Coverage Report

Created: 2026-10-17 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/net-snmp/snmplib/transports/snmpTLSBaseDomain.c
Line
Count
Source
1
#include <net-snmp/net-snmp-config.h>
2
#include <net-snmp/net-snmp-features.h>
3
#include <net-snmp/types.h>
4
5
netsnmp_feature_require(cert_util);
6
7
#ifdef HAVE_STRING_H
8
#include <string.h>
9
#else
10
#include <strings.h>
11
#endif
12
#ifdef HAVE_SYS_SOCKET_H
13
#include <sys/socket.h>
14
#endif
15
#ifdef HAVE_NETINET_IN_H
16
#include <netinet/in.h>
17
#endif
18
#ifdef HAVE_ARPA_INET_H
19
#include <arpa/inet.h>
20
#endif
21
#ifdef HAVE_NETDB_H
22
#include <netdb.h>
23
#endif
24
#include <errno.h>
25
#include <ctype.h>
26
#include "../memcheck.h"
27
28
/* OpenSSL Includes */
29
#include <openssl/bio.h>
30
#include <openssl/ssl.h>
31
#include <openssl/err.h>
32
#include <openssl/x509.h>
33
#include <openssl/x509_vfy.h>
34
#include <openssl/x509v3.h>
35
36
#include <net-snmp/config_api.h>
37
#include <net-snmp/library/container.h>
38
#include <net-snmp/library/cert_util.h>
39
#include <net-snmp/library/snmp_openssl.h>
40
#include <net-snmp/library/default_store.h>
41
#include <net-snmp/library/callback.h>
42
#include <net-snmp/library/snmp_logging.h>
43
#include <net-snmp/library/snmp_api.h>
44
#include <net-snmp/library/tools.h>
45
#include <net-snmp/library/snmp.h>
46
#include <net-snmp/library/snmp_debug.h>
47
#include <net-snmp/library/snmp_assert.h>
48
#include <net-snmp/library/snmp_impl.h>
49
#include <net-snmp/library/snmp_transport.h>
50
#include <net-snmp/library/snmp_secmod.h>
51
#include <net-snmp/library/read_config.h>
52
#include <net-snmp/library/system.h>
53
#include <net-snmp/library/snmpTLSBaseDomain.h>
54
#include "snmpTLSBaseDomain.h"
55
56
#ifndef X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS
57
#define X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS 0
58
#endif
59
60
0
#define LOGANDDIE(msg) do { snmp_log(LOG_ERR, "%s\n", msg); return 0; } while(0)
61
62
int openssl_local_index;
63
64
#ifndef HAVE_ERR_GET_ERROR_ALL
65
/*
66
 * A backport of the OpenSSL 3.0 ERR_get_error_all() function. See also
67
 * OpenSSL commit b13342e933c5 ("Modernise the ERR functionality further (new
68
 * functions and deprecations)").
69
 */
70
static unsigned long ERR_get_error_all(const char **file, int *line,
71
                                       const char **func,
72
                                       const char **data, int *flags)
73
0
{
74
0
    *func = "(?)";
75
#ifdef HAVE_ERR_GET_ERROR_FUNC
76
    ERR_get_error_func(func);
77
#endif
78
0
    return ERR_get_error_line_data(file, line, data, flags);
79
0
}
80
#endif
81
82
/* this is called during negotiation */
83
0
int verify_callback(int ok, X509_STORE_CTX *ctx) {
84
0
    int err, depth;
85
0
    char subject[SNMP_MAXBUF_MEDIUM], issuer[SNMP_MAXBUF_MEDIUM], *fingerprint;
86
0
    X509 *thecert;
87
0
    netsnmp_cert *cert;
88
0
    _netsnmp_verify_info *verify_info;
89
0
    SSL *ssl;
90
91
0
    thecert = X509_STORE_CTX_get_current_cert(ctx);
92
0
    err = X509_STORE_CTX_get_error(ctx);
93
0
    depth = X509_STORE_CTX_get_error_depth(ctx);
94
    
95
    /* things to do: */
96
97
0
    X509_NAME_oneline(X509_get_subject_name(thecert), subject, sizeof(subject));
98
0
    X509_NAME_oneline(X509_get_issuer_name(thecert), issuer, sizeof(issuer));
99
0
    fingerprint = netsnmp_openssl_cert_get_fingerprint(thecert, NS_HASH_SHA1);
100
0
    DEBUGMSGTL(("tls_x509:verify", " subject: %s\n", subject));
101
0
    DEBUGMSGTL(("tls_x509:verify", "  issuer: %s\n", issuer));
102
0
    DEBUGMSGTL(("tls_x509:verify", "      fp: %s\n", fingerprint ?
103
0
                fingerprint : "unknown"));
104
105
0
    ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
106
0
    verify_info = SSL_get_ex_data(ssl, openssl_local_index);
107
108
0
    if (verify_info && ok && depth > 0) {
109
        /* remember that a parent certificate has been marked as trusted */
110
0
        verify_info->flags |= VRFY_PARENT_WAS_OK;
111
0
    }
112
113
    /* this ensures for self-signed certificates we have a valid
114
       locally known fingerprint and then accept it */
115
0
    if (!ok &&
116
0
        (X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT == err ||
117
0
         X509_V_ERR_CERT_UNTRUSTED == err ||
118
0
         X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE == err ||
119
0
         X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN == err ||
120
0
         X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY == err ||
121
0
         X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT == err)) {
122
0
        X509 *leaf_cert = X509_STORE_CTX_get0_cert(ctx);
123
0
        char *leaf_fp = netsnmp_openssl_cert_get_fingerprint(leaf_cert ? leaf_cert : thecert, NS_HASH_SHA1);
124
0
        cert = netsnmp_cert_find(NS_CERT_REMOTE_PEER, NS_CERTKEY_FINGERPRINT,
125
0
                                 (void*)leaf_fp);
126
0
        SNMP_FREE(leaf_fp);
127
0
        if (cert && ssl && !SSL_is_server(ssl)) {
128
0
            X509_STORE *certstore = X509_STORE_CTX_get0_store(ctx);
129
0
            int store_num = certstore ? sk_X509_OBJECT_num(X509_STORE_get0_objects(certstore)) : 0;
130
0
            if (store_num == 0) {
131
0
                cert = NULL;
132
0
            }
133
0
        }
134
0
        if (cert)
135
0
            DEBUGMSGTL(("tls_x509:verify", " Found locally: %s/%s\n",
136
0
                        cert->info.dir, cert->info.filename));
137
138
139
0
        if (cert) {
140
0
            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)));
141
0
            DEBUGMSGTL(("tls_x509:verify", "  accepting matching fp of self-signed certificate found in: %s\n",
142
0
                        cert->info.filename));
143
0
            SNMP_FREE(fingerprint);
144
0
            return 1;
145
0
        } else {
146
0
            DEBUGMSGTL(("tls_x509:verify", "  no matching fp found\n"));
147
            /* log where we are and why called */
148
0
            snmp_log(LOG_ERR, "tls verification failure: ok=%d ctx=%p depth=%d fp=%s subject='%s' issuer='%s' err=%i:%s\n", ok, ctx, depth, fingerprint, subject, issuer, err, X509_verify_cert_error_string(err));
149
0
            SNMP_FREE(fingerprint);
150
0
            return 0;
151
0
        }
152
153
#if 0
154
        /*
155
         * This code is unreachable because of the return statements above.
156
         * Comment it out to avoid that Coverity complains about this code.
157
         */
158
        if (0 == depth && verify_info &&
159
            (verify_info->flags & VRFY_PARENT_WAS_OK)) {
160
            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)));
161
            DEBUGMSGTL(("tls_x509:verify", "  a parent was ok, so returning ok for this child certificate\n"));
162
            SNMP_FREE(fingerprint);
163
            return 1; /* we'll check the hostname later at this level */
164
        }
165
#endif
166
0
    }
167
168
0
    if (0 == ok)
169
0
        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));
170
0
    else
171
0
        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)));
172
0
    DEBUGMSGTL(("tls_x509:verify", "  returning the passed in value of %d\n",
173
0
                ok));
174
0
    SNMP_FREE(fingerprint);
175
0
    return(ok);
