summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Olson <olson@cumulusnetworks.com>2017-03-23 22:42:24 -0700
committerDave Olson <olson@cumulusnetworks.com>2017-05-23 17:05:52 -0700
commit9b056a2a66ec7006d86121509ef1049c7f6f0725 (patch)
tree7064198f039e24912c0fa573c12174861eb476b3
parent1e79d33bc397c0a9f30512a624ce51153e981f89 (diff)
downloadlibnss-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/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;
}
}