summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>1999-11-15 15:25:10 +1100
committerDamien Miller <djm@mindrot.org>1999-11-15 15:25:10 +1100
commit2ccf661cbe0924a1549a74b5a4f970e90f94d6a9 (patch)
tree8bb7ea3cbe9d473e7f46b7084f563cc593cc5d47
parentcedfecc99e73f9661d4dc3cea8c88e57c6e0b487 (diff)
- Merged more OpenBSD CVS changes:
[auth-krb4.c] - disconnect if getpeername() fails - missing xfree(*client) [canohost.c] - disconnect if getpeername() fails - fix comment: we _do_ disconnect if ip-options are set [sshd.c] - disconnect if getpeername() fails - move checking of remote port to central place [auth-rhosts.c] move checking of remote port to central place [log-server.c] avoid extra fd per sshd, from millert@ [readconf.c] print _all_ bad config-options in ssh(1), too [readconf.h] print _all_ bad config-options in ssh(1), too [ssh.c] print _all_ bad config-options in ssh(1), too [sshconnect.c] disconnect if getpeername() fails - OpenBSD's changes to sshd.c broke the PAM stuff, re-merged it.
-rw-r--r--ChangeLog17
-rw-r--r--auth-krb4.c7
-rw-r--r--auth-rhosts.c18
-rw-r--r--canohost.c17
-rw-r--r--log-server.c9
-rw-r--r--readconf.c34
-rw-r--r--readconf.h7
-rw-r--r--ssh.c7
-rw-r--r--sshconnect.c6
-rw-r--r--sshd.c671
10 files changed, 376 insertions, 417 deletions
diff --git a/ChangeLog b/ChangeLog
index 52899434..d1c75cce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,23 @@
- Changed to ssh-add.c broke askpass support. Revised it to be a little more
modular.
- Revised autoconf support for enabling/disabling askpass support.
+ - Merged more OpenBSD CVS changes:
+ [auth-krb4.c]
+ - disconnect if getpeername() fails
+ - missing xfree(*client)
+ [canohost.c]
+ - disconnect if getpeername() fails
+ - fix comment: we _do_ disconnect if ip-options are set
+ [sshd.c]
+ - disconnect if getpeername() fails
+ - move checking of remote port to central place
+ [auth-rhosts.c] move checking of remote port to central place
+ [log-server.c] avoid extra fd per sshd, from millert@
+ [readconf.c] print _all_ bad config-options in ssh(1), too
+ [readconf.h] print _all_ bad config-options in ssh(1), too
+ [ssh.c] print _all_ bad config-options in ssh(1), too
+ [sshconnect.c] disconnect if getpeername() fails
+ - OpenBSD's changes to sshd.c broke the PAM stuff, re-merged it.
19991114
- Solaris compilation fixes (still imcomplete)
diff --git a/auth-krb4.c b/auth-krb4.c
index 03205233..72acd47d 100644
--- a/auth-krb4.c
+++ b/auth-krb4.c
@@ -6,7 +6,7 @@
Kerberos v4 authentication and ticket-passing routines.
- $Id: auth-krb4.c,v 1.3 1999/11/11 06:57:39 damien Exp $
+ $Id: auth-krb4.c,v 1.4 1999/11/15 04:25:10 damien Exp $
*/
#include "includes.h"
@@ -89,8 +89,10 @@ int auth_krb4(const char *server_user, KTEXT auth, char **client)
debug("getsockname failed: %.100s", strerror(errno));
r = sizeof(foreign);
memset(&foreign, 0, sizeof(foreign));
- if (getpeername(s, (struct sockaddr *)&foreign, &r) < 0)
+ if (getpeername(s, (struct sockaddr *)&foreign, &r) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
+ fatal_cleanup();
+ }
instance[0] = '*'; instance[1] = 0;
@@ -110,6 +112,7 @@ int auth_krb4(const char *server_user, KTEXT auth, char **client)
packet_send_debug("Kerberos V4 .klogin authorization failed!");
log("Kerberos V4 .klogin authorization failed for %s to account %s",
*client, server_user);
+ xfree(*client);
return 0;
}
/* Increment the checksum, and return it encrypted with the session key. */
diff --git a/auth-rhosts.c b/auth-rhosts.c
index 7e5614cb..8f6655d4 100644
--- a/auth-rhosts.c
+++ b/auth-rhosts.c
@@ -16,7 +16,7 @@ the login based on rhosts authentication. This file also processes
*/
#include "includes.h"
-RCSID("$Id: auth-rhosts.c,v 1.2 1999/11/12 04:19:27 damien Exp $");
+RCSID("$Id: auth-rhosts.c,v 1.3 1999/11/15 04:25:10 damien Exp $");
#include "packet.h"
#include "ssh.h"
@@ -161,7 +161,6 @@ int auth_rhosts(struct passwd *pw, const char *client_user)
extern ServerOptions options;
char buf[1024];
const char *hostname, *ipaddr;
- int port;
struct stat st;
static const char *rhosts_files[] = { ".shosts", ".rhosts", NULL };
unsigned int rhosts_file_index;
@@ -190,21 +189,6 @@ int auth_rhosts(struct passwd *pw, const char *client_user)
/* Get the name, address, and port of the remote host. */
hostname = get_canonical_hostname();
ipaddr = get_remote_ipaddr();
- port = get_remote_port();
-
- /* Check that the connection comes from a privileged port.
- Rhosts authentication only makes sense for priviledged programs.
- Of course, if the intruder has root access on his local machine,
- he can connect from any port. So do not use .rhosts
- authentication from machines that you do not trust. */
- if (port >= IPPORT_RESERVED ||
- port < IPPORT_RESERVED / 2)
- {
- log("Connection from %.100s from nonpriviledged port %d",
- hostname, port);
- packet_send_debug("Your ssh client is not running as root.");
- return 0;
- }
/* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
if (pw->pw_uid != 0)
diff --git a/canohost.c b/canohost.c
index 85d97292..08f79875 100644
--- a/canohost.c
+++ b/canohost.c
@@ -14,7 +14,7 @@ Functions for returning the canonical host name of the remote site.
*/
#include "includes.h"
-RCSID("$Id: canohost.c,v 1.1 1999/10/27 03:42:43 damien Exp $");
+RCSID("$Id: canohost.c,v 1.2 1999/11/15 04:25:10 damien Exp $");
#include "packet.h"
#include "xmalloc.h"
@@ -35,9 +35,8 @@ char *get_remote_hostname(int socket)
memset(&from, 0, sizeof(from));
if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
{
- error("getpeername failed: %.100s", strerror(errno));
- strlcpy(name, "UNKNOWN", sizeof name);
- goto check_ip_options;
+ debug("getpeername failed: %.100s", strerror(errno));
+ fatal_cleanup();
}
/* Map the IP address to a host name. */
@@ -99,7 +98,7 @@ char *get_remote_hostname(int socket)
check_ip_options:
- /* If IP options are supported, make sure there are none (log and clear
+ /* If IP options are supported, make sure there are none (log and disconnect
them if any are found). Basically we are worried about source routing;
it can be used to pretend you are somebody (ip-address) you are not.
That itself may be "almost acceptable" under certain circumstances,
@@ -184,8 +183,8 @@ const char *get_remote_ipaddr()
memset(&from, 0, sizeof(from));
if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
{
- error("getpeername failed: %.100s", strerror(errno));
- return NULL;
+ debug("getpeername failed: %.100s", strerror(errno));
+ fatal_cleanup();
}
/* Get the IP address in ascii. */
@@ -207,8 +206,8 @@ int get_peer_port(int sock)
memset(&from, 0, sizeof(from));
if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0)
{
- error("getpeername failed: %.100s", strerror(errno));
- return 0;
+ debug("getpeername failed: %.100s", strerror(errno));
+ fatal_cleanup();
}
/* Return port number. */
diff --git a/log-server.c b/log-server.c
index 6642dbed..805df6b6 100644
--- a/log-server.c
+++ b/log-server.c
@@ -15,7 +15,7 @@ to the system log.
*/
#include "includes.h"
-RCSID("$Id: log-server.c,v 1.2 1999/11/11 06:57:39 damien Exp $");
+RCSID("$Id: log-server.c,v 1.3 1999/11/15 04:25:10 damien Exp $");
#include <syslog.h>
#include "packet.h"
@@ -24,6 +24,7 @@ RCSID("$Id: log-server.c,v 1.2 1999/11/11 06:57:39 damien Exp $");
static LogLevel log_level = SYSLOG_LEVEL_INFO;
static int log_on_stderr = 0;
+static int log_facility = LOG_AUTH;
/* Initialize the log.
av0 program name (should be argv[0])
@@ -33,7 +34,6 @@ static int log_on_stderr = 0;
void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
{
- int log_facility;
switch (level)
{
@@ -93,8 +93,6 @@ void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
}
log_on_stderr = on_stderr;
- closelog(); /* Close any previous log. */
- openlog(av0, LOG_PID, log_facility);
}
#define MSGBUFSIZE 1024
@@ -106,6 +104,7 @@ do_log(LogLevel level, const char *fmt, va_list args)
char fmtbuf[MSGBUFSIZE];
char *txt = NULL;
int pri = LOG_INFO;
+ extern char *__progname;
if (level > log_level)
return;
@@ -143,5 +142,7 @@ do_log(LogLevel level, const char *fmt, va_list args)
}
if (log_on_stderr)
fprintf(stderr, "%s\n", msgbuf);
+ openlog(__progname, LOG_PID, log_facility);
syslog(pri, "%.500s", msgbuf);
+ closelog();
}
diff --git a/readconf.c b/readconf.c
index 2a99266a..b341322c 100644
--- a/readconf.c
+++ b/readconf.c
@@ -14,7 +14,7 @@ Functions for reading the configuration files.
*/
#include "includes.h"
-RCSID("$Id: readconf.c,v 1.2 1999/11/11 06:57:39 damien Exp $");
+RCSID("$Id: readconf.c,v 1.3 1999/11/15 04:25:10 damien Exp $");
#include "ssh.h"
#include "cipher.h"
@@ -88,6 +88,7 @@ RCSID("$Id: readconf.c,v 1.2 1999/11/11 06:57:39 damien Exp $");
typedef enum
{
+ oBadOption,
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
#ifdef KRB4
@@ -222,16 +223,16 @@ static OpCodes parse_token(const char *cp, const char *filename, int linenum)
if (strcmp(cp, keywords[i].name) == 0)
return keywords[i].opcode;
- fatal("%.200s line %d: Bad configuration option.",
- filename, linenum);
- /*NOTREACHED*/
- return 0;
+ fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
+ filename, linenum, cp);
+ return oBadOption;
}
/* Processes a single option line as used in the configuration files.
This only sets those values that have not already been set. */
-void process_config_line(Options *options, const char *host,
+int
+process_config_line(Options *options, const char *host,
char *line, const char *filename, int linenum,
int *activep)
{
@@ -241,7 +242,7 @@ void process_config_line(Options *options, const char *host,
/* Skip leading whitespace. */
cp = line + strspn(line, WHITESPACE);
if (!*cp || *cp == '\n' || *cp == '#')
- return;
+ return 0;
/* Get the keyword. (Each line is supposed to begin with a keyword). */
cp = strtok(cp, WHITESPACE);
@@ -256,7 +257,9 @@ void process_config_line(Options *options, const char *host,
switch (opcode)
{
-
+ case oBadOption:
+ return -1; /* don't panic, but count bad options */
+ /*NOTREACHED*/
case oForwardAgent:
intptr = &options->forward_agent;
parse_flag:
@@ -426,7 +429,7 @@ void process_config_line(Options *options, const char *host,
*charptr = string;
else
xfree(string);
- return;
+ return 0;
case oPort:
intptr = &options->port;
@@ -533,7 +536,7 @@ void process_config_line(Options *options, const char *host,
break;
}
/* Avoid garbage check below, as strtok already returned NULL. */
- return;
+ return 0;
case oEscapeChar:
intptr = &options->escape_char;
@@ -561,13 +564,14 @@ void process_config_line(Options *options, const char *host,
break;
default:
- fatal("parse_config_file: Unimplemented opcode %d", opcode);
+ fatal("process_config_line: Unimplemented opcode %d", opcode);
}
/* Check that there is no garbage at end of line. */
if (strtok(NULL, WHITESPACE) != NULL)
fatal("%.200s line %d: garbage at end of line.",
filename, linenum);
+ return 0;
}
@@ -580,6 +584,7 @@ void read_config_file(const char *filename, const char *host, Options *options)
FILE *f;
char line[1024];
int active, linenum;
+ int bad_options = 0;
/* Open the file. */
f = fopen(filename, "r");
@@ -596,10 +601,13 @@ void read_config_file(const char *filename, const char *host, Options *options)
{
/* Update line number counter. */
linenum++;
-
- process_config_line(options, host, line, filename, linenum, &active);
+ if (process_config_line(options, host, line, filename, linenum, &active) != 0)
+ bad_options++;
}
fclose(f);
+ if (bad_options > 0)
+ fatal("%s: terminating, %d bad configuration options\n",
+ filename, bad_options);
}
/* Initializes options to special values that indicate that they have not
diff --git a/readconf.h b/readconf.h
index 8839a1bd..d2d387df 100644
--- a/readconf.h
+++ b/readconf.h
@@ -13,7 +13,7 @@ Functions for reading the configuration file.
*/
-/* RCSID("$Id: readconf.h,v 1.2 1999/11/11 06:57:39 damien Exp $"); */
+/* RCSID("$Id: readconf.h,v 1.3 1999/11/15 04:25:10 damien Exp $"); */
#ifndef READCONF_H
#define READCONF_H
@@ -92,8 +92,9 @@ void initialize_options(Options *options);
void fill_default_options(Options *options);
/* Processes a single option line as used in the configuration files.
- This only sets those values that have not already been set. */
-void process_config_line(Options *options, const char *host,
+ This only sets those values that have not already been set.
+ Returns 0 for legal options */
+int process_config_line(Options *options, const char *host,
char *line, const char *filename, int linenum,
int *activep);
diff --git a/ssh.c b/ssh.c
index a8a806b8..2f3b5fc1 100644
--- a/ssh.c
+++ b/ssh.c
@@ -18,7 +18,7 @@ Modified to work with SSL by Niels Provos <provos@citi.umich.edu> in Canada.
*/
#include "includes.h"
-RCSID("$Id: ssh.c,v 1.7 1999/11/13 02:28:45 damien Exp $");
+RCSID("$Id: ssh.c,v 1.8 1999/11/15 04:25:10 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
@@ -383,8 +383,9 @@ main(int ac, char **av)
case 'o':
dummy = 1;
- process_config_line(&options, host ? host : "", optarg,
- "command-line", 0, &dummy);
+ if (process_config_line(&options, host ? host : "", optarg,
+ "command-line", 0, &dummy) != 0)
+ exit(1);
break;
default:
diff --git a/sshconnect.c b/sshconnect.c
index 03318459..f984bcaa 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -15,7 +15,7 @@ login (authentication) dialog.
*/
#include "includes.h"
-RCSID("$Id: sshconnect.c,v 1.7 1999/11/12 23:51:58 damien Exp $");
+RCSID("$Id: sshconnect.c,v 1.8 1999/11/15 04:25:10 damien Exp $");
#ifdef HAVE_OPENSSL
#include <openssl/bn.h>
@@ -730,8 +730,10 @@ int try_kerberos_authentication()
r = sizeof(foreign);
memset(&foreign, 0, sizeof(foreign));
if (getpeername(packet_get_connection_in(),
- (struct sockaddr *)&foreign, &r) < 0)
+ (struct sockaddr *)&foreign, &r) < 0) {
debug("getpeername failed: %s", strerror(errno));
+ fatal_cleanup();
+ }
/* Get server reply. */
type = packet_read(&plen);
diff --git a/sshd.c b/sshd.c
index b975c8dc..a0cc4663 100644
--- a/sshd.c
+++ b/sshd.c
@@ -18,7 +18,7 @@ agent connections.
*/
#include "includes.h"
-RCSID("$Id: sshd.c,v 1.17 1999/11/12 04:19:27 damien Exp $");
+RCSID("$Id: sshd.c,v 1.18 1999/11/15 04:25:10 damien Exp $");
#include "xmalloc.h"
#include "rsa.h"
@@ -114,9 +114,10 @@ int received_sighup = 0;
RSA *public_key;
/* Prototypes for various functions defined later in this file. */
-void do_connection(int privileged_port);
-void do_authentication(char *user, int privileged_port);
-void eat_packets_and_disconnect(const char *user);
+void do_connection();
+void do_authentication(char *user);
+void do_authloop(struct passwd *pw);
+void do_fake_authloop(char *user);
void do_authenticated(struct passwd *pw);
void do_exec_pty(const char *command, int ptyfd, int ttyfd,
const char *ttyname, struct passwd *pw, const char *term,
@@ -128,11 +129,12 @@ void do_exec_no_pty(const char *command, struct passwd *pw,
void do_child(const char *command, struct passwd *pw, const char *term,
const char *display, const char *auth_proto,
const char *auth_data, const char *ttyname);
+
#ifdef HAVE_LIBPAM
static int pamconv(int num_msg, const struct pam_message **msg,
- struct pam_response **resp, void *appdata_ptr);
-void do_pam_account_and_session(const char *username, const char *password,
- const char *remote_user, const char *remote_host);
+ struct pam_response **resp, void *appdata_ptr);
+void do_pam_account_and_session(const char *username,
+ const char *remote_user, const char *remote_host);
void pam_cleanup_proc(void *context);
static struct pam_conv conv = {
@@ -228,7 +230,7 @@ void pam_cleanup_proc(void *context)
}
}
-void do_pam_account_and_session(const char *username, const char *password, const char *remote_user, const char *remote_host)
+void do_pam_account_and_session(const char *username, const char *remote_user, const char *remote_host)
{
int pam_retval;
@@ -239,7 +241,7 @@ void do_pam_account_and_session(const char *username, const char *password, cons
if (pam_retval != PAM_SUCCESS)
{
log("PAM set rhost failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval));
- eat_packets_and_disconnect(username);
+ do_fake_authloop(username);
}
}
@@ -250,7 +252,7 @@ void do_pam_account_and_session(const char *username, const char *password, cons
if (pam_retval != PAM_SUCCESS)
{
log("PAM set ruser failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval));
- eat_packets_and_disconnect(username);
+ do_fake_authloop(username);
}
}
@@ -258,14 +260,14 @@ void do_pam_account_and_session(const char *username, const char *password, cons
if (pam_retval != PAM_SUCCESS)
{
log("PAM rejected by account configuration: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval));
- eat_packets_and_disconnect(username);
+ do_fake_authloop(username);
}
pam_retval = pam_open_session((pam_handle_t *)pamh, 0);
if (pam_retval != PAM_SUCCESS)
{
log("PAM session setup failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval));
- eat_packets_and_disconnect(username);
+ do_fake_authloop(username);
}
}
#endif /* HAVE_LIBPAM */
@@ -375,6 +377,7 @@ main(int ac, char **av)
struct sockaddr_in sin;
char buf[100]; /* Must not be larger than remote_version. */
char remote_version[100]; /* Must be at least as big as buf. */
+ int remote_port;
char *comment;
FILE *f;
struct linger linger;
@@ -742,6 +745,8 @@ main(int ac, char **av)
have a key. */
packet_set_connection(sock_in, sock_out);
+ remote_port = get_remote_port();
+
/* Check whether logins are denied from this host. */
#ifdef LIBWRAP
{
@@ -755,13 +760,11 @@ main(int ac, char **av)
close(sock_out);
refuse(&req);
}
- log("Connection from %.500s port %d",
- eval_client(&req), get_remote_port());
+ log("Connection from %.500s port %d", eval_client(&req), remote_port);
}
#else
/* Log the connection. */
- log("Connection from %.100s port %d",
- get_remote_ipaddr(), get_remote_port());
+ log("Connection from %.100s port %d", get_remote_ipaddr(), remote_port);
#endif /* LIBWRAP */
/* We don\'t want to listen forever unless the other side successfully
@@ -834,11 +837,23 @@ main(int ac, char **av)
}
}
+ /* Check that the connection comes from a privileged port.
+ Rhosts- and Rhosts-RSA-Authentication only make sense
+ from priviledged programs.
+ Of course, if the intruder has root access on his local machine,
+ he can connect from any port. So do not use these authentication
+ methods from machines that you do not trust. */
+ if (remote_port >= IPPORT_RESERVED ||
+ remote_port < IPPORT_RESERVED / 2)
+ {
+ options.rhosts_authentication = 0;
+ options.rhosts_rsa_authentication = 0;
+ }
+
packet_set_nonblocking();
- /* Handle the connection. We pass as argument whether the connection
- came from a privileged port. */
- do_connection(get_remote_port() < IPPORT_RESERVED);
+ /* Handle the connection. */
+ do_connection();
#ifdef KRB4
/* Cleanup user's ticket cache file. */
@@ -879,7 +894,8 @@ main(int ac, char **av)
been exchanged. This sends server key and performs the key exchange.
Server and host keys will no longer be needed after this functions. */
-void do_connection(int privileged_port)
+void
+do_connection()
{
int i, len;
BIGNUM *session_key_int;
@@ -1071,7 +1087,7 @@ void do_connection(int privileged_port)
setproctitle("%s", user);
/* Do the authentication. */
- do_authentication(user, privileged_port);
+ do_authentication(user);
}
/* Check if the user is allowed to log in via ssh. If user is listed in
@@ -1154,26 +1170,13 @@ allowed_user(struct passwd *pw)
/* Performs authentication of an incoming connection. Session key has already
been exchanged and encryption is enabled. User is the user name to log
- in as (received from the clinet). Privileged_port is true if the
- connection comes from a privileged port (used for .rhosts authentication).*/
-
-#define MAX_AUTH_FAILURES 5
+ in as (received from the client). */
void
-do_authentication(char *user, int privileged_port)
+do_authentication(char *user)
{
- int type;
- int authenticated = 0;
- int authentication_failures = 0;
- char *password = NULL;
struct passwd *pw, pwcopy;
- char *client_user = NULL;
- unsigned int client_host_key_bits;
- BIGNUM *client_host_key_e, *client_host_key_n;
-#ifdef HAVE_LIBPAM
- int pam_retval;
-#endif /* HAVE_LIBPAM */
-
+
#ifdef AFS
/* If machine has AFS, set process authentication group. */
if (k_hasafs()) {
@@ -1185,8 +1188,8 @@ do_authentication(char *user, int privileged_port)
/* Verify that the user is a valid user. */
pw = getpwnam(user);
if (!pw || !allowed_user(pw))
- eat_packets_and_disconnect(user);
-
+ do_fake_authloop(user);
+
/* Take a copy of the returned structure. */
memset(&pwcopy, 0, sizeof(pwcopy));
pwcopy.pw_name = xstrdup(pw->pw_name);
@@ -1199,13 +1202,11 @@ do_authentication(char *user, int privileged_port)
#ifdef HAVE_LIBPAM
debug("Starting up PAM with username \"%.200s\"", pw->pw_name);
- pam_retval = pam_start("sshd", pw->pw_name, &conv, (pam_handle_t**)&pamh);
- if (pam_retval != PAM_SUCCESS)
- {
- log("PAM initialisation failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval));
- eat_packets_and_disconnect(user);
- }
- fatal_add_cleanup(&pam_cleanup_proc, NULL);
+
+ if (pam_start("sshd", pw->pw_name, &conv, (pam_handle_t**)&pamh) != PAM_SUCCESS)
+ fatal("PAM initialisation failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval));
+
+ fatal_add_cleanup(&pam_cleanup_proc, NULL);
#endif
/* If we are not running as root, the user must have the same uid as the
@@ -1224,313 +1225,263 @@ do_authentication(char *user, int privileged_port)
{
/* Authentication with empty password succeeded. */
debug("Login for user %.100s accepted without authentication.", user);
- /* authentication_type = SSH_AUTH_PASSWORD; */
- authenticated = 1;
- /* Success packet will be sent after loop below. */
+ } else {
+ /* Loop until the user has been authenticated or the connection is closed,
+ do_authloop() returns only if authentication is successfull */
+ do_authloop(pw);
}
- else
+
+ /* XXX log unified auth message */
+
+ /* Check if the user is logging in as root and root logins are disallowed. */
+ if (pw->pw_uid == 0 && !options.permit_root_login)
{
- /* Indicate that authentication is needed. */
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
+ if (forced_command)
+ log("Root login accepted for forced command.");
+ else
+ packet_disconnect("ROOT LOGIN REFUSED FROM %.200s",
+ get_canonical_hostname());
}
- /* Loop until the user has been authenticated or the connection is closed. */
- while (!authenticated)
- {
- int plen;
- /* Get a packet from the client. */
- type = packet_read(&plen);
-
- /* Process the packet. */
- switch (type)
- {
+ /* The user has been authenticated and accepted. */
+ packet_start(SSH_SMSG_SUCCESS);
+ packet_send();
+ packet_write_wait();
-#ifdef AFS
- case SSH_CMSG_HAVE_KERBEROS_TGT:
- if (!options.kerberos_tgt_passing)
- {
- /* packet_get_all(); */
- log("Kerberos tgt passing disabled.");
- break;
- }
- else {
- /* Accept Kerberos tgt. */
- int dlen;
- char *tgt = packet_get_string(&dlen);
- packet_integrity_check(plen, 4 + dlen, type);
- if (!auth_kerberos_tgt(pw, tgt))
- debug("Kerberos tgt REFUSED for %s", user);
- xfree(tgt);
- }
- continue;
+ /* Perform session preparation. */
+ do_authenticated(pw);
+}
+
+#define MAX_AUTH_FAILURES 5
+
+/* read packets and try to authenticate local user *pw.
+ return if authentication is successfull */
+void
+do_authloop(struct passwd *pw)
+{
+ int authentication_failures = 0;
+ unsigned int client_host_key_bits;
+ BIGNUM *client_host_key_e, *client_host_key_n;
+ BIGNUM *n;
+ char *client_user, *password;
+ int plen, dlen, nlen, ulen, elen;
+
+ /* Indicate that authentication is needed. */
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+
+ for (;;) {
+ int authenticated = 0;
- case SSH_CMSG_HAVE_AFS_TOKEN:
- if (!options.afs_token_passing || !k_hasafs()) {
+ /* Get a packet from the client. */
+ int type = packet_read(&plen);
+
+ /* Process the packet. */
+ switch (type)
+ {
+#ifdef AFS
+ case SSH_CMSG_HAVE_KERBEROS_TGT:
+ if (!options.kerberos_tgt_passing)
+ {
/* packet_get_all(); */
- log("AFS token passing disabled.");
+ log("Kerberos tgt passing disabled.");
break;
}
- else {
- /* Accept AFS token. */
- int dlen;
- char *token_string = packet_get_string(&dlen);
- packet_integrity_check(plen, 4 + dlen, type);
- if (!auth_afs_token(pw, token_string))
- debug("AFS token REFUSED for %s", user);
- xfree(token_string);
- continue;
- }
+ else {
+ /* Accept Kerberos tgt. */
+ char *tgt = packet_get_string(&dlen);
+ packet_integrity_check(plen, 4 + dlen, type);
+ if (!auth_kerberos_tgt(pw, tgt))
+ debug("Kerberos tgt REFUSED for %s", pw->pw_name);
+ xfree(tgt);
+ }
+ continue;
+
+ case SSH_CMSG_HAVE_AFS_TOKEN:
+ if (!options.afs_token_passing || !k_hasafs()) {
+ /* packet_get_all(); */
+ log("AFS token passing disabled.");
+ break;
+ }
+ else {
+ /* Accept AFS token. */
+ char *token_string = packet_get_string(&dlen);
+ packet_integrity_check(plen, 4 + dlen, type);
+ if (!auth_afs_token(pw, token_string))
+ debug("AFS token REFUSED for %s", pw->pw_name);
+ xfree(token_string);
+ }
+ continue;
#endif /* AFS */
-
-#ifdef KRB4
- case SSH_CMSG_AUTH_KERBEROS:
- if (!options.kerberos_authentication)
- {
- /* packet_get_all(); */
- log("Kerberos authentication disabled.");
- break;
- }
- else {
- /* Try Kerberos v4 authentication. */
- KTEXT_ST auth;
- char *tkt_user = NULL;
- char *kdata = packet_get_string((unsigned int *)&auth.length);
- packet_integrity_check(plen, 4 + auth.length, type);
-
- if (auth.length < MAX_KTXT_LEN)
- memcpy(auth.dat, kdata, auth.length);
- xfree(kdata);
- if (auth_krb4(user, &auth, &tkt_user)) {
- /* Client has successfully authenticated to us. */
- log("Kerberos authentication accepted %s for account "
- "%s from %s", tkt_user, user, get_canonical_hostname());
- /* authentication_type = SSH_AUTH_KERBEROS; */
- authenticated = 1;
- xfree(tkt_user);
- }
- else {
- log("Kerberos authentication failed for account "
- "%s from %s", user, get_canonical_hostname());
- }
+#ifdef KRB4
+ case SSH_CMSG_AUTH_KERBEROS:
+ if (!options.kerberos_authentication)
+ {
+ /* packet_get_all(); */
+ log("Kerberos authentication disabled.");
+ break;
}
- break;
-#endif /* KRB4 */
+ else {
+ /* Try Kerberos v4 authentication. */
+ KTEXT_ST auth;
+ char *tkt_user = NULL;
+ char *kdata = packet_get_string((unsigned int *)&auth.length);
+ packet_integrity_check(plen, 4 + auth.length, type);
+
+ if (auth.length < MAX_KTXT_LEN)
+ memcpy(auth.dat, kdata, auth.length);
+ xfree(kdata);
- case SSH_CMSG_AUTH_RHOSTS:
- if (!options.rhosts_authentication)
- {
- log("Rhosts authentication disabled.");
- break;
- }
-
- /* Rhosts authentication (also uses /etc/hosts.equiv). */
- if (!privileged_port)
- {
- log("Rhosts authentication not available for connections from unprivileged port.");
- break;
- }
-
- /* Get client user name. Note that we just have to trust the client;
- this is one reason why rhosts authentication is insecure.
- (Another is IP-spoofing on a local network.) */
+ authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
+
+ log("Kerberos authentication %s%s for account %s from %s",
+ authenticated ? "accepted " : "failed",
+ tkt_user != NULL ? tkt_user : "",
+ pw->pw_name, get_canonical_hostname());
+ if (authenticated)
+ xfree(tkt_user);
+ }
+ break;
+#endif /* KRB4 */
+
+ case SSH_CMSG_AUTH_RHOSTS:
+ if (!options.rhosts_authentication)
{
- int dlen;
- client_user = packet_get_string(&dlen);
- packet_integrity_check(plen, 4 + dlen, type);
+ log("Rhosts authentication disabled.");
+ break;
}
+
+ /* Get client user name. Note that we just have to trust the client;
+ this is one reason why rhosts authentication is insecure.
+ (Another is IP-spoofing on a local network.) */
+ client_user = packet_get_string(&dlen);
+ packet_integrity_check(plen, 4 + dlen, type);
+
+ /* Try to authenticate using /etc/hosts.equiv and .rhosts. */
+ authenticated = auth_rhosts(pw, client_user);
- /* Try to authenticate using /etc/hosts.equiv and .rhosts. */
- if (auth_rhosts(pw, client_user))
- {
- /* Authentication accepted. */
- log("Rhosts authentication accepted for %.100s, remote %.100s on %.700s.",
- user, client_user, get_canonical_hostname());
- authenticated = 1;
+ log("Rhosts authentication %s for %.100s, remote %.100s on %.700s.",
+ authenticated ? "accepted" : "failed",
+ pw->pw_name, client_user, get_canonical_hostname());
#ifndef HAVE_LIBPAM
- xfree(client_user);
+ xfree(client_user);
#endif /* HAVE_LIBPAM */
- break;
- }
- log("Rhosts authentication failed for %.100s, remote %.100s.",
- user, client_user);
-#ifndef HAVE_LIBPAM
- xfree(client_user);
-#endif /* HAVE_LIBPAM */
- break;
-
- case SSH_CMSG_AUTH_RHOSTS_RSA:
- if (!options.rhosts_rsa_authentication)
- {
- log("Rhosts with RSA authentication disabled.");
- break;
- }
-
- /* Rhosts authentication (also uses /etc/hosts.equiv) with RSA
- host authentication. */
- if (!privileged_port)
- {
- log("Rhosts authentication not available for connections from unprivileged port.");
- break;
- }
-
+ break;
+
+ case SSH_CMSG_AUTH_RHOSTS_RSA:
+ if (!options.rhosts_rsa_authentication)
{
- int ulen, elen, nlen;
- /* Get client user name. Note that we just have to trust
- the client; root on the client machine can claim to be
- any user. */
- client_user = packet_get_string(&ulen);
-
- /* Get the client host key. */
- client_host_key_e = BN_new();
- client_host_key_n = BN_new();
- client_host_key_bits = packet_get_int();
- packet_get_bignum(client_host_key_e, &elen);
- packet_get_bignum(client_host_key_n, &nlen);
-
- packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
+ log("Rhosts with RSA authentication disabled.");
+ break;
}
-
- if (auth_rhosts_rsa(pw, client_user,
- client_host_key_bits, client_host_key_e, client_host_key_n))
- {
- /* Authentication accepted. */
- authenticated = 1;
-#ifndef HAVE_LIBPAM
- xfree(client_user);
-#endif /* HAVE_LIBPAM */
- BN_clear_free(client_host_key_e);
- BN_clear_free(client_host_key_n);
- break;
- }
- log("Rhosts authentication failed for %.100s, remote %.100s.",
- user, client_user);
+
+ /* Get client user name. Note that we just have to trust
+ the client; root on the client machine can claim to be
+ any user. */
+ client_user = packet_get_string(&ulen);
+
+ /* Get the client host key. */
+ client_host_key_e = BN_new();
+ client_host_key_n = BN_new();
+ client_host_key_bits = packet_get_int();
+ packet_get_bignum(client_host_key_e, &elen);
+ packet_get_bignum(client_host_key_n, &nlen);
+
+ packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
+
+ authenticated = auth_rhosts_rsa(pw, client_user, client_host_key_bits,
+ client_host_key_e, client_host_key_n);
+ log("Rhosts authentication %s for %.100s, remote %.100s.",
+ authenticated ? "accepted" : "failed",
+ pw->pw_name, client_user);
#ifndef HAVE_LIBPAM
- xfree(client_user);
+ xfree(client_user);
#endif /* HAVE_LIBPAM */
- BN_clear_free(client_host_key_e);
- BN_clear_free(client_host_key_n);
- break;
-
- case SSH_CMSG_AUTH_RSA:
- if (!options.rsa_authentication)
- {
- log("RSA authentication disabled.");
- break;
- }
-
- /* RSA authentication requested. */
+ BN_clear_free(client_host_key_e);
+ BN_clear_free(client_host_key_n);
+ break;
+
+ case SSH_CMSG_AUTH_RSA:
+ if (!options.rsa_authentication)
{
- int nlen;
- BIGNUM *n;
- n = BN_new();
- packet_get_bignum(n, &nlen);
-
- packet_integrity_check(plen, nlen, type);
-
- if (auth_rsa(pw, n))
- {
- /* Successful authentication. */
- BN_clear_free(n);
- log("RSA authentication for %.100s accepted.", user);
- authenticated = 1;
- break;
- }
- BN_clear_free(n);
- log("RSA authentication for %.100s failed.", user);
+ log("RSA authentication disabled.");
+ break;
}
- break;
-
- case SSH_CMSG_AUTH_PASSWORD:
- if (!options.password_authentication)
- {
- log("Password authentication disabled.");
- break;
- }
-
- /* Password authentication requested. */
- /* Read user password. It is in plain text, but was transmitted
- over the encrypted channel so it is not visible to an outside
- observer. */
+
+ /* RSA authentication requested. */
+ n = BN_new();
+ packet_get_bignum(n, &nlen);
+ packet_integrity_check(plen, nlen, type);
+ authenticated = auth_rsa(pw, n);
+ BN_clear_free(n);
+ log("RSA authentication %s for %.100s.",
+ authenticated ? "accepted" : "failed",
+ pw->pw_name);
+ break;
+
+ case SSH_CMSG_AUTH_PASSWORD:
+ if (!options.password_authentication)
{
- int passw_len;
- password = packet_get_string(&passw_len);
- packet_integrity_check(plen, 4 + passw_len, type);
+ log("Password authentication disabled.");
+ break;
}
-
+
+ /* Read user password. It is in plain text, but was transmitted
+ over the encrypted channel so it is not visible to an outside
+ observer. */
+ password = packet_get_string(&dlen);
+ packet_integrity_check(plen, 4 + dlen, type);
+
#ifdef HAVE_LIBPAM
- pampasswd = password;
-
- pam_retval = pam_authenticate((pam_handle_t *)pamh, 0);
- if (pam_retval == PAM_SUCCESS)
- {
- log("PAM Password authentication accepted for \"%.100s\"", user);
- authenticated = 1;
- break;
- } else
- {
- log("PAM Password authentication for \"%.100s\" failed: %s",
- user, pam_strerror((pam_handle_t *)pamh, pam_retval));
- break;
- }
+ /* Do PAM auth with password */
+ pampasswd = password;
+ pam_retval = pam_authenticate((pam_handle_t *)pamh, 0);
+ if (pam_retval == PAM_SUCCESS)
+ {
+ log("PAM Password authentication accepted for user \"%.100s\"", user);
+ authenticated = 1;
+ break;
+ }
+
+ log("PAM Password authentication for \"%.100s\" failed: %s",
+ user, pam_strerror((pam_handle_t *)pamh, pam_retval));
+ break;
#else /* HAVE_LIBPAM */
- /* Try authentication with the password. */
- if (auth_password(pw, password))
- {
- /* Successful authentication. */
- /* Clear the password from memory. */
- memset(password, 0, strlen(password));
- xfree(password);
- log("Password authentication for %.100s accepted.", user);
- authenticated = 1;
- break;
- }
- log("Password authentication for %.100s failed.", user);
- memset(password, 0, strlen(password));
- xfree(password);
- break;
-#endif /* HAVE_LIBPAM */
-
- case SSH_CMSG_AUTH_TIS:
- /* TIS Authentication is unsupported */
- log("TIS authentication disabled.");
- break;
+ /* Try authentication with the password. */
+ authenticated = auth_password(pw, password);
- default:
- /* Any unknown messages will be ignored (and failure returned)
- during authentication. */
- log("Unknown message during authentication: type %d", type);
- break; /* Respond with a failure message. */
- }
- /* If successfully authenticated, break out of loop. */
- if (authenticated)
+ memset(password, 0, strlen(password));
+ xfree(password);
break;
-
- if (++authentication_failures >= MAX_AUTH_FAILURES) {
- packet_disconnect("Too many authentication failures for %.100s from %.200s",
- pw->pw_name, get_canonical_hostname());
+#endif /* HAVE_LIBPAM */
+
+ case SSH_CMSG_AUTH_TIS:
+ /* TIS Authentication is unsupported */
+ log("TIS authentication disabled.");
+ break;
+
+ default:
+ /* Any unknown messages will be ignored (and failure returned)
+ during authentication. */
+ log("Unknown message during authentication: type %d", type);
+ break; /* Respond with a failure message. */
}
- /* Send a message indicating that the authentication attempt failed. */
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
- }
-
- /* Check if the user is logging in as root and root logins are disallowed. */
- if (pw->pw_uid == 0 && !options.permit_root_login)
- {
- if (forced_command)
- log("Root login accepted for forced command.");
- else
- packet_disconnect("ROOT LOGIN REFUSED FROM %.200s",
- get_canonical_hostname());
- }
+ if (authenticated)
+ break;
+ if (++authentication_failures >= MAX_AUTH_FAILURES)
+ packet_disconnect("Too many authentication failures for %.100s from %.200s",
+ pw->pw_name, get_canonical_hostname());
+ /* Send a message indicating that the authentication attempt failed. */
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+ }
#ifdef HAVE_LIBPAM
- do_pam_account_and_session(pw->pw_name, password, client_user, get_canonical_hostname());
+ do_pam_account_and_session(pw->pw_name, client_user, get_canonical_hostname());
/* Clean up */
if (client_user != NULL)
@@ -1542,65 +1493,55 @@ do_authentication(char *user, int privileged_port)
xfree(password);
}
#endif /* HAVE_LIBPAM */
-
- /* The user has been authenticated and accepted. */
- packet_start(SSH_SMSG_SUCCESS);
- packet_send();
- packet_write_wait();
-
- /* Perform session preparation. */
- do_authenticated(pw);
}
-/* Read authentication messages, but return only failures until */
-/* max auth attempts exceeded, then disconnect */
-void eat_packets_and_disconnect(const char *user)
+/* The user does not exist or access is denied,
+ but fake indication that authentication is needed. */
+void
+do_fake_authloop(char *user)
{
int authentication_failures = 0;
-
+
+ /* Indicate that authentication is needed. */
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
/* Keep reading packets, and always respond with a failure. This is to
avoid disclosing whether such a user really exists. */
- while(1)
- {
- /* Read a packet. This will not return if the client disconnects. */
- int plen;
-#ifndef SKEY
- (void) packet_read(&plen);
-#else /* SKEY */
- int type = packet_read(&plen);
- int passw_len;
- char *password, *skeyinfo;
- if (options.password_authentication &&
- options.skey_authentication == 1 &&
- type == SSH_CMSG_AUTH_PASSWORD &&
- (password = packet_get_string(&passw_len)) != NULL &&
- passw_len == 5 &&
- strncasecmp(password, "s/key", 5) == 0 &&
- (skeyinfo = skey_fake_keyinfo(user)) != NULL )
+ for (;;)
{
- /* Send a fake s/key challenge. */
- packet_send_debug(skeyinfo);
- }
-#endif /* SKEY */
- if (++authentication_failures >= MAX_AUTH_FAILURES)
- {
- packet_disconnect("Too many authentication failures for %.100s from %.200s",
- user, get_canonical_hostname());
+ /* Read a packet. This will not return if the client disconnects. */
+ int plen;
+ int type = packet_read(&plen);
+#ifdef SKEY
+ int passw_len;
+ char *password, *skeyinfo;
+ if (options.password_authentication &&
+ options.skey_authentication == 1 &&
+ type == SSH_CMSG_AUTH_PASSWORD &&
+ (password = packet_get_string(&passw_len)) != NULL &&
+ passw_len == 5 &&
+ strncasecmp(password, "s/key", 5) == 0 &&
+ (skeyinfo = skey_fake_keyinfo(user)) != NULL ){
+ /* Send a fake s/key challenge. */
+ packet_send_debug(skeyinfo);
+ }
+#endif
+ if (++authentication_failures >= MAX_AUTH_FAILURES)
+ packet_disconnect("Too many authentication failures for %.100s from %.200s",
+ user, get_canonical_hostname());
+ /* Send failure. This should be indistinguishable from a failed
+ authentication. */
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
}
- /* Send failure. This should be indistinguishable from a failed
- authentication. */
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
- }
/*NOTREACHED*/
abort();
}
+
/* Remove local Xauthority file. */
static void
xauthfile_cleanup_proc(void *ignore)
@@ -2075,8 +2016,10 @@ void do_exec_pty(const char *command, int ptyfd, int ttyfd,
{
fromlen = sizeof(from);
if (getpeername(packet_get_connection_in(),
- (struct sockaddr *)&from, &fromlen) < 0)
- fatal("getpeername: %.100s", strerror(errno));
+ (struct sockaddr *)&from, &fromlen) < 0) {
+ debug("getpeername: %.100s", strerror(errno));
+ fatal_cleanup();
+ }
}
/* Record that there was a login on that terminal. */