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 *
5 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
6 * Copyright (c) 2012 - 2020 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
7 * SPDX-License-Identifier: BSD-4-Clause TODO ISC
8 */
9 /*
10 * Copyright (c) 2002
11 * Gunnar Ritter. All rights reserved.
12 *
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.
28 *
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.
40 */
41 #undef su_FILE
42 #define su_FILE xtls
43 #define mx_SOURCE
44
45 #ifndef mx_HAVE_AMALGAMATION
46 # include "mx/nail.h"
47 #endif
48
49 su_EMPTY_FILE()
50 #ifdef mx_HAVE_XTLS /* Shorthand for mx_HAVE_TLS==mx_TLS_IMPL{...} */
51 #include <sys/socket.h>
52
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>
62
63 #ifdef mx_XTLS_HAVE_CONFIG
64 # include <openssl/conf.h>
65 #endif
66 #ifdef mx_XTLS_HAVE_SET_RESEED_DEFAULTS
67 # include <openssl/rand_drbg.h>
68 #endif
69
70 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
71 # include <dirent.h>
72 #endif
73
74 #include <su/cs.h>
75 #include <su/mem.h>
76
77 #include "mx/cred-auth.h"
78 #include "mx/file-streams.h"
79 #include "mx/names.h"
80 #include "mx/net-socket.h"
81 #include "mx/random.h"
82 #include "mx/tty.h"
83 #include "mx/url.h"
84
85 /* TODO fake */
86 #include "su/code-in.h"
87
88 /* Compatibility shims which assume 0/-1 cannot really happen */
89 /* Always for _protocols #ifndef mx_XTLS_HAVE_CONF_CTX */
90 # ifndef SSL_OP_NO_SSLv2
91 # define SSL_OP_NO_SSLv2 0
92 # endif
93 # ifndef SSL_OP_NO_SSLv3
94 # define SSL_OP_NO_SSLv3 0
95 # endif
96 # ifndef SSL_OP_NO_TLSv1
97 # define SSL_OP_NO_TLSv1 0
98 # endif
99 # ifndef SSL_OP_NO_TLSv1_1
100 # define SSL_OP_NO_TLSv1_1 0
101 # endif
102 # ifndef SSL_OP_NO_TLSv1_2
103 # define SSL_OP_NO_TLSv1_2 0
104 # endif
105 # ifndef SSL_OP_NO_TLSv1_3
106 # define SSL_OP_NO_TLSv1_3 0
107 # endif
108 /* SSL_CONF_CTX and _OP_NO_SSL_MASK were both introduced with 1.0.2!?! */
109 # ifndef SSL_OP_NO_SSL_MASK
110 # define SSL_OP_NO_SSL_MASK \
111 (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |\
112 SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 |\
113 SSL_OP_NO_TLSv1_3)
114 # endif
115
116 # ifndef SSL2_VERSION
117 # define SSL2_VERSION 0
118 # endif
119 # ifndef SSL3_VERSION
120 # define SSL3_VERSION 0
121 # endif
122 # ifndef TLS1_VERSION
123 # define TLS1_VERSION 0
124 # endif
125 # ifndef TLS1_1_VERSION
126 # define TLS1_1_VERSION 0
127 # endif
128 # ifndef TLS1_2_VERSION
129 # define TLS1_2_VERSION 0
130 # endif
131 # ifndef TLS1_3_VERSION
132 # define TLS1_3_VERSION 0
133 # endif
134 /* #endif */
135
136 #ifdef mx_XTLS_HAVE_STACK_OF
137 # define a_XTLS_STACKOF(X) STACK_OF(X)
138 #else
139 # define a_XTLS_STACKOF(X) /*X*/STACK
140 #endif
141
142 #ifdef mx_XTLS_HAVE_RAND_FILE
143 # if OPENSSL_VERSION_NUMBER + 0 >= 0x0090581fL
144 # define a_XTLS_RAND_LOAD_FILE_MAXBYTES -1
145 # else
146 # define a_XTLS_RAND_LOAD_FILE_MAXBYTES 1024
147 # endif
148 #endif
149
150 /* More cute compatibility sighs */
151 #if mx_HAVE_XTLS >= 0x10100
152 # define a_xtls_X509_get_notBefore X509_get0_notBefore
153 # define a_xtls_X509_get_notAfter X509_get0_notAfter
154 # define a_xtls_SSL_get_verified_chain SSL_get0_verified_chain
155 #else
156 # define a_xtls_X509_get_notBefore X509_get_notBefore
157 # define a_xtls_X509_get_notAfter X509_get_notAfter
158 # define a_xtls_SSL_get_verified_chain SSL_get_peer_cert_chain
159 #endif
160
161 #if mx_HAVE_XTLS >= 0x30000
162 # define a_xtls_SSL_CTX_load_verify_file(CTXP,FILE) \
163 SSL_CTX_load_verify_file(CTXP, FILE)
164 # define a_xtls_SSL_CTX_load_verify_dir(CTXP,DIR) \
165 SSL_CTX_load_verify_dir(ctxp, ca_dir)
166
167 # define a_xtls_X509_STORE_load_file(STORE,FILE) \
168 X509_STORE_load_file(STORE, FILE)
169 # define a_xtls_X509_STORE_load_path(STORE,PATH) \
170 X509_STORE_load_path(STORE, PATH)
171
172 # define a_xtls_SSL_get_peer_certificate(TLSP) \
173 SSL_get0_peer_certificate(TLSP)
174 # define a_xtls_SSL_get_peer_certificate__FREE(CERT)
175
176 #else
177 # define a_xtls_SSL_CTX_load_verify_file(CTXP,FILE) \
178 SSL_CTX_load_verify_locations(CTXP, FILE, NIL)
179 # define a_xtls_SSL_CTX_load_verify_dir(CTXP,DIR) \
180 SSL_CTX_load_verify_locations(CTXP, NIL, DIR)
181
182 # define a_xtls_X509_STORE_load_file(STORE,FILE) \
183 X509_STORE_load_locations(STORE, FILE, NIL)
184 # define a_xtls_X509_STORE_load_path(STORE,PATH) \
185 X509_STORE_load_locations(STORE, NIL, PATH)
186
187 # define a_xtls_SSL_get_peer_certificate(TLSP) \
188 SSL_get_peer_certificate(TLSP)
189 # define a_xtls_SSL_get_peer_certificate__FREE(CERT) \
190 X509_free(CERT)
191 #endif /* mx_HAVE_XTLS >= 0x30000 */
192
193 /* X509_STORE_set_flags */
194 #undef a_XTLS_X509_V_ANY
195 #ifndef X509_V_FLAG_NO_ALT_CHAINS
196 # define X509_V_FLAG_NO_ALT_CHAINS -1
197 #else
198 # undef a_XTLS_X509_V_ANY
199 # define a_XTLS_X509_V_ANY
200 #endif
201 #ifndef X509_V_FLAG_NO_CHECK_TIME
202 # define X509_V_FLAG_NO_CHECK_TIME -1
203 #else
204 # undef a_XTLS_X509_V_ANY
205 # define a_XTLS_X509_V_ANY
206 #endif
207 #ifndef X509_V_FLAG_PARTIAL_CHAIN
208 # define X509_V_FLAG_PARTIAL_CHAIN -1
209 #else
210 # undef a_XTLS_X509_V_ANY
211 # define a_XTLS_X509_V_ANY
212 #endif
213 #ifndef X509_V_FLAG_X509_STRICT
214 # define X509_V_FLAG_X509_STRICT -1
215 #else
216 # undef a_XTLS_X509_V_ANY
217 # define a_XTLS_X509_V_ANY
218 #endif
219 #ifndef X509_V_FLAG_TRUSTED_FIRST
220 # define X509_V_FLAG_TRUSTED_FIRST -1
221 #else
222 # undef a_XTLS_X509_V_ANY
223 # define a_XTLS_X509_V_ANY
224 #endif
225
226 enum a_xtls_state{
227 a_XTLS_S_INIT = 1u<<0,
228 a_XTLS_S_RAND_DRBG_INIT = 1u<<1,
229 a_XTLS_S_RAND_INIT = 1u<<2,
230 a_XTLS_S_CONF_LOAD = 1u<<3,
231
232 #if mx_HAVE_XTLS < 0x10100
233 a_XTLS_S_EXIT_HDL = 1u<<8,
234 a_XTLS_S_ALGO_LOAD = 1u<<9,
235 #endif
236
237 a_XTLS_S_VERIFY_ERROR = 1u<<16
238 };
239
240 struct ssl_method { /* TODO v15 obsolete */
241 char const sm_name[8];
242 char const sm_map[16];
243 };
244
245 struct a_xtls_protocol{
246 char const xp_name[8];
247 sl xp_op_no; /* SSL_OP_NO_* bit */
248 u16 xp_version; /* *_VERSION number */
249 boole xp_ok_minmaxproto; /* Valid for {Min,Max}Protocol= */
250 boole xp_ok_proto; /* Valid for Protocol= */
251 boole xp_last;
252 boole xp_is_all; /* The special "ALL" */
253 u8 xp__dummy[2];
254 };
255
256 struct a_xtls_cipher{
257 char const xc_name[8];
258 EVP_CIPHER const *(*xc_fun)(void);
259 };
260
261 struct a_xtls_digest{
262 char const xd_name[16];
263 EVP_MD const *(*xd_fun)(void);
264 };
265
266 struct a_xtls_x509_v_flags{
267 char const xxvf_name[20];
268 s32 xxvf_flag;
269 };
270
271 /* Supported SSL/TLS methods: update manual on change! */
272 static struct ssl_method const _ssl_methods[] = { /* TODO obsolete */
273 {"auto", "ALL,-SSLv2"},
274 {"ssl3", "-ALL,SSLv3"},
275 {"tls1", "-ALL,TLSv1"},
276 {"tls1.1", "-ALL,TLSv1.1"},
277 {"tls1.2", "-ALL,TLSv1.2"}
278 };
279
280 /* Update manual on change!
281 * Ensure array size by adding \0 to longest entry.
282 * Strictly to be sorted new/up to old/down, [0]=ALL, [x-1]=None! */
283 static struct a_xtls_protocol const a_xtls_protocols[] = {
284 {"ALL", SSL_OP_NO_SSL_MASK, 0, FAL0, TRU1, FAL0, TRU1, {0}},
285 {"TLSv1.3\0", SSL_OP_NO_TLSv1_3, TLS1_3_VERSION, TRU1,TRU1,FAL0,FAL0,{0}},
286 {"TLSv1.2", SSL_OP_NO_TLSv1_2, TLS1_2_VERSION, TRU1, TRU1, FAL0, FAL0, {0}},
287 {"TLSv1.1", SSL_OP_NO_TLSv1_1, TLS1_1_VERSION, TRU1, TRU1, FAL0, FAL0, {0}},
288 {"TLSv1", SSL_OP_NO_TLSv1, TLS1_VERSION, TRU1, TRU1, FAL0, FAL0, {0}},
289 {"SSLv3", SSL_OP_NO_SSLv3, SSL3_VERSION, TRU1, TRU1, FAL0, FAL0, {0}},
290 {"SSLv2", SSL_OP_NO_SSLv2, SSL2_VERSION, TRU1, TRU1, FAL0, FAL0, {0}},
291 {"None", SSL_OP_NO_SSL_MASK, 0, TRU1, FAL0, TRU1, FAL0, {0}}
292 };
293
294 /* Supported S/MIME cipher algorithms */
295 static struct a_xtls_cipher const a_xtls_ciphers[] = { /*Manual!*/
296 #ifndef OPENSSL_NO_AES
297 # define a_XTLS_SMIME_DEFAULT_CIPHER EVP_aes_128_cbc /* According RFC 5751 */
298 {"AES128", &EVP_aes_128_cbc},
299 {"AES256", &EVP_aes_256_cbc},
300 {"AES192", &EVP_aes_192_cbc},
301 #endif
302 #ifndef OPENSSL_NO_DES
303 # ifndef a_XTLS_SMIME_DEFAULT_CIPHER
304 # define a_XTLS_SMIME_DEFAULT_CIPHER EVP_des_ede3_cbc
305 # endif
306 {"DES3", &EVP_des_ede3_cbc},
307 {"DES", &EVP_des_cbc},
308 #endif
309 };
310 #ifndef a_XTLS_SMIME_DEFAULT_CIPHER
311 # error Your OpenSSL library does not include the necessary
312 # error cipher algorithms that are required to support S/MIME
313 #endif
314
315 #ifndef OPENSSL_NO_AES
316 /* TODO obsolete a_xtls_smime_ciphers_obs */
317 static struct a_xtls_cipher const a_xtls_smime_ciphers_obs[] = {
318 {"AES-128", &EVP_aes_128_cbc},
319 {"AES-256", &EVP_aes_256_cbc},
320 {"AES-192", &EVP_aes_192_cbc}
321 };
322 #endif
323
324 /* Supported S/MIME message digest algorithms.
325 * Update manual on default changes! */
326 static struct a_xtls_digest const a_xtls_digests[] = { /*Manual!*/
327 #ifdef mx_XTLS_HAVE_BLAKE2
328 {"BLAKE2b512\0", &EVP_blake2b512},
329 {"BLAKE2s256", &EVP_blake2s256},
330 # ifndef a_XTLS_FINGERPRINT_DEFAULT_DIGEST
331 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST EVP_blake2s256
332 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S "BLAKE2s256"
333 # endif
334 #endif
335
336 #ifdef mx_XTLS_HAVE_SHA3
337 {"SHA3-512\0", &EVP_sha3_512},
338 {"SHA3-384", &EVP_sha3_384},
339 {"SHA3-256", &EVP_sha3_256},
340 {"SHA3-224", &EVP_sha3_224},
341 #endif
342
343 #ifndef OPENSSL_NO_SHA512
344 {"SHA512\0", &EVP_sha512},
345 {"SHA384", &EVP_sha384},
346 # ifndef a_XTLS_SMIME_DEFAULT_DIGEST
347 # define a_XTLS_SMIME_DEFAULT_DIGEST EVP_sha512
348 # define a_XTLS_SMIME_DEFAULT_DIGEST_S "SHA512"
349 # endif
350 #endif
351
352 #ifndef OPENSSL_NO_SHA256
353 {"SHA256\0", &EVP_sha256},
354 {"SHA224", &EVP_sha224},
355 # ifndef a_XTLS_SMIME_DEFAULT_DIGEST
356 # define a_XTLS_SMIME_DEFAULT_DIGEST EVP_sha256
357 # define a_XTLS_SMIME_DEFAULT_DIGEST_S "SHA256"
358 # endif
359 # ifndef a_XTLS_FINGERPRINT_DEFAULT_DIGEST
360 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST EVP_sha256
361 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S "SHA256"
362 # endif
363 #endif
364
365 #ifndef OPENSSL_NO_SHA
366 {"SHA1\0", &EVP_sha1},
367 # ifndef a_XTLS_SMIME_DEFAULT_DIGEST
368 # define a_XTLS_SMIME_DEFAULT_DIGEST EVP_sha1
369 # define a_XTLS_SMIME_DEFAULT_DIGEST_S "SHA1"
370 # endif
371 # ifndef a_XTLS_FINGERPRINT_DEFAULT_DIGEST
372 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST EVP_sha1
373 # define a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S "SHA1"
374 # endif
375 #endif
376
377 #ifndef OPENSSL_NO_MD5
378 {"MD5\0", &EVP_md5},
379 #endif
380 };
381
382 #if !defined a_XTLS_SMIME_DEFAULT_DIGEST || \
383 !defined a_XTLS_FINGERPRINT_DEFAULT_DIGEST
384 # error Not enough supported message digest algorithms available
385 #endif
386
387 /* X509_STORE_set_flags() for *{smime,ssl}-ca-flags* */
388 static struct a_xtls_x509_v_flags const a_xtls_x509_v_flags[] = { /* Manual! */
389 {"no-alt-chains", X509_V_FLAG_NO_ALT_CHAINS},
390 {"no-check-time", X509_V_FLAG_NO_CHECK_TIME},
391 {"partial-chain", X509_V_FLAG_PARTIAL_CHAIN},
392 {"strict", X509_V_FLAG_X509_STRICT},
393 {"trusted-first", X509_V_FLAG_TRUSTED_FIRST},
394 };
395
396 static uz a_xtls_state;
397 static uz a_xtls_msgno;
398
399 /* Special pre-PRNG PRNG init */
400 #ifdef mx_XTLS_HAVE_SET_RESEED_DEFAULTS
401 SINLINE void a_xtls_rand_drbg_init(void);
402 #else
403 # define a_xtls_rand_drbg_init() \
404 do {a_xtls_state |= a_XTLS_S_RAND_DRBG_INIT;} while(0)
405 #endif
406
407 /* PRNG init */
408 #ifdef mx_XTLS_HAVE_RAND_FILE
409 static void a_xtls_rand_init(void);
410 #else
411 # define a_xtls_rand_init() \
412 do {a_xtls_state |= a_XTLS_S_RAND_INIT;} while(0)
413 #endif
414
415 /* Library init */
416 static void a_xtls_init(void);
417
418 #if mx_HAVE_XTLS < 0x10100
419 # ifdef mx_HAVE_TLS_ALL_ALGORITHMS
420 static void a_xtls__load_algos(void);
421 # define a_xtls_load_algos a_xtls__load_algos
422 # endif
423 # if defined mx_XTLS_HAVE_CONFIG || defined mx_HAVE_TLS_ALL_ALGORITHMS
424 static void a_xtls_atexit(void);
425 # endif
426 #endif
427 #ifndef a_xtls_load_algos
428 # define a_xtls_load_algos() do{;}while(0)
429 #endif
430
431 static boole a_xtls_parse_asn1_time(ASN1_TIME const *atp,
432 char *bdat, uz blen);
433 static int a_xtls_verify_cb(int success, X509_STORE_CTX *store);
434
435 static boole a_xtls_digest_find(char const *name, EVP_MD const **mdp,
436 char const **normalized_name_or_null);
437
438 /* *smime-ca-flags*, *tls-ca-flags* */
439 static void a_xtls_ca_flags(X509_STORE *store, char const *flags);
440
441 /* SSL_CTX configuration; the latter always NULLs *confp */
442 static void *a_xtls_conf_setup(SSL_CTX *ctxp, struct mx_url const *urlp);
443 static boole a_xtls_conf(void *confp, char const *cmd, char const *value);
444 static boole a_xtls_conf_finish(void **confp, boole error);
445
446 static boole a_xtls_obsolete_conf_vars(void *confp, struct mx_url const *urlp);
447 static boole a_xtls_config_pairs(void *confp, struct mx_url const *urlp);
448 static boole a_xtls_load_verifications(SSL_CTX *ctxp,
449 struct mx_url const *urlp);
450
451 static boole a_xtls_check_host(struct mx_socket *sop, X509 *peercert,
452 struct mx_url const *urlp);
453
454 static int smime_verify(struct message *m, int n,
455 a_XTLS_STACKOF(X509) *chain, X509_STORE *store);
456 static EVP_CIPHER const * _smime_cipher(char const *name);
457 static int ssl_password_cb(char *buf, int size, int rwflag,
458 void *userdata);
459 static FILE * smime_sign_cert(char const *xname, char const *xname2,
460 boole dowarn, char const **match, boole fallback_from);
461 static char const * _smime_sign_include_certs(char const *name);
462 static boole _smime_sign_include_chain_creat(a_XTLS_STACKOF(X509) **chain,
463 char const *cfiles, char const *addr);
464 static EVP_MD const *a_xtls_smime_sign_digest(char const *name,
465 char const **digname);
466 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
467 static enum okay load_crl1(X509_STORE *store, char const *name);
468 #endif
469 static enum okay load_crls(X509_STORE *store, enum okeys fok, enum okeys dok);
470
471 #ifdef mx_XTLS_HAVE_SET_RESEED_DEFAULTS
472 SINLINE void
a_xtls_rand_drbg_init(void)473 a_xtls_rand_drbg_init(void){
474 (void)RAND_DRBG_set_reseed_defaults(0, 0, 0, 0); /* (does not fail here) */
475 a_xtls_state |= a_XTLS_S_RAND_DRBG_INIT;
476 }
477 #endif
478
479 #ifdef mx_XTLS_HAVE_RAND_FILE
480 static void
a_xtls_rand_init(void)481 a_xtls_rand_init(void){
482 # define a_XTLS_RAND_ENTROPY 32
483 char b64buf[a_XTLS_RAND_ENTROPY * 5 +1], *randfile;
484 char const *cp, *x;
485 boole err;
486 NYD2_IN;
487
488 a_xtls_rand_drbg_init();
489 a_xtls_state |= a_XTLS_S_RAND_INIT;
490
491 # ifdef mx_XTLS_HAVE_CONFIG
492 if(!(a_xtls_state & a_XTLS_S_INIT))
493 a_xtls_init();
494 # endif
495
496 err = TRU1;
497 randfile = NULL;
498
499 /* Prefer possible user setting */
500 if((cp = ok_vlook(tls_rand_file)) != NULL ||
501 (cp = ok_vlook(ssl_rand_file)) != NULL){
502 x = NULL;
503 if(*cp != '\0'){
504 if((x = fexpand(cp, (FEXP_NOPROTO | FEXP_LOCAL_FILE | FEXP_NSHELL))
505 ) == NIL)
506 n_err(_("*tls-rand-file*: expansion of %s failed "
507 "(using default)\n"),
508 n_shexp_quote_cp(cp, FAL0));
509 }
510 cp = x;
511 }
512 if(cp == NULL){
513 randfile = n_lofi_alloc(PATH_MAX);
514 if((cp = RAND_file_name(randfile, PATH_MAX)) == NULL){
515 n_err(_("*tls-rand-file*: no TLS entropy file, can't seed PRNG\n"));
516 goto jleave;
517 }
518 }
519
520 (void)RAND_load_file(cp, a_XTLS_RAND_LOAD_FILE_MAXBYTES);
521
522 /* And feed in some data, then write the updated file.
523 * While this rather feeds the PRNG with itself in the RANDOM_IMPL_TLS
524 * case, let us stir the buffer a little bit.
525 * Estimate a low but likely still too high number of entropy bytes, use
526 * 20%: base64 uses 3 input = 4 output bytes relation, and the base64
527 * alphabet is a 6 bit one */
528 for(x = (char*)-1;;){
529 RAND_add(mx_random_create_buf(b64buf, sizeof(b64buf) -1, NIL),
530 sizeof(b64buf) -1, a_XTLS_RAND_ENTROPY);
531 if((x = (char*)((up)x >> (1
532 # if mx_HAVE_RANDOM == mx_RANDOM_IMPL_TLS
533 + 3
534 # endif
535 ))) == NULL){
536 err = (RAND_status() == 0);
537 break;
538 }
539 # if mx_HAVE_RANDOM != mx_RANDOM_IMPL_TLS
540 if(!(err = (RAND_status() == 0)))
541 break;
542 # endif
543 }
544
545 if(!err)
546 err = (RAND_write_file(cp) == -1);
547
548 jleave:
549 if(randfile != NULL)
550 n_lofi_free(randfile);
551 if(err)
552 n_panic(_("Cannot seed the *TLS PseudoRandomNumberGenerator, "
553 "RAND_status() is 0!\n"
554 " Please set *tls-rand-file* to a file with sufficient entropy.\n"
555 " On a machine with entropy: "
556 "\"$ dd if=/dev/urandom of=FILE bs=1024 count=1\"\n"));
557 NYD2_OU;
558 }
559 #endif /* mx_XTLS_HAVE_RAND_FILE */
560
561 static void
a_xtls_init(void)562 a_xtls_init(void){
563 #ifdef mx_XTLS_HAVE_CONFIG
564 char const *cp;
565 #endif
566 NYD2_IN;
567
568 if(a_xtls_state & a_XTLS_S_INIT)
569 goto jleave;
570
571 #if mx_HAVE_XTLS >= 0x10100
572 OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
573 OPENSSL_INIT_LOAD_CRYPTO_STRINGS
574 # ifdef mx_HAVE_TLS_ALL_ALGORITHMS
575 | OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS
576 # endif
577 , NULL);
578 #else
579 SSL_load_error_strings();
580 SSL_library_init();
581 a_xtls_load_algos();
582 #endif
583 a_xtls_state |= a_XTLS_S_INIT;
584
585 a_xtls_rand_drbg_init();
586
587 /* Load openssl.cnf or whatever was given in *tls-config-file* */
588 #ifdef mx_XTLS_HAVE_CONFIG
589 if((cp = ok_vlook(tls_config_file)) != NULL ||
590 (cp = ok_vlook(ssl_config_file)) != NULL){
591 char const *msg;
592 ul flags;
593
594 if(*cp == '\0'){
595 msg = "[default]";
596 cp = NULL;
597 flags = CONF_MFLAGS_IGNORE_MISSING_FILE;
598 }else if((msg = cp, cp = fexpand(cp, (FEXP_NOPROTO | FEXP_LOCAL_FILE |
599 FEXP_NSHELL))) != NIL)
600 flags = 0;
601 else{
602 n_err(_("*tls-config-file*: file expansion failed: %s\n"),
603 n_shexp_quote_cp(msg, FAL0));
604 goto jefile;
605 }
606
607 if(CONF_modules_load_file(cp, n_uagent, flags) == 1){
608 a_xtls_state |= a_XTLS_S_CONF_LOAD;
609 # if mx_HAVE_XTLS < 0x10100
610 if(!(a_xtls_state & a_XTLS_S_EXIT_HDL)){
611 a_xtls_state |= a_XTLS_S_EXIT_HDL;
612 atexit(&a_xtls_atexit); /* TODO generic program-wide event mech. */
613 }
614 # endif
615 if(n_poption & n_PO_D_V)
616 n_err(_("Loaded TLS configuration for %s from %s\n"), n_uagent,
617 n_shexp_quote_cp(msg, FAL0));
618 jefile:;
619 }else
620 ssl_gen_err(_("TLS CONF_modules_load_file() load error"));
621 }
622 #endif /* mx_XTLS_HAVE_CONFIG */
623
624 if(!(a_xtls_state & a_XTLS_S_RAND_INIT))
625 a_xtls_rand_init();
626
627 jleave:
628 NYD2_OU;
629 }
630
631 #if mx_HAVE_XTLS < 0x10100
632 # ifdef mx_HAVE_TLS_ALL_ALGORITHMS
633 static void
a_xtls__load_algos(void)634 a_xtls__load_algos(void){
635 NYD2_IN;
636 if(!(a_xtls_state & a_XTLS_S_ALGO_LOAD)){
637 a_xtls_state |= a_XTLS_S_ALGO_LOAD;
638 OpenSSL_add_all_algorithms();
639
640 if(!(a_xtls_state & a_XTLS_S_EXIT_HDL)){
641 a_xtls_state |= a_XTLS_S_EXIT_HDL;
642 atexit(&a_xtls_atexit); /* TODO generic program-wide event mech. */
643 }
644 }
645 NYD2_OU;
646 }
647 # endif
648
649 # if defined mx_XTLS_HAVE_CONFIG || defined mx_HAVE_TLS_ALL_ALGORITHMS
650 static void
a_xtls_atexit(void)651 a_xtls_atexit(void){
652 NYD2_IN;
653
654 # ifdef mx_XTLS_HAVE_CONFIG
655 if(a_xtls_state & a_XTLS_S_CONF_LOAD)
656 CONF_modules_free();
657 # endif
658
659 # ifdef mx_HAVE_TLS_ALL_ALGORITHMS
660 if(a_xtls_state & a_XTLS_S_ALGO_LOAD)
661 EVP_cleanup();
662 # endif
663
664 NYD2_OU;
665 }
666 # endif
667 #endif /* mx_HAVE_XTLS < 0x10100 */
668
669 static boole
a_xtls_parse_asn1_time(ASN1_TIME const * atp,char * bdat,uz blen)670 a_xtls_parse_asn1_time(ASN1_TIME const *atp, char *bdat, uz blen)
671 {
672 BIO *mbp;
673 char *mcp;
674 long l;
675 NYD_IN;
676
677 mbp = BIO_new(BIO_s_mem());
678
679 if (ASN1_TIME_print(mbp, C(ASN1_TIME*,atp)) &&
680 (l = BIO_get_mem_data(mbp, &mcp)) > 0)
681 snprintf(bdat, blen, "%.*s", (int)l, mcp);
682 else {
683 snprintf(bdat, blen, _("Bogus certificate date: %.*s"),
684 /*is (int)*/atp->length, (char const*)atp->data);
685 mcp = NULL;
686 }
687
688 BIO_free(mbp);
689 NYD_OU;
690 return (mcp != NULL);
691 }
692
693 static int
a_xtls_verify_cb(int success,X509_STORE_CTX * store)694 a_xtls_verify_cb(int success, X509_STORE_CTX *store)
695 {
696 char data[256];
697 X509 *cert;
698 int rv = TRU1;
699 NYD_IN;
700
701 if (success && !(n_poption & n_PO_D_V))
702 goto jleave;
703
704 if (a_xtls_msgno != 0) {
705 n_err(_("Message %lu:\n"), (ul)a_xtls_msgno);
706 a_xtls_msgno = 0;
707 }
708 n_err(_(" Certificate depth %d %s\n"),
709 X509_STORE_CTX_get_error_depth(store),
710 (success ? su_empty : V_(n_error)));
711
712 if ((cert = X509_STORE_CTX_get_current_cert(store)) != NULL) {
713 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof data);
714 n_err(_(" subject = %s\n"), data);
715
716 a_xtls_parse_asn1_time(a_xtls_X509_get_notBefore(cert),
717 data, sizeof data);
718 n_err(_(" notBefore = %s\n"), data);
719
720 a_xtls_parse_asn1_time(a_xtls_X509_get_notAfter(cert),
721 data, sizeof data);
722 n_err(_(" notAfter = %s\n"), data);
723
724 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof data);
725 n_err(_(" issuer = %s\n"), data);
726 }
727
728 if (!success) {
729 int err = X509_STORE_CTX_get_error(store);
730
731 n_err(_(" err %i: %s\n"), err, X509_verify_cert_error_string(err));
732 a_xtls_state |= a_XTLS_S_VERIFY_ERROR;
733 }
734
735 if(!success)
736 rv = n_tls_verify_decide();
737 jleave:
738 NYD_OU;
739 return rv;
740 }
741
742 static boole
a_xtls_digest_find(char const * name,EVP_MD const ** mdp,char const ** normalized_name_or_null)743 a_xtls_digest_find(char const *name,
744 EVP_MD const **mdp, char const **normalized_name_or_null){
745 uz i;
746 char *nn;
747 NYD2_IN;
748
749 /* C99 */{
750 char *cp, c;
751
752 i = su_cs_len(name);
753 nn = cp = n_lofi_alloc(i +1);
754 while((c = *name++) != '\0')
755 *cp++ = su_cs_to_upper(c);
756 *cp = '\0';
757
758 if(normalized_name_or_null != NULL)
759 *normalized_name_or_null = savestrbuf(nn, P2UZ(cp - nn));
760 }
761
762 for(i = 0; i < NELEM(a_xtls_digests); ++i)
763 if(!su_cs_cmp(a_xtls_digests[i].xd_name, nn)){
764 *mdp = (*a_xtls_digests[i].xd_fun)();
765 goto jleave;
766 }
767
768 /* Not a built-in algorithm, but we may have dynamic support for more */
769 #ifdef mx_HAVE_TLS_ALL_ALGORITHMS
770 if((*mdp = EVP_get_digestbyname(nn)) != NULL)
771 goto jleave;
772 #endif
773
774 n_err(_("Invalid message digest: %s\n"), n_shexp_quote_cp(nn, FAL0));
775 *mdp = NULL;
776 jleave:
777 n_lofi_free(nn);
778
779 NYD2_OU;
780 return (*mdp != NULL);
781 }
782
783 static void
a_xtls_ca_flags(X509_STORE * store,char const * flags)784 a_xtls_ca_flags(X509_STORE *store, char const *flags){
785 NYD2_IN;
786 if(flags != NULL){
787 char *iolist, *cp;
788
789 iolist = savestr(flags);
790 jouter:
791 while((cp = su_cs_sep_c(&iolist, ',', TRU1)) != NULL){
792 struct a_xtls_x509_v_flags const *xvfp;
793
794 for(xvfp = &a_xtls_x509_v_flags[0];
795 xvfp < &a_xtls_x509_v_flags[NELEM(a_xtls_x509_v_flags)];
796 ++xvfp)
797 if(!su_cs_cmp_case(cp, xvfp->xxvf_name)){
798 if(xvfp->xxvf_flag != -1){
799 #ifdef a_XTLS_X509_V_ANY
800 X509_STORE_set_flags(store, xvfp->xxvf_flag);
801 #endif
802 }else if(n_poption & n_PO_D_V)
803 n_err(_("*{smime,tls}-ca-flags*: "
804 "directive not supported: %s\n"), cp);
805 goto jouter;
806 }
807 n_err(_("*{smime,tls}-ca-flags*: invalid directive: %s\n"), cp);
808 }
809 }
810 NYD2_OU;
811 }
812
813 #ifdef mx_XTLS_HAVE_CONF_CTX
814 static void *
a_xtls_conf_setup(SSL_CTX * ctxp,struct mx_url const * urlp)815 a_xtls_conf_setup(SSL_CTX *ctxp, struct mx_url const *urlp){
816 char const *cp;
817 SSL_CONF_CTX *sccp;
818 NYD2_IN;
819
820 sccp = NULL;
821
822 if((cp = xok_vlook(tls_config_module, urlp, OXM_ALL)) != NULL ||
823 (cp = xok_vlook(ssl_config_module, urlp, OXM_ALL)) != NULL){
824 # ifdef mx_XTLS_HAVE_CTX_CONFIG
825 if(!(a_xtls_state & a_XTLS_S_CONF_LOAD)){
826 n_err(_("*tls-config-module*: no *tls-config-file* loaded: %s\n"),
827 n_shexp_quote_cp(cp, FAL0));
828 goto jleave;
829 }else if(!SSL_CTX_config(ctxp, cp)){
830 ssl_gen_err(_("*tls-config-module*: load error for %s, section [%s]"),
831 n_uagent, n_shexp_quote_cp(cp, FAL0));
832 goto jleave;
833 }
834 # else
835 n_err(_("*tls-config-module*: set but not supported: %s\n"),
836 n_shexp_quote_cp(cp, FAL0));
837 goto jleave;
838 # endif
839 }
840
841 if((sccp = SSL_CONF_CTX_new()) != NULL){
842 SSL_CONF_CTX_set_flags(sccp,
843 SSL_CONF_FLAG_FILE | SSL_CONF_FLAG_CLIENT |
844 SSL_CONF_FLAG_CERTIFICATE | SSL_CONF_FLAG_SHOW_ERRORS);
845
846 SSL_CONF_CTX_set_ssl_ctx(sccp, ctxp);
847 }else
848 ssl_gen_err(_("SSL_CONF_CTX_new() failed"));
849 jleave:
850 NYD2_OU;
851 return sccp;
852 }
853
854 static boole
a_xtls_conf(void * confp,char const * cmd,char const * value)855 a_xtls_conf(void *confp, char const *cmd, char const *value){
856 int rv;
857 SSL_CONF_CTX *sccp;
858 NYD2_IN;
859
860 if(n_poption & n_PO_D_V)
861 n_err(_("TLS: applying config: %s = %s\n"),
862 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(value, FAL0));
863
864 rv = SSL_CONF_cmd(sccp = confp, cmd, value);
865 if(rv == 2)
866 rv = 0;
867 else{
868 cmd = n_shexp_quote_cp(cmd, FAL0);
869 value = n_shexp_quote_cp(value, FAL0);
870 if(rv == 0)
871 ssl_gen_err(_("TLS: config failure: %s = %s"), cmd, value);
872 else{
873 char const *err;
874
875 switch(rv){
876 case -2: err = N_("TLS: config command not recognized"); break;
877 case -3: err = N_("TLS: missing required config argument"); break;
878 default: err = N_("TLS: unspecified config error"); break;
879 }
880 err = V_(err);
881 n_err(_("%s (%d): %s = %s\n"), err, rv, cmd, value);
882 }
883 rv = 1;
884 }
885 NYD2_OU;
886 return (rv == 0);
887 }
888
889 static boole
a_xtls_conf_finish(void ** confp,boole error)890 a_xtls_conf_finish(void **confp, boole error){
891 SSL_CONF_CTX *sccp;
892 boole rv;
893 NYD2_IN;
894
895 sccp = (SSL_CONF_CTX*)*confp;
896 *confp = NULL;
897
898 if(!(rv = error))
899 rv = (SSL_CONF_CTX_finish(sccp) != 0);
900
901 SSL_CONF_CTX_free(sccp);
902 NYD2_OU;
903 return rv;
904 }
905
906 #else /* mx_XTLS_HAVE_CONF_CTX */
907 # ifdef mx_XTLS_HAVE_CTX_CONFIG
908 # error SSL_CTX_config(3) support unexpected without SSL_CONF_CTX support
909 # endif
910
911 static void *
a_xtls_conf_setup(SSL_CTX * ctxp,struct mx_url const * urlp)912 a_xtls_conf_setup(SSL_CTX* ctxp, struct mx_url const *urlp){
913 char const *cp;
914 NYD2_IN;
915
916 if((cp = xok_vlook(tls_config_module, urlp, OXM_ALL)) != NULL ||
917 (cp = xok_vlook(ssl_config_module, urlp, OXM_ALL)) != NULL){
918 n_err(_("*tls-config-module*: set but not supported: %s\n"),
919 n_shexp_quote_cp(cp, FAL0));
920 ctxp = NULL;
921 }
922 NYD2_OU;
923 return ctxp;
924 }
925
926 static boole
a_xtls_conf(void * confp,char const * cmd,char const * value)927 a_xtls_conf(void *confp, char const *cmd, char const *value){
928 char const *xcmd, *emsg;
929 SSL_CTX *ctxp;
930 NYD2_IN;
931
932 if(n_poption & n_PO_D_V)
933 n_err(_("TLS: applying config: %s = %s\n"),
934 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(value, FAL0));
935
936 ctxp = confp;
937
938 if(!su_cs_cmp_case(cmd, xcmd = "Certificate")){
939 if(SSL_CTX_use_certificate_chain_file(ctxp, value) != 1){
940 emsg = N_("TLS: %s: cannot load from file %s\n");
941 goto jerr;
942 }
943 }else if(!su_cs_cmp_case(cmd, xcmd = "CipherString") ||
944 !su_cs_cmp_case(cmd, xcmd = "CipherList")/* XXX bad bug in past! */){
945 if(SSL_CTX_set_cipher_list(ctxp, value) != 1){
946 emsg = N_("TLS: %s: invalid: %s\n");
947 goto jerr;
948 }
949 }else if(!su_cs_cmp_case(cmd, xcmd = "Ciphersuites")){
950 # ifdef mx_XTLS_HAVE_SET_CIPHERSUITES
951 if(SSL_CTX_set_ciphersuites(ctxp, value) != 1){
952 emsg = N_("TLS: %s: invalid: %s\n");
953 goto jerr;
954 }
955 # else
956 value = NULL;
957 emsg = N_("TLS: %s: directive not supported\n");
958 goto jxerr;
959 # endif
960 }else if(!su_cs_cmp_case(cmd, xcmd = "Curves")){
961 # ifdef SSL_CTRL_SET_CURVES_LIST
962 if(SSL_CTX_set1_curves_list(ctxp, n_UNCONST(value)) != 1){
963 emsg = N_("TLS: %s: invalid: %s\n");
964 goto jerr;
965 }
966 # else
967 value = NULL;
968 emsg = N_("TLS: %s: directive not supported\n");
969 goto jxerr;
970 # endif
971 }else if((emsg = NULL, !su_cs_cmp_case(cmd, xcmd = "MaxProtocol")) ||
972 (emsg = (char*)-1, !su_cs_cmp_case(cmd, xcmd = "MinProtocol"))){
973 # ifndef mx_XTLS_HAVE_SET_MIN_PROTO_VERSION
974 value = NULL;
975 emsg = N_("TLS: %s: directive not supported\n");
976 goto jxerr;
977 # else
978 struct a_xtls_protocol const *xpp;
979
980 for(xpp = &a_xtls_protocols[1] /* [0] == ALL */;;)
981 if(xpp->xp_ok_minmaxproto && !su_cs_cmp_case(value, xpp->xp_name)){
982 if(xpp->xp_op_no == 0 || xpp->xp_version == 0)
983 goto jenoproto;
984 break;
985 }else if((++xpp)->xp_last)
986 goto jenoproto;
987
988 if((emsg == NULL ? SSL_CTX_set_max_proto_version(ctxp, xpp->xp_version)
989 : SSL_CTX_set_min_proto_version(ctxp, xpp->xp_version)) != 1){
990 emsg = N_("TLS: %s: cannot set protocol version: %s\n");
991 goto jerr;
992 }
993 # endif /* !mx_XTLS_HAVE_SET_MIN_PROTO_VERSION */
994 }else if(!su_cs_cmp_case(cmd, xcmd = "Options")){
995 if(su_cs_cmp_case(value, "Bugs")){
996 emsg = N_("TLS: %s: fallback only supports value \"Bugs\": %s\n");
997 goto jxerr;
998 }
999 SSL_CTX_set_options(ctxp, SSL_OP_ALL);
1000 }else if(!su_cs_cmp_case(cmd, xcmd = "PrivateKey")){
1001 if(SSL_CTX_use_PrivateKey_file(ctxp, value, SSL_FILETYPE_PEM) != 1){
1002 emsg = N_("%s: cannot load from file %s\n");
1003 goto jerr;
1004 }
1005 }else if(!su_cs_cmp_case(cmd, xcmd = "Protocol")){
1006 struct a_xtls_protocol const *xpp;
1007 char *iolist, *cp, addin;
1008 sl opts;
1009
1010 opts = 0;
1011
1012 for(iolist = cp = savestr(value);
1013 (cp = su_cs_sep_c(&iolist, ',', FAL0)) != NULL;){
1014 if(*cp == '\0'){
1015 value = NULL;
1016 emsg = N_("TLS: %s: empty elements are not supported\n");
1017 goto jxerr;
1018 }
1019
1020 addin = TRU1;
1021 switch(cp[0]){
1022 case '-': addin = FAL0; /* FALLTHRU */
1023 case '+': ++cp; /* FALLTHRU */
1024 default : break;
1025 }
1026
1027 for(xpp = &a_xtls_protocols[0];;){
1028 if(xpp->xp_ok_proto && !su_cs_cmp_case(cp, xpp->xp_name)){
1029 if((xpp->xp_op_no == 0 || xpp->xp_version == 0) &&
1030 !xpp->xp_is_all)
1031 goto jenoproto;
1032 /* We need to inverse the meaning of the _NO_s */
1033 if(!addin)
1034 opts |= xpp->xp_op_no;
1035 else
1036 opts &= ~xpp->xp_op_no;
1037 break;
1038 }else if((++xpp)->xp_last){
1039 jenoproto:
1040 emsg = N_("TLS: %s: unknown or unsupported protocol: %s\n");
1041 goto jxerr;
1042 }
1043 }
1044 }
1045
1046 SSL_CTX_clear_options(ctxp, SSL_OP_NO_SSL_MASK);
1047 SSL_CTX_set_options(ctxp, opts);
1048 }else{
1049 xcmd = n_shexp_quote_cp(cmd, FAL0);
1050 emsg = N_("TLS: unsupported directive: %s: value: %s\n");
1051 goto jxerr;
1052 }
1053
1054 jleave:
1055 NYD2_OU;
1056 return (confp != NULL);
1057 jerr:
1058 ssl_gen_err(V_(emsg), xcmd, n_shexp_quote_cp(value, FAL0));
1059 confp = NULL;
1060 goto jleave;
1061 jxerr:
1062 if(value != NULL)
1063 value = n_shexp_quote_cp(value, FAL0);
1064 n_err(V_(emsg), xcmd, value);
1065 confp = NULL;
1066 goto jleave;
1067 }
1068
1069 static boole
a_xtls_conf_finish(void ** confp,boole error)1070 a_xtls_conf_finish(void **confp, boole error){
1071 UNUSED(confp);
1072 UNUSED(error);
1073 *confp = NULL;
1074 return TRU1;
1075 }
1076 #endif /* !mx_XTLS_HAVE_CONF_CTX */
1077
1078 static boole
a_xtls_obsolete_conf_vars(void * confp,struct mx_url const * urlp)1079 a_xtls_obsolete_conf_vars(void *confp, struct mx_url const *urlp){
1080 char const *cp, *cp_base, *certchain;
1081 boole rv;
1082 NYD2_IN;
1083
1084 rv = FAL0;
1085
1086 /* Certificate via ssl-cert */
1087 if((certchain = cp = xok_vlook(ssl_cert, urlp, OXM_ALL)) != NULL){
1088 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-cert*"));
1089 if((cp_base = fexpand(cp, (FEXP_NOPROTO | FEXP_LOCAL_FILE | FEXP_NSHELL))
1090 ) == NIL){
1091 n_err(_("*ssl-cert* value expansion failed: %s\n"),
1092 n_shexp_quote_cp(cp, FAL0));
1093 goto jleave;
1094 }
1095 if(!a_xtls_conf(confp, "Certificate", certchain = cp_base))
1096 goto jleave;
1097 }
1098
1099 /* CipherString via ssl-ciper-list */
1100 if((cp = xok_vlook(ssl_cipher_list, urlp, OXM_ALL)) != NULL){
1101 n_OBSOLETE(_("please use *tls-config-pairs* instead of "
1102 "*ssl-cipher-list*"));
1103 if(!a_xtls_conf(confp, "CipherString", cp))
1104 goto jleave;
1105 }
1106
1107 /* Curves via ssl-curves */
1108 if((cp = xok_vlook(ssl_curves, urlp, OXM_ALL)) != NULL){
1109 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-curves*"));
1110 if(!a_xtls_conf(confp, "Curves", cp))
1111 goto jleave;
1112 }
1113
1114 /* PrivateKey via ssl-key */
1115 if((cp = xok_vlook(ssl_key, urlp, OXM_ALL)) != NULL){
1116 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-key*"));
1117 if((cp_base = fexpand(cp, (FEXP_NOPROTO | FEXP_LOCAL_FILE | FEXP_NSHELL))
1118 ) == NIL){
1119 n_err(_("*ssl-key* value expansion failed: %s\n"),
1120 n_shexp_quote_cp(cp, FAL0));
1121 goto jleave;
1122 }
1123 cp = cp_base;
1124 if(certchain == NULL){
1125 n_err(_("*ssl-key* can only be used together with *ssl-cert*! "
1126 "And use *ssl-config-pairs*!\n"));
1127 goto jleave;
1128 }
1129 }
1130 if((cp != NULL || (cp = certchain) != NULL) &&
1131 !a_xtls_conf(confp, "PrivateKey", cp))
1132 goto jleave;
1133
1134 /* Protocol via ssl-method or ssl-protocol */
1135 if((cp = xok_vlook(ssl_method, urlp, OXM_ALL)) != NULL){
1136 uz i;
1137
1138 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-method*"));
1139 for(i = 0;;){
1140 if(!su_cs_cmp_case(_ssl_methods[i].sm_name, cp)){
1141 cp = _ssl_methods[i].sm_map;
1142 break;
1143 }
1144 if(++i == NELEM(_ssl_methods)){
1145 n_err(_("Unsupported SSL method: %s\n"), cp);
1146 goto jleave;
1147 }
1148 }
1149 }
1150 if((cp_base = xok_vlook(ssl_protocol, urlp, OXM_ALL)) != NULL){
1151 n_OBSOLETE(_("please use *tls-config-pairs* instead of *ssl-protocol*"));
1152 if(cp != NULL && (n_poption & n_PO_D_V))
1153 n_err(_("*ssl-protocol* overrides *ssl-method*! "
1154 "And please use *tls-config-pairs* instead!\n"));
1155 cp = cp_base;
1156 }
1157 if(cp != NULL && !a_xtls_conf(confp, "Protocol", cp))
1158 goto jleave;
1159
1160 rv = TRU1;
1161 jleave:
1162 NYD2_OU;
1163 return rv;
1164 }
1165
1166 static boole
a_xtls_config_pairs(void * confp,struct mx_url const * urlp)1167 a_xtls_config_pairs(void *confp, struct mx_url const *urlp){
1168 /* Due to interdependencies some commands have to be delayed a bit */
1169 static char const cmdcert[] = "Certificate", cmdprivkey[] = "PrivateKey";
1170 char const *valcert, *valprivkey;
1171 char *pairs, *cp, *cmd, *val;
1172 NYD2_IN;
1173
1174 if((pairs = n_UNCONST(xok_vlook(tls_config_pairs, urlp, OXM_ALL))
1175 ) == NULL &&
1176 (pairs = n_UNCONST(xok_vlook(ssl_config_pairs, urlp, OXM_ALL))
1177 ) == NULL)
1178 goto jleave;
1179 pairs = savestr(pairs);
1180
1181 valcert = valprivkey = NULL;
1182
1183 while((cp = su_cs_sep_escable_c(&pairs, ',', FAL0)) != NULL){
1184 char c;
1185 enum{
1186 a_NONE,
1187 a_EXPAND = 1u<<0,
1188 a_CERT = 1u<<1,
1189 a_PRIVKEY = 1u<<2,
1190 a_EXPAND_MASK = a_EXPAND | a_CERT | a_PRIVKEY
1191 } f;
1192
1193 /* Directive, space trimmed */
1194 if((cmd = su_cs_find_c(cp, '=')) == NULL){
1195 jenocmd:
1196 if(pairs == NULL)
1197 pairs = n_UNCONST(n_empty);
1198 n_err(_("*tls-config-pairs*: missing directive: %s; rest: %s\n"),
1199 n_shexp_quote_cp(cp, FAL0), n_shexp_quote_cp(pairs, FAL0));
1200 goto jleave;
1201 }
1202 val = &cmd[1];
1203
1204 if((cmd > cp && cmd[-1] == '*')){
1205 --cmd;
1206 f = a_EXPAND;
1207 }else
1208 f = a_NONE;
1209 while(cmd > cp && (c = cmd[-1], su_cs_is_space(c)))
1210 --cmd;
1211 if(cmd == cp)
1212 goto jenocmd;
1213 *cmd = '\0';
1214 cmd = cp;
1215
1216 /* Command with special treatment? */
1217 if(!su_cs_cmp_case(cmd, cmdcert))
1218 f |= a_CERT;
1219 else if(!su_cs_cmp_case(cmd, cmdprivkey))
1220 f |= a_PRIVKEY;
1221
1222 /* Value, space trimmed */
1223 while((c = *val) != '\0' && su_cs_is_space(c))
1224 ++val;
1225 cp = &val[su_cs_len(val)];
1226 while(cp > val && (c = cp[-1], su_cs_is_space(c)))
1227 --cp;
1228 *cp = '\0';
1229 if(cp == val){
1230 if(pairs == NULL)
1231 pairs = n_UNCONST(n_empty);
1232 n_err(_("*tls-config-pairs*: missing value: %s; rest: %s\n"),
1233 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(pairs, FAL0));
1234 goto jleave;
1235 }
1236
1237 /* Filename transformations to be applied? */
1238 if(f & a_EXPAND_MASK){
1239 if((cp = fexpand(val, (FEXP_NOPROTO | FEXP_LOCAL_FILE | FEXP_NSHELL))
1240 ) == NIL){
1241 if(pairs == NULL)
1242 pairs = n_UNCONST(n_empty);
1243 n_err(_("*tls-config-pairs*: value expansion failed: %s: %s; "
1244 "rest: %s\n"),
1245 n_shexp_quote_cp(cmd, FAL0), n_shexp_quote_cp(val, FAL0),
1246 n_shexp_quote_cp(pairs, FAL0));
1247 goto jleave;
1248 }
1249 val = cp;
1250 }
1251
1252 /* Some things have to be delayed */
1253 if(f & a_CERT)
1254 valcert = val;
1255 else if(f & a_PRIVKEY)
1256 valprivkey = val;
1257 else if(!a_xtls_conf(confp, cmd, val)){
1258 pairs = n_UNCONST(n_empty);
1259 goto jleave;
1260 }
1261 }
1262
1263 /* Work the delayed ones */
1264 if((valcert != NULL && !a_xtls_conf(confp, cmdcert, valcert)) ||
1265 ((valprivkey != NULL || (valprivkey = valcert) != NULL) &&
1266 !a_xtls_conf(confp, cmdprivkey, valprivkey)))
1267 pairs = n_UNCONST(n_empty);
1268
1269 jleave:
1270 NYD2_OU;
1271 return (pairs == NULL);
1272 }
1273
1274 static boole
a_xtls_load_verifications(SSL_CTX * ctxp,struct mx_url const * urlp)1275 a_xtls_load_verifications(SSL_CTX *ctxp, struct mx_url const *urlp){
1276 char *ca_dir, *ca_file;
1277 X509_STORE *store;
1278 boole rv;
1279 NYD2_IN;
1280
1281 if(n_tls_verify_level == n_TLS_VERIFY_IGNORE){
1282 rv = TRU1;
1283 goto jleave;
1284 }
1285 rv = FAL0;
1286
1287 if((ca_dir = xok_vlook(tls_ca_dir, urlp, OXM_ALL)) != NULL ||
1288 (ca_dir = xok_vlook(ssl_ca_dir, urlp, OXM_ALL)) != NULL)
1289 ca_dir = fexpand(ca_dir, (FEXP_NOPROTO | FEXP_LOCAL_FILE | FEXP_NSHELL));
1290 if((ca_file = xok_vlook(tls_ca_file, urlp, OXM_ALL)) != NULL ||
1291 (ca_file = xok_vlook(ssl_ca_file, urlp, OXM_ALL)) != NULL)
1292 ca_file = fexpand(ca_file, (FEXP_NOPROTO | FEXP_LOCAL_FILE |
1293 FEXP_NSHELL));
1294
1295 if(ca_file != NIL && a_xtls_SSL_CTX_load_verify_file(ctxp, ca_file) != 1){
1296 ssl_gen_err(_("Error loading %s\n"), n_shexp_quote_cp(ca_file, FAL0));
1297 goto jleave;
1298 }
1299
1300 if(ca_dir != NIL && a_xtls_SSL_CTX_load_verify_dir(ctxp, ca_dir) != 1){
1301 ssl_gen_err(_("Error loading %s\n"), n_shexp_quote_cp(ca_dir, FAL0));
1302 goto jleave;
1303 }
1304
1305 /* C99 */{
1306 boole xv15;
1307
1308 if((xv15 = ok_blook(ssl_no_default_ca)))
1309 n_OBSOLETE(_("please use *tls-ca-no-defaults*, "
1310 "not *ssl-no-default-ca*"));
1311 if(!xok_blook(tls_ca_no_defaults, urlp, OXM_ALL) &&
1312 !xok_blook(ssl_ca_no_defaults, urlp, OXM_ALL) && !xv15 &&
1313 SSL_CTX_set_default_verify_paths(ctxp) != 1) {
1314 ssl_gen_err(_("Error loading built-in default CA locations\n"));
1315 goto jleave;
1316 }
1317 }
1318
1319 a_xtls_state &= ~a_XTLS_S_VERIFY_ERROR;
1320 a_xtls_msgno = 0;
1321 SSL_CTX_set_verify(ctxp, SSL_VERIFY_PEER, &a_xtls_verify_cb);
1322 store = SSL_CTX_get_cert_store(ctxp);
1323 load_crls(store, ok_v_tls_crl_file, ok_v_tls_crl_dir);
1324 a_xtls_ca_flags(store, xok_vlook(tls_ca_flags, urlp, OXM_ALL));
1325 a_xtls_ca_flags(store, xok_vlook(ssl_ca_flags, urlp, OXM_ALL));
1326
1327 rv = TRU1;
1328 jleave:
1329 NYD2_OU;
1330 return rv;
1331 }
1332
1333 static boole
a_xtls_check_host(struct mx_socket * sop,X509 * peercert,struct mx_url const * urlp)1334 a_xtls_check_host(struct mx_socket *sop, X509 *peercert,
1335 struct mx_url const *urlp){
1336 char data[256];
1337 a_XTLS_STACKOF(GENERAL_NAME) *gens;
1338 GENERAL_NAME *gen;
1339 X509_NAME *subj;
1340 boole rv;
1341 NYD_IN;
1342 UNUSED(sop);
1343
1344 rv = FAL0;
1345
1346 if((gens = X509_get_ext_d2i(peercert, NID_subject_alt_name, NULL, NULL)
1347 ) != NULL){
1348 int i;
1349
1350 for(i = 0; i < sk_GENERAL_NAME_num(gens); ++i){
1351 gen = sk_GENERAL_NAME_value(gens, i);
1352 if(gen->type == GEN_DNS){
1353 if(n_poption & n_PO_D_V)
1354 n_err(_("Comparing subject_alt_name: need<%s> is<%s>\n"),
1355 urlp->url_host.s, (char*)gen->d.ia5->data);
1356 if((rv = n_tls_rfc2595_hostname_match(urlp->url_host.s,
1357 (char*)gen->d.ia5->data)))
1358 goto jleave;
1359 }
1360 }
1361 }
1362
1363 if((subj = X509_get_subject_name(peercert)) != NULL &&
1364 X509_NAME_get_text_by_NID(subj, NID_commonName, data, sizeof data
1365 ) > 0){
1366 data[sizeof data - 1] = '\0';
1367 if(n_poption & n_PO_D_V)
1368 n_err(_("Comparing commonName: need<%s> is<%s>\n"),
1369 urlp->url_host.s, data);
1370 rv = n_tls_rfc2595_hostname_match(urlp->url_host.s, data);
1371 }
1372 jleave:
1373 NYD_OU;
1374 return rv;
1375 }
1376
1377 static int
smime_verify(struct message * m,int n,a_XTLS_STACKOF (X509)* chain,X509_STORE * store)1378 smime_verify(struct message *m, int n, a_XTLS_STACKOF(X509) *chain,
1379 X509_STORE *store)
1380 {
1381 char data[LINESIZE], *sender, *to, *cc, *cnttype;
1382 int rv, c, i, j;
1383 struct message *x;
1384 FILE *fp, *ip;
1385 off_t size;
1386 BIO *fb, *pb;
1387 PKCS7 *pkcs7;
1388 a_XTLS_STACKOF(X509) *certs;
1389 a_XTLS_STACKOF(GENERAL_NAME) *gens;
1390 X509 *cert;
1391 X509_NAME *subj;
1392 GENERAL_NAME *gen;
1393 NYD_IN;
1394
1395 rv = 1;
1396 fp = NULL;
1397 fb = pb = NULL;
1398 pkcs7 = NULL;
1399 certs = NULL;
1400 a_xtls_state &= ~a_XTLS_S_VERIFY_ERROR;
1401 a_xtls_msgno = (uz)n;
1402
1403 for (;;) {
1404 sender = getsender(m);
1405 to = hfield1("to", m);
1406 cc = hfield1("cc", m);
1407 cnttype = hfield1("content-type", m);
1408
1409 #undef _X
1410 #undef _Y
1411 #define _X (sizeof("application/") -1)
1412 #define _Y(X) X, sizeof(X) -1
1413 if (cnttype && su_cs_starts_with_case(cnttype, "application/") &&
1414 (!su_cs_cmp_case_n(cnttype + _X, _Y("pkcs7-mime")) ||
1415 !su_cs_cmp_case_n(cnttype + _X, _Y("x-pkcs7-mime")))) {
1416 #undef _Y
1417 #undef _X
1418 if ((x = smime_decrypt(m, to, cc, TRU1)) == NULL)
1419 goto jleave;
1420 if (x != (struct message*)-1) {
1421 m = x;
1422 continue;
1423 }
1424 }
1425
1426 if ((ip = setinput(&mb, m, NEED_BODY)) == NULL)
1427 goto jleave;
1428 size = m->m_size;
1429 break;
1430 }
1431
1432 if((fp = mx_fs_tmp_open("smimever", (mx_FS_O_RDWR | mx_FS_O_UNLINK |
1433 mx_FS_O_REGISTER), NIL)) == NIL){
1434 n_perr(_("tempfile"), 0);
1435 goto jleave;
1436 }
1437 while (size-- > 0) {
1438 c = getc(ip);
1439 putc(c, fp);
1440 }
1441 fflush_rewind(fp);
1442
1443 if ((fb = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
1444 ssl_gen_err(_(
1445 "Error creating BIO verification object for message %d"), n);
1446 goto jleave;
1447 }
1448
1449 if ((pkcs7 = SMIME_read_PKCS7(fb, &pb)) == NULL) {
1450 ssl_gen_err(_("Error reading PKCS#7 object for message %d"), n);
1451 goto jleave;
1452 }
1453 if (PKCS7_verify(pkcs7, chain, store, pb, NULL, 0) != 1) {
1454 ssl_gen_err(_("Error verifying message %d"), n);
1455 goto jleave;
1456 }
1457
1458 if (sender == NULL) {
1459 n_err(_("Warning: Message %d has no sender\n"), n);
1460 rv = 0;
1461 goto jleave;
1462 }
1463
1464 certs = PKCS7_get0_signers(pkcs7, chain, 0);
1465 if (certs == NULL) {
1466 n_err(_("No certificates found in message %d\n"), n);
1467 goto jleave;
1468 }
1469
1470 for (i = 0; i < sk_X509_num(certs); ++i) {
1471 cert = sk_X509_value(certs, i);
1472 gens = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
1473 if (gens != NULL) {
1474 for (j = 0; j < sk_GENERAL_NAME_num(gens); ++j) {
1475 gen = sk_GENERAL_NAME_value(gens, j);
1476 if (gen->type == GEN_EMAIL) {
1477 if (n_poption & n_PO_D_V)
1478 n_err(_("Comparing subject_alt_name: need<%s> is<%s>)\n"),
1479 sender, (char*)gen->d.ia5->data);
1480 if (!su_cs_cmp_case((char*)gen->d.ia5->data, sender))
1481 goto jfound;
1482 }
1483 }
1484 }
1485
1486 if ((subj = X509_get_subject_name(cert)) != NULL &&
1487 X509_NAME_get_text_by_NID(subj, NID_pkcs9_emailAddress,
1488 data, sizeof data) > 0) {
1489 data[sizeof data -1] = '\0';
1490 if (n_poption & n_PO_D_V)
1491 n_err(_("Comparing emailAddress: need<%s> is<%s>\n"),
1492 sender, data);
1493 if (!su_cs_cmp_case(data, sender))
1494 goto jfound;
1495 }
1496 }
1497 n_err(_("Message %d: certificate does not match <%s>\n"), n, sender);
1498 goto jleave;
1499 jfound:
1500 rv = ((a_xtls_state & a_XTLS_S_VERIFY_ERROR) != 0);
1501 if (!rv)
1502 fprintf(n_stdout, _("Message %d was verified successfully\n"), n);
1503 jleave:
1504 if (certs != NULL)
1505 sk_X509_free(certs);
1506 if (pb != NULL)
1507 BIO_free(pb);
1508 if (fb != NULL)
1509 BIO_free(fb);
1510 if (pkcs7 != NULL)
1511 PKCS7_free(pkcs7);
1512 if(fp != NIL)
1513 mx_fs_close(fp);
1514 NYD_OU;
1515 return rv;
1516 }
1517
1518 static EVP_CIPHER const *
_smime_cipher(char const * name)1519 _smime_cipher(char const *name)
1520 {
1521 EVP_CIPHER const *cipher;
1522 char *vn;
1523 char const *cp;
1524 uz i;
1525 NYD_IN;
1526
1527 vn = n_lofi_alloc(i = su_cs_len(name) + sizeof("smime-cipher-") -1 +1);
1528 snprintf(vn, (int)i, "smime-cipher-%s", name);
1529 cp = n_var_vlook(vn, FAL0);
1530 n_lofi_free(vn);
1531
1532 if (cp == NULL && (cp = ok_vlook(smime_cipher)) == NULL) {
1533 cipher = a_XTLS_SMIME_DEFAULT_CIPHER();
1534 goto jleave;
1535 }
1536 cipher = NULL;
1537
1538 for(i = 0; i < NELEM(a_xtls_ciphers); ++i)
1539 if(!su_cs_cmp_case(a_xtls_ciphers[i].xc_name, cp)){
1540 cipher = (*a_xtls_ciphers[i].xc_fun)();
1541 goto jleave;
1542 }
1543 #ifndef OPENSSL_NO_AES
1544 for (i = 0; i < NELEM(a_xtls_smime_ciphers_obs); ++i) /* TODO obsolete */
1545 if (!su_cs_cmp_case(a_xtls_smime_ciphers_obs[i].xc_name, cp)) {
1546 n_OBSOLETE2(_("*smime-cipher* names with hyphens will vanish"), cp);
1547 cipher = (*a_xtls_smime_ciphers_obs[i].xc_fun)();
1548 goto jleave;
1549 }
1550 #endif
1551
1552 /* Not a built-in algorithm, but we may have dynamic support for more */
1553 #ifdef mx_HAVE_TLS_ALL_ALGORITHMS
1554 if((cipher = EVP_get_cipherbyname(cp)) != NULL)
1555 goto jleave;
1556 #endif
1557
1558 n_err(_("Invalid S/MIME cipher(s): %s\n"), cp);
1559 jleave:
1560 NYD_OU;
1561 return cipher;
1562 }
1563
1564 static int
ssl_password_cb(char * buf,int size,int rwflag,void * userdata)1565 ssl_password_cb(char *buf, int size, int rwflag, void *userdata)
1566 {
1567 char *pass;
1568 uz len;
1569 NYD_IN;
1570 UNUSED(rwflag);
1571 UNUSED(userdata);
1572
1573 /* New-style */
1574 if(userdata != NULL){
1575 struct mx_url url;
1576 struct mx_cred_ctx cred;
1577
1578 if(mx_url_parse(&url, CPROTO_CCRED, userdata)){
1579 if(mx_cred_auth_lookup(&cred, &url)){
1580 char *end;
1581
1582 if((end = su_cs_pcopy_n(buf, cred.cc_pass.s, size)) != NULL){
1583 size = (int)P2UZ(end - buf);
1584 goto jleave;
1585 }
1586 }
1587 size = 0;
1588 goto jleave;
1589 }
1590 }
1591
1592 /* Old-style */
1593 if((pass = mx_tty_getpass("PEM pass phrase:")) != NIL){
1594 len = su_cs_len(pass);
1595 if (UCMP(z, len, >=, size))
1596 len = size -1;
1597 su_mem_copy(buf, pass, len);
1598 buf[len] = '\0';
1599 size = (int)len;
1600 } else
1601 size = 0;
1602 jleave:
1603 NYD_OU;
1604 return size;
1605 }
1606
1607 static FILE *
smime_sign_cert(char const * xname,char const * xname2,boole dowarn,char const ** match,boole fallback_from)1608 smime_sign_cert(char const *xname, char const *xname2, boole dowarn,
1609 char const **match, boole fallback_from)
1610 {
1611 char *vn;
1612 int vs;
1613 struct mx_name *np;
1614 char const *name = xname, *name2 = xname2, *cp;
1615 FILE *fp = NULL;
1616 NYD_IN;
1617
1618 jloop:
1619 if (name) {
1620 np = lextract(name, GTO | GSKIN);
1621 while (np != NULL) {
1622 /* This needs to be more intelligent since it will currently take the
1623 * first name for which a private key is available regardless of
1624 * whether it is the right one for the message */
1625 vn = n_lofi_alloc(vs = su_cs_len(np->n_name) + 30);
1626 snprintf(vn, vs, "smime-sign-cert-%s", np->n_name);
1627 cp = n_var_vlook(vn, FAL0);
1628 n_lofi_free(vn);
1629 if (cp != NULL) {
1630 if (match != NULL)
1631 *match = np->n_name;
1632 goto jopen;
1633 }
1634 np = np->n_flink;
1635 }
1636 if (name2 != NULL) {
1637 name = name2;
1638 name2 = NULL;
1639 goto jloop;
1640 }
1641 }
1642
1643 /* It is the default *smime-sign-cert* / *from* pair */
1644 if((cp = ok_vlook(smime_sign_cert)) == NIL)
1645 goto jerr;
1646
1647 if(match != NIL){
1648 name = fallback_from ? myorigin(NIL) : NIL;
1649 *match = (name == NIL) ? NIL : savestr(name);
1650 }
1651
1652 jopen:
1653 if((cp = fexpand(cp, (FEXP_NOPROTO | FEXP_LOCAL_FILE | FEXP_NSHELL))
1654 ) == NIL)
1655 goto jleave;
1656 if((fp = mx_fs_open(cp, "r")) == NIL)
1657 n_perr(cp, 0);
1658
1659 jleave:
1660 NYD_OU;
1661 return fp;
1662
1663 jerr:
1664 if (dowarn)
1665 n_err(_("Could not find a certificate for %s%s%s\n"),
1666 xname, (xname2 != NULL ? _("or ") : n_empty),
1667 (xname2 != NULL ? xname2 : n_empty));
1668 goto jleave;
1669 }
1670
1671 static char const *
_smime_sign_include_certs(char const * name)1672 _smime_sign_include_certs(char const *name)
1673 {
1674 char const *rv;
1675 NYD_IN;
1676
1677 /* See comments in smime_sign_cert() for algorithm pitfalls */
1678 if (name != NULL) {
1679 struct mx_name *np;
1680
1681 for (np = lextract(name, GTO | GSKIN); np != NULL; np = np->n_flink) {
1682 int vs;
1683 char *vn;
1684
1685 vn = n_lofi_alloc(vs = su_cs_len(np->n_name) + 30);
1686 snprintf(vn, vs, "smime-sign-include-certs-%s", np->n_name);
1687 rv = n_var_vlook(vn, FAL0);
1688 n_lofi_free(vn);
1689 if (rv != NULL)
1690 goto jleave;
1691 }
1692 }
1693 rv = ok_vlook(smime_sign_include_certs);
1694 jleave:
1695 NYD_OU;
1696 return rv;
1697 }
1698
1699 static boole
_smime_sign_include_chain_creat(a_XTLS_STACKOF (X509)** chain,char const * cfiles,char const * addr)1700 _smime_sign_include_chain_creat(a_XTLS_STACKOF(X509) **chain,
1701 char const *cfiles, char const *addr)
1702 {
1703 X509 *tmp;
1704 FILE *fp;
1705 char *nfield, *cfield, *x;
1706 NYD_IN;
1707
1708 *chain = sk_X509_new_null();
1709
1710 for (nfield = savestr(cfiles);
1711 (cfield = su_cs_sep_c(&nfield, ',', TRU1)) != NULL;) {
1712 if((x = fexpand(cfield, (FEXP_NOPROTO | FEXP_LOCAL_FILE | FEXP_NSHELL))
1713 ) == NIL || (fp = mx_fs_open(cfield = x, "r")) == NIL){
1714 n_perr(cfiles, 0);
1715 goto jerr;
1716 }
1717 if ((tmp = PEM_read_X509(fp, NULL, &ssl_password_cb, n_UNCONST(addr))
1718 ) == NULL) {
1719 ssl_gen_err(_("Error reading certificate from %s"),
1720 n_shexp_quote_cp(cfield, FAL0));
1721 mx_fs_close(fp);
1722 goto jerr;
1723 }
1724 sk_X509_push(*chain, tmp);
1725 mx_fs_close(fp);
1726 }
1727
1728 if (sk_X509_num(*chain) == 0) {
1729 n_err(_("*smime-sign-include-certs* defined but empty\n"));
1730 goto jerr;
1731 }
1732 jleave:
1733 NYD_OU;
1734 return (*chain != NULL);
1735 jerr:
1736 sk_X509_pop_free(*chain, X509_free);
1737 *chain = NULL;
1738 goto jleave;
1739 }
1740
1741 static EVP_MD const *
a_xtls_smime_sign_digest(char const * name,char const ** digname)1742 a_xtls_smime_sign_digest(char const *name, char const **digname){
1743 EVP_MD const *digest;
1744 char const *cp;
1745 NYD2_IN;
1746
1747 /* See comments in smime_sign_cert() for algorithm pitfalls */
1748 if(name != NULL){
1749 struct mx_name *np;
1750
1751 for(np = lextract(name, GTO | GSKIN); np != NULL; np = np->n_flink){
1752 int vs;
1753 char *vn;
1754
1755 vn = n_lofi_alloc(vs = su_cs_len(np->n_name) + 30);
1756 snprintf(vn, vs, "smime-sign-digest-%s", np->n_name);
1757 if((cp = n_var_vlook(vn, FAL0)) == NULL){
1758 snprintf(vn, vs, "smime-sign-message-digest-%s",np->n_name);/*v15*/
1759 cp = n_var_vlook(vn, FAL0);
1760 }
1761 n_lofi_free(vn);
1762 if(cp != NULL)
1763 goto jhave_name;
1764 }
1765 }
1766
1767 if((cp = ok_vlook(smime_sign_digest)) != NULL ||
1768 (cp = ok_vlook(smime_sign_message_digest)/* v15 */) != NULL)
1769 jhave_name:
1770 if(a_xtls_digest_find(cp, &digest, digname)){
1771 #ifndef PKCS7_PARTIAL
1772 n_err(_("WARNING: old OpenSSL version, *smime-sign-digest*=%s "
1773 "ignored!\n"), digname);
1774 #endif
1775 goto jleave;
1776 }
1777
1778 digest = a_XTLS_SMIME_DEFAULT_DIGEST();
1779 *digname = a_XTLS_SMIME_DEFAULT_DIGEST_S;
1780 jleave:
1781 NYD2_OU;
1782 return digest;
1783 }
1784
1785 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1786 static enum okay
load_crl1(X509_STORE * store,char const * name)1787 load_crl1(X509_STORE *store, char const *name)
1788 {
1789 X509_LOOKUP *lookup;
1790 enum okay rv = STOP;
1791 NYD_IN;
1792
1793 if (n_poption & n_PO_D_V)
1794 n_err(_("Loading CRL from %s\n"), n_shexp_quote_cp(name, FAL0));
1795 if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) == NULL) {
1796 ssl_gen_err(_("Error creating X509 lookup object"));
1797 goto jleave;
1798 }
1799 if (X509_load_crl_file(lookup, name, X509_FILETYPE_PEM) != 1) {
1800 ssl_gen_err(_("Error loading CRL from %s"),
1801 n_shexp_quote_cp(name, FAL0));
1802 goto jleave;
1803 }
1804 rv = OKAY;
1805 jleave:
1806 NYD_OU;
1807 return rv;
1808 }
1809 #endif /* new OpenSSL */
1810
1811 static enum okay
load_crls(X509_STORE * store,enum okeys fok,enum okeys dok)1812 load_crls(X509_STORE *store, enum okeys fok, enum okeys dok)/*TODO nevertried*/
1813 {
1814 char *crl_file, *crl_dir;
1815 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1816 DIR *dirp;
1817 struct dirent *dp;
1818 char *fn = NULL;
1819 int fs = 0, ds, es;
1820 #endif
1821 boole any;
1822 enum okay rv;
1823 NYD_IN;
1824
1825 rv = STOP;
1826 any = FAL0;
1827
1828 jredo_v15:
1829 if ((crl_file = n_var_oklook(fok)) != NULL) {
1830 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1831 if((crl_file = fexpand(crl_file, (FEXP_NOPROTO | FEXP_LOCAL_FILE |
1832 FEXP_NSHELL))) == NIL || load_crl1(store, crl_file) != OKAY)
1833 goto jleave;
1834 any = TRU1;
1835 #else
1836 n_err(_("This OpenSSL version is too old to use CRLs\n"));
1837 goto jleave;
1838 #endif
1839 }
1840
1841 if ((crl_dir = n_var_oklook(dok)) != NULL) {
1842 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1843 char *x;
1844
1845 if((x = fexpand(crl_dir, (FEXP_NOPROTO | FEXP_LOCAL_FILE | FEXP_NSHELL))
1846 ) == NIL || (dirp = opendir(crl_dir = x)) == NIL){
1847 n_perr(crl_dir, 0);
1848 goto jleave;
1849 }
1850
1851 ds = su_cs_len(crl_dir);
1852 fn = n_alloc(fs = ds + 20);
1853 su_mem_copy(fn, crl_dir, ds);
1854 fn[ds] = '/';
1855 while ((dp = readdir(dirp)) != NULL) {
1856 if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' ||
1857 (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
1858 continue;
1859 if (dp->d_name[0] == '.')
1860 continue;
1861 if (ds + (es = su_cs_len(dp->d_name)) + 2 < fs)
1862 fn = n_realloc(fn, fs = ds + es + 20);
1863 su_mem_copy(fn + ds + 1, dp->d_name, es + 1);
1864 if (load_crl1(store, fn) != OKAY) {
1865 closedir(dirp);
1866 n_free(fn);
1867 goto jleave;
1868 }
1869 any = TRU1;
1870 }
1871 closedir(dirp);
1872 n_free(fn);
1873 #else /* old OpenSSL */
1874 n_err(_("This OpenSSL version is too old to use CRLs\n"));
1875 goto jleave;
1876 #endif
1877 }
1878
1879 if(fok == ok_v_tls_crl_file){
1880 fok = ok_v_ssl_crl_file;
1881 dok = ok_v_ssl_crl_dir;
1882 goto jredo_v15;
1883 }
1884 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1885 if(any)
1886 X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
1887 X509_V_FLAG_CRL_CHECK_ALL);
1888 #endif
1889 rv = OKAY;
1890 jleave:
1891 NYD_OU;
1892 return rv;
1893 }
1894
1895 #if mx_HAVE_RANDOM == mx_RANDOM_IMPL_TLS
1896 FL void
mx_tls_rand_bytes(void * buf,uz blen)1897 mx_tls_rand_bytes(void *buf, uz blen){
1898 NYD2_IN;
1899 if(!(a_xtls_state & a_XTLS_S_RAND_INIT))
1900 a_xtls_rand_init();
1901
1902 while(blen > 0){
1903 s32 i;
1904
1905 switch(RAND_bytes(buf, i = MIN(S32_MAX, blen))){
1906 default:
1907 /* LibreSSL always succeeds, i think it aborts otherwise.
1908 * With elder OpenSSL we ensure via RAND_status() in
1909 * a_xtls_rand_init() that the PRNG is seeded, so it does not fail.
1910 *
1911 * With newer OpenSSL we disable automatic reseeding, but do not
1912 * ASSERT RAND_status() ("Since you always have to check RAND_bytes's
1913 * return value now, RAND_status is mostly useless.",
1914 * 20190104180735.GA25041@roeckx.be), so we have not that many options
1915 * on what to do. Since OSs will try hard to serve, a simple sleep
1916 * may be it, so do that */
1917 #if mx_HAVE_TLS != mx_TLS_IMPL_RESSL && !defined mx_XTLS_HAVE_RAND_FILE
1918 n_err(_("TLS RAND_bytes(3ssl) failed (missing entropy?), "
1919 "waiting a bit\n"));
1920 /* Around ~Y2K+1 anything <= was a busy loop iirc, so give pad */
1921 n_msleep(250, FAL0);
1922 continue;
1923 #endif
1924 /* FALLTHRU */
1925 case 1:
1926 break;
1927 }
1928 blen -= i;
1929 buf = (u8*)buf + i;
1930 }
1931 NYD2_OU;
1932 }
1933 #endif /* HAVE_RANDOM == RANDOM_IMPL_TLS */
1934
1935 FL boole
n_tls_open(struct mx_url * urlp,struct mx_socket * sop)1936 n_tls_open(struct mx_url *urlp, struct mx_socket *sop){ /* TODO split */
1937 void *confp;
1938 SSL_CTX *ctxp;
1939 const EVP_MD *fprnt_mdp;
1940 char const *fprnt, *fprnt_namep;
1941 NYD_IN;
1942
1943 a_xtls_init();
1944 n_tls_set_verify_level(urlp); /* TODO should come in via URL! */
1945
1946 sop->s_tls = NULL;
1947 if(urlp->url_cproto != CPROTO_CERTINFO)
1948 fprnt = xok_vlook(tls_fingerprint, urlp, OXM_ALL);
1949 else
1950 fprnt = NULL;
1951 fprnt_namep = NULL;
1952 fprnt_mdp = NULL;
1953
1954 if(fprnt != NULL || urlp->url_cproto == CPROTO_CERTINFO ||
1955 (n_poption & n_PO_D_V)){
1956 if((fprnt_namep = xok_vlook(tls_fingerprint_digest, urlp,
1957 OXM_ALL)) == NULL ||
1958 !a_xtls_digest_find(fprnt_namep, &fprnt_mdp, &fprnt_namep)){
1959 fprnt_mdp = a_XTLS_FINGERPRINT_DEFAULT_DIGEST();
1960 fprnt_namep = a_XTLS_FINGERPRINT_DEFAULT_DIGEST_S;
1961 }
1962 }
1963
1964 if((ctxp = SSL_CTX_new(mx_XTLS_CLIENT_METHOD())) == NULL){
1965 ssl_gen_err(_("SSL_CTX_new() failed"));
1966 goto j_leave;
1967 }
1968
1969 /* Available with OpenSSL 0.9.6 or later */
1970 #ifdef SSL_MODE_AUTO_RETRY
1971 SSL_CTX_set_mode(ctxp, SSL_MODE_AUTO_RETRY);
1972 #endif
1973
1974 if((confp = a_xtls_conf_setup(ctxp, urlp)) == NULL)
1975 goto jleave;
1976
1977 if(!a_xtls_obsolete_conf_vars(confp, urlp))
1978 goto jerr1;
1979 if(!a_xtls_config_pairs(confp, urlp))
1980 goto jerr1;
1981 if((fprnt == NULL || urlp->url_cproto == CPROTO_CERTINFO) &&
1982 !a_xtls_load_verifications(ctxp, urlp))
1983 goto jerr1;
1984
1985 /* Done with context setup, create our new per-connection structure */
1986 if(!a_xtls_conf_finish(&confp, FAL0))
1987 goto jleave;
1988 ASSERT(confp == NULL);
1989
1990 if((sop->s_tls = SSL_new(ctxp)) == NULL){
1991 ssl_gen_err(_("SSL_new() failed"));
1992 goto jleave;
1993 }
1994
1995 /* Try establish SNI extension; even though this is a TLS extension the
1996 * protocol isn't checked by OpenSSL once the host name is set, and
1997 * therefore i refrained from changing so much code just to check out
1998 * whether we are using SSLv3, which should become more and more rare */
1999 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2000 if((urlp->url_flags & mx_URL_TLS_MASK) &&
2001 (urlp->url_flags & mx_URL_HOST_IS_NAME)){
2002 if(!SSL_set_tlsext_host_name(sop->s_tls, urlp->url_host.s) &&
2003 (n_poption & n_PO_D_V))
2004 n_err(_("Hostname cannot be used with ServerNameIndication "
2005 "TLS extension: %s\n"),
2006 n_shexp_quote_cp(urlp->url_host.s, FAL0));
2007 }
2008 #endif
2009
2010 SSL_set_fd(sop->s_tls, sop->s_fd);
2011 mx_socket_reset_io_buf(sop);
2012
2013 if(SSL_connect(sop->s_tls) < 0){
2014 ssl_gen_err(_("could not initiate TLS connection"));
2015 goto jerr2;
2016 }
2017
2018 if(fprnt != NULL || urlp->url_cproto == CPROTO_CERTINFO ||
2019 n_tls_verify_level != n_TLS_VERIFY_IGNORE){
2020 boole stay;
2021 X509 *peercert;
2022
2023 if((peercert = a_xtls_SSL_get_peer_certificate(sop->s_tls)) == NIL){
2024 n_err(_("TLS: no certificate from peer: %s\n"), urlp->url_h_p.s);
2025 goto jerr2;
2026 }
2027
2028 stay = FAL0;
2029
2030 if(fprnt == NULL){
2031 if(!a_xtls_check_host(sop, peercert, urlp)){
2032 n_err(_("TLS certificate does not match: %s\n"), urlp->url_h_p.s);
2033 stay = n_tls_verify_decide();
2034 }else{
2035 if(n_poption & n_PO_D_V)
2036 n_err(_("TLS certificate ok\n"));
2037 stay = TRU1;
2038 }
2039 }
2040
2041 if(fprnt != NULL || urlp->url_cproto == CPROTO_CERTINFO ||
2042 (n_poption & n_PO_D_V)){
2043 char fpmdhexbuf[EVP_MAX_MD_SIZE * 3], *cp;
2044 unsigned char fpmdbuf[EVP_MAX_MD_SIZE], *ucp;
2045 unsigned int fpmdlen;
2046
2047 if(!X509_digest(peercert, fprnt_mdp, fpmdbuf, &fpmdlen)){
2048 ssl_gen_err(_("TLS %s fingerprint creation failed"), fprnt_namep);
2049 goto jpeer_leave;
2050 }
2051 ASSERT(fpmdlen <= EVP_MAX_MD_SIZE);
2052
2053 for(cp = fpmdhexbuf, ucp = fpmdbuf; fpmdlen > 0; --fpmdlen){
2054 n_c_to_hex_base16(cp, (char)*ucp++);
2055 cp[2] = ':';
2056 cp += 3;
2057 }
2058 cp[-1] = '\0';
2059
2060 if(n_poption & n_PO_D_V)
2061 n_err(_("TLS %s fingerprint: %s\n"), fprnt_namep, fpmdhexbuf);
2062 if(fprnt != NULL){
2063 if(!(stay = !su_cs_cmp_case(fprnt, fpmdhexbuf))){
2064 n_err(_("TLS fingerprint mismatch: %s\n"
2065 " Expected: %s\n Detected: %s\n"),
2066 urlp->url_h_p.s, fprnt, fpmdhexbuf);
2067 stay = n_tls_verify_decide();
2068 }else if(n_poption & n_PO_D_V)
2069 n_err(_("TLS fingerprint ok\n"));
2070 goto jpeer_leave;
2071 }else if(urlp->url_cproto == CPROTO_CERTINFO){
2072 char *xcp;
2073 long i;
2074 BIO *biop;
2075 a_XTLS_STACKOF(X509) *certs;
2076
2077 sop->s_tls_finger = savestrbuf(fpmdhexbuf,
2078 P2UZ(cp - fpmdhexbuf));
2079
2080 /* For the sake of `tls cert(chain|ificate)', this too */
2081
2082 /*if((certs = SSL_get_peer_cert_chain(sop->s_tls)) != NIL){*/
2083 if((certs = a_xtls_SSL_get_verified_chain(sop->s_tls)) != NIL){
2084 if((biop = BIO_new(BIO_s_mem())) != NIL){
2085 xcp = NIL;
2086 peercert = NIL;
2087
2088 for(i = 0; i < sk_X509_num(certs); ++i){
2089 peercert = sk_X509_value(certs, i);
2090 if(((n_poption & n_PO_D_V) &&
2091 X509_print(biop, peercert) == 0) ||
2092 PEM_write_bio_X509(biop, peercert) == 0){
2093 ssl_gen_err(_("Error storing certificate %d from %s"),
2094 i, urlp->url_h_p.s);
2095 peercert = NIL;
2096 break;
2097 }
2098
2099 if(i == 0){
2100 i = BIO_get_mem_data(biop, &xcp);
2101 if(i > 0)
2102 sop->s_tls_certificate = savestrbuf(xcp, i);
2103 i = 0;
2104 }
2105 }
2106
2107 if(peercert != NIL){
2108 i = BIO_get_mem_data(biop, &xcp);
2109 if(i > 0)
2110 sop->s_tls_certchain = savestrbuf(xcp, i);
2111 }
2112
2113 BIO_free(biop);
2114 }
2115 }
2116 }
2117 }
2118
2119 jpeer_leave:
2120 a_xtls_SSL_get_peer_certificate__FREE(peercert);
2121 if(!stay)
2122 goto jerr2;
2123 }
2124
2125 if(n_poption & n_PO_D_V){
2126 struct a_xtls_protocol const *xpp;
2127 int ver;
2128
2129 ver = SSL_version(sop->s_tls);
2130 for(xpp = &a_xtls_protocols[1] /* [0] == ALL */;; ++xpp)
2131 if(xpp->xp_version == ver || xpp->xp_last){
2132 n_err(_("TLS connection using %s / %s\n"),
2133 (xpp->xp_last ? n_qm : xpp->xp_name),
2134 SSL_get_cipher(sop->s_tls));
2135 break;
2136 }
2137 }
2138
2139 sop->s_use_tls = 1;
2140 jleave:
2141 /* We're fully setup: since we don't reuse the SSL_CTX (pooh) keep it local
2142 * and free it right now -- it is reference counted by sp->s_tls.. */
2143 SSL_CTX_free(ctxp);
2144 j_leave:
2145 NYD_OU;
2146 return (sop->s_tls != NULL);
2147 jerr2:
2148 SSL_free(sop->s_tls);
2149 sop->s_tls = NULL;
2150 jerr1:
2151 if(confp != NULL)
2152 a_xtls_conf_finish(&confp, TRU1);
2153 goto jleave;
2154 }
2155
2156 FL void
ssl_gen_err(char const * fmt,...)2157 ssl_gen_err(char const *fmt, ...)
2158 {
2159 va_list ap;
2160 NYD_IN;
2161
2162 va_start(ap, fmt);
2163 n_verr(fmt, ap);
2164 va_end(ap);
2165
2166 n_err(_(": %s\n"), ERR_error_string(ERR_get_error(), NULL));
2167 NYD_OU;
2168 }
2169
2170 FL int
c_verify(void * vp)2171 c_verify(void *vp)
2172 {
2173 int *msgvec = vp, *ip, ec = 0, rv = 1;
2174 X509_STORE *store = NULL;
2175 char *ca_dir, *ca_file;
2176 NYD_IN;
2177
2178 a_xtls_init();
2179
2180 n_tls_verify_level = n_TLS_VERIFY_STRICT;
2181 if ((store = X509_STORE_new()) == NULL) {
2182 ssl_gen_err(_("Error creating X509 store"));
2183 goto jleave;
2184 }
2185 X509_STORE_set_verify_cb_func(store, &a_xtls_verify_cb);
2186
2187 if((ca_dir = ok_vlook(smime_ca_dir)) != NIL)
2188 ca_dir = fexpand(ca_dir, (FEXP_NOPROTO | FEXP_LOCAL_FILE | FEXP_NSHELL));
2189 if((ca_file = ok_vlook(smime_ca_file)) != NIL)
2190 ca_file = fexpand(ca_file, (FEXP_NOPROTO | FEXP_LOCAL_FILE |
2191 FEXP_NSHELL));
2192
2193 if(ca_file != NIL && a_xtls_X509_STORE_load_file(store, ca_file) != 1){
2194 ssl_gen_err(_("Error loading %s\n"), n_shexp_quote_cp(ca_file, FAL0));
2195 goto jleave;
2196 }
2197
2198 if(ca_dir != NIL && a_xtls_X509_STORE_load_path(store, ca_dir) != 1){
2199 ssl_gen_err(_("Error loading %s\n"), n_shexp_quote_cp(ca_dir, FAL0));
2200 goto jleave;
2201 }
2202
2203 /* C99 */{
2204 boole xv15;
2205
2206 if((xv15 = ok_blook(smime_no_default_ca)))
2207 n_OBSOLETE(_("please use *smime-ca-no-defaults*, "
2208 "not *smime-no-default-ca*"));
2209 if(!ok_blook(smime_ca_no_defaults) && !xv15 &&
2210 X509_STORE_set_default_paths(store) != 1) {
2211 ssl_gen_err(_("Error loading built-in default CA locations\n"));
2212 goto jleave;
2213 }
2214 }
2215
2216 if (load_crls(store, ok_v_smime_crl_file, ok_v_smime_crl_dir) != OKAY)
2217 goto jleave;
2218
2219 a_xtls_ca_flags(store, ok_vlook(smime_ca_flags));
2220
2221 srelax_hold();
2222 for (ip = msgvec; *ip != 0; ++ip) {
2223 struct message *mp = message + *ip - 1;
2224 setdot(mp);
2225 ec |= smime_verify(mp, *ip, NULL, store);
2226 srelax();
2227 }
2228 srelax_rele();
2229
2230 if ((rv = ec) != 0)
2231 n_exit_status |= n_EXIT_ERR;
2232 jleave:
2233 if (store != NULL)
2234 X509_STORE_free(store);
2235 NYD_OU;
2236 return rv;
2237 }
2238
2239 FL FILE *
smime_sign(FILE * ip,char const * addr)2240 smime_sign(FILE *ip, char const *addr)
2241 {
2242 FILE *rv, *sfp, *fp, *bp, *hp;
2243 X509 *cert = NULL;
2244 a_XTLS_STACKOF(X509) *chain = NIL;
2245 EVP_PKEY *pkey = NULL;
2246 BIO *bb, *sb;
2247 PKCS7 *pkcs7;
2248 EVP_MD const *md;
2249 char const *name;
2250 boole bail = FAL0;
2251 NYD_IN;
2252
2253 /* TODO smime_sign(): addr should vanish, it is either *from* aka *sender*
2254 * TODO or what we parsed as From:/Sender: from a template. This latter
2255 * TODO should set *from* / *sender* in a scope, we should use *sender*:
2256 * TODO *sender* should be set to the real *from*! */
2257 ASSERT(addr != NULL);
2258 rv = sfp = fp = bp = hp = NULL;
2259
2260 a_xtls_init();
2261
2262 if ((fp = smime_sign_cert(addr, NIL, 1, NIL, FAL0)) == NIL)
2263 goto jleave;
2264
2265 if ((pkey = PEM_read_PrivateKey(fp, NULL, &ssl_password_cb,
2266 savecat(addr, ".smime-cert-key"))) == NULL) {
2267 ssl_gen_err(_("Error reading private key from"));
2268 goto jleave;
2269 }
2270
2271 rewind(fp);
2272 if ((cert = PEM_read_X509(fp, NULL, &ssl_password_cb,
2273 savecat(addr, ".smime-cert-cert"))) == NULL) {
2274 ssl_gen_err(_("Error reading signer certificate from"));
2275 goto jleave;
2276 }
2277 mx_fs_close(fp);
2278 fp = NULL;
2279
2280 if ((name = _smime_sign_include_certs(addr)) != NULL &&
2281 !_smime_sign_include_chain_creat(&chain, name,
2282 savecat(addr, ".smime-include-certs")))
2283 goto jleave;
2284
2285 name = NULL;
2286 if ((md = a_xtls_smime_sign_digest(addr, &name)) == NULL)
2287 goto jleave;
2288
2289 if((sfp = mx_fs_tmp_open("smimesign", (mx_FS_O_RDWR | mx_FS_O_UNLINK |
2290 mx_FS_O_REGISTER), NIL)) == NIL){
2291 n_perr(_("tempfile"), 0);
2292 goto jleave;
2293 }
2294
2295 rewind(ip);
2296 if(!mx_smime_split(ip, &hp, &bp, -1, FAL0))
2297 goto jleave;
2298
2299 sb = NULL;
2300 pkcs7 = NULL;
2301
2302 if ((bb = BIO_new_fp(bp, BIO_NOCLOSE)) == NULL ||
2303 (sb = BIO_new_fp(sfp, BIO_NOCLOSE)) == NULL) {
2304 ssl_gen_err(_("Error creating BIO signing objects"));
2305 bail = TRU1;
2306 goto jerr;
2307 }
2308
2309 #ifdef PKCS7_PARTIAL
2310 if((pkcs7 = PKCS7_sign(NULL, NULL, chain, bb,
2311 (PKCS7_DETACHED | PKCS7_PARTIAL))) == NIL){
2312 ssl_gen_err(_("Error creating the PKCS#7 signing object"));
2313 bail = TRU1;
2314 goto jerr;
2315 }
2316 if(PKCS7_sign_add_signer(pkcs7, cert, pkey, md,
2317 (PKCS7_DETACHED | PKCS7_PARTIAL)) == NIL){
2318 ssl_gen_err(_("Error setting PKCS#7 signing object signer"));
2319 bail = TRU1;
2320 goto jerr;
2321 }
2322 if(!PKCS7_final(pkcs7, bb, (PKCS7_DETACHED | PKCS7_PARTIAL))){
2323 ssl_gen_err(_("Error finalizing the PKCS#7 signing object"));
2324 bail = TRU1;
2325 goto jerr;
2326 }
2327 #else
2328 if((pkcs7 = PKCS7_sign(cert, pkey, chain, bb, PKCS7_DETACHED)) == NIL){
2329 ssl_gen_err(_("Error creating the PKCS#7 signing object"));
2330 bail = TRU1;
2331 goto jerr;
2332 }
2333 #endif /* !PKCS7_PARTIAL */
2334
2335 if (PEM_write_bio_PKCS7(sb, pkcs7) == 0) {
2336 ssl_gen_err(_("Error writing signed S/MIME data"));
2337 bail = TRU1;
2338 /*goto jerr*/
2339 }
2340 jerr:
2341 if (pkcs7 != NULL)
2342 PKCS7_free(pkcs7);
2343 if (sb != NULL)
2344 BIO_free(sb);
2345 if (bb != NULL)
2346 BIO_free(bb);
2347 if (!bail) {
2348 rewind(bp);
2349 fflush_rewind(sfp);
2350 rv = smime_sign_assemble(hp, bp, sfp, name);
2351 hp = bp = sfp = NULL;
2352 }
2353
2354 jleave:
2355 if (chain != NULL)
2356 sk_X509_pop_free(chain, X509_free);
2357 if (cert != NULL)
2358 X509_free(cert);
2359 if (pkey != NULL)
2360 EVP_PKEY_free(pkey);
2361 if(fp != NIL)
2362 mx_fs_close(fp);
2363 if(hp != NIL)
2364 mx_fs_close(hp);
2365 if(bp != NIL)
2366 mx_fs_close(bp);
2367 if(sfp != NIL)
2368 mx_fs_close(sfp);
2369 NYD_OU;
2370 return rv;
2371 }
2372
2373 FL FILE *
smime_encrypt(FILE * ip,char const * xcertfile,char const * to)2374 smime_encrypt(FILE *ip, char const *xcertfile, char const *to)
2375 {
2376 FILE *rv, *yp, *fp, *bp, *hp;
2377 X509 *cert;
2378 PKCS7 *pkcs7;
2379 BIO *bb, *yb;
2380 a_XTLS_STACKOF(X509) *certs;
2381 EVP_CIPHER const *cipher;
2382 char *certfile;
2383 boole bail;
2384 NYD_IN;
2385
2386 bail = FAL0;
2387 rv = yp = fp = bp = hp = NULL;
2388
2389 if((certfile = fexpand(xcertfile, (FEXP_NOPROTO | FEXP_LOCAL_FILE |
2390 FEXP_NSHELL))) == NIL)
2391 goto jleave;
2392
2393 a_xtls_init();
2394
2395 if ((cipher = _smime_cipher(to)) == NULL)
2396 goto jleave;
2397
2398 if((fp = mx_fs_open(certfile, "r")) == NIL){
2399 n_perr(certfile, 0);
2400 goto jleave;
2401 }
2402 if ((cert = PEM_read_X509(fp, NULL, &ssl_password_cb, NULL)) == NULL) {
2403 ssl_gen_err(_("Error reading encryption certificate from %s"),
2404 n_shexp_quote_cp(certfile, FAL0));
2405 bail = TRU1;
2406 }
2407 if (bail)
2408 goto jleave;
2409 mx_fs_close(fp);
2410 fp = NULL;
2411 bail = FAL0;
2412
2413 certs = sk_X509_new_null();
2414 sk_X509_push(certs, cert);
2415
2416 if((yp = mx_fs_tmp_open("smimeenc", (mx_FS_O_RDWR | mx_FS_O_UNLINK |
2417 mx_FS_O_REGISTER), NIL)) == NIL){
2418 n_perr(_("tempfile"), 0);
2419 goto jerr1;
2420 }
2421
2422 rewind(ip);
2423 if(!mx_smime_split(ip, &hp, &bp, -1, FAL0))
2424 goto jerr1;
2425
2426 yb = NULL;
2427 if ((bb = BIO_new_fp(bp, BIO_NOCLOSE)) == NULL ||
2428 (yb = BIO_new_fp(yp, BIO_NOCLOSE)) == NULL) {
2429 ssl_gen_err(_("Error creating BIO encryption objects"));
2430 bail = TRU1;
2431 goto jerr2;
2432 }
2433 if ((pkcs7 = PKCS7_encrypt(certs, bb, cipher, 0)) == NULL) {
2434 ssl_gen_err(_("Error creating the PKCS#7 encryption object"));
2435 bail = TRU1;
2436 goto jerr2;
2437 }
2438 if (PEM_write_bio_PKCS7(yb, pkcs7) == 0) {
2439 ssl_gen_err(_("Error writing encrypted S/MIME data"));
2440 bail = TRU1;
2441 /* goto jerr2 */
2442 }
2443 PKCS7_free(pkcs7);
2444
2445 jerr2:
2446 if(bb != NIL)
2447 BIO_free(bb);
2448 if(yb != NIL)
2449 BIO_free(yb);
2450 mx_fs_close(bp);
2451 bp = NIL;
2452 if(!bail){
2453 fflush_rewind(yp);
2454 rv = smime_encrypt_assemble(hp, yp);
2455 hp = yp = NIL;
2456 }
2457 jerr1:
2458 sk_X509_pop_free(certs, X509_free);
2459
2460 jleave:
2461 if(yp != NIL)
2462 mx_fs_close(yp);
2463 if(fp != NIL)
2464 mx_fs_close(fp);
2465 if(bp != NIL)
2466 mx_fs_close(bp);
2467 if(hp != NIL)
2468 mx_fs_close(hp);
2469 NYD_OU;
2470 return rv;
2471 }
2472
2473 FL struct message *
smime_decrypt(struct message * m,char const * to,char const * cc,boole is_a_verify_call)2474 smime_decrypt(struct message *m, char const *to, char const *cc,
2475 boole is_a_verify_call)
2476 {
2477 char const *myaddr;
2478 long size;
2479 struct message *rv;
2480 FILE *bp, *hp, *op;
2481 PKCS7 *pkcs7;
2482 BIO *ob, *bb, *pb;
2483 X509 *cert;
2484 EVP_PKEY *pkey;
2485 FILE *yp;
2486 NYD_IN;
2487
2488 pkey = NULL;
2489 cert = NULL;
2490 ob = bb = pb = NULL;
2491 pkcs7 = NULL;
2492 bp = hp = op = NULL;
2493 rv = NULL;
2494 size = m->m_size;
2495
2496 if((yp = setinput(&mb, m, NEED_BODY)) == NULL)
2497 goto jleave;
2498
2499 a_xtls_init();
2500
2501 if((op = smime_sign_cert(to, cc, 0, &myaddr, TRU1)) != NULL){
2502 pkey = PEM_read_PrivateKey(op, NULL, &ssl_password_cb,
2503 savecat(myaddr, ".smime-cert-key"));
2504 if(pkey == NULL){
2505 ssl_gen_err(_("Error reading private key"));
2506 goto jleave;
2507 }
2508
2509 rewind(op);
2510 if((cert = PEM_read_X509(op, NULL, &ssl_password_cb,
2511 savecat(myaddr, ".smime-cert-cert"))) == NULL){
2512 ssl_gen_err(_("Error reading decryption certificate"));
2513 goto jleave;
2514 }
2515
2516 mx_fs_close(op);
2517 op = NULL;
2518 }
2519
2520 if((op = mx_fs_tmp_open("smimed", (mx_FS_O_RDWR | mx_FS_O_UNLINK |
2521 mx_FS_O_REGISTER), NIL)) == NIL){
2522 n_perr(_("tempfile"), 0);
2523 goto jleave;
2524 }
2525
2526 if(!mx_smime_split(yp, &hp, &bp, size, TRU1))
2527 goto jleave;
2528
2529 if((ob = BIO_new_fp(op, BIO_NOCLOSE)) == NULL ||
2530 (bb = BIO_new_fp(bp, BIO_NOCLOSE)) == NULL){
2531 ssl_gen_err(_("Error creating BIO decryption objects"));
2532 goto jleave;
2533 }
2534
2535 if((pkcs7 = SMIME_read_PKCS7(bb, &pb)) == NULL){
2536 ssl_gen_err(_("Error reading PKCS#7 object"));
2537 goto jleave;
2538 }
2539
2540 if(PKCS7_type_is_signed(pkcs7)){
2541 if(!is_a_verify_call){
2542 setinput(&mb, m, NEED_BODY);
2543 rv = (struct message*)-1;
2544 goto jleave;
2545 }
2546 if(PKCS7_verify(pkcs7, NULL, NULL, NULL, ob,
2547 PKCS7_NOVERIFY | PKCS7_NOSIGS) != 1)
2548 goto jerr;
2549 fseek(hp, 0L, SEEK_END);
2550 fprintf(hp, "X-Encryption-Cipher: none\n");
2551 fflush_rewind(hp);
2552 }else if(pkey == NULL){
2553 n_err(_("No appropriate private key found\n"));
2554 goto jleave;
2555 }else if(cert == NULL){
2556 n_err(_("No appropriate certificate found\n"));
2557 goto jleave;
2558 }else if(PKCS7_decrypt(pkcs7, pkey, cert, ob, 0) != 1){
2559 jerr:
2560 ssl_gen_err(_("Error decrypting PKCS#7 object"));
2561 goto jleave;
2562 }
2563 fflush_rewind(op);
2564
2565 mx_fs_close(bp);
2566 bp = NIL;
2567
2568 if((rv = mx_smime_decrypt_assemble(m, hp, op)) == NIL)
2569 n_err(_("I/O error while creating decrypted message\n"));
2570 jleave:
2571 if(op != NIL)
2572 mx_fs_close(op);
2573 if(hp != NIL)
2574 mx_fs_close(hp);
2575 if(bp != NIL)
2576 mx_fs_close(bp);
2577 if(bb != NIL)
2578 BIO_free(bb);
2579 if(ob != NIL)
2580 BIO_free(ob);
2581 if(pkcs7 != NIL)
2582 PKCS7_free(pkcs7);
2583 if(cert != NIL)
2584 X509_free(cert);
2585 if(pkey != NIL)
2586 EVP_PKEY_free(pkey);
2587
2588 NYD_OU;
2589 return rv;
2590 }
2591
2592 FL enum okay
smime_certsave(struct message * m,int n,FILE * op)2593 smime_certsave(struct message *m, int n, FILE *op)
2594 {
2595 struct message *x;
2596 char *to, *cc, *cnttype;
2597 int c, i;
2598 FILE *fp, *ip;
2599 off_t size;
2600 BIO *fb, *pb;
2601 PKCS7 *pkcs7;
2602 a_XTLS_STACKOF(X509) *certs, *chain = NIL;
2603 X509 *cert;
2604 enum okay rv = STOP;
2605 NYD_IN;
2606
2607 pkcs7 = NULL;
2608
2609 a_xtls_msgno = (uz)n;
2610 jloop:
2611 to = hfield1("to", m);
2612 cc = hfield1("cc", m);
2613 cnttype = hfield1("content-type", m);
2614
2615 if ((ip = setinput(&mb, m, NEED_BODY)) == NULL)
2616 goto jleave;
2617
2618 #undef _X
2619 #undef _Y
2620 #define _X (sizeof("application/") -1)
2621 #define _Y(X) X, sizeof(X) -1
2622 if (cnttype && su_cs_starts_with_case(cnttype, "application/") &&
2623 (!su_cs_cmp_case_n(cnttype + _X, _Y("pkcs7-mime")) ||
2624 !su_cs_cmp_case_n(cnttype + _X, _Y("x-pkcs7-mime")))) {
2625 #undef _Y
2626 #undef _X
2627 if ((x = smime_decrypt(m, to, cc, TRU1)) == NULL)
2628 goto jleave;
2629 if (x != (struct message*)-1) {
2630 m = x;
2631 goto jloop;
2632 }
2633 }
2634 size = m->m_size;
2635
2636 if((fp = mx_fs_tmp_open("smimecert", (mx_FS_O_RDWR | mx_FS_O_UNLINK |
2637 mx_FS_O_REGISTER), NIL)) == NIL){
2638 n_perr(_("tempfile"), 0);
2639 goto jleave;
2640 }
2641
2642 while (size-- > 0) {
2643 c = getc(ip);
2644 putc(c, fp);
2645 }
2646 fflush(fp);
2647
2648 rewind(fp);
2649 if ((fb = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
2650 ssl_gen_err("Error creating BIO object for message %d", n);
2651 mx_fs_close(fp);
2652 goto jleave;
2653 }
2654
2655 if ((pkcs7 = SMIME_read_PKCS7(fb, &pb)) == NULL) {
2656 ssl_gen_err(_("Error reading PKCS#7 object for message %d"), n);
2657 BIO_free(fb);
2658 mx_fs_close(fp);
2659 goto jleave;
2660 }
2661 BIO_free(fb);
2662 mx_fs_close(fp);
2663
2664 certs = PKCS7_get0_signers(pkcs7, chain, 0);
2665 if (certs == NULL) {
2666 n_err(_("No certificates found in message %d\n"), n);
2667 goto jleave;
2668 }
2669
2670 for (i = 0; i < sk_X509_num(certs); ++i) {
2671 cert = sk_X509_value(certs, i);
2672 if (X509_print_fp(op, cert) == 0 || PEM_write_X509(op, cert) == 0) {
2673 ssl_gen_err(_("Error writing certificate %d from message %d"),
2674 i, n);
2675 goto jleave;
2676 }
2677 }
2678 rv = OKAY;
2679 jleave:
2680 if(pkcs7 != NULL)
2681 PKCS7_free(pkcs7);
2682 NYD_OU;
2683 return rv;
2684 }
2685
2686 #include "su/code-ou.h"
2687 #endif /* mx_HAVE_XTLS */
2688 /* s-it-mode */
2689