diff options
author | Eduardo Chappa <chappa@washington.edu> | 2017-11-22 11:29:40 -0700 |
---|---|---|
committer | Eduardo Chappa <chappa@washington.edu> | 2017-11-22 11:29:40 -0700 |
commit | 0ef0caf0d77164aa615fffa8aff4e82a3a540f0f (patch) | |
tree | 2852cb0c74ddb64fe4d6bc4cfe73c495596bb51f | |
parent | b3376daf6c1857cb063d2ca2a25b7150ac4b861f (diff) | |
download | alpine-0ef0caf0d77164aa615fffa8aff4e82a3a540f0f.tar.xz |
* Add "remove password" command to the management screen for the
password file encryption key. This allows users to use their
password file without entering a master password.
-rw-r--r-- | alpine/keymenu.c | 19 | ||||
-rw-r--r-- | alpine/keymenu.h | 3 | ||||
-rw-r--r-- | alpine/smime.c | 120 | ||||
-rw-r--r-- | pith/pine.hlp | 42 | ||||
-rw-r--r-- | pith/state.h | 1 |
5 files changed, 154 insertions, 31 deletions
diff --git a/alpine/keymenu.c b/alpine/keymenu.c index 326bc239..3452e5ba 100644 --- a/alpine/keymenu.c +++ b/alpine/keymenu.c @@ -2710,10 +2710,10 @@ INST_KEY_MENU(config_smime_manage_certs_work_keymenu, config_smime_manage_certs_ struct key config_smime_view_cert[] = {HELP_MENU, - OTHER_MENU, + NULL_MENU, EXIT_SETUP_MENU, {"V", "[" N_("View Info") "]", {MC_CHOICE,3,{'v',ctrl('M'),ctrl('J')}}, KS_NONE}, - NULL_MENU, + {"D", N_("Delete pwd"), {MC_DELETE,1,{'d'}},KS_NONE}, NULL_MENU, NULL_MENU, NULL_MENU, @@ -2723,6 +2723,21 @@ struct key config_smime_view_cert[] = NULL_MENU}; INST_KEY_MENU(config_smime_manage_view_cert_keymenu, config_smime_view_cert); +struct key config_smime_view_cert_no_delete[] = + {HELP_MENU, + NULL_MENU, + EXIT_SETUP_MENU, + {"V", "[" N_("View Info") "]", {MC_CHOICE,3,{'v',ctrl('M'),ctrl('J')}}, KS_NONE}, + NULL_MENU, + NULL_MENU, + NULL_MENU, + NULL_MENU, + NULL_MENU, + NULL_MENU, + NULL_MENU, + NULL_MENU}; +INST_KEY_MENU(config_smime_manage_view_cert_keymenu_no_delete, config_smime_view_cert_no_delete); + struct key smime_certificate_info_keys[] = {HELP_MENU, OTHER_MENU, diff --git a/alpine/keymenu.h b/alpine/keymenu.h index 047e992a..061a58da 100644 --- a/alpine/keymenu.h +++ b/alpine/keymenu.h @@ -666,7 +666,8 @@ extern struct key_menu cancel_keymenu, config_smime_manage_password_file_menu_keymenu, smime_certificate_info_keymenu, config_smime_add_new_key_keymenu, - config_smime_manage_view_cert_keymenu; + config_smime_manage_view_cert_keymenu, + config_smime_manage_view_cert_keymenu_no_delete; extern struct key rev_msg_keys[]; diff --git a/alpine/smime.c b/alpine/smime.c index 43000385..2fe22a36 100644 --- a/alpine/smime.c +++ b/alpine/smime.c @@ -38,6 +38,7 @@ static char rcsid[] = "$Id: smime.c 1074 2008-06-04 00:08:43Z hubert@u.washingto #include "../pith/tempfile.h" #include "radio.h" #include "keymenu.h" +#include "mailcmd.h" #include "mailview.h" #include "conftype.h" #include "confscroll.h" @@ -1286,18 +1287,21 @@ manage_certs_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned flags) pathdir, MASTERNAME); filename[sizeof(filename)-1] = '\0'; rv = import_certificate(ctype, pc, filename); - if(rv == 1 && our_stat(pathdir, &sbuf) == 0){ - if(unlink(filename) < 0) - q_status_message1(SM_ORDER, 0, 2, + if(rv == 1){ + ps->keyemptypwd = 0; + if(our_stat(pathdir, &sbuf) == 0){ + if(unlink(filename) < 0) + q_status_message1(SM_ORDER, 0, 2, _("Could not remove private key %s.key"), MASTERNAME); - filename[strlen(filename)-4] = '\0'; - strcat(filename, ".crt"); - if(unlink(filename) < 0) - q_status_message1(SM_ORDER, 0, 2, + filename[strlen(filename)-4] = '\0'; + strcat(filename, ".crt"); + if(unlink(filename) < 0) + q_status_message1(SM_ORDER, 0, 2, _("Could not remove public certificate %s.crt"), MASTERNAME); - if(rmdir(pathdir) < 0) - q_status_message1(SM_ORDER, 0, 2, + if(rmdir(pathdir) < 0) + q_status_message1(SM_ORDER, 0, 2, _("Could not remove temporary directory %s"), pathdir); + } } } rv = 10; /* forces redraw */ @@ -1319,13 +1323,71 @@ manage_certs_tool(struct pine *ps, int cmd, CONF_S **cl, unsigned flags) break; case MC_DELETE: - if ((*cl)->d.s.deleted != 0) - q_status_message(SM_ORDER, 1, 3, _("Certificate already deleted")); - else{ - (*cl)->d.s.deleted = 1; - rv = 10 + (*cl)->varmem; /* forces redraw */ - mark_cert_deleted(ctype, (*cl)->varmem, 1); - q_status_message(SM_ORDER, 1, 3, _("Certificate marked deleted")); + if(ctype == Password){ + EVP_PKEY *key = NULL; + PERSONAL_CERT *pc = (PERSONAL_CERT *) ps->pwdcert; + RSA *rsa = NULL; + const EVP_CIPHER *enc = NULL; + BIO *out = NULL; + BIO *in = NULL; + char filename[MAXPATH+1]; + char passwd[MAILTMPLEN]; + char prompt[MAILTMPLEN]; + + if (pc != NULL && pc->key != NULL){ + strncpy(prompt, _("Enter password to unlock key: "), sizeof(prompt)); + prompt[sizeof(prompt)-1] = '\0'; + passwd[0] = '\0'; + + rv = alpine_get_password(prompt, passwd, sizeof(passwd)); + + if(rv == 1) + q_status_message(SM_ORDER, 1, 3, _("Password deletion cancelled")); + else if(rv == 0){ + snprintf(filename, sizeof(filename), "%s/%s.key", ps->pwdcertdir, pc->name); + filename[sizeof(filename)-1] = '\0'; + if((in = BIO_new_file(filename, "r")) != NULL){ + key = PEM_read_bio_PrivateKey(in, NULL, NULL, passwd); + if(key != NULL){ + if((rsa = EVP_PKEY_get1_RSA(key)) != NULL + && (out = BIO_new(BIO_s_file())) != NULL + && BIO_write_filename(out, filename) > 0 + && PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0, NULL, passwd) > 0){ + q_status_message(SM_ORDER, 1, 3, _("Password Removed from private key")); + ps->keyemptypwd = 1; + } + else + rv = 1; + } + else{ + rv = 1; + q_status_message(SM_ORDER, 1, 3, _("Failed to unlock private key")); + } + BIO_free(in); + } + else + rv = 1; + } + if(rv == 1) + q_status_message(SM_ORDER, 1, 3, _("Failed to remove password from private key")); + rv += 10; /* forces redraw */ + if(out != NULL) + BIO_free_all(out); + if(rsa != NULL) + RSA_free(rsa); + if(key != NULL) + EVP_PKEY_free(key); + } + } + else { + if ((*cl)->d.s.deleted != 0) + q_status_message(SM_ORDER, 1, 3, _("Certificate already deleted")); + else{ + (*cl)->d.s.deleted = 1; + rv = 10 + (*cl)->varmem; /* forces redraw */ + mark_cert_deleted(ctype, (*cl)->varmem, 1); + q_status_message(SM_ORDER, 1, 3, _("Certificate marked deleted")); + } } break; @@ -1406,6 +1468,7 @@ void manage_password_file_certificates(struct pine *ps) dprint((9, "manage_password_file_certificates")); ps->next_screen = SCREEN_FUN_NULL; + ps->keyemptypwd = 0; /* just in case */ do { CONF_S *ctmp = NULL, *first_line = NULL; @@ -1422,6 +1485,7 @@ void manage_password_file_certificates(struct pine *ps) memset(&screen, 0, sizeof(screen)); screen.deferred_ro_warning = readonly_warning; + rv = conf_scroll_screen(ps, &screen, first_line, _("MANAGE PASSWORD FILE CERTS"), /* TRANSLATORS: Print something1 using something2. @@ -1430,6 +1494,7 @@ void manage_password_file_certificates(struct pine *ps) } while (rv != 0); ps->mangled_screen = 1; + ps->keyemptypwd = 0; /* reset this so it will not confuse other routines */ smime_reinit(); } @@ -1444,9 +1509,12 @@ smime_manage_password_file_certs_init(struct pine *ps, CONF_S **ctmp, CONF_S **f CertList *cl; int i; void *pwdcert = NULL; /* this is our current password file */ - PERSONAL_CERT *pc; X509_LOOKUP *lookup = NULL; X509_STORE *store = NULL; + char filename[MAXPATH+1]; + BIO *in = NULL; + EVP_PKEY *key = NULL; + PERSONAL_CERT *pc; if(*state == 0){ /* first time around? */ setup_pwdcert(&pwdcert); @@ -1459,6 +1527,16 @@ smime_manage_password_file_certs_init(struct pine *ps, CONF_S **ctmp, CONF_S **f } pc = (PERSONAL_CERT *) ps_global->pwdcert; + snprintf(filename, sizeof(filename), "%s/%s.key", ps->pwdcertdir, pc->name); + filename[sizeof(filename)-1] = '\0'; + if((in = BIO_new_file(filename, "r")) != NULL + && (key = PEM_read_bio_PrivateKey(in, NULL, NULL, "")) != NULL) + ps->keyemptypwd = 1; + if(in != NULL) + BIO_free(in); + if(key != NULL) + EVP_PKEY_free(key); + ps->pwdcertlist = cl = smime_X509_to_cert_info(X509_dup(pc->cert), pc->name); for(i = 0; i < sizeof(tmp) && i < (ps->ttyo ? ps->ttyo->screen_cols : sizeof(tmp)); i++) @@ -1531,9 +1609,10 @@ smime_manage_password_file_certs_init(struct pine *ps, CONF_S **ctmp, CONF_S **f (*ctmp)->d.s.deleted = 0; (*ctmp)->help = h_config_smime_password_file_certificates; (*ctmp)->tool = manage_certs_tool; - (*ctmp)->keymenu = &config_smime_manage_view_cert_keymenu; + (*ctmp)->keymenu = ps->keyemptypwd == 0 + ? &config_smime_manage_view_cert_keymenu + : &config_smime_manage_view_cert_keymenu_no_delete; (*ctmp)->varmem = 0; - (*ctmp)->help = h_config_smime_manage_public_menu; strncpy((*ctmp)->d.s.address, cl->name, sizeof((*ctmp)->d.s.address)); (*ctmp)->d.s.address[sizeof((*ctmp)->d.s.address) - 1] = '\0'; snprintf(tmp, sizeof(tmp), u, @@ -1541,8 +1620,7 @@ smime_manage_password_file_certs_init(struct pine *ps, CONF_S **ctmp, CONF_S **f cl->name, DATEFROMCERT(cl), DATETOCERT(cl), MD5CERT(cl)); (*ctmp)->value = cpystr(tmp); - - } + } } #endif /* PASSFILE */ diff --git a/pith/pine.hlp b/pith/pine.hlp index 0c712e0a..547cb10d 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 232 2017-11-21 12:33:12 +Alpine Commit 233 2017-11-22 11:29:36 ============= h_news ================= <HTML> <HEAD> @@ -189,6 +189,11 @@ when spelling. Sample usage: -dict "en_US, de_DE, fr_FR". <LI> Improvements to the configure stage of compilation. Some of these contributed by Helmut Grohne. See <A href="https://bugs.debian.org/876164">Bug 876164</A> in Debian. + +<LI> Add "remove password" command to the management screen for the +password file encryption key. This allows users to use their password file +without entering a master password. + </UL> <P> @@ -35901,13 +35906,30 @@ 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. +Depending on the version of Alpine that you used for the first time +to set this up, you might have had to enter a password to enter this +screen. In the case that you did not enter a password to enter this +screen, you should know two things that are important: +<UL> +<LI> If anyone takes control of your computer (for example, if you +left it unattended) then that person can add a password to your +password file and make it unreadable to you in the future. +<LI> If anyone can access your computer (this includes remote access) +then that person can steal your password file and decrypt it without +your help. This gives access to that person to the same services you +have access and such person can use your name to access that service. +In particular, that person can try to hack into your service provider +with your name on it, or that person could try to send spam with +your name. +</UL> +<P> Needless to say, this is not advisable. You should keep your +password file protected. In order to do so, all you need to do is use +the "Create Key" command to create a key. Once you do this, +Alpine will use that key, encrypted with the password used to create that +key, to protect 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. +In this screen you can import a new key to encrypt your password file, +and read cryptographic 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 @@ -35927,6 +35949,12 @@ certificates are saved, and the old keys are permanently deleted. 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. +<P> +Observe that you can use this screen to remove the password for the key. +As explained earlier, this is not advisable, but you can always restore the +password to encrypt your password file by creating a new key. +<P> +Be safe and keep your password file encrypted with a password. <UL> <LI><A HREF="h_mainhelp_smime">General S/MIME help</A> </UL><P> diff --git a/pith/state.h b/pith/state.h index 316a5895..75cff1c5 100644 --- a/pith/state.h +++ b/pith/state.h @@ -362,6 +362,7 @@ struct pine { PRINT_S *print; #ifdef SMIME + int keyemptypwd; /* can we load the key without a password? */ char *smimedir; SMIME_STUFF_S *smime; char *pwdcertdir; /* path to location of certificates for password file */ |