CASA/c_adlib/ad_ff/native/ProfileManager.cpp

851 lines
20 KiB
C++
Raw Normal View History

2006-02-28 12:17:08 +01:00
#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; i<strlen(line); i++)
{
if( line[i] == '=' )
break;
if( line[i] >=65 && line[i]<=90 )
line[i]+=32;
}
if( isProfileFound )
{
temp = strchr(line,'=') + 1;
// check for IsRelative=
if( strstr(line, "isrelative=") != NULL )
{
// Is the value greater than 0 ( ascii 48 )
isRelative = (*temp > 48)? 1 : 0 ;
continue;
}
// check for Path=
if( strstr(line, "path=") != NULL )
{
path = (char*) malloc(strlen(temp) + 1);
if( !path )
{
PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Insufficient memory ");
fclose(profile);
return 0;
}
strcpy(path,temp);
continue;
}
// Break once you encounter next profile
if( strstr(line, "profile") != NULL )
{
break;
}
}
if( strstr(line, "name=") != NULL )
{
temp = strchr(line,'=') + 1;
if( STRCMPI(temp, profileName) == 0 )
{
PrintMessage(MESG_DEBUG, "\n GetFirefoxProfilePath : Profile name [%s] found ", profileName);
isProfileFound = 1;
}
}
}
fclose(profile);
if( !isProfileFound )
{
PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Specified Profile [%s] not present ", profileName);
return NULL;
}
if( !path )
{
PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Profile [%s] path not found ", profileName);
return NULL;
}
if( isRelative )
{
#ifdef WIN32
// if path contains '/' then make it '\\'
char *slash = strstr(path,"/");
if( slash != NULL )
*slash = '\\';
int totalLen = strlen(profileDir) + strlen(partialPath) + strlen(path) + 3 ;
finalProfilePath = (char *) malloc(totalLen);
if( finalProfilePath )
{
strcpy(finalProfilePath,profileDir);
strcat(finalProfilePath,"\\");
strcat(finalProfilePath,partialPath);
strcat(finalProfilePath,"\\");
strcat(finalProfilePath,path);
PrintMessage(MESG_DEBUG, "\n Final profile path is : %s ", finalProfilePath);
}
#else // Linux platform
int totalLen = strlen(homeDir) + strlen(profileDir) + strlen(path) + 2 ;
finalProfilePath = (char *) malloc(totalLen);
if( finalProfilePath )
{
strcpy(finalProfilePath,homeDir);
strcat(finalProfilePath,profileDir);
strcat(finalProfilePath,"/");
strcat(finalProfilePath,path);
PrintMessage(MESG_DEBUG, "\n Final profile path is : %s ", finalProfilePath);
}
#endif
if(path)
free(path);
}
else
{
finalProfilePath = path;
}
if( !finalProfilePath)
{
PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Insufficient memory ");
return NULL;
}
// check if profile directory exists.....
if( !IsDirectoryExists(finalProfilePath) )
{
PrintMessage(MESG_ERROR, "\n GetFirefoxProfilePath : Profile directory [%s] does not exist", finalProfilePath);
free(finalProfilePath);
return NULL;
}
return finalProfilePath;
}
char* ProfileManager::GetFirefoxLibPath()
{
char *firefoxPath = NULL;
#ifdef WIN32
char regSubKey[] = "SOFTWARE\\Clients\\StartMenuInternet\\firefox.exe\\shell\\open\\command";
char pathValue[MAX_PATH] ="";
DWORD pathSize = MAX_PATH;
DWORD valueType;
HKEY rkey;
// Open firefox registry key
if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, regSubKey, 0, KEY_READ, &rkey) != ERROR_SUCCESS )
{
PrintMessage(MESG_ERROR, "\n GetFirefoxLibPath : Failed to open the firefox registry key : HKCU\\%s", regSubKey );
return NULL;
}
// Read the firefox path value
if( RegQueryValueEx(rkey, NULL, 0, &valueType, (unsigned char*)&pathValue, &pathSize) != ERROR_SUCCESS )
{
PrintMessage(MESG_ERROR, "\n GetFirefoxLibPath : Failed to read the firefox path value from registry ");
RegCloseKey(rkey);
return NULL;
}
if( pathSize <= 0 || pathValue[0] == 0)
{
PrintMessage(MESG_ERROR, "\n GetFirefoxLibPath : Path value read from the registry is empty");
RegCloseKey(rkey);
return NULL;
}
RegCloseKey(rkey);
// This path may contain extra double quote....
if( pathValue[0] == '\"' )
{
for(unsigned int i=0; i< strlen(pathValue)-1 ; i++)
pathValue[i] = pathValue[i+1];
}
PrintMessage(MESG_DEBUG, "\n GetFirefoxLibPath : Path value read from registry is %s", pathValue);
StrLwr(pathValue);
char *firefox = strstr(pathValue, "firefox.exe");
if( firefox == NULL )
{
PrintMessage(MESG_ERROR, "\n GetFirefoxLibPath : Path value read from registry is invalid");
return NULL;
}
// remove the firefox.exe from the end...
*(firefox-1) = 0;
firefoxPath = (char*) malloc( strlen(pathValue) + 1);
if( firefoxPath )
{
strcpy(firefoxPath, pathValue);
if( !IsDirectoryExists(firefoxPath) )
{
free(firefoxPath);
return NULL;
}
}
#else // Linux platform...
char path[]="/opt/MozillaFirefox/lib";
firefoxPath = (char*) malloc( strlen(path) + 1);
if( firefoxPath )
{
strcpy(firefoxPath, path);
}
#endif
PrintMessage(MESG_DEBUG, "\n GetFirefoxLibPath : Firefox library path = [%s] ", firefoxPath);
return firefoxPath;
}
HMODULE ProfileManager::PMLoadLibrary(char *firefoxDir, char *libName)
{
char *loadPath;
HMODULE libtmp = NULL;
if( firefoxDir != NULL )
loadPath = ( char*) malloc(strlen(firefoxDir) + strlen(libName) + 2);
else
loadPath = ( char*) malloc(strlen(libName) + 1);
if( !loadPath )
{
PrintMessage(MESG_ERROR, "\n\n LoadLibrary : Insufficient memory");
return 0;
}
if( firefoxDir != NULL )
{
strcpy(loadPath, firefoxDir);
strcat(loadPath, "/");
strcat(loadPath, libName);
}
else
{
strcpy(loadPath, libName);
}
libtmp = LOADLIBRARY(loadPath);
if( !libtmp )
{
2006-03-06 10:54:36 +01:00
PrintMessage(MESG_DEBUG, "\n\n LoadLibrary : Failed to load library %s ", loadPath);
2006-02-28 12:17:08 +01:00
free(loadPath);
return 0;
}
free(loadPath);
return libtmp;
}
// Public functions...
int ProfileManager::ProfileInit(char *profileName)
{
if( isInitialized == FPM_TRUE)
{
PrintMessage(MESG_DEBUG, "\n ProfileInit : Firefox profile [%s] is already initialized ", profileName);
return FPM_TRUE;
}
profilePath = GetFirefoxProfilePath(profileName);
libraryPath = GetFirefoxLibPath();
if( !profilePath || !libraryPath )
{
PrintMessage(MESG_ERROR, "\n ProfileInit : Failed to find firefox profile or library path ");
return FPM_PROFILE_NOT_PRESENT;
}
PrintMessage(MESG_DEBUG, "\n Profile path = [%s] ", profilePath);
PrintMessage(MESG_DEBUG, "\n Library path = [%s] ", libraryPath);
// First try to load from the library path then try to load from default lib path
// Here we have to first load all dependent libraries and then
// load main library , otherwise face the problems...:)
if( PMLoadLibrary(libraryPath, NSPR_LIBRARY_NAME) )
{
if((libplc=PMLoadLibrary(libraryPath, PLC_LIBRARY_NAME)) )
{
if( PMLoadLibrary(libraryPath, PLDS_LIBRARY_NAME) )
{
if( PMLoadLibrary(libraryPath, SOFTN_LIBRARY_NAME) )
libnss=PMLoadLibrary(libraryPath, NSS_LIBRARY_NAME);
}
}
}
else // try to load library from default library path
{
if( PMLoadLibrary(NULL, NSPR_LIBRARY_NAME) )
{
if((libplc=PMLoadLibrary(NULL, PLC_LIBRARY_NAME)) )
{
if( PMLoadLibrary(NULL, PLDS_LIBRARY_NAME) )
{
if( PMLoadLibrary(NULL, SOFTN_LIBRARY_NAME) )
libnss=PMLoadLibrary(NULL, NSS_LIBRARY_NAME);
}
}
}
}
if( !libnss || !libplc )
{
2006-03-06 10:54:36 +01:00
PrintMessage(MESG_ERROR, "\n ProfileInit : Failed to load the required firefox library");
2006-02-28 12:17:08 +01:00
return FPM_LIBRARY_LOAD_FAILED;
}
PrintMessage(MESG_DEBUG, "\n ProfileInit : Required libraries are loaded from firefox path successfully..");
// Get all the functions from NSS library
NSSInit = (NSS_Init) GETPROCADDRESS(libnss, "NSS_Init");
NSSShutdown = (NSS_Shutdown)GETPROCADDRESS(libnss, "NSS_Shutdown");
//PK11SetPasswordFunc = (PK11_SetPasswordFunc) GETPROCADDRESS(libnss, "PK11_SetPasswordFunc");
PK11GetInternalKeySlot = (PK11_GetInternalKeySlot) GETPROCADDRESS(libnss, "PK11_GetInternalKeySlot");
PK11FreeSlot = (PK11_FreeSlot) GETPROCADDRESS(libnss, "PK11_FreeSlot");
PK11Authenticate = (PK11_Authenticate) GETPROCADDRESS(libnss, "PK11_Authenticate");
PK11SDRDecrypt = (PK11SDR_Decrypt) GETPROCADDRESS(libnss, "PK11SDR_Decrypt");
PK11SDREncrypt = (PK11SDR_Encrypt) GETPROCADDRESS(libnss, "PK11SDR_Encrypt");
PK11CheckUserPassword = (PK11_CheckUserPassword) GETPROCADDRESS(libnss, "PK11_CheckUserPassword");
if( !NSSInit || !NSSShutdown || !PK11GetInternalKeySlot || !PK11Authenticate || !PK11SDRDecrypt || !PK11SDREncrypt || !PK11FreeSlot || !PK11CheckUserPassword)
{
PrintMessage(MESG_ERROR, "\n\n ProfileInit : Failed to get function address for library %s ", NSS_LIBRARY_NAME);
ProfileExit();
return FPM_LIBRARY_LOAD_FAILED;
}
// Get all the functions from PLC library
PLBase64Encode = ( PL_Base64Encode ) GETPROCADDRESS(libplc, "PL_Base64Encode");
PLBase64Decode = ( PL_Base64Decode ) GETPROCADDRESS(libplc, "PL_Base64Decode");
if( !PLBase64Encode || !PLBase64Decode )
{
PrintMessage(MESG_ERROR, "\nProfileInit : Failed to get function address for library %s ", PLC_LIBRARY_NAME);
ProfileExit();
return FPM_LIBRARY_LOAD_FAILED;
}
// Initialize the NSS library
if( (*NSSInit) (profilePath) != SECSuccess )
{
PrintMessage(MESG_ERROR, "\n ProfileInit : Initialization failed , Make sure key3.db and cert8.db");
PrintMessage(MESG_ERROR, "\n files are present in the specified directory\n");
ProfileExit();
return FPM_LIBRARY_INIT_FAILED;
}
PrintMessage(MESG_DEBUG, "\n ProfileInit : NSS_Init success..");
// Copy the profile name for later use
this->profileName = (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()
{
2006-03-06 10:54:36 +01:00
int i;
2006-02-28 12:17:08 +01:00
PrintMessage(MESG_DEBUG, "\n ProfileExit : Shutting down the profile %s", profileName);
if( (isInitialized == FPM_TRUE) && NSSShutdown != NULL )
2006-03-06 10:54:36 +01:00
{
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");
}
2006-02-28 12:17:08 +01:00
if( libnss != NULL )
2006-03-06 10:54:36 +01:00
{
PrintMessage(MESG_DEBUG, "\n ProfileExit : Freeing library libnss.dll");
2006-02-28 12:17:08 +01:00
FREELIBRARY(libnss);
2006-03-06 10:54:36 +01:00
}
2006-02-28 12:17:08 +01:00
if( libplc != NULL )
2006-03-06 10:54:36 +01:00
{
PrintMessage(MESG_DEBUG, "\n ProfileExit : Freeing library libplc.dll");
2006-02-28 12:17:08 +01:00
FREELIBRARY(libplc);
2006-03-06 10:54:36 +01:00
}
2006-02-28 12:17:08 +01:00
// clean up signon data...
signonManager.RemoveSignonData();
isInitialized = FPM_FALSE;
}
int ProfileManager::IsMasterPasswordSet()
{
PK11SlotInfo *slot = 0;
int retValue = 0;
2006-03-06 10:54:36 +01:00
SECStatus status;
2006-02-28 12:17:08 +01:00
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
2006-03-06 10:54:36 +01:00
status = (*PK11CheckUserPassword)(slot,"");
if( status == SECSuccess )
2006-02-28 12:17:08 +01:00
{
PrintMessage(MESG_DEBUG, "\n IsMasterPasswordSet : Master password is not set...");
retValue = FPM_FALSE;
}
2006-03-06 10:54:36 +01:00
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;
}
2006-02-28 12:17:08 +01:00
// 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;
}