diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/Makefile.in openssh-3.6.1p2/Makefile.in
--- openssh-3.6.1p2.orig/Makefile.in	Tue Apr 29 10:12:08 2003
+++ openssh-3.6.1p2/Makefile.in	Wed Apr 30 10:12:45 2003
@@ -67,7 +67,7 @@
 	key.o dispatch.o kex.o mac.o uuencode.o misc.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 \
-	entropy.o
+	entropy.o kexgssc.o gss-genr.o
 
 SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
 	sshconnect.o sshconnect1.o sshconnect2.o
@@ -79,8 +79,9 @@
 	auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
 	auth2-none.o auth2-passwd.o auth2-pubkey.o \
 	monitor_mm.o monitor.o monitor_wrap.o monitor_fdpass.o \
-	kexdhs.o kexgexs.o \
-	auth-krb5.o auth-krb4.o \
+	kexdhs.o kexgexs.o kexgsss.o \
+	auth-krb5.o auth-krb4.o auth2-gss.o \
+	gss-serv.o gss-serv-krb5.o gss-serv-gsi.o \
 	loginrec.o auth-pam.o auth2-pam.o auth-sia.o md5crypt.o
 
 MANPAGES	= scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/acconfig.h openssh-3.6.1p2/acconfig.h
--- openssh-3.6.1p2.orig/acconfig.h	Mon Mar 10 00:38:10 2003
+++ openssh-3.6.1p2/acconfig.h	Wed Apr 30 10:12:45 2003
@@ -201,6 +201,9 @@
 /* Define if compiler implements __func__ */
 #undef HAVE___func__
 
+/* Define this is you want GSSAPI support in the version 2 protocol */
+#undef GSSAPI
+
 /* Define if you want Kerberos 5 support */
 #undef KRB5
 
@@ -212,6 +215,9 @@
 
 /* Define if you want AFS support */
 #undef AFS
+
+/* Define if you want GSI/Globus authentication support */
+#undef GSI
 
 /* Define if you want S/Key support */
 #undef SKEY
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/auth-pam.c openssh-3.6.1p2/auth-pam.c
--- openssh-3.6.1p2.orig/auth-pam.c	Tue Apr 29 10:12:08 2003
+++ openssh-3.6.1p2/auth-pam.c	Wed Apr 30 10:12:45 2003
@@ -423,6 +423,26 @@
 	}
 }
 
+/* Set a PAM environment string. We need to do this so that the session
+ * modules can handle things like Kerberos/GSI credentials that appear
+ * during the ssh authentication process.
+ */
+
+int do_pam_putenv(char *name, char *value) {
+	char *compound;
+	int ret=1;
+
+#ifdef HAVE_PAM_PUTENV	
+	compound=xmalloc(strlen(name)+strlen(value)+2);
+	if (compound) {
+		sprintf(compound,"%s=%s",name,value);
+		ret=pam_putenv(__pamh,compound);
+		xfree(compound);
+	}
+#endif
+	return(ret);
+}
+
 /* Print any messages that have been generated during authentication */
 /* or account checking to stderr */
 void print_pam_messages(void)
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/auth-pam.h openssh-3.6.1p2/auth-pam.h
--- openssh-3.6.1p2.orig/auth-pam.h	Tue Jul 23 01:44:07 2002
+++ openssh-3.6.1p2/auth-pam.h	Wed Apr 30 10:12:45 2003
@@ -44,6 +44,7 @@
 int is_pam_password_change_required(void);
 void do_pam_chauthtok(void);
 void do_pam_set_conv(struct pam_conv *);
+int do_pam_putenv(char *, char *);
 void message_cat(char **p, const char *a);
 
 #endif /* USE_PAM */
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/auth.c openssh-3.6.1p2/auth.c
--- openssh-3.6.1p2.orig/auth.c	Sat Jan 18 05:24:06 2003
+++ openssh-3.6.1p2/auth.c	Wed Apr 30 10:12:45 2003
@@ -263,7 +263,7 @@
 	    authmsg,
 	    method,
 	    authctxt->valid ? "" : "illegal user ",
-	    authctxt->user,
+	    (authctxt->user[0]) ? authctxt->user : "<implicit>",
 	    get_remote_ipaddr(),
 	    get_remote_port(),
 	    info);
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/auth.h openssh-3.6.1p2/auth.h
--- openssh-3.6.1p2.orig/auth.h	Fri Sep 27 04:26:01 2002
+++ openssh-3.6.1p2/auth.h	Wed Apr 30 10:12:45 2003
@@ -70,6 +70,7 @@
 	krb5_principal	 krb5_user;
 	char		*krb5_ticket_file;
 #endif
+	void *methoddata;
 };
 
 struct Authmethod {
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/auth2-gss.c openssh-3.6.1p2/auth2-gss.c
--- openssh-3.6.1p2.orig/auth2-gss.c	Thu Jan  1 01:00:00 1970
+++ openssh-3.6.1p2/auth2-gss.c	Wed Apr 30 10:12:46 2003
@@ -0,0 +1,273 @@
+/*
+ * 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
+#include "auth.h"
+#include "ssh2.h"
+#include "xmalloc.h"
+#include "log.h"
+#include "dispatch.h"
+#include "servconf.h"
+#include "compat.h"
+#include "packet.h"
+#include "monitor_wrap.h"
+
+#include "ssh-gss.h"
+
+extern ServerOptions options;
+
+static int
+userauth_external(Authctxt *authctxt)
+{
+        packet_check_eom();
+
+        return(PRIVSEP(ssh_gssapi_userok(authctxt->user)));
+}
+
+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_exchange_complete(int type, u_int32_t plen, void *ctxt);
+static void input_gssapi_errtok(int, u_int32_t, void *);
+
+/* We only support those mechanisms that we know about (ie ones that we know
+ * how to check local user kuserok and the like
+ */
+static int
+userauth_gssapi(Authctxt *authctxt)
+{
+        gss_OID_desc    oid= {0,NULL};
+        Gssctxt         *ctxt = NULL;
+        int             mechs;
+        gss_OID_set     supported;
+        int             present;
+        OM_uint32       ms;
+        u_int           len;
+        char *		doid = NULL;
+        
+        if (!authctxt->valid || authctxt->user == NULL)
+                return 0;
+                
+        if (datafellows & SSH_OLD_GSSAPI) {
+                debug("Early drafts of GSSAPI userauth not supported");
+                return 0;
+        }
+        
+        mechs=packet_get_int();
+        if (mechs==0) {
+                debug("Mechanism negotiation is not supported");
+                return 0;
+        }
+
+        ssh_gssapi_supported_oids(&supported);
+        do {
+                mechs--;
+                
+                if (doid)
+                        xfree(doid);
+                
+                debug("Trying to get OID string");
+                doid = packet_get_string(&len);
+                debug("Got string");
+                
+               	if (doid[0]!=0x06 || doid[1]!=len-2) {
+               		log("Mechanism OID received using the old encoding form");
+               		oid.elements = doid;
+               		oid.length = len;
+               	} else {
+               		oid.elements = doid + 2;
+               		oid.length   = len - 2;
+               	}
+            	gss_test_oid_set_member(&ms, &oid, supported, &present);
+        } while (mechs>0 && !present);
+        
+        if (!present) {
+                xfree(doid);
+                return(0);
+        }
+                
+	if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt,&oid)))) {
+		ssh_gssapi_userauth_error(ctxt);
+		return(0);
+	}
+	
+        authctxt->methoddata=(void *)ctxt;
+
+        /* Send SSH_MSG_USERAUTH_GSSAPI_RESPONSE */
+
+       	packet_start(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE);
+
+	/* Just return whatever they sent */
+	packet_put_string(doid,len);
+       	
+        packet_send();
+        packet_write_wait();
+        xfree(doid);
+
+        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, 
+                     &input_gssapi_token);
+        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,
+        	     &input_gssapi_errtok);
+        authctxt->postponed = 1;
+        
+        return 0;
+}
+
+static void
+input_gssapi_token(int type, u_int32_t plen, void *ctxt)
+{
+        Authctxt *authctxt = ctxt;
+        Gssctxt *gssctxt;
+        gss_buffer_desc send_tok,recv_tok;
+        OM_uint32 maj_status, min_status;
+	u_int len;
+        
+        if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
+                fatal("No authentication or GSSAPI context");
+                
+        gssctxt=authctxt->methoddata;
+        recv_tok.value=packet_get_string(&len);
+        recv_tok.length=len; /* u_int vs. size_t */
+        
+        maj_status=PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok, 
+        					 &send_tok, NULL));
+        packet_check_eom();
+        
+        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);
+        	        packet_send();
+               		packet_write_wait();
+               	}
+                authctxt->postponed = 0;
+                dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+                userauth_finish(authctxt, 0, "gssapi");
+        } else {
+               	if (send_tok.length != 0) {
+               		packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
+               		packet_put_string(send_tok.value,send_tok.length);
+               		packet_send();
+               		packet_write_wait();
+                }
+	        if (maj_status == GSS_S_COMPLETE) {
+        	        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,NULL);
+                	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
+                             	     &input_gssapi_exchange_complete);
+                }
+        }
+        
+        gss_release_buffer(&min_status, &send_tok);        
+}
+
+static void
+input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
+{
+        Authctxt *authctxt = ctxt;
+        Gssctxt *gssctxt;
+        gss_buffer_desc send_tok,recv_tok;
+        OM_uint32 maj_status;
+        
+        if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
+                fatal("No authentication or GSSAPI context");
+                
+        gssctxt=authctxt->methoddata;
+        recv_tok.value=packet_get_string(&recv_tok.length);
+        
+        /* Push the error token into GSSAPI to see what it says */
+        maj_status=PRIVSEP(ssh_gssapi_accept_ctx(gssctxt, &recv_tok, 
+        					 &send_tok, NULL));
+        packet_check_eom();
+
+	/* We can't return anything to the client, even if we wanted to */
+	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,NULL);
+
+	/* The client will have already moved on to the next auth */
+	
+}
+
+/* This is called when the client thinks we've completed authentication.
+ * It should only be enabled in the dispatch handler by the function above,
+ * which only enables it once the GSSAPI exchange is complete.
+ */
+ 
+static void
+input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
+{
+        Authctxt *authctxt = ctxt;
+        Gssctxt *gssctxt;
+        int authenticated;
+        
+	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
+                fatal("No authentication or GSSAPI context");
+                
+        gssctxt=authctxt->methoddata;
+        
+	/* We don't need to check the status, because the stored credentials
+	 * which userok uses are only populated once the context init step
+	 * has returned complete.
+	 */
+
+        authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+
+        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_EXCHANGE_COMPLETE, NULL);
+        userauth_finish(authctxt, authenticated, "gssapi");
+}
+
+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_gssapi = {
+        "gssapi",
+        userauth_gssapi,
+        &options.gss_authentication
+};
+
+#endif /* GSSAPI */
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/auth2.c openssh-3.6.1p2/auth2.c
--- openssh-3.6.1p2.orig/auth2.c	Mon Feb 24 00:59:27 2003
+++ openssh-3.6.1p2/auth2.c	Wed Apr 30 10:12:46 2003
@@ -36,6 +36,10 @@
 #include "pathnames.h"
 #include "monitor_wrap.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 /* import */
 extern ServerOptions options;
 extern u_char *session_id2;
@@ -50,9 +54,15 @@
 extern Authmethod method_passwd;
 extern Authmethod method_kbdint;
 extern Authmethod method_hostbased;
+extern Authmethod method_external;
+extern Authmethod method_gssapi;
 
 Authmethod *authmethods[] = {
 	&method_none,
+#ifdef GSSAPI
+	&method_external,
+	&method_gssapi,
+#endif
 	&method_pubkey,
 	&method_passwd,
 	&method_kbdint,
@@ -180,6 +190,12 @@
 	}
 	/* reset state */
 	auth2_challenge_stop(authctxt);
+
+#ifdef GSSAPI
+	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
+	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
+#endif
+
 	authctxt->postponed = 0;
 
 	/* try to authenticate user */
