]> 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

index d448c7550bfd1b78aa269a90c8acc567524824a1,ac8d66dc61bfc91cfa0eec33ac571480701616cd..3d10d92c73eafdb232253f87ac07aeab5b022ccc
@@@ -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
  
index 2cf692945ecb2b2500980b144f94bc5bb7b08684,a192d282fdf80de169f1d0d6b4a05e83d97306c8..1db62c438bad6e035735e5522ccb8ae31ce9ed82
@@@ -53,20 -52,6 +53,20 @@@ static void input_gssapi_mic(int type, 
  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.
   */
@@@ -89,25 -74,13 +89,26 @@@ userauth_gsskeyex(Authctxt *authctxt
        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);
@@@ -339,12 -278,8 +340,13 @@@ input_gssapi_exchange_complete(int type
  
        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);
@@@ -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");
  
diff --cc openssh/auth2.c
index 2e466384fcdf55636a290b23b114e705abda30ad,c6c983a3784b7b53ef250411e7b1bddeaae84203..1cd3e10364ee7df583ae46718936e226999d6112
@@@ -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
Simple merge
Simple merge
Simple merge
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 */
index bea0eaebd25acc85797a42bc3e5b187edd47761c,e7170ee415a151a491a2cdbb468e34498a204a57..a439393756bb988782a808b907f40ba1292d2c3f
@@@ -57,20 -57,6 +57,21 @@@ extern ServerOptions options
  #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 */
  
@@@ -242,6 -190,82 +243,71 @@@ ssh_gssapi_krb5_storecreds(ssh_gssapi_c
        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 */
index bf88d719278638e9a374cb7c96239c8fa39e156b,365e48d88f1863ac3afb5722efd1d292dd232f15..e1b2b433150f1476909c56221ac04c681dd7afa7
@@@ -46,8 -46,8 +46,9 @@@
  #include "session.h"
  #include "misc.h"
  #include "servconf.h"
+ #include "uidswap.h"
  
 +#include "xmalloc.h"
  #include "ssh-gss.h"
  #include "monitor_wrap.h"
  
@@@ -78,32 -71,7 +79,10 @@@ ssh_gssapi_mech* supported_mechs[]= 
        &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
@@@ -168,8 -158,9 +169,10 @@@ ssh_gssapi_supported_oids(gss_OID_set *
        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,
@@@ -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);
@@@ -406,16 -422,12 +464,18 @@@ ssh_gssapi_userok(char *user, struct pa
                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 --cc openssh/kex.h
Simple merge
index ae58cacb722f92b38cd7bb6a178628b038033aa3,0c3eeaa6339b101c65fba69086a0d4aea725c9f6..3e5205c43505c0f61ccab36684461d5bcf4ac944
  #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)
                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))
        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 */
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
@@@ -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},
@@@ -2037,106 -2031,73 +2054,137 @@@ mm_answer_gss_userok(int sock, Buffer *
        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
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,
index 368738f63be05cc9cdd85ee12a97430fac01acd2,5f608b3b61f4714cb00d45ebf4f9fc22972fd28b..a2bc3a6b348740b1198125a5ab8df29532815601
@@@ -1257,105 -1257,50 +1257,127 @@@ mm_ssh_gssapi_userok(char *user, struc
        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
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
index 6d05b4ee92c85e72deeb6804d9bc8afe16a7c1ce,dc78c6f613617522d26b6660bcee6a7e7ac505a8..0f29417f3b0440764909eb27a3b7dfcee5639e21
@@@ -254,6 -245,13 +245,12 @@@ static struct 
  #else
        { "zeroknowledgepasswordauthentication", oUnsupported },
  #endif
 -
+       { "noneenabled", oNoneEnabled },
+       { "tcprcvbufpoll", oTcpRcvBufPoll },
+       { "tcprcvbuf", oTcpRcvBuf },
+       { "noneswitch", oNoneSwitch },
+       { "hpndisabled", oHPNDisabled },
+       { "hpnbuffersize", oHPNBufferSize },
        { NULL, oBadOption }
  };
  
@@@ -1127,20 -1135,14 +1134,26 @@@ initialize_options(Options * options
        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)
Simple merge
index 90c0eb7cc7edc6402e38a16a133c1ebf3b7a1bda,95fe3b62c7a43d679009a93c1fe891d93dda9dd9..96a27f3ab196b3b7605ca356cdbafa58b607a181
@@@ -102,7 -95,7 +102,8 @@@ initialize_server_options(ServerOption
        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;
@@@ -239,8 -228,8 +240,10 @@@ fill_default_server_options(ServerOptio
                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)
@@@ -370,17 -356,13 +373,16 @@@ typedef enum 
        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;
  
@@@ -440,30 -420,17 +442,32 @@@ static struct 
        { "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 },
@@@ -1024,35 -983,14 +1028,41 @@@ process_server_config_line(ServerOption
                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;
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 */
index 794e670f1c4528356cfde93221ff4278db810bde,31d5a08352e070702d46f082a2b74cb2e82babfb..dcb9bca4cfe5bd9e5c7eb76bd8460f09274ef39e
@@@ -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 {
@@@ -104,10 -106,10 +109,10 @@@ 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 */
index 073d038cc372dc8b86520db91ac270f23ec6b80d,024491b90b37d1085b7c1d0edebe14e14cbede1d..a72a35b2114b8328746577bfa439a3dee0283cc9
@@@ -488,23 -482,33 +488,33 @@@ Note that this option applies to protoc
  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
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
   */
@@@ -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 --cc openssh/sshd.c
Simple merge
index 414be2458674427f39da00a692afab994890bd8e,a3357d445def7f22ef33962d5f492c0f27dfe60a..060249535a9a604f5aa9a5a4995602b8bc08209a
@@@ -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
index bf3a36846988f68cd8e32451c13ca0a02c6ea2c5,d57d174c693025e81ee810aa6ab5269d44b16842..1c416ad9ef8971e3fd5440988027455774aabeeb
@@@ -23,6 -3,5 +23,6 @@@
  #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.176709 seconds and 5 git commands to generate.