version 1.160, 2023/03/05 05:34:09 |
version 1.161, 2024/05/17 00:30:23 |
|
|
/* import */ |
/* import */ |
extern ServerOptions options; |
extern ServerOptions options; |
extern struct include_list includes; |
extern struct include_list includes; |
extern int use_privsep; |
|
extern struct sshauthopt *auth_opts; |
extern struct sshauthopt *auth_opts; |
|
|
/* Debugging messages */ |
/* Debugging messages */ |
|
|
const char *authmsg; |
const char *authmsg; |
char *extra = NULL; |
char *extra = NULL; |
|
|
if (use_privsep && !mm_is_monitor() && !authctxt->postponed) |
if (!mm_is_monitor() && !authctxt->postponed) |
return; |
return; |
|
|
/* Raise logging level */ |
/* Raise logging level */ |
|
|
struct connection_info *ci; |
struct connection_info *ci; |
u_int i; |
u_int i; |
|
|
ci = get_connection_info(ssh, 1, options.use_dns); |
ci = server_get_connection_info(ssh, 1, options.use_dns); |
ci->user = user; |
ci->user = user; |
parse_server_match_config(&options, &includes, ci); |
parse_server_match_config(&options, &includes, ci); |
log_change_level(options.log_level); |
log_change_level(options.log_level); |
log_verbose_reset(); |
log_verbose_reset(); |
for (i = 0; i < options.num_log_verbose; i++) |
for (i = 0; i < options.num_log_verbose; i++) |
log_verbose_add(options.log_verbose[i]); |
log_verbose_add(options.log_verbose[i]); |
process_permitopen(ssh, &options); |
server_process_permitopen(ssh); |
|
|
pw = getpwnam(user); |
pw = getpwnam(user); |
if (pw == NULL) { |
if (pw == NULL) { |
|
|
} |
} |
|
|
/* |
/* |
* 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 based on conflation of hostnames and IP addresses. |
|
*/ |
|
|
|
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) == -1) { |
|
debug("getpeername failed: %.100s", strerror(errno)); |
|
return xstrdup(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 xstrdup(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 xstrdup(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.", name, ntop); |
|
return xstrdup(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.", ntop, name); |
|
return xstrdup(ntop); |
|
} |
|
return xstrdup(name); |
|
} |
|
|
|
/* |
|
* Return the canonical name of the host in the other side of the current |
* 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 |
* connection. The host name is cached, so it is efficient to call this |
* several times. |
* several times. |
|
|
|
|
if (!use_dns) |
if (!use_dns) |
return ssh_remote_ipaddr(ssh); |
return ssh_remote_ipaddr(ssh); |
else if (dnsname != NULL) |
if (dnsname != NULL) |
return dnsname; |
return dnsname; |
else { |
dnsname = ssh_remote_hostname(ssh); |
dnsname = remote_hostname(ssh); |
return dnsname; |
return dnsname; |
|
} |
|
} |
} |
|
|
/* These functions link key/cert options to the auth framework */ |
/* These functions link key/cert options to the auth framework */ |