"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.19/src/mx/xtls.c" (26 Apr 2020, 75527 Bytes) of package /linux/misc/s-nail-14.9.19.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "xtls.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 14.9.18_vs_14.9.19.

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