176
0
}
177
178
0
#define VERIFIED_FINGERPRINT      0
179
0
#define NO_FINGERPRINT_AVAILABLE  1
180
0
#define FAILED_FINGERPRINT_VERIFY 2
181
182
static int
183
_netsnmp_tlsbase_verify_remote_fingerprint(X509 *remote_cert,
184
                                           _netsnmpTLSBaseData *tlsdata,
185
0
                                           int try_default) {
186
187
0
    char            *fingerprint;
188
189
0
    fingerprint =
190
0
        netsnmp_openssl_cert_get_fingerprint(remote_cert, NS_HASH_SHA1);
191
192
0
    if (!fingerprint) {
193
        /* no peer cert */
194
0
        snmp_log(LOG_ERR, "failed to get fingerprint of remote certificate\n");
195
0
        return FAILED_FINGERPRINT_VERIFY;
196
0
    }
197
198
0
    if (!tlsdata->their_fingerprint && tlsdata->their_identity) {
199
        /* we have an identity; try and find it's fingerprint */
200
0
        netsnmp_cert *peer_cert;
201
0
        peer_cert =
202
0
            netsnmp_cert_find(NS_CERT_REMOTE_PEER, NS_CERTKEY_MULTIPLE,
203
0
                              tlsdata->their_identity);
204
205
0
        if (peer_cert)
206
0
            tlsdata->their_fingerprint =
207
0
                netsnmp_openssl_cert_get_fingerprint(peer_cert->ocert, NS_HASH_SHA1);
208
0
    }
209
210
0
    if (!tlsdata->their_fingerprint && try_default) {
211
        /* try for the default instead */
212
0
        netsnmp_cert *peer_cert;
213
0
        peer_cert =
214
0
            netsnmp_cert_find(NS_CERT_REMOTE_PEER, NS_CERTKEY_DEFAULT,
215
0
                              NULL);
216
217
0
        if (peer_cert)
218
0
            tlsdata->their_fingerprint =
219
0
                netsnmp_openssl_cert_get_fingerprint(peer_cert->ocert, NS_HASH_SHA1);
220
0
    }
221
    
222
0
    if (tlsdata->their_fingerprint) {
223
0
        netsnmp_fp_lowercase_and_strip_colon(tlsdata->their_fingerprint);
224
0
        if (0 != strcmp(tlsdata->their_fingerprint, fingerprint)) {
225
0
            snmp_log(LOG_ERR, "The fingerprint from the remote side's certificate didn't match the expected\n");
226
0
            snmp_log(LOG_ERR, "  got %s, expected %s\n",
227
0
                     fingerprint, tlsdata->their_fingerprint);
228
0
            free(fingerprint);
229
0
            return FAILED_FINGERPRINT_VERIFY;
230
0
        }
231
0
    } else {
232
0
        DEBUGMSGTL(("tls_x509:verify", "No fingerprint for the remote entity available to verify\n"));
233
0
        free(fingerprint);
234
0
        return NO_FINGERPRINT_AVAILABLE;
235
0
    }
236
237
0
    free(fingerprint);
238
0
    return VERIFIED_FINGERPRINT;
239
0
}
240
241
/* this is called after the connection on the client side by us to check
242
   other aspects about the connection */
243
int
244
0
netsnmp_tlsbase_verify_server_cert(SSL *ssl, _netsnmpTLSBaseData *tlsdata) {
245
    /* XXX */
246
0
    X509            *remote_cert = NULL;
247
0
    char            *their_hostname;
248
0
    size_t           their_hostname_len;
249
0
    int              ret;
250
0
    size_t           i;
251
0
    int              rv = SNMPERR_GENERR;
252
253
0
    netsnmp_assert_or_return(ssl != NULL, SNMPERR_GENERR);
254
0
    netsnmp_assert_or_return(tlsdata != NULL, SNMPERR_GENERR);
255
256
0
    remote_cert = SSL_get_peer_certificate(ssl);
257
0
    if (!remote_cert) {
258
        /* no peer cert */
259
0
        DEBUGMSGTL(("tls_x509:verify",
260
0
                    "remote connection provided no certificate (yet)\n"));
261
0
        return SNMPERR_TLS_NO_CERTIFICATE;
262
0
    }
263
264
    /* make sure that the fingerprint matches */
265
0
    ret = _netsnmp_tlsbase_verify_remote_fingerprint(remote_cert, tlsdata, 1);
266
0
    switch(ret) {
267
0
    case VERIFIED_FINGERPRINT:
268
0
        rv = SNMPERR_SUCCESS;
269
0
        goto out;
270
271
0
    case FAILED_FINGERPRINT_VERIFY:
272
0
        rv = SNMPERR_GENERR;
273
0
        goto out;
274
275
0
    case NO_FINGERPRINT_AVAILABLE:
276
0
        if (tlsdata->their_hostname && tlsdata->their_hostname[0] != '\0') {
277
0
            char *lower_hostname;
278
279
0
            their_hostname_len = strlen(tlsdata->their_hostname);
280
0
            their_hostname = tlsdata->their_hostname;
281
            
282
            /* RFC 6353: convert their_hostname to lowercase */
283
0
            lower_hostname = calloc(their_hostname_len + 1, sizeof(char));
284
0
            if (NULL == lower_hostname) {
285
0
                snmp_log(LOG_ERR,
286
0
                         "Failed to allocate memory to convert hostname to lowercase\n");
287
0
                rv = SNMPERR_GENERR;
288
0
                goto out;
289
0
            }
290
0
            for (i = 0; i < their_hostname_len; ++i) {
291
0
                lower_hostname[i] = tolower((unsigned char) their_hostname[i]);
292
0
            }
293
            /* RFC 1034 section 3.5
294
               Disable support for "w*.example.com" and "*w.example.com"
295
               multilevel wildcards
296
            */
297
0
            if (1 == X509_check_host(remote_cert,
298
0
                                   lower_hostname,
299
0
                                   their_hostname_len,
300
0
                                   X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS | X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS,
301
0
                                   NULL)) {
302
0
                DEBUGMSGTL(("tls_x509:verify", "Successful match on a subjectAltname of dns or a common name: %s\n", lower_hostname));
303
0
                free(lower_hostname);
304
0
                rv = SNMPERR_SUCCESS;
305
0
                goto out;
306
0
            }
307
0
            if (strchr(lower_hostname, '*') != NULL &&
308
0
                1 == netsnmp_openssl_cert_check_host(remote_cert, lower_hostname)) {
309
0
                DEBUGMSGTL(("tls_x509:verify", "Successful match on a wildcard hostname: %s\n", lower_hostname));
310
0
                free(lower_hostname);
311
0
                rv = SNMPERR_SUCCESS;
312
0
                goto out;
313
0
            }
314
0
            free(lower_hostname);
315
0
            if (1 == X509_check_ip_asc(remote_cert,
316
0
                                      their_hostname,
317
0
                                      0)) {
318
0
                DEBUGMSGTL(("tls_x509:verify", "Successful match on a subjectAltname of IP: %s\n", their_hostname));
319
0
                rv = SNMPERR_SUCCESS;
320
0
                goto out;
321
0
            }
322
0
            snmp_log(LOG_ERR, "No matching names in the certificate to match the expected %s\n", their_hostname);
323
0
            rv = SNMPERR_GENERR;
324
0
            goto out;
325
0
        }
326
        /* XXX: check for hostname match instead */
327
0
        snmp_log(LOG_ERR, "Can not verify a remote server identity without configuration\n");
328
0
        rv = SNMPERR_GENERR;
329
0
        goto out;
330
0
    }
331
0
    DEBUGMSGTL(("tls_x509:verify", "shouldn't get here\n"));
332
0
    rv = SNMPERR_GENERR;
333
334
0
out:
335
0
    X509_free(remote_cert);
336
0
    return rv;
337
0
}
338
339
/* this is called after the connection on the server side by us to check
340
   the validity of the client's certificate */
