From 6cb6dcffe1a2204ba9006de20f73255c268fcb6b Mon Sep 17 00:00:00 2001 From: "markus@openbsd.org" Date: Sat, 13 Aug 2016 17:47:40 +0000 Subject: upstream commit remove ssh1 server code; ok djm@ Upstream-ID: c24c0c32c49b91740d5a94ae914fb1898ea5f534 --- Makefile.in | 6 +- auth-chall.c | 125 ------------ auth-rh-rsa.c | 109 ----------- auth-rhosts.c | 23 +-- auth-rsa.c | 349 --------------------------------- auth.c | 10 +- auth.h | 19 +- auth1.c | 444 ------------------------------------------ monitor.c | 305 ++--------------------------- monitor_wrap.c | 151 +-------------- monitor_wrap.h | 13 +- serverloop.c | 596 +++------------------------------------------------------ serverloop.h | 3 +- session.c | 212 ++------------------ session.h | 3 +- sshd.c | 479 ++-------------------------------------------- 16 files changed, 84 insertions(+), 2763 deletions(-) delete mode 100644 auth-chall.c delete mode 100644 auth-rh-rsa.c delete mode 100644 auth-rsa.c delete mode 100644 auth1.c diff --git a/Makefile.in b/Makefile.in index 12991cd9f..62fdb09f6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -97,11 +97,11 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ sshconnect.o sshconnect1.o sshconnect2.o mux.o -SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ +SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ audit.o audit-bsm.o audit-linux.o platform.o \ sshpty.o sshlogin.o servconf.o serverloop.o \ - auth.o auth1.o auth2.o auth-options.o session.o \ - auth-chall.o auth2-chall.o groupaccess.o \ + auth.o auth2.o auth-options.o session.o \ + auth2-chall.o groupaccess.o \ auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ auth2-none.o auth2-passwd.o auth2-pubkey.o \ monitor_mm.o monitor.o monitor_wrap.o auth-krb5.o \ diff --git a/auth-chall.c b/auth-chall.c deleted file mode 100644 index 60c9f14ca..000000000 --- a/auth-chall.c +++ /dev/null @@ -1,125 +0,0 @@ -/* $OpenBSD: auth-chall.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */ -/* - * Copyright (c) 2001 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" - -#include -#include -#include -#include - -#include "xmalloc.h" -#include "key.h" -#include "hostfile.h" -#include "auth.h" -#include "log.h" -#include "misc.h" -#include "servconf.h" - -/* limited protocol v1 interface to kbd-interactive authentication */ - -extern KbdintDevice *devices[]; -static KbdintDevice *device; -extern ServerOptions options; - -char * -get_challenge(Authctxt *authctxt) -{ - char *challenge, *name, *info, **prompts; - u_int i, numprompts; - u_int *echo_on; - -#ifdef USE_PAM - if (!options.use_pam) - remove_kbdint_device("pam"); -#endif - - device = devices[0]; /* we always use the 1st device for protocol 1 */ - if (device == NULL) - return NULL; - if ((authctxt->kbdintctxt = device->init_ctx(authctxt)) == NULL) - return NULL; - if (device->query(authctxt->kbdintctxt, &name, &info, - &numprompts, &prompts, &echo_on)) { - device->free_ctx(authctxt->kbdintctxt); - authctxt->kbdintctxt = NULL; - return NULL; - } - if (numprompts < 1) - fatal("get_challenge: numprompts < 1"); - challenge = xstrdup(prompts[0]); - for (i = 0; i < numprompts; i++) - free(prompts[i]); - free(prompts); - free(name); - free(echo_on); - free(info); - - return (challenge); -} -int -verify_response(Authctxt *authctxt, const char *response) -{ - char *resp[1], *name, *info, **prompts; - u_int i, numprompts, *echo_on; - int authenticated = 0; - - if (device == NULL) - return 0; - if (authctxt->kbdintctxt == NULL) - return 0; - resp[0] = (char *)response; - switch (device->respond(authctxt->kbdintctxt, 1, resp)) { - case 0: /* Success */ - authenticated = 1; - break; - case 1: /* Postponed - retry with empty query for PAM */ - if ((device->query(authctxt->kbdintctxt, &name, &info, - &numprompts, &prompts, &echo_on)) != 0) - break; - if (numprompts == 0 && - device->respond(authctxt->kbdintctxt, 0, resp) == 0) - authenticated = 1; - - for (i = 0; i < numprompts; i++) - free(prompts[i]); - free(prompts); - free(name); - free(echo_on); - free(info); - break; - } - device->free_ctx(authctxt->kbdintctxt); - authctxt->kbdintctxt = NULL; - return authenticated; -} -void -abandon_challenge_response(Authctxt *authctxt) -{ - if (authctxt->kbdintctxt != NULL) { - device->free_ctx(authctxt->kbdintctxt); - authctxt->kbdintctxt = NULL; - } -} diff --git a/auth-rh-rsa.c b/auth-rh-rsa.c deleted file mode 100644 index 057335ba4..000000000 --- a/auth-rh-rsa.c +++ /dev/null @@ -1,109 +0,0 @@ -/* $OpenBSD: auth-rh-rsa.c,v 1.45 2016/03/07 19:02:43 djm Exp $ */ -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * Rhosts or /etc/hosts.equiv authentication combined with RSA host - * authentication. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" - -#ifdef WITH_SSH1 - -#include - -#include -#include - -#include "packet.h" -#include "uidswap.h" -#include "log.h" -#include "buffer.h" -#include "misc.h" -#include "servconf.h" -#include "key.h" -#include "hostfile.h" -#include "pathnames.h" -#include "auth.h" -#include "canohost.h" -#ifdef GSSAPI -#include "ssh-gss.h" -#endif -#include "monitor_wrap.h" - -/* import */ -extern ServerOptions options; - -int -auth_rhosts_rsa_key_allowed(struct passwd *pw, const char *cuser, - const char *chost, Key *client_host_key) -{ - HostStatus host_status; - - if (auth_key_is_revoked(client_host_key)) - return 0; - - /* Check if we would accept it using rhosts authentication. */ - if (!auth_rhosts(pw, cuser)) - return 0; - - host_status = check_key_in_hostfiles(pw, client_host_key, - chost, _PATH_SSH_SYSTEM_HOSTFILE, - options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE); - - return (host_status == HOST_OK); -} - -/* - * Tries to authenticate the user using the .rhosts file and the host using - * its host key. Returns true if authentication succeeds. - */ -int -auth_rhosts_rsa(Authctxt *authctxt, char *cuser, Key *client_host_key) -{ - struct ssh *ssh = active_state; /* XXX */ - const char *chost; - struct passwd *pw = authctxt->pw; - - debug("Trying rhosts with RSA host authentication for client user %.100s", - cuser); - - if (!authctxt->valid || client_host_key == NULL || - client_host_key->rsa == NULL) - return 0; - - chost = auth_get_canonical_hostname(ssh, options.use_dns); - debug("Rhosts RSA authentication: canonical host %.900s", chost); - - if (!PRIVSEP(auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key))) { - debug("Rhosts with RSA host authentication denied: unknown or invalid host key"); - packet_send_debug("Your host key cannot be verified: unknown or invalid host key."); - return 0; - } - /* A matching host key was found and is known. */ - - /* Perform the challenge-response dialog with the client for the host key. */ - if (!auth_rsa_challenge_dialog(client_host_key)) { - logit("Client on %.800s failed to respond correctly to host authentication.", - chost); - return 0; - } - /* - * We have authenticated the user using .rhosts or /etc/hosts.equiv, - * and the host using RSA. We accept the authentication. - */ - - verbose("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.", - pw->pw_name, cuser, chost); - packet_send_debug("Rhosts with RSA host authentication accepted."); - return 1; -} - -#endif /* WITH_SSH1 */ diff --git a/auth-rhosts.c b/auth-rhosts.c index 0ef344712..ecf956f06 100644 --- a/auth-rhosts.c +++ b/auth-rhosts.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-rhosts.c,v 1.47 2016/03/07 19:02:43 djm Exp $ */ +/* $OpenBSD: auth-rhosts.c,v 1.48 2016/08/13 17:47:41 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -186,20 +186,8 @@ check_rhosts_file(const char *filename, const char *hostname, * true if authentication succeeds. If ignore_rhosts is true, only * /etc/hosts.equiv will be considered (.rhosts and .shosts are ignored). */ - int -auth_rhosts(struct passwd *pw, const char *client_user) -{ - struct ssh *ssh = active_state; /* XXX */ - const char *hostname, *ipaddr; - - hostname = auth_get_canonical_hostname(ssh, options.use_dns); - ipaddr = ssh_remote_ipaddr(ssh); - return auth_rhosts2(pw, client_user, hostname, ipaddr); -} - -static int -auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostname, +auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, const char *ipaddr) { char buf[1024]; @@ -334,10 +322,3 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam restore_uid(); return 0; } - -int -auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, - const char *ipaddr) -{ - return auth_rhosts2_raw(pw, client_user, hostname, ipaddr); -} diff --git a/auth-rsa.c b/auth-rsa.c deleted file mode 100644 index cbd971be1..000000000 --- a/auth-rsa.c +++ /dev/null @@ -1,349 +0,0 @@ -/* $OpenBSD: auth-rsa.c,v 1.90 2015/01/28 22:36:00 djm Exp $ */ -/* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * RSA-based authentication. This code determines whether to admit a login - * based on RSA authentication. This file also contains functions to check - * validity of the host key. - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" - -#ifdef WITH_SSH1 - -#include -#include - -#include - -#include -#include -#include -#include - -#include "xmalloc.h" -#include "rsa.h" -#include "packet.h" -#include "ssh1.h" -#include "uidswap.h" -#include "match.h" -#include "buffer.h" -#include "pathnames.h" -#include "log.h" -#include "misc.h" -#include "servconf.h" -#include "key.h" -#include "auth-options.h" -#include "hostfile.h" -#include "auth.h" -#ifdef GSSAPI -#include "ssh-gss.h" -#endif -#include "monitor_wrap.h" -#include "ssh.h" - -#include "digest.h" - -/* import */ -extern ServerOptions options; - -/* - * Session identifier that is used to bind key exchange and authentication - * responses to a particular session. - */ -extern u_char session_id[16]; - -/* - * The .ssh/authorized_keys file contains public keys, one per line, in the - * following format: - * options bits e n comment - * where bits, e and n are decimal numbers, - * and comment is any string of characters up to newline. The maximum - * length of a line is SSH_MAX_PUBKEY_BYTES characters. See sshd(8) for a - * description of the options. - */ - -BIGNUM * -auth_rsa_generate_challenge(Key *key) -{ - BIGNUM *challenge; - BN_CTX *ctx; - - if ((challenge = BN_new()) == NULL) - fatal("auth_rsa_generate_challenge: BN_new() failed"); - /* Generate a random challenge. */ - if (BN_rand(challenge, 256, 0, 0) == 0) - fatal("auth_rsa_generate_challenge: BN_rand failed"); - if ((ctx = BN_CTX_new()) == NULL) - fatal("auth_rsa_generate_challenge: BN_CTX_new failed"); - if (BN_mod(challenge, challenge, key->rsa->n, ctx) == 0) - fatal("auth_rsa_generate_challenge: BN_mod failed"); - BN_CTX_free(ctx); - - return challenge; -} - -int -auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16]) -{ - u_char buf[32], mdbuf[16]; - struct ssh_digest_ctx *md; - int len; - - /* don't allow short keys */ - if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { - error("%s: RSA modulus too small: %d < minimum %d bits", - __func__, - BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); - return (0); - } - - /* The response is MD5 of decrypted challenge plus session id. */ - len = BN_num_bytes(challenge); - if (len <= 0 || len > 32) - fatal("%s: bad challenge length %d", __func__, len); - memset(buf, 0, 32); - BN_bn2bin(challenge, buf + 32 - len); - if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || - ssh_digest_update(md, buf, 32) < 0 || - ssh_digest_update(md, session_id, 16) < 0 || - ssh_digest_final(md, mdbuf, sizeof(mdbuf)) < 0) - fatal("%s: md5 failed", __func__); - ssh_digest_free(md); - - /* Verify that the response is the original challenge. */ - if (timingsafe_bcmp(response, mdbuf, 16) != 0) { - /* Wrong answer. */ - return (0); - } - /* Correct answer. */ - return (1); -} - -/* - * Performs the RSA authentication challenge-response dialog with the client, - * and returns true (non-zero) if the client gave the correct answer to - * our challenge; returns zero if the client gives a wrong answer. - */ - -int -auth_rsa_challenge_dialog(Key *key) -{ - BIGNUM *challenge, *encrypted_challenge; - u_char response[16]; - int i, success; - - if ((encrypted_challenge = BN_new()) == NULL) - fatal("auth_rsa_challenge_dialog: BN_new() failed"); - - challenge = PRIVSEP(auth_rsa_generate_challenge(key)); - - /* Encrypt the challenge with the public key. */ - if (rsa_public_encrypt(encrypted_challenge, challenge, key->rsa) != 0) - fatal("%s: rsa_public_encrypt failed", __func__); - - /* Send the encrypted challenge to the client. */ - packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE); - packet_put_bignum(encrypted_challenge); - packet_send(); - BN_clear_free(encrypted_challenge); - packet_write_wait(); - - /* Wait for a response. */ - packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE); - for (i = 0; i < 16; i++) - response[i] = (u_char)packet_get_char(); - packet_check_eom(); - - success = PRIVSEP(auth_rsa_verify_response(key, challenge, response)); - BN_clear_free(challenge); - return (success); -} - -static int -rsa_key_allowed_in_file(struct passwd *pw, char *file, - const BIGNUM *client_n, Key **rkey) -{ - char *fp, line[SSH_MAX_PUBKEY_BYTES]; - int allowed = 0, bits; - FILE *f; - u_long linenum = 0; - Key *key; - - debug("trying public RSA key file %s", file); - if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL) - return 0; - - /* - * Go though the accepted keys, looking for the current key. If - * found, perform a challenge-response dialog to verify that the - * user really has the corresponding private key. - */ - key = key_new(KEY_RSA1); - while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { - char *cp; - char *key_options; - int keybits; - - /* Skip leading whitespace, empty and comment lines. */ - for (cp = line; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '\n' || *cp == '#') - continue; - - /* - * Check if there are options for this key, and if so, - * save their starting address and skip the option part - * for now. If there are no options, set the starting - * address to NULL. - */ - if (*cp < '0' || *cp > '9') { - int quoted = 0; - key_options = cp; - for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { - if (*cp == '\\' && cp[1] == '"') - cp++; /* Skip both */ - else if (*cp == '"') - quoted = !quoted; - } - } else - key_options = NULL; - - /* Parse the key from the line. */ - if (hostfile_read_key(&cp, &bits, key) == 0) { - debug("%.100s, line %lu: non ssh1 key syntax", - file, linenum); - continue; - } - /* cp now points to the comment part. */ - - /* - * Check if the we have found the desired key (identified - * by its modulus). - */ - if (BN_cmp(key->rsa->n, client_n) != 0) - continue; - - /* check the real bits */ - keybits = BN_num_bits(key->rsa->n); - if (keybits < 0 || bits != keybits) - logit("Warning: %s, line %lu: keysize mismatch: " - "actual %d vs. announced %d.", - file, linenum, BN_num_bits(key->rsa->n), bits); - - if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, - SSH_FP_DEFAULT)) == NULL) - continue; - debug("matching key found: file %s, line %lu %s %s", - file, linenum, key_type(key), fp); - free(fp); - - /* Never accept a revoked key */ - if (auth_key_is_revoked(key)) - break; - - /* We have found the desired key. */ - /* - * If our options do not allow this key to be used, - * do not send challenge. - */ - if (!auth_parse_options(pw, key_options, file, linenum)) - continue; - if (key_is_cert_authority) - continue; - /* break out, this key is allowed */ - allowed = 1; - break; - } - - /* Close the file. */ - fclose(f); - - /* return key if allowed */ - if (allowed && rkey != NULL) - *rkey = key; - else - key_free(key); - - return allowed; -} - -/* - * check if there's user key matching client_n, - * return key if login is allowed, NULL otherwise - */ - -int -auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) -{ - char *file; - u_int i, allowed = 0; - - temporarily_use_uid(pw); - - for (i = 0; !allowed && i < options.num_authkeys_files; i++) { - if (strcasecmp(options.authorized_keys_files[i], "none") == 0) - continue; - file = expand_authorized_keys( - options.authorized_keys_files[i], pw); - allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey); - free(file); - } - - restore_uid(); - - return allowed; -} - -/* - * Performs the RSA authentication dialog with the client. This returns - * 0 if the client could not be authenticated, and 1 if authentication was - * successful. This may exit if there is a serious protocol violation. - */ -int -auth_rsa(Authctxt *authctxt, BIGNUM *client_n) -{ - Key *key; - struct passwd *pw = authctxt->pw; - - /* no user given */ - if (!authctxt->valid) - return 0; - - if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) { - auth_clear_options(); - return (0); - } - - /* Perform the challenge-response dialog for this key. */ - if (!auth_rsa_challenge_dialog(key)) { - /* Wrong response. */ - verbose("Wrong response to RSA authentication challenge."); - packet_send_debug("Wrong response to RSA authentication challenge."); - /* - * Break out of the loop. Otherwise we might send - * another challenge and break the protocol. - */ - key_free(key); - return (0); - } - /* - * Correct response. The client has been successfully - * authenticated. Note that we have not yet processed the - * options; this will be reset if the options cause the - * authentication to be rejected. - */ - pubkey_auth_info(authctxt, key, NULL); - - packet_send_debug("RSA authentication accepted."); - return (1); -} - -#endif /* WITH_SSH1 */ diff --git a/auth.c b/auth.c index 24527dd7c..b6a440213 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.115 2016/06/15 00:40:40 dtucker Exp $ */ +/* $OpenBSD: auth.c,v 1.116 2016/08/13 17:47:41 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -298,7 +298,7 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, else authmsg = authenticated ? "Accepted" : "Failed"; - authlog("%s %s%s%s for %s%.100s from %.200s port %d %s%s%s", + authlog("%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s", authmsg, method, submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod, @@ -306,7 +306,6 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, authctxt->user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), - compat20 ? "ssh2" : "ssh1", authctxt->info != NULL ? ": " : "", authctxt->info != NULL ? authctxt->info : ""); free(authctxt->info); @@ -339,12 +338,11 @@ auth_maxtries_exceeded(Authctxt *authctxt) struct ssh *ssh = active_state; /* XXX */ error("maximum authentication attempts exceeded for " - "%s%.100s from %.200s port %d %s", + "%s%.100s from %.200s port %d ssh2", authctxt->valid ? "" : "invalid user ", authctxt->user, ssh_remote_ipaddr(ssh), - ssh_remote_port(ssh), - compat20 ? "ssh2" : "ssh1"); + ssh_remote_port(ssh)); packet_disconnect("Too many authentication failures"); /* NOTREACHED */ } diff --git a/auth.h b/auth.h index 55170af50..338a62da7 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.88 2016/05/04 14:04:40 markus Exp $ */ +/* $OpenBSD: auth.h,v 1.89 2016/08/13 17:47:41 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -112,20 +112,11 @@ struct KbdintDevice void (*free_ctx)(void *ctx); }; -int auth_rhosts(struct passwd *, const char *); int auth_rhosts2(struct passwd *, const char *, const char *, const char *); -int auth_rhosts_rsa(Authctxt *, char *, Key *); int auth_password(Authctxt *, const char *); -int auth_rsa(Authctxt *, BIGNUM *); -int auth_rsa_challenge_dialog(Key *); -BIGNUM *auth_rsa_generate_challenge(Key *); -int auth_rsa_verify_response(Key *, BIGNUM *, u_char[]); -int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); - -int auth_rhosts_rsa_key_allowed(struct passwd *, const char *, - const char *, Key *); + int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); int user_key_allowed(struct passwd *, Key *, int); void pubkey_auth_info(Authctxt *, const Key *, const char *, ...) @@ -156,7 +147,6 @@ void remove_kbdint_device(const char *); void disable_forwarding(void); -void do_authentication(Authctxt *); void do_authentication2(Authctxt *); void auth_info(Authctxt *authctxt, const char *, ...) @@ -187,10 +177,6 @@ int skey_respond(void *, u_int, char **); int allowed_user(struct passwd *); struct passwd * getpwnamallow(const char *user); -char *get_challenge(Authctxt *); -int verify_response(Authctxt *, const char *); -void abandon_challenge_response(Authctxt *); - char *expand_authorized_keys(const char *, struct passwd *pw); char *authorized_principals_file(struct passwd *); @@ -210,7 +196,6 @@ Key *get_hostkey_public_by_index(int, struct ssh *); Key *get_hostkey_public_by_type(int, int, struct ssh *); Key *get_hostkey_private_by_type(int, int, struct ssh *); int get_hostkey_index(Key *, int, struct ssh *); -int ssh1_session_key(BIGNUM *); int sshd_hostkey_sign(Key *, Key *, u_char **, size_t *, const u_char *, size_t, const char *, u_int); diff --git a/auth1.c b/auth1.c deleted file mode 100644 index 5073c49bb..000000000 --- a/auth1.c +++ /dev/null @@ -1,444 +0,0 @@ -/* $OpenBSD: auth1.c,v 1.82 2014/07/15 15:54:14 millert Exp $ */ -/* - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved - * - * As far as I am concerned, the code I have written for this software - * can be used freely for any purpose. Any derived versions of this - * software must be clearly marked as such, and if the derived work is - * incompatible with the protocol description in the RFC file, it must be - * called by a name other than "ssh" or "Secure Shell". - */ - -#include "includes.h" - -#ifdef WITH_SSH1 - -#include - -#include -#include -#include -#include -#include - -#include "openbsd-compat/sys-queue.h" -#include "xmalloc.h" -#include "rsa.h" -#include "ssh1.h" -#include "packet.h" -#include "buffer.h" -#include "log.h" -#include "misc.h" -#include "servconf.h" -#include "compat.h" -#include "key.h" -#include "hostfile.h" -#include "auth.h" -#include "channels.h" -#include "session.h" -#include "uidswap.h" -#ifdef GSSAPI -#include "ssh-gss.h" -#endif -#include "monitor_wrap.h" -#include "buffer.h" - -/* import */ -extern ServerOptions options; -extern Buffer loginmsg; - -static int auth1_process_password(Authctxt *); -static int auth1_process_rsa(Authctxt *); -static int auth1_process_rhosts_rsa(Authctxt *); -static int auth1_process_tis_challenge(Authctxt *); -static int auth1_process_tis_response(Authctxt *); - -static char *client_user = NULL; /* Used to fill in remote user for PAM */ - -struct AuthMethod1 { - int type; - char *name; - int *enabled; - int (*method)(Authctxt *); -}; - -const struct AuthMethod1 auth1_methods[] = { - { - SSH_CMSG_AUTH_PASSWORD, "password", - &options.password_authentication, auth1_process_password - }, - { - SSH_CMSG_AUTH_RSA, "rsa", - &options.rsa_authentication, auth1_process_rsa - }, - { - SSH_CMSG_AUTH_RHOSTS_RSA, "rhosts-rsa", - &options.rhosts_rsa_authentication, auth1_process_rhosts_rsa - }, - { - SSH_CMSG_AUTH_TIS, "challenge-response", - &options.challenge_response_authentication, - auth1_process_tis_challenge - }, - { - SSH_CMSG_AUTH_TIS_RESPONSE, "challenge-response", - &options.challenge_response_authentication, - auth1_process_tis_response - }, - { -1, NULL, NULL, NULL} -}; - -static const struct AuthMethod1 -*lookup_authmethod1(int type) -{ - int i; - - for (i = 0; auth1_methods[i].name != NULL; i++) - if (auth1_methods[i].type == type) - return (&(auth1_methods[i])); - - return (NULL); -} - -static char * -get_authname(int type) -{ - const struct AuthMethod1 *a; - static char buf[64]; - - if ((a = lookup_authmethod1(type)) != NULL) - return (a->name); - snprintf(buf, sizeof(buf), "bad-auth-msg-%d", type); - return (buf); -} - -/*ARGSUSED*/ -static int -auth1_process_password(Authctxt *authctxt) -{ - int authenticated = 0; - char *password; - u_int dlen; - - /* - * Read user password. It is in plain text, but was - * transmitted over the encrypted channel so it is - * not visible to an outside observer. - */ - password = packet_get_string(&dlen); - packet_check_eom(); - - /* Try authentication with the password. */ - authenticated = PRIVSEP(auth_password(authctxt, password)); - - explicit_bzero(password, dlen); - free(password); - - return (authenticated); -} - -/*ARGSUSED*/ -static int -auth1_process_rsa(Authctxt *authctxt) -{ - int authenticated = 0; - BIGNUM *n; - - /* RSA authentication requested. */ - if ((n = BN_new()) == NULL) - fatal("do_authloop: BN_new failed"); - packet_get_bignum(n); - packet_check_eom(); - authenticated = auth_rsa(authctxt, n); - BN_clear_free(n); - - return (authenticated); -} - -/*ARGSUSED*/ -static int -auth1_process_rhosts_rsa(Authctxt *authctxt) -{ - int keybits, authenticated = 0; - u_int bits; - Key *client_host_key; - u_int ulen; - - /* - * Get client user name. Note that we just have to - * trust the client; root on the client machine can - * claim to be any user. - */ - client_user = packet_get_cstring(&ulen); - - /* Get the client host key. */ - client_host_key = key_new(KEY_RSA1); - bits = packet_get_int(); - packet_get_bignum(client_host_key->rsa->e); - packet_get_bignum(client_host_key->rsa->n); - - keybits = BN_num_bits(client_host_key->rsa->n); - if (keybits < 0 || bits != (u_int)keybits) { - verbose("Warning: keysize mismatch for client_host_key: " - "actual %d, announced %d", - BN_num_bits(client_host_key->rsa->n), bits); - } - packet_check_eom(); - - authenticated = auth_rhosts_rsa(authctxt, client_user, - client_host_key); - key_free(client_host_key); - - auth_info(authctxt, "ruser %.100s", client_user); - - return (authenticated); -} - -/*ARGSUSED*/ -static int -auth1_process_tis_challenge(Authctxt *authctxt) -{ - char *challenge; - - if ((challenge = get_challenge(authctxt)) == NULL) - return (0); - - debug("sending challenge '%s'", challenge); - packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE); - packet_put_cstring(challenge); - free(challenge); - packet_send(); - packet_write_wait(); - - return (-1); -} - -/*ARGSUSED*/ -static int -auth1_process_tis_response(Authctxt *authctxt) -{ - int authenticated = 0; - char *response; - u_int dlen; - - response = packet_get_string(&dlen); - packet_check_eom(); - authenticated = verify_response(authctxt, response); - explicit_bzero(response, dlen); - free(response); - - return (authenticated); -} - -/* - * read packets, try to authenticate the user and - * return only if authentication is successful - */ -static void -do_authloop(Authctxt *authctxt) -{ - int authenticated = 0; - int prev = 0, type = 0; - const struct AuthMethod1 *meth; - - debug("Attempting authentication for %s%.100s.", - authctxt->valid ? "" : "invalid user ", authctxt->user); - - /* If the user has no password, accept authentication immediately. */ - if (options.permit_empty_passwd && options.password_authentication && -#ifdef KRB5 - (!options.kerberos_authentication || options.kerberos_or_local_passwd) && -#endif - PRIVSEP(auth_password(authctxt, ""))) { -#ifdef USE_PAM - if (options.use_pam && (PRIVSEP(do_pam_account()))) -#endif - { - auth_log(authctxt, 1, 0, "without authentication", - NULL); - return; - } - } - - /* Indicate that authentication is needed. */ - packet_start(SSH_SMSG_FAILURE); - packet_send(); - packet_write_wait(); - - for (;;) { - /* default to fail */ - authenticated = 0; - - - /* Get a packet from the client. */ - prev = type; - type = packet_read(); - - /* - * If we started challenge-response authentication but the - * next packet is not a response to our challenge, release - * the resources allocated by get_challenge() (which would - * normally have been released by verify_response() had we - * received such a response) - */ - if (prev == SSH_CMSG_AUTH_TIS && - type != SSH_CMSG_AUTH_TIS_RESPONSE) - abandon_challenge_response(authctxt); - - if (authctxt->failures >= options.max_authtries) - goto skip; - if ((meth = lookup_authmethod1(type)) == NULL) { - logit("Unknown message during authentication: " - "type %d", type); - goto skip; - } - - if (!*(meth->enabled)) { - verbose("%s authentication disabled.", meth->name); - goto skip; - } - - authenticated = meth->method(authctxt); - if (authenticated == -1) - continue; /* "postponed" */ - -#ifdef BSD_AUTH - if (authctxt->as) { - auth_close(authctxt->as); - authctxt->as = NULL; - } -#endif - if (!authctxt->valid && authenticated) - fatal("INTERNAL ERROR: authenticated invalid user %s", - authctxt->user); - -#ifdef _UNICOS - if (authenticated && cray_access_denied(authctxt->user)) { - authenticated = 0; - fatal("Access denied for user %s.",authctxt->user); - } -#endif /* _UNICOS */ - -#ifndef HAVE_CYGWIN - /* Special handling for root */ - if (authenticated && authctxt->pw->pw_uid == 0 && - !auth_root_allowed(meth->name)) { - authenticated = 0; -# ifdef SSH_AUDIT_EVENTS - PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED)); -# endif - } -#endif - -#ifdef USE_PAM - if (options.use_pam && authenticated && - !PRIVSEP(do_pam_account())) { - char *msg; - size_t len; - - error("Access denied for user %s by PAM account " - "configuration", authctxt->user); - len = buffer_len(&loginmsg); - buffer_append(&loginmsg, "\0", 1); - msg = buffer_ptr(&loginmsg); - /* strip trailing newlines */ - if (len > 0) - while (len > 0 && msg[--len] == '\n') - msg[len] = '\0'; - else - msg = "Access denied."; - packet_disconnect("%s", msg); - } -#endif - - skip: - /* Log before sending the reply */ - auth_log(authctxt, authenticated, 0, get_authname(type), NULL); - - free(client_user); - client_user = NULL; - - if (authenticated) - return; - - if (++authctxt->failures >= options.max_authtries) { -#ifdef SSH_AUDIT_EVENTS - PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); -#endif - auth_maxtries_exceeded(authctxt); - } - - packet_start(SSH_SMSG_FAILURE); - packet_send(); - packet_write_wait(); - } -} - -/* - * Performs authentication of an incoming connection. Session key has already - * been exchanged and encryption is enabled. - */ -void -do_authentication(Authctxt *authctxt) -{ - u_int ulen; - char *user, *style = NULL; - - /* Get the name of the user that we wish to log in as. */ - packet_read_expect(SSH_CMSG_USER); - - /* Get the user name. */ - user = packet_get_cstring(&ulen); - packet_check_eom(); - - if ((style = strchr(user, ':')) != NULL) - *style++ = '\0'; - - authctxt->user = user; - authctxt->style = style; - - /* Verify that the user is a valid user. */ - if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) - authctxt->valid = 1; - else { - debug("do_authentication: invalid user %s", user); - authctxt->pw = fakepw(); - } - - /* Configuration may have changed as a result of Match */ - if (options.num_auth_methods != 0) - fatal("AuthenticationMethods is not supported with SSH " - "protocol 1"); - - setproctitle("%s%s", authctxt->valid ? user : "unknown", - use_privsep ? " [net]" : ""); - -#ifdef USE_PAM - if (options.use_pam) - PRIVSEP(start_pam(authctxt)); -#endif - - /* - * If we are not running as root, the user must have the same uid as - * the server. - */ -#ifndef HAVE_CYGWIN - if (!use_privsep && getuid() != 0 && authctxt->pw && - authctxt->pw->pw_uid != getuid()) - packet_disconnect("Cannot change user when server not running as root."); -#endif - - /* - * Loop until the user has been authenticated or the connection is - * closed, do_authloop() returns only if authentication is successful - */ - do_authloop(authctxt); - - /* The user has been authenticated and accepted. */ - packet_start(SSH_SMSG_SUCCESS); - packet_send(); - packet_write_wait(); -} - -#endif /* WITH_SSH1 */ diff --git a/monitor.c b/monitor.c index cb57bd066..59b05a98f 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.161 2016/07/22 03:39:13 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.162 2016/08/13 17:47:41 markus Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -169,10 +169,6 @@ static int monitor_read_log(struct monitor *); static Authctxt *authctxt; -#ifdef WITH_SSH1 -static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ -#endif - /* local state for key verify */ static u_char *key_blob = NULL; static u_int key_bloblen = 0; @@ -254,52 +250,6 @@ struct mon_table mon_dispatch_postauth20[] = { {0, 0, NULL} }; -struct mon_table mon_dispatch_proto15[] = { -#ifdef WITH_SSH1 - {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, - {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, - {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, - {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, - {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_rsa_keyallowed}, - {MONITOR_REQ_KEYALLOWED, MON_ISAUTH|MON_ALOG, mm_answer_keyallowed}, - {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge}, - {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response}, -#ifdef BSD_AUTH - {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, - {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond}, -#endif -#ifdef SKEY - {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, - {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, -#endif -#ifdef USE_PAM - {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, - {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, - {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, - {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, - {MONITOR_REQ_PAM_RESPOND, MON_ISAUTH, mm_answer_pam_respond}, - {MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx}, -#endif -#ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, -#endif -#endif /* WITH_SSH1 */ - {0, 0, NULL} -}; - -struct mon_table mon_dispatch_postauth15[] = { -#ifdef WITH_SSH1 - {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, - {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, - {MONITOR_REQ_TERM, 0, mm_answer_term}, -#ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, - {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, -#endif -#endif /* WITH_SSH1 */ - {0, 0, NULL} -}; - struct mon_table *mon_dispatch; /* Specifies if a certain message is allowed at the moment */ @@ -348,17 +298,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) authctxt->loginmsg = &loginmsg; - if (compat20) { - mon_dispatch = mon_dispatch_proto20; - - /* Permit requests for moduli and signatures */ - monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); - } else { - mon_dispatch = mon_dispatch_proto15; - - monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); - } + mon_dispatch = mon_dispatch_proto20; + /* Permit requests for moduli and signatures */ + monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); /* The first few requests do not require asynchronous access */ while (!authenticated) { @@ -369,9 +312,6 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) /* Special handling for multiple required authentications */ if (options.num_auth_methods != 0) { - if (!compat20) - fatal("AuthenticationMethods is not supported" - "with SSH protocol 1"); if (authenticated && !auth2_update_methods_lists(authctxt, auth_method, auth_submethod)) { @@ -455,17 +395,13 @@ monitor_child_postauth(struct monitor *pmonitor) signal(SIGXFSZ, SIG_IGN); #endif - if (compat20) { - mon_dispatch = mon_dispatch_postauth20; + mon_dispatch = mon_dispatch_postauth20; + + /* Permit requests for moduli and signatures */ + monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); - /* Permit requests for moduli and signatures */ - monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); - } else { - mon_dispatch = mon_dispatch_postauth15; - monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); - } if (!no_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); @@ -845,7 +781,7 @@ mm_answer_pwnamallow(int sock, Buffer *m) #undef M_CP_STRARRAYOPT /* Create valid auth method lists */ - if (compat20 && auth2_setup_methods_lists(authctxt) != 0) { + if (auth2_setup_methods_lists(authctxt) != 0) { /* * The monitor will continue long enough to let the child * run to it's packet_disconnect(), but it must not allow any @@ -857,14 +793,10 @@ mm_answer_pwnamallow(int sock, Buffer *m) debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); mm_request_send(sock, MONITOR_ANS_PWNAM, m); - /* For SSHv1 allow authentication now */ - if (!compat20) - monitor_permit_authentications(1); - else { - /* Allow service/style information on the auth context */ - monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); - } + /* Allow service/style information on the auth context */ + monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); + #ifdef USE_PAM if (options.use_pam) monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1); @@ -991,11 +923,8 @@ mm_answer_bsdauthrespond(int sock, Buffer *m) debug3("%s: sending authenticated: %d", __func__, authok); mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); - if (compat20) { - auth_method = "keyboard-interactive"; - auth_submethod = "bsdauth"; - } else - auth_method = "bsdauth"; + auth_method = "keyboard-interactive"; + auth_submethod = "bsdauth"; return (authok != 0); } @@ -1205,10 +1134,6 @@ mm_answer_keyallowed(int sock, Buffer *m) key = key_from_blob(blob, bloblen); - if ((compat20 && type == MM_RSAHOSTKEY) || - (!compat20 && type != MM_RSAHOSTKEY)) - fatal("%s: key type and protocol mismatch", __func__); - debug3("%s: key_from_blob: %p", __func__, key); if (key != NULL && authctxt->valid) { @@ -1242,17 +1167,6 @@ mm_answer_keyallowed(int sock, Buffer *m) cuser, chost); auth_method = "hostbased"; break; -#ifdef WITH_SSH1 - case MM_RSAHOSTKEY: - key->type = KEY_RSA1; /* XXX */ - allowed = options.rhosts_rsa_authentication && - auth_rhosts_rsa_key_allowed(authctxt->pw, - cuser, chost, key); - if (options.rhosts_rsa_authentication && allowed != 1) - auth_clear_options(); - auth_method = "rsa"; - break; -#endif default: fatal("%s: unknown key type %d", __func__, type); break; @@ -1289,9 +1203,6 @@ mm_answer_keyallowed(int sock, Buffer *m) mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); - if (type == MM_RSAHOSTKEY) - monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); - return (0); } @@ -1600,186 +1511,6 @@ mm_answer_pty_cleanup(int sock, Buffer *m) return (0); } -#ifdef WITH_SSH1 -int -mm_answer_sesskey(int sock, Buffer *m) -{ - BIGNUM *p; - int rsafail; - - /* Turn off permissions */ - monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 0); - - if ((p = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - - buffer_get_bignum2(m, p); - - rsafail = ssh1_session_key(p); - - buffer_clear(m); - buffer_put_int(m, rsafail); - buffer_put_bignum2(m, p); - - BN_clear_free(p); - - mm_request_send(sock, MONITOR_ANS_SESSKEY, m); - - /* Turn on permissions for sessid passing */ - monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1); - - return (0); -} - -int -mm_answer_sessid(int sock, Buffer *m) -{ - int i; - - debug3("%s entering", __func__); - - if (buffer_len(m) != 16) - fatal("%s: bad ssh1 session id", __func__); - for (i = 0; i < 16; i++) - session_id[i] = buffer_get_char(m); - - /* Turn on permissions for getpwnam */ - monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); - - return (0); -} - -int -mm_answer_rsa_keyallowed(int sock, Buffer *m) -{ - BIGNUM *client_n; - Key *key = NULL; - u_char *blob = NULL; - u_int blen = 0; - int allowed = 0; - - debug3("%s entering", __func__); - - auth_method = "rsa"; - if (options.rsa_authentication && authctxt->valid) { - if ((client_n = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - buffer_get_bignum2(m, client_n); - allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key); - BN_clear_free(client_n); - } - buffer_clear(m); - buffer_put_int(m, allowed); - buffer_put_int(m, forced_command != NULL); - - /* clear temporarily storage (used by generate challenge) */ - monitor_reset_key_state(); - - if (allowed && key != NULL) { - key->type = KEY_RSA; /* cheat for key_to_blob */ - if (key_to_blob(key, &blob, &blen) == 0) - fatal("%s: key_to_blob failed", __func__); - buffer_put_string(m, blob, blen); - - /* Save temporarily for comparison in verify */ - key_blob = blob; - key_bloblen = blen; - key_blobtype = MM_RSAUSERKEY; - } - if (key != NULL) - key_free(key); - - mm_request_send(sock, MONITOR_ANS_RSAKEYALLOWED, m); - - monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); - monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0); - return (0); -} - -int -mm_answer_rsa_challenge(int sock, Buffer *m) -{ - Key *key = NULL; - u_char *blob; - u_int blen; - - debug3("%s entering", __func__); - - if (!authctxt->valid) - fatal("%s: authctxt not valid", __func__); - blob = buffer_get_string(m, &blen); - if (!monitor_allowed_key(blob, blen)) - fatal("%s: bad key, not previously allowed", __func__); - if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) - fatal("%s: key type mismatch", __func__); - if ((key = key_from_blob(blob, blen)) == NULL) - fatal("%s: received bad key", __func__); - if (key->type != KEY_RSA) - fatal("%s: received bad key type %d", __func__, key->type); - key->type = KEY_RSA1; - if (ssh1_challenge) - BN_clear_free(ssh1_challenge); - ssh1_challenge = auth_rsa_generate_challenge(key); - - buffer_clear(m); - buffer_put_bignum2(m, ssh1_challenge); - - debug3("%s sending reply", __func__); - mm_request_send(sock, MONITOR_ANS_RSACHALLENGE, m); - - monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1); - - free(blob); - key_free(key); - return (0); -} - -int -mm_answer_rsa_response(int sock, Buffer *m) -{ - Key *key = NULL; - u_char *blob, *response; - u_int blen, len; - int success; - - debug3("%s entering", __func__); - - if (!authctxt->valid) - fatal("%s: authctxt not valid", __func__); - if (ssh1_challenge == NULL) - fatal("%s: no ssh1_challenge", __func__); - - blob = buffer_get_string(m, &blen); - if (!monitor_allowed_key(blob, blen)) - fatal("%s: bad key, not previously allowed", __func__); - if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) - fatal("%s: key type mismatch: %d", __func__, key_blobtype); - if ((key = key_from_blob(blob, blen)) == NULL) - fatal("%s: received bad key", __func__); - response = buffer_get_string(m, &len); - if (len != 16) - fatal("%s: received bad response to challenge", __func__); - success = auth_rsa_verify_response(key, ssh1_challenge, response); - - free(blob); - key_free(key); - free(response); - - auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; - - /* reset state */ - BN_clear_free(ssh1_challenge); - ssh1_challenge = NULL; - monitor_reset_key_state(); - - buffer_clear(m); - buffer_put_int(m, success); - mm_request_send(sock, MONITOR_ANS_RSARESPONSE, m); - - return (success); -} -#endif - int mm_answer_term(int sock, Buffer *req) { diff --git a/monitor_wrap.c b/monitor_wrap.c index 99dc13b61..64ff92885 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.88 2016/03/07 19:02:43 djm Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.89 2016/08/13 17:47:41 markus Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -85,7 +85,6 @@ #include "ssherr.h" /* Imports */ -extern int compat20; extern z_stream incoming_stream; extern z_stream outgoing_stream; extern struct monitor *pmonitor; @@ -388,18 +387,6 @@ mm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host, return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0)); } -int -mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, const char *user, - const char *host, Key *key) -{ - int ret; - - key->type = KEY_RSA; /* XXX hack for key_to_blob */ - ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key, 0); - key->type = KEY_RSA1; - return (ret); -} - int mm_key_allowed(enum mm_keytype type, const char *user, const char *host, Key *key, int pubkey_auth_attempt) @@ -710,28 +697,6 @@ mm_terminate(void) buffer_free(&m); } -#ifdef WITH_SSH1 -int -mm_ssh1_session_key(BIGNUM *num) -{ - int rsafail; - Buffer m; - - buffer_init(&m); - buffer_put_bignum2(&m, num); - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m); - - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m); - - rsafail = buffer_get_int(&m); - buffer_get_bignum2(&m, num); - - buffer_free(&m); - - return (rsafail); -} -#endif - static void mm_chall_setup(char **name, char **infotxt, u_int *numprompts, char ***prompts, u_int **echo_on) @@ -862,120 +827,6 @@ mm_skey_respond(void *ctx, u_int numresponses, char **responses) } #endif /* SKEY */ -void -mm_ssh1_session_id(u_char session_id[16]) -{ - Buffer m; - int i; - - debug3("%s entering", __func__); - - buffer_init(&m); - for (i = 0; i < 16; i++) - buffer_put_char(&m, session_id[i]); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m); - buffer_free(&m); -} - -#ifdef WITH_SSH1 -int -mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) -{ - Buffer m; - Key *key; - u_char *blob; - u_int blen; - int allowed = 0, have_forced = 0; - - debug3("%s entering", __func__); - - buffer_init(&m); - buffer_put_bignum2(&m, client_n); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m); - - allowed = buffer_get_int(&m); - - /* fake forced command */ - auth_clear_options(); - have_forced = buffer_get_int(&m); - forced_command = have_forced ? xstrdup("true") : NULL; - - if (allowed && rkey != NULL) { - blob = buffer_get_string(&m, &blen); - if ((key = key_from_blob(blob, blen)) == NULL) - fatal("%s: key_from_blob failed", __func__); - *rkey = key; - free(blob); - } - buffer_free(&m); - - return (allowed); -} - -BIGNUM * -mm_auth_rsa_generate_challenge(Key *key) -{ - Buffer m; - BIGNUM *challenge; - u_char *blob; - u_int blen; - - debug3("%s entering", __func__); - - if ((challenge = BN_new()) == NULL) - fatal("%s: BN_new failed", __func__); - - key->type = KEY_RSA; /* XXX cheat for key_to_blob */ - if (key_to_blob(key, &blob, &blen) == 0) - fatal("%s: key_to_blob failed", __func__); - key->type = KEY_RSA1; - - buffer_init(&m); - buffer_put_string(&m, blob, blen); - free(blob); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m); - - buffer_get_bignum2(&m, challenge); - buffer_free(&m); - - return (challenge); -} - -int -mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16]) -{ - Buffer m; - u_char *blob; - u_int blen; - int success = 0; - - debug3("%s entering", __func__); - - key->type = KEY_RSA; /* XXX cheat for key_to_blob */ - if (key_to_blob(key, &blob, &blen) == 0) - fatal("%s: key_to_blob failed", __func__); - key->type = KEY_RSA1; - - buffer_init(&m); - buffer_put_string(&m, blob, blen); - buffer_put_string(&m, response, 16); - free(blob); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m); - - success = buffer_get_int(&m); - buffer_free(&m); - - return (success); -} -#endif - #ifdef SSH_AUDIT_EVENTS void mm_audit_event(ssh_audit_event_t event) diff --git a/monitor_wrap.h b/monitor_wrap.h index 9fd02b30c..1bc76afff 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.30 2016/03/07 19:02:43 djm Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.31 2016/08/13 17:47:41 markus Exp $ */ /* * Copyright 2002 Niels Provos @@ -31,7 +31,7 @@ extern int use_privsep; #define PRIVSEP(x) (use_privsep ? mm_##x : x) -enum mm_keytype {MM_NOKEY, MM_HOSTKEY, MM_USERKEY, MM_RSAHOSTKEY, MM_RSAUSERKEY}; +enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY }; struct monitor; struct mm_master; @@ -49,12 +49,7 @@ int mm_key_allowed(enum mm_keytype, const char *, const char *, Key *, int); int mm_user_key_allowed(struct passwd *, Key *, int); int mm_hostbased_key_allowed(struct passwd *, const char *, const char *, Key *); -int mm_auth_rhosts_rsa_key_allowed(struct passwd *, const char *, - const char *, Key *); int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int); -int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); -int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *); -BIGNUM *mm_auth_rsa_generate_challenge(Key *); #ifdef GSSAPI OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); @@ -84,10 +79,6 @@ void mm_terminate(void); int mm_pty_allocate(int *, int *, char *, size_t); void mm_session_pty_cleanup2(struct Session *); -/* SSHv1 interfaces */ -void mm_ssh1_session_id(u_char *); -int mm_ssh1_session_key(BIGNUM *); - /* Key export functions */ struct newkeys *mm_newkeys_from_blob(u_char *, int); int mm_newkeys_to_blob(int, u_char **, u_int *); diff --git a/serverloop.c b/serverloop.c index 3563e5d42..1e211701e 100644 --- a/serverloop.c +++ b/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.184 2016/03/07 19:02:43 djm Exp $ */ +/* $OpenBSD: serverloop.c,v 1.185 2016/08/13 17:47:41 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -67,7 +67,6 @@ #include "sshpty.h" #include "channels.h" #include "compat.h" -#include "ssh1.h" #include "ssh2.h" #include "key.h" #include "cipher.h" @@ -86,25 +85,6 @@ extern ServerOptions options; extern Authctxt *the_authctxt; extern int use_privsep; -static Buffer stdin_buffer; /* Buffer for stdin data. */ -static Buffer stdout_buffer; /* Buffer for stdout data. */ -static Buffer stderr_buffer; /* Buffer for stderr data. */ -static int fdin; /* Descriptor for stdin (for writing) */ -static int fdout; /* Descriptor for stdout (for reading); - May be same number as fdin. */ -static int fderr; /* Descriptor for stderr. May be -1. */ -static long stdin_bytes = 0; /* Number of bytes written to stdin. */ -static long stdout_bytes = 0; /* Number of stdout bytes sent to client. */ -static long stderr_bytes = 0; /* Number of stderr bytes sent to client. */ -static long fdout_bytes = 0; /* Number of stdout bytes read from program. */ -static int stdin_eof = 0; /* EOF message received from client. */ -static int fdout_eof = 0; /* EOF encountered reading from fdout. */ -static int fderr_eof = 0; /* EOF encountered readung from fderr. */ -static int fdin_is_tty = 0; /* fdin points to a tty. */ -static int connection_in; /* Connection to client (input). */ -static int connection_out; /* Connection to client (output). */ -static int connection_closed = 0; /* Connection to client closed. */ -static u_int buffer_high; /* "Soft" max buffer size. */ static int no_more_sessions = 0; /* Disallow further sessions. */ /* @@ -185,64 +165,6 @@ sigterm_handler(int sig) received_sigterm = sig; } -/* - * Make packets from buffered stderr data, and buffer it for sending - * to the client. - */ -static void -make_packets_from_stderr_data(void) -{ - u_int len; - - /* Send buffered stderr data to the client. */ - while (buffer_len(&stderr_buffer) > 0 && - packet_not_very_much_data_to_write()) { - len = buffer_len(&stderr_buffer); - if (packet_is_interactive()) { - if (len > 512) - len = 512; - } else { - /* Keep the packets at reasonable size. */ - if (len > packet_get_maxsize()) - len = packet_get_maxsize(); - } - packet_start(SSH_SMSG_STDERR_DATA); - packet_put_string(buffer_ptr(&stderr_buffer), len); - packet_send(); - buffer_consume(&stderr_buffer, len); - stderr_bytes += len; - } -} - -/* - * Make packets from buffered stdout data, and buffer it for sending to the - * client. - */ -static void -make_packets_from_stdout_data(void) -{ - u_int len; - - /* Send buffered stdout data to the client. */ - while (buffer_len(&stdout_buffer) > 0 && - packet_not_very_much_data_to_write()) { - len = buffer_len(&stdout_buffer); - if (packet_is_interactive()) { - if (len > 512) - len = 512; - } else { - /* Keep the packets at reasonable size. */ - if (len > packet_get_maxsize()) - len = packet_get_maxsize(); - } - packet_start(SSH_SMSG_STDOUT_DATA); - packet_put_string(buffer_ptr(&stdout_buffer), len); - packet_send(); - buffer_consume(&stdout_buffer, len); - stdout_bytes += len; - } -} - static void client_alive_check(void) { @@ -275,14 +197,14 @@ client_alive_check(void) * for the duration of the wait (0 = infinite). */ static void -wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, +wait_until_can_do_something(int connection_in, int connection_out, + fd_set **readsetp, fd_set **writesetp, int *maxfdp, u_int *nallocp, u_int64_t max_time_ms) { struct timeval tv, *tvp; int ret; time_t minwait_secs = 0; int client_alive_scheduled = 0; - int program_alive_scheduled = 0; /* Allocate and update select() masks for channel descriptors. */ channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, @@ -300,7 +222,7 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, * this could be randomized somewhat to make traffic * analysis more difficult, but we're not doing it yet. */ - if (compat20 && options.client_alive_interval) { + if (options.client_alive_interval) { uint64_t keepalive_ms = (uint64_t)options.client_alive_interval * 1000; @@ -309,38 +231,11 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, max_time_ms = keepalive_ms; } - if (compat20) { #if 0 - /* wrong: bad condition XXX */ - if (channel_not_very_much_buffered_data()) + /* wrong: bad condition XXX */ + if (channel_not_very_much_buffered_data()) #endif - FD_SET(connection_in, *readsetp); - } else { - /* - * Read packets from the client unless we have too much - * buffered stdin or channel data. - */ - if (buffer_len(&stdin_buffer) < buffer_high && - channel_not_very_much_buffered_data()) - FD_SET(connection_in, *readsetp); - /* - * If there is not too much data already buffered going to - * the client, try to get some more data from the program. - */ - if (packet_not_very_much_data_to_write()) { - program_alive_scheduled = child_terminated; - if (!fdout_eof) - FD_SET(fdout, *readsetp); - if (!fderr_eof) - FD_SET(fderr, *readsetp); - } - /* - * If we have buffered data, try to write some of that data - * to the program. - */ - if (fdin != -1 && buffer_len(&stdin_buffer) > 0) - FD_SET(fdin, *writesetp); - } + FD_SET(connection_in, *readsetp); notify_prepare(*readsetp); /* @@ -374,16 +269,8 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, memset(*writesetp, 0, *nallocp); if (errno != EINTR) error("select: %.100s", strerror(errno)); - } else { - if (ret == 0 && client_alive_scheduled) - client_alive_check(); - if (!compat20 && program_alive_scheduled && fdin_is_tty) { - if (!fdout_eof) - FD_SET(fdout, *readsetp); - if (!fderr_eof) - FD_SET(fderr, *readsetp); - } - } + } else if (ret == 0 && client_alive_scheduled) + client_alive_check(); notify_done(*readsetp); } @@ -392,8 +279,8 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, * Processes input from the client and the program. Input data is stored * in buffers and processed later. */ -static void -process_input(fd_set *readset) +static int +process_input(fd_set *readset, int connection_in) { struct ssh *ssh = active_state; /* XXX */ int len; @@ -405,10 +292,7 @@ process_input(fd_set *readset) if (len == 0) { verbose("Connection closed by %.100s port %d", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); - connection_closed = 1; - if (compat20) - return; - cleanup_exit(255); + return -1; } else if (len < 0) { if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) { @@ -423,381 +307,26 @@ process_input(fd_set *readset) packet_process_incoming(buf, len); } } - if (compat20) - return; - - /* Read and buffer any available stdout data from the program. */ - if (!fdout_eof && FD_ISSET(fdout, readset)) { - errno = 0; - len = read(fdout, buf, sizeof(buf)); - if (len < 0 && (errno == EINTR || ((errno == EAGAIN || - errno == EWOULDBLOCK) && !child_terminated))) { - /* do nothing */ -#ifndef PTY_ZEROREAD - } else if (len <= 0) { -#else - } else if ((!isatty(fdout) && len <= 0) || - (isatty(fdout) && (len < 0 || (len == 0 && errno != 0)))) { -#endif - fdout_eof = 1; - } else { - buffer_append(&stdout_buffer, buf, len); - fdout_bytes += len; - } - } - /* Read and buffer any available stderr data from the program. */ - if (!fderr_eof && FD_ISSET(fderr, readset)) { - errno = 0; - len = read(fderr, buf, sizeof(buf)); - if (len < 0 && (errno == EINTR || ((errno == EAGAIN || - errno == EWOULDBLOCK) && !child_terminated))) { - /* do nothing */ -#ifndef PTY_ZEROREAD - } else if (len <= 0) { -#else - } else if ((!isatty(fderr) && len <= 0) || - (isatty(fderr) && (len < 0 || (len == 0 && errno != 0)))) { -#endif - fderr_eof = 1; - } else { - buffer_append(&stderr_buffer, buf, len); - } - } + return 0; } /* * Sends data from internal buffers to client program stdin. */ static void -process_output(fd_set *writeset) +process_output(fd_set *writeset, int connection_out) { - struct termios tio; - u_char *data; - u_int dlen; - int len; - - /* Write buffered data to program stdin. */ - if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) { - data = buffer_ptr(&stdin_buffer); - dlen = buffer_len(&stdin_buffer); - len = write(fdin, data, dlen); - if (len < 0 && - (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) { - /* do nothing */ - } else if (len <= 0) { - if (fdin != fdout) - close(fdin); - else - shutdown(fdin, SHUT_WR); /* We will no longer send. */ - fdin = -1; - } else { - /* Successful write. */ - if (fdin_is_tty && dlen >= 1 && data[0] != '\r' && - tcgetattr(fdin, &tio) == 0 && - !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { - /* - * Simulate echo to reduce the impact of - * traffic analysis - */ - packet_send_ignore(len); - packet_send(); - } - /* Consume the data from the buffer. */ - buffer_consume(&stdin_buffer, len); - /* Update the count of bytes written to the program. */ - stdin_bytes += len; - } - } /* Send any buffered packet data to the client. */ if (FD_ISSET(connection_out, writeset)) packet_write_poll(); } -/* - * Wait until all buffered output has been sent to the client. - * This is used when the program terminates. - */ -static void -drain_output(void) -{ - /* Send any buffered stdout data to the client. */ - if (buffer_len(&stdout_buffer) > 0) { - packet_start(SSH_SMSG_STDOUT_DATA); - packet_put_string(buffer_ptr(&stdout_buffer), - buffer_len(&stdout_buffer)); - packet_send(); - /* Update the count of sent bytes. */ - stdout_bytes += buffer_len(&stdout_buffer); - } - /* Send any buffered stderr data to the client. */ - if (buffer_len(&stderr_buffer) > 0) { - packet_start(SSH_SMSG_STDERR_DATA); - packet_put_string(buffer_ptr(&stderr_buffer), - buffer_len(&stderr_buffer)); - packet_send(); - /* Update the count of sent bytes. */ - stderr_bytes += buffer_len(&stderr_buffer); - } - /* Wait until all buffered data has been written to the client. */ - packet_write_wait(); -} - static void process_buffered_input_packets(void) { dispatch_run(DISPATCH_NONBLOCK, NULL, active_state); } -/* - * Performs the interactive session. This handles data transmission between - * the client and the program. Note that the notion of stdin, stdout, and - * stderr in this function is sort of reversed: this function writes to - * stdin (of the child program), and reads from stdout and stderr (of the - * child program). - */ -void -server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) -{ - fd_set *readset = NULL, *writeset = NULL; - int max_fd = 0; - u_int nalloc = 0; - int wait_status; /* Status returned by wait(). */ - pid_t wait_pid; /* pid returned by wait(). */ - int waiting_termination = 0; /* Have displayed waiting close message. */ - u_int64_t max_time_milliseconds; - u_int previous_stdout_buffer_bytes; - u_int stdout_buffer_bytes; - int type; - - debug("Entering interactive session."); - - /* Initialize the SIGCHLD kludge. */ - child_terminated = 0; - mysignal(SIGCHLD, sigchld_handler); - - if (!use_privsep) { - signal(SIGTERM, sigterm_handler); - signal(SIGINT, sigterm_handler); - signal(SIGQUIT, sigterm_handler); - } - - /* Initialize our global variables. */ - fdin = fdin_arg; - fdout = fdout_arg; - fderr = fderr_arg; - - /* nonblocking IO */ - set_nonblock(fdin); - set_nonblock(fdout); - /* we don't have stderr for interactive terminal sessions, see below */ - if (fderr != -1) - set_nonblock(fderr); - - if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin)) - fdin_is_tty = 1; - - connection_in = packet_get_connection_in(); - connection_out = packet_get_connection_out(); - - notify_setup(); - - previous_stdout_buffer_bytes = 0; - - /* Set approximate I/O buffer size. */ - if (packet_is_interactive()) - buffer_high = 4096; - else - buffer_high = 64 * 1024; - -#if 0 - /* Initialize max_fd to the maximum of the known file descriptors. */ - max_fd = MAX(connection_in, connection_out); - max_fd = MAX(max_fd, fdin); - max_fd = MAX(max_fd, fdout); - if (fderr != -1) - max_fd = MAX(max_fd, fderr); -#endif - - /* Initialize Initialize buffers. */ - buffer_init(&stdin_buffer); - buffer_init(&stdout_buffer); - buffer_init(&stderr_buffer); - - /* - * If we have no separate fderr (which is the case when we have a pty - * - there we cannot make difference between data sent to stdout and - * stderr), indicate that we have seen an EOF from stderr. This way - * we don't need to check the descriptor everywhere. - */ - if (fderr == -1) - fderr_eof = 1; - - server_init_dispatch(); - - /* Main loop of the server for the interactive session mode. */ - for (;;) { - - /* Process buffered packets from the client. */ - process_buffered_input_packets(); - - /* - * If we have received eof, and there is no more pending - * input data, cause a real eof by closing fdin. - */ - if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) { - if (fdin != fdout) - close(fdin); - else - shutdown(fdin, SHUT_WR); /* We will no longer send. */ - fdin = -1; - } - /* Make packets from buffered stderr data to send to the client. */ - make_packets_from_stderr_data(); - - /* - * Make packets from buffered stdout data to send to the - * client. If there is very little to send, this arranges to - * not send them now, but to wait a short while to see if we - * are getting more data. This is necessary, as some systems - * wake up readers from a pty after each separate character. - */ - max_time_milliseconds = 0; - stdout_buffer_bytes = buffer_len(&stdout_buffer); - if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 && - stdout_buffer_bytes != previous_stdout_buffer_bytes) { - /* try again after a while */ - max_time_milliseconds = 10; - } else { - /* Send it now. */ - make_packets_from_stdout_data(); - } - previous_stdout_buffer_bytes = buffer_len(&stdout_buffer); - - /* Send channel data to the client. */ - if (packet_not_very_much_data_to_write()) - channel_output_poll(); - - /* - * Bail out of the loop if the program has closed its output - * descriptors, and we have no more data to send to the - * client, and there is no pending buffered data. - */ - if (fdout_eof && fderr_eof && !packet_have_data_to_write() && - buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) { - if (!channel_still_open()) - break; - if (!waiting_termination) { - const char *s = "Waiting for forwarded connections to terminate...\r\n"; - char *cp; - waiting_termination = 1; - buffer_append(&stderr_buffer, s, strlen(s)); - - /* Display list of open channels. */ - cp = channel_open_message(); - buffer_append(&stderr_buffer, cp, strlen(cp)); - free(cp); - } - } - max_fd = MAX(connection_in, connection_out); - max_fd = MAX(max_fd, fdin); - max_fd = MAX(max_fd, fdout); - max_fd = MAX(max_fd, fderr); - max_fd = MAX(max_fd, notify_pipe[0]); - - /* Sleep in select() until we can do something. */ - wait_until_can_do_something(&readset, &writeset, &max_fd, - &nalloc, max_time_milliseconds); - - if (received_sigterm) { - logit("Exiting on signal %d", (int)received_sigterm); - /* Clean up sessions, utmp, etc. */ - cleanup_exit(255); - } - - /* Process any channel events. */ - channel_after_select(readset, writeset); - - /* Process input from the client and from program stdout/stderr. */ - process_input(readset); - - /* Process output to the client and to program stdin. */ - process_output(writeset); - } - free(readset); - free(writeset); - - /* Cleanup and termination code. */ - - /* Wait until all output has been sent to the client. */ - drain_output(); - - debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.", - stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes); - - /* Free and clear the buffers. */ - buffer_free(&stdin_buffer); - buffer_free(&stdout_buffer); - buffer_free(&stderr_buffer); - - /* Close the file descriptors. */ - if (fdout != -1) - close(fdout); - fdout = -1; - fdout_eof = 1; - if (fderr != -1) - close(fderr); - fderr = -1; - fderr_eof = 1; - if (fdin != -1) - close(fdin); - fdin = -1; - - channel_free_all(); - - /* We no longer want our SIGCHLD handler to be called. */ - mysignal(SIGCHLD, SIG_DFL); - - while ((wait_pid = waitpid(-1, &wait_status, 0)) < 0) - if (errno != EINTR) - packet_disconnect("wait: %.100s", strerror(errno)); - if (wait_pid != pid) - error("Strange, wait returned pid %ld, expected %ld", - (long)wait_pid, (long)pid); - - /* Check if it exited normally. */ - if (WIFEXITED(wait_status)) { - /* Yes, normal exit. Get exit status and send it to the client. */ - debug("Command exited with status %d.", WEXITSTATUS(wait_status)); - packet_start(SSH_SMSG_EXITSTATUS); - packet_put_int(WEXITSTATUS(wait_status)); - packet_send(); - packet_write_wait(); - - /* - * Wait for exit confirmation. Note that there might be - * other packets coming before it; however, the program has - * already died so we just ignore them. The client is - * supposed to respond with the confirmation when it receives - * the exit status. - */ - do { - type = packet_read(); - } - while (type != SSH_CMSG_EXIT_CONFIRMATION); - - debug("Received exit confirmation."); - return; - } - /* Check if the program terminated due to a signal. */ - if (WIFSIGNALED(wait_status)) - packet_disconnect("Command terminated on signal %d.", - WTERMSIG(wait_status)); - - /* Some weird exit cause. Just exit. */ - packet_disconnect("wait returned status %04x.", wait_status); - /* NOTREACHED */ -} - static void collect_children(void) { @@ -825,7 +354,7 @@ server_loop2(Authctxt *authctxt) { fd_set *readset = NULL, *writeset = NULL; int max_fd; - u_int nalloc = 0; + u_int nalloc = 0, connection_in, connection_out; u_int64_t rekey_timeout_ms = 0; debug("Entering interactive session for SSH2."); @@ -854,14 +383,14 @@ server_loop2(Authctxt *authctxt) if (!ssh_packet_is_rekeying(active_state) && packet_not_very_much_data_to_write()) channel_output_poll(); - if (options.rekey_interval > 0 && compat20 && + if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(active_state)) rekey_timeout_ms = packet_get_rekey_timeout() * 1000; else rekey_timeout_ms = 0; - wait_until_can_do_something(&readset, &writeset, &max_fd, - &nalloc, rekey_timeout_ms); + wait_until_can_do_something(connection_in, connection_out, + &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms); if (received_sigterm) { logit("Exiting on signal %d", (int)received_sigterm); @@ -872,10 +401,9 @@ server_loop2(Authctxt *authctxt) collect_children(); if (!ssh_packet_is_rekeying(active_state)) channel_after_select(readset, writeset); - process_input(readset); - if (connection_closed) + if (process_input(readset, connection_in) < 0) break; - process_output(writeset); + process_output(writeset, connection_out); } collect_children(); @@ -902,53 +430,6 @@ server_input_keep_alive(int type, u_int32_t seq, void *ctxt) return 0; } -static int -server_input_stdin_data(int type, u_int32_t seq, void *ctxt) -{ - char *data; - u_int data_len; - - /* Stdin data from the client. Append it to the buffer. */ - /* Ignore any data if the client has closed stdin. */ - if (fdin == -1) - return 0; - data = packet_get_string(&data_len); - packet_check_eom(); - buffer_append(&stdin_buffer, data, data_len); - explicit_bzero(data, data_len); - free(data); - return 0; -} - -static int -server_input_eof(int type, u_int32_t seq, void *ctxt) -{ - /* - * Eof from the client. The stdin descriptor to the - * program will be closed when all buffered data has - * drained. - */ - debug("EOF received for stdin."); - packet_check_eom(); - stdin_eof = 1; - return 0; -} - -static int -server_input_window_size(int type, u_int32_t seq, void *ctxt) -{ - u_int row = packet_get_int(); - u_int col = packet_get_int(); - u_int xpixel = packet_get_int(); - u_int ypixel = packet_get_int(); - - debug("Window change received."); - packet_check_eom(); - if (fdin != -1) - pty_change_window_size(fdin, row, col, xpixel, ypixel); - return 0; -} - static Channel * server_request_direct_tcpip(void) { @@ -1353,9 +834,9 @@ server_input_channel_req(int type, u_int32_t seq, void *ctxt) } static void -server_init_dispatch_20(void) +server_init_dispatch(void) { - debug("server_init_dispatch_20"); + debug("server_init_dispatch"); dispatch_init(&dispatch_protocol_error); dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose); dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data); @@ -1375,36 +856,3 @@ server_init_dispatch_20(void) /* rekeying */ dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); } -static void -server_init_dispatch_13(void) -{ - debug("server_init_dispatch_13"); - dispatch_init(NULL); - dispatch_set(SSH_CMSG_EOF, &server_input_eof); - dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data); - dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size); - dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close); - dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation); - dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data); - dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); - dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); - dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open); -} -static void -server_init_dispatch_15(void) -{ - server_init_dispatch_13(); - debug("server_init_dispatch_15"); - dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof); - dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose); -} -static void -server_init_dispatch(void) -{ - if (compat20) - server_init_dispatch_20(); - else if (compat13) - server_init_dispatch_13(); - else - server_init_dispatch_15(); -} diff --git a/serverloop.h b/serverloop.h index 7311558f9..d5fbda16f 100644 --- a/serverloop.h +++ b/serverloop.h @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.h,v 1.6 2006/03/25 22:22:43 djm Exp $ */ +/* $OpenBSD: serverloop.h,v 1.7 2016/08/13 17:47:41 markus Exp $ */ /* * Author: Tatu Ylonen @@ -21,7 +21,6 @@ #ifndef SERVERLOOP_H #define SERVERLOOP_H -void server_loop(pid_t, int, int, int); void server_loop2(Authctxt *); #endif diff --git a/session.c b/session.c index 2235f26ac..9bad653fc 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.282 2016/03/10 11:47:57 djm Exp $ */ +/* $OpenBSD: session.c,v 1.283 2016/08/13 17:47:41 markus Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -66,7 +66,6 @@ #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" -#include "ssh1.h" #include "ssh2.h" #include "sshpty.h" #include "packet.h" @@ -128,7 +127,6 @@ void do_child(Session *, const char *); void do_motd(void); int check_quietlogin(Session *, const char *); -static void do_authenticated1(Authctxt *); static void do_authenticated2(Authctxt *); static int session_pty_req(Session *); @@ -267,11 +265,7 @@ do_authenticated(Authctxt *authctxt) auth_debug_send(); - if (compat20) - do_authenticated2(authctxt); - else - do_authenticated1(authctxt); - + do_authenticated2(authctxt); do_cleanup(authctxt); } @@ -290,164 +284,6 @@ xauth_valid_string(const char *s) return 1; } -/* - * Prepares for an interactive session. This is called after the user has - * been successfully authenticated. During this message exchange, pseudo - * terminals are allocated, X11, TCP/IP, and authentication agent forwardings - * are requested, etc. - */ -static void -do_authenticated1(Authctxt *authctxt) -{ - Session *s; - char *command; - int success, type, screen_flag; - int enable_compression_after_reply = 0; - u_int proto_len, data_len, dlen, compression_level = 0; - - s = session_new(); - if (s == NULL) { - error("no more sessions"); - return; - } - s->authctxt = authctxt; - s->pw = authctxt->pw; - - /* - * We stay in this loop until the client requests to execute a shell - * or a command. - */ - for (;;) { - success = 0; - - /* Get a packet from the client. */ - type = packet_read(); - - /* Process the packet. */ - switch (type) { - case SSH_CMSG_REQUEST_COMPRESSION: - compression_level = packet_get_int(); - packet_check_eom(); - if (compression_level < 1 || compression_level > 9) { - packet_send_debug("Received invalid compression level %d.", - compression_level); - break; - } - if (options.compression == COMP_NONE) { - debug2("compression disabled"); - break; - } - /* Enable compression after we have responded with SUCCESS. */ - enable_compression_after_reply = 1; - success = 1; - break; - - case SSH_CMSG_REQUEST_PTY: - success = session_pty_req(s); - break; - - case SSH_CMSG_X11_REQUEST_FORWARDING: - s->auth_proto = packet_get_string(&proto_len); - s->auth_data = packet_get_string(&data_len); - - screen_flag = packet_get_protocol_flags() & - SSH_PROTOFLAG_SCREEN_NUMBER; - debug2("SSH_PROTOFLAG_SCREEN_NUMBER: %d", screen_flag); - - if (packet_remaining() == 4) { - if (!screen_flag) - debug2("Buggy client: " - "X11 screen flag missing"); - s->screen = packet_get_int(); - } else { - s->screen = 0; - } - packet_check_eom(); - if (xauth_valid_string(s->auth_proto) && - xauth_valid_string(s->auth_data)) - success = session_setup_x11fwd(s); - else { - success = 0; - error("Invalid X11 forwarding data"); - } - if (!success) { - free(s->auth_proto); - free(s->auth_data); - s->auth_proto = NULL; - s->auth_data = NULL; - } - break; - - case SSH_CMSG_AGENT_REQUEST_FORWARDING: - if (!options.allow_agent_forwarding || - no_agent_forwarding_flag || compat13) { - debug("Authentication agent forwarding not permitted for this authentication."); - break; - } - debug("Received authentication agent forwarding request."); - success = auth_input_request_forwarding(s->pw); - break; - - case SSH_CMSG_PORT_FORWARD_REQUEST: - if (no_port_forwarding_flag) { - debug("Port forwarding not permitted for this authentication."); - break; - } - if (!(options.allow_tcp_forwarding & FORWARD_REMOTE)) { - debug("Port forwarding not permitted."); - break; - } - debug("Received TCP/IP port forwarding request."); - if (channel_input_port_forward_request(s->pw->pw_uid == 0, - &options.fwd_opts) < 0) { - debug("Port forwarding failed."); - break; - } - success = 1; - break; - - case SSH_CMSG_MAX_PACKET_SIZE: - if (packet_set_maxsize(packet_get_int()) > 0) - success = 1; - break; - - case SSH_CMSG_EXEC_SHELL: - case SSH_CMSG_EXEC_CMD: - if (type == SSH_CMSG_EXEC_CMD) { - command = packet_get_string(&dlen); - debug("Exec command '%.500s'", command); - if (do_exec(s, command) != 0) - packet_disconnect( - "command execution failed"); - free(command); - } else { - if (do_exec(s, NULL) != 0) - packet_disconnect( - "shell execution failed"); - } - packet_check_eom(); - session_close(s); - return; - - default: - /* - * Any unknown messages in this phase are ignored, - * and a failure message is returned. - */ - logit("Unknown packet type received after authentication: %d", type); - } - packet_start(success ? SSH_SMSG_SUCCESS : SSH_SMSG_FAILURE); - packet_send(); - packet_write_wait(); - - /* Enable compression now that we have replied if appropriate. */ - if (enable_compression_after_reply) { - enable_compression_after_reply = 0; - packet_start_compression(compression_level); - } - } -} - #define USE_PIPES 1 /* * This is called to fork and execute a command when we have no tty. This @@ -615,14 +451,8 @@ do_exec_no_pty(Session *s, const char *command) close(pout[1]); close(perr[1]); - if (compat20) { - session_set_fds(s, pin[1], pout[0], perr[0], - s->is_subsystem, 0); - } else { - /* Enter the interactive session. */ - server_loop(pid, pin[1], pout[0], perr[0]); - /* server_loop has closed pin[1], pout[0], and perr[0]. */ - } + session_set_fds(s, pin[1], pout[0], perr[0], + s->is_subsystem, 0); #else /* We are the parent. Close the child sides of the socket pairs. */ close(inout[0]); @@ -632,13 +462,8 @@ do_exec_no_pty(Session *s, const char *command) * Enter the interactive session. Note: server_loop must be able to * handle the case that fdin and fdout are the same. */ - if (compat20) { - session_set_fds(s, inout[1], inout[1], err[1], - s->is_subsystem, 0); - } else { - server_loop(pid, inout[1], inout[1], err[1]); - /* server_loop has closed inout[1] and err[1]. */ - } + session_set_fds(s, inout[1], inout[1], err[1], + s->is_subsystem, 0); #endif return 0; } @@ -756,12 +581,7 @@ do_exec_pty(Session *s, const char *command) s->ptymaster = ptymaster; packet_set_interactive(1, options.ip_qos_interactive, options.ip_qos_bulk); - if (compat20) { - session_set_fds(s, ptyfd, fdout, -1, 1, 1); - } else { - server_loop(pid, ptyfd, fdout, -1); - /* server_loop _has_ closed ptyfd and fdout. */ - } + session_set_fds(s, ptyfd, fdout, -1, 1, 1); return 0; } @@ -2106,14 +1926,8 @@ session_pty_req(Session *s) } s->term = packet_get_string(&len); - - if (compat20) { - s->col = packet_get_int(); - s->row = packet_get_int(); - } else { - s->row = packet_get_int(); - s->col = packet_get_int(); - } + s->col = packet_get_int(); + s->row = packet_get_int(); s->xpixel = packet_get_int(); s->ypixel = packet_get_int(); @@ -2135,9 +1949,7 @@ session_pty_req(Session *s) } debug("session_pty_req: session %d alloc %s", s->self, s->tty); - /* for SSH1 the tty modes length is not given */ - if (!compat20) - n_bytes = packet_remaining(); + n_bytes = packet_remaining(); tty_parse_modes(s->ttyfd, &n_bytes); if (!use_privsep) @@ -2353,8 +2165,6 @@ void session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr, int is_tty) { - if (!compat20) - fatal("session_set_fds: called for proto != 2.0"); /* * now that have a child and a pipe to the child, * we can activate our channel and register the fd's @@ -2794,7 +2604,7 @@ do_cleanup(Authctxt *authctxt) #endif #ifdef GSSAPI - if (compat20 && options.gss_cleanup_creds) + if (options.gss_cleanup_creds) ssh_gssapi_cleanup_creds(); #endif diff --git a/session.h b/session.h index f18eaf329..98e1dafee 100644 --- a/session.h +++ b/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.32 2016/03/07 19:02:43 djm Exp $ */ +/* $OpenBSD: session.h,v 1.33 2016/08/13 17:47:41 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -51,7 +51,6 @@ struct Session { char *auth_data; int single_connection; - /* proto 2 */ int chanid; int *x11_chanids; int is_subsystem; diff --git a/sshd.c b/sshd.c index 9fc829a91..b50ea1d99 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.471 2016/08/03 04:23:55 dtucker Exp $ */ +/* $OpenBSD: sshd.c,v 1.472 2016/08/13 17:47:41 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -87,7 +87,6 @@ #include "xmalloc.h" #include "ssh.h" -#include "ssh1.h" #include "ssh2.h" #include "rsa.h" #include "sshpty.h" @@ -201,22 +200,12 @@ int have_agent = 0; * not very useful. Currently, memory locking is not implemented. */ struct { - Key *server_key; /* ephemeral server key */ - Key *ssh1_host_key; /* ssh1 host key */ Key **host_keys; /* all private host keys */ Key **host_pubkeys; /* all public host keys */ Key **host_certificates; /* all public host certificates */ - int have_ssh1_key; int have_ssh2_key; - u_char ssh1_cookie[SSH_SESSION_KEY_LENGTH]; } sensitive_data; -/* - * Flag indicating whether the RSA server key needs to be regenerated. - * Is set in the SIGALRM handler and cleared when the key is regenerated. - */ -static volatile sig_atomic_t key_do_regen = 0; - /* This is set to true when a signal is received. */ static volatile sig_atomic_t received_sighup = 0; static volatile sig_atomic_t received_sigterm = 0; @@ -255,10 +244,6 @@ struct passwd *privsep_pw = NULL; /* Prototypes for various functions defined later in this file. */ void destroy_sensitive_data(void); void demote_sensitive_data(void); - -#ifdef WITH_SSH1 -static void do_ssh1_kex(void); -#endif static void do_ssh2_kex(void); /* @@ -375,43 +360,10 @@ grace_alarm_handler(int sig) ssh_remote_ipaddr(active_state), ssh_remote_port(active_state)); } -/* - * Signal handler for the key regeneration alarm. Note that this - * alarm only occurs in the daemon waiting for connections, and it does not - * do anything with the private key or random state before forking. - * Thus there should be no concurrency control/asynchronous execution - * problems. - */ -static void -generate_ephemeral_server_key(void) -{ - verbose("Generating %s%d bit RSA key.", - sensitive_data.server_key ? "new " : "", options.server_key_bits); - if (sensitive_data.server_key != NULL) - key_free(sensitive_data.server_key); - sensitive_data.server_key = key_generate(KEY_RSA1, - options.server_key_bits); - verbose("RSA key generation complete."); - - arc4random_buf(sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH); -} - -/*ARGSUSED*/ -static void -key_regeneration_alarm(int sig) -{ - int save_errno = errno; - - signal(SIGALRM, SIG_DFL); - errno = save_errno; - key_do_regen = 1; -} - static void sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) { u_int i; - int mismatch; int remote_major, remote_minor; int major, minor; char *s, *newline = "\n"; @@ -511,42 +463,13 @@ sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) "refusing connection", remote_version); } - mismatch = 0; - switch (remote_major) { - case 1: - if (remote_minor == 99) { - if (options.protocol & SSH_PROTO_2) - enable_compat20(); - else - mismatch = 1; - break; - } - if (!(options.protocol & SSH_PROTO_1)) { - mismatch = 1; - break; - } - if (remote_minor < 3) { - packet_disconnect("Your ssh version is too old and " - "is no longer supported. Please install a newer version."); - } else if (remote_minor == 3) { - /* note that this disables agent-forwarding */ - enable_compat13(); - } - break; - case 2: - if (options.protocol & SSH_PROTO_2) { - enable_compat20(); - break; - } - /* FALLTHROUGH */ - default: - mismatch = 1; - break; - } chop(server_version_string); debug("Local version string %.200s", server_version_string); - if (mismatch) { + if (remote_major == 2 || + (remote_major == 1 && remote_minor == 99)) { + enable_compat20(); + } else { s = "Protocol major versions differ.\n"; (void) atomicio(vwrite, sock_out, s, strlen(s)); close(sock_in); @@ -565,10 +488,6 @@ destroy_sensitive_data(void) { int i; - if (sensitive_data.server_key) { - key_free(sensitive_data.server_key); - sensitive_data.server_key = NULL; - } for (i = 0; i < options.num_host_key_files; i++) { if (sensitive_data.host_keys[i]) { key_free(sensitive_data.host_keys[i]); @@ -579,8 +498,6 @@ destroy_sensitive_data(void) sensitive_data.host_certificates[i] = NULL; } } - sensitive_data.ssh1_host_key = NULL; - explicit_bzero(sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH); } /* Demote private to public keys for network child */ @@ -590,24 +507,14 @@ demote_sensitive_data(void) Key *tmp; int i; - if (sensitive_data.server_key) { - tmp = key_demote(sensitive_data.server_key); - key_free(sensitive_data.server_key); - sensitive_data.server_key = tmp; - } - for (i = 0; i < options.num_host_key_files; i++) { if (sensitive_data.host_keys[i]) { tmp = key_demote(sensitive_data.host_keys[i]); key_free(sensitive_data.host_keys[i]); sensitive_data.host_keys[i] = tmp; - if (tmp->type == KEY_RSA1) - sensitive_data.ssh1_host_key = tmp; } /* Certs do not need demotion */ } - - /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ } static void @@ -803,7 +710,7 @@ list_hostkey_types(void) key = sensitive_data.host_keys[i]; if (key == NULL) key = sensitive_data.host_pubkeys[i]; - if (key == NULL || key->type == KEY_RSA1) + if (key == NULL) continue; /* Check that the key is accepted in HostkeyAlgorithms */ if (match_pattern_list(sshkey_ssh_name(key), @@ -952,7 +859,7 @@ notify_hostkeys(struct ssh *ssh) for (i = nkeys = 0; i < options.num_host_key_files; i++) { key = get_hostkey_public_by_index(i, ssh); if (key == NULL || key->type == KEY_UNSPEC || - key->type == KEY_RSA1 || sshkey_is_cert(key)) + sshkey_is_cert(key)) continue; fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); @@ -1038,13 +945,6 @@ send_rexec_state(int fd, struct sshbuf *conf) /* * Protocol from reexec master to child: * string configuration - * u_int ephemeral_key_follows - * bignum e (only if ephemeral_key_follows == 1) - * bignum n " - * bignum d " - * bignum iqmp " - * bignum p " - * bignum q " * string rngseed (only if OpenSSL is not self-seeded) */ if ((m = sshbuf_new()) == NULL) @@ -1052,28 +952,6 @@ send_rexec_state(int fd, struct sshbuf *conf) if ((r = sshbuf_put_stringb(m, conf)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); -#ifdef WITH_SSH1 - if (sensitive_data.server_key != NULL && - sensitive_data.server_key->type == KEY_RSA1) { - if ((r = sshbuf_put_u32(m, 1)) != 0 || - (r = sshbuf_put_bignum1(m, - sensitive_data.server_key->rsa->e)) != 0 || - (r = sshbuf_put_bignum1(m, - sensitive_data.server_key->rsa->n)) != 0 || - (r = sshbuf_put_bignum1(m, - sensitive_data.server_key->rsa->d)) != 0 || - (r = sshbuf_put_bignum1(m, - sensitive_data.server_key->rsa->iqmp)) != 0 || - (r = sshbuf_put_bignum1(m, - sensitive_data.server_key->rsa->p)) != 0 || - (r = sshbuf_put_bignum1(m, - sensitive_data.server_key->rsa->q)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - } else -#endif - if ((r = sshbuf_put_u32(m, 0)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - #if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY) rexec_send_rng_seed(m); #endif @@ -1107,24 +985,6 @@ recv_rexec_state(int fd, Buffer *conf) buffer_append(conf, cp, len); free(cp); - if (buffer_get_int(&m)) { -#ifdef WITH_SSH1 - if (sensitive_data.server_key != NULL) - key_free(sensitive_data.server_key); - sensitive_data.server_key = key_new_private(KEY_RSA1); - buffer_get_bignum(&m, sensitive_data.server_key->rsa->e); - buffer_get_bignum(&m, sensitive_data.server_key->rsa->n); - buffer_get_bignum(&m, sensitive_data.server_key->rsa->d); - buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp); - buffer_get_bignum(&m, sensitive_data.server_key->rsa->p); - buffer_get_bignum(&m, sensitive_data.server_key->rsa->q); - if (rsa_generate_additional_parameters( - sensitive_data.server_key->rsa) != 0) - fatal("%s: rsa_generate_additional_parameters " - "error", __func__); -#endif - } - #if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY) rexec_recv_rng_seed(&m); #endif @@ -1248,7 +1108,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) { fd_set *fdset; int i, j, ret, maxfd; - int key_used = 0, startups = 0; + int startups = 0; int startup_p[2] = { -1 , -1 }; struct sockaddr_storage from; socklen_t fromlen; @@ -1295,11 +1155,6 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) unlink(options.pid_file); exit(received_sigterm == SIGTERM ? 0 : 255); } - if (key_used && key_do_regen) { - generate_ephemeral_server_key(); - key_used = 0; - key_do_regen = 0; - } if (ret < 0) continue; @@ -1434,19 +1289,6 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) close(config_s[0]); close(config_s[1]); } - - /* - * Mark that the key has been used (it - * was "given" to the child). - */ - if ((options.protocol & SSH_PROTO_1) && - key_used == 0) { - /* Schedule server key regeneration alarm. */ - signal(SIGALRM, key_regeneration_alarm); - alarm(options.key_regeneration_time); - key_used = 1; - } - close(*newsock); /* @@ -1619,8 +1461,7 @@ main(int ac, char **av) options.log_level = SYSLOG_LEVEL_QUIET; break; case 'b': - options.server_key_bits = (int)strtonum(optarg, 256, - 32768, NULL); + /* ignored */ break; case 'p': options.ports_from_cmdline = 1; @@ -1726,9 +1567,6 @@ main(int ac, char **av) drop_cray_privs(); #endif - sensitive_data.server_key = NULL; - sensitive_data.ssh1_host_key = NULL; - sensitive_data.have_ssh1_key = 0; sensitive_data.have_ssh2_key = 0; /* @@ -1852,8 +1690,7 @@ main(int ac, char **av) sensitive_data.host_keys[i] = key; sensitive_data.host_pubkeys[i] = pubkey; - if (key == NULL && pubkey != NULL && pubkey->type != KEY_RSA1 && - have_agent) { + if (key == NULL && pubkey != NULL && have_agent) { debug("will rely on agent for hostkey %s", options.host_key_files[i]); keytype = pubkey->type; @@ -1868,10 +1705,6 @@ main(int ac, char **av) } switch (keytype) { - case KEY_RSA1: - sensitive_data.ssh1_host_key = key; - sensitive_data.have_ssh1_key = 1; - break; case KEY_RSA: case KEY_DSA: case KEY_ECDSA: @@ -1884,19 +1717,10 @@ main(int ac, char **av) SSH_FP_DEFAULT)) == NULL) fatal("sshkey_fingerprint failed"); debug("%s host key #%d: %s %s", - key ? "private" : "agent", i, keytype == KEY_RSA1 ? - sshkey_type(pubkey) : sshkey_ssh_name(pubkey), fp); + key ? "private" : "agent", i, sshkey_ssh_name(pubkey), fp); free(fp); } - if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { - logit("Disabling protocol version 1. Could not load host key"); - options.protocol &= ~SSH_PROTO_1; - } - if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { - logit("Disabling protocol version 2. Could not load host key"); - options.protocol &= ~SSH_PROTO_2; - } - if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { + if (!sensitive_data.have_ssh2_key) { logit("sshd: no hostkeys available -- exiting."); exit(1); } @@ -1944,33 +1768,6 @@ main(int ac, char **av) key_type(key)); } -#ifdef WITH_SSH1 - /* Check certain values for sanity. */ - if (options.protocol & SSH_PROTO_1) { - if (options.server_key_bits < SSH_RSA_MINIMUM_MODULUS_SIZE || - options.server_key_bits > OPENSSL_RSA_MAX_MODULUS_BITS) { - fprintf(stderr, "Bad server key size.\n"); - exit(1); - } - /* - * Check that server and host key lengths differ sufficiently. This - * is necessary to make double encryption work with rsaref. Oh, I - * hate software patents. I dont know if this can go? Niels - */ - if (options.server_key_bits > - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) - - SSH_KEY_BITS_RESERVED && options.server_key_bits < - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + - SSH_KEY_BITS_RESERVED) { - options.server_key_bits = - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + - SSH_KEY_BITS_RESERVED; - debug("Forcing server key to %d bits to make it differ from host key.", - options.server_key_bits); - } - } -#endif - if (use_privsep) { struct stat st; @@ -2068,9 +1865,6 @@ main(int ac, char **av) platform_pre_listen(); server_listen(); - if (options.protocol & SSH_PROTO_1) - generate_ephemeral_server_key(); - signal(SIGHUP, sighup_handler); signal(SIGCHLD, main_sigchld_handler); signal(SIGTERM, sigterm_handler); @@ -2220,11 +2014,6 @@ main(int ac, char **av) alarm(options.login_grace_time); sshd_exchange_identification(ssh, sock_in, sock_out); - - /* In inetd mode, generate ephemeral key only for proto 1 connections */ - if (!compat20 && inetd_flag && sensitive_data.server_key == NULL) - generate_ephemeral_server_key(); - packet_set_nonblocking(); /* allocate authentication context */ @@ -2242,7 +2031,7 @@ main(int ac, char **av) if (use_privsep) { if (privsep_preauth(authctxt) == 1) goto authenticated; - } else if (compat20 && have_agent) { + } else if (have_agent) { if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { error("Unable to get agent socket: %s", ssh_err(r)); have_agent = 0; @@ -2251,17 +2040,9 @@ main(int ac, char **av) /* perform the key exchange */ /* authenticate user and start session */ - if (compat20) { - do_ssh2_kex(); - do_authentication2(authctxt); - } else { -#ifdef WITH_SSH1 - do_ssh1_kex(); - do_authentication(authctxt); -#else - fatal("ssh1 not supported"); -#endif - } + do_ssh2_kex(); + do_authentication2(authctxt); + /* * If we use privilege separation, the unprivileged child transfers * the current keystate and exits @@ -2309,16 +2090,13 @@ main(int ac, char **av) if (use_privsep) { privsep_postauth(authctxt); /* the monitor process [priv] will not return */ - if (!compat20) - destroy_sensitive_data(); } packet_set_timeout(options.client_alive_interval, options.client_alive_count_max); /* Try to send all our hostkeys to the client */ - if (compat20) - notify_hostkeys(active_state); + notify_hostkeys(active_state); /* Start session. */ do_authenticated(authctxt); @@ -2347,229 +2125,6 @@ main(int ac, char **av) exit(0); } -#ifdef WITH_SSH1 -/* - * Decrypt session_key_int using our private server key and private host key - * (key with larger modulus first). - */ -int -ssh1_session_key(BIGNUM *session_key_int) -{ - struct ssh *ssh = active_state; /* XXX */ - int rsafail = 0; - - if (BN_cmp(sensitive_data.server_key->rsa->n, - sensitive_data.ssh1_host_key->rsa->n) > 0) { - /* Server key has bigger modulus. */ - if (BN_num_bits(sensitive_data.server_key->rsa->n) < - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + - SSH_KEY_BITS_RESERVED) { - fatal("do_connection: %s port %d: " - "server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), - BN_num_bits(sensitive_data.server_key->rsa->n), - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), - SSH_KEY_BITS_RESERVED); - } - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.server_key->rsa) != 0) - rsafail++; - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.ssh1_host_key->rsa) != 0) - rsafail++; - } else { - /* Host key has bigger modulus (or they are equal). */ - if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) < - BN_num_bits(sensitive_data.server_key->rsa->n) + - SSH_KEY_BITS_RESERVED) { - fatal("do_connection: %s port %d: " - "host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d", - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n), - BN_num_bits(sensitive_data.server_key->rsa->n), - SSH_KEY_BITS_RESERVED); - } - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.ssh1_host_key->rsa) != 0) - rsafail++; - if (rsa_private_decrypt(session_key_int, session_key_int, - sensitive_data.server_key->rsa) != 0) - rsafail++; - } - return (rsafail); -} - -/* - * SSH1 key exchange - */ -static void -do_ssh1_kex(void) -{ - struct ssh *ssh = active_state; /* XXX */ - int i, len; - int rsafail = 0; - BIGNUM *session_key_int, *fake_key_int, *real_key_int; - u_char session_key[SSH_SESSION_KEY_LENGTH]; - u_char fake_key_bytes[4096 / 8]; - size_t fake_key_len; - u_char cookie[8]; - u_int cipher_type, auth_mask, protocol_flags; - - /* - * Generate check bytes that the client must send back in the user - * packet in order for it to be accepted; this is used to defy ip - * spoofing attacks. Note that this only works against somebody - * doing IP spoofing from a remote machine; any machine on the local - * network can still see outgoing packets and catch the random - * cookie. This only affects rhosts authentication, and this is one - * of the reasons why it is inherently insecure. - */ - arc4random_buf(cookie, sizeof(cookie)); - - /* - * Send our public key. We include in the packet 64 bits of random - * data that must be matched in the reply in order to prevent IP - * spoofing. - */ - packet_start(SSH_SMSG_PUBLIC_KEY); - for (i = 0; i < 8; i++) - packet_put_char(cookie[i]); - - /* Store our public server RSA key. */ - packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n)); - packet_put_bignum(sensitive_data.server_key->rsa->e); - packet_put_bignum(sensitive_data.server_key->rsa->n); - - /* Store our public host RSA key. */ - packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n)); - packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e); - packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n); - - /* Put protocol flags. */ - packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN); - - /* Declare which ciphers we support. */ - packet_put_int(cipher_mask_ssh1(0)); - - /* Declare supported authentication types. */ - auth_mask = 0; - if (options.rhosts_rsa_authentication) - auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA; - if (options.rsa_authentication) - auth_mask |= 1 << SSH_AUTH_RSA; - if (options.challenge_response_authentication == 1) - auth_mask |= 1 << SSH_AUTH_TIS; - if (options.password_authentication) - auth_mask |= 1 << SSH_AUTH_PASSWORD; - packet_put_int(auth_mask); - - /* Send the packet and wait for it to be sent. */ - packet_send(); - packet_write_wait(); - - debug("Sent %d bit server key and %d bit host key.", - BN_num_bits(sensitive_data.server_key->rsa->n), - BN_num_bits(sensitive_data.ssh1_host_key->rsa->n)); - - /* Read clients reply (cipher type and session key). */ - packet_read_expect(SSH_CMSG_SESSION_KEY); - - /* Get cipher type and check whether we accept this. */ - cipher_type = packet_get_char(); - - if (!(cipher_mask_ssh1(0) & (1 << cipher_type))) - packet_disconnect("Warning: client selects unsupported cipher."); - - /* 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 (cookie[i] != packet_get_char()) - packet_disconnect("IP Spoofing check bytes do not match."); - - debug("Encryption type: %.200s", cipher_name(cipher_type)); - - /* Get the encrypted integer. */ - if ((real_key_int = BN_new()) == NULL) - fatal("do_ssh1_kex: BN_new failed"); - packet_get_bignum(real_key_int); - - protocol_flags = packet_get_int(); - packet_set_protocol_flags(protocol_flags); - packet_check_eom(); - - /* Setup a fake key in case RSA decryption fails */ - if ((fake_key_int = BN_new()) == NULL) - fatal("do_ssh1_kex: BN_new failed"); - fake_key_len = BN_num_bytes(real_key_int); - if (fake_key_len > sizeof(fake_key_bytes)) - fake_key_len = sizeof(fake_key_bytes); - arc4random_buf(fake_key_bytes, fake_key_len); - if (BN_bin2bn(fake_key_bytes, fake_key_len, fake_key_int) == NULL) - fatal("do_ssh1_kex: BN_bin2bn failed"); - - /* Decrypt real_key_int using host/server keys */ - rsafail = PRIVSEP(ssh1_session_key(real_key_int)); - /* If decryption failed, use the fake key. Else, the real key. */ - if (rsafail) - session_key_int = fake_key_int; - else - session_key_int = real_key_int; - - /* - * Extract session key from the decrypted integer. The key is in the - * least significant 256 bits of the integer; the first byte of the - * key is in the highest bits. - */ - (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8); - len = BN_num_bytes(session_key_int); - if (len < 0 || (u_int)len > sizeof(session_key)) { - error("%s: bad session key len from %s port %d: " - "session_key_int %d > sizeof(session_key) %lu", __func__, - ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), - len, (u_long)sizeof(session_key)); - rsafail++; - } else { - explicit_bzero(session_key, sizeof(session_key)); - BN_bn2bin(session_key_int, - session_key + sizeof(session_key) - len); - - derive_ssh1_session_id( - sensitive_data.ssh1_host_key->rsa->n, - sensitive_data.server_key->rsa->n, - cookie, session_id); - /* - * 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 private and public keys. No longer. */ - destroy_sensitive_data(); - - if (use_privsep) - mm_ssh1_session_id(session_id); - - /* Destroy the decrypted integer. It is no longer needed. */ - BN_clear_free(real_key_int); - BN_clear_free(fake_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); - - /* Destroy our copy of the session key. It is no longer needed. */ - explicit_bzero(session_key, sizeof(session_key)); - - debug("Received session key; encryption turned on."); - - /* Send an acknowledgment packet. Note that this packet is sent encrypted. */ - packet_start(SSH_SMSG_SUCCESS); - packet_send(); - packet_write_wait(); -} -#endif - int sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, size_t *slen, const u_char *data, size_t dlen, const char *alg, u_int flag) -- cgit v1.2.3