diff -Naur --exclude=autom4te.cache openssh-4.2p1/Makefile.in openssh-4.2p1-gssapi/Makefile.in
--- openssh-4.2p1/Makefile.in	2005-05-29 02:22:29.000000000 -0500
+++ openssh-4.2p1-gssapi/Makefile.in	2005-12-20 13:30:59.000000000 -0600
@@ -59,6 +59,7 @@
 
 INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
 INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
+INSTALL_GSISSH=@INSTALL_GSISSH@
 
 TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT)
 
@@ -71,7 +72,7 @@
 	atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
 	monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
 	kexgex.o kexdhc.o kexgexc.o scard.o msg.o progressmeter.o dns.o \
-	entropy.o scard-opensc.o gss-genr.o
+	entropy.o scard-opensc.o gss-genr.o kexgssc.o
 
 SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
 	sshconnect.o sshconnect1.o sshconnect2.o
@@ -84,7 +85,7 @@
 	auth2-none.o auth2-passwd.o auth2-pubkey.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 \
+	auth2-gss.o gss-serv.o gss-serv-krb5.o gss-serv-gsi.o kexgsss.o \
 	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
 	audit.o audit-bsm.o
 
@@ -282,6 +283,20 @@
 	ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
 	ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+	if [ ! -z "$(INSTALL_GSISSH)" ]; then \
+		rm -f $(DESTDIR)$(bindir)/gsissh; \
+		ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/gsissh; \
+		rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsissh.1; \
+		ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/gsissh.1; \
+		rm -f $(DESTDIR)$(bindir)/gsiscp; \
+		ln -s ./scp$(EXEEXT) $(DESTDIR)$(bindir)/gsiscp; \
+		rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsiscp.1; \
+		ln -s ./scp.1 $(DESTDIR)$(mandir)/$(mansubdir)1/gsiscp.1; \
+		rm -f $(DESTDIR)$(bindir)/gsisftp; \
+		ln -s ./sftp$(EXEEXT) $(DESTDIR)$(bindir)/gsisftp; \
+		rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsisftp.1; \
+		ln -s ./sftp.1 $(DESTDIR)$(mandir)/$(mansubdir)1/gsisftp.1; \
+	fi
 
 install-sysconf:
 	if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \
@@ -353,6 +368,11 @@
 
 uninstall:
 	-rm -f $(DESTDIR)$(bindir)/slogin
+	if [ ! -z "$(INSTALL_GSISSH)" ]; then \
+		rm -f $(DESTDIR)$(bindir)/gsiscp; \
+		rm -f $(DESTDIR)$(bindir)/gsissh; \
+		rm -f $(DESTDIR)$(bindir)/gsisftp; \
+	fi
 	-rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT)
 	-rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT)
 	-rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
@@ -366,6 +386,11 @@
 	-rm -f $(DESTDIR)$(RAND_HELPER)$(EXEEXT)
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
+	if [ ! -z "$(INSTALL_GSISSH)" ]; then \
+		rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsissh.1; \
+		rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsiscp.1; \
+		rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsisftp.1; \
+	fi
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
diff -Naur --exclude=autom4te.cache openssh-4.2p1/acconfig.h openssh-4.2p1-gssapi/acconfig.h
--- openssh-4.2p1/acconfig.h	2005-07-07 05:33:36.000000000 -0500
+++ openssh-4.2p1-gssapi/acconfig.h	2005-12-20 13:30:59.000000000 -0600
@@ -250,6 +250,9 @@
 /* Define if compiler implements __func__ */
 #undef HAVE___func__
 
+/* Define this if you're building with GSSAPI MechGlue */
+#undef MECHGLUE
+
 /* Define this is you want GSSAPI support in the version 2 protocol */
 #undef GSSAPI
 
@@ -259,6 +262,16 @@
 /* Define this if you are using the Heimdal version of Kerberos V5 */
 #undef HEIMDAL
 
+/* Define this if you want to use AFS/Kerberos 5 option, which runs aklog. */
+#undef AFS_KRB5
+#undef AKLOG_PATH
+
+/* Define if you want GSI/Globus authentication support */
+#undef GSI
+
+/* Define this if you want support for startup/shutdown hooks */
+#undef SESSION_HOOKS
+
 /* Define this if you want to use libkafs' AFS support */
 #undef USE_AFS
 
@@ -347,6 +360,12 @@
 /* getaddrinfo is broken (if present) */
 #undef BROKEN_GETADDRINFO
 
+/* platform uses an in-memory credentials cache */
+#undef USE_CCAPI
+
+/* platform has a Security Authorization Session API */
+#undef USE_SECURITY_SESSION_API
+
 /* updwtmpx is broken (if present) */
 #undef BROKEN_UPDWTMPX
 
diff -Naur --exclude=autom4te.cache openssh-4.2p1/auth-krb5.c openssh-4.2p1-gssapi/auth-krb5.c
--- openssh-4.2p1/auth-krb5.c	2005-07-07 05:33:36.000000000 -0500
+++ openssh-4.2p1-gssapi/auth-krb5.c	2005-12-20 13:30:59.000000000 -0600
@@ -159,8 +159,13 @@
 
 	len = strlen(authctxt->krb5_ticket_file) + 6;
 	authctxt->krb5_ccname = xmalloc(len);
+#ifdef USE_CCAPI
+	snprintf(authctxt->krb5_ccname, len, "API:%s",
+	    authctxt->krb5_ticket_file);
+#else
 	snprintf(authctxt->krb5_ccname, len, "FILE:%s",
 	    authctxt->krb5_ticket_file);
+#endif
 
 #ifdef USE_PAM
 	if (options.use_pam)
@@ -212,15 +217,22 @@
 #ifndef HEIMDAL
 krb5_error_code
 ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
-	int tmpfd, ret;
+	int ret;
 	char ccname[40];
 	mode_t old_umask;
+#ifdef USE_CCAPI
+	char cctemplate[] = "API:krb5cc_%d";
+#else
+	char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX";
+	int tmpfd;
+#endif
 
 	ret = snprintf(ccname, sizeof(ccname),
-	    "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
-	if (ret == -1 || ret >= sizeof(ccname))
+	    cctemplate, geteuid());
+	if (ret == -1 || ret >= (int) sizeof(ccname))
 		return ENOMEM;
 
+#ifndef USE_CCAPI
 	old_umask = umask(0177);
 	tmpfd = mkstemp(ccname + strlen("FILE:"));
 	umask(old_umask);
@@ -235,6 +247,7 @@
 		return errno;
 	}
 	close(tmpfd);
+#endif
 
 	return (krb5_cc_resolve(ctx, ccname, ccache));
 }
diff -Naur --exclude=autom4te.cache openssh-4.2p1/auth.c openssh-4.2p1-gssapi/auth.c
--- openssh-4.2p1/auth.c	2005-08-31 11:59:49.000000000 -0500
+++ openssh-4.2p1-gssapi/auth.c	2005-12-20 13:30:59.000000000 -0600
@@ -247,7 +247,8 @@
 	    authmsg,
 	    method,
 	    authctxt->valid ? "" : "invalid user ",
-	    authctxt->user,
+	    (authctxt->user && authctxt->user[0]) ?
+		authctxt->user : "<implicit>",
 	    get_remote_ipaddr(),
 	    get_remote_port(),
 	    info);
@@ -495,7 +496,8 @@
 	pw = getpwnam(user);
 	if (pw == NULL) {
 		logit("Invalid user %.100s from %.100s",
-		    user, get_remote_ipaddr());
+		      (user && user[0]) ? user : "<implicit>",
+		      get_remote_ipaddr());
 #ifdef CUSTOM_FAILED_LOGIN
 		record_failed_login(user,
 		    get_canonical_hostname(options.use_dns), "ssh");
diff -Naur --exclude=autom4te.cache openssh-4.2p1/auth.h openssh-4.2p1-gssapi/auth.h
--- openssh-4.2p1/auth.h	2005-07-06 20:50:20.000000000 -0500
+++ openssh-4.2p1-gssapi/auth.h	2005-12-20 13:30:59.000000000 -0600
@@ -42,6 +42,9 @@
 #ifdef KRB5
 #include <krb5.h>
 #endif
+#ifdef AFS_KRB5
+#include <krbafs.h>
+#endif
 
 typedef struct Authctxt Authctxt;
 typedef struct Authmethod Authmethod;
@@ -53,6 +56,7 @@
 	int		 valid;		/* user exists and is allowed to login */
 	int		 attempt;
 	int		 failures;
+	int		 server_caused_failure; 
 	int		 force_pwchange;
 	char		*user;		/* username sent by the client */
 	char		*service;
@@ -69,6 +73,9 @@
 	char		*krb5_ticket_file;
 	char		*krb5_ccname;
 #endif
+#ifdef SESSION_HOOKS
+        char            *session_env_file;
+#endif
 	Buffer		*loginmsg;
 	void		*methoddata;
 };
diff -Naur --exclude=autom4te.cache openssh-4.2p1/auth2-gss.c openssh-4.2p1-gssapi/auth2-gss.c
--- openssh-4.2p1/auth2-gss.c	2005-07-17 02:22:45.000000000 -0500
+++ openssh-4.2p1-gssapi/auth2-gss.c	2005-12-20 13:30:59.000000000 -0600
@@ -42,11 +42,72 @@
 
 extern ServerOptions options;
 
+static void ssh_gssapi_userauth_error(Gssctxt *ctxt);
 static void input_gssapi_token(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_errtok(int, u_int32_t, void *);
 
+static int gssapi_with_mic = 1;	/* flag to toggle "gssapi-with-mic" vs.
+				   "gssapi" */
+
+static int
+userauth_external(Authctxt *authctxt)
+{
+        packet_check_eom();
+
+	if (authctxt->valid && authctxt->user && authctxt->user[0]) {
+		return(PRIVSEP(ssh_gssapi_userok(authctxt->user)));
+	}
+	return 0;
+}
+
+/* 
+ * The 'gssapi_keyex' userauth mechanism.
+ */
+static int
+userauth_gsskeyex(Authctxt *authctxt)
+{
+	int authenticated = 0;
+	Buffer b, b2;
+	gss_buffer_desc mic, gssbuf, gssbuf2;
+	u_int len;
+
+	mic.value = packet_get_string(&len);
+	mic.length = len;
+
+	packet_check_eom();
+
+	ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
+	    "gssapi-keyex");
+
+	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))) ||
+	    !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));
+	    }
+	}
+	
+	buffer_free(&b);
+	buffer_free(&b2);
+	xfree(mic.value);
+
+	return (authenticated);
+}
+
 /*
  * We only support those mechanisms that we know about (ie ones that we know
  * how to check local user kuserok and the like
@@ -63,7 +124,10 @@
 	u_int len;
 	u_char *doid = NULL;
 
-	if (!authctxt->valid || authctxt->user == NULL)
+	/* authctxt->valid may be 0 if we haven't yet determined
+	   username from gssapi context. */
+
+	if (authctxt->user == NULL)
 		return (0);
 
 	mechs = packet_get_int();
@@ -97,11 +161,13 @@
 
 	if (!present) {
 		xfree(doid);
+		authctxt->server_caused_failure = 1;
 		return (0);
 	}
 
 	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, &goid)))) {
 		xfree(doid);
+		authctxt->server_caused_failure = 1;
 		return (0);
 	}
 
@@ -129,7 +195,7 @@
 	Gssctxt *gssctxt;
 	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
 	gss_buffer_desc recv_tok;
-	OM_uint32 maj_status, min_status, flags;
+	OM_uint32 maj_status, min_status, flags=0;
 	u_int len;
 
 	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
@@ -147,6 +213,7 @@
 	xfree(recv_tok.value);
 
 	if (GSS_ERROR(maj_status)) {
+        	ssh_gssapi_userauth_error(gssctxt);
 		if (send_tok.length != 0) {
 			packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
 			packet_put_string(send_tok.value, send_tok.length);
@@ -154,7 +221,9 @@
 		}
 		authctxt->postponed = 0;
 		dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
-		userauth_finish(authctxt, 0, "gssapi-with-mic");
+		userauth_finish(authctxt, 0,
+				gssapi_with_mic ? "gssapi-with-mic" :
+				                  "gssapi");
 	} else {
 		if (send_tok.length != 0) {
 			packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
@@ -163,7 +232,7 @@
 		}
 		if (maj_status == GSS_S_COMPLETE) {
 			dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
-			if (flags & GSS_C_INTEG_FLAG)
+			if (flags & GSS_C_INTEG_FLAG && gssapi_with_mic)
 				dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC,
 				    &input_gssapi_mic);
 			else
@@ -210,6 +279,32 @@
 	gss_release_buffer(&maj_status, &send_tok);
 }
 
+static void
+gssapi_set_implicit_username(Authctxt *authctxt)
+{
+    if ((authctxt->user == NULL) || (authctxt->user[0] == '\0')) {
+	char *lname = NULL;
+	PRIVSEP(ssh_gssapi_localname(&lname));
+	if (lname && lname[0] != '\0') {
+	    if (authctxt->user) xfree(authctxt->user);
+	    authctxt->user = lname;
+	    debug("set username to %s from gssapi context", lname);
+	    authctxt->pw = PRIVSEP(getpwnamallow(authctxt->user));
+	    if (authctxt->pw) {
+		authctxt->valid = 1;
+	    }
+	} else {
+	    debug("failed to set username from gssapi context");
+	}
+    }
+    if (authctxt->pw) {
+#ifdef USE_PAM
+	if (options.use_pam)
+		PRIVSEP(start_pam(authctxt));
+#endif
+    }
+}
+
 /*
  * This is called when the client thinks we've completed authentication.
  * It should only be enabled in the dispatch handler by the function above,
@@ -226,6 +321,8 @@
 	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
 		fatal("No authentication or GSSAPI context");
 
+	gssapi_set_implicit_username(authctxt);
+
 	gssctxt = authctxt->methoddata;
 
 	/*
@@ -235,14 +332,34 @@
 
 	packet_check_eom();
 
-	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+	/* 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));
+	} else {
+	    authenticated = 0;
+	}
 
 	authctxt->postponed = 0;
 	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
 	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
 	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
 	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
-	userauth_finish(authctxt, authenticated, "gssapi-with-mic");
+	userauth_finish(authctxt, authenticated,
+			gssapi_with_mic ? "gssapi-with-mic" : "gssapi");
+}
+
+static int
+userauth_gssapi_with_mic(Authctxt *authctxt)
+{
+    gssapi_with_mic = 1;
+    return userauth_gssapi(authctxt);
+}
+
+static int
+userauth_gssapi_without_mic(Authctxt *authctxt)
+{
+    gssapi_with_mic = 0;
+    return userauth_gssapi(authctxt);
 }
 
 static void
@@ -258,6 +375,8 @@
 	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
 		fatal("No authentication or GSSAPI context");
 
+	gssapi_set_implicit_username(authctxt);
+
 	gssctxt = authctxt->methoddata;
 
 	mic.value = packet_get_string(&len);
@@ -270,7 +389,11 @@
 	gssbuf.length = buffer_len(&b);
 
 	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
+	    if (authctxt->valid && authctxt->user && authctxt->user[0]) {
 		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+	    } else {
+		authenticated = 0;
+	    }
 	else
 		logit("GSSAPI MIC check failed");
 
@@ -285,9 +408,44 @@
 	userauth_finish(authctxt, authenticated, "gssapi-with-mic");
 }
 
+static void ssh_gssapi_userauth_error(Gssctxt *ctxt) {
+	char *errstr;
+	OM_uint32 maj,min;
+	
+	errstr=PRIVSEP(ssh_gssapi_last_error(ctxt,&maj,&min));
+	if (errstr) {
+		packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERROR);
+		packet_put_int(maj);
+		packet_put_int(min);
+		packet_put_cstring(errstr);
+		packet_put_cstring("");
+		packet_send();
+		packet_write_wait();
+		xfree(errstr);
+	}
+}
+
+Authmethod method_external = {
+	"external-keyx",
+	userauth_external,
+	&options.gss_authentication
+};
+	
+Authmethod method_gsskeyex = {
+	"gssapi-keyex",
+	userauth_gsskeyex,
+	&options.gss_authentication
+};
+
 Authmethod method_gssapi = {
 	"gssapi-with-mic",
-	userauth_gssapi,
+	userauth_gssapi_with_mic,
+	&options.gss_authentication
+};
+
+Authmethod method_gssapi_compat = {
+	"gssapi",
+	userauth_gssapi_without_mic,
 	&options.gss_authentication
 };
 
diff -Naur --exclude=autom4te.cache openssh-4.2p1/auth2.c openssh-4.2p1-gssapi/auth2.c
--- openssh-4.2p1/auth2.c	2005-07-17 02:26:44.000000000 -0500
+++ openssh-4.2p1-gssapi/auth2.c	2005-12-20 13:30:59.000000000 -0600
@@ -55,14 +55,20 @@
 extern Authmethod method_kbdint;
 extern Authmethod method_hostbased;
 #ifdef GSSAPI
+extern Authmethod method_external;
+extern Authmethod method_gsskeyex;
 extern Authmethod method_gssapi;
+extern Authmethod method_gssapi_compat;
 #endif
 
 Authmethod *authmethods[] = {
 	&method_none,
 	&method_pubkey,
 #ifdef GSSAPI
+	&method_gsskeyex,
+	&method_external,
 	&method_gssapi,
+	&method_gssapi_compat,
 #endif
 	&method_passwd,
 	&method_kbdint,
@@ -143,14 +149,53 @@
 	user = packet_get_string(NULL);
 	service = packet_get_string(NULL);
 	method = packet_get_string(NULL);
-	debug("userauth-request for user %s service %s method %s", user, service, method);
+
+#ifdef GSSAPI
+	if (user[0] == '\0') {
+	    debug("received empty username for %s", method);
+	    if (strcmp(method, "external-keyx") == 0 ||
+		strcmp(method, "gssapi-keyex") == 0) {
+		char *lname = NULL;
+		PRIVSEP(ssh_gssapi_localname(&lname));
+		if (lname && lname[0] != '\0') {
+		    xfree(user);
+		    user = lname;
+		    debug("set username to %s from gssapi context", user);
+		} else {
+		    debug("failed to set username from gssapi context");
+		}
+	    }
+	}
+#endif
+
+	debug("userauth-request for user %s service %s method %s",
+	      user[0] ? user : "<implicit>", service, method);
 	debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
 
 	if ((style = strchr(user, ':')) != NULL)
 		*style++ = 0;
 
-	if (authctxt->attempt++ == 0) {
-		/* setup auth context */
+	/* If first time or username changed or implicit username,
+	   setup/reset authentication context. */
+	if ((authctxt->attempt++ == 0) ||
+	    (strcmp(user, authctxt->user) != 0) ||
+	    (strcmp(user, "") == 0)) {
+		if (authctxt->user) {
+		    xfree(authctxt->user);
+		    authctxt->user = NULL;
+		}
+		authctxt->valid = 0;
+#ifdef GSSAPI
+		/* If we're going to set the username based on the
+		   GSSAPI context later, then wait until then to
+		   verify it. Just put in placeholders for now. */
+		if ((strcmp(user, "") == 0) &&
+		    ((strcmp(method, "gssapi") == 0) ||
+		     (strcmp(method, "gssapi-with-mic") == 0))) {
+			authctxt->pw = fakepw();
+			authctxt->user = xstrdup(user);
+		} else {
+#endif
 		authctxt->pw = PRIVSEP(getpwnamallow(user));
 		authctxt->user = xstrdup(user);
 		if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
@@ -171,15 +216,24 @@
 			PRIVSEP(audit_event(SSH_INVALID_USER));
 #endif
 		}
+#ifdef GSSAPI
+		} /* endif for setting username based on GSSAPI context */
+#endif
 		setproctitle("%s%s", authctxt->valid ? user : "unknown",
 		    use_privsep ? " [net]" : "");
+#ifdef GSSAPI
+		if (authctxt->attempt == 1) {
+#endif
 		authctxt->service = xstrdup(service);
 		authctxt->style = style ? xstrdup(style) : NULL;
 		if (use_privsep)
 			mm_inform_authserv(service, style);
-	} else if (strcmp(user, authctxt->user) != 0 ||
-	    strcmp(service, authctxt->service) != 0) {
-		packet_disconnect("Change of username or service not allowed: "
+#ifdef GSSAPI
+		} /* if (authctxt->attempt == 1) */
+#endif
+	}
+	if (strcmp(service, authctxt->service) != 0) {
+		packet_disconnect("Change of service not allowed: "
 		    "(%s,%s) -> (%s,%s)",
 		    authctxt->user, authctxt->service, user, service);
 	}
@@ -192,6 +246,7 @@
 #endif
 
 	authctxt->postponed = 0;
+	authctxt->server_caused_failure = 0;
 
 	/* try to authenticate user */
 	m = authmethod_lookup(method);
@@ -262,7 +317,9 @@
 		/* now we can break out */
 		authctxt->success = 1;
 	} else {
-		if (authctxt->failures++ > options.max_authtries) {
+		/* Dont count server configuration issues against the client */
+		if (!authctxt->server_caused_failure && 
+		    authctxt->failures++ > options.max_authtries) {
 #ifdef SSH_AUDIT_EVENTS
 			PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
 #endif
diff -Naur --exclude=autom4te.cache openssh-4.2p1/buffer.c openssh-4.2p1-gssapi/buffer.c
--- openssh-4.2p1/buffer.c	2005-03-14 06:22:26.000000000 -0600
+++ openssh-4.2p1-gssapi/buffer.c	2005-12-20 13:30:59.000000000 -0600
@@ -107,7 +107,7 @@
 	/* Increase the size of the buffer and retry. */
 
 	newlen = buffer->alloc + len + 32768;
-	if (newlen > BUFFER_MAX_LEN)
+	if (newlen > BUFFER_MAX_HPN_LEN)
 		fatal("buffer_append_space: alloc %u not supported",
 		    newlen);
 	buffer->buf = xrealloc(buffer->buf, newlen);
diff -Naur --exclude=autom4te.cache openssh-4.2p1/buffer.h openssh-4.2p1-gssapi/buffer.h
--- openssh-4.2p1/buffer.h	2005-03-14 06:22:26.000000000 -0600
+++ openssh-4.2p1-gssapi/buffer.h	2005-12-20 13:30:59.000000000 -0600
@@ -25,6 +25,7 @@
 
 #define	BUFFER_MAX_CHUNK	0x100000
 #define	BUFFER_MAX_LEN		0xa00000
+#define BUFFER_MAX_HPN_LEN	(2<<29)-1
 
 void	 buffer_init(Buffer *);
 void	 buffer_clear(Buffer *);
diff -Naur --exclude=autom4te.cache openssh-4.2p1/canohost.c openssh-4.2p1-gssapi/canohost.c
--- openssh-4.2p1/canohost.c	2005-07-17 02:04:47.000000000 -0500
+++ openssh-4.2p1-gssapi/canohost.c	2005-12-20 13:30:59.000000000 -0600
@@ -402,3 +402,33 @@
 {
 	return get_port(1);
 }
+
+void
+resolve_localhost(char **host)
+{
+    struct hostent *hostinfo;
+
+    hostinfo = gethostbyname(*host);
+    if (hostinfo == NULL || hostinfo->h_name == NULL) {
+	debug("gethostbyname(%s) failed", *host);
+	return;
+    }
+    if (hostinfo->h_addrtype == AF_INET) {
+	struct in_addr addr;
+	addr = *(struct in_addr *)(hostinfo->h_addr);
+	if (ntohl(addr.s_addr) == INADDR_LOOPBACK) {
+	    char buf[MAXHOSTNAMELEN];
+	    if (gethostname(buf, sizeof(buf)) < 0) {
+		debug("gethostname() failed");
+		return;
+	    }
+	    hostinfo = gethostbyname(buf);
+	    xfree(*host);
+	    if (hostinfo == NULL || hostinfo->h_name == NULL) {
+		*host = xstrdup(buf);
+	    } else {
+		*host = xstrdup(hostinfo->h_name);
+	    }
+	}
+    }
+}
diff -Naur --exclude=autom4te.cache openssh-4.2p1/canohost.h openssh-4.2p1-gssapi/canohost.h
--- openssh-4.2p1/canohost.h	2005-02-02 06:30:25.000000000 -0600
+++ openssh-4.2p1-gssapi/canohost.h	2005-12-20 13:30:59.000000000 -0600
@@ -24,4 +24,6 @@
 int		 get_remote_port(void);
 int		 get_local_port(void);
 
+void		 resolve_localhost(char **host);
+
 void		 ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *);
diff -Naur --exclude=autom4te.cache openssh-4.2p1/channels.c openssh-4.2p1-gssapi/channels.c
--- openssh-4.2p1/channels.c	2005-07-17 02:22:45.000000000 -0500
+++ openssh-4.2p1-gssapi/channels.c	2005-12-20 13:30:59.000000000 -0600
@@ -262,6 +262,7 @@
 	c->local_window_max = window;
 	c->local_consumed = 0;
 	c->local_maxpacket = maxpack;
+	c->dynamic_window = 0;
 	c->remote_id = -1;
 	c->remote_name = xstrdup(remote_name);
 	c->remote_window = 0;
@@ -718,7 +719,7 @@
 	u_int limit = compat20 ? c->remote_window : packet_get_maxsize();
 
 	/* check buffer limits */
-	limit = MIN(limit, (BUFFER_MAX_LEN - BUFFER_MAX_CHUNK - CHAN_RBUF));
+	limit = MIN(limit, (BUFFER_MAX_HPN_LEN - BUFFER_MAX_CHUNK - CHAN_RBUF));
 
 	if (c->istate == CHAN_INPUT_OPEN &&
 	    limit > 0 &&
@@ -1537,14 +1538,29 @@
 	    !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&
 	    c->local_window < c->local_window_max/2 &&
 	    c->local_consumed > 0) {
+		u_int32_t tcpwinsz = 0;
+		socklen_t optsz = sizeof(tcpwinsz);
+		int ret = -1;
+		u_int32_t addition = 0;
+		if (c->dynamic_window) {
+			ret = getsockopt(packet_get_connection_in(), 
+				SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz);
+			if ((ret == 0) && tcpwinsz > BUFFER_MAX_HPN_LEN) 
+				tcpwinsz = BUFFER_MAX_HPN_LEN;
+		}
+		if (c->dynamic_window && (ret == 0) && 
+		    (tcpwinsz > c->local_window_max)) {
+			addition = tcpwinsz - c->local_window_max;
+			c->local_window_max += addition;
+		}
 		packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
 		packet_put_int(c->remote_id);
-		packet_put_int(c->local_consumed);
+		packet_put_int(c->local_consumed + addition);
 		packet_send();
 		debug2("channel %d: window %d sent adjust %d",
 		    c->self, c->local_window,
 		    c->local_consumed);
-		c->local_window += c->local_consumed;
+		c->local_window += c->local_consumed + addition;
 		c->local_consumed = 0;
 	}
 	return 1;
diff -Naur --exclude=autom4te.cache openssh-4.2p1/channels.h openssh-4.2p1-gssapi/channels.h
--- openssh-4.2p1/channels.h	2005-07-17 02:19:25.000000000 -0500
+++ openssh-4.2p1-gssapi/channels.h	2005-12-20 13:30:59.000000000 -0600
@@ -99,6 +99,7 @@
 	u_int	local_window_max;
 	u_int	local_consumed;
 	u_int	local_maxpacket;
+	int	dynamic_window;
 	int     extended_usage;
 	int	single_connection;
 
@@ -119,11 +120,11 @@
 
 /* default window/packet sizes for tcp/x11-fwd-channel */
 #define CHAN_SES_PACKET_DEFAULT	(32*1024)
-#define CHAN_SES_WINDOW_DEFAULT	(4*CHAN_SES_PACKET_DEFAULT)
+#define CHAN_SES_WINDOW_DEFAULT	(0xa00000/2)
 #define CHAN_TCP_PACKET_DEFAULT	(32*1024)
-#define CHAN_TCP_WINDOW_DEFAULT	(4*CHAN_TCP_PACKET_DEFAULT)
+#define CHAN_TCP_WINDOW_DEFAULT	(0xa00000/2)
 #define CHAN_X11_PACKET_DEFAULT	(16*1024)
-#define CHAN_X11_WINDOW_DEFAULT	(4*CHAN_X11_PACKET_DEFAULT)
+#define CHAN_X11_WINDOW_DEFAULT	(0xa00000/2)
 
 /* possible input states */
 #define CHAN_INPUT_OPEN			0
diff -Naur --exclude=autom4te.cache openssh-4.2p1/cipher.c openssh-4.2p1-gssapi/cipher.c
--- openssh-4.2p1/cipher.c	2005-07-17 02:02:10.000000000 -0500
+++ openssh-4.2p1-gssapi/cipher.c	2005-12-20 13:30:59.000000000 -0600
@@ -151,7 +151,8 @@
 	for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
 	    (p = strsep(&cp, CIPHER_SEP))) {
 		c = cipher_by_name(p);
-		if (c == NULL || c->number != SSH_CIPHER_SSH2) {
+		if (c == NULL || (c->number != SSH_CIPHER_SSH2 && 
+c->number != SSH_CIPHER_NONE)) {
 			debug("bad cipher %s [%s]", p, names);
 			xfree(cipher_list);
 			return 0;
@@ -325,6 +326,7 @@
 	int evplen;
 
 	switch (c->number) {
+	case SSH_CIPHER_NONE:
 	case SSH_CIPHER_SSH2:
 	case SSH_CIPHER_DES:
 	case SSH_CIPHER_BLOWFISH:
@@ -359,6 +361,7 @@
 	int evplen = 0;
 
 	switch (c->number) {
+	case SSH_CIPHER_NONE:
 	case SSH_CIPHER_SSH2:
 	case SSH_CIPHER_DES:
 	case SSH_CIPHER_BLOWFISH:
diff -Naur --exclude=autom4te.cache openssh-4.2p1/compat.c openssh-4.2p1-gssapi/compat.c
--- openssh-4.2p1/compat.c	2005-03-01 04:24:33.000000000 -0600
+++ openssh-4.2p1-gssapi/compat.c	2005-12-20 13:30:59.000000000 -0600
@@ -162,6 +162,14 @@
 		    strlen(check[i].pat), 0) == 1) {
 			debug("match: %s pat %s", version, check[i].pat);
 			datafellows = check[i].bugs;
+			/* Check to see if the remote side is OpenSSH and not HPN */
+			if(strstr(version,"OpenSSH") != NULL)
+			{
+				if (strstr(version,"hpn") == NULL)
+				{
+					datafellows |= SSH_BUG_LARGEWINDOW;
+				}
+			}
 			return;
 		}
 	}
diff -Naur --exclude=autom4te.cache openssh-4.2p1/compat.h openssh-4.2p1-gssapi/compat.h
--- openssh-4.2p1/compat.h	2005-03-01 04:24:33.000000000 -0600
+++ openssh-4.2p1-gssapi/compat.h	2005-12-20 13:30:59.000000000 -0600
@@ -56,6 +56,7 @@
 #define SSH_BUG_PROBE		0x00400000
 #define SSH_BUG_FIRSTKEX	0x00800000
 #define SSH_OLD_FORWARD_ADDR	0x01000000
+#define SSH_BUG_LARGEWINDOW     0x02000000
 
 void     enable_compat13(void);
 void     enable_compat20(void);
diff -Naur --exclude=autom4te.cache openssh-4.2p1/config.h.in openssh-4.2p1-gssapi/config.h.in
--- openssh-4.2p1/config.h.in	2005-09-01 04:15:22.000000000 -0500
+++ openssh-4.2p1-gssapi/config.h.in	2005-12-20 13:31:15.000000000 -0600
@@ -250,6 +250,9 @@
 /* Define if compiler implements __func__ */
 #undef HAVE___func__
 
+/* Define this if you're building with GSSAPI MechGlue */
+#undef MECHGLUE
+
 /* Define this is you want GSSAPI support in the version 2 protocol */
 #undef GSSAPI
 
@@ -259,6 +262,16 @@
 /* Define this if you are using the Heimdal version of Kerberos V5 */
 #undef HEIMDAL
 
+/* Define this if you want to use AFS/Kerberos 5 option, which runs aklog. */
+#undef AFS_KRB5
+#undef AKLOG_PATH
+
+/* Define if you want GSI/Globus authentication support */
+#undef GSI
+
+/* Define this if you want support for startup/shutdown hooks */
+#undef SESSION_HOOKS
+
 /* Define this if you want to use libkafs' AFS support */
 #undef USE_AFS
 
@@ -347,6 +360,12 @@
 /* getaddrinfo is broken (if present) */
 #undef BROKEN_GETADDRINFO
 
+/* platform uses an in-memory credentials cache */
+#undef USE_CCAPI
+
+/* platform has a Security Authorization Session API */
+#undef USE_SECURITY_SESSION_API
+
 /* updwtmpx is broken (if present) */
 #undef BROKEN_UPDWTMPX
 
diff -Naur --exclude=autom4te.cache openssh-4.2p1/configure openssh-4.2p1-gssapi/configure
--- openssh-4.2p1/configure	2005-09-01 04:15:24.000000000 -0500
+++ openssh-4.2p1-gssapi/configure	2005-12-20 13:31:19.000000000 -0600
@@ -311,7 +311,7 @@
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT build build_cpu build_vendor build_os host host_cpu host_vendor host_os AWK CPP RANLIB ac_ct_RANLIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AR CAT KILL PERL SED ENT TEST_MINUS_S_SH SH TEST_SHELL PATH_GROUPADD_PROG PATH_USERADD_PROG MAKE_PACKAGE_SUPPORTED LOGIN_PROGRAM_FALLBACK PATH_PASSWD_PROG LD EGREP LIBWRAP LIBEDIT LIBPAM INSTALL_SSH_RAND_HELPER SSH_PRIVSEP_USER PROG_LS PROG_NETSTAT PROG_ARP PROG_IFCONFIG PROG_JSTAT PROG_PS PROG_SAR PROG_W PROG_WHO PROG_LAST PROG_LASTLOG PROG_DF PROG_VMSTAT PROG_UPTIME PROG_IPCS PROG_TAIL INSTALL_SSH_PRNG_CMDS OPENSC_CONFIG PRIVSEP_PATH xauth_path STRIP_OPT XAUTH_PATH NROFF MANTYPE mansubdir user_path piddir LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT build build_cpu build_vendor build_os host host_cpu host_vendor host_os AWK CPP RANLIB ac_ct_RANLIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AR CAT KILL PERL SED ENT TEST_MINUS_S_SH SH TEST_SHELL PATH_GROUPADD_PROG PATH_USERADD_PROG MAKE_PACKAGE_SUPPORTED LOGIN_PROGRAM_FALLBACK PATH_PASSWD_PROG LD EGREP INSTALL_GSISSH LIBWRAP LIBEDIT LIBPAM INSTALL_SSH_RAND_HELPER SSH_PRIVSEP_USER PROG_LS PROG_NETSTAT PROG_ARP PROG_IFCONFIG PROG_JSTAT PROG_PS PROG_SAR PROG_W PROG_WHO PROG_LAST PROG_LASTLOG PROG_DF PROG_VMSTAT PROG_UPTIME PROG_IPCS PROG_TAIL INSTALL_SSH_PRNG_CMDS OPENSC_CONFIG PRIVSEP_PATH xauth_path STRIP_OPT XAUTH_PATH NROFF MANTYPE mansubdir user_path piddir LIBOBJS LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -872,6 +872,11 @@
   --with-Werror           Build main code with -Werror
   --with-zlib=PATH        Use zlib in PATH
   --without-zlib-version-check Disable zlib version check
+  --with-mechglue=PATH    Build with GSSAPI mechglue library
+  --with-gsi              Enable Globus GSI authentication support
+  --with-globus           Enable Globus GSI authentication support
+  --with-globus-static    Link statically with Globus GSI libraries
+  --with-globus-flavor=TYPE  Specify Globus flavor type (ex: gcc32dbg)
   --with-skey[=PATH]      Enable S/Key support (optionally in PATH)
   --with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH)
   --with-libedit[=PATH]   Enable libedit support for sftp
@@ -886,6 +891,8 @@
   --with-sectok           Enable smartcard support using libsectok
 --with-opensc[=PFX]       Enable smartcard support using OpenSC (optionally in PATH)
   --with-kerberos5=PATH   Enable Kerberos 5 support
+  --with-afs-krb5[=AKLOG_PATH]  Enable aklog to get token (default=/usr/bin/aklog).
+  --with-session-hooks    Enable hooks for executing external commands                                       before/after a session
   --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty)
   --with-xauth=PATH       Specify path to xauth program
   --with-mantype=man|cat|doc  Set man page type
@@ -5275,69 +5282,143 @@
 
 	;;
 *-*-darwin*)
-	echo "$as_me:$LINENO: checking if we have working getaddrinfo" >&5
-echo $ECHO_N "checking if we have working getaddrinfo... $ECHO_C" >&6
-	if test "$cross_compiling" = yes; then
-  echo "$as_me:$LINENO: result: assume it is working" >&5
-echo "${ECHO_T}assume it is working" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
+	cat >>confdefs.h <<\_ACEOF
+#define BROKEN_GETADDRINFO 1
+_ACEOF
+
+	cat >>confdefs.h <<\_ACEOF
+#define SETEUID_BREAKS_SETUID 1
+_ACEOF
+
+	cat >>confdefs.h <<\_ACEOF
+#define BROKEN_SETREUID 1
+_ACEOF
+
+	cat >>confdefs.h <<\_ACEOF
+#define BROKEN_SETREGID 1
+_ACEOF
+
+	cat >>confdefs.h <<_ACEOF
+#define BIND_8_COMPAT 1
+_ACEOF
+
+	echo "$as_me:$LINENO: checking if we have the Security Authorization Session API" >&5
+echo $ECHO_N "checking if we have the Security Authorization Session API... $ECHO_C" >&6
+	cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <mach-o/dyld.h>
-main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
-		exit(0);
-	else
-		exit(1);
+#include <Security/AuthSession.h>
+int
+main ()
+{
+SessionCreate(0, 0);
+  ;
+  return 0;
 }
 _ACEOF
-rm -f conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>&5
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  echo "$as_me:$LINENO: result: working" >&5
-echo "${ECHO_T}working" >&6
+  ac_cv_use_security_session_api="yes"
+		 cat >>confdefs.h <<\_ACEOF
+#define USE_SECURITY_SESSION_API 1
+_ACEOF
+
+		 LIBS="$LIBS -framework Security"
+		 echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
 else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
+  echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-( exit $ac_status )
-echo "$as_me:$LINENO: result: buggy" >&5
-echo "${ECHO_T}buggy" >&6
-	cat >>confdefs.h <<\_ACEOF
-#define BROKEN_GETADDRINFO 1
-_ACEOF
-
-fi
-rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+ac_cv_use_security_session_api="no"
+		 echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
-	cat >>confdefs.h <<\_ACEOF
-#define SETEUID_BREAKS_SETUID 1
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+	echo "$as_me:$LINENO: checking if we have an in-memory credentials cache" >&5
+echo $ECHO_N "checking if we have an in-memory credentials cache... $ECHO_C" >&6
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
 _ACEOF
-
-	cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREUID 1
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <Kerberos/Kerberos.h>
+int
+main ()
+{
+cc_context_t c;
+		 (void) cc_initialize (&c, 0, NULL, NULL);
+  ;
+  return 0;
+}
 _ACEOF
-
-	cat >>confdefs.h <<\_ACEOF
-#define BROKEN_SETREGID 1
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  cat >>confdefs.h <<\_ACEOF
+#define USE_CCAPI 1
 _ACEOF
 
-	cat >>confdefs.h <<_ACEOF
-#define BIND_8_COMPAT 1
-_ACEOF
+		 LIBS="$LIBS -framework Security"
+		 echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+		 if test "x$ac_cv_use_security_session_api" = "xno"; then
+			{ { echo "$as_me:$LINENO: error: *** Need a security framework to use the credentials cache API ***" >&5
+echo "$as_me: error: *** Need a security framework to use the credentials cache API ***" >&2;}
+   { (exit 1); exit 1; }; }
+		fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 	;;
 *-*-hpux*)
 	# first we define all of the options common to all HP-UX releases
@@ -9819,62 +9900,376 @@
 rm -f conftest*
 
 
