diff options
-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 |