RSA BSAFE Cert-C

Certificate Components for C

Crypto-C 6.2.1 Developer's Guide
Search

ldap2.c

Connects to an LDAP server and downloads certificates and

CRLs. Uses the APIs that are designed to eliminate dependency on the Codebase database software.

/* $Id: ldap2.c,v 1.5 2004/03/02 05:18:39 gsingh Exp $ */
/* ldap2.c
** Copyright (c) 1999-2003, RSA Security Inc.
**
** This file is used to demonstrate how to interface to an RSA Security
** licensed development product.  You have a royalty-free right to use,
** modify, reproduce and distribute this demonstration file (including
** any modified version), provided that you agree that RSA Security has
** no warranty, implied or otherwise, or liability for this demonstration
** file or any modified version.
**
** This program connects to an LDAP server and downloads certificates and
** CRLs.  This sample uses the APIs that are designed to eliminate the
** dependency on the Codebase database software.
**
** When compiling, define the macro RSA_REQUIRE_FILE_LOG (-D compile
** option, or equivelent) to force the program to return an error code
** if file logging cannot be initialized.  For example, if the file
** containing the log message format strings cannot be located (certc.msg
** or equivalent).
*/

#include "certc.h"
#include "ldapapi.h"
#include "filelog.h"
#include "demoutil.h"
#include "pkiutil.h"
#include "certutil.h"
#include "crlutil.h"
#include "nameutil.h"

/*  This is used to identify the database service which has the LDAP_DATA
 *  parameters we wish to use.
 */
#define LDAP_SERVICE_NAME "LDAP provider"

/*  Specify URL in the form ldap://hostname:portNumber/searchRoot
 */
#define DEFAULT_LDAP_URL "ldap://century.rsa.com:389/c=US"

/*  LDAP_OPTIONS_INFO values  */
#define AUTH_TYPE 0
#define SIZE_LIMIT 0  /* no limit */
#define TIME_LIMIT 0  /* no limit */
#define B_DN_AT "c,o,ou,cn"
#define SEARCH_FILTER_AT "c,o,ou,cn"
#define CERT_ATTRS "userCertificate,cacertificate"
#define CRL_ATTRS "certificateRevocationList"
#define DISCONNECT_BEFORE_CONNECT 0
#define USER_NAME ""
#define USER_PASSWORD ""

/*  SetLdapStringField copies the src into dest.  dest must already
 *  have been allocated memory in the size of destLen.
 */
static int SetLdapStringField (char *dest, char *src, unsigned int destLen);

