]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - pageant.c
Centralise public-key output code into sshpubk.c.
[PuTTY.git] / pageant.c
index 51baab02fd434edd4c301e6a19f38b9200c45a75..754af9c6aca103c2b649446f72a92cb1da706aee 100644 (file)
--- 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);
+}