diff options
author | Dave Olson <olson@cumulusnetworks.com> | 2017-03-23 22:42:24 -0700 |
---|---|---|
committer | Dave Olson <olson@cumulusnetworks.com> | 2017-05-23 17:05:52 -0700 |
commit | 9b056a2a66ec7006d86121509ef1049c7f6f0725 (patch) | |
tree | 7064198f039e24912c0fa573c12174861eb476b3 | |
parent | 1e79d33bc397c0a9f30512a624ce51153e981f89 (diff) | |
download | libnss-tacplus-9b056a2a66ec7006d86121509ef1049c7f6f0725.tar.gz libnss-tacplus-9b056a2a66ec7006d86121509ef1049c7f6f0725.zip |
Support using and returning per-tacacs user homedir
Get setting from map on whether login was set up to use per-tacacs
user homedir, rather than the homedir from the local tacacsN users.
The mkhomedir_helper program is used in pam_tacplus to create home
directory (like pam_mkhomedir.so) when user homedir is requested, but
the home directory does not exist.
The config file setting in this code is not used when using map and the user
is found in map; we then use the setting from the map.
When mapping doesn't exist, then use our own config setting.
user_homedirs is ignored if shell is a restricted shell (as set up by
tacplus-restrict) because we need to honor the per-command
authorization setup in that case.
Updated changelog
Also fixed up the spelling of dev-support
-rw-r--r-- | debian/changelog | 12 | ||||
-rw-r--r-- | nss_tacplus.c | 65 |
2 files changed, 58 insertions, 19 deletions
diff --git a/debian/changelog b/debian/changelog index cf33b24..6b20592 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,7 @@ libnss-tacplus (1.0.3-1) unstable; urgency=low - * added config variable "timeout" to limit time attempting to - * added config variable "exclude_users" in /etc/tacplus_nss + * Added config variable "timeout" to limit time attempting to + connect to non-responding TACACS server. + * Added config variable "exclude_users" in /etc/tacplus_nss to avoid looking up "local" user accounts via TACACS servers. This improves overall system performance for local users, and avoids significant delays when a TACACS server is unreachable. @@ -10,11 +11,12 @@ libnss-tacplus (1.0.3-1) unstable; urgency=low * Minor corrections to Copyright and licensing * Added vrf config variable, so NSS lookups work correctly$ * During login, send remote add IP address in AUTH request - connect to non-responding TACACS server. - * configuration files should automatically be reparsed + * Configuration files should automatically be reparsed if they change, for long-lived programs and daemons that use NSS. + * Added user_homedir config variable to allow per-user + home directories (unless per-command authorization is enabled) - -- Dave Olson <olson@cumulusnetworks.com> Tue, 07 Mar 2017 12:58:03 -0800 + -- Dave Olson <olson@cumulusnetworks.com> Thu, 23 Mar 2017 22:40:01 -0800 libnss-tacplus (1.0.2-1) unstable; urgency=low diff --git a/nss_tacplus.c b/nss_tacplus.c index 60a221f..201b329 100644 --- a/nss_tacplus.c +++ b/nss_tacplus.c @@ -75,6 +75,7 @@ static char vrfname[64]; static char *exclude_users; static uid_t min_uid = ~0U; /* largest possible */ static int debug; +uint16_t use_tachome; static int conf_parsed = 0; static void get_remote_addr(void); @@ -176,6 +177,8 @@ static int nss_tacplus_config(int *errnop, const char *cfile, int top) } else if(!strncmp(lbuf, "debug=", 6)) debug = strtoul(lbuf+6, NULL, 0); + else if (!strncmp (lbuf, "user_homedir=", 13)) + use_tachome = (uint16_t)strtoul(lbuf+13, NULL, 0); else if (!strncmp (lbuf, "timeout=", 8)) { tac_timeout = (int)strtoul(lbuf+8, NULL, 0); if (tac_timeout < 0) /* explict neg values disable poll() use */ @@ -319,12 +322,15 @@ static void print_servers(void) */ static int pwcopy(char *buf, size_t len, struct passwd *srcpw, struct passwd *destpw, - const char *usename) + const char *usename, uint16_t tachome) { - int needlen, cnt; + int needlen, cnt, origlen = len; + char *shell; - if(!usename) + if(!usename) { usename = srcpw->pw_name; + tachome = 0; /* early lookups; no tachome */ + } needlen = usename ? strlen(usename) + 1 : 1 + srcpw->pw_dir ? strlen(srcpw->pw_dir) + 1 : 1 + @@ -353,6 +359,14 @@ pwcopy(char *buf, size_t len, struct passwd *srcpw, struct passwd *destpw, len -= cnt; cnt = snprintf(buf, len, "%s", srcpw->pw_shell ? srcpw->pw_shell : ""); destpw->pw_shell = buf; + shell = strrchr(buf, '/'); + shell = shell ? shell+1 : buf; + if (tachome && *shell == 'r') { + tachome = 0; + if(debug > 1) + syslog(LOG_DEBUG, "%s tacacs login %s with user_homedir not allowed; " + "shell is %s", nssname, srcpw->pw_name, buf); + } cnt++; buf += cnt; len -= cnt; @@ -361,11 +375,28 @@ pwcopy(char *buf, size_t len, struct passwd *srcpw, struct passwd *destpw, cnt++; buf += cnt; len -= cnt; - cnt = snprintf(buf, len, "%s", srcpw->pw_dir ? srcpw->pw_dir : ""); + if (tachome && usename) { + char *slash, dbuf[strlen(srcpw->pw_dir) + strlen(usename)]; + snprintf(dbuf, sizeof dbuf, "%s", srcpw->pw_dir ? srcpw->pw_dir : ""); + slash = strrchr(dbuf, '/'); + if (slash) { + slash++; + snprintf(slash, sizeof dbuf - (slash-dbuf), "%s", usename); + } + cnt = snprintf(buf, len, "%s", dbuf); + } + else + cnt = snprintf(buf, len, "%s", srcpw->pw_dir ? srcpw->pw_dir : ""); destpw->pw_dir = buf; cnt++; buf += cnt; len -= cnt; + if(len < 0) { + if(debug) + syslog(LOG_DEBUG, "%s provided password buffer too small (%ld<%d)", + nssname, (long)origlen, origlen-(int)len); + return 1; + } return 0; } @@ -413,11 +444,11 @@ recheck: if(!ent->pw_name) continue; /* shouldn't happen */ if(!strcmp(ent->pw_name, pb->name)) { - retu = pwcopy(ubuf, sizeof(ubuf), ent, &upw, NULL); + retu = pwcopy(ubuf, sizeof(ubuf), ent, &upw, NULL, use_tachome); matches++; } else if(!strcmp(ent->pw_name, tacuser)) { - rett = pwcopy(tbuf, sizeof(tbuf), ent, &tpw, NULL); + rett = pwcopy(tbuf, sizeof(tbuf), ent, &tpw, NULL, use_tachome); matches++; } } @@ -433,9 +464,11 @@ recheck: syslog(LOG_DEBUG, "%s: local user not found at privilege=%u," " using %s", nssname, origpriv, tacuser); if(upw.pw_name && !retu) - ret = pwcopy(pb->buf, pb->buflen, &upw, pb->pw, pb->name); + ret = pwcopy(pb->buf, pb->buflen, &upw, pb->pw, pb->name, + use_tachome); else if(tpw.pw_name && !rett) - ret = pwcopy(pb->buf, pb->buflen, &tpw, pb->pw, pb->name); + ret = pwcopy(pb->buf, pb->buflen, &tpw, pb->pw, pb->name, + use_tachome); } if(ret) *pb->errnop = ERANGE; @@ -452,7 +485,8 @@ recheck: * returns 0 on success */ static int -find_pw_user(const char *logname, const char *tacuser, struct pwbuf *pb) +find_pw_user(const char *logname, const char *tacuser, struct pwbuf *pb, + uint16_t usetachome) { FILE *pwfile; struct passwd *ent; @@ -476,7 +510,7 @@ find_pw_user(const char *logname, const char *tacuser, struct pwbuf *pb) if(!ent->pw_name) continue; /* shouldn't happen */ if(!strcmp(ent->pw_name, tacuser)) { - ret = pwcopy(pb->buf, pb->buflen, ent, pb->pw, logname); + ret = pwcopy(pb->buf, pb->buflen, ent, pb->pw, logname, usetachome); break; } } @@ -663,12 +697,13 @@ static int lookup_mapped_uid(struct pwbuf *pb, uid_t uid, uid_t auid, int session) { char *loginname, mappedname[256]; + uint16_t flag; mappedname[0] = '\0'; loginname = lookup_mapuid(uid, auid, session, - mappedname, sizeof mappedname); + mappedname, sizeof mappedname, &flag); if(loginname) - return find_pw_user(loginname, mappedname, pb); + return find_pw_user(loginname, mappedname, pb, flag & MAP_USERHOMEDIR); return 1; } @@ -718,6 +753,7 @@ enum nss_status _nss_tacplus_getpwnam_r(const char *name, struct passwd *pw, if(!lookup) status = NSS_STATUS_SUCCESS; else if(lookup == 1) { /* 2 means exclude_users match */ + uint16_t flag; /* * If we can't contact a tacacs server (either not configured, or * more likely, we aren't running as root and the config for the @@ -728,8 +764,9 @@ enum nss_status _nss_tacplus_getpwnam_r(const char *name, struct passwd *pw, * common case of wanting to use the original login name by non-root * users. */ - char *mapname = lookup_mapname(name, -1, -1, NULL); - if(mapname != name && !find_pw_user(name, mapname, &pbuf)) + char *mapname = lookup_mapname(name, -1, -1, NULL, &flag); + if(mapname != name && !find_pw_user(name, mapname, &pbuf, + flag & MAP_USERHOMEDIR)) status = NSS_STATUS_SUCCESS; } } |