]> andersk Git - gssapi-openssh.git/commitdiff
merging OPENSSH_5_2P1_SIMON_20090726_HPN13V6 to trunk:
authorbasney <basney>
Mon, 31 Aug 2009 18:45:53 +0000 (18:45 +0000)
committerbasney <basney>
Mon, 31 Aug 2009 18:45:53 +0000 (18:45 +0000)
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

25 files changed:
1  2 
openssh/Makefile.in
openssh/auth2-gss.c
openssh/auth2.c
openssh/channels.c
openssh/configure.ac
openssh/gss-genr.c
openssh/gss-serv-gsi.c
openssh/gss-serv-krb5.c
openssh/gss-serv.c
openssh/kex.h
openssh/kexgsss.c
openssh/monitor.c
openssh/monitor.h
openssh/monitor_wrap.c
openssh/monitor_wrap.h
openssh/readconf.c
openssh/readconf.h
openssh/servconf.c
openssh/servconf.h
openssh/ssh-gss.h
openssh/ssh_config.5
openssh/sshconnect2.c
openssh/sshd.c
openssh/sshd_config.5
openssh/version.h

diff --combined openssh/Makefile.in
index d448c7550bfd1b78aa269a90c8acc567524824a1,ac8d66dc61bfc91cfa0eec33ac571480701616cd..3d10d92c73eafdb232253f87ac07aeab5b022ccc
@@@ -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)
        -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 2cf692945ecb2b2500980b144f94bc5bb7b08684,a192d282fdf80de169f1d0d6b4a05e83d97306c8..1db62c438bad6e035735e5522ccb8ae31ce9ed82
@@@ -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
  
  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 *);
  
-               return(PRIVSEP(ssh_gssapi_userok(authctxt->user)));
 +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, 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);
        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))
        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);
                }
                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);
                }
                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;
  
        /*
  
        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");
  
        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,
  
  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 2e466384fcdf55636a290b23b114e705abda30ad,c6c983a3784b7b53ef250411e7b1bddeaae84203..1cd3e10364ee7df583ae46718936e226999d6112
@@@ -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 : "<implicit>", 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 : "<implicit>");
                log_flag = 1;
        }
        debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
        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 {
                        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 6996bde2b451412b43ab103340030470d6c5ddb5,c689e52869d42ecd4c73e4c4bf98b3a85b84e4c6..79c7696cebec97bf6590a5525cb063291e2246e6
@@@ -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 63029230ece767268e9014a618b0d6e7f0b678d3,ccc53a5cbf2bda4a17b6df1cdf3b5a9707f387b7..afc39b4814d8f307179399a38abe9a54d544feec
@@@ -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 <mach-o/dyld.h>
 -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)
            [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 <bsm/audit.h>]
-       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 <Security/AuthSession.h>],
                [SessionCreate(0, 0);],
                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 <bsm/audit.h>]
+       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 <openssl/header.h>]),
@@@ -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,
                        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
        ]
  )
  
 +# 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 92cd09ad08a45c0d7e38336b4ae8346d186e259e,c51fa727da3262f9a7f59d240a58a72a39ef6e72..a8255c3e2c72a193d66efa47a520f0815d6da3ba
@@@ -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;
        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)
                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);
  
            &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);
  }
  
  /* 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;
        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);
        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 e31d70cda30d5bfa036800219ac148cc66db96c1,0000000000000000000000000000000000000000..e77db62b1c343cdec87517727b3ca1cc23c8b87b
mode 100644,000000..100644
--- /dev/null
@@@ -1,225 -1,0 +1,226 @@@
-       &ssh_gssapi_gsi_storecreds
 +/*
 + * 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 <sys/types.h>
 +
 +#include <stdarg.h>
 +#include <string.h>
 +
 +#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 <globus_gss_assist.h>
 +
 +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,
++    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 bea0eaebd25acc85797a42bc3e5b187edd47761c,e7170ee415a151a491a2cdbb468e34498a204a57..a439393756bb988782a808b907f40ba1292d2c3f
@@@ -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 <krb5.h>
 -#else
 +#elif !defined(MECHGLUE)
  # ifdef HAVE_GSSAPI_KRB5_H
  #  include <gssapi_krb5.h>
  # elif HAVE_GSSAPI_GSSAPI_KRB5_H
  #endif
  
  static krb5_context krb_context = NULL;
-       &ssh_gssapi_krb5_storecreds
 +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_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;
  
  
        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;
        return;
  }
  
 -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
 -};
 -
+ 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;
+ }
  #endif /* KRB5 */
  
  #endif /* GSSAPI */
diff --combined openssh/gss-serv.c
index bf88d719278638e9a374cb7c96239c8fa39e156b,365e48d88f1863ac3afb5722efd1d292dd232f15..e1b2b433150f1476909c56221ac04c681dd7afa7
@@@ -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
  #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)
        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)
        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;
 -              if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, 
 -                  ctx->client_creds, ctx->oid, &new_name, 
+       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;
+               }
++        /* 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;
  
        if (client->mech == NULL)
                return GSS_S_FAILURE;
  
 -          (ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
 -           ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) {
++    /* 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(&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);
                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;
  
                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);
        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 39c28c8c38e039467eaf94d0bfe28ad25d00767d,73c45cc7ad20a56d5c2ec9135a40d86a7a744eea..6100df8d86b2fe8918044d7a72d6793c6f54536c
@@@ -108,7 -108,6 +108,7 @@@ struct Newkeys 
        Mac     mac;
        Comp    comp;
  };
 +
  struct Kex {
        u_char  *session_id;
        u_int   session_id_len;
        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 ae58cacb722f92b38cd7bb6a178628b038033aa3,0c3eeaa6339b101c65fba69086a0d4aea725c9f6..3e5205c43505c0f61ccab36684461d5bcf4ac944
@@@ -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
  #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);
  
        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:
                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))
        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);
  
                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;
  
        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 */
        }
        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 bc018a4802c5f2b36a5d1e1e65eb90258b1d2614,6a82936d41d8464c79ea713c76588fd9035d97af..e0434d5bcf506f732da2fb2212953acdd1a8464d
