//---------------------------------------------------------------------------
#include <stdio.h>
#include <time.h>
#ifdef _WIN32
  #include <windows.h>
  #define strlib "lib\\strlib.dll"
#else
  #define GetProcAddress dlsym
  #define FreeLibrary dlclose
  #include <string>
  #include  <unistd.h>
  #include  <dlfcn.h>
  #define strlib "lib/libstr.1.0.0.sl"
  #define _cdecl
  #define TRUE 1
  #define FALSE 0
  typedef void* HINSTANCE;
  typedef unsigned long       DWORD;
  typedef char CHAR;
  typedef unsigned char       BYTE;
#endif

#define CRYPT_VERIFYCONTEXT     0xF0000000
#define CRYPT_NEWKEYSET         0x00000008
#define CRYPT_DELETEKEYSET      0x00000010
#define CRYPT_MACHINE_KEYSET    0x00000020
#define CRYPT_SILENT            0x00000040
#define CRT_STORE_PROV_LDAP     0
#define RStoreType "t=R;"
#define AStoreType "t=A;"
#define StoreHost "127.0.0.1"
#define StorePort "62222"
#define DN "C=KZ;O=LOCAL;CN=ROOT;"
typedef unsigned long hCERTSTORE;
typedef unsigned long HCRYPTPROV;
//---------------------------------------------------------------------------
  typedef int (_cdecl *D_CrtOpenStore)
                                  (DWORD StoreProvider,
                                   HCRYPTPROV hProv,
                                   unsigned long dwFlags,
                                   bool  bFlag,
                                   const void *pvParam,
                                   hCERTSTORE *phStore);
  typedef int (_cdecl *D_CrtCloseStore)(hCERTSTORE *phStore);
  typedef int (_cdecl *D_CrtSetStorePropertyExt)(const hCERTSTORE hStore,
                                             const unsigned long Flags,
                                             const char *DName,
                                             const char *host,
                                             const char *port,
                                             const int timeOut,
                                             const char *name,
                                             const char *pass);
  typedef char* (_cdecl *D_ErrorString)(const int err);
  typedef DWORD (_cdecl *D_CSPOpenContext)(HCRYPTPROV *phProv,
                                       CHAR *pszContainer,
                                       DWORD dwProvType,
                                       DWORD dwProvParam,
                                       DWORD dwFlags,
                                       BYTE * pbSignature,
                                       DWORD dwSigLen,
                                       BYTE * pbContainer,
                                       DWORD * dwContLen,
                                       HINSTANCE *phLib);
  typedef int (_cdecl *D_CSPSetProvParam)(DWORD param, BYTE  *pbData);
  typedef int (_cdecl *D_GetMYCertificate)(hCERTSTORE hStore,
                                         const char *DName,
                                         const unsigned long keySpec,
                                         const bool isCA,
                                         unsigned char *certBody,
                                         unsigned long *bodySize);
  typedef int (_cdecl *D_CSPCloseContext)(HCRYPTPROV *phProv);
  typedef int (_cdecl *D_GetCurrentCRL)
                         (hCERTSTORE hStore,
                           const char *DName,
                           unsigned char *crlBody,
                           unsigned long *bodySize);
  typedef int (_cdecl *D_GetCRLnumber)
                           (const hCERTSTORE hStore,
                           const unsigned char *crlBody,
                           const unsigned long bodySize,
                           unsigned long *number);
  typedef int (_cdecl *D_GetCRLUpDates)
                          (const hCERTSTORE hStore,
                           const unsigned char *crlBody,
                           const unsigned long bodySize,
                           char *thisUpdate,
                           char *nextUpdate);
  typedef int (_cdecl *D_GetCRLIssuerInfo)
                            (const hCERTSTORE hStore,
                             const unsigned char *crlBody,
                             const unsigned long bodySize,
                             char *DName);
  typedef int (_cdecl *D_GetCRLDistrPoint)
                            (const hCERTSTORE hStore,
                             const unsigned char *crlBody,
                             const unsigned long bodySize,
                             char *CApoint);
  typedef int (_cdecl *D_GetCRLIssuerNumber)
                             (const hCERTSTORE hStore,
                             const unsigned char *crlBody,
                             const unsigned long bodySize,
                             unsigned char *serNum,
                             unsigned long *numSize);
  //---------------------------------------------------------------------------
  D_CrtOpenStore            CrtOpenStore                =0;
  D_CrtCloseStore           CrtCloseStore               =0;
  D_CrtSetStorePropertyExt  CrtSetStorePropertyExt      =0;
  D_ErrorString             ErrorString                 =0;
  D_CSPOpenContext          CSPOpenContext              =0;
  D_CSPSetProvParam         CSPSetProvParam             =0;
  D_GetMYCertificate        GetMYCertificate            =0;
  D_CSPCloseContext         CSPCloseContext             =0;
  D_GetCurrentCRL           GetCurrentCRL               =0;
  D_GetCRLnumber            GetCRLnumber                =0;
  D_GetCRLUpDates           GetCRLUpDates               =0;
  D_GetCRLIssuerInfo        GetCRLIssuerInfo            =0;
  D_GetCRLDistrPoint        GetCRLDistrPoint            =0;
  D_GetCRLIssuerNumber      GetCRLIssuerNumber          =0;
