[Fedora-directory-commits] ldapserver/ldap/synctools/passwordsync/passhook passhook.cpp, 1.7.2.1, 1.7.2.2

Nathan Kinder (nkinder) fedora-directory-commits at redhat.com
Thu Mar 30 23:09:02 UTC 2006


Author: nkinder

Update of /cvs/dirsec/ldapserver/ldap/synctools/passwordsync/passhook
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv2067/passwordsync/passhook

Modified Files:
      Tag: Directory71RtmBranch
	passhook.cpp 
Log Message:
186657 - Implemented locking around passhook data file access


Index: passhook.cpp
===================================================================
RCS file: /cvs/dirsec/ldapserver/ldap/synctools/passwordsync/passhook/passhook.cpp,v
retrieving revision 1.7.2.1
retrieving revision 1.7.2.2
diff -u -r1.7.2.1 -r1.7.2.2
--- passhook.cpp	22 Mar 2006 18:53:32 -0000	1.7.2.1
+++ passhook.cpp	30 Mar 2006 23:08:59 -0000	1.7.2.2
@@ -48,121 +48,74 @@
 #define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)
 #endif
 
+DWORD WINAPI SavePasshookChange( LPVOID passinfo );
+static HANDLE passhookMutexHandle;
+static unsigned long logLevel;
+
 NTSTATUS NTAPI PasswordChangeNotify(PUNICODE_STRING UserName, ULONG RelativeId, PUNICODE_STRING Password)
 {
-	HANDLE passhookEventHandle = OpenEvent(EVENT_MODIFY_STATE, FALSE, PASSHAND_EVENT_NAME);
-	PASS_INFO newPassInfo;
-	PASS_INFO_LIST passInfoList;
-	HKEY regKey;
-	DWORD type;
-	unsigned long buffSize;
-	char regBuff[PASSHAND_BUF_SIZE];
-	unsigned long logLevel;
+	PASS_INFO *newPassInfo = NULL;
+	HANDLE passhookThreadHandle;
 	fstream outLog;
+	DWORD waitRes;
 
-	RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\PasswordSync", &regKey);
-	buffSize = PASSHAND_BUF_SIZE;
-	if(RegQueryValueEx(regKey, "Log Level", NULL, &type, (unsigned char*)regBuff, &buffSize) == ERROR_SUCCESS)
-	{
-		logLevel = (unsigned long)atoi(regBuff);
-	}
-	else
-	{
-		logLevel = 0;
-	}
-	if(logLevel > 0)
-	{
-		outLog.open("passhook.log", ios::out | ios::app);
-	}
-	RegCloseKey(regKey);
-
-	// This memory will be free'd by calling clearSet below
-	newPassInfo.username = (char*)malloc((UserName->Length / 2) + 1);
-	newPassInfo.password = (char*)malloc((Password->Length / 2) + 1);
-
-	if (newPassInfo.username && newPassInfo.password) {
-		_snprintf(newPassInfo.username, (UserName->Length / 2), "%S", UserName->Buffer);
-		_snprintf(newPassInfo.password, (Password->Length / 2), "%S", Password->Buffer);
-		newPassInfo.username[UserName->Length / 2] = '\0';
-		newPassInfo.password[Password->Length / 2] = '\0';
+	// This memory will be freed in SavePasshookChange
+	if ( newPassInfo = (PASS_INFO *) malloc(sizeof(PASS_INFO)) ) {
+		// These get freed in SavePasshookChange by calling clearSet
+		newPassInfo->username = (char*)malloc((UserName->Length / 2) + 1);
+		newPassInfo->password = (char*)malloc((Password->Length / 2) + 1);
 	} else {
-		if(outLog.is_open()) {
-			timeStamp(&outLog);
-			outLog << "failed to allocate memory for username and password" << endl;
-		}
-		free(newPassInfo.username);
-		free(newPassInfo.password);
 		goto exit;
 	}
 
-	if(outLog.is_open())
-	{
-		timeStamp(&outLog);
-		outLog << "user " << newPassInfo.username << " password changed" << endl;
-		//outLog << "user " << newPassInfo.username << " password changed to " << newPassInfo.password << endl;
-	}
+	// Fill in the password change struct
+	if (newPassInfo->username && newPassInfo->password) {
+                _snprintf(newPassInfo->username, (UserName->Length / 2), "%S", UserName->Buffer);
+                _snprintf(newPassInfo->password, (Password->Length / 2), "%S", Password->Buffer);
+                newPassInfo->username[UserName->Length / 2] = '\0';
+                newPassInfo->password[Password->Length / 2] = '\0';
 
-	// loadSet allocates memory for the usernames and password.  We need to be
-	// sure to free it by calling clearSet.
-	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;
-		}
+		// Backoff
+                newPassInfo->backoffCount = 0;
+
+                // Load time
+                time(&(newPassInfo->atTime));
+	} else {
+		// Memory error.  Free everything we allocated.
+		free(newPassInfo->username);
+		free(newPassInfo->password);
+		free(newPassInfo);
+		goto exit;
 	}
 
-	// Add the new change to the list
-	passInfoList.push_back(newPassInfo);
+	// Fire off a thread to do the real work
+	passhookThreadHandle = CreateThread(NULL, 0, SavePasshookChange, newPassInfo, 0, NULL); 
 
-	// Save the list to disk
-	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;
-		}
-	}
+	// We need to close the handle to the thread we created.  Doing
+	// this will not terminate the thread.
+	if (passhookThreadHandle != NULL) {
+		CloseHandle(passhookThreadHandle);
+	} else {
+		// Acquire the mutex so we can log an error
+		waitRes = WaitForSingleObject(passhookMutexHandle, PASSHOOK_TIMEOUT);
 
-	// We need to call clearSet so memory gets free'd
-	clearSet(&passInfoList);
+		// If we got the mutex, log the error, otherwise it's not safe to log
+		if (waitRes == WAIT_OBJECT_0) {
+                	outLog.open("passhook.log", ios::out | ios::app);
+
+		        if(outLog.is_open()) {
+       		         	timeStamp(&outLog);
+		                outLog << "Failed to start thread.  Aborting change for " << newPassInfo->username << endl;
+       		 	}
 
-exit:
-	if(passhookEventHandle == NULL)
-	{
-		if(outLog.is_open())
-		{
-			timeStamp(&outLog);
-			outLog << "can not get password sync service event handle, service not running" << endl;
-		}
+			outLog.close();
 
-	}
-	else
-	{
-		SetEvent(passhookEventHandle);
-		CloseHandle(passhookEventHandle);
+			// Release mutex
+			ReleaseMutex(passhookMutexHandle);
+		}
 	}
 
-	outLog.close();
-
+exit:
 	return STATUS_SUCCESS;
 }
 
