From: basney Date: Mon, 31 Aug 2009 18:45:53 +0000 (+0000) Subject: merging OPENSSH_5_2P1_SIMON_20090726_HPN13V6 to trunk: X-Git-Tag: OPENSSH_5_2P1_GSSAPI_20090831~4 X-Git-Url: http://andersk.mit.edu/gitweb/gssapi-openssh.git/commitdiff_plain/c7931c9aedd8e12fdd0df715dcefce0e0c95be6a?hp=-c merging OPENSSH_5_2P1_SIMON_20090726_HPN13V6 to trunk: http://www.psc.edu/networking/projects/hpn-ssh/openssh-5.2p1-hpn13v6.diff.gz http://www.sxw.org.uk/computing/patches/openssh-5.2p1-gsskex-all-20090726.patch --- c7931c9aedd8e12fdd0df715dcefce0e0c95be6a diff --combined openssh/Makefile.in index d448c75,ac8d66d..3d10d92 --- a/openssh/Makefile.in +++ b/openssh/Makefile.in @@@ -59,7 -59,6 +59,7 @@@ EXEEXT=@EXEEXT INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@ +INSTALL_GSISSH=@INSTALL_GSISSH@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT) @@@ -72,8 -71,8 +72,8 @@@ LIBSSH_OBJS=acss.o authfd.o authfile.o atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \ kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \ - kexgssc.o \ - entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o + entropy.o scard-opensc.o gss-genr.o umac.o jpake.o schnorr.o \ + kexgssc.o SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ sshconnect.o sshconnect1.o sshconnect2.o mux.o @@@ -86,9 -85,7 +86,8 @@@ SSHDOBJS=sshd.o auth-rhosts.o auth-pass auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \ monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \ auth-krb5.o \ - auth2-gss.o gss-serv.o gss-serv-krb5.o \ - kexgsss.o \ + auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\ + gss-serv-gsi.o \ loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o @@@ -289,20 -286,6 +288,20 @@@ install-files: scard-instal 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 + if [ ! -z "$(INSTALL_GSISSH)" ]; then \ + rm -f $(DESTDIR)$(bindir)/gsissh; \ + ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/gsissh; \ + rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsissh.1; \ + ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/gsissh.1; \ + rm -f $(DESTDIR)$(bindir)/gsiscp; \ + ln -s ./scp$(EXEEXT) $(DESTDIR)$(bindir)/gsiscp; \ + rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsiscp.1; \ + ln -s ./scp.1 $(DESTDIR)$(mandir)/$(mansubdir)1/gsiscp.1; \ + rm -f $(DESTDIR)$(bindir)/gsisftp; \ + ln -s ./sftp$(EXEEXT) $(DESTDIR)$(bindir)/gsisftp; \ + rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsisftp.1; \ + ln -s ./sftp.1 $(DESTDIR)$(mandir)/$(mansubdir)1/gsisftp.1; \ + fi install-sysconf: if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \ @@@ -374,11 -357,6 +373,11 @@@ uninstallall: uninstal uninstall: -rm -f $(DESTDIR)$(bindir)/slogin + if [ ! -z "$(INSTALL_GSISSH)" ]; then \ + rm -f $(DESTDIR)$(bindir)/gsiscp; \ + rm -f $(DESTDIR)$(bindir)/gsissh; \ + rm -f $(DESTDIR)$(bindir)/gsisftp; \ + fi -rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT) @@@ -392,11 -370,6 +391,11 @@@ -rm -f $(DESTDIR)$(RAND_HELPER)$(EXEEXT) -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 + if [ ! -z "$(INSTALL_GSISSH)" ]; then \ + rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsissh.1; \ + rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsiscp.1; \ + rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsisftp.1; \ + fi -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 diff --combined openssh/auth2-gss.c index 2cf6929,a192d28..1db62c4 --- a/openssh/auth2-gss.c +++ b/openssh/auth2-gss.c @@@ -1,7 -1,7 +1,7 @@@ /* $OpenBSD: auth2-gss.c,v 1.16 2007/10/29 00:52:45 dtucker Exp $ */ /* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. + * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@@ -47,26 -47,11 +47,26 @@@ extern ServerOptions options; +static void ssh_gssapi_userauth_error(Gssctxt *ctxt); static void input_gssapi_token(int type, u_int32_t plen, void *ctxt); static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); static void input_gssapi_errtok(int, u_int32_t, void *); +static int gssapi_with_mic = 1; /* flag to toggle "gssapi-with-mic" vs. + "gssapi" */ + +static int +userauth_external(Authctxt *authctxt) +{ + packet_check_eom(); + + if (authctxt->valid && authctxt->user && authctxt->user[0]) { - return(PRIVSEP(ssh_gssapi_userok(authctxt->user))); ++ return(PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw))); + } + return 0; +} + /* * The 'gssapi_keyex' userauth mechanism. */ @@@ -74,8 -59,8 +74,8 @@@ static in userauth_gsskeyex(Authctxt *authctxt) { int authenticated = 0; - Buffer b; - gss_buffer_desc mic, gssbuf; + Buffer b, b2; + gss_buffer_desc mic, gssbuf, gssbuf2; u_int len; mic.value = packet_get_string(&len); @@@ -89,25 -74,13 +89,26 @@@ gssbuf.value = buffer_ptr(&b); gssbuf.length = buffer_len(&b); + /* client may have used empty username to determine target + name from GSSAPI context */ + ssh_gssapi_buildmic(&b2, "", authctxt->service, "gssapi-keyex"); + + gssbuf2.value = buffer_ptr(&b2); + gssbuf2.length = buffer_len(&b2); + /* gss_kex_context is NULL with privsep, so we can't check it here */ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, - &gssbuf, &mic)))) - authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, - authctxt->pw)); + &gssbuf, &mic))) || + !GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, + &gssbuf2, &mic)))) { + if (authctxt->valid && authctxt->user && authctxt->user[0]) { - authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw)); + } + } buffer_free(&b); + buffer_free(&b2); xfree(mic.value); return (authenticated); @@@ -129,10 -102,7 +130,10 @@@ userauth_gssapi(Authctxt *authctxt u_int len; u_char *doid = NULL; - if (!authctxt->valid || authctxt->user == NULL) + /* authctxt->valid may be 0 if we haven't yet determined + username from gssapi context. */ + + if (authctxt->user == NULL) return (0); mechs = packet_get_int(); @@@ -202,7 -172,7 +203,7 @@@ input_gssapi_token(int type, u_int32_t Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; - OM_uint32 maj_status, min_status, flags; + OM_uint32 maj_status, min_status, flags=0; u_int len; if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) @@@ -220,7 -190,6 +221,7 @@@ xfree(recv_tok.value); if (GSS_ERROR(maj_status)) { + ssh_gssapi_userauth_error(gssctxt); if (send_tok.length != 0) { packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK); packet_put_string(send_tok.value, send_tok.length); @@@ -228,9 -197,7 +229,9 @@@ } authctxt->postponed = 0; dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - userauth_finish(authctxt, 0, "gssapi-with-mic"); + userauth_finish(authctxt, 0, + gssapi_with_mic ? "gssapi-with-mic" : + "gssapi"); } else { if (send_tok.length != 0) { packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); @@@ -239,7 -206,7 +240,7 @@@ } if (maj_status == GSS_S_COMPLETE) { dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); - if (flags & GSS_C_INTEG_FLAG) + if (flags & GSS_C_INTEG_FLAG && gssapi_with_mic) dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, &input_gssapi_mic); else @@@ -286,32 -253,6 +287,32 @@@ input_gssapi_errtok(int type, u_int32_ gss_release_buffer(&maj_status, &send_tok); } +static void +gssapi_set_username(Authctxt *authctxt) +{ + char *lname = NULL; + + if ((authctxt->user == NULL) || (authctxt->user[0] == '\0')) { + PRIVSEP(ssh_gssapi_localname(&lname)); + if (lname && lname[0] != '\0') { + if (authctxt->user) xfree(authctxt->user); + authctxt->user = lname; + debug("set username to %s from gssapi context", lname); + authctxt->pw = PRIVSEP(getpwnamallow(authctxt->user)); + if (authctxt->pw) { + authctxt->valid = 1; +#ifdef USE_PAM + if (options.use_pam) + PRIVSEP(start_pam(authctxt)); +#endif + } + } else { + debug("failed to set username from gssapi context"); + packet_send_debug("failed to set username from gssapi context"); + } + } +} + /* * This is called when the client thinks we've completed authentication. * It should only be enabled in the dispatch handler by the function above, @@@ -328,8 -269,6 +329,8 @@@ input_gssapi_exchange_complete(int type if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep)) fatal("No authentication or GSSAPI context"); + gssapi_set_username(authctxt); + gssctxt = authctxt->methoddata; /* @@@ -339,34 -278,15 +340,35 @@@ packet_check_eom(); - authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, - authctxt->pw)); + /* user should be set if valid but we double-check here */ + if (authctxt->valid && authctxt->user && authctxt->user[0]) { - authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw)); + } else { + authenticated = 0; + } authctxt->postponed = 0; dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); - userauth_finish(authctxt, authenticated, "gssapi-with-mic"); + userauth_finish(authctxt, authenticated, + gssapi_with_mic ? "gssapi-with-mic" : "gssapi"); +} + +static int +userauth_gssapi_with_mic(Authctxt *authctxt) +{ + gssapi_with_mic = 1; + return userauth_gssapi(authctxt); +} + +static int +userauth_gssapi_without_mic(Authctxt *authctxt) +{ + gssapi_with_mic = 0; + return userauth_gssapi(authctxt); } static void @@@ -393,14 -313,9 +395,15 @@@ input_gssapi_mic(int type, u_int32_t pl gssbuf.value = buffer_ptr(&b); gssbuf.length = buffer_len(&b); + gssapi_set_username(authctxt); + if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) - authenticated = - PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)); + if (authctxt->valid && authctxt->user && authctxt->user[0]) { - authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = ++ PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)); + } else { - authenticated = 0; ++ authenticated = 0; + } else logit("GSSAPI MIC check failed"); @@@ -415,29 -330,6 +418,29 @@@ userauth_finish(authctxt, authenticated, "gssapi-with-mic"); } +static void ssh_gssapi_userauth_error(Gssctxt *ctxt) { + char *errstr; + OM_uint32 maj,min; + + errstr=PRIVSEP(ssh_gssapi_last_error(ctxt,&maj,&min)); + if (errstr) { + packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERROR); + packet_put_int(maj); + packet_put_int(min); + packet_put_cstring(errstr); + packet_put_cstring(""); + packet_send(); + packet_write_wait(); + xfree(errstr); + } +} + +Authmethod method_external = { + "external-keyx", + userauth_external, + &options.gss_authentication +}; + Authmethod method_gsskeyex = { "gssapi-keyex", userauth_gsskeyex, @@@ -446,13 -338,7 +449,13 @@@ Authmethod method_gssapi = { "gssapi-with-mic", - userauth_gssapi, + userauth_gssapi_with_mic, + &options.gss_authentication +}; + +Authmethod method_gssapi_compat = { + "gssapi", + userauth_gssapi_without_mic, &options.gss_authentication }; diff --combined openssh/auth2.c index 2e46638,c6c983a..1cd3e10 --- a/openssh/auth2.c +++ b/openssh/auth2.c @@@ -70,10 -70,8 +70,10 @@@ extern Authmethod method_passwd extern Authmethod method_kbdint; extern Authmethod method_hostbased; #ifdef GSSAPI +extern Authmethod method_external; extern Authmethod method_gsskeyex; extern Authmethod method_gssapi; +extern Authmethod method_gssapi_compat; #endif #ifdef JPAKE extern Authmethod method_jpake; @@@ -87,9 -85,7 +87,9 @@@ Authmethod *authmethods[] = &method_pubkey, #ifdef GSSAPI &method_gsskeyex, + &method_external, &method_gssapi, + &method_gssapi_compat, #endif #ifdef JPAKE &method_jpake, @@@ -234,32 -230,10 +234,32 @@@ input_userauth_request(int type, u_int3 user = packet_get_string(NULL); service = packet_get_string(NULL); method = packet_get_string(NULL); - debug("userauth-request for user %s service %s method %s", user, service, method); + +#ifdef GSSAPI + if (user[0] == '\0') { + debug("received empty username for %s", method); + if (strcmp(method, "external-keyx") == 0 || + strcmp(method, "gssapi-keyex") == 0) { + char *lname = NULL; + PRIVSEP(ssh_gssapi_localname(&lname)); + if (lname && lname[0] != '\0') { + xfree(user); + user = lname; + debug("set username to %s from gssapi context", user); + } else { + debug("failed to set username from gssapi context"); + packet_send_debug("failed to set username from gssapi context"); + } + } + } +#endif + + debug("userauth-request for user %s service %s method %s", + user[0] ? user : "", service, method); if (!log_flag) { logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s", - get_remote_ipaddr(), get_remote_port(), user); + get_remote_ipaddr(), get_remote_port(), + user[0] ? user : ""); log_flag = 1; } debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); @@@ -267,32 -241,11 +267,32 @@@ if ((style = strchr(user, ':')) != NULL) *style++ = 0; - if (authctxt->attempt++ == 0) { - /* setup auth context */ + /* If first time or username changed or empty username, + setup/reset authentication context. */ + if ((authctxt->attempt++ == 0) || + (strcmp(user, authctxt->user) != 0) || + (strcmp(user, "") == 0)) { + if (authctxt->user) { + xfree(authctxt->user); + authctxt->user = NULL; + } + authctxt->valid = 0; + authctxt->user = xstrdup(user); + if (strcmp(service, "ssh-connection") != 0) { + packet_disconnect("Unsupported service %s", service); + } +#ifdef GSSAPI + /* If we're going to set the username based on the + GSSAPI context later, then wait until then to + verify it. Just put in placeholders for now. */ + if ((strcmp(user, "") == 0) && + ((strcmp(method, "gssapi") == 0) || + (strcmp(method, "gssapi-with-mic") == 0))) { + authctxt->pw = fakepw(); + } else { +#endif authctxt->pw = PRIVSEP(getpwnamallow(user)); - authctxt->user = xstrdup(user); - if (authctxt->pw && strcmp(service, "ssh-connection")==0) { + if (authctxt->pw) { authctxt->valid = 1; debug2("input_userauth_request: setting up authctxt for %s", user); } else { @@@ -302,25 -255,20 +302,25 @@@ PRIVSEP(audit_event(SSH_INVALID_USER)); #endif } +#ifdef GSSAPI + } /* endif for setting username based on GSSAPI context */ +#endif #ifdef USE_PAM if (options.use_pam) PRIVSEP(start_pam(authctxt)); #endif setproctitle("%s%s", authctxt->valid ? user : "unknown", use_privsep ? " [net]" : ""); - authctxt->service = xstrdup(service); - authctxt->style = style ? xstrdup(style) : NULL; - if (use_privsep) - mm_inform_authserv(service, style); - userauth_banner(); - } else if (strcmp(user, authctxt->user) != 0 || - strcmp(service, authctxt->service) != 0) { - packet_disconnect("Change of username or service not allowed: " + if (authctxt->attempt == 1) { + authctxt->service = xstrdup(service); + authctxt->style = style ? xstrdup(style) : NULL; + if (use_privsep) + mm_inform_authserv(service, style); + userauth_banner(); + } + } + if (strcmp(service, authctxt->service) != 0) { + packet_disconnect("Change of service not allowed: " "(%s,%s) -> (%s,%s)", authctxt->user, authctxt->service, user, service); } @@@ -408,10 -356,10 +408,10 @@@ userauth_finish(Authctxt *authctxt, in /* now we can break out */ authctxt->success = 1; } else { - + /* Dont count server configuration issues against the client */ /* Allow initial try of "none" auth without failure penalty */ if (!authctxt->server_caused_failure && - (authctxt->attempt > 1 || strcmp(method, "none") != 0)) + (authctxt->attempt > 1 || strcmp(method, "none") != 0)) authctxt->failures++; if (authctxt->failures >= options.max_authtries) { #ifdef SSH_AUDIT_EVENTS diff --combined openssh/channels.c index 6996bde,c689e52..79c7696 --- a/openssh/channels.c +++ b/openssh/channels.c @@@ -818,6 -818,8 +818,6 @@@ int channel_tcpwinsz () /* return no more than 64MB */ if ((ret == 0) && tcpwinsz > BUFFER_MAX_LEN_HPN) tcpwinsz = BUFFER_MAX_LEN_HPN; - debug2("tcpwinsz: %d for connection: %d", tcpwinsz, - packet_get_connection_in()); return(tcpwinsz); } @@@ -2662,10 -2664,10 +2662,10 @@@ channel_setup_fwd_listener(int type, co c = channel_new("port listener", type, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "port listener", 1); - else - c = channel_new("port listener", type, sock, sock, -1, - hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, - 0, "port listener", 1); + else + c = channel_new("port listener", type, sock, sock, -1, + hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, + 0, "port listener", 1); c->path = xstrdup(host); c->host_port = port_to_connect; c->listening_port = listen_port; diff --combined openssh/configure.ac index 6302923,ccc53a5..afc39b4 --- a/openssh/configure.ac +++ b/openssh/configure.ac @@@ -19,115 -19,6 +19,115 @@@ AC_REVISION($Revision$ AC_CONFIG_SRCDIR([ssh.c]) AC_CONFIG_HEADER(config.h) + +# Handle Globus configuration right away, because the Globus flavor +# determines our compiler options. + +# Check whether the user wants GSI (Globus) support +gsi_path="no" +AC_ARG_WITH(gsi, + [ --with-gsi Enable Globus GSI authentication support], + [ + gsi_path="$withval" + ] +) + +AC_ARG_WITH(globus, + [ --with-globus Enable Globus GSI authentication support], + [ + gsi_path="$withval" + ] +) + +AC_ARG_WITH(globus-static, + [ --with-globus-static Link statically with Globus GSI libraries], + [ + gsi_static="-static" + if test "x$gsi_path" = "xno" ; then + gsi_path="$withval" + fi + ] +) + +# Check whether the user has a Globus flavor type +globus_flavor_type="no" +AC_ARG_WITH(globus-flavor, + [ --with-globus-flavor=TYPE Specify Globus flavor type (ex: gcc32dbg)], + [ + globus_flavor_type="$withval" + if test "x$gsi_path" = "xno" ; then + gsi_path="yes" + fi + ] +) + +if test "x$gsi_path" != "xno" ; then + # Globus GSSAPI configuration + AC_MSG_CHECKING(for Globus GSI) + AC_DEFINE(GSI, 1, [Define if you want GSI/Globus authentication support.]) + + if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then + AC_MSG_ERROR([Previously configured GSSAPI library conflicts with Globus GSI.]) + fi + if test -z "$GSSAPI"; then + AC_DEFINE(GSSAPI) + GSSAPI="GSI" + fi + + if test "x$gsi_path" = "xyes" ; then + if test -z "$GLOBUS_LOCATION" ; then + AC_MSG_ERROR(GLOBUS_LOCATION environment variable must be set.) + else + gsi_path="$GLOBUS_LOCATION" + fi + fi + GLOBUS_LOCATION="$gsi_path" + export GLOBUS_LOCATION + if test ! -d "$GLOBUS_LOCATION" ; then + AC_MSG_ERROR(Cannot find Globus installation. Set GLOBUS_LOCATION environment variable.) + fi + + if test "x$globus_flavor_type" = "xno" ; then + AC_MSG_ERROR(--with-globus-flavor=TYPE must be specified) + fi + if test "x$globus_flavor_type" = "xyes" ; then + AC_MSG_ERROR(--with-globus-flavor=TYPE must specify a flavor type) + fi + + GLOBUS_INCLUDE="${gsi_path}/include/${globus_flavor_type}" + if test ! -d "$GLOBUS_INCLUDE" ; then + AC_MSG_ERROR(Cannot find Globus flavor-specific include directory: ${GLOBUS_INCLUDE}) + fi + + if test -x ${gsi_path}/bin/globus-makefile-header ; then + ${gsi_path}/bin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | sed 's/ = \(.*\)/="\1"/' > ./gpt_build_tmp.sh + elif test -x ${gsi_path}/sbin/globus-makefile-header ; then + ${gsi_path}/sbin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | sed 's/ = \(.*\)/="\1"/' > ./gpt_build_tmp.sh + else + AC_MSG_ERROR(Cannot find globus-makefile-header: Globus installation is incomplete) + fi + . ./gpt_build_tmp.sh + if test -z "$GLOBUS_PKG_LIBS" ; then + AC_MSG_ERROR(globus-makefile-header failed) + fi + + AC_MSG_RESULT($GLOBUS_LOCATION) + AC_DEFINE(HAVE_GSSAPI_H) + + CC="$GLOBUS_CC" + CFLAGS="$GLOBUS_CFLAGS" + CPP="$GLOBUS_CPP" + CPPFLAGS="$GLOBUS_CPPFLAGS $GLOBUS_INCLUDES" + LIBS="$LIBS $GLOBUS_LIBS $GLOBUS_PKG_LIBS" + LD="$GLOBUS_LD" + LDFLAGS="$LDFLAGS $GLOBUS_LDFLAGS" + + INSTALL_GSISSH="yes" +else + INSTALL_GSISSH="" +fi +# End Globus/GSI section + AC_PROG_CC AC_CANONICAL_HOST AC_C_BIGENDIAN @@@ -561,8 -452,16 +561,8 @@@ int main(void) { exit(0); AC_DEFINE(BROKEN_SETREGID) ;; *-*-darwin*) - AC_MSG_CHECKING(if we have working getaddrinfo) - AC_TRY_RUN([#include -main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) - exit(0); - else - exit(1); -}], [AC_MSG_RESULT(working)], - [AC_MSG_RESULT(buggy) - AC_DEFINE(BROKEN_GETADDRINFO, 1, [getaddrinfo is broken (if present)])], - [AC_MSG_RESULT(assume it is working)]) + AC_DEFINE(BROKEN_GETADDRINFO, 1, [Define if getaddrinfo is broken)]) + AC_DEFINE(BROKEN_GETADDRINFO) AC_DEFINE(SETEUID_BREAKS_SETUID) AC_DEFINE(BROKEN_SETREUID) AC_DEFINE(BROKEN_SETREGID) @@@ -574,13 -473,6 +574,6 @@@ [Use tunnel device compatibility to OpenBSD]) AC_DEFINE(SSH_TUN_PREPEND_AF, 1, [Prepend the address family to IP tunnel traffic]) - m4_pattern_allow(AU_IPv) - AC_CHECK_DECL(AU_IPv4, [], - AC_DEFINE(AU_IPv4, 0, [System only supports IPv4 audit records]) - [#include ] - AC_DEFINE(LASTLOG_WRITE_PUTUTXLINE, 1, - [Define if pututxline updates lastlog too]) - ) AC_MSG_CHECKING(if we have the Security Authorization Session API) AC_TRY_COMPILE([#include ], [SessionCreate(0, 0);], @@@ -605,6 -497,13 +598,13 @@@ fi], [AC_MSG_RESULT(no)] ) + m4_pattern_allow(AU_IPv) + AC_CHECK_DECL(AU_IPv4, [], + AC_DEFINE(AU_IPv4, 0, [System only supports IPv4 audit records]) + [#include ] + AC_DEFINE(LASTLOG_WRITE_PUTUTXLINE, 1, + [Define if pututxline updates lastlog too]) + ) ;; *-*-dragonfly*) SSHDLIBS="$SSHDLIBS -lcrypt" @@@ -2005,9 -1904,7 +2005,9 @@@ AC_ARG_WITH(ssl-dir fi ] ) +if test -z "$GLOBUS_LDFLAGS" ; then LIBS="-lcrypto $LIBS" +fi AC_TRY_LINK_FUNC(RAND_add, AC_DEFINE(HAVE_OPENSSL, 1, [Define if your ssl headers are included with #include ]), @@@ -3467,55 -3364,6 +3467,55 @@@ AC_ARG_WITH(selinux fi ] ) +# Finish configuring Globus GSSAPI +if test "x$gsi_path" != "xno" ; then + if test ! -z "$need_dash_r" ; then + LDFLAGS="$LDFLAGS -R${gsi_path}/lib" + fi + if test ! -z "$blibpath" ; then + blibpath="$blibpath:${gsi_path}/lib" + fi + # test that we got the libraries OK + AC_TRY_LINK( + [], + [], + [], + [ + AC_MSG_ERROR(link with Globus libraries failed) + ] + ) + AC_CHECK_FUNCS(globus_gss_assist_map_and_authorize) +fi +AC_SUBST(INSTALL_GSISSH) + +# Check whether the user wants GSSAPI mechglue support +AC_ARG_WITH(mechglue, + [ --with-mechglue=PATH Build with GSSAPI mechglue library], + [ + AC_MSG_CHECKING(for mechglue library) + + if test -e ${withval}/libgssapi.a ; then + mechglue_lib=${withval}/libgssapi.a + elif test -e ${withval}/lib/libgssapi.a ; then + mechglue_lib=${withval}/lib/libgssapi.a + else + AC_MSG_ERROR("Can't find libgssapi in ${withval}"); + fi + LIBS="${mechglue_lib} $LIBS" + AC_MSG_RESULT(${mechglue_lib}) + + AC_CHECK_LIB(dl, dlopen, , ) + if test $ac_cv_lib_dl_dlopen = yes; then + LDFLAGS="$LDFLAGS -ldl -Wl,-Bsymbolic" + fi + + AC_DEFINE(GSSAPI) + AC_DEFINE(MECHGLUE, 1, [Define this if you're building with GSSAPI MechGlue.]) + GSSAPI="mechglue" + ] +) + + # Check whether user wants Kerberos 5 support KRB5_MSG="no" AC_ARG_WITH(kerberos5, @@@ -3603,21 -3451,7 +3603,21 @@@ AC_CHECK_HEADER(gssapi_krb5.h, , [ CPPFLAGS="$oldCPP" ]) - fi + # If we're using some other GSSAPI + if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then + AC_MSG_ERROR([$GSSAPI GSSAPI library conflicts with Kerberos support. Use mechglue instead.]) + fi + + if test -z "$GSSAPI"; then + GSSAPI="KRB5"; + fi + + oldCPP="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" + AC_CHECK_HEADER(gssapi_krb5.h, , + [ CPPFLAGS="$oldCPP" ]) + + fi if test ! -z "$need_dash_r" ; then LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib" fi @@@ -3636,42 -3470,6 +3636,42 @@@ ] ) +# Check whether user wants AFS_KRB5 support +AFS_KRB5_MSG="no" +AC_ARG_WITH(afs-krb5, + [ --with-afs-krb5[[=AKLOG_PATH]] Enable aklog to get token (default=/usr/bin/aklog).], + [ + if test "x$withval" != "xno" ; then + + if test "x$withval" != "xyes" ; then + AC_DEFINE_UNQUOTED(AKLOG_PATH, "$withval", + [Define this if you want to use AFS/Kerberos 5 option, which runs aklog.]) + else + AC_DEFINE_UNQUOTED(AKLOG_PATH, + "/usr/bin/aklog", + [Define this if you want to use AFS/Kerberos 5 option, which runs aklog.]) + fi + + if test -z "$KRB5ROOT" ; then + AC_MSG_WARN([AFS_KRB5 requires Kerberos 5 support, build may fail]) + fi + + LIBS="-lkrbafs -lkrb4 $LIBS" + if test ! -z "$AFS_LIBS" ; then + LIBS="$LIBS $AFS_LIBS" + fi + AC_DEFINE(AFS_KRB5, 1, + [Define this if you want to use AFS/Kerberos 5 option, which runs aklog.]) + AFS_KRB5_MSG="yes" + fi + ] +) + +AC_ARG_WITH(session-hooks, + [ --with-session-hooks Enable hooks for executing external commands before/after a session], + [ AC_DEFINE(SESSION_HOOKS, 1, [Define this if you want support for startup/shutdown hooks]) ] +) + # Looking for programs, paths and files PRIVSEP_PATH=/var/empty @@@ -3707,10 -3505,7 +3707,10 @@@ AC_ARG_WITH(xauth ] ) +# strip causes problems with GSI libraries... +if test -z "$GLOBUS_LDFLAGS" ; then STRIP_OPT=-s +fi AC_ARG_ENABLE(strip, [ --disable-strip Disable calling strip(1) on install], [ diff --combined openssh/gss-genr.c index 92cd09a,c51fa72..a8255c3 --- a/openssh/gss-genr.c +++ b/openssh/gss-genr.c @@@ -1,7 -1,7 +1,7 @@@ /* $OpenBSD: gss-genr.c,v 1.19 2007/06/12 11:56:15 dtucker Exp $ */ /* - * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@@ -38,7 -38,6 +38,7 @@@ #include "xmalloc.h" #include "buffer.h" #include "log.h" +#include "canohost.h" #include "ssh2.h" #include "cipher.h" #include "key.h" @@@ -77,19 -76,20 +77,20 @@@ ssh_gssapi_oid_table_ok() */ char * - ssh_gssapi_client_mechanisms(const char *host) { + ssh_gssapi_client_mechanisms(const char *host, const char *client) { gss_OID_set gss_supported; OM_uint32 min_status; - gss_indicate_mechs(&min_status, &gss_supported); + if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) + return NULL; return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, - host)); + host, client)); } char * ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, - const char *data) { + const char *host, const char *client) { Buffer buf; size_t i; int oidpos, enclen; @@@ -113,7 -113,7 +114,7 @@@ oidpos = 0; for (i = 0; i < gss_supported->count; i++) { if (gss_supported->elements[i].length < 128 && - (*check)(NULL, &(gss_supported->elements[i]), data)) { + (*check)(NULL, &(gss_supported->elements[i]), host, client)) { deroid[0] = SSH_GSS_OIDTYPE; deroid[1] = gss_supported->elements[i].length; @@@ -172,12 -172,18 +173,18 @@@ ssh_gssapi_id_kex(Gssctxt *ctx, char *n switch (kex_type) { case KEX_GSS_GRP1_SHA1: + if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID)) + return GSS_C_NO_OID; name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; break; case KEX_GSS_GRP14_SHA1: + if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID)) + return GSS_C_NO_OID; name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; break; case KEX_GSS_GEX_SHA1: + if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID)) + return GSS_C_NO_OID; name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; break; default: @@@ -304,13 -310,10 +311,13 @@@ ssh_gssapi_build_ctx(Gssctxt **ctx void ssh_gssapi_delete_ctx(Gssctxt **ctx) { +#if !defined(MECHGLUE) OM_uint32 ms; +#endif if ((*ctx) == NULL) return; +#if !defined(MECHGLUE) /* mechglue has some memory management issues */ if ((*ctx)->context != GSS_C_NO_CONTEXT) gss_delete_sec_context(&ms, &(*ctx)->context, GSS_C_NO_BUFFER); if ((*ctx)->name != GSS_C_NO_NAME) @@@ -326,7 -329,6 +333,7 @@@ gss_release_name(&ms, &(*ctx)->client); if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL) gss_release_cred(&ms, &(*ctx)->client_creds); +#endif xfree(*ctx); *ctx = NULL; @@@ -350,7 -352,7 +357,7 @@@ ssh_gssapi_init_ctx(Gssctxt *ctx, int d } ctx->major = gss_init_sec_context(&ctx->minor, - GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid, + ctx->client_creds, &ctx->context, ctx->name, ctx->oid, GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 0, NULL, recv_tok, NULL, send_tok, flags, NULL); @@@ -365,18 -367,9 +372,18 @@@ OM_uint3 ssh_gssapi_import_name(Gssctxt *ctx, const char *host) { gss_buffer_desc gssbuf; + char *xhost; char *val; - xasprintf(&val, "host@%s", host); + /* Make a copy of the host name, in case it was returned by a + * previous call to gethostbyname(). */ + xhost = xstrdup(host); + + /* Make sure we have the FQDN. Some GSSAPI implementations don't do + * this for us themselves */ + resolve_localhost(&xhost); + + xasprintf(&val, "host@%s", xhost); gssbuf.value = val; gssbuf.length = strlen(gssbuf.value); @@@ -384,14 -377,47 +391,48 @@@ &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name))) ssh_gssapi_error(ctx); + xfree(xhost); xfree(gssbuf.value); return (ctx->major); } + OM_uint32 + ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) + { + gss_buffer_desc gssbuf; + gss_name_t gssname; + OM_uint32 status; + gss_OID_set oidset; + + gssbuf.value = (void *) name; + gssbuf.length = strlen(gssbuf.value); + + gss_create_empty_oid_set(&status, &oidset); + gss_add_oid_set_member(&status, ctx->oid, &oidset); + + ctx->major = gss_import_name(&ctx->minor, &gssbuf, + GSS_C_NT_USER_NAME, &gssname); + + if (!ctx->major) + ctx->major = gss_acquire_cred(&ctx->minor, + gssname, 0, oidset, GSS_C_INITIATE, + &ctx->client_creds, NULL, NULL); + + gss_release_name(&status, &gssname); + gss_release_oid_set(&status, &oidset); + + if (ctx->major) + ssh_gssapi_error(ctx); + + return(ctx->major); + } + OM_uint32 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) { + if (ctx == NULL) + return -1; + if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); @@@ -400,17 -426,16 +441,16 @@@ } /* Priviledged when used by server */ - /* Moved here from gss-serv.c because called by kexgss_client(). */ OM_uint32 ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) { - if (ctx == NULL) - return -1; + if (ctx == NULL) + return -1; - ctx->major = gss_verify_mic(&ctx->minor, ctx->context, - gssbuf, gssmic, NULL); + ctx->major = gss_verify_mic(&ctx->minor, ctx->context, + gssbuf, gssmic, NULL); - return (ctx->major); + return (ctx->major); } void @@@ -426,7 -451,8 +466,8 @@@ ssh_gssapi_buildmic(Buffer *b, const ch } int - ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) + ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, + const char *client) { gss_buffer_desc token = GSS_C_EMPTY_BUFFER; OM_uint32 major, minor; @@@ -444,6 -470,10 +485,10 @@@ ssh_gssapi_build_ctx(ctx); ssh_gssapi_set_oid(*ctx, oid); major = ssh_gssapi_import_name(*ctx, host); + + if (!GSS_ERROR(major) && client) + major = ssh_gssapi_client_identity(*ctx, client); + if (!GSS_ERROR(major)) { major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, NULL); @@@ -459,4 -489,61 +504,61 @@@ return (!GSS_ERROR(major)); } + int + ssh_gssapi_credentials_updated(Gssctxt *ctxt) { + static gss_name_t saved_name = GSS_C_NO_NAME; + static OM_uint32 saved_lifetime = 0; + static gss_OID saved_mech = GSS_C_NO_OID; + static gss_name_t name; + static OM_uint32 last_call = 0; + OM_uint32 lifetime, now, major, minor; + int equal; + gss_cred_usage_t usage = GSS_C_INITIATE; + + now = time(NULL); + + if (ctxt) { + debug("Rekey has happened - updating saved versions"); + + if (saved_name != GSS_C_NO_NAME) + gss_release_name(&minor, &saved_name); + + major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, + &saved_name, &saved_lifetime, NULL, NULL); + + if (!GSS_ERROR(major)) { + saved_mech = ctxt->oid; + saved_lifetime+= now; + } else { + /* Handle the error */ + } + return 0; + } + + if (now - last_call < 10) + return 0; + + last_call = now; + + if (saved_mech == GSS_C_NO_OID) + return 0; + + major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, + &name, &lifetime, NULL, NULL); + if (major == GSS_S_CREDENTIALS_EXPIRED) + return 0; + else if (GSS_ERROR(major)) + return 0; + + major = gss_compare_name(&minor, saved_name, name, &equal); + gss_release_name(&minor, &name); + if (GSS_ERROR(major)) + return 0; + + if (equal && (saved_lifetime < lifetime + now - 10)) + return 1; + + return 0; + } + #endif /* GSSAPI */ diff --combined openssh/gss-serv-gsi.c index e31d70c,0000000..e77db62 mode 100644,000000..100644 --- a/openssh/gss-serv-gsi.c +++ b/openssh/gss-serv-gsi.c @@@ -1,225 -1,0 +1,226 @@@ +/* + * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "includes.h" + +#ifdef GSSAPI +#ifdef GSI + +#include + +#include +#include + +#include "xmalloc.h" +#include "key.h" +#include "hostfile.h" +#include "auth.h" +#include "log.h" +#include "servconf.h" + +#include "buffer.h" +#include "ssh-gss.h" + +extern ServerOptions options; + +#include + +static int ssh_gssapi_gsi_userok(ssh_gssapi_client *client, char *name); +static int ssh_gssapi_gsi_localname(ssh_gssapi_client *client, char **user); +static void ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client); + +ssh_gssapi_mech gssapi_gsi_mech = { + "dZuIebMjgUqaxvbF7hDbAw==", + "GSI", + {9, "\x2B\x06\x01\x04\x01\x9B\x50\x01\x01"}, + NULL, + &ssh_gssapi_gsi_userok, + &ssh_gssapi_gsi_localname, - &ssh_gssapi_gsi_storecreds ++ &ssh_gssapi_gsi_storecreds, ++ NULL +}; + +/* + * Check if this user is OK to login under GSI. User has been authenticated + * as identity in global 'client_name.value' and is trying to log in as passed + * username in 'name'. + * + * Returns non-zero if user is authorized, 0 otherwise. + */ +static int +ssh_gssapi_gsi_userok(ssh_gssapi_client *client, char *name) +{ + int authorized = 0; + globus_result_t res; +#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + char lname[256] = ""; +#endif + +#ifdef GLOBUS_GSI_GSS_ASSIST_MODULE + if (globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE) != 0) { + return 0; + } +#endif + +/* use new globus_gss_assist_map_and_authorize() interface if available */ +#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + debug("calling globus_gss_assist_map_and_authorize()"); + if (GLOBUS_SUCCESS != + (res = globus_gss_assist_map_and_authorize(client->context, "ssh", + name, lname, 256))) { + debug("%s", globus_error_print_chain(globus_error_get(res))); + } else if (lname && lname[0] && strcmp(name, lname) != 0) { + debug("GSI user maps to %s, not %s", lname, name); + } else { + authorized = 1; + } +#else + debug("calling globus_gss_assist_userok()"); + if (GLOBUS_SUCCESS != + (res = (globus_gss_assist_userok(client->displayname.value, + name)))) { + debug("%s", globus_error_print_chain(globus_error_get(res))); + } else { + authorized = 1; + } +#endif + + logit("GSI user %s is%s authorized as target user %s", + (char *) client->displayname.value, (authorized ? "" : " not"), name); + + return authorized; +} + +/* + * Return the local username associated with the GSI credentials. + */ +int +ssh_gssapi_gsi_localname(ssh_gssapi_client *client, char **user) +{ + globus_result_t res; +#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + char lname[256] = ""; +#endif + +#ifdef GLOBUS_GSI_GSS_ASSIST_MODULE + if (globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE) != 0) { + return 0; + } +#endif + +/* use new globus_gss_assist_map_and_authorize() interface if available */ +#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE + debug("calling globus_gss_assist_map_and_authorize()"); + if (GLOBUS_SUCCESS != + (res = globus_gss_assist_map_and_authorize(client->context, "ssh", + NULL, lname, 256))) { + debug("%s", globus_error_print_chain(globus_error_get(res))); + logit("failed to map GSI user %s", (char *)client->displayname.value); + return 0; + } + *user = strdup(lname); +#else + debug("calling globus_gss_assist_gridmap()"); + if (GLOBUS_SUCCESS != + (res = globus_gss_assist_gridmap(client->displayname.value, user))) { + debug("%s", globus_error_print_chain(globus_error_get(res))); + logit("failed to map GSI user %s", (char *)client->displayname.value); + return 0; + } +#endif + + logit("GSI user %s mapped to target user %s", + (char *) client->displayname.value, *user); + + return 1; +} + +/* + * Export GSI credentials to disk. + */ +static void +ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client) +{ + OM_uint32 major_status; + OM_uint32 minor_status; + gss_buffer_desc export_cred = GSS_C_EMPTY_BUFFER; + char * p; + + if (!client || !client->creds) { + return; + } + + major_status = gss_export_cred(&minor_status, + client->creds, + GSS_C_NO_OID, + 1, + &export_cred); + if (GSS_ERROR(major_status) && major_status != GSS_S_UNAVAILABLE) { + Gssctxt *ctx; + ssh_gssapi_build_ctx(&ctx); + ctx->major = major_status; + ctx->minor = minor_status; + ssh_gssapi_set_oid(ctx, &gssapi_gsi_mech.oid); + ssh_gssapi_error(ctx); + ssh_gssapi_delete_ctx(&ctx); + return; + } + + p = strchr((char *) export_cred.value, '='); + if (p == NULL) { + logit("Failed to parse exported credentials string '%.100s'", + (char *)export_cred.value); + gss_release_buffer(&minor_status, &export_cred); + return; + } + *p++ = '\0'; + if (strcmp((char *)export_cred.value,"X509_USER_DELEG_PROXY") == 0) { + client->store.envvar = strdup("X509_USER_PROXY"); + } else { + client->store.envvar = strdup((char *)export_cred.value); + } + if (access(p, R_OK) == 0) { + if (client->store.filename) { + if (rename(p, client->store.filename) < 0) { + logit("Failed to rename %s to %s: %s", p, + client->store.filename, strerror(errno)); + xfree(client->store.filename); + client->store.filename = strdup(p); + } else { + p = client->store.filename; + } + } else { + client->store.filename = strdup(p); + } + } + client->store.envval = strdup(p); +#ifdef USE_PAM + if (options.use_pam) + do_pam_putenv(client->store.envvar, client->store.envval); +#endif + gss_release_buffer(&minor_status, &export_cred); +} + +#endif /* GSI */ +#endif /* GSSAPI */ diff --combined openssh/gss-serv-krb5.c index bea0eae,e7170ee..a439393 --- a/openssh/gss-serv-krb5.c +++ b/openssh/gss-serv-krb5.c @@@ -1,7 -1,7 +1,7 @@@ /* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */ /* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. + * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@@ -48,7 -48,7 +48,7 @@@ extern ServerOptions options #ifdef HEIMDAL # include -#else +#elif !defined(MECHGLUE) # ifdef HAVE_GSSAPI_KRB5_H # include # elif HAVE_GSSAPI_GSSAPI_KRB5_H @@@ -57,20 -57,6 +57,21 @@@ #endif static krb5_context krb_context = NULL; +static int ssh_gssapi_krb5_init(); +static int ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name); +static int ssh_gssapi_krb5_localname(ssh_gssapi_client *client, char **user); +static void ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client); + +ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", + {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, + NULL, + &ssh_gssapi_krb5_userok, + &ssh_gssapi_krb5_localname, - &ssh_gssapi_krb5_storecreds ++ &ssh_gssapi_krb5_storecreds, ++ &ssh_gssapi_krb5_updatecreds +}; /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ @@@ -123,35 -109,6 +124,35 @@@ ssh_gssapi_krb5_userok(ssh_gssapi_clien } +/* Retrieve the local username associated with a set of Kerberos + * credentials. Hopefully we can use this for the 'empty' username + * logins discussed in the draft */ +static int +ssh_gssapi_krb5_localname(ssh_gssapi_client *client, char **user) { + krb5_principal princ; + int retval; + + if (ssh_gssapi_krb5_init() == 0) + return 0; + + if ((retval=krb5_parse_name(krb_context, client->displayname.value, + &princ))) { + logit("krb5_parse_name(): %.100s", + krb5_get_err_text(krb_context,retval)); + return 0; + } + + /* We've got to return a malloc'd string */ + *user = (char *)xmalloc(256); + if (krb5_aname_to_localname(krb_context, princ, 256, *user)) { + xfree(*user); + *user = NULL; + return(0); + } + + return(1); +} + /* This writes out any forwarded credentials from the structure populated * during userauth. Called after we have setuid to the user */ @@@ -162,7 -119,6 +163,7 @@@ ssh_gssapi_krb5_storecreds(ssh_gssapi_c krb5_error_code problem; krb5_principal princ; OM_uint32 maj_status, min_status; + gss_cred_id_t krb5_cred_handle; int len; const char *new_ccname; @@@ -206,16 -162,8 +207,16 @@@ krb5_free_principal(krb_context, princ); - if ((maj_status = gss_krb5_copy_ccache(&min_status, - client->creds, ccache))) { +#ifdef MECHGLUE + krb5_cred_handle = + __gss_get_mechanism_cred(client->creds, + &(gssapi_kerberos_mech.oid)); +#else + krb5_cred_handle = client->creds; +#endif + + if ((maj_status = gss_krb5_copy_ccache(&min_status, + krb5_cred_handle, ccache))) { logit("gss_krb5_copy_ccache() failed"); krb5_cc_destroy(krb_context, ccache); return; @@@ -242,6 -190,82 +243,71 @@@ return; } + int + ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, + ssh_gssapi_client *client) + { + krb5_ccache ccache = NULL; + krb5_principal principal = NULL; + char *name = NULL; + krb5_error_code problem; + OM_uint32 maj_status, min_status; + + if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { + logit("krb5_cc_resolve(): %.100s", + krb5_get_err_text(krb_context, problem)); + return 0; + } + + /* Find out who the principal in this cache is */ + if ((problem = krb5_cc_get_principal(krb_context, ccache, + &principal))) { + logit("krb5_cc_get_principal(): %.100s", + krb5_get_err_text(krb_context, problem)); + krb5_cc_close(krb_context, ccache); + return 0; + } + + if ((problem = krb5_unparse_name(krb_context, principal, &name))) { + logit("krb5_unparse_name(): %.100s", + krb5_get_err_text(krb_context, problem)); + krb5_free_principal(krb_context, principal); + krb5_cc_close(krb_context, ccache); + return 0; + } + + + if (strcmp(name,client->exportedname.value)!=0) { + debug("Name in local credentials cache differs. Not storing"); + krb5_free_principal(krb_context, principal); + krb5_cc_close(krb_context, ccache); + krb5_free_unparsed_name(krb_context, name); + return 0; + } + krb5_free_unparsed_name(krb_context, name); + + /* Name matches, so lets get on with it! */ + + if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { + logit("krb5_cc_initialize(): %.100s", + krb5_get_err_text(krb_context, problem)); + krb5_free_principal(krb_context, principal); + krb5_cc_close(krb_context, ccache); + return 0; + } + + krb5_free_principal(krb_context, principal); + + if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, + ccache))) { + logit("gss_krb5_copy_ccache() failed. Sorry!"); + krb5_cc_close(krb_context, ccache); + return 0; + } + + return 1; + } + -ssh_gssapi_mech gssapi_kerberos_mech = { - "toWM5Slw5Ew8Mqkay+al2g==", - "Kerberos", - {9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"}, - NULL, - &ssh_gssapi_krb5_userok, - NULL, - &ssh_gssapi_krb5_storecreds, - &ssh_gssapi_krb5_updatecreds -}; - #endif /* KRB5 */ #endif /* GSSAPI */ diff --combined openssh/gss-serv.c index bf88d71,365e48d..e1b2b43 --- a/openssh/gss-serv.c +++ b/openssh/gss-serv.c @@@ -1,7 -1,7 +1,7 @@@ /* $OpenBSD: gss-serv.c,v 1.22 2008/05/08 12:02:23 djm Exp $ */ /* - * Copyright (c) 2001-2006 Simon Wilkinson. All rights reserved. + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@@ -46,64 -46,32 +46,43 @@@ #include "session.h" #include "misc.h" #include "servconf.h" + #include "uidswap.h" +#include "xmalloc.h" #include "ssh-gss.h" #include "monitor_wrap.h" extern ServerOptions options; +extern Authctxt *the_authctxt; static ssh_gssapi_client gssapi_client = { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, - GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}}; + GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, NULL, {NULL, NULL, NULL}, 0, 0}; ssh_gssapi_mech gssapi_null_mech = - { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; + { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL}; #ifdef KRB5 extern ssh_gssapi_mech gssapi_kerberos_mech; #endif +#ifdef GSI +extern ssh_gssapi_mech gssapi_gsi_mech; +#endif ssh_gssapi_mech* supported_mechs[]= { #ifdef KRB5 &gssapi_kerberos_mech, +#endif +#ifdef GSI + &gssapi_gsi_mech, #endif &gssapi_null_mech, }; +#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG +static int limited = 0; +#endif - /* Unprivileged */ - char * - ssh_gssapi_server_mechanisms() { - gss_OID_set supported; - - ssh_gssapi_supported_oids(&supported); - return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech, - NULL)); - } - - /* Unprivileged */ - int - ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data) { - Gssctxt *ctx = NULL; - int res; - - res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); - ssh_gssapi_delete_ctx(&ctx); - - return (res); - } - /* * Acquire credentials for a server running on the current host. * Requires that the context structure contains a valid OID @@@ -146,7 -114,6 +125,6 @@@ ssh_gssapi_acquire_cred(Gssctxt *ctx return GSS_S_COMPLETE; } - /* Privileged */ OM_uint32 ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) @@@ -158,6 -125,29 +136,29 @@@ return (ssh_gssapi_acquire_cred(*ctx)); } + /* Unprivileged */ + char * + ssh_gssapi_server_mechanisms() { + gss_OID_set supported; + + ssh_gssapi_supported_oids(&supported); + return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech, + NULL, NULL)); + } + + /* Unprivileged */ + int + ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data, + const char *dummy) { + Gssctxt *ctx = NULL; + int res; + + res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); + ssh_gssapi_delete_ctx(&ctx); + + return (res); + } + /* Unprivileged */ void ssh_gssapi_supported_oids(gss_OID_set *oidset) @@@ -168,8 -158,9 +169,10 @@@ gss_OID_set supported; gss_create_empty_oid_set(&min_status, oidset); - /* Ask priviledged process what mechanisms it supports. */ - PRIVSEP(gss_indicate_mechs(&min_status, &supported)); + - if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) ++ /* Ask privileged process what mechanisms it supports. */ ++ if (GSS_ERROR(PRIVSEP(gss_indicate_mechs(&min_status, &supported)))) + return; while (supported_mechs[i]->name != NULL) { if (GSS_ERROR(gss_test_oid_set_member(&min_status, @@@ -221,10 -212,6 +224,10 @@@ ssh_gssapi_accept_ctx(Gssctxt *ctx, gss (*flags & GSS_C_INTEG_FLAG))) && (ctx->major == GSS_S_COMPLETE)) { if (ssh_gssapi_getclient(ctx, &gssapi_client)) fatal("Couldn't convert client name"); +#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG + if (flags && (*flags & GSS_C_GLOBUS_LIMITED_PROXY_FLAG)) + limited=1; +#endif } return (status); @@@ -244,17 -231,6 +247,17 @@@ ssh_gssapi_parse_ename(Gssctxt *ctx, gs tok = ename->value; +#ifdef GSI /* GSI gss_export_name() is broken. */ + if ((ctx->oid->length == gssapi_gsi_mech.oid.length) && + (memcmp(ctx->oid->elements, gssapi_gsi_mech.oid.elements, + gssapi_gsi_mech.oid.length) == 0)) { + name->length = ename->length; + name->value = xmalloc(ename->length+1); + memcpy(name->value, ename->value, ename->length); + return GSS_S_COMPLETE; + } +#endif + /* * Check that ename is long enough for all of the fixed length * header, and that the initial ID bytes are correct @@@ -308,8 -284,48 +311,51 @@@ OM_uint3 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) { int i = 0; + int equal = 0; + gss_name_t new_name = GSS_C_NO_NAME; + gss_buffer_desc ename = GSS_C_EMPTY_BUFFER; + + if (options.gss_store_rekey && client->used && ctx->client_creds) { + if (client->mech->oid.length != ctx->oid->length || + (memcmp(client->mech->oid.elements, + ctx->oid->elements, ctx->oid->length) !=0)) { + debug("Rekeyed credentials have different mechanism"); + return GSS_S_COMPLETE; + } + - if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, - ctx->client_creds, ctx->oid, &new_name, ++ /* Call gss_inquire_cred rather than gss_inquire_cred_by_mech ++ because GSI doesn't support the latter. -jbasney */ ++ ++ if ((ctx->major = gss_inquire_cred(&ctx->minor, ++ ctx->client_creds, &new_name, + NULL, NULL, NULL))) { + ssh_gssapi_error(ctx); + return (ctx->major); + } - gss_buffer_desc ename; + ctx->major = gss_compare_name(&ctx->minor, client->name, + new_name, &equal); + + if (GSS_ERROR(ctx->major)) { + ssh_gssapi_error(ctx); + return (ctx->major); + } + + if (!equal) { + debug("Rekeyed credentials have different name"); + return GSS_S_COMPLETE; + } + + debug("Marking rekeyed credentials for export"); + + gss_release_name(&ctx->minor, &client->name); + gss_release_cred(&ctx->minor, &client->creds); + client->name = new_name; + client->creds = ctx->client_creds; + ctx->client_creds = GSS_C_NO_CREDENTIAL; + client->updated = 1; + return GSS_S_COMPLETE; + } client->mech = NULL; @@@ -324,6 -340,13 +370,16 @@@ if (client->mech == NULL) return GSS_S_FAILURE; ++ /* Call gss_inquire_cred rather than gss_inquire_cred_by_mech ++ because GSI doesn't support the latter. -jbasney */ ++ + if (ctx->client_creds && - (ctx->major = gss_inquire_cred_by_mech(&ctx->minor, - ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) { ++ (ctx->major = gss_inquire_cred(&ctx->minor, ++ ctx->client_creds, &client->name, NULL, NULL, NULL))) { + ssh_gssapi_error(ctx); + return (ctx->major); + } + if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, &client->displayname, NULL))) { ssh_gssapi_error(ctx); @@@ -341,13 -364,11 +397,15 @@@ return (ctx->major); } + gss_release_buffer(&ctx->minor, &ename); + /* We can't copy this structure, so we just move the pointer to it */ client->creds = ctx->client_creds; ctx->client_creds = GSS_C_NO_CREDENTIAL; + + /* needed for globus_gss_assist_map_and_authorize() */ + client->context = ctx->context; + return (ctx->major); } @@@ -368,11 -389,6 +426,11 @@@ voi ssh_gssapi_storecreds(void) { if (gssapi_client.mech && gssapi_client.mech->storecreds) { + if (options.gss_creds_path) { + gssapi_client.store.filename = + expand_authorized_keys(options.gss_creds_path, + the_authctxt->pw); + } (*gssapi_client.mech->storecreds)(&gssapi_client); } else debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism"); @@@ -397,7 -413,7 +455,7 @@@ ssh_gssapi_do_child(char ***envp, u_in /* Privileged */ int - ssh_gssapi_userok(char *user) + ssh_gssapi_userok(char *user, struct passwd *pw) { OM_uint32 lmin; @@@ -406,16 -422,12 +464,18 @@@ debug("No suitable client data"); return 0; } +#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG + if (limited && options.gsi_allow_limited_proxy != 1) { + debug("limited proxy not acceptable for remote login"); + return 0; + } +#endif if (gssapi_client.mech && gssapi_client.mech->userok) - if ((*gssapi_client.mech->userok)(&gssapi_client, user)) + if ((*gssapi_client.mech->userok)(&gssapi_client, user)) { + gssapi_client.used = 1; + gssapi_client.store.owner = pw; return 1; - else { + } else { /* Destroy delegated credentials if userok fails */ gss_release_buffer(&lmin, &gssapi_client.displayname); gss_release_buffer(&lmin, &gssapi_client.exportedname); @@@ -428,25 -440,90 +488,111 @@@ return (0); } +/* ssh_gssapi_checkmic() moved to gss-genr.c so it can be called by + kexgss_client(). */ + +/* Priviledged */ +int +ssh_gssapi_localname(char **user) +{ + *user = NULL; + if (gssapi_client.displayname.length==0 || + gssapi_client.displayname.value==NULL) { + debug("No suitable client data"); + return(0);; + } + if (gssapi_client.mech && gssapi_client.mech->localname) { + return((*gssapi_client.mech->localname)(&gssapi_client,user)); + } else { + debug("Unknown client authentication type"); + } + return(0); +} + + /* These bits are only used for rekeying. The unpriviledged child is running + * as the user, the monitor is root. + * + * In the child, we want to : + * *) Ask the monitor to store our credentials into the store we specify + * *) If it succeeds, maybe do a PAM update + */ + + /* Stuff for PAM */ + + #ifdef USE_PAM + static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, + struct pam_response **resp, void *data) + { + return (PAM_CONV_ERR); + } + #endif + + void + ssh_gssapi_rekey_creds() { + int ok; + int ret; + #ifdef USE_PAM + pam_handle_t *pamh = NULL; + struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL}; + char *envstr; + #endif + + if (gssapi_client.store.filename == NULL && + gssapi_client.store.envval == NULL && + gssapi_client.store.envvar == NULL) + return; + + ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); + + if (!ok) + return; + + debug("Rekeyed credentials stored successfully"); + + /* Actually managing to play with the ssh pam stack from here will + * be next to impossible. In any case, we may want different options + * for rekeying. So, use our own :) + */ + #ifdef USE_PAM + if (!use_privsep) { + debug("Not even going to try and do PAM with privsep disabled"); + return; + } + + ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name, + &pamconv, &pamh); + if (ret) + return; + + xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, + gssapi_client.store.envval); + + ret = pam_putenv(pamh, envstr); + if (!ret) + pam_setcred(pamh, PAM_REINITIALIZE_CRED); + pam_end(pamh, PAM_SUCCESS); + #endif + } + + int + ssh_gssapi_update_creds(ssh_gssapi_ccache *store) { + int ok = 0; + + /* Check we've got credentials to store */ + if (!gssapi_client.updated) + return 0; + + gssapi_client.updated = 0; + + temporarily_use_uid(gssapi_client.store.owner); + if (gssapi_client.mech && gssapi_client.mech->updatecreds) + ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client); + else + debug("No update function for this mechanism"); + + restore_uid(); + + return ok; + } + #endif diff --combined openssh/kex.h index 39c28c8,73c45cc..6100df8 --- a/openssh/kex.h +++ b/openssh/kex.h @@@ -108,7 -108,6 +108,7 @@@ struct Newkeys Mac mac; Comp comp; }; + struct Kex { u_char *session_id; u_int session_id_len; @@@ -127,6 -126,7 +127,7 @@@ int gss_deleg_creds; int gss_trust_dns; char *gss_host; + char *gss_client; #endif char *client_version_string; char *server_version_string; diff --combined openssh/kexgsss.c index ae58cac,0c3eeaa..3e5205c --- a/openssh/kexgsss.c +++ b/openssh/kexgsss.c @@@ -1,5 -1,5 +1,5 @@@ /* - * Copyright (c) 2001-2006 Simon Wilkinson. All rights reserved. + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@@ -42,8 -42,9 +42,10 @@@ #include "dh.h" #include "ssh-gss.h" #include "monitor_wrap.h" + #include "servconf.h" +static void kex_gss_send_error(Gssctxt *ctxt); + extern ServerOptions options; void kexgss_server(Kex *kex) @@@ -69,6 -70,7 +71,7 @@@ BIGNUM *dh_client_pub = NULL; int type = 0; gss_OID oid; + char *mechs; /* Initialise GSSAPI */ @@@ -77,7 -79,8 +80,8 @@@ * into life */ if (!ssh_gssapi_oid_table_ok()) - ssh_gssapi_server_mechanisms(); + if ((mechs = ssh_gssapi_server_mechanisms())) + xfree(mechs); debug2("%s: Identifying %s", __func__, kex->name); oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); @@@ -86,10 -89,8 +90,10 @@@ debug2("%s: Acquiring credentials", __func__); - if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) + if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) { + kex_gss_send_error(ctxt); fatal("Unable to acquire credentials for the server"); + } switch (kex->kex_type) { case KEX_GSS_GRP1_SHA1: @@@ -168,20 -169,19 +172,20 @@@ if (maj_status & GSS_S_CONTINUE_NEEDED) { debug("Sending GSSAPI_CONTINUE"); packet_start(SSH2_MSG_KEXGSS_CONTINUE); -- packet_put_string(send_tok.value, send_tok.length); ++ packet_put_string((char *)send_tok.value, send_tok.length); packet_send(); gss_release_buffer(&min_status, &send_tok); } } while (maj_status & GSS_S_CONTINUE_NEEDED); if (GSS_ERROR(maj_status)) { + kex_gss_send_error(ctxt); if (send_tok.length > 0) { packet_start(SSH2_MSG_KEXGSS_CONTINUE); -- packet_put_string(send_tok.value, send_tok.length); ++ packet_put_string((char *)send_tok.value, send_tok.length); packet_send(); } - fatal("accept_ctx died"); + packet_disconnect("GSSAPI Key Exchange handshake failed"); } if (!(ret_flags & GSS_C_MUTUAL_FLAG)) @@@ -196,9 -196,16 +200,16 @@@ klen = DH_size(dh); kbuf = xmalloc(klen); kout = DH_compute_key(kbuf, dh_client_pub, dh); + if (kout < 0) + fatal("DH_compute_key: failed"); shared_secret = BN_new(); - BN_bin2bn(kbuf, kout, shared_secret); + if (shared_secret == NULL) + fatal("kexgss_server: BN_new failed"); + + if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) + fatal("kexgss_server: BN_bin2bn failed"); + memset(kbuf, 0, klen); xfree(kbuf); @@@ -233,7 -240,7 +244,7 @@@ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); } - BN_free(dh_client_pub); + BN_clear_free(dh_client_pub); if (kex->session_id == NULL) { kex->session_id_len = hashlen; @@@ -249,11 -256,11 +260,11 @@@ packet_start(SSH2_MSG_KEXGSS_COMPLETE); packet_put_bignum2(dh->pub_key); - packet_put_string(msg_tok.value,msg_tok.length); + packet_put_string((char *)msg_tok.value,msg_tok.length); if (send_tok.length != 0) { packet_put_char(1); /* true */ - packet_put_string(send_tok.value, send_tok.length); + packet_put_string((char *)send_tok.value, send_tok.length); } else { packet_put_char(0); /* false */ } @@@ -272,24 -279,10 +283,29 @@@ kex_derive_keys(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); + + /* If this was a rekey, then save out any delegated credentials we + * just exchanged. */ + if (options.gss_store_rekey) + ssh_gssapi_rekey_creds(); } + +static void +kex_gss_send_error(Gssctxt *ctxt) { + char *errstr; + OM_uint32 maj,min; + + errstr=PRIVSEP(ssh_gssapi_last_error(ctxt,&maj,&min)); + if (errstr) { + packet_start(SSH2_MSG_KEXGSS_ERROR); + packet_put_int(maj); + packet_put_int(min); + packet_put_cstring(errstr); + packet_put_cstring(""); + packet_send(); + packet_write_wait(); + /* XXX - We should probably log the error locally here */ + xfree(errstr); + } +} #endif /* GSSAPI */ diff --combined openssh/monitor.c index bc018a4,6a82936..e0434d5 --- a/openssh/monitor.c +++ b/openssh/monitor.c @@@ -171,9 -171,7 +171,10 @@@ int mm_answer_gss_accept_ctx(int, Buffe int mm_answer_gss_userok(int, Buffer *); int mm_answer_gss_checkmic(int, Buffer *); int mm_answer_gss_sign(int, Buffer *); +int mm_answer_gss_error(int, Buffer *); +int mm_answer_gss_indicate_mechs(int, Buffer *); +int mm_answer_gss_localname(int, Buffer *); + int mm_answer_gss_updatecreds(int, Buffer *); #endif #ifdef SSH_AUDIT_EVENTS @@@ -213,12 -211,12 +214,12 @@@ struct mon_table struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, - {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, + {MONITOR_REQ_PWNAM, MON_AUTH, mm_answer_pwnamallow}, {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, #ifdef USE_PAM - {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, + {MONITOR_REQ_PAM_START, MON_ISAUTH, mm_answer_pam_start}, {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, @@@ -244,9 -242,6 +245,9 @@@ {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, + {MONITOR_REQ_GSSERR, MON_ISAUTH | MON_ONCE, mm_answer_gss_error}, + {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs}, + {MONITOR_REQ_GSSLOCALNAME, MON_ISAUTH, mm_answer_gss_localname}, #endif #ifdef JPAKE {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata}, @@@ -263,8 -258,7 +264,9 @@@ struct mon_table mon_dispatch_postauth2 {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, + {MONITOR_REQ_GSSERR, 0, mm_answer_gss_error}, + {MONITOR_REQ_GSSMECHS, 0, mm_answer_gss_indicate_mechs}, + {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, #endif {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, {MONITOR_REQ_SIGN, 0, mm_answer_sign}, @@@ -295,15 -289,8 +297,15 @@@ struct mon_table mon_dispatch_proto15[ {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery}, {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond}, #endif +#ifdef GSSAPI + {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx}, + {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, + {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, + {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, + {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs}, +#endif #ifdef USE_PAM - {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start}, + {MONITOR_REQ_PAM_START, MON_ISAUTH, mm_answer_pam_start}, {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account}, {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx}, {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query}, @@@ -377,11 -364,9 +379,11 @@@ monitor_child_preauth(Authctxt *_authct /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); -#ifdef GSSAPI +#ifdef GSSAPI /* and for the GSSAPI key exchange */ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS, 1); #endif } else { mon_dispatch = mon_dispatch_proto15; @@@ -469,21 -454,14 +471,21 @@@ monitor_child_postauth(struct monitor * monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); + #ifdef GSSAPI /* and for the GSSAPI key exchange */ - monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); -#endif + monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS,1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP,1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR,1); +#endif + } else { mon_dispatch = mon_dispatch_postauth15; monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); } +#ifdef GSSAPI + monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR, 1); +#endif if (!no_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); @@@ -672,11 -650,13 +674,11 @@@ mm_answer_pwnamallow(int sock, Buffer * debug3("%s", __func__); - if (authctxt->attempt++ != 0) - fatal("%s: multiple attempts for getpwnam", __func__); - username = buffer_get_string(m, NULL); pwent = getpwnamallow(username); + if (authctxt->user) xfree(authctxt->user); authctxt->user = xstrdup(username); setproctitle("%s [priv]", pwent ? username : "unknown"); xfree(username); @@@ -1737,9 -1717,11 +1739,11 @@@ mm_get_kex(Buffer *m kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; #ifdef GSSAPI - kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; - kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; - kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; + if (options.gss_keyex) { + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; + kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; + } #endif kex->server = 1; kex->hostkey_type = buffer_get_int(m); @@@ -1940,6 -1922,9 +1944,9 @@@ mm_answer_gss_setup_ctx(int sock, Buffe OM_uint32 major; u_int len; + if (!options.gss_authentication && !options.gss_keyex) + fatal("In GSSAPI monitor when GSSAPI is disabled"); + goid.elements = buffer_get_string(m, &len); goid.length = len; @@@ -1967,6 -1952,9 +1974,9 @@@ mm_answer_gss_accept_ctx(int sock, Buff OM_uint32 flags = 0; /* GSI needs this */ u_int len; + if (!options.gss_authentication && !options.gss_keyex) + fatal("In GSSAPI monitor when GSSAPI is disabled"); + in.value = buffer_get_string(m, &len); in.length = len; major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); @@@ -1983,7 -1971,6 +1993,7 @@@ if (major == GSS_S_COMPLETE) { monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); } @@@ -1997,6 -1984,9 +2007,9 @@@ mm_answer_gss_checkmic(int sock, Buffe OM_uint32 ret; u_int len; + if (!options.gss_authentication && !options.gss_keyex) + fatal("In GSSAPI monitor when GSSAPI is disabled"); + gssbuf.value = buffer_get_string(m, &len); gssbuf.length = len; mic.value = buffer_get_string(m, &len); @@@ -2023,7 -2013,11 +2036,11 @@@ mm_answer_gss_userok(int sock, Buffer * { int authenticated; - authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); + if (!options.gss_authentication && !options.gss_keyex) + fatal("In GSSAPI monitor when GSSAPI is disabled"); + + authenticated = authctxt->valid && + ssh_gssapi_userok(authctxt->user, authctxt->pw); buffer_clear(m); buffer_put_int(m, authenticated); @@@ -2037,106 -2031,73 +2054,137 @@@ return (authenticated); } - int - mm_answer_gss_sign(int socket, Buffer *m) - { - gss_buffer_desc data; - gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; - OM_uint32 major, minor; - u_int len; - - data.value = buffer_get_string(m, &len); - data.length = len; - if (data.length != 20) - fatal("%s: data length incorrect: %d", __func__, (int)data.length); - - /* Save the session ID on the first time around */ - if (session_id2_len == 0) { - session_id2_len = data.length; - session_id2 = xmalloc(session_id2_len); - memcpy(session_id2, data.value, session_id2_len); - } - major = ssh_gssapi_sign(gsscontext, &data, &hash); - - xfree(data.value); - - buffer_clear(m); - buffer_put_int(m, major); - buffer_put_string(m, hash.value, hash.length); - - mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); - - gss_release_buffer(&minor, &hash); - - /* Turn on getpwnam permissions */ - monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); - - return (0); - } - +int +mm_answer_gss_error(int socket, Buffer *m) { + OM_uint32 major,minor; + char *msg; + + msg=ssh_gssapi_last_error(gsscontext,&major,&minor); + buffer_clear(m); + buffer_put_int(m,major); + buffer_put_int(m,minor); + buffer_put_cstring(m,msg); + + mm_request_send(socket,MONITOR_ANS_GSSERR,m); + + xfree(msg); + + return(0); +} + +int +mm_answer_gss_indicate_mechs(int socket, Buffer *m) { + OM_uint32 major,minor; + gss_OID_set mech_set; + size_t i; + + major=gss_indicate_mechs(&minor, &mech_set); + + buffer_clear(m); + buffer_put_int(m, major); + buffer_put_int(m, mech_set->count); + for (i=0; i < mech_set->count; i++) { + buffer_put_string(m, mech_set->elements[i].elements, + mech_set->elements[i].length); + } + +#if !defined(MECHGLUE) /* mechglue memory management bug ??? */ + gss_release_oid_set(&minor,&mech_set); +#endif + + mm_request_send(socket,MONITOR_ANS_GSSMECHS,m); + + return(0); +} + +int +mm_answer_gss_localname(int socket, Buffer *m) { + char *name; + + ssh_gssapi_localname(&name); + + buffer_clear(m); + if (name) { + buffer_put_cstring(m, name); + debug3("%s: sending result %s", __func__, name); + xfree(name); + } else { + buffer_put_cstring(m, ""); + debug3("%s: sending result \"\"", __func__); + } + + mm_request_send(socket, MONITOR_ANS_GSSLOCALNAME, m); + + return(0); +} ++ + int + mm_answer_gss_sign(int socket, Buffer *m) + { + gss_buffer_desc data; + gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; + OM_uint32 major, minor; + u_int len; + + if (!options.gss_authentication && !options.gss_keyex) + fatal("In GSSAPI monitor when GSSAPI is disabled"); + + data.value = buffer_get_string(m, &len); + data.length = len; + if (data.length != 20) + fatal("%s: data length incorrect: %d", __func__, + (int) data.length); + + /* Save the session ID on the first time around */ + if (session_id2_len == 0) { + session_id2_len = data.length; + session_id2 = xmalloc(session_id2_len); + memcpy(session_id2, data.value, session_id2_len); + } + major = ssh_gssapi_sign(gsscontext, &data, &hash); + + xfree(data.value); + + buffer_clear(m); + buffer_put_int(m, major); + buffer_put_string(m, hash.value, hash.length); + + mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); + + gss_release_buffer(&minor, &hash); + + /* Turn on getpwnam permissions */ + monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); + + /* And credential updating, for when rekeying */ + monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1); + + return (0); + } + + int + mm_answer_gss_updatecreds(int socket, Buffer *m) { + ssh_gssapi_ccache store; + int ok; + + store.filename = buffer_get_string(m, NULL); + store.envvar = buffer_get_string(m, NULL); + store.envval = buffer_get_string(m, NULL); + + ok = ssh_gssapi_update_creds(&store); + + xfree(store.filename); + xfree(store.envvar); + xfree(store.envval); + + buffer_clear(m); + buffer_put_int(m, ok); + + mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m); + + return(0); + } + #endif /* GSSAPI */ #ifdef JPAKE diff --combined openssh/monitor.h index 3b40f13,aa38b16..9219f4a --- a/openssh/monitor.h +++ b/openssh/monitor.h @@@ -52,11 -52,9 +52,12 @@@ enum monitor_reqtype MONITOR_REQ_GSSSETUP, MONITOR_ANS_GSSSETUP, MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP, MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK, + MONITOR_REQ_GSSMECHS, MONITOR_ANS_GSSMECHS, + MONITOR_REQ_GSSLOCALNAME, MONITOR_ANS_GSSLOCALNAME, + MONITOR_REQ_GSSERR, MONITOR_ANS_GSSERR, MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC, MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN, + MONITOR_REQ_GSSUPCREDS, MONITOR_ANS_GSSUPCREDS, MONITOR_REQ_PAM_START, MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT, MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX, @@@ -69,7 -67,7 +70,7 @@@ MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA, MONITOR_REQ_JPAKE_STEP2, MONITOR_ANS_JPAKE_STEP2, MONITOR_REQ_JPAKE_KEY_CONFIRM, MONITOR_ANS_JPAKE_KEY_CONFIRM, - MONITOR_REQ_JPAKE_CHECK_CONFIRM, MONITOR_ANS_JPAKE_CHECK_CONFIRM, + MONITOR_REQ_JPAKE_CHECK_CONFIRM, MONITOR_ANS_JPAKE_CHECK_CONFIRM }; struct mm_master; diff --combined openssh/monitor_wrap.c index 368738f,5f608b3..a2bc3a6 --- a/openssh/monitor_wrap.c +++ b/openssh/monitor_wrap.c @@@ -1239,7 -1239,7 +1239,7 @@@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gs } int - mm_ssh_gssapi_userok(char *user) + mm_ssh_gssapi_userok(char *user, struct passwd *pw) { Buffer m; int authenticated = 0; @@@ -1257,105 -1257,50 +1257,127 @@@ return (authenticated); } - OM_uint32 - mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) - { - Buffer m; - OM_uint32 major; - u_int len; - - buffer_init(&m); - buffer_put_string(&m, data->value, data->length); - - mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); - mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); - - major = buffer_get_int(&m); - hash->value = buffer_get_string(&m, &len); - hash->length = len; - - buffer_free(&m); - - return(major); - } - +char * +mm_ssh_gssapi_last_error(Gssctxt *ctx, OM_uint32 *major, OM_uint32 *minor) { + Buffer m; + OM_uint32 maj,min; + char *errstr; + + buffer_init(&m); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSERR, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSERR, &m); + + maj = buffer_get_int(&m); + min = buffer_get_int(&m); + + if (major) *major=maj; + if (minor) *minor=min; + + errstr=buffer_get_string(&m,NULL); + + buffer_free(&m); + + return(errstr); +} + +OM_uint32 +mm_gss_indicate_mechs(OM_uint32 *minor_status, gss_OID_set *mech_set) +{ + Buffer m; + OM_uint32 major,minor; + int count; + gss_OID_desc oid; + u_int length; + + buffer_init(&m); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSMECHS, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSMECHS, + &m); + major=buffer_get_int(&m); + count=buffer_get_int(&m); + + gss_create_empty_oid_set(&minor,mech_set); + while(count-->0) { + oid.elements=buffer_get_string(&m,&length); + oid.length=length; + gss_add_oid_set_member(&minor,&oid,mech_set); + } + + buffer_free(&m); + + return(major); +} + +int +mm_ssh_gssapi_localname(char **lname) +{ + Buffer m; + + buffer_init(&m); + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSLOCALNAME, &m); + + debug3("%s: waiting for MONITOR_ANS_GSSLOCALNAME", __func__); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSLOCALNAME, + &m); + + *lname = buffer_get_string(&m, NULL); + + buffer_free(&m); + if (lname[0] == '\0') { + debug3("%s: gssapi identity mapping failed", __func__); + } else { + debug3("%s: gssapi identity mapped to %s", __func__, *lname); + } + + return(0); +} + + OM_uint32 + mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) + { + Buffer m; + OM_uint32 major; + u_int len; + + buffer_init(&m); + buffer_put_string(&m, data->value, data->length); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); + + major = buffer_get_int(&m); + hash->value = buffer_get_string(&m, &len); + hash->length = len; + + buffer_free(&m); + + return(major); + } + + int + mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) + { + Buffer m; + int ok; + + buffer_init(&m); + + buffer_put_cstring(&m, store->filename ? store->filename : ""); + buffer_put_cstring(&m, store->envvar ? store->envvar : ""); + buffer_put_cstring(&m, store->envval ? store->envval : ""); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m); + + ok = buffer_get_int(&m); + + buffer_free(&m); + + return (ok); + } + #endif /* GSSAPI */ #ifdef JPAKE diff --combined openssh/monitor_wrap.h index a190a26,1e6f8b3..e4a3d48 --- a/openssh/monitor_wrap.h +++ b/openssh/monitor_wrap.h @@@ -57,13 -57,10 +57,14 @@@ BIGNUM *mm_auth_rsa_generate_challenge( OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); - int mm_ssh_gssapi_userok(char *user); + int mm_ssh_gssapi_userok(char *user, struct passwd *); OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); +int mm_ssh_gssapi_localname(char **user); +OM_uint32 mm_gss_indicate_mechs(OM_uint32 *minor_status, + gss_OID_set *mech_set); +char *mm_ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *maj, OM_uint32 *min); + int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *); #endif #ifdef USE_PAM diff --combined openssh/readconf.c index 6d05b4e,dc78c6f..0f29417 --- a/openssh/readconf.c +++ b/openssh/readconf.c @@@ -127,8 -127,7 +127,7 @@@ typedef enum oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, - oGssKeyEx, - oGssTrustDns, + oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, @@@ -171,11 -170,15 +170,15 @@@ static struct { "gssapikeyexchange", oGssKeyEx }, { "gssapidelegatecredentials", oGssDelegateCreds }, { "gssapitrustdns", oGssTrustDns }, + { "gssapiclientidentity", oGssClientIdentity }, + { "gssapirenewalforcesrekey", oGssRenewalRekey }, #else { "gssapiauthentication", oUnsupported }, { "gssapikeyexchange", oUnsupported }, { "gssapidelegatecredentials", oUnsupported }, { "gssapitrustdns", oUnsupported }, + { "gssapiclientidentity", oUnsupported }, + { "gssapirenewalforcesrekey", oUnsupported }, #endif { "fallbacktorsh", oDeprecated }, { "usersh", oDeprecated }, @@@ -235,25 -238,20 +238,19 @@@ { "tunneldevice", oTunnelDevice }, { "localcommand", oLocalCommand }, { "permitlocalcommand", oPermitLocalCommand }, - { "noneenabled", oNoneEnabled }, - { "tcprcvbufpoll", oTcpRcvBufPoll }, - { "tcprcvbuf", oTcpRcvBuf }, - { "noneswitch", oNoneSwitch }, - { "hpndisabled", oHPNDisabled }, - { "hpnbuffersize", oHPNBufferSize }, { "visualhostkey", oVisualHostKey }, - { "noneenabled", oNoneEnabled }, - { "tcprcvbufpoll", oTcpRcvBufPoll }, - { "tcprcvbuf", oTcpRcvBuf }, - { "noneswitch", oNoneSwitch }, - { "hpndisabled", oHPNDisabled }, - { "hpnbuffersize", oHPNBufferSize }, #ifdef JPAKE { "zeroknowledgepasswordauthentication", oZeroKnowledgePasswordAuthentication }, #else { "zeroknowledgepasswordauthentication", oUnsupported }, #endif + { "noneenabled", oNoneEnabled }, + { "tcprcvbufpoll", oTcpRcvBufPoll }, + { "tcprcvbuf", oTcpRcvBuf }, + { "noneswitch", oNoneSwitch }, + { "hpndisabled", oHPNDisabled }, + { "hpnbuffersize", oHPNBufferSize }, - { NULL, oBadOption } }; @@@ -473,7 -471,7 +470,7 @@@ parse_flag goto parse_flag; case oGssKeyEx: - intptr = &options->gss_keyex; + intptr = &options->gss_keyex; goto parse_flag; case oGssDelegateCreds: @@@ -484,6 -482,14 +481,14 @@@ intptr = &options->gss_trust_dns; goto parse_flag; + case oGssClientIdentity: + charptr = &options->gss_client_identity; + goto parse_string; + + case oGssRenewalRekey: + intptr = &options->gss_renewal_rekey; + goto parse_flag; + case oBatchMode: intptr = &options->batch_mode; goto parse_flag; @@@ -1073,6 -1079,8 +1078,8 @@@ initialize_options(Options * options options->gss_keyex = -1; options->gss_deleg_creds = -1; options->gss_trust_dns = -1; + options->gss_renewal_rekey = -1; + options->gss_client_identity = NULL; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; @@@ -1127,20 -1135,14 +1134,26 @@@ options->tun_remote = -1; options->local_command = NULL; options->permit_local_command = -1; + options->none_switch = -1; + options->none_enabled = -1; + options->hpn_disabled = -1; + options->hpn_buffer_size = -1; + options->tcp_rcv_buf_poll = -1; + options->tcp_rcv_buf = -1; options->visual_host_key = -1; + options->none_switch = -1; + options->none_enabled = -1; + options->hpn_disabled = -1; + options->hpn_buffer_size = -1; + options->tcp_rcv_buf_poll = -1; + options->tcp_rcv_buf = -1; options->zero_knowledge_password_authentication = -1; + options->none_switch = -1; + options->none_enabled = -1; + options->hpn_disabled = -1; + options->hpn_buffer_size = -1; + options->tcp_rcv_buf_poll = -1; + options->tcp_rcv_buf = -1; } /* @@@ -1174,13 -1176,15 +1187,15 @@@ fill_default_options(Options * options if (options->challenge_response_authentication == -1) options->challenge_response_authentication = 1; if (options->gss_authentication == -1) - options->gss_authentication = 0; + options->gss_authentication = 1; if (options->gss_keyex == -1) - options->gss_keyex = 0; + options->gss_keyex = 1; if (options->gss_deleg_creds == -1) - options->gss_deleg_creds = 0; + options->gss_deleg_creds = 1; if (options->gss_trust_dns == -1) - options->gss_trust_dns = 0; + options->gss_trust_dns = 1; + if (options->gss_renewal_rekey == -1) + options->gss_renewal_rekey = 0; if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) diff --combined openssh/readconf.h index 9396f17,a1e0a3d..12477c0 --- a/openssh/readconf.h +++ b/openssh/readconf.h @@@ -44,9 -44,11 +44,11 @@@ typedef struct int challenge_response_authentication; /* Try S/Key or TIS, authentication. */ int gss_authentication; /* Try GSS authentication */ - int gss_keyex; /* Try GSS key exchange */ + int gss_keyex; /* Try GSS key exchange */ int gss_deleg_creds; /* Delegate GSS credentials */ int gss_trust_dns; /* Trust DNS for GSS canonicalization */ + int gss_renewal_rekey; /* Credential renewal forces rekey */ + char *gss_client_identity; /* Principal to initiate GSSAPI with */ int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ @@@ -83,8 -85,6 +85,8 @@@ char *host_key_alias; /* hostname alias for .ssh/known_hosts */ char *proxy_command; /* Proxy command for connecting the host. */ char *user; /* User to log in as. */ + int implicit; /* Login user was not specified. + Server may choose based on authctxt. */ int escape_char; /* Escape character; -2 = none */ char *system_hostfile;/* Path for /etc/ssh/ssh_known_hosts. */ diff --combined openssh/servconf.c index 90c0eb7,95fe3b6..96a27f3 --- a/openssh/servconf.c +++ b/openssh/servconf.c @@@ -58,7 -58,6 +58,7 @@@ initialize_server_options(ServerOption /* Portable-specific options */ options->use_pam = -1; + options->permit_pam_user_change = -1; /* Standard Options */ options->num_ports = 0; @@@ -91,18 -90,12 +91,19 @@@ options->kerberos_authentication = -1; options->kerberos_or_local_passwd = -1; options->kerberos_ticket_cleanup = -1; +#ifdef SESSION_HOOKS + options->session_hooks_allow = -1; + options->session_hooks_startup_cmd = NULL; + options->session_hooks_shutdown_cmd = NULL; +#endif options->kerberos_get_afs_token = -1; - options->gss_authentication=-1; + options->gss_authentication = -1; + options->gss_deleg_creds = -1; options->gss_keyex = -1; options->gss_cleanup_creds = -1; options->gss_strict_acceptor = -1; + options->gsi_allow_limited_proxy = -1; + options->gss_store_rekey = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->challenge_response_authentication = -1; @@@ -137,11 -130,11 +138,11 @@@ options->num_permitted_opens = -1; options->adm_forced_command = NULL; options->chroot_directory = NULL; + options->zero_knowledge_password_authentication = -1; options->none_enabled = -1; options->tcp_rcv_buf_poll = -1; options->hpn_disabled = -1; options->hpn_buffer_size = -1; - options->zero_knowledge_password_authentication = -1; } void @@@ -155,8 -148,6 +156,8 @@@ fill_default_server_options(ServerOptio /* Portable-specific options */ if (options->use_pam == -1) options->use_pam = 0; + if (options->permit_pam_user_change == -1) + options->permit_pam_user_change = 0; /* Standard Options */ if (options->protocol == SSH_PROTO_UNKNOWN) @@@ -230,17 -221,15 +231,19 @@@ if (options->kerberos_get_afs_token == -1) options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) - options->gss_authentication = 0; + options->gss_authentication = 1; + if (options->gss_deleg_creds == -1) + options->gss_deleg_creds = 1; if (options->gss_keyex == -1) - options->gss_keyex = 0; + options->gss_keyex = 1; if (options->gss_cleanup_creds == -1) options->gss_cleanup_creds = 1; if (options->gss_strict_acceptor == -1) options->gss_strict_acceptor = 1; + if (options->gsi_allow_limited_proxy == -1) + options->gsi_allow_limited_proxy = 0; + if (options->gss_store_rekey == -1) + options->gss_store_rekey = 0; if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) @@@ -346,7 -335,7 +349,7 @@@ typedef enum { sBadOption, /* == unknown option */ /* Portable-specific options */ - sUsePAM, + sUsePAM, sPermitPAMUserChange, /* Standard Options */ sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, sPermitRootLogin, sLogFacility, sLogLevel, @@@ -354,9 -343,6 +357,9 @@@ sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, sKerberosGetAFSToken, sKerberosTgtPassing, sChallengeResponseAuthentication, +#ifdef SESSION_HOOKS + sAllowSessionHooks, sSessionHookStartupCmd, sSessionHookShutdownCmd, +#endif sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, sPrintMotd, sPrintLastLog, sIgnoreRhosts, @@@ -370,17 -356,13 +373,16 @@@ sBanner, sUseDNS, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, - sGssAuthentication, sGssCleanupCreds, + sGssDelegateCreds, - sGssStrictAcceptor, - sGssKeyEx, + sGssCredsPath, + sGsiAllowLimitedProxy, - sAcceptEnv, sPermitTunnel, + sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, + sGssKeyEx, sGssStoreRekey, + sAcceptEnv, sPermitTunnel, sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, - sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize, sZeroKnowledgePasswordAuthentication, + sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize, sDeprecated, sUnsupported } ServerOpCodes; @@@ -397,10 -379,8 +399,10 @@@ static struct /* Portable-specific options */ #ifdef USE_PAM { "usepam", sUsePAM, SSHCFG_GLOBAL }, + { "permitpamuserchange", sPermitPAMUserChange, SSHCFG_GLOBAL } #else { "usepam", sUnsupported, SSHCFG_GLOBAL }, + { "permitpamuserchange", sUnsupported, SSHCFG_GLOBAL }, #endif { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, /* Standard Options */ @@@ -440,30 -420,17 +442,32 @@@ { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, + { "gssapidelegatecredentials", sGssDelegateCreds, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, - { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, + { "gssapicredentialspath", sGssCredsPath, SSHCFG_GLOBAL }, - { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, +#ifdef GSI + { "gsiallowlimitedproxy", sGsiAllowLimitedProxy, SSHCFG_GLOBAL }, +#endif + { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, + { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, + { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, #else { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, + { "gssapidelegatecredentials", sUnsupported, SSHCFG_ALL }, { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, - { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, + { "gssapicredentialspath", sUnsupported, SSHCFG_GLOBAL }, - { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, +#ifdef GSI + { "gsiallowlimitedproxy", sUnsupported, SSHCFG_GLOBAL }, +#endif + { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, + { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, + { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, #endif +#ifdef SESSION_HOOKS + { "allowsessionhooks", sAllowSessionHooks, SSHCFG_GLOBAL }, + { "sessionhookstartupcmd", sSessionHookStartupCmd, SSHCFG_GLOBAL }, + { "sessionhookshutdowncmd", sSessionHookShutdownCmd, SSHCFG_GLOBAL }, +#endif { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, @@@ -782,10 -749,6 +786,10 @@@ process_server_config_line(ServerOption intptr = &options->use_pam; goto parse_flag; + case sPermitPAMUserChange: + intptr = &options->permit_pam_user_change; + goto parse_flag; + /* Standard Options */ case sBadOption: return -1; @@@ -1012,10 -975,6 +1016,10 @@@ intptr = &options->gss_authentication; goto parse_flag; + case sGssDelegateCreds: + intptr = &options->gss_deleg_creds; + goto parse_flag; + case sGssKeyEx: intptr = &options->gss_keyex; goto parse_flag; @@@ -1024,35 -983,14 +1028,41 @@@ intptr = &options->gss_cleanup_creds; goto parse_flag; ++ case sGssCredsPath: ++ charptr = &options->gss_creds_path; ++ goto parse_filename; ++ case sGssStrictAcceptor: intptr = &options->gss_strict_acceptor; goto parse_flag; - case sGssCredsPath: - charptr = &options->gss_creds_path; - goto parse_filename; + case sGssStoreRekey: + intptr = &options->gss_store_rekey; + goto parse_flag; ++#ifdef GSI + case sGsiAllowLimitedProxy: + intptr = &options->gsi_allow_limited_proxy; + goto parse_flag; ++#endif + +#ifdef SESSION_HOOKS + case sAllowSessionHooks: + intptr = &options->session_hooks_allow; + goto parse_flag; + case sSessionHookStartupCmd: + case sSessionHookShutdownCmd: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: empty session hook command", + filename, linenum); + if (opcode==sSessionHookStartupCmd) + options->session_hooks_startup_cmd = strdup(arg); + else + options->session_hooks_shutdown_cmd = strdup(arg); + break; +#endif + case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; @@@ -1543,7 -1481,6 +1553,7 @@@ copy_set_server_options(ServerOptions * { M_CP_INTOPT(password_authentication); M_CP_INTOPT(gss_authentication); + M_CP_INTOPT(gss_deleg_creds); M_CP_INTOPT(rsa_authentication); M_CP_INTOPT(pubkey_authentication); M_CP_INTOPT(kerberos_authentication); diff --combined openssh/servconf.h index fd8b909,1dcd25c..2c9f00e --- a/openssh/servconf.h +++ b/openssh/servconf.h @@@ -88,20 -88,13 +88,21 @@@ typedef struct * /etc/passwd */ int kerberos_ticket_cleanup; /* If true, destroy ticket * file on logout. */ +#ifdef SESSION_HOOKS + int session_hooks_allow; /* If true, permit user hooks */ + char* session_hooks_startup_cmd; /* cmd to be executed before */ + char* session_hooks_shutdown_cmd; /* cmd to be executed after */ +#endif int kerberos_get_afs_token; /* If true, try to get AFS token if * authenticated with Kerberos. */ ++ int gsi_allow_limited_proxy; /* If true, accept limited proxies */ int gss_authentication; /* If true, permit GSSAPI authentication */ + int gss_deleg_creds; /* If true, store delegated GSSAPI credentials*/ - int gss_keyex; /* If true, permit GSSAPI key exchange */ + int gss_keyex; /* If true, permit GSSAPI key exchange */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ - int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ + char* gss_creds_path; /* If true, destroy cred cache on logout */ - int gsi_allow_limited_proxy; /* If true, accept limited proxies */ + int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ + int gss_store_rekey; int password_authentication; /* If true, permit password * authentication. */ int kbd_interactive_authentication; /* If true, permit */ @@@ -155,7 -148,6 +156,7 @@@ char *adm_forced_command; int use_pam; /* Enable auth via PAM */ + int permit_pam_user_change; /* Allow PAM to change user name */ int none_enabled; /* enable NONE cipher switch */ int tcp_rcv_buf_poll; /* poll tcp rcv window in autotuning kernels*/ int hpn_disabled; /* disable hpn functionality. false by default */ diff --combined openssh/ssh-gss.h index 794e670,31d5a08..dcb9bca --- a/openssh/ssh-gss.h +++ b/openssh/ssh-gss.h @@@ -1,6 -1,6 +1,6 @@@ /* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */ /* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@@ -34,7 -34,6 +34,7 @@@ #include #endif +#ifndef MECHGLUE #ifdef KRB5 # ifndef HEIMDAL # ifdef HAVE_GSSAPI_GENERIC_H @@@ -50,7 -49,6 +50,7 @@@ #endif /* GSS_C_NT_... */ #endif /* !HEIMDAL */ #endif /* KRB5 */ +#endif /* !MECHGLUE */ /* draft-ietf-secsh-gsskeyex-06 */ #define SSH2_MSG_USERAUTH_GSSAPI_RESPONSE 60 @@@ -77,6 -75,7 +77,7 @@@ typedef struct char *filename; char *envvar; char *envval; + struct passwd *owner; void *data; } ssh_gssapi_ccache; @@@ -84,9 -83,11 +85,12 @@@ typedef struct gss_buffer_desc displayname; gss_buffer_desc exportedname; gss_cred_id_t creds; + gss_name_t name; struct ssh_gssapi_mech_struct *mech; ssh_gssapi_ccache store; + gss_ctx_id_t context; + int used; + int updated; } ssh_gssapi_client; typedef struct ssh_gssapi_mech_struct { @@@ -97,6 -98,7 +101,7 @@@ int (*userok) (ssh_gssapi_client *, char *); int (*localname) (ssh_gssapi_client *, char **); void (*storecreds) (ssh_gssapi_client *); + int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); } ssh_gssapi_mech; typedef struct { @@@ -104,10 -106,10 +109,10 @@@ OM_uint32 minor; /* both */ gss_ctx_id_t context; /* both */ gss_name_t name; /* both */ - gss_OID oid; /* client */ + gss_OID oid; /* both */ gss_cred_id_t creds; /* server */ gss_name_t client; /* server */ - gss_cred_id_t client_creds; /* server */ + gss_cred_id_t client_creds; /* both */ } Gssctxt; extern ssh_gssapi_mech *supported_mechs[]; @@@ -131,32 -133,30 +136,39 @@@ void ssh_gssapi_build_ctx(Gssctxt **) void ssh_gssapi_delete_ctx(Gssctxt **); OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); - int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); + int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); + OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); + int ssh_gssapi_credentials_updated(Gssctxt *); +int ssh_gssapi_localname(char **name); + /* In the server */ - typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *); - char *ssh_gssapi_client_mechanisms(const char *host); - char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *); + typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, + const char *); + char *ssh_gssapi_client_mechanisms(const char *, const char *); + char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, + const char *); gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); - int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *); + int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, + const char *); OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); - int ssh_gssapi_userok(char *name); + int ssh_gssapi_userok(char *name, struct passwd *); OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); void ssh_gssapi_do_child(char ***, u_int *); void ssh_gssapi_cleanup_creds(void); void ssh_gssapi_storecreds(void); - char * ssh_gssapi_server_mechanisms(void); - int ssh_gssapi_oid_table_ok(); +#ifdef MECHGLUE +gss_cred_id_t __gss_get_mechanism_cred + (gss_cred_id_t, /* union_cred */ + gss_OID /* mech_type */ + ); +#endif + + char *ssh_gssapi_server_mechanisms(void); + int ssh_gssapi_oid_table_ok(); + + int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); #endif /* GSSAPI */ #endif /* _SSH_GSS_H */ diff --combined openssh/ssh_config.5 index 073d038,024491b..a72a35b --- a/openssh/ssh_config.5 +++ b/openssh/ssh_config.5 @@@ -56,12 -56,6 +56,12 @@@ command-line option user's configuration file .Pq Pa ~/.ssh/config .It +GSSAPI configuration file +.Pq Pa $HOME/.ssh/config.gssapi +.It +Kerberos configuration file +.Pq Pa $HOME/.ssh/config.krb +.It system-wide configuration file .Pq Pa /etc/ssh/ssh_config .El @@@ -482,29 -476,39 +482,39 @@@ host key database instead o .It Cm GSSAPIAuthentication Specifies whether user authentication based on GSSAPI is allowed. The default is -.Dq no . +.Dq yes . Note that this option applies to protocol version 2 only. .It Cm GSSAPIKeyExchange Specifies whether key exchange based on GSSAPI may be used. When using GSSAPI key exchange the server need not have a host key. The default is -.Dq no . +.Dq yes . Note that this option applies to protocol version 2 only. + .It Cm GSSAPIClientIdentity + If set, specifies the GSSAPI client identity that ssh should use when + connecting to the server. The default is unset, which means that the default + identity will be used. .It Cm GSSAPIDelegateCredentials Forward (delegate) credentials to the server. The default is -.Dq no . +.Dq yes . - Note that this option applies to protocol version 2 only. + Note that this option applies to protocol version 2 connections using GSSAPI. + .It Cm GSSAPIRenewalForcesRekey + If set to + .Dq yes + then renewal of the client's GSSAPI credentials will force the rekeying of the + ssh connection. With a compatible server, this can delegate the renewed + credentials to a session on the server. + The default is -.Dq no . ++.Dq yes . .It Cm GSSAPITrustDns Set to - .Dq yes - to indicate that the DNS is trusted to securely canonicalize + .Dq yes to indicate that the DNS is trusted to securely canonicalize the name of the host being connected to. If - .Dq no , - the hostname entered on the + .Dq no, the hostname entered on the command line will be passed untouched to the GSSAPI library. The default is -.Dq no . +.Dq yes . This option only applies to protocol version 2 connections using GSSAPI. .It Cm HashKnownHosts Indicates that @@@ -738,9 -742,7 +748,9 @@@ This allows a client to prefer one meth over another method (e.g.\& .Cm password ) The default for this option is: -.Do gssapi-with-mic , +.Do gssapi-keyex , +external-keyx, +gssapi-with-mic, hostbased, publickey, keyboard-interactive, diff --combined openssh/sshconnect2.c index 4696f34,1ff0ff5..c7aadb4 --- a/openssh/sshconnect2.c +++ b/openssh/sshconnect2.c @@@ -78,17 -78,13 +78,23 @@@ extern char *client_version_string; extern char *server_version_string; extern Options options; + extern Kex *xxx_kex; + + /* tty_flag is set in ssh.c. use this in ssh_userauth2 */ + /* if it is set then prevent the switch to the null cipher */ + + extern int tty_flag; +/* tty_flag is set in ssh.c. use this in ssh_userauth2 */ +/* if it is set then prevent the switch to the null cipher */ + +extern int tty_flag; + +/* tty_flag is set in ssh.c. use this in ssh_userauth2 */ +/* if it is set then prevent the switch to the null cipher */ + +extern int tty_flag; + /* * SSH2 key exchange */ @@@ -133,7 -129,7 +139,7 @@@ ssh_kex2(char *host, struct sockaddr *h else gss_host = host; - gss = ssh_gssapi_client_mechanisms(gss_host); + gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); if (gss) { debug("Offering GSSAPI proposal: %s", gss); xasprintf(&myproposal[PROPOSAL_KEX_ALGS], @@@ -176,6 -172,7 +182,7 @@@ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], "%s,null", orig); + xfree(gss); } #endif @@@ -189,18 -186,23 +196,23 @@@ kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; #ifdef GSSAPI - kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; - kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; - kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; + if (options.gss_keyex) { + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; + kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; + } #endif kex->client_version_string=client_version_string; kex->server_version_string=server_version_string; kex->verify_host_key=&verify_host_key_callback; #ifdef GSSAPI - kex->gss_deleg_creds = options.gss_deleg_creds; - kex->gss_trust_dns = options.gss_trust_dns; - kex->gss_host = gss_host; + if (options.gss_keyex) { + kex->gss_deleg_creds = options.gss_deleg_creds; + kex->gss_trust_dns = options.gss_trust_dns; + kex->gss_client = options.gss_client_identity; + kex->gss_host = gss_host; + } #endif xxx_kex = kex; @@@ -285,10 -287,7 +297,10 @@@ int userauth_jpake(Authctxt *) void userauth_jpake_cleanup(Authctxt *); #ifdef GSSAPI +int userauth_external(Authctxt *authctxt); int userauth_gssapi(Authctxt *authctxt); +int userauth_gssapi_with_mic(Authctxt *authctxt); +int userauth_gssapi_without_mic(Authctxt *authctxt); void input_gssapi_response(int type, u_int32_t, void *); void input_gssapi_token(int type, u_int32_t, void *); void input_gssapi_hash(int type, u_int32_t, void *); @@@ -312,12 -311,6 +324,12 @@@ Authmethod authmethods[] = #ifdef GSSAPI {"gssapi-keyex", userauth_gsskeyex, + NULL, + &options.gss_authentication, + NULL}, + {"external-keyx", + userauth_external, + NULL, &options.gss_authentication, NULL}, {"gssapi-with-mic", @@@ -325,11 -318,6 +337,11 @@@ NULL, &options.gss_authentication, NULL}, + {"gssapi", + userauth_gssapi, + NULL, + &options.gss_authentication, + NULL}, #endif {"hostbased", userauth_hostbased, @@@ -638,30 -626,29 +650,34 @@@ userauth_gssapi(Authctxt *authctxt static u_int mech = 0; OM_uint32 min; int ok = 0; - const char *gss_host; + char *gss_host = NULL; + + if (!options.gss_authentication) { + verbose("GSSAPI authentication disabled."); + return 0; + } if (options.gss_trust_dns) - gss_host = get_canonical_hostname(1); + gss_host = (char *)get_canonical_hostname(1); else - gss_host = authctxt->host; + gss_host = (char *)authctxt->host; /* Try one GSSAPI method at a time, rather than sending them all at * once. */ if (gss_supported == NULL) - gss_indicate_mechs(&min, &gss_supported); + if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) { + gss_supported = NULL; + return 0; + } /* Check to see if the mechanism is usable before we offer it */ while (mech < gss_supported->count && !ok) { /* My DER encoding requires length<128 */ if (gss_supported->elements[mech].length < 128 && ssh_gssapi_check_mechanism(&gssctxt, - &gss_supported->elements[mech], gss_host)) { + &gss_supported->elements[mech], gss_host, + options.gss_client_identity)) { ok = 1; /* Mechanism works */ } else { mech++; @@@ -725,8 -712,7 +741,8 @@@ process_gssapi_token(void *ctxt, gss_bu if (status == GSS_S_COMPLETE) { /* send either complete or MIC, depending on mechanism */ - if (!(flags & GSS_C_INTEG_FLAG)) { + if (strcmp(authctxt->method->name,"gssapi")==0 || + (!(flags & GSS_C_INTEG_FLAG))) { packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE); packet_send(); } else { @@@ -871,48 -857,6 +887,48 @@@ input_gssapi_error(int type, u_int32_t xfree(lang); } +#ifdef GSI +extern +const gss_OID_desc * const gss_mech_globus_gssapi_openssl; +#define is_gsi_oid(oid) \ + (oid->length == gss_mech_globus_gssapi_openssl->length && \ + (memcmp(oid->elements, gss_mech_globus_gssapi_openssl->elements, \ + oid->length) == 0)) +#endif + +int +userauth_external(Authctxt *authctxt) +{ - static int attempt = 0; ++ static int attempt = 0; + - if (attempt++ >= 1) - return 0; ++ if (attempt++ >= 1) ++ return 0; + + /* The client MUST NOT try this method if initial key exchange + was not performed using a GSSAPI-based key exchange + method. */ + if (gss_kex_context == NULL) { + debug2("gsskex not performed, skipping external-keyx"); + return 0; + } + - debug2("userauth_external"); - packet_start(SSH2_MSG_USERAUTH_REQUEST); ++ debug2("userauth_external"); ++ packet_start(SSH2_MSG_USERAUTH_REQUEST); +#ifdef GSI - if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { - packet_put_cstring(""); ++ if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { ++ packet_put_cstring(""); + } else { +#endif - packet_put_cstring(authctxt->server_user); ++ packet_put_cstring(authctxt->server_user); +#ifdef GSI + } +#endif - packet_put_cstring(authctxt->service); - packet_put_cstring(authctxt->method->name); - packet_send(); - packet_write_wait(); - return 1; ++ packet_put_cstring(authctxt->service); ++ packet_put_cstring(authctxt->method->name); ++ packet_send(); ++ packet_write_wait(); ++ return 1; +} int userauth_gsskeyex(Authctxt *authctxt) { @@@ -930,16 -874,8 +946,16 @@@ return (0); } - ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, - "gssapi-keyex"); +#ifdef GSI - if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { - ssh_gssapi_buildmic(&b, "", authctxt->service, "gssapi-keyex"); ++ if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { ++ ssh_gssapi_buildmic(&b, "", authctxt->service, "gssapi-keyex"); + } else { +#endif - ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, - "gssapi-keyex"); ++ ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, ++ "gssapi-keyex"); +#ifdef GSI + } +#endif gssbuf.value = buffer_ptr(&b); gssbuf.length = buffer_len(&b); @@@ -950,15 -886,7 +966,15 @@@ } packet_start(SSH2_MSG_USERAUTH_REQUEST); +#ifdef GSI - if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { - packet_put_cstring(""); ++ if (options.implicit && is_gsi_oid(gss_kex_context->oid)) { ++ packet_put_cstring(""); + } else { +#endif packet_put_cstring(authctxt->server_user); +#ifdef GSI + } +#endif packet_put_cstring(authctxt->service); packet_put_cstring(authctxt->method->name); packet_put_string(mic.value, mic.length); diff --combined openssh/sshd.c index 5db24fd,1770ca3..1805bde --- a/openssh/sshd.c +++ b/openssh/sshd.c @@@ -1800,6 -1800,9 +1800,9 @@@ main(int ac, char **av cleanup_exit(255); } + /* set the HPN options for the child */ + channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); + /* * We use get_canonical_hostname with usedns = 0 instead of * get_remote_ipaddr here so IP options will be checked. @@@ -1891,9 -1894,6 +1894,6 @@@ } #endif - /* set the HPN options for the child */ - channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size); - /* * We don't want to listen forever unless the other side * successfully authenticates itself. So we set up an alarm which is @@@ -1907,13 -1907,6 +1907,13 @@@ alarm(options.login_grace_time); sshd_exchange_identification(sock_in, sock_out); +#if defined(AFS_KRB5) + /* If machine has AFS, set process authentication group. */ + if (k_hasafs()) { + k_setpag(); + k_unlog(); + } +#endif /* AFS || AFS_KRB5 */ /* In inetd mode, generate ephemeral key only for proto 1 connections */ if (!compat20 && inetd_flag && sensitive_data.server_key == NULL) @@@ -1972,7 -1965,7 +1972,7 @@@ #endif #ifdef GSSAPI - if (options.gss_authentication) { + if (options.gss_authentication && options.gss_deleg_creds) { temporarily_use_uid(authctxt->pw); ssh_gssapi_storecreds(); restore_uid(); @@@ -2326,7 -2319,6 +2326,6 @@@ do_ssh2_kex(void } #endif - /* start key exchange */ /* start key exchange */ kex = kex_setup(myproposal); kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; @@@ -2334,9 -2326,11 +2333,11 @@@ kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; #ifdef GSSAPI - kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; - kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; - kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; + if (options.gss_keyex) { + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; + kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; + kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; + } #endif kex->server = 1; kex->client_version_string=client_version_string; diff --combined openssh/sshd_config.5 index 414be24,a3357d4..0602495 --- a/openssh/sshd_config.5 +++ b/openssh/sshd_config.5 @@@ -372,17 -372,13 +372,17 @@@ The default i .It Cm GSSAPIAuthentication Specifies whether user authentication based on GSSAPI is allowed. The default is -.Dq no . +.Dq yes . Note that this option applies to protocol version 2 only. +.It Cm GSSAPIDelegateCredentials +Specifies whether delegated credentials are stored in the user's environment. +The default is +.Dq yes . .It Cm GSSAPIKeyExchange -Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange +Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange doesn't rely on ssh keys to verify host identity. The default is -.Dq no . +.Dq yes . Note that this option applies to protocol version 2 only. .It Cm GSSAPICleanupCredentials Specifies whether to automatically destroy the user's credentials cache @@@ -390,6 -386,6 +390,22 @@@ on logout The default is .Dq yes . Note that this option applies to protocol version 2 only. ++.It Cm GSSAPICredentialsPath ++If specified, the delegated GSSAPI credential is stored in the ++given path, overwriting any existing credentials. ++Paths can be specified with syntax similar to the AuthorizedKeysFile ++option (i.e., accepting %h and %u tokens). ++When using this option, ++setting 'GssapiCleanupCredentials no' is recommended, ++so logging out of one session ++doesn't remove the credentials in use by another session of ++the same user. ++Currently only implemented for the GSI mechanism. ++.It Cm GSIAllowLimitedProxy ++Specifies whether to accept limited proxy credentials for ++authentication. ++The default is ++.Dq no . .It Cm GSSAPIStrictAcceptorCheck Determines whether to be strict about the identity of the GSSAPI acceptor a client authenticates against. If @@@ -407,21 -403,10 +423,10 @@@ Note that this option applies only to p and setting it to .Dq no may only work with recent Kerberos GSSAPI libraries. - .It Cm GSSAPICredentialsPath - If specified, the delegated GSSAPI credential is stored in the - given path, overwriting any existing credentials. - Paths can be specified with syntax similar to the AuthorizedKeysFile - option (i.e., accepting %h and %u tokens). - When using this option, - setting 'GssapiCleanupCredentials no' is recommended, - so logging out of one session - doesn't remove the credentials in use by another session of - the same user. - Currently only implemented for the GSI mechanism. - .It Cm GSIAllowLimitedProxy - Specifies whether to accept limited proxy credentials for - authentication. - The default is + .It Cm GSSAPIStoreCredentialsOnRekey + Controls whether the user's GSSAPI credentials should be updated following a + successful connection rekeying. This option can be used to accepted renewed + or updated credentials from a compatible client. The default is .Dq no . .It Cm HostbasedAuthentication Specifies whether rhosts or /etc/hosts.equiv authentication together @@@ -966,12 -951,6 +971,12 @@@ is enabled, you will not be able to ru as a non-root user. The default is .Dq no . +.It Cm PermitPAMUserChange +If set to +.Dq yes +this will enable PAM authentication to change the name of the user being +authenticated. The default is +.Dq no . .It Cm UsePrivilegeSeparation Specifies whether .Xr sshd 8 diff --combined openssh/version.h index bf3a368,d57d174..1c416ad --- a/openssh/version.h +++ b/openssh/version.h @@@ -1,28 -1,7 +1,28 @@@ /* $OpenBSD: version.h,v 1.55 2009/02/23 00:06:15 djm Exp $ */ +#ifdef GSI +#define GSI_VERSION " GSI" +#else +#define GSI_VERSION "" +#endif + +#ifdef KRB5 +#define KRB5_VERSION " KRB5" +#else +#define KRB5_VERSION "" +#endif + +#ifdef MECHGLUE +#define MGLUE_VERSION " MECHGLUE" +#else +#define MGLUE_VERSION "" +#endif + +#define NCSA_VERSION " GLOBUS_GSSAPI_20090506" + #define SSH_VERSION "OpenSSH_5.2" #define SSH_PORTABLE "p1" - #define SSH_HPN "-hpn13v5" + #define SSH_HPN "-hpn13v6" -#define SSH_RELEASE SSH_VERSION SSH_PORTABLE SSH_HPN +#define SSH_RELEASE SSH_VERSION SSH_PORTABLE SSH_HPN \ + NCSA_VERSION GSI_VERSION KRB5_VERSION MGLUE_VERSION