394061aa31
security/ssh6: IPv4/v6 ready, socks unavailable, kerberos available (not tested) security/ssh: IPv4 onlyready, socks available, kerberos available (not tested) should be integrated into one whenever socks support becomes aware of getaddrinfo/getnameinfo. two directories with tons of patches/patch-* is a maintenance headache.
1141 lines
36 KiB
Text
1141 lines
36 KiB
Text
$NetBSD: patch-af,v 1.1 2000/03/20 02:25:34 itojun Exp $
|
|
|
|
--- sshd.c.orig Wed May 12 13:19:29 1999
|
|
+++ sshd.c Mon Mar 6 15:19:36 2000
|
|
@@ -511,7 +511,7 @@
|
|
#include "firewall.h" /* TIS authsrv authentication */
|
|
#endif
|
|
|
|
-#if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)
|
|
+#if (defined (__FreeBSD__) || defined(__NetBSD__)) && defined(HAVE_LOGIN_CAP_H)
|
|
#include <login_cap.h>
|
|
#endif
|
|
|
|
@@ -537,15 +537,26 @@
|
|
#define O_NOCTTY 0
|
|
#endif
|
|
|
|
-#ifdef KERBEROS
|
|
#ifdef KRB5
|
|
#include <krb5.h>
|
|
/* Global the contexts */
|
|
krb5_context ssh_context = 0;
|
|
krb5_auth_context auth_context = 0;
|
|
#endif /* KRB5 */
|
|
-char *ticket = "none\0";
|
|
-#endif /* KERBEROS */
|
|
+
|
|
+#ifdef KRB4
|
|
+#include <sys/param.h>
|
|
+#include <krb.h>
|
|
+#ifdef AFS
|
|
+#include <kafs.h>
|
|
+/* Local Xauthority file. */
|
|
+char *xauthfile = NULL;
|
|
+#endif /* AFS */
|
|
+#endif /* KRB4 */
|
|
+
|
|
+#if defined(KRB5) || defined(KRB4)
|
|
+char *ticket = NULL;
|
|
+#endif /* KRB5 || KRB4 */
|
|
|
|
/* Server configuration options. */
|
|
ServerOptions options;
|
|
@@ -553,6 +564,19 @@
|
|
/* Name of the server configuration file. */
|
|
char *config_file_name = SERVER_CONFIG_FILE;
|
|
|
|
+/* Flag indicating whether IPv4 or IPv6. This can be set on the command line.
|
|
+ Default value is AF_UNSPEC means both IPv4 and IPv6. */
|
|
+#ifdef ENABLE_IPV6
|
|
+int IPv4or6 = AF_UNSPEC;
|
|
+#else
|
|
+int IPv4or6 = AF_INET;
|
|
+#endif
|
|
+
|
|
+#ifdef ENABLE_LOG_AUTH
|
|
+char *unauthenticated_user = NULL;
|
|
+int log_auth_flag = 0;
|
|
+#endif /* ENABLE_LOG_AUTH */
|
|
+
|
|
/* Debug mode flag. This can be set on the command line. If debug
|
|
mode is enabled, extra debugging output will be sent to the system
|
|
log, the daemon will not go to background, and will exit after processing
|
|
@@ -576,7 +600,17 @@
|
|
|
|
/* This is set to the socket that the server is listening; this is used in
|
|
the SIGHUP signal handler. */
|
|
-int listen_sock;
|
|
+#define MAX_LISTEN_SOCKS 16
|
|
+int listen_socks[MAX_LISTEN_SOCKS];
|
|
+int num_listen_socks = 0;
|
|
+void close_listen_socks()
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < num_listen_socks; i++)
|
|
+ close(listen_socks[i]);
|
|
+ num_listen_socks = -1;
|
|
+}
|
|
|
|
/* This is not really needed, and could be eliminated if server-specific
|
|
and client-specific code were removed from newchannels.c */
|
|
@@ -649,7 +683,6 @@
|
|
const char *display, const char *auth_proto,
|
|
const char *auth_data, const char *ttyname);
|
|
|
|
-
|
|
/* Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP;
|
|
the effect is to reread the configuration file (and to regenerate
|
|
the server key). */
|
|
@@ -666,7 +699,7 @@
|
|
void sighup_restart(void)
|
|
{
|
|
log_msg("Received SIGHUP; restarting.");
|
|
- close(listen_sock);
|
|
+ close_listen_socks();
|
|
execvp(saved_argv[0], saved_argv);
|
|
log_msg("RESTART FAILED: av[0]='%.100s', error: %.100s.",
|
|
saved_argv[0], strerror(errno));
|
|
@@ -680,7 +713,7 @@
|
|
RETSIGTYPE sigterm_handler(int sig)
|
|
{
|
|
log_msg("Received signal %d; terminating.", sig);
|
|
- close(listen_sock);
|
|
+ close_listen_socks();
|
|
exit(255);
|
|
}
|
|
|
|
@@ -759,7 +792,7 @@
|
|
int perm_denied = 0;
|
|
int ret;
|
|
fd_set fdset;
|
|
- struct sockaddr_in sin;
|
|
+ struct sockaddr_storage from;
|
|
char buf[100]; /* Must not be larger than remote_version. */
|
|
char remote_version[100]; /* Must be at least as big as buf. */
|
|
char *comment;
|
|
@@ -769,6 +802,9 @@
|
|
struct linger linger;
|
|
#endif /* SO_LINGER */
|
|
int done;
|
|
+ struct addrinfo *ai;
|
|
+ char ntop[ADDRSTRLEN], strport[PORTSTRLEN];
|
|
+ int listen_sock, maxfd;
|
|
|
|
/* Save argv[0]. */
|
|
saved_argv = av;
|
|
@@ -787,10 +823,26 @@
|
|
initialize_server_options(&options);
|
|
|
|
/* Parse command-line arguments. */
|
|
- while ((opt = getopt(ac, av, "f:p:b:k:h:g:diqV:")) != EOF)
|
|
+ while ((opt = getopt(ac, av, "f:p:b:k:h:g:diqV:4"
|
|
+#ifdef ENABLE_IPV6
|
|
+ "6"
|
|
+#endif
|
|
+ )) != EOF)
|
|
{
|
|
switch (opt)
|
|
{
|
|
+ case '4':
|
|
+#ifdef ENABLE_IPV6
|
|
+ IPv4or6 = (IPv4or6 == AF_INET6) ? AF_UNSPEC : AF_INET;
|
|
+#else
|
|
+ IPv4or6 = AF_INET;
|
|
+#endif
|
|
+ break;
|
|
+#ifdef ENABLE_IPV6
|
|
+ case '6':
|
|
+ IPv4or6 = (IPv4or6 == AF_INET) ? AF_UNSPEC : AF_INET6;
|
|
+ break;
|
|
+#endif
|
|
case 'f':
|
|
config_file_name = optarg;
|
|
break;
|
|
@@ -807,7 +859,7 @@
|
|
options.server_key_bits = atoi(optarg);
|
|
break;
|
|
case 'p':
|
|
- options.port = atoi(optarg);
|
|
+ options.ports[options.num_ports++] = atoi(optarg);
|
|
break;
|
|
case 'g':
|
|
options.login_grace_time = atoi(optarg);
|
|
@@ -829,6 +881,10 @@
|
|
fprintf(stderr, "sshd version %s [%s]\n", SSH_VERSION, HOSTTYPE);
|
|
fprintf(stderr, "Usage: %s [options]\n", av0);
|
|
fprintf(stderr, "Options:\n");
|
|
+ fprintf(stderr, " -4 Use IPv4 only\n");
|
|
+#ifdef ENABLE_IPV6
|
|
+ fprintf(stderr, " -6 Use IPv6 only\n");
|
|
+#endif
|
|
fprintf(stderr, " -f file Configuration file (default %s/sshd_config)\n", ETCDIR);
|
|
fprintf(stderr, " -d Debugging mode\n");
|
|
fprintf(stderr, " -i Started from inetd\n");
|
|
@@ -857,16 +913,15 @@
|
|
fprintf(stderr, "fatal: Bad server key size.\n");
|
|
exit(1);
|
|
}
|
|
- if (options.port < 1 || options.port > 65535)
|
|
- {
|
|
- fprintf(stderr, "fatal: Bad port number.\n");
|
|
- exit(1);
|
|
- }
|
|
if (options.umask != -1)
|
|
{
|
|
umask(options.umask);
|
|
}
|
|
|
|
+#ifdef ENABLE_LOG_AUTH
|
|
+ log_auth_flag = options.log_auth;
|
|
+#endif /* ENABLE_LOG_AUTH */
|
|
+
|
|
/* Check that there are no remaining arguments. */
|
|
if (optind < ac)
|
|
{
|
|
@@ -1034,10 +1089,13 @@
|
|
}
|
|
else
|
|
{
|
|
+ for (ai = options.listen_addrs; ai; ai = ai->ai_next)
|
|
+ {
|
|
/* Create socket for listening. */
|
|
- listen_sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
+ listen_sock = socket(ai->ai_family, SOCK_STREAM, 0);
|
|
if (listen_sock < 0)
|
|
fatal("socket: %.100s", strerror(errno));
|
|
+ listen_socks[num_listen_socks] = listen_sock;
|
|
|
|
/* Set socket options. We try to make the port reusable and have it
|
|
close as fast as possible without waiting in unnecessary wait states
|
|
@@ -1051,21 +1109,30 @@
|
|
sizeof(linger));
|
|
#endif /* SO_LINGER */
|
|
|
|
- /* Initialize the socket address. */
|
|
- memset(&sin, 0, sizeof(sin));
|
|
- sin.sin_family = AF_INET;
|
|
- sin.sin_addr = options.listen_addr;
|
|
- sin.sin_port = htons(options.port);
|
|
+ getnameinfo(ai->ai_addr, ai->ai_addrlen,
|
|
+ ntop, sizeof(ntop), strport, sizeof(strport),
|
|
+ NI_NUMERICHOST|NI_NUMERICSERV);
|
|
|
|
/* Bind the socket to the desired port. */
|
|
- if (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
|
|
+ if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0)
|
|
{
|
|
- error("bind: %.100s", strerror(errno));
|
|
- shutdown(listen_sock, 2);
|
|
+ error("Bind to port %s on %s failed: %.200s.",
|
|
+ strport, ntop, strerror(errno));
|
|
close(listen_sock);
|
|
- fatal("Bind to port %d failed: %.200s.", options.port,
|
|
- strerror(errno));
|
|
+ continue;
|
|
}
|
|
+ num_listen_socks++;
|
|
+
|
|
+ /* Start listening on the port. */
|
|
+ log_msg("Server listening on %s port %s.", ntop, strport);
|
|
+ if (listen(listen_sock, 5) < 0)
|
|
+ fatal("listen: %.100s", strerror(errno));
|
|
+
|
|
+ } /* for (ai = options.listen_addrs; ai; ai = ai->ai_next) */
|
|
+ freeaddrinfo(options.listen_addrs);
|
|
+
|
|
+ if (!num_listen_socks)
|
|
+ fatal("Cannot bind all addresses.");
|
|
|
|
if (!debug_flag)
|
|
{
|
|
@@ -1081,11 +1148,6 @@
|
|
}
|
|
}
|
|
|
|
- /* Start listening on the port. */
|
|
- log_msg("Server listening on port %d.", options.port);
|
|
- if (listen(listen_sock, 5) < 0)
|
|
- fatal("listen: %.100s", strerror(errno));
|
|
-
|
|
/* Generate an rsa key. */
|
|
log_msg("Generating %d bit RSA key.", options.server_key_bits);
|
|
rsa_generate_key(&sensitive_data.private_key, &public_key,
|
|
@@ -1115,7 +1177,6 @@
|
|
/* Arrange SIGCHLD to be caught. */
|
|
signal(SIGCHLD, main_sigchld_handler);
|
|
|
|
-#ifdef KERBEROS
|
|
#ifdef KRB5
|
|
/* Initialize contexts and setup replay cache */
|
|
if (!ssh_context)
|
|
@@ -1128,7 +1189,6 @@
|
|
krb5_init_ets(ssh_context);
|
|
}
|
|
#endif
|
|
-#endif
|
|
|
|
/* Stay listening for connections until the system crashes or the
|
|
daemon is killed with a signal. */
|
|
@@ -1139,9 +1199,15 @@
|
|
|
|
/* Wait in select until there is a connection. */
|
|
FD_ZERO(&fdset);
|
|
- FD_SET(listen_sock, &fdset);
|
|
- ret = select(listen_sock + 1, &fdset, NULL, NULL, NULL);
|
|
- if (ret < 0 || !FD_ISSET(listen_sock, &fdset))
|
|
+ maxfd = 0;
|
|
+ for (i = 0; i < num_listen_socks; i++)
|
|
+ {
|
|
+ FD_SET(listen_socks[i], &fdset);
|
|
+ if (listen_socks[i] > maxfd)
|
|
+ maxfd = listen_socks[i];
|
|
+ }
|
|
+ ret = select(maxfd + 1, &fdset, NULL, NULL, NULL);
|
|
+ if (ret < 0)
|
|
{
|
|
if (errno == EINTR)
|
|
continue;
|
|
@@ -1149,8 +1215,12 @@
|
|
continue;
|
|
}
|
|
|
|
- aux = sizeof(sin);
|
|
- newsock = accept(listen_sock, (struct sockaddr *)&sin, &aux);
|
|
+ for (i = 0; i < num_listen_socks; i++)
|
|
+ {
|
|
+ if (!FD_ISSET(listen_socks[i], &fdset))
|
|
+ continue;
|
|
+ aux = sizeof(from);
|
|
+ newsock = accept(listen_socks[i], (struct sockaddr *)&from, &aux);
|
|
if (newsock < 0)
|
|
{
|
|
if (errno == EINTR)
|
|
@@ -1166,7 +1236,7 @@
|
|
/* In debugging mode. Close the listening socket, and start
|
|
processing the connection without forking. */
|
|
debug("Server will not fork when running in debugging mode.");
|
|
- close(listen_sock);
|
|
+ close_listen_socks();
|
|
sock_in = newsock;
|
|
sock_out = newsock;
|
|
pid = getpid();
|
|
@@ -1195,7 +1265,7 @@
|
|
the accepted socket. Reinitialize logging (since our
|
|
pid has changed). We break out of the loop to handle
|
|
the connection. */
|
|
- close(listen_sock);
|
|
+ close_listen_socks();
|
|
sock_in = newsock;
|
|
sock_out = newsock;
|
|
#ifdef LIBWRAP
|
|
@@ -1233,6 +1303,10 @@
|
|
|
|
/* Close the new socket (the child is now taking care of it). */
|
|
close(newsock);
|
|
+ } /* for (i = 0; i < num_host_socks; i++) */
|
|
+ /* child process check (or debug mode) */
|
|
+ if (num_listen_socks < 0)
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
@@ -1407,6 +1481,16 @@
|
|
/* Try to remove authentication socket and directory */
|
|
auth_delete_socket(NULL);
|
|
|
|
+#ifdef KRB4
|
|
+ /* Cleanup user's ticket cache file. */
|
|
+ if (options.kerberos_ticket_cleanup)
|
|
+ (void) dest_tkt();
|
|
+#ifdef AFS
|
|
+ /* Cleanup user's local Xauthority file. */
|
|
+ if (xauthfile) unlink(xauthfile);
|
|
+#endif /* AFS */
|
|
+#endif /* KRB4 */
|
|
+
|
|
/* The connection has been terminated. */
|
|
log_msg("Closing connection to %.100s", get_remote_ipaddr());
|
|
packet_close();
|
|
@@ -1470,17 +1554,17 @@
|
|
if (options.tis_authentication)
|
|
auth_mask |= 1 << SSH_AUTH_TIS;
|
|
#endif
|
|
-#ifdef KERBEROS
|
|
-#ifdef KRB5
|
|
+#if defined(KRB4) || defined(KRB5)
|
|
if (options.kerberos_authentication)
|
|
auth_mask |= 1 << SSH_AUTH_KERBEROS;
|
|
#endif
|
|
-#endif
|
|
-#ifdef KERBEROS_TGT_PASSING
|
|
-#ifdef KRB5
|
|
+#if defined(AFS) || defined(KRB5)
|
|
if (options.kerberos_tgt_passing)
|
|
auth_mask |= 1 << SSH_PASS_KERBEROS_TGT;
|
|
#endif
|
|
+#ifdef AFS
|
|
+ if (options.afs_token_passing)
|
|
+ auth_mask |= 1 << SSH_PASS_AFS_TOKEN;
|
|
#endif
|
|
if (options.password_authentication)
|
|
auth_mask |= 1 << SSH_AUTH_PASSWORD;
|
|
@@ -1677,7 +1761,7 @@
|
|
/* XXX No days_before_password_expires calculation here */
|
|
}
|
|
#endif /* HAVE_USERSEC_H */
|
|
-#ifdef HAVE_ETC_SHADOW
|
|
+#if defined(HAVE_ETC_SHADOW) && !defined(KRB4) && !defined(KRB5)
|
|
{
|
|
struct spwd *sp;
|
|
|
|
@@ -1783,56 +1867,62 @@
|
|
endspent();
|
|
}
|
|
#endif /* HAVE_ETC_SHADOW */
|
|
-#ifdef __FreeBSD__
|
|
- {
|
|
+/* Net2,BSD4.4,BSD/OS,NetBSD,FreeBSD and OpenBSD all define BSD4_4
|
|
+ man passwd(5) says that format has changed since BSD4.3
|
|
+ */
|
|
+#ifdef BSD4_4
|
|
+ if(pwd->pw_change || pwd->pw_expire) {
|
|
time_t currtime;
|
|
|
|
- if (pwd->pw_change || pwd->pw_expire)
|
|
currtime = time(NULL);
|
|
|
|
/*
|
|
* Check for an expired password
|
|
*/
|
|
- if (pwd->pw_change && pwd->pw_change <= currtime)
|
|
+
|
|
+ if (pwd->pw_change)
|
|
{
|
|
- debug("Account %.100s's password is too old - forced to change.",
|
|
- user);
|
|
- if (options.forced_passwd_change)
|
|
+ /* PASSWD_CHGNOW seems to be -1 for now but... */
|
|
+ if (
|
|
+#if defined(PASSWD_CHGNOW) && PASSWD_CHGNOW > 0
|
|
+ pwd->pw_change == PASSWD_CHGNOW ||
|
|
+#endif
|
|
+ pwd->pw_change <= currtime)
|
|
{
|
|
- forced_command = xmalloc(sizeof(PASSWD_PATH) + strlen(user) + 2);
|
|
- snprintf(forced_command, sizeof(PASSWD_PATH) + strlen(user) + 2,
|
|
- "%.100s %.100s", PASSWD_PATH, user);
|
|
+ packet_send_debug("Password has expired");
|
|
+ if(options.forced_passwd_change)
|
|
+ {
|
|
+ debug("Account %.99s's password is too old - change forced.",
|
|
+ user);
|
|
+ forced_command = xmalloc(sizeof(PASSWD_PATH) +
|
|
+ strlen(user) + 1);
|
|
+ sprintf(forced_command, "%s %s", PASSWD_PATH, user);
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
- else
|
|
- {
|
|
- if (pwd->pw_change)
|
|
- {
|
|
+#ifdef PASSWD_CHGNOW
|
|
+ if(pwd->pw_change != PASSWD_CHGNOW)
|
|
days_before_password_expires = (pwd->pw_change - currtime) / 86400;
|
|
- }
|
|
+#endif
|
|
}
|
|
|
|
/*
|
|
* Check for expired account
|
|
*/
|
|
- if (pwd->pw_expire && pwd->pw_expire <= currtime)
|
|
+ if (pwd->pw_expire)
|
|
{
|
|
- debug("Account %.100s has expired - access denied.", user);
|
|
+ if (pwd->pw_expire <= currtime)
|
|
+ {
|
|
+ packet_send_debug("Account has expired");
|
|
return 0;
|
|
}
|
|
- else
|
|
- {
|
|
- if (pwd->pw_expire)
|
|
- {
|
|
days_before_account_expires = (pwd->pw_expire - currtime) / 86400;
|
|
}
|
|
}
|
|
- }
|
|
-#endif /* !FreeBSD */
|
|
+#endif /* !BSD4_4 */
|
|
|
|
#ifdef HAVE_HPUX_TCB_AUTH
|
|
{
|
|
@@ -2039,7 +2129,7 @@
|
|
}
|
|
}
|
|
|
|
- /* Check whether logins are deneid for this group. */
|
|
+ /* Check whether logins are denied for this group. */
|
|
grp = getgrgid(pwd->pw_gid);
|
|
if (grp)
|
|
group = grp->gr_name;
|
|
@@ -2151,12 +2241,12 @@
|
|
unsigned int client_host_key_bits;
|
|
MP_INT client_host_key_e, client_host_key_n;
|
|
int password_attempts = 0;
|
|
-#if defined(KERBEROS) && defined(KRB5)
|
|
+#ifdef KRB5
|
|
char kuser[256];
|
|
krb5_principal client = 0, tkt_client = 0;
|
|
krb5_data krb5data;
|
|
-#endif /* defined(KERBEROS) && defined(KRB5) */
|
|
-#if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)
|
|
+#endif /* KRB5 */
|
|
+#if (defined (__FreeBSD__) || defined(__NetBSD__)) && defined(HAVE_LOGIN_CAP_H)
|
|
login_cap_t *lc;
|
|
const char *hostname;
|
|
const char *ipaddr;
|
|
@@ -2167,10 +2257,18 @@
|
|
ipaddr = get_remote_ipaddr();
|
|
#endif /* HAVE_LOGIN_CAP_H */
|
|
|
|
+#ifdef AFS
|
|
+ /* If machine has AFS, set process authentication group. */
|
|
+ if (k_hasafs()) {
|
|
+ k_setpag();
|
|
+ k_unlog();
|
|
+ }
|
|
+#endif /* AFS */
|
|
+
|
|
if (strlen(user) > 255)
|
|
do_authentication_fail_loop();
|
|
|
|
-#if defined(KERBEROS) && defined(KRB5)
|
|
+#ifdef KRB5
|
|
/* For KRB5 allow the user to input fully qualified name i.e.
|
|
"username@realm" as the local user name. Then use this name to call
|
|
out to krb5_aname_to_localname to find if there is a localname
|
|
@@ -2203,8 +2301,11 @@
|
|
}
|
|
else
|
|
krb5_parse_name(ssh_context, user, &client);
|
|
-#endif /* defined(KERBEROS) && defined(KRB5) */
|
|
+#endif /* KRB5 */
|
|
|
|
+#ifdef ENABLE_LOG_AUTH
|
|
+ unauthenticated_user = user;
|
|
+#endif /* ENABLE_LOG_AUTH */
|
|
/* Verify that the user is a valid user. We disallow usernames starting
|
|
with any characters that are commonly used to start NIS entries. */
|
|
pw = getpwnam(user);
|
|
@@ -2218,11 +2319,11 @@
|
|
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
|
|
pwcopy.pw_uid = pw->pw_uid;
|
|
pwcopy.pw_gid = pw->pw_gid;
|
|
-#if (defined (__bsdi__) && _BSDI_VERSION >= 199510) || (defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H))
|
|
+#ifdef BSD4_4
|
|
pwcopy.pw_class = xstrdup(pw->pw_class);
|
|
pwcopy.pw_change = pw->pw_change;
|
|
pwcopy.pw_expire = pw->pw_expire;
|
|
-#endif /* __bsdi__ && _BSDI_VERSION >= 199510 */
|
|
+#endif /* BSD4_4 */
|
|
pwcopy.pw_dir = xstrdup(pw->pw_dir);
|
|
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
|
pw = &pwcopy;
|
|
@@ -2241,11 +2342,11 @@
|
|
|
|
debug("Attempting authentication for %.100s.", user);
|
|
|
|
-#if defined (KERBEROS) && defined (KRB5)
|
|
+ /* If the user has no password, accept authentication immediately. */
|
|
+#ifdef KRB5
|
|
if (!options.kerberos_authentication && options.password_authentication &&
|
|
auth_password(user, "", 0))
|
|
-#else /* defined(KERBEROS) && defined(KRB5) */
|
|
- /* If the user has no password, accept authentication immediately. */
|
|
+#else /* KRB5 */
|
|
#if defined (HAVE_SIA)
|
|
/* For SIA, only call auth_password() here if the user really
|
|
has no password. Otherwise, the call would generate misleading
|
|
@@ -2254,12 +2355,21 @@
|
|
if (options.password_authentication && sia_no_password(user) &&
|
|
auth_password(user, ""))
|
|
#else /* defined(HAVE_SIA) */
|
|
- if (options.password_authentication && auth_password(user, ""))
|
|
+ if (options.password_authentication &&
|
|
+#ifdef KRB4
|
|
+ options.kerberos_or_local_passwd &&
|
|
+#endif /* KRB4 */
|
|
+ auth_password(user, ""))
|
|
#endif /* defined(HAVE_SIA) */
|
|
-#endif /* defined(KERBEROS) && defined(KRB5) */
|
|
+#endif /* KRB5 */
|
|
{
|
|
/* Authentication with empty password succeeded. */
|
|
debug("Login for user %.100s accepted without authentication.", user);
|
|
+#ifdef ENABLE_LOG_AUTH
|
|
+ log_auth("%.100s from %.700s (%s)",
|
|
+ user, get_canonical_hostname(),
|
|
+ "empty password accepted");
|
|
+#endif /* ENABLE_LOG_AUTH */
|
|
authentication_type = SSH_AUTH_PASSWORD;
|
|
authenticated = 1;
|
|
/* Success packet will be sent after loop below. */
|
|
@@ -2281,34 +2391,61 @@
|
|
/* Process the packet. */
|
|
switch (type)
|
|
{
|
|
-#ifdef KERBEROS_TGT_PASSING
|
|
-#ifdef KRB5
|
|
+#if defined(KRB5) || defined(AFS)
|
|
case SSH_CMSG_HAVE_KERBEROS_TGT:
|
|
+#ifdef KRB5
|
|
if (!options.kerberos_tgt_passing ||
|
|
(!(options.kerberos_authentication ||
|
|
options.password_authentication ||
|
|
options.rsa_authentication)))
|
|
+#else /* KRB5 */
|
|
+ if (!options.kerberos_tgt_passing)
|
|
+#endif /* KRB5 */
|
|
{
|
|
packet_get_all();
|
|
log_msg("Kerberos tgt passing disabled.");
|
|
break;
|
|
}
|
|
-
|
|
+#ifdef KRB5
|
|
/* Accept Kerberos tgt. */
|
|
krb5data.data = packet_get_string((unsigned int *) &krb5data.length);
|
|
|
|
- if (!auth_kerberos_tgt(user, &krb5data, client) ||
|
|
+ if (!auth_krb5_tgt(user, &krb5data, client) ||
|
|
!krb5_kuserok(ssh_context, client, user)){
|
|
log_msg("Kerberos tgt REFUSED for %.100s", user);
|
|
debug("Kerberos tgt REFUSED for %.100s", user);
|
|
}
|
|
free(krb5data.data);
|
|
-#endif
|
|
+#else /* KRB5 */
|
|
+ {
|
|
+ /* Accept Kerberos tgt. */
|
|
+ char *tgt = packet_get_string(NULL);
|
|
+ if (!auth_kerberos_tgt(pw, tgt))
|
|
+ debug("Kerberos tgt REFUSED for %s", user);
|
|
+ xfree(tgt);
|
|
+ }
|
|
+#endif /* KRB5 */
|
|
continue;
|
|
-#endif /* KERBEROS_TGT_PASSING */
|
|
+#endif /* KRB5 || AFS */
|
|
|
|
-#ifdef KERBEROS
|
|
-#ifdef KRB5
|
|
+#ifdef AFS
|
|
+ case SSH_CMSG_HAVE_AFS_TOKEN:
|
|
+ if (!k_hasafs() || !options.afs_token_passing) {
|
|
+ packet_get_all();
|
|
+ log_msg("AFS token passing disabled.");
|
|
+ break;
|
|
+ }
|
|
+ else {
|
|
+ /* Accept AFS token. */
|
|
+ char *token_string = packet_get_string(NULL);
|
|
+ if (!auth_afs_token(user, pw->pw_uid, token_string))
|
|
+ debug("AFS token REFUSED for %s", user);
|
|
+ xfree(token_string);
|
|
+ continue;
|
|
+ }
|
|
+#endif /* AFS */
|
|
+
|
|
+#if defined(KRB4) || defined(KRB5)
|
|
case SSH_CMSG_AUTH_KERBEROS:
|
|
if (!options.kerberos_authentication)
|
|
{
|
|
@@ -2316,9 +2453,10 @@
|
|
log_msg("Kerberos authentication disabled.");
|
|
break;
|
|
}
|
|
+#ifdef KRB5
|
|
/* Try Kerberos authentication. */
|
|
krb5data.data = packet_get_string((unsigned int *) &krb5data.length);
|
|
- if (auth_kerberos(user, &krb5data, &tkt_client))
|
|
+ if (auth_krb5(user, &krb5data, &tkt_client))
|
|
{
|
|
char *tkt_user;
|
|
|
|
@@ -2334,6 +2472,11 @@
|
|
/* Client has successfully authenticated to us. */
|
|
log_msg("Kerberos authentication accepted %.100s for login to account %.100s from %.200s",
|
|
tkt_user, user, get_canonical_hostname());
|
|
+#ifdef ENABLE_LOG_AUTH
|
|
+ log_auth("%.100s from %.700s (%s)",
|
|
+ user, get_canonical_hostname(),
|
|
+ "kerberos authentication accepted");
|
|
+#endif /* ENABLE_LOG_AUTH */
|
|
authentication_type = SSH_AUTH_KERBEROS;
|
|
authenticated = 1;
|
|
break;
|
|
@@ -2347,11 +2490,31 @@
|
|
}
|
|
free(tkt_user);
|
|
}
|
|
-#endif /* KRB5 */
|
|
- debug("Kerberos authentication failed for %.100s from %.200s",
|
|
- user, get_canonical_hostname());
|
|
+#else /* !KRB5 XXX - how to make these coexist? */
|
|
+ else {
|
|
+ /* Try Kerberos v4 authentication. */
|
|
+ KTEXT_ST auth;
|
|
+ char *tkt_user = NULL;
|
|
+ char *kdata = packet_get_string((unsigned int *)&auth.length);
|
|
+
|
|
+ memcpy(auth.dat, kdata, auth.length);
|
|
+ xfree(kdata);
|
|
+
|
|
+ if (auth_krb4(user, &auth, &tkt_user)) {
|
|
+ /* Client has successfully authenticated to us. */
|
|
+ log_msg("Kerberos authentication accepted %s for account "
|
|
+ "%.100s from %.200s", tkt_user, user,
|
|
+ get_canonical_hostname());
|
|
+ authentication_type = SSH_AUTH_KERBEROS;
|
|
+ authenticated = 1;
|
|
+ xfree(tkt_user);
|
|
break;
|
|
-#endif /* KERBEROS */
|
|
+ }
|
|
+ log_msg("Kerberos authentication failed for account "
|
|
+ "%.100s from %.200s", user, get_canonical_hostname());
|
|
+ }
|
|
+#endif /* KRB5 */
|
|
+#endif /* KRB5 || KRB4 */
|
|
|
|
case SSH_CMSG_AUTH_RHOSTS:
|
|
if (!options.rhosts_authentication)
|
|
@@ -2382,6 +2545,11 @@
|
|
/* Authentication accepted. */
|
|
log_msg("Rhosts authentication accepted for %.100s, remote %.100s on %.700s.",
|
|
user, client_user, get_canonical_hostname());
|
|
+#ifdef ENABLE_LOG_AUTH
|
|
+ log_auth("%.100s from %.100s@%.700s (%s)",
|
|
+ user, client_user, get_canonical_hostname(),
|
|
+ "rhosts authentication accepted");
|
|
+#endif /* ENABLE_LOG_AUTH */
|
|
authentication_type = SSH_AUTH_RHOSTS;
|
|
authenticated = 1;
|
|
remote_user_name = client_user;
|
|
@@ -2441,6 +2609,11 @@
|
|
options.strict_modes))
|
|
{
|
|
/* Authentication accepted. */
|
|
+#ifdef ENABLE_LOG_AUTH
|
|
+ log_auth("%.100s from %.100s@%.700s (%s)",
|
|
+ user, client_user, get_canonical_hostname(),
|
|
+ "rhosts with RSA host authentication accepted");
|
|
+#endif /* ENABLE_LOG_AUTH */
|
|
authentication_type = SSH_AUTH_RHOSTS_RSA;
|
|
authenticated = 1;
|
|
remote_user_name = client_user;
|
|
@@ -2474,6 +2647,11 @@
|
|
/* Successful authentication. */
|
|
mpz_clear(&n);
|
|
log_msg("RSA authentication for %.100s accepted.", user);
|
|
+#ifdef ENABLE_LOG_AUTH
|
|
+ log_auth("%.100s from %.700s (%s)",
|
|
+ user, get_canonical_hostname(),
|
|
+ "RSA user authentication accepted");
|
|
+#endif /* ENABLE_LOG_AUTH */
|
|
authentication_type = SSH_AUTH_RSA;
|
|
authenticated = 1;
|
|
break;
|
|
@@ -2568,7 +2746,7 @@
|
|
if (!strncmp(buf, "challenge ", 10) ||
|
|
!strncmp(buf, "chalnecho ", 10)) {
|
|
snprintf(prompt, sizeof(prompt),
|
|
- "Challenge \"%.100s\": ",&buf[10]);
|
|
+ "%.100s",&buf[10]);
|
|
debug("TIS challenge %.500s", buf);
|
|
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
|
|
packet_put_string(prompt, strlen(prompt));
|
|
@@ -2608,6 +2786,11 @@
|
|
auth_close();
|
|
memset(password, 0, strlen(password));
|
|
xfree(password);
|
|
+#ifdef ENABLE_LOG_AUTH
|
|
+ log_auth("%.100s from @%.700s (%s)",
|
|
+ user, get_canonical_hostname(),
|
|
+ "TIS authentication accepted");
|
|
+#endif /* ENABLE_LOG_AUTH */
|
|
authentication_type = SSH_AUTH_TIS;
|
|
authenticated = 1;
|
|
break;
|
|
@@ -2657,17 +2840,22 @@
|
|
password_attempts++;
|
|
|
|
/* Try authentication with the password. */
|
|
-#if defined(KERBEROS) && defined(KRB5)
|
|
+#ifdef KRB5
|
|
if (auth_password(user, password, client))
|
|
-#else /* defined(KERBEROS) && defined(KRB5) */
|
|
+#else /* KRB5 */
|
|
if (auth_password(user, password))
|
|
-#endif /* defined(KERBEROS) && defined(KRB5) */
|
|
+#endif /* KRB5 */
|
|
{
|
|
/* Successful authentication. */
|
|
/* Clear the password from memory. */
|
|
memset(password, 0, strlen(password));
|
|
xfree(password);
|
|
log_msg("Password authentication for %.100s accepted.", user);
|
|
+#ifdef ENABLE_LOG_AUTH
|
|
+ log_auth("%.100s from %.700s (%s)",
|
|
+ user, get_canonical_hostname(),
|
|
+ "password authentication accepted");
|
|
+#endif /* ENABLE_LOG_AUTH */
|
|
authentication_type = SSH_AUTH_PASSWORD;
|
|
authenticated = 1;
|
|
break;
|
|
@@ -2688,7 +2876,7 @@
|
|
if (authenticated)
|
|
break;
|
|
|
|
-#ifdef KERBEROS
|
|
+#if defined(KRB5)
|
|
/* If you forwarded a ticket you get one shot for proper
|
|
authentication. */
|
|
/* If tgt was passed unlink file */
|
|
@@ -2699,7 +2887,7 @@
|
|
else
|
|
ticket = NULL;
|
|
}
|
|
-#endif /* KERBEROS */
|
|
+#endif /* KRB5 */
|
|
|
|
/* Send a message indicating that the authentication attempt failed. */
|
|
packet_start(SSH_SMSG_FAILURE);
|
|
@@ -2708,6 +2896,11 @@
|
|
}
|
|
|
|
/* Check if the user is logging in as root and root logins are disallowed. */
|
|
+#ifdef ENABLE_LOG_AUTH
|
|
+ if ((pw->pw_uid == UID_ROOT && options.permit_root_login == 1) ||
|
|
+ (pw->pw_uid == UID_ROOT && options.permit_root_login == 0 && !forced_command))
|
|
+ log_auth("ROOT LOGIN REFUSED FROM %.200s", get_canonical_hostname());
|
|
+#endif /* ENABLE_LOG_AUTH */
|
|
if (pw->pw_uid == UID_ROOT && options.permit_root_login == 1)
|
|
{
|
|
if (authentication_type == SSH_AUTH_PASSWORD)
|
|
@@ -2724,7 +2917,7 @@
|
|
get_canonical_hostname());
|
|
}
|
|
|
|
-#if defined (__FreeBSD__) && defined (HAVE_LOGIN_CAP_H)
|
|
+#if (defined (__FreeBSD__) || defined(__NetBSD__)) && defined (HAVE_LOGIN_CAP_H)
|
|
|
|
lc = login_getclass(pw->pw_class);
|
|
|
|
@@ -2775,6 +2968,9 @@
|
|
packet_start(SSH_SMSG_SUCCESS);
|
|
packet_send();
|
|
packet_write_wait();
|
|
+#ifdef ENABLE_LOG_AUTH
|
|
+ unauthenticated_user = NULL;
|
|
+#endif /* ENABLE_LOG_AUTH */
|
|
|
|
/* Perform session preparation. */
|
|
do_authenticated(pw);
|
|
@@ -2965,6 +3161,21 @@
|
|
display = x11_create_display_inet(screen);
|
|
if (!display)
|
|
goto fail;
|
|
+#ifdef AFS
|
|
+ /* Setup to have a local .Xauthority, if homedir is in AFS. */
|
|
+ {
|
|
+ struct stat st;
|
|
+ char cell[64], *xauthdir = "/ticket";
|
|
+
|
|
+ if (k_hasafs() && k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0) {
|
|
+ xauthfile = xmalloc(MAXPATHLEN);
|
|
+ if (stat(xauthdir, &st) < 0)
|
|
+ xauthdir = "/tmp";
|
|
+ snprintf(xauthfile, MAXPATHLEN, "%s/Xauth%d_%d", xauthdir,
|
|
+ pw->pw_uid, getpid());
|
|
+ }
|
|
+ }
|
|
+#endif /* AFS */
|
|
break;
|
|
#else /* XAUTH_PATH */
|
|
/* No xauth program; we won't accept forwarding with spoofing. */
|
|
@@ -3280,15 +3491,12 @@
|
|
char line[256];
|
|
struct stat st;
|
|
int quiet_login;
|
|
- struct sockaddr_in from;
|
|
+ struct sockaddr_storage from;
|
|
int fromlen;
|
|
struct pty_cleanup_context cleanup_context;
|
|
-#if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)
|
|
+#if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(HAVE_LOGIN_CAP_H)
|
|
login_cap_t *lc;
|
|
#endif
|
|
-#if defined (__bsdi__) && _BSDI_VERSION >= 199510
|
|
- struct timeval tp;
|
|
-#endif /* __bsdi__ && _BSDI_VERSION >= 199510 */
|
|
|
|
/* We no longer need the child running on user's privileges. */
|
|
userfile_uninit();
|
|
@@ -3387,9 +3595,9 @@
|
|
|
|
/* Record that there was a login on that terminal. */
|
|
record_login(pid, ttyname, pw->pw_name, pw->pw_uid, hostname,
|
|
- &from);
|
|
+ (struct sockaddr *)&from);
|
|
|
|
-#if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)
|
|
+#if (defined (__FreeBSD__) || defined(__NetBSD__)) && defined(HAVE_LOGIN_CAP_H)
|
|
lc = login_getclass(pw->pw_class);
|
|
#endif
|
|
|
|
@@ -3398,7 +3606,7 @@
|
|
snprintf(line, sizeof(line), "%.200s/.hushlogin", pw->pw_dir);
|
|
quiet_login = stat(line, &st) >= 0;
|
|
|
|
-#if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)
|
|
+#if (defined (__FreeBSD__) || defined(__NetBSD__)) && defined(HAVE_LOGIN_CAP_H)
|
|
quiet_login = login_getcapbool(lc, "hushlogin", quiet_login);
|
|
#endif
|
|
|
|
@@ -3425,7 +3633,7 @@
|
|
}
|
|
#endif /* HAVE_SIA */
|
|
|
|
-#ifdef __FreeBSD__
|
|
+#if defined(__FreeBSD__) || defined(__NetBSD__)
|
|
if (command == NULL && !quiet_login)
|
|
{
|
|
#ifdef HAVE_LOGIN_CAP_H
|
|
@@ -3457,7 +3665,7 @@
|
|
FILE *f;
|
|
|
|
/* Print /etc/motd if it exists. */
|
|
-#if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)
|
|
+#if (defined (__FreeBSD__) || defined(__NetBSD__)) && defined(HAVE_LOGIN_CAP_H)
|
|
f = fopen(login_getcapstr(lc, "welcome", "/etc/motd", "/etc/motd"),
|
|
"r");
|
|
#else
|
|
@@ -3469,33 +3677,9 @@
|
|
fputs(line, stdout);
|
|
fclose(f);
|
|
}
|
|
-#if defined (__bsdi__) && _BSDI_VERSION >= 199510
|
|
- if (pw->pw_change || pw->pw_expire)
|
|
- (void)gettimeofday(&tp, (struct timezone *)NULL);
|
|
- if (pw->pw_change)
|
|
- {
|
|
- if (tp.tv_sec >= pw->pw_change)
|
|
- {
|
|
- fprintf(stderr,"Sorry -- your password has expired.\n");
|
|
- exit(254);
|
|
- }
|
|
- days_before_password_expires = (pw->pw_change - tp.tv_sec) /
|
|
- 86400;
|
|
- }
|
|
- if (pw->pw_expire)
|
|
- {
|
|
- if (tp.tv_sec >= pw->pw_expire)
|
|
- {
|
|
- fprintf(stderr,"Sorry -- your account has expired.\n");
|
|
- exit(254);
|
|
- }
|
|
- days_before_account_expires = (pw->pw_expire - tp.tv_sec) /
|
|
- 86400;
|
|
- }
|
|
-#endif /* __bsdi__ & _BSDI_VERSION >= 199510 */
|
|
}
|
|
|
|
-#if defined (__FreeBSD__) && defined HAVE_LOGIN_CAP_H
|
|
+#if (defined (__FreeBSD__) || defined(__NetBSD__)) && defined HAVE_LOGIN_CAP_H
|
|
login_close(lc);
|
|
#endif
|
|
|
|
@@ -3876,6 +4060,7 @@
|
|
char *user_shell;
|
|
char *remote_ip;
|
|
int remote_port;
|
|
+ int local_port;
|
|
#if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)
|
|
login_cap_t *lc;
|
|
char *real_shell;
|
|
@@ -3883,8 +4068,11 @@
|
|
lc = login_getclass(pw->pw_class);
|
|
auth_checknologin(lc);
|
|
#else /* !HAVE_LOGIN_CAP_H */
|
|
-#if defined (__bsdi__) && _BSDI_VERSION > 199510
|
|
+#if ( defined (__bsdi__) && _BSDI_VERSION > 199510 ) || (defined(HAVE_LOGIN_CAP_H) && defined(__NetBSD__))
|
|
login_cap_t *lc = 0;
|
|
+#if defined(__NetBSD__)
|
|
+ char *real_shell;
|
|
+#endif
|
|
|
|
if ((lc = login_getclass(pw->pw_class)) == NULL)
|
|
{
|
|
@@ -3981,6 +4169,7 @@
|
|
user_shell = xstrdup(pw->pw_shell);
|
|
remote_ip = xstrdup(get_remote_ipaddr());
|
|
remote_port = get_remote_port();
|
|
+ local_port = get_local_port();
|
|
|
|
/* Close the connection descriptors; note that this is the child, and the
|
|
server will still have the socket open, and it is important that we
|
|
@@ -4000,7 +4189,6 @@
|
|
/* Close any extra file descriptors. Note that there may still be
|
|
descriptors left by system functions. They will be closed later. */
|
|
endpwent();
|
|
- endhostent();
|
|
|
|
/* Set dummy encryption key to clear information about the key from
|
|
memory. This key will never be used. */
|
|
@@ -4019,7 +4207,7 @@
|
|
if (command != NULL || !options.use_login)
|
|
#endif /* USELOGIN */
|
|
{
|
|
-#if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)
|
|
+#if (defined (__FreeBSD__) || defined(__NetBSD__)) && defined(HAVE_LOGIN_CAP_H)
|
|
char *p, *s, **tmpenv;
|
|
|
|
/* Initialize the new environment.
|
|
@@ -4180,10 +4368,23 @@
|
|
and means /bin/sh. */
|
|
shell = (user_shell[0] == '\0') ? DEFAULT_SHELL : user_shell;
|
|
|
|
-#if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)
|
|
+#if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(HAVE_LOGIN_CAP_H)
|
|
real_shell = login_getcapstr(lc, "shell", (char*)shell, (char*)shell);
|
|
login_close(lc);
|
|
#endif /* HAVE_LOGIN_CAP_H */
|
|
+
|
|
+#ifdef AFS
|
|
+ /* Try to get AFS tokens for the local cell. */
|
|
+ if (k_hasafs()) {
|
|
+ char cell[64];
|
|
+
|
|
+ if (k_afs_cell_of_file(user_dir, cell, sizeof(cell)) == 0)
|
|
+ krb_afslog(cell, 0);
|
|
+
|
|
+ krb_afslog(0, 0);
|
|
+ }
|
|
+#endif /* AFS */
|
|
+
|
|
/* Initialize the environment if not already done. In the first part we
|
|
allocate space for all environment variables. */
|
|
if (env == NULL)
|
|
@@ -4257,7 +4458,7 @@
|
|
|
|
/* Set SSH_CLIENT. */
|
|
snprintf(buf, sizeof(buf),
|
|
- "%.50s %d %d", remote_ip, remote_port, options.port);
|
|
+ "%.50s %d %d", remote_ip, remote_port, local_port);
|
|
child_set_env(&env, &envsize, "SSH_CLIENT", buf);
|
|
|
|
/* Set SSH_TTY if we have a pty. */
|
|
@@ -4290,13 +4491,21 @@
|
|
}
|
|
#endif
|
|
|
|
-#ifdef KERBEROS
|
|
- /* Set KRBTKFILE to point to our ticket */
|
|
+ /* Set KRBTKFILE to point to our ticket. */
|
|
#ifdef KRB5
|
|
if (ticket)
|
|
child_set_env(&env, &envsize, "KRB5CCNAME", ticket);
|
|
#endif /* KRB5 */
|
|
-#endif /* KERBEROS */
|
|
+#ifdef KRB4 /* XXX - how to make these coexist? */
|
|
+ if (ticket)
|
|
+ child_set_env(&env, &envsize, "KRBTKFILE", ticket);
|
|
+
|
|
+#ifdef AFS
|
|
+ /* Set XAUTHORITY to a local file, if homedir is in AFS. */
|
|
+ if (xauthfile)
|
|
+ child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
|
|
+#endif /* AFS */
|
|
+#endif /* KRB4 */
|
|
|
|
/* Set variable for forwarded authentication connection, if we have one. */
|
|
if (auth_get_socket_name() != NULL)
|
|
@@ -4426,7 +4635,8 @@
|
|
int i;
|
|
char name[255], *p;
|
|
char line[256];
|
|
- struct hostent *hp;
|
|
+ struct addrinfo hints, *ai, *aitop;
|
|
+ char ntop[ADDRSTRLEN];
|
|
|
|
strncpy(name, display, sizeof(name));
|
|
name[sizeof(name) - 1] = '\0';
|
|
@@ -4443,7 +4653,10 @@
|
|
/* Moved this call here to avoid a nasty buf in SunOS
|
|
4.1.4 libc where gethostbyname closes an unrelated
|
|
file descriptor. */
|
|
- hp = gethostbyname(name);
|
|
+ memset(&hints, 0, sizeof(hints));
|
|
+ hints.ai_family = IPv4or6;
|
|
+ if (getaddrinfo(name, NULL, &hints, &aitop) != 0)
|
|
+ aitop = 0;
|
|
|
|
snprintf(line, sizeof(line),
|
|
"%.200s -q -", options.xauth_path);
|
|
@@ -4461,21 +4674,24 @@
|
|
cp - display, display, cp, auth_proto,
|
|
auth_data);
|
|
#endif
|
|
- if (hp)
|
|
+ if (aitop)
|
|
{
|
|
- for(i = 0; hp->h_addr_list[i]; i++)
|
|
+ for (ai = aitop; ai; ai = ai->ai_next)
|
|
{
|
|
+ getnameinfo(ai->ai_addr, ai->ai_addrlen,
|
|
+ ntop, sizeof(ntop), NULL, 0,
|
|
+ NI_NUMERICHOST);
|
|
+ if (strchr(ntop, ':'))
|
|
+ continue; /* XXX - xauth doesn't accept it */
|
|
if (debug_flag)
|
|
{
|
|
fprintf(stderr, "Running %s add %s%s %s %s\n",
|
|
options.xauth_path,
|
|
- inet_ntoa(*((struct in_addr *)
|
|
- hp->h_addr_list[i])),
|
|
+ ntop,
|
|
cp, auth_proto, auth_data);
|
|
}
|
|
fprintf(f, "add %s%s %s %s\n",
|
|
- inet_ntoa(*((struct in_addr *)
|
|
- hp->h_addr_list[i])),
|
|
+ ntop,
|
|
cp, auth_proto, auth_data);
|
|
}
|
|
}
|
|
@@ -4554,7 +4770,7 @@
|
|
/* Execute the shell. */
|
|
argv[0] = buf;
|
|
argv[1] = NULL;
|
|
-#if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)
|
|
+#if (defined (__FreeBSD__) || defined(__NetBSD__)) && defined(HAVE_LOGIN_CAP_H)
|
|
execve(real_shell, argv, env);
|
|
#else
|
|
execve(shell, argv, env);
|
|
@@ -4579,7 +4795,7 @@
|
|
argv[1] = "-c";
|
|
argv[2] = (char *)command;
|
|
argv[3] = NULL;
|
|
-#if defined (__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)
|
|
+#if (defined (__FreeBSD__) || defined(__NetBSD__)) && defined(HAVE_LOGIN_CAP_H)
|
|
execve(real_shell, argv, env);
|
|
#else
|
|
execve(shell, argv, env);
|