version 1.28, 2001/10/03 10:01:20 |
version 1.28.2.5, 2002/10/11 14:53:06 |
|
|
#include "bufaux.h" |
#include "bufaux.h" |
#include "uidswap.h" |
#include "uidswap.h" |
#include "tildexpand.h" |
#include "tildexpand.h" |
|
#include "misc.h" |
|
#include "bufaux.h" |
|
#include "packet.h" |
|
|
/* import */ |
/* import */ |
extern ServerOptions options; |
extern ServerOptions options; |
|
|
|
/* Debugging messages */ |
|
Buffer auth_debug; |
|
int auth_debug_init; |
|
|
/* |
/* |
* Check if the user is allowed to log in via ssh. If user is listed |
* Check if the user is allowed to log in via ssh. If user is listed |
* in DenyUsers or one of user's groups is listed in DenyGroups, false |
* in DenyUsers or one of user's groups is listed in DenyGroups, false |
|
|
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; |
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; |
|
|
/* deny if shell does not exists or is not executable */ |
/* deny if shell does not exists or is not executable */ |
if (stat(shell, &st) != 0) |
if (stat(shell, &st) != 0) { |
|
log("User %.100s not allowed because shell %.100s does not exist", |
|
pw->pw_name, shell); |
return 0; |
return 0; |
if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)))) |
} |
|
if (S_ISREG(st.st_mode) == 0 || |
|
(st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) { |
|
log("User %.100s not allowed because shell %.100s is not executable", |
|
pw->pw_name, shell); |
return 0; |
return 0; |
|
} |
|
|
if (options.num_deny_users > 0 || options.num_allow_users > 0) { |
if (options.num_deny_users > 0 || options.num_allow_users > 0) { |
hostname = get_canonical_hostname(options.reverse_mapping_check); |
hostname = get_canonical_hostname(options.verify_reverse_mapping); |
ipaddr = get_remote_ipaddr(); |
ipaddr = get_remote_ipaddr(); |
} |
} |
|
|
|
|
if (options.num_deny_users > 0) { |
if (options.num_deny_users > 0) { |
for (i = 0; i < options.num_deny_users; i++) |
for (i = 0; i < options.num_deny_users; i++) |
if (match_user(pw->pw_name, hostname, ipaddr, |
if (match_user(pw->pw_name, hostname, ipaddr, |
options.deny_users[i])) |
options.deny_users[i])) { |
|
log("User %.100s not allowed because listed in DenyUsers", |
|
pw->pw_name); |
return 0; |
return 0; |
|
} |
} |
} |
/* Return false if AllowUsers isn't empty and user isn't listed there */ |
/* Return false if AllowUsers isn't empty and user isn't listed there */ |
if (options.num_allow_users > 0) { |
if (options.num_allow_users > 0) { |
|
|
options.allow_users[i])) |
options.allow_users[i])) |
break; |
break; |
/* i < options.num_allow_users iff we break for loop */ |
/* i < options.num_allow_users iff we break for loop */ |
if (i >= options.num_allow_users) |
if (i >= options.num_allow_users) { |
|
log("User %.100s not allowed because not listed in AllowUsers", |
|
pw->pw_name); |
return 0; |
return 0; |
|
} |
} |
} |
if (options.num_deny_groups > 0 || options.num_allow_groups > 0) { |
if (options.num_deny_groups > 0 || options.num_allow_groups > 0) { |
/* Get the user's group access list (primary and supplementary) */ |
/* Get the user's group access list (primary and supplementary) */ |
if (ga_init(pw->pw_name, pw->pw_gid) == 0) |
if (ga_init(pw->pw_name, pw->pw_gid) == 0) { |
|
log("User %.100s not allowed because not in any group", |
|
pw->pw_name); |
return 0; |
return 0; |
|
} |
|
|
/* Return false if one of user's groups is listed in DenyGroups */ |
/* Return false if one of user's groups is listed in DenyGroups */ |
if (options.num_deny_groups > 0) |
if (options.num_deny_groups > 0) |
if (ga_match(options.deny_groups, |
if (ga_match(options.deny_groups, |
options.num_deny_groups)) { |
options.num_deny_groups)) { |
ga_free(); |
ga_free(); |
|
log("User %.100s not allowed because a group is listed in DenyGroups", |
|
pw->pw_name); |
return 0; |
return 0; |
} |
} |
/* |
/* |
|
|
if (!ga_match(options.allow_groups, |
if (!ga_match(options.allow_groups, |
options.num_allow_groups)) { |
options.num_allow_groups)) { |
ga_free(); |
ga_free(); |
|
log("User %.100s not allowed because none of user's groups are listed in AllowGroups", |
|
pw->pw_name); |
return 0; |
return 0; |
} |
} |
ga_free(); |
ga_free(); |
|
|
authmsg, |
authmsg, |
method, |
method, |
authctxt->valid ? "" : "illegal user ", |
authctxt->valid ? "" : "illegal user ", |
authctxt->valid && authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user, |
authctxt->user, |
get_remote_ipaddr(), |
get_remote_ipaddr(), |
get_remote_port(), |
get_remote_port(), |
info); |
info); |
|
|
} |
} |
if (cp[0] == '%' && cp[1] == 'u') { |
if (cp[0] == '%' && cp[1] == 'u') { |
buffer_append(&buffer, pw->pw_name, |
buffer_append(&buffer, pw->pw_name, |
strlen(pw->pw_name)); |
strlen(pw->pw_name)); |
cp++; |
cp++; |
continue; |
continue; |
} |
} |
|
|
Key *found; |
Key *found; |
char *user_hostfile; |
char *user_hostfile; |
struct stat st; |
struct stat st; |
int host_status; |
HostStatus host_status; |
|
|
/* Check if we know the host and its host key. */ |
/* Check if we know the host and its host key. */ |
found = key_new(key->type); |
found = key_new(key->type); |
|
|
if (options.strict_modes && |
if (options.strict_modes && |
(stat(user_hostfile, &st) == 0) && |
(stat(user_hostfile, &st) == 0) && |
((st.st_uid != 0 && st.st_uid != pw->pw_uid) || |
((st.st_uid != 0 && st.st_uid != pw->pw_uid) || |
(st.st_mode & 022) != 0)) { |
(st.st_mode & 022) != 0)) { |
log("Authentication refused for %.100s: " |
log("Authentication refused for %.100s: " |
"bad owner or modes for %.200s", |
"bad owner or modes for %.200s", |
pw->pw_name, user_hostfile); |
pw->pw_name, user_hostfile); |
|
|
|
|
/* |
/* |
* Check a given file for security. This is defined as all components |
* Check a given file for security. This is defined as all components |
* of the path to the file must either be owned by either the owner of |
* of the path to the file must be owned by either the owner of |
* of the file or root and no directories must be group or world writable. |
* of the file or root and no directories must be group or world writable. |
* |
* |
* XXX Should any specific check be done for sym links ? |
* XXX Should any specific check be done for sym links ? |
|
|
if (stat(buf, &st) < 0 || |
if (stat(buf, &st) < 0 || |
(st.st_uid != 0 && st.st_uid != uid) || |
(st.st_uid != 0 && st.st_uid != uid) || |
(st.st_mode & 022) != 0) { |
(st.st_mode & 022) != 0) { |
snprintf(err, errlen, |
snprintf(err, errlen, |
"bad ownership or modes for directory %s", buf); |
"bad ownership or modes for directory %s", buf); |
return -1; |
return -1; |
} |
} |
|
|
break; |
break; |
} |
} |
return 0; |
return 0; |
|
} |
|
|
|
struct passwd * |
|
getpwnamallow(const char *user) |
|
{ |
|
#ifdef HAVE_LOGIN_CAP |
|
extern login_cap_t *lc; |
|
#ifdef BSD_AUTH |
|
auth_session_t *as; |
|
#endif |
|
#endif |
|
struct passwd *pw; |
|
|
|
pw = getpwnam(user); |
|
if (pw == NULL) { |
|
log("Illegal user %.100s from %.100s", |
|
user, get_remote_ipaddr()); |
|
return (NULL); |
|
} |
|
if (!allowed_user(pw)) |
|
return (NULL); |
|
#ifdef HAVE_LOGIN_CAP |
|
if ((lc = login_getclass(pw->pw_class)) == NULL) { |
|
debug("unable to get login class: %s", user); |
|
return (NULL); |
|
} |
|
#ifdef BSD_AUTH |
|
if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 || |
|
auth_approval(as, lc, pw->pw_name, "ssh") <= 0) { |
|
debug("Approval failure for %s", user); |
|
pw = NULL; |
|
} |
|
if (as != NULL) |
|
auth_close(as); |
|
#endif |
|
#endif |
|
if (pw != NULL) |
|
return (pwcopy(pw)); |
|
return (NULL); |
|
} |
|
|
|
void |
|
auth_debug_add(const char *fmt,...) |
|
{ |
|
char buf[1024]; |
|
va_list args; |
|
|
|
if (!auth_debug_init) |
|
return; |
|
|
|
va_start(args, fmt); |
|
vsnprintf(buf, sizeof(buf), fmt, args); |
|
va_end(args); |
|
buffer_put_cstring(&auth_debug, buf); |
|
} |
|
|
|
void |
|
auth_debug_send(void) |
|
{ |
|
char *msg; |
|
|
|
if (!auth_debug_init) |
|
return; |
|
while (buffer_len(&auth_debug)) { |
|
msg = buffer_get_string(&auth_debug, NULL); |
|
packet_send_debug("%s", msg); |
|
xfree(msg); |
|
} |
|
} |
|
|
|
void |
|
auth_debug_reset(void) |
|
{ |
|
if (auth_debug_init) |
|
buffer_clear(&auth_debug); |
|
else { |
|
buffer_init(&auth_debug); |
|
auth_debug_init = 1; |
|
} |
} |
} |