/******************************************************************************/
/*                                                                            */
/*  PKCSCFG.C - Configure GSO for Smart Card                                  */
/*                                                                            */
/*                                                                            */
/*  DESCRIPTION:                                                              */
/*                                                                            */
/*  The following code performs Security Officer function for IBM's Global    */
/*  Sign On product.  This function is compatible with GSO version 2.0 for    */
/*  non-pki based authentication where GSO uses DCE authentication.  For      */
/*  operations that set the user password, the user must have signed on       */
/*  with GSO administrator authority before executing this program.           */
/*                                                                            */
/*  HOW TO BUILD THE PROGRAM YOURSELF:                                        */
/*                                                                            */
/*   The following files are required to build this sample program:           */
/*                                                                            */
/*     PKCSCFG.C      The main program source code (this file)                */
/*     GSOPKCS.H      Include file with common access definitions to the SC   */
/*     PKCSUTIL.H     PKCS#11 utility header file                             */
/*     PKCS11.H       PKCS#11 header file (and anything it requires)          */
/*     GSOGUI.H       Header for the GUI calls made by this program           */
/*                                                                            */
/*   The following code files are used for external requests:                 */
/*                                                                            */
/*     GSOPKCSF.C     GSO PKCS functions
/*     PKCSUTIL.C     Hides PKCS#11 interactions                              */
/*     GSOGUI.C       GUI calls made by this program                          */
/*     GSOGUI.RC      GUI Panel code                                          */
/*                                                                            */
/*   The following makefiles are used to build on various platforms:          */
/*                                                                            */
/*     MSWIN32.MAK use nmake.exe to build with MS visual C++ on WIN32         */
/*                                                                            */
/*  SOFTWARE/HARDWARE PREREQUISITES:                                          */
/*                                                                            */
/*    Windows 32 bit operating systems                                        */
/*    IBM or compatible 386 and up                                            */
/*                                                                            */
/*  ADDITIONAL INFORMATION:                                                   */
/*                                                                            */
/*                                                                            */
/******************************************************************************/

/*------------------------ library include files -----------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include <process.h>        
#include <signal.h>  

/* Windows header files */
#include "windows.h"

/* PKCS#11 header files */
#include "pkcsjnh.h"

/*------------------------ module prototypes ---------------------------------*/
void   CheckParameters(int, char **);

/*------------------------ module variables ----------------------------------*/
#define         idlen           4096
#define         concat(x,y)     #x y
#ifdef DEBUG

#define DEBUG_MSG(STR)                printf(STR);
#define DEBUG_INFO(STR, DATA)         printf(STR, DATA);
#define DEBUG_INFO2(STR, DATA, DATA2) printf(STR, DATA, DATA2);

#else

#define DEBUG_MSG(STR)                              
#define DEBUG_INFO(STR, DATA)                              
#define DEBUG_INFO2(STR, DATA, DATA2)                            

#endif
int OPERATION   = 0;                         /* Operation                     */    
unsigned char addr[65];                      /* File Address                  */
CK_SLOT_ID            slot;                   /* Cryptoki Slot           */
CK_SESSION_HANDLE     shandle;                /* Cryptoki Session Handle */
  
/*============================================================================*/
/* Check command line parameters                                              */
/*============================================================================*/
void CheckParameters(int argc, char **argv)
{
  while (argc-- > 1)
  {
    if (*argv[argc]=='/' || *argv[argc]=='-' || *argv[argc]=='?')
    {
      switch (*++argv[argc])
      {
	case '1': OPERATION = 1; break;
	case '2': OPERATION = 2; break;

	default:  puts("PKCSCLNT is the client side PKCS driver program.\n"
		       "Use /<option> or -<option> (case insensitive)\n"
		       " /1   : Configure GSO PKCS for the SO console\n"
		       " /2   : Configure GSO PKCS for the client\n");
		  exit(0);                                    
      }
    }
    /* This is for the name of the file containing data */
    else                                  
    {
      if (strlen(argv[argc])<=64)
      {
	strcpy((char *)&addr,argv[argc]);
      }
    } 
  }
}

/*============================================================================*/
int check_pkcs(void * ptr)
{
    CK_RV               rv;
    CK_SLOT_ID          slot = 1;
    CK_SLOT_INFO        slot_info;
    CK_TOKEN_INFO       token_info;
    CK_SESSION_HANDLE   session;
    CK_MECHANISM_TYPE   mechanismlist;
    CK_ULONG            nummechanisms;

    DEBUG_MSG("Enter check_pkcs\n");

    DEBUG_MSG("About to initialize cryptoki\n");
    rv = C_Initialize(NULL);
    DEBUG_INFO("RC from C_Initialize = %x\n", rv);

    DEBUG_MSG("About to open session with the card\n");
    rv = C_OpenSession(slot, CKF_RW_SESSION, 0, 0, &session);
    DEBUG_INFO("RC from open session %x\n", rv);
    DEBUG_INFO("Session opened is %x\n", session);

    DEBUG_INFO("Getting slot info for slot %d\n", slot);
    rv = C_GetSlotInfo(slot, &slot_info);
    DEBUG_INFO("Slot Description %s\n", slot_info.slotDescription);
    DEBUG_INFO("Slot Manufacturer ID %s\n", slot_info.manufacturerID);
    DEBUG_INFO("Slot Flags %x\n", slot_info.flags);
    
    DEBUG_INFO("Getting token info for slot %d\n", slot);
    rv = C_GetTokenInfo(slot, &token_info);
    DEBUG_INFO("Token Label %s\n", token_info.label);
    DEBUG_INFO("Token Manufacturer ID %s\n", token_info.manufacturerID);
    DEBUG_INFO("Token Model %s\n", token_info.model);
    DEBUG_INFO("Token Serial %s\n", token_info.serialNumber);
    DEBUG_INFO("Token flags %x\n", token_info.flags);
    DEBUG_INFO("Max sessions %d\n", token_info.ulMaxSessionCount);

    DEBUG_MSG("Getting Number of mechanisms\n");
    rv = C_GetMechanismList(slot, NULL_PTR, &nummechanisms);
    DEBUG_INFO("Number of mechanisms = %d\n", nummechanisms);

    DEBUG_MSG("Getting list of mechanisms\n");
    rv = C_GetMechanismList(slot, &mechanismlist, &nummechanisms);
    DEBUG_INFO("Number of mechanisms = %d\n", nummechanisms);
    if (nummechanisms > 0) {
	DEBUG_INFO("Mechanism 1 is %d\n", mechanismlist);
    } else {    
	DEBUG_MSG("No mechanisms defined\n");
    }

    DEBUG_MSG("Logging on as SO\n");
    rv = C_Login(session, CKU_SO, NULL_PTR, 0);
    DEBUG_INFO("rv from login = %x\n", rv);

    DEBUG_MSG("Exit check_pkcs\n");
    return 0;
}

/*============================================================================*/
int main(int argc, char **argv)
{ 
  CK_RV                 rv;                     /* Cryptoki return values  */        

  CheckParameters(argc, argv);               /* check command line parameters */

  switch (OPERATION)
  {
    case 1   : DEBUG_MSG("C_Init\n"); rv = check_pkcs(NULL); break;
    case 2       : break;

    default:  DEBUG_MSG("Seeing if Litronic files exist:\n");
	      break;                                                                          
  }
  
  return 0;
}

