فهرست منبع

Change password sync copyright notices, merge fixes to password sync code

David Boreham 20 سال پیش
والد
کامیت
341bc2d643

+ 6 - 0
ldap/synctools/passwordsync/README.txt

@@ -1,3 +1,9 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
 1. Download Wix (http://sourceforge.net/projects/wix/) and unzip it into the Wix folder.
    (steps 2 and 3 can be skipped if ldapserver has been built)
 2. Add the location of the Mozilla LDAP C SDK header files to your INCLUDE path.

+ 7 - 0
ldap/synctools/passwordsync/build.bat

@@ -1,3 +1,10 @@
+@rem //
+@rem // BEGIN COPYRIGHT BLOCK
+@rem // Copyright (C) 2005 Red Hat, Inc.
+@rem // All rights reserved.
+@rem // END COPYRIGHT BLOCK
+@rem //
+
 @echo off
 
 pushd

+ 18 - 120
ldap/synctools/passwordsync/passhand.cpp

@@ -1,3 +1,8 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK --- */
+
 // Created: 2-8-2005
 // Author(s): Scott Bridges
 #include "passhand.h"
@@ -19,21 +24,11 @@ void timeStamp(fstream* outFile)
 	}
 }
 
-PasswordHandler::PasswordHandler()
-{
-	outLog.open("./passhand.log", ios::out | ios::app);
-}
-
-PasswordHandler::~PasswordHandler()
-{
-	outLog.close();
-}
-
-int PasswordHandler::SaveSet(char* filename)
+int saveSet(PASS_INFO_LIST* passInfoList, char* filename)
 {
 	int result = 0;
 	fstream outFile;
-	list<USER_PASS_PAIR>::iterator currentPair;
+	PASS_INFO_LIST_ITERATOR currentPair;
 	strstream plainTextStream;
 	char* cipherTextBuf;
 	int usernameLen;
@@ -41,17 +36,11 @@ int PasswordHandler::SaveSet(char* filename)
 	int plainTextLen;
 	int cipherTextLen;
 	int resultTextLen = 0;
-	int pairCount = userPassPairs.size();
-
-	if(outLog.is_open())
-	{
-		timeStamp(&outLog);
-		outLog << "SaveSet: saving " << userPassPairs.size() << " entries to file" << endl;
-	}
+	int pairCount = passInfoList->size();
 
 	// Write usernames and passwords to a strstream
 	plainTextStream.write((char*)&pairCount, sizeof(pairCount));
-	for(currentPair = userPassPairs.begin(); currentPair != userPassPairs.end(); currentPair++)
+	for(currentPair = passInfoList->begin(); currentPair != passInfoList->end(); currentPair++)
 	{
 		// Usernames
 		usernameLen = strlen(currentPair->username) + 1;
@@ -87,20 +76,16 @@ int PasswordHandler::SaveSet(char* filename)
 	outFile.write(cipherTextBuf, resultTextLen);
 	outFile.close();
 
-	// ToDo: zero out memory
-
-	userPassPairs.clear();
-
 exit:
 	return result;
 }
 
-int PasswordHandler::LoadSet(char* filename)
+int loadSet(PASS_INFO_LIST* passInfoList, char* filename)
 {
 	int result = 0;
 	int i;
 	fstream inFile;
-	USER_PASS_PAIR newPair;
+	PASS_INFO newPair;
 	strstream* plainTextStream;
 	char* cipherTextBuf;
 	char* plainTextBuf;
@@ -154,84 +139,25 @@ int PasswordHandler::LoadSet(char* filename)
 		newPair.password = (char*)malloc(passwordLen);
 		plainTextStream->read((char*)newPair.password, passwordLen);
 
-		userPassPairs.push_back(newPair);
+		passInfoList->push_back(newPair);
 	}
 
 	delete plainTextStream;
 
-	if(outLog.is_open())
-	{
-		timeStamp(&outLog);
-		outLog << "LoadSet: "<< userPassPairs.size() << " entries loaded from file" << endl;
-	}
-
 exit:
 	return result;
 }
 
