Dave Wright
2007-Nov-02 23:18 UTC
[Patch, enh] Permit host and IP addresses in (Allow|Deny)Groups
Hi, I ran across a case in which my server maintenance was simplified by using SSHD configuration options like this in sshd_config: AllowGroups admin at 192.168.0.* sshuser in much the same fashion as (Allow|Deny)Users. In this case, the goal is to provide access to administrators only from the local network, while allowing SSH users to login from anywhere. This (IMHO) simplifies access management by leveraging group membership more effectively. Anyway, I've attached a patch in case anyone feels it's useful enough to put into a future release. -- Dave Wright -------------- diff -r -u -N openssh-4.7p1/auth.c osshGroupHostIP-4.7p1/auth.c --- openssh-4.7p1/auth.c 2007-03-26 09:35:28.000000000 -0700 +++ osshGroupHostIP-4.7p1/auth.c 2007-11-02 14:52:58.000000000 -0700 @@ -210,8 +210,13 @@ /* Return false if one of user's groups is listed in DenyGroups */ if (options.num_deny_groups > 0) +#ifndef GROUP_MATCH_HOST_AND_IP if (ga_match(options.deny_groups, options.num_deny_groups)) { +#else /* GROUP_MATCH_HOST_AND_IP */ + if (ga_match_host_and_ip(options.deny_groups, + options.num_deny_groups, hostname, ipaddr)) { +#endif /* GROUP_MATCH_HOST_AND_IP */ ga_free(); logit("User %.100s from %.100s not allowed " "because a group is listed in DenyGroups", @@ -223,8 +228,13 @@ * isn't listed there */ if (options.num_allow_groups > 0) +#ifndef GROUP_MATCH_HOST_AND_IP if (!ga_match(options.allow_groups, options.num_allow_groups)) { +#else /* GROUP_MATCH_HOST_AND_IP */ + if (!ga_match_host_and_ip(options.allow_groups, + options.num_allow_groups, hostname, ipaddr)) { +#endif /* GROUP_MATCH_HOST_AND_IP */ ga_free(); logit("User %.100s from %.100s not allowed " "because none of user's groups are listed " diff -r -u -N openssh-4.7p1/groupaccess.c osshGroupHostIP-4.7p1/groupaccess.c --- openssh-4.7p1/groupaccess.c 2006-08-04 19:39:40.000000000 -0700 +++ osshGroupHostIP-4.7p1/groupaccess.c 2007-11-02 14:46:08.000000000 -0700 @@ -37,6 +37,10 @@ #include "match.h" #include "log.h" +#ifdef GROUP_MATCH_HOST_AND_IP +#include <string.h> +#endif /* GROUP_MATCH_HOST_AND_IP */ + static int ngroups; static char **groups_byname; @@ -86,6 +90,40 @@ return 1; return 0; } +#ifdef GROUP_MATCH_HOST_AND_IP + +/* + * Permit the 'user at host' configuration file syntax (AllowUsers, ...) + * to be used for 'group at host' as well. (AllowGroups, ...). + * + * Return 1 if one of user's groups is matched by a group pattern AND + * (access allowed from anywhere OR access is from allowed host / network). + * Return 0 otherwise. + */ +int +ga_match_host_and_ip(char * const *patterns, int npatterns, + const char *hostname, const char *ipaddr) +{ + char *host_pattern; + char *name_pattern; + int found; + int i, j; + + found = 0; + for (i = 0; !found && i < npatterns; i++) { + name_pattern = xstrdup(patterns[i]); + host_pattern = strchr(name_pattern, '@'); + if (host_pattern) + *host_pattern++ = '\0'; + for (j = 0; !found && j < ngroups; j++) + if (match_pattern(groups_byname[j], name_pattern)) + found = !host_pattern || + match_host_and_ip(hostname, ipaddr, host_pattern); + xfree(name_pattern); + } + return found; +} +#endif /* GROUP_MATCH_HOST_AND_IP */ /* * Free memory allocated for group access list. diff -r -u -N openssh-4.7p1/groupaccess.h osshGroupHostIP-4.7p1/groupaccess.h --- openssh-4.7p1/groupaccess.h 2006-08-04 19:39:40.000000000 -0700 +++ osshGroupHostIP-4.7p1/groupaccess.h 2007-11-02 14:46:08.000000000 -0700 @@ -27,8 +27,15 @@ #ifndef GROUPACCESS_H #define GROUPACCESS_H +/* Permit group at host style {Allow|Deny}Groups directive. */ +#define GROUP_MATCH_HOST_AND_IP + int ga_init(const char *, gid_t); int ga_match(char * const *, int); void ga_free(void); +#ifdef GROUP_MATCH_HOST_AND_IP +int ga_match_host_and_ip(char * const *, int, const char *, const char *); +#endif /* GROUP_MATCH_HOST_AND_IP */ + #endif