-echo "$as_me:$LINENO: checking whether struct dirent allocates space for d_name" >&5
-echo $ECHO_N "checking whether struct dirent allocates space for d_name... $ECHO_C" >&6
-if test "$cross_compiling" = yes; then
+echo "$as_me:$LINENO: checking whether struct dirent allocates space for d_name" >&5
+echo $ECHO_N "checking whether struct dirent allocates space for d_name... $ECHO_C" >&6
+if test "$cross_compiling" = yes; then
+
+		{ echo "$as_me:$LINENO: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&5
+echo "$as_me: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&2;}
+		cat >>confdefs.h <<\_ACEOF
+#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1
+_ACEOF
+
+
+
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <dirent.h>
+int main(void){struct dirent d;exit(sizeof(d.d_name)<=sizeof(char));}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+
+		echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+		cat >>confdefs.h <<\_ACEOF
+#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1
+_ACEOF
+
+
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+# Check whether the user wants GSSAPI mechglue support
+
+# Check whether --with-mechglue or --without-mechglue was given.
+if test "${with_mechglue+set}" = set; then
+  withval="$with_mechglue"
+
+		echo "$as_me:$LINENO: checking for mechglue library" >&5
+echo $ECHO_N "checking for mechglue library... $ECHO_C" >&6
+
+		if test -e ${withval}/libgssapi.a ; then
+		    mechglue_lib=${withval}/libgssapi.a
+		elif test -e ${withval}/lib/libgssapi.a ; then
+		    mechglue_lib=${withval}/lib/libgssapi.a
+		else
+		    { { echo "$as_me:$LINENO: error: \"Can't find libgssapi in ${withval}\"" >&5
+echo "$as_me: error: \"Can't find libgssapi in ${withval}\"" >&2;}
+   { (exit 1); exit 1; }; };
+		fi
+		LIBS="$LIBS ${mechglue_lib}"
+		echo "$as_me:$LINENO: result: ${mechglue_lib}" >&5
+echo "${ECHO_T}${mechglue_lib}" >&6
+
+
+echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char dlopen ();
+int
+main ()
+{
+dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_dl_dlopen=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
+if test $ac_cv_lib_dl_dlopen = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+  LIBS="-ldl $LIBS"
+
+fi
+
+		if test $ac_cv_lib_dl_dlopen = yes; then
+		   LDFLAGS="$LDFLAGS -ldl -Wl,-Bsymbolic"
+		fi
+
+		cat >>confdefs.h <<\_ACEOF
+#define GSSAPI 1
+_ACEOF
+
+		cat >>confdefs.h <<\_ACEOF
+#define MECHGLUE 1
+_ACEOF
+
+		GSSAPI="mechglue"
+
+
+
+fi;
+
+
+# Check whether the user wants GSI (Globus) support
+gsi_path="no"
+
+# Check whether --with-gsi or --without-gsi was given.
+if test "${with_gsi+set}" = set; then
+  withval="$with_gsi"
+
+		gsi_path="$withval"
+
+
+fi;
+
+
+# Check whether --with-globus or --without-globus was given.
+if test "${with_globus+set}" = set; then
+  withval="$with_globus"
+
+		gsi_path="$withval"
+
+
+fi;
+
+
+# Check whether --with-globus-static or --without-globus-static was given.
+if test "${with_globus_static+set}" = set; then
+  withval="$with_globus_static"
+
+		gsi_static="-static"
+		if test "x$gsi_path" = "xno" ; then
+			gsi_path="$withval"
+		fi
+
+
+fi;
+
+# Check whether the user has a Globus flavor type
+globus_flavor_type="no"
+
+# Check whether --with-globus-flavor or --without-globus-flavor was given.
+if test "${with_globus_flavor+set}" = set; then
+  withval="$with_globus_flavor"
+
+		globus_flavor_type="$withval"
+		if test "x$gsi_path" = "xno" ; then
+			gsi_path="yes"
+		fi
+
+
+fi;
+
+if test "x$gsi_path" != "xno" ; then
+	# Globus GSSAPI configuration
+	echo "$as_me:$LINENO: checking for Globus GSI" >&5
+echo $ECHO_N "checking for Globus GSI... $ECHO_C" >&6
+	cat >>confdefs.h <<\_ACEOF
+#define GSI 1
+_ACEOF
+
+
+	if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then
+		{ { echo "$as_me:$LINENO: error: Previously configured GSSAPI library conflicts with Globus GSI." >&5
+echo "$as_me: error: Previously configured GSSAPI library conflicts with Globus GSI." >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+	if test -z "$GSSAPI"; then
+		cat >>confdefs.h <<\_ACEOF
+#define GSSAPI 1
+_ACEOF
+
+		GSSAPI="GSI"
+	fi
+
+	if test "x$gsi_path" = "xyes" ; then
+		if test -z "$GLOBUS_LOCATION" ; then
+			{ { echo "$as_me:$LINENO: error: GLOBUS_LOCATION environment variable must be set." >&5
+echo "$as_me: error: GLOBUS_LOCATION environment variable must be set." >&2;}
+   { (exit 1); exit 1; }; }
+		else
+			gsi_path="$GLOBUS_LOCATION"
+		fi
+	fi
+	GLOBUS_LOCATION="$gsi_path"
+	export GLOBUS_LOCATION
+	if test ! -d "$GLOBUS_LOCATION" ; then
+		{ { echo "$as_me:$LINENO: error: Cannot find Globus installation.  Set GLOBUS_LOCATION environment variable." >&5
+echo "$as_me: error: Cannot find Globus installation.  Set GLOBUS_LOCATION environment variable." >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+
+        if test "x$globus_flavor_type" = "xno" ; then
+                { { echo "$as_me:$LINENO: error: --with-globus-flavor=TYPE must be specified" >&5
+echo "$as_me: error: --with-globus-flavor=TYPE must be specified" >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+        if test "x$globus_flavor_type" = "xyes" ; then
+                { { echo "$as_me:$LINENO: error: --with-globus-flavor=TYPE must specify a flavor type" >&5
+echo "$as_me: error: --with-globus-flavor=TYPE must specify a flavor type" >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+
+	GLOBUS_INCLUDE="${gsi_path}/include/${globus_flavor_type}"
+	if test ! -d "$GLOBUS_INCLUDE" ; then
+		{ { echo "$as_me:$LINENO: error: Cannot find Globus flavor-specific include directory: ${GLOBUS_INCLUDE}" >&5
+echo "$as_me: error: Cannot find Globus flavor-specific include directory: ${GLOBUS_INCLUDE}" >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+	GSI_CPPFLAGS="-I${GLOBUS_INCLUDE}"
+
+	if test -x ${gsi_path}/bin/globus-makefile-header ; then
+		GSI_LIBS=`${gsi_path}/bin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | perl -n -e 'if (/GLOBUS_PKG_LIBS = (.*)/){print $1;}'`
+	elif test -x ${gsi_path}/sbin/globus-makefile-header ; then
+		GSI_LIBS=`${gsi_path}/sbin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | perl -n -e 'if (/GLOBUS_PKG_LIBS = (.*)/){print $1;}'`
+	else
+		{ { echo "$as_me:$LINENO: error: Cannot find globus-makefile-header: Globus installation is incomplete" >&5
+echo "$as_me: error: Cannot find globus-makefile-header: Globus installation is incomplete" >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+	if test -n "${need_dash_r}"; then
+		GSI_LDFLAGS="-L${gsi_path}/lib -R{gsi_path}/lib"
+	else
+		GSI_LDFLAGS="-L${gsi_path}/lib"
+	fi
+	if test -z "$GSI_LIBS" ; then
+		{ { echo "$as_me:$LINENO: error: globus-makefile-header failed" >&5
+echo "$as_me: error: globus-makefile-header failed" >&2;}
+   { (exit 1); exit 1; }; }
+	fi
 
-		{ echo "$as_me:$LINENO: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&5
-echo "$as_me: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&2;}
-		cat >>confdefs.h <<\_ACEOF
-#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1
+	cat >>confdefs.h <<\_ACEOF
+#define HAVE_GSSAPI_H 1
 _ACEOF
 
 
+	LIBS="$LIBS $GSI_LIBS"
+	LDFLAGS="$LDFLAGS $GSI_LDFLAGS"
+	CPPFLAGS="$CPPFLAGS $GSI_CPPFLAGS"
 
-else
-  cat >conftest.$ac_ext <<_ACEOF
+	# test that we got the libraries OK
+	cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-#include <sys/types.h>
-#include <dirent.h>
-int main(void){struct dirent d;exit(sizeof(d.d_name)<=sizeof(char));}
+int
+main ()
+{
 
+  ;
+  return 0;
+}
 _ACEOF
-rm -f conftest$ac_exeext
+rm -f conftest.$ac_objext conftest$ac_exeext
 if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  echo "$as_me:$LINENO: result: yes" >&5
+
+			echo "$as_me:$LINENO: result: yes" >&5
 echo "${ECHO_T}yes" >&6
+
 else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
+  echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-( exit $ac_status )
 
-		echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-		cat >>confdefs.h <<\_ACEOF
-#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1
-_ACEOF
+			{ { echo "$as_me:$LINENO: error: link with Globus libraries failed" >&5
+echo "$as_me: error: link with Globus libraries failed" >&2;}
+   { (exit 1); exit 1; }; }
 
 
 fi
-rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+	INSTALL_GSISSH="yes"
+else
+	INSTALL_GSISSH=""
 fi
 
+# End Globus/GSI section
+
 echo "$as_me:$LINENO: checking for /proc/pid/fd directory" >&5
 echo $ECHO_N "checking for /proc/pid/fd directory... $ECHO_C" >&6
 if test -d "/proc/$$/fd" ; then
@@ -14140,7 +14535,9 @@
 
 
 fi;
+if test -z "$GSI_LIBS" ; then
 LIBS="-lcrypto $LIBS"
+fi
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -23579,7 +23976,165 @@
 
 
 
-		fi
+			# If we're using some other GSSAPI
+			if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then
+				{ { echo "$as_me:$LINENO: error: $GSSAPI GSSAPI library conflicts with Kerberos support.  Use mechglue instead." >&5
+echo "$as_me: error: $GSSAPI GSSAPI library conflicts with Kerberos support.  Use mechglue instead." >&2;}
+   { (exit 1); exit 1; }; }
+			fi
+
+			if test -z "$GSSAPI"; then
+				GSSAPI="KRB5";
+			fi
+
+			oldCPP="$CPPFLAGS"
+			CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
+			if test "${ac_cv_header_gssapi_krb5_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for gssapi_krb5.h" >&5
+echo $ECHO_N "checking for gssapi_krb5.h... $ECHO_C" >&6
+if test "${ac_cv_header_gssapi_krb5_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_gssapi_krb5_h" >&5
+echo "${ECHO_T}$ac_cv_header_gssapi_krb5_h" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking gssapi_krb5.h usability" >&5
+echo $ECHO_N "checking gssapi_krb5.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <gssapi_krb5.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking gssapi_krb5.h presence" >&5
+echo $ECHO_N "checking gssapi_krb5.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <gssapi_krb5.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: gssapi_krb5.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: gssapi_krb5.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: gssapi_krb5.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: gssapi_krb5.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: gssapi_krb5.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: gssapi_krb5.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: gssapi_krb5.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: gssapi_krb5.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------- ##
+## Report this to openssh-unix-dev@mindrot.org ##
+## ------------------------------------------- ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for gssapi_krb5.h" >&5
+echo $ECHO_N "checking for gssapi_krb5.h... $ECHO_C" >&6
+if test "${ac_cv_header_gssapi_krb5_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_gssapi_krb5_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_gssapi_krb5_h" >&5
+echo "${ECHO_T}$ac_cv_header_gssapi_krb5_h" >&6
+
+fi
+if test $ac_cv_header_gssapi_krb5_h = yes; then
+  :
+else
+   CPPFLAGS="$oldCPP"
+fi
+
+
+
+                fi
 		if test ! -z "$need_dash_r" ; then
 			LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib"
 		fi
@@ -24176,6 +24731,57 @@
 
 fi;
 
+# Check whether user wants AFS_KRB5 support
+AFS_KRB5_MSG="no"
+
+# Check whether --with-afs-krb5 or --without-afs-krb5 was given.
+if test "${with_afs_krb5+set}" = set; then
+  withval="$with_afs_krb5"
+
+		if test "x$withval" != "xno" ; then
+
+			if test "x$withval" != "xyes" ; then
+				cat >>confdefs.h <<_ACEOF
+#define AKLOG_PATH "$withval"
+_ACEOF
+
+			else
+				cat >>confdefs.h <<_ACEOF
+#define AKLOG_PATH "/usr/bin/aklog"
+_ACEOF
+
+			fi
+
+			if test -z "$KRB5ROOT" ; then
+				{ echo "$as_me:$LINENO: WARNING: AFS_KRB5 requires Kerberos 5 support, build may fail" >&5
+echo "$as_me: WARNING: AFS_KRB5 requires Kerberos 5 support, build may fail" >&2;}
+			fi
+
+			LIBS="-lkrbafs -lkrb4 $LIBS"
+			if test ! -z "$AFS_LIBS" ; then
+				LIBS="$LIBS $AFS_LIBS"
+			fi
+			cat >>confdefs.h <<\_ACEOF
+#define AFS_KRB5 1
+_ACEOF
+
+			AFS_KRB5_MSG="yes"
+		fi
+
+
+fi;
+
+
+# Check whether --with-session-hooks or --without-session-hooks was given.
+if test "${with_session_hooks+set}" = set; then
+  withval="$with_session_hooks"
+   cat >>confdefs.h <<\_ACEOF
+#define SESSION_HOOKS 1
+_ACEOF
+
+
+fi;
+
 # Looking for programs, paths and files
 
 PRIVSEP_PATH=/var/empty
@@ -25821,9 +26427,9 @@
 exec 5>>config.log
 {
   echo
-  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<BOXI_EOF
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
 ## Running $as_me. ##
-BOXI_EOF
+_ASBOX
 } >&5
 cat >&5 <<_CSEOF
 
@@ -26120,6 +26726,7 @@
 s,@PATH_PASSWD_PROG@,$PATH_PASSWD_PROG,;t t
 s,@LD@,$LD,;t t
 s,@EGREP@,$EGREP,;t t
+s,@INSTALL_GSISSH@,$INSTALL_GSISSH,;t t
 s,@LIBWRAP@,$LIBWRAP,;t t
 s,@LIBEDIT@,$LIBEDIT,;t t
 s,@LIBPAM@,$LIBPAM,;t t
diff -Naur --exclude=autom4te.cache openssh-4.2p1/configure.ac openssh-4.2p1-gssapi/configure.ac
--- openssh-4.2p1/configure.ac	2005-08-31 11:59:49.000000000 -0500
+++ openssh-4.2p1-gssapi/configure.ac	2005-12-20 13:30:59.000000000 -0600
@@ -252,20 +252,33 @@
 	AC_DEFINE(BROKEN_SETREGID)
 	;;
 *-*-darwin*)
-	AC_MSG_CHECKING(if we have working getaddrinfo)
-	AC_TRY_RUN([#include <mach-o/dyld.h>
-main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
-		exit(0);
-	else
-		exit(1);
-}], [AC_MSG_RESULT(working)],
-	[AC_MSG_RESULT(buggy)
-	AC_DEFINE(BROKEN_GETADDRINFO)],
-	[AC_MSG_RESULT(assume it is working)])
+	AC_DEFINE(BROKEN_GETADDRINFO)
 	AC_DEFINE(SETEUID_BREAKS_SETUID)
 	AC_DEFINE(BROKEN_SETREUID)
 	AC_DEFINE(BROKEN_SETREGID)
 	AC_DEFINE_UNQUOTED(BIND_8_COMPAT, 1)
+	AC_MSG_CHECKING(if we have the Security Authorization Session API)
+	AC_TRY_COMPILE([#include <Security/AuthSession.h>],
+		[SessionCreate(0, 0);],
+		[ac_cv_use_security_session_api="yes"
+		 AC_DEFINE(USE_SECURITY_SESSION_API)
+		 LIBS="$LIBS -framework Security"
+		 AC_MSG_RESULT(yes)],
+		[ac_cv_use_security_session_api="no"
+		 AC_MSG_RESULT(no)])
+	AC_MSG_CHECKING(if we have an in-memory credentials cache)
+	AC_TRY_COMPILE(
+		[#include <Kerberos/Kerberos.h>],
+		[cc_context_t c;
+		 (void) cc_initialize (&c, 0, NULL, NULL);],
+		[AC_DEFINE(USE_CCAPI)
+		 LIBS="$LIBS -framework Security"
+		 AC_MSG_RESULT(yes)
+		 if test "x$ac_cv_use_security_session_api" = "xno"; then
+			AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***)
+		fi],
+		[AC_MSG_RESULT(no)]
+	)
 	;;
 *-*-hpux*)
 	# first we define all of the options common to all HP-UX releases
@@ -915,6 +928,152 @@
 	]
 )
 
+# Check whether the user wants GSSAPI mechglue support
+AC_ARG_WITH(mechglue,
+	[  --with-mechglue=PATH    Build with GSSAPI mechglue library],
+	[
+		AC_MSG_CHECKING(for mechglue library)
+
+		if test -e ${withval}/libgssapi.a ; then
+		    mechglue_lib=${withval}/libgssapi.a
+		elif test -e ${withval}/lib/libgssapi.a ; then
+		    mechglue_lib=${withval}/lib/libgssapi.a
+		else
+		    AC_MSG_ERROR("Can't find libgssapi in ${withval}");
+		fi
+		LIBS="$LIBS ${mechglue_lib}"
+		AC_MSG_RESULT(${mechglue_lib})
+
+		AC_CHECK_LIB(dl, dlopen, , )
+		if test $ac_cv_lib_dl_dlopen = yes; then
+		   LDFLAGS="$LDFLAGS -ldl -Wl,-Bsymbolic"
+		fi
+
+		AC_DEFINE(GSSAPI)
+		AC_DEFINE(MECHGLUE)
+		GSSAPI="mechglue"
+
+	]
+)
+
+
+# Check whether the user wants GSI (Globus) support
+gsi_path="no"
+AC_ARG_WITH(gsi,
+	[  --with-gsi              Enable Globus GSI authentication support],
+	[
+		gsi_path="$withval"
+	]
+)
+
+AC_ARG_WITH(globus,
+	[  --with-globus           Enable Globus GSI authentication support],
+	[
+		gsi_path="$withval"
+	]
+)
+
+AC_ARG_WITH(globus-static,
+	[  --with-globus-static    Link statically with Globus GSI libraries],
+	[
+		gsi_static="-static"
+		if test "x$gsi_path" = "xno" ; then
+			gsi_path="$withval"
+		fi
+	]
+)
+
+# Check whether the user has a Globus flavor type
+globus_flavor_type="no"
+AC_ARG_WITH(globus-flavor,
+	[  --with-globus-flavor=TYPE  Specify Globus flavor type (ex: gcc32dbg)],
+	[
+		globus_flavor_type="$withval"
+		if test "x$gsi_path" = "xno" ; then
+			gsi_path="yes"
+		fi
+	]
+)
+
+if test "x$gsi_path" != "xno" ; then
+	# Globus GSSAPI configuration
+	AC_MSG_CHECKING(for Globus GSI)
+	AC_DEFINE(GSI)
+
+	if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then
+		AC_MSG_ERROR([Previously configured GSSAPI library conflicts with Globus GSI.])
+	fi
+	if test -z "$GSSAPI"; then
+		AC_DEFINE(GSSAPI)
+		GSSAPI="GSI"
+	fi
+
+	if test "x$gsi_path" = "xyes" ; then
+		if test -z "$GLOBUS_LOCATION" ; then
+			AC_MSG_ERROR(GLOBUS_LOCATION environment variable must be set.)
+		else
+			gsi_path="$GLOBUS_LOCATION"
+		fi
+	fi
+	GLOBUS_LOCATION="$gsi_path"
+	export GLOBUS_LOCATION
+	if test ! -d "$GLOBUS_LOCATION" ; then
+		AC_MSG_ERROR(Cannot find Globus installation.  Set GLOBUS_LOCATION environment variable.)
+	fi
+
+        if test "x$globus_flavor_type" = "xno" ; then
+                AC_MSG_ERROR(--with-globus-flavor=TYPE must be specified)
+	fi
+        if test "x$globus_flavor_type" = "xyes" ; then
+                AC_MSG_ERROR(--with-globus-flavor=TYPE must specify a flavor type)
+	fi
+
+	GLOBUS_INCLUDE="${gsi_path}/include/${globus_flavor_type}"
+	if test ! -d "$GLOBUS_INCLUDE" ; then
+		AC_MSG_ERROR(Cannot find Globus flavor-specific include directory: ${GLOBUS_INCLUDE})
+	fi
+	GSI_CPPFLAGS="-I${GLOBUS_INCLUDE}"
+	
+	if test -x ${gsi_path}/bin/globus-makefile-header ; then
+		GSI_LIBS=`${gsi_path}/bin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | perl -n -e 'if (/GLOBUS_PKG_LIBS = (.*)/){print $1;}'`
+	elif test -x ${gsi_path}/sbin/globus-makefile-header ; then
+		GSI_LIBS=`${gsi_path}/sbin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | perl -n -e 'if (/GLOBUS_PKG_LIBS = (.*)/){print $1;}'`
+	else
+		AC_MSG_ERROR(Cannot find globus-makefile-header: Globus installation is incomplete)
+	fi
+	if test -n "${need_dash_r}"; then
+		GSI_LDFLAGS="-L${gsi_path}/lib -R{gsi_path}/lib"
+	else
+		GSI_LDFLAGS="-L${gsi_path}/lib"
+	fi
+	if test -z "$GSI_LIBS" ; then
+		AC_MSG_ERROR(globus-makefile-header failed)
+	fi
+
+	AC_DEFINE(HAVE_GSSAPI_H)
+
+	LIBS="$LIBS $GSI_LIBS"
+	LDFLAGS="$LDFLAGS $GSI_LDFLAGS"
+	CPPFLAGS="$CPPFLAGS $GSI_CPPFLAGS"
+
+	# test that we got the libraries OK
+	AC_TRY_LINK(
+		[],
+		[],
+		[
+			AC_MSG_RESULT(yes)
+		],
+		[
+			AC_MSG_ERROR(link with Globus libraries failed)
+		]
+	)
+	INSTALL_GSISSH="yes"
+else
+	INSTALL_GSISSH=""
+fi
+AC_SUBST(INSTALL_GSISSH)
+# End Globus/GSI section
+
 AC_MSG_CHECKING([for /proc/pid/fd directory])
 if test -d "/proc/$$/fd" ; then
 	AC_DEFINE(HAVE_PROC_PID)
@@ -1602,7 +1761,9 @@
 		fi
 	]
 )
+if test -z "$GSI_LIBS" ; then
 LIBS="-lcrypto $LIBS"
+fi
 AC_TRY_LINK_FUNC(RAND_add, AC_DEFINE(HAVE_OPENSSL),
 	[
 		dnl Check default openssl install dir
@@ -2750,7 +2911,21 @@
 			AC_CHECK_HEADER(gssapi_krb5.h, ,
 					[ CPPFLAGS="$oldCPP" ])
 
-		fi
+			# If we're using some other GSSAPI
+			if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then
+				AC_MSG_ERROR([$GSSAPI GSSAPI library conflicts with Kerberos support.  Use mechglue instead.])
+			fi
+
+			if test -z "$GSSAPI"; then
+				GSSAPI="KRB5";
+			fi
+
+			oldCPP="$CPPFLAGS"
+			CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
+			AC_CHECK_HEADER(gssapi_krb5.h, ,
+					[ CPPFLAGS="$oldCPP" ])
+
+                fi
 		if test ! -z "$need_dash_r" ; then
 			LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib"
 		fi
@@ -2768,6 +2943,38 @@
 	]
 )
 
+# Check whether user wants AFS_KRB5 support
+AFS_KRB5_MSG="no"
+AC_ARG_WITH(afs-krb5,
+	[  --with-afs-krb5[[=AKLOG_PATH]]  Enable aklog to get token (default=/usr/bin/aklog).],
+	[
+		if test "x$withval" != "xno" ; then
+
+			if test "x$withval" != "xyes" ; then
+				AC_DEFINE_UNQUOTED(AKLOG_PATH, "$withval")
+			else
+				AC_DEFINE_UNQUOTED(AKLOG_PATH, "/usr/bin/aklog")
+			fi
+
+			if test -z "$KRB5ROOT" ; then
+				AC_MSG_WARN([AFS_KRB5 requires Kerberos 5 support, build may fail])
+			fi
+
+			LIBS="-lkrbafs -lkrb4 $LIBS"
+			if test ! -z "$AFS_LIBS" ; then
+				LIBS="$LIBS $AFS_LIBS"
+			fi
+			AC_DEFINE(AFS_KRB5)
+			AFS_KRB5_MSG="yes"
+		fi
+	]
+)
+
+AC_ARG_WITH(session-hooks,
+        [  --with-session-hooks    Enable hooks for executing external commands                                       before/after a session],
+        [ AC_DEFINE(SESSION_HOOKS) ]
+)
+
 # Looking for programs, paths and files
 
 PRIVSEP_PATH=/var/empty
diff -Naur --exclude=autom4te.cache openssh-4.2p1/gss-genr.c openssh-4.2p1-gssapi/gss-genr.c
--- openssh-4.2p1/gss-genr.c	2005-07-17 02:22:45.000000000 -0500
+++ openssh-4.2p1-gssapi/gss-genr.c	2005-12-20 13:30:59.000000000 -0600
@@ -1,7 +1,7 @@
 /*	$OpenBSD: gss-genr.c,v 1.4 2005/07/17 07:17:55 djm Exp $	*/
 
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2005 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,17 +29,162 @@
 #ifdef GSSAPI
 
 #include "xmalloc.h"
+#include "buffer.h"
 #include "bufaux.h"
 #include "compat.h"
+#include <openssl/evp.h>
+#include "kex.h"
 #include "log.h"
 #include "monitor_wrap.h"
+#include "canohost.h"
 #include "ssh2.h"
+#include <openssl/evp.h>
 
 #include "ssh-gss.h"
 
 extern u_char *session_id2;
 extern u_int session_id2_len;
 
+typedef struct {
+	char *encoded;
+	gss_OID oid;
+} ssh_gss_kex_mapping;
+
+/*
+ * XXX - It would be nice to find a more elegant way of handling the
+ * XXX   passing of the key exchange context to the userauth routines
+ */
+
+Gssctxt *gss_kex_context = NULL;
+
+static ssh_gss_kex_mapping *gss_enc2oid = NULL;
+
+int 
+ssh_gssapi_oid_table_ok() {
+	return (gss_enc2oid != NULL);
+}
+
+/*
+ * Return a list of the gss-group1-sha1 mechanisms supported by this program
+ *
+ * We test mechanisms to ensure that we can use them, to avoid starting
+ * a key exchange with a bad mechanism
+ */
+
+
+char *
+ssh_gssapi_client_mechanisms(const char *host) {
+	gss_OID_set gss_supported;
+	OM_uint32 min_status;
+
+	gss_indicate_mechs(&min_status, &gss_supported);
+
+	return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
+	    (void *)host));
+}
+
+char *
+ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
+    void *data) {
+	Buffer buf;
+	size_t i;
+	int oidpos, enclen;
+	char *mechs, *encoded;
+	unsigned char digest[EVP_MAX_MD_SIZE];
+	char deroid[2];
+	const EVP_MD *evp_md = EVP_md5();
+	EVP_MD_CTX md;
+
+	if (gss_enc2oid != NULL) {
+		for (i=0;gss_enc2oid[i].encoded!=NULL;i++)
+			xfree(gss_enc2oid[i].encoded);
+		xfree(gss_enc2oid);
+	}
+
+	gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping)*
+	    (gss_supported->count+1));
+
+	buffer_init(&buf);
+
+	oidpos = 0;
+	for (i = 0;i < gss_supported->count;i++) {
+		if (gss_supported->elements[i].length < 128 &&
+		    (*check)(&(gss_supported->elements[i]), data)) {
+
+			deroid[0] = SSH_GSS_OIDTYPE;
+			deroid[1] = gss_supported->elements[i].length;
+
+			EVP_DigestInit(&md, evp_md);
+			EVP_DigestUpdate(&md, deroid, 2);
+			EVP_DigestUpdate(&md,
+			    gss_supported->elements[i].elements,
+			    gss_supported->elements[i].length);
+			EVP_DigestFinal(&md, digest, NULL);
+
+			encoded = xmalloc(EVP_MD_size(evp_md)*2);
+			enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
+			    encoded, EVP_MD_size(evp_md)*2);
+
+			if (oidpos != 0)
+			    buffer_put_char(&buf, ',');
+
+			buffer_append(&buf, KEX_GSS_GEX_SHA1_ID,
+			    sizeof(KEX_GSS_GEX_SHA1_ID)-1);
+			buffer_append(&buf, encoded, enclen);
+			buffer_put_char(&buf,',');
+			buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, 
+			    sizeof(KEX_GSS_GRP1_SHA1_ID)-1);
+			buffer_append(&buf, encoded, enclen);
+
+			gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
+			gss_enc2oid[oidpos].encoded = encoded;
+			oidpos++;
+		}
+	}
+	gss_enc2oid[oidpos].oid = NULL;
+	gss_enc2oid[oidpos].encoded = NULL;
+
+	buffer_put_char(&buf, '\0');
+
+	mechs = xmalloc(buffer_len(&buf));
+	buffer_get(&buf, mechs, buffer_len(&buf));
+	buffer_free(&buf);
+
+	if (strlen(mechs) == 0) {
+		xfree(mechs);
+		mechs = NULL;
+	}
+	
+	return (mechs);
+}
+
+gss_OID
+ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int *gex) {
+	int i = 0;
+
+	if (strncmp(name, KEX_GSS_GRP1_SHA1_ID,
+	    sizeof(KEX_GSS_GRP1_SHA1_ID)-1) == 0) {
+		name+=sizeof(KEX_GSS_GRP1_SHA1_ID)-1;
+		*gex = 0;
+	} else if (strncmp(name, KEX_GSS_GEX_SHA1_ID,
+	    sizeof(KEX_GSS_GEX_SHA1_ID)-1) == 0) {
+		name+=sizeof(KEX_GSS_GEX_SHA1_ID)-1;
+		*gex = 1;
+	} else {
+		return NULL;
+	}
+
+	while (gss_enc2oid[i].encoded != NULL &&
+	    strcmp(name, gss_enc2oid[i].encoded) != 0) {
+		i++;
+	}
+
+	if (gss_enc2oid[i].oid != NULL && ctx != NULL)
+		ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid);
+
+	return gss_enc2oid[i].oid;
+}
+
 /* Check that the OID in a data stream matches that in the context */
 int
 ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
