On Wed, May 22, 2002 at 10:28:03AM -0500, Steve Langasek wrote:
> I would love it if you could send these patches to me (or to the list),
> because it would save me the trouble of writing them.  I have a two-node
> high availability cluster here that I'd like to use kerberized ssh on,
> and it bugs me to no end that starting services on one of the nodes (and
> bringing up the shared IP address) causes ssh to smell funny on the node's
> real IP.  I'm always happy to accept a patch that'll save me the time to 
> implement it myself. :)

Sure, attached.  I'm afraid there are other fixes and such also.
What you're looking for has to do with

   ssh_gssapi_get_server_name()
   options.gss_server_name

and associated stuff.

Cheers,
-- 
Jacques A. Vidrine <[EMAIL PROTECTED]>                 http://www.nectar.cc/
NTT/Verio SME          .     FreeBSD UNIX     .       Heimdal Kerberos
[EMAIL PROTECTED]     .  [EMAIL PROTECTED]  .          [EMAIL PROTECTED]
Index: buffer.c
===================================================================
RCS file: /home/cvs/ssh/buffer.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- buffer.c    20 Feb 2002 14:43:30 -0000      1.1.1.1
+++ buffer.c    20 Feb 2002 15:34:09 -0000      1.1.1.1.4.1
@@ -106,6 +106,19 @@
        return buffer->end - buffer->offset;
 }
 
+/* Gets the byte at the beginning of the buffer without consuming it. */
+
+int
+buffer_peek(Buffer *buffer)
+{
+       char *p;
+
+       if (buffer->end - buffer->offset < 1)
+               fatal("buffer_peek: buffer exhausted");
+       p = (char *)(buffer->buf + buffer->offset);
+       return (u_char) *p;
+}
+
 /* Gets data from the beginning of the buffer. */
 
 void
Index: buffer.h
===================================================================
RCS file: /home/cvs/ssh/buffer.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- buffer.h    20 Feb 2002 14:43:30 -0000      1.1.1.1
+++ buffer.h    20 Feb 2002 15:34:09 -0000      1.1.1.1.4.1
@@ -33,6 +33,7 @@
 void    buffer_append(Buffer *, const char *, u_int);
 void    buffer_append_space(Buffer *, char **, u_int);
 
+int     buffer_peek(Buffer *);
 void    buffer_get(Buffer *, char *, u_int);
 
 void    buffer_consume(Buffer *, u_int);