@@ -173,5 +126,132 @@
 
 BOOL NTAPI InitializeChangeNotify()
 {
-	return TRUE;
+	HKEY regKey;
+	DWORD type;
+	unsigned long buffSize;
+	char regBuff[PASSHAND_BUF_SIZE];
+	fstream outLog;
+
+	// check if logging is enabled
+	RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\PasswordSync", &regKey);
+        buffSize = PASSHAND_BUF_SIZE;
+        if(RegQueryValueEx(regKey, "Log Level", NULL, &type, (unsigned char*)regBuff, &buffSize) == ERROR_SUCCESS)
+        {
+                logLevel = (unsigned long)atoi(regBuff);
+        }
+        else
+        {
+                logLevel = 0;
+        }
+        RegCloseKey(regKey);
+
+	// Create mutex for passhook data file and log file access
+	passhookMutexHandle = CreateMutex(NULL, FALSE, PASSHOOK_MUTEX_NAME);
+
+	if (passhookMutexHandle == NULL) {
+		// Log an error.
+		outLog.open("passhook.log", ios::out | ios::app);
+		timeStamp(&outLog);
+		outLog << "Failed to create passhook mutex.  Passhook DLL will not be loaded." << endl;
+		outLog.close();
+
+		return FALSE;
+	} else {
+		return TRUE;
+	}
+}
+
+// This function will save the password change to the passhook data file.  It
+// will be run as a separate thread.
+DWORD WINAPI SavePasshookChange( LPVOID passinfo ) 
+{
+	PASS_INFO *newPassInfo = NULL;
+        PASS_INFO_LIST passInfoList;
+        HANDLE passhookEventHandle = OpenEvent(EVENT_MODIFY_STATE, FALSE, PASSHAND_EVENT_NAME);
+	fstream outLog;
+
+	if ((newPassInfo = (PASS_INFO *)passinfo) == NULL) {
+		goto exit;
+	}
+
+        // Acquire the mutex for passhook.dat.  This mutex also guarantees
+	// that we can write to outLog safely.
+        WaitForSingleObject(passhookMutexHandle, INFINITE);
+
+	// Open the log file if logging is enabled
+        if(logLevel > 0)
+        {
+                outLog.open("passhook.log", ios::out | ios::app);
+        }
+
+	if(outLog.is_open())
+        {
+                timeStamp(&outLog);
+                outLog << "user " <<  newPassInfo->username << " password changed" << endl;
+                //outLog << "user " <<  newPassInfo->username << " password changed to " <<  newPassInfo->passname << endl;
+        }
+
+        // loadSet allocates memory for the usernames and password.  We need to be
+        // sure to free it by calling clearSet.
+        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;
+                }
+        }
+
+	// Add the new change to the list
+        passInfoList.push_back(*newPassInfo);
+
+        // Save the list to disk
+        if(saveSet(&passInfoList, "passhook.dat") == 0)
+        {
+                if(outLog.is_open())
+                {
+                        timeStamp(&outLog);
+                        outLog << passInfoList.size() << " entries saved to file" << endl;
+                }
+        }
+        else
+        {
+		// We always want to log this error condition
+                if(!outLog.is_open())
+                {
+			// We need to open the log since debug logging is turned off
+			outLog.open("passhook.log", ios::out | ios::app);
+		}
+
+                timeStamp(&outLog);
+                outLog << "failed to save entries to file" << endl;
+        }
+
+	// Close the log file before we release the mutex.
+	outLog.close();
+
+        // Release the mutex for passhook.dat
+        ReleaseMutex(passhookMutexHandle);
+
+        // We need to call clearSet so memory gets free'd
+        clearSet(&passInfoList);
+
+exit:
+	// Free the passed in struct from the heap
+	free(newPassInfo);
+
+        if (passhookEventHandle != NULL) {
+                SetEvent(passhookEventHandle);
+		CloseHandle(passhookEventHandle);
+        }
+
+	return 0;
 }




More information about the Fedora-directory-commits mailing list