diff -Naur --exclude=autom4te.cache openssh-5.5p1/ChangeLog.gssapi openssh-5.5p1-gssapi/ChangeLog.gssapi
--- openssh-5.5p1/ChangeLog.gssapi	1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.5p1-gssapi/ChangeLog.gssapi	2010-04-20 10:49:30.000000000 -0500
@@ -0,0 +1,95 @@
+20090615
+  - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c
+      sshd.c ]
+    Fix issues identified by Greg Hudson following a code review
+	Check return value of gss_indicate_mechs
+	Protect GSSAPI calls in monitor, so they can only be used if enabled
+	Check return values of bignum functions in key exchange
+	Use BN_clear_free to clear other side's DH value
+	Make ssh_gssapi_id_kex more robust
+	Only configure kex table pointers if GSSAPI is enabled
+	Don't leak mechanism list, or gss mechanism list
+	Cast data.length before printing
+	If serverkey isn't provided, use an empty string, rather than NULL
+
+20090201
+  - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h
+      ssh_config.5 sshconnet2.c ]
+    Add support for the GSSAPIClientIdentity option, which allows the user
+    to specify which GSSAPI identity to use to contact a given server
+
+20080404
+  - [ gss-serv.c ]
+    Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow
+    been omitted from a previous version of this patch. Reported by Borislav
+    Stoichkov
+
+20070317
+  - [ gss-serv-krb5.c ]
+    Remove C99ism, where new_ccname was being declared in the middle of a 
+    function
+
+20061220
+  - [ servconf.c ]
+    Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and 
+    documented, behaviour. Reported by Dan Watson.
+
+20060910
+  - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c
+      ssh-gss.h ]
+    add support for gss-group14-sha1 key exchange mechanisms
+  - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ]
+    Add GSSAPIStrictAcceptorCheck option to allow the disabling of
+    acceptor principal checking on multi-homed machines.
+    <Bugzilla #928>
+  - [ sshd_config ssh_config ]
+    Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample
+    configuration files
+  - [ kexgss.c kegsss.c sshconnect2.c sshd.c ]
+    Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf()
+    Limit length of error messages displayed by client
+
+20060909
+  - [ gss-genr.c gss-serv.c ]
+    move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server
+    only, where they belong 
+    <Bugzilla #1225>
+
+20060829
+  - [ gss-serv-krb5.c ]
+    Fix CCAPI credentials cache name when creating KRB5CCNAME environment 
+    variable
+
+20060828
+  - [ gss-genr.c ]
+    Avoid Heimdal context freeing problem
+    <Fixed upstream 20060829>
+
+20060818
+  - [ gss-genr.c ssh-gss.h sshconnect2.c ]
+    Make sure that SPENGO is disabled 
+    <Bugzilla #1218 - Fixed upstream 20060818>
+
+20060421
+  - [ gssgenr.c, sshconnect2.c ]
+    a few type changes (signed versus unsigned, int versus size_t) to
+    fix compiler errors/warnings 
+    (from jbasney AT ncsa.uiuc.edu)
+  - [ kexgssc.c, sshconnect2.c ]
+    fix uninitialized variable warnings
+    (from jbasney AT ncsa.uiuc.edu)
+  - [ gssgenr.c ]
+    pass oid to gss_display_status (helpful when using GSSAPI mechglue)
+    (from jbasney AT ncsa.uiuc.edu)
+    <Bugzilla #1220 >
+  - [ gss-serv-krb5.c ]
+    #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H
+    (from jbasney AT ncsa.uiuc.edu)
+    <Fixed upstream 20060304>
+  - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c 
+    add client-side GssapiKeyExchange option
+    (from jbasney AT ncsa.uiuc.edu)
+  - [ sshconnect2.c ]
+    add support for GssapiTrustDns option for gssapi-with-mic
+    (from jbasney AT ncsa.uiuc.edu)
+    <gssapi-with-mic support is Bugzilla #1008>
diff -Naur --exclude=autom4te.cache openssh-5.5p1/HPN12-README openssh-5.5p1-gssapi/HPN12-README
--- openssh-5.5p1/HPN12-README	1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.5p1-gssapi/HPN12-README	2010-04-20 10:49:30.000000000 -0500
@@ -0,0 +1,111 @@
+Notes:
+
+To use the NONE option you must have the NoneEnabled switch set on the server and
+you *must* have *both* NoneEnabled and NoneSwitch set to yes on the client. The NONE
+feature works with ALL ssh subsystems (as far as we can tell) *AS LONG AS* a tty is not 
+spawned. If a user uses the -T switch to prevent a tty being created the NONE cipher will
+be disabled. 
+
+The performance increase will only be as good as the network and TCP stack tuning
+on the reciever side of the connection allows. As a rule of thumb a user will need 
+at least 10Mb/s connection with a 100ms RTT to see a doubling of performance. The
+HPN-SSH home page describes this in greater detail. 
+
+http://www.psc.edu/networking/projects/hpn-ssh
+
+Buffer Sizes:
+
+If HPN is disabled the receive buffer size will be set to the 
+OpenSSH default of 64K.
+
+If an HPN system connects to a nonHPN system the receive buffer will
+be set to the HPNBufferSize value. The default is 2MB but user adjustable.
+
+If an HPN to HPN connection is established a number of different things might
+happen based on the user options and conditions. 
+
+Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set 
+HPN Buffer Size = up to 64MB 
+This is the default state. The HPN buffer size will grow to a maximum of 64MB 
+as the TCP receive buffer grows. The maximum HPN Buffer size of 64MB is 
+geared towards 10GigE transcontinental connections. 
+
+Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set
+HPN Buffer Size = TCP receive buffer value. 
+Users on non-autotuning systesm should disable TCPRcvBufPoll in the 
+ssh_cofig and sshd_config
+
+Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf NOT Set
+HPN Buffer Size = minmum of TCP receive buffer and HPNBufferSize. 
+This would be the system defined TCP receive buffer (RWIN).
+
+Conditions: HPNBufferSize SET, TCPRcvBufPoll disabled, TCPRcvBuf SET
+HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. 
+Generally there is no need to set both.
+
+Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf NOT Set
+HPN Buffer Size = grows to HPNBufferSize
+The buffer will grow up to the maximum size specified here. 
+
+Conditions: HPNBufferSize SET, TCPRcvBufPoll enabled, TCPRcvBuf SET
+HPN Buffer Size = minmum of TCPRcvBuf and HPNBufferSize. 
+Generally there is no need to set both of these, especially on autotuning 
+systems. However, if the users wishes to override the autotuning this would be 
+one way to do it.
+
+Conditions: HPNBufferSize NOT Set, TCPRcvBufPoll enabled, TCPRcvBuf SET
+HPN Buffer Size = TCPRcvBuf. 
+This will override autotuning and set the TCP recieve buffer to the user defined 
+value.
+
+
+HPN Specific Configuration options
+
+TcpRcvBuf=[int]KB client
+      set the TCP socket receive buffer to n Kilobytes. It can be set up to the 
+maximum socket size allowed by the system. This is useful in situations where 
+the tcp receive window is set low but the maximum buffer size is set 
+higher (as is typical). This works on a per TCP connection basis. You can also 
+use this to artifically limit the transfer rate of the connection. In these 
+cases the throughput will be no more than n/RTT. The minimum buffer size is 1KB. 
+Default is the current system wide tcp receive buffer size.
+
+TcpRcvBufPoll=[yes/no] client/server
+      enable of disable the polling of the tcp receive buffer through the life 
+of the connection. You would want to make sure that this option is enabled 
+for systems making use of autotuning kernels (linux 2.4.24+, 2.6, MS Vista) 
+default is yes.
+
+NoneEnabled=[yes/no] client/server
+      enable or disable the use of the None cipher. Care must always be used 
+when enabling this as it will allow users to send data in the clear. However, 
+it is important to note that authentication information remains encrypted 
+even if this option is enabled. Set to no by default.
+
+NoneSwitch=[yes/no] client
+     Switch the encryption cipher being used to the None cipher after
+authentication takes place. NoneEnabled must be enabled on both the client
+and server side of the connection. When the connection switches to the NONE
+cipher a warning is sent to STDERR. The connection attempt will fail with an
+error if a client requests a NoneSwitch from the server that does not explicitly
+have NoneEnabled set to yes. Note: The NONE cipher cannot be used in
+interactive (shell) sessions and it will fail silently. Set to no by default.
+
+HPNDisabled=[yes/no] client/server
+     In some situations, such as transfers on a local area network, the impact 
+of the HPN code produces a net decrease in performance. In these cases it is 
+helpful to disable the HPN functionality. By default HPNDisabled is set to no. 
+
+HPNBufferSize=[int]KB client/server
+     This is the default buffer size the HPN functionality uses when interacting
+with nonHPN SSH installations. Conceptually this is similar to the TcpRcvBuf
+option as applied to the internal SSH flow control. This value can range from 
+1KB to 64MB (1-65536). Use of oversized or undersized buffers can cause performance
+problems depending on the length of the network path. The default size of this buffer
+is 2MB.
+
+
+Credits: This patch was conceived, designed, and led by Chris Rapier (rapier@psc.edu)
+         The majority of the actual coding for versions up to HPN12v1 was performed
+         by Michael Stevens (mstevens@andrew.cmu.edu). This work was financed, in part,
+         by Cisco System, Inc., and the National Science Foundation. 
diff -Naur --exclude=autom4te.cache openssh-5.5p1/LICENSE.globus_usage openssh-5.5p1-gssapi/LICENSE.globus_usage
--- openssh-5.5p1/LICENSE.globus_usage	1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.5p1-gssapi/LICENSE.globus_usage	2010-04-20 10:49:30.000000000 -0500
@@ -0,0 +1,18 @@
+/*
+ * Portions of the Usage Metrics suport code are derived from the
+ * Globus project's GridFTP subject to the following license.
+ *
+ * Copyright 2010 University of Chicago
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
diff -Naur --exclude=autom4te.cache openssh-5.5p1/Makefile.in openssh-5.5p1-gssapi/Makefile.in
--- openssh-5.5p1/Makefile.in	2010-03-13 15:41:34.000000000 -0600
+++ openssh-5.5p1-gssapi/Makefile.in	2010-04-20 10:49:30.000000000 -0500
@@ -61,6 +61,7 @@
 
 INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
 INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
+INSTALL_GSISSH=@INSTALL_GSISSH@
 
 TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT)
 
@@ -72,6 +73,7 @@
 	readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \
 	atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
 	monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \
+	kexgssc.o \
 	kexgex.o kexdhc.o kexgexc.o msg.o progressmeter.o dns.o \
 	entropy.o gss-genr.o umac.o jpake.o schnorr.o \
 	ssh-pkcs11.o
@@ -88,9 +90,11 @@
 	auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \
 	monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o \
 	auth-krb5.o \
-	auth2-gss.o gss-serv.o gss-serv-krb5.o \
+	auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\
+	gss-serv-gsi.o \
 	loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
 	audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o \
+	ssh-globus-usage.o \
 	roaming_common.o roaming_serv.o
 
 MANPAGES	= moduli.5.out 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 ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
@@ -289,6 +293,20 @@
 	ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/slogin
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
 	ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
+	if [ ! -z "$(INSTALL_GSISSH)" ]; then \
+		rm -f $(DESTDIR)$(bindir)/gsissh; \
+		ln -s ./ssh$(EXEEXT) $(DESTDIR)$(bindir)/gsissh; \
+		rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsissh.1; \
+		ln -s ./ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/gsissh.1; \
+		rm -f $(DESTDIR)$(bindir)/gsiscp; \
+		ln -s ./scp$(EXEEXT) $(DESTDIR)$(bindir)/gsiscp; \
+		rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsiscp.1; \
+		ln -s ./scp.1 $(DESTDIR)$(mandir)/$(mansubdir)1/gsiscp.1; \
+		rm -f $(DESTDIR)$(bindir)/gsisftp; \
+		ln -s ./sftp$(EXEEXT) $(DESTDIR)$(bindir)/gsisftp; \
+		rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsisftp.1; \
+		ln -s ./sftp.1 $(DESTDIR)$(mandir)/$(mansubdir)1/gsisftp.1; \
+	fi
 
 install-sysconf:
 	if [ ! -d $(DESTDIR)$(sysconfdir) ]; then \
@@ -360,6 +378,11 @@
 
 uninstall:
 	-rm -f $(DESTDIR)$(bindir)/slogin
+	if [ ! -z "$(INSTALL_GSISSH)" ]; then \
+		rm -f $(DESTDIR)$(bindir)/gsiscp; \
+		rm -f $(DESTDIR)$(bindir)/gsissh; \
+		rm -f $(DESTDIR)$(bindir)/gsisftp; \
+	fi
 	-rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT)
 	-rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT)
 	-rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
@@ -374,6 +397,11 @@
 	-rm -f $(DESTDIR)$(RAND_HELPER)$(EXEEXT)
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
+	if [ ! -z "$(INSTALL_GSISSH)" ]; then \
+		rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsissh.1; \
+		rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsiscp.1; \
+		rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/gsisftp.1; \
+	fi
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
diff -Naur --exclude=autom4te.cache openssh-5.5p1/auth-krb5.c openssh-5.5p1-gssapi/auth-krb5.c
--- openssh-5.5p1/auth-krb5.c	2009-12-20 17:49:22.000000000 -0600
+++ openssh-5.5p1-gssapi/auth-krb5.c	2010-04-20 10:49:30.000000000 -0500
@@ -170,8 +170,13 @@
 
 	len = strlen(authctxt->krb5_ticket_file) + 6;
 	authctxt->krb5_ccname = xmalloc(len);
+#ifdef USE_CCAPI
+	snprintf(authctxt->krb5_ccname, len, "API:%s",
+	    authctxt->krb5_ticket_file);
+#else
 	snprintf(authctxt->krb5_ccname, len, "FILE:%s",
 	    authctxt->krb5_ticket_file);
+#endif
 
 #ifdef USE_PAM
 	if (options.use_pam)
@@ -226,15 +231,22 @@
 #ifndef HEIMDAL
 krb5_error_code
 ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
-	int tmpfd, ret;
+	int ret;
 	char ccname[40];
 	mode_t old_umask;
+#ifdef USE_CCAPI
+	char cctemplate[] = "API:krb5cc_%d";
+#else
+	char cctemplate[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX";
+	int tmpfd;
+#endif
 
 	ret = snprintf(ccname, sizeof(ccname),
-	    "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid());
+	    cctemplate, geteuid());
 	if (ret < 0 || (size_t)ret >= sizeof(ccname))
 		return ENOMEM;
 
+#ifndef USE_CCAPI
 	old_umask = umask(0177);
 	tmpfd = mkstemp(ccname + strlen("FILE:"));
 	umask(old_umask);
@@ -249,6 +261,7 @@
 		return errno;
 	}
 	close(tmpfd);
+#endif
 
 	return (krb5_cc_resolve(ctx, ccname, ccache));
 }
diff -Naur --exclude=autom4te.cache openssh-5.5p1/auth-pam.c openssh-5.5p1-gssapi/auth-pam.c
--- openssh-5.5p1/auth-pam.c	2009-07-12 07:07:21.000000000 -0500
+++ openssh-5.5p1-gssapi/auth-pam.c	2010-04-20 10:49:30.000000000 -0500
@@ -30,7 +30,7 @@
  */
 /*
  * Copyright (c) 2003,2004 Damien Miller <djm@mindrot.org>
- * Copyright (c) 2003,2004 Darren Tucker <dtucker@zip.com.au>
+ * Copyright (c) 2003,2004,2006 Darren Tucker <dtucker@zip.com.au>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -272,6 +272,49 @@
 # define pam_chauthtok(a,b)	(sshpam_chauthtok_ruid((a), (b)))
 #endif
 
+struct passwd *
+sshpam_getpw(const char *user)
+{
+	struct passwd *pw;
+
+	if ((pw = getpwnam(user)) != NULL)
+		return(pw);
+
+	debug("PAM: faking passwd struct for user '%.100s'", user);
+	if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL)
+		return NULL;
+	pw->pw_name = xstrdup(user);	/* XXX leak */
+	pw->pw_shell = "/bin/true";
+	pw->pw_gecos = "sshd fake PAM user";
+	return (pw);
+}
+
+void
+sshpam_check_userchanged(void)
+{
+	int sshpam_err;
+	struct passwd *pw;
+	const char *user;
+
+	debug("sshpam_check_userchanged");
+	sshpam_err = pam_get_item(sshpam_handle, PAM_USER, &user);
+	if (sshpam_err != PAM_SUCCESS)
+		fatal("PAM: could not get PAM_USER: %s",
+		    pam_strerror(sshpam_handle, sshpam_err));
+	if (strcmp(user, sshpam_authctxt->pw->pw_name) != 0) {
+		debug("PAM: user mapped from '%.100s' to '%.100s'",
+		    sshpam_authctxt->pw->pw_name, user);
+		if ((pw = getpwnam(user)) == NULL)
+			fatal("PAM: could not get passwd entry for user "
+			    "'%.100s' provided by PAM_USER", user);
+		pwfree(sshpam_authctxt->pw);
+		sshpam_authctxt->pw = pw;
+		sshpam_authctxt->valid = allowed_user(pw);
+		debug("PAM: user '%.100s' now %svalid", user,
+		    sshpam_authctxt->valid ? "" : "in");
+	}
+}
+
 void
 sshpam_password_change_required(int reqd)
 {
@@ -294,7 +337,7 @@
 static void
 import_environments(Buffer *b)
 {
-	char *env;
+	char *env, *user;
 	u_int i, num_env;
 	int err;
 
@@ -304,6 +347,15 @@
 	/* Import variables set by do_pam_account */
 	sshpam_account_status = buffer_get_int(b);
 	sshpam_password_change_required(buffer_get_int(b));
+	if (options.permit_pam_user_change) {
+        user = buffer_get_string(b, NULL);
+        debug("PAM: got username '%.100s' from thread", user);
+        if ((err = pam_set_item(sshpam_handle, PAM_USER, user)) != PAM_SUCCESS)
+            fatal("PAM: failed to set PAM_USER: %s",
+                  pam_strerror(sshpam_handle, err));
+        pwfree(sshpam_authctxt->pw);
+        sshpam_authctxt->pw = pwcopy(sshpam_getpw(user));
+    }
 
 	/* Import environment from subprocess */
 	num_env = buffer_get_int(b);
@@ -469,6 +521,9 @@
 	if (sshpam_err != PAM_SUCCESS)
 		goto auth_fail;
 
+	if (options.permit_pam_user_change) {
+        sshpam_check_userchanged();
+    }
 	if (compat20) {
 		if (!do_pam_account()) {
 			sshpam_err = PAM_ACCT_EXPIRED;
@@ -489,6 +544,9 @@
 	/* Export variables set by do_pam_account */
 	buffer_put_int(&buffer, sshpam_account_status);
 	buffer_put_int(&buffer, sshpam_authctxt->force_pwchange);
+	if (options.permit_pam_user_change) {
+        buffer_put_cstring(&buffer, sshpam_authctxt->pw->pw_name);
+    }
 
 	/* Export any environment strings set in child */
 	for(i = 0; environ[i] != NULL; i++)
@@ -907,6 +965,12 @@
 	debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
 	    pam_strerror(sshpam_handle, sshpam_err));
 
+	if (options.permit_pam_user_change) {
+        sshpam_check_userchanged();
+        if (getpwnam(sshpam_authctxt->pw->pw_name) == NULL)
+            fatal("PAM: completed authentication but PAM account invalid");
+    }
+
 	if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) {
 		sshpam_account_status = 0;
 		return (sshpam_account_status);
@@ -1206,6 +1270,9 @@
 		    pam_strerror(sshpam_handle, sshpam_err));
 
 	sshpam_err = pam_authenticate(sshpam_handle, flags);
+	if (options.permit_pam_user_change) {
+        sshpam_check_userchanged();
+    }
 	sshpam_password = NULL;
 	if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
 		debug("PAM: password authentication accepted for %.100s",
diff -Naur --exclude=autom4te.cache openssh-5.5p1/auth-pam.h openssh-5.5p1-gssapi/auth-pam.h
--- openssh-5.5p1/auth-pam.h	2004-09-11 07:17:26.000000000 -0500
+++ openssh-5.5p1-gssapi/auth-pam.h	2010-04-20 10:49:30.000000000 -0500
@@ -46,5 +46,6 @@
 void sshpam_cleanup(void);
 int sshpam_auth_passwd(Authctxt *, const char *);
 int is_pam_session_open(void);
+struct passwd *sshpam_getpw(const char *);
 
 #endif /* USE_PAM */
diff -Naur --exclude=autom4te.cache openssh-5.5p1/auth.c openssh-5.5p1-gssapi/auth.c
--- openssh-5.5p1/auth.c	2010-03-06 18:57:00.000000000 -0600
+++ openssh-5.5p1-gssapi/auth.c	2010-04-20 10:49:30.000000000 -0500
@@ -72,6 +72,9 @@
 #include "authfile.h"
 #include "monitor_wrap.h"
 
+#include "version.h"
+#include "ssh-globus-usage.h"
+
 /* import */
 extern ServerOptions options;
 extern int use_privsep;
@@ -275,7 +278,8 @@
 	    authmsg,
 	    method,
 	    authctxt->valid ? "" : "invalid user ",
-	    authctxt->user,
+	    (authctxt->user && authctxt->user[0]) ?
+		authctxt->user : "unknown",
 	    get_remote_ipaddr(),
 	    get_remote_port(),
 	    info);
@@ -297,6 +301,21 @@
 	if (authenticated == 0 && !authctxt->postponed)
 		audit_event(audit_classify_auth(method));
 #endif
+	if (authenticated) {
+		char *userdn = NULL;
+		char *mech_name = NULL;
+		ssh_gssapi_get_client_info(&userdn, &mech_name);
+		debug("REPORTING (%s) (%s) (%s) (%s) (%s) (%s) (%s)",
+			 SSH_RELEASE, SSLeay_version(SSLEAY_VERSION),
+			 method, mech_name?mech_name:"NULL", get_remote_ipaddr(),
+			 (authctxt->user && authctxt->user[0])?
+				authctxt->user : "unknown",
+			userdn?userdn:"NULL");
+		ssh_globus_send_usage_metrics(SSH_RELEASE,
+					SSLeay_version(SSLEAY_VERSION),
+					method, mech_name, get_remote_ipaddr(),
+					authctxt->user, userdn);
+	}
 }
 
 /*
@@ -331,7 +350,7 @@
  *
  * This returns a buffer allocated by xmalloc.
  */
-static char *
+char *
 expand_authorized_keys(const char *filename, struct passwd *pw)
 {
 	char *file, ret[MAXPATHLEN];
@@ -540,6 +559,10 @@
 #endif
 
 	pw = getpwnam(user);
+#ifdef USE_PAM
+	if (options.use_pam && options.permit_pam_user_change && pw == NULL)
+		pw = sshpam_getpw(user);
+#endif
 
 #if defined(_AIX) && defined(HAVE_SETAUTHDB)
 	aix_restoreauthdb();
@@ -559,7 +582,8 @@
 #endif
 	if (pw == NULL) {
 		logit("Invalid user %.100s from %.100s",
-		    user, get_remote_ipaddr());
+		      (user && user[0]) ? user : "unknown",
+		      get_remote_ipaddr());
 #ifdef CUSTOM_FAILED_LOGIN
 		record_failed_login(user,
 		    get_canonical_hostname(options.use_dns), "ssh");
diff -Naur --exclude=autom4te.cache openssh-5.5p1/auth.h openssh-5.5p1-gssapi/auth.h
--- openssh-5.5p1/auth.h	2010-03-04 04:53:35.000000000 -0600
+++ openssh-5.5p1-gssapi/auth.h	2010-04-20 10:49:30.000000000 -0500
@@ -41,6 +41,9 @@
 #ifdef KRB5
 #include <krb5.h>
 #endif
+#ifdef AFS_KRB5
+#include <krbafs.h>
+#endif
 
 typedef struct Authctxt Authctxt;
 typedef struct Authmethod Authmethod;
@@ -53,6 +56,7 @@
 	int		 valid;		/* user exists and is allowed to login */
 	int		 attempt;
 	int		 failures;
+	int		 server_caused_failure; 
 	int		 force_pwchange;
 	char		*user;		/* username sent by the client */
 	char		*service;
@@ -70,6 +74,9 @@
 	char		*krb5_ticket_file;
 	char		*krb5_ccname;
 #endif
+#ifdef SESSION_HOOKS
+        char            *session_env_file;
+#endif
 	Buffer		*loginmsg;
 	void		*methoddata;
 };
@@ -145,6 +152,7 @@
 void	userauth_finish(Authctxt *, int, char *);
 void	userauth_send_banner(const char *);
 int	auth_root_allowed(char *);
+char *expand_authorized_keys(const char *filename, struct passwd *pw);
 
 char	*auth2_read_banner(void);
 
diff -Naur --exclude=autom4te.cache openssh-5.5p1/auth2-gss.c openssh-5.5p1-gssapi/auth2-gss.c
--- openssh-5.5p1/auth2-gss.c	2007-12-02 05:59:45.000000000 -0600
+++ openssh-5.5p1-gssapi/auth2-gss.c	2010-04-20 10:49:30.000000000 -0500
@@ -1,7 +1,7 @@
 /* $OpenBSD: auth2-gss.c,v 1.16 2007/10/29 00:52:45 dtucker Exp $ */
 
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -47,11 +47,60 @@
 
 extern ServerOptions options;
 
+static void ssh_gssapi_userauth_error(Gssctxt *ctxt);
 static void input_gssapi_token(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
 static void input_gssapi_errtok(int, u_int32_t, void *);
 
+/* 
+ * The 'gssapi_keyex' userauth mechanism.
+ */
+static int
+userauth_gsskeyex(Authctxt *authctxt)
+{
+	int authenticated = 0;
+	Buffer b, b2;
+	gss_buffer_desc mic, gssbuf, gssbuf2;
+	u_int len;
+
+	mic.value = packet_get_string(&len);
+	mic.length = len;
+
+	packet_check_eom();
+
+	ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
+	    "gssapi-keyex");
+
+	gssbuf.value = buffer_ptr(&b);
+	gssbuf.length = buffer_len(&b);
+
+	/* client may have used empty username to determine target
+	   name from GSSAPI context */
+	ssh_gssapi_buildmic(&b2, "", authctxt->service, "gssapi-keyex");
+
+	gssbuf2.value = buffer_ptr(&b2);
+	gssbuf2.length = buffer_len(&b2);
+
+	/* gss_kex_context is NULL with privsep, so we can't check it here */
+	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 
+						   &gssbuf, &mic))) ||
+	    !GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 
+						   &gssbuf2, &mic)))) {
+	    if (authctxt->valid && authctxt->user && authctxt->user[0]) {
+            authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
+                                                      authctxt->pw,
+                                                      1 /* gssapi-keyex */));
+	    }
+	}
+	
+	buffer_free(&b);
+	buffer_free(&b2);
+	xfree(mic.value);
+
+	return (authenticated);
+}
+
 /*
  * We only support those mechanisms that we know about (ie ones that we know
  * how to check local user kuserok and the like)
@@ -68,7 +117,10 @@
 	u_int len;
 	u_char *doid = NULL;
 
-	if (!authctxt->valid || authctxt->user == NULL)
+	/* authctxt->valid may be 0 if we haven't yet determined
+	   username from gssapi context. */
+
+	if (authctxt->user == NULL)
 		return (0);
 
 	mechs = packet_get_int();
@@ -102,6 +154,7 @@
 
 	if (!present) {
 		xfree(doid);
+		authctxt->server_caused_failure = 1;
 		return (0);
 	}
 
@@ -109,6 +162,7 @@
 		if (ctxt != NULL)
 			ssh_gssapi_delete_ctx(&ctxt);
 		xfree(doid);
+		authctxt->server_caused_failure = 1;
 		return (0);
 	}
 
@@ -136,7 +190,7 @@
 	Gssctxt *gssctxt;
 	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
 	gss_buffer_desc recv_tok;
-	OM_uint32 maj_status, min_status, flags;
+	OM_uint32 maj_status, min_status, flags=0;
 	u_int len;
 
 	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
@@ -154,6 +208,7 @@
 	xfree(recv_tok.value);
 
 	if (GSS_ERROR(maj_status)) {
+        	ssh_gssapi_userauth_error(gssctxt);
 		if (send_tok.length != 0) {
 			packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK);
 			packet_put_string(send_tok.value, send_tok.length);
@@ -217,6 +272,32 @@
 	gss_release_buffer(&maj_status, &send_tok);
 }
 
+static void
+gssapi_set_username(Authctxt *authctxt)
+{
+    char *lname = NULL;
+
+    if ((authctxt->user == NULL) || (authctxt->user[0] == '\0')) {
+        PRIVSEP(ssh_gssapi_localname(&lname));
+        if (lname && lname[0] != '\0') {
+            if (authctxt->user) xfree(authctxt->user);
+            authctxt->user = lname;
+            debug("set username to %s from gssapi context", lname);
+            authctxt->pw = PRIVSEP(getpwnamallow(authctxt->user));
+            if (authctxt->pw) {
+                authctxt->valid = 1;
+#ifdef USE_PAM
+                if (options.use_pam)
+                    PRIVSEP(start_pam(authctxt));
+#endif
+            }
+        } else {
+            debug("failed to set username from gssapi context");
+            packet_send_debug("failed to set username from gssapi context");
+        }
+    }
+}
+
 /*
  * This is called when the client thinks we've completed authentication.
  * It should only be enabled in the dispatch handler by the function above,
@@ -233,6 +314,8 @@
 	if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
 		fatal("No authentication or GSSAPI context");
 
+	gssapi_set_username(authctxt);
+
 	gssctxt = authctxt->methoddata;
 
 	/*
@@ -242,7 +325,13 @@
 
 	packet_check_eom();
 
-	authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+	/* user should be set if valid but we double-check here */
+	if (authctxt->valid && authctxt->user && authctxt->user[0]) {
+	    authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
+                                       authctxt->pw, 0 /* !gssapi-keyex */));
+	} else {
+	    authenticated = 0;
+	}
 
 	authctxt->postponed = 0;
 	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
@@ -276,8 +365,16 @@
 	gssbuf.value = buffer_ptr(&b);
 	gssbuf.length = buffer_len(&b);
 
+    gssapi_set_username(authctxt);
+
 	if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
-		authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
+	    if (authctxt->valid && authctxt->user && authctxt->user[0]) {
+            authenticated =
+                PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw,
+                                              0 /* !gssapi-keyex */));
+	    } else {
+            authenticated = 0;
+	    }
 	else
 		logit("GSSAPI MIC check failed");
 
@@ -292,6 +389,29 @@
 	userauth_finish(authctxt, authenticated, "gssapi-with-mic");
 }
 