Common subdirectories: openssh-3.6.1p2.orig/autom4te.cache and openssh-3.6.1p2/autom4te.cache
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/compat.c openssh-3.6.1p2/compat.c
--- openssh-3.6.1p2.orig/compat.c	Tue Apr  1 12:44:37 2003
+++ openssh-3.6.1p2/compat.c	Wed Apr 30 10:12:46 2003
@@ -71,15 +71,21 @@
 		{ "OpenSSH_2.5.0p1*,"
 		  "OpenSSH_2.5.1p1*",
 					SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
-					SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
+					SSH_BUG_NOREKEY|SSH_BUG_EXTEOF|
+					SSH_OLD_GSSAPI},
 		{ "OpenSSH_2.5.0*,"
 		  "OpenSSH_2.5.1*,"
 		  "OpenSSH_2.5.2*",	SSH_OLD_DHGEX|SSH_BUG_NOREKEY|
 					SSH_BUG_EXTEOF},
 		{ "OpenSSH_2.5.3*",	SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
+		{ "OpenSSH_2.9p*",	SSH_BUG_EXTEOF|SSH_OLD_GSSAPI},
 		{ "OpenSSH_2.*,"
 		  "OpenSSH_3.0*,"
-		  "OpenSSH_3.1*",	SSH_BUG_EXTEOF},
+		  "OpenSSH_3.1*",	SSH_BUG_EXTEOF|SSH_BUG_GSSAPI_BER},
+		{ "OpenSSH_3.2*,"
+		  "OpenSSH_3.3*,"
+		  "OpenSSH_3.4*,"
+		  "OpenSSH_3.5*",	SSH_BUG_GSSAPI_BER},
 		{ "Sun_SSH_1.0*",	SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
 		{ "OpenSSH*",		0 },
 		{ "*MindTerm*",		0 },
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/compat.h openssh-3.6.1p2/compat.h
--- openssh-3.6.1p2.orig/compat.h	Tue Apr  1 12:44:37 2003
+++ openssh-3.6.1p2/compat.h	Wed Apr 30 10:12:46 2003
@@ -56,6 +56,8 @@
 #define SSH_BUG_K5USER		0x00400000
 #define SSH_BUG_PROBE		0x00800000
 #define SSH_BUG_FIRSTKEX	0x01000000
+#define SSH_OLD_GSSAPI		0x02000000
+#define SSH_BUG_GSSAPI_BER	0x04000000
 
 void     enable_compat13(void);
 void     enable_compat20(void);
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/configure.ac openssh-3.6.1p2/configure.ac
--- openssh-3.6.1p2.orig/configure.ac	Tue Apr 29 10:12:08 2003
+++ openssh-3.6.1p2/configure.ac	Wed Apr 30 10:12:46 2003
@@ -741,6 +741,7 @@
 			AC_CHECK_LIB(dl, dlopen, , )
 			AC_CHECK_LIB(pam, pam_set_item, , AC_MSG_ERROR([*** libpam missing]))
 			AC_CHECK_FUNCS(pam_getenvlist)
+			AC_CHECK_FUNCS(pam_putenv)
 
 			disable_shadow=yes
 			PAM_MSG="yes"
@@ -751,6 +752,7 @@
 			else
 				LIBPAM="-lpam"
 			fi
+
 			AC_SUBST(LIBPAM)
 		fi
 	]
@@ -781,6 +783,47 @@
 	AC_CHECK_LIB(crypt, crypt)
 fi
 
+# Start of GSI/Globus 2.0 mods
+# Check whether the user wants GSI (Globus 2.0) support
+# if we are using GSI, we will also use the 
+# OPenSSL that is built by Globus. This is called
+# -lcrypto_FLAVOR
+# and it will be in the GSI path. 
+# The includes will be in the include/FLAVOR/openssl
+# therfore we will not process the -with-ssl parameter.
+
+gsi_path="no"
+AC_ARG_WITH(gsi,
+    [  --with-gsi=PATH         Enable GSI/Globus GSSAPI support],
+    [
+        gsi_path="$withval"
+    ]
+)
+
+gsi_flavor=gcc32dbg
+AC_ARG_WITH(gsi-flavor,
+      [  --with-gsi-flavor=FLAVOR Globus build flavor ],
+      [
+              gsi_flavor="$withval"
+      ]
+)
+
+if test "x$gsi_path" != "xno" ; then
+    # Globus GSSAPI configuration
+    AC_DEFINE(GSSAPI)
+    AC_DEFINE(GSI)
+      AC_DEFINE(HAVE_OPENSSL)
+      LDFLAGS="$LDFLAGS -L${gsi_path}/lib"
+    if test ! -z "$need_dash_r" ; then
+        LDFLAGS="$LDFLAGS -R${gsi_path}/lib"
+    fi
+    if test ! -z "$blibpath" ; then
+        blibpath="$blibpath:${gsi_path}/lib"
+    fi
+      LIBS="$LIBS -lcrypto_${gsi_flavor} -lglobus_gss_assist_${gsi_flavor} -lglobus_gssapi_gsi_${gsi_flavor}"
+      CPPFLAGS="$CPPFLAGS -I${gsi_path}/include -I${gsi_path}/include/${gsi_flavor}"
+else
+
 # Search for OpenSSL
 saved_CPPFLAGS="$CPPFLAGS"
 saved_LDFLAGS="$LDFLAGS"
@@ -915,6 +958,8 @@
 	AC_CHECK_LIB(crypt, crypt, LIBS="$LIBS -lcrypt")
 fi
 
+fi
+#end of GSI/Globus 2.0 mods
 
 ### Configure cryptographic random number support
 
@@ -1835,6 +1880,31 @@
                                 blibpath="$blibpath:${KRB5ROOT}/lib"
                         fi
                         AC_CHECK_LIB(resolv, dn_expand, , )
+
+			AC_CHECK_LIB(gssapi,gss_init_sec_context,
+				[ AC_DEFINE(GSSAPI)
+				  K5LIBS="-lgssapi $K5LIBS" ],
+				[ AC_CHECK_LIB(gssapi_krb5,gss_init_sec_context,
+					[ AC_DEFINE(GSSAPI)
+				  	  K5LIBS="-lgssapi_krb5 $K5LIBS" ],
+					AC_MSG_WARN([Cannot find any suitable gss-api library - build may fail]),
+					$K5LIBS)
+				],
+				$K5LIBS)
+			
+			AC_CHECK_HEADER(gssapi.h, ,
+				[ unset ac_cv_header_gssapi_h
+				  CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" 
+				  AC_CHECK_HEADERS(gssapi.h, ,
+					AC_MSG_WARN([Cannot find any suitable gss-api header - build may fail])
+				  ) 
+				]
+			)
+
+			oldCPP="$CPPFLAGS"
+			CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
+			AC_CHECK_HEADER(gssapi_krb5.h, ,
+					[ CPPFLAGS="$oldCPP" ])
 
                         KRB5=yes
                 fi
