Blame snmplib/cert_util.c

Packit fcad23
/*
Packit fcad23
 * Portions of this file are subject to the following copyright(s).  See
Packit fcad23
 * the Net-SNMP's COPYING file for more details and other copyrights
Packit fcad23
 * that may apply:
Packit fcad23
 *
Packit fcad23
 * Portions of this file are copyrighted by:
Packit fcad23
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
Packit fcad23
 * Use is subject to license terms specified in the COPYING file
Packit fcad23
 * distributed with the Net-SNMP package.
Packit fcad23
 */
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#include <net-snmp/net-snmp-features.h>
Packit fcad23
Packit fcad23
#if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_LIBSSL) && NETSNMP_TRANSPORT_TLSBASE_DOMAIN
Packit fcad23
netsnmp_feature_child_of(cert_util_all, libnetsnmp)
Packit fcad23
netsnmp_feature_child_of(cert_util, cert_util_all)
Packit fcad23
#ifdef NETSNMP_FEATURE_REQUIRE_CERT_UTIL
Packit fcad23
netsnmp_feature_require(container_directory)
Packit fcad23
netsnmp_feature_require(container_fifo)
Packit fcad23
netsnmp_feature_require(container_dup)
Packit fcad23
netsnmp_feature_require(container_free_all)
Packit fcad23
netsnmp_feature_require(subcontainer_find)
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(cert_map_remove, netsnmp_unused)
Packit fcad23
netsnmp_feature_child_of(cert_map_find, netsnmp_unused)
Packit fcad23
netsnmp_feature_child_of(tlstmparams_external, cert_util_all)
Packit fcad23
netsnmp_feature_child_of(tlstmparams_container, tlstmparams_external)
Packit fcad23
netsnmp_feature_child_of(tlstmparams_remove, tlstmparams_external)
Packit fcad23
netsnmp_feature_child_of(tlstmparams_find, tlstmparams_external)
Packit fcad23
netsnmp_feature_child_of(tlstmAddr_remove, netsnmp_unused)
Packit fcad23
netsnmp_feature_child_of(tlstmaddr_external, cert_util_all)
Packit fcad23
netsnmp_feature_child_of(tlstmaddr_container, tlstmaddr_external)
Packit fcad23
netsnmp_feature_child_of(tlstmAddr_get_serverId, tlstmaddr_external)
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(cert_fingerprints, cert_util_all)
Packit fcad23
netsnmp_feature_child_of(tls_fingerprint_build, cert_util_all)
Packit fcad23
Packit fcad23
#endif /* NETSNMP_FEATURE_REQUIRE_CERT_UTIL */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CERT_UTIL
Packit fcad23
Packit fcad23
#include <ctype.h>
Packit fcad23
Packit fcad23
#if HAVE_STDLIB_H
Packit fcad23
#include <stdlib.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#if HAVE_STRING_H
Packit fcad23
#include <string.h>
Packit fcad23
#else
Packit fcad23
#include <strings.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#if HAVE_SYS_STAT_H
Packit fcad23
#   include <sys/stat.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_DIRENT_H
Packit fcad23
# include <dirent.h>
Packit fcad23
# define NAMLEN(dirent) strlen((dirent)->d_name)
Packit fcad23
#else
Packit fcad23
# define dirent direct
Packit fcad23
# define NAMLEN(dirent) (dirent)->d_namlen
Packit fcad23
# if HAVE_SYS_NDIR_H
Packit fcad23
#  include <sys/ndir.h>
Packit fcad23
# endif
Packit fcad23
# if HAVE_SYS_DIR_H
Packit fcad23
#  include <sys/dir.h>
Packit fcad23
# endif
Packit fcad23
# if HAVE_NDIR_H
Packit fcad23
#  include <ndir.h>
Packit fcad23
# endif
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#if HAVE_DMALLOC_H
Packit fcad23
#include <dmalloc.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#include <net-snmp/types.h>
Packit fcad23
#include <net-snmp/output_api.h>
Packit fcad23
#include <net-snmp/config_api.h>
Packit fcad23
Packit fcad23
#include <net-snmp/library/snmp_assert.h>
Packit fcad23
#include <net-snmp/library/snmp_transport.h>
Packit fcad23
#include <net-snmp/library/system.h>
Packit fcad23
#include <net-snmp/library/tools.h>
Packit fcad23
#include <net-snmp/library/container.h>
Packit fcad23
#include <net-snmp/library/data_list.h>
Packit fcad23
#include <net-snmp/library/file_utils.h>
Packit fcad23
#include <net-snmp/library/dir_utils.h>
Packit fcad23
#include <net-snmp/library/read_config.h>
Packit fcad23
Packit fcad23
#include <openssl/ssl.h>
Packit fcad23
#include <openssl/err.h>
Packit fcad23
#include <openssl/x509v3.h>
Packit fcad23
#include <net-snmp/library/cert_util.h>
Packit fcad23
#include <net-snmp/library/snmp_openssl.h>
Packit fcad23
Packit fcad23
#ifndef NAME_MAX
Packit fcad23
#define NAME_MAX 255
Packit fcad23
#endif
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * bump this value whenever cert index format changes, so indexes
Packit fcad23
 * will be regenerated with new format.
Packit fcad23
 */
Packit fcad23
#define CERT_INDEX_FORMAT  1
Packit fcad23
Packit fcad23
static netsnmp_container *_certs = NULL;
Packit fcad23
static netsnmp_container *_keys = NULL;
Packit fcad23
static netsnmp_container *_maps = NULL;
Packit fcad23
static netsnmp_container *_tlstmParams = NULL;
Packit fcad23
static netsnmp_container *_tlstmAddr = NULL;
Packit fcad23
static struct snmp_enum_list *_certindexes = NULL;
Packit fcad23
Packit fcad23
static netsnmp_container *_trusted_certs = NULL;
Packit fcad23
Packit fcad23
static void _setup_containers(void);
Packit fcad23
Packit fcad23
static void _cert_indexes_load(void);
Packit fcad23
static void _cert_free(netsnmp_cert *cert, void *context);
Packit fcad23
static void _key_free(netsnmp_key *key, void *context);
Packit fcad23
static int  _cert_compare(netsnmp_cert *lhs, netsnmp_cert *rhs);
Packit fcad23
static int  _cert_sn_compare(netsnmp_cert *lhs, netsnmp_cert *rhs);
Packit fcad23
static int  _cert_sn_ncompare(netsnmp_cert *lhs, netsnmp_cert *rhs);
Packit fcad23
static int  _cert_cn_compare(netsnmp_cert *lhs, netsnmp_cert *rhs);
Packit fcad23
static int  _cert_fn_compare(netsnmp_cert_common *lhs,
Packit fcad23
                             netsnmp_cert_common *rhs);
Packit fcad23
static int  _cert_fn_ncompare(netsnmp_cert_common *lhs,
Packit fcad23
                              netsnmp_cert_common *rhs);
Packit fcad23
static void _find_partner(netsnmp_cert *cert, netsnmp_key *key);
Packit fcad23
static netsnmp_cert *_find_issuer(netsnmp_cert *cert);
Packit fcad23
static netsnmp_void_array *_cert_find_subset_fn(const char *filename,
Packit fcad23
                                                const char *directory);
Packit fcad23
static netsnmp_void_array *_cert_find_subset_sn(const char *subject);
Packit fcad23
static netsnmp_void_array *_key_find_subset(const char *filename);
Packit fcad23
static netsnmp_cert *_cert_find_fp(const char *fingerprint);
Packit fcad23
static char *_find_tlstmParams_fingerprint(const char *param);
Packit fcad23
static char *_find_tlstmAddr_fingerprint(const char *name);
Packit fcad23
static const char *_mode_str(u_char mode);
Packit fcad23
static const char *_where_str(u_int what);
Packit fcad23
void netsnmp_cert_dump_all(void);
Packit fcad23
Packit fcad23
int netsnmp_cert_load_x509(netsnmp_cert *cert);
Packit fcad23
Packit fcad23
void netsnmp_cert_free(netsnmp_cert *cert);
Packit fcad23
void netsnmp_key_free(netsnmp_key *key);
Packit fcad23
Packit fcad23
static int _certindex_add( const char *dirname, int i );
Packit fcad23
Packit fcad23
static int _time_filter(netsnmp_file *f, struct stat *idx);
Packit fcad23
Packit fcad23
static void _init_tlstmCertToTSN(void);
Packit fcad23
#define TRUSTCERT_CONFIG_TOKEN "trustCert"
Packit fcad23
static void _parse_trustcert(const char *token, char *line);
Packit fcad23
Packit fcad23
static void _init_tlstmParams(void);
Packit fcad23
static void _init_tlstmAddr(void);
Packit fcad23
Packit fcad23
/** mode descriptions should match up with header */
Packit fcad23
static const char _modes[][256] =
Packit fcad23
        {
Packit fcad23
            "none",
Packit fcad23
            "identity",
Packit fcad23
            "remote_peer",
Packit fcad23
            "identity+remote_peer",
Packit fcad23
            "reserved1",
Packit fcad23
            "reserved1+identity",
Packit fcad23
            "reserved1+remote_peer",
Packit fcad23
            "reserved1+identity+remote_peer",
Packit fcad23
            "CA",
Packit fcad23
            "CA+identity",
Packit fcad23
            "CA+remote_peer",
Packit fcad23
            "CA+identity+remote_peer",
Packit fcad23
            "CA+reserved1",
Packit fcad23
            "CA+reserved1+identity",
Packit fcad23
            "CA+reserved1+remote_peer",
Packit fcad23
            "CA+reserved1+identity+remote_peer",
Packit fcad23
        };
Packit fcad23
Packit fcad23
/* #####################################################################
Packit fcad23
 *
Packit fcad23
 * init and shutdown functions
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
Packit fcad23
void
Packit fcad23
_netsnmp_release_trustcerts(void)
Packit fcad23
{
Packit fcad23
    if (NULL != _trusted_certs) {
Packit fcad23
        CONTAINER_FREE_ALL(_trusted_certs, NULL);
Packit fcad23
        CONTAINER_FREE(_trusted_certs);
Packit fcad23
        _trusted_certs = NULL;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
_setup_trusted_certs(void)
Packit fcad23
{
Packit fcad23
    _trusted_certs = netsnmp_container_find("trusted_certs:fifo");
Packit fcad23
    if (NULL == _trusted_certs) {
Packit fcad23
        snmp_log(LOG_ERR, "could not create container for trusted certs\n");
Packit fcad23
        netsnmp_certs_shutdown();
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    _trusted_certs->container_name = strdup("trusted certificates");
Packit fcad23
    _trusted_certs->compare = (netsnmp_container_compare*) strcmp;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * secname mapping for servers.
Packit fcad23
 */
