pkiutilities/DeviceToken/Src/TruSitesStore/Server/TrustedSitesServer.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 26 Jan 2010 15:20:08 +0200
changeset 0 164170e6151a
permissions -rw-r--r--
Revision: 201004

/*
* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "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:   Implementation of TrustedSitesStoreServer
*
*/



#include "TrustedSitesServer.h"
#include "TrustedSitesConduit.h"
#include "TrustedSitesSession.h"
#include "DevTokenCliServ.h"
#include "DevTokenUtil.h"
#include "DevTokenDataTypes.h"
#include "DevTokenServer.h"
#include "DevandTruSrvCertStoreServer.h"
#include <x509cert.h>
#include <ccertattributefilter.h>
#include <e32cmn.h>
#include <badesca.h>

_LIT(KTrustedSitesStoreFilename,"TrustedSitesStore.dat");
// Maximum length of SQL query clause
const TInt KMaxSQLLength = 256;

// API policing
_LIT_SECURITY_POLICY_C1(KReadSecurityPolicy, ECapabilityReadUserData);
_LIT_SECURITY_POLICY_C1(KWriteSecurityPolicy, ECapabilityWriteDeviceData);

// ======== MEMBER FUNCTIONS ========

//CTrustedSitesServer

// ---------------------------------------------------------------------------
// CTrustedSitesServer::NewL()
// ---------------------------------------------------------------------------
//
CTrustedSitesServer* CTrustedSitesServer::NewL( CDevTokenServer* aServer )
    {
    CTrustedSitesServer* self = new (ELeave) CTrustedSitesServer( aServer );
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::CTrustedSitesServer()
// ---------------------------------------------------------------------------
//
CTrustedSitesServer::CTrustedSitesServer( CDevTokenServer* aServer ) :
    iServer ( aServer )
    {
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::ConstructL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::ConstructL()
    {
    iConduit = CTrustedSitesConduit::NewL(*this);

    User::LeaveIfError( iFs.Connect() );

    TBuf<KMaxFilenameLength> filename;

    FileUtils::MakePrivateFilenameL(iFs, KTrustedSitesStoreFilename, filename);

    TInt err = iDatabase.Open( iFs, filename );

    if ( err != KErrNone ) 
        {
        CreateDBL(); // Create DB
        User::LeaveIfError( iDatabase.Open( iFs, filename ) );
        }
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::CreateDBL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::CreateDBL()
    {

    RFs fsSession;
    User::LeaveIfError( fsSession.Connect() ); // Connect to file server

    CleanupClosePushL( fsSession );

    RDbNamedDatabase database;

    TBuf<KMaxFilenameLength> filename;

    FileUtils::MakePrivateFilenameL(fsSession, KTrustedSitesStoreFilename, filename);

    FileUtils::EnsurePathL(fsSession, filename);
    CleanupClosePushL( database );

    User::LeaveIfError( database.Create( fsSession, filename ) );

    // Create tables

    // Trusted sites table
    _LIT( KSQLCreateTable1, "CREATE TABLE Certificates (\
    CertID COUNTER NOT NULL,\
    CertHash CHAR(20) NOT NULL)");

    _LIT( KSQLCreateTable2, "CREATE TABLE TrustedSites (\
    CertID INTEGER,\
    SiteName VARCHAR(100) NOT NULL,\
    Forgiven INTEGER NOT NULL,\
    OutOfDate INTEGER NOT NULL,\
    ClientUID INTEGER NOT NULL )");                                      
    
    User::LeaveIfError( database.Execute( KSQLCreateTable1 ) );
    User::LeaveIfError( database.Execute( KSQLCreateTable2 ) );

    CleanupStack::PopAndDestroy( 2 ); // database, fsSession
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::~CTrustedSitesServer()
// ---------------------------------------------------------------------------
//
CTrustedSitesServer::~CTrustedSitesServer()
    {
    delete iConduit;
    iDatabase.Close();  // Close database
    iFs.Close();
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::CreateSessionL()
// ---------------------------------------------------------------------------
//
CTrustedSitesSession* CTrustedSitesServer::CreateSessionL()
    {
    return CTrustedSitesSession::NewL(*iConduit);
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::AddL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::AddL(const TDesC8& aCertHash, const TDesC& aSiteName, const RMessage2& aMessage )
    {
    // API policing
    if (!KWriteSecurityPolicy.CheckPolicy(aMessage))
        {
        User::Leave(KErrPermissionDenied);
        }

    TInt certID;
    GetCertIDL( aCertHash, certID ); // Get certificate ID

    if ( certID == KErrNotFound ) // Not found
        {
        iDatabase.Begin(); // Begin transaction

        TRAPD( err, DoAddCertL( aCertHash ));

        if ( err ) // Some error occurred
            {
            iDatabase.Rollback(); // Rollback changes
            User::Leave ( err );
            }
        else
            {
            iDatabase.Commit(); // Commit changes
            }

        GetCertIDL( aCertHash, certID );

        if( certID == KErrNotFound )
            {
            User::Leave( KErrNotFound );
            }

        iDatabase.Begin();

        TRAP( err, DoAddSiteNameL( certID, aSiteName ));

        if ( err ) // Some error occurred
            {
            iDatabase.Rollback(); // Rollback changes
            User::Leave ( err );
            }
        else
            {
            iDatabase.Commit(); // Commit changes
            }    
        }
    else
        {
        if(IsSiteAlreadyExistL( certID, aSiteName ))
            {
            return; 
            }
        else
            {
            iDatabase.Begin(); // Begin transaction

            TRAPD( err, DoAddSiteNameL( certID, aSiteName ));

            if ( err ) // Some error occurred
                {
                iDatabase.Rollback(); // Rollback changes
                User::Leave ( err );
                }
            else
                {
                iDatabase.Commit(); // Commit changes
                }
            return;   
            } 
        }  

    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::AddL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::AddL(const TDesC8& aCertHash, const TDesC& aSiteName )
    {
    TInt certID;
    GetCertIDL( aCertHash, certID ); // Get certificate ID

    if ( certID == KErrNotFound ) // Not found
        {
        iDatabase.Begin(); // Begin transaction

        TRAPD( err, DoAddCertL( aCertHash ));

        if ( err ) // Some error occurred
            {
            iDatabase.Rollback(); // Rollback changes
            User::Leave ( err );
            }
        else
            {
            iDatabase.Commit(); // Commit changes
            }

        GetCertIDL( aCertHash, certID );

        if( certID == KErrNotFound )
            {
            User::Leave( KErrNotFound );
            }

        iDatabase.Begin();

        TRAP( err, DoAddSiteNameL( certID, aSiteName ));

        if ( err ) // Some error occurred
            {
            iDatabase.Rollback(); // Rollback changes
            User::Leave ( err );
            }
        else
            {
            iDatabase.Commit(); // Commit changes
            }    
        }
    else
        {
        if(IsSiteAlreadyExistL( certID, aSiteName ))
            {
            return; 
            }
        else
            {
            iDatabase.Begin(); // Begin transaction

            TRAPD( err, DoAddSiteNameL( certID, aSiteName ));

            if ( err ) // Some error occurred
                {
                iDatabase.Rollback(); // Rollback changes
                User::Leave ( err );
                }
            else
                {
                iDatabase.Commit(); // Commit changes
                }
            return;   
            } 
        }  
    }
    
    
// ---------------------------------------------------------------------------    
// CTrustedSitesServer::GetCertIDL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::GetCertIDL( const TDesC8& aCertHash, TInt& aCertID )
    {   
    _LIT( KSQLQuery, "SELECT CertID,\
    CertHash\
    FROM Certificates" );

    RDbView view;

    User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( KSQLQuery ) ) );

    CleanupClosePushL( view );

    // Get data
    TInt i = 0;

    while ( i == 0 && view.NextL() ) // Should find only one ID
        {
        view.GetL();

        if ( !view.ColDes8( 2 ).Compare( aCertHash ) )
            {
            aCertID = view.ColUint32( 1 );
            i++;
            }
        }

    if ( i == 0 ) // Not found any matching rows
        {
        aCertID = KErrNotFound;
        }

    CleanupStack::PopAndDestroy( 1 ); // view
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::DoAddSiteNameL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::DoAddSiteNameL(const TInt& aCertID, const TDesC& aSiteName )   
    {
    //insert the normal trusted site record,not for forgiven site
    TBuf<KMaxSQLLength> SQL;

    _LIT( KSQLInsert1,
    "INSERT INTO TrustedSites (CertID,SiteName,Forgiven,OutOfDate,ClientUID) VALUES (" );

    SQL.Copy(KSQLInsert1);
    SQL.AppendNum(aCertID);
    SQL.Append(_L(",'"));
    
    SQL.Append( aSiteName );
    SQL.Append(_L("',"));
    //not forgiven
    SQL.AppendNum(0);
    SQL.Append(_L(","));
    //not allowed out of date
    SQL.AppendNum(0); 
    //set the UID to -1 since in the normal case we don't need the information
    SQL.Append(_L(","));
    SQL.AppendNum(-1);
    SQL.Append(_L(")"));
    
    User::LeaveIfError( iDatabase.Execute( SQL ) );
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::DoAddCertL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::DoAddCertL( const TDesC8& aCertHash )
    {   
    RDbView view;

    _LIT( KSQLInsertCert, "SELECT CertHash\
    FROM Certificates" );

    User::LeaveIfError( view.Prepare( iDatabase, TDbQuery( KSQLInsertCert ),
    TDbWindow::EUnlimited, RDbView::EInsertOnly ) );

    CleanupClosePushL( view );

    view.InsertL();
    view.SetColL( 1, aCertHash );
    view.PutL();

    CleanupStack::PopAndDestroy( 1 ); 
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::IsSiteAlreadyExistL()
// ---------------------------------------------------------------------------
//
TBool CTrustedSitesServer::IsSiteAlreadyExistL(const TInt& aCertID, const TDesC& aSiteName)
    {
    RDbView view;   
    _LIT( KSQLQuery, 
    "SELECT SiteName FROM TrustedSites WHERE certID = " );

    TBuf<KMaxSQLLength> SQLStatement;
    SQLStatement.Copy( KSQLQuery );

    SQLStatement.AppendNum( aCertID );

    TPtrC sqlStat( SQLStatement.PtrZ() );

    TInt err = view.Prepare( iDatabase, TDbQuery( sqlStat ), TDbWindow::EUnlimited );

    if ( err != KErrNone )
        {
        User::Leave( KErrArgument );
        }

    err = view.EvaluateAll();

    CleanupClosePushL( view );

    TBool alreadyExist = EFalse;
    // Get data
    while ( view.NextL() ) // Should find only one certificate
        {
        TRAPD(error, view.GetL());
        error = error;
        if(!aSiteName.Compare(view.ColDes( 1 )))
            {
            alreadyExist = ETrue;
            break;
            }
        }
    CleanupStack::PopAndDestroy( 1 ); 
    return alreadyExist;
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::IsOutOfDateAllowedForTheSiteL()
// ---------------------------------------------------------------------------
//
TBool CTrustedSitesServer::IsOutOfDateAllowedForTheSiteL( const TInt& aCertID, const TDesC& aSiteName )
    {
    RDbView view;   
    _LIT( KSQLQuery, 
    "SELECT SiteName,OutOfDate FROM TrustedSites WHERE certID = " );

    TBuf<KMaxSQLLength> SQLStatement;
    SQLStatement.Copy( KSQLQuery );

    SQLStatement.AppendNum( aCertID );

    TPtrC sqlStat( SQLStatement.PtrZ() );

    TInt err = view.Prepare( iDatabase, TDbQuery( sqlStat ), TDbWindow::EUnlimited );

    if ( err != KErrNone )
        {
        User::Leave( KErrArgument );
        }

    err = view.EvaluateAll();

    CleanupClosePushL( view );

    TBool outofdate = EFalse;
    // Get data
    while ( view.NextL() ) // Should find only one certificate
        {
        TRAPD(error, view.GetL());
        error = error;
        
        if ( (!aSiteName.Compare( view.ColDes( 1 ) ) ) && ( view.ColInt( 2 ) == 1 ) )
            {
            outofdate = ETrue;
            break;
            }
        }
        
    CleanupStack::PopAndDestroy( 1 ); //view
    return outofdate; 
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::IsTrustedSiteL()
// ---------------------------------------------------------------------------
//
TBool CTrustedSitesServer::IsTrustedSiteL( const TDesC8& aCertHash, const TDesC& aSiteName, const TDesC8& aCert, const RMessage2& aMessage )
    {
    // API policing
    if (!KReadSecurityPolicy.CheckPolicy(aMessage))
        {
        User::Leave(KErrPermissionDenied);
        }
    
    //is it a forgiven site 
    if ( IsForgivenSiteAlreadyL( aSiteName ) )
        {
        // Insert the certificate into database
        DoOverWriteCertL( aSiteName, aCertHash );
        
        //check if the certificate is already existing
        CCertAttributeFilter* filter = CCertAttributeFilter::NewL();
        CleanupStack::PushL(filter);
        filter->SetOwnerType(EPeerCertificate);
        RPointerArray<CDevTokenCertInfo> certs;
        RMessage2 message;             
        iServer->CertStoreServerL().ListL( *filter,certs,message, ETrue  );            
      
        CleanupStack::PopAndDestroy(); //filter
      
        TBool exist = EFalse;
        if ( certs.Count() )
            {
            for (TInt i= 0; i<certs.Count();i++)
                {
                HBufC8* certData = iServer->CertStoreServerL().RetrieveLC( certs[i]->CertificateId(),message,ETrue );
                TPtr8 certPtr = certData->Des();
                
                //certificate from trusted server certstore
                CX509Certificate* cert = CX509Certificate::NewLC( certPtr );
                //certificate from client
                CX509Certificate* cert2 = CX509Certificate::NewLC( aCert );
              
                if ( cert->Fingerprint() == cert2->Fingerprint() )
                    {
                    exist = ETrue;
                    CleanupStack::PopAndDestroy(3); //cert, cert2, certData
                    break;
                    }
              
                CleanupStack::PopAndDestroy(3); //cert, cert2, certData
                }
            }
          
        if ( exist )
             {
             //server certificate has saved already, no need to save again
             return ETrue;  
             }

        TDevTokenAddCertDataStruct data;
        data.iLabel.Zero();
        data.iSubjectKeyId.Zero();
        
        CX509Certificate* cert = CX509Certificate::NewL(aCert);
        data.iSubjectKeyId.Copy( cert->KeyIdentifierL() );
        delete cert;
        
        data.iIssuerKeyId.Zero();   
        data.iLabel.Copy(aSiteName);   
        data.iFormat = EX509Certificate;
        data.iCertificateOwnerType = EPeerCertificate;
        
        iServer->CertStoreServerL().AddL( data, aCert, aMessage, ETrue ) ;
         
        return ETrue;
        }
    
    //It isn't a forgiven site, query in the normal way to check whether it is trusted by the user 
    TInt certID;
    GetCertIDL( aCertHash, certID ); // Get certificate ID

    if ( certID == KErrNotFound ) // Not found
        {
        return EFalse;
        }
    else
        {
        if(IsSiteAlreadyExistL( certID, aSiteName ))
            {
            return ETrue; 
            }
        else
            {
            return EFalse;    
            } 
        }  
    }



// ---------------------------------------------------------------------------
// CTrustedSitesServer::IsOutOfDateAllowedL()
// ---------------------------------------------------------------------------
//
TBool CTrustedSitesServer::IsOutOfDateAllowedL( const TDesC8& aCertHash, const TDesC& aSiteName, const RMessage2& aMessage )
    {
    // API policing
    if (!KReadSecurityPolicy.CheckPolicy(aMessage))
        {
        User::Leave(KErrPermissionDenied);
        }

    TInt certID;
    GetCertIDL( aCertHash, certID ); // Get certificate ID

    if ( certID == KErrNotFound ) // Not found
        {
        return EFalse;
        }
    else
        {
        if(IsOutOfDateAllowedForTheSiteL( certID, aSiteName ))
            {
            return ETrue; 
            }
        else
            {
            return EFalse;    
            } 
        }  
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::GetTrustedSitesL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::GetTrustedSitesL( const TDesC8& aCertHash, 
                                           RPointerArray<HBufC>& aListOfSites,
                                           const RMessage2& aMessage)
    {
    // API policing
    if (!KReadSecurityPolicy.CheckPolicy(aMessage))
        {
        User::Leave(KErrPermissionDenied);
        }

    TInt certID;
    GetCertIDL( aCertHash, certID );

    if( certID == KErrNotFound )
        {
        User::Leave( KErrNotFound );
        }
    DoGetTrustedSitesL( certID, aListOfSites );     
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::DoGetTrustedSitesL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::DoGetTrustedSitesL( const TInt& aCertID, 
                                              RPointerArray<HBufC>& aListOfSites)
    {
    RDbView view;   
    _LIT( KSQLQuery, 
    "SELECT SiteName FROM TrustedSites WHERE certID = " );

    TBuf<KMaxSQLLength> SQLStatement;
    SQLStatement.Copy( KSQLQuery );

    SQLStatement.AppendNum( aCertID );

    TPtrC sqlStat( SQLStatement.PtrZ() );

    TInt err = view.Prepare( iDatabase, TDbQuery( sqlStat ), TDbWindow::EUnlimited );

    if ( err != KErrNone )
        {
        User::Leave( KErrArgument );
        }

    err = view.EvaluateAll();

    CleanupClosePushL( view );

    // Get data
    while ( view.NextL() ) // Should find only one certificate
        {
        TRAPD(error, view.GetL());
        error = error;
        HBufC* temp = HBufC::NewL(KMaxSiteName);
        TPtr ptrTemp = temp->Des();
        ptrTemp.Copy(view.ColDes( 1 ));      
        aListOfSites.Append(temp);
        }
    CleanupStack::PopAndDestroy( 1 ); 
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::RemoveL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::RemoveL( const TDesC8& aCertHash )
    {  
    TInt certID;
    GetCertIDL( aCertHash, certID );

    if( certID == KErrNotFound )
        {
        User::Leave( KErrNotFound );
        }
    CCertAttributeFilter* filter = CCertAttributeFilter::NewL();
    CleanupStack::PushL(filter);
    filter->SetOwnerType(EPeerCertificate);
    RPointerArray<CDevTokenCertInfo> certs;
    RMessage2 message;             
    iServer->CertStoreServerL().ListL(*filter,certs,message, ETrue  );            
    
    CleanupStack::PopAndDestroy(); //filter
    
    TBool stillexist = EFalse;
    if ( certs.Count() )
        {
        for (TInt i= 0; i<certs.Count();i++)
            {
            HBufC8* certData = iServer->CertStoreServerL().RetrieveLC( certs[i]->CertificateId(),message,ETrue );

            TPtr8 certPtr = certData->Des();
        	
            CX509Certificate* cert = CX509Certificate::NewLC( certPtr );
            
            if ( cert->Fingerprint() == aCertHash )
                 {
                 stillexist = ETrue;
            	 CleanupStack::PopAndDestroy( 2 ); //certData, cert
                 break;
                 }

            CleanupStack::PopAndDestroy( 2 ); //certData, cert
            }
        }
        
    if ( stillexist )
        {
        //there are still same server certificate saved in cert store
        //with different label, doesn't delete information then
        return;	
        }
    iDatabase.Begin(); // Begin transaction

    TRAPD( err, DoRemoveL( certID ));

    if ( err ) // Some error occurred
        {
        iDatabase.Rollback(); // Rollback changes
        User::Leave ( err );
        }
    else
        {
        iDatabase.Commit(); // Commit changes
        } 
    }   


// ---------------------------------------------------------------------------
// CTrustedSitesServer::DoRemoveL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::DoRemoveL(const TInt& aCertID )
    {  
    _LIT( KSQLDelete1, "DELETE FROM Certificates WHERE CertID = " );
    _LIT( KSQLDelete2, "DELETE FROM TrustedSites WHERE CertID = " );

    TBuf<KMaxSQLLength> SQLStatement1;
    TBuf<KMaxSQLLength> SQLStatement2;

    SQLStatement1.Copy( KSQLDelete1 );
    SQLStatement1.AppendNum( aCertID );
    TPtrC sqlStat1( SQLStatement1.PtrZ() );

    SQLStatement2.Copy( KSQLDelete2 );
    SQLStatement2.AppendNum( aCertID );
    TPtrC sqlStat2( SQLStatement2.PtrZ() );

    User::LeaveIfError( iDatabase.Execute( sqlStat1) );
    User::LeaveIfError( iDatabase.Execute( sqlStat2 ) );
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::AddForgivenSiteL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::AddForgivenSiteL( const TDesC& aSite, const TBool& aOutOfDateAllowed, const RMessage2& aMessage )
    {
    // API policing,WriteDeviceData
    if (!KWriteSecurityPolicy.CheckPolicy(aMessage))
        {
        User::Leave(KErrPermissionDenied);
        }

    if ( IsForgivenSiteAlreadyL( aSite ) )
       {
       //the hostname is in table already.
       DoOverWriteOutOfDateL( aSite, aOutOfDateAllowed );
       return;  
       }
    else
       {
       iDatabase.Begin(); // Begin transaction

       TRAPD( err, DoAddForgivenSiteL( aSite, aOutOfDateAllowed, aMessage.SecureId().iId ));

       if ( err ) // Some error occurred
           {
           iDatabase.Rollback(); // Rollback changes
           User::Leave ( err );
           }
       else
           {
           iDatabase.Commit(); // Commit changes            
           }
       }    
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::RemoveAllForgivenSitesL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::RemoveAllForgivenSitesL( const RMessage2& aMessage )
	{
    // API policing,WriteDeviceData
    if (!KWriteSecurityPolicy.CheckPolicy(aMessage))
        {
        User::Leave(KErrPermissionDenied);
        }
    
    // get certid arrays for the ClientUID
    RDbView view;   
    _LIT( KSQLQuery, 
    "SELECT SiteName,CertID FROM TrustedSites WHERE ClientUID = " );

    TBuf<KMaxSQLLength> SQLStatement;
    SQLStatement.Copy( KSQLQuery );

    SQLStatement.AppendNum( aMessage.SecureId().iId );

    TPtrC sqlStat( SQLStatement.PtrZ() );

    TInt err = view.Prepare( iDatabase, TDbQuery( sqlStat ), TDbWindow::EUnlimited );

    if ( err != KErrNone )
        {
        User::Leave( KErrArgument );
        }

    err = view.EvaluateAll();

    CleanupClosePushL( view );
    
    RArray<TInt> certIDs;
    RArray<TInt> certIDs2;
    if ( view.CountL() )
    	{
        // Get data
        while ( view.NextL() ) // Should find only one certificate
            {
            TRAPD(error, view.GetL());
            error = error;
            certIDs.Append( view.ColInt( 2 ) );      
            }
        CleanupStack::PopAndDestroy( 1 ); //view
    	}
    else
    	{
    	CleanupStack::PopAndDestroy( 1 ); //view
    	//no match found, nothing to delete 
    	return;
    	}
    
    if ( certIDs.Count() == 0 )
    	{
    	//no cert id, just return;
    	return;
    	}
    
    //the certID may contain -1, then no need to delete the certificate but go to delete the site directly
    //filter the -1 out.
    for ( TInt i = 0; i < certIDs.Count() ; i++ )
    	{
    	if ( certIDs[i] != -1 )
    		{
    		certIDs2.Append( certIDs[i] );
    		}
    	}
    
    // if certid2 is not empty, it means there are certificates associated with the sitename,
    // we should delete it.
    if ( certIDs2.Count() > 0 )
    	{
    	// get the certhash array for certid arrays
        //the desc8 array to put the certhash
        TInt num = certIDs2.Count();
        CDesC8ArrayFlat* descarray = new (ELeave) CDesC8ArrayFlat( num );
        CleanupStack::PushL( descarray );
        
        for ( TInt i = 0; i < certIDs2.Count(); i++ )
        	{
        	//empty the previous command
        	SQLStatement.Zero();
            _LIT( KSQLQuery, "SELECT CertHash FROM Certificates WHERE CertID =" );
            SQLStatement.Append( KSQLQuery );
            SQLStatement.AppendNum( certIDs2[i] );
            
           	TPtrC sqlStat1( SQLStatement.PtrZ() );
        	
            TInt err = view.Prepare( iDatabase, TDbQuery( sqlStat1 ), TDbWindow::EUnlimited );
         
            if ( err != KErrNone )
                {
                User::Leave( KErrArgument );
                }

            err = view.EvaluateAll();
            
            CleanupClosePushL( view );
           
            //put the hash into array
            while ( view.NextL() ) // Should find only one certificate
                {
                TRAPD(error, view.GetL());
                error = error;
                descarray->AppendL( view.ColDes8( 1 ) );      
                }
            CleanupStack::PopAndDestroy( 1 ); //view
        	}
        
        // List all of the certificate in trusted server certstore
        // retrive them one by one to compare the certhash.
        //if match found, remove the certificate from the trusted server certstore
        
        CCertAttributeFilter* filter = CCertAttributeFilter::NewL();
        CleanupStack::PushL(filter);
        filter->SetOwnerType(EPeerCertificate);
        RPointerArray<CDevTokenCertInfo> certs;
        RMessage2 message;             
        iServer->CertStoreServerL().ListL(*filter,certs,message, ETrue  );            
        
        CleanupStack::PopAndDestroy(); //filter
        
        if ( certs.Count() )
            {
            for ( TInt i= 0; i < certs.Count(); i++ )
                {
                HBufC8* certData = iServer->CertStoreServerL().RetrieveLC( certs[i]->CertificateId(),message,ETrue );

                TPtr8 certPtr = certData->Des();
            	
                CX509Certificate* cert = CX509Certificate::NewLC( certPtr );
                
                for ( TInt ii=0; ii < descarray->Count(); ii++ )
                	{
                	if ( (*descarray)[ii] == cert->Fingerprint() )
                		{
                           //match, then delete it 
                		iServer->CertStoreServerL().RemoveL( certs[i]->CertificateId(),message,ETrue );
                		break;
                		}
                	}
                
                CleanupStack::PopAndDestroy( 2 ); //certData, cert
                }
            }
        descarray->Reset(); //clean the buffer for certhash
        CleanupStack::PopAndDestroy(); //descarray
        
        //delete the cert record in Certificates Table
        for ( TInt i = 0; i < certIDs2.Count(); i++ )
        	{
        	_LIT( KSQLDelete1, "DELETE FROM Certificates WHERE CertID = " );
        	SQLStatement.Zero();

        	SQLStatement.Copy( KSQLDelete1 );
        	SQLStatement.AppendNum( certIDs2[i] );
        	TPtrC sqlStat2( SQLStatement.PtrZ() );
        	
        	User::LeaveIfError( iDatabase.Execute( sqlStat2 ) );
        	}
    	}
        
    //now corresponding certificates are deleted,  it is time to delete the sitenames
    // just delete all of the record where uid matched with the client uid
    
    _LIT( KSQLDelete2, "DELETE FROM TrustedSites WHERE ClientUID = " );

    SQLStatement.Zero();
    SQLStatement.Copy( KSQLDelete2 );
    SQLStatement.AppendNum( aMessage.SecureId().iId  );
    
    TPtrC sqlStat3( SQLStatement.PtrZ() );

    User::LeaveIfError( iDatabase.Execute( sqlStat3) );
	}



// ---------------------------------------------------------------------------
// CTrustedSitesServer::RemoveThisForgivenSiteL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::RemoveThisForgivenSiteL( const TDesC& aSite, const RMessage2& aMessage )
	{
    // API policing,WriteDeviceData
    if (!KWriteSecurityPolicy.CheckPolicy(aMessage))
    	{
        User::Leave(KErrPermissionDenied);
        }
    
    // get certid arrays for the ClientUID
    RDbView view;   
    _LIT( KSQLQuery, 
    "SELECT CertID FROM TrustedSites WHERE ClientUID = " );

    TBuf<KMaxSQLLength> SQLStatement;
    SQLStatement.Copy( KSQLQuery );

    SQLStatement.AppendNum( aMessage.SecureId().iId );
    SQLStatement.Append(_L(" AND SiteName = '") );
    SQLStatement.Append( aSite );
    SQLStatement.Append(_L("'"));
    
    
    TPtrC sqlStat( SQLStatement.PtrZ() );

    TInt err = view.Prepare( iDatabase, TDbQuery( sqlStat ), TDbWindow::EUnlimited );

    if ( err != KErrNone )
        {
        User::Leave( KErrArgument );
        }

    err = view.EvaluateAll();
    
    
    CleanupClosePushL( view );
    
    RArray<TInt> certIDs;
    RArray<TInt> certIDs2;
    if ( view.CountL() )
    	{
        // Get data
        while ( view.NextL() ) // Should find only one certificate
            {
            TRAPD(error, view.GetL());
            error = error;
            certIDs.Append( view.ColInt( 1 ) );      
            }
        CleanupStack::PopAndDestroy( 1 ); //view
    	}
    else
    	{
    	CleanupStack::PopAndDestroy( 1 ); //view
    	//no match found, nothing to delete 
    	return;
    	}
    
    if ( certIDs.Count() == 0 )
    	{
    	//no cert id, just return;
    	return;
    	}
    
    //the certID may contain -1, then no need to delete the certificate but go to delete the site directly
    //filter the -1 out.
    for ( TInt i = 0; i < certIDs.Count() ; i++ )
    	{
    	if ( certIDs[i] != -1 )
    		{
    		certIDs2.Append( certIDs[i] );
    		}
    	}
    // if certid2 is not empty, it means there are certificates associated with the sitename,
    // we should delete it.
    
    if ( certIDs2.Count() > 0 )
    	{
    	// get the certhash array for certid arrays
        //the desc8 array to put the certhash
        TInt num = certIDs2.Count();
        CDesC8ArrayFlat* descarray = new (ELeave) CDesC8ArrayFlat( num );
        CleanupStack::PushL( descarray );
        
        for ( TInt i = 0; i < certIDs2.Count(); i++ )
        	{
        	//empty the previous command
        	SQLStatement.Zero();
            _LIT( KSQLQuery, "SELECT CertHash FROM Certificates WHERE CertID =" );
            SQLStatement.Append( KSQLQuery );
            SQLStatement.AppendNum( certIDs2[i] );
            
           	TPtrC sqlStat1( SQLStatement.PtrZ() );
        	
            TInt err = view.Prepare( iDatabase, TDbQuery( sqlStat1 ), TDbWindow::EUnlimited );
         
            if ( err != KErrNone )
                {
                User::Leave( KErrArgument );
                }

            err = view.EvaluateAll();
            
            CleanupClosePushL( view );
           
            //put the hash into array
            while ( view.NextL() ) // Should find only one certificate
                {
                TRAPD(error, view.GetL());
                error = error;
                descarray->AppendL( view.ColDes8( 1 ) );      
                }
            CleanupStack::PopAndDestroy( 1 ); //view
        	}
        
        // List all of the certificate in trusted server certstore
        // retrive them one by one to compare the certhash.
        //if match found, remove the certificate from the trusted server certstore
        
        CCertAttributeFilter* filter = CCertAttributeFilter::NewL();
        CleanupStack::PushL(filter);
        filter->SetOwnerType(EPeerCertificate);
        RPointerArray<CDevTokenCertInfo> certs;
        RMessage2 message;             
        iServer->CertStoreServerL().ListL(*filter,certs,message, ETrue  );            
        
        CleanupStack::PopAndDestroy(); //filter
        
        if ( certs.Count() )
            {
            for ( TInt i= 0; i < certs.Count(); i++ )
                {
                HBufC8* certData = iServer->CertStoreServerL().RetrieveLC( certs[i]->CertificateId(),message,ETrue );

                TPtr8 certPtr = certData->Des();
            	
                CX509Certificate* cert = CX509Certificate::NewLC( certPtr );
                
                for ( TInt ii=0; ii < descarray->Count(); ii++ )
                	{
                	if ( (*descarray)[ii] == cert->Fingerprint() )
                		{
                           //match, then delete it 
                		iServer->CertStoreServerL().RemoveL( certs[i]->CertificateId(),message,ETrue );
                		break;
                		}
                	}
                
                CleanupStack::PopAndDestroy( 2 ); //certData, cert
                }
            }
        descarray->Reset(); //clean the buffer for certhash
        CleanupStack::PopAndDestroy(); //descarray
        
        //delete the cert record in Certificates Table
        for ( TInt i = 0; i < certIDs2.Count(); i++ )
        	{
        	_LIT( KSQLDelete1, "DELETE FROM Certificates WHERE CertID = " );
        	SQLStatement.Zero();

        	SQLStatement.Copy( KSQLDelete1 );
        	SQLStatement.AppendNum( certIDs2[i] );
        	TPtrC sqlStat2( SQLStatement.PtrZ() );
        	
        	User::LeaveIfError( iDatabase.Execute( sqlStat2 ) );
        	}
    	}
    //now corresponding certificates are deleted,  it is time to delete the sitenames
    // just delete all of the record where uid matched with the client uid
    
    _LIT( KSQLDelete2, "DELETE FROM TrustedSites WHERE ClientUID = " );

    SQLStatement.Zero();
    SQLStatement.Copy( KSQLDelete2 );
    SQLStatement.AppendNum( aMessage.SecureId().iId  );
    SQLStatement.Append(_L("AND SiteName = '"));
    SQLStatement.Append( aSite );
    SQLStatement.Append(_L("'"));
    
    TPtrC sqlStat3( SQLStatement.PtrZ() );
    
    //TInt errr = iDatabase.Execute( sqlStat3);
    User::LeaveIfError( iDatabase.Execute( sqlStat3) );
	}


// ---------------------------------------------------------------------------
// CTrustedSitesServer::DoAddForgivenSiteL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::DoAddForgivenSiteL(const TDesC& aSite, const TBool& aOutOfDateAllowed, const TUint32& aUID )
    {
    TBuf<KMaxSQLLength> SQLStatement;

    _LIT( KSQLInsert1,
    "INSERT INTO TrustedSites (CertID,SiteName,Forgiven,OutOfDate,ClientUID) VALUES (" );

    SQLStatement.Copy(KSQLInsert1);
    SQLStatement.AppendNum(-1);
    SQLStatement.Append(_L(",'"));
    
    SQLStatement.Append( aSite );
    SQLStatement.Append(_L("',"));
    SQLStatement.AppendNum(1);
    SQLStatement.Append(_L(","));
    //add record for forgiven sites, check if outofdate is allowed also
    if ( aOutOfDateAllowed )
        {
        SQLStatement.AppendNum(1);
        }
    else 
        {
        SQLStatement.AppendNum(0); 
        }
    SQLStatement.Append(_L(","));
    //append the client UID.
    SQLStatement.AppendNum( aUID );
    SQLStatement.Append(_L(")"));
    
    User::LeaveIfError( iDatabase.Execute( SQLStatement ) );
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::IsForgivenSiteAlreadyL()
// ---------------------------------------------------------------------------
//
TBool CTrustedSitesServer::IsForgivenSiteAlreadyL( const TDesC& aSite )
    {
    RDbView view;   
    _LIT( KSQLCheckForgivenSite, 
    "SELECT SiteName, Forgiven, OutOfDate FROM TrustedSites" );

    TInt err = view.Prepare( iDatabase, TDbQuery( KSQLCheckForgivenSite ) );
    
    if( err == KErrNotFound )
        {
        return EFalse; 
        }
    
    if ( err != KErrNone )
        {
        User::Leave( KErrArgument );
        }

    err = view.EvaluateAll();

    CleanupClosePushL( view );

    TBool alreadyExist = EFalse;
    
    // looking for a match
    while ( view.NextL() ) // Should find only one certificate
        {
        TRAPD(error, view.GetL());
        error = error;
        
        // sitename is matched and forgiven is set to 1
        if(  (!aSite.Compare(view.ColDes( 1 ))) && ( view.ColInt( 2 ) == 1 )   )
            {
            alreadyExist = ETrue;
            break;
            }
        }
        
    CleanupStack::PopAndDestroy( 1 ); 
    return alreadyExist;
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::DoOverWriteOutOfDateL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::DoOverWriteOutOfDateL(const TDesC& aSite, const TBool& aOutOfDateAllowed )
    {
    _LIT( KSQLOverWrite1, "UPDATE TrustedSites SET OutOfDate = ");
    
    _LIT( KSQLOverWrite2, " WHERE SiteName = '");

    TBuf<KMaxSQLLength> SQLStatement;
    SQLStatement.Copy(KSQLOverWrite1);
    SQLStatement.AppendNum(aOutOfDateAllowed);
    SQLStatement.Append(KSQLOverWrite2);
    SQLStatement.Append(aSite);
    SQLStatement.Append(_L("'"));
    
    User::LeaveIfError( iDatabase.Execute( SQLStatement ) ); 
    }


// ---------------------------------------------------------------------------
// CTrustedSitesServer::DoOverWriteCertL()
// ---------------------------------------------------------------------------
//
void CTrustedSitesServer::DoOverWriteCertL( const TDesC& aSiteName, const TDesC8& aCertHash )
    {
    TInt certID;
    GetCertIDL( aCertHash, certID );
    
    if( certID == KErrNotFound )
        {
        DoAddCertL( aCertHash );
        GetCertIDL(aCertHash, certID);
        }
    
    RDbView view;
    TBuf<KMaxSQLLength> SQLStatement;

    _LIT( KSQLQuery2, "SELECT Forgiven, OutOfDate FROM TrustedSites WHERE CertID = ");
    
    _LIT( KSQLQuery3," AND SiteName ='" );
  
    SQLStatement.Copy( KSQLQuery2 );
    SQLStatement.AppendNum(certID);
    SQLStatement.Append( KSQLQuery3);
    SQLStatement.Append( aSiteName );
    SQLStatement.Append(_L("'"));
    
    TPtrC sqlStat( SQLStatement.PtrZ() );
    TInt err = view.Prepare( iDatabase, TDbQuery( sqlStat ) );
     
    err = view.EvaluateAll();

    CleanupClosePushL( view ); 
     
    //same sitename and same cert exists
    if (view.FirstL())
        {
        //already exist, no need to add
        CleanupStack::PopAndDestroy(); //view
        return;
        }
   
    CleanupStack::PopAndDestroy(); //view
   
    // no match found
   
    _LIT( KSQLQuery, 
    "SELECT Forgiven,OutOfDate, CertID FROM TrustedSites WHERE CertId = -1 AND SiteName = '" );

    SQLStatement.Zero(); 
    SQLStatement.Copy( KSQLQuery );

    SQLStatement.Append( aSiteName );
    SQLStatement.Append(_L("'"));

    sqlStat.Set( SQLStatement.PtrZ() );
    err = view.Prepare( iDatabase, TDbQuery( sqlStat ) );
    
    err = view.EvaluateAll();

    CleanupClosePushL( view );
    
    if ( view.CountL() )
        {
        //record is there but certid is empty, add the certid into the record
        //Update the certid 
        _LIT( KSQLOverWrite1, "UPDATE TrustedSites SET CertID = ");
        _LIT( KSQLOverWrite2, " WHERE SiteName = '");
   
        SQLStatement.Zero();
        SQLStatement.Copy(KSQLOverWrite1);
        SQLStatement.AppendNum( certID );
        SQLStatement.Append(KSQLOverWrite2);
        SQLStatement.Append(aSiteName);
        SQLStatement.Append(_L("'"));
    
        User::LeaveIfError( iDatabase.Execute(SQLStatement) );
        }
    else
        {
        //retrive the forgiven and outofdate, and make a same record for the certificate
        TInt forgiven = 0;
        TInt OutOfDate = 0;
        TInt ClientUID  = 0;
        _LIT( KSQLQuery, 
         "SELECT Forgiven,OutOfDate,CertID,ClientUID FROM TrustedSites WHERE SiteName = '" );

        SQLStatement.Zero(); 
        SQLStatement.Copy( KSQLQuery );

        SQLStatement.Append( aSiteName );
        SQLStatement.Append(_L("'"));

        sqlStat.Set( SQLStatement.PtrZ() );
        err = view.Prepare( iDatabase, TDbQuery( sqlStat ) );
      
        err = view.EvaluateAll();

        CleanupClosePushL( view );
      
        // looking for a match
        if ( view.FirstL() ) // Should find only one certificate
            {
            TRAPD(error, view.GetL());
            error = error;
            //add a new record
            forgiven = view.ColInt( 1 ); 
            OutOfDate = view.ColInt( 2 );
            ClientUID = view.ColInt( 4 );

            //set the new record with new certid and same forgiven and outofdate settings
            _LIT( KSQLInsert,
            "INSERT INTO TrustedSites (CertID,SiteName,Forgiven,OutOfDate,ClientUID) VALUES(" );
            SQLStatement.Zero();
            SQLStatement.Copy(KSQLInsert);
            SQLStatement.AppendNum(certID);
            SQLStatement.Append(_L(",'"));
      
            SQLStatement.Append( aSiteName );
            SQLStatement.Append(_L("',"));
            SQLStatement.AppendNum(forgiven);
            SQLStatement.Append(_L(","));
            SQLStatement.AppendNum(OutOfDate);  
            SQLStatement.Append(_L(","));
            SQLStatement.AppendNum(ClientUID);
            SQLStatement.Append(_L(")"));
            
            User::LeaveIfError( iDatabase.Execute( SQLStatement ) );  
            } 
        CleanupStack::PopAndDestroy();    
        }
    CleanupStack::PopAndDestroy(); //view 
    }
//EOF