Introduction


The example 'C' program certstack.c demonstrates how to load a list of X509 certificates, using the OpenSSL library functions. This is typically useful when we need to work with a collection of trusted Root CA certificates.

Example Code Listing


/* ------------------------------------------------------------ *
 * file:        certstack.c                                     *
 * purpose:     Example how to handle a pile of CA certificates *
 * author:      07/16/2012 Frank4DD                             *
 *                                                              *
 * gcc -o certstack certstack.c -lssl -lcrypto                  *
 * ------------------------------------------------------------ */

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>

int main() {

  STACK_OF(X509_INFO) *certstack;
  const char   ca_filestr[] = "./cabundle.pem";
  X509_INFO *stack_item     = NULL;
  X509_NAME    *certsubject = NULL;
  BIO             *stackbio = NULL;
  BIO               *outbio = NULL;
  X509                *cert = NULL;
  int i;

  /* ---------------------------------------------------------- *
   * These function calls initialize openssl for correct work.  *
   * ---------------------------------------------------------- */
  OpenSSL_add_all_algorithms();
  ERR_load_BIO_strings();
  ERR_load_crypto_strings();

  /* ---------------------------------------------------------- *
   * Create the Input/Output BIO's.                             *
   * ---------------------------------------------------------- */
  stackbio = BIO_new(BIO_s_file());
  outbio   = BIO_new_fp(stdout, BIO_NOCLOSE);

  /* ---------------------------------------------------------- *
   * Load the file with the list of certificates in PEM format  *
   * ---------------------------------------------------------- */
  if (BIO_read_filename(stackbio, ca_filestr) <= 0) {
    BIO_printf(outbio, "Error loading cert bundle into memory\n");
    exit(-1);
  }

  certstack = PEM_X509_INFO_read_bio(stackbio, NULL, NULL, NULL);

  /* ---------------------------------------------------------- *
   * Count the number of certs that are now on the stack        *
   * ---------------------------------------------------------- */
   BIO_printf(outbio, "# of stack certs: %d\n",
                      sk_X509_INFO_num(certstack));

  /* ---------------------------------------------------------- *
   * Cycle through the stack to display various cert data       *
   * ---------------------------------------------------------- */
  for (i = 0; i < sk_X509_INFO_num(certstack); i++) {
    char subject_cn[256] = "** n/a **";
    long cert_version;

    stack_item = sk_X509_INFO_value(certstack, i);

    certsubject = X509_get_subject_name(stack_item->x509);
    X509_NAME_get_text_by_NID(certsubject, NID_commonName,
                                           subject_cn, 256);
    cert_version = (X509_get_version(stack_item->x509)+1);

    BIO_printf(outbio, "Cert #%.2d v%ld CN: %.70s\n", i, 
                                  cert_version, subject_cn);
  }

  /* ---------------------------------------------------------- *
   * Free up the resources                                      *
   * ---------------------------------------------------------- */
  sk_X509_INFO_pop_free(certstack, X509_INFO_free);
  X509_free(cert);
  BIO_free_all(stackbio);
  BIO_free_all(outbio);
  exit(0);
}

Compiling the Code


Compile the test program with:

> gcc -o certstack certstack.c -lssl -lcrypto

Example Output


The program expects a certificate file called cabundle.pem in the same directory. After the file is loaded into a stack, we will cycle through it and print a list of the subjects common name (CN). I used the current Verisign CA certificate bundle for the test example below.

fm@susie114:~> ./certstack
# of stack certs: 41
Cert #00 v1 CN: ** n/a **
Cert #01 v1 CN: ** n/a **
Cert #02 v1 CN: ** n/a **
Cert #03 v1 CN: ** n/a **
Cert #04 v1 CN: VeriSign Class 3 Public Primary Certification Authority - G3
Cert #05 v1 CN: VeriSign Class 4 Public Primary Certification Authority - G3
Cert #06 v1 CN: VeriSign Class 1 Public Primary Certification Authority - G3
Cert #07 v1 CN: VeriSign Class 2 Public Primary Certification Authority - G3
Cert #08 v3 CN: VeriSign Class 3 Public Primary Certification Authority - G5
Cert #09 v1 CN: ** n/a **
Cert #10 v1 CN: ** n/a **
Cert #11 v1 CN: ** n/a **
Cert #12 v3 CN: VeriSign Universal Root Certification Authority
Cert #13 v3 CN: VeriSign Class 3 Public Primary Certification Authority - G4
Cert #14 v3 CN: Thawte Personal Freemail CA
Cert #15 v1 CN: ** n/a **
Cert #16 v3 CN: thawte Primary Root CA
Cert #17 v3 CN: Thawte Timestamping CA
Cert #18 v3 CN: thawte Primary Root CA - G2
Cert #19 v3 CN: Thawte Personal Premium CA
Cert #20 v3 CN: thawte Primary Root CA - G3
Cert #21 v3 CN: Thawte Premium Server CA
Cert #22 v3 CN: Thawte Personal Basic CA
Cert #23 v3 CN: Thawte Server CA
Cert #24 v3 CN: ** n/a **
Cert #25 v3 CN: ** n/a **
Cert #26 v3 CN: GeoTrust Global CA
Cert #27 v3 CN: Equifax Secure Global eBusiness CA-1
Cert #28 v3 CN: GeoTrust Global CA 2
Cert #29 v3 CN: GeoTrust Universal CA
Cert #30 v3 CN: GeoTrust Primary Certification Authority
Cert #31 v3 CN: GeoTrust Primary Certification Authority - G3
Cert #32 v3 CN: GeoTrust Primary Certification Authority
Cert #33 v3 CN: Equifax Secure eBusiness CA-1
Cert #34 v3 CN: GeoTrust Primary Certification Authority - G2
Cert #35 v3 CN: GeoTrust Universal CA 2
Cert #36 v3 CN: GeoTrust True Credentials CA 2
Cert #37 v3 CN: GeoTrust Mobile Device Root - Privileged
Cert #38 v3 CN: GeoTrust CA for UTI
Cert #39 v3 CN: GeoTrust Mobile Device Root - Unprivileged
Cert #40 v3 CN: GeoTrust CA for Adobe

Remarks


Another good example of a Root CA certificate bundle is the one included with the Linux distribution. In OpenSuse, this is the file /etc/ssl/ca-bundle.pem .


OpenSSL Logo

Topics:

Source:

Documentation: