a_go_evaluate(): fix un/signed comparison
[s-mailx.git] / xtls.c
blob06cc345df0de9f9d73e3b4f0dddf4c260ca18afe
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[16];
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 * Update manual on default changes! */
273 static struct a_xtls_digest const a_xtls_digests[] = { /*Manual!*/
274 #ifdef HAVE_XTLS_BLAKE2
275 {"BLAKE2b512\0", &EVP_blake2b512},
276 {"BLAKE2s256", &EVP_blake2s256},
277 # ifndef a_XTLS_FINGERPRINT_DEFAULT_DIGEST
278 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST EVP_blake2s256
279 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S "BLAKE2s256"
280 # endif
281 #endif
283 #ifdef HAVE_XTLS_SHA3
284 {"SHA3-512\0", &EVP_sha3_512},
285 {"SHA3-384", &EVP_sha3_384},
286 {"SHA3-256", &EVP_sha3_256},
287 {"SHA3-224", &EVP_sha3_224},
288 #endif
290 #ifndef OPENSSL_NO_SHA512
291 {"SHA512\0", &EVP_sha512},
292 {"SHA384", &EVP_sha384},
293 # ifndef a_XTLS_SMIME_DEFAULT_DIGEST
294 # define a_XTLS_SMIME_DEFAULT_DIGEST EVP_sha512
295 # define a_XTLS_SMIME_DEFAULT_DIGEST_S "SHA512"
296 # endif
297 #endif
299 #ifndef OPENSSL_NO_SHA256
300 {"SHA256\0", &EVP_sha256},
301 {"SHA224", &EVP_sha224},
302 # ifndef a_XTLS_SMIME_DEFAULT_DIGEST
303 # define a_XTLS_SMIME_DEFAULT_DIGEST EVP_sha256
304 # define a_XTLS_SMIME_DEFAULT_DIGEST_S "SHA256"
305 # endif
306 # ifndef a_XTLS_FINGERPRINT_DEFAULT_DIGEST
307 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST EVP_sha256
308 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S "SHA256"
309 # endif
310 #endif
312 #ifndef OPENSSL_NO_SHA
313 {"SHA1\0", &EVP_sha1},
314 # ifndef a_XTLS_SMIME_DEFAULT_DIGEST
315 # define a_XTLS_SMIME_DEFAULT_DIGEST EVP_sha1
316 # define a_XTLS_SMIME_DEFAULT_DIGEST_S "SHA1"
317 # endif
318 # ifndef a_XTLS_FINGERPRINT_DEFAULT_DIGEST
319 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST EVP_sha1
320 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S "SHA1"
321 # endif
322 #endif
324 #ifndef OPENSSL_NO_MD5
325 {"MD5\0", &EVP_md5},
326 #endif
329 #if !defined a_XTLS_SMIME_DEFAULT_DIGEST || \
330 !defined a_XTLS_FINGERPRINT_DEFAULT_DIGEST
331 # error Not enough supported message digest algorithms available
332 #endif
334 /* X509_STORE_set_flags() for *{smime,ssl}-ca-flags* */
335 static struct a_xtls_x509_v_flags const a_xtls_x509_v_flags[] = { /* Manual! */
336 {"no-alt-chains", X509_V_FLAG_NO_ALT_CHAINS},
337 {"no-check-time", X509_V_FLAG_NO_CHECK_TIME},
338 {"partial-chain", X509_V_FLAG_PARTIAL_CHAIN},
339 {"strict", X509_V_FLAG_X509_STRICT},
340 {"trusted-first", X509_V_FLAG_TRUSTED_FIRST},
343 static enum a_xtls_state a_xtls_state;
344 static size_t a_xtls_msgno;
346 static void a_xtls_rand_init(void);
347 static void a_xtls_init(void);
349 #if HAVE_XTLS_OPENSSL < 0x10100
350 # ifdef HAVE_TLS_ALL_ALGORITHMS
351 static void a_xtls__load_algos(void);
352 # define a_xtls_load_algos a_xtls__load_algos
353 # endif
354 # if defined HAVE_XTLS_CONFIG || defined HAVE_TLS_ALL_ALGORITHMS
355 static void a_xtls_atexit(void);
356 # endif
357 #endif
358 #ifndef a_xtls_load_algos
359 # define a_xtls_load_algos() do{;}while(0)
360 #endif
362 static bool_t a_xtls_parse_asn1_time(ASN1_TIME const *atp,
363 char *bdat, size_t blen);
364 static int a_xtls_verify_cb(int success, X509_STORE_CTX *store);
366 static bool_t a_xtls_digest_find(char const *name, EVP_MD const **mdp,
367 char const **normalized_name_or_null);
369 /* *smime-ca-flags*, *tls-ca-flags* */
370 static void a_xtls_ca_flags(X509_STORE *store, char const *flags);
372 /* SSL_CTX configuration; the latter always NULLs *confp */
373 static void *a_xtls_conf_setup(SSL_CTX *ctxp, struct url const *urlp);
374 static bool_t a_xtls_conf(void *confp, char const *cmd, char const *value);
375 static bool_t a_xtls_conf_finish(void **confp, bool_t error);
377 static bool_t a_xtls_obsolete_conf_vars(void *confp, struct url const *urlp);
378 static bool_t a_xtls_config_pairs(void *confp, struct url const *urlp);
379 static bool_t a_xtls_load_verifications(SSL_CTX *ctxp, struct url const *urlp);
381 static bool_t a_xtls_check_host(struct sock *sp, X509 *peercert,
382 struct url const *urlp);
384 static int smime_verify(struct message *m, int n,
385 n_XTLS_STACKOF(X509) *chain, X509_STORE *store);
386 static EVP_CIPHER const * _smime_cipher(char const *name);
387 static int ssl_password_cb(char *buf, int size, int rwflag,
388 void *userdata);
389 static FILE * smime_sign_cert(char const *xname, char const *xname2,
390 bool_t dowarn, char const **match);
391 static char const * _smime_sign_include_certs(char const *name);
392 static bool_t _smime_sign_include_chain_creat(n_XTLS_STACKOF(X509) **chain,
393 char const *cfiles, char const *addr);
394 static EVP_MD const *a_xtls_smime_sign_digest(char const *name,
395 char const **digname);
396 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
397 static enum okay load_crl1(X509_STORE *store, char const *name);
398 #endif
399 static enum okay load_crls(X509_STORE *store, enum okeys fok, enum okeys dok);
401 static void
402 a_xtls_rand_init(void){
403 #define a_XTLS_RAND_ENTROPY 32
404 char b64buf[a_XTLS_RAND_ENTROPY * 5 +1], *randfile;
405 char const *cp, *x;
406 bool_t err;
407 NYD2_ENTER;
409 a_xtls_state |= a_XTLS_S_RAND_INIT;
411 err = TRU1;
412 randfile = NULL;
414 #ifdef HAVE_XTLS_CONFIG
415 if(!(a_xtls_state & a_XTLS_S_INIT))
416 a_xtls_init();
417 #endif
419 /* Prefer possible user setting */
420 if((cp = ok_vlook(tls_rand_file)) != NULL ||
421 (cp = ok_vlook(ssl_rand_file)) != NULL){
422 x = NULL;
423 if(*cp != '\0'){
424 if((x = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) == NULL)
425 n_err(_("*tls-rand-file*: expansion of %s failed "
426 "(using default)\n"),
427 n_shexp_quote_cp(cp, FAL0));
429 cp = x;
431 if(cp == NULL){
432 randfile = n_lofi_alloc(PATH_MAX);
433 if((cp = RAND_file_name(randfile, PATH_MAX)) == NULL){
434 n_err(_("*tls-rand-file*: no TLS entropy file, can't seed PRNG\n"));
435 goto jleave;
439 (void)RAND_load_file(cp, a_XTLS_RAND_LOAD_FILE_MAXBYTES);
441 /* And feed in some data, then write the updated file.
442 * While this rather feeds the PRNG with itself in the n_RANDOM_IMPL_TLS
443 * case, let us stir the buffer a little bit.
444 * Estimate a low but likely still too high number of entropy bytes, use
445 * 20%: base64 uses 3 input = 4 output bytes relation, and the base64
446 * alphabet is a 6 bit one */
447 for(x = (char*)-1;;){
448 RAND_add(n_random_create_buf(b64buf, sizeof(b64buf) -1, NULL),
449 sizeof(b64buf) -1, a_XTLS_RAND_ENTROPY);
450 if((x = (char*)((uintptr_t)x >> (1
451 #if HAVE_RANDOM == n_RANDOM_IMPL_TLS
453 #endif
454 ))) == NULL){
455 err = (RAND_status() == 0);
456 break;
458 #if HAVE_RANDOM != n_RANDOM_IMPL_TLS
459 if(!(err = (RAND_status() == 0)))
460 break;
461 #endif
464 if(!err)
465 err = (RAND_write_file(cp) == -1);
467 jleave:
468 if(randfile != NULL)
469 n_lofi_free(randfile);
470 if(err)
471 n_panic(_("Cannot seed the *TLS PseudoRandomNumberGenerator, "
472 "RAND_status() is 0!\n"
473 " Please set *tls-rand-file* to a file with sufficient entropy.\n"
474 " On a machine with entropy: "
475 "\"$ dd if=/dev/urandom of=FILE bs=1024 count=1\"\n"));
476 NYD2_LEAVE;
479 static void
480 a_xtls_init(void){
481 #ifdef HAVE_XTLS_CONFIG
482 char const *cp;
483 #endif
484 NYD2_ENTER;
486 if(a_xtls_state & a_XTLS_S_INIT)
487 goto jleave;
489 #if HAVE_XTLS_OPENSSL >= 0x10100
490 OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
491 OPENSSL_INIT_LOAD_CRYPTO_STRINGS
492 # ifdef HAVE_TLS_ALL_ALGORITHMS
493 | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS
494 # endif
495 , NULL);
496 #else
497 SSL_load_error_strings();
498 SSL_library_init();
499 a_xtls_load_algos();
500 #endif
501 a_xtls_state |= a_XTLS_S_INIT;
504 /* Load openssl.cnf or whatever was given in *tls-config-file* */
505 #ifdef HAVE_XTLS_CONFIG
506 if((cp = ok_vlook(tls_config_file)) != NULL ||
507 (cp = ok_vlook(ssl_config_file)) != NULL){
508 char const *msg;
509 ul_i flags;
511 if(*cp == '\0'){
512 msg = "[default]";
513 cp = NULL;
514 flags = CONF_MFLAGS_IGNORE_MISSING_FILE;
515 }else if((msg = cp, cp = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) != NULL)
516 flags = 0;
517 else{
518 n_err(_("*tls-config-file*: file expansion failed: %s\n"),
519 n_shexp_quote_cp(msg, FAL0));
520 goto jefile;
523 if(CONF_modules_load_file(cp, n_uagent, flags) == 1){
524 a_xtls_state |= a_XTLS_S_CONF_LOAD;
525 # if HAVE_XTLS_OPENSSL < 0x10100
526 if(!(a_xtls_state & a_XTLS_S_EXIT_HDL)){
527 a_xtls_state |= a_XTLS_S_EXIT_HDL;
528 atexit(&a_xtls_atexit); /* TODO generic program-wide event mech. */
530 # endif
531 if(n_poption & n_PO_D_V)
532 n_err(_("Loaded TLS configuration for %s from %s\n"), n_uagent,
533 n_shexp_quote_cp(msg, FAL0));
534 jefile:;
535 }else
536 ssl_gen_err(_("TLS CONF_modules_load_file() load error"));
538 #endif /* HAVE_XTLS_CONFIG */
540 if(!(a_xtls_state & a_XTLS_S_RAND_INIT))
541 a_xtls_rand_init();
542 jleave:
543 NYD2_LEAVE;
546 #if HAVE_XTLS_OPENSSL < 0x10100
547 # ifdef HAVE_TLS_ALL_ALGORITHMS
548 static void
549 a_xtls__load_algos(void){
550 NYD2_ENTER;
551 if(!(a_xtls_state & a_XTLS_S_ALGO_LOAD)){
552 a_xtls_state |= a_XTLS_S_ALGO_LOAD;
553 OpenSSL_add_all_algorithms();
555 if(!(a_xtls_state & a_XTLS_S_EXIT_HDL)){
556 a_xtls_state |= a_XTLS_S_EXIT_HDL;
557 atexit(&a_xtls_atexit); /* TODO generic program-wide event mech. */
560 NYD2_LEAVE;
562 # endif
564 # if defined HAVE_XTLS_CONFIG || defined HAVE_TLS_ALL_ALGORITHMS
565 static void
566 a_xtls_atexit(void){
567 NYD2_ENTER;
568 # ifdef HAVE_XTLS_CONFIG
569 if(a_xtls_state & a_XTLS_S_CONF_LOAD)
570 CONF_modules_free();
571 # endif
573 # ifdef HAVE_TLS_ALL_ALGORITHMS
574 if(a_xtls_state & a_XTLS_S_ALGO_LOAD)
575 EVP_cleanup();
576 # endif
577 NYD2_LEAVE;
579 # endif
580 #endif /* HAVE_XTLS_OPENSSL < 0x10100 */
582 static bool_t
583 a_xtls_parse_asn1_time(ASN1_TIME const *atp, char *bdat, size_t blen)
585 BIO *mbp;
586 char *mcp;
587 long l;
588 NYD_ENTER;
590 mbp = BIO_new(BIO_s_mem());
592 if (ASN1_TIME_print(mbp, atp) && (l = BIO_get_mem_data(mbp, &mcp)) > 0)
593 snprintf(bdat, blen, "%.*s", (int)l, mcp);
594 else {
595 snprintf(bdat, blen, _("Bogus certificate date: %.*s"),
596 /*is (int)*/atp->length, (char const*)atp->data);
597 mcp = NULL;
600 BIO_free(mbp);
601 NYD_LEAVE;
602 return (mcp != NULL);
605 static int
606 a_xtls_verify_cb(int success, X509_STORE_CTX *store)
608 char data[256];
609 X509 *cert;
610 int rv = TRU1;
611 NYD_ENTER;
613 if (success && !(n_poption & n_PO_D_V))
614 goto jleave;
616 if (a_xtls_msgno != 0) {
617 n_err(_("Message %lu:\n"), (ul_i)a_xtls_msgno);
618 a_xtls_msgno = 0;
620 n_err(_(" Certificate depth %d %s\n"),
621 X509_STORE_CTX_get_error_depth(store), (success ? n_empty : V_(n_error)));
623 if ((cert = X509_STORE_CTX_get_current_cert(store)) != NULL) {
624 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof data);
625 n_err(_(" subject = %s\n"), data);
627 a_xtls_parse_asn1_time(a_xtls_X509_get_notBefore(cert),
628 data, sizeof data);
629 n_err(_(" notBefore = %s\n"), data);
631 a_xtls_parse_asn1_time(a_xtls_X509_get_notAfter(cert),
632 data, sizeof data);
633 n_err(_(" notAfter = %s\n"), data);
635 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof data);
636 n_err(_(" issuer = %s\n"), data);
639 if (!success) {
640 int err = X509_STORE_CTX_get_error(store);
642 n_err(_(" err %i: %s\n"), err, X509_verify_cert_error_string(err));
643 a_xtls_state |= a_XTLS_S_VERIFY_ERROR;
646 if(!success)
647 rv = n_tls_verify_decide();
648 jleave:
649 NYD_LEAVE;
650 return rv;
653 static bool_t
654 a_xtls_digest_find(char const *name,
655 EVP_MD const **mdp, char const **normalized_name_or_null){
656 size_t i;
657 char *nn;
658 NYD2_ENTER;
660 /* C99 */{
661 char *cp, c;
663 i = strlen(name);
664 nn = cp = n_lofi_alloc(i +1);
665 while((c = *name++) != '\0')
666 *cp++ = upperconv(c);
667 *cp = '\0';
669 if(normalized_name_or_null != NULL)
670 *normalized_name_or_null = savestrbuf(nn, PTR2SIZE(cp - nn));
673 for(i = 0; i < n_NELEM(a_xtls_digests); ++i)
674 if(!strcmp(a_xtls_digests[i].xd_name, nn)){
675 *mdp = (*a_xtls_digests[i].xd_fun)();
676 goto jleave;
679 /* Not a built-in algorithm, but we may have dynamic support for more */
680 #ifdef HAVE_TLS_ALL_ALGORITHMS
681 if((*mdp = EVP_get_digestbyname(nn)) != NULL)
682 goto jleave;
683 #endif
685 n_err(_("Invalid message digest: %s\n"), n_shexp_quote_cp(nn, FAL0));
686 *mdp = NULL;
687 jleave:
688 n_lofi_free(nn);
690 NYD2_LEAVE;
691 return (*mdp != NULL);
694 static void
695 a_xtls_ca_flags(X509_STORE *store, char const *flags){
696 NYD2_ENTER;
697 if(flags != NULL){
698 char *iolist, *cp;
700 iolist = savestr(flags);
701 jouter:
702 while((cp = n_strsep(&iolist, ',', TRU1)) != NULL){
703 struct a_xtls_x509_v_flags const *xvfp;
705 for(xvfp = &a_xtls_x509_v_flags[0];
706 xvfp < &a_xtls_x509_v_flags[n_NELEM(a_xtls_x509_v_flags)];
707 ++xvfp)
708 if(!asccasecmp(cp, xvfp->xxvf_name)){
709 if(xvfp->xxvf_flag != -1){
710 #ifdef a_XTLS_X509_V_ANY
711 X509_STORE_set_flags(store, xvfp->xxvf_flag);
712 #endif
713 }else if(n_poption & n_PO_D_V)
714 n_err(_("*{smime,tls}-ca-flags*: "
715 "directive not supported: %s\n"), cp);
716 goto jouter;
718 n_err(_("*{smime,tls}-ca-flags*: invalid directive: %s\n"), cp);
721 NYD2_LEAVE;
724 #ifdef HAVE_XTLS_CONF_CTX
725 static void *
726 a_xtls_conf_setup(SSL_CTX *ctxp, struct url const *urlp){
727 char const *cp;
728 SSL_CONF_CTX *sccp;
729 NYD2_ENTER;
731 sccp = NULL;
733 if((cp = xok_vlook(tls_config_module, urlp, OXM_ALL)) != NULL ||
734 (cp = xok_vlook(ssl_config_module, urlp, OXM_ALL)) != NULL){
735 # ifdef HAVE_XTLS_CTX_CONFIG
736 if(!(a_xtls_state & a_XTLS_S_CONF_LOAD)){
737 n_err(_("*tls-config-module*: no *tls-config-file* loaded: %s\n"),
738 n_shexp_quote_cp(cp, FAL0));
739 goto jleave;
740 }else if(!SSL_CTX_config(ctxp, cp)){
741 ssl_gen_err(_("*tls-config-module*: load error for %s, section [%s]"),
742 n_uagent, n_shexp_quote_cp(cp, FAL0));
743 goto jleave;
745 # else
746 n_err(_("*tls-config-module*: set but not supported: %s\n"),
747 n_shexp_quote_cp(cp, FAL0));
748 goto jleave;
749 # endif
752 if((sccp = SSL_CONF_CTX_new()) != NULL){
753 SSL_CONF_CTX_set_flags(sccp,
754 SSL_CONF_FLAG_FILE | SSL_CONF_FLAG_CLIENT |
755 SSL_CONF_FLAG_CERTIFICATE | SSL_CONF_FLAG_SHOW_ERRORS);
757 SSL_CONF_CTX_set_ssl_ctx(sccp, ctxp);
758 }else
759 ssl_gen_err(_("SSL_CONF_CTX_new() failed"));
760 jleave:
761 NYD2_LEAVE;
762 return sccp;
765 static bool_t
766 a_xtls_conf(void *confp, char const *cmd, char const *value){
767 int rv;
768 SSL_CONF_CTX *sccp;
769 NYD2_ENTER;
771 if(n_poption & n_PO_D_V)
772 n_err(_("TLS: applying config: %s = %s\n"),
773 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(value, FAL0));
775 rv = SSL_CONF_cmd(sccp = confp, cmd, value);
776 if(rv == 2)
777 rv = 0;
778 else{
779 cmd = n_shexp_quote_cp(cmd, FAL0);
780 value = n_shexp_quote_cp(value, FAL0);
781 if(rv == 0)
782 ssl_gen_err(_("TLS: config failure: %s = %s"), cmd, value);
783 else{
784 char const *err;
786 switch(rv){
787 case -2: err = N_("TLS: config command not recognized"); break;
788 case -3: err = N_("TLS: missing required config argument"); break;
789 default: err = N_("TLS: unspecified config error"); break;
791 err = V_(err);
792 n_err(_("%s (%d): %s = %s\n"), err, rv, cmd, value);
794 rv = 1;
796 NYD2_LEAVE;
797 return (rv == 0);
800 static bool_t
801 a_xtls_conf_finish(void **confp, bool_t error){
802 SSL_CONF_CTX *sccp;
803 bool_t rv;
804 NYD2_ENTER;
806 sccp = (SSL_CONF_CTX*)*confp;
807 *confp = NULL;
809 if(!(rv = error))
810 rv = (SSL_CONF_CTX_finish(sccp) != 0);
812 SSL_CONF_CTX_free(sccp);
813 NYD2_LEAVE;
814 return rv;
817 #else /* HAVE_XTLS_CONF_CTX */
818 # ifdef HAVE_XTLS_CTX_CONFIG
819 # error SSL_CTX_config(3) support unexpected without SSL_CONF_CTX support
820 # endif
822 static void *
823 a_xtls_conf_setup(SSL_CTX* ctxp, struct url const *urlp){
824 char const *cp;
825 NYD2_ENTER;
827 if((cp = xok_vlook(tls_config_module, urlp, OXM_ALL)) != NULL ||
828 (cp = xok_vlook(ssl_config_module, urlp, OXM_ALL)) != NULL){
829 n_err(_("*tls-config-module*: set but not supported: %s\n"),
830 n_shexp_quote_cp(cp, FAL0));
831 ctxp = NULL;
833 NYD2_LEAVE;
834 return ctxp;
837 static bool_t
838 a_xtls_conf(void *confp, char const *cmd, char const *value){
839 char const *xcmd, *emsg;
840 SSL_CTX *ctxp;
841 NYD2_ENTER;
843 if(n_poption & n_PO_D_V)
844 n_err(_("TLS: applying config: %s = %s\n"),
845 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(value, FAL0));
847 ctxp = confp;
849 if(!asccasecmp(cmd, xcmd = "Certificate")){
850 if(SSL_CTX_use_certificate_chain_file(ctxp, value) != 1){
851 emsg = N_("TLS: %s: cannot load from file %s\n");
852 goto jerr;
854 }else if(!asccasecmp(cmd, xcmd = "CipherString") ||
855 !asccasecmp(cmd, xcmd = "CipherList")/* grr, bad fault in past! */){
856 if(SSL_CTX_set_cipher_list(ctxp, value) != 1){
857 emsg = N_("TLS: %s: invalid: %s\n");
858 goto jerr;
860 }else if(!asccasecmp(cmd, xcmd = "Ciphersuites")){
861 #ifdef HAVE_XTLS_SET_CIPHERSUITES
862 if(SSL_CTX_set_ciphersuites(ctxp, value) != 1){
863 emsg = N_("TLS: %s: invalid: %s\n");
864 goto jerr;
866 #else
867 value = NULL;
868 emsg = N_("TLS: %s: directive not supported\n");
869 goto jxerr;
870 #endif
871 }else if(!asccasecmp(cmd, xcmd = "Curves")){
872 #ifdef SSL_CTRL_SET_CURVES_LIST
873 if(SSL_CTX_set1_curves_list(ctxp, value) != 1){
874 emsg = N_("TLS: %s: invalid: %s\n");
875 goto jerr;
877 #else
878 value = NULL;
879 emsg = N_("TLS: %s: directive not supported\n");
880 goto jxerr;
881 #endif
882 }else if((emsg = NULL, !asccasecmp(cmd, xcmd = "MaxProtocol")) ||
883 (emsg = (char*)-1, !asccasecmp(cmd, xcmd = "MinProtocol"))){
884 #ifndef HAVE_XTLS_SET_MIN_PROTO_VERSION
885 value = NULL;
886 emsg = N_("TLS: %s: directive not supported\n");
887 goto jxerr;
888 #else
889 struct a_xtls_protocol const *xpp;
890 size_t i;
892 for(i = 1 /* [0] == ALL */;;){
893 xpp = &a_xtls_protocols[i];
895 if(xpp->xp_ok_minmaxproto && !asccasecmp(value, xpp->xp_name))
896 break;
898 if(++i >= n_NELEM(a_xtls_protocols)){
899 emsg = N_("TLS: %s: unsupported element: %s\n");
900 goto jxerr;
904 if((emsg == NULL ? SSL_CTX_set_max_proto_version(ctxp, xpp->xp_version)
905 : SSL_CTX_set_min_proto_version(ctxp, xpp->xp_version)) != 1){
906 emsg = N_("TLS: %s: invalid protocol: %s\n");
907 goto jerr;
909 #endif /* !HAVE_XTLS_SET_MIN_PROTO_VERSION */
910 }else if(!asccasecmp(cmd, xcmd = "Options")){
911 if(asccasecmp(value, "Bugs")){
912 emsg = N_("TLS: %s: fallback only supports value \"Bugs\": %s\n");
913 goto jxerr;
915 SSL_CTX_set_options(ctxp, SSL_OP_ALL);
916 }else if(!asccasecmp(cmd, xcmd = "PrivateKey")){
917 if(SSL_CTX_use_PrivateKey_file(ctxp, value, SSL_FILETYPE_PEM) != 1){
918 emsg = N_("%s: cannot load from file %s\n");
919 goto jerr;
921 }else if(!asccasecmp(cmd, xcmd = "Protocol")){
922 char *iolist, *cp, addin;
923 size_t i;
924 sl_i opts;
926 opts = 0;
928 for(iolist = cp = savestr(value);
929 (cp = n_strsep(&iolist, ',', FAL0)) != NULL;){
930 if(*cp == '\0'){
931 value = NULL;
932 emsg = N_("TLS: %s: empty elements are not supported\n");
933 goto jxerr;
936 addin = TRU1;
937 switch(cp[0]){
938 case '-': addin = FAL0; /* FALLTHRU */
939 case '+': ++cp; /* FALLTHRU */
940 default : break;
943 for(i = 0;;){
944 struct a_xtls_protocol const *xpp;
946 xpp = &a_xtls_protocols[i];
948 if(xpp->xp_ok_proto && !asccasecmp(cp, xpp->xp_name)){
949 /* We need to inverse the meaning of the _NO_s */
950 if(!addin)
951 opts |= xpp->xp_op_no;
952 else
953 opts &= ~xpp->xp_op_no;
954 break;
957 if(++i >= n_NELEM(a_xtls_protocols)){
958 emsg = N_("TLS: %s: unsupported element: %s\n");
959 goto jxerr;
964 SSL_CTX_clear_options(ctxp, SSL_OP_NO_SSL_MASK);
965 SSL_CTX_set_options(ctxp, opts);
966 }else{
967 xcmd = n_shexp_quote_cp(cmd, FAL0);
968 emsg = N_("TLS: unsupported directive: %s: value: %s\n");
969 goto jxerr;
972 jleave:
973 NYD2_LEAVE;
974 return (confp != NULL);
975 jerr:
976 ssl_gen_err(V_(emsg), xcmd, n_shexp_quote_cp(value, FAL0));
977 confp = NULL;
978 goto jleave;
979 jxerr:
980 if(value != NULL)
981 value = n_shexp_quote_cp(value, FAL0);
982 n_err(V_(emsg), xcmd, value);
983 confp = NULL;
984 goto jleave;
987 static bool_t
988 a_xtls_conf_finish(void **confp, bool_t error){
989 n_UNUSED(confp);
990 n_UNUSED(error);
991 *confp = NULL;
992 return TRU1;
994 #endif /* !HAVE_XTLS_CONF_CTX */
996 static bool_t
997 a_xtls_obsolete_conf_vars(void *confp, struct url const *urlp){
998 char const *cp, *cp_base, *certchain;
999 bool_t rv;
1000 NYD2_ENTER;
1002 rv = FAL0;
1004 /* Certificate via ssl-cert */
1005 if((certchain = cp = xok_vlook(ssl_cert, urlp, OXM_ALL)) != NULL){
1006 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-cert*"));
1007 if((cp_base = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) == NULL){
1008 n_err(_("*ssl-cert* value expansion failed: %s\n"),
1009 n_shexp_quote_cp(cp, FAL0));
1010 goto jleave;
1012 if(!a_xtls_conf(confp, "Certificate", certchain = cp_base))
1013 goto jleave;
1016 /* CipherString via ssl-ciper-list */
1017 if((cp = xok_vlook(ssl_cipher_list, urlp, OXM_ALL)) != NULL){
1018 n_OBSOLETE(_("please use *tls-config-pairs* instead of "
1019 "*ssl-cipher-list*"));
1020 if(!a_xtls_conf(confp, "CipherString", cp))
1021 goto jleave;
1024 /* Curves via ssl-curves */
1025 if((cp = xok_vlook(ssl_curves, urlp, OXM_ALL)) != NULL){
1026 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-curves*"));
1027 if(!a_xtls_conf(confp, "Curves", cp))
1028 goto jleave;
1031 /* PrivateKey via ssl-key */
1032 if((cp = xok_vlook(ssl_key, urlp, OXM_ALL)) != NULL){
1033 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-key*"));
1034 if((cp_base = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) == NULL){
1035 n_err(_("*ssl-key* value expansion failed: %s\n"),
1036 n_shexp_quote_cp(cp, FAL0));
1037 goto jleave;
1039 cp = cp_base;
1040 if(certchain == NULL){
1041 n_err(_("*ssl-key* can only be used together with *ssl-cert*! "
1042 "And use *ssl-config-pairs*!\n"));
1043 goto jleave;
1046 if((cp != NULL || (cp = certchain) != NULL) &&
1047 !a_xtls_conf(confp, "PrivateKey", cp))
1048 goto jleave;
1050 /* Protocol via ssl-method or ssl-protocol */
1051 if((cp = xok_vlook(ssl_method, urlp, OXM_ALL)) != NULL){
1052 size_t i;
1054 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-method*"));
1055 for(i = 0;;){
1056 if(!asccasecmp(_ssl_methods[i].sm_name, cp)){
1057 cp = _ssl_methods[i].sm_map;
1058 break;
1060 if(++i == n_NELEM(_ssl_methods)){
1061 n_err(_("Unsupported SSL method: %s\n"), cp);
1062 goto jleave;
1066 if((cp_base = xok_vlook(ssl_protocol, urlp, OXM_ALL)) != NULL){
1067 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-protocol*"));
1068 if(cp != NULL && (n_poption & n_PO_D_V))
1069 n_err(_("*ssl-protocol* overrides *ssl-method*! "
1070 "And please use *tls-config-pairs* instead!\n"));
1071 cp = cp_base;
1073 if(cp != NULL && !a_xtls_conf(confp, "Protocol", cp))
1074 goto jleave;
1076 rv = TRU1;
1077 jleave:
1078 NYD2_LEAVE;
1079 return rv;
1082 static bool_t
1083 a_xtls_config_pairs(void *confp, struct url const *urlp){
1084 /* Due to interdependencies some commands have to be delayed a bit */
1085 static char const cmdcert[] = "Certificate", cmdprivkey[] = "PrivateKey";
1086 char const *valcert, *valprivkey;
1087 char *pairs, *cp, *cmd, *val;
1088 NYD2_ENTER;
1090 if((pairs = n_UNCONST(xok_vlook(tls_config_pairs, urlp, OXM_ALL))
1091 ) == NULL &&
1092 (pairs = n_UNCONST(xok_vlook(ssl_config_pairs, urlp, OXM_ALL))
1093 ) == NULL)
1094 goto jleave;
1095 pairs = savestr(pairs);
1097 valcert = valprivkey = NULL;
1099 while((cp = n_strsep_esc(&pairs, ',', FAL0)) != NULL){
1100 char c;
1101 enum{
1102 a_NONE,
1103 a_EXPAND = 1u<<0,
1104 a_CERT = 1u<<1,
1105 a_PRIVKEY = 1u<<2,
1106 a_EXPAND_MASK = a_EXPAND | a_CERT | a_PRIVKEY
1107 } f;
1109 /* Directive, space trimmed */
1110 if((cmd = strchr(cp, '=')) == NULL){
1111 jenocmd:
1112 if(pairs == NULL)
1113 pairs = n_UNCONST(n_empty);
1114 n_err(_("*tls-config-pairs*: missing directive: %s; rest: %s\n"),
1115 n_shexp_quote_cp(cp, FAL0), n_shexp_quote_cp(pairs, FAL0));
1116 goto jleave;
1118 val = &cmd[1];
1120 if((cmd > cp && cmd[-1] == '*')){
1121 --cmd;
1122 f = a_EXPAND;
1123 }else
1124 f = a_NONE;
1125 while(cmd > cp && (c = cmd[-1], blankspacechar(c)))
1126 --cmd;
1127 if(cmd == cp)
1128 goto jenocmd;
1129 *cmd = '\0';
1130 cmd = cp;
1132 /* Command with special treatment? */
1133 if(!asccasecmp(cmd, cmdcert))
1134 f |= a_CERT;
1135 else if(!asccasecmp(cmd, cmdprivkey))
1136 f |= a_PRIVKEY;
1138 /* Value, space trimmed */
1139 while((c = *val) != '\0' && blankspacechar(c))
1140 ++val;
1141 cp = &val[strlen(val)];
1142 while(cp > val && (c = cp[-1], blankspacechar(c)))
1143 --cp;
1144 *cp = '\0';
1145 if(cp == val){
1146 if(pairs == NULL)
1147 pairs = n_UNCONST(n_empty);
1148 n_err(_("*tls-config-pairs*: missing value: %s; rest: %s\n"),
1149 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(pairs, FAL0));
1150 goto jleave;
1153 /* Filename transformations to be applied? */
1154 if(f & a_EXPAND_MASK){
1155 if((cp = fexpand(val, FEXP_LOCAL | FEXP_NOPROTO)) == NULL){
1156 if(pairs == NULL)
1157 pairs = n_UNCONST(n_empty);
1158 n_err(_("*tls-config-pairs*: value expansion failed: %s: %s; "
1159 "rest: %s\n"),
1160 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(val, FAL0),
1161 n_shexp_quote_cp(pairs, FAL0));
1162 goto jleave;
1164 val = cp;
1167 /* Some things have to be delayed */
1168 if(f & a_CERT)
1169 valcert = val;
1170 else if(f & a_PRIVKEY)
1171 valprivkey = val;
1172 else if(!a_xtls_conf(confp, cmd, val)){
1173 pairs = n_UNCONST(n_empty);
1174 goto jleave;
1178 /* Work the delayed ones */
1179 if((valcert != NULL && !a_xtls_conf(confp, cmdcert, valcert)) ||
1180 ((valprivkey != NULL || (valprivkey = valcert) != NULL) &&
1181 !a_xtls_conf(confp, cmdprivkey, valprivkey)))
1182 pairs = n_UNCONST(n_empty);
1184 jleave:
1185 NYD2_LEAVE;
1186 return (pairs == NULL);
1189 static bool_t
1190 a_xtls_load_verifications(SSL_CTX *ctxp, struct url const *urlp){
1191 char *ca_dir, *ca_file;
1192 X509_STORE *store;
1193 bool_t rv;
1194 NYD2_ENTER;
1196 if(n_tls_verify_level == n_TLS_VERIFY_IGNORE){
1197 rv = TRU1;
1198 goto jleave;
1200 rv = FAL0;
1202 if((ca_dir = xok_vlook(tls_ca_dir, urlp, OXM_ALL)) != NULL ||
1203 (ca_dir = xok_vlook(ssl_ca_dir, urlp, OXM_ALL)) != NULL)
1204 ca_dir = fexpand(ca_dir, FEXP_LOCAL | FEXP_NOPROTO);
1205 if((ca_file = xok_vlook(tls_ca_file, urlp, OXM_ALL)) != NULL ||
1206 (ca_file = xok_vlook(ssl_ca_file, urlp, OXM_ALL)) != NULL)
1207 ca_file = fexpand(ca_file, FEXP_LOCAL | FEXP_NOPROTO);
1209 if((ca_dir != NULL || ca_file != NULL) &&
1210 SSL_CTX_load_verify_locations(ctxp, ca_file, ca_dir) != 1){
1211 char const *m1, *m2, *m3;
1213 if(ca_dir != NULL){
1214 m1 = ca_dir;
1215 m2 = (ca_file != NULL) ? _(" or ") : n_empty;
1216 }else
1217 m1 = m2 = n_empty;
1218 m3 = (ca_file != NULL) ? ca_file : n_empty;
1219 ssl_gen_err(_("Error loading %s%s%s\n"), m1, m2, m3);
1220 goto jleave;
1223 /* C99 */{
1224 bool_t xv15;
1226 if((xv15 = ok_blook(ssl_no_default_ca)))
1227 n_OBSOLETE(_("please use *tls-ca-no-defaults*, "
1228 "not *ssl-no-default-ca*"));
1229 if(!xok_blook(tls_ca_no_defaults, urlp, OXM_ALL) &&
1230 !xok_blook(ssl_ca_no_defaults, urlp, OXM_ALL) && !xv15 &&
1231 SSL_CTX_set_default_verify_paths(ctxp) != 1) {
1232 ssl_gen_err(_("Error loading built-in default CA locations\n"));
1233 goto jleave;
1237 a_xtls_state &= ~a_XTLS_S_VERIFY_ERROR;
1238 a_xtls_msgno = 0;
1239 SSL_CTX_set_verify(ctxp, SSL_VERIFY_PEER, &a_xtls_verify_cb);
1240 store = SSL_CTX_get_cert_store(ctxp);
1241 load_crls(store, ok_v_tls_crl_file, ok_v_tls_crl_dir);
1242 a_xtls_ca_flags(store, xok_vlook(tls_ca_flags, urlp, OXM_ALL));
1243 a_xtls_ca_flags(store, xok_vlook(ssl_ca_flags, urlp, OXM_ALL));
1245 rv = TRU1;
1246 jleave:
1247 NYD2_LEAVE;
1248 return rv;
1251 static bool_t
1252 a_xtls_check_host(struct sock *sp, X509 *peercert, struct url const *urlp){
1253 char data[256];
1254 n_XTLS_STACKOF(GENERAL_NAME) *gens;
1255 GENERAL_NAME *gen;
1256 X509_NAME *subj;
1257 bool_t rv;
1258 NYD_ENTER;
1259 n_UNUSED(sp);
1261 rv = FAL0;
1263 if((gens = X509_get_ext_d2i(peercert, NID_subject_alt_name, NULL, NULL)
1264 ) != NULL){
1265 int i;
1267 for(i = 0; i < sk_GENERAL_NAME_num(gens); ++i){
1268 gen = sk_GENERAL_NAME_value(gens, i);
1269 if(gen->type == GEN_DNS){
1270 if(n_poption & n_PO_D_V)
1271 n_err(_("Comparing subject_alt_name: need<%s> is<%s>\n"),
1272 urlp->url_host.s, (char*)gen->d.ia5->data);
1273 if((rv = n_tls_rfc2595_hostname_match(urlp->url_host.s,
1274 (char*)gen->d.ia5->data)))
1275 goto jleave;
1280 if((subj = X509_get_subject_name(peercert)) != NULL &&
1281 X509_NAME_get_text_by_NID(subj, NID_commonName, data, sizeof data
1282 ) > 0){
1283 data[sizeof data - 1] = '\0';
1284 if(n_poption & n_PO_D_V)
1285 n_err(_("Comparing commonName: need<%s> is<%s>\n"),
1286 urlp->url_host.s, data);
1287 rv = n_tls_rfc2595_hostname_match(urlp->url_host.s, data);
1289 jleave:
1290 NYD_LEAVE;
1291 return rv;
1294 static int
1295 smime_verify(struct message *m, int n, n_XTLS_STACKOF(X509) *chain,
1296 X509_STORE *store)
1298 char data[LINESIZE], *sender, *to, *cc, *cnttype;
1299 int rv, c, i, j;
1300 struct message *x;
1301 FILE *fp, *ip;
1302 off_t size;
1303 BIO *fb, *pb;
1304 PKCS7 *pkcs7;
1305 n_XTLS_STACKOF(X509) *certs;
1306 n_XTLS_STACKOF(GENERAL_NAME) *gens;
1307 X509 *cert;
1308 X509_NAME *subj;
1309 GENERAL_NAME *gen;
1310 NYD_ENTER;
1312 rv = 1;
1313 fp = NULL;
1314 fb = pb = NULL;
1315 pkcs7 = NULL;
1316 certs = NULL;
1317 a_xtls_state &= ~a_XTLS_S_VERIFY_ERROR;
1318 a_xtls_msgno = (size_t)n;
1320 for (;;) {
1321 sender = getsender(m);
1322 to = hfield1("to", m);
1323 cc = hfield1("cc", m);
1324 cnttype = hfield1("content-type", m);
1326 #undef _X
1327 #undef _Y
1328 #define _X (sizeof("application/") -1)
1329 #define _Y(X) X, sizeof(X) -1
1330 if (cnttype && is_asccaseprefix("application/", cnttype) &&
1331 (!ascncasecmp(cnttype + _X, _Y("pkcs7-mime")) ||
1332 !ascncasecmp(cnttype + _X, _Y("x-pkcs7-mime")))) {
1333 #undef _Y
1334 #undef _X
1335 if ((x = smime_decrypt(m, to, cc, 1)) == NULL)
1336 goto jleave;
1337 if (x != (struct message*)-1) {
1338 m = x;
1339 continue;
1343 if ((ip = setinput(&mb, m, NEED_BODY)) == NULL)
1344 goto jleave;
1345 size = m->m_size;
1346 break;
1349 if ((fp = Ftmp(NULL, "smimever", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
1350 NULL) {
1351 n_perr(_("tempfile"), 0);
1352 goto jleave;
1354 while (size-- > 0) {
1355 c = getc(ip);
1356 putc(c, fp);
1358 fflush_rewind(fp);
1360 if ((fb = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
1361 ssl_gen_err(_(
1362 "Error creating BIO verification object for message %d"), n);
1363 goto jleave;
1366 if ((pkcs7 = SMIME_read_PKCS7(fb, &pb)) == NULL) {
1367 ssl_gen_err(_("Error reading PKCS#7 object for message %d"), n);
1368 goto jleave;
1370 if (PKCS7_verify(pkcs7, chain, store, pb, NULL, 0) != 1) {
1371 ssl_gen_err(_("Error verifying message %d"), n);
1372 goto jleave;
1375 if (sender == NULL) {
1376 n_err(_("Warning: Message %d has no sender\n"), n);
1377 rv = 0;
1378 goto jleave;
1381 certs = PKCS7_get0_signers(pkcs7, chain, 0);
1382 if (certs == NULL) {
1383 n_err(_("No certificates found in message %d\n"), n);
1384 goto jleave;
1387 for (i = 0; i < sk_X509_num(certs); ++i) {
1388 cert = sk_X509_value(certs, i);
1389 gens = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
1390 if (gens != NULL) {
1391 for (j = 0; j < sk_GENERAL_NAME_num(gens); ++j) {
1392 gen = sk_GENERAL_NAME_value(gens, j);
1393 if (gen->type == GEN_EMAIL) {
1394 if (n_poption & n_PO_D_V)
1395 n_err(_("Comparing subject_alt_name: need<%s> is<%s>)\n"),
1396 sender, (char*)gen->d.ia5->data);
1397 if (!asccasecmp((char*)gen->d.ia5->data, sender))
1398 goto jfound;
1403 if ((subj = X509_get_subject_name(cert)) != NULL &&
1404 X509_NAME_get_text_by_NID(subj, NID_pkcs9_emailAddress,
1405 data, sizeof data) > 0) {
1406 data[sizeof data -1] = '\0';
1407 if (n_poption & n_PO_D_V)
1408 n_err(_("Comparing emailAddress: need<%s> is<%s>\n"),
1409 sender, data);
1410 if (!asccasecmp(data, sender))
1411 goto jfound;
1414 n_err(_("Message %d: certificate does not match <%s>\n"), n, sender);
1415 goto jleave;
1416 jfound:
1417 rv = ((a_xtls_state & a_XTLS_S_VERIFY_ERROR) != 0);
1418 if (!rv)
1419 fprintf(n_stdout, _("Message %d was verified successfully\n"), n);
1420 jleave:
1421 if (certs != NULL)
1422 sk_X509_free(certs);
1423 if (pb != NULL)
1424 BIO_free(pb);
1425 if (fb != NULL)
1426 BIO_free(fb);
1427 if (pkcs7 != NULL)
1428 PKCS7_free(pkcs7);
1429 if (fp != NULL)
1430 Fclose(fp);
1431 NYD_LEAVE;
1432 return rv;
1435 static EVP_CIPHER const *
1436 _smime_cipher(char const *name)
1438 EVP_CIPHER const *cipher;
1439 char *vn;
1440 char const *cp;
1441 size_t i;
1442 NYD_ENTER;
1444 vn = n_lofi_alloc(i = strlen(name) + sizeof("smime-cipher-") -1 +1);
1445 snprintf(vn, (int)i, "smime-cipher-%s", name);
1446 cp = n_var_vlook(vn, FAL0);
1447 n_lofi_free(vn);
1449 if (cp == NULL && (cp = ok_vlook(smime_cipher)) == NULL) {
1450 cipher = a_XTLS_SMIME_DEFAULT_CIPHER();
1451 goto jleave;
1453 cipher = NULL;
1455 for(i = 0; i < n_NELEM(a_xtls_ciphers); ++i)
1456 if(!asccasecmp(a_xtls_ciphers[i].xc_name, cp)){
1457 cipher = (*a_xtls_ciphers[i].xc_fun)();
1458 goto jleave;
1460 #ifndef OPENSSL_NO_AES
1461 for (i = 0; i < n_NELEM(a_xtls_smime_ciphers_obs); ++i) /* TODO obsolete */
1462 if (!asccasecmp(a_xtls_smime_ciphers_obs[i].xc_name, cp)) {
1463 n_OBSOLETE2(_("*smime-cipher* names with hyphens will vanish"), cp);
1464 cipher = (*a_xtls_smime_ciphers_obs[i].xc_fun)();
1465 goto jleave;
1467 #endif
1469 /* Not a built-in algorithm, but we may have dynamic support for more */
1470 #ifdef HAVE_TLS_ALL_ALGORITHMS
1471 if((cipher = EVP_get_cipherbyname(cp)) != NULL)
1472 goto jleave;
1473 #endif
1475 n_err(_("Invalid S/MIME cipher(s): %s\n"), cp);
1476 jleave:
1477 NYD_LEAVE;
1478 return cipher;
1481 static int
1482 ssl_password_cb(char *buf, int size, int rwflag, void *userdata)
1484 char *pass;
1485 size_t len;
1486 NYD_ENTER;
1487 n_UNUSED(rwflag);
1488 n_UNUSED(userdata);
1490 /* New-style */
1491 if(userdata != NULL){
1492 struct url url;
1493 struct ccred cred;
1495 if(url_parse(&url, CPROTO_CCRED, userdata)){
1496 if(ccred_lookup(&cred, &url)){
1497 ssize_t slen;
1499 if((slen = n_strscpy(buf, cred.cc_pass.s, size)) >= 0){
1500 size = (int)slen;
1501 goto jleave;
1504 size = 0;
1505 goto jleave;
1509 /* Old-style */
1510 if ((pass = getpassword("PEM pass phrase:")) != NULL) {
1511 len = strlen(pass);
1512 if (UICMP(z, len, >=, size))
1513 len = size -1;
1514 memcpy(buf, pass, len);
1515 buf[len] = '\0';
1516 size = (int)len;
1517 } else
1518 size = 0;
1519 jleave:
1520 NYD_LEAVE;
1521 return size;
1524 static FILE *
1525 smime_sign_cert(char const *xname, char const *xname2, bool_t dowarn,
1526 char const **match)
1528 char *vn;
1529 int vs;
1530 struct name *np;
1531 char const *name = xname, *name2 = xname2, *cp;
1532 FILE *fp = NULL;
1533 NYD_ENTER;
1535 jloop:
1536 if (name) {
1537 np = lextract(name, GTO | GSKIN);
1538 while (np != NULL) {
1539 /* This needs to be more intelligent since it will currently take the
1540 * first name for which a private key is available regardless of
1541 * whether it is the right one for the message */
1542 vn = n_lofi_alloc(vs = strlen(np->n_name) + 30);
1543 snprintf(vn, vs, "smime-sign-cert-%s", np->n_name);
1544 cp = n_var_vlook(vn, FAL0);
1545 n_lofi_free(vn);
1546 if (cp != NULL) {
1547 if (match != NULL)
1548 *match = np->n_name;
1549 goto jopen;
1551 np = np->n_flink;
1553 if (name2 != NULL) {
1554 name = name2;
1555 name2 = NULL;
1556 goto jloop;
1560 if ((cp = ok_vlook(smime_sign_cert)) == NULL)
1561 goto jerr;
1562 if(match != NULL)
1563 *match = NULL;
1564 jopen:
1565 if ((cp = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) == NULL)
1566 goto jleave;
1567 if ((fp = Fopen(cp, "r")) == NULL)
1568 n_perr(cp, 0);
1569 jleave:
1570 NYD_LEAVE;
1571 return fp;
1572 jerr:
1573 if (dowarn)
1574 n_err(_("Could not find a certificate for %s%s%s\n"),
1575 xname, (xname2 != NULL ? _("or ") : n_empty),
1576 (xname2 != NULL ? xname2 : n_empty));
1577 goto jleave;
1580 static char const *
1581 _smime_sign_include_certs(char const *name)
1583 char const *rv;
1584 NYD_ENTER;
1586 /* See comments in smime_sign_cert() for algorithm pitfalls */
1587 if (name != NULL) {
1588 struct name *np;
1590 for (np = lextract(name, GTO | GSKIN); np != NULL; np = np->n_flink) {
1591 int vs;
1592 char *vn;
1594 vn = n_lofi_alloc(vs = strlen(np->n_name) + 30);
1595 snprintf(vn, vs, "smime-sign-include-certs-%s", np->n_name);
1596 rv = n_var_vlook(vn, FAL0);
1597 n_lofi_free(vn);
1598 if (rv != NULL)
1599 goto jleave;
1602 rv = ok_vlook(smime_sign_include_certs);
1603 jleave:
1604 NYD_LEAVE;
1605 return rv;
1608 static bool_t
1609 _smime_sign_include_chain_creat(n_XTLS_STACKOF(X509) **chain,
1610 char const *cfiles, char const *addr)
1612 X509 *tmp;
1613 FILE *fp;
1614 char *nfield, *cfield, *x;
1615 NYD_ENTER;
1617 *chain = sk_X509_new_null();
1619 for (nfield = savestr(cfiles);
1620 (cfield = n_strsep(&nfield, ',', TRU1)) != NULL;) {
1621 if ((x = fexpand(cfield, FEXP_LOCAL | FEXP_NOPROTO)) == NULL ||
1622 (fp = Fopen(cfield = x, "r")) == NULL) {
1623 n_perr(cfiles, 0);
1624 goto jerr;
1626 if ((tmp = PEM_read_X509(fp, NULL, &ssl_password_cb, n_UNCONST(addr))
1627 ) == NULL) {
1628 ssl_gen_err(_("Error reading certificate from %s"),
1629 n_shexp_quote_cp(cfield, FAL0));
1630 Fclose(fp);
1631 goto jerr;
1633 sk_X509_push(*chain, tmp);
1634 Fclose(fp);
1637 if (sk_X509_num(*chain) == 0) {
1638 n_err(_("*smime-sign-include-certs* defined but empty\n"));
1639 goto jerr;
1641 jleave:
1642 NYD_LEAVE;
1643 return (*chain != NULL);
1644 jerr:
1645 sk_X509_pop_free(*chain, X509_free);
1646 *chain = NULL;
1647 goto jleave;
1650 static EVP_MD const *
1651 a_xtls_smime_sign_digest(char const *name, char const **digname){
1652 EVP_MD const *digest;
1653 char const *cp;
1654 NYD2_ENTER;
1656 /* See comments in smime_sign_cert() for algorithm pitfalls */
1657 if(name != NULL){
1658 struct name *np;
1660 for(np = lextract(name, GTO | GSKIN); np != NULL; np = np->n_flink){
1661 int vs;
1662 char *vn;
1664 vn = n_lofi_alloc(vs = strlen(np->n_name) + 30);
1665 snprintf(vn, vs, "smime-sign-digest-%s", np->n_name);
1666 if((cp = n_var_vlook(vn, FAL0)) == NULL){
1667 snprintf(vn, vs, "smime-sign-message-digest-%s",np->n_name);/*v15*/
1668 cp = n_var_vlook(vn, FAL0);
1670 n_lofi_free(vn);
1671 if(cp != NULL)
1672 goto jhave_name;
1676 if((cp = ok_vlook(smime_sign_digest)) != NULL ||
1677 (cp = ok_vlook(smime_sign_message_digest)/* v15 */) != NULL)
1678 jhave_name:
1679 if(a_xtls_digest_find(cp, &digest, digname))
1680 goto jleave;
1682 digest = a_XTLS_SMIME_DEFAULT_DIGEST();
1683 *digname = a_XTLS_SMIME_DEFAULT_DIGEST_S;
1684 jleave:
1685 NYD2_LEAVE;
1686 return digest;
1689 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1690 static enum okay
1691 load_crl1(X509_STORE *store, char const *name)
1693 X509_LOOKUP *lookup;
1694 enum okay rv = STOP;
1695 NYD_ENTER;
1697 if (n_poption & n_PO_D_V)
1698 n_err(_("Loading CRL from %s\n"), n_shexp_quote_cp(name, FAL0));
1699 if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) == NULL) {
1700 ssl_gen_err(_("Error creating X509 lookup object"));
1701 goto jleave;
1703 if (X509_load_crl_file(lookup, name, X509_FILETYPE_PEM) != 1) {
1704 ssl_gen_err(_("Error loading CRL from %s"),
1705 n_shexp_quote_cp(name, FAL0));
1706 goto jleave;
1708 rv = OKAY;
1709 jleave:
1710 NYD_LEAVE;
1711 return rv;
1713 #endif /* new OpenSSL */
1715 static enum okay
1716 load_crls(X509_STORE *store, enum okeys fok, enum okeys dok)/*TODO nevertried*/
1718 char *crl_file, *crl_dir;
1719 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1720 DIR *dirp;
1721 struct dirent *dp;
1722 char *fn = NULL;
1723 int fs = 0, ds, es;
1724 #endif
1725 bool_t any;
1726 enum okay rv;
1727 NYD_ENTER;
1729 rv = STOP;
1730 any = FAL0;
1732 jredo_v15:
1733 if ((crl_file = n_var_oklook(fok)) != NULL) {
1734 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1735 if ((crl_file = fexpand(crl_file, FEXP_LOCAL | FEXP_NOPROTO)) == NULL ||
1736 load_crl1(store, crl_file) != OKAY)
1737 goto jleave;
1738 any = TRU1;
1739 #else
1740 n_err(_("This OpenSSL version is too old to use CRLs\n"));
1741 goto jleave;
1742 #endif
1745 if ((crl_dir = n_var_oklook(dok)) != NULL) {
1746 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1747 char *x;
1748 if ((x = fexpand(crl_dir, FEXP_LOCAL | FEXP_NOPROTO)) == NULL ||
1749 (dirp = opendir(crl_dir = x)) == NULL) {
1750 n_perr(crl_dir, 0);
1751 goto jleave;
1754 ds = strlen(crl_dir);
1755 fn = n_alloc(fs = ds + 20);
1756 memcpy(fn, crl_dir, ds);
1757 fn[ds] = '/';
1758 while ((dp = readdir(dirp)) != NULL) {
1759 if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
1760 (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
1761 continue;
1762 if (dp->d_name[0] == '.')
1763 continue;
1764 if (ds + (es = strlen(dp->d_name)) + 2 < fs)
1765 fn = n_realloc(fn, fs = ds + es + 20);
1766 memcpy(fn + ds + 1, dp->d_name, es + 1);
1767 if (load_crl1(store, fn) != OKAY) {
1768 closedir(dirp);
1769 n_free(fn);
1770 goto jleave;
1772 any = TRU1;
1774 closedir(dirp);
1775 n_free(fn);
1776 #else /* old OpenSSL */
1777 n_err(_("This OpenSSL version is too old to use CRLs\n"));
1778 goto jleave;
1779 #endif
1782 if(fok == ok_v_tls_crl_file){
1783 fok = ok_v_ssl_crl_file;
1784 dok = ok_v_ssl_crl_dir;
1785 goto jredo_v15;
1787 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1788 if(any)
1789 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
1790 X509_V_FLAG_CRL_CHECK_ALL);
1791 #endif
1792 rv = OKAY;
1793 jleave:
1794 NYD_LEAVE;
1795 return rv;
1798 #if HAVE_RANDOM == n_RANDOM_IMPL_TLS
1799 FL void
1800 n_tls_rand_bytes(void *buf, size_t blen){
1801 NYD2_ENTER;
1803 if(!(a_xtls_state & a_XTLS_S_RAND_INIT))
1804 a_xtls_rand_init();
1806 while(blen > 0){
1807 si32_t i;
1809 i = n_MIN(SI32_MAX, blen);
1810 blen -= i;
1811 RAND_bytes(buf, i);
1812 buf = (ui8_t*)buf + i;
1814 NYD2_LEAVE;
1816 #endif
1818 FL bool_t
1819 n_tls_open(struct url *urlp, struct sock *sp){
1820 void *confp;
1821 SSL_CTX *ctxp;
1822 const EVP_MD *fprnt_mdp;
1823 char const *fprnt, *fprnt_namep;
1824 NYD_ENTER;
1826 a_xtls_init();
1827 n_tls_set_verify_level(urlp); /* TODO should come in via URL! */
1829 sp->s_tls = NULL;
1830 if(urlp->url_cproto != CPROTO_CERTINFO)
1831 fprnt = xok_vlook(tls_fingerprint, urlp, OXM_ALL);
1832 else
1833 fprnt = NULL;
1834 fprnt_namep = NULL;
1835 fprnt_mdp = NULL;
1837 if(fprnt != NULL || urlp->url_cproto == CPROTO_CERTINFO ||
1838 (n_poption & n_PO_D_V)){
1839 if((fprnt_namep = xok_vlook(tls_fingerprint_digest, urlp,
1840 OXM_ALL)) == NULL ||
1841 !a_xtls_digest_find(fprnt_namep, &fprnt_mdp, &fprnt_namep)){
1842 fprnt_mdp = a_XTLS_FINGERPRINT_DEFAULT_DIGEST();
1843 fprnt_namep = a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S;
1847 if((ctxp = SSL_CTX_new(n_XTLS_CLIENT_METHOD())) == NULL){
1848 ssl_gen_err(_("SSL_CTX_new() failed"));
1849 goto j_leave;
1852 /* Available with OpenSSL 0.9.6 or later */
1853 #ifdef SSL_MODE_AUTO_RETRY
1854 SSL_CTX_set_mode(ctxp, SSL_MODE_AUTO_RETRY);
1855 #endif
1857 if((confp = a_xtls_conf_setup(ctxp, urlp)) == NULL)
1858 goto jleave;
1860 if(!a_xtls_obsolete_conf_vars(confp, urlp))
1861 goto jerr1;
1862 if(!a_xtls_config_pairs(confp, urlp))
1863 goto jerr1;
1864 if((fprnt == NULL || urlp->url_cproto == CPROTO_CERTINFO) &&
1865 !a_xtls_load_verifications(ctxp, urlp))
1866 goto jerr1;
1868 /* Done with context setup, create our new per-connection structure */
1869 if(!a_xtls_conf_finish(&confp, FAL0))
1870 goto jleave;
1871 assert(confp == NULL);
1873 if((sp->s_tls = SSL_new(ctxp)) == NULL){
1874 ssl_gen_err(_("SSL_new() failed"));
1875 goto jleave;
1878 /* Try establish SNI extension; even though this is a TLS extension the
1879 * protocol isn't checked by OpenSSL once the host name is set, and
1880 * therefore i refrained from changing so much code just to check out
1881 * whether we are using SSLv3, which should become more and more rare */
1882 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1883 if((urlp->url_flags & n_URL_TLS_MASK) &&
1884 (urlp->url_flags & n_URL_HOST_IS_NAME)){
1885 if(!SSL_set_tlsext_host_name(sp->s_tls, urlp->url_host.s) &&
1886 (n_poption & n_PO_D_V))
1887 n_err(_("Hostname cannot be used with ServerNameIndication "
1888 "TLS extension: %s\n"),
1889 n_shexp_quote_cp(urlp->url_host.s, FAL0));
1891 #endif
1893 SSL_set_fd(sp->s_tls, sp->s_fd);
1895 if(SSL_connect(sp->s_tls) < 0){
1896 ssl_gen_err(_("could not initiate TLS connection"));
1897 goto jerr2;
1900 if(fprnt != NULL || urlp->url_cproto == CPROTO_CERTINFO ||
1901 n_tls_verify_level != n_TLS_VERIFY_IGNORE){
1902 bool_t stay;
1903 X509 *peercert;
1905 if((peercert = SSL_get_peer_certificate(sp->s_tls)) == NULL){
1906 n_err(_("TLS: no certificate from peer: %s\n"), urlp->url_h_p.s);
1907 goto jerr2;
1910 stay = FAL0;
1912 if(fprnt == NULL){
1913 if(!a_xtls_check_host(sp, peercert, urlp)){
1914 n_err(_("TLS certificate does not match: %s\n"), urlp->url_h_p.s);
1915 stay = n_tls_verify_decide();
1916 }else{
1917 if(n_poption & n_PO_D_V)
1918 n_err(_("TLS certificate ok\n"));
1919 stay = TRU1;
1923 if(fprnt != NULL || urlp->url_cproto == CPROTO_CERTINFO ||
1924 (n_poption & n_PO_D_V)){
1925 char fpmdhexbuf[EVP_MAX_MD_SIZE * 3], *cp;
1926 unsigned char fpmdbuf[EVP_MAX_MD_SIZE], *ucp;
1927 unsigned int fpmdlen;
1929 if(!X509_digest(peercert, fprnt_mdp, fpmdbuf, &fpmdlen)){
1930 ssl_gen_err(_("TLS %s fingerprint creation failed"), fprnt_namep);
1931 goto jpeer_leave;
1933 assert(fpmdlen <= EVP_MAX_MD_SIZE);
1935 for(cp = fpmdhexbuf, ucp = fpmdbuf; fpmdlen > 0; --fpmdlen){
1936 n_c_to_hex_base16(cp, (char)*ucp++);
1937 cp[2] = ':';
1938 cp += 3;
1940 cp[-1] = '\0';
1942 if(n_poption & n_PO_D_V)
1943 n_err(_("TLS %s fingerprint: %s\n"), fprnt_namep, fpmdhexbuf);
1944 if(fprnt != NULL){
1945 if(!(stay = !strcmp(fprnt, fpmdhexbuf))){
1946 n_err(_("TLS fingerprint does not match: %s\n"
1947 " Expected: %s\n Detected: %s\n"),
1948 urlp->url_h_p.s, fprnt, fpmdhexbuf);
1949 stay = n_tls_verify_decide();
1950 }else if(n_poption & n_PO_D_V)
1951 n_err(_("TLS fingerprint ok\n"));
1952 goto jpeer_leave;
1953 }else if(urlp->url_cproto == CPROTO_CERTINFO)
1954 sp->s_tls_finger = savestrbuf(fpmdhexbuf,
1955 PTR2SIZE(cp - fpmdhexbuf));
1958 jpeer_leave:
1959 X509_free(peercert);
1960 if(!stay)
1961 goto jerr2;
1964 sp->s_use_tls = 1;
1965 jleave:
1966 /* We're fully setup: since we don't reuse the SSL_CTX (pooh) keep it local
1967 * and free it right now -- it is reference counted by sp->s_tls.. */
1968 SSL_CTX_free(ctxp);
1969 j_leave:
1970 NYD_LEAVE;
1971 return (sp->s_tls != NULL);
1972 jerr2:
1973 SSL_free(sp->s_tls);
1974 sp->s_tls = NULL;
1975 jerr1:
1976 if(confp != NULL)
1977 a_xtls_conf_finish(&confp, TRU1);
1978 goto jleave;
1981 FL void
1982 ssl_gen_err(char const *fmt, ...)
1984 va_list ap;
1985 NYD_ENTER;
1987 va_start(ap, fmt);
1988 n_verr(fmt, ap);
1989 va_end(ap);
1991 n_err(_(": %s\n"), ERR_error_string(ERR_get_error(), NULL));
1992 NYD_LEAVE;
1995 FL int
1996 c_verify(void *vp)
1998 int *msgvec = vp, *ip, ec = 0, rv = 1;
1999 X509_STORE *store = NULL;
2000 char *ca_dir, *ca_file;
2001 NYD_ENTER;
2003 a_xtls_init();
2005 n_tls_verify_level = n_TLS_VERIFY_STRICT;
2006 if ((store = X509_STORE_new()) == NULL) {
2007 ssl_gen_err(_("Error creating X509 store"));
2008 goto jleave;
2010 X509_STORE_set_verify_cb_func(store, &a_xtls_verify_cb);
2012 if ((ca_dir = ok_vlook(smime_ca_dir)) != NULL)
2013 ca_dir = fexpand(ca_dir, FEXP_LOCAL | FEXP_NOPROTO);
2014 if ((ca_file = ok_vlook(smime_ca_file)) != NULL)
2015 ca_file = fexpand(ca_file, FEXP_LOCAL | FEXP_NOPROTO);
2017 if((ca_dir != NULL || ca_file != NULL) &&
2018 X509_STORE_load_locations(store, ca_file, ca_dir) != 1){
2019 char const *m1, *m2, *m3;
2021 if(ca_dir != NULL){
2022 m1 = ca_dir;
2023 m2 = (ca_file != NULL) ? _(" or ") : n_empty;
2024 }else
2025 m1 = m2 = n_empty;
2026 m3 = (ca_file != NULL) ? ca_file : n_empty;
2027 ssl_gen_err(_("Error loading %s%s%s\n"), m1, m2, m3);
2028 goto jleave;
2031 /* C99 */{
2032 bool_t xv15;
2034 if((xv15 = ok_blook(smime_no_default_ca)))
2035 n_OBSOLETE(_("please use *smime-ca-no-defaults*, "
2036 "not *smime-no-default-ca*"));
2037 if(!ok_blook(smime_ca_no_defaults) && !xv15 &&
2038 X509_STORE_set_default_paths(store) != 1) {
2039 ssl_gen_err(_("Error loading built-in default CA locations\n"));
2040 goto jleave;
2044 if (load_crls(store, ok_v_smime_crl_file, ok_v_smime_crl_dir) != OKAY)
2045 goto jleave;
2047 a_xtls_ca_flags(store, ok_vlook(smime_ca_flags));
2049 srelax_hold();
2050 for (ip = msgvec; *ip != 0; ++ip) {
2051 struct message *mp = message + *ip - 1;
2052 setdot(mp);
2053 ec |= smime_verify(mp, *ip, NULL, store);
2054 srelax();
2056 srelax_rele();
2058 if ((rv = ec) != 0)
2059 n_exit_status |= n_EXIT_ERR;
2060 jleave:
2061 if (store != NULL)
2062 X509_STORE_free(store);
2063 NYD_LEAVE;
2064 return rv;
2067 FL FILE *
2068 smime_sign(FILE *ip, char const *addr)
2070 FILE *rv, *sp, *fp, *bp, *hp;
2071 X509 *cert = NULL;
2072 n_XTLS_STACKOF(X509) *chain = NULL;
2073 EVP_PKEY *pkey = NULL;
2074 BIO *bb, *sb;
2075 PKCS7 *pkcs7;
2076 EVP_MD const *md;
2077 char const *name;
2078 bool_t bail = FAL0;
2079 NYD_ENTER;
2081 assert(addr != NULL);
2082 rv = sp = fp = bp = hp = NULL;
2084 a_xtls_init();
2086 if (addr == NULL) {
2087 n_err(_("No *from* address for signing specified\n"));
2088 goto jleave;
2090 if ((fp = smime_sign_cert(addr, NULL, 1, NULL)) == NULL)
2091 goto jleave;
2093 if ((pkey = PEM_read_PrivateKey(fp, NULL, &ssl_password_cb,
2094 savecat(addr, ".smime-cert-key"))) == NULL) {
2095 ssl_gen_err(_("Error reading private key from"));
2096 goto jleave;
2099 rewind(fp);
2100 if ((cert = PEM_read_X509(fp, NULL, &ssl_password_cb,
2101 savecat(addr, ".smime-cert-cert"))) == NULL) {
2102 ssl_gen_err(_("Error reading signer certificate from"));
2103 goto jleave;
2105 Fclose(fp);
2106 fp = NULL;
2108 if ((name = _smime_sign_include_certs(addr)) != NULL &&
2109 !_smime_sign_include_chain_creat(&chain, name,
2110 savecat(addr, ".smime-include-certs")))
2111 goto jleave;
2113 name = NULL;
2114 if ((md = a_xtls_smime_sign_digest(addr, &name)) == NULL)
2115 goto jleave;
2117 if ((sp = Ftmp(NULL, "smimesign", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
2118 NULL) {
2119 n_perr(_("tempfile"), 0);
2120 goto jleave;
2123 rewind(ip);
2124 if (smime_split(ip, &hp, &bp, -1, 0) == STOP)
2125 goto jleave;
2127 sb = NULL;
2128 pkcs7 = NULL;
2130 if ((bb = BIO_new_fp(bp, BIO_NOCLOSE)) == NULL ||
2131 (sb = BIO_new_fp(sp, BIO_NOCLOSE)) == NULL) {
2132 ssl_gen_err(_("Error creating BIO signing objects"));
2133 bail = TRU1;
2134 goto jerr;
2137 #undef _X
2138 #define _X PKCS7_DETACHED | PKCS7_PARTIAL
2139 if ((pkcs7 = PKCS7_sign(NULL, NULL, chain, bb, _X)) == NULL) {
2140 ssl_gen_err(_("Error creating the PKCS#7 signing object"));
2141 bail = TRU1;
2142 goto jerr;
2144 if (PKCS7_sign_add_signer(pkcs7, cert, pkey, md, _X) == NULL) {
2145 ssl_gen_err(_("Error setting PKCS#7 signing object signer"));
2146 bail = TRU1;
2147 goto jerr;
2149 if (!PKCS7_final(pkcs7, bb, _X)) {
2150 ssl_gen_err(_("Error finalizing the PKCS#7 signing object"));
2151 bail = TRU1;
2152 goto jerr;
2154 #undef _X
2156 if (PEM_write_bio_PKCS7(sb, pkcs7) == 0) {
2157 ssl_gen_err(_("Error writing signed S/MIME data"));
2158 bail = TRU1;
2159 /*goto jerr*/
2161 jerr:
2162 if (pkcs7 != NULL)
2163 PKCS7_free(pkcs7);
2164 if (sb != NULL)
2165 BIO_free(sb);
2166 if (bb != NULL)
2167 BIO_free(bb);
2168 if (!bail) {
2169 rewind(bp);
2170 fflush_rewind(sp);
2171 rv = smime_sign_assemble(hp, bp, sp, name);
2172 hp = bp = sp = NULL;
2175 jleave:
2176 if (chain != NULL)
2177 sk_X509_pop_free(chain, X509_free);
2178 if (cert != NULL)
2179 X509_free(cert);
2180 if (pkey != NULL)
2181 EVP_PKEY_free(pkey);
2182 if (fp != NULL)
2183 Fclose(fp);
2184 if (hp != NULL)
2185 Fclose(hp);
2186 if (bp != NULL)
2187 Fclose(bp);
2188 if (sp != NULL)
2189 Fclose(sp);
2190 NYD_LEAVE;
2191 return rv;
2194 FL FILE *
2195 smime_encrypt(FILE *ip, char const *xcertfile, char const *to)
2197 FILE *rv, *yp, *fp, *bp, *hp;
2198 X509 *cert;
2199 PKCS7 *pkcs7;
2200 BIO *bb, *yb;
2201 n_XTLS_STACKOF(X509) *certs;
2202 EVP_CIPHER const *cipher;
2203 char *certfile;
2204 bool_t bail;
2205 NYD_ENTER;
2207 bail = FAL0;
2208 rv = yp = fp = bp = hp = NULL;
2210 if ((certfile = fexpand(xcertfile, FEXP_LOCAL | FEXP_NOPROTO)) == NULL)
2211 goto jleave;
2213 a_xtls_init();
2215 if ((cipher = _smime_cipher(to)) == NULL)
2216 goto jleave;
2218 if ((fp = Fopen(certfile, "r")) == NULL) {
2219 n_perr(certfile, 0);
2220 goto jleave;
2222 if ((cert = PEM_read_X509(fp, NULL, &ssl_password_cb, NULL)) == NULL) {
2223 ssl_gen_err(_("Error reading encryption certificate from %s"),
2224 n_shexp_quote_cp(certfile, FAL0));
2225 bail = TRU1;
2227 if (bail)
2228 goto jleave;
2229 Fclose(fp);
2230 fp = NULL;
2231 bail = FAL0;
2233 certs = sk_X509_new_null();
2234 sk_X509_push(certs, cert);
2236 if ((yp = Ftmp(NULL, "smimeenc", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
2237 NULL) {
2238 n_perr(_("tempfile"), 0);
2239 goto jerr1;
2242 rewind(ip);
2243 if (smime_split(ip, &hp, &bp, -1, 0) == STOP)
2244 goto jerr1;
2246 yb = NULL;
2247 if ((bb = BIO_new_fp(bp, BIO_NOCLOSE)) == NULL ||
2248 (yb = BIO_new_fp(yp, BIO_NOCLOSE)) == NULL) {
2249 ssl_gen_err(_("Error creating BIO encryption objects"));
2250 bail = TRU1;
2251 goto jerr2;
2253 if ((pkcs7 = PKCS7_encrypt(certs, bb, cipher, 0)) == NULL) {
2254 ssl_gen_err(_("Error creating the PKCS#7 encryption object"));
2255 bail = TRU1;
2256 goto jerr2;
2258 if (PEM_write_bio_PKCS7(yb, pkcs7) == 0) {
2259 ssl_gen_err(_("Error writing encrypted S/MIME data"));
2260 bail = TRU1;
2261 /* goto jerr2 */
2263 PKCS7_free(pkcs7);
2265 jerr2:
2266 if (bb != NULL)
2267 BIO_free(bb);
2268 if (yb != NULL)
2269 BIO_free(yb);
2270 Fclose(bp);
2271 bp = NULL;
2272 if (!bail) {
2273 fflush_rewind(yp);
2274 rv = smime_encrypt_assemble(hp, yp);
2275 hp = yp = NULL;
2277 jerr1:
2278 sk_X509_pop_free(certs, X509_free);
2279 jleave:
2280 if(yp != NULL)
2281 Fclose(yp);
2282 if(fp != NULL)
2283 Fclose(fp);
2284 if(bp != NULL)
2285 Fclose(bp);
2286 if(hp != NULL)
2287 Fclose(hp);
2288 NYD_LEAVE;
2289 return rv;
2292 FL struct message *
2293 smime_decrypt(struct message *m, char const *to, char const *cc,
2294 bool_t signcall)
2296 char const *myaddr;
2297 long size;
2298 struct message *rv;
2299 FILE *bp, *hp, *op;
2300 PKCS7 *pkcs7;
2301 BIO *ob, *bb, *pb;
2302 X509 *cert;
2303 EVP_PKEY *pkey;
2304 FILE *yp;
2305 NYD_ENTER;
2307 pkey = NULL;
2308 cert = NULL;
2309 ob = bb = pb = NULL;
2310 pkcs7 = NULL;
2311 bp = hp = op = NULL;
2312 rv = NULL;
2313 size = m->m_size;
2315 if((yp = setinput(&mb, m, NEED_BODY)) == NULL)
2316 goto jleave;
2318 a_xtls_init();
2320 if((op = smime_sign_cert(to, cc, 0, &myaddr)) != NULL){
2321 pkey = PEM_read_PrivateKey(op, NULL, &ssl_password_cb,
2322 savecat(myaddr, ".smime-cert-key"));
2323 if(pkey == NULL){
2324 ssl_gen_err(_("Error reading private key"));
2325 goto jleave;
2328 rewind(op);
2329 if((cert = PEM_read_X509(op, NULL, &ssl_password_cb,
2330 savecat(myaddr, ".smime-cert-cert"))) == NULL){
2331 ssl_gen_err(_("Error reading decryption certificate"));
2332 goto jleave;
2335 Fclose(op);
2336 op = NULL;
2339 if((op = Ftmp(NULL, "smimed", OF_RDWR | OF_UNLINK | OF_REGISTER)) == NULL){
2340 n_perr(_("tempfile"), 0);
2341 goto jleave;
2344 if(smime_split(yp, &hp, &bp, size, 1) == STOP)
2345 goto jleave;
2347 if((ob = BIO_new_fp(op, BIO_NOCLOSE)) == NULL ||
2348 (bb = BIO_new_fp(bp, BIO_NOCLOSE)) == NULL){
2349 ssl_gen_err(_("Error creating BIO decryption objects"));
2350 goto jleave;
2353 if((pkcs7 = SMIME_read_PKCS7(bb, &pb)) == NULL){
2354 ssl_gen_err(_("Error reading PKCS#7 object"));
2355 goto jleave;
2358 if(PKCS7_type_is_signed(pkcs7)){
2359 if(signcall){
2360 setinput(&mb, m, NEED_BODY);
2361 rv = (struct message*)-1;
2362 goto jleave;
2364 if(PKCS7_verify(pkcs7, NULL, NULL, NULL, ob,
2365 PKCS7_NOVERIFY | PKCS7_NOSIGS) != 1)
2366 goto jerr;
2367 fseek(hp, 0L, SEEK_END);
2368 fprintf(hp, "X-Encryption-Cipher: none\n");
2369 fflush_rewind(hp);
2370 }else if(pkey == NULL){
2371 n_err(_("No appropriate private key found\n"));
2372 goto jleave;
2373 }else if(cert == NULL){
2374 n_err(_("No appropriate certificate found\n"));
2375 goto jleave;
2376 }else if(PKCS7_decrypt(pkcs7, pkey, cert, ob, 0) != 1){
2377 jerr:
2378 ssl_gen_err(_("Error decrypting PKCS#7 object"));
2379 goto jleave;
2381 fflush_rewind(op);
2382 Fclose(bp);
2383 bp = NULL;
2385 rv = smime_decrypt_assemble(m, hp, op);
2386 hp = op = NULL; /* xxx closed by decrypt_assemble */
2387 jleave:
2388 if(op != NULL)
2389 Fclose(op);
2390 if(hp != NULL)
2391 Fclose(hp);
2392 if(bp != NULL)
2393 Fclose(bp);
2394 if(bb != NULL)
2395 BIO_free(bb);
2396 if(ob != NULL)
2397 BIO_free(ob);
2398 if(pkcs7 != NULL)
2399 PKCS7_free(pkcs7);
2400 if(cert != NULL)
2401 X509_free(cert);
2402 if(pkey != NULL)
2403 EVP_PKEY_free(pkey);
2404 NYD_LEAVE;
2405 return rv;
2408 FL enum okay
2409 smime_certsave(struct message *m, int n, FILE *op)
2411 struct message *x;
2412 char *to, *cc, *cnttype;
2413 int c, i;
2414 FILE *fp, *ip;
2415 off_t size;
2416 BIO *fb, *pb;
2417 PKCS7 *pkcs7;
2418 n_XTLS_STACKOF(X509) *certs, *chain = NULL;
2419 X509 *cert;
2420 enum okay rv = STOP;
2421 NYD_ENTER;
2423 pkcs7 = NULL;
2425 a_xtls_msgno = (size_t)n;
2426 jloop:
2427 to = hfield1("to", m);
2428 cc = hfield1("cc", m);
2429 cnttype = hfield1("content-type", m);
2431 if ((ip = setinput(&mb, m, NEED_BODY)) == NULL)
2432 goto jleave;
2434 #undef _X
2435 #undef _Y
2436 #define _X (sizeof("application/") -1)
2437 #define _Y(X) X, sizeof(X) -1
2438 if (cnttype && is_asccaseprefix("application/", cnttype) &&
2439 (!ascncasecmp(cnttype + _X, _Y("pkcs7-mime")) ||
2440 !ascncasecmp(cnttype + _X, _Y("x-pkcs7-mime")))) {
2441 #undef _Y
2442 #undef _X
2443 if ((x = smime_decrypt(m, to, cc, 1)) == NULL)
2444 goto jleave;
2445 if (x != (struct message*)-1) {
2446 m = x;
2447 goto jloop;
2450 size = m->m_size;
2452 if ((fp = Ftmp(NULL, "smimecert", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
2453 NULL) {
2454 n_perr(_("tempfile"), 0);
2455 goto jleave;
2458 while (size-- > 0) {
2459 c = getc(ip);
2460 putc(c, fp);
2462 fflush(fp);
2464 rewind(fp);
2465 if ((fb = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
2466 ssl_gen_err("Error creating BIO object for message %d", n);
2467 Fclose(fp);
2468 goto jleave;
2471 if ((pkcs7 = SMIME_read_PKCS7(fb, &pb)) == NULL) {
2472 ssl_gen_err(_("Error reading PKCS#7 object for message %d"), n);
2473 BIO_free(fb);
2474 Fclose(fp);
2475 goto jleave;
2477 BIO_free(fb);
2478 Fclose(fp);
2480 certs = PKCS7_get0_signers(pkcs7, chain, 0);
2481 if (certs == NULL) {
2482 n_err(_("No certificates found in message %d\n"), n);
2483 goto jleave;
2486 for (i = 0; i < sk_X509_num(certs); ++i) {
2487 cert = sk_X509_value(certs, i);
2488 if (X509_print_fp(op, cert) == 0 || PEM_write_X509(op, cert) == 0) {
2489 ssl_gen_err(_("Error writing certificate %d from message %d"),
2490 i, n);
2491 goto jleave;
2494 rv = OKAY;
2495 jleave:
2496 if(pkcs7 != NULL)
2497 PKCS7_free(pkcs7);
2498 NYD_LEAVE;
2499 return rv;
2501 #endif /* HAVE_XTLS */
2503 /* s-it-mode */