X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=pageant.c;h=754af9c6aca103c2b649446f72a92cb1da706aee;hb=eef0235a0f79e92f25f34782fc486c101fa703ee;hp=51baab02fd434edd4c301e6a19f38b9200c45a75;hpb=66b5455b139942ff08625ac194e4e4a3f27abcf5;p=PuTTY.git diff --git a/pageant.c b/pageant.c index 51baab02..754af9c6 100644 --- a/pageant.c +++ b/pageant.c @@ -1582,3 +1582,199 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase, } return PAGEANT_ACTION_OK; } + +int pageant_enum_keys(pageant_key_enum_fn_t callback, void *callback_ctx, + char **retstr) +{ + unsigned char *keylist, *p; + int i, nkeys, keylistlen; + char *comment; + struct pageant_pubkey cbkey; + + keylist = pageant_get_keylist1(&keylistlen); + if (keylistlen < 4) { + *retstr = dupstr("Received broken SSH-1 key list from agent"); + sfree(keylist); + return PAGEANT_ACTION_FAILURE; + } + nkeys = toint(GET_32BIT(keylist)); + if (nkeys < 0) { + *retstr = dupstr("Received broken SSH-1 key list from agent"); + sfree(keylist); + return PAGEANT_ACTION_FAILURE; + } + p = keylist + 4; + keylistlen -= 4; + + for (i = 0; i < nkeys; i++) { + struct RSAKey rkey; + char fingerprint[128]; + int n; + + /* public blob and fingerprint */ + memset(&rkey, 0, sizeof(rkey)); + n = makekey(p, keylistlen, &rkey, NULL, 0); + if (n < 0 || n > keylistlen) { + freersakey(&rkey); + *retstr = dupstr("Received broken SSH-1 key list from agent"); + sfree(keylist); + return PAGEANT_ACTION_FAILURE; + } + p += n, keylistlen -= n; + rsa_fingerprint(fingerprint, sizeof(fingerprint), &rkey); + + /* comment */ + if (keylistlen < 4) { + *retstr = dupstr("Received broken SSH-1 key list from agent"); + freersakey(&rkey); + sfree(keylist); + return PAGEANT_ACTION_FAILURE; + } + n = toint(GET_32BIT(p)); + p += 4, keylistlen -= 4; + if (n < 0 || keylistlen < n) { + *retstr = dupstr("Received broken SSH-1 key list from agent"); + freersakey(&rkey); + sfree(keylist); + return PAGEANT_ACTION_FAILURE; + } + comment = dupprintf("%.*s", (int)n, (const char *)p); + p += n, keylistlen -= n; + + cbkey.blob = rsa_public_blob(&rkey, &cbkey.bloblen); + cbkey.ssh_version = 1; + callback(callback_ctx, fingerprint, comment, &cbkey); + sfree(cbkey.blob); + freersakey(&rkey); + sfree(comment); + } + + sfree(keylist); + + if (keylistlen != 0) { + *retstr = dupstr("Received broken SSH-1 key list from agent"); + return PAGEANT_ACTION_FAILURE; + } + + keylist = pageant_get_keylist2(&keylistlen); + if (keylistlen < 4) { + *retstr = dupstr("Received broken SSH-2 key list from agent"); + sfree(keylist); + return PAGEANT_ACTION_FAILURE; + } + nkeys = toint(GET_32BIT(keylist)); + if (nkeys < 0) { + *retstr = dupstr("Received broken SSH-2 key list from agent"); + sfree(keylist); + return PAGEANT_ACTION_FAILURE; + } + p = keylist + 4; + keylistlen -= 4; + + for (i = 0; i < nkeys; i++) { + char *fingerprint; + int n; + + /* public blob */ + if (keylistlen < 4) { + *retstr = dupstr("Received broken SSH-2 key list from agent"); + sfree(keylist); + return PAGEANT_ACTION_FAILURE; + } + n = toint(GET_32BIT(p)); + p += 4, keylistlen -= 4; + if (n < 0 || keylistlen < n) { + *retstr = dupstr("Received broken SSH-2 key list from agent"); + sfree(keylist); + return PAGEANT_ACTION_FAILURE; + } + fingerprint = fingerprint_ssh2_blob(p, n); + cbkey.blob = p; + cbkey.bloblen = n; + p += n, keylistlen -= n; + + /* comment */ + if (keylistlen < 4) { + *retstr = dupstr("Received broken SSH-2 key list from agent"); + sfree(fingerprint); + sfree(keylist); + return PAGEANT_ACTION_FAILURE; + } + n = toint(GET_32BIT(p)); + p += 4, keylistlen -= 4; + if (n < 0 || keylistlen < n) { + *retstr = dupstr("Received broken SSH-2 key list from agent"); + sfree(fingerprint); + sfree(keylist); + return PAGEANT_ACTION_FAILURE; + } + comment = dupprintf("%.*s", (int)n, (const char *)p); + p += n, keylistlen -= n; + + cbkey.ssh_version = 2; + callback(callback_ctx, fingerprint, comment, &cbkey); + sfree(fingerprint); + sfree(comment); + } + + sfree(keylist); + + if (keylistlen != 0) { + *retstr = dupstr("Received broken SSH-1 key list from agent"); + return PAGEANT_ACTION_FAILURE; + } + + return PAGEANT_ACTION_OK; +} + +int pageant_delete_key(struct pageant_pubkey *key, char **retstr) +{ + unsigned char *request, *response; + int reqlen, resplen, ret; + void *vresponse; + + if (key->ssh_version == 1) { + reqlen = 5 + key->bloblen; + request = snewn(reqlen, unsigned char); + PUT_32BIT(request, reqlen - 4); + request[4] = SSH1_AGENTC_REMOVE_RSA_IDENTITY; + memcpy(request + 5, key->blob, key->bloblen); + } else { + reqlen = 9 + key->bloblen; + request = snewn(reqlen, unsigned char); + PUT_32BIT(request, reqlen - 4); + request[4] = SSH2_AGENTC_REMOVE_IDENTITY; + PUT_32BIT(request + 5, key->bloblen); + memcpy(request + 9, key->blob, key->bloblen); + } + + ret = agent_query(request, reqlen, &vresponse, &resplen, NULL, NULL); + assert(ret == 1); + response = vresponse; + if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) { + *retstr = dupstr("Agent failed to delete key"); + ret = PAGEANT_ACTION_FAILURE; + } else { + *retstr = NULL; + ret = PAGEANT_ACTION_OK; + } + sfree(request); + sfree(response); + return ret; +} + +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->ssh_version = key->ssh_version; + return ret; +} + +void pageant_pubkey_free(struct pageant_pubkey *key) +{ + sfree(key->blob); + sfree(key); +}