@@ -98,7 +243,7 @@
 	/* The GSSAPI error */
 	do {
 		gss_display_status(&lmin, ctxt->major,
-		    GSS_C_GSS_CODE, GSS_C_NULL_OID, &ctx, &msg);
+		    GSS_C_GSS_CODE, ctxt->oid, &ctx, &msg);
 
 		buffer_append(&b, msg.value, msg.length);
 		buffer_put_char(&b, '\n');
@@ -109,7 +254,7 @@
 	/* The mechanism specific error */
 	do {
 		gss_display_status(&lmin, ctxt->minor,
-		    GSS_C_MECH_CODE, GSS_C_NULL_OID, &ctx, &msg);
+		    GSS_C_MECH_CODE, ctxt->oid, &ctx, &msg);
 
 		buffer_append(&b, msg.value, msg.length);
 		buffer_put_char(&b, '\n');
@@ -148,10 +293,13 @@
 void
 ssh_gssapi_delete_ctx(Gssctxt **ctx)
 {
+#if !defined(MECHGLUE)
 	OM_uint32 ms;
+#endif
 
 	if ((*ctx) == NULL)
 		return;
+#if !defined(MECHGLUE) /* mechglue has some memory management issues */
 	if ((*ctx)->context != GSS_C_NO_CONTEXT)
 		gss_delete_sec_context(&ms, &(*ctx)->context, GSS_C_NO_BUFFER);
 	if ((*ctx)->name != GSS_C_NO_NAME)
@@ -167,6 +315,7 @@
 		gss_release_name(&ms, &(*ctx)->client);
 	if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL)
 		gss_release_cred(&ms, &(*ctx)->client_creds);
+#endif
 
 	xfree(*ctx);
 	*ctx = NULL;
@@ -205,15 +354,25 @@
 ssh_gssapi_import_name(Gssctxt *ctx, const char *host)
 {
 	gss_buffer_desc gssbuf;
+	char *xhost;
 
-	gssbuf.length = sizeof("host@") + strlen(host);
+	/* Make a copy of the host name, in case it was returned by a
+	 * previous call to gethostbyname(). */	
+	xhost = xstrdup(host);
+
+	/* Make sure we have the FQDN. Some GSSAPI implementations don't do
+	 * this for us themselves */
+	resolve_localhost(&xhost);
+	
+	gssbuf.length = sizeof("host@") + strlen(xhost);
 	gssbuf.value = xmalloc(gssbuf.length);
-	snprintf(gssbuf.value, gssbuf.length, "host@%s", host);
+	snprintf(gssbuf.value, gssbuf.length, "host@%s", xhost);
 
 	if ((ctx->major = gss_import_name(&ctx->minor,
 	    &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name)))
 		ssh_gssapi_error(ctx);
 
+	xfree(xhost);
 	xfree(gssbuf.value);
 	return (ctx->major);
 }
@@ -250,6 +409,9 @@
 OM_uint32
 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
 {
+	if (ctx == NULL) 
+		return -1;
+
 	if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
 	    GSS_C_QOP_DEFAULT, buffer, hash)))
 		ssh_gssapi_error(ctx);
@@ -257,6 +419,19 @@
 	return (ctx->major);
 }
 
+/* Priviledged when used by server */
+OM_uint32
+ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
+{
+	if (ctx == NULL)
+		return -1;
+
+	ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
+	    gssbuf, gssmic, NULL);
+
+	return (ctx->major);
+}
+
 void
 ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
     const char *context)
@@ -278,4 +453,19 @@
 	return (ssh_gssapi_acquire_cred(*ctx));
 }
 
+int
+ssh_gssapi_check_mechanism(gss_OID oid, void *host) {
+	Gssctxt * ctx = NULL;
+	gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
+	OM_uint32 major, minor;
+	
+	ssh_gssapi_build_ctx(&ctx);
+	ssh_gssapi_set_oid(ctx, oid);
+	ssh_gssapi_import_name(ctx, host);
+	major = ssh_gssapi_init_ctx(ctx, 0, GSS_C_NO_BUFFER, &token, NULL);
+	gss_release_buffer(&minor, &token);
+	ssh_gssapi_delete_ctx(&ctx);
+	return (!GSS_ERROR(major));
+}
+
 #endif /* GSSAPI */
diff -Naur --exclude=autom4te.cache openssh-4.2p1/gss-serv-gsi.c openssh-4.2p1-gssapi/gss-serv-gsi.c
--- openssh-4.2p1/gss-serv-gsi.c	1969-12-31 18:00:00.000000000 -0600
+++ openssh-4.2p1-gssapi/gss-serv-gsi.c	2005-12-20 13:30:59.000000000 -0600
@@ -0,0 +1,157 @@
+/*
+ * 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 "auth.h"
+#include "auth-pam.h"
+#include "xmalloc.h"
+#include "log.h"
+#include "servconf.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
+};
+
+/*
+ * 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;
+    
+#ifdef GLOBUS_GSI_GSS_ASSIST_MODULE
+    if (globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE) != 0) {
+	return 0;
+    }
+#endif
+
+    /* This returns 0 on success */
+    authorized = (globus_gss_assist_userok(client->displayname.value,
+					   name) == 0);
+    
+    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)
+{
+#ifdef GLOBUS_GSI_GSS_ASSIST_MODULE
+    if (globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE) != 0) {
+	return 0;
+    }
+#endif
+    return(globus_gss_assist_gridmap(client->displayname.value, user) == 0);
+}
+
+/*
+ * 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);
+	}
+	client->store.envval = strdup(p);
+#ifdef USE_PAM
+	if (options.use_pam)
+	    do_pam_putenv(client->store.envvar, client->store.envval);
+#endif
+	if (strncmp(p, "FILE:", 5) == 0) {
+	    p += 5;
+	}
+	if (access(p, R_OK) == 0) {
+	    client->store.filename = strdup(p);
+	}
+	gss_release_buffer(&minor_status, &export_cred);
+}
+
+#endif /* GSI */
+#endif /* GSSAPI */
diff -Naur --exclude=autom4te.cache openssh-4.2p1/gss-serv-krb5.c openssh-4.2p1-gssapi/gss-serv-krb5.c
--- openssh-4.2p1/gss-serv-krb5.c	2005-07-07 05:33:36.000000000 -0500
+++ openssh-4.2p1-gssapi/gss-serv-krb5.c	2005-12-20 13:30:59.000000000 -0600
@@ -40,15 +40,29 @@
 
 #ifdef HEIMDAL
 # include <krb5.h>
-#else
-# ifdef HAVE_GSSAPI_KRB5
+#elsif !defined(MECHGLUE)
+# ifdef HAVE_GSSAPI_KRB5_H
 #  include <gssapi_krb5.h>
-# elif HAVE_GSSAPI_GSSAPI_KRB5
+# elif HAVE_GSSAPI_GSSAPI_KRB5_H
 #  include <gssapi/gssapi_krb5.h>
 # endif
 #endif
 
 static krb5_context krb_context = NULL;
+static int ssh_gssapi_krb5_init();
+static int ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name);
+static int ssh_gssapi_krb5_localname(ssh_gssapi_client *client, char **user);
+static void ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client);
+
+ssh_gssapi_mech gssapi_kerberos_mech = {
+	"toWM5Slw5Ew8Mqkay+al2g==",
+	"Kerberos",
+	{9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"},
+	NULL,
+	&ssh_gssapi_krb5_userok,
+	&ssh_gssapi_krb5_localname,
+	&ssh_gssapi_krb5_storecreds
+};
 
 /* Initialise the krb5 library, for the stuff that GSSAPI won't do */
 
@@ -101,6 +115,35 @@
 }
 
 
+/* Retrieve the local username associated with a set of Kerberos 
+ * credentials. Hopefully we can use this for the 'empty' username
+ * logins discussed in the draft  */
+static int
+ssh_gssapi_krb5_localname(ssh_gssapi_client *client, char **user) {
+	krb5_principal princ;
+	int retval;
+	
+	if (ssh_gssapi_krb5_init() == 0)
+		return 0;
+
+	if ((retval=krb5_parse_name(krb_context, client->displayname.value, 
+				    &princ))) {
+		logit("krb5_parse_name(): %.100s", 
+			krb5_get_err_text(krb_context,retval));
+		return 0;
+	}
+	
+	/* We've got to return a malloc'd string */
+	*user = (char *)xmalloc(256);
+	if (krb5_aname_to_localname(krb_context, princ, 256, *user)) {
+		xfree(*user);
+		*user = NULL;
+		return(0);
+	}
+	
+	return(1);
+}
+	
 /* This writes out any forwarded credentials from the structure populated
  * during userauth. Called after we have setuid to the user */
 
@@ -111,6 +154,7 @@
 	krb5_error_code problem;
 	krb5_principal princ;
 	OM_uint32 maj_status, min_status;
+	gss_cred_id_t krb5_cred_handle;
 	int len;
 
 	if (client->creds == NULL) {
@@ -153,8 +197,16 @@
 
 	krb5_free_principal(krb_context, princ);
 
-	if ((maj_status = gss_krb5_copy_ccache(&min_status,
-	    client->creds, ccache))) {
+#ifdef MECHGLUE
+	krb5_cred_handle =
+	    __gss_get_mechanism_cred(client->creds,
+				     &(gssapi_kerberos_mech.oid));
+#else
+	krb5_cred_handle = client->creds;
+#endif
+
+	if ((maj_status = gss_krb5_copy_ccache(&min_status, 
+	    krb5_cred_handle, ccache))) {
 		logit("gss_krb5_copy_ccache() failed");
 		krb5_cc_destroy(krb_context, ccache);
 		return;
@@ -176,16 +228,6 @@
 	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
-};
-
 #endif /* KRB5 */
 
 #endif /* GSSAPI */
diff -Naur --exclude=autom4te.cache openssh-4.2p1/gss-serv.c openssh-4.2p1-gssapi/gss-serv.c
--- openssh-4.2p1/gss-serv.c	2005-08-31 04:46:27.000000000 -0500
+++ openssh-4.2p1-gssapi/gss-serv.c	2005-12-20 13:30:59.000000000 -0600
@@ -28,8 +28,11 @@
 
 #ifdef GSSAPI
 
+#include "buffer.h"
 #include "bufaux.h"
 #include "compat.h"
+#include <openssl/evp.h>
+#include "kex.h"
 #include "auth.h"
 #include "log.h"
 #include "channels.h"
@@ -53,14 +56,46 @@
 #ifdef KRB5
 extern ssh_gssapi_mech gssapi_kerberos_mech;
 #endif
+#ifdef GSI
+extern ssh_gssapi_mech gssapi_gsi_mech;
+#endif
 
 ssh_gssapi_mech* supported_mechs[]= {
 #ifdef KRB5
 	&gssapi_kerberos_mech,
 #endif
+#ifdef GSI
+	&gssapi_gsi_mech,
+#endif
 	&gssapi_null_mech,
 };
 
+#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG
+static int limited = 0;
+#endif
+
+/* Unpriviledged */
+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));
+}
+
+/* Unpriviledged */
+int
+ssh_gssapi_server_check_mech(gss_OID oid, void *data) {
+        Gssctxt * ctx = NULL;
+	int res;
+
+	res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
+	ssh_gssapi_delete_ctx(&ctx);
+
+	return (res);
+}
+
 /* Unpriviledged */
 void
 ssh_gssapi_supported_oids(gss_OID_set *oidset)
@@ -71,7 +106,8 @@
 	gss_OID_set supported;
 
 	gss_create_empty_oid_set(&min_status, oidset);
-	gss_indicate_mechs(&min_status, &supported);
+	/* Ask priviledged process what mechanisms it supports. */
+	PRIVSEP(gss_indicate_mechs(&min_status, &supported));
 
 	while (supported_mechs[i]->name != NULL) {
 		if (GSS_ERROR(gss_test_oid_set_member(&min_status,
@@ -121,6 +157,10 @@
 	    (*flags & GSS_C_INTEG_FLAG))) && (ctx->major == GSS_S_COMPLETE)) {
 		if (ssh_gssapi_getclient(ctx, &gssapi_client))
 			fatal("Couldn't convert client name");
+#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG
+		if (flags && (*flags & GSS_C_GLOBUS_LIMITED_PROXY_FLAG))
+			limited=1;
+#endif
 	}
 
 	return (status);
@@ -140,6 +180,17 @@
 
 	tok=ename->value;
 
+#ifdef GSI /* GSI gss_export_name() is broken. */
+	if ((ctx->oid->length == gssapi_gsi_mech.oid.length) &&
+	    (memcmp(ctx->oid->elements, gssapi_gsi_mech.oid.elements,
+		    gssapi_gsi_mech.oid.length) == 0)) {
+	    name->length = ename->length;
+	    name->value = xmalloc(ename->length+1);
+	    memcpy(name->value, ename->value, ename->length);
+	    return GSS_S_COMPLETE;
+	}
+#endif
+
 	/*
 	 * Check that ename is long enough for all of the fixed length
 	 * header, and that the initial ID bytes are correct
@@ -282,6 +333,12 @@
 		debug("No suitable client data");
 		return 0;
 	}
+#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG
+	if (limited) {
+		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))
 			return 1;
@@ -299,13 +356,21 @@
 }
 
 /* Priviledged */
-OM_uint32
-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
+int
+ssh_gssapi_localname(char **user)
 {
-	ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
-	    gssbuf, gssmic, NULL);
-
-	return (ctx->major);
+    	*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);
 }
 
 #endif