+static void ssh_gssapi_userauth_error(Gssctxt *ctxt) {
+	char *errstr;
+	OM_uint32 maj,min;
+	
+	errstr=PRIVSEP(ssh_gssapi_last_error(ctxt,&maj,&min));
+	if (errstr) {
+		packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERROR);
+		packet_put_int(maj);
+		packet_put_int(min);
+		packet_put_cstring(errstr);
+		packet_put_cstring("");
+		packet_send();
+		packet_write_wait();
+		xfree(errstr);
+	}
+}
+
+Authmethod method_gsskeyex = {
+	"gssapi-keyex",
+	userauth_gsskeyex,
+	&options.gss_authentication
+};
+
 Authmethod method_gssapi = {
 	"gssapi-with-mic",
 	userauth_gssapi,
diff -Naur --exclude=autom4te.cache openssh-5.5p1/auth2.c openssh-5.5p1-gssapi/auth2.c
--- openssh-5.5p1/auth2.c	2009-06-22 01:11:07.000000000 -0500
+++ openssh-5.5p1-gssapi/auth2.c	2010-04-20 10:49:30.000000000 -0500
@@ -49,6 +49,7 @@
 #include "dispatch.h"
 #include "pathnames.h"
 #include "buffer.h"
+#include "canohost.h"
 
 #ifdef GSSAPI
 #include "ssh-gss.h"
@@ -69,16 +70,21 @@
 extern Authmethod method_kbdint;
 extern Authmethod method_hostbased;
 #ifdef GSSAPI
+extern Authmethod method_gsskeyex;
 extern Authmethod method_gssapi;
 #endif
 #ifdef JPAKE
 extern Authmethod method_jpake;
 #endif
 
+static int log_flag = 0;
+
+
 Authmethod *authmethods[] = {
 	&method_none,
 	&method_pubkey,
 #ifdef GSSAPI
+	&method_gsskeyex,
 	&method_gssapi,
 #endif
 #ifdef JPAKE
@@ -224,17 +230,64 @@
 	user = packet_get_string(NULL);
 	service = packet_get_string(NULL);
 	method = packet_get_string(NULL);
-	debug("userauth-request for user %s service %s method %s", user, service, method);
+
+#ifdef GSSAPI
+	if (user[0] == '\0') {
+	    debug("received empty username for %s", method);
+	    if (strcmp(method, "gssapi-keyex") == 0) {
+		char *lname = NULL;
+		PRIVSEP(ssh_gssapi_localname(&lname));
+		if (lname && lname[0] != '\0') {
+		    xfree(user);
+		    user = lname;
+		    debug("set username to %s from gssapi context", user);
+		} else {
+		    debug("failed to set username from gssapi context");
+		    packet_send_debug("failed to set username from gssapi context");
+		}
+	    }
+	}
+#endif
+
+	debug("userauth-request for user %s service %s method %s",
+	      user[0] ? user : "<implicit>", service, method);
+	if (!log_flag) {
+		logit("SSH: Server;Ltype: Authname;Remote: %s-%d;Name: %s", 
+		      get_remote_ipaddr(), get_remote_port(),
+              user[0] ? user : "<implicit>");
+		log_flag = 1;
+	}
 	debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
 
 	if ((style = strchr(user, ':')) != NULL)
 		*style++ = 0;
 
-	if (authctxt->attempt++ == 0) {
-		/* setup auth context */
+	/* If first time or username changed or empty username,
+	   setup/reset authentication context. */
+	if ((authctxt->attempt++ == 0) ||
+	    (strcmp(user, authctxt->user) != 0) ||
+	    (strcmp(user, "") == 0)) {
+		if (authctxt->user) {
+		    xfree(authctxt->user);
+		    authctxt->user = NULL;
+		}
+		authctxt->valid = 0;
+        authctxt->user = xstrdup(user);
+        if (strcmp(service, "ssh-connection") != 0) {
+            packet_disconnect("Unsupported service %s", service);
+        }
+#ifdef GSSAPI
+		/* If we're going to set the username based on the
+		   GSSAPI context later, then wait until then to
+		   verify it. Just put in placeholders for now. */
+		if ((strcmp(user, "") == 0) &&
+		    ((strcmp(method, "gssapi") == 0) ||
+		     (strcmp(method, "gssapi-with-mic") == 0))) {
+			authctxt->pw = fakepw();
+		} else {
+#endif
 		authctxt->pw = PRIVSEP(getpwnamallow(user));
-		authctxt->user = xstrdup(user);
-		if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
+		if (authctxt->pw) {
 			authctxt->valid = 1;
 			debug2("input_userauth_request: setting up authctxt for %s", user);
 		} else {
@@ -244,20 +297,25 @@
 			PRIVSEP(audit_event(SSH_INVALID_USER));
 #endif
 		}
+#ifdef GSSAPI
+		} /* endif for setting username based on GSSAPI context */
+#endif
 #ifdef USE_PAM
 		if (options.use_pam)
 			PRIVSEP(start_pam(authctxt));
 #endif
 		setproctitle("%s%s", authctxt->valid ? user : "unknown",
 		    use_privsep ? " [net]" : "");
-		authctxt->service = xstrdup(service);
-		authctxt->style = style ? xstrdup(style) : NULL;
-		if (use_privsep)
-			mm_inform_authserv(service, style);
-		userauth_banner();
-	} else if (strcmp(user, authctxt->user) != 0 ||
-	    strcmp(service, authctxt->service) != 0) {
-		packet_disconnect("Change of username or service not allowed: "
+		if (authctxt->attempt == 1) {
+            authctxt->service = xstrdup(service);
+            authctxt->style = style ? xstrdup(style) : NULL;
+            if (use_privsep)
+                mm_inform_authserv(service, style);
+            userauth_banner();
+		}
+	}
+	if (strcmp(service, authctxt->service) != 0) {
+		packet_disconnect("Change of service not allowed: "
 		    "(%s,%s) -> (%s,%s)",
 		    authctxt->user, authctxt->service, user, service);
 	}
@@ -274,6 +332,7 @@
 #endif
 
 	authctxt->postponed = 0;
+	authctxt->server_caused_failure = 0;
 
 	/* try to authenticate user */
 	m = authmethod_lookup(method);
@@ -344,9 +403,10 @@
 		/* now we can break out */
 		authctxt->success = 1;
 	} else {
-
+		/* Dont count server configuration issues against the client */
 		/* Allow initial try of "none" auth without failure penalty */
-		if (authctxt->attempt > 1 || strcmp(method, "none") != 0)
+		if (!authctxt->server_caused_failure &&
+		    (authctxt->attempt > 1 || strcmp(method, "none") != 0))
 			authctxt->failures++;
 		if (authctxt->failures >= options.max_authtries) {
 #ifdef SSH_AUDIT_EVENTS
diff -Naur --exclude=autom4te.cache openssh-5.5p1/buffer.c openssh-5.5p1-gssapi/buffer.c
--- openssh-5.5p1/buffer.c	2010-02-11 16:23:40.000000000 -0600
+++ openssh-5.5p1-gssapi/buffer.c	2010-04-20 10:49:30.000000000 -0500
@@ -127,7 +127,7 @@
 
 	/* Increase the size of the buffer and retry. */
 	newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ);
-	if (newlen > BUFFER_MAX_LEN)
+	if (newlen > BUFFER_MAX_LEN_HPN)
 		fatal("buffer_append_space: alloc %u not supported",
 		    newlen);
 	buffer->buf = xrealloc(buffer->buf, 1, newlen);
diff -Naur --exclude=autom4te.cache openssh-5.5p1/buffer.h openssh-5.5p1-gssapi/buffer.h
--- openssh-5.5p1/buffer.h	2010-02-11 16:23:40.000000000 -0600
+++ openssh-5.5p1-gssapi/buffer.h	2010-04-20 10:49:30.000000000 -0500
@@ -16,6 +16,9 @@
 #ifndef BUFFER_H
 #define BUFFER_H
 
+/* move the following to a more appropriate place and name */
+#define BUFFER_MAX_LEN_HPN          0x4000000  /* 64MB */
+
 typedef struct {
 	u_char	*buf;		/* Buffer for data. */
 	u_int	 alloc;		/* Number of bytes allocated for data. */
diff -Naur --exclude=autom4te.cache openssh-5.5p1/canohost.c openssh-5.5p1-gssapi/canohost.c
--- openssh-5.5p1/canohost.c	2010-01-13 05:43:34.000000000 -0600
+++ openssh-5.5p1-gssapi/canohost.c	2010-04-20 10:49:30.000000000 -0500
@@ -16,6 +16,7 @@
 
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/param.h>          /* for MAXHOSTNAMELEN */
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -438,3 +439,33 @@
 {
 	return get_port(1);
 }
+
+void
+resolve_localhost(char **host)
+{
+    struct hostent *hostinfo;
+
+    hostinfo = gethostbyname(*host);
+    if (hostinfo == NULL || hostinfo->h_name == NULL) {
+	debug("gethostbyname(%s) failed", *host);
+	return;
+    }
+    if (hostinfo->h_addrtype == AF_INET) {
+	struct in_addr addr;
+	addr = *(struct in_addr *)(hostinfo->h_addr);
+	if (ntohl(addr.s_addr) == INADDR_LOOPBACK) {
+	    char buf[MAXHOSTNAMELEN];
+	    if (gethostname(buf, sizeof(buf)) < 0) {
+		debug("gethostname() failed");
+		return;
+	    }
+	    hostinfo = gethostbyname(buf);
+	    xfree(*host);
+	    if (hostinfo == NULL || hostinfo->h_name == NULL) {
+		*host = xstrdup(buf);
+	    } else {
+		*host = xstrdup(hostinfo->h_name);
+	    }
+	}
+    }
+}
diff -Naur --exclude=autom4te.cache openssh-5.5p1/canohost.h openssh-5.5p1-gssapi/canohost.h
--- openssh-5.5p1/canohost.h	2009-06-21 04:50:08.000000000 -0500
+++ openssh-5.5p1-gssapi/canohost.h	2010-04-20 10:49:30.000000000 -0500
@@ -26,4 +26,6 @@
 int		 get_sock_port(int, int);
 void		 clear_cached_addr(void);
 
+void		 resolve_localhost(char **host);
+
 void		 ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *);
diff -Naur --exclude=autom4te.cache openssh-5.5p1/channels.c openssh-5.5p1-gssapi/channels.c
--- openssh-5.5p1/channels.c	2010-03-25 19:09:45.000000000 -0500
+++ openssh-5.5p1-gssapi/channels.c	2010-04-20 10:49:30.000000000 -0500
@@ -170,8 +170,14 @@
 static int connect_next(struct channel_connect *);
 static void channel_connect_ctx_free(struct channel_connect *);
 
+
+static int hpn_disabled = 0;
+static int hpn_buffer_size = 2 * 1024 * 1024;
+
 /* -- channel core */
 
+
+
 Channel *
 channel_by_id(int id)
 {
@@ -313,6 +319,7 @@
 	c->local_window_max = window;
 	c->local_consumed = 0;
 	c->local_maxpacket = maxpack;
+	c->dynamic_window = 0;
 	c->remote_id = -1;
 	c->remote_name = xstrdup(remote_name);
 	c->remote_window = 0;
@@ -810,11 +817,33 @@
 		FD_SET(c->sock, writeset);
 }
 
+int channel_tcpwinsz () {
+        u_int32_t tcpwinsz = 0;
+        socklen_t optsz = sizeof(tcpwinsz);
+	int ret = -1;
+
+	/* if we aren't on a socket return 128KB*/
+	if(!packet_connection_is_on_socket()) 
+	    return(128*1024);
+	ret = getsockopt(packet_get_connection_in(),
+			 SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz);
+	/* return no more than 64MB */
+	if ((ret == 0) && tcpwinsz > BUFFER_MAX_LEN_HPN)
+	    tcpwinsz = BUFFER_MAX_LEN_HPN;
+	return(tcpwinsz);
+}
+
 static void
 channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
 {
 	u_int limit = compat20 ? c->remote_window : packet_get_maxsize();
 
+        /* check buffer limits */
+	if ((!c->tcpwinsz) || (c->dynamic_window > 0))
+    	    c->tcpwinsz = channel_tcpwinsz();
+	
+	limit = MIN(limit, 2 * c->tcpwinsz);
+	
 	if (c->istate == CHAN_INPUT_OPEN &&
 	    limit > 0 &&
 	    buffer_len(&c->input) < limit &&
@@ -1784,14 +1813,21 @@
 	    c->local_maxpacket*3) ||
 	    c->local_window < c->local_window_max/2) &&
 	    c->local_consumed > 0) {
+		u_int addition = 0;
+		/* adjust max window size if we are in a dynamic environment */
+		if (c->dynamic_window && (c->tcpwinsz > c->local_window_max)) {
+			/* grow the window somewhat aggressively to maintain pressure */
+			addition = 1.5*(c->tcpwinsz - c->local_window_max);
+			c->local_window_max += addition;
+		}
 		packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
 		packet_put_int(c->remote_id);
-		packet_put_int(c->local_consumed);
+		packet_put_int(c->local_consumed + addition);
 		packet_send();
 		debug2("channel %d: window %d sent adjust %d",
 		    c->self, c->local_window,
 		    c->local_consumed);
-		c->local_window += c->local_consumed;
+		c->local_window += c->local_consumed + addition;
 		c->local_consumed = 0;
 	}
 	return 1;
@@ -2123,11 +2159,12 @@
 
 
 /* If there is data to send to the connection, enqueue some of it now. */
-void
+int
 channel_output_poll(void)
 {
 	Channel *c;
 	u_int i, len;
+	int packet_length = 0;
 
 	for (i = 0; i < channels_alloc; i++) {
 		c = channels[i];
@@ -2167,7 +2204,7 @@
 					packet_start(SSH2_MSG_CHANNEL_DATA);
 					packet_put_int(c->remote_id);
 					packet_put_string(data, dlen);
-					packet_send();
+					packet_length = packet_send();
 					c->remote_window -= dlen + 4;
 					xfree(data);
 				}
@@ -2197,7 +2234,7 @@
 				    SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA);
 				packet_put_int(c->remote_id);
 				packet_put_string(buffer_ptr(&c->input), len);
-				packet_send();
+				packet_length = packet_send();
 				buffer_consume(&c->input, len);
 				c->remote_window -= len;
 			}
@@ -2232,12 +2269,13 @@
 			packet_put_int(c->remote_id);
 			packet_put_int(SSH2_EXTENDED_DATA_STDERR);
 			packet_put_string(buffer_ptr(&c->extended), len);
-			packet_send();
+			packet_length = packet_send();
 			buffer_consume(&c->extended, len);
 			c->remote_window -= len;
 			debug2("channel %d: sent ext data %d", c->self, len);
 		}
 	}
+	return (packet_length);
 }
 
 
@@ -2613,6 +2651,15 @@
 	IPv4or6 = af;
 }
 
+
+void 
+channel_set_hpn(int external_hpn_disabled, int external_hpn_buffer_size)
+{
+      	hpn_disabled = external_hpn_disabled;
+	hpn_buffer_size = external_hpn_buffer_size;
+	debug("HPN Disabled: %d, HPN Buffer Size: %d", hpn_disabled, hpn_buffer_size);
+}
+
 static int
 channel_setup_fwd_listener(int type, const char *listen_addr,
     u_short listen_port, int *allocated_listen_port,
@@ -2766,9 +2813,15 @@
 		}
 
 		/* Allocate a channel number for the socket. */
+		/* explicitly test for hpn disabled option. if true use smaller window size */
+		if (hpn_disabled)
 		c = channel_new("port listener", type, sock, sock, -1,
 		    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
 		    0, "port listener", 1);
+ 		else
+ 			c = channel_new("port listener", type, sock, sock, -1,
+ 		    	  hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT,
+ 		    	  0, "port listener", 1); 
 		c->path = xstrdup(host);
 		c->host_port = port_to_connect;
 		c->listening_port = listen_port;
@@ -3306,10 +3359,17 @@
 	*chanids = xcalloc(num_socks + 1, sizeof(**chanids));
 	for (n = 0; n < num_socks; n++) {
 		sock = socks[n];
+		/* Is this really necassary? */
+		if (hpn_disabled) 
 		nc = channel_new("x11 listener",
 		    SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
 		    CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
 		    0, "X11 inet listener", 1);
+		else 
+			nc = channel_new("x11 listener",
+			    SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
+			    hpn_buffer_size, CHAN_X11_PACKET_DEFAULT,
+			    0, "X11 inet listener", 1);
 		nc->single_connection = single_connection;
 		(*chanids)[n] = nc->self;
 	}
diff -Naur --exclude=autom4te.cache openssh-5.5p1/channels.h openssh-5.5p1-gssapi/channels.h
--- openssh-5.5p1/channels.h	2010-01-25 20:26:22.000000000 -0600
+++ openssh-5.5p1-gssapi/channels.h	2010-04-20 10:49:30.000000000 -0500
@@ -124,8 +124,10 @@
 	u_int	local_window_max;
 	u_int	local_consumed;
 	u_int	local_maxpacket;
+	int	dynamic_window;
 	int     extended_usage;
 	int	single_connection;
+	u_int 	tcpwinsz;	
 
 	char   *ctype;		/* type */
 
@@ -159,9 +161,11 @@
 
 /* default window/packet sizes for tcp/x11-fwd-channel */
 #define CHAN_SES_PACKET_DEFAULT	(32*1024)
-#define CHAN_SES_WINDOW_DEFAULT	(64*CHAN_SES_PACKET_DEFAULT)
+#define CHAN_SES_WINDOW_DEFAULT	(4*CHAN_SES_PACKET_DEFAULT)
+
 #define CHAN_TCP_PACKET_DEFAULT	(32*1024)
-#define CHAN_TCP_WINDOW_DEFAULT	(64*CHAN_TCP_PACKET_DEFAULT)
+#define CHAN_TCP_WINDOW_DEFAULT	(4*CHAN_TCP_PACKET_DEFAULT)
+
 #define CHAN_X11_PACKET_DEFAULT	(16*1024)
 #define CHAN_X11_WINDOW_DEFAULT	(4*CHAN_X11_PACKET_DEFAULT)
 
@@ -235,7 +239,7 @@
 
 void	 channel_prepare_select(fd_set **, fd_set **, int *, u_int*, int);
 void     channel_after_select(fd_set *, fd_set *);
-void     channel_output_poll(void);
+int      channel_output_poll(void);
 
 int      channel_not_very_much_buffered_data(void);
 void     channel_close_all(void);
@@ -292,4 +296,7 @@
 void	 chan_write_failed(Channel *);
 void	 chan_obuf_empty(Channel *);
 
+/* hpn handler */
+void     channel_set_hpn(int, int);
+
 #endif
