summaryrefslogtreecommitdiff
path: root/usr.bin/ssh
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2000-01-16 23:03:11 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2000-01-16 23:03:11 +0000
commit973929e301f19d3be1b9ed024329e1b209a9ed26 (patch)
tree275127ceeb0535fb409a3a82735f52df7022f6e0 /usr.bin/ssh
parenta7259a6771c35fbaf44dd8ea8bd3b5216e74de4e (diff)
split key exchange (kex) and user authentication (user-auth), ok: provos@
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r--usr.bin/ssh/sshconnect.c111
-rw-r--r--usr.bin/ssh/sshd.c76
2 files changed, 106 insertions, 81 deletions
diff --git a/usr.bin/ssh/sshconnect.c b/usr.bin/ssh/sshconnect.c
index 15db438c705..f16e2b32dab 100644
--- a/usr.bin/ssh/sshconnect.c
+++ b/usr.bin/ssh/sshconnect.c
@@ -8,7 +8,7 @@
*/
#include "includes.h"
-RCSID("$Id: sshconnect.c,v 1.50 2000/01/05 08:32:42 markus Exp $");
+RCSID("$OpenBSD: sshconnect.c,v 1.51 2000/01/16 23:03:10 markus Exp $");
#include <ssl/bn.h>
#include "xmalloc.h"
@@ -28,6 +28,9 @@ RCSID("$Id: sshconnect.c,v 1.50 2000/01/05 08:32:42 markus Exp $");
/* Session id for the current session. */
unsigned char session_id[16];
+/* authentications supported by server */
+unsigned int supported_authentications;
+
extern Options options;
extern char *__progname;
@@ -1264,63 +1267,31 @@ check_host_key(char *host, struct sockaddr *hostaddr, RSA *host_key)
}
/*
- * Starts a dialog with the server, and authenticates the current user on the
- * server. This does not need any extra privileges. The basic connection
- * to the server must already have been established before this is called.
- * User is the remote user; if it is NULL, the current local user name will
- * be used. Anonymous indicates that no rhosts authentication will be used.
- * If login fails, this function prints an error and never returns.
- * This function does not require super-user privileges.
+ * SSH1 key exchange
*/
void
-ssh_login(int host_key_valid,
- RSA *own_host_key,
- const char *orighost,
- struct sockaddr *hostaddr,
- uid_t original_real_uid)
+ssh_kex(char *host, struct sockaddr *hostaddr)
{
- int i, type;
- struct passwd *pw;
+ int i;
BIGNUM *key;
RSA *host_key;
RSA *public_key;
int bits, rbits;
unsigned char session_key[SSH_SESSION_KEY_LENGTH];
- const char *server_user, *local_user;
- char *host, *cp;
- unsigned char check_bytes[8];
- unsigned int supported_ciphers, supported_authentications;
+ unsigned char cookie[8];
+ unsigned int supported_ciphers;
unsigned int server_flags, client_flags;
int payload_len, clen, sum_len = 0;
u_int32_t rand = 0;
- /* Convert the user-supplied hostname into all lowercase. */
- host = xstrdup(orighost);
- for (cp = host; *cp; cp++)
- if (isupper(*cp))
- *cp = tolower(*cp);
-
- /* Exchange protocol version identification strings with the server. */
- ssh_exchange_identification();
-
- /* Put the connection into non-blocking mode. */
- packet_set_nonblocking();
-
- /* Get local user name. Use it as server user if no user name was given. */
- pw = getpwuid(original_real_uid);
- if (!pw)
- fatal("User id %d not found from user database.", original_real_uid);
- local_user = xstrdup(pw->pw_name);
- server_user = options.user ? options.user : local_user;
-
debug("Waiting for server public key.");
/* Wait for a public key packet from the server. */
packet_read_expect(&payload_len, SSH_SMSG_PUBLIC_KEY);
- /* Get check bytes from the packet. */
+ /* Get cookie from the packet. */
for (i = 0; i < 8; i++)
- check_bytes[i] = packet_get_char();
+ cookie[i] = packet_get_char();
/* Get the public key. */
public_key = RSA_new();
@@ -1373,7 +1344,7 @@ ssh_login(int host_key_valid,
client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN;
- compute_session_id(session_id, check_bytes, host_key->n, public_key->n);
+ compute_session_id(session_id, cookie, host_key->n, public_key->n);
/* Generate a session key. */
arc4random_stir();
@@ -1456,9 +1427,9 @@ ssh_login(int host_key_valid,
packet_start(SSH_CMSG_SESSION_KEY);
packet_put_char(options.cipher);
- /* Send the check bytes back to the server. */
+ /* Send the cookie back to the server. */
for (i = 0; i < 8; i++)
- packet_put_char(check_bytes[i]);
+ packet_put_char(cookie[i]);
/* Send the encrypted encryption key. */
packet_put_bignum(key);
@@ -1490,6 +1461,26 @@ ssh_login(int host_key_valid,
packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
debug("Received encrypted confirmation.");
+}
+
+/*
+ * Authenticate user
+ */
+void
+ssh_userauth(int host_key_valid, RSA *own_host_key,
+ uid_t original_real_uid, char *host)
+{
+ int i, type;
+ int payload_len;
+ struct passwd *pw;
+ const char *server_user, *local_user;
+
+ /* Get local user name. Use it as server user if no user name was given. */
+ pw = getpwuid(original_real_uid);
+ if (!pw)
+ fatal("User id %d not found from user database.", original_real_uid);
+ local_user = xstrdup(pw->pw_name);
+ server_user = options.user ? options.user : local_user;
/* Send the name of the user to log in as on the server. */
packet_start(SSH_CMSG_USER);
@@ -1608,3 +1599,37 @@ ssh_login(int host_key_valid,
fatal("Permission denied.");
/* NOTREACHED */
}
+
+/*
+ * Starts a dialog with the server, and authenticates the current user on the
+ * server. This does not need any extra privileges. The basic connection
+ * to the server must already have been established before this is called.
+ * If login fails, this function prints an error and never returns.
+ * This function does not require super-user privileges.
+ */
+void
+ssh_login(int host_key_valid, RSA *own_host_key, const char *orighost,
+ struct sockaddr *hostaddr, uid_t original_real_uid)
+{
+ char *host, *cp;
+
+ /* Convert the user-supplied hostname into all lowercase. */
+ host = xstrdup(orighost);
+ for (cp = host; *cp; cp++)
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+
+ /* Exchange protocol version identification strings with the server. */
+ ssh_exchange_identification();
+
+ /* Put the connection into non-blocking mode. */
+ packet_set_nonblocking();
+
+ supported_authentications = 0;
+ /* key exchange */
+ ssh_kex(host, hostaddr);
+ if (supported_authentications == 0)
+ fatal("supported_authentications == 0.");
+ /* authenticate user */
+ ssh_userauth(host_key_valid, own_host_key, original_real_uid, host);
+}
diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c
index e25ace295bf..1c8b3aee5f1 100644
--- a/usr.bin/ssh/sshd.c
+++ b/usr.bin/ssh/sshd.c
@@ -11,7 +11,7 @@
*/
#include "includes.h"
-RCSID("$Id: sshd.c,v 1.76 2000/01/04 16:54:58 markus Exp $");
+RCSID("$OpenBSD: sshd.c,v 1.77 2000/01/16 23:03:10 markus Exp $");
#include <poll.h>
@@ -129,8 +129,8 @@ int received_sighup = 0;
RSA *public_key;
/* Prototypes for various functions defined later in this file. */
-void do_connection();
-void do_authentication(char *user);
+void do_ssh_kex();
+void do_authentication();
void do_authloop(struct passwd * pw);
void do_fake_authloop(char *user);
void do_authenticated(struct passwd * pw);
@@ -858,8 +858,11 @@ main(int ac, char **av)
packet_set_nonblocking();
- /* Handle the connection. */
- do_connection();
+ /* perform the key exchange */
+ do_ssh_kex();
+
+ /* authenticate user and start session */
+ do_authentication();
#ifdef KRB4
/* Cleanup user's ticket cache file. */
@@ -878,20 +881,17 @@ main(int ac, char **av)
}
/*
- * Process an incoming connection. Protocol version identifiers have already
- * been exchanged. This sends server key and performs the key exchange.
- * Server and host keys will no longer be needed after this functions.
+ * SSH1 key exchange
*/
void
-do_connection()
+do_ssh_kex()
{
int i, len;
+ int plen, slen;
BIGNUM *session_key_int;
unsigned char session_key[SSH_SESSION_KEY_LENGTH];
- unsigned char check_bytes[8];
- char *user;
+ unsigned char cookie[8];
unsigned int cipher_type, auth_mask, protocol_flags;
- int plen, slen, ulen;
u_int32_t rand = 0;
/*
@@ -906,7 +906,7 @@ do_connection()
for (i = 0; i < 8; i++) {
if (i % 4 == 0)
rand = arc4random();
- check_bytes[i] = rand & 0xff;
+ cookie[i] = rand & 0xff;
rand >>= 8;
}
@@ -917,7 +917,7 @@ do_connection()
*/
packet_start(SSH_SMSG_PUBLIC_KEY);
for (i = 0; i < 8; i++)
- packet_put_char(check_bytes[i]);
+ packet_put_char(cookie[i]);
/* Store our public server RSA key. */
packet_put_int(BN_num_bits(public_key->n));
@@ -980,7 +980,7 @@ do_connection()
/* Get check bytes from the packet. These must match those we
sent earlier with the public key packet. */
for (i = 0; i < 8; i++)
- if (check_bytes[i] != packet_get_char())
+ if (cookie[i] != packet_get_char())
packet_disconnect("IP Spoofing check bytes do not match.");
debug("Encryption type: %.200s", cipher_name(cipher_type));
@@ -1028,10 +1028,15 @@ do_connection()
sensitive_data.private_key);
}
- compute_session_id(session_id, check_bytes,
+ compute_session_id(session_id, cookie,
sensitive_data.host_key->n,
sensitive_data.private_key->n);
+ /* Destroy the private and public keys. They will no longer be needed. */
+ RSA_free(public_key);
+ RSA_free(sensitive_data.private_key);
+ RSA_free(sensitive_data.host_key);
+
/*
* Extract session key from the decrypted integer. The key is in the
* least significant 256 bits of the integer; the first byte of the
@@ -1046,13 +1051,13 @@ do_connection()
memset(session_key, 0, sizeof(session_key));
BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len);
+ /* Destroy the decrypted integer. It is no longer needed. */
+ BN_clear_free(session_key_int);
+
/* Xor the first 16 bytes of the session key with the session id. */
for (i = 0; i < 16; i++)
session_key[i] ^= session_id[i];
- /* Destroy the decrypted integer. It is no longer needed. */
- BN_clear_free(session_key_int);
-
/* Set the session key. From this on all communications will be encrypted. */
packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type);
@@ -1065,24 +1070,9 @@ do_connection()
packet_start(SSH_SMSG_SUCCESS);
packet_send();
packet_write_wait();
-
- /* Get the name of the user that we wish to log in as. */
- packet_read_expect(&plen, SSH_CMSG_USER);
-
- /* Get the user name. */
- user = packet_get_string(&ulen);
- packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
-
- /* Destroy the private and public keys. They will no longer be needed. */
- RSA_free(public_key);
- RSA_free(sensitive_data.private_key);
- RSA_free(sensitive_data.host_key);
-
- setproctitle("%s", user);
- /* Do the authentication. */
- do_authentication(user);
}
+
/*
* Check if the user is allowed to log in via ssh. If user is listed in
* DenyUsers or user's primary group is listed in DenyGroups, false will
@@ -1158,13 +1148,23 @@ allowed_user(struct passwd * pw)
/*
* Performs authentication of an incoming connection. Session key has already
- * been exchanged and encryption is enabled. User is the user name to log
- * in as (received from the client).
+ * been exchanged and encryption is enabled.
*/
void
-do_authentication(char *user)
+do_authentication()
{
struct passwd *pw, pwcopy;
+ int plen, ulen;
+ char *user;
+
+ /* Get the name of the user that we wish to log in as. */
+ packet_read_expect(&plen, SSH_CMSG_USER);
+
+ /* Get the user name. */
+ user = packet_get_string(&ulen);
+ packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
+
+ setproctitle("%s", user);
#ifdef AFS
/* If machine has AFS, set process authentication group. */