From f9abcda006eb71f30df14218a4a2588dbc41ceb5 Mon Sep 17 00:00:00 2001 From: David Sommerseth Date: Fri, 7 Jun 2013 17:29:06 +0200 Subject: common: Improved the certificate information extračtion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added a function to extract the needed information from an OpenSSL X509 object. Also extended parse_tlsid() to include a pointer to the certificate digest, to have a common behaviour between parse_tlsid() and parse_x509_cert(). Signed-off-by: David Sommerseth --- common/certinfo.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- common/certinfo.h | 4 ++- 2 files changed, 88 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/certinfo.c b/common/certinfo.c index 12a03fc..36a92a7 100644 --- a/common/certinfo.c +++ b/common/certinfo.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -53,7 +54,7 @@ * * @return Pointer to a certinfo structure containing the information */ -certinfo *parse_tlsid(const char *input) { +certinfo *parse_tlsid(const char *input, const char *digest) { char tmp[130], *mainp, *origptr, *sub, *tok, *tok2; certinfo *ret = NULL; @@ -86,6 +87,9 @@ certinfo *parse_tlsid(const char *input) { } free(origptr); mainp = NULL; origptr = NULL; + /* Copy over the digest info */ + ret->digest = digest; + /* Make sure we at least have empty NULL terminated strings */ if( ret->org == NULL ) { ret->org = strdup("\0"); @@ -100,6 +104,86 @@ certinfo *parse_tlsid(const char *input) { return ret; } +/** + * Parses an X.509 certificate data structure into a certinfo struct + * This implementation depends on OpenSSL + */ +certinfo *parse_x509_cert (X509 *cert) +{ + int i, n, objnid; + const int hashlen = SHA_DIGEST_LENGTH*3+2; + ASN1_OBJECT *asn1 = NULL; + ASN1_STRING *asn1val = NULL; + X509_NAME *x509_name = NULL; + X509_NAME_ENTRY *ent = NULL; + const char *objbuf = NULL; + unsigned char *buf = NULL; + char *ptr = NULL; + certinfo *ret = NULL; + + ret = (certinfo *) malloc_nullsafe(NULL, sizeof(certinfo)+2); + + x509_name = X509_get_subject_name(cert); + n = X509_NAME_entry_count(x509_name); + for (i = 0; i < n; i++) { + ent = X509_NAME_get_entry(x509_name, i); + if( !ent ) { + continue; + } + + asn1 = X509_NAME_ENTRY_get_object(ent); + if( !asn1 ) { + continue; + } + + asn1val = X509_NAME_ENTRY_get_data(ent); + if( !asn1val ) { + continue; + } + + objnid = OBJ_obj2nid(asn1); + if( objnid == NID_undef ) { + continue; + } + + objbuf = OBJ_nid2sn(objnid); + if( !objbuf ) { + continue; + } + + if( ASN1_STRING_to_UTF8(&buf, asn1val) <= 0 ) { + continue; + } + + // At this point we now have the 'field name' from the certificate + // available in objbuf and the 'field value' in buf. + + if( (ret->org == NULL) && (strcmp(objbuf, "O") == 0) ) { + ret->org = strdup_nullsafe((char *) buf); + } else if( (ret->common_name == NULL) && (strcmp(objbuf, "CN") == 0) ) { + ret->common_name = strdup_nullsafe((char *) buf); + } else if( (ret->email == NULL) && (strcmp(objbuf, "emailAddress") == 0) ) { + ret->email = strdup_nullsafe((char *) buf); + } + OPENSSL_free(buf); buf = NULL; + + if( ret->org && ret->common_name && ret->email ) { + // If we got all we need, skip the rest + break; + } + } + + // Extract the SHA1 certificate fingerprint/digest + ptr = ret->digest = malloc_nullsafe(NULL, hashlen); + buf = cert->sha1_hash; + for( i = 0; i < SHA_DIGEST_LENGTH; ++i ) { + snprintf(ptr, 4, "%02x:", buf[i]); + ptr += 3; + } + *(ptr-1) = 0; + + return ret; +} /** * Frees up the memory used by a certinfo structure diff --git a/common/certinfo.h b/common/certinfo.h index 91103d8..f306e36 100644 --- a/common/certinfo.h +++ b/common/certinfo.h @@ -41,7 +41,9 @@ typedef struct _certinfo { char *email; /**< Contains the emailAddress field from the X.509 certificate */ } certinfo; -certinfo *parse_tlsid(const char *); +certinfo *parse_tlsid(const char *, const char *); +certinfo *parse_x509_cert (X509 *cert); + void free_certinfo(certinfo *); #endif -- cgit