- s->method = 0;
- ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
- s->need_pw = FALSE;
-
- /*
- * Most password/passphrase prompts will be
- * non-echoing, so we set this to 0 by default.
- * Exception is that some keyboard-interactive prompts
- * can be echoing, in which case we'll set this to 1.
- */
- s->echo = 0;
-
- if (!s->method && s->can_pubkey &&
- agent_exists() && !s->tried_agent) {
- /*
- * Attempt public-key authentication using Pageant.
- */
- void *r;
- s->authed = FALSE;
-
- ssh->pkt_ctx &= ~SSH2_PKTCTX_AUTH_MASK;
- ssh->pkt_ctx |= SSH2_PKTCTX_PUBLICKEY;
-
- s->tried_agent = TRUE;
-
- logevent("Pageant is running. Requesting keys.");
-
- /* Request the keys held by the agent. */
- PUT_32BIT(s->request, 1);
- s->request[4] = SSH2_AGENTC_REQUEST_IDENTITIES;
- if (!agent_query(s->request, 5, &r, &s->responselen,
- ssh_agent_callback, ssh)) {
- do {
- crReturnV;
- if (pktin) {
- bombout(("Unexpected data from server while"
- " waiting for agent response"));
- crStopV;
- }
- } while (pktin || inlen > 0);
- r = ssh->agent_response;
- s->responselen = ssh->agent_response_len;
- }
- s->response = (unsigned char *) r;
- if (s->response && s->responselen >= 5 &&
- s->response[4] == SSH2_AGENT_IDENTITIES_ANSWER) {
- s->p = s->response + 5;
- s->nkeys = GET_32BIT(s->p);
- s->p += 4;
- logeventf(ssh, "Pageant has %d SSH-2 keys", s->nkeys);
- for (s->keyi = 0; s->keyi < s->nkeys; s->keyi++) {
- void *vret;
-
- logeventf(ssh, "Trying Pageant key #%d", s->keyi);
- s->pklen = GET_32BIT(s->p);
- s->p += 4;
- if (s->publickey_blob &&
- s->pklen == s->publickey_bloblen &&
- !memcmp(s->p, s->publickey_blob,
- s->publickey_bloblen)) {
- logevent("This key matches configured key file");
- s->tried_pubkey_config = 1;
- }
- s->pkblob = (char *)s->p;
- s->p += s->pklen;
- s->alglen = GET_32BIT(s->pkblob);
- s->alg = s->pkblob + 4;
- s->commentlen = GET_32BIT(s->p);
- s->p += 4;
- s->commentp = (char *)s->p;
- s->p += s->commentlen;
- s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
- ssh2_pkt_addstring(s->pktout, s->username);
- ssh2_pkt_addstring(s->pktout, "ssh-connection"); /* service requested */
- ssh2_pkt_addstring(s->pktout, "publickey"); /* method */
- ssh2_pkt_addbool(s->pktout, FALSE); /* no signature included */
- ssh2_pkt_addstring_start(s->pktout);
- ssh2_pkt_addstring_data(s->pktout, s->alg, s->alglen);
- ssh2_pkt_addstring_start(s->pktout);
- ssh2_pkt_addstring_data(s->pktout, s->pkblob, s->pklen);
- ssh2_pkt_send(ssh, s->pktout);
-
- crWaitUntilV(pktin);
- if (pktin->type != SSH2_MSG_USERAUTH_PK_OK) {
- logevent("Key refused");
- continue;
- }
-
- if (flags & FLAG_VERBOSE) {
- c_write_str(ssh, "Authenticating with "
- "public key \"");
- c_write(ssh, s->commentp, s->commentlen);
- c_write_str(ssh, "\" from agent\r\n");
- }
-
- /*
- * Server is willing to accept the key.
- * Construct a SIGN_REQUEST.
- */
- s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
- ssh2_pkt_addstring(s->pktout, s->username);
- ssh2_pkt_addstring(s->pktout, "ssh-connection"); /* service requested */
- ssh2_pkt_addstring(s->pktout, "publickey"); /* method */
- ssh2_pkt_addbool(s->pktout, TRUE);
- ssh2_pkt_addstring_start(s->pktout);
- ssh2_pkt_addstring_data(s->pktout, s->alg, s->alglen);
- ssh2_pkt_addstring_start(s->pktout);
- ssh2_pkt_addstring_data(s->pktout, s->pkblob, s->pklen);
-
- s->siglen = s->pktout->length - 5 + 4 + 20;
- if (ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)
- s->siglen -= 4;
- s->len = 1; /* message type */
- s->len += 4 + s->pklen; /* key blob */
- s->len += 4 + s->siglen; /* data to sign */
- s->len += 4; /* flags */
- s->agentreq = snewn(4 + s->len, char);
- PUT_32BIT(s->agentreq, s->len);
- s->q = s->agentreq + 4;
- *s->q++ = SSH2_AGENTC_SIGN_REQUEST;
- PUT_32BIT(s->q, s->pklen);
- s->q += 4;
- memcpy(s->q, s->pkblob, s->pklen);
- s->q += s->pklen;
- PUT_32BIT(s->q, s->siglen);
- s->q += 4;
- /* Now the data to be signed... */
- if (!(ssh->remote_bugs & BUG_SSH2_PK_SESSIONID)) {
- PUT_32BIT(s->q, 20);
- s->q += 4;
- }
- memcpy(s->q, ssh->v2_session_id, 20);
- s->q += 20;
- memcpy(s->q, s->pktout->data + 5,
- s->pktout->length - 5);
- s->q += s->pktout->length - 5;
- /* And finally the (zero) flags word. */
- PUT_32BIT(s->q, 0);
- if (!agent_query(s->agentreq, s->len + 4,
- &vret, &s->retlen,
- ssh_agent_callback, ssh)) {
- do {
- crReturnV;
- if (pktin) {
- bombout(("Unexpected data from server"
- " while waiting for agent"
- " response"));
- crStopV;
- }
- } while (pktin || inlen > 0);
- vret = ssh->agent_response;
- s->retlen = ssh->agent_response_len;
- }
- s->ret = vret;
- sfree(s->agentreq);
- if (s->ret) {
- if (s->ret[4] == SSH2_AGENT_SIGN_RESPONSE) {
- logevent("Sending Pageant's response");
- ssh2_add_sigblob(ssh, s->pktout,
- s->pkblob, s->pklen,
- s->ret + 9,
- GET_32BIT(s->ret + 5));
- ssh2_pkt_send(ssh, s->pktout);
- s->authed = TRUE;
- break;
- } else {
- logevent
- ("Pageant failed to answer challenge");
- sfree(s->ret);
- }
- }
- }
- if (s->authed)
- continue;
- }
- sfree(s->response);
- }
-
- if (!s->method && s->can_pubkey && s->publickey_blob
- && !s->tried_pubkey_config) {
- unsigned char *pub_blob;
- char *algorithm, *comment;
- int pub_blob_len;