diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 1999-10-11 21:48:30 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 1999-10-11 21:48:30 +0000 |
commit | 3ab5aa187caae58d1242f08cf76db8defb374eb2 (patch) | |
tree | 79a3a6cd4fec6a596b835c781b3b5035794dd820 /usr.bin/ssh | |
parent | 0461bbc379a16b36969fe1cfc71df132ccdd0861 (diff) |
Allow/Deny Users/Groups, from zzlevo@dd.chalmers.se, ok deraadt@
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r-- | usr.bin/ssh/servconf.c | 65 | ||||
-rw-r--r-- | usr.bin/ssh/servconf.h | 14 | ||||
-rw-r--r-- | usr.bin/ssh/sshd.8 | 49 | ||||
-rw-r--r-- | usr.bin/ssh/sshd.c | 85 |
4 files changed, 206 insertions, 7 deletions
diff --git a/usr.bin/ssh/servconf.c b/usr.bin/ssh/servconf.c index 6fddc363159..7bcf12cf870 100644 --- a/usr.bin/ssh/servconf.c +++ b/usr.bin/ssh/servconf.c @@ -12,7 +12,7 @@ Created: Mon Aug 21 15:48:58 1995 ylo */ #include "includes.h" -RCSID("$Id: servconf.c,v 1.12 1999/10/11 21:07:37 markus Exp $"); +RCSID("$Id: servconf.c,v 1.13 1999/10/11 21:48:29 markus Exp $"); #include "ssh.h" #include "servconf.h" @@ -60,6 +60,10 @@ void initialize_server_options(ServerOptions *options) options->use_login = -1; options->num_allow_hosts = 0; options->num_deny_hosts = 0; + options->num_allow_users = 0; + options->num_deny_users = 0; + options->num_allow_groups = 0; + options->num_deny_groups = 0; } void fill_default_server_options(ServerOptions *options) @@ -157,7 +161,8 @@ typedef enum sPasswordAuthentication, sAllowHosts, sDenyHosts, sListenAddress, sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset, sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail, - sUseLogin + sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups + } ServerOpCodes; /* Textual representation of the tokens. */ @@ -205,6 +210,10 @@ static struct { "uselogin", sUseLogin }, { "randomseed", sRandomSeedFile }, { "keepalive", sKeepAlives }, + { "allowusers", sAllowUsers }, + { "denyusers", sDenyUsers }, + { "allowgroups", sAllowGroups }, + { "denygroups", sDenyGroups }, { NULL, 0 } }; @@ -499,6 +508,58 @@ void read_server_config(ServerOptions *options, const char *filename) } break; + case sAllowUsers: + while ((cp = strtok(NULL, WHITESPACE))) + { + if (options->num_allow_users >= MAX_ALLOW_USERS) + { + fprintf(stderr, "%s line %d: too many allow users.\n", + filename, linenum); + exit(1); + } + options->allow_users[options->num_allow_users++] = xstrdup(cp); + } + break; + + case sDenyUsers: + while ((cp = strtok(NULL, WHITESPACE))) + { + if (options->num_deny_users >= MAX_DENY_USERS) + { + fprintf(stderr, "%s line %d: too many deny users.\n", + filename, linenum); + exit(1); + } + options->deny_users[options->num_deny_users++] = xstrdup(cp); + } + break; + + case sAllowGroups: + while ((cp = strtok(NULL, WHITESPACE))) + { + if (options->num_allow_groups >= MAX_ALLOW_GROUPS) + { + fprintf(stderr, "%s line %d: too many allow groups.\n", + filename, linenum); + exit(1); + } + options->allow_groups[options->num_allow_groups++] = xstrdup(cp); + } + break; + + case sDenyGroups: + while ((cp = strtok(NULL, WHITESPACE))) + { + if (options->num_deny_groups >= MAX_DENY_GROUPS) + { + fprintf(stderr, "%s line %d: too many deny groups.\n", + filename, linenum); + exit(1); + } + options->deny_groups[options->num_deny_groups++] = xstrdup(cp); + } + break; + default: fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n", filename, linenum, cp, opcode); diff --git a/usr.bin/ssh/servconf.h b/usr.bin/ssh/servconf.h index 57f673132c0..7a30201a68f 100644 --- a/usr.bin/ssh/servconf.h +++ b/usr.bin/ssh/servconf.h @@ -13,13 +13,17 @@ Definitions for server configuration data and for the functions reading it. */ -/* RCSID("$Id: servconf.h,v 1.7 1999/10/11 21:07:37 markus Exp $"); */ +/* RCSID("$Id: servconf.h,v 1.8 1999/10/11 21:48:29 markus Exp $"); */ #ifndef SERVCONF_H #define SERVCONF_H #define MAX_ALLOW_HOSTS 256 /* Max # hosts on allow list. */ #define MAX_DENY_HOSTS 256 /* Max # hosts on deny list. */ +#define MAX_ALLOW_USERS 256 /* Max # users on allow list. */ +#define MAX_DENY_USERS 256 /* Max # users on deny list. */ +#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */ +#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */ typedef struct { @@ -64,6 +68,14 @@ typedef struct char *allow_hosts[MAX_ALLOW_HOSTS]; unsigned int num_deny_hosts; char *deny_hosts[MAX_DENY_HOSTS]; + unsigned int num_allow_users; + char *allow_users[MAX_ALLOW_USERS]; + unsigned int num_deny_users; + char *deny_users[MAX_DENY_USERS]; + unsigned int num_allow_groups; + char *allow_groups[MAX_ALLOW_GROUPS]; + unsigned int num_deny_groups; + char *deny_groups[MAX_DENY_GROUPS]; } ServerOptions; /* Initializes the server options to special values that indicate that they diff --git a/usr.bin/ssh/sshd.8 b/usr.bin/ssh/sshd.8 index 3d80c164535..45a028aff9a 100644 --- a/usr.bin/ssh/sshd.8 +++ b/usr.bin/ssh/sshd.8 @@ -9,7 +9,7 @@ .\" .\" Created: Sat Apr 22 21:55:14 1995 ylo .\" -.\" $Id: sshd.8,v 1.10 1999/10/11 21:07:37 markus Exp $ +.\" $Id: sshd.8,v 1.11 1999/10/11 21:48:29 markus Exp $ .\" .Dd September 25, 1999 .Dt SSHD 8 @@ -173,6 +173,17 @@ The following keywords are possible. .It Cm AFSTokenPassing Specifies whether an AFS token may be forwarded to the server. Default is .Dq yes . +.It Cm AllowGroups +This keyword can be followed by a number of group names, separated +by spaces. If specified, login is allowed only for users whose primary +group matches one of the patterns. +.Ql \&* +and +.Ql ? +can be used as +wildcards in the patterns. Only group names are valid, a numerical group +id isn't recognized. By default login is allowed regardless of +the primary group. .Pp .It Cm AllowHosts This keyword can be followed by any number of host name patterns, @@ -192,16 +203,52 @@ Note that can also be configured to use tcp_wrappers using the .Sy LIBWARP compile-time option. +.It Cm AllowUsers +This keyword can be followed by a number of user names, separated +by spaces. If specified, login is allowed only for users names that +match one of the patterns. +.Ql \&* +and +.Ql ? +can be used as +wildcards in the patterns. Only user names are valid, a numerical user +id isn't recognized. By default login is allowed regardless of +the user name. +.Pp .It Cm CheckMail Specifies whether .Nm should check for new mail for interactive logins. The default is .Dq no . +.It Cm DenyGroups +This keyword can be followed by a number of group names, separated +by spaces. Users whose primary group matches one of the patterns +aren't allowed to log in. +.Ql \&* +and +.Ql ? +can be used as +wildcards in the patterns. Only group names are valid, a numerical group +id isn't recognized. By default login is allowed regardless of +the primary group. +.Pp .It Cm DenyHosts This keyword can be followed by any number of host name patterns, separated by spaces. If specified, login is disallowed from the hosts whose name matches any of the patterns. +.It Cm DenyUsers +This keyword can be followed by a number of user names, separated +by spaces. Login is allowed disallowed for user names that match +one of the patterns. +.Ql \&* +and +.Ql ? +can be used as +wildcards in the patterns. Only user names are valid, a numerical user +id isn't recognized. By default login is allowed regardless of +the user name. +.Pp .It Cm FascistLogging Specifies whether to use verbose logging. Verbose logging violates the privacy of users and is not recommended. The argument must be diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c index 93c0462b17d..bd76da711a6 100644 --- a/usr.bin/ssh/sshd.c +++ b/usr.bin/ssh/sshd.c @@ -18,7 +18,7 @@ agent connections. */ #include "includes.h" -RCSID("$Id: sshd.c,v 1.27 1999/10/11 21:07:37 markus Exp $"); +RCSID("$Id: sshd.c,v 1.28 1999/10/11 21:48:29 markus Exp $"); #include "xmalloc.h" #include "rsa.h" @@ -934,6 +934,84 @@ void do_connection(int privileged_port) do_authentication(user, privileged_port); } +/* Check if the user is allowed to log in via ssh. If user is listed in + DenyUsers or user's primary group is listed in DenyGroups, false will + be returned. If AllowUsers isn't empty and user isn't listed there, or + if AllowGroups isn't empty and user isn't listed there, false will be + returned. Otherwise true is returned. + XXX This function should also check if user has a valid shell */ + +static int +allowed_user(struct passwd *pw) +{ + struct group *grp; + int i; + + /* Shouldn't be called if pw is NULL, but better safe than sorry... */ + if (!pw) + return 0; + + /* XXX Should check for valid login shell */ + + /* Return false if user is listed in DenyUsers */ + if (options.num_deny_users > 0) + { + if (!pw->pw_name) + return 0; + for (i = 0; i < options.num_deny_users; i++) + if (match_pattern(pw->pw_name, options.deny_users[i])) + return 0; + } + + /* Return false if AllowUsers isn't empty and user isn't listed there */ + if (options.num_allow_users > 0) + { + if (!pw->pw_name) + return 0; + for (i = 0; i < options.num_allow_users; i++) + if (match_pattern(pw->pw_name, options.allow_users[i])) + break; + /* i < options.num_allow_users iff we break for loop */ + if (i >= options.num_allow_users) + return 0; + } + + /* Get the primary group name if we need it. Return false if it fails */ + if (options.num_deny_groups > 0 || options.num_allow_groups > 0 ) + { + grp = getgrgid(pw->pw_gid); + if (!grp) + return 0; + + /* Return false if user's group is listed in DenyGroups */ + if (options.num_deny_groups > 0) + { + if (!grp->gr_name) + return 0; + for (i = 0; i < options.num_deny_groups; i++) + if (match_pattern(grp->gr_name, options.deny_groups[i])) + return 0; + } + + /* Return false if AllowGroups isn't empty and user's group isn't + listed there */ + if (options.num_allow_groups > 0) + { + if (!grp->gr_name) + return 0; + for (i = 0; i < options.num_allow_groups; i++) + if (match_pattern(grp->gr_name, options.allow_groups[i])) + break; + /* i < options.num_allow_groups iff we break for loop */ + if (i >= options.num_allow_groups) + return 0; + } + } + + /* We found no reason not to let this user try to log on... */ + return 1; +} + /* 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 @@ -963,9 +1041,10 @@ do_authentication(char *user, int privileged_port) /* Verify that the user is a valid user. */ pw = getpwnam(user); - if (!pw) + if (!pw || !allowed_user(pw)) { - /* The user does not exist. */ + /* The user does not exist or access is denied, + but fake indication that authentication is needed. */ packet_start(SSH_SMSG_FAILURE); packet_send(); packet_write_wait(); |