From: damien Date: Thu, 20 Jan 2000 11:44:08 +0000 (+0000) Subject: - Update to latest OpenBSD CVS: X-Git-Tag: V_1_2_2_PRE28~15 X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/commitdiff_plain/7b2ea3a180f7ab27cf15e0438da23a8d2fe5e8cc - Update to latest OpenBSD CVS: - [auth-rsa.c] - fix user/1056, sshd keeps restrictions; dbt@meat.net - [sshconnect.c] - disable agent fwding for proto 1.3, remove abuse of auth-rsa flags. - destroy keys earlier - split key exchange (kex) and user authentication (user-auth), ok: provos@ - [sshd.c] - no need for poll.h; from bright@wintelcom.net - disable agent fwding for proto 1.3, remove abuse of auth-rsa flags. - split key exchange (kex) and user authentication (user-auth), ok: provos@ --- diff --git a/ChangeLog b/ChangeLog index d49ac0bb..25ca7e0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 20000120 - Don't use getaddrinfo on AIX + - Update to latest OpenBSD CVS: + - [auth-rsa.c] + - fix user/1056, sshd keeps restrictions; dbt@meat.net + - [sshconnect.c] + - disable agent fwding for proto 1.3, remove abuse of auth-rsa flags. + - destroy keys earlier + - split key exchange (kex) and user authentication (user-auth), ok: provos@ + - [sshd.c] + - no need for poll.h; from bright@wintelcom.net + - disable agent fwding for proto 1.3, remove abuse of auth-rsa flags. + - split key exchange (kex) and user authentication (user-auth), ok: provos@ 20000119 - SCO compile fixes from Gary E. Miller diff --git a/auth-rsa.c b/auth-rsa.c index 955532ce..2dcfd749 100644 --- a/auth-rsa.c +++ b/auth-rsa.c @@ -415,7 +415,22 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n) packet_send_debug("Your host '%.200s' is not permitted to use this key for login.", get_canonical_hostname()); xfree(patterns); + /* key invalid for this host, reset flags */ authenticated = 0; + no_agent_forwarding_flag = 0; + no_port_forwarding_flag = 0; + no_pty_flag = 0; + no_x11_forwarding_flag = 0; + while (custom_environment) { + struct envstring *ce = custom_environment; + custom_environment = ce->next; + xfree(ce->s); + xfree(ce); + } + if (forced_command) { + xfree(forced_command); + forced_command = NULL; + } break; } xfree(patterns); diff --git a/ssh.1.in b/ssh.1.in index f7f10ea7..4915c994 100644 --- a/ssh.1.in +++ b/ssh.1.in @@ -33,16 +33,16 @@ .Op Fl p Ar port .Oo Fl L Xo .Sm off -.Ar host : .Ar port : +.Ar host : .Ar hostport .Sm on .Xc .Oc .Oo Fl R Xo .Sm off -.Ar host : .Ar port : +.Ar host : .Ar hostport .Sm on .Xc @@ -302,6 +302,8 @@ wants it in the background. This implies The recommended way to start X11 programs at a remote site is with something like .Ic ssh -f host xterm . +.It Fl g +Allows remote hosts to connect to local forwarded ports. .It Fl i Ar identity_file Selects the file from which the identity (private key) for RSA authentication is read. Default is @@ -312,8 +314,6 @@ multiple .Fl i options (and multiple identities specified in configuration files). -.It Fl g -Allows remote hosts to connect to local forwarded ports. .It Fl k Disables forwarding of Kerberos tickets and AFS tokens. This may also be specified on a per-host basis in the configuration file. @@ -378,7 +378,9 @@ Enables X11 forwarding. .It Fl C Requests compression of all data (including stdin, stdout, stderr, and data for forwarded X11 and TCP/IP connections). The compression -algorithm is the same used by gzip, and the +algorithm is the same used by +.Xr gzip 1 , +and the .Dq level can be controlled by the .Cm CompressionLevel @@ -486,6 +488,15 @@ user to supply the password. The argument must be .Dq yes or .Dq no . +.It Cm CheckHostIP +If this flag is set to +.Dq yes , +ssh will additionally check the host ip address in the +.Pa known_hosts +file. This allows ssh to detect if a host key changed due to DNS spoofing. +If the option is set to +.Dq no , +the check will not be executed. .It Cm Cipher Specifies the cipher to use for encrypting the session. Currently, .Dq blowfish , @@ -502,7 +513,8 @@ or Specifies the compression level to use if compression is enable. The argument must be an integer from 1 (fast) to 9 (slow, best). The default level is 6, which is good for most applications. The meaning -of the values is the same as in GNU GZIP. +of the values is the same as in +.Xr gzip 1 . .It Cm ConnectionAttempts Specifies the number of tries (one per second) to make before falling back to rsh or exiting. The argument must be an integer. This may be @@ -610,12 +622,6 @@ first argument must be a port number, and the second must be host:port. Multiple forwardings may be specified, and additional forwardings can be given on the command line. Only the root can forward privileged ports. -.It Cm PasswordAuthentication -Specifies whether to use password authentication. The argument to -this keyword must be -.Dq yes -or -.Dq no . .It Cm LogLevel Gives the verbosity level that is used when logging messages from .Nm ssh . @@ -625,6 +631,12 @@ The default is INFO. .It Cm NumberOfPasswordPrompts Specifies the number of password prompts before giving up. The argument to this keyword must be an integer. Default is 3. +.It Cm PasswordAuthentication +Specifies whether to use password authentication. The argument to +this keyword must be +.Dq yes +or +.Dq no . .It Cm Port Specifies the port number to connect on the remote host. Default is 22. @@ -689,15 +701,6 @@ or .Dq no . The default is .Dq no . -.It Cm CheckHostIP -If this flag is set to -.Dq yes , -ssh will additionally check the host ip address in the -.Pa known_hosts -file. This allows ssh to detect if a host key changed due to DNS spoofing. -If the option is set to -.Dq no , -the check will not be executed. .It Cm StrictHostKeyChecking If this flag is set to .Dq yes , @@ -717,13 +720,6 @@ argument must be .Dq yes or .Dq no . -.It Cm User -Specifies the user to log in as. This can be useful if you have a -different user name in different machines. This saves the trouble of -having to remember to give the user name on the command line. -.It Cm UserKnownHostsFile -Specifies a file to use instead of -.Pa $HOME/.ssh/known_hosts . .It Cm UsePrivilegedPort Specifies whether to use a privileged port for outgoing connections. The argument must be @@ -738,6 +734,13 @@ turns off .Cm RhostsAuthentication and .Cm RhostsRSAAuthentication . +.It Cm User +Specifies the user to log in as. This can be useful if you have a +different user name in different machines. This saves the trouble of +having to remember to give the user name on the command line. +.It Cm UserKnownHostsFile +Specifies a file to use instead of +.Pa $HOME/.ssh/known_hosts . .It Cm UseRsh Specifies that rlogin/rsh should be used for this host. It is possible that the host does not at all support the diff --git a/sshconnect.c b/sshconnect.c index c1b38f0f..5e2a3449 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -8,7 +8,7 @@ */ #include "includes.h" -RCSID("$Id$"); +RCSID("$OpenBSD: sshconnect.c,v 1.53 2000/01/18 09:42:17 markus Exp $"); #ifdef HAVE_OPENSSL #include @@ -34,6 +34,9 @@ RCSID("$Id$"); /* 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; @@ -988,9 +991,8 @@ ssh_exchange_identification() /* We speak 1.3, too. */ if (remote_major == 1 && remote_minor == 3) { enable_compat13(); - if (options.forward_agent && strcmp(remote_version, "OpenSSH-1.1") != 0) { - log("Agent forwarding disabled, remote version '%s' is not compatible.", - remote_version); + if (options.forward_agent) { + log("Agent forwarding disabled for protocol 1.3"); options.forward_agent = 0; } } @@ -1274,63 +1276,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(); @@ -1383,7 +1353,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(); @@ -1445,6 +1415,10 @@ ssh_login(int host_key_valid, rsa_public_encrypt(key, key, public_key); } + /* Destroy the public keys since we no longer need them. */ + RSA_free(public_key); + RSA_free(host_key); + if (options.cipher == SSH_CIPHER_NOT_SET) { if (cipher_mask() & supported_ciphers & (1 << ssh_cipher_default)) options.cipher = ssh_cipher_default; @@ -1466,12 +1440,13 @@ 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. */ + /* Send and destroy the encrypted encryption key integer. */ packet_put_bignum(key); + BN_clear_free(key); /* Send protocol flags. */ packet_put_int(client_flags); @@ -1480,11 +1455,6 @@ ssh_login(int host_key_valid, packet_send(); packet_write_wait(); - /* Destroy the session key integer and the public keys since we no longer need them. */ - BN_clear_free(key); - RSA_free(public_key); - RSA_free(host_key); - debug("Sent encrypted session key."); /* Set the encryption key. */ @@ -1500,6 +1470,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); @@ -1618,3 +1608,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/sshd.8.in b/sshd.8.in index 2dca60e5..a7c0e4d2 100644 --- a/sshd.8.in +++ b/sshd.8.in @@ -242,7 +242,7 @@ the primary group. .Pp .It Cm DenyUsers This keyword can be followed by a number of user names, separated -by spaces. Login is allowed disallowed for user names that match +by spaces. Login is disallowed for user names that match one of the patterns. .Ql \&* and @@ -436,17 +436,17 @@ Specifies whether .Xr login 1 is used. The default is .Dq no . -.It Cm X11Forwarding -Specifies whether X11 forwarding is permitted. The default is -.Dq yes . -Note that disabling X11 forwarding does not improve security in any -way, as users can always install their own forwarders. .It Cm X11DisplayOffset Specifies the first display number available for .Nm sshd Ns 's X11 forwarding. This prevents .Nm from interfering with real X11 servers. +.It Cm X11Forwarding +Specifies whether X11 forwarding is permitted. The default is +.Dq yes . +Note that disabling X11 forwarding does not improve security in any +way, as users can always install their own forwarders. .El .Sh LOGIN PROCESS When a user successfully logs in, diff --git a/sshd.c b/sshd.c index 33b84ddb..03a9ce12 100644 --- a/sshd.c +++ b/sshd.c @@ -11,7 +11,7 @@ */ #include "includes.h" -RCSID("$Id$"); +RCSID("$OpenBSD: sshd.c,v 1.79 2000/01/18 13:45:05 markus Exp $"); #include "xmalloc.h" #include "rsa.h" @@ -131,8 +131,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); @@ -835,11 +835,8 @@ main(int ac, char **av) packet_disconnect("Your ssh version is too old and is no longer supported. Please install a newer version."); if (remote_major == 1 && remote_minor == 3) { + /* note that this disables agent-forwarding */ enable_compat13(); - if (strcmp(remote_version, "OpenSSH-1.1") != 0) { - debug("Agent forwarding disabled, remote version is not compatible."); - no_agent_forwarding_flag = 1; - } } /* * Check that the connection comes from a privileged port. Rhosts- @@ -863,8 +860,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. */ @@ -888,20 +888,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; /* @@ -916,7 +913,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; } @@ -927,7 +924,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)); @@ -990,7 +987,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)); @@ -1038,10 +1035,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 @@ -1056,13 +1058,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); @@ -1075,24 +1077,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 @@ -1168,13 +1155,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. */ @@ -1771,7 +1768,7 @@ do_authenticated(struct passwd * pw) #endif /* XAUTH_PATH */ case SSH_CMSG_AGENT_REQUEST_FORWARDING: - if (no_agent_forwarding_flag) { + if (no_agent_forwarding_flag || compat13) { debug("Authentication agent forwarding not permitted for this authentication."); goto fail; }