From 1e5742369aedc8708d5dbe4411ffd5bf4b10537a Mon Sep 17 00:00:00 2001 From: Dave Olson Date: Mon, 2 Apr 2018 11:01:09 -0700 Subject: 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). --- debian/libnss-mapuser.postinst | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'debian/libnss-mapuser.postinst') diff --git a/debian/libnss-mapuser.postinst b/debian/libnss-mapuser.postinst index 2e9b04f..ee6a70d 100644 --- a/debian/libnss-mapuser.postinst +++ b/debian/libnss-mapuser.postinst @@ -19,11 +19,19 @@ case "$1" in -e '/^passwd:/s/\s\s*/&mapuid /' \ -e '/^passwd:.*#/s/#.*/ mapname &/' \ -e '/^passwd:[^#]*$/s/$/ mapname &/' \ + -e '/^group:.*#/s/#.*/ mapname &/' \ + -e '/^group:[^#]*$/s/: */& mapname /' \ /etc/nsswitch.conf fi addgroup --quiet $rgroup 2>&1 | grep -v 'already exists' adduser --quiet --firstuid 1000 --disabled-login --ingroup $rgroup \ --gecos "radius user" radius_user 2>&1 | grep -v 'already exists' + adduser --quiet --firstuid 1000 --disabled-login --ingroup $rgroup \ + --gecos "radius privileged user" radius_priv_user 2>&1 | grep -v 'already exists' + # regular radius logins can run net show commands + adduser --quiet radius_user netshow + # privileged radius logins can run net config commands, as well as show + adduser --quiet radius_priv_user netedit exit 0 ) ;; -- cgit v1.2.3 From 4b24261d4a28ed1cd994939d6fa658b44c30a0ac Mon Sep 17 00:00:00 2001 From: Dave Olson Date: Fri, 6 Apr 2018 15:06:27 -0700 Subject: cleanup group mapname in nsswitch on remove; add priv user to sudo group Needed to add sed code to remove mapname from nsswitch.conf group search line, similar to passwd line. Somehow forgot that when I added the code to add it in postinst I also somehow forgot to checkin the adduser line to add the radius_priv_user to the sudo group, so fixed that too. --- debian/changelog | 2 +- debian/libnss-mapuser.postinst | 1 + debian/libnss-mapuser.prerm | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'debian/libnss-mapuser.postinst') diff --git a/debian/changelog b/debian/changelog index d11304d..190d66d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,7 +8,7 @@ libnss-mapuser (1.1.0-cl3u1) RELEASED; urgency=low have radius_user and/or radius_priv_user, to give that that user account more privileges, similar to tacplus client privilege 15. - -- dev-support Tue, 03 Apr 2018 00:13:47 -0700 + -- dev-support Fri, 06 Apr 2018 15:46:56 -0700 libnss-mapuser (1.0.0-cl3u2) RELEASED; urgency=low diff --git a/debian/libnss-mapuser.postinst b/debian/libnss-mapuser.postinst index ee6a70d..13bf0d0 100644 --- a/debian/libnss-mapuser.postinst +++ b/debian/libnss-mapuser.postinst @@ -32,6 +32,7 @@ case "$1" in adduser --quiet radius_user netshow # privileged radius logins can run net config commands, as well as show adduser --quiet radius_priv_user netedit + adduser --quiet radius_priv_user sudo exit 0 ) ;; diff --git a/debian/libnss-mapuser.prerm b/debian/libnss-mapuser.prerm index af98f1b..c4f259f 100644 --- a/debian/libnss-mapuser.prerm +++ b/debian/libnss-mapuser.prerm @@ -8,6 +8,7 @@ if [ "$1" = remove ]; then if [ -e "/etc/nsswitch.conf" ]; then sed -i -e '/^passwd:.*mapuid[ \t]/s/mapuid[ \t]//' \ -e '/^passwd:.*[ \t]mapname/s/[ \t]mapname//' \ + -e '/^group:.*[ \t]mapname/s/[ \t]mapname//' \ /etc/nsswitch.conf || true # don't prevent remove on error fi fi -- cgit v1.2.3 From 613f1949208809a116bd1b3737e39a1599bf7d43 Mon Sep 17 00:00:00 2001 From: Dave Olson Date: Fri, 13 Apr 2018 01:04:39 -0700 Subject: Changes and cleanups around the privileged user. Ticket: CM-19457 Reviewed By: nobody Testing Done: lots of logins, and login combinations Validate that the mapuser database files are valid by using kill 0 on the pids. If not valid, try to unlink, and if we do, report it as a DEBUG. If we can't unlink (not root) report that we are skipping at INFO. As part of that, don't count valid fields and read entire file. Document in man page and config file that the mapped_priv_user account is known to libpam-radius-auth as well, and must be updated in both places if it changes. Updated the public symbols (the getgr additions) from previous commit Fixed some white space and line length issues. --- debian/changelog | 2 +- debian/libnss-mapuser.postinst | 7 ++++-- debian/libnss-mapuser.symbols | 5 ++++ map_common.c | 53 ++++++++++++++++++++++++++++-------------- nss_mapuser.5 | 3 +++ nss_mapuser.conf | 2 ++ 6 files changed, 52 insertions(+), 20 deletions(-) (limited to 'debian/libnss-mapuser.postinst') diff --git a/debian/changelog b/debian/changelog index 190d66d..d0ea75f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,7 +8,7 @@ libnss-mapuser (1.1.0-cl3u1) RELEASED; urgency=low have radius_user and/or radius_priv_user, to give that that user account more privileges, similar to tacplus client privilege 15. - -- dev-support Fri, 06 Apr 2018 15:46:56 -0700 + -- dev-support Fri, 13 Apr 2018 16:19:08 -0700 libnss-mapuser (1.0.0-cl3u2) RELEASED; urgency=low diff --git a/debian/libnss-mapuser.postinst b/debian/libnss-mapuser.postinst index 13bf0d0..54c661b 100644 --- a/debian/libnss-mapuser.postinst +++ b/debian/libnss-mapuser.postinst @@ -24,10 +24,13 @@ case "$1" in /etc/nsswitch.conf fi addgroup --quiet $rgroup 2>&1 | grep -v 'already exists' + ourshell=/bin/bash # not radius_shell, has pkg ordering issues. adduser --quiet --firstuid 1000 --disabled-login --ingroup $rgroup \ - --gecos "radius user" radius_user 2>&1 | grep -v 'already exists' + --gecos "radius user" --shell $ourshell radius_user 2>&1 | + grep -v 'already exists' adduser --quiet --firstuid 1000 --disabled-login --ingroup $rgroup \ - --gecos "radius privileged user" radius_priv_user 2>&1 | grep -v 'already exists' + --gecos "radius privileged user" --shell $ourshell radius_priv_user 2>&1 | + grep -v 'already exists' # regular radius logins can run net show commands adduser --quiet radius_user netshow # privileged radius logins can run net config commands, as well as show diff --git a/debian/libnss-mapuser.symbols b/debian/libnss-mapuser.symbols index 2254c2e..c5a3ed0 100644 --- a/debian/libnss-mapuser.symbols +++ b/debian/libnss-mapuser.symbols @@ -1,4 +1,9 @@ libnss_mapname.so.2 libnss-mapuser #MINVER# + _nss_mapname_setgrent@Base 1.1.0-cl3u1 + _nss_mapname_endgrent@Base 1.1.0-cl3u1 + _nss_mapname_getgrent_r@Base 1.1.0-cl3u1 + _nss_mapname_getgrgid_r@Base 1.1.0-cl3u1 + _nss_mapname_getgrnam_r@Base 1.1.0 _nss_mapname_getpwnam_r@Base 1.0.0 libnss_mapuid.so.2 libnss-mapuser #MINVER# diff --git a/map_common.c b/map_common.c index 830d85a..b6fe3bc 100644 --- a/map_common.c +++ b/map_common.c @@ -26,6 +26,7 @@ #include "map_common.h" #include #include +#include #include #include #include @@ -293,7 +294,7 @@ get_pw_mapuser(const char *name, struct pwbuf *pb, uid_t mapuid, int privileged) for (ret = 1; ret && (ent = fgetpwent(pwfile));) { if (!ent->pw_name) continue; /* shouldn't happen */ - if (!strcmp(ent->pw_name, name) || + if (!strcmp(ent->pw_name, name) || /* added locally */ !strcmp(ent->pw_name, privileged ? mapped_priv_user : mappeduser) || ent->pw_uid == mapuid) { ret = @@ -320,7 +321,6 @@ static int chk_session_file(char *session, uid_t uid, struct pwbuf *pb) FILE *mapf; uid_t auid = 0; int ret = 1, privileged = 0;; - int gotinfo = 0; /* user, session, auid */ snprintf(sessfile, sizeof sessfile, "%s%s", dbdir, session); @@ -333,46 +333,65 @@ static int chk_session_file(char *session, uid_t uid, struct pwbuf *pb) return ret; } user[0] = '\0'; - while (gotinfo != 4 && fgets(rbuf, sizeof rbuf, mapf)) { - strtok(rbuf, " \t\n\r\f"); /* terminate buffer at first whitespace */ + while (fgets(rbuf, sizeof rbuf, mapf)) { + /* terminate buffer at first whitespace */ + strtok(rbuf, " \t\n\r\f"); if (!strncmp("user=", rbuf, 5)) { if (pb->name && strcmp(rbuf + 5, pb->name)) break; snprintf(user, sizeof user, "%s", rbuf + 5); - gotinfo++; + } else if (!strncmp("pid=", rbuf, 4)) { + char *ok; + unsigned pid = (unsigned) strtoul(rbuf + 4, &ok, 10); + if (ok != (rbuf + 4) && pid > 0 && kill(pid, 0) && + errno == ESRCH) { + /* ESRCH instead of any error because perms as + * non-root. Try to unlink, since we often + * run as root; report as DEBUG if we unlink, + * report as INFO if not */ + if (unlink(sessfile) == 0) + syslog(LOG_DEBUG, "session file %s" + " PID=%u no longer active," + " removed", sessfile, pid); + else + syslog(LOG_INFO, "session file %s" + " PID=%u no longer active, skip", + sessfile, pid); + auid = 0; /* force fail */ + break; + } } else if (!strncmp("auid=", rbuf, 5)) { char *ok; uid_t fuid = (uid_t) strtoul(rbuf + 5, &ok, 10); if (ok != (rbuf + 5)) { - gotinfo++; if (uid != -1 && fuid != uid) { - auid = fuid; - break; /* getpwuid, but uid/auid mismatch, nogo */ + /* getpwuid call but mismatch, nogo */ + break; } else auid = fuid; } } else if (!strcasecmp("privileged=yes", rbuf)) { privileged = 1; - gotinfo++; - } else if (!strcasecmp("privileged=no", rbuf)) - gotinfo++; - else if (!strncmp("session=", rbuf, 8)) { + } else if (!strcasecmp("privileged=no", rbuf)) { + privileged = 0; + } else if (!strncmp("session=", rbuf, 8)) { /* structural problem, so log warning */ if (strcmp(session, rbuf + 8)) { syslog(LOG_WARNING, - "%s: session field \"%s\" mismatch in %s", + "%s: session \"%s\" mismatch in %s", libname, rbuf, sessfile); - } else - gotinfo++; + auid = 0; /* force a skip */ + } } } fclose(mapf); - if (auid && user[0]) { /* otherwise not a match */ + if (auid && (uid == (uid_t)-1 || auid == uid) && user[0]) { if (!pb->name) pb->name = user; /* uid lookups */ ret = get_pw_mapuser(user, pb, auid, privileged); } + /* otherwise not a match */ return ret; } @@ -429,7 +448,7 @@ int find_mappingfile(struct pwbuf *pb, uid_t uid) int make_mapuser(struct pwbuf *pb, const char *name) { int ret; - ret = get_pw_mapuser(mappeduser, pb, (uid_t) - 1, 0); + ret = get_pw_mapuser(mappeduser, pb, (uid_t)-1, 0); return ret; } diff --git a/nss_mapuser.5 b/nss_mapuser.5 index 6e63138..92aff16 100644 --- a/nss_mapuser.5 +++ b/nss_mapuser.5 @@ -45,6 +45,9 @@ When a uid or name match is found, this account information is read from .I /etc/passwd and used as a template for the matching account. The default at installation is .BR radius_priv_user . +It must match the privileged account name in +.IR pam_radius_auth (5) +for correct operation. .TP .I mapped_user=NAME This is the local account used as a template for unprivileged logins diff --git a/nss_mapuser.conf b/nss_mapuser.conf index c5f2098..1ed70d1 100644 --- a/nss_mapuser.conf +++ b/nss_mapuser.conf @@ -35,4 +35,6 @@ exclude_users=root,daemon,nobody,cron,sshd,cumulus,quagga,frr,snmp,www-data,ntp, # Map all usernames to the radius_user account (use the uid, gid, shell, and # base of the home directory from the cumulus entry in /etc/passwd). mapped_user=radius_user +# if you change the account for mapped_priv_user, you must change it in +# /etc/pam_radius_auth.conf as well. mapped_priv_user=radius_priv_user -- cgit v1.2.3