@@@ -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},
      {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);
        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);
        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 3b40f13210a2e3eb65219d52be0eb9359df8f9cf,aa38b163cf1eb7635704419692f2fea7b95a2643..9219f4ad6a428a68fd329eb4e8e218c01430eca9
@@@ -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 368738f63be05cc9cdd85ee12a97430fac01acd2,5f608b3b61f4714cb00d45ebf4f9fc22972fd28b..a2bc3a6b348740b1198125a5ab8df29532815601
@@@ -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;
        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 a190a26f6012deff172eb68560a385a58c312101,1e6f8b30ed027da1c2e7f0fc15fd1df60728dd32..e4a3d485810f827511453ffac5cae870fbbe2759
@@@ -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 6d05b4ee92c85e72deeb6804d9bc8afe16a7c1ce,dc78c6f613617522d26b6660bcee6a7e7ac505a8..0f29417f3b0440764909eb27a3b7dfcee5639e21
@@@ -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 },
        { "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:
                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;
        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 9396f177cf674808151144ba58a234464447cf85,a1e0a3d0ec7209319e5d43d75089d1c236a22229..12477c05681b36dbfa5323ef5c142683a3749c80
@@@ -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 90c0eb7cc7edc6402e38a16a133c1ebf3b7a1bda,95fe3b62c7a43d679009a93c1fe891d93dda9dd9..96a27f3ab196b3b7605ca356cdbafa58b607a181
@@@ -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;
        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;
        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)
        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)
  typedef enum {
        sBadOption,             /* == unknown option */
        /* Portable-specific options */
 -      sUsePAM,
 +      sUsePAM, sPermitPAMUserChange,
        /* Standard Options */
        sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
        sPermitRootLogin, sLogFacility, sLogLevel,
        sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
        sKerberosGetAFSToken,
        sKerberosTgtPassing, sChallengeResponseAuthentication,
 +#ifdef SESSION_HOOKS
 +        sAllowSessionHooks, sSessionHookStartupCmd, sSessionHookShutdownCmd,
 +#endif
        sPasswordAuthentication, sKbdInteractiveAuthentication,
        sListenAddress, sAddressFamily,
        sPrintMotd, sPrintLastLog, sIgnoreRhosts,
        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 */
        { "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;
                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;
                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 fd8b90975c7d5331b477e8a12817c183d3b181e0,1dcd25c91ca77d3ae7b59e07c03e6f278eb1b6a1..2c9f00e5a47192b47228b9ccb113b45b4eaca563
@@@ -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_keyex;              /* If true, permit GSSAPI key exchange */
 +      int     gss_deleg_creds;        /* If true, store delegated GSSAPI credentials*/
+       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 */
        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 794e670f1c4528356cfde93221ff4278db810bde,31d5a08352e070702d46f082a2b74cb2e82babfb..dcb9bca4cfe5bd9e5c7eb76bd8460f09274ef39e
@@@ -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 <gssapi/gssapi.h>
  #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 {
        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 {
        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 073d038cc372dc8b86520db91ac270f23ec6b80d,024491b90b37d1085b7c1d0edebe14e14cbede1d..a72a35b2114b8328746577bfa439a3dee0283cc9
@@@ -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 4696f344dbcf618aeb0dfb154cb4d2b99276d73e,1ff0ff596c7c1473824ae8799629043cfa28ab1b..c7aadb4a9526c5433d685ee0b1c9c07d0e720c06
  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],
                orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
                xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], 
                    "%s,null", orig);
+               xfree(gss);
        }
  #endif
  
        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",
                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);
  }
  
-         static int attempt = 0;
 +#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)
 +{
-         if (attempt++ >= 1)
-               return 0;
++    static int attempt = 0;
 +        
-         debug2("userauth_external");
-         packet_start(SSH2_MSG_USERAUTH_REQUEST);
++    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;
 +      }
 +
-         if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
-       packet_put_cstring("");
++    debug2("userauth_external");
++    packet_start(SSH2_MSG_USERAUTH_REQUEST);
 +#ifdef GSI
-       packet_put_cstring(authctxt->server_user);
++    if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
++        packet_put_cstring("");
 +      } else {
 +#endif
-         packet_put_cstring(authctxt->service);
-         packet_put_cstring(authctxt->method->name);
-         packet_send();
-         packet_write_wait();
-         return 1;
++    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;
 +}                                                                                                
  int
  userauth_gsskeyex(Authctxt *authctxt)
  {
                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);
        }
  
        packet_start(SSH2_MSG_USERAUTH_REQUEST);
-         if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
-       packet_put_cstring("");
 +#ifdef GSI
++    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 5db24fdd9336c11d0e1a38ffe6cdfb2b0f93403f,1770ca33c081da6e3a32dd04123b0ba231d61aeb..1805bdef230295bcedabcb860195b8a26602a83f
@@@ -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.
        }
  #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
                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)
  #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;
        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 414be2458674427f39da00a692afab994890bd8e,a3357d445def7f22ef33962d5f492c0f27dfe60a..060249535a9a604f5aa9a5a4995602b8bc08209a
@@@ -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 bf3a36846988f68cd8e32451c13ca0a02c6ea2c5,d57d174c693025e81ee810aa6ab5269d44b16842..1c416ad9ef8971e3fd5440988027455774aabeeb
@@@ -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
This page took 0.234278 seconds and 5 git commands to generate.