RSA BSAFE Cert-C

Certificate Components for C

Crypto-C 6.2.1 Developer's Guide
Search

ldap.c

Connects to an LDAP server and downloads certificates and CRLs.

/* $Id: ldap.c,v 1.5 2004/03/02 05:18:39 gsingh Exp $ */
/* ldap.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.  You must fill in the appopriate NET_ADDR and SEARCH_ROOT below.
**
** 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 "certutil.h"
#include "crlutil.h"
#include "nameutil.h"

#define SP_COUNT 1

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

/*  LDAP_INIT_PARAMS info  */
#define DATABASE_NAME "ldapdb"
#define LDAP_SOURCE "LDAP Test"
#define USER_NAME ""
#define USER_PASSWORD ""

/*  LDAP_DATA info  */
#define DESCRIPTIVE_NAME LDAP_SOURCE
#define NET_ADDR "century.rsa.com"
#define PORT_NUMBER 389
#define AUTH_TYPE 0
#define SIZE_LIMIT 200
#define TIME_LIMIT 0  /* no limit */
#define B_DN_AT "c,o,ou,cn"
#define SEARCH_ROOT "c=US"
#define SEARCH_FILTER_AT "c,o,ou,cn"
#define CERT_ATTRS "userCertificate,cacertificate"
#define CRL_ATTRS "certificateRevocationList"
#define SEARCH_PRIORITY 1
#define DISCONNECT_BEFORE_CONNECT 0

/*  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;
  SERVICE_HANDLER spTable[SP_COUNT];
  LDAP_INIT_PARAMS initParams;
  LDAP_DATA ldapData;

  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;

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

  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

  /*  The first thing we must do is to Create an LDAP Config Record, so that
   *  when we call C_InitializeCertC or C_RegisterService to register the LDAP
   *  configuration database, there is a record available.  Cert-C will use
   *  the LDAP_INIT_PARAMS.sourceName to look for a record in the
   *  LDAP_INIT_PARAMS.cfgDbName database which has an
   *  LDAP_DATA.descriptiveName identical to the sourceName.
   */
  status = SetLdapStringField (ldapData.descriptiveName, DESCRIPTIVE_NAME,
                               MAXLEN_LD_NAME);
  if (status != 0)
    goto CLEANUP;

  status = SetLdapStringField (ldapData.networkAddress, NET_ADDR,
                               MAXLEN_LD_NETADDR);
  if (status != 0)
    goto CLEANUP;

  ldapData.portNo = PORT_NUMBER;
  ldapData.authType = AUTH_TYPE;
  ldapData.sizeLimit = SIZE_LIMIT;
  ldapData.timeLimit = TIME_LIMIT;

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

  status = SetLdapStringField (ldapData.searchRoot, SEARCH_ROOT,
                               MAXLEN_LD_STR);
  if (status != 0)
    goto CLEANUP;

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

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

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

  ldapData.searchPriority = SEARCH_PRIORITY;
  ldapData.disconnectBeforeConnect = DISCONNECT_BEFORE_CONNECT;
  ldapData.otherData.data = NULL;
  ldapData.otherData.len = 0;

  /*  Insert a record into the LDAP configuration database.  This record will
   *  be accessed by the LDAP_DATA.descriptiveName field.
   */
  status = S_InsertLDAPConfigRecord (ctx, DATABASE_NAME, &ldapData);

  spTable[0].type = SPT_DATABASE;
  spTable[0].name = LDAP_SERVICE_NAME;
  spTable[0].Initialize = S_InitializeLDAPSource;

  /* initialize LDAP_INIT_PARAMS with info given above */
  status = SetLdapStringField (initParams.cfgDbName, DATABASE_NAME,
                               MAXLEN_LD_CFG_DBNAME);
  if (status != 0)
    goto CLEANUP;

  /*  LDAP_SOURCE, defined above, will be used to find one of the records in
   *  the LDAP configuration database and will be effectively be registered
   *  as a database provider.
   */
  status = SetLdapStringField (initParams.sourceName, LDAP_SOURCE,
                               MAXLEN_LD_NAME);
  if (status != 0)
    goto CLEANUP;

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

  status = SetLdapStringField (initParams.userPassword, USER_PASSWORD,
                               MAXLEN_LD_PASSPHRASE);
  if (status != 0)
    goto CLEANUP;

  /*  Register the LDAP database service, whose parameters are the LDAP_DATA
   *  parameters in the LDAP configuration database whose descriptiveName is
   *  equal to the sourceName.
   */
  status = C_RegisterService (ctx, spTable, (POINTER)&initParams,
                              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 from %s...\n", NET_ADDR);
  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 from %s...\n", NET_ADDR);
    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 ("ldap.c", status);

  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