File openssh-5.8p1-kex.patch of Package openssh.openSUSE_12.1_Update
diff -Naur --exclude=autom4te.cache openssh-5.8p2/ChangeLog.gssapi openssh-5.8p2-gssapi/ChangeLog.gssapi
--- openssh-5.8p2/ChangeLog.gssapi 1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.8p2-gssapi/ChangeLog.gssapi 2011-05-31 12:54:34.000000000 -0500
@@ -0,0 +1,113 @@
+20110101
+ - Finally update for OpenSSH 5.6p1
+ - Add GSSAPIServerIdentity option from Jim Basney
+
+20100308
+ - [ Makefile.in, key.c, key.h ]
+ Updates for OpenSSH 5.4p1
+ - [ servconf.c ]
+ Include GSSAPI options in the sshd -T configuration dump, and flag
+ some older configuration options as being unsupported. Thanks to Colin
+ Watson.
+ -
+
+20100124
+ - [ sshconnect2.c ]
+ Adapt to deal with additional element in Authmethod structure. Thanks to
+ Colin Watson
+
+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.8p2/HPN-README openssh-5.8p2-gssapi/HPN-README
--- openssh-5.8p2/HPN-README 1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.8p2-gssapi/HPN-README 2011-05-31 12:54:34.000000000 -0500
@@ -0,0 +1,128 @@
+Notes:
+
+MULTI-THREADED CIPHER:
+The AES cipher in CTR mode has been multithreaded (MTR-AES-CTR). This will allow ssh installations
+on hosts with multiple cores to use more than one processing core during encryption.
+Tests have show significant throughput performance increases when using MTR-AES-CTR up
+to and including a full gigabit per second on quad core systems. It should be possible to
+achieve full line rate on dual core systems but OS and data management overhead makes this
+more difficult to achieve. The cipher stream from MTR-AES-CTR is entirely compatible with single
+thread AES-CTR (ST-AES-CTR) implementations and should be 100% backward compatible. Optimal
+performance requires the MTR-AES-CTR mode be enabled on both ends of the connection.
+The MTR-AES-CTR replaces ST-AES-CTR and is used in exactly the same way with the same
+nomenclature.
+Use examples: ssh -caes128-ctr you@host.com
+ scp -oCipher=aes256-ctr file you@host.com:~/file
+
+NONE CIPHER:
+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). The MT-AES-CTR cipher was
+ implemented by Ben Bennet (ben@psc.edu). This work was financed, in part,
+ by Cisco System, Inc., the National Library of Medicine,
+ and the National Science Foundation.
diff -Naur --exclude=autom4te.cache openssh-5.8p2/LICENSE.globus_usage openssh-5.8p2-gssapi/LICENSE.globus_usage
--- openssh-5.8p2/LICENSE.globus_usage 1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.8p2-gssapi/LICENSE.globus_usage 2011-05-31 12:54:34.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.8p2/Makefile.in openssh-5.8p2-gssapi/Makefile.in
--- openssh-5.8p2/Makefile.in 2011-02-03 18:42:13.000000000 -0600
+++ openssh-5.8p2-gssapi/Makefile.in 2011-05-31 12:54:34.000000000 -0500
@@ -63,6 +63,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)
@@ -75,6 +76,7 @@
atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
+ kexgssc.o \
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \
schnorr.o ssh-pkcs11.o
@@ -91,9 +93,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 kexecdhs.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 \
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
@@ -293,6 +297,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 \
@@ -372,6 +390,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)
@@ -386,6 +409,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.8p2/auth-krb5.c openssh-5.8p2-gssapi/auth-krb5.c
--- openssh-5.8p2/auth-krb5.c 2009-12-20 17:49:22.000000000 -0600
+++ openssh-5.8p2-gssapi/auth-krb5.c 2011-05-31 12:54:34.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.8p2/auth-pam.c openssh-5.8p2-gssapi/auth-pam.c
--- openssh-5.8p2/auth-pam.c 2009-07-12 07:07:21.000000000 -0500
+++ openssh-5.8p2-gssapi/auth-pam.c 2011-05-31 12:54:34.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
@@ -122,6 +122,10 @@
*/
typedef pthread_t sp_pthread_t;
#else
+#define pthread_create openssh_pthread_create
+#define pthread_exit openssh_pthread_exit
+#define pthread_cancel openssh_pthread_cancel
+#define pthread_join openssh_pthread_join
typedef pid_t sp_pthread_t;
#endif
@@ -272,6 +276,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 +341,7 @@
static void
import_environments(Buffer *b)
{
- char *env;
+ char *env, *user;
u_int i, num_env;
int err;
@@ -304,6 +351,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 +525,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 +548,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 +969,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 +1274,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.8p2/auth-pam.h openssh-5.8p2-gssapi/auth-pam.h
--- openssh-5.8p2/auth-pam.h 2004-09-11 07:17:26.000000000 -0500
+++ openssh-5.8p2-gssapi/auth-pam.h 2011-05-31 12:54:34.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.8p2/auth.c openssh-5.8p2-gssapi/auth.c
--- openssh-5.8p2/auth.c 2010-11-30 19:21:51.000000000 -0600
+++ openssh-5.8p2-gssapi/auth.c 2011-05-31 12:54:34.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];
@@ -568,6 +587,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();
@@ -587,7 +610,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.8p2/auth.h openssh-5.8p2-gssapi/auth.h
--- openssh-5.8p2/auth.h 2010-05-09 20:58:03.000000000 -0500
+++ openssh-5.8p2-gssapi/auth.h 2011-05-31 12:54:34.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.8p2/auth2-gss.c openssh-5.8p2-gssapi/auth2-gss.c
--- openssh-5.8p2/auth2-gss.c 2007-12-02 05:59:45.000000000 -0600
+++ openssh-5.8p2-gssapi/auth2-gss.c 2011-05-31 12:54:34.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.8p2/auth2.c openssh-5.8p2-gssapi/auth2.c
--- openssh-5.8p2/auth2.c 2010-08-31 07:36:39.000000000 -0500
+++ openssh-5.8p2-gssapi/auth2.c 2011-05-31 12:54:34.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
@@ -221,20 +227,67 @@
if (authctxt == NULL)
fatal("input_userauth_request: no authctxt");
- user = packet_get_cstring(NULL);
- service = packet_get_cstring(NULL);
- method = packet_get_cstring(NULL);
- debug("userauth-request for user %s service %s method %s", user, service, method);
+ user = packet_get_string(NULL);
+ service = packet_get_string(NULL);
+ method = packet_get_string(NULL);
+
+#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.8p2/buffer.c openssh-5.8p2-gssapi/buffer.c
--- openssh-5.8p2/buffer.c 2010-02-11 16:23:40.000000000 -0600
+++ openssh-5.8p2-gssapi/buffer.c 2011-05-31 12:54:34.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.8p2/buffer.h openssh-5.8p2-gssapi/buffer.h
--- openssh-5.8p2/buffer.h 2010-09-09 20:39:27.000000000 -0500
+++ openssh-5.8p2-gssapi/buffer.h 2011-05-31 12:54:34.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.8p2/canohost.c openssh-5.8p2-gssapi/canohost.c
--- openssh-5.8p2/canohost.c 2010-10-11 21:28:12.000000000 -0500
+++ openssh-5.8p2-gssapi/canohost.c 2011-05-31 12:54:34.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.8p2/canohost.h openssh-5.8p2-gssapi/canohost.h
--- openssh-5.8p2/canohost.h 2009-06-21 04:50:08.000000000 -0500
+++ openssh-5.8p2-gssapi/canohost.h 2011-05-31 12:54:34.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.8p2/channels.c openssh-5.8p2-gssapi/channels.c
--- openssh-5.8p2/channels.c 2010-11-30 19:02:35.000000000 -0600
+++ openssh-5.8p2-gssapi/channels.c 2011-05-31 12:54:34.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;
@@ -808,11 +815,37 @@
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;
+#if 0 /* too verbose */
+ debug2("tcpwinsz: %d for connection: %d", tcpwinsz,
+ packet_get_connection_in());
+#endif
+ 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 &&
@@ -1789,14 +1822,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;
@@ -2128,11 +2168,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];
@@ -2180,7 +2221,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);
}
@@ -2210,7 +2251,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;
}
@@ -2245,12 +2286,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);
}
@@ -2634,6 +2676,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,
@@ -2787,9 +2838,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;
@@ -3334,10 +3391,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.8p2/channels.h openssh-5.8p2-gssapi/channels.h
--- openssh-5.8p2/channels.h 2010-05-20 23:57:10.000000000 -0500
+++ openssh-5.8p2-gssapi/channels.h 2011-05-31 12:54:34.000000000 -0500
@@ -125,8 +125,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 */
@@ -161,9 +163,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)
@@ -237,7 +241,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);
@@ -294,4 +298,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.8p2/cipher.c openssh-5.8p2-gssapi/cipher.c
--- openssh-5.8p2/cipher.c 2009-01-27 23:38:41.000000000 -0600
+++ openssh-5.8p2-gssapi/cipher.c 2011-05-31 12:54:34.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.8p2/clientloop.c openssh-5.8p2-gssapi/clientloop.c
--- openssh-5.8p2/clientloop.c 2011-01-16 06:18:35.000000000 -0600
+++ openssh-5.8p2-gssapi/clientloop.c 2011-05-31 12:54:34.000000000 -0500
@@ -111,6 +111,10 @@
#include "msg.h"
#include "roaming.h"
+#ifdef GSSAPI
+#include "ssh-gss.h"
+#endif
+
/* import options */
extern Options options;
@@ -1483,6 +1487,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;
@@ -1768,9 +1781,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;
}
@@ -1790,9 +1809,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;
@@ -1820,10 +1845,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.8p2/compat.c openssh-5.8p2-gssapi/compat.c
--- openssh-5.8p2/compat.c 2008-11-03 02:20:14.000000000 -0600
+++ openssh-5.8p2-gssapi/compat.c 2011-05-31 12:54:34.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.8p2/compat.h openssh-5.8p2-gssapi/compat.h
--- openssh-5.8p2/compat.h 2008-11-03 02:20:14.000000000 -0600
+++ openssh-5.8p2-gssapi/compat.h 2011-05-31 12:54:34.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.8p2/config.h.in openssh-5.8p2-gssapi/config.h.in
--- openssh-5.8p2/config.h.in 2011-05-04 20:58:07.000000000 -0500
+++ openssh-5.8p2-gssapi/config.h.in 2011-05-31 12:54:38.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 */
@@ -149,6 +155,9 @@
/* Define if your system glob() function has gl_statv options in glob_t */
#undef GLOB_HAS_GL_STATV
+/* Define if you want GSI/Globus authentication support. */
+#undef GSI
+
/* Define this if you want GSSAPI support in the version 2 protocol */
#undef GSSAPI
@@ -473,6 +482,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
@@ -1262,6 +1281,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
@@ -1329,6 +1351,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
@@ -1417,6 +1442,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
@@ -1432,6 +1460,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.8p2/configure openssh-5.8p2-gssapi/configure
--- openssh-5.8p2/configure 2011-05-04 20:58:10.000000000 -0500
+++ openssh-5.8p2-gssapi/configure 2011-05-31 12:54:40.000000000 -0500
@@ -722,6 +722,7 @@
INSTALL_SSH_PRNG_CMDS
SSHLIBS
SSHDLIBS
+INSTALL_GSISSH
KRB5CONF
PRIVSEP_PATH
xauth_path
@@ -1333,6 +1334,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
@@ -1359,7 +1364,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
@@ -1822,6 +1830,161 @@
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
+ LD_LIBRARY_PATH="${gsi_path}/lib:$LD_LIBRARY_PATH"
+ export LD_LIBRARY_PATH
+ 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
+
+ if test -z "$LOOK_FOR_FC_GLOBUS_INCLUDE" ; then
+ GLOBUS_INCLUDE="${gsi_path}/include/${globus_flavor_type}"
+ else
+ GLOBUS_INCLUDE="${gsi_path}/include/globus"
+ fi
+ 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 globus_usage | 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 globus_usage | 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'
@@ -7729,64 +7892,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
@@ -7825,6 +7938,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; }
@@ -17321,7 +17545,9 @@
fi
+if test -z "$GLOBUS_LDFLAGS" ; then
LIBS="-lcrypto $LIBS"
+fi
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
@@ -27910,46 +28136,492 @@
-# 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
+# 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. */
- KRB5_MSG="yes"
+int
+main ()
+{
- # 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"
+ ;
+ 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
+
+
+ { { echo "$as_me:$LINENO: error: link with Globus libraries failed" >&5
+echo "$as_me: error: link with Globus libraries failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+
+fi
+
+rm -f core 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
+
+
+{ echo "$as_me:$LINENO: checking for globus_usage_stats_send" >&5
+echo $ECHO_N "checking for globus_usage_stats_send... $ECHO_C" >&6; }
+if test "${ac_cv_func_globus_usage_stats_send+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 globus_usage_stats_send to an innocuous variant, in case <limits.h> declares globus_usage_stats_send.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define globus_usage_stats_send innocuous_globus_usage_stats_send
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char globus_usage_stats_send (); 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 globus_usage_stats_send
+
+/* 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 ();
+/* 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_globus_usage_stats_send || defined __stub___globus_usage_stats_send
+choke me
+#endif
+
+int
+main ()
+{
+return globus_usage_stats_send ();
+ ;
+ 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_func_globus_usage_stats_send=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_globus_usage_stats_send=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_globus_usage_stats_send" >&5
+echo "${ECHO_T}$ac_cv_func_globus_usage_stats_send" >&6; }
+if test $ac_cv_func_globus_usage_stats_send = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GLOBUS_USAGE 1
+_ACEOF
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for globus_usage_stats_send_array" >&5
+echo $ECHO_N "checking for globus_usage_stats_send_array... $ECHO_C" >&6; }
+if test "${ac_cv_func_globus_usage_stats_send_array+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 globus_usage_stats_send_array to an innocuous variant, in case <limits.h> declares globus_usage_stats_send_array.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define globus_usage_stats_send_array innocuous_globus_usage_stats_send_array
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char globus_usage_stats_send_array (); 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 globus_usage_stats_send_array
+
+/* 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 ();
+/* 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_globus_usage_stats_send_array || defined __stub___globus_usage_stats_send_array
+choke me
+#endif
+
+int
+main ()
+{
+return globus_usage_stats_send_array ();
+ ;
+ 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_func_globus_usage_stats_send_array=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_globus_usage_stats_send_array=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_globus_usage_stats_send_array" >&5
+echo "${ECHO_T}$ac_cv_func_globus_usage_stats_send_array" >&6; }
+if test $ac_cv_func_globus_usage_stats_send_array = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GLOBUS_USAGE_SEND_ARRAY 1
+_ACEOF
+
+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
@@ -28889,7 +29561,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
@@ -29430,6 +30253,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
@@ -29511,7 +30389,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;
@@ -31485,6 +32366,7 @@
INSTALL_SSH_PRNG_CMDS!$INSTALL_SSH_PRNG_CMDS$ac_delim
SSHLIBS!$SSHLIBS$ac_delim
SSHDLIBS!$SSHDLIBS$ac_delim
+INSTALL_GSISSH!$INSTALL_GSISSH$ac_delim
KRB5CONF!$KRB5CONF$ac_delim
PRIVSEP_PATH!$PRIVSEP_PATH$ac_delim
xauth_path!$xauth_path$ac_delim
@@ -31499,7 +32381,7 @@
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 21; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 22; 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.8p2/configure.ac openssh-5.8p2-gssapi/configure.ac
--- openssh-5.8p2/configure.ac 2011-02-03 18:42:14.000000000 -0600
+++ openssh-5.8p2-gssapi/configure.ac 2011-05-31 12:54:34.000000000 -0500
@@ -31,6 +31,121 @@
}])
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
+ LD_LIBRARY_PATH="${gsi_path}/lib:$LD_LIBRARY_PATH"
+ export LD_LIBRARY_PATH
+ 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
+
+ if test -z "$LOOK_FOR_FC_GLOBUS_INCLUDE" ; then
+ GLOBUS_INCLUDE="${gsi_path}/include/${globus_flavor_type}"
+ else
+ GLOBUS_INCLUDE="${gsi_path}/include/globus"
+ fi
+ 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 globus_usage | 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 globus_usage | 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
@@ -493,16 +608,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)
@@ -514,6 +621,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])
@@ -2016,7 +2147,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>]),
@@ -3522,6 +3655,68 @@
AC_SUBST(SSHLIBS)
AC_SUBST(SSHDLIBS)
+# 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)
+
+dnl
+dnl Check for globus_usage_stats_send
+dnl
+AC_CHECK_FUNC(globus_usage_stats_send,
+ AC_DEFINE([HAVE_GLOBUS_USAGE], 1, [Have Globus Usage]))
+
+dnl
+dnl Check for globus_usage_stats_send_array
+dnl
+AC_CHECK_FUNC(globus_usage_stats_send_array,
+ AC_DEFINE([HAVE_GLOBUS_USAGE_SEND_ARRAY], 1,
+ [Have Globus Usage send_array]))
+
+# 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,
@@ -3610,7 +3805,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
@@ -3629,6 +3838,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
@@ -3664,7 +3909,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.8p2/defines.h openssh-5.8p2-gssapi/defines.h
--- openssh-5.8p2/defines.h 2011-01-17 04:15:31.000000000 -0600
+++ openssh-5.8p2-gssapi/defines.h 2011-05-31 12:54:34.000000000 -0500
@@ -385,6 +385,8 @@
# define _PATH_DEVNULL "/dev/null"
#endif
+#ifndef PATH_MAILDIR_IN_PATHS_H
+
#ifndef MAIL_DIRECTORY
# define MAIL_DIRECTORY "/var/spool/mail"
#endif
@@ -397,6 +399,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.8p2/gss-genr.c openssh-5.8p2-gssapi/gss-genr.c
--- openssh-5.8p2/gss-genr.c 2009-06-22 01:11:07.000000000 -0500
+++ openssh-5.8p2-gssapi/gss-genr.c 2011-05-31 12:54:34.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.8p2/gss-serv-gsi.c openssh-5.8p2-gssapi/gss-serv-gsi.c
--- openssh-5.8p2/gss-serv-gsi.c 1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.8p2-gssapi/gss-serv-gsi.c 2011-05-31 12:54:34.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[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.8p2/gss-serv-krb5.c openssh-5.8p2-gssapi/gss-serv-krb5.c
--- openssh-5.8p2/gss-serv-krb5.c 2006-09-01 00:38:36.000000000 -0500
+++ openssh-5.8p2-gssapi/gss-serv-krb5.c 2011-05-31 12:54:34.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.8p2/gss-serv.c openssh-5.8p2-gssapi/gss-serv.c
--- openssh-5.8p2/gss-serv.c 2008-05-19 00:05:07.000000000 -0500
+++ openssh-5.8p2-gssapi/gss-serv.c 2011-05-31 12:54:34.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");
@@ -326,8 +454,9 @@
}
/* Privileged */
+/* gssapi_keyex arg added for Globus usage */
int
-ssh_gssapi_userok(char *user)
+ssh_gssapi_userok(char *user, struct passwd *pw, int gssapi_keyex)
{
OM_uint32 lmin;
@@ -336,10 +465,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 +489,133 @@
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;
+}
+
+/* added for Globus usage */
+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.8p2/kex.c openssh-5.8p2-gssapi/kex.c
--- openssh-5.8p2/kex.c 2010-09-24 07:11:14.000000000 -0500
+++ openssh-5.8p2-gssapi/kex.c 2011-05-31 12:54:34.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)
@@ -91,7 +96,8 @@
}
/* 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;
@@ -358,6 +364,20 @@
k->kex_type = KEX_ECDH_SHA2;
k->evp_md = kex_ecdh_name_to_evpmd(k->name);
#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);
}
@@ -407,6 +427,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);
@@ -441,11 +468,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.8p2/kex.h openssh-5.8p2-gssapi/kex.h
--- openssh-5.8p2/kex.h 2010-09-24 07:11:14.000000000 -0500
+++ openssh-5.8p2-gssapi/kex.h 2011-05-31 12:54:34.000000000 -0500
@@ -73,6 +73,9 @@
KEX_DH_GEX_SHA1,
KEX_DH_GEX_SHA256,
KEX_ECDH_SHA2,
+ KEX_GSS_GRP1_SHA1,
+ KEX_GSS_GRP14_SHA1,
+ KEX_GSS_GEX_SHA1,
KEX_MAX
};
@@ -129,6 +132,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 *);
@@ -140,6 +149,8 @@
int kex_names_valid(const char *);
+void kex_prop2buf(Buffer *, char *proposal[PROPOSAL_MAX]);
+
Kex *kex_setup(char *[PROPOSAL_MAX]);
void kex_finish(Kex *);
@@ -156,6 +167,16 @@
void kexecdh_client(Kex *);
void kexecdh_server(Kex *);
+#ifdef GSSAPI
+void kexgss_client(Kex *);
+void kexgss_server(Kex *);
+#endif
+
+#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.8p2/kexgssc.c openssh-5.8p2-gssapi/kexgssc.c
--- openssh-5.8p2/kexgssc.c 1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.8p2-gssapi/kexgssc.c 2011-05-31 12:54:34.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.8p2/kexgsss.c openssh-5.8p2-gssapi/kexgsss.c
--- openssh-5.8p2/kexgsss.c 1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.8p2-gssapi/kexgsss.c 2011-05-31 12:54:34.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.8p2/key.c openssh-5.8p2-gssapi/key.c
--- openssh-5.8p2/key.c 2011-02-03 18:48:34.000000000 -0600
+++ openssh-5.8p2-gssapi/key.c 2011-05-31 12:54:34.000000000 -0500
@@ -971,6 +971,8 @@
}
break;
#endif /* OPENSSL_HAS_ECC */
+ case KEY_NULL:
+ return "null";
}
return "ssh-unknown";
}
@@ -1276,6 +1278,8 @@
strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) {
return KEY_ECDSA_CERT;
#endif
+ } else if (strcmp(name, "null") == 0) {
+ return KEY_NULL;
}
debug2("key_type_from_name: unknown key type '%s'", name);
diff -Naur --exclude=autom4te.cache openssh-5.8p2/key.h openssh-5.8p2-gssapi/key.h
--- openssh-5.8p2/key.h 2010-11-04 18:19:49.000000000 -0500
+++ openssh-5.8p2-gssapi/key.h 2011-05-31 12:54:34.000000000 -0500
@@ -44,6 +44,7 @@
KEY_ECDSA_CERT,
KEY_RSA_CERT_V00,
KEY_DSA_CERT_V00,
+ KEY_NULL,
KEY_UNSPEC
};
enum fp_type {
diff -Naur --exclude=autom4te.cache openssh-5.8p2/misc.c openssh-5.8p2-gssapi/misc.c
--- openssh-5.8p2/misc.c 2011-01-12 19:21:36.000000000 -0600
+++ openssh-5.8p2-gssapi/misc.c 2011-05-31 12:54:34.000000000 -0500
@@ -158,11 +158,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)
@@ -170,6 +173,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);
@@ -223,6 +241,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.8p2/misc.h openssh-5.8p2-gssapi/misc.h
--- openssh-5.8p2/misc.h 2010-11-30 18:50:35.000000000 -0600
+++ openssh-5.8p2-gssapi/misc.h 2011-05-31 12:54:34.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.8p2/monitor.c openssh-5.8p2-gssapi/monitor.c
--- openssh-5.8p2/monitor.c 2010-09-09 20:23:34.000000000 -0500
+++ openssh-5.8p2-gssapi/monitor.c 2011-05-31 12:54:34.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);
@@ -1692,6 +1736,13 @@
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
kex->kex[KEX_ECDH_SHA2] = kexecdh_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);
@@ -1898,6 +1949,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;
@@ -1925,6 +1979,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);
@@ -1941,7 +1998,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);
}
@@ -1953,6 +2012,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);
@@ -1978,8 +2040,18 @@
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);
+ if (!options.gss_authentication && !options.gss_keyex)
+ fatal("In GSSAPI monitor when GSSAPI is disabled");
+
+ authenticated = authctxt->valid &&
+ ssh_gssapi_userok(authctxt->user, authctxt->pw, gssapi_keyex);
buffer_clear(m);
buffer_put_int(m, authenticated);
@@ -1987,11 +2059,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.8p2/monitor.h openssh-5.8p2-gssapi/monitor.h
--- openssh-5.8p2/monitor.h 2008-11-04 23:20:46.000000000 -0600
+++ openssh-5.8p2-gssapi/monitor.h 2011-05-31 12:54:34.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.8p2/monitor_wrap.c openssh-5.8p2-gssapi/monitor_wrap.c
--- openssh-5.8p2/monitor_wrap.c 2010-08-31 07:41:14.000000000 -0500
+++ openssh-5.8p2-gssapi/monitor_wrap.c 2011-05-31 12:54:34.000000000 -0500
@@ -1232,12 +1232,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,
@@ -1249,6 +1250,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.8p2/monitor_wrap.h openssh-5.8p2-gssapi/monitor_wrap.h
--- openssh-5.8p2/monitor_wrap.h 2009-03-05 07:58:22.000000000 -0600
+++ openssh-5.8p2-gssapi/monitor_wrap.h 2011-05-31 12:54:34.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.8p2/mux.c openssh-5.8p2-gssapi/mux.c
--- openssh-5.8p2/mux.c 2011-01-13 19:01:32.000000000 -0600
+++ openssh-5.8p2-gssapi/mux.c 2011-05-31 12:54:34.000000000 -0500
@@ -440,6 +440,7 @@
set_nonblock(new_fd[2]);
window = CHAN_SES_WINDOW_DEFAULT;
+
packetmax = CHAN_SES_PACKET_DEFAULT;
if (cctx->want_tty) {
window >>= 1;
diff -Naur --exclude=autom4te.cache openssh-5.8p2/myproposal.h openssh-5.8p2-gssapi/myproposal.h
--- openssh-5.8p2/myproposal.h 2011-01-13 05:00:22.000000000 -0600
+++ openssh-5.8p2-gssapi/myproposal.h 2011-05-31 12:54:34.000000000 -0500
@@ -75,6 +75,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.8p2/openbsd-compat/port-aix.c openssh-5.8p2-gssapi/openbsd-compat/port-aix.c
--- openssh-5.8p2/openbsd-compat/port-aix.c 2009-12-20 17:49:22.000000000 -0600
+++ openssh-5.8p2-gssapi/openbsd-compat/port-aix.c 2011-05-31 12:54:34.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.8p2/packet.c openssh-5.8p2-gssapi/packet.c
--- openssh-5.8p2/packet.c 2010-11-23 17:46:37.000000000 -0600
+++ openssh-5.8p2-gssapi/packet.c 2011-05-31 12:54:34.000000000 -0500
@@ -842,7 +842,7 @@
/*
* Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
*/
-static void
+static int
packet_send2_wrapped(void)
{
u_char type, *cp, *macbuf = NULL;
@@ -961,11 +961,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;
@@ -983,7 +985,7 @@
sizeof(Buffer));
buffer_init(&active_state->outgoing_packet);
TAILQ_INSERT_TAIL(&active_state->outgoing, p, next);
- return;
+ return(sizeof(Buffer));
}
}
@@ -991,7 +993,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) {
@@ -1004,19 +1006,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);
}
/*
@@ -1655,12 +1660,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,
@@ -1668,13 +1675,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);
}
/*
@@ -1861,12 +1869,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) ||
@@ -1958,3 +1978,9 @@
add_recv_bytes(len);
}
}
+
+int
+packet_authentication_state(void)
+{
+ return(active_state->after_authentication);
+}
diff -Naur --exclude=autom4te.cache openssh-5.8p2/packet.h openssh-5.8p2-gssapi/packet.h
--- openssh-5.8p2/packet.h 2010-11-19 22:19:38.000000000 -0600
+++ openssh-5.8p2-gssapi/packet.h 2011-05-31 12:54:34.000000000 -0500
@@ -23,6 +23,12 @@
#include <openssl/ec.h>
#endif
+void
+packet_request_rekeying(void);
+
+void
+packet_request_rekeying(void);
+
void packet_set_connection(int, int);
void packet_set_timeout(int, int);
void packet_set_nonblocking(void);
@@ -38,6 +44,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);
@@ -51,7 +58,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);
@@ -86,7 +93,7 @@
void packet_set_iv(int, u_char *);
void *packet_get_newkeys(int);
-void packet_write_poll(void);
+int packet_write_poll(void);
void 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.8p2/progressmeter.c openssh-5.8p2-gssapi/progressmeter.c
--- openssh-5.8p2/progressmeter.c 2006-08-04 21:39:40.000000000 -0500
+++ openssh-5.8p2-gssapi/progressmeter.c 2011-05-31 12:54:34.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.8p2/readconf.c openssh-5.8p2-gssapi/readconf.c
--- openssh-5.8p2/readconf.c 2010-11-19 22:19:38.000000000 -0600
+++ openssh-5.8p2-gssapi/readconf.c 2011-05-31 12:54:34.000000000 -0500
@@ -129,12 +129,16 @@
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
+ oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
+ oGssServerIdentity,
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
oSendEnv, oControlPath, oControlMaster, oControlPersist,
oHashKnownHosts,
oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
oKexAlgorithms, oIPQoS,
+ oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
+ oHPNBufferSize,
oDeprecated, oUnsupported
} OpCodes;
@@ -169,10 +173,19 @@
{ "afstokenpassing", oUnsupported },
#if defined(GSSAPI)
{ "gssapiauthentication", oGssAuthentication },
+ { "gssapikeyexchange", oGssKeyEx },
{ "gssapidelegatecredentials", oGssDelegateCreds },
+ { "gssapitrustdns", oGssTrustDns },
+ { "gssapiclientidentity", oGssClientIdentity },
+ { "gssapiserveridentity", oGssServerIdentity },
+ { "gssapirenewalforcesrekey", oGssRenewalRekey },
#else
{ "gssapiauthentication", oUnsupported },
+ { "gssapikeyexchange", oUnsupported },
{ "gssapidelegatecredentials", oUnsupported },
+ { "gssapitrustdns", oUnsupported },
+ { "gssapiclientidentity", oUnsupported },
+ { "gssapirenewalforcesrekey", oUnsupported },
#endif
{ "fallbacktorsh", oDeprecated },
{ "usersh", oDeprecated },
@@ -245,7 +258,12 @@
#endif
{ "kexalgorithms", oKexAlgorithms },
{ "ipqos", oIPQoS },
-
+ { "noneenabled", oNoneEnabled },
+ { "tcprcvbufpoll", oTcpRcvBufPoll },
+ { "tcprcvbuf", oTcpRcvBuf },
+ { "noneswitch", oNoneSwitch },
+ { "hpndisabled", oHPNDisabled },
+ { "hpnbuffersize", oHPNBufferSize },
{ NULL, oBadOption }
};
@@ -479,10 +497,30 @@
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 oGssServerIdentity:
+ charptr = &options->gss_server_identity;
+ goto parse_string;
+
+ case oGssRenewalRekey:
+ intptr = &options->gss_renewal_rekey;
+ goto parse_flag;
+
case oBatchMode:
intptr = &options->batch_mode;
goto parse_flag;
@@ -491,6 +529,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;
@@ -669,6 +738,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);
@@ -1092,7 +1165,12 @@
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->gss_server_identity = NULL;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->kbd_interactive_devices = NULL;
@@ -1157,6 +1235,12 @@
options->zero_knowledge_password_authentication = -1;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -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;
}
/*
@@ -1192,9 +1276,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)
@@ -1289,6 +1379,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->control_persist == -1) {
diff -Naur --exclude=autom4te.cache openssh-5.8p2/readconf.h openssh-5.8p2-gssapi/readconf.h
--- openssh-5.8p2/readconf.h 2010-11-19 22:19:38.000000000 -0600
+++ openssh-5.8p2-gssapi/readconf.h 2011-05-31 12:54:34.000000000 -0500
@@ -46,7 +46,12 @@
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 */
+ char *gss_server_identity; /* GSSAPI target principal */
int password_authentication; /* Try password
* authentication. */
int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
@@ -59,6 +64,10 @@
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 */
int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */
int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */
LogLevel log_level; /* Level for logging. */
@@ -81,6 +90,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. */
@@ -107,6 +118,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.8p2/scp.c openssh-5.8p2-gssapi/scp.c
--- openssh-5.8p2/scp.c 2011-01-06 05:41:21.000000000 -0600
+++ openssh-5.8p2-gssapi/scp.c 2011-05-31 12:54:34.000000000 -0500
@@ -727,7 +727,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) {
@@ -909,7 +909,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.8p2/servconf.c openssh-5.8p2-gssapi/servconf.c
--- openssh-5.8p2/servconf.c 2010-11-19 22:19:38.000000000 -0600
+++ openssh-5.8p2-gssapi/servconf.c 2011-05-31 12:54:34.000000000 -0500
@@ -62,6 +62,7 @@
/* Portable-specific options */
options->use_pam = -1;
+ options->permit_pam_user_change = -1;
/* Standard Options */
options->num_ports = 0;
@@ -95,9 +96,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;
@@ -134,9 +145,15 @@
options->adm_forced_command = NULL;
options->chroot_directory = NULL;
options->zero_knowledge_password_authentication = -1;
+ options->disable_usage_stats = 0;
+ options->usage_stats_targets = NULL;
options->revoked_keys_file = NULL;
options->trusted_user_ca_keys = NULL;
options->authorized_principals_file = NULL;
+ options->none_enabled = -1;
+ options->tcp_rcv_buf_poll = -1;
+ options->hpn_disabled = -1;
+ options->hpn_buffer_size = -1;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
}
@@ -144,9 +161,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)
@@ -222,12 +246,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)
@@ -282,6 +320,42 @@
if (options->ip_qos_bulk == -1)
options->ip_qos_bulk = IPTOS_THROUGHPUT;
+ 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;
@@ -294,14 +368,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,
@@ -309,6 +382,9 @@
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
sKerberosGetAFSToken,
sKerberosTgtPassing, sChallengeResponseAuthentication,
+#ifdef SESSION_HOOKS
+ sAllowSessionHooks, sSessionHookStartupCmd, sSessionHookShutdownCmd,
+#endif
sPasswordAuthentication, sKbdInteractiveAuthentication,
sListenAddress, sAddressFamily,
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
@@ -322,11 +398,18 @@
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,
+ sDisUsageStats, sUsageStatsTarg,
sZeroKnowledgePasswordAuthentication, sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
+ sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize,
sKexAlgorithms, sIPQoS,
sDeprecated, sUnsupported
} ServerOpCodes;
@@ -344,8 +427,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 */
@@ -385,11 +470,36 @@
{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
#ifdef GSSAPI
{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
+ { "gssapidelegatecredentials", sGssDelegateCreds, SSHCFG_ALL },
{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
+ { "gssapicleanupcreds", 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 },
+ { "gssapicleanupcreds", 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
+ { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
+ { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
@@ -446,10 +556,16 @@
{ "permitopen", sPermitOpen, SSHCFG_ALL },
{ "forcecommand", sForceCommand, SSHCFG_ALL },
{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
+ { "disableusagestats", sDisUsageStats, SSHCFG_GLOBAL},
+ { "usagestatstargets", sUsageStatsTarg, SSHCFG_GLOBAL},
{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
+ { "noneenabled", sNoneEnabled, SSHCFG_ALL },
+ { "hpndisabled", sHPNDisabled, SSHCFG_ALL },
+ { "hpnbuffersize", sHPNBufferSize, SSHCFG_ALL },
+ { "tcprcvbufpoll", sTcpRcvBufPoll, SSHCFG_ALL },
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
{ "ipqos", sIPQoS, SSHCFG_ALL },
{ NULL, sBadOption, 0 }
@@ -478,6 +594,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;
}
@@ -724,6 +841,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;
@@ -900,6 +1021,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;
@@ -944,10 +1081,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;
@@ -1373,6 +1553,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;
@@ -1489,6 +1702,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);
@@ -1704,7 +1918,10 @@
#endif
#ifdef GSSAPI
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
+ dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);
dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
+ dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
+ dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
#endif
#ifdef JPAKE
dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication,
diff -Naur --exclude=autom4te.cache openssh-5.8p2/servconf.h openssh-5.8p2-gssapi/servconf.h
--- openssh-5.8p2/servconf.h 2010-11-19 22:19:38.000000000 -0600
+++ openssh-5.8p2-gssapi/servconf.h 2011-05-31 12:54:34.000000000 -0500
@@ -94,10 +94,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 */
@@ -151,12 +162,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;
char *authorized_principals_file;
diff -Naur --exclude=autom4te.cache openssh-5.8p2/serverloop.c openssh-5.8p2-gssapi/serverloop.c
--- openssh-5.8p2/serverloop.c 2009-09-08 20:07:28.000000000 -0500
+++ openssh-5.8p2-gssapi/serverloop.c 2011-05-31 12:54:34.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.8p2/session.c openssh-5.8p2-gssapi/session.c
--- openssh-5.8p2/session.c 2010-11-30 19:02:59.000000000 -0600
+++ openssh-5.8p2-gssapi/session.c 2011-05-31 12:54:34.000000000 -0500
@@ -125,6 +125,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;
@@ -232,6 +237,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,
@@ -279,6 +285,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);
}
@@ -808,6 +829,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));
@@ -1036,6 +1077,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.
@@ -1199,6 +1351,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) {
@@ -1613,6 +1782,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();
@@ -1725,6 +1906,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 */
@@ -1805,7 +2021,7 @@
/* Execute the shell. */
argv[0] = argv0;
argv[1] = NULL;
- execve(shell, argv, env);
+ execve(shell, argv, environ);
/* Executing the shell failed. */
perror(shell);
@@ -1819,7 +2035,7 @@
argv[1] = "-c";
argv[2] = (char *) command;
argv[3] = NULL;
- execve(shell, argv, env);
+ execve(shell, argv, environ);
perror(shell);
exit(1);
}
@@ -2271,10 +2487,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,
ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
1, is_tty, CHAN_SES_WINDOW_DEFAULT);
+ else
+ channel_set_fds(s->chanid,
+ fdout, fdin, fderr,
+ ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
+ 1, is_tty, options.hpn_buffer_size);
}
/*
diff -Naur --exclude=autom4te.cache openssh-5.8p2/sftp.1 openssh-5.8p2-gssapi/sftp.1
--- openssh-5.8p2/sftp.1 2010-12-04 16:02:48.000000000 -0600
+++ openssh-5.8p2-gssapi/sftp.1 2011-05-31 12:54:34.000000000 -0500
@@ -241,7 +241,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.8p2/sftp.c openssh-5.8p2-gssapi/sftp.c
--- openssh-5.8p2/sftp.c 2010-12-04 16:02:48.000000000 -0600
+++ openssh-5.8p2-gssapi/sftp.c 2011-05-31 12:54:34.000000000 -0500
@@ -69,7 +69,7 @@
#include "sftp-client.h"
#define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */
-#define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */
+#define DEFAULT_NUM_REQUESTS 256 /* # concurrent outstanding requests */
/* File to read commands from */
FILE* infile;
diff -Naur --exclude=autom4te.cache openssh-5.8p2/ssh-globus-usage.c openssh-5.8p2-gssapi/ssh-globus-usage.c
--- openssh-5.8p2/ssh-globus-usage.c 1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.8p2-gssapi/ssh-globus-usage.c 2011-05-31 12:54:34.000000000 -0500
@@ -0,0 +1,396 @@
+/*
+ * 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 "includes.h"
+
+#ifdef HAVE_GLOBUS_USAGE
+
+#include <stdarg.h>
+#include <unistd.h>
+
+#include "log.h"
+#include "ssh-globus-usage.h"
+
+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 STATS 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, ',') || 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);
+ }
+
+ result = GLOBUS_SUCCESS;
+ 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;
+ if (globus_usage_stats_handle_init(
+ &usage_ent->handle,
+ SSH_GLOBUS_USAGE_ID,
+ SSH_GLOBUS_USAGE_VER,
+ usage_ent->target) != GLOBUS_SUCCESS)
+ {
+ error("USAGE-STATS: Error initializing (%s) (%s)",
+ usage_ent->target?:"NULL",
+ usage_ent->taglist?:"NULL");
+ result = GLOBUS_FAILURE;
+ } else
+ debug("USAGE-STATS: Initialized (%s) (%s)", usage_ent->target?:"NULL",
+ usage_ent->taglist?:"NULL");
+
+ }
+
+ 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)
+ continue;
+
+ 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.8p2/ssh-globus-usage.h openssh-5.8p2-gssapi/ssh-globus-usage.h
--- openssh-5.8p2/ssh-globus-usage.h 1969-12-31 18:00:00.000000000 -0600
+++ openssh-5.8p2-gssapi/ssh-globus-usage.h 2011-05-31 12:54:34.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.8p2/ssh-gss.h openssh-5.8p2-gssapi/ssh-gss.h
--- openssh-5.8p2/ssh-gss.h 2007-06-12 08:40:39.000000000 -0500
+++ openssh-5.8p2-gssapi/ssh-gss.h 2011-05-31 12:54:34.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; /* needed for globus_gss_assist_map_and_authorize() */
+ 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.8p2/ssh.1 openssh-5.8p2-gssapi/ssh.1
--- openssh-5.8p2/ssh.1 2010-11-19 22:21:03.000000000 -0600
+++ openssh-5.8p2-gssapi/ssh.1 2011-05-31 12:54:34.000000000 -0500
@@ -1176,8 +1176,38 @@
explicitly, as that
will render the X11 connection insecure (and will require the user to
manually copy any required authorization cookies).
+.It Ev GSSAPI_MECH_CONF
+Applies to mechglue used to support both GSI and Kerberos GSSAPI mechanisms.
+Used to specify the location of the mech.conf file that lists the mechanism-
+specific GSSAPI libraries (both Kerberos and GSI versions). If
+.Ev GSSAPI_MECH_CONF
+is not set then /etc/mech.conf is used. This applies to both the clients and
+the server. The NCSA GSSAPI mechglue distribution includes a sample mech.conf
+file. You will need to edit the library paths in that file and install it in
+an appropriate location on your system. If the mech.conf file is not found,
+the GSSAPI mechglue library will not load any GSSAPI mechanisms and GSI-OpenSSH
+will simply skip GSSAPI authentication.
.It Ev HOME
Set to the path of the user's home directory.
+.It LD_LIBRARY_PATH
+The ssh client is typically linked dynamically with Globus
+security libraries, which must be present in the dynamic linker's
+search path. This typically requires
+.Cm $GLOBUS_LOCATION/lib
+to be included in the list in the
+.Ev LD_LIBRARY_PATH
+environment variable, which is set by the
+.Cm $GLOBUS_LOCATION/libexec/globus-script-initializer
+script, which should be called from any
+.Cm ssh
+invocation script.
+Alternatively, to set
+.Ev LD_LIBRARY_PATH
+appropriately for the Globus libraries in an interactive shell, source
+.Cm $GLOBUS_LOCATION/etc/globus-user-env.sh
+(for sh shells) or
+.Cm $GLOBUS_LOCATION/etc/globus-user.env.csh
+(for csh shells).
.It Ev LOGNAME
Synonym for
.Ev USER ;
@@ -1236,6 +1266,18 @@
on to new connections).
.It Ev USER
Set to the name of the user logging in.
+.It Ev X509_CERT_DIR
+Used for GSI authentication. Specifies a non-standard location for the
+CA certificates directory.
+.It Ev X509_USER_CERT
+Used for GSI authentication. Specifies a non-standard location for the
+certificate to be used for authentication to the server.
+.It Ev X509_USER_KEY
+Used for GSI authentication. Specifies a non-standard location for the
+private key to be used for authentication to the server.
+.It Ev X509_USER_PROXY
+Used for GSI authentication. Specifies a non-standard location for the
+proxy credential to be used for authentication to the server.
.El
.Pp
Additionally,
diff -Naur --exclude=autom4te.cache openssh-5.8p2/ssh.c openssh-5.8p2-gssapi/ssh.c
--- openssh-5.8p2/ssh.c 2011-02-03 18:42:15.000000000 -0600
+++ openssh-5.8p2-gssapi/ssh.c 2011-05-31 12:54:34.000000000 -0500
@@ -543,9 +543,6 @@
no_shell_flag = 1;
no_tty_flag = 1;
break;
- case 'T':
- no_tty_flag = 1;
- break;
case 'o':
dummy = 1;
line = xstrdup(optarg);
@@ -554,6 +551,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;
@@ -664,6 +668,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))
@@ -684,8 +714,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) {
@@ -1330,6 +1363,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);
@@ -1350,9 +1386,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;
}
@@ -1360,7 +1462,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.8p2/ssh_config openssh-5.8p2-gssapi/ssh_config
--- openssh-5.8p2/ssh_config 2010-01-12 02:40:27.000000000 -0600
+++ openssh-5.8p2-gssapi/ssh_config 2011-05-31 12:54:34.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.8p2/ssh_config.5 openssh-5.8p2-gssapi/ssh_config.5
--- openssh-5.8p2/ssh_config.5 2010-12-25 21:26:48.000000000 -0600
+++ openssh-5.8p2-gssapi/ssh_config.5 2011-05-31 12:54:34.000000000 -0500
@@ -55,6 +55,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
@@ -506,13 +512,45 @@
.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 GSSAPIServerIdentity
+If set, specifies the GSSAPI server identity that ssh should expect when
+connecting to the server. The default is unset, which means that the
+expected GSSAPI server identity will be determined from the target
+hostname.
.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
@@ -825,7 +863,7 @@
.Cm password ) .
The default is:
.Bd -literal -offset indent
-gssapi-with-mic,hostbased,publickey,
+gssapi-keyex,gssapi-with-mic,hostbased,publickey,
keyboard-interactive,password
.Ed
.It Cm Protocol
diff -Naur --exclude=autom4te.cache openssh-5.8p2/sshconnect.c openssh-5.8p2-gssapi/sshconnect.c
--- openssh-5.8p2/sshconnect.c 2011-01-16 06:17:59.000000000 -0600
+++ openssh-5.8p2-gssapi/sshconnect.c 2011-05-31 12:54:34.000000000 -0500
@@ -182,6 +182,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
@@ -204,6 +229,8 @@
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);
@@ -213,6 +240,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;
@@ -556,7 +586,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.8p2/sshconnect2.c openssh-5.8p2-gssapi/sshconnect2.c
--- openssh-5.8p2/sshconnect2.c 2010-11-30 19:21:51.000000000 -0600
+++ openssh-5.8p2-gssapi/sshconnect2.c 2011-05-31 12:54:34.000000000 -0500
@@ -81,6 +81,12 @@
extern char *client_version_string;
extern char *server_version_string;
extern Options options;
+extern Kex *xxx_kex;
+
+/* tty_flag is set in ssh.c. use this in ssh_userauth2 */
+/* if it is set then prevent the switch to the null cipher */
+
+extern int tty_flag;
/*
* SSH2 key exchange
@@ -159,9 +165,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;
@@ -196,6 +227,17 @@
if (options.kex_algorithms != NULL)
myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
+#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);
@@ -206,10 +248,30 @@
kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
kex->kex[KEX_ECDH_SHA2] = kexecdh_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;
+ if (options.gss_server_identity) {
+ kex->gss_host = options.gss_server_identity;
+ } else {
+ kex->gss_host = gss_host;
+ }
+ }
+#endif
+
xxx_kex = kex;
dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -304,6 +366,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 *);
@@ -319,6 +382,11 @@
Authmethod authmethods[] = {
#ifdef GSSAPI
+ {"gssapi-keyex",
+ userauth_gsskeyex,
+ NULL,
+ &options.gss_authentication,
+ NULL},
{"gssapi-with-mic",
userauth_gssapi,
NULL,
@@ -419,6 +487,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);
}
@@ -625,19 +715,36 @@
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_server_identity)
+ gss_host = (char *)options.gss_server_identity;
+ else 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++;
@@ -701,7 +808,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 {
@@ -734,8 +842,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");
@@ -845,6 +953,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.8p2/sshd.8 openssh-5.8p2-gssapi/sshd.8
--- openssh-5.8p2/sshd.8 2010-11-04 18:20:14.000000000 -0500
+++ openssh-5.8p2-gssapi/sshd.8 2011-05-31 12:54:34.000000000 -0500
@@ -753,6 +753,73 @@
# A CA key, accepted for any host in *.mydomain.com or *.mydomain.org
@cert-authority *.mydomain.org,*.mydomain.com ssh-rsa AAAAB5W...
.Ed
+.Sh ENVIRONMENT
+.Nm
+will normally set the following environment variables:
+.Bl -tag -width "SSH_ORIGINAL_COMMAND"
+.It Ev GLOBUS_USAGE_OPTOUT
+Setting this environment variable to "1" will disable the reporting
+of usage metrics. Usage metrics can also be disabled using the
+.Cm DisableUsageStats
+setting in
+.Xr sshd_config 5 .
+.It Ev GLOBUS_USAGE_TARGETS
+If
+.Cm UsageStatsTargets
+is not specified in
+.Xr sshd_config 5 ,
+a comma-separated list of targets (without any tags specified) if
+specified in the environment variable
+.Ev GLOBUS_USAGE_TARGETS
+will be used.
+.It Ev GRIDMAP
+Applies to GSI authentication/authorization. Specifies the location of the
+gridmapfile. If not specified, the gridmap file is assumed to be available at
+/etc/grid-security/grid-mapfile for services running as root and at
+HOME/.gridmap for services running as non-root where HOME is the home directory
+of the effective user from the password file entry.
+.It Ev GSSAPI_MECH_CONF
+Applies to mechglue used to support both GSI and Kerberos GSSAPI mechanisms.
+Used to specify the location of the mech.conf file that lists the mechanism-
+specific GSSAPI libraries (both Kerberos and GSI versions). If
+.Ev GSSAPI_MECH_CONF
+is not set then /etc/mech.conf is used. This applies to both the clients and
+the server. The NCSA GSSAPI mechglue distribution includes a sample mech.conf
+file. You will need to edit the library paths in that file and install it in
+an appropriate location on your system. If the mech.conf file is not found,
+the GSSAPI mechglue library will not load any GSSAPI mechanisms and GSI-OpenSSH
+will simply skip GSSAPI authentication.
+.It LD_LIBRARY_PATH
+The sshd server is typically linked dynamically with Globus
+security libraries, which must be present in the dynamic linker's
+search path. This typically requires
+.Cm $GLOBUS_LOCATION/lib
+to be included in the list in the
+.Ev LD_LIBRARY_PATH
+environment variable, which is set by the
+.Cm $GLOBUS_LOCATION/libexec/globus-script-initializer
+script, which should be called from any
+.Cm sshd
+startup script.
+Alternatively, to set
+.Ev LD_LIBRARY_PATH
+appropriately for the Globus libraries in an interactive shell, source
+.Cm $GLOBUS_LOCATION/etc/globus-user-env.sh
+(for sh shells) or
+.Cm $GLOBUS_LOCATION/etc/globus-user.env.csh
+(for csh shells).
+.It Ev X509_CERT_DIR
+Used for GSI authentication. Specifies a non-standard location for the
+CA certificates directory.
+.It Ev X509_USER_CERT
+Used for GSI authentication. Specifies a non-standard location for the
+certificate to be used for authentication to the client.
+.It Ev X509_USER_KEY
+Used for GSI authentication. Specifies a non-standard location for the
+private key to be used for authentication to the client.
+.It Ev X509_USER_PROXY
+Used for GSI authentication. Specifies a non-standard location for the
+proxy credential to be used for authentication to the client.
.Sh FILES
.Bl -tag -width Ds -compact
.It Pa ~/.hushlogin
diff -Naur --exclude=autom4te.cache openssh-5.8p2/sshd.c openssh-5.8p2-gssapi/sshd.c
--- openssh-5.8p2/sshd.c 2011-01-11 00:20:31.000000000 -0600
+++ openssh-5.8p2-gssapi/sshd.c 2011-05-31 12:54:34.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);
@@ -1000,6 +1011,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)
@@ -1040,6 +1053,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.",
@@ -1529,6 +1547,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) {
+ error("Error initializing Globus Usage Metrics, but continuing ...");
+ }
+#endif /* HAVE_GLOBUS_USAGE */
+
/* challenge-response is implemented via keyboard interactive */
if (options.challenge_response_authentication)
options.kbd_interactive_authentication = 1;
@@ -1590,10 +1615,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);
@@ -1885,6 +1913,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.
@@ -1922,6 +1953,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
@@ -1935,6 +2020,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)
@@ -1994,7 +2086,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();
@@ -2278,9 +2370,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]);
@@ -2303,6 +2401,48 @@
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;
@@ -2310,6 +2450,13 @@
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
kex->kex[KEX_ECDH_SHA2] = kexecdh_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.8p2/sshd_config openssh-5.8p2-gssapi/sshd_config
--- openssh-5.8p2/sshd_config 2010-09-09 20:20:12.000000000 -0500
+++ openssh-5.8p2-gssapi/sshd_config 2011-05-31 12:54:34.000000000 -0500
@@ -69,9 +69,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
@@ -84,6 +92,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
@@ -111,8 +123,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.8p2/sshd_config.5 openssh-5.8p2-gssapi/sshd_config.5
--- openssh-5.8p2/sshd_config.5 2010-12-25 21:26:48.000000000 -0600
+++ openssh-5.8p2-gssapi/sshd_config.5 2011-05-31 12:54:34.000000000 -0500
@@ -379,6 +379,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 ,
@@ -421,7 +431,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
@@ -429,6 +449,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
@@ -992,6 +1050,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.
@@ -1059,6 +1232,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.8p2/version.h openssh-5.8p2-gssapi/version.h
--- openssh-5.8p2/version.h 2011-05-04 20:56:54.000000000 -0500
+++ openssh-5.8p2-gssapi/version.h 2011-05-31 12:54:34.000000000 -0500
@@ -1,6 +1,28 @@
/* $OpenBSD: version.h,v 1.61 2011/02/04 00:44:43 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_20110531"
+
#define SSH_VERSION "OpenSSH_5.8"
#define SSH_PORTABLE "p2"
-#define SSH_RELEASE SSH_VERSION SSH_PORTABLE
+#define SSH_HPN "-hpn13v11"
+#define SSH_RELEASE SSH_VERSION SSH_PORTABLE SSH_HPN \
+ NCSA_VERSION GSI_VERSION KRB5_VERSION MGLUE_VERSION