diff -Nur openssh-7.7p1.orig/auth2.c openssh-7.7p1/auth2.c
--- openssh-7.7p1.orig/auth2.c 2018-07-05 14:58:40.604584490 +0200
+++ openssh-7.7p1/auth2.c 2018-07-05 13:40:25.453373817 +0200
@@ -230,7 +230,27 @@
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);
+
+#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') {
+ free(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);
debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
#ifdef WITH_SELINUX
@@ -241,11 +261,32 @@
if ((style = strchr(user, ':')) != NULL)
*style++ = 0;
- if (authctxt->attempt++ == 0) {
- /* setup auth context */
- authctxt->pw = PRIVSEP(getpwnamallow(user));
+ /* 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) {
+ free(authctxt->user);
+ authctxt->user = NULL;
+ }
+ authctxt->valid = 0;
authctxt->user = xstrdup(user);
- if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
+ 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));
+ if (authctxt->pw) {
authctxt->valid = 1;
debug2("%s: setting up authctxt for %s",
__func__, user);
@@ -253,6 +294,9 @@
/* Invalid user, fake password information */
authctxt->pw = fakepw();
}
+#ifdef GSSAPI
+ } /* endif for setting username based on GSSAPI context */
+#endif
#ifdef USE_PAM
if (options.use_pam)
PRIVSEP(start_pam(authctxt));
@@ -261,6 +305,7 @@
authctxt->valid ? "authenticating " : "invalid ", user);
setproctitle("%s%s", authctxt->valid ? user : "unknown",
use_privsep ? " [net]" : "");
+ if (authctxt->attempt == 1) {
authctxt->service = xstrdup(service);
authctxt->style = style ? xstrdup(style) : NULL;
#ifdef WITH_SELINUX
@@ -275,9 +320,10 @@
userauth_banner();
if (auth2_setup_methods_lists(authctxt) != 0)
packet_disconnect("no authentication methods enabled");
- } else if (strcmp(user, authctxt->user) != 0 ||
- strcmp(service, authctxt->service) != 0) {
- packet_disconnect("Change of username or service not allowed: "
+ }
+ }
+ if (strcmp(service, authctxt->service) != 0) {
+ packet_disconnect("Change of service not allowed: "
"(%s,%s) -> (%s,%s)",
authctxt->user, authctxt->service, user, service);
}
diff -Nur openssh-7.7p1.orig/auth2-gss.c openssh-7.7p1/auth2-gss.c
--- openssh-7.7p1.orig/auth2-gss.c 2018-07-05 14:58:40.604584490 +0200
+++ openssh-7.7p1/auth2-gss.c 2018-07-05 13:40:25.453373817 +0200
@@ -49,6 +49,7 @@
extern ServerOptions options;
+static void ssh_gssapi_userauth_error(Gssctxt *ctxt);
static int input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh);
static int input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh);
static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh);
@@ -62,8 +63,8 @@
{
Authctxt *authctxt = ssh->authctxt;
int authenticated = 0;
- Buffer b;
- gss_buffer_desc mic, gssbuf;
+ Buffer b, b2;
+ gss_buffer_desc mic, gssbuf, gssbuf2;
u_int len;
mic.value = packet_get_string(&len);
@@ -77,13 +78,27 @@
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))))
- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
- authctxt->pw));
+ &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);
free(mic.value);
return (authenticated);
@@ -105,7 +120,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();
@@ -170,7 +188,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))
@@ -188,6 +206,7 @@
free(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);
@@ -253,6 +272,32 @@
return 0;
}
+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) free(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,
@@ -269,6 +314,8 @@
if (authctxt == NULL || (authctxt->methoddata == NULL && !use_privsep))
fatal("No authentication or GSSAPI context");
+ gssapi_set_username(authctxt);
+
/*
* We don't need to check the status, because we're only enabled in
* the dispatcher once the exchange is complete
@@ -276,8 +323,13 @@
packet_check_eom();
- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
- authctxt->pw));
+ /* 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;
+ }
if ((!use_privsep || mm_is_monitor()) &&
(displayname = ssh_gssapi_displayname()) != NULL)
@@ -324,9 +376,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, authctxt->pw));
+ 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");
@@ -348,6 +407,23 @@
return 0;
}
+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();
+ free(errstr);
+ }
+}
+
Authmethod method_gsskeyex = {
"gssapi-keyex",
userauth_gsskeyex,
diff -Nur openssh-7.7p1.orig/auth.c openssh-7.7p1/auth.c
--- openssh-7.7p1.orig/auth.c 2018-07-05 14:58:40.605584480 +0200
+++ openssh-7.7p1/auth.c 2018-07-05 13:40:25.453373817 +0200
@@ -76,6 +76,9 @@
#include "compat.h"
#include "channels.h"
+#include "version.h"
+#include "ssh-globus-usage.h"
+
/* import */
extern ServerOptions options;
extern int use_privsep;
@@ -340,7 +343,8 @@
method,
submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
authctxt->valid ? "" : "invalid user ",
- authctxt->user,
+ (authctxt->user && authctxt->user[0]) ?
+ authctxt->user : "unknown",
ssh_remote_ipaddr(ssh),
ssh_remote_port(ssh),
extra != NULL ? ": " : "",
@@ -366,6 +370,23 @@
if (authenticated == 0 && !authctxt->postponed && !partial)
audit_event(audit_classify_auth(method));
#endif
+ if (authenticated) {
+ char *userdn = NULL;
+ char *mech_name = NULL;
+#ifdef GSSAPI
+ ssh_gssapi_get_client_info(&userdn, &mech_name);
+#endif
+ debug("REPORTING (%s) (%s) (%s) (%s) (%s) (%s) (%s)",
+ SSH_RELEASE, SSLeay_version(SSLEAY_VERSION),
+ method, mech_name?mech_name:"NULL", ssh_remote_ipaddr(ssh),
+ (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, ssh_remote_ipaddr(ssh),
+ authctxt->user, userdn);
+ }
}
@@ -576,6 +597,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();
@@ -595,7 +620,8 @@
#endif
if (pw == NULL) {
logit("Invalid user %.100s from %.100s port %d",
- user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
+ (user && user[0]) ? user : "unknown",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
#ifdef CUSTOM_FAILED_LOGIN
record_failed_login(user,
auth_get_canonical_hostname(ssh, options.use_dns), "ssh");
diff -Nur openssh-7.7p1.orig/auth.h openssh-7.7p1/auth.h
--- openssh-7.7p1.orig/auth.h 2018-07-05 14:58:40.605584480 +0200
+++ openssh-7.7p1/auth.h 2018-07-05 13:40:25.454373806 +0200
@@ -85,6 +85,8 @@
krb5_principal krb5_user;
char *krb5_ticket_file;
char *krb5_ccname;
+#endif
+#ifdef GSSAPI
int krb5_set_env;
#endif
struct sshbuf *loginmsg;
diff -Nur openssh-7.7p1.orig/auth-pam.c openssh-7.7p1/auth-pam.c
--- openssh-7.7p1.orig/auth-pam.c 2018-07-05 14:58:40.605584480 +0200
+++ openssh-7.7p1/auth-pam.c 2018-07-05 13:40:25.454373806 +0200
@@ -288,6 +288,56 @@
# 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,
+ (sshpam_const void **)&user);
+ if (sshpam_err != PAM_SUCCESS)
+ fatal("PAM: could not get PAM_USER: %s",
+ pam_strerror(sshpam_handle, sshpam_err));
+ debug("sshpam_check_userchanged: user was '%.100s'",
+ sshpam_authctxt->pw->pw_name);
+ 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 = pwcopy(pw);
+ sshpam_authctxt->valid = allowed_user(pw);
+ free(sshpam_authctxt->user);
+ sshpam_authctxt->user = xstrdup(user);
+ debug("PAM: user '%.100s' now %svalid", user,
+ sshpam_authctxt->valid ? "" : "in");
+ }
+ debug("sshpam_check_userchanged: user is '%.100s'",
+ sshpam_authctxt->pw->pw_name);
+}
+
void
sshpam_password_change_required(int reqd)
{
@@ -319,7 +369,7 @@
static void
import_environments(Buffer *b)
{
- char *env;
+ char *env, *user;
u_int i, num_env;
int err;
@@ -329,6 +379,17 @@
/* 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: user is '%.100s'",
+ sshpam_authctxt->pw->pw_name);
+ 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);
@@ -480,6 +541,13 @@
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
+ if (options.permit_pam_user_change) {
+ debug("sshpam_thread: user is '%.100s'",
+ sshpam_authctxt->pw->pw_name);
+ sshpam_check_userchanged();
+ debug("sshpam_thread: user is '%.100s'",
+ sshpam_authctxt->pw->pw_name);
+ }
if (!do_pam_account()) {
sshpam_err = PAM_ACCT_EXPIRED;
goto auth_fail;
@@ -498,6 +566,11 @@
/* 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) {
+ debug("sshpam_thread: user is '%.100s'",
+ sshpam_authctxt->pw->pw_name);
+ buffer_put_cstring(&buffer, sshpam_authctxt->pw->pw_name);
+ }
/* Export any environment strings set in child */
for(i = 0; environ[i] != NULL; i++)
@@ -973,6 +1046,18 @@
debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
pam_strerror(sshpam_handle, sshpam_err));
+ if (options.permit_pam_user_change) {
+ debug("do_pam_account: user is '%.100s'",
+ sshpam_authctxt->pw->pw_name);
+ sshpam_check_userchanged();
+ debug("do_pam_account: user is '%.100s'",
+ sshpam_authctxt->pw->pw_name);
+ if (getpwnam(sshpam_authctxt->pw->pw_name) == NULL)
+ fatal("PAM: completed authentication but PAM account invalid");
+ debug("do_pam_account: user is '%.100s'",
+ sshpam_authctxt->pw->pw_name);
+ }
+
if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) {
sshpam_account_status = 0;
return (sshpam_account_status);
@@ -1262,6 +1347,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;
free(fake);
if (sshpam_err == PAM_MAXTRIES)
diff -Nur openssh-7.7p1.orig/auth-pam.h openssh-7.7p1/auth-pam.h
--- openssh-7.7p1.orig/auth-pam.h 2018-07-05 14:58:40.605584480 +0200
+++ openssh-7.7p1/auth-pam.h 2018-07-05 13:40:25.454373806 +0200
@@ -43,5 +43,6 @@
int sshpam_get_maxtries_reached(void);
void sshpam_set_maxtries_reached(int);
int is_pam_session_open(void);
+struct passwd *sshpam_getpw(const char *);
#endif /* USE_PAM */
diff -Nur openssh-7.7p1.orig/canohost.c openssh-7.7p1/canohost.c
--- openssh-7.7p1.orig/canohost.c 2018-07-05 14:58:40.606584469 +0200
+++ openssh-7.7p1/canohost.c 2018-07-05 13:40:25.454373806 +0200
@@ -17,6 +17,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
+#include <sys/param.h> /* for MAXHOSTNAMELEN */
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -202,3 +203,33 @@
{
return get_sock_port(sock, 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);
+ free(*host);
+ if (hostinfo == NULL || hostinfo->h_name == NULL) {
+ *host = xstrdup(buf);
+ } else {
+ *host = xstrdup(hostinfo->h_name);
+ }
+ }
+ }
+}
diff -Nur openssh-7.7p1.orig/canohost.h openssh-7.7p1/canohost.h
--- openssh-7.7p1.orig/canohost.h 2018-07-05 14:58:40.615584372 +0200
+++ openssh-7.7p1/canohost.h 2018-07-05 13:40:25.454373806 +0200
@@ -23,4 +23,6 @@
#endif /* _CANOHOST_H */
+void resolve_localhost(char **host);
+
void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *);
diff -Nur openssh-7.7p1.orig/configure.ac openssh-7.7p1/configure.ac
--- openssh-7.7p1.orig/configure.ac 2018-07-05 14:58:40.616584361 +0200
+++ openssh-7.7p1/configure.ac 2018-07-05 13:40:25.455373795 +0200
@@ -4542,6 +4542,14 @@
AC_CHECK_HEADER([gssapi_krb5.h], ,
[ CPPFLAGS="$oldCPP" ])
+ # If we're using some other GSSAPI
+ if test -n "$GSSAPI" ; then
+ AC_MSG_ERROR([Previously configured GSSAPI library conflicts with Kerberos GSI.])
+ fi
+
+ if test -z "$GSSAPI"; then
+ GSSAPI="KRB5";
+ fi
fi
if test ! -z "$need_dash_r" ; then
LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib"
@@ -4581,6 +4589,50 @@
AC_SUBST([GSSLIBS])
AC_SUBST([K5LIBS])
+# Check whether the user wants GSI (Globus) support
+gsi="no"
+AC_ARG_WITH(gsi,
+ [ --with-gsi Enable Globus GSI authentication support],
+ [
+ gsi="$withval"
+ ]
+)
+
+if test "x$gsi" != "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 -n "$GSSAPI" ; then
+ AC_MSG_ERROR([Previously configured GSSAPI library conflicts with Globus GSI.])
+ fi
+
+ if test -z "$GSSAPI" ; then
+ GSSAPI="GSI"
+ fi
+
+ LIBS="$LIBS `pkg-config --libs globus-gss-assist globus-gssapi-gsi globus-common`"
+ CPPFLAGS="$CPPFLAGS `pkg-config --cflags globus-gss-assist globus-gssapi-gsi globus-common`"
+
+ AC_DEFINE(GSSAPI)
+ AC_DEFINE(HAVE_GSSAPI_H)
+
+ AC_CHECK_FUNCS(globus_gss_assist_map_and_authorize)
+
+ dnl
+ dnl Check for globus_usage_stats_send
+ dnl
+ AC_SEARCH_LIBS(globus_usage_stats_send,
+ globus_usage,
+ AC_DEFINE([HAVE_GLOBUS_USAGE], 1, [Have Globus Usage]))
+ dnl
+ dnl Check for globus_usage_stats_send_array
+ dnl
+ AC_SEARCH_LIBS(globus_usage_stats_send_array,
+ globus_usage,
+ AC_DEFINE([HAVE_GLOBUS_USAGE_SEND_ARRAY], 1, [Have Globus Usage send_array]))
+fi
+
# Check whether user wants systemd support
SYSTEMD_MSG="no"
AC_ARG_WITH(systemd,
diff -Nur openssh-7.7p1.orig/gss-genr.c openssh-7.7p1/gss-genr.c
--- openssh-7.7p1.orig/gss-genr.c 2018-07-05 14:58:40.616584361 +0200
+++ openssh-7.7p1/gss-genr.c 2018-07-05 13:40:25.456373784 +0200
@@ -39,6 +39,7 @@
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
+#include "canohost.h"
#include "ssh2.h"
#include "cipher.h"
#include "key.h"
@@ -371,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);
@@ -381,6 +391,7 @@
&gssbuf, GSS_C_NT_HOSTBASED_SERVICE, &ctx->name)))
ssh_gssapi_error(ctx);
+ free(xhost);
free(gssbuf.value);
return (ctx->major);
}
diff -Nur openssh-7.7p1.orig/gss-serv.c openssh-7.7p1/gss-serv.c
--- openssh-7.7p1.orig/gss-serv.c 2018-07-05 14:58:40.616584361 +0200
+++ openssh-7.7p1/gss-serv.c 2018-07-05 15:02:46.526946800 +0200
@@ -51,10 +51,12 @@
#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,
- GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL}, 0, 0};
+ { {0, NULL}, GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL,
+ GSS_C_NO_NAME, GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL},
+ GSS_C_NO_CONTEXT, 0, 0};
ssh_gssapi_mech gssapi_null_mech =
{ NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};
@@ -62,14 +64,26 @@
#ifdef KRB5
extern ssh_gssapi_mech gssapi_kerberos_mech;
#endif
+#ifdef GSI
+extern ssh_gssapi_mech gssapi_gsi_mech;
+extern ssh_gssapi_mech gssapi_gsi_mech_micv2;
+#endif
ssh_gssapi_mech* supported_mechs[]= {
#ifdef KRB5
&gssapi_kerberos_mech,
#endif
+#ifdef GSI
+ &gssapi_gsi_mech_micv2,
+ &gssapi_gsi_mech,
+#endif
&gssapi_null_mech,
};
+#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG
+static int limited = 0;
+#endif
+
/*
* ssh_gssapi_supported_oids() can cause sandbox violations, so prepare the
* list of supported mechanisms before privsep is set up.
@@ -230,6 +244,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);
@@ -249,6 +267,20 @@
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)) ||
+ ((ctx->oid->length == gssapi_gsi_mech_micv2.oid.length) &&
+ (memcmp(ctx->oid->elements, gssapi_gsi_mech_micv2.oid.elements,
+ gssapi_gsi_mech_micv2.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
@@ -309,21 +341,24 @@
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,
+ if (client->oid.length != ctx->oid->length ||
+ (memcmp(client->oid.elements,
ctx->oid->elements, ctx->oid->length) !=0)) {
debug("Rekeyed credentials have different mechanism");
return GSS_S_COMPLETE;
}
- if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
- ctx->client_creds, ctx->oid, &new_name,
+ /* 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,
+ ctx->major = gss_compare_name(&ctx->minor, client->cred_name,
new_name, &equal);
if (GSS_ERROR(ctx->major)) {
@@ -338,9 +373,9 @@
debug("Marking rekeyed credentials for export");
- gss_release_name(&ctx->minor, &client->name);
+ gss_release_name(&ctx->minor, &client->cred_name);
gss_release_cred(&ctx->minor, &client->creds);
- client->name = new_name;
+ client->cred_name = new_name;
client->creds = ctx->client_creds;
ctx->client_creds = GSS_C_NO_CREDENTIAL;
client->updated = 1;
@@ -357,12 +392,17 @@
i++;
}
+ if (client->oid.elements == NULL)
+ client->oid = *ctx->oid;
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_by_mech(&ctx->minor,
- ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) {
+ (ctx->major = gss_inquire_cred(&ctx->minor,
+ ctx->client_creds, &client->cred_name, NULL, NULL, NULL))) {
ssh_gssapi_error(ctx);
return (ctx->major);
}
@@ -379,16 +419,25 @@
return (ctx->major);
}
- if ((ctx->major = ssh_gssapi_parse_ename(ctx,&ename,
+ if ((client->mech->oid.elements != NULL) &&
+ (ctx->major = ssh_gssapi_parse_ename(ctx,&ename,
&client->exportedname))) {
return (ctx->major);
}
+ if ((ctx->major = gss_duplicate_name(&ctx->minor, ctx->client,
+ &client->ctx_name)))
+ 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);
}
@@ -396,6 +445,7 @@
void
ssh_gssapi_cleanup_creds(void)
{
+#ifdef KRB5
krb5_ccache ccache = NULL;
krb5_error_code problem;
@@ -411,6 +461,14 @@
gssapi_client.store.data = NULL;
}
}
+#else
+ if (gssapi_client.store.filename != NULL) {
+ /* Unlink probably isn't sufficient */
+ debug("removing gssapi cred file\"%s\"",
+ gssapi_client.store.filename);
+ unlink(gssapi_client.store.filename);
+ }
+#endif
}
/* As user */
@@ -418,6 +476,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);
+ }
return (*gssapi_client.mech->storecreds)(&gssapi_client);
} else
debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism");
@@ -443,16 +506,19 @@
}
/* Privileged */
+/* gssapi_keyex arg added for Globus usage */
int
-ssh_gssapi_userok(char *user, struct passwd *pw)
+ssh_gssapi_userok(char *user, struct passwd *pw, int gssapi_keyex)
{
OM_uint32 lmin;
- if (gssapi_client.exportedname.length == 0 ||
- gssapi_client.exportedname.value == NULL) {
- debug("No suitable client data");
+#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)) {
gssapi_client.used = 1;
@@ -463,6 +529,7 @@
gss_release_buffer(&lmin, &gssapi_client.displayname);
gss_release_buffer(&lmin, &gssapi_client.exportedname);
gss_release_cred(&lmin, &gssapi_client.creds);
+ gss_release_name(&lmin, &gssapi_client.ctx_name);
explicit_bzero(&gssapi_client,
sizeof(ssh_gssapi_client));
return 0;
@@ -472,6 +539,24 @@
return (0);
}
+/* 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.
*
@@ -498,9 +583,11 @@
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.envval == NULL &&
+ if (gssapi_client.store.filename == NULL &&
+ gssapi_client.store.envval == NULL &&
gssapi_client.store.envvar == NULL)
return;
@@ -526,6 +613,18 @@
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);
@@ -566,4 +665,13 @@
return (char *)gssapi_client.displayname.value;
}
+/* 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 -Nur openssh-7.7p1.orig/gss-serv-gsi.c openssh-7.7p1/gss-serv-gsi.c
--- openssh-7.7p1.orig/gss-serv-gsi.c 1970-01-01 01:00:00.000000000 +0100
+++ openssh-7.7p1/gss-serv-gsi.c 2018-07-05 13:40:25.459373752 +0200
@@ -0,0 +1,331 @@
+/*
+ * 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 "misc.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 int ssh_gssapi_gsi_storecreds(ssh_gssapi_client *client);
+static int ssh_gssapi_gsi_storecreds_micv2(ssh_gssapi_client *client);
+static int ssh_gssapi_gsi_updatecreds(ssh_gssapi_ccache *store,
+ ssh_gssapi_client *client);
+static int ssh_gssapi_gsi_updatecreds_micv2(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
+};
+
+ssh_gssapi_mech gssapi_gsi_mech_micv2 = {
+ "vz8J1E9PzLr8b1K+0remTg==",
+ "GSI",
+ {10, "\x2b\x06\x01\x04\x01\x9b\x50\x01\x01\x01"},
+ NULL,
+ &ssh_gssapi_gsi_userok,
+ &ssh_gssapi_gsi_localname,
+ &ssh_gssapi_gsi_storecreds_micv2,
+ &ssh_gssapi_gsi_updatecreds_micv2
+};
+
+/*
+ * 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 int
+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 0;
+ }
+
+ 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 0;
+ }
+
+ 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 0;
+ }
+ *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));
+ free(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);
+
+ return 1;
+}
+
+/*
+ * Export GSI credentials to disk.
+ */
+static int
+ssh_gssapi_gsi_storecreds_micv2(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 0;
+ }
+
+ 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_micv2.oid);
+ ssh_gssapi_error(ctx);
+ ssh_gssapi_delete_ctx(&ctx);
+ return 0;
+ }
+
+ 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 0;
+ }
+ *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));
+ free(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);
+
+ return 1;
+}
+
+/*
+ * Export updated GSI credentials to disk.
+ */
+static int
+ssh_gssapi_gsi_updatecreds(ssh_gssapi_ccache *store,ssh_gssapi_client *client)
+{
+ return ssh_gssapi_gsi_storecreds(client);
+}
+
+/*
+ * Export updated GSI credentials to disk.
+ */
+static int
+ssh_gssapi_gsi_updatecreds_micv2(ssh_gssapi_ccache *store,ssh_gssapi_client *client)
+{
+ return ssh_gssapi_gsi_storecreds_micv2(client);
+}
+
+#endif /* GSI */
+#endif /* GSSAPI */
diff -Nur openssh-7.7p1.orig/gss-serv-krb5.c openssh-7.7p1/gss-serv-krb5.c
--- openssh-7.7p1.orig/gss-serv-krb5.c 2018-07-05 14:58:40.617584351 +0200
+++ openssh-7.7p1/gss-serv-krb5.c 2018-07-05 13:40:25.459373752 +0200
@@ -378,6 +378,34 @@
return found_principal;
}
+/* 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)) {
+ free(*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 */
@@ -470,7 +498,7 @@
return set_env;
}
-int
+static int
ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store,
ssh_gssapi_client *client)
{
@@ -541,7 +569,7 @@
{9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"},
NULL,
&ssh_gssapi_krb5_userok,
- NULL,
+ &ssh_gssapi_krb5_localname,
&ssh_gssapi_krb5_storecreds,
&ssh_gssapi_krb5_updatecreds
};
diff -Nur openssh-7.7p1.orig/kexgsss.c openssh-7.7p1/kexgsss.c
--- openssh-7.7p1.orig/kexgsss.c 2018-07-05 14:58:40.617584351 +0200
+++ openssh-7.7p1/kexgsss.c 2018-07-05 13:40:25.460373741 +0200
@@ -48,6 +48,7 @@
#include "digest.h"
#include "ssherr.h"
+static void kex_gss_send_error(Gssctxt *ctxt);
extern ServerOptions options;
int
@@ -97,8 +98,10 @@
debug2("%s: Acquiring credentials", __func__);
- if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))
+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) {
+ kex_gss_send_error(ctxt);
fatal("Unable to acquire credentials for the server");
+ }
switch (ssh->kex->kex_type) {
case KEX_GSS_GRP1_SHA1:
@@ -190,12 +193,13 @@
} while (maj_status & GSS_S_CONTINUE_NEEDED);
if (GSS_ERROR(maj_status)) {
+ kex_gss_send_error(ctxt);
if (send_tok.length > 0) {
packet_start(SSH2_MSG_KEXGSS_CONTINUE);
packet_put_string(send_tok.value, send_tok.length);
packet_send();
}
- fatal("accept_ctx died");
+ packet_disconnect("GSSAPI Key Exchange handshake failed");
}
if (!(ret_flags & GSS_C_MUTUAL_FLAG))
@@ -636,4 +640,23 @@
}
return r;
}
+
+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 */
+ free(errstr);
+ }
+}
#endif /* GSSAPI */
diff -Nur openssh-7.7p1.orig/LICENSE.globus_usage openssh-7.7p1/LICENSE.globus_usage
--- openssh-7.7p1.orig/LICENSE.globus_usage 1970-01-01 01:00:00.000000000 +0100
+++ openssh-7.7p1/LICENSE.globus_usage 2018-07-05 13:40:25.460373741 +0200
@@ -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 -Nur openssh-7.7p1.orig/Makefile.in openssh-7.7p1/Makefile.in
--- openssh-7.7p1.orig/Makefile.in 2018-07-05 14:58:40.617584351 +0200
+++ openssh-7.7p1/Makefile.in 2018-07-05 13:40:25.473373600 +0200
@@ -124,8 +124,10 @@
auth2-none.o auth2-passwd.o auth2-pubkey.o \
monitor.o monitor_wrap.o auth-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 \
sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
sandbox-solaris.o
diff -Nur openssh-7.7p1.orig/misc.c openssh-7.7p1/misc.c
--- openssh-7.7p1.orig/misc.c 2018-07-05 14:58:40.618584340 +0200
+++ openssh-7.7p1/misc.c 2018-07-05 13:40:25.460373741 +0200
@@ -238,11 +238,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)
@@ -250,6 +253,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);
@@ -305,6 +323,20 @@
return copy;
}
+void
+pwfree(struct passwd *pw)
+{
+ free(pw->pw_name);
+ free(pw->pw_passwd);
+ free(pw->pw_gecos);
+#ifdef HAVE_PW_CLASS_IN_PASSWD
+ free(pw->pw_class);
+#endif
+ free(pw->pw_dir);
+ free(pw->pw_shell);
+ free(pw);
+}
+
/*
* Convert ASCII string to TCP/IP port number.
* Port must be >=0 and <=65535.
diff -Nur openssh-7.7p1.orig/misc.h openssh-7.7p1/misc.h
--- openssh-7.7p1.orig/misc.h 2018-07-05 14:58:40.618584340 +0200
+++ openssh-7.7p1/misc.h 2018-07-05 13:40:25.461373730 +0200
@@ -82,6 +82,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 -Nur openssh-7.7p1.orig/monitor.c openssh-7.7p1/monitor.c
--- openssh-7.7p1.orig/monitor.c 2018-07-05 14:58:40.619584329 +0200
+++ openssh-7.7p1/monitor.c 2018-07-05 15:10:21.951050957 +0200
@@ -165,6 +165,9 @@
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
@@ -215,7 +218,7 @@
{MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
#endif
{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},
#ifdef WITH_SELINUX
{MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole},
@@ -223,7 +226,7 @@
{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_ONCE, mm_answer_pam_init_ctx},
{MONITOR_REQ_PAM_QUERY, 0, mm_answer_pam_query},
@@ -251,8 +254,11 @@
{MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
{MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
{MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok},
- {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic},
+ {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
{MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign},
+ {MONITOR_REQ_GSSERR, MON_ISAUTH | MON_ONCE, mm_answer_gss_error},
+ {MONITOR_REQ_GSSMECHS, MON_ISAUTH, mm_answer_gss_indicate_mechs},
+ {MONITOR_REQ_GSSLOCALNAME, MON_ISAUTH, mm_answer_gss_localname},
#endif
{0, 0, NULL}
};
@@ -262,6 +268,8 @@
{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
#ifdef WITH_OPENSSL
@@ -343,6 +351,8 @@
#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
/* The first few requests do not require asynchronous access */
@@ -458,6 +468,8 @@
#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
if (auth_opts->permit_pty_flag) {
@@ -767,14 +779,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) free(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");
free(username);
@@ -1992,13 +2007,16 @@
mm_answer_gss_userok(int sock, Buffer *m)
{
int authenticated;
+ int gssapi_keyex;
const char *displayname;
if (!options.gss_authentication && !options.gss_keyex)
fatal("%s: GSSAPI authentication not enabled", __func__);
+ gssapi_keyex = buffer_get_int(m);
+
authenticated = authctxt->valid &&
- ssh_gssapi_userok(authctxt->user, authctxt->pw);
+ ssh_gssapi_userok(authctxt->user, authctxt->pw, gssapi_keyex);
buffer_clear(m);
buffer_put_int(m, authenticated);
@@ -2006,7 +2024,10 @@
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";
if ((displayname = ssh_gssapi_displayname()) != NULL)
auth2_record_info(authctxt, "%s", displayname);
@@ -2015,6 +2036,68 @@
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);
+
+ free(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);
+ }
+
+ gss_release_oid_set(&minor, &mech_set);
+
+ mm_request_send(socket, MONITOR_ANS_GSSMECHS, m);
+
+ return(0);
+}
+
+int
+mm_answer_gss_localname(int socket, Buffer *m) {
+ char *name;
+
+ ssh_gssapi_localname(&name);
+
+ buffer_clear(m);
+ if (name) {
+ buffer_put_cstring(m, name);
+ debug3("%s: sending result %s", __func__, name);
+ free(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)
{
@@ -2065,11 +2148,13 @@
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);
+ free(store.filename);
free(store.envvar);
free(store.envval);
diff -Nur openssh-7.7p1.orig/monitor.h openssh-7.7p1/monitor.h
--- openssh-7.7p1.orig/monitor.h 2018-07-05 14:58:40.619584329 +0200
+++ openssh-7.7p1/monitor.h 2018-07-05 13:40:25.461373730 +0200
@@ -75,8 +75,10 @@
MONITOR_REQ_AUDIT_UNSUPPORTED = 118, MONITOR_ANS_AUDIT_UNSUPPORTED = 119,
MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121,
MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 122, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 123,
- MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124
-
+ MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124,
+ MONITOR_REQ_GSSMECHS = 200, MONITOR_ANS_GSSMECHS = 201,
+ MONITOR_REQ_GSSLOCALNAME = 202, MONITOR_ANS_GSSLOCALNAME = 203,
+ MONITOR_REQ_GSSERR = 204, MONITOR_ANS_GSSERR = 205
};
struct monitor {
diff -Nur openssh-7.7p1.orig/monitor_wrap.c openssh-7.7p1/monitor_wrap.c
--- openssh-7.7p1.orig/monitor_wrap.c 2018-07-05 14:58:40.619584329 +0200
+++ openssh-7.7p1/monitor_wrap.c 2018-07-05 15:04:51.534606293 +0200
@@ -998,12 +998,13 @@
}
int
-mm_ssh_gssapi_userok(char *user, struct passwd *pw)
+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,
@@ -1016,6 +1017,83 @@
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)
{
@@ -1046,6 +1124,7 @@
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 : "");
diff -Nur openssh-7.7p1.orig/monitor_wrap.h openssh-7.7p1/monitor_wrap.h
--- openssh-7.7p1.orig/monitor_wrap.h 2018-07-05 14:58:40.619584329 +0200
+++ openssh-7.7p1/monitor_wrap.h 2018-07-05 13:40:25.462373719 +0200
@@ -65,9 +65,13 @@
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, struct passwd *);
+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
diff -Nur openssh-7.7p1.orig/readconf.c openssh-7.7p1/readconf.c
--- openssh-7.7p1.orig/readconf.c 2018-07-05 14:58:40.620584318 +0200
+++ openssh-7.7p1/readconf.c 2018-07-05 13:40:25.462373719 +0200
@@ -1959,13 +1959,13 @@
if (options->challenge_response_authentication == -1)
options->challenge_response_authentication = 1;
if (options->gss_authentication == -1)
- options->gss_authentication = 0;
+ options->gss_authentication = 1;
if (options->gss_keyex == -1)
- options->gss_keyex = 0;
+ 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 = 0;
+ options->gss_trust_dns = 1;
if (options->gss_renewal_rekey == -1)
options->gss_renewal_rekey = 0;
#ifdef GSSAPI
diff -Nur openssh-7.7p1.orig/readconf.h openssh-7.7p1/readconf.h
--- openssh-7.7p1.orig/readconf.h 2018-07-05 14:58:40.620584318 +0200
+++ openssh-7.7p1/readconf.h 2018-07-05 13:40:25.462373719 +0200
@@ -80,6 +80,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 */
u_int num_system_hostfiles; /* Paths for /etc/ssh/ssh_known_hosts */
diff -Nur openssh-7.7p1.orig/servconf.c openssh-7.7p1/servconf.c
--- openssh-7.7p1.orig/servconf.c 2018-07-05 14:58:40.621584308 +0200
+++ openssh-7.7p1/servconf.c 2018-07-05 13:40:25.463373709 +0200
@@ -83,6 +83,7 @@
/* Portable-specific options */
options->use_pam = -1;
+ options->permit_pam_user_change = -1;
/* Standard Options */
options->num_ports = 0;
@@ -126,9 +127,11 @@
options->kerberos_get_afs_token = -1;
options->kerberos_unique_ticket = -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->gss_kex_algorithms = NULL;
options->use_kuserok = -1;
@@ -173,6 +176,8 @@
options->chroot_directory = NULL;
options->authorized_keys_command = NULL;
options->authorized_keys_command_user = NULL;
+ options->disable_usage_stats = 1;
+ options->usage_stats_targets = NULL;
options->revoked_keys_file = NULL;
options->trusted_user_ca_keys = NULL;
options->authorized_principals_file = NULL;
@@ -256,6 +261,8 @@
/* 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->num_host_key_files == 0) {
@@ -333,13 +340,17 @@
if (options->kerberos_unique_ticket == -1)
options->kerberos_unique_ticket = 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 = 0;
+ 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;
#ifdef GSSAPI
@@ -472,7 +483,7 @@
typedef enum {
sBadOption, /* == unknown option */
/* Portable-specific options */
- sUsePAM,
+ sUsePAM, sPermitPAMUserChange,
/* Standard Options */
sPort, sHostKeyFile, sLoginGraceTime,
sPermitRootLogin, sLogFacility, sLogLevel,
@@ -494,10 +505,14 @@
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
sHostKeyAlgorithms,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
+ sGssDelegateCreds,
+ sGssCredsPath,
+ sGsiAllowLimitedProxy,
sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,
sGssKeyEx, sGssStoreRekey, sGssKexAlgorithms, sAcceptEnv, sPermitTunnel,
sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
+ sDisUsageStats, sUsageStatsTarg,
sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
@@ -523,8 +538,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 */
@@ -572,7 +589,14 @@
{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
#ifdef GSSAPI
{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
+ { "gssapidelegatecredentials", sGssDelegateCreds, SSHCFG_ALL },
{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
+ { "gssapicredentialspath", sGssCredsPath, SSHCFG_GLOBAL },
+#ifdef GSI
+ { "gsiallowlimitedproxy", sGsiAllowLimitedProxy, SSHCFG_GLOBAL },
+#else
+ { "gsiallowlimitedproxy", sUnsupported, SSHCFG_GLOBAL },
+#endif
{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
@@ -580,7 +604,10 @@
{ "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },
#else
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
+ { "gssapidelegatecredentials", sUnsupported, SSHCFG_ALL },
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
+ { "gssapicredentialspath", sUnsupported, SSHCFG_GLOBAL },
+ { "gsiallowlimitedproxy", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
{ "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
@@ -649,6 +676,8 @@
{ "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 },
@@ -1249,6 +1278,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;
@@ -1463,6 +1496,10 @@
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;
@@ -1471,6 +1508,10 @@
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;
@@ -1491,6 +1532,12 @@
options->gss_kex_algorithms = xstrdup(arg);
break;
+#ifdef GSI
+ case sGsiAllowLimitedProxy:
+ intptr = &options->gsi_allow_limited_proxy;
+ goto parse_flag;
+#endif
+
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
@@ -1948,6 +1995,35 @@
*charptr = xstrdup(arg);
break;
+ case sDisUsageStats:
+ 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:
+ 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;
@@ -2241,6 +2317,7 @@
M_CP_INTOPT(password_authentication);
M_CP_INTOPT(gss_authentication);
+ M_CP_INTOPT(gss_deleg_creds);
M_CP_INTOPT(pubkey_authentication);
M_CP_INTOPT(kerberos_authentication);
M_CP_INTOPT(hostbased_authentication);
diff -Nur openssh-7.7p1.orig/servconf.h openssh-7.7p1/servconf.h
--- openssh-7.7p1.orig/servconf.h 2018-07-05 14:58:40.621584308 +0200
+++ openssh-7.7p1/servconf.h 2018-07-05 13:40:25.463373709 +0200
@@ -135,9 +135,12 @@
* be stored in per-session ccache */
int use_kuserok;
int enable_k5users;
+ 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; /* Use non-default credentials path */
int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */
int gss_store_rekey;
char *gss_kex_algorithms; /* GSSAPI kex methods to be offered by client. */
@@ -194,6 +197,7 @@
char *adm_forced_command;
int use_pam; /* Enable auth via PAM */
+ int permit_pam_user_change; /* Allow PAM to change user name */
int permit_tun;
@@ -201,6 +205,10 @@
u_int num_permitted_opens; /* May also be one of PERMITOPEN_* */
char *chroot_directory;
+
+ int disable_usage_stats;
+ char *usage_stats_targets;
+
char *revoked_keys_file;
char *trusted_user_ca_keys;
char *authorized_keys_command;
diff -Nur openssh-7.7p1.orig/ssh.1 openssh-7.7p1/ssh.1
--- openssh-7.7p1.orig/ssh.1 2018-07-05 14:58:40.622584297 +0200
+++ openssh-7.7p1/ssh.1 2018-07-05 13:40:25.463373709 +0200
@@ -1419,6 +1419,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 -Nur openssh-7.7p1.orig/ssh.c openssh-7.7p1/ssh.c
--- openssh-7.7p1.orig/ssh.c 2018-07-05 14:58:40.622584297 +0200
+++ openssh-7.7p1/ssh.c 2018-07-05 13:40:25.464373698 +0200
@@ -522,6 +522,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, pw, host, host_arg, &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, pw, host, host_arg, &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, pw, host, host_arg, &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))
@@ -1283,8 +1309,12 @@
logit("FIPS mode initialized");
}
- if (options.user == NULL)
+ if (options.user == NULL) {
options.user = xstrdup(pw->pw_name);
+ options.implicit = 1;
+ } else {
+ options.implicit = 0;
+ }
/* Set up strings used to percent_expand() arguments */
if (gethostname(thishost, sizeof(thishost)) == -1)
diff -Nur openssh-7.7p1.orig/ssh_config openssh-7.7p1/ssh_config
--- openssh-7.7p1.orig/ssh_config 2018-07-05 14:58:40.622584297 +0200
+++ openssh-7.7p1/ssh_config 2018-07-05 13:40:25.464373698 +0200
@@ -22,10 +22,10 @@
# ForwardX11 no
# PasswordAuthentication yes
# HostbasedAuthentication no
-# GSSAPIAuthentication no
-# GSSAPIDelegateCredentials no
-# GSSAPIKeyExchange no
-# GSSAPITrustDNS no
+# GSSAPIAuthentication yes
+# GSSAPIDelegateCredentials yes
+# GSSAPIKeyExchange yes
+# GSSAPITrustDNS yes
# BatchMode no
# CheckHostIP yes
# AddressFamily any
diff -Nur openssh-7.7p1.orig/ssh_config.5 openssh-7.7p1/ssh_config.5
--- openssh-7.7p1.orig/ssh_config.5 2018-07-05 14:58:40.623584286 +0200
+++ openssh-7.7p1/ssh_config.5 2018-07-05 13:40:25.464373698 +0200
@@ -52,6 +52,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
@@ -727,7 +733,7 @@
.It Cm GSSAPIAuthentication
Specifies whether user authentication based on GSSAPI is allowed.
The default is
-.Cm no .
+.Cm yes .
.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
@@ -735,12 +741,12 @@
.It Cm GSSAPIDelegateCredentials
Forward (delegate) credentials to the server.
The default is
-.Cm no .
+.Cm yes .
.It Cm GSSAPIKeyExchange
Specifies whether key exchange based on GSSAPI may be used. When using
GSSAPI key exchange the server need not have a host key.
The default is
-.Dq no .
+.Dq yes .
.It Cm GSSAPIRenewalForcesRekey
If set to
.Dq yes
@@ -772,7 +778,7 @@
the hostname entered on the
command line will be passed untouched to the GSSAPI library.
The default is
-.Dq no .
+.Dq yes .
.It Cm GSSAPIKexAlgorithms
The list of key exchange algorithms that are offered for GSSAPI
key exchange. Possible values are
@@ -1234,7 +1240,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 ProxyCommand
diff -Nur openssh-7.7p1.orig/sshconnect2.c openssh-7.7p1/sshconnect2.c
--- openssh-7.7p1.orig/sshconnect2.c 2018-07-05 14:58:40.623584286 +0200
+++ openssh-7.7p1/sshconnect2.c 2018-07-05 13:40:25.465373687 +0200
@@ -285,7 +285,7 @@
#ifdef GSSAPI
char *orig = NULL, *gss = NULL;
- char *gss_host = NULL;
+ const char *gss_host = NULL;
#endif
xxx_host = host;
@@ -302,7 +302,7 @@
orig = options.kex_algorithms;
if (options.gss_trust_dns)
- gss_host = (char *)get_canonical_hostname(active_state, 1);
+ gss_host = get_canonical_hostname(active_state, 1);
else
gss_host = host;
@@ -841,6 +841,11 @@
int ok = 0;
const char *gss_host = NULL;
+ if (!options.gss_authentication) {
+ verbose("GSSAPI authentication disabled.");
+ return 0;
+ }
+
if (options.gss_server_identity)
gss_host = options.gss_server_identity;
else if (options.gss_trust_dns) {
@@ -930,7 +935,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 {
@@ -1078,6 +1084,20 @@
return 0;
}
+#ifdef GSI
+extern
+const gss_OID_desc * const gss_mech_globus_gssapi_openssl;
+extern
+const gss_OID_desc * const gss_mech_globus_gssapi_openssl_micv2;
+#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)) || \
+ (oid->length == gss_mech_globus_gssapi_openssl_micv2->length && \
+ (memcmp(oid->elements, gss_mech_globus_gssapi_openssl_micv2->elements, \
+ oid->length) == 0)))
+#endif
+
int
userauth_gsskeyex(Authctxt *authctxt)
{
@@ -1095,8 +1115,16 @@
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);
@@ -1107,7 +1135,15 @@
}
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);
diff -Nur openssh-7.7p1.orig/sshd.8 openssh-7.7p1/sshd.8
--- openssh-7.7p1.orig/sshd.8 2018-07-05 14:58:40.624584275 +0200
+++ openssh-7.7p1/sshd.8 2018-07-05 13:40:25.465373687 +0200
@@ -760,6 +760,44 @@
# 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 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.
+.El
.Sh FILES
.Bl -tag -width Ds -compact
.It Pa ~/.hushlogin
diff -Nur openssh-7.7p1.orig/sshd.c openssh-7.7p1/sshd.c
--- openssh-7.7p1.orig/sshd.c 2018-07-05 14:58:40.624584275 +0200
+++ openssh-7.7p1/sshd.c 2018-07-05 13:40:25.466373676 +0200
@@ -130,6 +130,7 @@
#include "auth-options.h"
#include "version.h"
#include "ssherr.h"
+#include "ssh-globus-usage.h"
/* Re-exec fds */
#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
@@ -1749,6 +1750,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;
@@ -2247,7 +2255,7 @@
#endif
#ifdef GSSAPI
- if (options.gss_authentication) {
+ if (options.gss_authentication && options.gss_deleg_creds) {
temporarily_use_uid(authctxt->pw);
authctxt->krb5_set_env = ssh_gssapi_storecreds();
restore_uid();
diff -Nur openssh-7.7p1.orig/sshd_config openssh-7.7p1/sshd_config
--- openssh-7.7p1.orig/sshd_config 2018-07-05 14:58:40.624584275 +0200
+++ openssh-7.7p1/sshd_config 2018-07-05 13:40:25.475373579 +0200
@@ -84,10 +84,11 @@
#KerberosUseKuserok yes
# GSSAPI options
-GSSAPIAuthentication yes
+#GSSAPIAuthentication yes
+#GSSAPIDelegateCredentials yes
GSSAPICleanupCredentials no
#GSSAPIStrictAcceptorCheck yes
-#GSSAPIKeyExchange no
+#GSSAPIKeyExchange yes
#GSSAPIEnablek5users no
# Set this to 'yes' to enable PAM authentication, account processing,
@@ -103,6 +104,10 @@
# problems.
UsePAM yes
+# 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
@@ -142,6 +147,10 @@
# override default of no subsystems
Subsystem sftp /usr/libexec/sftp-server
+# Usage Metrics
+#UsageStatsTargets usage-stats.example.edu:4810
+#DisableUsageStats yes
+
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
diff -Nur openssh-7.7p1.orig/sshd_config.5 openssh-7.7p1/sshd_config.5
--- openssh-7.7p1.orig/sshd_config.5 2018-07-05 14:58:40.626584254 +0200
+++ openssh-7.7p1/sshd_config.5 2018-07-05 13:40:25.466373676 +0200
@@ -575,6 +575,15 @@
TCP and StreamLocal.
This option overrides all other forwarding-related options and may
simplify restricted configurations.
+.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. 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 ExposeAuthInfo
Writes a temporary file containing a list of authentication methods and
public credentials (e.g. keys) used to authenticate the user.
@@ -632,15 +641,34 @@
to allow the client to select the address to which the forwarding is bound.
The default is
.Cm no .
+.It Cm GSIAllowLimitedProxy
+Specifies whether to accept limited proxy credentials for authentication.
+The default is
+.Cm no .
.It Cm GSSAPIAuthentication
Specifies whether user authentication based on GSSAPI is allowed.
The default is
-.Cm no .
+.Cm yes .
.It Cm GSSAPICleanupCredentials
Specifies whether to automatically destroy the user's credentials cache
on logout.
The default is
.Cm yes .
+.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 GSSAPIDelegateCredentials
+Specifies whether delegated credentials are stored in the user's environment.
+The default is
+.Cm yes .
.It Cm GSSAPIEnablek5users
Specifies whether to look at .k5users file for GSSAPI authentication
access control. Further details are described in
@@ -651,7 +679,7 @@
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 no .
+.Dq yes .
.It Cm GSSAPIStrictAcceptorCheck
Determines whether to be strict about the identity of the GSSAPI acceptor
a client authenticates against.
@@ -690,7 +718,6 @@
.Pp
The default is
.Dq gss-gex-sha1-,gss-group14-sha1- .
-This option only applies to protocol version 2 connections using GSSAPI.
.It Cm HostbasedAcceptedKeyTypes
Specifies the key types that will be accepted for hostbased authentication
as a comma-separated pattern list.
@@ -1556,6 +1583,103 @@
.Cm TrustedUserCAKeys .
For more details on certificates, see the CERTIFICATES section in
.Xr ssh-keygen 1 .
+.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
+.Cm default
+is specified, the tags
+.Cm 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
+.Cm I ,
+.Cm u
+and
+.Cm 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
+.Cm all
+denotes all tags.
+.El
+.Pp
+Usage Metrics reporting is disabled unless
+.Cm UsageStatsTargets
+is specified.
+.Pp
.It Cm UseDNS
Specifies whether
.Xr sshd 8
@@ -1597,6 +1721,12 @@
as a non-root user.
The default is
.Cm no .
+.It Cm PermitPAMUserChange
+If set to
+.Cm yes
+this will enable PAM authentication to change the name of the user being
+authenticated. The default is
+.Cm no .
.It Cm VersionAddendum
Optionally specifies additional text to append to the SSH protocol banner
sent by the server upon connection.
diff -Nur openssh-7.7p1.orig/ssh-globus-usage.c openssh-7.7p1/ssh-globus-usage.c
--- openssh-7.7p1.orig/ssh-globus-usage.c 1970-01-01 01:00:00.000000000 +0100
+++ openssh-7.7p1/ssh-globus-usage.c 2018-07-05 13:40:25.466373676 +0200
@@ -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 || !usage_stats_targets)
+ return GLOBUS_SUCCESS;
+
+ result = globus_module_activate(GLOBUS_USAGE_MODULE);
+ if (result != GLOBUS_SUCCESS)
+ {
+ error("ERROR: couldn't activate USAGE STATS module");
+ return result;
+ }
+
+ 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(const char *ssh_release, const char *ssl_release,
+ const char *method, const char *mechanism,
+ const char *clientip,
+ const char *username, const 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 = (char *) 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 = (char *) method;
+ break;
+
+ case SSH_GLOBUS_USAGE_MECHANISM:
+ key = "MECH";
+ value = (char *) mechanism?:"";
+ break;
+
+ case SSH_GLOBUS_USAGE_CLIENTIP:
+ key = "CLIENTIP";
+ value = (char *) clientip?:"";
+ break;
+
+ case SSH_GLOBUS_USAGE_USERNAME:
+ key = "USER";
+ value = (char *) username?:"";
+ break;
+
+ case SSH_GLOBUS_USAGE_USERDN:
+ key = "USERDN";
+ value = (char *) 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(const char *ssh_release,
+ const char *ssl_release,
+ const char *method,
+ const char *mechanism,
+ const char *client_ip,
+ const char *username,
+ const char *userdn)
+{
+#ifdef HAVE_GLOBUS_USAGE
+
+ log_usage_stats(ssh_release, ssl_release, method, mechanism,
+ client_ip, username, userdn);
+
+#endif /* HAVE_GLOBUS_USAGE */
+}
diff -Nur openssh-7.7p1.orig/ssh-globus-usage.h openssh-7.7p1/ssh-globus-usage.h
--- openssh-7.7p1.orig/ssh-globus-usage.h 1970-01-01 01:00:00.000000000 +0100
+++ openssh-7.7p1/ssh-globus-usage.h 2018-07-05 13:40:25.467373665 +0200
@@ -0,0 +1,48 @@
+/*
+ * 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"
+
+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(const char *ssh_release,
+ const char *ssl_release,
+ const char *method,
+ const char *mechanism,
+ const char *client_ip,
+ const char *username,
+ const char *userdn);
+
+#endif /* __SSH_GLOBUS_USAGE_H */
diff -Nur openssh-7.7p1.orig/ssh-gss.h openssh-7.7p1/ssh-gss.h
--- openssh-7.7p1.orig/ssh-gss.h 2018-07-05 14:58:40.627584243 +0200
+++ openssh-7.7p1/ssh-gss.h 2018-07-05 13:40:25.467373665 +0200
@@ -85,6 +85,7 @@
KEX_GSS_GRP14_SHA1_ID
typedef struct {
+ char *filename;
char *envvar;
char *envval;
struct passwd *owner;
@@ -92,12 +93,14 @@
} ssh_gssapi_ccache;
typedef struct {
+ gss_OID_desc oid;
gss_buffer_desc displayname;
gss_buffer_desc exportedname;
gss_cred_id_t creds;
- gss_name_t name;
+ gss_name_t cred_name, ctx_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;
@@ -118,7 +121,7 @@
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; /* both */
@@ -151,6 +154,9 @@
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 *);
@@ -161,7 +167,7 @@
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, struct passwd *);
+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);
@@ -174,6 +180,7 @@
int ssh_gssapi_update_creds(ssh_gssapi_ccache *store);
void ssh_gssapi_rekey_creds(void);
+void ssh_gssapi_get_client_info(char **userdn, char **mech);
#endif /* GSSAPI */
#endif /* _SSH_GSS_H */
diff -Nur openssh-7.7p1.orig/version.h openssh-7.7p1/version.h
--- openssh-7.7p1.orig/version.h 2018-07-05 14:58:40.627584243 +0200
+++ openssh-7.7p1/version.h 2018-07-05 13:40:25.467373665 +0200
@@ -2,5 +2,19 @@
#define SSH_VERSION "OpenSSH_7.7"
+#ifdef GSI
+#define GSI_VERSION " GSI"
+#else
+#define GSI_VERSION ""
+#endif
+
+#ifdef KRB5
+#define KRB5_VERSION " KRB5"
+#else
+#define KRB5_VERSION ""
+#endif
+
#define SSH_PORTABLE "p1"
-#define SSH_RELEASE SSH_VERSION SSH_PORTABLE
+#define GSI_PORTABLE "b-GSI"
+#define SSH_RELEASE SSH_VERSION SSH_PORTABLE GSI_PORTABLE \
+ GSI_VERSION KRB5_VERSION