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 - 2014 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 #ifndef HAVE_AMALGAMATION
46 #include <sys/socket.h>
51 #include <netinet/in.h>
53 #include <openssl/crypto.h>
54 #include <openssl/ssl.h>
55 #include <openssl/err.h>
56 #include <openssl/x509v3.h>
57 #include <openssl/x509.h>
58 #include <openssl/pem.h>
59 #include <openssl/rand.h>
61 #ifdef HAVE_ARPA_INET_H
62 # include <arpa/inet.h>
66 * OpenSSL client implementation according to: John Viega, Matt Messier,
67 * Pravir Chandra: Network Security with OpenSSL. Sebastopol, CA 2002.
71 # define _STACKOF(X) STACK_OF(X)
73 # define _STACKOF(X) /*X*/STACK
77 char const sm_name
[8];
78 SSL_METHOD
const * (*sm_fun
)(void);
82 char const sc_name
[8];
83 EVP_CIPHER
const * (*sc_fun
)(void);
86 /* Supported SSL/TLS methods: update manual on change! */
87 static struct ssl_method
const _ssl_methods
[] = {
88 {"auto", &SSLv23_client_method
},
89 #define _SSL_DEFAULT_METHOD SSLv23_client_method
90 #ifndef OPENSSL_NO_TLS1
91 # ifdef TLS1_2_VERSION
92 {"tls1.2", &TLSv1_2_client_method
},
94 # ifdef TLS1_1_VERSION
95 {"tls1.1", &TLSv1_1_client_method
},
97 {"tls1", &TLSv1_client_method
},
99 #ifndef OPENSSL_NO_SSL3
100 {"ssl3", &SSLv3_client_method
},
102 #ifndef OPENSSL_NO_SSL2
103 {"ssl2", &SSLv2_client_method
}
107 /* Supported S/MIME cipher algorithms: update manual on change! */
108 static struct smime_cipher
const _smime_ciphers
[] = {
109 #ifndef OPENSSL_NO_AES
110 # define _SMIME_DEFAULT_CIPHER EVP_aes_128_cbc /* According to RFC 5751 */
111 {"aes-128", &EVP_aes_128_cbc
},
112 {"aes-256", &EVP_aes_256_cbc
},
113 {"aes-192", &EVP_aes_192_cbc
},
115 #ifndef OPENSSL_NO_DES
116 # ifndef _SMIME_DEFAULT_CIPHER
117 # define _SMIME_DEFAULT_CIPHER EVP_des_ede3_cbc
119 {"des3", &EVP_des_ede3_cbc
},
120 {"des", &EVP_des_cbc
},
122 #ifndef OPENSSL_NO_RC2
123 {"rc2-40", &EVP_rc2_40_cbc
},
124 {"rc2-64", &EVP_rc2_64_cbc
},
127 #ifndef _SMIME_DEFAULT_CIPHER
128 # error Your OpenSSL library does not include the necessary
129 # error cipher algorithms that are required to support S/MIME
132 static int _ssl_isinit
;
133 static int _ssl_rand_isinit
;
134 static int _ssl_msgno
;
135 static int _ssl_verify_error
;
137 static int _ssl_rand_init(void);
138 static void _ssl_init(void);
139 static bool_t
_ssl_parse_asn1_time(ASN1_TIME
*atp
,
140 char *bdat
, size_t blen
);
141 static int _ssl_verify_cb(int success
, X509_STORE_CTX
*store
);
142 static const SSL_METHOD
*ssl_select_method(char const *uhp
);
143 static void ssl_load_verifications(struct sock
*sp
);
144 static void ssl_certificate(struct sock
*sp
, char const *uhp
);
145 static enum okay
ssl_check_host(char const *server
, struct sock
*sp
);
146 static int smime_verify(struct message
*m
, int n
, _STACKOF(X509
) *chain
,
148 static EVP_CIPHER
const * _smime_cipher(char const *name
);
149 static int ssl_password_cb(char *buf
, int size
, int rwflag
,
151 static FILE * smime_sign_cert(char const *xname
, char const *xname2
,
153 static char * _smime_sign_include_certs(char const *name
);
154 static bool_t
_smime_sign_include_chain_creat(_STACKOF(X509
) **chain
,
156 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
157 static enum okay
load_crl1(X509_STORE
*store
, char const *name
);
159 static enum okay
load_crls(X509_STORE
*store
, enum okeys fok
, enum okeys dok
);
168 if ((cp
= ok_vlook(ssl_rand_egd
)) != NULL
) {
169 if ((x
= file_expand(cp
)) == NULL
|| RAND_egd(cp
= x
) == -1)
170 fprintf(stderr
, tr(245, "entropy daemon at \"%s\" not available\n"),
174 } else if ((cp
= ok_vlook(ssl_rand_file
)) != NULL
) {
175 if ((x
= file_expand(cp
)) == NULL
|| RAND_load_file(cp
= x
, 1024) == -1)
176 fprintf(stderr
, tr(246, "entropy file at \"%s\" not available\n"), cp
);
180 if (!stat(cp
, &st
) && S_ISREG(st
.st_mode
) && !access(cp
, W_OK
)) {
181 if (RAND_write_file(cp
) == -1) {
182 fprintf(stderr
, tr(247,
183 "writing entropy data to \"%s\" failed\n"), cp
);
197 if (_ssl_isinit
== 0) {
201 if (_ssl_rand_isinit
== 0)
202 _ssl_rand_isinit
= _ssl_rand_init();
207 _ssl_parse_asn1_time(ASN1_TIME
*atp
, char *bdat
, size_t blen
)
209 /* Shamelessly stolen from CURL */
211 int Y
, M
, d
, h
, m
, s
;
215 db
= (char const*)atp
->data
;
216 if (atp
->length
< 10)
219 for (s
= 0; s
< 10; ++s
)
220 if (!digitchar(db
[s
]))
223 gm
= (db
[atp
->length
- 1] == 'Z') ? "GMT" : "";
225 Y
= (db
[0] - '0') * 10 + (db
[1] - '0');
230 M
= (db
[2] - '0') * 10 + (db
[3] - '0');
234 d
= (db
[4] - '0') * 10 + (db
[5] - '0');
235 h
= (db
[6] - '0') * 10 + (db
[7] - '0');
236 m
= (db
[8] - '0') * 10 + (db
[9] - '0');
237 s
= (db
[10] >= '0' && db
[10] <= '9' && db
[11] >= '0' && db
[11] <= '9')
238 ? ((db
[10] - '0') * 10 + (db
[11] - '0')) : 0;
240 snprintf(bdat
, blen
, "%04d-%02d-%02d %02d:%02d:%02d %s",
241 Y
, M
, d
, h
, m
, s
, gm
);
247 snprintf(bdat
, blen
, tr(576, "Bogus certificate date: %.*s\n"),
254 _ssl_verify_cb(int success
, X509_STORE_CTX
*store
)
261 if (success
&& !(options
& OPT_VERB
))
264 if (_ssl_msgno
!= 0) {
265 fprintf(stderr
, "Message %d:\n", _ssl_msgno
);
268 fprintf(stderr
, tr(229, " Certificate depth %d %s\n"),
269 X509_STORE_CTX_get_error_depth(store
), (success
? "" : tr(579, "ERROR")));
271 cert
= X509_STORE_CTX_get_current_cert(store
);
273 X509_NAME_oneline(X509_get_subject_name(cert
), data
, sizeof data
);
274 fprintf(stderr
, tr(231, " subject = %s\n"), data
);
276 _ssl_parse_asn1_time(X509_get_notBefore(cert
), data
, sizeof data
);
277 fprintf(stderr
, tr(577, " notBefore = %s\n"), data
);
279 _ssl_parse_asn1_time(X509_get_notAfter(cert
), data
, sizeof data
);
280 fprintf(stderr
, tr(578, " notAfter = %s\n"), data
);
283 int err
= X509_STORE_CTX_get_error(store
);
284 fprintf(stderr
, tr(232, " err %i: %s\n"),
285 err
, X509_verify_cert_error_string(err
));
286 _ssl_verify_error
= 1;
289 X509_NAME_oneline(X509_get_issuer_name(cert
), data
, sizeof data
);
290 fprintf(stderr
, tr(230, " issuer = %s\n"), data
);
292 if (!success
&& ssl_verify_decide() != OKAY
)
299 static SSL_METHOD
const *
300 ssl_select_method(char const *uhp
)
302 SSL_METHOD
const *method
;
307 if ((cp
= ssl_method_string(uhp
)) != NULL
) {
309 for (i
= 0; i
< NELEM(_ssl_methods
); ++i
)
310 if (!strcmp(_ssl_methods
[i
].sm_name
, cp
)) {
311 method
= (*_ssl_methods
[i
].sm_fun
)();
314 fprintf(stderr
, tr(244, "Invalid SSL method \"%s\"\n"), cp
);
316 method
= _SSL_DEFAULT_METHOD();
323 ssl_load_verifications(struct sock
*sp
)
325 char *ca_dir
, *ca_file
;
329 if (ssl_verify_level
== SSL_VERIFY_IGNORE
)
332 if ((ca_dir
= ok_vlook(ssl_ca_dir
)) != NULL
)
333 ca_dir
= file_expand(ca_dir
);
334 if ((ca_file
= ok_vlook(ssl_ca_file
)) != NULL
)
335 ca_file
= file_expand(ca_file
);
337 if (ca_dir
!= NULL
|| ca_file
!= NULL
) {
338 if (SSL_CTX_load_verify_locations(sp
->s_ctx
, ca_file
, ca_dir
) != 1) {
339 fprintf(stderr
, tr(233, "Error loading "));
341 fputs(ca_dir
, stderr
);
343 fputs(tr(234, " or "), stderr
);
346 fputs(ca_file
, stderr
);
351 if (!ok_blook(ssl_no_default_ca
)) {
352 if (SSL_CTX_set_default_verify_paths(sp
->s_ctx
) != 1)
353 fprintf(stderr
, tr(243, "Error loading default CA locations\n"));
356 _ssl_verify_error
= 0;
358 SSL_CTX_set_verify(sp
->s_ctx
, SSL_VERIFY_PEER
, &_ssl_verify_cb
);
359 store
= SSL_CTX_get_cert_store(sp
->s_ctx
);
360 load_crls(store
, ok_v_ssl_crl_file
, ok_v_ssl_crl_dir
);
366 ssl_certificate(struct sock
*sp
, char const *uhp
)
369 char *certvar
, *keyvar
, *cert
, *key
, *x
;
373 certvar
= ac_alloc(i
+ 9 +1);
374 memcpy(certvar
, "ssl-cert-", 9);
375 memcpy(certvar
+ 9, uhp
, i
+1);
377 if ((cert
= vok_vlook(certvar
)) != NULL
||
378 (cert
= ok_vlook(ssl_cert
)) != NULL
) {
380 if ((cert
= file_expand(cert
)) == NULL
) {
383 } else if (SSL_CTX_use_certificate_chain_file(sp
->s_ctx
, cert
) == 1) {
384 keyvar
= ac_alloc(strlen(uhp
) + 8 +1);
385 memcpy(keyvar
, "ssl-key-", 8);
386 memcpy(keyvar
+ 8, uhp
, i
+1);
387 if ((key
= vok_vlook(keyvar
)) == NULL
&&
388 (key
= ok_vlook(ssl_key
)) == NULL
)
390 else if ((x
= key
, key
= file_expand(key
)) == NULL
) {
394 if (SSL_CTX_use_PrivateKey_file(sp
->s_ctx
, key
, SSL_FILETYPE_PEM
) != 1)
396 fprintf(stderr
, tr(238, "cannot load private key from file %s\n"),
401 fprintf(stderr
, tr(239, "cannot load certificate from file %s\n"),
409 ssl_check_host(char const *server
, struct sock
*sp
)
414 _STACKOF(GENERAL_NAME
) *gens
;
420 if ((cert
= SSL_get_peer_certificate(sp
->s_ssl
)) == NULL
) {
421 fprintf(stderr
, tr(248, "no certificate from \"%s\"\n"), server
);
425 gens
= X509_get_ext_d2i(cert
, NID_subject_alt_name
, NULL
, NULL
);
427 for (i
= 0; i
< sk_GENERAL_NAME_num(gens
); ++i
) {
428 gen
= sk_GENERAL_NAME_value(gens
, i
);
429 if (gen
->type
== GEN_DNS
) {
430 if (options
& OPT_VERB
)
431 fprintf(stderr
, "Comparing DNS: <%s>; should <%s>\n",
432 server
, (char*)gen
->d
.ia5
->data
);
433 rv
= rfc2595_hostname_match(server
, (char*)gen
->d
.ia5
->data
);
440 if ((subj
= X509_get_subject_name(cert
)) != NULL
&&
441 X509_NAME_get_text_by_NID(subj
, NID_commonName
, data
, sizeof data
)
443 data
[sizeof data
- 1] = '\0';
444 if (options
& OPT_VERB
)
445 fprintf(stderr
, "Comparing commonName: <%s>; should <%s>\n",
447 rv
= rfc2595_hostname_match(server
, data
);
457 smime_verify(struct message
*m
, int n
, _STACKOF(X509
) *chain
, X509_STORE
*store
)
459 char data
[LINESIZE
], *sender
, *to
, *cc
, *cnttype
;
466 _STACKOF(X509
) *certs
;
467 _STACKOF(GENERAL_NAME
) *gens
;
476 _ssl_verify_error
= 0;
480 sender
= getsender(m
);
481 to
= hfield1("to", m
);
482 cc
= hfield1("cc", m
);
483 cnttype
= hfield1("content-type", m
);
484 if ((ip
= setinput(&mb
, m
, NEED_BODY
)) == NULL
)
486 if (cnttype
&& !ascncasecmp(cnttype
, "application/x-pkcs7-mime", 24)) {
487 if ((x
= smime_decrypt(m
, to
, cc
, 1)) == NULL
)
489 if (x
!= (struct message
*)-1) {
498 if ((fp
= Ftmp(NULL
, "smimever", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
509 if ((fb
= BIO_new_fp(fp
, BIO_NOCLOSE
)) == NULL
) {
511 "Error creating BIO verification object for message %d"), n
);
515 if ((pkcs7
= SMIME_read_PKCS7(fb
, &pb
)) == NULL
) {
516 ssl_gen_err(tr(538, "Error reading PKCS#7 object for message %d"), n
);
519 if (PKCS7_verify(pkcs7
, chain
, store
, pb
, NULL
, 0) != 1) {
520 ssl_gen_err(tr(539, "Error verifying message %d"), n
);
524 if (sender
== NULL
) {
525 fprintf(stderr
, tr(540, "Warning: Message %d has no sender.\n"), n
);
530 certs
= PKCS7_get0_signers(pkcs7
, chain
, 0);
532 fprintf(stderr
, tr(541, "No certificates found in message %d.\n"), n
);
536 for (i
= 0; i
< sk_X509_num(certs
); ++i
) {
537 cert
= sk_X509_value(certs
, i
);
538 gens
= X509_get_ext_d2i(cert
, NID_subject_alt_name
, NULL
, NULL
);
540 for (j
= 0; j
< sk_GENERAL_NAME_num(gens
); ++j
) {
541 gen
= sk_GENERAL_NAME_value(gens
, j
);
542 if (gen
->type
== GEN_EMAIL
) {
543 if (options
& OPT_VERB
)
545 "Comparing subject_alt_name: <%s>; should <%s>\n",
546 sender
, (char*)gen
->d
.ia5
->data
);
547 if (!asccasecmp((char*)gen
->d
.ia5
->data
, sender
))
553 if ((subj
= X509_get_subject_name(cert
)) != NULL
&&
554 X509_NAME_get_text_by_NID(subj
, NID_pkcs9_emailAddress
,
555 data
, sizeof data
) > 0) {
556 data
[sizeof data
-1] = '\0';
557 if (options
& OPT_VERB
)
558 fprintf(stderr
, "Comparing emailAddress: <%s>; should <%s>\n",
560 if (!asccasecmp(data
, sender
))
564 fprintf(stderr
, tr(542, "Message %d: certificate does not match <%s>\n"),
568 if (_ssl_verify_error
== 0)
569 printf(tr(543, "Message %d was verified successfully.\n"), n
);
570 rv
= _ssl_verify_error
;
580 static EVP_CIPHER
const *
581 _smime_cipher(char const *name
)
583 EVP_CIPHER
const *cipher
;
588 vn
= ac_alloc(i
= strlen(name
) + 13 +1);
589 snprintf(vn
, (int)i
, "smime-cipher-%s", name
);
595 for (i
= 0; i
< NELEM(_smime_ciphers
); ++i
)
596 if (!strcmp(_smime_ciphers
[i
].sc_name
, cp
)) {
597 cipher
= (*_smime_ciphers
[i
].sc_fun
)();
600 fprintf(stderr
, tr(240, "Invalid cipher(s): %s\n"), cp
);
602 cipher
= _SMIME_DEFAULT_CIPHER();
609 ssl_password_cb(char *buf
, int size
, int rwflag
, void *userdata
)
617 if ((pass
= getpassword("PEM pass phrase:")) != NULL
) {
619 if (UICMP(z
, len
, >=, size
))
621 memcpy(buf
, pass
, len
);
630 smime_sign_cert(char const *xname
, char const *xname2
, bool_t dowarn
)
635 char const *name
= xname
, *name2
= xname2
;
641 np
= lextract(name
, GTO
| GSKIN
);
643 /* This needs to be more intelligent since it will currently take the
644 * first name for which a private key is available regardless of
645 * whether it is the right one for the message */
646 vn
= ac_alloc(vs
= strlen(np
->n_name
) + 30);
647 snprintf(vn
, vs
, "smime-sign-cert-%s", np
->n_name
);
661 if ((cp
= ok_vlook(smime_sign_cert
)) == NULL
)
664 if ((cp
= file_expand(cp
)) == NULL
)
666 if ((fp
= Fopen(cp
, "r")) == NULL
)
673 fprintf(stderr
, tr(558, "Could not find a certificate for %s"), xname
);
675 fprintf(stderr
, tr(559, "or %s"), xname2
);
682 _smime_sign_include_certs(char const *name
)
687 /* See comments in smime_sign_cert() for algorithm pitfalls */
691 for (np
= lextract(name
, GTO
| GSKIN
); np
!= NULL
; np
= np
->n_flink
) {
693 char *vn
= ac_alloc(vs
= strlen(np
->n_name
) + 30);
694 snprintf(vn
, vs
, "smime-sign-include-certs-%s", np
->n_name
);
701 rv
= ok_vlook(smime_sign_include_certs
);
708 _smime_sign_include_chain_creat(_STACKOF(X509
) **chain
, char const *cfiles
)
712 char *nfield
, *cfield
, *x
;
715 *chain
= sk_X509_new_null();
717 for (nfield
= savestr(cfiles
);
718 (cfield
= n_strsep(&nfield
, ',', TRU1
)) != NULL
;) {
719 if ((x
= file_expand(cfield
)) == NULL
||
720 (fp
= Fopen(cfield
= x
, "r")) == NULL
) {
724 if ((tmp
= PEM_read_X509(fp
, NULL
, &ssl_password_cb
, NULL
)) == NULL
) {
725 ssl_gen_err(tr(560, "Error reading certificate from \"%s\""), cfield
);
729 sk_X509_push(*chain
, tmp
);
733 if (sk_X509_num(*chain
) == 0) {
734 fprintf(stderr
, tr(561, "smime-sign-include-certs defined but empty\n"));
739 return (*chain
!= NULL
);
741 sk_X509_pop_free(*chain
, X509_free
);
746 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
748 load_crl1(X509_STORE
*store
, char const *name
)
754 if (options
& OPT_VERB
)
755 printf("Loading CRL from \"%s\".\n", name
);
756 if ((lookup
= X509_STORE_add_lookup(store
, X509_LOOKUP_file())) == NULL
) {
757 ssl_gen_err(tr(565, "Error creating X509 lookup object"));
760 if (X509_load_crl_file(lookup
, name
, X509_FILETYPE_PEM
) != 1) {
761 ssl_gen_err(tr(566, "Error loading CRL from \"%s\""), name
);
769 #endif /* new OpenSSL */
772 load_crls(X509_STORE
*store
, enum okeys fok
, enum okeys dok
)
774 char *crl_file
, *crl_dir
;
775 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
784 if ((crl_file
= _var_oklook(fok
)) != NULL
) {
785 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
786 if ((crl_file
= file_expand(crl_file
)) == NULL
||
787 load_crl1(store
, crl_file
) != OKAY
)
790 fprintf(stderr
, tr(567,
791 "This OpenSSL version is too old to use CRLs.\n"));
796 if ((crl_dir
= _var_oklook(dok
)) != NULL
) {
797 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
799 if ((x
= file_expand(crl_dir
)) == NULL
||
800 (dirp
= opendir(crl_dir
= x
)) == NULL
) {
805 ds
= strlen(crl_dir
);
806 fn
= smalloc(fs
= ds
+ 20);
807 memcpy(fn
, crl_dir
, ds
);
809 while ((dp
= readdir(dirp
)) != NULL
) {
810 if (dp
->d_name
[0] == '.' && (dp
->d_name
[1] == '\0' ||
811 (dp
->d_name
[1] == '.' && dp
->d_name
[2] == '\0')))
813 if (dp
->d_name
[0] == '.')
815 if (ds
+ (es
= strlen(dp
->d_name
)) + 2 < fs
)
816 fn
= srealloc(fn
, fs
= ds
+ es
+ 20);
817 memcpy(fn
+ ds
+ 1, dp
->d_name
, es
+ 1);
818 if (load_crl1(store
, fn
) != OKAY
) {
826 #else /* old OpenSSL */
827 fprintf(stderr
, tr(567,
828 "This OpenSSL version is too old to use CRLs.\n"));
832 #if defined X509_V_FLAG_CRL_CHECK && defined X509_V_FLAG_CRL_CHECK_ALL
833 if (crl_file
|| crl_dir
)
834 X509_STORE_set_flags(store
, X509_V_FLAG_CRL_CHECK
|
835 X509_V_FLAG_CRL_CHECK_ALL
);
844 ssl_open(char const *server
, struct sock
*sp
, char const *uhp
)
852 ssl_set_verify_level(uhp
);
853 if ((sp
->s_ctx
= SSL_CTX_new(UNCONST(ssl_select_method(uhp
)))) == NULL
) {
854 ssl_gen_err(tr(261, "SSL_CTX_new() failed"));
858 #ifdef SSL_MODE_AUTO_RETRY
859 /* available with OpenSSL 0.9.6 or later */
860 SSL_CTX_set_mode(sp
->s_ctx
, SSL_MODE_AUTO_RETRY
);
861 #endif /* SSL_MODE_AUTO_RETRY */
863 if (!ok_blook(ssl_v2_allow
))
864 opts
|= SSL_OP_NO_SSLv2
;
865 SSL_CTX_set_options(sp
->s_ctx
, opts
);
866 ssl_load_verifications(sp
);
867 ssl_certificate(sp
, uhp
);
868 if ((cp
= ok_vlook(ssl_cipher_list
)) != NULL
) {
869 if (SSL_CTX_set_cipher_list(sp
->s_ctx
, cp
) != 1)
870 fprintf(stderr
, tr(240, "Invalid cipher(s): %s\n"), cp
);
873 if ((sp
->s_ssl
= SSL_new(sp
->s_ctx
)) == NULL
) {
874 ssl_gen_err(tr(262, "SSL_new() failed"));
877 SSL_set_fd(sp
->s_ssl
, sp
->s_fd
);
878 if (SSL_connect(sp
->s_ssl
) < 0) {
879 ssl_gen_err(tr(263, "could not initiate SSL/TLS connection"));
882 if (ssl_verify_level
!= SSL_VERIFY_IGNORE
) {
883 if (ssl_check_host(server
, sp
) != OKAY
) {
884 fprintf(stderr
, tr(249, "host certificate does not match \"%s\"\n"),
886 if (ssl_verify_decide() != OKAY
)
898 ssl_gen_err(char const *fmt
, ...)
904 vfprintf(stderr
, fmt
, ap
);
906 SSL_load_error_strings();
907 fprintf(stderr
, ": %s\n", ERR_error_string(ERR_get_error(), NULL
));
914 int *msgvec
= vp
, *ip
, ec
= 0, rv
= 1;
915 _STACKOF(X509
) *chain
= NULL
;
917 char *ca_dir
, *ca_file
;
922 ssl_verify_level
= SSL_VERIFY_STRICT
;
923 if ((store
= X509_STORE_new()) == NULL
) {
924 ssl_gen_err(tr(544, "Error creating X509 store"));
927 X509_STORE_set_verify_cb_func(store
, &_ssl_verify_cb
);
929 if ((ca_dir
= ok_vlook(smime_ca_dir
)) != NULL
)
930 ca_dir
= file_expand(ca_dir
);
931 if ((ca_file
= ok_vlook(smime_ca_file
)) != NULL
)
932 ca_file
= file_expand(ca_file
);
934 if (ca_dir
!= NULL
|| ca_file
!= NULL
) {
935 if (X509_STORE_load_locations(store
, ca_file
, ca_dir
) != 1) {
936 ssl_gen_err(tr(545, "Error loading %s"),
937 (ca_file
!= NULL
) ? ca_file
: ca_dir
);
941 if (!ok_blook(smime_no_default_ca
)) {
942 if (X509_STORE_set_default_paths(store
) != 1) {
943 ssl_gen_err(tr(546, "Error loading default CA locations"));
948 if (load_crls(store
, ok_v_smime_crl_file
, ok_v_smime_crl_dir
) != OKAY
)
950 for (ip
= msgvec
; *ip
!= 0; ++ip
) {
951 struct message
*mp
= message
+ *ip
- 1;
953 ec
|= smime_verify(mp
, *ip
, chain
, store
);
956 exit_status
|= EXIT_ERR
;
963 smime_sign(FILE *ip
, char const *addr
)
965 FILE *rv
= NULL
, *sp
= NULL
, *fp
= NULL
, *bp
, *hp
;
967 _STACKOF(X509
) *chain
= NULL
;
969 EVP_PKEY
*pkey
= NULL
;
977 fprintf(stderr
, tr(531, "No \"from\" address for signing specified\n"));
980 if ((fp
= smime_sign_cert(addr
, NULL
, 1)) == NULL
)
983 if ((pkey
= PEM_read_PrivateKey(fp
, NULL
, &ssl_password_cb
, NULL
)) == NULL
) {
984 ssl_gen_err(tr(532, "Error reading private key from"));
989 if ((cert
= PEM_read_X509(fp
, NULL
, &ssl_password_cb
, NULL
)) == NULL
) {
990 ssl_gen_err(tr(533, "Error reading signer certificate from"));
996 if ((addr
= _smime_sign_include_certs(addr
)) != NULL
&&
997 !_smime_sign_include_chain_creat(&chain
, addr
))
1000 if ((sp
= Ftmp(NULL
, "smimesign", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600))
1007 if (smime_split(ip
, &hp
, &bp
, -1, 0) == STOP
) {
1013 if ((bb
= BIO_new_fp(bp
, BIO_NOCLOSE
)) == NULL
||
1014 (sb
= BIO_new_fp(sp
, BIO_NOCLOSE
)) == NULL
) {
1015 ssl_gen_err(tr(534, "Error creating BIO signing objects"));
1020 if ((pkcs7
= PKCS7_sign(cert
, pkey
, chain
, bb
, PKCS7_DETACHED
)) == NULL
) {
1021 ssl_gen_err(tr(535, "Error creating the PKCS#7 signing object"));
1025 if (PEM_write_bio_PKCS7(sb
, pkcs7
) == 0) {
1026 ssl_gen_err(tr(536, "Error writing signed S/MIME data"));
1038 rv
= smime_sign_assemble(hp
, bp
, sp
);
1045 sk_X509_pop_free(chain
, X509_free
);
1049 EVP_PKEY_free(pkey
);
1057 smime_encrypt(FILE *ip
, char const *xcertfile
, char const *to
)
1059 char *certfile
= UNCONST(xcertfile
);
1060 FILE *rv
= NULL
, *yp
, *fp
, *bp
, *hp
;
1064 _STACKOF(X509
) *certs
;
1065 EVP_CIPHER
const *cipher
;
1069 if ((certfile
= file_expand(certfile
)) == NULL
)
1074 if ((cipher
= _smime_cipher(to
)) == NULL
)
1076 if ((fp
= Fopen(certfile
, "r")) == NULL
) {
1081 if ((cert
= PEM_read_X509(fp
, NULL
, &ssl_password_cb
, NULL
)) == NULL
) {
1082 ssl_gen_err(tr(547, "Error reading encryption certificate from \"%s\""),
1091 certs
= sk_X509_new_null();
1092 sk_X509_push(certs
, cert
);
1094 if ((yp
= Ftmp(NULL
, "smimeenc", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
1101 if (smime_split(ip
, &hp
, &bp
, -1, 0) == STOP
) {
1107 if ((bb
= BIO_new_fp(bp
, BIO_NOCLOSE
)) == NULL
||
1108 (yb
= BIO_new_fp(yp
, BIO_NOCLOSE
)) == NULL
) {
1109 ssl_gen_err(tr(548, "Error creating BIO encryption objects"));
1113 if ((pkcs7
= PKCS7_encrypt(certs
, bb
, cipher
, 0)) == NULL
) {
1114 ssl_gen_err(tr(549, "Error creating the PKCS#7 encryption object"));
1118 if (PEM_write_bio_PKCS7(yb
, pkcs7
) == 0) {
1119 ssl_gen_err(tr(550, "Error writing encrypted S/MIME data"));
1133 rv
= smime_encrypt_assemble(hp
, yp
);
1141 smime_decrypt(struct message
*m
, char const *to
, char const *cc
, int signcall
)
1144 FILE *fp
, *bp
, *hp
, *op
;
1158 if ((yp
= setinput(&mb
, m
, NEED_BODY
)) == NULL
)
1163 if ((fp
= smime_sign_cert(to
, cc
, 0)) != NULL
) {
1164 pkey
= PEM_read_PrivateKey(fp
, NULL
, &ssl_password_cb
, NULL
);
1166 ssl_gen_err(tr(551, "Error reading private key"));
1172 if ((cert
= PEM_read_X509(fp
, NULL
, &ssl_password_cb
, NULL
)) == NULL
) {
1173 ssl_gen_err(tr(552, "Error reading decryption certificate"));
1175 EVP_PKEY_free(pkey
);
1181 if ((op
= Ftmp(NULL
, "smimedec", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600)) ==
1187 if (smime_split(yp
, &hp
, &bp
, size
, 1) == STOP
)
1190 if ((ob
= BIO_new_fp(op
, BIO_NOCLOSE
)) == NULL
||
1191 (bb
= BIO_new_fp(bp
, BIO_NOCLOSE
)) == NULL
) {
1192 ssl_gen_err(tr(553, "Error creating BIO decryption objects"));
1195 if ((pkcs7
= SMIME_read_PKCS7(bb
, &pb
)) == NULL
) {
1196 ssl_gen_err(tr(554, "Error reading PKCS#7 object"));
1203 EVP_PKEY_free(pkey
);
1207 if (PKCS7_type_is_signed(pkcs7
)) {
1209 setinput(&mb
, m
, NEED_BODY
);
1210 rv
= (struct message
*)-1;
1213 if (PKCS7_verify(pkcs7
, NULL
, NULL
, NULL
, ob
,
1214 PKCS7_NOVERIFY
| PKCS7_NOSIGS
) != 1)
1216 fseek(hp
, 0L, SEEK_END
);
1217 fprintf(hp
, "X-Encryption-Cipher: none\n");
1220 } else if (pkey
== NULL
) {
1221 fprintf(stderr
, tr(555, "No appropriate private key found.\n"));
1223 } else if (cert
== NULL
) {
1224 fprintf(stderr
, tr(556, "No appropriate certificate found.\n"));
1226 } else if (PKCS7_decrypt(pkcs7
, pkey
, cert
, ob
, 0) != 1) {
1228 ssl_gen_err(tr(557, "Error decrypting PKCS#7 object"));
1238 EVP_PKEY_free(pkey
);
1246 EVP_PKEY_free(pkey
);
1250 rv
= smime_decrypt_assemble(m
, hp
, op
);
1257 smime_certsave(struct message
*m
, int n
, FILE *op
)
1260 char *to
, *cc
, *cnttype
;
1266 _STACKOF(X509
) *certs
, *chain
= NULL
;
1268 enum okay rv
= STOP
;
1273 to
= hfield1("to", m
);
1274 cc
= hfield1("cc", m
);
1275 cnttype
= hfield1("content-type", m
);
1276 if ((ip
= setinput(&mb
, m
, NEED_BODY
)) == NULL
)
1278 if (cnttype
&& !strncmp(cnttype
, "application/x-pkcs7-mime", 24)) {
1279 if ((x
= smime_decrypt(m
, to
, cc
, 1)) == NULL
)
1281 if (x
!= (struct message
*)-1) {
1288 if ((fp
= Ftmp(NULL
, "smimecert", OF_RDWR
| OF_UNLINK
| OF_REGISTER
, 0600))
1294 while (size
-- > 0) {
1301 if ((fb
= BIO_new_fp(fp
, BIO_NOCLOSE
)) == NULL
) {
1302 ssl_gen_err("Error creating BIO object for message %d", n
);
1307 if ((pkcs7
= SMIME_read_PKCS7(fb
, &pb
)) == NULL
) {
1308 ssl_gen_err(tr(562, "Error reading PKCS#7 object for message %d"), n
);
1316 certs
= PKCS7_get0_signers(pkcs7
, chain
, 0);
1317 if (certs
== NULL
) {
1318 fprintf(stderr
, tr(563, "No certificates found in message %d\n"), n
);
1322 for (i
= 0; i
< sk_X509_num(certs
); ++i
) {
1323 cert
= sk_X509_value(certs
, i
);
1324 if (X509_print_fp(op
, cert
) == 0 || PEM_write_X509(op
, cert
) == 0) {
1325 ssl_gen_err(tr(564, "Error writing certificate %d from message %d"),
1335 #endif /* HAVE_OPENSSL */
1337 /* vim:set fenc=utf-8:s-it-mode */