/*
* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
#include <f32file.h>
#include "tPinAuthPlugin.h"
#include <e32svr.h>
#ifndef __INIPARSER_H__
#include <cinidata.h>
#endif // __INIPARSER_H__
CTPinAuthPlugin::~CTPinAuthPlugin()
{
delete iClientMessage;
}
CTPinAuthPlugin::CTPinAuthPlugin()
{
// See ConstructL() for initialisation completion.
}
/**
Safely complete the initialization of the constructed object
*/
void CTPinAuthPlugin::ConstructL()
{
iName.Set(KPluginNamePin);
iDescription.Set(KPluginDescriptionPin);
iMinEntropy = KEntropyPin;
iFalsePositiveRate = KFalsePosPin;
iFalseNegativeRate = KFalseNegPin;
iClientMessage = HBufC::NewL(2048);
ReloadAllFromIniFile();
}
/**
Sets information like iActiveState and iSupportsDefaultData from
the TEF ini file to the individual plugin database files
*/
void CTPinAuthPlugin::ReloadAllFromIniFile()
{
// Set the file to be read, based on the Id of the plugin
_LIT(KFileText, "\\tAuth\\tAuthSvr\\testdata\\Pin");
_LIT(KFileSuffix, "Db.ini");
_LIT(KFormatFileName,"%S%x%S");
TDriveUnit sysDrive (RFs::GetSystemDrive());
TBuf<64> fileText(sysDrive.Name());
fileText.Append(KFileText);
iFileToRead.Format(KFormatFileName,&fileText, Id(), &KFileSuffix);
//Read data from file to get initialisation information
// Open and read in INI file
// Default path to look for INI file is in 'c:\system\data'
// on target filesystem
CIniData* file=NULL;
TRAPD(r,file=CIniData::NewL(iFileToRead));
//Put file on the cleanupstack if anything else in this function is going to leave, but nothing does.
if(r!=KErrNone)
{
RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
}
else
{
// Look for a key under a named section, retrieve text value
TPtrC result;
TBool ret; //return value from FindVar functions
ret=file->FindVar(_L("SectionOne"),_L("iSupportsDefaultData"),result);
if(!ret)
{
RDebug::Print(_L("Key or section not found. iSupportsDefaultData default value used."));
iSupportsDefaultData = ETrue; // Default value
}
else
{
_LIT(KFalse,"false");
// Create a lower case copy of the data that is read from the file
TBuf<10> resultLowerCase;
resultLowerCase.Copy(result);
resultLowerCase.LowerCase();
iSupportsDefaultData = (resultLowerCase.FindF(KFalse) == KErrNotFound);
}
// Set the active state of the plugin depending on the contents of the
// corresponding file, which has been set as a member variable
ret =file->FindVar(_L("SectionOne"),_L("activeState"),result);
if(!ret)
{
RDebug::Print(_L("Key or section not found. iActiveState default value of ETRUE used."));
iActiveState = ETrue; // Default value
}
else
{
_LIT(KFalse,"false");
// Create a lower case copy of the data that is read from the file
TBuf<10> resultLowerCase;
resultLowerCase.Copy(result);
resultLowerCase.LowerCase();
// If the string 'false' was not found, we set the value to 'true' -the default value
iActiveState = (resultLowerCase.FindF(KFalse) == KErrNotFound);
}
TRAPD(r,file->WriteToFileL());
if (KErrNone != r)
{
RDebug::Print(_L("Error occurred while writing to the file."));
TBuf<84> initInfoFile(sysDrive.Name());
initInfoFile.Append(KInitInfoFile);
RDebug::Print(_L("Filename = %S, KeyName = iSupportsDefaultData,"), &initInfoFile);
RDebug::Print(_L("value = %S."), &result);
}
delete file;
TRAP(r,file=CIniData::NewL(KAuthSvrPolicyFile));
TPtrC displayMessage;
ret=file->FindVar(_L("SectionOne"),_L("DisplayMessage"),displayMessage);
if(displayMessage.Length() == 0) //Value = 0
{
RDebug::Print(_L("DisplayMessage not passed."));
iClientMessage = iClientMessage->ReAllocL(0); // Default value
TPtr ptr(iClientMessage->Des());
ptr = KNullDesC();
ret=file->SetValue(_L("SectionOne"),_L("DisplayMessage"),displayMessage);
TRAP(r,file->WriteToFileL());
}
else
{
iClientMessage = iClientMessage->ReAllocL(displayMessage.Length());
TPtr ptr(iClientMessage->Des());
ptr = displayMessage;
ret=file->SetValue(_L("SectionOne"),_L("DisplayMessage"),displayMessage);
TRAP(r,file->WriteToFileL());
}
delete file;
}
}
void CTPinAuthPlugin::ReloadActiveStateFromIniFile() const
{
// Set the file to be read, based on the Id of the plugin
_LIT(KFileText, "\\tAuth\\tAuthSvr\\testdata\\Pin");
_LIT(KFileSuffix, "Db.ini");
_LIT(KFormatFileName,"%S%x%S");
TDriveUnit sysDrive (RFs::GetSystemDrive());
TBuf<64> fileText(sysDrive.Name());
fileText.Append(KFileText);
iFileToRead.Format(KFormatFileName,&fileText, Id(), &KFileSuffix);
//Read data from file to get initialisation information
// Open and read in INI file
// Default path to look for INI file is in 'c:\system\data'
// on target filesystem
CIniData* file=NULL;
TRAPD(r,file=CIniData::NewL(iFileToRead));
//Put file on the cleanupstack if anything else in this function is going to leave, but nothing does.
if(r!=KErrNone)
{
RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
}
else
{
// Look for a key under a named section, retrieve text value
TPtrC result;
TBool ret=EFalse; //return value from FindVar functions
// Set the active state of the plugin depending on the contents of the
// corresponding file, which has been set as a member variable
ret =file->FindVar(_L("SectionOne"),_L("activeState"),result);
if(!ret)
{
RDebug::Print(_L("Key or section not found. iActiveState default value of ETRUE used."));
iActiveState = ETrue; // Default value
}
else
{
_LIT(KFalse,"false");
// Create a lower case copy of the data that is read from the file
TBuf<10> resultLowerCase;
resultLowerCase.Copy(result);
resultLowerCase.LowerCase();
if (resultLowerCase.FindF(KFalse) == KErrNotFound)
iActiveState = ETrue; // The string 'false' was not found, so we set the value to 'true' -the default value
else
iActiveState = EFalse;
}
TRAPD(r,file->WriteToFileL());
if (KErrNone != r)
{
RDebug::Print(_L("Error occurred while writing to the file."));
TBuf<84> initInfoFile(sysDrive.Name());
initInfoFile.Append(KInitInfoFile);
RDebug::Print(_L("Filename = %S, KeyName = activeState,"), &initInfoFile);
RDebug::Print(_L("value = %S."), &result);
}
delete file;
}
}
//Implement CAuthPluginInterface definitions
/**
Normally, this would ask the user to input a 4-digit pin and then compare it to
the values that this plugin has been trained with. The result should be the
user that this PIN corresponds to.
'aResult' should be the 'hash' of the stored PIN (which corresponds to the freshly entered PIN)
but in this case, it's returned as it was 'unhashed'.
*/
void CTPinAuthPlugin::Identify(TIdentityId& aId, const TDesC& aClientMessage,
HBufC8*& aResult, TRequestStatus& aRequest)
{
ASSERT(IsActive());
// We are simulating user input by reading from a file
// (The data contained in this file has been freshly written by the 'client part in TestExecute')
if(aClientMessage != *ClientMessage())
{
RDebug::Print(_L("Display String Mismatch !!!"));
}
else
{
RDebug::Print(_L("Display String at the plugin matches the string sent !! "));
}
aRequest = KRequestPending;
TBuf8<32> userInput;
TRAPD(result1, IdReadUserInput(userInput)); //Get the data from the AuthSvrPolicy.ini file
if (KErrNone != result1)
{
aRequest = result1;
}
else
{
// No errors, carry on
//Convert the 8-bit string to a 16-bit string for printing in RDebug
HBufC* buf = 0;
buf = HBufC::NewLC(32);
buf->Des().Copy(userInput);
_LIT(KMsgDebug1,"Identifying Userinput read from file = %S");
RDebug::Print(KMsgDebug1, buf);
CleanupStack::PopAndDestroy(buf); //Memory cleanup. This string was only needed for the above Print function
// Possibly, to allow for the cancellation or quitting, allow that to be the input string
_LIT8(KCancelText, "Cancel");
_LIT8(KQuitText, "Quit");
if (userInput == KCancelText)
{
TRequestStatus* status = &aRequest;
User::RequestComplete(status, KErrAuthServPluginCancelled);
//aResult will not be updated, as specified
}
else if (userInput == KQuitText)
{
TRequestStatus* status = &aRequest;
User::RequestComplete(status, KErrAuthServPluginQuit);
//aResult will not be updated, as specified
}
else
{
//compare with the known set of inputs and see if this is one of them.
TInt result2 = CheckForStringPresence(aId, userInput, aRequest);
if (KErrNone == result2) //The above function did not leave
{
//See if the string was found.
TInt length = userInput.Length();
aResult = HBufC8::New(length);
aResult->Des().Format(_L8("%S"), &userInput);
RDebug::Printf("aResult has been updated. aResult = %S, userInput = %S",
aResult, &userInput);
TRequestStatus* status = &aRequest;
User::RequestComplete(status, result2);
//Note: aRequest has been updated by the CheckForStringPresence function
}
else if (KErrNotFound == result2)
{
RDebug::Printf("The data that the user input was not found (recognized)"
"Error = %d", result2);
TRequestStatus* status = &aRequest;
aId = KUnknownIdentity;
User::RequestComplete(status, KErrNone);
}
else
{
//Caters for file access errors etc
RDebug::Printf("Error occurred while checking for the presence of the string"
"in the list. Error = %d", result2);
TRequestStatus* status = &aRequest;
aId = KUnknownIdentity;
User::RequestComplete(status, KErrNone);
}
}
//End of 'else' where the user did not cancel or quit the 'identify' process
}
}
void CTPinAuthPlugin::Cancel()
{
}
void CTPinAuthPlugin::Train(TIdentityId aId, HBufC8*& aResult, TRequestStatus& aRequest)
{
//Accept user input and update the list of inputs along with IDs.
ASSERT(IsActive());
aRequest = KRequestPending;
//TInt result = KErrNone;
TBuf8<32> userInput;
TRAPD(result1, TrainReadUserInput(userInput));
if (KErrNone != result1)
{
_LIT(KMsgDebug2,"Training Userinput read Error: result = %d");
RDebug::Print(KMsgDebug2, result1);
}
else
{
// No errors, carry on
//Convert the 8-bit string to a 16-bit string for printing in RDebug
HBufC* buf = 0;
TRAPD(err, buf = HBufC::NewL(32));
if(err == KErrNoMemory)
{
TRequestStatus* status = &aRequest;
User::RequestComplete(status, KErrNoMemory);
return;
}
buf->Des().Copy(userInput);
_LIT(KMsgDebug3, "--Training Userinput read from file = %S");
RDebug::Print(KMsgDebug3, buf);
delete buf; //Memory cleanup. This string was only needed for the above Print function
// To allow for the cancellation or quitting, allow that to be the input string
TRequestStatus aRequest2 = KRequestPending;
_LIT8(KCancelText, "Cancel");
_LIT8(KQuitText, "Quit");
userInput.Trim();
if (userInput.CompareF(KCancelText) == 0)
{ aRequest2 = KErrAuthServPluginCancelled; }
else if (userInput.CompareF(KQuitText) == 0)
{ aRequest2 = KErrAuthServPluginQuit; }
else
{
//compare with the present set of inputs and see if this is one of them.
// update this list with this new user input, tagged to the aId
TRAPD(result2, CheckForNewStringPresenceL(aId, userInput, aRequest2));
if (KErrNone != result2)
{
_LIT(KMsgDebug4, "Training Userinput read Error: results = %d");
RDebug::Print(KMsgDebug4, result2);
}
else if(KErrNone == aRequest2.Int())
{
// No errors, update aResult.
// First allocate space for it since this variable will always be a
// null pointer coming into this function
TRAPD(err1,aResult = HBufC8::NewL(userInput.Size()));
if(err1 == KErrNoMemory)
{
TRequestStatus* status = &aRequest;
RDebug::Printf("User::request complete with kerr no memory");
User::RequestComplete(status, KErrNoMemory);
return;
}
*aResult = userInput;
aRequest2 = KErrNone;
}
else
{
_LIT(KMsgDebug5, "Error occurred during training. aRequest.Int() = %d");
RDebug::Print(KMsgDebug5, aRequest2.Int());
//aResult is not updated, nor is aId
}
}
// Complete the asynchronous function
TRequestStatus* status = &aRequest;
User::RequestComplete(status, aRequest2.Int());
}
}
TBool CTPinAuthPlugin::IsActive () const
{
// There is never any user intervention required
//return true;
// As a future development note, this value may be read from a file (or a section in a file)
ReloadActiveStateFromIniFile();
return iActiveState;
}
TInt CTPinAuthPlugin::Forget(TIdentityId aId)
{
// Open the list of userInputs that have been stored by this plugin
// Then find the one that corresponds to this id
// Then remove this string from the list and return the correct status value
//Open the file
TRAPD(result3, FindStringAndRemoveL(aId));
return result3;
}
TInt CTPinAuthPlugin::DefaultData(TIdentityId aId, HBufC8*& aOutputBuf)
{
// This implementation of the PIN plugin does support default data.
// There will be cases where i don't want this available. Hence the addition of a
// new class member iSupportsDefaultData
ReloadAllFromIniFile();
TInt result = KErrNotSupported;
TRequestStatus aRequest2 = KRequestPending;
if (iSupportsDefaultData) //Class member initialised in the constructor
{
TBufC8<16> defaultBuf(KDefaultData);
//compare with the present set of inputs and see if this is one of them.
// update this list with this new user input, tagged to the aId
TRAPD(result2, CheckForNewStringPresenceL(aId, defaultBuf, aRequest2));
if (KErrNone != result2)
{
_LIT(KMsgDebug4, "Training Userinput read Error: results = %d");
RDebug::Print(KMsgDebug4, result2);
}
else if(KErrNone == aRequest2.Int())
{
// No errors, update aOutputBuf.
// First allocate space for it since this variable will always be a
// null pointer coming into this function
TRAPD(resAlloc, (aOutputBuf = HBufC8::NewL(KDefaultData().Size())) );
if (KErrNone != resAlloc)
{
_LIT(KMsgAllocFailed2,"Failed to allocate memory for updating aOutputBuf");
RDebug::Print(KMsgAllocFailed2);
result = resAlloc;
}
else
{
*aOutputBuf = KDefaultData;
result = KErrNone;
}
}
else
{
_LIT(KMsgDebug5, "Error occurred during training. aRequest2.Int() = %d");
RDebug::Print(KMsgDebug5, aRequest2.Int());
//aOutputBuf is not updated, nor is aId
}
}
return result;
}
TInt CTPinAuthPlugin::Reset(TIdentityId aId, const TDesC& aRegistrationData, HBufC8*& aResult)
{
// To enable testing return KErrNotSupported for one of the knowledge-based incarnations of this class
if (Id() == 0x11113102)
{
return KErrNotSupported;
}
// If no registration data is supplied or if this plugin is configured as non-knowledge
// type plugin then reset is simply a forget operation else the registration data is
// used to retrain the plugin
if ((aRegistrationData == KNullDesC) || (Id() == 0x11113101) || (Type() == EAuthBiometric) || (Type() == EAuthToken))
{
aResult = NULL;
TRAPD(err, FindStringAndRemoveL(aId));
return err;
}
// For EAuthKnowledge type
// Convert the 16-bit string to a 8-bit string (pin)
// Note that no unicode conversion is being done here since a pin cannot be in unicode
RBuf8 pinBuf;
TBuf8<32> newPin;
TRAPD(err, pinBuf.CreateL(32);\
CleanupClosePushL(pinBuf);\
pinBuf.Copy(aRegistrationData.Left(32));\
newPin = pinBuf;\
CleanupStack::PopAndDestroy(&pinBuf));
if (err != KErrNone)
{
return err;
}
// Log a message
TBuf8<32> userInput;
_LIT(KMsgDebug3, "Reset with registration data = %S");
RDebug::Print(KMsgDebug3, &aRegistrationData);
// Compare with the present set of inputs and see if this is one of them.
// update this list with this new user input, tagged to the aId
TRequestStatus request = KRequestPending;
TRAP(err, CheckForNewStringPresenceL(aId, newPin, request));
if( KErrNoMemory == err)
{
User::LeaveNoMemory();
}
if (err != KErrNone)
{
RDebug::Print(_L("Reset error = %d"), err);
return err;
}
else if (request.Int() == KErrNone)
{
// No errors, update aResult.
TRAP(err, aResult = HBufC8::NewL(newPin.Size()));
if (err != KErrNone)
{
return err;
}
*aResult = newPin;
}
else
{
_LIT(KMsgDebug5, "Error occurred during reset. request.Int() = %d");
RDebug::Print(KMsgDebug5, request.Int());
return request.Int();
}
return KErrNone;
}
//--------------------------------------------------------------------------------
/**
Utility method to capture the data that the user has input
(in the form of data stored in a file)
*/
TInt CTPinAuthPlugin::IdReadUserInput(TBuf8<32>& aInputValue)
{
TInt retValue;
CIniData* file=NULL;
TRAPD(r,file=CIniData::NewL(iFileToRead));
if(r!=KErrNone)
{
RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
retValue = r;
}
else
{
// Look for a key under a named section, retrieve text value
TPtrC result;
TBool ret=EFalse; //return value from FindVar functions
ret=file->FindVar(_L("SectionOne"),_L("IdEnteredPinValue"),result);
if(!ret)
{
RDebug::Print(_L("Unable to find the key in the file %S. IdEnteredPinValue is not known, 9999 used. Error = %d"), &iFileToRead, ret);
_LIT8(KEnteredPinValueErr, "9999");
aInputValue = KEnteredPinValueErr; // Default value
retValue = KErrNotFound;
}
else
{
//Later,include a check to ensure that only digits were entered
aInputValue.Copy(result);
aInputValue.Trim();
retValue = KErrNone; //Not necessary
}
delete file; //memory cleanup
}
return retValue;
}
TInt CTPinAuthPlugin::TrainReadUserInput(TBuf8<32>& aInputValue)
{
TInt retValue;
CIniData* file=NULL;
TRAPD(r,file=CIniData::NewL(iFileToRead));
if(r!=KErrNone)
{
RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
retValue = r;
}
else
{
// Look for a key under a named section, retrieve text value
TPtrC result;
TBool ret=EFalse; //return value from FindVar functions
ret=file->FindVar(_L("SectionOne"),_L("TrainEnteredPinValue"),result);
if(!ret)
{
RDebug::Print(_L("Unable to find the key in the file %S. TrainEnteredPinValue is not known, 9999 used. Error = %d"), &iFileToRead, ret);
_LIT8(KEnteredPinValueErr, "9999");
aInputValue = KEnteredPinValueErr; // Default value
retValue = KErrNotFound;
}
else
{
aInputValue.Copy(result);
aInputValue.Trim();
retValue = KErrNone; //Not necessary
}
delete file; //memory cleanup
}
return retValue;
}
/**
Utility method to compare the data that the user has input
with all the data that has been stored for users
Called by Identify()
@return - success or failure value
*/
TInt CTPinAuthPlugin::CheckForStringPresence(TIdentityId& aId, TBuf8<32> aInputValue, TRequestStatus& aRequestValue)
{
TInt retValue = KErrNone;
// First format the aInputValue string so that it starts with a ':' and ends with a ','.
_LIT8(KFormatValue2, ":%S,");
TBuf8<32> aInputValue2;
aInputValue2.Format(KFormatValue2, &aInputValue);
//Convert the 8-bit string to a 16-bit string for printing in RDebug
HBufC* buf = 0;
buf = HBufC::New(32);
buf->Des().Copy(aInputValue);
RDebug::Print(_L("Formatted string: %S"), buf);
delete buf; //Memory cleanup. This string was only needed for the above Print function
TBuf8<500> pinFileContents1, pinFileContents2;
// Read the contents of the file that contains all the ID/PIN combinations
CIniData* file=NULL;
TRAPD(r,file=CIniData::NewL(iFileToRead));
if(KErrNoMemory == r)
{
delete file;
RDebug::Print(_L("Unable to create CIniData object - No memory !! "));
User::LeaveNoMemory();
}
if(r!=KErrNone)
{
RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
retValue = r;
}
else
{
// Look for a key under a named section, retrieve text value
TPtrC result;
TBool ret=EFalse; //return value from FindVar functions
ret=file->FindVar(_L("SectionOne"),_L("Identity&PinValues"),result);
if(!ret)
{
RDebug::Print(_L("Unable to find the Identity&PinValues key in the file %S."), &iFileToRead);
retValue = KErrNotFound;
aRequestValue =KErrNotFound;
}
else
{
pinFileContents1.Copy(result);
TInt searchResult;
searchResult = pinFileContents1.Find(aInputValue2);
if (KErrNotFound == searchResult)
{
RDebug::Print(_L("Userinput not found in the pinFile %S. Identification error"), &iFileToRead);
aRequestValue= KErrAuthServIdentityNotFound;
retValue = searchResult;
}
else if (searchResult) // a positive value
{
// Now find the userID by searching back through the string for the "," marker
pinFileContents2 = pinFileContents1.Left(searchResult);
TInt userIdStartPos = pinFileContents2.LocateReverse(',');
//Extract this userId for use by the calling function
TBuf8<50> p1 = pinFileContents2.Right(searchResult - userIdStartPos - 1);
TLex8 input (p1);
TRadix aRadix = EDecimal;
input.Val(aId, aRadix);
RDebug::Print(_L("UserId that is stored = %u"), aId);
aRequestValue = KErrNone;
retValue = KErrNone;
}
else
{
RDebug::Print(_L("Unexpected error in the 'Find' function. Searchresult = %d"), searchResult);
aRequestValue = searchResult;
retValue = searchResult;
}//End check for key§ion search in file
}//End check for safe file access
delete file;
}
return retValue;
}
/**
Utility method to compare the data that the user has input
with all the data that has been stored for users
Used to find out if the input is unique.
-since KIdAmbiguous is no longer used, KIdCancel will be returned if the input is non-unique
Called by Train() and DefaultData()
*/
TInt CTPinAuthPlugin::CheckForNewStringPresenceL(TIdentityId aId, TBuf8<32> aInputValue, TRequestStatus& aRequestValue)
{
TBuf8<500> pinFileContents, pinFileContents2;
TInt retValue = KErrNone;
CIniData* file=NULL;
TRAPD(r,file=CIniData::NewL(iFileToRead));
if(KErrNoMemory == r)
{
User::LeaveNoMemory();
}
if(r!=KErrNone)
{
RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
return r;
}
// Look for a key under a named section, retrieve text value
TPtrC result;
TBool ret=EFalse; //return value from FindVar functions
aRequestValue = KErrAuthServIdentityNotFound; //Initialisation
ret=file->FindVar(KPluginIniSection, KPinDbTag,result);
if(!ret)
{
RDebug::Print(_L("Unable to find the %S key in the file %S."), &KPinDbTag, &iFileToRead);
delete file;
return KErrNotFound;
}
//Copy the data from the named section in the file, and see if any previous user has used this input string
pinFileContents.Copy(result);
TInt searchResultPin;
TBuf8<50> searchStringPin;
_LIT8(KFormat3, ":%S,");
searchStringPin.Format(KFormat3, &aInputValue);
searchResultPin = pinFileContents.Find(searchStringPin);
if (KErrNotFound == searchResultPin)
{
//check that the identity is unique, if so, update the Db
// with the new Id-PIN pair, as is done already
// else update the PIN only, ie training data for that identity
TInt searchResultId;
TBuf8<50> searchStringId;
_LIT8(KFormat4, ",%u:");
searchStringId.Format(KFormat4, aId);
searchResultId = pinFileContents.Find(searchStringId);
TDriveUnit sysDrive (RFs::GetSystemDrive());
TBuf<80> policyFile;
if (KErrNotFound == searchResultId)
{
// Add this entry to the file
// This is a simple system, expecting a format as below:
// ",aId:inputPin,aId:inputPin,aId:inputPin,"
_LIT8(KFormat2, "%S%u:%S,");
if (pinFileContents.Size() == 0)
{
pinFileContents.Append(','); //Initialisation
}
pinFileContents2.Format(KFormat2, &pinFileContents, aId, &aInputValue);
//For the purpose of writing the data to a file, i'll create a 16-bit version of pinFileContents
TInt ret2 = 0;
HBufC* buf = 0;
TRAPD(err,buf = HBufC::NewL(pinFileContents2.Length()));
if(err == KErrNoMemory)
{
delete file;
User::LeaveNoMemory();
}
buf->Des().Copy(pinFileContents2);
ret2 = file->SetValue(_L("SectionOne"),_L("Identity&PinValues"), *buf);
TRAPD(r,file->WriteToFileL());
if (KErrNone != r)
{
policyFile.Copy(sysDrive.Name());
policyFile.Append(KPolicyFile);
RDebug::Print(_L("Error occurred while writing to the file. Filename = %S, KeyName = AllUserID&PinValues, value = %S."), &policyFile, buf);
}
delete buf; //Memory cleanup. This string was only needed for the above Print function
if(KErrNone == ret2)
{
aRequestValue = KErrNone;
//Update the global database
AddToGlobalDb(aId, aInputValue);
}
else
{
RDebug::Print(_L("Error occurred while writing data to file. Error = %d"), ret2);
aRequestValue = ret2;
}
}
else
{
//The Identity has already been trained with this plugin,
// update the PIN (training data)
//extract the string to the right of the end of the aId
pinFileContents2 = pinFileContents.Mid(searchResultId + searchStringId.Size());
//Find the end of the PIN (Training data)
_LIT8(KPinEndMarker, ",");
TBufC8<5> bufPinEndMarker(KPinEndMarker);
TInt pinEndPos = pinFileContents2.Find(bufPinEndMarker);
//Replace this with the new PIN
pinFileContents.Replace((searchResultId + searchStringId.Size()),
pinEndPos, aInputValue);
//For the purpose of writing the data to a file, i'll create a 16-bit version of pinFileContents
TInt ret2 = 0;
HBufC* buf = 0;
TRAPD(err1,buf = HBufC::NewL(pinFileContents.Length()));
if(err1 == KErrNoMemory)
{
delete file;
User::LeaveNoMemory();
}
buf->Des().Copy(pinFileContents);
ret2 = file->SetValue(_L("SectionOne"),_L("Identity&PinValues"), *buf);
TRAPD(r,file->WriteToFileL());
if (KErrNone != r)
{
policyFile.Copy(sysDrive.Name());
policyFile.Append(KPolicyFile);
RDebug::Print(_L("Error occurred while writing to the file. Filename = %S, KeyName = AllUserID&PinValues, value = %S."), &policyFile, buf);
}
delete buf; //Memory cleanup. This string was only needed for the above Print function
if(KErrNone ==ret2)
{
aRequestValue = KErrNone;
//Update the global database
AddToGlobalDb(aId, aInputValue);
}
else
{
RDebug::Print(_L("Error occurred while writing data to file. Error = %d"), ret2);
aRequestValue = ret2;
}
}
delete file;
return ret;
}
if (searchResultPin) // a positive value
{
// A user has already tried to train this plugin using the given data.
// The pinFileContents are not updated, to avoid duplication
aRequestValue = KErrAuthServPluginCancelled;
delete file;
return searchResultPin;
}
RDebug::Print(_L("Unexpected error in the 'Find' function. SearchresultPin = %d"), searchResultPin);
retValue = searchResultPin;
delete file;
return retValue;
}
/**
Utility function to remove the training data that is associated with a given Id
Called by the Forget function
@return - KIdSuccess, KIdUnknown or some error code
*/
TInt CTPinAuthPlugin::FindStringAndRemoveL (TIdentityId aId)
{
TBuf8<500> pinFileContents, pinFileContents2;
TInt retValue = KErrAuthServNoSuchIdentity; //init
CIniData* file=NULL;
//First read the list of userId and PIN combinations from a file
TRAPD(r,file=CIniData::NewL(iFileToRead));
if(r!=KErrNone)
{
RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &iFileToRead);
retValue = r;
}
else
{
// Look for a key under a named section, retrieve text value
TPtrC result;
TBool ret=EFalse; //return value from FindVar functions
ret=file->FindVar(KPluginIniSection, KPinDbTag,result);
if(!ret)
{
RDebug::Print(_L("Config error: Unable to find the %S key in the file %S."), &KPinDbTag, &iFileToRead);
retValue = KErrNotFound;
}
else
{
//Copy the data from the named section in the file, and see if any previous user has used this input string
pinFileContents.Copy(result);
//Format the searchstring as defined in the file so that it starts with a ',' and ends with a ':'.
_LIT8(KFormatValue3, ",%u:");
TBuf8<32> searchString;
searchString.Format(KFormatValue3, aId);
//For the purpose of printing the data to a file, i'll create a 16-bit version of pinFileContents
HBufC* buf = 0;
buf = HBufC::NewL(searchString.Length());
buf->Des().Copy(searchString);
RDebug::Print(_L("Formatted searchString used in 'FindStringAndRemove(): %S"), buf);
delete buf;
TInt userIdStartPos; //The offset of the searchString within pinFileContents
//i.e the position of the '.' just before the identityId
userIdStartPos = pinFileContents.Find(searchString);
if (KErrNotFound == userIdStartPos)
{
RDebug::Print(_L("FindStringAndRemoveL: The specified ID was not found in the pinFile"));
retValue = KErrAuthServNoSuchIdentity; //KIdUnknown;
}
else
{
//Find where the string (including PIN) ends
TLex8 aLex = TLex8(pinFileContents);
TInt length(0);
aLex.Inc(userIdStartPos+1);
while(aLex.Peek() != ',')
{
aLex.Inc();
length++;
}
//remove the found (total) string from the list (including the starting ',')
pinFileContents.Delete(userIdStartPos,length+1);
//Update the file
//For the purpose of writing the data to a file, i'll create a 16-bit version of pinFileContents
TInt ret2 = 0;
HBufC* buf;
buf = HBufC::NewL(pinFileContents.Length());
buf->Des().Copy(pinFileContents);
ret2 = file->SetValue(KPluginIniSection, KPinDbTag, *buf);
TRAPD(r,file->WriteToFileL());
TDriveUnit sysDrive (RFs::GetSystemDrive());
TBuf<2> sysDriveName (sysDrive.Name());
TBuf<84> policyFile;
if (KErrNone != r)
{
policyFile.Copy(sysDriveName);
policyFile.Append(KPolicyFile);
RDebug::Print(_L("Error occurred while writing to the file. Filename = %S, KeyName = AllUserID&PinValues, value = %S."), &policyFile, buf);
}
delete buf; //Memory cleanup. This string was only needed for the above Print function
if (KErrNone !=ret2)
{
policyFile .Copy(sysDriveName);
policyFile.Append(KAuthSvrPolicyFile);
RDebug::Print(_L("Error occurred in WriteToFileL(). Error = %d. Filename= %S"), ret2, &policyFile);
retValue = ret2;
}
else
{
retValue = KErrNone;
}
}
}//End check for key§ion search in file
delete file;
}//End check for safe file access
return retValue;
}
/**
Utility function to Update the Global Db with the training data
that is associated with a given Id. The update will not happen if
the identity is already present in this list, i.e. it's been pu in
by another plugin
Called by the CheckForNewStringPresence function
@return - KErrNone, or some error code
*/
TInt CTPinAuthPlugin::AddToGlobalDb (TIdentityId aId, TBuf8<32> aInputValue)
{
TBuf8<500> totalDbFileContents, totalDbFileContents2;
TInt retValue = KErrNone;
CIniData* file=NULL;
TDriveUnit sysDrive (RFs::GetSystemDrive());
TDriveName sysDriveName (sysDrive.Name());
TBuf<128> authSvrPolicyFile(sysDriveName);
authSvrPolicyFile.Append(KAuthSvrPolicyFile);
TRAPD(r,file=CIniData::NewL(authSvrPolicyFile));
if(r!=KErrNone)
{
RDebug::Print(_L("Unable to create CIniData object. Error = %d, File = %S"), r, &authSvrPolicyFile);
retValue = r;
}
else
{
// Look for a key under a named section, retrieve text value
TPtrC result;
TBool ret=EFalse; //return value from FindVar functions
ret=file->FindVar(KPluginIniSection, KTotalDbTag,result);
if(!ret)
{
RDebug::Print(_L("Unable to find the %S key in the file %S."), &KTotalDbTag, &authSvrPolicyFile);
retValue = KErrNotFound;
}
else
{
//Copy the data from the named section in the file, and see if any previous user has used this input string
totalDbFileContents.Copy(result);
TBuf8<20> aidString;
aidString.Num(aId, EDecimal);
TInt searchResult;
searchResult = totalDbFileContents.Find(aidString);
if (KErrNotFound == searchResult)
{
// Add this entry to the file
// This is a simple system, expecting a format as below:
// ",aId:inputPin,aId:inputPin,aId:inputPin,"
_LIT8(KFormat2, "%S%u:%S,");
if (totalDbFileContents.Size() == 0)
{
totalDbFileContents.Append(','); //Initialisation
}
totalDbFileContents2.Format(KFormat2, &totalDbFileContents, aId, &aInputValue);
//For the purpose of writing the data to a file, i'll create a 16-bit version of pinFileContents
TInt ret2 = 0;
HBufC* buf = 0;
TRAPD(err,buf = HBufC::NewL(totalDbFileContents2.Length()));
if(err == KErrNoMemory)
{
delete file;
return KErrNoMemory;
}
buf->Des().Copy(totalDbFileContents2);
ret2 = file->SetValue(KPluginIniSection, KTotalDbTag, *buf);
TRAPD(r,file->WriteToFileL());
if (KErrNone != r)
{
TBuf<80> policyFile(sysDriveName);
policyFile.Append(KPolicyFile);
RDebug::Print(_L("Error occurred while writing to the file. Filename = %S, KeyName = AllUserID&PinValues, value = %S."), &policyFile, buf);
}
delete buf; //Memory cleanup. This string was only needed for the above Print function
if (KErrNone !=ret2)
{
RDebug::Print(_L("Error occurred in SetValue(). Error = %d. Filename= %S"), ret2, &authSvrPolicyFile);
retValue = ret2;
}
}
else
{
// A user has already tried to train this plugin using the given data.
// The pinFileContents are not updated, to avoid duplication
retValue = KErrNone;
}//End aidString search in the totalDbFileContents string (Find())
}//End check for key§ion search in file (FindVar())
delete file;
}//End check for safe file access
return retValue;
}
const HBufC* CTPinAuthPlugin::ClientMessage()
{
return iClientMessage;
}
const TPtrC& CTPinAuthPlugin::Name() const
{
return iName;
}
const TPtrC& CTPinAuthPlugin::Description() const
{
return iDescription;
}
AuthServer::TAuthPluginType CTPinAuthPlugin::Type() const
{
return iType;
}
AuthServer::TEntropy CTPinAuthPlugin::MinEntropy() const
{
return iMinEntropy;
}
AuthServer::TPercentage CTPinAuthPlugin::FalsePositiveRate() const
{
return iFalsePositiveRate;
}
AuthServer::TPercentage CTPinAuthPlugin::FalseNegativeRate() const
{
return iFalseNegativeRate;
}