예제 #1
0
/*
 * Checks if the user has an authentication agent, and if so, tries to
 * authenticate using the agent.
 */
static int
try_agent_authentication(void)
{
	int type;
	char *comment;
	AuthenticationConnection *auth;
	u_char response[16];
	u_int i;
	Key *key;
	BIGNUM *challenge;

	/* Get connection to the agent. */
	auth = ssh_get_authentication_connection();
	if (!auth)
		return 0;

	if ((challenge = BN_new()) == NULL)
		fatal("try_agent_authentication: BN_new failed");
	/* Loop through identities served by the agent. */
	for (key = ssh_get_first_identity(auth, &comment, 1);
	    key != NULL;
	    key = ssh_get_next_identity(auth, &comment, 1)) {

		/* Try this identity. */
		debug("Trying RSA authentication via agent with '%.100s'", comment);
		xfree(comment);

		/* Tell the server that we are willing to authenticate using this key. */
		packet_start(SSH_CMSG_AUTH_RSA);
		packet_put_bignum(key->rsa->n);
		packet_send();
		packet_write_wait();

		/* Wait for server's response. */
		type = packet_read();

		/* The server sends failure if it doesn\'t like our key or
		   does not support RSA authentication. */
		if (type == SSH_SMSG_FAILURE) {
			debug("Server refused our key.");
			key_free(key);
			continue;
		}
		/* Otherwise it should have sent a challenge. */
		if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
			packet_disconnect("Protocol error during RSA authentication: %d",
					  type);

		packet_get_bignum(challenge);
		packet_check_eom();

		debug("Received RSA challenge from server.");

		/* Ask the agent to decrypt the challenge. */
		if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) {
			/*
			 * The agent failed to authenticate this identifier
			 * although it advertised it supports this.  Just
			 * return a wrong value.
			 */
			log("Authentication agent failed to decrypt challenge.");
			memset(response, 0, sizeof(response));
		}
		key_free(key);
		debug("Sending response to RSA challenge.");

		/* Send the decrypted challenge back to the server. */
		packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
		for (i = 0; i < 16; i++)
			packet_put_char(response[i]);
		packet_send();
		packet_write_wait();

		/* Wait for response from the server. */
		type = packet_read();

		/* The server returns success if it accepted the authentication. */
		if (type == SSH_SMSG_SUCCESS) {
			ssh_close_authentication_connection(auth);
			BN_clear_free(challenge);
			debug("RSA authentication accepted by server.");
			return 1;
		}
		/* Otherwise it should return failure. */
		if (type != SSH_SMSG_FAILURE)
			packet_disconnect("Protocol error waiting RSA auth response: %d",
					  type);
	}
	ssh_close_authentication_connection(auth);
	BN_clear_free(challenge);
	debug("RSA authentication using agent refused.");
	return 0;
}
예제 #2
0
/*
 * Checks if the user has an authentication agent, and if so, tries to
 * authenticate using the agent.
 */
static int
try_agent_authentication(struct ssh *ssh)
{
    int r, type, agent_fd, ret = 0;
    u_char response[16];
    size_t i;
    BIGNUM *challenge;
    struct ssh_identitylist *idlist = NULL;

    /* Get connection to the agent. */
    if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
        if (r != SSH_ERR_AGENT_NOT_PRESENT)
            debug("%s: ssh_get_authentication_socket: %s",
                  __func__, ssh_err(r));
        return 0;
    }

    if ((challenge = BN_new()) == NULL)
        fatal("try_agent_authentication: BN_new failed");

    /* Loop through identities served by the agent. */
    if ((r = ssh_fetch_identitylist(agent_fd, 1, &idlist)) != 0) {
        if (r != SSH_ERR_AGENT_NO_IDENTITIES)
            debug("%s: ssh_fetch_identitylist: %s",
                  __func__, ssh_err(r));
        goto out;
    }
    for (i = 0; i < idlist->nkeys; i++) {
        /* Try this identity. */
        debug("Trying RSA authentication via agent with '%.100s'",
              idlist->comments[i]);

        /*
         * Tell the server that we are willing to authenticate
         * using this key.
         */
        if ((r = sshpkt_start(ssh, SSH_CMSG_AUTH_RSA)) != 0 ||
                (r = sshpkt_put_bignum1(ssh, idlist->keys[i]->rsa->n)) != 0 ||
                (r = sshpkt_send(ssh)) != 0)
            fatal("%s: %s", __func__, ssh_err(r));
        ssh_packet_write_wait(ssh);

        /* Wait for server's response. */
        type = ssh_packet_read(ssh);

        /* The server sends failure if it doesn't like our key or
           does not support RSA authentication. */
        if (type == SSH_SMSG_FAILURE) {
            debug("Server refused our key.");
            continue;
        }
        /* Otherwise it should have sent a challenge. */
        if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
            ssh_packet_disconnect(ssh, "Protocol error during RSA "
                                  "authentication: %d", type);

        if ((r = sshpkt_get_bignum1(ssh, challenge)) != 0 ||
                (r = sshpkt_get_end(ssh)) != 0)
            fatal("%s: %s", __func__, ssh_err(r));

        debug("Received RSA challenge from server.");

        /* Ask the agent to decrypt the challenge. */
        if ((r = ssh_decrypt_challenge(agent_fd, idlist->keys[i],
                                       challenge, session_id, response)) != 0) {
            /*
             * The agent failed to authenticate this identifier
             * although it advertised it supports this.  Just
             * return a wrong value.
             */
            logit("Authentication agent failed to decrypt "
                  "challenge: %s", ssh_err(r));
            memset(response, 0, sizeof(response));
        }
        debug("Sending response to RSA challenge.");

        /* Send the decrypted challenge back to the server. */
        if ((r = sshpkt_start(ssh, SSH_CMSG_AUTH_RSA_RESPONSE)) != 0 ||
                (r = sshpkt_put(ssh, &response, sizeof(response))) != 0 ||
                (r = sshpkt_send(ssh)) != 0)
            fatal("%s: %s", __func__, ssh_err(r));
        ssh_packet_write_wait(ssh);

        /* Wait for response from the server. */
        type = ssh_packet_read(ssh);

        /*
         * The server returns success if it accepted the
         * authentication.
         */
        if (type == SSH_SMSG_SUCCESS) {
            debug("RSA authentication accepted by server.");
            ret = 1;
            break;
        } else if (type != SSH_SMSG_FAILURE)
            ssh_packet_disconnect(ssh, "Protocol error waiting RSA auth "
                                  "response: %d", type);
    }
    if (ret != 1)
        debug("RSA authentication using agent refused.");
out:
    ssh_free_identitylist(idlist);
    ssh_close_authentication_socket(agent_fd);
    BN_clear_free(challenge);
    return ret;
}