341
int
342
0
netsnmp_tlsbase_verify_client_cert(SSL *ssl, _netsnmpTLSBaseData *tlsdata) {
343
    /* XXX */
344
0
    X509            *remote_cert = NULL;
345
0
    int ret;
346
0
    int rv = SNMPERR_GENERR;
347
348
    /* RFC5953: section 5.3.2, paragraph 1:
349
       A (D)TLS server should accept new session connections from any client
350
       that it is able to verify the client's credentials for.  This is done
351
       by authenticating the client's presented certificate through a
352
       certificate path validation process (e.g.  [RFC5280]) or through
353
       certificate fingerprint verification using fingerprints configured in
354
       the snmpTlstmCertToTSNTable.  Afterward the server will determine the
355
       identity of the remote entity using the following procedures.
356
     */
357
    /* Implementation notes:
358
       + path validation is taken care of during the openssl verify
359
         routines, our part of which is handled in verify_callback
360
         above.
361
       + fingerprint verification happens below.
362
     */
363
0
    remote_cert = SSL_get_peer_certificate(ssl);
364
0
    if (!remote_cert) {
365
        /* no peer cert */
366
0
        DEBUGMSGTL(("tls_x509:verify",
367
0
                    "remote connection provided no certificate (yet)\n"));
368
0
        return SNMPERR_TLS_NO_CERTIFICATE;
369
0
    }
370
371
    /* we don't force a known remote fingerprint for a client since we
372
       will accept any certificate we know about (and later derive the
373
       securityName from it and apply access control) */
374
0
    ret = _netsnmp_tlsbase_verify_remote_fingerprint(remote_cert, tlsdata, 0);
375
0
    switch(ret) {
376
0
    case FAILED_FINGERPRINT_VERIFY:
377
0
        DEBUGMSGTL(("tls_x509:verify", "failed to verify a client fingerprint\n"));
378
0
        rv = SNMPERR_GENERR;
379
0
        goto out;
380
381
0
    case NO_FINGERPRINT_AVAILABLE:
382
0
        DEBUGMSGTL(("tls_x509:verify", "no known fingerprint available (not a failure case)\n"));
383
0
        rv = SNMPERR_SUCCESS;
384
0
        goto out;
385
386
0
    case VERIFIED_FINGERPRINT:
387
0
        DEBUGMSGTL(("tls_x509:verify", "Verified client fingerprint\n"));
388
0
        tlsdata->flags |= NETSNMP_TLSBASE_CERT_FP_VERIFIED;
389
0
        rv = SNMPERR_SUCCESS;
390
0
        goto out;
391
0
    }
392
393
0
    DEBUGMSGTL(("tls_x509:verify", "shouldn't get here\n"));
394
0
    rv = SNMPERR_GENERR;
395
396
0
out:
397
0
    X509_free(remote_cert);
398
0
    return rv;
399
0
}
400
401
/* this is called after the connection on the server side by us to
402
   check other aspects about the connection and obtain the
403
   securityName from the remote certificate. */
404
int
405
0
netsnmp_tlsbase_extract_security_name(SSL *ssl, _netsnmpTLSBaseData *tlsdata) {
406
0
    netsnmp_container  *chain_maps;
407
0
    netsnmp_cert_map   *cert_map, *peer_cert;
408
0
    netsnmp_iterator  *itr;
409
0
    int                 rc;
410
0
    X509               *client_cert;
411
0
    char               *client_fp;
412
413
0
    netsnmp_assert_or_return(ssl != NULL, SNMPERR_GENERR);
414
0
    netsnmp_assert_or_return(tlsdata != NULL, SNMPERR_GENERR);
415
416
0
    if (NULL == (chain_maps = netsnmp_openssl_get_cert_chain(ssl)))
417
0
        return SNMPERR_GENERR;
418
    /*
419
     * map fingerprints to mapping entries
420
     */
421
0
    rc = netsnmp_cert_get_secname_maps(chain_maps);
422
0
    if ((-1 == rc) || (CONTAINER_SIZE(chain_maps) == 0)) {
423
0
        netsnmp_cert_map_container_free(chain_maps);
424
0
        return SNMPERR_GENERR;
425
0
    }
426
427
0
    client_cert = SSL_get_peer_certificate(ssl);
428
0
    client_fp = netsnmp_openssl_cert_get_fingerprint(client_cert, NS_HASH_SHA1);
429
0
    X509_free(client_cert);
430
431
0
    peer_cert = NULL;
432
0
    itr = CONTAINER_ITERATOR(chain_maps);
433
0
    if (NULL == itr) {
434
0
        snmp_log(LOG_ERR, "could not get iterator for secname fingerprints\n");
435
0
        free(client_fp);
436
0
        netsnmp_cert_map_container_free(chain_maps);
437
0
        return SNMPERR_GENERR;
438
0
    }
439
0
    for (cert_map = ITERATOR_FIRST(itr); cert_map; cert_map = ITERATOR_NEXT(itr)) {
440
0
        if (client_fp && cert_map->fingerprint &&
441
0
            strcmp(cert_map->fingerprint, client_fp) == 0) {
442
0
            peer_cert = cert_map;
443
0
            break;
444
0
        }
445
0
    }
446
0
    ITERATOR_RELEASE(itr);
447
0
    free(client_fp);
448
449
0
    if (NULL == peer_cert) {
450
0
        snmp_log(LOG_ERR, "could not find peer certificate in chain maps\n");
451
0
        netsnmp_cert_map_container_free(chain_maps);
452
0
        return SNMPERR_GENERR;
453
0
    }
454
455
    /*
456
     * change container to sorted (by clearing unsorted option), then
457
     * iterate over it until we find a map that returns a secname.
458
     */
459
0
    CONTAINER_SET_OPTIONS(chain_maps, 0, rc);
460
0
    itr = CONTAINER_ITERATOR(chain_maps);
461
0
    if (NULL == itr) {
462
0
        snmp_log(LOG_ERR, "could not get iterator for secname fingerprints\n");
463
0
        netsnmp_cert_map_container_free(chain_maps);
464
0
        return SNMPERR_GENERR;
465
0
    }
466
0
    cert_map = ITERATOR_FIRST(itr);
467
0
    for( ; !tlsdata->securityName && cert_map; cert_map = ITERATOR_NEXT(itr))
468
0
        tlsdata->securityName =
469
0
            netsnmp_openssl_extract_secname(cert_map, peer_cert);
470
0
    ITERATOR_RELEASE(itr);
471
472
0
    netsnmp_cert_map_container_free(chain_maps);
473
       
474
0
    return (tlsdata->securityName ? SNMPERR_SUCCESS : SNMPERR_GENERR);
475
0
}
476
477
int
478
0
_trust_this_cert(SSL_CTX *the_ctx, char *certspec) {
479
0
    netsnmp_cert *trustcert;
480
0
    netsnmp_cert *candidate;
481
0
    netsnmp_void_array *matching = NULL;
482
483
0
    int                 i;
484
485
0
    DEBUGMSGTL(("sslctx_client", "Trying to load a trusted certificate: %s\n",
486
0
                certspec));
487
488
    /* load this identifier into the trust chain */
489
0
    trustcert = netsnmp_cert_find(NS_CERT_CA,
490
0
                                  NS_CERTKEY_FINGERPRINT,
491
0
                                  certspec);
492
493
    /* loop through all CA certs in the given files */
494
0
    if (!trustcert) {
495
0
        matching = netsnmp_certs_find(NS_CERT_CA,
496
0
                                      NS_CERTKEY_FILE,
497
0
                                      certspec);
498
0
        for (i = 0; (matching) && (i < matching->size); ++i) {
499
0
            candidate = (netsnmp_cert*)matching->array[i];
500
0
            if (netsnmp_cert_trust(the_ctx, candidate) != SNMPERR_SUCCESS) {
501
0
                free(matching->array);
502
0
                free(matching);
503
0
                LOGANDDIE("failed to load trust certificate");
504
0
            }
505
0
        } /** matching loop */
506
507
0
        if (matching) {
508
0
            free(matching->array);
509
0
            free(matching);
510
0
            return 1;
511
0
  }
512
0
    }
513
514
    /* fall back to trusting the remote peer certificate */
515
0
    if (!trustcert)
516
0
        trustcert = netsnmp_cert_find(NS_CERT_REMOTE_PEER,
517
0
                                      NS_CERTKEY_MULTIPLE,
518
0
                                      certspec);
519
0
    if (!trustcert)
520
0
        LOGANDDIE("failed to find requested certificate to trust");
521
522
    /* Add the certificate to the context */
523
0
    if (netsnmp_cert_trust(the_ctx, trustcert) != SNMPERR_SUCCESS)
524
0
        LOGANDDIE("failed to load trust certificate");
525
526
0
    return 1;
527
0
}
528
529
void
530
0
_load_trusted_certs(SSL_CTX *the_ctx) {
531
0
    netsnmp_container *trusted_certs = NULL;
532
0
    netsnmp_iterator  *trusted_cert_iterator = NULL;
533
0
    char *fingerprint;
534
535
0
    trusted_certs = netsnmp_cert_get_trustlist();
536
0
    trusted_cert_iterator = CONTAINER_ITERATOR(trusted_certs);
537
0
    if (trusted_cert_iterator) {
538
0
        for (fingerprint = (char *) ITERATOR_FIRST(trusted_cert_iterator);
539
0
             fingerprint; fingerprint = ITERATOR_NEXT(trusted_cert_iterator)) {
540
0
            if (!_trust_this_cert(the_ctx, fingerprint))
541
0
                snmp_log(LOG_ERR, "failed to load trust cert: %s\n",
542
0
                         fingerprint);
543
0
        }
544
0
        ITERATOR_RELEASE(trusted_cert_iterator);
545
0
    }
546
0
}    
547
548
#ifndef TLS1_3_VERSION
549
#define TLS1_3_VERSION 0x304
550
#endif
551
552
int _sslctx_set_tls_version(SSL_CTX *the_ctx)
553
0
{
554
0
#ifdef SSL_CTX_set_min_proto_version
555
0
    const char   *tlsMinVersion;
556
0
    const char   *tlsMaxVersion;
557
0
    int          tlsVersion;
558
559
0
    tlsVersion = TLS1_2_VERSION;
560
0
    tlsMinVersion = "tls1_2";
561
0
    tlsMinVersion = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
562
0
                                          NETSNMP_DS_LIB_TLS_MIN_VERSION);
563
0
    if (NULL != tlsMinVersion) {
564
0
        if (strcmp("tls1",tlsMinVersion) == 0) {
565
0
           tlsVersion = TLS1_VERSION;
566
0
        }
567
0
        else if (strcmp("tls1_1",tlsMinVersion) == 0) {
568
0
           tlsVersion = TLS1_1_VERSION;
569
0
        }
570
0
        else if (strcmp("tls1_2",tlsMinVersion) == 0) {
571
0
           tlsVersion = TLS1_2_VERSION;
572
0
        }
573
0
        else if (strcmp("tls1_3",tlsMinVersion) == 0) {
574
0
           tlsVersion = TLS1_3_VERSION;
575
0
        }
576
0
        else {
577
0
            LOGANDDIE("Invalid tlsMinVersion value");
578
0
        }
579
0
    }
580
0
    if (1 == SSL_CTX_set_min_proto_version(the_ctx, tlsVersion)) {
581
0
        DEBUGMSGTL(("sslctx", "Set tlsMinVersion to '%s'\n", tlsMinVersion));
582
0
    }
583
0
    else {
584
0
        LOGANDDIE("Set tlsMinVersion failed");
585
0
    }
586
587
0
    tlsVersion = TLS1_3_VERSION;
588
0
    tlsMaxVersion = "tls1_3";
589
0
    tlsMaxVersion = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
590
0
                                          NETSNMP_DS_LIB_TLS_MAX_VERSION);
591
0
    if (NULL != tlsMaxVersion) {
592
0
        if (strcmp("tls1",tlsMaxVersion) == 0) {
593
0
            tlsVersion = TLS1_VERSION;
594
0
        }
595
0
        else if (strcmp("tls1_1",tlsMaxVersion) == 0) {
596
0
            tlsVersion = TLS1_1_VERSION;
597
0
        }
598
0
        else if (strcmp("tls1_2",tlsMaxVersion) == 0) {
599
0
            tlsVersion = TLS1_2_VERSION;
600
0
        }
601
0
        else if (strcmp("tls1_3",tlsMaxVersion) == 0) {
602
0
            tlsVersion = TLS1_3_VERSION;
603
0
        }
604
0
        else {
605
0
            LOGANDDIE("Invalid tlsMaxVersion value");
606
0
        }
607
0
    }
608
609
0
    if (1 == SSL_CTX_set_max_proto_version(the_ctx, tlsVersion)) {
610
0
        DEBUGMSGTL(("sslctx", "Set tlsMaxVersion to '%s'\n", tlsMaxVersion));
611
0
    }
612
0
    else {
613
0
        LOGANDDIE("Set tlsMaxVersion failed");
614
0
    }
615
0
#endif
616
617
0
    return 1;
618
0
}
619
620
SSL_CTX *
621
0
_sslctx_common_setup(SSL_CTX *the_ctx, _netsnmpTLSBaseData *tlsbase) {
622
0
    char         *crlFile;
623
0
    const SSL_METHOD *method;
624
0
    char         *cipherList;
625
0
    X509_LOOKUP  *lookup;
626
0
    X509_STORE   *cert_store = NULL;
627
628
0
    _load_trusted_certs(the_ctx);
629
630
    /* add in the CRLs if available */
631
632
0
    crlFile = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
633
0
                                    NETSNMP_DS_LIB_X509_CRL_FILE);
634
0
    if (NULL != crlFile) {
635
0
        cert_store = SSL_CTX_get_cert_store(the_ctx);
636
0
        DEBUGMSGTL(("sslctx_common", "loading CRL: %s\n", crlFile));
637
0
        if (!cert_store) {
638
0
            SSL_CTX_free(the_ctx);
639
0
            LOGANDDIE("failed to find certificate store");
640
0
        }
641
0
        if (!(lookup = X509_STORE_add_lookup(cert_store, X509_LOOKUP_file()))) {
642
0
            SSL_CTX_free(the_ctx);
643
0
            LOGANDDIE("failed to create a lookup function for the CRL file");
644
0
        }
645
0
        if (X509_load_crl_file(lookup, crlFile, X509_FILETYPE_PEM) != 1) {
646
0
            SSL_CTX_free(the_ctx);
647
0
            LOGANDDIE("failed to load the CRL file");
648
0
        }
649
        /* tell openssl to check CRLs */
650
0
        X509_STORE_set_flags(cert_store,
651
0
                             X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
652
0
    }
653
654
0
    method = SSL_CTX_get_ssl_method(the_ctx);
655
0
    if ((method == TLS_method() || method == TLS_client_method() ||
656
0
         method == TLS_server_method()) &&
657
0
        _sslctx_set_tls_version(the_ctx) == 0) {
658
0
        SSL_CTX_free(the_ctx);
659
0
        return NULL;
660
0
    }
661
662
0
    cipherList = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
663
0
                                       NETSNMP_DS_LIB_TLS_ALGORITMS);
664
0
    if (NULL != cipherList) {
665
0
        if (SSL_CTX_set_cipher_list(the_ctx, cipherList) != 1) {
666
0
            SSL_CTX_free(the_ctx);
667
0
            LOGANDDIE("failed to set the cipher list to the requested value");
668
0
        } else
669
0
            snmp_log(LOG_INFO,"set SSL cipher list to '%s'\n", cipherList);
670
0
    }
671
0
    SSL_CTX_set_session_cache_mode(the_ctx, SSL_SESS_CACHE_OFF);
672
0
    return the_ctx;