Common subdirectories: openssh-3.6.1p2.orig/contrib and openssh-3.6.1p2/contrib
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/gss-genr.c openssh-3.6.1p2/gss-genr.c
--- openssh-3.6.1p2.orig/gss-genr.c	Thu Jan  1 01:00:00 1970
+++ openssh-3.6.1p2/gss-genr.c	Wed Apr 30 10:12:46 2003
@@ -0,0 +1,461 @@
+/*
+ * 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
+
+#include "ssh.h"
+#include "ssh2.h"
+#include "xmalloc.h"
+#include "buffer.h"
+#include "bufaux.h"
+#include "packet.h"
+#include "compat.h"
+#include <openssl/evp.h>
+#include "cipher.h"
+#include "kex.h"
+#include "log.h"
+#include "compat.h"
+#include "monitor_wrap.h"
+
+#include <netdb.h>
+
+#include "ssh-gss.h"
+
+typedef struct {
+	char *encoded;
+	gss_OID oid;
+} ssh_gss_kex_mapping;
+	
+static ssh_gss_kex_mapping *gss_enc2oid;
+
+/* Return a list of the gss-group1-sha1-x mechanisms supported by this
+ * program.
+ *
+ * On the client side, we don't need to worry about whether we 'know'
+ * about the mechanism or not - we assume that any mechanism that we've been
+ * linked against is suitable for inclusion.
+ *
+ * XXX - We might want to make this configurable in the future, so as to
+ * XXX - allow the user control over which mechanisms to use.
+ */
+ 
+char * 
+ssh_gssapi_client_mechanisms(char *host) {
+	gss_OID_set 	supported;
+	OM_uint32	min_status;
+	Buffer		buf;
+	int 		i = 0;
+	char 		*mechs;
+	char		*encoded;
+	int		enclen;
+	char		digest[EVP_MAX_MD_SIZE];
+	char		deroid[2];
+	const EVP_MD	*evp_md = EVP_md5();
+	EVP_MD_CTX	md;
+	int 		oidpos=0;
+	
+	if (datafellows & SSH_OLD_GSSAPI) return NULL;
+	
+	gss_indicate_mechs(&min_status,&supported);
+	if (datafellows & SSH_BUG_GSSAPI_BER) {
+		gss_enc2oid=xmalloc(sizeof(ssh_gss_kex_mapping)
+					*((supported->count*2)+1));
+	} else {
+		gss_enc2oid=xmalloc(sizeof(ssh_gss_kex_mapping)
+					*(supported->count+1));
+	}
+	
+	buffer_init(&buf);
+
+
+	for (i=0;i<supported->count;i++) {
+
+		gss_enc2oid[oidpos].encoded=NULL;
+		
+		if (supported->elements[i].length<128 &&
+		    ssh_gssapi_check_mechanism(&(supported->elements[i]),host)) {
+
+			/* Earlier versions of this code interpreted the
+			 * spec incorrectly with regard to OID encoding. They
+			 * also mis-encoded the krb5 OID. The following
+			 * _temporary_ code interfaces with these broken
+			 * servers */
+
+			if (datafellows & SSH_BUG_GSSAPI_BER) {
+				char *bodge=NULL;
+				gss_OID_desc krb5oid={9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"};
+				gss_OID_desc gsioid={9, "\x2B\x06\x01\x04\x01\x9B\x50\x01\x01"};
+				
+				if (supported->elements[i].length==krb5oid.length &&
+				    memcmp(supported->elements[i].elements,
+				    	   krb5oid.elements, krb5oid.length)==0) {
+					bodge="Se3H81ismmOC3OE+FwYCiQ==";
+				}
+				
+				if (supported->elements[i].length==gsioid.length &&
+				    memcmp(supported->elements[i].elements,
+				    	   gsioid.elements, gsioid.length)==0) {
+					bodge="N3+k7/4wGxHyuP8Yxi4RhA==";
+				}
+
+				if (bodge) {				
+					if (oidpos!=0) {
+						buffer_put_char(&buf,',');
+					}
+				
+					buffer_append(&buf, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1);
+					buffer_append(&buf, bodge, strlen(bodge));
+
+					gss_enc2oid[oidpos].oid=&(supported->elements[i]);
+					gss_enc2oid[oidpos].encoded=bodge;
+			
+					oidpos++;
+				}
+			}
+			
+			/* Add the required DER encoding octets and MD5 hash */
+			deroid[0]=0x06; /* Object Identifier */
+			deroid[1]=supported->elements[i].length;
+
+			EVP_DigestInit(&md, evp_md);
+			EVP_DigestUpdate(&md,deroid,2);
+			EVP_DigestUpdate(&md,
+					 supported->elements[i].elements,
+					 supported->elements[i].length);
+			EVP_DigestFinal(&md, digest, NULL);
+			
+			/* Base64 encode it */
+			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_SHA1, sizeof(KEX_GSS_SHA1)-1);
+			buffer_append(&buf, encoded, enclen);
+
+			debug("Mechanism encoded as %s",encoded);
+
+			gss_enc2oid[oidpos].oid=&(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)
+		return(NULL);
+	else
+		return(mechs);
+}
+
+gss_OID
+ssh_gssapi_client_id_kex(Gssctxt *ctx, char *name) {
+	int i=0;
+	
+	if (strncmp(name, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1) !=0) {
+		return(NULL);
+	}
+	
+	name+=sizeof(KEX_GSS_SHA1)-1; /* Move to the start of the ID string */
+	
+	while (gss_enc2oid[i].encoded!=NULL &&
+	       	strcmp(name,gss_enc2oid[i].encoded)!=0) {
+	      	i++;
+	}
+	
+	if (gss_enc2oid[i].oid!=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) {
+  
+  return (ctx!=NULL && ctx->oid != GSS_C_NO_OID && 
+  	  ctx->oid->length == len &&
+  	  memcmp(ctx->oid->elements,data,len)==0);
+}
+  	
+/* Set the contexts OID from a data stream */
+void ssh_gssapi_set_oid_data(Gssctxt *ctx, void *data, size_t len) { 
+  if (ctx->oid != GSS_C_NO_OID) {
+	xfree(ctx->oid->elements);
+   	xfree(ctx->oid);
+  }
+  ctx->oid=xmalloc(sizeof(gss_OID_desc));
+  ctx->oid->length=len;
+  ctx->oid->elements=xmalloc(len);
+  memcpy(ctx->oid->elements,data,len);
+}
+
+/* Set the contexts OID */
+void ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid) {  
+  ssh_gssapi_set_oid_data(ctx,oid->elements,oid->length);
+}
+
+/* All this effort to report an error ... */
+
+void
+ssh_gssapi_error(Gssctxt *ctxt) {
+	
+	debug(ssh_gssapi_last_error(ctxt,NULL,NULL));
+}
+
+char *
+ssh_gssapi_last_error(Gssctxt *ctxt, 
+		      OM_uint32 *major_status, OM_uint32 *minor_status) {
+	OM_uint32 lmin;
+        gss_buffer_desc msg;
+        OM_uint32 ctx;
+        Buffer b;
+        char *ret;
+        
+        buffer_init(&b);
+
+	if (major_status!=NULL) *major_status=ctxt->major;
+	if (minor_status!=NULL) *minor_status=ctxt->minor;
+	
+        ctx = 0;
+	/* The GSSAPI error */
+        do {
+        	gss_display_status(&lmin, ctxt->major,
+        			   GSS_C_GSS_CODE, GSS_C_NULL_OID,
+        		           &ctx, &msg);
+
+        	buffer_append(&b,msg.value,msg.length);
+        	buffer_put_char(&b,'\n');
+        	
+       	    	gss_release_buffer(&lmin, &msg);
+        } while (ctx!=0);
+
+        /* The mechanism specific error */
+        do {
+        	gss_display_status(&lmin, ctxt->minor,
+        			   GSS_C_MECH_CODE, GSS_C_NULL_OID,
+        			   &ctx, &msg);
+        	
+        	buffer_append(&b,msg.value,msg.length);
+        	buffer_put_char(&b,'\n');
+        	
+        	gss_release_buffer(&lmin, &msg);
+        } while (ctx!=0);
+        
+        buffer_put_char(&b,'\0');
+        ret=xmalloc(buffer_len(&b));
+        buffer_get(&b,ret,buffer_len(&b));
+        buffer_free(&b);
+        return(ret);
+}
+
+/* Initialise our GSSAPI context. We use this opaque structure to contain all
+ * of the data which both the client and server need to persist across
+ * {accept,init}_sec_context calls, so that when we do it from the userauth
+ * stuff life is a little easier
+ */
+void
+ssh_gssapi_build_ctx(Gssctxt **ctx)
+{
+	*ctx=xmalloc(sizeof (Gssctxt));
+	(*ctx)->major=0;
+	(*ctx)->minor=0;
+	(*ctx)->context=GSS_C_NO_CONTEXT;
+	(*ctx)->name=GSS_C_NO_NAME;
+	(*ctx)->oid=GSS_C_NO_OID;
+	(*ctx)->creds=GSS_C_NO_CREDENTIAL;
+	(*ctx)->client=GSS_C_NO_NAME;
+	(*ctx)->client_creds=GSS_C_NO_CREDENTIAL;
+}
+
+/* Delete our context, providing it has been built correctly */
+void
+ssh_gssapi_delete_ctx(Gssctxt **ctx)
+{
+	OM_uint32 ms;
+	
+	/* Return if there's no context */
+	if ((*ctx)==NULL)
+		return;
+		
+	if ((*ctx)->context != GSS_C_NO_CONTEXT) 
+		gss_delete_sec_context(&ms,&(*ctx)->context,GSS_C_NO_BUFFER);
+	if ((*ctx)->name != GSS_C_NO_NAME)
+		gss_release_name(&ms,&(*ctx)->name);
+	if ((*ctx)->oid != GSS_C_NO_OID) {
+		xfree((*ctx)->oid->elements);
+		xfree((*ctx)->oid);
+		(*ctx)->oid = GSS_C_NO_OID;
+	}
+	if ((*ctx)->creds != GSS_C_NO_CREDENTIAL)
+		gss_release_cred(&ms,&(*ctx)->creds);
+	if ((*ctx)->client != GSS_C_NO_NAME)
+		gss_release_name(&ms,&(*ctx)->client);	
+	if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL)
+		gss_release_cred(&ms,&(*ctx)->client_creds);
+	
+	xfree(*ctx);
+	*ctx=NULL; 
+}
+
+/* Wrapper to init_sec_context 
+ * Requires that the context contains:
+ *	oid
+ * 	server name (from ssh_gssapi_import_name)
+ */
+OM_uint32 
+ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok,
+       	      	    gss_buffer_desc* send_tok, OM_uint32 *flags) 
+{
+	int deleg_flag = 0;
+	
+	if (deleg_creds) {
+		deleg_flag=GSS_C_DELEG_FLAG;
+		debug("Delegating credentials");
+	}
+	      	
+      	ctx->major=gss_init_sec_context(&ctx->minor,
+      					GSS_C_NO_CREDENTIAL, /* def. cred */
+      					&ctx->context,
+      					ctx->name,
+      					ctx->oid,
+      					GSS_C_MUTUAL_FLAG |
+      					GSS_C_INTEG_FLAG |
+      					deleg_flag,
+      					0, /* default lifetime */
+      					NULL, /* no channel bindings */
+      					recv_tok,
+      					NULL,
+      					send_tok,
+      					flags,
+      					NULL);
+      	if (GSS_ERROR(ctx->major)) {
+      		ssh_gssapi_error(ctx);
+      	}
+      	return(ctx->major);
+}
+
+/* Create a service name for the given host */
+OM_uint32
+ssh_gssapi_import_name(Gssctxt *ctx, const char *host) {
+	gss_buffer_desc gssbuf;
+
+        gssbuf.length = sizeof("host@")+strlen(host);
+
+        gssbuf.value = xmalloc(gssbuf.length);
+        if (gssbuf.value == NULL) {
+		return(-1);
+        }
+        snprintf(gssbuf.value,gssbuf.length,"host@%s",host);
+        if ((ctx->major=gss_import_name(&ctx->minor,
+                                   	&gssbuf,
+                                        GSS_C_NT_HOSTBASED_SERVICE,
+                                        &ctx->name))) {
+		ssh_gssapi_error(ctx);
+	}
+	
+	xfree(gssbuf.value);
+	return(ctx->major);
+}
+
+/* Acquire credentials for a server running on the current host.
+ * Requires that the context structure contains a valid OID
+ */
+ 
+/* Returns a GSSAPI error code */
+OM_uint32
+ssh_gssapi_acquire_cred(Gssctxt *ctx) {
+	OM_uint32 status;
+	char lname[MAXHOSTNAMELEN];
+	gss_OID_set oidset;
+	
+	gss_create_empty_oid_set(&status,&oidset);
+	gss_add_oid_set_member(&status,ctx->oid,&oidset);
+	
+        if (gethostname(lname, MAXHOSTNAMELEN)) {
+                return(-1);
+        }
+
+	if (GSS_ERROR(ssh_gssapi_import_name(ctx,lname))) {
+		return(ctx->major);
+	}
+	
+	if ((ctx->major=gss_acquire_cred(&ctx->minor,
+			 	    ctx->name,
+				    0,
+				    oidset,
+				    GSS_C_ACCEPT,
+				    &ctx->creds,
+				    NULL,
+				    NULL))) {
+		ssh_gssapi_error(ctx);
+	}
+				
+	gss_release_oid_set(&status, &oidset);
+	return(ctx->major);
+}
+
+OM_uint32
+ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *buffer, gss_buffer_desc *hash) {
+	
+	if ((ctx->major=gss_get_mic(&ctx->minor,ctx->context,
+				    GSS_C_QOP_DEFAULT, buffer, hash))) {
+		ssh_gssapi_error(ctx);
+	}
+	
+	return(ctx->major);
+}
+
+OM_uint32
+ssh_gssapi_server_ctx(Gssctxt **ctx,gss_OID oid) {
+	if (*ctx) ssh_gssapi_delete_ctx(ctx);
+	ssh_gssapi_build_ctx(ctx);
+	ssh_gssapi_set_oid(*ctx,oid);
+	return(ssh_gssapi_acquire_cred(*ctx));
+}
+
+int
+ssh_gssapi_check_mechanism(gss_OID oid, char *host) {
+	Gssctxt * ctx = NULL;
+	gss_buffer_desc token;
+	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 -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/gss-serv-gsi.c openssh-3.6.1p2/gss-serv-gsi.c
--- openssh-3.6.1p2.orig/gss-serv-gsi.c	Thu Jan  1 01:00:00 1970
+++ openssh-3.6.1p2/gss-serv-gsi.c	Wed Apr 30 10:12:46 2003
@@ -0,0 +1,164 @@
+/*
+ * 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"
+
+#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_old = {
+	"N3+k7/4wGxHyuP8Yxi4RhA==",
+	"GSI",
+	{9, "\x2B\x06\x01\x04\x01\x9B\x50\x01\x01"},
+	NULL,
+	&ssh_gssapi_gsi_userok,
+	&ssh_gssapi_gsi_localname,
+	&ssh_gssapi_gsi_storecreds
+};
+
+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->name.value,
+					   name) == 0);
+    
+    log("GSI user %s is%s authorized as target user %s",
+	(char *) client->name.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->name.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) {
+	    log("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
+	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 -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/gss-serv-krb5.c openssh-3.6.1p2/gss-serv-krb5.c
--- openssh-3.6.1p2.orig/gss-serv-krb5.c	Thu Jan  1 01:00:00 1970
+++ openssh-3.6.1p2/gss-serv-krb5.c	Wed Apr 30 10:12:46 2003
@@ -0,0 +1,261 @@
+/*
+ * 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 KRB5
+
+#include "auth.h"
+#include "auth-pam.h"
+#include "xmalloc.h"
+#include "log.h"
+#include "servconf.h"
+
+#include "ssh-gss.h"
+
+extern ServerOptions options;
+
+#ifdef HEIMDAL
+#include <krb5.h>
+#else
+#include <gssapi_krb5.h>
+#define krb5_get_err_text(context,code) error_message(code)
+#endif
+
+static krb5_context krb_context = NULL;
+
+/* Initialise the krb5 library, so we can use it for those bits that
+ * GSSAPI won't do */
+
+static int 
+ssh_gssapi_krb5_init() {
+	krb5_error_code problem;
+	
+	if (krb_context !=NULL)
+		return 1;
+		
+	problem = krb5_init_context(&krb_context);
+	if (problem) {
+		log("Cannot initialize krb5 context");
+		return 0;
+	}
+	krb5_init_ets(krb_context);
+
+	return 1;	
+}			
+
+/* Check if this user is OK to login. This only works with krb5 - other 
+ * GSSAPI mechanisms will need their own.
+ * Returns true if the user is OK to log in, otherwise returns 0
+ */
+
+static int
+ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) {
+	krb5_principal princ;
+	int retval;
+
+	if (ssh_gssapi_krb5_init() == 0)
+		return 0;
+		
+	if ((retval=krb5_parse_name(krb_context, client->name.value, 
+				    &princ))) {
+		log("krb5_parse_name(): %.100s", 
+			krb5_get_err_text(krb_context,retval));
+		return 0;
+	}
+	if (krb5_kuserok(krb_context, princ, name)) {
+		retval = 1;
+		log("Authorized to %s, krb5 principal %s (krb5_kuserok)",name,
+		    (char *)client->name.value);
+	}
+	else
+		retval = 0;
+	
+	krb5_free_principal(krb_context, princ);
+	return retval;
+}
+
+/* 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->name.value, 
+				    &princ))) {
+		log("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);
+}
+	
+/* Make sure that this is called _after_ we've setuid to the user */
+
+/* This writes out any forwarded credentials. Its specific to the Kerberos
+ * GSSAPI mechanism
+ *
+ * We assume that our caller has made sure that the user has selected
+ * delegated credentials, and that the client_creds structure is correctly
+ * populated.
+ */
+
+static void
+ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) {
+	krb5_ccache ccache;
+	krb5_error_code problem;
+	krb5_principal princ;
+	char ccname[35];
+	static char name[40];
+	int tmpfd;
+	OM_uint32 maj_status,min_status;
+
+	if (client->creds==NULL) {
+		debug("No credentials stored"); 
+		return;
+	}
+		
+	if (ssh_gssapi_krb5_init() == 0)
+		return;
+
+	if (options.gss_use_session_ccache) {
+        	snprintf(ccname,sizeof(ccname),"/tmp/krb5cc_%d_XXXXXX",geteuid());
+       
+        	if ((tmpfd = mkstemp(ccname))==-1) {
+                	log("mkstemp(): %.100s", strerror(errno));
+                	return;
+        	}
+	        if (fchmod(tmpfd, S_IRUSR | S_IWUSR) == -1) {
+	               	log("fchmod(): %.100s", strerror(errno));
+	               	close(tmpfd);
+	               	return;
+	        }
+        } else {
+        	snprintf(ccname,sizeof(ccname),"/tmp/krb5cc_%d",geteuid());
+        	tmpfd = open(ccname, O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+        	if (tmpfd == -1) {
+        		log("open(): %.100s", strerror(errno));
+        		return;
+        	}
+        }
+
+       	close(tmpfd);
+        snprintf(name, sizeof(name), "FILE:%s",ccname);
+ 
+        if ((problem = krb5_cc_resolve(krb_context, name, &ccache))) {
+                log("krb5_cc_default(): %.100s", 
+                	krb5_get_err_text(krb_context,problem));
+                return;
+        }
+
+	if ((problem = krb5_parse_name(krb_context, client->name.value, 
+				       &princ))) {
+		log("krb5_parse_name(): %.100s", 
+			krb5_get_err_text(krb_context,problem));
+		krb5_cc_destroy(krb_context,ccache);
+		return;
+	}
+	
+	if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) {
+		log("krb5_cc_initialize(): %.100s", 
+			krb5_get_err_text(krb_context,problem));
+		krb5_free_principal(krb_context,princ);
+		krb5_cc_destroy(krb_context,ccache);
+		return;
+	}
+	
+	krb5_free_principal(krb_context,princ);
+
+	#ifdef HEIMDAL
+	if ((problem = krb5_cc_copy_cache(krb_context, 
+					   client->creds->ccache,
+					   ccache))) {
+		log("krb5_cc_copy_cache(): %.100s", 
+			krb5_get_err_text(krb_context,problem));
+		krb5_cc_destroy(krb_context,ccache);
+		return;
+	}
+	#else
+	if ((maj_status = gss_krb5_copy_ccache(&min_status, 
+					       client->creds, 
+					       ccache))) {
+		log("gss_krb5_copy_ccache() failed");
+		krb5_cc_destroy(krb_context,ccache);
+		return;
+	}
+	#endif
+	
+	krb5_cc_close(krb_context,ccache);
+
+#ifdef USE_PAM
+	do_pam_putenv("KRB5CCNAME",name);
+#endif
+
+	client->store.filename=strdup(ccname);
+	client->store.envvar="KRB5CCNAME";
+	client->store.envval=strdup(name);
+
+	return;
+}
+
+/* We've been using a wrongly encoded mechanism ID for yonks */
+
+ssh_gssapi_mech gssapi_kerberos_mech_old = {
+	"Se3H81ismmOC3OE+FwYCiQ==",
+	"Kerberos",
+	{9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"},
+	&ssh_gssapi_krb5_init,
+	&ssh_gssapi_krb5_userok,
+	&ssh_gssapi_krb5_localname,
+	&ssh_gssapi_krb5_storecreds
+};
+
+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
+};
+	
+#endif /* KRB5 */
+
+#endif /* GSSAPI */
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/gss-serv.c openssh-3.6.1p2/gss-serv.c
--- openssh-3.6.1p2.orig/gss-serv.c	Thu Jan  1 01:00:00 1970
+++ openssh-3.6.1p2/gss-serv.c	Wed Apr 30 10:12:46 2003
@@ -0,0 +1,388 @@
+/*
+ * 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
+
+#include "ssh.h"
+#include "ssh2.h"
+#include "xmalloc.h"
+#include "buffer.h"
+#include "bufaux.h"
+#include "packet.h"
+#include "compat.h"
+#include <openssl/evp.h>
+#include "cipher.h"
+#include "kex.h"
+#include "auth.h"
+#include "log.h"
+#include "channels.h"
+#include "session.h"
+#include "dispatch.h"
+#include "servconf.h"
+#include "compat.h"
+#include "monitor_wrap.h"
+
+#include "ssh-gss.h"
+
+extern ServerOptions options;
+extern u_char *session_id2;
+extern int session_id2_len;
+
+static ssh_gssapi_client gssapi_client =
+	{ {0,NULL}, GSS_C_NO_CREDENTIAL, NULL, {NULL,NULL,NULL}};
+
+ssh_gssapi_mech gssapi_null_mech 
+  = {NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
+
+#ifdef KRB5
+extern ssh_gssapi_mech gssapi_kerberos_mech;
+extern ssh_gssapi_mech gssapi_kerberos_mech_old;
+#endif
+#ifdef GSI
+extern ssh_gssapi_mech gssapi_gsi_mech;
+extern ssh_gssapi_mech gssapi_gsi_mech_old;
+#endif
+
+ssh_gssapi_mech* supported_mechs[]= {
+#ifdef KRB5
+  &gssapi_kerberos_mech,
+  &gssapi_kerberos_mech_old, /* Support for legacy clients */
+#endif
+#ifdef GSI
+  &gssapi_gsi_mech,
+  &gssapi_gsi_mech_old,	/* Support for legacy clients */
+#endif
+  &gssapi_null_mech,
+};
+
+/* Return a list of the gss-group1-sha1-x mechanisms supported by this
+ * program.
+ *
+ * We only support the mechanisms that we've indicated in the list above,
+ * but we check that they're supported by the GSSAPI mechanism on the 
+ * machine. We also check, before including them in the list, that
+ * we have the necesary information in order to carry out the key exchange
+ * (that is, that the user has credentials, the server's creds are accessible,
+ * etc)
+ *
+ * The way that this is done is fairly nasty, as we do a lot of work that
+ * is then thrown away. This should possibly be implemented with a cache
+ * that stores the results (in an expanded Gssctxt structure), which are
+ * then used by the first calls if that key exchange mechanism is chosen.
+ */
+
+/* Unpriviledged */ 
+char * 
+ssh_gssapi_server_mechanisms() {
+	gss_OID_set 	supported;
+	Gssctxt		*ctx = NULL;
+	OM_uint32	maj_status, min_status;
+	Buffer		buf;
+	int 		i = 0;
+	int		first = 0;
+	int		present;
+	char *		mechs;
+
+	if (datafellows & SSH_OLD_GSSAPI) return NULL;
+	
+	ssh_gssapi_supported_oids(&supported);
+	
+	buffer_init(&buf);
+
+	while(supported_mechs[i]->name != NULL) {
+		if ((maj_status=gss_test_oid_set_member(&min_status,
+						   	&supported_mechs[i]->oid,
+						   	supported,
+						   	&present))) {
+			present=0;
+		}
+
+		if (present) {
+		    if (!GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx,
+					    &supported_mechs[i]->oid)))) {
+			/* Append gss_group1_sha1_x to our list */
+			if (first++!=0)
+				buffer_put_char(&buf,',');
+			buffer_append(&buf, KEX_GSS_SHA1,
+				      sizeof(KEX_GSS_SHA1)-1);
+	        	buffer_append(&buf, 
+	        		      supported_mechs[i]->enc_name,
+        	      		      strlen(supported_mechs[i]->enc_name));
+			debug("GSSAPI mechanism %s (%s%s) supported",
+			      supported_mechs[i]->name, KEX_GSS_SHA1,
+			      supported_mechs[i]->enc_name);
+		    } else {
+			debug("no credentials for GSSAPI mechanism %s",
+			      supported_mechs[i]->name);
+		    }
+        	} else {
+		    debug("GSSAPI mechanism %s not supported",
+			  supported_mechs[i]->name);
+        	}
+        	ssh_gssapi_delete_ctx(&ctx);
+        	i++;
+	}
+	
+	buffer_put_char(&buf,'\0');
+	
+	mechs=xmalloc(buffer_len(&buf));
+	buffer_get(&buf,mechs,buffer_len(&buf));
+	buffer_free(&buf);
+	if (strlen(mechs)==0)
+	   return(NULL);
+	else
+	   return(mechs);
+}
+
+/* Unpriviledged */
+void ssh_gssapi_supported_oids(gss_OID_set *oidset) {
+	int i =0;
+	OM_uint32 maj_status,min_status;
+	int present;
+	gss_OID_set supported;
+	
+	gss_create_empty_oid_set(&min_status,oidset);
+	PRIVSEP(gss_indicate_mechs(&min_status, &supported));
+
+	while (supported_mechs[i]->name!=NULL) {
+		if ((maj_status=gss_test_oid_set_member(&min_status,
+						       &supported_mechs[i]->oid,
+						       supported,
+						       &present))) {
+			present=0;
+		}
+		if (present) {
+			gss_add_oid_set_member(&min_status,
+					       &supported_mechs[i]->oid,
+				       	       oidset);	
+		}
+		i++;
+	}
+}	
+
+/* Find out which GSS type (out of the list we define in ssh-gss.h) a
+ * particular connection is using 
+ */
+
+/* Priviledged (called ssh_gssapi_accept_ctx -> ssh_gssapi_getclient ->) */
+ssh_gssapi_mech *
+ssh_gssapi_get_ctype(Gssctxt *ctxt) {
+	int i=0;
+	
+	while(supported_mechs[i]->name!=NULL) {
+	    if (supported_mechs[i]->oid.length == ctxt->oid->length &&
+	      	(memcmp(supported_mechs[i]->oid.elements,
+			ctxt->oid->elements,ctxt->oid->length)==0)) {
+		return supported_mechs[i];
+	    }
+	   i++;
+	}
+	return NULL;
+}
+
+/* Return the OID that corresponds to the given context name */
+ 
+/* Unpriviledged */
+gss_OID 
+ssh_gssapi_server_id_kex(char *name) {
+  int i=0;
+  
+  if (strncmp(name, KEX_GSS_SHA1, sizeof(KEX_GSS_SHA1)-1) !=0) {
+     return(NULL);
+  }
+  
+  name+=sizeof(KEX_GSS_SHA1)-1; /* Move to the start of the MIME string */
+  
+  while (supported_mechs[i]->name!=NULL &&
+  	 strcmp(name,supported_mechs[i]->enc_name)!=0) {
+  	i++;
+  }
+
+  if (supported_mechs[i]->name==NULL)
+     return (NULL);
+
+  debug("using GSSAPI mechanism %s (%s%s)", supported_mechs[i]->name,
+	KEX_GSS_SHA1, supported_mechs[i]->enc_name);
+
+  return &supported_mechs[i]->oid;
+}
+
+/* Wrapper around accept_sec_context
+ * Requires that the context contains:
+ *    oid		
+ *    credentials	(from ssh_gssapi_acquire_cred)
+ */
+/* Priviledged */
+OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx,gss_buffer_desc *recv_tok,
+				gss_buffer_desc *send_tok, OM_uint32 *flags) 
+{
+	OM_uint32 status;
+	gss_OID mech;
+	
+	ctx->major=gss_accept_sec_context(&ctx->minor,
+					  &ctx->context,
+					  ctx->creds,
+					  recv_tok,
+					  GSS_C_NO_CHANNEL_BINDINGS,
+					  &ctx->client,
+					  &mech, /* read-only pointer */
+					  send_tok,
+					  flags,
+					  NULL,
+					  &ctx->client_creds);
+	if (GSS_ERROR(ctx->major)) {
+		ssh_gssapi_error(ctx);
+	}
+	
+	if (ctx->client_creds) {
+		debug("Received some client credentials");
+	} else {
+		debug("Got no client credentials");
+	}
+
+	/* FIXME: We should check that the me
+	 * the one that we asked for (in ctx->oid) */
+
+	status=ctx->major;
+	
+	/* Now, if we're complete and we have the right flags, then
+	 * we flag the user as also having been authenticated
+	 */
+	
+	if (((flags==NULL) || ((*flags & GSS_C_MUTUAL_FLAG) && 
+	                       (*flags & GSS_C_INTEG_FLAG))) &&
+	    (ctx->major == GSS_S_COMPLETE)) {
+		if (ssh_gssapi_getclient(ctx,&gssapi_client.mech,
+	  			         &gssapi_client.name,
+	  			         &gssapi_client.creds))
+	  		fatal("Couldn't convert client name");
+	}
+
+	/* Make sure that the getclient call hasn't stamped on this */
+	return(status);
+}
+
+/* Extract the client details from a given context. This can only reliably
+ * be called once for a context */
+
+/* Priviledged (called from accept_secure_ctx) */
+OM_uint32 
+ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_mech **type,
+		     gss_buffer_desc *name, gss_cred_id_t *creds) {
+
+	*type=ssh_gssapi_get_ctype(ctx);
+	if ((ctx->major=gss_display_name(&ctx->minor,ctx->client,name,NULL))) {
+		ssh_gssapi_error(ctx);
+		return(ctx->major);
+	}
+	
+	/* This is icky. There appears to be no way to copy this structure,
+	 * rather than the pointer to it, so we simply copy the pointer and
+	 * mark the originator as empty so we don't destroy it. 
+	 */
+	*creds=ctx->client_creds;
+	ctx->client_creds=GSS_C_NO_CREDENTIAL;
+	return(ctx->major);
+}
+
+/* As user - called through fatal cleanup hook */
+void
+ssh_gssapi_cleanup_creds(void *ignored)
+{
+	if (gssapi_client.store.filename!=NULL) {
+		/* Unlink probably isn't sufficient */
+		debug("removing gssapi cred file\"%s\"",gssapi_client.store.filename);
+		unlink(gssapi_client.store.filename);
+	}
+}
+
+/* As user */
+void 
+ssh_gssapi_storecreds()
+{
+	if (gssapi_client.mech && gssapi_client.mech->storecreds) {
+		(*gssapi_client.mech->storecreds)(&gssapi_client);
+		if (options.gss_cleanup_creds) {
+			fatal_add_cleanup(ssh_gssapi_cleanup_creds, NULL);
+		}
+	} else {
+		debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism");
+	}
+}
+
+/* This allows GSSAPI methods to do things to the childs environment based
+ * on the passed authentication process and credentials.
+ */
+/* As user */
+void 
+ssh_gssapi_do_child(char ***envp, u_int *envsizep) 
+{
+
+	if (gssapi_client.store.envvar!=NULL && 
+	    gssapi_client.store.envval!=NULL) {
+	    
+		debug("Setting %s to %s", gssapi_client.store.envvar,
+					  gssapi_client.store.envval);				  
+		child_set_env(envp, envsizep, gssapi_client.store.envvar, 
+					      gssapi_client.store.envval);
+	}
+}
+
+/* Priviledged */
+int
+ssh_gssapi_userok(char *user)
+{
+	if (gssapi_client.name.length==0 || 
+	    gssapi_client.name.value==NULL) {
+		debug("No suitable client data");
+		return 0;
+	}
+	if (gssapi_client.mech && gssapi_client.mech->userok) {
+		return((*gssapi_client.mech->userok)(&gssapi_client,user));
+	} else {
+		debug("ssh_gssapi_userok: Unknown GSSAPI mechanism");
+	}
+	return(0);
+}
+
+/* Priviledged */
+int
+ssh_gssapi_localname(char **user)
+{
+    	*user = NULL;
+	if (gssapi_client.name.length==0 || 
+	    gssapi_client.name.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 -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/kex.c openssh-3.6.1p2/kex.c
--- openssh-3.6.1p2.orig/kex.c	Tue Apr  1 12:44:37 2003
+++ openssh-3.6.1p2/kex.c	Wed Apr 30 10:12:46 2003
@@ -42,6 +42,10 @@
 #include "dispatch.h"
 #include "monitor.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 #define KEX_COOKIE_LEN	16
 
 /* prototype */
@@ -295,6 +299,10 @@
 		k->kex_type = KEX_DH_GRP1_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_SHA1, sizeof(KEX_GSS_SHA1)-1) == 0) {
+		k->kex_type = KEX_GSS_GRP1_SHA1;
+#endif
 	} else
 		fatal("bad kex alg %s", k->name);
 }
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/kex.h openssh-3.6.1p2/kex.h
--- openssh-3.6.1p2.orig/kex.h	Mon Feb 24 01:03:03 2003
+++ openssh-3.6.1p2/kex.h	Wed Apr 30 10:12:47 2003
@@ -57,6 +57,7 @@
 enum kex_exchange {
 	KEX_DH_GRP1_SHA1,
 	KEX_DH_GEX_SHA1,
+	KEX_GSS_GRP1_SHA1,
 	KEX_MAX
 };
 
