diff options
author | Remi Ferrand <remi.ferrand@cc.in2p3.fr> | 2014-03-31 15:18:54 +0200 |
---|---|---|
committer | Russ Allbery <rra@stanford.edu> | 2014-06-16 10:56:13 -0700 |
commit | f92a381dbdaf753a90235a9f1e33b193a752c1c4 (patch) | |
tree | 8a3f52c0c471d2a08baad2811513adbb8a203dc0 /server | |
parent | b6b2009aa32869a2a988ba458b45b044264cfd78 (diff) |
Add ACL scheme for checking that user belongs to nss group
* Add documentation for *unxgrp* ACL scheme
* Add *unxgrp* in supported ACL scheme in usage message
* Add test suite for acl-unxgrp
Change-Id: I7ed3008953e7751c02d81323e3c08cc9dddb9e49
Reviewed-on: https://gerrit.stanford.edu/1492
Reviewed-by: Russ Allbery <rra@stanford.edu>
Tested-by: Russ Allbery <rra@stanford.edu>
Diffstat (limited to 'server')
-rw-r--r-- | server/config.c | 83 | ||||
-rw-r--r-- | server/remctld.c | 3 |
2 files changed, 86 insertions, 0 deletions
diff --git a/server/config.c b/server/config.c index f6d7608..85bd795 100644 --- a/server/config.c +++ b/server/config.c @@ -27,6 +27,11 @@ # include <regex.h> #endif #include <sys/stat.h> +#ifdef HAVE_GETGRNAM_R +# include <sys/types.h> +# include <grp.h> +# include <unistd.h> +#endif #include <server/internal.h> #include <util/macros.h> @@ -885,6 +890,79 @@ acl_check_regex(const char *user, const char *data, const char *file, } #endif /* HAVE_REGCOMP */ +#ifdef HAVE_GETGRNAM_R +static enum config_status +acl_check_unxgrp (const char *user, const char *data, const char *file, + int lineno) +{ + struct group grp; + struct group *tempgrp = NULL; + int status = -1; + enum config_status result = CONFIG_ERROR; + long buf_len = -1; + char *buf = NULL; + size_t buf_sz = 1024; + + memset(&grp, 0x0, sizeof(grp)); + + buf_len = sysconf(_SC_GETGR_R_SIZE_MAX); + if (buf_len > 0) { + buf_sz = (size_t) buf_sz; + } + + buf = (char *) xmalloc(sizeof(char) * buf_sz); + memset(buf, 0x0, buf_sz); + + do { + status = getgrnam_r(data, &grp, buf, buf_sz, &tempgrp); + if (status != 0 && status != EINTR) { + warn("%s:%d: resolving unix group '%s' failed with status %d", file, + lineno, data, status); + result = CONFIG_ERROR; + goto die; + } + } while (status == EINTR); + + /* No group matching */ + if (tempgrp == NULL) { + result = CONFIG_NOMATCH; + } + else { + /* Sanitize and search for match in group members */ + char *cur_member = grp.gr_mem[0]; + char *p_user = user; + int i = 0; + char *sanitized_user = NULL; + + /* Sanitize username, remove instances and REALM */ + sanitized_user = xmalloc(sizeof(char)* strlen(user)); + memset(sanitized_user, 0x0, strlen(user)); + + while (p_user != NULL && *p_user != '\0') { + if (*p_user == '\x40' || *p_user == '\x2F') + break; + sanitized_user[i++] = *p_user; + p_user += 1; + } + + /* Check if sanitized user is within group members */ + i = 0; + while (cur_member != NULL && *cur_member != '\0') { + if (strcmp(cur_member, sanitized_user) == 0) { + result = CONFIG_SUCCESS; + goto die; + } + cur_member = grp.gr_mem[++i]; + } + + result = CONFIG_NOMATCH; + } + +die: + return result; +} +#endif /* HAVE_GETGRNAM_R */ + /* * The table relating ACL scheme names to functions. The first two ACL * schemes must remain in their current slots or the index constants set at @@ -909,6 +987,11 @@ static const struct acl_scheme schemes[] = { #else { "regex", NULL }, #endif +#ifdef HAVE_GETGRNAM_R + { "unxgrp", acl_check_unxgrp }, +#else + { "unxgrp", NULL }, +#endif { NULL, NULL } }; diff --git a/server/remctld.c b/server/remctld.c index 2fde503..3209b1e 100644 --- a/server/remctld.c +++ b/server/remctld.c @@ -107,6 +107,9 @@ usage(int status) #ifdef HAVE_REGCOMP fprintf(output, ", regex"); #endif +#ifdef HAVE_GETGRNAM_R + fprintf(output, ", unxgrp"); +#endif fprintf(output, "\n"); exit(status); } |