📄 pgpremoteprefs.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: pgpRemotePrefs.c,v 1.16 2002/08/06 20:10:16 dallen Exp $
____________________________________________________________________________*/
#include <string.h>
#include "pgpRemotePrefs.h"
#include "pgpClientPrefs.h"
#include "pgpNetPrefs.h"
#include "pgpMem.h"
#include "pgpUtilities.h"
#include "pgpStrings.h"
#include "pgpHash.h"
#include "pgpPFLPriv.h"
#include "pgpLDAP.h"
#define kPGPRemotePGPPrefsDN "pgpelementtype=pgpprefs"
#define kPGPRemotePGPnetPrefsDN "pgpElementType=pgpnetprefs"
#define kPGPRemoteObjectclass "objectclass"
#define kPGPRemoteObjectclassAny "(objectclass=*)"
#define kPGPRemotePGPDataAttr "pgpData"
#define kPGPRemotePGPProfile "pgpprofile"
#define kPGPRemotePGPElement "pgpelement"
#define kPGPOwnerAttr "owner"
#define kPGPRemotePrefSpaceDN "baseClientPrefDN"
#define kPGPRemoteVersionDN "version"
#define kPGPServerInfoCN "cn=PGPServerInfo"
#define kPGPSHAPrefix "{SSHA}"
/*
* (kPGPSHANullLength + kPGPSHASaltLength + kPGPSHAHashLength) % 3 must = 0
*/
#define kPGPSHASaltLength 8 /* no NULLs in this count */
#define kPGPSHAHashLength 20 /* size of a SHA hash in bytes */
#define kPGPSHANullLength 2
#define kPGPSSHAOutputLength ( kPGPSHASaltLength + kPGPSHAHashLength )
#define MAX(a,b) ( (a) > (b) ? (a) : (b) )
#define CKERR if( IsPGPError( err ) ) goto done
/* This is are table of 6-bit value -> character */
static char const armorTable[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const PGPByte kPGPSHASaltBytes[] =
{
0xA0, 0xAA, 0x5C, 0x1E,
0xED, 0x57, 0x7B, 0xC7,
0x00, 0x00
};
static PGPError
sSendTLSEvent(
PGPContextRef context,
PGPEventHandlerProcPtr handler,
PGPUserValue userValue,
PGPKeyServerState state,
PGPtlsSessionRef tlsSession)
{
PGPEvent event;
if( IsNull( handler ) )
return kPGPError_NoErr;
pgpClearMemory( &event, sizeof( PGPEvent ) );
event.type = kPGPEvent_KeyServerTLSEvent;
event.data.keyServerTLSData.state = state;
event.data.keyServerTLSData.tlsSession = tlsSession;
return handler( context, &event, userValue );
}
static PGPError
sSendEvent(
PGPContextRef context,
PGPEventHandlerProcPtr handler,
PGPUserValue userValue,
PGPKeyServerState state )
{
PGPEvent event;
if( IsNull( handler ) )
return kPGPError_NoErr;
pgpClearMemory( &event, sizeof( PGPEvent ) );
event.type = kPGPEvent_KeyServerEvent;
event.data.keyServerData.state = state;
return handler( context, &event, userValue );
}
static PGPError
sSendPrefsToServer(
PGPContextRef context,
PGPldapContextRef ldap,
char * DN,
char * username,
PGPPrefRef prefs )
{
PGPldapMod modData;
PGPldapMod objectclassData;
PGPldapMod ownerData;
char * ownerAttr[2];
char * element[2] = { kPGPRemotePGPElement, NULL };
PGPldapMod * mod[4];
PGPberValue berData;
PGPberValue * bvalue[2];
PGPSize prefBufferSize = 0;
void * prefBuffer = NULL;
PGPError err = kPGPError_NoErr;
(void) context;
ownerAttr[0] = username; ownerAttr[1] = NULL;
mod[0] = &modData; mod[1] = mod[2] = mod[3] = NULL;
bvalue[0] = &berData; bvalue[1] = NULL;
err = PGPExportPrefsToBuffer( prefs, &prefBufferSize, &prefBuffer ); CKERR;
//prefBuffer = PGPNewData( PGPPeekContextMemoryMgr( context ), strlen( "Test buffer" ) + 1, kPGPMemoryMgrFlags_Clear );
//strcpy( prefBuffer, "Test buffer" );
//prefBufferSize = strlen( "Test buffer" );
mod[0]->op = (PGPldapModOp) ( kPGPldapModOp_Replace | kPGPldapModOpMask_UseBERValues );
mod[0]->type = kPGPRemotePGPDataAttr;
bvalue[0]->value = prefBuffer;
bvalue[0]->length = prefBufferSize;
bvalue[1] = NULL;
mod[0]->bvalue = bvalue;
mod[1] = &ownerData;
mod[1]->op = kPGPldapModOp_Replace;
mod[1]->type = kPGPOwnerAttr;
mod[1]->value = ownerAttr;
mod[2] = NULL;
/*
* First, assume that it already exists on the server and we can
* just modify it.
*/
err = PGPldapModifySync( ldap, DN, mod );
if( err == kPGPError_LDAPNoSuchObject )
{
/*
* Oops. The object doesn't exist on the server, so we need
* to create it first. In order to tell the LDAP server to accept
* the "pgpData" attribute, we need to tell it we're creating an
* object with objectclass=pgpelement (and the server administrator
* has to have added the correct schema, of course).
*
* We can leave mod[0] to be the pgpData=<blob>, and set mod[1]
* to be the request to create the right objectclass.
*/
mod[0]->op = (PGPldapModOp) ( kPGPldapModOp_Add | kPGPldapModOpMask_UseBERValues );
mod[1] = &objectclassData;
mod[1]->op = kPGPldapModOp_Add;
mod[1]->type = kPGPRemoteObjectclass;
mod[1]->value = element;
mod[2] = &ownerData;
mod[2]->op = kPGPldapModOp_Replace;
mod[2]->type = kPGPOwnerAttr;
mod[2]->value = ownerAttr;
mod[3] = NULL;
err = PGPldapAddSync( ldap, DN, mod );
}
CKERR;
done:
if( IsntNull( prefBuffer ) )
(void) PGPFreeData( prefBuffer );
return err;
}
static PGPError
sGetPrefsFromServer(
PGPContextRef context,
PGPldapContextRef ldap,
char * DN,
PGPEventHandlerProcPtr handler,
PGPUserValue userValue,
const PGPPrefDefinition * prefDef,
PGPUInt32 prefSize,
PGPPrefRef * prefs )
{
PGPError err = kPGPError_NoErr;
PGPldapMessageRef message = kInvalidPGPldapMessageRef;
PGPldapMessageRef dataMessage = kInvalidPGPldapMessageRef;
PGPberValue ** bval = NULL;
err = sSendEvent( context, handler, userValue, kPGPKeyServerState_Querying ); CKERR;
err = PGPNewLDAPMessage( ldap, &message ); CKERR;
err = PGPldapSearchSync( ldap, DN, kPGPldapScope_Base,
kPGPRemoteObjectclassAny, NULL, FALSE,
message ); CKERR;
err = sSendEvent( context, handler, userValue,
kPGPKeyServerState_ProcessingResults ); CKERR;
err = PGPldapFirstEntry( ldap, message, &dataMessage ); CKERR;
err = PGPldapGetValuesLen( ldap, dataMessage, kPGPRemotePGPDataAttr, &bval ); CKERR;
err = PGPImportBufferToMemoryPrefs( PGPPeekContextMemoryMgr( context ),
bval[0]->value, bval[0]->length, prefDef, prefSize, prefs ); CKERR;
done:
if( PGPldapMessageRefIsValid( message ) )
(void) PGPFreeLDAPMessage( message );
if( IsntNull( bval ) )
(void) PGPFreeLDAPValuesLen( bval );
return err;
}
static PGPError
sEstablishTLSSession(
PGPContextRef pgpContext,
PGPldapContextRef ldap,
PGPtlsContextRef * tlsContext,
PGPtlsSessionRef * tlsSession )
{
PGPSocketRef sock = kInvalidPGPSocketRef;
PGPError err = kPGPError_NoErr;
err = PGPldapGetOption( ldap, kPGPldapOpt_Desc, &sock ); CKERR;
err = PGPNewTLSContext( pgpContext, tlsContext ); CKERR;
err = PGPNewTLSSession( *tlsContext, tlsSession ); CKERR;
err = PGPSocketsEstablishTLSSession( sock, *tlsSession ); CKERR;
done:
return err;
}
static PGPError
sParseURL(
PGPContextRef context,
PGPldapContextRef ldap,
char * url,
PGPtlsContextRef * tlsContext,
PGPtlsSessionRef * tlsSession,
PGPEventHandlerProcPtr handler,
PGPUserValue userValue,
PGPBoolean * isKeyserver,
PGPldapURLDesc ** urlDesc )
{
PGPError err = kPGPError_NoErr;
char * fixedURL = NULL;
PGPMemoryMgrRef mgr = kInvalidPGPMemoryMgrRef;
PGPldapMessageRef message = kInvalidPGPldapMessageRef;
char * attr[] = { kPGPRemotePrefSpaceDN,
kPGPRemoteVersionDN,
NULL };
char ** values = NULL;
PGPValidatePtr( url );
PGPValidatePtr( tlsContext );
PGPValidatePtr( tlsSession );
PGPValidatePtr( isKeyserver );
PGPValidatePtr( urlDesc );
mgr = PGPPeekContextMemoryMgr( context );
*isKeyserver = FALSE;
err = PGPldapURLParse( ldap, url, urlDesc );
if( err == kPGPError_LDAPNoDN )
{
fixedURL = PGPNewData( mgr, strlen( url ) + 2, kPGPMemoryMgrFlags_Clear );
if( IsNull( fixedURL ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
pgpCopyMemory( url, fixedURL, strlen( url ) + 1 );
strcat( fixedURL, "/" );
err = PGPldapURLParse( ldap, fixedURL, urlDesc ); CKERR;
if( (*urlDesc)->port == 0 )
{
if( strstr( url, "ldaps://" ) != NULL )
(*urlDesc)->port = kPGPldap_DefaultSecurePort;
else
(*urlDesc)->port = kPGPldap_DefaultPort;
}
/* Query cn=PGPServerInfo */
err = PGPldapOpen( ldap, (*urlDesc)->host, (*urlDesc)->port ); CKERR;
if( strstr( url, "ldaps://" ) != NULL )
{
/* Try to use TLS */
err = sEstablishTLSSession( context, ldap, tlsContext, tlsSession );
if( IsPGPError( err ) )
{
(void) sSendTLSEvent( context, handler, userValue,
kPGPKeyServerState_TLSUnableToSecureConnection, *tlsSession );
goto done;
}
else
{
err = sSendTLSEvent( context, handler, userValue,
kPGPKeyServerState_TLSConnectionSecured, *tlsSession ); CKERR;
}
}
err = PGPldapSimpleBindSync( ldap, NULL, NULL ); CKERR;
err = PGPNewLDAPMessage( ldap, &message ); CKERR;
err = PGPldapSearchSync( ldap,
kPGPServerInfoCN,
kPGPldapScope_Base,
kPGPRemoteObjectclassAny,
attr,
FALSE,
message ); CKERR;
err = PGPldapGetValues( ldap, message, kPGPRemotePrefSpaceDN, &values ); CKERR;
if( IsNull( values ) || IsNull( *values ) )
{
err = kPGPError_LDAPNoSuchAttribute;
goto done;
}
if( IsntNull( (*urlDesc)->dn ) )
(void) PGPFreeData( (*urlDesc)->dn );
(*urlDesc)->dn = PGPNewData( mgr, strlen( values[0] ) + 1, kPGPMemoryMgrFlags_Clear );
if( IsNull( (*urlDesc)->dn ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
pgpCopyMemory( values[0], (*urlDesc)->dn, strlen( values[0] ) + 1 );
*isKeyserver = TRUE;
}
CKERR;
if( IsNull( (*urlDesc)->host ) )
{
err = kPGPError_LDAPNotLDAPURL;
goto done;
}
if( (*urlDesc)->port == 0 )
{
if( strstr( url, "ldaps://" ) != NULL )
(*urlDesc)->port = kPGPldap_DefaultSecurePort;
else
(*urlDesc)->port = kPGPldap_DefaultPort;
}
done:
if( IsntNull( values ) )
(void) PGPFreeLDAPValues( values );
return err;
}
static PGPError
sFreeTLSSession(
PGPtlsContextRef * tlsContext,
PGPtlsSessionRef * tlsSession )
{
(void) PGPFreeTLSContext( *tlsContext );
*tlsContext = kInvalidPGPtlsContextRef;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -