summaryrefslogtreecommitdiff
path: root/pith
diff options
context:
space:
mode:
Diffstat (limited to 'pith')
-rw-r--r--pith/adrbklib.c42
-rw-r--r--pith/adrbklib.h2
-rw-r--r--pith/conf.c2
-rw-r--r--pith/conftype.h1
-rw-r--r--pith/mimedesc.c7
-rw-r--r--pith/pattern.c6
-rw-r--r--pith/pine.hlp119
-rw-r--r--pith/reply.c2
-rw-r--r--pith/send.c18
-rw-r--r--pith/smime.c196
-rw-r--r--pith/smime.h11
-rw-r--r--pith/smkeys.c71
12 files changed, 276 insertions, 201 deletions
diff --git a/pith/adrbklib.c b/pith/adrbklib.c
index 51979bdc..bdd505fb 100644
--- a/pith/adrbklib.c
+++ b/pith/adrbklib.c
@@ -6026,3 +6026,45 @@ add_forced_entries(AdrBk *abook)
}
}
}
+
+/* Go through the list of addressbooks and check if any
+ * of them point to the given stream.
+ */
+int
+any_addressbook_in_remote_stream(MAILSTREAM *stream)
+{
+ int rv = 0;
+ int i = 0, num = 0;
+ char *nickname = NULL;
+ char *filename = NULL;
+ char *q = NULL;
+
+ do{
+ if(ps_global->VAR_ADDRESSBOOK &&
+ ps_global->VAR_ADDRESSBOOK[num] &&
+ ps_global->VAR_ADDRESSBOOK[num][0]){
+ q = ps_global->VAR_ADDRESSBOOK[num++];
+ i = num;
+ }
+ else if(ps_global->VAR_GLOB_ADDRBOOK &&
+ ps_global->VAR_GLOB_ADDRBOOK[i-num] &&
+ ps_global->VAR_GLOB_ADDRBOOK[i-num][0]){
+ q = ps_global->VAR_GLOB_ADDRBOOK[i - num];
+ i++;
+ } else q = NULL;
+ if(q != NULL){
+ get_pair(q, &nickname, &filename, 0, 0);
+
+ if(nickname) fs_give((void **)&nickname);
+
+ if(filename){
+ if(*filename == '{'
+ && same_stream(filename, stream) != NULL)
+ rv = 1;
+ fs_give((void **)&filename);
+ }
+ }
+ } while (rv == 0 && q != NULL);
+
+ return rv;
+}
diff --git a/pith/adrbklib.h b/pith/adrbklib.h
index 9fbeb37c..505a8525 100644
--- a/pith/adrbklib.h
+++ b/pith/adrbklib.h
@@ -852,6 +852,6 @@ void adrbk_maintenance(void);
char **parse_addrlist(char *);
char *skip_to_next_addr(char *);
void add_forced_entries(AdrBk *);
-
+int any_addressbook_in_remote_stream(MAILSTREAM *);
#endif /* PITH_ADRBKLIB_INCLUDED */
diff --git a/pith/conf.c b/pith/conf.c
index 4bc9481b..81eed75b 100644
--- a/pith/conf.c
+++ b/pith/conf.c
@@ -3259,6 +3259,8 @@ feature_list(int index)
F_REMEMBER_SMIME_PASSPHRASE, h_config_smime_remember_passphrase, PREF_HIDDEN, 0},
{"smime-sign-by-default", "S/MIME -- Sign by Default",
F_SIGN_DEFAULT_ON, h_config_smime_sign_by_default, PREF_HIDDEN, 0},
+ {"smime-use-store-only", "S/MIME -- Validate Using Certificate Store Only",
+ F_USE_CERT_STORE_ONLY, h_config_smime_use_cert_store, PREF_HIDDEN, 1},
#ifdef APPLEKEYCHAIN
{"publiccerts-in-keychain", "S/MIME -- Public Certs in MacOS Keychain",
F_PUBLICCERTS_IN_KEYCHAIN, h_config_smime_pubcerts_in_keychain, PREF_HIDDEN, 0},
diff --git a/pith/conftype.h b/pith/conftype.h
index 16e8de25..8ba7941c 100644
--- a/pith/conftype.h
+++ b/pith/conftype.h
@@ -544,6 +544,7 @@ typedef enum {
F_SIGN_DEFAULT_ON,
F_ENCRYPT_DEFAULT_ON,
F_REMEMBER_SMIME_PASSPHRASE,
+ F_USE_CERT_STORE_ONLY,
#ifdef APPLEKEYCHAIN
F_PUBLICCERTS_IN_KEYCHAIN,
#endif
diff --git a/pith/mimedesc.c b/pith/mimedesc.c
index 5b9db1b4..8a1d7f7d 100644
--- a/pith/mimedesc.c
+++ b/pith/mimedesc.c
@@ -579,12 +579,15 @@ type_desc(int type, char *subtype, PARAMETER *params, PARAMETER *disp_params, in
}
if(full && type != TYPEMULTIPART && type != TYPEMESSAGE){
+ unsigned char decodebuf[10000];
if((parmval = parameter_val(params, "name")) != NULL){
- snprintf(p, sizeof(type_d)-(p-type_d), " (Name: \"%s\")", parmval);
+ rfc1522_decode_to_utf8(decodebuf, sizeof(decodebuf), parmval);
+ snprintf(p, sizeof(type_d)-(p-type_d), " (Name: \"%s\")", decodebuf);
fs_give((void **) &parmval);
}
else if((parmval = parameter_val(disp_params, "filename")) != NULL){
- snprintf(p, sizeof(type_d)-(p-type_d), " (Filename: \"%s\")", parmval);
+ rfc1522_decode_to_utf8(decodebuf, sizeof(decodebuf), parmval);
+ snprintf(p, sizeof(type_d)-(p-type_d), " (Filename: \"%s\")", decodebuf);
fs_give((void **) &parmval);
}
}
diff --git a/pith/pattern.c b/pith/pattern.c
index 3a258e7c..0b2eaf58 100644
--- a/pith/pattern.c
+++ b/pith/pattern.c
@@ -3,8 +3,8 @@ static char rcsid[] = "$Id: pattern.c 1204 2009-02-02 19:54:23Z hubert@u.washing
#endif
/*
* ========================================================================
- * Copyright 2006-2009 University of Washington
* Copyright 2013-2014 Eduardo Chappa
+ * Copyright 2006-2009 University of Washington
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -4764,7 +4764,9 @@ match_pattern(PATGRP_S *patgrp, MAILSTREAM *stream, SEARCHSET *searchset,
}
if(in_client_callback && is_imap_stream(stream)
- && (patgrp->alltext || patgrp->bodytext))
+ && (patgrp->alltext || patgrp->bodytext
+ || (patgrp->inabook != IAB_EITHER
+ && any_addressbook_in_remote_stream(stream))))
return(-1);
pgm = match_pattern_srchpgm(patgrp, stream, searchset);
diff --git a/pith/pine.hlp b/pith/pine.hlp
index b296f024..6377dabb 100644
--- a/pith/pine.hlp
+++ b/pith/pine.hlp
@@ -140,7 +140,7 @@ with help text for the config screen and the composer that didn't have any
reasonable place to be called from.
Dummy change to get revision in pine.hlp
============= h_revision =================
-Alpine Commit 61 2014-05-02 18:29:37
+Alpine Commit 62 2014-05-17 16:49:55
============= h_news =================
<HTML>
<HEAD>
@@ -162,7 +162,7 @@ Version <!--#echo var="ALPINE_VERSION"--> (<!--#echo var="ALPINE_REVISION"-->)
<P>
Alpine is an &quot;Alternatively Licensed Program for Internet
-News and Email&quot; produced until 2008 by the University of Washington.
+News and Email&quot; produced until 2009 by the University of Washington.
It is intended to be an easy-to-use program for
sending, receiving, and filing Internet electronic mail messages and
bulletin board (Netnews) messages. Alpine is designed to run on a wide
@@ -184,6 +184,11 @@ Additions include:
<LI> Upgrade UW-IMAP to Panda IMAP from
<A HREF="https://github.com/jonabbey/panda-imap">https://github.com/jonabbey/panda-imap</A>.
<LI> S/MIME: Add screen to manage certificates.
+ <LI> S/MIME: Signatures are validated using the user's certificates instead
+ of the ones included in the message. Behavior can be disabled by
+ disabling the option <A href="h_config_smime_use_cert_store">
+ <!--#echo var="FEAT_smime-use-storey-only"--></A>, which is enabled
+ by default.
<LI> S/MIME: sign messages using intermediate certificates when needed
and possible.
<LI> S/MIME: validation of certificates for servers that modify signed
@@ -192,7 +197,11 @@ Additions include:
encrypted second, so that they can be decoded by other clients.
<LI> S/MIME: add the sender certificate to the list of certificates in
encrypted messages to make it possible for the sender to decrypt
- the message they sent.
+ the message they sent.
+ <LI> S/MIME: When transferring certificates to a local container, create
+ container with default names PublicContainer, PrivateContainer and
+ CAContainer, as appropriate for these files, unless the user has
+ provided some other names.
<LI> Add support to selective expunge through a subcommand of the
select-apply commands. Read more in the <A
HREF="h_index_cmd_expunge">help</A> for the expunge command.
@@ -235,6 +244,8 @@ Additions include:
<LI> Pico: Justification works without need of a predefined quote
string. This allows justification of blocks of text that are
indented with spaces.
+ <LI> Decode the name of attachment names, so they can be written as part
+ of the description of the part.
<LI> Check bounds and tie strings off to improve security. Contributed
by James Jerkins.
<LI> Replace tabs by spaces in From and Subject fields to control for
@@ -267,10 +278,21 @@ Bugs that have been addressed include:
and Stefan Mueller.
<LI> S/MIME: Certificates are lost when using a pinerc file outside of the
home directory.
- <LI> S/MIME: accessing the S/MIME configuration screen would deinitialize
+ <LI> S/MIME: Accessing the S/MIME configuration screen would deinitialize
SMIME making it not possible to sign or encrypt messages.
+ <LI> S/MIME: Forwarding a signed message might make the body contain mime
+ information that is not part of the body, and hence making the body
+ of the message seem wrong.
<LI> Crash when tcp connection to NNTP server was lost after connection
had been established, but lost immediately afterwards.
+ <LI> Crash with message &quot;lock when already locked&quot;, when painting
+ an index was based on scores that needed information from a remote
+ addressbook in the same server as the folder opened. Reported by
+ Peter Koellner.
+ <LI> Alpine cannot handle correctly some characters in the Windows-1256
+ character set, which might lead to a crash or a corruption in the
+ screen. Work was done to contain the bug. A more complete fix will
+ be done in a future release. Reported by Professor Robert Funnell.
<LI> WebAlpine: add _GNU_SOURCE to make pubcookie build.
<LI> WebAlpine: fail to build with debug disabled. Fix from Sam Hathaway.
<LI> Save command did not warn of existence of a message with a deleted
@@ -294,7 +316,7 @@ Bugs that have been addressed include:
$alpine_TCLINC instead of $alpine_TCLINC/tcl.h. Reported and fixed
by Werner Scheinast.
<LI> Move SSL configurations from UW-IMAP to configure script, and
- update OpenSSL configuration for Mac OSX.
+ update OpenSSL configuration for Mac OS X.
<LI> Remove -lregex from linker flags when building --with-supplied-regex.
</UL>
<P>
@@ -357,7 +379,7 @@ Additions include:
<UL>
<LI> Quota report for IMAP folders that support it (press the &quot;@&quot; command in the index screen of such folder).
<LI> Search a folder for the content of any header with the &quot;;&quot; command.
- <LI> Foreign characters are decoded correctly in IMAP folders.
+ <LI> Foreign characters are decoded correctly in IMAP folder names.
<LI> Question about breaking connection to slow servers includes their name.
<LI> Internal x-alpine-help: resource locator for sending links to internal help.
<LI> OpenSuse: Alpine find location of OpenSSL certificates.
@@ -380,7 +402,7 @@ Bugs that have been addressed include:
<LI> Not display of login prompt during initial keystrokes.
<LI> justification of long urls breaks them.
<LI> Incorrect New Mail message when envelope is not available.
- <LI> Inorrect display of PREFDATE, PREFDATETIME and PREFTIME tokens.
+ <LI> Incorrect display of PREFDATE, PREFDATETIME and PREFTIME tokens.
<LI> Crash when resizing the screen after display of LDAP search.
<LI> Crash when redrawing screen while opening a remote folder collection.
<LI> Infinite loop in scrolltool function during notification of new mail.
@@ -713,7 +735,7 @@ version <!--#echo var="C_CLIENT_VERSION"-->.
Alpine was developed until 2009 by the Office of Computing
&amp; Communications at the University of Washington in Seattle.
Since then, the effort of developing Alpine has been continued by
-a community of volunteers who make a good software even better!
+a community of volunteers who make good software even better!
<P>
Alpine Copyright 2013-2014 Eduardo Chappa,
@@ -1535,7 +1557,7 @@ employer, ... ; or
</UL>
Due to the large number of Alpine installations worldwide, and because we
-receive no funding for it, the Alpine development team <B>cannot provide
+receive no funding for it, the University of Washington <B>cannot provide
individual support services outside the University of Washington</B>.
<P>
If you have no local computing support to turn to, the worldwide <b>comp.mail.pine</b>
@@ -1599,13 +1621,14 @@ select Setup/Config to see many of the options available to you. Also note
that all screens have context-sensitive help text available.<P>
<!--chtml if pinemode="phone_home"-->
SPECIAL REQUEST:
-This software is made available as a public service of the
-University of Washington in Seattle. We are no longer actively developing
-the software, but it is still helpful to us to have an idea of how many
-people are using Alpine. Are you willing to be counted as an Alpine user? Pressing
+This software was originally created and maintained as a public
+service by the University of Washington until 2009; updates are made
+available as a public service of the Alpine community. It is always
+helpful to have an idea of how many users are using Alpine. Are you
+willing to be counted as an Alpine user? Pressing
<A HREF="X-Alpine-Phone-Home:">Return</A>
will send an anonymous (meaning, your real email address will not be revealed)
-message to the Alpine team at the University of Washington for purposes of tallying.
+message to the Alpine developers for purposes of tallying.
<P>
<!--To Exit this screen and continue your Alpine session press "E".-->
<!--chtml else-->
@@ -1632,13 +1655,14 @@ The Release Notes may be viewed by pressing
<P>
<!--chtml if pinemode="phone_home"-->
SPECIAL REQUEST:
-This software is made available as a public service of the
-University of Washington in Seattle. We are no longer actively developing
-the software, but it is still helpful to us to have an idea of how many
-people are using Alpine. Are you willing to be counted as an Alpine user? Pressing
+This software was originally created and maintained as a public
+service by the University of Washington until 2009; updates are made
+available as a public service of the Alpine community. It is always
+helpful to have an idea of how many users are using Alpine. Are you
+willing to be counted as an Alpine user? Pressing
<A HREF="X-Alpine-Phone-Home:">Return</A>
will send an anonymous (meaning, your real email address will not be revealed)
-message to the Alpine team at the University of Washington for purposes of tallying.
+message to the Alpine developers for purposes of tallying.
<P>
<!--To Exit this screen and continue your Alpine session press "E".-->
<!--chtml else-->
@@ -1662,14 +1686,15 @@ documented in the Release Notes, which may be viewed by pressing
<P>
<!--chtml if pinemode="phone_home"-->
SPECIAL REQUEST:
-This software is made available as a public service of the
-University of Washington in Seattle. We are no longer actively developing
-the software, but it is still helpful to us to have an idea of how many
-people are using Alpine. Are you willing to be counted as an Alpine user? Pressing
+This software was originally created and maintained as a public
+service by the University of Washington until 2009; updates are made
+available as a public service of the Alpine community. It is always
+helpful to have an idea of how many users are using Alpine. Are you
+willing to be counted as an Alpine user? Pressing
<A HREF="X-Alpine-Phone-Home:">Return</A>
will send an anonymous (meaning, your real email address will not be revealed)
-message to the Alpine team at the University of Washington for purposes of tallying.
-
+message to the Alpine developers for purposes of tallying.
+<P>
<!--To Exit this screen and continue your Alpine session press "E".-->
<!--chtml else-->
To Exit this screen and continue your Alpine session press "Return".
@@ -1766,7 +1791,7 @@ The &quot;NextLink&quot; and &quot;PrevLink&quot; commands
<H1>Introduction</H1>
Alpine is an &quot;Alternatively Licensed Program for Internet
-News and Email&quot; produced until 2008 by the University of Washington.
+News and Email&quot; produced until 2009 by the University of Washington.
It is intended to be an easy-to-use program for
sending, receiving, and filing Internet electronic mail messages and
bulletin board (Netnews/Usenet) messages. Alpine supports the following
@@ -3945,6 +3970,7 @@ There are also additional details on
<li><a href="h_config_smime_encrypt_by_default">S/MIME FEATURE: <!--#echo var="FEAT_smime-encrypt-by-default"--></a>
<li><a href="h_config_smime_remember_passphrase">S/MIME FEATURE: <!--#echo var="FEAT_smime-remember-passphrase"--></a>
<li><a href="h_config_smime_sign_by_default">S/MIME FEATURE: <!--#echo var="FEAT_smime-sign-by-default"--></a>
+<li><a href="h_config_smime_use_cert_store">S/MIME FEATURE: <!--#echo var="FEAT_smime-use-store-only"--></a>
<li><a href="h_config_smime_pubcerts_in_keychain">S/MIME FEATURE: <!--#echo var="FEAT_publiccerts-in-keychain"--></a>
<li><a href="h_config_smime_cacertcon">S/MIME OPTION: <!--#echo var="VAR_smime-cacert-container"--></a>
<li><a href="h_config_smime_cacertdir">S/MIME OPTION: <!--#echo var="VAR_smime-cacert-directory"--></a>
@@ -34597,6 +34623,47 @@ certificate).
&lt;End of help on this topic&gt;
</BODY>
</HTML>
+========== h_config_smime_use_cert_store ==========
+<HTML>
+<HEAD>
+<TITLE>S/MIME FEATURE: <!--#echo var="FEAT_smime-use-store-only"--></TITLE>
+</HEAD>
+<BODY>
+<H1>S/MIME FEATURE: <!--#echo var="FEAT_smime-use-store-only"--></H1>
+
+UNIX Alpine only.
+<P>
+This feature only has an effect if your version of Alpine includes
+support for S/MIME.
+It affects Alpine's behavior when you validate a message, and should
+not be disabled, unless you are performing a test.
+<P>
+There are two important aspects of validation: validation of the message
+(that is, the message was not modified after it was sent)
+as well as validation of the identity of the sender. This option has to
+do with the latter.
+<P>
+In order to validate that the message came from the sender in the message
+and not an impersonator, Alpine can
+either use the certificates that come in the message, or the ones that
+you have personally stored. If this feature is enabled (the default) then
+Alpine will use certificates that you have already saved in your store
+and not those that come in the message to validate the sender of the
+message. This behavior helps you prevent against impersonation, because
+it is assumed that you trust the certificates that you have saved, and
+might not trust those that came with the message that you are validating.
+<P>
+<UL>
+<LI><A HREF="h_mainhelp_smime">General S/MIME help</A>
+</UL><P>
+<P>
+
+<UL>
+<LI><A HREF="h_finding_help">Finding more information and requesting help</A>
+</UL><P>
+&lt;End of help on this topic&gt;
+</BODY>
+</HTML>
========== h_config_smime_pubcerts_in_keychain ==========
<HTML>
<HEAD>
diff --git a/pith/reply.c b/pith/reply.c
index d7270a2c..60a7c489 100644
--- a/pith/reply.c
+++ b/pith/reply.c
@@ -2253,7 +2253,7 @@ forward_body(MAILSTREAM *stream, ENVELOPE *env, struct mail_bodystruct *orig_bod
&& orig_body->nested.part){
/* only operate on the signed data (not the signature) */
body = forward_body(stream, env, &orig_body->nested.part->body,
- msgno, sect_prefix, msgtext, flags);
+ msgno, section, msgtext, flags);
}
/*---- Message is multipart ----*/
else if(!(orig_body->subtype && !strucmp(orig_body->subtype,
diff --git a/pith/send.c b/pith/send.c
index 4620d1aa..191e186d 100644
--- a/pith/send.c
+++ b/pith/send.c
@@ -4245,6 +4245,7 @@ l_putc(int c)
long
pine_rfc822_output_body(struct mail_bodystruct *body, soutr_t f, void *s)
{
+ STORE_S *bodyso;
PART *part;
PARAMETER *param;
char *t, *cookie = NIL, *encode_error;
@@ -4255,6 +4256,9 @@ pine_rfc822_output_body(struct mail_bodystruct *body, soutr_t f, void *s)
dprint((4, "-- pine_rfc822_output_body: %d\n",
body ? body->type : 0));
+
+ bodyso = (STORE_S *) body->contents.text.data;
+
if(body->type == TYPEMULTIPART) { /* multipart gets special handling */
part = body->nested.part; /* first body part */
/* find cookie */
@@ -4307,8 +4311,8 @@ pine_rfc822_output_body(struct mail_bodystruct *body, soutr_t f, void *s)
dprint((4, "-- pine_rfc822_output_body: segment %ld bytes\n",
body->size.bytes));
- if(body->contents.text.data)
- gf_set_so_readc(&gc, (STORE_S *) body->contents.text.data);
+ if(bodyso)
+ gf_set_so_readc(&gc, bodyso);
else
return(1);
@@ -4316,15 +4320,15 @@ pine_rfc822_output_body(struct mail_bodystruct *body, soutr_t f, void *s)
* Don't add trailing line if it is ExternalText, which already guarantees
* a trailing newline.
*/
- add_trailing_crlf = !(((STORE_S *) body->contents.text.data)->src == ExternalText);
+ add_trailing_crlf = !(bodyso->src == ExternalText);
- so_seek((STORE_S *) body->contents.text.data, 0L, 0);
+ so_seek(bodyso, 0L, 0);
if(body->type != TYPEMESSAGE){ /* NOT encapsulated message */
char *charset;
if(body->type == TYPETEXT
- && so_attr((STORE_S *) body->contents.text.data, "edited", NULL)
+ && so_attr(bodyso, "edited", NULL)
&& (charset = parameter_val(body->parameter, "charset"))){
if(strucmp(charset, "utf-8") && strucmp(charset, "us-ascii")){
if(!strucmp(charset, "iso-2022-jp")){
@@ -4356,7 +4360,7 @@ pine_rfc822_output_body(struct mail_bodystruct *body, soutr_t f, void *s)
*/
if(body->type == TYPETEXT
&& body->encoding != ENCBASE64
- && !so_attr((STORE_S *) body->contents.text.data, "rawbody", NULL)){
+ && !so_attr(bodyso, "rawbody", NULL)){
gf_link_filter(gf_local_nvtnl, NULL);
}
@@ -4380,7 +4384,7 @@ pine_rfc822_output_body(struct mail_bodystruct *body, soutr_t f, void *s)
display_message('x');
}
- gf_clear_so_readc((STORE_S *) body->contents.text.data);
+ gf_clear_so_readc(bodyso);
if(encode_error || !l_flush_net(TRUE))
return(0);
diff --git a/pith/smime.c b/pith/smime.c
index ce7b6a70..6c49fdcc 100644
--- a/pith/smime.c
+++ b/pith/smime.c
@@ -62,7 +62,7 @@ static BIO *bio_from_store(STORE_S *store);
static STORE_S *get_part_contents(long msgno, const char *section);
static PKCS7 *get_pkcs7_from_part(long msgno, const char *section);
static int do_signature_verify(PKCS7 *p7, BIO *in, BIO *out, int silent);
-int do_detached_signature_verify(BODY *b, long msgno, char *section);
+static int do_detached_signature_verify(BODY *b, long msgno, char *section);
static PERSONAL_CERT *find_certificate_matching_pkcs7(PKCS7 *p7);
static int do_decoding(BODY *b, long msgno, const char *section);
static void free_smime_struct(SMIME_STUFF_S **smime);
@@ -90,13 +90,6 @@ static X509_STORE *s_cert_store;
static int seeded = 0;
static int egdsocket = 0;
-typedef enum {P7Type, CharType, SizedText} SpareType;
-
-typedef struct smime_sparep_t {
- SpareType sptype;
- void *data;
-} SMIME_SPARE_S;
-
void *
create_smime_sparep(SpareType stype, void *s)
{
@@ -1410,13 +1403,15 @@ copy_dir_to_container(WhichCerts which, char *contents)
int ret = 0;
BIO *bio_out = NULL, *bio_in = NULL;
char srcpath[MAXPATH+1], dstpath[MAXPATH+1], emailaddr[MAXPATH], file[MAXPATH], line[4096];
- char *tempfile = NULL;
+ char *tempfile = NULL, fpath[MAXPATH+1];
DIR *dirp;
struct dirent *d;
REMDATA_S *rd = NULL;
char *configdir = NULL;
char *configpath = NULL;
+ char *configcontainer = NULL;
char *filesuffix = NULL;
+ char *ret_dir = NULL;
dprint((9, "copy_dir_to_container(%s)", which==Public ? "Public" : which==Private ? "Private" : which==CACert ? "CACert" : "?"));
smime_init();
@@ -1429,16 +1424,19 @@ copy_dir_to_container(WhichCerts which, char *contents)
if(which == Public){
configdir = ps_global->VAR_PUBLICCERT_DIR;
configpath = ps_global->smime->publicpath;
+ configcontainer = cpystr(DF_PUBLIC_CONTAINER);
filesuffix = ".crt";
}
else if(which == Private){
configdir = ps_global->VAR_PRIVATEKEY_DIR;
configpath = ps_global->smime->privatepath;
+ configcontainer = cpystr(DF_PRIVATE_CONTAINER);
filesuffix = ".key";
}
else if(which == CACert){
configdir = ps_global->VAR_CACERT_DIR;
configpath = ps_global->smime->capath;
+ configcontainer = cpystr(DF_CA_CONTAINER);
filesuffix = ".crt";
}
@@ -1534,7 +1532,7 @@ copy_dir_to_container(WhichCerts which, char *contents)
* dstpath is either the local Container file or the local cache file
* for the remote Container file.
*/
- tempfile = tempfile_in_same_dir(dstpath, "az", NULL);
+ tempfile = tempfile_in_same_dir(dstpath, "az", &ret_dir);
}
/*
@@ -1609,12 +1607,24 @@ copy_dir_to_container(WhichCerts which, char *contents)
BIO_free(bio_out);
if(!ret){
- if(rename_file(tempfile, dstpath) < 0){
+ if(ret_dir){
+ if(strlen(dstpath) + strlen(configcontainer) - strlen(ret_dir) + 1 < sizeof(dstpath))
+ snprintf(fpath, sizeof(fpath), "%s%c%s",
+ dstpath, tempfile[strlen(ret_dir)], configcontainer);
+ else
+ ret = -1;
+ }
+ else ret = -1;
+
+ if(!ret){
+ if(rename_file(tempfile, fpath) < 0){
q_status_message2(SM_ORDER, 3, 3,
- _("Can't rename %s to %s"), tempfile, dstpath);
+ _("Can't rename %s to %s"), tempfile, fpath);
ret = -1;
+ } else q_status_message1(SM_ORDER, 3, 3,
+ _("saved container to %s"), fpath);
}
-
+
/* if the container is remote, copy it */
if(!ret && IS_REMOTE(configpath)){
int e;
@@ -1656,6 +1666,12 @@ copy_dir_to_container(WhichCerts which, char *contents)
if(tempfile)
fs_give((void **) &tempfile);
+ if(ret_dir)
+ fs_give((void **) &ret_dir);
+
+ if(configcontainer)
+ fs_give((void **) &configcontainer);
+
return ret;
}
@@ -1921,36 +1937,6 @@ is_pkcs7_body(BODY *body)
}
-#ifdef notdef
-/*
- * Somewhat useful debug utility to dump the contents of a BIO to a file.
- * Note that a memory BIO will have its contents eliminated after they
- * are read so this will break the next step.
- */
-static void
-dump_bio_to_file(BIO *in, char *filename)
-{
- char iobuf[4096];
- int len;
- BIO *out;
-
- out = BIO_new_file(filename, "w");
-
- if(out){
- if(BIO_method_type(in) != BIO_TYPE_MEM)
- BIO_reset(in);
-
- while((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0)
- BIO_write(out, iobuf, len);
-
- BIO_free(out);
- }
-
- BIO_reset(in);
-}
-#endif
-
-
/*
* Recursively stash a pointer to the decrypted data in our
* manufactured body.
@@ -2255,7 +2241,7 @@ end:
/*
* Encrypt a message on the way out. Called from call_mailer in send.c
- * The body may be reallocated.
+ * The body may be reallocated.
*/
int
encrypt_outgoing_message(METAENV *header, BODY **bodyP)
@@ -2287,9 +2273,9 @@ encrypt_outgoing_message(METAENV *header, BODY **bodyP)
for(a=*pf->addr; a; a=a->next){
snprintf(buf, sizeof(buf), "%s@%s", a->mailbox, a->host);
- if((cert = get_cert_for(buf, Public)) != NULL)
+ if((cert = get_cert_for(buf, Public)) != NULL){
sk_X509_push(encerts,cert);
- else{
+ }else{
q_status_message2(SM_ORDER, 1, 1,
_("Unable to find certificate for <%s@%s>"),
a->mailbox, a->host);
@@ -2491,10 +2477,12 @@ static int
do_signature_verify(PKCS7 *p7, BIO *in, BIO *out, int silent)
{
STACK_OF(X509) *otherCerts = NULL;
+ CertList *cl;
int result;
+ int flags;
const char *data;
long err;
-
+
if(!s_cert_store){
if(!silent) q_status_message(SM_ORDER | SM_DING, 2, 2,
_("Couldn't verify S/MIME signature: No CA Certs were loaded"));
@@ -2504,8 +2492,31 @@ do_signature_verify(PKCS7 *p7, BIO *in, BIO *out, int silent)
smime_extract_and_save_cert(p7);
- result = PKCS7_verify(p7, otherCerts, s_cert_store, in, out, 0);
-
+ flags = F_ON(F_USE_CERT_STORE_ONLY, ps_global) ? PKCS7_NOINTERN : 0;
+
+ if(ps_global->smime->publiccertlist == NULL){
+ renew_cert_data(&ps_global->smime->publiccertlist, Public);
+ for(cl = ps_global->smime->publiccertlist; cl ; cl = cl->next){
+ if(cl->x509_cert == NULL){
+ char *s = strrchr(cl->name, '.');
+ *s = '\0';
+ cl->x509_cert = get_cert_for(cl->name, Public);
+ *s = '.';
+ }
+ }
+ }
+
+ if(ps_global->smime->publiccertlist){
+ otherCerts = sk_X509_new_null();
+ for(cl = ps_global->smime->publiccertlist; cl ; cl = cl->next)
+ if(cl->x509_cert != NULL)
+ sk_X509_push(otherCerts, X509_dup(cl->x509_cert));
+ }
+
+ result = PKCS7_verify(p7, otherCerts, s_cert_store, in, out, flags);
+
+ sk_X509_pop_free(otherCerts, X509_free);
+
if(result){
q_status_message(SM_ORDER, 1, 1, _("S/MIME signature verified ok"));
}
@@ -2550,54 +2561,6 @@ free_smime_body_sparep(void **sparep)
}
}
-/* return the mime header for this body part. Memory freed by caller */
-char *
-smime_fetch_mime(BODY *b, MAILSTREAM *stream, long msgno, char * section,
- unsigned long *mimelen)
-{
- char *rv;
- char newSec[100];
-
- if(b->type == TYPEMULTIPART)
- snprintf(newSec, sizeof(newSec), "%s%s1", section ? section : "", (section && *section) ? "." : "");
- else
- strncpy(newSec, section, sizeof(newSec));
- newSec[sizeof(newSec)-1] = '\0';
- rv = mail_fetch_mime(stream, msgno, newSec, mimelen, 0);
- return rv ? cpystr(rv) : NULL;
-}
-
-
-void
-smime_write_body_header(BODY *b, MAILSTREAM *stream, long msgno, char *section, soutr_t f, void *s)
-{
- char *rv;
- char newSec[100];
-
- if(b->nested.part == NULL)
- return;
-
- if(b->nested.part->body.type == TYPEMULTIPART)
- snprintf(newSec, sizeof(newSec), "%s%s1", section ? section : "", (section && *section) ? "." : "");
- else
- strncpy(newSec, section, sizeof(newSec));
- newSec[sizeof(newSec)-1] = '\0';
- rv = mail_fetch_mime(stream, msgno, newSec, NULL, 0);
- if(f && rv != NULL)
- (*f)(s, rv);
-}
-
-int
-write_signed_body(BODY *b, MAILSTREAM *stream, long msgno, char *section, BIO *in)
-{
-
- smime_write_body_header(b, stream, msgno, section, rfc822_output_func, in);
-
-
-}
-
-
-
/* Big comment, explaining the mess that exists out there, and how we deal
with it, and also how we solve the problems that are created this way.
@@ -2664,19 +2627,30 @@ write_signed_body(BODY *b, MAILSTREAM *stream, long msgno, char *section, BIO *i
processed text. Nevertheless, at this time, this is automatic, and is
causing a delay in the processing of the message, but it is validating
correctly all messages.
+
+ PART IV
+
+ When the user sends a message as encrypted and signed, this code used to
+ encrypt first, and then sign the pkcs7 body, but it turns out that some
+ other clients can not handle these messages. While we could argue that the
+ other clients need to improve, we will support reading messages in both
+ ways, and will send messages using this technique; that is, signed first,
+ encrypted second. It seems that all tested clients support this way, so it
+ should be safe to do so.
*/
/*
* Given a multipart body of type multipart/signed, attempt to verify it.
* Returns non-zero if the body was changed.
*/
-int
+static int
do_detached_signature_verify(BODY *b, long msgno, char *section)
{
PKCS7 *p7 = NULL;
BIO *in = NULL;
PART *p;
int result, modified_the_body = 0;
+ int flag; /* 1 silent, 0 not silent */
unsigned long mimelen, bodylen;
char newSec[100], *mimetext, *bodytext;
char *what_we_did;
@@ -2693,7 +2667,7 @@ do_detached_signature_verify(BODY *b, long msgno, char *section)
if(get_smime_sparep_type(b->sparep) == SizedText){
/* bodytext includes mimetext */
st = (SIZEDTEXT *) get_smime_sparep_data(b->sparep);
- bodytext = st->data;
+ bodytext = (char *) st->data;
bodylen = st->size;
mimetext = NULL;
mimelen = 0L;
@@ -2724,7 +2698,9 @@ do_detached_signature_verify(BODY *b, long msgno, char *section)
* validates when we remove the last two characters. Silence
* any failures first.
*/
- if(((result = do_signature_verify(p7, in, NULL, 1)) == 0)
+ flag = (bodylen <= 2 || strncmp(bodytext+bodylen-2, "\r\n", 2))
+ ? 0 : 1;
+ if(((result = do_signature_verify(p7, in, NULL, flag)) == 0)
&& bodylen > 2
&& (strncmp(bodytext+bodylen-2,"\r\n", 2) == 0)){
BUF_MEM *biobuf = NULL;
@@ -2738,7 +2714,9 @@ do_detached_signature_verify(BODY *b, long msgno, char *section)
* information. In this case, we fetch the message and we process
* it by hand.
*/
- if((result = do_signature_verify(p7, in, NULL, 1)) == 0
+ flag = (mimelen == 0 || !IS_REMOTE(ps_global->mail_stream->mailbox))
+ ? 0 : 1;
+ if((result = do_signature_verify(p7, in, NULL, flag)) == 0
&& mimelen > 0 /* do not do this for encrypted messages */
&& IS_REMOTE(ps_global->mail_stream->mailbox)){
char *fetch;
@@ -2766,7 +2744,7 @@ do_detached_signature_verify(BODY *b, long msgno, char *section)
mail_free_envelope(&env);
mail_free_body_part(&b->nested.part);
- b->nested.part = body->nested.part;
+ b->nested.part = mail_body_section(body, section)->nested.part;
create_local_cache(bstart, bstart, &b->nested.part->body, 1);
modified_the_body = 1;
@@ -3086,11 +3064,15 @@ do_decoding(BODY *b, long msgno, const char *section)
char *cookie = NULL;
PARAMETER *param;
for (param = body->parameter; param && !cookie; param = param->next)
- if (!strucmp (param->attribute,"BOUNDARY")) cookie = param->value;
- st = fs_get(sizeof(SIZEDTEXT));
- st->data = (void *) cpystr(bstart + strlen(cookie)+4); /* 4 = strlen("--\r\n") */
- st->size = body->nested.part->next->body.mime.offset - 2*(strlen(cookie) + 4);
- body->sparep = create_smime_sparep(SizedText, (void *)st);
+ if (!strucmp (param->attribute,"BOUNDARY")) cookie = param->value;
+ if(cookie != NULL){
+ st = fs_get(sizeof(SIZEDTEXT));
+ st->data = (void *) cpystr(bstart + strlen(cookie)+4); /* 4 = strlen("--\r\n") */
+ st->size = body->nested.part->next->body.mime.offset - 2*(strlen(cookie) + 4);
+ body->sparep = create_smime_sparep(SizedText, (void *)st);
+ }
+ else
+ q_status_message(SM_ORDER, 3, 3, _("Couldn't find cookie in attachment list."));
}
body->mime.offset = 0;
body->mime.text.size = 0;
diff --git a/pith/smime.h b/pith/smime.h
index 8acaaa8e..a2d2c805 100644
--- a/pith/smime.h
+++ b/pith/smime.h
@@ -34,6 +34,14 @@
#define OUR_PKCS7_ENCLOSURE_SUBTYPE "x-pkcs7-enclosure"
+typedef enum {P7Type, CharType, SizedText} SpareType;
+
+typedef struct smime_sparep_t {
+ SpareType sptype;
+ void *data;
+} SMIME_SPARE_S;
+
+
/* exported protoypes */
int smime_validate_cert(X509 *cert, long *error);
int encrypt_file(char *fp, char *text, PERSONAL_CERT *pc);
@@ -73,6 +81,9 @@ void mark_cert_deleted(WhichCerts ctype, int num, unsigned state);
unsigned get_cert_deleted(WhichCerts ctype, int num);
int smime_expunge_cert(WhichCerts ctype);
int add_file_to_container(WhichCerts ctype, char *fpath, char *altname);
+void *create_smime_sparep(SpareType stype, void *s);
+SpareType get_smime_sparep_type(void *s);
+void *get_smime_sparep_data(void *s);
#endif /* PITH_SMIME_INCLUDED */
#endif /* SMIME */
diff --git a/pith/smkeys.c b/pith/smkeys.c
index 56103e91..23c9d21a 100644
--- a/pith/smkeys.c
+++ b/pith/smkeys.c
@@ -252,58 +252,6 @@ load_key(PERSONAL_CERT *pc, char *pass)
}
-#ifdef notdef
-static char *
-get_x509_name_entry(const char *key, X509_NAME *name)
-{
- int i, c, n;
- char buf[256];
- char *id;
-
- if(!name)
- return NULL;
-
- c = X509_NAME_entry_count(name);
-
- for(i=0; i<c; i++){
- X509_NAME_ENTRY *e;
-
- e = X509_NAME_get_entry(name, i);
- if(!e)
- continue;
-
- buf[0] = 0;
- id = buf;
-
- n = OBJ_obj2nid(e->object);
- if((n == NID_undef) || ((id=(char*) OBJ_nid2sn(n)) == NULL)){
- i2t_ASN1_OBJECT(buf, sizeof(buf), e->object);
- id = buf;
- }
-
- if((strucmp(id, "email")==0) || (strucmp(id, "emailAddress")==0)){
- X509_NAME_get_text_by_OBJ(name, e->object, buf, sizeof(buf)-1);
- return cpystr(buf);
- }
- }
-
- return NULL;
-}
-
-
-char *
-get_x509_subject_email(X509 *x)
-{
- char* result;
- result = get_x509_name_entry("email", X509_get_subject_name(x));
- if( !result ){
- result = get_x509_name_entry("emailAddress", X509_get_subject_name(x));
- }
-
- return result;
-}
-#endif /* notdef */
-
#include <openssl/x509v3.h>
/*
* This newer version is from Adrian Vogel. It looks for the email
@@ -392,7 +340,9 @@ save_cert_for(char *email, X509 *cert, WhichCerts ctype)
}
else if(SMHOLDERTYPE(ctype) == Container){
REMDATA_S *rd = NULL;
+ char *ret_dir = NULL;
char path[MAXPATH];
+ char fpath[MAXPATH];
char *upath = PATHCERTDIR(ctype);
char *tempfile = NULL;
int err = 0;
@@ -472,15 +422,26 @@ save_cert_for(char *email, X509 *cert, WhichCerts ctype)
path[sizeof(path)-1] = '\0';
}
- tempfile = tempfile_in_same_dir(path, "az", NULL);
+ tempfile = tempfile_in_same_dir(path, "az", &ret_dir);
if(tempfile){
if(certlist_to_file(tempfile, DATACERT(ctype)))
err++;
+ if(!err && ret_dir){
+ if(strlen(path) + strlen(tempfile) - strlen(ret_dir) + 1 < sizeof(path))
+ snprintf(fpath, sizeof(fpath), "%s%c%s",
+ path, tempfile[strlen(ret_dir)], tempfile + strlen(ret_dir) + 1);
+ else
+ err++;
+ }
+ else err++;
+
+ fs_give((void **)&ret_dir);
+
if(!err){
- if(rename_file(tempfile, path) < 0){
+ if(rename_file(tempfile, fpath) < 0){
q_status_message2(SM_ORDER, 3, 3,
- _("Can't rename %s to %s"), tempfile, path);
+ _("Can't rename %s to %s"), tempfile, fpath);
err++;
}
}