README: review
[s-mailx.git] / xtls.c
blob23cbba20049f48e222f0bad6725686ffcac2e7f8
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 * SPDX-License-Identifier: BSD-4-Clause TODO ISC
9 */
11 * Copyright (c) 2002
12 * Gunnar Ritter. All rights reserved.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by Gunnar Ritter
25 * and his contributors.
26 * 4. Neither the name of Gunnar Ritter nor the names of his contributors
27 * may be used to endorse or promote products derived from this software
28 * without specific prior written permission.
30 * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
42 #undef n_FILE
43 #define n_FILE xtls
45 #ifndef HAVE_AMALGAMATION
46 # include "nail.h"
47 #endif
49 EMPTY_FILE()
50 #ifdef HAVE_XTLS
51 #include <sys/socket.h>
53 #include <openssl/crypto.h>
54 #include <openssl/err.h>
55 #include <openssl/evp.h>
56 #include <openssl/opensslv.h>
57 #include <openssl/pem.h>
58 #include <openssl/rand.h>
59 #include <openssl/ssl.h>
60 #include <openssl/x509v3.h>
61 #include <openssl/x509.h>
63 #ifdef HAVE_XTLS_CONFIG
64 # include <openssl/conf.h>
65 #endif
67 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
68 # include <dirent.h>
69 #endif
71 /* Compatibility shims which assume 0/-1 cannot really happen */
72 #ifndef HAVE_XTLS_CONF_CTX
73 # ifndef SSL_OP_NO_SSLv2
74 # define SSL_OP_NO_SSLv2 0
75 # endif
76 # ifndef SSL_OP_NO_SSLv3
77 # define SSL_OP_NO_SSLv3 0
78 # endif
79 # ifndef SSL_OP_NO_TLSv1
80 # define SSL_OP_NO_TLSv1 0
81 # endif
82 # ifndef SSL_OP_NO_TLSv1_1
83 # define SSL_OP_NO_TLSv1_1 0
84 # endif
85 # ifndef SSL_OP_NO_TLSv1_2
86 # define SSL_OP_NO_TLSv1_2 0
87 # endif
88 # ifndef SSL_OP_NO_TLSv1_3
89 # define SSL_OP_NO_TLSv1_3 0
90 # endif
91 /* SSL_CONF_CTX and _OP_NO_SSL_MASK were both introduced with 1.0.2!?! */
92 # ifndef SSL_OP_NO_SSL_MASK
93 # define SSL_OP_NO_SSL_MASK \
94 (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |\
95 SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 |\
96 SSL_OP_NO_TLSv1_3)
97 # endif
99 # ifndef SSL2_VERSION
100 # define SSL2_VERSION 0
101 # endif
102 # ifndef SSL3_VERSION
103 # define SSL3_VERSION 0
104 # endif
105 # ifndef TLS1_VERSION
106 # define TLS1_VERSION 0
107 # endif
108 # ifndef TLS1_1_VERSION
109 # define TLS1_1_VERSION 0
110 # endif
111 # ifndef TLS1_2_VERSION
112 # define TLS1_2_VERSION 0
113 # endif
114 # ifndef TLS1_3_VERSION
115 # define TLS1_3_VERSION 0
116 # endif
117 #endif
119 #ifdef HAVE_XTLS_STACK_OF
120 # define n_XTLS_STACKOF(X) STACK_OF(X)
121 #else
122 # define n_XTLS_STACKOF(X) /*X*/STACK
123 #endif
125 #if OPENSSL_VERSION_NUMBER + 0 >= 0x0090581fL
126 # define a_XTLS_RAND_LOAD_FILE_MAXBYTES -1
127 #else
128 # define a_XTLS_RAND_LOAD_FILE_MAXBYTES 1024
129 #endif
131 /* Compatibility sighs (that sigh is _really_ a cute one) */
132 #if HAVE_XTLS_OPENSSL >= 0x10100
133 # define a_xtls_X509_get_notBefore X509_get0_notBefore
134 # define a_xtls_X509_get_notAfter X509_get0_notAfter
135 #else
136 # define a_xtls_X509_get_notBefore X509_get_notBefore
137 # define a_xtls_X509_get_notAfter X509_get_notAfter
138 #endif
140 /* X509_STORE_set_flags */
141 #undef a_XTLS_X509_V_ANY
142 #ifndef X509_V_FLAG_NO_ALT_CHAINS
143 # define X509_V_FLAG_NO_ALT_CHAINS -1
144 #else
145 # undef a_XTLS_X509_V_ANY
146 # define a_XTLS_X509_V_ANY
147 #endif
148 #ifndef X509_V_FLAG_NO_CHECK_TIME
149 # define X509_V_FLAG_NO_CHECK_TIME -1
150 #else
151 # undef a_XTLS_X509_V_ANY
152 # define a_XTLS_X509_V_ANY
153 #endif
154 #ifndef X509_V_FLAG_PARTIAL_CHAIN
155 # define X509_V_FLAG_PARTIAL_CHAIN -1
156 #else
157 # undef a_XTLS_X509_V_ANY
158 # define a_XTLS_X509_V_ANY
159 #endif
160 #ifndef X509_V_FLAG_X509_STRICT
161 # define X509_V_FLAG_X509_STRICT -1
162 #else
163 # undef a_XTLS_X509_V_ANY
164 # define a_XTLS_X509_V_ANY
165 #endif
166 #ifndef X509_V_FLAG_TRUSTED_FIRST
167 # define X509_V_FLAG_TRUSTED_FIRST -1
168 #else
169 # undef a_XTLS_X509_V_ANY
170 # define a_XTLS_X509_V_ANY
171 #endif
173 enum a_xtls_state{
174 a_XTLS_S_INIT = 1u<<0,
175 a_XTLS_S_RAND_INIT = 1u<<1,
176 a_XTLS_S_CONF_LOAD = 1u<<2,
178 #if HAVE_XTLS_OPENSSL < 0x10100
179 a_XTLS_S_EXIT_HDL = 1u<<8,
180 a_XTLS_S_ALGO_LOAD = 1u<<9,
181 #endif
183 a_XTLS_S_VERIFY_ERROR = 1u<<16
186 struct ssl_method { /* TODO v15 obsolete */
187 char const sm_name[8];
188 char const sm_map[16];
191 #ifndef HAVE_XTLS_CONF_CTX
192 struct a_xtls_protocol{
193 char const xp_name[8];
194 sl_i xp_op_no; /* SSL_OP_NO_* bit */
195 ui16_t xp_version; /* *_VERSION number */
196 bool_t xp_ok_minmaxproto; /* Valid for {Min,Max}Protocol= */
197 bool_t xp_ok_proto; /* Valid for Protocol= */
198 ui8_t xp__dummy[4];
200 #endif
202 struct a_xtls_cipher{
203 char const xc_name[8];
204 EVP_CIPHER const *(*xc_fun)(void);
207 struct a_xtls_digest{
208 char const xd_name[16];
209 EVP_MD const *(*xd_fun)(void);
212 struct a_xtls_x509_v_flags{
213 char const xxvf_name[20];
214 si32_t xxvf_flag;
217 /* Supported SSL/TLS methods: update manual on change! */
218 static struct ssl_method const _ssl_methods[] = { /* TODO obsolete */
219 {"auto", "ALL,-SSLv2"},
220 {"ssl3", "-ALL,SSLv3"},
221 {"tls1", "-ALL,TLSv1"},
222 {"tls1.1", "-ALL,TLSv1.1"},
223 {"tls1.2", "-ALL,TLSv1.2"}
226 /* Update manual on change!
227 * Ensure array size by adding \0 to longest entry.
228 * Strictly to be sorted new/up to old/down, [0]=ALL, [x-1]=None! */
229 #ifndef HAVE_XTLS_CONF_CTX
230 static struct a_xtls_protocol const a_xtls_protocols[] = {
231 {"ALL", SSL_OP_NO_SSL_MASK, 0, FAL0, TRU1, {0}},
232 {"TLSv1.3\0", SSL_OP_NO_TLSv1_3, TLS1_3_VERSION, TRU1, TRU1, {0}},
233 {"TLSv1.2", SSL_OP_NO_TLSv1_2, TLS1_2_VERSION, TRU1, TRU1, {0}},
234 {"TLSv1.1", SSL_OP_NO_TLSv1_1, TLS1_1_VERSION, TRU1, TRU1, {0}},
235 {"TLSv1", SSL_OP_NO_TLSv1, TLS1_VERSION, TRU1, TRU1, {0}},
236 {"SSLv3", SSL_OP_NO_SSLv3, SSL3_VERSION, TRU1, TRU1, {0}},
237 {"SSLv2", SSL_OP_NO_SSLv2, SSL2_VERSION, TRU1, TRU1, {0}},
238 {"None", SSL_OP_NO_SSL_MASK, 0, TRU1, FAL0, {0}}
240 #endif /* HAVE_XTLS_CONF_CTX */
242 /* Supported S/MIME cipher algorithms */
243 static struct a_xtls_cipher const a_xtls_ciphers[] = { /*Manual!*/
244 #ifndef OPENSSL_NO_AES
245 # define a_XTLS_SMIME_DEFAULT_CIPHER EVP_aes_128_cbc /* According RFC 5751 */
246 {"AES128", &EVP_aes_128_cbc},
247 {"AES256", &EVP_aes_256_cbc},
248 {"AES192", &EVP_aes_192_cbc},
249 #endif
250 #ifndef OPENSSL_NO_DES
251 # ifndef a_XTLS_SMIME_DEFAULT_CIPHER
252 # define a_XTLS_SMIME_DEFAULT_CIPHER EVP_des_ede3_cbc
253 # endif
254 {"DES3", &EVP_des_ede3_cbc},
255 {"DES", &EVP_des_cbc},
256 #endif
258 #ifndef a_XTLS_SMIME_DEFAULT_CIPHER
259 # error Your OpenSSL library does not include the necessary
260 # error cipher algorithms that are required to support S/MIME
261 #endif
263 #ifndef OPENSSL_NO_AES
264 /* TODO obsolete a_xtls_smime_ciphers_obs */
265 static struct a_xtls_cipher const a_xtls_smime_ciphers_obs[] = {
266 {"AES-128", &EVP_aes_128_cbc},
267 {"AES-256", &EVP_aes_256_cbc},
268 {"AES-192", &EVP_aes_192_cbc}
270 #endif
272 /* Supported S/MIME message digest algorithms.
273 * Update manual on default changes! */
274 static struct a_xtls_digest const a_xtls_digests[] = { /*Manual!*/
275 #ifdef HAVE_XTLS_BLAKE2
276 {"BLAKE2b512\0", &EVP_blake2b512},
277 {"BLAKE2s256", &EVP_blake2s256},
278 # ifndef a_XTLS_FINGERPRINT_DEFAULT_DIGEST
279 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST EVP_blake2s256
280 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S "BLAKE2s256"
281 # endif
282 #endif
284 #ifdef HAVE_XTLS_SHA3
285 {"SHA3-512\0", &EVP_sha3_512},
286 {"SHA3-384", &EVP_sha3_384},
287 {"SHA3-256", &EVP_sha3_256},
288 {"SHA3-224", &EVP_sha3_224},
289 #endif
291 #ifndef OPENSSL_NO_SHA512
292 {"SHA512\0", &EVP_sha512},
293 {"SHA384", &EVP_sha384},
294 # ifndef a_XTLS_SMIME_DEFAULT_DIGEST
295 # define a_XTLS_SMIME_DEFAULT_DIGEST EVP_sha512
296 # define a_XTLS_SMIME_DEFAULT_DIGEST_S "SHA512"
297 # endif
298 #endif
300 #ifndef OPENSSL_NO_SHA256
301 {"SHA256\0", &EVP_sha256},
302 {"SHA224", &EVP_sha224},
303 # ifndef a_XTLS_SMIME_DEFAULT_DIGEST
304 # define a_XTLS_SMIME_DEFAULT_DIGEST EVP_sha256
305 # define a_XTLS_SMIME_DEFAULT_DIGEST_S "SHA256"
306 # endif
307 # ifndef a_XTLS_FINGERPRINT_DEFAULT_DIGEST
308 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST EVP_sha256
309 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S "SHA256"
310 # endif
311 #endif
313 #ifndef OPENSSL_NO_SHA
314 {"SHA1\0", &EVP_sha1},
315 # ifndef a_XTLS_SMIME_DEFAULT_DIGEST
316 # define a_XTLS_SMIME_DEFAULT_DIGEST EVP_sha1
317 # define a_XTLS_SMIME_DEFAULT_DIGEST_S "SHA1"
318 # endif
319 # ifndef a_XTLS_FINGERPRINT_DEFAULT_DIGEST
320 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST EVP_sha1
321 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S "SHA1"
322 # endif
323 #endif
325 #ifndef OPENSSL_NO_MD5
326 {"MD5\0", &EVP_md5},
327 #endif
330 #if !defined a_XTLS_SMIME_DEFAULT_DIGEST || \
331 !defined a_XTLS_FINGERPRINT_DEFAULT_DIGEST
332 # error Not enough supported message digest algorithms available
333 #endif
335 /* X509_STORE_set_flags() for *{smime,ssl}-ca-flags* */
336 static struct a_xtls_x509_v_flags const a_xtls_x509_v_flags[] = { /* Manual! */
337 {"no-alt-chains", X509_V_FLAG_NO_ALT_CHAINS},
338 {"no-check-time", X509_V_FLAG_NO_CHECK_TIME},
339 {"partial-chain", X509_V_FLAG_PARTIAL_CHAIN},
340 {"strict", X509_V_FLAG_X509_STRICT},
341 {"trusted-first", X509_V_FLAG_TRUSTED_FIRST},
344 static enum a_xtls_state a_xtls_state;
345 static size_t a_xtls_msgno;
347 static void a_xtls_rand_init(void);
348 static void a_xtls_init(void);
350 #if HAVE_XTLS_OPENSSL < 0x10100
351 # ifdef HAVE_TLS_ALL_ALGORITHMS
352 static void a_xtls__load_algos(void);
353 # define a_xtls_load_algos a_xtls__load_algos
354 # endif
355 # if defined HAVE_XTLS_CONFIG || defined HAVE_TLS_ALL_ALGORITHMS
356 static void a_xtls_atexit(void);
357 # endif
358 #endif
359 #ifndef a_xtls_load_algos
360 # define a_xtls_load_algos() do{;}while(0)
361 #endif
363 static bool_t a_xtls_parse_asn1_time(ASN1_TIME const *atp,
364 char *bdat, size_t blen);
365 static int a_xtls_verify_cb(int success, X509_STORE_CTX *store);
367 static bool_t a_xtls_digest_find(char const *name, EVP_MD const **mdp,
368 char const **normalized_name_or_null);
370 /* *smime-ca-flags*, *tls-ca-flags* */
371 static void a_xtls_ca_flags(X509_STORE *store, char const *flags);
373 /* SSL_CTX configuration; the latter always NULLs *confp */
374 static void *a_xtls_conf_setup(SSL_CTX *ctxp, struct url const *urlp);
375 static bool_t a_xtls_conf(void *confp, char const *cmd, char const *value);
376 static bool_t a_xtls_conf_finish(void **confp, bool_t error);
378 static bool_t a_xtls_obsolete_conf_vars(void *confp, struct url const *urlp);
379 static bool_t a_xtls_config_pairs(void *confp, struct url const *urlp);
380 static bool_t a_xtls_load_verifications(SSL_CTX *ctxp, struct url const *urlp);
382 static bool_t a_xtls_check_host(struct sock *sp, X509 *peercert,
383 struct url const *urlp);
385 static int smime_verify(struct message *m, int n,
386 n_XTLS_STACKOF(X509) *chain, X509_STORE *store);
387 static EVP_CIPHER const * _smime_cipher(char const *name);
388 static int ssl_password_cb(char *buf, int size, int rwflag,
389 void *userdata);
390 static FILE * smime_sign_cert(char const *xname, char const *xname2,
391 bool_t dowarn, char const **match);
392 static char const * _smime_sign_include_certs(char const *name);
393 static bool_t _smime_sign_include_chain_creat(n_XTLS_STACKOF(X509) **chain,
394 char const *cfiles, char const *addr);
395 static EVP_MD const *a_xtls_smime_sign_digest(char const *name,
396 char const **digname);
397 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
398 static enum okay load_crl1(X509_STORE *store, char const *name);
399 #endif
400 static enum okay load_crls(X509_STORE *store, enum okeys fok, enum okeys dok);
402 static void
403 a_xtls_rand_init(void){
404 #define a_XTLS_RAND_ENTROPY 32
405 char b64buf[a_XTLS_RAND_ENTROPY * 5 +1], *randfile;
406 char const *cp, *x;
407 bool_t err;
408 NYD2_ENTER;
410 a_xtls_state |= a_XTLS_S_RAND_INIT;
412 err = TRU1;
413 randfile = NULL;
415 #ifdef HAVE_XTLS_CONFIG
416 if(!(a_xtls_state & a_XTLS_S_INIT))
417 a_xtls_init();
418 #endif
420 /* Prefer possible user setting */
421 if((cp = ok_vlook(tls_rand_file)) != NULL ||
422 (cp = ok_vlook(ssl_rand_file)) != NULL){
423 x = NULL;
424 if(*cp != '\0'){
425 if((x = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) == NULL)
426 n_err(_("*tls-rand-file*: expansion of %s failed "
427 "(using default)\n"),
428 n_shexp_quote_cp(cp, FAL0));
430 cp = x;
432 if(cp == NULL){
433 randfile = n_lofi_alloc(PATH_MAX);
434 if((cp = RAND_file_name(randfile, PATH_MAX)) == NULL){
435 n_err(_("*tls-rand-file*: no TLS entropy file, can't seed PRNG\n"));
436 goto jleave;
440 (void)RAND_load_file(cp, a_XTLS_RAND_LOAD_FILE_MAXBYTES);
442 /* And feed in some data, then write the updated file.
443 * While this rather feeds the PRNG with itself in the n_RANDOM_IMPL_TLS
444 * case, let us stir the buffer a little bit.
445 * Estimate a low but likely still too high number of entropy bytes, use
446 * 20%: base64 uses 3 input = 4 output bytes relation, and the base64
447 * alphabet is a 6 bit one */
448 for(x = (char*)-1;;){
449 RAND_add(n_random_create_buf(b64buf, sizeof(b64buf) -1, NULL),
450 sizeof(b64buf) -1, a_XTLS_RAND_ENTROPY);
451 if((x = (char*)((uintptr_t)x >> (1
452 #if HAVE_RANDOM == n_RANDOM_IMPL_TLS
454 #endif
455 ))) == NULL){
456 err = (RAND_status() == 0);
457 break;
459 #if HAVE_RANDOM != n_RANDOM_IMPL_TLS
460 if(!(err = (RAND_status() == 0)))
461 break;
462 #endif
465 if(!err)
466 err = (RAND_write_file(cp) == -1);
468 jleave:
469 if(randfile != NULL)
470 n_lofi_free(randfile);
471 if(err)
472 n_panic(_("Cannot seed the *TLS PseudoRandomNumberGenerator, "
473 "RAND_status() is 0!\n"
474 " Please set *tls-rand-file* to a file with sufficient entropy.\n"
475 " On a machine with entropy: "
476 "\"$ dd if=/dev/urandom of=FILE bs=1024 count=1\"\n"));
477 NYD2_LEAVE;
480 static void
481 a_xtls_init(void){
482 #ifdef HAVE_XTLS_CONFIG
483 char const *cp;
484 #endif
485 NYD2_ENTER;
487 if(a_xtls_state & a_XTLS_S_INIT)
488 goto jleave;
490 #if HAVE_XTLS_OPENSSL >= 0x10100
491 OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
492 OPENSSL_INIT_LOAD_CRYPTO_STRINGS
493 # ifdef HAVE_TLS_ALL_ALGORITHMS
494 | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS
495 # endif
496 , NULL);
497 #else
498 SSL_load_error_strings();
499 SSL_library_init();
500 a_xtls_load_algos();
501 #endif
502 a_xtls_state |= a_XTLS_S_INIT;
505 /* Load openssl.cnf or whatever was given in *tls-config-file* */
506 #ifdef HAVE_XTLS_CONFIG
507 if((cp = ok_vlook(tls_config_file)) != NULL ||
508 (cp = ok_vlook(ssl_config_file)) != NULL){
509 char const *msg;
510 ul_i flags;
512 if(*cp == '\0'){
513 msg = "[default]";
514 cp = NULL;
515 flags = CONF_MFLAGS_IGNORE_MISSING_FILE;
516 }else if((msg = cp, cp = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) != NULL)
517 flags = 0;
518 else{
519 n_err(_("*tls-config-file*: file expansion failed: %s\n"),
520 n_shexp_quote_cp(msg, FAL0));
521 goto jefile;
524 if(CONF_modules_load_file(cp, n_uagent, flags) == 1){
525 a_xtls_state |= a_XTLS_S_CONF_LOAD;
526 # if HAVE_XTLS_OPENSSL < 0x10100
527 if(!(a_xtls_state & a_XTLS_S_EXIT_HDL)){
528 a_xtls_state |= a_XTLS_S_EXIT_HDL;
529 atexit(&a_xtls_atexit); /* TODO generic program-wide event mech. */
531 # endif
532 if(n_poption & n_PO_D_V)
533 n_err(_("Loaded TLS configuration for %s from %s\n"), n_uagent,
534 n_shexp_quote_cp(msg, FAL0));
535 jefile:;
536 }else
537 ssl_gen_err(_("TLS CONF_modules_load_file() load error"));
539 #endif /* HAVE_XTLS_CONFIG */
541 if(!(a_xtls_state & a_XTLS_S_RAND_INIT))
542 a_xtls_rand_init();
543 jleave:
544 NYD2_LEAVE;
547 #if HAVE_XTLS_OPENSSL < 0x10100
548 # ifdef HAVE_TLS_ALL_ALGORITHMS
549 static void
550 a_xtls__load_algos(void){
551 NYD2_ENTER;
552 if(!(a_xtls_state & a_XTLS_S_ALGO_LOAD)){
553 a_xtls_state |= a_XTLS_S_ALGO_LOAD;
554 OpenSSL_add_all_algorithms();
556 if(!(a_xtls_state & a_XTLS_S_EXIT_HDL)){
557 a_xtls_state |= a_XTLS_S_EXIT_HDL;
558 atexit(&a_xtls_atexit); /* TODO generic program-wide event mech. */
561 NYD2_LEAVE;
563 # endif
565 # if defined HAVE_XTLS_CONFIG || defined HAVE_TLS_ALL_ALGORITHMS
566 static void
567 a_xtls_atexit(void){
568 NYD2_ENTER;
569 # ifdef HAVE_XTLS_CONFIG
570 if(a_xtls_state & a_XTLS_S_CONF_LOAD)
571 CONF_modules_free();
572 # endif
574 # ifdef HAVE_TLS_ALL_ALGORITHMS
575 if(a_xtls_state & a_XTLS_S_ALGO_LOAD)
576 EVP_cleanup();
577 # endif
578 NYD2_LEAVE;
580 # endif
581 #endif /* HAVE_XTLS_OPENSSL < 0x10100 */
583 static bool_t
584 a_xtls_parse_asn1_time(ASN1_TIME const *atp, char *bdat, size_t blen)
586 BIO *mbp;
587 char *mcp;
588 long l;
589 NYD_ENTER;
591 mbp = BIO_new(BIO_s_mem());
593 if (ASN1_TIME_print(mbp, atp) && (l = BIO_get_mem_data(mbp, &mcp)) > 0)
594 snprintf(bdat, blen, "%.*s", (int)l, mcp);
595 else {
596 snprintf(bdat, blen, _("Bogus certificate date: %.*s"),
597 /*is (int)*/atp->length, (char const*)atp->data);
598 mcp = NULL;
601 BIO_free(mbp);
602 NYD_LEAVE;
603 return (mcp != NULL);
606 static int
607 a_xtls_verify_cb(int success, X509_STORE_CTX *store)
609 char data[256];
610 X509 *cert;
611 int rv = TRU1;
612 NYD_ENTER;
614 if (success && !(n_poption & n_PO_D_V))
615 goto jleave;
617 if (a_xtls_msgno != 0) {
618 n_err(_("Message %lu:\n"), (ul_i)a_xtls_msgno);
619 a_xtls_msgno = 0;
621 n_err(_(" Certificate depth %d %s\n"),
622 X509_STORE_CTX_get_error_depth(store), (success ? n_empty : V_(n_error)));
624 if ((cert = X509_STORE_CTX_get_current_cert(store)) != NULL) {
625 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof data);
626 n_err(_(" subject = %s\n"), data);
628 a_xtls_parse_asn1_time(a_xtls_X509_get_notBefore(cert),
629 data, sizeof data);
630 n_err(_(" notBefore = %s\n"), data);
632 a_xtls_parse_asn1_time(a_xtls_X509_get_notAfter(cert),
633 data, sizeof data);
634 n_err(_(" notAfter = %s\n"), data);
636 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof data);
637 n_err(_(" issuer = %s\n"), data);
640 if (!success) {
641 int err = X509_STORE_CTX_get_error(store);
643 n_err(_(" err %i: %s\n"), err, X509_verify_cert_error_string(err));
644 a_xtls_state |= a_XTLS_S_VERIFY_ERROR;
647 if(!success)
648 rv = n_tls_verify_decide();
649 jleave:
650 NYD_LEAVE;
651 return rv;
654 static bool_t
655 a_xtls_digest_find(char const *name,
656 EVP_MD const **mdp, char const **normalized_name_or_null){
657 size_t i;
658 char *nn;
659 NYD2_ENTER;
661 /* C99 */{
662 char *cp, c;
664 i = strlen(name);
665 nn = cp = n_lofi_alloc(i +1);
666 while((c = *name++) != '\0')
667 *cp++ = upperconv(c);
668 *cp = '\0';
670 if(normalized_name_or_null != NULL)
671 *normalized_name_or_null = savestrbuf(nn, PTR2SIZE(cp - nn));
674 for(i = 0; i < n_NELEM(a_xtls_digests); ++i)
675 if(!strcmp(a_xtls_digests[i].xd_name, nn)){
676 *mdp = (*a_xtls_digests[i].xd_fun)();
677 goto jleave;
680 /* Not a built-in algorithm, but we may have dynamic support for more */
681 #ifdef HAVE_TLS_ALL_ALGORITHMS
682 if((*mdp = EVP_get_digestbyname(nn)) != NULL)
683 goto jleave;
684 #endif
686 n_err(_("Invalid message digest: %s\n"), n_shexp_quote_cp(nn, FAL0));
687 *mdp = NULL;
688 jleave:
689 n_lofi_free(nn);
691 NYD2_LEAVE;
692 return (*mdp != NULL);
695 static void
696 a_xtls_ca_flags(X509_STORE *store, char const *flags){
697 NYD2_ENTER;
698 if(flags != NULL){
699 char *iolist, *cp;
701 iolist = savestr(flags);
702 jouter:
703 while((cp = n_strsep(&iolist, ',', TRU1)) != NULL){
704 struct a_xtls_x509_v_flags const *xvfp;
706 for(xvfp = &a_xtls_x509_v_flags[0];
707 xvfp < &a_xtls_x509_v_flags[n_NELEM(a_xtls_x509_v_flags)];
708 ++xvfp)
709 if(!asccasecmp(cp, xvfp->xxvf_name)){
710 if(xvfp->xxvf_flag != -1){
711 #ifdef a_XTLS_X509_V_ANY
712 X509_STORE_set_flags(store, xvfp->xxvf_flag);
713 #endif
714 }else if(n_poption & n_PO_D_V)
715 n_err(_("*{smime,tls}-ca-flags*: "
716 "directive not supported: %s\n"), cp);
717 goto jouter;
719 n_err(_("*{smime,tls}-ca-flags*: invalid directive: %s\n"), cp);
722 NYD2_LEAVE;
725 #ifdef HAVE_XTLS_CONF_CTX
726 static void *
727 a_xtls_conf_setup(SSL_CTX *ctxp, struct url const *urlp){
728 char const *cp;
729 SSL_CONF_CTX *sccp;
730 NYD2_ENTER;
732 sccp = NULL;
734 if((cp = xok_vlook(tls_config_module, urlp, OXM_ALL)) != NULL ||
735 (cp = xok_vlook(ssl_config_module, urlp, OXM_ALL)) != NULL){
736 # ifdef HAVE_XTLS_CTX_CONFIG
737 if(!(a_xtls_state & a_XTLS_S_CONF_LOAD)){
738 n_err(_("*tls-config-module*: no *tls-config-file* loaded: %s\n"),
739 n_shexp_quote_cp(cp, FAL0));
740 goto jleave;
741 }else if(!SSL_CTX_config(ctxp, cp)){
742 ssl_gen_err(_("*tls-config-module*: load error for %s, section [%s]"),
743 n_uagent, n_shexp_quote_cp(cp, FAL0));
744 goto jleave;
746 # else
747 n_err(_("*tls-config-module*: set but not supported: %s\n"),
748 n_shexp_quote_cp(cp, FAL0));
749 goto jleave;
750 # endif
753 if((sccp = SSL_CONF_CTX_new()) != NULL){
754 SSL_CONF_CTX_set_flags(sccp,
755 SSL_CONF_FLAG_FILE | SSL_CONF_FLAG_CLIENT |
756 SSL_CONF_FLAG_CERTIFICATE | SSL_CONF_FLAG_SHOW_ERRORS);
758 SSL_CONF_CTX_set_ssl_ctx(sccp, ctxp);
759 }else
760 ssl_gen_err(_("SSL_CONF_CTX_new() failed"));
761 jleave:
762 NYD2_LEAVE;
763 return sccp;
766 static bool_t
767 a_xtls_conf(void *confp, char const *cmd, char const *value){
768 int rv;
769 SSL_CONF_CTX *sccp;
770 NYD2_ENTER;
772 if(n_poption & n_PO_D_V)
773 n_err(_("TLS: applying config: %s = %s\n"),
774 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(value, FAL0));
776 rv = SSL_CONF_cmd(sccp = confp, cmd, value);
777 if(rv == 2)
778 rv = 0;
779 else{
780 cmd = n_shexp_quote_cp(cmd, FAL0);
781 value = n_shexp_quote_cp(value, FAL0);
782 if(rv == 0)
783 ssl_gen_err(_("TLS: config failure: %s = %s"), cmd, value);
784 else{
785 char const *err;
787 switch(rv){
788 case -2: err = N_("TLS: config command not recognized"); break;
789 case -3: err = N_("TLS: missing required config argument"); break;
790 default: err = N_("TLS: unspecified config error"); break;
792 err = V_(err);
793 n_err(_("%s (%d): %s = %s\n"), err, rv, cmd, value);
795 rv = 1;
797 NYD2_LEAVE;
798 return (rv == 0);
801 static bool_t
802 a_xtls_conf_finish(void **confp, bool_t error){
803 SSL_CONF_CTX *sccp;
804 bool_t rv;
805 NYD2_ENTER;
807 sccp = (SSL_CONF_CTX*)*confp;
808 *confp = NULL;
810 if(!(rv = error))
811 rv = (SSL_CONF_CTX_finish(sccp) != 0);
813 SSL_CONF_CTX_free(sccp);
814 NYD2_LEAVE;
815 return rv;
818 #else /* HAVE_XTLS_CONF_CTX */
819 # ifdef HAVE_XTLS_CTX_CONFIG
820 # error SSL_CTX_config(3) support unexpected without SSL_CONF_CTX support
821 # endif
823 static void *
824 a_xtls_conf_setup(SSL_CTX* ctxp, struct url const *urlp){
825 char const *cp;
826 NYD2_ENTER;
828 if((cp = xok_vlook(tls_config_module, urlp, OXM_ALL)) != NULL ||
829 (cp = xok_vlook(ssl_config_module, urlp, OXM_ALL)) != NULL){
830 n_err(_("*tls-config-module*: set but not supported: %s\n"),
831 n_shexp_quote_cp(cp, FAL0));
832 ctxp = NULL;
834 NYD2_LEAVE;
835 return ctxp;
838 static bool_t
839 a_xtls_conf(void *confp, char const *cmd, char const *value){
840 char const *xcmd, *emsg;
841 SSL_CTX *ctxp;
842 NYD2_ENTER;
844 if(n_poption & n_PO_D_V)
845 n_err(_("TLS: applying config: %s = %s\n"),
846 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(value, FAL0));
848 ctxp = confp;
850 if(!asccasecmp(cmd, xcmd = "Certificate")){
851 if(SSL_CTX_use_certificate_chain_file(ctxp, value) != 1){
852 emsg = N_("TLS: %s: cannot load from file %s\n");
853 goto jerr;
855 }else if(!asccasecmp(cmd, xcmd = "CipherString") ||
856 !asccasecmp(cmd, xcmd = "CipherList")/* grr, bad fault in past! */){
857 if(SSL_CTX_set_cipher_list(ctxp, value) != 1){
858 emsg = N_("TLS: %s: invalid: %s\n");
859 goto jerr;
861 }else if(!asccasecmp(cmd, xcmd = "Ciphersuites")){
862 #ifdef HAVE_XTLS_SET_CIPHERSUITES
863 if(SSL_CTX_set_ciphersuites(ctxp, value) != 1){
864 emsg = N_("TLS: %s: invalid: %s\n");
865 goto jerr;
867 #else
868 value = NULL;
869 emsg = N_("TLS: %s: directive not supported\n");
870 goto jxerr;
871 #endif
872 }else if(!asccasecmp(cmd, xcmd = "Curves")){
873 #ifdef SSL_CTRL_SET_CURVES_LIST
874 if(SSL_CTX_set1_curves_list(ctxp, n_UNCONST(value)) != 1){
875 emsg = N_("TLS: %s: invalid: %s\n");
876 goto jerr;
878 #else
879 value = NULL;
880 emsg = N_("TLS: %s: directive not supported\n");
881 goto jxerr;
882 #endif
883 }else if((emsg = NULL, !asccasecmp(cmd, xcmd = "MaxProtocol")) ||
884 (emsg = (char*)-1, !asccasecmp(cmd, xcmd = "MinProtocol"))){
885 #ifndef HAVE_XTLS_SET_MIN_PROTO_VERSION
886 value = NULL;
887 emsg = N_("TLS: %s: directive not supported\n");
888 goto jxerr;
889 #else
890 struct a_xtls_protocol const *xpp;
891 size_t i;
893 for(i = 1 /* [0] == ALL */;;){
894 xpp = &a_xtls_protocols[i];
896 if(xpp->xp_ok_minmaxproto && !asccasecmp(value, xpp->xp_name))
897 break;
899 if(++i >= n_NELEM(a_xtls_protocols)){
900 emsg = N_("TLS: %s: unsupported element: %s\n");
901 goto jxerr;
905 if((emsg == NULL ? SSL_CTX_set_max_proto_version(ctxp, xpp->xp_version)
906 : SSL_CTX_set_min_proto_version(ctxp, xpp->xp_version)) != 1){
907 emsg = N_("TLS: %s: invalid protocol: %s\n");
908 goto jerr;
910 #endif /* !HAVE_XTLS_SET_MIN_PROTO_VERSION */
911 }else if(!asccasecmp(cmd, xcmd = "Options")){
912 if(asccasecmp(value, "Bugs")){
913 emsg = N_("TLS: %s: fallback only supports value \"Bugs\": %s\n");
914 goto jxerr;
916 SSL_CTX_set_options(ctxp, SSL_OP_ALL);
917 }else if(!asccasecmp(cmd, xcmd = "PrivateKey")){
918 if(SSL_CTX_use_PrivateKey_file(ctxp, value, SSL_FILETYPE_PEM) != 1){
919 emsg = N_("%s: cannot load from file %s\n");
920 goto jerr;
922 }else if(!asccasecmp(cmd, xcmd = "Protocol")){
923 char *iolist, *cp, addin;
924 size_t i;
925 sl_i opts;
927 opts = 0;
929 for(iolist = cp = savestr(value);
930 (cp = n_strsep(&iolist, ',', FAL0)) != NULL;){
931 if(*cp == '\0'){
932 value = NULL;
933 emsg = N_("TLS: %s: empty elements are not supported\n");
934 goto jxerr;
937 addin = TRU1;
938 switch(cp[0]){
939 case '-': addin = FAL0; /* FALLTHRU */
940 case '+': ++cp; /* FALLTHRU */
941 default : break;
944 for(i = 0;;){
945 struct a_xtls_protocol const *xpp;
947 xpp = &a_xtls_protocols[i];
949 if(xpp->xp_ok_proto && !asccasecmp(cp, xpp->xp_name)){
950 /* We need to inverse the meaning of the _NO_s */
951 if(!addin)
952 opts |= xpp->xp_op_no;
953 else
954 opts &= ~xpp->xp_op_no;
955 break;
958 if(++i >= n_NELEM(a_xtls_protocols)){
959 emsg = N_("TLS: %s: unsupported element: %s\n");
960 goto jxerr;
965 SSL_CTX_clear_options(ctxp, SSL_OP_NO_SSL_MASK);
966 SSL_CTX_set_options(ctxp, opts);
967 }else{
968 xcmd = n_shexp_quote_cp(cmd, FAL0);
969 emsg = N_("TLS: unsupported directive: %s: value: %s\n");
970 goto jxerr;
973 jleave:
974 NYD2_LEAVE;
975 return (confp != NULL);
976 jerr:
977 ssl_gen_err(V_(emsg), xcmd, n_shexp_quote_cp(value, FAL0));
978 confp = NULL;
979 goto jleave;
980 jxerr:
981 if(value != NULL)
982 value = n_shexp_quote_cp(value, FAL0);
983 n_err(V_(emsg), xcmd, value);
984 confp = NULL;
985 goto jleave;
988 static bool_t
989 a_xtls_conf_finish(void **confp, bool_t error){
990 n_UNUSED(confp);
991 n_UNUSED(error);
992 *confp = NULL;
993 return TRU1;
995 #endif /* !HAVE_XTLS_CONF_CTX */
997 static bool_t
998 a_xtls_obsolete_conf_vars(void *confp, struct url const *urlp){
999 char const *cp, *cp_base, *certchain;
1000 bool_t rv;
1001 NYD2_ENTER;
1003 rv = FAL0;
1005 /* Certificate via ssl-cert */
1006 if((certchain = cp = xok_vlook(ssl_cert, urlp, OXM_ALL)) != NULL){
1007 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-cert*"));
1008 if((cp_base = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) == NULL){
1009 n_err(_("*ssl-cert* value expansion failed: %s\n"),
1010 n_shexp_quote_cp(cp, FAL0));
1011 goto jleave;
1013 if(!a_xtls_conf(confp, "Certificate", certchain = cp_base))
1014 goto jleave;
1017 /* CipherString via ssl-ciper-list */
1018 if((cp = xok_vlook(ssl_cipher_list, urlp, OXM_ALL)) != NULL){
1019 n_OBSOLETE(_("please use *tls-config-pairs* instead of "
1020 "*ssl-cipher-list*"));
1021 if(!a_xtls_conf(confp, "CipherString", cp))
1022 goto jleave;
1025 /* Curves via ssl-curves */
1026 if((cp = xok_vlook(ssl_curves, urlp, OXM_ALL)) != NULL){
1027 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-curves*"));
1028 if(!a_xtls_conf(confp, "Curves", cp))
1029 goto jleave;
1032 /* PrivateKey via ssl-key */
1033 if((cp = xok_vlook(ssl_key, urlp, OXM_ALL)) != NULL){
1034 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-key*"));
1035 if((cp_base = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) == NULL){
1036 n_err(_("*ssl-key* value expansion failed: %s\n"),
1037 n_shexp_quote_cp(cp, FAL0));
1038 goto jleave;
1040 cp = cp_base;
1041 if(certchain == NULL){
1042 n_err(_("*ssl-key* can only be used together with *ssl-cert*! "
1043 "And use *ssl-config-pairs*!\n"));
1044 goto jleave;
1047 if((cp != NULL || (cp = certchain) != NULL) &&
1048 !a_xtls_conf(confp, "PrivateKey", cp))
1049 goto jleave;
1051 /* Protocol via ssl-method or ssl-protocol */
1052 if((cp = xok_vlook(ssl_method, urlp, OXM_ALL)) != NULL){
1053 size_t i;
1055 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-method*"));
1056 for(i = 0;;){
1057 if(!asccasecmp(_ssl_methods[i].sm_name, cp)){
1058 cp = _ssl_methods[i].sm_map;
1059 break;
1061 if(++i == n_NELEM(_ssl_methods)){
1062 n_err(_("Unsupported SSL method: %s\n"), cp);
1063 goto jleave;
1067 if((cp_base = xok_vlook(ssl_protocol, urlp, OXM_ALL)) != NULL){
1068 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-protocol*"));
1069 if(cp != NULL && (n_poption & n_PO_D_V))
1070 n_err(_("*ssl-protocol* overrides *ssl-method*! "
1071 "And please use *tls-config-pairs* instead!\n"));
1072 cp = cp_base;
1074 if(cp != NULL && !a_xtls_conf(confp, "Protocol", cp))
1075 goto jleave;
1077 rv = TRU1;
1078 jleave:
1079 NYD2_LEAVE;
1080 return rv;
1083 static bool_t
1084 a_xtls_config_pairs(void *confp, struct url const *urlp){
1085 /* Due to interdependencies some commands have to be delayed a bit */
1086 static char const cmdcert[] = "Certificate", cmdprivkey[] = "PrivateKey";
1087 char const *valcert, *valprivkey;
1088 char *pairs, *cp, *cmd, *val;
1089 NYD2_ENTER;
1091 if((pairs = n_UNCONST(xok_vlook(tls_config_pairs, urlp, OXM_ALL))
1092 ) == NULL &&
1093 (pairs = n_UNCONST(xok_vlook(ssl_config_pairs, urlp, OXM_ALL))
1094 ) == NULL)
1095 goto jleave;
1096 pairs = savestr(pairs);
1098 valcert = valprivkey = NULL;
1100 while((cp = n_strsep_esc(&pairs, ',', FAL0)) != NULL){
1101 char c;
1102 enum{
1103 a_NONE,
1104 a_EXPAND = 1u<<0,
1105 a_CERT = 1u<<1,
1106 a_PRIVKEY = 1u<<2,
1107 a_EXPAND_MASK = a_EXPAND | a_CERT | a_PRIVKEY
1108 } f;
1110 /* Directive, space trimmed */
1111 if((cmd = strchr(cp, '=')) == NULL){
1112 jenocmd:
1113 if(pairs == NULL)
1114 pairs = n_UNCONST(n_empty);
1115 n_err(_("*tls-config-pairs*: missing directive: %s; rest: %s\n"),
1116 n_shexp_quote_cp(cp, FAL0), n_shexp_quote_cp(pairs, FAL0));
1117 goto jleave;
1119 val = &cmd[1];
1121 if((cmd > cp && cmd[-1] == '*')){
1122 --cmd;
1123 f = a_EXPAND;
1124 }else
1125 f = a_NONE;
1126 while(cmd > cp && (c = cmd[-1], blankspacechar(c)))
1127 --cmd;
1128 if(cmd == cp)
1129 goto jenocmd;
1130 *cmd = '\0';
1131 cmd = cp;
1133 /* Command with special treatment? */
1134 if(!asccasecmp(cmd, cmdcert))
1135 f |= a_CERT;
1136 else if(!asccasecmp(cmd, cmdprivkey))
1137 f |= a_PRIVKEY;
1139 /* Value, space trimmed */
1140 while((c = *val) != '\0' && blankspacechar(c))
1141 ++val;
1142 cp = &val[strlen(val)];
1143 while(cp > val && (c = cp[-1], blankspacechar(c)))
1144 --cp;
1145 *cp = '\0';
1146 if(cp == val){
1147 if(pairs == NULL)
1148 pairs = n_UNCONST(n_empty);
1149 n_err(_("*tls-config-pairs*: missing value: %s; rest: %s\n"),
1150 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(pairs, FAL0));
1151 goto jleave;
1154 /* Filename transformations to be applied? */
1155 if(f & a_EXPAND_MASK){
1156 if((cp = fexpand(val, FEXP_LOCAL | FEXP_NOPROTO)) == NULL){
1157 if(pairs == NULL)
1158 pairs = n_UNCONST(n_empty);
1159 n_err(_("*tls-config-pairs*: value expansion failed: %s: %s; "
1160 "rest: %s\n"),
1161 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(val, FAL0),
1162 n_shexp_quote_cp(pairs, FAL0));
1163 goto jleave;
1165 val = cp;
1168 /* Some things have to be delayed */
1169 if(f & a_CERT)
1170 valcert = val;
1171 else if(f & a_PRIVKEY)
1172 valprivkey = val;
1173 else if(!a_xtls_conf(confp, cmd, val)){
1174 pairs = n_UNCONST(n_empty);
1175 goto jleave;
1179 /* Work the delayed ones */
1180 if((valcert != NULL && !a_xtls_conf(confp, cmdcert, valcert)) ||
1181 ((valprivkey != NULL || (valprivkey = valcert) != NULL) &&
1182 !a_xtls_conf(confp, cmdprivkey, valprivkey)))
1183 pairs = n_UNCONST(n_empty);
1185 jleave:
1186 NYD2_LEAVE;
1187 return (pairs == NULL);
1190 static bool_t
1191 a_xtls_load_verifications(SSL_CTX *ctxp, struct url const *urlp){
1192 char *ca_dir, *ca_file;
1193 X509_STORE *store;
1194 bool_t rv;
1195 NYD2_ENTER;
1197 if(n_tls_verify_level == n_TLS_VERIFY_IGNORE){
1198 rv = TRU1;
1199 goto jleave;
1201 rv = FAL0;
1203 if((ca_dir = xok_vlook(tls_ca_dir, urlp, OXM_ALL)) != NULL ||
1204 (ca_dir = xok_vlook(ssl_ca_dir, urlp, OXM_ALL)) != NULL)
1205 ca_dir = fexpand(ca_dir, FEXP_LOCAL | FEXP_NOPROTO);
1206 if((ca_file = xok_vlook(tls_ca_file, urlp, OXM_ALL)) != NULL ||
1207 (ca_file = xok_vlook(ssl_ca_file, urlp, OXM_ALL)) != NULL)
1208 ca_file = fexpand(ca_file, FEXP_LOCAL | FEXP_NOPROTO);
1210 if((ca_dir != NULL || ca_file != NULL) &&
1211 SSL_CTX_load_verify_locations(ctxp, ca_file, ca_dir) != 1){
1212 char const *m1, *m2, *m3;
1214 if(ca_dir != NULL){
1215 m1 = ca_dir;
1216 m2 = (ca_file != NULL) ? _(" or ") : n_empty;
1217 }else
1218 m1 = m2 = n_empty;
1219 m3 = (ca_file != NULL) ? ca_file : n_empty;
1220 ssl_gen_err(_("Error loading %s%s%s\n"), m1, m2, m3);
1221 goto jleave;
1224 /* C99 */{
1225 bool_t xv15;
1227 if((xv15 = ok_blook(ssl_no_default_ca)))
1228 n_OBSOLETE(_("please use *tls-ca-no-defaults*, "
1229 "not *ssl-no-default-ca*"));
1230 if(!xok_blook(tls_ca_no_defaults, urlp, OXM_ALL) &&
1231 !xok_blook(ssl_ca_no_defaults, urlp, OXM_ALL) && !xv15 &&
1232 SSL_CTX_set_default_verify_paths(ctxp) != 1) {
1233 ssl_gen_err(_("Error loading built-in default CA locations\n"));
1234 goto jleave;
1238 a_xtls_state &= ~a_XTLS_S_VERIFY_ERROR;
1239 a_xtls_msgno = 0;
1240 SSL_CTX_set_verify(ctxp, SSL_VERIFY_PEER, &a_xtls_verify_cb);
1241 store = SSL_CTX_get_cert_store(ctxp);
1242 load_crls(store, ok_v_tls_crl_file, ok_v_tls_crl_dir);
1243 a_xtls_ca_flags(store, xok_vlook(tls_ca_flags, urlp, OXM_ALL));
1244 a_xtls_ca_flags(store, xok_vlook(ssl_ca_flags, urlp, OXM_ALL));
1246 rv = TRU1;
1247 jleave:
1248 NYD2_LEAVE;
1249 return rv;
1252 static bool_t
1253 a_xtls_check_host(struct sock *sp, X509 *peercert, struct url const *urlp){
1254 char data[256];
1255 n_XTLS_STACKOF(GENERAL_NAME) *gens;
1256 GENERAL_NAME *gen;
1257 X509_NAME *subj;
1258 bool_t rv;
1259 NYD_ENTER;
1260 n_UNUSED(sp);
1262 rv = FAL0;
1264 if((gens = X509_get_ext_d2i(peercert, NID_subject_alt_name, NULL, NULL)
1265 ) != NULL){
1266 int i;
1268 for(i = 0; i < sk_GENERAL_NAME_num(gens); ++i){
1269 gen = sk_GENERAL_NAME_value(gens, i);
1270 if(gen->type == GEN_DNS){
1271 if(n_poption & n_PO_D_V)
1272 n_err(_("Comparing subject_alt_name: need<%s> is<%s>\n"),
1273 urlp->url_host.s, (char*)gen->d.ia5->data);
1274 if((rv = n_tls_rfc2595_hostname_match(urlp->url_host.s,
1275 (char*)gen->d.ia5->data)))
1276 goto jleave;
1281 if((subj = X509_get_subject_name(peercert)) != NULL &&
1282 X509_NAME_get_text_by_NID(subj, NID_commonName, data, sizeof data
1283 ) > 0){
1284 data[sizeof data - 1] = '\0';
1285 if(n_poption & n_PO_D_V)
1286 n_err(_("Comparing commonName: need<%s> is<%s>\n"),
1287 urlp->url_host.s, data);
1288 rv = n_tls_rfc2595_hostname_match(urlp->url_host.s, data);
1290 jleave:
1291 NYD_LEAVE;
1292 return rv;
1295 static int
1296 smime_verify(struct message *m, int n, n_XTLS_STACKOF(X509) *chain,
1297 X509_STORE *store)
1299 char data[LINESIZE], *sender, *to, *cc, *cnttype;
1300 int rv, c, i, j;
1301 struct message *x;
1302 FILE *fp, *ip;
1303 off_t size;
1304 BIO *fb, *pb;
1305 PKCS7 *pkcs7;
1306 n_XTLS_STACKOF(X509) *certs;
1307 n_XTLS_STACKOF(GENERAL_NAME) *gens;
1308 X509 *cert;
1309 X509_NAME *subj;
1310 GENERAL_NAME *gen;
1311 NYD_ENTER;
1313 rv = 1;
1314 fp = NULL;
1315 fb = pb = NULL;
1316 pkcs7 = NULL;
1317 certs = NULL;
1318 a_xtls_state &= ~a_XTLS_S_VERIFY_ERROR;
1319 a_xtls_msgno = (size_t)n;
1321 for (;;) {
1322 sender = getsender(m);
1323 to = hfield1("to", m);
1324 cc = hfield1("cc", m);
1325 cnttype = hfield1("content-type", m);
1327 #undef _X
1328 #undef _Y
1329 #define _X (sizeof("application/") -1)
1330 #define _Y(X) X, sizeof(X) -1
1331 if (cnttype && is_asccaseprefix("application/", cnttype) &&
1332 (!ascncasecmp(cnttype + _X, _Y("pkcs7-mime")) ||
1333 !ascncasecmp(cnttype + _X, _Y("x-pkcs7-mime")))) {
1334 #undef _Y
1335 #undef _X
1336 if ((x = smime_decrypt(m, to, cc, 1)) == NULL)
1337 goto jleave;
1338 if (x != (struct message*)-1) {
1339 m = x;
1340 continue;
1344 if ((ip = setinput(&mb, m, NEED_BODY)) == NULL)
1345 goto jleave;
1346 size = m->m_size;
1347 break;
1350 if ((fp = Ftmp(NULL, "smimever", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
1351 NULL) {
1352 n_perr(_("tempfile"), 0);
1353 goto jleave;
1355 while (size-- > 0) {
1356 c = getc(ip);
1357 putc(c, fp);
1359 fflush_rewind(fp);
1361 if ((fb = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
1362 ssl_gen_err(_(
1363 "Error creating BIO verification object for message %d"), n);
1364 goto jleave;
1367 if ((pkcs7 = SMIME_read_PKCS7(fb, &pb)) == NULL) {
1368 ssl_gen_err(_("Error reading PKCS#7 object for message %d"), n);
1369 goto jleave;
1371 if (PKCS7_verify(pkcs7, chain, store, pb, NULL, 0) != 1) {
1372 ssl_gen_err(_("Error verifying message %d"), n);
1373 goto jleave;
1376 if (sender == NULL) {
1377 n_err(_("Warning: Message %d has no sender\n"), n);
1378 rv = 0;
1379 goto jleave;
1382 certs = PKCS7_get0_signers(pkcs7, chain, 0);
1383 if (certs == NULL) {
1384 n_err(_("No certificates found in message %d\n"), n);
1385 goto jleave;
1388 for (i = 0; i < sk_X509_num(certs); ++i) {
1389 cert = sk_X509_value(certs, i);
1390 gens = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
1391 if (gens != NULL) {
1392 for (j = 0; j < sk_GENERAL_NAME_num(gens); ++j) {
1393 gen = sk_GENERAL_NAME_value(gens, j);
1394 if (gen->type == GEN_EMAIL) {
1395 if (n_poption & n_PO_D_V)
1396 n_err(_("Comparing subject_alt_name: need<%s> is<%s>)\n"),
1397 sender, (char*)gen->d.ia5->data);
1398 if (!asccasecmp((char*)gen->d.ia5->data, sender))
1399 goto jfound;
1404 if ((subj = X509_get_subject_name(cert)) != NULL &&
1405 X509_NAME_get_text_by_NID(subj, NID_pkcs9_emailAddress,
1406 data, sizeof data) > 0) {
1407 data[sizeof data -1] = '\0';
1408 if (n_poption & n_PO_D_V)
1409 n_err(_("Comparing emailAddress: need<%s> is<%s>\n"),
1410 sender, data);
1411 if (!asccasecmp(data, sender))
1412 goto jfound;
1415 n_err(_("Message %d: certificate does not match <%s>\n"), n, sender);
1416 goto jleave;
1417 jfound:
1418 rv = ((a_xtls_state & a_XTLS_S_VERIFY_ERROR) != 0);
1419 if (!rv)
1420 fprintf(n_stdout, _("Message %d was verified successfully\n"), n);
1421 jleave:
1422 if (certs != NULL)
1423 sk_X509_free(certs);
1424 if (pb != NULL)
1425 BIO_free(pb);
1426 if (fb != NULL)
1427 BIO_free(fb);
1428 if (pkcs7 != NULL)
1429 PKCS7_free(pkcs7);
1430 if (fp != NULL)
1431 Fclose(fp);
1432 NYD_LEAVE;
1433 return rv;
1436 static EVP_CIPHER const *
1437 _smime_cipher(char const *name)
1439 EVP_CIPHER const *cipher;
1440 char *vn;
1441 char const *cp;
1442 size_t i;
1443 NYD_ENTER;
1445 vn = n_lofi_alloc(i = strlen(name) + sizeof("smime-cipher-") -1 +1);
1446 snprintf(vn, (int)i, "smime-cipher-%s", name);
1447 cp = n_var_vlook(vn, FAL0);
1448 n_lofi_free(vn);
1450 if (cp == NULL && (cp = ok_vlook(smime_cipher)) == NULL) {
1451 cipher = a_XTLS_SMIME_DEFAULT_CIPHER();
1452 goto jleave;
1454 cipher = NULL;
1456 for(i = 0; i < n_NELEM(a_xtls_ciphers); ++i)
1457 if(!asccasecmp(a_xtls_ciphers[i].xc_name, cp)){
1458 cipher = (*a_xtls_ciphers[i].xc_fun)();
1459 goto jleave;
1461 #ifndef OPENSSL_NO_AES
1462 for (i = 0; i < n_NELEM(a_xtls_smime_ciphers_obs); ++i) /* TODO obsolete */
1463 if (!asccasecmp(a_xtls_smime_ciphers_obs[i].xc_name, cp)) {
1464 n_OBSOLETE2(_("*smime-cipher* names with hyphens will vanish"), cp);
1465 cipher = (*a_xtls_smime_ciphers_obs[i].xc_fun)();
1466 goto jleave;
1468 #endif
1470 /* Not a built-in algorithm, but we may have dynamic support for more */
1471 #ifdef HAVE_TLS_ALL_ALGORITHMS
1472 if((cipher = EVP_get_cipherbyname(cp)) != NULL)
1473 goto jleave;
1474 #endif
1476 n_err(_("Invalid S/MIME cipher(s): %s\n"), cp);
1477 jleave:
1478 NYD_LEAVE;
1479 return cipher;
1482 static int
1483 ssl_password_cb(char *buf, int size, int rwflag, void *userdata)
1485 char *pass;
1486 size_t len;
1487 NYD_ENTER;
1488 n_UNUSED(rwflag);
1489 n_UNUSED(userdata);
1491 /* New-style */
1492 if(userdata != NULL){
1493 struct url url;
1494 struct ccred cred;
1496 if(url_parse(&url, CPROTO_CCRED, userdata)){
1497 if(ccred_lookup(&cred, &url)){
1498 ssize_t slen;
1500 if((slen = n_strscpy(buf, cred.cc_pass.s, size)) >= 0){
1501 size = (int)slen;
1502 goto jleave;
1505 size = 0;
1506 goto jleave;
1510 /* Old-style */
1511 if ((pass = getpassword("PEM pass phrase:")) != NULL) {
1512 len = strlen(pass);
1513 if (UICMP(z, len, >=, size))
1514 len = size -1;
1515 memcpy(buf, pass, len);
1516 buf[len] = '\0';
1517 size = (int)len;
1518 } else
1519 size = 0;
1520 jleave:
1521 NYD_LEAVE;
1522 return size;
1525 static FILE *
1526 smime_sign_cert(char const *xname, char const *xname2, bool_t dowarn,
1527 char const **match)
1529 char *vn;
1530 int vs;
1531 struct name *np;
1532 char const *name = xname, *name2 = xname2, *cp;
1533 FILE *fp = NULL;
1534 NYD_ENTER;
1536 jloop:
1537 if (name) {
1538 np = lextract(name, GTO | GSKIN);
1539 while (np != NULL) {
1540 /* This needs to be more intelligent since it will currently take the
1541 * first name for which a private key is available regardless of
1542 * whether it is the right one for the message */
1543 vn = n_lofi_alloc(vs = strlen(np->n_name) + 30);
1544 snprintf(vn, vs, "smime-sign-cert-%s", np->n_name);
1545 cp = n_var_vlook(vn, FAL0);
1546 n_lofi_free(vn);
1547 if (cp != NULL) {
1548 if (match != NULL)
1549 *match = np->n_name;
1550 goto jopen;
1552 np = np->n_flink;
1554 if (name2 != NULL) {
1555 name = name2;
1556 name2 = NULL;
1557 goto jloop;
1561 if ((cp = ok_vlook(smime_sign_cert)) == NULL)
1562 goto jerr;
1563 if(match != NULL)
1564 *match = NULL;
1565 jopen:
1566 if ((cp = fexpand(cp, FEXP_LOCAL | FEXP_NOPROTO)) == NULL)
1567 goto jleave;
1568 if ((fp = Fopen(cp, "r")) == NULL)
1569 n_perr(cp, 0);
1570 jleave:
1571 NYD_LEAVE;
1572 return fp;
1573 jerr:
1574 if (dowarn)
1575 n_err(_("Could not find a certificate for %s%s%s\n"),
1576 xname, (xname2 != NULL ? _("or ") : n_empty),
1577 (xname2 != NULL ? xname2 : n_empty));
1578 goto jleave;
1581 static char const *
1582 _smime_sign_include_certs(char const *name)
1584 char const *rv;
1585 NYD_ENTER;
1587 /* See comments in smime_sign_cert() for algorithm pitfalls */
1588 if (name != NULL) {
1589 struct name *np;
1591 for (np = lextract(name, GTO | GSKIN); np != NULL; np = np->n_flink) {
1592 int vs;
1593 char *vn;
1595 vn = n_lofi_alloc(vs = strlen(np->n_name) + 30);
1596 snprintf(vn, vs, "smime-sign-include-certs-%s", np->n_name);
1597 rv = n_var_vlook(vn, FAL0);
1598 n_lofi_free(vn);
1599 if (rv != NULL)
1600 goto jleave;
1603 rv = ok_vlook(smime_sign_include_certs);
1604 jleave:
1605 NYD_LEAVE;
1606 return rv;
1609 static bool_t
1610 _smime_sign_include_chain_creat(n_XTLS_STACKOF(X509) **chain,
1611 char const *cfiles, char const *addr)
1613 X509 *tmp;
1614 FILE *fp;
1615 char *nfield, *cfield, *x;
1616 NYD_ENTER;
1618 *chain = sk_X509_new_null();
1620 for (nfield = savestr(cfiles);
1621 (cfield = n_strsep(&nfield, ',', TRU1)) != NULL;) {
1622 if ((x = fexpand(cfield, FEXP_LOCAL | FEXP_NOPROTO)) == NULL ||
1623 (fp = Fopen(cfield = x, "r")) == NULL) {
1624 n_perr(cfiles, 0);
1625 goto jerr;
1627 if ((tmp = PEM_read_X509(fp, NULL, &ssl_password_cb, n_UNCONST(addr))
1628 ) == NULL) {
1629 ssl_gen_err(_("Error reading certificate from %s"),
1630 n_shexp_quote_cp(cfield, FAL0));
1631 Fclose(fp);
1632 goto jerr;
1634 sk_X509_push(*chain, tmp);
1635 Fclose(fp);
1638 if (sk_X509_num(*chain) == 0) {
1639 n_err(_("*smime-sign-include-certs* defined but empty\n"));
1640 goto jerr;
1642 jleave:
1643 NYD_LEAVE;
1644 return (*chain != NULL);
1645 jerr:
1646 sk_X509_pop_free(*chain, X509_free);
1647 *chain = NULL;
1648 goto jleave;
1651 static EVP_MD const *
1652 a_xtls_smime_sign_digest(char const *name, char const **digname){
1653 EVP_MD const *digest;
1654 char const *cp;
1655 NYD2_ENTER;
1657 /* See comments in smime_sign_cert() for algorithm pitfalls */
1658 if(name != NULL){
1659 struct name *np;
1661 for(np = lextract(name, GTO | GSKIN); np != NULL; np = np->n_flink){
1662 int vs;
1663 char *vn;
1665 vn = n_lofi_alloc(vs = strlen(np->n_name) + 30);
1666 snprintf(vn, vs, "smime-sign-digest-%s", np->n_name);
1667 if((cp = n_var_vlook(vn, FAL0)) == NULL){
1668 snprintf(vn, vs, "smime-sign-message-digest-%s",np->n_name);/*v15*/
1669 cp = n_var_vlook(vn, FAL0);
1671 n_lofi_free(vn);
1672 if(cp != NULL)
1673 goto jhave_name;
1677 if((cp = ok_vlook(smime_sign_digest)) != NULL ||
1678 (cp = ok_vlook(smime_sign_message_digest)/* v15 */) != NULL)
1679 jhave_name:
1680 if(a_xtls_digest_find(cp, &digest, digname))
1681 goto jleave;
1683 digest = a_XTLS_SMIME_DEFAULT_DIGEST();
1684 *digname = a_XTLS_SMIME_DEFAULT_DIGEST_S;
1685 jleave:
1686 NYD2_LEAVE;
1687 return digest;
1690 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1691 static enum okay
1692 load_crl1(X509_STORE *store, char const *name)
1694 X509_LOOKUP *lookup;
1695 enum okay rv = STOP;
1696 NYD_ENTER;
1698 if (n_poption & n_PO_D_V)
1699 n_err(_("Loading CRL from %s\n"), n_shexp_quote_cp(name, FAL0));
1700 if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) == NULL) {
1701 ssl_gen_err(_("Error creating X509 lookup object"));
1702 goto jleave;
1704 if (X509_load_crl_file(lookup, name, X509_FILETYPE_PEM) != 1) {
1705 ssl_gen_err(_("Error loading CRL from %s"),
1706 n_shexp_quote_cp(name, FAL0));
1707 goto jleave;
1709 rv = OKAY;
1710 jleave:
1711 NYD_LEAVE;
1712 return rv;
1714 #endif /* new OpenSSL */
1716 static enum okay
1717 load_crls(X509_STORE *store, enum okeys fok, enum okeys dok)/*TODO nevertried*/
1719 char *crl_file, *crl_dir;
1720 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1721 DIR *dirp;
1722 struct dirent *dp;
1723 char *fn = NULL;
1724 int fs = 0, ds, es;
1725 #endif
1726 bool_t any;
1727 enum okay rv;
1728 NYD_ENTER;
1730 rv = STOP;
1731 any = FAL0;
1733 jredo_v15:
1734 if ((crl_file = n_var_oklook(fok)) != NULL) {
1735 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1736 if ((crl_file = fexpand(crl_file, FEXP_LOCAL | FEXP_NOPROTO)) == NULL ||
1737 load_crl1(store, crl_file) != OKAY)
1738 goto jleave;
1739 any = TRU1;
1740 #else
1741 n_err(_("This OpenSSL version is too old to use CRLs\n"));
1742 goto jleave;
1743 #endif
1746 if ((crl_dir = n_var_oklook(dok)) != NULL) {
1747 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1748 char *x;
1749 if ((x = fexpand(crl_dir, FEXP_LOCAL | FEXP_NOPROTO)) == NULL ||
1750 (dirp = opendir(crl_dir = x)) == NULL) {
1751 n_perr(crl_dir, 0);
1752 goto jleave;
1755 ds = strlen(crl_dir);
1756 fn = n_alloc(fs = ds + 20);
1757 memcpy(fn, crl_dir, ds);
1758 fn[ds] = '/';
1759 while ((dp = readdir(dirp)) != NULL) {
1760 if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
1761 (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
1762 continue;
1763 if (dp->d_name[0] == '.')
1764 continue;
1765 if (ds + (es = strlen(dp->d_name)) + 2 < fs)
1766 fn = n_realloc(fn, fs = ds + es + 20);
1767 memcpy(fn + ds + 1, dp->d_name, es + 1);
1768 if (load_crl1(store, fn) != OKAY) {
1769 closedir(dirp);
1770 n_free(fn);
1771 goto jleave;
1773 any = TRU1;
1775 closedir(dirp);
1776 n_free(fn);
1777 #else /* old OpenSSL */
1778 n_err(_("This OpenSSL version is too old to use CRLs\n"));
1779 goto jleave;
1780 #endif
1783 if(fok == ok_v_tls_crl_file){
1784 fok = ok_v_ssl_crl_file;
1785 dok = ok_v_ssl_crl_dir;
1786 goto jredo_v15;
1788 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1789 if(any)
1790 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
1791 X509_V_FLAG_CRL_CHECK_ALL);
1792 #endif
1793 rv = OKAY;
1794 jleave:
1795 NYD_LEAVE;
1796 return rv;
1799 #if HAVE_RANDOM == n_RANDOM_IMPL_TLS
1800 FL void
1801 n_tls_rand_bytes(void *buf, size_t blen){
1802 NYD2_ENTER;
1804 if(!(a_xtls_state & a_XTLS_S_RAND_INIT))
1805 a_xtls_rand_init();
1807 while(blen > 0){
1808 si32_t i;
1810 i = n_MIN(SI32_MAX, blen);
1811 blen -= i;
1812 RAND_bytes(buf, i);
1813 buf = (ui8_t*)buf + i;
1815 NYD2_LEAVE;
1817 #endif
1819 FL bool_t
1820 n_tls_open(struct url *urlp, struct sock *sp){
1821 void *confp;
1822 SSL_CTX *ctxp;
1823 const EVP_MD *fprnt_mdp;
1824 char const *fprnt, *fprnt_namep;
1825 NYD_ENTER;
1827 a_xtls_init();
1828 n_tls_set_verify_level(urlp); /* TODO should come in via URL! */
1830 sp->s_tls = NULL;
1831 if(urlp->url_cproto != CPROTO_CERTINFO)
1832 fprnt = xok_vlook(tls_fingerprint, urlp, OXM_ALL);
1833 else
1834 fprnt = NULL;
1835 fprnt_namep = NULL;
1836 fprnt_mdp = NULL;
1838 if(fprnt != NULL || urlp->url_cproto == CPROTO_CERTINFO ||
1839 (n_poption & n_PO_D_V)){
1840 if((fprnt_namep = xok_vlook(tls_fingerprint_digest, urlp,
1841 OXM_ALL)) == NULL ||
1842 !a_xtls_digest_find(fprnt_namep, &fprnt_mdp, &fprnt_namep)){
1843 fprnt_mdp = a_XTLS_FINGERPRINT_DEFAULT_DIGEST();
1844 fprnt_namep = a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S;
1848 if((ctxp = SSL_CTX_new(n_XTLS_CLIENT_METHOD())) == NULL){
1849 ssl_gen_err(_("SSL_CTX_new() failed"));
1850 goto j_leave;
1853 /* Available with OpenSSL 0.9.6 or later */
1854 #ifdef SSL_MODE_AUTO_RETRY
1855 SSL_CTX_set_mode(ctxp, SSL_MODE_AUTO_RETRY);
1856 #endif
1858 if((confp = a_xtls_conf_setup(ctxp, urlp)) == NULL)
1859 goto jleave;
1861 if(!a_xtls_obsolete_conf_vars(confp, urlp))
1862 goto jerr1;
1863 if(!a_xtls_config_pairs(confp, urlp))
1864 goto jerr1;
1865 if((fprnt == NULL || urlp->url_cproto == CPROTO_CERTINFO) &&
1866 !a_xtls_load_verifications(ctxp, urlp))
1867 goto jerr1;
1869 /* Done with context setup, create our new per-connection structure */
1870 if(!a_xtls_conf_finish(&confp, FAL0))
1871 goto jleave;
1872 assert(confp == NULL);
1874 if((sp->s_tls = SSL_new(ctxp)) == NULL){
1875 ssl_gen_err(_("SSL_new() failed"));
1876 goto jleave;
1879 /* Try establish SNI extension; even though this is a TLS extension the
1880 * protocol isn't checked by OpenSSL once the host name is set, and
1881 * therefore i refrained from changing so much code just to check out
1882 * whether we are using SSLv3, which should become more and more rare */
1883 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1884 if((urlp->url_flags & n_URL_TLS_MASK) &&
1885 (urlp->url_flags & n_URL_HOST_IS_NAME)){
1886 if(!SSL_set_tlsext_host_name(sp->s_tls, urlp->url_host.s) &&
1887 (n_poption & n_PO_D_V))
1888 n_err(_("Hostname cannot be used with ServerNameIndication "
1889 "TLS extension: %s\n"),
1890 n_shexp_quote_cp(urlp->url_host.s, FAL0));
1892 #endif
1894 SSL_set_fd(sp->s_tls, sp->s_fd);
1896 if(SSL_connect(sp->s_tls) < 0){
1897 ssl_gen_err(_("could not initiate TLS connection"));
1898 goto jerr2;
1901 if(fprnt != NULL || urlp->url_cproto == CPROTO_CERTINFO ||
1902 n_tls_verify_level != n_TLS_VERIFY_IGNORE){
1903 bool_t stay;
1904 X509 *peercert;
1906 if((peercert = SSL_get_peer_certificate(sp->s_tls)) == NULL){
1907 n_err(_("TLS: no certificate from peer: %s\n"), urlp->url_h_p.s);
1908 goto jerr2;
1911 stay = FAL0;
1913 if(fprnt == NULL){
1914 if(!a_xtls_check_host(sp, peercert, urlp)){
1915 n_err(_("TLS certificate does not match: %s\n"), urlp->url_h_p.s);
1916 stay = n_tls_verify_decide();
1917 }else{
1918 if(n_poption & n_PO_D_V)
1919 n_err(_("TLS certificate ok\n"));
1920 stay = TRU1;
1924 if(fprnt != NULL || urlp->url_cproto == CPROTO_CERTINFO ||
1925 (n_poption & n_PO_D_V)){
1926 char fpmdhexbuf[EVP_MAX_MD_SIZE * 3], *cp;
1927 unsigned char fpmdbuf[EVP_MAX_MD_SIZE], *ucp;
1928 unsigned int fpmdlen;
1930 if(!X509_digest(peercert, fprnt_mdp, fpmdbuf, &fpmdlen)){
1931 ssl_gen_err(_("TLS %s fingerprint creation failed"), fprnt_namep);
1932 goto jpeer_leave;
1934 assert(fpmdlen <= EVP_MAX_MD_SIZE);
1936 for(cp = fpmdhexbuf, ucp = fpmdbuf; fpmdlen > 0; --fpmdlen){
1937 n_c_to_hex_base16(cp, (char)*ucp++);
1938 cp[2] = ':';
1939 cp += 3;
1941 cp[-1] = '\0';
1943 if(n_poption & n_PO_D_V)
1944 n_err(_("TLS %s fingerprint: %s\n"), fprnt_namep, fpmdhexbuf);
1945 if(fprnt != NULL){
1946 if(!(stay = !strcmp(fprnt, fpmdhexbuf))){
1947 n_err(_("TLS fingerprint does not match: %s\n"
1948 " Expected: %s\n Detected: %s\n"),
1949 urlp->url_h_p.s, fprnt, fpmdhexbuf);
1950 stay = n_tls_verify_decide();
1951 }else if(n_poption & n_PO_D_V)
1952 n_err(_("TLS fingerprint ok\n"));
1953 goto jpeer_leave;
1954 }else if(urlp->url_cproto == CPROTO_CERTINFO)
1955 sp->s_tls_finger = savestrbuf(fpmdhexbuf,
1956 PTR2SIZE(cp - fpmdhexbuf));
1959 jpeer_leave:
1960 X509_free(peercert);
1961 if(!stay)
1962 goto jerr2;
1965 sp->s_use_tls = 1;
1966 jleave:
1967 /* We're fully setup: since we don't reuse the SSL_CTX (pooh) keep it local
1968 * and free it right now -- it is reference counted by sp->s_tls.. */
1969 SSL_CTX_free(ctxp);
1970 j_leave:
1971 NYD_LEAVE;
1972 return (sp->s_tls != NULL);
1973 jerr2:
1974 SSL_free(sp->s_tls);
1975 sp->s_tls = NULL;
1976 jerr1:
1977 if(confp != NULL)
1978 a_xtls_conf_finish(&confp, TRU1);
1979 goto jleave;
1982 FL void
1983 ssl_gen_err(char const *fmt, ...)
1985 va_list ap;
1986 NYD_ENTER;
1988 va_start(ap, fmt);
1989 n_verr(fmt, ap);
1990 va_end(ap);
1992 n_err(_(": %s\n"), ERR_error_string(ERR_get_error(), NULL));
1993 NYD_LEAVE;
1996 FL int
1997 c_verify(void *vp)
1999 int *msgvec = vp, *ip, ec = 0, rv = 1;
2000 X509_STORE *store = NULL;
2001 char *ca_dir, *ca_file;
2002 NYD_ENTER;
2004 a_xtls_init();
2006 n_tls_verify_level = n_TLS_VERIFY_STRICT;
2007 if ((store = X509_STORE_new()) == NULL) {
2008 ssl_gen_err(_("Error creating X509 store"));
2009 goto jleave;
2011 X509_STORE_set_verify_cb_func(store, &a_xtls_verify_cb);
2013 if ((ca_dir = ok_vlook(smime_ca_dir)) != NULL)
2014 ca_dir = fexpand(ca_dir, FEXP_LOCAL | FEXP_NOPROTO);
2015 if ((ca_file = ok_vlook(smime_ca_file)) != NULL)
2016 ca_file = fexpand(ca_file, FEXP_LOCAL | FEXP_NOPROTO);
2018 if((ca_dir != NULL || ca_file != NULL) &&
2019 X509_STORE_load_locations(store, ca_file, ca_dir) != 1){
2020 char const *m1, *m2, *m3;
2022 if(ca_dir != NULL){
2023 m1 = ca_dir;
2024 m2 = (ca_file != NULL) ? _(" or ") : n_empty;
2025 }else
2026 m1 = m2 = n_empty;
2027 m3 = (ca_file != NULL) ? ca_file : n_empty;
2028 ssl_gen_err(_("Error loading %s%s%s\n"), m1, m2, m3);
2029 goto jleave;
2032 /* C99 */{
2033 bool_t xv15;
2035 if((xv15 = ok_blook(smime_no_default_ca)))
2036 n_OBSOLETE(_("please use *smime-ca-no-defaults*, "
2037 "not *smime-no-default-ca*"));
2038 if(!ok_blook(smime_ca_no_defaults) && !xv15 &&
2039 X509_STORE_set_default_paths(store) != 1) {
2040 ssl_gen_err(_("Error loading built-in default CA locations\n"));
2041 goto jleave;
2045 if (load_crls(store, ok_v_smime_crl_file, ok_v_smime_crl_dir) != OKAY)
2046 goto jleave;
2048 a_xtls_ca_flags(store, ok_vlook(smime_ca_flags));
2050 srelax_hold();
2051 for (ip = msgvec; *ip != 0; ++ip) {
2052 struct message *mp = message + *ip - 1;
2053 setdot(mp);
2054 ec |= smime_verify(mp, *ip, NULL, store);
2055 srelax();
2057 srelax_rele();
2059 if ((rv = ec) != 0)
2060 n_exit_status |= n_EXIT_ERR;
2061 jleave:
2062 if (store != NULL)
2063 X509_STORE_free(store);
2064 NYD_LEAVE;
2065 return rv;
2068 FL FILE *
2069 smime_sign(FILE *ip, char const *addr)
2071 FILE *rv, *sp, *fp, *bp, *hp;
2072 X509 *cert = NULL;
2073 n_XTLS_STACKOF(X509) *chain = NULL;
2074 EVP_PKEY *pkey = NULL;
2075 BIO *bb, *sb;
2076 PKCS7 *pkcs7;
2077 EVP_MD const *md;
2078 char const *name;
2079 bool_t bail = FAL0;
2080 NYD_ENTER;
2082 assert(addr != NULL);
2083 rv = sp = fp = bp = hp = NULL;
2085 a_xtls_init();
2087 if (addr == NULL) {
2088 n_err(_("No *from* address for signing specified\n"));
2089 goto jleave;
2091 if ((fp = smime_sign_cert(addr, NULL, 1, NULL)) == NULL)
2092 goto jleave;
2094 if ((pkey = PEM_read_PrivateKey(fp, NULL, &ssl_password_cb,
2095 savecat(addr, ".smime-cert-key"))) == NULL) {
2096 ssl_gen_err(_("Error reading private key from"));
2097 goto jleave;
2100 rewind(fp);
2101 if ((cert = PEM_read_X509(fp, NULL, &ssl_password_cb,
2102 savecat(addr, ".smime-cert-cert"))) == NULL) {
2103 ssl_gen_err(_("Error reading signer certificate from"));
2104 goto jleave;
2106 Fclose(fp);
2107 fp = NULL;
2109 if ((name = _smime_sign_include_certs(addr)) != NULL &&
2110 !_smime_sign_include_chain_creat(&chain, name,
2111 savecat(addr, ".smime-include-certs")))
2112 goto jleave;
2114 name = NULL;
2115 if ((md = a_xtls_smime_sign_digest(addr, &name)) == NULL)
2116 goto jleave;
2118 if ((sp = Ftmp(NULL, "smimesign", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
2119 NULL) {
2120 n_perr(_("tempfile"), 0);
2121 goto jleave;
2124 rewind(ip);
2125 if (smime_split(ip, &hp, &bp, -1, 0) == STOP)
2126 goto jleave;
2128 sb = NULL;
2129 pkcs7 = NULL;
2131 if ((bb = BIO_new_fp(bp, BIO_NOCLOSE)) == NULL ||
2132 (sb = BIO_new_fp(sp, BIO_NOCLOSE)) == NULL) {
2133 ssl_gen_err(_("Error creating BIO signing objects"));
2134 bail = TRU1;
2135 goto jerr;
2138 #undef _X
2139 #define _X PKCS7_DETACHED | PKCS7_PARTIAL
2140 if ((pkcs7 = PKCS7_sign(NULL, NULL, chain, bb, _X)) == NULL) {
2141 ssl_gen_err(_("Error creating the PKCS#7 signing object"));
2142 bail = TRU1;
2143 goto jerr;
2145 if (PKCS7_sign_add_signer(pkcs7, cert, pkey, md, _X) == NULL) {
2146 ssl_gen_err(_("Error setting PKCS#7 signing object signer"));
2147 bail = TRU1;
2148 goto jerr;
2150 if (!PKCS7_final(pkcs7, bb, _X)) {
2151 ssl_gen_err(_("Error finalizing the PKCS#7 signing object"));
2152 bail = TRU1;
2153 goto jerr;
2155 #undef _X
2157 if (PEM_write_bio_PKCS7(sb, pkcs7) == 0) {
2158 ssl_gen_err(_("Error writing signed S/MIME data"));
2159 bail = TRU1;
2160 /*goto jerr*/
2162 jerr:
2163 if (pkcs7 != NULL)
2164 PKCS7_free(pkcs7);
2165 if (sb != NULL)
2166 BIO_free(sb);
2167 if (bb != NULL)
2168 BIO_free(bb);
2169 if (!bail) {
2170 rewind(bp);
2171 fflush_rewind(sp);
2172 rv = smime_sign_assemble(hp, bp, sp, name);
2173 hp = bp = sp = NULL;
2176 jleave:
2177 if (chain != NULL)
2178 sk_X509_pop_free(chain, X509_free);
2179 if (cert != NULL)
2180 X509_free(cert);
2181 if (pkey != NULL)
2182 EVP_PKEY_free(pkey);
2183 if (fp != NULL)
2184 Fclose(fp);
2185 if (hp != NULL)
2186 Fclose(hp);
2187 if (bp != NULL)
2188 Fclose(bp);
2189 if (sp != NULL)
2190 Fclose(sp);
2191 NYD_LEAVE;
2192 return rv;
2195 FL FILE *
2196 smime_encrypt(FILE *ip, char const *xcertfile, char const *to)
2198 FILE *rv, *yp, *fp, *bp, *hp;
2199 X509 *cert;
2200 PKCS7 *pkcs7;
2201 BIO *bb, *yb;
2202 n_XTLS_STACKOF(X509) *certs;
2203 EVP_CIPHER const *cipher;
2204 char *certfile;
2205 bool_t bail;
2206 NYD_ENTER;
2208 bail = FAL0;
2209 rv = yp = fp = bp = hp = NULL;
2211 if ((certfile = fexpand(xcertfile, FEXP_LOCAL | FEXP_NOPROTO)) == NULL)
2212 goto jleave;
2214 a_xtls_init();
2216 if ((cipher = _smime_cipher(to)) == NULL)
2217 goto jleave;
2219 if ((fp = Fopen(certfile, "r")) == NULL) {
2220 n_perr(certfile, 0);
2221 goto jleave;
2223 if ((cert = PEM_read_X509(fp, NULL, &ssl_password_cb, NULL)) == NULL) {
2224 ssl_gen_err(_("Error reading encryption certificate from %s"),
2225 n_shexp_quote_cp(certfile, FAL0));
2226 bail = TRU1;
2228 if (bail)
2229 goto jleave;
2230 Fclose(fp);
2231 fp = NULL;
2232 bail = FAL0;
2234 certs = sk_X509_new_null();
2235 sk_X509_push(certs, cert);
2237 if ((yp = Ftmp(NULL, "smimeenc", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
2238 NULL) {
2239 n_perr(_("tempfile"), 0);
2240 goto jerr1;
2243 rewind(ip);
2244 if (smime_split(ip, &hp, &bp, -1, 0) == STOP)
2245 goto jerr1;
2247 yb = NULL;
2248 if ((bb = BIO_new_fp(bp, BIO_NOCLOSE)) == NULL ||
2249 (yb = BIO_new_fp(yp, BIO_NOCLOSE)) == NULL) {
2250 ssl_gen_err(_("Error creating BIO encryption objects"));
2251 bail = TRU1;
2252 goto jerr2;
2254 if ((pkcs7 = PKCS7_encrypt(certs, bb, cipher, 0)) == NULL) {
2255 ssl_gen_err(_("Error creating the PKCS#7 encryption object"));
2256 bail = TRU1;
2257 goto jerr2;
2259 if (PEM_write_bio_PKCS7(yb, pkcs7) == 0) {
2260 ssl_gen_err(_("Error writing encrypted S/MIME data"));
2261 bail = TRU1;
2262 /* goto jerr2 */
2264 PKCS7_free(pkcs7);
2266 jerr2:
2267 if (bb != NULL)
2268 BIO_free(bb);
2269 if (yb != NULL)
2270 BIO_free(yb);
2271 Fclose(bp);
2272 bp = NULL;
2273 if (!bail) {
2274 fflush_rewind(yp);
2275 rv = smime_encrypt_assemble(hp, yp);
2276 hp = yp = NULL;
2278 jerr1:
2279 sk_X509_pop_free(certs, X509_free);
2280 jleave:
2281 if(yp != NULL)
2282 Fclose(yp);
2283 if(fp != NULL)
2284 Fclose(fp);
2285 if(bp != NULL)
2286 Fclose(bp);
2287 if(hp != NULL)
2288 Fclose(hp);
2289 NYD_LEAVE;
2290 return rv;
2293 FL struct message *
2294 smime_decrypt(struct message *m, char const *to, char const *cc,
2295 bool_t signcall)
2297 char const *myaddr;
2298 long size;
2299 struct message *rv;
2300 FILE *bp, *hp, *op;
2301 PKCS7 *pkcs7;
2302 BIO *ob, *bb, *pb;
2303 X509 *cert;
2304 EVP_PKEY *pkey;
2305 FILE *yp;
2306 NYD_ENTER;
2308 pkey = NULL;
2309 cert = NULL;
2310 ob = bb = pb = NULL;
2311 pkcs7 = NULL;
2312 bp = hp = op = NULL;
2313 rv = NULL;
2314 size = m->m_size;
2316 if((yp = setinput(&mb, m, NEED_BODY)) == NULL)
2317 goto jleave;
2319 a_xtls_init();
2321 if((op = smime_sign_cert(to, cc, 0, &myaddr)) != NULL){
2322 pkey = PEM_read_PrivateKey(op, NULL, &ssl_password_cb,
2323 savecat(myaddr, ".smime-cert-key"));
2324 if(pkey == NULL){
2325 ssl_gen_err(_("Error reading private key"));
2326 goto jleave;
2329 rewind(op);
2330 if((cert = PEM_read_X509(op, NULL, &ssl_password_cb,
2331 savecat(myaddr, ".smime-cert-cert"))) == NULL){
2332 ssl_gen_err(_("Error reading decryption certificate"));
2333 goto jleave;
2336 Fclose(op);
2337 op = NULL;
2340 if((op = Ftmp(NULL, "smimed", OF_RDWR | OF_UNLINK | OF_REGISTER)) == NULL){
2341 n_perr(_("tempfile"), 0);
2342 goto jleave;
2345 if(smime_split(yp, &hp, &bp, size, 1) == STOP)
2346 goto jleave;
2348 if((ob = BIO_new_fp(op, BIO_NOCLOSE)) == NULL ||
2349 (bb = BIO_new_fp(bp, BIO_NOCLOSE)) == NULL){
2350 ssl_gen_err(_("Error creating BIO decryption objects"));
2351 goto jleave;
2354 if((pkcs7 = SMIME_read_PKCS7(bb, &pb)) == NULL){
2355 ssl_gen_err(_("Error reading PKCS#7 object"));
2356 goto jleave;
2359 if(PKCS7_type_is_signed(pkcs7)){
2360 if(signcall){
2361 setinput(&mb, m, NEED_BODY);
2362 rv = (struct message*)-1;
2363 goto jleave;
2365 if(PKCS7_verify(pkcs7, NULL, NULL, NULL, ob,
2366 PKCS7_NOVERIFY | PKCS7_NOSIGS) != 1)
2367 goto jerr;
2368 fseek(hp, 0L, SEEK_END);
2369 fprintf(hp, "X-Encryption-Cipher: none\n");
2370 fflush_rewind(hp);
2371 }else if(pkey == NULL){
2372 n_err(_("No appropriate private key found\n"));
2373 goto jleave;
2374 }else if(cert == NULL){
2375 n_err(_("No appropriate certificate found\n"));
2376 goto jleave;
2377 }else if(PKCS7_decrypt(pkcs7, pkey, cert, ob, 0) != 1){
2378 jerr:
2379 ssl_gen_err(_("Error decrypting PKCS#7 object"));
2380 goto jleave;
2382 fflush_rewind(op);
2383 Fclose(bp);
2384 bp = NULL;
2386 rv = smime_decrypt_assemble(m, hp, op);
2387 hp = op = NULL; /* xxx closed by decrypt_assemble */
2388 jleave:
2389 if(op != NULL)
2390 Fclose(op);
2391 if(hp != NULL)
2392 Fclose(hp);
2393 if(bp != NULL)
2394 Fclose(bp);
2395 if(bb != NULL)
2396 BIO_free(bb);
2397 if(ob != NULL)
2398 BIO_free(ob);
2399 if(pkcs7 != NULL)
2400 PKCS7_free(pkcs7);
2401 if(cert != NULL)
2402 X509_free(cert);
2403 if(pkey != NULL)
2404 EVP_PKEY_free(pkey);
2405 NYD_LEAVE;
2406 return rv;
2409 FL enum okay
2410 smime_certsave(struct message *m, int n, FILE *op)
2412 struct message *x;
2413 char *to, *cc, *cnttype;
2414 int c, i;
2415 FILE *fp, *ip;
2416 off_t size;
2417 BIO *fb, *pb;
2418 PKCS7 *pkcs7;
2419 n_XTLS_STACKOF(X509) *certs, *chain = NULL;
2420 X509 *cert;
2421 enum okay rv = STOP;
2422 NYD_ENTER;
2424 pkcs7 = NULL;
2426 a_xtls_msgno = (size_t)n;
2427 jloop:
2428 to = hfield1("to", m);
2429 cc = hfield1("cc", m);
2430 cnttype = hfield1("content-type", m);
2432 if ((ip = setinput(&mb, m, NEED_BODY)) == NULL)
2433 goto jleave;
2435 #undef _X
2436 #undef _Y
2437 #define _X (sizeof("application/") -1)
2438 #define _Y(X) X, sizeof(X) -1
2439 if (cnttype && is_asccaseprefix("application/", cnttype) &&
2440 (!ascncasecmp(cnttype + _X, _Y("pkcs7-mime")) ||
2441 !ascncasecmp(cnttype + _X, _Y("x-pkcs7-mime")))) {
2442 #undef _Y
2443 #undef _X
2444 if ((x = smime_decrypt(m, to, cc, 1)) == NULL)
2445 goto jleave;
2446 if (x != (struct message*)-1) {
2447 m = x;
2448 goto jloop;
2451 size = m->m_size;
2453 if ((fp = Ftmp(NULL, "smimecert", OF_RDWR | OF_UNLINK | OF_REGISTER)) ==
2454 NULL) {
2455 n_perr(_("tempfile"), 0);
2456 goto jleave;
2459 while (size-- > 0) {
2460 c = getc(ip);
2461 putc(c, fp);
2463 fflush(fp);
2465 rewind(fp);
2466 if ((fb = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
2467 ssl_gen_err("Error creating BIO object for message %d", n);
2468 Fclose(fp);
2469 goto jleave;
2472 if ((pkcs7 = SMIME_read_PKCS7(fb, &pb)) == NULL) {
2473 ssl_gen_err(_("Error reading PKCS#7 object for message %d"), n);
2474 BIO_free(fb);
2475 Fclose(fp);
2476 goto jleave;
2478 BIO_free(fb);
2479 Fclose(fp);
2481 certs = PKCS7_get0_signers(pkcs7, chain, 0);
2482 if (certs == NULL) {
2483 n_err(_("No certificates found in message %d\n"), n);
2484 goto jleave;
2487 for (i = 0; i < sk_X509_num(certs); ++i) {
2488 cert = sk_X509_value(certs, i);
2489 if (X509_print_fp(op, cert) == 0 || PEM_write_X509(op, cert) == 0) {
2490 ssl_gen_err(_("Error writing certificate %d from message %d"),
2491 i, n);
2492 goto jleave;
2495 rv = OKAY;
2496 jleave:
2497 if(pkcs7 != NULL)
2498 PKCS7_free(pkcs7);
2499 NYD_LEAVE;
2500 return rv;
2502 #endif /* HAVE_XTLS */
2504 /* s-it-mode */