diff -Naur --exclude=autom4te.cache openssh-5.5p1/cipher.c openssh-5.5p1-gssapi/cipher.c
--- openssh-5.5p1/cipher.c	2009-01-27 23:38:41.000000000 -0600
+++ openssh-5.5p1-gssapi/cipher.c	2010-04-20 10:49:30.000000000 -0500
@@ -163,7 +163,8 @@
 	for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
 	    (p = strsep(&cp, CIPHER_SEP))) {
 		c = cipher_by_name(p);
-		if (c == NULL || c->number != SSH_CIPHER_SSH2) {
+		if (c == NULL || (c->number != SSH_CIPHER_SSH2 &&
+				  c->number != SSH_CIPHER_NONE)) {
 			debug("bad cipher %s [%s]", p, names);
 			xfree(cipher_list);
 			return 0;
@@ -337,6 +338,7 @@
 	int evplen;
 
 	switch (c->number) {
+	case SSH_CIPHER_NONE:
 	case SSH_CIPHER_SSH2:
 	case SSH_CIPHER_DES:
 	case SSH_CIPHER_BLOWFISH:
@@ -371,6 +373,7 @@
 	int evplen = 0;
 
 	switch (c->number) {
+	case SSH_CIPHER_NONE:
 	case SSH_CIPHER_SSH2:
 	case SSH_CIPHER_DES:
 	case SSH_CIPHER_BLOWFISH:
diff -Naur --exclude=autom4te.cache openssh-5.5p1/clientloop.c openssh-5.5p1-gssapi/clientloop.c
--- openssh-5.5p1/clientloop.c	2010-03-21 13:54:02.000000000 -0500
+++ openssh-5.5p1-gssapi/clientloop.c	2010-04-20 10:49:30.000000000 -0500
@@ -111,6 +111,10 @@
 #include "msg.h"
 #include "roaming.h"
 
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
 /* import options */
 extern Options options;
 
@@ -1431,6 +1435,15 @@
 		/* Do channel operations unless rekeying in progress. */
 		if (!rekeying) {
 			channel_after_select(readset, writeset);
+
+#ifdef GSSAPI
+			if (options.gss_renewal_rekey &&
+			    ssh_gssapi_credentials_updated((Gssctxt *)GSS_C_NO_CONTEXT)) {
+				debug("credentials updated - forcing rekey");
+				need_rekeying = 1;
+			}
+#endif
+
 			if (need_rekeying || packet_need_rekeying()) {
 				debug("need rekeying");
 				xxx_kex->done = 0;
@@ -1701,9 +1714,15 @@
 	sock = x11_connect_display();
 	if (sock < 0)
 		return NULL;
+	/* again is this really necessary for X11? */
+	if (options.hpn_disabled) 
 	c = channel_new("x11",
 	    SSH_CHANNEL_X11_OPEN, sock, sock, -1,
 	    CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
+	else 
+		c = channel_new("x11",
+		    SSH_CHANNEL_X11_OPEN, sock, sock, -1,
+		    options.hpn_buffer_size, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
 	c->force_drain = 1;
 	return c;
 }
@@ -1723,9 +1742,15 @@
 	sock = ssh_get_authentication_socket();
 	if (sock < 0)
 		return NULL;
+	if (options.hpn_disabled) 
 	c = channel_new("authentication agent connection",
 	    SSH_CHANNEL_OPEN, sock, sock, -1,
-	    CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
+		    CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
+		    "authentication agent connection", 1);
+       else
+	c = channel_new("authentication agent connection",
+	    SSH_CHANNEL_OPEN, sock, sock, -1,
+                   options.hpn_buffer_size, options.hpn_buffer_size, 0,
 	    "authentication agent connection", 1);
 	c->force_drain = 1;
 	return c;
@@ -1753,10 +1778,18 @@
 		return -1;
 	}
 
+	if(options.hpn_disabled)
+	c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
+				CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
+				0, "tun", 1);
+	else
 	c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1,
-	    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
+				options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT,
+				0, "tun", 1);
 	c->datagram = 1;
 
+
+
 #if defined(SSH_TUN_FILTER)
 	if (options.tun_open == SSH_TUNMODE_POINTOPOINT)
 		channel_register_filter(c->self, sys_tun_infilter,
diff -Naur --exclude=autom4te.cache openssh-5.5p1/compat.c openssh-5.5p1-gssapi/compat.c
--- openssh-5.5p1/compat.c	2008-11-03 02:20:14.000000000 -0600
+++ openssh-5.5p1-gssapi/compat.c	2010-04-20 10:49:30.000000000 -0500
@@ -170,6 +170,15 @@
 		    strlen(check[i].pat), 0) == 1) {
 			debug("match: %s pat %s", version, check[i].pat);
 			datafellows = check[i].bugs;
+			/* Check to see if the remote side is OpenSSH and not HPN */
+			if(strstr(version,"OpenSSH") != NULL)
+			{
+				if (strstr(version,"hpn") == NULL)
+				{
+					datafellows |= SSH_BUG_LARGEWINDOW;
+					debug("Remote is NON-HPN aware");
+				}
+			}
 			return;
 		}
 	}
diff -Naur --exclude=autom4te.cache openssh-5.5p1/compat.h openssh-5.5p1-gssapi/compat.h
--- openssh-5.5p1/compat.h	2008-11-03 02:20:14.000000000 -0600
+++ openssh-5.5p1-gssapi/compat.h	2010-04-20 10:49:30.000000000 -0500
@@ -58,6 +58,7 @@
 #define SSH_OLD_FORWARD_ADDR	0x01000000
 #define SSH_BUG_RFWD_ADDR	0x02000000
 #define SSH_NEW_OPENSSH		0x04000000
+#define SSH_BUG_LARGEWINDOW     0x08000000
 
 void     enable_compat13(void);
 void     enable_compat20(void);
diff -Naur --exclude=autom4te.cache openssh-5.5p1/config.h.in openssh-5.5p1-gssapi/config.h.in
--- openssh-5.5p1/config.h.in	2010-04-15 19:17:09.000000000 -0500
+++ openssh-5.5p1-gssapi/config.h.in	2010-04-20 10:49:34.000000000 -0500
@@ -1,5 +1,8 @@
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Define this if you want to use AFS/Kerberos 5 option, which runs aklog. */
+#undef AFS_KRB5
+
 /* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address
    */
 #undef AIX_GETNAMEINFO_HACK
@@ -7,6 +10,9 @@
 /* Define if your AIX loginfailed() function takes 4 arguments (AIX >= 5.2) */
 #undef AIX_LOGINFAILED_4ARG
 
+/* Define this if you want to use AFS/Kerberos 5 option, which runs aklog. */
+#undef AKLOG_PATH
+
 /* System only supports IPv4 audit records */
 #undef AU_IPv4
 
@@ -16,7 +22,7 @@
 /* Define if cmsg_type is not passed correctly */
 #undef BROKEN_CMSG_TYPE
 
-/* getaddrinfo is broken (if present) */
+/* Define if getaddrinfo is broken) */
 #undef BROKEN_GETADDRINFO
 
 /* getgroups(0,NULL) will return -1 */
@@ -143,6 +149,9 @@
 /* Define if your system glob() function has gl_matchc options in glob_t */
 #undef GLOB_HAS_GL_MATCHC
 
+/* Define if you want GSI/Globus authentication support. */
+#undef GSI
+
 /* Define this if you want GSSAPI support in the version 2 protocol */
 #undef GSSAPI
 
@@ -461,6 +470,16 @@
 /* Define to 1 if you have the `glob' function. */
 #undef HAVE_GLOB
 
+/* Define to 1 if you have the `globus_gss_assist_map_and_authorize' function.
+   */
+#undef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE
+
+/* Have Globus Usage */
+#undef HAVE_GLOBUS_USAGE
+
+/* Have Globus Usage send_array */
+#undef HAVE_GLOBUS_USAGE_SEND_ARRAY
+
 /* Define to 1 if you have the <glob.h> header file. */
 #undef HAVE_GLOB_H
 
@@ -1232,6 +1251,9 @@
 /* Set this to your mail directory if you don't have maillock.h */
 #undef MAIL_DIRECTORY
 
+/* Define this if you're building with GSSAPI MechGlue. */
+#undef MECHGLUE
+
 /* Define on *nto-qnx systems */
 #undef MISSING_FD_MASK
 
@@ -1296,6 +1318,9 @@
 /* read(1) can return 0 for a non-closed fd */
 #undef PTY_ZEROREAD
 
+/* Define this if you want support for startup/shutdown hooks */
+#undef SESSION_HOOKS
+
 /* Define if your platform breaks doing a seteuid before a setuid */
 #undef SETEUID_BREAKS_SETUID
 
@@ -1384,6 +1409,9 @@
 /* Use btmp to log bad logins */
 #undef USE_BTMP
 
+/* platform uses an in-memory credentials cache */
+#undef USE_CCAPI
+
 /* Use libedit for sftp */
 #undef USE_LIBEDIT
 
@@ -1396,6 +1424,9 @@
 /* Use PIPES instead of a socketpair() */
 #undef USE_PIPES
 
+/* platform has the Security Authorization Session API */
+#undef USE_SECURITY_SESSION_API
+
 /* Define if you have Solaris process contracts */
 #undef USE_SOLARIS_PROCESS_CONTRACTS
 
diff -Naur --exclude=autom4te.cache openssh-5.5p1/configure openssh-5.5p1-gssapi/configure
--- openssh-5.5p1/configure	2010-04-15 19:17:11.000000000 -0500
+++ openssh-5.5p1-gssapi/configure	2010-04-20 10:49:36.000000000 -0500
@@ -714,6 +714,7 @@
 PROG_IPCS
 PROG_TAIL
 INSTALL_SSH_PRNG_CMDS
+INSTALL_GSISSH
 KRB5CONF
 PRIVSEP_PATH
 xauth_path
@@ -1326,6 +1327,10 @@
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-gsi              Enable Globus GSI authentication support
+  --with-globus           Enable Globus GSI authentication support
+  --with-globus-static    Link statically with Globus GSI libraries
+  --with-globus-flavor=TYPE  Specify Globus flavor type (ex: gcc32dbg)
   --without-stackprotect  Don't use compiler's stack protection
   --without-rpath         Disable auto-added -R linker paths
   --with-cflags           Specify additional flags to pass to compiler
@@ -1351,7 +1356,10 @@
   --with-entropy-timeout  Specify entropy gathering command timeout (msec)
   --with-privsep-user=user Specify non-privileged user for privilege separation
   --with-selinux          Enable SELinux support
+  --with-mechglue=PATH    Build with GSSAPI mechglue library
   --with-kerberos5=PATH   Enable Kerberos 5 support
+  --with-afs-krb5[=AKLOG_PATH]  Enable aklog to get token (default=/usr/bin/aklog).
+  --with-session-hooks    Enable hooks for executing external commands                                       before/after a session
   --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty)
   --with-xauth=PATH       Specify path to xauth program
   --with-mantype=man|cat|doc  Set man page type
@@ -1811,6 +1819,155 @@
 
 ac_config_headers="$ac_config_headers config.h"
 
+
+# Handle Globus configuration right away, because the Globus flavor
+# determines our compiler options.
+
+# Check whether the user wants GSI (Globus) support
+gsi_path="no"
+
+# Check whether --with-gsi was given.
+if test "${with_gsi+set}" = set; then
+  withval=$with_gsi;
+		gsi_path="$withval"
+
+
+fi
+
+
+
+# Check whether --with-globus was given.
+if test "${with_globus+set}" = set; then
+  withval=$with_globus;
+		gsi_path="$withval"
+
+
+fi
+
+
+
+# Check whether --with-globus-static was given.
+if test "${with_globus_static+set}" = set; then
+  withval=$with_globus_static;
+		gsi_static="-static"
+		if test "x$gsi_path" = "xno" ; then
+			gsi_path="$withval"
+		fi
+
+
+fi
+
+
+# Check whether the user has a Globus flavor type
+globus_flavor_type="no"
+
+# Check whether --with-globus-flavor was given.
+if test "${with_globus_flavor+set}" = set; then
+  withval=$with_globus_flavor;
+		globus_flavor_type="$withval"
+		if test "x$gsi_path" = "xno" ; then
+			gsi_path="yes"
+		fi
+
+
+fi
+
+
+if test "x$gsi_path" != "xno" ; then
+	# Globus GSSAPI configuration
+	{ echo "$as_me:$LINENO: checking for Globus GSI" >&5
+echo $ECHO_N "checking for Globus GSI... $ECHO_C" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define GSI 1
+_ACEOF
+
+
+	if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then
+		{ { echo "$as_me:$LINENO: error: Previously configured GSSAPI library conflicts with Globus GSI." >&5
+echo "$as_me: error: Previously configured GSSAPI library conflicts with Globus GSI." >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+	if test -z "$GSSAPI"; then
+		cat >>confdefs.h <<\_ACEOF
+#define GSSAPI 1
+_ACEOF
+
+		GSSAPI="GSI"
+	fi
+
+	if test "x$gsi_path" = "xyes" ; then
+		if test -z "$GLOBUS_LOCATION" ; then
+			{ { echo "$as_me:$LINENO: error: GLOBUS_LOCATION environment variable must be set." >&5
+echo "$as_me: error: GLOBUS_LOCATION environment variable must be set." >&2;}
+   { (exit 1); exit 1; }; }
+		else
+			gsi_path="$GLOBUS_LOCATION"
+		fi
+	fi
+	GLOBUS_LOCATION="$gsi_path"
+	export GLOBUS_LOCATION
+	if test ! -d "$GLOBUS_LOCATION" ; then
+		{ { echo "$as_me:$LINENO: error: Cannot find Globus installation.  Set GLOBUS_LOCATION environment variable." >&5
+echo "$as_me: error: Cannot find Globus installation.  Set GLOBUS_LOCATION environment variable." >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+
+        if test "x$globus_flavor_type" = "xno" ; then
+                { { echo "$as_me:$LINENO: error: --with-globus-flavor=TYPE must be specified" >&5
+echo "$as_me: error: --with-globus-flavor=TYPE must be specified" >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+        if test "x$globus_flavor_type" = "xyes" ; then
+                { { echo "$as_me:$LINENO: error: --with-globus-flavor=TYPE must specify a flavor type" >&5
+echo "$as_me: error: --with-globus-flavor=TYPE must specify a flavor type" >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+
+	GLOBUS_INCLUDE="${gsi_path}/include/${globus_flavor_type}"
+	if test ! -d "$GLOBUS_INCLUDE" ; then
+		{ { echo "$as_me:$LINENO: error: Cannot find Globus flavor-specific include directory: ${GLOBUS_INCLUDE}" >&5
+echo "$as_me: error: Cannot find Globus flavor-specific include directory: ${GLOBUS_INCLUDE}" >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+
+	if test -x ${gsi_path}/bin/globus-makefile-header ; then
+		${gsi_path}/bin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | sed 's/ = \(.*\)/="\1"/' > ./gpt_build_tmp.sh
+	elif test -x ${gsi_path}/sbin/globus-makefile-header ; then
+		${gsi_path}/sbin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | sed 's/ = \(.*\)/="\1"/' > ./gpt_build_tmp.sh
+	else
+		{ { echo "$as_me:$LINENO: error: Cannot find globus-makefile-header: Globus installation is incomplete" >&5
+echo "$as_me: error: Cannot find globus-makefile-header: Globus installation is incomplete" >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+	. ./gpt_build_tmp.sh
+	if test -z "$GLOBUS_PKG_LIBS" ; then
+		{ { echo "$as_me:$LINENO: error: globus-makefile-header failed" >&5
+echo "$as_me: error: globus-makefile-header failed" >&2;}
+   { (exit 1); exit 1; }; }
+	fi
+
+    { echo "$as_me:$LINENO: result: $GLOBUS_LOCATION" >&5
+echo "${ECHO_T}$GLOBUS_LOCATION" >&6; }
+	cat >>confdefs.h <<\_ACEOF
+#define HAVE_GSSAPI_H 1
+_ACEOF
+
+
+    CC="$GLOBUS_CC"
+    CFLAGS="$GLOBUS_CFLAGS"
+    CPP="$GLOBUS_CPP"
+	CPPFLAGS="$GLOBUS_CPPFLAGS $GLOBUS_INCLUDES"
+	LIBS="$LIBS $GLOBUS_LIBS $GLOBUS_PKG_LIBS"
+    LD="$GLOBUS_LD"
+	LDFLAGS="$LDFLAGS $GLOBUS_LDFLAGS"
+
+	INSTALL_GSISSH="yes"
+else
+	INSTALL_GSISSH=""
+fi
+# End Globus/GSI section
+
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -7266,64 +7423,14 @@
 
 	;;
 *-*-darwin*)
-	{ echo "$as_me:$LINENO: checking if we have working getaddrinfo" >&5
-echo $ECHO_N "checking if we have working getaddrinfo... $ECHO_C" >&6; }
-	if test "$cross_compiling" = yes; then
-  { echo "$as_me:$LINENO: result: assume it is working" >&5
-echo "${ECHO_T}assume it is working" >&6; }
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <mach-o/dyld.h>
-main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
-		exit(0);
-	else
-		exit(1);
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  { echo "$as_me:$LINENO: result: working" >&5
-echo "${ECHO_T}working" >&6; }
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-{ echo "$as_me:$LINENO: result: buggy" >&5
-echo "${ECHO_T}buggy" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
 #define BROKEN_GETADDRINFO 1
 _ACEOF
 
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
+	cat >>confdefs.h <<\_ACEOF
+#define BROKEN_GETADDRINFO 1
+_ACEOF
 
 	cat >>confdefs.h <<\_ACEOF
 #define SETEUID_BREAKS_SETUID 1
@@ -7362,6 +7469,117 @@
 #define SSH_TUN_PREPEND_AF 1
 _ACEOF
 
+	{ echo "$as_me:$LINENO: checking if we have the Security Authorization Session API" >&5
+echo $ECHO_N "checking if we have the Security Authorization Session API... $ECHO_C" >&6; }
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <Security/AuthSession.h>
+int
+main ()
+{
+SessionCreate(0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_use_security_session_api="yes"
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_SECURITY_SESSION_API 1
+_ACEOF
+
+		 LIBS="$LIBS -framework Security"
+		 { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_use_security_session_api="no"
+		 { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+	{ echo "$as_me:$LINENO: checking if we have an in-memory credentials cache" >&5
+echo $ECHO_N "checking if we have an in-memory credentials cache... $ECHO_C" >&6; }
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <Kerberos/Kerberos.h>
+int
+main ()
+{
+cc_context_t c;
+		 (void) cc_initialize (&c, 0, NULL, NULL);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_CCAPI 1
+_ACEOF
+
+		 LIBS="$LIBS -framework Security"
+		 { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+		 if test "x$ac_cv_use_security_session_api" = "xno"; then
+			{ { echo "$as_me:$LINENO: error: *** Need a security framework to use the credentials cache API ***" >&5
+echo "$as_me: error: *** Need a security framework to use the credentials cache API ***" >&2;}
+   { (exit 1); exit 1; }; }
+		fi
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	{ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 	{ echo "$as_me:$LINENO: checking whether AU_IPv4 is declared" >&5
 echo $ECHO_N "checking whether AU_IPv4 is declared... $ECHO_C" >&6; }
@@ -11754,37 +11972,18 @@
 done
 
 
-
-for ac_func in strftime
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+{ echo "$as_me:$LINENO: checking for library containing globus_usage_stats_send" >&5
+echo $ECHO_N "checking for library containing globus_usage_stats_send... $ECHO_C" >&6; }
+if test "${ac_cv_search_globus_usage_stats_send+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  cat >conftest.$ac_ext <<_ACEOF
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
-   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char $ac_func (); below.
-    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-    <limits.h> exists even on freestanding compilers.  */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
 
 /* Override any GCC internal prototype to avoid an error.
    Use char because int might match the return type of a GCC
@@ -11792,23 +11991,23 @@
 #ifdef __cplusplus
 extern "C"
 #endif
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined __stub_$ac_func || defined __stub___$ac_func
-choke me
-#endif
-
+char globus_usage_stats_send ();
 int
 main ()
 {
-return $ac_func ();
+return globus_usage_stats_send ();
   ;
   return 0;
 }
 _ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
+for ac_lib in '' globus_usage globus_usage_${globus_flavor_type}; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
 if { (ac_try="$ac_link"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
@@ -11826,18 +12025,212 @@
 	 test ! -s conftest.err
        } && test -s conftest$ac_exeext &&
        $as_test_x conftest$ac_exeext; then
-  eval "$as_ac_var=yes"
+  ac_cv_search_globus_usage_stats_send=$ac_res
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-	eval "$as_ac_var=no"
+
 fi
 
 rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
+      conftest$ac_exeext
+  if test "${ac_cv_search_globus_usage_stats_send+set}" = set; then
+  break
 fi
-ac_res=`eval echo '${'$as_ac_var'}'`
+done
+if test "${ac_cv_search_globus_usage_stats_send+set}" = set; then
+  :
+else
+  ac_cv_search_globus_usage_stats_send=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_globus_usage_stats_send" >&5
+echo "${ECHO_T}$ac_cv_search_globus_usage_stats_send" >&6; }
+ac_res=$ac_cv_search_globus_usage_stats_send
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GLOBUS_USAGE 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for library containing globus_usage_stats_send_array" >&5
+echo $ECHO_N "checking for library containing globus_usage_stats_send_array... $ECHO_C" >&6; }
+if test "${ac_cv_search_globus_usage_stats_send_array+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char globus_usage_stats_send_array ();
+int
+main ()
+{
+return globus_usage_stats_send_array ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' globus_usage globus_usage_${globus_flavor_type}; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_search_globus_usage_stats_send_array=$ac_res
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext
+  if test "${ac_cv_search_globus_usage_stats_send_array+set}" = set; then
+  break
+fi
+done
+if test "${ac_cv_search_globus_usage_stats_send_array+set}" = set; then
+  :
+else
+  ac_cv_search_globus_usage_stats_send_array=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_globus_usage_stats_send_array" >&5
+echo "${ECHO_T}$ac_cv_search_globus_usage_stats_send_array" >&6; }
+ac_res=$ac_cv_search_globus_usage_stats_send_array
+if test "$ac_res" != no; then
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GLOBUS_USAGE_SEND_ARRAY 1
+_ACEOF
+
+fi
+
+
+
+for ac_func in strftime
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
 	       { echo "$as_me:$LINENO: result: $ac_res" >&5
 echo "${ECHO_T}$ac_res" >&6; }
 if test `eval echo '${'$as_ac_var'}'` = yes; then
@@ -16509,7 +16902,9 @@
 
 fi
 
+if test -z "$GLOBUS_LDFLAGS" ; then
 LIBS="-lcrypto $LIBS"
+fi
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -26922,56 +27317,322 @@
 fi
 
 
-# Check whether user wants Kerberos 5 support
-KRB5_MSG="no"
-
-# Check whether --with-kerberos5 was given.
-if test "${with_kerberos5+set}" = set; then
-  withval=$with_kerberos5;  if test "x$withval" != "xno" ; then
-		if test "x$withval" = "xyes" ; then
-			KRB5ROOT="/usr/local"
-		else
-			KRB5ROOT=${withval}
-		fi
+# Finish configuring Globus GSSAPI
+if test "x$gsi_path" != "xno" ; then
+	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
+	# test that we got the libraries OK
+	cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
 
+int
+main ()
+{
 
-cat >>confdefs.h <<\_ACEOF
-#define KRB5 1
+  ;
+  return 0;
+}
 _ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
-		KRB5_MSG="yes"
 
-		# Extract the first word of "krb5-config", so it can be a program name with args.
-set dummy krb5-config; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_KRB5CONF+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  case $KRB5CONF in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_KRB5CONF="$KRB5CONF" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-as_dummy="$KRB5ROOT/bin:$PATH"
-for as_dir in $as_dummy
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_path_KRB5CONF="$as_dir/$ac_word$ac_exec_ext"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-IFS=$as_save_IFS
+			{ { echo "$as_me:$LINENO: error: link with Globus libraries failed" >&5
+echo "$as_me: error: link with Globus libraries failed" >&2;}
+   { (exit 1); exit 1; }; }
+
 
-  test -z "$ac_cv_path_KRB5CONF" && ac_cv_path_KRB5CONF="$KRB5ROOT/bin/krb5-config"
-  ;;
-esac
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+
+for ac_func in globus_gss_assist_map_and_authorize
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  eval "$as_ac_var=yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+fi
+
+
+# Check whether the user wants GSSAPI mechglue support
+
+# Check whether --with-mechglue was given.
+if test "${with_mechglue+set}" = set; then
+  withval=$with_mechglue;
+		{ echo "$as_me:$LINENO: checking for mechglue library" >&5
+echo $ECHO_N "checking for mechglue library... $ECHO_C" >&6; }
+
+		if test -e ${withval}/libgssapi.a ; then
+		    mechglue_lib=${withval}/libgssapi.a
+		elif test -e ${withval}/lib/libgssapi.a ; then
+		    mechglue_lib=${withval}/lib/libgssapi.a
+		else
+		    { { echo "$as_me:$LINENO: error: \"Can't find libgssapi in ${withval}\"" >&5
+echo "$as_me: error: \"Can't find libgssapi in ${withval}\"" >&2;}
+   { (exit 1); exit 1; }; };
+		fi
+		LIBS="${mechglue_lib} $LIBS"
+		{ echo "$as_me:$LINENO: result: ${mechglue_lib}" >&5
+echo "${ECHO_T}${mechglue_lib}" >&6; }
+
+
+{ echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_dl_dlopen=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+  LIBS="-ldl $LIBS"
+
+fi
+
+		if test $ac_cv_lib_dl_dlopen = yes; then
+		   LDFLAGS="$LDFLAGS -ldl -Wl,-Bsymbolic"
+		fi
+
+		cat >>confdefs.h <<\_ACEOF
+#define GSSAPI 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define MECHGLUE 1
+_ACEOF
+
+		GSSAPI="mechglue"
+
+
+fi
+
+
+
+# Check whether user wants Kerberos 5 support
+KRB5_MSG="no"
+
+# Check whether --with-kerberos5 was given.
+if test "${with_kerberos5+set}" = set; then
+  withval=$with_kerberos5;  if test "x$withval" != "xno" ; then
+		if test "x$withval" = "xyes" ; then
+			KRB5ROOT="/usr/local"
+		else
+			KRB5ROOT=${withval}
+		fi
+
+
+cat >>confdefs.h <<\_ACEOF
+#define KRB5 1
+_ACEOF
+
+		KRB5_MSG="yes"
+
+		# Extract the first word of "krb5-config", so it can be a program name with args.
+set dummy krb5-config; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_KRB5CONF+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $KRB5CONF in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_KRB5CONF="$KRB5CONF" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy="$KRB5ROOT/bin:$PATH"
+for as_dir in $as_dummy
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_KRB5CONF="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_KRB5CONF" && ac_cv_path_KRB5CONF="$KRB5ROOT/bin/krb5-config"
+  ;;
+esac
 fi
 KRB5CONF=$ac_cv_path_KRB5CONF
 if test -n "$KRB5CONF"; then
@@ -27836,7 +28497,158 @@
 
 
 
-		fi
+			# If we're using some other GSSAPI
+			if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then
+				{ { echo "$as_me:$LINENO: error: $GSSAPI GSSAPI library conflicts with Kerberos support.  Use mechglue instead." >&5
+echo "$as_me: error: $GSSAPI GSSAPI library conflicts with Kerberos support.  Use mechglue instead." >&2;}
+   { (exit 1); exit 1; }; }
+			fi
+
+			if test -z "$GSSAPI"; then
+				GSSAPI="KRB5";
+			fi
+
+			oldCPP="$CPPFLAGS"
+			CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
+			if test "${ac_cv_header_gssapi_krb5_h+set}" = set; then
+  { echo "$as_me:$LINENO: checking for gssapi_krb5.h" >&5
+echo $ECHO_N "checking for gssapi_krb5.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_gssapi_krb5_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_gssapi_krb5_h" >&5
+echo "${ECHO_T}$ac_cv_header_gssapi_krb5_h" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking gssapi_krb5.h usability" >&5
+echo $ECHO_N "checking gssapi_krb5.h usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <gssapi_krb5.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking gssapi_krb5.h presence" >&5
+echo $ECHO_N "checking gssapi_krb5.h presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <gssapi_krb5.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: gssapi_krb5.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: gssapi_krb5.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: gssapi_krb5.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: gssapi_krb5.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: gssapi_krb5.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: gssapi_krb5.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: gssapi_krb5.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: gssapi_krb5.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: gssapi_krb5.h: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## ------------------------------------------- ##
+## Report this to openssh-unix-dev@mindrot.org ##
+## ------------------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for gssapi_krb5.h" >&5
+echo $ECHO_N "checking for gssapi_krb5.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_gssapi_krb5_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_gssapi_krb5_h=$ac_header_preproc
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_gssapi_krb5_h" >&5
+echo "${ECHO_T}$ac_cv_header_gssapi_krb5_h" >&6; }
+
+fi
+if test $ac_cv_header_gssapi_krb5_h = yes; then
+  :
+else
+   CPPFLAGS="$oldCPP"
+fi
+
+
+
+                fi
 		if test ! -z "$need_dash_r" ; then
 			LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib"
 		fi
@@ -28377,6 +29189,61 @@
 fi
 
 
+# Check whether user wants AFS_KRB5 support
+AFS_KRB5_MSG="no"
+
+# Check whether --with-afs-krb5 was given.
+if test "${with_afs_krb5+set}" = set; then
+  withval=$with_afs_krb5;
+		if test "x$withval" != "xno" ; then
+
+			if test "x$withval" != "xyes" ; then
+
+cat >>confdefs.h <<_ACEOF
+#define AKLOG_PATH "$withval"
+_ACEOF
+
+			else
+
+cat >>confdefs.h <<_ACEOF
+#define AKLOG_PATH "/usr/bin/aklog"
+_ACEOF
+
+			fi
+
+			if test -z "$KRB5ROOT" ; then
+				{ echo "$as_me:$LINENO: WARNING: AFS_KRB5 requires Kerberos 5 support, build may fail" >&5
+echo "$as_me: WARNING: AFS_KRB5 requires Kerberos 5 support, build may fail" >&2;}
+			fi
+
+			LIBS="-lkrbafs -lkrb4 $LIBS"
+			if test ! -z "$AFS_LIBS" ; then
+				LIBS="$LIBS $AFS_LIBS"
+			fi
+
+cat >>confdefs.h <<\_ACEOF
+#define AFS_KRB5 1
+_ACEOF
+
+			AFS_KRB5_MSG="yes"
+		fi
+
+
+fi
+
+
+
+# Check whether --with-session-hooks was given.
+if test "${with_session_hooks+set}" = set; then
+  withval=$with_session_hooks;
+cat >>confdefs.h <<\_ACEOF
+#define SESSION_HOOKS 1
+_ACEOF
+
+
+fi
+
+
 # Looking for programs, paths and files
 
 PRIVSEP_PATH=/var/empty
@@ -28458,7 +29325,10 @@
 fi
 
 
+# strip causes problems with GSI libraries...
+if test -z "$GLOBUS_LDFLAGS" ; then
 STRIP_OPT=-s
+fi
 # Check whether --enable-strip was given.
 if test "${enable_strip+set}" = set; then
   enableval=$enable_strip;
@@ -30424,6 +31294,7 @@
 for ac_last_try in false false false false false :; do
   cat >conf$$subs.sed <<_ACEOF
 INSTALL_SSH_PRNG_CMDS!$INSTALL_SSH_PRNG_CMDS$ac_delim
+INSTALL_GSISSH!$INSTALL_GSISSH$ac_delim
 KRB5CONF!$KRB5CONF$ac_delim
 PRIVSEP_PATH!$PRIVSEP_PATH$ac_delim
 xauth_path!$xauth_path$ac_delim
@@ -30439,7 +31310,7 @@
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 14; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 15; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff -Naur --exclude=autom4te.cache openssh-5.5p1/configure.ac openssh-5.5p1-gssapi/configure.ac
--- openssh-5.5p1/configure.ac	2010-04-10 07:58:01.000000000 -0500
+++ openssh-5.5p1-gssapi/configure.ac	2010-04-20 10:49:30.000000000 -0500
@@ -19,6 +19,115 @@
 AC_CONFIG_SRCDIR([ssh.c])
 
 AC_CONFIG_HEADER(config.h)
+
+# Handle Globus configuration right away, because the Globus flavor
+# determines our compiler options.
+
+# Check whether the user wants GSI (Globus) support
+gsi_path="no"
+AC_ARG_WITH(gsi,
+	[  --with-gsi              Enable Globus GSI authentication support],
+	[
+		gsi_path="$withval"
+	]
+)
+
+AC_ARG_WITH(globus,
+	[  --with-globus           Enable Globus GSI authentication support],
+	[
+		gsi_path="$withval"
+	]
+)
+
+AC_ARG_WITH(globus-static,
+	[  --with-globus-static    Link statically with Globus GSI libraries],
+	[
+		gsi_static="-static"
+		if test "x$gsi_path" = "xno" ; then
+			gsi_path="$withval"
+		fi
+	]
+)
+
+# Check whether the user has a Globus flavor type
+globus_flavor_type="no"
+AC_ARG_WITH(globus-flavor,
+	[  --with-globus-flavor=TYPE  Specify Globus flavor type (ex: gcc32dbg)],
+	[
+		globus_flavor_type="$withval"
+		if test "x$gsi_path" = "xno" ; then
+			gsi_path="yes"
+		fi
+	]
+)
+
+if test "x$gsi_path" != "xno" ; then
+	# Globus GSSAPI configuration
+	AC_MSG_CHECKING(for Globus GSI)
+	AC_DEFINE(GSI, 1, [Define if you want GSI/Globus authentication support.])
+
+	if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then
+		AC_MSG_ERROR([Previously configured GSSAPI library conflicts with Globus GSI.])
+	fi
+	if test -z "$GSSAPI"; then
+		AC_DEFINE(GSSAPI)
+		GSSAPI="GSI"
+	fi
+
+	if test "x$gsi_path" = "xyes" ; then
+		if test -z "$GLOBUS_LOCATION" ; then
+			AC_MSG_ERROR(GLOBUS_LOCATION environment variable must be set.)
+		else
+			gsi_path="$GLOBUS_LOCATION"
+		fi
+	fi
+	GLOBUS_LOCATION="$gsi_path"
+	export GLOBUS_LOCATION
+	if test ! -d "$GLOBUS_LOCATION" ; then
+		AC_MSG_ERROR(Cannot find Globus installation.  Set GLOBUS_LOCATION environment variable.)
+	fi
+
+        if test "x$globus_flavor_type" = "xno" ; then
+                AC_MSG_ERROR(--with-globus-flavor=TYPE must be specified)
+	fi
+        if test "x$globus_flavor_type" = "xyes" ; then
+                AC_MSG_ERROR(--with-globus-flavor=TYPE must specify a flavor type)
+	fi
+
+	GLOBUS_INCLUDE="${gsi_path}/include/${globus_flavor_type}"
+	if test ! -d "$GLOBUS_INCLUDE" ; then
+		AC_MSG_ERROR(Cannot find Globus flavor-specific include directory: ${GLOBUS_INCLUDE})
+	fi
+	
+	if test -x ${gsi_path}/bin/globus-makefile-header ; then
+		${gsi_path}/bin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | sed 's/ = \(.*\)/="\1"/' > ./gpt_build_tmp.sh
+	elif test -x ${gsi_path}/sbin/globus-makefile-header ; then
+		${gsi_path}/sbin/globus-makefile-header --flavor=${globus_flavor_type} ${gsi_static} globus_gss_assist | sed 's/ = \(.*\)/="\1"/' > ./gpt_build_tmp.sh
+	else
+		AC_MSG_ERROR(Cannot find globus-makefile-header: Globus installation is incomplete)
+	fi
+	. ./gpt_build_tmp.sh
+	if test -z "$GLOBUS_PKG_LIBS" ; then
+		AC_MSG_ERROR(globus-makefile-header failed)
+	fi
+
+    AC_MSG_RESULT($GLOBUS_LOCATION)
+	AC_DEFINE(HAVE_GSSAPI_H)
+
+    CC="$GLOBUS_CC"
+    CFLAGS="$GLOBUS_CFLAGS"
+    CPP="$GLOBUS_CPP"
+	CPPFLAGS="$GLOBUS_CPPFLAGS $GLOBUS_INCLUDES"
+	LIBS="$LIBS $GLOBUS_LIBS $GLOBUS_PKG_LIBS"
+    LD="$GLOBUS_LD"
+	LDFLAGS="$LDFLAGS $GLOBUS_LDFLAGS"
+
+	INSTALL_GSISSH="yes"
+else
+	INSTALL_GSISSH=""
+fi
+# End Globus/GSI section
+
 AC_PROG_CC
 AC_CANONICAL_HOST
 AC_C_BIGENDIAN
@@ -456,16 +565,8 @@
 	AC_DEFINE(BROKEN_SETREGID)
 	;;
 *-*-darwin*)
-	AC_MSG_CHECKING(if we have working getaddrinfo)
-	AC_TRY_RUN([#include <mach-o/dyld.h>
-main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
-		exit(0);
-	else
-		exit(1);
-}], [AC_MSG_RESULT(working)],
-	[AC_MSG_RESULT(buggy)
-	AC_DEFINE(BROKEN_GETADDRINFO, 1, [getaddrinfo is broken (if present)])],
-	[AC_MSG_RESULT(assume it is working)])
+	AC_DEFINE(BROKEN_GETADDRINFO, 1, [Define if getaddrinfo is broken)])
+	AC_DEFINE(BROKEN_GETADDRINFO)
 	AC_DEFINE(SETEUID_BREAKS_SETUID)
 	AC_DEFINE(BROKEN_SETREUID)
 	AC_DEFINE(BROKEN_SETREGID)
@@ -477,6 +578,30 @@
 	    [Use tunnel device compatibility to OpenBSD])
 	AC_DEFINE(SSH_TUN_PREPEND_AF, 1,
 	    [Prepend the address family to IP tunnel traffic])
+	AC_MSG_CHECKING(if we have the Security Authorization Session API)
+	AC_TRY_COMPILE([#include <Security/AuthSession.h>],
+		[SessionCreate(0, 0);],
+		[ac_cv_use_security_session_api="yes"
+		 AC_DEFINE(USE_SECURITY_SESSION_API, 1, 
+			[platform has the Security Authorization Session API])
+		 LIBS="$LIBS -framework Security"
+		 AC_MSG_RESULT(yes)],
+		[ac_cv_use_security_session_api="no"
+		 AC_MSG_RESULT(no)])
+	AC_MSG_CHECKING(if we have an in-memory credentials cache)
+	AC_TRY_COMPILE(
+		[#include <Kerberos/Kerberos.h>],
+		[cc_context_t c;
+		 (void) cc_initialize (&c, 0, NULL, NULL);],
+		[AC_DEFINE(USE_CCAPI, 1, 
+			[platform uses an in-memory credentials cache])
+		 LIBS="$LIBS -framework Security"
+		 AC_MSG_RESULT(yes)
+		 if test "x$ac_cv_use_security_session_api" = "xno"; then
+			AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***)
+		fi],
+		[AC_MSG_RESULT(no)]
+	)
 	m4_pattern_allow(AU_IPv)
 	AC_CHECK_DECL(AU_IPv4, [], 
 	    AC_DEFINE(AU_IPv4, 0, [System only supports IPv4 audit records])
@@ -1080,6 +1205,19 @@
 	[Define if your libraries define login()])])
 AC_CHECK_FUNCS(fmt_scaled logout updwtmp logwtmp)
 
+dnl
+dnl Check for globus_usage_stats_send
+dnl
+AC_SEARCH_LIBS(globus_usage_stats_send,
+               globus_usage globus_usage_${globus_flavor_type},
+               AC_DEFINE([HAVE_GLOBUS_USAGE], 1, [Have Globus Usage]))
+dnl
+dnl Check for globus_usage_stats_send_array
+dnl
+AC_SEARCH_LIBS(globus_usage_stats_send_array,
+               globus_usage globus_usage_${globus_flavor_type},
+               AC_DEFINE([HAVE_GLOBUS_USAGE_SEND_ARRAY], 1, [Have Globus Usage send_array]))
+
 AC_FUNC_STRFTIME
 
 # Check for ALTDIRFUNC glob() extension
@@ -1921,7 +2059,9 @@
 		fi
 	]
 )
+if test -z "$GLOBUS_LDFLAGS" ; then
 LIBS="-lcrypto $LIBS"
+fi
 AC_TRY_LINK_FUNC(RAND_add, AC_DEFINE(HAVE_OPENSSL, 1,
 	[Define if your ssl headers are included
 	with #include <openssl/header.h>]),
@@ -3386,6 +3526,55 @@
 	fi ]
 )
 
+# Finish configuring Globus GSSAPI
+if test "x$gsi_path" != "xno" ; then
+	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
+	# test that we got the libraries OK
+	AC_TRY_LINK(
+		[],
+		[],
+		[],
+		[
+			AC_MSG_ERROR(link with Globus libraries failed)
+		]
+	)
+    AC_CHECK_FUNCS(globus_gss_assist_map_and_authorize)
+fi
+AC_SUBST(INSTALL_GSISSH)
+
+# Check whether the user wants GSSAPI mechglue support
+AC_ARG_WITH(mechglue,
+	[  --with-mechglue=PATH    Build with GSSAPI mechglue library],
+	[
+		AC_MSG_CHECKING(for mechglue library)
+
+		if test -e ${withval}/libgssapi.a ; then
+		    mechglue_lib=${withval}/libgssapi.a
+		elif test -e ${withval}/lib/libgssapi.a ; then
+		    mechglue_lib=${withval}/lib/libgssapi.a
+		else
+		    AC_MSG_ERROR("Can't find libgssapi in ${withval}");
+		fi
+		LIBS="${mechglue_lib} $LIBS"
+		AC_MSG_RESULT(${mechglue_lib})
+
+		AC_CHECK_LIB(dl, dlopen, , )
+		if test $ac_cv_lib_dl_dlopen = yes; then
+		   LDFLAGS="$LDFLAGS -ldl -Wl,-Bsymbolic"
+		fi
+
+		AC_DEFINE(GSSAPI)
+		AC_DEFINE(MECHGLUE, 1, [Define this if you're building with GSSAPI MechGlue.])
+		GSSAPI="mechglue"
+	]
+)
+
+
 # Check whether user wants Kerberos 5 support
 KRB5_MSG="no"
 AC_ARG_WITH(kerberos5,
@@ -3472,7 +3661,21 @@
 			AC_CHECK_HEADER(gssapi_krb5.h, ,
 					[ CPPFLAGS="$oldCPP" ])
 
-		fi
+			# If we're using some other GSSAPI
+			if test "$GSSAPI" -a "$GSSAPI" != "mechglue"; then
+				AC_MSG_ERROR([$GSSAPI GSSAPI library conflicts with Kerberos support.  Use mechglue instead.])
+			fi
+
+			if test -z "$GSSAPI"; then
+				GSSAPI="KRB5";
+			fi
+
+			oldCPP="$CPPFLAGS"
+			CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
+			AC_CHECK_HEADER(gssapi_krb5.h, ,
+					[ CPPFLAGS="$oldCPP" ])
+
+                fi
 		if test ! -z "$need_dash_r" ; then
 			LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib"
 		fi
@@ -3491,6 +3694,42 @@
 	]
 )
 
+# Check whether user wants AFS_KRB5 support
+AFS_KRB5_MSG="no"
+AC_ARG_WITH(afs-krb5,
+	[  --with-afs-krb5[[=AKLOG_PATH]]  Enable aklog to get token (default=/usr/bin/aklog).],
+	[
+		if test "x$withval" != "xno" ; then
+
+			if test "x$withval" != "xyes" ; then
+				AC_DEFINE_UNQUOTED(AKLOG_PATH, "$withval",
+					[Define this if you want to use AFS/Kerberos 5 option, which runs aklog.])
+			else
+				AC_DEFINE_UNQUOTED(AKLOG_PATH,
+					"/usr/bin/aklog",
+					[Define this if you want to use AFS/Kerberos 5 option, which runs aklog.])
+			fi
+
+			if test -z "$KRB5ROOT" ; then
+				AC_MSG_WARN([AFS_KRB5 requires Kerberos 5 support, build may fail])
+			fi
+
+			LIBS="-lkrbafs -lkrb4 $LIBS"
+			if test ! -z "$AFS_LIBS" ; then
+				LIBS="$LIBS $AFS_LIBS"
+			fi
+			AC_DEFINE(AFS_KRB5, 1,
+				[Define this if you want to use AFS/Kerberos 5 option, which runs aklog.])
+			AFS_KRB5_MSG="yes"
+		fi
+	]
+)
+
+AC_ARG_WITH(session-hooks,
+        [  --with-session-hooks    Enable hooks for executing external commands                                       before/after a session],
+        [ AC_DEFINE(SESSION_HOOKS, 1, [Define this if you want support for startup/shutdown hooks]) ]
+)
+
 # Looking for programs, paths and files
 
 PRIVSEP_PATH=/var/empty
@@ -3526,7 +3765,10 @@
 	]
 )
 
+# strip causes problems with GSI libraries...
+if test -z "$GLOBUS_LDFLAGS" ; then
 STRIP_OPT=-s
+fi
 AC_ARG_ENABLE(strip,
 	[  --disable-strip         Disable calling strip(1) on install],
 	[
diff -Naur --exclude=autom4te.cache openssh-5.5p1/defines.h openssh-5.5p1-gssapi/defines.h
--- openssh-5.5p1/defines.h	2010-04-09 03:13:27.000000000 -0500
+++ openssh-5.5p1-gssapi/defines.h	2010-04-20 10:49:30.000000000 -0500
@@ -344,6 +344,8 @@
 # define _PATH_DEVNULL "/dev/null"
 #endif
 
+#ifndef PATH_MAILDIR_IN_PATHS_H
+
 #ifndef MAIL_DIRECTORY
 # define MAIL_DIRECTORY "/var/spool/mail"
 #endif
@@ -356,6 +358,8 @@
 # define _PATH_MAILDIR MAILDIR
 #endif /* !defined(_PATH_MAILDIR) && defined(MAILDIR) */
 
+#endif /* PATH_MAILDIR_IN_PATHS_H */
+
 #ifndef _PATH_NOLOGIN
 # define _PATH_NOLOGIN "/etc/nologin"
 #endif
diff -Naur --exclude=autom4te.cache openssh-5.5p1/gss-genr.c openssh-5.5p1-gssapi/gss-genr.c
--- openssh-5.5p1/gss-genr.c	2009-06-22 01:11:07.000000000 -0500
+++ openssh-5.5p1-gssapi/gss-genr.c	2010-04-20 10:49:30.000000000 -0500
@@ -1,7 +1,7 @@
 /* $OpenBSD: gss-genr.c,v 1.20 2009/06/22 05:39:28 dtucker Exp $ */
 
 /*
- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -38,13 +38,169 @@
 #include "xmalloc.h"
 #include "buffer.h"
 #include "log.h"
+#include "canohost.h"
 #include "ssh2.h"
+#include "cipher.h"
+#include "key.h"
+#include "kex.h"
+#include <openssl/evp.h>
 
 #include "ssh-gss.h"
 
 extern u_char *session_id2;
 extern u_int session_id2_len;
 
+typedef struct {
+	char *encoded;
+	gss_OID oid;
+} ssh_gss_kex_mapping;
+
+/*
+ * XXX - It would be nice to find a more elegant way of handling the
+ * XXX   passing of the key exchange context to the userauth routines
+ */
+
+Gssctxt *gss_kex_context = NULL;
+
+static ssh_gss_kex_mapping *gss_enc2oid = NULL;
+
+int 
+ssh_gssapi_oid_table_ok() {
+	return (gss_enc2oid != NULL);
+}
+
+/*
+ * Return a list of the gss-group1-sha1 mechanisms supported by this program
+ *
+ * We test mechanisms to ensure that we can use them, to avoid starting
+ * a key exchange with a bad mechanism
+ */
+
+char *
+ssh_gssapi_client_mechanisms(const char *host, const char *client) {
+	gss_OID_set gss_supported;
+	OM_uint32 min_status;
+
+	if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported)))
+		return NULL;
+
+	return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
+	    host, client));
+}
+
+char *
+ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
+    const char *host, const char *client) {
+	Buffer buf;
+	size_t i;
+	int oidpos, enclen;
+	char *mechs, *encoded;
+	u_char digest[EVP_MAX_MD_SIZE];
+	char deroid[2];
+	const EVP_MD *evp_md = EVP_md5();
+	EVP_MD_CTX md;
+
+	if (gss_enc2oid != NULL) {
+		for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
+			xfree(gss_enc2oid[i].encoded);
+		xfree(gss_enc2oid);
+	}
+
+	gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) *
+	    (gss_supported->count + 1));
+
+	buffer_init(&buf);
+
+	oidpos = 0;
+	for (i = 0; i < gss_supported->count; i++) {
+		if (gss_supported->elements[i].length < 128 &&
+		    (*check)(NULL, &(gss_supported->elements[i]), host, client)) {
+
+			deroid[0] = SSH_GSS_OIDTYPE;
+			deroid[1] = gss_supported->elements[i].length;
+
+			EVP_DigestInit(&md, evp_md);
+			EVP_DigestUpdate(&md, deroid, 2);
+			EVP_DigestUpdate(&md,
+			    gss_supported->elements[i].elements,
+			    gss_supported->elements[i].length);
+			EVP_DigestFinal(&md, digest, NULL);
+
+			encoded = xmalloc(EVP_MD_size(evp_md) * 2);
+			enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
+			    encoded, EVP_MD_size(evp_md) * 2);
+
+			if (oidpos != 0)
+				buffer_put_char(&buf, ',');
+
+			buffer_append(&buf, KEX_GSS_GEX_SHA1_ID,
+			    sizeof(KEX_GSS_GEX_SHA1_ID) - 1);
+			buffer_append(&buf, encoded, enclen);
+			buffer_put_char(&buf, ',');
+			buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, 
+			    sizeof(KEX_GSS_GRP1_SHA1_ID) - 1);
+			buffer_append(&buf, encoded, enclen);
+			buffer_put_char(&buf, ',');
+			buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID,
+			    sizeof(KEX_GSS_GRP14_SHA1_ID) - 1);
+			buffer_append(&buf, encoded, enclen);
+
+			gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
+			gss_enc2oid[oidpos].encoded = encoded;
+			oidpos++;
+		}
+	}
+	gss_enc2oid[oidpos].oid = NULL;
+	gss_enc2oid[oidpos].encoded = NULL;
+
+	buffer_put_char(&buf, '\0');
+
+	mechs = xmalloc(buffer_len(&buf));
+	buffer_get(&buf, mechs, buffer_len(&buf));
+	buffer_free(&buf);
+
+	if (strlen(mechs) == 0) {
+		xfree(mechs);
+		mechs = NULL;
+	}
+	
+	return (mechs);
+}
+
+gss_OID
+ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {
+	int i = 0;
+	
+	switch (kex_type) {
+	case KEX_GSS_GRP1_SHA1:
+		if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID))
+			return GSS_C_NO_OID;
+		name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1;
+		break;
+	case KEX_GSS_GRP14_SHA1:
+		if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID))
+			return GSS_C_NO_OID;
+		name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;
+		break;
+	case KEX_GSS_GEX_SHA1:
+		if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))
+			return GSS_C_NO_OID;
+		name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;
+		break;
+	default:
+		return GSS_C_NO_OID;
+	}
+
+	while (gss_enc2oid[i].encoded != NULL &&
+	    strcmp(name, gss_enc2oid[i].encoded) != 0)
+		i++;
+
+	if (gss_enc2oid[i].oid != NULL && ctx != NULL)
+		ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid);
+
+	return gss_enc2oid[i].oid;
+}
+
 /* Check that the OID in a data stream matches that in the context */
 int
 ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
@@ -155,10 +311,13 @@
 void
 ssh_gssapi_delete_ctx(Gssctxt **ctx)
 {
+#if !defined(MECHGLUE)
 	OM_uint32 ms;
+#endif
 
 	if ((*ctx) == NULL)
 		return;
+#if !defined(MECHGLUE) /* mechglue has some memory management issues */
 	if ((*ctx)->context != GSS_C_NO_CONTEXT)
 		gss_delete_sec_context(&ms, &(*ctx)->context, GSS_C_NO_BUFFER);
 	if ((*ctx)->name != GSS_C_NO_NAME)
@@ -174,6 +333,7 @@
 		gss_release_name(&ms, &(*ctx)->client);
 	if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL)
 		gss_release_cred(&ms, &(*ctx)->client_creds);
+#endif
 
 	xfree(*ctx);
 	*ctx = NULL;
@@ -197,7 +357,7 @@
 	}
 
 	ctx->major = gss_init_sec_context(&ctx->minor,
-	    GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid,
+	    ctx->client_creds, &ctx->context, ctx->name, ctx->oid,
 	    GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
 	    0, NULL, recv_tok, NULL, send_tok, flags, NULL);
 
@@ -212,9 +372,18 @@
 ssh_gssapi_import_name(Gssctxt *ctx, const char *host)
 {
 	gss_buffer_desc gssbuf;
+	char *xhost;
 	char *val;
 
-	xasprintf(&val, "host@%s", host);
+	/* Make a copy of the host name, in case it was returned by a
+	 * previous call to gethostbyname(). */	
+	xhost = xstrdup(host);
+
+	/* Make sure we have the FQDN. Some GSSAPI implementations don't do
+	 * this for us themselves */
+	resolve_localhost(&xhost);
+	
+	xasprintf(&val, "host@%s", xhost);
 	gssbuf.value = val;
 	gssbuf.length = strlen(gssbuf.value);
 
@@ -222,13 +391,48 @@
 	    &gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name)))
 		ssh_gssapi_error(ctx);
 
+	xfree(xhost);
 	xfree(gssbuf.value);
 	return (ctx->major);
 }
 
 OM_uint32
+ssh_gssapi_client_identity(Gssctxt *ctx, const char *name)
+{
+	gss_buffer_desc gssbuf;
+	gss_name_t gssname;
+	OM_uint32 status;
+	gss_OID_set oidset;
+
+	gssbuf.value = (void *) name;
+	gssbuf.length = strlen(gssbuf.value);
+
+	gss_create_empty_oid_set(&status, &oidset);
+	gss_add_oid_set_member(&status, ctx->oid, &oidset);
+
+	ctx->major = gss_import_name(&ctx->minor, &gssbuf,
+	    GSS_C_NT_USER_NAME, &gssname);
+
+	if (!ctx->major)
+		ctx->major = gss_acquire_cred(&ctx->minor, 
+		    gssname, 0, oidset, GSS_C_INITIATE, 
+		    &ctx->client_creds, NULL, NULL);
+
+	gss_release_name(&status, &gssname);
+	gss_release_oid_set(&status, &oidset);
+
+	if (ctx->major)
+		ssh_gssapi_error(ctx);
+
+	return(ctx->major);
+}
+
+OM_uint32
 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
 {
+	if (ctx == NULL) 
+		return -1;
+
 	if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
 	    GSS_C_QOP_DEFAULT, buffer, hash)))
 		ssh_gssapi_error(ctx);
@@ -236,6 +440,19 @@
 	return (ctx->major);
 }
 
+/* Priviledged when used by server */
+OM_uint32
+ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
+{
+	if (ctx == NULL)
+		return -1;
+
+	ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
+	    gssbuf, gssmic, NULL);
+
+	return (ctx->major);
+}
+
 void
 ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service,
     const char *context)
@@ -249,11 +466,16 @@
 }
 
 int
-ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
+ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, 
+    const char *client)
 {
 	gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
 	OM_uint32 major, minor;
 	gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"};
+	Gssctxt *intctx = NULL;
+
+	if (ctx == NULL)
+		ctx = &intctx;
 
 	/* RFC 4462 says we MUST NOT do SPNEGO */
 	if (oid->length == spnego_oid.length && 
@@ -263,6 +485,10 @@
 	ssh_gssapi_build_ctx(ctx);
 	ssh_gssapi_set_oid(*ctx, oid);
 	major = ssh_gssapi_import_name(*ctx, host);
+
+	if (!GSS_ERROR(major) && client)
+		major = ssh_gssapi_client_identity(*ctx, client);
+
 	if (!GSS_ERROR(major)) {
 		major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, 
 		    NULL);
@@ -272,10 +498,66 @@
 			    GSS_C_NO_BUFFER);
 	}
 
-	if (GSS_ERROR(major)) 
+	if (GSS_ERROR(major) || intctx != NULL) 
 		ssh_gssapi_delete_ctx(ctx);
 
 	return (!GSS_ERROR(major));
 }
 
+int
+ssh_gssapi_credentials_updated(Gssctxt *ctxt) {
+	static gss_name_t saved_name = GSS_C_NO_NAME;
+	static OM_uint32 saved_lifetime = 0;
+	static gss_OID saved_mech = GSS_C_NO_OID;
+	static gss_name_t name;
+	static OM_uint32 last_call = 0;
+	OM_uint32 lifetime, now, major, minor;
+	int equal;
+	
+	now = time(NULL);
+
+	if (ctxt) {
+		debug("Rekey has happened - updating saved versions");
+
+		if (saved_name != GSS_C_NO_NAME)
+			gss_release_name(&minor, &saved_name);
+
+		major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
+		    &saved_name, &saved_lifetime, NULL, NULL);
+
+		if (!GSS_ERROR(major)) {
+			saved_mech = ctxt->oid;
+		        saved_lifetime+= now;
+		} else {
+			/* Handle the error */
+		}
+		return 0;
+	}
+
+	if (now - last_call < 10)
+		return 0;
+
+	last_call = now;
+
+	if (saved_mech == GSS_C_NO_OID)
+		return 0;
+	
+	major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, 
+	    &name, &lifetime, NULL, NULL);
+	if (major == GSS_S_CREDENTIALS_EXPIRED)
+		return 0;
+	else if (GSS_ERROR(major))
+		return 0;
+
+	major = gss_compare_name(&minor, saved_name, name, &equal);
+	gss_release_name(&minor, &name);
+	if (GSS_ERROR(major))
+		return 0;
+
+	if (equal && (saved_lifetime < lifetime + now - 10))
+		return 1;
+
+	return 0;
+}
+
 #endif /* GSSAPI */
