diff options
author | Dave Olson <olson@cumulusnetworks.com> | 2018-04-02 11:01:09 -0700 |
---|---|---|
committer | Dave Olson <olson@cumulusnetworks.com> | 2018-04-02 20:40:02 -0700 |
commit | 1e5742369aedc8708d5dbe4411ffd5bf4b10537a (patch) | |
tree | 2480dc22d6bd3e99084aa85e5679e06b71a33ea0 /nss_mapuid.c | |
parent | 556625e62b692b723cc6809d2374c3da9616dc3d (diff) | |
download | libnss-mapuser-1e5742369aedc8708d5dbe4411ffd5bf4b10537a.tar.gz libnss-mapuser-1e5742369aedc8708d5dbe4411ffd5bf4b10537a.zip |
Add VSA shell:priv-lvl support for privileged radius user logins
Ticket: CM-19457
Reviewed By: roopa
Testing Done: lots of variations of login, su, sudo, automated radius tests
Now we always read the map files. If session is set, we try that
file first, so that a user always sees their name, same as tacplus.
If that's the wrong file, read through all of the map files, look
for the correct match based on either name+session or auid+session,
depending on getpwnam or getpwuid entry point
Ignore same set of users as tacacs, including new radius_priv_user
account for the privileged RADIUS user.
create and delete the mapuser files from libpam-radius-auth now;
we need to have the mapping file written early enough for the pam
interfaces to get the correct info.
Using the pam_script is too limiting, and since we are creating the
database in libpam-radius-auth now, we'll delete it there as well
to keep things symmetric, so delete the script and the references to
the scripts
A significant part of this effort was adding getgrent, getgrgid, and
getgrnam support, so that the radius users are put into the netshow
(unprivileged) and netedit and sudo (privileged) groups at login.
A lot of restructuring went in as part of that, and cleaned up some
longstanding bugs, including return values for the getpw* routines.
Also cleaned up some whitespace issues.
Also renamed some globals (debug, min_uid, init_common()) that might
collide with other programs, so that when I build unstripped and
normal visibility shared libs, they won't collide with programs
calling the functions (saw this with "debug" and bgpd, for example).
Diffstat (limited to 'nss_mapuid.c')
-rw-r--r-- | nss_mapuid.c | 134 |
1 files changed, 5 insertions, 129 deletions
diff --git a/nss_mapuid.c b/nss_mapuid.c index cc6c5ec..acee3f5 100644 --- a/nss_mapuid.c +++ b/nss_mapuid.c @@ -43,119 +43,8 @@ #include "map_common.h" #include <sys/types.h> -#include <fcntl.h> -#include <dirent.h> -#include <ctype.h> static const char *nssname = "nss_mapuid"; /* for syslogs */ -static const char dbdir[] = "/run/mapuser/"; - -/* - * If you aren't using glibc or a variant that supports this, - * and you have a system that supports the BSD getprogname(), - * you can replace this use with getprogname() - */ -extern const char *__progname; - -/* - * Read the requested session file (in the dbdir by intent), verify the - * uid matches, and setup the passwd structure with the username found - * in the file. - */ -static int chk_session_file(char *sfile, uid_t uid, struct pwbuf *pb) -{ - char rbuf[256], user[64]; - FILE *mapf; - uid_t auid = 0; - int ret = 1; - - mapf = fopen(sfile, "r"); - if (!mapf) { - if (debug) - syslog(LOG_DEBUG, - "%s: session map file %s open fails: %m", - nssname, sfile); - return ret; - } - user[0] = '\0'; - while (fgets(rbuf, sizeof rbuf, mapf)) { - strtok(rbuf, " \t\n\r\f"); /* terminate buffer at first whitespace */ - if (!strncmp("user=", rbuf, 5)) { /* should precede auid */ - snprintf(user, sizeof user, "%s", rbuf + 5); - if (auid) /* found out of order, but now have both */ - break; - } else if (!strncmp("auid=", rbuf, 5)) { - uid_t fuid = (uid_t) strtoul(rbuf + 5, NULL, 10); - if (fuid && uid == fuid) { - auid = fuid; - if (user[0]) - break; /* normal ordering, else keep looking for user */ - } - } - } - fclose(mapf); - - if (auid && user[0]) /* otherwise not a match */ - ret = get_pw_mapuser(user, pb); /* should always succeed */ - - return ret; -} - -/* find mapping for this sessionid */ -static int find_mapped_name(struct pwbuf *pb, uid_t uid, uint32_t session) -{ - char sessfile[sizeof dbdir + 11]; - - snprintf(sessfile, sizeof sessfile, "%s%u", dbdir, session); - return chk_session_file(sessfile, uid, pb); -} - -static int find_mappingfile(struct pwbuf *pb, uid_t uid) -{ - DIR *dir; - struct dirent *ent; - int ret = 1; - - dir = opendir(dbdir); - if (!dir) { /* can happen if no mapped users logged in */ - if (debug > 1) - syslog(LOG_DEBUG, - "%s: Unable to open mapping directory %s: %m", - nssname, dbdir); - return 1; - } - - /* Loop through all numeric files in dbdir, check for matching uid */ - while (ret && (ent = readdir(dir))) { - char sessfile[sizeof dbdir + 11]; - if (!isdigit(ent->d_name[0])) /* sanity check on session file */ - continue; - snprintf(sessfile, sizeof sessfile, "%s%s", dbdir, ent->d_name); - ret = chk_session_file(sessfile, uid, pb); - } - if (ret && debug) - syslog(LOG_DEBUG, "%s: uid %u mapping not found in map files", - nssname, uid); - closedir(dir); - return ret; -} - -static uint32_t get_sessionid(void) -{ - int fd = -1, cnt; - uint32_t id = 0U; - static char buf[12]; - - fd = open("/proc/self/sessionid", O_RDONLY); - if (fd != -1) { - cnt = read(fd, buf, sizeof(buf)); - close(fd); - } - if (fd != -1 && cnt > 0) { - id = strtoul(buf, NULL, 0); - } - return id; -} /* * This is an NSS entry point. @@ -189,27 +78,14 @@ enum nss_status _nss_mapuid_getpwuid_r(uid_t uid, struct passwd *pw, enum nss_status status = NSS_STATUS_NOTFOUND; uint32_t session; - /* - * the useradd family will not add/mod/del users correctly with - * the mapuid functionality, so return immediately if we are - * running as part of those processes. - */ - if (__progname && (!strcmp(__progname, "useradd") || - !strcmp(__progname, "usermod") || - !strcmp(__progname, "userdel"))) + if (map_init_common(errnop, nssname)) return status; - /* this can happen for permission reasons, do don't complain except - * at debug */ - if (nss_mapuser_config(errnop, nssname) == 1) { - return status; /* syslog already done */ - } - - if (min_uid != ~0U && uid < min_uid) { - if (debug > 1) + if (map_min_uid != ~0U && uid < map_min_uid) { + if (map_debug > 1) syslog(LOG_DEBUG, - "%s: uid %u < min_uid %u, don't lookup", nssname, - uid, min_uid); + "%s: uid %u < map_min_uid %u, don't lookup", + nssname, uid, map_min_uid); return status; } |