-int PasswordHandler::PushUserPass(char* username, char* password)
+int clearSet(PASS_INFO_LIST* passInfoList)
 {
-	USER_PASS_PAIR newPair;
-
-	newPair.username = (char*)malloc(strlen(username) + 1);
-	strcpy(newPair.username, username);
-
-	newPair.password = (char*)malloc(strlen(password) + 1);
-	strcpy(newPair.password, password);
-
-	userPassPairs.push_back(newPair);
-
-	if(outLog.is_open())
-	{
-		timeStamp(&outLog);
-		outLog << "PushUserPass: pushed user password pair, new length " << userPassPairs.size() << endl;
-	}
-
-	return 0;
-}
-
-int PasswordHandler::PeekUserPass(char* username, char* password)
-{
-	int result = 0;
-	list<USER_PASS_PAIR>::iterator currentPair;
-
-	if(userPassPairs.size() < 1)
-	{
-		result = -1;
-		goto exit;
-	}
-
-	currentPair = userPassPairs.begin();
-	strcpy(username, currentPair->username);
-	strcpy(password, currentPair->password);
-
-	if(outLog.is_open())
-	{
-		timeStamp(&outLog);
-		outLog << "PeekUserPass: current length " << userPassPairs.size() << endl;
-	}
-
-exit:
-	return result;
-}
-
-int PasswordHandler::PopUserPass()
-{
-	// ToDo: zero out memory.
-
-	userPassPairs.pop_front();
+	// ToDo: zero out memory
 
-	if(outLog.is_open())
-	{
-		timeStamp(&outLog);
-		outLog << "PopUserPass: popped user password pair, new length " << userPassPairs.size() << endl;
-	}
+	passInfoList->clear();
 
-	return 0;
+	return -1;
 }
 
-
-int PasswordHandler::encrypt(char* plainTextBuf, int plainTextLen, char* cipherTextBuf, int cipherTextLen, int* resultTextLen)
+int encrypt(char* plainTextBuf, int plainTextLen, char* cipherTextBuf, int cipherTextLen, int* resultTextLen)
 {
 	int result = 0;
 	SECStatus rv1, rv2, rv3;
@@ -311,24 +237,10 @@ int PasswordHandler::encrypt(char* plainTextBuf, int plainTextLen, char* cipherT
 	}
 
 exit:
-	if(outLog.is_open())
-	{
-		if(result == 0)
-		{
-			timeStamp(&outLog);
-			outLog << "encrypt: success" << endl;
-		}
-		else
-		{
-			timeStamp(&outLog);
-			outLog << "encrypt: failure" << endl;
-		}
-	}
-
 	return result;
 }
 
-int PasswordHandler::decrypt(char* cipherTextBuf, int cipherTextLen, char* plainTextBuf, int plainTextLen, int* resultTextLen)
+int decrypt(char* cipherTextBuf, int cipherTextLen, char* plainTextBuf, int plainTextLen, int* resultTextLen)
 {
 	int result = 0;
 	SECStatus rv1, rv2, rv3;
@@ -408,19 +320,5 @@ int PasswordHandler::decrypt(char* cipherTextBuf, int cipherTextLen, char* plain
 	}
 
 exit:
-	if(outLog.is_open())
-	{
-		if(result == 0)
-		{
-			timeStamp(&outLog);
-			outLog << "decrypt: success" << endl;
-		}
-		else
-		{
-			timeStamp(&outLog);
-			outLog << "decrypt: failure" << endl;
-		}
-	}
-
 	return result;
 }

+ 15 - 20
ldap/synctools/passwordsync/passhand.h

@@ -1,3 +1,8 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK --- */
+
 // Created: 2-8-2005
 // Author(s): Scott Bridges
 #ifndef _PASSHAND_H_
@@ -18,32 +23,22 @@
 
 using namespace std;
 
-struct USER_PASS_PAIR
+struct PASS_INFO
 {
 	char* username;
 	char* password;
 };
 
+typedef list<PASS_INFO> PASS_INFO_LIST;
+typedef list<PASS_INFO>::iterator PASS_INFO_LIST_ITERATOR;
+
 void timeStamp(fstream* outFile);
 
