18
25
/* const char *tls_dns_name(gn, TLScontext)
19
26
/* const GENERAL_NAME *gn;
20
27
/* TLS_SESS_STATE *TLScontext;
22
/* char *tls_fingerprint(peercert, dgst)
26
/* char *tls_pkey_fprint(peercert, dgst)
30
/* int tls_verify_certificate_callback(ok, ctx)
32
/* X509_STORE_CTX *ctx;
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.
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.
34
41
/* tls_peer_CN() returns the text CommonName for the peer
35
42
/* certificate subject, or an empty string if no CommonName was
36
43
/* found. The result is allocated with mymalloc() and must be
48
55
/* are found, a null string is returned instead. Further sanity
49
56
/* checks may be added if the need arises.
51
/* tls_fingerprint() returns a fingerprint of the the given
52
/* certificate using the requested message digest. Panics if the
53
/* (previously verified) digest algorithm is not found. The return
54
/* value is dynamically allocated with mymalloc(), and the caller
55
/* must eventually free it with myfree().
57
/* tls_pkey_fprint() returns a public-key fingerprint; in all
58
/* other respects the function behaves as tls_fingerprint().
59
/* The var_tls_bc_pkey_fprint variable enables an incorrect
60
/* algorithm that was used in Postfix versions 2.9.[0-5].
62
/* tls_verify_callback() is called several times (directly or
63
/* indirectly) from crypto/x509/x509_vfy.c. It is called as
64
/* a final check, and if it returns "0", the handshake is
65
/* immediately shut down and the connection fails.
67
/* Postfix/TLS has two modes, the "opportunistic" mode and
68
/* the "enforce" mode:
70
/* In the "opportunistic" mode we never want the connection
71
/* to fail just because there is something wrong with the
72
/* peer's certificate. After all, we would have sent or received
73
/* the mail even if TLS weren't available. Therefore the
74
/* return value is always "1".
76
/* The SMTP client or server may require TLS (e.g. to protect
77
/* passwords), while peer certificates are optional. In this
78
/* case we must return "1" even when we are unhappy with the
79
/* peer certificate. Only when peer certificates are required,
80
/* certificate verification failure will result in immediate
81
/* termination (return 0).
83
/* The only error condition not handled inside the OpenSSL
84
/* library is the case of a too-long certificate chain. We
85
/* test for this condition only if "ok = 1", that is, if
86
/* verification didn't fail because of some earlier problem.
90
60
/* Result of prior verification: non-zero means success. In
149
115
#include <mymalloc.h>
150
116
#include <stringops.h>
152
/* Global library. */
154
#include <mail_params.h>
156
118
/* TLS library. */
158
120
#define TLS_INTERNAL
161
/* Application-specific. */
163
static const char hexcodes[] = "0123456789ABCDEF";
123
/* update_error_state - safely stash away error state */
125
static void update_error_state(TLS_SESS_STATE *TLScontext, int depth,
126
X509 *errorcert, int errorcode)
128
/* No news is good news */
129
if (TLScontext->errordepth >= 0 && TLScontext->errordepth <= depth)
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.
138
if (TLScontext->errorcert != 0)
139
X509_free(TLScontext->errorcert);
141
CRYPTO_add(&errorcert->references, 1, CRYPTO_LOCK_X509);
142
TLScontext->errorcert = errorcert;
143
TLScontext->errorcode = errorcode;
144
TLScontext->errordepth = depth;
165
147
/* tls_verify_certificate_callback - verify peer certificate info */
174
157
TLS_SESS_STATE *TLScontext;
176
depth = X509_STORE_CTX_get_error_depth(ctx);
159
/* May be NULL as of OpenSSL 1.0, thanks for the API change! */
177
160
cert = X509_STORE_CTX_get_current_cert(ctx);
161
err = X509_STORE_CTX_get_error(ctx);
178
162
con = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
179
163
TLScontext = SSL_get_ex_data(con, TLScontext_index);
164
depth = X509_STORE_CTX_get_error_depth(ctx);
166
/* Don't log the internal root CA unless there's an unexpected error. */
167
if (ok && TLScontext->tadepth > 0 && depth > TLScontext->tadepth)
182
* The callback function is called repeatedly, first with the root
183
* certificate, and then with each intermediate certificate ending with
184
* the peer certificate.
186
* With each call, the validity of the current certificate (usage bits,
187
* attributes, expiration, ... checked by the OpenSSL library) is
188
* available in the "ok" argument. Error details are available via
189
* X509_STORE_CTX API.
191
* We never terminate the SSL handshake in the verification callback, rather
192
* we allow the TLS handshake to continue, but mark the session as
193
* unverified. The application is responsible for closing any sessions
194
* with unverified credentials.
196
* Certificate chain depth limit violations are mis-reported by the OpenSSL
197
* library, from SSL_CTX_set_verify(3):
171
* Certificate chain depth limit violations are mis-reported by the
172
* OpenSSL library, from SSL_CTX_set_verify(3):
199
174
* The certificate verification depth set with SSL[_CTX]_verify_depth()
200
175
* stops the verification at a certain depth. The error message produced
206
181
* present at this depth. This disambiguates trust chain truncation from
207
182
* an incomplete trust chain.
209
if (depth >= SSL_get_verify_depth(con)) {
184
max_depth = SSL_get_verify_depth(con) - 1;
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.
192
if (max_depth >= 0 && depth > max_depth) {
193
X509_STORE_CTX_set_error(ctx, err = X509_V_ERR_CERT_CHAIN_TOO_LONG);
211
X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_CHAIN_TOO_LONG);
197
update_error_state(TLScontext, depth, cert, err);
213
199
if (TLScontext->log_mask & TLS_LOG_VERBOSE) {
214
X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
215
msg_info("%s: certificate verification depth=%d verify=%d subject=%s",
201
X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
203
strcpy(buf, "<unknown>");
204
msg_info("%s: depth=%d verify=%d subject=%s",
216
205
TLScontext->namaddr, depth, ok, printable(buf, '?'));
220
* If no errors, or we are not logging verification errors, we are done.
222
if (ok || (TLScontext->log_mask & TLS_LOG_UNTRUSTED) == 0)
226
* One counter-example is enough.
228
TLScontext->log_mask &= ~TLS_LOG_UNTRUSTED;
210
/* tls_log_verify_error - Report final verification error status */
212
void tls_log_verify_error(TLS_SESS_STATE *TLScontext)
214
char buf[CCERT_BUFSIZ];
215
int err = TLScontext->errorcode;
216
X509 *cert = TLScontext->errorcert;
217
int depth = TLScontext->errordepth;
230
219
#define PURPOSE ((depth>0) ? "CA": TLScontext->am_server ? "client": "server")
221
if (err == X509_V_OK)
233
225
* Specific causes for verification failure.
235
switch (err = X509_STORE_CTX_get_error(ctx)) {
228
case X509_V_ERR_CERT_UNTRUSTED:
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.
234
msg_info("certificate verification failed for %s: "
235
"not trusted by local or TLSA policy", TLScontext->namaddr);
236
237
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
237
238
msg_info("certificate verification failed for %s: "
238
239
"self-signed certificate", TLScontext->namaddr);
245
246
* provided, but not found in CAfile/CApath. Either way, we don't
248
X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),
250
X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
252
strcpy(buf, "<unknown>");
250
253
msg_info("certificate verification failed for %s: untrusted issuer %s",
251
254
TLScontext->namaddr, printable(buf, '?'));
499
500
if ((cn = tls_text_name(name, NID_commonName,
500
501
"issuer CN", TLScontext, DONT_GRIPE)) == 0)
501
502
cn = tls_text_name(name, NID_organizationName,
502
"issuer Organization", TLScontext, DO_GRIPE);
503
"issuer Organization", TLScontext, DONT_GRIPE);
503
504
return (cn ? cn : mystrdup(""));
506
/* tls_fprint - compute and encode digest of DER-encoded object */
508
static char *tls_fprint(const char *buf, int len, const char *dgst)
510
const char *myname = "tls_fprint";
512
const EVP_MD *md_alg;
513
unsigned char md_buf[EVP_MAX_MD_SIZE];
518
/* Previously available in "init" routine. */
519
if ((md_alg = EVP_get_digestbyname(dgst)) == 0)
520
msg_panic("%s: digest algorithm \"%s\" not found", myname, dgst);
522
mdctx = EVP_MD_CTX_create();
523
if (EVP_DigestInit_ex(mdctx, md_alg, NULL) == 0
524
|| EVP_DigestUpdate(mdctx, buf, len) == 0
525
|| EVP_DigestFinal_ex(mdctx, md_buf, &md_len) == 0)
526
msg_fatal("%s: error computing %s message digest", myname, dgst);
527
EVP_MD_CTX_destroy(mdctx);
529
/* Check for OpenSSL contract violation */
530
if (md_len > EVP_MAX_MD_SIZE || md_len >= INT_MAX / 3)
531
msg_panic("%s: unexpectedly large %s digest size: %u",
532
myname, dgst, md_len);
534
result = mymalloc(md_len * 3);
535
for (i = 0; i < md_len; i++) {
536
result[i * 3] = hexcodes[(md_buf[i] & 0xf0) >> 4U];
537
result[(i * 3) + 1] = hexcodes[(md_buf[i] & 0x0f)];
538
result[(i * 3) + 2] = (i + 1 != md_len) ? ':' : '\0';
543
/* tls_fingerprint - extract certificate fingerprint */
545
char *tls_fingerprint(X509 *peercert, const char *dgst)
552
len = i2d_X509(peercert, NULL);
553
buf2 = buf = mymalloc(len);
554
i2d_X509(peercert, (unsigned char **)&buf2);
555
if (buf2 - buf != len)
556
msg_panic("i2d_X509 invalid result length");
558
result = tls_fprint(buf, len, dgst);
564
/* tls_pkey_fprint - extract public key fingerprint from certificate */
566
char *tls_pkey_fprint(X509 *peercert, const char *dgst)
568
if (var_tls_bc_pkey_fprint) {
569
const char *myname = "tls_pkey_fprint";
570
ASN1_BIT_STRING *key;
573
key = X509_get0_pubkey_bitstr(peercert);
575
msg_fatal("%s: error extracting legacy public-key fingerprint: %m",
578
result = tls_fprint((char *) key->data, key->length, dgst);
586
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(peercert), NULL);
587
buf2 = buf = mymalloc(len);
588
i2d_X509_PUBKEY(X509_get_X509_PUBKEY(peercert), (unsigned char **) &buf2);
589
if (buf2 - buf != len)
590
msg_panic("i2d_X509_PUBKEY invalid result length");
592
result = tls_fprint(buf, len, dgst);