From 2f51096c0765e52afd109ea81f6fa0fe1b35cb61 Mon Sep 17 00:00:00 2001 From: Dave Olson Date: Fri, 21 Oct 2016 16:01:03 -0700 Subject: Updated COPYING, corrected copyrights --- debian/copyright | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'debian/copyright') diff --git a/debian/copyright b/debian/copyright index 0cca9f3..48bfa52 100644 --- a/debian/copyright +++ b/debian/copyright @@ -3,8 +3,9 @@ Upstream-Name: libnss-tacplus Source: http://www.cumulusnetworks.com Files: * -Copyright: 2010 Pawel Krawczyk and Jeroen Nijhof , - 2015, 2016 Cumulus Networks, Inc. +Copyright: 2015, 2016 Cumulus Networks, Inc.. All rights reserved., + 2010 Pawel Krawczyk and Jeroen Nijhof + License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -- cgit v1.2.3 From f38818cdcec8f1f4b0ded6d74d49835d10d3e24e Mon Sep 17 00:00:00 2001 From: Dave Olson Date: Wed, 26 Oct 2016 14:51:53 -0700 Subject: Fixed trailing line whitespace issues --- debian/copyright | 1 - nss_tacplus.c | 29 ++++++++++++++--------------- nss_tacplus.h | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) (limited to 'debian/copyright') diff --git a/debian/copyright b/debian/copyright index 48bfa52..6d103c9 100644 --- a/debian/copyright +++ b/debian/copyright @@ -5,7 +5,6 @@ Source: http://www.cumulusnetworks.com Files: * Copyright: 2015, 2016 Cumulus Networks, Inc.. All rights reserved., 2010 Pawel Krawczyk and Jeroen Nijhof - License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/nss_tacplus.c b/nss_tacplus.c index b82613e..4c62a82 100644 --- a/nss_tacplus.c +++ b/nss_tacplus.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2014, 2015, 2016 Cumulus Networks, Inc. All rights reserved. * Author: Dave Olson - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -85,7 +85,7 @@ static int nss_tacplus_config(int *errnop, const char *cfile, int top) *errnop = errno; if(!conf_parsed && debug) /* debug because privileges may not allow */ syslog(LOG_DEBUG, "%s: can't open config file %s: %m", - nssname, cfile); + nssname, cfile); goto err; } @@ -101,7 +101,7 @@ static int nss_tacplus_config(int *errnop, const char *cfile, int top) if(lbuf[8]) /* else treat as empty config, ignoring errors */ (void)nss_tacplus_config(errnop, &lbuf[8], top+1); } - else if(!strncmp(lbuf, "debug=", 6)) + else if(!strncmp(lbuf, "debug=", 6)) debug = strtoul(lbuf+6, NULL, 0); /* * This next group is here to prevent a warning in the @@ -123,7 +123,7 @@ static int nss_tacplus_config(int *errnop, const char *cfile, int top) } } else if(!strncmp(lbuf, "exclude_users=", 14)) { - /* + /* * Don't lookup users in this comma-separated list for both * robustness and performnce. Typically root and other commonly * used local users. If set, we also look up the uids @@ -228,7 +228,7 @@ pwcopy(char *buf, size_t len, struct passwd *srcpw, struct passwd *destpw, if(!usename) usename = srcpw->pw_name; - needlen = usename ? strlen(usename) + 1 : 1 + + needlen = usename ? strlen(usename) + 1 : 1 + srcpw->pw_dir ? strlen(srcpw->pw_dir) + 1 : 1 + srcpw->pw_gecos ? strlen(srcpw->pw_gecos) + 1 : 1 + srcpw->pw_shell ? strlen(srcpw->pw_shell) + 1 : 1 + @@ -396,7 +396,7 @@ find_pw_user(const char *logname, const char *tacuser, struct pwbuf *pb) * We could optimize this for programs that do lots of lookups by leaving * the passwd file open and rewinding, but it doesn't seem worthwhile. */ -static bool +static bool lookup_local(char *name, uid_t uid) { FILE *pwfile; @@ -504,7 +504,7 @@ lookup_tacacs_user(struct pwbuf *pb) if (list) { bool islocal = 0; user = strtok(list, ","); - list = NULL; + list = NULL; while (user && !strcmp(user, pb->name)) { if(debug) syslog(LOG_DEBUG, "%s: check user=(%s)", nssname, user); @@ -555,7 +555,7 @@ lookup_tacacs_user(struct pwbuf *pb) tac_ntop(tac_srv[srvr].addr->ai_addr), ret, pb->name); } - tac_free_attrib(&attr); + tac_free_attrib(&attr); close(tac_fd); if(ret < 0) continue; @@ -565,7 +565,7 @@ lookup_tacacs_user(struct pwbuf *pb) ret = got_tacacs_user(arep.attr, pb); if(debug) syslog(LOG_DEBUG, "%s: TACACS+ server %s successful for user %s." - " local lookup %s", nssname, + " local lookup %s", nssname, tac_ntop(tac_srv[srvr].addr->ai_addr), pb->name, ret?"OK":"no match"); done = 1; /* break out of loop after arep cleanup */ @@ -574,7 +574,7 @@ lookup_tacacs_user(struct pwbuf *pb) ret = 1; /* in case last server */ if(debug) syslog(LOG_DEBUG, "%s: TACACS+ server %s replies user %s" - " invalid (%d)", nssname, + " invalid (%d)", nssname, tac_ntop(tac_srv[srvr].addr->ai_addr), pb->name, arep.status); } @@ -583,7 +583,7 @@ lookup_tacacs_user(struct pwbuf *pb) if(arep.attr) /* free returned attributes */ tac_free_attrib(&arep.attr); } - + return ret < 0? 1 : ret; } @@ -601,14 +601,14 @@ lookup_mapped_uid(struct pwbuf *pb, uid_t uid, uid_t auid, int session) } /* - * This is an NSS entry point. + * This is an NSS entry point. * We implement getpwnam(), because we remap from the tacacs login * to the local tacacs0 ... tacacs15 users for all other info, and so * the normal order of "passwd tacplus" (possibly with ldap or anything * else prior to tacplus) will mean we only get used when there isn't * a local user to be found. * - * We try the lookup to the tacacs server first. If we can't make a + * We try the lookup to the tacacs server first. If we can't make a * connection to the server for some reason, we also try looking up * the account name via the mapping file, primarily to handle cases * where we aren't running with privileges to read the tacacs configuration @@ -657,14 +657,13 @@ enum nss_status _nss_tacplus_getpwnam_r(const char *name, struct passwd *pw, char *mapname = lookup_mapname(name, -1, -1, NULL); if(mapname != name && !find_pw_user(name, mapname, &pbuf)) status = NSS_STATUS_SUCCESS; - } } return status; } /* - * This is an NSS entry point. + * This is an NSS entry point. * We implement getpwuid(), for anything that wants to get the original * login name from the uid. * If it matches an entry in the map, we use that data to replace diff --git a/nss_tacplus.h b/nss_tacplus.h index 72a1fb1..25e73e7 100644 --- a/nss_tacplus.h +++ b/nss_tacplus.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2014, 2015, 2016 Cumulus Networks, Inc. All rights reserved. - * + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or -- cgit v1.2.3 From b2cad0cf995560ea689be75d149e0fa030e2fe35 Mon Sep 17 00:00:00 2001 From: Dave Olson Date: Mon, 31 Oct 2016 13:04:42 -0700 Subject: Fixed copyright punctuation error --- debian/copyright | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'debian/copyright') diff --git a/debian/copyright b/debian/copyright index 6d103c9..9b1b34a 100644 --- a/debian/copyright +++ b/debian/copyright @@ -3,7 +3,7 @@ Upstream-Name: libnss-tacplus Source: http://www.cumulusnetworks.com Files: * -Copyright: 2015, 2016 Cumulus Networks, Inc.. All rights reserved., +Copyright: 2015, 2016 Cumulus Networks, Inc. All rights reserved., 2010 Pawel Krawczyk and Jeroen Nijhof License: GPL-2+ This package is free software; you can redistribute it and/or modify -- cgit v1.2.3 From dab6c3bb9feb10b67f08b18656fe24d1f7b01d2b Mon Sep 17 00:00:00 2001 From: Dave Olson Date: Fri, 12 May 2017 11:43:01 -0700 Subject: Track changes to config files, and reparse if any change This is done to handle the case where nss_tacplus.so is included in a long-lived daemon. It's desirable to have long-lived daemons reflect changes to the configuration, both to enable/disable debugging, and particularly if the server list or key changes. Clear all read config variables to defaults when re-parsing. This is complicated by nested configuration files via the include directive. At top level, we need to check all the previously used configuration files to see if any have changed. This also adds a limitation to no more than 8 deep include nesting. In practice, > 2 is going to be very rare, so it should be OK. Log a message when we re-initialize (without using debug qualifier). --- debian/changelog | 4 ++- debian/copyright | 5 ++-- nss_tacplus.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 80 insertions(+), 9 deletions(-) (limited to 'debian/copyright') diff --git a/debian/changelog b/debian/changelog index 43d371e..cf33b24 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -libnss-tacplus (1.0.2) unstable; urgency=low +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 to avoid looking up "local" user accounts via TACACS servers. This @@ -11,6 +11,8 @@ libnss-tacplus (1.0.2) unstable; urgency=low * 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 + if they change, for long-lived programs and daemons that use NSS. -- Dave Olson Tue, 07 Mar 2017 12:58:03 -0800 diff --git a/debian/copyright b/debian/copyright index 9b1b34a..710851e 100644 --- a/debian/copyright +++ b/debian/copyright @@ -3,8 +3,9 @@ Upstream-Name: libnss-tacplus Source: http://www.cumulusnetworks.com Files: * -Copyright: 2015, 2016 Cumulus Networks, Inc. All rights reserved., - 2010 Pawel Krawczyk and Jeroen Nijhof +Copyright: 2015, 2016, 2017 Cumulus Networks, Inc. All rights reserved., + 2010 Pawel Krawczyk and + Jeroen Nijhof License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/nss_tacplus.c b/nss_tacplus.c index 2d4f193..1cf99c5 100644 --- a/nss_tacplus.c +++ b/nss_tacplus.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2014, 2015, 2016 Cumulus Networks, Inc. All rights reserved. + * Copyright (C) 2014, 2015, 2016, 2017 Cumulus Networks, Inc. + * All rights reserved. * Author: Dave Olson * * This program is free software; you can redistribute it and/or modify @@ -37,6 +38,7 @@ #include #include #include +#include #include #include @@ -60,7 +62,7 @@ struct pwbuf { typedef struct { struct addrinfo *addr; - const char *key; + char *key; } tacplus_server_t; /* set from configuration file parsing */ @@ -77,14 +79,77 @@ static int conf_parsed = 0; static void get_remote_addr(void); +#define MAX_INCL 8 /* max config level nesting */ + +/* reset all config variables when we are going to re-parse */ +static void +reset_config(void) +{ + int i, nservers; + + /* reset the config variables that we use, freeing memory where needed */ + nservers = tac_srv_no; + tac_srv_no = 0; + tac_key_no = 0; + vrfname[0] = '\0'; + if(exclude_users[0]) + (void)free(exclude_users); + exclude_users = NULL; + debug = 0; + use_tachome = 0; + tac_timeout = 0; + min_uid = ~0U; + + for(i = 0; i < nservers; i++) { + if(tac_srv[i].key) { + free(tac_srv[i].key); + tac_srv[i].key = NULL; + } + tac_srv[i].addr = NULL; + } +} + static int nss_tacplus_config(int *errnop, const char *cfile, int top) { FILE *conf; char lbuf[256]; + static struct stat lastconf[MAX_INCL]; + static char *cfilelist[MAX_INCL]; + struct stat st, *lst; + + if(top > MAX_INCL) { + syslog(LOG_NOTICE, "%s: Config file include depth > %d, ignoring %s", + nssname, MAX_INCL, cfile); + return 1; + } - if(conf_parsed > 1) /* 1: we've tried and thrown errors, 2, OK */ - return 0; + lst = &lastconf[top-1]; + if(conf_parsed && top == 1) { + /* + * check to see if the config file(s) have changed since last time, + * in case we are part of a long-lived daemon. If any changed, + * reparse. If not, return the appropriate status (err or OK) + * This is somewhat complicated by the include file mechanism. + * When we have nested includes, we have to check all the config + * files we saw previously, not just the top level config file. + */ + int i; + for(i=0; i < MAX_INCL; i++) { + struct stat *cst; + cst = &lastconf[i]; + if(!cst->st_ino || !cfilelist[i]) /* end of files */ + return conf_parsed == 2 ? 0 : 1; + if (stat(cfilelist[i], &st) || st.st_ino != cst->st_ino || + st.st_mtime != cst->st_mtime || st.st_ctime != cst->st_ctime) + break; /* found removed or different file, so re-parse */ + } + reset_config(); + syslog(LOG_NOTICE, "%s: Configuration file(s) have changed, re-initializing", + nssname); + } + /* don't check for failures, we'll just skip, don't want to error out */ + cfilelist[top-1] = strdup(cfile); conf = fopen(cfile, "r"); if(conf == NULL) { *errnop = errno; @@ -93,6 +158,8 @@ static int nss_tacplus_config(int *errnop, const char *cfile, int top) nssname, cfile); return 1; } + if (fstat(fileno(conf), lst) != 0) + memset(lst, 0, sizeof *lst); /* avoid stale data, no warning */ while(fgets(lbuf, sizeof lbuf, conf)) { if(*lbuf == '#' || isspace(*lbuf)) @@ -101,9 +168,10 @@ static int nss_tacplus_config(int *errnop, const char *cfile, int top) if(!strncmp(lbuf, "include=", 8)) { /* * allow include files, useful for centralizing tacacs - * server IP address and secret. + * server IP address and secret. When running non-privileged, + * may not be able to read one or more config files. */ - if(lbuf[8]) /* else treat as empty config, ignoring errors */ + if(lbuf[8]) (void)nss_tacplus_config(errnop, &lbuf[8], top+1); } else if(!strncmp(lbuf, "debug=", 6)) -- cgit v1.2.3