@@ -95,6 +96,11 @@
 	Mac	mac;
 	Comp	comp;
 };
+
+struct KexOptions {
+	int	gss_deleg_creds;
+};
+
 struct Kex {
 	u_char	*session_id;
 	u_int	session_id_len;
@@ -110,6 +116,7 @@
 	int	flags;
 	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 *);
@@ -129,6 +136,10 @@
 void	 kexdh_server(Kex *);
 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,
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/kexgssc.c openssh-3.6.1p2/kexgssc.c
--- openssh-3.6.1p2.orig/kexgssc.c	Thu Jan  1 01:00:00 1970
+++ openssh-3.6.1p2/kexgssc.c	Wed Apr 30 10:12:47 2003
@@ -0,0 +1,253 @@
+/*
+ * 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
+
+#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 gssbuf,send_tok,recv_tok, msg_tok, *token_ptr;
+	Gssctxt *ctxt;
+	OM_uint32 maj_status, min_status, ret_flags;
+	unsigned int klen, kout;
+	DH *dh; 
+	BIGNUM *dh_server_pub = 0;
+	BIGNUM *shared_secret = 0;	
+	unsigned char *kbuf;
+	unsigned char *hash;
+	unsigned char *serverhostkey;
+	char *msg;
+	char *lang;
+	int type = 0;
+	int first = 1;
+	int slen = 0;
+	u_int strlen;
+	
+	/* Initialise our GSSAPI world */
+	ssh_gssapi_build_ctx(&ctxt);
+	if (ssh_gssapi_client_id_kex(ctxt,kex->name)==NULL) {
+		fatal("Couldn't identify host exchange");
+	}
+
+	if (ssh_gssapi_import_name(ctxt,get_canonical_hostname(1))) {
+		fatal("Couldn't import hostname ");
+	}
+	
+	/* This code should match that in ssh_dh1_client */
+		
+	/* Step 1 - e is dh->pub_key */
+	dh = dh_new_group1();
+	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->options.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)
+	  		(void) gss_release_buffer(&min_status, &recv_tok);
+ 	
+		
+		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();
+			packet_write_wait();
+
+			
+			/* If we've sent them data, they'd better be polite
+			 * and reply. */
+		
+			type = packet_read();
+			switch (type) {
+			case SSH2_MSG_KEXGSS_HOSTKEY:
+				debug("Received KEXGSS_HOSTKEY");
+				serverhostkey=packet_get_string(&slen);
+				break;
+			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; /* u_int vs. size_t */
+				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; /* u_int vs. size_t */
+
+				/* Is there a token included? */
+				if (packet_get_char()) {
+					recv_tok.value=
+					    packet_get_string(&strlen);
+					recv_tok.length=strlen; /*u_int/size_t*/
+					/* 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);
+				fprintf(stderr,"GSSAPI 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);
+        
+        /* 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 H matches the token we just got. */
+                if ((maj_status = gss_verify_mic(&min_status,
+        	       		         ctxt->context,
+        	                         &gssbuf,
+        	                         &msg_tok,
+        	                         NULL))) {
+
+		packet_disconnect("Hash's MIC didn't verify");
+      	}	
+        
+        DH_free(dh);
+       	ssh_gssapi_delete_ctx(&ctxt);
+        /* 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);
+        }
+        
+	kex_derive_keys(kex, hash, shared_secret);
+	BN_clear_free(shared_secret);
+        kex_finish(kex);
+}
+
+#endif /* GSSAPI */
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/kexgsss.c openssh-3.6.1p2/kexgsss.c
--- openssh-3.6.1p2.orig/kexgsss.c	Thu Jan  1 01:00:00 1970
+++ openssh-3.6.1p2/kexgsss.c	Wed Apr 30 10:12:47 2003
@@ -0,0 +1,241 @@
+/*
+ * 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
+
+#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,send_tok,recv_tok,msg_tok;
+	Gssctxt *ctxt = NULL;
+        unsigned int klen, kout;
+        unsigned char *kbuf;
+        unsigned char *hash;
+        DH *dh;
+        BIGNUM *shared_secret = NULL;
+        BIGNUM *dh_client_pub = NULL;
+	int type =0;
+	u_int slen;
+	gss_OID oid;
+	
+	/* Initialise GSSAPI */
+
+	debug2("%s: Identifying %s",__func__,kex->name);
+	oid=ssh_gssapi_server_id_kex(kex->name);
+	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");
+        }
+                                                                                                                                
+	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; /* int vs. size_t */
+
+		        dh_client_pub = BN_new();
+		        
+		        if (dh_client_pub == 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; /* int vs. size_t */
+			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));
+
+		gss_release_buffer(&min_status,&recv_tok);
+		
+		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();
+			packet_write_wait();
+			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_write_wait();
+		}	
+		fatal("accept_ctx died");
+	}
+	
+	debug("gss_complete");
+	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");
+			
+	dh = dh_new_group1();
+	dh_gen_key(dh, kex->we_need * 8);
+	
+        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);
+	
+	/* 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)))) {
+		kex_gss_send_error(ctxt);
+		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();
+	packet_write_wait();
+
+        /* We used to store the client name and credentials here for later
+         * use. With privsep, its easier to do this as a by product of the
+         * call to accept_context, which stores delegated information when
+         * the context is complete */
+         
+	gss_release_buffer(&min_status, &send_tok);	
+
+	/* If we've got a context, delete it. It may be NULL if we've been
+	 * using privsep */
+	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 -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/key.c openssh-3.6.1p2/key.c
--- openssh-3.6.1p2.orig/key.c	Mon Feb 24 01:01:41 2003
+++ openssh-3.6.1p2/key.c	Wed Apr 30 10:12:47 2003
@@ -646,6 +646,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 -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/key.h openssh-3.6.1p2/key.h
--- openssh-3.6.1p2.orig/key.h	Mon Feb 24 01:01:41 2003
+++ openssh-3.6.1p2/key.h	Wed Apr 30 10:12:47 2003
@@ -34,6 +34,7 @@
 	KEY_RSA1,
 	KEY_RSA,
 	KEY_DSA,