Packit fcad23
void
Packit fcad23
netsnmp_certs_agent_init(void)
Packit fcad23
{
Packit fcad23
    _init_tlstmCertToTSN();
Packit fcad23
    _init_tlstmParams();
Packit fcad23
    _init_tlstmAddr();
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_certs_init(void)
Packit fcad23
{
Packit fcad23
    const char *trustCert_help = TRUSTCERT_CONFIG_TOKEN
Packit fcad23
        " FINGERPRINT|FILENAME";
Packit fcad23
Packit fcad23
    register_config_handler("snmp", TRUSTCERT_CONFIG_TOKEN,
Packit fcad23
                            _parse_trustcert, _netsnmp_release_trustcerts,
Packit fcad23
                            trustCert_help);
Packit fcad23
    _setup_containers();
Packit fcad23
Packit fcad23
    /** add certificate type mapping */
Packit fcad23
    se_add_pair_to_slist("cert_types", strdup("pem"), NS_CERT_TYPE_PEM);
Packit fcad23
    se_add_pair_to_slist("cert_types", strdup("crt"), NS_CERT_TYPE_DER);
Packit fcad23
    se_add_pair_to_slist("cert_types", strdup("cer"), NS_CERT_TYPE_DER);
Packit fcad23
    se_add_pair_to_slist("cert_types", strdup("cert"), NS_CERT_TYPE_DER);
Packit fcad23
    se_add_pair_to_slist("cert_types", strdup("der"), NS_CERT_TYPE_DER);
Packit fcad23
    se_add_pair_to_slist("cert_types", strdup("key"), NS_CERT_TYPE_KEY);
Packit fcad23
    se_add_pair_to_slist("cert_types", strdup("private"), NS_CERT_TYPE_KEY);
Packit fcad23
Packit fcad23
    /** hash algs */
Packit fcad23
    se_add_pair_to_slist("cert_hash_alg", strdup("sha1"), NS_HASH_SHA1);
Packit fcad23
    se_add_pair_to_slist("cert_hash_alg", strdup("md5"), NS_HASH_MD5);
Packit fcad23
    se_add_pair_to_slist("cert_hash_alg", strdup("sha224"), NS_HASH_SHA224);
Packit fcad23
    se_add_pair_to_slist("cert_hash_alg", strdup("sha256"), NS_HASH_SHA256);
Packit fcad23
    se_add_pair_to_slist("cert_hash_alg", strdup("sha384"), NS_HASH_SHA384);
Packit fcad23
    se_add_pair_to_slist("cert_hash_alg", strdup("sha512"), NS_HASH_SHA512);
Packit fcad23
Packit fcad23
    /** map types */
Packit fcad23
    se_add_pair_to_slist("cert_map_type", strdup("cn"),
Packit fcad23
                         TSNM_tlstmCertCommonName);
Packit fcad23
    se_add_pair_to_slist("cert_map_type", strdup("ip"),
Packit fcad23
                         TSNM_tlstmCertSANIpAddress);
Packit fcad23
    se_add_pair_to_slist("cert_map_type", strdup("rfc822"),
Packit fcad23
                         TSNM_tlstmCertSANRFC822Name);
Packit fcad23
    se_add_pair_to_slist("cert_map_type", strdup("dns"),
Packit fcad23
                         TSNM_tlstmCertSANDNSName);
Packit fcad23
    se_add_pair_to_slist("cert_map_type", strdup("any"), TSNM_tlstmCertSANAny);
Packit fcad23
    se_add_pair_to_slist("cert_map_type", strdup("sn"),
Packit fcad23
                         TSNM_tlstmCertSpecified);
Packit fcad23
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_certs_shutdown(void)
Packit fcad23
{
Packit fcad23
    DEBUGMSGT(("cert:util:shutdown","shutdown\n"));
Packit fcad23
    if (_maps) {
Packit fcad23
        CONTAINER_FREE_ALL(_maps, NULL);
Packit fcad23
        CONTAINER_FREE(_maps);
Packit fcad23
        _maps = NULL;
Packit fcad23
    }
Packit fcad23
    if (NULL != _certs) {
Packit fcad23
        CONTAINER_FREE_ALL(_certs, NULL);
Packit fcad23
        CONTAINER_FREE(_certs);
Packit fcad23
        _certs = NULL;
Packit fcad23
    }
Packit fcad23
    if (NULL != _keys) {
Packit fcad23
        CONTAINER_FREE_ALL(_keys, NULL);
Packit fcad23
        CONTAINER_FREE(_keys);
Packit fcad23
        _keys = NULL;
Packit fcad23
    }
Packit fcad23
    _netsnmp_release_trustcerts();
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_certs_load(void)
Packit fcad23
{
Packit fcad23
    netsnmp_iterator  *itr;
Packit fcad23
    netsnmp_key        *key;
Packit fcad23
    netsnmp_cert       *cert;
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:util:init","init\n"));
Packit fcad23
Packit fcad23
    if (NULL == _certs) {
Packit fcad23
        snmp_log(LOG_ERR, "cant load certs without container\n");
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (CONTAINER_SIZE(_certs) != 0) {
Packit fcad23
        DEBUGMSGT(("cert:util:init", "ignoring duplicate init\n"));
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    netsnmp_init_openssl();
Packit fcad23
Packit fcad23
    /** scan config dirs for certs */
Packit fcad23
    _cert_indexes_load();
Packit fcad23
Packit fcad23
    /** match up keys w/certs */
Packit fcad23
    itr = CONTAINER_ITERATOR(_keys);
Packit fcad23
    if (NULL == itr) {
Packit fcad23
        snmp_log(LOG_ERR, "could not get iterator for keys\n");
Packit fcad23
        netsnmp_certs_shutdown();
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    key = ITERATOR_FIRST(itr);
Packit fcad23
    for( ; key; key = ITERATOR_NEXT(itr))
Packit fcad23
        _find_partner(NULL, key);
Packit fcad23
    ITERATOR_RELEASE(itr);
Packit fcad23
Packit fcad23
    DEBUGIF("cert:dump") {
Packit fcad23
        itr = CONTAINER_ITERATOR(_certs);
Packit fcad23
        if (NULL == itr) {
Packit fcad23
            snmp_log(LOG_ERR, "could not get iterator for certs\n");
Packit fcad23
            netsnmp_certs_shutdown();
Packit fcad23
            return;
Packit fcad23
        }
Packit fcad23
        cert = ITERATOR_FIRST(itr);
Packit fcad23
        for( ; cert; cert = ITERATOR_NEXT(itr)) {
Packit fcad23
            netsnmp_cert_load_x509(cert);
Packit fcad23
        }
Packit fcad23
        ITERATOR_RELEASE(itr);
Packit fcad23
        DEBUGMSGT(("cert:dump",
Packit fcad23
                   "-------------------- Certificates -----------------\n"));
Packit fcad23
        netsnmp_cert_dump_all();
Packit fcad23
        DEBUGMSGT(("cert:dump",
Packit fcad23
                   "------------------------ End ----------------------\n"));
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
/* #####################################################################
Packit fcad23
 *
Packit fcad23
 * cert container functions
Packit fcad23
 */
Packit fcad23
Packit fcad23
static netsnmp_container *
Packit fcad23
_get_cert_container(const char *use)
Packit fcad23
{
Packit fcad23
    netsnmp_container *c;
Packit fcad23
Packit fcad23
    c = netsnmp_container_find("certs:binary_array");
Packit fcad23
    if (NULL == c) {
Packit fcad23
        snmp_log(LOG_ERR, "could not create container for %s\n", use);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    c->container_name = strdup(use);
Packit fcad23
    c->free_item = (netsnmp_container_obj_func*)_cert_free;
Packit fcad23
    c->compare = (netsnmp_container_compare*)_cert_compare;
Packit fcad23
Packit fcad23
    return c;
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
_setup_containers(void)
Packit fcad23
{
Packit fcad23
    netsnmp_container *additional_keys;
Packit fcad23
Packit fcad23
    _certs = _get_cert_container("netsnmp certificates");
Packit fcad23
    if (NULL == _certs)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    /** additional keys: common name */
Packit fcad23
    additional_keys = netsnmp_container_find("certs_cn:binary_array");
Packit fcad23
    if (NULL == additional_keys) {
Packit fcad23
        snmp_log(LOG_ERR, "could not create CN container for certificates\n");
Packit fcad23
        netsnmp_certs_shutdown();
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    additional_keys->container_name = strdup("certs_cn");
Packit fcad23
    additional_keys->free_item = NULL;
Packit fcad23
    additional_keys->compare = (netsnmp_container_compare*)_cert_cn_compare;
Packit fcad23
    netsnmp_container_add_index(_certs, additional_keys);
Packit fcad23
Packit fcad23
    /** additional keys: subject name */
Packit fcad23
    additional_keys = netsnmp_container_find("certs_sn:binary_array");
Packit fcad23
    if (NULL == additional_keys) {
Packit fcad23
        snmp_log(LOG_ERR, "could not create SN container for certificates\n");
Packit fcad23
        netsnmp_certs_shutdown();
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    additional_keys->container_name = strdup("certs_sn");
Packit fcad23
    additional_keys->free_item = NULL;
Packit fcad23
    additional_keys->compare = (netsnmp_container_compare*)_cert_sn_compare;
Packit fcad23
    additional_keys->ncompare = (netsnmp_container_compare*)_cert_sn_ncompare;
Packit fcad23
    netsnmp_container_add_index(_certs, additional_keys);
Packit fcad23
Packit fcad23
    /** additional keys: file name */
Packit fcad23
    additional_keys = netsnmp_container_find("certs_fn:binary_array");
Packit fcad23
    if (NULL == additional_keys) {
Packit fcad23
        snmp_log(LOG_ERR, "could not create FN container for certificates\n");
Packit fcad23
        netsnmp_certs_shutdown();
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    additional_keys->container_name = strdup("certs_fn");
Packit fcad23
    additional_keys->free_item = NULL;
Packit fcad23
    additional_keys->compare = (netsnmp_container_compare*)_cert_fn_compare;
Packit fcad23
    additional_keys->ncompare = (netsnmp_container_compare*)_cert_fn_ncompare;
Packit fcad23
    netsnmp_container_add_index(_certs, additional_keys);
Packit fcad23
Packit fcad23
    _keys = netsnmp_container_find("cert_keys:binary_array");
Packit fcad23
    if (NULL == _keys) {
Packit fcad23
        snmp_log(LOG_ERR, "could not create container for certificate keys\n");
Packit fcad23
        netsnmp_certs_shutdown();
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    _keys->container_name = strdup("netsnmp certificate keys");
Packit fcad23
    _keys->free_item = (netsnmp_container_obj_func*)_key_free;
Packit fcad23
    _keys->compare = (netsnmp_container_compare*)_cert_fn_compare;
Packit fcad23
Packit fcad23
    _setup_trusted_certs();
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_container *
Packit fcad23
netsnmp_cert_map_container(void)
Packit fcad23
{
Packit fcad23
    return _maps;
Packit fcad23
}
Packit fcad23
Packit fcad23
static netsnmp_cert *
Packit fcad23
_new_cert(const char *dirname, const char *filename, int certType,
Packit fcad23
          int hashType, const char *fingerprint, const char *common_name,
Packit fcad23
          const char *subject)
Packit fcad23
{
Packit fcad23
    netsnmp_cert    *cert;
Packit fcad23
Packit fcad23
    if ((NULL == dirname) || (NULL == filename)) {
Packit fcad23
        snmp_log(LOG_ERR, "bad parameters to _new_cert\n");
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    cert = SNMP_MALLOC_TYPEDEF(netsnmp_cert);
Packit fcad23
    if (NULL == cert) {
Packit fcad23
        snmp_log(LOG_ERR,"could not allocate memory for certificate at %s/%s\n",
Packit fcad23
                 dirname, filename);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DEBUGMSGT(("9:cert:struct:new","new cert 0x%p for %s\n", cert, filename));
Packit fcad23
Packit fcad23
    cert->info.dir = strdup(dirname);
Packit fcad23
    cert->info.filename = strdup(filename);
Packit fcad23
    cert->info.allowed_uses = NS_CERT_REMOTE_PEER;
Packit fcad23
    cert->info.type = certType;
Packit fcad23
    if (fingerprint) {
Packit fcad23
        cert->hash_type = hashType;
Packit fcad23
        cert->fingerprint = strdup(fingerprint);
Packit fcad23
    }
Packit fcad23
    if (common_name)
Packit fcad23
        cert->common_name = strdup(common_name);
Packit fcad23
    if (subject)
Packit fcad23
        cert->subject = strdup(subject);
Packit fcad23
Packit fcad23
    return cert;
Packit fcad23
}
Packit fcad23
Packit fcad23
static netsnmp_key *
Packit fcad23
_new_key(const char *dirname, const char *filename)
Packit fcad23
{
Packit fcad23
    netsnmp_key    *key;
Packit fcad23
    struct stat     fstat;
Packit fcad23
    char            fn[SNMP_MAXPATH];
Packit fcad23
Packit fcad23
    if ((NULL == dirname) || (NULL == filename)) {
Packit fcad23
        snmp_log(LOG_ERR, "bad parameters to _new_key\n");
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /** check file permissions */
Packit fcad23
    snprintf(fn, sizeof(fn), "%s/%s", dirname, filename);
Packit fcad23
    if (stat(fn, &fstat) != 0) {
Packit fcad23
        snmp_log(LOG_ERR, "could  not stat %s\n", fn);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
#if !defined(_MSC_VER)
Packit fcad23
    if ((fstat.st_mode & S_IROTH) || (fstat.st_mode & S_IWOTH)) {
Packit fcad23
        snmp_log(LOG_ERR,
Packit fcad23
                 "refusing to read world readable or writable key %s\n", fn);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    key = SNMP_MALLOC_TYPEDEF(netsnmp_key);
Packit fcad23
    if (NULL == key) {
Packit fcad23
        snmp_log(LOG_ERR, "could not allocate memory for key at %s/%s\n",
Packit fcad23
                 dirname, filename);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:key:struct:new","new key %p for %s\n", key, filename));
Packit fcad23
Packit fcad23
    key->info.type = NS_CERT_TYPE_KEY;
Packit fcad23
    key->info.dir = strdup(dirname);
Packit fcad23
    key->info.filename = strdup(filename);
Packit fcad23
    key->info.allowed_uses = NS_CERT_IDENTITY;
Packit fcad23
Packit fcad23
    return key;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_cert_free(netsnmp_cert *cert)
Packit fcad23
{
Packit fcad23
    if (NULL == cert)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    DEBUGMSGT(("9:cert:struct:free","freeing cert %p, %s (fp %s; CN %s)\n",
Packit fcad23
               cert, cert->info.filename ? cert->info.filename : "UNK",
Packit fcad23
               cert->fingerprint ? cert->fingerprint : "UNK",
Packit fcad23
               cert->common_name ? cert->common_name : "UNK"));
Packit fcad23
Packit fcad23
    SNMP_FREE(cert->info.dir);
Packit fcad23
    SNMP_FREE(cert->info.filename);
Packit fcad23
    SNMP_FREE(cert->subject);
Packit fcad23
    SNMP_FREE(cert->issuer);
Packit fcad23
    SNMP_FREE(cert->fingerprint);
Packit fcad23
    SNMP_FREE(cert->common_name);
Packit fcad23
    if (cert->ocert)
Packit fcad23
        X509_free(cert->ocert);
Packit fcad23
    if (cert->key && cert->key->cert == cert)
Packit fcad23
        cert->key->cert = NULL;
Packit fcad23
Packit fcad23
    free(cert); /* SNMP_FREE not needed on parameters */
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_key_free(netsnmp_key *key)
Packit fcad23
{
Packit fcad23
    if (NULL == key)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:key:struct:free","freeing key %p, %s\n",
Packit fcad23
               key, key->info.filename ? key->info.filename : "UNK"));
Packit fcad23
Packit fcad23
    SNMP_FREE(key->info.dir);
Packit fcad23
    SNMP_FREE(key->info.filename);
Packit fcad23
    EVP_PKEY_free(key->okey);
Packit fcad23
    if (key->cert && key->cert->key == key)
Packit fcad23
        key->cert->key = NULL;
Packit fcad23
Packit fcad23
    free(key); /* SNMP_FREE not needed on parameters */
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
_cert_free(netsnmp_cert *cert, void *context)
Packit fcad23
{
Packit fcad23
    netsnmp_cert_free(cert);
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
_key_free(netsnmp_key *key, void *context)
Packit fcad23
{
Packit fcad23
    netsnmp_key_free(key);
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_cert_compare(netsnmp_cert *lhs, netsnmp_cert *rhs)
Packit fcad23
{
Packit fcad23
    netsnmp_assert((lhs != NULL) && (rhs != NULL));
Packit fcad23
    netsnmp_assert((lhs->fingerprint != NULL) &&
Packit fcad23
                   (rhs->fingerprint != NULL));
Packit fcad23
Packit fcad23
    /** ignore hash type? */
Packit fcad23
    return strcmp(lhs->fingerprint, rhs->fingerprint);
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_cert_path_compare(netsnmp_cert_common *lhs, netsnmp_cert_common *rhs)
Packit fcad23
{
Packit fcad23
    int rc;
Packit fcad23
Packit fcad23
    netsnmp_assert((lhs != NULL) && (rhs != NULL));
Packit fcad23
    
Packit fcad23
    /** dir name first */
Packit fcad23
    rc = strcmp(lhs->dir, rhs->dir);
Packit fcad23
    if (rc)
Packit fcad23
        return rc;
Packit fcad23
Packit fcad23
    /** filename */
Packit fcad23
    return strcmp(lhs->filename, rhs->filename);
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_cert_cn_compare(netsnmp_cert *lhs, netsnmp_cert *rhs)
Packit fcad23
{
Packit fcad23
    int rc;
Packit fcad23
    const char *lhcn, *rhcn;
Packit fcad23
Packit fcad23
    netsnmp_assert((lhs != NULL) && (rhs != NULL));
Packit fcad23
Packit fcad23
    if (NULL == lhs->common_name)
Packit fcad23
        lhcn = "";
Packit fcad23
    else
Packit fcad23
        lhcn = lhs->common_name;
Packit fcad23
    if (NULL == rhs->common_name)
Packit fcad23
        rhcn = "";
Packit fcad23
    else
Packit fcad23
        rhcn = rhs->common_name;
Packit fcad23
Packit fcad23
    rc = strcmp(lhcn, rhcn);
Packit fcad23
    if (rc)
Packit fcad23
        return rc;
Packit fcad23
Packit fcad23
    /** in case of equal common names, sub-sort by path */
Packit fcad23
    return _cert_path_compare((netsnmp_cert_common*)lhs,
Packit fcad23
                              (netsnmp_cert_common*)rhs);
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_cert_sn_compare(netsnmp_cert *lhs, netsnmp_cert *rhs)
Packit fcad23
{
Packit fcad23
    int rc;
Packit fcad23
    const char *lhsn, *rhsn;
Packit fcad23
Packit fcad23
    netsnmp_assert((lhs != NULL) && (rhs != NULL));
Packit fcad23
Packit fcad23
    if (NULL == lhs->subject)
Packit fcad23
        lhsn = "";
Packit fcad23
    else
Packit fcad23
        lhsn = lhs->subject;
Packit fcad23
    if (NULL == rhs->subject)
Packit fcad23
        rhsn = "";
Packit fcad23
    else
Packit fcad23
        rhsn = rhs->subject;
Packit fcad23
Packit fcad23
    rc = strcmp(lhsn, rhsn);
Packit fcad23
    if (rc)
Packit fcad23
        return rc;
Packit fcad23
Packit fcad23
    /** in case of equal common names, sub-sort by path */
Packit fcad23
    return _cert_path_compare((netsnmp_cert_common*)lhs,
Packit fcad23
                              (netsnmp_cert_common*)rhs);
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_cert_fn_compare(netsnmp_cert_common *lhs, netsnmp_cert_common *rhs)
Packit fcad23
{
Packit fcad23
    int rc;
Packit fcad23
Packit fcad23
    netsnmp_assert((lhs != NULL) && (rhs != NULL));
Packit fcad23
Packit fcad23
    rc = strcmp(lhs->filename, rhs->filename);
Packit fcad23
    if (rc)
Packit fcad23
        return rc;
Packit fcad23
Packit fcad23
    /** in case of equal common names, sub-sort by dir */
Packit fcad23
    return strcmp(lhs->dir, rhs->dir);
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_cert_fn_ncompare(netsnmp_cert_common *lhs, netsnmp_cert_common *rhs)
Packit fcad23
{
Packit fcad23
    netsnmp_assert((lhs != NULL) && (rhs != NULL));
Packit fcad23
    netsnmp_assert((lhs->filename != NULL) && (rhs->filename != NULL));
Packit fcad23
Packit fcad23
    return strncmp(lhs->filename, rhs->filename, strlen(rhs->filename));
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_cert_sn_ncompare(netsnmp_cert *lhs, netsnmp_cert *rhs)
Packit fcad23
{
Packit fcad23
    netsnmp_assert((lhs != NULL) && (rhs != NULL));
Packit fcad23
    netsnmp_assert((lhs->subject != NULL) && (rhs->subject != NULL));
Packit fcad23
Packit fcad23
    return strncmp(lhs->subject, rhs->subject, strlen(rhs->subject));
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_cert_ext_type(const char *ext)
Packit fcad23
{
Packit fcad23
    int rc = se_find_value_in_slist("cert_types", ext);
Packit fcad23
    if (SE_DNE == rc)
Packit fcad23
        return NS_CERT_TYPE_UNKNOWN;
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_type_from_filename(const char *filename)
Packit fcad23
{
Packit fcad23
    char     *pos;
Packit fcad23
    int       type;
Packit fcad23
Packit fcad23
    if (NULL == filename)
Packit fcad23
        return NS_CERT_TYPE_UNKNOWN;
Packit fcad23
Packit fcad23
    pos = strrchr(filename, '.');
Packit fcad23
    if (NULL == pos)
Packit fcad23
        return NS_CERT_TYPE_UNKNOWN;
Packit fcad23
Packit fcad23
    type = _cert_ext_type(++pos);
Packit fcad23
    return type;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * filter functions; return 1 to include file, 0 to exclude
Packit fcad23
 */
Packit fcad23
static int
Packit fcad23
_cert_cert_filter(const char *filename)
Packit fcad23
{
Packit fcad23
    int  len = strlen(filename);
Packit fcad23
    const char *pos;
Packit fcad23
Packit fcad23
    if (len < 5) /* shortest name: x.YYY */
Packit fcad23
        return 0;
Packit fcad23
Packit fcad23
    pos = strrchr(filename, '.');
Packit fcad23
    if (NULL == pos)
Packit fcad23
        return 0;
Packit fcad23
Packit fcad23
    if (_cert_ext_type(++pos) != NS_CERT_TYPE_UNKNOWN)
Packit fcad23
        return 1;
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
/* #####################################################################
Packit fcad23
 *
Packit fcad23
 * cert index functions
Packit fcad23
 *
Packit fcad23
 * This code mimics what the mib index code does. The persistent
Packit fcad23
 * directory will have a subdirectory named 'cert_indexes'. Inside
Packit fcad23
 * this directory will be some number of files with ascii numeric
Packit fcad23
 * names (0, 1, 2, etc). Each of these files will start with a line
Packit fcad23
 * with the text "DIR ", followed by a directory name. The rest of the
Packit fcad23
 * file will be certificate fields and the certificate file name, one
Packit fcad23
 * certificate per line. The numeric file name is the integer 'directory
Packit fcad23
 * index'.
Packit fcad23
 */
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * _certindex_add
Packit fcad23
 *
Packit fcad23
 * add a directory name to the indexes
Packit fcad23
 */
Packit fcad23
static int
Packit fcad23
_certindex_add( const char *dirname, int i )
Packit fcad23
{
Packit fcad23
    int rc;
Packit fcad23
    char *dirname_copy = strdup(dirname);
Packit fcad23
Packit fcad23
    if ( i == -1 ) {
Packit fcad23
        int max = se_find_free_value_in_list(_certindexes);
Packit fcad23
        if (SE_DNE == max)
Packit fcad23
            i = 0;
Packit fcad23
        else
Packit fcad23
            i = max;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:index:add","dir %s at index %d\n", dirname, i ));
Packit fcad23
    rc = se_add_pair_to_list(&_certindexes, dirname_copy, i);
Packit fcad23
    if (SE_OK != rc) {
Packit fcad23
        snmp_log(LOG_ERR, "adding certindex dirname failed; "
Packit fcad23
                 "%d (%s) not added\n", i, dirname);
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return i;
Packit fcad23
}
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * _certindex_load
Packit fcad23
 *
Packit fcad23
 * read in the existing indexes
Packit fcad23
 */
Packit fcad23
static void
Packit fcad23
_certindexes_load( void )
Packit fcad23
{
Packit fcad23
    DIR *dir;
Packit fcad23
    struct dirent *file;
Packit fcad23
    FILE *fp;
Packit fcad23
    char filename[SNMP_MAXPATH], line[300];
Packit fcad23
    int  i;
Packit fcad23
    char *cp, *pos;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Open the CERT index directory, or create it (empty)
Packit fcad23
     */
Packit fcad23
    snprintf( filename, sizeof(filename), "%s/cert_indexes",
Packit fcad23
              get_persistent_directory());
Packit fcad23
    filename[sizeof(filename)-1] = 0;
Packit fcad23
    dir = opendir( filename );
Packit fcad23
    if ( dir == NULL ) {
Packit fcad23
        DEBUGMSGT(("cert:index:load",
Packit fcad23
                   "creating new cert_indexes directory\n"));
Packit fcad23
        mkdirhier( filename, NETSNMP_AGENT_DIRECTORY_MODE, 0);
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Create a list of which directory each file refers to
Packit fcad23
     */
Packit fcad23
    while ((file = readdir( dir ))) {
Packit fcad23
        if ( !isdigit(0xFF & file->d_name[0]))
Packit fcad23
            continue;
Packit fcad23
        i = atoi( file->d_name );
Packit fcad23
Packit fcad23
        snprintf( filename, sizeof(filename), "%s/cert_indexes/%d",
Packit fcad23
              get_persistent_directory(), i );
Packit fcad23
        filename[sizeof(filename)-1] = 0;
Packit fcad23
        fp = fopen( filename, "r" );
Packit fcad23
        if ( !fp ) {
Packit fcad23
            DEBUGMSGT(("cert:index:load", "error opening index (%d)\n", i));
Packit fcad23
            continue;
Packit fcad23
        }
Packit fcad23
        cp = fgets( line, sizeof(line), fp );
Packit fcad23
        if ( cp ) {
Packit fcad23
            line[strlen(line)-1] = 0;
Packit fcad23
            pos = strrchr(line, ' ');
Packit fcad23
            if (pos)
Packit fcad23
                *pos = '\0';
Packit fcad23
            DEBUGMSGT(("9:cert:index:load","adding (%d) %s\n", i, line));
Packit fcad23
            (void)_certindex_add( line+4, i );  /* Skip 'DIR ' */
Packit fcad23
        } else {
Packit fcad23
            DEBUGMSGT(("cert:index:load", "Empty index (%d)\n", i));
Packit fcad23
        }
Packit fcad23
        fclose( fp );
Packit fcad23
    }
Packit fcad23
    closedir( dir );
Packit fcad23
}
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * _certindex_lookup
Packit fcad23
 *
Packit fcad23
 * find index for a directory
Packit fcad23
 */
Packit fcad23
static char *
Packit fcad23
_certindex_lookup( const char *dirname )
Packit fcad23
{
Packit fcad23
    int i;
Packit fcad23
    char filename[SNMP_MAXPATH];
Packit fcad23
Packit fcad23
Packit fcad23
    i = se_find_value_in_list(_certindexes, dirname);
Packit fcad23
    if (SE_DNE == i) {
Packit fcad23
        DEBUGMSGT(("9:cert:index:lookup","%s : (none)\n", dirname));
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    snprintf(filename, sizeof(filename), "%s/cert_indexes/%d",
Packit fcad23
             get_persistent_directory(), i);
Packit fcad23
    filename[sizeof(filename)-1] = 0;
Packit fcad23
    DEBUGMSGT(("cert:index:lookup", "%s (%d) %s\n", dirname, i, filename ));
Packit fcad23
    return strdup(filename);
Packit fcad23
}
Packit fcad23
Packit fcad23
static FILE *
Packit fcad23
_certindex_new( const char *dirname )
Packit fcad23
{
Packit fcad23
    FILE *fp;
Packit fcad23
    char  filename[SNMP_MAXPATH], *cp;
Packit fcad23
    int   i;
Packit fcad23
Packit fcad23
    cp = _certindex_lookup( dirname );
Packit fcad23
    if (!cp) {
Packit fcad23
        i  = _certindex_add( dirname, -1 );
Packit fcad23
        if (-1 == i)
Packit fcad23
            return NULL; /* msg already logged */
Packit fcad23
        snprintf( filename, sizeof(filename), "%s/cert_indexes/%d",
Packit fcad23
                  get_persistent_directory(), i );
Packit fcad23
        filename[sizeof(filename)-1] = 0;
Packit fcad23
        cp = filename;
Packit fcad23
    }
Packit fcad23
    DEBUGMSGT(("9:cert:index:new", "%s (%s)\n", dirname, cp ));
Packit fcad23
    fp = fopen( cp, "w" );
Packit fcad23
    if (fp)
Packit fcad23
        fprintf( fp, "DIR %s %d\n", dirname, CERT_INDEX_FORMAT );
Packit fcad23
    else
Packit fcad23
        DEBUGMSGTL(("cert:index", "error opening new index file %s\n", dirname));
Packit fcad23
Packit fcad23
    if (cp != filename)
Packit fcad23
        free(cp);
Packit fcad23
Packit fcad23
    return fp;
Packit fcad23
}
Packit fcad23
Packit fcad23
/* #####################################################################
Packit fcad23
 *
Packit fcad23
 * certificate utility functions
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
static X509 *
Packit fcad23
netsnmp_ocert_get(netsnmp_cert *cert)
Packit fcad23
{
Packit fcad23
    BIO            *certbio;
Packit fcad23
    X509           *ocert = NULL;
Packit fcad23
    EVP_PKEY       *okey = NULL;
Packit fcad23
    char            file[SNMP_MAXPATH];
Packit fcad23
    int             is_ca;
Packit fcad23
Packit fcad23
    if (NULL == cert)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    if (cert->ocert)
Packit fcad23
        return cert->ocert;
Packit fcad23
Packit fcad23
    if (NS_CERT_TYPE_UNKNOWN == cert->info.type) {
Packit fcad23
        cert->info.type = _type_from_filename(cert->info.filename);
Packit fcad23
        if (NS_CERT_TYPE_UNKNOWN == cert->info.type) {
Packit fcad23
            snmp_log(LOG_ERR, "unknown certificate type %d for %s\n",
Packit fcad23
                     cert->info.type, cert->info.filename);
Packit fcad23
            return NULL;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DEBUGMSGT(("9:cert:read", "Checking file %s\n", cert->info.filename));
Packit fcad23
Packit fcad23
    certbio = BIO_new(BIO_s_file());
Packit fcad23
    if (NULL == certbio) {
Packit fcad23
        snmp_log(LOG_ERR, "error creating BIO\n");
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    snprintf(file, sizeof(file),"%s/%s", cert->info.dir, cert->info.filename);
Packit fcad23
    if (BIO_read_filename(certbio, file) <=0) {
Packit fcad23
        snmp_log(LOG_ERR, "error reading certificate %s into BIO\n", file);
Packit fcad23
        BIO_vfree(certbio);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (NS_CERT_TYPE_UNKNOWN == cert->info.type) {
Packit fcad23
        char *pos = strrchr(cert->info.filename, '.');
Packit fcad23
        if (NULL == pos)
Packit fcad23
            return NULL;
Packit fcad23
        cert->info.type = _cert_ext_type(++pos);
Packit fcad23
        netsnmp_assert(cert->info.type != NS_CERT_TYPE_UNKNOWN);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    switch (cert->info.type) {
Packit fcad23
Packit fcad23
        case NS_CERT_TYPE_DER:
Packit fcad23
            ocert = d2i_X509_bio(certbio,NULL); /* DER/ASN1 */
Packit fcad23
            if (NULL != ocert)
Packit fcad23
                break;
Packit fcad23
            (void)BIO_reset(certbio);
Packit fcad23
            /* Check for PEM if DER didn't work */
Packit fcad23
            /* FALLTHROUGH */
Packit fcad23
Packit fcad23
        case NS_CERT_TYPE_PEM:
Packit fcad23
            ocert = PEM_read_bio_X509_AUX(certbio, NULL, NULL, NULL);
Packit fcad23
            if (NULL == ocert)
Packit fcad23
                break;
Packit fcad23
            if (NS_CERT_TYPE_DER == cert->info.type) {
Packit fcad23
                DEBUGMSGT(("9:cert:read", "Changing type from DER to PEM\n"));
Packit fcad23
                cert->info.type = NS_CERT_TYPE_PEM;
Packit fcad23
            }
Packit fcad23
            /** check for private key too */
Packit fcad23
            if (NULL == cert->key) {
Packit fcad23
                (void)BIO_reset(certbio);
Packit fcad23
                okey =  PEM_read_bio_PrivateKey(certbio, NULL, NULL, NULL);
Packit fcad23
                if (NULL != okey) {
Packit fcad23
                    netsnmp_key  *key;
Packit fcad23
                    DEBUGMSGT(("cert:read:key", "found key with cert in %s\n",
Packit fcad23
                               cert->info.filename));
Packit fcad23
                    key = _new_key(cert->info.dir, cert->info.filename);
Packit fcad23
                    if (NULL != key) {
Packit fcad23
                        key->okey = okey;
Packit fcad23
                        if (-1 == CONTAINER_INSERT(_keys, key)) {
Packit fcad23
                            DEBUGMSGT(("cert:read:key:add",
Packit fcad23
                                       "error inserting key into container\n"));
Packit fcad23
                            netsnmp_key_free(key);
Packit fcad23
                            key = NULL;
Packit fcad23
                        }
Packit fcad23
                        else {
Packit fcad23
                            DEBUGMSGT(("cert:read:partner", "%s match found!\n",
Packit fcad23
                                       cert->info.filename));
Packit fcad23
                            key->cert = cert;
Packit fcad23
                            cert->key = key;
Packit fcad23
                            cert->info.allowed_uses |= NS_CERT_IDENTITY;
Packit fcad23
                        }
Packit fcad23
                    }
Packit fcad23
                } /* null return from read */
Packit fcad23
            } /* null key */
Packit fcad23
            break;
Packit fcad23
#ifdef CERT_PKCS12_SUPPORT_MAYBE_LATER
Packit fcad23
        case NS_CERT_TYPE_PKCS12:
Packit fcad23
            (void)BIO_reset(certbio);
Packit fcad23
            PKCS12 *p12 = d2i_PKCS12_bio(certbio, NULL);
Packit fcad23
            if ( (NULL != p12) && (PKCS12_verify_mac(p12, "", 0) ||
Packit fcad23
                                   PKCS12_verify_mac(p12, NULL, 0)))
Packit fcad23
                PKCS12_parse(p12, "", NULL, &cert, NULL);
Packit fcad23
            break;
Packit fcad23
#endif
Packit fcad23
        default:
Packit fcad23
            snmp_log(LOG_ERR, "unknown certificate type %d for %s\n",
Packit fcad23
                     cert->info.type, cert->info.filename);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    BIO_vfree(certbio);
Packit fcad23
Packit fcad23
    if (NULL == ocert) {
Packit fcad23
        snmp_log(LOG_ERR, "error parsing certificate file %s\n",
Packit fcad23
                 cert->info.filename);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    cert->ocert = ocert;
Packit fcad23
    /*
Packit fcad23
     * X509_check_ca return codes:
Packit fcad23
     * 0 not a CA
Packit fcad23
     * 1 is a CA
Packit fcad23
     * 2 basicConstraints absent so "maybe" a CA
Packit fcad23
     * 3 basicConstraints absent but self signed V1.
Packit fcad23
     * 4 basicConstraints absent but keyUsage present and keyCertSign asserted.
Packit fcad23
     * 5 outdated Netscape Certificate Type CA extension.
Packit fcad23
     */
Packit fcad23
    is_ca = X509_check_ca(ocert);
Packit fcad23
    if (1 == is_ca)
Packit fcad23
        cert->info.allowed_uses |= NS_CERT_CA;
Packit fcad23
Packit fcad23
    if (NULL == cert->subject) {
Packit fcad23
        cert->subject = X509_NAME_oneline(X509_get_subject_name(ocert), NULL,
Packit fcad23
                                          0);
Packit fcad23
        DEBUGMSGT(("9:cert:add:subject", "subject name: %s\n", cert->subject));
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (NULL == cert->issuer) {
Packit fcad23
        cert->issuer = X509_NAME_oneline(X509_get_issuer_name(ocert), NULL, 0);
Packit fcad23
        if (strcmp(cert->subject, cert->issuer) == 0) {
Packit fcad23
            free(cert->issuer);
Packit fcad23
            cert->issuer = strdup("self-signed");
Packit fcad23
        }
Packit fcad23
        DEBUGMSGT(("9:cert:add:issuer", "CA issuer: %s\n", cert->issuer));
Packit fcad23
    }
Packit fcad23
    
Packit fcad23
    if (NULL == cert->fingerprint) {
Packit fcad23
        cert->hash_type = netsnmp_openssl_cert_get_hash_type(ocert);
Packit fcad23
        cert->fingerprint =
Packit fcad23
            netsnmp_openssl_cert_get_fingerprint(ocert, cert->hash_type);
Packit fcad23
    }
Packit fcad23
    
Packit fcad23
    if (NULL == cert->common_name) {
Packit fcad23
        cert->common_name =netsnmp_openssl_cert_get_commonName(ocert, NULL,
Packit fcad23
                                                               NULL);
Packit fcad23
        DEBUGMSGT(("9:cert:add:name","%s\n", cert->common_name));
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return ocert;
Packit fcad23
}
Packit fcad23
Packit fcad23
EVP_PKEY *
Packit fcad23
netsnmp_okey_get(netsnmp_key  *key)
Packit fcad23
{
Packit fcad23
    BIO            *keybio;
Packit fcad23
    EVP_PKEY       *okey;
Packit fcad23
    char            file[SNMP_MAXPATH];
Packit fcad23
Packit fcad23
    if (NULL == key)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    if (key->okey)
Packit fcad23
        return key->okey;
Packit fcad23
Packit fcad23
    snprintf(file, sizeof(file),"%s/%s", key->info.dir, key->info.filename);
Packit fcad23
    DEBUGMSGT(("cert:key:read", "Checking file %s\n", key->info.filename));
Packit fcad23
Packit fcad23
    keybio = BIO_new(BIO_s_file());
Packit fcad23
    if (NULL == keybio) {
Packit fcad23
        snmp_log(LOG_ERR, "error creating BIO\n");
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (BIO_read_filename(keybio, file) <=0) {
Packit fcad23
        snmp_log(LOG_ERR, "error reading certificate %s into BIO\n",
Packit fcad23
                 key->info.filename);
Packit fcad23
        BIO_vfree(keybio);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    okey = PEM_read_bio_PrivateKey(keybio, NULL, NULL, NULL);
Packit fcad23
    if (NULL == okey)
Packit fcad23
        snmp_log(LOG_ERR, "error parsing certificate file %s\n",
Packit fcad23
                 key->info.filename);
Packit fcad23
    else
Packit fcad23
        key->okey = okey;
Packit fcad23
Packit fcad23
    BIO_vfree(keybio);
Packit fcad23
Packit fcad23
    return okey;
Packit fcad23
}
Packit fcad23
Packit fcad23
static netsnmp_cert *
Packit fcad23
_find_issuer(netsnmp_cert *cert)
Packit fcad23
{
Packit fcad23
    netsnmp_void_array *matching;
Packit fcad23
    netsnmp_cert       *candidate, *issuer = NULL;
Packit fcad23
    int                 i;
Packit fcad23
Packit fcad23
    if ((NULL == cert) || (NULL == cert->issuer))
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    /** find matching subject names */
Packit fcad23
Packit fcad23
    matching = _cert_find_subset_sn(cert->issuer);
Packit fcad23
    if (NULL == matching)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    /** check each to see if it's the issuer */
Packit fcad23
    for ( i=0; (NULL == issuer) && (i < matching->size); ++i) {
Packit fcad23
        /** make sure we have ocert */
Packit fcad23
        candidate = (netsnmp_cert*)matching->array[i];
Packit fcad23
        if ((NULL == candidate->ocert) &&
Packit fcad23
            (netsnmp_ocert_get(candidate) == NULL))
Packit fcad23
            continue;
Packit fcad23
Packit fcad23
        /** compare **/
Packit fcad23
        if (netsnmp_openssl_cert_issued_by(candidate->ocert, cert->ocert))
Packit fcad23
            issuer = candidate;
Packit fcad23
    } /** candidate loop */
Packit fcad23
Packit fcad23
    free(matching->array);
Packit fcad23
    free(matching);
Packit fcad23
Packit fcad23
    return issuer;
Packit fcad23
}
Packit fcad23
Packit fcad23
#define CERT_LOAD_OK       0
Packit fcad23
#define CERT_LOAD_ERR     -1
Packit fcad23
#define CERT_LOAD_PARTIAL -2
Packit fcad23
int
Packit fcad23
netsnmp_cert_load_x509(netsnmp_cert *cert)
Packit fcad23
{
Packit fcad23
    int rc = CERT_LOAD_OK;
Packit fcad23
Packit fcad23
    /** load ocert */
Packit fcad23
    if ((NULL == cert->ocert) && (netsnmp_ocert_get(cert) == NULL)) {
Packit fcad23
        DEBUGMSGT(("cert:load:err", "couldn't load cert for %s\n",
Packit fcad23
                   cert->info.filename));
Packit fcad23
        rc = CERT_LOAD_ERR;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /** load key */
Packit fcad23
    if ((NULL != cert->key) && (NULL == cert->key->okey) &&
Packit fcad23
        (netsnmp_okey_get(cert->key) == NULL)) {
Packit fcad23
        DEBUGMSGT(("cert:load:err", "couldn't load key for cert %s\n",
Packit fcad23
                   cert->info.filename));
Packit fcad23
        rc = CERT_LOAD_ERR;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /** make sure we have cert chain */
Packit fcad23
    for (; cert && cert->issuer; cert = cert->issuer_cert) {
Packit fcad23
        /** skip self signed */
Packit fcad23
        if (strcmp(cert->issuer, "self-signed") == 0) {
Packit fcad23
            netsnmp_assert(cert->issuer_cert == NULL);
Packit fcad23
            break;
Packit fcad23
        }
Packit fcad23
        /** get issuer cert */
Packit fcad23
        if (NULL == cert->issuer_cert) {
Packit fcad23
            cert->issuer_cert =  _find_issuer(cert);
Packit fcad23
            if (NULL == cert->issuer_cert) {
Packit fcad23
                DEBUGMSGT(("cert:load:warn",
Packit fcad23
                           "couldn't load CA chain for cert %s\n",
Packit fcad23
                           cert->info.filename));
Packit fcad23
                rc = CERT_LOAD_PARTIAL;
Packit fcad23
                break;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
        /** get issuer ocert */
Packit fcad23
        if ((NULL == cert->issuer_cert->ocert) &&
Packit fcad23
            (netsnmp_ocert_get(cert->issuer_cert) == NULL)) {
Packit fcad23
            DEBUGMSGT(("cert:load:warn", "couldn't load cert chain for %s\n",
Packit fcad23
                       cert->info.filename));
Packit fcad23
            rc = CERT_LOAD_PARTIAL;
Packit fcad23
            break;
Packit fcad23
        }
Packit fcad23
    } /* cert CA for loop */
Packit fcad23
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
_find_partner(netsnmp_cert *cert, netsnmp_key *key)
Packit fcad23
{
Packit fcad23
    netsnmp_void_array *matching = NULL;
Packit fcad23
    char                filename[NAME_MAX], *pos;
Packit fcad23
Packit fcad23
    if ((cert && key) || (!cert && ! key)) {
Packit fcad23
        DEBUGMSGT(("cert:partner", "bad parameters searching for partner\n"));
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if(key) {
Packit fcad23
        if (key->cert) {
Packit fcad23
            DEBUGMSGT(("cert:partner", "key already has partner\n"));
Packit fcad23
            return;
Packit fcad23
        }
Packit fcad23
        DEBUGMSGT(("9:cert:partner", "%s looking for partner near %s\n",
Packit fcad23
                   key->info.filename, key->info.dir));
Packit fcad23
        snprintf(filename, sizeof(filename), "%s", key->info.filename);
Packit fcad23
        pos = strrchr(filename, '.');
Packit fcad23
        if (NULL == pos)
Packit fcad23
            return;
Packit fcad23
        *pos = 0;
Packit fcad23
Packit fcad23
        matching = _cert_find_subset_fn( filename, key->info.dir );
Packit fcad23
        if (!matching)
Packit fcad23
            return;
Packit fcad23
        if (1 == matching->size) {
Packit fcad23
            cert = (netsnmp_cert*)matching->array[0];
Packit fcad23
            if (NULL == cert->key) {
Packit fcad23
                DEBUGMSGT(("cert:partner", "%s match found!\n",
Packit fcad23
                           cert->info.filename));
Packit fcad23
                key->cert = cert;
Packit fcad23
                cert->key = key;
Packit fcad23
                cert->info.allowed_uses |= NS_CERT_IDENTITY;
Packit fcad23
            }
Packit fcad23
            else if (cert->key != key)
Packit fcad23
                snmp_log(LOG_ERR, "%s matching cert already has partner\n",
Packit fcad23
                         cert->info.filename);
Packit fcad23
        }
Packit fcad23
        else
Packit fcad23
            DEBUGMSGT(("cert:partner", "%s matches multiple certs\n",
Packit fcad23
                          key->info.filename));
Packit fcad23
    }
Packit fcad23
    else if(cert) {
Packit fcad23
        if (cert->key) {
Packit fcad23
            DEBUGMSGT(("cert:partner", "cert already has partner\n"));
Packit fcad23
            return;
Packit fcad23
        }
Packit fcad23
        DEBUGMSGT(("9:cert:partner", "%s looking for partner\n",
Packit fcad23
                   cert->info.filename));
Packit fcad23
        snprintf(filename, sizeof(filename), "%s", cert->info.filename);
Packit fcad23
        pos = strrchr(filename, '.');
Packit fcad23
        if (NULL == pos)
Packit fcad23
            return;
Packit fcad23
        *pos = 0;
Packit fcad23
Packit fcad23
        matching = _key_find_subset(filename);
Packit fcad23
        if (!matching)
Packit fcad23
            return;
Packit fcad23
        if (1 == matching->size) {
Packit fcad23
            key = (netsnmp_key*)matching->array[0];
Packit fcad23
            if (NULL == key->cert) {
Packit fcad23
                DEBUGMSGT(("cert:partner", "%s found!\n", cert->info.filename));
Packit fcad23
                key->cert = cert;
Packit fcad23
                cert->key = key;
Packit fcad23
            }
Packit fcad23
            else if (key->cert != cert)
Packit fcad23
                snmp_log(LOG_ERR, "%s matching key already has partner\n",
Packit fcad23
                         cert->info.filename);
Packit fcad23
        }
Packit fcad23
        else
Packit fcad23
            DEBUGMSGT(("cert:partner", "%s matches multiple keys\n",
Packit fcad23
                       cert->info.filename));
Packit fcad23
    }
Packit fcad23
    
Packit fcad23
    if (matching) {
Packit fcad23
        free(matching->array);
Packit fcad23
        free(matching);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_add_certfile(const char* dirname, const char* filename, FILE *index)
Packit fcad23
{
Packit fcad23
    X509         *ocert;
Packit fcad23
    EVP_PKEY     *okey;
Packit fcad23
    netsnmp_cert *cert = NULL;
Packit fcad23
    netsnmp_key  *key = NULL;
Packit fcad23
    char          certfile[SNMP_MAXPATH];
Packit fcad23
    int           type;
Packit fcad23
Packit fcad23
    if (((const void*)NULL == dirname) || (NULL == filename))
Packit fcad23
        return -1;
Packit fcad23
Packit fcad23
    type = _type_from_filename(filename);
Packit fcad23
    netsnmp_assert(type != NS_CERT_TYPE_UNKNOWN);
Packit fcad23
Packit fcad23
    snprintf(certfile, sizeof(certfile),"%s/%s", dirname, filename);
Packit fcad23
Packit fcad23
    DEBUGMSGT(("9:cert:file:add", "Checking file: %s (type %d)\n", filename,
Packit fcad23
               type));
Packit fcad23
Packit fcad23
    if (NS_CERT_TYPE_KEY == type) {
Packit fcad23
        key = _new_key(dirname, filename);
Packit fcad23
        if (NULL == key)
Packit fcad23
            return -1;
Packit fcad23
        okey = netsnmp_okey_get(key);
Packit fcad23
        if (NULL == okey) {
Packit fcad23
            netsnmp_key_free(key);
Packit fcad23
            return -1;
Packit fcad23
        }
Packit fcad23
        key->okey = okey;
Packit fcad23
        if (-1 == CONTAINER_INSERT(_keys, key)) {
Packit fcad23
            DEBUGMSGT(("cert:key:file:add:err",
Packit fcad23
                       "error inserting key into container\n"));
Packit fcad23
            netsnmp_key_free(key);
Packit fcad23
            key = NULL;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    else {
Packit fcad23
        cert = _new_cert(dirname, filename, type, -1, NULL, NULL, NULL);
Packit fcad23
        if (NULL == cert)
Packit fcad23
            return -1;
Packit fcad23
        ocert = netsnmp_ocert_get(cert);
Packit fcad23
        if (NULL == ocert) {
Packit fcad23
            netsnmp_cert_free(cert);
Packit fcad23
            return -1;
Packit fcad23
        }
Packit fcad23
        cert->ocert = ocert;
Packit fcad23
        if (-1 == CONTAINER_INSERT(_certs, cert)) {
Packit fcad23
            DEBUGMSGT(("cert:file:add:err",
Packit fcad23
                       "error inserting cert into container\n"));
Packit fcad23
            netsnmp_cert_free(cert);
Packit fcad23
            cert = NULL;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    if ((NULL == cert) && (NULL == key)) {
Packit fcad23
        DEBUGMSGT(("cert:file:add:failure", "for %s\n", certfile));
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (index) {
Packit fcad23
        /** filename = NAME_MAX = 255 */
Packit fcad23
        /** fingerprint max = 64*3=192 for sha512 */
Packit fcad23
        /** common name / CN  = 64 */
Packit fcad23
        if (cert)
Packit fcad23
            fprintf(index, "c:%s %d %d %s '%s' '%s'\n", filename,
Packit fcad23
                    cert->info.type, cert->hash_type, cert->fingerprint,
Packit fcad23
                    cert->common_name, cert->subject);
Packit fcad23
        else if (key)
Packit fcad23
            fprintf(index, "k:%s\n", filename);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_cert_read_index(const char *dirname, struct stat *dirstat)
Packit fcad23
{
Packit fcad23
    FILE           *index;
Packit fcad23
    char           *idxname, *pos;
Packit fcad23
    struct stat     idx_stat;
Packit fcad23
    char            tmpstr[SNMP_MAXPATH + 5], filename[NAME_MAX];
Packit fcad23
    char            fingerprint[EVP_MAX_MD_SIZE*3], common_name[64+1], type_str[15];
Packit fcad23
    char            subject[SNMP_MAXBUF_SMALL], hash_str[15];
Packit fcad23
    int             count = 0, type, hash, version;
Packit fcad23
    netsnmp_cert    *cert;
Packit fcad23
    netsnmp_key     *key;
Packit fcad23
    netsnmp_container *newer, *found;
Packit fcad23
Packit fcad23
    netsnmp_assert(NULL != dirname);
Packit fcad23
Packit fcad23
    idxname = _certindex_lookup( dirname );
Packit fcad23
    if (NULL == idxname) {
Packit fcad23
        DEBUGMSGT(("cert:index:parse", "no index for cert directory\n"));
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * see if directory has been modified more recently than the index
Packit fcad23
     */
Packit fcad23
    if (stat(idxname, &idx_stat) != 0) {
Packit fcad23
        DEBUGMSGT(("cert:index:parse", "error getting index file stats\n"));
Packit fcad23
        SNMP_FREE(idxname);
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
#if (defined(WIN32) || defined(cygwin))
Packit fcad23
    /* For Win32 platforms, the directory does not maintain a last modification
Packit fcad23
     * date that we can compare with the modification date of the .index file.
Packit fcad23
     */
Packit fcad23
#else
Packit fcad23
    if (dirstat->st_mtime >= idx_stat.st_mtime) {
Packit fcad23
        DEBUGMSGT(("cert:index:parse", "Index outdated; dir modified\n"));
Packit fcad23
        SNMP_FREE(idxname);
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * dir mtime doesn't change when files are touched, so we need to check
Packit fcad23
     * each file against the index in case a file has been modified.
Packit fcad23
     */
Packit fcad23
    newer =
Packit fcad23
        netsnmp_directory_container_read_some(NULL, dirname,
Packit fcad23
                                              (netsnmp_directory_filter*)
Packit fcad23
                                              _time_filter,(void*)&idx_stat,
Packit fcad23
                                              NETSNMP_DIR_NSFILE |
Packit fcad23
                                              NETSNMP_DIR_NSFILE_STATS);
Packit fcad23
    if (newer) {
Packit fcad23
        DEBUGMSGT(("cert:index:parse", "Index outdated; files modified\n"));
Packit fcad23
        CONTAINER_FREE_ALL(newer, NULL);
Packit fcad23
        CONTAINER_FREE(newer);
Packit fcad23
        SNMP_FREE(idxname);
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:index:parse", "The index for %s looks good\n", dirname));
Packit fcad23
Packit fcad23
    index = fopen(idxname, "r");
Packit fcad23
    if (NULL == index) {
Packit fcad23
        snmp_log(LOG_ERR, "cert:index:parse can't open index for %s\n",
Packit fcad23
            dirname);
Packit fcad23
        SNMP_FREE(idxname);
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    found = _get_cert_container(idxname);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * check index format version
Packit fcad23
     */
Packit fcad23
    fgets(tmpstr, sizeof(tmpstr), index);
Packit fcad23
    pos = strrchr(tmpstr, ' ');
Packit fcad23
    if (pos) {
Packit fcad23
        ++pos;
Packit fcad23
        version = atoi(pos);
Packit fcad23
    }
Packit fcad23
    if ((NULL == pos) || (version != CERT_INDEX_FORMAT)) {
Packit fcad23
        DEBUGMSGT(("cert:index:add", "missing or wrong index format!\n"));
Packit fcad23
        fclose(index);
Packit fcad23
        SNMP_FREE(idxname);
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
    while (1) {
Packit fcad23
        if (NULL == fgets(tmpstr, sizeof(tmpstr), index))
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        if ('c' == tmpstr[0]) {
Packit fcad23
            pos = &tmpstr[2];
Packit fcad23
            if ((NULL == (pos=copy_nword(pos, filename, sizeof(filename)))) ||
Packit fcad23
                (NULL == (pos=copy_nword(pos, type_str, sizeof(type_str)))) ||
Packit fcad23
                (NULL == (pos=copy_nword(pos, hash_str, sizeof(hash_str)))) ||
Packit fcad23
                (NULL == (pos=copy_nword(pos, fingerprint,
Packit fcad23
                                         sizeof(fingerprint)))) ||
Packit fcad23
                (NULL == (pos=copy_nword(pos, common_name,
Packit fcad23
                                           sizeof(common_name)))) ||
Packit fcad23
                (NULL != copy_nword(pos, subject, sizeof(subject)))) {
Packit fcad23
                snmp_log(LOG_ERR, "_cert_read_index: error parsing line: %s\n",
Packit fcad23
                         tmpstr);
Packit fcad23
                count = -1;
Packit fcad23
                break;
Packit fcad23
            }
Packit fcad23
            type = atoi(type_str);
Packit fcad23
            hash = atoi(hash_str);
Packit fcad23
            cert = (void*)_new_cert(dirname, filename, type, hash, fingerprint,
Packit fcad23
                                    common_name, subject);
Packit fcad23
            if (cert && 0 == CONTAINER_INSERT(found, cert))
Packit fcad23
                ++count;
Packit fcad23
            else {
Packit fcad23
                DEBUGMSGT(("cert:index:add",
Packit fcad23
                           "error inserting cert into container\n"));
Packit fcad23
                netsnmp_cert_free(cert);
Packit fcad23
                cert = NULL;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
        else if ('k' == tmpstr[0]) {
Packit fcad23
            if (NULL != copy_nword(&tmpstr[2], filename, sizeof(filename))) {
Packit fcad23
                snmp_log(LOG_ERR, "_cert_read_index: error parsing line %s\n",
Packit fcad23
                    tmpstr);
Packit fcad23
                continue;
Packit fcad23
            }
Packit fcad23
            key = _new_key(dirname, filename);
Packit fcad23
            if (key && 0 == CONTAINER_INSERT(_keys, key))
Packit fcad23
                ++count;
Packit fcad23
            else {
Packit fcad23
                DEBUGMSGT(("cert:index:add:key",
Packit fcad23
                           "error inserting key into container\n"));
Packit fcad23
                netsnmp_key_free(key);
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
        else {
Packit fcad23
            snmp_log(LOG_ERR, "unknown line in cert index for %s\n", dirname);
Packit fcad23
            continue;
Packit fcad23
        }
Packit fcad23
    } /* while */
Packit fcad23
    fclose(index);
Packit fcad23
    SNMP_FREE(idxname);
Packit fcad23
Packit fcad23
    if (count > 0) {
Packit fcad23
        netsnmp_iterator  *itr = CONTAINER_ITERATOR(found);
Packit fcad23
        if (NULL == itr) {
Packit fcad23
            snmp_log(LOG_ERR, "could not get iterator for found certs\n");
Packit fcad23
            count = -1;
Packit fcad23
        }
Packit fcad23
        else {
Packit fcad23
            cert = ITERATOR_FIRST(itr);
Packit fcad23
            for( ; cert; cert = ITERATOR_NEXT(itr))
Packit fcad23
                CONTAINER_INSERT(_certs, cert);
Packit fcad23
            ITERATOR_RELEASE(itr);
Packit fcad23
            DEBUGMSGT(("cert:index:parse","added %d certs from index\n",
Packit fcad23
                       count));
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    if (count < 0)
Packit fcad23
        CONTAINER_FREE_ALL(found, NULL);
Packit fcad23
    CONTAINER_FREE(found);
Packit fcad23
Packit fcad23
    return count;
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_add_certdir(const char *dirname)
Packit fcad23
{
Packit fcad23
    FILE           *index;
Packit fcad23
    char           *file;
Packit fcad23
    int             count = 0;
Packit fcad23
    netsnmp_container *cert_container;
Packit fcad23
    netsnmp_iterator  *it;
Packit fcad23
    struct stat     statbuf;
Packit fcad23
Packit fcad23
    netsnmp_assert(NULL != dirname);
Packit fcad23
Packit fcad23
    DEBUGMSGT(("9:cert:dir:add", " config dir: %s\n", dirname ));
Packit fcad23
Packit fcad23
    if (stat(dirname, &statbuf) != 0) {
Packit fcad23
        DEBUGMSGT(("9:cert:dir:add", " dir not present: %s\n",
Packit fcad23
                   dirname ));
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
#ifdef S_ISDIR
Packit fcad23
    if (!S_ISDIR(statbuf.st_mode)) {
Packit fcad23
        DEBUGMSGT(("9:cert:dir:add", " not a dir: %s\n", dirname ));
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:index:dir", "Scanning directory %s\n", dirname));
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * look for existing index
Packit fcad23
     */
Packit fcad23
    count = _cert_read_index(dirname, &statbuf);
Packit fcad23
    if (count >= 0)
Packit fcad23
        return count;
Packit fcad23
Packit fcad23
    index = _certindex_new( dirname );
Packit fcad23
    if (NULL == index) {
Packit fcad23
        DEBUGMSGT(("9:cert:index:dir",
Packit fcad23
                    "error opening index for cert directory\n"));
Packit fcad23
        DEBUGMSGTL(("cert:index", "could not open certificate index file\n"));
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * index was missing, out of date or bad. rescan directory.
Packit fcad23
     */
Packit fcad23
    cert_container =
Packit fcad23
        netsnmp_directory_container_read_some(NULL, dirname,
Packit fcad23
                                              (netsnmp_directory_filter*)
Packit fcad23
                                              &_cert_cert_filter, NULL,
Packit fcad23
                                              NETSNMP_DIR_RELATIVE_PATH |
Packit fcad23
                                              NETSNMP_DIR_EMPTY_OK );
Packit fcad23
    if (NULL == cert_container) {
Packit fcad23
        DEBUGMSGT(("cert:index:dir",
Packit fcad23
                    "error creating container for cert files\n"));
Packit fcad23
        goto err_index;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * iterate through the found files and add them to index
Packit fcad23
     */
Packit fcad23
    it = CONTAINER_ITERATOR(cert_container);
Packit fcad23
    if (NULL == it) {
Packit fcad23
        DEBUGMSGT(("cert:index:dir",
Packit fcad23
                    "error creating iterator for cert files\n"));
Packit fcad23
        goto err_container;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    for (file = ITERATOR_FIRST(it); file; file = ITERATOR_NEXT(it)) {
Packit fcad23
        DEBUGMSGT(("cert:index:dir", "adding %s to index\n", file));
Packit fcad23
        if ( 0 == _add_certfile( dirname, file, index ))
Packit fcad23
            count++;
Packit fcad23
        else
Packit fcad23
            DEBUGMSGT(("cert:index:dir", "error adding %s to index\n",
Packit fcad23
                        file));
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * clean up and return
Packit fcad23
     */
Packit fcad23
    ITERATOR_RELEASE(it);
Packit fcad23
Packit fcad23
  err_container:
Packit fcad23
    netsnmp_directory_container_free(cert_container);
Packit fcad23
Packit fcad23
  err_index:
Packit fcad23
    if (index)
Packit fcad23
        fclose(index);
Packit fcad23
Packit fcad23
    return count;
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
_cert_indexes_load(void)
Packit fcad23
{
Packit fcad23
    const char     *confpath;
Packit fcad23
    char           *confpath_copy, *dir, *st = NULL;
Packit fcad23
    char            certdir[SNMP_MAXPATH];
Packit fcad23
    const char     *subdirs[] = { NULL, "ca-certs", "certs", "private", NULL };
Packit fcad23
    int             i = 0;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * load indexes from persistent dir
Packit fcad23
     */
Packit fcad23
    _certindexes_load();
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * duplicate path building from read_config_files_of_type() in
Packit fcad23
     * read_config.c. That is, use SNMPCONFPATH environment variable if
Packit fcad23
     * it is defined, otherwise use configuration directory.
Packit fcad23
     */
Packit fcad23
    confpath = netsnmp_getenv("SNMPCONFPATH");
Packit fcad23
    if (NULL == confpath)
Packit fcad23
        confpath = get_configuration_directory();
Packit fcad23
Packit fcad23
    subdirs[0] = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                                       NETSNMP_DS_LIB_CERT_EXTRA_SUBDIR);
Packit fcad23
    confpath_copy = strdup(confpath);
Packit fcad23
    if (!confpath_copy)
Packit fcad23
        return;
Packit fcad23
    for ( dir = strtok_r(confpath_copy, ENV_SEPARATOR, &st);
Packit fcad23
          dir; dir = strtok_r(NULL, ENV_SEPARATOR, &st)) {
Packit fcad23
Packit fcad23
        i = (NULL == subdirs[0]) ? 1 : 0;
Packit fcad23
        for ( ; subdirs[i] ; ++i ) {
Packit fcad23
            /** check tls subdir */
Packit fcad23
            snprintf(certdir, sizeof(certdir), "%s/tls/%s", dir, subdirs[i]);
Packit fcad23
            _add_certdir(certdir);
Packit fcad23
        } /* for subdirs */
Packit fcad23
    } /* for conf path dirs */
Packit fcad23
    SNMP_FREE(confpath_copy);
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
_cert_print(netsnmp_cert *c, void *context)
Packit fcad23
{
Packit fcad23
    if (NULL == c)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:dump", "cert %s in %s\n", c->info.filename, c->info.dir));
Packit fcad23
    DEBUGMSGT(("cert:dump", "   type %d flags 0x%x (%s)\n",
Packit fcad23
             c->info.type, c->info.allowed_uses,
Packit fcad23
              _mode_str(c->info.allowed_uses)));
Packit fcad23
    DEBUGIF("9:cert:dump") {
Packit fcad23
        if (NS_CERT_TYPE_KEY != c->info.type) {
Packit fcad23
            if(c->subject) {
Packit fcad23
                if (c->info.allowed_uses & NS_CERT_CA)
Packit fcad23
                    DEBUGMSGT(("9:cert:dump", "   CA: %s\n", c->subject));
Packit fcad23
                else
Packit fcad23
                    DEBUGMSGT(("9:cert:dump", "   subject: %s\n", c->subject));
Packit fcad23
            }
Packit fcad23
            if(c->issuer)
Packit fcad23
                DEBUGMSGT(("9:cert:dump", "   issuer: %s\n", c->issuer));
Packit fcad23
            if(c->fingerprint)
Packit fcad23
                DEBUGMSGT(("9:cert:dump", "   fingerprint: %s(%d):%s\n",
Packit fcad23
                           se_find_label_in_slist("cert_hash_alg", c->hash_type),
Packit fcad23
                           c->hash_type, c->fingerprint));
Packit fcad23
        }
Packit fcad23
        /* netsnmp_feature_require(cert_utils_dump_names) */
Packit fcad23
        /* netsnmp_openssl_cert_dump_names(c->ocert); */
Packit fcad23
        netsnmp_openssl_cert_dump_extensions(c->ocert);
Packit fcad23
    }
Packit fcad23
    
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
_key_print(netsnmp_key *k, void *context)
Packit fcad23
{
Packit fcad23
    if (NULL == k)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:dump", "key %s in %s\n", k->info.filename, k->info.dir));
Packit fcad23
    DEBUGMSGT(("cert:dump", "   type %d flags 0x%x (%s)\n", k->info.type,
Packit fcad23
              k->info.allowed_uses, _mode_str(k->info.allowed_uses)));
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_cert_dump_all(void)
Packit fcad23
{
Packit fcad23
    CONTAINER_FOR_EACH(_certs, (netsnmp_container_obj_func*)_cert_print, NULL);
Packit fcad23
    CONTAINER_FOR_EACH(_keys, (netsnmp_container_obj_func*)_key_print, NULL);
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifdef CERT_MAIN
Packit fcad23
/*
Packit fcad23
 * export BLD=~/net-snmp/build/ SRC=~/net-snmp/src 
Packit fcad23
 * cc -DCERT_MAIN `$BLD/net-snmp-config --cflags` `$BLD/net-snmp-config --build-includes $BLD/`  $SRC/snmplib/cert_util.c   -o cert_util `$BLD/net-snmp-config --build-lib-dirs $BLD` `$BLD/net-snmp-config --libs` -lcrypto -lssl
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
main(int argc, char** argv)
Packit fcad23
{
Packit fcad23
    int          ch;
Packit fcad23
    extern char *optarg;
Packit fcad23
Packit fcad23
    while ((ch = getopt(argc, argv, "D:fHLMx:")) != EOF)
Packit fcad23
        switch(ch) {
Packit fcad23
            case 'D':
Packit fcad23
                debug_register_tokens(optarg);
Packit fcad23
                snmp_set_do_debugging(1);
Packit fcad23
                break;
Packit fcad23
            default:
Packit fcad23
                fprintf(stderr,"unknown option %c\n", ch);
Packit fcad23
        }
Packit fcad23
Packit fcad23
    init_snmp("dtlsapp");
Packit fcad23
Packit fcad23
    netsnmp_cert_dump_all();
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
#endif /* CERT_MAIN */
Packit fcad23
Packit fcad23
static netsnmp_cert *_cert_find_fp(const char *fingerprint);
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_fp_lowercase_and_strip_colon(char *fp)
Packit fcad23
{
Packit fcad23
    char *pos, *dest=NULL;
Packit fcad23
    
Packit fcad23
    if(!fp)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    /** skip to first : */
Packit fcad23
    for (pos = fp; *pos; ++pos ) {
Packit fcad23
        if (':' == *pos) {
Packit fcad23
            dest = pos;
Packit fcad23
            break;
Packit fcad23
        }
Packit fcad23
        else
Packit fcad23
            *pos = isalpha(0xFF & *pos) ? tolower(0xFF & *pos) : *pos;
Packit fcad23
    }
Packit fcad23
    if (!*pos)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    /** copy, skipping any ':' */
Packit fcad23
    for (++pos; *pos; ++pos) {
Packit fcad23
        if (':' == *pos)
Packit fcad23
            continue;
Packit fcad23
        *dest++ = isalpha(0xFF & *pos) ? tolower(0xFF & *pos) : *pos;
Packit fcad23
    }
Packit fcad23
    *dest = *pos; /* nul termination */
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_cert *
Packit fcad23
netsnmp_cert_find(int what, int where, void *hint)
Packit fcad23
{
Packit fcad23
    netsnmp_cert *result = NULL;
Packit fcad23
    char         *fp, *hint_str;
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:find:params", "looking for %s(%d) in %s(0x%x), hint %p\n",
Packit fcad23
               _mode_str(what), what, _where_str(where), where, hint));
Packit fcad23
Packit fcad23
    if (NS_CERTKEY_DEFAULT == where) {
Packit fcad23
            
Packit fcad23
        switch (what) {
Packit fcad23
            case NS_CERT_IDENTITY: /* want my ID */
Packit fcad23
                fp =
Packit fcad23
                    netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                                          NETSNMP_DS_LIB_TLS_LOCAL_CERT);
Packit fcad23
                /** temp backwards compability; remove in 5.7 */
Packit fcad23
                if (!fp) {
Packit fcad23
                    int           tmp;
Packit fcad23
                    tmp = (ptrdiff_t)hint;
Packit fcad23
                    DEBUGMSGT(("cert:find:params", " hint = %s\n",
Packit fcad23
                               tmp ? "server" : "client"));
Packit fcad23
                    fp =
Packit fcad23
                        netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, tmp ?
Packit fcad23
                                              NETSNMP_DS_LIB_X509_SERVER_PUB :
Packit fcad23
                                              NETSNMP_DS_LIB_X509_CLIENT_PUB );
Packit fcad23
                }
Packit fcad23
                if (!fp) {
Packit fcad23
                    /* As a special case, use the application type to
Packit fcad23
                       determine a file name to pull the default identity
Packit fcad23
                       from. */
Packit fcad23
                    return netsnmp_cert_find(what, NS_CERTKEY_FILE, netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE));
Packit fcad23
                }
Packit fcad23
                break;
Packit fcad23
            case NS_CERT_REMOTE_PEER:
Packit fcad23
                fp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                                           NETSNMP_DS_LIB_TLS_PEER_CERT);
Packit fcad23
                /** temp backwards compability; remove in 5.7 */
Packit fcad23
                if (!fp)
Packit fcad23
                    fp = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                                               NETSNMP_DS_LIB_X509_SERVER_PUB);
Packit fcad23
                break;
Packit fcad23
            default:
Packit fcad23
                DEBUGMSGT(("cert:find:err", "unhandled type %d for %s(%d)\n",
Packit fcad23
                           what, _where_str(where), where));
Packit fcad23
                return NULL;
Packit fcad23
        }
Packit fcad23
        if (fp)
Packit fcad23
            return netsnmp_cert_find(what, NS_CERTKEY_MULTIPLE, fp);
Packit fcad23
        return NULL;
Packit fcad23
    } /* where = ds store */
Packit fcad23
    else if (NS_CERTKEY_MULTIPLE == where) {
Packit fcad23
        /* tries multiple sources of certificates based on ascii lookup keys */
Packit fcad23
Packit fcad23
        /* Try a fingerprint match first, which should always be done first */
Packit fcad23
        /* (to avoid people naming filenames with conflicting FPs) */
Packit fcad23
        result = netsnmp_cert_find(what, NS_CERTKEY_FINGERPRINT, hint);
Packit fcad23
        if (!result) {
Packit fcad23
            /* Then try a file name lookup */
Packit fcad23
            result = netsnmp_cert_find(what, NS_CERTKEY_FILE, hint);
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    else if (NS_CERTKEY_FINGERPRINT == where) {
Packit fcad23
        DEBUGMSGT(("cert:find:params", " hint = %s\n", (char *)hint));
Packit fcad23
        result = _cert_find_fp((char *)hint);
Packit fcad23
    }
Packit fcad23
    else if (NS_CERTKEY_TARGET_PARAM == where) {
Packit fcad23
        if (what != NS_CERT_IDENTITY) {
Packit fcad23
            snmp_log(LOG_ERR, "only identity is valid for target params\n");
Packit fcad23
            return NULL;
Packit fcad23
        }
Packit fcad23
        /** hint == target mib data */
Packit fcad23
        hint_str = (char *)hint;
Packit fcad23
        fp = _find_tlstmParams_fingerprint(hint_str);
Packit fcad23
        if (NULL != fp)
Packit fcad23
            result = _cert_find_fp(fp);
Packit fcad23
Packit fcad23
    }
Packit fcad23
    else if (NS_CERTKEY_TARGET_ADDR == where) {
Packit fcad23
        
Packit fcad23
        /** hint == target mib data */
Packit fcad23
        if (what != NS_CERT_REMOTE_PEER) {
Packit fcad23
            snmp_log(LOG_ERR, "only peer is valid for target addr\n");
Packit fcad23
            return NULL;
Packit fcad23
        }
Packit fcad23
        /** hint == target mib data */
Packit fcad23
        hint_str = (char *)hint;
Packit fcad23
        fp = _find_tlstmAddr_fingerprint(hint_str);
Packit fcad23
        if (NULL != fp)
Packit fcad23
            result = _cert_find_fp(fp);
Packit fcad23
Packit fcad23
    }
Packit fcad23
    else if (NS_CERTKEY_FILE == where) {
Packit fcad23
        /** hint == filename */
Packit fcad23
        char               *filename = (char*)hint;
Packit fcad23
        netsnmp_void_array *matching;
Packit fcad23
Packit fcad23
        DEBUGMSGT(("cert:find:params", " hint = %s\n", (char *)hint));
Packit fcad23
        matching = _cert_find_subset_fn( filename, NULL );
Packit fcad23
        if (!matching)
Packit fcad23
            return NULL;
Packit fcad23
        if (1 == matching->size)
Packit fcad23
            result = (netsnmp_cert*)matching->array[0];
Packit fcad23
        else {
Packit fcad23
            DEBUGMSGT(("cert:find:err", "%s matches multiple certs\n",
Packit fcad23
                       filename));
Packit fcad23
            result = NULL;
Packit fcad23
        }
Packit fcad23
        free(matching->array);
Packit fcad23
        free(matching);
Packit fcad23
    } /* where = NS_CERTKEY_FILE */
Packit fcad23
    else { /* unknown location */
Packit fcad23
        
Packit fcad23
        DEBUGMSGT(("cert:find:err", "unhandled location %d for %d\n", where,
Packit fcad23
                   what));
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    
Packit fcad23
    if (NULL == result)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    /** make sure result found can be used for specified type */
Packit fcad23
    if (!(result->info.allowed_uses & what)) {
Packit fcad23
        DEBUGMSGT(("cert:find:err",
Packit fcad23
                   "cert %s / %s not allowed for %s(%d) (uses=%s (%d))\n",
Packit fcad23
                   result->info.filename, result->fingerprint, _mode_str(what),
Packit fcad23
                   what , _mode_str(result->info.allowed_uses),
Packit fcad23
                   result->info.allowed_uses));
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    
Packit fcad23
    /** make sure we have the cert data */
Packit fcad23
    if (netsnmp_cert_load_x509(result) == CERT_LOAD_ERR)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:find:found",
Packit fcad23
               "using cert %s / %s for %s(%d) (uses=%s (%d))\n",
Packit fcad23
               result->info.filename, result->fingerprint, _mode_str(what),
Packit fcad23
               what , _mode_str(result->info.allowed_uses),
Packit fcad23
               result->info.allowed_uses));
Packit fcad23
            
Packit fcad23
    return result;
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CERT_FINGERPRINTS
Packit fcad23
int
Packit fcad23
netsnmp_cert_check_vb_fingerprint(const netsnmp_variable_list *var)
Packit fcad23
{
Packit fcad23
    if (!var)
Packit fcad23
        return SNMP_ERR_GENERR;
Packit fcad23
Packit fcad23
    if (0 == var->val_len) /* empty allowed in some cases */
Packit fcad23
        return SNMP_ERR_NOERROR;
Packit fcad23
Packit fcad23
    if (! (0x01 & var->val_len)) { /* odd len */
Packit fcad23
        DEBUGMSGT(("cert:varbind:fingerprint",
Packit fcad23
                   "expecting odd length for fingerprint\n"));
Packit fcad23
        return SNMP_ERR_WRONGLENGTH;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (var->val.string[0] > NS_HASH_MAX) {
Packit fcad23
        DEBUGMSGT(("cert:varbind:fingerprint", "hashtype %d > max %d\n",
Packit fcad23
                   var->val.string[0], NS_HASH_MAX));
Packit fcad23
        return SNMP_ERR_WRONGVALUE;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return SNMP_ERR_NOERROR;
Packit fcad23
}
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * break a SnmpTLSFingerprint into an integer hash type + hex string
Packit fcad23
 *
Packit fcad23
 * @return SNMPERR_SUCCESS : on success
Packit fcad23
 * @return SNMPERR_GENERR  : on failure
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
netsnmp_tls_fingerprint_parse(const u_char *binary_fp, int fp_len,
Packit fcad23
                              char **fp_str_ptr, u_int *fp_str_len, int realloc,
Packit fcad23
                              u_char *hash_type_ptr)
Packit fcad23
{
Packit fcad23
    int     needed;
Packit fcad23
    size_t  fp_str_size;
Packit fcad23
Packit fcad23
    netsnmp_require_ptr_LRV( hash_type_ptr, SNMPERR_GENERR );
Packit fcad23
    netsnmp_require_ptr_LRV( fp_str_ptr, SNMPERR_GENERR );
Packit fcad23
    netsnmp_require_ptr_LRV( fp_str_len, SNMPERR_GENERR );
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * output string is binary fp length (minus 1 for initial hash type 
Packit fcad23
     * char) * 2 for bin to hex conversion, + 1 for null termination.
Packit fcad23
     */
Packit fcad23
    needed = ((fp_len - 1) * 2) + 1;
Packit fcad23
    if (*fp_str_len < needed) {
Packit fcad23
        DEBUGMSGT(("tls:fp:parse", "need %d bytes for output\n", needed ));
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * make sure hash type is in valid range
Packit fcad23
     */
Packit fcad23
    if ((0 == binary_fp[0]) || (binary_fp[0] > NS_HASH_MAX)) {
Packit fcad23
        DEBUGMSGT(("tls:fp:parse", "invalid hash type %d\n",
Packit fcad23
                   binary_fp[0]));
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * netsnmp_binary_to_hex allocate space for string, if needed
Packit fcad23
     */
Packit fcad23
    fp_str_size = *fp_str_len;
Packit fcad23
    *hash_type_ptr = binary_fp[0];
Packit fcad23
    netsnmp_binary_to_hex((u_char**)fp_str_ptr, &fp_str_size,
Packit fcad23
                          realloc, &binary_fp[1], fp_len - 1);
Packit fcad23
    *fp_str_len = fp_str_size;
Packit fcad23
    if (0 == *fp_str_len)
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
Packit fcad23
    return SNMPERR_SUCCESS;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CERT_FINGERPRINTS */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_TLS_FINGERPRINT_BUILD
Packit fcad23
/**
Packit fcad23
 * combine a hash type and hex fingerprint into a SnmpTLSFingerprint
Packit fcad23
 *
Packit fcad23
 * On entry, tls_fp_len should point to the size of the tls_fp buffer.
Packit fcad23
 * On a successful exit, tls_fp_len will contain the length of the
Packit fcad23
 * fingerprint buffer.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
netsnmp_tls_fingerprint_build(int hash_type, const char *hex_fp,
Packit fcad23
                                   u_char **tls_fp, size_t *tls_fp_len,
Packit fcad23
                                   int realloc)
Packit fcad23
{
Packit fcad23
    int     hex_fp_len, rc;
Packit fcad23
    size_t  tls_fp_size = *tls_fp_len;
Packit fcad23
    size_t  offset;
Packit fcad23
Packit fcad23
    netsnmp_require_ptr_LRV( hex_fp, SNMPERR_GENERR );
Packit fcad23
    netsnmp_require_ptr_LRV( tls_fp, SNMPERR_GENERR );
Packit fcad23
    netsnmp_require_ptr_LRV( tls_fp_len, SNMPERR_GENERR );
Packit fcad23
Packit fcad23
    hex_fp_len = strlen(hex_fp);
Packit fcad23
    if (0 == hex_fp_len) {
Packit fcad23
        *tls_fp_len = 0;
Packit fcad23
        return SNMPERR_SUCCESS;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if ((hash_type <= NS_HASH_NONE) || (hash_type > NS_HASH_MAX)) {
Packit fcad23
        DEBUGMSGT(("tls:fp:build", "invalid hash type %d\n", hash_type ));
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * convert to binary
Packit fcad23
     */
Packit fcad23
    offset = 1;
Packit fcad23
    rc = netsnmp_hex_to_binary(tls_fp, &tls_fp_size, &offset, realloc, hex_fp,
Packit fcad23
                               ":");
Packit fcad23
    *tls_fp_len = tls_fp_size;
Packit fcad23
    if (rc != 1)
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    *tls_fp_len = offset;
Packit fcad23
    (*tls_fp)[0] = hash_type;
Packit fcad23
                               
Packit fcad23
    return SNMPERR_SUCCESS;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_TLS_FINGERPRINT_BUILD */
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * Trusts a given certificate for use in TLS translations.
Packit fcad23
 *
Packit fcad23
 * @param ctx The SSL context to trust the certificate in
Packit fcad23
 * @param thiscert The netsnmp_cert certificate to trust
Packit fcad23
 *
Packit fcad23
 * @return SNMPERR_SUCCESS : on success
Packit fcad23
 * @return SNMPERR_GENERR  : on failure
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
netsnmp_cert_trust(SSL_CTX *ctx, netsnmp_cert *thiscert)
Packit fcad23
{
Packit fcad23
    X509_STORE     *certstore;
Packit fcad23
    X509           *cert;
Packit fcad23
    char           *fingerprint;
Packit fcad23
Packit fcad23
    /* ensure all needed pieces are present */
Packit fcad23
    netsnmp_assert_or_msgreturn(NULL != thiscert, "NULL certificate passed in",
Packit fcad23
                                SNMPERR_GENERR);
Packit fcad23
    netsnmp_assert_or_msgreturn(NULL != thiscert->info.dir,
Packit fcad23
                                "NULL certificate directory name passed in",
Packit fcad23
                                SNMPERR_GENERR);
Packit fcad23
    netsnmp_assert_or_msgreturn(NULL != thiscert->info.filename,
Packit fcad23
                                "NULL certificate filename name passed in",
Packit fcad23
                                SNMPERR_GENERR);
Packit fcad23
Packit fcad23
    /* get the trusted certificate store and the certificate to load into it */
Packit fcad23
    certstore = SSL_CTX_get_cert_store(ctx);
Packit fcad23
    netsnmp_assert_or_msgreturn(NULL != certstore,
Packit fcad23
                                "failed to get certificate trust store",
Packit fcad23
                                SNMPERR_GENERR);
Packit fcad23
    cert = netsnmp_ocert_get(thiscert);
Packit fcad23
    netsnmp_assert_or_msgreturn(NULL != cert,
Packit fcad23
                                "failed to get certificate from netsnmp_cert",
Packit fcad23
                                SNMPERR_GENERR);
Packit fcad23
Packit fcad23
    /* Put the certificate into the store */
Packit fcad23
    fingerprint = netsnmp_openssl_cert_get_fingerprint(cert, -1);
Packit fcad23
    DEBUGMSGTL(("cert:trust",
Packit fcad23
                "putting trusted cert %p = %s in certstore %p\n", cert,
Packit fcad23
                fingerprint, certstore));
Packit fcad23
    SNMP_FREE(fingerprint);
Packit fcad23
    X509_STORE_add_cert(certstore, cert);
Packit fcad23
Packit fcad23
    return SNMPERR_SUCCESS;
Packit fcad23
}
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * Trusts a given certificate's root CA for use in TLS translations.
Packit fcad23
 * If no issuer is found the existing certificate will be trusted instead.
Packit fcad23
 *
Packit fcad23
 * @param ctx The SSL context to trust the certificate in
Packit fcad23
 * @param thiscert The netsnmp_cert certificate 
Packit fcad23
 *
Packit fcad23
 * @return SNMPERR_SUCCESS : on success
Packit fcad23
 * @return SNMPERR_GENERR  : on failure
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
netsnmp_cert_trust_ca(SSL_CTX *ctx, netsnmp_cert *thiscert)
Packit fcad23
{
Packit fcad23
    netsnmp_assert_or_msgreturn(NULL != thiscert, "NULL certificate passed in",
Packit fcad23
                                SNMPERR_GENERR);
Packit fcad23
Packit fcad23
    /* find the root CA certificate in the chain */
Packit fcad23
    DEBUGMSGTL(("cert:trust_ca", "checking roots for %p \n", thiscert));
Packit fcad23
    while (thiscert->issuer_cert) {
Packit fcad23
        thiscert = thiscert->issuer_cert;
Packit fcad23
        DEBUGMSGTL(("cert:trust_ca", "  up one to %p\n", thiscert));
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /* Add the found top level certificate to the store */
Packit fcad23
    return netsnmp_cert_trust(ctx, thiscert);
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_container *
Packit fcad23
netsnmp_cert_get_trustlist(void)
Packit fcad23
{
Packit fcad23
    if (!_trusted_certs)
Packit fcad23
        _setup_trusted_certs();
Packit fcad23
    return _trusted_certs;
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
_parse_trustcert(const char *token, char *line)
Packit fcad23
{
Packit fcad23
    if (!_trusted_certs)
Packit fcad23
        _setup_trusted_certs();
Packit fcad23
Packit fcad23
    if (!_trusted_certs)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    CONTAINER_INSERT(_trusted_certs, strdup(line));
Packit fcad23
}
Packit fcad23
Packit fcad23
/* ***************************************************************************
Packit fcad23
 *
Packit fcad23
 * mode text functions
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
static const char *_mode_str(u_char mode)
Packit fcad23
{
Packit fcad23
    return _modes[mode];
Packit fcad23
}
Packit fcad23
Packit fcad23
static const char *_where_str(u_int what)
Packit fcad23
{
Packit fcad23
    switch (what) {
Packit fcad23
        case NS_CERTKEY_DEFAULT: return "DEFAULT";
Packit fcad23
        case NS_CERTKEY_FILE: return "FILE";
Packit fcad23
        case NS_CERTKEY_FINGERPRINT: return "FINGERPRINT";
Packit fcad23
        case NS_CERTKEY_MULTIPLE: return "MULTIPLE";
Packit fcad23
        case NS_CERTKEY_CA: return "CA";
Packit fcad23
        case NS_CERTKEY_SAN_RFC822: return "SAN_RFC822";
Packit fcad23
        case NS_CERTKEY_SAN_DNS: return "SAN_DNS";
Packit fcad23
        case NS_CERTKEY_SAN_IPADDR: return "SAN_IPADDR";
Packit fcad23
        case NS_CERTKEY_COMMON_NAME: return "COMMON_NAME";
Packit fcad23
        case NS_CERTKEY_TARGET_PARAM: return "TARGET_PARAM";
Packit fcad23
        case NS_CERTKEY_TARGET_ADDR: return "TARGET_ADDR";
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return "UNKNOWN";
Packit fcad23
}
Packit fcad23
Packit fcad23
/* ***************************************************************************
Packit fcad23
 *
Packit fcad23
 * find functions
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
static netsnmp_cert *
Packit fcad23
_cert_find_fp(const char *fingerprint)
Packit fcad23
{
Packit fcad23
    netsnmp_cert cert, *result = NULL;
Packit fcad23
    char         fp[EVP_MAX_MD_SIZE*3];
Packit fcad23
Packit fcad23
    if (NULL == fingerprint)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    strlcpy(fp, fingerprint, sizeof(fp));
Packit fcad23
    netsnmp_fp_lowercase_and_strip_colon(fp);
Packit fcad23
Packit fcad23
    /** clear search key */
Packit fcad23
    memset(&cert, 0x00, sizeof(cert));
Packit fcad23
Packit fcad23
    cert.fingerprint = fp;
Packit fcad23
Packit fcad23
    result = CONTAINER_FIND(_certs,&cert);
Packit fcad23
    return result;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * reduce subset by eliminating any filenames that are longer than
Packit fcad23
 * the specified file name. e.g. 'snmp' would match 'snmp.key' and
Packit fcad23
 * 'snmpd.key'. We only want 'snmp.X', where X is a valid extension.
Packit fcad23
 */
Packit fcad23
static void
Packit fcad23
_reduce_subset(netsnmp_void_array *matching, const char *filename)
Packit fcad23
{
Packit fcad23
    netsnmp_cert_common *cc;
Packit fcad23
    int i = 0, j, newsize, pos;
Packit fcad23
Packit fcad23
    if ((NULL == matching) || (NULL == filename))
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    pos = strlen(filename);
Packit fcad23
    newsize = matching->size;
Packit fcad23
Packit fcad23
    for( ; i < matching->size; ) {
Packit fcad23
        /*
Packit fcad23
         * if we've shifted matches down we'll hit a NULL entry before
Packit fcad23
         * we hit the end of the array.
Packit fcad23
         */
Packit fcad23
        if (NULL == matching->array[i])
Packit fcad23
            break;
Packit fcad23
        /*
Packit fcad23
         * skip over valid matches. Note that we do not want to use
Packit fcad23
         * _type_from_filename.
Packit fcad23
         */
Packit fcad23
        cc = (netsnmp_cert_common*)matching->array[i];
Packit fcad23
        if (('.' == cc->filename[pos]) &&
Packit fcad23
            (NS_CERT_TYPE_UNKNOWN != _cert_ext_type(&cc->filename[pos+1]))) {
Packit fcad23
            ++i;
Packit fcad23
            continue;
Packit fcad23
        }
Packit fcad23
        /*
Packit fcad23
         * shrink array by shifting everything down a spot. Might not be
Packit fcad23
         * the most efficient soloution, but this is just happening at
Packit fcad23
         * startup and hopefully most certs won't have common prefixes.
Packit fcad23
         */
Packit fcad23
        --newsize;
Packit fcad23
        for ( j=i; j < newsize; ++j )
Packit fcad23
            matching->array[j] = matching->array[j+1];
Packit fcad23
        matching->array[j] = NULL;
Packit fcad23
        /** no ++i; just shifted down, need to look at same position again */
Packit fcad23
    }
Packit fcad23
    /*
Packit fcad23
     * if we shifted, set the new size
Packit fcad23
     */
Packit fcad23
    if (newsize != matching->size) {
Packit fcad23
        DEBUGMSGT(("9:cert:subset:reduce", "shrank from %" NETSNMP_PRIz "d to %d\n",
Packit fcad23
                   matching->size, newsize));
Packit fcad23
        matching->size = newsize;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * reduce subset by eliminating any filenames that are not under the
Packit fcad23
 * specified directory path.
Packit fcad23
 */
Packit fcad23
static void
Packit fcad23
_reduce_subset_dir(netsnmp_void_array *matching, const char *directory)
Packit fcad23
{
Packit fcad23
    netsnmp_cert_common *cc;
Packit fcad23
    int                  i = 0, j, newsize, dir_len;
Packit fcad23
    char                 dir[SNMP_MAXPATH], *pos;
Packit fcad23
Packit fcad23
    if ((NULL == matching) || (NULL == directory))
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    newsize = matching->size;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * dir struct should be something like
Packit fcad23
     *          /usr/share/snmp/tls/certs
Packit fcad23
     *          /usr/share/snmp/tls/private
Packit fcad23
     *
Packit fcad23
     * so we want to backup up on directory for compares..
Packit fcad23
     */
Packit fcad23
    strlcpy(dir, directory, sizeof(dir));
Packit fcad23
    pos = strrchr(dir, '/');
Packit fcad23
    if (NULL == pos) {
Packit fcad23
        DEBUGMSGTL(("cert:subset:dir", "no '/' in directory %s\n", directory));
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    *pos = '\0';
Packit fcad23
    dir_len = strlen(dir);
Packit fcad23
Packit fcad23
    for( ; i < matching->size; ) {
Packit fcad23
        /*
Packit fcad23
         * if we've shifted matches down we'll hit a NULL entry before
Packit fcad23
         * we hit the end of the array.
Packit fcad23
         */
Packit fcad23
        if (NULL == matching->array[i])
Packit fcad23
            break;
Packit fcad23
        /*
Packit fcad23
         * skip over valid matches. 
Packit fcad23
         */
Packit fcad23
        cc = (netsnmp_cert_common*)matching->array[i];
Packit fcad23
        if (strncmp(dir, cc->dir, dir_len) == 0) {
Packit fcad23
            ++i;
Packit fcad23
            continue;
Packit fcad23
        }
Packit fcad23
        /*
Packit fcad23
         * shrink array by shifting everything down a spot. Might not be
Packit fcad23
         * the most efficient soloution, but this is just happening at
Packit fcad23
         * startup and hopefully most certs won't have common prefixes.
Packit fcad23
         */
Packit fcad23
        --newsize;
Packit fcad23
        for ( j=i; j < newsize; ++j )
Packit fcad23
            matching->array[j] = matching->array[j+1];
Packit fcad23
        matching->array[j] = NULL;
Packit fcad23
        /** no ++i; just shifted down, need to look at same position again */
Packit fcad23
    }
Packit fcad23
    /*
Packit fcad23
     * if we shifted, set the new size
Packit fcad23
     */
Packit fcad23
    if (newsize != matching->size) {
Packit fcad23
        DEBUGMSGT(("9:cert:subset:dir", "shrank from %" NETSNMP_PRIz "d to %d\n",
Packit fcad23
                   matching->size, newsize));
Packit fcad23
        matching->size = newsize;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
static netsnmp_void_array *
Packit fcad23
_cert_find_subset_common(const char *filename, netsnmp_container *container)
Packit fcad23
{
Packit fcad23
    netsnmp_cert_common   search;
Packit fcad23
    netsnmp_void_array   *matching;
Packit fcad23
Packit fcad23
    netsnmp_assert(filename && container);
Packit fcad23
Packit fcad23
    memset(&search, 0x00, sizeof(search));    /* clear search key */
Packit fcad23
Packit fcad23
    search.filename = NETSNMP_REMOVE_CONST(char*,filename);
Packit fcad23
Packit fcad23
    matching = CONTAINER_GET_SUBSET(container, &search);
Packit fcad23
    DEBUGMSGT(("9:cert:subset:found", "%" NETSNMP_PRIz "d matches\n", matching ?
Packit fcad23
               matching->size : 0));
Packit fcad23
    if (matching && matching->size > 1) {
Packit fcad23
        _reduce_subset(matching, filename);
Packit fcad23
        if (0 == matching->size) {
Packit fcad23
            free(matching->array);
Packit fcad23
            SNMP_FREE(matching);
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    return matching;
Packit fcad23
}
Packit fcad23
Packit fcad23
static netsnmp_void_array *
Packit fcad23
_cert_find_subset_fn(const char *filename, const char *directory)
Packit fcad23
{
Packit fcad23
    netsnmp_container    *fn_container;
Packit fcad23
    netsnmp_void_array   *matching;
Packit fcad23
Packit fcad23
    /** find subcontainer with filename as key */
Packit fcad23
    fn_container = SUBCONTAINER_FIND(_certs, "certs_fn");
Packit fcad23
    netsnmp_assert(fn_container);
Packit fcad23
Packit fcad23
    matching = _cert_find_subset_common(filename, fn_container);
Packit fcad23
    if (matching && (matching->size > 1) && directory) {
Packit fcad23
        _reduce_subset_dir(matching, directory);
Packit fcad23
        if (0 == matching->size) {
Packit fcad23
            free(matching->array);
Packit fcad23
            SNMP_FREE(matching);
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    return matching;
Packit fcad23
}
Packit fcad23
Packit fcad23
static netsnmp_void_array *
Packit fcad23
_cert_find_subset_sn(const char *subject)
Packit fcad23
{
Packit fcad23
    netsnmp_cert          search;
Packit fcad23
    netsnmp_void_array   *matching;
Packit fcad23
    netsnmp_container    *sn_container;
Packit fcad23
Packit fcad23
    /** find subcontainer with subject as key */
Packit fcad23
    sn_container = SUBCONTAINER_FIND(_certs, "certs_sn");
Packit fcad23
    netsnmp_assert(sn_container);
Packit fcad23
Packit fcad23
    memset(&search, 0x00, sizeof(search));    /* clear search key */
Packit fcad23
Packit fcad23
    search.subject = NETSNMP_REMOVE_CONST(char*,subject);
Packit fcad23
Packit fcad23
    matching = CONTAINER_GET_SUBSET(sn_container, &search);
Packit fcad23
    DEBUGMSGT(("9:cert:subset:found", "%" NETSNMP_PRIz "d matches\n", matching ?
Packit fcad23
               matching->size : 0));
Packit fcad23
    return matching;
Packit fcad23
}
Packit fcad23
Packit fcad23
static netsnmp_void_array *
Packit fcad23
_key_find_subset(const char *filename)
Packit fcad23
{
Packit fcad23
    return _cert_find_subset_common(filename, _keys);
Packit fcad23
}
Packit fcad23
Packit fcad23
/** find all entries matching given fingerprint */
Packit fcad23
static netsnmp_void_array *
Packit fcad23
_find_subset_fp(netsnmp_container *certs, const char *fp)
Packit fcad23
{
Packit fcad23
    netsnmp_cert_map    entry;
Packit fcad23
    netsnmp_container  *fp_container;
Packit fcad23
    netsnmp_void_array *va;
Packit fcad23
Packit fcad23
    if ((NULL == certs) || (NULL == fp))
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    fp_container = SUBCONTAINER_FIND(certs, "cert2sn_fp");
Packit fcad23
    netsnmp_assert_or_msgreturn(fp_container, "cert2sn_fp container missing",
Packit fcad23
                                NULL);
Packit fcad23
Packit fcad23
    memset(&entry, 0x0, sizeof(entry));
Packit fcad23
Packit fcad23
    entry.fingerprint = NETSNMP_REMOVE_CONST(char*,fp);
Packit fcad23
Packit fcad23
    va = CONTAINER_GET_SUBSET(fp_container, &entry);
Packit fcad23
    return va;
Packit fcad23
}
Packit fcad23
Packit fcad23
#if 0  /* not used yet */
Packit fcad23
static netsnmp_key *
Packit fcad23
_key_find_fn(const char *filename)
Packit fcad23
{
Packit fcad23
    netsnmp_key key, *result = NULL;
Packit fcad23
Packit fcad23
    netsnmp_assert(NULL != filename);
Packit fcad23
Packit fcad23
    memset(&key, 0x00, sizeof(key));    /* clear search key */
Packit fcad23
    key.info.filename = NETSNMP_REMOVE_CONST(char*,filename);
Packit fcad23
    result = CONTAINER_FIND(_keys,&key);
Packit fcad23
    return result;
Packit fcad23
}
Packit fcad23
#endif
Packit fcad23
Packit fcad23
static int
Packit fcad23
_time_filter(netsnmp_file *f, struct stat *idx)
Packit fcad23
{
Packit fcad23
    /** include if mtime or ctime newer than index mtime */
Packit fcad23
    if (f && idx && f->stats &&
Packit fcad23
        ((f->stats->st_mtime >= idx->st_mtime) ||
Packit fcad23
         (f->stats->st_ctime >= idx->st_mtime)))
Packit fcad23
        return NETSNMP_DIR_INCLUDE;
Packit fcad23
Packit fcad23
    return NETSNMP_DIR_EXCLUDE;
Packit fcad23
}
Packit fcad23
Packit fcad23
/* ***************************************************************************
Packit fcad23
 * ***************************************************************************
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * cert map functions
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * ***************************************************************************
Packit fcad23
 * ***************************************************************************/
Packit fcad23
#define MAP_CONFIG_TOKEN "certSecName"
Packit fcad23
static void _parse_map(const char *token, char *line);
Packit fcad23
static void _map_free(netsnmp_cert_map* entry, void *ctx);
Packit fcad23
static void _purge_config_entries(void);
Packit fcad23
Packit fcad23
static void
Packit fcad23
_init_tlstmCertToTSN(void)
Packit fcad23
{
Packit fcad23
    const char *certSecName_help = MAP_CONFIG_TOKEN " PRIORITY FINGERPRINT "
Packit fcad23
        "[--shaNN|md5] <--sn SECNAME | --rfc822 | --dns | --ip | --cn | --any>";
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * container for cert to fingerprint mapping, with fingerprint key
Packit fcad23
     */
Packit fcad23
    _maps = netsnmp_cert_map_container_create(1);
Packit fcad23
Packit fcad23
    register_config_handler(NULL, MAP_CONFIG_TOKEN, _parse_map, _purge_config_entries,
Packit fcad23
                            certSecName_help);
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_cert_map *
Packit fcad23
netsnmp_cert_map_alloc(char *fingerprint, X509 *ocert)
Packit fcad23
{
Packit fcad23
    netsnmp_cert_map *cert_map = SNMP_MALLOC_TYPEDEF(netsnmp_cert_map);
Packit fcad23
    if (NULL == cert_map) {
Packit fcad23
        snmp_log(LOG_ERR, "could not allocate netsnmp_cert_map\n");
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    
Packit fcad23
    if (fingerprint) {
Packit fcad23
        /** MIB limits to 255 bytes; 2x since we've got ascii */
Packit fcad23
        if (strlen(fingerprint) > (SNMPADMINLENGTH * 2)) {
Packit fcad23
            snmp_log(LOG_ERR, "fingerprint %s exceeds max length %d\n",
Packit fcad23
                     fingerprint, (SNMPADMINLENGTH * 2));
Packit fcad23
            free(cert_map);
Packit fcad23
            return NULL;
Packit fcad23
        }
Packit fcad23
        cert_map->fingerprint = strdup(fingerprint);
Packit fcad23
    }
Packit fcad23
    if (ocert) {
Packit fcad23
        cert_map->hashType = netsnmp_openssl_cert_get_hash_type(ocert);
Packit fcad23
        cert_map->ocert = ocert;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return cert_map;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_cert_map_free(netsnmp_cert_map *cert_map)
Packit fcad23
{
Packit fcad23
    if (NULL == cert_map)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    SNMP_FREE(cert_map->fingerprint);
Packit fcad23
    SNMP_FREE(cert_map->data);
Packit fcad23
    /** x509 cert isn't ours */
Packit fcad23
    free(cert_map); /* SNMP_FREE wasted on param */
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_cert_map_add(netsnmp_cert_map *map)
Packit fcad23
{
Packit fcad23
    int                rc;
Packit fcad23
Packit fcad23
    if (NULL == map)
Packit fcad23
        return -1;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("cert:map:add", "pri %d, fp %s\n",
Packit fcad23
                map->priority, map->fingerprint));
Packit fcad23
Packit fcad23
    if ((rc = CONTAINER_INSERT(_maps, map)) != 0)
Packit fcad23
        snmp_log(LOG_ERR, "could not insert new certificate map");
Packit fcad23
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CERT_MAP_REMOVE
Packit fcad23
int
Packit fcad23
netsnmp_cert_map_remove(netsnmp_cert_map *map)
Packit fcad23
{
Packit fcad23
    int                rc;
Packit fcad23
Packit fcad23
    if (NULL == map)
Packit fcad23
        return -1;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("cert:map:remove", "pri %d, fp %s\n",
Packit fcad23
                map->priority, map->fingerprint));
Packit fcad23
Packit fcad23
    if ((rc = CONTAINER_REMOVE(_maps, map)) != 0)
Packit fcad23
        snmp_log(LOG_ERR, "could not remove certificate map");
Packit fcad23
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CERT_MAP_REMOVE */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_CERT_MAP_FIND
Packit fcad23
netsnmp_cert_map *
Packit fcad23
netsnmp_cert_map_find(netsnmp_cert_map *map)
Packit fcad23
{
Packit fcad23
    if (NULL == map)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    return CONTAINER_FIND(_maps, map);
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CERT_MAP_FIND */
Packit fcad23
Packit fcad23
static void
Packit fcad23
_map_free(netsnmp_cert_map *map, void *context)
Packit fcad23
{
Packit fcad23
    netsnmp_cert_map_free(map);
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_map_compare(netsnmp_cert_map *lhs, netsnmp_cert_map *rhs)
Packit fcad23
{
Packit fcad23
    netsnmp_assert((lhs != NULL) && (rhs != NULL));
Packit fcad23
Packit fcad23
    if (lhs->priority < rhs->priority)
Packit fcad23
        return -1;
Packit fcad23
    else if (lhs->priority > rhs->priority)
Packit fcad23
        return 1;
Packit fcad23
Packit fcad23
    return strcmp(lhs->fingerprint, rhs->fingerprint);
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_map_fp_compare(netsnmp_cert_map *lhs, netsnmp_cert_map *rhs)
Packit fcad23
{
Packit fcad23
    int rc;
Packit fcad23
    netsnmp_assert((lhs != NULL) && (rhs != NULL));
Packit fcad23
Packit fcad23
    if ((rc = strcmp(lhs->fingerprint, rhs->fingerprint)) != 0)
Packit fcad23
        return rc;
Packit fcad23
Packit fcad23
    if (lhs->priority < rhs->priority)
Packit fcad23
        return -1;
Packit fcad23
    else if (lhs->priority > rhs->priority)
Packit fcad23
        return 1;
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_map_fp_ncompare(netsnmp_cert_map *lhs, netsnmp_cert_map *rhs)
Packit fcad23
{
Packit fcad23
    netsnmp_assert((lhs != NULL) && (rhs != NULL));
Packit fcad23
Packit fcad23
    return strncmp(lhs->fingerprint, rhs->fingerprint,
Packit fcad23
                   strlen(rhs->fingerprint));
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_container *
Packit fcad23
netsnmp_cert_map_container_create(int with_fp)
Packit fcad23
{
Packit fcad23
    netsnmp_container *chain_map, *fp;
Packit fcad23
Packit fcad23
    chain_map = netsnmp_container_find("cert_map:stack:binary_array");
Packit fcad23
    if (NULL == chain_map) {
Packit fcad23
        snmp_log(LOG_ERR, "could not allocate container for cert_map\n");
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    chain_map->container_name = strdup("cert_map");
Packit fcad23
    chain_map->free_item = (netsnmp_container_obj_func*)_map_free;
Packit fcad23
    chain_map->compare = (netsnmp_container_compare*)_map_compare;
Packit fcad23
Packit fcad23
    if (!with_fp)
Packit fcad23
        return chain_map;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * add a secondary index to the table container
Packit fcad23
     */
Packit fcad23
    fp = netsnmp_container_find("cert2sn_fp:binary_array");
Packit fcad23
    if (NULL == fp) {
Packit fcad23
        snmp_log(LOG_ERR,
Packit fcad23
                 "error creating sub-container for tlstmCertToTSNTable\n");
Packit fcad23
        CONTAINER_FREE(chain_map);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    fp->container_name = strdup("cert2sn_fp");
Packit fcad23
    fp->compare = (netsnmp_container_compare*)_map_fp_compare;
Packit fcad23
    fp->ncompare = (netsnmp_container_compare*)_map_fp_ncompare;
Packit fcad23
    netsnmp_container_add_index(chain_map, fp);
Packit fcad23
Packit fcad23
    return chain_map;
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_cert_parse_hash_type(const char *str)
Packit fcad23
{
Packit fcad23
    int rc = se_find_value_in_slist("cert_hash_alg", str);
Packit fcad23
    if (SE_DNE == rc)
Packit fcad23
        return NS_HASH_NONE;
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_cert_map_container_free(netsnmp_container *c)
Packit fcad23
{
Packit fcad23
    if (NULL == c)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    CONTAINER_FREE_ALL(c, NULL);
Packit fcad23
    CONTAINER_FREE(c);
Packit fcad23
}
Packit fcad23
Packit fcad23
/** clear out config rows
Packit fcad23
 * called during reconfig processing (e.g. SIGHUP)
Packit fcad23
*/
Packit fcad23
static void
Packit fcad23
_purge_config_entries(void)
Packit fcad23
{
Packit fcad23
    /**
Packit fcad23
     ** dup container
Packit fcad23
     ** iterate looking for NSCM_FROM_CONFIG flag
Packit fcad23
     ** delete from original
Packit fcad23
     ** delete dup
Packit fcad23
     **/
Packit fcad23
    netsnmp_iterator   *itr;
Packit fcad23
    netsnmp_cert_map   *cert_map;
Packit fcad23
    netsnmp_container  *cert_maps = netsnmp_cert_map_container();
Packit fcad23
    netsnmp_container  *tmp_maps = NULL;
Packit fcad23
Packit fcad23
    if ((NULL == cert_maps) || (CONTAINER_SIZE(cert_maps) == 0))
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:map:reconfig", "removing locally configured rows\n"));
Packit fcad23
    
Packit fcad23
    /*
Packit fcad23
     * duplicate cert_maps and then iterate over the copy. That way we can
Packit fcad23
     * add/remove to cert_maps without distrubing the iterator.
Packit fcad23
xx
Packit fcad23
     */
Packit fcad23
    tmp_maps = CONTAINER_DUP(cert_maps, NULL, 0);
Packit fcad23
    if (NULL == tmp_maps) {
Packit fcad23
        snmp_log(LOG_ERR, "could not duplicate maps for reconfig\n");
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    itr = CONTAINER_ITERATOR(tmp_maps);
Packit fcad23
    if (NULL == itr) {
Packit fcad23
        snmp_log(LOG_ERR, "could not get iterator for reconfig\n");
Packit fcad23
        CONTAINER_FREE(tmp_maps);
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    cert_map = ITERATOR_FIRST(itr);
Packit fcad23
    for( ; cert_map; cert_map = ITERATOR_NEXT(itr)) {
Packit fcad23
Packit fcad23
        if (!(cert_map->flags & NSCM_FROM_CONFIG))
Packit fcad23
            continue;
Packit fcad23
Packit fcad23
        if (CONTAINER_REMOVE(cert_maps, cert_map) == 0)
Packit fcad23
            netsnmp_cert_map_free(cert_map);
Packit fcad23
    }
Packit fcad23
    ITERATOR_RELEASE(itr);
Packit fcad23
    CONTAINER_FREE(tmp_maps);
Packit fcad23
Packit fcad23
    return;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
  certSecName PRIORITY [--shaNN|md5] FINGERPRINT <--sn SECNAME | --rfc822 | --dns | --ip | --cn | --any>
Packit fcad23
Packit fcad23
  certSecName  100  ff:..11 --sn Wes
Packit fcad23
  certSecName  200  ee:..:22 --sn JohnDoe
Packit fcad23
  certSecName  300  ee:..:22 --rfc822
Packit fcad23
*/
Packit fcad23
netsnmp_cert_map *
Packit fcad23
netsnmp_certToTSN_parse_common(char **line)
Packit fcad23
{
Packit fcad23
    netsnmp_cert_map *map;
Packit fcad23
    char             *tmp, buf[SNMP_MAXBUF_SMALL];
Packit fcad23
    size_t            len;
Packit fcad23
    netsnmp_cert     *tmpcert;
Packit fcad23
Packit fcad23
    if ((NULL == line) || (NULL == *line))
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    /** need somewhere to save rows */
Packit fcad23
    if (NULL == _maps) {
Packit fcad23
        NETSNMP_LOGONCE((LOG_ERR, "no container for certificate mappings\n"));
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:util:config", "parsing %s\n", *line));
Packit fcad23
Packit fcad23
    /* read the priority */
Packit fcad23
    len = sizeof(buf);
Packit fcad23
    tmp = buf;
Packit fcad23
    *line = read_config_read_octet_string(*line, (u_char **)&tmp, &len;;
Packit fcad23
    tmp[len] = 0;
Packit fcad23
    if (!isdigit(0xFF & tmp[0])) {
Packit fcad23
        netsnmp_config_error("could not parse priority");
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    map = netsnmp_cert_map_alloc(NULL, NULL);
Packit fcad23
    if (NULL == map) {
Packit fcad23
        netsnmp_config_error("could not allocate cert map struct");
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    map->flags |= NSCM_FROM_CONFIG;
Packit fcad23
    map->priority = atoi(buf);
Packit fcad23
Packit fcad23
    /* read the flag or the fingerprint */
Packit fcad23
    len = sizeof(buf);
Packit fcad23
    tmp = buf;
Packit fcad23
    *line = read_config_read_octet_string(*line, (u_char **)&tmp, &len;;
Packit fcad23
    tmp[len] = 0;
Packit fcad23
    if ((buf[0] == '-') && (buf[1] == '-')) {
Packit fcad23
        map->hashType = netsnmp_cert_parse_hash_type(&buf[2]);
Packit fcad23
        if (NS_HASH_NONE == map->hashType) {
Packit fcad23
            netsnmp_config_error("invalid hash type");
Packit fcad23
            goto end;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /** set up for fingerprint */
Packit fcad23
        len = sizeof(buf);
Packit fcad23
        tmp = buf;
Packit fcad23
        *line = read_config_read_octet_string(*line, (u_char **)&tmp, &len;;
Packit fcad23
        tmp[len] = 0;
Packit fcad23
    }
Packit fcad23
    else
Packit fcad23
        map->hashType = NS_HASH_SHA1;
Packit fcad23
Packit fcad23
    /* look up the fingerprint */
Packit fcad23
    tmpcert = netsnmp_cert_find(NS_CERT_REMOTE_PEER, NS_CERTKEY_MULTIPLE, buf);
Packit fcad23
    if (NULL == tmpcert) {
Packit fcad23
        /* assume it's a raw fingerprint we don't have */
Packit fcad23
        netsnmp_fp_lowercase_and_strip_colon(buf);
Packit fcad23
        map->fingerprint = strdup(buf);
Packit fcad23
    } else {
Packit fcad23
        map->fingerprint =
Packit fcad23
            netsnmp_openssl_cert_get_fingerprint(tmpcert->ocert, -1);
Packit fcad23
    }
Packit fcad23
    
Packit fcad23
    if (NULL == *line) {
Packit fcad23
        netsnmp_config_error("must specify map type");
Packit fcad23
        goto end;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /* read the mapping type */
Packit fcad23
    len = sizeof(buf);
Packit fcad23
    tmp = buf;
Packit fcad23
    *line = read_config_read_octet_string(*line, (u_char **)&tmp, &len;;
Packit fcad23
    tmp[len] = 0;
Packit fcad23
    if ((buf[0] != '-') || (buf[1] != '-')) {
Packit fcad23
        netsnmp_config_error("unexpected fromat: %s\n", *line);
Packit fcad23
        goto end;
Packit fcad23
    }
Packit fcad23
    if (strcmp(&buf[2], "sn") == 0) {
Packit fcad23
        if (NULL == *line) {
Packit fcad23
            netsnmp_config_error("must specify secName for --sn");
Packit fcad23
            goto end;
Packit fcad23
        }
Packit fcad23
        len = sizeof(buf);
Packit fcad23
        tmp = buf;
Packit fcad23
        *line = read_config_read_octet_string(*line, (u_char **)&tmp, &len;;
Packit fcad23
        map->data = strdup(buf);
Packit fcad23
        if (map->data)
Packit fcad23
            map->mapType = TSNM_tlstmCertSpecified;
Packit fcad23
    }
Packit fcad23
    else if (strcmp(&buf[2], "cn") == 0)
Packit fcad23
        map->mapType = TSNM_tlstmCertCommonName;
Packit fcad23
    else if (strcmp(&buf[2], "ip") == 0)
Packit fcad23
        map->mapType = TSNM_tlstmCertSANIpAddress;
Packit fcad23
    else if (strcmp(&buf[2], "rfc822") == 0)
Packit fcad23
        map->mapType = TSNM_tlstmCertSANRFC822Name;
Packit fcad23
    else if (strcmp(&buf[2], "dns") == 0)
Packit fcad23
        map->mapType = TSNM_tlstmCertSANDNSName;
Packit fcad23
    else if (strcmp(&buf[2], "any") == 0)
Packit fcad23
        map->mapType = TSNM_tlstmCertSANAny;
Packit fcad23
    else
Packit fcad23
        netsnmp_config_error("unknown argument %s\n", buf);
Packit fcad23
    
Packit fcad23
  end:
Packit fcad23
    if (0 == map->mapType) {
Packit fcad23
        netsnmp_cert_map_free(map);
Packit fcad23
        map = NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return map;
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
_parse_map(const char *token, char *line)
Packit fcad23
{
Packit fcad23
    netsnmp_cert_map *map = netsnmp_certToTSN_parse_common(&line);
Packit fcad23
    if (NULL == map)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    if (netsnmp_cert_map_add(map) != 0) {
Packit fcad23
        netsnmp_cert_map_free(map);
Packit fcad23
        netsnmp_config_error(MAP_CONFIG_TOKEN
Packit fcad23
                             ": duplicate priority for certificate map");
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
_fill_cert_map(netsnmp_cert_map *cert_map, netsnmp_cert_map *entry)
Packit fcad23
{
Packit fcad23
    DEBUGMSGT(("cert:map:secname", "map: pri %d type %d data %s\n",
Packit fcad23
               entry->priority, entry->mapType, entry->data));
Packit fcad23
    cert_map->priority = entry->priority;
Packit fcad23
    cert_map->mapType = entry->mapType;
Packit fcad23
    cert_map->hashType = entry->hashType;
Packit fcad23
    if (entry->data) {
Packit fcad23
        cert_map->data = strdup(entry->data);
Packit fcad23
        if (NULL == cert_map->data ) {
Packit fcad23
            snmp_log(LOG_ERR, "secname map data dup failed\n");
Packit fcad23
            return -1;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * get secname map(s) for fingerprints
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
netsnmp_cert_get_secname_maps(netsnmp_container *cert_maps)
Packit fcad23
{
Packit fcad23
    netsnmp_iterator   *itr;
Packit fcad23
    netsnmp_cert_map   *cert_map, *new_cert_map, *entry;
Packit fcad23
    netsnmp_container  *new_maps = NULL;
Packit fcad23
    netsnmp_void_array *results;
Packit fcad23
    int                 j;
Packit fcad23
Packit fcad23
    if ((NULL == cert_maps) || (CONTAINER_SIZE(cert_maps) == 0))
Packit fcad23
        return -1;
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:map:secname", "looking for matches for %" NETSNMP_PRIz "d fingerprints\n",
Packit fcad23
               CONTAINER_SIZE(cert_maps)));
Packit fcad23
    
Packit fcad23
    /*
Packit fcad23
     * duplicate cert_maps and then iterate over the copy. That way we can
Packit fcad23
     * add/remove to cert_maps without distrubing the iterator.
Packit fcad23
     */
Packit fcad23
    new_maps = CONTAINER_DUP(cert_maps, NULL, 0);
Packit fcad23
    if (NULL == new_maps) {
Packit fcad23
        snmp_log(LOG_ERR, "could not duplicate maps for secname mapping\n");
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    itr = CONTAINER_ITERATOR(new_maps);
Packit fcad23
    if (NULL == itr) {
Packit fcad23
        snmp_log(LOG_ERR, "could not get iterator for secname mappings\n");
Packit fcad23
        CONTAINER_FREE(new_maps);
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
    cert_map = ITERATOR_FIRST(itr);
Packit fcad23
    for( ; cert_map; cert_map = ITERATOR_NEXT(itr)) {
Packit fcad23
Packit fcad23
        results = _find_subset_fp( netsnmp_cert_map_container(),
Packit fcad23
                                   cert_map->fingerprint );
Packit fcad23
        if (NULL == results) {
Packit fcad23
            DEBUGMSGT(("cert:map:secname", "no match for %s\n",
Packit fcad23
                       cert_map->fingerprint));
Packit fcad23
            if (CONTAINER_REMOVE(cert_maps, cert_map) != 0)
Packit fcad23
                goto fail;
Packit fcad23
            continue;
Packit fcad23
        }
Packit fcad23
        DEBUGMSGT(("cert:map:secname", "%" NETSNMP_PRIz "d matches for %s\n",
Packit fcad23
                   results->size, cert_map->fingerprint));
Packit fcad23
        /*
Packit fcad23
         * first entry is a freebie
Packit fcad23
         */
Packit fcad23
        entry = (netsnmp_cert_map*)results->array[0];
Packit fcad23
        if (_fill_cert_map(cert_map, entry) != 0)
Packit fcad23
            goto fail;
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * additional entries must be allocated/inserted
Packit fcad23
         */
Packit fcad23
        if (results->size > 1) {
Packit fcad23
            for(j=1; j < results->size; ++j) {
Packit fcad23
                entry = (netsnmp_cert_map*)results->array[j];
Packit fcad23
                new_cert_map = netsnmp_cert_map_alloc(entry->fingerprint,
Packit fcad23
                                                      entry->ocert);
Packit fcad23
                if (NULL == new_cert_map) {
Packit fcad23
                    snmp_log(LOG_ERR,
Packit fcad23
                             "could not allocate new cert map entry\n");
Packit fcad23
                    goto fail;
Packit fcad23
                }
Packit fcad23
                if (_fill_cert_map(new_cert_map, entry) != 0) {
Packit fcad23
                    netsnmp_cert_map_free(new_cert_map);
Packit fcad23
                    goto fail;
Packit fcad23
                }
Packit fcad23
                new_cert_map->ocert = cert_map->ocert;
Packit fcad23
                if (CONTAINER_INSERT(cert_maps,new_cert_map) != 0) {
Packit fcad23
                    netsnmp_cert_map_free(new_cert_map);
Packit fcad23
                    goto fail;
Packit fcad23
                }
Packit fcad23
            } /* for results */
Packit fcad23
        } /* results size > 1 */
Packit fcad23
Packit fcad23
        free(results->array);
Packit fcad23
        SNMP_FREE(results);
Packit fcad23
    }
Packit fcad23
    ITERATOR_RELEASE(itr);
Packit fcad23
    CONTAINER_FREE(new_maps);
Packit fcad23
Packit fcad23
    DEBUGMSGT(("cert:map:secname",
Packit fcad23
               "found %" NETSNMP_PRIz "d matches for fingerprints\n",
Packit fcad23
               CONTAINER_SIZE(cert_maps)));
Packit fcad23
    return 0;
Packit fcad23
Packit fcad23
  fail:
Packit fcad23
    if (results) {
Packit fcad23
        free(results->array);
Packit fcad23
        free(results);
Packit fcad23
    }
Packit fcad23
    ITERATOR_RELEASE(itr);
Packit fcad23
    CONTAINER_FREE(new_maps);
Packit fcad23
    return -1;
Packit fcad23
}
Packit fcad23
Packit fcad23
/* ***************************************************************************
Packit fcad23
 * ***************************************************************************
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * snmpTlstmParmsTable data
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * ***************************************************************************
Packit fcad23
 * ***************************************************************************/
Packit fcad23
#define PARAMS_CONFIG_TOKEN "snmpTlstmParams"
Packit fcad23
static void _parse_params(const char *token, char *line);
Packit fcad23
Packit fcad23
static void
Packit fcad23
_init_tlstmParams(void)
Packit fcad23
{
Packit fcad23
    const char *params_help = 
Packit fcad23
        PARAMS_CONFIG_TOKEN " targetParamsName hashType:fingerPrint";
Packit fcad23
    
Packit fcad23
    /*
Packit fcad23
     * container for snmpTlstmParamsTable data
Packit fcad23
     */
Packit fcad23
    _tlstmParams = netsnmp_container_find("tlstmParams:string");
Packit fcad23
    if (NULL == _tlstmParams)
Packit fcad23
        snmp_log(LOG_ERR,
Packit fcad23
                 "error creating sub-container for tlstmParamsTable\n");
Packit fcad23
    else
Packit fcad23
        _tlstmParams->container_name = strdup("tlstmParams");
Packit fcad23
Packit fcad23
    register_config_handler(NULL, PARAMS_CONFIG_TOKEN, _parse_params, NULL,
Packit fcad23
                                params_help);
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_TLSTMPARAMS_CONTAINER
Packit fcad23
netsnmp_container *
Packit fcad23
netsnmp_tlstmParams_container(void)
Packit fcad23
{
Packit fcad23
    return _tlstmParams;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_TLSTMPARAMS_CONTAINER */
Packit fcad23
Packit fcad23
snmpTlstmParams *
Packit fcad23
netsnmp_tlstmParams_create(const char *name, int hashType, const char *fp,
Packit fcad23
                           int fp_len)
Packit fcad23
{
Packit fcad23
    snmpTlstmParams *stp = SNMP_MALLOC_TYPEDEF(snmpTlstmParams);
Packit fcad23
    if (NULL == stp)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    if (name)
Packit fcad23
        stp->name = strdup(name);
Packit fcad23
    stp->hashType = hashType;
Packit fcad23
    if (fp)
Packit fcad23
        stp->fingerprint = strdup(fp);
Packit fcad23
    DEBUGMSGT(("9:tlstmParams:create", "%p: %s\n", stp,
Packit fcad23
               stp->name ? stp->name : "null"));
Packit fcad23
Packit fcad23
    return stp;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_tlstmParams_free(snmpTlstmParams *stp)
Packit fcad23
{
Packit fcad23
    if (NULL == stp)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    DEBUGMSGT(("9:tlstmParams:release", "%p %s\n", stp,
Packit fcad23
               stp->name ? stp->name : "null"));
Packit fcad23
    SNMP_FREE(stp->name);
Packit fcad23
    SNMP_FREE(stp->fingerprint);
Packit fcad23
    free(stp); /* SNMP_FREE pointless on parameter */
Packit fcad23
}
Packit fcad23
Packit fcad23
snmpTlstmParams *
Packit fcad23
netsnmp_tlstmParams_restore_common(char **line)
Packit fcad23
{
Packit fcad23
    snmpTlstmParams  *stp;
Packit fcad23
    char             *tmp, buf[SNMP_MAXBUF_SMALL];
Packit fcad23
    size_t            len;
Packit fcad23
Packit fcad23
    if ((NULL == line) || (NULL == *line))
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    /** need somewhere to save rows */
Packit fcad23
    netsnmp_assert(_tlstmParams);
Packit fcad23
Packit fcad23
    stp = netsnmp_tlstmParams_create(NULL, 0, NULL, 0);
Packit fcad23
    if (NULL == stp)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    /** name */
Packit fcad23
    len = sizeof(buf);
Packit fcad23
    tmp = buf;
Packit fcad23
    *line = read_config_read_octet_string(*line, (u_char **)&tmp, &len;;
Packit fcad23
    tmp[len] = 0;
Packit fcad23
    /** xxx-rks: validate snmpadminstring? */
Packit fcad23
    if (len)
Packit fcad23
        stp->name = strdup(buf);
Packit fcad23
Packit fcad23
    /** fingerprint hash type*/
Packit fcad23
    len = sizeof(buf);
Packit fcad23
    tmp = buf;
Packit fcad23
    *line = read_config_read_octet_string(*line, (u_char **)&tmp, &len;;
Packit fcad23
    tmp[len] = 0;
Packit fcad23
    if ((buf[0] == '-') && (buf[1] == '-')) {
Packit fcad23
        stp->hashType = netsnmp_cert_parse_hash_type(&buf[2]);
Packit fcad23
Packit fcad23
        /** set up for fingerprint */
Packit fcad23
        len = sizeof(buf);
Packit fcad23
        tmp = buf;
Packit fcad23
        *line = read_config_read_octet_string(*line, (u_char **)&tmp, &len;;
Packit fcad23
        tmp[len] = 0;
Packit fcad23
    }
Packit fcad23
    else
Packit fcad23
        stp->hashType =NS_HASH_SHA1;
Packit fcad23
    
Packit fcad23
    netsnmp_fp_lowercase_and_strip_colon(buf);
Packit fcad23
    stp->fingerprint = strdup(buf);
Packit fcad23
    stp->fingerprint_len = strlen(buf);
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("tlstmParams:restore:common", "name '%s'\n", stp->name));
Packit fcad23
Packit fcad23
    return stp;
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_tlstmParams_add(snmpTlstmParams *stp)
Packit fcad23
{
Packit fcad23
    if (NULL == stp)
Packit fcad23
        return -1;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("tlstmParams:add", "adding entry %p %s\n", stp, stp->name));
Packit fcad23
Packit fcad23
    if (CONTAINER_INSERT(_tlstmParams, stp) != 0) {
Packit fcad23
        snmp_log(LOG_ERR, "error inserting tlstmParams %s", stp->name);
Packit fcad23
        netsnmp_tlstmParams_free(stp);
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_TLSTMPARAMS_REMOVE
Packit fcad23
int
Packit fcad23
netsnmp_tlstmParams_remove(snmpTlstmParams *stp)
Packit fcad23
{
Packit fcad23
    if (NULL == stp)
Packit fcad23
        return -1;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("tlstmParams:remove", "removing entry %p %s\n", stp,
Packit fcad23
                stp->name));
Packit fcad23
Packit fcad23
    if (CONTAINER_REMOVE(_tlstmParams, stp) != 0) {
Packit fcad23
        snmp_log(LOG_ERR, "error removing tlstmParams %s", stp->name);
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_TLSTMPARAMS_REMOVE */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_TLSTMPARAMS_FIND
Packit fcad23
snmpTlstmParams *
Packit fcad23
netsnmp_tlstmParams_find(snmpTlstmParams *stp)
Packit fcad23
{
Packit fcad23
    snmpTlstmParams *found;
Packit fcad23
Packit fcad23
    if (NULL == stp)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    found = CONTAINER_FIND(_tlstmParams, stp);
Packit fcad23
    return found;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_TLSTMPARAMS_FIND */
Packit fcad23
Packit fcad23
static void
Packit fcad23
_parse_params(const char *token, char *line)
Packit fcad23
{
Packit fcad23
    snmpTlstmParams *stp = netsnmp_tlstmParams_restore_common(&line);
Packit fcad23
Packit fcad23
    if (!stp)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    stp->flags = TLSTM_PARAMS_FROM_CONFIG | TLSTM_PARAMS_NONVOLATILE;
Packit fcad23
Packit fcad23
    netsnmp_tlstmParams_add(stp);
Packit fcad23
}
Packit fcad23
Packit fcad23
static char *
Packit fcad23
_find_tlstmParams_fingerprint(const char *name)
Packit fcad23
{
Packit fcad23
    snmpTlstmParams lookup_key, *result;
Packit fcad23
Packit fcad23
    if (NULL == name)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    lookup_key.name = NETSNMP_REMOVE_CONST(char*, name);
Packit fcad23
Packit fcad23
    result = CONTAINER_FIND(_tlstmParams, &lookup_key);
Packit fcad23
    if ((NULL == result) || (NULL == result->fingerprint))
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    return result->fingerprint;
Packit fcad23
}
Packit fcad23
/*
Packit fcad23
 * END snmpTlstmParmsTable data
Packit fcad23
 * ***************************************************************************/
Packit fcad23
Packit fcad23
/* ***************************************************************************
Packit fcad23
 * ***************************************************************************
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * snmpTlstmAddrTable data
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * ***************************************************************************
Packit fcad23
 * ***************************************************************************/
Packit fcad23
#define ADDR_CONFIG_TOKEN "snmpTlstmAddr"
Packit fcad23
static void _parse_addr(const char *token, char *line);
Packit fcad23
Packit fcad23
static void
Packit fcad23
_init_tlstmAddr(void)
Packit fcad23
{
Packit fcad23
    const char *addr_help = 
Packit fcad23
        ADDR_CONFIG_TOKEN " targetAddrName hashType:fingerprint serverIdentity";
Packit fcad23
    
Packit fcad23
    /*
Packit fcad23
     * container for snmpTlstmAddrTable data
Packit fcad23
     */
Packit fcad23
    _tlstmAddr = netsnmp_container_find("tlstmAddr:string");
Packit fcad23
    if (NULL == _tlstmAddr)
Packit fcad23
        snmp_log(LOG_ERR,
Packit fcad23
                 "error creating sub-container for tlstmAddrTable\n");
Packit fcad23
    else
Packit fcad23
        _tlstmAddr->container_name = strdup("tlstmAddr");
Packit fcad23
Packit fcad23
    register_config_handler(NULL, ADDR_CONFIG_TOKEN, _parse_addr, NULL,
Packit fcad23
                            addr_help);
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_TLSTMADDR_CONTAINER
Packit fcad23
netsnmp_container *
Packit fcad23
netsnmp_tlstmAddr_container(void)
Packit fcad23
{
Packit fcad23
    return _tlstmAddr;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_TLSTMADDR_CONTAINER */
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * create a new row in the table 
Packit fcad23
 */
Packit fcad23
snmpTlstmAddr *
Packit fcad23
netsnmp_tlstmAddr_create(char *targetAddrName)
Packit fcad23
{
Packit fcad23
    snmpTlstmAddr *entry;
Packit fcad23
Packit fcad23
    if (NULL == targetAddrName)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    entry = SNMP_MALLOC_TYPEDEF(snmpTlstmAddr);
Packit fcad23
    if (!entry)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    DEBUGMSGT(("tlstmAddr:entry:create", "entry %p %s\n", entry,
Packit fcad23
               targetAddrName ? targetAddrName : "NULL"));
Packit fcad23
Packit fcad23
    entry->name = strdup(targetAddrName);
Packit fcad23
Packit fcad23
    return entry;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_tlstmAddr_free(snmpTlstmAddr *entry)
Packit fcad23
{
Packit fcad23
    if (!entry)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    SNMP_FREE(entry->name);
Packit fcad23
    SNMP_FREE(entry->fingerprint);
Packit fcad23
    SNMP_FREE(entry->identity);
Packit fcad23
    free(entry);
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_tlstmAddr_restore_common(char **line, char *name, size_t *name_len,
Packit fcad23
                                 char *id, size_t *id_len, char *fp,
Packit fcad23
                                 size_t *fp_len, u_char *ht)
Packit fcad23
{
Packit fcad23
    size_t fp_len_save = *fp_len;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Calling this function with name == NULL, fp == NULL or id == NULL would
Packit fcad23
     * trigger a memory leak.
Packit fcad23
     */
Packit fcad23
    if (!name || !fp || !id)
Packit fcad23
        return -1;
Packit fcad23
Packit fcad23
    *line = read_config_read_octet_string(*line, (u_char **)&name, name_len);
Packit fcad23
    if (NULL == *line) {
Packit fcad23
        config_perror("incomplete line");
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
    name[*name_len] = 0;
Packit fcad23
Packit fcad23
    *line = read_config_read_octet_string(*line, (u_char **)&fp, fp_len);
Packit fcad23
    if (NULL == *line) {
Packit fcad23
        config_perror("incomplete line");
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
    fp[*fp_len] = 0;
Packit fcad23
    if ((fp[0] == '-') && (fp[1] == '-')) {
Packit fcad23
        *ht = netsnmp_cert_parse_hash_type(&fp[2]);
Packit fcad23
        
Packit fcad23
        /** set up for fingerprint */
Packit fcad23
        *fp_len = fp_len_save;
Packit fcad23
        *line = read_config_read_octet_string(*line, (u_char **)&fp, fp_len);
Packit fcad23
        fp[*fp_len] = 0;
Packit fcad23
    }
Packit fcad23
    else
Packit fcad23
        *ht = NS_HASH_SHA1;
Packit fcad23
    netsnmp_fp_lowercase_and_strip_colon(fp);
Packit fcad23
    *fp_len = strlen(fp);
Packit fcad23
    
Packit fcad23
    *line = read_config_read_octet_string(*line, (u_char **)&id, id_len);
Packit fcad23
    id[*id_len] = 0;
Packit fcad23
    
Packit fcad23
    if (*ht <= NS_HASH_NONE || *ht > NS_HASH_MAX) {
Packit fcad23
        config_perror("invalid algorithm for fingerprint");
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if ((0 == *fp_len) && ((0 == *id_len || (*id_len == 1 && id[0] == '*')))) {
Packit fcad23
        /*
Packit fcad23
         * empty fingerprint not allowed with '*' identity
Packit fcad23
         */
Packit fcad23
        config_perror("must specify fingerprint for '*' identity");
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_tlstmAddr_add(snmpTlstmAddr *entry)
Packit fcad23
{
Packit fcad23
    if (!entry)
Packit fcad23
        return -1;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("tlstmAddr:add", "adding entry %p %s %s\n",
Packit fcad23
                entry, entry->name, entry->fingerprint));
Packit fcad23
    if (CONTAINER_INSERT(_tlstmAddr, entry) != 0) {
Packit fcad23
        snmp_log(LOG_ERR, "could not insert addr %s", entry->name);
Packit fcad23
        netsnmp_tlstmAddr_free(entry);
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_TLSTMADDR_REMOVE
Packit fcad23
int
Packit fcad23
netsnmp_tlstmAddr_remove(snmpTlstmAddr *entry)
Packit fcad23
{
Packit fcad23
    if (!entry)
Packit fcad23
        return -1;
Packit fcad23
Packit fcad23
    if (CONTAINER_REMOVE(_tlstmAddr, entry) != 0) {
Packit fcad23
        snmp_log(LOG_ERR, "could not remove addr %s", entry->name);
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_TLSTMADDR_REMOVE */
Packit fcad23
Packit fcad23
static void
Packit fcad23
_parse_addr(const char *token, char *line)
Packit fcad23
{
Packit fcad23
    snmpTlstmAddr *entry;
Packit fcad23
    char           name[SNMPADMINLENGTH  + 1], id[SNMPADMINLENGTH  + 1],
Packit fcad23
                   fingerprint[SNMPTLSFINGERPRINT_MAX_LEN + 1];
Packit fcad23
    size_t         name_len = sizeof(name), id_len = sizeof(id),
Packit fcad23
                   fp_len = sizeof(fingerprint);
Packit fcad23
    u_char         hashType;
Packit fcad23
    int            rc;
Packit fcad23
Packit fcad23
    rc = netsnmp_tlstmAddr_restore_common(&line, name, &name_len, id, &id_len,
Packit fcad23
                                          fingerprint, &fp_len, &hashType);
Packit fcad23
    if (rc < 0)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    if (NULL != line)
Packit fcad23
        config_pwarn("ignore extra tokens on line");
Packit fcad23
Packit fcad23
    entry = netsnmp_tlstmAddr_create(name);
Packit fcad23
    if (NULL == entry)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    entry->flags |= TLSTM_ADDR_FROM_CONFIG;
Packit fcad23
    entry->hashType = hashType;
Packit fcad23
    if (fp_len)
Packit fcad23
        entry->fingerprint = strdup(fingerprint);
Packit fcad23
    if (id_len)
Packit fcad23
        entry->identity = strdup(id);
Packit fcad23
Packit fcad23
    netsnmp_tlstmAddr_add(entry);
Packit fcad23
}
Packit fcad23
Packit fcad23
static char *
Packit fcad23
_find_tlstmAddr_fingerprint(const char *name)
Packit fcad23
{
Packit fcad23
    snmpTlstmAddr    lookup_key, *result;
Packit fcad23
Packit fcad23
    if (NULL == name)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    lookup_key.name = NETSNMP_REMOVE_CONST(char*, name);
Packit fcad23
Packit fcad23
    result = CONTAINER_FIND(_tlstmAddr, &lookup_key);
Packit fcad23
    if (NULL == result)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    return result->fingerprint;
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_TLSTMADDR_GET_SERVERID
Packit fcad23
char *
Packit fcad23
netsnmp_tlstmAddr_get_serverId(const char *name)
Packit fcad23
{
Packit fcad23
    snmpTlstmAddr    lookup_key, *result;
Packit fcad23
Packit fcad23
    if (NULL == name)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    lookup_key.name = NETSNMP_REMOVE_CONST(char*, name);
Packit fcad23
Packit fcad23
    result = CONTAINER_FIND(_tlstmAddr, &lookup_key);
Packit fcad23
    if (NULL == result)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    return result->identity;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_TLSTMADDR_GET_SERVERID */
Packit fcad23
/*
Packit fcad23
 * END snmpTlstmAddrTable data
Packit fcad23
 * ***************************************************************************/
Packit fcad23
Packit fcad23
#else
Packit fcad23
netsnmp_feature_unused(cert_util);
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_CERT_UTIL */
Packit fcad23
netsnmp_feature_unused(cert_util);
Packit fcad23
#endif /* defined(NETSNMP_USE_OPENSSL) && defined(HAVE_LIBSSL) && NETSNMP_TRANSPORT_TLSBASE_DOMAIN */