summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>1999-10-11 21:48:30 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>1999-10-11 21:48:30 +0000
commit3ab5aa187caae58d1242f08cf76db8defb374eb2 (patch)
tree79a3a6cd4fec6a596b835c781b3b5035794dd820
parent0461bbc379a16b36969fe1cfc71df132ccdd0861 (diff)
Allow/Deny Users/Groups, from zzlevo@dd.chalmers.se, ok deraadt@
-rw-r--r--usr.bin/ssh/servconf.c65
-rw-r--r--usr.bin/ssh/servconf.h14
-rw-r--r--usr.bin/ssh/sshd.849
-rw-r--r--usr.bin/ssh/sshd.c85
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();