//---------------------------------------------------------------------------
HINSTANCE load_lib(char *lib)
{
   #ifdef _WIN32
	  return LoadLibraryA(lib);
   #else
	  return dlopen(lib,RTLD_LAZY);
   #endif
}
//------------------------------------------------------------------------------
void lib_free( HINSTANCE Instance )
{
#ifdef _WIN32
  FreeLibrary(Instance);
#else
  dlclose(Instance);
#endif
}
//---------------------------------------------------------------------------
int        LoadLib();
void b2h(unsigned char *inbuf, long  insize, unsigned char *oubuf);
HINSTANCE hInstSTRLib=NULL;
//---------------------------------------------------------------------------
//Получить номер СОСа
int CRLNumber (hCERTSTORE Store,unsigned char *Body,unsigned long Size)
{
int code, ret=0;
unsigned long num;
if (!Body) return 1;
try
  {
  code = GetCRLnumber (Store, Body, Size, &num);
  if (code) throw code;
  printf("GetCRLnumber: Current CLR number = %d\n", num);
  }
catch (int err)
 {
 ret = err;
 printf("%s [GetCRLnumber: error = %d]\n",ErrorString(ret), ret);
 }
return ret;
}
//---------------------------------------------------------------------------
//Получить время действия СОСа
int CRLUpDates (hCERTSTORE Store, unsigned char *Body, unsigned long Size)
{
int code, ret = 0;
char t_date[64], n_date[64];
if (!Body) return 1;
try
  {
  code  = GetCRLUpDates (Store, Body, Size, t_date, n_date);
  if (code) throw code;
  printf("GetCRLUpDates: thisUpdate = %s\nnextUpdate = %s\n", t_date, n_date);
  }
catch (int err)
 {
 ret = err;
 printf("%s [GetCRLUpDates: error = %d]\n",ErrorString(ret), ret);
 }
return ret;
}
//---------------------------------------------------------------------------
//получить информацию о выпустившем CRL
int CRLIssuerInfo (hCERTSTORE Store, unsigned char *Body, unsigned long Size)
{
int code, ret = 0;
char DName [256];
try
  {
  code = GetCRLIssuerInfo(Store, Body, Size,DName);
  if (code) throw code;
  printf("GetCRLIssuerInfo: Issuer = %s\n",DName);
  }
catch (int err)
 {
 ret = err;
 printf("%s [GetCRLIssuerInfo: error = %d]\n",ErrorString(ret), ret);
 }
return ret;
}
//---------------------------------------------------------------------------
//Получить адрес УЦ
int CRLDistrPoint (hCERTSTORE *Store, unsigned char *Body, unsigned long Size)
{
int code, ret =0;
char DName [256];
try
  {
  code  = GetCRLDistrPoint(*Store, Body,Size, DName);
  if (code) throw code;
  printf("GetCRLDistrPoint = %s\n",DName);
  }
catch (int err)
 {
 ret = err;
 printf("%s [GetCRLDistrPoint: error = %d]\n",ErrorString(ret), ret);
 }
return ret;
}
//---------------------------------------------------------------------------
//получить информацию о серийном номере выпустившего CRL
int CRLIssuerNumber (hCERTSTORE Store, unsigned char *Body, unsigned long Size)
{
int code, ret = 0, n;
unsigned char serNum[64];
unsigned char *hNum;
unsigned long numSize;
try
  {
  code = GetCRLIssuerNumber (Store,Body, Size, serNum, &numSize);
  if (code) throw code;
  hNum = (unsigned char*) calloc (numSize*2+1, sizeof(unsigned char));
  b2h(serNum,numSize,hNum);
  n = numSize*2;
  printf("Serial number = %s\nSerial number len = %d\n", hNum, n);
  if (hNum) free (hNum);
  }
catch (int err)
  {
  ret = err;
  printf("%s [GetCRLIssuerNumber: error = %d]", ErrorString(ret), ret);
  }
return ret;
}
//---------------------------------------------------------------------------
int main(int argc, char* argv[])
{
 int ret = 0;
 int code = 0;
 hCERTSTORE hStore = 0;
 HCRYPTPROV hP = 0;
 unsigned char *crlBody=NULL;
 unsigned long bodySize;
 try
 {
  //Загрузить библиотеку
  code = LoadLib();
  if( code )
    {
    printf ("[LoadLib: error = %d]\n",code);
    throw code;
    }
  //Открыть контекст CSP без загрузки прфайла
  code = CSPOpenContext(&hP,NULL, 25, 0, CRYPT_VERIFYCONTEXT, NULL, 0, NULL, 0, NULL);
  if( code )
    {
    printf("%s [CSPOpenContext: error = %d]\n",ErrorString(code), code);
    throw code;
    }
  // Открыть конекст хранилища
  code = CrtOpenStore(CRT_STORE_PROV_LDAP, hP, 0, false, NULL, &hStore);
  if( code )
    {
    printf("%s [CrtOpenStore: error = %d]\n",ErrorString(code), code);
    throw code;
    }
  // Установить параметры хранилища
  // функцию можно не вызывать, если, например, CRL будет загружен из файла или объявлен константой
  // в этом случае нет необходимости вызывать GetCurrentCRL, можно сразу перейти к получению номера СОСа
  code = CrtSetStorePropertyExt(hStore, 0, RStoreType, StoreHost, StorePort, 300, 0, 0);
  if( code )
    {
    printf("%s [CrtSetStorePropertyExt: error = %d]\n",ErrorString(code), code);
    throw code;
    }
  //Получить текущий СОС
  code  = GetCurrentCRL (hStore, DN, crlBody, &bodySize);
  if( code )
    {
    printf("%s [GetCurrentCRL: error = %d]\n",ErrorString(code), code);
    throw code;
    }
  crlBody = (unsigned char*) calloc (bodySize,sizeof(unsigned char));
  memset(crlBody,0,bodySize);
  code  = GetCurrentCRL (hStore, DN, crlBody,&bodySize);
  //Получить номер СОСа
  code = CRLNumber (hStore,crlBody,bodySize);
  //Получить время действия СОСа
  code  = CRLUpDates (hStore, crlBody, bodySize);
  //получить информацию о выпустившем CRL
  code = CRLIssuerInfo(hStore, crlBody, bodySize);
  //Получить адрес УЦ
  code  = CRLDistrPoint(&hStore, crlBody, bodySize);
  //получить информацию о серийном номере выпустившего CRL
  code = CRLIssuerNumber (hStore,crlBody, bodySize);
  //Если не было ошибки, то отозванные сертификаты хранятся в crlBody соответственно.
  }
 catch(int er){ret=er;}
 if (crlBody) free (crlBody);
 //закрыть контексты
 if( hStore ) { CrtCloseStore(&hStore); hStore = 0;}
 if( hP ) { CSPCloseContext(&hP); hP = 0;}
 if( hInstSTRLib ) { lib_free(hInstSTRLib); hInstSTRLib = NULL; }
 return ret;
}
//---------------------------------------------------------------------------
int LoadLib()
{
 int ret = 0;
 try
 {
  hInstSTRLib = load_lib(strlib);
  if( hInstSTRLib == NULL ) throw 1;
  CrtOpenStore = (D_CrtOpenStore) GetProcAddress (hInstSTRLib, "CrtOpenStore");
  if( CrtOpenStore == NULL ) throw 2;
  CrtCloseStore = (D_CrtCloseStore) GetProcAddress (hInstSTRLib, "CrtCloseStore");
  if( CrtCloseStore == NULL ) throw 3;
  CrtSetStorePropertyExt = (D_CrtSetStorePropertyExt) GetProcAddress (hInstSTRLib, "CrtSetStorePropertyExt");
  if( CrtSetStorePropertyExt == NULL ) throw 4;
  ErrorString = (D_ErrorString) GetProcAddress (hInstSTRLib, "ErrorString");
  if( ErrorString == NULL ) throw 5;
  CSPOpenContext = (D_CSPOpenContext) GetProcAddress (hInstSTRLib, "CSPOpenContext");
  if( CSPOpenContext == NULL ) throw 6;
  CSPSetProvParam = (D_CSPSetProvParam) GetProcAddress (hInstSTRLib, "CSPSetProvParam");
  if( CSPSetProvParam == NULL ) throw 7;
  CSPCloseContext = (D_CSPCloseContext) GetProcAddress (hInstSTRLib, "CSPCloseContext");
  if( CSPCloseContext == NULL ) throw 8;
  GetCurrentCRL = (D_GetCurrentCRL) GetProcAddress (hInstSTRLib, "GetCurrentCRL");
  if( GetCurrentCRL == NULL ) throw 9;
  GetCRLnumber = (D_GetCRLnumber) GetProcAddress (hInstSTRLib, "GetCRLnumber");
  if( GetCRLnumber == NULL ) throw 10;
  GetCRLUpDates = (D_GetCRLUpDates) GetProcAddress (hInstSTRLib, "GetCRLUpDates");
  if( GetCRLUpDates == NULL ) throw 11;
  GetCRLIssuerInfo = (D_GetCRLIssuerInfo) GetProcAddress (hInstSTRLib, "GetCRLIssuerInfo");
  if ( GetCRLIssuerInfo == NULL ) throw 12;
  GetCRLDistrPoint = (D_GetCRLDistrPoint) GetProcAddress (hInstSTRLib, "GetCRLDistrPoint");
  if (GetCRLDistrPoint == NULL) throw 13;
  GetCRLIssuerNumber = (D_GetCRLIssuerNumber) GetProcAddress (hInstSTRLib, "GetCRLIssuerNumber");
  if (GetCRLIssuerNumber == NULL) throw 14;
 }
 catch(int er){ret = er;}
 return ret;
}
//---------------------------------------------------------------------------
void b2h(unsigned char *inbuf, long  insize, unsigned char *oubuf)
{
 char *HAlf ="0123456789ABCDEF";
 long l;
 memset(oubuf,0,sizeof(oubuf));
 for (l=0;l<insize;l++) {
   oubuf[2*l]    =(unsigned char) HAlf[inbuf[(int) l]>>4];
   oubuf[(2*l)+1]=(unsigned char) HAlf[inbuf[(int) l]&0x0F];
 }
}
//---------------------------------------------------------------------------