diff -Naur --exclude=autom4te.cache openssh-5.5p1/gss-serv-gsi.c openssh-5.5p1-gssapi/gss-serv-gsi.c
--- openssh-5.5p1/gss-serv-gsi.c	1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.5p1-gssapi/gss-serv-gsi.c	2010-04-20 10:49:30.000000000 -0500
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#ifdef GSSAPI
+#ifdef GSI
+
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <string.h>
+
+#include "xmalloc.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "log.h"
+#include "servconf.h"
+
+#include "buffer.h"
+#include "ssh-gss.h"
+
+extern ServerOptions options;
+
+#include <globus_gss_assist.h>
+
+static int ssh_gssapi_gsi_userok(ssh_gssapi_client *client, char *name);
+static int ssh_gssapi_gsi_localname(ssh_gssapi_client *client, char **user);
+static void ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client);
+static int ssh_gssapi_gsi_updatecreds(ssh_gssapi_ccache *store,
+				       ssh_gssapi_client *client);
+
+ssh_gssapi_mech gssapi_gsi_mech = {
+	"dZuIebMjgUqaxvbF7hDbAw==",
+	"GSI",
+	{9, "\x2B\x06\x01\x04\x01\x9B\x50\x01\x01"},
+	NULL,
+	&ssh_gssapi_gsi_userok,
+	&ssh_gssapi_gsi_localname,
+	&ssh_gssapi_gsi_storecreds,
+	&ssh_gssapi_gsi_updatecreds
+};
+
+/*
+ * Check if this user is OK to login under GSI. User has been authenticated
+ * as identity in global 'client_name.value' and is trying to log in as passed
+ * username in 'name'.
+ *
+ * Returns non-zero if user is authorized, 0 otherwise.
+ */
+static int
+ssh_gssapi_gsi_userok(ssh_gssapi_client *client, char *name)
+{
+    int authorized = 0;
+    globus_result_t res;
+#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE
+    char lname[256] = "";
+#endif
+    
+#ifdef GLOBUS_GSI_GSS_ASSIST_MODULE
+    if (globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE) != 0) {
+	return 0;
+    }
+#endif
+
+/* use new globus_gss_assist_map_and_authorize() interface if available */
+#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE
+    debug("calling globus_gss_assist_map_and_authorize()");
+    if (GLOBUS_SUCCESS !=
+        (res = globus_gss_assist_map_and_authorize(client->context, "ssh",
+                                                   name, lname, 256))) {
+        debug("%s", globus_error_print_chain(globus_error_get(res)));
+    } else if (lname && lname[0] && strcmp(name, lname) != 0) {
+        debug("GSI user maps to %s, not %s", lname, name);
+    } else {
+        authorized = 1;
+    }
+#else
+    debug("calling globus_gss_assist_userok()");
+    if (GLOBUS_SUCCESS !=
+        (res = (globus_gss_assist_userok(client->displayname.value,
+                                         name)))) {
+        debug("%s", globus_error_print_chain(globus_error_get(res)));
+    } else {
+        authorized = 1;
+    }
+#endif
+    
+    logit("GSI user %s is%s authorized as target user %s",
+	(char *) client->displayname.value, (authorized ? "" : " not"), name);
+    
+    return authorized;
+}
+
+/*
+ * Return the local username associated with the GSI credentials.
+ */
+int
+ssh_gssapi_gsi_localname(ssh_gssapi_client *client, char **user)
+{
+    globus_result_t res;
+#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE
+    char lname[256] = "";
+#endif
+
+#ifdef GLOBUS_GSI_GSS_ASSIST_MODULE
+    if (globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE) != 0) {
+	return 0;
+    }
+#endif
+
+/* use new globus_gss_assist_map_and_authorize() interface if available */
+#ifdef HAVE_GLOBUS_GSS_ASSIST_MAP_AND_AUTHORIZE
+    debug("calling globus_gss_assist_map_and_authorize()");
+    if (GLOBUS_SUCCESS !=
+        (res = globus_gss_assist_map_and_authorize(client->context, "ssh",
+                                                   NULL, lname, 256))) {
+        debug("%s", globus_error_print_chain(globus_error_get(res)));
+        logit("failed to map GSI user %s", (char *)client->displayname.value);
+        return 0;
+    }
+    *user = strdup(lname);
+#else
+    debug("calling globus_gss_assist_gridmap()");
+    if (GLOBUS_SUCCESS !=
+        (res = globus_gss_assist_gridmap(client->displayname.value, user))) {
+        debug("%s", globus_error_print_chain(globus_error_get(res)));
+        logit("failed to map GSI user %s", (char *)client->displayname.value);
+        return 0;
+    }
+#endif
+
+    logit("GSI user %s mapped to target user %s",
+          (char *) client->displayname.value, *user);
+
+    return 1;
+}
+
+/*
+ * Export GSI credentials to disk.
+ */
+static void
+ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client)
+{
+	OM_uint32	major_status;
+	OM_uint32	minor_status;
+	gss_buffer_desc	export_cred = GSS_C_EMPTY_BUFFER;
+	char *		p;
+	
+	if (!client || !client->creds) {
+	    return;
+	}
+
+	major_status = gss_export_cred(&minor_status,
+				       client->creds,
+				       GSS_C_NO_OID,
+				       1,
+				       &export_cred);
+	if (GSS_ERROR(major_status) && major_status != GSS_S_UNAVAILABLE) {
+	    Gssctxt *ctx;
+	    ssh_gssapi_build_ctx(&ctx);
+	    ctx->major = major_status;
+	    ctx->minor = minor_status;
+	    ssh_gssapi_set_oid(ctx, &gssapi_gsi_mech.oid);
+	    ssh_gssapi_error(ctx);
+	    ssh_gssapi_delete_ctx(&ctx);
+	    return;
+	}
+	
+	p = strchr((char *) export_cred.value, '=');
+	if (p == NULL) {
+	    logit("Failed to parse exported credentials string '%.100s'",
+		(char *)export_cred.value);
+	    gss_release_buffer(&minor_status, &export_cred);
+	    return;
+	}
+	*p++ = '\0';
+	if (strcmp((char *)export_cred.value,"X509_USER_DELEG_PROXY") == 0) {
+	    client->store.envvar = strdup("X509_USER_PROXY");
+	} else {
+	    client->store.envvar = strdup((char *)export_cred.value);
+	}
+	if (access(p, R_OK) == 0) {
+        if (client->store.filename) {
+            if (rename(p, client->store.filename) < 0) {
+                logit("Failed to rename %s to %s: %s", p,
+                      client->store.filename, strerror(errno));
+                xfree(client->store.filename);
+                client->store.filename = strdup(p);
+            } else {
+                p = client->store.filename;
+            }
+        } else {
+            client->store.filename = strdup(p);
+        }
+	}
+	client->store.envval = strdup(p);
+#ifdef USE_PAM
+	if (options.use_pam)
+	    do_pam_putenv(client->store.envvar, client->store.envval);
+#endif
+	gss_release_buffer(&minor_status, &export_cred);
+}
+
+/*
+ * Export updated GSI credentials to disk.
+ */
+static int
+ssh_gssapi_gsi_updatecreds(ssh_gssapi_ccache *store,ssh_gssapi_client *client)
+{
+	ssh_gssapi_gsi_storecreds(client);
+	return 1;
+}
+
+#endif /* GSI */
+#endif /* GSSAPI */
diff -Naur --exclude=autom4te.cache openssh-5.5p1/gss-serv-krb5.c openssh-5.5p1-gssapi/gss-serv-krb5.c
--- openssh-5.5p1/gss-serv-krb5.c	2006-09-01 00:38:36.000000000 -0500
+++ openssh-5.5p1-gssapi/gss-serv-krb5.c	2010-04-20 10:49:30.000000000 -0500
@@ -1,7 +1,7 @@
 /* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */
 
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -48,7 +48,7 @@
 
 #ifdef HEIMDAL
 # include <krb5.h>
-#else
+#elif !defined(MECHGLUE)
 # ifdef HAVE_GSSAPI_KRB5_H
 #  include <gssapi_krb5.h>
 # elif HAVE_GSSAPI_GSSAPI_KRB5_H
@@ -57,6 +57,23 @@
 #endif
 
 static krb5_context krb_context = NULL;
+static int ssh_gssapi_krb5_init();
+static int ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name);
+static int ssh_gssapi_krb5_localname(ssh_gssapi_client *client, char **user);
+static void ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client);
+static int ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store,
+                                       ssh_gssapi_client *client);
+
+ssh_gssapi_mech gssapi_kerberos_mech = {
+	"toWM5Slw5Ew8Mqkay+al2g==",
+	"Kerberos",
+	{9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"},
+	NULL,
+	&ssh_gssapi_krb5_userok,
+	&ssh_gssapi_krb5_localname,
+	&ssh_gssapi_krb5_storecreds,
+	&ssh_gssapi_krb5_updatecreds
+};
 
 /* Initialise the krb5 library, for the stuff that GSSAPI won't do */
 
@@ -109,6 +126,35 @@
 }
 
 
+/* Retrieve the local username associated with a set of Kerberos 
+ * credentials. Hopefully we can use this for the 'empty' username
+ * logins discussed in the draft  */
+static int
+ssh_gssapi_krb5_localname(ssh_gssapi_client *client, char **user) {
+	krb5_principal princ;
+	int retval;
+	
+	if (ssh_gssapi_krb5_init() == 0)
+		return 0;
+
+	if ((retval=krb5_parse_name(krb_context, client->displayname.value, 
+				    &princ))) {
+		logit("krb5_parse_name(): %.100s", 
+			krb5_get_err_text(krb_context,retval));
+		return 0;
+	}
+	
+	/* We've got to return a malloc'd string */
+	*user = (char *)xmalloc(256);
+	if (krb5_aname_to_localname(krb_context, princ, 256, *user)) {
+		xfree(*user);
+		*user = NULL;
+		return(0);
+	}
+	
+	return(1);
+}
+	
 /* This writes out any forwarded credentials from the structure populated
  * during userauth. Called after we have setuid to the user */
 
@@ -119,7 +165,9 @@
 	krb5_error_code problem;
 	krb5_principal princ;
 	OM_uint32 maj_status, min_status;
+	gss_cred_id_t krb5_cred_handle;
 	int len;
+	const char *new_ccname;
 
 	if (client->creds == NULL) {
 		debug("No credentials stored");
@@ -161,18 +209,31 @@
 
 	krb5_free_principal(krb_context, princ);
 
-	if ((maj_status = gss_krb5_copy_ccache(&min_status,
-	    client->creds, ccache))) {
+#ifdef MECHGLUE
+	krb5_cred_handle =
+	    __gss_get_mechanism_cred(client->creds,
+				     &(gssapi_kerberos_mech.oid));
+#else
+	krb5_cred_handle = client->creds;
+#endif
+
+	if ((maj_status = gss_krb5_copy_ccache(&min_status, 
+	    krb5_cred_handle, ccache))) {
 		logit("gss_krb5_copy_ccache() failed");
 		krb5_cc_destroy(krb_context, ccache);
 		return;
 	}
 
-	client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache));
+	new_ccname = krb5_cc_get_name(krb_context, ccache);
+
 	client->store.envvar = "KRB5CCNAME";
-	len = strlen(client->store.filename) + 6;
-	client->store.envval = xmalloc(len);
-	snprintf(client->store.envval, len, "FILE:%s", client->store.filename);
+#ifdef USE_CCAPI
+	xasprintf(&client->store.envval, "API:%s", new_ccname);
+	client->store.filename = NULL;
+#else
+	xasprintf(&client->store.envval, "FILE:%s", new_ccname);
+	client->store.filename = xstrdup(new_ccname);
+#endif
 
 #ifdef USE_PAM
 	if (options.use_pam)
@@ -184,15 +245,70 @@
 	return;
 }
 
-ssh_gssapi_mech gssapi_kerberos_mech = {
-	"toWM5Slw5Ew8Mqkay+al2g==",
-	"Kerberos",
-	{9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"},
-	NULL,
-	&ssh_gssapi_krb5_userok,
-	NULL,
-	&ssh_gssapi_krb5_storecreds
-};
+static int
+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, 
+    ssh_gssapi_client *client)
+{
+	krb5_ccache ccache = NULL;
+	krb5_principal principal = NULL;
+	char *name = NULL;
+	krb5_error_code problem;
+	OM_uint32 maj_status, min_status;
+
+   	if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) {
+                logit("krb5_cc_resolve(): %.100s",
+                    krb5_get_err_text(krb_context, problem));
+                return 0;
+       	}
+	
+	/* Find out who the principal in this cache is */
+	if ((problem = krb5_cc_get_principal(krb_context, ccache, 
+	    &principal))) {
+		logit("krb5_cc_get_principal(): %.100s",
+		    krb5_get_err_text(krb_context, problem));
+		krb5_cc_close(krb_context, ccache);
+		return 0;
+	}
+
+	if ((problem = krb5_unparse_name(krb_context, principal, &name))) {
+		logit("krb5_unparse_name(): %.100s",
+		    krb5_get_err_text(krb_context, problem));
+		krb5_free_principal(krb_context, principal);
+		krb5_cc_close(krb_context, ccache);
+		return 0;
+	}
+
+
+	if (strcmp(name,client->exportedname.value)!=0) {
+		debug("Name in local credentials cache differs. Not storing");
+		krb5_free_principal(krb_context, principal);
+		krb5_cc_close(krb_context, ccache);
+		krb5_free_unparsed_name(krb_context, name);
+		return 0;
+	}
+	krb5_free_unparsed_name(krb_context, name);
+
+	/* Name matches, so lets get on with it! */
+
+	if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) {
+		logit("krb5_cc_initialize(): %.100s",
+		    krb5_get_err_text(krb_context, problem));
+		krb5_free_principal(krb_context, principal);
+		krb5_cc_close(krb_context, ccache);
+		return 0;
+	}
+
+	krb5_free_principal(krb_context, principal);
+
+	if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds,
+	    ccache))) {
+		logit("gss_krb5_copy_ccache() failed. Sorry!");
+		krb5_cc_close(krb_context, ccache);
+		return 0;
+	}
+
+	return 1;
+}
 
 #endif /* KRB5 */
 
diff -Naur --exclude=autom4te.cache openssh-5.5p1/gss-serv.c openssh-5.5p1-gssapi/gss-serv.c
--- openssh-5.5p1/gss-serv.c	2008-05-19 00:05:07.000000000 -0500
+++ openssh-5.5p1-gssapi/gss-serv.c	2010-04-20 10:49:30.000000000 -0500
@@ -1,7 +1,7 @@
 /* $OpenBSD: gss-serv.c,v 1.22 2008/05/08 12:02:23 djm Exp $ */
 
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -45,27 +45,43 @@
 #include "channels.h"
 #include "session.h"
 #include "misc.h"
+#include "servconf.h"
+#include "uidswap.h"
 
+#include "xmalloc.h"
 #include "ssh-gss.h"
+#include "monitor_wrap.h"
+
+extern ServerOptions options;
+extern Authctxt *the_authctxt;
 
 static ssh_gssapi_client gssapi_client =
     { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
-    GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}};
+    GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,  NULL, {NULL, NULL, NULL}, 0, 0};
 
 ssh_gssapi_mech gssapi_null_mech =
-    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
+    { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};
 
 #ifdef KRB5
 extern ssh_gssapi_mech gssapi_kerberos_mech;
 #endif
+#ifdef GSI
+extern ssh_gssapi_mech gssapi_gsi_mech;
+#endif
 
 ssh_gssapi_mech* supported_mechs[]= {
 #ifdef KRB5
 	&gssapi_kerberos_mech,
 #endif
+#ifdef GSI
+	&gssapi_gsi_mech,
+#endif
 	&gssapi_null_mech,
 };
 
+#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG
+static int limited = 0;
+#endif
 
 /*
  * Acquire credentials for a server running on the current host.
@@ -81,25 +97,32 @@
 	char lname[MAXHOSTNAMELEN];
 	gss_OID_set oidset;
 
-	gss_create_empty_oid_set(&status, &oidset);
-	gss_add_oid_set_member(&status, ctx->oid, &oidset);
+	if (options.gss_strict_acceptor) {
+		gss_create_empty_oid_set(&status, &oidset);
+		gss_add_oid_set_member(&status, ctx->oid, &oidset);
+
+		if (gethostname(lname, MAXHOSTNAMELEN)) {
+			gss_release_oid_set(&status, &oidset);
+			return (-1);
+		}
 
-	if (gethostname(lname, MAXHOSTNAMELEN)) {
-		gss_release_oid_set(&status, &oidset);
-		return (-1);
-	}
+		if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
+			gss_release_oid_set(&status, &oidset);
+			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);
 
-	if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) {
 		gss_release_oid_set(&status, &oidset);
 		return (ctx->major);
+	} else {
+		ctx->name = GSS_C_NO_NAME;
+		ctx->creds = GSS_C_NO_CREDENTIAL;
 	}
-
-	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);
+	return GSS_S_COMPLETE;
 }
 
 /* Privileged */
@@ -114,6 +137,29 @@
 }
 
 /* Unprivileged */
+char *
+ssh_gssapi_server_mechanisms() {
+	gss_OID_set	supported;
+
+	ssh_gssapi_supported_oids(&supported);
+	return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech,
+	    NULL, NULL));
+}
+
+/* Unprivileged */
+int
+ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data,
+    const char *dummy) {
+	Gssctxt *ctx = NULL;
+	int res;
+ 
+	res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
+	ssh_gssapi_delete_ctx(&ctx);
+
+	return (res);
+}
+
+/* Unprivileged */
 void
 ssh_gssapi_supported_oids(gss_OID_set *oidset)
 {
@@ -123,7 +169,10 @@
 	gss_OID_set supported;
 
 	gss_create_empty_oid_set(&min_status, oidset);
-	gss_indicate_mechs(&min_status, &supported);
+
+	/* Ask privileged process what mechanisms it supports. */
+	if (GSS_ERROR(PRIVSEP(gss_indicate_mechs(&min_status, &supported))))
+		return;
 
 	while (supported_mechs[i]->name != NULL) {
 		if (GSS_ERROR(gss_test_oid_set_member(&min_status,
@@ -175,6 +224,10 @@
 	    (*flags & GSS_C_INTEG_FLAG))) && (ctx->major == GSS_S_COMPLETE)) {
 		if (ssh_gssapi_getclient(ctx, &gssapi_client))
 			fatal("Couldn't convert client name");
+#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG
+		if (flags && (*flags & GSS_C_GLOBUS_LIMITED_PROXY_FLAG))
+			limited=1;
+#endif
 	}
 
 	return (status);
@@ -194,6 +247,17 @@
 
 	tok = ename->value;
 
+#ifdef GSI /* GSI gss_export_name() is broken. */
+	if ((ctx->oid->length == gssapi_gsi_mech.oid.length) &&
+	    (memcmp(ctx->oid->elements, gssapi_gsi_mech.oid.elements,
+		    gssapi_gsi_mech.oid.length) == 0)) {
+	    name->length = ename->length;
+	    name->value = xmalloc(ename->length+1);
+	    memcpy(name->value, ename->value, ename->length);
+	    return GSS_S_COMPLETE;
+	}
+#endif
+
 	/*
 	 * Check that ename is long enough for all of the fixed length
 	 * header, and that the initial ID bytes are correct
@@ -247,8 +311,51 @@
 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
 {
 	int i = 0;
+	int equal = 0;
+	gss_name_t new_name = GSS_C_NO_NAME;
+	gss_buffer_desc ename = GSS_C_EMPTY_BUFFER;
+
+	if (options.gss_store_rekey && client->used && ctx->client_creds) {
+		if (client->mech->oid.length != ctx->oid->length ||
+		    (memcmp(client->mech->oid.elements,
+		     ctx->oid->elements, ctx->oid->length) !=0)) {
+			debug("Rekeyed credentials have different mechanism");
+			return GSS_S_COMPLETE;
+		}
+
+        /* Call gss_inquire_cred rather than gss_inquire_cred_by_mech
+           because GSI doesn't support the latter. -jbasney */
+
+		if ((ctx->major = gss_inquire_cred(&ctx->minor, 
+		    ctx->client_creds, &new_name, 
+		    NULL, NULL, NULL))) {
+			ssh_gssapi_error(ctx);
+			return (ctx->major);
+		}
+
+		ctx->major = gss_compare_name(&ctx->minor, client->name, 
+		    new_name, &equal);
 
-	gss_buffer_desc ename;
+		if (GSS_ERROR(ctx->major)) {
+			ssh_gssapi_error(ctx);
+			return (ctx->major);
+		}
+ 
+		if (!equal) {
+			debug("Rekeyed credentials have different name");
+			return GSS_S_COMPLETE;
+		}
+
+		debug("Marking rekeyed credentials for export");
+
+		gss_release_name(&ctx->minor, &client->name);
+		gss_release_cred(&ctx->minor, &client->creds);
+		client->name = new_name;
+		client->creds = ctx->client_creds;
+        	ctx->client_creds = GSS_C_NO_CREDENTIAL;
+		client->updated = 1;
+		return GSS_S_COMPLETE;
+	}
 
 	client->mech = NULL;
 
@@ -263,6 +370,16 @@
 	if (client->mech == NULL)
 		return GSS_S_FAILURE;
 
+    /* Call gss_inquire_cred rather than gss_inquire_cred_by_mech
+       because GSI doesn't support the latter. -jbasney */
+
+	if (ctx->client_creds &&
+	    (ctx->major = gss_inquire_cred(&ctx->minor,
+	     ctx->client_creds, &client->name, NULL, NULL, NULL))) {
+		ssh_gssapi_error(ctx);
+		return (ctx->major);
+	}
+
 	if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
 	    &client->displayname, NULL))) {
 		ssh_gssapi_error(ctx);
@@ -280,9 +397,15 @@
 		return (ctx->major);
 	}
 
+	gss_release_buffer(&ctx->minor, &ename);
+
 	/* We can't copy this structure, so we just move the pointer to it */
 	client->creds = ctx->client_creds;
 	ctx->client_creds = GSS_C_NO_CREDENTIAL;
+
+    /* needed for globus_gss_assist_map_and_authorize() */
+    client->context = ctx->context;
+
 	return (ctx->major);
 }
 
@@ -303,6 +426,11 @@
 ssh_gssapi_storecreds(void)
 {
 	if (gssapi_client.mech && gssapi_client.mech->storecreds) {
+        if (options.gss_creds_path) {
+            gssapi_client.store.filename =
+                expand_authorized_keys(options.gss_creds_path,
+                                       the_authctxt->pw);
+        }
 		(*gssapi_client.mech->storecreds)(&gssapi_client);
 	} else
 		debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism");
@@ -327,7 +455,7 @@
 
 /* Privileged */
 int
-ssh_gssapi_userok(char *user)
+ssh_gssapi_userok(char *user, struct passwd *pw, int gssapi_keyex)
 {
 	OM_uint32 lmin;
 
@@ -336,10 +464,18 @@
 		debug("No suitable client data");
 		return 0;
 	}
+#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG
+	if (limited && options.gsi_allow_limited_proxy != 1) {
+		debug("limited proxy not acceptable for remote login");
+		return 0;
+	}
+#endif
 	if (gssapi_client.mech && gssapi_client.mech->userok)
-		if ((*gssapi_client.mech->userok)(&gssapi_client, user))
+		if ((*gssapi_client.mech->userok)(&gssapi_client, user)) {
+			gssapi_client.used = 1;
+			gssapi_client.store.owner = pw;
 			return 1;
-		else {
+		} else {
 			/* Destroy delegated credentials if userok fails */
 			gss_release_buffer(&lmin, &gssapi_client.displayname);
 			gss_release_buffer(&lmin, &gssapi_client.exportedname);
@@ -352,14 +488,132 @@
 	return (0);
 }
 
-/* Privileged */
-OM_uint32
-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
+/* ssh_gssapi_checkmic() moved to gss-genr.c so it can be called by
+   kexgss_client(). */
+
+/* Priviledged */
+int
+ssh_gssapi_localname(char **user)
+{
+    	*user = NULL;
+	if (gssapi_client.displayname.length==0 || 
+	    gssapi_client.displayname.value==NULL) {
+		debug("No suitable client data");
+		return(0);;
+	}
+	if (gssapi_client.mech && gssapi_client.mech->localname) {
+		return((*gssapi_client.mech->localname)(&gssapi_client,user));
+	} else {
+		debug("Unknown client authentication type");
+	}
+	return(0);
+}
+
+/* These bits are only used for rekeying. The unpriviledged child is running 
+ * as the user, the monitor is root.
+ *
+ * In the child, we want to :
+ *    *) Ask the monitor to store our credentials into the store we specify
+ *    *) If it succeeds, maybe do a PAM update
+ */
+
+/* Stuff for PAM */
+
+#ifdef USE_PAM
+static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, 
+    struct pam_response **resp, void *data)
 {
-	ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
-	    gssbuf, gssmic, NULL);
+	return (PAM_CONV_ERR);
+}
+#endif
 
-	return (ctx->major);
+void
+ssh_gssapi_rekey_creds() {
+	int ok;
+#ifdef USE_PAM
+	int ret;
+	pam_handle_t *pamh = NULL;
+	struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL};
+	char *envstr;
+	char **p;char **pw;
+#endif
+
+	if (gssapi_client.store.filename == NULL && 
+	    gssapi_client.store.envval == NULL &&
+	    gssapi_client.store.envvar == NULL)
+		return;
+ 
+	ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
+
+	if (!ok)
+		return;
+
+	debug("Rekeyed credentials stored successfully");
+
+	/* Actually managing to play with the ssh pam stack from here will
+	 * be next to impossible. In any case, we may want different options
+	 * for rekeying. So, use our own :)
+	 */
+#ifdef USE_PAM	
+	if (!use_privsep) {
+		debug("Not even going to try and do PAM with privsep disabled");
+		return;
+	}
+
+	ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name,
+ 	    &pamconv, &pamh);
+	if (ret)
+		return;
+
+	/* Put ssh pam stack env variables in this new pam stack env 
+	 * Using pam-pkinit, KRB5CCNAME is set during do_pam_session
+	 * this addition enables pam-pkinit to access KRB5CCNAME if used 
+	 * in sshd-rekey stack too
+	 */
+	pw = p = fetch_pam_environment();
+	while ( *pw != NULL ) {
+	        pam_putenv(pamh,*pw);
+		pw++;
+	}
+	free_pam_environment(p);
+
+	xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, 
+	    gssapi_client.store.envval);
+
+	ret = pam_putenv(pamh, envstr);
+	if (!ret)
+		pam_setcred(pamh, PAM_REINITIALIZE_CRED);
+	pam_end(pamh, PAM_SUCCESS);
+#endif
+}
+
+int 
+ssh_gssapi_update_creds(ssh_gssapi_ccache *store) {
+	int ok = 0;
+
+	/* Check we've got credentials to store */
+	if (!gssapi_client.updated)
+		return 0;
+
+	gssapi_client.updated = 0;
+
+	temporarily_use_uid(gssapi_client.store.owner);
+	if (gssapi_client.mech && gssapi_client.mech->updatecreds)
+		ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client);
+	else
+		debug("No update function for this mechanism");
+
+	restore_uid();
+
+	return ok;
+}
+
+void
+ssh_gssapi_get_client_info(char **userdn, char **mech) {
+	*userdn = gssapi_client.displayname.value;
+
+	if (gssapi_client.mech)
+		*mech = gssapi_client.mech->name;
 }
 
 #endif
diff -Naur --exclude=autom4te.cache openssh-5.5p1/kex.c openssh-5.5p1-gssapi/kex.c
--- openssh-5.5p1/kex.c	2010-01-07 23:50:41.000000000 -0600
+++ openssh-5.5p1-gssapi/kex.c	2010-04-20 10:49:30.000000000 -0500
@@ -49,6 +49,11 @@
 #include "dispatch.h"
 #include "monitor.h"
 #include "roaming.h"
+#include "canohost.h"
+
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
 
 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
 # if defined(HAVE_EVP_SHA256)
@@ -63,7 +68,8 @@
 static void kex_choose_conf(Kex *);
 
 /* put algorithm proposal into buffer */
-static void
+/* used in sshconnect.c as well as kex.c */
+void
 kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
 {
 	u_int i;
@@ -326,6 +332,20 @@
 		k->kex_type = KEX_DH_GEX_SHA256;
 		k->evp_md = evp_ssh_sha256();
 #endif
+#ifdef GSSAPI
+	} else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID,
+	    sizeof(KEX_GSS_GEX_SHA1_ID) - 1) == 0) {
+		k->kex_type = KEX_GSS_GEX_SHA1;
+		k->evp_md = EVP_sha1();
+	} else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID,
+	    sizeof(KEX_GSS_GRP1_SHA1_ID) - 1) == 0) {
+		k->kex_type = KEX_GSS_GRP1_SHA1;
+		k->evp_md = EVP_sha1();
+	} else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID,
+	    sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) {
+		k->kex_type = KEX_GSS_GRP14_SHA1;
+		k->evp_md = EVP_sha1();
+#endif
 	} else
 		fatal("bad kex alg %s", k->name);
 }
@@ -375,6 +395,13 @@
 	int nenc, nmac, ncomp;
 	u_int mode, ctos, need;
 	int first_kex_follows, type;
+	int log_flag = 0;
+
+	int auth_flag;
+
+	auth_flag = packet_authentication_state();
+
+	debug ("AUTH STATE IS %d", auth_flag);
 
 	my   = kex_buf2prop(&kex->my, NULL);
 	peer = kex_buf2prop(&kex->peer, &first_kex_follows);
@@ -409,11 +436,34 @@
 		choose_enc (&newkeys->enc,  cprop[nenc],  sprop[nenc]);
 		choose_mac (&newkeys->mac,  cprop[nmac],  sprop[nmac]);
 		choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]);
+		debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name);
+		if (strcmp(newkeys->enc.name, "none") == 0) {
+				debug("Requesting NONE. Authflag is %d", auth_flag);			
+			if (auth_flag == 1) {
+				debug("None requested post authentication.");
+			} else {
+				fatal("Pre-authentication none cipher requests are not allowed.");
+			}
+		} 
 		debug("kex: %s %s %s %s",
 		    ctos ? "client->server" : "server->client",
 		    newkeys->enc.name,
 		    newkeys->mac.name,
 		    newkeys->comp.name);
+		/* client starts withctos = 0 && log flag = 0 and no log*/
+		/* 2nd client pass ctos=1 and flag = 1 so no log*/
+		/* server starts with ctos =1 && log_flag = 0 so log */
+		/* 2nd sever pass ctos = 1 && log flag = 1 so no log*/
+		/* -cjr*/
+		if (ctos && !log_flag) {
+			logit("SSH: Server;Ltype: Kex;Remote: %s-%d;Enc: %s;MAC: %s;Comp: %s",
+			      get_remote_ipaddr(),
+			      get_remote_port(),
+			      newkeys->enc.name,
+			      newkeys->mac.name,
+			      newkeys->comp.name);
+		}
+		log_flag = 1;
 	}
 	choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
 	choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
diff -Naur --exclude=autom4te.cache openssh-5.5p1/kex.h openssh-5.5p1-gssapi/kex.h
--- openssh-5.5p1/kex.h	2010-02-26 14:55:05.000000000 -0600
+++ openssh-5.5p1-gssapi/kex.h	2010-04-20 10:49:30.000000000 -0500
@@ -67,6 +67,9 @@
 	KEX_DH_GRP14_SHA1,
 	KEX_DH_GEX_SHA1,
 	KEX_DH_GEX_SHA256,
+	KEX_GSS_GRP1_SHA1,
+	KEX_GSS_GRP14_SHA1,
+	KEX_GSS_GEX_SHA1,
 	KEX_MAX
 };
 
@@ -108,6 +111,7 @@
 	Mac	mac;
 	Comp	comp;
 };
+
 struct Kex {
 	u_char	*session_id;
 	u_int	session_id_len;
@@ -123,6 +127,12 @@
 	sig_atomic_t done;
 	int	flags;
 	const EVP_MD *evp_md;
+#ifdef GSSAPI
+	int	gss_deleg_creds;
+	int	gss_trust_dns;
+	char    *gss_host;
+	char	*gss_client;
+#endif
 	char	*client_version_string;
 	char	*server_version_string;
 	int	(*verify_host_key)(Key *);
@@ -132,6 +142,8 @@
 	void	(*kex[KEX_MAX])(Kex *);
 };
 
+void kex_prop2buf(Buffer *, char *proposal[PROPOSAL_MAX]);
+
 Kex	*kex_setup(char *[PROPOSAL_MAX]);
 void	 kex_finish(Kex *);
 
@@ -146,6 +158,11 @@
 void	 kexgex_client(Kex *);
 void	 kexgex_server(Kex *);
 
+#ifdef GSSAPI
+void	kexgss_client(Kex *);
+void	kexgss_server(Kex *);
+#endif
+
 void
 kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
     BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *);