+	KEY_NULL,
 	KEY_UNSPEC
 };
 enum fp_type {
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/makegssname.pl openssh-3.6.1p2/makegssname.pl
--- openssh-3.6.1p2.orig/makegssname.pl	Thu Jan  1 01:00:00 1970
+++ openssh-3.6.1p2/makegssname.pl	Wed Apr 30 10:12:47 2003
@@ -0,0 +1,50 @@
+#!/usr/bin/perl
+
+use Convert::ASN1 qw(:tag);
+use Digest::MD5 qw(md5);
+use MIME::Base64;
+use Data::Dumper;
+ 
+$oid=shift;
+my $asn=Convert::ASN1->new;
+$asn->prepare("oid OBJECT IDENTIFIER");
+$encoded=$asn->encode(oid => $oid);
+Convert::ASN1::asn_dump($encoded);
+print Dumper($asn->decode($encoded));
+
+@entries=unpack("C*",$encoded);
+
+print "DER representation: ";
+foreach $entry (@entries) {
+  print "\\x";
+  printf "%02X",$entry;
+}
+print "\n";
+
+$digest = md5($encoded);
+# We only want the first 10 characters;
+# Conversations with the authors suggest that we want to use all of the
+# characters of the digest.
+#$digest = substr($digest,0,10);
+print "gsskeyex representation: ",encode_base64($digest),"\n";
+
+sub encode_object_id {
+  $string="";
+
+  my @data = ($_[0] =~ /(\d+)/g);
+
+  if(@data < 2) {
+      @data = (0);
+  }
+  else {
+      my $first = $data[1] + ($data[0] * 40);
+      splice(@data,0,2,$first);
+  }
+
+#  my $l = length $string;
+  $string .= pack("cw*", 0, @data);
+#  substr($string,$l,1) = asn_encode_length(length($string) - $l - 1);
+  return $string;
+}
+
+
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/monitor.c openssh-3.6.1p2/monitor.c
--- openssh-3.6.1p2.orig/monitor.c	Tue Apr 29 10:12:08 2003
+++ openssh-3.6.1p2/monitor.c	Wed Apr 30 10:12:47 2003
@@ -59,6 +59,11 @@
 #include "ssh2.h"
 #include "mpaux.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+static Gssctxt *gsscontext = NULL;
+#endif
+
 /* Imports */
 extern ServerOptions options;
 extern u_int utmp_len;
@@ -127,6 +132,16 @@
 int mm_answer_krb5(int, Buffer *);
 #endif
 
+#ifdef GSSAPI
+int mm_answer_gss_setup_ctx(int, Buffer *);
+int mm_answer_gss_accept_ctx(int, Buffer *);
+int mm_answer_gss_userok(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
+
 static Authctxt *authctxt;
 static BIGNUM *ssh1_challenge = NULL;	/* used for ssh1 rsa auth */
 
@@ -172,12 +187,31 @@
     {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_GSSERR, MON_ISAUTH | MON_ONCE, mm_answer_gss_error},
+    {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs},
+    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
+/* Turn this off until we use it */
+#if 0
+    {MONITOR_REQ_GSSLOCALNAME, MON_ISAUTH, mm_answer_gss_localname},
+#endif
+#endif
     {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
     {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
     {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},
@@ -267,6 +301,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;
 
@@ -321,6 +361,13 @@
 		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);
@@ -1468,6 +1515,9 @@
 	kex->we_need = buffer_get_int(m);
 	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
 	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+#ifdef GSSAPI
+	kex->kex[KEX_GSS_GRP1_SHA1] =kexgss_server;
+#endif
 	kex->server = 1;
 	kex->hostkey_type = buffer_get_int(m);
 	kex->kex_type = buffer_get_int(m);
@@ -1648,3 +1698,170 @@
 	mon->m_recvfd = pair[0];
 	mon->m_sendfd = pair[1];
 }
+
+#ifdef GSSAPI
+
+int
+mm_answer_gss_setup_ctx(int socket, Buffer *m) {
+        gss_OID_desc oid;
+        OM_uint32 major;
+	u_int len;
+
+        oid.elements=buffer_get_string(m,&len);
+	oid.length=len;
+                
+        major=ssh_gssapi_server_ctx(&gsscontext,&oid);
+
+        xfree(oid.elements);
+
+        buffer_clear(m);
+        buffer_put_int(m,major);
+
+        mm_request_send(socket,MONITOR_ANS_GSSSETUP,m);
+
+	/* Now we have a context, enable the step and sign */
+	monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP,1);
+
+        return(0);
+}
+
+int
+mm_answer_gss_accept_ctx(int socket, Buffer *m) {
+        gss_buffer_desc in,out;
+        OM_uint32 major,minor;
+        OM_uint32 flags = 0; /* GSI needs this */
+
+        in.value = buffer_get_string(m,&in.length);
+        major=ssh_gssapi_accept_ctx(gsscontext,&in,&out,&flags);
+        xfree(in.value);
+
+        buffer_clear(m);
+        buffer_put_int(m, major);
+        buffer_put_string(m, out.value, out.length);
+        buffer_put_int(m, flags);
+        mm_request_send(socket,MONITOR_ANS_GSSSTEP,m);
+
+        gss_release_buffer(&minor, &out);
+
+	/* Complete - now we can do signing */
+	if (major==GSS_S_COMPLETE) {
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP,0);
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN,1);		
+	}
+        return(0);
+}
+
+int
+mm_answer_gss_userok(int socket, Buffer *m) {
+	int authenticated;
+
+        authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
+
+        buffer_clear(m);
+        buffer_put_int(m, authenticated);
+
+        debug3("%s: sending result %d", __func__, authenticated);
+        mm_request_send(socket, MONITOR_ANS_GSSUSEROK, m);
+
+	/* XXX - auth method could also be 'external' */
+	auth_method="gssapi";
+	
+        /* Monitor loop will terminate if authenticated */
+        return(authenticated);
+}
+
+int
+mm_answer_gss_sign(int socket, Buffer *m) {
+        gss_buffer_desc data,hash;
+        OM_uint32 major,minor;
+
+        data.value = buffer_get_string(m,&data.length);
+        if (data.length != 20)
+                fatal("%s: data length incorrect: %d", __func__, data.length);
+
+        /* Save the session ID - only first time round */
+        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 permissions for getpwnam */
+	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;
+	int 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);
+	}
+
+	gss_release_oid_set(&minor,&mech_set);
+	
+	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 -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/monitor.h openssh-3.6.1p2/monitor.h
--- openssh-3.6.1p2.orig/monitor.h	Fri Sep 27 04:26:02 2002
+++ openssh-3.6.1p2/monitor.h	Wed Apr 30 10:12:47 2003
@@ -39,6 +39,15 @@
 	MONITOR_REQ_BSDAUTHRESPOND, MONITOR_ANS_BSDAUTHRESPOND,
 	MONITOR_REQ_SKEYQUERY, MONITOR_ANS_SKEYQUERY,
 	MONITOR_REQ_SKEYRESPOND, MONITOR_ANS_SKEYRESPOND,
