📄 pgplicensenumbernet.c
字号:
typedef struct formUrlEncodedParam {
const PGPByte *tok;
PGPByte *value;
} formUrlEncodedParam;
static PGPError parseParams( const PGPByte *in,
PGPByte *ticket, PGPByte *scookie, PGPByte *ln, PGPByte *companyName, PGPByte *customerName,
PGPByte *la, PGPByte *groupid )
{
PGPByte buf[kPGPLANet_ReceiveSize];
PGPByte *p;
const PGPByte *s;
PGPUInt32 i;
PGPUInt32 j;
PGPSize len;
PGPBoolean more;
formUrlEncodedParam params[] = {
{ tok_ticket, ticket },
{ tok_scookie, scookie },
{ tok_ln, ln },
{ tok_companyName, companyName },
{ tok_customerName, customerName },
{ "la", la },
{ "group_id", groupid }
};
for( i=0; i<sizeof(params)/sizeof(params[0]); i++ ) {
if( params[i].value )
params[i].value[0] = '\0';
}
/* process parameters */
s = in;
more = TRUE;
while( more ) {
PGPInt32 k;
p = strchr( s, '&' );
if( p != NULL ) {
more = TRUE;
*p = '\0';
}
else
more = FALSE;
/* s points to the pair, decode it into buf */
{
/* remove line breaks and remove encoding */
i=j=0;
while( s[i]=='\r' )
i++;
len = strlen(s);
if( len > sizeof(buf) )
len = sizeof(buf);
for( ; i<len; i++ ) {
if( s[i]=='\r' || s[i]=='\n' || s[i]==' ')
continue;
if( s[i]=='%' ) {
if( len-i >= 3 ) {
PGPUInt32 bv;
PGPByte b[] = { s[i+1], s[i+2], '\0' };
if( sscanf( b, "%02X", &bv ) )
buf[j++] = (PGPByte)bv;
i += 2; /* two extra */
continue; /* one more i */
}
else /* remove it */
break;
}
if( s[i]=='+' ) {
buf[j++] = ' ';
continue;
}
buf[j++] = s[i];
}
buf[j] = '\0';
}
for( k=0; k<sizeof(params)/sizeof(params[0]); k++ ) {
if( params[k].value!=NULL && strncmp( buf, params[k].tok, strlen(params[k].tok))==0 &&
buf[strlen(params[k].tok)]=='=' )
{
strcpy( params[k].value, buf+strlen(params[k].tok)+1 );
}
}
if( more )
s += strlen(s)+1;
}
return kPGPError_NoErr;
}
/* make authorization request, that will be sent to the website as
the main payload */
static PGPError makeAuthReq( PGPContextRef context, const PGPLicenseNumberRef ln,
const PGPByte *customerName,
const PGPByte *companyName,
PGPByte buf[kPGPLANet_ReceiveSize] )
{
PGPError err = kPGPError_NoErr;
PGPByte ln_b32[kPGPLicenseNumberMaxSize] = {'\0'};
PGPLNExportBase32( context, ln, NULL, ln_b32 );
buf[0] = '\0';
if( ln_b32[0] != '\0' ) {
PGPByte *hash_b64 = NULL;
addFormUrlEncodedParam( tok_ln, ln_b32, buf );
addFormUrlEncodedParam( tok_customerName, customerName, buf );
addFormUrlEncodedParam( tok_companyName, companyName, buf );
err = PGPLAGetNameHash( context, customerName, companyName, &hash_b64 );
if( IsntPGPError( err ) )
addFormUrlEncodedParam( tok_nameHash, hash_b64, buf );
if( hash_b64 != NULL )
PGPFreeData( hash_b64 );
}
else {
return kPGPError_CorruptData;
}
return err;
}
/* creates objects from authorization request */
PGPError pgpLAParseAuthenticationRequest(PGPContextRef context,
const PGPByte *authReq, PGPLicenseNumberRef *ln,
PGPByte *custName, PGPByte *compName )
{
PGPError err;
PGPByte ln_b32[kPGPLANet_ReceiveSize];
err = parseParams( authReq,
NULL, NULL, ln_b32, compName, custName, NULL, NULL );
if( IsntPGPError(err) ) {
err = PGPLNImportBase32( context, ln_b32, ln );
}
return err;
}
/* sends request for license authorization */
PGPError pgpLACreateNet(PGPContextRef context,
const PGPByte *url,
const PGPLicenseNumberRef licenseNumber,
const PGPByte *customerName,
const PGPByte *companyName,
PGPLicenseAuthorizationRef *buffer )
{
PGPError err;
PGPInternetAddress addr;
PGPUInt16 port;
PGPByte host_port[kPGPLANet_UrlMax];
PGPByte resource[kPGPLANet_UrlMax];
PGPByte out[kPGPLANet_ReceiveSize];
PGPUInt32 httpError=0;
PGPError remotePgpError=kPGPError_NoErr;
PGPSocketRef socket = kInvalidPGPSocketRef;
PGPByte ln_cust_comp_b64[kPGPLANet_SendSize];
PGPByte ticket_b64[kPGPLANet_ReceiveSize];
PGPByte scookie_b64[kPGPLANet_ReceiveSize];
PGPByte IV[32]; /* for CBC IV */
PGPByte *ticket_stub_b64 = NULL;
PGPByte *ln_cust_comp_b64_encr_b64 = NULL;
PGPByte postParams[kPGPLANet_ReceiveSize];
pgpDHExchangeRef dhExchange = NULL;
PGPSize tsize;
PGPSize cipherBlockSize=0;
PGPSymmetricCipherContextRef symmRef = kInvalidPGPSymmetricCipherContextRef;
PGPCBCContextRef cbcContext = NULL;
err = dhInitDL( context, 0 /*group*/, &dhExchange );
if( IsPGPError(err) )
return err;
err = dhGenerate1( dhExchange );
if( IsPGPError(err) ) {
dhFree(dhExchange);
return err;
}
#if PGP_DEBUG_PRINT
fprintf(stderr,"DH=");
dhPrintBuffer( dhExchange );
fprintf(stderr,"\n");
#endif
tc_encode_base64( PGPPeekContextMemoryMgr(context),
&ticket_stub_b64, &tsize,
dhBuf(dhExchange), dhBufSize(dhExchange) );
makeAuthReq( context, licenseNumber, customerName, companyName,
ln_cust_comp_b64 );
err = parseHttpUrl( url, &addr, &port, host_port, resource );
if( IsPGPError(err) ) {
dhFree(dhExchange);
return err;
}
if( IsntPGPError(err) )
err = createSocket( addr, port, &socket );
postParams[0] = '\0';
addFormUrlEncodedParam( "r", tok_ticket, postParams );
addFormUrlEncodedParam( "group", "0", postParams );
if( IsntPGPError(err) )
err = roundTrip( socket, host_port, resource, FALSE, postParams, out, &httpError, &remotePgpError );
if( httpError == 200 && IsntPGPError(err) && IsntPGPError(remotePgpError) ) {
err = parseParams( out, ticket_b64, scookie_b64, NULL, NULL, NULL, NULL, NULL );
}
else {
ticket_b64[0] = scookie_b64[0] = '\0';
if( httpError ) {
#if PGP_DEBUG_PRINT
fprintf( stderr, "HTTP communication with %s returned %d error code in round 1\n", url, httpError );
#endif
if( IsPGPError(remotePgpError) )
err = remotePgpError;
else
err = kPGPError_NetworkOpFailed;
}
}
if( IsntPGPError(err) ) {
if( *ticket_b64 == '\0' || *scookie_b64 == '\0' )
err = kPGPError_BadParams;
}
#if PGP_DEBUG_PRINT
if( IsntPGPError(err) ) {
fprintf( stderr, "Received (Phase 1):\n" );
fprintf( stderr, "ticket=%s\n", ticket_b64 );
fprintf( stderr, "scookie=%s\n", scookie_b64 );
}
#endif
if( IsntPGPError(err) ) {
PGPByte *ticket_bin = NULL;
PGPSize ticket_bin_size;
PGPByte *scookie_bin_p=NULL;
PGPInt32 paddingSize;
PGPByte ln_cust_comp_b64_encr[kPGPLANet_SendSize];
PGPUInt32 i;
tc_decode_base64( PGPPeekContextMemoryMgr(context),
&ticket_bin, &ticket_bin_size, ticket_b64 );
if( ticket_bin )
err = dhImportGY( dhExchange, ticket_bin, ticket_bin_size );
if( ticket_bin )
PGPFreeData(ticket_bin);
/* prepare secure ln */
dhGenerate2( dhExchange );
PGPNewSymmetricCipherContext( context, kPGPCipherAlgorithm_3DES, &symmRef );
err = PGPGetSymmetricCipherSizes( symmRef, NULL, &cipherBlockSize );
pgpAssert( cipherBlockSize <= sizeof(IV) );
/* get (part of) binary secure cookie and put it in IV */
tc_decode_base64( PGPPeekContextMemoryMgr(context),
&scookie_bin_p, &tsize, scookie_b64 );
if( scookie_bin_p ) {
pgpCopyMemory( scookie_bin_p, IV, cipherBlockSize );
PGPFreeData(scookie_bin_p);
}
err = PGPNewCBCContext( symmRef, &cbcContext );
symmRef = kInvalidPGPSymmetricCipherContextRef;
err = PGPInitCBC( cbcContext, dhBuf(dhExchange), IV );
paddingSize = pkcs5Padding( ln_cust_comp_b64, cipherBlockSize );
/* do an encryption, check the result */
for( i = 0; i < strlen(ln_cust_comp_b64)+1 + paddingSize; i += cipherBlockSize )
{
err = PGPCBCEncrypt( cbcContext, ln_cust_comp_b64 + i, cipherBlockSize, ln_cust_comp_b64_encr + i );
if( IsPGPError( err ) )
break;
}
tc_encode_base64( PGPPeekContextMemoryMgr(context),
&ln_cust_comp_b64_encr_b64, &tsize,
ln_cust_comp_b64_encr, i ); /* multiple of block size */
}
postParams[0] = '\0';
/// XXX check parameters size -- what if scookie was huge??? XXX
addFormUrlEncodedParam( "r", "activate", postParams );
addFormUrlEncodedParam( "protected", "yes", postParams );
addFormUrlEncodedParam( tok_scookie, scookie_b64, postParams );
addFormUrlEncodedParam( tok_ticket_stub, ticket_stub_b64, postParams );
addFormUrlEncodedParam( "authorize_request", ln_cust_comp_b64_encr_b64, postParams );
if( ticket_stub_b64 != NULL )
PGPFreeData( ticket_stub_b64 );
if( ln_cust_comp_b64_encr_b64 != NULL )
PGPFreeData( ln_cust_comp_b64_encr_b64 );
if( IsntPGPError(err) )
err = roundTrip( socket, host_port, resource, TRUE, postParams, out, &httpError, &remotePgpError );
if( IsntPGPError(err) ) {
if( IsPGPError(remotePgpError) )
err = remotePgpError;
if( httpError<200 || httpError>=300) {
#if PGP_DEBUG_PRINT
fprintf( stderr,
"HTTP communication with %s returned %d HTTP code and %d remote PGPError in round 2\n",
url, httpError, remotePgpError );
#endif
if( IsntPGPError(err) )
err = kPGPError_NetworkOpFailed;
}
else if( httpError==204 ) {
#if PGP_DEBUG_PRINT
fprintf( stderr, "HTTP LA server said that there is no information to return in round 2. "
"This means that the server software refused LA (remote PGPError %d)\n", remotePgpError );
#endif
if( IsntPGPError(err) )
err = kPGPError_NetLARefused;
}
}
if( IsntPGPError(err) ) {
PGPByte la[kPGPLANet_ReceiveSize];
PGPByte *la_encr = NULL;
PGPSize la_encr_size;
PGPUInt32 i;
parseParams( out, NULL, NULL, NULL, NULL, NULL, la, NULL );
if( la[0] != '\0' ) {
tc_decode_base64( PGPPeekContextMemoryMgr(context),
&la_encr, &la_encr_size, la );
err = PGPInitCBC( cbcContext, dhBuf(dhExchange), IV );
for( i = 0; i < la_encr_size; i += cipherBlockSize )
{
err = PGPCBCDecrypt( cbcContext, la_encr + i, cipherBlockSize, la + i );
if( IsPGPError( err ) )
break;
}
// TODO: check PKCS5 padding
err = PGPLAImportBase64( context, la, buffer );
}
else {
err = kPGPError_NetLARefused; // We got HTTP OK, but could not parse data
// this is an unidentified server error
}
}
if( cbcContext != NULL )
(void) PGPFreeCBCContext( cbcContext );
if( PGPSymmetricCipherContextRefIsValid( symmRef ) )
(void)PGPFreeSymmetricCipherContext( symmRef );
if( dhExchange )
dhFree( dhExchange );
if( socket != kInvalidPGPSocketRef )
PGPCloseSocket(socket);
return err;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -