net-snmp 5.7
|
00001 /* 00002 * snmp_openssl.c 00003 */ 00004 00005 #include <net-snmp/net-snmp-config.h> 00006 00007 #include <net-snmp/net-snmp-includes.h> 00008 00009 #include <net-snmp/net-snmp-features.h> 00010 00011 #if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_LIBSSL) && !defined(NETSNMP_FEATURE_REMOVE_CERT_UTIL) 00012 00013 netsnmp_feature_require(container_free_all) 00014 00015 netsnmp_feature_child_of(openssl_cert_get_subjectAltNames, netsnmp_unused) 00016 netsnmp_feature_child_of(openssl_ht2nid, netsnmp_unused) 00017 netsnmp_feature_child_of(openssl_err_log, netsnmp_unused) 00018 netsnmp_feature_child_of(cert_dump_names, netsnmp_unused) 00019 00020 #include <ctype.h> 00021 00022 #include <openssl/evp.h> 00023 #include <openssl/ssl.h> 00024 #include <openssl/x509.h> 00025 #include <openssl/x509v3.h> 00026 #include <openssl/err.h> 00027 #include <openssl/objects.h> 00028 00029 #include <net-snmp/library/snmp_debug.h> 00030 #include <net-snmp/library/cert_util.h> 00031 #include <net-snmp/library/snmp_openssl.h> 00032 00033 static u_char have_started_already = 0; 00034 00035 /* 00036 * This code merely does openssl initialization so that multilpe 00037 * modules are safe to call netsnmp_init_openssl() for bootstrapping 00038 * without worrying about other callers that may have already done so. 00039 */ 00040 void netsnmp_init_openssl(void) { 00041 00042 /* avoid duplicate calls */ 00043 if (have_started_already) 00044 return; 00045 have_started_already = 1; 00046 00047 DEBUGMSGTL(("snmp_openssl", "initializing\n")); 00048 00049 /* Initializing OpenSSL */ 00050 SSL_library_init(); 00051 SSL_load_error_strings(); 00052 ERR_load_BIO_strings(); 00053 OpenSSL_add_all_algorithms(); 00054 } 00055 00061 static char * 00062 _cert_get_name(X509 *ocert, int which, char **buf, int *len, int flags) 00063 { 00064 X509_NAME *osubj_name; 00065 int space; 00066 char *buf_ptr; 00067 00068 if ((NULL == ocert) || ((buf && !len) || (len && !buf))) 00069 return NULL; 00070 00071 osubj_name = X509_get_subject_name(ocert); 00072 if (NULL == osubj_name) { 00073 DEBUGMSGT(("openssl:cert:name", "no subject name!\n")); 00074 return NULL; 00075 } 00076 00078 space = X509_NAME_get_text_by_NID(osubj_name, which, NULL, 0); 00079 if (-1 == space) 00080 return NULL; 00081 ++space; /* for NUL */ 00082 if (buf && *buf) { 00083 if (*len < space) 00084 return NULL; 00085 buf_ptr = *buf; 00086 } 00087 else { 00088 buf_ptr = calloc(1,space); 00089 if (!buf_ptr) 00090 return NULL; 00091 } 00092 space = X509_NAME_get_text_by_NID(osubj_name, which, buf_ptr, space); 00093 if (len) 00094 *len = space; 00095 00096 return buf_ptr; 00097 } 00098 00101 char * 00102 netsnmp_openssl_cert_get_subjectName(X509 *ocert, char **buf, int *len) 00103 { 00104 X509_NAME *osubj_name; 00105 int space; 00106 char *buf_ptr; 00107 00108 if ((NULL == ocert) || ((buf && !len) || (len && !buf))) 00109 return NULL; 00110 00111 osubj_name = X509_get_subject_name(ocert); 00112 if (NULL == osubj_name) { 00113 DEBUGMSGT(("openssl:cert:name", "no subject name!\n")); 00114 return NULL; 00115 } 00116 00117 if (buf) { 00118 buf_ptr = *buf; 00119 space = *len; 00120 } 00121 else { 00122 buf_ptr = NULL; 00123 space = 0; 00124 } 00125 buf_ptr = X509_NAME_oneline(osubj_name, buf_ptr, space); 00126 if (len) 00127 *len = strlen(buf_ptr); 00128 00129 return buf_ptr; 00130 } 00131 00137 char * 00138 netsnmp_openssl_cert_get_commonName(X509 *ocert, char **buf, int *len) 00139 { 00140 return _cert_get_name(ocert, NID_commonName, buf, len, 0); 00141 } 00142 00143 #ifndef NETSNMP_FEATURE_REMOVE_CERT_DUMP_NAMES 00144 00146 void 00147 netsnmp_openssl_cert_dump_names(X509 *ocert) 00148 { 00149 int i, onid; 00150 X509_NAME_ENTRY *oname_entry; 00151 X509_NAME *osubj_name; 00152 const char *prefix_short, *prefix_long; 00153 00154 if (NULL == ocert) 00155 return; 00156 00157 osubj_name = X509_get_subject_name(ocert); 00158 if (NULL == osubj_name) { 00159 DEBUGMSGT(("9:cert:dump:names", "no subject name!\n")); 00160 return; 00161 } 00162 00163 for (i = 0; i < X509_NAME_entry_count(osubj_name); i++) { 00164 oname_entry = X509_NAME_get_entry(osubj_name, i); 00165 netsnmp_assert(NULL != oname_entry); 00166 00167 if (oname_entry->value->type != V_ASN1_PRINTABLESTRING) 00168 continue; 00169 00171 onid = OBJ_obj2nid(oname_entry->object); 00172 if (onid == NID_undef) { 00173 prefix_long = prefix_short = "UNKNOWN"; 00174 } 00175 else { 00176 prefix_long = OBJ_nid2ln(onid); 00177 prefix_short = OBJ_nid2sn(onid); 00178 } 00179 00180 DEBUGMSGT(("9:cert:dump:names", 00181 "[%02d] NID type %d, ASN type %d\n", i, onid, 00182 oname_entry->value->type)); 00183 DEBUGMSGT(("9:cert:dump:names", "%s/%s: '%s'\n", prefix_long, 00184 prefix_short, ASN1_STRING_data(oname_entry->value))); 00185 } 00186 } 00187 #endif /* NETSNMP_FEATURE_REMOVE_CERT_DUMP_NAMES */ 00188 00189 static char * 00190 _cert_get_extension(X509_EXTENSION *oext, char **buf, int *len, int flags) 00191 { 00192 int space; 00193 char *buf_ptr = NULL; 00194 u_char *data; 00195 BIO *bio; 00196 00197 if ((NULL == oext) || ((buf && !len) || (len && !buf))) 00198 return NULL; 00199 00200 bio = BIO_new(BIO_s_mem()); 00201 if (NULL == bio) { 00202 snmp_log(LOG_ERR, "could not get bio for extension\n"); 00203 return NULL; 00204 } 00205 if (X509V3_EXT_print(bio, oext, 0, 0) != 1) { 00206 snmp_log(LOG_ERR, "could not print extension!\n"); 00207 BIO_vfree(bio); 00208 return NULL; 00209 } 00210 00211 space = BIO_get_mem_data(bio, &data); 00212 if (buf && *buf) { 00213 if (*len < space) 00214 buf_ptr = NULL; 00215 else 00216 buf_ptr = *buf; 00217 } 00218 else 00219 buf_ptr = calloc(1,space + 1); 00220 00221 if (!buf_ptr) { 00222 snmp_log(LOG_ERR, 00223 "not enough space or error in allocation for extenstion\n"); 00224 BIO_vfree(bio); 00225 return NULL; 00226 } 00227 memcpy(buf_ptr, data, space); 00228 buf_ptr[space] = 0; 00229 if (len) 00230 *len = space; 00231 00232 BIO_vfree(bio); 00233 00234 return buf_ptr; 00235 } 00236 00242 X509_EXTENSION * 00243 _cert_get_extension_at(X509 *ocert, int pos, char **buf, int *len, int flags) 00244 { 00245 X509_EXTENSION *oext; 00246 00247 if ((NULL == ocert) || ((buf && !len) || (len && !buf))) 00248 return NULL; 00249 00250 oext = X509_get_ext(ocert,pos); 00251 if (NULL == oext) { 00252 snmp_log(LOG_ERR, "extension number %d not found!\n", pos); 00253 netsnmp_openssl_cert_dump_extensions(ocert); 00254 return NULL; 00255 } 00256 00257 return oext; 00258 } 00259 00265 static char * 00266 _cert_get_extension_str_at(X509 *ocert, int pos, char **buf, int *len, 00267 int flags) 00268 { 00269 X509_EXTENSION *oext; 00270 00271 if ((NULL == ocert) || ((buf && !len) || (len && !buf))) 00272 return NULL; 00273 00274 oext = X509_get_ext(ocert,pos); 00275 if (NULL == oext) { 00276 snmp_log(LOG_ERR, "extension number %d not found!\n", pos); 00277 netsnmp_openssl_cert_dump_extensions(ocert); 00278 return NULL; 00279 } 00280 00281 return _cert_get_extension(oext, buf, len, flags); 00282 } 00283 00289 X509_EXTENSION * 00290 _cert_get_extension_id(X509 *ocert, int which, char **buf, int *len, int flags) 00291 { 00292 int pos; 00293 00294 if ((NULL == ocert) || ((buf && !len) || (len && !buf))) 00295 return NULL; 00296 00297 pos = X509_get_ext_by_NID(ocert,which,-1); 00298 if (pos < 0) { 00299 DEBUGMSGT(("openssl:cert:name", "no extension %d\n", which)); 00300 return NULL; 00301 } 00302 00303 return _cert_get_extension_at(ocert, pos, buf, len, flags); 00304 } 00305 00311 static char * 00312 _cert_get_extension_id_str(X509 *ocert, int which, char **buf, int *len, 00313 int flags) 00314 { 00315 int pos; 00316 00317 if ((NULL == ocert) || ((buf && !len) || (len && !buf))) 00318 return NULL; 00319 00320 pos = X509_get_ext_by_NID(ocert,which,-1); 00321 if (pos < 0) { 00322 DEBUGMSGT(("openssl:cert:name", "no extension %d\n", which)); 00323 return NULL; 00324 } 00325 00326 return _cert_get_extension_str_at(ocert, pos, buf, len, flags); 00327 } 00328 00329 static char * 00330 _extract_oname(const GENERAL_NAME *oname) 00331 { 00332 char ipbuf[60], *buf = NULL, *rtn = NULL; 00333 00334 if (NULL == oname) 00335 return NULL; 00336 00337 switch ( oname->type ) { 00338 case GEN_EMAIL: 00339 case GEN_DNS: 00340 /*case GEN_URI:*/ 00341 ASN1_STRING_to_UTF8((unsigned char**)&buf, oname->d.ia5); 00342 if (buf) 00343 rtn = strdup(buf); 00344 break; 00345 00346 case GEN_IPADD: 00347 if (oname->d.iPAddress->length == 4) { 00348 sprintf(ipbuf, "%d.%d.%d.%d", oname->d.iPAddress->data[0], 00349 oname->d.iPAddress->data[1], 00350 oname->d.iPAddress->data[2], 00351 oname->d.iPAddress->data[3]); 00352 rtn = strdup(ipbuf); 00353 } 00354 else if ((oname->d.iPAddress->length == 16) || 00355 (oname->d.iPAddress->length == 20)) { 00356 char *pos = ipbuf; 00357 int j; 00358 for(j = 0; j < oname->d.iPAddress->length; ++j) { 00359 *pos++ = VAL2HEX(oname->d.iPAddress->data[j]); 00360 *pos++ = ':'; 00361 } 00362 *pos = '\0'; 00363 rtn = strdup(ipbuf); 00364 } 00365 else 00366 NETSNMP_LOGONCE((LOG_WARNING, "unexpected ip addr length %d\n", 00367 oname->d.iPAddress->length)); 00368 00369 break; 00370 default: 00371 DEBUGMSGT(("openssl:cert:san", "unknown/unsupported type %d\n", 00372 oname->type)); 00373 break; 00374 } 00375 DEBUGMSGT(("9:openssl:cert:san", "san=%s\n", buf)); 00376 if (buf) 00377 OPENSSL_free(buf); 00378 00379 return rtn; 00380 } 00381 00382 #ifndef NETSNMP_FEATURE_REMOVE_OPENSSL_CERT_GET_SUBJECTALTNAMES 00383 00388 char * 00389 netsnmp_openssl_cert_get_subjectAltNames(X509 *ocert, char **buf, int *len) 00390 { 00391 return _cert_get_extension_id_str(ocert, NID_subject_alt_name, buf, len, 0); 00392 } 00393 #endif /* NETSNMP_FEATURE_REMOVE_OPENSSL_CERT_GET_SUBJECTALTNAMES */ 00394 00395 void 00396 netsnmp_openssl_cert_dump_extensions(X509 *ocert) 00397 { 00398 X509_EXTENSION *extension; 00399 const char *extension_name; 00400 char buf[SNMP_MAXBUF_SMALL], *buf_ptr = buf, *str, *lf; 00401 int i, num_extensions, buf_len, nid; 00402 00403 if (NULL == ocert) 00404 return; 00405 00406 DEBUGIF("9:cert:dump") 00407 ; 00408 else 00409 return; /* bail if debug not enabled */ 00410 00411 num_extensions = X509_get_ext_count(ocert); 00412 if (0 == num_extensions) 00413 DEBUGMSGT(("9:cert:dump", " 0 extensions\n")); 00414 for(i = 0; i < num_extensions; i++) { 00415 extension = X509_get_ext(ocert, i); 00416 nid = OBJ_obj2nid(X509_EXTENSION_get_object(extension)); 00417 extension_name = OBJ_nid2sn(nid); 00418 buf_len = sizeof(buf); 00419 str = _cert_get_extension_str_at(ocert, i, &buf_ptr, &buf_len, 0); 00420 lf = strchr(str, '\n'); /* look for multiline strings */ 00421 if (NULL != lf) 00422 *lf = '\0'; /* only log first line of multiline here */ 00423 DEBUGMSGT(("9:cert:dump", " %2d: %s = %s\n", i, 00424 extension_name, str)); 00425 while(lf) { /* log remaining parts of multiline string */ 00426 str = ++lf; 00427 if (*str == '\0') 00428 break; 00429 lf = strchr(str, '\n'); 00430 if (NULL == lf) 00431 break; 00432 *lf = '\0'; 00433 DEBUGMSGT(("9:cert:dump", " %s\n", str)); 00434 } 00435 } 00436 } 00437 00438 static int _htmap[NS_HASH_MAX + 1] = { 00439 0, NID_md5WithRSAEncryption, NID_sha1WithRSAEncryption, 00440 NID_sha224WithRSAEncryption, NID_sha256WithRSAEncryption, 00441 NID_sha384WithRSAEncryption, NID_sha512WithRSAEncryption }; 00442 00443 int 00444 _nid2ht(int nid) 00445 { 00446 int i; 00447 for (i=1; i<= NS_HASH_MAX; ++i) { 00448 if (nid == _htmap[i]) 00449 return i; 00450 } 00451 return 0; 00452 } 00453 00454 #ifndef NETSNMP_FEATURE_REMOVE_OPENSSL_HT2NID 00455 int 00456 _ht2nid(int ht) 00457 { 00458 if ((ht < 0) || (ht > NS_HASH_MAX)) 00459 return 0; 00460 return _htmap[ht]; 00461 } 00462 #endif /* NETSNMP_FEATURE_REMOVE_OPENSSL_HT2NID */ 00463 00467 int 00468 netsnmp_openssl_cert_get_hash_type(X509 *ocert) 00469 { 00470 if (NULL == ocert) 00471 return 0; 00472 00473 return _nid2ht(OBJ_obj2nid(ocert->sig_alg->algorithm)); 00474 } 00475 00479 char * 00480 netsnmp_openssl_cert_get_fingerprint(X509 *ocert, int alg) 00481 { 00482 u_char fingerprint[EVP_MAX_MD_SIZE]; 00483 u_int fingerprint_len, nid; 00484 const EVP_MD *digest; 00485 char *result = NULL; 00486 00487 if (NULL == ocert) 00488 return NULL; 00489 00490 nid = OBJ_obj2nid(ocert->sig_alg->algorithm); 00491 DEBUGMSGT(("9:openssl:fingerprint", "alg %d, cert nid %d (%d)\n", alg, nid, 00492 _nid2ht(nid))); 00493 00494 if ((-1 == alg) && nid) 00495 alg = _nid2ht(nid); 00496 00497 switch (alg) { 00498 case NS_HASH_MD5: 00499 snmp_log(LOG_ERR, "hash type md5 not yet supported\n"); 00500 return NULL; 00501 break; 00502 00503 case NS_HASH_NONE: 00504 snmp_log(LOG_ERR, "hash type none not supported. using SHA1\n"); 00507 case NS_HASH_SHA1: 00508 digest = EVP_sha1(); 00509 break; 00510 00511 #ifdef HAVE_EVP_SHA224 00512 case NS_HASH_SHA224: 00513 digest = EVP_sha224(); 00514 break; 00515 00516 case NS_HASH_SHA256: 00517 digest = EVP_sha256(); 00518 break; 00519 00520 #endif 00521 #ifdef HAVE_EVP_SHA384 00522 case NS_HASH_SHA384: 00523 digest = EVP_sha384(); 00524 break; 00525 00526 case NS_HASH_SHA512: 00527 digest = EVP_sha512(); 00528 break; 00529 #endif 00530 00531 default: 00532 snmp_log(LOG_ERR, "unknown hash algorithm %d\n", alg); 00533 return NULL; 00534 } 00535 00536 if (_nid2ht(nid) != alg) { 00537 DEBUGMSGT(("openssl:fingerprint", 00538 "WARNING: alg %d does not match cert alg %d\n", 00539 alg, _nid2ht(nid))); 00540 } 00541 if (X509_digest(ocert,digest,fingerprint,&fingerprint_len)) { 00542 binary_to_hex(fingerprint, fingerprint_len, &result); 00543 if (NULL == result) 00544 snmp_log(LOG_ERR, "failed to hexify fingerprint\n"); 00545 else 00546 DEBUGMSGT(("9:openssl:fingerprint", "fingerprint %s\n", result)); 00547 } 00548 else 00549 snmp_log(LOG_ERR,"failed to compute fingerprint\n"); 00550 00551 return result; 00552 } 00553 00558 netsnmp_container * 00559 netsnmp_openssl_get_cert_chain(SSL *ssl) 00560 { 00561 X509 *ocert, *ocert_tmp; 00562 STACK_OF(X509) *ochain; 00563 char *fingerprint; 00564 netsnmp_container *chain_map; 00565 netsnmp_cert_map *cert_map; 00566 int i; 00567 00568 netsnmp_assert_or_return(ssl != NULL, NULL); 00569 00570 if (NULL == (ocert = SSL_get_peer_certificate(ssl))) { 00572 snmp_log(LOG_ERR, "SSL peer has no certificate\n"); 00573 return NULL; 00574 } 00575 DEBUGIF("9:cert:dump") { 00576 netsnmp_openssl_cert_dump_extensions(ocert); 00577 } 00578 00579 /* 00580 * get fingerprint and save it 00581 */ 00582 fingerprint = netsnmp_openssl_cert_get_fingerprint(ocert, -1); 00583 if (NULL == fingerprint) 00584 return NULL; 00585 00586 /* 00587 * allocate cert map. Don't pass in fingerprint, since it would strdup 00588 * it and we've already got a copy. 00589 */ 00590 cert_map = netsnmp_cert_map_alloc(NULL, ocert); 00591 if (NULL == cert_map) { 00592 free(fingerprint); 00593 return NULL; 00594 } 00595 cert_map->fingerprint = fingerprint; 00596 cert_map->hashType = netsnmp_openssl_cert_get_hash_type(ocert); 00597 00598 chain_map = netsnmp_cert_map_container_create(0); /* no fp subcontainer */ 00599 if (NULL == chain_map) { 00600 netsnmp_cert_map_free(cert_map); 00601 return NULL; 00602 } 00603 00604 CONTAINER_INSERT(chain_map, cert_map); 00605 00607 ochain = SSL_get_peer_cert_chain(ssl); 00608 if ((NULL == ochain) || (0 == sk_num((const void *)ochain))) { 00609 DEBUGMSGT(("ssl:cert:chain", "peer has no cert chain\n")); 00610 } 00611 else { 00612 /* 00613 * loop over chain, adding fingerprint / cert for each 00614 */ 00615 DEBUGMSGT(("ssl:cert:chain", "examining cert chain\n")); 00616 for(i = 0; i < sk_num((const void *)ochain); ++i) { 00617 ocert_tmp = (X509*)sk_value((const void *)ochain,i); 00618 fingerprint = netsnmp_openssl_cert_get_fingerprint(ocert_tmp, 00619 NS_HASH_SHA1); 00620 if (NULL == fingerprint) 00621 break; 00622 cert_map = netsnmp_cert_map_alloc(NULL, ocert); 00623 if (NULL == cert_map) { 00624 free(fingerprint); 00625 break; 00626 } 00627 cert_map->fingerprint = fingerprint; 00628 cert_map->hashType = netsnmp_openssl_cert_get_hash_type(ocert_tmp); 00629 00630 CONTAINER_INSERT(chain_map, cert_map); 00631 } /* chain loop */ 00632 /* 00633 * if we broke out of loop before finishing, clean up 00634 */ 00635 if (i < sk_num((const void *)ochain)) 00636 CONTAINER_FREE_ALL(chain_map, NULL); 00637 } /* got peer chain */ 00638 00639 DEBUGMSGT(("ssl:cert:chain", "found %" NETSNMP_PRIz "u certs in chain\n", 00640 CONTAINER_SIZE(chain_map))); 00641 if (CONTAINER_SIZE(chain_map) == 0) { 00642 CONTAINER_FREE(chain_map); 00643 chain_map = NULL; 00644 } 00645 00646 return chain_map; 00647 } 00648 00649 /* 00650 tlstmCertSANRFC822Name "Maps a subjectAltName's rfc822Name to a 00651 tmSecurityName. The local part of the rfc822Name is 00652 passed unaltered but the host-part of the name must 00653 be passed in lower case. 00654 Example rfc822Name Field: FooBar@Example.COM 00655 is mapped to tmSecurityName: FooBar@example.com" 00656 00657 tlstmCertSANDNSName "Maps a subjectAltName's dNSName to a 00658 tmSecurityName after first converting it to all 00659 lower case." 00660 00661 tlstmCertSANIpAddress "Maps a subjectAltName's iPAddress to a 00662 tmSecurityName by transforming the binary encoded 00663 address as follows: 00664 1) for IPv4 the value is converted into a decimal 00665 dotted quad address (e.g. '192.0.2.1') 00666 2) for IPv6 addresses the value is converted into a 00667 32-character all lowercase hexadecimal string 00668 without any colon separators. 00669 00670 Note that the resulting length is the maximum 00671 length supported by the View-Based Access Control 00672 Model (VACM). Note that using both the Transport 00673 Security Model's support for transport prefixes 00674 (see the SNMP-TSM-MIB's 00675 snmpTsmConfigurationUsePrefix object for details) 00676 will result in securityName lengths that exceed 00677 what VACM can handle." 00678 00679 tlstmCertSANAny "Maps any of the following fields using the 00680 corresponding mapping algorithms: 00681 | rfc822Name | tlstmCertSANRFC822Name | 00682 | dNSName | tlstmCertSANDNSName | 00683 | iPAddress | tlstmCertSANIpAddress | 00684 The first matching subjectAltName value found in the 00685 certificate of the above types MUST be used when 00686 deriving the tmSecurityName." 00687 */ 00688 char * 00689 _cert_get_san_type(X509 *ocert, int mapType) 00690 { 00691 GENERAL_NAMES *onames; 00692 const GENERAL_NAME *oname = NULL; 00693 char *buf = NULL, *lower = NULL; 00694 int count, i; 00695 00696 onames = (GENERAL_NAMES *)X509_get_ext_d2i(ocert, NID_subject_alt_name, 00697 NULL, NULL ); 00698 if (NULL == onames) 00699 return NULL; 00700 00701 count = sk_GENERAL_NAME_num(onames); 00702 00703 for (i=0 ; i <count; ++i) { 00704 oname = sk_GENERAL_NAME_value(onames, i); 00705 00706 if (GEN_DNS == oname->type) { 00707 if ((TSNM_tlstmCertSANDNSName == mapType) || 00708 (TSNM_tlstmCertSANAny == mapType)) { 00709 lower = buf = _extract_oname( oname );; 00710 break; 00711 } 00712 } 00713 else if (GEN_IPADD == oname->type) { 00714 if ((TSNM_tlstmCertSANIpAddress == mapType) || 00715 (TSNM_tlstmCertSANAny == mapType)) 00716 buf = _extract_oname(oname); 00717 break; 00718 } 00719 else if (GEN_EMAIL == oname->type) { 00720 if ((TSNM_tlstmCertSANRFC822Name == mapType) || 00721 (TSNM_tlstmCertSANAny == mapType)) { 00722 buf = _extract_oname(oname); 00723 lower = strchr(buf, '@'); 00724 if (NULL == lower) { 00725 DEBUGMSGT(("openssl:secname:extract", 00726 "email %s has no '@'!\n", buf)); 00727 } 00728 else { 00729 ++lower; 00730 break; 00731 } 00732 } 00733 00734 } 00735 } /* for loop */ 00736 00737 if (lower) 00738 for ( ; *lower; ++lower ) 00739 if (isascii(*lower)) 00740 *lower = tolower(*lower); 00741 DEBUGMSGT(("openssl:cert:extension:san", "#%d type %d: %s\n", i, 00742 oname ? oname->type : -1, buf ? buf : "NULL")); 00743 00744 return buf; 00745 } 00746 00747 char * 00748 netsnmp_openssl_extract_secname(netsnmp_cert_map *cert_map, 00749 netsnmp_cert_map *peer_cert) 00750 { 00751 char *rtn = NULL; 00752 00753 if (NULL == cert_map) 00754 return NULL; 00755 00756 DEBUGMSGT(("openssl:secname:extract", 00757 "checking priority %d, san of type %d for %s\n", 00758 cert_map->priority, cert_map->mapType, peer_cert->fingerprint)); 00759 00760 switch(cert_map->mapType) { 00761 case TSNM_tlstmCertSpecified: 00762 rtn = strdup(cert_map->data); 00763 break; 00764 00765 case TSNM_tlstmCertSANRFC822Name: 00766 case TSNM_tlstmCertSANDNSName: 00767 case TSNM_tlstmCertSANIpAddress: 00768 case TSNM_tlstmCertSANAny: 00769 if (NULL == peer_cert) { 00770 DEBUGMSGT(("openssl:secname:extract", "no peer cert for %s\n", 00771 cert_map->fingerprint)); 00772 break; 00773 } 00774 rtn = _cert_get_san_type(peer_cert->ocert, cert_map->mapType); 00775 if (NULL == rtn) { 00776 DEBUGMSGT(("openssl:secname:extract", "no san for %s\n", 00777 peer_cert->fingerprint)); 00778 } 00779 break; 00780 00781 case TSNM_tlstmCertCommonName: 00782 rtn = netsnmp_openssl_cert_get_commonName(cert_map->ocert, NULL, 00783 NULL); 00784 break; 00785 default: 00786 snmp_log(LOG_ERR, "cant extract secname for unknown map type %d\n", 00787 cert_map->mapType); 00788 break; 00789 } /* switch mapType */ 00790 00791 if (rtn) { 00792 DEBUGMSGT(("openssl:secname:extract", 00793 "found map %d, type %d for %s: %s\n", cert_map->priority, 00794 cert_map->mapType, peer_cert->fingerprint, rtn)); 00795 if (strlen(rtn) >32) { 00796 DEBUGMSGT(("openssl:secname:extract", 00797 "secName longer than 32 chars! dropping...\n")); 00798 SNMP_FREE(rtn); 00799 } 00800 } 00801 else 00802 DEBUGMSGT(("openssl:secname:extract", 00803 "no map of type %d for %s\n", 00804 cert_map->mapType, peer_cert->fingerprint)); 00805 return rtn; 00806 } 00807 00808 int 00809 netsnmp_openssl_cert_issued_by(X509 *issuer, X509 *cert) 00810 { 00811 return (X509_check_issued(issuer, cert) == X509_V_OK); 00812 } 00813 00814 00815 #ifndef NETSNMP_FEATURE_REMOVE_OPENSSL_ERR_LOG 00816 void 00817 netsnmp_openssl_err_log(const char *prefix) 00818 { 00819 unsigned long err; 00820 for (err = ERR_get_error(); err; err = ERR_get_error()) { 00821 snmp_log(LOG_ERR,"%s: %ld\n", prefix ? prefix: "openssl error", err); 00822 snmp_log(LOG_ERR, "library=%d, function=%d, reason=%d\n", 00823 ERR_GET_LIB(err), ERR_GET_FUNC(err), ERR_GET_REASON(err)); 00824 } 00825 } 00826 #endif /* NETSNMP_FEATURE_REMOVE_OPENSSL_ERR_LOG */ 00827 00828 void 00829 netsnmp_openssl_null_checks(SSL *ssl, int *null_auth, int *null_cipher) 00830 { 00831 const SSL_CIPHER *cipher; 00832 char *description, tmp_buf[128], *cipher_alg, *auth_alg; 00833 00834 if (null_auth) 00835 *null_auth = -1; /* unknown */ 00836 if (null_cipher) 00837 *null_cipher = -1; /* unknown */ 00838 if (NULL == ssl) 00839 return; 00840 00841 cipher = SSL_get_current_cipher(ssl); 00842 if (NULL == cipher) { 00843 DEBUGMSGTL(("ssl:cipher", "no cipher yet\n")); 00844 return; 00845 } 00846 description = SSL_CIPHER_description(NETSNMP_REMOVE_CONST(SSL_CIPHER *, cipher), tmp_buf, sizeof(tmp_buf)); 00848 DEBUGMSGTL(("ssl:cipher", "current cipher: %s", tmp_buf)); 00849 00850 /* 00851 * run "openssl ciphers -v eNULL" and "openssl ciphers -v aNULL" 00852 * to see NULL encryption/authentication algorithms. e.g. 00853 * 00854 * EXP-ADH-RC4-MD5 SSLv3 Kx=DH(512) Au=None Enc=RC4(40) Mac=MD5 export 00855 * NULL-SHA SSLv3 Kx=RSA Au=RSA Enc=None Mac=SHA1 00856 */ 00857 if (null_cipher) { 00858 cipher_alg = strstr(tmp_buf, "Enc="); 00859 if (cipher_alg) { 00860 cipher_alg += 4; 00861 if (strncmp(cipher_alg,"None", 4) == 0) 00862 *null_cipher = 1; 00863 else 00864 *null_cipher = 0; 00865 } 00866 } 00867 if (null_auth) { 00868 auth_alg = strstr(tmp_buf, "Au="); 00869 if (auth_alg) { 00870 auth_alg += 3; 00871 if (strncmp(auth_alg,"None", 4) == 0) 00872 *null_auth = 1; 00873 else 00874 *null_auth = 0; 00875 } 00876 } 00877 } 00878 00879 #endif /* NETSNMP_USE_OPENSSL && HAVE_LIBSSL && !defined(NETSNMP_FEATURE_REMOVE_CERT_UTIL) */