diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2000-01-16 23:03:11 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2000-01-16 23:03:11 +0000 |
commit | 973929e301f19d3be1b9ed024329e1b209a9ed26 (patch) | |
tree | 275127ceeb0535fb409a3a82735f52df7022f6e0 /usr.bin/ssh | |
parent | a7259a6771c35fbaf44dd8ea8bd3b5216e74de4e (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.c | 111 | ||||
-rw-r--r-- | usr.bin/ssh/sshd.c | 76 |
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. */ |