1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: smime.c 1176 2008-09-29 21:16:42Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2008 University of Washington
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * ========================================================================
19 * This is based on a contribution from Jonathan Paisley
22 * Author: paisleyj@dcs.gla.ac.uk
27 #include "../pith/headers.h"
31 #include "../pith/osdep/canaccess.h"
32 #include "../pith/helptext.h"
33 #include "../pith/store.h"
34 #include "../pith/status.h"
35 #include "../pith/detach.h"
36 #include "../pith/conf.h"
37 #include "../pith/smkeys.h"
38 #include "../pith/smime.h"
39 #include "../pith/mailpart.h"
40 #include "../pith/reply.h"
41 #include "../pith/tempfile.h"
42 #include "../pith/readfile.h"
43 #include "../pith/remote.h"
45 #include <openssl/buffer.h>
48 typedef enum {Public
, Private
, CACert
} WhichCerts
;
51 /* internal prototypes */
52 static void forget_private_keys(void);
53 static int app_RAND_load_file(const char *file
);
54 static void openssl_extra_randomness(void);
55 static int app_RAND_write_file(const char *file
);
56 static void smime_init(void);
57 static const char *openssl_error_string(void);
58 static void create_local_cache(char *base
, BODY
*b
);
59 static BIO
*raw_part_to_bio(long msgno
, const char *section
);
60 static long rfc822_output_func(void *b
, char *string
);
61 static int load_private_key(PERSONAL_CERT
*pcert
);
62 static void setup_pkcs7_body_for_signature(BODY
*b
, char *description
,
63 char *type
, char *filename
);
64 static BIO
*body_to_bio(BODY
*body
);
65 static BIO
*bio_from_store(STORE_S
*store
);
66 static STORE_S
*get_part_contents(long msgno
, const char *section
);
67 static PKCS7
*get_pkcs7_from_part(long msgno
, const char *section
);
68 static int do_signature_verify(PKCS7
*p7
, BIO
*in
, BIO
*out
);
69 static int do_detached_signature_verify(BODY
*b
, long msgno
, char *section
);
70 static PERSONAL_CERT
*find_certificate_matching_pkcs7(PKCS7
*p7
);
71 static int do_decoding(BODY
*b
, long msgno
, const char *section
);
72 static void free_smime_struct(SMIME_STUFF_S
**smime
);
73 static void setup_storage_locations(void);
74 static int copy_dir_to_container(WhichCerts which
);
75 static int copy_container_to_dir(WhichCerts which
);
78 int (*pith_opt_smime_get_passphrase
)(void);
81 static X509_STORE
*s_cert_store
;
83 /* State management for randomness functions below */
84 static int seeded
= 0;
85 static int egdsocket
= 0;
89 * Forget any cached private keys
92 forget_private_keys(void)
98 dprint((9, "forget_private_keys()"));
100 for(pcert
=(PERSONAL_CERT
*) ps_global
->smime
->personal_certs
;
105 EVP_PKEY_free(pcert
->key
);
110 ps_global
->smime
->entered_passphrase
= 0;
111 len
= sizeof(ps_global
->smime
->passphrase
);
112 p
= ps_global
->smime
->passphrase
;
121 * taken from openssl/apps/app_rand.c
124 app_RAND_load_file(const char *file
)
129 file
= RAND_file_name(buffer
, sizeof buffer
);
130 else if(RAND_egd(file
) > 0){
131 /* we try if the given filename is an EGD socket.
132 if it is, we don't write anything back to the file. */
137 if(file
== NULL
|| !RAND_load_file(file
, -1)){
138 if(RAND_status() == 0){
139 dprint((1, "unable to load 'random state'\n"));
140 dprint((1, "This means that the random number generator has not been seeded\n"));
141 dprint((1, "with much random data.\n"));
153 * copied and fiddled from imap/src/osdep/unix/auth_ssl.c
156 openssl_extra_randomness(void)
164 /* if system doesn't have /dev/urandom */
165 if(stat ("/dev/urandom", &sbuf
)){
167 tf
= temp_nam(NULL
, NULL
);
169 strncpy(tmp
, tf
, sizeof(tmp
));
170 tmp
[sizeof(tmp
)-1] = '\0';
171 fs_give((void **) &tf
);
174 if((fd
= open(tmp
, O_WRONLY
|O_CREAT
|O_EXCL
, 0600)) < 0)
175 i
= (unsigned long) tmp
;
177 unlink(tmp
); /* don't need the file */
178 fstat(fd
, &sbuf
); /* get information about the file */
179 i
= sbuf
.st_ino
; /* remember its inode */
180 close(fd
); /* or its descriptor */
182 /* not great but it'll have to do */
183 snprintf(tmp
+strlen(tmp
), sizeof(tmp
)-strlen(tmp
), "%.80s%lx%lx%lx",
185 (unsigned long) (time (0) ^ gethostid ()),
186 (unsigned long) getpid ());
187 RAND_seed(tmp
, strlen(tmp
));
193 /* taken from openssl/apps/app_rand.c */
195 app_RAND_write_file(const char *file
)
199 if(egdsocket
|| !seeded
)
201 * If we did not manage to read the seed file,
202 * we should not write a low-entropy seed file back --
203 * it would suppress a crucial warning the next time
209 file
= RAND_file_name(buffer
, sizeof buffer
);
211 if(file
== NULL
|| !RAND_write_file(file
)){
212 dprint((1, "unable to write 'random state'\n"));
220 /* Installed as an atexit() handler to save the random data */
224 dprint((9, "smime_deinit()"));
225 app_RAND_write_file(NULL
);
226 free_smime_struct(&ps_global
->smime
);
230 /* Initialise openssl stuff if needed */
234 if(F_OFF(F_DONT_DO_SMIME
, ps_global
) && !(ps_global
->smime
&& ps_global
->smime
->inited
)){
236 dprint((9, "smime_init()"));
237 if(!ps_global
->smime
)
238 ps_global
->smime
= new_smime_struct();
240 setup_storage_locations();
242 s_cert_store
= get_ca_store();
244 OpenSSL_add_all_algorithms();
245 ERR_load_crypto_strings();
247 app_RAND_load_file(NULL
);
249 openssl_extra_randomness();
250 ps_global
->smime
->inited
= 1;
258 setup_storage_locations(void)
260 int publiccertcontainer
= 0, privatekeycontainer
= 0, cacertcontainer
= 0;
261 char path
[MAXPATH
+1], *contents
;
263 if(!ps_global
->smime
)
267 if(F_ON(F_PUBLICCERTS_IN_KEYCHAIN
, ps_global
)){
268 ps_global
->smime
->publictype
= Keychain
;
271 #endif /* APPLEKEYCHAIN */
272 /* Public certificates in a container */
273 if(ps_global
->VAR_PUBLICCERT_CONTAINER
&& ps_global
->VAR_PUBLICCERT_CONTAINER
[0]){
275 publiccertcontainer
= 1;
278 if(!signature_path(ps_global
->VAR_PUBLICCERT_CONTAINER
, path
, MAXPATH
))
279 publiccertcontainer
= 0;
281 if(publiccertcontainer
&& !IS_REMOTE(path
)
282 && ps_global
->VAR_OPER_DIR
283 && !in_dir(ps_global
->VAR_OPER_DIR
, path
)){
284 q_status_message2(SM_ORDER
| SM_DING
, 3, 4,
285 /* TRANSLATORS: First arg is the directory name, second is
286 the file user wants to read but can't. */
287 _("Can't read file outside %s: %s"),
288 ps_global
->VAR_OPER_DIR
, path
);
289 publiccertcontainer
= 0;
292 if(publiccertcontainer
293 && (IS_REMOTE(path
) || can_access(path
, ACCESS_EXISTS
) == 0)){
294 if(!(IS_REMOTE(path
) && (contents
= simple_read_remote_file(path
, REMOTE_SMIME_SUBTYPE
)))
296 !(contents
= read_file(path
, READ_FROM_LOCALE
)))
297 publiccertcontainer
= 0;
300 if(publiccertcontainer
&& path
[0]){
301 ps_global
->smime
->publictype
= Container
;
302 ps_global
->smime
->publicpath
= cpystr(path
);
305 ps_global
->smime
->publiccontent
= contents
;
306 ps_global
->smime
->publiccertlist
= mem_to_certlist(contents
);
311 /* Public certificates in a directory of files */
312 if(!publiccertcontainer
){
313 ps_global
->smime
->publictype
= Directory
;
316 if(!(signature_path(ps_global
->VAR_PUBLICCERT_DIR
, path
, MAXPATH
)
317 && !IS_REMOTE(path
)))
318 ps_global
->smime
->publictype
= Nada
;
319 else if(can_access(path
, ACCESS_EXISTS
)){
320 if(our_mkpath(path
, 0700)){
321 q_status_message1(SM_ORDER
, 3, 3, _("Can't create directory %s"), path
);
322 ps_global
->smime
->publictype
= Nada
;
326 if(ps_global
->smime
->publictype
== Directory
)
327 ps_global
->smime
->publicpath
= cpystr(path
);
332 #endif /* APPLEKEYCHAIN */
334 /* private keys in a container */
335 if(ps_global
->VAR_PRIVATEKEY_CONTAINER
&& ps_global
->VAR_PRIVATEKEY_CONTAINER
[0]){
337 privatekeycontainer
= 1;
340 if(!signature_path(ps_global
->VAR_PRIVATEKEY_CONTAINER
, path
, MAXPATH
))
341 privatekeycontainer
= 0;
343 if(privatekeycontainer
&& !IS_REMOTE(path
)
344 && ps_global
->VAR_OPER_DIR
345 && !in_dir(ps_global
->VAR_OPER_DIR
, path
)){
346 q_status_message2(SM_ORDER
| SM_DING
, 3, 4,
347 /* TRANSLATORS: First arg is the directory name, second is
348 the file user wants to read but can't. */
349 _("Can't read file outside %s: %s"),
350 ps_global
->VAR_OPER_DIR
, path
);
351 privatekeycontainer
= 0;
354 if(privatekeycontainer
355 && (IS_REMOTE(path
) || can_access(path
, ACCESS_EXISTS
) == 0)){
356 if(!(IS_REMOTE(path
) && (contents
= simple_read_remote_file(path
, REMOTE_SMIME_SUBTYPE
)))
358 !(contents
= read_file(path
, READ_FROM_LOCALE
)))
359 privatekeycontainer
= 0;
362 if(privatekeycontainer
&& path
[0]){
363 ps_global
->smime
->privatetype
= Container
;
364 ps_global
->smime
->privatepath
= cpystr(path
);
367 ps_global
->smime
->privatecontent
= contents
;
368 ps_global
->smime
->personal_certs
= mem_to_personal_certs(contents
);
373 /* private keys in a directory of files */
374 if(!privatekeycontainer
){
375 PERSONAL_CERT
*result
= NULL
;
377 ps_global
->smime
->privatetype
= Directory
;
380 if(!(signature_path(ps_global
->VAR_PRIVATEKEY_DIR
, path
, MAXPATH
)
381 && !IS_REMOTE(path
)))
382 ps_global
->smime
->privatetype
= Nada
;
383 else if(can_access(path
, ACCESS_EXISTS
)){
384 if(our_mkpath(path
, 0700)){
385 q_status_message1(SM_ORDER
, 3, 3, _("Can't create directory %s"), path
);
386 ps_global
->smime
->privatetype
= Nada
;
390 if(ps_global
->smime
->privatetype
== Directory
){
395 ps_global
->smime
->privatepath
= cpystr(path
);
396 dirp
= opendir(path
);
399 while((d
=readdir(dirp
)) != NULL
){
403 if((ll
=strlen(d
->d_name
)) && ll
> 4 && !strcmp(d
->d_name
+ll
-4, ".key")){
405 /* copy file name to temp buffer */
406 strncpy(buf2
, d
->d_name
, sizeof(buf2
)-1);
407 buf2
[sizeof(buf2
)-1] = '\0';
408 /* chop off ".key" trailier */
409 buf2
[strlen(buf2
)-4] = 0;
410 /* Look for certificate */
411 cert
= get_cert_for(buf2
);
416 /* create a new PERSONAL_CERT, fill it in */
418 pc
= (PERSONAL_CERT
*) fs_get(sizeof(*pc
));
420 pc
->name
= cpystr(buf2
);
422 /* Try to load the key with an empty password */
423 pc
->key
= load_key(pc
, "");
435 ps_global
->smime
->personal_certs
= result
;
438 /* extra cacerts in a container */
439 if(ps_global
->VAR_CACERT_CONTAINER
&& ps_global
->VAR_CACERT_CONTAINER
[0]){
444 if(!signature_path(ps_global
->VAR_CACERT_CONTAINER
, path
, MAXPATH
))
447 if(cacertcontainer
&& !IS_REMOTE(path
)
448 && ps_global
->VAR_OPER_DIR
449 && !in_dir(ps_global
->VAR_OPER_DIR
, path
)){
450 q_status_message2(SM_ORDER
| SM_DING
, 3, 4,
451 /* TRANSLATORS: First arg is the directory name, second is
452 the file user wants to read but can't. */
453 _("Can't read file outside %s: %s"),
454 ps_global
->VAR_OPER_DIR
, path
);
459 && (IS_REMOTE(path
) || can_access(path
, ACCESS_EXISTS
) == 0)){
460 if(!(IS_REMOTE(path
) && (contents
= simple_read_remote_file(path
, REMOTE_SMIME_SUBTYPE
)))
462 !(contents
= read_file(path
, READ_FROM_LOCALE
)))
466 if(cacertcontainer
&& path
[0]){
467 ps_global
->smime
->catype
= Container
;
468 ps_global
->smime
->capath
= cpystr(path
);
469 ps_global
->smime
->cacontent
= contents
;
473 if(!cacertcontainer
){
474 ps_global
->smime
->catype
= Directory
;
477 if(!(signature_path(ps_global
->VAR_CACERT_DIR
, path
, MAXPATH
)
478 && !IS_REMOTE(path
)))
479 ps_global
->smime
->catype
= Nada
;
480 else if(can_access(path
, ACCESS_EXISTS
)){
481 if(our_mkpath(path
, 0700)){
482 q_status_message1(SM_ORDER
, 3, 3, _("Can't create directory %s"), path
);
483 ps_global
->smime
->catype
= Nada
;
487 if(ps_global
->smime
->catype
== Directory
)
488 ps_global
->smime
->capath
= cpystr(path
);
494 copy_publiccert_dir_to_container(void)
496 return(copy_dir_to_container(Public
));
501 copy_publiccert_container_to_dir(void)
503 return(copy_container_to_dir(Public
));
508 copy_privatecert_dir_to_container(void)
510 return(copy_dir_to_container(Private
));
515 copy_privatecert_container_to_dir(void)
517 return(copy_container_to_dir(Private
));
522 copy_cacert_dir_to_container(void)
524 return(copy_dir_to_container(CACert
));
529 copy_cacert_container_to_dir(void)
531 return(copy_container_to_dir(CACert
));
536 * returns 0 on success, -1 on failure
539 copy_dir_to_container(WhichCerts which
)
542 BIO
*bio_out
= NULL
, *bio_in
= NULL
;
543 char srcpath
[MAXPATH
+1], dstpath
[MAXPATH
+1], emailaddr
[MAXPATH
], file
[MAXPATH
], line
[4096];
544 char *tempfile
= NULL
;
547 REMDATA_S
*rd
= NULL
;
548 char *configdir
= NULL
;
549 char *configpath
= NULL
;
550 char *filesuffix
= NULL
;
552 dprint((9, "copy_dir_to_container(%s)", which
==Public
? "Public" : which
==Private
? "Private" : which
==CACert
? "CACert" : "?"));
561 configdir
= ps_global
->VAR_PUBLICCERT_DIR
;
562 configpath
= ps_global
->smime
->publicpath
;
565 else if(which
== Private
){
566 configdir
= ps_global
->VAR_PRIVATEKEY_DIR
;
567 configpath
= ps_global
->smime
->privatepath
;
570 else if(which
== CACert
){
571 configdir
= ps_global
->VAR_CACERT_DIR
;
572 configpath
= ps_global
->smime
->capath
;
576 if(!(configdir
&& configdir
[0])){
577 q_status_message(SM_ORDER
, 3, 3, _("Directory not defined"));
581 if(!(configpath
&& configpath
[0])){
583 if(which
== Public
&& F_ON(F_PUBLICCERTS_IN_KEYCHAIN
, ps_global
)){
584 q_status_message(SM_ORDER
, 3, 3, _("Turn off the Keychain feature above first"));
587 #endif /* APPLEKEYCHAIN */
588 q_status_message(SM_ORDER
, 3, 3, _("Container path is not defined"));
592 if(!(filesuffix
&& strlen(filesuffix
) == 4)){
598 * If there is a legit directory to read from set up the
599 * container file to write to.
601 if(signature_path(configdir
, srcpath
, MAXPATH
) && !IS_REMOTE(srcpath
)){
603 if(IS_REMOTE(configpath
)){
604 rd
= rd_create_remote(RemImap
, configpath
, REMOTE_SMIME_SUBTYPE
,
606 _("Can't access remote smime configuration."));
610 (void) rd_read_metadata(rd
);
612 if(rd
->access
== MaybeRorW
){
613 if(rd
->read_status
== 'R')
614 rd
->access
= ReadOnly
;
616 rd
->access
= ReadWrite
;
619 if(rd
->access
!= NoExists
){
621 rd_check_remvalid(rd
, 1L);
624 * If the cached info says it is readonly but
625 * it looks like it's been fixed now, change it to readwrite.
627 if(rd
->read_status
== 'R'){
628 rd_check_readonly_access(rd
);
629 if(rd
->read_status
== 'W'){
630 rd
->access
= ReadWrite
;
631 rd
->flags
|= REM_OUTOFDATE
;
634 rd
->access
= ReadOnly
;
638 if(rd
->flags
& REM_OUTOFDATE
){
639 if(rd_update_local(rd
) != 0){
641 dprint((1, "copy_dir_to_container: rd_update_local failed\n"));
642 rd_close_remdata(&rd
);
649 if(rd
->access
!= ReadWrite
|| rd_remote_is_readonly(rd
)){
650 rd_close_remdata(&rd
);
654 rd
->flags
|= DO_REMTRIM
;
656 strncpy(dstpath
, rd
->lf
, sizeof(dstpath
)-1);
657 dstpath
[sizeof(dstpath
)-1] = '\0';
660 strncpy(dstpath
, configpath
, sizeof(dstpath
)-1);
661 dstpath
[sizeof(dstpath
)-1] = '\0';
665 * dstpath is either the local Container file or the local cache file
666 * for the remote Container file.
668 tempfile
= tempfile_in_same_dir(dstpath
, "az", NULL
);
672 * If there is a legit directory to read from and a tempfile
673 * to write to we continue.
675 if(tempfile
&& (bio_out
=BIO_new_file(tempfile
, "w")) != NULL
){
677 dirp
= opendir(srcpath
);
680 while((d
=readdir(dirp
)) && !ret
){
683 if((ll
=strlen(d
->d_name
)) && ll
> 4 && !strcmp(d
->d_name
+ll
-4, filesuffix
)){
685 /* copy file name to temp buffer */
686 strncpy(emailaddr
, d
->d_name
, sizeof(emailaddr
)-1);
687 emailaddr
[sizeof(emailaddr
)-1] = '\0';
688 /* chop off suffix trailier */
689 emailaddr
[strlen(emailaddr
)-4] = 0;
692 * This is the separator between the contents of
696 if(!((BIO_puts(bio_out
, CACERTSTORELEADER
) > 0)
697 && (BIO_puts(bio_out
, emailaddr
) > 0)
698 && (BIO_puts(bio_out
, "\n") > 0)))
702 if(!((BIO_puts(bio_out
, EMAILADDRLEADER
) > 0)
703 && (BIO_puts(bio_out
, emailaddr
) > 0)
704 && (BIO_puts(bio_out
, "\n") > 0)))
708 /* read then write contents of file */
709 build_path(file
, srcpath
, d
->d_name
, sizeof(file
));
710 if(!(bio_in
= BIO_new_file(file
, "r")))
716 while(BIO_gets(bio_in
, line
, sizeof(line
)) > 0){
717 if(strncmp("-----BEGIN", line
, strlen("-----BEGIN")) == 0)
721 BIO_puts(bio_out
, line
);
723 if(strncmp("-----END", line
, strlen("-----END")) == 0)
738 if(rename_file(tempfile
, dstpath
) < 0){
739 q_status_message2(SM_ORDER
, 3, 3,
740 _("Can't rename %s to %s"), tempfile
, dstpath
);
744 /* if the container is remote, copy it */
745 if(!ret
&& IS_REMOTE(configpath
)){
751 if((e
= rd_update_remote(rd
, datebuf
)) != 0){
753 q_status_message2(SM_ORDER
| SM_DING
, 3, 5,
754 _("Error opening temporary smime file %s: %s"),
755 rd
->lf
, error_description(errno
));
757 "write_remote_smime: error opening temp file %s\n",
758 rd
->lf
? rd
->lf
: "?"));
761 q_status_message2(SM_ORDER
| SM_DING
, 3, 5,
762 _("Error copying to %s: %s"),
763 rd
->rn
, error_description(errno
));
765 "write_remote_smime: error copying from %s to %s\n",
766 rd
->lf
? rd
->lf
: "?", rd
->rn
? rd
->rn
: "?"));
769 q_status_message(SM_ORDER
| SM_DING
, 5, 5,
770 _("Copy of smime key to remote folder failed, NOT saved remotely"));
773 rd_update_metadata(rd
, datebuf
);
774 rd
->read_status
= 'W';
777 rd_close_remdata(&rd
);
783 fs_give((void **) &tempfile
);
790 * returns 0 on success, -1 on failure
793 copy_container_to_dir(WhichCerts which
)
795 char path
[MAXPATH
+1], file
[MAXPATH
+1], buf
[MAXPATH
+1];
797 char *contents
= NULL
;
799 char *filesuffix
= NULL
;
800 char *configdir
= NULL
;
801 char *configpath
= NULL
;
802 char *tempfile
= NULL
;
803 char *p
, *q
, *line
, *name
, *certtext
, *save_p
;
807 dprint((9, "copy_container_to_dir(%s)", which
==Public
? "Public" : which
==Private
? "Private" : which
==CACert
? "CACert" : "?"));
813 leader
= EMAILADDRLEADER
;
814 contents
= ps_global
->smime
->publiccontent
;
815 configdir
= ps_global
->VAR_PUBLICCERT_DIR
;
816 configpath
= ps_global
->smime
->publicpath
;
818 if(!(configpath
&& configpath
[0])){
820 if(which
== Public
&& F_ON(F_PUBLICCERTS_IN_KEYCHAIN
, ps_global
)){
821 q_status_message(SM_ORDER
, 3, 3, _("Turn off the Keychain feature above first"));
824 #endif /* APPLEKEYCHAIN */
825 q_status_message(SM_ORDER
, 3, 3, _("Container path is not defined"));
829 fs_give((void **) &ps_global
->smime
->publicpath
);
832 if(!(signature_path(ps_global
->VAR_PUBLICCERT_DIR
, path
, MAXPATH
)
833 && !IS_REMOTE(path
))){
834 q_status_message(SM_ORDER
, 3, 3, _("Directory is not defined"));
838 if(can_access(path
, ACCESS_EXISTS
)){
839 if(our_mkpath(path
, 0700)){
840 q_status_message1(SM_ORDER
, 3, 3, _("Can't create directory %s"), path
);
845 ps_global
->smime
->publicpath
= cpystr(path
);
846 configpath
= ps_global
->smime
->publicpath
;
848 else if(which
== Private
){
849 leader
= EMAILADDRLEADER
;
850 contents
= ps_global
->smime
->privatecontent
;
851 configdir
= ps_global
->VAR_PRIVATEKEY_DIR
;
852 configpath
= ps_global
->smime
->privatepath
;
854 if(!(configpath
&& configpath
[0])){
855 q_status_message(SM_ORDER
, 3, 3, _("Container path is not defined"));
859 fs_give((void **) &ps_global
->smime
->privatepath
);
862 if(!(signature_path(ps_global
->VAR_PRIVATEKEY_DIR
, path
, MAXPATH
)
863 && !IS_REMOTE(path
))){
864 q_status_message(SM_ORDER
, 3, 3, _("Directory is not defined"));
868 if(can_access(path
, ACCESS_EXISTS
)){
869 if(our_mkpath(path
, 0700)){
870 q_status_message1(SM_ORDER
, 3, 3, _("Can't create directory %s"), path
);
875 ps_global
->smime
->privatepath
= cpystr(path
);
876 configpath
= ps_global
->smime
->privatepath
;
878 else if(which
== CACert
){
879 leader
= CACERTSTORELEADER
;
880 contents
= ps_global
->smime
->cacontent
;
881 configdir
= ps_global
->VAR_CACERT_DIR
;
882 configpath
= ps_global
->smime
->capath
;
884 if(!(configpath
&& configpath
[0])){
885 q_status_message(SM_ORDER
, 3, 3, _("Container path is not defined"));
889 fs_give((void **) &ps_global
->smime
->capath
);
892 if(!(signature_path(ps_global
->VAR_CACERT_DIR
, path
, MAXPATH
)
893 && !IS_REMOTE(path
))){
894 q_status_message(SM_ORDER
, 3, 3, _("Directory is not defined"));
898 if(can_access(path
, ACCESS_EXISTS
)){
899 if(our_mkpath(path
, 0700)){
900 q_status_message1(SM_ORDER
, 3, 3, _("Can't create directory %s"), path
);
905 ps_global
->smime
->capath
= cpystr(path
);
906 configpath
= ps_global
->smime
->capath
;
909 if(!(configdir
&& configdir
[0])){
910 q_status_message(SM_ORDER
, 3, 3, _("Directory not defined"));
914 if(!(configpath
&& configpath
[0])){
915 q_status_message(SM_ORDER
, 3, 3, _("Container path is not defined"));
919 if(!(filesuffix
&& strlen(filesuffix
) == 4)){
924 if(contents
&& *contents
){
925 for(p
= contents
; *p
!= '\0';){
928 while(*p
&& *p
!= '\n')
937 if(strncmp(leader
, line
, strlen(leader
)) == 0){
938 name
= line
+ strlen(leader
);
940 if(strncmp("-----BEGIN", certtext
, strlen("-----BEGIN")) == 0){
941 if((q
= strstr(certtext
, leader
)) != NULL
){
944 else{ /* end of file */
945 q
= certtext
+ strlen(certtext
);
949 strncpy(buf
, name
, sizeof(buf
)-5);
950 buf
[sizeof(buf
)-5] = '\0';
951 strncat(buf
, filesuffix
, 5);
952 build_path(file
, configpath
, buf
, sizeof(file
));
954 in
= BIO_new_mem_buf(certtext
, q
-certtext
);
956 tempfile
= tempfile_in_same_dir(file
, "az", NULL
);
959 out
= BIO_new_file(tempfile
, "w");
962 while((len
= BIO_read(in
, iobuf
, sizeof(iobuf
))) > 0)
963 BIO_write(out
, iobuf
, len
);
967 if(rename_file(tempfile
, file
) < 0){
968 q_status_message2(SM_ORDER
, 3, 3,
969 _("Can't rename %s to %s"),
974 fs_give((void **) &tempfile
);
994 copy_publiccert_container_to_keychain(void)
1001 copy_publiccert_keychain_to_container(void)
1003 /* NOT IMPLEMNTED */
1007 #endif /* APPLEKEYCHAIN */
1011 * Get a pointer to a string describing the most recent OpenSSL error.
1012 * It's statically allocated, so don't change or attempt to free it.
1015 openssl_error_string(void)
1018 const char *data
= NULL
;
1021 errn
= ERR_peek_error_line_data(NULL
, NULL
, &data
, NULL
);
1022 errs
= (char*) ERR_reason_error_string(errn
);
1029 return "unknown error";
1033 /* Return true if the body looks like a PKCS7 object */
1035 is_pkcs7_body(BODY
*body
)
1039 result
= body
->type
==TYPEAPPLICATION
&&
1041 (strucmp(body
->subtype
,"pkcs7-mime")==0 ||
1042 strucmp(body
->subtype
,"x-pkcs7-mime")==0 ||
1043 strucmp(body
->subtype
,"pkcs7-signature")==0 ||
1044 strucmp(body
->subtype
,"x-pkcs7-signature")==0);
1052 * Somewhat useful debug utility to dump the contents of a BIO to a file.
1053 * Note that a memory BIO will have its contents eliminated after they
1054 * are read so this will break the next step.
1057 dump_bio_to_file(BIO
*in
, char *filename
)
1063 out
= BIO_new_file(filename
, "w");
1066 if(BIO_method_type(in
) != BIO_TYPE_MEM
)
1069 while((len
= BIO_read(in
, iobuf
, sizeof(iobuf
))) > 0)
1070 BIO_write(out
, iobuf
, len
);
1081 * Recursively stash a pointer to the decrypted data in our
1082 * manufactured body.
1085 create_local_cache(char *base
, BODY
*b
)
1087 if(b
->type
==TYPEMULTIPART
){
1091 cpytxt(&b
->contents
.text
, base
+ b
->contents
.offset
, b
->size
.bytes
);
1094 * We don't really want to copy the real body contents. It shouldn't be
1095 * used, and in the case of a message with attachments, we'll be
1096 * duplicating the files multiple times.
1098 cpytxt(&b
->contents
.text
, "BODY UNAVAILABLE", 16);
1101 for(p
=b
->nested
.part
; p
; p
=p
->next
)
1102 create_local_cache(base
, (BODY
*) p
);
1105 cpytxt(&b
->contents
.text
, base
+ b
->contents
.offset
, b
->size
.bytes
);
1111 rfc822_output_func(void *b
, char *string
)
1113 BIO
*bio
= (BIO
*) b
;
1115 return((BIO_puts(bio
, string
) > 0) ? 1L : 0L);
1120 * Attempt to load the private key for the given PERSONAL_CERT.
1121 * This sets the appropriate passphrase globals in order to
1122 * interact with the user correctly.
1125 load_private_key(PERSONAL_CERT
*pcert
)
1129 /* Try empty password by default */
1130 char *password
= "";
1133 && (ps_global
->smime
->need_passphrase
1134 || ps_global
->smime
->entered_passphrase
)){
1135 /* We've already been in here and discovered we need a different password */
1137 if(ps_global
->smime
->entered_passphrase
)
1138 password
= (char *) ps_global
->smime
->passphrase
; /* already entered */
1145 if(!(pcert
->key
= load_key(pcert
, password
))){
1146 long err
= ERR_get_error();
1148 /* Couldn't load key... */
1150 if(ps_global
->smime
&& ps_global
->smime
->entered_passphrase
){
1152 /* The user got the password wrong maybe? */
1154 if((ERR_GET_LIB(err
)==ERR_LIB_EVP
&& ERR_GET_REASON(err
)==EVP_R_BAD_DECRYPT
) ||
1155 (ERR_GET_LIB(err
)==ERR_LIB_PEM
&& ERR_GET_REASON(err
)==PEM_R_BAD_DECRYPT
))
1156 q_status_message(SM_ORDER
| SM_DING
, 4, 4, _("Incorrect passphrase"));
1158 q_status_message1(SM_ORDER
, 4, 4, _("Couldn't read key: %s"),(char*)openssl_error_string());
1160 /* This passphrase is no good; forget it */
1161 ps_global
->smime
->entered_passphrase
= 0;
1164 /* Indicate to the UI that we need re-entry (see mailcmd.c:process_cmd())*/
1165 if(ps_global
->smime
)
1166 ps_global
->smime
->need_passphrase
= 1;
1168 if(ps_global
->smime
){
1169 if(ps_global
->smime
->passphrase_emailaddr
){
1171 for(i
= 0; ps_global
->smime
->passphrase_emailaddr
[i
] != NULL
; i
++)
1172 fs_give((void **)&ps_global
->smime
->passphrase_emailaddr
[i
]);
1173 fs_give((void **) ps_global
->smime
->passphrase_emailaddr
);
1176 ps_global
->smime
->passphrase_emailaddr
= get_x509_subject_email(pcert
->cert
);
1182 /* This key will be cached, so we won't be called again */
1183 if(ps_global
->smime
){
1184 ps_global
->smime
->entered_passphrase
= 0;
1185 ps_global
->smime
->need_passphrase
= 0;
1197 setup_pkcs7_body_for_signature(BODY
*b
, char *description
, char *type
, char *filename
)
1199 b
->type
= TYPEAPPLICATION
;
1200 b
->subtype
= cpystr(type
);
1201 b
->encoding
= ENCBINARY
;
1202 b
->description
= cpystr(description
);
1204 b
->disposition
.type
= cpystr("attachment");
1205 set_parameter(&b
->disposition
.parameter
, "filename", filename
);
1207 set_parameter(&b
->parameter
, "name", filename
);
1212 * Look for a personal certificate matching the
1216 match_personal_cert_to_email(ADDRESS
*a
)
1218 PERSONAL_CERT
*pcert
= NULL
;
1223 if(!a
|| !a
->mailbox
|| !a
->host
)
1226 snprintf(buf
, sizeof(buf
), "%s@%s", a
->mailbox
, a
->host
);
1228 if(ps_global
->smime
){
1229 for(pcert
=(PERSONAL_CERT
*) ps_global
->smime
->personal_certs
;
1236 email
= get_x509_subject_email(pcert
->cert
);
1240 for(i
= 0; email
[i
] && strucmp(email
[i
], buf
) != 0; i
++);
1241 if(email
[i
] != NULL
) done
++;
1242 for(i
= 0; email
[i
] != NULL
; i
++)
1243 fs_give((void **)&email
[i
]);
1244 fs_give((void **)email
);
1257 * Look for a personal certificate matching the from
1258 * (or reply_to? in the given envelope)
1261 match_personal_cert(ENVELOPE
*env
)
1263 PERSONAL_CERT
*pcert
;
1265 pcert
= match_personal_cert_to_email(env
->reply_to
);
1267 pcert
= match_personal_cert_to_email(env
->from
);
1274 * Flatten the given body into its MIME representation.
1275 * Return the result in a BIO.
1278 body_to_bio(BODY
*body
)
1283 bio
= BIO_new(BIO_s_mem());
1287 pine_encode_body(body
); /* this attaches random boundary strings to multiparts */
1288 pine_write_body_header(body
, rfc822_output_func
, bio
);
1289 pine_rfc822_output_body(body
, rfc822_output_func
, bio
);
1292 * Now need to truncate by two characters since the above
1295 if((len
=BIO_ctrl_pending(bio
)) > 1){
1296 BUF_MEM
*biobuf
= NULL
;
1298 BIO_get_mem_ptr(bio
, &biobuf
);
1300 BUF_MEM_grow(biobuf
, len
-2); /* remove CRLF */
1309 bio_from_store(STORE_S
*store
)
1313 if(store
&& store
->src
== BioType
&& store
->txt
){
1314 ret
= (BIO
*) store
->txt
;
1321 * Encrypt file; given a path (char *) fp, replace the file
1322 * by an encrypted version of it. If (char *) text is not null, then
1323 * replace the text of (char *) fp by the encrypted version of (char *) text.
1326 encrypt_file(char *fp
, char *text
)
1328 const EVP_CIPHER
*cipher
= NULL
;
1329 STACK_OF(X509
) *encerts
= NULL
;
1331 PERSONAL_CERT
*pcert
;
1338 if((pcert
= ps_global
->smime
->personal_certs
) == NULL
)
1341 cipher
= EVP_aes_256_cbc();
1342 encerts
= sk_X509_new_null();
1344 if((cert
= get_cert_for(pcert
->name
)) != NULL
)
1345 sk_X509_push(encerts
, cert
);
1350 in
= BIO_new(BIO_s_mem());
1353 (void) BIO_reset(in
);
1357 if(!(in
= BIO_new_file(fp
, "rb")))
1360 BIO_read_filename(in
, fp
);
1363 if((p7
= PKCS7_encrypt(encerts
, in
, cipher
, 0)) == NULL
)
1365 BIO_set_close(in
, BIO_CLOSE
);
1367 if(!(in
= BIO_new_file(fp
, "w")))
1370 rv
= PEM_write_bio_PKCS7(in
, p7
);
1376 sk_X509_pop_free(encerts
, X509_free
);
1382 * Encrypt a message on the way out. Called from call_mailer in send.c
1383 * The body may be reallocated.
1386 encrypt_outgoing_message(METAENV
*header
, BODY
**bodyP
)
1391 const EVP_CIPHER
*cipher
= NULL
;
1392 STACK_OF(X509
) *encerts
= NULL
;
1393 STORE_S
*outs
= NULL
;
1396 BODY
*body
= *bodyP
;
1397 BODY
*newBody
= NULL
;
1400 dprint((9, "encrypt_outgoing_message()"));
1403 cipher
= EVP_aes_256_cbc();
1405 encerts
= sk_X509_new_null();
1407 /* Look for a certificate for each of the recipients */
1408 for(pf
= header
->local
; pf
&& pf
->name
; pf
= pf
->next
)
1409 if(pf
->type
== Address
&& pf
->rcptto
&& pf
->addr
&& *pf
->addr
){
1410 for(a
=*pf
->addr
; a
; a
=a
->next
){
1414 snprintf(buf
, sizeof(buf
), "%s@%s", a
->mailbox
, a
->host
);
1416 cert
= get_cert_for(buf
);
1418 sk_X509_push(encerts
,cert
);
1420 q_status_message2(SM_ORDER
, 1, 1,
1421 _("Unable to find certificate for <%s@%s>"),
1422 a
->mailbox
, a
->host
);
1429 in
= body_to_bio(body
);
1431 p7
= PKCS7_encrypt(encerts
, in
, cipher
, 0);
1433 outs
= so_get(BioType
, NULL
, EDIT_ACCESS
);
1434 out
= bio_from_store(outs
);
1436 i2d_PKCS7_bio(out
, p7
);
1437 (void) BIO_flush(out
);
1439 so_seek(outs
, 0, SEEK_SET
);
1441 newBody
= mail_newbody();
1443 newBody
->type
= TYPEAPPLICATION
;
1444 newBody
->subtype
= cpystr("pkcs7-mime");
1445 newBody
->encoding
= ENCBINARY
;
1447 newBody
->disposition
.type
= cpystr("attachment");
1448 set_parameter(&newBody
->disposition
.parameter
, "filename", "smime.p7m");
1450 newBody
->description
= cpystr("S/MIME Encrypted Message");
1451 set_parameter(&newBody
->parameter
, "smime-type", "enveloped-data");
1452 set_parameter(&newBody
->parameter
, "name", "smime.p7m");
1454 newBody
->contents
.text
.data
= (unsigned char *) outs
;
1464 sk_X509_pop_free(encerts
, X509_free
);
1466 dprint((9, "encrypt_outgoing_message returns %d", result
));
1472 * Plonk the contents (mime headers and body) of the given
1473 * section of a message to a BIO_s_mem BIO object.
1476 raw_part_to_bio(long msgno
, const char *section
)
1482 bio
= BIO_new(BIO_s_mem());
1486 (void) BIO_reset(bio
);
1488 /* First grab headers of the chap */
1489 text
= mail_fetch_mime(ps_global
->mail_stream
, msgno
, (char*) section
, &len
, 0);
1492 BIO_write(bio
, text
, len
);
1494 /** Now grab actual body */
1495 text
= mail_fetch_body (ps_global
->mail_stream
, msgno
, (char*) section
, &len
, 0);
1497 BIO_write(bio
, text
, len
);
1516 Get (and decode) the body of the given section of msg
1519 get_part_contents(long msgno
, const char *section
)
1523 STORE_S
*store
= NULL
;
1526 store
= so_get(CharStar
, NULL
, EDIT_ACCESS
);
1528 gf_set_so_writec(&pc
,store
);
1530 err
= detach(ps_global
->mail_stream
, msgno
, (char*) section
, 0L, &len
, pc
, NULL
, 0L);
1532 gf_clear_so_writec(store
);
1534 so_seek(store
, 0, SEEK_SET
);
1545 get_pkcs7_from_part(long msgno
,const char *section
)
1547 STORE_S
*store
= NULL
;
1551 store
= get_part_contents(msgno
, section
);
1554 if(store
->src
== CharStar
){
1558 * We're reaching inside the STORE_S structure. We should
1559 * probably have a way to get the length, instead.
1561 len
= (int) (store
->eod
- store
->dp
);
1562 in
= BIO_new_mem_buf(store
->txt
, len
);
1564 else{ /* just copy it */
1567 in
= BIO_new(BIO_s_mem());
1568 (void) BIO_reset(in
);
1570 so_seek(store
, 0L, 0);
1571 while(so_readc(&c
, store
)){
1572 BIO_write(in
, &c
, 1);
1577 /* dump_bio_to_file(in, "/tmp/decoded-signature"); */
1578 if((p7
=d2i_PKCS7_bio(in
,NULL
)) == NULL
){
1593 * Try to verify a signature.
1595 * p7 - the pkcs7 object to verify
1596 * in - the plain data to verify (NULL if not detached)
1597 * out - BIO to which to write the opaque data
1600 do_signature_verify(PKCS7
*p7
, BIO
*in
, BIO
*out
)
1602 STACK_OF(X509
) *otherCerts
= NULL
;
1608 dump_bio_to_file(in
,"/tmp/verified-data");
1612 q_status_message(SM_ORDER
| SM_DING
, 2, 2,
1613 _("Couldn't verify S/MIME signature: No CA Certs were loaded"));
1618 result
= PKCS7_verify(p7
, otherCerts
, s_cert_store
, in
, out
, 0);
1621 q_status_message(SM_ORDER
, 1, 1, _("S/MIME signature verified ok"));
1624 err
= ERR_peek_error_line_data(NULL
, NULL
, &data
, NULL
);
1626 if(out
&& err
==ERR_PACK(ERR_LIB_PKCS7
,PKCS7_F_PKCS7_VERIFY
,PKCS7_R_CERTIFICATE_VERIFY_ERROR
)){
1628 /* Retry verification so we can get the plain text */
1629 /* Might be better to reimplement PKCS7_verify here? */
1631 PKCS7_verify(p7
, otherCerts
, s_cert_store
, in
, out
, PKCS7_NOVERIFY
);
1634 q_status_message1(SM_ORDER
| SM_DING
, 3, 3,
1635 _("Couldn't verify S/MIME signature: %s"), (char*) openssl_error_string());
1638 /* now try to extract the certificates of any signers */
1640 STACK_OF(X509
) *signers
;
1643 signers
= PKCS7_get0_signers(p7
, NULL
, 0);
1646 for(i
=0; i
<sk_X509_num(signers
); i
++){
1648 X509
*x
= sk_X509_value(signers
,i
);
1654 email
= get_x509_subject_email(x
);
1658 for(i
= 0; email
[i
] != NULL
; i
++){
1659 cert
= get_cert_for(email
[i
]);
1663 save_cert_for(email
[i
], x
);
1664 fs_give((void **) &email
[i
]);
1666 fs_give((void **) email
);
1670 sk_X509_free(signers
);
1678 free_smime_body_sparep(void **sparep
)
1680 if(sparep
&& *sparep
){
1681 PKCS7_free((PKCS7
*) (*sparep
));
1688 * Given a multipart body of type multipart/signed, attempt to verify it.
1689 * Returns non-zero if the body was changed.
1692 do_detached_signature_verify(BODY
*b
, long msgno
, char *section
)
1697 int result
, modified_the_body
= 0;
1701 dprint((9, "do_detached_signature_verify(msgno=%ld type=%d subtype=%s section=%s)", msgno
, b
->type
, b
->subtype
? b
->subtype
: "NULL", (section
&& *section
) ? section
: (section
!= NULL
) ? "Top" : "NULL"));
1704 snprintf(newSec
, sizeof(newSec
), "%s%s1", section
? section
: "", (section
&& *section
) ? "." : "");
1705 in
= raw_part_to_bio(msgno
, newSec
);
1709 snprintf(newSec
, sizeof(newSec
), "%s%s2", section
? section
: "", (section
&& *section
) ? "." : "");
1710 p7
= get_pkcs7_from_part(msgno
, newSec
);
1715 result
= do_signature_verify(p7
, in
, NULL
);
1718 fs_give((void**) &b
->subtype
);
1720 b
->subtype
= cpystr(OUR_PKCS7_ENCLOSURE_SUBTYPE
);
1721 b
->encoding
= ENC8BIT
;
1724 fs_give ((void**) &b
->description
);
1726 what_we_did
= result
? _("This message was cryptographically signed.") :
1727 _("This message was cryptographically signed but the signature could not be verified.");
1729 b
->description
= cpystr(what_we_did
);
1736 /* p is signed plaintext */
1738 mail_free_body_part(&p
->next
); /* hide the pkcs7 from the viewer */
1742 modified_the_body
= 1;
1748 return modified_the_body
;
1753 find_certificate_matching_recip_info(PKCS7_RECIP_INFO
*ri
)
1755 PERSONAL_CERT
*x
= NULL
;
1757 if(ps_global
->smime
){
1758 for(x
= (PERSONAL_CERT
*) ps_global
->smime
->personal_certs
; x
; x
=x
->next
){
1763 if(!X509_NAME_cmp(ri
->issuer_and_serial
->issuer
,mine
->cert_info
->issuer
) &&
1764 !ASN1_INTEGER_cmp(ri
->issuer_and_serial
->serial
,mine
->cert_info
->serialNumber
)){
1774 static PERSONAL_CERT
*
1775 find_certificate_matching_pkcs7(PKCS7
*p7
)
1778 STACK_OF(PKCS7_RECIP_INFO
) *recips
;
1779 PERSONAL_CERT
*x
= NULL
;
1781 recips
= p7
->d
.enveloped
->recipientinfo
;
1783 for(i
=0; i
<sk_PKCS7_RECIP_INFO_num(recips
); i
++){
1784 PKCS7_RECIP_INFO
*ri
;
1786 ri
= sk_PKCS7_RECIP_INFO_value(recips
, i
);
1788 if((x
=find_certificate_matching_recip_info(ri
))!=0){
1796 /* decrypt an encrypted file.
1797 Args: fp - the path to the encrypted file.
1798 rv - a code that thells the caller what happened inside the function
1799 Returns the decoded text allocated in a char *, whose memory must be
1804 decrypt_file(char *fp
, int *rv
)
1808 BIO
*in
= NULL
, *out
= NULL
;
1809 EVP_PKEY
*pkey
= NULL
, *key
= NULL
;
1810 PERSONAL_CERT
*pcert
= NULL
;
1812 STORE_S
*outs
= NULL
, *store
, *ins
;
1814 long unsigned int len
;
1819 if((text
= read_file(fp
, 0)) == NULL
)
1822 tmp
= fs_get(strlen(text
) + (strlen(text
) << 6) + 1);
1823 for(j
= 0, i
= strlen("-----BEGIN PKCS7-----") + 1; text
[i
] != '\0'
1824 && text
[i
] != '-'; j
++, i
++)
1828 ret
= rfc822_base64(tmp
, strlen(tmp
), &len
);
1830 if((in
= BIO_new_mem_buf((char *)ret
, len
)) != NULL
){
1831 p7
= d2i_PKCS7_bio(in
, NULL
);
1835 if(text
) fs_give((void **)&text
);
1836 if(ret
) fs_give((void **)&ret
);
1838 if((pcert
= ps_global
->smime
->personal_certs
) == NULL
)
1841 if((i
= load_private_key(pcert
)) == 0
1843 && ps_global
->smime
->need_passphrase
1844 && !ps_global
->smime
->already_auto_asked
)
1846 ps_global
->smime
->already_auto_asked
= 1;
1847 if(pith_opt_smime_get_passphrase
){
1848 switch((*pith_opt_smime_get_passphrase
)()){
1849 case 0 : i
= load_private_key(pcert
);
1855 default: break; /* repeat until we cancel */
1864 if((key
= pcert
->key
) == NULL
)
1867 recip
= get_cert_for(pcert
->name
);
1868 out
= BIO_new(BIO_s_mem());
1869 (void) BIO_reset(out
);
1871 i
= PKCS7_decrypt(p7
, key
, recip
, out
, 0);
1873 if(F_OFF(F_REMEMBER_SMIME_PASSPHRASE
,ps_global
))
1874 forget_private_keys();
1877 q_status_message1(SM_ORDER
, 1, 1, _("Error decrypting: %s"),
1878 (char*) openssl_error_string());
1882 BIO_get_mem_data(out
, &tmp
);
1894 * Try to decode (decrypt or verify a signature) a PKCS7 body
1895 * Returns non-zero if something was changed.
1898 do_decoding(BODY
*b
, long msgno
, const char *section
)
1900 int modified_the_body
= 0;
1904 EVP_PKEY
*key
= NULL
;
1905 PERSONAL_CERT
*pcert
= NULL
;
1906 char *what_we_did
= "";
1909 dprint((9, "do_decoding(msgno=%ld type=%d subtype=%s section=%s)", msgno
, b
->type
, b
->subtype
? b
->subtype
: "NULL", (section
&& *section
) ? section
: (section
!= NULL
) ? "Top" : "NULL"));
1914 * Extract binary data from part to an in-memory store
1917 if(b
->sparep
){ /* already done */
1918 p7
= (PKCS7
*) b
->sparep
;
1922 p7
= get_pkcs7_from_part(msgno
, section
&& *section
? section
: "1");
1924 q_status_message1(SM_ORDER
, 2, 2, "Couldn't load PKCS7 object: %s",
1925 (char*) openssl_error_string());
1930 * Save the PKCS7 object for later dealings by the user interface.
1931 * It will be cleaned up when the body is garbage collected.
1936 if(PKCS7_type_is_signed(p7
)){
1939 out
= BIO_new(BIO_s_mem());
1940 (void) BIO_reset(out
);
1941 BIO_puts(out
, "MIME-Version: 1.0\r\n"); /* needed so rfc822_parse_msg_full believes it's MIME */
1943 sigok
= do_signature_verify(p7
, NULL
, out
);
1945 /* shouldn't really duplicate these messages */
1946 what_we_did
= sigok
? _("This message was cryptographically signed.") :
1947 _("This message was cryptographically signed but the signature could not be verified.");
1949 /* make sure it's null terminated */
1950 BIO_write(out
, null
, 1);
1952 else if(!PKCS7_type_is_enveloped(p7
)){
1953 q_status_message(SM_ORDER
, 1, 1, "PKCS7 object not recognised.");
1956 else{ /* It *is* enveloped */
1959 what_we_did
= _("This message was encrypted.");
1961 /* now need to find a cert that can decrypt this */
1962 pcert
= find_certificate_matching_pkcs7(p7
);
1965 q_status_message(SM_ORDER
, 3, 3, _("Couldn't find the certificate needed to decrypt."));
1969 recip
= pcert
->cert
;
1971 if(!load_private_key(pcert
)
1973 && ps_global
->smime
->need_passphrase
1974 && !ps_global
->smime
->already_auto_asked
){
1975 /* Couldn't load key with blank password, ask user */
1976 ps_global
->smime
->already_auto_asked
= 1;
1977 if(pith_opt_smime_get_passphrase
){
1978 (*pith_opt_smime_get_passphrase
)();
1979 load_private_key(pcert
);
1987 out
= BIO_new(BIO_s_mem());
1988 (void) BIO_reset(out
);
1989 BIO_puts(out
, "MIME-Version: 1.0\r\n");
1991 decrypt_result
= PKCS7_decrypt(p7
, key
, recip
, out
, 0);
1993 if(F_OFF(F_REMEMBER_SMIME_PASSPHRASE
,ps_global
))
1994 forget_private_keys();
1996 if(!decrypt_result
){
1997 q_status_message1(SM_ORDER
, 1, 1, _("Error decrypting: %s"),
1998 (char*) openssl_error_string());
2002 BIO_write(out
, null
, 1);
2006 * We've now produced a flattened MIME object in BIO out.
2007 * It needs to be turned back into a BODY.
2016 BUF_MEM
*bptr
= NULL
;
2018 BIO_get_mem_ptr(out
, &bptr
);
2022 /* look for start of body */
2023 bstart
= strstr(h
, "\r\n\r\n");
2026 q_status_message(SM_ORDER
, 3, 3, _("Encrypted data couldn't be parsed."));
2029 bstart
+= 4; /* skip over CRLF*2 */
2031 INIT(&s
, mail_string
, bstart
, strlen(bstart
));
2032 rfc822_parse_msg_full(&env
, &body
, h
, bstart
-h
-2, &s
, BADHOST
, 0, 0);
2033 mail_free_envelope(&env
); /* Don't care about this */
2036 * Now convert original body (application/pkcs7-mime)
2037 * to a multipart body with one sub-part (the decrypted body).
2038 * Note that the sub-part may also be multipart!
2041 b
->type
= TYPEMULTIPART
;
2043 fs_give((void**) &b
->subtype
);
2046 * This subtype is used in mailview.c to annotate the display of
2047 * encrypted or signed messages. We know for sure then that it's a PKCS7
2048 * part because the sparep field is set to the PKCS7 object (see above).
2050 b
->subtype
= cpystr(OUR_PKCS7_ENCLOSURE_SUBTYPE
);
2051 b
->encoding
= ENC8BIT
;
2054 fs_give((void**) &b
->description
);
2056 b
->description
= cpystr(what_we_did
);
2058 if(b
->disposition
.type
)
2059 fs_give((void **) &b
->disposition
.type
);
2061 if(b
->contents
.text
.data
)
2062 fs_give((void **) &b
->contents
.text
.data
);
2065 mail_free_body_parameter(&b
->parameter
);
2067 /* Allocate mem for the sub-part, and copy over the contents of our parsed body */
2068 b
->nested
.part
= fs_get(sizeof(PART
));
2069 b
->nested
.part
->body
= *body
;
2070 b
->nested
.part
->next
= NULL
;
2072 fs_give((void**) &body
);
2075 * IMPORTANT BIT: set the body->contents.text.data elements to contain the decrypted
2076 * data. Otherwise, it'll try to load it from the original data. Eek.
2078 create_local_cache(bstart
, &b
->nested
.part
->body
);
2080 modified_the_body
= 1;
2088 return modified_the_body
;
2093 * Recursively handle PKCS7 bodies in our message.
2095 * Returns non-zero if some fiddling was done.
2098 do_fiddle_smime_message(BODY
*b
, long msgno
, char *section
)
2100 int modified_the_body
= 0;
2105 dprint((9, "do_fiddle_smime_message(msgno=%ld type=%d subtype=%s section=%s)", msgno
, b
->type
, b
->subtype
? b
->subtype
: "NULL", (section
&& *section
) ? section
: (section
!= NULL
) ? "Top" : "NULL"));
2107 if(is_pkcs7_body(b
)){
2109 if(do_decoding(b
, msgno
, section
)){
2111 * b should now be a multipart message:
2112 * fiddle it too in case it's been multiply-encrypted!
2116 modified_the_body
= 1;
2120 if(b
->type
==TYPEMULTIPART
|| MIME_MSG(b
->type
, b
->subtype
)){
2126 if(MIME_MULT_SIGNED(b
->type
, b
->subtype
)){
2130 * Ahah. We have a multipart signed entity.
2133 * part 1 (signed thing)
2134 * part 2 (the pkcs7 signature)
2136 * We're going to convert that to
2138 * Multipart/OUR_PKCS7_ENCLOSURE_SUBTYPE
2139 * part 1 (signed thing)
2140 * part 2 has been freed
2142 * We also extract the signature from part 2 and save it
2143 * in the multipart body->sparep, and we add a description
2144 * in the multipart body->description.
2147 * The results of a decrypted message will be similar. It
2150 * Multipart/OUR_PKCS7_ENCLOSURE_SUBTYPE
2151 * part 1 (decrypted thing)
2154 modified_the_body
+= do_detached_signature_verify(b
, msgno
, section
);
2156 else if(MIME_MSG(b
->type
, b
->subtype
)){
2157 modified_the_body
+= do_fiddle_smime_message(b
->nested
.msg
->body
, msgno
, section
);
2161 for(p
=b
->nested
.part
,partNum
=1; p
; p
=p
->next
,partNum
++){
2163 /* Append part number to the section string */
2165 snprintf(newSec
, sizeof(newSec
), "%s%s%d", section
, *section
? "." : "", partNum
);
2167 modified_the_body
+= do_fiddle_smime_message(&p
->body
, msgno
, newSec
);
2172 return modified_the_body
;
2177 * Fiddle a message in-place by decrypting/verifying S/MIME entities.
2178 * Returns non-zero if something was changed.
2181 fiddle_smime_message(BODY
*b
, long msgno
)
2183 return do_fiddle_smime_message(b
, msgno
, "");
2187 /********************************************************************************/
2191 * Output a string in a distinctive style
2194 gf_puts_uline(char *txt
, gf_io_t pc
)
2196 pc(TAG_EMBED
); pc(TAG_BOLDON
);
2198 pc(TAG_EMBED
); pc(TAG_BOLDOFF
);
2203 * Sign a message. Called from call_mailer in send.c.
2205 * This takes the header for the outgoing message as well as a pointer
2206 * to the current body (which may be reallocated).
2209 sign_outgoing_message(METAENV
*header
, BODY
**bodyP
, int dont_detach
)
2211 STORE_S
*outs
= NULL
;
2212 BODY
*body
= *bodyP
;
2213 BODY
*newBody
= NULL
;
2216 PERSONAL_CERT
*pcert
;
2221 int flags
= dont_detach
? 0 : PKCS7_DETACHED
;
2223 dprint((9, "sign_outgoing_message()"));
2227 /* Look for a private key matching the sender address... */
2229 pcert
= match_personal_cert(header
->env
);
2232 q_status_message(SM_ORDER
, 3, 3, _("Couldn't find the certificate needed to sign."));
2236 if(!load_private_key(pcert
) && ps_global
->smime
&& ps_global
->smime
->need_passphrase
){
2237 /* Couldn't load key with blank password, try again */
2238 if(pith_opt_smime_get_passphrase
){
2239 (*pith_opt_smime_get_passphrase
)();
2240 load_private_key(pcert
);
2247 in
= body_to_bio(body
);
2250 dump_bio_to_file(in
,"/tmp/signed-data");
2253 p7
= PKCS7_sign(pcert
->cert
, pcert
->key
, NULL
, in
, flags
);
2255 if(F_OFF(F_REMEMBER_SMIME_PASSPHRASE
,ps_global
))
2256 forget_private_keys();
2259 q_status_message(SM_ORDER
, 1, 1, _("Error creating signed object."));
2263 outs
= so_get(BioType
, NULL
, EDIT_ACCESS
);
2264 out
= bio_from_store(outs
);
2266 i2d_PKCS7_bio(out
, p7
);
2267 (void) BIO_flush(out
);
2269 so_seek(outs
, 0, SEEK_SET
);
2271 if((flags
&PKCS7_DETACHED
)==0){
2273 /* the simple case: the signed data is in the pkcs7 object */
2275 newBody
= mail_newbody();
2277 setup_pkcs7_body_for_signature(newBody
, "S/MIME Cryptographically Signed Message", "pkcs7-mime", "smime.p7m");
2279 newBody
->contents
.text
.data
= (unsigned char *) outs
;
2288 * We have to create a new body as follows:
2290 * multipart/signed; blah blah blah
2291 * reference to existing body
2296 newBody
= mail_newbody();
2298 newBody
->type
= TYPEMULTIPART
;
2299 newBody
->subtype
= cpystr("signed");
2300 newBody
->encoding
= ENC7BIT
;
2302 set_parameter(&newBody
->parameter
, "protocol", "application/pkcs7-signature");
2303 set_parameter(&newBody
->parameter
, "micalg", "sha1");
2305 p1
= mail_newbody_part();
2306 p2
= mail_newbody_part();
2309 * This is nasty. We're just copying the body in here,
2310 * but since our newBody is freed at the end of call_mailer,
2311 * we mustn't let this body (the original one) be freed twice.
2313 p1
->body
= *body
; /* ARRGH. This is special cased at the end of call_mailer */
2317 setup_pkcs7_body_for_signature(&p2
->body
, "S/MIME Cryptographic Signature", "pkcs7-signature", "smime.p7s");
2318 p2
->body
.contents
.text
.data
= (unsigned char *) outs
;
2320 newBody
->nested
.part
= p1
;
2332 dprint((9, "sign_outgoing_message returns %d", result
));
2338 new_smime_struct(void)
2340 SMIME_STUFF_S
*ret
= NULL
;
2342 ret
= (SMIME_STUFF_S
*) fs_get(sizeof(*ret
));
2343 memset((void *) ret
, 0, sizeof(*ret
));
2344 ret
->publictype
= Nada
;
2351 free_smime_struct(SMIME_STUFF_S
**smime
)
2353 if(smime
&& *smime
){
2354 if((*smime
)->passphrase_emailaddr
){
2356 for(i
= 0; (*smime
)->passphrase_emailaddr
[i
] != NULL
; i
++)
2357 fs_give((void **) &(*smime
)->passphrase_emailaddr
[i
]);
2358 fs_give((void **) (*smime
)->passphrase_emailaddr
);
2361 if((*smime
)->publicpath
)
2362 fs_give((void **) &(*smime
)->publicpath
);
2364 if((*smime
)->publiccertlist
)
2365 free_certlist(&(*smime
)->publiccertlist
);
2367 if((*smime
)->publiccontent
)
2368 fs_give((void **) &(*smime
)->publiccontent
);
2370 if((*smime
)->privatepath
)
2371 fs_give((void **) &(*smime
)->privatepath
);
2373 if((*smime
)->personal_certs
){
2376 pc
= (PERSONAL_CERT
*) (*smime
)->personal_certs
;
2377 free_personal_certs(&pc
);
2378 (*smime
)->personal_certs
= NULL
;
2381 if((*smime
)->privatecontent
)
2382 fs_give((void **) &(*smime
)->privatecontent
);
2384 if((*smime
)->capath
)
2385 fs_give((void **) &(*smime
)->capath
);
2387 if((*smime
)->cacontent
)
2388 fs_give((void **) &(*smime
)->cacontent
);
2390 fs_give((void **) smime
);