sources/PassphraseCache.c

//  PassphraseCache.c -  Passphrase Cache Interface Object  
// 
// Apple Macintosh Developer Technical Support
// Written by:  Vinnie Moscaritolo
//
//  Copyright (work in progress)  Apple Computer, Inc All rights reserved.
//
// You may incorporate this sample code into your applications without
// restriction, though the sample code has been provided "AS IS" and the
// responsibility for its operation is 100% yours.  However, what you are
// not permitted to do is to redistribute the source as "DSC Sample Code"
// after having made changes. If you're going to re-distribute the source,
// we require that you make it clear in the source that the code was
// descended from Apple Sample Code, but that you've made changes.
// 
 
#include <string.h>
#include <Timer.h>
#include <CodeFragments.h>
#include <Errors.h>
 
#define PGP_MACINTOSH 1
#include "pgpkeys.h"
#include "pgpUtilities.h"
#include "pgpMemoryMgr.h"
 
// dont include the .h else the linker gets confused..
//#include "PassphraseCache.h"
 
// ---------------------------------------------------------------------------
#pragma mark Exported Symbols
// ---------------------------------------------------------------------------
 
#ifdef __cplusplus
extern "C" {
#endif
 
#pragma export on
 
    OSErr       __passphrasecache_initialize(const CFragInitBlock* initBlock);
    void        __passphrasecache_terminate(void);
 
    void     FlushPassphraseCache();
 
    void     EnablePassphraseCaching( Boolean  enable);
    void     SetPassphraseCacheTimeLimit( SInt16 mins);
 
    void     RememberPassphrase (PGPKeyRef  keyRef, const char* passphrase);        
 
    Boolean  GetPassphrase      (PGPContextRef, PGPKeyRef, char** passphrase);      
    
    pascal OSErr __initialize(const CFragInitBlock *theInitBlock);
    pascal OSErr __terminate(void);
  
 
#pragma export off
 
#ifdef __cplusplus
}
#endif
 
 
#define k1Minute        (1000  * 60) /* actually 60 */ 
 
// ---------------------------------------------------------------------------
#pragma mark Globals
// ---------------------------------------------------------------------------
    TMTask              gTMTask = {nil,0,nil,0,0};
    long                gCacheTimeLimit;
    UInt32              gWatchdogTick;
    UInt32              gExpired;
    
    
    char                gCache[256];
 
 
    CFragConnectionID   gConnID         = nil;
    Boolean             gCachingEnabled = false;
    FSSpec              gFragSpec;
    UInt32              gFragOffset;
    UInt32              gFragLength;
 
// ---------------------------------------------------------------------------
#pragma mark Local Prototypes
// ---------------------------------------------------------------------------
 
static void __passphrasecache_timerProc(void);
static void  ResetWatchDog(void);
 
 
// ---------------------------------------------------------------------------
static void __passphrasecache_timerProc(void)
// ---------------------------------------------------------------------------
//
{
    FlushPassphraseCache();
//  DebugStr("\pTimer Expires");
}
 
 
// ---------------------------------------------------------------------------
 void FlushPassphraseCache() 
// ---------------------------------------------------------------------------
//  shutdown  Passphrase Cache Interface Object  
{
    gCache[0] = '\0';
 
}
 
 
 // ---------------------------------------------------------------------------
OSErr __passphrasecache_initialize(const CFragInitBlock* initBlock)
// ---------------------------------------------------------------------------
//
//
 
{
#pragma unused (initBlock)
    OSStatus                ErrNo = noErr;
    
    ErrNo = __initialize( initBlock );
    if( ErrNo != noErr) return ErrNo;
 
//DebugStr("\p__passphrasecache_initialize");
 
    if( initBlock->fragLocator.where != kDataForkCFragLocator)  
        {
            DebugStr("\pError Could't load PassphraseCacheLib, wrong frag type?\n");
            return cfragFragmentUsageErr;
        }
 
    gFragSpec = *initBlock->fragLocator.u.onDisk.fileSpec;
    gFragOffset = initBlock->fragLocator.u.onDisk.offset,
    gFragLength = initBlock->fragLocator.u.onDisk.length,
    
    gCache[0] = '\0';
  
    return ErrNo;
}
 
