summaryrefslogtreecommitdiff
path: root/pith
diff options
context:
space:
mode:
Diffstat (limited to 'pith')
-rw-r--r--pith/adrbklib.c2
-rw-r--r--pith/conf.c5
-rw-r--r--pith/conftype.h11
-rw-r--r--pith/filter.c8
-rw-r--r--pith/help.c2
-rw-r--r--pith/imap.c2
-rw-r--r--pith/pine.hlp2
-rw-r--r--pith/send.c1
-rw-r--r--pith/smime.c601
-rw-r--r--pith/smkeys.c62
-rw-r--r--pith/smkeys.h2
-rw-r--r--pith/state.c7
-rw-r--r--pith/state.h3
-rw-r--r--pith/string.c6
-rw-r--r--pith/thread.c2
15 files changed, 398 insertions, 318 deletions
diff --git a/pith/adrbklib.c b/pith/adrbklib.c
index 1ccca637..51979bdc 100644
--- a/pith/adrbklib.c
+++ b/pith/adrbklib.c
@@ -3469,7 +3469,7 @@ io_error:
writing = 0;
- if(ab_stream){
+ if(ab_stream != NULL){
fclose(ab_stream);
ab_stream = (FILE *)NULL;
}
diff --git a/pith/conf.c b/pith/conf.c
index 1b216d3a..4bc9481b 100644
--- a/pith/conf.c
+++ b/pith/conf.c
@@ -5935,11 +5935,11 @@ write_pinerc(struct pine *ps, EditWhich which, int flags)
if(basep == NULL){
*basep = '\0';
slpath = (char *) fs_get((strlen(filename) + strlen(slink) + 2)*sizeof(char));
- sprintf(slpath, "%s/%s", filename, slink);
+ snprintf(slpath, sizeof(slpath), "%s/%s", filename, slink);
*basep = '/';
} else {
slpath = (char *) fs_get((strlen(ps_global->home_dir) + strlen(slink) + 2)*sizeof(char));
- sprintf(slpath, "%s/%s", ps_global->home_dir, slink);
+ snprintf(slpath, sizeof(slpath), "%s/%s", ps_global->home_dir, slink);
}
}
file_attrib_copy(tmp, slpath);
@@ -5964,6 +5964,7 @@ write_pinerc(struct pine *ps, EditWhich which, int flags)
char datebuf[200];
datebuf[0] = '\0';
+ we_cancel = 0;
if(!(flags & WRP_NOUSER))
we_cancel = busy_cue(_("Copying to remote config"), NULL, 1);
diff --git a/pith/conftype.h b/pith/conftype.h
index d8636b48..16e8de25 100644
--- a/pith/conftype.h
+++ b/pith/conftype.h
@@ -673,8 +673,8 @@ typedef enum {Directory, Container, Keychain, Nada} SmimeHolderType;
typedef enum {Public, Private, CACert} WhichCerts;
typedef struct certdata {
- unsigned deleted:1; /* certificate is marked deleted */
- unsigned renew:1; /* we must renew this list, set at top cert */
+ unsigned deleted:1; /* certificate is marked deleted */
+ unsigned renew:1; /* we must renew this list, set at top cert */
} CertData;
typedef struct certlist {
@@ -693,9 +693,6 @@ 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
@@ -724,7 +721,7 @@ typedef struct smime_stuff {
#define DATACERT(X) (((X) == Public ? ps_global->smime->publiccertlist \
: ((X) == Private ? ps_global->smime->privatecertlist \
- : ((X) == CACert ? ps_global->smime->cacertlist : NULL))))
+ : ps_global->smime->cacertlist)))
#define PATHCERTDIR(X) (((X) == Public ? ps_global->smime->publicpath \
: ((X) == Private ? ps_global->smime->privatepath \
@@ -740,7 +737,7 @@ typedef struct smime_stuff {
#define EXTCERT(X) (((X) == Public ? ".crt" \
: ((X) == Private ? ".key" \
- : ((X) == CACert ? ".crt" : NULL))))
+ : ((X) == CACert ? ".crt" : ""))))
#define DELETEDCERT(X) ((X)->data.deleted)
#define RENEWCERT(X) ((X)->data.renew)
diff --git a/pith/filter.c b/pith/filter.c
index d22b1215..c60416b1 100644
--- a/pith/filter.c
+++ b/pith/filter.c
@@ -3696,7 +3696,6 @@ html_pop(FILTER_S *fd, ELPROP_S *ep)
for(tp = HANDLERS(fd); tp && ep != EL(tp); tp = tp->below){
HANDLER_S *tp2;
- ELPROP_S *ep2;
dprint((3, "-- html error: bad nesting: given /%s expected /%s", ep->element, EL(tp)->element));
/* if no evidence of opening tag, ignore given closing tag */
@@ -6931,7 +6930,7 @@ rss_title(HANDLER_S *hd, int ch, int cmd)
RSS_ITEM_S *rip;
if(feed){
- if(rip = feed->items){
+ if((rip = feed->items) != NULL){
for(; rip->next; rip = rip->next)
;
@@ -7025,7 +7024,7 @@ rss_link(HANDLER_S *hd, int ch, int cmd)
RSS_ITEM_S *rip;
if(feed){
- if(rip = feed->items){
+ if((rip = feed->items) != NULL){
for(; rip->next; rip = rip->next)
;
@@ -7078,7 +7077,7 @@ rss_description(HANDLER_S *hd, int ch, int cmd)
RSS_ITEM_S *rip;
if(feed){
- if(rip = feed->items){
+ if((rip = feed->items) != NULL){
for(; rip->next; rip = rip->next)
;
@@ -8886,7 +8885,6 @@ void *
gf_html2plain_rss_opt(RSS_FEED_S **feedp, int flags)
{
HTML_OPT_S *op;
- int margin_l, margin_r;
op = (HTML_OPT_S *) fs_get(sizeof(HTML_OPT_S));
memset(op, 0, sizeof(HTML_OPT_S));
diff --git a/pith/help.c b/pith/help.c
index f92cab4f..6f61e885 100644
--- a/pith/help.c
+++ b/pith/help.c
@@ -216,7 +216,7 @@ debugjournal_to_file(FILE *dfile)
p = NULL;
}
- if(p){
+ if(p != NULL){
if(p->timestamp && p->timestamp[0]
&& (fputs(p->timestamp, dfile) == EOF
|| fputs(": ", dfile) == EOF))
diff --git a/pith/imap.c b/pith/imap.c
index 21732411..90219992 100644
--- a/pith/imap.c
+++ b/pith/imap.c
@@ -206,7 +206,7 @@ necessary.
void
mm_expunged(MAILSTREAM *stream, long unsigned int rawno)
{
- MESSAGECACHE *mc;
+ MESSAGECACHE *mc = NULL;
long i;
int is_current = 0;
MSGNO_S *msgmap;
diff --git a/pith/pine.hlp b/pith/pine.hlp
index 8e9120ba..70cf2041 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 58 2014-04-21 01:23:26
+Alpine Commit 59 2014-04-25 17:31:16
============= h_news =================
<HTML>
<HEAD>
diff --git a/pith/send.c b/pith/send.c
index 3f21f1f3..bd99d49a 100644
--- a/pith/send.c
+++ b/pith/send.c
@@ -1563,6 +1563,7 @@ set_priority_header(METAENV *header, char *value)
pf->textbuf = cpystr(value);
}
}
+ return pf;
}
diff --git a/pith/smime.c b/pith/smime.c
index b4ec7150..566e2be5 100644
--- a/pith/smime.c
+++ b/pith/smime.c
@@ -53,7 +53,7 @@ static void openssl_extra_randomness(void);
static int app_RAND_write_file(const char *file);
static const char *openssl_error_string(void);
static int load_private_key(PERSONAL_CERT *pcert);
-static void create_local_cache(char *h, char *base, BODY *b);
+static void create_local_cache(char *h, char *base, BODY *b, int type);
static long rfc822_output_func(void *b, char *string);
static void setup_pkcs7_body_for_signature(BODY *b, char *description,
char *type, char *filename);
@@ -74,7 +74,7 @@ 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);
+void load_key_and_cert(char *pathkeydir, char *pathcertdir, char **keyfile, char **certfile, EVP_PKEY **pkey, X509 **pcert);
#endif /* PASSFILE */
STACK_OF(X509) *get_chain_for_cert(X509 *cert, int *error);
EVP_PKEY *load_pkey_with_prompt(char *fpath, char *text, char *prompt);
@@ -91,54 +91,57 @@ static int egdsocket = 0;
#ifdef PASSFILE
+/*
+ * load key from pathkeydir and cert from pathcertdir. It chooses the first
+ * key/certificate pair that matches. Delete pairs that you do not want used,
+ * if you do not want them selected. All parameters must be non-null.
+ * Memory freed by caller.
+ */
void
-load_key_and_cert(char *pathdir, char **keyfile,
+load_key_and_cert(char *pathkeydir, char *pathcertdir, char **keyfile,
char **certfile, EVP_PKEY **pkey, X509 **pcert)
{
- BIO *in;
char buf[MAXPATH+1], pathkey[MAXPATH+1], prompt[MAILTMPLEN];
DIR *dirp;
struct dirent *d;
+ int b = 0;
- if(keyfile) *keyfile = NULL;
- if(certfile) *certfile = NULL;
- if(pkey) *pkey = NULL;
- if(pcert) *pcert = NULL;
+ if(pathkeydir == NULL || pathcertdir == NULL || keyfile == NULL
+ || pkey == NULL || certfile == NULL || pcert == NULL)
+ return;
- if(pathdir == NULL) return;
+ *keyfile = NULL;
+ *certfile = NULL;
+ *pkey = NULL;
+ *pcert = NULL;
- if((dirp = opendir(pathdir)) != NULL){
- while((d=readdir(dirp)) != NULL){
+ if((dirp = opendir(pathkeydir)) != NULL){
+ while(b == 0 && (d=readdir(dirp)) != NULL){
size_t ll;
if((ll=strlen(d->d_name)) && ll > 4){
- if(pkey && *pkey == NULL && keyfile && !strcmp(d->d_name+ll-4, ".key")){
+ if(!strcmp(d->d_name+ll-4, ".key")){
strncpy(buf, d->d_name, sizeof(buf));
buf[sizeof(buf)-1] = '\0';
- build_path(pathkey, pathdir, buf, sizeof(pathkey));
- buf[strlen(buf)-4] = '\0';
+ build_path(pathkey, pathkeydir, buf, sizeof(pathkey));
+ buf[strlen(buf)-4] = '\0';
snprintf(prompt, sizeof(prompt),
_("Enter password of key <%s> to unlock password file: "), buf);
- if((*pkey = load_pkey_with_prompt(pathkey, NULL, prompt)) != NULL)
- *keyfile = cpystr(buf);
- }
-
- if(pcert && *pcert == NULL && certfile && !strcmp(d->d_name+ll-4, ".crt")){
- strncpy(buf, d->d_name, sizeof(buf));
- 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);
+ if((*pkey = load_pkey_with_prompt(pathkey, NULL, prompt)) != NULL){
+ if(load_cert_for_key(pathcertdir, *pkey, certfile, pcert)){
+ b = 1; /* break */
+ *keyfile = cpystr(buf);
+ } else {
+ EVP_PKEY_free(*pkey);
+ *pkey = NULL;
+ q_status_message1(SM_ORDER, 0, 2,
+ _("Cannot find certificate that matches key <%s>. Continuing..."), buf);
+ }
}
}
}
}
+ closedir(dirp);
}
}
@@ -151,32 +154,36 @@ load_key_and_cert(char *pathdir, char **keyfile,
* 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)
+ * - If the user has a key/cert pair, in the .alpine-smime/.pwd dir
+ * setup is successful;
+ * - if the user does not have a key/cert pair, look to see if
+ * ps_global->smime->personal_certs is already setup, if so, use it.
+ * - if ps_global->smime->personal_certs is not set up, see if we can
+ * find a certificate/cert pair in the default locations at compilation
+ * time. (~/.alpine-smime/private and ~/.alpine-smime/public
+ * - if none of this is successful, create a key/certificate pair
+ * (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.
+ * If setup is successful, setup ps_global->pwdcert.
+ * If any of this fails, ps_global->pwdcert will be null.
* Ok, that should do it.
*/
void
setup_pwdcert(void **pwdcert)
{
+ int we_inited = 0;
int setup_dir = 0; /* make it non zero if we know which dir to use */
- int i,j,k;
struct stat sbuf;
- char pathdir[MAXPATH+1], pathkey[MAXPATH+1], fpath[MAXPATH+1];
- char prompt[MAILTMPLEN], buf[MAXPATH+1];
+ char pathdir[MAXPATH+1], pathkey[MAXPATH+1], fpath[MAXPATH+1], pathcert[MAXPATH+1];
+ char fpath2[MAXPATH+1], prompt[MAILTMPLEN];
char *keyfile, *certfile, *text;
- DIR *dirp;
- struct dirent *d;
EVP_PKEY *pkey = NULL;
X509 *pcert = NULL;
- BIO *in = NULL;
PERSONAL_CERT *pc, *pc2 = NULL;
- smime_init();
+ if(pwdcert == NULL)
+ return;
if(ps_global->pwdcertdir){
if(our_stat(ps_global->pwdcertdir, &sbuf) == 0
@@ -190,91 +197,52 @@ setup_pwdcert(void **pwdcert)
if(our_stat(pathdir, &sbuf) == 0){
if((sbuf.st_mode & S_IFMT) == S_IFDIR)
setup_dir++;
- } else {
- if(can_access(pathdir, ACCESS_EXISTS) != 0
+ } 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;
-
- /* BUG: add container support */
- 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){
- build_path(fpath, pathdir, keyfile, sizeof(fpath));
- strncat(fpath, ".key", 4);
- fpath[sizeof(fpath)-1] = '\0';
-
- smime_path(ps_global->VAR_PRIVATEKEY_DIR, pathkey, MAXPATH);
- strncat(pathkey, "/", 1);
- strncat(pathkey, keyfile, strlen(keyfile));
- strncat(pathkey, ".key", 4);
- pathkey[sizeof(pathkey)-1] = '\0';
-
- if(our_copy(fpath, pathkey) == 0)
- setup_dir++;
-
- if(setup_dir){
- setup_dir = 0;
-
- build_path(fpath, pathdir, certfile, sizeof(fpath));
-
- smime_path(ps_global->VAR_PUBLICCERT_DIR, pathkey, MAXPATH);
- strncat(pathkey, "/", 1);
- strncat(pathkey, keyfile, strlen(keyfile));
- strncat(pathkey, ".crt", 4);
- pathkey[sizeof(pathkey)-1] = '\0';
-
- if(our_copy(fpath, pathkey) == 0)
- setup_dir++;
- }
- }
+ load_key_and_cert(pathdir, pathdir, &keyfile, &certfile, &pkey, &pcert);
+
+ if(certfile && keyfile){
+ pc = (PERSONAL_CERT *) fs_get(sizeof(PERSONAL_CERT));
+ memset((void *)pc, 0, sizeof(PERSONAL_CERT));
+ pc->name = keyfile;
+ pc->key = pkey;
+ pc->cert = pcert;
+ *pwdcert = (void *) pc;
+ fs_give((void **)&certfile);
+ return;
}
- if(setup_dir > 0){
- pc2 = (PERSONAL_CERT *) fs_get(sizeof(PERSONAL_CERT));
- memset((void *)pc2, 0, sizeof(PERSONAL_CERT));
- pc2->name = keyfile;
- pc2->key = pkey;
- pc2->cert = pcert;
- if(pwdcert) *pwdcert = (void *) pc2;
- }
+ /* if the user gave a pwdcertdir and there is nothing there, do not
+ * continue. Let the user initialize on their own this directory.
+ */
+ if(ps_global->pwdcertdir != NULL)
+ return;
- if(certfile)
- fs_give((void **)&certfile);
+ /* look to see if there are any certificates lying around, first
+ * we try to load ps_global->smime to see if that has information
+ * we can use. If we are the process filling the smime structure
+ * we deinit at the end, since this might not do a full init.
+ */
+ if(ps_global && ps_global->smime && !ps_global->smime->inited){
+ we_inited++;
+ smime_init();
+ }
- if(setup_dir == 0){ /* try looking for an existent key */
- if(ps_global->smime->personal_certs){
- pc = (PERSONAL_CERT *) ps_global->smime->personal_certs;
- if(ps_global->smime->privatetype == Directory){
+ /* at this point ps_global->smime->inited == 1 */
+ if(ps_global->smime && ps_global->smime->personal_certs != NULL){
+ 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';
text = NULL;
- } else { /* ps_global->smime->privatetype == Container */
+ } else if (ps_global->smime->privatetype == Container){
if(pc->keytext == NULL){ /* we should *never* be here, but just in case */
if(ps_global->smime->privatecontent != NULL){
char tmp[MAILTMPLEN], *s, *t, c;
@@ -294,85 +262,138 @@ setup_pwdcert(void **pwdcert)
}
if(pc->keytext != NULL) /* we should go straigth here */
text = pc->keytext;
- }
- if((pathkey && *pathkey) || text){
- snprintf(prompt, sizeof(prompt),
- _("Enter password of key <%s> to unlock password file: "), pc->name);
-
- if((pkey = load_pkey_with_prompt(pathkey, text, prompt)) != 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);
-
- /* now copy the keys and certs, starting by the key... */
- 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(ps_global->smime->privatetype == Directory){
- if(our_copy(fpath, pathkey) == 0)
- setup_dir++;
- } else { /* ps_global->smime->privatetype == Container */
+ } else if (ps_global->smime->privatetype == Keychain){
+ pathkey[0] = '\0'; /* no apple key chain support yet */
+ text = NULL;
+ }
+ if((pathkey && *pathkey) || text){
+ snprintf(prompt, sizeof(prompt),
+ _("Enter password of key <%s> to unlock password file: "), pc->name);
+
+ if((pkey = load_pkey_with_prompt(pathkey, text, prompt)) != 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);
+
+ /* now copy the keys and certs, starting by the key... */
+ build_path(fpath, pathdir, pc->name, sizeof(fpath));
+ strncat(fpath, ".key", 4);
+ fpath[sizeof(fpath)-1] = '\0';
+ if(our_stat(fpath, &sbuf) == 0){ /* if fpath exists */
+ if((sbuf.st_mode & S_IFMT) == S_IFREG) /* and is a regular file */
+ setup_dir++; /* we are done */
+ } else if(ps_global->smime->privatetype == Directory){
+ if(our_copy(fpath, pathkey) == 0)
+ setup_dir++;
+ } else if(ps_global->smime->privatetype == Container){
BIO *out;
if((out = BIO_new_file(fpath, "w")) != NULL){
if(BIO_puts(out, pc->keytext) > 0)
setup_dir++;
BIO_free(out);
}
- }
- }
+ } else if(ps_global->smime->privatetype == Keychain){
+ /* add support for Apple Mac OS X */
+ }
+ }
- /* successful copy of key, now continue with certificate */
- if(setup_dir){
- setup_dir = 0;
+ /* successful copy of key, now continue with certificate */
+ 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(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';
+ 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(ps_global->smime->privatetype == Directory){
- if(our_copy(fpath, pathkey) == 0)
- setup_dir++;
- } else { /* ps_global->smime->privatetype == Container */
- BIO *out;
- if((out = BIO_new_file(fpath, "w")) != NULL){
- if(PEM_write_bio_X509(out, pc->cert))
- setup_dir++;
+ if(our_stat(fpath, &sbuf) == 0){
+ if((sbuf.st_mode & S_IFMT) == S_IFREG)
+ setup_dir++;
+ }
+ else if(ps_global->smime->privatetype == Directory){
+ if(our_copy(fpath, pathkey) == 0)
+ setup_dir++;
+ } else if(ps_global->smime->privatetype == Container) {
+ BIO *out;
+ if((out = BIO_new_file(fpath, "w")) != NULL){
+ if(PEM_write_bio_X509(out, pc->cert))
+ setup_dir++;
BIO_free(out);
- }
- }
- }
- }
+ }
+ } else if (ps_global->smime->privatetype == Keychain) {
+ /* add support for Mac OS X */
+ }
+ }
- if(setup_dir)
- if(pwdcert) *pwdcert = (void *) pc2;
- else{
- free_personal_certs(&pc2);
- return;
- }
- } /* end of if(pkey != NULL) */
- BIO_free(in);
- } /* end of if(in != NULL) */
- } /* end of if(ps_global->personal_certs) */
+ if(setup_dir){
+ *pwdcert = (void *) pc2;
+ return;
+ }
+ else if(pc2 != NULL)
+ free_personal_certs(&pc2);
+ } /* if (pathkey...) */
+ } /* if(ps_global->smime->personal_certs) */
+
+
+ if(setup_dir == 0){
+ /* 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, sizeof(pathkey));
+
+ /* 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, pathcert, sizeof(pathcert));
+
+ /* BUG: this does not support local containers */
+ load_key_and_cert(pathkey, pathcert, &keyfile, &certfile, &pkey, &pcert);
+
+ if(certfile && keyfile){
+ build_path(fpath, pathdir, keyfile, sizeof(fpath));
+ strncat(fpath, ".key", 4);
+ fpath[sizeof(fpath)-1] = '\0';
+
+ build_path(fpath2, pathkey, keyfile, sizeof(fpath));
+ strncat(fpath2, ".key", 4);
+ fpath2[sizeof(fpath2)-1] = '\0';
+
+ if(our_copy(fpath, fpath2) == 0)
+ setup_dir++;
+
+ if(setup_dir){
+ setup_dir = 0;
+
+ build_path(fpath, pathdir, certfile, sizeof(fpath));
+ build_path(fpath2, pathcert, certfile, sizeof(fpath2));
+
+ if(our_copy(fpath, fpath2) == 0)
+ 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){
+ pc = (PERSONAL_CERT *) fs_get(sizeof(PERSONAL_CERT));
+ memset((void *)pc, 0, sizeof(PERSONAL_CERT));
+ pc->name = keyfile;
+ pc->key = pkey;
+ pc->cert = pcert;
+ *pwdcert = (void *) pc;
+ fs_give((void **)&certfile);
+ return;
+ }
+
+/* TODO: create self signed certificate
+ q_status_message(SM_ORDER, 2, 2,
+ _("No key/certificate pair found for password file encryption support"));
+*/
+
+ if(we_inited)
+ smime_deinit();
}
#endif /* PASSFILE */
@@ -385,20 +406,20 @@ smime_expunge_cert(WhichCerts ctype)
{
int count, removed;
CertList *cl, *dummy, *data;
- char *path, *ext, buf[MAXPATH+1];
+ char *path, buf[MAXPATH+1];
char *contents;
if(DATACERT(ctype)== NULL)
return -1;
- /* data cert is the way we unify certificate management across functions, but it is
- * not where we really save the information in the case ctype is equal to Private.
- * What we will do is to update the datacert, and in the case of ctype equal to Private
- * use the updated certdata to update the personal_certs data.
+ /* data cert is the way we unify certificate management across
+ * functions, but it is not where we really save the information in the
+ * case ctype is equal to Private. What we will do is to update the
+ * datacert, and in the case of ctype equal to Private use the updated
+ * certdata to update the personal_certs data.
*/
path = PATHCERTDIR(ctype);
- ext = EXTCERT(ctype);
if(path){
/* add a fake certificate at the beginning of the list */
@@ -415,8 +436,10 @@ smime_expunge_cert(WhichCerts ctype)
removed = 1; /* assume success */
if(SMHOLDERTYPE(ctype) == Directory){
build_path(buf, path, cl->next->name, sizeof(buf));
- if(ctype == Private && strlen(buf) + strlen(EXTCERT(Private)) < sizeof(buf))
- strcat(buf, EXTCERT(Private));
+ if(ctype == Private && strlen(buf) + strlen(EXTCERT(Private)) < sizeof(buf)){
+ strncat(buf, EXTCERT(Private), 4);
+ buf[sizeof(buf)-1] = '\0';
+ }
if(our_unlink(buf) < 0){
q_status_message1(SM_ORDER, 3, 3, _("Error removing certificate %s"), cl->next->name);
@@ -503,7 +526,6 @@ load_pkey_with_prompt(char *fpath, char *text, char *prompt)
{
EVP_PKEY *pkey;
int rc = 0; /* rc == 1, cancel, rc == 0 success */
- int we_clear = 0;
char pass[MAILTMPLEN+1];
BIO *in;
@@ -556,9 +578,7 @@ import_certificate(WhichCerts ctype)
return r;
else if (ctype == Private){
char prompt[500], *s, *t;
- BIO *in;
EVP_PKEY *key = NULL;
- PERSONAL_CERT *pc;
if(!ps_global->smime->privatecertlist){
ps_global->smime->privatecertlist = fs_get(sizeof(CertList));
@@ -569,11 +589,14 @@ import_certificate(WhichCerts ctype)
if(s) *(s-1) = 0;
snprintf(prompt, sizeof(prompt), _("Enter passphrase for <%s>: "), filename);
+ prompt[sizeof(prompt)-1] = '\0';
if((key = load_pkey_with_prompt(full_filename, NULL, prompt)) != NULL){
if(SMHOLDERTYPE(ctype) == Directory){
build_path(buf, PATHCERTDIR(ctype), filename, sizeof(buf));
- if(strcmp(buf + strlen(buf) - 4, EXTCERT(ctype)) != 0 && strlen(buf) + 4 < sizeof(buf))
- strcat(buf, EXTCERT(ctype));
+ if(strcmp(buf + strlen(buf) - 4, EXTCERT(ctype)) != 0 && strlen(buf) + 4 < sizeof(buf)){
+ strncat(buf, EXTCERT(ctype), 4);
+ buf[sizeof(buf)-1] = '\0';
+ }
rc = our_copy(buf, full_filename);
}
else /* if(SMHOLDERTYPE(ctype) == Container){ */
@@ -595,8 +618,10 @@ import_certificate(WhichCerts ctype)
if((cert = PEM_read_bio_X509(ins, NULL, NULL, NULL)) != NULL){
if(SMHOLDERTYPE(ctype) == Directory){
build_path(buf, PATHCERTDIR(ctype), filename, sizeof(buf));
- if(strcmp(buf + strlen(buf) - 4, ".crt") != 0 && strlen(buf) + 4 < sizeof(buf))
- strcat(buf, EXTCERT(ctype));
+ if(strcmp(buf + strlen(buf) - 4, ".crt") != 0 && strlen(buf) + 4 < sizeof(buf)){
+ strncat(buf, EXTCERT(ctype), 4);
+ buf[sizeof(buf)-1] = '\0';
+ }
rc = our_copy(buf, full_filename);
}
@@ -887,23 +912,23 @@ renew_cert_data(CertList **data, WhichCerts ctype)
X509_LOOKUP *lookup = NULL;
X509_STORE *store = NULL;
- if((store = X509_STORE_new()) != NULL)
+ if((store = X509_STORE_new()) != NULL){
if((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) == NULL){
X509_STORE_free(store);
store = NULL;
- }
- else{
- free_certlist(data);
- if(SMHOLDERTYPE(ctype) == Directory)
- add_certs_in_dir(lookup, PATHCERTDIR(ctype), EXTCERT(ctype), data);
- else /* if(SMHOLDERTYPE(ctype) == Container) */
- *data = mem_to_certlist(CONTENTCERTLIST(ctype), ctype);
- if(data && *data)
- RENEWCERT(*data) = 0;
- if(ctype == Public)
- ps_global->smime->publiccertlist = *data;
- else
- ps_global->smime->cacertlist = *data;
+ } else{
+ free_certlist(data);
+ if(SMHOLDERTYPE(ctype) == Directory)
+ add_certs_in_dir(lookup, PATHCERTDIR(ctype), EXTCERT(ctype), data);
+ else /* if(SMHOLDERTYPE(ctype) == Container) */
+ *data = mem_to_certlist(CONTENTCERTLIST(ctype), ctype);
+ if(data && *data)
+ RENEWCERT(*data) = 0;
+ if(ctype == Public)
+ ps_global->smime->publiccertlist = *data;
+ else
+ ps_global->smime->cacertlist = *data;
+ }
}
}
}
@@ -1074,8 +1099,6 @@ setup_privatekey_storage(void)
/* private keys in a directory of files */
if(!privatekeycontainer){
- PERSONAL_CERT *result = NULL;
-
ps_global->smime->privatetype = Directory;
path[0] = '\0';
@@ -1289,7 +1312,8 @@ add_file_to_container(WhichCerts ctype, char *fpath, char *altname)
: (ctype == Private ? ps_global->smime->privatecontent
: ps_global->smime->cacontent);
char *name;
- char *s, c;
+ char *s;
+ unsigned char c;
struct stat sbuf;
STORE_S *in = NULL;
int rv = -1; /* assume error */
@@ -1323,7 +1347,7 @@ add_file_to_container(WhichCerts ctype, char *fpath, char *altname)
*content++ = '\n';
while(so_readc(&c, in))
- *content++ = c;
+ *content++ = (char) c;
*content = '\0';
switch(ctype){
@@ -1899,26 +1923,29 @@ dump_bio_to_file(BIO *in, char *filename)
/*
* Recursively stash a pointer to the decrypted data in our
* manufactured body.
+ * parameters: type: call of type 1, save the base and header for multipart messages
+ call of type 0, do not save the base and header for multipart messages
*/
static void
-create_local_cache(char *h, char *base, BODY *b)
+create_local_cache(char *h, char *base, BODY *b, int type)
{
if(b->type==TYPEMULTIPART){
PART *p;
-#if 0
- cpytxt(&b->contents.text, base + b->contents.offset, b->size.bytes);
-#else
- /*
- * We don't really want to copy the real body contents. It shouldn't be
+ if(type == 1){
+ cpytxt(&b->mime.text, h+b->mime.offset, b->mime.text.size);
+ cpytxt(&b->contents.text, base + b->contents.offset, b->size.bytes);
+ } else if(type == 0){
+ /*
+ * We don't really want to copy the real body contents. It shouldn't be
* used, and in the case of a message with attachments, we'll be
* duplicating the files multiple times.
*/
- cpytxt(&b->contents.text, "BODY UNAVAILABLE", 16);
-#endif
+ cpytxt(&b->contents.text, "BODY UNAVAILABLE", 16);
- for(p=b->nested.part; p; p=p->next)
- create_local_cache(h, base, (BODY*) p);
+ for(p=b->nested.part; p; p=p->next)
+ create_local_cache(h, base, (BODY *) p, type);
+ }
}
else{
cpytxt(&b->mime.text, h+b->mime.offset, b->mime.text.size);
@@ -2149,21 +2176,16 @@ encrypt_file(char *fp, char *text, PERSONAL_CERT *pc)
{
const EVP_CIPHER *cipher = NULL;
STACK_OF(X509) *encerts = NULL;
- X509 *cert;
- BIO *out;
+ BIO *out = NULL;
PKCS7 *p7 = NULL;
- FILE *fpp;
- int i, rv = 0;
- char *fname;
- char emailaddress[MAILTMPLEN];
+ int rv = 0;
+
+ if(pc == NULL)
+ return 0;
- smime_init();
cipher = EVP_aes_256_cbc();
encerts = sk_X509_new_null();
- if(pc == NULL)
- goto end;
-
sk_X509_push(encerts, X509_dup(pc->cert));
if(text){
@@ -2190,7 +2212,8 @@ encrypt_file(char *fp, char *text, PERSONAL_CERT *pc)
BIO_flush(out);
end:
- BIO_free(out);
+ if(out != NULL)
+ BIO_free(out);
PKCS7_free(p7);
sk_X509_pop_free(encerts, X509_free);
@@ -2393,7 +2416,6 @@ int smime_extract_and_save_cert(PKCS7 *p7)
X509 *x, *cert;
char **email;
int i, j;
- long error;
if((signers = PKCS7_get0_signers(p7, NULL, 0)) == NULL)
return -1;
@@ -2481,8 +2503,8 @@ free_smime_body_sparep(void **sparep)
When Alpine sends a message, it constructs that message, computes the
signature, but then it forgets the message it signed and reconstructs it
again. Since it signs a message containing a notice about "mime aware
- tools", but it does not send that we do not include that in the part that
- is signed, and that takes care of much of the problems.
+ tools", but it does not send that we do not include that in the part
+ that is signed, and that takes care of much of the problems.
Another problem is what is received from the servers. All servers tested
seem to transmit the message that was signed intact and Alpine can check
@@ -2493,10 +2515,10 @@ free_smime_body_sparep(void **sparep)
When a message containing and attachment is sent by Alpine, UW-IMAP,
Panda-IMAP, Gmail, and local reading of folders send exactly the message
- that was sent by Alpine, but GMX.com, Exchange, and probably other servers
- add a trailing \r\n in the message, so when validating the signature,
- these messages will not validate. There are several things that can be
- done.
+ that was sent by Alpine, but GMX.com, Exchange, and probably other
+ servers add a trailing \r\n in the message, so when validating the
+ signature, these messages will not validate. There are several things
+ that can be done.
1. Add a trailing \r\n to any message that contains attachments, sign that
and send that. In this way, all messages will validate with all
@@ -2507,21 +2529,40 @@ free_smime_body_sparep(void **sparep)
remove the trailing \r\n and try to revalidate again.
3. We do not add \r\n to validate a message that we sent, because that
- would only work in Alpine, and not in any other client. That would not
- be a good thing to do.
+ would only work in Alpine, and not in any other client. That would
+ not be a good thing to do.
PART II
- Now we have to deal with encrypted and signed messages. The problem is that
- c-client makes all its pointers point to "on disk" content, but since we
- decrypted the data earlier, we have to make sure of two things. One is that we
- saved that data (so we do not have to decrypt it again) and second that we can
- use it.
+ Now we have to deal with encrypted and signed messages. The problem is
+ that c-client makes all its pointers point to "on disk" content, but
+ since we decrypted the data earlier, we have to make sure of two things.
+ One is that we saved that data (so we do not have to decrypt it again)
+ and second that we can use it.
In order to save the data we use create_local_cache, so that we do not
have to redecrypt the message. Once this is saved, c-client functions will
find it and send it to us in mail_fetch_mime and mail_fetch_body.
+ PART III
+
+ When we are trying to verify messages with detached signatures, some
+ imap servers send incorrect information in the mail_fetch_mime call. By
+ incorrect I mean that this is not fetched directly from the message, but
+ it is read from the message, processed, and then the processed part is
+ sent to us, so this text might not agree with what is in the message,
+ and so the validation of the signature might fail. However, the good
+ news is that the message validates if saved to a local folder. This
+ means that if normal validation does not work we can make it work by
+ saving the message locally and validating that. This is implemented
+ below, and causes delay in the display of the message. I am considering
+ at this time not to do this automatically, but wait for the user to tell
+ us to do it for them by means of a command available in the
+ mail_view_screen. This might help in other situations, where a message
+ is supposed to have an attachment, but it can not be seen in the
+ 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.
*/
/*
@@ -2537,9 +2578,10 @@ do_detached_signature_verify(BODY *b, long msgno, char *section)
int result, modified_the_body = 0;
unsigned long mimelen, bodylen;
char newSec[100], *mimetext, *bodytext;
- char *what_we_did, *s;
+ char *what_we_did;
dprint((9, "do_detached_signature_verify(msgno=%ld type=%d subtype=%s section=%s)", msgno, b->type, b->subtype ? b->subtype : "NULL", (section && *section) ? section : (section != NULL) ? "Top" : "NULL"));
+
smime_init();
snprintf(newSec, sizeof(newSec), "%s%s1", section ? section : "", (section && *section) ? "." : "");
@@ -2587,7 +2629,6 @@ do_detached_signature_verify(BODY *b, long msgno, char *section)
STORE_S *msg_so;
BIO_free(in);
- in = NULL;
if((in = BIO_new(BIO_s_mem())) != NULL
&& (fetch = mail_fetch_header(ps_global->mail_stream, msgno, NULL,
NULL, &hlen, FT_PEEK)) != NULL
@@ -2600,32 +2641,19 @@ do_detached_signature_verify(BODY *b, long msgno, char *section)
char *h = (char *) so_text(msg_so);
char *bstart = strstr(h, "\r\n\r\n");
ENVELOPE *env;
- BODY *body, *b2;
- char *s;
-
- dprint((1, "h = \"%s\"", h));
+ BODY *body;
bstart += 4;
INIT(&bs, mail_string, bstart, tlen);
- rfc822_parse_msg_full(&env, &body, h, (bstart-h)+2, &bs, BADHOST, 0, 0);
+ rfc822_parse_msg_full(&env, &body, h, (bstart-h), &bs, BADHOST, 0, 0);
mail_free_envelope(&env);
- if(b->nested.part->body.mime.text.data)
- fs_give((void **)&b->nested.part->body.mime.text.data);
- b->nested.part->body.mime.text.size = body->nested.part->body.mime.text.size;
- b->nested.part->body.mime.offset = body->nested.part->body.mime.offset;
-
- if(b->nested.part->body.contents.text.data)
- fs_give((void **)&b->nested.part->body.contents.text.data);
- b->nested.part->body.contents.text.size = body->nested.part->body.contents.text.size;
- b->nested.part->body.contents.offset = body->nested.part->body.contents.offset;
-
- create_local_cache(bstart, bstart, &b->nested.part->body);
-
+ mail_free_body_part(&b->nested.part);
+ b->nested.part = body->nested.part;
+ create_local_cache(bstart, bstart, &b->nested.part->body, 1);
modified_the_body = 1;
snprintf(newSec, sizeof(newSec), "%s%s1", section ? section : "", (section && *section) ? "." : "");
-
mimetext = mail_fetch_mime(ps_global->mail_stream, msgno, (char*) newSec, &mimelen, 0);
if(mimetext)
@@ -2634,20 +2662,25 @@ do_detached_signature_verify(BODY *b, long msgno, char *section)
if (mimetext == NULL || bodytext == NULL)
return modified_the_body;
+ snprintf(newSec, sizeof(newSec), "%s%s2", section ? section : "", (section && *section) ? "." : "");
+
+ if((p7 = get_pkcs7_from_part(msgno, newSec)) == NULL)
+ return modified_the_body;
+
(void) BIO_reset(in);
BIO_write(in, mimetext, mimelen);
BIO_write(in, bodytext, bodylen);
so_give(&msg_so);
if(((result = do_signature_verify(p7, in, NULL, 1)) == 0)
- && bodylen > 2
- && (strncmp(bodytext+bodylen-2,"\r\n", 2) == 0)){
- BUF_MEM *biobuf = NULL;
-
- BIO_get_mem_ptr(in, &biobuf);
- if(biobuf)
- BUF_MEM_grow(biobuf, mimelen + bodylen - 2);
- result = do_signature_verify(p7, in, NULL, 0);
+ && bodylen > 2
+ && (strncmp(bodytext+bodylen-2,"\r\n", 2) == 0)){
+ BUF_MEM *biobuf = NULL;
+
+ BIO_get_mem_ptr(in, &biobuf);
+ if(biobuf)
+ BUF_MEM_grow(biobuf, mimelen + bodylen - 2);
+ result = do_signature_verify(p7, in, NULL, 0);
}
}
}
@@ -2738,17 +2771,13 @@ char *
decrypt_file(char *fp, int *rv, PERSONAL_CERT *pc)
{
PKCS7 *p7 = NULL;
- char *text, *tmp, file_name[MAILTMPLEN];
+ char *text, *tmp;
BIO *in = NULL, *out = NULL;
- EVP_PKEY *pkey = NULL;
- X509 *recip;
int i, j;
long unsigned int len;
void *ret;
- smime_init();
-
- if(pc == NULL || (text = read_file(fp, 0)) == NULL)
+ if(pc == NULL || (text = read_file(fp, 0)) == NULL || *text == '\0')
return NULL;
tmp = fs_get(strlen(text) + (strlen(text) << 6) + 1);
@@ -2757,7 +2786,7 @@ decrypt_file(char *fp, int *rv, PERSONAL_CERT *pc)
tmp[j] = text[i];
tmp[j] = '\0';
- ret = rfc822_base64(tmp, strlen(tmp), &len);
+ ret = rfc822_base64((unsigned char *)tmp, strlen(tmp), &len);
if((in = BIO_new_mem_buf((char *)ret, len)) != NULL){
p7 = d2i_PKCS7_bio(in, NULL);
@@ -2981,7 +3010,7 @@ do_decoding(BODY *b, long msgno, const char *section)
* the decrypted data. Otherwise, it'll try to load it from the original
* data. Eek.
*/
- create_local_cache(bstart-b->nested.part->body.mime.offset, bstart, &b->nested.part->body);
+ create_local_cache(bstart-b->nested.part->body.mime.offset, bstart, &b->nested.part->body, 0);
modified_the_body = 1;
}
@@ -3329,16 +3358,6 @@ free_smime_struct(SMIME_STUFF_S **smime)
(*smime)->personal_certs = NULL;
}
-#ifdef PASSFILE
- if((*smime)->pwdcert){
- PERSONAL_CERT *pc;
-
- pc = (PERSONAL_CERT *) (*smime)->pwdcert;
- free_personal_certs(&pc);
- (*smime)->pwdcert = NULL;
- }
-#endif /* PASSFILE */
-
if((*smime)->privatecontent)
fs_give((void **) &(*smime)->privatecontent);
diff --git a/pith/smkeys.c b/pith/smkeys.c
index 7d57cdac..56103e91 100644
--- a/pith/smkeys.c
+++ b/pith/smkeys.c
@@ -399,11 +399,12 @@ save_cert_for(char *email, X509 *cert, WhichCerts ctype)
CertList *clist = DATACERT(ctype);
add_to_end_of_certlist(&clist, email, X509_dup(cert));
+
switch(ctype){
- Private: ps_global->smime->privatecertlist = clist; break;
- Public : ps_global->smime->publiccertlist = clist; break;
- CACert : ps_global->smime->cacertlist = clist; break;
- default: break;
+ case Private: ps_global->smime->privatecertlist = clist; break;
+ case Public : ps_global->smime->publiccertlist = clist; break;
+ case CACert : ps_global->smime->cacertlist = clist; break;
+ default: break;
}
if(!upath)
@@ -555,7 +556,6 @@ save_cert_for(char *email, X509 *cert, WhichCerts ctype)
X509 *
get_cert_for(char *email, WhichCerts ctype)
{
- char *path;
char certfilename[MAXPATH];
char emailaddr[MAXPATH];
X509 *cert = NULL;
@@ -666,6 +666,58 @@ get_cert_for(char *email, WhichCerts ctype)
return cert;
}
+/*
+ * load_cert_for_key finds a certificate in pathdir that matches a private key
+ * pkey. It returns its name in certfile, and the certificate in *pcert.
+ * return value: success: different from zero, failure 0. If both certfile
+ * and pcert are NULL, this function returns if there is certificate that
+ * matches the given key.
+ */
+int
+load_cert_for_key(char *pathdir, EVP_PKEY *pkey, char **certfile, X509 **pcert)
+{
+ DIR *dirp;
+ struct dirent *d;
+ int rv = 0;
+ BIO *in;
+ X509 *x;
+ char buf[MAXPATH+1], pathcert[MAXPATH+1];
+
+ if(pathdir == NULL || pkey == NULL)
+ return 0;
+
+ if(certfile) *certfile = NULL;
+ if(pcert) *pcert = NULL;
+
+ if((dirp = opendir(pathdir)) != NULL){
+ while(rv == 0 && (d=readdir(dirp)) != NULL){
+ size_t ll;
+
+ if((ll=strlen(d->d_name)) && ll > 4){
+ if(!strcmp(d->d_name+ll-4, ".crt")){
+ strncpy(buf, d->d_name, sizeof(buf));
+ buf[sizeof(buf)-1] = '\0';
+ build_path(pathcert, pathdir, buf, sizeof(pathcert));
+ if((in = BIO_new_file(pathcert, "r")) != NULL){
+ if((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) != NULL){
+ if(X509_check_private_key(x, pkey) > 0){
+ rv = 1;
+ if(certfile) *certfile = cpystr(buf);
+ if(pcert) *pcert = x;
+ }
+ else
+ X509_free(x);
+ }
+ BIO_free(in);
+ }
+ }
+ }
+ }
+ closedir(dirp);
+ }
+ return rv;
+}
+
PERSONAL_CERT *
mem_to_personal_certs(char *contents)
diff --git a/pith/smkeys.h b/pith/smkeys.h
index 58705bd7..0781a018 100644
--- a/pith/smkeys.h
+++ b/pith/smkeys.h
@@ -59,6 +59,8 @@ PERSONAL_CERT *mem_to_personal_certs(char *contents);
void free_personal_certs(PERSONAL_CERT **pc);
void get_fingerprint(X509 *cert, const EVP_MD *type, char *buf, size_t maxLen);
int certlist_to_file(char *filename, CertList *certlist);
+int load_cert_for_key(char *pathdir, EVP_PKEY *pkey, char **certfile, X509 **pcert);
+
#endif /* PITH_SMKEYS_INCLUDED */
#endif /* SMIME */
diff --git a/pith/state.c b/pith/state.c
index bf5ff24e..84775792 100644
--- a/pith/state.c
+++ b/pith/state.c
@@ -179,6 +179,13 @@ free_pine_struct(struct pine **pps)
if((*pps)->passfile)
fs_give((void **)&(*pps)->passfile);
#ifdef SMIME
+ if((*pps)->pwdcert){
+ PERSONAL_CERT *pc;
+
+ pc = (PERSONAL_CERT *) (*pps)->pwdcert;
+ free_personal_certs(&pc);
+ (*pps)->pwdcert = NULL;
+ }
if((*pps)->pwdcertdir)
fs_give((void **)&(*pps)->pwdcertdir);
#endif /* SMIME inside PASSFILE */
diff --git a/pith/state.h b/pith/state.h
index 3fb4f2ee..3c0b19dc 100644
--- a/pith/state.h
+++ b/pith/state.h
@@ -356,6 +356,9 @@ struct pine {
#ifdef SMIME
SMIME_STUFF_S *smime;
+#ifdef PASSFILE
+ void *pwdcert; /* this is of type PERSONAL_CERT */
+#endif /* PASSFILE inside SMIME */
#endif /* SMIME */
struct variable *vars;
diff --git a/pith/string.c b/pith/string.c
index e23b704f..6ad1045a 100644
--- a/pith/string.c
+++ b/pith/string.c
@@ -431,7 +431,7 @@ short_str(char *src, char *buf, size_t buflen, int wid, WhereDots where)
}
q = buf;
- if(first){
+ if(first > 0){
q += utf8_to_width(q, src, buflen, first, &got_width);
if(got_width != first){
if(second)
@@ -448,7 +448,7 @@ short_str(char *src, char *buf, size_t buflen, int wid, WhereDots where)
q += strlen(q);
}
- if(second){
+ if(second > 0){
char *p;
p = utf8_count_back_width(src, src+strlen(src), second, &got_width);
@@ -2738,7 +2738,7 @@ add_escapes(char *src, char *quote_these_chars, int quoting_char,
char *
copy_quoted_string_asis(char *src)
{
- char *q, *p;
+ char *q = NULL, *p;
int done = 0, quotes = 0;
if(src){
diff --git a/pith/thread.c b/pith/thread.c
index f31dea67..a46e21a3 100644
--- a/pith/thread.c
+++ b/pith/thread.c
@@ -884,7 +884,7 @@ collapse_or_expand(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap,
void
select_thread_stmp(struct pine *state, MAILSTREAM *stream, MSGNO_S *msgmap)
{
- PINETHRD_S *thrd;
+ PINETHRD_S *thrd = NULL;
unsigned long rawno, in_thread, set_in_thread, save_branch;
/* ugly bit means the same thing as return of 1 from individual_select */