diff -Naur --exclude=autom4te.cache openssh-5.5p1/kexgssc.c openssh-5.5p1-gssapi/kexgssc.c
--- openssh-5.5p1/kexgssc.c	1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.5p1-gssapi/kexgssc.c	2010-04-20 10:49:30.000000000 -0500
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2001-2009 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 "includes.h"
+
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+
+#include <string.h>
+
+#include "xmalloc.h"
+#include "buffer.h"
+#include "ssh2.h"
+#include "key.h"
+#include "cipher.h"
+#include "kex.h"
+#include "log.h"
+#include "packet.h"
+#include "dh.h"
+
+#include "ssh-gss.h"
+
+void
+kexgss_client(Kex *kex) {
+	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
+	gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr;
+	Gssctxt *ctxt;
+	OM_uint32 maj_status, min_status, ret_flags;
+	u_int klen, kout, slen = 0, hashlen, strlen;
+	DH *dh; 
+	BIGNUM *dh_server_pub = NULL;
+	BIGNUM *shared_secret = NULL;
+	BIGNUM *p = NULL;
+	BIGNUM *g = NULL;	
+	u_char *kbuf, *hash;
+	u_char *serverhostkey = NULL;
+	u_char *empty = "";
+	char *msg;
+	char *lang;
+	int type = 0;
+	int first = 1;
+	int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
+
+	/* Initialise our GSSAPI world */	
+	ssh_gssapi_build_ctx(&ctxt);
+	if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) 
+	    == GSS_C_NO_OID)
+		fatal("Couldn't identify host exchange");
+
+	if (ssh_gssapi_import_name(ctxt, kex->gss_host))
+		fatal("Couldn't import hostname");
+
+	if (kex->gss_client && 
+	    ssh_gssapi_client_identity(ctxt, kex->gss_client))
+		fatal("Couldn't acquire client credentials");
+
+	switch (kex->kex_type) {
+	case KEX_GSS_GRP1_SHA1:
+		dh = dh_new_group1();
+		break;
+	case KEX_GSS_GRP14_SHA1:
+		dh = dh_new_group14();
+		break;
+	case KEX_GSS_GEX_SHA1:
+		debug("Doing group exchange\n");
+		nbits = dh_estimate(kex->we_need * 8);
+		packet_start(SSH2_MSG_KEXGSS_GROUPREQ);
+		packet_put_int(min);
+		packet_put_int(nbits);
+		packet_put_int(max);
+
+		packet_send();
+
+		packet_read_expect(SSH2_MSG_KEXGSS_GROUP);
+
+		if ((p = BN_new()) == NULL)
+			fatal("BN_new() failed");
+		packet_get_bignum2(p);
+		if ((g = BN_new()) == NULL)
+			fatal("BN_new() failed");
+		packet_get_bignum2(g);
+		packet_check_eom();
+
+		if (BN_num_bits(p) < min || BN_num_bits(p) > max)
+			fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
+			    min, BN_num_bits(p), max);
+
+		dh = dh_new_group(g, p);
+		break;
+	default:
+		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
+	}
+	
+	/* Step 1 - e is dh->pub_key */
+	dh_gen_key(dh, kex->we_need * 8);
+
+	/* This is f, we initialise it now to make life easier */
+	dh_server_pub = BN_new();
+	if (dh_server_pub == NULL)
+		fatal("dh_server_pub == NULL");
+
+	token_ptr = GSS_C_NO_BUFFER;
+			 
+	do {
+		debug("Calling gss_init_sec_context");
+		
+		maj_status = ssh_gssapi_init_ctx(ctxt,
+		    kex->gss_deleg_creds, token_ptr, &send_tok,
+		    &ret_flags);
+
+		if (GSS_ERROR(maj_status)) {
+			if (send_tok.length != 0) {
+				packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+				packet_put_string(send_tok.value,
+				    send_tok.length);
+			}
+			fatal("gss_init_context failed");
+		}
+
+		/* If we've got an old receive buffer get rid of it */
+		if (token_ptr != GSS_C_NO_BUFFER)
+			xfree(recv_tok.value);
+
+		if (maj_status == GSS_S_COMPLETE) {
+			/* If mutual state flag is not true, kex fails */
+			if (!(ret_flags & GSS_C_MUTUAL_FLAG))
+				fatal("Mutual authentication failed");
+
+			/* If integ avail flag is not true kex fails */
+			if (!(ret_flags & GSS_C_INTEG_FLAG))
+				fatal("Integrity check failed");
+		}
+
+		/* 
+		 * If we have data to send, then the last message that we
+		 * received cannot have been a 'complete'. 
+		 */
+		if (send_tok.length != 0) {
+			if (first) {
+				packet_start(SSH2_MSG_KEXGSS_INIT);
+				packet_put_string(send_tok.value,
+				    send_tok.length);
+				packet_put_bignum2(dh->pub_key);
+				first = 0;
+			} else {
+				packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+				packet_put_string(send_tok.value,
+				    send_tok.length);
+			}
+			packet_send();
+			gss_release_buffer(&min_status, &send_tok);
+
+			/* If we've sent them data, they should reply */
+			do {	
+				type = packet_read();
+				if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
+					debug("Received KEXGSS_HOSTKEY");
+					if (serverhostkey)
+						fatal("Server host key received more than once");
+					serverhostkey = 
+					    packet_get_string(&slen);
+				}
+			} while (type == SSH2_MSG_KEXGSS_HOSTKEY);
+
+			switch (type) {
+			case SSH2_MSG_KEXGSS_CONTINUE:
+				debug("Received GSSAPI_CONTINUE");
+				if (maj_status == GSS_S_COMPLETE) 
+					fatal("GSSAPI Continue received from server when complete");
+				recv_tok.value = packet_get_string(&strlen);
+				recv_tok.length = strlen; 
+				break;
+			case SSH2_MSG_KEXGSS_COMPLETE:
+				debug("Received GSSAPI_COMPLETE");
+				packet_get_bignum2(dh_server_pub);
+				msg_tok.value =  packet_get_string(&strlen);
+				msg_tok.length = strlen; 
+
+				/* Is there a token included? */
+				if (packet_get_char()) {
+					recv_tok.value=
+					    packet_get_string(&strlen);
+					recv_tok.length = strlen;
+					/* If we're already complete - protocol error */
+					if (maj_status == GSS_S_COMPLETE)
+						packet_disconnect("Protocol error: received token when complete");
+					} else {
+						/* No token included */
+						if (maj_status != GSS_S_COMPLETE)
+							packet_disconnect("Protocol error: did not receive final token");
+				}
+				break;
+			case SSH2_MSG_KEXGSS_ERROR:
+				debug("Received Error");
+				maj_status = packet_get_int();
+				min_status = packet_get_int();
+				msg = packet_get_string(NULL);
+				lang = packet_get_string(NULL);
+				fatal("GSSAPI Error: \n%.400s",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);
+	if (kout < 0)
+		fatal("DH_compute_key: failed");
+
+	shared_secret = BN_new();
+	if (shared_secret == NULL)
+		fatal("kexgss_client: BN_new failed");
+
+	if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
+		fatal("kexdh_client: BN_bin2bn failed");
+
+	memset(kbuf, 0, klen);
+	xfree(kbuf);
+
+	switch (kex->kex_type) {
+	case KEX_GSS_GRP1_SHA1:
+	case KEX_GSS_GRP14_SHA1:
+		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 ? serverhostkey : empty), slen,
+		    dh->pub_key,	/* e */
+		    dh_server_pub,	/* f */
+		    shared_secret,	/* K */
+		    &hash, &hashlen
+		);
+		break;
+	case KEX_GSS_GEX_SHA1:
+		kexgex_hash(
+		    kex->evp_md,
+		    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 ? serverhostkey : empty), slen,
+ 		    min, nbits, max,
+		    dh->p, dh->g,
+		    dh->pub_key,
+		    dh_server_pub,
+		    shared_secret,
+		    &hash, &hashlen
+		);
+		break;
+	default:
+		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
+	}
+
+	gssbuf.value = hash;
+	gssbuf.length = hashlen;
+
+	/* Verify that the hash matches the MIC we just got. */
+	if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
+		packet_disconnect("Hash's MIC didn't verify");
+
+	xfree(msg_tok.value);
+
+	DH_free(dh);
+	if (serverhostkey)
+		xfree(serverhostkey);
+	BN_clear_free(dh_server_pub);
+
+	/* save session id */
+	if (kex->session_id == NULL) {
+		kex->session_id_len = hashlen;
+		kex->session_id = xmalloc(kex->session_id_len);
+		memcpy(kex->session_id, hash, kex->session_id_len);
+	}
+
+	if (kex->gss_deleg_creds)
+		ssh_gssapi_credentials_updated(ctxt);
+
+	if (gss_kex_context == NULL)
+		gss_kex_context = ctxt;
+	else
+		ssh_gssapi_delete_ctx(&ctxt);
+
+	kex_derive_keys(kex, hash, hashlen, shared_secret);
+	BN_clear_free(shared_secret);
+	kex_finish(kex);
+}
+
+#endif /* GSSAPI */
diff -Naur --exclude=autom4te.cache openssh-5.5p1/kexgsss.c openssh-5.5p1-gssapi/kexgsss.c
--- openssh-5.5p1/kexgsss.c	1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.5p1-gssapi/kexgsss.c	2010-04-20 10:49:30.000000000 -0500
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2001-2009 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 <string.h>
+
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+
+#include "xmalloc.h"
+#include "buffer.h"
+#include "ssh2.h"
+#include "key.h"
+#include "cipher.h"
+#include "kex.h"
+#include "log.h"
+#include "packet.h"
+#include "dh.h"
+#include "ssh-gss.h"
+#include "monitor_wrap.h"
+#include "servconf.h"
+
+static void kex_gss_send_error(Gssctxt *ctxt);
+extern ServerOptions options;
+
+void
+kexgss_server(Kex *kex)
+{
+	OM_uint32 maj_status, min_status;
+	
+	/* 
+	 * Some GSSAPI implementations use the input value of ret_flags (an
+ 	 * output variable) as a means of triggering mechanism specific 
+ 	 * features. Initializing it to zero avoids inadvertently 
+ 	 * activating this non-standard behaviour.
+	 */
+
+	OM_uint32 ret_flags = 0;
+	gss_buffer_desc gssbuf, recv_tok, msg_tok;
+	gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
+	Gssctxt *ctxt = NULL;
+	u_int slen, klen, kout, hashlen;
+	u_char *kbuf, *hash;
+	DH *dh;
+	int min = -1, max = -1, nbits = -1;
+	BIGNUM *shared_secret = NULL;
+	BIGNUM *dh_client_pub = NULL;
+	int type = 0;
+	gss_OID oid;
+	char *mechs;
+
+	/* Initialise GSSAPI */
+
+	/* If we're rekeying, privsep means that some of the private structures
+	 * in the GSSAPI code are no longer available. This kludges them back
+	 * into life
+	 */
+	if (!ssh_gssapi_oid_table_ok()) 
+		if ((mechs = ssh_gssapi_server_mechanisms()))
+			xfree(mechs);
+
+	debug2("%s: Identifying %s", __func__, kex->name);
+	oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type);
+	if (oid == GSS_C_NO_OID)
+	   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");
+    }
+
+	switch (kex->kex_type) {
+	case KEX_GSS_GRP1_SHA1:
+		dh = dh_new_group1();
+		break;
+	case KEX_GSS_GRP14_SHA1:
+		dh = dh_new_group14();
+		break;
+	case KEX_GSS_GEX_SHA1:
+		debug("Doing group exchange");
+		packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);
+		min = packet_get_int();
+		nbits = packet_get_int();
+		max = packet_get_int();
+		min = MAX(DH_GRP_MIN, min);
+		max = MIN(DH_GRP_MAX, max);
+		packet_check_eom();
+		if (max < min || nbits < min || max < nbits)
+			fatal("GSS_GEX, bad parameters: %d !< %d !< %d",
+			    min, nbits, max);
+		dh = PRIVSEP(choose_dh(min, nbits, max));
+		if (dh == NULL)
+			packet_disconnect("Protocol error: no matching group found");
+
+		packet_start(SSH2_MSG_KEXGSS_GROUP);
+		packet_put_bignum2(dh->p);
+		packet_put_bignum2(dh->g);
+		packet_send();
+
+		packet_write_wait();
+		break;
+	default:
+		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
+	}
+
+	dh_gen_key(dh, kex->we_need * 8);
+
+	do {
+		debug("Wait SSH2_MSG_GSSAPI_INIT");
+		type = packet_read();
+		switch(type) {
+		case SSH2_MSG_KEXGSS_INIT:
+			if (dh_client_pub != NULL) 
+				fatal("Received KEXGSS_INIT after initialising");
+			recv_tok.value = packet_get_string(&slen);
+			recv_tok.length = slen; 
+
+			if ((dh_client_pub = BN_new()) == NULL)
+				fatal("dh_client_pub == NULL");
+
+			packet_get_bignum2(dh_client_pub);
+
+			/* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
+			break;
+		case SSH2_MSG_KEXGSS_CONTINUE:
+			recv_tok.value = packet_get_string(&slen);
+			recv_tok.length = slen; 
+			break;
+		default:
+			packet_disconnect(
+			    "Protocol error: didn't expect packet type %d",
+			    type);
+		}
+
+		maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, 
+		    &send_tok, &ret_flags));
+
+		xfree(recv_tok.value);
+
+		if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
+			fatal("Zero length token output when incomplete");
+
+		if (dh_client_pub == NULL)
+			fatal("No client public key");
+		
+		if (maj_status & GSS_S_CONTINUE_NEEDED) {
+			debug("Sending GSSAPI_CONTINUE");
+			packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+			packet_put_string((char *)send_tok.value, send_tok.length);
+			packet_send();
+			gss_release_buffer(&min_status, &send_tok);
+		}
+	} while (maj_status & GSS_S_CONTINUE_NEEDED);
+
+	if (GSS_ERROR(maj_status)) {
+		kex_gss_send_error(ctxt);
+		if (send_tok.length > 0) {
+			packet_start(SSH2_MSG_KEXGSS_CONTINUE);
+			packet_put_string((char *)send_tok.value, send_tok.length);
+			packet_send();
+		}
+		packet_disconnect("GSSAPI Key Exchange handshake failed");
+	}
+
+	if (!(ret_flags & GSS_C_MUTUAL_FLAG))
+		fatal("Mutual Authentication flag wasn't set");
+
+	if (!(ret_flags & GSS_C_INTEG_FLAG))
+		fatal("Integrity flag wasn't set");
+	
+	if (!dh_pub_is_valid(dh, dh_client_pub))
+		packet_disconnect("bad client public DH value");
+
+	klen = DH_size(dh);
+	kbuf = xmalloc(klen); 
+	kout = DH_compute_key(kbuf, dh_client_pub, dh);
+	if (kout < 0)
+		fatal("DH_compute_key: failed");
+
+	shared_secret = BN_new();
+	if (shared_secret == NULL)
+		fatal("kexgss_server: BN_new failed");
+
+	if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
+		fatal("kexgss_server: BN_bin2bn failed");
+
+	memset(kbuf, 0, klen);
+	xfree(kbuf);
+
+	switch (kex->kex_type) {
+	case KEX_GSS_GRP1_SHA1:
+	case KEX_GSS_GRP14_SHA1:
+		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,
+		    &hash, &hashlen
+		);
+		break;
+	case KEX_GSS_GEX_SHA1:
+		kexgex_hash(
+		    kex->evp_md,
+		    kex->client_version_string, kex->server_version_string,
+		    buffer_ptr(&kex->peer), buffer_len(&kex->peer),
+		    buffer_ptr(&kex->my), buffer_len(&kex->my),
+		    NULL, 0,
+		    min, nbits, max,
+		    dh->p, dh->g,
+		    dh_client_pub,
+		    dh->pub_key,
+		    shared_secret,
+		    &hash, &hashlen
+		);
+		break;
+	default:
+		fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
+	}
+
+	BN_clear_free(dh_client_pub);
+
+	if (kex->session_id == NULL) {
+		kex->session_id_len = hashlen;
+		kex->session_id = xmalloc(kex->session_id_len);
+		memcpy(kex->session_id, hash, kex->session_id_len);
+	}
+
+	gssbuf.value = hash;
+	gssbuf.length = hashlen;
+
+	if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))
+		fatal("Couldn't get MIC");
+
+	packet_start(SSH2_MSG_KEXGSS_COMPLETE);
+	packet_put_bignum2(dh->pub_key);
+	packet_put_string((char *)msg_tok.value,msg_tok.length);
+
+	if (send_tok.length != 0) {
+		packet_put_char(1); /* true */
+		packet_put_string((char *)send_tok.value, send_tok.length);
+	} else {
+		packet_put_char(0); /* false */
+	}
+	packet_send();
+
+	gss_release_buffer(&min_status, &send_tok);
+	gss_release_buffer(&min_status, &msg_tok);
+
+	if (gss_kex_context == NULL)
+		gss_kex_context = ctxt;
+	else 
+		ssh_gssapi_delete_ctx(&ctxt);
+
+	DH_free(dh);
+
+	kex_derive_keys(kex, hash, hashlen, shared_secret);
+	BN_clear_free(shared_secret);
+	kex_finish(kex);
+
+	/* If this was a rekey, then save out any delegated credentials we
+	 * just exchanged.  */
+	if (options.gss_store_rekey)
+		ssh_gssapi_rekey_creds();
+}
+
+static void 
+kex_gss_send_error(Gssctxt *ctxt) {
+	char *errstr;
+	OM_uint32 maj,min;
+		
+	errstr=PRIVSEP(ssh_gssapi_last_error(ctxt,&maj,&min));
+	if (errstr) {
+		packet_start(SSH2_MSG_KEXGSS_ERROR);
+		packet_put_int(maj);
+		packet_put_int(min);
+		packet_put_cstring(errstr);
+		packet_put_cstring("");
+		packet_send();
+		packet_write_wait();
+		/* XXX - We should probably log the error locally here */
+		xfree(errstr);
+	}
+}
+#endif /* GSSAPI */
diff -Naur --exclude=autom4te.cache openssh-5.5p1/key.c openssh-5.5p1-gssapi/key.c
--- openssh-5.5p1/key.c	2010-03-21 13:58:24.000000000 -0500
+++ openssh-5.5p1-gssapi/key.c	2010-04-20 10:49:30.000000000 -0500
@@ -978,6 +978,8 @@
 		return KEY_RSA;
 	} else if (strcmp(name, "ssh-dss") == 0) {
 		return KEY_DSA;
+	} else if (strcmp(name, "null") == 0) {
+		return KEY_NULL;
 	} else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) {
 		return KEY_RSA_CERT;
 	} else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) {
diff -Naur --exclude=autom4te.cache openssh-5.5p1/key.h openssh-5.5p1-gssapi/key.h
--- openssh-5.5p1/key.h	2010-03-21 13:58:24.000000000 -0500
+++ openssh-5.5p1-gssapi/key.h	2010-04-20 10:49:30.000000000 -0500
@@ -35,6 +35,7 @@
 	KEY_RSA1,
 	KEY_RSA,
 	KEY_DSA,
+	KEY_NULL,
 	KEY_RSA_CERT,
 	KEY_DSA_CERT,
 	KEY_UNSPEC
diff -Naur --exclude=autom4te.cache openssh-5.5p1/misc.c openssh-5.5p1-gssapi/misc.c
--- openssh-5.5p1/misc.c	2010-01-09 17:31:12.000000000 -0600
+++ openssh-5.5p1-gssapi/misc.c	2010-04-20 10:49:30.000000000 -0500
@@ -155,11 +155,14 @@
 #define WHITESPACE " \t\r\n"
 #define QUOTE	"\""
 
+/* Characters considered as quotations. */
+#define QUOTES "'\""
+
 /* return next token in configuration line */
 char *
 strdelim(char **s)
 {
-	char *old;
+	char *old, *p, *q;
 	int wspace = 0;
 
 	if (*s == NULL)
@@ -167,6 +170,21 @@
 
 	old = *s;
 
+        if ((q=strchr(QUOTES, (int) *old)) && *q)
+        {
+            /* find next quote character, point old to start of quoted
+             * string */
+            for (p = ++old;*p && *p!=*q; p++)
+                 ;
+            
+            /* find start of next token */
+            *s = (*p) ? p + strspn(p + 1, WHITESPACE) + 1 : NULL;
+            
+            /* terminate 'old' token */
+            *p = '\0';
+            return (old);
+        }
+
 	*s = strpbrk(*s, WHITESPACE QUOTE "=");
 	if (*s == NULL)
 		return (old);
@@ -219,6 +237,20 @@
 	return copy;
 }
 
+void
+pwfree(struct passwd *pw)
+{
+	xfree(pw->pw_name);
+	xfree(pw->pw_passwd);
+	xfree(pw->pw_gecos);
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+	xfree(pw->pw_class);
+#endif
+	xfree(pw->pw_dir);
+	xfree(pw->pw_shell);
+	xfree(pw);
+}
+
 /*
  * Convert ASCII string to TCP/IP port number.
  * Port must be >=0 and <=65535.
diff -Naur --exclude=autom4te.cache openssh-5.5p1/misc.h openssh-5.5p1-gssapi/misc.h
--- openssh-5.5p1/misc.h	2010-01-09 17:31:12.000000000 -0600
+++ openssh-5.5p1-gssapi/misc.h	2010-04-20 10:49:30.000000000 -0500
@@ -38,6 +38,7 @@
 void	 sock_set_v6only(int);
 
 struct passwd *pwcopy(struct passwd *);
+void	 pwfree(struct passwd *);
 const char *ssh_gai_strerror(int);
 
 typedef struct arglist arglist;
diff -Naur --exclude=autom4te.cache openssh-5.5p1/monitor.c openssh-5.5p1-gssapi/monitor.c
--- openssh-5.5p1/monitor.c	2010-03-07 06:05:17.000000000 -0600
+++ openssh-5.5p1-gssapi/monitor.c	2010-04-20 10:49:30.000000000 -0500
@@ -172,6 +172,11 @@
 int mm_answer_gss_accept_ctx(int, Buffer *);
 int mm_answer_gss_userok(int, Buffer *);
 int mm_answer_gss_checkmic(int, Buffer *);
+int mm_answer_gss_sign(int, Buffer *);
+int mm_answer_gss_error(int, Buffer *);
+int mm_answer_gss_indicate_mechs(int, Buffer *);
+int mm_answer_gss_localname(int, Buffer *);
+int mm_answer_gss_updatecreds(int, Buffer *);
 #endif
 
 #ifdef SSH_AUDIT_EVENTS
@@ -211,12 +216,12 @@
 struct mon_table mon_dispatch_proto20[] = {
     {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
-    {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
+    {MONITOR_REQ_PWNAM, MON_AUTH, mm_answer_pwnamallow},
     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
     {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
     {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
 #ifdef USE_PAM
-    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
+    {MONITOR_REQ_PAM_START, MON_ISAUTH, mm_answer_pam_start},
     {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
     {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
     {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
@@ -241,6 +246,10 @@
     {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
     {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
     {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
+    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
+    {MONITOR_REQ_GSSERR, MON_ISAUTH | MON_ONCE, mm_answer_gss_error},
+    {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs},
+    {MONITOR_REQ_GSSLOCALNAME, MON_ISAUTH, mm_answer_gss_localname},
 #endif
 #ifdef JPAKE
     {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata},
@@ -253,6 +262,14 @@
 };
 
 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},
+    {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds},
+#endif
     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
     {MONITOR_REQ_SIGN, 0, mm_answer_sign},
     {MONITOR_REQ_PTY, 0, mm_answer_pty},
@@ -282,8 +299,15 @@
     {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
     {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
 #endif
+#ifdef GSSAPI
+    {MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
+    {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
+    {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
+    {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
+    {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs},
+#endif
 #ifdef USE_PAM
-    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
+    {MONITOR_REQ_PAM_START, MON_ISAUTH, mm_answer_pam_start},
     {MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
     {MONITOR_REQ_PAM_INIT_CTX, MON_ISAUTH, mm_answer_pam_init_ctx},
     {MONITOR_REQ_PAM_QUERY, MON_ISAUTH, mm_answer_pam_query},
@@ -357,6 +381,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;
 
@@ -443,10 +473,21 @@
 		monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
+
+#ifdef GSSAPI
+		/* and for the GSSAPI key exchange */
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSMECHS,1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP,1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR,1);
+#endif
+
 	} else {
 		mon_dispatch = mon_dispatch_postauth15;
 		monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
 	}
+#ifdef GSSAPI		
+	monitor_permit(mon_dispatch, MONITOR_REQ_GSSERR, 1);
+#endif
 	if (!no_pty_flag) {
 		monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
@@ -635,14 +676,17 @@
 
 	debug3("%s", __func__);
 
-	if (authctxt->attempt++ != 0)
-		fatal("%s: multiple attempts for getpwnam", __func__);
-
 	username = buffer_get_string(m, NULL);
 
 	pwent = getpwnamallow(username);
 
+	if (authctxt->user) xfree(authctxt->user);
 	authctxt->user = xstrdup(username);
+#ifdef USE_PAM
+    if (options.permit_pam_user_change)
+        setproctitle("%s [priv]", pwent ? "[pam]" : "unknown");
+    else
+#endif
 	setproctitle("%s [priv]", pwent ? username : "unknown");
 	xfree(username);
 
@@ -1691,6 +1735,13 @@
 	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
 	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
 	kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+#ifdef GSSAPI
+	if (options.gss_keyex) {
+		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
+		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+	}
+#endif
 	kex->server = 1;
 	kex->hostkey_type = buffer_get_int(m);
 	kex->kex_type = buffer_get_int(m);
@@ -1897,6 +1948,9 @@
 	OM_uint32 major;
 	u_int len;
 
+	if (!options.gss_authentication && !options.gss_keyex)
+		fatal("In GSSAPI monitor when GSSAPI is disabled");
+
 	goid.elements = buffer_get_string(m, &len);
 	goid.length = len;
 
@@ -1924,6 +1978,9 @@
 	OM_uint32 flags = 0; /* GSI needs this */
 	u_int len;
 
+	if (!options.gss_authentication && !options.gss_keyex)
+		fatal("In GSSAPI monitor when GSSAPI is disabled");
+
 	in.value = buffer_get_string(m, &len);
 	in.length = len;
 	major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
@@ -1940,7 +1997,9 @@
 	if (major == GSS_S_COMPLETE) {
 		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
 		monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
+		monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1);
 	}
 	return (0);
 }
@@ -1952,6 +2011,9 @@
 	OM_uint32 ret;
 	u_int len;
 
+	if (!options.gss_authentication && !options.gss_keyex)
+		fatal("In GSSAPI monitor when GSSAPI is disabled");
+
 	gssbuf.value = buffer_get_string(m, &len);
 	gssbuf.length = len;
 	mic.value = buffer_get_string(m, &len);
@@ -1977,8 +2039,15 @@
 mm_answer_gss_userok(int sock, Buffer *m)
 {
 	int authenticated;
+	int gssapi_keyex;
+
+	if (!options.gss_authentication && !options.gss_keyex)
+		fatal("In GSSAPI monitor when GSSAPI is disabled");
+
+	gssapi_keyex = buffer_get_int(m);
 
-	authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
+	authenticated = authctxt->valid && 
+	    ssh_gssapi_userok(authctxt->user, authctxt->pw, gssapi_keyex);
 
 	buffer_clear(m);
 	buffer_put_int(m, authenticated);
@@ -1986,11 +2055,146 @@
 	debug3("%s: sending result %d", __func__, authenticated);
 	mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m);
 
-	auth_method = "gssapi-with-mic";
+	if (gssapi_keyex)
+		auth_method = "gssapi-keyex";
+	else
+		auth_method = "gssapi-with-mic";
 
 	/* Monitor loop will terminate if authenticated */
 	return (authenticated);
 }
+
+int
+mm_answer_gss_error(int socket, Buffer *m) {
+        OM_uint32 major,minor;
+        char *msg;
+
+	msg=ssh_gssapi_last_error(gsscontext,&major,&minor);
+	buffer_clear(m);
+	buffer_put_int(m,major);
+	buffer_put_int(m,minor);
+	buffer_put_cstring(m,msg);
+
+	mm_request_send(socket,MONITOR_ANS_GSSERR,m);
+
+	xfree(msg);
+	
+        return(0);
+}
+
+int
+mm_answer_gss_indicate_mechs(int socket, Buffer *m) {
+        OM_uint32 major,minor;
+	gss_OID_set mech_set;
+	size_t i;
+
+	major=gss_indicate_mechs(&minor, &mech_set);
+
+	buffer_clear(m);
+	buffer_put_int(m, major);
+	buffer_put_int(m, mech_set->count);
+	for (i=0; i < mech_set->count; i++) {
+	    buffer_put_string(m, mech_set->elements[i].elements,
+			      mech_set->elements[i].length);
+	}
+
+#if !defined(MECHGLUE) /* mechglue memory management bug ??? */
+	gss_release_oid_set(&minor,&mech_set);
+#endif
+	
+	mm_request_send(socket,MONITOR_ANS_GSSMECHS,m);
+
+	return(0);
+}
+
+int
+mm_answer_gss_localname(int socket, Buffer *m) {
+	char *name;
+
+	ssh_gssapi_localname(&name);
+
+        buffer_clear(m);
+	if (name) {
+	    buffer_put_cstring(m, name);
+	    debug3("%s: sending result %s", __func__, name);
+	    xfree(name);
+	} else {
+	    buffer_put_cstring(m, "");
+	    debug3("%s: sending result \"\"", __func__);
+	}
+
+        mm_request_send(socket, MONITOR_ANS_GSSLOCALNAME, m);
+
+        return(0);
+}
+
+int 
+mm_answer_gss_sign(int socket, Buffer *m)
+{
+	gss_buffer_desc data;
+	gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
+	OM_uint32 major, minor;
+	u_int len;
+
+	if (!options.gss_authentication && !options.gss_keyex)
+		fatal("In GSSAPI monitor when GSSAPI is disabled");
+
+	data.value = buffer_get_string(m, &len);
+	data.length = len;
+	if (data.length != 20) 
+		fatal("%s: data length incorrect: %d", __func__, 
+		    (int) data.length);
+
+	/* Save the session ID on the first time around */
+	if (session_id2_len == 0) {
+		session_id2_len = data.length;
+		session_id2 = xmalloc(session_id2_len);
+		memcpy(session_id2, data.value, session_id2_len);
+	}
+	major = ssh_gssapi_sign(gsscontext, &data, &hash);
+
+	xfree(data.value);
+
+	buffer_clear(m);
+	buffer_put_int(m, major);
+	buffer_put_string(m, hash.value, hash.length);
+
+	mm_request_send(socket, MONITOR_ANS_GSSSIGN, m);
+
+	gss_release_buffer(&minor, &hash);
+
+	/* Turn on getpwnam permissions */
+	monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
+	
+	/* And credential updating, for when rekeying */
+	monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1);
+
+	return (0);
+}
+
+int
+mm_answer_gss_updatecreds(int socket, Buffer *m) {
+	ssh_gssapi_ccache store;
+	int ok;
+
+	store.filename = buffer_get_string(m, NULL);
+	store.envvar   = buffer_get_string(m, NULL);
+	store.envval   = buffer_get_string(m, NULL);
+
+	ok = ssh_gssapi_update_creds(&store);
+
+	xfree(store.filename);
+	xfree(store.envvar);
+	xfree(store.envval);
+
+	buffer_clear(m);
+	buffer_put_int(m, ok);
+
+	mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m);
+
+	return(0);
+}
+
 #endif /* GSSAPI */
 
 #ifdef JPAKE
diff -Naur --exclude=autom4te.cache openssh-5.5p1/monitor.h openssh-5.5p1-gssapi/monitor.h
--- openssh-5.5p1/monitor.h	2008-11-04 23:20:46.000000000 -0600
+++ openssh-5.5p1-gssapi/monitor.h	2010-04-20 10:49:30.000000000 -0500
@@ -52,7 +52,12 @@
 	MONITOR_REQ_GSSSETUP, MONITOR_ANS_GSSSETUP,
 	MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP,
 	MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK,
+	MONITOR_REQ_GSSMECHS, MONITOR_ANS_GSSMECHS,
+	MONITOR_REQ_GSSLOCALNAME, MONITOR_ANS_GSSLOCALNAME,
+	MONITOR_REQ_GSSERR, MONITOR_ANS_GSSERR,
 	MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC,
+	MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN,
+	MONITOR_REQ_GSSUPCREDS, MONITOR_ANS_GSSUPCREDS,
 	MONITOR_REQ_PAM_START,
 	MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT,
 	MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX,
@@ -65,7 +70,7 @@
 	MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
 	MONITOR_REQ_JPAKE_STEP2, MONITOR_ANS_JPAKE_STEP2,
 	MONITOR_REQ_JPAKE_KEY_CONFIRM, MONITOR_ANS_JPAKE_KEY_CONFIRM,
-	MONITOR_REQ_JPAKE_CHECK_CONFIRM, MONITOR_ANS_JPAKE_CHECK_CONFIRM,
+	MONITOR_REQ_JPAKE_CHECK_CONFIRM, MONITOR_ANS_JPAKE_CHECK_CONFIRM
 };
 
 struct mm_master;
diff -Naur --exclude=autom4te.cache openssh-5.5p1/monitor_wrap.c openssh-5.5p1-gssapi/monitor_wrap.c
--- openssh-5.5p1/monitor_wrap.c	2010-03-07 06:05:17.000000000 -0600
+++ openssh-5.5p1-gssapi/monitor_wrap.c	2010-04-20 10:49:30.000000000 -0500
@@ -1231,12 +1231,13 @@
 }
 
 int
-mm_ssh_gssapi_userok(char *user)
+mm_ssh_gssapi_userok(char *user, struct passwd *pw, int gssapi_keyex)
 {
 	Buffer m;
 	int authenticated = 0;
 
 	buffer_init(&m);
+	buffer_put_int(&m, gssapi_keyex);
 
 	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m);
 	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK,
@@ -1248,6 +1249,128 @@
 	debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
 	return (authenticated);
 }
+
+char *
+mm_ssh_gssapi_last_error(Gssctxt *ctx, OM_uint32 *major, OM_uint32 *minor) {
+	Buffer m;
+	OM_uint32 maj,min;
+	char *errstr;
+	
+	buffer_init(&m);
+
+	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSERR, &m);
+	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSERR, &m);
+
+	maj = buffer_get_int(&m);
+	min = buffer_get_int(&m);
+
+	if (major) *major=maj;
+	if (minor) *minor=min;
+	
+	errstr=buffer_get_string(&m,NULL);
+
+	buffer_free(&m);
+	
+	return(errstr);
+}	
+
+OM_uint32
+mm_gss_indicate_mechs(OM_uint32 *minor_status, gss_OID_set *mech_set)
+{
+        Buffer m;
+	OM_uint32 major,minor;
+	int count;
+	gss_OID_desc oid;
+        u_int length;
+
+	buffer_init(&m);
+
+	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSMECHS, &m);
+        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSMECHS,
+				  &m);
+        major=buffer_get_int(&m);
+	count=buffer_get_int(&m);
+	
+        gss_create_empty_oid_set(&minor,mech_set);
+	while(count-->0) {
+	    oid.elements=buffer_get_string(&m,&length);
+	    oid.length=length;
+	    gss_add_oid_set_member(&minor,&oid,mech_set);
+	}
+
+	buffer_free(&m);
+	
+        return(major);
+}
+
+int
+mm_ssh_gssapi_localname(char **lname)
+{
+        Buffer m;
+
+	buffer_init(&m);
+        mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSLOCALNAME, &m);
+
+        debug3("%s: waiting for MONITOR_ANS_GSSLOCALNAME", __func__);
+        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSLOCALNAME,
+                                  &m);
+
+	*lname = buffer_get_string(&m, NULL);
+
+        buffer_free(&m);
+	if (lname[0] == '\0') {
+	    debug3("%s: gssapi identity mapping failed", __func__);
+	} else {
+	    debug3("%s: gssapi identity mapped to %s", __func__, *lname);
+	}
+	
+        return(0);
+}	
+
+OM_uint32
+mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash)
+{
+	Buffer m;
+	OM_uint32 major;
+	u_int len;
+
+	buffer_init(&m);
+	buffer_put_string(&m, data->value, data->length);
+
+	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m);
+	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m);
+
+	major = buffer_get_int(&m);
+	hash->value = buffer_get_string(&m, &len);
+	hash->length = len;
+
+	buffer_free(&m);
+
+	return(major);
+}
+
+int
+mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store)
+{
+	Buffer m;
+	int ok;
+
+	buffer_init(&m);
+
+	buffer_put_cstring(&m, store->filename ? store->filename : "");
+	buffer_put_cstring(&m, store->envvar ? store->envvar : "");
+	buffer_put_cstring(&m, store->envval ? store->envval : "");
+	
+	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m);
+	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m);
+
+	ok = buffer_get_int(&m);
+
+	buffer_free(&m);
+	
+	return (ok);
+}
+
 #endif /* GSSAPI */
 
 #ifdef JPAKE
diff -Naur --exclude=autom4te.cache openssh-5.5p1/monitor_wrap.h openssh-5.5p1-gssapi/monitor_wrap.h
--- openssh-5.5p1/monitor_wrap.h	2009-03-05 07:58:22.000000000 -0600
+++ openssh-5.5p1-gssapi/monitor_wrap.h	2010-04-20 10:49:30.000000000 -0500
@@ -57,8 +57,14 @@
 OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
 OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
    gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
-int mm_ssh_gssapi_userok(char *user);
+int mm_ssh_gssapi_userok(char *user, struct passwd *, int gssapi_keyex);
 OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
+OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
+int mm_ssh_gssapi_localname(char **user);
+OM_uint32 mm_gss_indicate_mechs(OM_uint32 *minor_status,
+				gss_OID_set *mech_set);
+char *mm_ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *maj, OM_uint32 *min);
+int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);
 #endif
 
 #ifdef USE_PAM
diff -Naur --exclude=autom4te.cache openssh-5.5p1/mux.c openssh-5.5p1-gssapi/mux.c
--- openssh-5.5p1/mux.c	2010-01-30 00:36:33.000000000 -0600
+++ openssh-5.5p1-gssapi/mux.c	2010-04-20 10:49:30.000000000 -0500
@@ -428,7 +428,11 @@
 	if (!isatty(new_fd[2]))
 		set_nonblock(new_fd[2]);
 
-	window = CHAN_SES_WINDOW_DEFAULT;
+	if (options.hpn_disabled) 
+	  window = CHAN_SES_WINDOW_DEFAULT;
+	else
+	  window = options.hpn_buffer_size;
+
 	packetmax = CHAN_SES_PACKET_DEFAULT;
 	if (cctx->want_tty) {
 		window >>= 1;
diff -Naur --exclude=autom4te.cache openssh-5.5p1/myproposal.h openssh-5.5p1-gssapi/myproposal.h
--- openssh-5.5p1/myproposal.h	2010-02-26 14:55:05.000000000 -0600
+++ openssh-5.5p1-gssapi/myproposal.h	2010-04-20 10:49:30.000000000 -0500
@@ -49,6 +49,8 @@
 	"arcfour256,arcfour128," \
 	"aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \
 	"aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"
+#define KEX_ENCRYPT_INCLUDE_NONE KEX_DEFAULT_ENCRYPT \
+	",none"
 #define	KEX_DEFAULT_MAC \
 	"hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160," \
 	"hmac-ripemd160@openssh.com," \
diff -Naur --exclude=autom4te.cache openssh-5.5p1/openbsd-compat/port-aix.c openssh-5.5p1-gssapi/openbsd-compat/port-aix.c
--- openssh-5.5p1/openbsd-compat/port-aix.c	2009-12-20 17:49:22.000000000 -0600
+++ openssh-5.5p1-gssapi/openbsd-compat/port-aix.c	2010-04-20 10:49:30.000000000 -0500
@@ -50,6 +50,7 @@
 # include <login.h>
 # include <userpw.h>
 # if defined(HAVE_SYS_AUDIT_H) && defined(AIX_LOGINFAILED_4ARG)
+#  undef T_NULL
 #  include <sys/audit.h>
 # endif
 # include <usersec.h>
diff -Naur --exclude=autom4te.cache openssh-5.5p1/packet.c openssh-5.5p1-gssapi/packet.c
--- openssh-5.5p1/packet.c	2009-10-01 20:49:04.000000000 -0500
+++ openssh-5.5p1-gssapi/packet.c	2010-04-20 10:49:30.000000000 -0500
@@ -835,7 +835,7 @@
 /*
  * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
  */
-static void
+static int
 packet_send2_wrapped(void)
 {
 	u_char type, *cp, *macbuf = NULL;
@@ -954,11 +954,13 @@
 		set_newkeys(MODE_OUT);
 	else if (type == SSH2_MSG_USERAUTH_SUCCESS && active_state->server_side)
 		packet_enable_delayed_compress();
+	return(packet_length);
 }
 
-static void
+static int
 packet_send2(void)
 {
+	static int packet_length = 0;
 	struct packet *p;
 	u_char type, *cp;
 
@@ -976,7 +978,7 @@
 			    sizeof(Buffer));
 			buffer_init(&active_state->outgoing_packet);
 			TAILQ_INSERT_TAIL(&active_state->outgoing, p, next);
-			return;
+			return(sizeof(Buffer));
 		}
 	}
 
@@ -984,7 +986,7 @@
 	if (type == SSH2_MSG_KEXINIT)
 		active_state->rekeying = 1;
 
