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 /nss_tacplus.c | |
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
Diffstat (limited to 'nss_tacplus.c')
-rw-r--r-- | nss_tacplus.c | 65 |
1 files changed, 51 insertions, 14 deletions
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; } } |