diff -Naur --exclude=autom4te.cache openssh-4.2p1/kex.c openssh-4.2p1-gssapi/kex.c
--- openssh-4.2p1/kex.c	2005-07-26 06:54:56.000000000 -0500
+++ openssh-4.2p1-gssapi/kex.c	2005-12-20 13:30:59.000000000 -0600
@@ -42,6 +42,10 @@
 #include "dispatch.h"
 #include "monitor.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 #define KEX_COOKIE_LEN	16
 
 /* prototype */
@@ -49,7 +53,7 @@
 static void kex_choose_conf(Kex *);
 
 /* put algorithm proposal into buffer */
-static void
+void
 kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
 {
 	u_int i;
@@ -298,6 +302,14 @@
 		k->kex_type = KEX_DH_GRP14_SHA1;
 	} else if (strcmp(k->name, KEX_DHGEX) == 0) {
 		k->kex_type = KEX_DH_GEX_SHA1;
+#ifdef GSSAPI
+	} else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID,
+	    sizeof(KEX_GSS_GEX_SHA1_ID)-1) == 0) {
+		k->kex_type = KEX_GSS_GEX_SHA1;
+	} else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID, 
+	    sizeof(KEX_GSS_GRP1_SHA1_ID)-1) == 0) {
+		k->kex_type = KEX_GSS_GRP1_SHA1;
+#endif
 	} else
 		fatal("bad kex alg %s", k->name);
 }
diff -Naur --exclude=autom4te.cache openssh-4.2p1/kex.h openssh-4.2p1-gssapi/kex.h
--- openssh-4.2p1/kex.h	2005-07-26 06:54:56.000000000 -0500
+++ openssh-4.2p1-gssapi/kex.h	2005-12-20 13:30:59.000000000 -0600
@@ -63,6 +63,8 @@
 	KEX_DH_GRP1_SHA1,
 	KEX_DH_GRP14_SHA1,
 	KEX_DH_GEX_SHA1,
+	KEX_GSS_GRP1_SHA1,
+	KEX_GSS_GEX_SHA1,
 	KEX_MAX
 };
 
@@ -101,6 +103,11 @@
 	Mac	mac;
 	Comp	comp;
 };
+
+struct KexOptions {
+	int	gss_deleg_creds;
+};
+
 struct Kex {
 	u_char	*session_id;
 	u_int	session_id_len;
@@ -114,14 +121,22 @@
 	Buffer	peer;
 	int	done;
 	int	flags;
+#ifdef GSSAPI
+	int 	gss_deleg_creds;
+	int	gss_trust_dns;
+	char    *gss_host;
+#endif
 	char	*client_version_string;
 	char	*server_version_string;
+	struct  KexOptions options;
 	int	(*verify_host_key)(Key *);
 	Key	*(*load_host_key)(int);
 	int	(*host_key_index)(Key *);
 	void	(*kex[KEX_MAX])(Kex *);
 };
 
+void kex_prop2buf(Buffer *, char *proposal[PROPOSAL_MAX]);
+
 Kex	*kex_setup(char *[PROPOSAL_MAX]);
 void	 kex_finish(Kex *);
 
@@ -136,6 +151,11 @@
 void	 kexgex_client(Kex *);
 void	 kexgex_server(Kex *);
 
+#ifdef GSSAPI
+void	kexgss_client(Kex *);
+void	kexgss_server(Kex *);
+#endif
+
 u_char *
 kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
     BIGNUM *, BIGNUM *, BIGNUM *);
diff -Naur --exclude=autom4te.cache openssh-4.2p1/kexgssc.c openssh-4.2p1-gssapi/kexgssc.c
--- openssh-4.2p1/kexgssc.c	1969-12-31 18:00:00.000000000 -0600
+++ openssh-4.2p1-gssapi/kexgssc.c	2005-12-20 13:30:59.000000000 -0600
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2001-2005 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
+
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+
+#include "xmalloc.h"
+#include "buffer.h"
+#include "bufaux.h"
+#include "kex.h"
+#include "log.h"
+#include "packet.h"
+#include "dh.h"
+#include "canohost.h"
+#include "ssh2.h"
+#include "ssh-gss.h"
+
+void
+kexgss_client(Kex *kex) {
+	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
+        gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr;
+	Gssctxt *ctxt;
+	OM_uint32 maj_status, min_status, ret_flags;
+	unsigned int klen, kout;
+	DH *dh; 
+	BIGNUM *dh_server_pub = NULL;
+	BIGNUM *shared_secret = NULL;
+	BIGNUM *p = NULL;
+	BIGNUM *g = NULL;	
+	unsigned char *kbuf;
+	unsigned char *hash;
+	unsigned char *serverhostkey = NULL;
+	char *msg;
+	char *lang;
+	int type = 0;
+	int first = 1;
+	unsigned int slen = 0;
+	int gex = 0;
+	int nbits = -1, min = -1, max = -1;
+	u_int strlen;
+
+	/* Initialise our GSSAPI world */	
+	ssh_gssapi_build_ctx(&ctxt);
+	if (ssh_gssapi_id_kex(ctxt, kex->name, &gex) == NULL)
+		fatal("Couldn't identify host exchange");
+
+	if (ssh_gssapi_import_name(ctxt, kex->gss_host))
+		fatal("Couldn't import hostname");
+	
+	if (gex) {
+		debug("Doing group exchange\n");
+		nbits = dh_estimate(kex->we_need * 8);
+		min = DH_GRP_MIN;
+		max = DH_GRP_MAX;
+		packet_start(SSH2_MSG_KEXGSS_GROUPREQ);
+		packet_put_int(min);
+		packet_put_int(nbits);
+		packet_put_int(max);
+
+		packet_send();
+
+		packet_read_expect(SSH2_MSG_KEXGSS_GROUP);
+
+		if ((p = BN_new()) == NULL)
+			fatal("BN_new() failed");
+		packet_get_bignum2(p);
+		if ((g = BN_new()) == NULL)
+			fatal("BN_new() failed");
+		packet_get_bignum2(g);
+		packet_check_eom();
+
+		if (BN_num_bits(p) < min || BN_num_bits(p) > max)
+			fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
+			    min, BN_num_bits(p), max);
+
+		dh = dh_new_group(g, p);
+	} else {
+		dh = dh_new_group1();
+	}
+	
+	/* Step 1 - e is dh->pub_key */
+	dh_gen_key(dh, kex->we_need * 8);
+
+	/* This is f, we initialise it now to make life easier */
+	dh_server_pub = BN_new();
+	if (dh_server_pub == NULL)
+		fatal("dh_server_pub == NULL");
+
+	token_ptr = GSS_C_NO_BUFFER;
+			 
+	do {
+		debug("Calling gss_init_sec_context");
+		
+		maj_status = ssh_gssapi_init_ctx(ctxt,
+		    kex->gss_deleg_creds, token_ptr, &send_tok,
+		    &ret_flags);
+
+		if (GSS_ERROR(maj_status)) {
+			if (send_tok.length != 0) {
+				packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+				packet_put_string(send_tok.value,
+				    send_tok.length);
+			}
+			fatal("gss_init_context failed");
+		}
+
+		/* If we've got an old receive buffer get rid of it */
+		if (token_ptr != GSS_C_NO_BUFFER)
+			xfree(recv_tok.value);
+
+		if (maj_status == GSS_S_COMPLETE) {
+			/* If mutual state flag is not true, kex fails */
+			if (!(ret_flags & GSS_C_MUTUAL_FLAG))
+				fatal("Mutual authentication failed");
+
+			/* If integ avail flag is not true kex fails */
+			if (!(ret_flags & GSS_C_INTEG_FLAG))
+				fatal("Integrity check failed");
+		}
+
+		/* 
+		 * If we have data to send, then the last message that we
+		 * received cannot have been a 'complete'. 
+		 */
+		if (send_tok.length != 0) {
+			if (first) {
+				packet_start(SSH2_MSG_KEXGSS_INIT);
+				packet_put_string(send_tok.value,
+				    send_tok.length);
+				packet_put_bignum2(dh->pub_key);
+				first = 0;
+			} else {
+				packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+				packet_put_string(send_tok.value,
+				    send_tok.length);
+			}
+			packet_send();
+			gss_release_buffer(&min_status, &send_tok);
+
+			/* If we've sent them data, they should reply */
+			do {	
+				type = packet_read();
+				if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
+					debug("Received KEXGSS_HOSTKEY");
+					if (serverhostkey)
+						fatal("Server host key received more than once");
+					serverhostkey = 
+					    packet_get_string(&slen);
+				}
+			} while (type == SSH2_MSG_KEXGSS_HOSTKEY);
+
+			switch (type) {
+			case SSH2_MSG_KEXGSS_CONTINUE:
+				debug("Received GSSAPI_CONTINUE");
+				if (maj_status == GSS_S_COMPLETE) 
+					fatal("GSSAPI Continue received from server when complete");
+				recv_tok.value = packet_get_string(&strlen);
+				recv_tok.length = strlen; 
+				break;
+			case SSH2_MSG_KEXGSS_COMPLETE:
+				debug("Received GSSAPI_COMPLETE");
+				packet_get_bignum2(dh_server_pub);
+				msg_tok.value =  packet_get_string(&strlen);
+				msg_tok.length = strlen; 
+
+				/* Is there a token included? */
+				if (packet_get_char()) {
+					recv_tok.value=
+					    packet_get_string(&strlen);
+					recv_tok.length = strlen;
+					/* If we're already complete - protocol error */
+					if (maj_status == GSS_S_COMPLETE)
+						packet_disconnect("Protocol error: received token when complete");
+					} else {
+						/* No token included */
+						if (maj_status != GSS_S_COMPLETE)
+							packet_disconnect("Protocol error: did not receive final token");
+				}
+				break;
+			case SSH2_MSG_KEXGSS_ERROR:
+				debug("Received Error");
+				maj_status = packet_get_int();
+				min_status = packet_get_int();
+				msg = packet_get_string(NULL);
+				lang = packet_get_string(NULL);
+				fatal("GSSAPI Key Exchange Error: \n%s",msg);
+			default:
+				packet_disconnect("Protocol error: didn't expect packet type %d",
+		    		type);
+			}
+			token_ptr = &recv_tok;
+		} else {
+			/* No data, and not complete */
+			if (maj_status != GSS_S_COMPLETE)
+				fatal("Not complete, and no token output");
+		}
+	} while (maj_status & GSS_S_CONTINUE_NEEDED);
+
+	/* 
+	 * We _must_ have received a COMPLETE message in reply from the 
+	 * server, which will have set dh_server_pub and msg_tok 
+	 */
+
+	if (type != SSH2_MSG_KEXGSS_COMPLETE)
+		fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
+
+	/* Check f in range [1, p-1] */
+	if (!dh_pub_is_valid(dh, dh_server_pub))
+		packet_disconnect("bad server public DH value");
+
+	/* compute K=f^x mod p */
+	klen = DH_size(dh);
+	kbuf = xmalloc(klen);
+	kout = DH_compute_key(kbuf, dh_server_pub, dh);
+
+	shared_secret = BN_new();
+	BN_bin2bn(kbuf,kout, shared_secret);
+	memset(kbuf, 0, klen);
+	xfree(kbuf);
+
+	if (gex) {
+		hash = kexgex_hash( kex->client_version_string,
+		    kex->server_version_string,
+		    buffer_ptr(&kex->my), buffer_len(&kex->my),
+		    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
+		    serverhostkey, slen,
+ 		    min, nbits, max,
+		    dh->p, dh->g,
+		    dh->pub_key,
+		    dh_server_pub,
+		    shared_secret
+		);
+	} else {
+		/* The GSS hash is identical to the DH one */
+		hash = kex_dh_hash( kex->client_version_string, 
+		    kex->server_version_string,
+		    buffer_ptr(&kex->my), buffer_len(&kex->my),
+		    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
+		    serverhostkey, slen, /* server host key */
+		    dh->pub_key,	/* e */
+		    dh_server_pub,	/* f */
+		    shared_secret	/* K */
+		);
+        }
+
+	gssbuf.value = hash;
+	gssbuf.length = 20;
+
+        /* Verify that the hash matches the MIC we just got. */
+	if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
+		packet_disconnect("Hash's MIC didn't verify");
+
+	xfree(msg_tok.value);
+
+	DH_free(dh);
+	if (serverhostkey)
+		xfree(serverhostkey);
+	BN_clear_free(dh_server_pub);
+
+	/* save session id */
+	if (kex->session_id == NULL) {
+		kex->session_id_len = 20;
+		kex->session_id = xmalloc(kex->session_id_len);
+		memcpy(kex->session_id, hash, kex->session_id_len);
+	}
+
+	if (gss_kex_context == NULL)
+		gss_kex_context = ctxt;
+	else
+		ssh_gssapi_delete_ctx(&ctxt);
+
+	kex_derive_keys(kex, hash, shared_secret);
+	BN_clear_free(shared_secret);
+	kex_finish(kex);
+}
+
+#endif /* GSSAPI */
diff -Naur --exclude=autom4te.cache openssh-4.2p1/kexgsss.c openssh-4.2p1-gssapi/kexgsss.c
--- openssh-4.2p1/kexgsss.c	1969-12-31 18:00:00.000000000 -0600
+++ openssh-4.2p1-gssapi/kexgsss.c	2005-12-20 13:30:59.000000000 -0600
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2001-2005 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
+
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+
+#include "xmalloc.h"
+#include "buffer.h"
+#include "bufaux.h"
+#include "kex.h"
+#include "log.h"
+#include "packet.h"
+#include "dh.h"
+#include "ssh2.h"
+#include "ssh-gss.h"
+#include "monitor_wrap.h"
+
+static void kex_gss_send_error(Gssctxt *ctxt);
+
+void
+kexgss_server(Kex *kex)
+{
+	OM_uint32 maj_status, min_status;
+	
+	/* 
+	 * Some GSSAPI implementations use the input value of ret_flags (an
+ 	 * output variable) as a means of triggering mechanism specific 
+ 	 * features. Initializing it to zero avoids inadvertently 
+ 	 * activating this non-standard behaviour.
+	 */
+
+	OM_uint32 ret_flags = 0;
+	gss_buffer_desc gssbuf, recv_tok, msg_tok;
+	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
+	Gssctxt *ctxt = NULL;
+	unsigned int klen, kout;
+	unsigned char *kbuf, *hash;
+	DH *dh;
+	int min = -1, max = -1, nbits = -1;
+	BIGNUM *shared_secret = NULL;
+	BIGNUM *dh_client_pub = NULL;
+	int type = 0;
+	int gex;
+	u_int slen;
+	gss_OID oid;
+	
+	/* Initialise GSSAPI */
+
+	/* If we're rekeying, privsep means that some of the private structures
+	 * in the GSSAPI code are no longer available. This kludges them back
+         * into life
+	 */
+	if (!ssh_gssapi_oid_table_ok()) 
+		ssh_gssapi_server_mechanisms();
+
+	debug2("%s: Identifying %s", __func__, kex->name);
+	oid = ssh_gssapi_id_kex(NULL, kex->name, &gex);
+	if (oid == NULL)
+	   fatal("Unknown gssapi mechanism");
+
+	debug2("%s: Acquiring credentials", __func__);
+
+	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) {
+		kex_gss_send_error(ctxt);
+        	fatal("Unable to acquire credentials for the server");
+	}
+
+	if (gex) {
+		debug("Doing group exchange");
+		packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);
+		min = packet_get_int();
+		nbits = packet_get_int();
+		max = packet_get_int();
+		min = MAX(DH_GRP_MIN, min);
+		max = MIN(DH_GRP_MAX, max);
+		packet_check_eom();
+		if (max < min || nbits < min || max < nbits)
+			fatal("GSS_GEX, bad parameters: %d !< %d !< %d",
+			    min, nbits, max);
+		dh = PRIVSEP(choose_dh(min, nbits, max));
+		if (dh == NULL)
+			packet_disconnect("Protocol error: no matching group found");
+
+		packet_start(SSH2_MSG_KEXGSS_GROUP);
+		packet_put_bignum2(dh->p);
+		packet_put_bignum2(dh->g);
+		packet_send();
+
+		packet_write_wait();
+		
+	} else {
+        	dh = dh_new_group1();
+	}
+	dh_gen_key(dh, kex->we_need * 8);
+
+	do {
+		debug("Wait SSH2_MSG_GSSAPI_INIT");
+		type = packet_read();
+		switch(type) {
+		case SSH2_MSG_KEXGSS_INIT:
+			if (dh_client_pub != NULL) 
+				fatal("Received KEXGSS_INIT after initialising");
+			recv_tok.value = packet_get_string(&slen);
+			recv_tok.length = slen; 
+
+			if ((dh_client_pub = BN_new()) == NULL)
+				fatal("dh_client_pub == NULL");
+
+			packet_get_bignum2(dh_client_pub);
+
+			/* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
+			break;
+		case SSH2_MSG_KEXGSS_CONTINUE:
+			recv_tok.value = packet_get_string(&slen);
+			recv_tok.length = slen; 
+			break;
+		default:
+			packet_disconnect(
+			    "Protocol error: didn't expect packet type %d",
+			    type);
+		}
+
+		maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, 
+		    &send_tok, &ret_flags));
+
+		xfree(recv_tok.value);
+
+		if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
+			fatal("Zero length token output when incomplete");
+
+		if (dh_client_pub == NULL)
+			fatal("No client public key");
+		
+		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_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_send();
+		}
+		packet_disconnect("GSSAPI Key Exchange handshake failed");
+	}
+
+	if (!(ret_flags & GSS_C_MUTUAL_FLAG))
+		fatal("Mutual Authentication flag wasn't set");
+
+	if (!(ret_flags & GSS_C_INTEG_FLAG))
+		fatal("Integrity flag wasn't set");
+	
+	if (!dh_pub_is_valid(dh, dh_client_pub))
+		packet_disconnect("bad client public DH value");
+
+	klen = DH_size(dh);
+	kbuf = xmalloc(klen); 
+	kout = DH_compute_key(kbuf, dh_client_pub, dh);
+
+	shared_secret = BN_new();
+	BN_bin2bn(kbuf, kout, shared_secret);
+	memset(kbuf, 0, klen);
+	xfree(kbuf);
+
+	if (gex) {
+		hash = kexgex_hash(
+		    kex->client_version_string, kex->server_version_string,
+		    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
+		    buffer_ptr(&kex->my), buffer_len(&kex->my),
+		    NULL, 0,
+		    min, nbits, max,
+		    dh->p, dh->g,
+		    dh_client_pub,
+		    dh->pub_key,
+		    shared_secret
+		);
+	}
+	else {	
+		/* The GSSAPI hash is identical to the Diffie Helman one */
+		hash = kex_dh_hash(
+		    kex->client_version_string, kex->server_version_string,
+		    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
+		    buffer_ptr(&kex->my), buffer_len(&kex->my),
+		    NULL, 0, /* Change this if we start sending host keys */
+		    dh_client_pub, dh->pub_key, shared_secret
+		);
+	}
+	BN_free(dh_client_pub);
+
+	if (kex->session_id == NULL) {
+		kex->session_id_len = 20;
+		kex->session_id = xmalloc(kex->session_id_len);
+		memcpy(kex->session_id, hash, kex->session_id_len);
+	}
+
+	gssbuf.value = hash;
+	gssbuf.length = 20; /* Hashlen appears to always be 20 */
+
+	if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))
+		fatal("Couldn't get MIC");
+
+	packet_start(SSH2_MSG_KEXGSS_COMPLETE);
+	packet_put_bignum2(dh->pub_key);
+	packet_put_string((char *)msg_tok.value,msg_tok.length);
+
+	if (send_tok.length != 0) {
+		packet_put_char(1); /* true */
+		packet_put_string((char *)send_tok.value, send_tok.length);
+	} else {
+		packet_put_char(0); /* false */
+	}
+	packet_send();
+
+	gss_release_buffer(&min_status, &send_tok);
+	gss_release_buffer(&min_status, &msg_tok);
+
+	if (gss_kex_context == NULL)
+		gss_kex_context = ctxt;
+	else 
+		ssh_gssapi_delete_ctx(&ctxt);
+
+	DH_free(dh);
+
+	kex_derive_keys(kex, hash, shared_secret);
+	BN_clear_free(shared_secret);
+	kex_finish(kex);
+}
+
+static void 
+kex_gss_send_error(Gssctxt *ctxt) {
+	char *errstr;
+	OM_uint32 maj,min;
+		
+	errstr=PRIVSEP(ssh_gssapi_last_error(ctxt,&maj,&min));
+	if (errstr) {
+		packet_start(SSH2_MSG_KEXGSS_ERROR);
+		packet_put_int(maj);
+		packet_put_int(min);
+		packet_put_cstring(errstr);
+		packet_put_cstring("");
+		packet_send();
+		packet_write_wait();
+		/* XXX - We should probably log the error locally here */
+		xfree(errstr);
+	}
+}
+#endif /* GSSAPI */
diff -Naur --exclude=autom4te.cache openssh-4.2p1/key.c openssh-4.2p1-gssapi/key.c
--- openssh-4.2p1/key.c	2005-06-16 21:59:35.000000000 -0500
+++ openssh-4.2p1-gssapi/key.c	2005-12-20 13:30:59.000000000 -0600
@@ -650,6 +650,8 @@
 		return KEY_RSA;
 	} else if (strcmp(name, "ssh-dss") == 0) {
 		return KEY_DSA;
+	} else if (strcmp(name, "null") == 0) {
+		return KEY_NULL;
 	}
 	debug2("key_type_from_name: unknown key type '%s'", name);
 	return KEY_UNSPEC;
