X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;ds=sidebyside;f=pageant.c;h=e7430e7865faac93a173f15ede19442d76ea54cf;hb=991d30412d0911e7727a852d0a00ae0f1bec1b3e;hp=c249a3b7188cc93dd6a7c3458ab1e1dc6f0a5dce;hpb=8682246d33f21e369a3e5b38fa2fdec58b1e4425;p=PuTTY.git diff --git a/pageant.c b/pageant.c index c249a3b7..e7430e78 100644 --- a/pageant.c +++ b/pageant.c @@ -406,6 +406,7 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen, if (i < 0) { freebn(reqkey.exponent); freebn(reqkey.modulus); + freebn(challenge); fail_reason = "request truncated before challenge"; goto failure; } @@ -674,7 +675,7 @@ void *pageant_handle_msg(const void *msg, int msglen, int *outlen, } bloblen = msgend - p; - key->data = key->alg->openssh_createkey(&p, &bloblen); + key->data = key->alg->openssh_createkey(key->alg, &p, &bloblen); if (!key->data) { sfree(key); fail_reason = "key setup failed"; @@ -1100,6 +1101,7 @@ static int pageant_listen_accepting(Plug plug, struct pageant_listen_state *pl = (struct pageant_listen_state *)plug; struct pageant_conn_state *pc; const char *err; + char *peerinfo; pc = snew(struct pageant_conn_state); pc->fn = &connection_fn_table; @@ -1116,8 +1118,13 @@ static int pageant_listen_accepting(Plug plug, sk_set_frozen(pc->connsock, 0); - /* FIXME: can we get any useful peer id info? */ - plog(pl->logctx, pl->logfn, "%p: new connection", pc); + peerinfo = sk_peer_info(pc->connsock); + if (peerinfo) { + plog(pl->logctx, pl->logfn, "%p: new connection from %s", + pc, peerinfo); + } else { + plog(pl->logctx, pl->logfn, "%p: new connection", pc); + } return 0; } @@ -1172,6 +1179,9 @@ static tree234 *passphrases = NULL; */ void pageant_forget_passphrases(void) { + if (!passphrases) /* in case we never set it up at all */ + return; + while (count234(passphrases) > 0) { char *pp = index234(passphrases, 0); smemclr(pp, strlen(pp)); @@ -1187,12 +1197,12 @@ void *pageant_get_keylist1(int *length) if (!pageant_local) { unsigned char request[5], *response; void *vresponse; - int resplen, retval; + int resplen; + request[4] = SSH1_AGENTC_REQUEST_RSA_IDENTITIES; PUT_32BIT(request, 1); - retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL); - assert(retval == 1); + agent_query_synchronous(request, 5, &vresponse, &resplen); response = vresponse; if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER) { sfree(response); @@ -1218,13 +1228,12 @@ void *pageant_get_keylist2(int *length) if (!pageant_local) { unsigned char request[5], *response; void *vresponse; - int resplen, retval; + int resplen; request[4] = SSH2_AGENTC_REQUEST_IDENTITIES; PUT_32BIT(request, 1); - retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL); - assert(retval == 1); + agent_query_synchronous(request, 5, &vresponse, &resplen); response = vresponse; if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER) { sfree(response); @@ -1326,6 +1335,8 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, int n = rsa_public_blob_len(p, keylistlen); if (n < 0) { *retstr = dupstr("Received broken key list from agent"); + sfree(keylist); + sfree(blob); return PAGEANT_ACTION_FAILURE; } p += n; @@ -1334,11 +1345,18 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, int n; if (keylistlen < 4) { *retstr = dupstr("Received broken key list from agent"); + sfree(keylist); + sfree(blob); return PAGEANT_ACTION_FAILURE; } - n = toint(4 + GET_32BIT(p)); - if (n < 0 || keylistlen < n) { + n = GET_32BIT(p); + p += 4; + keylistlen -= 4; + + if (n < 0 || n > keylistlen) { *retstr = dupstr("Received broken key list from agent"); + sfree(keylist); + sfree(blob); return PAGEANT_ACTION_FAILURE; } p += n; @@ -1349,11 +1367,18 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, int n; if (keylistlen < 4) { *retstr = dupstr("Received broken key list from agent"); + sfree(keylist); + sfree(blob); return PAGEANT_ACTION_FAILURE; } - n = toint(4 + GET_32BIT(p)); - if (n < 0 || keylistlen < n) { + n = GET_32BIT(p); + p += 4; + keylistlen -= 4; + + if (n < 0 || n > keylistlen) { *retstr = dupstr("Received broken key list from agent"); + sfree(keylist); + sfree(blob); return PAGEANT_ACTION_FAILURE; } p += n; @@ -1400,6 +1425,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, * Run out of passphrases to try. */ *retstr = comment; + sfree(rkey); return PAGEANT_ACTION_NEED_PP; } } else @@ -1423,6 +1449,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, * a bad passphrase. */ *retstr = dupstr(error); + sfree(rkey); return PAGEANT_ACTION_FAILURE; } else if (ret == 1) { /* @@ -1462,7 +1489,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, if (!pageant_local) { unsigned char *request, *response; void *vresponse; - int reqlen, clen, resplen, ret; + int reqlen, clen, resplen; clen = strlen(rkey->comment); @@ -1495,19 +1522,24 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, reqlen += 4 + clen; PUT_32BIT(request, reqlen - 4); - ret = agent_query(request, reqlen, &vresponse, &resplen, - NULL, NULL); - assert(ret == 1); + agent_query_synchronous(request, reqlen, &vresponse, &resplen); response = vresponse; if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) { *retstr = dupstr("The already running Pageant " "refused to add the key."); + freersakey(rkey); + sfree(rkey); + sfree(request); + sfree(response); return PAGEANT_ACTION_FAILURE; } + freersakey(rkey); + sfree(rkey); sfree(request); sfree(response); } else { if (!pageant_add_ssh1_key(rkey)) { + freersakey(rkey); sfree(rkey); /* already present, don't waste RAM */ } } @@ -1515,7 +1547,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, if (!pageant_local) { unsigned char *request, *response; void *vresponse; - int reqlen, alglen, clen, keybloblen, resplen, ret; + int reqlen, alglen, clen, keybloblen, resplen; alglen = strlen(skey->alg->name); clen = strlen(skey->comment); @@ -1543,13 +1575,13 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, reqlen += clen + 4; PUT_32BIT(request, reqlen - 4); - ret = agent_query(request, reqlen, &vresponse, &resplen, - NULL, NULL); - assert(ret == 1); + agent_query_synchronous(request, reqlen, &vresponse, &resplen); response = vresponse; if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) { *retstr = dupstr("The already running Pageant " "refused to add the key."); + sfree(request); + sfree(response); return PAGEANT_ACTION_FAILURE; } @@ -1624,6 +1656,7 @@ int pageant_enum_keys(pageant_key_enum_fn_t callback, void *callback_ctx, p += n, keylistlen -= n; cbkey.blob = rsa_public_blob(&rkey, &cbkey.bloblen); + cbkey.comment = comment; cbkey.ssh_version = 1; callback(callback_ctx, fingerprint, comment, &cbkey); sfree(cbkey.blob); @@ -1694,6 +1727,7 @@ int pageant_enum_keys(pageant_key_enum_fn_t callback, void *callback_ctx, p += n, keylistlen -= n; cbkey.ssh_version = 2; + cbkey.comment = comment; callback(callback_ctx, fingerprint, comment, &cbkey); sfree(fingerprint); sfree(comment); @@ -1730,8 +1764,7 @@ int pageant_delete_key(struct pageant_pubkey *key, char **retstr) memcpy(request + 9, key->blob, key->bloblen); } - ret = agent_query(request, reqlen, &vresponse, &resplen, NULL, NULL); - assert(ret == 1); + agent_query_synchronous(request, reqlen, &vresponse, &resplen); response = vresponse; if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) { *retstr = dupstr("Agent failed to delete key"); @@ -1745,18 +1778,54 @@ int pageant_delete_key(struct pageant_pubkey *key, char **retstr) return ret; } +int pageant_delete_all_keys(char **retstr) +{ + unsigned char request[5], *response; + int reqlen, resplen, success; + void *vresponse; + + PUT_32BIT(request, 1); + request[4] = SSH2_AGENTC_REMOVE_ALL_IDENTITIES; + reqlen = 5; + agent_query_synchronous(request, reqlen, &vresponse, &resplen); + response = vresponse; + success = (resplen >= 4 && response[4] == SSH_AGENT_SUCCESS); + sfree(response); + if (!success) { + *retstr = dupstr("Agent failed to delete SSH-2 keys"); + return PAGEANT_ACTION_FAILURE; + } + + PUT_32BIT(request, 1); + request[4] = SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES; + reqlen = 5; + agent_query_synchronous(request, reqlen, &vresponse, &resplen); + response = vresponse; + success = (resplen >= 4 && response[4] == SSH_AGENT_SUCCESS); + sfree(response); + if (!success) { + *retstr = dupstr("Agent failed to delete SSH-1 keys"); + return PAGEANT_ACTION_FAILURE; + } + + *retstr = NULL; + return PAGEANT_ACTION_OK; +} + struct pageant_pubkey *pageant_pubkey_copy(struct pageant_pubkey *key) { struct pageant_pubkey *ret = snew(struct pageant_pubkey); ret->blob = snewn(key->bloblen, unsigned char); memcpy(ret->blob, key->blob, key->bloblen); ret->bloblen = key->bloblen; + ret->comment = key->comment ? dupstr(key->comment) : NULL; ret->ssh_version = key->ssh_version; return ret; } void pageant_pubkey_free(struct pageant_pubkey *key) { + sfree(key->comment); sfree(key->blob); sfree(key); }