673
0
}
674
675
SSL_CTX *
676
0
sslctx_client_setup(const SSL_METHOD *method, _netsnmpTLSBaseData *tlsbase) {
677
0
    netsnmp_cert *id_cert, *peer_cert;
678
0
    SSL_CTX      *the_ctx;
679
0
    X509         *ocert;
680
0
    const char   *msg;
681
682
    /***********************************************************************
683
     * Set up the client context
684
     */
685
0
    the_ctx = SSL_CTX_new(NETSNMP_REMOVE_CONST(SSL_METHOD *, method));
686
0
    if (!the_ctx) {
687
0
        snmp_log(LOG_ERR, "ack: %p\n", the_ctx);
688
0
        msg = "can't create a new context";
689
0
        goto err;
690
0
    }
691
0
    MAKE_MEM_DEFINED(the_ctx, 256/*sizeof(*the_ctx)*/);
692
0
    SSL_CTX_set_read_ahead (the_ctx, 1); /* Required for DTLS */
693
        
694
0
    SSL_CTX_set_verify(the_ctx,
695
0
                       SSL_VERIFY_PEER|
696
0
                       SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
697
0
                       SSL_VERIFY_CLIENT_ONCE,
698
0
                       &verify_callback);
699
700
0
    if (tlsbase->our_identity) {
701
0
        DEBUGMSGTL(("sslctx_client", "looking for local id: %s\n", tlsbase->our_identity));
702
0
        id_cert = netsnmp_cert_find(NS_CERT_IDENTITY, NS_CERTKEY_MULTIPLE,
703
0
                                    tlsbase->our_identity);
704
0
    } else {
705
0
        DEBUGMSGTL(("sslctx_client", "looking for default local id: %s\n", tlsbase->our_identity));
706
0
        id_cert = netsnmp_cert_find(NS_CERT_IDENTITY, NS_CERTKEY_DEFAULT, NULL);
707
0
    }
708
709
0
    if (!id_cert) {
710
0
        msg = "error finding client identity keys";
711
0
        goto err;
712
0
    }
713
714
0
    if (!id_cert->key || !id_cert->key->okey) {
715
0
        msg = "failed to load private key";
716
0
        goto err;
717
0
    }
718
719
0
    DEBUGMSGTL(("sslctx_client", "using public key: %s\n",
720
0
                id_cert->info.filename));
721
0
    DEBUGMSGTL(("sslctx_client", "using private key: %s\n",
722
0
                id_cert->key->info.filename));
723
724
0
    if (SSL_CTX_use_certificate(the_ctx, id_cert->ocert) <= 0) {
725
0
        msg = "failed to set the client certificate to use";
726
0
        goto err;
727
0
    }
728
729
0
    if (SSL_CTX_use_PrivateKey(the_ctx, id_cert->key->okey) <= 0) {
730
0
        msg = "failed to set the client private key to use";
731
0
        goto err;
732
0
    }
733
734
0
    if (!SSL_CTX_check_private_key(the_ctx)) {
735
0
        msg = "client public and private keys incompatible";
736
0
        goto err;
737
0
    }
738
739
0
    while (id_cert->issuer_cert) {
740
0
        id_cert = id_cert->issuer_cert;
741
0
        if (id_cert->ocert)
742
0
        {
743
0
            ocert = X509_dup(id_cert->ocert);
744
0
            DEBUGMSGTL(("sslctx_client", "adding cert-chain certificate %p", ocert));
745
0
            if (!ocert || !SSL_CTX_add_extra_chain_cert(the_ctx, ocert)) {
746
0
                X509_free(ocert);
747
0
                msg = "failed to add intermediate client certificate";
748
0
                goto err;
749
0
            }
750
0
        }
751
0
    }
752
753
0
    if (tlsbase->their_identity)
754
0
        peer_cert = netsnmp_cert_find(NS_CERT_REMOTE_PEER,
755
0
                                      NS_CERTKEY_MULTIPLE,
756
0
                                      tlsbase->their_identity);
757
0
    else
758
0
        peer_cert = netsnmp_cert_find(NS_CERT_REMOTE_PEER, NS_CERTKEY_DEFAULT,
759
0
                                      NULL);
760
0
    if (peer_cert) {
761
0
        DEBUGMSGTL(("sslctx_client", "server's expected public key: %s\n",
762
0
                    peer_cert ? peer_cert->info.filename : "none"));
763
764
        /* Trust the expected certificate */
765
0
        if (netsnmp_cert_trust(the_ctx, peer_cert) != SNMPERR_SUCCESS) {
766
0
            msg = "failed to set verify paths";
767
0
            goto err;
768
0
        }
769
0
    }
770
771
    /* trust a certificate (possibly a CA) specifically passed in */
772
0
    if (tlsbase->trust_cert) {
773
0
        if (!_trust_this_cert(the_ctx, tlsbase->trust_cert)) {
774
0
            SSL_CTX_free(the_ctx);
775
0
            return 0;
776
0
        }
777
0
    }
778
779
0
    return _sslctx_common_setup(the_ctx, tlsbase);
780
781
0
err:
782
0
    snmp_log(LOG_ERR, "%s\n", msg);
783
0
    SSL_CTX_free(the_ctx);
784
0
    return 0;
785
0
}
786
787
SSL_CTX *
788
0
sslctx_server_setup(const SSL_METHOD *method) {
789
0
    netsnmp_cert *id_cert;
790
0
    X509         *ocert;
791
0
    const char   *msg;
792
793
    /***********************************************************************
794
     * Set up the server context
795
     */
796
    /* setting up for ssl */
797
0
    SSL_CTX *the_ctx = SSL_CTX_new(NETSNMP_REMOVE_CONST(SSL_METHOD *, method));
798
0
    if (!the_ctx) {
799
0
        msg = "can't create a new server context";
800
0
        goto err;
801
0
    }
802
0
    MAKE_MEM_DEFINED(the_ctx, 256/*sizeof(*the_ctx)*/);
803
804
0
    id_cert = netsnmp_cert_find(NS_CERT_IDENTITY, NS_CERTKEY_DEFAULT, NULL);
805
0
    if (!id_cert) {
806
0
        msg = "error finding server identity keys";
807
0
        goto err;
808
0
    }
809
810
0
    if (!id_cert->key || !id_cert->key->okey) {
811
0
        msg = "failed to load server private key";
812
0
        goto err;
813
0
    }
814
815
0
    DEBUGMSGTL(("sslctx_server", "using public key: %s\n",
816
0
                id_cert->info.filename));
817
0
    DEBUGMSGTL(("sslctx_server", "using private key: %s\n",
818
0
                id_cert->key->info.filename));
819
820
0
    if (SSL_CTX_use_certificate(the_ctx, id_cert->ocert) <= 0) {
821
0
        msg = "failed to set the server certificate to use";
822
0
        goto err;
823
0
    }
824
825
0
    if (SSL_CTX_use_PrivateKey(the_ctx, id_cert->key->okey) <= 0) {
826
0
        msg = "failed to set the server private key to use";
827
0
        goto err;
828
0
    }
829
830
0
    if (!SSL_CTX_check_private_key(the_ctx)) {
831
0
        msg ="server public and private keys incompatible";
832
0
        goto err;
833
0
    }
834
835
0
    while (id_cert->issuer_cert) {
836
0
        id_cert = id_cert->issuer_cert;
837
0
        if (id_cert->ocert)
838
0
        {
839
0
            ocert = X509_dup(id_cert->ocert);
840
0
            DEBUGMSGTL(("sslctx_server", "adding cert-chain certificate %p", ocert));
841
0
            if (!ocert || !SSL_CTX_add_extra_chain_cert(the_ctx, ocert)) {
842
0
                X509_free(ocert);
843
0
                msg = "failed to add intermediate server certificate";
844
0
                goto err;
845
0
            }
846
0
        }
847
0
    }
848
849
0
    SSL_CTX_set_read_ahead(the_ctx, 1); /* XXX: DTLS only? */
850
851
0
    SSL_CTX_set_verify(the_ctx,
852
0
                       SSL_VERIFY_PEER|
853
0
                       SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
854
0
                       SSL_VERIFY_CLIENT_ONCE,
855
0
                       &verify_callback);
856
857
0
    SSL_CTX_set_options(the_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
858
859
0
    return _sslctx_common_setup(the_ctx, NULL);
860
    
861
0
err:
862
0
    snmp_log(LOG_ERR, "%s\n", msg);
863
0
    SSL_CTX_free(the_ctx);
864
0
    return NULL;
865
0
}
866
867
int
868
0
netsnmp_tlsbase_config(struct netsnmp_transport_s *t, const char *token, const char *value) {
869
0
    _netsnmpTLSBaseData *tlsdata;
870
871
0
    netsnmp_assert_or_return(t != NULL, -1);
872
0
    netsnmp_assert_or_return(t->data != NULL, -1);
873
874
0
    tlsdata = t->data;
875
876
0
    if ((strcmp(token, "localCert") == 0) ||
877
0
        (strcmp(token, "our_identity") == 0)) {
878
0
        SNMP_FREE(tlsdata->our_identity);
879
0
        tlsdata->our_identity = strdup(value);
880
0
        DEBUGMSGT(("tls:config","our identity %s\n", value));
881
0
    }
882
883
0
    if ((strcmp(token, "peerCert") == 0) ||
884
0
        (strcmp(token, "their_identity") == 0)) {
885
0
        SNMP_FREE(tlsdata->their_identity);
886
0
        tlsdata->their_identity = strdup(value);
887
0
        DEBUGMSGT(("tls:config","their identity %s\n", value));
888
0
    }
889
890
0
    if ((strcmp(token, "peerHostname") == 0) ||
891
0
        (strcmp(token, "their_hostname") == 0)) {
892
0
        SNMP_FREE(tlsdata->their_hostname);
893
0
        tlsdata->their_hostname = strdup(value);
894
0
    }
895
896
0
    if ((strcmp(token, "trust_cert") == 0) ||
897
0
        (strcmp(token, "trustCert") == 0)) {
898
0
        SNMP_FREE(tlsdata->trust_cert);
899
0
        tlsdata->trust_cert = strdup(value);
900
0
    }
901
    
902
0
    return SNMPERR_SUCCESS;
903
0
}
904
905
int
906
netsnmp_tlsbase_session_init(struct netsnmp_transport_s *transport,
907
0
                             struct snmp_session *sess) {
908
0
    _netsnmpTLSBaseData *tlsdata = NULL;
909
0
    if (transport && transport->data)
910
0
        tlsdata = (_netsnmpTLSBaseData *)transport->data;
911
912
    /* the default security model here should be TSM; most other
913
       things won't work with TLS because we'll throw out the packet
914
       if it doesn't have a proper tmStateRef (and only TSM generates
915
       this at the moment */
916
0
    if (tlsdata && (tlsdata->flags & NETSNMP_TLSBASE_IS_CLIENT)) {
917
0
        if (sess->securityModel == SNMP_DEFAULT_SECMODEL) {
918
0
            sess->securityModel = SNMP_SEC_MODEL_TSM;
919
0
        } else if (sess->securityModel != SNMP_SEC_MODEL_TSM) {
920
0
            sess->securityModel = SNMP_SEC_MODEL_TSM;
921
0
            snmp_log(LOG_ERR, "A security model other than TSM is being used with (D)TLS; using TSM anyways\n");
922
0
        }
923
924
0
        if (NULL == sess->securityName) {
925
            /* client side doesn't need a real securityName */
926
            /* XXX: call-home issues require them to set one for VACM; but
927
               we don't do callhome yet */
928
0
            sess->securityName = strdup("__BOGUS__");
929
0
            sess->securityNameLen = strlen(sess->securityName);
930
0
        }
931
932
0
        if (sess->version != SNMP_VERSION_3) {
933
0
            sess->version = SNMP_VERSION_3;
934
0
            snmp_log(LOG_ERR, "A SNMP version other than 3 was requested with (D)TLS; using 3 anyways\n");
935
0
        }
936
937
0
        if (sess->securityLevel <= 0) {
938
0
            sess->securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
939
0
        }
940
0
    }
941
0
    return SNMPERR_SUCCESS;
942
0
}
943
944
static int have_done_bootstrap = 0;
945
946
static void verify_info_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
947
                             int idx, long argl, void *argp)