-	packet_send2_wrapped();
+	packet_length = packet_send2_wrapped();
 
 	/* after a NEWKEYS message we can send the complete queue */
 	if (type == SSH2_MSG_NEWKEYS) {
@@ -997,19 +999,22 @@
 			    sizeof(Buffer));
 			TAILQ_REMOVE(&active_state->outgoing, p, next);
 			xfree(p);
-			packet_send2_wrapped();
+			packet_length += packet_send2_wrapped();
 		}
 	}
+	return(packet_length);
 }
 
-void
+int
 packet_send(void)
 {
+  int packet_len = 0;
 	if (compat20)
-		packet_send2();
+		packet_len = packet_send2();
 	else
 		packet_send1();
 	DBG(debug("packet_send done"));
+	return(packet_len);
 }
 
 /*
@@ -1633,12 +1638,14 @@
 
 /* Checks if there is any buffered output, and tries to write some of the output. */
 
-void
+int
 packet_write_poll(void)
 {
-	int len = buffer_len(&active_state->output);
+	int len = 0;
 	int cont;
 
+	len = buffer_len(&active_state->output);
+
 	if (len > 0) {
 		cont = 0;
 		len = roaming_write(active_state->connection_out,
@@ -1646,13 +1653,14 @@
 		if (len == -1) {
 			if (errno == EINTR || errno == EAGAIN ||
 			    errno == EWOULDBLOCK)
-				return;
+				return (0);
 			fatal("Write failed: %.100s", strerror(errno));
 		}
 		if (len == 0 && !cont)
 			fatal("Write connection closed");
 		buffer_consume(&active_state->output, len);
 	}
+	return(len);
 }
 
 /*
@@ -1660,16 +1668,17 @@
  * written.
  */
 
-void
+int
 packet_write_wait(void)
 {
 	fd_set *setp;
 	int ret, ms_remain;
 	struct timeval start, timeout, *timeoutp = NULL;
+	u_int bytes_sent = 0;
 
 	setp = (fd_set *)xcalloc(howmany(active_state->connection_out + 1,
 	    NFDBITS), sizeof(fd_mask));
-	packet_write_poll();
+	bytes_sent += packet_write_poll();
 	while (packet_have_data_to_write()) {
 		memset(setp, 0, howmany(active_state->connection_out + 1,
 		    NFDBITS) * sizeof(fd_mask));
@@ -1703,9 +1712,10 @@
 			    "waiting to write", get_remote_ipaddr());
 			cleanup_exit(255);
 		}
-		packet_write_poll();
+		bytes_sent += packet_write_poll();
 	}
 	xfree(setp);
+	return (bytes_sent);
 }
 
 /* Returns true if there is buffered data to write to the connection. */
@@ -1840,12 +1850,24 @@
 	}
 }
 
+int rekey_requested = 0;
+void
+packet_request_rekeying(void)
+{
+	rekey_requested = 1;
+}
+
 #define MAX_PACKETS	(1U<<31)
 int
 packet_need_rekeying(void)
 {
 	if (datafellows & SSH_BUG_NOREKEY)
 		return 0;
+	if (rekey_requested == 1)
+	{
+		rekey_requested = 0;
+		return 1;
+	}
 	return
 	    (active_state->p_send.packets > MAX_PACKETS) ||
 	    (active_state->p_read.packets > MAX_PACKETS) ||
@@ -1937,3 +1959,9 @@
 		add_recv_bytes(len);
 	}
 }
+
+int
+packet_authentication_state(void)
+{
+	return(active_state->after_authentication);
+}
diff -Naur --exclude=autom4te.cache openssh-5.5p1/packet.h openssh-5.5p1-gssapi/packet.h
--- openssh-5.5p1/packet.h	2009-07-05 16:11:13.000000000 -0500
+++ openssh-5.5p1-gssapi/packet.h	2010-04-20 10:49:30.000000000 -0500
@@ -20,6 +20,9 @@
 
 #include <openssl/bn.h>
 
+void
+packet_request_rekeying(void);
+
 void     packet_set_connection(int, int);
 void     packet_set_timeout(int, int);
 void     packet_set_nonblocking(void);
@@ -35,6 +38,7 @@
 int      packet_is_interactive(void);
 void     packet_set_server(void);
 void     packet_set_authenticated(void);
+int	 packet_authentication_state(void);
 
 void     packet_start(u_char);
 void     packet_put_char(int ch);
@@ -45,7 +49,7 @@
 void     packet_put_string(const void *buf, u_int len);
 void     packet_put_cstring(const char *str);
 void     packet_put_raw(const void *buf, u_int len);
-void     packet_send(void);
+int      packet_send(void);
 
 int      packet_read(void);
 void     packet_read_expect(int type);
@@ -76,8 +80,8 @@
 void	 packet_set_iv(int, u_char *);
 void	*packet_get_newkeys(int);
 
-void     packet_write_poll(void);
-void     packet_write_wait(void);
+int      packet_write_poll(void);
+int      packet_write_wait(void);
 int      packet_have_data_to_write(void);
 int      packet_not_very_much_data_to_write(void);
 
diff -Naur --exclude=autom4te.cache openssh-5.5p1/progressmeter.c openssh-5.5p1-gssapi/progressmeter.c
--- openssh-5.5p1/progressmeter.c	2006-08-04 21:39:40.000000000 -0500
+++ openssh-5.5p1-gssapi/progressmeter.c	2010-04-20 10:49:30.000000000 -0500
@@ -68,6 +68,8 @@
 static char *file;		/* name of the file being transferred */
 static off_t end_pos;		/* ending position of transfer */
 static off_t cur_pos;		/* transfer position as of last refresh */
+static off_t last_pos;
+static off_t max_delta_pos = 0;
 static volatile off_t *counter;	/* progress counter */
 static long stalled;		/* how long we have been stalled */
 static int bytes_per_second;	/* current speed in bytes per second */
@@ -128,12 +130,17 @@
 	int hours, minutes, seconds;
 	int i, len;
 	int file_len;
+	off_t delta_pos;
 
 	transferred = *counter - cur_pos;
 	cur_pos = *counter;
 	now = time(NULL);
 	bytes_left = end_pos - cur_pos;
 
+	delta_pos = cur_pos - last_pos;
+	if (delta_pos > max_delta_pos) 
+		max_delta_pos = delta_pos;
+
 	if (bytes_left > 0)
 		elapsed = now - last_update;
 	else {
@@ -158,7 +165,7 @@
 
 	/* filename */
 	buf[0] = '\0';
-	file_len = win_size - 35;
+	file_len = win_size - 45;
 	if (file_len > 0) {
 		len = snprintf(buf, file_len + 1, "\r%s", file);
 		if (len < 0)
@@ -175,7 +182,8 @@
 		percent = ((float)cur_pos / end_pos) * 100;
 	else
 		percent = 100;
-	snprintf(buf + strlen(buf), win_size - strlen(buf),
+
+	snprintf(buf + strlen(buf), win_size - strlen(buf-8),
 	    " %3d%% ", percent);
 
 	/* amount transferred */
@@ -188,6 +196,15 @@
 	    (off_t)bytes_per_second);
 	strlcat(buf, "/s ", win_size);
 
+	/* instantaneous rate */
+	if (bytes_left > 0)
+		format_rate(buf + strlen(buf), win_size - strlen(buf),
+			    delta_pos);
+	else
+		format_rate(buf + strlen(buf), win_size - strlen(buf),
+			    max_delta_pos);
+	strlcat(buf, "/s ", win_size);
+
 	/* ETA */
 	if (!transferred)
 		stalled += elapsed;
@@ -224,6 +241,7 @@
 
 	atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1);
 	last_update = now;
+	last_pos = cur_pos;
 }
 
 /*ARGSUSED*/
diff -Naur --exclude=autom4te.cache openssh-5.5p1/readconf.c openssh-5.5p1-gssapi/readconf.c
--- openssh-5.5p1/readconf.c	2010-02-11 16:21:03.000000000 -0600
+++ openssh-5.5p1-gssapi/readconf.c	2010-04-20 10:49:30.000000000 -0500
@@ -127,10 +127,13 @@
 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+	oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
 	oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
 	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
 	oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
+	oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
+	oHPNBufferSize,
 	oDeprecated, oUnsupported
 } OpCodes;
 
@@ -164,10 +167,18 @@
 	{ "afstokenpassing", oUnsupported },
 #if defined(GSSAPI)
 	{ "gssapiauthentication", oGssAuthentication },
+	{ "gssapikeyexchange", oGssKeyEx },
 	{ "gssapidelegatecredentials", oGssDelegateCreds },
+	{ "gssapitrustdns", oGssTrustDns },
+	{ "gssapiclientidentity", oGssClientIdentity },
+	{ "gssapirenewalforcesrekey", oGssRenewalRekey },
 #else
 	{ "gssapiauthentication", oUnsupported },
+	{ "gssapikeyexchange", oUnsupported },
 	{ "gssapidelegatecredentials", oUnsupported },
+	{ "gssapitrustdns", oUnsupported },
+	{ "gssapiclientidentity", oUnsupported },
+	{ "gssapirenewalforcesrekey", oUnsupported },
 #endif
 	{ "fallbacktorsh", oDeprecated },
 	{ "usersh", oDeprecated },
@@ -237,7 +248,12 @@
 #else
 	{ "zeroknowledgepasswordauthentication", oUnsupported },
 #endif
-
+	{ "noneenabled", oNoneEnabled },
+	{ "tcprcvbufpoll", oTcpRcvBufPoll },
+	{ "tcprcvbuf", oTcpRcvBuf },
+	{ "noneswitch", oNoneSwitch },
+	{ "hpndisabled", oHPNDisabled },
+	{ "hpnbuffersize", oHPNBufferSize },
 	{ NULL, oBadOption }
 };
 
@@ -456,10 +472,26 @@
 		intptr = &options->gss_authentication;
 		goto parse_flag;
 
+	case oGssKeyEx:
+		intptr = &options->gss_keyex;
+		goto parse_flag;
+
 	case oGssDelegateCreds:
 		intptr = &options->gss_deleg_creds;
 		goto parse_flag;
 
+	case oGssTrustDns:
+		intptr = &options->gss_trust_dns;
+		goto parse_flag;
+
+	case oGssClientIdentity:
+		charptr = &options->gss_client_identity;
+		goto parse_string;
+
+	case oGssRenewalRekey:
+		intptr = &options->gss_renewal_rekey;
+		goto parse_flag;
+
 	case oBatchMode:
 		intptr = &options->batch_mode;
 		goto parse_flag;
@@ -468,6 +500,37 @@
 		intptr = &options->check_host_ip;
 		goto parse_flag;
 
+	case oNoneEnabled:
+		intptr = &options->none_enabled;
+		goto parse_flag;
+ 
+	/* we check to see if the command comes from the */
+	/* command line or not. If it does then enable it */
+	/* otherwise fail. NONE should never be a default configuration */
+	case oNoneSwitch:
+		if(strcmp(filename,"command-line")==0)
+		{		
+		    intptr = &options->none_switch;
+		    goto parse_flag;
+		} else {
+		    error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename);
+		    error("Continuing...");
+		    debug("NoneSwitch directive found in %.200s.", filename);
+		    return 0;
+	        }
+
+	case oHPNDisabled:
+		intptr = &options->hpn_disabled;
+		goto parse_flag;
+
+	case oHPNBufferSize:
+		intptr = &options->hpn_buffer_size;
+		goto parse_int;
+
+	case oTcpRcvBufPoll:
+		intptr = &options->tcp_rcv_buf_poll;
+		goto parse_flag;
+
 	case oVerifyHostKeyDNS:
 		intptr = &options->verify_host_key_dns;
 		goto parse_yesnoask;
@@ -646,6 +709,10 @@
 		intptr = &options->connection_attempts;
 		goto parse_int;
 
+	case oTcpRcvBuf:
+		intptr = &options->tcp_rcv_buf;
+		goto parse_int;
+
 	case oCipher:
 		intptr = &options->cipher;
 		arg = strdelim(&s);
@@ -1015,7 +1082,11 @@
 	options->pubkey_authentication = -1;
 	options->challenge_response_authentication = -1;
 	options->gss_authentication = -1;
+	options->gss_keyex = -1;
 	options->gss_deleg_creds = -1;
+	options->gss_trust_dns = -1;
+	options->gss_renewal_rekey = -1;
+	options->gss_client_identity = NULL;
 	options->password_authentication = -1;
 	options->kbd_interactive_authentication = -1;
 	options->kbd_interactive_devices = NULL;
@@ -1073,6 +1144,12 @@
 	options->use_roaming = -1;
 	options->visual_host_key = -1;
 	options->zero_knowledge_password_authentication = -1;
+	options->none_switch = -1;
+	options->none_enabled = -1;
+	options->hpn_disabled = -1;
+	options->hpn_buffer_size = -1;
+	options->tcp_rcv_buf_poll = -1;
+	options->tcp_rcv_buf = -1;
 }
 
 /*
@@ -1106,9 +1183,15 @@
 	if (options->challenge_response_authentication == -1)
 		options->challenge_response_authentication = 1;
 	if (options->gss_authentication == -1)
-		options->gss_authentication = 0;
+		options->gss_authentication = 1;
+	if (options->gss_keyex == -1)
+		options->gss_keyex = 1;
 	if (options->gss_deleg_creds == -1)
-		options->gss_deleg_creds = 0;
+		options->gss_deleg_creds = 1;
+	if (options->gss_trust_dns == -1)
+		options->gss_trust_dns = 1;
+	if (options->gss_renewal_rekey == -1)
+		options->gss_renewal_rekey = 0;
 	if (options->password_authentication == -1)
 		options->password_authentication = 1;
 	if (options->kbd_interactive_authentication == -1)
@@ -1195,6 +1278,29 @@
 		options->server_alive_interval = 0;
 	if (options->server_alive_count_max == -1)
 		options->server_alive_count_max = 3;
+	if (options->none_switch == -1)
+	        options->none_switch = 0;
+	if (options->hpn_disabled == -1)
+	        options->hpn_disabled = 0;
+	if (options->hpn_buffer_size > -1)
+	{
+	  /* if a user tries to set the size to 0 set it to 1KB */
+		if (options->hpn_buffer_size == 0)
+		options->hpn_buffer_size = 1024;
+		/*limit the buffer to 64MB*/
+		if (options->hpn_buffer_size > 65536)
+		{
+			options->hpn_buffer_size = 65536*1024;
+			debug("User requested buffer larger than 64MB. Request reverted to 64MB");
+		}
+		debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
+	}
+	if (options->tcp_rcv_buf == 0)
+		options->tcp_rcv_buf = 1;
+	if (options->tcp_rcv_buf > -1) 
+		options->tcp_rcv_buf *=1024;
+	if (options->tcp_rcv_buf_poll == -1)
+		options->tcp_rcv_buf_poll = 1;
 	if (options->control_master == -1)
 		options->control_master = 0;
 	if (options->hash_known_hosts == -1)
diff -Naur --exclude=autom4te.cache openssh-5.5p1/readconf.h openssh-5.5p1-gssapi/readconf.h
--- openssh-5.5p1/readconf.h	2010-02-11 16:21:03.000000000 -0600
+++ openssh-5.5p1-gssapi/readconf.h	2010-04-20 10:49:30.000000000 -0500
@@ -44,7 +44,11 @@
 	int     challenge_response_authentication;
 					/* Try S/Key or TIS, authentication. */
 	int     gss_authentication;	/* Try GSS authentication */
+	int     gss_keyex;		/* Try GSS key exchange */
 	int     gss_deleg_creds;	/* Delegate GSS credentials */
+	int	gss_trust_dns;		/* Trust DNS for GSS canonicalization */
+	int	gss_renewal_rekey;	/* Credential renewal forces rekey */
+	char    *gss_client_identity;   /* Principal to initiate GSSAPI with */
 	int     password_authentication;	/* Try password
 						 * authentication. */
 	int     kbd_interactive_authentication; /* Try keyboard-interactive auth. */
@@ -57,6 +61,11 @@
 	int     compression_level;	/* Compression level 1 (fast) to 9
 					 * (best). */
 	int     tcp_keep_alive;	/* Set SO_KEEPALIVE. */
+        int     tcp_rcv_buf; /* user switch to set tcp recv buffer */
+	int	tcp_rcv_buf_poll; /* Option to poll recv buf every window transfer */
+	int 	hpn_disabled; 	 /* Switch to disable HPN buffer management */
+	int	hpn_buffer_size; /* User definable size for HPN buffer window */
+
 	LogLevel log_level;	/* Level for logging. */
 
 	int     port;		/* Port to connect. */
@@ -76,6 +85,8 @@
 	char   *host_key_alias;	/* hostname alias for .ssh/known_hosts */
 	char   *proxy_command;	/* Proxy command for connecting the host. */
 	char   *user;		/* User to log in as. */
+	int    implicit;	/* Login user was not specified.
+				   Server may choose based on authctxt. */
 	int     escape_char;	/* Escape character; -2 = none */
 
 	char   *system_hostfile;/* Path for /etc/ssh/ssh_known_hosts. */
@@ -102,6 +113,8 @@
 
 	int	enable_ssh_keysign;
 	int64_t rekey_limit;
+	int     none_switch;    /* Use none cipher */
+	int     none_enabled;   /* Allow none to be used */
 	int	no_host_authentication_for_localhost;
 	int	identities_only;
 	int	server_alive_interval;
diff -Naur --exclude=autom4te.cache openssh-5.5p1/scp.c openssh-5.5p1-gssapi/scp.c
--- openssh-5.5p1/scp.c	2010-01-08 01:53:43.000000000 -0600
+++ openssh-5.5p1-gssapi/scp.c	2010-04-20 10:49:30.000000000 -0500
@@ -639,7 +639,7 @@
 	off_t i, statbytes;
 	size_t amt;
 	int fd = -1, haderr, indx;
-	char *last, *name, buf[2048], encname[MAXPATHLEN];
+	char *last, *name, buf[16384], encname[MAXPATHLEN];
 	int len;
 
 	for (indx = 0; indx < argc; ++indx) {
@@ -875,7 +875,7 @@
 	mode_t mode, omode, mask;
 	off_t size, statbytes;
 	int setimes, targisdir, wrerrno = 0;
-	char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
+	char ch, *cp, *np, *targ, *why, *vect[1], buf[16384];
 	struct timeval tv[2];
 
 #define	atime	tv[0]
diff -Naur --exclude=autom4te.cache openssh-5.5p1/servconf.c openssh-5.5p1-gssapi/servconf.c
--- openssh-5.5p1/servconf.c	2010-03-25 18:40:04.000000000 -0500
+++ openssh-5.5p1-gssapi/servconf.c	2010-04-20 10:49:30.000000000 -0500
@@ -58,6 +58,7 @@
 
 	/* Portable-specific options */
 	options->use_pam = -1;
+	options->permit_pam_user_change = -1;
 
 	/* Standard Options */
 	options->num_ports = 0;
@@ -91,9 +92,19 @@
 	options->kerberos_authentication = -1;
 	options->kerberos_or_local_passwd = -1;
 	options->kerberos_ticket_cleanup = -1;
+#ifdef  SESSION_HOOKS
+        options->session_hooks_allow = -1;
+        options->session_hooks_startup_cmd = NULL;
+        options->session_hooks_shutdown_cmd = NULL;
+#endif
 	options->kerberos_get_afs_token = -1;
-	options->gss_authentication=-1;
+	options->gss_authentication = -1;
+	options->gss_deleg_creds = -1;
+	options->gss_keyex = -1;
 	options->gss_cleanup_creds = -1;
+	options->gss_strict_acceptor = -1;
+	options->gsi_allow_limited_proxy = -1;
+	options->gss_store_rekey = -1;
 	options->password_authentication = -1;
 	options->kbd_interactive_authentication = -1;
 	options->challenge_response_authentication = -1;
@@ -129,6 +140,12 @@
 	options->adm_forced_command = NULL;
 	options->chroot_directory = NULL;
 	options->zero_knowledge_password_authentication = -1;
+	options->none_enabled = -1;
+	options->tcp_rcv_buf_poll = -1;
+	options->hpn_disabled = -1;
+	options->hpn_buffer_size = -1;
+	options->disable_usage_stats = 0;
+	options->usage_stats_targets = NULL;
 	options->revoked_keys_file = NULL;
 	options->trusted_user_ca_keys = NULL;
 }
@@ -136,9 +153,16 @@
 void
 fill_default_server_options(ServerOptions *options)
 {
+	/* needed for hpn socket tests */
+	int sock;
+	int socksize;
+	int socksizelen = sizeof(int);
+
 	/* Portable-specific options */
 	if (options->use_pam == -1)
 		options->use_pam = 0;
+	if (options->permit_pam_user_change == -1)
+		options->permit_pam_user_change = 0;
 
 	/* Standard Options */
 	if (options->protocol == SSH_PROTO_UNKNOWN)
@@ -210,12 +234,26 @@
 		options->kerberos_or_local_passwd = 1;
 	if (options->kerberos_ticket_cleanup == -1)
 		options->kerberos_ticket_cleanup = 1;
+#ifdef  SESSION_HOOKS
+    if (options->session_hooks_allow == -1)
+        options->session_hooks_allow = 0;
+#endif
 	if (options->kerberos_get_afs_token == -1)
 		options->kerberos_get_afs_token = 0;
 	if (options->gss_authentication == -1)
-		options->gss_authentication = 0;
+		options->gss_authentication = 1;
+	if (options->gss_deleg_creds == -1)
+		options->gss_deleg_creds = 1;
+	if (options->gss_keyex == -1)
+		options->gss_keyex = 1;
 	if (options->gss_cleanup_creds == -1)
 		options->gss_cleanup_creds = 1;
+	if (options->gss_strict_acceptor == -1)
+		options->gss_strict_acceptor = 1;
+	if (options->gsi_allow_limited_proxy == -1)
+		options->gsi_allow_limited_proxy = 0;
+	if (options->gss_store_rekey == -1)
+		options->gss_store_rekey = 0;
 	if (options->password_authentication == -1)
 		options->password_authentication = 1;
 	if (options->kbd_interactive_authentication == -1)
@@ -266,6 +304,42 @@
 	if (options->zero_knowledge_password_authentication == -1)
 		options->zero_knowledge_password_authentication = 0;
 
+	if (options->hpn_disabled == -1) 
+		options->hpn_disabled = 0;
+
+	if (options->hpn_buffer_size == -1) {
+		/* option not explicitly set. Now we have to figure out */
+		/* what value to use */
+		if (options->hpn_disabled == 1) {
+			options->hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT;
+		} else {
+			/* get the current RCV size and set it to that */
+			/*create a socket but don't connect it */
+			/* we use that the get the rcv socket size */
+			sock = socket(AF_INET, SOCK_STREAM, 0);
+			getsockopt(sock, SOL_SOCKET, SO_RCVBUF, 
+				   &socksize, &socksizelen);
+			close(sock);
+			options->hpn_buffer_size = socksize;
+			debug ("HPN Buffer Size: %d", options->hpn_buffer_size);
+			
+		} 
+	} else {
+		/* we have to do this incase the user sets both values in a contradictory */
+		/* manner. hpn_disabled overrrides hpn_buffer_size*/
+		if (options->hpn_disabled <= 0) {
+			if (options->hpn_buffer_size == 0)
+				options->hpn_buffer_size = 1;
+			/* limit the maximum buffer to 64MB */
+			if (options->hpn_buffer_size > 64*1024) {
+				options->hpn_buffer_size = 64*1024*1024;
+			} else {
+				options->hpn_buffer_size *= 1024;
+			}
+		} else
+			options->hpn_buffer_size = CHAN_TCP_WINDOW_DEFAULT;
+	}
+
 	/* Turn privilege separation on by default */
 	if (use_privsep == -1)
 		use_privsep = 1;
@@ -278,14 +352,13 @@
 		options->compression = 0;
 	}
 #endif
