mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
Unix Pageant: -E option to load key files encrypted.
This applies to both server modes ('pageant -E key.ppk [lifetime]') and client mode ('pageant -a -E key.ppk'). I'm not completely confident that the CLI syntax is actually right yet, but for the moment, it's enough that it _exists_. Now I don't have to test the encrypted-key loading via manually mocked-up agent requests.
This commit is contained in:
parent
8677ee00fb
commit
55005a08ea
39
pageant.c
39
pageant.c
@ -1604,7 +1604,7 @@ void *pageant_get_keylist2(int *length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
||||||
char **retstr)
|
char **retstr, bool add_encrypted)
|
||||||
{
|
{
|
||||||
RSAKey *rkey = NULL;
|
RSAKey *rkey = NULL;
|
||||||
ssh2_userkey *skey = NULL;
|
ssh2_userkey *skey = NULL;
|
||||||
@ -1629,6 +1629,11 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||||||
return PAGEANT_ACTION_FAILURE;
|
return PAGEANT_ACTION_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (add_encrypted && type == SSH_KEYTYPE_SSH1) {
|
||||||
|
*retstr = dupprintf("Can't add SSH-1 keys in encrypted form");
|
||||||
|
return PAGEANT_ACTION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if the key is already loaded (in the primary Pageant,
|
* See if the key is already loaded (in the primary Pageant,
|
||||||
* which may or may not be us).
|
* which may or may not be us).
|
||||||
@ -1747,6 +1752,38 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||||||
strbuf_free(blob);
|
strbuf_free(blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (add_encrypted) {
|
||||||
|
const char *load_error;
|
||||||
|
LoadedFile *lf = lf_load_keyfile(filename, &load_error);
|
||||||
|
if (!lf) {
|
||||||
|
*retstr = dupstr(load_error);
|
||||||
|
return PAGEANT_ACTION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
strbuf *request = strbuf_new_for_agent_query();
|
||||||
|
put_byte(request, SSH2_AGENTC_EXTENSION);
|
||||||
|
put_stringpl(request, PUTTYEXT("add-ppk"));
|
||||||
|
put_string(request, lf->data, lf->len);
|
||||||
|
|
||||||
|
lf_free(lf);
|
||||||
|
|
||||||
|
void *vresponse;
|
||||||
|
int resplen;
|
||||||
|
pageant_client_query(request, &vresponse, &resplen);
|
||||||
|
strbuf_free(request);
|
||||||
|
|
||||||
|
unsigned char *response = vresponse;
|
||||||
|
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
|
||||||
|
*retstr = dupstr("The already running Pageant "
|
||||||
|
"refused to add the key.");
|
||||||
|
sfree(response);
|
||||||
|
return PAGEANT_ACTION_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sfree(response);
|
||||||
|
return PAGEANT_ACTION_OK;
|
||||||
|
}
|
||||||
|
|
||||||
error = NULL;
|
error = NULL;
|
||||||
if (type == SSH_KEYTYPE_SSH1)
|
if (type == SSH_KEYTYPE_SSH1)
|
||||||
needs_pass = rsa1_encrypted_f(filename, &comment);
|
needs_pass = rsa1_encrypted_f(filename, &comment);
|
||||||
|
@ -220,7 +220,7 @@ enum {
|
|||||||
PAGEANT_ACTION_NEED_PP /* need passphrase: *retstr is key comment */
|
PAGEANT_ACTION_NEED_PP /* need passphrase: *retstr is key comment */
|
||||||
};
|
};
|
||||||
int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
||||||
char **retstr);
|
char **retstr, bool add_encrypted);
|
||||||
void pageant_forget_passphrases(void);
|
void pageant_forget_passphrases(void);
|
||||||
|
|
||||||
struct pageant_pubkey {
|
struct pageant_pubkey {
|
||||||
|
@ -312,7 +312,10 @@ static void tty_life_timer(void *ctx, unsigned long now)
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
KEYACT_AGENT_LOAD,
|
KEYACT_AGENT_LOAD,
|
||||||
KEYACT_CLIENT_ADD,
|
KEYACT_AGENT_LOAD_ENCRYPTED,
|
||||||
|
KEYACT_CLIENT_BASE,
|
||||||
|
KEYACT_CLIENT_ADD = KEYACT_CLIENT_BASE,
|
||||||
|
KEYACT_CLIENT_ADD_ENCRYPTED,
|
||||||
KEYACT_CLIENT_DEL,
|
KEYACT_CLIENT_DEL,
|
||||||
KEYACT_CLIENT_DEL_ALL,
|
KEYACT_CLIENT_DEL_ALL,
|
||||||
KEYACT_CLIENT_LIST,
|
KEYACT_CLIENT_LIST,
|
||||||
@ -327,7 +330,7 @@ struct cmdline_key_action {
|
|||||||
|
|
||||||
bool is_agent_action(keyact action)
|
bool is_agent_action(keyact action)
|
||||||
{
|
{
|
||||||
return action == KEYACT_AGENT_LOAD;
|
return action < KEYACT_CLIENT_BASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cmdline_key_action *keyact_head = NULL, *keyact_tail = NULL;
|
static struct cmdline_key_action *keyact_head = NULL, *keyact_tail = NULL;
|
||||||
@ -438,7 +441,7 @@ static char *askpass(const char *prompt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool unix_add_keyfile(const char *filename_str)
|
static bool unix_add_keyfile(const char *filename_str, bool add_encrypted)
|
||||||
{
|
{
|
||||||
Filename *filename = filename_from_str(filename_str);
|
Filename *filename = filename_from_str(filename_str);
|
||||||
int status;
|
int status;
|
||||||
@ -450,7 +453,7 @@ static bool unix_add_keyfile(const char *filename_str)
|
|||||||
/*
|
/*
|
||||||
* Try without a passphrase.
|
* Try without a passphrase.
|
||||||
*/
|
*/
|
||||||
status = pageant_add_keyfile(filename, NULL, &err);
|
status = pageant_add_keyfile(filename, NULL, &err, add_encrypted);
|
||||||
if (status == PAGEANT_ACTION_OK) {
|
if (status == PAGEANT_ACTION_OK) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if (status == PAGEANT_ACTION_FAILURE) {
|
} else if (status == PAGEANT_ACTION_FAILURE) {
|
||||||
@ -472,7 +475,8 @@ static bool unix_add_keyfile(const char *filename_str)
|
|||||||
if (!passphrase)
|
if (!passphrase)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
status = pageant_add_keyfile(filename, passphrase, &err);
|
status = pageant_add_keyfile(filename, passphrase, &err,
|
||||||
|
add_encrypted);
|
||||||
|
|
||||||
smemclr(passphrase, strlen(passphrase));
|
smemclr(passphrase, strlen(passphrase));
|
||||||
sfree(passphrase);
|
sfree(passphrase);
|
||||||
@ -692,7 +696,9 @@ void run_client(void)
|
|||||||
for (act = keyact_head; act; act = act->next) {
|
for (act = keyact_head; act; act = act->next) {
|
||||||
switch (act->action) {
|
switch (act->action) {
|
||||||
case KEYACT_CLIENT_ADD:
|
case KEYACT_CLIENT_ADD:
|
||||||
if (!unix_add_keyfile(act->filename))
|
case KEYACT_CLIENT_ADD_ENCRYPTED:
|
||||||
|
if (!unix_add_keyfile(act->filename,
|
||||||
|
act->action == KEYACT_CLIENT_ADD_ENCRYPTED))
|
||||||
errors = true;
|
errors = true;
|
||||||
break;
|
break;
|
||||||
case KEYACT_CLIENT_LIST:
|
case KEYACT_CLIENT_LIST:
|
||||||
@ -875,8 +881,10 @@ void run_agent(FILE *logfp, const char *symlink_path)
|
|||||||
* Start by loading any keys provided on the command line.
|
* Start by loading any keys provided on the command line.
|
||||||
*/
|
*/
|
||||||
for (act = keyact_head; act; act = act->next) {
|
for (act = keyact_head; act; act = act->next) {
|
||||||
assert(act->action == KEYACT_AGENT_LOAD);
|
assert(act->action == KEYACT_AGENT_LOAD ||
|
||||||
if (!unix_add_keyfile(act->filename))
|
act->action == KEYACT_AGENT_LOAD_ENCRYPTED);
|
||||||
|
if (!unix_add_keyfile(act->filename,
|
||||||
|
act->action == KEYACT_AGENT_LOAD_ENCRYPTED))
|
||||||
errors = true;
|
errors = true;
|
||||||
}
|
}
|
||||||
if (errors)
|
if (errors)
|
||||||
@ -1097,6 +1105,16 @@ int main(int argc, char **argv)
|
|||||||
life = LIFE_X11;
|
life = LIFE_X11;
|
||||||
} else if (!strcmp(p, "-T")) {
|
} else if (!strcmp(p, "-T")) {
|
||||||
life = LIFE_TTY;
|
life = LIFE_TTY;
|
||||||
|
} else if (!strcmp(p, "-E")) {
|
||||||
|
if (curr_keyact == KEYACT_AGENT_LOAD)
|
||||||
|
curr_keyact = KEYACT_AGENT_LOAD_ENCRYPTED;
|
||||||
|
else if (curr_keyact == KEYACT_CLIENT_ADD)
|
||||||
|
curr_keyact = KEYACT_CLIENT_ADD_ENCRYPTED;
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "pageant: unexpected -E while not adding "
|
||||||
|
"keys\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
} else if (!strcmp(p, "--debug")) {
|
} else if (!strcmp(p, "--debug")) {
|
||||||
life = LIFE_DEBUG;
|
life = LIFE_DEBUG;
|
||||||
} else if (!strcmp(p, "--permanent")) {
|
} else if (!strcmp(p, "--permanent")) {
|
||||||
|
@ -373,7 +373,7 @@ static void win_add_keyfile(Filename *filename)
|
|||||||
* _new_ passphrase; pageant_add_keyfile will take care of trying
|
* _new_ passphrase; pageant_add_keyfile will take care of trying
|
||||||
* all the passphrases we've already stored.)
|
* all the passphrases we've already stored.)
|
||||||
*/
|
*/
|
||||||
ret = pageant_add_keyfile(filename, NULL, &err);
|
ret = pageant_add_keyfile(filename, NULL, &err, false);
|
||||||
if (ret == PAGEANT_ACTION_OK) {
|
if (ret == PAGEANT_ACTION_OK) {
|
||||||
goto done;
|
goto done;
|
||||||
} else if (ret == PAGEANT_ACTION_FAILURE) {
|
} else if (ret == PAGEANT_ACTION_FAILURE) {
|
||||||
@ -401,7 +401,7 @@ static void win_add_keyfile(Filename *filename)
|
|||||||
|
|
||||||
assert(passphrase != NULL);
|
assert(passphrase != NULL);
|
||||||
|
|
||||||
ret = pageant_add_keyfile(filename, passphrase, &err);
|
ret = pageant_add_keyfile(filename, passphrase, &err, false);
|
||||||
if (ret == PAGEANT_ACTION_OK) {
|
if (ret == PAGEANT_ACTION_OK) {
|
||||||
goto done;
|
goto done;
|
||||||
} else if (ret == PAGEANT_ACTION_FAILURE) {
|
} else if (ret == PAGEANT_ACTION_FAILURE) {
|
||||||
|
Loading…
Reference in New Issue
Block a user