sources/PGPserverUAM.c

// 
// 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 <types.h>
 
 
typedef UInt32 KernelID;
 
#include <string.h>
 
#include <PLStringFuncs.h>
#include <CodeFragments.h> 
 
#include "AppleShareRegistry.h"
#include "AppleShareFileServerRegistry.h"
 
 #include "UAM.h"
//#include "OAMTypes.h"
 
 
#define PGP_MACINTOSH 1
 
#include "pgpErrors.h"
#include "pgpKeys.h"
#include "pgpMemoryMgr.h"
#include "pgpUtilities.h"
#include "pgpFeatures.h"
#include "pgpHash.h"
#include "pgpPublicKey.h"
#include "TPGPException.h"
#include "TMacException.h"
#include "TPGPkey.h"
#include "TMemPGPkey.h"
#include "PGPUAMmsgFormat.h"
#include "PGPServerMemory.h"
#include "ASIPChallenge.h"
 
// ---------------------------------------------------------------------------
#pragma mark  Prototypes 
// ---------------------------------------------------------------------------
 
#ifdef __cplusplus
extern "C" {
#endif
#pragma export on
 
    unsigned long UAMVersion = 0;
    unsigned long UAMFlags = 0;
    unsigned char *UAMName = "\pPGPUAM 1.0";
 
            OAMStatus UAMAuthenticate ( int operation, int id,
                                        void* authState, int authStateSize,
                                        void* authData, int authDataSize,
                                        void* authStateOut, int* authStateSizeOut, 
                                        void* authDataOut, int* authDataSizeOut);
 
    pascal  OSErr   UAMSetUP(const CFragInitBlock *theInitBlock);
    pascal  void    UAMCleanUP(void);
 
    pascal OSErr __initialize(const CFragInitBlock *theInitBlock);
    pascal OSErr __terminate(void);
 
#pragma export off
 
 
#ifdef __cplusplus
}
#endif
static void BuildObjectSpecByNameType(OAMObjectSpec *obj, StringPtr name, OAMType type);
 
 
// ---------------------------------------------------------------------------
#pragma mark  Globals 
// ---------------------------------------------------------------------------
 
static  TMemPGPkey *    gServerKey          = nil;
static  PGPMemoryMgrRef gMemMgr             = nil;
static  Boolean         gReloadServerKey    = false;
 
 
class TLoginState
{
 public: 
 
    void*   operator new    (size_t size)       { return ::OTAllocMem (size); };
    void    operator delete (void* deadObject)  { ::OTFreeMem(deadObject); };
 
// PRIVATE FIELDS
    TMemPGPkey  fClientKey;
    Str255      fCounterChallengeString;
 
 };
 
 
 
// ---------------------------------------------------------------------------
static void BuildObjectSpecByNameType(OAMObjectSpec *obj, StringPtr name, OAMType type)
// ---------------------------------------------------------------------------
//
{
    short len = 0;
    
    memset(obj, 0, sizeof(OAMObjectSpec));
    obj->specType = kOAMObjectSpecByNameType;
    obj->objectType = type;
    len = *name + 1;
    memcpy(obj->u.name, name, len);
}
 
 
// ---------------------------------------------------------------------------
OAMStatus UAMAuthenticate
    (int operation, int id,
    void* authState, int authStateSize, void* authData, int authDataSize,
    void* authStateOut, int* authStateSizeOut, void* authDataOut, int* authDataSizeOut)