+#ifdef GSSAPI
+	MONITOR_REQ_GSSSETUP,MONITOR_ANS_GSSSETUP,
+	MONITOR_REQ_GSSSTEP,MONITOR_ANS_GSSSTEP,
+	MONITOR_REQ_GSSSIGN,MONITOR_ANS_GSSSIGN,
+	MONITOR_REQ_GSSUSEROK,MONITOR_ANS_GSSUSEROK,
+	MONITOR_REQ_GSSMECHS,MONITOR_ANS_GSSMECHS,
+	MONITOR_REQ_GSSLOCALNAME,MONITOR_ANS_GSSLOCALNAME,
+	MONITOR_REQ_GSSERR,MONITOR_ANS_GSSERR,
+#endif
 	MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
 	MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY,
 	MONITOR_REQ_KEYEXPORT,
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/monitor_wrap.c openssh-3.6.1p2/monitor_wrap.c
--- openssh-3.6.1p2.orig/monitor_wrap.c	Tue Apr  1 12:43:39 2003
+++ openssh-3.6.1p2/monitor_wrap.c	Wed Apr 30 10:12:47 2003
@@ -52,6 +52,10 @@
 #include "channels.h"
 #include "session.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 /* Imports */
 extern int compat20;
 extern Newkeys *newkeys[];
@@ -1019,3 +1023,160 @@
 	return (success);
 }
 #endif
+#ifdef GSSAPI
+OM_uint32
+mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) {
+        Buffer m;
+        OM_uint32 major;
+                
+        /* Client doesn't get to see the context */
+        *ctx=NULL;
+
+        buffer_init(&m);
+        buffer_put_string(&m,oid->elements,oid->length);
+
+        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m);
+        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m);
+
+        major=buffer_get_int(&m);
+
+	buffer_free(&m);
+        return(major);
+}
+
+OM_uint32
+mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
+                         gss_buffer_desc *out, OM_uint32 *flags) {
+ 
+        Buffer m;
+        OM_uint32 major;
+
+        buffer_init(&m);
+        buffer_put_string(&m, in->value, in->length);
+
+        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m);
+        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m);
+
+        major=buffer_get_int(&m);
+        out->value=buffer_get_string(&m,&out->length);
+        if (flags) *flags=buffer_get_int(&m);
+
+	buffer_free(&m);
+	
+        return(major);
+}
+
+int
+mm_ssh_gssapi_userok(char *user) {
+        Buffer m;
+        int authenticated = 0;
+
+        buffer_init(&m);
+        
+        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
+        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
+                                  &m);
+
+        authenticated = buffer_get_int(&m);
+
+        buffer_free(&m);
+        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;
+
+        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, &hash->length);
+
+	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 -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/monitor_wrap.h openssh-3.6.1p2/monitor_wrap.h
--- openssh-3.6.1p2.orig/monitor_wrap.h	Fri Sep 27 04:26:04 2002
+++ openssh-3.6.1p2/monitor_wrap.h	Wed Apr 30 10:12:47 2003
@@ -59,6 +59,18 @@
 void mm_start_pam(char *);
 #endif
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **ctxt, gss_OID oid);
+OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *ctxt, gss_buffer_desc *recv,
+				   gss_buffer_desc *send, OM_uint32 *flags);
+OM_uint32 mm_ssh_gssapi_sign(Gssctxt *ctxt, gss_buffer_desc *buffer,
+			     gss_buffer_desc *hash);
+int mm_ssh_gssapi_userok(char *user);
+char *mm_ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *maj, OM_uint32 *min);
+
+#endif
+
 void mm_terminate(void);
 int mm_pty_allocate(int *, int *, char *, int);
 void mm_session_pty_cleanup2(void *);
Common subdirectories: openssh-3.6.1p2.orig/openbsd-compat and openssh-3.6.1p2/openbsd-compat
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/readconf.c openssh-3.6.1p2/readconf.c
--- openssh-3.6.1p2.orig/readconf.c	Tue Apr  1 12:43:39 2003
+++ openssh-3.6.1p2/readconf.c	Wed Apr 30 10:12:47 2003
@@ -97,6 +97,12 @@
 #if defined(KRB4) || defined(KRB5)
 	oKerberosAuthentication,
 #endif
+#ifdef GSSAPI
+	oGssAuthentication, oGssDelegateCreds,
+#ifdef GSI
+	oGssGlobusDelegateLimitedCreds,
+#endif /* GSI */
+#endif /* GSSAPI */
 #if defined(AFS) || defined(KRB5)
 	oKerberosTgtPassing,
 #endif
@@ -144,6 +150,15 @@
 #if defined(KRB4) || defined(KRB5)
 	{ "kerberosauthentication", oKerberosAuthentication },
 #endif
+#ifdef GSSAPI
+	{ "gssapiauthentication", oGssAuthentication },
+	{ "gssapidelegatecredentials", oGssDelegateCreds },
+#ifdef GSI
+	/* For backwards compatability with old 1.2.27 client code */
+	{ "forwardgssapiglobusproxy", oGssDelegateCreds }, /* alias */
+	{ "forwardgssapiglobuslimitedproxy", oGssGlobusDelegateLimitedCreds },
+#endif /* GSI */
+#endif /* GSSAPI */
 #if defined(AFS) || defined(KRB5)
 	{ "kerberostgtpassing", oKerberosTgtPassing },
 #endif
@@ -366,6 +381,23 @@
 		intptr = &options->kerberos_authentication;
 		goto parse_flag;
 #endif
+#ifdef GSSAPI
+	case oGssAuthentication:
+		intptr = &options->gss_authentication;
+		goto parse_flag;
+      
+	case oGssDelegateCreds:
+		intptr = &options->gss_deleg_creds;
+		goto parse_flag;
+ 
+#ifdef GSI
+	case oGssGlobusDelegateLimitedCreds:
+		intptr = &options->gss_globus_deleg_limited_proxy;
+		goto parse_flag;
+#endif /* GSI */
+
+#endif /* GSSAPI */
+
 #if defined(AFS) || defined(KRB5)
 	case oKerberosTgtPassing:
 		intptr = &options->kerberos_tgt_passing;
@@ -748,6 +780,14 @@
 	options->rsa_authentication = -1;
 	options->pubkey_authentication = -1;
 	options->challenge_response_authentication = -1;
+#ifdef GSSAPI
+        options->gss_authentication = -1;
+        options->gss_deleg_creds = -1;
+#ifdef GSI
+        options->gss_globus_deleg_limited_proxy = -1;
+#endif /* GSI */
+#endif /* GSSAPI */
+
 #if defined(KRB4) || defined(KRB5)
 	options->kerberos_authentication = -1;
 #endif
@@ -825,6 +865,16 @@
 		options->pubkey_authentication = 1;
 	if (options->challenge_response_authentication == -1)
 		options->challenge_response_authentication = 1;
+#ifdef GSSAPI
+	if (options->gss_authentication == -1)
+		options->gss_authentication = 1;
+	if (options->gss_deleg_creds == -1)
+		options->gss_deleg_creds = 1;
+#ifdef GSI
+	if (options->gss_globus_deleg_limited_proxy == -1)
+		options->gss_globus_deleg_limited_proxy = 0;
+#endif /* GSI */
+#endif /* GSSAPI */
 #if defined(KRB4) || defined(KRB5)
 	if (options->kerberos_authentication == -1)
 		options->kerberos_authentication = 1;
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/readconf.h openssh-3.6.1p2/readconf.h
--- openssh-3.6.1p2.orig/readconf.h	Tue Apr  1 12:43:40 2003
+++ openssh-3.6.1p2/readconf.h	Wed Apr 30 10:12:47 2003
@@ -47,6 +47,15 @@
 #if defined(AFS) || defined(KRB5)
 	int     kerberos_tgt_passing;	/* Try Kerberos TGT passing. */
 #endif
+
+#ifdef GSSAPI
+	int 	gss_authentication;
+	int	gss_deleg_creds;
+#ifdef GSI
+	int	gss_globus_deleg_limited_proxy;
+#endif /* GSI */
+#endif /* GSSAPI */
+
 #ifdef AFS
 	int     afs_token_passing;	/* Try AFS token passing. */
 #endif
Common subdirectories: openssh-3.6.1p2.orig/regress and openssh-3.6.1p2/regress
Common subdirectories: openssh-3.6.1p2.orig/scard and openssh-3.6.1p2/scard
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/servconf.c openssh-3.6.1p2/servconf.c
--- openssh-3.6.1p2.orig/servconf.c	Mon Feb 24 01:04:34 2003
+++ openssh-3.6.1p2/servconf.c	Wed Apr 30 10:12:47 2003
@@ -86,6 +86,12 @@
 	options->hostbased_uses_name_from_packet_only = -1;
 	options->rsa_authentication = -1;
 	options->pubkey_authentication = -1;
+#ifdef GSSAPI
+	options->gss_authentication=-1;
+	options->gss_keyex=-1;
+	options->gss_use_session_ccache = -1;
+	options->gss_cleanup_creds = -1;
+#endif
 #if defined(KRB4) || defined(KRB5)
 	options->kerberos_authentication = -1;
 	options->kerberos_or_local_passwd = -1;
@@ -200,6 +206,16 @@
 		options->rsa_authentication = 1;
 	if (options->pubkey_authentication == -1)
 		options->pubkey_authentication = 1;
+#ifdef GSSAPI
+	if (options->gss_authentication == -1)
+		options->gss_authentication = 1;
+	if (options->gss_keyex == -1)
+		options->gss_keyex =1;
+	if (options->gss_use_session_ccache == -1)
+		options->gss_use_session_ccache = 1;
+	if (options->gss_cleanup_creds == -1)
+		options->gss_cleanup_creds = 1;
+#endif
 #if defined(KRB4) || defined(KRB5)
 	if (options->kerberos_authentication == -1)
 		options->kerberos_authentication = 0;
