diff --git a/defs.h b/defs.h index f500a04c..661c404f 100644 --- a/defs.h +++ b/defs.h @@ -18,6 +18,7 @@ #if defined _MSC_VER && _MSC_VER < 1800 /* Work around lack of inttypes.h and strtoumax in older MSVC */ #define PRIx32 "x" +#define PRIu32 "u" #define PRIu64 "I64u" #define PRIdMAX "I64d" #define PRIXMAX "I64X" diff --git a/pageant.c b/pageant.c index d64a5c22..40b495b9 100644 --- a/pageant.c +++ b/pageant.c @@ -2214,6 +2214,55 @@ int pageant_delete_all_keys(char **retstr) return PAGEANT_ACTION_OK; } +int pageant_reencrypt_key(struct pageant_pubkey *key, char **retstr) +{ + PageantClientOp *pco = pageant_client_op_new(); + + if (key->ssh_version == 1) { + *retstr = dupstr("Can't re-encrypt an SSH-1 key"); + return PAGEANT_ACTION_FAILURE; + } else { + put_byte(pco, SSH2_AGENTC_EXTENSION); + put_stringpl(pco, extension_names[EXT_REENCRYPT]); + put_string(pco, key->blob->s, key->blob->len); + } + + unsigned reply = pageant_client_op_query(pco); + pageant_client_op_free(pco); + + if (reply != SSH_AGENT_SUCCESS) { + *retstr = dupstr("Agent failed to re-encrypt key"); + return PAGEANT_ACTION_FAILURE; + } else { + *retstr = NULL; + return PAGEANT_ACTION_OK; + } +} + +int pageant_reencrypt_all_keys(char **retstr) +{ + PageantClientOp *pco = pageant_client_op_new(); + put_byte(pco, SSH2_AGENTC_EXTENSION); + put_stringpl(pco, extension_names[EXT_REENCRYPT_ALL]); + unsigned reply = pageant_client_op_query(pco); + uint32_t failures = get_uint32(pco); + pageant_client_op_free(pco); + if (reply != SSH_AGENT_SUCCESS) { + *retstr = dupstr("Agent failed to re-encrypt any keys"); + return PAGEANT_ACTION_FAILURE; + } else if (failures == 1) { + /* special case for English grammar */ + *retstr = dupstr("1 key remains unencrypted"); + return PAGEANT_ACTION_WARNING; + } else if (failures > 0) { + *retstr = dupprintf("%"PRIu32" keys remain unencrypted", failures); + return PAGEANT_ACTION_WARNING; + } else { + *retstr = NULL; + return PAGEANT_ACTION_OK; + } +} + int pageant_sign(struct pageant_pubkey *key, ptrlen message, strbuf *out, uint32_t flags, char **retstr) { diff --git a/pageant.h b/pageant.h index 8b62623e..617133eb 100644 --- a/pageant.h +++ b/pageant.h @@ -211,7 +211,9 @@ void pageant_listener_free(struct pageant_listen_state *pl); enum { PAGEANT_ACTION_OK, /* success; no further action needed */ PAGEANT_ACTION_FAILURE, /* failure; *retstr is error message */ - PAGEANT_ACTION_NEED_PP /* need passphrase: *retstr is key comment */ + PAGEANT_ACTION_NEED_PP, /* need passphrase: *retstr is key comment */ + PAGEANT_ACTION_WARNING, /* success but with a warning message; + * *retstr is warning message */ }; int pageant_add_keyfile(Filename *filename, const char *passphrase, char **retstr, bool add_encrypted); @@ -236,5 +238,7 @@ int pageant_enum_keys(pageant_key_enum_fn_t callback, void *callback_ctx, char **retstr); int pageant_delete_key(struct pageant_pubkey *key, char **retstr); int pageant_delete_all_keys(char **retstr); +int pageant_reencrypt_key(struct pageant_pubkey *key, char **retstr); +int pageant_reencrypt_all_keys(char **retstr); int pageant_sign(struct pageant_pubkey *key, ptrlen message, strbuf *out, uint32_t flags, char **retstr);