(BWDIC!) *user*: enforce it is not empty
[s-mailx.git] / xtls.c
blob1e86ba3933c18b363601350d9e635bfc7586b571
1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ OpenSSL client implementation according to: John Viega, Matt Messier,
3 *@ Pravir Chandra: Network Security with OpenSSL. Sebastopol, CA 2002.
4 *@ TODO This needs an overhaul -- there _are_ stack leaks!?
6 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
7 * Copyright (c) 2012 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
8 */
9 /*
10 * Copyright (c) 2002
11 * Gunnar Ritter. All rights reserved.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by Gunnar Ritter
24 * and his contributors.
25 * 4. Neither the name of Gunnar Ritter nor the names of his contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
41 #undef n_FILE
42 #define n_FILE xtls
44 #ifndef HAVE_AMALGAMATION
45 # include "nail.h"
46 #endif
48 EMPTY_FILE()
49 #ifdef HAVE_XTLS
50 #include <sys/socket.h>
52 #include <openssl/crypto.h>
53 #include <openssl/err.h>
54 #include <openssl/evp.h>
55 #include <openssl/opensslv.h>
56 #include <openssl/pem.h>
57 #include <openssl/rand.h>
58 #include <openssl/ssl.h>
59 #include <openssl/x509v3.h>
60 #include <openssl/x509.h>
62 #ifdef HAVE_XTLS_CONFIG
63 # include <openssl/conf.h>
64 #endif
66 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
67 # include <dirent.h>
68 #endif
70 /* Compatibility shims which assume 0/-1 cannot really happen */
71 #ifndef HAVE_XTLS_CONF_CTX
72 # ifndef SSL_OP_NO_SSLv2
73 # define SSL_OP_NO_SSLv2 0
74 # endif
75 # ifndef SSL_OP_NO_SSLv3
76 # define SSL_OP_NO_SSLv3 0
77 # endif
78 # ifndef SSL_OP_NO_TLSv1
79 # define SSL_OP_NO_TLSv1 0
80 # endif
81 # ifndef SSL_OP_NO_TLSv1_1
82 # define SSL_OP_NO_TLSv1_1 0
83 # endif
84 # ifndef SSL_OP_NO_TLSv1_2
85 # define SSL_OP_NO_TLSv1_2 0
86 # endif
87 # ifndef SSL_OP_NO_TLSv1_3
88 # define SSL_OP_NO_TLSv1_3 0
89 # endif
90 /* SSL_CONF_CTX and _OP_NO_SSL_MASK were both introduced with 1.0.2!?! */
91 # ifndef SSL_OP_NO_SSL_MASK
92 # define SSL_OP_NO_SSL_MASK \
93 (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |\
94 SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 |\
95 SSL_OP_NO_TLSv1_3)
96 # endif
98 # ifndef SSL2_VERSION
99 # define SSL2_VERSION 0
100 # endif
101 # ifndef SSL3_VERSION
102 # define SSL3_VERSION 0
103 # endif
104 # ifndef TLS1_VERSION
105 # define TLS1_VERSION 0
106 # endif
107 # ifndef TLS1_1_VERSION
108 # define TLS1_1_VERSION 0
109 # endif
110 # ifndef TLS1_2_VERSION
111 # define TLS1_2_VERSION 0
112 # endif
113 # ifndef TLS1_3_VERSION
114 # define TLS1_3_VERSION 0
115 # endif
116 #endif
118 #ifdef HAVE_XTLS_STACK_OF
119 # define n_XTLS_STACKOF(X) STACK_OF(X)
120 #else
121 # define n_XTLS_STACKOF(X) /*X*/STACK
122 #endif
124 #if OPENSSL_VERSION_NUMBER + 0 >= 0x0090581fL
125 # define a_XTLS_RAND_LOAD_FILE_MAXBYTES -1
126 #else
127 # define a_XTLS_RAND_LOAD_FILE_MAXBYTES 1024
128 #endif
130 /* Compatibility sighs (that sigh is _really_ a cute one) */
131 #if HAVE_XTLS_OPENSSL >= 0x10100
132 # define a_xtls_X509_get_notBefore X509_get0_notBefore
133 # define a_xtls_X509_get_notAfter X509_get0_notAfter
134 #else
135 # define a_xtls_X509_get_notBefore X509_get_notBefore
136 # define a_xtls_X509_get_notAfter X509_get_notAfter
137 #endif
139 /* X509_STORE_set_flags */
140 #undef a_XTLS_X509_V_ANY
141 #ifndef X509_V_FLAG_NO_ALT_CHAINS
142 # define X509_V_FLAG_NO_ALT_CHAINS -1
143 #else
144 # undef a_XTLS_X509_V_ANY
145 # define a_XTLS_X509_V_ANY
146 #endif
147 #ifndef X509_V_FLAG_NO_CHECK_TIME
148 # define X509_V_FLAG_NO_CHECK_TIME -1
149 #else
150 # undef a_XTLS_X509_V_ANY
151 # define a_XTLS_X509_V_ANY
152 #endif
153 #ifndef X509_V_FLAG_PARTIAL_CHAIN
154 # define X509_V_FLAG_PARTIAL_CHAIN -1
155 #else
156 # undef a_XTLS_X509_V_ANY
157 # define a_XTLS_X509_V_ANY
158 #endif
159 #ifndef X509_V_FLAG_X509_STRICT
160 # define X509_V_FLAG_X509_STRICT -1
161 #else
162 # undef a_XTLS_X509_V_ANY
163 # define a_XTLS_X509_V_ANY
164 #endif
165 #ifndef X509_V_FLAG_TRUSTED_FIRST
166 # define X509_V_FLAG_TRUSTED_FIRST -1
167 #else
168 # undef a_XTLS_X509_V_ANY
169 # define a_XTLS_X509_V_ANY
170 #endif
172 enum a_xtls_state{
173 a_XTLS_S_INIT = 1u<<0,
174 a_XTLS_S_RAND_INIT = 1u<<1,
175 a_XTLS_S_CONF_LOAD = 1u<<2,
177 #if HAVE_XTLS_OPENSSL < 0x10100
178 a_XTLS_S_EXIT_HDL = 1u<<8,
179 a_XTLS_S_ALGO_LOAD = 1u<<9,
180 #endif
182 a_XTLS_S_VERIFY_ERROR = 1u<<16
185 struct ssl_method { /* TODO v15 obsolete */
186 char const sm_name[8];
187 char const sm_map[16];
190 #ifndef HAVE_XTLS_CONF_CTX
191 struct a_xtls_protocol{
192 char const xp_name[8];
193 sl_i xp_op_no; /* SSL_OP_NO_* bit */
194 ui16_t xp_version; /* *_VERSION number */
195 bool_t xp_ok_minmaxproto; /* Valid for {Min,Max}Protocol= */
196 bool_t xp_ok_proto; /* Valid for Protocol= */
197 ui8_t xp__dummy[4];
199 #endif
201 struct a_xtls_cipher{
202 char const xc_name[8];
203 EVP_CIPHER const *(*xc_fun)(void);
206 struct a_xtls_digest{
207 char const xd_name[8];
208 EVP_MD const *(*xd_fun)(void);
211 struct a_xtls_x509_v_flags{
212 char const xxvf_name[20];
213 si32_t xxvf_flag;
216 /* Supported SSL/TLS methods: update manual on change! */
217 static struct ssl_method const _ssl_methods[] = { /* TODO obsolete */
218 {"auto", "ALL,-SSLv2"},
219 {"ssl3", "-ALL,SSLv3"},
220 {"tls1", "-ALL,TLSv1"},
221 {"tls1.1", "-ALL,TLSv1.1"},
222 {"tls1.2", "-ALL,TLSv1.2"}
225 /* Update manual on change!
226 * Ensure array size by adding \0 to longest entry.
227 * Strictly to be sorted new/up to old/down, [0]=ALL, [x-1]=None! */
228 #ifndef HAVE_XTLS_CONF_CTX
229 static struct a_xtls_protocol const a_xtls_protocols[] = {
230 {"ALL", SSL_OP_NO_SSL_MASK, 0, FAL0, TRU1, {0}},
231 {"TLSv1.3\0", SSL_OP_NO_TLSv1_3, TLS1_3_VERSION, TRU1, TRU1, {0}},
232 {"TLSv1.2", SSL_OP_NO_TLSv1_2, TLS1_2_VERSION, TRU1, TRU1, {0}},
233 {"TLSv1.1", SSL_OP_NO_TLSv1_1, TLS1_1_VERSION, TRU1, TRU1, {0}},
234 {"TLSv1", SSL_OP_NO_TLSv1, TLS1_VERSION, TRU1, TRU1, {0}},
235 {"SSLv3", SSL_OP_NO_SSLv3, SSL3_VERSION, TRU1, TRU1, {0}},
236 {"SSLv2", SSL_OP_NO_SSLv2, SSL2_VERSION, TRU1, TRU1, {0}},
237 {"None", SSL_OP_NO_SSL_MASK, 0, TRU1, FAL0, {0}}
239 #endif /* HAVE_XTLS_CONF_CTX */
241 /* Supported S/MIME cipher algorithms */
242 static struct a_xtls_cipher const a_xtls_ciphers[] = { /*Manual!*/
243 #ifndef OPENSSL_NO_AES
244 # define a_XTLS_SMIME_DEFAULT_CIPHER EVP_aes_128_cbc /* According RFC 5751 */
245 {"AES128", &EVP_aes_128_cbc},
246 {"AES256", &EVP_aes_256_cbc},
247 {"AES192", &EVP_aes_192_cbc},
248 #endif
249 #ifndef OPENSSL_NO_DES
250 # ifndef a_XTLS_SMIME_DEFAULT_CIPHER
251 # define a_XTLS_SMIME_DEFAULT_CIPHER EVP_des_ede3_cbc
252 # endif
253 {"DES3", &EVP_des_ede3_cbc},
254 {"DES", &EVP_des_cbc},
255 #endif
257 #ifndef a_XTLS_SMIME_DEFAULT_CIPHER
258 # error Your OpenSSL library does not include the necessary
259 # error cipher algorithms that are required to support S/MIME
260 #endif
262 #ifndef OPENSSL_NO_AES
263 /* TODO obsolete a_xtls_smime_ciphers_obs */
264 static struct a_xtls_cipher const a_xtls_smime_ciphers_obs[] = {
265 {"AES-128", &EVP_aes_128_cbc},
266 {"AES-256", &EVP_aes_256_cbc},
267 {"AES-192", &EVP_aes_192_cbc}
269 #endif
271 /* Supported S/MIME message digest algorithms */
272 static struct a_xtls_digest const a_xtls_digests[] = { /*Manual!*/
273 #define a_XTLS_SMIME_DEFAULT_DIGEST EVP_sha1 /* According to RFC 5751 */
274 #define a_XTLS_SMIME_DEFAULT_DIGEST_S "SHA1" /* Manual! */
275 #define a_XTLS_FINGERPRINT_DEFAULT_DIGEST EVP_sha256 /* Manual! */
276 #define a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S "SHA256" /* Manual! */
277 {"SHA1", &EVP_sha1},
278 {"SHA256", &EVP_sha256},
279 {"SHA512", &EVP_sha512},
280 {"SHA384", &EVP_sha384},
281 {"SHA224", &EVP_sha224},
282 #ifndef OPENSSL_NO_MD5
283 {"MD5", &EVP_md5},
284 #endif
287 /* X509_STORE_set_flags() for *{smime,ssl}-ca-flags* */
288 static struct a_xtls_x509_v_flags const a_xtls_x509_v_flags[] = { /* Manual! */
289 {"no-alt-chains", X509_V_FLAG_NO_ALT_CHAINS},
290 {"no-check-time", X509_V_FLAG_NO_CHECK_TIME},
291 {"partial-chain", X509_V_FLAG_PARTIAL_CHAIN},
292 {"strict", X509_V_FLAG_X509_STRICT},
293 {"trusted-first", X509_V_FLAG_TRUSTED_FIRST},
296 static enum a_xtls_state a_xtls_state;
297 static size_t a_xtls_msgno;
299 static void a_xtls_rand_init(void);
300 static void a_xtls_init(void);
302 #if HAVE_XTLS_OPENSSL < 0x10100
303 # ifdef HAVE_TLS_ALL_ALGORITHMS
304 static void a_xtls__load_algos(void);
305 # define a_xtls_load_algos a_xtls__load_algos
306 # endif
307 # if defined HAVE_XTLS_CONFIG || defined HAVE_TLS_ALL_ALGORITHMS
308 static void a_xtls_atexit(void);
309 # endif
310 #endif
311 #ifndef a_xtls_load_algos
312 # define a_xtls_load_algos() do{;}while(0)
313 #endif
315 static bool_t a_xtls_parse_asn1_time(ASN1_TIME const *atp,
316 char *bdat, size_t blen);
317 static int a_xtls_verify_cb(int success, X509_STORE_CTX *store);
319 static bool_t a_xtls_digest_find(char const *name, EVP_MD const **mdp,
320 char const **normalized_name_or_null);
322 /* *smime-ca-flags*, *tls-ca-flags* */
323 static void a_xtls_ca_flags(X509_STORE *store, char const *flags);
325 /* SSL_CTX configuration; the latter always NULLs *confp */
326 static void *a_xtls_conf_setup(SSL_CTX *ctxp, struct url const *urlp);
327 static bool_t a_xtls_conf(void *confp, char const *cmd, char const *value);
328 static bool_t a_xtls_conf_finish(void **confp, bool_t error);
330 static bool_t a_xtls_obsolete_conf_vars(void *confp, struct url const *urlp);
331 static bool_t a_xtls_config_pairs(void *confp, struct url const *urlp);
332 static bool_t a_xtls_load_verifications(SSL_CTX *ctxp, struct url const *urlp);
334 static bool_t a_xtls_check_host(struct sock *sp, X509 *peercert,
335 struct url const *urlp);
337 static int smime_verify(struct message *m, int n,
338 n_XTLS_STACKOF(X509) *chain, X509_STORE *store);
339 static EVP_CIPHER const * _smime_cipher(char const *name);
340 static int ssl_password_cb(char *buf, int size, int rwflag,
341 void *userdata);
342 static FILE * smime_sign_cert(char const *xname, char const *xname2,
343 bool_t dowarn, char const **match);
344 static char const * _smime_sign_include_certs(char const *name);
345 static bool_t _smime_sign_include_chain_creat(n_XTLS_STACKOF(X509) **chain,
346 char const *cfiles, char const *addr);
347 static EVP_MD const *a_xtls_smime_sign_digest(char const *name,
348 char const **digname);
349 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
350 static enum okay load_crl1(X509_STORE *store, char const *name);
351 #endif
352 static enum okay load_crls(X509_STORE *store, enum okeys fok, enum okeys dok);
354 static void
355 a_xtls_rand_init(void){
356 #define a_XTLS_RAND_ENTROPY 32
357 char b64buf[a_XTLS_RAND_ENTROPY * 5 +1], *randfile;
358 char const *cp, *x;
359 bool_t err;
360 NYD2_ENTER;
362 a_xtls_state |= a_XTLS_S_RAND_INIT;
364 err = TRU1;
365 randfile = NULL;
367 #ifdef HAVE_XTLS_CONFIG
368 if(!(a_xtls_state & a_XTLS_S_INIT))
369 a_xtls_init();
370 #endif
372 /* Prefer possible user setting */
373 if((cp = ok_vlook(tls_rand_file)) != NULL ||
374 (cp = ok_vlook(ssl_rand_file)) != NULL){
375 x = NULL;
376 if(*cp != '\0'){
377 if((x = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) == NULL)
378 n_err(_("*tls-rand-file*: expansion of %s failed "
379 "(using default)\n"),
380 n_shexp_quote_cp(cp, FAL0));
382 cp = x;
384 if(cp == NULL){
385 randfile = n_lofi_alloc(PATH_MAX);
386 if((cp = RAND_file_name(randfile, PATH_MAX)) == NULL){
387 n_err(_("*tls-rand-file*: no TLS entropy file, can't seed PRNG\n"));
388 goto jleave;
392 (void)RAND_load_file(cp, a_XTLS_RAND_LOAD_FILE_MAXBYTES);
394 /* And feed in some data, then write the updated file.
395 * While this rather feeds the PRNG with itself in the n_RANDOM_IMPL_TLS
396 * case, let us stir the buffer a little bit.
397 * Estimate a low but likely still too high number of entropy bytes, use
398 * 20%: base64 uses 3 input = 4 output bytes relation, and the base64
399 * alphabet is a 6 bit one */
400 for(x = (char*)-1;;){
401 RAND_add(n_random_create_buf(b64buf, sizeof(b64buf) -1, NULL),
402 sizeof(b64buf) -1, a_XTLS_RAND_ENTROPY);
403 if((x = (char*)((uintptr_t)x >> (1
404 #if HAVE_RANDOM == n_RANDOM_IMPL_TLS
406 #endif
407 ))) == NULL){
408 err = (RAND_status() == 0);
409 break;
411 #if HAVE_RANDOM != n_RANDOM_IMPL_TLS
412 if(!(err = (RAND_status() == 0)))
413 break;
414 #endif
417 if(!err)
418 err = (RAND_write_file(cp) == -1);
420 jleave:
421 if(randfile != NULL)
422 n_lofi_free(randfile);
423 if(err)
424 n_panic(_("Cannot seed the *TLS PseudoRandomNumberGenerator, "
425 "RAND_status() is 0!\n"
426 " Please set *tls-rand-file* to a file with sufficient entropy.\n"
427 " On a machine with entropy: "
428 "\"$ dd if=/dev/urandom of=FILE bs=1024 count=1\"\n"));
429 NYD2_LEAVE;
432 static void
433 a_xtls_init(void){
434 #ifdef HAVE_XTLS_CONFIG
435 char const *cp;
436 #endif
437 NYD2_ENTER;
439 if(a_xtls_state & a_XTLS_S_INIT)
440 goto jleave;
442 #if HAVE_XTLS_OPENSSL >= 0x10100
443 OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
444 OPENSSL_INIT_LOAD_CRYPTO_STRINGS
445 # ifdef HAVE_TLS_ALL_ALGORITHMS
446 | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS
447 # endif
448 , NULL);
449 #else
450 SSL_load_error_strings();
451 SSL_library_init();
452 a_xtls_load_algos();
453 #endif
454 a_xtls_state |= a_XTLS_S_INIT;
457 /* Load openssl.cnf or whatever was given in *tls-config-file* */
458 #ifdef HAVE_XTLS_CONFIG
459 if((cp = ok_vlook(tls_config_file)) != NULL ||
460 (cp = ok_vlook(ssl_config_file)) != NULL){
461 char const *msg;
462 ul_i flags;
464 if(*cp == '\0'){
465 msg = "[default]";
466 cp = NULL;
467 flags = CONF_MFLAGS_IGNORE_MISSING_FILE;
468 }else if((msg = cp, cp = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) != NULL)
469 flags = 0;
470 else{
471 n_err(_("*tls-config-file*: file expansion failed: %s\n"),
472 n_shexp_quote_cp(msg, FAL0));
473 goto jefile;
476 if(CONF_modules_load_file(cp, n_uagent, flags) == 1){
477 a_xtls_state |= a_XTLS_S_CONF_LOAD;
478 # if HAVE_XTLS_OPENSSL < 0x10100
479 if(!(a_xtls_state & a_XTLS_S_EXIT_HDL)){
480 a_xtls_state |= a_XTLS_S_EXIT_HDL;
481 atexit(&a_xtls_atexit); /* TODO generic program-wide event mech. */
483 # endif
484 if(n_poption & n_PO_D_V)
485 n_err(_("Loaded TLS configuration for %s from %s\n"), n_uagent,
486 n_shexp_quote_cp(msg, FAL0));
487 jefile:;
488 }else
489 ssl_gen_err(_("TLS CONF_modules_load_file() load error"));
491 #endif /* HAVE_XTLS_CONFIG */
493 if(!(a_xtls_state & a_XTLS_S_RAND_INIT))
494 a_xtls_rand_init();
495 jleave:
496 NYD2_LEAVE;
499 #if HAVE_XTLS_OPENSSL < 0x10100
500 # ifdef HAVE_TLS_ALL_ALGORITHMS
501 static void
502 a_xtls__load_algos(void){
503 NYD2_ENTER;
504 if(!(a_xtls_state & a_XTLS_S_ALGO_LOAD)){
505 a_xtls_state |= a_XTLS_S_ALGO_LOAD;
506 OpenSSL_add_all_algorithms();
508 if(!(a_xtls_state & a_XTLS_S_EXIT_HDL)){
509 a_xtls_state |= a_XTLS_S_EXIT_HDL;
510 atexit(&a_xtls_atexit); /* TODO generic program-wide event mech. */
513 NYD2_LEAVE;
515 # endif
517 # if defined HAVE_XTLS_CONFIG || defined HAVE_TLS_ALL_ALGORITHMS
518 static void
519 a_xtls_atexit(void){
520 NYD2_ENTER;
521 # ifdef HAVE_XTLS_CONFIG
522 if(a_xtls_state & a_XTLS_S_CONF_LOAD)
523 CONF_modules_free();
524 # endif
526 # ifdef HAVE_TLS_ALL_ALGORITHMS
527 if(a_xtls_state & a_XTLS_S_ALGO_LOAD)
528 EVP_cleanup();
529 # endif
530 NYD2_LEAVE;
532 # endif
533 #endif /* HAVE_XTLS_OPENSSL < 0x10100 */
535 static bool_t
536 a_xtls_parse_asn1_time(ASN1_TIME const *atp, char *bdat, size_t blen)
538 BIO *mbp;
539 char *mcp;
540 long l;
541 NYD_ENTER;
543 mbp = BIO_new(BIO_s_mem());
545 if (ASN1_TIME_print(mbp, atp) && (l = BIO_get_mem_data(mbp, &mcp)) > 0)
546 snprintf(bdat, blen, "%.*s", (int)l, mcp);
547 else {
548 snprintf(bdat, blen, _("Bogus certificate date: %.*s"),
549 /*is (int)*/atp->length, (char const*)atp->data);
550 mcp = NULL;
553 BIO_free(mbp);
554 NYD_LEAVE;
555 return (mcp != NULL);
558 static int
559 a_xtls_verify_cb(int success, X509_STORE_CTX *store)
561 char data[256];
562 X509 *cert;
563 int rv = TRU1;
564 NYD_ENTER;
566 if (success && !(n_poption & n_PO_D_V))
567 goto jleave;
569 if (a_xtls_msgno != 0) {
570 n_err(_("Message %lu:\n"), (ul_i)a_xtls_msgno);
571 a_xtls_msgno = 0;
573 n_err(_(" Certificate depth %d %s\n"),
574 X509_STORE_CTX_get_error_depth(store), (success ? n_empty : V_(n_error)));
576 if ((cert = X509_STORE_CTX_get_current_cert(store)) != NULL) {
577 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof data);
578 n_err(_(" subject = %s\n"), data);
580 a_xtls_parse_asn1_time(a_xtls_X509_get_notBefore(cert),
581 data, sizeof data);
582 n_err(_(" notBefore = %s\n"), data);
584 a_xtls_parse_asn1_time(a_xtls_X509_get_notAfter(cert),
585 data, sizeof data);
586 n_err(_(" notAfter = %s\n"), data);
588 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof data);
589 n_err(_(" issuer = %s\n"), data);
592 if (!success) {
593 int err = X509_STORE_CTX_get_error(store);
595 n_err(_(" err %i: %s\n"), err, X509_verify_cert_error_string(err));
596 a_xtls_state |= a_XTLS_S_VERIFY_ERROR;
599 if(!success)
600 rv = n_tls_verify_decide();
601 jleave:
602 NYD_LEAVE;
603 return rv;
606 static bool_t
607 a_xtls_digest_find(char const *name,
608 EVP_MD const **mdp, char const **normalized_name_or_null){
609 size_t i;
610 char *nn;
611 NYD2_ENTER;
613 /* C99 */{
614 char *cp, c;
616 i = strlen(name);
617 nn = cp = n_lofi_alloc(i +1);
618 while((c = *name++) != '\0')
619 *cp++ = upperconv(c);
620 *cp = '\0';
622 if(normalized_name_or_null != NULL)
623 *normalized_name_or_null = savestrbuf(nn, PTR2SIZE(cp - nn));
626 for(i = 0; i < n_NELEM(a_xtls_digests); ++i)
627 if(!strcmp(a_xtls_digests[i].xd_name, nn)){
628 *mdp = (*a_xtls_digests[i].xd_fun)();
629 goto jleave;
632 /* Not a built-in algorithm, but we may have dynamic support for more */
633 #ifdef HAVE_TLS_ALL_ALGORITHMS
634 if((*mdp = EVP_get_digestbyname(nn)) != NULL)
635 goto jleave;
636 #endif
638 n_err(_("Invalid message digest: %s\n"), n_shexp_quote_cp(nn, FAL0));
639 *mdp = NULL;
640 jleave:
641 n_lofi_free(nn);
643 NYD2_LEAVE;
644 return (*mdp != NULL);
647 static void
648 a_xtls_ca_flags(X509_STORE *store, char const *flags){
649 NYD2_ENTER;
650 if(flags != NULL){
651 char *iolist, *cp;
653 iolist = savestr(flags);
654 jouter:
655 while((cp = n_strsep(&iolist, ',', TRU1)) != NULL){
656 struct a_xtls_x509_v_flags const *xvfp;
658 for(xvfp = &a_xtls_x509_v_flags[0];
659 xvfp < &a_xtls_x509_v_flags[n_NELEM(a_xtls_x509_v_flags)];
660 ++xvfp)
661 if(!asccasecmp(cp, xvfp->xxvf_name)){
662 if(xvfp->xxvf_flag != -1){
663 #ifdef a_XTLS_X509_V_ANY
664 X509_STORE_set_flags(store, xvfp->xxvf_flag);
665 #endif
666 }else if(n_poption & n_PO_D_V)
667 n_err(_("*{smime,tls}-ca-flags*: "
668 "directive not supported: %s\n"), cp);
669 goto jouter;
671 n_err(_("*{smime,tls}-ca-flags*: invalid directive: %s\n"), cp);
674 NYD2_LEAVE;
677 #ifdef HAVE_XTLS_CONF_CTX
678 static void *
679 a_xtls_conf_setup(SSL_CTX *ctxp, struct url const *urlp){
680 char const *cp;
681 SSL_CONF_CTX *sccp;
682 NYD2_ENTER;
684 sccp = NULL;
686 if((cp = xok_vlook(tls_config_module, urlp, OXM_ALL)) != NULL ||
687 (cp = xok_vlook(ssl_config_module, urlp, OXM_ALL)) != NULL){
688 # ifdef HAVE_XTLS_CTX_CONFIG
689 if(!(a_xtls_state & a_XTLS_S_CONF_LOAD)){
690 n_err(_("*tls-config-module*: no *tls-config-file* loaded: %s\n"),
691 n_shexp_quote_cp(cp, FAL0));
692 goto jleave;
693 }else if(!SSL_CTX_config(ctxp, cp)){
694 ssl_gen_err(_("*tls-config-module*: load error for %s, section [%s]"),
695 n_uagent, n_shexp_quote_cp(cp, FAL0));
696 goto jleave;
698 # else
699 n_err(_("*tls-config-module*: set but not supported: %s\n"),
700 n_shexp_quote_cp(cp, FAL0));
701 goto jleave;
702 # endif
705 if((sccp = SSL_CONF_CTX_new()) != NULL){
706 SSL_CONF_CTX_set_flags(sccp,
707 SSL_CONF_FLAG_FILE | SSL_CONF_FLAG_CLIENT |
708 SSL_CONF_FLAG_CERTIFICATE | SSL_CONF_FLAG_SHOW_ERRORS);
710 SSL_CONF_CTX_set_ssl_ctx(sccp, ctxp);
711 }else
712 ssl_gen_err(_("SSL_CONF_CTX_new() failed"));
713 jleave:
714 NYD2_LEAVE;
715 return sccp;
718 static bool_t
719 a_xtls_conf(void *confp, char const *cmd, char const *value){
720 int rv;
721 SSL_CONF_CTX *sccp;
722 NYD2_ENTER;
724 if(n_poption & n_PO_D_V)
725 n_err(_("TLS: applying config: %s = %s\n"),
726 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(value, FAL0));
728 rv = SSL_CONF_cmd(sccp = confp, cmd, value);
729 if(rv == 2)
730 rv = 0;
731 else{
732 cmd = n_shexp_quote_cp(cmd, FAL0);
733 value = n_shexp_quote_cp(value, FAL0);
734 if(rv == 0)
735 ssl_gen_err(_("TLS: config failure: %s = %s"), cmd, value);
736 else{
737 char const *err;
739 switch(rv){
740 case -2: err = N_("TLS: config command not recognized"); break;
741 case -3: err = N_("TLS: missing required config argument"); break;
742 default: err = N_("TLS: unspecified config error"); break;
744 err = V_(err);
745 n_err(_("%s (%d): %s = %s\n"), err, rv, cmd, value);
747 rv = 1;
749 NYD2_LEAVE;
750 return (rv == 0);
753 static bool_t
754 a_xtls_conf_finish(void **confp, bool_t error){
755 SSL_CONF_CTX *sccp;
756 bool_t rv;
757 NYD2_ENTER;
759 sccp = (SSL_CONF_CTX*)*confp;
760 *confp = NULL;
762 if(!(rv = error))
763 rv = (SSL_CONF_CTX_finish(sccp) != 0);
765 SSL_CONF_CTX_free(sccp);
766 NYD2_LEAVE;
767 return rv;
770 #else /* HAVE_XTLS_CONF_CTX */
771 # ifdef HAVE_XTLS_CTX_CONFIG
772 # error SSL_CTX_config(3) support unexpected without SSL_CONF_CTX support
773 # endif
775 static void *
776 a_xtls_conf_setup(SSL_CTX* ctxp, struct url const *urlp){
777 char const *cp;
778 NYD2_ENTER;
780 if((cp = xok_vlook(tls_config_module, urlp, OXM_ALL)) != NULL ||
781 (cp = xok_vlook(ssl_config_module, urlp, OXM_ALL)) != NULL){
782 n_err(_("*tls-config-module*: set but not supported: %s\n"),
783 n_shexp_quote_cp(cp, FAL0));
784 ctxp = NULL;
786 NYD2_LEAVE;
787 return ctxp;
790 static bool_t
791 a_xtls_conf(void *confp, char const *cmd, char const *value){
792 char const *xcmd, *emsg;
793 SSL_CTX *ctxp;
794 NYD2_ENTER;
796 if(n_poption & n_PO_D_V)
797 n_err(_("TLS: applying config: %s = %s\n"),
798 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(value, FAL0));
800 ctxp = confp;
802 if(!asccasecmp(cmd, xcmd = "Certificate")){
803 if(SSL_CTX_use_certificate_chain_file(ctxp, value) != 1){
804 emsg = N_("TLS: %s: cannot load from file %s\n");
805 goto jerr;
807 }else if(!asccasecmp(cmd, xcmd = "CipherString") ||
808 !asccasecmp(cmd, xcmd = "CipherList")/* grr, bad fault in past! */){
809 if(SSL_CTX_set_cipher_list(ctxp, value) != 1){
810 emsg = N_("TLS: %s: invalid: %s\n");
811 goto jerr;
813 }else if(!asccasecmp(cmd, xcmd = "Ciphersuites")){
814 #ifdef HAVE_XTLS_SET_CIPHERSUITES
815 if(SSL_CTX_set_ciphersuites(ctxp, value) != 1){
816 emsg = N_("TLS: %s: invalid: %s\n");
817 goto jerr;
819 #else
820 value = NULL;
821 emsg = N_("TLS: %s: directive not supported\n");
822 goto jxerr;
823 #endif
824 }else if(!asccasecmp(cmd, xcmd = "Curves")){
825 #ifdef SSL_CTRL_SET_CURVES_LIST
826 if(SSL_CTX_set1_curves_list(ctxp, value) != 1){
827 emsg = N_("TLS: %s: invalid: %s\n");
828 goto jerr;
830 #else
831 value = NULL;
832 emsg = N_("TLS: %s: directive not supported\n");
833 goto jxerr;
834 #endif
835 }else if((emsg = NULL, !asccasecmp(cmd, xcmd = "MaxProtocol")) ||
836 (emsg = (char*)-1, !asccasecmp(cmd, xcmd = "MinProtocol"))){
837 #ifndef HAVE_XTLS_SET_MIN_PROTO_VERSION
838 value = NULL;
839 emsg = N_("TLS: %s: directive not supported\n");
840 goto jxerr;
841 #else
842 struct a_xtls_protocol const *xpp;
843 size_t i;
845 for(i = 1 /* [0] == ALL */;;){
846 xpp = &a_xtls_protocols[i];
848 if(xpp->xp_ok_minmaxproto && !asccasecmp(value, xpp->xp_name))
849 break;
851 if(++i >= n_NELEM(a_xtls_protocols)){
852 emsg = N_("TLS: %s: unsupported element: %s\n");
853 goto jxerr;
857 if((emsg == NULL ? SSL_CTX_set_max_proto_version(ctxp, xpp->xp_version)
858 : SSL_CTX_set_min_proto_version(ctxp, xpp->xp_version)) != 1){
859 emsg = N_("TLS: %s: invalid protocol: %s\n");
860 goto jerr;
862 #endif /* !HAVE_XTLS_SET_MIN_PROTO_VERSION */
863 }else if(!asccasecmp(cmd, xcmd = "Options")){
864 if(asccasecmp(value, "Bugs")){
865 emsg = N_("TLS: %s: fallback only supports value \"Bugs\": %s\n");
866 goto jxerr;
868 SSL_CTX_set_options(ctxp, SSL_OP_ALL);
869 }else if(!asccasecmp(cmd, xcmd = "PrivateKey")){
870 if(SSL_CTX_use_PrivateKey_file(ctxp, value, SSL_FILETYPE_PEM) != 1){
871 emsg = N_("%s: cannot load from file %s\n");
872 goto jerr;
874 }else if(!asccasecmp(cmd, xcmd = "Protocol")){
875 char *iolist, *cp, addin;
876 size_t i;
877 sl_i opts;
879 opts = 0;
881 for(iolist = cp = savestr(value);
882 (cp = n_strsep(&iolist, ',', FAL0)) != NULL;){
883 if(*cp == '\0'){
884 value = NULL;
885 emsg = N_("TLS: %s: empty elements are not supported\n");
886 goto jxerr;
889 addin = TRU1;
890 switch(cp[0]){
891 case '-': addin = FAL0; /* FALLTHRU */
892 case '+': ++cp; /* FALLTHRU */
893 default : break;
896 for(i = 0;;){
897 struct a_xtls_protocol const *xpp;
899 xpp = &a_xtls_protocols[i];
901 if(xpp->xp_ok_proto && !asccasecmp(cp, xpp->xp_name)){
902 /* We need to inverse the meaning of the _NO_s */
903 if(!addin)
904 opts |= xpp->xp_op_no;
905 else
906 opts &= ~xpp->xp_op_no;
907 break;
910 if(++i >= n_NELEM(a_xtls_protocols)){
911 emsg = N_("TLS: %s: unsupported element: %s\n");
912 goto jxerr;
917 SSL_CTX_clear_options(ctxp, SSL_OP_NO_SSL_MASK);
918 SSL_CTX_set_options(ctxp, opts);
919 }else{
920 xcmd = n_shexp_quote_cp(cmd, FAL0);
921 emsg = N_("TLS: unsupported directive: %s: value: %s\n");
922 goto jxerr;
925 jleave:
926 NYD2_LEAVE;
927 return (confp != NULL);
928 jerr:
929 ssl_gen_err(V_(emsg), xcmd, n_shexp_quote_cp(value, FAL0));
930 confp = NULL;
931 goto jleave;
932 jxerr:
933 if(value != NULL)
934 value = n_shexp_quote_cp(value, FAL0);
935 n_err(V_(emsg), xcmd, value);
936 confp = NULL;
937 goto jleave;
940 static bool_t
941 a_xtls_conf_finish(void **confp, bool_t error){
942 n_UNUSED(confp);
943 n_UNUSED(error);
944 *confp = NULL;
945 return TRU1;
947 #endif /* !HAVE_XTLS_CONF_CTX */
949 static bool_t
950 a_xtls_obsolete_conf_vars(void *confp, struct url const *urlp){
951 char const *cp, *cp_base, *certchain;
952 bool_t rv;
953 NYD2_ENTER;
955 rv = FAL0;
957 /* Certificate via ssl-cert */
958 if((certchain = cp = xok_vlook(ssl_cert, urlp, OXM_ALL)) != NULL){
959 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-cert*"));
960 if((cp_base = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) == NULL){
961 n_err(_("*ssl-cert* value expansion failed: %s\n"),
962 n_shexp_quote_cp(cp, FAL0));
963 goto jleave;
965 if(!a_xtls_conf(confp, "Certificate", certchain = cp_base))
966 goto jleave;
969 /* CipherString via ssl-ciper-list */
970 if((cp = xok_vlook(ssl_cipher_list, urlp, OXM_ALL)) != NULL){
971 n_OBSOLETE(_("please use *tls-config-pairs* instead of "
972 "*ssl-cipher-list*"));
973 if(!a_xtls_conf(confp, "CipherString", cp))
974 goto jleave;
977 /* Curves via ssl-curves */
978 if((cp = xok_vlook(ssl_curves, urlp, OXM_ALL)) != NULL){
979 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-curves*"));
980 if(!a_xtls_conf(confp, "Curves", cp))
981 goto jleave;
984 /* PrivateKey via ssl-key */
985 if((cp = xok_vlook(ssl_key, urlp, OXM_ALL)) != NULL){
986 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-key*"));
987 if((cp_base = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) == NULL){
988 n_err(_("*ssl-key* value expansion failed: %s\n"),
989 n_shexp_quote_cp(cp, FAL0));
990 goto jleave;
992 cp = cp_base;
993 if(certchain == NULL){
994 n_err(_("*ssl-key* can only be used together with *ssl-cert*! "
995 "And use *ssl-config-pairs*!\n"));
996 goto jleave;
999 if((cp != NULL || (cp = certchain) != NULL) &&
1000 !a_xtls_conf(confp, "PrivateKey", cp))
1001 goto jleave;
1003 /* Protocol via ssl-method or ssl-protocol */
1004 if((cp = xok_vlook(ssl_method, urlp, OXM_ALL)) != NULL){
1005 size_t i;
1007 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-method*"));
1008 for(i = 0;;){
1009 if(!asccasecmp(_ssl_methods[i].sm_name, cp)){
1010 cp = _ssl_methods[i].sm_map;
1011 break;
1013 if(++i == n_NELEM(_ssl_methods)){
1014 n_err(_("Unsupported SSL method: %s\n"), cp);
1015 goto jleave;
1019 if((cp_base = xok_vlook(ssl_protocol, urlp, OXM_ALL)) != NULL){
1020 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-protocol*"));
1021 if(cp != NULL && (n_poption & n_PO_D_V))
1022 n_err(_("*ssl-protocol* overrides *ssl-method*! "
1023 "And please use *tls-config-pairs* instead!\n"));
1024 cp = cp_base;
1026 if(cp != NULL && !a_xtls_conf(confp, "Protocol", cp))
1027 goto jleave;
1029 rv = TRU1;
1030 jleave:
1031 NYD2_LEAVE;
1032 return rv;
1035 static bool_t
1036 a_xtls_config_pairs(void *confp, struct url const *urlp){
1037 /* Due to interdependencies some commands have to be delayed a bit */
1038 static char const cmdcert[] = "Certificate", cmdprivkey[] = "PrivateKey";
1039 char const *valcert, *valprivkey;
1040 char *pairs, *cp, *cmd, *val;
1041 NYD2_ENTER;
1043 if((pairs = n_UNCONST(xok_vlook(tls_config_pairs, urlp, OXM_ALL))
1044 ) == NULL &&
1045 (pairs = n_UNCONST(xok_vlook(ssl_config_pairs, urlp, OXM_ALL))
1046 ) == NULL)
1047 goto jleave;
1048 pairs = savestr(pairs);
1050 valcert = valprivkey = NULL;
1052 while((cp = n_strsep_esc(&pairs, ',', FAL0)) != NULL){
1053 char c;
1054 enum{
1055 a_NONE,
1056 a_EXPAND = 1u<<0,
1057 a_CERT = 1u<<1,
1058 a_PRIVKEY = 1u<<2,
1059 a_EXPAND_MASK = a_EXPAND | a_CERT | a_PRIVKEY
1060 } f;
1062 /* Directive, space trimmed */
1063 if((cmd = strchr(cp, '=')) == NULL){
1064 jenocmd:
1065 if(pairs == NULL)
1066 pairs = n_UNCONST(n_empty);
1067 n_err(_("*tls-config-pairs*: missing directive: %s; rest: %s\n"),
1068 n_shexp_quote_cp(cp, FAL0), n_shexp_quote_cp(pairs, FAL0));
1069 goto jleave;
1071 val = &cmd[1];
1073 if((cmd > cp && cmd[-1] == '*')){
1074 --cmd;
1075 f = a_EXPAND;
1076 }else
1077 f = a_NONE;
1078 while(cmd > cp && (c = cmd[-1], blankspacechar(c)))
1079 --cmd;
1080 if(cmd == cp)
1081 goto jenocmd;
1082 *cmd = '\0';
1083 cmd = cp;
1085 /* Command with special treatment? */
1086 if(!asccasecmp(cmd, cmdcert))
1087 f |= a_CERT;
1088 else if(!asccasecmp(cmd, cmdprivkey))
1089 f |= a_PRIVKEY;
1091 /* Value, space trimmed */
1092 while((c = *val) != '\0' && blankspacechar(c))
1093 ++val;
1094 cp = &val[strlen(val)];
1095 while(cp > val && (c = cp[-1], blankspacechar(c)))
1096 --cp;
1097 *cp = '\0';
1098 if(cp == val){
1099 if(pairs == NULL)
1100 pairs = n_UNCONST(n_empty);
1101 n_err(_("*tls-config-pairs*: missing value: %s; rest: %s\n"),
1102 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(pairs, FAL0));
1103 goto jleave;
1106 /* Filename transformations to be applied? */
1107 if(f & a_EXPAND_MASK){
1108 if((cp = fexpand(val, FEXP_LOCAL | FEXP_NOPROTO)) == NULL){
1109 if(pairs == NULL)
1110 pairs = n_UNCONST(n_empty);
1111 n_err(_("*tls-config-pairs*: value expansion failed: %s: %s; "
1112 "rest: %s\n"),
1113 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(val, FAL0),
1114 n_shexp_quote_cp(pairs, FAL0));
1115 goto jleave;
1117 val = cp;
1120 /* Some things have to be delayed */
1121 if(f & a_CERT)
1122 valcert = val;
1123 else if(f & a_PRIVKEY)
1124 valprivkey = val;
1125 else if(!a_xtls_conf(confp, cmd, val)){
1126 pairs = n_UNCONST(n_empty);
1127 goto jleave;
1131 /* Work the delayed ones */
1132 if((valcert != NULL && !a_xtls_conf(confp, cmdcert, valcert)) ||
1133 ((valprivkey != NULL || (valprivkey = valcert) != NULL) &&
1134 !a_xtls_conf(confp, cmdprivkey, valprivkey)))
1135 pairs = n_UNCONST(n_empty);
1137 jleave:
1138 NYD2_LEAVE;
1139 return (pairs == NULL);
1142 static bool_t
1143 a_xtls_load_verifications(SSL_CTX *ctxp, struct url const *urlp){
1144 char *ca_dir, *ca_file;
1145 X509_STORE *store;
1146 bool_t rv;
1147 NYD2_ENTER;
1149 if(n_tls_verify_level == n_TLS_VERIFY_IGNORE){
1150 rv = TRU1;
1151 goto jleave;
1153 rv = FAL0;
1155 if((ca_dir = xok_vlook(tls_ca_dir, urlp, OXM_ALL)) != NULL ||
1156 (ca_dir = xok_vlook(ssl_ca_dir, urlp, OXM_ALL)) != NULL)
1157 ca_dir = fexpand(ca_dir, FEXP_LOCAL | FEXP_NOPROTO);
1158 if((ca_file = xok_vlook(tls_ca_file, urlp, OXM_ALL)) != NULL ||
1159 (ca_file = xok_vlook(ssl_ca_file, urlp, OXM_ALL)) != NULL)
1160 ca_file = fexpand(ca_file, FEXP_LOCAL | FEXP_NOPROTO);
1162 if((ca_dir != NULL || ca_file != NULL) &&
1163 SSL_CTX_load_verify_locations(ctxp, ca_file, ca_dir) != 1){
1164 char const *m1, *m2, *m3;
1166 if(ca_dir != NULL){
1167 m1 = ca_dir;
1168 m2 = (ca_file != NULL) ? _(" or ") : n_empty;
1169 }else
1170 m1 = m2 = n_empty;
1171 m3 = (ca_file != NULL) ? ca_file : n_empty;
1172 ssl_gen_err(_("Error loading %s%s%s\n"), m1, m2, m3);
1173 goto jleave;
1176 /* C99 */{
1177 bool_t xv15;
1179 if((xv15 = ok_blook(ssl_no_default_ca)))
1180 n_OBSOLETE(_("please use *tls-ca-no-defaults*, "
1181 "not *ssl-no-default-ca*"));
1182 if(!xok_blook(tls_ca_no_defaults, urlp, OXM_ALL) &&
1183 !xok_blook(ssl_ca_no_defaults, urlp, OXM_ALL) && !xv15 &&
1184 SSL_CTX_set_default_verify_paths(ctxp) != 1) {
1185 ssl_gen_err(_("Error loading built-in default CA locations\n"));
1186 goto jleave;
1190 a_xtls_state &= ~a_XTLS_S_VERIFY_ERROR;
1191 a_xtls_msgno = 0;
1192 SSL_CTX_set_verify(ctxp, SSL_VERIFY_PEER, &a_xtls_verify_cb);
1193 store = SSL_CTX_get_cert_store(ctxp);
1194 load_crls(store, ok_v_tls_crl_file, ok_v_tls_crl_dir);
1195 a_xtls_ca_flags(store, xok_vlook(tls_ca_flags, urlp, OXM_ALL));
1196 a_xtls_ca_flags(store, xok_vlook(ssl_ca_flags, urlp, OXM_ALL));
1198 rv = TRU1;
1199 jleave:
1200 NYD2_LEAVE;
1201 return rv;
1204 static bool_t
1205 a_xtls_check_host(struct sock *sp, X509 *peercert, struct url const *urlp){
1206 char data[256];
1207 n_XTLS_STACKOF(GENERAL_NAME) *gens;
1208 GENERAL_NAME *gen;
1209 X509_NAME *subj;
1210 bool_t rv;
1211 NYD_ENTER;
1212 n_UNUSED(sp);
1214 rv = FAL0;
1216 if((gens = X509_get_ext_d2i(peercert, NID_subject_alt_name, NULL, NULL)
1217 ) != NULL){
1218 int i;
1220 for(i = 0; i < sk_GENERAL_NAME_num(gens); ++i){
1221 gen = sk_GENERAL_NAME_value(gens, i);
1222 if(gen->type == GEN_DNS){
1223 if(n_poption & n_PO_D_V)
1224 n_err(_("Comparing subject_alt_name: need<%s> is<%s>\n"),
1225 urlp->url_host.s, (char*)gen->d.ia5->data);
1226 if((rv = n_tls_rfc2595_hostname_match(urlp->url_host.s,
1227 (char*)gen->d.ia5->data)))
1228 goto jleave;
1233 if((subj = X509_get_subject_name(peercert)) != NULL &&
1234 X509_NAME_get_text_by_NID(subj, NID_commonName, data, sizeof data
1235 ) > 0){
1236 data[sizeof data - 1] = '\0';
1237 if(n_poption & n_PO_D_V)
1238 n_err(_("Comparing commonName: need<%s> is<%s>\n"),
1239 urlp->url_host.s, data);
1240 rv = n_tls_rfc2595_hostname_match(urlp->url_host.s, data);
1242 jleave:
1243 NYD_LEAVE;
1244 return rv;
1247 static int
1248 smime_verify(struct message *m, int n, n_XTLS_STACKOF(X509) *chain,
1249 X509_STORE *store)
1251 char data[LINESIZE], *sender, *to, *cc, *cnttype;
1252 int rv, c, i, j;
1253 struct message *x;
1254 FILE *fp, *ip;
1255 off_t size;
1256 BIO *fb, *pb;
1257 PKCS7 *pkcs7;
1258 n_XTLS_STACKOF(X509) *certs;
1259 n_XTLS_STACKOF(GENERAL_NAME) *gens;
1260 X509 *cert;
1261 X509_NAME *subj;
1262 GENERAL_NAME *gen;
1263 NYD_ENTER;
1265 rv = 1;
1266 fp = NULL;
1267 fb = pb = NULL;
1268 pkcs7 = NULL;
1269 certs = NULL;
1270 a_xtls_state &= ~a_XTLS_S_VERIFY_ERROR;
1271 a_xtls_msgno = (size_t)n;
1273 for (;;) {
1274 sender = getsender(m);
1275 to = hfield1("to", m);
1276 cc = hfield1("cc", m);
1277 cnttype = hfield1("content-type", m);
1279 #undef _X
1280 #undef _Y
1281 #define _X (sizeof("application/") -1)
1282 #define _Y(X) X, sizeof(X) -1
1283 if (cnttype && is_asccaseprefix("application/", cnttype) &&
1284 (!ascncasecmp(cnttype + _X, _Y("pkcs7-mime")) ||
1285 !ascncasecmp(cnttype + _X, _Y("x-pkcs7-mime")))) {
1286 #undef _Y
1287 #undef _X
1288 if ((x = smime_decrypt(m, to, cc, 1)) == NULL)
1289 goto jleave;
1290 if (x != (struct message*)-1) {
1291 m = x;
1292 continue;
1296 if ((ip = setinput(&mb, m, NEED_BODY)) == NULL)
1297 goto jleave;
1298 size = m->m_size;
1299 break;
1302 if ((fp = Ftmp(NULL, "smimever", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
1303 NULL) {
1304 n_perr(_("tempfile"), 0);
1305 goto jleave;
1307 while (size-- > 0) {
1308 c = getc(ip);
1309 putc(c, fp);
1311 fflush_rewind(fp);
1313 if ((fb = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
1314 ssl_gen_err(_(
1315 "Error creating BIO verification object for message %d"), n);
1316 goto jleave;
1319 if ((pkcs7 = SMIME_read_PKCS7(fb, &pb)) == NULL) {
1320 ssl_gen_err(_("Error reading PKCS#7 object for message %d"), n);
1321 goto jleave;
1323 if (PKCS7_verify(pkcs7, chain, store, pb, NULL, 0) != 1) {
1324 ssl_gen_err(_("Error verifying message %d"), n);
1325 goto jleave;
1328 if (sender == NULL) {
1329 n_err(_("Warning: Message %d has no sender\n"), n);
1330 rv = 0;
1331 goto jleave;
1334 certs = PKCS7_get0_signers(pkcs7, chain, 0);
1335 if (certs == NULL) {
1336 n_err(_("No certificates found in message %d\n"), n);
1337 goto jleave;
1340 for (i = 0; i < sk_X509_num(certs); ++i) {
1341 cert = sk_X509_value(certs, i);
1342 gens = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
1343 if (gens != NULL) {
1344 for (j = 0; j < sk_GENERAL_NAME_num(gens); ++j) {
1345 gen = sk_GENERAL_NAME_value(gens, j);
1346 if (gen->type == GEN_EMAIL) {
1347 if (n_poption & n_PO_D_V)
1348 n_err(_("Comparing subject_alt_name: need<%s> is<%s>)\n"),
1349 sender, (char*)gen->d.ia5->data);
1350 if (!asccasecmp((char*)gen->d.ia5->data, sender))
1351 goto jfound;
1356 if ((subj = X509_get_subject_name(cert)) != NULL &&
1357 X509_NAME_get_text_by_NID(subj, NID_pkcs9_emailAddress,
1358 data, sizeof data) > 0) {
1359 data[sizeof data -1] = '\0';
1360 if (n_poption & n_PO_D_V)
1361 n_err(_("Comparing emailAddress: need<%s> is<%s>\n"),
1362 sender, data);
1363 if (!asccasecmp(data, sender))
1364 goto jfound;
1367 n_err(_("Message %d: certificate does not match <%s>\n"), n, sender);
1368 goto jleave;
1369 jfound:
1370 rv = ((a_xtls_state & a_XTLS_S_VERIFY_ERROR) != 0);
1371 if (!rv)
1372 fprintf(n_stdout, _("Message %d was verified successfully\n"), n);
1373 jleave:
1374 if (certs != NULL)
1375 sk_X509_free(certs);
1376 if (pb != NULL)
1377 BIO_free(pb);
1378 if (fb != NULL)
1379 BIO_free(fb);
1380 if (pkcs7 != NULL)
1381 PKCS7_free(pkcs7);
1382 if (fp != NULL)
1383 Fclose(fp);
1384 NYD_LEAVE;
1385 return rv;
1388 static EVP_CIPHER const *
1389 _smime_cipher(char const *name)
1391 EVP_CIPHER const *cipher;
1392 char *vn;
1393 char const *cp;
1394 size_t i;
1395 NYD_ENTER;
1397 vn = n_lofi_alloc(i = strlen(name) + sizeof("smime-cipher-") -1 +1);
1398 snprintf(vn, (int)i, "smime-cipher-%s", name);
1399 cp = n_var_vlook(vn, FAL0);
1400 n_lofi_free(vn);
1402 if (cp == NULL && (cp = ok_vlook(smime_cipher)) == NULL) {
1403 cipher = a_XTLS_SMIME_DEFAULT_CIPHER();
1404 goto jleave;
1406 cipher = NULL;
1408 for(i = 0; i < n_NELEM(a_xtls_ciphers); ++i)
1409 if(!asccasecmp(a_xtls_ciphers[i].xc_name, cp)){
1410 cipher = (*a_xtls_ciphers[i].xc_fun)();
1411 goto jleave;
1413 #ifndef OPENSSL_NO_AES
1414 for (i = 0; i < n_NELEM(a_xtls_smime_ciphers_obs); ++i) /* TODO obsolete */
1415 if (!asccasecmp(a_xtls_smime_ciphers_obs[i].xc_name, cp)) {
1416 n_OBSOLETE2(_("*smime-cipher* names with hyphens will vanish"), cp);
1417 cipher = (*a_xtls_smime_ciphers_obs[i].xc_fun)();
1418 goto jleave;
1420 #endif
1422 /* Not a built-in algorithm, but we may have dynamic support for more */
1423 #ifdef HAVE_TLS_ALL_ALGORITHMS
1424 if((cipher = EVP_get_cipherbyname(cp)) != NULL)
1425 goto jleave;
1426 #endif
1428 n_err(_("Invalid S/MIME cipher(s): %s\n"), cp);
1429 jleave:
1430 NYD_LEAVE;
1431 return cipher;
1434 static int
1435 ssl_password_cb(char *buf, int size, int rwflag, void *userdata)
1437 char *pass;
1438 size_t len;
1439 NYD_ENTER;
1440 n_UNUSED(rwflag);
1441 n_UNUSED(userdata);
1443 /* New-style */
1444 if(userdata != NULL){
1445 struct url url;
1446 struct ccred cred;
1448 if(url_parse(&url, CPROTO_CCRED, userdata)){
1449 if(ccred_lookup(&cred, &url)){
1450 ssize_t slen;
1452 if((slen = n_strscpy(buf, cred.cc_pass.s, size)) >= 0){
1453 size = (int)slen;
1454 goto jleave;
1457 size = 0;
1458 goto jleave;
1462 /* Old-style */
1463 if ((pass = getpassword("PEM pass phrase:")) != NULL) {
1464 len = strlen(pass);
1465 if (UICMP(z, len, >=, size))
1466 len = size -1;
1467 memcpy(buf, pass, len);
1468 buf[len] = '\0';
1469 size = (int)len;
1470 } else
1471 size = 0;
1472 jleave:
1473 NYD_LEAVE;
1474 return size;
1477 static FILE *
1478 smime_sign_cert(char const *xname, char const *xname2, bool_t dowarn,
1479 char const **match)
1481 char *vn;
1482 int vs;
1483 struct name *np;
1484 char const *name = xname, *name2 = xname2, *cp;
1485 FILE *fp = NULL;
1486 NYD_ENTER;
1488 jloop:
1489 if (name) {
1490 np = lextract(name, GTO | GSKIN);
1491 while (np != NULL) {
1492 /* This needs to be more intelligent since it will currently take the
1493 * first name for which a private key is available regardless of
1494 * whether it is the right one for the message */
1495 vn = n_lofi_alloc(vs = strlen(np->n_name) + 30);
1496 snprintf(vn, vs, "smime-sign-cert-%s", np->n_name);
1497 cp = n_var_vlook(vn, FAL0);
1498 n_lofi_free(vn);
1499 if (cp != NULL) {
1500 if (match != NULL)
1501 *match = np->n_name;
1502 goto jopen;
1504 np = np->n_flink;
1506 if (name2 != NULL) {
1507 name = name2;
1508 name2 = NULL;
1509 goto jloop;
1513 if ((cp = ok_vlook(smime_sign_cert)) == NULL)
1514 goto jerr;
1515 if(match != NULL)
1516 *match = NULL;
1517 jopen:
1518 if ((cp = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) == NULL)
1519 goto jleave;
1520 if ((fp = Fopen(cp, "r")) == NULL)
1521 n_perr(cp, 0);
1522 jleave:
1523 NYD_LEAVE;
1524 return fp;
1525 jerr:
1526 if (dowarn)
1527 n_err(_("Could not find a certificate for %s%s%s\n"),
1528 xname, (xname2 != NULL ? _("or ") : n_empty),
1529 (xname2 != NULL ? xname2 : n_empty));
1530 goto jleave;
1533 static char const *
1534 _smime_sign_include_certs(char const *name)
1536 char const *rv;
1537 NYD_ENTER;
1539 /* See comments in smime_sign_cert() for algorithm pitfalls */
1540 if (name != NULL) {
1541 struct name *np;
1543 for (np = lextract(name, GTO | GSKIN); np != NULL; np = np->n_flink) {
1544 int vs;
1545 char *vn;
1547 vn = n_lofi_alloc(vs = strlen(np->n_name) + 30);
1548 snprintf(vn, vs, "smime-sign-include-certs-%s", np->n_name);
1549 rv = n_var_vlook(vn, FAL0);
1550 n_lofi_free(vn);
1551 if (rv != NULL)
1552 goto jleave;
1555 rv = ok_vlook(smime_sign_include_certs);
1556 jleave:
1557 NYD_LEAVE;
1558 return rv;
1561 static bool_t
1562 _smime_sign_include_chain_creat(n_XTLS_STACKOF(X509) **chain,
1563 char const *cfiles, char const *addr)
1565 X509 *tmp;
1566 FILE *fp;
1567 char *nfield, *cfield, *x;
1568 NYD_ENTER;
1570 *chain = sk_X509_new_null();
1572 for (nfield = savestr(cfiles);
1573 (cfield = n_strsep(&nfield, ',', TRU1)) != NULL;) {
1574 if ((x = fexpand(cfield, FEXP_LOCAL | FEXP_NOPROTO)) == NULL ||
1575 (fp = Fopen(cfield = x, "r")) == NULL) {
1576 n_perr(cfiles, 0);
1577 goto jerr;
1579 if ((tmp = PEM_read_X509(fp, NULL, &ssl_password_cb, n_UNCONST(addr))
1580 ) == NULL) {
1581 ssl_gen_err(_("Error reading certificate from %s"),
1582 n_shexp_quote_cp(cfield, FAL0));
1583 Fclose(fp);
1584 goto jerr;
1586 sk_X509_push(*chain, tmp);
1587 Fclose(fp);
1590 if (sk_X509_num(*chain) == 0) {
1591 n_err(_("*smime-sign-include-certs* defined but empty\n"));
1592 goto jerr;
1594 jleave:
1595 NYD_LEAVE;
1596 return (*chain != NULL);
1597 jerr:
1598 sk_X509_pop_free(*chain, X509_free);
1599 *chain = NULL;
1600 goto jleave;
1603 static EVP_MD const *
1604 a_xtls_smime_sign_digest(char const *name, char const **digname){
1605 EVP_MD const *digest;
1606 char const *cp;
1607 NYD2_ENTER;
1609 /* See comments in smime_sign_cert() for algorithm pitfalls */
1610 if(name != NULL){
1611 struct name *np;
1613 for(np = lextract(name, GTO | GSKIN); np != NULL; np = np->n_flink){
1614 int vs;
1615 char *vn;
1617 vn = n_lofi_alloc(vs = strlen(np->n_name) + 30);
1618 snprintf(vn, vs, "smime-sign-digest-%s", np->n_name);
1619 if((cp = n_var_vlook(vn, FAL0)) == NULL){
1620 snprintf(vn, vs, "smime-sign-message-digest-%s",np->n_name);/*v15*/
1621 cp = n_var_vlook(vn, FAL0);
1623 n_lofi_free(vn);
1624 if(cp != NULL)
1625 goto jhave_name;
1629 if((cp = ok_vlook(smime_sign_digest)) != NULL ||
1630 (cp = ok_vlook(smime_sign_message_digest)/* v15 */) != NULL)
1631 jhave_name:
1632 if(a_xtls_digest_find(cp, &digest, digname))
1633 goto jleave;
1635 digest = a_XTLS_SMIME_DEFAULT_DIGEST();
1636 *digname = a_XTLS_SMIME_DEFAULT_DIGEST_S;
1637 jleave:
1638 NYD2_LEAVE;
1639 return digest;
1642 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1643 static enum okay
1644 load_crl1(X509_STORE *store, char const *name)
1646 X509_LOOKUP *lookup;
1647 enum okay rv = STOP;
1648 NYD_ENTER;
1650 if (n_poption & n_PO_D_V)
1651 n_err(_("Loading CRL from %s\n"), n_shexp_quote_cp(name, FAL0));
1652 if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) == NULL) {
1653 ssl_gen_err(_("Error creating X509 lookup object"));
1654 goto jleave;
1656 if (X509_load_crl_file(lookup, name, X509_FILETYPE_PEM) != 1) {
1657 ssl_gen_err(_("Error loading CRL from %s"),
1658 n_shexp_quote_cp(name, FAL0));
1659 goto jleave;
1661 rv = OKAY;
1662 jleave:
1663 NYD_LEAVE;
1664 return rv;
1666 #endif /* new OpenSSL */
1668 static enum okay
1669 load_crls(X509_STORE *store, enum okeys fok, enum okeys dok)/*TODO nevertried*/
1671 char *crl_file, *crl_dir;
1672 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1673 DIR *dirp;
1674 struct dirent *dp;
1675 char *fn = NULL;
1676 int fs = 0, ds, es;
1677 #endif
1678 bool_t any;
1679 enum okay rv;
1680 NYD_ENTER;
1682 rv = STOP;
1683 any = FAL0;
1685 jredo_v15:
1686 if ((crl_file = n_var_oklook(fok)) != NULL) {
1687 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1688 if ((crl_file = fexpand(crl_file, FEXP_LOCAL | FEXP_NOPROTO)) == NULL ||
1689 load_crl1(store, crl_file) != OKAY)
1690 goto jleave;
1691 any = TRU1;
1692 #else
1693 n_err(_("This OpenSSL version is too old to use CRLs\n"));
1694 goto jleave;
1695 #endif
1698 if ((crl_dir = n_var_oklook(dok)) != NULL) {
1699 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1700 char *x;
1701 if ((x = fexpand(crl_dir, FEXP_LOCAL | FEXP_NOPROTO)) == NULL ||
1702 (dirp = opendir(crl_dir = x)) == NULL) {
1703 n_perr(crl_dir, 0);
1704 goto jleave;
1707 ds = strlen(crl_dir);
1708 fn = n_alloc(fs = ds + 20);
1709 memcpy(fn, crl_dir, ds);
1710 fn[ds] = '/';
1711 while ((dp = readdir(dirp)) != NULL) {
1712 if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
1713 (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
1714 continue;
1715 if (dp->d_name[0] == '.')
1716 continue;
1717 if (ds + (es = strlen(dp->d_name)) + 2 < fs)
1718 fn = n_realloc(fn, fs = ds + es + 20);
1719 memcpy(fn + ds + 1, dp->d_name, es + 1);
1720 if (load_crl1(store, fn) != OKAY) {
1721 closedir(dirp);
1722 n_free(fn);
1723 goto jleave;
1725 any = TRU1;
1727 closedir(dirp);
1728 n_free(fn);
1729 #else /* old OpenSSL */
1730 n_err(_("This OpenSSL version is too old to use CRLs\n"));
1731 goto jleave;
1732 #endif
1735 if(fok == ok_v_tls_crl_file){
1736 fok = ok_v_ssl_crl_file;
1737 dok = ok_v_ssl_crl_dir;
1738 goto jredo_v15;
1740 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1741 if(any)
1742 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
1743 X509_V_FLAG_CRL_CHECK_ALL);
1744 #endif
1745 rv = OKAY;
1746 jleave:
1747 NYD_LEAVE;
1748 return rv;
1751 #if HAVE_RANDOM == n_RANDOM_IMPL_TLS
1752 FL void
1753 n_tls_rand_bytes(void *buf, size_t blen){
1754 NYD2_ENTER;
1756 if(!(a_xtls_state & a_XTLS_S_RAND_INIT))
1757 a_xtls_rand_init();
1759 while(blen > 0){
1760 si32_t i;
1762 i = n_MIN(SI32_MAX, blen);
1763 blen -= i;
1764 RAND_bytes(buf, i);
1765 buf = (ui8_t*)buf + i;
1767 NYD2_LEAVE;
1769 #endif
1771 FL bool_t
1772 n_tls_open(struct url *urlp, struct sock *sp){
1773 void *confp;
1774 SSL_CTX *ctxp;
1775 const EVP_MD *fprnt_mdp;
1776 char const *fprnt, *fprnt_namep;
1777 NYD_ENTER;
1779 a_xtls_init();
1780 n_tls_set_verify_level(urlp); /* TODO should come in via URL! */
1782 sp->s_tls = NULL;
1783 if(urlp->url_cproto != CPROTO_CERTINFO)
1784 fprnt = xok_vlook(tls_fingerprint, urlp, OXM_ALL);
1785 else
1786 fprnt = NULL;
1787 fprnt_namep = NULL;
1788 fprnt_mdp = NULL;
1790 if(fprnt != NULL || urlp->url_cproto == CPROTO_CERTINFO ||
1791 (n_poption & n_PO_D_V)){
1792 if((fprnt_namep = xok_vlook(tls_fingerprint_digest, urlp,
1793 OXM_ALL)) == NULL ||
1794 !a_xtls_digest_find(fprnt_namep, &fprnt_mdp, &fprnt_namep)){
1795 fprnt_mdp = a_XTLS_FINGERPRINT_DEFAULT_DIGEST();
1796 fprnt_namep = a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S;
1800 if((ctxp = SSL_CTX_new(n_XTLS_CLIENT_METHOD())) == NULL){
1801 ssl_gen_err(_("SSL_CTX_new() failed"));
1802 goto j_leave;
1805 /* Available with OpenSSL 0.9.6 or later */
1806 #ifdef SSL_MODE_AUTO_RETRY
1807 SSL_CTX_set_mode(ctxp, SSL_MODE_AUTO_RETRY);
1808 #endif
1810 if((confp = a_xtls_conf_setup(ctxp, urlp)) == NULL)
1811 goto jleave;
1813 if(!a_xtls_obsolete_conf_vars(confp, urlp))
1814 goto jerr1;
1815 if(!a_xtls_config_pairs(confp, urlp))
1816 goto jerr1;
1817 if((fprnt == NULL || urlp->url_cproto == CPROTO_CERTINFO) &&
1818 !a_xtls_load_verifications(ctxp, urlp))
1819 goto jerr1;
1821 /* Done with context setup, create our new per-connection structure */
1822 if(!a_xtls_conf_finish(&confp, FAL0))
1823 goto jleave;
1824 assert(confp == NULL);
1826 if((sp->s_tls = SSL_new(ctxp)) == NULL){
1827 ssl_gen_err(_("SSL_new() failed"));
1828 goto jleave;
1831 /* Try establish SNI extension; even though this is a TLS extension the
1832 * protocol isn't checked by OpenSSL once the host name is set, and
1833 * therefore i refrained from changing so much code just to check out
1834 * whether we are using SSLv3, which should become more and more rare */
1835 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1836 if((urlp->url_flags & n_URL_TLS_MASK) &&
1837 (urlp->url_flags & n_URL_HOST_IS_NAME)){
1838 if(!SSL_set_tlsext_host_name(sp->s_tls, urlp->url_host.s) &&
1839 (n_poption & n_PO_D_V))
1840 n_err(_("Hostname cannot be used with ServerNameIndication "
1841 "TLS extension: %s\n"),
1842 n_shexp_quote_cp(urlp->url_host.s, FAL0));
1844 #endif
1846 SSL_set_fd(sp->s_tls, sp->s_fd);
1848 if(SSL_connect(sp->s_tls) < 0){
1849 ssl_gen_err(_("could not initiate TLS connection"));
1850 goto jerr2;
1853 if(fprnt != NULL || urlp->url_cproto == CPROTO_CERTINFO ||
1854 n_tls_verify_level != n_TLS_VERIFY_IGNORE){
1855 bool_t stay;
1856 X509 *peercert;
1858 if((peercert = SSL_get_peer_certificate(sp->s_tls)) == NULL){
1859 n_err(_("TLS: no certificate from peer: %s\n"), urlp->url_h_p.s);
1860 goto jerr2;
1863 stay = FAL0;
1865 if(fprnt == NULL){
1866 if(!a_xtls_check_host(sp, peercert, urlp)){
1867 n_err(_("TLS certificate does not match: %s\n"), urlp->url_h_p.s);
1868 stay = n_tls_verify_decide();
1869 }else{
1870 if(n_poption & n_PO_D_V)
1871 n_err(_("TLS certificate ok\n"));
1872 stay = TRU1;
1876 if(fprnt != NULL || urlp->url_cproto == CPROTO_CERTINFO ||
1877 (n_poption & n_PO_D_V)){
1878 char fpmdhexbuf[EVP_MAX_MD_SIZE * 3], *cp;
1879 unsigned char fpmdbuf[EVP_MAX_MD_SIZE], *ucp;
1880 unsigned int fpmdlen;
1882 if(!X509_digest(peercert, fprnt_mdp, fpmdbuf, &fpmdlen)){
1883 ssl_gen_err(_("TLS %s fingerprint creation failed"), fprnt_namep);
1884 goto jpeer_leave;
1886 assert(fpmdlen <= EVP_MAX_MD_SIZE);
1888 for(cp = fpmdhexbuf, ucp = fpmdbuf; fpmdlen > 0; --fpmdlen){
1889 n_c_to_hex_base16(cp, (char)*ucp++);
1890 cp[2] = ':';
1891 cp += 3;
1893 cp[-1] = '\0';
1895 if(n_poption & n_PO_D_V)
1896 n_err(_("TLS %s fingerprint: %s\n"), fprnt_namep, fpmdhexbuf);
1897 if(fprnt != NULL){
1898 if(!(stay = !strcmp(fprnt, fpmdhexbuf))){
1899 n_err(_("TLS fingerprint does not match: %s\n"
1900 " Expected: %s\n Detected: %s\n"),
1901 urlp->url_h_p.s, fprnt, fpmdhexbuf);
1902 stay = n_tls_verify_decide();
1903 }else if(n_poption & n_PO_D_V)
1904 n_err(_("TLS fingerprint ok\n"));
1905 goto jpeer_leave;
1906 }else if(urlp->url_cproto == CPROTO_CERTINFO)
1907 sp->s_tls_finger = savestrbuf(fpmdhexbuf,
1908 PTR2SIZE(cp - fpmdhexbuf));
1911 jpeer_leave:
1912 X509_free(peercert);
1913 if(!stay)
1914 goto jerr2;
1917 sp->s_use_tls = 1;
1918 jleave:
1919 /* We're fully setup: since we don't reuse the SSL_CTX (pooh) keep it local
1920 * and free it right now -- it is reference counted by sp->s_tls.. */
1921 SSL_CTX_free(ctxp);
1922 j_leave:
1923 NYD_LEAVE;
1924 return (sp->s_tls != NULL);
1925 jerr2:
1926 SSL_free(sp->s_tls);
1927 sp->s_tls = NULL;
1928 jerr1:
1929 if(confp != NULL)
1930 a_xtls_conf_finish(&confp, TRU1);
1931 goto jleave;
1934 FL void
1935 ssl_gen_err(char const *fmt, ...)
1937 va_list ap;
1938 NYD_ENTER;
1940 va_start(ap, fmt);
1941 n_verr(fmt, ap);
1942 va_end(ap);
1944 n_err(_(": %s\n"), ERR_error_string(ERR_get_error(), NULL));
1945 NYD_LEAVE;
1948 FL int
1949 c_verify(void *vp)
1951 int *msgvec = vp, *ip, ec = 0, rv = 1;
1952 X509_STORE *store = NULL;
1953 char *ca_dir, *ca_file;
1954 NYD_ENTER;
1956 a_xtls_init();
1958 n_tls_verify_level = n_TLS_VERIFY_STRICT;
1959 if ((store = X509_STORE_new()) == NULL) {
1960 ssl_gen_err(_("Error creating X509 store"));
1961 goto jleave;
1963 X509_STORE_set_verify_cb_func(store, &a_xtls_verify_cb);
1965 if ((ca_dir = ok_vlook(smime_ca_dir)) != NULL)
1966 ca_dir = fexpand(ca_dir, FEXP_LOCAL | FEXP_NOPROTO);
1967 if ((ca_file = ok_vlook(smime_ca_file)) != NULL)
1968 ca_file = fexpand(ca_file, FEXP_LOCAL | FEXP_NOPROTO);
1970 if((ca_dir != NULL || ca_file != NULL) &&
1971 X509_STORE_load_locations(store, ca_file, ca_dir) != 1){
1972 char const *m1, *m2, *m3;
1974 if(ca_dir != NULL){
1975 m1 = ca_dir;
1976 m2 = (ca_file != NULL) ? _(" or ") : n_empty;
1977 }else
1978 m1 = m2 = n_empty;
1979 m3 = (ca_file != NULL) ? ca_file : n_empty;
1980 ssl_gen_err(_("Error loading %s%s%s\n"), m1, m2, m3);
1981 goto jleave;
1984 /* C99 */{
1985 bool_t xv15;
1987 if((xv15 = ok_blook(smime_no_default_ca)))
1988 n_OBSOLETE(_("please use *smime-ca-no-defaults*, "
1989 "not *smime-no-default-ca*"));
1990 if(!ok_blook(smime_ca_no_defaults) && !xv15 &&
1991 X509_STORE_set_default_paths(store) != 1) {
1992 ssl_gen_err(_("Error loading built-in default CA locations\n"));
1993 goto jleave;
1997 if (load_crls(store, ok_v_smime_crl_file, ok_v_smime_crl_dir) != OKAY)
1998 goto jleave;
2000 a_xtls_ca_flags(store, ok_vlook(smime_ca_flags));
2002 srelax_hold();
2003 for (ip = msgvec; *ip != 0; ++ip) {
2004 struct message *mp = message + *ip - 1;
2005 setdot(mp);
2006 ec |= smime_verify(mp, *ip, NULL, store);
2007 srelax();
2009 srelax_rele();
2011 if ((rv = ec) != 0)
2012 n_exit_status |= n_EXIT_ERR;
2013 jleave:
2014 if (store != NULL)
2015 X509_STORE_free(store);
2016 NYD_LEAVE;
2017 return rv;
2020 FL FILE *
2021 smime_sign(FILE *ip, char const *addr)
2023 FILE *rv, *sp, *fp, *bp, *hp;
2024 X509 *cert = NULL;
2025 n_XTLS_STACKOF(X509) *chain = NULL;
2026 EVP_PKEY *pkey = NULL;
2027 BIO *bb, *sb;
2028 PKCS7 *pkcs7;
2029 EVP_MD const *md;
2030 char const *name;
2031 bool_t bail = FAL0;
2032 NYD_ENTER;
2034 assert(addr != NULL);
2035 rv = sp = fp = bp = hp = NULL;
2037 a_xtls_init();
2039 if (addr == NULL) {
2040 n_err(_("No *from* address for signing specified\n"));
2041 goto jleave;
2043 if ((fp = smime_sign_cert(addr, NULL, 1, NULL)) == NULL)
2044 goto jleave;
2046 if ((pkey = PEM_read_PrivateKey(fp, NULL, &ssl_password_cb,
2047 savecat(addr, ".smime-cert-key"))) == NULL) {
2048 ssl_gen_err(_("Error reading private key from"));
2049 goto jleave;
2052 rewind(fp);
2053 if ((cert = PEM_read_X509(fp, NULL, &ssl_password_cb,
2054 savecat(addr, ".smime-cert-cert"))) == NULL) {
2055 ssl_gen_err(_("Error reading signer certificate from"));
2056 goto jleave;
2058 Fclose(fp);
2059 fp = NULL;
2061 if ((name = _smime_sign_include_certs(addr)) != NULL &&
2062 !_smime_sign_include_chain_creat(&chain, name,
2063 savecat(addr, ".smime-include-certs")))
2064 goto jleave;
2066 name = NULL;
2067 if ((md = a_xtls_smime_sign_digest(addr, &name)) == NULL)
2068 goto jleave;
2070 if ((sp = Ftmp(NULL, "smimesign", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
2071 NULL) {
2072 n_perr(_("tempfile"), 0);
2073 goto jleave;
2076 rewind(ip);
2077 if (smime_split(ip, &hp, &bp, -1, 0) == STOP)
2078 goto jleave;
2080 sb = NULL;
2081 pkcs7 = NULL;
2083 if ((bb = BIO_new_fp(bp, BIO_NOCLOSE)) == NULL ||
2084 (sb = BIO_new_fp(sp, BIO_NOCLOSE)) == NULL) {
2085 ssl_gen_err(_("Error creating BIO signing objects"));
2086 bail = TRU1;
2087 goto jerr;
2090 #undef _X
2091 #define _X PKCS7_DETACHED | PKCS7_PARTIAL
2092 if ((pkcs7 = PKCS7_sign(NULL, NULL, chain, bb, _X)) == NULL) {
2093 ssl_gen_err(_("Error creating the PKCS#7 signing object"));
2094 bail = TRU1;
2095 goto jerr;
2097 if (PKCS7_sign_add_signer(pkcs7, cert, pkey, md, _X) == NULL) {
2098 ssl_gen_err(_("Error setting PKCS#7 signing object signer"));
2099 bail = TRU1;
2100 goto jerr;
2102 if (!PKCS7_final(pkcs7, bb, _X)) {
2103 ssl_gen_err(_("Error finalizing the PKCS#7 signing object"));
2104 bail = TRU1;
2105 goto jerr;
2107 #undef _X
2109 if (PEM_write_bio_PKCS7(sb, pkcs7) == 0) {
2110 ssl_gen_err(_("Error writing signed S/MIME data"));
2111 bail = TRU1;
2112 /*goto jerr*/
2114 jerr:
2115 if (pkcs7 != NULL)
2116 PKCS7_free(pkcs7);
2117 if (sb != NULL)
2118 BIO_free(sb);
2119 if (bb != NULL)
2120 BIO_free(bb);
2121 if (!bail) {
2122 rewind(bp);
2123 fflush_rewind(sp);
2124 rv = smime_sign_assemble(hp, bp, sp, name);
2125 hp = bp = sp = NULL;
2128 jleave:
2129 if (chain != NULL)
2130 sk_X509_pop_free(chain, X509_free);
2131 if (cert != NULL)
2132 X509_free(cert);
2133 if (pkey != NULL)
2134 EVP_PKEY_free(pkey);
2135 if (fp != NULL)
2136 Fclose(fp);
2137 if (hp != NULL)
2138 Fclose(hp);
2139 if (bp != NULL)
2140 Fclose(bp);
2141 if (sp != NULL)
2142 Fclose(sp);
2143 NYD_LEAVE;
2144 return rv;
2147 FL FILE *
2148 smime_encrypt(FILE *ip, char const *xcertfile, char const *to)
2150 FILE *rv, *yp, *fp, *bp, *hp;
2151 X509 *cert;
2152 PKCS7 *pkcs7;
2153 BIO *bb, *yb;
2154 n_XTLS_STACKOF(X509) *certs;
2155 EVP_CIPHER const *cipher;
2156 char *certfile;
2157 bool_t bail;
2158 NYD_ENTER;
2160 bail = FAL0;
2161 rv = yp = fp = bp = hp = NULL;
2163 if ((certfile = fexpand(xcertfile, FEXP_LOCAL | FEXP_NOPROTO)) == NULL)
2164 goto jleave;
2166 a_xtls_init();
2168 if ((cipher = _smime_cipher(to)) == NULL)
2169 goto jleave;
2171 if ((fp = Fopen(certfile, "r")) == NULL) {
2172 n_perr(certfile, 0);
2173 goto jleave;
2175 if ((cert = PEM_read_X509(fp, NULL, &ssl_password_cb, NULL)) == NULL) {
2176 ssl_gen_err(_("Error reading encryption certificate from %s"),
2177 n_shexp_quote_cp(certfile, FAL0));
2178 bail = TRU1;
2180 if (bail)
2181 goto jleave;
2182 Fclose(fp);
2183 fp = NULL;
2184 bail = FAL0;
2186 certs = sk_X509_new_null();
2187 sk_X509_push(certs, cert);
2189 if ((yp = Ftmp(NULL, "smimeenc", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
2190 NULL) {
2191 n_perr(_("tempfile"), 0);
2192 goto jerr1;
2195 rewind(ip);
2196 if (smime_split(ip, &hp, &bp, -1, 0) == STOP)
2197 goto jerr1;
2199 yb = NULL;
2200 if ((bb = BIO_new_fp(bp, BIO_NOCLOSE)) == NULL ||
2201 (yb = BIO_new_fp(yp, BIO_NOCLOSE)) == NULL) {
2202 ssl_gen_err(_("Error creating BIO encryption objects"));
2203 bail = TRU1;
2204 goto jerr2;
2206 if ((pkcs7 = PKCS7_encrypt(certs, bb, cipher, 0)) == NULL) {
2207 ssl_gen_err(_("Error creating the PKCS#7 encryption object"));
2208 bail = TRU1;
2209 goto jerr2;
2211 if (PEM_write_bio_PKCS7(yb, pkcs7) == 0) {
2212 ssl_gen_err(_("Error writing encrypted S/MIME data"));
2213 bail = TRU1;
2214 /* goto jerr2 */
2216 PKCS7_free(pkcs7);
2218 jerr2:
2219 if (bb != NULL)
2220 BIO_free(bb);
2221 if (yb != NULL)
2222 BIO_free(yb);
2223 Fclose(bp);
2224 bp = NULL;
2225 if (!bail) {
2226 fflush_rewind(yp);
2227 rv = smime_encrypt_assemble(hp, yp);
2228 hp = yp = NULL;
2230 jerr1:
2231 sk_X509_pop_free(certs, X509_free);
2232 jleave:
2233 if(yp != NULL)
2234 Fclose(yp);
2235 if(fp != NULL)
2236 Fclose(fp);
2237 if(bp != NULL)
2238 Fclose(bp);
2239 if(hp != NULL)
2240 Fclose(hp);
2241 NYD_LEAVE;
2242 return rv;
2245 FL struct message *
2246 smime_decrypt(struct message *m, char const *to, char const *cc,
2247 bool_t signcall)
2249 char const *myaddr;
2250 long size;
2251 struct message *rv;
2252 FILE *bp, *hp, *op;
2253 PKCS7 *pkcs7;
2254 BIO *ob, *bb, *pb;
2255 X509 *cert;
2256 EVP_PKEY *pkey;
2257 FILE *yp;
2258 NYD_ENTER;
2260 pkey = NULL;
2261 cert = NULL;
2262 ob = bb = pb = NULL;
2263 pkcs7 = NULL;
2264 bp = hp = op = NULL;
2265 rv = NULL;
2266 size = m->m_size;
2268 if((yp = setinput(&mb, m, NEED_BODY)) == NULL)
2269 goto jleave;
2271 a_xtls_init();
2273 if((op = smime_sign_cert(to, cc, 0, &myaddr)) != NULL){
2274 pkey = PEM_read_PrivateKey(op, NULL, &ssl_password_cb,
2275 savecat(myaddr, ".smime-cert-key"));
2276 if(pkey == NULL){
2277 ssl_gen_err(_("Error reading private key"));
2278 goto jleave;
2281 rewind(op);
2282 if((cert = PEM_read_X509(op, NULL, &ssl_password_cb,
2283 savecat(myaddr, ".smime-cert-cert"))) == NULL){
2284 ssl_gen_err(_("Error reading decryption certificate"));
2285 goto jleave;
2288 Fclose(op);
2289 op = NULL;
2292 if((op = Ftmp(NULL, "smimed", OF_RDWR | OF_UNLINK | OF_REGISTER)) == NULL){
2293 n_perr(_("tempfile"), 0);
2294 goto jleave;
2297 if(smime_split(yp, &hp, &bp, size, 1) == STOP)
2298 goto jleave;
2300 if((ob = BIO_new_fp(op, BIO_NOCLOSE)) == NULL ||
2301 (bb = BIO_new_fp(bp, BIO_NOCLOSE)) == NULL){
2302 ssl_gen_err(_("Error creating BIO decryption objects"));
2303 goto jleave;
2306 if((pkcs7 = SMIME_read_PKCS7(bb, &pb)) == NULL){
2307 ssl_gen_err(_("Error reading PKCS#7 object"));
2308 goto jleave;
2311 if(PKCS7_type_is_signed(pkcs7)){
2312 if(signcall){
2313 setinput(&mb, m, NEED_BODY);
2314 rv = (struct message*)-1;
2315 goto jleave;
2317 if(PKCS7_verify(pkcs7, NULL, NULL, NULL, ob,
2318 PKCS7_NOVERIFY | PKCS7_NOSIGS) != 1)
2319 goto jerr;
2320 fseek(hp, 0L, SEEK_END);
2321 fprintf(hp, "X-Encryption-Cipher: none\n");
2322 fflush_rewind(hp);
2323 }else if(pkey == NULL){
2324 n_err(_("No appropriate private key found\n"));
2325 goto jleave;
2326 }else if(cert == NULL){
2327 n_err(_("No appropriate certificate found\n"));
2328 goto jleave;
2329 }else if(PKCS7_decrypt(pkcs7, pkey, cert, ob, 0) != 1){
2330 jerr:
2331 ssl_gen_err(_("Error decrypting PKCS#7 object"));
2332 goto jleave;
2334 fflush_rewind(op);
2335 Fclose(bp);
2336 bp = NULL;
2338 rv = smime_decrypt_assemble(m, hp, op);
2339 hp = op = NULL; /* xxx closed by decrypt_assemble */
2340 jleave:
2341 if(op != NULL)
2342 Fclose(op);
2343 if(hp != NULL)
2344 Fclose(hp);
2345 if(bp != NULL)
2346 Fclose(bp);
2347 if(bb != NULL)
2348 BIO_free(bb);
2349 if(ob != NULL)
2350 BIO_free(ob);
2351 if(pkcs7 != NULL)
2352 PKCS7_free(pkcs7);
2353 if(cert != NULL)
2354 X509_free(cert);
2355 if(pkey != NULL)
2356 EVP_PKEY_free(pkey);
2357 NYD_LEAVE;
2358 return rv;
2361 FL enum okay
2362 smime_certsave(struct message *m, int n, FILE *op)
2364 struct message *x;
2365 char *to, *cc, *cnttype;
2366 int c, i;
2367 FILE *fp, *ip;
2368 off_t size;
2369 BIO *fb, *pb;
2370 PKCS7 *pkcs7;
2371 n_XTLS_STACKOF(X509) *certs, *chain = NULL;
2372 X509 *cert;
2373 enum okay rv = STOP;
2374 NYD_ENTER;
2376 pkcs7 = NULL;
2378 a_xtls_msgno = (size_t)n;
2379 jloop:
2380 to = hfield1("to", m);
2381 cc = hfield1("cc", m);
2382 cnttype = hfield1("content-type", m);
2384 if ((ip = setinput(&mb, m, NEED_BODY)) == NULL)
2385 goto jleave;
2387 #undef _X
2388 #undef _Y
2389 #define _X (sizeof("application/") -1)
2390 #define _Y(X) X, sizeof(X) -1
2391 if (cnttype && is_asccaseprefix("application/", cnttype) &&
2392 (!ascncasecmp(cnttype + _X, _Y("pkcs7-mime")) ||
2393 !ascncasecmp(cnttype + _X, _Y("x-pkcs7-mime")))) {
2394 #undef _Y
2395 #undef _X
2396 if ((x = smime_decrypt(m, to, cc, 1)) == NULL)
2397 goto jleave;
2398 if (x != (struct message*)-1) {
2399 m = x;
2400 goto jloop;
2403 size = m->m_size;
2405 if ((fp = Ftmp(NULL, "smimecert", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
2406 NULL) {
2407 n_perr(_("tempfile"), 0);
2408 goto jleave;
2411 while (size-- > 0) {
2412 c = getc(ip);
2413 putc(c, fp);
2415 fflush(fp);
2417 rewind(fp);
2418 if ((fb = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
2419 ssl_gen_err("Error creating BIO object for message %d", n);
2420 Fclose(fp);
2421 goto jleave;
2424 if ((pkcs7 = SMIME_read_PKCS7(fb, &pb)) == NULL) {
2425 ssl_gen_err(_("Error reading PKCS#7 object for message %d"), n);
2426 BIO_free(fb);
2427 Fclose(fp);
2428 goto jleave;
2430 BIO_free(fb);
2431 Fclose(fp);
2433 certs = PKCS7_get0_signers(pkcs7, chain, 0);
2434 if (certs == NULL) {
2435 n_err(_("No certificates found in message %d\n"), n);
2436 goto jleave;
2439 for (i = 0; i < sk_X509_num(certs); ++i) {
2440 cert = sk_X509_value(certs, i);
2441 if (X509_print_fp(op, cert) == 0 || PEM_write_X509(op, cert) == 0) {
2442 ssl_gen_err(_("Error writing certificate %d from message %d"),
2443 i, n);
2444 goto jleave;
2447 rv = OKAY;
2448 jleave:
2449 if(pkcs7 != NULL)
2450 PKCS7_free(pkcs7);
2451 NYD_LEAVE;
2452 return rv;
2454 #endif /* HAVE_XTLS */
2456 /* s-it-mode */