// ---------------------------------------------------------------------------
// 
{
    *authStateSizeOut = 0;
    *authDataSizeOut = 0;
    
    OAMStatus err = kOAMAuthenticationErr;
 
    try
    {
        switch (operation) 
        {
            case kUAMAuthLogin:              
  //    DebugStr("\pPGP UAMAuthenticate operation = kUAMAuthLogin");
    
                // check if server key needs to be reloaded
                if(gReloadServerKey)    
                {
                    OAMObjectSpec   obj;    
                    unsigned char   keyBuf[1024];
                    UInt32          bufLen = sizeof (keyBuf);
                    
//                  DebugStr("\pInitializing Server Key");
 
                    memset(&obj, 0, sizeof(OAMObjectSpec));
                    obj.specType = kOAMObjectSpecByShortID;
                    obj.u.shortID = kOAMMachineShortID;
 
                    err = UAMGetAttribute(&obj, kOAMMachine, 'PGPs', (void*) keyBuf, &bufLen);
                    if(err == noErr)
                        {
                        gServerKey->Initialize( (void*)keyBuf, bufLen );
                        gReloadServerKey = false;
                        }
                }
            
            // Do authentication challenge.
                {
                    PUAM_LOGIN_CMD  cmd;
                    TLoginState*    stateP;
                    
                    OAMObjectSpec   obj;    
                    unsigned char   keyBuf[1024];
                    UInt32          bufLen = sizeof (keyBuf);
                    Str32           fpString;
 
                    ParseLoginCmd(authData,  (unsigned long *) &authDataSize,  &cmd);
 
                    // find users key
                    memset(&obj, 0, sizeof(OAMObjectSpec));
                    BuildObjectSpecByNameType(&obj,(StringPtr) cmd.userName, kOAMUser);
                    
                    err = UAMGetAttribute(&obj, kOAMUser, 'PGPs', (void*) keyBuf, &bufLen);
 
                    if(err != noErr) break;
                    
                    stateP = new TLoginState();
                    stateP->fClientKey.Initialize((void*) keyBuf, bufLen );
                            
                    // build Challenge String .
                    stateP->fClientKey.GetFingerprintBinaryPString(fpString ); 
                    ReplyToChallenge(gServerKey, "\0", &stateP->fClientKey, (StringPtr) cmd.challengeString, stateP->fCounterChallengeString);
                    
                    *authDataSizeOut = ((char*) FormatLoginResp(authDataOut, stateP->fCounterChallengeString, fpString) - (char*)authDataOut);
                
                    memcpy( authStateOut, &stateP, sizeof stateP );
                    *authStateSizeOut = sizeof stateP;
                    
                    err = kOAMAuthenticationInProgressErr;  
                }
                        
                break;
                
            case kUAMAuthLoginContinue: 
                err = kOAMAuthenticationErr;
                if (authStateSize == sizeof (TLoginState*) )
                {
                    PUAM_LOGIN_CONT_CMD cmd;
                    TLoginState*    stateP =  nil;
                    
                    memcpy( &stateP,authState, sizeof stateP );
                    if(stateP) 
                    {
                        ParseLoginContinueCmd(authData,  (unsigned long *) &authDataSize,  &cmd);
                        err =  VerifyCounterChallenge( &stateP->fClientKey,  stateP->fCounterChallengeString, cmd.SigPString) 
                                    ? noErr : kOAMAuthenticationErr;
                        delete stateP;
                    }
                }
                
                *authStateSizeOut = 0;
                break;
                
            case kUAMAuthChangeKey:         // for change password
                DebugStr("\pPGP UAMAuthenticate operation = kUAMAuthChangeKey");
                break;
                
            case kUAMAuthChangeKeyContinue: // for change password
                DebugStr("\pPGP UAMAuthenticate operation = kUAMAuthChangeKeyContinue");
                break;
            
        }
    }
// handle PGP errors
    catch (TPGPException &ex)
    {
        DebugStr("\pTPGPException");
        err = kOAMAuthenticationErr;
    
    }
 
    return err;
}
 
 
 
// ---------------------------------------------------------------------------
pascal OSErr UAMSetUP(const CFragInitBlock *theInitBlock)
// ---------------------------------------------------------------------------
// 
    {
    OSStatus err = noErr;
    
//  DebugStr("\pPGP UAMSetUP");
    err = __initialize( theInitBlock );
    if (err != noErr) return err;
 
    try
    {
    
        // Create a custom PGP context
        ThrowIfMacErr(  InitializeServerMemory(&gMemMgr));
        
        TPGPkey::Initialize(gMemMgr);
        
        gServerKey = new TMemPGPkey(); 
        
        gReloadServerKey = true;
    }
 
    catch (TMacException & ex)
    {
        err = ex.GetExceptionErr();
    }
    
    catch (TPGPException &ex)
    {
        err = ex.GetExceptionErr();
    }
 
    return err; 
}
 
 
// ---------------------------------------------------------------------------
pascal  void    UAMCleanUP(void)
// ---------------------------------------------------------------------------
// 
{
    DebugStr("\pUAM UAMCleanUP");
    try
    {
//      if(gClientKey) delete gClientKey;
//      if(gServerKey) delete gServerKey;
    
        TPGPkey::Finalize();
 
        FinalizeServerMemory(gMemMgr);  
    }
 
    catch (TMacException & ex)
    {
    }
    
    catch (TPGPException &ex)
    {
    }
    
    __terminate();
 
}