948
0
{
949
0
    free(ptr);
950
0
}
951
952
static int
953
3.42k
tls_bootstrap(int majorid, int minorid, void *serverarg, void *clientarg) {
954
3.42k
    char indexname[] = "_netsnmp_verify_info";
955
956
    /* don't do this more than once */
957
3.42k
    if (have_done_bootstrap)
958
3.42k
        return 0;
959
8
    have_done_bootstrap = 1;
960
961
8
    netsnmp_certs_load();
962
963
8
    openssl_local_index =
964
8
        SSL_get_ex_new_index(0, indexname, NULL, NULL, verify_info_free);
965
966
8
    return 0;
967
3.42k
}
968
969
int
970
0
tls_get_verify_info_index(void) {
971
0
    return openssl_local_index;
972
0
}
973
974
static void _parse_client_cert(const char *tok, char *line)
975
94
{
976
94
    config_pwarn("clientCert is deprecated. Clients should use localCert, servers should use peerCert");
977
94
    if (*line == '"') {
978
51
        char buf[SNMP_MAXBUF];
979
51
        copy_nword(line, buf, sizeof(buf));
980
51
        netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
981
51
                              NETSNMP_DS_LIB_X509_CLIENT_PUB, buf);
982
51
    } else
983
43
        netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
984
43
                              NETSNMP_DS_LIB_X509_CLIENT_PUB, line);
985
94
}
986
987
static void _parse_server_cert(const char *tok, char *line)
988
63
{
989
63
    config_pwarn("serverCert is deprecated. Clients should use peerCert, servers should use localCert.");
990
63
    if (*line == '"') {
991
23
        char buf[SNMP_MAXBUF];
992
23
        copy_nword(line, buf, sizeof(buf));
993
23
        netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
994
23
                              NETSNMP_DS_LIB_X509_SERVER_PUB, buf);
995
23
    } else
996
40
        netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
997
40
                              NETSNMP_DS_LIB_X509_SERVER_PUB, line);
998
63
}
999
1000
void
1001
4.22k
netsnmp_tlsbase_ctor(void) {
1002
1003
    /* bootstrap ssl since we'll need it */
1004
4.22k
    netsnmp_init_openssl();
1005
1006
    /* the private client cert to authenticate with */
1007
4.22k
    netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "extraX509SubDir",
1008
4.22k
                               NETSNMP_DS_LIBRARY_ID,
1009
4.22k
                               NETSNMP_DS_LIB_CERT_EXTRA_SUBDIR);
1010
1011
    /* Do we have a CRL list? */
1012
4.22k
    netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "x509CRLFile",
1013
4.22k
                               NETSNMP_DS_LIBRARY_ID,
1014
4.22k
                               NETSNMP_DS_LIB_X509_CRL_FILE);
1015
1016
    /* What TLS algorithms should be use */
1017
4.22k
    netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "tlsAlgorithms",
1018
4.22k
                               NETSNMP_DS_LIBRARY_ID,
1019
4.22k
                               NETSNMP_DS_LIB_TLS_ALGORITMS);
1020
1021
    /* What TLS version should be used at least */
1022
4.22k
    netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "tlsMinVersion",
1023
4.22k
                               NETSNMP_DS_LIBRARY_ID,
1024
4.22k
                               NETSNMP_DS_LIB_TLS_MIN_VERSION);
1025
1026
    /* What TLS version should be used at max */
1027
4.22k
    netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "tlsMaxVersion",
1028
4.22k
                               NETSNMP_DS_LIBRARY_ID,
1029
4.22k
                               NETSNMP_DS_LIB_TLS_MAX_VERSION);
1030
1031
    /*
1032
     * for the client
1033
     */
1034
1035
    /* the public client cert to authenticate with */
1036
4.22k
    register_config_handler("snmp", "clientCert", _parse_client_cert, NULL,
1037
4.22k
                            NULL);
1038
1039
    /*
1040
     * for the server
1041
     */
1042
1043
    /* The X509 server key to use */
1044
4.22k
    register_config_handler("snmp", "serverCert", _parse_server_cert, NULL,
1045
4.22k
                            NULL);
1046
    /*
1047
     * remove cert config ambiguity: localCert, peerCert
1048
     */
1049
4.22k
    netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "localCert",
1050
4.22k
                               NETSNMP_DS_LIBRARY_ID,
1051
4.22k
                               NETSNMP_DS_LIB_TLS_LOCAL_CERT);
1052
4.22k
    netsnmp_ds_register_config(ASN_OCTET_STR, "snmp", "peerCert",
1053
4.22k
                               NETSNMP_DS_LIBRARY_ID,
1054
4.22k
                               NETSNMP_DS_LIB_TLS_PEER_CERT);
1055
1056
    /*
1057
     * register our boot-strapping needs
1058
     */
1059
4.22k
    snmp_register_callback(SNMP_CALLBACK_LIBRARY,
1060
4.22k
         SNMP_CALLBACK_POST_PREMIB_READ_CONFIG,
1061
4.22k
         tls_bootstrap, NULL);
