Blame snmplib/snmp_openssl.c

Packit Service b38f0b
/*
Packit Service b38f0b
 * snmp_openssl.c
Packit Service b38f0b
 *
Packit Service b38f0b
 * Portions of this file are subject to the following copyright(s).  See
Packit Service b38f0b
 * the Net-SNMP's COPYING file for more details and other copyrights
Packit Service b38f0b
 * that may apply:
Packit Service b38f0b
 *
Packit Service b38f0b
 * Portions of this file are copyrighted by:
Packit Service b38f0b
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
Packit Service b38f0b
 * Use is subject to license terms specified in the COPYING file
Packit Service b38f0b
 * distributed with the Net-SNMP package.
Packit Service b38f0b
 */
Packit Service b38f0b
Packit Service b38f0b
#include <net-snmp/net-snmp-config.h>
Packit Service b38f0b
Packit Service b38f0b
#include <net-snmp/net-snmp-includes.h>
Packit Service b38f0b
Packit Service b38f0b
#include <net-snmp/net-snmp-features.h>
Packit Service b38f0b
Packit Service b38f0b
/** OpenSSL compat functions for apps */
Packit Service b38f0b
#if defined(NETSNMP_USE_OPENSSL)
Packit Service b38f0b
Packit Service b38f0b
#include <string.h>
Packit Service b38f0b
#include <openssl/dh.h>
Packit Service b38f0b
Packit Service b38f0b
#ifndef HAVE_DH_GET0_PQG
Packit Service b38f0b
void
Packit Service b38f0b
DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
Packit Service b38f0b
{
Packit Service b38f0b
   if (p != NULL)
Packit Service b38f0b
       *p = dh->p;
Packit Service b38f0b
   if (q != NULL)
Packit Service b38f0b
       *q = dh->q;
Packit Service b38f0b
   if (g != NULL)
Packit Service b38f0b
       *g = dh->g;
Packit Service b38f0b
}
Packit Service b38f0b
#endif
Packit Service b38f0b
Packit Service b38f0b
#ifndef HAVE_DH_GET0_KEY
Packit Service b38f0b
void
Packit Service b38f0b
DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
Packit Service b38f0b
{
Packit Service b38f0b
   if (pub_key != NULL)
Packit Service b38f0b
       *pub_key = dh->pub_key;
Packit Service b38f0b
   if (priv_key != NULL)
Packit Service b38f0b
       *priv_key = dh->priv_key;
Packit Service b38f0b
}
Packit Service b38f0b
#endif
Packit Service b38f0b
Packit Service b38f0b
#ifndef HAVE_DH_SET0_PQG
Packit Service b38f0b
int
Packit Service b38f0b
DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
Packit Service b38f0b
{
Packit Service b38f0b
   /* If the fields p and g in d are NULL, the corresponding input
Packit Service b38f0b
    * parameters MUST be non-NULL.  q may remain NULL.
Packit Service b38f0b
    */
Packit Service b38f0b
   if ((dh->p == NULL && p == NULL)
Packit Service b38f0b
       || (dh->g == NULL && g == NULL))
Packit Service b38f0b
       return 0;
Packit Service b38f0b
Packit Service b38f0b
   if (p != NULL) {
Packit Service b38f0b
       BN_free(dh->p);
Packit Service b38f0b
       dh->p = p;
Packit Service b38f0b
   }
Packit Service b38f0b
   if (q != NULL) {
Packit Service b38f0b
       BN_free(dh->q);
Packit Service b38f0b
       dh->q = q;
Packit Service b38f0b
   }
Packit Service b38f0b
   if (g != NULL) {
Packit Service b38f0b
       BN_free(dh->g);
Packit Service b38f0b
       dh->g = g;
Packit Service b38f0b
   }
Packit Service b38f0b
Packit Service b38f0b
   if (q != NULL) {
Packit Service b38f0b
       dh->length = BN_num_bits(q);
Packit Service b38f0b
   }
Packit Service b38f0b
Packit Service b38f0b
   return 1;
Packit Service b38f0b
}
Packit Service b38f0b
#endif
Packit Service b38f0b
#endif /* defined(NETSNMP_USE_OPENSSL) */
Packit Service b38f0b
Packit Service b38f0b
/** TLS/DTLS certificatte support */
Packit Service b38f0b
#if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_LIBSSL) && !defined(NETSNMP_FEATURE_REMOVE_CERT_UTIL)
Packit Service b38f0b
Packit Service b38f0b
netsnmp_feature_require(container_free_all)
Packit Service b38f0b
Packit Service b38f0b
netsnmp_feature_child_of(openssl_cert_get_subjectAltNames, netsnmp_unused)
Packit Service b38f0b
netsnmp_feature_child_of(openssl_ht2nid, netsnmp_unused)
Packit Service b38f0b
netsnmp_feature_child_of(openssl_err_log, netsnmp_unused)
Packit Service b38f0b
netsnmp_feature_child_of(cert_dump_names, netsnmp_unused)
Packit Service b38f0b
Packit Service b38f0b
#include <ctype.h>
Packit Service b38f0b
Packit Service b38f0b
#include <openssl/evp.h>
Packit Service b38f0b
#include <openssl/ssl.h>
Packit Service b38f0b
#include <openssl/x509.h>
Packit Service b38f0b
#include <openssl/x509v3.h>
Packit Service b38f0b
#include <openssl/err.h>
Packit Service b38f0b
#include <openssl/objects.h>
Packit Service b38f0b
Packit Service b38f0b
#include <net-snmp/library/snmp_debug.h>
Packit Service b38f0b
#include <net-snmp/library/cert_util.h>
Packit Service b38f0b
#include <net-snmp/library/snmp_openssl.h>
Packit Service b38f0b
Packit Service b38f0b
static u_char have_started_already = 0;
Packit Service b38f0b
Packit Service b38f0b
/*
Packit Service b38f0b
 * This code merely does openssl initialization so that multilpe
Packit Service b38f0b
 * modules are safe to call netsnmp_init_openssl() for bootstrapping
Packit Service b38f0b
 * without worrying about other callers that may have already done so.
Packit Service b38f0b
 */
