/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Created: Sat Mar 18 22:15:47 1995 ylo
* Code to connect to a remote host, and to perform the client side of the
* login (authentication) dialog.
*
*/
#include "includes.h"
RCSID("$OpenBSD: sshconnect1.c,v 1.2 2000/05/04 22:38:00 markus Exp $");
#include <openssl/bn.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include "xmalloc.h"
#include "rsa.h"
#include "ssh.h"
#include "buffer.h"
#include "packet.h"
#include "authfd.h"
#include "cipher.h"
#include "mpaux.h"
#include "uidswap.h"
#include "readconf.h"
#include "key.h"
#include "sshconnect.h"
#include "authfile.h"
/* Session id for the current session. */
unsigned char session_id[16];
unsigned int supported_authentications = 0;
extern Options options;
extern char *__progname;
/*
* Checks if the user has an authentication agent, and if so, tries to
* authenticate using the agent.
*/
int
try_agent_authentication()
{
int status, type;
char *comment;
AuthenticationConnection *auth;
unsigned char response[16];
unsigned int i;
BIGNUM *e, *n, *challenge;
/* Get connection to the agent. */
auth = ssh_get_authentication_connection();
if (!auth)
return 0;
e = BN_new();
n = BN_new();
challenge = BN_new();
/* Loop through identities served by the agent. */
for (status = ssh_get_first_identity(auth, e, n, &comment);
status;
status = ssh_get_next_identity(auth, e, n, &comment)) {
int plen, clen;
/* 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(n);
packet_send();
packet_write_wait();
/* Wait for server's response. */
type = packet_read(&plen);
/* 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)
packet_disconnect("Protocol error during RSA authentication: %d",
type);
packet_get_bignum(challenge, &clen);
packet_integrity_check(plen, clen, type);
debug("Received RSA challenge from server.");
/* Ask the agent to decrypt the challenge. */
if (!ssh_decrypt_challenge(auth, e, n, 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));
}
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(&plen);
/* The server returns success if it accepted the authentication. */
if (type == SSH_SMSG_SUCCESS) {
debug("RSA authentication accepted by server.");
BN_clear_free(e);
BN_clear_free(n);
BN_clear_free(challenge);
return 1;
}
/* Otherwise it should return failure. */
if (type != SSH_SMSG_FAILURE)
packet_disconnect("Protocol error waiting RSA auth response: %d",
type);
}
BN_clear_free(e);
BN_clear_free(n);
BN_clear_free(challenge);
debug("RSA authentication using agent refused.");
return 0;
}
/*
* Computes the proper response to a RSA challenge, and sends the response to
* the server.
*/
void
respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
{
unsigned char buf[32], response[16];
MD5_CTX md;
int i, len;
/* Decrypt the challenge using the private key. */
rsa_private_decrypt(challenge, challenge, prv);
/* Compute the response. */
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > sizeof(