@@ -280,6 +296,9 @@
 	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
 	sPermitRootLogin, sLogFacility, sLogLevel,
 	sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
+#ifdef GSSAPI
+	sGssAuthentication, sGssKeyEx, sGssUseSessionCredCache, sGssCleanupCreds,
+#endif
 #if defined(KRB4) || defined(KRB5)
 	sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
 #endif
@@ -330,6 +349,13 @@
 	{ "rsaauthentication", sRSAAuthentication },
 	{ "pubkeyauthentication", sPubkeyAuthentication },
 	{ "dsaauthentication", sPubkeyAuthentication },			/* alias */
+#ifdef GSSAPI
+	{ "gssapiauthentication", sGssAuthentication },
+	{ "gssapikeyexchange", sGssKeyEx },
+	{ "gssusesessionccache", sGssUseSessionCredCache },
+	{ "gssapiusesessioncredcache", sGssUseSessionCredCache },
+	{ "gssapicleanupcreds", sGssCleanupCreds },
+#endif
 #if defined(KRB4) || defined(KRB5)
 	{ "kerberosauthentication", sKerberosAuthentication },
 	{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
@@ -645,6 +671,20 @@
 	case sPubkeyAuthentication:
 		intptr = &options->pubkey_authentication;
 		goto parse_flag;
+#ifdef GSSAPI
+	case sGssAuthentication:
+		intptr = &options->gss_authentication;
+		goto parse_flag;
+	case sGssKeyEx:
+		intptr = &options->gss_keyex;
+		goto parse_flag;
+	case sGssUseSessionCredCache:
+		intptr = &options->gss_use_session_ccache;
+		goto parse_flag;
+	case sGssCleanupCreds:
+		intptr = &options->gss_cleanup_creds;
+		goto parse_flag;
+#endif
 #if defined(KRB4) || defined(KRB5)
 	case sKerberosAuthentication:
 		intptr = &options->kerberos_authentication;
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/servconf.h openssh-3.6.1p2/servconf.h
--- openssh-3.6.1p2.orig/servconf.h	Thu Aug  1 02:28:39 2002
+++ openssh-3.6.1p2/servconf.h	Wed Apr 30 10:12:48 2003
@@ -73,6 +73,13 @@
 	int     hostbased_uses_name_from_packet_only; /* experimental */
 	int     rsa_authentication;	/* If true, permit RSA authentication. */
 	int     pubkey_authentication;	/* If true, permit ssh2 pubkey authentication. */
+	#ifdef GSSAPI
+	int     gss_authentication;
+	int     gss_keyex;
+	int     gss_use_session_ccache;        /* If true, delegated credentials are
+	                                        * stored in a session specific cache */
+	int 	gss_cleanup_creds;	       /* If true, destroy cred cache on logout */
+#endif	
 #if defined(KRB4) || defined(KRB5)
 	int     kerberos_authentication;	/* If true, permit Kerberos
 						 * authentication. */
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/session.c openssh-3.6.1p2/session.c
--- openssh-3.6.1p2.orig/session.c	Fri Mar 21 01:18:09 2003
+++ openssh-3.6.1p2/session.c	Wed Apr 30 10:12:48 2003
@@ -58,6 +58,10 @@
 #include "session.h"
 #include "monitor_wrap.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 #ifdef HAVE_CYGWIN
 #include <windows.h>
 #include <sys/cygwin.h>
@@ -455,6 +459,12 @@
 
 	session_proctitle(s);
 
+#if defined(GSSAPI)
+	temporarily_use_uid(s->pw);
+	ssh_gssapi_storecreds();
+	restore_uid();
+#endif
+
 #if defined(USE_PAM)
 	do_pam_session(s->pw->pw_name, NULL);
 	do_pam_setcred(1);
@@ -582,6 +592,12 @@
 	ptyfd = s->ptyfd;
 	ttyfd = s->ttyfd;
 
+#if defined(GSSAPI)
+	temporarily_use_uid(s->pw);
+	ssh_gssapi_storecreds();
+	restore_uid();
+#endif
+
 #if defined(USE_PAM)
 	do_pam_session(s->pw->pw_name, s->tty);
 	do_pam_setcred(1);
@@ -840,7 +856,7 @@
  * Sets the value of the given variable in the environment.  If the variable
  * already exists, its value is overriden.
  */
-static void
+void
 child_set_env(char ***envp, u_int *envsizep, const char *name,
 	const char *value)
 {
@@ -967,6 +983,13 @@
 	copy_environment(environ, &env, &envsize);
 #endif
 
+#ifdef GSSAPI
+	/* Allow any GSSAPI methods that we've used to alter 
+	 * the childs environment as they see fit
+	 */
+	ssh_gssapi_do_child(&env,&envsize);
+#endif
+
 	if (!options.use_login) {
 		/* Set basic environment. */
 		child_set_env(&env, &envsize, "USER", pw->pw_name);
@@ -2121,4 +2144,7 @@
 do_authenticated2(Authctxt *authctxt)
 {
 	server_loop2(authctxt);
+#if defined(GSSAPI)
+	ssh_gssapi_cleanup_creds(NULL);
+#endif
 }
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/session.h openssh-3.6.1p2/session.h
--- openssh-3.6.1p2.orig/session.h	Thu Jul  4 01:14:18 2002
+++ openssh-3.6.1p2/session.h	Wed Apr 30 10:12:48 2003
@@ -68,4 +68,7 @@
 Session	*session_by_tty(char *);
 void	 session_close(Session *);
 void	 do_setusercontext(struct passwd *);
+
+void	 child_set_env(char ***envp, u_int *envsizep, const char *name,
+		       const char *value);
 #endif
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/ssh-gss.h openssh-3.6.1p2/ssh-gss.h
--- openssh-3.6.1p2.orig/ssh-gss.h	Thu Jan  1 01:00:00 1970
+++ openssh-3.6.1p2/ssh-gss.h	Wed Apr 30 10:12:48 2003
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+#ifndef _SSH_GSS_H
+#define _SSH_GSS_H
+
+#ifdef GSSAPI
+
+#include "kex.h"
+#include "buffer.h"
+
+#include <gssapi.h>
+
+#ifdef KRB5
+#ifndef HEIMDAL
+#include <gssapi_generic.h>
+
+/* MIT Kerberos doesn't seem to define GSS_NT_HOSTBASED_SERVICE */
+#ifndef GSS_C_NT_HOSTBASED_SERVICE
+#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#endif /* GSS_C_NT_... */
+#endif /* !HEIMDAL */
+#endif /* KRB5 */
+
+/* draft-ietf-secsh-gsskeyex-03 */
+#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_USERAUTH_GSSAPI_RESPONSE     		60
+#define SSH2_MSG_USERAUTH_GSSAPI_TOKEN        		61
+#define SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE	63    
+#define SSH2_MSG_USERAUTH_GSSAPI_ERROR			64  
+#define SSH2_MSG_USERAUTH_GSSAPI_ERRTOK			65
+
+#define KEX_GSS_SHA1					"gss-group1-sha1-"
+
+typedef struct {
+        char *filename;
+        char *envvar;
+        char *envval;
+        void *data;
+} ssh_gssapi_ccache;
+
+typedef struct {
+	gss_buffer_desc name;
+	gss_cred_id_t   creds;
+	struct ssh_gssapi_mech_struct *mech;
+	ssh_gssapi_ccache store;
+} ssh_gssapi_client;
+
+typedef struct ssh_gssapi_mech_struct {
+        char *enc_name;
+        char *name;
+        gss_OID_desc oid;
+	int (*dochild) (ssh_gssapi_client *);
+	int (*userok) (ssh_gssapi_client *, char *);
+	int (*localname) (ssh_gssapi_client *, char **);
+	void (*storecreds) (ssh_gssapi_client *);
+} ssh_gssapi_mech;
+
+
+
+typedef struct {
+	OM_uint32	major; /* both */
+	OM_uint32	minor; /* both */
+	gss_ctx_id_t	context; /* both */
+	gss_name_t	name; /* both */
+	gss_OID		oid; /* client */
+	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[];
+
+char *ssh_gssapi_mechanisms(char *host);
+char *ssh_gssapi_client_mechanisms(char *host);
+gss_OID ssh_gssapi_client_id_kex(Gssctxt *ctx, char *name);
+int  ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len);
+void ssh_gssapi_set_oid_data(Gssctxt *ctx, void *data, size_t len);
+void ssh_gssapi_set_oid(Gssctxt *ctx, gss_OID oid);
+void ssh_gssapi_supported_oids(gss_OID_set *oidset);
+ssh_gssapi_mech *ssh_gssapi_get_ctype(Gssctxt *ctxt);
+
+OM_uint32 ssh_gssapi_import_name(Gssctxt *ctx, const char *host);
+OM_uint32 ssh_gssapi_acquire_cred(Gssctxt *ctx);
+OM_uint32 ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds,
+			      gss_buffer_desc *recv_tok, 
+			      gss_buffer_desc *send_tok, OM_uint32 *flags);
+OM_uint32 ssh_gssapi_accept_ctx(Gssctxt *ctx,
+				gss_buffer_desc *recv_tok,
+				gss_buffer_desc *send_tok,
+				OM_uint32 *flags);
+OM_uint32 ssh_gssapi_getclient(Gssctxt *ctx,
+				ssh_gssapi_mech **mech,
+				gss_buffer_desc *name,
+				gss_cred_id_t *creds);
+void ssh_gssapi_error(Gssctxt *ctx);
+char *ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *maj, OM_uint32 *min);
+void ssh_gssapi_build_ctx(Gssctxt **ctx);
+void ssh_gssapi_delete_ctx(Gssctxt **ctx);
+OM_uint32 ssh_gssapi_server_ctx(Gssctxt **ctx,gss_OID oid);
+
+int ssh_gssapi_check_mechanism(gss_OID oid, char *host);
+
+/* In the server */
+gss_OID ssh_gssapi_server_id_kex(char *name);
+int ssh_gssapi_userok(char *name);
+int ssh_gssapi_localname(char **name);
+void ssh_gssapi_server(Kex *kex, Buffer *client_kexinit, 
+		       Buffer *server_kexinit);
+
+OM_uint32 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *buffer, 
+					gss_buffer_desc *hash);
+
+void ssh_gssapi_do_child(char ***envp, u_int *envsizep);                 
+void ssh_gssapi_cleanup_creds(void *ignored);
+void ssh_gssapi_storecreds();
+char *ssh_gssapi_server_mechanisms();
+#endif /* GSSAPI */
+
+#endif /* _SSH_GSS_H */
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/sshconnect2.c openssh-3.6.1p2/sshconnect2.c
--- openssh-3.6.1p2.orig/sshconnect2.c	Tue Apr  1 12:43:40 2003
+++ openssh-3.6.1p2/sshconnect2.c	Wed Apr 30 10:12:48 2003
@@ -48,6 +48,10 @@
 #include "msg.h"
 #include "pathnames.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 /* import */
 extern char *client_version_string;
 extern char *server_version_string;