diff -Naur --exclude=autom4te.cache openssh-4.2p1/key.h openssh-4.2p1-gssapi/key.h
--- openssh-4.2p1/key.h	2003-11-17 04:18:23.000000000 -0600
+++ openssh-4.2p1-gssapi/key.h	2005-12-20 13:30:59.000000000 -0600
@@ -34,6 +34,7 @@
 	KEY_RSA1,
 	KEY_RSA,
 	KEY_DSA,
+	KEY_NULL,
 	KEY_UNSPEC
 };
 enum fp_type {
diff -Naur --exclude=autom4te.cache openssh-4.2p1/misc.c openssh-4.2p1-gssapi/misc.c
--- openssh-4.2p1/misc.c	2005-07-14 02:05:02.000000000 -0500
+++ openssh-4.2p1-gssapi/misc.c	2005-12-20 13:30:59.000000000 -0600
@@ -120,11 +120,14 @@
 /* Characters considered whitespace in strsep calls. */
 #define WHITESPACE " \t\r\n"
 
+/* Characters considered as quotations. */
+#define QUOTES "'\""
+
 /* return next token in configuration line */
 char *
 strdelim(char **s)
 {
-	char *old;
+	char *old, *p, *q;
 	int wspace = 0;
 
 	if (*s == NULL)
@@ -132,7 +135,22 @@
 
 	old = *s;
 
-	*s = strpbrk(*s, WHITESPACE "=");
+        if ((q=strchr(QUOTES, (int) *old)) && *q)
+        {
+            /* find next quote character, point old to start of quoted
+             * string */
+            for (p = ++old;*p && *p!=*q; p++)
+                 ;
+            
+            /* find start of next token */
+            *s = (*p) ? p + strspn(p + 1, WHITESPACE) + 1 : NULL;
+            
+            /* terminate 'old' token */
+            *p = '\0';
+            return (old);
+        }
+
+        *s = strpbrk(*s, WHITESPACE "=");
 	if (*s == NULL)
 		return (old);
 
diff -Naur --exclude=autom4te.cache openssh-4.2p1/monitor.c openssh-4.2p1-gssapi/monitor.c
--- openssh-4.2p1/monitor.c	2005-07-17 02:53:31.000000000 -0500
+++ openssh-4.2p1-gssapi/monitor.c	2005-12-20 13:30:59.000000000 -0600
@@ -141,6 +141,10 @@
 int mm_answer_gss_accept_ctx(int, Buffer *);
 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 *);
 #endif
 
 #ifdef SSH_AUDIT_EVENTS
@@ -179,12 +183,12 @@
 struct mon_table mon_dispatch_proto20[] = {
     {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
-    {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
+    {MONITOR_REQ_PWNAM, MON_AUTH, mm_answer_pwnamallow},
     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
     {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
     {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
 #ifdef USE_PAM
-    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
+    {MONITOR_REQ_PAM_START, MON_ISAUTH, mm_answer_pam_start},
     {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
     {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
     {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
@@ -209,11 +213,22 @@
     {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
     {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
     {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
+    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
+    {MONITOR_REQ_GSSERR, MON_ISAUTH | MON_ONCE, mm_answer_gss_error},
+    {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs},
+    {MONITOR_REQ_GSSLOCALNAME, MON_ISAUTH, mm_answer_gss_localname},
 #endif
     {0, 0, NULL}
 };
 
 struct mon_table mon_dispatch_postauth20[] = {
+#ifdef GSSAPI
+    {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},
+#endif
     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
     {MONITOR_REQ_SIGN, 0, mm_answer_sign},
     {MONITOR_REQ_PTY, 0, mm_answer_pty},
@@ -243,8 +258,15 @@
     {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
     {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
 #endif
+#ifdef GSSAPI
+    {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
+    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
+    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
+    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
+    {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs},
+#endif
 #ifdef USE_PAM
-    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
+    {MONITOR_REQ_PAM_START, MON_ISAUTH, mm_answer_pam_start},
     {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
     {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
     {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
@@ -318,6 +340,12 @@
 		/* Permit requests for moduli and signatures */
 		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
+#ifdef GSSAPI		
+		/* and for the GSSAPI key exchange */
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR, 1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS, 1);
+#endif
 	} else {
 		mon_dispatch = mon_dispatch_proto15;
 
@@ -391,10 +419,21 @@
 		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+
+#ifdef GSSAPI
+		/* and for the GSSAPI key exchange */
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS,1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP,1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR,1);
+#endif
+
 	} else {
 		mon_dispatch = mon_dispatch_postauth15;
 		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
 	}
+#ifdef GSSAPI		
+	monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR, 1);
+#endif
 	if (!no_pty_flag) {
 		monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
@@ -579,13 +618,11 @@
 
 	debug3("%s", __func__);
 
-	if (authctxt->attempt++ != 0)
-		fatal("%s: multiple attempts for getpwnam", __func__);
-
 	username = buffer_get_string(m, NULL);
 
 	pwent = getpwnamallow(username);
 
+	if (authctxt->user) xfree(authctxt->user);
 	authctxt->user = xstrdup(username);
 	setproctitle("%s [priv]", pwent ? username : "unknown");
 	xfree(username);
@@ -1623,6 +1660,10 @@
 	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
 	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
 	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+#ifdef GSSAPI
+	kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+	kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+#endif
 	kex->server = 1;
 	kex->hostkey_type = buffer_get_int(m);
 	kex->kex_type = buffer_get_int(m);
@@ -1864,7 +1905,9 @@
 	if (major==GSS_S_COMPLETE) {
 		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
 		monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
 	}
 	return (0);
 }
@@ -1915,4 +1958,106 @@
 	/* Monitor loop will terminate if authenticated */
 	return (authenticated);
 }
+
+int 
+mm_answer_gss_sign(int socket, Buffer *m)
+{
+	gss_buffer_desc data;
+	gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
+	OM_uint32 major, minor;
+	u_int len;
+
+	data.value = buffer_get_string(m, &len);
+	data.length = len;
+	if (data.length != 20) 
+		fatal("%s: data length incorrect: %d", __func__, 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);
+}
+
 #endif /* GSSAPI */
diff -Naur --exclude=autom4te.cache openssh-4.2p1/monitor.h openssh-4.2p1-gssapi/monitor.h
--- openssh-4.2p1/monitor.h	2005-02-02 07:20:53.000000000 -0600
+++ openssh-4.2p1-gssapi/monitor.h	2005-12-20 13:30:59.000000000 -0600
@@ -52,7 +52,11 @@
 	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_PAM_START,
 	MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
 	MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
diff -Naur --exclude=autom4te.cache openssh-4.2p1/monitor_wrap.c openssh-4.2p1-gssapi/monitor_wrap.c
--- openssh-4.2p1/monitor_wrap.c	2005-07-17 02:53:31.000000000 -0500
+++ openssh-4.2p1-gssapi/monitor_wrap.c	2005-12-20 13:30:59.000000000 -0600
@@ -1216,4 +1216,104 @@
 	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
 	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);
+}	
+
 #endif /* GSSAPI */
diff -Naur --exclude=autom4te.cache openssh-4.2p1/monitor_wrap.h openssh-4.2p1-gssapi/monitor_wrap.h
--- openssh-4.2p1/monitor_wrap.h	2005-02-08 04:52:48.000000000 -0600
+++ openssh-4.2p1-gssapi/monitor_wrap.h	2005-12-20 13:30:59.000000000 -0600
@@ -63,6 +63,11 @@
    gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
 int mm_ssh_gssapi_userok(char *user);
 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);
 #endif
 
 #ifdef USE_PAM
diff -Naur --exclude=autom4te.cache openssh-4.2p1/myproposal.h openssh-4.2p1-gssapi/myproposal.h
--- openssh-4.2p1/myproposal.h	2005-07-26 06:54:56.000000000 -0500
+++ openssh-4.2p1-gssapi/myproposal.h	2005-12-20 13:30:59.000000000 -0600
@@ -31,7 +31,7 @@
 	"aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \
 	"arcfour128,arcfour256,arcfour," \
 	"aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se," \
-	"aes128-ctr,aes192-ctr,aes256-ctr"
+	"aes128-ctr,aes192-ctr,aes256-ctr,none"
 #define	KEX_DEFAULT_MAC \
 	"hmac-md5,hmac-sha1,hmac-ripemd160," \
 	"hmac-ripemd160@openssh.com," \
diff -Naur --exclude=autom4te.cache openssh-4.2p1/openbsd-compat/port-aix.h openssh-4.2p1-gssapi/openbsd-compat/port-aix.h
--- openssh-4.2p1/openbsd-compat/port-aix.h	2005-05-28 05:28:40.000000000 -0500
+++ openssh-4.2p1-gssapi/openbsd-compat/port-aix.h	2005-12-20 13:31:00.000000000 -0600
@@ -39,6 +39,7 @@
 # include <login.h>
 # include <userpw.h>
 # if defined(HAVE_SYS_AUDIT_H) && defined(AIX_LOGINFAILED_4ARG)
+#  undef T_NULL
 #  include <sys/audit.h>
 # endif
 # include <usersec.h>
diff -Naur --exclude=autom4te.cache openssh-4.2p1/packet.c openssh-4.2p1-gssapi/packet.c
--- openssh-4.2p1/packet.c	2005-08-12 07:10:29.000000000 -0500
+++ openssh-4.2p1-gssapi/packet.c	2005-12-20 13:31:00.000000000 -0600
@@ -1546,6 +1546,13 @@
 		rnd >>= 8;
 	}
 }
+int rekey_requested = 0;
+
+void
+packet_request_rekeying(void)
+{
+	rekey_requested = 1;
+}
 
 #define MAX_PACKETS	(1U<<31)
 int
@@ -1553,6 +1560,11 @@
 {
 	if (datafellows & SSH_BUG_NOREKEY)
 		return 0;
+	if (rekey_requested == 1)
+	{
+		rekey_requested = 0;
+		return 1;
+	}
 	return
 	    (p_send.packets > MAX_PACKETS) ||
 	    (p_read.packets > MAX_PACKETS) ||
diff -Naur --exclude=autom4te.cache openssh-4.2p1/packet.h openssh-4.2p1-gssapi/packet.h
--- openssh-4.2p1/packet.h	2005-07-26 06:54:56.000000000 -0500
+++ openssh-4.2p1-gssapi/packet.h	2005-12-20 13:31:00.000000000 -0600
@@ -18,6 +18,9 @@
 
 #include <openssl/bn.h>
 
+void
+packet_request_rekeying(void);
+
 void     packet_set_connection(int, int);
 void     packet_set_nonblocking(void);
 int      packet_get_connection_in(void);
diff -Naur --exclude=autom4te.cache openssh-4.2p1/readconf.c openssh-4.2p1-gssapi/readconf.c
--- openssh-4.2p1/readconf.c	2005-08-12 07:11:18.000000000 -0500
+++ openssh-4.2p1-gssapi/readconf.c	2005-12-20 13:31:00.000000000 -0600
@@ -104,7 +104,8 @@
 	oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
-	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+	oAddressFamily, oGssAuthentication, oGssKeyEx, oGssDelegateCreds,
+	oGssTrustDns,
 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
 	oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
 	oDeprecated, oUnsupported
@@ -139,10 +140,14 @@
 	{ "afstokenpassing", oUnsupported },
 #if defined(GSSAPI)
 	{ "gssapiauthentication", oGssAuthentication },
+	{ "gssapikeyexchange", oGssKeyEx },
 	{ "gssapidelegatecredentials", oGssDelegateCreds },
+	{ "gssapitrustdns", oGssTrustDns },
 #else
 	{ "gssapiauthentication", oUnsupported },
+	{ "gssapikeyexchange", oUnsupported },
 	{ "gssapidelegatecredentials", oUnsupported },
+	{ "gssapitrustdns", oUnsupported },
 #endif
 	{ "fallbacktorsh", oDeprecated },
 	{ "usersh", oDeprecated },
@@ -406,10 +411,18 @@
 		intptr = &options->gss_authentication;
 		goto parse_flag;
 
+	case oGssKeyEx:
+	    	intptr = &options->gss_keyex;
+		goto parse_flag;
+
 	case oGssDelegateCreds:
 		intptr = &options->gss_deleg_creds;
 		goto parse_flag;
 
+	case oGssTrustDns:
+		intptr = &options->gss_trust_dns;
+		goto parse_flag;
+
 	case oBatchMode:
 		intptr = &options->batch_mode;
 		goto parse_flag;
@@ -916,7 +929,9 @@
 	options->pubkey_authentication = -1;
 	options->challenge_response_authentication = -1;
 	options->gss_authentication = -1;
+	options->gss_keyex = -1;
 	options->gss_deleg_creds = -1;
+	options->gss_trust_dns = -1;
 	options->password_authentication = -1;
 	options->kbd_interactive_authentication = -1;
 	options->kbd_interactive_devices = NULL;
@@ -962,6 +977,7 @@
 	options->verify_host_key_dns = -1;
 	options->server_alive_interval = -1;
 	options->server_alive_count_max = -1;
+	options->none_switch = -1;
 	options->num_send_env = 0;
 	options->control_path = NULL;
 	options->control_master = -1;
@@ -997,9 +1013,13 @@
 	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 = 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 = 1;
 	if (options->password_authentication == -1)
 		options->password_authentication = 1;
 	if (options->kbd_interactive_authentication == -1)
@@ -1086,6 +1106,8 @@
 		options->server_alive_interval = 0;
 	if (options->server_alive_count_max == -1)
 		options->server_alive_count_max = 3;
+	if (options->none_switch == -1)
+	        options->none_switch = 0;
 	if (options->control_master == -1)
 		options->control_master = 0;
 	if (options->hash_known_hosts == -1)
diff -Naur --exclude=autom4te.cache openssh-4.2p1/readconf.h openssh-4.2p1-gssapi/readconf.h
--- openssh-4.2p1/readconf.h	2005-06-15 22:19:42.000000000 -0500
+++ openssh-4.2p1-gssapi/readconf.h	2005-12-20 13:31:00.000000000 -0600
@@ -45,7 +45,9 @@
 	int     challenge_response_authentication;
 					/* Try S/Key or TIS, authentication. */
 	int     gss_authentication;	/* Try GSS authentication */
+	int	gss_keyex;
 	int     gss_deleg_creds;	/* Delegate GSS credentials */
+	int	gss_trust_dns;		/* Trust DNS for GSS canonicalization */
 	int     password_authentication;	/* Try password
 						 * authentication. */
 	int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
@@ -57,6 +59,7 @@
 	int     compression_level;	/* Compression level 1 (fast) to 9
 					 * (best). */
 	int     tcp_keep_alive;	/* Set SO_KEEPALIVE. */
+        int     tcp_rcv_buf; /* user switch to set tcp recv buffer */
 	LogLevel log_level;	/* Level for logging. */
 
 	int     port;		/* Port to connect. */
@@ -76,6 +79,8 @@
 	char   *host_key_alias;	/* hostname alias for .ssh/known_hosts */
 	char   *proxy_command;	/* Proxy command for connecting the host. */
 	char   *user;		/* User to log in as. */
+	int    implicit;	/* Login user was not specified.
+				   Server may choose based on authctxt. */
 	int     escape_char;	/* Escape character; -2 = none */
 
 	char   *system_hostfile;/* Path for /etc/ssh/ssh_known_hosts. */
@@ -102,6 +107,7 @@
 
 	int	enable_ssh_keysign;
 	int	rekey_limit;
+	int	none_switch;
 	int	no_host_authentication_for_localhost;
 	int	identities_only;
 	int	server_alive_interval;
diff -Naur --exclude=autom4te.cache openssh-4.2p1/scp.c openssh-4.2p1-gssapi/scp.c
--- openssh-4.2p1/scp.c	2005-08-02 02:07:08.000000000 -0500
+++ openssh-4.2p1-gssapi/scp.c	2005-12-20 13:31:00.000000000 -0600
@@ -231,7 +231,7 @@
 	addargs(&args, "-oClearAllForwardings yes");
 
 	fflag = tflag = 0;
-	while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1)
+	while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246zS:o:F:w:")) != -1)
 		switch (ch) {
 		/* User-visible flags. */
 		case '1':
@@ -239,6 +239,7 @@
 		case '4':
 		case '6':
 		case 'C':
+		case 'z':	
 			addargs(&args, "-%c", ch);
 			break;
 		case 'o':
@@ -292,6 +293,9 @@
 			setmode(0, O_BINARY);
 #endif
 			break;
+		case 'w':
+		  addargs(&args, "-w%s", optarg);
+		  break;
 		default:
 			usage();
 		}
@@ -507,7 +511,7 @@
 	off_t i, amt, statbytes;
 	size_t result;
 	int fd = -1, haderr, indx;
-	char *last, *name, buf[2048];
+	char *last, *name, buf[16384];
 	int len;
 
 	for (indx = 0; indx < argc; ++indx) {
@@ -567,7 +571,11 @@
 		(void) atomicio(vwrite, remout, buf, strlen(buf));
 		if (response() < 0)
 			goto next;
-		if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) {
+		/* this change decreases the number of read/write syscalls*/
+		/* when scp acts as data source. this is the critical change*/
+		/* buf can actually remain at 2k but increasing both to 16k*/
+		/* seemed to make sense*/
+		if ((bp = allocbuf(&buffer, fd, sizeof(buf))) == NULL) {
 next:			(void) close(fd);
 			continue;
 		}
@@ -728,7 +736,7 @@
 	int amt, exists, first, mask, mode, ofd, omode;
 	off_t size, statbytes;
 	int setimes, targisdir, wrerrno = 0;
-	char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
+	char ch, *cp, *np, *targ, *why, *vect[1], buf[16384];
 	struct timeval tv[2];
 
 #define	atime	tv[0]
@@ -889,7 +897,7 @@
 			continue;
 		}
 		(void) atomicio(vwrite, remout, "", 1);
-		if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) {
+		if ((bp = allocbuf(&buffer, ofd, sizeof(buf))) == NULL) {
 			(void) close(ofd);
 			continue;
 		}
@@ -899,8 +907,8 @@
 		statbytes = 0;
 		if (showprogress)
 			start_progress_meter(curfile, size, &statbytes);
-		for (count = i = 0; i < size; i += 4096) {
-			amt = 4096;
+		for (count = i = 0; i < size; i += sizeof(buf)) {
+			amt = sizeof(buf);
 			if (i + amt > size)
 				amt = size - i;
 			count += amt;
@@ -917,7 +925,7 @@
 			} while (amt > 0);
 
 			if (limit_rate)
-				bwlimit(4096);
+				bwlimit(sizeof(buf));
 
 			if (count == bp->cnt) {
 				/* Keep reading so we stay sync'd up. */
@@ -1033,7 +1041,7 @@
 {
 	(void) fprintf(stderr,
 	    "usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
-	    "           [-l limit] [-o ssh_option] [-P port] [-S program]\n"
+	    "           [-l limit] [-o ssh_option] [-P port] [-w buffer size] [-S program]\n"
 	    "           [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
 	exit(1);
 }
diff -Naur --exclude=autom4te.cache openssh-4.2p1/servconf.c openssh-4.2p1-gssapi/servconf.c
--- openssh-4.2p1/servconf.c	2005-08-12 07:11:37.000000000 -0500
+++ openssh-4.2p1-gssapi/servconf.c	2005-12-20 13:31:00.000000000 -0600
@@ -70,8 +70,14 @@
 	options->kerberos_authentication = -1;
 	options->kerberos_or_local_passwd = -1;
 	options->kerberos_ticket_cleanup = -1;
+#ifdef  SESSION_HOOKS
+        options->session_hooks_allow = -1;
+        options->session_hooks_startup_cmd = NULL;
+        options->session_hooks_shutdown_cmd = NULL;
+#endif
 	options->kerberos_get_afs_token = -1;
 	options->gss_authentication=-1;
+	options->gss_keyex = -1;
 	options->gss_cleanup_creds = -1;
 	options->password_authentication = -1;
 	options->kbd_interactive_authentication = -1;
@@ -185,7 +191,9 @@
 	if (options->kerberos_get_afs_token == -1)
 		options->kerberos_get_afs_token = 0;
 	if (options->gss_authentication == -1)
-		options->gss_authentication = 0;
+		options->gss_authentication = 1;
+	if (options->gss_keyex == -1)
+		options->gss_keyex = 1;
 	if (options->gss_cleanup_creds == -1)
 		options->gss_cleanup_creds = 1;
 	if (options->password_authentication == -1)
@@ -257,6 +265,9 @@
 	sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
 	sKerberosGetAFSToken,
 	sKerberosTgtPassing, sChallengeResponseAuthentication,
+#ifdef SESSION_HOOKS
+        sAllowSessionHooks, sSessionHookStartupCmd, sSessionHookShutdownCmd,
+#endif
 	sPasswordAuthentication, sKbdInteractiveAuthentication,
 	sListenAddress, sAddressFamily,
 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
@@ -270,7 +281,7 @@
 	sBanner, sUseDNS, sHostbasedAuthentication,
 	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
 	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
-	sGssAuthentication, sGssCleanupCreds, sAcceptEnv,
+	sGssAuthentication, sGssKeyEx, sGssCleanupCreds, sAcceptEnv,
 	sUsePrivilegeSeparation,
 	sDeprecated, sUnsupported
 } ServerOpCodes;
@@ -324,11 +335,18 @@
 	{ "afstokenpassing", sUnsupported },
 #ifdef GSSAPI
 	{ "gssapiauthentication", sGssAuthentication },
+	{ "gssapikeyexchange", sGssKeyEx },
 	{ "gssapicleanupcredentials", sGssCleanupCreds },
 #else
 	{ "gssapiauthentication", sUnsupported },
+	{ "gssapikeyexchange", sUnsupported },
 	{ "gssapicleanupcredentials", sUnsupported },
 #endif
+#ifdef SESSION_HOOKS
+        { "allowsessionhooks", sAllowSessionHooks },
+        { "sessionhookstartupcmd", sSessionHookStartupCmd },
+        { "sessionhookshutdowncmd", sSessionHookShutdownCmd },
+#endif        
 	{ "passwordauthentication", sPasswordAuthentication },
 	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
 	{ "challengeresponseauthentication", sChallengeResponseAuthentication },
@@ -669,10 +687,31 @@
 		intptr = &options->gss_authentication;
 		goto parse_flag;
 
+	case sGssKeyEx:
+		intptr = &options->gss_keyex;
+		goto parse_flag;
+
 	case sGssCleanupCreds:
 		intptr = &options->gss_cleanup_creds;
 		goto parse_flag;
 
+#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;
diff -Naur --exclude=autom4te.cache openssh-4.2p1/servconf.h openssh-4.2p1-gssapi/servconf.h
--- openssh-4.2p1/servconf.h	2005-01-19 17:57:56.000000000 -0600
+++ openssh-4.2p1-gssapi/servconf.h	2005-12-20 13:31:00.000000000 -0600
@@ -85,9 +85,15 @@
 						 * /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     gss_authentication;	/* If true, permit GSSAPI authentication */
+	int 	gss_keyex;		/* If true, permit GSSAPI key exchange */
 	int     gss_cleanup_creds;	/* If true, destroy cred cache on logout */
 	int     password_authentication;	/* If true, permit password
 						 * authentication. */
diff -Naur --exclude=autom4te.cache openssh-4.2p1/serverloop.c openssh-4.2p1-gssapi/serverloop.c
--- openssh-4.2p1/serverloop.c	2005-07-17 02:26:44.000000000 -0500
+++ openssh-4.2p1-gssapi/serverloop.c	2005-12-20 13:31:00.000000000 -0600
@@ -895,6 +895,8 @@
 	c = channel_new("session", SSH_CHANNEL_LARVAL,
 	    -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
 	    0, "server-session", 1);
+	if (!(datafellows & SSH_BUG_LARGEWINDOW))
+		c->dynamic_window = 1;
 	if (session_open(the_authctxt, c->self) != 1) {
 		debug("session open failed, free channel %d", c->self);
 		channel_free(c);
diff -Naur --exclude=autom4te.cache openssh-4.2p1/session.c openssh-4.2p1-gssapi/session.c
--- openssh-4.2p1/session.c	2005-08-31 11:59:49.000000000 -0500
+++ openssh-4.2p1-gssapi/session.c	2005-12-20 13:31:00.000000000 -0600
@@ -90,6 +90,11 @@
 
 static int session_pty_req(Session *);
 
+#ifdef SESSION_HOOKS
+static void execute_session_hook(char* prog, Authctxt *authctxt,
+                                 int startup, int save);
+#endif
+
 /* import */
 extern ServerOptions options;
 extern char *__progname;
@@ -227,6 +232,21 @@
 	else
 		do_authenticated1(authctxt);
 
+#ifdef SESSION_HOOKS
+        if (options.session_hooks_allow &&
+            options.session_hooks_shutdown_cmd)
+        {
+            execute_session_hook(options.session_hooks_shutdown_cmd,
+                                 authctxt,
+                                 /* startup = */ 0, /* save = */ 0);
+
+            if (authctxt->session_env_file)
+            {
+                free(authctxt->session_env_file);
+            }
+        }
+#endif
+
 	do_cleanup(authctxt);
 }
 
@@ -666,6 +686,26 @@
 		debug("Forced command '%.900s'", command);
 	}
 
+#if defined(SESSION_HOOKS)
+	if (options.session_hooks_allow &&
+	    (options.session_hooks_startup_cmd ||
+	     options.session_hooks_shutdown_cmd))
+	{
+		char env_file[1000];
+		struct stat st;
+		do
+		{
+			snprintf(env_file,
+				 sizeof(env_file),
+				 "/tmp/ssh_env_%d%d%d",
+				 getuid(),
+				 getpid(),
+				 rand());
+		} while (stat(env_file, &st)==0);
+		s->authctxt->session_env_file = strdup(env_file);
+	}
+#endif
+
 #ifdef SSH_AUDIT_EVENTS
 	if (command != NULL)
 		PRIVSEP(audit_run_command(command));
@@ -892,6 +932,117 @@
 	fclose(f);
 }
 
+#ifdef SESSION_HOOKS
+#define SSH_SESSION_ENV_FILE "SSH_SESSION_ENV_FILE"
+
+typedef enum { no_op, execute, clear_env, restore_env,
+               read_env, save_or_rm_env } session_action_t;
+
+static session_action_t action_order[2][5] = {
+    { clear_env, read_env, execute, save_or_rm_env, restore_env }, /*shutdown*/
+    { execute, read_env, save_or_rm_env, no_op, no_op }            /*startup */
+};
+
+static
+void execute_session_hook(char* prog, Authctxt *authctxt,
+                          int startup, int save)
+{
+    extern char **environ;
+
+    struct stat  st;
+    char         **saved_env, **tmpenv;
+    char         *env_file = authctxt->session_env_file;
+    int          i, status = 0;
+
+    for (i=0; i<5; i++)
+    {
+        switch (action_order[startup][i])
+        {
+          case no_op:
+            break;
+
+          case execute:
+            {
+                FILE* fp;
+                char  buf[1000];
+
+                snprintf(buf,
+                         sizeof(buf),
+                         "%s -c '%s'",
+                         authctxt->pw->pw_shell,
+                         prog);
+
+                debug("executing session hook: [%s]", buf);
+                setenv(SSH_SESSION_ENV_FILE, env_file, /* overwrite = */ 1);
+
+                /* flusing is recommended in the popen(3) man page, to avoid
+                   intermingling of output */
+                fflush(stdout);
+                fflush(stderr);
+                if ((fp=popen(buf, "w")) == NULL)
+                {
+                    perror("Unable to run session hook");
+                    return;
+                }
+                status = pclose(fp);
+                debug2("session hook executed, status=%d", status);
+                unsetenv(SSH_SESSION_ENV_FILE);
+            }
+            break;
+
+          case clear_env:
+            saved_env = environ;
+            tmpenv = (char**) malloc(sizeof(char*));
+            tmpenv[0] = NULL;
+            environ = tmpenv;
+            break;
+
+          case restore_env:
+            environ = saved_env;
+            free(tmpenv);
+            break;
+
+          case read_env:
+            if (status==0 && stat(env_file, &st)==0)
+            {
+                int envsize = 0;
+
+                debug("reading environment from %s", env_file);
+                while (environ[envsize++]) ;
+                read_environment_file(&environ, &envsize, env_file);
+            }
+            break;
+
+          case save_or_rm_env:
+            if (status==0 && save)
+            {
+                FILE* fp;
+                int    envcount=0;
+
+                debug2("saving environment to %s", env_file);
+                if ((fp = fopen(env_file, "w")) == NULL) /* hmm: file perms? */
+                {
+                    perror("Unable to save session hook info");
+                }
+                while (environ[envcount])
+                {
+                    fprintf(fp, "%s\n", environ[envcount++]);
+                }
+                fflush(fp);
+                fclose(fp);
+            }
+            else if (stat(env_file, &st)==0)
+            {
+                debug2("removing environment file %s", env_file);
+                remove(env_file);
+            }
+            break;
+        }
+    }
+
+}
+#endif
+
 #ifdef HAVE_ETC_DEFAULT_LOGIN
 /*
  * Return named variable from specified environment, or NULL if not present.
@@ -1052,6 +1203,23 @@
 	if (getenv("TZ"))
 		child_set_env(&env, &envsize, "TZ", getenv("TZ"));
 
+#ifdef GSI /* GSI shared libs typically installed in non-system locations. */
+	{
+		char *cp;
+
+		if ((cp = getenv("LD_LIBRARY_PATH")) != NULL)
+			child_set_env(&env, &envsize, "LD_LIBRARY_PATH", cp);
+		if ((cp = getenv("LIBPATH")) != NULL)
+			child_set_env(&env, &envsize, "LIBPATH", cp);
+		if ((cp = getenv("SHLIB_PATH")) != NULL)
+			child_set_env(&env, &envsize, "SHLIB_PATH", cp);
+		if ((cp = getenv("LD_LIBRARYN32_PATH")) != NULL)
+			child_set_env(&env, &envsize, "LD_LIBRARYN32_PATH",cp);
+		if ((cp = getenv("LD_LIBRARY64_PATH")) != NULL)
+			child_set_env(&env, &envsize, "LD_LIBRARY64_PATH",cp);
+	}
+#endif
+
 	/* Set custom environment options from RSA authentication. */
 	if (!options.use_login) {
 		while (custom_environment) {
@@ -1442,6 +1610,18 @@
 	const char *shell, *shell0, *hostname = NULL;
 	struct passwd *pw = s->pw;
 
+#ifdef AFS_KRB5
+/* Default place to look for aklog. */
+#ifdef AKLOG_PATH
+#define KPROGDIR AKLOG_PATH
+#else
+#define KPROGDIR "/usr/bin/aklog"
+#endif /* AKLOG_PATH */
+
+	struct stat st;
+	char *aklog_path;
+#endif /* AFS_KRB5 */
+
 	/* remove hostkey from the child's memory */
 	destroy_sensitive_data();
 
@@ -1552,6 +1732,41 @@
 	}
 #endif
 
+#ifdef AFS_KRB5
+
+	/* User has authenticated, and if a ticket was going to be
+	 * passed we would have it.  KRB5CCNAME should already be set.
+	 * Now try to get an AFS token using aklog.
+	 */
+	if (k_hasafs()) {  /* Do we have AFS? */
+
+		aklog_path = xstrdup(KPROGDIR);
+
+		/*
+		 * Make sure it exists before we try to run it
+		 */
+		if (stat(aklog_path, &st) == 0) {
+			debug("Running %s to get afs token.",aklog_path);
+			system(aklog_path);
+		} else {
+			debug("%s does not exist.",aklog_path);
+		}
+
+		xfree(aklog_path);
+	}
+#endif /* AFS_KRB5 */
+
+#ifdef SESSION_HOOKS
+        if (options.session_hooks_allow &&
+            options.session_hooks_startup_cmd)
+        {
+            execute_session_hook(options.session_hooks_startup_cmd,
+                                 s->authctxt,
+                                 /* startup = */ 1,
+                                 options.session_hooks_shutdown_cmd != NULL);
+        }
+#endif
+
 	/* Change current directory to the user\'s home directory. */
 	if (chdir(pw->pw_dir) < 0) {
 		fprintf(stderr, "Could not chdir to home directory %s: %s\n",
@@ -1600,7 +1815,7 @@
 		/* Execute the shell. */
 		argv[0] = argv0;
 		argv[1] = NULL;
-		execve(shell, argv, env);
+		execve(shell, argv, environ);
 
 		/* Executing the shell failed. */
 		perror(shell);
@@ -1614,7 +1829,7 @@
 	argv[1] = "-c";
 	argv[2] = (char *) command;
 	argv[3] = NULL;
-	execve(shell, argv, env);
+	execve(shell, argv, environ);
 	perror(shell);
 	exit(1);
 }
diff -Naur --exclude=autom4te.cache openssh-4.2p1/ssh-gss.h openssh-4.2p1-gssapi/ssh-gss.h
--- openssh-4.2p1/ssh-gss.h	2004-06-21 21:56:02.000000000 -0500
+++ openssh-4.2p1-gssapi/ssh-gss.h	2005-12-20 13:31:00.000000000 -0600
@@ -28,6 +28,7 @@
 
 #ifdef GSSAPI
 
+#include "kex.h"
 #include "buffer.h"
 
 #ifdef HAVE_GSSAPI_H
@@ -36,6 +37,7 @@
 #include <gssapi/gssapi.h>
 #endif
 
+#ifndef MECHGLUE
 #ifdef KRB5
 # ifndef HEIMDAL
 #  ifdef HAVE_GSSAPI_GENERIC_H
@@ -51,6 +53,7 @@
 #endif /* GSS_C_NT_... */
 #endif /* !HEIMDAL */
 #endif /* KRB5 */
+#endif /* !MECHGLUE */
 
 /* draft-ietf-secsh-gsskeyex-06 */
 #define SSH2_MSG_USERAUTH_GSSAPI_RESPONSE		60
@@ -62,6 +65,16 @@
 
 #define SSH_GSS_OIDTYPE 0x06
 
+#define SSH2_MSG_KEXGSS_INIT                           30
+#define SSH2_MSG_KEXGSS_CONTINUE                       31
+#define SSH2_MSG_KEXGSS_COMPLETE                       32
+#define SSH2_MSG_KEXGSS_HOSTKEY                                33
+#define SSH2_MSG_KEXGSS_ERROR                          34
+#define SSH2_MSG_KEXGSS_GROUPREQ			40
+#define SSH2_MSG_KEXGSS_GROUP				41
+#define KEX_GSS_GRP1_SHA1_ID				"gss-group1-sha1-"
+#define KEX_GSS_GEX_SHA1_ID				"gss-gex-sha1-"
+
 typedef struct {
 	char *filename;
 	char *envvar;
@@ -92,13 +105,14 @@
 	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 */
 } Gssctxt;
 
 extern ssh_gssapi_mech *supported_mechs[];
+extern Gssctxt *gss_kex_context;
 
 int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
 void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
@@ -121,12 +135,29 @@
 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
 void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *);
 
-/* In the server */
+int ssh_gssapi_localname(char **name);
+
+typedef int ssh_gssapi_check_fn(gss_OID, void *);
+char *ssh_gssapi_client_mechanisms(const char *host);
+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, void *);
+int ssh_gssapi_check_mechanism(gss_OID, void *);
+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int *);
+
+int ssh_gssapi_server_check_mech(gss_OID, void *);
 int ssh_gssapi_userok(char *name);
 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
 
 #endif /* GSSAPI */
 
diff -Naur --exclude=autom4te.cache openssh-4.2p1/ssh.c openssh-4.2p1-gssapi/ssh.c
--- openssh-4.2p1/ssh.c	2005-08-12 07:10:56.000000000 -0500
+++ openssh-4.2p1-gssapi/ssh.c	2005-12-20 13:31:00.000000000 -0600
@@ -158,7 +158,7 @@
 {
 	fprintf(stderr,
 "usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
-"           [-D port] [-e escape_char] [-F configfile]\n"
+"           [-D port] [-e escape_char] [-F configfile] [-w receive buffer size]\n"
 "           [-i identity_file] [-L [bind_address:]port:host:hostport]\n"
 "           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
 "           [-R [bind_address:]port:host:hostport] [-S ctl_path]\n"
@@ -239,9 +239,12 @@
 	/* Parse command-line arguments. */
 	host = NULL;
 
+	/* need to set options.tcp_rcv_buf to 0 */
+	options.tcp_rcv_buf = 0;
+
 again:
 	while ((opt = getopt(ac, av,
-	    "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVXY")) != -1) {
+	    "1246ab:c:e:fgi:kl:m:no:p:qstvw:xzACD:F:I:L:MNO:PR:S:TVXY")) != -1) {
 		switch (opt) {
 		case '1':
 			options.protocol = SSH_PROTO_1;
@@ -460,6 +463,7 @@
 			break;
 		case 'T':
 			no_tty_flag = 1;
+			options.none_switch = 0;
 			break;
 		case 'o':
 			dummy = 1;
@@ -483,6 +487,17 @@
 		case 'F':
 			config = optarg;
 			break;
+		case 'w':
+		        options.tcp_rcv_buf = atoi(optarg);
+		        break;
+		case 'z':
+			/* make sure we can't turn on the none_switch */
+			/* if they try to force a no tty flag on a tty session */
+			if (!no_tty_flag) {
+				options.none_switch = 1;
+			}
+			break;
+
 		default:
 			usage();
 		}
@@ -575,6 +590,29 @@
 			fatal("Can't open user config file %.100s: "
 			    "%.100s", config, strerror(errno));
 	} else  {
+	    /*
+	     * Since the config file parsing code aborts if it sees
+	     * options it doesn't recognize, allow users to put
+	     * options specific to compile-time add-ons in alternate
+	     * config files so their primary config file will
+	     * interoperate SSH versions that don't support those
+	     * options.
+	     */
+#ifdef GSSAPI
+		snprintf(buf, sizeof buf, "%.100s/%.100s.gssapi", pw->pw_dir,
+		    _PATH_SSH_USER_CONFFILE);
+		(void)read_config_file(buf, host, &options, 1);
+#ifdef GSI
+		snprintf(buf, sizeof buf, "%.100s/%.100s.gsi", pw->pw_dir,
+		    _PATH_SSH_USER_CONFFILE);
+		(void)read_config_file(buf, host, &options, 1);
+#endif
+#if defined(KRB5)
+		snprintf(buf, sizeof buf, "%.100s/%.100s.krb", pw->pw_dir,
+		    _PATH_SSH_USER_CONFFILE);
+		(void)read_config_file(buf, host, &options, 1);
+#endif
+#endif
 		snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir,
 		    _PATH_SSH_USER_CONFFILE);
 		(void)read_config_file(buf, host, &options, 1);
@@ -594,8 +632,11 @@
 
 	seed_rng();
 
-	if (options.user == NULL)
+	if (options.user == NULL) {
 		options.user = xstrdup(pw->pw_name);
+		options.implicit = 1;
+	}
+        else options.implicit = 0;
 
 	if (options.hostname != NULL)
 		host = options.hostname;
@@ -1092,6 +1133,7 @@
 	window = CHAN_SES_WINDOW_DEFAULT;
 	packetmax = CHAN_SES_PACKET_DEFAULT;
 	if (tty_flag) {
+		window = 4*CHAN_SES_PACKET_DEFAULT;
 		window >>= 1;
 		packetmax >>= 1;
 	}
@@ -1099,7 +1141,9 @@
 	    "session", SSH_CHANNEL_OPENING, in, out, err,
 	    window, packetmax, CHAN_EXTENDED_WRITE,
 	    "client-session", /*nonblock*/0);
-
+	if (!tty_flag && (!(datafellows & SSH_BUG_LARGEWINDOW))) {
+		c->dynamic_window = 1;
+	}
 	debug3("ssh_session2_open: channel_new: %d", c->self);
 
 	channel_send_open(c->self);
diff -Naur --exclude=autom4te.cache openssh-4.2p1/ssh_config.5 openssh-4.2p1-gssapi/ssh_config.5
--- openssh-4.2p1/ssh_config.5	2005-07-14 02:06:51.000000000 -0500
+++ openssh-4.2p1-gssapi/ssh_config.5	2005-12-20 13:31:00.000000000 -0600
@@ -57,6 +57,12 @@
 user's configuration file
 .Pq Pa ~/.ssh/config
 .It
+GSSAPI configuration file
+.Pq Pa $HOME/.ssh/config.gssapi
+.It
+Kerberos configuration file
+.Pq Pa $HOME/.ssh/config.krb
+.It
 system-wide configuration file
 .Pq Pa /etc/ssh/ssh_config
 .El
@@ -439,14 +445,30 @@
 .Pa /etc/ssh/ssh_known_hosts .
 .It Cm GSSAPIAuthentication
 Specifies whether user authentication based on GSSAPI is allowed.
+The default is 
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI may be used. When using
+GSSAPI key exchange the server need not have a host key.
 The default is
-.Dq no .
+.Dq yes .
 Note that this option applies to protocol version 2 only.
 .It Cm GSSAPIDelegateCredentials
 Forward (delegate) credentials to the server.
 The default is
-.Dq no .
+.Dq yes .
 Note that this option applies to protocol version 2 only.
+.It Cm GSSAPITrustDns
+Set to 
+.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
+command line will be passed untouched to the GSSAPI library.
+The default is
+.Dq yes .
+This option only applies to protocol version 2 connections using GSSAPI 
+key exchange.
 .It Cm HashKnownHosts
 Indicates that
 .Nm ssh
@@ -612,7 +634,7 @@
 over another method (e.g.\&
 .Cm password )
 The default for this option is:
-.Dq hostbased,publickey,keyboard-interactive,password .
+.Dq publickey,gssapi-keyex,external-keyx,gssapi-with-mic,gssapi,password,keyboard-interactive .
 .It Cm Protocol
 Specifies the protocol versions
 .Nm ssh
diff -Naur --exclude=autom4te.cache openssh-4.2p1/sshconnect.c openssh-4.2p1-gssapi/sshconnect.c
--- openssh-4.2p1/sshconnect.c	2005-07-17 02:22:46.000000000 -0500
+++ openssh-4.2p1-gssapi/sshconnect.c	2005-12-20 13:31:00.000000000 -0600
@@ -167,13 +167,58 @@
 			    strerror(errno));
 		else
 			debug("Allocated local port %d.", p);
+
+		
+		/* tuning needs to happen after the socket is */
+		/* created but before the connection happens */
+		/* so winscale is negotiated properly -cjr */
+		
+		/* Set tcp receive buffer if requested */
+		if (options.tcp_rcv_buf) 
+		  {
+		    if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, 
+				   (void *)&options.tcp_rcv_buf, 
+				   sizeof(options.tcp_rcv_buf)) >= 0)
+		      {             
+			debug("setsockopt SO_RCVBUF: %.100s", strerror(errno));
+		      } 
+		    else 
+		      {
+			/* coudln't set the socket size to use spec. */
+			/* should default to system param and continue */
+			/* warn the user though - cjr */
+			error("Couldn't set socket receive buffer as requested. Continuing anyway.");
+		      }
+		  }
 		return sock;
 	}
 	sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
 	if (sock < 0)
 		error("socket: %.100s", strerror(errno));
-
-	/* Bind the socket to an alternative local IP address */
+	
+	/* tuning needs to happen after the socket is */
+	/* created but before the connection happens */
+	/* so winscale is negotiated properly -cjr */
+	
+	/* Set tcp receive buffer if requested */
+	if (options.tcp_rcv_buf) 
+	  {
+	    if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, 
+			   (void *)&options.tcp_rcv_buf, 
+			   sizeof(options.tcp_rcv_buf)) >= 0)
+	      {             
+		debug("setsockopt SO_RCVBUF: %.100s", strerror(errno));
+	      }
+	    else 
+	      {
+		/* coudln't set the socket size to use spec. */
+		/* should default to system param and continue */
+		/* warn the user though - cjr */
+		error("Couldn't set socket receive buffer as requested. Continuing anyway.");
+	      }
+	  }
+	
+       	/* Bind the socket to an alternative local IP address */
 	if (options.bind_address == NULL)
 		return sock;
 
