From e9702f7d1a391091b2fe6510c1e353bd51313b1e Mon Sep 17 00:00:00 2001 From: jbasney Date: Wed, 13 Mar 2002 20:25:08 +0000 Subject: [PATCH] resolving conflicts from import of OpenSSH 3.1p1 --- openssh/Makefile.in | 37 +- openssh/acconfig.h | 12 +- openssh/auth-krb5.c | 93 ++-- openssh/auth-pam.c | 2 +- openssh/auth.h | 23 +- openssh/auth2.c | 225 +++++----- openssh/configure.ac | 464 ++++++++++++-------- openssh/kex.c | 51 ++- openssh/kex.h | 6 +- openssh/key.c | 113 ++--- openssh/key.h | 6 +- openssh/readconf.c | 44 +- openssh/readconf.h | 6 +- openssh/servconf.c | 965 +++++++++++++++++++++--------------------- openssh/servconf.h | 15 +- openssh/session.c | 889 ++++++++++++++++---------------------- openssh/session.h | 4 +- openssh/sshconnect1.c | 349 +++++++-------- openssh/sshconnect2.c | 116 ++--- openssh/sshd.8 | 153 ++++--- openssh/sshd.c | 161 ++++--- 21 files changed, 1934 insertions(+), 1800 deletions(-) diff --git a/openssh/Makefile.in b/openssh/Makefile.in index f4ab6f0..3f6d987 100644 --- a/openssh/Makefile.in +++ b/openssh/Makefile.in @@ -19,17 +19,20 @@ SSH_PROGRAM=@bindir@/ssh ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass SFTP_SERVER=$(libexecdir)/sftp-server -PATHS= -DETCDIR=\"$(sysconfdir)\" \ +PATHS= -DSSHDIR=\"$(sysconfdir)\" \ -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \ -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \ - -D_PATH_SSH_PIDDIR=\"$(piddir)\" + -D_PATH_SSH_PIDDIR=\"$(piddir)\" \ + -DSSH_RAND_HELPER=\"$(libexecdir)/ssh-rand-helper\" CC=@CC@ LD=@LD@ CFLAGS=@CFLAGS@ CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ LIBS=@LIBS@ +LIBPAM=@LIBPAM@ +LIBWRAP=@LIBWRAP@ AR=@AR@ RANLIB=@RANLIB@ INSTALL=@INSTALL@ @@ -41,12 +44,13 @@ EXEEXT=@EXEEXT@ SSH_MODE= @SSHMODE@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ +INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ @NO_SFTP@SFTP_PROGS=sftp-server$(EXEEXT) sftp$(EXEEXT) -TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) $(SFTP_PROGS) +TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} $(SFTP_PROGS) -LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dh.o dispatch.o mac.o hostfile.o key.o kex.o kexdh.o kexgex.o kexgss.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o scard.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o gss-genr.o +LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dh.o dispatch.o fatal.o mac.o hostfile.o key.o kex.o kexdh.o kexgex.o log.o match.o misc.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o scard.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o uuencode.o xmalloc.o gss-genr.o SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o sshtty.o readconf.o clientloop.o @@ -60,17 +64,17 @@ CONFIGFILES=sshd_config.out ssh_config.out moduli.out CONFIGFILES_IN=sshd_config ssh_config moduli PATHSUBS = \ - -D/etc/ssh_config=$(sysconfdir)/ssh_config \ - -D/etc/ssh_known_hosts=$(sysconfdir)/ssh_known_hosts \ - -D/etc/sshd_config=$(sysconfdir)/sshd_config \ + -D/etc/ssh/ssh_config=$(sysconfdir)/ssh_config \ + -D/etc/ssh/ssh_known_hosts=$(sysconfdir)/ssh_known_hosts \ + -D/etc/ssh/sshd_config=$(sysconfdir)/sshd_config \ -D/usr/libexec=$(libexecdir) \ -D/etc/shosts.equiv=$(sysconfdir)/shosts.equiv \ - -D/etc/ssh_host_key=$(sysconfdir)/ssh_host_key \ - -D/etc/ssh_host_dsa_key=$(sysconfdir)/ssh_host_dsa_key \ - -D/etc/ssh_host_rsa_key=$(sysconfdir)/ssh_host_rsa_key \ + -D/etc/ssh/ssh_host_key=$(sysconfdir)/ssh_host_key \ + -D/etc/ssh/ssh_host_dsa_key=$(sysconfdir)/ssh_host_dsa_key \ + -D/etc/ssh/ssh_host_rsa_key=$(sysconfdir)/ssh_host_rsa_key \ -D/var/run/sshd.pid=$(piddir)/sshd.pid \ - -D/etc/moduli=$(sysconfdir)/moduli \ - -D/etc/sshrc=$(sysconfdir)/sshrc \ + -D/etc/ssh/moduli=$(sysconfdir)/moduli \ + -D/etc/ssh/sshrc=$(sysconfdir)/sshrc \ -D/usr/X11R6/bin/xauth=$(XAUTH_PATH) \ -D/usr/bin:/bin:/usr/sbin:/sbin=@user_path@ @@ -98,7 +102,7 @@ ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) - $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBWRAP) $(LIBPAM) $(LIBS) scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o $(LD) -o $@ scp.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) @@ -121,6 +125,9 @@ sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-int.o sftp-common.o sftp-glob.o $(LD) -o $@ sftp.o sftp-client.o sftp-common.o sftp-int.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o + $(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + # test driver for the loginrec code - not built by default logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS) @@ -197,6 +204,9 @@ install-files: scard-install $(INSTALL) -m 0755 -s ssh-keygen $(DESTDIR)$(bindir)/ssh-keygen $(INSTALL) -m 0755 -s ssh-keyscan $(DESTDIR)$(bindir)/ssh-keyscan $(INSTALL) -m 0755 -s sshd $(DESTDIR)$(sbindir)/sshd + if test ! -z "$(INSTALL_SSH_RAND_HELPER)" ; then \ + $(INSTALL) -m 0755 -s ssh-rand-helper $(DESTDIR)$(libexecdir)/ssh-rand-helper ; \ + fi @NO_SFTP@$(INSTALL) -m 0755 -s sftp $(DESTDIR)$(bindir)/sftp @NO_SFTP@$(INSTALL) -m 0755 -s sftp-server $(DESTDIR)$(SFTP_SERVER) $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 @@ -212,7 +222,6 @@ install-files: scard-install ln -s ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 ln -s ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 - #@FILEPRIV@ -f dev,filesys,driver $(DESTDIR)$(bindir)/ssh $(DESTDIR)$(bindir)/slogin if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \ $(srcdir)/mkinstalldirs $(DESTDIR)$(sysconfdir); \ fi diff --git a/openssh/acconfig.h b/openssh/acconfig.h index 84e0e64..3a39d09 100644 --- a/openssh/acconfig.h +++ b/openssh/acconfig.h @@ -59,9 +59,6 @@ /* Define if you are on Cygwin */ #undef HAVE_CYGWIN -/* Define if you lack native POSIX regex and you are using PCRE */ -#undef HAVE_LIBPCRE - /* Define if you have a broken realpath. */ #undef BROKEN_REALPATH @@ -89,9 +86,6 @@ /* Define if you want IRIX kernel jobs */ #undef WITH_IRIX_JOBS -/* Location of random number pool */ -#undef RANDOM_POOL - /* Location of PRNGD/EGD random number socket */ #undef PRNGD_SOCKET @@ -275,9 +269,6 @@ #undef HAVE_SS_FAMILY_IN_SS #undef HAVE___SS_FAMILY_IN_SS -/* Define if you have a regcomp() function */ -#undef HAVE_REGCOMP - /* Define if you have /dev/ptmx */ #undef HAVE_DEV_PTMX @@ -341,6 +332,9 @@ /* Define if you want smartcard support */ #undef SMARTCARD +/* Define if you want to use OpenSSL's internally seeded PRNG only */ +#undef OPENSSL_PRNG_ONLY + @BOTTOM@ /* ******************* Shouldn't need to edit below this line ************** */ diff --git a/openssh/auth-krb5.c b/openssh/auth-krb5.c index 176eb27..f105207 100644 --- a/openssh/auth-krb5.c +++ b/openssh/auth-krb5.c @@ -2,10 +2,11 @@ * Kerberos v5 authentication and ticket-passing routines. * * $FreeBSD: src/crypto/openssh/auth-krb5.c,v 1.6 2001/02/13 16:58:04 assar Exp $ - * $OpenBSD: auth-krb5.c,v 1.2 2001/11/12 01:47:09 dugsong Exp $ */ #include "includes.h" +RCSID("$OpenBSD: auth-krb5.c,v 1.6 2002/03/04 17:27:39 stevesk Exp $"); + #include "ssh.h" #include "ssh1.h" #include "packet.h" @@ -29,7 +30,7 @@ krb5_init(void *context) Authctxt *authctxt = (Authctxt *)context; krb5_error_code problem; static int cleanup_registered = 0; - + if (authctxt->krb5_ctx == NULL) { problem = krb5_init_context(&authctxt->krb5_ctx); if (problem) @@ -48,7 +49,7 @@ krb5_init(void *context) * only, in auth is received ticket, in client is returned principal * from the ticket */ -int +int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client) { krb5_error_code problem; @@ -61,16 +62,16 @@ auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client) server = NULL; ticket = NULL; reply.length = 0; - + problem = krb5_init(authctxt); - if (problem) + if (problem) goto err; - + problem = krb5_auth_con_init(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx); if (problem) goto err; - + fd = packet_get_connection_in(); #ifdef HEIMDAL problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx, @@ -83,12 +84,12 @@ auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client) #endif if (problem) goto err; - + problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL , KRB5_NT_SRV_HST, &server); if (problem) goto err; - + problem = krb5_rd_req(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx, auth, server, NULL, NULL, &ticket); if (problem) @@ -103,22 +104,22 @@ auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client) #endif if (problem) goto err; - + /* if client wants mutual auth */ problem = krb5_mk_rep(authctxt->krb5_ctx, authctxt->krb5_auth_ctx, &reply); if (problem) goto err; - + /* Check .k5login authorization now. */ if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, authctxt->pw->pw_name)) goto err; - + if (client) krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user, client); - + packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE); packet_put_string((char *) reply.data, reply.length); packet_send(); @@ -132,10 +133,15 @@ auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client) krb5_free_ticket(authctxt->krb5_ctx, ticket); if (reply.length) xfree(reply.data); - - if (problem) - debug("Kerberos v5 authentication failed: %s", - krb5_get_err_text(authctxt->krb5_ctx, problem)); + + if (problem) { + if (authctxt->krb5_ctx != NULL) + debug("Kerberos v5 authentication failed: %s", + krb5_get_err_text(authctxt->krb5_ctx, problem)); + else + debug("Kerberos v5 authentication failed: %d", + problem); + } return (ret); } @@ -150,7 +156,7 @@ auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt) if (authctxt->pw == NULL || authctxt->krb5_user == NULL) return (0); - + temporarily_use_uid(authctxt->pw); #ifdef HEIMDAL @@ -165,7 +171,7 @@ auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt) #endif if (problem) goto fail; - + problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache, authctxt->krb5_user); if (problem) @@ -188,29 +194,29 @@ auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt) authctxt->krb5_fwd_ccache = ccache; ccache = NULL; - + authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); - + problem = krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user, &pname); if (problem) goto fail; - + debug("Kerberos v5 TGT accepted (%s)", pname); - + restore_uid(); - + return (1); - + fail: if (problem) debug("Kerberos v5 TGT passing failed: %s", krb5_get_err_text(authctxt->krb5_ctx, problem)); if (ccache) krb5_cc_destroy(authctxt->krb5_ctx, ccache); - + restore_uid(); - + return (0); } @@ -222,16 +228,16 @@ auth_krb5_password(Authctxt *authctxt, const char *password) krb5_principal server; #endif krb5_error_code problem; - + if (authctxt->pw == NULL) return (0); - + temporarily_use_uid(authctxt->pw); - + problem = krb5_init(authctxt); if (problem) goto out; - + problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name, &authctxt->krb5_user); if (problem) @@ -246,15 +252,18 @@ auth_krb5_password(Authctxt *authctxt, const char *password) #endif if (problem) goto out; - + problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, authctxt->krb5_user); if (problem) goto out; #ifdef HEIMDAL + restore_uid(); problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user, authctxt->krb5_fwd_ccache, password, 1, NULL); + temporarily_use_uid(authctxt->pw); + if (problem) goto out; @@ -279,22 +288,24 @@ auth_krb5_password(Authctxt *authctxt, const char *password) goto out; problem = krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache, &creds); - if (problem) - goto out; #endif /* HEIMDAL */ authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); - + out: restore_uid(); - + if (problem) { - debug("Kerberos password authentication failed: %s", - krb5_get_err_text(authctxt->krb5_ctx, problem)); - + if (authctxt->krb5_ctx != NULL) + debug("Kerberos password authentication failed: %s", + krb5_get_err_text(authctxt->krb5_ctx, problem)); + else + debug("Kerberos password authentication failed: %d", + problem); + krb5_cleanup_proc(authctxt); - + if (options.kerberos_or_local_passwd) return (-1); else @@ -307,7 +318,7 @@ void krb5_cleanup_proc(void *context) { Authctxt *authctxt = (Authctxt *)context; - + debug("krb5_cleanup_proc called"); if (authctxt->krb5_fwd_ccache) { krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); diff --git a/openssh/auth-pam.c b/openssh/auth-pam.c index 8e170d4..15eac39 100644 --- a/openssh/auth-pam.c +++ b/openssh/auth-pam.c @@ -360,7 +360,7 @@ void start_pam(const char *user) fatal("PAM initialisation failed[%d]: %.200s", pam_retval, PAM_STRERROR(__pamh, pam_retval)); - rhost = get_remote_name_or_ip(utmp_len, options.reverse_mapping_check); + rhost = get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping); debug("PAM setting rhost to \"%.200s\"", rhost); pam_retval = pam_set_item(__pamh, PAM_RHOST, rhost); diff --git a/openssh/auth.h b/openssh/auth.h index 656918e..cbf282c 100644 --- a/openssh/auth.h +++ b/openssh/auth.h @@ -1,3 +1,5 @@ +/* $OpenBSD: auth.h,v 1.29 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -21,8 +23,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $OpenBSD: auth.h,v 1.22 2001/06/26 17:27:22 markus Exp $ */ + #ifndef AUTH_H #define AUTH_H @@ -72,30 +74,28 @@ struct Authctxt { /* * Keyboard interactive device: - * init_ctx returns: non NULL upon success - * query returns: 0 - success, otherwise failure + * init_ctx returns: non NULL upon success + * query returns: 0 - success, otherwise failure * respond returns: 0 - success, 1 - need further interaction, * otherwise - failure */ struct KbdintDevice { const char *name; - void* (*init_ctx) __P((Authctxt*)); - int (*query) __P((void *ctx, char **name, char **infotxt, - u_int *numprompts, char ***prompts, - u_int **echo_on)); - int (*respond) __P((void *ctx, u_int numresp, char **responses)); - void (*free_ctx) __P((void *ctx)); + void* (*init_ctx)(Authctxt*); + int (*query)(void *ctx, char **name, char **infotxt, + u_int *numprompts, char ***prompts, u_int **echo_on); + int (*respond)(void *ctx, u_int numresp, char **responses); + 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(struct passwd *, const char *, RSA *); +int auth_rhosts_rsa(struct passwd *, const char *, Key *); int auth_password(Authctxt *, const char *); int auth_rsa(struct passwd *, BIGNUM *); -int auth_rsa_read_key(char **, u_int *, BIGNUM *, BIGNUM *); int auth_rsa_challenge_dialog(RSA *); #ifdef KRB4 @@ -131,6 +131,7 @@ void userauth_finish(Authctxt *, int, char *); int auth_root_allowed(char *); int auth2_challenge(Authctxt *, char *); +void auth2_challenge_stop(Authctxt *); int allowed_user(struct passwd *); diff --git a/openssh/auth2.c b/openssh/auth2.c index 2fbe819..481a6bf 100644 --- a/openssh/auth2.c +++ b/openssh/auth2.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: auth2.c,v 1.72 2001/11/07 22:41:51 markus Exp $"); +RCSID("$OpenBSD: auth2.c,v 1.85 2002/02/24 19:14:59 markus Exp $"); #include @@ -73,9 +73,8 @@ struct Authmethod { /* protocol */ -static void input_service_request(int, int, void *); -static void input_userauth_request(int, int, void *); -static void protocol_error(int, int, void *); +static void input_service_request(int, u_int32_t, void *); +static void input_userauth_request(int, u_int32_t, void *); /* helper */ static Authmethod *authmethod_lookup(const char *); @@ -128,7 +127,7 @@ Authmethod authmethods[] = { */ void -do_authentication2() +do_authentication2(void) { Authctxt *authctxt = authctxt_new(); @@ -140,30 +139,20 @@ do_authentication2() if (options.pam_authentication_via_kbd_int) options.kbd_interactive_authentication = 1; - dispatch_init(&protocol_error); + dispatch_init(&dispatch_protocol_error); dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt); do_authenticated(authctxt); } static void -protocol_error(int type, int plen, void *ctxt) -{ - log("auth: protocol error: type %d plen %d", type, plen); - packet_start(SSH2_MSG_UNIMPLEMENTED); - packet_put_int(0); - packet_send(); - packet_write_wait(); -} - -static void -input_service_request(int type, int plen, void *ctxt) +input_service_request(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; u_int len; int accept = 0; char *service = packet_get_string(&len); - packet_done(); + packet_check_eom(); if (authctxt == NULL) fatal("input_service_request: no authctxt"); @@ -190,7 +179,7 @@ input_service_request(int type, int plen, void *ctxt) } static void -input_userauth_request(int type, int plen, void *ctxt) +input_userauth_request(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; Authmethod *m = NULL; @@ -237,20 +226,12 @@ input_userauth_request(int type, int plen, void *ctxt) authctxt->user, authctxt->service, user, service); } /* reset state */ - dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, &protocol_error); - #ifdef GSSAPI dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &protocol_error); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, &protocol_error); #endif - + auth2_challenge_stop(authctxt); authctxt->postponed = 0; -#ifdef BSD_AUTH - if (authctxt->as) { - auth_close(authctxt->as); - authctxt->as = NULL; - } -#endif /* try to authenticate user */ m = authmethod_lookup(method); @@ -294,7 +275,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method) /* XXX todo: check if multiple auth methods are needed */ if (authenticated == 1) { /* turn off userauth */ - dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error); + dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); packet_start(SSH2_MSG_USERAUTH_SUCCESS); packet_send(); packet_write_wait(); @@ -304,7 +285,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method) if (authctxt->failures++ > AUTH_FAIL_MAX) { #ifdef WITH_AIXAUTHENTICATE loginfailed(authctxt->user, - get_canonical_hostname(options.reverse_mapping_check), + get_canonical_hostname(options.verify_reverse_mapping), "ssh"); #endif /* WITH_AIXAUTHENTICATE */ packet_disconnect(AUTH_FAIL_MSG, authctxt->user); @@ -357,14 +338,14 @@ userauth_none(Authctxt *authctxt) Authmethod *m = authmethod_lookup("none"); if (m != NULL) m->enabled = NULL; - packet_done(); + packet_check_eom(); userauth_banner(); if (authctxt->valid == 0) return(0); #ifdef HAVE_CYGWIN - if (check_nt_auth(1, authctxt->pw->pw_uid) == 0) + if (check_nt_auth(1, authctxt->pw) == 0) return(0); #endif #ifdef USE_PAM @@ -387,10 +368,10 @@ userauth_passwd(Authctxt *authctxt) if (change) log("password change not supported"); password = packet_get_string(&len); - packet_done(); + packet_check_eom(); if (authctxt->valid && #ifdef HAVE_CYGWIN - check_nt_auth(1, authctxt->pw->pw_uid) && + check_nt_auth(1, authctxt->pw) && #endif #ifdef USE_PAM auth_pam_password(authctxt->pw, password) == 1) @@ -413,7 +394,7 @@ userauth_kbdint(Authctxt *authctxt) lang = packet_get_string(NULL); devs = packet_get_string(NULL); - packet_done(); + packet_check_eom(); debug("keyboard-interactive devs %s", devs); @@ -427,7 +408,7 @@ userauth_kbdint(Authctxt *authctxt) xfree(devs); xfree(lang); #ifdef HAVE_CYGWIN - if (check_nt_auth(0, authctxt->pw->pw_uid) == 0) + if (check_nt_auth(0, authctxt->pw) == 0) return(0); #endif return authenticated; @@ -437,8 +418,9 @@ static int userauth_pubkey(Authctxt *authctxt) { Buffer b; - Key *key; - char *pkalg, *pkblob, *sig; + Key *key = NULL; + char *pkalg; + u_char *pkblob, *sig; u_int alen, blen, slen; int have_sig, pktype; int authenticated = 0; @@ -464,76 +446,84 @@ userauth_pubkey(Authctxt *authctxt) pktype = key_type_from_name(pkalg); if (pktype == KEY_UNSPEC) { /* this is perfectly legal */ - log("userauth_pubkey: unsupported public key algorithm: %s", pkalg); - xfree(pkalg); - xfree(pkblob); - return 0; + log("userauth_pubkey: unsupported public key algorithm: %s", + pkalg); + goto done; } key = key_from_blob(pkblob, blen); - if (key != NULL) { - if (have_sig) { - sig = packet_get_string(&slen); - packet_done(); - buffer_init(&b); - if (datafellows & SSH_OLD_SESSIONID) { - buffer_append(&b, session_id2, session_id2_len); - } else { - buffer_put_string(&b, session_id2, session_id2_len); - } - /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, authctxt->user); - buffer_put_cstring(&b, - datafellows & SSH_BUG_PKSERVICE ? - "ssh-userauth" : - authctxt->service); - if (datafellows & SSH_BUG_PKAUTH) { - buffer_put_char(&b, have_sig); - } else { - buffer_put_cstring(&b, "publickey"); - buffer_put_char(&b, have_sig); - buffer_put_cstring(&b, pkalg); - } - buffer_put_string(&b, pkblob, blen); + if (key == NULL) { + error("userauth_pubkey: cannot decode key: %s", pkalg); + goto done; + } + if (key->type != pktype) { + error("userauth_pubkey: type mismatch for decoded key " + "(received %d, expected %d)", key->type, pktype); + goto done; + } + if (have_sig) { + sig = packet_get_string(&slen); + packet_check_eom(); + buffer_init(&b); + if (datafellows & SSH_OLD_SESSIONID) { + buffer_append(&b, session_id2, session_id2_len); + } else { + buffer_put_string(&b, session_id2, session_id2_len); + } + /* reconstruct packet */ + buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); + buffer_put_cstring(&b, authctxt->user); + buffer_put_cstring(&b, + datafellows & SSH_BUG_PKSERVICE ? + "ssh-userauth" : + authctxt->service); + if (datafellows & SSH_BUG_PKAUTH) { + buffer_put_char(&b, have_sig); + } else { + buffer_put_cstring(&b, "publickey"); + buffer_put_char(&b, have_sig); + buffer_put_cstring(&b, pkalg); + } + buffer_put_string(&b, pkblob, blen); #ifdef DEBUG_PK - buffer_dump(&b); + buffer_dump(&b); #endif - /* test for correct signature */ - if (user_key_allowed(authctxt->pw, key) && - key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) - authenticated = 1; - buffer_clear(&b); - xfree(sig); - } else { - debug("test whether pkalg/pkblob are acceptable"); - packet_done(); - - /* XXX fake reply and always send PK_OK ? */ - /* - * XXX this allows testing whether a user is allowed - * to login: if you happen to have a valid pubkey this - * message is sent. the message is NEVER sent at all - * if a user is not allowed to login. is this an - * issue? -markus - */ - if (user_key_allowed(authctxt->pw, key)) { - packet_start(SSH2_MSG_USERAUTH_PK_OK); - packet_put_string(pkalg, alen); - packet_put_string(pkblob, blen); - packet_send(); - packet_write_wait(); - authctxt->postponed = 1; - } + /* test for correct signature */ + if (user_key_allowed(authctxt->pw, key) && + key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) + authenticated = 1; + buffer_clear(&b); + xfree(sig); + } else { + debug("test whether pkalg/pkblob are acceptable"); + packet_check_eom(); + + /* XXX fake reply and always send PK_OK ? */ + /* + * XXX this allows testing whether a user is allowed + * to login: if you happen to have a valid pubkey this + * message is sent. the message is NEVER sent at all + * if a user is not allowed to login. is this an + * issue? -markus + */ + if (user_key_allowed(authctxt->pw, key)) { + packet_start(SSH2_MSG_USERAUTH_PK_OK); + packet_put_string(pkalg, alen); + packet_put_string(pkblob, blen); + packet_send(); + packet_write_wait(); + authctxt->postponed = 1; } - if (authenticated != 1) - auth_clear_options(); - key_free(key); } + if (authenticated != 1) + auth_clear_options(); +done: debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg); + if (key != NULL) + key_free(key); xfree(pkalg); xfree(pkblob); #ifdef HAVE_CYGWIN - if (check_nt_auth(0, authctxt->pw->pw_uid) == 0) + if (check_nt_auth(0, authctxt->pw) == 0) return(0); #endif return authenticated; @@ -543,8 +533,9 @@ static int userauth_hostbased(Authctxt *authctxt) { Buffer b; - Key *key; - char *pkalg, *pkblob, *sig, *cuser, *chost, *service; + Key *key = NULL; + char *pkalg, *cuser, *chost, *service; + u_char *pkblob, *sig; u_int alen, blen, slen; int pktype; int authenticated = 0; @@ -577,7 +568,12 @@ userauth_hostbased(Authctxt *authctxt) } key = key_from_blob(pkblob, blen); if (key == NULL) { - debug("userauth_hostbased: cannot decode key: %s", pkalg); + error("userauth_hostbased: cannot decode key: %s", pkalg); + goto done; + } + if (key->type != pktype) { + error("userauth_hostbased: type mismatch for decoded key " + "(received %d, expected %d)", key->type, pktype); goto done; } service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" : @@ -602,10 +598,10 @@ userauth_hostbased(Authctxt *authctxt) authenticated = 1; buffer_clear(&b); - key_free(key); - done: debug2("userauth_hostbased: authenticated %d", authenticated); + if (key != NULL) + key_free(key); xfree(pkalg); xfree(pkblob); xfree(cuser); @@ -628,7 +624,7 @@ static char * authmethods_get(void) { Authmethod *method = NULL; - u_int size = 0; + Buffer b; char *list; for (method = authmethods; method->name != NULL; method++) { @@ -644,15 +640,19 @@ authmethods_get(void) list = xmalloc(size); list[0] = '\0'; + buffer_init(&b); for (method = authmethods; method->name != NULL; method++) { if (strcmp(method->name, "none") == 0) continue; if (method->enabled != NULL && *(method->enabled) != 0) { - if (list[0] != '\0') - strlcat(list, DELIM, size); - strlcat(list, method->name, size); + if (buffer_len(&b) > 0) + buffer_append(&b, ",", 1); + buffer_append(&b, method->name, strlen(method->name)); } } + buffer_append(&b, "\0", 1); + list = xstrdup(buffer_ptr(&b)); + buffer_free(&b); return list; } @@ -680,6 +680,7 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) u_long linenum = 0; struct stat st; Key *found; + char *fp; if (pw == NULL) return 0; @@ -747,6 +748,10 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) found_key = 1; debug("matching key found: file %s, line %lu", file, linenum); + fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); + verbose("Found matching %s key: %s", + key_type(found), fp); + xfree(fp); break; } } @@ -784,9 +789,10 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, Key *key) { const char *resolvedname, *ipaddr, *lookup; - int host_status, len; + HostStatus host_status; + int len; - resolvedname = get_canonical_hostname(options.reverse_mapping_check); + resolvedname = get_canonical_hostname(options.verify_reverse_mapping); ipaddr = get_remote_ipaddr(); debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s", @@ -824,4 +830,3 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, return (host_status == HOST_OK); } - diff --git a/openssh/configure.ac b/openssh/configure.ac index 717d19d..bd76134 100644 --- a/openssh/configure.ac +++ b/openssh/configure.ac @@ -63,9 +63,10 @@ case "$host" in AC_DEFINE(BROKEN_GETADDRINFO) dnl AIX handles lastlog as part of its login message AC_DEFINE(DISABLE_LASTLOG) + AC_DEFINE(HAVE_BOGUS_SYS_QUEUE_H) ;; *-*-cygwin*) - LIBS="$LIBS -lregex /usr/lib/textmode.o" + LIBS="$LIBS /usr/lib/textmode.o" AC_DEFINE(HAVE_CYGWIN) AC_DEFINE(USE_PIPES) AC_DEFINE(DISABLE_SHADOW) @@ -122,6 +123,7 @@ case "$host" in check_for_libcrypt_later=1 AC_DEFINE(DONT_TRY_OTHER_AF) AC_DEFINE(PAM_TTY_KLUDGE) + AC_DEFINE(HAVE_BOGUS_SYS_QUEUE_H) inet6_default_4in6=yes ;; mips-sony-bsd|mips-sony-newsos4) @@ -184,6 +186,7 @@ mips-sony-bsd|mips-sony-newsos4) LDFLAGS="$LDFLAGS -L/usr/local/lib" LIBS="$LIBS -lc89" AC_DEFINE(HAVE_BOGUS_SYS_QUEUE_H) + AC_DEFINE(USE_PIPES) ;; *-sni-sysv*) CPPFLAGS="$CPPFLAGS -I/usr/local/include" @@ -357,6 +360,18 @@ AC_ARG_WITH(pcre, ] ) +# Checks for header files. +AC_CHECK_HEADERS(bstring.h crypt.h endian.h floatingpoint.h \ + getopt.h glob.h lastlog.h limits.h login.h \ + login_cap.h maillock.h netdb.h netgroup.h \ + netinet/in_systm.h paths.h poll.h pty.h \ + security/pam_appl.h shadow.h stddef.h stdint.h \ + strings.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h \ + sys/poll.h sys/queue.h sys/select.h sys/stat.h \ + sys/stropts.h sys/sysmacros.h sys/time.h \ + sys/ttcompat.h sys/un.h time.h ttyent.h usersec.h \ + util.h utime.h utmp.h utmpx.h) + # Checks for libraries. AC_CHECK_FUNC(yp_match, , AC_CHECK_LIB(nsl, yp_match)) AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt)) @@ -371,10 +386,25 @@ fi AC_CHECK_FUNC(getspnam, , AC_CHECK_LIB(gen, getspnam, LIBS="$LIBS -lgen")) +AC_ARG_WITH(rpath, + [ --without-rpath Disable auto-added -R linker paths], + [ + if test "x$withval" = "xno" ; then + need_dash_r="" + fi + if test "x$withval" = "xyes" ; then + need_dash_r=1 + fi + ] +) + dnl zlib is required AC_ARG_WITH(zlib, [ --with-zlib=PATH Use zlib in PATH], [ + if test "x$withval" = "xno" ; then + AC_MSG_ERROR([*** zlib is required ***]) + fi if test -d "$withval/lib"; then if test -n "${need_dash_r}"; then LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}" @@ -398,23 +428,6 @@ AC_ARG_WITH(zlib, AC_CHECK_LIB(z, deflate, ,AC_MSG_ERROR([*** zlib missing - please install first or check config.log ***])) -# We don't want to check if we did an pcre override. -if test -z "$no_comp_check" ; then - AC_CHECK_FUNC(regcomp, - [ AC_DEFINE(HAVE_REGCOMP)], - [ - AC_CHECK_LIB(pcre, pcre_info, - [ - AC_DEFINE(HAVE_LIBPCRE) - LIBS="$LIBS -lpcreposix -lpcre" - ], - [ - AC_MSG_ERROR([*** No regex library found.]) - ]) - ] - ) -fi - dnl UnixWare 2.x AC_CHECK_FUNC(strcasecmp, [], [ AC_CHECK_LIB(resolv, strcasecmp, LIBS="$LIBS -lresolv") ] @@ -430,18 +443,6 @@ AC_CHECK_FUNCS(logout updwtmp logwtmp) AC_FUNC_STRFTIME -# Checks for header files. -AC_CHECK_HEADERS(bstring.h crypt.h endian.h floatingpoint.h \ - getopt.h glob.h lastlog.h limits.h login.h \ - login_cap.h maillock.h netdb.h netgroup.h \ - netinet/in_systm.h paths.h poll.h pty.h regex.h \ - security/pam_appl.h shadow.h stddef.h stdint.h \ - strings.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h \ - sys/poll.h sys/queue.h sys/select.h sys/stat.h \ - sys/stropts.h sys/sysmacros.h sys/time.h \ - sys/ttcompat.h sys/un.h time.h ttyent.h usersec.h \ - util.h utime.h utmp.h utmpx.h) - # Check for ALTDIRFUNC glob() extension AC_MSG_CHECKING(for GLOB_ALTDIRFUNC support) AC_EGREP_CPP(FOUNDIT, @@ -593,9 +594,16 @@ AC_ARG_WITH(skey, LIBS="-lskey $LIBS" SKEY_MSG="yes" - AC_CHECK_FUNC(skey_keyinfo, - [], + AC_MSG_CHECKING([for s/key support]) + AC_TRY_RUN( + [ +#include +#include +int main() { char *ff = skey_keyinfo(""); ff=""; return 0; } + ], + [AC_MSG_RESULT(yes)], [ + AC_MSG_RESULT(no) AC_MSG_ERROR([** Incomplete or missing s/key libraries.]) ]) fi @@ -632,7 +640,8 @@ AC_ARG_WITH(tcp-wrappers, CPPFLAGS="-I${withval} ${CPPFLAGS}" fi fi - LIBS="-lwrap $LIBS" + LIBWRAP="-lwrap" + LIBS="$LIBWRAP $LIBS" AC_MSG_CHECKING(for libwrap) AC_TRY_LINK( [ @@ -643,12 +652,14 @@ AC_ARG_WITH(tcp-wrappers, [ AC_MSG_RESULT(yes) AC_DEFINE(LIBWRAP) + AC_SUBST(LIBWRAP) TCPW_MSG="yes" ], [ AC_MSG_ERROR([*** libwrap missing]) ] ) + LIBS="$saved_LIBS" fi ] ) @@ -764,6 +775,12 @@ AC_ARG_WITH(pam, PAM_MSG="yes" AC_DEFINE(USE_PAM) + if test $ac_cv_lib_dl_dlopen = yes; then + LIBPAM="-lpam -ldl" + else + LIBPAM="-lpam" + fi + AC_SUBST(LIBPAM) fi ] ) @@ -951,12 +968,204 @@ else fi fi +# Sanity check OpenSSL headers +AC_MSG_CHECKING([whether OpenSSL's headers match the library]) +AC_TRY_RUN( + [ +#include +#include +int main(void) { return(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1); } + ], + [ + AC_MSG_RESULT(yes) + ], + [ + AC_MSG_RESULT(no) + AC_MSG_ERROR(Your OpenSSL headers do not match your library) + ] +) + # Some Linux systems (Slackware) need crypt() from libcrypt, *not* the # version in OpenSSL. Skip this for PAM if test "x$PAM_MSG" = "xno" -a "x$check_for_libcrypt_later" = "x1"; then AC_CHECK_LIB(crypt, crypt, LIBS="$LIBS -lcrypt") fi + +### Configure cryptographic random number support + +# Check wheter OpenSSL seeds itself +AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded]) +AC_TRY_RUN( + [ +#include +#include +int main(void) { return(RAND_status() == 1 ? 0 : 1); } + ], + [ + OPENSSL_SEEDS_ITSELF=yes + AC_MSG_RESULT(yes) + ], + [ + AC_MSG_RESULT(no) + # Default to use of the rand helper if OpenSSL doesn't + # seed itself + USE_RAND_HELPER=yes + ] +) + + +# Do we want to force the use of the rand helper? +AC_ARG_WITH(rand-helper, + [ --with-rand-helper Use subprocess to gather strong randomness ], + [ + if test "x$withval" = "xno" ; then + # Force use of OpenSSL's internal RNG, even if + # the previous test showed it to be unseeded. + if test -z "$OPENSSL_SEEDS_ITSELF" ; then + AC_MSG_WARN([*** Forcing use of OpenSSL's non-self-seeding PRNG]) + OPENSSL_SEEDS_ITSELF=yes + USE_RAND_HELPER="" + fi + else + USE_RAND_HELPER=yes + fi + ], +) + +# Which randomness source do we use? +if test ! -z "$OPENSSL_SEEDS_ITSELF" -a -z "$USE_RAND_HELPER" ; then + # OpenSSL only + AC_DEFINE(OPENSSL_PRNG_ONLY) + RAND_MSG="OpenSSL internal ONLY" + INSTALL_SSH_RAND_HELPER="" +elif test ! -z "$USE_RAND_HELPER" ; then + # install rand helper + RAND_MSG="ssh-rand-helper" + INSTALL_SSH_RAND_HELPER="yes" +fi +AC_SUBST(INSTALL_SSH_RAND_HELPER) + +### Configuration of ssh-rand-helper + +# PRNGD TCP socket +AC_ARG_WITH(prngd-port, + [ --with-prngd-port=PORT read entropy from PRNGD/EGD TCP localhost:PORT], + [ + case "$withval" in + no) + withval="" + ;; + [[0-9]]*) + ;; + *) + AC_MSG_ERROR(You must specify a numeric port number for --with-prngd-port) + ;; + esac + if test ! -z "$withval" ; then + PRNGD_PORT="$withval" + AC_DEFINE_UNQUOTED(PRNGD_PORT, $PRNGD_PORT) + fi + ] +) + +# PRNGD Unix domain socket +AC_ARG_WITH(prngd-socket, + [ --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)], + [ + case "$withval" in + yes) + withval="/var/run/egd-pool" + ;; + no) + withval="" + ;; + /*) + ;; + *) + AC_MSG_ERROR(You must specify an absolute path to the entropy socket) + ;; + esac + + if test ! -z "$withval" ; then + if test ! -z "$PRNGD_PORT" ; then + AC_MSG_ERROR(You may not specify both a PRNGD/EGD port and socket) + fi + if test ! -r "$withval" ; then + AC_MSG_WARN(Entropy socket is not readable) + fi + PRNGD_SOCKET="$withval" + AC_DEFINE_UNQUOTED(PRNGD_SOCKET, "$PRNGD_SOCKET") + fi + ], + [ + # Check for existing socket only if we don't have a random device already + if test "$USE_RAND_HELPER" = yes ; then + AC_MSG_CHECKING(for PRNGD/EGD socket) + # Insert other locations here + for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do + if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then + PRNGD_SOCKET="$sock" + AC_DEFINE_UNQUOTED(PRNGD_SOCKET, "$PRNGD_SOCKET") + break; + fi + done + if test ! -z "$PRNGD_SOCKET" ; then + AC_MSG_RESULT($PRNGD_SOCKET) + else + AC_MSG_RESULT(not found) + fi + fi + ] +) + +# Change default command timeout for hashing entropy source +entropy_timeout=200 +AC_ARG_WITH(entropy-timeout, + [ --with-entropy-timeout Specify entropy gathering command timeout (msec)], + [ + if test "x$withval" != "xno" ; then + entropy_timeout=$withval + fi + ] +) + +AC_DEFINE_UNQUOTED(ENTROPY_TIMEOUT_MSEC, $entropy_timeout) + +# These programs are used by the command hashing source to gather entropy +OSSH_PATH_ENTROPY_PROG(PROG_LS, ls) +OSSH_PATH_ENTROPY_PROG(PROG_NETSTAT, netstat) +OSSH_PATH_ENTROPY_PROG(PROG_ARP, arp) +OSSH_PATH_ENTROPY_PROG(PROG_IFCONFIG, ifconfig) +OSSH_PATH_ENTROPY_PROG(PROG_JSTAT, jstat) +OSSH_PATH_ENTROPY_PROG(PROG_PS, ps) +OSSH_PATH_ENTROPY_PROG(PROG_SAR, sar) +OSSH_PATH_ENTROPY_PROG(PROG_W, w) +OSSH_PATH_ENTROPY_PROG(PROG_WHO, who) +OSSH_PATH_ENTROPY_PROG(PROG_LAST, last) +OSSH_PATH_ENTROPY_PROG(PROG_LASTLOG, lastlog) +OSSH_PATH_ENTROPY_PROG(PROG_DF, df) +OSSH_PATH_ENTROPY_PROG(PROG_VMSTAT, vmstat) +OSSH_PATH_ENTROPY_PROG(PROG_UPTIME, uptime) +OSSH_PATH_ENTROPY_PROG(PROG_IPCS, ipcs) +OSSH_PATH_ENTROPY_PROG(PROG_TAIL, tail) + +# Where does ssh-rand-helper get its randomness from? +INSTALL_SSH_PRNG_CMDS="" +if test ! -z "$INSTALL_SSH_RAND_HELPER" ; then + if test ! -z "$PRNGD_PORT" ; then + RAND_HELPER_MSG="TCP localhost:$PRNGD_PORT" + elif test ! -z "$PRNGD_SOCKET" ; then + RAND_HELPER_MSG="Unix domain socket \"$PRNGD_SOCKET\"" + else + RAND_HELPER_MSG="Command hashing (timeout $entropy_timeout)" + RAND_HELPER_CMDHASH=yes + INSTALL_SSH_PRNG_CMDS="yes" + fi +fi +AC_SUBST(INSTALL_SSH_PRNG_CMDS) + + # Cheap hack to ensure NEWS-OS libraries are arranged right. if test ! -z "$SONY" ; then LIBS="$LIBS -liberty"; @@ -1037,6 +1246,19 @@ if test -z "$have_int64_t" ; then ) fi +if test -z "$have_int64_t" ; then + AC_MSG_CHECKING([for int64_t type in sys/bitypes.h]) + AC_TRY_COMPILE( + [ #include ], + [ int64_t a; a = 1], + [ + AC_DEFINE(HAVE_INT64_T) + AC_MSG_RESULT(yes) + ], + [ AC_MSG_RESULT(no) ] + ) +fi + AC_CACHE_CHECK([for u_intXX_t types], ac_cv_have_u_intxx_t, [ AC_TRY_COMPILE( [ #include ], @@ -1076,6 +1298,19 @@ if test "x$ac_cv_have_u_int64_t" = "xyes" ; then have_u_int64_t=1 fi +if test -z "$have_u_int64_t" ; then + AC_MSG_CHECKING([for u_int64_t type in sys/bitypes.h]) + AC_TRY_COMPILE( + [ #include ], + [ u_int64_t a; a = 1], + [ + AC_DEFINE(HAVE_U_INT64_T) + AC_MSG_RESULT(yes) + ], + [ AC_MSG_RESULT(no) ] + ) +fi + if test -z "$have_u_intxx_t" ; then AC_CACHE_CHECK([for uintXX_t types], ac_cv_have_uintxx_t, [ AC_TRY_COMPILE( @@ -1144,6 +1379,8 @@ fi TYPE_SOCKLEN_T +AC_CHECK_TYPES(sig_atomic_t,,,[#include ]) + AC_CACHE_CHECK([for size_t], ac_cv_have_size_t, [ AC_TRY_COMPILE( [ @@ -1734,97 +1971,6 @@ AC_CHECK_FILE("/dev/ptc", ) # Options from here on. Some of these are preset by platform above - -# Check for user-specified random device, otherwise check /dev/urandom -AC_ARG_WITH(random, - [ --with-random=FILE read entropy from FILE (default=/dev/urandom)], - [ - if test "x$withval" != "xno" ; then - RANDOM_POOL="$withval"; - AC_DEFINE_UNQUOTED(RANDOM_POOL, "$RANDOM_POOL") - fi - ], - [ - # Check for random device - AC_CHECK_FILE("/dev/urandom", - [ - RANDOM_POOL="/dev/urandom"; - AC_SUBST(RANDOM_POOL) - AC_DEFINE_UNQUOTED(RANDOM_POOL, "$RANDOM_POOL") - ] - ) - ] -) - -# Check for PRNGD/EGD pool file -AC_ARG_WITH(prngd-port, - [ --with-prngd-port=PORT read entropy from PRNGD/EGD localhost:PORT], - [ - if test ! -z "$withval" -a "x$withval" != "xno" ; then - PRNGD_PORT="$withval" - AC_DEFINE_UNQUOTED(PRNGD_PORT, $PRNGD_PORT) - fi - ] -) - -# Check for PRNGD/EGD pool file -AC_ARG_WITH(prngd-socket, - [ --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)], - [ - if test "x$withval" != "xno" ; then - PRNGD_SOCKET="$withval" - AC_DEFINE_UNQUOTED(PRNGD_SOCKET, "$PRNGD_SOCKET") - fi - ], - [ - # Check for existing socket only if we don't have a random device already - if test -z "$RANDOM_POOL" ; then - AC_MSG_CHECKING(for PRNGD/EGD socket) - # Insert other locations here - for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do - if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then - PRNGD_SOCKET="$sock" - AC_DEFINE_UNQUOTED(PRNGD_SOCKET, "$PRNGD_SOCKET") - break; - fi - done - if test ! -z "$PRNGD_SOCKET" ; then - AC_MSG_RESULT($PRNGD_SOCKET) - else - AC_MSG_RESULT(not found) - fi - fi - ] -) - - -# detect pathnames for entropy gathering commands, if we need them -INSTALL_SSH_PRNG_CMDS="" -rm -f prng_commands -if (test -z "$RANDOM_POOL" && test -z "$PRNGD") ; then - # Use these commands to collect entropy - OSSH_PATH_ENTROPY_PROG(PROG_LS, ls) - OSSH_PATH_ENTROPY_PROG(PROG_NETSTAT, netstat) - OSSH_PATH_ENTROPY_PROG(PROG_ARP, arp) - OSSH_PATH_ENTROPY_PROG(PROG_IFCONFIG, ifconfig) - OSSH_PATH_ENTROPY_PROG(PROG_JSTAT, jstat) - OSSH_PATH_ENTROPY_PROG(PROG_PS, ps) - OSSH_PATH_ENTROPY_PROG(PROG_SAR, sar) - OSSH_PATH_ENTROPY_PROG(PROG_W, w) - OSSH_PATH_ENTROPY_PROG(PROG_WHO, who) - OSSH_PATH_ENTROPY_PROG(PROG_LAST, last) - OSSH_PATH_ENTROPY_PROG(PROG_LASTLOG, lastlog) - OSSH_PATH_ENTROPY_PROG(PROG_DF, df) - OSSH_PATH_ENTROPY_PROG(PROG_VMSTAT, vmstat) - OSSH_PATH_ENTROPY_PROG(PROG_UPTIME, uptime) - OSSH_PATH_ENTROPY_PROG(PROG_IPCS, ipcs) - OSSH_PATH_ENTROPY_PROG(PROG_TAIL, tail) - - INSTALL_SSH_PRNG_CMDS="yes" -fi -AC_SUBST(INSTALL_SSH_PRNG_CMDS) - - AC_ARG_WITH(mantype, [ --with-mantype=man|cat|doc Set man page type], [ @@ -2016,12 +2162,13 @@ AC_ARG_WITH(4in6, ) # Whether to enable BSD auth support +BSD_AUTH_MSG=no AC_ARG_WITH(bsd-auth, [ --with-bsd-auth Enable BSD auth support], [ if test "x$withval" != "xno" ; then AC_DEFINE(BSD_AUTH) - bsd_auth=yes + BSD_AUTH_MSG=yes fi ] ) @@ -2288,44 +2435,25 @@ else fi -# Change default command timeout for builtin PRNG -entropy_timeout=200 -AC_ARG_WITH(entropy-timeout, - [ --with-entropy-timeout Specify entropy gathering command timeout (msec)], - [ - if test "x$withval" != "xno" ; then - entropy_timeout=$withval - fi - ] -) -AC_DEFINE_UNQUOTED(ENTROPY_TIMEOUT_MSEC, $entropy_timeout) - - if test ! -z "$blibpath" ; then LDFLAGS="$LDFLAGS -blibpath:$blibpath" AC_MSG_WARN([Please check and edit -blibpath in LDFLAGS in Makefile]) fi -AC_EXEEXT +dnl remove pam and dl because they are in $LIBPAM +if test "$PAM_MSG" = yes ; then + LIBS=`echo $LIBS | sed 's/-lpam //'` +fi +if test "$ac_cv_lib_pam_pam_set_item" = yes ; then + LIBS=`echo $LIBS | sed 's/-ldl //'` +fi +AC_EXEEXT AC_CONFIG_FILES([Makefile openbsd-compat/Makefile scard/Makefile ssh_prng_cmds]) AC_OUTPUT # Print summary of options -if test ! -z "$RANDOM_POOL" ; then - RAND_MSG="Device ($RANDOM_POOL)" -else - if test ! -z "$PRNGD_PORT" ; then - RAND_MSG="PRNGD/EGD (port localhost:$PRNGD_PORT)" - elif test ! -z "$PRNGD_SOCKET" ; then - RAND_MSG="PRNGD/EGD (socket $PRNGD_SOCKET)" - else - RAND_MSG="Builtin (timeout $entropy_timeout)" - BUILTIN_RNG=1 - fi -fi - # Someone please show me a better way :) A=`eval echo ${prefix}` ; A=`eval echo ${A}` B=`eval echo ${bindir}` ; B=`eval echo ${B}` @@ -2345,7 +2473,6 @@ echo " Askpass program: $E" echo " Manual pages: $F" echo " PID file: $G" echo " sshd default user PATH: $H" -echo " Random number collection: $RAND_MSG" echo " Manpage format: $MANTYPE" echo " PAM support: ${PAM_MSG}" echo " KerberosIV support: $KRB4_MSG" @@ -2357,9 +2484,10 @@ echo " MD5 password support: $MD5_MSG" echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" echo " Use IPv4 by default hack: $IPV4_HACK_MSG" echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" - -if test ! -z "$bsd_auth"; then - echo " BSD Auth support: yes" +echo " BSD Auth support: $BSD_AUTH_MSG" +echo " Random number source: $RAND_MSG" +if test ! -z "$USE_RAND_HELPER" ; then + echo " ssh-rand-helper collects from: $RAND_HELPER_MSG" fi echo "" @@ -2369,27 +2497,29 @@ echo " Compiler: ${CC}" echo " Compiler flags: ${CFLAGS}" echo "Preprocessor flags: ${CPPFLAGS}" echo " Linker flags: ${LDFLAGS}" -echo " Libraries: ${LIBS}" +echo " Libraries: ${LIBWRAP} ${LIBPAM} ${LIBS}" echo "" if test "x$PAM_MSG" = "xyes" ; then - echo "PAM is enabled. You may need to install a PAM control file for sshd," - echo "otherwise password authentication may fail. Example PAM control files" - echo "can be found in the contrib/ subdirectory" + echo "PAM is enabled. You may need to install a PAM control file " + echo "for sshd, otherwise password authentication may fail. " + echo "Example PAM control files can be found in the contrib/ " + echo "subdirectory" echo "" fi -if test ! -z "$BUILTIN_RNG" ; then - echo "WARNING: you are using the builtin random number collection service." - echo "Please read WARNING.RNG and request that your OS vendor includes" - echo "/dev/random in future versions of their OS." +if test ! -z "$NO_SFTP"; then + echo "sftp-server will be disabled. Your compiler does not " + echo "support 64bit integers." echo "" fi -if test ! -z "$NO_SFTP"; then - echo "sftp-server will be disabled. Your compiler does not support" - echo "64bit integers." +if test ! -z "$RAND_HELPER_CMDHASH" ; then + echo "WARNING: you are using the builtin random number collection " + echo "service. Please read WARNING.RNG and request that your OS " + echo "vendor includes kernel-based random number collection in " + echo "future versions of your OS." echo "" fi diff --git a/openssh/kex.c b/openssh/kex.c index 3a4478b..480d51a 100644 --- a/openssh/kex.c +++ b/openssh/kex.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: kex.c,v 1.36 2001/06/25 08:25:37 markus Exp $"); +RCSID("$OpenBSD: kex.c,v 1.47 2002/02/28 15:46:33 markus Exp $"); #include @@ -111,27 +111,23 @@ kex_prop_free(char **proposal) } static void -kex_protocol_error(int type, int plen, void *ctxt) +kex_protocol_error(int type, u_int32_t seq, void *ctxt) { - error("Hm, kex protocol error: type %d plen %d", type, plen); + error("Hm, kex protocol error: type %d seq %u", type, seq); } static void -kex_clear_dispatch(void) +kex_reset_dispatch(void) { - int i; - - /* Numbers 30-49 are used for kex packets */ - for (i = 30; i <= 49; i++) - dispatch_set(i, &kex_protocol_error); + dispatch_range(SSH2_MSG_TRANSPORT_MIN, + SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); + dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); } void kex_finish(Kex *kex) { - int plen; - - kex_clear_dispatch(); + kex_reset_dispatch(); packet_start(SSH2_MSG_NEWKEYS); packet_send(); @@ -139,7 +135,8 @@ kex_finish(Kex *kex) debug("SSH2_MSG_NEWKEYS sent"); debug("waiting for SSH2_MSG_NEWKEYS"); - packet_read_expect(&plen, SSH2_MSG_NEWKEYS); + packet_read_expect(SSH2_MSG_NEWKEYS); + packet_check_eom(); debug("SSH2_MSG_NEWKEYS received"); kex->done = 1; @@ -170,7 +167,7 @@ kex_send_kexinit(Kex *kex) } void -kex_input_kexinit(int type, int plen, void *ctxt) +kex_input_kexinit(int type, u_int32_t seq, void *ctxt) { char *ptr; int dlen; @@ -191,7 +188,7 @@ kex_input_kexinit(int type, int plen, void *ctxt) xfree(packet_get_string(NULL)); packet_get_char(); packet_get_int(); - packet_done(); + packet_check_eom(); kex_kexinit_finish(kex); } @@ -209,8 +206,7 @@ kex_setup(char *proposal[PROPOSAL_MAX]) kex->done = 0; kex_send_kexinit(kex); /* we start */ - kex_clear_dispatch(); - dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); + kex_reset_dispatch(); return kex; } @@ -223,7 +219,7 @@ kex_kexinit_finish(Kex *kex) kex_choose_conf(kex); - switch(kex->kex_type) { + switch (kex->kex_type) { case DH_GRP1_SHA1: kexdh(kex); break; @@ -246,13 +242,14 @@ choose_enc(Enc *enc, char *client, char *server) char *name = match_list(client, server, NULL); if (name == NULL) fatal("no matching cipher found: client %s server %s", client, server); - enc->cipher = cipher_by_name(name); - if (enc->cipher == NULL) + if ((enc->cipher = cipher_by_name(name)) == NULL) fatal("matching cipher is not supported: %s", name); enc->name = name; enc->enabled = 0; enc->iv = NULL; enc->key = NULL; + enc->key_len = cipher_keylen(enc->cipher); + enc->block_size = cipher_blocksize(enc->cipher); } static void choose_mac(Mac *mac, char *client, char *server) @@ -359,10 +356,10 @@ kex_choose_conf(Kex *kex) need = 0; for (mode = 0; mode < MODE_MAX; mode++) { newkeys = kex->newkeys[mode]; - if (need < newkeys->enc.cipher->key_len) - need = newkeys->enc.cipher->key_len; - if (need < newkeys->enc.cipher->block_size) - need = newkeys->enc.cipher->block_size; + if (need < newkeys->enc.key_len) + need = newkeys->enc.key_len; + if (need < newkeys->enc.block_size) + need = newkeys->enc.block_size; if (need < newkeys->mac.key_len) need = newkeys->mac.key_len; } @@ -377,11 +374,11 @@ static u_char * derive_key(Kex *kex, int id, int need, u_char *hash, BIGNUM *shared_secret) { Buffer b; - EVP_MD *evp_md = EVP_sha1(); + const EVP_MD *evp_md = EVP_sha1(); EVP_MD_CTX md; char c = id; int have; - int mdsz = evp_md->md_size; + int mdsz = EVP_MD_size(evp_md); u_char *digest = xmalloc(roundup(need, mdsz)); buffer_init(&b); @@ -457,7 +454,7 @@ dump_digest(char *msg, u_char *digest, int len) int i; fprintf(stderr, "%s\n", msg); - for (i = 0; i< len; i++){ + for (i = 0; i< len; i++) { fprintf(stderr, "%02x", digest[i]); if (i%32 == 31) fprintf(stderr, "\n"); diff --git a/openssh/kex.h b/openssh/kex.h index 0fde811..71ae3b3 100644 --- a/openssh/kex.h +++ b/openssh/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.26 2001/06/26 17:27:23 markus Exp $ */ +/* $OpenBSD: kex.h,v 1.29 2002/02/14 23:41:01 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -72,6 +72,8 @@ struct Enc { char *name; Cipher *cipher; int enabled; + u_int key_len; + u_int block_size; u_char *key; u_char *iv; }; @@ -123,7 +125,7 @@ Kex *kex_setup(char *[PROPOSAL_MAX]); void kex_finish(Kex *); void kex_send_kexinit(Kex *); -void kex_input_kexinit(int, int, void *); +void kex_input_kexinit(int, u_int32_t, void *); void kex_derive_keys(Kex *, u_char *, BIGNUM *); void kexdh(Kex *); diff --git a/openssh/key.c b/openssh/key.c index db3a689..c3f6452 100644 --- a/openssh/key.c +++ b/openssh/key.c @@ -32,7 +32,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" -RCSID("$OpenBSD: key.c,v 1.33 2001/10/04 14:34:16 markus Exp $"); +RCSID("$OpenBSD: key.c,v 1.41 2002/02/28 15:46:33 markus Exp $"); #include @@ -60,17 +60,25 @@ key_new(int type) switch (k->type) { case KEY_RSA1: case KEY_RSA: - rsa = RSA_new(); - rsa->n = BN_new(); - rsa->e = BN_new(); + if ((rsa = RSA_new()) == NULL) + fatal("key_new: RSA_new failed"); + if ((rsa->n = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + if ((rsa->e = BN_new()) == NULL) + fatal("key_new: BN_new failed"); k->rsa = rsa; break; case KEY_DSA: - dsa = DSA_new(); - dsa->p = BN_new(); - dsa->q = BN_new(); - dsa->g = BN_new(); - dsa->pub_key = BN_new(); + if ((dsa = DSA_new()) == NULL) + fatal("key_new: DSA_new failed"); + if ((dsa->p = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + if ((dsa->q = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + if ((dsa->g = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + if ((dsa->pub_key = BN_new()) == NULL) + fatal("key_new: BN_new failed"); k->dsa = dsa; break; case KEY_UNSPEC: @@ -88,15 +96,22 @@ key_new_private(int type) switch (k->type) { case KEY_RSA1: case KEY_RSA: - k->rsa->d = BN_new(); - k->rsa->iqmp = BN_new(); - k->rsa->q = BN_new(); - k->rsa->p = BN_new(); - k->rsa->dmq1 = BN_new(); - k->rsa->dmp1 = BN_new(); + if ((k->rsa->d = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->iqmp = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->q = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->p = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->dmq1 = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->dmp1 = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); break; case KEY_DSA: - k->dsa->priv_key = BN_new(); + if ((k->dsa->priv_key = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); break; case KEY_UNSPEC: break; @@ -155,13 +170,13 @@ key_equal(Key *a, Key *b) } static u_char* -key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length) +key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length) { - EVP_MD *md = NULL; + const EVP_MD *md = NULL; EVP_MD_CTX ctx; u_char *blob = NULL; u_char *retval = NULL; - int len = 0; + u_int len = 0; int nlen, elen; *dgst_raw_length = 0; @@ -201,8 +216,7 @@ key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length) retval = xmalloc(EVP_MAX_MD_SIZE); EVP_DigestInit(&ctx, md); EVP_DigestUpdate(&ctx, blob, len); - EVP_DigestFinal(&ctx, retval, NULL); - *dgst_raw_length = md->md_size; + EVP_DigestFinal(&ctx, retval, dgst_raw_length); memset(blob, 0, len); xfree(blob); } else { @@ -212,14 +226,14 @@ key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length) } static char* -key_fingerprint_hex(u_char* dgst_raw, size_t dgst_raw_len) +key_fingerprint_hex(u_char* dgst_raw, u_int dgst_raw_len) { char *retval; int i; retval = xmalloc(dgst_raw_len * 3 + 1); retval[0] = '\0'; - for(i = 0; i < dgst_raw_len; i++) { + for (i = 0; i < dgst_raw_len; i++) { char hex[4]; snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); strlcat(retval, hex, dgst_raw_len * 3); @@ -229,7 +243,7 @@ key_fingerprint_hex(u_char* dgst_raw, size_t dgst_raw_len) } static char* -key_fingerprint_bubblebabble(u_char* dgst_raw, size_t dgst_raw_len) +key_fingerprint_bubblebabble(u_char* dgst_raw, u_int dgst_raw_len) { char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', @@ -280,12 +294,12 @@ key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) { char *retval = NULL; u_char *dgst_raw; - size_t dgst_raw_len; - + u_int dgst_raw_len; + dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len); if (!dgst_raw) fatal("key_fingerprint: null from key_fingerprint_raw()"); - switch(dgst_rep) { + switch (dgst_rep) { case SSH_FP_HEX: retval = key_fingerprint_hex(dgst_raw, dgst_raw_len); break; @@ -371,7 +385,7 @@ key_read(Key *ret, char **cpp) cp = *cpp; - switch(ret->type) { + switch (ret->type) { case KEY_RSA1: /* Get number of bits. */ if (*cp < '0' || *cp > '9') @@ -420,14 +434,15 @@ key_read(Key *ret, char **cpp) n = uudecode(cp, blob, len); if (n < 0) { error("key_read: uudecode %s failed", cp); + xfree(blob); return -1; } k = key_from_blob(blob, n); + xfree(blob); if (k == NULL) { error("key_read: key_from_blob %s failed", cp); return -1; } - xfree(blob); if (k->type != type) { error("key_read: type mismatch: encoding error"); key_free(k); @@ -454,9 +469,9 @@ key_read(Key *ret, char **cpp) #endif } /*XXXX*/ + key_free(k); if (success != 1) break; - key_free(k); /* advance cp: skip whitespace and data */ while (*cp == ' ' || *cp == '\t') cp++; @@ -473,8 +488,9 @@ key_read(Key *ret, char **cpp) int key_write(Key *key, FILE *f) { - int success = 0; - u_int bits = 0; + int n, success = 0; + u_int len, bits = 0; + u_char *blob, *uu; if (key->type == KEY_RSA1 && key->rsa != NULL) { /* size of modulus 'n' */ @@ -488,8 +504,6 @@ key_write(Key *key, FILE *f) } } else if ((key->type == KEY_DSA && key->dsa != NULL) || (key->type == KEY_RSA && key->rsa != NULL)) { - int len, n; - u_char *blob, *uu; key_to_blob(key, &blob, &len); uu = xmalloc(2*len); n = uuencode(blob, len, uu, 2*len); @@ -532,7 +546,8 @@ key_ssh_name(Key *k) return "ssh-unknown"; } u_int -key_size(Key *k){ +key_size(Key *k) +{ switch (k->type) { case KEY_RSA1: case KEY_RSA: @@ -615,15 +630,15 @@ key_from_private(Key *k) int key_type_from_name(char *name) { - if (strcmp(name, "rsa1") == 0){ + if (strcmp(name, "rsa1") == 0) { return KEY_RSA1; - } else if (strcmp(name, "rsa") == 0){ + } else if (strcmp(name, "rsa") == 0) { return KEY_RSA; - } else if (strcmp(name, "dsa") == 0){ + } else if (strcmp(name, "dsa") == 0) { return KEY_DSA; - } else if (strcmp(name, "ssh-rsa") == 0){ + } else if (strcmp(name, "ssh-rsa") == 0) { return KEY_RSA; - } else if (strcmp(name, "ssh-dss") == 0){ + } else if (strcmp(name, "ssh-dss") == 0) { return KEY_DSA; } else if (strcmp(name, "null") == 0){ return KEY_NULL; @@ -641,7 +656,7 @@ key_names_valid2(const char *names) return 0; s = cp = xstrdup(names); for ((p = strsep(&cp, ",")); p && *p != '\0'; - (p = strsep(&cp, ","))) { + (p = strsep(&cp, ","))) { switch (key_type_from_name(p)) { case KEY_RSA1: case KEY_UNSPEC: @@ -670,7 +685,7 @@ key_from_blob(u_char *blob, int blen) ktype = buffer_get_string(&b, NULL); type = key_type_from_name(ktype); - switch(type){ + switch (type) { case KEY_RSA: key = key_new(type); buffer_get_bignum2(&b, key->rsa->e); @@ -716,7 +731,7 @@ key_to_blob(Key *key, u_char **blobp, u_int *lenp) return 0; } buffer_init(&b); - switch(key->type){ + switch (key->type) { case KEY_DSA: buffer_put_cstring(&b, key_ssh_name(key)); buffer_put_bignum2(&b, key->dsa->p); @@ -749,10 +764,10 @@ key_to_blob(Key *key, u_char **blobp, u_int *lenp) int key_sign( Key *key, - u_char **sigp, int *lenp, - u_char *data, int datalen) + u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) { - switch(key->type){ + switch (key->type) { case KEY_DSA: return ssh_dss_sign(key, sigp, lenp, data, datalen); break; @@ -769,13 +784,13 @@ key_sign( int key_verify( Key *key, - u_char *signature, int signaturelen, - u_char *data, int datalen) + u_char *signature, u_int signaturelen, + u_char *data, u_int datalen) { if (signaturelen == 0) return -1; - switch(key->type){ + switch (key->type) { case KEY_DSA: return ssh_dss_verify(key, signature, signaturelen, data, datalen); break; diff --git a/openssh/key.h b/openssh/key.h index 6a878d8..7b4d1c2 100644 --- a/openssh/key.h +++ b/openssh/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.17 2001/09/17 19:27:15 stevesk Exp $ */ +/* $OpenBSD: key.h,v 1.18 2002/02/24 19:14:59 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -75,7 +75,7 @@ int key_to_blob(Key *, u_char **, u_int *); char *key_ssh_name(Key *); int key_names_valid2(const char *); -int key_sign(Key *, u_char **, int *, u_char *, int); -int key_verify(Key *, u_char *, int, u_char *, int); +int key_sign(Key *, u_char **, u_int *, u_char *, u_int); +int key_verify(Key *, u_char *, u_int, u_char *, u_int); #endif diff --git a/openssh/readconf.c b/openssh/readconf.c index 1f35670..8469422 100644 --- a/openssh/readconf.c +++ b/openssh/readconf.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: readconf.c,v 1.91 2001/10/01 21:51:16 markus Exp $"); +RCSID("$OpenBSD: readconf.c,v 1.95 2002/02/04 12:15:25 markus Exp $"); #include "ssh.h" #include "xmalloc.h" @@ -121,7 +121,7 @@ typedef enum { oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, - oClearAllForwardings, oNoHostAuthenticationForLocalhost + oClearAllForwardings, oNoHostAuthenticationForLocalhost } OpCodes; /* Textual representations of the tokens. */ @@ -200,9 +200,9 @@ static struct { { "hostkeyalgorithms", oHostKeyAlgorithms }, { "bindaddress", oBindAddress }, { "smartcarddevice", oSmartcardDevice }, - { "clearallforwardings", oClearAllForwardings }, - { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, - { NULL, 0 } + { "clearallforwardings", oClearAllForwardings }, + { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, + { NULL, oBadOption } }; /* @@ -240,7 +240,7 @@ add_remote_forward(Options *options, u_short port, const char *host, Forward *fwd; if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) fatal("Too many remote forwards (max %d).", - SSH_MAX_FORWARDS_PER_DIRECTION); + SSH_MAX_FORWARDS_PER_DIRECTION); fwd = &options->remote_forwards[options->num_remote_forwards++]; fwd->port = port; fwd->host = xstrdup(host); @@ -426,7 +426,7 @@ parse_flag: arg = strdelim(&s); if (!arg || *arg == '\0') fatal("%.200s line %d: Missing yes/no/ask argument.", - filename, linenum); + filename, linenum); value = 0; /* To avoid compiler warning... */ if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) value = 1; @@ -468,7 +468,7 @@ parse_flag: intptr = &options->num_identity_files; if (*intptr >= SSH_MAX_IDENTITY_FILES) fatal("%.200s line %d: Too many identity files specified (max %d).", - filename, linenum, SSH_MAX_IDENTITY_FILES); + filename, linenum, SSH_MAX_IDENTITY_FILES); charptr = &options->identity_files[*intptr]; *charptr = xstrdup(arg); *intptr = *intptr + 1; @@ -568,7 +568,7 @@ parse_int: value = cipher_number(arg); if (value == -1) fatal("%.200s line %d: Bad cipher '%s'.", - filename, linenum, arg ? arg : ""); + filename, linenum, arg ? arg : ""); if (*activep && *intptr == -1) *intptr = value; break; @@ -579,7 +579,7 @@ parse_int: fatal("%.200s line %d: Missing argument.", filename, linenum); if (!ciphers_valid(arg)) fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", - filename, linenum, arg ? arg : ""); + filename, linenum, arg ? arg : ""); if (*activep && options->ciphers == NULL) options->ciphers = xstrdup(arg); break; @@ -590,7 +590,7 @@ parse_int: fatal("%.200s line %d: Missing argument.", filename, linenum); if (!mac_valid(arg)) fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.", - filename, linenum, arg ? arg : ""); + filename, linenum, arg ? arg : ""); if (*activep && options->macs == NULL) options->macs = xstrdup(arg); break; @@ -601,7 +601,7 @@ parse_int: fatal("%.200s line %d: Missing argument.", filename, linenum); if (!key_names_valid2(arg)) fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.", - filename, linenum, arg ? arg : ""); + filename, linenum, arg ? arg : ""); if (*activep && options->hostkeyalgorithms == NULL) options->hostkeyalgorithms = xstrdup(arg); break; @@ -614,7 +614,7 @@ parse_int: value = proto_spec(arg); if (value == SSH_PROTO_UNKNOWN) fatal("%.200s line %d: Bad protocol spec '%s'.", - filename, linenum, arg ? arg : ""); + filename, linenum, arg ? arg : ""); if (*activep && *intptr == SSH_PROTO_UNKNOWN) *intptr = value; break; @@ -623,10 +623,10 @@ parse_int: intptr = (int *) &options->log_level; arg = strdelim(&s); value = log_level_number(arg); - if (value == (LogLevel) - 1) + if (value == SYSLOG_LEVEL_NOT_SET) fatal("%.200s line %d: unsupported log level '%s'", - filename, linenum, arg ? arg : ""); - if (*activep && (LogLevel) * intptr == -1) + filename, linenum, arg ? arg : ""); + if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET) *intptr = (LogLevel) value; break; @@ -702,7 +702,7 @@ parse_int: value = SSH_ESCAPECHAR_NONE; else { fatal("%.200s line %d: Bad escape character.", - filename, linenum); + filename, linenum); /* NOTREACHED */ value = 0; /* Avoid compiler warning. */ } @@ -717,7 +717,7 @@ parse_int: /* Check that there is no garbage at end of line. */ if ((arg = strdelim(&s)) != NULL && *arg != '\0') { fatal("%.200s line %d: garbage at end of line; \"%.200s\".", - filename, linenum, arg); + filename, linenum, arg); } return 0; } @@ -759,7 +759,7 @@ read_config_file(const char *filename, const char *host, Options *options) fclose(f); if (bad_options > 0) fatal("%s: terminating, %d bad configuration options", - filename, bad_options); + filename, bad_options); return 1; } @@ -834,7 +834,7 @@ initialize_options(Options * options) options->num_local_forwards = 0; options->num_remote_forwards = 0; options->clear_forwardings = -1; - options->log_level = (LogLevel) - 1; + options->log_level = SYSLOG_LEVEL_NOT_SET; options->preferred_authentications = NULL; options->bind_address = NULL; options->smartcard_device = NULL; @@ -855,10 +855,8 @@ fill_default_options(Options * options) options->forward_agent = 0; if (options->forward_x11 == -1) options->forward_x11 = 0; -#ifdef _PATH_XAUTH if (options->xauth_location == NULL) options->xauth_location = _PATH_XAUTH; -#endif if (options->gateway_ports == -1) options->gateway_ports = 0; if (options->use_privileged_port == -1) @@ -963,7 +961,7 @@ fill_default_options(Options * options) options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2; if (options->user_hostfile2 == NULL) options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2; - if (options->log_level == (LogLevel) - 1) + if (options->log_level == SYSLOG_LEVEL_NOT_SET) options->log_level = SYSLOG_LEVEL_INFO; if (options->clear_forwardings == 1) clear_forwardings(options); diff --git a/openssh/readconf.h b/openssh/readconf.h index 6a3823b..78eb92a 100644 --- a/openssh/readconf.h +++ b/openssh/readconf.h @@ -1,3 +1,5 @@ +/* $OpenBSD: readconf.h,v 1.42 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,8 +13,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: readconf.h,v 1.40 2001/10/01 21:51:16 markus Exp $"); */ - #ifndef READCONF_H #define READCONF_H @@ -90,7 +90,7 @@ typedef struct { char *user; /* User to log in as. */ int escape_char; /* Escape character; -2 = none */ - char *system_hostfile;/* Path for /etc/ssh_known_hosts. */ + char *system_hostfile;/* Path for /etc/ssh/ssh_known_hosts. */ char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */ char *system_hostfile2; char *user_hostfile2; diff --git a/openssh/servconf.c b/openssh/servconf.c index 461da8d..0c22e30 100644 --- a/openssh/servconf.c +++ b/openssh/servconf.c @@ -10,7 +10,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: servconf.c,v 1.91 2001/11/12 18:17:07 markus Exp $"); +RCSID("$OpenBSD: servconf.c,v 1.101 2002/02/04 12:15:25 markus Exp $"); #if defined(KRB4) #include @@ -72,11 +72,12 @@ initialize_server_options(ServerOptions *options) options->print_lastlog = -1; options->x11_forwarding = -1; options->x11_display_offset = -1; + options->x11_use_localhost = -1; options->xauth_location = NULL; options->strict_modes = -1; options->keepalives = -1; - options->log_facility = (SyslogFacility) - 1; - options->log_level = (LogLevel) - 1; + options->log_facility = SYSLOG_FACILITY_NOT_SET; + options->log_level = SYSLOG_LEVEL_NOT_SET; options->rhosts_authentication = -1; options->rhosts_rsa_authentication = -1; options->hostbased_authentication = -1; @@ -119,7 +120,7 @@ initialize_server_options(ServerOptions *options) options->max_startups_rate = -1; options->max_startups = -1; options->banner = NULL; - options->reverse_mapping_check = -1; + options->verify_reverse_mapping = -1; options->client_alive_interval = -1; options->client_alive_count_max = -1; options->authorized_keys_file = NULL; @@ -139,9 +140,14 @@ fill_default_server_options(ServerOptions *options) if (options->num_host_key_files == 0) { /* fill default hostkeys for protocols */ if (options->protocol & SSH_PROTO_1) - options->host_key_files[options->num_host_key_files++] = _PATH_HOST_KEY_FILE; - if (options->protocol & SSH_PROTO_2) - options->host_key_files[options->num_host_key_files++] = _PATH_HOST_DSA_KEY_FILE; + options->host_key_files[options->num_host_key_files++] = + _PATH_HOST_KEY_FILE; + if (options->protocol & SSH_PROTO_2) { + options->host_key_files[options->num_host_key_files++] = + _PATH_HOST_RSA_KEY_FILE; + options->host_key_files[options->num_host_key_files++] = + _PATH_HOST_DSA_KEY_FILE; + } } if (options->num_ports == 0) options->ports[options->num_ports++] = SSH_DEFAULT_PORT; @@ -169,17 +175,17 @@ fill_default_server_options(ServerOptions *options) options->x11_forwarding = 0; if (options->x11_display_offset == -1) options->x11_display_offset = 10; -#ifdef _PATH_XAUTH + if (options->x11_use_localhost == -1) + options->x11_use_localhost = 1; if (options->xauth_location == NULL) options->xauth_location = _PATH_XAUTH; -#endif if (options->strict_modes == -1) options->strict_modes = 1; if (options->keepalives == -1) options->keepalives = 1; - if (options->log_facility == (SyslogFacility) (-1)) + if (options->log_facility == SYSLOG_FACILITY_NOT_SET) options->log_facility = SYSLOG_FACILITY_AUTH; - if (options->log_level == (LogLevel) (-1)) + if (options->log_level == SYSLOG_LEVEL_NOT_SET) options->log_level = SYSLOG_LEVEL_INFO; if (options->rhosts_authentication == -1) options->rhosts_authentication = 0; @@ -215,7 +221,7 @@ fill_default_server_options(ServerOptions *options) if (options->kerberos_tgt_passing == -1) options->kerberos_tgt_passing = 0; #endif -#ifdef AFS +#ifdef AFS if (options->afs_token_passing == -1) options->afs_token_passing = k_hasafs(); #endif @@ -239,10 +245,10 @@ fill_default_server_options(ServerOptions *options) options->max_startups_rate = 100; /* 100% */ if (options->max_startups_begin == -1) options->max_startups_begin = options->max_startups; - if (options->reverse_mapping_check == -1) - options->reverse_mapping_check = 0; + if (options->verify_reverse_mapping == -1) + options->verify_reverse_mapping = 0; if (options->client_alive_interval == -1) - options->client_alive_interval = 0; + options->client_alive_interval = 0; if (options->client_alive_count_max == -1) options->client_alive_count_max = 3; if (options->authorized_keys_file2 == NULL) { @@ -280,16 +286,16 @@ typedef enum { sChallengeResponseAuthentication, sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sPrintMotd, sPrintLastLog, sIgnoreRhosts, - sX11Forwarding, sX11DisplayOffset, + sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, sStrictModes, sEmptyPasswd, sKeepAlives, sUseLogin, sAllowTcpForwarding, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups, - sBanner, sReverseMappingCheck, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, + sBanner, sVerifyReverseMapping, sHostbasedAuthentication, + sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, - sDeprecated + sDeprecated } ServerOpCodes; /* Textual representation of the tokens. */ @@ -347,6 +353,7 @@ static struct { { "ignoreuserknownhosts", sIgnoreUserKnownHosts }, { "x11forwarding", sX11Forwarding }, { "x11displayoffset", sX11DisplayOffset }, + { "x11uselocalhost", sX11UseLocalhost }, { "xauthlocation", sXAuthLocation }, { "strictmodes", sStrictModes }, { "permitemptypasswords", sEmptyPasswd }, @@ -364,12 +371,13 @@ static struct { { "subsystem", sSubsystem }, { "maxstartups", sMaxStartups }, { "banner", sBanner }, - { "reversemappingcheck", sReverseMappingCheck }, + { "verifyreversemapping", sVerifyReverseMapping }, + { "reversemappingcheck", sVerifyReverseMapping }, { "clientaliveinterval", sClientAliveInterval }, { "clientalivecountmax", sClientAliveCountMax }, { "authorizedkeysfile", sAuthorizedKeysFile }, { "authorizedkeysfile2", sAuthorizedKeysFile2 }, - { NULL, 0 } + { NULL, sBadOption } }; /* @@ -427,501 +435,516 @@ add_one_listen_addr(ServerOptions *options, char *addr, u_short port) options->listen_addrs = aitop; } -/* Reads the server configuration file. */ - -void -read_server_config(ServerOptions *options, const char *filename) +int +process_server_config_line(ServerOptions *options, char *line, + const char *filename, int linenum) { - FILE *f; - char line[1024]; char *cp, **charptr, *arg, *p; - int linenum, *intptr, value; - int bad_options = 0; + int *intptr, value; ServerOpCodes opcode; int i, n; - f = fopen(filename, "r"); - if (!f) { - perror(filename); - exit(1); - } - linenum = 0; - while (fgets(line, sizeof(line), f)) { - linenum++; - cp = line; + cp = line; + arg = strdelim(&cp); + /* Ignore leading whitespace */ + if (*arg == '\0') arg = strdelim(&cp); - /* Ignore leading whitespace */ - if (*arg == '\0') - arg = strdelim(&cp); - if (!arg || !*arg || *arg == '#') - continue; - intptr = NULL; - charptr = NULL; - opcode = parse_token(arg, filename, linenum); - switch (opcode) { - case sBadOption: - bad_options++; - continue; - - /* Portable-specific options */ - case sPAMAuthenticationViaKbdInt: - intptr = &options->pam_authentication_via_kbd_int; - goto parse_flag; - - /* Standard Options */ - case sPort: - /* ignore ports from configfile if cmdline specifies ports */ - if (options->ports_from_cmdline) - continue; - if (options->listen_addrs != NULL) - fatal("%s line %d: ports must be specified before " - "ListenAdress.", filename, linenum); - if (options->num_ports >= MAX_PORTS) - fatal("%s line %d: too many ports.", - filename, linenum); - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing port number.", - filename, linenum); - options->ports[options->num_ports++] = a2port(arg); - if (options->ports[options->num_ports-1] == 0) - fatal("%s line %d: Badly formatted port number.", - filename, linenum); - break; + if (!arg || !*arg || *arg == '#') + return 0; + intptr = NULL; + charptr = NULL; + opcode = parse_token(arg, filename, linenum); + switch (opcode) { + /* Portable-specific options */ + case sPAMAuthenticationViaKbdInt: + intptr = &options->pam_authentication_via_kbd_int; + goto parse_flag; - case sServerKeyBits: - intptr = &options->server_key_bits; + /* Standard Options */ + case sBadOption: + return -1; + case sPort: + /* ignore ports from configfile if cmdline specifies ports */ + if (options->ports_from_cmdline) + return 0; + if (options->listen_addrs != NULL) + fatal("%s line %d: ports must be specified before " + "ListenAddress.", filename, linenum); + if (options->num_ports >= MAX_PORTS) + fatal("%s line %d: too many ports.", + filename, linenum); + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing port number.", + filename, linenum); + options->ports[options->num_ports++] = a2port(arg); + if (options->ports[options->num_ports-1] == 0) + fatal("%s line %d: Badly formatted port number.", + filename, linenum); + break; + + case sServerKeyBits: + intptr = &options->server_key_bits; parse_int: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing integer value.", - filename, linenum); - value = atoi(arg); - if (*intptr == -1) - *intptr = value; - break; - - case sLoginGraceTime: - intptr = &options->login_grace_time; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing integer value.", + filename, linenum); + value = atoi(arg); + if (*intptr == -1) + *intptr = value; + break; + + case sLoginGraceTime: + intptr = &options->login_grace_time; parse_time: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing time value.", - filename, linenum); - if ((value = convtime(arg)) == -1) - fatal("%s line %d: invalid time value.", + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing time value.", + filename, linenum); + if ((value = convtime(arg)) == -1) + fatal("%s line %d: invalid time value.", + filename, linenum); + if (*intptr == -1) + *intptr = value; + break; + + case sKeyRegenerationTime: + intptr = &options->key_regeneration_time; + goto parse_time; + + case sListenAddress: + arg = strdelim(&cp); + if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0) + fatal("%s line %d: missing inet addr.", + filename, linenum); + if (*arg == '[') { + if ((p = strchr(arg, ']')) == NULL) + fatal("%s line %d: bad ipv6 inet addr usage.", filename, linenum); - if (*intptr == -1) - *intptr = value; + arg++; + memmove(p, p+1, strlen(p+1)+1); + } else if (((p = strchr(arg, ':')) == NULL) || + (strchr(p+1, ':') != NULL)) { + add_listen_addr(options, arg, 0); break; + } + if (*p == ':') { + u_short port; - case sKeyRegenerationTime: - intptr = &options->key_regeneration_time; - goto parse_time; - - case sListenAddress: - arg = strdelim(&cp); - if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0) - fatal("%s line %d: missing inet addr.", + p++; + if (*p == '\0') + fatal("%s line %d: bad inet addr:port usage.", filename, linenum); - if (*arg == '[') { - if ((p = strchr(arg, ']')) == NULL) - fatal("%s line %d: bad ipv6 inet addr usage.", + else { + *(p-1) = '\0'; + if ((port = a2port(p)) == 0) + fatal("%s line %d: bad port number.", filename, linenum); - arg++; - memmove(p, p+1, strlen(p+1)+1); - } else if (((p = strchr(arg, ':')) == NULL) || - (strchr(p+1, ':') != NULL)) { - add_listen_addr(options, arg, 0); - break; + add_listen_addr(options, arg, port); } - if (*p == ':') { - u_short port; - - p++; - if (*p == '\0') - fatal("%s line %d: bad inet addr:port usage.", - filename, linenum); - else { - *(p-1) = '\0'; - if ((port = a2port(p)) == 0) - fatal("%s line %d: bad port number.", - filename, linenum); - add_listen_addr(options, arg, port); - } - } else if (*p == '\0') - add_listen_addr(options, arg, 0); - else - fatal("%s line %d: bad inet addr usage.", - filename, linenum); - break; - - case sHostKeyFile: - intptr = &options->num_host_key_files; - if (*intptr >= MAX_HOSTKEYS) - fatal("%s line %d: too many host keys specified (max %d).", - filename, linenum, MAX_HOSTKEYS); - charptr = &options->host_key_files[*intptr]; + } else if (*p == '\0') + add_listen_addr(options, arg, 0); + else + fatal("%s line %d: bad inet addr usage.", + filename, linenum); + break; + + case sHostKeyFile: + intptr = &options->num_host_key_files; + if (*intptr >= MAX_HOSTKEYS) + fatal("%s line %d: too many host keys specified (max %d).", + filename, linenum, MAX_HOSTKEYS); + charptr = &options->host_key_files[*intptr]; parse_filename: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing file name.", - filename, linenum); - if (*charptr == NULL) { - *charptr = tilde_expand_filename(arg, getuid()); - /* increase optional counter */ - if (intptr != NULL) - *intptr = *intptr + 1; - } - break; - - case sPidFile: - charptr = &options->pid_file; - goto parse_filename; - - case sPermitRootLogin: - intptr = &options->permit_root_login; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/" - "without-password/forced-commands-only/no " - "argument.", filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "without-password") == 0) - value = PERMIT_NO_PASSWD; - else if (strcmp(arg, "forced-commands-only") == 0) - value = PERMIT_FORCED_ONLY; - else if (strcmp(arg, "yes") == 0) - value = PERMIT_YES; - else if (strcmp(arg, "no") == 0) - value = PERMIT_NO; - else - fatal("%s line %d: Bad yes/" - "without-password/forced-commands-only/no " - "argument: %s", filename, linenum, arg); - if (*intptr == -1) - *intptr = value; - break; - - case sIgnoreRhosts: - intptr = &options->ignore_rhosts; -parse_flag: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/no argument.", - filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "yes") == 0) - value = 1; - else if (strcmp(arg, "no") == 0) - value = 0; - else - fatal("%s line %d: Bad yes/no argument: %s", - filename, linenum, arg); - if (*intptr == -1) - *intptr = value; - break; - - case sIgnoreUserKnownHosts: - intptr = &options->ignore_user_known_hosts; - goto parse_flag; - - case sRhostsAuthentication: - intptr = &options->rhosts_authentication; - goto parse_flag; - - case sRhostsRSAAuthentication: - intptr = &options->rhosts_rsa_authentication; - goto parse_flag; - - case sHostbasedAuthentication: - intptr = &options->hostbased_authentication; - goto parse_flag; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing file name.", + filename, linenum); + if (*charptr == NULL) { + *charptr = tilde_expand_filename(arg, getuid()); + /* increase optional counter */ + if (intptr != NULL) + *intptr = *intptr + 1; + } + break; - case sHostbasedUsesNameFromPacketOnly: - intptr = &options->hostbased_uses_name_from_packet_only; - goto parse_flag; + case sPidFile: + charptr = &options->pid_file; + goto parse_filename; - case sRSAAuthentication: - intptr = &options->rsa_authentication; - goto parse_flag; + case sPermitRootLogin: + intptr = &options->permit_root_login; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing yes/" + "without-password/forced-commands-only/no " + "argument.", filename, linenum); + value = 0; /* silence compiler */ + if (strcmp(arg, "without-password") == 0) + value = PERMIT_NO_PASSWD; + else if (strcmp(arg, "forced-commands-only") == 0) + value = PERMIT_FORCED_ONLY; + else if (strcmp(arg, "yes") == 0) + value = PERMIT_YES; + else if (strcmp(arg, "no") == 0) + value = PERMIT_NO; + else + fatal("%s line %d: Bad yes/" + "without-password/forced-commands-only/no " + "argument: %s", filename, linenum, arg); + if (*intptr == -1) + *intptr = value; + break; - case sPubkeyAuthentication: - intptr = &options->pubkey_authentication; - goto parse_flag; #ifdef GSSAPI - case sGssAuthentication: - intptr = &options->gss_authentication; - goto parse_flag; - case sGssKeyEx: - intptr = &options->gss_keyex; - goto parse_flag; - case sGssUseSessionCredCache: - intptr = &options->gss_use_session_ccache; - goto parse_flag; - case sGssCleanupCreds: - intptr = &options->gss_cleanup_creds; - goto parse_flag; + case sGssAuthentication: + intptr = &options->gss_authentication; + goto parse_flag; + case sGssKeyEx: + intptr = &options->gss_keyex; + goto parse_flag; + case sGssUseSessionCredCache: + intptr = &options->gss_use_session_ccache; + goto parse_flag; + case sGssCleanupCreds: + intptr = &options->gss_cleanup_creds; + goto parse_flag; #endif + + case sIgnoreRhosts: + intptr = &options->ignore_rhosts; +parse_flag: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing yes/no argument.", + filename, linenum); + value = 0; /* silence compiler */ + if (strcmp(arg, "yes") == 0) + value = 1; + else if (strcmp(arg, "no") == 0) + value = 0; + else + fatal("%s line %d: Bad yes/no argument: %s", + filename, linenum, arg); + if (*intptr == -1) + *intptr = value; + break; + + case sIgnoreUserKnownHosts: + intptr = &options->ignore_user_known_hosts; + goto parse_flag; + + case sRhostsAuthentication: + intptr = &options->rhosts_authentication; + goto parse_flag; + + case sRhostsRSAAuthentication: + intptr = &options->rhosts_rsa_authentication; + goto parse_flag; + + case sHostbasedAuthentication: + intptr = &options->hostbased_authentication; + goto parse_flag; + + case sHostbasedUsesNameFromPacketOnly: + intptr = &options->hostbased_uses_name_from_packet_only; + goto parse_flag; + + case sRSAAuthentication: + intptr = &options->rsa_authentication; + goto parse_flag; + + case sPubkeyAuthentication: + intptr = &options->pubkey_authentication; + goto parse_flag; #if defined(KRB4) || defined(KRB5) - case sKerberosAuthentication: - intptr = &options->kerberos_authentication; - goto parse_flag; + case sKerberosAuthentication: + intptr = &options->kerberos_authentication; + goto parse_flag; - case sKerberosOrLocalPasswd: - intptr = &options->kerberos_or_local_passwd; - goto parse_flag; + case sKerberosOrLocalPasswd: + intptr = &options->kerberos_or_local_passwd; + goto parse_flag; - case sKerberosTicketCleanup: - intptr = &options->kerberos_ticket_cleanup; - goto parse_flag; + case sKerberosTicketCleanup: + intptr = &options->kerberos_ticket_cleanup; + goto parse_flag; #endif #if defined(AFS) || defined(KRB5) - case sKerberosTgtPassing: - intptr = &options->kerberos_tgt_passing; - goto parse_flag; + case sKerberosTgtPassing: + intptr = &options->kerberos_tgt_passing; + goto parse_flag; #endif #ifdef AFS - case sAFSTokenPassing: - intptr = &options->afs_token_passing; - goto parse_flag; + case sAFSTokenPassing: + intptr = &options->afs_token_passing; + goto parse_flag; #endif - case sPasswordAuthentication: - intptr = &options->password_authentication; - goto parse_flag; - - case sKbdInteractiveAuthentication: - intptr = &options->kbd_interactive_authentication; - goto parse_flag; - - case sChallengeResponseAuthentication: - intptr = &options->challenge_response_authentication; - goto parse_flag; - - case sPrintMotd: - intptr = &options->print_motd; - goto parse_flag; - - case sPrintLastLog: - intptr = &options->print_lastlog; - goto parse_flag; - - case sX11Forwarding: - intptr = &options->x11_forwarding; - goto parse_flag; - - case sX11DisplayOffset: - intptr = &options->x11_display_offset; - goto parse_int; - - case sXAuthLocation: - charptr = &options->xauth_location; - goto parse_filename; - - case sStrictModes: - intptr = &options->strict_modes; - goto parse_flag; - - case sKeepAlives: - intptr = &options->keepalives; - goto parse_flag; - - case sEmptyPasswd: - intptr = &options->permit_empty_passwd; - goto parse_flag; - - case sUseLogin: - intptr = &options->use_login; - goto parse_flag; - - case sGatewayPorts: - intptr = &options->gateway_ports; - goto parse_flag; - - case sReverseMappingCheck: - intptr = &options->reverse_mapping_check; - goto parse_flag; - - case sLogFacility: - intptr = (int *) &options->log_facility; - arg = strdelim(&cp); - value = log_facility_number(arg); - if (value == (SyslogFacility) - 1) - fatal("%.200s line %d: unsupported log facility '%s'", - filename, linenum, arg ? arg : ""); - if (*intptr == -1) - *intptr = (SyslogFacility) value; - break; + case sPasswordAuthentication: + intptr = &options->password_authentication; + goto parse_flag; - case sLogLevel: - intptr = (int *) &options->log_level; - arg = strdelim(&cp); - value = log_level_number(arg); - if (value == (LogLevel) - 1) - fatal("%.200s line %d: unsupported log level '%s'", - filename, linenum, arg ? arg : ""); - if (*intptr == -1) - *intptr = (LogLevel) value; - break; + case sKbdInteractiveAuthentication: + intptr = &options->kbd_interactive_authentication; + goto parse_flag; - case sAllowTcpForwarding: - intptr = &options->allow_tcp_forwarding; - goto parse_flag; + case sChallengeResponseAuthentication: + intptr = &options->challenge_response_authentication; + goto parse_flag; - case sAllowUsers: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_allow_users >= MAX_ALLOW_USERS) - fatal("%s line %d: too many allow users.", - filename, linenum); - options->allow_users[options->num_allow_users++] = xstrdup(arg); - } - break; + case sPrintMotd: + intptr = &options->print_motd; + goto parse_flag; - case sDenyUsers: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_deny_users >= MAX_DENY_USERS) - fatal( "%s line %d: too many deny users.", - filename, linenum); - options->deny_users[options->num_deny_users++] = xstrdup(arg); - } - break; + case sPrintLastLog: + intptr = &options->print_lastlog; + goto parse_flag; - case sAllowGroups: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_allow_groups >= MAX_ALLOW_GROUPS) - fatal("%s line %d: too many allow groups.", - filename, linenum); - options->allow_groups[options->num_allow_groups++] = xstrdup(arg); - } - break; + case sX11Forwarding: + intptr = &options->x11_forwarding; + goto parse_flag; - case sDenyGroups: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_deny_groups >= MAX_DENY_GROUPS) - fatal("%s line %d: too many deny groups.", - filename, linenum); - options->deny_groups[options->num_deny_groups++] = xstrdup(arg); - } - break; + case sX11DisplayOffset: + intptr = &options->x11_display_offset; + goto parse_int; - case sCiphers: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", filename, linenum); - if (!ciphers_valid(arg)) - fatal("%s line %d: Bad SSH2 cipher spec '%s'.", - filename, linenum, arg ? arg : ""); - if (options->ciphers == NULL) - options->ciphers = xstrdup(arg); - break; + case sX11UseLocalhost: + intptr = &options->x11_use_localhost; + goto parse_flag; - case sMacs: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", filename, linenum); - if (!mac_valid(arg)) - fatal("%s line %d: Bad SSH2 mac spec '%s'.", - filename, linenum, arg ? arg : ""); - if (options->macs == NULL) - options->macs = xstrdup(arg); - break; + case sXAuthLocation: + charptr = &options->xauth_location; + goto parse_filename; - case sProtocol: - intptr = &options->protocol; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", filename, linenum); - value = proto_spec(arg); - if (value == SSH_PROTO_UNKNOWN) - fatal("%s line %d: Bad protocol spec '%s'.", - filename, linenum, arg ? arg : ""); - if (*intptr == SSH_PROTO_UNKNOWN) - *intptr = value; - break; + case sStrictModes: + intptr = &options->strict_modes; + goto parse_flag; - case sSubsystem: - if(options->num_subsystems >= MAX_SUBSYSTEMS) { - fatal("%s line %d: too many subsystems defined.", - filename, linenum); - } - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing subsystem name.", - filename, linenum); - for (i = 0; i < options->num_subsystems; i++) - if(strcmp(arg, options->subsystem_name[i]) == 0) - fatal("%s line %d: Subsystem '%s' already defined.", - filename, linenum, arg); - options->subsystem_name[options->num_subsystems] = xstrdup(arg); - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing subsystem command.", - filename, linenum); - options->subsystem_command[options->num_subsystems] = xstrdup(arg); - options->num_subsystems++; - break; + case sKeepAlives: + intptr = &options->keepalives; + goto parse_flag; - case sMaxStartups: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing MaxStartups spec.", - filename, linenum); - if ((n = sscanf(arg, "%d:%d:%d", - &options->max_startups_begin, - &options->max_startups_rate, - &options->max_startups)) == 3) { - if (options->max_startups_begin > - options->max_startups || - options->max_startups_rate > 100 || - options->max_startups_rate < 1) - fatal("%s line %d: Illegal MaxStartups spec.", - filename, linenum); - } else if (n != 1) - fatal("%s line %d: Illegal MaxStartups spec.", + case sEmptyPasswd: + intptr = &options->permit_empty_passwd; + goto parse_flag; + + case sUseLogin: + intptr = &options->use_login; + goto parse_flag; + + case sGatewayPorts: + intptr = &options->gateway_ports; + goto parse_flag; + + case sVerifyReverseMapping: + intptr = &options->verify_reverse_mapping; + goto parse_flag; + + case sLogFacility: + intptr = (int *) &options->log_facility; + arg = strdelim(&cp); + value = log_facility_number(arg); + if (value == SYSLOG_FACILITY_NOT_SET) + fatal("%.200s line %d: unsupported log facility '%s'", + filename, linenum, arg ? arg : ""); + if (*intptr == -1) + *intptr = (SyslogFacility) value; + break; + + case sLogLevel: + intptr = (int *) &options->log_level; + arg = strdelim(&cp); + value = log_level_number(arg); + if (value == SYSLOG_LEVEL_NOT_SET) + fatal("%.200s line %d: unsupported log level '%s'", + filename, linenum, arg ? arg : ""); + if (*intptr == -1) + *intptr = (LogLevel) value; + break; + + case sAllowTcpForwarding: + intptr = &options->allow_tcp_forwarding; + goto parse_flag; + + case sAllowUsers: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_allow_users >= MAX_ALLOW_USERS) + fatal("%s line %d: too many allow users.", filename, linenum); - else - options->max_startups = options->max_startups_begin; - break; + options->allow_users[options->num_allow_users++] = xstrdup(arg); + } + break; - case sBanner: - charptr = &options->banner; - goto parse_filename; - /* - * These options can contain %X options expanded at - * connect time, so that you can specify paths like: - * - * AuthorizedKeysFile /etc/ssh_keys/%u - */ - case sAuthorizedKeysFile: - case sAuthorizedKeysFile2: - charptr = (opcode == sAuthorizedKeysFile ) ? - &options->authorized_keys_file : - &options->authorized_keys_file2; - goto parse_filename; - - case sClientAliveInterval: - intptr = &options->client_alive_interval; - goto parse_time; - - case sClientAliveCountMax: - intptr = &options->client_alive_count_max; - goto parse_int; - - case sDeprecated: - log("%s line %d: Deprecated option %s", - filename, linenum, arg); - while(arg) - arg = strdelim(&cp); - break; + case sDenyUsers: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_deny_users >= MAX_DENY_USERS) + fatal( "%s line %d: too many deny users.", + filename, linenum); + options->deny_users[options->num_deny_users++] = xstrdup(arg); + } + break; - default: - fatal("%s line %d: Missing handler for opcode %s (%d)", - filename, linenum, arg, opcode); + case sAllowGroups: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_allow_groups >= MAX_ALLOW_GROUPS) + fatal("%s line %d: too many allow groups.", + filename, linenum); + options->allow_groups[options->num_allow_groups++] = xstrdup(arg); + } + break; + + case sDenyGroups: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_deny_groups >= MAX_DENY_GROUPS) + fatal("%s line %d: too many deny groups.", + filename, linenum); + options->deny_groups[options->num_deny_groups++] = xstrdup(arg); } - if ((arg = strdelim(&cp)) != NULL && *arg != '\0') - fatal("%s line %d: garbage at end of line; \"%.200s\".", - filename, linenum, arg); + break; + + case sCiphers: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + if (!ciphers_valid(arg)) + fatal("%s line %d: Bad SSH2 cipher spec '%s'.", + filename, linenum, arg ? arg : ""); + if (options->ciphers == NULL) + options->ciphers = xstrdup(arg); + break; + + case sMacs: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + if (!mac_valid(arg)) + fatal("%s line %d: Bad SSH2 mac spec '%s'.", + filename, linenum, arg ? arg : ""); + if (options->macs == NULL) + options->macs = xstrdup(arg); + break; + + case sProtocol: + intptr = &options->protocol; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + value = proto_spec(arg); + if (value == SSH_PROTO_UNKNOWN) + fatal("%s line %d: Bad protocol spec '%s'.", + filename, linenum, arg ? arg : ""); + if (*intptr == SSH_PROTO_UNKNOWN) + *intptr = value; + break; + + case sSubsystem: + if (options->num_subsystems >= MAX_SUBSYSTEMS) { + fatal("%s line %d: too many subsystems defined.", + filename, linenum); + } + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing subsystem name.", + filename, linenum); + for (i = 0; i < options->num_subsystems; i++) + if (strcmp(arg, options->subsystem_name[i]) == 0) + fatal("%s line %d: Subsystem '%s' already defined.", + filename, linenum, arg); + options->subsystem_name[options->num_subsystems] = xstrdup(arg); + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing subsystem command.", + filename, linenum); + options->subsystem_command[options->num_subsystems] = xstrdup(arg); + options->num_subsystems++; + break; + + case sMaxStartups: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing MaxStartups spec.", + filename, linenum); + if ((n = sscanf(arg, "%d:%d:%d", + &options->max_startups_begin, + &options->max_startups_rate, + &options->max_startups)) == 3) { + if (options->max_startups_begin > + options->max_startups || + options->max_startups_rate > 100 || + options->max_startups_rate < 1) + fatal("%s line %d: Illegal MaxStartups spec.", + filename, linenum); + } else if (n != 1) + fatal("%s line %d: Illegal MaxStartups spec.", + filename, linenum); + else + options->max_startups = options->max_startups_begin; + break; + + case sBanner: + charptr = &options->banner; + goto parse_filename; + /* + * These options can contain %X options expanded at + * connect time, so that you can specify paths like: + * + * AuthorizedKeysFile /etc/ssh_keys/%u + */ + case sAuthorizedKeysFile: + case sAuthorizedKeysFile2: + charptr = (opcode == sAuthorizedKeysFile ) ? + &options->authorized_keys_file : + &options->authorized_keys_file2; + goto parse_filename; + + case sClientAliveInterval: + intptr = &options->client_alive_interval; + goto parse_time; + + case sClientAliveCountMax: + intptr = &options->client_alive_count_max; + goto parse_int; + + case sDeprecated: + log("%s line %d: Deprecated option %s", + filename, linenum, arg); + while (arg) + arg = strdelim(&cp); + break; + + default: + fatal("%s line %d: Missing handler for opcode %s (%d)", + filename, linenum, arg, opcode); + } + if ((arg = strdelim(&cp)) != NULL && *arg != '\0') + fatal("%s line %d: garbage at end of line; \"%.200s\".", + filename, linenum, arg); + return 0; +} + +/* Reads the server configuration file. */ + +void +read_server_config(ServerOptions *options, const char *filename) +{ + FILE *f; + char line[1024]; + int linenum; + int bad_options = 0; + + f = fopen(filename, "r"); + if (!f) { + perror(filename); + exit(1); + } + linenum = 0; + while (fgets(line, sizeof(line), f)) { + /* Update line number counter. */ + linenum++; + if (process_server_config_line(options, line, filename, linenum) != 0) + bad_options++; } fclose(f); if (bad_options > 0) diff --git a/openssh/servconf.h b/openssh/servconf.h index e58e994..ecb3f18 100644 --- a/openssh/servconf.h +++ b/openssh/servconf.h @@ -1,3 +1,5 @@ +/* $OpenBSD: servconf.h,v 1.54 2002/03/04 17:27:39 stevesk Exp $ */ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -11,8 +13,6 @@ * called by a name other than "ssh" or "Secure Shell". */ -/* RCSID("$OpenBSD: servconf.h,v 1.49 2001/08/17 18:59:47 stevesk Exp $"); */ - #ifndef SERVCONF_H #define SERVCONF_H @@ -55,6 +55,7 @@ typedef struct { int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */ int x11_display_offset; /* What DISPLAY number to start * searching at */ + int x11_use_localhost; /* If true, use localhost for fake X11 server. */ char *xauth_location; /* Location of xauth program */ int strict_modes; /* If true, require string home dir modes. */ int keepalives; /* If true, set SO_KEEPALIVE. */ @@ -122,15 +123,15 @@ typedef struct { int max_startups_rate; int max_startups; char *banner; /* SSH-2 banner message */ - int reverse_mapping_check; /* cross-check ip and dns */ + int verify_reverse_mapping; /* cross-check ip and dns */ int client_alive_interval; /* - * poke the client this often to - * see if it's still there + * poke the client this often to + * see if it's still there */ int client_alive_count_max; /* * If the client is unresponsive * for this many intervals above, - * disconnect the session + * disconnect the session */ char *authorized_keys_file; /* File containing public keys */ @@ -142,5 +143,7 @@ typedef struct { void initialize_server_options(ServerOptions *); void read_server_config(ServerOptions *, const char *); void fill_default_server_options(ServerOptions *); +int process_server_config_line(ServerOptions *, char *, const char *, int); + #endif /* SERVCONF_H */ diff --git a/openssh/session.c b/openssh/session.c index d7e4806..f3b3088 100644 --- a/openssh/session.c +++ b/openssh/session.c @@ -33,7 +33,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.108 2001/10/11 13:45:21 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.128 2002/02/16 00:51:44 markus Exp $"); #include "ssh.h" #include "ssh1.h" @@ -81,21 +81,6 @@ RCSID("$OpenBSD: session.c,v 1.108 2001/10/11 13:45:21 markus Exp $"); #define is_winnt (GetVersion() < 0x80000000) #endif -/* AIX limits */ -#if defined(HAVE_GETUSERATTR) && !defined(S_UFSIZE_HARD) && defined(S_UFSIZE) -# define S_UFSIZE_HARD S_UFSIZE "_hard" -# define S_UCPU_HARD S_UCPU "_hard" -# define S_UDATA_HARD S_UDATA "_hard" -# define S_USTACK_HARD S_USTACK "_hard" -# define S_URSS_HARD S_URSS "_hard" -# define S_UCORE_HARD S_UCORE "_hard" -# define S_UNOFILE_HARD S_UNOFILE "_hard" -#endif - -#ifdef _AIX -# include -#endif - /* types */ #define TTYSZ 64 @@ -112,8 +97,10 @@ struct Session { int row, col, xpixel, ypixel; char tty[TTYSZ]; /* X11 */ + int display_number; char *display; int screen; + char *auth_display; char *auth_proto; char *auth_data; int single_connection; @@ -197,7 +184,7 @@ do_authenticated(Authctxt *authctxt) #ifdef WITH_AIXAUTHENTICATE /* We don't have a pty yet, so just label the line as "ssh" */ if (loginsuccess(authctxt->user, - get_canonical_hostname(options.reverse_mapping_check), + get_canonical_hostname(options.verify_reverse_mapping), "ssh", &aixloginmsg) < 0) aixloginmsg = NULL; #endif /* WITH_AIXAUTHENTICATE */ @@ -235,7 +222,7 @@ do_authenticated1(Authctxt *authctxt) { Session *s; char *command; - int success, type, plen, screen_flag; + int success, type, screen_flag; int compression_level = 0, enable_compression_after_reply = 0; u_int proto_len, data_len, dlen; @@ -251,16 +238,16 @@ do_authenticated1(Authctxt *authctxt) success = 0; /* Get a packet from the client. */ - type = packet_read(&plen); + type = packet_read(); /* Process the packet. */ switch (type) { case SSH_CMSG_REQUEST_COMPRESSION: - packet_integrity_check(plen, 4, type); compression_level = packet_get_int(); + packet_check_eom(); if (compression_level < 1 || compression_level > 9) { packet_send_debug("Received illegal compression level %d.", - compression_level); + compression_level); break; } /* Enable compression after we have responded with SUCCESS. */ @@ -288,7 +275,7 @@ do_authenticated1(Authctxt *authctxt) } else { s->screen = 0; } - packet_done(); + packet_check_eom(); success = session_setup_x11fwd(s); if (!success) { xfree(s->auth_proto); @@ -325,22 +312,22 @@ do_authenticated1(Authctxt *authctxt) if (packet_set_maxsize(packet_get_int()) > 0) success = 1; break; - + #if defined(AFS) || defined(KRB5) case SSH_CMSG_HAVE_KERBEROS_TGT: if (!options.kerberos_tgt_passing) { verbose("Kerberos TGT passing disabled."); } else { char *kdata = packet_get_string(&dlen); - packet_integrity_check(plen, 4 + dlen, type); - + packet_check_eom(); + /* XXX - 0x41, see creds_to_radix version */ if (kdata[0] != 0x41) { #ifdef KRB5 krb5_data tgt; tgt.data = kdata; tgt.length = dlen; - + if (auth_krb5_tgt(s->authctxt, &tgt)) success = 1; else @@ -358,7 +345,7 @@ do_authenticated1(Authctxt *authctxt) } break; #endif /* AFS || KRB5 */ - + #ifdef AFS case SSH_CMSG_HAVE_AFS_TOKEN: if (!options.afs_token_passing || !k_hasafs()) { @@ -366,8 +353,8 @@ do_authenticated1(Authctxt *authctxt) } else { /* Accept AFS token. */ char *token = packet_get_string(&dlen); - packet_integrity_check(plen, 4 + dlen, type); - + packet_check_eom(); + if (auth_afs_token(s->authctxt, token)) success = 1; else @@ -388,7 +375,7 @@ do_authenticated1(Authctxt *authctxt) } else { do_exec(s, NULL); } - packet_done(); + packet_check_eom(); session_close(s); return; @@ -663,14 +650,14 @@ do_pre_login(Session *s) if (packet_connection_is_on_socket()) { fromlen = sizeof(from); if (getpeername(packet_get_connection_in(), - (struct sockaddr *) & from, &fromlen) < 0) { + (struct sockaddr *) & from, &fromlen) < 0) { debug("getpeername: %.100s", strerror(errno)); fatal_cleanup(); } } record_utmp_only(pid, s->tty, s->pw->pw_name, - get_remote_name_or_ip(utmp_len, options.reverse_mapping_check), + get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping), (struct sockaddr *)&from); } #endif @@ -696,6 +683,7 @@ do_exec(Session *s, const char *command) original_command = NULL; } + /* administrative, login(1)-like work */ void do_login(Session *s, const char *command) @@ -716,7 +704,7 @@ do_login(Session *s, const char *command) if (packet_connection_is_on_socket()) { fromlen = sizeof(from); if (getpeername(packet_get_connection_in(), - (struct sockaddr *) & from, &fromlen) < 0) { + (struct sockaddr *) & from, &fromlen) < 0) { debug("getpeername: %.100s", strerror(errno)); fatal_cleanup(); } @@ -731,7 +719,7 @@ do_login(Session *s, const char *command) /* Record that there was a login on that tty from the remote host. */ record_login(pid, s->tty, pw->pw_name, pw->pw_uid, - get_remote_name_or_ip(utmp_len, options.reverse_mapping_check), + get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping), (struct sockaddr *)&from); #ifdef USE_PAM @@ -825,7 +813,7 @@ check_quietlogin(Session *s, const char *command) */ void child_set_env(char ***envp, u_int *envsizep, const char *name, - const char *value) + const char *value) { u_int i, namelen; char **env; @@ -866,7 +854,7 @@ child_set_env(char ***envp, u_int *envsizep, const char *name, */ static void read_environment_file(char ***env, u_int *envsize, - const char *filename) + const char *filename) { FILE *f; char buf[4096]; @@ -899,326 +887,36 @@ read_environment_file(char ***env, u_int *envsize, fclose(f); } -#ifdef USE_PAM -/* - * Sets any environment variables which have been specified by PAM - */ -void do_pam_environment(char ***env, u_int *envsize) +void copy_environment(char **source, char ***env, u_int *envsize) { - char *equals, var_name[512], var_val[512]; - char **pam_env; + char *var_name, *var_val; int i; - if ((pam_env = fetch_pam_environment()) == NULL) + if (source == NULL) return; - for(i = 0; pam_env[i] != NULL; i++) { - if ((equals = strstr(pam_env[i], "=")) == NULL) - continue; - - if (strlen(pam_env[i]) < (sizeof(var_name) - 1)) { - memset(var_name, '\0', sizeof(var_name)); - memset(var_val, '\0', sizeof(var_val)); - - strncpy(var_name, pam_env[i], equals - pam_env[i]); - strcpy(var_val, equals + 1); - - debug3("PAM environment: %s=%s", var_name, var_val); - - child_set_env(env, envsize, var_name, var_val); - } - } -} -#endif /* USE_PAM */ - -#ifdef HAVE_CYGWIN -void copy_environment(char ***env, u_int *envsize) -{ - char *equals, var_name[512], var_val[512]; - int i; - - for(i = 0; environ[i] != NULL; i++) { - if ((equals = strstr(environ[i], "=")) == NULL) + for(i = 0; source[i] != NULL; i++) { + var_name = xstrdup(source[i]); + if ((var_val = strstr(var_name, "=")) == NULL) { + xfree(var_name); continue; - - if (strlen(environ[i]) < (sizeof(var_name) - 1)) { - memset(var_name, '\0', sizeof(var_name)); - memset(var_val, '\0', sizeof(var_val)); - - strncpy(var_name, environ[i], equals - environ[i]); - strcpy(var_val, equals + 1); - - debug3("Copy environment: %s=%s", var_name, var_val); - - child_set_env(env, envsize, var_name, var_val); } - } -} -#endif + *var_val++ = '\0'; -#if defined(HAVE_GETUSERATTR) -/* - * AIX-specific login initialisation - */ -void set_limit(char *user, char *soft, char *hard, int resource, int mult) -{ - struct rlimit rlim; - int slim, hlim; - - getrlimit(resource, &rlim); - - slim = 0; - if (getuserattr(user, soft, &slim, SEC_INT) != -1) { - if (slim < 0) { - rlim.rlim_cur = RLIM_INFINITY; - } else if (slim != 0) { - /* See the wackiness below */ - if (rlim.rlim_cur == slim * mult) - slim = 0; - else - rlim.rlim_cur = slim * mult; - } - } - - hlim = 0; - if (getuserattr(user, hard, &hlim, SEC_INT) != -1) { - if (hlim < 0) { - rlim.rlim_max = RLIM_INFINITY; - } else if (hlim != 0) { - rlim.rlim_max = hlim * mult; - } + debug3("Copy environment: %s=%s", var_name, var_val); + child_set_env(env, envsize, var_name, var_val); + + xfree(var_name); } - - /* - * XXX For cpu and fsize the soft limit is set to the hard limit - * if the hard limit is left at its default value and the soft limit - * is changed from its default value, either by requesting it - * (slim == 0) or by setting it to the current default. At least - * that's how rlogind does it. If you're confused you're not alone. - * Bug or feature? AIX 4.3.1.2 - */ - if ((!strcmp(soft, "fsize") || !strcmp(soft, "cpu")) - && hlim == 0 && slim != 0) - rlim.rlim_max = rlim.rlim_cur; - /* A specified hard limit limits the soft limit */ - else if (hlim > 0 && rlim.rlim_cur > rlim.rlim_max) - rlim.rlim_cur = rlim.rlim_max; - /* A soft limit can increase a hard limit */ - else if (rlim.rlim_cur > rlim.rlim_max) - rlim.rlim_max = rlim.rlim_cur; - - if (setrlimit(resource, &rlim) != 0) - error("setrlimit(%.10s) failed: %.100s", soft, strerror(errno)); } -void set_limits_from_userattr(char *user) +static char ** +do_setup_env(Session *s, const char *shell) { - int mask; - char buf[16]; - - set_limit(user, S_UFSIZE, S_UFSIZE_HARD, RLIMIT_FSIZE, 512); - set_limit(user, S_UCPU, S_UCPU_HARD, RLIMIT_CPU, 1); - set_limit(user, S_UDATA, S_UDATA_HARD, RLIMIT_DATA, 512); - set_limit(user, S_USTACK, S_USTACK_HARD, RLIMIT_STACK, 512); - set_limit(user, S_URSS, S_URSS_HARD, RLIMIT_RSS, 512); - set_limit(user, S_UCORE, S_UCORE_HARD, RLIMIT_CORE, 512); -#if defined(S_UNOFILE) - set_limit(user, S_UNOFILE, S_UNOFILE_HARD, RLIMIT_NOFILE, 1); -#endif - - if (getuserattr(user, S_UMASK, &mask, SEC_INT) != -1) { - /* Convert decimal to octal */ - (void) snprintf(buf, sizeof(buf), "%d", mask); - if (sscanf(buf, "%o", &mask) == 1) - umask(mask); - } -} -#endif /* defined(HAVE_GETUSERATTR) */ - -/* - * Performs common processing for the child, such as setting up the - * environment, closing extra file descriptors, setting the user and group - * ids, and executing the command or shell. - */ -void -do_child(Session *s, const char *command) -{ - const char *shell, *hostname = NULL, *cp = NULL; - struct passwd *pw = s->pw; char buf[256]; - char cmd[1024]; - FILE *f = NULL; - u_int envsize, i; + u_int i, envsize; char **env; - extern char **environ; - struct stat st; - char *argv[10]; - int do_xauth; -#ifdef WITH_IRIX_PROJECT - prid_t projid; -#endif /* WITH_IRIX_PROJECT */ -#ifdef WITH_IRIX_JOBS - jid_t jid = 0; -#else -#ifdef WITH_IRIX_ARRAY - int jid = 0; -#endif /* WITH_IRIX_ARRAY */ -#endif /* WITH_IRIX_JOBS */ - - do_xauth = - s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL; - - /* remove hostkey from the child's memory */ - destroy_sensitive_data(); - - /* login(1) is only called if we execute the login shell */ - if (options.use_login && command != NULL) - options.use_login = 0; - -#if !defined(HAVE_OSF_SIA) - if (!options.use_login) { -# ifdef HAVE_LOGIN_CAP - if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid) - f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN, - _PATH_NOLOGIN), "r"); -# else /* HAVE_LOGIN_CAP */ - if (pw->pw_uid) - f = fopen(_PATH_NOLOGIN, "r"); -# endif /* HAVE_LOGIN_CAP */ - if (f) { - /* /etc/nologin exists. Print its contents and exit. */ - while (fgets(buf, sizeof(buf), f)) - fputs(buf, stderr); - fclose(f); - exit(254); - } - } -#endif /* HAVE_OSF_SIA */ - - /* Set login name, uid, gid, and groups. */ - /* Login(1) does this as well, and it needs uid 0 for the "-h" - switch, so we let login(1) to this for us. */ - if (!options.use_login) { -#ifdef HAVE_OSF_SIA - session_setup_sia(pw->pw_name, s->ttyfd == -1 ? NULL : s->tty); - if (!check_quietlogin(s, command)) - do_motd(); -#else /* HAVE_OSF_SIA */ -#ifdef HAVE_CYGWIN - if (is_winnt) { -#else - if (getuid() == 0 || geteuid() == 0) { -#endif -# ifdef HAVE_GETUSERATTR - set_limits_from_userattr(pw->pw_name); -# endif /* HAVE_GETUSERATTR */ -# ifdef HAVE_LOGIN_CAP - if (setusercontext(lc, pw, pw->pw_uid, - (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) { - perror("unable to set user context"); - exit(1); - } -# else /* HAVE_LOGIN_CAP */ -#if defined(HAVE_GETLUID) && defined(HAVE_SETLUID) - /* Sets login uid for accounting */ - if (getluid() == -1 && setluid(pw->pw_uid) == -1) - error("setluid: %s", strerror(errno)); -#endif /* defined(HAVE_GETLUID) && defined(HAVE_SETLUID) */ - - if (setlogin(pw->pw_name) < 0) - error("setlogin failed: %s", strerror(errno)); - if (setgid(pw->pw_gid) < 0) { - perror("setgid"); - exit(1); - } - /* Initialize the group list. */ - if (initgroups(pw->pw_name, pw->pw_gid) < 0) { - perror("initgroups"); - exit(1); - } - endgrent(); - -# ifdef USE_PAM - /* - * PAM credentials may take the form of - * supplementary groups. These will have been - * wiped by the above initgroups() call. - * Reestablish them here. - */ - do_pam_setcred(0); -# endif /* USE_PAM */ -# ifdef WITH_IRIX_JOBS - jid = jlimit_startjob(pw->pw_name, pw->pw_uid, "interactive"); - if (jid == -1) { - fatal("Failed to create job container: %.100s", - strerror(errno)); - } -# endif /* WITH_IRIX_JOBS */ -# ifdef WITH_IRIX_ARRAY - /* initialize array session */ - if (jid == 0) { - if (newarraysess() != 0) - fatal("Failed to set up new array session: %.100s", - strerror(errno)); - } -# endif /* WITH_IRIX_ARRAY */ -# ifdef WITH_IRIX_PROJECT - /* initialize irix project info */ - if ((projid = getdfltprojuser(pw->pw_name)) == -1) { - debug("Failed to get project id, using projid 0"); - projid = 0; - } - if (setprid(projid)) - fatal("Failed to initialize project %d for %s: %.100s", - (int)projid, pw->pw_name, strerror(errno)); -# endif /* WITH_IRIX_PROJECT */ -#ifdef WITH_IRIX_AUDIT - if (sysconf(_SC_AUDIT)) { - debug("Setting sat id to %d", (int) pw->pw_uid); - if (satsetid(pw->pw_uid)) - debug("error setting satid: %.100s", strerror(errno)); - } -#endif /* WITH_IRIX_AUDIT */ - -#ifdef _AIX - /* - * AIX has a "usrinfo" area where logname and - * other stuff is stored - a few applications - * actually use this and die if it's not set - */ - if (s->ttyfd == -1) - s->tty[0] = '\0'; - cp = xmalloc(22 + strlen(s->tty) + - 2 * strlen(pw->pw_name)); - i = sprintf(cp, "LOGNAME=%s%cNAME=%s%cTTY=%s%c%c", - pw->pw_name, 0, pw->pw_name, 0, s->tty, 0, 0); - if (usrinfo(SETUINFO, cp, i) == -1) - fatal("Couldn't set usrinfo: %s", - strerror(errno)); - debug3("AIX/UsrInfo: set len %d", i); - xfree(cp); -#endif - - /* Permanently switch to the desired uid. */ - permanently_set_uid(pw); -# endif /* HAVE_LOGIN_CAP */ - } -#endif /* HAVE_OSF_SIA */ - -#ifdef HAVE_CYGWIN - if (is_winnt) -#endif - if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) - fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); - } - /* - * Get the shell from the password data. An empty shell field is - * legal, and means /bin/sh. - */ - shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; -#ifdef HAVE_LOGIN_CAP - shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); -#endif + struct passwd *pw = s->pw; /* Initialize the environment. */ envsize = 100; @@ -1230,7 +928,7 @@ do_child(Session *s, const char *command) * The Windows environment contains some setting which are * important for a running system. They must not be dropped. */ - copy_environment(&env, &envsize); + copy_environment(environ, &env, &envsize); #endif #ifdef GSSAPI @@ -1275,7 +973,7 @@ do_child(Session *s, const char *command) while (custom_environment) { struct envstring *ce = custom_environment; char *s = ce->s; - int i; + for (i = 0; s[i] != '=' && s[i]; i++) ; if (s[i] == '=') { @@ -1289,7 +987,7 @@ do_child(Session *s, const char *command) } snprintf(buf, sizeof buf, "%.50s %d %d", - get_remote_ipaddr(), get_remote_port(), get_local_port()); + get_remote_ipaddr(), get_remote_port(), get_local_port()); child_set_env(&env, &envsize, "SSH_CLIENT", buf); if (s->ttyfd != -1) @@ -1303,11 +1001,15 @@ do_child(Session *s, const char *command) original_command); #ifdef _AIX - if ((cp = getenv("AUTHSTATE")) != NULL) - child_set_env(&env, &envsize, "AUTHSTATE", cp); - if ((cp = getenv("KRB5CCNAME")) != NULL) - child_set_env(&env, &envsize, "KRB5CCNAME", cp); - read_environment_file(&env, &envsize, "/etc/environment"); + { + char *cp; + + if ((cp = getenv("AUTHSTATE")) != NULL) + child_set_env(&env, &envsize, "AUTHSTATE", cp); + if ((cp = getenv("KRB5CCNAME")) != NULL) + child_set_env(&env, &envsize, "KRB5CCNAME", cp); + read_environment_file(&env, &envsize, "/etc/environment"); + } #endif #ifdef KRB4 if (s->authctxt->krb4_ticket_file) @@ -1321,12 +1023,12 @@ do_child(Session *s, const char *command) #endif #ifdef USE_PAM /* Pull in any environment variables that may have been set by PAM. */ - do_pam_environment(&env, &envsize); + copy_environment(fetch_pam_environment(), &env, &envsize); #endif /* USE_PAM */ if (auth_get_socket_name() != NULL) child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME, - auth_get_socket_name()); + auth_get_socket_name()); /* read $HOME/.ssh/environment. */ if (!options.use_login) { @@ -1340,10 +1042,210 @@ do_child(Session *s, const char *command) for (i = 0; env[i]; i++) fprintf(stderr, " %.200s\n", env[i]); } + return env; +} + +/* + * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found + * first in this order). + */ +static void +do_rc_files(Session *s, const char *shell) +{ + FILE *f = NULL; + char cmd[1024]; + int do_xauth; + struct stat st; + + do_xauth = + s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL; + + /* ignore _PATH_SSH_USER_RC for subsystems */ + if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) { + snprintf(cmd, sizeof cmd, "%s -c '%s %s'", + shell, _PATH_BSHELL, _PATH_SSH_USER_RC); + if (debug_flag) + fprintf(stderr, "Running %s\n", cmd); + f = popen(cmd, "w"); + if (f) { + if (do_xauth) + fprintf(f, "%s %s\n", s->auth_proto, + s->auth_data); + pclose(f); + } else + fprintf(stderr, "Could not run %s\n", + _PATH_SSH_USER_RC); + } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) { + if (debug_flag) + fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, + _PATH_SSH_SYSTEM_RC); + f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w"); + if (f) { + if (do_xauth) + fprintf(f, "%s %s\n", s->auth_proto, + s->auth_data); + pclose(f); + } else + fprintf(stderr, "Could not run %s\n", + _PATH_SSH_SYSTEM_RC); + } else if (do_xauth && options.xauth_location != NULL) { + /* Add authority data to .Xauthority if appropriate. */ + if (debug_flag) { + fprintf(stderr, + "Running %.100s add " + "%.100s %.100s %.100s\n", + options.xauth_location, s->auth_display, + s->auth_proto, s->auth_data); + } + snprintf(cmd, sizeof cmd, "%s -q -", + options.xauth_location); + f = popen(cmd, "w"); + if (f) { + fprintf(f, "add %s %s %s\n", + s->auth_display, s->auth_proto, + s->auth_data); + pclose(f); + } else { + fprintf(stderr, "Could not run %s\n", + cmd); + } + } +} + +static void +do_nologin(struct passwd *pw) +{ + FILE *f = NULL; + char buf[1024]; + +#ifdef HAVE_LOGIN_CAP + if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid) + f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN, + _PATH_NOLOGIN), "r"); +#else + if (pw->pw_uid) + f = fopen(_PATH_NOLOGIN, "r"); +#endif + if (f) { + /* /etc/nologin exists. Print its contents and exit. */ + while (fgets(buf, sizeof(buf), f)) + fputs(buf, stderr); + fclose(f); + exit(254); + } +} + +/* Set login name, uid, gid, and groups. */ +static void +do_setusercontext(struct passwd *pw) +{ +#ifdef HAVE_CYGWIN + if (is_winnt) { +#else /* HAVE_CYGWIN */ + if (getuid() == 0 || geteuid() == 0) { +#endif /* HAVE_CYGWIN */ +#ifdef HAVE_GETUSERATTR + set_limits_from_userattr(pw->pw_name); +#endif /* HAVE_GETUSERATTR */ +#ifdef HAVE_LOGIN_CAP + if (setusercontext(lc, pw, pw->pw_uid, + (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) { + perror("unable to set user context"); + exit(1); + } +#else +# if defined(HAVE_GETLUID) && defined(HAVE_SETLUID) + /* Sets login uid for accounting */ + if (getluid() == -1 && setluid(pw->pw_uid) == -1) + error("setluid: %s", strerror(errno)); +# endif /* defined(HAVE_GETLUID) && defined(HAVE_SETLUID) */ + + if (setlogin(pw->pw_name) < 0) + error("setlogin failed: %s", strerror(errno)); + if (setgid(pw->pw_gid) < 0) { + perror("setgid"); + exit(1); + } + /* Initialize the group list. */ + if (initgroups(pw->pw_name, pw->pw_gid) < 0) { + perror("initgroups"); + exit(1); + } + endgrent(); +# ifdef USE_PAM + /* + * PAM credentials may take the form of supplementary groups. + * These will have been wiped by the above initgroups() call. + * Reestablish them here. + */ + do_pam_setcred(0); +# endif /* USE_PAM */ +# if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) + irix_setusercontext(pw); +# endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */ + /* Permanently switch to the desired uid. */ + permanently_set_uid(pw); +#endif + } + if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) + fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); +} + +/* + * Performs common processing for the child, such as setting up the + * environment, closing extra file descriptors, setting the user and group + * ids, and executing the command or shell. + */ +void +do_child(Session *s, const char *command) +{ + extern char **environ; + char **env; + char *argv[10]; + const char *shell, *shell0, *hostname = NULL; + struct passwd *pw = s->pw; + u_int i; + + /* remove hostkey from the child's memory */ + destroy_sensitive_data(); + + /* login(1) is only called if we execute the login shell */ + if (options.use_login && command != NULL) + options.use_login = 0; + + /* + * Login(1) does this as well, and it needs uid 0 for the "-h" + * switch, so we let login(1) to this for us. + */ + if (!options.use_login) { +#ifdef HAVE_OSF_SIA + session_setup_sia(pw->pw_name, s->ttyfd == -1 ? NULL : s->tty); + if (!check_quietlogin(s, command)) + do_motd(); +#else /* HAVE_OSF_SIA */ + do_nologin(pw); +# ifdef _AIX + aix_usrinfo(pw, s->tty, s->ttyfd); +# endif /* _AIX */ + do_setusercontext(pw); +#endif /* HAVE_OSF_SIA */ + } + + /* + * Get the shell from the password data. An empty shell field is + * legal, and means /bin/sh. + */ + shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; +#ifdef HAVE_LOGIN_CAP + shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); +#endif + + env = do_setup_env(s, shell); + /* we have to stash the hostname before we close our socket. */ if (options.use_login) hostname = get_remote_name_or_ip(utmp_len, - options.reverse_mapping_check); + options.verify_reverse_mapping); /* * Close the connection descriptors; note that this is the child, and * the server will still have the socket open, and it is important @@ -1380,8 +1282,8 @@ do_child(Session *s, const char *command) close(i); /* - * Must take new environment into use so that .ssh/rc, /etc/sshrc and - * xauth are run in the proper environment. + * Must take new environment into use so that .ssh/rc, + * /etc/ssh/sshrc and xauth are run in the proper environment. */ environ = env; @@ -1389,10 +1291,10 @@ do_child(Session *s, const char *command) /* Try to get AFS tokens for the local cell. */ if (k_hasafs()) { char cell[64]; - + if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0) krb_afslog(cell, 0); - + krb_afslog(0, 0); } #endif /* AFS */ @@ -1407,128 +1309,65 @@ do_child(Session *s, const char *command) #endif } - /* - * Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first - * in this order). - */ - if (!options.use_login) { - /* ignore _PATH_SSH_USER_RC for subsystems */ - if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) { - snprintf(cmd, sizeof cmd, "%s -c '%s %s'", - shell, _PATH_BSHELL, _PATH_SSH_USER_RC); - if (debug_flag) - fprintf(stderr, "Running %s\n", cmd); - f = popen(cmd, "w"); - if (f) { - if (do_xauth) - fprintf(f, "%s %s\n", s->auth_proto, - s->auth_data); - pclose(f); - } else - fprintf(stderr, "Could not run %s\n", - _PATH_SSH_USER_RC); - } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) { - if (debug_flag) - fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, - _PATH_SSH_SYSTEM_RC); - f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w"); - if (f) { - if (do_xauth) - fprintf(f, "%s %s\n", s->auth_proto, - s->auth_data); - pclose(f); - } else - fprintf(stderr, "Could not run %s\n", - _PATH_SSH_SYSTEM_RC); - } else if (do_xauth && options.xauth_location != NULL) { - /* Add authority data to .Xauthority if appropriate. */ - char *screen = strchr(s->display, ':'); - - if (debug_flag) { - fprintf(stderr, - "Running %.100s add " - "%.100s %.100s %.100s\n", - options.xauth_location, s->display, - s->auth_proto, s->auth_data); - if (screen != NULL) - fprintf(stderr, - "Adding %.*s/unix%s %s %s\n", - (int)(screen - s->display), - s->display, screen, - s->auth_proto, s->auth_data); - } - snprintf(cmd, sizeof cmd, "%s -q -", - options.xauth_location); - f = popen(cmd, "w"); - if (f) { - fprintf(f, "add %s %s %s\n", s->display, - s->auth_proto, s->auth_data); - if (screen != NULL) - fprintf(f, "add %.*s/unix%s %s %s\n", - (int)(screen - s->display), - s->display, screen, - s->auth_proto, - s->auth_data); - pclose(f); - } else { - fprintf(stderr, "Could not run %s\n", - cmd); - } - } - /* Get the last component of the shell name. */ - cp = strrchr(shell, '/'); - if (cp) - cp++; - else - cp = shell; - } + if (!options.use_login) + do_rc_files(s, shell); /* restore SIGPIPE for child */ signal(SIGPIPE, SIG_DFL); + if (options.use_login) { + /* Launch login(1). */ + + execl(LOGIN_PROGRAM, "login", "-h", hostname, +#ifdef LOGIN_NEEDS_TERM + (s->term ? s->term : "unknown"), +#endif /* LOGIN_NEEDS_TERM */ + "-p", "-f", "--", pw->pw_name, (char *)NULL); + + /* Login couldn't be executed, die. */ + + perror("login"); + exit(1); + } + + /* Get the last component of the shell name. */ + if ((shell0 = strrchr(shell, '/')) != NULL) + shell0++; + else + shell0 = shell; + /* * If we have no command, execute the shell. In this case, the shell * name to be passed in argv[0] is preceded by '-' to indicate that * this is a login shell. */ if (!command) { - if (!options.use_login) { - char buf[256]; + char argv0[256]; - /* Start the shell. Set initial character to '-'. */ - buf[0] = '-'; - strncpy(buf + 1, cp, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = 0; + /* Start the shell. Set initial character to '-'. */ + argv0[0] = '-'; - /* Execute the shell. */ - argv[0] = buf; - argv[1] = NULL; - execve(shell, argv, env); - - /* Executing the shell failed. */ + if (strlcpy(argv0 + 1, shell0, sizeof(argv0) - 1) + >= sizeof(argv0) - 1) { + errno = EINVAL; perror(shell); exit(1); + } - } else { - /* Launch login(1). */ - - execl(LOGIN_PROGRAM, "login", "-h", hostname, -#ifdef LOGIN_NEEDS_TERM - s->term? s->term : "unknown", -#endif - "-p", "-f", "--", pw->pw_name, (char *)NULL); - - /* Login couldn't be executed, die. */ + /* Execute the shell. */ + argv[0] = argv0; + argv[1] = NULL; + execve(shell, argv, env); - perror("login"); - exit(1); - } + /* Executing the shell failed. */ + perror(shell); + exit(1); } /* * Execute the command using the user's shell. This uses the -c * option to execute the command. */ - argv[0] = (char *) cp; + argv[0] = (char *) shell0; argv[1] = "-c"; argv[2] = (char *) command; argv[3] = NULL; @@ -1544,12 +1383,12 @@ session_new(void) static int did_init = 0; if (!did_init) { debug("session_new: init"); - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { sessions[i].used = 0; } did_init = 1; } - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; if (! s->used) { memset(s, 0, sizeof(*s)); @@ -1569,7 +1408,7 @@ static void session_dump(void) { int i; - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; debug("dump: used %d session %d %p channel %d pid %d", s->used, @@ -1602,7 +1441,7 @@ static Session * session_by_channel(int id) { int i; - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; if (s->used && s->chanid == id) { debug("session_by_channel: session %d channel %d", i, id); @@ -1619,7 +1458,7 @@ session_by_pid(pid_t pid) { int i; debug("session_by_pid: pid %d", pid); - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; if (s->used && s->pid == pid) return s; @@ -1636,7 +1475,7 @@ session_window_change_req(Session *s) s->row = packet_get_int(); s->xpixel = packet_get_int(); s->ypixel = packet_get_int(); - packet_done(); + packet_check_eom(); pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); return 1; } @@ -1701,7 +1540,7 @@ session_pty_req(Session *s) /* Set window size from the packet. */ pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); - packet_done(); + packet_check_eom(); session_proctitle(s); return 1; } @@ -1715,8 +1554,8 @@ session_subsystem_req(Session *s) char *cmd, *subsys = packet_get_string(&len); int i; - packet_done(); - log("subsystem request for %s", subsys); + packet_check_eom(); + log("subsystem request for %.100s", subsys); for (i = 0; i < options.num_subsystems; i++) { if (strcmp(subsys, options.subsystem_name[i]) == 0) { @@ -1730,11 +1569,12 @@ session_subsystem_req(Session *s) s->is_subsystem = 1; do_exec(s, cmd); success = 1; + break; } } if (!success) - log("subsystem request for %s failed, subsystem not found", + log("subsystem request for %.100s failed, subsystem not found", subsys); xfree(subsys); @@ -1750,7 +1590,7 @@ session_x11_req(Session *s) s->auth_proto = packet_get_string(NULL); s->auth_data = packet_get_string(NULL); s->screen = packet_get_int(); - packet_done(); + packet_check_eom(); success = session_setup_x11fwd(s); if (!success) { @@ -1765,7 +1605,7 @@ session_x11_req(Session *s) static int session_shell_req(Session *s) { - packet_done(); + packet_check_eom(); do_exec(s, NULL); return 1; } @@ -1775,7 +1615,7 @@ session_exec_req(Session *s) { u_int len; char *command = packet_get_string(&len); - packet_done(); + packet_check_eom(); do_exec(s, command); xfree(command); return 1; @@ -1785,7 +1625,7 @@ static int session_auth_agent_req(Session *s) { static int called = 0; - packet_done(); + packet_check_eom(); if (no_agent_forwarding_flag) { debug("session_auth_agent_req: no_agent_forwarding_flag"); return 0; @@ -1798,28 +1638,18 @@ session_auth_agent_req(Session *s) } } -void -session_input_channel_req(int id, void *arg) +int +session_input_channel_req(Channel *c, const char *rtype) { - u_int len; - int reply; int success = 0; - char *rtype; Session *s; - Channel *c; - rtype = packet_get_string(&len); - reply = packet_get_char(); - - s = session_by_channel(id); - if (s == NULL) - fatal("session_input_channel_req: channel %d: no session", id); - c = channel_lookup(id); - if (c == NULL) - fatal("session_input_channel_req: channel %d: bad channel", id); - - debug("session_input_channel_req: session %d channel %d request %s reply %d", - s->self, id, rtype, reply); + if ((s = session_by_channel(c->self)) == NULL) { + log("session_input_channel_req: no session %d req %.100s", + c->self, rtype); + return 0; + } + debug("session_input_channel_req: session %d req %s", s->self, rtype); /* * a session is in LARVAL state until a shell, a command @@ -1843,14 +1673,7 @@ session_input_channel_req(int id, void *arg) if (strcmp(rtype, "window-change") == 0) { success = session_window_change_req(s); } - - if (reply) { - packet_start(success ? - SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); - packet_put_int(c->remote_id); - packet_send(); - } - xfree(rtype); + return success; } void @@ -1867,7 +1690,8 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr) channel_set_fds(s->chanid, fdout, fdin, fderr, fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, - 1); + 1, + CHAN_SES_WINDOW_DEFAULT); } /* @@ -1890,7 +1714,7 @@ session_pty_cleanup(void *session) /* Record that the user has logged out. */ if (s->pid != 0) - record_logout(s->pid, s->tty); + record_logout(s->pid, s->tty, s->pw->pw_name); /* Release the pseudo-tty. */ pty_release(s->tty); @@ -1911,23 +1735,19 @@ static void session_exit_message(Session *s, int status) { Channel *c; - if (s == NULL) - fatal("session_close: no session"); - c = channel_lookup(s->chanid); - if (c == NULL) + + if ((c = channel_lookup(s->chanid)) == NULL) fatal("session_exit_message: session %d: no channel %d", s->self, s->chanid); debug("session_exit_message: session %d channel %d pid %d", s->self, s->chanid, s->pid); if (WIFEXITED(status)) { - channel_request_start(s->chanid, - "exit-status", 0); + channel_request_start(s->chanid, "exit-status", 0); packet_put_int(WEXITSTATUS(status)); packet_send(); } else if (WIFSIGNALED(status)) { - channel_request_start(s->chanid, - "exit-signal", 0); + channel_request_start(s->chanid, "exit-signal", 0); packet_put_int(WTERMSIG(status)); #ifdef WCOREDUMP packet_put_char(WCOREDUMP(status)); @@ -1968,6 +1788,8 @@ session_close(Session *s) xfree(s->term); if (s->display) xfree(s->display); + if (s->auth_display) + xfree(s->auth_display); if (s->auth_data) xfree(s->auth_data); if (s->auth_proto) @@ -2024,9 +1846,9 @@ void session_destroy_all(void) { int i; - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; - if (s->used) + if (s->used) session_close(s); } } @@ -2037,7 +1859,7 @@ session_tty_list(void) static char buf[1024]; int i; buf[0] = '\0'; - for(i = 0; i < MAX_SESSIONS; i++) { + for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; if (s->used && s->ttyfd != -1) { if (buf[0] != '\0') @@ -2063,6 +1885,8 @@ int session_setup_x11fwd(Session *s) { struct stat st; + char display[512], auth_display[512]; + char hostname[MAXHOSTNAMELEN]; if (no_x11_forwarding_flag) { packet_send_debug("X11 forwarding disabled in user configuration file."); @@ -2086,11 +1910,50 @@ session_setup_x11fwd(Session *s) debug("X11 display already set."); return 0; } - s->display = x11_create_display_inet(s->screen, options.x11_display_offset); - if (s->display == NULL) { + s->display_number = x11_create_display_inet(options.x11_display_offset, + options.x11_use_localhost, s->single_connection); + if (s->display_number == -1) { debug("x11_create_display_inet failed."); return 0; } + + /* Set up a suitable value for the DISPLAY variable. */ + if (gethostname(hostname, sizeof(hostname)) < 0) + fatal("gethostname: %.100s", strerror(errno)); + /* + * auth_display must be used as the displayname when the + * authorization entry is added with xauth(1). This will be + * different than the DISPLAY string for localhost displays. + */ + if (options.x11_use_localhost) { + snprintf(display, sizeof display, "localhost:%d.%d", + s->display_number, s->screen); + snprintf(auth_display, sizeof auth_display, "unix:%d.%d", + s->display_number, s->screen); + s->display = xstrdup(display); + s->auth_display = xstrdup(auth_display); + } else { +#ifdef IPADDR_IN_DISPLAY + struct hostent *he; + struct in_addr my_addr; + + he = gethostbyname(hostname); + if (he == NULL) { + error("Can't get IP address for X11 DISPLAY."); + packet_send_debug("Can't get IP address for X11 DISPLAY."); + return 0; + } + memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr)); + snprintf(display, sizeof display, "%.50s:%d.%d", inet_ntoa(my_addr), + s->display_number, s->screen); +#else + snprintf(display, sizeof display, "%.400s:%d.%d", hostname, + s->display_number, s->screen); +#endif + s->display = xstrdup(display); + s->auth_display = xstrdup(display); + } + return 1; } diff --git a/openssh/session.h b/openssh/session.h index e752c66..b83a57a 100644 --- a/openssh/session.h +++ b/openssh/session.h @@ -1,4 +1,4 @@ -/* $OpenBSD: session.h,v 1.13 2001/10/10 22:18:47 markus Exp $ */ +/* $OpenBSD: session.h,v 1.14 2002/02/03 17:53:25 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -29,7 +29,7 @@ void do_authenticated(Authctxt *); int session_open(Authctxt*, int); -void session_input_channel_req(int, void *); +int session_input_channel_req(Channel *, const char *); void session_close_by_pid(pid_t, int); void session_close_by_channel(int, void *); void session_destroy_all(void); diff --git a/openssh/sshconnect1.c b/openssh/sshconnect1.c index 1c35f03..dc02a23 100644 --- a/openssh/sshconnect1.c +++ b/openssh/sshconnect1.c @@ -13,10 +13,10 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect1.c,v 1.41 2001/10/06 11:18:19 markus Exp $"); +RCSID("$OpenBSD: sshconnect1.c,v 1.48 2002/02/11 16:15:46 markus Exp $"); #include -#include +#include #ifdef KRB4 #include @@ -70,7 +70,6 @@ try_agent_authentication(void) AuthenticationConnection *auth; u_char response[16]; u_int i; - int plen, clen; Key *key; BIGNUM *challenge; @@ -79,12 +78,12 @@ try_agent_authentication(void) if (!auth) return 0; - challenge = BN_new(); - + if ((challenge = BN_new()) == NULL) + fatal("try_agent_authentication: BN_new failed"); /* Loop through identities served by the agent. */ for (key = ssh_get_first_identity(auth, &comment, 1); - key != NULL; - key = ssh_get_next_identity(auth, &comment, 1)) { + key != NULL; + key = ssh_get_next_identity(auth, &comment, 1)) { /* Try this identity. */ debug("Trying RSA authentication via agent with '%.100s'", comment); @@ -97,7 +96,7 @@ try_agent_authentication(void) packet_write_wait(); /* Wait for server's response. */ - type = packet_read(&plen); + type = packet_read(); /* The server sends failure if it doesn\'t like our key or does not support RSA authentication. */ @@ -111,9 +110,8 @@ try_agent_authentication(void) packet_disconnect("Protocol error during RSA authentication: %d", type); - packet_get_bignum(challenge, &clen); - - packet_integrity_check(plen, clen, type); + packet_get_bignum(challenge); + packet_check_eom(); debug("Received RSA challenge from server."); @@ -138,7 +136,7 @@ try_agent_authentication(void) packet_write_wait(); /* Wait for response from the server. */ - type = packet_read(&plen); + type = packet_read(); /* The server returns success if it accepted the authentication. */ if (type == SSH_SMSG_SUCCESS) { @@ -213,7 +211,7 @@ try_rsa_authentication(int idx) BIGNUM *challenge; Key *public, *private; char buf[300], *passphrase, *comment, *authfile; - int i, type, quit, plen, clen; + int i, type, quit; public = options.identity_keys[idx]; authfile = options.identity_files[idx]; @@ -228,7 +226,7 @@ try_rsa_authentication(int idx) packet_write_wait(); /* Wait for server's response. */ - type = packet_read(&plen); + type = packet_read(); /* * The server responds with failure if it doesn\'t like our key or @@ -244,10 +242,10 @@ try_rsa_authentication(int idx) packet_disconnect("Protocol error during RSA authentication: %d", type); /* Get the challenge from the packet. */ - challenge = BN_new(); - packet_get_bignum(challenge, &clen); - - packet_integrity_check(plen, clen, type); + if ((challenge = BN_new()) == NULL) + fatal("try_rsa_authentication: BN_new failed"); + packet_get_bignum(challenge); + packet_check_eom(); debug("Received RSA challenge from server."); @@ -295,7 +293,7 @@ try_rsa_authentication(int idx) packet_write_wait(); /* Expect the server to reject it... */ - packet_read_expect(&plen, SSH_SMSG_FAILURE); + packet_read_expect(SSH_SMSG_FAILURE); BN_clear_free(challenge); return 0; } @@ -311,7 +309,7 @@ try_rsa_authentication(int idx) BN_clear_free(challenge); /* Wait for response from the server. */ - type = packet_read(&plen); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) { debug("RSA authentication accepted by server."); return 1; @@ -331,7 +329,6 @@ try_rhosts_rsa_authentication(const char *local_user, Key * host_key) { int type; BIGNUM *challenge; - int plen, clen; debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication."); @@ -345,7 +342,7 @@ try_rhosts_rsa_authentication(const char *local_user, Key * host_key) packet_write_wait(); /* Wait for server's response. */ - type = packet_read(&plen); + type = packet_read(); /* The server responds with failure if it doesn't admit our .rhosts authentication or doesn't know our host key. */ @@ -358,10 +355,10 @@ try_rhosts_rsa_authentication(const char *local_user, Key * host_key) packet_disconnect("Protocol error during RSA authentication: %d", type); /* Get the challenge from the packet. */ - challenge = BN_new(); - packet_get_bignum(challenge, &clen); - - packet_integrity_check(plen, clen, type); + if ((challenge = BN_new()) == NULL) + fatal("try_rhosts_rsa_authentication: BN_new failed"); + packet_get_bignum(challenge); + packet_check_eom(); debug("Received RSA challenge for host key from server."); @@ -372,7 +369,7 @@ try_rhosts_rsa_authentication(const char *local_user, Key * host_key) BN_clear_free(challenge); /* Wait for response from the server. */ - type = packet_read(&plen); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) { debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server."); return 1; @@ -392,7 +389,7 @@ try_krb4_authentication(void) char inst[INST_SZ]; char *realm; CREDENTIALS cred; - int r, type, plen; + int r, type; socklen_t slen; Key_schedule schedule; u_long checksum, cksum; @@ -403,10 +400,10 @@ try_krb4_authentication(void) /* Don't do anything if we don't have any tickets. */ if (stat(tkt_string(), &st) < 0) return 0; - + strlcpy(inst, (char *)krb_get_phost(get_canonical_hostname(1)), INST_SZ); - + realm = (char *)krb_realmofhost(get_canonical_hostname(1)); if (!realm) { debug("Kerberos v4: no realm for %s", get_canonical_hostname(1)); @@ -414,7 +411,7 @@ try_krb4_authentication(void) } /* This can really be anything. */ checksum = (u_long)getpid(); - + r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum); if (r != KSUCCESS) { debug("Kerberos v4 krb_mk_req failed: %s", krb_err_txt[r]); @@ -427,22 +424,22 @@ try_krb4_authentication(void) return 0; } des_key_sched((des_cblock *) cred.session, schedule); - + /* Send authentication info to server. */ packet_start(SSH_CMSG_AUTH_KERBEROS); packet_put_string((char *) auth.dat, auth.length); packet_send(); packet_write_wait(); - + /* Zero the buffer. */ (void) memset(auth.dat, 0, MAX_KTXT_LEN); - + slen = sizeof(local); memset(&local, 0, sizeof(local)); if (getsockname(packet_get_connection_in(), (struct sockaddr *)&local, &slen) < 0) debug("getsockname failed: %s", strerror(errno)); - + slen = sizeof(foreign); memset(&foreign, 0, sizeof(foreign)); if (getpeername(packet_get_connection_in(), @@ -451,25 +448,25 @@ try_krb4_authentication(void) fatal_cleanup(); } /* Get server reply. */ - type = packet_read(&plen); + type = packet_read(); switch (type) { case SSH_SMSG_FAILURE: /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */ debug("Kerberos v4 authentication failed."); return 0; break; - + case SSH_SMSG_AUTH_KERBEROS_RESPONSE: /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ debug("Kerberos v4 authentication accepted."); - + /* Get server's response. */ reply = packet_get_string((u_int *) &auth.length); memcpy(auth.dat, reply, auth.length); xfree(reply); - - packet_integrity_check(plen, 4 + auth.length, type); - + + packet_check_eom(); + /* * If his response isn't properly encrypted with the session * key, and the decrypted checksum fails to match, he's @@ -486,7 +483,7 @@ try_krb4_authentication(void) memcpy((char *)&cksum, (char *)msg_data.app_data, sizeof(cksum)); cksum = ntohl(cksum); - + /* If it matches, we're golden. */ if (cksum == checksum + 1) { debug("Kerberos v4 challenge successful."); @@ -494,7 +491,7 @@ try_krb4_authentication(void) } else packet_disconnect("Kerberos v4 challenge failed!"); break; - + default: packet_disconnect("Protocol error on Kerberos v4 response: %d", type); } @@ -513,12 +510,12 @@ try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) krb5_ccache ccache = NULL; const char *remotehost; krb5_data ap; - int type, payload_len; + int type; krb5_ap_rep_enc_part *reply = NULL; int ret; - + memset(&ap, 0, sizeof(ap)); - + problem = krb5_init_context(context); if (problem) { debug("Kerberos v5: krb5_init_context failed"); @@ -546,13 +543,13 @@ try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) tkfile = krb5_cc_default_name(*context); if (strncmp(tkfile, "FILE:", 5) == 0) tkfile += 5; - + if (stat(tkfile, &buf) == 0 && getuid() != buf.st_uid) { debug("Kerberos v5: could not get default ccache (permission denied)."); ret = 0; goto out; } - + problem = krb5_cc_default(*context, &ccache); if (problem) { debug("Kerberos v5: krb5_cc_default failed: %s", @@ -560,9 +557,9 @@ try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) ret = 0; goto out; } - + remotehost = get_canonical_hostname(1); - + problem = krb5_mk_req(*context, auth_context, AP_OPTS_MUTUAL_REQUIRED, "host", remotehost, NULL, ccache, &ap); if (problem) { @@ -571,48 +568,47 @@ try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) ret = 0; goto out; } - + packet_start(SSH_CMSG_AUTH_KERBEROS); packet_put_string((char *) ap.data, ap.length); packet_send(); packet_write_wait(); - + xfree(ap.data); ap.length = 0; - - type = packet_read(&payload_len); + + type = packet_read(); switch (type) { - case SSH_SMSG_FAILURE: - /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */ - debug("Kerberos v5 authentication failed."); - ret = 0; - break; - + case SSH_SMSG_FAILURE: + /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */ + debug("Kerberos v5 authentication failed."); + ret = 0; + break; + case SSH_SMSG_AUTH_KERBEROS_RESPONSE: - /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ - debug("Kerberos v5 authentication accepted."); - - /* Get server's response. */ - ap.data = packet_get_string((unsigned int *) &ap.length); - - packet_integrity_check(payload_len, 4 + ap.length, type); - /* XXX je to dobre? */ - - problem = krb5_rd_rep(*context, *auth_context, &ap, &reply); - if (problem) { + /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ + debug("Kerberos v5 authentication accepted."); + + /* Get server's response. */ + ap.data = packet_get_string((unsigned int *) &ap.length); + packet_check_eom(); + /* XXX je to dobre? */ + + problem = krb5_rd_rep(*context, *auth_context, &ap, &reply); + if (problem) { ret = 0; } ret = 1; break; - + default: packet_disconnect("Protocol error on Kerberos v5 response: %d", type); ret = 0; break; - + } - + out: if (ccache != NULL) krb5_cc_close(*context, ccache); @@ -631,7 +627,7 @@ try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) static void send_krb5_tgt(krb5_context context, krb5_auth_context auth_context) { - int fd, type, payload_len; + int fd, type; krb5_error_code problem; krb5_data outbuf; krb5_ccache ccache = NULL; @@ -642,10 +638,10 @@ send_krb5_tgt(krb5_context context, krb5_auth_context auth_context) int forwardable; #endif const char *remotehost; - + memset(&creds, 0, sizeof(creds)); memset(&outbuf, 0, sizeof(outbuf)); - + fd = packet_get_connection_in(); #ifdef HEIMDAL @@ -665,7 +661,7 @@ send_krb5_tgt(krb5_context context, krb5_auth_context auth_context) problem = krb5_cc_default(context, &ccache); if (problem) goto out; - + problem = krb5_cc_get_principal(context, ccache, &creds.client); if (problem) goto out; @@ -682,7 +678,7 @@ send_krb5_tgt(krb5_context context, krb5_auth_context auth_context) if (problem) goto out; - + creds.times.endtime = 0; #ifdef HEIMDAL @@ -690,9 +686,9 @@ send_krb5_tgt(krb5_context context, krb5_auth_context auth_context) flags.b.forwarded = 1; flags.b.forwardable = krb5_config_get_bool(context, NULL, "libdefaults", "forwardable", NULL); - + remotehost = get_canonical_hostname(1); - + problem = krb5_get_forwarded_creds(context, auth_context, ccache, flags.i, remotehost, &creds, &outbuf); if (problem) @@ -708,25 +704,24 @@ send_krb5_tgt(krb5_context context, krb5_auth_context auth_context) if (problem) goto out; #endif - packet_start(SSH_CMSG_HAVE_KERBEROS_TGT); packet_put_string((char *)outbuf.data, outbuf.length); packet_send(); packet_write_wait(); - - type = packet_read(&payload_len); - + + type = packet_read(); + if (type == SSH_SMSG_SUCCESS) { char *pname; - + krb5_unparse_name(context, creds.client, &pname); debug("Kerberos v5 TGT forwarded (%s).", pname); xfree(pname); } else debug("Kerberos v5 TGT forwarding failed."); - + return; - + out: if (problem) debug("Kerberos v5 TGT forwarding failed: %s", @@ -749,45 +744,45 @@ send_krb4_tgt(void) CREDENTIALS *creds; struct stat st; char buffer[4096], pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ]; - int problem, type, len; - + int problem, type; + /* Don't do anything if we don't have any tickets. */ if (stat(tkt_string(), &st) < 0) return; - + creds = xmalloc(sizeof(*creds)); - + problem = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm); if (problem) goto out; - + problem = krb_get_cred("krbtgt", prealm, prealm, creds); if (problem) goto out; - + if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) { problem = RD_AP_EXP; goto out; } creds_to_radix(creds, (u_char *)buffer, sizeof(buffer)); - + packet_start(SSH_CMSG_HAVE_KERBEROS_TGT); packet_put_cstring(buffer); packet_send(); packet_write_wait(); - - type = packet_read(&len); - + + type = packet_read(); + if (type == SSH_SMSG_SUCCESS) debug("Kerberos v4 TGT forwarded (%s%s%s@%s).", creds->pname, creds->pinst[0] ? "." : "", creds->pinst, creds->realm); else debug("Kerberos v4 TGT rejected."); - + xfree(creds); return; - + out: debug("Kerberos v4 TGT passing failed: %s", krb_err_txt[problem]); xfree(creds); @@ -802,7 +797,7 @@ send_afs_tokens(void) int i, type, len; char buf[2048], *p, *server_cell; char buffer[8192]; - + /* Move over ktc_GetToken, here's something leaner. */ for (i = 0; i < 100; i++) { /* just in case */ parms.in = (char *) &i; @@ -812,7 +807,7 @@ send_afs_tokens(void) if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0) break; p = buf; - + /* Get secret token. */ memcpy(&creds.ticket_st.length, p, sizeof(u_int)); if (creds.ticket_st.length > MAX_KTXT_LEN) @@ -820,7 +815,7 @@ send_afs_tokens(void) p += sizeof(u_int); memcpy(creds.ticket_st.dat, p, creds.ticket_st.length); p += creds.ticket_st.length; - + /* Get clear token. */ memcpy(&len, p, sizeof(len)); if (len != sizeof(struct ClearToken)) @@ -830,7 +825,7 @@ send_afs_tokens(void) p += len; p += sizeof(len); /* primary flag */ server_cell = p; - + /* Flesh out our credentials. */ strlcpy(creds.service, "afs", sizeof(creds.service)); creds.instance[0] = '\0'; @@ -842,7 +837,7 @@ send_afs_tokens(void) creds.kvno = ct.AuthHandle; snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId); creds.pinst[0] = '\0'; - + /* Encode token, ship it off. */ if (creds_to_radix(&creds, (u_char *)buffer, sizeof(buffer)) <= 0) @@ -854,8 +849,8 @@ send_afs_tokens(void) /* Roger, Roger. Clearance, Clarence. What's your vector, Victor? */ - type = packet_read(&len); - + type = packet_read(); + if (type == SSH_SMSG_FAILURE) debug("AFS token for cell %s rejected.", server_cell); else if (type != SSH_SMSG_SUCCESS) @@ -873,7 +868,6 @@ static int try_challenge_response_authentication(void) { int type, i; - int payload_len; u_int clen; char prompt[1024]; char *challenge, *response; @@ -886,7 +880,7 @@ try_challenge_response_authentication(void) packet_send(); packet_write_wait(); - type = packet_read(&payload_len); + type = packet_read(); if (type != SSH_SMSG_FAILURE && type != SSH_SMSG_AUTH_TIS_CHALLENGE) { packet_disconnect("Protocol error: got %d in response " @@ -897,9 +891,9 @@ try_challenge_response_authentication(void) return 0; } challenge = packet_get_string(&clen); - packet_integrity_check(payload_len, (4 + clen), type); + packet_check_eom(); snprintf(prompt, sizeof prompt, "%s%s", challenge, - strchr(challenge, '\n') ? "" : "\nResponse: "); + strchr(challenge, '\n') ? "" : "\nResponse: "); xfree(challenge); if (i != 0) error("Permission denied, please try again."); @@ -917,7 +911,7 @@ try_challenge_response_authentication(void) xfree(response); packet_send(); packet_write_wait(); - type = packet_read(&payload_len); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) return 1; if (type != SSH_SMSG_FAILURE) @@ -934,7 +928,7 @@ try_challenge_response_authentication(void) static int try_password_authentication(char *prompt) { - int type, i, payload_len; + int type, i; char *password; debug("Doing password authentication."); @@ -951,7 +945,7 @@ try_password_authentication(char *prompt) packet_send(); packet_write_wait(); - type = packet_read(&payload_len); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) return 1; if (type != SSH_SMSG_FAILURE) @@ -969,54 +963,43 @@ ssh_kex(char *host, struct sockaddr *hostaddr) { int i; BIGNUM *key; - RSA *host_key; - RSA *public_key; - Key k; + Key *host_key, *server_key; int bits, rbits; int ssh_cipher_default = SSH_CIPHER_3DES; u_char session_key[SSH_SESSION_KEY_LENGTH]; u_char cookie[8]; u_int supported_ciphers; u_int server_flags, client_flags; - int payload_len, clen, sum_len = 0; u_int32_t rand = 0; debug("Waiting for server public key."); /* Wait for a public key packet from the server. */ - packet_read_expect(&payload_len, SSH_SMSG_PUBLIC_KEY); + packet_read_expect(SSH_SMSG_PUBLIC_KEY); /* Get cookie from the packet. */ for (i = 0; i < 8; i++) cookie[i] = packet_get_char(); /* Get the public key. */ - public_key = RSA_new(); - bits = packet_get_int();/* bits */ - public_key->e = BN_new(); - packet_get_bignum(public_key->e, &clen); - sum_len += clen; - public_key->n = BN_new(); - packet_get_bignum(public_key->n, &clen); - sum_len += clen; - - rbits = BN_num_bits(public_key->n); + server_key = key_new(KEY_RSA1); + bits = packet_get_int(); + packet_get_bignum(server_key->rsa->e); + packet_get_bignum(server_key->rsa->n); + + rbits = BN_num_bits(server_key->rsa->n); if (bits != rbits) { log("Warning: Server lies about size of server public key: " "actual size is %d bits vs. announced %d.", rbits, bits); log("Warning: This may be due to an old implementation of ssh."); } /* Get the host key. */ - host_key = RSA_new(); - bits = packet_get_int();/* bits */ - host_key->e = BN_new(); - packet_get_bignum(host_key->e, &clen); - sum_len += clen; - host_key->n = BN_new(); - packet_get_bignum(host_key->n, &clen); - sum_len += clen; - - rbits = BN_num_bits(host_key->n); + host_key = key_new(KEY_RSA1); + bits = packet_get_int(); + packet_get_bignum(host_key->rsa->e); + packet_get_bignum(host_key->rsa->n); + + rbits = BN_num_bits(host_key->rsa->n); if (bits != rbits) { log("Warning: Server lies about size of server host key: " "actual size is %d bits vs. announced %d.", rbits, bits); @@ -1029,21 +1012,17 @@ ssh_kex(char *host, struct sockaddr *hostaddr) supported_ciphers = packet_get_int(); supported_authentications = packet_get_int(); + packet_check_eom(); debug("Received server public key (%d bits) and host key (%d bits).", - BN_num_bits(public_key->n), BN_num_bits(host_key->n)); - - packet_integrity_check(payload_len, - 8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4, - SSH_SMSG_PUBLIC_KEY); - k.type = KEY_RSA1; - k.rsa = host_key; - if (verify_host_key(host, hostaddr, &k) == -1) + BN_num_bits(server_key->rsa->n), BN_num_bits(host_key->rsa->n)); + + if (verify_host_key(host, hostaddr, host_key) == -1) fatal("Host key verification failed."); client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN; - compute_session_id(session_id, cookie, host_key->n, public_key->n); + compute_session_id(session_id, cookie, host_key->rsa->n, server_key->rsa->n); /* Generate a session key. */ arc4random_stir(); @@ -1065,7 +1044,8 @@ ssh_kex(char *host, struct sockaddr *hostaddr) * is the highest byte of the integer. The session key is xored with * the first 16 bytes of the session id. */ - key = BN_new(); + if ((key = BN_new()) == NULL) + fatal("respond_to_rsa_challenge: BN_new failed"); BN_set_word(key, 0); for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) { BN_lshift(key, key, 8); @@ -1079,35 +1059,35 @@ ssh_kex(char *host, struct sockaddr *hostaddr) * Encrypt the integer using the public key and host key of the * server (key with smaller modulus first). */ - if (BN_cmp(public_key->n, host_key->n) < 0) { + if (BN_cmp(server_key->rsa->n, host_key->rsa->n) < 0) { /* Public key has smaller modulus. */ - if (BN_num_bits(host_key->n) < - BN_num_bits(public_key->n) + SSH_KEY_BITS_RESERVED) { - fatal("respond_to_rsa_challenge: host_key %d < public_key %d + " - "SSH_KEY_BITS_RESERVED %d", - BN_num_bits(host_key->n), - BN_num_bits(public_key->n), - SSH_KEY_BITS_RESERVED); + if (BN_num_bits(host_key->rsa->n) < + BN_num_bits(server_key->rsa->n) + SSH_KEY_BITS_RESERVED) { + fatal("respond_to_rsa_challenge: host_key %d < server_key %d + " + "SSH_KEY_BITS_RESERVED %d", + BN_num_bits(host_key->rsa->n), + BN_num_bits(server_key->rsa->n), + SSH_KEY_BITS_RESERVED); } - rsa_public_encrypt(key, key, public_key); - rsa_public_encrypt(key, key, host_key); + rsa_public_encrypt(key, key, server_key->rsa); + rsa_public_encrypt(key, key, host_key->rsa); } else { /* Host key has smaller modulus (or they are equal). */ - if (BN_num_bits(public_key->n) < - BN_num_bits(host_key->n) + SSH_KEY_BITS_RESERVED) { - fatal("respond_to_rsa_challenge: public_key %d < host_key %d + " - "SSH_KEY_BITS_RESERVED %d", - BN_num_bits(public_key->n), - BN_num_bits(host_key->n), - SSH_KEY_BITS_RESERVED); + if (BN_num_bits(server_key->rsa->n) < + BN_num_bits(host_key->rsa->n) + SSH_KEY_BITS_RESERVED) { + fatal("respond_to_rsa_challenge: server_key %d < host_key %d + " + "SSH_KEY_BITS_RESERVED %d", + BN_num_bits(server_key->rsa->n), + BN_num_bits(host_key->rsa->n), + SSH_KEY_BITS_RESERVED); } - rsa_public_encrypt(key, key, host_key); - rsa_public_encrypt(key, key, public_key); + rsa_public_encrypt(key, key, host_key->rsa); + rsa_public_encrypt(key, key, server_key->rsa); } /* Destroy the public keys since we no longer need them. */ - RSA_free(public_key); - RSA_free(host_key); + key_free(server_key); + key_free(host_key); if (options.cipher == SSH_CIPHER_NOT_SET) { if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default)) @@ -1121,7 +1101,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr) /* Check that the selected cipher is supported. */ if (!(supported_ciphers & (1 << options.cipher))) fatal("Selected cipher type %.100s not supported by server.", - cipher_name(options.cipher)); + cipher_name(options.cipher)); debug("Encryption type: %.100s", cipher_name(options.cipher)); @@ -1156,7 +1136,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr) * Expect a success message from the server. Note that this message * will be received in encrypted form. */ - packet_read_expect(&payload_len, SSH_SMSG_SUCCESS); + packet_read_expect(SSH_SMSG_SUCCESS); debug("Received encrypted confirmation."); } @@ -1173,8 +1153,7 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, krb5_auth_context auth_context = NULL; #endif int i, type; - int payload_len; - + if (supported_authentications == 0) fatal("ssh_userauth1: server supports no auth methods"); @@ -1189,21 +1168,21 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, * needed (the user has no password). Otherwise the server responds * with failure. */ - type = packet_read(&payload_len); + type = packet_read(); /* check whether the connection was accepted without authentication. */ if (type == SSH_SMSG_SUCCESS) goto success; if (type != SSH_SMSG_FAILURE) packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", type); - + #ifdef KRB5 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && - options.kerberos_authentication) { + options.kerberos_authentication) { debug("Trying Kerberos v5 authentication."); - + if (try_krb5_authentication(&context, &auth_context)) { - type = packet_read(&payload_len); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) goto success; if (type != SSH_SMSG_FAILURE) @@ -1211,14 +1190,14 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, } } #endif /* KRB5 */ - + #ifdef KRB4 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && options.kerberos_authentication) { debug("Trying Kerberos v4 authentication."); - + if (try_krb4_authentication()) { - type = packet_read(&payload_len); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) goto success; if (type != SSH_SMSG_FAILURE) @@ -1226,7 +1205,7 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, } } #endif /* KRB4 */ - + /* * Use rhosts authentication if running in privileged socket and we * do not wish to remain anonymous. @@ -1240,7 +1219,7 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, packet_write_wait(); /* The server should respond with success or failure. */ - type = packet_read(&payload_len); + type = packet_read(); if (type == SSH_SMSG_SUCCESS) goto success; if (type != SSH_SMSG_FAILURE) @@ -1311,7 +1290,7 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, if (context) krb5_free_context(context); #endif - + #ifdef AFS /* Try Kerberos v4 TGT passing if the server supports it. */ if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) && diff --git a/openssh/sshconnect2.c b/openssh/sshconnect2.c index d97aed4..698d515 100644 --- a/openssh/sshconnect2.c +++ b/openssh/sshconnect2.c @@ -23,26 +23,18 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshconnect2.c,v 1.85 2001/11/07 16:03:17 markus Exp $"); - -#include -#include -#include -#include +RCSID("$OpenBSD: sshconnect2.c,v 1.97 2002/02/25 16:33:27 markus Exp $"); #include "ssh.h" #include "ssh2.h" #include "xmalloc.h" -#include "rsa.h" #include "buffer.h" #include "packet.h" -#include "uidswap.h" #include "compat.h" #include "bufaux.h" #include "cipher.h" #include "kex.h" #include "myproposal.h" -#include "key.h" #include "sshconnect.h" #include "authfile.h" #include "dh.h" @@ -139,7 +131,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; } if (options.hostkeyalgorithms != NULL) - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = options.hostkeyalgorithms; /* start key exchange */ @@ -179,7 +171,7 @@ typedef struct Authmethod Authmethod; typedef int sign_cb_fn( Authctxt *authctxt, Key *key, - u_char **sigp, int *lenp, u_char *data, int datalen); + u_char **sigp, u_int *lenp, u_char *data, u_int datalen); struct Authctxt { const char *server_user; @@ -228,11 +220,23 @@ int userauth_gssapi(Authctxt *authctxt); void input_gssapi_response(int type, int plen, void *ctxt); void input_gssapi_token(int type, int plen, void *ctxt); void input_gssapi_hash(int type, int plen, void *ctxt); - int gss_host_key_ok=0; #endif -void userauth(Authctxt *authctxt, char *authlist); +void input_userauth_success(int, u_int32_t, void *); +void input_userauth_failure(int, u_int32_t, void *); +void input_userauth_banner(int, u_int32_t, void *); +void input_userauth_error(int, u_int32_t, void *); +void input_userauth_info_req(int, u_int32_t, void *); +void input_userauth_pk_ok(int, u_int32_t, void *); + +int userauth_none(Authctxt *); +int userauth_pubkey(Authctxt *); +int userauth_passwd(Authctxt *); +int userauth_kbdint(Authctxt *); +int userauth_hostbased(Authctxt *); + +void userauth(Authctxt *, char *); static int sign_and_send_pubkey(Authctxt *, Key *, sign_cb_fn *); static void clear_auth_state(Authctxt *); @@ -281,7 +285,6 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, { Authctxt authctxt; int type; - int plen; if (options.challenge_response_authentication) options.kbd_interactive_authentication = 1; @@ -291,18 +294,18 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, packet_put_cstring("ssh-userauth"); packet_send(); packet_write_wait(); - type = packet_read(&plen); + type = packet_read(); if (type != SSH2_MSG_SERVICE_ACCEPT) { fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type); } if (packet_remaining() > 0) { - char *reply = packet_get_string(&plen); + char *reply = packet_get_string(NULL); debug("service_accept: %s", reply); xfree(reply); } else { debug("buggy server: service_accept w/o service"); } - packet_done(); + packet_check_eom(); debug("got SSH2_MSG_SERVICE_ACCEPT"); if (options.preferred_authentications == NULL) @@ -369,13 +372,13 @@ userauth(Authctxt *authctxt, char *authlist) } } void -input_userauth_error(int type, int plen, void *ctxt) +input_userauth_error(int type, u_int32_t seq, void *ctxt) { fatal("input_userauth_error: bad message during authentication: " "type %d", type); } void -input_userauth_banner(int type, int plen, void *ctxt) +input_userauth_banner(int type, u_int32_t seq, void *ctxt) { char *msg, *lang; debug3("input_userauth_banner"); @@ -386,7 +389,7 @@ input_userauth_banner(int type, int plen, void *ctxt) xfree(lang); } void -input_userauth_success(int type, int plen, void *ctxt) +input_userauth_success(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; if (authctxt == NULL) @@ -399,7 +402,7 @@ input_userauth_success(int type, int plen, void *ctxt) authctxt->success = 1; /* break out */ } void -input_userauth_failure(int type, int plen, void *ctxt) +input_userauth_failure(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; char *authlist = NULL; @@ -410,7 +413,7 @@ input_userauth_failure(int type, int plen, void *ctxt) authlist = packet_get_string(NULL); partial = packet_get_char(); - packet_done(); + packet_check_eom(); if (partial != 0) log("Authenticated with partial success."); @@ -420,13 +423,15 @@ input_userauth_failure(int type, int plen, void *ctxt) userauth(authctxt, authlist); } void -input_userauth_pk_ok(int type, int plen, void *ctxt) +input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; Key *key = NULL; Buffer b; - int alen, blen, sent = 0; - char *pkalg, *pkblob, *fp; + int pktype, sent = 0; + u_int alen, blen; + char *pkalg, *fp; + u_char *pkblob; if (authctxt == NULL) fatal("input_userauth_pk_ok: no authentication context"); @@ -442,7 +447,7 @@ input_userauth_pk_ok(int type, int plen, void *ctxt) pkalg = packet_get_string(&alen); pkblob = packet_get_string(&blen); } - packet_done(); + packet_check_eom(); debug("input_userauth_pk_ok: pkalg %s blen %d lastkey %p hint %d", pkalg, blen, authctxt->last_key, authctxt->last_key_hint); @@ -453,7 +458,7 @@ input_userauth_pk_ok(int type, int plen, void *ctxt) debug("no last key or no sign cb"); break; } - if (key_type_from_name(pkalg) == KEY_UNSPEC) { + if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) { debug("unknown pkalg %s", pkalg); break; } @@ -461,6 +466,12 @@ input_userauth_pk_ok(int type, int plen, void *ctxt) debug("no key from blob. pkalg %s", pkalg); break; } + if (key->type != pktype) { + error("input_userauth_pk_ok: type mismatch " + "for decoded key (received %d, expected %d)", + key->type, pktype); + break; + } fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); debug2("input_userauth_pk_ok: fp %s", fp); xfree(fp); @@ -470,7 +481,7 @@ input_userauth_pk_ok(int type, int plen, void *ctxt) } sent = sign_and_send_pubkey(authctxt, key, authctxt->last_key_sign); - } while(0); + } while (0); if (key != NULL) key_free(key); @@ -655,7 +666,7 @@ userauth_passwd(Authctxt *authctxt) if (attempt++ >= options.number_of_password_prompts) return 0; - if(attempt != 1) + if (attempt != 1) error("Permission denied, please try again."); snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ", @@ -692,7 +703,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) { Buffer b; u_char *blob, *signature; - int bloblen, slen; + u_int bloblen, slen; int skip = 0; int ret = -1; int have_sig = 1; @@ -777,7 +788,7 @@ send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback, int hint) { u_char *blob; - int bloblen, have_sig = 0; + u_int bloblen, have_sig = 0; debug3("send_pubkey_test"); @@ -822,7 +833,7 @@ load_identity_file(char *filename) if (options.batch_mode) return NULL; snprintf(prompt, sizeof prompt, - "Enter passphrase for key '%.100s': ", filename); + "Enter passphrase for key '%.100s': ", filename); for (i = 0; i < options.number_of_password_prompts; i++) { passphrase = read_passphrase(prompt, 0); if (strcmp(passphrase, "") != 0) { @@ -844,8 +855,8 @@ load_identity_file(char *filename) } static int -identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, - u_char *data, int datalen) +identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) { Key *private; int idx, ret; @@ -855,7 +866,7 @@ identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, return -1; /* private key is stored in external hardware */ - if (options.identity_keys[idx]->flags & KEY_FLAG_EXT) + if (options.identity_keys[idx]->flags & KEY_FLAG_EXT) return key_sign(options.identity_keys[idx], sigp, lenp, data, datalen); private = load_identity_file(options.identity_files[idx]); @@ -867,15 +878,15 @@ identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, } static int -agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, - u_char *data, int datalen) +agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) { return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen); } static int -key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, - u_char *data, int datalen) +key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp, + u_char *data, u_int datalen) { return key_sign(key, sigp, lenp, data, datalen); } @@ -919,7 +930,7 @@ userauth_pubkey(Authctxt *authctxt) if (authctxt->agent != NULL) { do { sent = userauth_pubkey_agent(authctxt); - } while(!sent && authctxt->agent->howmany > 0); + } while (!sent && authctxt->agent->howmany > 0); } while (!sent && idx < options.num_identity_files) { key = options.identity_keys[idx]; @@ -977,7 +988,7 @@ userauth_kbdint(Authctxt *authctxt) * parse INFO_REQUEST, prompt user and send INFO_RESPONSE */ void -input_userauth_info_req(int type, int plen, void *ctxt) +input_userauth_info_req(int type, u_int32_t seq, void *ctxt) { Authctxt *authctxt = ctxt; char *name, *inst, *lang, *prompt, *response; @@ -1024,7 +1035,7 @@ input_userauth_info_req(int type, int plen, void *ctxt) xfree(response); xfree(prompt); } - packet_done(); /* done with parsing incoming message. */ + packet_check_eom(); /* done with parsing incoming message. */ packet_add_padding(64); packet_send(); @@ -1166,7 +1177,7 @@ authmethod_get(char *authlist) { char *name = NULL; - int next; + u_int next; /* Use a suitable default if we're passed a nil list. */ if (authlist == NULL || strlen(authlist) == 0) @@ -1201,22 +1212,23 @@ authmethod_get(char *authlist) } } - -#define DELIM "," - static char * authmethods_get(void) { Authmethod *method = NULL; - char buf[1024]; + Buffer b; + char *list; - buf[0] = '\0'; + buffer_init(&b); for (method = authmethods; method->name != NULL; method++) { if (authmethod_is_enabled(method)) { - if (buf[0] != '\0') - strlcat(buf, DELIM, sizeof buf); - strlcat(buf, method->name, sizeof buf); + if (buffer_len(&b) > 0) + buffer_append(&b, ",", 1); + buffer_append(&b, method->name, strlen(method->name)); } } - return xstrdup(buf); + buffer_append(&b, "\0", 1); + list = xstrdup(buffer_ptr(&b)); + buffer_free(&b); + return list; } diff --git a/openssh/sshd.8 b/openssh/sshd.8 index ab83cfb..b17a07b 100644 --- a/openssh/sshd.8 +++ b/openssh/sshd.8 @@ -34,7 +34,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd.8,v 1.154 2001/11/07 22:12:01 markus Exp $ +.\" $OpenBSD: sshd.8,v 1.170 2002/02/28 20:46:10 stevesk Exp $ .Dd September 25, 1999 .Dt SSHD 8 .Os @@ -49,6 +49,7 @@ .Op Fl g Ar login_grace_time .Op Fl h Ar host_key_file .Op Fl k Ar key_gen_time +.Op Fl o Ar option .Op Fl p Ar port .Op Fl u Ar len .Sh DESCRIPTION @@ -197,7 +198,7 @@ will send the output to the standard error instead of the system log. .It Fl f Ar configuration_file Specifies the name of the configuration file. The default is -.Pa /etc/sshd_config . +.Pa /etc/ssh/sshd_config . .Nm refuses to start if there is no configuration file. .It Fl g Ar login_grace_time @@ -207,12 +208,18 @@ If the client fails to authenticate the user within this many seconds, the server disconnects and exits. A value of zero indicates no limit. .It Fl h Ar host_key_file -Specifies the file from which the host key is read (default -.Pa /etc/ssh_host_key ) . +Specifies a file from which a host key is read. This option must be given if .Nm is not run as root (as the normal -host file is normally not readable by anyone but root). +host key files are normally not readable by anyone but root). +The default is +.Pa /etc/ssh/ssh_host_key +for protocol version 1, and +.Pa /etc/ssh/ssh_host_rsa_key +and +.Pa /etc/ssh/ssh_host_dsa_key +for protocol version 2. It is possible to have multiple host key files for the different protocol versions and host key algorithms. .It Fl i @@ -237,9 +244,16 @@ it becomes impossible to recover the key for decrypting intercepted communications even if the machine is cracked into or physically seized. A value of zero indicates that the key will never be regenerated. +.It Fl o Ar option +Can be used to give options in the format used in the configuration file. +This is useful for specifying options for which there is no separate +command-line flag. .It Fl p Ar port Specifies the port on which the server listens for connections (default 22). +Multiple port options are permitted. +Ports specified in the configuration file are ignored when a +command-line port is specified. .It Fl q Quiet mode. Nothing is sent to the system log. @@ -248,7 +262,7 @@ authentication, and termination of each connection is logged. .It Fl t Test mode. Only check the validity of the configuration file and sanity of the keys. -This is useful for updating +This is useful for updating .Nm reliably as configuration options may change. .It Fl u Ar len @@ -279,6 +293,11 @@ Authentication mechanisms that may require DNS include and using a .Cm from="pattern-list" option in a key file. +Configuration options that require DNS include using a +USER@HOST pattern in +.Cm AllowUsers +or +.Cm DenyUsers . .It Fl D When this option is specified .Nm @@ -297,7 +316,7 @@ to use IPv6 addresses only. .Sh CONFIGURATION FILE .Nm reads configuration data from -.Pa /etc/sshd_config +.Pa /etc/ssh/sshd_config (or the file specified with .Fl f on the command line). @@ -315,7 +334,7 @@ Specifies whether an AFS token may be forwarded to the server. Default is .Dq yes . .It Cm AllowGroups -This keyword can be followed by a list of group names, separated +This keyword can be followed by a list of group name patterns, separated by spaces. If specified, login is allowed only for users whose primary group or supplementary group list matches one of the patterns. @@ -325,7 +344,7 @@ and can be used as wildcards in the patterns. Only group names are valid; a numerical group ID is not recognized. -By default login is allowed regardless of the group list. +By default, login is allowed for all groups. .Pp .It Cm AllowTcpForwarding Specifies whether TCP forwarding is permitted. @@ -336,7 +355,7 @@ users are also denied shell access, as they can always install their own forwarders. .Pp .It Cm AllowUsers -This keyword can be followed by a list of user names, separated +This keyword can be followed by a list of user name patterns, separated by spaces. If specified, login is allowed only for users names that match one of the patterns. @@ -346,7 +365,7 @@ and can be used as wildcards in the patterns. Only user names are valid; a numerical user ID is not recognized. -By default login is allowed regardless of the user name. +By default, login is allowed for all users. If the pattern takes the form USER@HOST then USER and HOST are separately checked, restricting logins to particular users from particular hosts. @@ -364,7 +383,7 @@ After expansion, is taken to be an absolute path or one relative to the user's home directory. The default is -.Dq .ssh/authorized_keys +.Dq .ssh/authorized_keys . .It Cm Banner In some jurisdictions, sending a warning message before authentication may be relevant for getting legal protection. @@ -383,7 +402,11 @@ The default is Specifies the ciphers allowed for protocol version 2. Multiple ciphers must be comma-separated. The default is -.Dq aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour. +.Pp +.Bd -literal + ``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour, + aes192-cbc,aes256-cbc'' +.Ed .It Cm ClientAliveInterval Sets a timeout interval in seconds after which if no data has been received from the client, @@ -417,20 +440,20 @@ The default value is 3. If is left at the default, unresponsive ssh clients will be disconnected after approximately 45 seconds. .It Cm DenyGroups -This keyword can be followed by a number of group names, separated +This keyword can be followed by a list of group name patterns, separated by spaces. -Users whose primary group or supplementary group list matches -one of the patterns aren't allowed to log in. +Login is disallowed for users whose primary group or supplementary +group list matches one of the patterns. .Ql \&* and .Ql ? can be used as wildcards in the patterns. Only group names are valid; a numerical group ID is not recognized. -By default login is allowed regardless of the group list. +By default, login is allowed for all groups. .Pp .It Cm DenyUsers -This keyword can be followed by a number of user names, separated +This keyword can be followed by a list of user name patterns, separated by spaces. Login is disallowed for user names that match one of the patterns. .Ql \&* @@ -438,7 +461,10 @@ and .Ql ? can be used as wildcards in the patterns. Only user names are valid; a numerical user ID is not recognized. -By default login is allowed regardless of the user name. +By default, login is allowed for all users. +If the pattern takes the form USER@HOST then USER and HOST +are separately checked, restricting logins to particular +users from particular hosts. .It Cm GatewayPorts Specifies whether remote hosts are allowed to connect to ports forwarded for the client. @@ -486,9 +512,15 @@ The default is .Dq yes . Note that this option applies to protocol version 2 only. .It Cm HostKey -Specifies the file containing the private host keys (default -.Pa /etc/ssh_host_key ) -used by SSH protocol versions 1 and 2. +Specifies a file containing a private host key +used by SSH. +The default is +.Pa /etc/ssh/ssh_host_key +for protocol version 1, and +.Pa /etc/ssh/ssh_host_rsa_key +and +.Pa /etc/ssh/ssh_host_dsa_key +for protocol version 2. Note that .Nm will refuse to use a file if it is group/world-accessible. @@ -528,7 +560,7 @@ or The default is .Dq no . .It Cm KeepAlive -Specifies whether the system should send keepalive messages to the +Specifies whether the system should send TCP keepalive messages to the other side. If they are sent, death of the connection or crash of one of the machines will be properly noticed. @@ -543,12 +575,11 @@ users and consuming server resources. The default is .Dq yes (to send keepalives), and the server will notice -if the network goes down or the client host reboots. +if the network goes down or the client host crashes. This avoids infinitely hanging sessions. .Pp To disable keepalives, the value should be set to -.Dq no -in both the server and the client configuration files. +.Dq no . .It Cm KerberosAuthentication Specifies whether Kerberos authentication is allowed. This can be in the form of a Kerberos ticket, or if @@ -631,9 +662,10 @@ The default is 600 (seconds). Gives the verbosity level that is used when logging messages from .Nm sshd . The possible values are: -QUIET, FATAL, ERROR, INFO, VERBOSE and DEBUG. -The default is INFO. -Logging with level DEBUG violates the privacy of users +QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2 and DEBUG3. +The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2 +and DEBUG3 each specify higher levels of debugging output. +Logging with a DEBUG level violates the privacy of users and is not recommended. .It Cm MACs Specifies the available MAC (message authentication code) algorithms. @@ -760,14 +792,6 @@ Specifies whether public key authentication is allowed. The default is .Dq yes . Note that this option applies to protocol version 2 only. -.It Cm ReverseMappingCheck -Specifies whether -.Nm -should try to verify the remote host name and check that -the resolved host name for the remote IP address maps back to the -very same IP address. -The default is -.Dq no . .It Cm RhostsAuthentication Specifies whether authentication using rhosts or /etc/hosts.equiv files is sufficient. @@ -835,6 +859,14 @@ will be disabled because does not know how to handle .Xr xauth 1 cookies. +.It Cm VerifyReverseMapping +Specifies whether +.Nm +should try to verify the remote host name and check that +the resolved host name for the remote IP address maps back to the +very same IP address. +The default is +.Dq no . .It Cm X11DisplayOffset Specifies the first display number available for .Nm sshd Ns 's @@ -852,6 +884,31 @@ way, as users can always install their own forwarders. X11 forwarding is automatically disabled if .Cm UseLogin is enabled. +.It Cm X11UseLocalhost +Specifies whether +.Nm +should bind the X11 forwarding server to the loopback address or to +the wildcard address. By default, +.Nm +binds the forwarding server to the loopback address and sets the +hostname part of the +.Ev DISPLAY +environment variable to +.Dq localhost . +This prevents remote hosts from connecting to the fake display. +However, some older X11 clients may not function with this +configuration. +.Cm X11UseLocalhost +may be set to +.Dq no +to specify that the forwarding server should be bound to the wildcard +address. +The argument must be +.Dq yes +or +.Dq no . +The default is +.Dq yes . .It Cm XAuthLocation Specifies the location of the .Xr xauth 1 @@ -936,7 +993,7 @@ Changes to user's home directory. If .Pa $HOME/.ssh/rc exists, runs it; else if -.Pa /etc/sshrc +.Pa /etc/ssh/sshrc exists, runs it; otherwise runs xauth. The @@ -1073,7 +1130,7 @@ command="dump /home",no-pty,no-port-forwarding 1024 33 23.\|.\|.\|2323 backup.hu permitopen="10.2.1.55:80",permitopen="10.2.1.56:25" 1024 33 23.\|.\|.\|2323 .Sh SSH_KNOWN_HOSTS FILE FORMAT The -.Pa /etc/ssh_known_hosts , +.Pa /etc/ssh/ssh_known_hosts , and .Pa $HOME/.ssh/known_hosts files contain host public keys for all known hosts. @@ -1098,7 +1155,7 @@ pattern on the line. .Pp Bits, exponent, and modulus are taken directly from the RSA host key; they can be obtained, e.g., from -.Pa /etc/ssh_host_key.pub . +.Pa /etc/ssh/ssh_host_key.pub . The optional comment field continues to the end of the line, and is not used. .Pp Lines starting with @@ -1120,7 +1177,7 @@ Note that the lines in these files are typically hundreds of characters long, and you definitely don't want to type in the host keys by hand. Rather, generate them by a script or by taking -.Pa /etc/ssh_host_key.pub +.Pa /etc/ssh/ssh_host_key.pub and adding the host names at the front. .Ss Examples .Bd -literal @@ -1129,19 +1186,19 @@ cvs.openbsd.org,199.185.137.3 ssh-rsa AAAA1234.....= .Ed .Sh FILES .Bl -tag -width Ds -.It Pa /etc/sshd_config +.It Pa /etc/ssh/sshd_config Contains configuration data for .Nm sshd . This file should be writable by root only, but it is recommended (though not necessary) that it be world-readable. -.It Pa /etc/ssh_host_key, /etc/ssh_host_dsa_key, /etc/ssh_host_rsa_key +.It Pa /etc/ssh/ssh_host_key, /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_rsa_key These three files contain the private parts of the host keys. These files should only be owned by root, readable only by root, and not accessible to others. Note that .Nm does not start if this file is group/world-accessible. -.It Pa /etc/ssh_host_key.pub, /etc/ssh_host_dsa_key.pub, /etc/ssh_host_rsa_key.pub +.It Pa /etc/ssh/ssh_host_key.pub, /etc/ssh/ssh_host_dsa_key.pub, /etc/ssh/ssh_host_rsa_key.pub These three files contain the public parts of the host keys. These files should be world-readable but writable only by root. @@ -1174,7 +1231,7 @@ and/or .Pa id_rsa.pub files into this file, as described in .Xr ssh-keygen 1 . -.It Pa "/etc/ssh_known_hosts" and "$HOME/.ssh/known_hosts" +.It Pa "/etc/ssh/ssh_known_hosts" and "$HOME/.ssh/known_hosts" These files are consulted when using rhosts with RSA host authentication or protocol version 2 hostbased authentication to check the public key of the host. @@ -1182,7 +1239,7 @@ The key must be listed in one of these files to be accepted. The client uses the same files to verify that it is connecting to the correct remote host. These files should be writable only by root/the owner. -.Pa /etc/ssh_known_hosts +.Pa /etc/ssh/ssh_known_hosts should be world-readable, and .Pa $HOME/.ssh/known_hosts can but need not be world-readable. @@ -1290,13 +1347,13 @@ something similar to: .Ed .Pp If this file does not exist, -.Pa /etc/sshrc +.Pa /etc/ssh/sshrc is run, and if that does not exist either, xauth is used to store the cookie. .Pp This file should be writable only by the user, and need not be readable by anyone else. -.It Pa /etc/sshrc +.It Pa /etc/ssh/sshrc Like .Pa $HOME/.ssh/rc . This can be used to specify diff --git a/openssh/sshd.c b/openssh/sshd.c index 5c7d8d0..68a743b 100644 --- a/openssh/sshd.c +++ b/openssh/sshd.c @@ -40,11 +40,11 @@ */ #include "includes.h" -RCSID("$OpenBSD: sshd.c,v 1.209 2001/11/10 13:19:45 markus Exp $"); +RCSID("$OpenBSD: sshd.c,v 1.228 2002/02/27 21:23:13 stevesk Exp $"); #include #include -#include +#include #include "ssh.h" #include "ssh1.h" @@ -173,11 +173,11 @@ struct { * Flag indicating whether the RSA server key needs to be regenerated. * Is set in the SIGALRM handler and cleared when the key is regenerated. */ -int key_do_regen = 0; +static volatile sig_atomic_t key_do_regen = 0; /* This is set to true when a signal is received. */ -int received_sighup = 0; -int received_sigterm = 0; +static volatile sig_atomic_t received_sighup = 0; +static volatile sig_atomic_t received_sigterm = 0; /* session identifier, used by RSA-auth */ u_char session_id[16]; @@ -189,6 +189,10 @@ int session_id2_len = 0; /* record remote hostname or ip */ u_int utmp_len = MAXHOSTNAMELEN; +/* options.max_startup sized array of fd ints */ +int *startup_pipes = NULL; +int startup_pipe; /* in child */ + /* Prototypes for various functions defined later in this file. */ void destroy_sensitive_data(void); @@ -207,6 +211,16 @@ close_listen_socks(void) num_listen_socks = -1; } +static void +close_startup_pipes(void) +{ + int i; + if (startup_pipes) + for (i = 0; i < options.max_startups; i++) + if (startup_pipes[i] != -1) + close(startup_pipes[i]); +} + /* * Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP; * the effect is to reread the configuration file (and to regenerate @@ -215,8 +229,11 @@ close_listen_socks(void) static void sighup_handler(int sig) { + int save_errno = errno; + received_sighup = 1; signal(SIGHUP, sighup_handler); + errno = save_errno; } /* @@ -228,6 +245,7 @@ sighup_restart(void) { log("Received SIGHUP; restarting."); close_listen_socks(); + close_startup_pipes(); execv(saved_argv[0], saved_argv); log("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0], strerror(errno)); exit(1); @@ -385,7 +403,7 @@ sshd_exchange_identification(int sock_in, int sock_out) fatal_cleanup(); } debug("Client protocol version %d.%d; client software version %.100s", - remote_major, remote_minor, remote_version); + remote_major, remote_minor, remote_version); compat_datafellows(remote_version); @@ -396,7 +414,7 @@ sshd_exchange_identification(int sock_in, int sock_out) } mismatch = 0; - switch(remote_major) { + switch (remote_major) { case 1: if (remote_minor == 99) { if (options.protocol & SSH_PROTO_2) @@ -453,7 +471,7 @@ destroy_sensitive_data(void) key_free(sensitive_data.server_key); sensitive_data.server_key = NULL; } - for(i = 0; i < options.num_host_key_files; i++) { + for (i = 0; i < options.num_host_key_files; i++) { if (sensitive_data.host_keys[i]) { key_free(sensitive_data.host_keys[i]); sensitive_data.host_keys[i] = NULL; @@ -466,33 +484,37 @@ destroy_sensitive_data(void) static char * list_hostkey_types(void) { - static char buf[1024]; + Buffer b; + char *p; int i; - buf[0] = '\0'; - for(i = 0; i < options.num_host_key_files; i++) { + + buffer_init(&b); + for (i = 0; i < options.num_host_key_files; i++) { Key *key = sensitive_data.host_keys[i]; if (key == NULL) continue; - switch(key->type) { + switch (key->type) { case KEY_RSA: case KEY_DSA: - strlcat(buf, key_ssh_name(key), sizeof buf); - strlcat(buf, ",", sizeof buf); + if (buffer_len(&b) > 0) + buffer_append(&b, ",", 1); + p = key_ssh_name(key); + buffer_append(&b, p, strlen(p)); break; } } - i = strlen(buf); - if (i > 0 && buf[i-1] == ',') - buf[i-1] = '\0'; - debug("list_hostkey_types: %s", buf); - return buf; + buffer_append(&b, "\0", 1); + p = xstrdup(buffer_ptr(&b)); + buffer_free(&b); + debug("list_hostkey_types: %s", p); + return p; } static Key * get_hostkey_by_type(int type) { int i; - for(i = 0; i < options.num_host_key_files; i++) { + for (i = 0; i < options.num_host_key_files; i++) { Key *key = sensitive_data.host_keys[i]; if (key != NULL && key->type == type) return key; @@ -529,8 +551,30 @@ drop_connection(int startups) return (r < p) ? 1 : 0; } -int *startup_pipes = NULL; /* options.max_startup sized array of fd ints */ -int startup_pipe; /* in child */ +static void +usage(void) +{ + fprintf(stderr, "sshd version %s\n", SSH_VERSION); + fprintf(stderr, "Usage: %s [options]\n", __progname); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " -f file Configuration file (default %s)\n", _PATH_SERVER_CONFIG_FILE); + fprintf(stderr, " -d Debugging mode (multiple -d means more debugging)\n"); + fprintf(stderr, " -i Started from inetd\n"); + fprintf(stderr, " -D Do not fork into daemon mode\n"); + fprintf(stderr, " -t Only test configuration file and keys\n"); + fprintf(stderr, " -q Quiet (no logging)\n"); + fprintf(stderr, " -p port Listen on the specified port (default: 22)\n"); + fprintf(stderr, " -k seconds Regenerate server key every this many seconds (default: 3600)\n"); + fprintf(stderr, " -g seconds Grace period for authentication (default: 600)\n"); + fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n"); + fprintf(stderr, " -h file File from which to read host key (default: %s)\n", + _PATH_HOST_KEY_FILE); + fprintf(stderr, " -u len Maximum hostname length for utmp recording\n"); + fprintf(stderr, " -4 Use IPv4 only\n"); + fprintf(stderr, " -6 Use IPv6 only\n"); + fprintf(stderr, " -o option Process the option as if it was read from a configuration file.\n"); + exit(1); +} /* * Main program for the daemon. @@ -568,7 +612,7 @@ main(int ac, char **av) initialize_server_options(&options); /* Parse command-line arguments. */ - while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:dDeiqtQ46")) != -1) { + while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:o:dDeiqtQ46")) != -1) { switch (opt) { case '4': IPv4or6 = AF_INET; @@ -650,27 +694,15 @@ main(int ac, char **av) case 'u': utmp_len = atoi(optarg); break; + case 'o': + if (process_server_config_line(&options, optarg, + "command-line", 0) != 0) + exit(1); + break; case '?': default: - fprintf(stderr, "sshd version %s\n", SSH_VERSION); - fprintf(stderr, "Usage: %s [options]\n", __progname); - fprintf(stderr, "Options:\n"); - fprintf(stderr, " -f file Configuration file (default %s)\n", _PATH_SERVER_CONFIG_FILE); - fprintf(stderr, " -d Debugging mode (multiple -d means more debugging)\n"); - fprintf(stderr, " -i Started from inetd\n"); - fprintf(stderr, " -D Do not fork into daemon mode\n"); - fprintf(stderr, " -t Only test configuration file and keys\n"); - fprintf(stderr, " -q Quiet (no logging)\n"); - fprintf(stderr, " -p port Listen on the specified port (default: 22)\n"); - fprintf(stderr, " -k seconds Regenerate server key every this many seconds (default: 3600)\n"); - fprintf(stderr, " -g seconds Grace period for authentication (default: 600)\n"); - fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n"); - fprintf(stderr, " -h file File from which to read host key (default: %s)\n", - _PATH_HOST_KEY_FILE); - fprintf(stderr, " -u len Maximum hostname length for utmp recording\n"); - fprintf(stderr, " -4 Use IPv4 only\n"); - fprintf(stderr, " -6 Use IPv6 only\n"); - exit(1); + usage(); + break; } } SSLeay_add_all_algorithms(); @@ -681,8 +713,10 @@ main(int ac, char **av) * key (unless started from inetd) */ log_init(__progname, - options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, - options.log_facility == -1 ? SYSLOG_FACILITY_AUTH : options.log_facility, + options.log_level == SYSLOG_LEVEL_NOT_SET ? + SYSLOG_LEVEL_INFO : options.log_level, + options.log_facility == SYSLOG_FACILITY_NOT_SET ? + SYSLOG_FACILITY_AUTH : options.log_facility, !inetd_flag); #ifdef _CRAY @@ -710,14 +744,14 @@ main(int ac, char **av) /* load private host keys */ sensitive_data.host_keys = xmalloc(options.num_host_key_files*sizeof(Key*)); - for(i = 0; i < options.num_host_key_files; i++) + for (i = 0; i < options.num_host_key_files; i++) sensitive_data.host_keys[i] = NULL; sensitive_data.server_key = NULL; sensitive_data.ssh1_host_key = NULL; sensitive_data.have_ssh1_key = 0; sensitive_data.have_ssh2_key = 0; - for(i = 0; i < options.num_host_key_files; i++) { + for (i = 0; i < options.num_host_key_files; i++) { key = key_load_private(options.host_key_files[i], "", NULL); sensitive_data.host_keys[i] = key; if (key == NULL) { @@ -726,7 +760,7 @@ main(int ac, char **av) sensitive_data.host_keys[i] = NULL; continue; } - switch(key->type){ + switch (key->type) { case KEY_RSA1: sensitive_data.ssh1_host_key = key; sensitive_data.have_ssh1_key = 1; @@ -821,7 +855,7 @@ main(int ac, char **av) /* Chdir to the root directory so that the current disk can be unmounted if desired. */ chdir("/"); - + /* ignore SIGPIPE */ signal(SIGPIPE, SIG_IGN); @@ -873,11 +907,11 @@ main(int ac, char **av) * close. */ setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, - (void *) &on, sizeof(on)); + &on, sizeof(on)); linger.l_onoff = 1; linger.l_linger = 5; setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, - (void *) &linger, sizeof(linger)); + &linger, sizeof(linger)); debug("Bind to port %s on %s.", strport, ntop); @@ -970,7 +1004,7 @@ main(int ac, char **av) error("select: %.100s", strerror(errno)); if (received_sigterm) { log("Received signal %d; terminating.", - received_sigterm); + (int) received_sigterm); close_listen_socks(); unlink(options.pid_file); exit(255); @@ -1009,6 +1043,7 @@ main(int ac, char **av) } if (fcntl(newsock, F_SETFL, 0) < 0) { error("newsock del O_NONBLOCK: %s", strerror(errno)); + close(newsock); continue; } if (drop_connection(startups) == 1) { @@ -1062,9 +1097,7 @@ main(int ac, char **av) * the connection. */ startup_pipe = startup_p[1]; - for (j = 0; j < options.max_startups; j++) - if (startup_pipes[j] != -1) - close(startup_pipes[j]); + close_startup_pipes(); close_listen_socks(); sock_in = newsock; sock_out = newsock; @@ -1124,11 +1157,11 @@ main(int ac, char **av) /* setsockopt(sock_in, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */ linger.l_onoff = 1; linger.l_linger = 5; - setsockopt(sock_in, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger)); + setsockopt(sock_in, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)); /* Set keepalives if requested. */ if (options.keepalives && - setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, + setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); @@ -1181,8 +1214,9 @@ main(int ac, char **av) * machine, he can connect from any port. So do not use these * authentication methods from machines that you do not trust. */ - if (remote_port >= IPPORT_RESERVED || - remote_port < IPPORT_RESERVED / 2) { + if (options.rhosts_authentication && + (remote_port >= IPPORT_RESERVED || + remote_port < IPPORT_RESERVED / 2)) { debug("Rhosts Authentication disabled, " "originating port %d not trusted.", remote_port); options.rhosts_authentication = 0; @@ -1231,7 +1265,6 @@ static void do_ssh1_kex(void) { int i, len; - int plen, slen; int rsafail = 0; BIGNUM *session_key_int; u_char session_key[SSH_SESSION_KEY_LENGTH]; @@ -1315,7 +1348,7 @@ do_ssh1_kex(void) BN_num_bits(sensitive_data.ssh1_host_key->rsa->n)); /* Read clients reply (cipher type and session key). */ - packet_read_expect(&plen, SSH_CMSG_SESSION_KEY); + packet_read_expect(SSH_CMSG_SESSION_KEY); /* Get cipher type and check whether we accept this. */ cipher_type = packet_get_char(); @@ -1332,11 +1365,13 @@ do_ssh1_kex(void) debug("Encryption type: %.200s", cipher_name(cipher_type)); /* Get the encrypted integer. */ - session_key_int = BN_new(); - packet_get_bignum(session_key_int, &slen); + if ((session_key_int = BN_new()) == NULL) + fatal("do_ssh1_kex: BN_new failed"); + packet_get_bignum(session_key_int); protocol_flags = packet_get_int(); packet_set_protocol_flags(protocol_flags); + packet_check_eom(); packet_integrity_check(plen, 1 + 8 + slen + 4, SSH_CMSG_SESSION_KEY); @@ -1408,7 +1443,7 @@ do_ssh1_kex(void) } if (rsafail) { int bytes = BN_num_bytes(session_key_int); - char *buf = xmalloc(bytes); + u_char *buf = xmalloc(bytes); MD5_CTX md; log("do_connection: generating a fake encryption key"); -- 2.45.1