-
 }
 
 /* Keyword tokens. */
 typedef enum {
 	sBadOption,		/* == unknown option */
 	/* Portable-specific options */
-	sUsePAM,
+	sUsePAM, sPermitPAMUserChange,
 	/* Standard Options */
 	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
 	sPermitRootLogin, sLogFacility, sLogLevel,
@@ -293,6 +366,9 @@
 	sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
 	sKerberosGetAFSToken,
 	sKerberosTgtPassing, sChallengeResponseAuthentication,
+#ifdef SESSION_HOOKS
+        sAllowSessionHooks, sSessionHookStartupCmd, sSessionHookShutdownCmd,
+#endif
 	sPasswordAuthentication, sKbdInteractiveAuthentication,
 	sListenAddress, sAddressFamily,
 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
@@ -306,9 +382,16 @@
 	sBanner, sUseDNS, sHostbasedAuthentication,
 	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
 	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
-	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
+    sGssDelegateCreds,
+    sGssCredsPath,
+	sGsiAllowLimitedProxy,
+	sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
+	sGssKeyEx, sGssStoreRekey,
+	sAcceptEnv, sPermitTunnel,
 	sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
 	sUsePrivilegeSeparation, sAllowAgentForwarding,
+	sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize,
+	sDisUsageStats, sUsageStatsTarg,
 	sZeroKnowledgePasswordAuthentication, sHostCertificate,
 	sRevokedKeys, sTrustedUserCAKeys,
 	sDeprecated, sUnsupported
@@ -327,8 +410,10 @@
 	/* Portable-specific options */
 #ifdef USE_PAM
 	{ "usepam", sUsePAM, SSHCFG_GLOBAL },
+	{ "permitpamuserchange", sPermitPAMUserChange, SSHCFG_GLOBAL },
 #else
 	{ "usepam", sUnsupported, SSHCFG_GLOBAL },
+	{ "permitpamuserchange", sUnsupported, SSHCFG_GLOBAL },
 #endif
 	{ "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
 	/* Standard Options */
@@ -368,11 +453,32 @@
 	{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
 #ifdef GSSAPI
 	{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
+	{ "gssapidelegatecredentials", sGssDelegateCreds, SSHCFG_ALL },
 	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
+	{ "gssapicredentialspath", sGssCredsPath, SSHCFG_GLOBAL },
+#ifdef GSI
+	{ "gsiallowlimitedproxy", sGsiAllowLimitedProxy, SSHCFG_GLOBAL },
+#endif
+	{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
+	{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
+	{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
 #else
 	{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
+	{ "gssapidelegatecredentials", sUnsupported, SSHCFG_ALL },
 	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
+	{ "gssapicredentialspath", sUnsupported, SSHCFG_GLOBAL },
+#ifdef GSI
+	{ "gsiallowlimitedproxy", sUnsupported, SSHCFG_GLOBAL },
+#endif
+	{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
+	{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
+	{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
 #endif
+#ifdef SESSION_HOOKS
+    { "allowsessionhooks", sAllowSessionHooks, SSHCFG_GLOBAL },
+    { "sessionhookstartupcmd", sSessionHookStartupCmd, SSHCFG_GLOBAL },
+    { "sessionhookshutdowncmd", sSessionHookShutdownCmd, SSHCFG_GLOBAL },
+#endif        
 	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
 	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
 	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
@@ -429,6 +535,12 @@
 	{ "permitopen", sPermitOpen, SSHCFG_ALL },
 	{ "forcecommand", sForceCommand, SSHCFG_ALL },
 	{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
+	{ "noneenabled", sNoneEnabled },
+	{ "hpndisabled", sHPNDisabled },
+	{ "hpnbuffersize", sHPNBufferSize },
+	{ "tcprcvbufpoll", sTcpRcvBufPoll },
+	{ "disableusagestats", sDisUsageStats, SSHCFG_GLOBAL},
+	{ "usagestatstargets", sUsageStatsTarg, SSHCFG_GLOBAL},
 	{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
 	{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
 	{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
@@ -458,6 +570,7 @@
 
 	for (i = 0; keywords[i].name; i++)
 		if (strcasecmp(cp, keywords[i].name) == 0) {
+		        debug ("Config token is %s", keywords[i].name);
 			*flags = keywords[i].flags;
 			return keywords[i].opcode;
 		}
@@ -704,6 +817,10 @@
 		intptr = &options->use_pam;
 		goto parse_flag;
 
+	case sPermitPAMUserChange:
+		intptr = &options->permit_pam_user_change;
+		goto parse_flag;
+
 	/* Standard Options */
 	case sBadOption:
 		return -1;
@@ -880,6 +997,22 @@
 			*intptr = value;
 		break;
 
+	case sNoneEnabled:
+		intptr = &options->none_enabled;
+		goto parse_flag;
+
+	case sTcpRcvBufPoll:
+		intptr = &options->tcp_rcv_buf_poll;
+		goto parse_flag;
+
+	case sHPNDisabled:
+		intptr = &options->hpn_disabled;
+		goto parse_flag;
+
+	case sHPNBufferSize:
+		intptr = &options->hpn_buffer_size;
+		goto parse_int;
+
 	case sIgnoreUserKnownHosts:
 		intptr = &options->ignore_user_known_hosts;
 		goto parse_flag;
@@ -924,10 +1057,53 @@
 		intptr = &options->gss_authentication;
 		goto parse_flag;
 
+	case sGssDelegateCreds:
+		intptr = &options->gss_deleg_creds;
+		goto parse_flag;
+
+	case sGssKeyEx:
+		intptr = &options->gss_keyex;
+		goto parse_flag;
+
 	case sGssCleanupCreds:
 		intptr = &options->gss_cleanup_creds;
 		goto parse_flag;
 
+	case sGssCredsPath:
+		charptr = &options->gss_creds_path;
+		goto parse_filename;
+
+	case sGssStrictAcceptor:
+		intptr = &options->gss_strict_acceptor;
+		goto parse_flag;
+
+	case sGssStoreRekey:
+		intptr = &options->gss_store_rekey;
+		goto parse_flag;
+
+#ifdef GSI
+	case sGsiAllowLimitedProxy:
+		intptr = &options->gsi_allow_limited_proxy;
+		goto parse_flag;
+#endif
+
+#ifdef SESSION_HOOKS
+        case sAllowSessionHooks:
+                intptr = &options->session_hooks_allow;
+                goto parse_flag;
+        case sSessionHookStartupCmd:
+        case sSessionHookShutdownCmd:
+                arg = strdelim(&cp);
+                if (!arg || *arg == '\0')
+                    fatal("%s line %d: empty session hook command",
+                          filename, linenum);
+                if (opcode==sSessionHookStartupCmd)
+                    options->session_hooks_startup_cmd = strdup(arg);
+                else
+                    options->session_hooks_shutdown_cmd = strdup(arg);
+                break;
+#endif                  
+
 	case sPasswordAuthentication:
 		intptr = &options->password_authentication;
 		goto parse_flag;
@@ -1337,6 +1513,39 @@
 			*charptr = xstrdup(arg);
 		break;
 
+	case sDisUsageStats:
+		charptr = &options->chroot_directory;
+
+		arg = strdelim(&cp);
+		if (!arg || *arg == '\0')
+			fatal("%s line %d: missing value.",
+			    filename, linenum);
+		if (!strcasecmp(arg, "true") ||
+		    !strcasecmp(arg, "enabled") ||
+		    !strcasecmp(arg, "yes") ||
+		    !strcasecmp(arg, "on") ||
+		    !strcasecmp(arg, "1"))
+			options->disable_usage_stats = 1;
+		else if (!strcasecmp(arg, "false") ||
+			 !strcasecmp(arg, "disabled") ||
+			 !strcasecmp(arg, "no") ||
+			 !strcasecmp(arg, "off") ||
+			 !strcasecmp(arg, "0"))
+			options->disable_usage_stats = 0;
+		else
+			fatal("Incorrect value for disable_usage_stats");
+		break;
+
+	case sUsageStatsTarg:
+		charptr = &options->chroot_directory;
+
+		arg = strdelim(&cp);
+		if (!arg || *arg == '\0')
+			fatal("%s line %d: missing value.",
+			    filename, linenum);
+		options->usage_stats_targets = xstrdup(arg);
+		break;
+
 	case sTrustedUserCAKeys:
 		charptr = &options->trusted_user_ca_keys;
 		goto parse_filename;
@@ -1436,6 +1645,7 @@
 {
 	M_CP_INTOPT(password_authentication);
 	M_CP_INTOPT(gss_authentication);
+	M_CP_INTOPT(gss_deleg_creds);
 	M_CP_INTOPT(rsa_authentication);
 	M_CP_INTOPT(pubkey_authentication);
 	M_CP_INTOPT(kerberos_authentication);
diff -Naur --exclude=autom4te.cache openssh-5.5p1/servconf.h openssh-5.5p1-gssapi/servconf.h
--- openssh-5.5p1/servconf.h	2010-03-04 04:53:35.000000000 -0600
+++ openssh-5.5p1-gssapi/servconf.h	2010-04-20 10:49:30.000000000 -0500
@@ -91,10 +91,21 @@
 						 * /etc/passwd */
 	int     kerberos_ticket_cleanup;	/* If true, destroy ticket
 						 * file on logout. */
+#ifdef SESSION_HOOKS
+        int     session_hooks_allow;        /* If true, permit user hooks */
+        char*   session_hooks_startup_cmd;  /* cmd to be executed before */
+        char*   session_hooks_shutdown_cmd; /* cmd to be executed after */
+#endif
 	int     kerberos_get_afs_token;		/* If true, try to get AFS token if
 						 * authenticated with Kerberos. */
+	int     gsi_allow_limited_proxy;	/* If true, accept limited proxies */
 	int     gss_authentication;	/* If true, permit GSSAPI authentication */
+	int     gss_deleg_creds;	/* If true, store delegated GSSAPI credentials*/
+	int     gss_keyex;		/* If true, permit GSSAPI key exchange */
 	int     gss_cleanup_creds;	/* If true, destroy cred cache on logout */
+	char*   gss_creds_path;	/* If true, destroy cred cache on logout */
+	int 	gss_strict_acceptor;	/* If true, restrict the GSSAPI acceptor name */
+	int 	gss_store_rekey;
 	int     password_authentication;	/* If true, permit password
 						 * authentication. */
 	int     kbd_interactive_authentication;	/* If true, permit */
@@ -148,12 +159,21 @@
 	char   *adm_forced_command;
 
 	int	use_pam;		/* Enable auth via PAM */
+ 	int	permit_pam_user_change;	/* Allow PAM to change user name */
+        int     none_enabled;           /* enable NONE cipher switch */
+        int     tcp_rcv_buf_poll;       /* poll tcp rcv window in autotuning kernels*/
+	int	hpn_disabled;		/* disable hpn functionality. false by default */
+	int	hpn_buffer_size;	/* set the hpn buffer size - default 3MB */
 
 	int	permit_tun;
 
 	int	num_permitted_opens;
 
 	char   *chroot_directory;
+
+	int    disable_usage_stats;
+	char   *usage_stats_targets;
+
 	char   *revoked_keys_file;
 	char   *trusted_user_ca_keys;
 }       ServerOptions;
diff -Naur --exclude=autom4te.cache openssh-5.5p1/serverloop.c openssh-5.5p1-gssapi/serverloop.c
--- openssh-5.5p1/serverloop.c	2009-09-08 20:07:28.000000000 -0500
+++ openssh-5.5p1-gssapi/serverloop.c	2010-04-20 10:49:30.000000000 -0500
@@ -94,10 +94,10 @@
 static int fdout;		/* Descriptor for stdout (for reading);
 				   May be same number as fdin. */
 static int fderr;		/* Descriptor for stderr.  May be -1. */
-static long stdin_bytes = 0;	/* Number of bytes written to stdin. */
-static long stdout_bytes = 0;	/* Number of stdout bytes sent to client. */
-static long stderr_bytes = 0;	/* Number of stderr bytes sent to client. */
-static long fdout_bytes = 0;	/* Number of stdout bytes read from program. */
+static u_long stdin_bytes = 0;	/* Number of bytes written to stdin. */
+static u_long stdout_bytes = 0;	/* Number of stdout bytes sent to client. */
+static u_long stderr_bytes = 0;	/* Number of stderr bytes sent to client. */
+static u_long fdout_bytes = 0;	/* Number of stdout bytes read from program. */
 static int stdin_eof = 0;	/* EOF message received from client. */
 static int fdout_eof = 0;	/* EOF encountered reading from fdout. */
 static int fderr_eof = 0;	/* EOF encountered readung from fderr. */
@@ -122,6 +122,20 @@
 static void server_init_dispatch(void);
 
 /*
+ * Returns current time in seconds from Jan 1, 1970 with the maximum
+ * available resolution.
+ */
+
+static double
+get_current_time(void)
+{
+	struct timeval tv;
+	gettimeofday(&tv, NULL);
+	return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
+}
+
+
+/*
  * we write to this pipe if a SIGCHLD is caught in order to avoid
  * the race between select() and child_terminated
  */
@@ -414,6 +428,7 @@
 		} else {
 			/* Buffer any received data. */
 			packet_process_incoming(buf, len);
+			fdout_bytes += len;
 		}
 	}
 	if (compat20)
@@ -436,6 +451,7 @@
 		} else {
 			buffer_append(&stdout_buffer, buf, len);
 			fdout_bytes += len;
+			debug ("FD out now: %ld", fdout_bytes);
 		}
 	}
 	/* Read and buffer any available stderr data from the program. */
@@ -503,7 +519,7 @@
 	}
 	/* Send any buffered packet data to the client. */
 	if (FD_ISSET(connection_out, writeset))
-		packet_write_poll();
+		stdin_bytes += packet_write_poll();
 }
 
 /*
@@ -820,8 +836,10 @@
 {
 	fd_set *readset = NULL, *writeset = NULL;
 	int rekeying = 0, max_fd, nalloc = 0;
+	double start_time, total_time;
 
 	debug("Entering interactive session for SSH2.");
+	start_time = get_current_time();
 
 	mysignal(SIGCHLD, sigchld_handler);
 	child_terminated = 0;
@@ -883,6 +901,11 @@
 
 	/* free remaining sessions, e.g. remove wtmp entries */
 	session_destroy_all(NULL);
+	total_time = get_current_time() - start_time;
+	logit("SSH: Server;LType: Throughput;Remote: %s-%d;IN: %lu;OUT: %lu;Duration: %.1f;tPut_in: %.1f;tPut_out: %.1f",
+	      get_remote_ipaddr(), get_remote_port(),
+	      stdin_bytes, fdout_bytes, total_time, stdin_bytes / total_time, 
+	      fdout_bytes / total_time);
 }
 
 static void
@@ -998,8 +1021,12 @@
 	sock = tun_open(tun, mode);
 	if (sock < 0)
 		goto done;
+	if (options.hpn_disabled)
 	c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
 	    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
+	else
+		c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1,
+		    options.hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
 	c->datagram = 1;
 #if defined(SSH_TUN_FILTER)
 	if (mode == SSH_TUNMODE_POINTOPOINT)
@@ -1035,6 +1062,8 @@
 	c = channel_new("session", SSH_CHANNEL_LARVAL,
 	    -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
 	    0, "server-session", 1);
+	if ((options.tcp_rcv_buf_poll) && (!options.hpn_disabled))
+		c->dynamic_window = 1;
 	if (session_open(the_authctxt, c->self) != 1) {
 		debug("session open failed, free channel %d", c->self);
 		channel_free(c);
diff -Naur --exclude=autom4te.cache openssh-5.5p1/session.c openssh-5.5p1-gssapi/session.c
--- openssh-5.5p1/session.c	2010-03-25 19:04:09.000000000 -0500
+++ openssh-5.5p1-gssapi/session.c	2010-04-20 10:49:30.000000000 -0500
@@ -124,6 +124,11 @@
 
 static int session_pty_req(Session *);
 
+#ifdef SESSION_HOOKS
+static void execute_session_hook(char* prog, Authctxt *authctxt,
+                                 int startup, int save);
+#endif
+
 /* import */
 extern ServerOptions options;
 extern char *__progname;
@@ -231,6 +236,7 @@
 	}
 
 	/* Allocate a channel for the authentication agent socket. */
+	/* this shouldn't matter if its hpn or not - cjr */
 	nc = channel_new("auth socket",
 	    SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
 	    CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
@@ -278,6 +284,21 @@
 	else
 		do_authenticated1(authctxt);
 
+#ifdef SESSION_HOOKS
+        if (options.session_hooks_allow &&
+            options.session_hooks_shutdown_cmd)
+        {
+            execute_session_hook(options.session_hooks_shutdown_cmd,
+                                 authctxt,
+                                 /* startup = */ 0, /* save = */ 0);
+
+            if (authctxt->session_env_file)
+            {
+                free(authctxt->session_env_file);
+            }
+        }
+#endif
+
 	do_cleanup(authctxt);
 }
 
@@ -384,7 +405,7 @@
 			}
 			debug("Received TCP/IP port forwarding request.");
 			if (channel_input_port_forward_request(s->pw->pw_uid == 0,
-			    options.gateway_ports) < 0) {
+			      options.gateway_ports) < 0) {
 				debug("Port forwarding failed.");
 				break;
 			}
@@ -805,6 +826,26 @@
 		debug("Forced command (key option) '%.900s'", command);
 	}
 
+#if defined(SESSION_HOOKS)
+	if (options.session_hooks_allow &&
+	    (options.session_hooks_startup_cmd ||
+	     options.session_hooks_shutdown_cmd))
+	{
+		char env_file[1000];
+		struct stat st;
+		do
+		{
+			snprintf(env_file,
+				 sizeof(env_file),
+				 "/tmp/ssh_env_%d%d%d",
+				 getuid(),
+				 getpid(),
+				 rand());
+		} while (stat(env_file, &st)==0);
+		s->authctxt->session_env_file = strdup(env_file);
+	}
+#endif
+
 #ifdef SSH_AUDIT_EVENTS
 	if (command != NULL)
 		PRIVSEP(audit_run_command(command));
@@ -1033,6 +1074,117 @@
 	fclose(f);
 }
 
+#ifdef SESSION_HOOKS
+#define SSH_SESSION_ENV_FILE "SSH_SESSION_ENV_FILE"
+
+typedef enum { no_op, execute, clear_env, restore_env,
+               read_env, save_or_rm_env } session_action_t;
+
+static session_action_t action_order[2][5] = {
+    { clear_env, read_env, execute, save_or_rm_env, restore_env }, /*shutdown*/
+    { execute, read_env, save_or_rm_env, no_op, no_op }            /*startup */
+};
+
+static
+void execute_session_hook(char* prog, Authctxt *authctxt,
+                          int startup, int save)
+{
+    extern char **environ;
+
+    struct stat  st;
+    char         **saved_env, **tmpenv;
+    char         *env_file = authctxt->session_env_file;
+    int          i, status = 0;
+
+    for (i=0; i<5; i++)
+    {
+        switch (action_order[startup][i])
+        {
+          case no_op:
+            break;
+
+          case execute:
+            {
+                FILE* fp;
+                char  buf[1000];
+
+                snprintf(buf,
+                         sizeof(buf),
+                         "%s -c '%s'",
+                         authctxt->pw->pw_shell,
+                         prog);
+
+                debug("executing session hook: [%s]", buf);
+                setenv(SSH_SESSION_ENV_FILE, env_file, /* overwrite = */ 1);
+
+                /* flusing is recommended in the popen(3) man page, to avoid
+                   intermingling of output */
+                fflush(stdout);
+                fflush(stderr);
+                if ((fp=popen(buf, "w")) == NULL)
+                {
+                    perror("Unable to run session hook");
+                    return;
+                }
+                status = pclose(fp);
+                debug2("session hook executed, status=%d", status);
+                unsetenv(SSH_SESSION_ENV_FILE);
+            }
+            break;
+
+          case clear_env:
+            saved_env = environ;
+            tmpenv = (char**) malloc(sizeof(char*));
+            tmpenv[0] = NULL;
+            environ = tmpenv;
+            break;
+
+          case restore_env:
+            environ = saved_env;
+            free(tmpenv);
+            break;
+
+          case read_env:
+            if (status==0 && stat(env_file, &st)==0)
+            {
+                int envsize = 0;
+
+                debug("reading environment from %s", env_file);
+                while (environ[envsize++]) ;
+                read_environment_file(&environ, &envsize, env_file);
+            }
+            break;
+
+          case save_or_rm_env:
+            if (status==0 && save)
+            {
+                FILE* fp;
+                int    envcount=0;
+
+                debug2("saving environment to %s", env_file);
+                if ((fp = fopen(env_file, "w")) == NULL) /* hmm: file perms? */
+                {
+                    perror("Unable to save session hook info");
+                }
+                while (environ[envcount])
+                {
+                    fprintf(fp, "%s\n", environ[envcount++]);
+                }
+                fflush(fp);
+                fclose(fp);
+            }
+            else if (stat(env_file, &st)==0)
+            {
+                debug2("removing environment file %s", env_file);
+                remove(env_file);
+            }
+            break;
+        }
+    }
+
+}
+#endif
+
 #ifdef HAVE_ETC_DEFAULT_LOGIN
 /*
  * Return named variable from specified environment, or NULL if not present.
@@ -1196,6 +1348,23 @@
 	if (getenv("TZ"))
 		child_set_env(&env, &envsize, "TZ", getenv("TZ"));
 
+#ifdef GSI /* GSI shared libs typically installed in non-system locations. */
+	{
+		char *cp;
+
+		if ((cp = getenv("LD_LIBRARY_PATH")) != NULL)
+			child_set_env(&env, &envsize, "LD_LIBRARY_PATH", cp);
+		if ((cp = getenv("LIBPATH")) != NULL)
+			child_set_env(&env, &envsize, "LIBPATH", cp);
+		if ((cp = getenv("SHLIB_PATH")) != NULL)
+			child_set_env(&env, &envsize, "SHLIB_PATH", cp);
+		if ((cp = getenv("LD_LIBRARYN32_PATH")) != NULL)
+			child_set_env(&env, &envsize, "LD_LIBRARYN32_PATH",cp);
+		if ((cp = getenv("LD_LIBRARY64_PATH")) != NULL)
+			child_set_env(&env, &envsize, "LD_LIBRARY64_PATH",cp);
+	}
+#endif
+
 	/* Set custom environment options from RSA authentication. */
 	if (!options.use_login) {
 		while (custom_environment) {
@@ -1674,6 +1843,18 @@
 	struct passwd *pw = s->pw;
 	int r = 0;
 
+#ifdef AFS_KRB5
+/* Default place to look for aklog. */
+#ifdef AKLOG_PATH
+#define KPROGDIR AKLOG_PATH
+#else
+#define KPROGDIR "/usr/bin/aklog"
+#endif /* AKLOG_PATH */
+
+	struct stat st;
+	char *aklog_path;
+#endif /* AFS_KRB5 */
+
 	/* remove hostkey from the child's memory */
 	destroy_sensitive_data();
 
@@ -1786,6 +1967,41 @@
 	}
 #endif
 
+#ifdef AFS_KRB5
+
+	/* User has authenticated, and if a ticket was going to be
+	 * passed we would have it.  KRB5CCNAME should already be set.
+	 * Now try to get an AFS token using aklog.
+	 */
+	if (k_hasafs()) {  /* Do we have AFS? */
+
+		aklog_path = xstrdup(KPROGDIR);
+
+		/*
+		 * Make sure it exists before we try to run it
+		 */
+		if (stat(aklog_path, &st) == 0) {
+			debug("Running %s to get afs token.",aklog_path);
+			system(aklog_path);
+		} else {
+			debug("%s does not exist.",aklog_path);
+		}
+
+		xfree(aklog_path);
+	}
+#endif /* AFS_KRB5 */
+
+#ifdef SESSION_HOOKS
+        if (options.session_hooks_allow &&
+            options.session_hooks_startup_cmd)
+        {
+            execute_session_hook(options.session_hooks_startup_cmd,
+                                 s->authctxt,
+                                 /* startup = */ 1,
+                                 options.session_hooks_shutdown_cmd != NULL);
+        }
+#endif
+
 	/* Change current directory to the user's home directory. */
 	if (chdir(pw->pw_dir) < 0) {
 		/* Suppress missing homedir warning for chroot case */
@@ -1865,7 +2081,7 @@
 		/* Execute the shell. */
 		argv[0] = argv0;
 		argv[1] = NULL;
-		execve(shell, argv, env);
+		execve(shell, argv, environ);
 
 		/* Executing the shell failed. */
 		perror(shell);
@@ -1879,7 +2095,7 @@
 	argv[1] = "-c";
 	argv[2] = (char *) command;
 	argv[3] = NULL;
-	execve(shell, argv, env);
+	execve(shell, argv, environ);
 	perror(shell);
 	exit(1);
 }
@@ -2329,10 +2545,16 @@
 	 */
 	if (s->chanid == -1)
 		fatal("no channel for session %d", s->self);
+	if (options.hpn_disabled)
 	channel_set_fds(s->chanid,
 	    fdout, fdin, fderr,
 	    fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
 	    1, is_tty, CHAN_SES_WINDOW_DEFAULT);
+	else 
+		channel_set_fds(s->chanid,
+		    fdout, fdin, fderr,
+	            fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
+		    1, is_tty, options.hpn_buffer_size);
 }
 
 /*
diff -Naur --exclude=autom4te.cache openssh-5.5p1/sftp.1 openssh-5.5p1-gssapi/sftp.1
--- openssh-5.5p1/sftp.1	2010-02-11 16:21:03.000000000 -0600
+++ openssh-5.5p1-gssapi/sftp.1	2010-04-20 10:49:30.000000000 -0500
@@ -234,7 +234,8 @@
 Specify how many requests may be outstanding at any one time.
 Increasing this may slightly improve file transfer speed
 but will increase memory usage.
-The default is 64 outstanding requests.
+The default is 256 outstanding requests providing for 8MB 
+of outstanding data with a 32KB buffer.
 .It Fl r
 Recursively copy entire directories when uploading and downloading.
 Note that
diff -Naur --exclude=autom4te.cache openssh-5.5p1/sftp.c openssh-5.5p1-gssapi/sftp.c
--- openssh-5.5p1/sftp.c	2010-01-27 13:27:54.000000000 -0600
+++ openssh-5.5p1-gssapi/sftp.c	2010-04-20 10:49:30.000000000 -0500
@@ -77,6 +77,12 @@
 /* Are we in batchfile mode? */
 int batchmode = 0;
 
+/* Size of buffer used when copying files */
+size_t copy_buffer_len = 32768;
+
+/* Number of concurrent outstanding requests */
+size_t num_requests = 256;
+
 /* PID of ssh transport process */
 static pid_t sshpid = -1;
 
diff -Naur --exclude=autom4te.cache openssh-5.5p1/ssh-globus-usage.c openssh-5.5p1-gssapi/ssh-globus-usage.c
--- openssh-5.5p1/ssh-globus-usage.c	1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.5p1-gssapi/ssh-globus-usage.c	2010-04-20 10:49:30.000000000 -0500
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2009 The Board of Trustees of the University
+ * of Illinois.  See the LICENSE file for detailed license information.
+ *
+ * Portions, specifically log_usage_stats(), ssh_usage_stats_init(),
+ * ssh_usage_stats_close(), ssh_usage_ent_s, ssh_usage_tag_e and
+ * TAG #defines were based on those from Usage Metrics portions of:
+ * gridftp/server/source/globus_i_gfs_log.c
+ *
+ * Copyright 1999-2006 University of Chicago
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdarg.h>
+
+#include "log.h"
+#include "ssh-globus-usage.h"
+
+#ifdef HAVE_GLOBUS_USAGE
+
+static globus_list_t *usage_handle_list = NULL;
+
+#define SSH_GLOBUS_USAGE_ID 12
+#define SSH_GLOBUS_USAGE_VER 0
+
+#define SSH_GLOBUS_DEFAULT_TAGLIST "VvMm"
+#define SSH_GLOBUS_ALL_TAGLIST     "VvMmIuU"
+#define SSH_GLOBUS_TAGCOUNT 25
+
+typedef enum ssh_usage_tag_e
+{
+    SSH_GLOBUS_USAGE_SSH_VER        = 'V',
+    SSH_GLOBUS_USAGE_SSL_VER        = 'v',
+    SSH_GLOBUS_USAGE_METHOD         = 'M',
+    SSH_GLOBUS_USAGE_MECHANISM      = 'm',
+    SSH_GLOBUS_USAGE_CLIENTIP       = 'I',
+    SSH_GLOBUS_USAGE_USERNAME       = 'u',
+    SSH_GLOBUS_USAGE_USERDN         = 'U'
+    /* !! ADD to ALL_TAGLIST above and to globus_usage_stats_send()
+          invocation below when adding here */
+} ssh_usage_tag_t;
+
+typedef struct ssh_usage_ent_s
+{
+    globus_usage_stats_handle_t         handle;
+    char *                              target;
+    char *                              taglist;
+} ssh_usage_ent_t;
+
+
+globus_result_t
+ssh_usage_stats_init(int disable_usage_stats, char *usage_stats_targets)
+{
+    globus_result_t                     result;
+    char *                              target_str = NULL;
+    char *                              ptr = ptr;
+    char *                              target = NULL;
+    char *                              entry = NULL;
+    globus_list_t *                     list = NULL;
+    ssh_usage_ent_t *               usage_ent = NULL;
+
+    if (disable_usage_stats)
+	return GLOBUS_SUCCESS;
+
+    result = globus_module_activate(GLOBUS_USAGE_MODULE);
+    if (result != GLOBUS_SUCCESS)
+    {
+        error("ERROR: couldn't activate USAGE module");
+        return result;
+    }
+
+    if (!usage_stats_targets ||
+        !strcasecmp(usage_stats_targets, "default"))
+        target_str = strdup(CILOGON_COLLECTOR);
+    else
+        target_str = strdup(usage_stats_targets);
+
+    if (target_str == NULL)
+    {
+        error("ERROR: strdup failure for target_str");
+        goto error;
+    }
+    debug("Processing usage_stats_target (%s)\n", target_str);
+
+    if(target_str && strchr(target_str, '!'))
+    {
+        target = target_str;
+
+        do {
+            usage_ent = (ssh_usage_ent_t *) malloc(sizeof(ssh_usage_ent_t));
+            if (usage_ent == NULL)
+            {
+                error("ERROR: couldn't allocate for ssh_usage_ent_t");
+                goto error;
+            }
+
+            if ((ptr = strchr(target, ',')) != NULL)
+                *ptr = '\0';
+
+            entry = strdup(target);
+            if (entry == NULL)
+            {
+                error("ERROR: strdup failure for target");
+                goto error;
+            }
+
+            if (ptr)
+                target = ptr + 1;
+            else
+                target = NULL;
+
+            if((ptr = strchr(entry, '!')) != NULL)
+            {
+                *ptr = '\0';
+                usage_ent->taglist = strdup(ptr + 1);
+                if (usage_ent->taglist == NULL)
+                {
+                    error("ERROR: strdup failure for taglist");
+                    goto error;
+                }
+                if(strlen(usage_ent->taglist) > SSH_GLOBUS_TAGCOUNT)
+                {
+                    usage_ent->taglist[SSH_GLOBUS_TAGCOUNT + 1] = '\0';
+                }
+            }
+            else
+            {
+                usage_ent->taglist = strdup(SSH_GLOBUS_DEFAULT_TAGLIST);
+                if (usage_ent->taglist == NULL)
+                {
+                    error("ERROR: couldn't allocate for taglist");
+                    goto error;
+                }
+            }
+            
+            if(strcasecmp(usage_ent->taglist, "default") == 0)
+            {
+                free(usage_ent->taglist);
+                usage_ent->taglist = strdup(SSH_GLOBUS_DEFAULT_TAGLIST);
+                if (usage_ent->taglist == NULL)
+                {
+                    error("ERROR: couldn't allocate for taglist");
+                    goto error;
+                }
+            }                
+            else if(strcasecmp(usage_ent->taglist, "all") == 0)
+            {
+                free(usage_ent->taglist);
+                usage_ent->taglist = strdup(SSH_GLOBUS_ALL_TAGLIST);
+                if (usage_ent->taglist == NULL)
+                {
+                    error("ERROR: couldn't allocate for taglist");
+                    goto error;
+                }
+            }
+            
+            usage_ent->target = entry;
+
+            globus_list_insert(&usage_handle_list, usage_ent);
+        }
+        while(target != NULL);
+
+        free(target_str);
+    }
+    else
+    {
+        usage_ent = (ssh_usage_ent_t *) malloc(sizeof(ssh_usage_ent_t));
+        if (usage_ent == NULL)
+        {
+             error("ERROR: couldn't allocate for usage_ent");
+             goto error;
+        }
+
+        usage_ent->target = target_str;
+        usage_ent->taglist = strdup(SSH_GLOBUS_DEFAULT_TAGLIST);
+        if (usage_ent->taglist == NULL)
+        {
+             error("ERROR: couldn't allocate for taglist");
+             goto error;
+        }
+
+        globus_list_insert(&usage_handle_list, usage_ent);
+    }
+
+
+    for(list = usage_handle_list;
+        !globus_list_empty(list);
+        list = globus_list_rest(list))
+    {
+        usage_ent = (ssh_usage_ent_t *) globus_list_first(list);
+
+        usage_ent->handle = NULL;
+        debug("USAGE: Initializing (%s) (%s)", usage_ent->target?:"NULL",
+                     usage_ent->taglist?:"NULL");
+        result = globus_usage_stats_handle_init(
+            &usage_ent->handle,
+            SSH_GLOBUS_USAGE_ID,
+            SSH_GLOBUS_USAGE_VER,
+            usage_ent->target);
+    }
+
+    return result;
+
+error:
+    if (target_str)
+    {
+        free(target_str); 
+        target_str = NULL;
+    }
+    if (entry)
+    {
+        free(target_str); 
+        target_str = NULL;
+    }
+    return GLOBUS_FAILURE;
+}
+
+void
+ssh_usage_stats_close(int disable_usage_stats)
+{
+    globus_list_t *list;
+
+    if (disable_usage_stats)
+	return;
+
+    list = usage_handle_list;
+    
+    while(!globus_list_empty(list))
+    {
+        ssh_usage_ent_t *usage_ent;
+        
+        usage_ent = (ssh_usage_ent_t *) 
+            globus_list_remove(&list, list);
+    
+        if(usage_ent)
+        {
+            if(usage_ent->handle)
+            {
+                globus_usage_stats_handle_destroy(usage_ent->handle);
+            }
+            if(usage_ent->target)
+            {
+                free(usage_ent->target);
+            }
+            if(usage_ent->taglist)
+            {
+                free(usage_ent->taglist);
+            }
+            free(usage_ent);
+        }
+    }
+    usage_handle_list = NULL;
+}
+
+static void
+log_usage_stats(char *ssh_release, const char *ssl_release,
+                char *method, char *mechanism, const char *clientip,
+                char *username, char *userdn)
+{
+    globus_result_t                     result;
+    globus_list_t *                     list;
+    ssh_usage_ent_t *                   usage_ent;
+    char *                              keys[SSH_GLOBUS_TAGCOUNT];
+    char *                              values[SSH_GLOBUS_TAGCOUNT];
+    char *                              ptr;
+    char *                              key;
+    char *                              value;
+    int                                 i = 0;
+    char *                              save_taglist = NULL;
+
+    for(list = usage_handle_list;
+        !globus_list_empty(list);
+        list = globus_list_rest(list))
+    {
+        usage_ent = (ssh_usage_ent_t *) globus_list_first(list);
+
+        if(!usage_ent || usage_ent->handle == NULL)
+            return;
+        
+        if(save_taglist == NULL || 
+            strcmp(save_taglist, usage_ent->taglist) != 0)
+        {
+            save_taglist = usage_ent->taglist;
+            
+            ptr = usage_ent->taglist;
+            i = 0;
+            while(ptr && *ptr)
+            {
+                switch(*ptr)
+                {
+                  case SSH_GLOBUS_USAGE_SSH_VER:
+                    key = "SSH_VER";
+                    value = ssh_release;
+                    break;
+    
+                  case SSH_GLOBUS_USAGE_SSL_VER:
+                    key = "SSL_VER";
+                    value = (char *) ssl_release;
+                    break;
+    
+                  case SSH_GLOBUS_USAGE_METHOD:
+                    key = "METHOD";
+                    value = method;
+                    break;
+    
+                  case SSH_GLOBUS_USAGE_MECHANISM:
+                    key = "MECH";
+                    value = mechanism?:"";
+                    break;
+    
+                  case SSH_GLOBUS_USAGE_CLIENTIP:
+                    key = "CLIENTIP";
+                    value = (char *) clientip?:"";
+                    break;
+    
+                  case SSH_GLOBUS_USAGE_USERNAME:
+                    key = "USER";
+                    value = username?:"";
+                    break;
+    
+                  case SSH_GLOBUS_USAGE_USERDN:
+                    key = "USERDN";
+                    value = userdn?:"";
+                    break;
+    
+                  default:
+                    key = NULL;
+                    value = NULL;
+                    break;
+                }
+                
+                if(key != NULL && value != NULL)
+                {
+                    keys[i] = key;
+                    values[i] = value;
+                    i++;
+                }
+                
+                ptr++;
+            }
+        }
+
+#ifdef HAVE_GLOBUS_USAGE_SEND_ARRAY
+        result = globus_usage_stats_send_array(
+            usage_ent->handle, i, keys, values);
+#else
+        if (i)
+            result = globus_usage_stats_send(
+                usage_ent->handle, i,
+                i>0?keys[0]:NULL, i>0?values[0]:NULL,
+                i>1?keys[1]:NULL, i>1?values[1]:NULL,
+                i>2?keys[2]:NULL, i>2?values[2]:NULL,
+                i>3?keys[3]:NULL, i>3?values[3]:NULL,
+                i>4?keys[4]:NULL, i>4?values[4]:NULL,
+                i>5?keys[5]:NULL, i>5?values[5]:NULL,
+                i>6?keys[6]:NULL, i>6?values[6]:NULL);
+#endif /* HAVE_GLOBUS_USAGE_SEND_ARRAY */
+    }
+    
+    return;
+}
+#endif /* HAVE_GLOBUS_USAGE */
+
+void
+ssh_globus_send_usage_metrics(char *ssh_release, const char *ssl_release,
+                              char *method, char *mechanism, const char *client_ip,
+                              char *username, char *userdn)
+{
+#ifdef HAVE_GLOBUS_USAGE
+
+    log_usage_stats(ssh_release, ssl_release, method, mechanism,
+                    client_ip, username, userdn);
+
+#endif /* HAVE_GLOBUS_USAGE */
+}
diff -Naur --exclude=autom4te.cache openssh-5.5p1/ssh-globus-usage.h openssh-5.5p1-gssapi/ssh-globus-usage.h
--- openssh-5.5p1/ssh-globus-usage.h	1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.5p1-gssapi/ssh-globus-usage.h	2010-04-20 10:49:30.000000000 -0500
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2009 The Board of Trustees of the University
+ * of Illinois.  See the LICENSE file for detailed license information.
+ *
+ * Portions, specifically ssh_usage_stats_init(), ssh_usage_stats_close()
+ * were based on those from: gridftp/server/source/globus_i_gfs_log.h
+ * Copyright 1999-2006 University of Chicago
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SSH_GLOBUS_USAGE_H
+#define __SSH_GLOBUS_USAGE_H
+
+#include "includes.h"
+
+#ifdef HAVE_GLOBUS_USAGE
+
+#include "globus_usage.h"
+
+#define CILOGON_COLLECTOR "usage-stats.cilogon.org:4810"
+
+globus_result_t
+ssh_usage_stats_init(int disable_usage_stats, char *usage_stats_targets);
+
+void
+ssh_usage_stats_close(int disable_usage_stats);
+
+#endif /* HAVE_GLOBUS_USAGE */
+
+void
+ssh_globus_send_usage_metrics(char *ssh_release, const char *ssl_release,
+                           char *method, char *mechanism, const char *client_ip,
+                           char *username, char *userdn);
+
+#endif /* __SSH_GLOBUS_USAGE_H */
diff -Naur --exclude=autom4te.cache openssh-5.5p1/ssh-gss.h openssh-5.5p1-gssapi/ssh-gss.h
--- openssh-5.5p1/ssh-gss.h	2007-06-12 08:40:39.000000000 -0500
+++ openssh-5.5p1-gssapi/ssh-gss.h	2010-04-20 10:49:30.000000000 -0500
@@ -1,6 +1,6 @@
 /* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */
 /*
- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,6 +34,7 @@
 #include <gssapi/gssapi.h>
 #endif
 
+#ifndef MECHGLUE
 #ifdef KRB5
 # ifndef HEIMDAL
 #  ifdef HAVE_GSSAPI_GENERIC_H
@@ -49,6 +50,7 @@
 #endif /* GSS_C_NT_... */
 #endif /* !HEIMDAL */
 #endif /* KRB5 */
+#endif /* !MECHGLUE */
 
 /* draft-ietf-secsh-gsskeyex-06 */
 #define SSH2_MSG_USERAUTH_GSSAPI_RESPONSE		60
@@ -60,10 +62,22 @@
 
 #define SSH_GSS_OIDTYPE 0x06
 
+#define SSH2_MSG_KEXGSS_INIT                            30
+#define SSH2_MSG_KEXGSS_CONTINUE                        31
+#define SSH2_MSG_KEXGSS_COMPLETE                        32
+#define SSH2_MSG_KEXGSS_HOSTKEY                         33
+#define SSH2_MSG_KEXGSS_ERROR                           34
+#define SSH2_MSG_KEXGSS_GROUPREQ			40
+#define SSH2_MSG_KEXGSS_GROUP				41
+#define KEX_GSS_GRP1_SHA1_ID				"gss-group1-sha1-"
+#define KEX_GSS_GRP14_SHA1_ID				"gss-group14-sha1-"
+#define KEX_GSS_GEX_SHA1_ID				"gss-gex-sha1-"
+
 typedef struct {
 	char *filename;
 	char *envvar;
 	char *envval;
+	struct passwd *owner;
 	void *data;
 } ssh_gssapi_ccache;
 
@@ -71,8 +85,12 @@
 	gss_buffer_desc displayname;
 	gss_buffer_desc exportedname;
 	gss_cred_id_t creds;
+	gss_name_t name;
 	struct ssh_gssapi_mech_struct *mech;
 	ssh_gssapi_ccache store;
+    gss_ctx_id_t context;
+	int used;
+	int updated;
 } ssh_gssapi_client;
 
 typedef struct ssh_gssapi_mech_struct {
@@ -83,6 +101,7 @@
 	int (*userok) (ssh_gssapi_client *, char *);
 	int (*localname) (ssh_gssapi_client *, char **);
 	void (*storecreds) (ssh_gssapi_client *);
+	int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *);
 } ssh_gssapi_mech;
 
 typedef struct {
@@ -90,13 +109,14 @@
 	OM_uint32	minor; /* both */
 	gss_ctx_id_t	context; /* both */
 	gss_name_t	name; /* both */
-	gss_OID		oid; /* client */
+	gss_OID		oid; /* both */
 	gss_cred_id_t	creds; /* server */
 	gss_name_t	client; /* server */
-	gss_cred_id_t	client_creds; /* server */
+	gss_cred_id_t	client_creds; /* both */
 } Gssctxt;
 
 extern ssh_gssapi_mech *supported_mechs[];
+extern Gssctxt *gss_kex_context;
 
 int  ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
 void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
@@ -116,16 +136,41 @@
 void ssh_gssapi_delete_ctx(Gssctxt **);
 OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
 void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *);
-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
+int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *);
+OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *);
+int ssh_gssapi_credentials_updated(Gssctxt *);
+
+int ssh_gssapi_localname(char **name);
+void ssh_gssapi_rekey_creds();
 
 /* In the server */
+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, 
+    const char *);
+char *ssh_gssapi_client_mechanisms(const char *, const char *);
+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,
+    const char *);
+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, 
+    const char *);
 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
-int ssh_gssapi_userok(char *name);
+int ssh_gssapi_userok(char *name, struct passwd *, int gssapi_keyex);
 OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
 void ssh_gssapi_do_child(char ***, u_int *);
 void ssh_gssapi_cleanup_creds(void);
 void ssh_gssapi_storecreds(void);
 
+#ifdef MECHGLUE
+gss_cred_id_t __gss_get_mechanism_cred
+   (gss_cred_id_t,	/* union_cred */
+    gss_OID		/* mech_type */
+   );
+#endif
+
+char *ssh_gssapi_server_mechanisms(void);
+int ssh_gssapi_oid_table_ok();
+
+int ssh_gssapi_update_creds(ssh_gssapi_ccache *store);
+void ssh_gssapi_get_client_info(char **userdn, char **mech);
 #endif /* GSSAPI */
 
 #endif /* _SSH_GSS_H */
diff -Naur --exclude=autom4te.cache openssh-5.5p1/ssh.c openssh-5.5p1-gssapi/ssh.c
--- openssh-5.5p1/ssh.c	2010-02-26 14:55:06.000000000 -0600
+++ openssh-5.5p1-gssapi/ssh.c	2010-04-20 10:49:30.000000000 -0500
@@ -526,9 +526,6 @@
 			no_shell_flag = 1;
 			no_tty_flag = 1;
 			break;
-		case 'T':
-			no_tty_flag = 1;
-			break;
 		case 'o':
 			dummy = 1;
 			line = xstrdup(optarg);
@@ -537,6 +534,13 @@
 				exit(255);
 			xfree(line);
 			break;
+		case 'T':
+			no_tty_flag = 1;
+			/* ensure that the user doesn't try to backdoor a */
+			/* null cipher switch on an interactive session */
+			/* so explicitly disable it no matter what */
+			options.none_switch=0;
+			break;
 		case 's':
 			subsystem_flag = 1;
 			break;
@@ -647,6 +651,32 @@
 			fatal("Can't open user config file %.100s: "
 			    "%.100s", config, strerror(errno));
 	} else {
+	    /*
+	     * Since the config file parsing code aborts if it sees
+	     * options it doesn't recognize, allow users to put
+	     * options specific to compile-time add-ons in alternate
+	     * config files so their primary config file will
+	     * interoperate SSH versions that don't support those
+	     * options.
+	     */
+#ifdef GSSAPI
+		r = snprintf(buf, sizeof buf, "%s/%s.gssapi", pw->pw_dir,
+		    _PATH_SSH_USER_CONFFILE);
+		if (r > 0 && (size_t)r < sizeof(buf))
+			(void)read_config_file(buf, host, &options, 1);
+#ifdef GSI
+		r = snprintf(buf, sizeof buf, "%s/%s.gsi", pw->pw_dir,
+		    _PATH_SSH_USER_CONFFILE);
+		if (r > 0 && (size_t)r < sizeof(buf))
+			(void)read_config_file(buf, host, &options, 1);
+#endif
+#if defined(KRB5)
+		r = snprintf(buf, sizeof buf, "%s/%s.krb", pw->pw_dir,
+		    _PATH_SSH_USER_CONFFILE);
+		if (r > 0 && (size_t)r < sizeof(buf))
+			(void)read_config_file(buf, host, &options, 1);
+#endif
+#endif
 		r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir,
 		    _PATH_SSH_USER_CONFFILE);
 		if (r > 0 && (size_t)r < sizeof(buf))
@@ -667,8 +697,11 @@
 
 	seed_rng();
 