int main (int argc, char *argv[])
{
  int status = 0;
  CERTC_CTX ctx = NULL;

  FILE_LOG_PARAMS logParams = {NULL, NULL};
  SERVICE_HANDLER logHandler = {
    SPT_LOG, "Default File Log", S_InitializeFileLog
  };

  LDAP_DATA2 ldapData2 = {0};
  SERVICE_HANDLER ldapHandler = {
    SPT_DATABASE, LDAP_SERVICE_NAME, S_InitializeLDAP2
  };
  
  SERVICE ldapService = NULL;

  unsigned int numCerts = 0, i = 0, numCrls = 0, j = 0;
  UINT4 currentTime = 0;

  CERT_FIELDS certFields;
  CERT_OBJ certObj = NULL;
  CRL_OBJ crlObj = NULL;
  LIST_OBJ certs = NULL, crls = NULL;
  NAME_OBJ baseDn = NULL;

  status = RSA_SetOptions (&logParams, argc, argv);
  if (status != 0)
    goto CLEANUP;

  status = C_InitializeCertC (NULL, NULL, 0, &ctx);
  if (status != 0)
    goto CLEANUP;

  /* Attempt to initialize file logging, but unless RSA_REQUIRE_FILE_LOG is
   * defined, treat it as a non-fatal condition.
   */
  status = C_RegisterService (ctx, &logHandler, (POINTER)&logParams,
                              SERVICE_ORDER_FIRST);
#ifdef RSA_REQUIRE_FILE_LOG
  if (status != 0)
    goto CLEANUP;
#endif

  RSA_PrintMessage ("LDAP Cert and CRL Retrieval Example\n");
  RSA_PrintMessage ("===================================\n");

  /* Begin by filling in the LDAP_DATA2 fields */
  RSA_PrintMessage ("Supply the LDAP server URL in the following form:\n");
  RSA_PrintMessage ("  ldap://hostname:portNumber/searchRoot\n");
  status = RSA_CreateTransportInfoFieldsPrompt (&ldapData2.ldapTransportInfo,
                                                DEFAULT_LDAP_URL);
  if (status != 0)
    goto CLEANUP;
  
  ldapData2.ldapOptionsInfo.authType = AUTH_TYPE;
  ldapData2.ldapOptionsInfo.sizeLimit = SIZE_LIMIT;
  ldapData2.ldapOptionsInfo.timeLimit = TIME_LIMIT;

  status = SetLdapStringField (ldapData2.ldapOptionsInfo.baseDNAttrs, B_DN_AT,
                               MAXLEN_LD_STR);
  if (status != 0)
    goto CLEANUP;

  status = SetLdapStringField (ldapData2.ldapOptionsInfo.searchFilterAttrs,
                               SEARCH_FILTER_AT, MAXLEN_LD_STR);
  if (status != 0)
    goto CLEANUP;

  status = SetLdapStringField (ldapData2.ldapOptionsInfo.certificateAttrs,
                               CERT_ATTRS, MAXLEN_LD_STR);
  if (status != 0)
    goto CLEANUP;

  status = SetLdapStringField
             (ldapData2.ldapOptionsInfo.certificateRevocationAttrs,
              CRL_ATTRS, MAXLEN_LD_STR);
  if (status != 0)
    goto CLEANUP;

  ldapData2.ldapOptionsInfo.disconnectBeforeConnect =
    DISCONNECT_BEFORE_CONNECT;

  status = SetLdapStringField (ldapData2.ldapOptionsInfo.userName,
                               USER_NAME, MAXLEN_LD_DN);
  if (status != 0)
    goto CLEANUP;

  status = SetLdapStringField (ldapData2.ldapOptionsInfo.userPassword,
                               USER_PASSWORD, MAXLEN_LD_PASSPHRASE);
  if (status != 0)
    goto CLEANUP;
  
  RSA_PrintMessage ("Registering LDAP database instance...\n");
  status = C_RegisterService (ctx, &ldapHandler, (POINTER)&ldapData2,
                              SERVICE_ORDER_FIRST);
  if (status != 0)
    goto CLEANUP;

  /*  In order to use our LDAP database service, we must obtain a SERVICE
   *  handle.
   */
  status = C_BindService (ctx, SPT_DATABASE, LDAP_SERVICE_NAME, &ldapService);
  if (status != 0)
    goto CLEANUP;

  /*  Now we can use some calls (such as C_SelectCertByIssuerSerial,
   *  C_SelectCertBySubject, C_SelectCertByExtensions, C_SelectCRLByIssuerTime)
   *  which operate on databases through a bound database SERVICE.
   */
  status = C_CreateListObject (&certs);
  if (status != 0)
    goto CLEANUP;

  /* Use a blank name object to retrieve all entries */
  status = C_CreateNameObject (&baseDn);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("Requesting certs...\n");
  status = C_SelectCertByExtensions (ldapService, baseDn, NULL, certs);
  if (status != 0)
    goto CLEANUP;

  status = C_GetListObjectCount (certs, &numCerts);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("Retrieved %d certs\n", numCerts);
  status = RSA_PrintCertList (certs);
  if (status != 0)
    goto CLEANUP;

  status = C_CreateListObject (&crls);
  if (status != 0)
    goto CLEANUP;

  for (i = 0; i < numCerts; i++) {
    status = C_GetListObjectEntry (certs, i, (POINTER *)&certObj);
    if (status != 0)
      goto CLEANUP;

    RSA_PrintMessage ("\nCert #%d\n", i + 1);
    RSA_PrintCertObject (certObj);

    status = RSA_SaveCertObjToFile (certObj);
    if (status != 0 && status != RSA_DEMO_E_CANCEL)
      goto CLEANUP;

    status = C_GetCertFields (certObj, &certFields);
    if (status != 0)
      goto CLEANUP;

    RSA_PrintMessage ("\nRetrieving current CRLs issued by:\n");
    RSA_PrintNameObject (NULL, certFields.subjectName);

    T_time (&currentTime);

    RSA_PrintMessage ("\nRequesting CRLs...\n");
    status = C_SelectCRLByIssuerTime (ldapService, certFields.subjectName,
                                      currentTime, crls);
    if (status == E_NOT_FOUND) {
      RSA_PrintMessage ("No CRLs...\n");
      status = 0;
      continue;
    } else if (status != 0)
      goto CLEANUP;

    status = C_GetListObjectCount (crls, &numCrls);
    if (status != 0)
      goto CLEANUP;

    RSA_PrintMessage ("Retrieved %d CRLs\n", numCrls);
    status = RSA_PrintCrlList (crls);
    if (status != 0)
      goto CLEANUP;

    for (j = 0; j < numCrls; j++) {
      status = C_GetListObjectEntry (crls, j, (POINTER *)&crlObj);
      if (status != 0)
        goto CLEANUP;

      status = RSA_SaveCrlObjToFile (crlObj);
      if (status != 0 && status != RSA_DEMO_E_CANCEL)
        goto CLEANUP;
    }
  }

CLEANUP:
  if (status != 0)
    RSA_PrintError ("ldap2.c", status);

  RSA_DestroyTransportInfoFields (&ldapData2.ldapTransportInfo);
  
  C_DestroyNameObject (&baseDn);
  C_DestroyListObject (&certs);
  C_DestroyListObject (&crls);
  C_UnbindService (&ldapService);
  C_FinalizeCertC (&ctx);

  return status;
}  /* end main */

/* See function declaration at the top for a description */
static int SetLdapStringField (char *dest, char *src, unsigned int destLen)
{
  unsigned int srcLen = T_strlen (src);

  if (destLen < srcLen)
    return RSA_DEMO_E_BUFFER_TOO_SMALL;

  T_strcpy (dest, src);

  return 0;
}  /* end SetLdapStringField */

Copyright (c) 1999-2005 RSA Security Inc. All rights reserved. 067-001001-2720-001-000 - 2.7.2