/*********************************************************************** * * Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2.1 * of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, Novell, Inc. * * To contact Novell about this file by physical or electronic mail, * you may find current contact information at www.novell.com. * ***********************************************************************/ #include "ProfileManager.h" // Private functions.... ProfileManager::ProfileManager() { isInitialized = 0; libnss = NULL; libplc = NULL; profileName = NULL; profilePath = NULL; libraryPath = NULL; masterPassword = NULL; } char * ProfileManager::GetFirefoxProfilePath(char *profileName) { #ifdef WIN32 char profileDir[MAX_PATH] = ""; char partialPath[] = "Application Data\\Mozilla\\Firefox"; char profilePath[MAX_PATH]; char line[1024]; DWORD pathSize = MAX_PATH; char *finalProfilePath = NULL; unsigned int i; HANDLE token; // Get current user's profile directory if( OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == FALSE ) { PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Failed to get current process token "); return 0; } if( GetUserProfileDirectory(token, profileDir, &pathSize) == FALSE ) { PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Failed to get user profile directory"); return 0; } PrintMessage(MESG_DEBUG, "\n GetFirefoxProfilePath : User Profile directory = %s", profileDir); // Get firefox profile directory strcpy(profilePath, profileDir); strcat(profilePath,"\\"); strcat(profilePath,partialPath); strcat(profilePath,"\\profiles.ini"); PrintMessage(MESG_DEBUG, "\n GetFirefoxProfilePath : Firefox profile.ini path = %s ", profilePath); #else // Linux platform.... char profileDir[] ="/.mozilla/firefox"; char profileFile[] ="/.mozilla/firefox/profiles.ini"; char line[1024]; char *profilePath = NULL; char *homeDir = NULL; char *finalProfilePath = NULL; unsigned int i; // Get home directory homeDir = getenv("HOME"); if(homeDir == NULL ) { PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Unable to get home directory "); return 0; } profilePath = (char*) malloc( strlen(homeDir) + strlen(profileFile) + 3 ); if( profilePath == NULL ) { PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Insufficient memory "); return 0; } strcpy(profilePath,homeDir); strcat(profilePath,profileFile); PrintMessage(MESG_DEBUG, "\n GetFirefoxProfilePath : Firefox profile dir path = %s ", profilePath); #endif // Open the firefox profile setting file FILE *profile = fopen(profilePath, "r"); if( profile == NULL ) { PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Unable to find firefox profile file : %s ", profilePath); return NULL; } // Find out the profile path for given profile name char *temp; int isProfileFound = 0; int isRelative = 1; char *path = NULL; while(fgets(line, 1024, profile)) { // Remove trailing end of line character line[strlen(line)-1]= 0; // Convert to smaller case until "=" found.... for(i=0; iprofileName = (char*) malloc(strlen(profileName)+1); if( !this->profileName ) { PrintMessage(MESG_ERROR, "\n ProfileInit : Insufficient memory.."); return FPM_INSUFFICIENT_MEMORY; } strcpy(this->profileName, profileName); // TODO // Read the preference from the config file present in the profile... isInitialized = FPM_TRUE; // Setup the function pointers... void *funList[9]; funList[0] = (void*)NULL ; //PK11SetPasswordFunc; funList[1] = (void*)PK11GetInternalKeySlot; funList[2] = (void*)PK11FreeSlot; funList[3] = (void*)PK11Authenticate; funList[4] = (void*)PK11CheckUserPassword; funList[5] = (void*)PK11SDRDecrypt; funList[6] = (void*)PK11SDREncrypt; funList[7] = (void*)PLBase64Encode; funList[8] = (void*)PLBase64Decode; signonManager.SetupFunctions(funList); return FPM_TRUE; } void ProfileManager::ProfileExit() { int i; PrintMessage(MESG_DEBUG, "\n ProfileExit : Shutting down the profile %s", profileName); if( (isInitialized == FPM_TRUE) && NSSShutdown != NULL ) { PrintMessage(MESG_DEBUG, "\n ProfileExit : invoking NSSShutdown for profile", profileName); for(i=0; (i<5) && ((*NSSShutdown)() == SECFailure); i++ ) { PrintMessage(MESG_DEBUG, "\n ProfileExit %d: NSSShutdown : FAILURE",i); //Sleep(500); } if( i != 5) { PrintMessage(MESG_DEBUG, "\n ProfileExit :NSSShutdown : SUCCESS"); } else PrintMessage(MESG_DEBUG, "\n ProfileExit : NSSShutdown : FAILURE"); } if( libnss != NULL ) { PrintMessage(MESG_DEBUG, "\n ProfileExit : Freeing library libnss.dll"); FREELIBRARY(libnss); } if( libplc != NULL ) { PrintMessage(MESG_DEBUG, "\n ProfileExit : Freeing library libplc.dll"); FREELIBRARY(libplc); } // clean up signon data... signonManager.RemoveSignonData(); isInitialized = FPM_FALSE; } int ProfileManager::IsMasterPasswordSet() { PK11SlotInfo *slot = 0; int retValue = 0; SECStatus status; slot = (*PK11GetInternalKeySlot)(); if (!slot) { PrintMessage(MESG_ERROR, "\n IsMasterPasswordSet PK11_GetInternalKeySlot failed ..."); return FPM_FALSE; } PrintMessage(MESG_DEBUG, "\n PK11_GetInternalKeySlot SUCCESS ..."); // Check with empty password....If it succeeds then master password is not set status = (*PK11CheckUserPassword)(slot,""); if( status == SECSuccess ) { PrintMessage(MESG_DEBUG, "\n IsMasterPasswordSet : Master password is not set..."); retValue = FPM_FALSE; } else if(status == SECWouldBlock ) // password is wrong { PrintMessage(MESG_DEBUG, "\n IsMasterPasswordSet : Master password is set..."); retValue = FPM_TRUE; } else // something is wrong, may be key3.db is not initialized for crypt { PrintMessage(MESG_DEBUG, "\n IsMasterPasswordSet : Master password is not set..."); retValue = FPM_FALSE; } // Free the slot (*PK11FreeSlot) (slot); return retValue; } int ProfileManager::CheckMasterPassword(char *masterPassword, int doSave) { PK11SlotInfo *slot = 0; int retValue = 0; slot = (*PK11GetInternalKeySlot)(); if (!slot) { PrintMessage(MESG_ERROR, "\n CheckMasterPassword PK11_GetInternalKeySlot failed ..."); return FPM_FALSE; } if( (*PK11CheckUserPassword)(slot, masterPassword) == SECSuccess ) { // Store the password for internal use... if( doSave ) { PrintMessage(MESG_DEBUG, "\n CheckMasterPassword : saving master password for future use ******..."); this->masterPassword = (char *) malloc( strlen(masterPassword)+1 ); if( !this->masterPassword ) { PrintMessage(MESG_ERROR, "\n CheckMasterPassword : Insufficient memory"); (*PK11FreeSlot) (slot); // Free the slot... return FPM_INSUFFICIENT_MEMORY; } strcpy(this->masterPassword, masterPassword); } PrintMessage(MESG_DEBUG, "\n CheckMasterPassword : specified master password is correct..."); retValue = FPM_TRUE; } else { PrintMessage(MESG_ERROR, "\n CheckMasterPassword : specified master password is wrong..."); retValue = FPM_FALSE; } // Free the slot (*PK11FreeSlot) (slot); return retValue; } int ProfileManager::GetSignonData( struct Host **host, int doRefresh) { int retValue; //TODO NAG: //check if "remember password" enabled.... // Reload the signon data from the file... if( doRefresh ) { retValue = RefreshSignonData(); *host = signonManager.GetHostInfo(); return retValue; } // if host list is null read again.... // TODO NAG : If there is no data , this will cause refresh to happen every time... if( signonManager.GetHostInfo() == NULL ) { retValue = RefreshSignonData(); *host = signonManager.GetHostInfo(); return retValue; } // Just return the previously loaded data *host = signonManager.GetHostInfo(); return FPM_TRUE; } int ProfileManager::RefreshSignonData() { // First check if master password is correct.... if( masterPassword ) { // Just check for password , don't save.... if( CheckMasterPassword(masterPassword, 0 ) != FPM_TRUE ) { PrintMessage(MESG_ERROR, "\n RefreshSignonData : master password is wrong..can't proceed with signon decryption" ); return FPM_MASTERPASSWORD_WRONG; } } else // check if master password is set... { // master password is set and its not specified if( IsMasterPasswordSet() == FPM_TRUE ) { PrintMessage(MESG_ERROR, "\n RefreshSignonData : master password is set..but its not specified " ); return FPM_MASTERPASSWORD_WRONG; } } return signonManager.LoadSignonData(profilePath); } int ProfileManager::WriteSignonData() { // First check if master password is correct.... if( masterPassword ) { // Just check for password , don't save.... if( CheckMasterPassword(masterPassword, 0 ) != FPM_TRUE ) { PrintMessage(MESG_ERROR, "\n WriteSignonData : master password is wrong..can't proceed with signon decryption" ); return FPM_MASTERPASSWORD_WRONG; } } else // check if master password is set... { // master password is set and its not specified if( IsMasterPasswordSet() == FPM_TRUE ) { PrintMessage(MESG_ERROR, "\n WriteSignonData : master password is set..but its not specified " ); return FPM_MASTERPASSWORD_WRONG; } } return signonManager.WriteSignonData(profilePath); } int ProfileManager::AddHost(struct Host *host, int doUpdate) { int retValue; if( (retValue = signonManager.AddHost(host)) != FPM_TRUE) { PrintMessage(MESG_ERROR, "\n AddHost : Failed to add the host %s ", host->hostName); return retValue; } if( doUpdate > 0 ) { PrintMessage(MESG_ERROR, "\n AddHost : Updating the signon file "); return WriteSignonData(); } return FPM_TRUE; } int ProfileManager::ModifyHost(struct Host *host, int doUpdate) { int retValue; if( (retValue = signonManager.ModifyHost(host)) != FPM_TRUE) { PrintMessage(MESG_ERROR, "\n ModifyHost : Failed to modify the host %s ", host->hostName); return retValue; } if( doUpdate > 0) { PrintMessage(MESG_ERROR, "\n ModifyHost : Updating the signon file "); return WriteSignonData(); } return FPM_TRUE; } int ProfileManager::RemoveHost(char *hostName, int doUpdate) { int retValue; if( (retValue = signonManager.RemoveHost(hostName)) != FPM_TRUE) { PrintMessage(MESG_ERROR, "\n RemoveHost : Failed to remove the hsot %s ", hostName); return retValue; } if( doUpdate > 0 ) { PrintMessage(MESG_ERROR, "\n RemoveHost : Updating the signon file "); return WriteSignonData(); } return FPM_TRUE; }