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