📄 pgpskep.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: pgpSKEP.c,v 1.9 2002/08/06 20:10:16 dallen Exp $
____________________________________________________________________________*/
#include "pgpSKEP.h"
#include "pgpSharePriv.h"
#include "pgpSockets.h"
#include "pgpTLS.h"
#include "pgpMem.h"
#include "pgpMemoryMgr.h"
#include "pgpEncode.h"
#include "pgpUtilities.h"
#include "pgpEndianConversion.h"
#include "pgpClientErrors.h"
#include "pgpPFLPriv.h"
#if PGP_WIN32
#include "pgpAsyncDNS.h"
#endif
typedef struct PGPskep PGPskep;
#define kPGPskepMagic 0x156A3C91
struct PGPskep
{
PGPUInt32 magic;
PGPContextRef context;
PGPtlsContextRef tlsContext;
PGPSocketRef socketOut;
PGPSocketRef socketIn;
PGPskepEventHandler eventHandler;
PGPUserValue userValue;
PGPBoolean cancel;
PGPBoolean freeTLSContext;
#if PGP_WIN32
PGPAsyncHostEntryRef asyncHostEntryRef;
#endif
};
#define PGPValidateSKEP(ref) PGPValidateParam(ref != NULL)
#define kPGPskep_Port 14747
#define kPGPskep_ClosingMessage 0x155901C5
#define kPGPskepEndian kPGPBigEndian
#define kPGPskepMajor 0x02 /* SKEP major version */
#define kPGPskepMinor 0x00 /* SKEP minor version */
#define kPGPskepAcceptTimeout 2
#define kPGPskepReceiveTimeout 1
static PGPError sSocketSend(PGPskepRef skep, PGPSocketRef socket,
void *data, PGPInt32 dataSize, PGPBoolean crossPlatform,
PGPskepEventProgressData *progressData);
static PGPError sSocketReceive(PGPskepRef skep, PGPSocketRef socket,
void *data, PGPInt32 dataSize, PGPBoolean crossPlatform,
PGPskepEventProgressData *progressData);
static PGPSocketRef sSocketAccept(PGPskepRef skep, PGPSocketRef sock,
PGPSocketAddress *sockAddr, PGPInt32 *addrLength);
static PGPError sProcessResult(PGPskepRef skep, PGPInt32 result,
PGPskepEventProgressData *progressData);
static PGPError sSocketCallback(PGPContextRef context,
struct PGPEvent *event, PGPUserValue userValue);
PGPError PGPNewSKEP(PGPContextRef context,
PGPtlsContextRef tlsContext,
PGPskepRef *skep)
{
PGPMemoryMgrRef memoryMgr = NULL;
PGPError err = kPGPError_NoErr;
if (IsntNull(skep))
*skep = NULL;
PGPValidateParam(PGPContextRefIsValid(context));
PGPValidatePtr(skep);
memoryMgr = PGPPeekContextMemoryMgr(context);
*skep = (PGPskepRef) PGPNewData(memoryMgr, sizeof(PGPskep),
kPGPMemoryMgrFlags_Clear);
pgpAssert(IsntNull(*skep));
if (IsNull(*skep))
return kPGPError_OutOfMemory;
if (PGPtlsContextRefIsValid(tlsContext))
{
(*skep)->tlsContext = tlsContext;
(*skep)->freeTLSContext = FALSE;
}
else
{
PGPNewTLSContext(context, &((*skep)->tlsContext));
(*skep)->freeTLSContext = TRUE;
}
(*skep)->magic = kPGPskepMagic;
(*skep)->context = context;
(*skep)->socketOut = NULL;
(*skep)->socketIn = NULL;
(*skep)->eventHandler = NULL;
(*skep)->userValue = NULL;
(*skep)->cancel = FALSE;
return err;
}
PGPError PGPskepSetEventHandler(PGPskepRef skep, PGPskepEventHandler handler,
PGPUserValue userValue)
{
PGPValidateSKEP(skep);
PGPValidatePtr(handler);
pgpAssertMsg(skep->magic == kPGPskepMagic, "Invalid SKEP object");
skep->eventHandler = handler;
skep->userValue = userValue;
return kPGPError_NoErr;
}
PGPError PGPskepSendShares(PGPskepRef skep, PGPKeyDBObjRef authKey,
const char *passphrase, PGPShareRef shares,
const char *destSocketAddress)
{
PGPSocketRef socket = NULL;
PGPtlsSessionRef tlsSession = NULL;
PGPEventHandlerProcPtr oldCallback = NULL;
PGPUserValue oldUserValue;
PGPSocketAddressInternet sockAddr;
PGPHostEntry * hostEntry = NULL;
PGPskepEvent skepEvent;
PGPskepEventProgressData progressData = {0,0};
PGPInt32 result;
PGPKeyDBObjRef remoteKey = NULL;
PGPKeyID keyID;
PGPShareID shareID;
PGPUInt32 inetAddress;
PGPUInt32 threshold;
PGPUInt32 numShares;
PGPUInt32 totalShares;
PGPUInt32 closing;
PGPSize shareDataSize;
PGPSize dataSize;
PGPByte * shareData = NULL;
PGPByte version;
PGPBoolean weConfirmed;
PGPBoolean theyConfirmed;
char * newPassphrase = NULL;
PGPByte * newPasskey = NULL;
PGPSize newPasskeySize = 0;
PGPError err = kPGPError_NoErr;
PGPSocketsThreadStorageRef previousStorage;
#if PGP_WIN32
char h_name[256];
#endif
PGPValidateSKEP(skep);
PGPValidateParam(PGPKeyDBObjRefIsValid(authKey));
PGPValidateParam(PGPShareRefIsValid(shares));
PGPValidatePtr(destSocketAddress);
pgpAssertMsg(skep->magic == kPGPskepMagic, "Invalid SKEP object");
skep->cancel = FALSE;
PGPSocketsInit();
PGPSocketsCreateThreadStorage(&previousStorage);
if (IsntNull(skep->eventHandler))
{
PGPGetSocketsIdleEventHandler(&oldCallback, &oldUserValue);
PGPSetSocketsIdleEventHandler(sSocketCallback, skep);
}
inetAddress = PGPDottedToInternetAddress(destSocketAddress);
if (inetAddress != kPGPSockets_Error)
{
#if PGP_WIN32
err = PGPStartAsyncGetHostByAddress(inetAddress,
&skep->asyncHostEntryRef);
if (IsntPGPError(err)) {
PGPWaitForGetHostByAddress(skep->asyncHostEntryRef,
h_name, 256);
skep->asyncHostEntryRef = kPGPInvalidAsyncHostEntryRef;
}
#else
hostEntry = PGPGetHostByAddress((char *) &inetAddress,
sizeof(PGPInternetAddress),
kPGPProtocolFamilyInternet);
#endif
}
else
{
#if PGP_WIN32
err = PGPStartAsyncGetHostByName(destSocketAddress,
&skep->asyncHostEntryRef);
if (IsntPGPError(err)) {
PGPWaitForGetHostByName(skep->asyncHostEntryRef,
&inetAddress);
skep->asyncHostEntryRef = kPGPInvalidAsyncHostEntryRef;
strcpy(h_name, destSocketAddress);
}
#else
hostEntry = PGPGetHostByName(destSocketAddress);
#endif
}
if (IsntPGPError(err) && IsNull(hostEntry))
if (inetAddress == kPGPSockets_Error)
err = PGPGetLastSocketsError();
if (IsntPGPError(err))
{
socket = PGPOpenSocket(kPGPAddressFamilyInternet,
kPGPSocketTypeStream, kPGPTCPProtocol);
if (IsNull(socket))
{
err = PGPGetLastSocketsError();
pgpAssertNoErr(err);
}
}
if (IsntPGPError(err))
{
skep->socketOut = socket;
sockAddr.sin_family = kPGPAddressFamilyInternet;
sockAddr.sin_port = PGPHostToNetShort(kPGPskep_Port);
/* If we were able to get the host entry, use the IP address list */
/* from that. If not, use the IP address passed in by the caller */
if (IsntNull(hostEntry))
sockAddr.sin_addr = *((PGPInternetAddress*)
*hostEntry->h_addr_list);
else
sockAddr.sin_addr = *((PGPInternetAddress*) &inetAddress);
result = PGPConnect(socket, (PGPSocketAddress *) &sockAddr,
sizeof(sockAddr));
if (result == kPGPSockets_Error)
err = PGPGetLastSocketsError();
else
{
skepEvent.type = kPGPskepEvent_ConnectEvent;
if (skep->eventHandler != NULL)
err = skep->eventHandler(skep, &skepEvent,
skep->userValue);
}
}
if (IsntPGPError(err))
{
err = PGPNewTLSSession(skep->tlsContext, &tlsSession);
pgpAssertNoErr(err);
}
if (IsntPGPError(err))
{
err = PGPtlsSetProtocolOptions(tlsSession, kPGPtlsFlags_ClientSide);
pgpAssertNoErr(err);
}
while (IsntPGPError(err))
{
PGPBoolean goodPassphrase;
if (IsNull(newPasskey))
goodPassphrase = PGPPassphraseIsValid(authKey,
passphrase ?
PGPOPassphrase(skep->context, passphrase):
PGPONullOption(skep->context),
PGPOLastOption(skep->context));
else
goodPassphrase = PGPPassphraseIsValid(authKey,
PGPOPasskeyBuffer(skep->context, newPasskey,
newPasskeySize),
PGPOLastOption(skep->context));
if (!goodPassphrase)
{
if (IsntNull(skep->eventHandler))
{
if (IsntNull(newPassphrase))
PGPFreeData(newPassphrase);
if (IsntNull(newPasskey))
PGPFreeData(newPasskey);
skepEvent.type = kPGPskepEvent_PassphraseEvent;
skepEvent.data.ppd.passphrase = NULL;
skepEvent.data.ppd.passkey = NULL;
err = skep->eventHandler(skep, &skepEvent, skep->userValue);
if (IsPGPError(err))
break;
newPassphrase = skepEvent.data.ppd.passphrase;
newPasskey = skepEvent.data.ppd.passkey;
newPasskeySize = skepEvent.data.ppd.passkeySize;
if (IsNull(newPassphrase) && IsNull(newPasskey))
err = kPGPError_BadPassphrase;
else
passphrase = newPassphrase;
}
else
err = kPGPError_BadPassphrase;
}
else
break;
}
if (IsntPGPError(err))
{
if (IsNull(newPasskey))
err = PGPtlsSetLocalPrivateKey(tlsSession, authKey, NULL,
passphrase ?
PGPOPassphrase( skep->context, passphrase ) :
PGPONullOption( skep->context),
PGPOLastOption( skep->context ) );
else
err = PGPtlsSetLocalPrivateKey(tlsSession, authKey, NULL,
PGPOPasskeyBuffer( skep->context, newPasskey,
newPasskeySize ),
PGPOLastOption( skep->context ) );
pgpAssertNoErr(err);
}
if (IsntPGPError(err))
{
err = PGPSocketsEstablishTLSSession(socket, tlsSession);
if (IsPGPError(err))
err = PGPGetLastSocketsError();
if (skep->cancel == TRUE)
err = kPGPError_UserAbort;
pgpAssertNoErr(err);
}
if (IsntPGPError(err))
{
err = PGPtlsGetRemoteAuthenticatedKey(tlsSession, &remoteKey, NULL);
if (skep->cancel == TRUE)
err = kPGPError_UserAbort;
pgpAssertNoErr(err);
}
if (IsntPGPError(err))
{
/* If we don't have the host name, set it to the IP address */
if (IsntNull(hostEntry))
#if PGP_WIN32
skepEvent.data.ad.remoteHostname = h_name;
#else
skepEvent.data.ad.remoteHostname = hostEntry->h_name;
#endif
else
skepEvent.data.ad.remoteHostname =
PGPInternetAddressToDottedString(sockAddr.sin_addr);
skepEvent.type = kPGPskepEvent_AuthenticateEvent;
skepEvent.data.ad.remoteKey = remoteKey;
skepEvent.data.ad.remoteIPAddress =
PGPInternetAddressToDottedString(sockAddr.sin_addr);
PGPtlsGetNegotiatedCipherSuite( tlsSession,
&skepEvent.data.ad.tlsCipher );
if( ( skepEvent.data.ad.tlsCipher == kPGPtls_TLS_PGP_DHE_DSS_WITH_NULL_SHA ) ||
( skepEvent.data.ad.tlsCipher == kPGPtls_TLS_DHE_DSS_WITH_NULL_SHA ) )
err = kPGPError_TLSNoCommonCipher;
else
{
if (skep->eventHandler != NULL)
err = skep->eventHandler(skep, &skepEvent,
skep->userValue);
if (IsntPGPError(err))
weConfirmed = TRUE;
else
weConfirmed = FALSE;
err = kPGPError_NoErr;
}
}
if (IsntPGPError(err))
{
pgpGetShareData(shares, &shareData, &shareDataSize);
progressData.bytesTotal = sizeof(shareDataSize) + shareDataSize +
sizeof(dataSize) + sizeof(dataSize) +
sizeof(PGPKeyID) + sizeof(PGPShareID) +
sizeof(threshold) + sizeof(numShares) +
sizeof(totalShares) + 4;
version = kPGPskepMajor;
err = sSocketSend(skep, socket, &version, 1, FALSE, &progressData);
}
else
remoteKey = NULL;
if (IsntPGPError(err))
{
version = kPGPskepMinor;
err = sSocketSend(skep, socket, &version, 1, FALSE, &progressData);
}
if (IsntPGPError(err))
{
err = sSocketSend(skep, socket, &weConfirmed, 1, FALSE,
&progressData);
}
if (IsntPGPError(err))
{
err = sSocketReceive(skep, socket, &theyConfirmed, 1, FALSE,
&progressData);
if (!theyConfirmed)
err = kPGPClientError_RejectedSKEPAuthentication;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -