home *** CD-ROM | disk | FTP | other *** search
- /*
- * This is a part of the Microsoft Source Code Samples.
- * Copyright 1996-1997 Microsoft Corporation.
- * All rights reserved.
- *
- * The following example demonstrates how license updates are made and
- * how the challenge mechanism is used at request and update times. The
- * application developer should analyze the application to determine the
- * appropriate time to perform an update. For example, this application
- * prints a message 20 times and the appropriate time to do an update
- * was decided to be done after every 5th message was printed.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #include "windows.h"
-
- /*
- * Include the MD4 header for computing the challenge.
- */
- #include "md4.h"
-
- /*
- * Include the LSAPI header file.
- */
- #include "lsapi.h"
-
- /*
- * Define the product name, product version, and publisher name for
- * use with the licensing calls.
- */
- #define MYAPP_PRODUCT_NAME "sample_product"
- #define MYAPP_PRODUCT_VERSION "2.0"
- #define MYAPP_PUBLISHER_NAME "sample_publishers"
-
-
- /*
- * Define the strings used to log a comment with the license system.
- */
- #define MYAPP_REQUEST_LOG_COMMENT "Comment for the LSRequest call"
- #define MYAPP_RELEASE_LOG_COMMENT "Comment for the LSRelease call"
- #define MYAPP_UPDATE_LOG_COMMENT "Comment for the LSUpdate call"
-
- /*
- * The digest length is defined to be 16 according to the LSAPI spec.
- */
- #define DIGESTLEN 16
-
- /*
- * Define the number of secrets
- */
- #define NUMBER_OF_SECRETS 4
-
- /*
- * Define macros to indicate to the challenge routines whether we are
- * doing an LSRequest or an LSUpdate
- */
- #define LS_REQUEST 0
- #define LS_UPDATE 1
-
- /*
- * Global variable used to determine if we are on a little endian machine
- * or not.
- */
- int littleEndian = 0;
-
-
- /*
- * Forward declarations.
- */
- void PrintErrors( LS_HANDLE handle, LS_STATUS_CODE errorCode );
- LS_STATUS_CODE getChallenge(
- LS_CHALLENGE FAR *challenge,
- LS_STR FAR *theString,
- LS_ULONG unitsConsumed,
- LS_ULONG unitsReserved,
- LS_STR FAR *logcomment,
- LS_ULONG R,
- LS_ULONG X,
- LS_ULONG typeOfCall);
- int checkChallenge(
- LS_CHALLENGE FAR *challenge,
- LS_STR FAR *theString,
- LS_ULONG unitsConsumed ,
- LS_ULONG unitsReserved ,
- LS_STR FAR *logComment ,
- LS_ULONG unitsGranted ,
- LS_STATUS_CODE status ,
- LS_ULONG R,
- LS_ULONG X,
- LS_ULONG typeOfCall);
- void swap( LS_STR FAR *byte1, LS_STR FAR *byte2 );
- int PlaceInt( char FAR *buffer, LS_ULONG value );
-
-
-
-
-
- __cdecl main()
- {
- LS_STATUS_CODE status;
- unsigned long unitsGranted = 0;
- LS_CHALLENGE challenge;
- LS_HANDLE licenseHandle = (LS_HANDLE) NULL;
- LS_ULONG R;
- LS_ULONG X;
- int i;
- int endianTester = 1 ;
- LS_STR challengeString[100];
- char FAR *endianChar = NULL;
- LS_ULONG Secrets[4] = { 0x7778797A, 0x31323334, 1633837924, 926431536 };
-
- /************ the following code is for the LSAPI beta only! ************/
- char szProviderPath[ MAX_PATH ];
- UINT nChars;
-
- /* install if necessary */
- nChars = GetSystemDirectory( szProviderPath, sizeof( szProviderPath ) );
- if ( 0 == nChars )
- {
- printf( "Can't get system directory, error %d.\n", GetLastError() );
- }
-
- lstrcat( szProviderPath, "\\mslsp32.dll" );
- status = LSInstall( szProviderPath );
- if ( LS_SUCCESS != status )
- {
- printf( "Cannot install LSAPI, error 0x%08lx.\n", status );
- }
-
- /* add licenses for our product */
- status = LSLicenseUnitsSet( LS_ANY,
- MYAPP_PUBLISHER_NAME,
- MYAPP_PRODUCT_NAME,
- MYAPP_PRODUCT_VERSION,
- LS_LICENSE_TYPE_NODE,
- LS_NULL,
- 1,
- sizeof( Secrets ) / sizeof( *Secrets ),
- Secrets );
- if ( LS_SUCCESS != status )
- {
- printf( "Cannot install licenses, error 0x%lx.\n", status );
- }
- /************ the above code is for the LSAPI beta only! ************/
-
- /*
- * test endianness and set global variable by casting an int
- * as bytes and look at the first byte
- */
- endianChar = (char FAR *) &endianTester ;
- if ( *endianChar )
- littleEndian = 1 ;
-
- /*
- * Calculate the string for the challenge on the LSRequest call.
- */
- sprintf( challengeString, "%s%s%s%s%s",
- "LSRequest",
- LS_ANY,
- MYAPP_PUBLISHER_NAME,
- MYAPP_PRODUCT_NAME,
- MYAPP_PRODUCT_VERSION );
-
- /*
- * Pick the random number R and randomly pick a number for the index X
- * between 1 and the number of secrets.
- */
- srand( (unsigned)time( NULL ) );
- R = rand();
- X = (int)(NUMBER_OF_SECRETS * ((float)rand()/(float)RAND_MAX)) + 1;
-
- /*
- * Calculate the message digest for the challenge argument.
- */
- status = getChallenge(
- &challenge,
- challengeString,
- 0, /* Unused argument for LSRequest call */
- LS_DEFAULT_UNITS,
- MYAPP_REQUEST_LOG_COMMENT,
- R,
- X,
- LS_REQUEST );
- if ( LS_SUCCESS != status )
- {
- PrintErrors( licenseHandle, status );
- return(1);
- }
-
- /*
- * Make the grant request call
- */
- status = LSRequest(
- (LS_STR FAR *) LS_ANY,
- (LS_STR FAR *) MYAPP_PUBLISHER_NAME,
- (LS_STR FAR *) MYAPP_PRODUCT_NAME,
- (LS_STR FAR *) MYAPP_PRODUCT_VERSION,
- LS_DEFAULT_UNITS,
- (LS_STR FAR *) MYAPP_REQUEST_LOG_COMMENT,
- &challenge,
- &unitsGranted,
- &licenseHandle);
- if ( LS_SUCCESS != status )
- {
- PrintErrors( licenseHandle, status );
- LSFreeHandle( licenseHandle );
- return(1);
- }
-
- /*
- * Check whether the challenge succeeded.
- */
- if ( !checkChallenge(
- &challenge,
- challengeString,
- 0, /* Unused argument for LSRequest call */
- LS_DEFAULT_UNITS,
- MYAPP_REQUEST_LOG_COMMENT,
- unitsGranted,
- status,
- R,
- X,
- LS_REQUEST ) )
- {
- printf("Challenge failed!!!\n");
- /*
- * Since we failed, we should still release the grant and free
- * the license handle.
- */
- status = LSRelease( licenseHandle,
- LS_DEFAULT_UNITS,
- (LS_STR FAR *) MYAPP_RELEASE_LOG_COMMENT);
- if ( LS_SUCCESS != status )
- PrintErrors( licenseHandle, status );
-
- LSFreeHandle( licenseHandle );
- return(1);
- }
-
- /*
- * Now we can start the application. Print "Hello, World" 20 times
- * performing an update after every 5th time.
- */
- for ( i = 0; i<20; i++ )
- {
- printf("Hello, World.\n");
-
- if ( 0 == i%5 )
- {
- /*
- * Calculate the challenge string for the challenge on
- * the LSUpdate call.
- */
- sprintf( challengeString, "%s", "LSUpdate");
-
- /*
- * Pick the random number R using the process id for the seed
- * to the random number generator. Also randomly pick a number
- * for the index X between 1 and NUMBER_OF_SECRETS.
- */
- srand( (unsigned)time( NULL ) );
- R = rand();
- X = (int)(NUMBER_OF_SECRETS * ((float)rand()/(float)RAND_MAX)) + 1;
-
- /*
- * Calculate the message digest for the challenge argument.
- */
- status = getChallenge(
- &challenge,
- challengeString,
- LS_DEFAULT_UNITS,
- LS_DEFAULT_UNITS,
- MYAPP_UPDATE_LOG_COMMENT,
- R,
- X,
- LS_UPDATE );
- if ( LS_SUCCESS != status )
- {
- PrintErrors( licenseHandle, status );
- status = LSRelease( licenseHandle,
- LS_DEFAULT_UNITS,
- (LS_STR FAR *) MYAPP_RELEASE_LOG_COMMENT);
- LSFreeHandle( licenseHandle );
- return(1);
- }
-
- /*
- * Make the update call.
- */
- status = LSUpdate( licenseHandle,
- LS_DEFAULT_UNITS,
- LS_DEFAULT_UNITS,
- (LS_STR FAR *) MYAPP_UPDATE_LOG_COMMENT,
- &challenge,
- &unitsGranted);
- if ( LS_SUCCESS != status )
- {
- PrintErrors( licenseHandle, status );
- status = LSRelease( licenseHandle,
- LS_DEFAULT_UNITS,
- (LS_STR FAR *) MYAPP_RELEASE_LOG_COMMENT);
- LSFreeHandle( licenseHandle );
- return( 1 );
- }
-
- /*
- * Check whether the challenge succeeded.
- */
- if ( !checkChallenge(
- &challenge,
- challengeString,
- LS_DEFAULT_UNITS,
- LS_DEFAULT_UNITS,
- MYAPP_UPDATE_LOG_COMMENT,
- unitsGranted,
- status,
- R,
- X,
- LS_UPDATE ) )
- {
- printf("Challenge failed!!!\n");
- /*
- * Release the grant.
- */
- status = LSRelease( licenseHandle,
- LS_DEFAULT_UNITS,
- (LS_STR FAR *) MYAPP_RELEASE_LOG_COMMENT);
- if ( LS_SUCCESS != status )
- PrintErrors( licenseHandle, status );
-
- LSFreeHandle( licenseHandle );
- return(1);
- }
- } /* End of if ( 0 == i%5 ) */
-
- } /* End of for loop. */
-
- /*
- * Release the grant.
- */
- status = LSRelease( licenseHandle,
- LS_DEFAULT_UNITS,
- (LS_STR FAR *) MYAPP_RELEASE_LOG_COMMENT);
- if ( LS_SUCCESS != status )
- {
- PrintErrors( licenseHandle, status );
- LSFreeHandle( licenseHandle );
- return( 1 );
- }
-
- /*
- * Free the license handle.
- */
- LSFreeHandle( licenseHandle );
- return(0);
- }
-
-
- /*
- * Print the error message.
- */
- void PrintErrors( LS_HANDLE handle, LS_STATUS_CODE errorCode )
- {
- LS_STATUS_CODE status;
- char errorText[200];
-
-
- status = LSGetMessage( handle, errorCode, (LS_STR FAR *)errorText, 200);
- if ( LS_TEXT_UNAVAILABLE == status )
- printf("Error: No message catalog available.\n");
- else
- if ( LS_UNKNOWN_STATUS == status )
- printf("Error: Unknown error code was used.\n");
- else
- printf("Error: %s\n", errorText);
- }
-
-
- /*
- * Use the algorithmic approach to calculate the message digest to send
- * to the server.
- */
- LS_STATUS_CODE getChallenge(
- LS_CHALLENGE FAR *challenge,
- LS_STR FAR *theString,
- LS_ULONG unitsConsumed,
- LS_ULONG unitsReserved,
- LS_STR FAR *logComment,
- LS_ULONG R,
- LS_ULONG X,
- LS_ULONG typeOfCall)
- {
- MD4_CTX MD;
- char secret[4];
- LS_STR hashString[200], FAR *hashStringPtr;
- int bufferLen, bytes, i;
-
-
- /*
- * Set the protocol, index, random number, and size on the challenge
- * argument.
- */
- challenge->Protocol = LS_BASIC_PROTOCOL;
- challenge->ChallengeData.SecretIndex = X;
- challenge->ChallengeData.Random = R;
-
- /*
- * Get the secret. NOTE: Greater steps should be taken to obsure the
- * secrets than is shown. Also, more secrets should be used than 4.
- * Several methods are shown on how the secret can be specified.
- */
- switch ( X )
- {
- case 1:
- PlaceInt( secret, 0x7778797A );
- break;
- case 2:
- PlaceInt( secret, 0x31323334 );
- break;
- case 3:
- PlaceInt( secret, 1633837924 );
- break;
- case 4:
- PlaceInt( secret, 926431536 );
- break;
- default:
- printf("Index out of range\n");
- return( 0 );
- break;
- }
-
- /*
- * Compute the hash string to be used on input to the MD4 algorithm.
- */
- strcpy( hashString, theString );
- hashStringPtr = hashString + strlen( theString );
- bufferLen = strlen( theString );
-
- /*
- * Add units consumed only for LSUpdate call
- */
- if ( LS_UPDATE == typeOfCall )
- {
- bytes = PlaceInt( hashStringPtr, (LS_ULONG) unitsConsumed );
- hashStringPtr += bytes;
- bufferLen += bytes;
- }
-
- bytes = PlaceInt( hashStringPtr, (LS_ULONG) unitsReserved );
- hashStringPtr += bytes;
- bufferLen += bytes;
-
- strcpy( hashStringPtr, logComment );
- bufferLen += strlen( logComment );
- hashStringPtr += strlen( logComment );
-
- bytes = PlaceInt( hashStringPtr, (LS_ULONG) R );
- hashStringPtr += bytes;
- bufferLen += bytes;
-
- bytes = PlaceInt( hashStringPtr, (LS_ULONG) X );
- hashStringPtr += bytes;
- bufferLen += bytes;
-
- for ( i=0; i<4; i++ )
- {
- *hashStringPtr = secret[i];
- hashStringPtr++;
- bufferLen++;
- }
-
-
- /*
- * Make the MD4 calls.
- */
- MD4Init(&MD);
- MD4Update(
- (MD4_CTX *) &MD,
- (unsigned char *) hashString,
- (unsigned int) bufferLen );
- MD4Final(
- challenge->ChallengeData.MsgDigest.MessageDigest,
- (MD4_CTX *) &MD);
-
- challenge->Size = sizeof( challenge->ChallengeData );
- return( LS_SUCCESS );
- }
-
-
- /*
- * Check the return challenge argument.
- */
- int checkChallenge(
- LS_CHALLENGE FAR *challenge,
- LS_STR FAR *theString,
- LS_ULONG unitsConsumed ,
- LS_ULONG unitsReserved ,
- LS_STR FAR *logComment ,
- LS_ULONG unitsGranted ,
- LS_STATUS_CODE status ,
- LS_ULONG R,
- LS_ULONG X,
- LS_ULONG typeOfCall)
- {
- char secret[4];
- MD4_CTX MD;
- LS_STR hashString[200];
- LS_STR digest[DIGESTLEN], FAR *hashStringPtr;
- int i, bufferLen, bytes, j;
-
-
- /*
- * Get the secret. NOTE: Greater steps should be taken to obsure the
- * secrets than is shown. Also, more secrets should be used than 4.
- * Several methods are shown on how the secret can be specified.
- */
- switch ( X )
- {
- case 1:
- PlaceInt( secret, 0x7778797A );
- break;
- case 2:
- PlaceInt( secret, 0x31323334 );
- break;
- case 3:
- PlaceInt( secret, 1633837924 );
- break;
- case 4:
- PlaceInt( secret, 926431536 );
- break;
- default:
- printf("Index out of range\n");
- return( 0 );
- break;
- }
-
- /*
- * Compute the hash string.
- */
- strcpy( hashString, theString );
- hashStringPtr = hashString + strlen( theString );
- bufferLen = strlen( theString );
-
- /*
- * Add units consumed only for LSUpdate call
- */
- if ( LS_UPDATE == typeOfCall )
- {
- bytes = PlaceInt( hashStringPtr, (LS_ULONG) unitsConsumed );
- hashStringPtr += bytes;
- bufferLen += bytes;
- }
-
- bytes = PlaceInt( hashStringPtr, (LS_ULONG) unitsReserved );
- hashStringPtr += bytes;
- bufferLen += bytes;
-
- strcpy( hashStringPtr, logComment );
- bufferLen += strlen( logComment );
- hashStringPtr += strlen( logComment );
-
- bytes = PlaceInt( hashStringPtr, (LS_ULONG) unitsGranted );
- hashStringPtr += bytes;
- bufferLen += bytes;
-
- bytes = PlaceInt( hashStringPtr, (LS_ULONG) status );
- hashStringPtr += bytes;
- bufferLen += bytes;
-
- bytes = PlaceInt( hashStringPtr, (LS_ULONG) R );
- hashStringPtr += bytes;
- bufferLen += bytes;
-
- bytes = PlaceInt( hashStringPtr, (LS_ULONG) X );
- hashStringPtr += bytes;
- bufferLen += bytes;
-
- for ( i=0; i<4; i++ )
- {
- *hashStringPtr = secret[i];
- hashStringPtr++;
- bufferLen++;
- }
-
-
- /*
- * Compute the message digest.
- */
- MD4Init(&MD);
- MD4Update(
- (MD4_CTX *) &MD,
- (unsigned char *) hashString,
- (unsigned int) bufferLen );
- MD4Final(
- digest,
- (MD4_CTX *) &MD);
-
- /*
- * Compare the digest with the one on the challenge
- */
- j = 0 ;
- for( i = 0; i < DIGESTLEN; i++ )
- {
- if( digest[i] != challenge->ChallengeData.MsgDigest.MessageDigest[i] )
- break ;
- j++ ;
- }
-
- if( j == DIGESTLEN )
- return( 1 );
-
- return( 0 );
- }
-
- /*
- * swap bytes
- */
- void swap( LS_STR FAR *byte1, LS_STR FAR *byte2 )
- {
- LS_STR tmp;
-
- tmp = *byte2;
- *byte2 = *byte1;
- *byte1 = tmp;
- }
-
-
-
- /*
- * Places integer in byte buffer, swapping bytes if necessary
- */
- int PlaceInt( char FAR *buffer, LS_ULONG value )
- {
- if ( littleEndian )
- {
- swap(&(((char FAR *) &value)[0]), &(((char FAR *) &value)[3]));
- swap(&(((char FAR *) &value)[1]), &(((char FAR *) &value)[2]));
- }
-
- memcpy( buffer, &value, sizeof( LS_ULONG ) );
-
- return( (int) sizeof( LS_ULONG ) );
- }
-