diff options
author | Eduardo Chappa <chappa@washington.edu> | 2014-05-17 16:50:01 -0600 |
---|---|---|
committer | Eduardo Chappa <chappa@washington.edu> | 2014-05-17 16:50:01 -0600 |
commit | 0b9aa5eb03014bb55211186ba0ce60b2a8986ba0 (patch) | |
tree | 0b5c4f9861aa883b0914c00385d8fd480c528044 | |
parent | 223b392e8d40a0622936403d1da5eaf0cdd54d60 (diff) | |
download | alpine-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.
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | alpine/confscroll.c | 6 | ||||
-rw-r--r-- | alpine/keymenu.c | 4 | ||||
-rw-r--r-- | alpine/osdep/mswin.rc | 16 | ||||
-rw-r--r-- | alpine/smime.c | 21 | ||||
-rwxr-xr-x | configure | 38 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | doc/alpine.1 | 2 | ||||
-rw-r--r-- | doc/tech-notes/index.html | 2 | ||||
-rw-r--r-- | doc/tech-notes/tech-notes.txt | 2 | ||||
-rw-r--r-- | imap/src/c-client/mail.c | 33 | ||||
-rw-r--r-- | imap/src/c-client/mail.h | 1 | ||||
-rw-r--r-- | include/config.h.in | 9 | ||||
-rw-r--r-- | mapi/pmapi.c | 2 | ||||
-rw-r--r-- | mapi/pmapi.rc | 14 | ||||
-rw-r--r-- | pico/edef.h | 2 | ||||
-rw-r--r-- | pico/estruct.h | 1 | ||||
-rw-r--r-- | pico/osdep/mswin.c | 12 | ||||
-rw-r--r-- | pico/pico.c | 30 | ||||
-rw-r--r-- | pith/adrbklib.c | 42 | ||||
-rw-r--r-- | pith/adrbklib.h | 2 | ||||
-rw-r--r-- | pith/conf.c | 2 | ||||
-rw-r--r-- | pith/conftype.h | 1 | ||||
-rw-r--r-- | pith/mimedesc.c | 7 | ||||
-rw-r--r-- | pith/pattern.c | 6 | ||||
-rw-r--r-- | pith/pine.hlp | 119 | ||||
-rw-r--r-- | pith/reply.c | 2 | ||||
-rw-r--r-- | pith/send.c | 18 | ||||
-rw-r--r-- | pith/smime.c | 196 | ||||
-rw-r--r-- | pith/smime.h | 11 | ||||
-rw-r--r-- | pith/smkeys.c | 71 | ||||
-rw-r--r-- | po/Makefile.in | 2 |
32 files changed, 433 insertions, 249 deletions
@@ -1 +1 @@ -2.19.991 +2.19.999 diff --git a/alpine/confscroll.c b/alpine/confscroll.c index 5ca2702b..71648202 100644 --- a/alpine/confscroll.c +++ b/alpine/confscroll.c @@ -4611,6 +4611,12 @@ toggle_feature_bit(struct pine *ps, int index, struct variable *var, CONF_S *cl, ps->pass_ctrl_chars = F_ON(F_PASS_CONTROL_CHARS,ps_global) ? 1 : 0; break; + case F_USE_CERT_STORE_ONLY: + if(F_OFF(F_USE_CERT_STORE_ONLY, ps)) + q_status_message(SM_ORDER | SM_DING, 3, 4, + "Disabling this feature should only be done for testing. Press \"?\" for help"); + break; + case F_PASS_C1_CONTROL_CHARS : ps->pass_c1_ctrl_chars = F_ON(F_PASS_C1_CONTROL_CHARS,ps_global) ? 1 : 0; break; diff --git a/alpine/keymenu.c b/alpine/keymenu.c index 3e90f1b7..3ce23503 100644 --- a/alpine/keymenu.c +++ b/alpine/keymenu.c @@ -2686,8 +2686,8 @@ struct key smime_certificate_info_keys[] = {"R",N_("Private Key"),{MC_PRIVATE,1,{'r'}},KS_NONE}, NULL_MENU, NULL_MENU, - FWDEMAIL_MENU, - {"S", N_("Save"), {MC_SAVETEXT,1,{'s'}}, KS_SAVE}, + NULL_MENU, + NULL_MENU, HELP_MENU, OTHER_MENU, diff --git a/alpine/osdep/mswin.rc b/alpine/osdep/mswin.rc index eb6950ec..a6ae8c6c 100644 --- a/alpine/osdep/mswin.rc +++ b/alpine/osdep/mswin.rc @@ -244,8 +244,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,19,991,0 - PRODUCTVERSION 2,19,991,0 + FILEVERSION 2,19,999,0 + PRODUCTVERSION 2,19,999,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -260,19 +260,19 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "Comments", "see http://www.washington.edu/alpine\0" - VALUE "CompanyName", "University of Washington\0" + VALUE "Comments", "see http://patches.freeiz.com/alpine/\0" + VALUE "CompanyName", "Patches for Alpine\0" #ifdef _PCP_W2K VALUE "FileDescription", "Alpine with krb5 for Windows\0" #else VALUE "FileDescription", "Alpine\0" #endif - VALUE "FileVersion", "2.19.991\0" + VALUE "FileVersion", "2.19.999\0" VALUE "InternalName", "alpine\0" - VALUE "LegalCopyright", "Copyright 2006-2009\0" + VALUE "LegalCopyright", "Copyright 2006-2009 University of Washington, Copyright 2013-2014\0" VALUE "OriginalFilename", "alpine.exe\0" VALUE "ProductName", "alpine\0" - VALUE "ProductVersion", "2.19.991\0" + VALUE "ProductVersion", "2.19.999\0" END END BLOCK "VarFileInfo" @@ -583,7 +583,7 @@ END STRINGTABLE DISCARDABLE BEGIN - IDS_BYLINE "Copyright 2006-2009 University of Washington" + IDS_BYLINE "Copyright 2013-2014 Eduardo Chappa, Copyright 2006-2009 University of Washington" IDS_APPNAME "Alpine" IDS_APPIDENT "alpine" END diff --git a/alpine/smime.c b/alpine/smime.c index 135ab3cf..1249ec72 100644 --- a/alpine/smime.c +++ b/alpine/smime.c @@ -56,7 +56,7 @@ void revert_to_saved_smime_config(struct pine *ps, SAVED_CONFIG_S *vsave); SAVED_CONFIG_S *save_smime_config_vars(struct pine *ps); void free_saved_smime_config(struct pine *ps, SAVED_CONFIG_S **vsavep); int smime_helper_tool(struct pine *, int, CONF_S **, unsigned); -int smime_public_certs_tool(struct pine *, int, CONF_S **, unsigned); +//int smime_public_certs_tool(struct pine *, int, CONF_S **, unsigned); void manage_certificates(struct pine *, WhichCerts); void smime_manage_certs_init (struct pine *, CONF_S **, CONF_S **, WhichCerts, int); void display_certificate_information(struct pine *, X509 *, char *, WhichCerts, int num); @@ -187,7 +187,7 @@ smime_info_screen(struct pine *ps) void format_smime_info(int pass, BODY *body, long msgno, gf_io_t pc) { - PKCS7 *p7; + PKCS7 *p7 = NULL; int i; if(body->type == TYPEMULTIPART){ @@ -196,8 +196,10 @@ format_smime_info(int pass, BODY *body, long msgno, gf_io_t pc) for(p=body->nested.part; p; p=p->next) format_smime_info(pass, &p->body, msgno, pc); } - - p7 = body->sparep; + if(body->sparep) + p7 = get_smime_sparep_type(body->sparep) == P7Type + ? (PKCS7 *)get_smime_sparep_data(body->sparep) + : NULL; if(p7){ if(PKCS7_type_is_signed(p7)){ @@ -766,6 +768,17 @@ smime_config_init_display(struct pine *ps, CONF_S **ctmp, CONF_S **first_line) (*ctmp)->varmem = ind; (*ctmp)->value = pretty_value(ps, (*ctmp)); + ind = feature_list_index(F_USE_CERT_STORE_ONLY); + feature = feature_list(ind); + new_confline(ctmp)->var = vtmp; + (*ctmp)->varnamep = ctmpb; + (*ctmp)->keymenu = &config_checkbox_keymenu; + (*ctmp)->help = config_help(vtmp-ps->vars, feature->id); + (*ctmp)->tool = checkbox_tool; + (*ctmp)->valoffset = feature_indent(); + (*ctmp)->varmem = ind; + (*ctmp)->value = pretty_value(ps, (*ctmp)); + #ifdef APPLEKEYCHAIN new_confline(ctmp); (*ctmp)->flags |= CF_NOSELECT | CF_B_LINE; @@ -1,7 +1,7 @@ #! /bin/sh -# From configure.ac Rev:13 by chappa@washington.edu. +# From configure.ac Rev:14 by chappa@washington.edu. # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for alpine 2.19.991. +# Generated by GNU Autoconf 2.69 for alpine 2.19.999. # # Report bugs to <chappa@washington.edu>. # @@ -730,8 +730,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='alpine' PACKAGE_TARNAME='alpine' -PACKAGE_VERSION='2.19.991' -PACKAGE_STRING='alpine 2.19.991' +PACKAGE_VERSION='2.19.999' +PACKAGE_STRING='alpine 2.19.999' PACKAGE_BUGREPORT='chappa@washington.edu' PACKAGE_URL='' @@ -1596,7 +1596,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures alpine 2.19.991 to adapt to many kinds of systems. +\`configure' configures alpine 2.19.999 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1666,7 +1666,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of alpine 2.19.991:";; + short | recursive ) echo "Configuration of alpine 2.19.999:";; esac cat <<\_ACEOF @@ -1953,7 +1953,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -alpine configure 2.19.991 +alpine configure 2.19.999 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2559,7 +2559,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by alpine $as_me 2.19.991, which was +It was created by alpine $as_me 2.19.999, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3380,7 +3380,7 @@ fi # Define the identity of the package. PACKAGE='alpine' - VERSION='2.19.991' + VERSION='2.19.999' cat >>confdefs.h <<_ACEOF @@ -15533,6 +15533,22 @@ _ACEOF +cat >>confdefs.h <<_ACEOF +#define DF_PUBLIC_CONTAINER "PublicContainer" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define DF_PRIVATE_CONTAINER "PrivateContainer" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define DF_CA_CONTAINER "CAContainer" +_ACEOF + + + # Check whether --with-passfile was given. if test "${with_passfile+set}" = set; then : withval=$with_passfile; @@ -20339,7 +20355,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by alpine $as_me 2.19.991, which was +This file was extended by alpine $as_me 2.19.999, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -20405,7 +20421,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -alpine config.status 2.19.991 +alpine config.status 2.19.999 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 1e818b7c..672a0bdb 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ dnl */ AC_PREREQ([2.69]) -AC_REVISION([Rev:13 by chappa@washington.edu]) +AC_REVISION([Rev:14 by chappa@washington.edu]) dnl Alpine Version Number is in $srcdir/VERSION AC_INIT([alpine],[m4_normalize(m4_include(VERSION))],[chappa@washington.edu]) @@ -631,6 +631,10 @@ PINEVAR(smime-private-key-directory, DF_PRIVATEKEY_DIR, [.alpine-smime/private], PINEVAR(smime-cacert-directory, DF_CACERT_DIR, [.alpine-smime/ca], [Default Cert Authority Directory]) PINEVAR_UNQUOTED(default-printer, DF_DEFAULT_PRINTER, [ANSI_PRINTER], [Default printer]) +AC_DEFINE_UNQUOTED([DF_PUBLIC_CONTAINER], "PublicContainer", [Name of default public container]) +AC_DEFINE_UNQUOTED([DF_PRIVATE_CONTAINER], "PrivateContainer", [Name of default private container]) +AC_DEFINE_UNQUOTED([DF_CA_CONTAINER], "CAContainer", [Name of default certificate authority container]) + dnl set PASSFILE? AC_ARG_WITH(passfile, AS_HELP_STRING([--with-passfile=FILENAME],[Password cache file (recommended when S/MIME is enabled and configured)]), diff --git a/doc/alpine.1 b/doc/alpine.1 index 550e676e..51e8a70a 100644 --- a/doc/alpine.1 +++ b/doc/alpine.1 @@ -1,4 +1,4 @@ -.TH alpine 1 "Version 2.19.991" +.TH alpine 1 "Version 2.19.999" .SH NAME alpine \- an Alternatively Licensed Program for Internet News and Email .SH SYNTAX diff --git a/doc/tech-notes/index.html b/doc/tech-notes/index.html index ad0b5095..5a05c1e4 100644 --- a/doc/tech-notes/index.html +++ b/doc/tech-notes/index.html @@ -3,7 +3,7 @@ <BODY> <H1>Alpine Technical Notes</H1> -Version 2.19.991, April 2014 +Version 2.19.999, May 2014 <H2><A NAME="TOC">Table of Contents</A></H2><P> diff --git a/doc/tech-notes/tech-notes.txt b/doc/tech-notes/tech-notes.txt index acfecdc2..e9bed323 100644 --- a/doc/tech-notes/tech-notes.txt +++ b/doc/tech-notes/tech-notes.txt @@ -1,7 +1,7 @@ Alpine Technical Notes - Version 2.19.991, April 2014 + Version 2.19.999, May 2014 Table of Contents diff --git a/imap/src/c-client/mail.c b/imap/src/c-client/mail.c index 871d07eb..03952d2e 100644 --- a/imap/src/c-client/mail.c +++ b/imap/src/c-client/mail.c @@ -2723,21 +2723,18 @@ void mail_gc_body (BODY *body) if (body->mime.text.data) fs_give ((void **) &body->mime.text.data); if (body->contents.text.data) fs_give ((void **) &body->contents.text.data); } - -/* Mail get body part - * Accepts: mail stream - * message number - * section specifier - * Returns: pointer to body +/* Mail get body section + * Accepts: body of message + * section specifier + * Returns: pointer to body at given section */ -BODY *mail_body (MAILSTREAM *stream,unsigned long msgno,unsigned char *section) +BODY *mail_body_section (BODY *b, unsigned char *section) { - BODY *b = NIL; PART *pt; unsigned long i; /* make sure have a body */ - if (section && *section && mail_fetchstructure (stream,msgno,&b) && b) + if (section && *section && b) while (*section) { /* find desired section */ if (isdigit (*section)) { /* get section specifier */ /* make sure what follows is valid */ @@ -2768,6 +2765,24 @@ BODY *mail_body (MAILSTREAM *stream,unsigned long msgno,unsigned char *section) else return NIL; /* unknown section specifier */ } return b; +} + +/* Mail get body part + * Accepts: mail stream + * message number + * section specifier + * Returns: pointer to body + */ + +BODY *mail_body (MAILSTREAM *stream,unsigned long msgno,unsigned char *section) +{ + BODY *b = NIL; + PART *pt; + unsigned long i; + /* make sure have a body */ + if (section && *section && mail_fetchstructure (stream,msgno,&b) && b) + return mail_body_section(b, section); + return b; } /* Mail output date from elt fields diff --git a/imap/src/c-client/mail.h b/imap/src/c-client/mail.h index fe7eaa77..2accc85b 100644 --- a/imap/src/c-client/mail.h +++ b/imap/src/c-client/mail.h @@ -1704,6 +1704,7 @@ void mail_gc (MAILSTREAM *stream,long gcflags); void mail_gc_msg (MESSAGE *msg,long gcflags); void mail_gc_body (BODY *body); +BODY *mail_body_section (BODY *b, unsigned char *section); BODY *mail_body (MAILSTREAM *stream,unsigned long msgno, unsigned char *section); char *mail_date (char *string,MESSAGECACHE *elt); diff --git a/include/config.h.in b/include/config.h.in index 8c0097da..edb0db6d 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -51,6 +51,9 @@ /* Default configuration value */ #undef DF_CACERT_DIR +/* Name of default certificate authority container */ +#undef DF_CA_CONTAINER + /* Default configuration value */ #undef DF_DEFAULT_FCC @@ -99,9 +102,15 @@ /* Default configuration value */ #undef DF_PRIVATEKEY_DIR +/* Name of default private container */ +#undef DF_PRIVATE_CONTAINER + /* Default configuration value */ #undef DF_PUBLICCERT_DIR +/* Name of default public container */ +#undef DF_PUBLIC_CONTAINER + /* Default configuration value */ #undef DF_REMOTE_ABOOK_HISTORY diff --git a/mapi/pmapi.c b/mapi/pmapi.c index bfdda141..4d4b3101 100644 --- a/mapi/pmapi.c +++ b/mapi/pmapi.c @@ -1952,7 +1952,7 @@ BOOL APIENTRY DllMain( now = time((time_t *)0); tm_now = localtime(&now); - fprintf(ms_global->dfd, "pmapi32.dll for Alpine Version 2.19.991\r\n"); + fprintf(ms_global->dfd, "pmapi32.dll for Alpine Version 2.19.999\r\n"); fprintf(ms_global->dfd, " Build date: %s\r\n", datestamp); fprintf(ms_global->dfd, " please report all bugs to chappa@gmx.com\r\n"); diff --git a/mapi/pmapi.rc b/mapi/pmapi.rc index e6a37725..ed2e7b7e 100644 --- a/mapi/pmapi.rc +++ b/mapi/pmapi.rc @@ -98,8 +98,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,19,991,0 - PRODUCTVERSION 2,19,991,0 + FILEVERSION 2,19,999,0 + PRODUCTVERSION 2,19,999,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x29L @@ -114,17 +114,17 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "Comments", "alpine info: http://www.washington.edu/alpine\0" - VALUE "CompanyName", "University of Washington\0" + VALUE "Comments", "alpine info: http://patches.freeiz.com/alpine\0" + VALUE "CompanyName", "Patches for Alpine\0" VALUE "FileDescription", "Simple MAPI DLL for Alpine for Windows\0" - VALUE "FileVersion", "2.19.991\0" + VALUE "FileVersion", "2.19.999\0" VALUE "InternalName", "pmapi32\0" - VALUE "LegalCopyright", "Copyright ? 2006-2009\0" + VALUE "LegalCopyright", "Copyright ? University of Washington 2006-2009, Eduardo Chappa 2013-2014\0" VALUE "LegalTrademarks", "Apache License, Version 2.0\0" VALUE "OriginalFilename", "pmapi32.dll\0" VALUE "PrivateBuild", " \0" VALUE "ProductName", "Simple MAPI for Alpine for Windows\0" - VALUE "ProductVersion", "2.19.991\0" + VALUE "ProductVersion", "2.19.999\0" VALUE "SpecialBuild", " \0" END END diff --git a/pico/edef.h b/pico/edef.h index 209a4600..3cc7fd3e 100644 --- a/pico/edef.h +++ b/pico/edef.h @@ -32,6 +32,7 @@ /* initialized global definitions */ +int direction = 0; /* direction of writing */ int fillcol = 72; /* Current fill column */ int userfillcol = -1; /* Fillcol set from cmd line */ UCS pat[NPAT]; /* Search pattern */ @@ -84,6 +85,7 @@ void *input_cs; /* passed to mbtow() via kbseq() */ /* initialized global external declarations */ +extern int direction; extern int fillcol; /* Fill column */ extern int userfillcol; /* Fillcol set from cmd line */ extern UCS pat[]; /* Search pattern */ diff --git a/pico/estruct.h b/pico/estruct.h index cff5a6de..0cfe2e01 100644 --- a/pico/estruct.h +++ b/pico/estruct.h @@ -239,6 +239,7 @@ typedef struct { typedef struct CELL { unsigned int c : 24; /* Character value in cell */ unsigned int a : 8; /* Its attributes */ + unsigned int d : 1; /* direction */ } CELL; /* flags for color_options */ diff --git a/pico/osdep/mswin.c b/pico/osdep/mswin.c index 538e0d33..6fce077a 100644 --- a/pico/osdep/mswin.c +++ b/pico/osdep/mswin.c @@ -157,6 +157,9 @@ #define CQ_FLAG_EXTENDED 0x02 #define CQ_FLAG_ALT 0x04 +#define ARABIC_LRM 0x200E +#define ARABIC_RLM 0x200F + /* Special ASCII characters. */ #define ASCII_BEL 0x07 #define ASCII_BS 0x08 @@ -3395,6 +3398,10 @@ WriteTTYBlock (HWND hWnd, LPTSTR lpBlock, int nLength) for (i = 0 ; i < nLength; i++) { switch (lpBlock[i]) { + case ARABIC_LRM: + case ARABIC_RLM: + break; + case ASCII_BEL: /* Bell */ MessageBeep (0) ; @@ -7054,6 +7061,11 @@ int mswin_putc (UCS ucs) { TCHAR cc = (TCHAR)ucs; + if(ucs == ARABIC_LRM || ucs == ARABIC_RLM){ + FlushWriteAccum(); + WriteTTYBlock (ghTTYWnd, &cc, 1); + return 0; + } if (ucs >= (UCS)(' ')) { /* Not carriage control. */ gpTTYInfo->writeAccum[gpTTYInfo->writeAccumCount++] = (TCHAR)ucs; diff --git a/pico/pico.c b/pico/pico.c index 40d971b9..ca09749f 100644 --- a/pico/pico.c +++ b/pico/pico.c @@ -72,6 +72,7 @@ static char rcsid[] = "$Id: pico.c 921 2008-01-31 02:09:25Z hubert@u.washington. #include "../pith/charconv/filesys.h" +void remove_directions_mark(void); void func_init(void); void breplace(void *w); int any_header_changes(void); @@ -102,6 +103,33 @@ static UCS pfkm[12][2] = { }; +void +remove_directions_mark(void) +{ + LINE *lp; + int i, ll; + UCS c; + + for(lp = lforw(curbp->b_linep); lp != curbp->b_linep; lp = lforw(lp)){ + ll = llength(lp); + for(i = 0; i < ll;){ + c = lgetc(lp, i).c; + if(c == 0x200E || c == 0x200F){ + curwp->w_dotp = lp; + curwp->w_doto = i; + forwdel(FALSE, 1); + direction = c == 0x200E ? 0 : 1; + } + else + lgetc(lp,i++).d = direction; + } + } + curwp->w_linep = lforw(curbp->b_linep); + curwp->w_dotp = lforw(curbp->b_linep); + curwp->w_doto = 0; +} + + /* * flag for the various functions in pico() to set when ready * for pico() to return... @@ -172,6 +200,8 @@ pico(PICO *pm) if(pm->msgtext) breplace(pm->msgtext); + remove_directions_mark(); + #ifdef _WINDOWS cursor_shown = mswin_showcaret(1); /* turn on for main window */ mswin_allowpaste(MSWIN_PASTE_FULL); 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 "Alternatively Licensed Program for Internet -News and Email" produced until 2008 by the University of Washington. +News and Email" 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 "lock when already locked", 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 "@" command in the index screen of such folder). <LI> Search a folder for the content of any header with the ";" 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 & 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 "NextLink" and "PrevLink" commands <H1>Introduction</H1> Alpine is an "Alternatively Licensed Program for Internet -News and Email" produced until 2008 by the University of Washington. +News and Email" 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). <End of help on this topic> </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> +<End of help on this topic> +</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++; } } diff --git a/po/Makefile.in b/po/Makefile.in index cc1c5abc..4b532b75 100644 --- a/po/Makefile.in +++ b/po/Makefile.in @@ -11,7 +11,7 @@ # Origin: gettext-0.16 PACKAGE = alpine -VERSION = 2.19.991 +VERSION = 2.19.999 PACKAGE_BUGREPORT = chappa@washington.edu SHELL = /bin/sh |