// ---------------------------------------------------------------------------
void __passphrasecache_terminate(void)
// ---------------------------------------------------------------------------
//
//
 
{
//  DebugStr("\p__passphrasecache_terminate");
    
    if(gTMTask.tmAddr != nil)
    {
        RmvTime((QElemPtr) &gTMTask);
        DisposeRoutineDescriptor(gTMTask.tmAddr);
        gTMTask.tmAddr = nil;
    }
    
    __terminate();
    
}
 
#pragma mark -
 
 
// ---------------------------------------------------------------------------
static void ResetWatchDog(void)
// ---------------------------------------------------------------------------
//   
{
    if(gCachingEnabled)
    {
        RmvTime((QElemPtr) &gTMTask);
        InsTime((QElemPtr) &gTMTask);            
        PrimeTime((QElemPtr)&gTMTask, gCacheTimeLimit);      
    }
}
 
// ---------------------------------------------------------------------------
void EnablePassphraseCaching( Boolean  enable) 
// ---------------------------------------------------------------------------
//   
{
    THz saveZone;
    OSStatus    ErrNo = noErr;
    
// this needs to be done in system heap
    saveZone = GetZone();
    SetZone( SystemZone() );
 
    if(gCachingEnabled &&  !enable) 
    {
        // turn caching off
        RmvTime((QElemPtr) &gTMTask);
        DisposeRoutineDescriptor(gTMTask.tmAddr);
        gTMTask.tmAddr = nil;
        gCachingEnabled = false;
        FlushPassphraseCache();
 
        CloseConnection(&gConnID);
    }
    else if(enable && !gCachingEnabled)
    {
        ProcPtr codePtr;
        Str255  errorMessage;
        
// create persistant connection by   increment library  refcount
        ErrNo = GetDiskFragment( &gFragSpec,gFragOffset, gFragLength,
                                "\pPassphraseCacheLib", 
                                kReferenceCFrag, 
                                &gConnID, 
                                &(Ptr)codePtr, 
                                errorMessage);
    if (ErrNo != noErr)
        {
            DebugStr("\pError  Could't load PassphraseCacheLib\n");
        }
 
// start the caching timer up.
        gTMTask.tmAddr      =  NewTimerProc( __passphrasecache_timerProc );  
        gCachingEnabled = true;
     }
    
    SetZone(saveZone);
}
 
// ---------------------------------------------------------------------------
 void SetPassphraseCacheTimeLimit( SInt16 mins) //  (static public)
// ---------------------------------------------------------------------------
//   
{
 
    gCacheTimeLimit = mins * 1000 /* * 60 */ ;
 
    if(mins == 0)  // don't cache
    {
        
     // take this out to cache passphrase
    };
    
    if(mins == 90)  // no time limit
    {
    };  
    
}
 
 
 
// ---------------------------------------------------------------------------
 void RememberPassphrase(PGPKeyRef  keyRef, const char* passphrase)   //  (static public)
// ---------------------------------------------------------------------------
//   
{
    PGPPublicKeyAlgorithm algorithm;
    PGPKeyID              keyID;
    
    PGPGetKeyNumber (keyRef,  kPGPKeyPropAlgID,  (PGPInt32*) &algorithm);
    PGPGetKeyIDFromKey (keyRef, &keyID );
    
    strcpy (gCache, passphrase);
    
    ResetWatchDog();
}
 
// ---------------------------------------------------------------------------
 Boolean GetPassphrase (PGPContextRef   context, PGPKeyRef  keyRef, char** passphrase)   //  (static public)
// ---------------------------------------------------------------------------
//   
{
    PGPPublicKeyAlgorithm algorithm;
    PGPKeyID              keyID;
    
    ResetWatchDog();
 
    PGPGetKeyNumber (keyRef,  kPGPKeyPropAlgID,  (PGPInt32*) &algorithm);
    PGPGetKeyIDFromKey (keyRef, &keyID );
 
    if( strlen(gCache) > 0)
    {
 
        *passphrase  = (char*) PGPNewSecureData( PGPGetContextMemoryMgr(context),  strlen(gCache) , kPGPMemoryMgrFlags_None );
         strcpy (*passphrase, gCache);
         return true;
    }
//   if(  PGPCompareKeyIDs(keyID, keyID) == 0);
 
 
 
return false;
}