@@ -480,7 +525,7 @@
 	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
 	    compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
 	    compat20 ? PROTOCOL_MINOR_2 : minor1,
-	    SSH_VERSION);
+	    SSH_RELEASE);
 	if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf))
 		fatal("write: %.100s", strerror(errno));
 	client_version_string = xstrdup(buf);
diff -Naur --exclude=autom4te.cache openssh-4.2p1/sshconnect2.c openssh-4.2p1-gssapi/sshconnect2.c
--- openssh-4.2p1/sshconnect2.c	2005-08-31 04:46:27.000000000 -0500
+++ openssh-4.2p1-gssapi/sshconnect2.c	2005-12-20 13:31:00.000000000 -0600
@@ -58,6 +58,12 @@
 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;
 
 /*
  * SSH2 key exchange
@@ -84,9 +90,36 @@
 {
 	Kex *kex;
 
+#ifdef GSSAPI
+	char *orig = NULL, *gss = NULL;
+	int len;
+        char *gss_host = NULL;
+#endif
+
 	xxx_host = host;
 	xxx_hostaddr = hostaddr;
 
+#ifdef GSSAPI
+	if (options.gss_keyex) {
+	/* Add the GSSAPI mechanisms currently supported on this client to
+	 * the key exchange algorithm proposal */
+	orig = myproposal[PROPOSAL_KEX_ALGS];
+	if (options.gss_trust_dns)
+		gss_host = (char *)get_canonical_hostname(1);
+	else
+		gss_host = host;
+
+	gss = ssh_gssapi_client_mechanisms(gss_host);
+	if (gss) {
+		debug("Offering GSSAPI proposal: %s", gss);
+		len = strlen(orig) + strlen(gss) + 2;
+		myproposal[PROPOSAL_KEX_ALGS] = xmalloc(len);
+		snprintf(myproposal[PROPOSAL_KEX_ALGS], len, "%s,%s", gss, 
+		    orig);
+	}
+	}
+#endif
+
 	if (options.ciphers == (char *)-1) {
 		logit("No valid ciphers for protocol version 2 given, using defaults.");
 		options.ciphers = NULL;
@@ -114,6 +147,18 @@
 		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
 		    options.hostkeyalgorithms;
 
+#ifdef GSSAPI
+	/* If we've got GSSAPI algorithms, then we also support the
+	 * 'null' hostkey, as a last resort */
+	if (options.gss_keyex && gss) {
+		orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
+		len = strlen(orig) + sizeof(",null");
+		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xmalloc(len);
+		snprintf(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], len, 
+		    "%s,null", orig);
+	}
+#endif
+
 	if (options.rekey_limit)
 		packet_set_rekey_limit(options.rekey_limit);
 
