"Fossies" - the Fresh Open Source Software Archive

Member "s-nail-14.9.22/src/mx/xtls.c" (24 Feb 2021, 76631 Bytes) of package /linux/misc/s-nail-14.9.22.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.21_vs_14.9.22.

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