1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ OpenSSL functions. TODO this needs an overhaul -- there _are_ stack leaks!?
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 - 2015 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
9 * Gunnar Ritter. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by Gunnar Ritter
22 * and his contributors.
23 * 4. Neither the name of Gunnar Ritter nor the names of his contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 #define n_FILE openssl
42 #ifndef HAVE_AMALGAMATION
48 #include <sys/socket.h>
50 #include <openssl/crypto.h>
51 #include <openssl/err.h>
52 #include <openssl/evp.h>
53 #include <openssl/pem.h>
54 #include <openssl/rand.h>
55 #include <openssl/ssl.h>
56 #include <openssl/x509v3.h>
57 #include <openssl/x509.h>
59 #ifdef HAVE_OPENSSL_CONFIG
60 # include <openssl/conf.h>
63 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
68 * OpenSSL client implementation according to: John Viega, Matt Messier,
69 * Pravir Chandra: Network Security with OpenSSL. Sebastopol, CA 2002.
72 /* Update manual on changes (for all those)! */
73 #define SSL_DISABLED_PROTOCOLS "-SSLv2"
75 #ifndef HAVE_OPENSSL_CONF_CTX /* TODO obsolete the fallback */
76 # ifndef SSL_OP_NO_SSLv2
77 # define SSL_OP_NO_SSLv2 0
79 # ifndef SSL_OP_NO_SSLv3
80 # define SSL_OP_NO_SSLv3 0
82 # ifndef SSL_OP_NO_TLSv1
83 # define SSL_OP_NO_TLSv1 0
85 # ifndef SSL_OP_NO_TLSv1_1
86 # define SSL_OP_NO_TLSv1_1 0
88 # ifndef SSL_OP_NO_TLSv1_2
89 # define SSL_OP_NO_TLSv1_2 0
92 /* SSL_CONF_CTX and _OP_NO_SSL_MASK were both introduced with 1.0.2!?! */
93 # ifndef SSL_OP_NO_SSL_MASK
94 # define SSL_OP_NO_SSL_MASK \
95 (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |\
96 SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2)
100 #if HAVE_OPENSSL < 10100
101 # define _SSL_CLIENT_METHOD() SSLv23_client_method()
103 # define _SSL_CLIENT_METHOD() TLS_client_method()
106 #ifdef HAVE_OPENSSL_STACK_OF
107 # define _STACKOF(X) STACK_OF(X)
109 # define _STACKOF(X) /*X*/STACK
119 SS_VERIFY_ERROR
= 1<<7
122 /* We go for the OpenSSL v1.0.2+ SSL_CONF_CTX if available even if that means
123 * that the library does internally what we'd otherwise do ourselfs.
124 * Eventually we can drop the direct use cases */
133 struct ssl_method
{ /* TODO obsolete */
134 char const sm_name
[8];
135 char const sm_map
[16];
138 #ifndef HAVE_OPENSSL_CONF_CTX /* TODO obsolete the fallback */
139 struct ssl_protocol
{
145 struct smime_cipher
{
146 char const sc_name
[8];
147 EVP_CIPHER
const *(*sc_fun
)(void);
150 struct smime_digest
{
151 char const sd_name
[8];
152 EVP_MD
const *(*sd_fun
)(void);
155 /* Supported SSL/TLS methods: update manual on change! */
157 static struct ssl_method
const _ssl_methods
[] = { /* TODO obsolete */
158 {"auto", "ALL,-SSLv2"},
159 {"ssl3", "-ALL,SSLv3"},
160 {"tls1", "-ALL,TLSv1"},
161 {"tls1.1", "-ALL,TLSv1.1"},
162 {"tls1.2", "-ALL,TLSv1.2"}
165 /* Update manual on change! */
166 #ifndef HAVE_OPENSSL_CONF_CTX /* TODO obsolete the fallback */
167 static struct ssl_protocol
const _ssl_protocols
[] = {
168 {"ALL", SSL_OP_NO_SSL_MASK
},
169 {"TLSv1.2", SSL_OP_NO_TLSv1_2
},
170 {"TLSv1.1", SSL_OP_NO_TLSv1_1
},
171 {"TLSv1", SSL_OP_NO_TLSv1
},
172 {"SSLv3", SSL_OP_NO_SSLv3
},
177 /* Supported S/MIME cipher algorithms */
178 static struct smime_cipher
const _smime_ciphers
[] = { /* Manual!! */
179 #ifndef OPENSSL_NO_AES
180 # define _SMIME_DEFAULT_CIPHER EVP_aes_128_cbc /* According to RFC 5751 */
181 {"aes128", &EVP_aes_128_cbc
},
182 {"aes256", &EVP_aes_256_cbc
},
183 {"aes192", &EVP_aes_192_cbc
},
185 #ifndef OPENSSL_NO_DES
186 # ifndef _SMIME_DEFAULT_CIPHER
187 # define _SMIME_DEFAULT_CIPHER EVP_des_ede3_cbc
189 {"des3", &EVP_des_ede3_cbc
},
190 {"des", &EVP_des_cbc
},
193 #ifndef _SMIME_DEFAULT_CIPHER
194 # error Your OpenSSL library does not include the necessary
195 # error cipher algorithms that are required to support S/MIME
198 #ifndef OPENSSL_NO_AES
199 static struct smime_cipher
const _smime_ciphers_obs
[] = { /* TODO obsolete */
200 {"aes-128", &EVP_aes_128_cbc
},
201 {"aes-256", &EVP_aes_256_cbc
},
202 {"aes-192", &EVP_aes_192_cbc
}
206 /* Supported S/MIME message digest algorithms */
207 static struct smime_digest
const _smime_digests
[] = { /* Manual!! */
208 #define _SMIME_DEFAULT_DIGEST EVP_sha1 /* According to RFC 5751 */
209 #define _SMIME_DEFAULT_DIGEST_S "sha1"
211 {"sha256", &EVP_sha256
},
212 {"sha512", &EVP_sha512
},
213 {"sha384", &EVP_sha384
},
214 {"sha224", &EVP_sha224
},
215 #ifndef OPENSSL_NO_MD5
220 static enum ssl_state _ssl_state
;
221 static size_t _ssl_msgno
;
223 static int _ssl_rand_init(void);
224 static void _ssl_init(void);
225 #if defined HAVE_DEVEL && defined HAVE_OPENSSL_MEMHOOKS && defined HAVE_DEBUG
226 static void _ssl_free(void *vp
);
228 #ifdef HAVE_SSL_ALL_ALGORITHMS
229 static void _ssl_load_algos(void);
231 #if defined HAVE_OPENSSL_CONFIG || defined HAVE_SSL_ALL_ALGORITHMS
232 static void _ssl_atexit(void);
235 static bool_t
_ssl_parse_asn1_time(ASN1_TIME
*atp
,
236 char *bdat
, size_t blen
);
237 static int _ssl_verify_cb(int success
, X509_STORE_CTX
*store
);
239 /* SSL_CTX configuration */
240 static void * _ssl_conf_setup(SSL_CTX
*ctxp
);
241 static bool_t
_ssl_conf(void *confp
, enum ssl_conf_type sct
,
243 static bool_t
_ssl_conf_finish(void **confp
, bool_t error
);
245 static bool_t
_ssl_load_verifications(SSL_CTX
*ctxp
);
247 static enum okay
ssl_check_host(struct sock
*sp
, struct url
const *urlp
);
249 static int smime_verify(struct message
*m
, int n
, _STACKOF(X509
) *chain
,
251 static EVP_CIPHER
const * _smime_cipher(char const *name
);
252 static int ssl_password_cb(char *buf
, int size
, int rwflag
,
254 static FILE * smime_sign_cert(char const *xname
, char const *xname2
,
256 static char * _smime_sign_include_certs(char const *name
);
257 static bool_t
_smime_sign_include_chain_creat(_STACKOF(X509
) **chain
,
259 static EVP_MD
const * _smime_sign_digest(char const *name
,
260 char const **digname
);
261 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
262 static enum okay
load_crl1(X509_STORE
*store
, char const *name
);
264 static enum okay
load_crls(X509_STORE
*store
, enum okeys fok
, enum okeys dok
);
273 #ifdef HAVE_OPENSSL_RAND_EGD
274 if ((cp
= ok_vlook(ssl_rand_egd
)) != NULL
) {
275 if ((x
= file_expand(cp
)) == NULL
|| RAND_egd(cp
= x
) == -1)
276 n_err(_("Entropy daemon at \"%s\" not available\n"), cp
);
281 if ((cp
= ok_vlook(ssl_rand_file
)) != NULL
) {
282 if ((x
= file_expand(cp
)) == NULL
|| RAND_load_file(cp
= x
, 1024) == -1)
283 n_err(_("Entropy file at \"%s\" not available\n"), cp
);
287 if (!stat(cp
, &st
) && S_ISREG(st
.st_mode
) && !access(cp
, W_OK
)) {
288 if (RAND_write_file(cp
) == -1) {
289 n_err(_("Writing entropy data to \"%s\" failed\n"), cp
);
302 #ifdef HAVE_OPENSSL_CONFIG
307 if (!(_ssl_state
& SS_INIT
)) {
308 #if defined HAVE_DEVEL && defined HAVE_OPENSSL_MEMHOOKS
310 CRYPTO_set_mem_ex_functions(&smalloc
, &srealloc
, &_ssl_free
);
312 CRYPTO_set_mem_functions(&smalloc
, &srealloc
, &free
);
316 SSL_load_error_strings();
317 _ssl_state
|= SS_INIT
;
320 /* Load openssl.cnf or whatever was given in *ssl-config-file* */
321 #ifdef HAVE_OPENSSL_CONFIG
322 if (!(_ssl_state
& SS_CONF_LOAD
) &&
323 (cp
= ok_vlook(ssl_config_file
)) != NULL
) {
324 ul_i flags
= CONF_MFLAGS_IGNORE_MISSING_FILE
;
330 if (CONF_modules_load_file(cp
, uagent
, flags
) == 1) {
331 _ssl_state
|= SS_CONF_LOAD
;
332 if (!(_ssl_state
& SS_EXIT_HDL
)) {
333 _ssl_state
|= SS_EXIT_HDL
;
334 atexit(&_ssl_atexit
); /* TODO generic program-wide event mech. */
337 ssl_gen_err(_("Ignoring CONF_modules_load_file() load error"));
341 if (!(_ssl_state
& SS_RAND_INIT
) && _ssl_rand_init())
342 _ssl_state
|= SS_RAND_INIT
;
346 #if defined HAVE_DEVEL && defined HAVE_OPENSSL_MEMHOOKS && defined HAVE_DEBUG
357 #ifdef HAVE_SSL_ALL_ALGORITHMS
359 _ssl_load_algos(void)
362 if (!(_ssl_state
& SS_ALGO_LOAD
)) {
363 _ssl_state
|= SS_ALGO_LOAD
;
364 OpenSSL_add_all_algorithms();
366 if (!(_ssl_state
& SS_EXIT_HDL
)) {
367 _ssl_state
|= SS_EXIT_HDL
;
368 atexit(&_ssl_atexit
); /* TODO generic program-wide event mech. */
375 #if defined HAVE_OPENSSL_CONFIG || defined HAVE_SSL_ALL_ALGORITHMS
380 # ifdef HAVE_SSL_ALL_ALGORITHMS
381 if (_ssl_state
& SS_ALGO_LOAD
)
384 # ifdef HAVE_OPENSSL_CONFIG
385 if (_ssl_state
& SS_CONF_LOAD
)
393 _ssl_parse_asn1_time(ASN1_TIME
*atp
, char *bdat
, size_t blen
)
400 mbp
= BIO_new(BIO_s_mem());
402 if (ASN1_TIME_print(mbp
, atp
) && (l
= BIO_get_mem_data(mbp
, &mcp
)) > 0)
403 snprintf(bdat
, blen
, "%.*s", (int)l
, mcp
);
405 snprintf(bdat
, blen
, _("Bogus certificate date: %.*s"),
406 /*is (int)*/atp
->length
, (char const*)atp
->data
);
412 return (mcp
!= NULL
);
416 _ssl_verify_cb(int success
, X509_STORE_CTX
*store
)
423 if (success
&& !(options
& OPT_VERB
))
426 if (_ssl_msgno
!= 0) {
427 n_err(_("Message %lu:\n"), (ul_i
)_ssl_msgno
);
430 n_err(_(" Certificate depth %d %s\n"),
431 X509_STORE_CTX_get_error_depth(store
), (success
? "" : _("ERROR")));
433 if ((cert
= X509_STORE_CTX_get_current_cert(store
)) != NULL
) {
434 X509_NAME_oneline(X509_get_subject_name(cert
), data
, sizeof data
);
435 n_err(_(" subject = %s\n"), data
);
437 _ssl_parse_asn1_time(X509_get_notBefore(cert
), data
, sizeof data
);
438 n_err(_(" notBefore = %s\n"), data
);
440 _ssl_parse_asn1_time(X509_get_notAfter(cert
), data
, sizeof data
);
441 n_err(_(" notAfter = %s\n"), data
);
443 X509_NAME_oneline(X509_get_issuer_name(cert
), data
, sizeof data
);
444 n_err(_(" issuer = %s\n"), data
);
448 int err
= X509_STORE_CTX_get_error(store
);
450 n_err(_(" err %i: %s\n"), err
, X509_verify_cert_error_string(err
));
451 _ssl_state
|= SS_VERIFY_ERROR
;
454 if (!success
&& ssl_verify_decide() != OKAY
)
461 #ifdef HAVE_OPENSSL_CONF_CTX
463 _ssl_conf_setup(SSL_CTX
*ctxp
)
468 if ((sccp
= SSL_CONF_CTX_new()) != NULL
) {
469 SSL_CONF_CTX_set_flags(sccp
,
470 SSL_CONF_FLAG_FILE
| SSL_CONF_FLAG_CLIENT
|
471 SSL_CONF_FLAG_CERTIFICATE
| SSL_CONF_FLAG_SHOW_ERRORS
);
473 SSL_CONF_CTX_set_ssl_ctx(sccp
, ctxp
);
475 ssl_gen_err(_("SSL_CONF_CTX_new() failed"));
482 _ssl_conf(void *confp
, enum ssl_conf_type sct
, char const *value
)
486 SSL_CONF_CTX
*sccp
= (SSL_CONF_CTX
*)confp
;
490 case SCT_CERTIFICATE
:
492 rv
= SSL_CONF_cmd(sccp
, "Certificate", value
);
494 case SCT_CIPHER_STRING
:
495 cmsg
= "ssl-cipher-list";
496 rv
= SSL_CONF_cmd(sccp
, "CipherString", value
);
498 case SCT_PRIVATE_KEY
:
500 rv
= SSL_CONF_cmd(sccp
, "PrivateKey", value
);
504 cmsg
= "ssl-options";
505 rv
= SSL_CONF_cmd(sccp
, "Options", "Bugs");
508 cmsg
= "ssl-protocol";
509 rv
= SSL_CONF_cmd(sccp
, "Protocol", value
);
517 ssl_gen_err(_("SSL_CONF_CTX_cmd() failed for *%s*"), cmsg
);
519 n_err(_("%s: *%s* implementation error, please report this\n"),
529 _ssl_conf_finish(void **confp
, bool_t error
)
531 SSL_CONF_CTX
**sccp
= (SSL_CONF_CTX
**)confp
;
536 rv
= (SSL_CONF_CTX_finish(*sccp
) != 0);
538 SSL_CONF_CTX_free(*sccp
);
545 #else /* HAVE_OPENSSL_CONF_CTX */
547 _ssl_conf_setup(SSL_CTX
* ctxp
)
553 _ssl_conf(void *confp
, enum ssl_conf_type sct
, char const *value
)
555 SSL_CTX
*ctxp
= (SSL_CTX
*)confp
;
559 case SCT_CERTIFICATE
:
560 if (SSL_CTX_use_certificate_chain_file(ctxp
, value
) != 1) {
561 ssl_gen_err(_("Can't load certificate from file \"%s\"\n"), value
);
565 case SCT_CIPHER_STRING
:
566 if (SSL_CTX_set_cipher_list(ctxp
, value
) != 1) {
567 ssl_gen_err(_("Invalid cipher string: \"%s\"\n"), value
);
571 case SCT_PRIVATE_KEY
:
572 if (SSL_CTX_use_PrivateKey_file(ctxp
, value
, SSL_FILETYPE_PEM
) != 1) {
573 ssl_gen_err(_("Can't load private key from file \"%s\"\n"), value
);
578 /* "Options"="Bugs" TODO *ssl-options* */
579 SSL_CTX_set_options(ctxp
, SSL_OP_ALL
);
582 char *iolist
, *cp
, addin
;
587 for (iolist
= cp
= savestr(value
);
588 (cp
= n_strsep(&iolist
, ',', FAL0
)) != NULL
;) {
590 n_err(_("*ssl-protocol*: empty arguments are not supported\n"));
596 case '-': addin
= FAL0
; /* FALLTHRU */
597 case '+': ++cp
; /* FALLTHRU */
602 if (!asccasecmp(cp
, _ssl_protocols
[i
].sp_name
)) {
603 /* We need to inverse the meaning of the _NO_s */
605 opts
|= _ssl_protocols
[i
].sp_flag
;
607 opts
&= ~_ssl_protocols
[i
].sp_flag
;
610 if (++i
< NELEM(_ssl_protocols
))
612 n_err(_("*ssl-protocol*: unsupported value \"%s\"\n"), cp
);
617 SSL_CTX_set_options(ctxp
, opts
);
623 return (confp
!= NULL
);
627 _ssl_conf_finish(void **confp
, bool_t error
)
633 #endif /* !HAVE_OPENSSL_CONF_CTX */
636 _ssl_load_verifications(SSL_CTX
*ctxp
)
638 char *ca_dir
, *ca_file
;
643 if (ssl_verify_level
== SSL_VERIFY_IGNORE
) {
648 if ((ca_dir
= ok_vlook(ssl_ca_dir
)) != NULL
)
649 ca_dir
= file_expand(ca_dir
);
650 if ((ca_file
= ok_vlook(ssl_ca_file
)) != NULL
)
651 ca_file
= file_expand(ca_file
);
653 if ((ca_dir
!= NULL
|| ca_file
!= NULL
) &&
654 SSL_CTX_load_verify_locations(ctxp
, ca_file
, ca_dir
) != 1) {
655 char const *m1
, *m2
, *m3
;
657 if (ca_dir
!= NULL
) {
659 m2
= (ca_file
!= NULL
) ? _(" or ") : "";
662 m3
= (ca_file
!= NULL
) ? ca_file
: "";
663 ssl_gen_err(_("Error loading %s%s%s\n"), m1
, m2
, m3
);
667 if (!ok_blook(ssl_no_default_ca
) &&
668 SSL_CTX_set_default_verify_paths(ctxp
) != 1) {
669 ssl_gen_err(_("Error loading default CA locations\n"));
673 _ssl_state
&= ~SS_VERIFY_ERROR
;
675 SSL_CTX_set_verify(ctxp
, SSL_VERIFY_PEER
, &_ssl_verify_cb
);
676 store
= SSL_CTX_get_cert_store(ctxp
);
677 load_crls(store
, ok_v_ssl_crl_file
, ok_v_ssl_crl_dir
);
686 ssl_check_host(struct sock
*sp
, struct url
const *urlp
)
690 _STACKOF(GENERAL_NAME
) *gens
;
696 if ((cert
= SSL_get_peer_certificate(sp
->s_ssl
)) == NULL
) {
697 n_err(_("No certificate from \"%s\"\n"), urlp
->url_h_p
.s
);
701 gens
= X509_get_ext_d2i(cert
, NID_subject_alt_name
, NULL
, NULL
);
705 for (i
= 0; i
< sk_GENERAL_NAME_num(gens
); ++i
) {
706 gen
= sk_GENERAL_NAME_value(gens
, i
);
707 if (gen
->type
== GEN_DNS
) {
708 if (options
& OPT_VERB
)
709 n_err(_("Comparing subject_alt_name: need<%s> is<%s>\n"),
710 urlp
->url_host
.s
, (char*)gen
->d
.ia5
->data
);
711 rv
= rfc2595_hostname_match(urlp
->url_host
.s
,
712 (char*)gen
->d
.ia5
->data
);
719 if ((subj
= X509_get_subject_name(cert
)) != NULL
&&
720 X509_NAME_get_text_by_NID(subj
, NID_commonName
, data
, sizeof data
)
722 data
[sizeof data
- 1] = '\0';
723 if (options
& OPT_VERB
)
724 n_err(_("Comparing commonName: need<%s> is<%s>\n"),
725 urlp
->url_host
.s
, data
);
726 rv
= rfc2595_hostname_match(urlp
->url_host
.s
, data
);
737 smime_verify(struct message
*m
, int n
, _STACKOF(X509
) *chain
, X509_STORE
*store
)
739 char data
[LINESIZE
], *sender
, *to
, *cc
, *cnttype
;
746 _STACKOF(X509
) *certs
;
747 _STACKOF(GENERAL_NAME
) *gens
;
756 _ssl_state
&= ~SS_VERIFY_ERROR
;
757 _ssl_msgno
= (size_t)n
;
760 sender
= getsender(m
);
761 to
= hfield1("to", m
);
762 cc
= hfield1("cc", m
);
763 cnttype
= hfield1("content-type", m
);
767 #define _X (sizeof("application/") -1)
768 #define _Y(X) X, sizeof(X) -1
769 if (cnttype
&& is_asccaseprefix(cnttype
, "application/") &&
770 (!ascncasecmp(cnttype
+ _X
, _Y("pkcs7-mime")) ||
771 !ascncasecmp(cnttype
+ _X
, _Y("x-pkcs7-mime")))) {
774 if ((x
= smime_decrypt(m
, to
, cc
, 1)) == NULL
)
776 if (x
!= (struct message
*)-1) {
782 if ((ip
= setinput(&mb
, m
, NEED_BODY
)) == NULL
)
788 if ((fp
= Ftmp(NULL
, "smimever", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
790 n_perr(_("tempfile"), 0);
799 if ((fb
= BIO_new_fp(fp
, BIO_NOCLOSE
)) == NULL
) {
801 "Error creating BIO verification object for message %d"), n
);
805 if ((pkcs7
= SMIME_read_PKCS7(fb
, &pb
)) == NULL
) {
806 ssl_gen_err(_("Error reading PKCS#7 object for message %d"), n
);
809 if (PKCS7_verify(pkcs7
, chain
, store
, pb
, NULL
, 0) != 1) {
810 ssl_gen_err(_("Error verifying message %d"), n
);
814 if (sender
== NULL
) {
815 n_err(_("Warning: Message %d has no sender\n"), n
);
820 certs
= PKCS7_get0_signers(pkcs7
, chain
, 0);
822 n_err(_("No certificates found in message %d\n"), n
);
826 for (i
= 0; i
< sk_X509_num(certs
); ++i
) {
827 cert
= sk_X509_value(certs
, i
);
828 gens
= X509_get_ext_d2i(cert
, NID_subject_alt_name
, NULL
, NULL
);
830 for (j
= 0; j
< sk_GENERAL_NAME_num(gens
); ++j
) {
831 gen
= sk_GENERAL_NAME_value(gens
, j
);
832 if (gen
->type
== GEN_EMAIL
) {
833 if (options
& OPT_VERB
)
834 n_err(_("Comparing subject_alt_name: need<%s> is<%s>)\n"),
835 sender
, (char*)gen
->d
.ia5
->data
);
836 if (!asccasecmp((char*)gen
->d
.ia5
->data
, sender
))
842 if ((subj
= X509_get_subject_name(cert
)) != NULL
&&
843 X509_NAME_get_text_by_NID(subj
, NID_pkcs9_emailAddress
,
844 data
, sizeof data
) > 0) {
845 data
[sizeof data
-1] = '\0';
846 if (options
& OPT_VERB
)
847 n_err(_("Comparing emailAddress: need<%s> is<%s>\n"),
849 if (!asccasecmp(data
, sender
))
853 n_err(_("Message %d: certificate does not match <%s>\n"), n
, sender
);
856 rv
= ((_ssl_state
& SS_VERIFY_ERROR
) != 0);
858 printf(_("Message %d was verified successfully\n"), n
);
868 static EVP_CIPHER
const *
869 _smime_cipher(char const *name
)
871 EVP_CIPHER
const *cipher
;
877 vn
= ac_alloc(i
= strlen(name
) + sizeof("smime-cipher-") -1 +1);
878 snprintf(vn
, (int)i
, "smime-cipher-%s", name
);
882 if (cp
== NULL
&& (cp
= ok_vlook(smime_cipher
)) == NULL
) {
883 cipher
= _SMIME_DEFAULT_CIPHER();
888 for (i
= 0; i
< NELEM(_smime_ciphers
); ++i
)
889 if (!asccasecmp(_smime_ciphers
[i
].sc_name
, cp
)) {
890 cipher
= (*_smime_ciphers
[i
].sc_fun
)();
893 #ifndef OPENSSL_NO_AES
894 for (i
= 0; i
< NELEM(_smime_ciphers_obs
); ++i
) /* TODO obsolete */
895 if (!asccasecmp(_smime_ciphers_obs
[i
].sc_name
, cp
)) {
896 OBSOLETE2(_("*smime-cipher* names with hyphens will vanish"), cp
);
897 cipher
= (*_smime_ciphers_obs
[i
].sc_fun
)();
902 /* Not a builtin algorithm, but we may have dynamic support for more */
903 #ifdef HAVE_SSL_ALL_ALGORITHMS
905 if ((cipher
= EVP_get_cipherbyname(cp
)) != NULL
)
909 n_err(_("Invalid S/MIME cipher(s): \"%s\"\n"), cp
);
916 ssl_password_cb(char *buf
, int size
, int rwflag
, void *userdata
)
924 if ((pass
= getpassword("PEM pass phrase:")) != NULL
) {
926 if (UICMP(z
, len
, >=, size
))
928 memcpy(buf
, pass
, len
);
937 smime_sign_cert(char const *xname
, char const *xname2
, bool_t dowarn
)
942 char const *name
= xname
, *name2
= xname2
;
948 np
= lextract(name
, GTO
| GSKIN
);
950 /* This needs to be more intelligent since it will currently take the
951 * first name for which a private key is available regardless of
952 * whether it is the right one for the message */
953 vn
= ac_alloc(vs
= strlen(np
->n_name
) + 30);
954 snprintf(vn
, vs
, "smime-sign-cert-%s", np
->n_name
);
968 if ((cp
= ok_vlook(smime_sign_cert
)) == NULL
)
971 if ((cp
= file_expand(cp
)) == NULL
)
973 if ((fp
= Fopen(cp
, "r")) == NULL
)
980 n_err(_("Could not find a certificate for %s%s%s\n"),
981 xname
, (xname2
!= NULL
? _("or ") : ""),
982 (xname2
!= NULL
? xname2
: ""));
987 _smime_sign_include_certs(char const *name
)
992 /* See comments in smime_sign_cert() for algorithm pitfalls */
996 for (np
= lextract(name
, GTO
| GSKIN
); np
!= NULL
; np
= np
->n_flink
) {
998 char *vn
= ac_alloc(vs
= strlen(np
->n_name
) + 30);
999 snprintf(vn
, vs
, "smime-sign-include-certs-%s", np
->n_name
);
1006 rv
= ok_vlook(smime_sign_include_certs
);
1013 _smime_sign_include_chain_creat(_STACKOF(X509
) **chain
, char const *cfiles
)
1017 char *nfield
, *cfield
, *x
;
1020 *chain
= sk_X509_new_null();
1022 for (nfield
= savestr(cfiles
);
1023 (cfield
= n_strsep(&nfield
, ',', TRU1
)) != NULL
;) {
1024 if ((x
= file_expand(cfield
)) == NULL
||
1025 (fp
= Fopen(cfield
= x
, "r")) == NULL
) {
1029 if ((tmp
= PEM_read_X509(fp
, NULL
, &ssl_password_cb
, NULL
)) == NULL
) {
1030 ssl_gen_err(_("Error reading certificate from \"%s\""), cfield
);
1034 sk_X509_push(*chain
, tmp
);
1038 if (sk_X509_num(*chain
) == 0) {
1039 n_err(_("*smime-sign-include-certs* defined but empty\n"));
1044 return (*chain
!= NULL
);
1046 sk_X509_pop_free(*chain
, X509_free
);
1051 static EVP_MD
const *
1052 _smime_sign_digest(char const *name
, char const **digname
)
1054 EVP_MD
const *digest
;
1059 /* See comments in smime_sign_cert() for algorithm pitfalls */
1063 for (np
= lextract(name
, GTO
| GSKIN
); np
!= NULL
; np
= np
->n_flink
) {
1065 char *vn
= ac_alloc(vs
= strlen(np
->n_name
) + 30);
1066 snprintf(vn
, vs
, "smime-sign-message-digest-%s", np
->n_name
);
1074 if ((cp
= ok_vlook(smime_sign_message_digest
)) == NULL
) {
1075 digest
= _SMIME_DEFAULT_DIGEST();
1076 *digname
= _SMIME_DEFAULT_DIGEST_S
;
1082 { char *x
= salloc(i
+1);
1083 i_strcpy(x
, cp
, i
+1);
1088 for (i
= 0; i
< NELEM(_smime_digests
); ++i
)
1089 if (!strcmp(_smime_digests
[i
].sd_name
, cp
)) {
1090 digest
= (*_smime_digests
[i
].sd_fun
)();
1094 /* Not a builtin algorithm, but we may have dynamic support for more */
1095 #ifdef HAVE_SSL_ALL_ALGORITHMS
1097 if ((digest
= EVP_get_digestbyname(cp
)) != NULL
)
1101 n_err(_("Invalid message digest: \"%s\"\n"), cp
);
1108 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1110 load_crl1(X509_STORE
*store
, char const *name
)
1112 X509_LOOKUP
*lookup
;
1113 enum okay rv
= STOP
;
1116 if (options
& OPT_VERB
)
1117 n_err(_("Loading CRL from \"%s\"\n"), name
);
1118 if ((lookup
= X509_STORE_add_lookup(store
, X509_LOOKUP_file())) == NULL
) {
1119 ssl_gen_err(_("Error creating X509 lookup object"));
1122 if (X509_load_crl_file(lookup
, name
, X509_FILETYPE_PEM
) != 1) {
1123 ssl_gen_err(_("Error loading CRL from \"%s\""), name
);
1131 #endif /* new OpenSSL */
1134 load_crls(X509_STORE
*store
, enum okeys fok
, enum okeys dok
)
1136 char *crl_file
, *crl_dir
;
1137 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1143 enum okay rv
= STOP
;
1146 if ((crl_file
= _var_oklook(fok
)) != NULL
) {
1147 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1148 if ((crl_file
= file_expand(crl_file
)) == NULL
||
1149 load_crl1(store
, crl_file
) != OKAY
)
1152 n_err(_("This OpenSSL version is too old to use CRLs\n"));
1157 if ((crl_dir
= _var_oklook(dok
)) != NULL
) {
1158 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1160 if ((x
= file_expand(crl_dir
)) == NULL
||
1161 (dirp
= opendir(crl_dir
= x
)) == NULL
) {
1166 ds
= strlen(crl_dir
);
1167 fn
= smalloc(fs
= ds
+ 20);
1168 memcpy(fn
, crl_dir
, ds
);
1170 while ((dp
= readdir(dirp
)) != NULL
) {
1171 if (dp
->d_name
[0] == '.' && (dp
->d_name
[1] == '\0' ||
1172 (dp
->d_name
[1] == '.' && dp
->d_name
[2] == '\0')))
1174 if (dp
->d_name
[0] == '.')
1176 if (ds
+ (es
= strlen(dp
->d_name
)) + 2 < fs
)
1177 fn
= srealloc(fn
, fs
= ds
+ es
+ 20);
1178 memcpy(fn
+ ds
+ 1, dp
->d_name
, es
+ 1);
1179 if (load_crl1(store
, fn
) != OKAY
) {
1187 #else /* old OpenSSL */
1188 n_err(_("This OpenSSL version is too old to use CRLs\n"));
1192 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
1193 if (crl_file
|| crl_dir
)
1194 X509_STORE_set_flags(store
, X509_V_FLAG_CRL_CHECK
|
1195 X509_V_FLAG_CRL_CHECK_ALL
);
1204 ssl_open(struct url
const *urlp
, struct sock
*sp
)
1208 char const *cp
, *cp_base
;
1210 enum okay rv
= STOP
;
1215 ssl_set_verify_level(urlp
);
1217 if ((ctxp
= SSL_CTX_new(_SSL_CLIENT_METHOD())) == NULL
) {
1218 ssl_gen_err(_("SSL_CTX_new() failed"));
1222 /* Available with OpenSSL 0.9.6 or later */
1223 #ifdef SSL_MODE_AUTO_RETRY
1224 SSL_CTX_set_mode(ctxp
, SSL_MODE_AUTO_RETRY
);
1227 if ((confp
= _ssl_conf_setup(ctxp
)) == NULL
)
1230 /* TODO obsolete Check for *ssl-method*, warp to a *ssl-protocol* value */
1231 if ((cp
= xok_vlook(ssl_method
, urlp
, OXM_ALL
)) != NULL
) {
1232 OBSOLETE(_("please use *ssl-protocol* instead of *ssl-method*"));
1233 if (options
& OPT_VERB
)
1234 n_err(_("*ssl-method*: \"%s\"\n"), cp
);
1236 if (!asccasecmp(_ssl_methods
[i
].sm_name
, cp
)) {
1237 cp
= _ssl_methods
[i
].sm_map
;
1240 if (++i
== NELEM(_ssl_methods
)) {
1241 n_err(_("Unsupported TLS/SSL method \"%s\"\n"), cp
);
1246 /* *ssl-protocol* */
1247 if ((cp_base
= xok_vlook(ssl_protocol
, urlp
, OXM_ALL
)) != NULL
) {
1248 if (options
& OPT_VERB
)
1249 n_err(_("*ssl-protocol*: \"%s\"\n"), cp_base
);
1252 cp
= (cp
!= NULL
? savecatsep(cp
, ',', SSL_DISABLED_PROTOCOLS
)
1253 : SSL_DISABLED_PROTOCOLS
);
1254 if (!_ssl_conf(confp
, SCT_PROTOCOL
, cp
))
1258 if ((cp
= xok_vlook(ssl_cert
, urlp
, OXM_ALL
)) != NULL
) {
1259 if (options
& OPT_VERB
)
1260 n_err(_("*ssl-cert* \"%s\"\n"), cp
);
1261 if ((cp_base
= file_expand(cp
)) == NULL
) {
1262 n_err(_("*ssl-cert* value expansion failed: \"%s\"\n"), cp
);
1266 if (!_ssl_conf(confp
, SCT_CERTIFICATE
, cp
))
1270 if ((cp_base
= xok_vlook(ssl_key
, urlp
, OXM_ALL
)) != NULL
) {
1271 if (options
& OPT_VERB
)
1272 n_err(_("*ssl-key* \"%s\"\n"), cp_base
);
1273 if ((cp
= file_expand(cp_base
)) == NULL
) {
1274 n_err(_("*ssl-key* value expansion failed: \"%s\"\n"), cp_base
);
1278 if (!_ssl_conf(confp
, SCT_PRIVATE_KEY
, cp
))
1282 if ((cp
= xok_vlook(ssl_cipher_list
, urlp
, OXM_ALL
)) != NULL
&&
1283 !_ssl_conf(confp
, SCT_CIPHER_STRING
, cp
))
1286 if (!_ssl_load_verifications(ctxp
))
1289 if (!_ssl_conf(confp
, SCT_OPTIONS
, NULL
)) /* TODO *ssl-options* */
1292 /* Done with context setup, create our new per-connection structure */
1293 if (!_ssl_conf_finish(&confp
, FAL0
))
1296 if ((sp
->s_ssl
= SSL_new(ctxp
)) == NULL
) {
1297 ssl_gen_err(_("SSL_new() failed"));
1301 SSL_set_fd(sp
->s_ssl
, sp
->s_fd
);
1303 if (SSL_connect(sp
->s_ssl
) < 0) {
1304 ssl_gen_err(_("could not initiate SSL/TLS connection"));
1308 if (ssl_verify_level
!= SSL_VERIFY_IGNORE
) {
1309 if (ssl_check_host(sp
, urlp
) != OKAY
) {
1310 n_err(_("Host certificate does not match \"%s\"\n"),
1312 if (ssl_verify_decide() != OKAY
)
1317 /* We're fully setup: since we don't reuse the SSL_CTX (pooh) keep it local
1318 * and free it right now -- it is reference counted by sp->s_ssl.. */
1326 SSL_free(sp
->s_ssl
);
1330 _ssl_conf_finish(&confp
, TRU1
);
1337 ssl_gen_err(char const *fmt
, ...)
1346 n_err(_(": %s\n"), ERR_error_string(ERR_get_error(), NULL
));
1353 int *msgvec
= vp
, *ip
, ec
= 0, rv
= 1;
1354 _STACKOF(X509
) *chain
= NULL
;
1355 X509_STORE
*store
= NULL
;
1356 char *ca_dir
, *ca_file
;
1361 ssl_verify_level
= SSL_VERIFY_STRICT
;
1362 if ((store
= X509_STORE_new()) == NULL
) {
1363 ssl_gen_err(_("Error creating X509 store"));
1366 X509_STORE_set_verify_cb_func(store
, &_ssl_verify_cb
);
1368 if ((ca_dir
= ok_vlook(smime_ca_dir
)) != NULL
)
1369 ca_dir
= file_expand(ca_dir
);
1370 if ((ca_file
= ok_vlook(smime_ca_file
)) != NULL
)
1371 ca_file
= file_expand(ca_file
);
1373 if (ca_dir
!= NULL
|| ca_file
!= NULL
) {
1374 if (X509_STORE_load_locations(store
, ca_file
, ca_dir
) != 1) {
1375 ssl_gen_err(_("Error loading %s"),
1376 (ca_file
!= NULL
) ? ca_file
: ca_dir
);
1380 if (!ok_blook(smime_no_default_ca
)) {
1381 if (X509_STORE_set_default_paths(store
) != 1) {
1382 ssl_gen_err(_("Error loading default CA locations"));
1387 if (load_crls(store
, ok_v_smime_crl_file
, ok_v_smime_crl_dir
) != OKAY
)
1390 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
1391 struct message
*mp
= message
+ *ip
- 1;
1393 ec
|= smime_verify(mp
, *ip
, chain
, store
);
1396 exit_status
|= EXIT_ERR
;
1399 X509_STORE_free(store
);
1405 smime_sign(FILE *ip
, char const *addr
)
1407 FILE *rv
= NULL
, *sp
= NULL
, *fp
= NULL
, *bp
, *hp
;
1409 _STACKOF(X509
) *chain
= NULL
;
1410 EVP_PKEY
*pkey
= NULL
;
1421 n_err(_("No *from* address for signing specified\n"));
1424 if ((fp
= smime_sign_cert(addr
, NULL
, 1)) == NULL
)
1427 if ((pkey
= PEM_read_PrivateKey(fp
, NULL
, &ssl_password_cb
, NULL
)) == NULL
) {
1428 ssl_gen_err(_("Error reading private key from"));
1433 if ((cert
= PEM_read_X509(fp
, NULL
, &ssl_password_cb
, NULL
)) == NULL
) {
1434 ssl_gen_err(_("Error reading signer certificate from"));
1440 if ((name
= _smime_sign_include_certs(addr
)) != NULL
&&
1441 !_smime_sign_include_chain_creat(&chain
, name
))
1445 if ((md
= _smime_sign_digest(addr
, &name
)) == NULL
)
1448 if ((sp
= Ftmp(NULL
, "smimesign", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600))
1450 n_perr(_("tempfile"), 0);
1455 if (smime_split(ip
, &hp
, &bp
, -1, 0) == STOP
)
1461 if ((bb
= BIO_new_fp(bp
, BIO_NOCLOSE
)) == NULL
||
1462 (sb
= BIO_new_fp(sp
, BIO_NOCLOSE
)) == NULL
) {
1463 ssl_gen_err(_("Error creating BIO signing objects"));
1469 #define _X PKCS7_DETACHED | PKCS7_PARTIAL
1470 if ((pkcs7
= PKCS7_sign(NULL
, NULL
, chain
, bb
, _X
)) == NULL
) {
1471 ssl_gen_err(_("Error creating the PKCS#7 signing object"));
1475 if (PKCS7_sign_add_signer(pkcs7
, cert
, pkey
, md
, _X
) == NULL
) {
1476 ssl_gen_err(_("Error setting PKCS#7 signing object signer"));
1480 if (!PKCS7_final(pkcs7
, bb
, _X
)) {
1481 ssl_gen_err(_("Error finalizing the PKCS#7 signing object"));
1487 if (PEM_write_bio_PKCS7(sb
, pkcs7
) == 0) {
1488 ssl_gen_err(_("Error writing signed S/MIME data"));
1502 rv
= smime_sign_assemble(hp
, bp
, sp
, name
);
1509 sk_X509_pop_free(chain
, X509_free
);
1513 EVP_PKEY_free(pkey
);
1521 smime_encrypt(FILE *ip
, char const *xcertfile
, char const *to
)
1523 FILE *rv
= NULL
, *yp
, *fp
, *bp
, *hp
;
1527 _STACKOF(X509
) *certs
;
1528 EVP_CIPHER
const *cipher
;
1533 if ((certfile
= file_expand(xcertfile
)) == NULL
)
1538 if ((cipher
= _smime_cipher(to
)) == NULL
)
1540 if ((fp
= Fopen(certfile
, "r")) == NULL
) {
1541 n_perr(certfile
, 0);
1545 if ((cert
= PEM_read_X509(fp
, NULL
, &ssl_password_cb
, NULL
)) == NULL
) {
1546 ssl_gen_err(_("Error reading encryption certificate from \"%s\""),
1555 certs
= sk_X509_new_null();
1556 sk_X509_push(certs
, cert
);
1558 if ((yp
= Ftmp(NULL
, "smimeenc", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
1560 n_perr(_("tempfile"), 0);
1565 if (smime_split(ip
, &hp
, &bp
, -1, 0) == STOP
) {
1571 if ((bb
= BIO_new_fp(bp
, BIO_NOCLOSE
)) == NULL
||
1572 (yb
= BIO_new_fp(yp
, BIO_NOCLOSE
)) == NULL
) {
1573 ssl_gen_err(_("Error creating BIO encryption objects"));
1577 if ((pkcs7
= PKCS7_encrypt(certs
, bb
, cipher
, 0)) == NULL
) {
1578 ssl_gen_err(_("Error creating the PKCS#7 encryption object"));
1582 if (PEM_write_bio_PKCS7(yb
, pkcs7
) == 0) {
1583 ssl_gen_err(_("Error writing encrypted S/MIME data"));
1598 rv
= smime_encrypt_assemble(hp
, yp
);
1601 sk_X509_pop_free(certs
, X509_free
);
1608 smime_decrypt(struct message
*m
, char const *to
, char const *cc
, int signcall
)
1611 FILE *fp
, *bp
, *hp
, *op
;
1625 if ((yp
= setinput(&mb
, m
, NEED_BODY
)) == NULL
)
1630 if ((fp
= smime_sign_cert(to
, cc
, 0)) != NULL
) {
1631 pkey
= PEM_read_PrivateKey(fp
, NULL
, &ssl_password_cb
, NULL
);
1633 ssl_gen_err(_("Error reading private key"));
1639 if ((cert
= PEM_read_X509(fp
, NULL
, &ssl_password_cb
, NULL
)) == NULL
) {
1640 ssl_gen_err(_("Error reading decryption certificate"));
1642 EVP_PKEY_free(pkey
);
1648 if ((op
= Ftmp(NULL
, "smimedec", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
1650 n_perr(_("tempfile"), 0);
1654 if (smime_split(yp
, &hp
, &bp
, size
, 1) == STOP
)
1657 if ((ob
= BIO_new_fp(op
, BIO_NOCLOSE
)) == NULL
||
1658 (bb
= BIO_new_fp(bp
, BIO_NOCLOSE
)) == NULL
) {
1659 ssl_gen_err(_("Error creating BIO decryption objects"));
1662 if ((pkcs7
= SMIME_read_PKCS7(bb
, &pb
)) == NULL
) {
1663 ssl_gen_err(_("Error reading PKCS#7 object"));
1670 EVP_PKEY_free(pkey
);
1674 if (PKCS7_type_is_signed(pkcs7
)) {
1676 setinput(&mb
, m
, NEED_BODY
);
1677 rv
= (struct message
*)-1;
1680 if (PKCS7_verify(pkcs7
, NULL
, NULL
, NULL
, ob
,
1681 PKCS7_NOVERIFY
| PKCS7_NOSIGS
) != 1)
1683 fseek(hp
, 0L, SEEK_END
);
1684 fprintf(hp
, "X-Encryption-Cipher: none\n");
1687 } else if (pkey
== NULL
) {
1688 n_err(_("No appropriate private key found\n"));
1690 } else if (cert
== NULL
) {
1691 n_err(_("No appropriate certificate found\n"));
1693 } else if (PKCS7_decrypt(pkcs7
, pkey
, cert
, ob
, 0) != 1) {
1695 ssl_gen_err(_("Error decrypting PKCS#7 object"));
1705 EVP_PKEY_free(pkey
);
1713 EVP_PKEY_free(pkey
);
1717 rv
= smime_decrypt_assemble(m
, hp
, op
);
1724 smime_certsave(struct message
*m
, int n
, FILE *op
)
1727 char *to
, *cc
, *cnttype
;
1733 _STACKOF(X509
) *certs
, *chain
= NULL
;
1735 enum okay rv
= STOP
;
1738 _ssl_msgno
= (size_t)n
;
1740 to
= hfield1("to", m
);
1741 cc
= hfield1("cc", m
);
1742 cnttype
= hfield1("content-type", m
);
1744 if ((ip
= setinput(&mb
, m
, NEED_BODY
)) == NULL
)
1749 #define _X (sizeof("application/") -1)
1750 #define _Y(X) X, sizeof(X) -1
1751 if (cnttype
&& is_asccaseprefix(cnttype
, "application/") &&
1752 (!ascncasecmp(cnttype
+ _X
, _Y("pkcs7-mime")) ||
1753 !ascncasecmp(cnttype
+ _X
, _Y("x-pkcs7-mime")))) {
1756 if ((x
= smime_decrypt(m
, to
, cc
, 1)) == NULL
)
1758 if (x
!= (struct message
*)-1) {
1765 if ((fp
= Ftmp(NULL
, "smimecert", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600))
1767 n_perr(_("tempfile"), 0);
1771 while (size
-- > 0) {
1778 if ((fb
= BIO_new_fp(fp
, BIO_NOCLOSE
)) == NULL
) {
1779 ssl_gen_err("Error creating BIO object for message %d", n
);
1784 if ((pkcs7
= SMIME_read_PKCS7(fb
, &pb
)) == NULL
) {
1785 ssl_gen_err(_("Error reading PKCS#7 object for message %d"), n
);
1793 certs
= PKCS7_get0_signers(pkcs7
, chain
, 0);
1794 if (certs
== NULL
) {
1795 n_err(_("No certificates found in message %d\n"), n
);
1799 for (i
= 0; i
< sk_X509_num(certs
); ++i
) {
1800 cert
= sk_X509_value(certs
, i
);
1801 if (X509_print_fp(op
, cert
) == 0 || PEM_write_X509(op
, cert
) == 0) {
1802 ssl_gen_err(_("Error writing certificate %d from message %d"),
1812 #endif /* HAVE_OPENSSL */