- if (msgend < p+commentlen) {
- freersakey(key);
- sfree(key);
- goto failure;
- }
-
- comment = snewn(commentlen+1, char);
- if (comment) {
- memcpy(comment, p + 4, commentlen);
- comment[commentlen] = '\0';
- key->comment = comment;
- }
- PUT_32BIT(ret, 1);
- ret[4] = SSH_AGENT_FAILURE;
- if (add234(rsakeys, key) == key) {
- keylist_update();
- ret[4] = SSH_AGENT_SUCCESS;
- } else {
- freersakey(key);
- sfree(key);
- }
- }
- break;
- case SSH2_AGENTC_ADD_IDENTITY:
- /*
- * Add to the list and return SSH_AGENT_SUCCESS, or
- * SSH_AGENT_FAILURE if the key was malformed.
- */
- {
- struct ssh2_userkey *key;
- char *comment, *alg;
- int alglen, commlen;
- int bloblen;
-
-
- if (msgend < p+4)
- goto failure;
- alglen = GET_32BIT(p);
- p += 4;
- if (msgend < p+alglen)
- goto failure;
- alg = p;
- p += alglen;
-
- key = snew(struct ssh2_userkey);
- /* Add further algorithm names here. */
- if (alglen == 7 && !memcmp(alg, "ssh-rsa", 7))
- key->alg = &ssh_rsa;
- else if (alglen == 7 && !memcmp(alg, "ssh-dss", 7))
- key->alg = &ssh_dss;
- else {
- sfree(key);
- goto failure;
- }
-
- bloblen = msgend - p;
- key->data = key->alg->openssh_createkey(&p, &bloblen);
- if (!key->data) {
- sfree(key);
- goto failure;
- }
-
- /*
- * p has been advanced by openssh_createkey, but
- * certainly not _beyond_ the end of the buffer.
- */
- assert(p <= msgend);
-
- if (msgend < p+4) {
- key->alg->freekey(key->data);
- sfree(key);
- goto failure;
- }
- commlen = GET_32BIT(p);
- p += 4;
-
- if (msgend < p+commlen) {
- key->alg->freekey(key->data);
- sfree(key);
- goto failure;
- }
- comment = snewn(commlen + 1, char);
- if (comment) {
- memcpy(comment, p, commlen);
- comment[commlen] = '\0';
- }
- key->comment = comment;
-
- PUT_32BIT(ret, 1);
- ret[4] = SSH_AGENT_FAILURE;
- if (add234(ssh2keys, key) == key) {
- keylist_update();
- ret[4] = SSH_AGENT_SUCCESS;
- } else {
- key->alg->freekey(key->data);
- sfree(key->comment);
- sfree(key);
- }
- }
- break;
- case SSH1_AGENTC_REMOVE_RSA_IDENTITY:
- /*
- * Remove from the list and return SSH_AGENT_SUCCESS, or
- * perhaps SSH_AGENT_FAILURE if it wasn't in the list to
- * start with.
- */
- {
- struct RSAKey reqkey, *key;
- int n;
-
- n = makekey(p, msgend - p, &reqkey, NULL, 0);
- if (n < 0)
- goto failure;
-
- key = find234(rsakeys, &reqkey, NULL);
- freebn(reqkey.exponent);
- freebn(reqkey.modulus);
- PUT_32BIT(ret, 1);
- ret[4] = SSH_AGENT_FAILURE;
- if (key) {
- del234(rsakeys, key);
- keylist_update();
- freersakey(key);
- sfree(key);
- ret[4] = SSH_AGENT_SUCCESS;
- }
- }
- break;
- case SSH2_AGENTC_REMOVE_IDENTITY:
- /*
- * Remove from the list and return SSH_AGENT_SUCCESS, or
- * perhaps SSH_AGENT_FAILURE if it wasn't in the list to
- * start with.
- */
- {
- struct ssh2_userkey *key;
- struct blob b;
-
- if (msgend < p+4)
- goto failure;
- b.len = GET_32BIT(p);
- p += 4;
-
- if (msgend < p+b.len)
- goto failure;
- b.blob = p;
- p += b.len;
-
- key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
- if (!key)
- goto failure;
-
- PUT_32BIT(ret, 1);
- ret[4] = SSH_AGENT_FAILURE;
- if (key) {
- del234(ssh2keys, key);
- keylist_update();
- key->alg->freekey(key->data);
- sfree(key);
- ret[4] = SSH_AGENT_SUCCESS;
- }
- }
- break;
- case SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
- /*
- * Remove all SSH-1 keys. Always returns success.
- */
- {
- struct RSAKey *rkey;
-
- while ((rkey = index234(rsakeys, 0)) != NULL) {
- del234(rsakeys, rkey);
- freersakey(rkey);
- sfree(rkey);
- }
- keylist_update();
-
- PUT_32BIT(ret, 1);
- ret[4] = SSH_AGENT_SUCCESS;
- }
- break;
- case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
- /*
- * Remove all SSH-2 keys. Always returns success.
- */
- {
- struct ssh2_userkey *skey;
-
- while ((skey = index234(ssh2keys, 0)) != NULL) {
- del234(ssh2keys, skey);
- skey->alg->freekey(skey->data);
- sfree(skey);
- }
- keylist_update();
-
- PUT_32BIT(ret, 1);
- ret[4] = SSH_AGENT_SUCCESS;
- }
- break;
- default:
- failure:
- /*
- * Unrecognised message. Return SSH_AGENT_FAILURE.
- */
- PUT_32BIT(ret, 1);
- ret[4] = SSH_AGENT_FAILURE;
- break;
- }
-}
-
-/*
- * Key comparison function for the 2-3-4 tree of RSA keys.
- */
-static int cmpkeys_rsa(void *av, void *bv)
-{
- struct RSAKey *a = (struct RSAKey *) av;
- struct RSAKey *b = (struct RSAKey *) bv;
- Bignum am, bm;
- int alen, blen;
-
- am = a->modulus;
- bm = b->modulus;
- /*
- * Compare by length of moduli.
- */
- alen = bignum_bitcount(am);
- blen = bignum_bitcount(bm);
- if (alen > blen)
- return +1;
- else if (alen < blen)
- return -1;
- /*
- * Now compare by moduli themselves.
- */
- alen = (alen + 7) / 8; /* byte count */
- while (alen-- > 0) {
- int abyte, bbyte;
- abyte = bignum_byte(am, alen);
- bbyte = bignum_byte(bm, alen);
- if (abyte > bbyte)
- return +1;
- else if (abyte < bbyte)
- return -1;
- }
- /*
- * Give up.
- */
- return 0;
-}
-
-/*
- * Key comparison function for the 2-3-4 tree of SSH-2 keys.
- */
-static int cmpkeys_ssh2(void *av, void *bv)
-{
- struct ssh2_userkey *a = (struct ssh2_userkey *) av;
- struct ssh2_userkey *b = (struct ssh2_userkey *) bv;
- int i;
- int alen, blen;
- unsigned char *ablob, *bblob;
- int c;
-
- /*
- * Compare purely by public blob.
- */
- ablob = a->alg->public_blob(a->data, &alen);
- bblob = b->alg->public_blob(b->data, &blen);