示例#1
0
static int
_netsnmp_tlsbase_verify_remote_fingerprint (X509 * remote_cert, _netsnmpTLSBaseData * tlsdata, int try_default)
{

    char *fingerprint;

    fingerprint = netsnmp_openssl_cert_get_fingerprint (remote_cert, -1);

    if (!fingerprint)
    {
        /* no peer cert */
        snmp_log (LOG_ERR, "failed to get fingerprint of remote certificate\n");
        return FAILED_FINGERPRINT_VERIFY;
    }

    if (!tlsdata->their_fingerprint && tlsdata->their_identity)
    {
        /* we have an identity; try and find it's fingerprint */
        netsnmp_cert *peer_cert;

        peer_cert = netsnmp_cert_find (NS_CERT_REMOTE_PEER, NS_CERTKEY_MULTIPLE, tlsdata->their_identity);

        if (peer_cert)
            tlsdata->their_fingerprint = netsnmp_openssl_cert_get_fingerprint (peer_cert->ocert, -1);
    }

    if (!tlsdata->their_fingerprint && try_default)
    {
        /* try for the default instead */
        netsnmp_cert *peer_cert;

        peer_cert = netsnmp_cert_find (NS_CERT_REMOTE_PEER, NS_CERTKEY_DEFAULT, NULL);

        if (peer_cert)
            tlsdata->their_fingerprint = netsnmp_openssl_cert_get_fingerprint (peer_cert->ocert, -1);
    }

    if (tlsdata->their_fingerprint)
    {
        netsnmp_fp_lowercase_and_strip_colon (tlsdata->their_fingerprint);
        if (0 != strcmp (tlsdata->their_fingerprint, fingerprint))
        {
            snmp_log (LOG_ERR, "The fingerprint from the remote side's certificate didn't match the expected\n");
            snmp_log (LOG_ERR, "  got %s, expected %s\n", fingerprint, tlsdata->their_fingerprint);
            free (fingerprint);
            return FAILED_FINGERPRINT_VERIFY;
        }
    }
    else
    {
        DEBUGMSGTL (("tls_x509:verify", "No fingerprint for the remote entity available to verify\n"));
        free (fingerprint);
        return NO_FINGERPRINT_AVAILABLE;
    }

    free (fingerprint);
    return VERIFIED_FINGERPRINT;
}
示例#2
0
int _trust_this_cert (SSL_CTX * the_ctx, char *certspec)
{
    netsnmp_cert *trustcert;

    DEBUGMSGTL (("sslctx_client", "Trying to load a trusted certificate: %s\n", certspec));

    /* load this identifier into the trust chain */
    trustcert = netsnmp_cert_find (NS_CERT_CA, NS_CERTKEY_MULTIPLE, certspec);
    if (!trustcert)
        trustcert = netsnmp_cert_find (NS_CERT_REMOTE_PEER, NS_CERTKEY_MULTIPLE, certspec);
    if (!trustcert)
        LOGANDDIE ("failed to find requested certificate to trust");

    /* Add the certificate to the context */
    if (netsnmp_cert_trust_ca (the_ctx, trustcert) != SNMPERR_SUCCESS)
        LOGANDDIE ("failed to load trust certificate");

    return 1;
}
示例#3
0
SSL_CTX *
sslctx_server_setup(const SSL_METHOD *method) {
    netsnmp_cert *id_cert;

    /***********************************************************************
     * Set up the server context
     */
    /* setting up for ssl */
    SSL_CTX *the_ctx = SSL_CTX_new(NETSNMP_REMOVE_CONST(SSL_METHOD *, method));
    if (!the_ctx) {
        LOGANDDIE("can't create a new context");
    }

    id_cert = netsnmp_cert_find(NS_CERT_IDENTITY, NS_CERTKEY_DEFAULT, NULL);
    if (!id_cert)
        LOGANDDIE ("error finding server identity keys");

    if (!id_cert->key || !id_cert->key->okey)
        LOGANDDIE("failed to load private key");

    DEBUGMSGTL(("sslctx_server", "using public key: %s\n",
                id_cert->info.filename));
    DEBUGMSGTL(("sslctx_server", "using private key: %s\n",
                id_cert->key->info.filename));

    if (SSL_CTX_use_certificate(the_ctx, id_cert->ocert) <= 0)
        LOGANDDIE("failed to set the certificate to use");

    if (SSL_CTX_use_PrivateKey(the_ctx, id_cert->key->okey) <= 0)
        LOGANDDIE("failed to set the private key to use");

    if (!SSL_CTX_check_private_key(the_ctx))
        LOGANDDIE("public and private keys incompatible");

    SSL_CTX_set_read_ahead(the_ctx, 1); /* XXX: DTLS only? */

    SSL_CTX_set_verify(the_ctx,
                       SSL_VERIFY_PEER|
                       SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
                       SSL_VERIFY_CLIENT_ONCE,
                       &verify_callback);

    return _sslctx_common_setup(the_ctx, NULL);
}
示例#4
0
文件: target.c 项目: 274914765/C
     netsnmp_session *get_target_sessions (char *taglist, TargetFilterFunction * filterfunct, void *filterArg)
{
    netsnmp_session *ret = NULL, thissess;

    struct targetAddrTable_struct *targaddrs;

    char buf[SPRINT_MAX_LEN];

    char tags[MAX_TAGS][SPRINT_MAX_LEN], *cp;

    int numtags = 0, i;

#if defined(NETSNMP_TRANSPORT_DTLSUDP_DOMAIN) || defined(NETSNMP_TRANSPORT_TLSTCP_DOMAIN)
    int tls = 0;
#endif
    static struct targetParamTable_struct *param;

    DEBUGMSGTL (("target_sessions", "looking for: %s\n", taglist));
    for (cp = taglist; cp && numtags < MAX_TAGS;)
    {
        cp = copy_nword (cp, tags[numtags], sizeof (tags[numtags]));
        DEBUGMSGTL (("target_sessions", " for: %d=%s\n", numtags, tags[numtags]));
        numtags++;
    }

    for (targaddrs = get_addrTable (); targaddrs; targaddrs = targaddrs->next)
    {

        /*
         * legal row? 
         */
        if (targaddrs->tDomain == NULL || targaddrs->tAddress == NULL || targaddrs->rowStatus != SNMP_ROW_ACTIVE)
        {
            DEBUGMSGTL (("target_sessions", "  which is not ready yet\n"));
            continue;
        }

        if (netsnmp_tdomain_support (targaddrs->tDomain, targaddrs->tDomainLen, NULL, NULL) == 0)
        {
            snmp_log (LOG_ERR, "unsupported domain for target address table entry %s\n", targaddrs->name);
        }

        /*
         * check tag list to see if we match 
         */
        if (targaddrs->tagList)
        {
            int matched = 0;

            /*
             * loop through tag list looking for requested tags 
             */
            for (cp = targaddrs->tagList; cp && !matched;)
            {
                cp = copy_nword (cp, buf, sizeof (buf));
                for (i = 0; i < numtags && !matched; i++)
                {
                    if (strcmp (buf, tags[i]) == 0)
                    {
                        /*
                         * found a valid target table entry 
                         */
                        DEBUGMSGTL (("target_sessions", "found one: %s\n", tags[i]));

                        if (targaddrs->params)
                        {
                            param = get_paramEntry (targaddrs->params);
                            if (!param || param->rowStatus != SNMP_ROW_ACTIVE)
                            {
                                /*
                                 * parameter entry must exist and be active 
                                 */
                                continue;
                            }
                        }
                        else
                        {
                            /*
                             * parameter entry must be specified 
                             */
                            continue;
                        }

                        /*
                         * last chance for caller to opt-out.  Call
                         * filtering function 
                         */
                        if (filterfunct && (*(filterfunct)) (targaddrs, param, filterArg))
                        {
                            continue;
                        }

                        /*
                         * Only one notification per TargetAddrEntry,
                         * rather than one per tag
                         */
                        matched = 1;

                        if (targaddrs->storageType != ST_READONLY &&
                            targaddrs->sess && param->updateTime >= targaddrs->sessionCreationTime)
                        {
                            /*
                             * parameters have changed, nuke the old session 
                             */
                            snmp_close (targaddrs->sess);
                            targaddrs->sess = NULL;
                        }

                        /*
                         * target session already exists? 
                         */
                        if (targaddrs->sess == NULL)
                        {
                            /*
                             * create an appropriate snmp session and add
                             * it to our return list 
                             */
                            netsnmp_transport *t = NULL;

                            t = netsnmp_tdomain_transport_oid (targaddrs->tDomain,
                                                               targaddrs->tDomainLen,
                                                               targaddrs->tAddress, targaddrs->tAddressLen, 0);
                            if (t == NULL)
                            {
                                DEBUGMSGTL (("target_sessions", "bad dest \""));
                                DEBUGMSGOID (("target_sessions", targaddrs->tDomain, targaddrs->tDomainLen));
                                DEBUGMSG (("target_sessions", "\", \""));
                                DEBUGMSGHEX (("target_sessions", targaddrs->tAddress, targaddrs->tAddressLen));
                                DEBUGMSG (("target_sessions", "\n"));
                                continue;
                            }
                            else
                            {
                                char *dst_str = t->f_fmtaddr (t, NULL, 0);

                                if (dst_str != NULL)
                                {
                                    DEBUGMSGTL (("target_sessions", "  to: %s\n", dst_str));
                                    free (dst_str);
                                }
                            }
                            /*
                             * if tDomain is tls related, check for tls config
                             */
#ifdef NETSNMP_TRANSPORT_DTLSUDP_DOMAIN
                            tls = snmp_oid_compare (targaddrs->tDomain,
                                                    targaddrs->tDomainLen,
                                                    netsnmpDTLSUDPDomain, netsnmpDTLSUDPDomain_len);

#endif
#ifdef NETSNMP_TRANSPORT_TLSTCP_DOMAIN
                            if (tls)
                                tls = snmp_oid_compare (targaddrs->tDomain,
                                                        targaddrs->tDomainLen,
                                                        netsnmpTLSTCPDomain, netsnmpTLSTCPDomain_len);
#endif
#if defined(NETSNMP_TRANSPORT_DTLSUDP_DOMAIN) || defined(NETSNMP_TRANSPORT_TLSTCP_DOMAIN)
                            if (!tls)
                            {
                                netsnmp_cert *cert;

                                char *server_id = NULL;

                                DEBUGMSGTL (("target_sessions", "  looking up our id: %s\n", targaddrs->params));
                                cert = netsnmp_cert_find (NS_CERT_IDENTITY, NS_CERTKEY_TARGET_PARAM, targaddrs->params);
                                netsnmp_assert (t->f_config);
                                if (cert)
                                {
                                    DEBUGMSGTL (("target_sessions", "  found fingerprint: %s\n", cert->fingerprint));
                                    t->f_config (t, "localCert", cert->fingerprint);
                                }
                                DEBUGMSGTL (("target_sessions", "  looking up their id: %s\n", targaddrs->name));
                                cert = netsnmp_cert_find (NS_CERT_REMOTE_PEER, NS_CERTKEY_TARGET_ADDR, targaddrs->name);
                                if (cert)
                                {
                                    DEBUGMSGTL (("target_sessions", "  found fingerprint: %s\n", cert->fingerprint));
                                    t->f_config (t, "peerCert", cert->fingerprint);
                                }
#ifndef NETSNMP_FEATURE_REMOVE_TLSTMADDR_GET_SERVERID
                                server_id = netsnmp_tlstmAddr_get_serverId (targaddrs->name);
#endif                            /* NETSNMP_FEATURE_REMOVE_TLSTMADDR_GET_SERVERID */
                                if (server_id)
                                {
                                    DEBUGMSGTL (("target_sessions", "  found serverId: %s\n", server_id));
                                    t->f_config (t, "their_hostname", server_id);
                                }
                            }
#endif
                            memset (&thissess, 0, sizeof (thissess));
                            thissess.timeout = (targaddrs->timeout) * 1000;
                            thissess.retries = targaddrs->retryCount;
                            DEBUGMSGTL (("target_sessions",
                                         "timeout: %d -> %ld\n", targaddrs->timeout, thissess.timeout));

                            if (param->mpModel == SNMP_VERSION_3 &&
                                param->secModel != SNMP_SEC_MODEL_USM && param->secModel != SNMP_SEC_MODEL_TSM)
                            {
                                snmp_log (LOG_ERR,
                                          "unsupported mpModel/secModel combo %d/%d for target %s\n",
                                          param->mpModel, param->secModel, targaddrs->name);
                                /*
                                 * XXX: memleak 
                                 */
                                netsnmp_transport_free (t);
                                continue;
                            }
                            thissess.paramName = strdup (param->paramName);
                            thissess.version = param->mpModel;
                            if (param->mpModel == SNMP_VERSION_3)
                            {
                                thissess.securityName = strdup (param->secName);
                                thissess.securityNameLen = strlen (thissess.securityName);
                                thissess.securityLevel = param->secLevel;
                                thissess.securityModel = param->secModel;
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
                            }
                            else
                            {
                                thissess.community = (u_char *) strdup (param->secName);
                                thissess.community_len = strlen ((char *) thissess.community);
#endif
                            }

                            thissess.flags |= SNMP_FLAGS_DONT_PROBE;
                            targaddrs->sess = snmp_add (&thissess, t, NULL, NULL);
                            thissess.flags &= ~SNMP_FLAGS_DONT_PROBE;
                            targaddrs->sessionCreationTime = time (NULL);
                        }
                        if (targaddrs->sess)
                        {
                            if (NULL == targaddrs->sess->paramName)
                                targaddrs->sess->paramName = strdup (param->paramName);

                            targaddrs->sess->next = ret;
                            ret = targaddrs->sess;
                        }
                        else
                        {
                            snmp_sess_perror ("target session", &thissess);
                        }
                    }
                }
            }
        }
    }
    return ret;
}
示例#5
0
/* this is called during negotiationn */
     int verify_callback (int ok, X509_STORE_CTX * ctx)
{
    int err, depth;

    char buf[1024], *fingerprint;

    X509 *thecert;

    netsnmp_cert *cert;

    _netsnmp_verify_info *verify_info;

    SSL *ssl;

    thecert = X509_STORE_CTX_get_current_cert (ctx);
    err = X509_STORE_CTX_get_error (ctx);
    depth = X509_STORE_CTX_get_error_depth (ctx);

    /* things to do: */

    X509_NAME_oneline (X509_get_subject_name (thecert), buf, sizeof (buf));
    fingerprint = netsnmp_openssl_cert_get_fingerprint (thecert, -1);
    DEBUGMSGTL (("tls_x509:verify", "Cert: %s\n", buf));
    DEBUGMSGTL (("tls_x509:verify", "  fp: %s\n", fingerprint ? fingerprint : "unknown"));

    ssl = X509_STORE_CTX_get_ex_data (ctx, SSL_get_ex_data_X509_STORE_CTX_idx ());
    verify_info = SSL_get_ex_data (ssl, openssl_local_index);

    if (verify_info && ok && depth > 0)
    {
        /* remember that a parent certificate has been marked as trusted */
        verify_info->flags |= VRFY_PARENT_WAS_OK;
    }

    /* this ensures for self-signed certificates we have a valid
       locally known fingerprint and then accept it */
    if (!ok &&
        (X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT == err ||
         X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY == err ||
         X509_V_ERR_CERT_UNTRUSTED == err ||
         X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE == err || X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN == err))
    {

        cert = netsnmp_cert_find (NS_CERT_REMOTE_PEER, NS_CERTKEY_FINGERPRINT, (void *) fingerprint);
        if (cert)
            DEBUGMSGTL (("tls_x509:verify", " Found locally: %s/%s\n", cert->info.dir, cert->info.filename));


        if (cert)
        {
            DEBUGMSGTL (("tls_x509:verify", "verify_callback called with: ok=%d ctx=%p depth=%d err=%i:%s\n", ok, ctx,
                         depth, err, X509_verify_cert_error_string (err)));
            DEBUGMSGTL (("tls_x509:verify", "  accepting matching fp of self-signed certificate found in: %s\n",
                         cert->info.filename));
            SNMP_FREE (fingerprint);
            return 1;
        }
        else
        {
            DEBUGMSGTL (("tls_x509:verify", "  no matching fp found\n"));
            /* log where we are and why called */
            snmp_log (LOG_ERR, "tls verification failure: ok=%d ctx=%p depth=%d err=%i:%s\n", ok, ctx, depth, err,
                      X509_verify_cert_error_string (err));
            SNMP_FREE (fingerprint);
            return 0;
        }

        if (0 == depth && verify_info && (verify_info->flags & VRFY_PARENT_WAS_OK))
        {
            DEBUGMSGTL (("tls_x509:verify", "verify_callback called with: ok=%d ctx=%p depth=%d err=%i:%s\n", ok, ctx,
                         depth, err, X509_verify_cert_error_string (err)));
            DEBUGMSGTL (("tls_x509:verify", "  a parent was ok, so returning ok for this child certificate\n"));
            SNMP_FREE (fingerprint);
            return 1;            /* we'll check the hostname later at this level */
        }
    }

    if (0 == ok)
        snmp_log (LOG_ERR, "tls verification failure: ok=%d ctx=%p depth=%d err=%i:%s\n", ok, ctx, depth, err,
                  X509_verify_cert_error_string (err));
    else
        DEBUGMSGTL (("tls_x509:verify", "verify_callback called with: ok=%d ctx=%p depth=%d err=%i:%s\n", ok, ctx,
                     depth, err, X509_verify_cert_error_string (err)));
    DEBUGMSGTL (("tls_x509:verify", "  returning the passed in value of %d\n", ok));
    SNMP_FREE (fingerprint);
    return (ok);
}
示例#6
0
SSL_CTX *sslctx_client_setup (const SSL_METHOD * method, _netsnmpTLSBaseData * tlsbase)
{
    netsnmp_cert *id_cert, *peer_cert;

    SSL_CTX *the_ctx;

    /***********************************************************************
     * Set up the client context
     */
    the_ctx = SSL_CTX_new (NETSNMP_REMOVE_CONST (SSL_METHOD *, method));
    if (!the_ctx)
    {
        snmp_log (LOG_ERR, "ack: %p\n", the_ctx);
        LOGANDDIE ("can't create a new context");
    }
    SSL_CTX_set_read_ahead (the_ctx, 1);    /* Required for DTLS */

    SSL_CTX_set_verify (the_ctx,
                        SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, &verify_callback);

    if (tlsbase->our_identity)
    {
        DEBUGMSGTL (("sslctx_client", "looking for local id: %s\n", tlsbase->our_identity));
        id_cert = netsnmp_cert_find (NS_CERT_IDENTITY, NS_CERTKEY_MULTIPLE, tlsbase->our_identity);
    }
    else
    {
        DEBUGMSGTL (("sslctx_client", "looking for default local id: %s\n", tlsbase->our_identity));
        id_cert = netsnmp_cert_find (NS_CERT_IDENTITY, NS_CERTKEY_DEFAULT, NULL);
    }

    if (!id_cert)
        LOGANDDIE ("error finding client identity keys");

    if (!id_cert->key || !id_cert->key->okey)
        LOGANDDIE ("failed to load private key");

    DEBUGMSGTL (("sslctx_client", "using public key: %s\n", id_cert->info.filename));
    DEBUGMSGTL (("sslctx_client", "using private key: %s\n", id_cert->key->info.filename));

    if (SSL_CTX_use_certificate (the_ctx, id_cert->ocert) <= 0)
        LOGANDDIE ("failed to set the certificate to use");

    if (SSL_CTX_use_PrivateKey (the_ctx, id_cert->key->okey) <= 0)
        LOGANDDIE ("failed to set the private key to use");

    if (!SSL_CTX_check_private_key (the_ctx))
        LOGANDDIE ("public and private keys incompatible");

    if (tlsbase->their_identity)
        peer_cert = netsnmp_cert_find (NS_CERT_REMOTE_PEER, NS_CERTKEY_MULTIPLE, tlsbase->their_identity);
    else
        peer_cert = netsnmp_cert_find (NS_CERT_REMOTE_PEER, NS_CERTKEY_DEFAULT, NULL);
    if (peer_cert)
    {
        DEBUGMSGTL (("sslctx_client", "server's expected public key: %s\n",
                     peer_cert ? peer_cert->info.filename : "none"));

        /* Trust the expected certificate */
        if (netsnmp_cert_trust_ca (the_ctx, peer_cert) != SNMPERR_SUCCESS)
            LOGANDDIE ("failed to set verify paths");
    }

    /* trust a certificate (possibly a CA) aspecifically passed in */
    if (tlsbase->trust_cert)
    {
        if (!_trust_this_cert (the_ctx, tlsbase->trust_cert))
            return 0;
    }

    return _sslctx_common_setup (the_ctx, tlsbase);
}