Most of our users are using captive logins, with a menu program execed by the shell. We needed for these users to be able to use ssh to log in to the server, but not to be able to use ssh to run arbitrary commands on the server. Here is a patch against 1.2.21 which adds two new sshd configuration directives which support this, AllowCommandUsers and DenyCommandUsers. I sent this to the SSH folks. They said they'll try to include something like this in the SSH 2 distribution, but that they won't be putting any new features into the current release. Index: servconf.c Prereq: 1.10 --- servconf.c Thu Aug 21 20:28:34 1997 +++ ../ssh/servconf.c Fri Sep 5 16:30:13 1997 @@ -101,6 +101,8 @@ options->num_deny_hosts = 0; options->num_allow_users = 0; options->num_deny_users = 0; + options->num_allow_cmd_users = 0; + options->num_deny_cmd_users = 0; #ifdef F_SECURE_COMMERCIAL @@ -207,7 +209,7 @@ sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sPidFile, sForcedPasswd, sUmask, sSilentDeny, sIdleTimeout, sUseLogin, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTgtPassing, - sAllowTcpForwarding, sAllowUsers, sDenyUsers, + sAllowTcpForwarding, sAllowUsers, sDenyUsers, sAllowCmdUsers, sDenyCmdUsers, #ifdef F_SECURE_COMMERCIAL @@ -240,6 +242,8 @@ { "denyhosts", sDenyHosts }, { "allowusers", sAllowUsers }, { "denyusers", sDenyUsers }, + { "allowcommandusers", sAllowCmdUsers }, + { "denycommandusers", sDenyCmdUsers }, #ifdef F_SECURE_COMMERCIAL @@ -681,6 +685,35 @@ exit(1); } options->deny_users[options->num_deny_users++] = xstrdup(cp); + } + break; + + case sAllowCmdUsers: + while ((cp = strtok(NULL, WHITESPACE))) + { + if (options->num_allow_cmd_users >= MAX_ALLOW_CMD_USERS) + { + fprintf(stderr, + "%s line %d: too many allow command users.\n", + filename, linenum); + exit(1); + } + options->allow_cmd_users[options->num_allow_cmd_users++] + = xstrdup(cp); + } + break; + + case sDenyCmdUsers: + while ((cp = strtok(NULL, WHITESPACE))) + { + if (options->num_deny_cmd_users >= MAX_DENY_CMD_USERS) + { + fprintf(stderr, "%s line %d: too many deny command users.\n", + filename, linenum); + exit(1); + } + options->deny_cmd_users[options->num_deny_cmd_users++] + = xstrdup(cp); } break; Index: servconf.h Prereq: 1.7 --- servconf.h Thu Aug 21 20:28:34 1997 +++ ../ssh/servconf.h Fri Sep 5 16:32:53 1997 @@ -53,6 +53,8 @@ #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_CMD_USERS 256 /* Max # users on cmd allow list. */ +#define MAX_DENY_CMD_USERS 256 /* Max # users on cmd deny list. */ #ifdef F_SECURE_COMMERCIAL #define MAX_ALLOW_FORWD_TO 256 /* Max # forwardingto on allow list. */ @@ -108,6 +110,10 @@ char *allow_users[MAX_ALLOW_USERS]; unsigned int num_deny_users; char *deny_users[MAX_DENY_USERS]; + unsigned int num_allow_cmd_users; + char *allow_cmd_users[MAX_ALLOW_CMD_USERS]; + unsigned int num_deny_cmd_users; + char *deny_cmd_users[MAX_DENY_CMD_USERS]; #ifdef F_SECURE_COMMERCIAL Index: sshd.8.in Prereq: 1.13 --- sshd.8.in Thu Aug 21 20:28:42 1997 +++ ../ssh/sshd.8.in Fri Sep 5 16:37:51 1997 @@ -279,7 +279,7 @@ .TP .B AllowHosts This keyword can be followed by any number of host name patterns, -separated by spaces. If specified, login is allowed only from hosts +separated by spaces. If specified, access is allowed only from hosts whose name matches one of the patterns. \'*\' and \'?\' can be used as wildcards in the patterns. Normal name servers are used to map the client's host into a canonical host name. If the name cannot be @@ -316,17 +316,29 @@ .TP .B AllowUsers This keyword can be followed by any number of user name patterns, -separated by spaces. If specified, login is allowed only as users whose +separated by spaces. If specified, access is allowed only as users whose name matches one of the patterns. \'*\' and \'?\' can be used as wildcards -in the patterns. By default, logins as all users are allowed. +in the patterns. By default, access as all users are allowed. -Note that the all other login authentication steps must still be +Note that the all other authentication steps must still be sucessfully completed. AllowUsers and DenyUsers are additional restrictions. .TP +.B AllowCommandUsers +This keyword can be followed by any number of user name patterns, +separated by spaces. If specified, command execution (rather than +execution of the user's shell) is allowed only as users whose name +matches one of the patterns. \'*\' and \'?\' can be used as wildcards +in the patterns. By default, command execution as all users are +allowed. + +Note that the all other authentication steps must still be sucessfully +completed. AllowCommandUsers and DenyCommandUsers are additional +restrictions. +.TP .B DenyHosts This keyword can be followed by any number of host name patterns, -separated by spaces. If specified, login is disallowed from the hosts +separated by spaces. If specified, access is disallowed from the hosts whose name matches any of the patterns. .TP .if \n(CO \{ @@ -354,8 +366,14 @@ .TP .B DenyUsers This keyword can be followed by any number of user name patterns, -separated by spaces. If specified, login is disallowed as users +separated by spaces. If specified, access is disallowed as users whose name matches any of the patterns. +.TP +.B DenyCommandUsers +This keyword can be followed by any number of user name patterns, +separated by spaces. If specified, command execution (as opposed to +execution of the user's shell) is disallowed as users whose name matches +any of the patterns. .TP .B FascistLogging Specifies whether to use verbose logging. Verbose logging violates Index: sshd.c Prereq: 1.44 --- sshd.c Thu Aug 21 20:28:37 1997 +++ ../ssh/sshd.c Fri Sep 5 17:40:55 1997 @@ -2508,6 +2508,26 @@ return; case SSH_CMSG_EXEC_CMD: + /* Check that command access is allowed. */ + if (options.num_allow_cmd_users > 0) + { + for (i = 0; i < options.num_allow_cmd_users; i++) + { + if (match_pattern(pw->pw_name, options.allow_cmd_users[i])) + break; + } + if (i >= options.num_allow_cmd_users) + packet_disconnect("Non-login access denied"); + } + if (options.num_deny_cmd_users > 0) + { + for (i = 0; i < options.num_deny_cmd_users; i++) + { + if (match_pattern(pw->pw_name, options.deny_cmd_users[i])) + packet_disconnect("Non-login access denied"); + } + } + /* Set interactive/non-interactive mode. */ packet_set_interactive(have_pty || display != NULL, options.keepalives); -- Roderick Schertler roderick@argon.org