diff options
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | alpine/alpine.c | 5 | ||||
-rw-r--r-- | alpine/arg.c | 33 | ||||
-rw-r--r-- | alpine/conftype.h | 2 | ||||
-rw-r--r-- | alpine/imap.c | 18 | ||||
-rw-r--r-- | alpine/mailcmd.c | 25 | ||||
-rw-r--r-- | alpine/mailcmd.h | 3 | ||||
-rw-r--r-- | alpine/smime.c | 68 | ||||
-rwxr-xr-x | configure | 40 | ||||
-rw-r--r-- | configure.ac | 10 | ||||
-rw-r--r-- | doc/tech-notes/tech-notes.txt | 2 | ||||
-rw-r--r-- | include/config.h.in | 2 | ||||
-rw-r--r-- | include/config.wnt.h | 581 | ||||
-rw-r--r-- | pith/charconv/filesys.c | 1 | ||||
-rw-r--r-- | pith/conftype.h | 3 | ||||
-rw-r--r-- | pith/options.h | 7 | ||||
-rw-r--r-- | pith/pine.hlp | 44 | ||||
-rw-r--r-- | pith/readfile.c | 28 | ||||
-rw-r--r-- | pith/readfile.h | 2 | ||||
-rw-r--r-- | pith/smime.c | 430 | ||||
-rw-r--r-- | pith/smime.h | 12 | ||||
-rw-r--r-- | pith/state.c | 4 | ||||
-rw-r--r-- | pith/state.h | 3 |
23 files changed, 563 insertions, 762 deletions
@@ -55,7 +55,7 @@ If you are reading this, you have presumably succeeded in extracting the distribution from the compressed tar archive file, via the following command, or equivalent: - tar --xz -xf alpine.tar.xz + tar -Jxf alpine.tar.xz Some of the instructions that follow assume that your current working directory is the alpine-X.XX directory created by the un-tar process diff --git a/alpine/alpine.c b/alpine/alpine.c index 8266c30e..b34469e9 100644 --- a/alpine/alpine.c +++ b/alpine/alpine.c @@ -188,10 +188,11 @@ main(int argc, char **argv) pith_opt_pretty_feature_name = pretty_feature_name; pith_opt_closing_stream = titlebar_stream_closing; pith_opt_current_expunged = mm_expunged_current; - pith_enter_password = alpine_get_password; #ifdef SMIME - pith_smime_import_certificate = smime_import_certificate; pith_opt_smime_get_passphrase = smime_get_passphrase; + pith_smime_import_certificate = smime_import_certificate; + pith_smime_enter_password = alpine_get_password; + pith_opt_get_data_prompt = alpine_get_data_prompt; #endif #ifdef ENABLE_LDAP pith_opt_save_ldap_entry = save_ldap_entry; diff --git a/alpine/arg.c b/alpine/arg.c index 9391a1db..409ffaf1 100644 --- a/alpine/arg.c +++ b/alpine/arg.c @@ -58,6 +58,10 @@ static char args_err_missing_aux[] = N_("missing argument for option \"-aux\"") #ifdef PASSFILE static char args_err_missing_passfile[] = N_("missing argument for option \"-passfile\""); static char args_err_non_abs_passfile[] = N_("argument to \"-passfile\" should be fully-qualified"); +#ifdef SMIME +static char args_err_missing_pwdcertdir[] = N_("missing argument for option \"-pwdcertdir\""); +static char args_err_non_abs_pwdcertdir[] = N_("argument to \"-pwdcertdir\" should be fully-qualified"); +#endif /* SMIME inside PASSFILE */ #endif static char args_err_missing_sort[] = N_("missing argument for option \"-sort\""); static char args_err_missing_flag_arg[] = N_("missing argument for flag \"%c\""); @@ -130,6 +134,10 @@ N_(" -erase_stored_passwords\tEliminate any stored passwords"), #ifdef PASSFILE N_(" -passfile <fully_qualified_filename>\tSet the password file to something other"), N_("\t\tthan the default"), +#ifdef SMIME +N_(" -pwdcertdir <fully_qualified_filename>\tSet the directory to store a personal"), +N_("\t\tkey and certificates to encrypt and decrypt your password file."), +#endif /* SMIME inside PASSFILE */ #endif /* PASSFILE */ #ifdef LOCAL_PASSWD_CACHE @@ -290,6 +298,31 @@ Loop: while(--ac > 0) goto Loop; } +#ifdef SMIME + else if(strcmp(*av, "pwdcertdir") == 0){ + if(--ac){ + if((str = *++av) != NULL){ + if(!is_absolute_path(str)){ + display_args_err(_(args_err_non_abs_pwdcertdir), + NULL, 1); + ++usage; + } + else{ + if(pine_state->pwdcertdir) + fs_give((void **)&pine_state->pwdcertdir); + + pine_state->pwdcertdir = cpystr(str); + } + } + } + else{ + display_args_err(_(args_err_missing_pwdcertdir), NULL, 1); + ++usage; + } + + goto Loop; + } +#endif /* SMIME inside PASSFILE */ #endif /* PASSFILE */ #ifdef LOCAL_PASSWD_CACHE diff --git a/alpine/conftype.h b/alpine/conftype.h index ccd5c4b6..f6d98704 100644 --- a/alpine/conftype.h +++ b/alpine/conftype.h @@ -60,10 +60,12 @@ typedef struct conf_line { struct flag_table **ftbl; /* address of start of table */ struct flag_table *fp; /* pointer into table for each row */ } f; +#ifdef SMIME struct smime_data { WhichCerts ctype; int deleted; } s; +#endif /* SMIME */ struct context_and_screen { CONTEXT_S *ct; CONT_SCR_S *cs; diff --git a/alpine/imap.c b/alpine/imap.c index a9f3c956..04da3065 100644 --- a/alpine/imap.c +++ b/alpine/imap.c @@ -4,8 +4,8 @@ static char rcsid[] = "$Id: imap.c 1266 2009-07-14 18:39:12Z hubert@u.washington /* * ======================================================================== - * 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. @@ -2041,7 +2041,6 @@ passfile_name(char *pinerc, char *path, size_t len) return(NULL); #endif } - #endif /* PASSFILE */ @@ -2374,17 +2373,18 @@ read_passfile(pinerc, l) }; #ifdef SMIME + smime_init(); + if(ps_global->smime->pwdcert == NULL) + setup_pwdcert(); tmp2[0] = '\0'; fgets(tmp2, sizeof(tmp2), fp); + fclose(fp); if(strcmp(tmp2, "-----BEGIN PKCS7-----\n")){ - fclose(fp); - if(encrypt_file(tmp, NULL)) + if(encrypt_file(tmp, NULL, ps_global->smime->pwdcert)) encrypted++; } - else{ - fclose(fp); + else encrypted++; - } /* * if password file is encrypted we attemtp to decrypt. We ask the @@ -2399,7 +2399,7 @@ read_passfile(pinerc, l) * unencrypted and rewritten again. */ if(encrypted){ - text = text2 = decrypt_file(tmp, &i); + text = text2 = decrypt_file(tmp, &i, ps_global->smime->pwdcert); switch(i){ case 1 : save_password = 1; break; @@ -2631,7 +2631,7 @@ write_passfile(pinerc, l) fclose(fp); #ifdef SMIME - if(encrypt_file(tmp2, text) == 0){ + if(encrypt_file(tmp2, text, ps_global->smime->pwdcert) == 0){ if((fp = our_fopen(tmp2, "wb")) != NULL){ fputs(text, fp); fclose(fp); diff --git a/alpine/mailcmd.c b/alpine/mailcmd.c index a9fca5da..d9a6f412 100644 --- a/alpine/mailcmd.c +++ b/alpine/mailcmd.c @@ -116,8 +116,6 @@ char *choose_a_keyword(void); int select_sort(struct pine *, int, SortOrder *, int *); int print_index(struct pine *, MSGNO_S *, int); - - /* * List of Select options used by apply_* functions... */ @@ -304,16 +302,25 @@ static ESCKEY_S flag_text_opt[] = { {-1, 0, NULL, NULL} }; -void +int alpine_get_data_prompt(char *prompt, char *value, size_t len) +{ + int rv, flags; + flags = OE_DISALLOW_HELP; + value[0] = '\0'; + rv = optionally_enter(value, -FOOTER_ROWS(ps_global), 0, len, + prompt, NULL, NO_HELP, &flags); + return rv; +} + +int alpine_get_password(char *prompt, char *pass, size_t len) { - int rc, flags; - do { /* transform this to a (*pith_)() function */ - flags = OE_PASSWD | OE_DISALLOW_HELP; - pass[0] = '\0'; - rc = optionally_enter(pass, -FOOTER_ROWS(ps_global), 0, len, + int rv, flags; + flags = OE_PASSWD | OE_DISALLOW_HELP; + pass[0] = '\0'; + rv = optionally_enter(pass, -FOOTER_ROWS(ps_global), 0, len, prompt, NULL, NO_HELP, &flags); - } while (rc!=0 && rc!=1 && rc>0); + return rv; } int smime_import_certificate(char *filename, char *full_filename, size_t len) diff --git a/alpine/mailcmd.h b/alpine/mailcmd.h index d26d321c..6f5e7f11 100644 --- a/alpine/mailcmd.h +++ b/alpine/mailcmd.h @@ -63,7 +63,8 @@ typedef enum {View, MsgIndx, ThrdIndx} CmdWhere; /* exported protoypes */ -void alpine_get_password(char *, char *, size_t); +int alpine_get_data_prompt(char *, char *, size_t); +int alpine_get_password(char *, char *, size_t); int smime_import_certificate(char *, char *, size_t); int process_cmd(struct pine *, MAILSTREAM *, MSGNO_S *, int, CmdWhere, int *); char *pretty_command(UCS); diff --git a/alpine/smime.c b/alpine/smime.c index 6d4ea49c..b8fc9791 100644 --- a/alpine/smime.c +++ b/alpine/smime.c @@ -34,6 +34,7 @@ static char rcsid[] = "$Id: smime.c 1074 2008-06-04 00:08:43Z hubert@u.washingto #include "../pith/store.h" #include "../pith/conf.h" #include "../pith/list.h" +#include "../pith/mailcmd.h" #include "radio.h" #include "keymenu.h" #include "mailview.h" @@ -351,7 +352,29 @@ output_cert_info(X509 *cert, gf_io_t pc) gf_puts_uline("Serial Number", spc); gf_puts(NEWLINE, spc); - snprintf(buf, sizeof(buf), "%ld", ASN1_INTEGER_get(cert->cert_info->serialNumber)); + { + ASN1_INTEGER *bs; + long l; + const char *neg; + int i; + + bs = X509_get_serialNumber(cert); + if (bs->length <= (int)sizeof(long)){ + l = ASN1_INTEGER_get(bs); + if (bs->type == V_ASN1_NEG_INTEGER){ + l = -l; + neg="-"; + } + else + neg=""; + snprintf(buf, sizeof(buf), " %s%lu (%s0x%lx)", neg, l, neg, l); + } else { + snprintf(buf, sizeof(buf), "%s", bs->type == V_ASN1_NEG_INTEGER ? "(Negative)" : ""); + for (i = 0; i < bs->length; i++) + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%02x%s", bs->data[i], + i+1 == bs->length ? "" : ":"); + } + } gf_puts(buf, spc); gf_puts(NEWLINE, spc); gf_puts(NEWLINE, spc); @@ -550,6 +573,13 @@ smime_config_screen(struct pine *ps, int edit_exceptions) dprint((9, "smime_config_screen()")); ps->next_screen = SCREEN_FUN_NULL; + /* + * this is necessary because we need to know the correct paths + * to configure certificates and keys, and we could get here + * without having done that before we reach this place. + */ + smime_reinit(); + if(ps->fix_fixed_warning) offer_to_fix_pinerc(ps); @@ -608,7 +638,7 @@ smime_config_screen(struct pine *ps, int edit_exceptions) } free_saved_smime_config(ps, &vsave); - smime_deinit(); + smime_reinit(); } @@ -926,6 +956,7 @@ void display_certificate_information(struct pine *ps, X509 *cert, char *email, W case MC_TRUST: save_cert_for(email, cert, CACert); renew_store(); + new_store = 1; break; case MC_DELETE: @@ -1063,12 +1094,8 @@ int manage_certs_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned flags) { int rv = 0; - char *file, *ext; - char tmp[200], buf[MAXPATH], *path; X509 *cert = NULL; - BIO *in; WhichCerts ctype = (*cl)->d.s.ctype; - SMIME_STUFF_S *smime = ps->smime; switch(cmd){ case MC_CHOICE: @@ -1111,15 +1138,31 @@ manage_certs_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned flags) { CertList *cl; for(cl = DATACERT(ctype); cl != NULL && DELETEDCERT(cl) == 0; cl = cl->next); - if(cl != NULL && DELETEDCERT(cl) != 0) + if(cl != NULL && DELETEDCERT(cl) != 0){ smime_expunge_cert(ctype); - else + rv = 10; /* forces redraw */ + } + else{ q_status_message(SM_ORDER, 3, 3, _("No certificates marked deleted")); - rv = 10; /* forces redraw */ + rv = 0; + } break; } case MC_IMPORT: - import_certificate(ctype); + rv = import_certificate(ctype); + if(rv < 0){ + switch(rv){ + default: + case -1: + cmd_cancelled("Import certificate"); + break; + + case -2: + q_status_message1(SM_ORDER, 0, 2, _("Can't import certificate outside of %s"), + ps_global->VAR_OPER_DIR); + break; + } + } rv = 10; /* forces redraw */ break; @@ -1132,7 +1175,6 @@ manage_certs_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned flags) break; } - BIO_free(in); X509_free(cert); return rv; } @@ -1231,7 +1273,7 @@ void manage_certificates(struct pine *ps, WhichCerts ctype) if(ctmp == NULL){ ps->mangled_screen = 1; - smime_deinit(); + smime_reinit(); return; } @@ -1245,7 +1287,7 @@ void manage_certificates(struct pine *ps, WhichCerts ctype) } while (rv != 0); ps->mangled_screen = 1; - smime_deinit(); + smime_reinit(); } int @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Rev:9 by chappa@washington.edu. +# From configure.ac Rev:13 by chappa@washington.edu. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for alpine 2.19.9. # @@ -1834,7 +1834,8 @@ Optional Packages: --with-default-printer=VALUE Default printer (ANSI_PRINTER) --with-passfile=FILENAME - Password cache file (NOT secure, NOT recommended) + Password cache file (recommended when S/MIME is + enabled and configured) --without-local-password-cache Disable OS-specific password cache, if supported --with-local-password-cache-method @@ -5586,13 +5587,13 @@ if ${lt_cv_nm_interface+:} false; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:5589: $ac_compile\"" >&5) + (eval echo "\"\$as_me:5590: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:5592: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:5593: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:5595: output\"" >&5) + (eval echo "\"\$as_me:5596: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -6787,7 +6788,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 6790 "configure"' > conftest.$ac_ext + echo '#line 6791 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -8316,11 +8317,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8319: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8320: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8323: \$? = $ac_status" >&5 + echo "$as_me:8324: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -8655,11 +8656,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8658: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8659: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8662: \$? = $ac_status" >&5 + echo "$as_me:8663: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -8760,11 +8761,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8763: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8764: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8767: \$? = $ac_status" >&5 + echo "$as_me:8768: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -8815,11 +8816,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8818: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8819: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8822: \$? = $ac_status" >&5 + echo "$as_me:8823: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -11183,7 +11184,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11186 "configure" +#line 11187 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11279,7 +11280,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11282 "configure" +#line 11283 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -15549,6 +15550,7 @@ fi + # Check whether --with-local-password-cache was given. if test "${with_local_password_cache+set}" = set; then : withval=$with_local_password_cache; @@ -17088,8 +17090,8 @@ fi if test "$alpine_has_ldap" = "yes" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Including LDAP Support" >&5 -$as_echo "$as_me: Including LDAP Support" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: * * * Including LDAP Support" >&5 +$as_echo "$as_me: * * * Including LDAP Support" >&6;} $as_echo "#define ENABLE_LDAP /**/" >>confdefs.h @@ -19673,6 +19675,8 @@ $as_echo "$as_me: SSL Problem: certificate directory not found" >&6;} if test "x$with_smime" != "xno" ; then if test -n "$certdir" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: * * * S/MIME support enabled" >&5 +$as_echo "$as_me: * * * S/MIME support enabled" >&6;} $as_echo "#define SMIME /**/" >>confdefs.h diff --git a/configure.ac b/configure.ac index bc0d74a5..d3b35d0b 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ dnl */ AC_PREREQ([2.69]) -AC_REVISION([Rev:9 by chappa@washington.edu]) +AC_REVISION([Rev:13 by chappa@washington.edu]) dnl Alpine Version Number is in $srcdir/VERSION AC_INIT([alpine],[m4_normalize(m4_include(VERSION))],[chappa@washington.edu]) @@ -633,7 +633,7 @@ PINEVAR_UNQUOTED(default-printer, DF_DEFAULT_PRINTER, [ANSI_PRINTER], [Default p dnl set PASSFILE? AC_ARG_WITH(passfile, - AS_HELP_STRING([--with-passfile=FILENAME],[Password cache file (NOT secure, NOT recommended)]), + AS_HELP_STRING([--with-passfile=FILENAME],[Password cache file (recommended when S/MIME is enabled and configured)]), [ case "$withval" in no) @@ -646,6 +646,7 @@ AC_ARG_WITH(passfile, esac ]) + dnl os-specific credential cache? AC_ARG_WITH(local-password-cache, AS_HELP_STRING([--without-local-password-cache],[Disable OS-specific password cache, if supported]), @@ -669,7 +670,7 @@ if test -n "$alpine_PASSFILE" ; then AC_MSG_NOTICE([--with-passfile definition overrides OS-Specific password caching]) ;; esac - AC_DEFINE_UNQUOTED([PASSFILE], "$alpine_PASSFILE", [Password cache file (NOT secure. NOT recommended)]) + AC_DEFINE_UNQUOTED([PASSFILE], "$alpine_PASSFILE", [Password cache file (recommended if S/MIME is enabled and configured)]) fi dnl set DF_SSHPATH? @@ -1393,7 +1394,7 @@ if test "$alpine_with_ldap" = "yes" ; then ]) if test "$alpine_has_ldap" = "yes" ; then - AC_MSG_NOTICE([Including LDAP Support]) + AC_MSG_NOTICE([* * * Including LDAP Support]) AC_DEFINE([ENABLE_LDAP], [], [Enable LDAP query support]) dnl we use deprecated functions (ldap_get_values) @@ -1837,6 +1838,7 @@ else if test "x$with_smime" != "xno" ; then if test -n "$certdir" ; then + AC_MSG_NOTICE([* * * S/MIME support enabled]) AC_DEFINE([SMIME], [], [Enable S/MIME code]) AC_DEFINE_UNQUOTED([SMIME_SSLCERTS],"$certdir",[Directory where S/MIME CACerts are located]) fi diff --git a/doc/tech-notes/tech-notes.txt b/doc/tech-notes/tech-notes.txt index dba272e4..0bef022a 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.8, February 2014 + Version 2.19.9, March 2014 Table of Contents diff --git a/include/config.h.in b/include/config.h.in index d41cdee2..8c0097da 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -518,7 +518,7 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION -/* Password cache file (NOT secure. NOT recommended) */ +/* Password cache file (recommended if S/MIME is enabled and configured) */ #undef PASSFILE /* Program users use to change their password */ diff --git a/include/config.wnt.h b/include/config.wnt.h deleted file mode 100644 index a6634dd8..00000000 --- a/include/config.wnt.h +++ /dev/null @@ -1,581 +0,0 @@ -/* include/config.h.in. Generated from configure.ac by autoheader. */ - -/* Default configuration value */ -#define ANSI_PRINTER "attached-to-ansi" - -/* Enable background posting support */ -#undef BACKGROUND_POST - -/* Default configuration value */ -#define CHECK_POINT_FREQ 12 - -/* Default configuration value */ -#define CHECK_POINT_TIME 420 - -/* File name separator as character constant */ -#define C_FILESEP '\\' -/* Avoid OSX Conflict */ -/* #undef Comment */ - -/* Default configuration value */ -#define DEADLETTER "deadletr" - -/* Compile in debugging */ -#define DEBUG - -/* Default configuration value */ -#define DEBUGFILE "pinedebg.txt" - -/* Display debug messages in journal */ -#define DEBUGJOURNAL - -/* Default configuration value */ -#define DEFAULT_COLUMNS_ON_TERMINAL 80 - -/* Default configuration value */ -#define DEFAULT_DEBUG 2 - -/* Default configuration value */ -#define DEFAULT_LINES_ON_TERMINAL 25 - -/* Default configuration value */ -#define DEFAULT_SAVE "savemail" - -/* Default configuration value */ -#define DF_AB_SORT_RULE "fullname-with-lists-last" - -/* Default configuration value */ -#define DF_ADDRESSBOOK "addrbook" - -/* Default configuration value */ -#define DF_DEFAULT_FCC "sentmail" - -/* Default configuration value */ -#define DF_DEFAULT_PRINTER ANSI_PRINTER - -/* Default configuration value */ -#define DF_ELM_STYLE_SAVE "no" - -/* Default configuration value */ -#define DF_FCC_RULE "default-fcc" - -/* Default configuration value */ -#define DF_FILLCOL "74" - -/* Default configuration value */ -#define DF_FLD_SORT_RULE "alphabetical" - -/* Default configuration value */ -#define DF_HEADER_IN_REPLY "no" - -/* Default configuration value */ -#define DF_KBLOCK_PASSWD_COUNT "1" - -/* Default configuration value */ -#define DF_LOCAL_ADDRESS "postmaster" - -/* Default configuration value */ -#define DF_LOCAL_FULLNAME "Local Support" - -/* Default configuration value */ -#define DF_MAILCHECK "150" - -/* Default configuration value */ -#define DF_MAIL_DIRECTORY "mail" - -/* Default configuration value */ -#define DF_MARGIN "0" - -/* Default configuration value */ -#define DF_OLD_STYLE_REPLY "no" - -/* Default configuration value */ -#define DF_OVERLAP "2" - -#define DF_PINEDIR "\\pine" - -/* Default configuration value */ -#define DF_REMOTE_ABOOK_HISTORY "3" - -/* Default configuration value */ -#define DF_SAVED_MSG_NAME_RULE "default-folder" - -/* Default configuration value */ -#define DF_SAVE_BY_SENDER "no" - -/* Default configuration value */ -#define DF_SIGNATURE_FILE "pine.sig" - -/* Default configuration value */ -#define DF_SORT_KEY "arrival" - -/* Default configuration value */ -#define DF_STANDARD_PRINTER "lpr" - -/* Default configuration value */ -#define DF_USE_ONLY_DOMAIN_NAME "no" - -/* Define enable dmalloc debugging */ -/* #undef ENABLE_DMALLOC */ - -/* Enable LDAP query support - the build command defines this */ -/* #define ENABLE_LDAP */ - -/* Define to 1 if translation of program messages to the user's native - language is requested. */ -/* #define ENABLE_NLS 1 */ /* What should this be? - jpf */ - -/* Enable From address encoding in sent messages */ -/* #undef ENCODE_FROMS */ - -#define FORWARDED_FLAG "$Forwarded" - -/* Avoid OSX Conflict */ -/* #undef Fixed */ - -/* Define to 1 if `TIOCGWINSZ' requires <sys/ioctl.h>. */ -/* #undef GWINSZ_IN_SYS_IOCTL */ - -/* Define if systems uses old BSD-style terminal control */ -/* #undef HAS_SGTTY */ - -/* Define if systems uses termcap terminal database */ -/* #undef HAS_TERMCAP */ - -/* Define if systems uses terminfo terminal database */ -/* #undef HAS_TERMINFO */ - -/* Define if systems uses termio terminal control */ -/* #undef HAS_TERMIO */ - -/* Define if systems uses termios terminal control */ -/* #undef HAS_TERMIOS */ - -/* Define to 1 if you have the `bind' function. */ -/* #undef HAVE_BIND */ - -/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the - CoreFoundation framework. */ -/* #undef HAVE_CFLOCALECOPYCURRENT */ - -/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in - the CoreFoundation framework. */ -/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ - -/* Define to 1 if you have the `chown' function. */ -/* #undef HAVE_CHOWN */ - -/* Define if the GNU dcgettext() function is already present or preinstalled. - */ -/* #undef HAVE_DCGETTEXT */ - -/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. - */ -/* #undef HAVE_DIRENT_H */ - -/* Define to 1 if you have the <dlfcn.h> header file. */ -/* #define HAVE_DLFCN_H */ - -/* Define to 1 if you have the <errno.h> header file. */ -#define HAVE_ERRNO_H 1 - -/* Define to 1 if you have the <fcntl.h> header file. */ -#define HAVE_FCNTL_H 1 - -/* Define to 1 if you have the `fork' function. */ -/* #define HAVE_FORK */ - -/* Define to 1 if you have the `fsync' function. */ -/* #define HAVE_FSYNC */ - -/* Define to 1 if you have the `getpwnam' function. */ -/* #define HAVE_GETPWNAM */ - -/* Define to 1 if you have the `getpwuid' function. */ -/* #define HAVE_GETPWUID */ - -/* Define if the GNU gettext() function is already present or preinstalled. */ -/* #define HAVE_GETTEXT */ - -/* Define to 1 if you have the `gettimeofday' function. */ -/* #define HAVE_GETTIMEOFDAY */ - -/* Define to 1 if you have the `getuid' function. */ -/* #define HAVE_GETUID */ - -/* Define if you have the iconv() function. */ -/* #define HAVE_ICONV */ - -/* Define to 1 if you have the <inttypes.h> header file. */ -/* #define HAVE_INTTYPES_H */ - -/* Define to 1 if you have the `dmalloc' library (-ldmalloc). */ -/* #define HAVE_LIBDMALLOC */ - -/* Define to 1 if you have the `tcl' library (-ltcl). */ -/* #define HAVE_LIBTCL */ - -/* Define to 1 if you have the <limits.h> header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the `listen' function. */ -#define HAVE_LISTEN 1 - -/* Define to 1 if you have the <locale.h> header file. */ -#define HAVE_LOCALE_H 1 - -/* Define to 1 if you have the `mbstowcs' function. */ -#define HAVE_MBSTOWCS 1 - -/* Define to 1 if you have the `memcpy' function. */ -#define HAVE_MEMCPY 1 - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ -/* #define HAVE_NDIR_H */ - -/* Define to 1 if you have the <netdb.h> header file. */ -/* #define HAVE_NETDB_H */ - -/* Define to 1 if you have the <pwd.h> header file. */ -/* #define HAVE_PWD_H */ - -/* Define to 1 if you have the `pclose' function. */ -/* #define HAVE_PCLOSE 1 */ - -/* Define to 1 if you have the `poll' function. */ -/* #define HAVE_POLL */ - -/* Define to 1 if you have the `popen' function. */ -/* #define HAVE_POPEN 1 */ - -/* Define to 1 if you have the `qsort' function. */ -#define HAVE_QSORT 1 - -/* Define to 1 if you have the `read' function. */ -#define HAVE_READ 1 - -/* Define to 1 if you have the `rename' function. */ -/* #define HAVE_RENAME */ - -/* Define to 1 if you have the `select' function. */ -#define HAVE_SELECT 1 - -/* Define to 1 if you have the `setjmp' function. */ -#define HAVE_SETJMP 1 - -/* Define to 1 if you have the <setjmp.h> header file. */ -#define HAVE_SETJMP_H 1 - -/* Define to 1 if you have the `sigaction' function. */ -/* #define HAVE_SIGACTION */ - -/* Define to 1 if you have the `sigaddset' function. */ -/* #define HAVE_SIGADDSET */ - -/* Define to 1 if you have the `sigemptyset' function. */ -/* #define HAVE_SIGEMPTYSET */ - -/* Define to 1 if you have the `signal' function. */ -#define HAVE_SIGNAL 1 - -/* Define to 1 if you have the <signal.h> header file. */ -#define HAVE_SIGNAL_H 1 - -/* Define to 1 if you have the `sigprocmask' function. */ -/* #define HAVE_SIGPROCMASK */ - -/* Define to 1 if you have the `sigrelse' function. */ -/* #define HAVE_SIGRELSE */ - -/* Define to 1 if you have the `sigset' function. */ -/* #define HAVE_SIGSET */ - -/* Define to 1 if you have the `srandom' function. */ -/* #define HAVE_SRANDOM */ - -/* Define to 1 if you have the <stdint.h> header file. */ -/* #define HAVE_STDINT_H */ - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strchr' function. */ -#define HAVE_STRCHR 1 - -/* Define to 1 if you have the `strcoll' function and it is properly defined. - */ -#define HAVE_STRCOLL 1 - -/* Define to 1 if you have the <strings.h> header file. */ -/* #define HAVE_STRINGS_H */ - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the <stropts.h> header file. */ -/* #define HAVE_STROPTS_H */ - -/* Define to 1 if you have the `strtol' function. */ -#define HAVE_STRTOL 1 - -/* Define to 1 if you have the `strtoul' function. */ -#define HAVE_STRTOUL 1 - -/* Define to 1 if you have the <syslog.h> header file. */ -/* #define HAVE_SYSLOG_H */ - -/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'. - */ -/* #define HAVE_SYS_DIR_H */ - -/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'. - */ -/* #define HAVE_SYS_NDIR_H */ - -/* Define to 1 if you have the <sys/param.h> header file. */ -/* #define HAVE_SYS_PARAM_H */ - -/* Define to 1 if you have the <sys/poll.h> header file. */ -/* #define HAVE_SYS_POLL_H */ - -/* Define to 1 if you have the <sys/select.h> header file. */ -/* #define HAVE_SYS_SELECT_H */ - -/* Define to 1 if you have the <sys/socket.h> header file. */ -/* #define HAVE_SYS_SOCKET_H */ - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the <sys/un.h> header file. */ -/* #define HAVE_SYS_UN_H */ - -#define HAVE_SYS_UTIME_H 1 - -/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ -/* #define HAVE_SYS_WAIT_H */ - -/* Define to 1 if you have the <term.h> header file. */ -/* #define HAVE_TERM_H */ - -/* Define to 1 if you have the `tmpfile' function. */ -#define HAVE_TMPFILE 1 - -/* Define to 1 if you have the `truncate' function. */ -/* #define HAVE_TRUNCATE */ - -/* Define to 1 if you have the `uname' function. */ -/* #define HAVE_UNAME */ - -/* Define to 1 if the system has the type `union wait'. */ -/* #define HAVE_UNION_WAIT */ - -/* Define to 1 if you have the <unistd.h> header file. */ -/* #define HAVE_UNISTD_H */ - -/* Define to 1 if you have the `vfork' function. */ -/* #define HAVE_VFORK */ - -/* Define to 1 if you have the <vfork.h> header file. */ -/* #define HAVE_VFORK_H */ - -/* Define to 1 if you have the `wait' function. */ -/* #define HAVE_WAIT */ - -/* Define to 1 if you have the `wait4' function. */ -/* #define HAVE_WAIT4 */ - -/* Define to 1 if you have the `waitpid' function. */ -/* #define HAVE_WAITPID */ - -/* Define to 1 if you have the <wchar.h> header file. */ -#define HAVE_WCHAR_H 1 - -/* Define to 1 if `fork' works. */ -/* #define HAVE_WORKING_FORK */ - -/* Define to 1 if `vfork' works. */ -/* #define HAVE_WORKING_VFORK */ - -/* Always 1 because we use regex/regex.h */ -#define HAVE_REGEX_H 1 - -/* Avoid OSX Conflict */ -/* #undef Handle */ - -/* Default configuration value */ -#define INBOX_NAME "INBOX" - -/* Default configuration value */ -#define INTERRUPTED_MAIL "intruptd" - -/* Path to local inboxes for pico newmail check */ -#undef MAILDIR - -/* Default configuration value */ -#define MAX_FILLCOL 80 - -/* Default configuration value */ -#define MAX_SCREEN_COLS 500 - -/* Default configuration value */ -#define MAX_SCREEN_ROWS 200 - -/* File mode used to set readonly access */ -#undef MODE_READONLY - -/* Compile in mouse support */ -#define MOUSE -/* Windows has this set */ -#define EX_MOUSE - -/* Disallow users changing their From address */ -/* #undef NEVER_ALLOW_CHANGING_FROM */ - -/* Disable keyboard lock support */ -/* #undef NO_KEYBOARD_LOCK */ - -/* Default configuration value */ -#define NUMDEBUGFILES 4 - -/* Name of package */ -#define PACKAGE "alpine" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "chappa@gmx.com" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "alpine" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "alpine 2.19.9" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "alpine" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "2.19.9" - -/* Program users use to change their password */ -/* #undef PASSWD_PROG */ - -/* Define if system supports POSIX signal interface */ -/* #define POSIX_SIGNALS */ - -/* Default configuration value */ -#define POSTPONED_MAIL "postpone" - -/* Default configuration value */ -#define POSTPONED_MSGS "postpond" - -/* Default Trash folder for Web Alpine */ -#define TRASH_FOLDER "Trash" - -/* Define as the return type of signal handlers (`int' or `void'). */ -#define RETSIGTYPE void - -/* Define to the type of arg 1 for `select'. */ -#define SELECT_TYPE_ARG1 int - -/* Define to the type of args 2, 3 and 4 for `select'. */ -#define SELECT_TYPE_ARG234 (fd_set *) - -/* Define to the type of arg 5 for `select'. */ -#define SELECT_TYPE_ARG5 (struct timeval *) - -/* Local mail submission agent */ -/* #define SENDMAIL */ - -/* Local MSA flags for SMTP on stdin/stdout */ -/* #define SENDMAILFLAGS */ - -/* Posting agent to use when no nntp-servers defined */ -/* #define SENDNEWS */ - -/* The size of a `unsigned int', as computed by sizeof. */ -/* #define SIZEOF_UNSIGNED_INT */ - -/* The size of a `unsigned long', as computed by sizeof. */ -/* #define SIZEOF_UNSIGNED_LONG */ - -/* The size of a `unsigned short', as computed by sizeof. */ -/* #define SIZEOF_UNSIGNED_SHORT */ - -/* Program pico uses to check spelling */ -#define SPELLER - -/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */ -/* #define STAT_MACROS_BROKEN */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Default configuration value */ -#define SYSTEM_PINERC "pinerc" - -/* Default configuration value */ -/* #define SYSTEM_PINERC_FIXED */ - -/* Pine-Centric Host Specifier */ -#define SYSTYPE "WNT" - -/* Define if system supports SYSV signal interface */ -/* #define SYSV_SIGNALS */ - -/* File name separator as string constant */ -#define S_FILESEP "\\" - -/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ -/* #define TIME_WITH_SYS_TIME */ - -/* Define to 1 if your <sys/time.h> declares `struct tm'. */ -/* #define TM_IN_SYS_TIME */ - -/* System defined unsigned 16 bit integer */ -/* #define UINT16 uint16_t */ -/* #define UINT16 unsigned int */ - -/* System defined unsigned 32 bit integer */ -/* #define UINT32 uint32_t */ -/* #define UINT32 unsigned long */ - -/* Compile in quota check on startup */ -/* #define USE_QUOTAS */ - -/* Enable internal utf8 handling */ -#define UTF8_INTERNAL - -/* Version number of package */ -#define VERSION "2.19.9" - -/* Windows is just too different */ -#ifndef _WINDOWS -#define _WINDOWS -#endif - -/* Define to `int' if <sys/types.h> doesn't define. */ -/* #define gid_t */ - -/* Define to `int' if <sys/types.h> does not define. */ -/* #define mode_t */ - -/* Define to `int' if <sys/types.h> does not define. */ -#define pid_t int - -/* qsort compare function argument type */ -#define qsort_t void - -/* Define to `unsigned' if <sys/types.h> does not define. */ -/* #define size_t */ - -/* Define to `int' if <sys/types.h> doesn't define. */ -/* #define uid_t */ - -/* Define as `fork' if `vfork' does not work. */ -/* #define vfork */ diff --git a/pith/charconv/filesys.c b/pith/charconv/filesys.c index 3be45a5f..63ac7b13 100644 --- a/pith/charconv/filesys.c +++ b/pith/charconv/filesys.c @@ -663,7 +663,6 @@ our_getenv(char *env_variable) #endif /* !_WINDOWS */ } - int our_access(char *path, int mode) { diff --git a/pith/conftype.h b/pith/conftype.h index 38097f9e..11fe18f7 100644 --- a/pith/conftype.h +++ b/pith/conftype.h @@ -693,6 +693,9 @@ typedef struct smime_stuff { unsigned already_auto_asked:1; /* asked for passphrase automatically, not again */ volatile char passphrase[100]; /* storage for the entered passphrase */ char **passphrase_emailaddr; /* pointer to allocated storage */ +#ifdef PASSFILE + void *pwdcert; /* this has type (PERSONAL_CERT *) */ +#endif /* PASSFILE */ /* * If we are using the Container type it is easiest if we diff --git a/pith/options.h b/pith/options.h index c452b97b..4eadc9b7 100644 --- a/pith/options.h +++ b/pith/options.h @@ -232,6 +232,11 @@ extern int (*pith_smime_import_certificate)(char *, char *, size_t); /* * Required call to ask user to enter a password, with a given char * prompt */ -extern void (*pith_enter_password)(char *, char *, size_t); +extern int (*pith_smime_enter_password)(char *, char *, size_t); + +/* + * used to ask for data to users + */ +extern int (*pith_opt_get_data_prompt)(char *, char *, size_t); #endif /* PITH_OPTIONS_INCLUDED */ diff --git a/pith/pine.hlp b/pith/pine.hlp index af3d8207..59ab5574 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 48 2014-03-09 14:26:45 +Alpine Commit 52 2014-04-08 23:57:42 ============= h_news ================= <HTML> <HEAD> @@ -191,6 +191,8 @@ Additions include: HREF="h_index_cmd_expunge">help</A> for the expunge command. <LI> Pico: New subcommand of the search command, allows to reverse the direction of search. + <LI> If a password file is defined, and S/MIME is enabled, the key that is + used to encrypt the password file is saved under the name password_file_key. <LI> Add /tls1, /tls1_1, /tls1_2 and /dtls1 to the definition of a server to use different ways to connect using ssl, for example {server.com/tls1} will attempt to connect to @@ -248,7 +250,10 @@ Bugs that have been addressed include: <LI> S/MIME: Forwarding messages with multipart content-type failed to be signed with "Error writing pipe" message. Reported by Andreas Schamanek and Stefan Mueller. - <LI> S/MIME: Certificates are lost when using a pinerc file outside of the home directory. + <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 + SMIME making it not possible to sign or encrypt messages. <LI> Crash when tcp connection to NNTP server was lost after connection had been established, but lost immediately afterwards. <LI> WebAlpine: add _GNU_SOURCE to make pubcookie build. @@ -649,7 +654,7 @@ Changes included: Details on changes in previous (prerelease) versions of Alpine may be found at the following URL: <P> -<CENTER><SAMP><A HREF="http://www.washington.edu/alpine/changes.html">http://www.washington.edu/alpine/changes.html</A></SAMP></CENTER> +<CENTER><SAMP><A HREF="http://patches.freeiz.com/alpine/release/">http://patches.freeiz.com/alpine/release/</A></SAMP></CENTER> <P> <HR WIDTH="75%"><P> @@ -685,27 +690,25 @@ General Alpine configuration information can be found <A HREF="h_news_config">here</A>. <P> This is revision (<!--#echo var="ALPINE_REVISION"-->) of the Alpine software. -Alpine mailbox and <A HREF="http://www.washington.edu/imap/">IMAP</A> server +Alpine mailbox and <A HREF="https://github.com/jonabbey/panda-imap/">IMAP</A> server access is provided by the IMAP Toolkit Environment (c-client library) version <!--#echo var="C_CLIENT_VERSION"-->. <P> 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 dedicate their time to make a good software -even better! -software +a community of volunteers who make a good software even better! <P> Alpine Copyright 2013-2014 Eduardo Chappa, <BR> Copyright 2006-2008 University of Washington. <P> -Additional legal notices can be found <A HREF="h_news_legal">here</A> -or at the web URL: +Additional legal notices can be found <A HREF="h_news_legal">here</A>, +or instead you can find the Apache License, version 2.0 at the web URL: <P> -<CENTER><A HREF="http://www.washington.edu/alpine/overview/legal.html">http://www.washington.edu/alpine/overview/legal</A></CENTER> +<CENTER><A HREF="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</A></CENTER> <P> <End of Release Notes> @@ -1363,6 +1366,11 @@ listing of changes in Alpine <!--#echo var="ALPINE_VERSION"--> a change in the way an aspect of Alpine works. There, you will also find notes on Alpine configuration.<P> + <LI> The main site for Alpine contains information on configuring and solving problems + with Alpine, it can be found at + +<CENTER><A HREF="http://patches.freeiz.com/alpine/">http://patches.freeiz.com/alpine/</A></CENTER> + <LI> The Alpine Information Center (maintained by the University of Washington) World Wide Web site contains, among other things <UL> @@ -20017,6 +20025,18 @@ example. <P> </DD> +<DT>Loser</DT> +<DD>This option makes sense only for IMAP servers that do not perform +a SEARCH command correctly. If your filtering rules +fail to filter some messages, that should have been filtered, then this +option will make Alpine download all data necessary to perform that search. +There is a performance penalty when using this option. Downloading the +data to perfom the search will take longer than requesting the IMAP +server to perform the filtering, but the filtering will be done correctly. +<P> +</DD> + + <DT>Service</DT> <DD>This parameter requires an associated value. The default value is "IMAP" which indicates communication with the server based @@ -29315,11 +29335,11 @@ When this feature is set (the default) Alpine will select possible web hostnames from the displayed text and display them in boldface for selection. This can be useful when you receive messages referencing World Wide Web sites without the use of complete URLs; for example, specifying only -"www.washington.edu/alpine/" (which will <B>not</B> become a +"www.patches.freeiz.com/alpine/" (which will <B>not</B> become a selectable item by setting <A HREF="h_config_enable_view_url">"<!--#echo var="FEAT_enable-msg-view-urls"-->"</A>) rather than explicitly -"http://www.washington.edu/alpine/". +"http://www.patches.freeiz.com/alpine/". <P> The first available hostname is displayed in inverse. This is the "selected" hostname. Pressing RETURN will cause Alpine to display diff --git a/pith/readfile.c b/pith/readfile.c index 4fc9fa3e..cae03fc1 100644 --- a/pith/readfile.c +++ b/pith/readfile.c @@ -69,3 +69,31 @@ read_file(char *filename, int so_get_flags) return(return_text); } + +/* our copy, to_file and from_file must be full paths. from_file + * must exist. + */ +int +our_copy(char *to_file, char *from_file) +{ + STORE_S *in_cert, *out_cert; + unsigned char c; + + in_cert = so_get(FileStar, from_file, READ_ACCESS | READ_FROM_LOCALE); + if (in_cert == NULL) + return -1; + + out_cert = so_get(FileStar, to_file, WRITE_ACCESS | WRITE_TO_LOCALE); + if (out_cert == NULL){ + so_give(&in_cert); + return -1; + } + + while(so_readc(&c, in_cert) > 0) + so_writec(c, out_cert); + + so_give(&in_cert); + so_give(&out_cert); + + return 0; +} diff --git a/pith/readfile.h b/pith/readfile.h index 485144be..4be766f1 100644 --- a/pith/readfile.h +++ b/pith/readfile.h @@ -30,6 +30,6 @@ * Exported Prototypes */ char *read_file(char *, int); - +int our_copy(char *, char *); #endif /* PITH_READFILE_INCLUDED */ diff --git a/pith/smime.c b/pith/smime.c index e691ae68..05d41e7a 100644 --- a/pith/smime.c +++ b/pith/smime.c @@ -72,10 +72,14 @@ int smime_path(char *rpath, char *fpath, size_t len); int smime_extract_and_save_cert(PKCS7 *p7); int same_cert(X509 *, X509 *); CertList * certlist_from_personal_certs(PERSONAL_CERT *pc); +#ifdef PASSFILE +void load_key_and_cert(char *pathdir, char **keyfile, char **certfile, EVP_PKEY **pkey, X509 **pcert); +#endif /* PASSFILE */ int (*pith_opt_smime_get_passphrase)(void); int (*pith_smime_import_certificate)(char *, char *, size_t); -char *(*pith_enter_password)(char *prompt, char *, size_t); +int (*pith_smime_enter_password)(char *prompt, char *, size_t); +int (*pith_opt_get_data_prompt)(char *prompt, char *, size_t); static X509_STORE *s_cert_store; @@ -84,33 +88,277 @@ static int seeded = 0; static int egdsocket = 0; +#ifdef PASSFILE +void +load_key_and_cert(char *pathdir, char **keyfile, + char **certfile, EVP_PKEY **pkey, X509 **pcert) +{ + BIO *in; + char buf[MAXPATH+1], pathkey[MAXPATH+1], prompt[MAILTMPLEN], pass[MAILTMPLEN]; + DIR *dirp; + struct dirent *d; + int rc; + + if(keyfile) *keyfile = NULL; + if(certfile) *certfile = NULL; + if(pkey) *pkey = NULL; + if(pcert) *pcert = NULL; + + if(pathdir == NULL) return; + + if((dirp = opendir(pathdir)) != NULL){ + while((d=readdir(dirp)) != NULL){ + size_t ll; + + if((ll=strlen(d->d_name)) && ll > 4){ + if(keyfile && !strcmp(d->d_name+ll-4, ".key") && pkey == NULL){ + strncpy(buf, d->d_name, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + build_path(pathkey, pathdir, buf, sizeof(pathkey)); + buf[strlen(buf)-4] = '\0'; + if((in = BIO_new_file(pathkey, "r")) != NULL){ + + snprintf(prompt, sizeof(prompt), + _("Enter password of key <%s> to unlock password file: "), buf); + + do { + rc = 0; + pass[0] = '\0'; + if(pith_smime_enter_password) + rc = (*pith_smime_enter_password)((char *)prompt, (char *)pass, sizeof(pass)); + } while (rc!=0 && rc!=1 && rc>0); + + if((*pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, pass)) != NULL){ + *keyfile = cpystr(buf); + } + else + q_status_message1(SM_ORDER, 0, 2, + _("loading private key <%s> failed. Continuing..."), buf); + BIO_free(in); + } + } + + if(certfile && !strcmp(d->d_name+ll-4, ".crt") && pcert == NULL){ + strncpy(buf, d->d_name, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + build_path(pathkey, pathdir, buf, sizeof(pathkey)); + if((in = BIO_new_file(pathkey, "r")) != NULL){ + if((*pcert = PEM_read_bio_X509(in, NULL, NULL, NULL)) != NULL) + *certfile = cpystr(buf); + else{ + q_status_message1(SM_ORDER, 0, 2, + _("loading public certificate %s failed. Continuing..."), buf); + } + BIO_free(in); + } + } + } + } + } +} + + +/* setup a key and certificate to encrypt and decrypt a password file. + * These files will be saved in the .alpine-smime/.pwd directory, but its + * location can be setup in the command line with the -pwdcertdir option. + * Here are the rules: + * + * Check if the .alpine-smime/.pwd (or -pwdcertdir directory) exists, + * if not create it. If we are successful, move to the next step + * + * - If the user has a key/cert pair, setup is successful; + * - if the used does not have a key/cert pair, or one cannot be found + * create one, setup is successful; (TODO: implement this) + * - in any other case, setup is not successful. + * + * If setup is successful, setup ps_global->smime->pwdcert. + * If any of this fails, ps_global->smime->pwdcert will be null. + * Ok, that should do it. + */ +void +setup_pwdcert(void) +{ + int setup_dir = 0; /* make it non zero if we know which dir to use */ + int rc,i,j,k; + struct stat sbuf; + char pathdir[MAXPATH+1], pathkey[MAXPATH+1], fpath[MAXPATH+1], pass[200]; + char prompt[MAILTMPLEN]; + EVP_PKEY *pkey = NULL; + X509 *pcert = NULL; + BIO *in; + PERSONAL_CERT *pc, *pc2 = NULL; + + smime_init(); + + if(ps_global->pwdcertdir){ + if(our_stat(ps_global->pwdcertdir, &sbuf) == 0 + && ((sbuf.st_mode & S_IFMT) == S_IFDIR)){ + setup_dir++; + strncpy(pathdir, ps_global->pwdcertdir, sizeof(pathdir)); + pathdir[sizeof(pathdir)-1] = '\0'; + } + } else { + smime_path(DF_PASSWORD_DIR, pathdir, sizeof(pathdir)); + if(our_stat(pathdir, &sbuf) == 0){ + if((sbuf.st_mode & S_IFMT) == S_IFDIR) + setup_dir++; + } else { + if(can_access(pathdir, ACCESS_EXISTS) != 0 + && our_mkpath(pathdir, 0700) == 0) + setup_dir++; + } + } + + if(setup_dir == 0) + return; + + /* reuse setup dir to mean setup_key */ + setup_dir = 0; + + if(ps_global->smime->personal_certs){ + pc = (PERSONAL_CERT *) ps_global->smime->personal_certs; + if(ps_global->smime->privatetype == Directory){ + build_path(pathkey, ps_global->smime->privatepath, pc->name, sizeof(pathkey)); + strncat(pathkey, ".key", 4); + pathkey[sizeof(pathkey)-1] = '\0'; + if((in = BIO_new_file(pathkey, "r")) != NULL){ + snprintf(prompt, sizeof(prompt), + _("Enter password of key <%s> to unlock password file: "), pc->name); + + do { + rc = 0; + pass[0] = '\0'; + if(pith_smime_enter_password) + rc = (*pith_smime_enter_password)((char *)prompt, (char *)pass, sizeof(pass)); + } while (rc!=0 && rc!=1 && rc>0); + + if((pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, pass)) != NULL){ + pc2 = (PERSONAL_CERT *) fs_get(sizeof(PERSONAL_CERT)); + memset((void *)pc2, 0, sizeof(PERSONAL_CERT)); + pc2->name = cpystr(pc->name); + pc2->key = pkey; + pc2->cert = X509_dup(pc->cert); + build_path(fpath, pathdir, pc->name, sizeof(fpath)); + strncat(fpath, ".key", 4); + fpath[sizeof(fpath)-1] = '\0'; + if(our_stat(fpath, &sbuf) == 0){ + if((sbuf.st_mode & S_IFMT) == S_IFREG) + setup_dir++; + } + else if(our_copy(fpath, pathkey) == 0) + setup_dir++; + + if(setup_dir){ + setup_dir = 0; + + build_path(pathkey, ps_global->smime->publicpath, pc->name, sizeof(pathkey)); + strncat(pathkey, ".crt", 4); + pathkey[sizeof(pathkey)-1] = '\0'; + + build_path(fpath, pathdir, pc->name, sizeof(fpath)); + strncat(fpath, ".crt", 4); + fpath[sizeof(fpath)-1] = '\0'; + + if(our_stat(fpath, &sbuf) == 0){ + if((sbuf.st_mode & S_IFMT) == S_IFREG) + setup_dir++; + } + else if(our_copy(fpath, pathkey) == 0) + setup_dir++; + } + + if(setup_dir) + ps_global->smime->pwdcert = (void *) pc2; + else{ + free_personal_certs(&pc2); + return; + } + } + } + } + } /* end of if(ps_global->personal_certs) */ + else { + /* if we are here it might be because we have not read the .pinerc file + * or because there are no certificates to copy. Which one is it? + */ + /* look for a private key and public cert in pathdir + look for a public cert in pathdir + if not successful find one in DF_PRIVATE_DIR, etc. + if not successful, create a self-signed certificate and save it in pathdir. + if successful, load the keys. + if successful, set these keys as the keys to encrypt/decrypt. + */ + char buf[MAXPATH+1]; + char *keyfile; + char *certfile; + DIR *dirp; + struct dirent *d; + + load_key_and_cert(pathdir, &keyfile, &certfile, &pkey, &pcert); + if(certfile && keyfile) + setup_dir++; + + if(setup_dir == 0){ + if(keyfile == NULL){ + /* PATHCERTDIR(Private) must be null, so create a path */ + set_current_val(&ps_global->vars[V_PRIVATEKEY_DIR], TRUE, TRUE); + smime_path(ps_global->VAR_PRIVATEKEY_DIR, pathkey, MAXPATH); + load_key_and_cert(pathkey, &keyfile, NULL, &pkey, NULL); + } + if(certfile == NULL){ + /* PATHCERTDIR(Public) must be null, so create a path */ + set_current_val(&ps_global->vars[V_PUBLICCERT_DIR], TRUE, TRUE); + smime_path(ps_global->VAR_PUBLICCERT_DIR, pathkey, MAXPATH); + load_key_and_cert(pathkey, NULL, &certfile, NULL, &pcert); + } + + smime_reinit(); + if(certfile && keyfile) + setup_dir++; + } + + /* TODO: create self signed certificate */ + if(setup_dir == 0) + q_status_message(SM_ORDER, 0, 2, + _("No key/certificate pair found. Password file not encrypted.")); + + if(keyfile && certfile){ + pc2 = (PERSONAL_CERT *) fs_get(sizeof(PERSONAL_CERT)); + memset((void *)pc, 0, sizeof(PERSONAL_CERT)); + pc2->name = keyfile; + pc2->key = pkey; + pc2->cert = pcert; + ps_global->smime->pwdcert = (void *) pc2; + } + + if(certfile) + fs_give((void **)&certfile); + } +} +#endif /* PASSFILE */ + + int import_certificate(WhichCerts ctype) { int r = 1; char filename[MAXPATH+1], full_filename[MAXPATH+1], buf[MAXPATH+1]; - if(pith_smime_import_certificate == NULL) + if(pith_smime_import_certificate == NULL){ q_status_message(SM_ORDER, 0, 2, _("import of certificates not implemented yet!")); + return -1; + } smime_init(); r = (*pith_smime_import_certificate)(filename, full_filename, sizeof(filename) - 20); - if(r < 0){ - switch(r){ - default: - case -1: - cmd_cancelled("Import certificate"); - break; - case -2: - q_status_message1(SM_ORDER, 0, 2, - _("Can't import certificate outside of %s"), - ps_global->VAR_OPER_DIR); - break; - } - } else if (ctype == Private){ + ps_global->mangled_screen = 1; + + if(r < 0) + return r; + else if (ctype == Private){ char prompt[500], *s, *t; char pass[MAILTMPLEN+1]; BIO *in; @@ -132,8 +380,8 @@ import_certificate(WhichCerts ctype) _("Enter passphrase for <%s>: "), s ? s : filename); pass[0] = '\0'; - if(pith_enter_password) - (*pith_enter_password)(prompt, (char *)pass, sizeof(pass)); + if(pith_smime_enter_password) + (*pith_smime_enter_password)(prompt, (char *)pass, sizeof(pass)); if((key = PEM_read_bio_PrivateKey(in, NULL, NULL, pass)) != NULL){ if(SMHOLDERTYPE(ctype) == Directory){ @@ -223,7 +471,6 @@ import_certificate(WhichCerts ctype) } } if(DATACERT(ctype)) RENEWCERT(DATACERT(ctype)) = 1; - ps_global->mangled_screen = 1; return 0; } @@ -302,14 +549,12 @@ forget_private_keys(void) * directory where the .pinerc is located, since according to documentation, * the .alpine-smime directories are subdirectories of the home directory */ - int smime_path(char *rpath, char *fpath, size_t len) { *fpath = '\0'; if(rpath && *rpath){ size_t spl = strlen(rpath); - *fpath = '\0'; if(IS_REMOTE(rpath)){ if(spl < len - 1) strncpy(fpath, rpath, len-1); @@ -492,7 +737,12 @@ renew_cert_data(CertList **data, WhichCerts ctype) } } - +void +smime_reinit(void) +{ + smime_deinit(); + smime_init(); +} /* Installed as an atexit() handler to save the random data */ void @@ -531,7 +781,6 @@ smime_init(void) ERR_load_crypto_strings(); app_RAND_load_file(NULL); - openssl_extra_randomness(); ps_global->smime->inited = 1; } @@ -1631,57 +1880,56 @@ bio_from_store(STORE_S *store) * Encrypt file; given a path (char *) fp, replace the file * by an encrypted version of it. If (char *) text is not null, then * replace the text of (char *) fp by the encrypted version of (char *) text. + * certpath is the FULL path to the file containing the certificate used for + * encryption. */ int -encrypt_file(char *fp, char *text) +encrypt_file(char *fp, char *text, PERSONAL_CERT *pc) { const EVP_CIPHER *cipher = NULL; STACK_OF(X509) *encerts = NULL; X509 *cert; - PERSONAL_CERT *pcert; - BIO *in; + BIO *out; PKCS7 *p7 = NULL; FILE *fpp; - int rv = 0; + int i, rv = 0; + char *fname; + char emailaddress[MAILTMPLEN]; smime_init(); - if((pcert = ps_global->smime->personal_certs) == NULL) - return 0; - cipher = EVP_aes_256_cbc(); encerts = sk_X509_new_null(); - - if((cert = get_cert_for(pcert->name, Public)) != NULL) - sk_X509_push(encerts, cert); - else - goto end; + + if(pc == NULL) + goto end; + + sk_X509_push(encerts, pc->cert); if(text){ - in = BIO_new(BIO_s_mem()); - if(in == NULL) + if((out = BIO_new(BIO_s_mem())) == NULL) goto end; - (void) BIO_reset(in); - BIO_puts(in, text); + (void) BIO_reset(out); + BIO_puts(out, text); } else{ - if(!(in = BIO_new_file(fp, "rb"))) + if(!(out = BIO_new_file(fp, "rb"))) goto end; - BIO_read_filename(in, fp); + BIO_read_filename(out, fp); } - if((p7 = PKCS7_encrypt(encerts, in, cipher, 0)) == NULL) + if((p7 = PKCS7_encrypt(encerts, out, cipher, 0)) == NULL) goto end; - BIO_set_close(in, BIO_CLOSE); - BIO_free(in); - if(!(in = BIO_new_file(fp, "w"))) + BIO_set_close(out, BIO_CLOSE); + BIO_free(out); + if(!(out = BIO_new_file(fp, "w"))) goto end; - BIO_reset(in); - rv = PEM_write_bio_PKCS7(in, p7); - BIO_flush(in); + BIO_reset(out); + rv = PEM_write_bio_PKCS7(out, p7); + BIO_flush(out); end: - BIO_free(in); + BIO_free(out); PKCS7_free(p7); sk_X509_pop_free(encerts, X509_free); @@ -2171,94 +2419,60 @@ find_certificate_matching_pkcs7(PKCS7 *p7) /* decrypt an encrypted file. Args: fp - the path to the encrypted file. - rv - a code that thells the caller what happened inside the function + rv - a code that tells the caller what happened inside the function + pcert - a personal certificate that was used to encrypt this file Returns the decoded text allocated in a char *, whose memory must be freed by caller */ char * -decrypt_file(char *fp, int *rv) +decrypt_file(char *fp, int *rv, PERSONAL_CERT *pc) { PKCS7 *p7 = NULL; - char *text, *tmp; BIO *in = NULL, *out = NULL; - EVP_PKEY *pkey = NULL, *key = NULL; - PERSONAL_CERT *pcert = NULL; - X509 *recip, *cert; - STORE_S *outs = NULL, *store, *ins; - int i, j; + int i; long unsigned int len; + char *text, *s; void *ret; smime_init(); - if((text = read_file(fp, 0)) == NULL) + if(rv) *rv = -1; /* assume error initially */ + + if((text = read_file(fp, 0)) == NULL + || pc == NULL + || pc->key == NULL) return NULL; - tmp = fs_get(strlen(text) + (strlen(text) << 6) + 1); - for(j = 0, i = strlen("-----BEGIN PKCS7-----") + 1; text[i] != '\0' - && text[i] != '-'; j++, i++) - tmp[j] = text[i]; - tmp[j] = '\0'; + i = strlen("-----BEGIN PKCS7-----") + 1; + if((s = strchr(text+i, '-')) != NULL) + *s = '\0'; - ret = rfc822_base64(tmp, strlen(tmp), &len); + ret = rfc822_base64(text+i, strlen(text+i), &len); if((in = BIO_new_mem_buf((char *)ret, len)) != NULL){ p7 = d2i_PKCS7_bio(in, NULL); BIO_free(in); } - if(text) fs_give((void **)&text); - if(ret) fs_give((void **)&ret); - - if((pcert = ps_global->smime->personal_certs) == NULL) - goto end; - - if((i = load_private_key(pcert)) == 0 - && ps_global->smime - && ps_global->smime->need_passphrase - && !ps_global->smime->already_auto_asked) - for(; i == 0;){ - ps_global->smime->already_auto_asked = 1; - if(pith_opt_smime_get_passphrase){ - switch((*pith_opt_smime_get_passphrase)()){ - case 0 : i = load_private_key(pcert); - break; - - case 1 : i = -1; - break; - - default: break; /* repeat until we cancel */ - } - } - else - i = -2; - } - - if(rv) *rv = i; + if (ret) fs_give((void **)&ret); - if((key = pcert->key) == NULL) - goto end; - - recip = get_cert_for(pcert->name, Public); out = BIO_new(BIO_s_mem()); (void) BIO_reset(out); - i = PKCS7_decrypt(p7, key, recip, out, 0); - - if(F_OFF(F_REMEMBER_SMIME_PASSPHRASE,ps_global)) - forget_private_keys(); - - if(i == 0){ + if(PKCS7_decrypt(p7, pc->key, pc->cert, out, 0) == 0){ q_status_message1(SM_ORDER, 1, 1, _("Error decrypting: %s"), (char*) openssl_error_string()); goto end; } - BIO_get_mem_data(out, &tmp); - - text = cpystr(tmp); + BIO_get_mem_data(out, &s); + i = strlen(s); + fs_resize((void **)&text, i+1); + strncpy(text, s, i+1); + text[i] = '\0'; BIO_free(out); + if (rv) *rv = 1; end: PKCS7_free(p7); @@ -2766,6 +2980,14 @@ free_smime_struct(SMIME_STUFF_S **smime) (*smime)->personal_certs = NULL; } + if((*smime)->pwdcert){ + PERSONAL_CERT *pc; + + pc = (PERSONAL_CERT *) (*smime)->pwdcert; + free_personal_certs(&pc); + (*smime)->pwdcert = NULL; + } + if((*smime)->privatecontent) fs_give((void **) &(*smime)->privatecontent); diff --git a/pith/smime.h b/pith/smime.h index a8ca8dd2..3d65d924 100644 --- a/pith/smime.h +++ b/pith/smime.h @@ -27,14 +27,17 @@ #include <openssl/rand.h> #include <openssl/err.h> +#ifdef PASSFILE +#define DF_PASSWORD_DIR ".alpine-smime/.pwd" +#endif #define OUR_PKCS7_ENCLOSURE_SUBTYPE "x-pkcs7-enclosure" /* exported protoypes */ int smime_validate_cert(X509 *cert, long *error); -int encrypt_file(char *fp, char *text); -char *decrypt_file(char *fp, int *rv); +int encrypt_file(char *fp, char *text, PERSONAL_CERT *pc); +char *decrypt_file(char *fp, int *rv, PERSONAL_CERT *pc); int is_pkcs7_body(BODY *b); int fiddle_smime_message(BODY *b, long msgno); int encrypt_outgoing_message(METAENV *header, BODY **bodyP); @@ -45,6 +48,7 @@ PERSONAL_CERT *find_certificate_matching_recip_info(PKCS7_RECIP_INFO *ri); PERSONAL_CERT *get_personal_certs(char *path); void smime_init(void); void smime_deinit(void); +void smime_reinit(void); void renew_store(void); void renew_cert_data(CertList **data, WhichCerts ctype); BIO *print_private_key_information(char *email, int itype); @@ -61,7 +65,9 @@ int copy_publiccert_container_to_keychain(void); int copy_publiccert_keychain_to_container(void); #endif /* APPLEKEYCHAIN */ int import_certificate(WhichCerts); - +#ifdef PASSFILE +void setup_pwdcert(void); +#endif /* PASSFILE */ #endif /* PITH_SMIME_INCLUDED */ #endif /* SMIME */ diff --git a/pith/state.c b/pith/state.c index 07b77131..bf5ff24e 100644 --- a/pith/state.c +++ b/pith/state.c @@ -178,6 +178,10 @@ free_pine_struct(struct pine **pps) #ifdef PASSFILE if((*pps)->passfile) fs_give((void **)&(*pps)->passfile); +#ifdef SMIME + if((*pps)->pwdcertdir) + fs_give((void **)&(*pps)->pwdcertdir); +#endif /* SMIME inside PASSFILE */ #endif /* PASSFILE */ if((*pps)->hdr_colors) diff --git a/pith/state.h b/pith/state.h index b1a20da3..3fb4f2ee 100644 --- a/pith/state.h +++ b/pith/state.h @@ -271,6 +271,9 @@ struct pine { #endif #ifdef PASSFILE *passfile, +#ifdef SMIME + *pwdcertdir, +#endif /* SMIME inside PASSFILE */ #endif /* PASSFILE */ *pinerc, /* Location of user's pinerc */ *exceptions, /* Location of user's exceptions */ |