This commit is contained in:
650
c_adlib/ad_ff/native/SignonManager.cpp
Normal file
650
c_adlib/ad_ff/native/SignonManager.cpp
Normal file
@@ -0,0 +1,650 @@
|
||||
|
||||
#include "SignonManager.h"
|
||||
|
||||
SignonManager::SignonManager()
|
||||
{
|
||||
signonFile = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SignonManager::~SignonManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SignonManager::SetupFunctions(void *funList[])
|
||||
{
|
||||
cryptManager.SetupFunctions(funList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int SignonManager::OpenSignonFile(char *firefoxProfileDir, char *fileName, char *accessType )
|
||||
{
|
||||
char *signonFilePath = NULL;
|
||||
|
||||
signonFilePath = (char*) malloc( strlen(firefoxProfileDir) + strlen(fileName) + 3 );
|
||||
|
||||
if( signonFilePath == NULL )
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\n Insufficient memory ....");
|
||||
return FPM_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
|
||||
strcpy(signonFilePath, firefoxProfileDir);
|
||||
strcat(signonFilePath, "/");
|
||||
strcat(signonFilePath, fileName);
|
||||
|
||||
PrintMessage(MESG_DEBUG, "\n Final signon filename is = %s ", signonFilePath);
|
||||
|
||||
// Open the signon file
|
||||
signonFile = fopen(signonFilePath, accessType);
|
||||
|
||||
if( signonFile == NULL )
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\n SignonManager : Error opening signon file %s", signonFilePath);
|
||||
free(signonFilePath);
|
||||
return FPM_SIGNON_FILE_NOT_PRESENT;
|
||||
}
|
||||
|
||||
// cleanup
|
||||
free(signonFilePath);
|
||||
|
||||
return FPM_TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int SignonManager::CloseSignonFile()
|
||||
{
|
||||
|
||||
if( signonFile )
|
||||
fclose(signonFile);
|
||||
|
||||
return FPM_TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int SignonManager::ReadLine(char *buffer, int size)
|
||||
{
|
||||
Unichar c;
|
||||
int strLength = 0, i=0;
|
||||
|
||||
buffer[0] = 0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
c = ReadCharUTF8();
|
||||
|
||||
/* note that eof is not set until we read past the end of the file */
|
||||
if ( c == FPM_FALSE ) // || feof(file) )
|
||||
return FPM_FALSE;
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
buffer[strLength++] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (c != '\r')
|
||||
{
|
||||
for(i=0; i < 4 && ( (c & 0xff) != 0 ) ; i++)
|
||||
{
|
||||
if( strLength >= size )
|
||||
{
|
||||
// Increase the capacity dynamically
|
||||
PrintMessage(MESG_ERROR, "SignonManager : Buffer is insufficient to store data");
|
||||
return FPM_FALSE;
|
||||
}
|
||||
|
||||
buffer[strLength++] = (char)c;
|
||||
c = c >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// PrintMessage(MESG_DEBUG,"SignonManager : ReadLine = %s ",buffer);
|
||||
return FPM_TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Unichar SignonManager::ReadCharUTF8()
|
||||
{
|
||||
Unichar c = ReadChar();
|
||||
|
||||
if ((c & 0x80) == 0x00)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
else if ((c & 0xE0) == 0xC0)
|
||||
{
|
||||
return (((c & 0x1F)<<6) + (ReadChar() & 0x3F));
|
||||
}
|
||||
else if ((c & 0xF0) == 0xE0)
|
||||
{
|
||||
return (((c & 0x0F)<<12) + ((ReadChar() & 0x3F)<<6) + (ReadChar() & 0x3F));
|
||||
}
|
||||
|
||||
|
||||
return FPM_FALSE; // 0 => not a utf8 character...
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// This does buffered reading...
|
||||
//
|
||||
char SignonManager::ReadChar()
|
||||
{
|
||||
const int buflen = 1000;
|
||||
static char buf[buflen+1];
|
||||
static int last = 0;
|
||||
static int next = 0;
|
||||
|
||||
if (next >= last)
|
||||
{
|
||||
next = 0;
|
||||
last = fread(buf, 1, buflen, signonFile);
|
||||
PrintMessage(MESG_DEBUG,"\n SignonManager : ReadChar = Read %d bytes ",last);
|
||||
|
||||
if (last <= 0) // || feof(file)
|
||||
{
|
||||
/* note that eof is not set until we read past the end of the file */
|
||||
PrintMessage(MESG_DEBUG,"\n SignonManager : ReadChar = End of file..! ");
|
||||
return FPM_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return (buf[next++]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int SignonManager::WriteCharUTF8(Unichar c)
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
if( fputc((char)c, signonFile) == EOF )
|
||||
return FPM_SIGNON_FILE_WRITE_ERROR;
|
||||
}
|
||||
else if (c <= 0x7FF)
|
||||
{
|
||||
if( fputc( ((Unichar)0xC0) | ((c>>6) & 0x1F), signonFile) == EOF )
|
||||
return FPM_SIGNON_FILE_WRITE_ERROR;
|
||||
|
||||
if( fputc( ((Unichar)0x80) | (c & 0x3F), signonFile ) == EOF )
|
||||
return FPM_SIGNON_FILE_WRITE_ERROR;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if( fputc( ((Unichar)0xE0) | ((c>>12) & 0xF), signonFile) == EOF )
|
||||
return FPM_SIGNON_FILE_WRITE_ERROR;
|
||||
if( fputc( ((Unichar)0x80) | ((c>>6) & 0x3F), signonFile) == EOF)
|
||||
return FPM_SIGNON_FILE_WRITE_ERROR;
|
||||
if( fputc( ((Unichar)0x80) | (c & 0x3F), signonFile) == EOF)
|
||||
return FPM_SIGNON_FILE_WRITE_ERROR;
|
||||
}
|
||||
|
||||
return FPM_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int SignonManager::WriteLine(char *line)
|
||||
{
|
||||
|
||||
for(int i=0; i < strlen(line); i++)
|
||||
{
|
||||
if( WriteCharUTF8(line[i]) != FPM_TRUE )
|
||||
return FPM_SIGNON_FILE_WRITE_ERROR;
|
||||
|
||||
}
|
||||
|
||||
if( WriteCharUTF8('\n') != FPM_TRUE )
|
||||
return FPM_SIGNON_FILE_WRITE_ERROR;
|
||||
|
||||
return FPM_TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Load the signon data from firefox signon file.....
|
||||
*
|
||||
*
|
||||
*/
|
||||
int SignonManager::LoadSignonData(char *firefoxProfileDir )
|
||||
{
|
||||
char header[256];
|
||||
char buffer[4096];
|
||||
char hostName[4096];
|
||||
char name[1024];
|
||||
int bufferLength = 4095;
|
||||
int retValue;
|
||||
char *clearData = NULL;
|
||||
int count = 0;
|
||||
|
||||
|
||||
// open the signon file
|
||||
if( (retValue = OpenSignonFile(firefoxProfileDir, SIGNON_FILE_NAME, "r")) != FPM_TRUE )
|
||||
{
|
||||
return retValue;
|
||||
}
|
||||
|
||||
// Clean up any previously loaded data...
|
||||
dataManager.RemoveAllData();
|
||||
|
||||
// read the signon header information
|
||||
if( ReadLine(header, 256) != FPM_TRUE )
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\n SignonManager : Error in reading signon format header %s", header);
|
||||
CloseSignonFile();
|
||||
return FPM_SIGNON_FILE_READ_ERROR;
|
||||
}
|
||||
|
||||
// check if the format is right...
|
||||
if( strcmp(header, HEADER_VERSION) != 0)
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\n SignonManager : Header version information is not proper");
|
||||
CloseSignonFile();
|
||||
return FPM_SIGNON_FILE_INVALID_DATA;
|
||||
}
|
||||
|
||||
|
||||
PrintMessage(MESG_DEBUG, "\n\n ****** Reject Host List *******");
|
||||
|
||||
// read the reject list
|
||||
while ( ReadLine(buffer, bufferLength) == FPM_TRUE)
|
||||
{
|
||||
// Check for end of reject list i.e full stop
|
||||
if (strlen(buffer) != 0 && buffer[0] == '.')
|
||||
{
|
||||
break; // end of reject list
|
||||
}
|
||||
|
||||
if( (retValue = dataManager.AddRejectHost(buffer) ) != FPM_TRUE )
|
||||
{
|
||||
CloseSignonFile();
|
||||
dataManager.RemoveAllData(); // clean up any partial loaded data
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
PrintMessage(MESG_DEBUG, "\n Reject Host : %s ", buffer);
|
||||
|
||||
}
|
||||
|
||||
|
||||
PrintMessage(MESG_DEBUG, "\n\n ****** Host list with username / password ****** ");
|
||||
|
||||
|
||||
while (ReadLine(hostName, bufferLength) == FPM_TRUE)
|
||||
{
|
||||
// a blank line is perfectly valid here -- corresponds to a local file
|
||||
if (strlen(hostName) < 1)
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\n SignonManager : Host URL is not proper");
|
||||
CloseSignonFile();
|
||||
dataManager.RemoveAllData(); // clean up partial loaded data
|
||||
|
||||
return FPM_ILLEGAL_HOSTNAME;
|
||||
}
|
||||
|
||||
if( ( retValue = dataManager.AddHost(hostName) ) != FPM_TRUE )
|
||||
{
|
||||
CloseSignonFile();
|
||||
dataManager.RemoveAllData(); // clean up partial loaded data
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
PrintMessage(MESG_DEBUG, "\n\n Host : %s ", hostName);
|
||||
|
||||
// prepare to read the name/value pairs
|
||||
while( ReadLine(buffer, bufferLength) == FPM_TRUE )
|
||||
{
|
||||
// line starting with . terminates the pairs for this URL entry
|
||||
if (buffer[0] == '.')
|
||||
{
|
||||
break; // end of URL entry
|
||||
}
|
||||
|
||||
// save the name part and determine if it is a password
|
||||
unsigned char isPassword = 0;
|
||||
if (buffer[0] == '*')
|
||||
{
|
||||
isPassword = 1;
|
||||
strcpy(name,&buffer[1]);
|
||||
retValue = ReadLine(buffer, bufferLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
isPassword = 0;
|
||||
strcpy(name, buffer);
|
||||
retValue = ReadLine(buffer, bufferLength);
|
||||
}
|
||||
|
||||
PrintMessage(MESG_DEBUG, "\n\n name = %s and value = %s ", name, buffer);
|
||||
|
||||
// read in and save the value part
|
||||
if ( retValue != FPM_TRUE )
|
||||
{
|
||||
// error in input file so give up
|
||||
PrintMessage(MESG_ERROR, "\n SignonManager : Error occured while reading VALUE for : %s ", name);
|
||||
CloseSignonFile();
|
||||
dataManager.RemoveAllData(); // clean up partial loaded data
|
||||
|
||||
return FPM_SIGNON_FILE_READ_ERROR;
|
||||
}
|
||||
|
||||
// Decrypt the encrypted value....
|
||||
retValue = FPM_FALSE;
|
||||
if( ((retValue = cryptManager.DecryptString(buffer, &clearData)) == FPM_TRUE) && (clearData != NULL) )
|
||||
{
|
||||
// Add the name/value pair to the existing store....
|
||||
retValue = dataManager.AddHostElement(hostName, name, clearData, isPassword);
|
||||
|
||||
if( retValue != FPM_TRUE )
|
||||
{
|
||||
CloseSignonFile();
|
||||
dataManager.RemoveAllData(); // clean up partial loaded data
|
||||
return retValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
CloseSignonFile();
|
||||
dataManager.RemoveAllData(); // clean up partial loaded data
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Now close the signon file
|
||||
CloseSignonFile();
|
||||
|
||||
// Print data for cross checking
|
||||
#ifdef DEBUG
|
||||
dataManager.PrintAllRejectHosts();
|
||||
dataManager.PrintAllHosts();
|
||||
#endif
|
||||
return FPM_TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int SignonManager::WriteSignonData(char *firefoxProfileDir)
|
||||
{
|
||||
int retValue;
|
||||
char *cryptData = NULL;
|
||||
char *signonFilePath = NULL;
|
||||
char *tempFilePath = NULL;
|
||||
char fileName[256];
|
||||
|
||||
Host *t;
|
||||
HostElement *h;
|
||||
RejectHost *r;
|
||||
|
||||
// TODO : If signon data has not changed since last write then return...
|
||||
/* // There may be requirement to write empty data...
|
||||
if( dataManager.hostList == NULL )
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\n WriteSignonData : Signon data is empty...");
|
||||
return FPM_SIGNON_DATASTORE_EMPTY;
|
||||
}
|
||||
*/
|
||||
|
||||
// Generate random file name
|
||||
srand( (unsigned)time( NULL ) );
|
||||
sprintf(fileName,"signon_fpm_%d.txt", rand());
|
||||
|
||||
// Setup the signon and temp filename..
|
||||
signonFilePath = (char*) malloc( strlen(firefoxProfileDir) + strlen(SIGNON_FILE_NAME) + 3);
|
||||
tempFilePath =(char*) malloc( strlen(firefoxProfileDir) + strlen(fileName) + 3);
|
||||
|
||||
if( signonFilePath == NULL || tempFilePath == NULL)
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\n WriteSignonData : Insufficient memory ....");
|
||||
return FPM_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
|
||||
strcpy(signonFilePath, firefoxProfileDir);
|
||||
strcat(signonFilePath, "/");
|
||||
strcat(signonFilePath, SIGNON_FILE_NAME);
|
||||
|
||||
strcpy(tempFilePath, firefoxProfileDir);
|
||||
strcat(tempFilePath, "/");
|
||||
strcat(tempFilePath, fileName);
|
||||
|
||||
// Open signon file
|
||||
if( (retValue = OpenSignonFile(firefoxProfileDir, fileName, "w")) != FPM_TRUE )
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\nWriteSignonData : Failed to create temp signon file : %s.", fileName);
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
// write out the format revision number
|
||||
if( (retValue = WriteLine(HEADER_VERSION)) != FPM_TRUE)
|
||||
goto write_signon_error;
|
||||
|
||||
// write out reject host list
|
||||
for(r=dataManager.rejectHostList; r ; r=r->next)
|
||||
{
|
||||
if( (retValue = WriteLine(r->hostName)) != FPM_TRUE )
|
||||
goto write_signon_error;
|
||||
|
||||
}
|
||||
|
||||
// End of reject host list
|
||||
if( (retValue = WriteLine(".")) != FPM_TRUE )
|
||||
goto write_signon_error;
|
||||
|
||||
|
||||
/* format for cached logins shall be:
|
||||
* url LINEBREAK {name LINEBREAK value LINEBREAK}* . LINEBREAK
|
||||
* if type is password, name is preceded by an asterisk (*)
|
||||
*/
|
||||
|
||||
|
||||
// write out each URL node
|
||||
for(t=dataManager.hostList; t ; t=t->next)
|
||||
{
|
||||
PrintMessage(MESG_DEBUG, "\n\nWriteSignonData : Adding name/value pairs for host %s", t->hostName);
|
||||
|
||||
if( (retValue = WriteLine(t->hostName)) != FPM_TRUE )
|
||||
goto write_signon_error;
|
||||
|
||||
|
||||
for(h=t->child; h ; h= h->next)
|
||||
{
|
||||
PrintMessage(MESG_DEBUG, "\n nWriteSignonData : %s : %s ", h->name, h->value);
|
||||
|
||||
if( h->isPassword)
|
||||
{
|
||||
if( (retValue = WriteCharUTF8('*')) != FPM_TRUE )
|
||||
goto write_signon_error;
|
||||
}
|
||||
|
||||
if( (retValue = WriteLine(h->name)) != FPM_TRUE )
|
||||
goto write_signon_error;
|
||||
|
||||
|
||||
// encrypt the value
|
||||
retValue = FPM_FALSE;
|
||||
retValue = cryptManager.EncryptString(h->value, &cryptData);
|
||||
|
||||
if( (retValue == FPM_TRUE) && (cryptData != NULL ))
|
||||
{
|
||||
if( (retValue = WriteLine(cryptData)) != FPM_TRUE )
|
||||
goto write_signon_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\n nWriteSignonData : Encryption of value %s failed ", h->value);
|
||||
goto write_signon_error;
|
||||
}
|
||||
}
|
||||
|
||||
if( (retValue = WriteLine(".")) != FPM_TRUE )
|
||||
goto write_signon_error;
|
||||
}
|
||||
|
||||
// close this temporary file...
|
||||
CloseSignonFile();
|
||||
|
||||
|
||||
PrintMessage(MESG_DEBUG, "\n WriteSignonData : Removing previous signon file %s ", signonFilePath);
|
||||
|
||||
// Delete previous signon file
|
||||
if( remove(signonFilePath) != 0 )
|
||||
{
|
||||
// Either file not present or file is locked...
|
||||
PrintMessage(MESG_ERROR, "\n WriteSignonData : Failed to delete signon file : %s ", signonFilePath);
|
||||
FILE *sfile= NULL;
|
||||
if( (sfile = fopen(signonFilePath,"r") ) != NULL )
|
||||
{
|
||||
// we are able to open signon file in read only mode => file is present
|
||||
fclose(sfile);
|
||||
remove(tempFilePath); // delete temporary signon file
|
||||
|
||||
PrintMessage(MESG_ERROR, "\nWriteSignonData : Signon file is locked ");
|
||||
return FPM_SIGNON_FILE_LOCKED;
|
||||
}
|
||||
|
||||
// File is not present ..that's good news , so continue...
|
||||
}
|
||||
|
||||
PrintMessage(MESG_DEBUG, "success \n WriteSignonData : Renaming temp file %s back to signon file %s ", tempFilePath, signonFilePath);
|
||||
|
||||
// Rename temp file back to signon file
|
||||
if( ( retValue = rename(tempFilePath, signonFilePath) ) != 0 )
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\n WriteSignonData : Failed to rename the temp file %s back to signon file %s ", tempFilePath, signonFilePath);
|
||||
PrintMessage(MESG_ERROR, "\n WriteSignonData : Following error has occured : %d ", retValue);
|
||||
|
||||
return FPM_FALSE;
|
||||
}
|
||||
|
||||
PrintMessage(MESG_DEBUG, "\n WriteSignonData : Successfully written new signon data ...");
|
||||
|
||||
return FPM_TRUE;
|
||||
|
||||
write_signon_error:
|
||||
|
||||
CloseSignonFile();
|
||||
remove(tempFilePath); // remove the temporary signon file....
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int SignonManager::RemoveSignonData()
|
||||
{
|
||||
|
||||
return dataManager.RemoveAllData();
|
||||
|
||||
}
|
||||
|
||||
|
||||
int SignonManager::AddHost(struct Host *host)
|
||||
{
|
||||
|
||||
return dataManager.AddHost(host);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int SignonManager::ModifyHost(struct Host *host)
|
||||
{
|
||||
|
||||
return dataManager.ModifyHost(host);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int SignonManager::RemoveHost(char *hostName)
|
||||
{
|
||||
return dataManager.RemoveHost(hostName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
struct Host * SignonManager::GetHostInfo()
|
||||
{
|
||||
|
||||
return dataManager.hostList;
|
||||
}
|
||||
|
||||
|
||||
int SignonManager::AddUser(char *host, char *userName, char *password)
|
||||
{
|
||||
char checkString[]="test123";
|
||||
char *cryptData = NULL;
|
||||
char *clearData = NULL;
|
||||
char *newdata = NULL;
|
||||
/*
|
||||
// TODO : check if signon preference enabled....
|
||||
if( CheckSignonPref() == FPM_FALSE )
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\n MCSignonManager : Signon preference is not enabled...");
|
||||
return FPM_FALSE;
|
||||
}
|
||||
|
||||
|
||||
if( EncryptString ("test123", &cryptData) == FPM_FALSE )
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\n MCSignonManager : fAILED TO EncryptString");
|
||||
return FPM_FALSE;
|
||||
}
|
||||
|
||||
newdata = (char*) malloc(strlen(cryptData) + 1);
|
||||
strcpy(newdata, cryptData);
|
||||
|
||||
if( DecryptString(newdata, &clearData) == FPM_FALSE )
|
||||
{
|
||||
PrintMessage(MESG_ERROR, "\n MCSignonManager : Failed to DecryptString");
|
||||
return FPM_FALSE;
|
||||
}
|
||||
|
||||
printf("\n final decrypted string is : %s ", clearData);
|
||||
|
||||
if( strcmp(checkString, clearData) == 0 )
|
||||
{
|
||||
printf("\n Encryption - decryption test is success ");
|
||||
}
|
||||
else
|
||||
printf("\n Encryption - decryption test is FAILED ");
|
||||
*/
|
||||
return FPM_TRUE;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user