diff options
-rw-r--r-- | debian/changelog | 3 | ||||
-rw-r--r-- | nss_tacplus.c | 36 |
2 files changed, 37 insertions, 2 deletions
diff --git a/debian/changelog b/debian/changelog index fefa524..43d371e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,5 @@ libnss-tacplus (1.0.2) unstable; urgency=low * 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 @@ -10,6 +9,8 @@ libnss-tacplus (1.0.2) unstable; urgency=low * Improved debugging messages. * 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. -- Dave Olson <olson@cumulusnetworks.com> Tue, 07 Mar 2017 12:58:03 -0800 diff --git a/nss_tacplus.c b/nss_tacplus.c index 4fa652e..2d4f193 100644 --- a/nss_tacplus.c +++ b/nss_tacplus.c @@ -36,6 +36,7 @@ #include <ctype.h> #include <nss.h> #include <libaudit.h> +#include <sys/socket.h> #include <tacplus/libtac.h> #include <tacplus/map_tacplus_user.h> @@ -67,12 +68,15 @@ static tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; static int tac_srv_no, tac_key_no; static char tac_service[] = "shell"; static char tac_protocol[] = "ssh"; +static char tac_rhost[INET6_ADDRSTRLEN]; static char vrfname[64]; static char *exclude_users; static uid_t min_uid = ~0U; /* largest possible */ static int debug; static int conf_parsed = 0; +static void get_remote_addr(void); + static int nss_tacplus_config(int *errnop, const char *cfile, int top) { FILE *conf; @@ -531,7 +535,7 @@ lookup_tacacs_user(struct pwbuf *pb) tac_ntop(tac_srv[srvr].addr->ai_addr) : "unknown", tac_fd); continue; } - ret = tac_author_send(tac_fd, pb->name, "", "", attr); + ret = tac_author_send(tac_fd, pb->name, "", tac_rhost, attr); if(ret < 0) { if(debug) syslog(LOG_WARNING, "%s: TACACS+ server %s send failed (%d) for" @@ -621,6 +625,8 @@ enum nss_status _nss_tacplus_getpwnam_r(const char *name, struct passwd *pw, result = nss_tacplus_config(errnop, config_file, 1); conf_parsed = result == 0 ? 2 : 1; + get_remote_addr(); + if(result) { /* no config file, no servers, etc. */ /* this is a debug because privileges may not allow access */ if(debug) @@ -730,3 +736,31 @@ enum nss_status _nss_tacplus_getpwuid_r(uid_t uid, struct passwd *pw, status = NSS_STATUS_SUCCESS; return status; } + +static void get_remote_addr(void) +{ + struct sockaddr_storage addr; + socklen_t len = sizeof addr; + char ipstr[INET6_ADDRSTRLEN]; + + /* This is so we can fill in the rhost field when we talk to the + * TACACS+ server, when it's an ssh connection, so sites that refuse + * authorization unless from specific IP addresses will get that + * information. It's pretty much of a hack, but it works. + */ + if (getpeername(0, (struct sockaddr*)&addr, &len) == -1) + return; + + *ipstr = 0; + if (addr.ss_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *)&addr; + inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr); + } else { + struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr; + inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr); + } + + snprintf(tac_rhost, sizeof tac_rhost, "%s", ipstr); + if(debug > 1 && tac_rhost[0]) + syslog(LOG_DEBUG, "%s: rhost=%s", nssname, tac_rhost); +} |