mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-26 23:34:55 +02:00
- 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
|
- Changed to ssh-add.c broke askpass support. Revised it to be a little more
|
||||||
modular.
|
modular.
|
||||||
- Revised autoconf support for enabling/disabling askpass support.
|
- 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
|
19991114
|
||||||
- Solaris compilation fixes (still imcomplete)
|
- Solaris compilation fixes (still imcomplete)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
Kerberos v4 authentication and ticket-passing routines.
|
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"
|
#include "includes.h"
|
||||||
@ -89,8 +89,10 @@ int auth_krb4(const char *server_user, KTEXT auth, char **client)
|
|||||||
debug("getsockname failed: %.100s", strerror(errno));
|
debug("getsockname failed: %.100s", strerror(errno));
|
||||||
r = sizeof(foreign);
|
r = sizeof(foreign);
|
||||||
memset(&foreign, 0, 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));
|
debug("getpeername failed: %.100s", strerror(errno));
|
||||||
|
fatal_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
instance[0] = '*'; instance[1] = 0;
|
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!");
|
packet_send_debug("Kerberos V4 .klogin authorization failed!");
|
||||||
log("Kerberos V4 .klogin authorization failed for %s to account %s",
|
log("Kerberos V4 .klogin authorization failed for %s to account %s",
|
||||||
*client, server_user);
|
*client, server_user);
|
||||||
|
xfree(*client);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Increment the checksum, and return it encrypted with the session key. */
|
/* 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"
|
#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 "packet.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
@ -161,7 +161,6 @@ int auth_rhosts(struct passwd *pw, const char *client_user)
|
|||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
const char *hostname, *ipaddr;
|
const char *hostname, *ipaddr;
|
||||||
int port;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
static const char *rhosts_files[] = { ".shosts", ".rhosts", NULL };
|
static const char *rhosts_files[] = { ".shosts", ".rhosts", NULL };
|
||||||
unsigned int rhosts_file_index;
|
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. */
|
/* Get the name, address, and port of the remote host. */
|
||||||
hostname = get_canonical_hostname();
|
hostname = get_canonical_hostname();
|
||||||
ipaddr = get_remote_ipaddr();
|
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 not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
|
||||||
if (pw->pw_uid != 0)
|
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"
|
#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 "packet.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
@ -35,9 +35,8 @@ char *get_remote_hostname(int socket)
|
|||||||
memset(&from, 0, sizeof(from));
|
memset(&from, 0, sizeof(from));
|
||||||
if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
|
if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
|
||||||
{
|
{
|
||||||
error("getpeername failed: %.100s", strerror(errno));
|
debug("getpeername failed: %.100s", strerror(errno));
|
||||||
strlcpy(name, "UNKNOWN", sizeof name);
|
fatal_cleanup();
|
||||||
goto check_ip_options;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Map the IP address to a host name. */
|
/* Map the IP address to a host name. */
|
||||||
@ -99,7 +98,7 @@ char *get_remote_hostname(int socket)
|
|||||||
|
|
||||||
check_ip_options:
|
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;
|
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.
|
it can be used to pretend you are somebody (ip-address) you are not.
|
||||||
That itself may be "almost acceptable" under certain circumstances,
|
That itself may be "almost acceptable" under certain circumstances,
|
||||||
@ -184,8 +183,8 @@ const char *get_remote_ipaddr()
|
|||||||
memset(&from, 0, sizeof(from));
|
memset(&from, 0, sizeof(from));
|
||||||
if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
|
if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
|
||||||
{
|
{
|
||||||
error("getpeername failed: %.100s", strerror(errno));
|
debug("getpeername failed: %.100s", strerror(errno));
|
||||||
return NULL;
|
fatal_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the IP address in ascii. */
|
/* Get the IP address in ascii. */
|
||||||
@ -207,8 +206,8 @@ int get_peer_port(int sock)
|
|||||||
memset(&from, 0, sizeof(from));
|
memset(&from, 0, sizeof(from));
|
||||||
if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0)
|
if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0)
|
||||||
{
|
{
|
||||||
error("getpeername failed: %.100s", strerror(errno));
|
debug("getpeername failed: %.100s", strerror(errno));
|
||||||
return 0;
|
fatal_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return port number. */
|
/* Return port number. */
|
||||||
|
@ -15,7 +15,7 @@ to the system log.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 <syslog.h>
|
||||||
#include "packet.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 LogLevel log_level = SYSLOG_LEVEL_INFO;
|
||||||
static int log_on_stderr = 0;
|
static int log_on_stderr = 0;
|
||||||
|
static int log_facility = LOG_AUTH;
|
||||||
|
|
||||||
/* Initialize the log.
|
/* Initialize the log.
|
||||||
av0 program name (should be argv[0])
|
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)
|
void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
|
||||||
{
|
{
|
||||||
int log_facility;
|
|
||||||
|
|
||||||
switch (level)
|
switch (level)
|
||||||
{
|
{
|
||||||
@ -93,8 +93,6 @@ void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
log_on_stderr = on_stderr;
|
log_on_stderr = on_stderr;
|
||||||
closelog(); /* Close any previous log. */
|
|
||||||
openlog(av0, LOG_PID, log_facility);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MSGBUFSIZE 1024
|
#define MSGBUFSIZE 1024
|
||||||
@ -106,6 +104,7 @@ do_log(LogLevel level, const char *fmt, va_list args)
|
|||||||
char fmtbuf[MSGBUFSIZE];
|
char fmtbuf[MSGBUFSIZE];
|
||||||
char *txt = NULL;
|
char *txt = NULL;
|
||||||
int pri = LOG_INFO;
|
int pri = LOG_INFO;
|
||||||
|
extern char *__progname;
|
||||||
|
|
||||||
if (level > log_level)
|
if (level > log_level)
|
||||||
return;
|
return;
|
||||||
@ -143,5 +142,7 @@ do_log(LogLevel level, const char *fmt, va_list args)
|
|||||||
}
|
}
|
||||||
if (log_on_stderr)
|
if (log_on_stderr)
|
||||||
fprintf(stderr, "%s\n", msgbuf);
|
fprintf(stderr, "%s\n", msgbuf);
|
||||||
|
openlog(__progname, LOG_PID, log_facility);
|
||||||
syslog(pri, "%.500s", msgbuf);
|
syslog(pri, "%.500s", msgbuf);
|
||||||
|
closelog();
|
||||||
}
|
}
|
||||||
|
34
readconf.c
34
readconf.c
@ -14,7 +14,7 @@ Functions for reading the configuration files.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "ssh.h"
|
||||||
#include "cipher.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
|
typedef enum
|
||||||
{
|
{
|
||||||
|
oBadOption,
|
||||||
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
|
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
|
||||||
oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
|
oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
|
||||||
#ifdef KRB4
|
#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)
|
if (strcmp(cp, keywords[i].name) == 0)
|
||||||
return keywords[i].opcode;
|
return keywords[i].opcode;
|
||||||
|
|
||||||
fatal("%.200s line %d: Bad configuration option.",
|
fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
|
||||||
filename, linenum);
|
filename, linenum, cp);
|
||||||
/*NOTREACHED*/
|
return oBadOption;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Processes a single option line as used in the configuration files.
|
/* Processes a single option line as used in the configuration files.
|
||||||
This only sets those values that have not already been set. */
|
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,
|
char *line, const char *filename, int linenum,
|
||||||
int *activep)
|
int *activep)
|
||||||
{
|
{
|
||||||
@ -241,7 +242,7 @@ void process_config_line(Options *options, const char *host,
|
|||||||
/* Skip leading whitespace. */
|
/* Skip leading whitespace. */
|
||||||
cp = line + strspn(line, WHITESPACE);
|
cp = line + strspn(line, WHITESPACE);
|
||||||
if (!*cp || *cp == '\n' || *cp == '#')
|
if (!*cp || *cp == '\n' || *cp == '#')
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
/* Get the keyword. (Each line is supposed to begin with a keyword). */
|
/* Get the keyword. (Each line is supposed to begin with a keyword). */
|
||||||
cp = strtok(cp, WHITESPACE);
|
cp = strtok(cp, WHITESPACE);
|
||||||
@ -256,7 +257,9 @@ void process_config_line(Options *options, const char *host,
|
|||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
|
case oBadOption:
|
||||||
|
return -1; /* don't panic, but count bad options */
|
||||||
|
/*NOTREACHED*/
|
||||||
case oForwardAgent:
|
case oForwardAgent:
|
||||||
intptr = &options->forward_agent;
|
intptr = &options->forward_agent;
|
||||||
parse_flag:
|
parse_flag:
|
||||||
@ -426,7 +429,7 @@ void process_config_line(Options *options, const char *host,
|
|||||||
*charptr = string;
|
*charptr = string;
|
||||||
else
|
else
|
||||||
xfree(string);
|
xfree(string);
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
case oPort:
|
case oPort:
|
||||||
intptr = &options->port;
|
intptr = &options->port;
|
||||||
@ -533,7 +536,7 @@ void process_config_line(Options *options, const char *host,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Avoid garbage check below, as strtok already returned NULL. */
|
/* Avoid garbage check below, as strtok already returned NULL. */
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
case oEscapeChar:
|
case oEscapeChar:
|
||||||
intptr = &options->escape_char;
|
intptr = &options->escape_char;
|
||||||
@ -561,13 +564,14 @@ void process_config_line(Options *options, const char *host,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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. */
|
/* Check that there is no garbage at end of line. */
|
||||||
if (strtok(NULL, WHITESPACE) != NULL)
|
if (strtok(NULL, WHITESPACE) != NULL)
|
||||||
fatal("%.200s line %d: garbage at end of line.",
|
fatal("%.200s line %d: garbage at end of line.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -580,6 +584,7 @@ void read_config_file(const char *filename, const char *host, Options *options)
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
char line[1024];
|
char line[1024];
|
||||||
int active, linenum;
|
int active, linenum;
|
||||||
|
int bad_options = 0;
|
||||||
|
|
||||||
/* Open the file. */
|
/* Open the file. */
|
||||||
f = fopen(filename, "r");
|
f = fopen(filename, "r");
|
||||||
@ -596,10 +601,13 @@ void read_config_file(const char *filename, const char *host, Options *options)
|
|||||||
{
|
{
|
||||||
/* Update line number counter. */
|
/* Update line number counter. */
|
||||||
linenum++;
|
linenum++;
|
||||||
|
if (process_config_line(options, host, line, filename, linenum, &active) != 0)
|
||||||
process_config_line(options, host, line, filename, linenum, &active);
|
bad_options++;
|
||||||
}
|
}
|
||||||
fclose(f);
|
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
|
/* 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
|
#ifndef READCONF_H
|
||||||
#define READCONF_H
|
#define READCONF_H
|
||||||
@ -92,8 +92,9 @@ void initialize_options(Options *options);
|
|||||||
void fill_default_options(Options *options);
|
void fill_default_options(Options *options);
|
||||||
|
|
||||||
/* Processes a single option line as used in the configuration files.
|
/* Processes a single option line as used in the configuration files.
|
||||||
This only sets those values that have not already been set. */
|
This only sets those values that have not already been set.
|
||||||
void process_config_line(Options *options, const char *host,
|
Returns 0 for legal options */
|
||||||
|
int process_config_line(Options *options, const char *host,
|
||||||
char *line, const char *filename, int linenum,
|
char *line, const char *filename, int linenum,
|
||||||
int *activep);
|
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"
|
#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 "xmalloc.h"
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
@ -383,8 +383,9 @@ main(int ac, char **av)
|
|||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
dummy = 1;
|
dummy = 1;
|
||||||
process_config_line(&options, host ? host : "", optarg,
|
if (process_config_line(&options, host ? host : "", optarg,
|
||||||
"command-line", 0, &dummy);
|
"command-line", 0, &dummy) != 0)
|
||||||
|
exit(1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -15,7 +15,7 @@ login (authentication) dialog.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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
|
#ifdef HAVE_OPENSSL
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
@ -730,8 +730,10 @@ int try_kerberos_authentication()
|
|||||||
r = sizeof(foreign);
|
r = sizeof(foreign);
|
||||||
memset(&foreign, 0, sizeof(foreign));
|
memset(&foreign, 0, sizeof(foreign));
|
||||||
if (getpeername(packet_get_connection_in(),
|
if (getpeername(packet_get_connection_in(),
|
||||||
(struct sockaddr *)&foreign, &r) < 0)
|
(struct sockaddr *)&foreign, &r) < 0) {
|
||||||
debug("getpeername failed: %s", strerror(errno));
|
debug("getpeername failed: %s", strerror(errno));
|
||||||
|
fatal_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
/* Get server reply. */
|
/* Get server reply. */
|
||||||
type = packet_read(&plen);
|
type = packet_read(&plen);
|
||||||
|
705
sshd.c
705
sshd.c
@ -18,7 +18,7 @@ agent connections.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "xmalloc.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
@ -114,9 +114,10 @@ int received_sighup = 0;
|
|||||||
RSA *public_key;
|
RSA *public_key;
|
||||||
|
|
||||||
/* Prototypes for various functions defined later in this file. */
|
/* Prototypes for various functions defined later in this file. */
|
||||||
void do_connection(int privileged_port);
|
void do_connection();
|
||||||
void do_authentication(char *user, int privileged_port);
|
void do_authentication(char *user);
|
||||||
void eat_packets_and_disconnect(const char *user);
|
void do_authloop(struct passwd *pw);
|
||||||
|
void do_fake_authloop(char *user);
|
||||||
void do_authenticated(struct passwd *pw);
|
void do_authenticated(struct passwd *pw);
|
||||||
void do_exec_pty(const char *command, int ptyfd, int ttyfd,
|
void do_exec_pty(const char *command, int ptyfd, int ttyfd,
|
||||||
const char *ttyname, struct passwd *pw, const char *term,
|
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,
|
void do_child(const char *command, struct passwd *pw, const char *term,
|
||||||
const char *display, const char *auth_proto,
|
const char *display, const char *auth_proto,
|
||||||
const char *auth_data, const char *ttyname);
|
const char *auth_data, const char *ttyname);
|
||||||
|
|
||||||
#ifdef HAVE_LIBPAM
|
#ifdef HAVE_LIBPAM
|
||||||
static int pamconv(int num_msg, const struct pam_message **msg,
|
static int pamconv(int num_msg, const struct pam_message **msg,
|
||||||
struct pam_response **resp, void *appdata_ptr);
|
struct pam_response **resp, void *appdata_ptr);
|
||||||
void do_pam_account_and_session(const char *username, const char *password,
|
void do_pam_account_and_session(const char *username,
|
||||||
const char *remote_user, const char *remote_host);
|
const char *remote_user, const char *remote_host);
|
||||||
void pam_cleanup_proc(void *context);
|
void pam_cleanup_proc(void *context);
|
||||||
|
|
||||||
static struct pam_conv conv = {
|
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;
|
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)
|
if (pam_retval != PAM_SUCCESS)
|
||||||
{
|
{
|
||||||
log("PAM set rhost failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval));
|
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)
|
if (pam_retval != PAM_SUCCESS)
|
||||||
{
|
{
|
||||||
log("PAM set ruser failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval));
|
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)
|
if (pam_retval != PAM_SUCCESS)
|
||||||
{
|
{
|
||||||
log("PAM rejected by account configuration: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval));
|
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);
|
pam_retval = pam_open_session((pam_handle_t *)pamh, 0);
|
||||||
if (pam_retval != PAM_SUCCESS)
|
if (pam_retval != PAM_SUCCESS)
|
||||||
{
|
{
|
||||||
log("PAM session setup failed: %.200s", pam_strerror((pam_handle_t *)pamh, pam_retval));
|
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 */
|
#endif /* HAVE_LIBPAM */
|
||||||
@ -375,6 +377,7 @@ main(int ac, char **av)
|
|||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
char buf[100]; /* Must not be larger than remote_version. */
|
char buf[100]; /* Must not be larger than remote_version. */
|
||||||
char remote_version[100]; /* Must be at least as big as buf. */
|
char remote_version[100]; /* Must be at least as big as buf. */
|
||||||
|
int remote_port;
|
||||||
char *comment;
|
char *comment;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
struct linger linger;
|
struct linger linger;
|
||||||
@ -742,6 +745,8 @@ main(int ac, char **av)
|
|||||||
have a key. */
|
have a key. */
|
||||||
packet_set_connection(sock_in, sock_out);
|
packet_set_connection(sock_in, sock_out);
|
||||||
|
|
||||||
|
remote_port = get_remote_port();
|
||||||
|
|
||||||
/* Check whether logins are denied from this host. */
|
/* Check whether logins are denied from this host. */
|
||||||
#ifdef LIBWRAP
|
#ifdef LIBWRAP
|
||||||
{
|
{
|
||||||
@ -755,13 +760,11 @@ main(int ac, char **av)
|
|||||||
close(sock_out);
|
close(sock_out);
|
||||||
refuse(&req);
|
refuse(&req);
|
||||||
}
|
}
|
||||||
log("Connection from %.500s port %d",
|
log("Connection from %.500s port %d", eval_client(&req), remote_port);
|
||||||
eval_client(&req), get_remote_port());
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* Log the connection. */
|
/* Log the connection. */
|
||||||
log("Connection from %.100s port %d",
|
log("Connection from %.100s port %d", get_remote_ipaddr(), remote_port);
|
||||||
get_remote_ipaddr(), get_remote_port());
|
|
||||||
#endif /* LIBWRAP */
|
#endif /* LIBWRAP */
|
||||||
|
|
||||||
/* We don\'t want to listen forever unless the other side successfully
|
/* 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();
|
packet_set_nonblocking();
|
||||||
|
|
||||||
/* Handle the connection. We pass as argument whether the connection
|
/* Handle the connection. */
|
||||||
came from a privileged port. */
|
do_connection();
|
||||||
do_connection(get_remote_port() < IPPORT_RESERVED);
|
|
||||||
|
|
||||||
#ifdef KRB4
|
#ifdef KRB4
|
||||||
/* Cleanup user's ticket cache file. */
|
/* 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.
|
been exchanged. This sends server key and performs the key exchange.
|
||||||
Server and host keys will no longer be needed after this functions. */
|
Server and host keys will no longer be needed after this functions. */
|
||||||
|
|
||||||
void do_connection(int privileged_port)
|
void
|
||||||
|
do_connection()
|
||||||
{
|
{
|
||||||
int i, len;
|
int i, len;
|
||||||
BIGNUM *session_key_int;
|
BIGNUM *session_key_int;
|
||||||
@ -1071,7 +1087,7 @@ void do_connection(int privileged_port)
|
|||||||
|
|
||||||
setproctitle("%s", user);
|
setproctitle("%s", user);
|
||||||
/* Do the authentication. */
|
/* 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
|
/* Check if the user is allowed to log in via ssh. If user is listed in
|
||||||
@ -1154,25 +1170,12 @@ allowed_user(struct passwd *pw)
|
|||||||
|
|
||||||
/* Performs authentication of an incoming connection. Session key has already
|
/* Performs authentication of an incoming connection. Session key has already
|
||||||
been exchanged and encryption is enabled. User is the user name to log
|
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
|
in as (received from the client). */
|
||||||
connection comes from a privileged port (used for .rhosts authentication).*/
|
|
||||||
|
|
||||||
#define MAX_AUTH_FAILURES 5
|
|
||||||
|
|
||||||
void
|
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;
|
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
|
#ifdef AFS
|
||||||
/* If machine has AFS, set process authentication group. */
|
/* If machine has AFS, set process authentication group. */
|
||||||
@ -1185,7 +1188,7 @@ do_authentication(char *user, int privileged_port)
|
|||||||
/* Verify that the user is a valid user. */
|
/* Verify that the user is a valid user. */
|
||||||
pw = getpwnam(user);
|
pw = getpwnam(user);
|
||||||
if (!pw || !allowed_user(pw))
|
if (!pw || !allowed_user(pw))
|
||||||
eat_packets_and_disconnect(user);
|
do_fake_authloop(user);
|
||||||
|
|
||||||
/* Take a copy of the returned structure. */
|
/* Take a copy of the returned structure. */
|
||||||
memset(&pwcopy, 0, sizeof(pwcopy));
|
memset(&pwcopy, 0, sizeof(pwcopy));
|
||||||
@ -1199,13 +1202,11 @@ do_authentication(char *user, int privileged_port)
|
|||||||
|
|
||||||
#ifdef HAVE_LIBPAM
|
#ifdef HAVE_LIBPAM
|
||||||
debug("Starting up PAM with username \"%.200s\"", pw->pw_name);
|
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)
|
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));
|
||||||
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);
|
||||||
}
|
|
||||||
fatal_add_cleanup(&pam_cleanup_proc, NULL);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If we are not running as root, the user must have the same uid as the
|
/* 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. */
|
/* Authentication with empty password succeeded. */
|
||||||
debug("Login for user %.100s accepted without authentication.", user);
|
debug("Login for user %.100s accepted without authentication.", user);
|
||||||
/* authentication_type = SSH_AUTH_PASSWORD; */
|
} else {
|
||||||
authenticated = 1;
|
/* Loop until the user has been authenticated or the connection is closed,
|
||||||
/* Success packet will be sent after loop below. */
|
do_authloop() returns only if authentication is successfull */
|
||||||
}
|
do_authloop(pw);
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Indicate that authentication is needed. */
|
|
||||||
packet_start(SSH_SMSG_FAILURE);
|
|
||||||
packet_send();
|
|
||||||
packet_write_wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Loop until the user has been authenticated or the connection is closed. */
|
/* XXX log unified auth message */
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if the user is logging in as root and root logins are disallowed. */
|
/* Check if the user is logging in as root and root logins are disallowed. */
|
||||||
if (pw->pw_uid == 0 && !options.permit_root_login)
|
if (pw->pw_uid == 0 && !options.permit_root_login)
|
||||||
@ -1529,8 +1243,245 @@ do_authentication(char *user, int privileged_port)
|
|||||||
get_canonical_hostname());
|
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
|
#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 */
|
/* Clean up */
|
||||||
if (client_user != NULL)
|
if (client_user != NULL)
|
||||||
@ -1542,65 +1493,55 @@ do_authentication(char *user, int privileged_port)
|
|||||||
xfree(password);
|
xfree(password);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_LIBPAM */
|
#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 */
|
/* The user does not exist or access is denied,
|
||||||
/* max auth attempts exceeded, then disconnect */
|
but fake indication that authentication is needed. */
|
||||||
void eat_packets_and_disconnect(const char *user)
|
void
|
||||||
|
do_fake_authloop(char *user)
|
||||||
{
|
{
|
||||||
int authentication_failures = 0;
|
int authentication_failures = 0;
|
||||||
|
|
||||||
|
/* Indicate that authentication is needed. */
|
||||||
packet_start(SSH_SMSG_FAILURE);
|
packet_start(SSH_SMSG_FAILURE);
|
||||||
packet_send();
|
packet_send();
|
||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
|
|
||||||
/* Keep reading packets, and always respond with a failure. This is to
|
/* Keep reading packets, and always respond with a failure. This is to
|
||||||
avoid disclosing whether such a user really exists. */
|
avoid disclosing whether such a user really exists. */
|
||||||
while(1)
|
for (;;)
|
||||||
{
|
|
||||||
/* 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 )
|
|
||||||
{
|
{
|
||||||
/* Send a fake s/key challenge. */
|
/* Read a packet. This will not return if the client disconnects. */
|
||||||
packet_send_debug(skeyinfo);
|
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*/
|
/*NOTREACHED*/
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Remove local Xauthority file. */
|
/* Remove local Xauthority file. */
|
||||||
static void
|
static void
|
||||||
xauthfile_cleanup_proc(void *ignore)
|
xauthfile_cleanup_proc(void *ignore)
|
||||||
@ -2075,8 +2016,10 @@ void do_exec_pty(const char *command, int ptyfd, int ttyfd,
|
|||||||
{
|
{
|
||||||
fromlen = sizeof(from);
|
fromlen = sizeof(from);
|
||||||
if (getpeername(packet_get_connection_in(),
|
if (getpeername(packet_get_connection_in(),
|
||||||
(struct sockaddr *)&from, &fromlen) < 0)
|
(struct sockaddr *)&from, &fromlen) < 0) {
|
||||||
fatal("getpeername: %.100s", strerror(errno));
|
debug("getpeername: %.100s", strerror(errno));
|
||||||
|
fatal_cleanup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record that there was a login on that terminal. */
|
/* Record that there was a login on that terminal. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user