summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/changelog12
-rw-r--r--nss_tacplus.c65
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;
}
}