Packit Service b38f0b
void netsnmp_init_openssl(void) {
Packit Service b38f0b
Packit Service b38f0b
    /* avoid duplicate calls */
Packit Service b38f0b
    if (have_started_already)
Packit Service b38f0b
        return;
Packit Service b38f0b
    have_started_already = 1;
Packit Service b38f0b
Packit Service b38f0b
    DEBUGMSGTL(("snmp_openssl", "initializing\n"));
Packit Service b38f0b
Packit Service b38f0b
    /* Initializing OpenSSL */
Packit Service b38f0b
#ifdef HAVE_SSL_LIBRARY_INIT
Packit Service b38f0b
    SSL_library_init();
Packit Service b38f0b
#endif
Packit Service b38f0b
#ifdef HAVE_SSL_LOAD_ERROR_STRINGS
Packit Service b38f0b
    SSL_load_error_strings();
Packit Service b38f0b
#endif
Packit Service b38f0b
    ERR_load_BIO_strings();
Packit Service b38f0b
    OpenSSL_add_all_algorithms();
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
/** netsnmp_openssl_cert_get_name: get subject name field from cert
Packit Service b38f0b
 * @internal
Packit Service b38f0b
 */
Packit Service b38f0b
/** instead of exposing this function, make helper functions for each
Packit Service b38f0b
 * field, like netsnmp_openssl_cert_get_commonName, below */
Packit Service b38f0b
static char *
Packit Service b38f0b
_cert_get_name(X509 *ocert, int which, char **buf, int *len, int flags)
Packit Service b38f0b
{
Packit Service b38f0b
    X509_NAME       *osubj_name;
Packit Service b38f0b
    int              space;
Packit Service b38f0b
    char            *buf_ptr;
Packit Service b38f0b
Packit Service b38f0b
    if ((NULL == ocert) || ((buf && !len) || (len && !buf)))
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
Packit Service b38f0b
    osubj_name = X509_get_subject_name(ocert);
Packit Service b38f0b
    if (NULL == osubj_name) {
Packit Service b38f0b
        DEBUGMSGT(("openssl:cert:name", "no subject name!\n"));
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    /** see if buf is big enough, or allocate buf if none specified */
Packit Service b38f0b
    space = X509_NAME_get_text_by_NID(osubj_name, which, NULL, 0);
Packit Service b38f0b
    if (-1 == space)
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    ++space; /* for NUL */
Packit Service b38f0b
    if (buf && *buf) {
Packit Service b38f0b
        if (*len < space)
Packit Service b38f0b
            return NULL;
Packit Service b38f0b
        buf_ptr = *buf;
Packit Service b38f0b
    }
Packit Service b38f0b
    else {
Packit Service b38f0b
        buf_ptr = calloc(1,space);
Packit Service b38f0b
        if (!buf_ptr)
Packit Service b38f0b
            return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
    space = X509_NAME_get_text_by_NID(osubj_name, which, buf_ptr, space);
Packit Service b38f0b
    if (len)
Packit Service b38f0b
        *len = space;
Packit Service b38f0b
Packit Service b38f0b
    return buf_ptr;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
/** netsnmp_openssl_cert_get_subjectName: get subject name field from cert
Packit Service b38f0b
 */
Packit Service b38f0b
char *
Packit Service b38f0b
netsnmp_openssl_cert_get_subjectName(X509 *ocert, char **buf, int *len)
Packit Service b38f0b
{
Packit Service b38f0b
    X509_NAME       *osubj_name;
Packit Service b38f0b
    int              space;
Packit Service b38f0b
    char            *buf_ptr;
Packit Service b38f0b
Packit Service b38f0b
    if ((NULL == ocert) || ((buf && !len) || (len && !buf)))
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
Packit Service b38f0b
    osubj_name = X509_get_subject_name(ocert);
Packit Service b38f0b
    if (NULL == osubj_name) {
Packit Service b38f0b
        DEBUGMSGT(("openssl:cert:name", "no subject name!\n"));
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    if (buf) {
Packit Service b38f0b
        buf_ptr = *buf;
Packit Service b38f0b
        space = *len;
Packit Service b38f0b
    }
Packit Service b38f0b
    else {
Packit Service b38f0b
        buf_ptr = NULL;
Packit Service b38f0b
        space = 0;
Packit Service b38f0b
    }
Packit Service b38f0b
    buf_ptr = X509_NAME_oneline(osubj_name, buf_ptr, space);
Packit Service b38f0b
    if (len)
Packit Service b38f0b
        *len = strlen(buf_ptr);
Packit Service b38f0b
Packit Service b38f0b
    return buf_ptr;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
/** netsnmp_openssl_cert_get_commonName: get commonName for cert.
Packit Service b38f0b
 * if a pointer to a buffer and its length are specified, they will be
Packit Service b38f0b
 * used. otherwise, a new buffer will be allocated, which the caller will
Packit Service b38f0b
 * be responsbile for releasing.
Packit Service b38f0b
 */
Packit Service b38f0b
char *
Packit Service b38f0b
netsnmp_openssl_cert_get_commonName(X509 *ocert, char **buf, int *len)
Packit Service b38f0b
{
Packit Service b38f0b
    return _cert_get_name(ocert, NID_commonName, buf, len, 0);
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
#ifndef NETSNMP_FEATURE_REMOVE_CERT_DUMP_NAMES
Packit Service b38f0b
Packit Service b38f0b
/** netsnmp_openssl_cert_dump_name: dump subject names in cert
Packit Service b38f0b
 */
Packit Service b38f0b
void
Packit Service b38f0b
netsnmp_openssl_cert_dump_names(X509 *ocert)
Packit Service b38f0b
{
Packit Service b38f0b
    int              i, onid;
Packit Service b38f0b
    X509_NAME_ENTRY *oname_entry;
Packit Service b38f0b
    ASN1_STRING     *oname_value;
Packit Service b38f0b
    X509_NAME       *osubj_name;
Packit Service b38f0b
    const char      *prefix_short, *prefix_long;
Packit Service b38f0b
Packit Service b38f0b
    if (NULL == ocert)
Packit Service b38f0b
        return;
Packit Service b38f0b
Packit Service b38f0b
    osubj_name = X509_get_subject_name(ocert);
Packit Service b38f0b
    if (NULL == osubj_name) {
Packit Service b38f0b
        DEBUGMSGT(("9:cert:dump:names", "no subject name!\n"));
Packit Service b38f0b
        return;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    for (i = 0; i < X509_NAME_entry_count(osubj_name); i++) {
Packit Service b38f0b
        oname_entry = X509_NAME_get_entry(osubj_name, i);
Packit Service b38f0b
        netsnmp_assert(NULL != oname_entry);
Packit Service b38f0b
        oname_value = X509_NAME_ENTRY_get_data(oname_entry);
Packit Service b38f0b
Packit Service b38f0b
        if (oname_value->type != V_ASN1_PRINTABLESTRING)
Packit Service b38f0b
            continue;
Packit Service b38f0b
Packit Service b38f0b
        /** get NID */
Packit Service b38f0b
        onid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(oname_entry));
Packit Service b38f0b
        if (onid == NID_undef) {
Packit Service b38f0b
            prefix_long = prefix_short = "UNKNOWN";
Packit Service b38f0b
        }
Packit Service b38f0b
        else {
Packit Service b38f0b
            prefix_long = OBJ_nid2ln(onid);
Packit Service b38f0b
            prefix_short = OBJ_nid2sn(onid);
Packit Service b38f0b
        }
Packit Service b38f0b
Packit Service b38f0b
        DEBUGMSGT(("9:cert:dump:names",
Packit Service b38f0b
                   "[%02d] NID type %d, ASN type %d\n", i, onid,
Packit Service b38f0b
                   oname_value->type));
Packit Service b38f0b
        DEBUGMSGT(("9:cert:dump:names", "%s/%s: '%s'\n", prefix_long,
Packit Service b38f0b
                   prefix_short, ASN1_STRING_get0_data(oname_value)));
Packit Service b38f0b
    }
Packit Service b38f0b
}
Packit Service b38f0b
#endif /* NETSNMP_FEATURE_REMOVE_CERT_DUMP_NAMES */
Packit Service b38f0b
Packit Service b38f0b
static char *
Packit Service b38f0b
_cert_get_extension(X509_EXTENSION  *oext, char **buf, int *len, int flags)
Packit Service b38f0b
{
Packit Service b38f0b
    int              space;
Packit Service b38f0b
    char            *buf_ptr = NULL;
Packit Service b38f0b
    u_char          *data;
Packit Service b38f0b
    BIO             *bio;
Packit Service b38f0b
    
Packit Service b38f0b
    if ((NULL == oext) || ((buf && !len) || (len && !buf)))
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
Packit Service b38f0b
    bio = BIO_new(BIO_s_mem());
Packit Service b38f0b
    if (NULL == bio) {
Packit Service b38f0b
        snmp_log(LOG_ERR, "could not get bio for extension\n");
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
    if (X509V3_EXT_print(bio, oext, 0, 0) != 1) {
Packit Service b38f0b
        snmp_log(LOG_ERR, "could not print extension!\n");
Packit Service b38f0b
        BIO_vfree(bio);
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    space = BIO_get_mem_data(bio, &data);
Packit Service b38f0b
    if (buf && *buf) {
Packit Service b38f0b
        if (*len < space) 
Packit Service b38f0b
            buf_ptr = NULL;
Packit Service b38f0b
        else
Packit Service b38f0b
            buf_ptr = *buf;
Packit Service b38f0b
    }
Packit Service b38f0b
    else
Packit Service b38f0b
        buf_ptr = calloc(1,space + 1);
Packit Service b38f0b
    
Packit Service b38f0b
    if (!buf_ptr) {
Packit Service b38f0b
        snmp_log(LOG_ERR,
Packit Service b38f0b
                 "not enough space or error in allocation for extenstion\n");
Packit Service b38f0b
        BIO_vfree(bio);
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
    memcpy(buf_ptr, data, space);
Packit Service b38f0b
    buf_ptr[space] = 0;
Packit Service b38f0b
    if (len)
Packit Service b38f0b
        *len = space;
Packit Service b38f0b
Packit Service b38f0b
    BIO_vfree(bio);
Packit Service b38f0b
Packit Service b38f0b
    return buf_ptr;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
/** netsnmp_openssl_cert_get_extension: get extension field from cert
Packit Service b38f0b
 * @internal
Packit Service b38f0b
 */
Packit Service b38f0b
/** instead of exposing this function, make helper functions for each
Packit Service b38f0b
 * field, like netsnmp_openssl_cert_get_subjectAltName, below */
Packit Service b38f0b
X509_EXTENSION  *
Packit Service b38f0b
_cert_get_extension_at(X509 *ocert, int pos, char **buf, int *len, int flags)
Packit Service b38f0b
{
Packit Service b38f0b
    X509_EXTENSION  *oext;
Packit Service b38f0b
Packit Service b38f0b
    if ((NULL == ocert) || ((buf && !len) || (len && !buf)))
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
Packit Service b38f0b
    oext = X509_get_ext(ocert,pos);
Packit Service b38f0b
    if (NULL == oext) {
Packit Service b38f0b
        snmp_log(LOG_ERR, "extension number %d not found!\n", pos);
Packit Service b38f0b
        netsnmp_openssl_cert_dump_extensions(ocert);
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    return oext;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
/** netsnmp_openssl_cert_get_extension: get extension field from cert
Packit Service b38f0b
 * @internal
Packit Service b38f0b
 */
Packit Service b38f0b
/** instead of exposing this function, make helper functions for each
Packit Service b38f0b
 * field, like netsnmp_openssl_cert_get_subjectAltName, below */
Packit Service b38f0b
static char *
Packit Service b38f0b
_cert_get_extension_str_at(X509 *ocert, int pos, char **buf, int *len,
Packit Service b38f0b
                           int flags)
Packit Service b38f0b
{
Packit Service b38f0b
    X509_EXTENSION  *oext;
Packit Service b38f0b
Packit Service b38f0b
    if ((NULL == ocert) || ((buf && !len) || (len && !buf)))
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
Packit Service b38f0b
    oext = X509_get_ext(ocert,pos);
Packit Service b38f0b
    if (NULL == oext) {
Packit Service b38f0b
        snmp_log(LOG_ERR, "extension number %d not found!\n", pos);
Packit Service b38f0b
        netsnmp_openssl_cert_dump_extensions(ocert);
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    return _cert_get_extension(oext, buf, len, flags);
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
/** _cert_get_extension_id: get extension field from cert
Packit Service b38f0b
 * @internal
Packit Service b38f0b
 */
Packit Service b38f0b
/** instead of exposing this function, make helper functions for each
Packit Service b38f0b
 * field, like netsnmp_openssl_cert_get_subjectAltName, below */
Packit Service b38f0b
X509_EXTENSION *
Packit Service b38f0b
_cert_get_extension_id(X509 *ocert, int which, char **buf, int *len, int flags)
Packit Service b38f0b
{
Packit Service b38f0b
    int pos;
Packit Service b38f0b
Packit Service b38f0b
    if ((NULL == ocert) || ((buf && !len) || (len && !buf)))
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
Packit Service b38f0b
    pos = X509_get_ext_by_NID(ocert,which,-1);
Packit Service b38f0b
    if (pos < 0) {
Packit Service b38f0b
        DEBUGMSGT(("openssl:cert:name", "no extension %d\n", which));
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    return _cert_get_extension_at(ocert, pos, buf, len, flags);
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
#ifndef NETSNMP_FEATURE_REMOVE_OPENSSL_CERT_GET_SUBJECTALTNAMES
Packit Service b38f0b
/** _cert_get_extension_id_str: get extension field from cert
Packit Service b38f0b
 * @internal
Packit Service b38f0b
 */
Packit Service b38f0b
/** instead of exposing this function, make helper functions for each
Packit Service b38f0b
 * field, like netsnmp_openssl_cert_get_subjectAltName, below */
Packit Service b38f0b
static char *
Packit Service b38f0b
_cert_get_extension_id_str(X509 *ocert, int which, char **buf, int *len,
Packit Service b38f0b
                           int flags)
Packit Service b38f0b
{
Packit Service b38f0b
    int pos;
Packit Service b38f0b
Packit Service b38f0b
    if ((NULL == ocert) || ((buf && !len) || (len && !buf)))
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
Packit Service b38f0b
    pos = X509_get_ext_by_NID(ocert,which,-1);
Packit Service b38f0b
    if (pos < 0) {
Packit Service b38f0b
        DEBUGMSGT(("openssl:cert:name", "no extension %d\n", which));
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    return _cert_get_extension_str_at(ocert, pos, buf, len, flags);
Packit Service b38f0b
}
Packit Service b38f0b
#endif /* NETSNMP_FEATURE_REMOVE_OPENSSL_CERT_GET_SUBJECTALTNAMES */
Packit Service b38f0b
Packit Service b38f0b
static char *
Packit Service b38f0b
_extract_oname(const GENERAL_NAME *oname)
Packit Service b38f0b
{
Packit Service b38f0b
    char  ipbuf[60], *buf = NULL, *rtn = NULL;
Packit Service b38f0b
Packit Service b38f0b
    if (NULL == oname)
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
Packit Service b38f0b
    switch ( oname->type ) {
Packit Service b38f0b
        case GEN_EMAIL:
Packit Service b38f0b
        case GEN_DNS:
Packit Service b38f0b
            /*case GEN_URI:*/
Packit Service b38f0b
            ASN1_STRING_to_UTF8((unsigned char**)&buf, oname->d.ia5);
Packit Service b38f0b
            if (buf)
Packit Service b38f0b
                rtn = strdup(buf);
Packit Service b38f0b
            break;
Packit Service b38f0b
Packit Service b38f0b
        case GEN_IPADD:
Packit Service b38f0b
            if (oname->d.iPAddress->length == 4) {
Packit Service b38f0b
                sprintf(ipbuf, "%d.%d.%d.%d", oname->d.iPAddress->data[0],
Packit Service b38f0b
                        oname->d.iPAddress->data[1],
Packit Service b38f0b
                        oname->d.iPAddress->data[2],
Packit Service b38f0b
                        oname->d.iPAddress->data[3]);
Packit Service b38f0b
                rtn = strdup(ipbuf);
Packit Service b38f0b
            }
Packit Service b38f0b
            else if ((oname->d.iPAddress->length == 16) ||
Packit Service b38f0b
                     (oname->d.iPAddress->length == 20)) {
Packit Service b38f0b
                char *pos = ipbuf;
Packit Service b38f0b
                int   j;
Packit Service b38f0b
                for(j = 0; j < oname->d.iPAddress->length; ++j) {
Packit Service b38f0b
                    *pos++ = VAL2HEX(oname->d.iPAddress->data[j]);
Packit Service b38f0b
                    *pos++ = ':';
Packit Service b38f0b
                }
Packit Service b38f0b
                *pos = '\0';
Packit Service b38f0b
                rtn = strdup(ipbuf);
Packit Service b38f0b
            }
Packit Service b38f0b
            else
Packit Service b38f0b
                NETSNMP_LOGONCE((LOG_WARNING, "unexpected ip addr length %d\n",
Packit Service b38f0b
                       oname->d.iPAddress->length));
Packit Service b38f0b
Packit Service b38f0b
            break;
Packit Service b38f0b
        default:
Packit Service b38f0b
            DEBUGMSGT(("openssl:cert:san", "unknown/unsupported type %d\n",
Packit Service b38f0b
                       oname->type));
Packit Service b38f0b
            break;
Packit Service b38f0b
    }
Packit Service b38f0b
    DEBUGMSGT(("9:openssl:cert:san", "san=%s\n", buf));
Packit Service b38f0b
    if (buf)
Packit Service b38f0b
        OPENSSL_free(buf);
Packit Service b38f0b
Packit Service b38f0b
    return rtn;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
#ifndef NETSNMP_FEATURE_REMOVE_OPENSSL_CERT_GET_SUBJECTALTNAMES
Packit Service b38f0b
/** netsnmp_openssl_cert_get_subjectAltName: get subjectAltName for cert.
Packit Service b38f0b
 * if a pointer to a buffer and its length are specified, they will be
Packit Service b38f0b
 * used. otherwise, a new buffer will be allocated, which the caller will
Packit Service b38f0b
 * be responsbile for releasing.
Packit Service b38f0b
 */
Packit Service b38f0b
char *
Packit Service b38f0b
netsnmp_openssl_cert_get_subjectAltNames(X509 *ocert, char **buf, int *len)
Packit Service b38f0b
{
Packit Service b38f0b
    return _cert_get_extension_id_str(ocert, NID_subject_alt_name, buf, len, 0);
Packit Service b38f0b
}
Packit Service b38f0b
#endif /* NETSNMP_FEATURE_REMOVE_OPENSSL_CERT_GET_SUBJECTALTNAMES */
Packit Service b38f0b
Packit Service b38f0b
void
Packit Service b38f0b
netsnmp_openssl_cert_dump_extensions(X509 *ocert)
Packit Service b38f0b
{
Packit Service b38f0b
    X509_EXTENSION  *extension;
Packit Service b38f0b
    const char      *extension_name;
Packit Service b38f0b
    char             buf[SNMP_MAXBUF_SMALL], *buf_ptr = buf, *str, *lf;
Packit Service b38f0b
    int              i, num_extensions, buf_len, nid;
Packit Service b38f0b
Packit Service b38f0b
    if (NULL == ocert)
Packit Service b38f0b
        return;
Packit Service b38f0b
Packit Service b38f0b
    DEBUGIF("9:cert:dump") 
Packit Service b38f0b
        ;
Packit Service b38f0b
    else
Packit Service b38f0b
        return; /* bail if debug not enabled */
Packit Service b38f0b
Packit Service b38f0b
    num_extensions = X509_get_ext_count(ocert);
Packit Service b38f0b
    if (0 == num_extensions)
Packit Service b38f0b
        DEBUGMSGT(("9:cert:dump", "    0 extensions\n"));
Packit Service b38f0b
    for(i = 0; i < num_extensions; i++) {
Packit Service b38f0b
        extension = X509_get_ext(ocert, i);
Packit Service b38f0b
        nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension));
Packit Service b38f0b
        extension_name = OBJ_nid2sn(nid);
Packit Service b38f0b
        buf_len = sizeof(buf);
Packit Service b38f0b
        str = _cert_get_extension_str_at(ocert, i, &buf_ptr, &buf_len, 0);
Packit Service b38f0b
        lf = strchr(str, '\n'); /* look for multiline strings */
Packit Service b38f0b
        if (NULL != lf)
Packit Service b38f0b
            *lf = '\0'; /* only log first line of multiline here */
Packit Service b38f0b
        DEBUGMSGT(("9:cert:dump", "    %2d: %s = %s\n", i,
Packit Service b38f0b
                   extension_name, str));
Packit Service b38f0b
        while(lf) { /* log remaining parts of multiline string */
Packit Service b38f0b
            str = ++lf;
Packit Service b38f0b
            if (*str == '\0')
Packit Service b38f0b
               break;
Packit Service b38f0b
            lf = strchr(str, '\n');
Packit Service b38f0b
            if (NULL == lf) 
Packit Service b38f0b
                break;
Packit Service b38f0b
            *lf = '\0';
Packit Service b38f0b
            DEBUGMSGT(("9:cert:dump", "        %s\n", str));
Packit Service b38f0b
        }
Packit Service b38f0b
    }
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
static int _htmap[NS_HASH_MAX + 1] = {
Packit Service b38f0b
    0, NID_md5WithRSAEncryption, NID_sha1WithRSAEncryption,
Packit Service b38f0b
    NID_sha224WithRSAEncryption, NID_sha256WithRSAEncryption,
Packit Service b38f0b
    NID_sha384WithRSAEncryption, NID_sha512WithRSAEncryption };
Packit Service b38f0b
Packit Service b38f0b
int
Packit Service b38f0b
_nid2ht(int nid)
Packit Service b38f0b
{
Packit Service b38f0b
    int i;
Packit Service b38f0b
    for (i=1; i<= NS_HASH_MAX; ++i) {
Packit Service b38f0b
        if (nid == _htmap[i])
Packit Service b38f0b
            return i;
Packit Service b38f0b
    }
Packit Service b38f0b
    return 0;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
#ifndef NETSNMP_FEATURE_REMOVE_OPENSSL_HT2NID
Packit Service b38f0b
int
Packit Service b38f0b
_ht2nid(int ht)
Packit Service b38f0b
{
Packit Service b38f0b
    if ((ht < 0) || (ht > NS_HASH_MAX))
Packit Service b38f0b
        return 0;
Packit Service b38f0b
    return _htmap[ht];
Packit Service b38f0b
}
Packit Service b38f0b
#endif /* NETSNMP_FEATURE_REMOVE_OPENSSL_HT2NID */
Packit Service b38f0b
Packit Service b38f0b
/**
Packit Service b38f0b
 * returns allocated pointer caller must free.
Packit Service b38f0b
 */
Packit Service b38f0b
int
Packit Service b38f0b
netsnmp_openssl_cert_get_hash_type(X509 *ocert)
Packit Service b38f0b
{
Packit Service b38f0b
    if (NULL == ocert)
Packit Service b38f0b
        return 0;
Packit Service b38f0b
Packit Service b38f0b
    return _nid2ht(X509_get_signature_nid(ocert));
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
/**
Packit Service b38f0b
 * returns allocated pointer caller must free.
Packit Service b38f0b
 */
Packit Service b38f0b
char *
Packit Service b38f0b
netsnmp_openssl_cert_get_fingerprint(X509 *ocert, int alg)
Packit Service b38f0b
{
Packit Service b38f0b
    u_char           fingerprint[EVP_MAX_MD_SIZE];
Packit Service b38f0b
    u_int            fingerprint_len, nid;
Packit Service b38f0b
    const EVP_MD    *digest;
Packit Service b38f0b
    char            *result = NULL;
Packit Service b38f0b
Packit Service b38f0b
    if (NULL == ocert)
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
Packit Service b38f0b
    nid = X509_get_signature_nid(ocert);
Packit Service b38f0b
    DEBUGMSGT(("9:openssl:fingerprint", "alg %d, cert nid %d (%d)\n", alg, nid,
Packit Service b38f0b
               _nid2ht(nid)));
Packit Service b38f0b
        
Packit Service b38f0b
    if ((-1 == alg) && nid)
Packit Service b38f0b
        alg = _nid2ht(nid);
Packit Service b38f0b
Packit Service b38f0b
    switch (alg) {
Packit Service b38f0b
        case NS_HASH_MD5:
Packit Service b38f0b
            snmp_log(LOG_ERR, "hash type md5 not yet supported\n");
Packit Service b38f0b
            return NULL;
Packit Service b38f0b
            break;
Packit Service b38f0b
        
Packit Service b38f0b
        case NS_HASH_NONE:
Packit Service b38f0b
            snmp_log(LOG_ERR, "hash type none not supported. using SHA1\n");
Packit Service b38f0b
            /* FALLTHROUGH */
Packit Service b38f0b
Packit Service b38f0b
        case NS_HASH_SHA1:
Packit Service b38f0b
            digest = EVP_sha1();
Packit Service b38f0b
            break;
Packit Service b38f0b
Packit Service b38f0b
#ifdef HAVE_EVP_SHA224
Packit Service b38f0b
        case NS_HASH_SHA224:
Packit Service b38f0b
            digest = EVP_sha224();
Packit Service b38f0b
            break;
Packit Service b38f0b
Packit Service b38f0b
        case NS_HASH_SHA256:
Packit Service b38f0b
            digest = EVP_sha256();
Packit Service b38f0b
            break;
Packit Service b38f0b
Packit Service b38f0b
#endif
Packit Service b38f0b
#ifdef HAVE_EVP_SHA384
Packit Service b38f0b
        case NS_HASH_SHA384:
Packit Service b38f0b
            digest = EVP_sha384();
Packit Service b38f0b
            break;
Packit Service b38f0b
Packit Service b38f0b
        case NS_HASH_SHA512:
Packit Service b38f0b
            digest = EVP_sha512();
Packit Service b38f0b
            break;
Packit Service b38f0b
#endif
Packit Service b38f0b
Packit Service b38f0b
        default:
Packit Service b38f0b
            snmp_log(LOG_ERR, "unknown hash algorithm %d\n", alg);
Packit Service b38f0b
            return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    if (_nid2ht(nid) != alg) {
Packit Service b38f0b
        DEBUGMSGT(("openssl:fingerprint",
Packit Service b38f0b
                   "WARNING: alg %d does not match cert alg %d\n",
Packit Service b38f0b
                   alg, _nid2ht(nid)));
Packit Service b38f0b
    }
Packit Service b38f0b
    if (X509_digest(ocert,digest,fingerprint,&fingerprint_len)) {
Packit Service b38f0b
        binary_to_hex(fingerprint, fingerprint_len, &result);
Packit Service b38f0b
        if (NULL == result)
Packit Service b38f0b
            snmp_log(LOG_ERR, "failed to hexify fingerprint\n");
Packit Service b38f0b
        else
Packit Service b38f0b
            DEBUGMSGT(("9:openssl:fingerprint", "fingerprint %s\n", result));
Packit Service b38f0b
    }
Packit Service b38f0b
    else
Packit Service b38f0b
        snmp_log(LOG_ERR,"failed to compute fingerprint\n");
Packit Service b38f0b
Packit Service b38f0b
    return result;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
/**
Packit Service b38f0b
 * get container of netsnmp_cert_map structures from an ssl connection
Packit Service b38f0b
 * certificate chain.
Packit Service b38f0b
 */
Packit Service b38f0b
netsnmp_container *
Packit Service b38f0b
netsnmp_openssl_get_cert_chain(SSL *ssl)
Packit Service b38f0b
{
Packit Service b38f0b
    X509                  *ocert, *ocert_tmp;
Packit Service b38f0b
    STACK_OF(X509)        *ochain;
Packit Service b38f0b
    char                  *fingerprint;
Packit Service b38f0b
    netsnmp_container     *chain_map;
Packit Service b38f0b
    netsnmp_cert_map      *cert_map;
Packit Service b38f0b
    int                    i;
Packit Service b38f0b
Packit Service b38f0b
    netsnmp_assert_or_return(ssl != NULL, NULL);
Packit Service b38f0b
    
Packit Service b38f0b
    if (NULL == (ocert = SSL_get_peer_certificate(ssl))) {
Packit Service b38f0b
        /** no peer cert */
Packit Service b38f0b
        snmp_log(LOG_ERR, "SSL peer has no certificate\n");
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
    DEBUGIF("9:cert:dump") {
Packit Service b38f0b
        netsnmp_openssl_cert_dump_extensions(ocert);
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    /*
Packit Service b38f0b
     * get fingerprint and save it
Packit Service b38f0b
     */
Packit Service b38f0b
    fingerprint = netsnmp_openssl_cert_get_fingerprint(ocert, -1);
Packit Service b38f0b
    if (NULL == fingerprint)
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
Packit Service b38f0b
    /*
Packit Service b38f0b
     * allocate cert map. Don't pass in fingerprint, since it would strdup
Packit Service b38f0b
     * it and we've already got a copy.
Packit Service b38f0b
     */
Packit Service b38f0b
    cert_map = netsnmp_cert_map_alloc(NULL, ocert);
Packit Service b38f0b
    if (NULL == cert_map) {
Packit Service b38f0b
        free(fingerprint);
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
    cert_map->fingerprint = fingerprint;
Packit Service b38f0b
    cert_map->hashType = netsnmp_openssl_cert_get_hash_type(ocert);
Packit Service b38f0b
Packit Service b38f0b
    chain_map = netsnmp_cert_map_container_create(0); /* no fp subcontainer */
Packit Service b38f0b
    if (NULL == chain_map) {
Packit Service b38f0b
        netsnmp_cert_map_free(cert_map);
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
    
Packit Service b38f0b
    CONTAINER_INSERT(chain_map, cert_map);
Packit Service b38f0b
Packit Service b38f0b
    /** check for a chain to a CA */
Packit Service b38f0b
    ochain = SSL_get_peer_cert_chain(ssl);
Packit Service b38f0b
    if ((NULL == ochain) || (0 == sk_num((const void *)ochain))) {
Packit Service b38f0b
        DEBUGMSGT(("ssl:cert:chain", "peer has no cert chain\n"));
Packit Service b38f0b
    }
Packit Service b38f0b
    else {
Packit Service b38f0b
        /*
Packit Service b38f0b
         * loop over chain, adding fingerprint / cert for each
Packit Service b38f0b
         */
Packit Service b38f0b
        DEBUGMSGT(("ssl:cert:chain", "examining cert chain\n"));
Packit Service b38f0b
        for(i = 0; i < sk_num((const void *)ochain); ++i) {
Packit Service b38f0b
            ocert_tmp = (X509*)sk_value((const void *)ochain,i);
Packit Service b38f0b
            fingerprint = netsnmp_openssl_cert_get_fingerprint(ocert_tmp,
Packit Service b38f0b
                                                               NS_HASH_SHA1);
Packit Service b38f0b
            if (NULL == fingerprint)
Packit Service b38f0b
                break;
Packit Service b38f0b
            cert_map = netsnmp_cert_map_alloc(NULL, ocert);
Packit Service b38f0b
            if (NULL == cert_map) {
Packit Service b38f0b
                free(fingerprint);
Packit Service b38f0b
                break;
Packit Service b38f0b
            }
Packit Service b38f0b
            cert_map->fingerprint = fingerprint;
Packit Service b38f0b
            cert_map->hashType = netsnmp_openssl_cert_get_hash_type(ocert_tmp);
Packit Service b38f0b
Packit Service b38f0b
            CONTAINER_INSERT(chain_map, cert_map);
Packit Service b38f0b
        } /* chain loop */
Packit Service b38f0b
        /*
Packit Service b38f0b
         * if we broke out of loop before finishing, clean up
Packit Service b38f0b
         */
Packit Service b38f0b
        if (i < sk_num((const void *)ochain)) 
Packit Service b38f0b
            CONTAINER_FREE_ALL(chain_map, NULL);
Packit Service b38f0b
    } /* got peer chain */
Packit Service b38f0b
Packit Service b38f0b
    DEBUGMSGT(("ssl:cert:chain", "found %" NETSNMP_PRIz "u certs in chain\n",
Packit Service b38f0b
               CONTAINER_SIZE(chain_map)));
Packit Service b38f0b
    if (CONTAINER_SIZE(chain_map) == 0) {
Packit Service b38f0b
        CONTAINER_FREE(chain_map);
Packit Service b38f0b
        chain_map = NULL;
Packit Service b38f0b
    }
Packit Service b38f0b
Packit Service b38f0b
    return chain_map;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
/*
Packit Service b38f0b
tlstmCertSANRFC822Name "Maps a subjectAltName's rfc822Name to a
Packit Service b38f0b
                  tmSecurityName.  The local part of the rfc822Name is
Packit Service b38f0b
                  passed unaltered but the host-part of the name must
Packit Service b38f0b
                  be passed in lower case.
Packit Service b38f0b
                  Example rfc822Name Field:  FooBar@Example.COM
Packit Service b38f0b
                  is mapped to tmSecurityName: FooBar@example.com"
Packit Service b38f0b
Packit Service b38f0b
tlstmCertSANDNSName "Maps a subjectAltName's dNSName to a
Packit Service b38f0b
                  tmSecurityName after first converting it to all
Packit Service b38f0b
                  lower case."
Packit Service b38f0b
Packit Service b38f0b
tlstmCertSANIpAddress "Maps a subjectAltName's iPAddress to a
Packit Service b38f0b
                  tmSecurityName by transforming the binary encoded
Packit Service b38f0b
                  address as follows:
Packit Service b38f0b
                  1) for IPv4 the value is converted into a decimal
Packit Service b38f0b
                     dotted quad address (e.g. '192.0.2.1')
Packit Service b38f0b
                  2) for IPv6 addresses the value is converted into a
Packit Service b38f0b
                     32-character all lowercase hexadecimal string
Packit Service b38f0b
                     without any colon separators.
Packit Service b38f0b
Packit Service b38f0b
                     Note that the resulting length is the maximum
Packit Service b38f0b
                     length supported by the View-Based Access Control
Packit Service b38f0b
                     Model (VACM).  Note that using both the Transport
Packit Service b38f0b
                     Security Model's support for transport prefixes
Packit Service b38f0b
                     (see the SNMP-TSM-MIB's
Packit Service b38f0b
                     snmpTsmConfigurationUsePrefix object for details)
Packit Service b38f0b
                     will result in securityName lengths that exceed
Packit Service b38f0b
                     what VACM can handle."
Packit Service b38f0b
Packit Service b38f0b
tlstmCertSANAny "Maps any of the following fields using the
Packit Service b38f0b
                  corresponding mapping algorithms:
Packit Service b38f0b
                  | rfc822Name | tlstmCertSANRFC822Name |
Packit Service b38f0b
                  | dNSName    | tlstmCertSANDNSName    |
Packit Service b38f0b
                  | iPAddress  | tlstmCertSANIpAddress  |
Packit Service b38f0b
                  The first matching subjectAltName value found in the
Packit Service b38f0b
                  certificate of the above types MUST be used when
Packit Service b38f0b
                  deriving the tmSecurityName."
Packit Service b38f0b
*/
Packit Service b38f0b
char *
Packit Service b38f0b
_cert_get_san_type(X509 *ocert, int mapType)
Packit Service b38f0b
{
Packit Service b38f0b
    GENERAL_NAMES      *onames;
Packit Service b38f0b
    const GENERAL_NAME *oname = NULL;
Packit Service b38f0b
    char               *buf = NULL, *lower = NULL;
Packit Service b38f0b
    int                 count, i;
Packit Service b38f0b
 
Packit Service b38f0b
    onames = (GENERAL_NAMES *)X509_get_ext_d2i(ocert, NID_subject_alt_name,
Packit Service b38f0b
                                               NULL, NULL );
Packit Service b38f0b
    if (NULL == onames)
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
Packit Service b38f0b
    count = sk_GENERAL_NAME_num(onames);
Packit Service b38f0b
Packit Service b38f0b
    for (i=0 ; i 
Packit Service b38f0b
        oname = sk_GENERAL_NAME_value(onames, i);
Packit Service b38f0b
Packit Service b38f0b
        if (GEN_DNS == oname->type) {
Packit Service b38f0b
            if ((TSNM_tlstmCertSANDNSName == mapType) ||
Packit Service b38f0b
                (TSNM_tlstmCertSANAny == mapType)) {
Packit Service b38f0b
                lower = buf = _extract_oname( oname );
Packit Service b38f0b
                break;
Packit Service b38f0b
            }
Packit Service b38f0b
        }
Packit Service b38f0b
        else if (GEN_IPADD == oname->type) {
Packit Service b38f0b
            if ((TSNM_tlstmCertSANIpAddress == mapType) ||
Packit Service b38f0b
                (TSNM_tlstmCertSANAny == mapType)) {
Packit Service b38f0b
                buf = _extract_oname(oname);
Packit Service b38f0b
                break;
Packit Service b38f0b
            }
Packit Service b38f0b
        }
Packit Service b38f0b
        else if (GEN_EMAIL == oname->type) {
Packit Service b38f0b
            if ((TSNM_tlstmCertSANRFC822Name == mapType) ||
Packit Service b38f0b
                (TSNM_tlstmCertSANAny == mapType)) {
Packit Service b38f0b
                buf = _extract_oname(oname);
Packit Service b38f0b
                lower = strchr(buf, '@');
Packit Service b38f0b
                if (NULL == lower) {
Packit Service b38f0b
                    DEBUGMSGT(("openssl:secname:extract",
Packit Service b38f0b
                               "email %s has no '@'!\n", buf));
Packit Service b38f0b
                }
Packit Service b38f0b
                else {
Packit Service b38f0b
                    ++lower;
Packit Service b38f0b
                    break;
Packit Service b38f0b
                }
Packit Service b38f0b
            }
Packit Service b38f0b
            
Packit Service b38f0b
        }
Packit Service b38f0b
    } /* for loop */
Packit Service b38f0b
Packit Service b38f0b
    if (lower)
Packit Service b38f0b
        for ( ; *lower; ++lower )
Packit Service b38f0b
            if (isascii(*lower))
Packit Service b38f0b
                *lower = tolower(0xFF & *lower);
Packit Service b38f0b
    DEBUGMSGT(("openssl:cert:extension:san", "#%d type %d: %s\n", i,
Packit Service b38f0b
               oname ? oname->type : -1, buf ? buf : "NULL"));
Packit Service b38f0b
Packit Service b38f0b
    return buf;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
char *
Packit Service b38f0b
netsnmp_openssl_extract_secname(netsnmp_cert_map *cert_map,
Packit Service b38f0b
                                netsnmp_cert_map *peer_cert)
Packit Service b38f0b
{
Packit Service b38f0b
    char       *rtn = NULL;
Packit Service b38f0b
Packit Service b38f0b
    if (NULL == cert_map)
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
Packit Service b38f0b
    DEBUGMSGT(("openssl:secname:extract",
Packit Service b38f0b
               "checking priority %d, san of type %d for %s\n",
Packit Service b38f0b
               cert_map->priority, cert_map->mapType, peer_cert->fingerprint));
Packit Service b38f0b
Packit Service b38f0b
    switch(cert_map->mapType) {
Packit Service b38f0b
        case TSNM_tlstmCertSpecified:
Packit Service b38f0b
            rtn = strdup(cert_map->data);
Packit Service b38f0b
            break;
Packit Service b38f0b
Packit Service b38f0b
        case TSNM_tlstmCertSANRFC822Name:
Packit Service b38f0b
        case TSNM_tlstmCertSANDNSName:
Packit Service b38f0b
        case TSNM_tlstmCertSANIpAddress:
Packit Service b38f0b
        case TSNM_tlstmCertSANAny:
Packit Service b38f0b
            if (NULL == peer_cert) {
Packit Service b38f0b
                DEBUGMSGT(("openssl:secname:extract", "no peer cert for %s\n",
Packit Service b38f0b
                           cert_map->fingerprint));
Packit Service b38f0b
                break;
Packit Service b38f0b
            }
Packit Service b38f0b
            rtn = _cert_get_san_type(peer_cert->ocert, cert_map->mapType);
Packit Service b38f0b
            if (NULL == rtn) {
Packit Service b38f0b
                DEBUGMSGT(("openssl:secname:extract", "no san for %s\n",
Packit Service b38f0b
                           peer_cert->fingerprint));
Packit Service b38f0b
            }
Packit Service b38f0b
            break;
Packit Service b38f0b
Packit Service b38f0b
        case TSNM_tlstmCertCommonName:
Packit Service b38f0b
            rtn = netsnmp_openssl_cert_get_commonName(cert_map->ocert, NULL,
Packit Service b38f0b
                                                       NULL);
Packit Service b38f0b
            break;
Packit Service b38f0b
        default:
Packit Service b38f0b
            snmp_log(LOG_ERR, "cant extract secname for unknown map type %d\n",
Packit Service b38f0b
                     cert_map->mapType);
Packit Service b38f0b
            break;
Packit Service b38f0b
    } /* switch mapType */
Packit Service b38f0b
Packit Service b38f0b
    if (rtn) {
Packit Service b38f0b
        DEBUGMSGT(("openssl:secname:extract",
Packit Service b38f0b
                   "found map %d, type %d for %s: %s\n", cert_map->priority,
Packit Service b38f0b
                   cert_map->mapType, peer_cert->fingerprint, rtn));
Packit Service b38f0b
        if (strlen(rtn) >32) {
Packit Service b38f0b
            DEBUGMSGT(("openssl:secname:extract",
Packit Service b38f0b
                       "secName longer than 32 chars! dropping...\n"));
Packit Service b38f0b
            SNMP_FREE(rtn);
Packit Service b38f0b
        }
Packit Service b38f0b
    }
Packit Service b38f0b
    else
Packit Service b38f0b
        DEBUGMSGT(("openssl:secname:extract",
Packit Service b38f0b
                   "no map of type %d for %s\n",
Packit Service b38f0b
                   cert_map->mapType, peer_cert->fingerprint));
Packit Service b38f0b
    return rtn;
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
int
Packit Service b38f0b
netsnmp_openssl_cert_issued_by(X509 *issuer, X509 *cert)
Packit Service b38f0b
{
Packit Service b38f0b
    return (X509_check_issued(issuer, cert) == X509_V_OK);
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
Packit Service b38f0b
#ifndef NETSNMP_FEATURE_REMOVE_OPENSSL_ERR_LOG
Packit Service b38f0b
void
Packit Service b38f0b
netsnmp_openssl_err_log(const char *prefix)
Packit Service b38f0b
{
Packit Service b38f0b
    unsigned long err;
Packit Service b38f0b
    for (err = ERR_get_error(); err; err = ERR_get_error()) {
Packit Service b38f0b
        snmp_log(LOG_ERR,"%s: %ld\n", prefix ? prefix: "openssl error", err);
Packit Service b38f0b
        snmp_log(LOG_ERR, "library=%d, function=%d, reason=%d\n",
Packit Service b38f0b
                 ERR_GET_LIB(err), ERR_GET_FUNC(err), ERR_GET_REASON(err));
Packit Service b38f0b
    }
Packit Service b38f0b
}
Packit Service b38f0b
#endif /* NETSNMP_FEATURE_REMOVE_OPENSSL_ERR_LOG */
Packit Service b38f0b
Packit Service b38f0b
void
Packit Service b38f0b
netsnmp_openssl_null_checks(SSL *ssl, int *null_auth, int *null_cipher)
Packit Service b38f0b
{
Packit Service b38f0b
    const SSL_CIPHER *cipher;
Packit Service b38f0b
    char           tmp_buf[128], *cipher_alg, *auth_alg;
Packit Service b38f0b
Packit Service b38f0b
    if (null_auth)
Packit Service b38f0b
        *null_auth = -1; /* unknown */
Packit Service b38f0b
    if (null_cipher)
Packit Service b38f0b
        *null_cipher = -1; /* unknown */
Packit Service b38f0b
    if (NULL == ssl)
Packit Service b38f0b
        return;
Packit Service b38f0b
Packit Service b38f0b
    cipher = SSL_get_current_cipher(ssl);
Packit Service b38f0b
    if (NULL == cipher) {
Packit Service b38f0b
        DEBUGMSGTL(("ssl:cipher", "no cipher yet\n"));
Packit Service b38f0b
        return;
Packit Service b38f0b
    }
Packit Service b38f0b
    SSL_CIPHER_description(NETSNMP_REMOVE_CONST(SSL_CIPHER *, cipher), tmp_buf, sizeof(tmp_buf));
Packit Service b38f0b
    /** no \n since tmp_buf already has one */
Packit Service b38f0b
    DEBUGMSGTL(("ssl:cipher", "current cipher: %s", tmp_buf));
Packit Service b38f0b
Packit Service b38f0b
    /*
Packit Service b38f0b
     * run "openssl ciphers -v eNULL" and "openssl ciphers -v aNULL"
Packit Service b38f0b
     * to see NULL encryption/authentication algorithms. e.g.
Packit Service b38f0b
     *
Packit Service b38f0b
     * EXP-ADH-RC4-MD5 SSLv3 Kx=DH(512) Au=None Enc=RC4(40) Mac=MD5  export
Packit Service b38f0b
     * NULL-SHA        SSLv3 Kx=RSA     Au=RSA  Enc=None    Mac=SHA1
Packit Service b38f0b
     */
Packit Service b38f0b
    if (null_cipher) {
Packit Service b38f0b
        cipher_alg = strstr(tmp_buf, "Enc=");
Packit Service b38f0b
        if (cipher_alg) {
Packit Service b38f0b
            cipher_alg += 4;
Packit Service b38f0b
            if (strncmp(cipher_alg,"None", 4) == 0)
Packit Service b38f0b
                *null_cipher = 1;
Packit Service b38f0b
            else
Packit Service b38f0b
                *null_cipher = 0;
Packit Service b38f0b
        }
Packit Service b38f0b
    }
Packit Service b38f0b
    if (null_auth) {
Packit Service b38f0b
        auth_alg = strstr(tmp_buf, "Au=");
Packit Service b38f0b
        if (auth_alg) {
Packit Service b38f0b
            auth_alg += 3;
Packit Service b38f0b
            if (strncmp(auth_alg,"None", 4) == 0)
Packit Service b38f0b
                *null_auth = 1;
Packit Service b38f0b
            else
Packit Service b38f0b
                *null_auth = 0;
Packit Service b38f0b
        }
Packit Service b38f0b
    }
Packit Service b38f0b
}
Packit Service b38f0b
Packit Service b38f0b
#ifndef HAVE_X509_GET_SIGNATURE_NID
Packit Service b38f0b
int X509_get_signature_nid(const X509 *x)
Packit Service b38f0b
{
Packit Service b38f0b
    return OBJ_obj2nid(x->sig_alg->algorithm);
Packit Service b38f0b
}
Packit Service b38f0b
#endif
Packit Service b38f0b
Packit Service b38f0b
#ifndef HAVE_ASN1_STRING_GET0_DATA
Packit Service b38f0b
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
Packit Service b38f0b
{
Packit Service b38f0b
    return x->data;
Packit Service b38f0b
}
Packit Service b38f0b
#endif
Packit Service b38f0b
Packit Service b38f0b
#ifndef HAVE_X509_NAME_ENTRY_GET_OBJECT
Packit Service b38f0b
ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne)
Packit Service b38f0b
{
Packit Service b38f0b
    if (ne == NULL)
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    return ne->object;
Packit Service b38f0b
}
Packit Service b38f0b
#endif
Packit Service b38f0b
Packit Service b38f0b
#ifndef HAVE_X509_NAME_ENTRY_GET_DATA
Packit Service b38f0b
ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne)
Packit Service b38f0b
{
Packit Service b38f0b
    if (ne == NULL)
Packit Service b38f0b
        return NULL;
Packit Service b38f0b
    return ne->value;
Packit Service b38f0b
}
Packit Service b38f0b
#endif
Packit Service b38f0b
Packit Service b38f0b
#ifndef HAVE_TLS_METHOD
Packit Service b38f0b
const SSL_METHOD *TLS_method(void)
Packit Service b38f0b
{
Packit Service b38f0b
    return TLSv1_method();
Packit Service b38f0b
}
Packit Service b38f0b
#endif
Packit Service b38f0b
Packit Service b38f0b
#ifndef HAVE_DTLS_METHOD
Packit Service b38f0b
const SSL_METHOD *DTLS_method(void)
Packit Service b38f0b
{
Packit Service b38f0b
    return DTLSv1_method();
Packit Service b38f0b
}
Packit Service b38f0b
#endif
Packit Service b38f0b
Packit Service b38f0b
#endif /* NETSNMP_USE_OPENSSL && HAVE_LIBSSL && !defined(NETSNMP_FEATURE_REMOVE_CERT_UTIL) */