CASA/c_adlib/ad_ff/native/SignonManager.cpp
Manohar 0bc1f679e4
2006-03-06 09:54:36 +00:00

608 lines
14 KiB
C++

#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;
}