-class PasswordHandler
-{
-public:
-	PasswordHandler();
-	~PasswordHandler();
-
-	int SaveSet(char* filename);
-	int LoadSet(char* filename);
-	int PushUserPass(char* username, char* password);
-	int PeekUserPass(char* username, char* password);
-	int PopUserPass();
-private:
-	int encrypt(char* plainTextBuf, int plainTextLen, char* cipherTextBuf, int cipherTextLen, int* resultTextLen);
-	int decrypt(char* cipherTextBuf, int cipherTextLen, char* plainTextBuf, int plainTextLen, int* resultTextLen);
-
-	list<USER_PASS_PAIR> userPassPairs;
-	char* keyPath;
-	fstream outLog;
-};
+int encrypt(char* plainTextBuf, int plainTextLen, char* cipherTextBuf, int cipherTextLen, int* resultTextLen);
+int decrypt(char* cipherTextBuf, int cipherTextLen, char* plainTextBuf, int plainTextLen, int* resultTextLen);
+
+int saveSet(PASS_INFO_LIST* passInfoList, char* filename);
+int loadSet(PASS_INFO_LIST* passInfoList, char* filename);
+int clearSet(PASS_INFO_LIST* passInfoList);
 
 #endif

+ 45 - 6
ldap/synctools/passwordsync/passhook/passhook.cpp

@@ -1,3 +1,8 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK --- */
+
 // Created: 2-8-2005
 // Author(s): Scott Bridges
 #include <windows.h>