-	if (options.user == NULL)
+	if (options.user == NULL) {
 		options.user = xstrdup(pw->pw_name);
+		options.implicit = 1;
+	}
+        else options.implicit = 0;
 
 	/* Get default port if port has not been set. */
 	if (options.port == 0) {
@@ -1214,6 +1247,9 @@
 {
 	Channel *c;
 	int window, packetmax, in, out, err;
+	int sock;
+	int socksize;
+	int socksizelen = sizeof(int);
 
 	if (stdin_null_flag) {
 		in = open(_PATH_DEVNULL, O_RDONLY);
@@ -1234,9 +1270,75 @@
 	if (!isatty(err))
 		set_nonblock(err);
 
-	window = CHAN_SES_WINDOW_DEFAULT;
+	/* we need to check to see if what they want to do about buffer */
+	/* sizes here. In a hpn to nonhpn connection we want to limit */
+	/* the window size to something reasonable in case the far side */
+	/* has the large window bug. In hpn to hpn connection we want to */
+	/* use the max window size but allow the user to override it */
+	/* lastly if they disabled hpn then use the ssh std window size */
+
+	/* so why don't we just do a getsockopt() here and set the */
+	/* ssh window to that? In the case of a autotuning receive */
+	/* window the window would get stuck at the initial buffer */
+	/* size generally less than 96k. Therefore we need to set the */
+	/* maximum ssh window size to the maximum hpn buffer size */
+	/* unless the user has specifically set the tcprcvbufpoll */
+	/* to no. In which case we *can* just set the window to the */
+	/* minimum of the hpn buffer size and tcp receive buffer size */
+	
+	if (tty_flag)
+		options.hpn_buffer_size = CHAN_SES_WINDOW_DEFAULT;
+	else
+		options.hpn_buffer_size = 2*1024*1024;
+
+	if (datafellows & SSH_BUG_LARGEWINDOW) 
+	{
+		debug("HPN to Non-HPN Connection");
+	} 
+	else 
+	{
+		if (options.tcp_rcv_buf_poll <= 0) 
+		{
+			sock = socket(AF_INET, SOCK_STREAM, 0);
+			getsockopt(sock, SOL_SOCKET, SO_RCVBUF, 
+				   &socksize, &socksizelen);
+			close(sock);
+			debug("socksize %d", socksize);
+			options.hpn_buffer_size = socksize;
+			debug ("HPNBufferSize set to TCP RWIN: %d", options.hpn_buffer_size);
+		} 
+		else
+		{
+			if (options.tcp_rcv_buf > 0) 
+			{
+				/*create a socket but don't connect it */
+				/* we use that the get the rcv socket size */
+				sock = socket(AF_INET, SOCK_STREAM, 0);
+				/* if they are using the tcp_rcv_buf option */
+				/* attempt to set the buffer size to that */
+				if (options.tcp_rcv_buf) 
+					setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&options.tcp_rcv_buf, 
+						   sizeof(options.tcp_rcv_buf));
+				getsockopt(sock, SOL_SOCKET, SO_RCVBUF, 
+					   &socksize, &socksizelen);
+				close(sock);
+				debug("socksize %d", socksize);
+				options.hpn_buffer_size = socksize;
+				debug ("HPNBufferSize set to user TCPRcvBuf: %d", options.hpn_buffer_size);
+			}
+ 		}
+		
+	}
+
+	debug("Final hpn_buffer_size = %d", options.hpn_buffer_size);
+
+	window = options.hpn_buffer_size;
+
+	channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size);
+
 	packetmax = CHAN_SES_PACKET_DEFAULT;
 	if (tty_flag) {
+		window = 4*CHAN_SES_PACKET_DEFAULT;
 		window >>= 1;
 		packetmax >>= 1;
 	}
@@ -1244,7 +1346,10 @@
 	    "session", SSH_CHANNEL_OPENING, in, out, err,
 	    window, packetmax, CHAN_EXTENDED_WRITE,
 	    "client-session", /*nonblock*/0);
-
+	if ((options.tcp_rcv_buf_poll > 0) && (!options.hpn_disabled)) {
+		c->dynamic_window = 1;
+		debug ("Enabled Dynamic Window Scaling\n");
+	}
 	debug3("ssh_session2_open: channel_new: %d", c->self);
 
 	channel_send_open(c->self);
diff -Naur --exclude=autom4te.cache openssh-5.5p1/ssh_config openssh-5.5p1-gssapi/ssh_config
--- openssh-5.5p1/ssh_config	2010-01-12 02:40:27.000000000 -0600
+++ openssh-5.5p1-gssapi/ssh_config	2010-04-20 10:49:30.000000000 -0500
@@ -24,8 +24,10 @@
 #   RSAAuthentication yes
 #   PasswordAuthentication yes
 #   HostbasedAuthentication no
-#   GSSAPIAuthentication no
-#   GSSAPIDelegateCredentials no
+#   GSSAPIAuthentication yes
+#   GSSAPIDelegateCredentials yes
+#   GSSAPIKeyExchange yes
+#   GSSAPITrustDNS yes
 #   BatchMode no
 #   CheckHostIP yes
 #   AddressFamily any
diff -Naur --exclude=autom4te.cache openssh-5.5p1/ssh_config.5 openssh-5.5p1-gssapi/ssh_config.5
--- openssh-5.5p1/ssh_config.5	2010-03-25 20:09:13.000000000 -0500
+++ openssh-5.5p1-gssapi/ssh_config.5	2010-04-20 10:49:30.000000000 -0500
@@ -56,6 +56,12 @@
 user's configuration file
 .Pq Pa ~/.ssh/config
 .It
+GSSAPI configuration file
+.Pq Pa $HOME/.ssh/config.gssapi
+.It
+Kerberos configuration file
+.Pq Pa $HOME/.ssh/config.krb
+.It
 system-wide configuration file
 .Pq Pa /etc/ssh/ssh_config
 .El
@@ -476,13 +482,40 @@
 .It Cm GSSAPIAuthentication
 Specifies whether user authentication based on GSSAPI is allowed.
 The default is
-.Dq no .
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI 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 GSSAPIClientIdentity
+If set, specifies the GSSAPI client identity that ssh should use when 
+connecting to the server. The default is unset, which means that the default 
+identity will be used.
 .It Cm GSSAPIDelegateCredentials
 Forward (delegate) credentials to the server.
 The default is
-.Dq no .
-Note that this option applies to protocol version 2 only.
+.Dq yes .
+Note that this option applies to protocol version 2 connections using GSSAPI.
+.It Cm GSSAPIRenewalForcesRekey
+If set to 
+.Dq yes
+then renewal of the client's GSSAPI credentials will force the rekeying of the
+ssh connection. With a compatible server, this can delegate the renewed 
+credentials to a session on the server.
+The default is
+.Dq yes .
+.It Cm GSSAPITrustDns
+Set to 
+.Dq yes to indicate that the DNS is trusted to securely canonicalize
+the name of the host being connected to. If 
+.Dq no, the hostname entered on the
+command line will be passed untouched to the GSSAPI library.
+The default is
+.Dq yes .
+This option only applies to protocol version 2 connections using GSSAPI.
 .It Cm HashKnownHosts
 Indicates that
 .Xr ssh 1
@@ -734,7 +767,7 @@
 over another method (e.g.\&
 .Cm password )
 The default for this option is:
-.Do gssapi-with-mic,hostbased,publickey,keyboard-interactive,password
+.Do gssapi-keyex,gssapi-with-mic,hostbased,publickey,keyboard-interactive,password
 .Dc .
 .It Cm Protocol
 Specifies the protocol versions
diff -Naur --exclude=autom4te.cache openssh-5.5p1/sshconnect.c openssh-5.5p1-gssapi/sshconnect.c
--- openssh-5.5p1/sshconnect.c	2010-03-04 04:53:36.000000000 -0600
+++ openssh-5.5p1-gssapi/sshconnect.c	2010-04-20 10:49:30.000000000 -0500
@@ -168,6 +168,31 @@
 }
 
 /*
+ * Set TCP receive buffer if requested.
+ * Note: tuning needs to happen after the socket is
+ * created but before the connection happens
+ * so winscale is negotiated properly -cjr
+ */
+static void
+ssh_set_socket_recvbuf(int sock)
+{
+	void *buf = (void *)&options.tcp_rcv_buf;
+	int sz = sizeof(options.tcp_rcv_buf);
+	int socksize;
+	int socksizelen = sizeof(int);
+
+	debug("setsockopt Attempting to set SO_RCVBUF to %d", options.tcp_rcv_buf);
+	if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, buf, sz) >= 0) {
+	  getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &socksize, &socksizelen);
+	  debug("setsockopt SO_RCVBUF: %.100s %d", strerror(errno), socksize);
+	}
+	else
+		error("Couldn't set socket receive buffer to %d: %.100s",
+		    options.tcp_rcv_buf, strerror(errno));
+}
+
+
+/*
  * Creates a (possibly privileged) socket for use as the ssh connection.
  */
 static int
@@ -190,6 +215,9 @@
 			    strerror(errno));
 		else
 			debug("Allocated local port %d.", p);
+
+		if (options.tcp_rcv_buf > 0)
+			ssh_set_socket_recvbuf(sock);		
 		return sock;
 	}
 	sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
@@ -199,6 +227,9 @@
 	}
 	fcntl(sock, F_SETFD, FD_CLOEXEC);
 
+	if (options.tcp_rcv_buf > 0)
+		ssh_set_socket_recvbuf(sock);
+	
 	/* Bind the socket to an alternative local IP address */
 	if (options.bind_address == NULL)
 		return sock;
@@ -542,7 +573,7 @@
 	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
 	    compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
 	    compat20 ? PROTOCOL_MINOR_2 : minor1,
-	    SSH_VERSION, compat20 ? "\r\n" : "\n");
+	    SSH_RELEASE, compat20 ? "\r\n" : "\n");
 	if (roaming_atomicio(vwrite, connection_out, buf, strlen(buf))
 	    != strlen(buf))
 		fatal("write: %.100s", strerror(errno));
diff -Naur --exclude=autom4te.cache openssh-5.5p1/sshconnect2.c openssh-5.5p1-gssapi/sshconnect2.c
--- openssh-5.5p1/sshconnect2.c	2010-02-26 14:55:06.000000000 -0600
+++ openssh-5.5p1-gssapi/sshconnect2.c	2010-04-20 10:49:30.000000000 -0500
@@ -80,6 +80,22 @@
 extern char *client_version_string;
 extern char *server_version_string;
 extern Options options;
+extern Kex *xxx_kex;
+
+/* tty_flag is set in ssh.c. use this in ssh_userauth2 */
+/* if it is set then prevent the switch to the null cipher */
+
+extern int tty_flag;
+
+/* tty_flag is set in ssh.c. use this in ssh_userauth2 */
+/* if it is set then prevent the switch to the null cipher */
+
+extern int tty_flag;
+
+/* tty_flag is set in ssh.c. use this in ssh_userauth2 */
+/* if it is set then prevent the switch to the null cipher */
+
+extern int tty_flag;
 
 /*
  * SSH2 key exchange
@@ -106,9 +122,34 @@
 {
 	Kex *kex;
 
+#ifdef GSSAPI
+	char *orig = NULL, *gss = NULL;
+	char *gss_host = NULL;
+#endif
+
 	xxx_host = host;
 	xxx_hostaddr = hostaddr;
 
+#ifdef GSSAPI
+	if (options.gss_keyex) {
+		/* Add the GSSAPI mechanisms currently supported on this 
+		 * client to the key exchange algorithm proposal */
+		orig = myproposal[PROPOSAL_KEX_ALGS];
+
+		if (options.gss_trust_dns)
+			gss_host = (char *)get_canonical_hostname(1);
+		else
+			gss_host = host;
+
+		gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
+		if (gss) {
+			debug("Offering GSSAPI proposal: %s", gss);
+			xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
+			    "%s,%s", gss, orig);
+		}
+	}
+#endif
+
 	if (options.ciphers == (char *)-1) {
 		logit("No valid ciphers for protocol version 2 given, using defaults.");
 		options.ciphers = NULL;
@@ -136,6 +177,17 @@
 		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
 		    options.hostkeyalgorithms;
 
+#ifdef GSSAPI
+	/* If we've got GSSAPI algorithms, then we also support the
+	 * 'null' hostkey, as a last resort */
+	if (options.gss_keyex && gss) {
+		orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
+		xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], 
+		    "%s,null", orig);
+		xfree(gss);
+	}
+#endif
+
 	if (options.rekey_limit)
 		packet_set_rekey_limit((u_int32_t)options.rekey_limit);
 
@@ -145,10 +197,26 @@
 	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
 	kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
 	kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
+#ifdef GSSAPI
+	if (options.gss_keyex) {
+		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
+		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
+		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
+	}
+#endif
 	kex->client_version_string=client_version_string;
 	kex->server_version_string=server_version_string;
 	kex->verify_host_key=&verify_host_key_callback;
 
+#ifdef GSSAPI
+	if (options.gss_keyex) {
+		kex->gss_deleg_creds = options.gss_deleg_creds;
+		kex->gss_trust_dns = options.gss_trust_dns;
+		kex->gss_client = options.gss_client_identity;
+		kex->gss_host = gss_host;
+	}
+#endif
+
 	xxx_kex = kex;
 
 	dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -243,6 +311,7 @@
 void	input_gssapi_hash(int type, u_int32_t, void *);
 void	input_gssapi_error(int, u_int32_t, void *);
 void	input_gssapi_errtok(int, u_int32_t, void *);
+int	userauth_gsskeyex(Authctxt *authctxt);
 #endif
 
 void	userauth(Authctxt *, char *);
@@ -258,6 +327,11 @@
 
 Authmethod authmethods[] = {
 #ifdef GSSAPI
+	{"gssapi-keyex",
+		userauth_gsskeyex,
+		NULL,
+		&options.gss_authentication,
+		NULL},
 	{"gssapi-with-mic",
 		userauth_gssapi,
 		NULL,
@@ -358,6 +432,28 @@
 	pubkey_cleanup(&authctxt);
 	dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL);
 
+	/* if the user wants to use the none cipher do it */
+	/* post authentication and only if the right conditions are met */
+	/* both of the NONE commands must be true and there must be no */
+	/* tty allocated */
+	if ((options.none_switch == 1) && (options.none_enabled == 1)) 
+	{
+		if (!tty_flag) /* no null on tty sessions */
+		{
+			debug("Requesting none rekeying...");
+			myproposal[PROPOSAL_ENC_ALGS_STOC] = "none";
+			myproposal[PROPOSAL_ENC_ALGS_CTOS] = "none";
+			kex_prop2buf(&xxx_kex->my,myproposal);
+			packet_request_rekeying();
+			fprintf(stderr, "WARNING: ENABLED NONE CIPHER\n");
+		}
+		else
+		{
+			/* requested NONE cipher when in a tty */
+			debug("Cannot switch to NONE cipher with tty allocated");
+			fprintf(stderr, "NONE cipher switch disabled when a TTY is allocated\n");
+		}
+	}
 	debug("Authentication succeeded (%s).", authctxt.method->name);
 }
 
@@ -564,19 +660,34 @@
 	static u_int mech = 0;
 	OM_uint32 min;
 	int ok = 0;
+	char *gss_host = NULL;
+
+	if (!options.gss_authentication) {
+		verbose("GSSAPI authentication disabled.");
+		return 0;
+	}
+
+	if (options.gss_trust_dns)
+		gss_host = (char *)get_canonical_hostname(1);
+	else
+		gss_host = (char *)authctxt->host;
 
 	/* Try one GSSAPI method at a time, rather than sending them all at
 	 * once. */
 
 	if (gss_supported == NULL)
-		gss_indicate_mechs(&min, &gss_supported);
+		if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
+			gss_supported = NULL;
+			return 0;
+		}
 
 	/* Check to see if the mechanism is usable before we offer it */
 	while (mech < gss_supported->count && !ok) {
 		/* My DER encoding requires length<128 */
 		if (gss_supported->elements[mech].length < 128 &&
 		    ssh_gssapi_check_mechanism(&gssctxt, 
-		    &gss_supported->elements[mech], authctxt->host)) {
+		    &gss_supported->elements[mech], gss_host, 
+                    options.gss_client_identity)) {
 			ok = 1; /* Mechanism works */
 		} else {
 			mech++;
@@ -640,7 +751,8 @@
 
 	if (status == GSS_S_COMPLETE) {
 		/* send either complete or MIC, depending on mechanism */
-		if (!(flags & GSS_C_INTEG_FLAG)) {
+		if (strcmp(authctxt->method->name,"gssapi")==0 ||
+		    (!(flags & GSS_C_INTEG_FLAG))) {
 			packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
 			packet_send();
 		} else {
@@ -673,8 +785,8 @@
 {
 	Authctxt *authctxt = ctxt;
 	Gssctxt *gssctxt;
-	int oidlen;
-	char *oidv;
+	u_int oidlen;
+	u_char *oidv;
 
 	if (authctxt == NULL)
 		fatal("input_gssapi_response: no authentication context");
@@ -784,6 +896,73 @@
 	xfree(msg);
 	xfree(lang);
 }
+
+#ifdef GSI
+extern
+const gss_OID_desc * const              gss_mech_globus_gssapi_openssl;
+#define is_gsi_oid(oid) \
+  (oid->length == gss_mech_globus_gssapi_openssl->length && \
+   (memcmp(oid->elements, gss_mech_globus_gssapi_openssl->elements, \
+	   oid->length) == 0))
+#endif
+
+int
+userauth_gsskeyex(Authctxt *authctxt)
+{
+	Buffer b;
+	gss_buffer_desc gssbuf;
+	gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
+	OM_uint32 ms;
+
+	static int attempt = 0;
+	if (attempt++ >= 1)
+		return (0);
+
+	if (gss_kex_context == NULL) {
+		debug("No valid Key exchange context"); 
+		return (0);
+	}
+
+#ifdef GSI
+    if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
+        ssh_gssapi_buildmic(&b, "", authctxt->service, "gssapi-keyex");
+	} else {
+#endif
+        ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
+                            "gssapi-keyex");
+#ifdef GSI
+	}
+#endif
+
+	gssbuf.value = buffer_ptr(&b);
+	gssbuf.length = buffer_len(&b);
+
+	if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
+		buffer_free(&b);
+		return (0);
+	}
+
+	packet_start(SSH2_MSG_USERAUTH_REQUEST);
+#ifdef GSI
+    if (options.implicit && is_gsi_oid(gss_kex_context->oid)) {
+        packet_put_cstring("");
+	} else {
+#endif
+	packet_put_cstring(authctxt->server_user);
+#ifdef GSI
+	}
+#endif
+	packet_put_cstring(authctxt->service);
+	packet_put_cstring(authctxt->method->name);
+	packet_put_string(mic.value, mic.length);
+	packet_send();
+
+	buffer_free(&b);
+	gss_release_buffer(&ms, &mic);
+
+	return (1);
+}
+
 #endif /* GSSAPI */
 
 int
diff -Naur --exclude=autom4te.cache openssh-5.5p1/sshd.c openssh-5.5p1-gssapi/sshd.c
--- openssh-5.5p1/sshd.c	2010-03-07 06:05:17.000000000 -0600
+++ openssh-5.5p1-gssapi/sshd.c	2010-04-20 10:49:30.000000000 -0500
@@ -119,6 +119,11 @@
 #include "monitor_wrap.h"
 #include "roaming.h"
 #include "version.h"
+#include "ssh-globus-usage.h"
+
+#ifdef USE_SECURITY_SESSION_API
+#include <Security/AuthSession.h>
+#endif
 
 #ifdef LIBWRAP
 #include <tcpd.h>
@@ -137,6 +142,9 @@
 #define REEXEC_CONFIG_PASS_FD		(STDERR_FILENO + 3)
 #define REEXEC_MIN_FREE_FD		(STDERR_FILENO + 4)
 
+int myflag = 0;
+
+
 extern char *__progname;
 
 /* Server configuration options. */
@@ -418,7 +426,7 @@
 		minor = PROTOCOL_MINOR_1;
 	}
 	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
-	    SSH_VERSION, newline);
+	    SSH_RELEASE, newline);
 	server_version_string = xstrdup(buf);
 
 	/* Send our protocol version identification. */
@@ -469,6 +477,9 @@
 	}
 	debug("Client protocol version %d.%d; client software version %.100s",
 	    remote_major, remote_minor, remote_version);
+	logit("SSH: Server;Ltype: Version;Remote: %s-%d;Protocol: %d.%d;Client: %.100s",
+	      get_remote_ipaddr(), get_remote_port(),
+	    remote_major, remote_minor, remote_version);
 
 	compat_datafellows(remote_version);
 
@@ -988,6 +999,8 @@
 	int ret, listen_sock, on = 1;
 	struct addrinfo *ai;
 	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
+	int socksize;
+	int socksizelen = sizeof(int);
 
 	for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
 		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
@@ -1028,6 +1041,11 @@
 
 		debug("Bind to port %s on %s.", strport, ntop);
 
+		getsockopt(listen_sock, SOL_SOCKET, SO_RCVBUF, 
+				   &socksize, &socksizelen);
+		debug("Server TCP RWIN socket size: %d", socksize);
+		debug("HPN Buffer Size: %d", options.hpn_buffer_size);
+
 		/* Bind the socket to the desired port. */
 		if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) {
 			error("Bind to port %s on %s failed: %.200s.",
@@ -1517,6 +1535,13 @@
 	/* Fill in default values for those options not explicitly set. */
 	fill_default_server_options(&options);
 
+#ifdef HAVE_GLOBUS_USAGE
+	if (ssh_usage_stats_init(options.disable_usage_stats,
+			options.usage_stats_targets) != GLOBUS_SUCCESS) {
+		fatal("Error initializing Globus Usage Metrics");
+	}
+#endif /* HAVE_GLOBUS_USAGE */
+
 	/* challenge-response is implemented via keyboard interactive */
 	if (options.challenge_response_authentication)
 		options.kbd_interactive_authentication = 1;
@@ -1577,10 +1602,13 @@
 		logit("Disabling protocol version 1. Could not load host key");
 		options.protocol &= ~SSH_PROTO_1;
 	}
+#ifndef GSSAPI
+	/* The GSSAPI key exchange can run without a host key */
 	if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
 		logit("Disabling protocol version 2. Could not load host key");
 		options.protocol &= ~SSH_PROTO_2;
 	}
+#endif
 	if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
 		logit("sshd: no hostkeys available -- exiting.");
 		exit(1);
@@ -1872,6 +1900,9 @@
 		cleanup_exit(255);
 	}
 
+	/* set the HPN options for the child */
+	channel_set_hpn(options.hpn_disabled, options.hpn_buffer_size);
+
 	/*
 	 * We use get_canonical_hostname with usedns = 0 instead of
 	 * get_remote_ipaddr here so IP options will be checked.
@@ -1909,6 +1940,60 @@
 	/* Log the connection. */
 	verbose("Connection from %.500s port %d", remote_ip, remote_port);
 
+#ifdef USE_SECURITY_SESSION_API
+	/*
+	 * Create a new security session for use by the new user login if
+	 * the current session is the root session or we are not launched
+	 * by inetd (eg: debugging mode or server mode).  We do not
+	 * necessarily need to create a session if we are launched from
+	 * inetd because Panther xinetd will create a session for us.
+	 *
+	 * The only case where this logic will fail is if there is an
+	 * inetd running in a non-root session which is not creating
+	 * new sessions for us.  Then all the users will end up in the
+	 * same session (bad).
+	 *
+	 * When the client exits, the session will be destroyed for us
+	 * automatically.
+	 *
+	 * We must create the session before any credentials are stored
+	 * (including AFS pags, which happens a few lines below).
+	 */
+	{
+		OSStatus err = 0;
+		SecuritySessionId sid = 0;
+		SessionAttributeBits sattrs = 0;
+
+		err = SessionGetInfo(callerSecuritySession, &sid, &sattrs);
+		if (err)
+			error("SessionGetInfo() failed with error %.8X",
+			    (unsigned) err);
+		else
+			debug("Current Session ID is %.8X / Session Attributes are %.8X",
+			    (unsigned) sid, (unsigned) sattrs);
+
+		if (inetd_flag && !(sattrs & sessionIsRoot))
+			debug("Running in inetd mode in a non-root session... "
+			    "assuming inetd created the session for us.");
+		else {
+			debug("Creating new security session...");
+			err = SessionCreate(0, sessionHasTTY | sessionIsRemote);
+			if (err)
+				error("SessionCreate() failed with error %.8X",
+				    (unsigned) err);
+
+			err = SessionGetInfo(callerSecuritySession, &sid, 
+			    &sattrs);
+			if (err)
+				error("SessionGetInfo() failed with error %.8X",
+				    (unsigned) err);
+			else
+				debug("New Session ID is %.8X / Session Attributes are %.8X",
+				    (unsigned) sid, (unsigned) sattrs);
+		}
+	}
+#endif
+
 	/*
 	 * We don't want to listen forever unless the other side
 	 * successfully authenticates itself.  So we set up an alarm which is
@@ -1922,6 +2007,13 @@
 		alarm(options.login_grace_time);
 
 	sshd_exchange_identification(sock_in, sock_out);
+#if defined(AFS_KRB5)
+	/* If machine has AFS, set process authentication group. */
+	if (k_hasafs()) {
+		k_setpag();
+		k_unlog();
+	}
+#endif /* AFS || AFS_KRB5 */
 
 	/* In inetd mode, generate ephemeral key only for proto 1 connections */
 	if (!compat20 && inetd_flag && sensitive_data.server_key == NULL)
@@ -1981,7 +2073,7 @@
 #endif
 
 #ifdef GSSAPI
-	if (options.gss_authentication) {
+	if (options.gss_authentication && options.gss_deleg_creds) {
 		temporarily_use_uid(authctxt->pw);
 		ssh_gssapi_storecreds();
 		restore_uid();
@@ -2264,9 +2356,15 @@
 {
 	Kex *kex;
 
+	myflag++;
+	debug ("MYFLAG IS %d", myflag);
 	if (options.ciphers != NULL) {
 		myproposal[PROPOSAL_ENC_ALGS_CTOS] =
 		myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
+	} else if (options.none_enabled == 1) {
+		debug ("WARNING: None cipher enabled");
+		myproposal[PROPOSAL_ENC_ALGS_CTOS] =
+		myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_ENCRYPT_INCLUDE_NONE;
 	}
 	myproposal[PROPOSAL_ENC_ALGS_CTOS] =
 	    compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
@@ -2287,12 +2385,61 @@
 
 	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 there's no point advertising
+	 * the other key exchange algorithms
+	 */
+
+	if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
+		orig = NULL;
+
+	if (options.gss_keyex)
+		gss = ssh_gssapi_server_mechanisms();
+	else
+		gss = NULL;
+
+	if (gss && orig)
+		xasprintf(&newstr, "%s,%s", gss, orig);
+	else if (gss)
+		newstr = gss;
+	else if (orig)
+		newstr = orig;
+
+	/* 
+	 * If we've got GSSAPI mechanisms, then we've got the 'null' host
+	 * key alg, but we can't tell people about it unless its the only
+  	 * host key algorithm we support
+	 */
+	if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
+		myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
+
+	if (newstr)
+		myproposal[PROPOSAL_KEX_ALGS] = newstr;
+	else
+		fatal("No supported key exchange algorithms");
+	}
+#endif
+
 	/* start key exchange */
 	kex = kex_setup(myproposal);
 	kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
 	kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
 	kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
 	kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+#ifdef GSSAPI
+	if (options.gss_keyex) {
+		kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
+		kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
+		kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server;
+	}
+#endif
 	kex->server = 1;
 	kex->client_version_string=client_version_string;
 	kex->server_version_string=server_version_string;
diff -Naur --exclude=autom4te.cache openssh-5.5p1/sshd_config openssh-5.5p1-gssapi/sshd_config
--- openssh-5.5p1/sshd_config	2009-10-11 05:51:09.000000000 -0500
+++ openssh-5.5p1-gssapi/sshd_config	2010-04-20 10:49:30.000000000 -0500
@@ -68,9 +68,17 @@
 #KerberosTicketCleanup yes
 #KerberosGetAFSToken no
 
+# Session hooks: if allowed, specify the commands to execute
+#AllowSessionHooks no
+#SessionHookStartupCmd /bin/true
+#SessionHookShutdownCmd /bin/true
+
 # GSSAPI options
-#GSSAPIAuthentication no
+#GSSAPIAuthentication yes
+#GSSAPIDelegateCredentials yes
 #GSSAPICleanupCredentials yes
+#GSSAPIStrictAcceptorCheck yes
+#GSSAPIKeyExchange yes
 
 # Set this to 'yes' to enable PAM authentication, account processing, 
 # and session processing. If this is enabled, PAM authentication will 
@@ -83,6 +91,10 @@
 # and ChallengeResponseAuthentication to 'no'.
 #UsePAM no
 
+# Set to 'yes' to allow the PAM stack to change the user name during
+# calls to authentication
+#PermitPAMUserChange no
+
 #AllowAgentForwarding yes
 #AllowTcpForwarding yes
 #GatewayPorts no
@@ -110,8 +122,27 @@
 # override default of no subsystems
 Subsystem	sftp	/usr/libexec/sftp-server
 
+# the following are HPN related configuration options
+# tcp receive buffer polling. disable in non autotuning kernels
+#TcpRcvBufPoll yes
+ 
+# allow the use of the none cipher
+#NoneEnabled no
+
+# disable hpn performance boosts. 
+#HPNDisabled no
+
+# buffer size for hpn to non-hpn connections
+#HPNBufferSize 2048
+
+
 # Example of overriding settings on a per-user basis
 #Match User anoncvs
 #	X11Forwarding no
 #	AllowTcpForwarding no
 #	ForceCommand cvs server
+
+
+# Usage Metrics
+#UsageStatsTargets usage-stats.cilogon.org:4810
+#DisableUsageStats No
diff -Naur --exclude=autom4te.cache openssh-5.5p1/sshd_config.5 openssh-5.5p1-gssapi/sshd_config.5
--- openssh-5.5p1/sshd_config.5	2010-03-04 17:41:45.000000000 -0600
+++ openssh-5.5p1-gssapi/sshd_config.5	2010-04-20 10:49:30.000000000 -0500
@@ -335,6 +335,16 @@
 in
 .Xr ssh_config 5
 for more information on patterns.
+.It Cm DisableUsageStats
+This keyword can be followed by one of the keywords "true", "enabled", "yes",
+"on" or "1" to disable reporting of usage metrics. Or it can be set to "false",
+"disabled", "no", "off", "0" to enable reporting of usage metrics, which is the
+default. Setting the
+.Cm GLOBUS_USAGE_OPTOUT
+environment variable to "1" will also disable the reporting of usage metrics.
+Disabling reporting of usage metrics will cause the
+.Cm UsageStatsTargets
+setting to be ignored.
 .It Cm ForceCommand
 Forces the execution of the command specified by
 .Cm ForceCommand ,
@@ -377,7 +387,17 @@
 .It Cm GSSAPIAuthentication
 Specifies whether user authentication based on GSSAPI is allowed.
 The default is
-.Dq no .
+.Dq yes .
+Note that this option applies to protocol version 2 only.
+.It Cm GSSAPIDelegateCredentials
+Specifies whether delegated credentials are stored in the user's environment.
+The default is
+.Dq yes .
+.It Cm GSSAPIKeyExchange
+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange 
+doesn't rely on ssh keys to verify host identity.
+The default is
+.Dq yes .
 Note that this option applies to protocol version 2 only.
 .It Cm GSSAPICleanupCredentials
 Specifies whether to automatically destroy the user's credentials cache
@@ -385,6 +405,44 @@
 The default is
 .Dq yes .
 Note that this option applies to protocol version 2 only.
+.It Cm GSSAPICredentialsPath
+If specified, the delegated GSSAPI credential is stored in the
+given path, overwriting any existing credentials.  
+Paths can be specified with syntax similar to the AuthorizedKeysFile 
+option (i.e., accepting %h and %u tokens).  
+When using this option,
+setting 'GssapiCleanupCredentials no' is recommended,
+so logging out of one session
+doesn't remove the credentials in use by another session of
+the same user.
+Currently only implemented for the GSI mechanism.
+.It Cm GSIAllowLimitedProxy
+Specifies whether to accept limited proxy credentials for
+authentication.
+The default is
+.Dq no .
+.It Cm GSSAPIStrictAcceptorCheck
+Determines whether to be strict about the identity of the GSSAPI acceptor 
+a client authenticates against. If
+.Dq yes
+then the client must authenticate against the
+.Pa host
+service on the current hostname. If 
+.Dq no
+then the client may authenticate against any service key stored in the 
+machine's default store. This facility is provided to assist with operation 
+on multi homed machines. 
+The default is
+.Dq yes .
+Note that this option applies only to protocol version 2 GSSAPI connections,
+and setting it to 
+.Dq no
+may only work with recent Kerberos GSSAPI libraries.
+.It Cm GSSAPIStoreCredentialsOnRekey
+Controls whether the user's GSSAPI credentials should be updated following a 
+successful connection rekeying. This option can be used to accepted renewed 
+or updated credentials from a compatible client. The default is
+.Dq no .
 .It Cm HostbasedAuthentication
 Specifies whether rhosts or /etc/hosts.equiv authentication together
 with successful public key client host authentication is allowed
@@ -894,6 +952,121 @@
 .Pp
 To disable TCP keepalive messages, the value should be set to
 .Dq no .
+.It Cm UsageStatsTargets
+This option can be used to specify the target collector hosts to which usage
+metrics should be reported. This setting will be ignored if
+.Cm DisableUsageStats
+is enabled. Multiple targets can be specified separated by comma(s), but no
+space(s). Each target specification is of the format
+.Pa host:port[!tags].
+Tags control what data elements are reported. The following list specifies
+the tags for the corresponding data elements.
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm V
+.Sm off
+- OpenSSH version, reported by default.
+.Sm on
+.It
+.Cm v
+.Sm off
+- SSL version, reported by default.
+.Sm on
+.It
+.Cm M
+.Sm off
+- User authentication method used such as "gssapi-keyex", "gssapi-with-mic", etc. Reported by default.
+.Sm on
+.It
+.Cm m
+.Sm off
+- User authentication mechanism used such as "GSI", "Kerberos", etc. Reported by default.
+.Sm on
+.It
+.Cm I
+.Sm off
+- Client IP address. Not reported by default.
+.Sm on
+.It
+.Cm u
+.Sm off
+- User name. Not reported by default.
+.Sm on
+.It
+.Cm U
+.Sm off
+- User DN. Not reported by default.
+.Sm on
+.Pp
+In addition to the above selected information, the following data are
+reported to ALL the specified/default target collectors. There's no way to
+exclude these from being reported other than by disabling the reporting of
+usage metrics altogether:
+.Pp
+.It
+.Cm Component code
+.Sm off
+- 12 for GSI OpenSSH
+.Sm on
+.It
+.Cm Component Data Format version
+.Sm off
+- 0 currently
+.Sm on
+.It
+.Cm IP Address
+.Sm off
+- IP address of reporting server
+.Sm on
+.It
+.Cm Timestamp
+.It
+.Cm Hostname
+.Sm off
+- Host name of reporting server
+.Sm on
+.Pp
+If no tags are specified in a host spec, or the special string
+.Dq default
+is specified, the tags
+.Dq VvMm
+are assumed. A site could choose to allow a
+different set of data to be reported by specifying a different tag set. The
+last 3 tags
+.Dq I ,
+.Dq u
+and
+.Dq U
+above are more meant for a local collector that a
+site might like to deploy since they could be construed as private information.
+The special string
+.Dq all
+denotes all tags.
+.El
+.Pp
+By default, Usage Metrics reporting is sent to
+.Dq usage-stats.cilogon.org:4810 .
+This can be made explicit by specifying
+.Dq default
+(all by itself) for the
+target specification as in:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm UsageStatsTargets
+.Sm off
+default
+.Sm on
+.El
+.Pp
+If
+.Cm UsageStatsTargets
+is not specified, a comma-separated list of targets
+(without any tags specified) if specified in the environment variable
+.Cm GLOBUS_USAGE_TARGETS
+will be used.
+.Pp
 .It Cm TrustedUserCAKeys
 Specifies a file containing public keys of certificate authorities that are
 trusted to sign user certificates for authentication.
@@ -961,6 +1134,12 @@
 as a non-root user.
 The default is
 .Dq no .
+.It Cm PermitPAMUserChange
+If set to
+.Dq yes
+this will enable PAM authentication to change the name of the user being
+authenticated.  The default is
+.Dq no .
 .It Cm UsePrivilegeSeparation
 Specifies whether
 .Xr sshd 8
diff -Naur --exclude=autom4te.cache openssh-5.5p1/version.h openssh-5.5p1-gssapi/version.h
--- openssh-5.5p1/version.h	2010-03-21 13:59:22.000000000 -0500
+++ openssh-5.5p1-gssapi/version.h	2010-04-20 10:49:30.000000000 -0500
@@ -1,6 +1,28 @@
 /* $OpenBSD: version.h,v 1.58 2010/03/16 16:36:49 djm Exp $ */
 
+#ifdef GSI
+#define GSI_VERSION	" GSI"
+#else
+#define GSI_VERSION	""
+#endif
+
+#ifdef KRB5
+#define KRB5_VERSION	" KRB5"
+#else
+#define KRB5_VERSION	""
+#endif
+
+#ifdef MECHGLUE
+#define MGLUE_VERSION	" MECHGLUE"
+#else
+#define MGLUE_VERSION	""
+#endif
+
+#define NCSA_VERSION	" GSI_GSSAPI_20100420"
+
 #define SSH_VERSION	"OpenSSH_5.5"
 
 #define SSH_PORTABLE	"p1"
-#define SSH_RELEASE	SSH_VERSION SSH_PORTABLE
+#define SSH_HPN         "-hpn13v6"
+#define SSH_RELEASE	SSH_VERSION SSH_PORTABLE SSH_HPN \
+            NCSA_VERSION GSI_VERSION KRB5_VERSION MGLUE_VERSION
