PRIVSEP_PATH=@PRIVSEP_PATH@
PATHS= -D_PATH_SSH_PIDDIR=\"$(piddir)\" \
- -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\"
+ -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\"
CC=@CC@
LD=@LD@
/* A matching host key was found and is known. */
/* Perform the challenge-response dialog with the client for the host key. */
- if (!auth_rsa_challenge_dialog(client_host_key->rsa)) {
+ if (!auth_rsa_challenge_dialog(client_host_key)) {
log("Client on %.800s failed to respond correctly to host authentication.",
chost);
return 0;
/* Return false if AllowUsers isn't empty and user isn't listed there */
if (options.num_allow_users > 0) {
for (i = 0; i < options.num_allow_users; i++)
- if (match_user(pw->pw_name, hostname, ipaddr,
+ if (match_user(pw->pw_name, hostname, ipaddr,
options.allow_users[i]))
break;
/* i < options.num_allow_users iff we break for loop */
packet_check_eom();
#ifdef GSSAPI
- /* Parse GSSAPI identity from userstring */
- user = ssh1_gssapi_parse_userstring(user);
+ /* Parse GSSAPI identity from userstring */
+ user = ssh1_gssapi_parse_userstring(user);
#endif /* GSSAPI */
if ((style = strchr(user, ':')) != NULL)
#include "match.h"
#include "monitor_wrap.h"
#include "atomicio.h"
+#include "misc.h"
#ifdef GSSAPI
#include "ssh-gss.h"
AC_DEFINE(HAVE_PW_CHANGE_IN_PASSWD)
fi
+dnl make sure we're using the real structure members and not defines
AC_CACHE_CHECK([for msg_accrights field in struct msghdr],
ac_cv_have_accrights_in_msghdr, [
- AC_TRY_COMPILE(
+ AC_TRY_RUN(
[
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
+int main() {
+#ifdef msg_accrights
+exit(1);
+#endif
+struct msghdr m;
+m.msg_accrights = 0;
+exit(0);
+}
],
- [ struct msghdr m; m.msg_accrights = 0; ],
[ ac_cv_have_accrights_in_msghdr="yes" ],
[ ac_cv_have_accrights_in_msghdr="no" ]
)
AC_CACHE_CHECK([for msg_control field in struct msghdr],
ac_cv_have_control_in_msghdr, [
- AC_TRY_COMPILE(
+ AC_TRY_RUN(
[
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
+int main() {
+#ifdef msg_control
+exit(1);
+#endif
+struct msghdr m;
+m.msg_control = 0;
+exit(0);
+}
],
- [ struct msghdr m; m.msg_control = 0; ],
[ ac_cv_have_control_in_msghdr="yes" ],
[ ac_cv_have_control_in_msghdr="no" ]
)
AC_SUBST(user_path)
fi
+# Set superuser path separately to user path
+AC_ARG_WITH(superuser-path,
+ [ --with-superuser-path= Specify different path for super-user],
+ [
+ if test "x$withval" != "xno" ; then
+ AC_DEFINE_UNQUOTED(SUPERUSER_PATH, "$withval")
+ superuser_path=$withval
+ fi
+ fi ]
+)
+if test "$USES_LOGIN_CONF" != "yes" ; then
+ AC_DEFINE_UNQUOTED(USER_PATH, "$user_path")
+ AC_SUBST(user_path)
+fi
+
# Set superuser path separately to user path
AC_ARG_WITH(superuser-path,
[ --with-superuser-path= Specify different path for super-user],
/* All this effort to report an error ... */
-void
-ssh_gssapi_error(OM_uint32 major_status,OM_uint32 minor_status) {
+static void
+ssh_gssapi_error_ex(OM_uint32 major_status,OM_uint32 minor_status,
+ int send_packet) {
OM_uint32 lmaj, lmin;
gss_buffer_desc msg;
OM_uint32 ctx;
&ctx, &msg);
if (lmaj == GSS_S_COMPLETE) {
debug((char *)msg.value);
+ if (send_packet) packet_send_debug((char *)msg.value);
(void) gss_release_buffer(&lmin, &msg);
}
} while (ctx!=0);
&ctx, &msg);
if (lmaj == GSS_S_COMPLETE) {
debug((char *)msg.value);
+ if (send_packet) packet_send_debug((char *)msg.value);
(void) gss_release_buffer(&lmin, &msg);
}
} while (ctx!=0);
}
+void
+ssh_gssapi_error(OM_uint32 major_status,OM_uint32 minor_status) {
+ ssh_gssapi_error_ex(major_status, minor_status, 0);
+}
+
+void
+ssh_gssapi_send_error(OM_uint32 major_status,OM_uint32 minor_status) {
+ ssh_gssapi_error_ex(major_status, minor_status, 1);
+}
+
+
+
+
/* Initialise our GSSAPI context. We use this opaque structure to contain all
* of the data which both the client and server need to persist across
* {accept,init}_sec_context calls, so that when we do it from the userauth
NULL,
&ctx->client_creds);
if (GSS_ERROR(maj_status)) {
- ssh_gssapi_error(maj_status,min_status);
+ ssh_gssapi_send_error(maj_status,min_status);
}
if (ctx->client_creds) {
if (GSS_ERROR(maj_status)) {
/* Failure <sniff> */
+ ssh_gssapi_send_error(maj_status,min_status);
authctxt->postponed = 0;
dispatch_set(SSH_MSG_AUTH_GSSAPI_TOKEN, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
ssh_gssapi_build_ctx(&ctxt);
if (ssh_gssapi_id_kex(&ctxt,kex->name))
- fatal("Unknown gssapi mechanism");
+ packet_disconnect("Unknown gssapi mechanism");
if (ssh_gssapi_acquire_cred(&ctxt))
- fatal("Unable to acquire credentials for the server");
+ packet_disconnect("Unable to acquire credentials for the server");
do {
debug("Wait SSH2_MSG_GSSAPI_INIT");
switch(type) {
case SSH2_MSG_KEXGSS_INIT:
if (dh_client_pub!=NULL)
- fatal("Received KEXGSS_INIT after initialising");
+ packet_disconnect("Received KEXGSS_INIT after initialising");
recv_tok.value=packet_get_string(&recv_tok.length);
dh_client_pub = BN_new();
break;
case SSH2_MSG_KEXGSS_CONTINUE:
if (dh_client_pub == NULL)
- fatal("Received KEXGSS_CONTINUE without initialising");
+ packet_disconnect("Received KEXGSS_CONTINUE without initialising");
recv_tok.value=packet_get_string(&recv_tok.length);
break;
default:
#ifdef GSS_C_GLOBUS_LIMITED_PROXY_FLAG
if (ret_flags & GSS_C_GLOBUS_LIMITED_PROXY_FLAG) {
- fatal("Limited proxy is not allowed.");
+ packet_disconnect("Limited proxy is not allowed in gssapi key exchange.");
}
#endif
}
} while (maj_status & GSS_S_CONTINUE_NEEDED);
- if (GSS_ERROR(maj_status))
- fatal("gss_accept_context died");
-
+ if (GSS_ERROR(maj_status)) {
+ ssh_gssapi_send_error(maj_status,min_status);
+ packet_disconnect("gssapi key exchange handshake failed");
+ }
+
debug("gss_complete");
- if (!(ret_flags & GSS_C_MUTUAL_FLAG))
- fatal("mutual authentication flag wasn't set");
-
- if (!(ret_flags & GSS_C_INTEG_FLAG))
- fatal("Integrity flag wasn't set");
+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) {
+ ssh_gssapi_send_error(maj_status,min_status);
+ packet_disconnect("gssapi mutual authentication failed");
+ }
+ if (!(ret_flags & GSS_C_INTEG_FLAG)) {
+ ssh_gssapi_send_error(maj_status,min_status);
+ packet_disconnect("gssapi channel integrity not established");
+ }
dh = dh_new_group1();
dh_gen_key(dh, kex->we_need * 8);
GSS_C_QOP_DEFAULT,
&gssbuf,
&msg_tok))) {
- ssh_gssapi_error(maj_status,min_status);
- fatal("Couldn't get MIC");
+ ssh_gssapi_send_error(maj_status,min_status);
+ packet_disconnect("Couldn't get MIC");
}
packet_start(SSH2_MSG_KEXGSS_COMPLETE);
if (ssh_gssapi_getclient(&ctxt,&gssapi_client_type,
&gssapi_client_name,
&gssapi_client_creds)) {
- fatal("Couldn't convert client name");
+ packet_disconnect("Couldn't convert client name");
}
gss_release_buffer(&min_status, &send_tok);
struct iovec vec;
char ch = '\0';
int n;
-#if !defined(HAVE_ACCRIGHTS_IN_MSGHDR) || \
- (defined(HAVE_ACCRIGHTS_IN_MSGHDR) && defined(HAVE_CONTROL_IN_MSGHDR))
+#ifndef HAVE_ACCRIGHTS_IN_MSGHDR
char tmp[CMSG_SPACE(sizeof(int))];
struct cmsghdr *cmsg;
#endif
memset(&msg, 0, sizeof(msg));
-#if defined(HAVE_ACCRIGHTS_IN_MSGHDR) && !defined(HAVE_CONTROL_IN_MSGHDR)
+#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
msg.msg_accrights = (caddr_t)&fd;
msg.msg_accrightslen = sizeof(fd);
#else
struct iovec vec;
char ch;
int fd, n;
-#if !defined(HAVE_ACCRIGHTS_IN_MSGHDR) || \
- (defined(HAVE_ACCRIGHTS_IN_MSGHDR) && defined(HAVE_CONTROL_IN_MSGHDR))
+#ifndef HAVE_ACCRIGHTS_IN_MSGHDR
char tmp[CMSG_SPACE(sizeof(int))];
struct cmsghdr *cmsg;
#endif
vec.iov_len = 1;
msg.msg_iov = &vec;
msg.msg_iovlen = 1;
-#if defined(HAVE_ACCRIGHTS_IN_MSGHDR) && !defined(HAVE_CONTROL_IN_MSGHDR)
+#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
msg.msg_accrights = (caddr_t)&fd;
msg.msg_accrightslen = sizeof(fd);
#else
fatal("%s: recvmsg: expected received 1 got %d",
__FUNCTION__, n);
-#if defined(HAVE_ACCRIGHTS_IN_MSGHDR) && !defined(HAVE_CONTROL_IN_MSGHDR)
+#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
if (msg.msg_accrightslen != sizeof(fd))
fatal("%s: no fd", __FUNCTION__);
#else
#define _PATH_PRIVSEP_CHROOT_DIR "/var/empty"
#endif
+/* chroot directory for unprivileged user when UsePrivilegeSeparation=yes */
+#ifndef _PATH_PRIVSEP_CHROOT_DIR
+#define _PATH_PRIVSEP_CHROOT_DIR "/var/empty"
+#endif
+
#ifndef _PATH_LS
#define _PATH_LS "ls"
#endif
gss_buffer_desc *name,
gss_cred_id_t *creds);
void ssh_gssapi_error(OM_uint32 major_status,OM_uint32 minor_status);
+void ssh_gssapi_send_error(OM_uint32 major_status,OM_uint32 minor_status);
void ssh_gssapi_build_ctx(Gssctxt *ctx);
void ssh_gssapi_delete_ctx(Gssctxt *ctx);
.Nm
obtains configuration data from the following sources in
the following order:
-command line options, user's configuration file
+command line options,
+feature-specific user configuration file(s) (see below),
+user's configuration file
.Pq Pa $HOME/.ssh/config ,
and system-wide configuration file
.Pq Pa /etc/ssh/ssh_config .
+For compatibility with other
+.Nm
+versions, the following feature-specific user configuration files
+will be processed after the command line options but before the user's
+main configuration file, so options that other
+.Nm
+versions may not support don't need to go in the main configuration file:
+.Bl -tag -width Ds
+.It Pa $HOME/.ssh/config.gssapi
+Read if GSSAPI authentication is supported. This is a good place for
+the GssapiAuthentication and GssapiDelegateCredentials options.
+.It Pa $HOME/.ssh/config.krb
+Read if Kerberos authentication is supported. This is a good place
+for the KerberosAuthentication and KerberosTgtPassing options.
+.It Pa $HOME/.ssh/config.afs
+Read if AFS token passing is supported. This is a good place for the
+AfsTokenPassing option.
+.El
+.Pp
For each parameter, the first obtained value
will be used.
The configuration files contain sections bracketed by
Specifies a file to use for the global
host key database instead of
.Pa /etc/ssh/ssh_known_hosts .
+.It Cm GssapiAuthentication
+Specifies whether authentication based on GSSAPI may be used, either using
+the result of a successful key exchange, or using GSSAPI user
+authentication.
+The default is
+.Dq yes .
+.It Cm GssapiDelegateCredentials
+Specifies whether GSSAPI credentials will be delegated (forwarded) to
+the server.
+The default is
+.Dq yes .
.It Cm HostbasedAuthentication
Specifies whether to try rhosts based authentication with public key
authentication.
fatal("Can't open user config file %.100s: "
"%.100s", config, strerror(errno));
} else {
+ /*
+ * Since the config file parsing code aborts if it sees
+ * options it doesn't recognize, allow users to put
+ * options specific to compile-time add-ons in alternate
+ * config files so their primary config file will
+ * interoperate SSH versions that don't support those
+ * options.
+ */
+#ifdef GSSAPI
+ snprintf(buf, sizeof buf, "%.100s/%.100s.gssapi", pw->pw_dir,
+ _PATH_SSH_USER_CONFFILE);
+ (void)read_config_file(buf, host, &options);
+#ifdef GSI
+ snprintf(buf, sizeof buf, "%.100s/%.100s.gsi", pw->pw_dir,
+ _PATH_SSH_USER_CONFFILE);
+ (void)read_config_file(buf, host, &options);
+#endif
+#if defined(KRB4) || defined(KRB5)
+ snprintf(buf, sizeof buf, "%.100s/%.100s.krb", pw->pw_dir,
+ _PATH_SSH_USER_CONFFILE);
+ (void)read_config_file(buf, host, &options);
+#endif
+#ifdef AFS
+ snprintf(buf, sizeof buf, "%.100s/%.100s.afs", pw->pw_dir,
+ _PATH_SSH_USER_CONFFILE);
+ (void)read_config_file(buf, host, &options);
+#endif
+#endif
snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir,
_PATH_SSH_USER_CONFFILE);
(void)read_config_file(buf, host, &options);
authentication.
The default is
.Dq yes .
-Note that this option applies to protocol version 2 only.
.It Cm GssapiKeyExchange
Specifies whether key exchange based on GSSAPI may be used. When using
GSSAPI key exchange the server need not have a host key.
The default is
.Dq yes .
-Note that this option applies to protocol version 2 only.
.It Cm GssapiUseSessionCredCache
Specifies whether a unique credentials cache name should be generated per
session for storing delegated credentials.
The default is
.Dq yes .
-Note that this option applies to protocol version 2 only.
.It Cm HostKey
Specifies a file containing a private host key
used by SSH.