summaryrefslogtreecommitdiff
path: root/pith
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2014-05-17 16:50:01 -0600
committerEduardo Chappa <chappa@washington.edu>2014-05-17 16:50:01 -0600
commit0b9aa5eb03014bb55211186ba0ce60b2a8986ba0 (patch)
tree0b5c4f9861aa883b0914c00385d8fd480c528044 /pith
parent223b392e8d40a0622936403d1da5eaf0cdd54d60 (diff)
downloadalpine-0b9aa5eb03014bb55211186ba0ce60b2a8986ba0.tar.xz
* New version 2.19.999
* Introduce the option "Validate Using Certificate Store Only", and make it the default. This will make Alpine check for the validity of signatures in certificates that a user has installed in their system, and not in the certificates that come with the message. A user can override this, although is not recommended, by disabling this feature. * When viewing a signed message, the ^E command would present an empty screen or Alpine would crash because when Alpine would get the PKCS7 body of the message from body->sparep, it would not decode it properly due to the new way in which the sparep pointer is encoded that was introduced in version 2.19.991. * When a signed message is forwarded, the message might not be filtered correctly, and mime information might make it into the body of the forwarded message. In order to produce this, the message must be forwarded from the index screen and not be opened. The reason why this makes a difference is because opening a signed message changes its body structure. The reason why a person could forward a message before reading it is because the person could already be aware of the content of the message (e.g. the message is in the sent-mail folder). * When a message fails to validate and the body is saved from the server for validation, be careful in the way that body part pointers are set, in order to do this we split the mail_body function into two parts, one that gets the body, the other that gets the section of the body. The new function that gets the section of the body (mail_body_section), is used to assign pointers of the reconstructed new body. * When a container has not been defined, transferring messages to a container will succeed, and the name of the container will be written on screen. * When Alpine is receiving the envelopes from an imap server, it attempts to generate the index line immediately; while doing so it might need to compute a score, and for this, it might need to go back and do some operation in the same imap server. In this case, Alpine will crash with a "lock when already locked" message. In order to avoid this crash, a new check in match_pattern was added to Alpine to avoid the second trip to a server that is busy sending us envelopes. Reported by Peter Koellner. * Update copyright notice in mswin.rc and pmapi.rc, as well as first time user notice and special request notice. * 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. * Decode the name of attachment names, so they can be written as part of the description of the part. * 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.
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++;
}
}