home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sysmgmt / lsapi / challeng.c next >
C/C++ Source or Header  |  1997-10-08  |  18KB  |  646 lines

  1. /*
  2.  *  This is a part of the Microsoft Source Code Samples.
  3.  *  Copyright 1996-1997 Microsoft Corporation.
  4.  *  All rights reserved.
  5.  *
  6.  *  The following example demonstrates how license updates are made and
  7.  *  how the challenge mechanism is used at request and update times.  The
  8.  *  application developer should analyze the application to determine the
  9.  *  appropriate time to perform an update.  For example, this application
  10.  *  prints a message 20 times and the appropriate time to do an update
  11.  *  was decided to be done after every 5th message was printed.
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <time.h>
  17. #include "windows.h"
  18.  
  19. /*
  20.  * Include the MD4 header for computing the challenge.
  21.  */
  22. #include "md4.h"
  23.  
  24. /*
  25.  * Include the LSAPI header file.
  26.  */
  27. #include "lsapi.h"
  28.  
  29. /*
  30.  * Define the product name, product version, and publisher name for
  31.  * use with the licensing calls.
  32.  */
  33. #define MYAPP_PRODUCT_NAME    "sample_product"
  34. #define MYAPP_PRODUCT_VERSION "2.0"
  35. #define MYAPP_PUBLISHER_NAME  "sample_publishers"
  36.  
  37.  
  38. /*
  39.  * Define the strings used to log a comment with the license system.
  40.  */
  41. #define MYAPP_REQUEST_LOG_COMMENT "Comment for the LSRequest call"
  42. #define MYAPP_RELEASE_LOG_COMMENT "Comment for the LSRelease call"
  43. #define MYAPP_UPDATE_LOG_COMMENT  "Comment for the LSUpdate call"
  44.  
  45. /*
  46.  * The digest length is defined to be 16 according to the LSAPI spec.
  47.  */
  48. #define DIGESTLEN                16
  49.  
  50. /*
  51.  * Define the number of secrets
  52.  */
  53. #define NUMBER_OF_SECRETS         4
  54.  
  55. /*
  56.  * Define macros to indicate to the challenge routines whether we are
  57.  * doing an LSRequest or an LSUpdate
  58.  */
  59. #define LS_REQUEST 0
  60. #define LS_UPDATE  1
  61.  
  62. /*
  63.  * Global variable used to determine if we are on a little endian machine
  64.  * or not.
  65.  */
  66. int          littleEndian = 0;
  67.  
  68.  
  69. /*
  70.  * Forward declarations.
  71.  */
  72. void PrintErrors( LS_HANDLE handle, LS_STATUS_CODE errorCode );
  73. LS_STATUS_CODE getChallenge(
  74.       LS_CHALLENGE    FAR *challenge,
  75.       LS_STR          FAR *theString,
  76.       LS_ULONG        unitsConsumed,
  77.       LS_ULONG        unitsReserved,
  78.       LS_STR          FAR *logcomment,
  79.       LS_ULONG        R,
  80.       LS_ULONG        X,
  81.       LS_ULONG        typeOfCall);
  82. int checkChallenge(
  83.       LS_CHALLENGE    FAR *challenge,
  84.       LS_STR          FAR *theString,
  85.       LS_ULONG        unitsConsumed ,
  86.       LS_ULONG        unitsReserved ,
  87.       LS_STR          FAR *logComment ,
  88.       LS_ULONG        unitsGranted ,
  89.       LS_STATUS_CODE  status ,
  90.       LS_ULONG        R,
  91.       LS_ULONG        X,
  92.       LS_ULONG        typeOfCall);
  93. void swap( LS_STR FAR *byte1, LS_STR FAR *byte2 );
  94. int PlaceInt( char FAR *buffer, LS_ULONG value );
  95.  
  96.  
  97.  
  98.  
  99.  
  100. __cdecl main()
  101. {
  102.    LS_STATUS_CODE     status;
  103.    unsigned long      unitsGranted = 0;
  104.    LS_CHALLENGE       challenge;
  105.    LS_HANDLE          licenseHandle = (LS_HANDLE) NULL;
  106.    LS_ULONG           R;
  107.    LS_ULONG           X;
  108.    int                i;
  109.    int                endianTester = 1 ;
  110.    LS_STR             challengeString[100];
  111.    char               FAR *endianChar = NULL;
  112.    LS_ULONG           Secrets[4] = { 0x7778797A, 0x31323334, 1633837924, 926431536 };
  113.  
  114.    /************ the following code is for the LSAPI beta only! ************/
  115.    char               szProviderPath[ MAX_PATH ];
  116.    UINT               nChars;
  117.  
  118.    /* install if necessary */
  119.    nChars = GetSystemDirectory( szProviderPath, sizeof( szProviderPath ) );
  120.    if ( 0 == nChars )
  121.    {
  122.       printf( "Can't get system directory, error %d.\n", GetLastError() );
  123.    }
  124.  
  125.    lstrcat( szProviderPath, "\\mslsp32.dll" );
  126.    status = LSInstall( szProviderPath );
  127.    if ( LS_SUCCESS != status )
  128.    {
  129.       printf( "Cannot install LSAPI, error 0x%08lx.\n", status );
  130.    }
  131.  
  132.    /* add licenses for our product */
  133.    status = LSLicenseUnitsSet( LS_ANY,
  134.                                MYAPP_PUBLISHER_NAME,
  135.                                MYAPP_PRODUCT_NAME,
  136.                                MYAPP_PRODUCT_VERSION,
  137.                                LS_LICENSE_TYPE_NODE,
  138.                                LS_NULL,
  139.                                1,
  140.                                sizeof( Secrets ) / sizeof( *Secrets ),
  141.                                Secrets );
  142.    if ( LS_SUCCESS != status )
  143.    {
  144.       printf( "Cannot install licenses, error 0x%lx.\n", status );
  145.    }
  146.    /************ the above code is for the LSAPI beta only! ************/
  147.  
  148.    /*
  149.     * test endianness and set global variable by casting an int
  150.     * as bytes and look at the first byte
  151.     */
  152.    endianChar = (char FAR *) &endianTester ;
  153.    if ( *endianChar )
  154.         littleEndian = 1 ;
  155.  
  156.    /*
  157.     * Calculate the string for the challenge on the LSRequest call.
  158.     */
  159.    sprintf( challengeString, "%s%s%s%s%s",
  160.             "LSRequest",
  161.             LS_ANY,
  162.             MYAPP_PUBLISHER_NAME,
  163.             MYAPP_PRODUCT_NAME,
  164.             MYAPP_PRODUCT_VERSION );
  165.  
  166.    /*
  167.     * Pick the random number R and randomly pick a number for the index X
  168.     * between 1 and the number of secrets.
  169.     */
  170.    srand( (unsigned)time( NULL ) );
  171.    R = rand();
  172.    X = (int)(NUMBER_OF_SECRETS * ((float)rand()/(float)RAND_MAX)) + 1;
  173.  
  174.    /*
  175.     * Calculate the message digest for the challenge argument.
  176.     */
  177.    status = getChallenge(
  178.          &challenge,
  179.          challengeString,
  180.          0,                    /* Unused argument for LSRequest call */
  181.          LS_DEFAULT_UNITS,
  182.          MYAPP_REQUEST_LOG_COMMENT,
  183.          R,
  184.          X,
  185.          LS_REQUEST );
  186.    if ( LS_SUCCESS != status )
  187.       {
  188.       PrintErrors( licenseHandle, status );
  189.       return(1);
  190.       }
  191.  
  192.    /*
  193.     * Make the grant request call
  194.     */
  195.    status = LSRequest(
  196.          (LS_STR FAR *) LS_ANY,
  197.          (LS_STR FAR *) MYAPP_PUBLISHER_NAME,
  198.          (LS_STR FAR *) MYAPP_PRODUCT_NAME,
  199.          (LS_STR FAR *) MYAPP_PRODUCT_VERSION,
  200.          LS_DEFAULT_UNITS,
  201.          (LS_STR FAR *) MYAPP_REQUEST_LOG_COMMENT,
  202.          &challenge,
  203.          &unitsGranted,
  204.          &licenseHandle);
  205.    if ( LS_SUCCESS != status )
  206.       {
  207.       PrintErrors( licenseHandle, status );
  208.       LSFreeHandle( licenseHandle );
  209.       return(1);
  210.       }
  211.  
  212.    /*
  213.     * Check whether the challenge succeeded.
  214.     */
  215.    if ( !checkChallenge(
  216.          &challenge,
  217.          challengeString,
  218.          0,                    /* Unused argument for LSRequest call */
  219.          LS_DEFAULT_UNITS,
  220.          MYAPP_REQUEST_LOG_COMMENT,
  221.          unitsGranted,
  222.          status,
  223.          R,
  224.          X,
  225.          LS_REQUEST ) )
  226.       {
  227.       printf("Challenge failed!!!\n");
  228.       /*
  229.        * Since we failed, we should still release the grant and free
  230.        * the license handle.
  231.        */
  232.       status = LSRelease( licenseHandle,
  233.                           LS_DEFAULT_UNITS,
  234.                           (LS_STR FAR *) MYAPP_RELEASE_LOG_COMMENT);
  235.       if ( LS_SUCCESS != status )
  236.          PrintErrors( licenseHandle, status );
  237.  
  238.       LSFreeHandle( licenseHandle );
  239.       return(1);
  240.       }
  241.  
  242.    /*
  243.     * Now we can start the application.  Print "Hello, World" 20 times
  244.     * performing an update after every 5th time.
  245.     */
  246.    for ( i = 0; i<20; i++ )
  247.       {
  248.       printf("Hello, World.\n");
  249.  
  250.       if ( 0 == i%5 )
  251.          {
  252.          /*
  253.           * Calculate the challenge string for the challenge on
  254.           * the LSUpdate call.
  255.           */
  256.          sprintf( challengeString, "%s", "LSUpdate");
  257.  
  258.          /*
  259.           * Pick the random number R using the process id for the seed
  260.           * to the random number generator.  Also randomly pick a number
  261.           * for the index X between 1 and NUMBER_OF_SECRETS.
  262.           */
  263.          srand( (unsigned)time( NULL ) );
  264.          R = rand();
  265.          X = (int)(NUMBER_OF_SECRETS * ((float)rand()/(float)RAND_MAX)) + 1;
  266.  
  267.          /*
  268.           * Calculate the message digest for the challenge argument.
  269.           */
  270.          status = getChallenge(
  271.                &challenge,
  272.                challengeString,
  273.                LS_DEFAULT_UNITS,
  274.                LS_DEFAULT_UNITS,
  275.                MYAPP_UPDATE_LOG_COMMENT,
  276.                R,
  277.                X,
  278.                LS_UPDATE );
  279.          if ( LS_SUCCESS != status )
  280.             {
  281.             PrintErrors( licenseHandle, status );
  282.             status = LSRelease( licenseHandle,
  283.                                 LS_DEFAULT_UNITS,
  284.                                 (LS_STR FAR *) MYAPP_RELEASE_LOG_COMMENT);
  285.             LSFreeHandle( licenseHandle );
  286.             return(1);
  287.             }
  288.  
  289.          /*
  290.           * Make the update call.
  291.           */
  292.          status = LSUpdate( licenseHandle,
  293.                             LS_DEFAULT_UNITS,
  294.                             LS_DEFAULT_UNITS,
  295.                             (LS_STR FAR *) MYAPP_UPDATE_LOG_COMMENT,
  296.                             &challenge,
  297.                             &unitsGranted);
  298.          if ( LS_SUCCESS != status )
  299.             {
  300.             PrintErrors( licenseHandle, status );
  301.             status = LSRelease( licenseHandle,
  302.                                 LS_DEFAULT_UNITS,
  303.                                 (LS_STR FAR *) MYAPP_RELEASE_LOG_COMMENT);
  304.             LSFreeHandle( licenseHandle );
  305.             return( 1 );
  306.             }
  307.  
  308.          /*
  309.           * Check whether the challenge succeeded.
  310.           */
  311.          if ( !checkChallenge(
  312.                &challenge,
  313.                challengeString,
  314.                LS_DEFAULT_UNITS,
  315.                LS_DEFAULT_UNITS,
  316.                MYAPP_UPDATE_LOG_COMMENT,
  317.                unitsGranted,
  318.                status,
  319.                R,
  320.                X,
  321.                LS_UPDATE ) )
  322.             {
  323.             printf("Challenge failed!!!\n");
  324.             /*
  325.              * Release the grant.
  326.              */
  327.             status = LSRelease( licenseHandle,
  328.                                 LS_DEFAULT_UNITS,
  329.                                 (LS_STR FAR *) MYAPP_RELEASE_LOG_COMMENT);
  330.             if ( LS_SUCCESS != status )
  331.                PrintErrors( licenseHandle, status );
  332.  
  333.             LSFreeHandle( licenseHandle );
  334.             return(1);
  335.             }
  336.          }  /* End of if ( 0 == i%5 ) */
  337.  
  338.       }  /* End of for loop. */
  339.  
  340.    /*
  341.     * Release the grant.
  342.     */
  343.    status = LSRelease( licenseHandle,
  344.                        LS_DEFAULT_UNITS,
  345.                        (LS_STR FAR *) MYAPP_RELEASE_LOG_COMMENT);
  346.    if ( LS_SUCCESS != status )
  347.       {
  348.       PrintErrors( licenseHandle, status );
  349.       LSFreeHandle( licenseHandle );
  350.       return( 1 );
  351.       }
  352.  
  353.    /*
  354.     * Free the license handle.
  355.     */
  356.    LSFreeHandle( licenseHandle );
  357.    return(0);
  358. }
  359.  
  360.  
  361. /*
  362.  * Print the error message.
  363.  */
  364. void PrintErrors( LS_HANDLE handle, LS_STATUS_CODE errorCode )
  365. {
  366.    LS_STATUS_CODE   status;
  367.    char             errorText[200];
  368.  
  369.  
  370.    status = LSGetMessage( handle, errorCode, (LS_STR FAR *)errorText, 200);
  371.    if ( LS_TEXT_UNAVAILABLE == status )
  372.       printf("Error: No message catalog available.\n");
  373.    else
  374.       if ( LS_UNKNOWN_STATUS == status )
  375.          printf("Error: Unknown error code was used.\n");
  376.       else
  377.          printf("Error: %s\n", errorText);
  378. }
  379.  
  380.  
  381. /*
  382.  * Use the algorithmic approach to calculate the message digest to send
  383.  * to the server.
  384.  */
  385. LS_STATUS_CODE getChallenge(
  386.       LS_CHALLENGE    FAR *challenge,
  387.       LS_STR          FAR *theString,
  388.       LS_ULONG        unitsConsumed,
  389.       LS_ULONG        unitsReserved,
  390.       LS_STR          FAR *logComment,
  391.       LS_ULONG        R,
  392.       LS_ULONG        X,
  393.       LS_ULONG        typeOfCall)
  394. {
  395.    MD4_CTX        MD;
  396.    char           secret[4];
  397.    LS_STR         hashString[200], FAR *hashStringPtr;
  398.    int            bufferLen, bytes, i;
  399.  
  400.  
  401.    /*
  402.     * Set the protocol, index, random number, and size on the challenge
  403.     * argument.
  404.     */
  405.    challenge->Protocol = LS_BASIC_PROTOCOL;
  406.    challenge->ChallengeData.SecretIndex = X;
  407.    challenge->ChallengeData.Random = R;
  408.  
  409.    /*
  410.     * Get the secret.  NOTE: Greater steps should be taken to obsure the
  411.     * secrets than is shown.  Also, more secrets should be used than 4.
  412.     * Several methods are shown on how the secret can be specified.
  413.     */
  414.    switch ( X )
  415.       {
  416.       case 1:
  417.          PlaceInt( secret, 0x7778797A );
  418.          break;
  419.       case 2:
  420.          PlaceInt( secret, 0x31323334 );
  421.          break;
  422.       case 3:
  423.          PlaceInt( secret, 1633837924 );
  424.          break;
  425.       case 4:
  426.          PlaceInt( secret, 926431536 );
  427.          break;
  428.       default:
  429.          printf("Index out of range\n");
  430.          return( 0 );
  431.          break;
  432.       }
  433.  
  434.    /*
  435.     * Compute the hash string to be used on input to the MD4 algorithm.
  436.     */
  437.    strcpy( hashString, theString );
  438.    hashStringPtr = hashString + strlen( theString );
  439.    bufferLen = strlen( theString );
  440.  
  441.    /*
  442.     * Add units consumed only for LSUpdate call
  443.     */
  444.    if ( LS_UPDATE == typeOfCall )
  445.       {
  446.       bytes = PlaceInt( hashStringPtr, (LS_ULONG) unitsConsumed );
  447.       hashStringPtr += bytes;
  448.       bufferLen += bytes;
  449.       }
  450.  
  451.    bytes = PlaceInt( hashStringPtr, (LS_ULONG) unitsReserved );
  452.    hashStringPtr += bytes;
  453.    bufferLen += bytes;
  454.  
  455.    strcpy( hashStringPtr, logComment );
  456.    bufferLen += strlen( logComment );
  457.    hashStringPtr += strlen( logComment );
  458.  
  459.    bytes = PlaceInt( hashStringPtr, (LS_ULONG) R );
  460.    hashStringPtr += bytes;
  461.    bufferLen += bytes;
  462.  
  463.    bytes = PlaceInt( hashStringPtr, (LS_ULONG) X );
  464.    hashStringPtr += bytes;
  465.    bufferLen += bytes;
  466.  
  467.    for ( i=0; i<4; i++ )
  468.       {
  469.       *hashStringPtr = secret[i];
  470.       hashStringPtr++;
  471.       bufferLen++;
  472.       }
  473.  
  474.  
  475.    /*
  476.     * Make the MD4 calls.
  477.     */
  478.    MD4Init(&MD);
  479.    MD4Update(
  480.       (MD4_CTX *) &MD,
  481.       (unsigned char *) hashString,
  482.       (unsigned int) bufferLen );
  483.    MD4Final(
  484.       challenge->ChallengeData.MsgDigest.MessageDigest,
  485.       (MD4_CTX *) &MD);
  486.  
  487.    challenge->Size = sizeof( challenge->ChallengeData );
  488.    return( LS_SUCCESS );
  489. }
  490.  
  491.  
  492. /*
  493.  * Check the return challenge argument.
  494.  */
  495. int checkChallenge(
  496.       LS_CHALLENGE    FAR *challenge,
  497.       LS_STR          FAR *theString,
  498.       LS_ULONG        unitsConsumed ,
  499.       LS_ULONG        unitsReserved ,
  500.       LS_STR          FAR *logComment ,
  501.       LS_ULONG        unitsGranted ,
  502.       LS_STATUS_CODE  status ,
  503.       LS_ULONG        R,
  504.       LS_ULONG        X,
  505.       LS_ULONG        typeOfCall)
  506. {
  507.    char           secret[4];
  508.    MD4_CTX        MD;
  509.    LS_STR         hashString[200];
  510.    LS_STR         digest[DIGESTLEN], FAR *hashStringPtr;
  511.    int            i, bufferLen, bytes, j;
  512.  
  513.  
  514.    /*
  515.     * Get the secret.  NOTE: Greater steps should be taken to obsure the
  516.     * secrets than is shown.  Also, more secrets should be used than 4.
  517.     * Several methods are shown on how the secret can be specified.
  518.     */
  519.    switch ( X )
  520.       {
  521.       case 1:
  522.          PlaceInt( secret, 0x7778797A );
  523.          break;
  524.       case 2:
  525.          PlaceInt( secret, 0x31323334 );
  526.          break;
  527.       case 3:
  528.          PlaceInt( secret, 1633837924 );
  529.          break;
  530.       case 4:
  531.          PlaceInt( secret, 926431536 );
  532.          break;
  533.       default:
  534.          printf("Index out of range\n");
  535.          return( 0 );
  536.          break;
  537.       }
  538.  
  539.    /*
  540.     * Compute the hash string.
  541.     */
  542.    strcpy( hashString, theString );
  543.    hashStringPtr = hashString + strlen( theString );
  544.    bufferLen = strlen( theString );
  545.  
  546.    /*
  547.     * Add units consumed only for LSUpdate call
  548.     */
  549.    if ( LS_UPDATE == typeOfCall )
  550.       {
  551.       bytes = PlaceInt( hashStringPtr, (LS_ULONG) unitsConsumed );
  552.       hashStringPtr += bytes;
  553.       bufferLen += bytes;
  554.       }
  555.  
  556.    bytes = PlaceInt( hashStringPtr, (LS_ULONG) unitsReserved );
  557.    hashStringPtr += bytes;
  558.    bufferLen += bytes;
  559.  
  560.    strcpy( hashStringPtr, logComment );
  561.    bufferLen += strlen( logComment );
  562.    hashStringPtr += strlen( logComment );
  563.  
  564.    bytes = PlaceInt( hashStringPtr, (LS_ULONG) unitsGranted );
  565.    hashStringPtr += bytes;
  566.    bufferLen += bytes;
  567.  
  568.    bytes = PlaceInt( hashStringPtr, (LS_ULONG) status );
  569.    hashStringPtr += bytes;
  570.    bufferLen += bytes;
  571.  
  572.    bytes = PlaceInt( hashStringPtr, (LS_ULONG) R );
  573.    hashStringPtr += bytes;
  574.    bufferLen += bytes;
  575.  
  576.    bytes = PlaceInt( hashStringPtr, (LS_ULONG) X );
  577.    hashStringPtr += bytes;
  578.    bufferLen += bytes;
  579.  
  580.    for ( i=0; i<4; i++ )
  581.       {
  582.       *hashStringPtr = secret[i];
  583.       hashStringPtr++;
  584.       bufferLen++;
  585.       }
  586.  
  587.  
  588.    /*
  589.     * Compute the message digest.
  590.     */
  591.    MD4Init(&MD);
  592.    MD4Update(
  593.       (MD4_CTX *) &MD,
  594.       (unsigned char *) hashString,
  595.       (unsigned int) bufferLen );
  596.    MD4Final(
  597.       digest,
  598.       (MD4_CTX *) &MD);
  599.  
  600.    /*
  601.     * Compare the digest with the one on the challenge
  602.     */
  603.    j = 0 ;
  604.    for( i = 0; i < DIGESTLEN; i++ )
  605.     {
  606.       if( digest[i] != challenge->ChallengeData.MsgDigest.MessageDigest[i] )
  607.          break ;
  608.       j++ ;
  609.     }
  610.  
  611.    if( j == DIGESTLEN )
  612.       return( 1 );
  613.  
  614.    return( 0 );
  615. }
  616.  
  617. /*
  618.  * swap bytes
  619.  */
  620. void swap( LS_STR FAR *byte1, LS_STR FAR *byte2 )
  621. {
  622.    LS_STR           tmp;
  623.  
  624.    tmp = *byte2;
  625.    *byte2 = *byte1;
  626.    *byte1 = tmp;
  627. }
  628.  
  629.  
  630.  
  631. /*
  632.  * Places integer in byte buffer, swapping bytes if necessary
  633.  */
  634. int PlaceInt( char FAR *buffer, LS_ULONG value )
  635. {
  636.    if ( littleEndian )
  637.       {
  638.       swap(&(((char FAR *) &value)[0]), &(((char FAR *) &value)[3]));
  639.       swap(&(((char FAR *) &value)[1]), &(((char FAR *) &value)[2]));
  640.       }
  641.  
  642.    memcpy( buffer, &value, sizeof( LS_ULONG ) );
  643.  
  644.    return( (int) sizeof( LS_ULONG ) );
  645. }
  646.