Index: channels.c
===================================================================
RCS file: /home/cvs/ssh/channels.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- channels.c  20 Feb 2002 14:43:30 -0000      1.1.1.1
+++ channels.c  8 Mar 2002 04:06:42 -0000       1.1.1.1.4.1
@@ -145,7 +145,7 @@
 {
        Channel *c;
 
-       if (id < 0 || id > channels_alloc) {
+       if (id < 0 || id >= channels_alloc) {
                log("channel_lookup: %d: bad id", id);
                return NULL;
        }
Index: gss-genr.c
===================================================================
RCS file: /home/cvs/ssh/gss-genr.c,v
retrieving revision 1.1.2.1
retrieving revision 1.1.4.3
diff -u -r1.1.2.1 -r1.1.4.3
--- gss-genr.c  20 Feb 2002 14:47:22 -0000      1.1.2.1
+++ gss-genr.c  20 Feb 2002 20:24:01 -0000      1.1.4.3
@@ -31,6 +31,7 @@
 #include "buffer.h"
 #include "bufaux.h"
 #include "packet.h"
+#include "canohost.h"
 #include "compat.h"
 #include <openssl/evp.h>
 #include "cipher.h"
@@ -93,7 +94,7 @@
  */
  
 char * 
-ssh_gssapi_mechanisms(int server,char *host) {
+ssh_gssapi_mechanisms(const char *gss_server_name, char *host) {
        gss_OID_set     supported;
        OM_uint32       maj_status, min_status;
        Buffer          buf;
@@ -118,8 +119,8 @@
                if (present) {
                        ssh_gssapi_build_ctx(&ctx);
                        ssh_gssapi_set_oid(&ctx,&supported_mechs[i].oid);
-                       if (server) {
-                               if (ssh_gssapi_acquire_cred(&ctx)) {
+                       if (gss_server_name != NULL) {
+                               if (ssh_gssapi_acquire_cred(&ctx, gss_server_name)) {
                                        ssh_gssapi_delete_ctx(&ctx);
                                        continue;
                                }
@@ -237,14 +238,26 @@
   return 0;
 }
 
+void
+ssh_gssapi_free_errors(struct ssh_gssapi_errors *errors)
+{
+       int i;
+
+       for (i = 0; i < errors->count; i++)
+               free(errors->msg[i]);
+}
 
 /* All this effort to report an error ... */
 void
-ssh_gssapi_error(OM_uint32 major_status,OM_uint32 minor_status) {
+ssh_gssapi_get_errors(OM_uint32 major_status, OM_uint32 minor_status,
+                       struct ssh_gssapi_errors *errors)
+{
+#define SSH_GSSAPI_ERRORS_MAX(errors) (sizeof((errors).msg) / sizeof((errors).msg[0]))
        OM_uint32 lmaj, lmin;
         gss_buffer_desc msg;
         OM_uint32 ctx;
         
+       memset(errors, 0, sizeof(*errors));
         ctx = 0;
        /* The GSSAPI error */
         do {
@@ -253,7 +266,17 @@
                                          GSS_C_NULL_OID,
                                          &ctx, &msg);
                if (lmaj == GSS_S_COMPLETE) {
-                       debug((char *)msg.value);
+                       if (errors->count == SSH_GSSAPI_ERRORS_MAX(*errors)) {
+                               debug("ssh_gssapi_errors: maximum error count reached 
+(%d)",
+                                   SSH_GSSAPI_ERRORS_MAX(*errors));
+                               return;
+                       }
+                       errors->msg[errors->count] = strdup((char *)msg.value);
+                       if (errors->msg[errors->count] == NULL) {
+                               debug("ssh_gssapi_errors: memory allocation failure");
+                               return;
+                       }
+                       errors->count++;
                        (void) gss_release_buffer(&lmin, &msg);
                }
         } while (ctx!=0);         
@@ -265,10 +288,58 @@
                                          GSS_C_NULL_OID,
                                          &ctx, &msg);
                if (lmaj == GSS_S_COMPLETE) {
-                       debug((char *)msg.value);
+                       if (errors->count == SSH_GSSAPI_ERRORS_MAX(*errors)) {
+                               debug("ssh_gssapi_errors: maximum error count reached 
+(%d)",
+                                   SSH_GSSAPI_ERRORS_MAX(*errors));
+                               return;
+                       }
+                       errors->msg[errors->count] = strdup((char *)msg.value);
+                       if (errors->msg[errors->count] == NULL) {
+                               debug("ssh_gssapi_errors: memory allocation failure");
+                               return;
+                       }
+                       errors->count++;
                        (void) gss_release_buffer(&lmin, &msg);
                }
         } while (ctx!=0);
+#undef SSH_GSSAPI_ERRORS_MAX
+}
+
+void
+ssh_gssapi_error(OM_uint32 major_status,OM_uint32 minor_status)
+{
+       struct ssh_gssapi_errors errors;
+       int i;
+
+       ssh_gssapi_get_errors(major_status, minor_status, &errors);
+       for (i = 0; i < errors.count; i++)
+               debug(errors.msg[i]);
+       ssh_gssapi_free_errors(&errors);
+}
+
+void
+ssh_gssapi_flatten_errors(struct ssh_gssapi_errors *errors, char *buf, size_t buflen)
+{
+       char *p;
+       int i, n;
+
+       if (errors->count < 1) {
+               debug("ssh_gssapi_flatten_errors: no errors");
+               return;
+       } else {
+               n = snprintf(buf, buflen, "%s", errors->msg[0]);
+               if (n >= buflen)
+                       return;
+               buflen -= n;
+               buf += n;
+       }
+       for (i = 1; i < errors->count; i++) {
+               n = snprintf(buf, buflen, "/ %s", errors->msg[i]);
+               if (n >= buflen)
+                       return;
+               buflen -= n;
+               buf += n;
+       }
 }
 
 /* Initialise our GSSAPI context. We use this opaque structure to contain all
@@ -354,13 +425,13 @@
  *    oid              
  *    credentials      (from ssh_gssapi_acquire_cred)
  */
-OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx,gss_buffer_desc *recv_tok,
+OM_uint32 ssh_gssapi_accept_ctx(OM_uint32 *min_status, Gssctxt *ctx, gss_buffer_desc 
+*recv_tok,
                                gss_buffer_desc *send_tok, OM_uint32 *flags) 
 {
-       OM_uint32 maj_status, min_status;
+       OM_uint32 maj_status;
        gss_OID mech;
        
-       maj_status=gss_accept_sec_context(&min_status,
+       maj_status=gss_accept_sec_context(min_status,
                                          &ctx->context,
                                          ctx->creds,
                                          recv_tok,
@@ -372,7 +443,7 @@
                                          NULL,
                                          &ctx->client_creds);
        if (GSS_ERROR(maj_status)) {
-               ssh_gssapi_error(maj_status,min_status);
+               ssh_gssapi_error(maj_status, *min_status);
        }
        
        if (ctx->client_creds) {
@@ -431,11 +502,38 @@
        return(maj_status);
 }
 
+static int
+ssh_gssapi_get_server_name(const char *gss_server_name, char *buf, size_t buflen)
+{
+       char *p;
+       int fd;
+
+       if (gss_server_name == NULL)
+               fatal("ssh_gssapi_import_server_name: gss_server_name == NULL");
+       if (strcmp(gss_server_name, GSS_SERVER_NAME_HOSTNAME) == 0) {
+               if (gethostname(buf, buflen) != 0) {
+                       debug("ssh_gssapi_import_server_name: gethostname failed");
+                       return(-1);
+               }
+       } else if (strcmp(gss_server_name, GSS_SERVER_NAME_SOCKET) == 0) {
+               fd = packet_get_connection_in();
+               if ((p = get_local_name(fd)) == NULL) {
+                       debug("ssh_gssapi_import_server_name: get_local_name failed");
+                       return(-1);
+               }
+               strlcpy(buf, p, buflen);
+               free(p);
+       } else
+               strlcpy(buf, gss_server_name, buflen);
+       debug("Server GSSAPI name: %s", buf);
+       return 0;
+}
+
 /* Acquire credentials for a server running on the current host.
  * Requires that the context structure contains a valid OID
  */      
 OM_uint32
-ssh_gssapi_acquire_cred(Gssctxt *ctx) {
+ssh_gssapi_acquire_cred(Gssctxt *ctx, const char *gss_server_name) {
        OM_uint32 maj_status, min_status;
        char lname[MAXHOSTNAMELEN];
        gss_OID_set oidset;
@@ -443,13 +541,10 @@
        gss_create_empty_oid_set(&min_status,&oidset);
        gss_add_oid_set_member(&min_status,ctx->oid,&oidset);
        
-        if (gethostname(lname, MAXHOSTNAMELEN)) {
-                return(-1);
-        }
-
-       if ((maj_status=ssh_gssapi_import_name(ctx,lname))) {
+       if (ssh_gssapi_get_server_name(gss_server_name, lname, sizeof(lname)) != 0)
+               return(-1);
+       if ((maj_status=ssh_gssapi_import_name(ctx, lname)))
                return(maj_status);
-       }
        if ((maj_status=gss_acquire_cred(&min_status,
                                    ctx->name,
                                    0,
Index: gss-serv.c
===================================================================
RCS file: /home/cvs/ssh/gss-serv.c,v
retrieving revision 1.1.2.1
retrieving revision 1.1.4.2
diff -u -r1.1.2.1 -r1.1.4.2
--- gss-serv.c  20 Feb 2002 14:47:23 -0000      1.1.2.1
+++ gss-serv.c  20 Feb 2002 19:46:02 -0000      1.1.4.2
@@ -137,8 +137,6 @@
        char ccname[35];
        static char name[40];
        int tmpfd;
-       OM_uint32 maj_status,min_status;
-
 
        if (gssapi_client_creds==NULL) {
                debug("No credentials stored"); 
@@ -488,7 +486,7 @@
        ssh_gssapi_build_ctx(ctxt);
        ssh_gssapi_set_oid(ctxt,&oid);
 
-       if (ssh_gssapi_acquire_cred(ctxt))
+       if (ssh_gssapi_acquire_cred(ctxt, options.gss_server_name))
                return 0;
 
        /* Send SSH_MSG_USERAUTH_GSSAPI_RESPONSE */
@@ -521,7 +519,7 @@
 
        recv_tok.value=packet_get_string(&recv_tok.length);
        
-       maj_status=ssh_gssapi_accept_ctx(gssctxt, &recv_tok, &send_tok, NULL);
+       maj_status=ssh_gssapi_accept_ctx(&min_status, gssctxt, &recv_tok, &send_tok, 
+NULL);
        packet_done();
        
        if (GSS_ERROR(maj_status)) {
diff -u -r1.1.1.1.2.1 -r1.1.1.1.4.1
Index: kex.h
===================================================================
RCS file: /home/cvs/ssh/kex.h,v
retrieving revision 1.1.1.1.2.1
retrieving revision 1.1.1.1.4.3
diff -u -r1.1.1.1.2.1 -r1.1.1.1.4.3
--- kex.h       20 Feb 2002 14:47:23 -0000      1.1.1.1.2.1
+++ kex.h       20 Feb 2002 19:46:02 -0000      1.1.1.1.4.3
@@ -96,7 +96,12 @@
 
 struct KexOptions {
        int     gss_deleg_creds;
+       int     gss_backwards_compat;
+       const char *gss_server_name;
 };
+
+#define GSS_SERVER_NAME_SOCKET  "*SOCKET*"
+#define GSS_SERVER_NAME_HOSTNAME "*HOSTNAME*"
 
 struct Kex {
        u_char  *session_id;
Index: kexgss.c
===================================================================
RCS file: /home/cvs/ssh/kexgss.c,v
retrieving revision 1.1.2.1
retrieving revision 1.1.4.5
diff -u -r1.1.2.1 -r1.1.4.5
--- kexgss.c    20 Feb 2002 14:47:23 -0000      1.1.2.1
+++ kexgss.c    20 Feb 2002 20:24:01 -0000      1.1.4.5
@@ -50,7 +50,8 @@
     u_char *serverhostkeyblob, int sbloblen,
     BIGNUM *client_dh_pub,
     BIGNUM *server_dh_pub,
-    BIGNUM *shared_secret)
+    BIGNUM *shared_secret,
+    int gss_backwards_compat)
 {
        Buffer b;
        static u_char digest[EVP_MAX_MD_SIZE];
@@ -69,7 +70,8 @@
        buffer_put_char(&b, SSH2_MSG_KEXINIT);
        buffer_append(&b, skexinit, skexinitlen);
 
-       buffer_put_string(&b, serverhostkeyblob, sbloblen);
+       if (!gss_backwards_compat)
+               buffer_put_string(&b, serverhostkeyblob, sbloblen);
        buffer_put_bignum2(&b, client_dh_pub);
        buffer_put_bignum2(&b, server_dh_pub);
        buffer_put_bignum2(&b, shared_secret);
@@ -103,6 +105,7 @@
        unsigned char *kbuf;
        unsigned char *hash;
        unsigned char *serverhostkey;
+       const char *host;
        int type = 0;
        int first = 1;
        int slen = 0;
@@ -112,9 +115,10 @@
        if (ssh_gssapi_id_kex(&ctxt,kex->name)) {
                fatal("Couldn't identify host exchange");
        }
-       if (ssh_gssapi_import_name(&ctxt,kex->host)) {
-               fatal("Couldn't import hostname ");
-       }
+       host = kex->options.gss_server_name ? kex->options.gss_server_name : kex->host;
+       debug("Server GSSAPI name: %s", host);
+       if (ssh_gssapi_import_name(&ctxt, host))
+               fatal("Couldn't import server name");
        
        /* This code should match that in ssh_dh1_client */
                
@@ -163,12 +167,19 @@
                if (send_tok.length !=0) {
                        if (first) {
                                packet_start(SSH2_MSG_KEXGSS_INIT);
+                               if (kex->options.gss_backwards_compat)
+                                       packet_put_char(first);
                                packet_put_string(send_tok.value,
                                                  send_tok.length);
                                packet_put_bignum2(dh->pub_key);
                                first=0;
                        } else {
-                               packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+                               if (!kex->options.gss_backwards_compat) {
+                                       packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+                               } else {
+                                       packet_start(SSH2_MSG_KEXGSS_INIT);
+                                       packet_put_char(first);
+                               }
                                packet_put_string(send_tok.value,
                                                  send_tok.length);
                        }
@@ -247,7 +258,8 @@
             serverhostkey, slen, /* server host key */
             dh->pub_key,       /* e */
             dh_server_pub,     /* f */
-            shared_secret      /* K */
+            shared_secret,     /* K */
+            kex->options.gss_backwards_compat
         );
         
         gssbuf.value=hash;
@@ -284,7 +296,7 @@
 kexgss_server(Kex *kex)
 {
 
-       OM_uint32 maj_status, min_status;
+       OM_uint32 maj_status, min_status, discard;
        
        /* Some GSSAPI implementations use the input value of ret_flags (an
         * output variable) as a means of triggering mechanism specific 
@@ -303,13 +315,14 @@
         BIGNUM *shared_secret = 0;
         BIGNUM *dh_client_pub = 0;
        int type =0;
+       int first = 1;
        
        /* Initialise GSSAPI */
 
        ssh_gssapi_build_ctx(&ctxt);
         if (ssh_gssapi_id_kex(&ctxt,kex->name))
                fatal("Unknown gssapi mechanism");
-        if (ssh_gssapi_acquire_cred(&ctxt))
+        if (ssh_gssapi_acquire_cred(&ctxt, kex->options.gss_server_name))
                fatal("Unable to acquire credentials for the server");
                                                                                       
                                          
        /* Initialise some bignums */
@@ -318,14 +331,23 @@
                fatal("dh_client_pub == NULL");
 
        do {
-               debug("Wait SSH2_MSG_GSSAPI_INIT");
+               debug("Wait SSH2_MSG_KEXGSS_INIT");
                type = packet_read(&plen);
                switch(type) {
                case SSH2_MSG_KEXGSS_INIT:
                        if (dlen!=0) 
                                fatal("Received KEXGSS_INIT after initialising");
+                       if (!kex->options.gss_backwards_compat && packet_peek() != 0) {
+                               debug("Enabling GssapiBackwardsCompatibility");
+                               kex->options.gss_backwards_compat = 1;
+                       }
+                       if (kex->options.gss_backwards_compat)
+                               first = packet_get_char();
                        recv_tok.value=packet_get_string(&recv_tok.length);
-                       packet_get_bignum2(dh_client_pub, &dlen);
+                       if (!kex->options.gss_backwards_compat || first) {
+                               packet_get_bignum2(dh_client_pub, &dlen);
+                               first = 0;
+                       }
                        /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
                        break;
                case SSH2_MSG_KEXGSS_CONTINUE:
@@ -337,10 +359,10 @@
                        packet_disconnect("Protocol error: didn't expect packet type 
%d",
                                           type);
                }
-               maj_status=ssh_gssapi_accept_ctx(&ctxt,&recv_tok, &send_tok,
+               maj_status=ssh_gssapi_accept_ctx(&min_status, &ctxt,&recv_tok, 
+&send_tok,
                                                 &ret_flags);
 
-               gss_release_buffer(&min_status,&recv_tok);
+               gss_release_buffer(&discard,&recv_tok);
                
                if (maj_status & GSS_S_CONTINUE_NEEDED) {
                        debug("Sending GSSAPI_CONTINUE");
@@ -352,8 +374,15 @@
                }
        } while (maj_status & GSS_S_CONTINUE_NEEDED);
 
-       if (GSS_ERROR(maj_status))
-               fatal("gss_accept_context died");
+       if (GSS_ERROR(maj_status)) {
+               char errbuf[1024]; /* XXX packet_disconnect handles 1024 bytes max */
+               struct ssh_gssapi_errors errors;
+
+               ssh_gssapi_get_errors(maj_status, min_status, &errors);
+               ssh_gssapi_flatten_errors(&errors, errbuf, sizeof(errbuf));
+               ssh_gssapi_free_errors(&errors);
+               packet_disconnect(errbuf);
+       }
        
        debug("gss_complete");
        if (!(ret_flags & GSS_C_MUTUAL_FLAG))
@@ -386,7 +415,8 @@
             NULL, 0, /* Change this if we start sending host keys */
             dh_client_pub,
             dh->pub_key,
-            shared_secret
+            shared_secret,
+            kex->options.gss_backwards_compat
        );
        BN_free(dh_client_pub);
                
Index: packet.c
===================================================================
RCS file: /home/cvs/ssh/packet.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- packet.c    20 Feb 2002 14:43:31 -0000      1.1.1.1
+++ packet.c    20 Feb 2002 15:34:10 -0000      1.1.1.1.4.1
@@ -961,6 +961,13 @@
        buffer_append(&input, buf, len);
 }
 
+/* Returns the next character from the packet without consuming it. */
+u_int
+packet_peek()
+{
+       return buffer_peek(&incoming_packet);
+}
+
 /* Returns a character from the packet. */
 
 u_int
Index: packet.h
===================================================================
RCS file: /home/cvs/ssh/packet.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- packet.h    20 Feb 2002 14:43:31 -0000      1.1.1.1
+++ packet.h    20 Feb 2002 15:34:10 -0000      1.1.1.1.4.1
@@ -45,6 +45,8 @@
 int      packet_read_poll(int *packet_len_ptr);
 void     packet_process_incoming(const char *buf, u_int len);
 
+u_int   packet_peek(void);
+
 u_int   packet_get_char(void);
 u_int   packet_get_int(void);
 void     packet_get_bignum(BIGNUM * value, int *length_ptr);
Index: readconf.c
===================================================================
RCS file: /home/cvs/ssh/readconf.c,v
retrieving revision 1.1.1.1.2.1
retrieving revision 1.1.1.1.4.3
diff -u -r1.1.1.1.2.1 -r1.1.1.1.4.3
--- readconf.c  20 Feb 2002 14:47:24 -0000      1.1.1.1.2.1
+++ readconf.c  20 Feb 2002 20:24:02 -0000      1.1.1.1.4.3
@@ -100,7 +100,7 @@
        oKerberosAuthentication,
 #endif
 #ifdef GSSAPI
-       oGssAuthentication, oGssDelegateCreds,
+       oGssAuthentication, oGssDelegateCreds, oGssBackwardsCompat, oGssServerName,
 #ifdef GSI
        oGssGlobusDelegateLimitedCreds,
 #endif /* GSI */
@@ -153,6 +153,8 @@
 #ifdef GSSAPI
        { "gssapiauthentication", oGssAuthentication },
        { "gssapidelegatecredentials", oGssDelegateCreds },
+       { "gssapibackwardscompatibility", oGssBackwardsCompat },
+       { "gssapiservername", oGssServerName },
 #ifdef GSI
        /* For backwards compatability with old 1.2.27 client code */
        { "forwardgssapiglobusproxy", oGssDelegateCreds }, /* alias */
@@ -387,6 +389,18 @@
                intptr = &options->gss_deleg_creds;
                goto parse_flag;
  
+       case oGssBackwardsCompat:
+               intptr = &options->gss_backwards_compat;
+               goto parse_flag;
+
+       case oGssServerName:
+               charptr = &options->gss_server_name;
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+               if (*activep && *charptr == NULL)
+                       *charptr = xstrdup(arg);
+               break;
 #ifdef GSI
        case oGssGlobusDelegateLimitedCreds:
                intptr = &options->gss_globus_deleg_limited_proxy;
@@ -786,6 +800,8 @@
 #ifdef GSSAPI
         options->gss_authentication = -1;
         options->gss_deleg_creds = -1;
+        options->gss_backwards_compat = -1;
+        options->gss_server_name = NULL;
 #ifdef GSI
         options->gss_globus_deleg_limited_proxy = -1;
 #endif /* GSI */
@@ -876,6 +892,8 @@
                options->gss_authentication = 1;
        if (options->gss_deleg_creds == -1)
                options->gss_deleg_creds = 1;
+       if (options->gss_backwards_compat == -1)
+               options->gss_backwards_compat = 0;
 #ifdef GSI
        if (options->gss_globus_deleg_limited_proxy == -1)
                options->gss_globus_deleg_limited_proxy = 0;
Index: readconf.h
===================================================================
RCS file: /home/cvs/ssh/readconf.h,v
retrieving revision 1.1.1.1.2.1
retrieving revision 1.1.1.1.4.3
diff -u -r1.1.1.1.2.1 -r1.1.1.1.4.3
--- readconf.h  20 Feb 2002 14:47:24 -0000      1.1.1.1.2.1
+++ readconf.h  20 Feb 2002 20:24:03 -0000      1.1.1.1.4.3
@@ -51,6 +51,8 @@
 #ifdef GSSAPI
        int     gss_authentication;
        int     gss_deleg_creds;
+       int     gss_backwards_compat;
+       const char *gss_server_name;
 #ifdef GSI
        int     gss_globus_deleg_limited_proxy;
 #endif /* GSI */
Index: servconf.c
===================================================================
RCS file: /home/cvs/ssh/servconf.c,v
retrieving revision 1.1.1.1.2.1
retrieving revision 1.1.1.1.4.4
diff -u -r1.1.1.1.2.1 -r1.1.1.1.4.4
--- servconf.c  20 Feb 2002 14:47:24 -0000      1.1.1.1.2.1
+++ servconf.c  20 Feb 2002 20:24:03 -0000      1.1.1.1.4.4
@@ -16,13 +16,7 @@
 #include <krb.h>
 #endif
 #if defined(KRB5)
-#ifdef HEIMDAL
-#include <krb.h>
-#else
-/* Bodge - but then, so is using the kerberos IV KEYFILE to get a Kerberos V
- * keytab */
-#define KEYFILE "/etc/krb5.keytab"
-#endif
+extern const char *krb5_defkeyname;
 #endif
 #ifdef AFS
 #include <kafs.h>
@@ -88,6 +82,7 @@
        options->gss_keyex=-1;
        options->gss_use_session_ccache = -1;
        options->gss_cleanup_creds = -1;
+       options->gss_server_name = NULL;
 #endif
 #if defined(KRB4) || defined(KRB5)
        options->kerberos_authentication = -1;
@@ -129,6 +124,10 @@
 void
 fill_default_server_options(ServerOptions *options)
 {
+       int krb4_keyfile, krb5_keyfile;
+
+       krb4_keyfile = krb5_keyfile = 0;
+
        /* Portable-specific options */
        if (options->pam_authentication_via_kbd_int == -1)
                options->pam_authentication_via_kbd_int = 0;
@@ -193,6 +192,12 @@
                options->rsa_authentication = 1;
        if (options->pubkey_authentication == -1)
                options->pubkey_authentication = 1;
+#ifdef KRB4
+       krb4_keyfile = (access(KEYFILE, R_OK) == 0);
+#endif
+#ifdef KRB5
+       krb5_keyfile = (access(krb5_defkeyname, R_OK) == 0);
+#endif
 #ifdef GSSAPI
        if (options->gss_authentication == -1)
                options->gss_authentication = 1;
@@ -202,10 +207,12 @@
                options->gss_use_session_ccache = 1;
        if (options->gss_cleanup_creds == -1)
                options->gss_cleanup_creds = 1;
+       if (options->gss_server_name == NULL)
+               options->gss_server_name = xstrdup(GSS_SERVER_NAME_SOCKET);
 #endif
 #if defined(KRB4) || defined(KRB5)
        if (options->kerberos_authentication == -1)
-               options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
+               options->kerberos_authentication = krb4_keyfile||krb5_keyfile;
        if (options->kerberos_or_local_passwd == -1)
                options->kerberos_or_local_passwd = 1;
        if (options->kerberos_ticket_cleanup == -1)
@@ -267,6 +274,7 @@
        sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
 #ifdef GSSAPI
        sGssAuthentication, sGssKeyEx, sGssUseSessionCredCache, sGssCleanupCreds,
+       sGssServerName,
 #endif
 #if defined(KRB4) || defined(KRB5)
        sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
@@ -323,6 +331,7 @@
        { "gssusesessionccache", sGssUseSessionCredCache },
        { "gssapiusesessioncredcache", sGssUseSessionCredCache },
        { "gssapicleanupcreds", sGssCleanupCreds },
+       { "gssapiservername", sGssServerName },
 #endif
 #if defined(KRB4) || defined(KRB5)
        { "kerberosauthentication", sKerberosAuthentication },
@@ -662,6 +671,15 @@
                case sGssCleanupCreds:
                        intptr = &options->gss_cleanup_creds;
                        goto parse_flag;
+               case sGssServerName:
+                       charptr = &options->gss_server_name;
+                       arg = strdelim(&cp);
+                       if (!arg || *arg == '\0')
+                               fatal("%s line %d: missing server name.", filename, 
+linenum);
+                       if (*charptr != NULL)
+                               free(*charptr);
+                       *charptr = xstrdup(arg);
+                       break;
 #endif
 #if defined(KRB4) || defined(KRB5)
                case sKerberosAuthentication:
Index: servconf.h
===================================================================
RCS file: /home/cvs/ssh/servconf.h,v
retrieving revision 1.1.1.1.2.1
retrieving revision 1.1.1.1.4.4
diff -u -r1.1.1.1.2.1 -r1.1.1.1.4.4
--- servconf.h  20 Feb 2002 14:47:24 -0000      1.1.1.1.2.1
+++ servconf.h  20 Feb 2002 20:24:03 -0000      1.1.1.1.4.4
@@ -72,12 +72,13 @@
        int     hostbased_uses_name_from_packet_only; /* experimental */
        int     rsa_authentication;     /* If true, permit RSA authentication. */
        int     pubkey_authentication;  /* If true, permit ssh2 pubkey authentication. 
*/
-       #ifdef GSSAPI
+#ifdef GSSAPI
        int     gss_authentication;
        int     gss_keyex;
        int     gss_use_session_ccache;        /* If true, delegated credentials are
                                                * stored in a session specific cache */
        int     gss_cleanup_creds;             /* If true, destroy cred cache on 
logout */
+       const char *gss_server_name;
 #endif 
 #if defined(KRB4) || defined(KRB5)
        int     kerberos_authentication;        /* If true, permit Kerberos
Index: ssh-gss.h
===================================================================
RCS file: /home/cvs/ssh/ssh-gss.h,v
retrieving revision 1.1.2.1
retrieving revision 1.1.4.2
diff -u -r1.1.2.1 -r1.1.4.2
--- ssh-gss.h   20 Feb 2002 14:47:25 -0000      1.1.2.1
+++ ssh-gss.h   20 Feb 2002 19:46:04 -0000      1.1.4.2
@@ -80,12 +80,17 @@
        gss_cred_id_t   client_creds; /* server */
 } Gssctxt;
 
+struct ssh_gssapi_errors {
+       int      count;
+       char    *msg[16];
+};
+
 extern ssh_gssapi_mech supported_mechs[];
 extern gss_buffer_desc gssapi_client_name;
 extern gss_cred_id_t   gssapi_client_creds;
 extern enum ssh_gss_id gssapi_client_type;
 
-char *ssh_gssapi_mechanisms(int server, char *host);
+char *ssh_gssapi_mechanisms(const char *gss_server_name, char *host);
 int ssh_gssapi_id_kex(Gssctxt *ctx, char *name);
 void ssh_gssapi_set_oid_data(Gssctxt *ctx, void *data, size_t len);
 void ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid);
@@ -93,11 +98,12 @@
 enum ssh_gss_id ssh_gssapi_get_ctype(Gssctxt *ctxt);
 
 OM_uint32 ssh_gssapi_import_name(Gssctxt *ctx, char *host);
-OM_uint32 ssh_gssapi_acquire_cred(Gssctxt *ctx);
+OM_uint32 ssh_gssapi_acquire_cred(Gssctxt *ctx, const char *gss_server_name);
 OM_uint32 ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds,
                              gss_buffer_desc *recv_tok, 
                              gss_buffer_desc *send_tok, OM_uint32 *flags);
-OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx,
+OM_uint32 ssh_gssapi_accept_ctx(OM_uint32 *min_status,
+                               Gssctxt *ctx,
                                gss_buffer_desc *recv_tok,
                                gss_buffer_desc *send_tok,
                                OM_uint32 *flags);
@@ -105,6 +111,10 @@
                                enum ssh_gss_id *type,
                                gss_buffer_desc *name,
                                gss_cred_id_t *creds);
+void ssh_gssapi_get_errors(OM_uint32 major_status,OM_uint32 minor_status,
+                               struct ssh_gssapi_errors *errors);
+void ssh_gssapi_free_errors(struct ssh_gssapi_errors *errors);
+void ssh_gssapi_flatten_errors(struct ssh_gssapi_errors *errors, char *buf, size_t 
+buflen);
 void ssh_gssapi_error(OM_uint32 major_status,OM_uint32 minor_status);
 void ssh_gssapi_build_ctx(Gssctxt *ctx);
 void ssh_gssapi_delete_ctx(Gssctxt *ctx);
Index: ssh.c
===================================================================
RCS file: /home/cvs/ssh/ssh.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- ssh.c       20 Feb 2002 14:43:33 -0000      1.1.1.1
+++ ssh.c       20 Feb 2002 20:24:04 -0000      1.1.1.1.4.1
@@ -312,7 +312,7 @@
 
 again:
        while ((opt = getopt(ac, av,
-           "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVX")) != -1) {
+           "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:G:I:L:NPR:TVX")) != -1) {
                switch (opt) {
                case '1':
                        options.protocol = SSH_PROTO_1;
@@ -522,6 +522,9 @@
                        break;
                case 'F':
                        config = optarg;
+                       break;
+               case 'G':
+                       options.gss_server_name = xstrdup(optarg);
                        break;
                default:
                        usage();
Index: sshconnect2.c
===================================================================
RCS file: /home/cvs/ssh/sshconnect2.c,v
retrieving revision 1.1.1.1.2.1
retrieving revision 1.1.1.1.4.5
diff -u -r1.1.1.1.2.1 -r1.1.1.1.4.5
--- sshconnect2.c       20 Feb 2002 14:47:25 -0000      1.1.1.1.2.1
+++ sshconnect2.c       21 Feb 2002 03:15:32 -0000      1.1.1.1.4.5
@@ -97,10 +97,12 @@
         * code to decide whether each one should be included or not.
         */     
        {
-               char *orig, *gss;
+               char *orig, *gss, *gss_host;
                int len;
                orig = myproposal[PROPOSAL_KEX_ALGS];
-               gss = ssh_gssapi_mechanisms(0,host);
+               gss_host = options.gss_server_name ? options.gss_server_name :
+                   host;
+               gss = ssh_gssapi_mechanisms(NULL, gss_host);
                if (gss) {
                   len = strlen(orig)+strlen(gss)+2;
                   myproposal[PROPOSAL_KEX_ALGS]=xmalloc(len);
@@ -151,6 +153,8 @@
 
 #ifdef GSSAPI
        kex->options.gss_deleg_creds=options.gss_deleg_creds;
+       kex->options.gss_backwards_compat=options.gss_backwards_compat;
+       kex->options.gss_server_name=options.gss_server_name;
 #endif
 
        xxx_kex = kex;
@@ -493,6 +497,7 @@
 {
        int i;
        Gssctxt *gssctxt;
+       const char *host;
        static int tries=0;
 
        /* For now, we only make one attempt at this. We could try offering
@@ -506,7 +511,9 @@
         * trapped before sending any packets.
         */
        ssh_gssapi_build_ctx(gssctxt);
-       if (ssh_gssapi_import_name(gssctxt,authctxt->host)) {
+       host = options.gss_server_name ? options.gss_server_name : authctxt->host;
+       debug("Server GSSAPI name: %s", host);
+       if (ssh_gssapi_import_name(gssctxt, host)) {
                return(0);
        }
        authctxt->methoddata=(void *)gssctxt;
Index: sshd.c
===================================================================
RCS file: /home/cvs/ssh/sshd.c,v
retrieving revision 1.1.1.1.2.1
retrieving revision 1.1.1.1.4.2
diff -u -r1.1.1.1.2.1 -r1.1.1.1.4.2
--- sshd.c      20 Feb 2002 14:47:25 -0000      1.1.1.1.2.1
+++ sshd.c      20 Feb 2002 19:46:04 -0000      1.1.1.1.4.2
@@ -1483,7 +1483,7 @@
                orig= NULL;
                
         if (options.gss_keyex)
-               gss = ssh_gssapi_mechanisms(1,NULL);
+               gss = ssh_gssapi_mechanisms(options.gss_server_name, NULL);
         else
                gss = NULL;
         
@@ -1515,6 +1515,10 @@
        kex->client_version_string=client_version_string;
        kex->server_version_string=server_version_string;
        kex->load_host_key=&get_hostkey_by_type;
+
+#ifdef GSSAPI
+       kex->options.gss_server_name=options.gss_server_name;
+#endif
 
        xxx_kex = kex;
 

Reply via email to