1062
1063
4.22k
}
1064
1065
_netsnmpTLSBaseData *
1066
0
netsnmp_tlsbase_allocate_tlsdata(netsnmp_transport *t, int isserver) {
1067
1068
0
    _netsnmpTLSBaseData *tlsdata;
1069
1070
0
    if (NULL == t)
1071
0
        return NULL;
1072
1073
    /* allocate our TLS specific data */
1074
0
    tlsdata = SNMP_MALLOC_TYPEDEF(_netsnmpTLSBaseData);
1075
0
    if (NULL == tlsdata) {
1076
0
        return NULL;
1077
0
    }
1078
1079
0
    if (!isserver)
1080
0
        tlsdata->flags |= NETSNMP_TLSBASE_IS_CLIENT;
1081
1082
0
    return tlsdata;
1083
0
}
1084
1085
0
void netsnmp_tlsbase_free_tlsdata(_netsnmpTLSBaseData *tlsbase) {
1086
0
    if (!tlsbase)
1087
0
        return;
1088
1089
0
    DEBUGMSGTL(("tlsbase","Freeing TLS Base data for a session\n"));
1090
1091
0
    if (tlsbase->ssl)
1092
0
        SSL_free(tlsbase->ssl);
1093
1094
0
    if (tlsbase->ssl_context)
1095
0
        SSL_CTX_free(tlsbase->ssl_context);
1096
0
    if (tlsbase->accept_bio)
1097
0
        BIO_free(tlsbase->accept_bio);
1098
1099
    /* free the config data */
1100
0
    SNMP_FREE(tlsbase->securityName);
1101
0
    SNMP_FREE(tlsbase->addr_string);
1102
0
    SNMP_FREE(tlsbase->our_identity);
1103
0
    SNMP_FREE(tlsbase->their_identity);
1104
0
    SNMP_FREE(tlsbase->their_fingerprint);
1105
0
    SNMP_FREE(tlsbase->their_hostname);
1106
0
    SNMP_FREE(tlsbase->trust_cert);
1107
0
    SNMP_FREE(tlsbase->addr);
1108
0
    SNMP_FREE(tlsbase->write_cache);
1109
1110
    /* free the base itself */
1111
0
    SNMP_FREE(tlsbase);
1112
0
}
1113
1114
int netsnmp_tlsbase_wrapup_recv(netsnmp_tmStateReference *tmStateRef,
1115
                                _netsnmpTLSBaseData *tlsdata,
1116
0
                                void **opaque, int *olength) {
1117
0
    int no_auth, no_priv;
1118
1119
0
    if (NULL == tlsdata)
1120
0
        return SNMPERR_GENERR;
1121
1122
    /* RFC5953 Section 5.1.2 step 2: tmSecurityLevel */
1123
    /*
1124
     * Don't accept null authentication. Null encryption ok.
1125
     *
1126
     * XXX: this should actually check for a configured list of encryption
1127
     *      algorithms to map to NOPRIV, but for the moment we'll
1128
     *      accept any encryption alogrithms that openssl is using.
1129
     */
1130
0
    netsnmp_openssl_null_checks(tlsdata->ssl, &no_auth, &no_priv);
1131
0
    if (no_auth == 1) { /* null/unknown authentication */
1132
        /* xxx-rks: snmp_increment_statistic(STAT_???); */
1133
0
        snmp_log(LOG_ERR, "tls connection with NULL authentication\n");
1134
0
        SNMP_FREE(tmStateRef);
1135
0
        return SNMPERR_GENERR;
1136
0
    }
1137
0
    else if (no_priv == 1) /* null/unknown encryption */
1138
0
        tmStateRef->transportSecurityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
1139
0
    else
1140
0
        tmStateRef->transportSecurityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
1141
0
    DEBUGMSGTL(("tls:secLevel", "SecLevel %d\n",
1142
0
                tmStateRef->transportSecurityLevel));
1143
1144
    /* use x509 cert to do lookup to secname if DNE in cachep yet */
1145
1146
    /* RFC5953: section 5.3.2, paragraph 2:
1147
       The (D)TLS server identifies the authenticated identity from the
1148
       (D)TLS client's principal certificate using configuration information
1149
       from the snmpTlstmCertToTSNTable mapping table.  The (D)TLS server
1150
       MUST request and expect a certificate from the client and MUST NOT
1151
       accept SNMP messages over the (D)TLS connection until the client has
1152
       sent a certificate and it has been authenticated.  The resulting
1153
       derived tmSecurityName is recorded in the tmStateReference cache as
1154
       tmSecurityName.  The details of the lookup process are fully
1155
       described in the DESCRIPTION clause of the snmpTlstmCertToTSNTable
1156
       MIB object.  If any verification fails in any way (for example
1157
       because of failures in cryptographic verification or because of the
1158
       lack of an appropriate row in the snmpTlstmCertToTSNTable) then the
1159
       session establishment MUST fail, and the
1160
       snmpTlstmSessionInvalidClientCertificates object is incremented.  If
1161
       the session can not be opened for any reason at all, including
1162
       cryptographic verification failures, then the
1163
       snmpTlstmSessionOpenErrors counter is incremented and processing
1164
       stops.
1165
    */
1166
1167
0
    if (!tlsdata->securityName) {
1168
0
        netsnmp_tlsbase_extract_security_name(tlsdata->ssl, tlsdata);
1169
0
        if (NULL != tlsdata->securityName) {
1170
0
            DEBUGMSGTL(("tls", "set SecName to: %s\n", tlsdata->securityName));
1171
0
        } else {
1172
0
      snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONINVALIDCLIENTCERTIFICATES);
1173
0
      snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONOPENERRORS);
1174
0
            SNMP_FREE(tmStateRef);
1175
0
            return SNMPERR_GENERR;
1176
0
        }
1177
0
    }
1178
1179
    /* RFC5953 Section 5.1.2 step 2: tmSecurityName */
1180
    /* XXX: detect and throw out overflow secname sizes rather
1181
       than truncating. */
1182
0
    strlcpy(tmStateRef->securityName, tlsdata->securityName,
1183
0
            sizeof(tmStateRef->securityName));
1184
0
    tmStateRef->securityNameLen = strlen(tmStateRef->securityName);
1185
1186
    /* RFC5953 Section 5.1.2 step 2: tmSessionID */
1187
    /* use our TLSData pointer as the session ID */
1188
0
    memcpy(tmStateRef->sessionID, &tlsdata, sizeof(netsnmp_tmStateReference *));
1189
1190
    /* save the tmStateRef in our special pointer */
1191
0
    *opaque = tmStateRef;
1192
0
    *olength = sizeof(netsnmp_tmStateReference);
1193
1194
0
    return SNMPERR_SUCCESS;
