OpenSSH problem on Solaris 8

Jacques A. Vidrine n at nectar.cc
Wed May 22 14:45:46 EDT 2002


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 <n at nectar.cc>                 http://www.nectar.cc/
NTT/Verio SME          .     FreeBSD UNIX     .       Heimdal Kerberos
jvidrine at verio.net     .  nectar at FreeBSD.org  .          nectar at kth.se
-------------- next part --------------
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;
 


More information about the Kerberos mailing list