@@ -122,9 +167,22 @@
 	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
 	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
 	kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
+#ifdef GSSAPI
+	kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
+	kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
+#endif
 	kex->client_version_string=client_version_string;
 	kex->server_version_string=server_version_string;
 	kex->verify_host_key=&verify_host_key_callback;
+#ifdef GSSAPI
+	kex->options.gss_deleg_creds=options.gss_deleg_creds;
+#endif
+
+#ifdef GSSAPI
+	kex->gss_deleg_creds = options.gss_deleg_creds;
+	kex->gss_trust_dns = options.gss_trust_dns;
+	kex->gss_host = gss_host;
+#endif
 
 	xxx_kex = kex;
 
@@ -202,12 +260,16 @@
 int	userauth_kerberos(Authctxt *);
 
 #ifdef GSSAPI
+int	userauth_external(Authctxt *authctxt);
 int	userauth_gssapi(Authctxt *authctxt);
+int	userauth_gssapi_with_mic(Authctxt *authctxt);
+int	userauth_gssapi_without_mic(Authctxt *authctxt);
 void	input_gssapi_response(int type, u_int32_t, void *);
 void	input_gssapi_token(int type, u_int32_t, void *);
 void	input_gssapi_hash(int type, u_int32_t, void *);
 void	input_gssapi_error(int, u_int32_t, void *);
 void	input_gssapi_errtok(int, u_int32_t, void *);
+int	userauth_gsskeyex(Authctxt *authctxt);
 #endif
 
 void	userauth(Authctxt *, char *);
@@ -223,10 +285,22 @@
 
 Authmethod authmethods[] = {
 #ifdef GSSAPI
+	{"gssapi-keyex",
+		userauth_gsskeyex,
+		&options.gss_authentication,
+		NULL},
+	{"external-keyx",
+		userauth_external,
+		&options.gss_authentication,
+		NULL},
 	{"gssapi-with-mic",
 		userauth_gssapi,
 		&options.gss_authentication,
 		NULL},
+	{"gssapi",
+		userauth_gssapi,
+		&options.gss_authentication,
+		NULL},
 #endif
 	{"hostbased",
 		userauth_hostbased,
@@ -309,7 +383,15 @@
 
 	pubkey_cleanup(&authctxt);
 	dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL);
-
+	if ((options.none_switch == 1) && !tty_flag) /* no null on tty sessions */
+	{
+		debug("Requesting none rekeying...");
+		myproposal[PROPOSAL_ENC_ALGS_STOC] = "none";
+		myproposal[PROPOSAL_ENC_ALGS_CTOS] = "none";
+		kex_prop2buf(&xxx_kex->my,myproposal);
+		packet_request_rekeying();
+		fprintf(stderr, "WARNING: ENABLED NULL CIPHER\n");
+	}
 	debug("Authentication succeeded (%s).", authctxt.method->name);
 }
 
@@ -485,6 +567,17 @@
 	static u_int mech = 0;
 	OM_uint32 min;
 	int ok = 0;
+	char *gss_host = NULL;
+
+	if (!options.gss_authentication) {
+		verbose("GSSAPI authentication disabled.");
+		return 0;
+	}
+
+	if (options.gss_trust_dns)
+		gss_host = (char *)get_canonical_hostname(1);
+	else
+		gss_host = (char *)authctxt->host;
 
 	/* Try one GSSAPI method at a time, rather than sending them all at
 	 * once. */
@@ -501,8 +594,10 @@
 
 		/* My DER encoding requires length<128 */
 		if (gss_supported->elements[mech].length < 128 &&
+		    ssh_gssapi_check_mechanism(&gss_supported->elements[mech],
+					       gss_host) &&
 		    !GSS_ERROR(ssh_gssapi_import_name(gssctxt,
-		    authctxt->host))) {
+						      gss_host))) {
 			ok = 1; /* Mechanism works */
 		} else {
 			mech++;
@@ -566,7 +661,8 @@
 
 	if (status == GSS_S_COMPLETE) {
 		/* send either complete or MIC, depending on mechanism */
-		if (!(flags & GSS_C_INTEG_FLAG)) {
+		if (strcmp(authctxt->method->name,"gssapi")==0 ||
+		    (!(flags & GSS_C_INTEG_FLAG))) {
 			packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
 			packet_send();
 		} else {
@@ -598,8 +694,8 @@
 {
 	Authctxt *authctxt = ctxt;
 	Gssctxt *gssctxt;
-	int oidlen;
-	char *oidv;
+	unsigned int oidlen;
+	unsigned char *oidv;
 
 	if (authctxt == NULL)
 		fatal("input_gssapi_response: no authentication context");
@@ -706,6 +802,106 @@
 	xfree(msg);
 	xfree(lang);
 }
+
+#ifdef GSI
+extern
+const gss_OID_desc * const              gss_mech_globus_gssapi_openssl;
+#define is_gsi_oid(oid) \
+  (oid->length == gss_mech_globus_gssapi_openssl->length && \
+   (memcmp(oid->elements, gss_mech_globus_gssapi_openssl->elements, \
+	   oid->length) == 0))
+#endif
+
+int
+userauth_external(Authctxt *authctxt)
+{
+        static int attempt = 0;
+        
+        if (attempt++ >= 1)
+        	return 0;
+                                
+	/* The client MUST NOT try this method if initial key exchange
+	   was not performed using a GSSAPI-based key exchange
+	   method. */
+	if (gss_kex_context == NULL) {
+		debug2("gsskex not performed, skipping external-keyx");
+		return 0;
+	}
+
+        debug2("userauth_external");
+        packet_start(SSH2_MSG_USERAUTH_REQUEST);
+#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_send();
+        packet_write_wait();
+        return 1;
+}                                                                                                
+int
+userauth_gsskeyex(Authctxt *authctxt)
+{
+	Buffer b;
+	gss_buffer_desc gssbuf;
+	gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
+	OM_uint32 ms;
+
+	static int attempt = 0;
+	if (attempt++ >= 1)
+		return (0);
+
+	if (gss_kex_context == NULL) {
+		debug("No valid Key exchange context"); 
+		return (0);
+	}
+
+#ifdef GSI
+        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");
+#ifdef GSI
+	}
+#endif
+
+	gssbuf.value = buffer_ptr(&b);
+	gssbuf.length = buffer_len(&b);
+
+	if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
+		buffer_free(&b);
+		return (0);
+	}
+
+	packet_start(SSH2_MSG_USERAUTH_REQUEST);
+#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);
+	packet_send();
+
+	buffer_free(&b);
+	gss_release_buffer(&ms, &mic);
+
+	return (1);
+}
+
 #endif /* GSSAPI */
 
 int
diff -Naur --exclude=autom4te.cache openssh-4.2p1/sshd.c openssh-4.2p1-gssapi/sshd.c
--- openssh-4.2p1/sshd.c	2005-07-26 06:54:56.000000000 -0500
+++ openssh-4.2p1-gssapi/sshd.c	2005-12-20 13:31:00.000000000 -0600
@@ -86,6 +86,10 @@
 #include "monitor_wrap.h"
 #include "monitor_fdpass.h"
 
+#ifdef USE_SECURITY_SESSION_API
+#include <Security/AuthSession.h>
+#endif
+
 #ifdef LIBWRAP
 #include <tcpd.h>
 #include <syslog.h>
@@ -377,7 +381,7 @@
 		major = PROTOCOL_MAJOR_1;
 		minor = PROTOCOL_MINOR_1;
 	}
-	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_VERSION);
+	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n", major, minor, SSH_RELEASE);
 	server_version_string = xstrdup(buf);
 
 	/* Send our protocol version identification. */
@@ -1117,10 +1121,13 @@
 		logit("Disabling protocol version 1. Could not load host key");
 		options.protocol &= ~SSH_PROTO_1;
 	}
+#ifndef GSSAPI
+	/* The GSSAPI key exchange can run without a host key */
 	if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
 		logit("Disabling protocol version 2. Could not load host key");
 		options.protocol &= ~SSH_PROTO_2;
 	}
+#endif
 	if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
 		logit("sshd: no hostkeys available -- exiting.");
 		exit(1);
@@ -1663,6 +1670,60 @@
 	/* Log the connection. */
 	verbose("Connection from %.500s port %d", remote_ip, remote_port);
 
+#ifdef USE_SECURITY_SESSION_API
+	/*
+	 * Create a new security session for use by the new user login if
+	 * the current session is the root session or we are not launched
+	 * by inetd (eg: debugging mode or server mode).  We do not
+	 * necessarily need to create a session if we are launched from
+	 * inetd because Panther xinetd will create a session for us.
+	 *
+	 * The only case where this logic will fail is if there is an
+	 * inetd running in a non-root session which is not creating
+	 * new sessions for us.  Then all the users will end up in the
+	 * same session (bad).
+	 *
+	 * When the client exits, the session will be destroyed for us
+	 * automatically.
+	 *
+	 * We must create the session before any credentials are stored
+	 * (including AFS pags, which happens a few lines below).
+	 */
+	{
+		OSStatus err = 0;
+		SecuritySessionId sid = 0;
+		SessionAttributeBits sattrs = 0;
+
+		err = SessionGetInfo(callerSecuritySession, &sid, &sattrs);
+		if (err)
+			error("SessionGetInfo() failed with error %.8X",
+			    (unsigned) err);
+		else
+			debug("Current Session ID is %.8X / Session Attributes are %.8X",
+			    (unsigned) sid, (unsigned) sattrs);
+
+		if (inetd_flag && !(sattrs & sessionIsRoot))
+			debug("Running in inetd mode in a non-root session... "
+			    "assuming inetd created the session for us.");
+		else {
+			debug("Creating new security session...");
+			err = SessionCreate(0, sessionHasTTY | sessionIsRemote);
+			if (err)
+				error("SessionCreate() failed with error %.8X",
+				    (unsigned) err);
+
+			err = SessionGetInfo(callerSecuritySession, &sid, 
+			    &sattrs);
+			if (err)
+				error("SessionGetInfo() failed with error %.8X",
+				    (unsigned) err);
+			else
+				debug("New Session ID is %.8X / Session Attributes are %.8X",
+				    (unsigned) sid, (unsigned) sattrs);
+		}
+	}
+#endif
+
 	/*
 	 * We don\'t want to listen forever unless the other side
 	 * successfully authenticates itself.  So we set up an alarm which is
@@ -1676,6 +1737,13 @@
 		alarm(options.login_grace_time);
 
 	sshd_exchange_identification(sock_in, sock_out);
+#if defined(AFS_KRB5)
+	/* If machine has AFS, set process authentication group. */
+	if (k_hasafs()) {
+		k_setpag();
+		k_unlog();
+	}
+#endif /* AFS || AFS_KRB5 */
 
 	packet_set_nonblocking();
 
@@ -2006,13 +2074,63 @@
 	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
 
 	/* start key exchange */
-	kex = kex_setup(myproposal);
-	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
+  
+#ifdef GSSAPI
+	{
+	char *orig;
+	char *gss = NULL;
+	char *newstr = NULL;
+	orig = myproposal[PROPOSAL_KEX_ALGS];
+
+	/* 
+ 	 * If we don't have a host key, then there's no point advertising
+         * the other key exchange algorithms
+	 */
+
+	if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
+		orig = NULL;
+
+	if (options.gss_keyex)
+		gss = ssh_gssapi_server_mechanisms();
+	else
+		gss = NULL;
+
+	if (gss && orig) {
+		int len = strlen(orig) + strlen(gss) + 2;
+		newstr = xmalloc(len);
+		snprintf(newstr, len, "%s,%s", gss, orig);
+	} else if (gss) {
+		newstr = gss;
+	} else if (orig) {
+		newstr = orig;
+	}
+	/* 
+	 * If we've got GSSAPI mechanisms, then we've got the 'null' host
+	 * key alg, but we can't tell people about it unless its the only
+  	 * host key algorithm we support
+	 */
+	if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
+		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
+
+	if (newstr)
+		myproposal[PROPOSAL_KEX_ALGS] = newstr;
+	else
+		fatal("No supported key exchange algorithms");
+	}
+#endif
+
+  	/* start key exchange */
+  	kex = kex_setup(myproposal);
+  	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
 	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
 	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
-	kex->server = 1;
-	kex->client_version_string=client_version_string;
-	kex->server_version_string=server_version_string;
+#ifdef GSSAPI
+	kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+	kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+#endif
+  	kex->server = 1;
+  	kex->client_version_string=client_version_string;
+  	kex->server_version_string=server_version_string;
 	kex->load_host_key=&get_hostkey_by_type;
 	kex->host_key_index=&get_hostkey_index;
 
diff -Naur --exclude=autom4te.cache openssh-4.2p1/sshd_config openssh-4.2p1-gssapi/sshd_config
--- openssh-4.2p1/sshd_config	2005-07-26 06:54:57.000000000 -0500
+++ openssh-4.2p1-gssapi/sshd_config	2005-12-20 13:31:00.000000000 -0600
@@ -65,8 +65,13 @@
 #KerberosTicketCleanup yes
 #KerberosGetAFSToken no
 
+# Session hooks: if allowed, specify the commands to execute
+#AllowSessionHooks yes
+#SessionHookStartupCmd /bin/true
+#SessionHookShutdownCmd /bin/true
+
 # GSSAPI options
-#GSSAPIAuthentication no
+#GSSAPIAuthentication yes
 #GSSAPICleanupCredentials yes
 
 # Set this to 'yes' to enable PAM authentication, account processing, 
diff -Naur --exclude=autom4te.cache openssh-4.2p1/sshd_config.5 openssh-4.2p1-gssapi/sshd_config.5
--- openssh-4.2p1/sshd_config.5	2005-07-26 06:54:57.000000000 -0500
+++ openssh-4.2p1-gssapi/sshd_config.5	2005-12-20 13:31:00.000000000 -0600
@@ -275,7 +275,13 @@
 .It Cm GSSAPIAuthentication
 Specifies whether user authentication based on GSSAPI is allowed.
 The default is
-.Dq no .
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange 
+doesn't rely on ssh keys to verify host identity.
+The default is
+.Dq yes .
 Note that this option applies to protocol version 2 only.
 .It Cm GSSAPICleanupCredentials
 Specifies whether to automatically destroy the user's credentials cache
diff -Naur --exclude=autom4te.cache openssh-4.2p1/version.h openssh-4.2p1-gssapi/version.h
--- openssh-4.2p1/version.h	2005-08-31 04:47:07.000000000 -0500
+++ openssh-4.2p1-gssapi/version.h	2005-12-20 13:31:00.000000000 -0600
@@ -1,6 +1,27 @@
 /* $OpenBSD: version.h,v 1.45 2005/08/31 09:28:42 markus Exp $ */
 
+#ifdef GSI
+#define GSI_VERSION	" GSI"
+#else
+#define GSI_VERSION	""
+#endif
+
+#ifdef KRB5
+#define KRB5_VERSION	" KRB5"
+#else
+#define KRB5_VERSION	""
+#endif
+
+#ifdef MECHGLUE
+#define MGLUE_VERSION	" MECHGLUE"
+#else
+#define MGLUE_VERSION	""
+#endif
+
 #define SSH_VERSION	"OpenSSH_4.2"
 
 #define SSH_PORTABLE	"p1"
-#define SSH_RELEASE	SSH_VERSION SSH_PORTABLE
+#define SSH_HPN		"-hpn"
+#define SSH_RELEASE	SSH_VERSION SSH_PORTABLE SSH_HPN \
+			" NCSA_GSSAPI_20051220" \
+			GSI_VERSION KRB5_VERSION MGLUE_VERSION
