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