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