diff options
author | Eduardo Chappa <chappa@washington.edu> | 2016-02-28 14:12:49 -0700 |
---|---|---|
committer | Eduardo Chappa <chappa@washington.edu> | 2016-02-28 14:12:49 -0700 |
commit | 4bf825141cd564a2c5a23c55f79e04665c428641 (patch) | |
tree | 4fd033202e91d414985f4896fe63b0039adc2cf2 /pith | |
parent | dc1062254da60a0f2bf8d52e861dbf4fb7b8cab9 (diff) | |
download | alpine-4bf825141cd564a2c5a23c55f79e04665c428641.tar.xz |
* Add the ability to change the private key and certificates used
to encrypt a password file in the SMIME setup configuration screen.
Diffstat (limited to 'pith')
-rw-r--r-- | pith/conftype.h | 51 | ||||
-rw-r--r-- | pith/imap.c | 52 | ||||
-rw-r--r-- | pith/imap.h | 4 | ||||
-rw-r--r-- | pith/pine.hlp | 54 | ||||
-rw-r--r-- | pith/smime.c | 261 | ||||
-rw-r--r-- | pith/smime.h | 2 | ||||
-rw-r--r-- | pith/smkeys.c | 90 | ||||
-rw-r--r-- | pith/smkeys.h | 4 | ||||
-rw-r--r-- | pith/state.h | 9 |
9 files changed, 426 insertions, 101 deletions
diff --git a/pith/conftype.h b/pith/conftype.h index abae2b0d..3c9316fa 100644 --- a/pith/conftype.h +++ b/pith/conftype.h @@ -675,7 +675,7 @@ typedef enum {Main, Post, None} EditWhich; typedef enum {Directory, Container, Keychain, Nada} SmimeHolderType; -typedef enum {Public, Private, CACert} WhichCerts; +typedef enum {Public, Private, CACert, Password} WhichCerts; typedef struct certdata { unsigned deleted:1; /* certificate is marked deleted */ @@ -721,7 +721,6 @@ typedef struct smime_stuff { char *privatecontent; CertList *privatecertlist; CertList *backupprivatecertlist; - void *backuppersonal_certs; /* this is type (PERSONAL_CERT *) */ void *personal_certs; /* this is type (PERSONAL_CERT *) */ SmimeHolderType catype; @@ -732,25 +731,35 @@ typedef struct smime_stuff { } SMIME_STUFF_S; -#define BACKUPDATACERT(X) (((X) == Public ? ps_global->smime->backuppubliccertlist \ - : ((X) == Private ? ps_global->smime->backupprivatecertlist \ - : ps_global->smime->backupcacertlist))) - -#define DATACERT(X) (((X) == Public ? ps_global->smime->publiccertlist \ - : ((X) == Private ? ps_global->smime->privatecertlist \ - : ps_global->smime->cacertlist))) - -#define PATHCERTDIR(X) (((X) == Public ? ps_global->smime->publicpath \ - : ((X) == Private ? ps_global->smime->privatepath \ - : ((X) == CACert ? ps_global->smime->capath : NULL)))) - -#define CONTENTCERTLIST(X) (((X) == Public ? ps_global->smime->publiccontent \ - : ((X) == Private ? ps_global->smime->privatecontent \ - : ((X) == CACert ? ps_global->smime->cacontent : NULL)))) - -#define SMHOLDERTYPE(X) (((X) == Public ? ps_global->smime->publictype \ - : ((X) == Private ? ps_global->smime->privatetype \ - : ((X) == CACert ? ps_global->smime->catype : Nada)))) +#define BACKUPDATACERT(X) ((X) == Public ? ps_global->smime->backuppubliccertlist : \ + (X) == Private ? ps_global->smime->backupprivatecertlist : \ + (X) == CACert ? ps_global->smime->backupcacertlist : \ + (X) == Password ? (CertList *) ps_global->backuppassword : \ + NULL) + +#define DATACERT(X) ((X) == Public ? ps_global->smime->publiccertlist : \ + (X) == Private ? ps_global->smime->privatecertlist : \ + (X) == CACert ? ps_global->smime->cacertlist : \ + (X) == Password ? (CertList *) ps_global->pwdcertlist : \ + NULL) + +#define PATHCERTDIR(X) ((X) == Public ? ps_global->smime->publicpath : \ + (X) == Private ? ps_global->smime->privatepath : \ + (X) == CACert ? ps_global->smime->capath : \ + (X) == Password ? ps_global->pwdcertdir : \ + NULL) + +#define CONTENTCERTLIST(X) ((X) == Public ? ps_global->smime->publiccontent : \ + (X) == Private ? ps_global->smime->privatecontent : \ + (X) == CACert ? ps_global->smime->cacontent : \ + (X) == Password ? ps_global->pwdcertcontent : \ + NULL) + +#define SMHOLDERTYPE(X) ((X) == Public ? ps_global->smime->publictype : \ + (X) == Private ? ps_global->smime->privatetype : \ + (X) == CACert ? ps_global->smime->catype : \ + (X) == Password ? Directory : \ + Nada) #define EXTCERT(X) (((X) == Public ? ".crt" \ : ((X) == Private ? ".key" \ diff --git a/pith/imap.c b/pith/imap.c index da338712..e02f46ba 100644 --- a/pith/imap.c +++ b/pith/imap.c @@ -1109,3 +1109,55 @@ ps_get(size_t size) return(block); } + +#ifdef PASSFILE +char * +passfile_name(char *pinerc, char *path, size_t len) +{ + struct stat sbuf; + char *p = NULL; + int i, j; + + if(!path || !((pinerc && pinerc[0]) || ps_global->passfile)) + return(NULL); + + if(ps_global->passfile) + strncpy(path, ps_global->passfile, len-1); + else{ + if((p = last_cmpnt(pinerc)) && *(p-1) && *(p-1) != PASSFILE[0]) + for(i = 0; pinerc < p && i < len; pinerc++, i++) + path[i] = *pinerc; + else + i = 0; + + for(j = 0; (i < len) && (path[i] = PASSFILE[j]); i++, j++) + ; + + } + + path[len-1] = '\0'; + + dprint((9, "Looking for passfile \"%s\"\n", + path ? path : "?")); + +#if defined(DOS) || defined(OS2) + return((our_stat(path, &sbuf) == 0 + && ((sbuf.st_mode & S_IFMT) == S_IFREG)) + ? path : NULL); +#else + /* First, make sure it's ours and not sym-linked */ + if(our_lstat(path, &sbuf) == 0 + && ((sbuf.st_mode & S_IFMT) == S_IFREG) + && sbuf.st_uid == getuid()){ + /* if too liberal permissions, fix them */ + if((sbuf.st_mode & 077) != 0) + if(our_chmod(path, sbuf.st_mode & ~077) != 0) + return(NULL); + + return(path); + } + else + return(NULL); +#endif +} +#endif /* PASSFILE */ diff --git a/pith/imap.h b/pith/imap.h index 86a0b533..1b30e456 100644 --- a/pith/imap.h +++ b/pith/imap.h @@ -131,5 +131,9 @@ void imap_flush_passwd_cache(int); void set_read_predicted(int); void mm_login_work (NETMBX *mb,char *user,char *pwd,long trial,char *usethisprompt, char *altuserforcache); +/* this is necessary to figure out the name of the password file of the application */ +#ifdef PASSFILE +char *passfile_name(char *, char *, size_t); +#endif /* PASSFILE */ #endif /* PITH_IMAP_INCLUDED */ diff --git a/pith/pine.hlp b/pith/pine.hlp index de174d2b..2e0fd0c4 100644 --- a/pith/pine.hlp +++ b/pith/pine.hlp @@ -197,6 +197,10 @@ Additions include: in lower case, as some SMTP servers, such as those of libero.it reject messages if the boundary attribute is in uppercase. + <LI> Add the ability to change the private key and certificates used + to encrypt a password file in the SMIME setup configuration screen. + <A HREF="h_config_smime_password_file_certificates">Learn more</A> + <LI> SMIME: The ctrl-E command that gives information on the certificate is only available for messages that have a signed or encrypted part. @@ -35422,6 +35426,56 @@ import a command to this collection. <End of help on this topic> </BODY> </HTML> +====== h_config_smime_password_file_certificates ===== +<HTML> +<HEAD> +<TITLE>S/MIME: Manage Password File Certificates</TITLE> +</HEAD> +<BODY> +<H1>S/MIME: Manage Password File Certificates</H1> + +UNIX Alpine only. +<P> +This option allows you to manage the certificates that are used to +encrypt and decrypt your password file. This is useful in case you +want to change the certificates used to encrypt your password file. +<P> +In order to avoid unauthorized use of this option, you are asked to +enter the password of the current private key used to encrypt your +password file. +<P> +Once you have entered your password for the current key, you enter a +screen where you can import your new key, and see the information on your +current key. +<P> +To import a new key press "RETURN" and enter the location of +the new key. You will be asked to enter the password of the new key. If +this part of the process is successful, Alpine will search for the +certificate that matches that key. If your key is named +"your_email@address.com.key", then Alpine will look for your +certificate in the same directory in the file named +"your_email@address.com.crt", otherwise it will look for it +as part of your key (that is, it will look to see if your certificate +is in the file "your_email@address.com.key"), if all of this +fails, Alpine will ask you to enter the location of the certificate +that matches the key you unlocked. If a certificate is found, it will be +used, and in this case, the password file will be read, decrypted with the +old key and encrypted with the new key. Once this is done, the new key and +certificates are saved, and the old keys are permanently deleted. +<P> +Alpine does not create a backup of your password file, or your old keys +that will be replaced. If you need to keep old copies, you will have to do +this operation outside Alpine. +<UL> +<LI><A HREF="h_mainhelp_smime">General S/MIME help</A> +</UL><P> +<P> +<UL> +<LI><A HREF="h_finding_help">Finding more information and requesting help</A> +</UL><P> +<End of help on this topic> +</BODY> +</HTML> ====== h_certificate_information ===== <HTML> <HEAD> diff --git a/pith/smime.c b/pith/smime.c index 6f9efc7f..d32a97c9 100644 --- a/pith/smime.c +++ b/pith/smime.c @@ -42,6 +42,9 @@ static char rcsid[] = "$Id: smime.c 1176 2008-09-29 21:16:42Z hubert@u.washingto #include "../pith/tempfile.h" #include "../pith/readfile.h" #include "../pith/remote.h" +#ifdef PASSFILE +#include "../pith/imap.h" +#endif /* PASSFILE */ #include <openssl/buffer.h> #include <openssl/x509v3.h> @@ -70,10 +73,8 @@ static void setup_storage_locations(void); static int copy_container_to_dir(WhichCerts which); static int do_fiddle_smime_message(BODY *b, long msgno, char *section); void setup_privatekey_storage(void); -int smime_path(char *rpath, char *fpath, size_t len); int smime_extract_and_save_cert(PKCS7 *p7, int check_cert); int same_cert(X509 *, X509 *); -CertList * certlist_from_personal_certs(PERSONAL_CERT *pc); #ifdef PASSFILE int load_key_and_cert(char *pathkeydir, char *pathcertdir, char **keyfile, char **certfile, EVP_PKEY **pkey, X509 **pcert); #endif /* PASSFILE */ @@ -245,14 +246,18 @@ setup_pwdcert(void **pwdcert) return; } + + if(ps_global->pwdcertdir == NULL) /* save the result of pwdcertdir */ + ps_global->pwdcertdir = cpystr(pathdir); + 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; + pc->cname = certfile; *pwdcert = (void *) pc; - fs_give((void **)&certfile); was_here = 0; return; } @@ -596,8 +601,10 @@ load_pkey_with_prompt(char *fpath, char *text, char *prompt, int *ret) return pkey; } - - +/* This is a tool for conf_screen, The return value must be zero when + * nothing changed, so if there is a failure in the import return 0 + * and return 1 when we succeeded + */ int import_certificate(WhichCerts ctype) { @@ -607,18 +614,221 @@ import_certificate(WhichCerts ctype) if(pith_smime_import_certificate == NULL){ q_status_message(SM_ORDER, 0, 2, _("import of certificates not implemented yet!")); - return -1; + return 0; } - smime_init(); - r = (*pith_smime_import_certificate)(filename, full_filename, sizeof(filename) - 20); + if(r < 0) + return 0; + + /* we are trying to import a new key for the password file. First we ask for the + * private key. Once this is loaded, we make a reasonable attempt to find the + * public key in the same directory as the key was loaded from. We do this by + * looking for a file with the correct public certificate name, then we look + * in the same private key, and if not, we ask the user for its location. If all + * of this works, we import the key and public to the password directory. + */ + if(ctype == Password){ + char PrivateKeyPath[MAXPATH+1], PublicCertPath[MAXPATH+1], s[MAXPATH+1]; + char full_name_key[MAXPATH+1], full_name_cert[MAXPATH+1]; + char *use_this_file; + char prompt[500]; + EVP_PKEY *key = NULL; + + rc = 1; /* assume success :) */ + if(strlen(filename) > 4){ + strncpy(s, filename, sizeof(s)); + s[sizeof(s)-1] = '\0'; + if(!strcmp(s + strlen(s) - strlen(EXTCERT(Private)), EXTCERT(Private))) + s[strlen(s) - strlen(EXTCERT(Private))] = '\0'; + else + rc = 0; + } else rc = 0; + + if(rc == 0){ + q_status_message(SM_ORDER, 1, 3, _("Error in key name. Check file extension")); + return 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)) != NULL){ + BIO *ins = NULL; + X509 *cert = NULL; + + strncpy(full_name_key, full_filename, sizeof(full_filename)); + full_name_key[sizeof(full_name_key)-1] = '\0'; + + build_path(buf, PATHCERTDIR(ctype), s, sizeof(buf)); + + strncpy(PrivateKeyPath, buf, sizeof(PrivateKeyPath)); + PrivateKeyPath[sizeof(PrivateKeyPath)-1] = '\0'; + if(strlen(PrivateKeyPath) + 4 < sizeof(PrivateKeyPath)){ + strncat(PrivateKeyPath, EXTCERT(Private), 4); + PrivateKeyPath[sizeof(PrivateKeyPath)-1] = '\0'; + } + + /* remove .key extension and replace it with .crt extension */ + strncpy(full_name_cert, full_name_key, sizeof(full_name_key)); + full_name_cert[sizeof(full_name_cert)-1] = '\0'; + full_name_cert[strlen(full_name_cert) - strlen(EXTCERT(Private))] = '\0'; + strncat(full_name_cert, EXTCERT(Public), 4); + full_name_cert[sizeof(full_name_cert)-1] = '\0'; + + + /* set up path to location where we will save public cert */ + strncpy(PublicCertPath, buf, sizeof(PublicCertPath)); + PublicCertPath[sizeof(PublicCertPath)-1] = '\0'; + if(strlen(PublicCertPath) + 4 < sizeof(PublicCertPath)){ + strncat(PublicCertPath, EXTCERT(Public), 4); + PublicCertPath[sizeof(PublicCertPath)-1] = '\0'; + } + + /* attempt #1 to guess public cert name, use .crt extension */ + if((ins = BIO_new_file(full_name_cert, "r")) != NULL){ + if((cert = PEM_read_bio_X509(ins, NULL, NULL, NULL)) != NULL){ + use_this_file = &full_name_cert[0]; + } + } + else{ + /* attempt #2 to guess public cert name: user the original key */ + if((ins = BIO_new_file(full_name_key, "r")) != NULL){ + if((cert = PEM_read_bio_X509(ins, NULL, NULL, NULL)) != NULL){ + use_this_file = &full_name_key[0]; + } + } + else { + int done = 0; + /* attempt #3, ask the user */ + do { + r = (*pith_smime_import_certificate)(filename, use_this_file, sizeof(filename) - 20); + if(r < 0){ + if(ins != NULL) BIO_free(ins); + if(cert != NULL) X509_free(cert); + return 0; + } + if((ins = BIO_new_file(use_this_file, "r")) != NULL){ + if((cert = PEM_read_bio_X509(ins, NULL, NULL, NULL)) != NULL) + done++; + else + q_status_message(SM_ORDER, 1, 3, _("Error parsing certificate")); + } + else + q_status_message(SM_ORDER, 1, 3, _("Error reading certificate")); + } while (done == 0); + } + } + if(ins != NULL){ + if(cert != NULL){ /* check that certificate matches key */ + if(!X509_check_private_key(cert, key)){ + rc = 0; + q_status_message(SM_ORDER, 1, 3, _("Certificate does not match key")); + } + else + rc = 1; /* Success! */ + } + else + q_status_message(SM_ORDER, 1, 3, _("Error in certificate file (not a certificate?)")); + } + if(rc == 1){ /* if everything has been successful, + * copy the files to their final destination */ + if(our_copy(PrivateKeyPath, full_filename) == 0){ /* <-- save the private key */ + q_status_message(SM_ORDER, 1, 3, _("Private key saved")); + if(our_copy(PublicCertPath, use_this_file) == 0){ + char tmp[MAILTMPLEN]; + FILE *fp; + + if(!passfile_name(ps_global->pinerc, tmp, sizeof(tmp)) + || !(fp = our_fopen(tmp, "rb"))){ + q_status_message(SM_ORDER, 1, 3, _("Error reading password file!")); + rc = 0; + } + else { + char tmp2[MAILTMPLEN]; + int encrypted = 0; + char *text; + PERSONAL_CERT *pwdcert, *pc; + + pwdcert = (PERSONAL_CERT *) ps_global->pwdcert; + if(pwdcert == NULL) + setup_pwdcert((void **)&pwdcert); + + tmp2[0] = '\0'; + fgets(tmp2, sizeof(tmp2), fp); + fclose(fp); + if(strcmp(tmp2, "-----BEGIN PKCS7-----\n")){ + if(encrypt_file((char *)tmp, NULL, pwdcert)) + encrypted++; + } + else + encrypted++; + + if(encrypted){ + text = decrypt_file((char *)tmp, NULL, pwdcert); + if(text != NULL){ + pc = fs_get(sizeof(PERSONAL_CERT)); + memset((void *)pc, 0, sizeof(PERSONAL_CERT)); + filename[strlen(filename)-strlen(EXTCERT(Private))] = '\0'; + pc->name = cpystr(filename); + snprintf(buf, sizeof(buf), "%s%s", filename, EXTCERT(Public)); + buf[sizeof(buf)-1] = '\0'; + pc->cname = cpystr(buf); + pc->key = key; + pc->cert = cert; + + if(encrypt_file((char *)tmp, text, pc)){ /* we did it! */ + build_path(buf, PATHCERTDIR(ctype), pwdcert->name, sizeof(buf)); + strncat(buf, EXTCERT(Private), 4); + buf[sizeof(buf)-1] = '\0'; + if(unlink(buf) < 0) + q_status_message(SM_ORDER, 1, 3, _("Failed to remove old key")); + build_path(buf, PATHCERTDIR(ctype), pwdcert->cname, sizeof(buf)); + if(unlink(buf) < 0) + q_status_message(SM_ORDER, 1, 3, _("Failed to remove old certificate")); + free_personal_certs((PERSONAL_CERT **)&ps_global->pwdcert); + ps_global->pwdcert = pc; + rc = 1; + q_status_message(SM_ORDER, 1, 3, _("Password file reencrypted")); + } else { + q_status_message(SM_ORDER, 1, 3, _("Failed to reencrypt password file")); + rc = 0; + } + } else { + q_status_message(SM_ORDER, 1, 3, _("Error decrypting Password file")); + } + } else { + q_status_message(SM_ORDER, 1, 3, _("Password file not encrypted and coulr not encrypt")); + rc = 0; + } + } + } + else{ + q_status_message(SM_ORDER, 1, 3, _("Error saving public certificate")); + if(our_unlink(PrivateKeyPath) < 0) + q_status_message(SM_ORDER, 1, 3, _("Error while cleaning private key")); + rc = 0; + } + } + else{ + rc = 0; + q_status_message(SM_ORDER, 1, 3, _("Error saving private key")); + } + if(ins != NULL) BIO_free(ins); + if(rc == 0 && cert != NULL) X509_free(cert); + } + } else { + rc = 0; + q_status_message(SM_ORDER, 1, 3, _("Error unlocking private key")); + } + + return rc; + } + + smime_init(); ps_global->mangled_screen = 1; - if(r < 0) - return r; - else if (ctype == Private){ + if (ctype == Private){ char prompt[500], *s, *t; EVP_PKEY *key = NULL; @@ -651,7 +861,7 @@ import_certificate(WhichCerts ctype) ps_global->smime->publiccertlist->data.renew = 1; } else - q_status_message(SM_ORDER, 1, 3, _("Problem unlocking key (not a certificate and/or wrong password)")); + q_status_message(SM_ORDER, 1, 3, _("Problem unlocking key (not a certificate or wrong password)")); } else if (ctype == CACert){ BIO *ins; X509 *cert; @@ -713,7 +923,7 @@ import_certificate(WhichCerts ctype) } } if(DATACERT(ctype)) RENEWCERT(DATACERT(ctype)) = 1; - return 0; + return 1; } /* itype: information type to add: 0 - public, 1 - private. @@ -920,23 +1130,12 @@ certlist_from_personal_certs(PERSONAL_CERT *pc) { CertList *cl; X509 *x; - char buf[MAXPATH]; if(pc == NULL) return NULL; - - cl = fs_get(sizeof(CertList)); - memset((void *)cl, 0, sizeof(CertList)); - cl->name = cpystr(pc->name); - x = get_cert_for(pc->name, Public, 1); - if(x){ - if(x->cert_info){ - cl->data.date_from = smime_get_date(x->cert_info->validity->notBefore); - cl->data.date_to = smime_get_date(x->cert_info->validity->notAfter); - get_fingerprint(x, EVP_md5(), buf, sizeof(buf), NULL); - cl->data.md5 = cpystr(buf); - cl->cn = smime_get_cn(x->cert_info->subject); - } + + if((x = get_cert_for(pc->name, Public, 1)) != NULL){ + cl = smime_X509_to_cert_info(x, pc->name); X509_free(x); } cl->next = certlist_from_personal_certs(pc->next); @@ -3641,14 +3840,6 @@ free_smime_struct(SMIME_STUFF_S **smime) (*smime)->personal_certs = NULL; } - if((*smime)->backuppersonal_certs){ - PERSONAL_CERT *pc; - - pc = (PERSONAL_CERT *) (*smime)->backuppersonal_certs; - free_personal_certs(&pc); - (*smime)->backuppersonal_certs = NULL; - } - if((*smime)->privatecontent) fs_give((void **) &(*smime)->privatecontent); diff --git a/pith/smime.h b/pith/smime.h index 636d8805..01e4cdc0 100644 --- a/pith/smime.h +++ b/pith/smime.h @@ -85,6 +85,8 @@ void *create_smime_sparep(SpareType stype, void *s); SpareType get_smime_sparep_type(void *s); void *get_smime_sparep_data(void *s); STACK_OF(X509) *get_chain_for_cert(X509 *cert, int *error, int *level); +CertList *certlist_from_personal_certs(PERSONAL_CERT *pc); +int smime_path(char *rpath, char *fpath, size_t len); #endif /* PITH_SMIME_INCLUDED */ #endif /* SMIME */ diff --git a/pith/smkeys.c b/pith/smkeys.c index 18509622..415bc190 100644 --- a/pith/smkeys.c +++ b/pith/smkeys.c @@ -49,6 +49,30 @@ static char *emailstrclean(char *string); static int mem_add_extra_cacerts(char *contents, X509_LOOKUP *lookup); int compare_certs_by_name(const void *data1, const void *data2); + +CertList * +smime_X509_to_cert_info(X509 *x, char *name) +{ + CertList *cert; + char buf[MAXPATH+1]; + + if(x == NULL) return NULL; + + cert = fs_get(sizeof(CertList)); + memset((void *)cert, 0, sizeof(CertList)); + cert->x509_cert = x; + cert->name = name ? cpystr(name) : NULL; + if(x && x->cert_info){ + cert->data.date_from = smime_get_date(x->cert_info->validity->notBefore); + cert->data.date_to = smime_get_date(x->cert_info->validity->notAfter); + cert->cn = smime_get_cn(x->cert_info->subject); + } + get_fingerprint(x, EVP_md5(), buf, sizeof(buf), NULL); + cert->data.md5 = cpystr(buf); + + return cert; +} + #define SMIME_BACKUP_DIR ".backup" #define MAX_TRY_BACKUP 100 @@ -199,25 +223,11 @@ setup_certs_backup_by_type(WhichCerts ctype) if((in = BIO_new_file(buf2, "r"))!=0){ x = PEM_read_bio_X509(in, NULL, NULL, NULL); if(x && x->cert_info){ /* for now copy this information */ - X509_NAME_ENTRY *e; - - cert = fs_get(sizeof(CertList)); - memset((void *)cert, 0, sizeof(CertList)); - cert->x509_cert = x; - cert->data.date_from = smime_get_date(x->cert_info->validity->notBefore); - cert->data.date_to = smime_get_date(x->cert_info->validity->notAfter); - get_fingerprint(x, EVP_md5(), buf, sizeof(buf), NULL); - cert->data.md5 = cpystr(buf); - cert->name = cpystr(df->d_name); - cert->cn = smime_get_cn(x->cert_info->subject); + cert = smime_X509_to_cert_info(x, df->d_name); /* we will use the cert->data.md5 variable to find a backup certificate, not the name */ - if(data == NULL) - data = cert; - else{ - for (cl2 = data; cl2 && cl2->next; cl2 = cl2->next); - cl2->next = cert; - } + cert->next = data; + data = cert; } BIO_free(in); } @@ -872,6 +882,25 @@ get_cert_for(char *email, WhichCerts ctype, int tolower) X509 *cert = NULL; BIO *in; + if(ctype == Password){ + build_path(certfilename, PATHCERTDIR(ctype), email, sizeof(certfilename)); + strncat(certfilename, EXTCERT(Public), sizeof(certfilename)-1-strlen(certfilename)); + certfilename[sizeof(certfilename)-1] = 0; + + if((in = BIO_new_file(certfilename, "r"))!=0){ + + cert = PEM_read_bio_X509(in, NULL, NULL, NULL); + + if(cert){ + /* could check email addr in cert matches */ + } + + BIO_free(in); + } + + return cert; + } + if(!ps_global->smime) return cert; @@ -1274,33 +1303,14 @@ certlist_to_file(char *filename, CertList *certlist) void add_to_end_of_certlist(CertList **cl, char *name, X509 *cert) { - CertList *new, *clp; - char buf[MAILTMPLEN]; + CertList *new; if(!cl) return; - new = (CertList *) fs_get(sizeof(*new)); - memset((void *) new, 0, sizeof(*new)); - new->x509_cert = cert; - new->name = name ? cpystr(name) : NULL; - if(cert && cert->cert_info){ - new->data.date_from = smime_get_date(cert->cert_info->validity->notBefore); - new->data.date_to = smime_get_date(cert->cert_info->validity->notAfter); - get_fingerprint(cert, EVP_md5(), buf, sizeof(buf), NULL); - new->data.md5 = cpystr(buf); - new->cn = smime_get_cn(cert->cert_info->subject); - } - - if(!*cl){ - *cl = new; - } - else{ - for(clp = (*cl); clp->next; clp = clp->next) - ; - - clp->next = new; - } + new = smime_X509_to_cert_info(cert, name); + new->next = *cl; + *cl = new; } diff --git a/pith/smkeys.h b/pith/smkeys.h index 0a2b0065..8c23d905 100644 --- a/pith/smkeys.h +++ b/pith/smkeys.h @@ -38,7 +38,8 @@ typedef struct personal_cert { X509 *cert; EVP_PKEY *key; - char *name; + char *name; /* name of key */ + char *cname; /* name of cert */ char *keytext; struct personal_cert *next; } PERSONAL_CERT; @@ -67,6 +68,7 @@ char *smime_get_date(ASN1_GENERALIZEDTIME *tm); void resort_certificates(CertList **data, WhichCerts ctype); int setup_certs_backup_by_type(WhichCerts ctype); char *smime_get_cn(X509_NAME *); +CertList *smime_X509_to_cert_info(X509 *, char *); #endif /* PITH_SMKEYS_INCLUDED */ diff --git a/pith/state.h b/pith/state.h index 481d8b41..52628cf0 100644 --- a/pith/state.h +++ b/pith/state.h @@ -272,9 +272,6 @@ 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 */ @@ -359,7 +356,11 @@ struct pine { char *smimedir; SMIME_STUFF_S *smime; #ifdef PASSFILE - void *pwdcert; /* this is of type PERSONAL_CERT */ + char *pwdcertdir; /* path to location of certificates for password file */ + char *pwdcertcontent; /* No comment yet */ + void *pwdcert; /* this is of type PERSONAL_CERT */ + void *backuppassword; /* this is of type CertList */ + void *pwdcertlist; /* this is of type CertList */ #endif /* PASSFILE inside SMIME */ #endif /* SMIME */ |