1 /* $NetBSD: tls_verify.c,v 1.2 2017/02/14 01:16:48 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* tls_verify 3 6 /* SUMMARY 7 /* peer name and peer certificate verification 8 /* SYNOPSIS 9 /* #define TLS_INTERNAL 10 /* #include <tls.h> 11 /* 12 /* int tls_verify_certificate_callback(ok, ctx) 13 /* int ok; 14 /* X509_STORE_CTX *ctx; 15 /* 16 /* int tls_log_verify_error(TLScontext) 17 /* TLS_SESS_STATE *TLScontext; 18 /* 19 /* char *tls_peer_CN(peercert, TLScontext) 20 /* X509 *peercert; 21 /* TLS_SESS_STATE *TLScontext; 22 /* 23 /* char *tls_issuer_CN(peercert, TLScontext) 24 /* X509 *peercert; 25 /* TLS_SESS_STATE *TLScontext; 26 /* 27 /* const char *tls_dns_name(gn, TLScontext) 28 /* const GENERAL_NAME *gn; 29 /* TLS_SESS_STATE *TLScontext; 30 /* DESCRIPTION 31 /* tls_verify_certificate_callback() is called several times (directly 32 /* or indirectly) from crypto/x509/x509_vfy.c. It collects errors 33 /* and trust information at each element of the trust chain. 34 /* The last call at depth 0 sets the verification status based 35 /* on the cumulative winner (lowest depth) of errors vs. trust. 36 /* We always return 1 (continue the handshake) and handle trust 37 /* and peer-name verification problems at the application level. 38 /* 39 /* tls_log_verify_error() (called only when we care about the 40 /* peer certificate, that is not when opportunistic) logs the 41 /* reason why the certificate failed to be verified. 42 /* 43 /* tls_peer_CN() returns the text CommonName for the peer 44 /* certificate subject, or an empty string if no CommonName was 45 /* found. The result is allocated with mymalloc() and must be 46 /* freed by the caller; it contains UTF-8 without non-printable 47 /* ASCII characters. 48 /* 49 /* tls_issuer_CN() returns the text CommonName for the peer 50 /* certificate issuer, or an empty string if no CommonName was 51 /* found. The result is allocated with mymalloc() and must be 52 /* freed by the caller; it contains UTF-8 without non-printable 53 /* ASCII characters. 54 /* 55 /* tls_dns_name() returns the string value of a GENERAL_NAME 56 /* from a DNS subjectAltName extension. If non-printable characters 57 /* are found, a null string is returned instead. Further sanity 58 /* checks may be added if the need arises. 59 /* 60 /* Arguments: 61 /* .IP ok 62 /* Result of prior verification: non-zero means success. In 63 /* order to reduce the noise level, some tests or error reports 64 /* are disabled when verification failed because of some 65 /* earlier problem. 66 /* .IP ctx 67 /* SSL application context. This links to the Postfix TLScontext 68 /* with enforcement and logging options. 69 /* .IP gn 70 /* An OpenSSL GENERAL_NAME structure holding a DNS subjectAltName 71 /* to be decoded and checked for validity. 72 /* .IP peercert 73 /* Server or client X.509 certificate. 74 /* .IP TLScontext 75 /* Server or client context for warning messages. 76 /* DIAGNOSTICS 77 /* tls_peer_CN(), tls_issuer_CN() and tls_dns_name() log a warning 78 /* when 1) the requested information is not available in the specified 79 /* certificate, 2) the result exceeds a fixed limit, 3) the result 80 /* contains NUL characters or the result contains non-printable or 81 /* non-ASCII characters. 82 /* LICENSE 83 /* .ad 84 /* .fi 85 /* This software is free. You can do with it whatever you want. 86 /* The original author kindly requests that you acknowledge 87 /* the use of his software. 88 /* AUTHOR(S) 89 /* Originally written by: 90 /* Lutz Jaenicke 91 /* BTU Cottbus 92 /* Allgemeine Elektrotechnik 93 /* Universitaetsplatz 3-4 94 /* D-03044 Cottbus, Germany 95 /* 96 /* Updated by: 97 /* Wietse Venema 98 /* IBM T.J. Watson Research 99 /* P.O. Box 704 100 /* Yorktown Heights, NY 10598, USA 101 /* 102 /* Victor Duchovni 103 /* Morgan Stanley 104 /*--*/ 105 106 /* System library. */ 107 108 #include <sys_defs.h> 109 #include <ctype.h> 110 111 #ifdef USE_TLS 112 #include <string.h> 113 114 /* Utility library. */ 115 116 #include <msg.h> 117 #include <mymalloc.h> 118 #include <stringops.h> 119 120 /* TLS library. */ 121 122 #define TLS_INTERNAL 123 #include <tls.h> 124 125 /* update_error_state - safely stash away error state */ 126 127 static void update_error_state(TLS_SESS_STATE *TLScontext, int depth, 128 X509 *errorcert, int errorcode) 129 { 130 /* No news is good news */ 131 if (TLScontext->errordepth >= 0 && TLScontext->errordepth <= depth) 132 return; 133 134 /* 135 * The certificate pointer is stable during the verification callback, 136 * but may be freed after the callback returns. Since we delay error 137 * reporting till later, we bump the refcount so we can rely on it still 138 * being there until later. 139 */ 140 if (TLScontext->errorcert != 0) 141 X509_free(TLScontext->errorcert); 142 if (errorcert != 0) 143 X509_up_ref(errorcert); 144 TLScontext->errorcert = errorcert; 145 TLScontext->errorcode = errorcode; 146 TLScontext->errordepth = depth; 147 } 148 149 /* tls_verify_certificate_callback - verify peer certificate info */ 150 151 int tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx) 152 { 153 char buf[CCERT_BUFSIZ]; 154 X509 *cert; 155 int err; 156 int depth; 157 int max_depth; 158 SSL *con; 159 TLS_SESS_STATE *TLScontext; 160 161 /* May be NULL as of OpenSSL 1.0, thanks for the API change! */ 162 cert = X509_STORE_CTX_get_current_cert(ctx); 163 err = X509_STORE_CTX_get_error(ctx); 164 con = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); 165 TLScontext = SSL_get_ex_data(con, TLScontext_index); 166 depth = X509_STORE_CTX_get_error_depth(ctx); 167 168 /* Don't log the internal root CA unless there's an unexpected error. */ 169 if (ok && TLScontext->tadepth > 0 && depth > TLScontext->tadepth) 170 return (1); 171 172 /* 173 * Certificate chain depth limit violations are mis-reported by the 174 * OpenSSL library, from SSL_CTX_set_verify(3): 175 * 176 * The certificate verification depth set with SSL[_CTX]_verify_depth() 177 * stops the verification at a certain depth. The error message produced 178 * will be that of an incomplete certificate chain and not 179 * X509_V_ERR_CERT_CHAIN_TOO_LONG as may be expected. 180 * 181 * We set a limit that is one higher than the user requested limit. If this 182 * higher limit is reached, we raise an error even a trusted root CA is 183 * present at this depth. This disambiguates trust chain truncation from 184 * an incomplete trust chain. 185 */ 186 max_depth = SSL_get_verify_depth(con) - 1; 187 188 /* 189 * We never terminate the SSL handshake in the verification callback, 190 * rather we allow the TLS handshake to continue, but mark the session as 191 * unverified. The application is responsible for closing any sessions 192 * with unverified credentials. 193 */ 194 if (max_depth >= 0 && depth > max_depth) { 195 X509_STORE_CTX_set_error(ctx, err = X509_V_ERR_CERT_CHAIN_TOO_LONG); 196 ok = 0; 197 } 198 if (ok == 0) 199 update_error_state(TLScontext, depth, cert, err); 200 201 if (TLScontext->log_mask & TLS_LOG_VERBOSE) { 202 if (cert) 203 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); 204 else 205 strcpy(buf, "<unknown>"); 206 msg_info("%s: depth=%d verify=%d subject=%s", 207 TLScontext->namaddr, depth, ok, printable(buf, '?')); 208 } 209 return (1); 210 } 211 212 /* tls_log_verify_error - Report final verification error status */ 213 214 void tls_log_verify_error(TLS_SESS_STATE *TLScontext) 215 { 216 char buf[CCERT_BUFSIZ]; 217 int err = TLScontext->errorcode; 218 X509 *cert = TLScontext->errorcert; 219 int depth = TLScontext->errordepth; 220 221 #define PURPOSE ((depth>0) ? "CA": TLScontext->am_server ? "client": "server") 222 223 if (err == X509_V_OK) 224 return; 225 226 /* 227 * Specific causes for verification failure. 228 */ 229 switch (err) { 230 case X509_V_ERR_CERT_UNTRUSTED: 231 232 /* 233 * We expect the error cert to be the leaf, but it is likely 234 * sufficient to omit it from the log, even less user confusion. 235 */ 236 msg_info("certificate verification failed for %s: " 237 "not trusted by local or TLSA policy", TLScontext->namaddr); 238 break; 239 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: 240 msg_info("certificate verification failed for %s: " 241 "self-signed certificate", TLScontext->namaddr); 242 break; 243 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: 244 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: 245 246 /* 247 * There is no difference between issuing cert not provided and 248 * provided, but not found in CAfile/CApath. Either way, we don't 249 * trust it. 250 */ 251 if (cert) 252 X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)); 253 else 254 strcpy(buf, "<unknown>"); 255 msg_info("certificate verification failed for %s: untrusted issuer %s", 256 TLScontext->namaddr, printable(buf, '?')); 257 break; 258 case X509_V_ERR_CERT_NOT_YET_VALID: 259 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: 260 msg_info("%s certificate verification failed for %s: certificate not" 261 " yet valid", PURPOSE, TLScontext->namaddr); 262 break; 263 case X509_V_ERR_CERT_HAS_EXPIRED: 264 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: 265 msg_info("%s certificate verification failed for %s: certificate has" 266 " expired", PURPOSE, TLScontext->namaddr); 267 break; 268 case X509_V_ERR_INVALID_PURPOSE: 269 msg_info("certificate verification failed for %s: not designated for " 270 "use as a %s certificate", TLScontext->namaddr, PURPOSE); 271 break; 272 case X509_V_ERR_CERT_CHAIN_TOO_LONG: 273 msg_info("certificate verification failed for %s: " 274 "certificate chain longer than limit(%d)", 275 TLScontext->namaddr, depth - 1); 276 break; 277 default: 278 msg_info("%s certificate verification failed for %s: num=%d:%s", 279 PURPOSE, TLScontext->namaddr, err, 280 X509_verify_cert_error_string(err)); 281 break; 282 } 283 } 284 285 #ifndef DONT_GRIPE 286 #define DONT_GRIPE 0 287 #define DO_GRIPE 1 288 #endif 289 290 /* tls_text_name - extract certificate property value by name */ 291 292 static char *tls_text_name(X509_NAME *name, int nid, const char *label, 293 const TLS_SESS_STATE *TLScontext, int gripe) 294 { 295 const char *myname = "tls_text_name"; 296 int pos; 297 X509_NAME_ENTRY *entry; 298 ASN1_STRING *entry_str; 299 int asn1_type; 300 int utf8_length; 301 unsigned char *utf8_value; 302 int ch; 303 unsigned char *cp; 304 305 if (name == 0 || (pos = X509_NAME_get_index_by_NID(name, nid, -1)) < 0) { 306 if (gripe != DONT_GRIPE) { 307 msg_warn("%s: %s: peer certificate has no %s", 308 myname, TLScontext->namaddr, label); 309 tls_print_errors(); 310 } 311 return (0); 312 } 313 #if 0 314 315 /* 316 * If the match is required unambiguous, insist that that no other values 317 * be present. 318 */ 319 if (X509_NAME_get_index_by_NID(name, nid, pos) >= 0) { 320 msg_warn("%s: %s: multiple %ss in peer certificate", 321 myname, TLScontext->namaddr, label); 322 return (0); 323 } 324 #endif 325 326 if ((entry = X509_NAME_get_entry(name, pos)) == 0) { 327 /* This should not happen */ 328 msg_warn("%s: %s: error reading peer certificate %s entry", 329 myname, TLScontext->namaddr, label); 330 tls_print_errors(); 331 return (0); 332 } 333 if ((entry_str = X509_NAME_ENTRY_get_data(entry)) == 0) { 334 /* This should not happen */ 335 msg_warn("%s: %s: error reading peer certificate %s data", 336 myname, TLScontext->namaddr, label); 337 tls_print_errors(); 338 return (0); 339 } 340 341 /* 342 * XXX Convert everything into UTF-8. This is a super-set of ASCII, so we 343 * don't have to bother with separate code paths for ASCII-like content. 344 * If the payload is ASCII then we won't waste lots of CPU cycles 345 * converting it into UTF-8. It's up to OpenSSL to do something 346 * reasonable when converting ASCII formats that contain non-ASCII 347 * content. 348 * 349 * XXX Don't bother optimizing the string length error check. It is not 350 * worth the complexity. 351 */ 352 asn1_type = ASN1_STRING_type(entry_str); 353 if ((utf8_length = ASN1_STRING_to_UTF8(&utf8_value, entry_str)) < 0) { 354 msg_warn("%s: %s: error decoding peer %s of ASN.1 type=%d", 355 myname, TLScontext->namaddr, label, asn1_type); 356 tls_print_errors(); 357 return (0); 358 } 359 360 /* 361 * No returns without cleaning up. A good optimizer will replace multiple 362 * blocks of identical code by jumps to just one such block. 363 */ 364 #define TLS_TEXT_NAME_RETURN(x) do { \ 365 char *__tls_text_name_temp = (x); \ 366 OPENSSL_free(utf8_value); \ 367 return (__tls_text_name_temp); \ 368 } while (0) 369 370 /* 371 * Remove trailing null characters. They would give false alarms with the 372 * length check and with the embedded null check. 373 */ 374 #define TRIM0(s, l) do { while ((l) > 0 && (s)[(l)-1] == 0) --(l); } while (0) 375 376 TRIM0(utf8_value, utf8_length); 377 378 /* 379 * Enforce the length limit, because the caller will copy the result into 380 * a fixed-length buffer. 381 */ 382 if (utf8_length >= CCERT_BUFSIZ) { 383 msg_warn("%s: %s: peer %s too long: %d", 384 myname, TLScontext->namaddr, label, utf8_length); 385 TLS_TEXT_NAME_RETURN(0); 386 } 387 388 /* 389 * Reject embedded nulls in ASCII or UTF-8 names. OpenSSL is responsible 390 * for producing properly-formatted UTF-8. 391 */ 392 if (utf8_length != strlen((char *) utf8_value)) { 393 msg_warn("%s: %s: NULL character in peer %s", 394 myname, TLScontext->namaddr, label); 395 TLS_TEXT_NAME_RETURN(0); 396 } 397 398 /* 399 * Reject non-printable ASCII characters in UTF-8 content. 400 * 401 * Note: the code below does not find control characters in illegal UTF-8 402 * sequences. It's OpenSSL's job to produce valid UTF-8, and reportedly, 403 * it does validation. 404 */ 405 for (cp = utf8_value; (ch = *cp) != 0; cp++) { 406 if (ISASCII(ch) && !ISPRINT(ch)) { 407 msg_warn("%s: %s: non-printable content in peer %s", 408 myname, TLScontext->namaddr, label); 409 TLS_TEXT_NAME_RETURN(0); 410 } 411 } 412 TLS_TEXT_NAME_RETURN(mystrdup((char *) utf8_value)); 413 } 414 415 /* tls_dns_name - Extract valid DNS name from subjectAltName value */ 416 417 const char *tls_dns_name(const GENERAL_NAME * gn, 418 const TLS_SESS_STATE *TLScontext) 419 { 420 const char *myname = "tls_dns_name"; 421 char *cp; 422 const char *dnsname; 423 int len; 424 425 /* 426 * Peername checks are security sensitive, carefully scrutinize the 427 * input! 428 */ 429 if (gn->type != GEN_DNS) 430 msg_panic("%s: Non DNS input argument", myname); 431 432 /* 433 * We expect the OpenSSL library to construct GEN_DNS extesion objects as 434 * ASN1_IA5STRING values. Check we got the right union member. 435 */ 436 if (ASN1_STRING_type(gn->d.ia5) != V_ASN1_IA5STRING) { 437 msg_warn("%s: %s: invalid ASN1 value type in subjectAltName", 438 myname, TLScontext->namaddr); 439 return (0); 440 } 441 442 /* 443 * Safe to treat as an ASCII string possibly holding a DNS name 444 */ 445 dnsname = (const char *) ASN1_STRING_get0_data(gn->d.ia5); 446 len = ASN1_STRING_length(gn->d.ia5); 447 TRIM0(dnsname, len); 448 449 /* 450 * Per Dr. Steven Henson of the OpenSSL development team, ASN1_IA5STRING 451 * values can have internal ASCII NUL values in this context because 452 * their length is taken from the decoded ASN1 buffer, a trailing NUL is 453 * always appended to make sure that the string is terminated, but the 454 * ASN.1 length may differ from strlen(). 455 */ 456 if (len != strlen(dnsname)) { 457 msg_warn("%s: %s: internal NUL in subjectAltName", 458 myname, TLScontext->namaddr); 459 return 0; 460 } 461 462 /* 463 * XXX: Should we be more strict and call valid_hostname()? So long as 464 * the name is safe to handle, if it is not a valid hostname, it will not 465 * compare equal to the expected peername, so being more strict than 466 * "printable" is likely excessive... 467 */ 468 if (*dnsname && !allprint(dnsname)) { 469 cp = mystrdup(dnsname); 470 msg_warn("%s: %s: non-printable characters in subjectAltName: %.100s", 471 myname, TLScontext->namaddr, printable(cp, '?')); 472 myfree(cp); 473 return 0; 474 } 475 return (dnsname); 476 } 477 478 /* tls_peer_CN - extract peer common name from certificate */ 479 480 char *tls_peer_CN(X509 *peercert, const TLS_SESS_STATE *TLScontext) 481 { 482 char *cn; 483 484 cn = tls_text_name(X509_get_subject_name(peercert), NID_commonName, 485 "subject CN", TLScontext, DONT_GRIPE); 486 return (cn ? cn : mystrdup("")); 487 } 488 489 /* tls_issuer_CN - extract issuer common name from certificate */ 490 491 char *tls_issuer_CN(X509 *peer, const TLS_SESS_STATE *TLScontext) 492 { 493 X509_NAME *name; 494 char *cn; 495 496 name = X509_get_issuer_name(peer); 497 498 /* 499 * If no issuer CN field, use Organization instead. CA certs without a CN 500 * are common, so we only complain if the organization is also missing. 501 */ 502 if ((cn = tls_text_name(name, NID_commonName, 503 "issuer CN", TLScontext, DONT_GRIPE)) == 0) 504 cn = tls_text_name(name, NID_organizationName, 505 "issuer Organization", TLScontext, DONT_GRIPE); 506 return (cn ? cn : mystrdup("")); 507 } 508 509 #endif 510