+
+ if (add234(ssh2keys, key) == key) {
+ keylist_update();
+ PUT_32BIT(ret, 1);
+ ret[4] = SSH_AGENT_SUCCESS;
+
+ plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
+ } else {
+ key->alg->freekey(key->data);
+ sfree(key->comment);
+ sfree(key);
+
+ fail_reason = "key already present";
+ goto failure;
+ }
+ }
+ 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;
+
+ plog(logctx, logfn, "request: SSH1_AGENTC_REMOVE_RSA_IDENTITY");
+
+ n = makekey(p, msgend - p, &reqkey, NULL, 0);
+ if (n < 0) {
+ fail_reason = "request truncated before public key";
+ goto failure;
+ }
+
+ if (logfn) {
+ char fingerprint[128];
+ reqkey.comment = NULL;
+ rsa_fingerprint(fingerprint, sizeof(fingerprint), &reqkey);
+ plog(logctx, logfn, "unwanted key: %s", fingerprint);
+ }
+
+ key = find234(rsakeys, &reqkey, NULL);
+ freebn(reqkey.exponent);
+ freebn(reqkey.modulus);
+ PUT_32BIT(ret, 1);
+ if (key) {
+ plog(logctx, logfn, "found with comment: %s", key->comment);
+
+ del234(rsakeys, key);
+ keylist_update();
+ freersakey(key);
+ sfree(key);
+ ret[4] = SSH_AGENT_SUCCESS;
+
+ plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
+ } else {
+ fail_reason = "key not found";
+ goto failure;
+ }
+ }
+ 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;
+
+ plog(logctx, logfn, "request: SSH2_AGENTC_REMOVE_IDENTITY");
+
+ if (msgend < p+4) {
+ fail_reason = "request truncated before public key";
+ goto failure;
+ }
+ b.len = toint(GET_32BIT(p));
+ p += 4;
+
+ if (b.len < 0 || b.len > msgend - p) {
+ fail_reason = "request truncated before public key";
+ goto failure;
+ }
+ b.blob = p;
+ p += b.len;
+
+ if (logfn) {
+ char *fingerprint = ssh2_fingerprint_blob(b.blob, b.len);
+ plog(logctx, logfn, "unwanted key: %s", fingerprint);
+ sfree(fingerprint);
+ }
+
+ key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
+ if (!key) {
+ fail_reason = "key not found";
+ goto failure;
+ }
+
+ plog(logctx, logfn, "found with comment: %s", key->comment);
+
+ del234(ssh2keys, key);
+ keylist_update();
+ key->alg->freekey(key->data);
+ sfree(key);
+ PUT_32BIT(ret, 1);
+ ret[4] = SSH_AGENT_SUCCESS;
+
+ plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
+ }
+ break;
+ case SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
+ /*
+ * Remove all SSH-1 keys. Always returns success.
+ */
+ {
+ struct RSAKey *rkey;
+
+ plog(logctx, logfn, "request:"
+ " SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES");
+
+ while ((rkey = index234(rsakeys, 0)) != NULL) {
+ del234(rsakeys, rkey);
+ freersakey(rkey);
+ sfree(rkey);
+ }
+ keylist_update();
+
+ PUT_32BIT(ret, 1);
+ ret[4] = SSH_AGENT_SUCCESS;
+
+ plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
+ }
+ break;
+ case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
+ /*
+ * Remove all SSH-2 keys. Always returns success.
+ */
+ {
+ struct ssh2_userkey *skey;
+
+ plog(logctx, logfn, "request: SSH2_AGENTC_REMOVE_ALL_IDENTITIES");
+
+ 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;
+
+ plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
+ }
+ break;