7 /* peer name and peer certificate verification
9 /* #define TLS_INTERNAL
12 /* char *tls_peer_CN(peercert, TLScontext)
14 /* TLS_SESS_STATE *TLScontext;
16 /* char *tls_issuer_CN(peercert, TLScontext)
18 /* TLS_SESS_STATE *TLScontext;
20 /* const char *tls_dns_name(gn, TLScontext)
21 /* const GENERAL_NAME *gn;
22 /* TLS_SESS_STATE *TLScontext;
24 /* char *tls_fingerprint(peercert, dgst)
28 /* int tls_verify_certificate_callback(ok, ctx)
30 /* X509_STORE_CTX *ctx;
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
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
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.
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().
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.
60 /* Postfix/TLS has two modes, the "opportunistic" mode and
61 /* the "enforce" mode:
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".
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).
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.
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
88 /* SSL application context. This links to the Postfix TLScontext
89 /* with enforcement and logging options.
91 /* An OpenSSL GENERAL_NAME structure holding a DNS subjectAltName
92 /* to be decoded and checked for validity.
94 /* Server or client X.509 certificate.
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.
100 /* Server or client context for warning messages.
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.
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.
114 /* Originally written by:
117 /* Allgemeine Elektrotechnik
118 /* Universitaetsplatz 3-4
119 /* D-03044 Cottbus, Germany
123 /* IBM T.J. Watson Research
125 /* Yorktown Heights, NY 10598, USA
131 /* System library. */
133 #include <sys_defs.h>
139 /* Utility library. */
142 #include <mymalloc.h>
143 #include <stringops.h>
150 /* Application-specific. */
152 static const char hexcodes
[] = "0123456789ABCDEF";
154 /* tls_verify_certificate_callback - verify peer certificate info */
156 int tls_verify_certificate_callback(int ok
, X509_STORE_CTX
*ctx
)
158 char buf
[CCERT_BUFSIZ
];
163 TLS_SESS_STATE
*TLScontext
;
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
);
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.
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.
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.
185 * Certificate chain depth limit violations are mis-reported by the OpenSSL
186 * library, from SSL_CTX_set_verify(3):
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.
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.
198 if (depth
>= SSL_get_verify_depth(con
)) {
200 X509_STORE_CTX_set_error(ctx
, X509_V_ERR_CERT_CHAIN_TOO_LONG
);
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
, '?'));
209 * If no errors, or we are not logging verification errors, we are done.
211 if (ok
|| (TLScontext
->peer_status
& TLS_CERT_FLAG_LOGGED
) != 0)
215 * One counter-example is enough.
217 TLScontext
->peer_status
|= TLS_CERT_FLAG_LOGGED
;
219 #define PURPOSE ((depth>0) ? "CA": TLScontext->am_server ? "client": "server")
222 * Specific causes for verification failure.
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
);
229 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
:
230 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
:
233 * There is no difference between issuing cert not provided and
234 * provided, but not found in CAfile/CApath. Either way, we don't
237 X509_NAME_oneline(X509_get_issuer_name(ctx
->current_cert
),
239 msg_info("certificate verification failed for %s: untrusted issuer %s",
240 TLScontext
->namaddr
, printable(buf
, '?'));
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
);
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
);
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
);
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);
262 msg_info("%s certificate verification failed for %s: num=%d:%s",
263 PURPOSE
, TLScontext
->namaddr
, err
,
264 X509_verify_cert_error_string(err
));
276 /* tls_text_name - extract certificate property value by name */
278 static char *tls_text_name(X509_NAME
*name
, int nid
, const char *label
,
279 const TLS_SESS_STATE
*TLScontext
, int gripe
)
281 const char *myname
= "tls_text_name";
283 X509_NAME_ENTRY
*entry
;
284 ASN1_STRING
*entry_str
;
287 unsigned char *utf8_value
;
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
);
302 * If the match is required unambiguous, insist that that no other values
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
);
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
);
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
);
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
335 * XXX Don't bother optimizing the string length error check. It is not
336 * worth the complexity.
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
);
347 * No returns without cleaning up. A good optimizer will replace multiple
348 * blocks of identical code by jumps to just one such block.
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); \
357 * Remove trailing null characters. They would give false alarms with the
358 * length check and with the embedded null check.
360 #define TRIM0(s, l) do { while ((l) > 0 && (s)[(l)-1] == 0) --(l); } while (0)
362 TRIM0(utf8_value
, utf8_length
);
365 * Enforce the length limit, because the caller will copy the result into
366 * a fixed-length buffer.
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);
375 * Reject embedded nulls in ASCII or UTF-8 names. OpenSSL is responsible
376 * for producing properly-formatted UTF-8.
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);
385 * Reject non-printable ASCII characters in UTF-8 content.
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.
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);
398 TLS_TEXT_NAME_RETURN(mystrdup((char *) utf8_value
));
401 /* tls_dns_name - Extract valid DNS name from subjectAltName value */
403 const char *tls_dns_name(const GENERAL_NAME
* gn
,
404 const TLS_SESS_STATE
*TLScontext
)
406 const char *myname
= "tls_dns_name";
412 * Peername checks are security sensitive, carefully scrutinize the
415 if (gn
->type
!= GEN_DNS
)
416 msg_panic("%s: Non DNS input argument", myname
);
419 * We expect the OpenSSL library to construct GEN_DNS extesion objects as
420 * ASN1_IA5STRING values. Check we got the right union member.
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
);
429 * Safe to treat as an ASCII string possibly holding a DNS name
431 dnsname
= (char *) ASN1_STRING_data(gn
->d
.ia5
);
432 len
= ASN1_STRING_length(gn
->d
.ia5
);
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().
442 if (len
!= strlen(dnsname
)) {
443 msg_warn("%s: %s: internal NUL in subjectAltName",
444 myname
, TLScontext
->namaddr
);
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...
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
, '?'));
464 /* tls_peer_CN - extract peer common name from certificate */
466 char *tls_peer_CN(X509
*peercert
, const TLS_SESS_STATE
*TLScontext
)
470 cn
= tls_text_name(X509_get_subject_name(peercert
), NID_commonName
,
471 "subject CN", TLScontext
, DO_GRIPE
);
472 return (cn
? cn
: mystrdup(""));
475 /* tls_issuer_CN - extract issuer common name from certificate */
477 char *tls_issuer_CN(X509
*peer
, const TLS_SESS_STATE
*TLScontext
)
482 name
= X509_get_issuer_name(peer
);
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.
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(""));
495 /* tls_fingerprint - extract fingerprint from certificate */
497 char *tls_fingerprint(X509
*peercert
, const char *dgst
)
499 const char *myname
= "tls_fingerprint";
500 const EVP_MD
*md_alg
;
501 unsigned char md_buf
[EVP_MAX_MD_SIZE
];
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
);
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?)",
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
);
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';