@@ -77,10 +81,26 @@
 ssh_kex2(char *host, struct sockaddr *hostaddr)
 {
 	Kex *kex;
+#ifdef GSSAPI
+	char *orig, *gss;
+	int len;
+#endif
 
 	xxx_host = host;
 	xxx_hostaddr = hostaddr;
 
+#ifdef GSSAPI
+	/* Add the GSSAPI mechanisms currently supported on this client to
+	 * the key exchange algorithm proposal */
+	orig = myproposal[PROPOSAL_KEX_ALGS];
+	gss = ssh_gssapi_client_mechanisms(get_canonical_hostname(1));	
+	if (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) {
 		log("No valid ciphers for protocol version 2 given, using defaults.");
 		options.ciphers = NULL;
@@ -108,14 +128,29 @@
 		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 (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
 	/* start key exchange */
 	kex = kex_setup(myproposal);
 	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
 	kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
+#ifdef GSSAPI
+	kex->kex[KEX_GSS_GRP1_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
 	xxx_kex = kex;
 
 	dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -160,6 +195,8 @@
 	Sensitive *sensitive;
 	/* kbd-interactive */
 	int info_req_seen;
+	/* generic */
+	void *methoddata;
 };
 struct Authmethod {
 	char	*name;		/* string to compare against server's list */
@@ -182,6 +219,16 @@
 int	userauth_kbdint(Authctxt *);
 int	userauth_hostbased(Authctxt *);
 
+#ifdef GSSAPI
+int	userauth_external(Authctxt *authctxt);
+int	userauth_gssapi(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 *);
+#endif
+
 void	userauth(Authctxt *, char *);
 
 static int sign_and_send_pubkey(Authctxt *, Key *, sign_cb_fn *);
@@ -192,6 +239,16 @@
 static char *authmethods_get(void);
 
 Authmethod authmethods[] = {
+#ifdef GSSAPI
+	{"external-keyx",
+		userauth_external,
+		&options.gss_authentication,
+		NULL},
+	{"gssapi",
+		userauth_gssapi,
+		&options.gss_authentication,
+		NULL},
+#endif
 	{"hostbased",
 		userauth_hostbased,
 		&options.hostbased_authentication,
@@ -256,6 +313,7 @@
 	authctxt.success = 0;
 	authctxt.method = authmethod_lookup("none");
 	authctxt.authlist = NULL;
+	authctxt.methoddata = NULL;
 	authctxt.sensitive = sensitive;
 	authctxt.info_req_seen = 0;
 	if (authctxt.method == NULL)
@@ -278,6 +336,11 @@
 void
 userauth(Authctxt *authctxt, char *authlist)
 {
+	if (authctxt->methoddata!=NULL) {
+		xfree(authctxt->methoddata);
+		authctxt->methoddata=NULL;
+	}
+           
 	if (authlist == NULL) {
 		authlist = authctxt->authlist;
 	} else {
@@ -327,6 +390,8 @@
 		fatal("input_userauth_success: no authentication context");
 	if (authctxt->authlist)
 		xfree(authctxt->authlist);
+	if (authctxt->methoddata)
+		xfree(authctxt->methoddata);
 	clear_auth_state(authctxt);
 	authctxt->success = 1;			/* break out */
 }
@@ -428,6 +493,263 @@
 
 }
 
+#ifdef GSSAPI
+int 
+userauth_gssapi(Authctxt *authctxt)
+{
+	Gssctxt *gssctxt = NULL;
+	static gss_OID_set supported = NULL;
+	static int mech=0;
+	OM_uint32 min;
+	int ok=0;
+
+	/* Things work better if we send one mechanism at a time, rather
+	 * than them all at once. This means that if we fail at some point
+	 * in the middle of a negotiation, we can come back and try something
+	 * different. */
+
+	if (datafellows & SSH_OLD_GSSAPI) return 0;
+	
+	/* Before we offer a mechanism, check that we can support it. Don't
+	 * bother trying to get credentials - as the standard fallback will
+	 * deal with that kind of failure.
+	 */
+
+	if (supported==NULL) gss_indicate_mechs(&min, &supported);
+	
+	while (mech<supported->count && !ok) {
+		if (gssctxt) ssh_gssapi_delete_ctx(&gssctxt);
+		ssh_gssapi_build_ctx(&gssctxt);
+		ssh_gssapi_set_oid(gssctxt,&supported->elements[mech]);
+
+		/* The DER encoding below only works for lengths<128,
+		 * so check this here 
+		 */
+		if (supported->elements[mech].length<128 &&
+		    !GSS_ERROR(ssh_gssapi_import_name(gssctxt,
+						      authctxt->host))) {
+		 	ok = 1; /* Mechanism works */
+		} else {
+			mech++;
+		}
+	}
+	
+	if (!ok) return 0;
+	
+	authctxt->methoddata=(void *)gssctxt;
+		
+	packet_start(SSH2_MSG_USERAUTH_REQUEST);
+	packet_put_cstring(authctxt->server_user);
+	packet_put_cstring(authctxt->service);
+        packet_put_cstring(authctxt->method->name);
+	
+	packet_put_int(1);
+
+	/* The newest gsskeyex draft stipulates that OIDs should
+	 * be DER encoded, so we need to add the object type and
+	 * length information back on */
+	if (datafellows & SSH_BUG_GSSAPI_BER) {
+		packet_put_string(supported->elements[mech].elements,
+			  	  supported->elements[mech].length);
+	} else {
+		packet_put_int((supported->elements[mech].length)+2);
+		packet_put_char(0x06);
+		packet_put_char(supported->elements[mech].length);
+		packet_put_raw(supported->elements[mech].elements,
+			       supported->elements[mech].length);
+	}
+
+        packet_send();
+        packet_write_wait();
+
+        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,&input_gssapi_response);
+        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,&input_gssapi_token);
+	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR,&input_gssapi_error);
+	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK,&input_gssapi_errtok);
+	
+	mech++; /* Move along to next candidate */
+
+        return 1;
+}
+
+void
+input_gssapi_response(int type, u_int32_t plen, void *ctxt) 
+{
+	Authctxt *authctxt = ctxt;
+	Gssctxt *gssctxt;
+	OM_uint32 status,ms;
+	int oidlen;
+	char *oidv;
+	gss_buffer_desc send_tok;
+	
+	if (authctxt == NULL)
+		fatal("input_gssapi_response: no authentication context");
+	gssctxt = authctxt->methoddata;
+	
+	/* Setup our OID */
+	oidv=packet_get_string(&oidlen);
+	
+	if (datafellows & SSH_BUG_GSSAPI_BER) {
+		if (!ssh_gssapi_check_oid(gssctxt,oidv,oidlen)) {
+			fatal("Server returned different OID than expected");
+		}
+		ssh_gssapi_set_oid_data(gssctxt,oidv,oidlen);
+	} else {
+		if(oidv[0]!=0x06 || oidv[1]!=oidlen-2) {
+			debug("Badly encoded mechanism OID received");
+			clear_auth_state(authctxt);
+			userauth(authctxt,NULL);
+			return;
+		}
+		if (!ssh_gssapi_check_oid(gssctxt,oidv+2,oidlen-2)) {
+			fatal("Server returned different OID than expected");
+		}
+		ssh_gssapi_set_oid_data(gssctxt,oidv+2,oidlen-2);
+	}
+		
+	packet_check_eom();
+	
+	status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
+				     GSS_C_NO_BUFFER, &send_tok, 
+				     NULL);
+	if (GSS_ERROR(status)) {
+		if (send_tok.length>0) {
+			packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
+			packet_put_string(send_tok.value,send_tok.length);
+			packet_send();
+			packet_write_wait();
+		}
+		/* Start again with next method on list */
+		debug("Trying to start again");
+		clear_auth_state(authctxt);
+		userauth(authctxt,NULL);
+		return;
+	}
+
+	/* We must have data to send */					
+	packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
+	packet_put_string(send_tok.value,send_tok.length);
+	packet_send();
+	packet_write_wait();
+	gss_release_buffer(&ms, &send_tok);
+}
+
+void
+input_gssapi_token(int type, u_int32_t plen, void *ctxt)
+{
+	Authctxt *authctxt = ctxt;
+	Gssctxt *gssctxt;
+	gss_buffer_desc send_tok,recv_tok;
+	OM_uint32 status;
+	u_int slen;
+	
+	if (authctxt == NULL)
+		fatal("input_gssapi_response: no authentication context");
+	gssctxt = authctxt->methoddata;
+	
+	recv_tok.value=packet_get_string(&slen);
+	recv_tok.length=slen;	/* safe typecast */
+
+	status=ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
+				   &recv_tok, &send_tok, NULL);
+
+	packet_check_eom();
+	
+	if (GSS_ERROR(status)) {
+		if (send_tok.length>0) {
+			packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
+			packet_put_string(send_tok.value,send_tok.length);
+			packet_send();
+			packet_write_wait();
+		}
+		/* Start again with the next method in the list */
+		clear_auth_state(authctxt);
+		userauth(authctxt,NULL);
+		return;
+	}
+	
+	if (send_tok.length>0) {
+		packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
+		packet_put_string(send_tok.value,send_tok.length);
+		packet_send();
+		packet_write_wait();
+	}
+	
+	if (status == GSS_S_COMPLETE) {
+		/* If that succeeded, send a exchange complete message */
+		packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
+		packet_send();
+		packet_write_wait();
+	}
+}
+
+void
+input_gssapi_errtok(int type, u_int32_t plen, void *ctxt)
+{
+	Authctxt *authctxt = ctxt;
+	Gssctxt *gssctxt;
+	gss_buffer_desc send_tok,recv_tok;
+	OM_uint32 status;
+	
+	if (authctxt == NULL)
+		fatal("input_gssapi_response: no authentication context");
+	gssctxt = authctxt->methoddata;
+	
+	recv_tok.value=packet_get_string(&recv_tok.length);
+
+	/* Stick it into GSSAPI and see what it says */
+	status=ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
+				   &recv_tok, &send_tok, NULL);
+
+	packet_check_eom();
+	
+	/* We can't send a packet to the server */
+
+	/* The draft says that we should wait for the server to fail 
+	 * before starting the next authentication. So, we clear the
+	 * state, but don't do anything else */
+	clear_auth_state(authctxt);
+	return;
+}
+
+void
+input_gssapi_error(int type, u_int32_t plen, void *ctxt)
+{
+	OM_uint32 maj,min;
+	char *msg;
+	char *lang;
+	
+	maj=packet_get_int();
+	min=packet_get_int();
+	msg=packet_get_string(NULL);
+	lang=packet_get_string(NULL);
+
+	packet_check_eom();
+	
+	fprintf(stderr, "Server GSSAPI Error:\n%s\n", msg);
+	xfree(msg);
+	xfree(lang);
+}
+
+int
+userauth_external(Authctxt *authctxt)
+{
+        static int attempt =0;
+        
+        if (attempt++ >= 1)
+        	return 0;
+                                
+        debug2("userauth_external");
+        packet_start(SSH2_MSG_USERAUTH_REQUEST);
+        packet_put_cstring(authctxt->server_user);
+        packet_put_cstring(authctxt->service);
+        packet_put_cstring(authctxt->method->name);
+        packet_send();
+        packet_write_wait();
+        return 1;
+}                                                                                                
+#endif /* GSSAPI */
+
 int
 userauth_none(Authctxt *authctxt)
 {
@@ -438,6 +760,7 @@
 	packet_put_cstring(authctxt->method->name);
 	packet_send();
 	return 1;
+
 }
 
 int
@@ -544,7 +867,12 @@
 {
 	/* XXX clear authentication state */
 	dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, NULL);
-
+#ifdef GSSAPI
+	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,NULL);
+	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,NULL);
+	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR,NULL);
+#endif
+	
 	if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) {
 		debug3("clear_auth_state: key_free %p", authctxt->last_key);
 		key_free(authctxt->last_key);
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/sshd.c openssh-3.6.1p2/sshd.c
--- openssh-3.6.1p2.orig/sshd.c	Mon Mar 10 00:38:10 2003
+++ openssh-3.6.1p2/sshd.c	Wed Apr 30 10:12:48 2003
@@ -85,6 +85,10 @@
 #include "monitor_wrap.h"
 #include "monitor_fdpass.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 #ifdef LIBWRAP
 #include <tcpd.h>
 #include <syslog.h>
@@ -1013,10 +1017,13 @@
 		log("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) {
 		log("Disabling protocol version 2. Could not load host key");
 		options.protocol &= ~SSH_PROTO_2;
 	}
+#endif
 	if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
 		log("sshd: no hostkeys available -- exiting.");
 		exit(1);
@@ -1816,10 +1823,52 @@
 	}
 	myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
 
+#ifdef GSSAPI
+	{ 
+	char *orig;
+	char *gss = NULL;
+	char *newstr = NULL;
+       	orig = myproposal[PROPOSAL_KEX_ALGS];
+
+	/* If we don't have a host key, then all of the algorithms
+	 * currently in myproposal are useless */
+	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 also got the 'null'
+	   host key algorithm, but we're not allowed to advertise it, unless
+	   its the only host key algorithm we're supporting */
+	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_GEX_SHA1] = kexgex_server;
+#ifdef GSSAPI
+        kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+#endif	        
 	kex->server = 1;
 	kex->client_version_string=client_version_string;
 	kex->server_version_string=server_version_string;
diff -u -N --exclude configure --exclude config.h.in openssh-3.6.1p2.orig/sshd_config.5 openssh-3.6.1p2/sshd_config.5
--- openssh-3.6.1p2.orig/sshd_config.5	Tue Apr  1 12:42:14 2003
+++ openssh-3.6.1p2/sshd_config.5	Wed Apr 30 10:12:48 2003
@@ -253,6 +253,26 @@
 or
 .Dq rsa
 are used for version 2 of the SSH protocol.
+.It Cm GssapiAuthentication
+Specifies whether authentication based on GSSAPI may be used, either using
+the result of a successful key exchange, or using GSSAPI user
+authentication.
+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 yes .
+Note that this option applies to protocol version 2 only.
+.It Cm GssapiUseSessionCredCache
+Specifies whether a unique credentials cache name should be generated per
+session for storing delegated credentials.
+The default is
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+
 .It Cm IgnoreRhosts
 Specifies that
 .Pa .rhosts

