📄 pgpnetservice.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: pgpNetService.c,v 1.26 2002/08/06 20:10:26 dallen Exp $
____________________________________________________________________________*/
#include <errno.h>
#include <pwd.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "pgpMem.h"
#include "pgpErrors.h"
#include "pgpSockets.h"
#include "pgpPFLPriv.h"
#include "pgpNetPrefs.h"
#include "pgpNetService.h"
#define CKERR if( IsPGPError( err ) ) goto done
#define CKNULL(x) do { if( IsNull( x ) ) { err = kPGPError_OutOfMemory; goto done; } } while(0)
#define RETERR(x) do { err = x; goto done; } while(0)
#define STARTUPSCRIPT "/Library/StartupItems/PGPnet/PGPnet"
static PGPError
sGetClientSockPath(
char * sockPath )
{
struct passwd * pw = NULL;
PGPValidatePtr( sockPath );
pw = getpwuid( getuid() );
sprintf( sockPath, "/tmp/.pgpnet-%s-%d-sock", pw->pw_name, getpid() );
return kPGPError_NoErr;
}
static PGPError
sConnectToService(
PGPnetContextRef netContext )
{
PGPInt32 sock = 0;
struct sockaddr_un sun;
PGPInt32 retval = 0;
sock = socket( AF_LOCAL, SOCK_STREAM, 0 );
if( sock < 0 )
goto done;
sun.sun_family = AF_LOCAL;
memcpy( sun.sun_path, kPGPnetSocket, strlen( kPGPnetSocket ) + 1 );
retval = connect( sock, (struct sockaddr *) &sun, sizeof( sun ) );
if( retval < 0 )
goto done;
netContext->sockToService = sock;
done:
if( retval < 0 )
{
if( sock > 0 )
(void) close( sock );
return kPGPError_SocketsNotConnected;
}
return kPGPError_NoErr;
}
static PGPError
sCreateIPCSocket(
char * sockPath,
PGPInt32 * outSock )
{
PGPError err = kPGPError_NoErr;
struct sockaddr_un sun;
PGPInt32 sock = 0;
PGPInt32 retval = 0;
sock = socket( AF_LOCAL, SOCK_STREAM, 0 );
if( sock < 0 )
RETERR( kPGPError_UnknownError );
/* In case the sock is sitting around from a previous run */
(void) unlink( sockPath );
sun.sun_family = AF_LOCAL;
pgpCopyMemory( sockPath, sun.sun_path, strlen( sockPath ) + 1 );
retval = bind( sock, (struct sockaddr *) &sun, SUN_LEN( &sun ) );
if( retval < 0 )
RETERR( kPGPError_UnknownError );
retval = listen( sock, 10 );
if( retval < 0 )
RETERR( kPGPError_UnknownError );
*outSock = sock;
done:
return err;
}
static PGPError
sNewContextInternal(
PGPContextRef context,
PGPnetContextRef *outNetContext,
PGPBoolean getMessagesFromService )
{
PGPError err = kPGPError_NoErr;
PGPnetContextRef netContext = kInvalidPGPnetContextRef;
PGPInt32 sock = 0;
struct sockaddr_un sun;
PGPInt32 len = 0;
PGPInt32 retval = 0;
struct timeval tv;
fd_set sockSet;
char sockPath[PATH_MAX];
time_t startTime = 0;
netContext = PGPNewData( PGPPeekContextMemoryMgr( context ),
sizeof( PGPnetContextPriv ),
kPGPMemoryMgrFlags_Clear );
CKNULL( netContext );
pgpClearMemory( netContext, sizeof( PGPnetContextPriv ) );
err = sConnectToService( netContext );
if( err == kPGPError_SocketsNotConnected )
{
/* PGPnetService isn't running. Start it. */
system( STARTUPSCRIPT " >& /dev/null" );
}
/* Loop for 10 seconds, trying to connect */
startTime = time( NULL );
do
{
usleep( 500000 );
err = sConnectToService( netContext );
} while( IsPGPError( err ) && ( time( NULL ) < ( startTime + 5 ) ) );
CKERR;
if( getMessagesFromService )
{
(void) sGetClientSockPath( sockPath );
(void) unlink( sockPath );
err = sCreateIPCSocket( sockPath, &sock ); CKERR;
}
else
sockPath[0] = '\0';
err = PGPrpcPackAndWrite( context, netContext->sockToService,
kPGPnet_MT_ClientConnect, "bs", getMessagesFromService, sockPath ); CKERR;
if( getMessagesFromService )
{
/* Only wait 30 seconds for service to respond */
tv.tv_sec = 30;
tv.tv_usec = 0;
FD_ZERO( &sockSet );
FD_SET( sock, &sockSet );
retval = select( sock + 1, &sockSet, NULL, NULL, &tv );
if( retval <= 0 )
RETERR( kPGPError_UnknownError );
len = sizeof( sun );
netContext->sockFromService = accept( sock, (struct sockaddr *) &sun, &len );
if( netContext->sockFromService < 0 )
RETERR( kPGPError_UnknownError );
}
else
netContext->sockFromService = -1;
netContext->context = context;
*outNetContext = netContext;
done:
if( IsPGPError( err ) )
{
(void) sGetClientSockPath( sockPath );
(void) unlink( sockPath );
if( IsntNull( netContext ) )
{
if( netContext->sockToService )
(void) close( netContext->sockToService );
if( netContext->sockFromService )
(void) close( netContext->sockFromService );
(void) PGPFreeData( netContext );
}
}
return err;
}
PGPError
PGPnetNewContext(
PGPContextRef context,
PGPnetContextRef *outNetContext )
{
return sNewContextInternal( context, outNetContext, TRUE );
}
PGPError
PGPnetFreeContext(
PGPnetContextRef netContext )
{
char sockPath[PATH_MAX];
PGPnetValidateContextRef( netContext );
if( netContext->sockToService > 0 )
(void) close( netContext->sockToService );
if( netContext->sockFromService > 0 )
(void) close( netContext->sockFromService );
(void) sGetClientSockPath( sockPath );
(void) unlink( sockPath );
(void) PGPFreeData( netContext );
return kPGPError_NoErr;
}
PGPContextRef
PGPnetPeekContextPGPContext(
PGPnetContextRef netContext )
{
return netContext->context;
}
PGPError
PGPnetRereadConfig(
PGPnetContextRef netContext )
{
PGPError err = kPGPError_NoErr;
PGPnetValidateContextRef( netContext );
err = PGPrpcPackAndWrite( netContext->context, netContext->sockToService,
kPGPnet_MT_RereadConfig, "" ); CKERR;
done:
return err;
}
PGPError
PGPnetTellServiceToClearLogFile(
PGPnetContextRef netContext )
{
PGPError err = kPGPError_NoErr;
PGPnetValidateContextRef( netContext );
err = PGPrpcPackAndWrite( netContext->context, netContext->sockToService,
kPGPnet_MT_ClearLogFile, "" ); CKERR;
done:
return err;
}
PGPError
PGPnetConnectToHost(
PGPnetContextRef netContext,
PGPNetPrefHostEntry * hostEntry )
{
PGPError err = kPGPError_NoErr;
PGPByte * buf = NULL;
PGPnetSAIdent said;
PGPnetValidateContextRef( netContext );
said.ipAddress = hostEntry->ipAddrStart;
said.ipAddrStart = hostEntry->ipAddrStart;
said.ipMaskEnd = hostEntry->ipMaskEnd;
said.destIsRange = hostEntry->destIsRange;
err = PGPrpcPackAndWrite( netContext->context, netContext->sockToService,
kPGPnet_MT_Connect, "B", &said, sizeof( PGPnetSAIdent ) ); CKERR;
done:
if( IsntNull( buf ) )
(void) PGPFreeData( buf );
return err;
}
PGPError
PGPnetDisconnectFromHost(
PGPnetContextRef netContext,
PGPipsecSA * sa )
{
PGPError err = kPGPError_NoErr;
PGPnetValidateContextRef( netContext );
err = PGPrpcPackAndWrite( netContext->context, netContext->sockToService,
kPGPnet_MT_Disconnect, "B", sa->transform[0].inSPI, sizeof( PGPipsecSPI ) ); CKERR;
done:
return err;
}
PGPError
PGPnetGetSAList(
PGPnetContextRef netContext,
PGPipsecSA ** sa,
PGPSize * numSAs )
{
PGPError err = kPGPError_NoErr;
PGPByte * buf = NULL;
PGPSize len = 0;
PGPUInt32 numSAsFromService = 0;
PGPipsecSA * tempSAList = NULL;
PGPnetValidateContextRef( netContext );
PGPValidatePtr( sa );
PGPValidatePtr( numSAs );
err = PGPrpcPackAndWrite( netContext->context, netContext->sockToService,
kPGPnet_MT_GetSAList, "" ); CKERR;
err = PGPrpcReadAndUnpack( netContext->context, netContext->sockToService,
kPGPnet_MT_SendSAList, "uB", &numSAsFromService, &buf, &len ); CKERR;
if( numSAsFromService * sizeof( PGPipsecSA ) != len )
{
/* Service said we have X SAs, but didn't send us the right size of data */
RETERR( kPGPError_CorruptData );
}
tempSAList = PGPNewData( PGPPeekContextMemoryMgr( netContext->context ),
len,
kPGPMemoryMgrFlags_Clear );
CKNULL( tempSAList );
pgpCopyMemory( buf, tempSAList, len );
*sa = tempSAList;
*numSAs = numSAsFromService;
done:
if( IsntNull( buf ) )
(void) PGPFreeData( buf );
return err;
}
PGPError
PGPnetGetRemoteAuthKey(
PGPnetContextRef netContext,
PGPipsecSA * sa,
PGPByte ** remoteAuthKey,
PGPSize * remoteAuthKeySize )
{
PGPError err = kPGPError_NoErr;
PGPByte * buf = NULL;
PGPSize len = 0;
PGPnetValidateContextRef( netContext );
PGPValidatePtr( sa );
PGPValidatePtr( remoteAuthKey );
PGPValidatePtr( remoteAuthKeySize );
err = PGPrpcPackAndWrite( netContext->context, netContext->sockToService,
kPGPnet_MT_GetRemoteAuthKey, "B", sa->transform[0].inSPI, sizeof( PGPipsecSPI ) ); CKERR;
err = PGPrpcReadAndUnpack( netContext->context, netContext->sockToService,
kPGPnet_MT_SendRemoteAuthKey, "B", &buf, &len ); CKERR;
*remoteAuthKey = buf;
*remoteAuthKeySize = len;
done:
return err;
}
PGPError
PGPnetFlushPassphrases(
PGPnetContextRef netContext )
{
PGPError err = kPGPError_NoErr;
PGPnetValidateContextRef( netContext );
err = PGPrpcPackAndWrite( netContext->context, netContext->sockToService,
kPGPnet_MT_FlushPassphrases, "" ); CKERR;
done:
return err;
}
PGPError
PGPnetLogTraffic(
PGPnetContextRef netContext,
PGPBoolean allowed,
PGPBoolean blocked )
{
PGPError err = kPGPError_NoErr;
PGPnetValidateContextRef( netContext );
err = PGPrpcPackAndWrite( netContext->context, netContext->sockToService,
kPGPnet_MT_LogTraffic, "bb", allowed, blocked ); CKERR;
done:
return err;
}
#if PGP_OSX
PGPError
PGPnetAddMessageCallbackToCFRunLoop(
PGPnetContextRef netContext,
CFRunLoopRef rl,
CFSocketCallBack callback,
PGPUserValue userValue )
{
CFSocketRef socket;
CFRunLoopSourceRef source;
CFSocketContext socketContext;
socketContext.version = 1;
socketContext.info = userValue;
socketContext.retain = NULL;
socketContext.release = NULL;
socketContext.copyDescription = NULL;
socket = CFSocketCreateWithNative( kCFAllocatorDefault,
netContext->sockFromService,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -