- 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.
This commit is contained in:
parent
cedfecc99e
commit
2ccf661cbe
17
ChangeLog
17
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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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)
|
||||
|
|
17
canohost.c
17
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. */
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
34
readconf.c
34
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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
7
ssh.c
7
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:
|
||||
|
|
|
@ -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);
|
||||
|
|
711
sshd.c
711
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,300 +1225,13 @@ 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
|
||||
{
|
||||
/* Indicate that authentication is needed. */
|
||||
packet_start(SSH_SMSG_FAILURE);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
} else {
|
||||
/* Loop until the user has been authenticated or the connection is closed,
|
||||
do_authloop() returns only if authentication is successfull */
|
||||
do_authloop(pw);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
|
||||
#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;
|
||||
|
||||
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. */
|
||||
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;
|
||||
}
|
||||
#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());
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* KRB4 */
|
||||
|
||||
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.) */
|
||||
{
|
||||
int dlen;
|
||||
client_user = packet_get_string(&dlen);
|
||||
packet_integrity_check(plen, 4 + dlen, type);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
#ifndef HAVE_LIBPAM
|
||||
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;
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
#ifndef HAVE_LIBPAM
|
||||
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. */
|
||||
{
|
||||
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);
|
||||
}
|
||||
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. */
|
||||
{
|
||||
int passw_len;
|
||||
password = packet_get_string(&passw_len);
|
||||
packet_integrity_check(plen, 4 + passw_len, 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;
|
||||
}
|
||||
#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;
|
||||
|
||||
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)
|
||||
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();
|
||||
|
||||
}
|
||||
/* 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)
|
||||
|
@ -1529,8 +1243,245 @@ do_authentication(char *user, int privileged_port)
|
|||
get_canonical_hostname());
|
||||
}
|
||||
|
||||
/* The user has been authenticated and accepted. */
|
||||
packet_start(SSH_SMSG_SUCCESS);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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("Kerberos tgt passing disabled.");
|
||||
break;
|
||||
}
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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);
|
||||
#endif /* HAVE_LIBPAM */
|
||||
break;
|
||||
|
||||
case SSH_CMSG_AUTH_RHOSTS_RSA:
|
||||
if (!options.rhosts_rsa_authentication)
|
||||
{
|
||||
log("Rhosts with RSA authentication disabled.");
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
#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. */
|
||||
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)
|
||||
{
|
||||
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
|
||||
do_pam_account_and_session(pw->pw_name, password, client_user, get_canonical_hostname());
|
||||
/* 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. */
|
||||
authenticated = auth_password(pw, password);
|
||||
|
||||
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;
|
||||
|
||||
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 (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, 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);
|
||||
/* 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();
|
||||
}
|
||||
#endif /* SKEY */
|
||||
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();
|
||||
}
|
||||
/*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. */
|
||||
|
|
Loading…
Reference in New Issue