@@ -16,7 +21,8 @@ NTSTATUS NTAPI PasswordChangeNotify(PUNICODE_STRING UserName, ULONG RelativeId,
 	char singleByteUsername[PASSHAND_BUF_SIZE];
 	char singleBytePassword[PASSHAND_BUF_SIZE];
 	HANDLE passhookEventHandle = OpenEvent(EVENT_MODIFY_STATE, FALSE, PASSHAND_EVENT_NAME);
-	PasswordHandler ourPasswordHandler;
+	PASS_INFO newPassInfo;
+	PASS_INFO_LIST passInfoList;
 	fstream outLog;
 
 	outLog.open("passhook.log", ios::out | ios::app);
@@ -29,16 +35,49 @@ NTSTATUS NTAPI PasswordChangeNotify(PUNICODE_STRING UserName, ULONG RelativeId,
 	if(outLog.is_open())
 	{
 		timeStamp(&outLog);
-		outLog << "user " << singleByteUsername << "(" << UserName->Length / 2 << ") " << "password changed" << endl;
+		outLog << "user " << singleByteUsername << " password changed" << endl;
+	}
+
+	if(loadSet(&passInfoList, "passhook.dat") == 0)
+	{
+		if(outLog.is_open())
+		{
+			timeStamp(&outLog);
+			outLog << passInfoList.size() << " entries loaded from file" << endl;
+		}
+	}
+	else
+	{
+		if(outLog.is_open())
+		{
+			timeStamp(&outLog);
+			outLog << "failed to load entries from file" << endl;
+		}
 	}
 
-	ourPasswordHandler.LoadSet("passhook.dat");
-	ourPasswordHandler.PushUserPass(singleByteUsername, singleBytePassword);
-	ourPasswordHandler.SaveSet("passhook.dat");
+	newPassInfo.username = singleByteUsername;
+	newPassInfo.password = singleBytePassword;
+	passInfoList.push_back(newPassInfo);
+
+	if(saveSet(&passInfoList, "passhook.dat") == 0)
+	{
+		if(outLog.is_open())
+		{
+			timeStamp(&outLog);
+			outLog << passInfoList.size() << " entries saved to file" << endl;
+		}
+	}
+	else
+	{
+		if(outLog.is_open())
+		{
+			timeStamp(&outLog);
+			outLog << "failed to save entries to file" << endl;
+		}
+	}
 
 	if(passhookEventHandle == NULL)
 	{
-		// ToDo: generate event sync service not running.
 		if(outLog.is_open())
 		{
 			timeStamp(&outLog);

+ 6 - 0
ldap/synctools/passwordsync/passhook/passhook.dep

@@ -1,3 +1,9 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
 # Microsoft Developer Studio Generated Dependency File, included by passhook.mak
 
 ..\passhand.cpp : \

+ 6 - 0
ldap/synctools/passwordsync/passhook/passhook.dsp

@@ -1,3 +1,9 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
 # Microsoft Developer Studio Project File - Name="passhook" - Package Owner=<4>
 # Microsoft Developer Studio Generated Build File, Format Version 6.00
 # ** DO NOT EDIT **

+ 6 - 0
ldap/synctools/passwordsync/passhook/passhook.mak

@@ -1,3 +1,9 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
 # Microsoft Developer Studio Generated NMAKE File, Based on passhook.dsp
 !IF "$(CFG)" == ""
 CFG=passhook - Win32 Debug

+ 6 - 0
ldap/synctools/passwordsync/passsync.dsw

@@ -1,3 +1,9 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
 Microsoft Developer Studio Workspace File, Format Version 6.00
 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
 

BIN
ldap/synctools/passwordsync/passsync.ncb


BIN
ldap/synctools/passwordsync/passsync.opt


+ 5 - 0
ldap/synctools/passwordsync/passsync/dssynchmsg.h

@@ -1,3 +1,8 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK --- */
+
 //
 //  Values are 32 bit values layed out as follows:
 //

+ 5 - 0
ldap/synctools/passwordsync/passsync/resource.h

@@ -1,3 +1,8 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK --- */
+
 //{{NO_DEPENDENCIES}}
 // Microsoft Developer Studio generated include file.
 // Used by passsync.rc

+ 5 - 0
ldap/synctools/passwordsync/passsync/service.cpp

@@ -1,3 +1,8 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK --- */
+
 // Created: 2-8-2005
 // Author(s): Scott Bridges
 

+ 6 - 0
ldap/synctools/passwordsync/passsync/subuniutil.cpp

@@ -1,3 +1,9 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
 #include "subuniutil.h"
 
 // Copied: 2-8-2005

+ 6 - 0
ldap/synctools/passwordsync/passsync/subuniutil.h

@@ -1,3 +1,9 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
 #ifndef _SUBUNIUTIL_H_
 #define _SUBUNIUTIL_H_
 

+ 247 - 106
ldap/synctools/passwordsync/passsync/syncserv.cpp

@@ -1,3 +1,8 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK --- */
+
 // Created: 2-8-2005
 // Author(s): Scott Bridges
 #include "syncserv.h"
@@ -5,6 +10,9 @@
 #include "prerror.h"
 static char* certdbh;
 
+// ****************************************************************
+// passwdcb
+// ****************************************************************
 char* passwdcb(PK11SlotInfo* info, PRBool retry, void* arg)
 {
 	char* result = NULL;
@@ -24,6 +32,9 @@ char* passwdcb(PK11SlotInfo* info, PRBool retry, void* arg)
 	return result;
 }
 
+// ****************************************************************
+// PassSyncService::PassSyncService
+// ****************************************************************
 PassSyncService::PassSyncService(const TCHAR *serviceName) : CNTService(serviceName)
 {
 	char sysPath[SYNCSERV_BUF_SIZE];
@@ -33,7 +44,7 @@ PassSyncService::PassSyncService(const TCHAR *serviceName) : CNTService(serviceN
 
 	passhookEventHandle = CreateEvent(NULL, FALSE, FALSE, PASSHAND_EVENT_NAME);
 
-	pLdapConnection = NULL;
+	mainLdapConnection = NULL;
 	results = NULL;
 	currentResult = NULL;
 	lastLdapError = LDAP_SUCCESS;
@@ -76,6 +87,9 @@ PassSyncService::PassSyncService(const TCHAR *serviceName) : CNTService(serviceN
 	PK11_SetPasswordFunc(passwdcb);
 }
 
+// ****************************************************************
+// PassSyncService::~PassSyncService
+// ****************************************************************
 PassSyncService::~PassSyncService()
 {
 	if(outLog.is_open())
@@ -86,87 +100,144 @@ PassSyncService::~PassSyncService()
 	outLog.close();
 }
 
+// ****************************************************************
+// PassSyncService::SyncPasswords
+// ****************************************************************
 int PassSyncService::SyncPasswords()
 {
 	int result = 0;
-	char username[PASSHAND_BUF_SIZE];
-	char password[PASSHAND_BUF_SIZE];
+	PASS_INFO_LIST_ITERATOR currentPassInfo;
+	PASS_INFO_LIST_ITERATOR tempPassInfo;
 	char* dn;
 
-	if(Connect() < 0)
+	if(Connect(&mainLdapConnection, ldapAuthUsername, ldapAuthPassword) < 0)
 	{
-		// ToDo: generate event connection failure.
+		// log connection failure.
 		if(outLog.is_open())
 		{
 			timeStamp(&outLog);
 			outLog << "can not connect to ldap server in SyncPasswords" << endl;
 		}
-		result = -1;
+
 		goto exit;
 	}
 
-	ourPasswordHandler.LoadSet(dataFilename);
+	if(loadSet(&passInfoList, dataFilename) == 0)
+	{
+		if(outLog.is_open())
+		{
+			timeStamp(&outLog);
+			outLog << passInfoList.size() << " entries loaded from file" << endl;
+		}
+	}
+	else
+	{
+		if(outLog.is_open())
+		{
+			timeStamp(&outLog);
+			outLog << "failed to load entries from file" << endl;
+		}
+	}
 
-	while(ourPasswordHandler.PeekUserPass(username, password) == 0)
+	while(passInfoList.size() > 0)
 	{
-		if(QueryUsername(username) != 0)
+		currentPassInfo = passInfoList.begin();
+
+		while(currentPassInfo != passInfoList.end())
 		{
-			// ToDo: generate event search failure.			
-			if(outLog.is_open())
+			if(QueryUsername(currentPassInfo->username) != 0)
 			{
-				timeStamp(&outLog);
-				outLog << "search for " << username << " failed in SyncPasswords" << endl;
+				// log search failure.			
+				if(outLog.is_open())
+				{
+					timeStamp(&outLog);
+					outLog << "search for " << currentPassInfo->username << " failed in SyncPasswords" << endl;
+				}
 			}
-		}
-		else
-		{
-			while((dn = GetDN()) != NULL)
+			else
 			{
-				if(ModifyPassword(dn, password) != 0)
+				while((dn = GetDN()) != NULL)
 				{
-					// ToDo: generate event modify failure.					
-					if(outLog.is_open())
+					if(CanBind(dn, currentPassInfo->password))
 					{
-						timeStamp(&outLog);
-						outLog << "modify password for " << username << " failed in SyncPasswords" << endl;
+						if(outLog.is_open())
+						{
+							timeStamp(&outLog);
+							outLog << "password match, no modify preformed: " << currentPassInfo->username << endl;
+						}
 					}
-				}
-				else
-				{
-					if(outLog.is_open())
+					else if(ModifyPassword(dn, currentPassInfo->password) != 0)
 					{
-						timeStamp(&outLog);
-						outLog << "password for " << username << " modified" << endl;
-						outLog << "\t" << dn << endl;
+						// log modify failure.
+						if(outLog.is_open())
+						{
+							timeStamp(&outLog);
+							outLog << "modify password for " << currentPassInfo->username << " failed in SyncPasswords" << endl;
+						}
 					}
-				}
+					else
+					{
+						if(outLog.is_open())
+						{
+							timeStamp(&outLog);
+							outLog << "password for " << currentPassInfo->username << " modified" << endl;
+							outLog << "\t" << dn << endl;
+						}
+					}
+				} // end while((dn = GetDN()) != NULL)
 			}
-		}
-		// ToDo: zero out buffers
 
-		ourPasswordHandler.PopUserPass();
-	}
+			tempPassInfo = currentPassInfo;
+			currentPassInfo++;
+			passInfoList.erase(tempPassInfo);
+		} // end while(currentPassInfo != passInfoList.end())
+	} // end while(passInfoList.size() > 0)
 
-	ourPasswordHandler.SaveSet(dataFilename);
+	if(saveSet(&passInfoList, dataFilename) == 0)
+	{
+		if(outLog.is_open())
+		{
+			timeStamp(&outLog);
+			outLog << passInfoList.size() << " entries saved to file" << endl;
+		}
+	}
+	else
+	{
+		if(outLog.is_open())
+		{
+			timeStamp(&outLog);
+			outLog << "failed to save entries to file" << endl;
+		}
+	}
 
-	Disconnect();
+	clearSet(&passInfoList);
+	Disconnect(&mainLdapConnection);
 
 exit:
 	return result;
 }
 
+// ****************************************************************
+// 
+// ****************************************************************
 void PassSyncService::OnStop()
 {
 	isRunning = false;
 	SetEvent(passhookEventHandle);
 }
 
+// ****************************************************************
+// 
+// ****************************************************************
 void PassSyncService::OnShutdown()
 {
 	isRunning = false;
 	SetEvent(passhookEventHandle);
 }
 
+// ****************************************************************
+// PassSyncService::Run
+// ****************************************************************
 void PassSyncService::Run()
 {
 	isRunning = true;
@@ -178,9 +249,14 @@ void PassSyncService::Run()
 		SyncPasswords();
 		ResetEvent(passhookEventHandle);
 	}
+
+	CloseHandle(passhookEventHandle);
 }
 
-int PassSyncService::Connect()
+// ****************************************************************
+// PassSyncService::Connect
+// ****************************************************************
+int PassSyncService::Connect(LDAP** connection, char* dn, char* auth)
 {
 	int result = 0;
 
@@ -192,7 +268,7 @@ int PassSyncService::Connect()
 		{
 			timeStamp(&outLog);
 			outLog << "ldapssl_client_init failed in Connect" << endl;
-			outLog << "\t" << result << ": " <<  ldapssl_err2string(result) << endl;
+			outLog << "\t" << result << ": " << ldap_err2string(result) << endl;
 		}
 
 		result = GetLastError();
@@ -201,9 +277,9 @@ int PassSyncService::Connect()
 		goto exit;
 	}
 
-	pLdapConnection = ldapssl_init(ldapHostName, atoi(ldapHostPort), 1);
+	*connection = ldapssl_init(ldapHostName, atoi(ldapHostPort), 1);
 
-	if(pLdapConnection == NULL)
+	if(*connection == NULL)
 	{
 		if(outLog.is_open())
 		{
@@ -215,34 +291,45 @@ int PassSyncService::Connect()
 		goto exit;
 	}
 
-	lastLdapError = ldap_simple_bind_s(pLdapConnection, ldapAuthUsername, ldapAuthPassword);
+	ResetBackoff();
+	while(((lastLdapError = ldap_simple_bind_s(*connection, dn, auth)) != LDAP_SUCCESS) && Backoff())
+	{
+		// empty
+	}
 
 	if(lastLdapError != LDAP_SUCCESS)
 	{
-		// ToDo: log reason for bind failure.
+		// log reason for bind failure.
 		if(outLog.is_open())
 		{
 			timeStamp(&outLog);
 			outLog << "ldap error in Connect" << endl;
-			outLog << "\t" << lastLdapError << ": " << ldapssl_err2string(lastLdapError) << endl;
+			outLog << "\t" << lastLdapError << ": " << ldap_err2string(lastLdapError) << endl;
 		}
 
 		result = -1;
 		goto exit;
 	}
+
 exit:
 	return result;
 }
 
-int PassSyncService::Disconnect()
+// ****************************************************************
+// PassSyncService::Disconnect
+// ****************************************************************
+int PassSyncService::Disconnect(LDAP** connection)
 {
-	ldap_unbind(pLdapConnection);
+	ldap_unbind(*connection);
 
-	pLdapConnection = NULL;
+	connection = NULL;
 
 	return 0;
 }
 
+// ****************************************************************
+// PassSyncService::QueryUsername
+// ****************************************************************
 int PassSyncService::QueryUsername(char* username)
 {
 	int result = 0;
@@ -252,83 +339,96 @@ int PassSyncService::QueryUsername(char* username)
 
 	_snprintf(searchFilter, SYNCSERV_BUF_SIZE, "(%s=%s)", ldapUsernameField, username);
 
-	lastLdapError = ldap_search_ext_s(
-		pLdapConnection,
-		ldapSearchBase,
-		LDAP_SCOPE_ONELEVEL,
-		searchFilter,
-		NULL,
-		0,
-		NULL,
-		NULL,
-		NULL,
-		-1,
-		&results);
-
-	if(lastLdapError != LDAP_SUCCESS)
+	ResetBackoff();
+	while(Backoff())
 	{
-		// ToDo: log reason for search failure.
-		if(outLog.is_open())
+		lastLdapError = ldap_search_ext_s(mainLdapConnection, ldapSearchBase, LDAP_SCOPE_ONELEVEL, searchFilter, NULL, 0, NULL, NULL, NULL, -1, &results);
+
+		if(lastLdapError != LDAP_SUCCESS)
 		{
-			timeStamp(&outLog);
-			outLog << "ldap error in QueryUsername" << endl;
-			outLog << "\t" << lastLdapError << ": " << ldapssl_err2string(lastLdapError) << endl;
+			// log reason for search failure.
+			if(outLog.is_open())
+			{
+				timeStamp(&outLog);
+				outLog << "ldap error in QueryUsername" << endl;
+				outLog << "\t" << lastLdapError << ": " << ldap_err2string(lastLdapError) << endl;
+			}
+			result = -1;
+			EndBackoff();
+		}
+		else if(ldap_first_entry(mainLdapConnection, results) == NULL)
+		{
+			if(outLog.is_open())
+			{
+				timeStamp(&outLog);
+				outLog << "there are no entries that match: " << username << endl;
+			}
+			result = -1;
+		}
+		else if(ldap_next_entry(mainLdapConnection, ldap_first_entry(mainLdapConnection, results)) != NULL)
+		{
+			if(outLog.is_open())
+			{
+				timeStamp(&outLog);
+				outLog << "there are multiple entries that match: " << username << endl;
+			}
+
+			if(!SYNCSERV_ALLOW_MULTI_MOD)
+			{
+				result = -1;
+				EndBackoff();
+			}
 		}
-		result = -1;
-		goto exit;
 	}
 
-exit:
 	return result;
 }
 
+// ****************************************************************
+// PassSyncService::GetDN
+// ****************************************************************
 char* PassSyncService::GetDN()
 {
 	char* result = NULL;
 
-	if(multipleModify)
+	if(currentResult == NULL)
 	{
-		if(currentResult == NULL)
-		{
-			currentResult = ldap_first_entry(pLdapConnection, results);
-		}
-		else
-		{
-			currentResult = ldap_next_entry(pLdapConnection, currentResult);
-		}
-
-		result = ldap_get_dn(pLdapConnection, currentResult);
+		currentResult = ldap_first_entry(mainLdapConnection, results);
 	}
 	else
 	{
-		if(currentResult == NULL)
-		{
-			currentResult = ldap_first_entry(pLdapConnection, results);
-			if(ldap_next_entry(pLdapConnection, currentResult) != NULLMSG)
-			{
-				// Too many results
-				if(outLog.is_open())
-				{
-					timeStamp(&outLog);
-					outLog << "too many results in GetDN" << endl;
-				}
-				currentResult = NULL;
-				goto exit;
-			}
-
-			result = ldap_get_dn(pLdapConnection, currentResult);
-		}
-		else
-		{
-			currentResult = NULL;
-			goto exit;
-		}
+		currentResult = ldap_next_entry(mainLdapConnection, currentResult);
 	}
 
-exit:
+	result = ldap_get_dn(mainLdapConnection, currentResult);
+
+	return result;
+}
+
+// ****************************************************************
+// PassSyncService::CanBind
+// ****************************************************************
+bool PassSyncService::CanBind(char* dn, char* password)
+{
+	bool result;
+	LDAP* tempConnection = NULL;
+
+	if(Connect(&tempConnection, dn, password) == 0)
+	{
+		Disconnect(&tempConnection);
+		result = true;
+	}
+	else
+	{
+		result = false;
+	}
+	
 	return result;
 }
 
+// ****************************************************************
+// PassSyncService::ModifyPassword
+// ****************************************************************
 int PassSyncService::ModifyPassword(char* dn, char* password)
 {
 	int result = 0;
@@ -340,18 +440,59 @@ int PassSyncService::ModifyPassword(char* dn, char* password)
 	passMod.mod_op = LDAP_MOD_REPLACE;
 	passMod.mod_values = modValues;
 
-	lastLdapError = ldap_modify_ext_s(pLdapConnection, dn, mods, NULL, NULL);
+	lastLdapError = ldap_modify_ext_s(mainLdapConnection, dn, mods, NULL, NULL);
 	if(lastLdapError != LDAP_SUCCESS)
 	{
-		// ToDo: log the reason for the modify failure.
+		// log reason for modify failure.
 		if(outLog.is_open())
 		{
 			timeStamp(&outLog);
 			outLog << "ldap error in ModifyPassword" << endl;
-			outLog << "\t" << lastLdapError << ": " << ldapssl_err2string(lastLdapError) << endl;
+			outLog << "\t" << lastLdapError << ": " << ldap_err2string(lastLdapError) << endl;
 		}
 		result = -1;
 	}
 
 	return result;
-}
+}
+
+// ****************************************************************
+// PassSyncService::ResetBackoff
+// ****************************************************************
+void PassSyncService::ResetBackoff()
+{
+	backoffCount = 0;
+}
+
+// ****************************************************************
+// PassSyncService::EndBackoff
+// ****************************************************************
+void PassSyncService::EndBackoff()
+{
+	backoffCount = SYNCSERV_MAX_BACKOFF_COUNT;
+}
+
+// ****************************************************************
+// PassSyncService::Backoff
+// ****************************************************************
+bool PassSyncService::Backoff()
+{
+	bool result;
+
+	if(backoffCount == 0)
+	{
+		result = true;
+	}
+	else if(backoffCount < SYNCSERV_MAX_BACKOFF_COUNT)
+	{
+		Sleep((2 ^ backoffCount) * SYNCSERV_BASE_BACKOFF_LEN);
+		result = true;
+	}
+	else
+	{
+		result = false;
+	}
+
+	backoffCount++;
+	return result;
+}

+ 17 - 4
ldap/synctools/passwordsync/passsync/syncserv.h

@@ -1,3 +1,8 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK --- */
+
 // Created: 2-8-2005
 // Author(s): Scott Bridges
 #ifndef _SYNCSERV_H_
@@ -13,6 +18,8 @@
 #define SYNCSERV_BUF_SIZE 256
 #define SYNCSERV_TIMEOUT 10000
 #define SYNCSERV_ALLOW_MULTI_MOD false
+#define SYNCSERV_MAX_BACKOFF_COUNT 4
+#define SYNCSERV_BASE_BACKOFF_LEN 1000
 
 class PassSyncService : public CNTService
 {
@@ -27,17 +34,22 @@ public:
 	int SyncPasswords();
 
 private:
-	int Connect();
-	int Disconnect();
+	int Connect(LDAP** connection, char* dn, char* auth);
+	int Disconnect(LDAP** connection);
 	int QueryUsername(char* username);
 	char* GetDN();
+	bool CanBind(char* dn, char* password);
 	int ModifyPassword(char* dn, char* password);
 
-	PasswordHandler ourPasswordHandler;
+	void ResetBackoff();
+	void EndBackoff();
+	bool Backoff();
+
+	PASS_INFO_LIST passInfoList;
 	HANDLE passhookEventHandle;
 
 	// LDAP variables
-	LDAP* pLdapConnection;
+	LDAP* mainLdapConnection;
 	LDAPMessage* results;
 	LDAPMessage* currentResult;
 	int lastLdapError;
@@ -56,6 +68,7 @@ private:
 	char ldapPasswordField[SYNCSERV_BUF_SIZE];
 	bool multipleModify;
 	bool isRunning;
+	int backoffCount;
 	fstream outLog;
 };
 

+ 5 - 1
ldap/synctools/passwordsync/wix/PassSync.wxs

@@ -1,4 +1,8 @@
 <?xml version='1.0' encoding='windows-1252'?>
+<!-- BEGIN COPYRIGHT BLOCK
+ Copyright (C) 2005 Red Hat, Inc.
+ All rights reserved.
+ END COPYRIGHT BLOCK -->
 <Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>
   <Product Name='Password Sync' Id='DB501C18-86C7-4D14-AEC0-86416A69ABDE'
     Language='1033' Codepage='1252'
@@ -87,7 +91,7 @@
 		  <Registry Id='Certtkn' Root='HKLM' Key='Software\PasswordSync' Name='Cert Token' Action='write' Type='string' Value='[CERTTOKEN]' />
 		  <Registry Id='SrchBase' Root='HKLM' Key='Software\PasswordSync' Name='Search Base' Action='write' Type='string' Value='[SRCHBASE]' />
 		  <Registry Id='UserFld' Root='HKLM' Key='Software\PasswordSync' Name='User Name Field' Action='write' Type='string' Value='ntuserdomainid' />
-		  <Registry Id='PassFld' Root='HKLM' Key='Software\PasswordSync' Name='Password Field' Action='write' Type='string' Value='ntusercomment' />
+		  <Registry Id='PassFld' Root='HKLM' Key='Software\PasswordSync' Name='Password Field' Action='write' Type='string' Value='userpassword' />
 		  <Registry Id='NotPkgs' Root='HKLM' Key='SYSTEM\ControlSet001\Control\Lsa' Name='Notification Packages' Action='append'
 		   Type='multiString' Value='passhook'/>
 

+ 6 - 0
ldap/synctools/passwordsync/wix/README.txt

@@ -1,3 +1,9 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright (C) 2005 Red Hat, Inc.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
 1. Download Wix (http://sourceforge.net/projects/wix/) and unzip it into the Wix folder.
    (steps 2 and 3 can be skipped if ldapserver has been built)
 2. Add the location of the Mozilla LDAP C SDK header files to your INCLUDE path.