1195
0
}
1196
1197
netsnmp_feature_child_of(_x509_get_error, netsnmp_unused);
1198
#ifndef NETSNMP_FEATURE_REMOVE__X509_GET_ERROR
1199
0
const char * _x509_get_error(int x509failvalue, const char *location) {
1200
0
    static const char *reason = NULL;
1201
    
1202
    /* XXX: use this instead: X509_verify_cert_error_string(err) */
1203
1204
0
    switch (x509failvalue) {
1205
0
    case X509_V_OK:
1206
0
        reason = "X509_V_OK";
1207
0
        break;
1208
0
    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
1209
0
        reason = "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT";
1210
0
        break;
1211
0
    case X509_V_ERR_UNABLE_TO_GET_CRL:
1212
0
        reason = "X509_V_ERR_UNABLE_TO_GET_CRL";
1213
0
        break;
1214
0
    case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
1215
0
        reason = "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE";
1216
0
        break;
1217
0
    case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
1218
0
        reason = "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE";
1219
0
        break;
1220
0
    case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
1221
0
        reason = "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY";
1222
0
        break;
1223
0
    case X509_V_ERR_CERT_SIGNATURE_FAILURE:
1224
0
        reason = "X509_V_ERR_CERT_SIGNATURE_FAILURE";
1225
0
        break;
1226
0
    case X509_V_ERR_CRL_SIGNATURE_FAILURE:
1227
0
        reason = "X509_V_ERR_CRL_SIGNATURE_FAILURE";
1228
0
        break;
1229
0
    case X509_V_ERR_CERT_NOT_YET_VALID:
1230
0
        reason = "X509_V_ERR_CERT_NOT_YET_VALID";
1231
0
        break;
1232
0
    case X509_V_ERR_CERT_HAS_EXPIRED:
1233
0
        reason = "X509_V_ERR_CERT_HAS_EXPIRED";
1234
0
        break;
1235
0
    case X509_V_ERR_CRL_NOT_YET_VALID:
1236
0
        reason = "X509_V_ERR_CRL_NOT_YET_VALID";
1237
0
        break;
1238
0
    case X509_V_ERR_CRL_HAS_EXPIRED:
1239
0
        reason = "X509_V_ERR_CRL_HAS_EXPIRED";
1240
0
        break;
1241
0
    case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
1242
0
        reason = "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD";
1243
0
        break;
1244
0
    case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
1245
0
        reason = "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD";
1246
0
        break;
1247
0
    case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
1248
0
        reason = "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD";
1249
0
        break;
1250
0
    case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
1251
0
        reason = "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD";
1252
0
        break;
1253
0
    case X509_V_ERR_OUT_OF_MEM:
1254
0
        reason = "X509_V_ERR_OUT_OF_MEM";
1255
0
        break;
1256
0
    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
1257
0
        reason = "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT";
1258
0
        break;
1259
0
    case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
1260
0
        reason = "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN";
1261
0
        break;
1262
0
    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
1263
0
        reason = "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY";
1264
0
        break;
1265
0
    case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
1266
0
        reason = "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE";
1267
0
        break;
1268
0
    case X509_V_ERR_CERT_CHAIN_TOO_LONG:
1269
0
        reason = "X509_V_ERR_CERT_CHAIN_TOO_LONG";
1270
0
        break;
1271
0
    case X509_V_ERR_CERT_REVOKED:
1272
0
        reason = "X509_V_ERR_CERT_REVOKED";
1273
0
        break;
1274
0
    case X509_V_ERR_INVALID_CA:
1275
0
        reason = "X509_V_ERR_INVALID_CA";
1276
0
        break;
1277
0
    case X509_V_ERR_PATH_LENGTH_EXCEEDED:
1278
0
        reason = "X509_V_ERR_PATH_LENGTH_EXCEEDED";
1279
0
        break;
1280
0
    case X509_V_ERR_INVALID_PURPOSE:
1281
0
        reason = "X509_V_ERR_INVALID_PURPOSE";
1282
0
        break;
1283
0
    case X509_V_ERR_CERT_UNTRUSTED:
1284
0
        reason = "X509_V_ERR_CERT_UNTRUSTED";
1285
0
        break;
1286
0
    case X509_V_ERR_CERT_REJECTED:
1287
0
        reason = "X509_V_ERR_CERT_REJECTED";
1288
0
        break;
1289
0
    case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
1290
0
        reason = "X509_V_ERR_SUBJECT_ISSUER_MISMATCH";
1291
0
        break;
1292
0
    case X509_V_ERR_AKID_SKID_MISMATCH:
1293
0
        reason = "X509_V_ERR_AKID_SKID_MISMATCH";
1294
0
        break;
1295
0
    case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
1296
0
        reason = "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH";
1297
0
        break;
1298
0
    case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
1299
0
        reason = "X509_V_ERR_KEYUSAGE_NO_CERTSIGN";
1300
0
        break;
1301
0
    case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
1302
0
        reason = "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER";
1303
0
        break;
1304
0
    case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
1305
0
        reason = "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION";
1306
0
        break;
1307
0
    case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN:
1308
0
        reason = "X509_V_ERR_KEYUSAGE_NO_CRL_SIGN";
1309
0
        break;
1310
0
    case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
1311
0
        reason = "X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION";
1312
0
        break;
1313
0
    case X509_V_ERR_INVALID_NON_CA:
1314
0
        reason = "X509_V_ERR_INVALID_NON_CA";
1315
0
        break;
1316
0
    case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
1317
0
        reason = "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED";
1318
0
        break;
1319
0
    case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE:
1320
0
        reason = "X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE";
1321
0
        break;
1322
0
    case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
1323
0
        reason = "X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED";
1324
0
        break;
1325
0
#ifdef X509_V_ERR_INVALID_EXTENSION /* not avail on darwin */
1326
0
    case X509_V_ERR_INVALID_EXTENSION:
1327
0
        reason = "X509_V_ERR_INVALID_EXTENSION";
1328
0
        break;
1329
0
#endif
1330
0
#ifdef X509_V_ERR_INVALID_POLICY_EXTENSION /* not avail on darwin */
1331
0
    case X509_V_ERR_INVALID_POLICY_EXTENSION:
1332
0
        reason = "X509_V_ERR_INVALID_POLICY_EXTENSION";
1333
0
        break;
1334
0
#endif
1335
0
#ifdef X509_V_ERR_NO_EXPLICIT_POLICY /* not avail on darwin */
1336
0
    case X509_V_ERR_NO_EXPLICIT_POLICY:
1337
0
        reason = "X509_V_ERR_NO_EXPLICIT_POLICY";
1338
0
        break;
1339
0
#endif
1340
0
#ifdef X509_V_ERR_UNNESTED_RESOURCE /* not avail on darwin */
1341
0
    case X509_V_ERR_UNNESTED_RESOURCE:
1342
0
        reason = "X509_V_ERR_UNNESTED_RESOURCE";
1343
0
        break;
1344
0
#endif
1345
0
    case X509_V_ERR_APPLICATION_VERIFICATION:
1346
0
        reason = "X509_V_ERR_APPLICATION_VERIFICATION";
1347
0
        break;
1348
0
    default:
1349
0
        reason = "unknown failure code";
1350
0
    }
1351
1352
0
    return reason;
1353
0
}
1354
#endif /* NETSNMP_FEATURE_REMOVE__X509_GET_ERROR */
1355
1356
0
void _openssl_log_error(int rc, SSL *con, const char *location) {
1357
0
    const char     *reason, *file, *func, *data;
1358
0
    unsigned long   numerical_reason;
1359
0
    int             flags, line;
1360
1361
0
    snmp_log(LOG_ERR, "---- OpenSSL Related Errors: ----\n");
1362
1363
    /* SSL specific errors */
1364
0
    if (con) {
1365
1366
0
        int sslnum = SSL_get_error(con, rc);
1367
1368
0
        switch(sslnum) {
1369
0
        case SSL_ERROR_NONE:
1370
0
            reason = "SSL_ERROR_NONE";
1371
0
            break;
1372
1373
0
        case SSL_ERROR_SSL:
1374
0
            reason = "SSL_ERROR_SSL";
1375
0
            break;
1376
1377
0
        case SSL_ERROR_WANT_READ:
1378
0
            reason = "SSL_ERROR_WANT_READ";
1379
0
            break;
1380
1381
0
        case SSL_ERROR_WANT_WRITE:
1382
0
            reason = "SSL_ERROR_WANT_WRITE";
1383
0
            break;
1384
1385
0
        case SSL_ERROR_WANT_X509_LOOKUP:
1386
0
            reason = "SSL_ERROR_WANT_X509_LOOKUP";
1387
0
            break;
1388
1389
0
        case SSL_ERROR_SYSCALL:
1390
0
            reason = "SSL_ERROR_SYSCALL";
1391
0
            snmp_log(LOG_ERR, "TLS error: %s: rc=%d, sslerror = %d (%s): system_error=%d (%s)\n",
1392
0
                     location, rc, sslnum, reason, errno, strerror(errno));
1393
0
            snmp_log(LOG_ERR, "TLS Error: %s\n",
1394
0
                     ERR_reason_error_string(ERR_get_error()));
1395
0
            ERR_clear_error();
1396
0
            return;
1397
1398
0
        case SSL_ERROR_ZERO_RETURN:
1399
0
            reason = "SSL_ERROR_ZERO_RETURN";
1400
0
            break;
1401
1402
0
        case SSL_ERROR_WANT_CONNECT:
1403
0
            reason = "SSL_ERROR_WANT_CONNECT";
1404
0
            break;
1405
1406
0
        case SSL_ERROR_WANT_ACCEPT:
1407
0
            reason = "SSL_ERROR_WANT_ACCEPT";
1408
0
            break;
1409
            
1410
0
        default:
1411
0
            reason = "unknown";
1412
0
        }
1413
1414
0
        snmp_log(LOG_ERR, " TLS error: %s: rc=%d, sslerror = %d (%s)\n",
1415
0
                 location, rc, sslnum, reason);
1416
1417
0
        snmp_log(LOG_ERR, " TLS Error: %s\n",
1418
0
                 ERR_reason_error_string(ERR_get_error()));
1419
1420
0
    }
1421
1422
    /* other errors */
1423
0
    while ((numerical_reason =
1424
0
            ERR_get_error_all(&file, &line, &func, &data, &flags)) != 0) {
1425
0
        snmp_log(LOG_ERR, "%s (file %s, func %s, line %d)\n",
1426
0
                 ERR_error_string(numerical_reason, NULL), file, func, line);
1427
1428
        /* if we have a text translation: */
1429
0
        if (data && (flags & ERR_TXT_STRING)) {
1430
0
            snmp_log(LOG_ERR, "  Textual Error: %s\n", data);
1431
0
        }
1432
0
    }
1433
    /* clear openssl error ring buffer */
1434
0
    ERR_clear_error();
1435
1436
    snmp_log(LOG_ERR, "---- End of OpenSSL Errors ----\n");
1437
0
}