version 1.113, 2015/08/21 03:42:19 |
version 1.114, 2016/03/07 19:02:43 |
|
|
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <sys/stat.h> |
|
#include <sys/socket.h> |
|
|
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
|
|
#include <string.h> |
#include <string.h> |
#include <unistd.h> |
#include <unistd.h> |
#include <limits.h> |
#include <limits.h> |
|
#include <netdb.h> |
|
|
#include "xmalloc.h" |
#include "xmalloc.h" |
#include "match.h" |
#include "match.h" |
|
|
int |
int |
allowed_user(struct passwd * pw) |
allowed_user(struct passwd * pw) |
{ |
{ |
|
struct ssh *ssh = active_state; /* XXX */ |
struct stat st; |
struct stat st; |
const char *hostname = NULL, *ipaddr = NULL; |
const char *hostname = NULL, *ipaddr = NULL; |
u_int i; |
u_int i; |
|
|
|
|
if (options.num_deny_users > 0 || options.num_allow_users > 0 || |
if (options.num_deny_users > 0 || options.num_allow_users > 0 || |
options.num_deny_groups > 0 || options.num_allow_groups > 0) { |
options.num_deny_groups > 0 || options.num_allow_groups > 0) { |
hostname = get_canonical_hostname(options.use_dns); |
hostname = auth_get_canonical_hostname(ssh, options.use_dns); |
ipaddr = get_remote_ipaddr(); |
ipaddr = ssh_remote_ipaddr(ssh); |
} |
} |
|
|
/* Return false if user is listed in DenyUsers */ |
/* Return false if user is listed in DenyUsers */ |
|
|
auth_log(Authctxt *authctxt, int authenticated, int partial, |
auth_log(Authctxt *authctxt, int authenticated, int partial, |
const char *method, const char *submethod) |
const char *method, const char *submethod) |
{ |
{ |
|
struct ssh *ssh = active_state; /* XXX */ |
void (*authlog) (const char *fmt,...) = verbose; |
void (*authlog) (const char *fmt,...) = verbose; |
char *authmsg; |
char *authmsg; |
|
|
|
|
submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod, |
submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod, |
authctxt->valid ? "" : "invalid user ", |
authctxt->valid ? "" : "invalid user ", |
authctxt->user, |
authctxt->user, |
get_remote_ipaddr(), |
ssh_remote_ipaddr(ssh), |
get_remote_port(), |
ssh_remote_port(ssh), |
compat20 ? "ssh2" : "ssh1", |
compat20 ? "ssh2" : "ssh1", |
authctxt->info != NULL ? ": " : "", |
authctxt->info != NULL ? ": " : "", |
authctxt->info != NULL ? authctxt->info : ""); |
authctxt->info != NULL ? authctxt->info : ""); |
|
|
void |
void |
auth_maxtries_exceeded(Authctxt *authctxt) |
auth_maxtries_exceeded(Authctxt *authctxt) |
{ |
{ |
|
struct ssh *ssh = active_state; /* XXX */ |
|
|
error("maximum authentication attempts exceeded for " |
error("maximum authentication attempts exceeded for " |
"%s%.100s from %.200s port %d %s", |
"%s%.100s from %.200s port %d %s", |
authctxt->valid ? "" : "invalid user ", |
authctxt->valid ? "" : "invalid user ", |
authctxt->user, |
authctxt->user, |
get_remote_ipaddr(), |
ssh_remote_ipaddr(ssh), |
get_remote_port(), |
ssh_remote_port(ssh), |
compat20 ? "ssh2" : "ssh1"); |
compat20 ? "ssh2" : "ssh1"); |
packet_disconnect("Too many authentication failures"); |
packet_disconnect("Too many authentication failures"); |
/* NOTREACHED */ |
/* NOTREACHED */ |
|
|
int |
int |
auth_root_allowed(const char *method) |
auth_root_allowed(const char *method) |
{ |
{ |
|
struct ssh *ssh = active_state; /* XXX */ |
|
|
switch (options.permit_root_login) { |
switch (options.permit_root_login) { |
case PERMIT_YES: |
case PERMIT_YES: |
return 1; |
return 1; |
|
|
} |
} |
break; |
break; |
} |
} |
logit("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr()); |
logit("ROOT LOGIN REFUSED FROM %.200s port %d", |
|
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); |
return 0; |
return 0; |
} |
} |
|
|
|
|
struct passwd * |
struct passwd * |
getpwnamallow(const char *user) |
getpwnamallow(const char *user) |
{ |
{ |
|
struct ssh *ssh = active_state; /* XXX */ |
extern login_cap_t *lc; |
extern login_cap_t *lc; |
auth_session_t *as; |
auth_session_t *as; |
struct passwd *pw; |
struct passwd *pw; |
|
|
|
|
pw = getpwnam(user); |
pw = getpwnam(user); |
if (pw == NULL) { |
if (pw == NULL) { |
logit("Invalid user %.100s from %.100s", |
logit("Invalid user %.100s from %.100s port %d", |
user, get_remote_ipaddr()); |
user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); |
return (NULL); |
return (NULL); |
} |
} |
if (!allowed_user(pw)) |
if (!allowed_user(pw)) |
|
|
fake.pw_shell = "/nonexist"; |
fake.pw_shell = "/nonexist"; |
|
|
return (&fake); |
return (&fake); |
|
} |
|
|
|
/* |
|
* Returns the remote DNS hostname as a string. The returned string must not |
|
* be freed. NB. this will usually trigger a DNS query the first time it is |
|
* called. |
|
* This function does additional checks on the hostname to mitigate some |
|
* attacks on legacy rhosts-style authentication. |
|
* XXX is RhostsRSAAuthentication vulnerable to these? |
|
* XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?) |
|
*/ |
|
|
|
static char * |
|
remote_hostname(struct ssh *ssh) |
|
{ |
|
struct sockaddr_storage from; |
|
socklen_t fromlen; |
|
struct addrinfo hints, *ai, *aitop; |
|
char name[NI_MAXHOST], ntop2[NI_MAXHOST]; |
|
const char *ntop = ssh_remote_ipaddr(ssh); |
|
|
|
/* Get IP address of client. */ |
|
fromlen = sizeof(from); |
|
memset(&from, 0, sizeof(from)); |
|
if (getpeername(ssh_packet_get_connection_in(ssh), |
|
(struct sockaddr *)&from, &fromlen) < 0) { |
|
debug("getpeername failed: %.100s", strerror(errno)); |
|
return strdup(ntop); |
|
} |
|
|
|
debug3("Trying to reverse map address %.100s.", ntop); |
|
/* Map the IP address to a host name. */ |
|
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), |
|
NULL, 0, NI_NAMEREQD) != 0) { |
|
/* Host name not found. Use ip address. */ |
|
return strdup(ntop); |
|
} |
|
|
|
/* |
|
* if reverse lookup result looks like a numeric hostname, |
|
* someone is trying to trick us by PTR record like following: |
|
* 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 |
|
*/ |
|
memset(&hints, 0, sizeof(hints)); |
|
hints.ai_socktype = SOCK_DGRAM; /*dummy*/ |
|
hints.ai_flags = AI_NUMERICHOST; |
|
if (getaddrinfo(name, NULL, &hints, &ai) == 0) { |
|
logit("Nasty PTR record \"%s\" is set up for %s, ignoring", |
|
name, ntop); |
|
freeaddrinfo(ai); |
|
return strdup(ntop); |
|
} |
|
|
|
/* Names are stored in lowercase. */ |
|
lowercase(name); |
|
|
|
/* |
|
* Map it back to an IP address and check that the given |
|
* address actually is an address of this host. This is |
|
* necessary because anyone with access to a name server can |
|
* define arbitrary names for an IP address. Mapping from |
|
* name to IP address can be trusted better (but can still be |
|
* fooled if the intruder has access to the name server of |
|
* the domain). |
|
*/ |
|
memset(&hints, 0, sizeof(hints)); |
|
hints.ai_family = from.ss_family; |
|
hints.ai_socktype = SOCK_STREAM; |
|
if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { |
|
logit("reverse mapping checking getaddrinfo for %.700s " |
|
"[%s] failed - POSSIBLE BREAK-IN ATTEMPT!", name, ntop); |
|
return strdup(ntop); |
|
} |
|
/* Look for the address from the list of addresses. */ |
|
for (ai = aitop; ai; ai = ai->ai_next) { |
|
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, |
|
sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && |
|
(strcmp(ntop, ntop2) == 0)) |
|
break; |
|
} |
|
freeaddrinfo(aitop); |
|
/* If we reached the end of the list, the address was not there. */ |
|
if (ai == NULL) { |
|
/* Address not found for the host name. */ |
|
logit("Address %.100s maps to %.600s, but this does not " |
|
"map back to the address - POSSIBLE BREAK-IN ATTEMPT!", |
|
ntop, name); |
|
return strdup(ntop); |
|
} |
|
return strdup(name); |
|
} |
|
|
|
/* |
|
* Return the canonical name of the host in the other side of the current |
|
* connection. The host name is cached, so it is efficient to call this |
|
* several times. |
|
*/ |
|
|
|
const char * |
|
auth_get_canonical_hostname(struct ssh *ssh, int use_dns) |
|
{ |
|
static char *dnsname; |
|
|
|
if (!use_dns) |
|
return ssh_remote_ipaddr(ssh); |
|
else if (dnsname != NULL) |
|
return dnsname; |
|
else { |
|
dnsname = remote_hostname(ssh); |
|
return dnsname; |
|
} |
} |
} |