Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TACACS+]: Add support to specify source address for TACACS+ #1238

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions files/image_config/hostcfgd/common-auth-sonic.j2
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ auth [success=1 default=ignore] pam_unix.so nullok try_first_pass
{% elif auth['login'] == 'local,tacacs+' %}
auth [success=done new_authtok_reqd=done default=ignore{{ ' auth_err=die' if not auth['failthrough'] }}] pam_unix.so nullok try_first_pass
{% for server in servers | sub(0, -1) %}
auth [success=done new_authtok_reqd=done default=ignore{{ ' auth_err=die' if not auth['failthrough'] }}] pam_tacplus.so server={{ server.ip }}:{{ server.tcp_port }} secret={{ server.passkey }} login={{ server.auth_type }} timeout={{ server.timeout }} try_first_pass
auth [success=done new_authtok_reqd=done default=ignore{{ ' auth_err=die' if not auth['failthrough'] }}] pam_tacplus.so server={{ server.ip }}:{{ server.tcp_port }} secret={{ server.passkey }} login={{ server.auth_type }} timeout={{ server.timeout }} {{ 'source_ip=%s' % src_ip if src_ip }} try_first_pass
{% endfor %}
{% if servers | count %}
{% set last_server = servers | last %}
auth [success=1 default=ignore] pam_tacplus.so server={{ last_server.ip }}:{{ last_server.tcp_port }} secret={{ last_server.passkey }} login={{ last_server.auth_type }} timeout={{ last_server.timeout }} try_first_pass
auth [success=1 default=ignore] pam_tacplus.so server={{ last_server.ip }}:{{ last_server.tcp_port }} secret={{ last_server.passkey }} login={{ last_server.auth_type }} timeout={{ last_server.timeout }} {{ 'source_ip=%s' % src_ip if src_ip }} try_first_pass

{% endif %}
{% elif auth['login'] == 'tacacs+' or auth['login'] == 'tacacs+,local' %}
{% for server in servers %}
auth [success=done new_authtok_reqd=done default=ignore{{ ' auth_err=die' if not auth['failthrough'] }}] pam_tacplus.so server={{ server.ip }}:{{ server.tcp_port }} secret={{ server.passkey }} login={{ server.auth_type }} timeout={{ server.timeout }} try_first_pass
auth [success=done new_authtok_reqd=done default=ignore{{ ' auth_err=die' if not auth['failthrough'] }}] pam_tacplus.so server={{ server.ip }}:{{ server.tcp_port }} secret={{ server.passkey }} login={{ server.auth_type }} timeout={{ server.timeout }} {{ 'source_ip=%s' % src_ip if src_ip }} try_first_pass
{% endfor %}
auth [success=1 default=ignore] pam_unix.so nullok try_first_pass

Expand Down
8 changes: 6 additions & 2 deletions files/image_config/hostcfgd/hostcfgd
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ class AaaCfg(object):
auth.update(self.auth)
tacplus_global = self.tacplus_global_default.copy()
tacplus_global.update(self.tacplus_global)
if 'src_ip' in tacplus_global:
src_ip = tacplus_global['src_ip']
else:
src_ip = None

servers_conf = []
if self.tacplus_servers:
Expand All @@ -104,7 +108,7 @@ class AaaCfg(object):
env = jinja2.Environment(loader=jinja2.FileSystemLoader('/'), trim_blocks=True)
env.filters['sub'] = sub
template = env.get_template(template_file)
pam_conf = template.render(auth=auth, servers=servers_conf)
pam_conf = template.render(auth=auth, src_ip=src_ip, servers=servers_conf)
with open(PAM_AUTH_CONF, 'w') as f:
f.write(pam_conf)

Expand All @@ -127,7 +131,7 @@ class AaaCfg(object):
# Set tacacs+ server in nss-tacplus conf
template_file = os.path.abspath(NSS_TACPLUS_CONF_TEMPLATE)
template = env.get_template(template_file)
nss_tacplus_conf = template.render(debug=self.debug, servers=servers_conf)
nss_tacplus_conf = template.render(debug=self.debug, src_ip=src_ip, servers=servers_conf)
with open(NSS_TACPLUS_CONF, 'w') as f:
f.write(nss_tacplus_conf)

Expand Down
9 changes: 8 additions & 1 deletion files/image_config/hostcfgd/tacplus_nss.conf.j2
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
onfiguration for libnss-tacplus
# Configuration for libnss-tacplus

# debug - If you want to open debug log, set it on
# Default: off
Expand All @@ -7,6 +7,13 @@ onfiguration for libnss-tacplus
debug=on
{% endif %}

# src_ip - set source address of TACACS+ protocl packets
# Default: None (auto source ip address)
# src_ip=2.2.2.2
{% if src_ip %}
src_ip={{ src_ip }}
{% endif %}

# server - set ip address, tcp port, secret string and timeout for TACACS+ servers
# Default: None (no TACACS+ server)
# server=1.1.1.1:49,secret=test,timeout=3
Expand Down
64 changes: 64 additions & 0 deletions src/tacacs/nss/0002-Add-support-for-TACACS-source-address.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
From a1b2b5193a6b1ce84d3961ecbc9ed16d8c9df44e Mon Sep 17 00:00:00 2001
From: Liuqu <chenchen.qcc@alibaba-inc.com>
Date: Wed, 13 Dec 2017 22:50:45 +0800
Subject: [PATCH] Add support for TACACS+ source address

---
nss_tacplus.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/nss_tacplus.c b/nss_tacplus.c
index ecfa0b0..0d78ced 100644
--- a/nss_tacplus.c
+++ b/nss_tacplus.c
@@ -73,6 +73,7 @@ typedef struct {
static tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS];
static int tac_srv_no;
static useradd_info_t useradd_grp_list[MAX_TACACS_USER_PRIV + 1];
+static struct addrinfo *source_addr;

static char *tac_service = "shell";
static char *tac_protocol = "ssh";
@@ -258,6 +259,21 @@ static int parse_config(const char *file)
else if(!strncmp(buf, "user_priv=", 10)) {
parse_user_priv(buf);
}
+ else if(!strncmp(buf, "src_ip=", 7)) {
+ struct addrinfo hints;
+ char *ip = buf + 7;
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if(source_addr)
+ freeaddrinfo(source_addr);
+
+ if(0 != getaddrinfo(ip, NULL, &hints, &source_addr))
+ syslog(LOG_ERR, "%s: error setting the source ip information",
+ nssname);
+ }
else if(!strncmp(buf, "server=", 7)) {
if(TAC_PLUS_MAXSERVERS <= tac_srv_no) {
syslog(LOG_ERR, "%s: tac server num is more than %d",
@@ -278,6 +294,8 @@ static int parse_config(const char *file)
nssname, n, tac_ntop(tac_srv[n].addr->ai_addr),
tac_srv[n].key, tac_srv[n].timeout);
}
+ syslog(LOG_DEBUG, "%s: src_ip=%s", nssname, NULL == source_addr
+ ? "NULL" : tac_ntop(source_addr->ai_addr));
syslog(LOG_DEBUG, "%s: many_to_one %s", nssname, 1 == many_to_one
? "enable" : "disable");
for(n = MIN_TACACS_USER_PRIV; n <= MAX_TACACS_USER_PRIV; n++) {
@@ -630,7 +648,7 @@ connect_tacacs(struct tac_attrib **attr, int srvr)
if(!*tac_service) /* reported at config file processing */
return -1;

- fd = tac_connect_single(tac_srv[srvr].addr, tac_srv[srvr].key, NULL,
+ fd = tac_connect_single(tac_srv[srvr].addr, tac_srv[srvr].key, source_addr,
tac_srv[srvr].timeout);
if(fd >= 0) {
*attr = NULL; /* so tac_add_attr() allocates memory */
--
1.9.1

1 change: 1 addition & 0 deletions src/tacacs/nss/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% :

# Apply patch
git apply ../0001-Modify-user-map-profile.patch
git apply ../0002-Add-support-for-TACACS-source-address.patch

dpkg-buildpackage -rfakeroot -b -us -uc
popd
Expand Down
124 changes: 124 additions & 0 deletions src/tacacs/pam/0003-Add-support-for-source-ip-address.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
From 9494f71bc5f04b28b790ab25f1729b480ca18879 Mon Sep 17 00:00:00 2001
From: Liuqu <chenchen.qcc@alibaba-inc.com>
Date: Thu, 14 Dec 2017 18:30:46 +0800
Subject: [PATCH] Add support for source ip address

---
pam_tacplus.c | 8 ++++----
support.c | 31 +++++++++++++++++++++++++++++++
support.h | 1 +
3 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/pam_tacplus.c b/pam_tacplus.c
index 2b7d2cd..4369306 100644
--- a/pam_tacplus.c
+++ b/pam_tacplus.c
@@ -175,7 +175,7 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv,

status = PAM_SESSION_ERR;
for(srv_i = 0; srv_i < tac_srv_no; srv_i++) {
- tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout);
+ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, tac_source_addr, tac_timeout);
if (tac_fd < 0) {
_pam_log(LOG_WARNING, "%s: error sending %s (fd)",
__FUNCTION__, typemsg);
@@ -274,7 +274,7 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags,
if (ctrl & PAM_TAC_DEBUG)
syslog(LOG_DEBUG, "%s: trying srv %d", __FUNCTION__, srv_i );

- tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout);
+ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, tac_source_addr, tac_timeout);
if (tac_fd < 0) {
_pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i);
continue;
@@ -577,7 +577,7 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags,
if(tac_protocol[0] != '\0')
tac_add_attrib(&attr, "protocol", tac_protocol);

- tac_fd = tac_connect_single(active_server.addr, active_server.key, NULL, tac_timeout);
+ tac_fd = tac_connect_single(active_server.addr, active_server.key, tac_source_addr, tac_timeout);
if(tac_fd < 0) {
_pam_log (LOG_ERR, "TACACS+ server unavailable");
if(arep.msg != NULL)
@@ -760,7 +760,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
if (ctrl & PAM_TAC_DEBUG)
syslog(LOG_DEBUG, "%s: trying srv %d", __FUNCTION__, srv_i );

- tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout);
+ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, tac_source_addr, tac_timeout);
if (tac_fd < 0) {
_pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i);
continue;
diff --git a/support.c b/support.c
index 44efee3..14bfca1 100644
--- a/support.c
+++ b/support.c
@@ -36,6 +36,8 @@ int tac_srv_no = 0;
char tac_service[64];
char tac_protocol[64];
char tac_prompt[64];
+char tac_source_ip[64];
+struct addrinfo *tac_source_addr = NULL;

void _pam_log(int err, const char *format,...) {
char msg[256];
@@ -271,6 +273,10 @@ int _pam_parse (int argc, const char **argv) {
} else {
tac_readtimeout_enable = 1;
}
+ } else if (!strncmp (*argv, "source_ip=", strlen("source_ip="))) {
+ /* source ip for the packets */
+ strncpy (tac_source_ip, *argv + strlen("source_ip="), sizeof(tac_source_ip));
+ set_source_ip (tac_source_ip, &tac_source_addr);
} else {
_pam_log (LOG_WARNING, "unrecognized option: %s", *argv);
}
@@ -289,8 +295,33 @@ int _pam_parse (int argc, const char **argv) {
_pam_log(LOG_DEBUG, "tac_protocol='%s'", tac_protocol);
_pam_log(LOG_DEBUG, "tac_prompt='%s'", tac_prompt);
_pam_log(LOG_DEBUG, "tac_login='%s'", tac_login);
+ _pam_log(LOG_DEBUG, "tac_source_ip='%s'", tac_source_ip);
}

return ctrl;
} /* _pam_parse */

+/* set source ip address for the outgoing tacacs packets */
+void set_source_ip(const char *tac_source_ip,
+ struct addrinfo **source_address) {
+
+ struct addrinfo hints;
+ int rv;
+
+ /* check if source address is configured */
+ if (*tac_source_ip == 0)
+ return;
+
+ /* set the source ip address for the tacacs packets */
+ if (tac_source_ip != NULL) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ if ((rv = getaddrinfo(tac_source_ip, NULL, &hints,
+ source_address)) != 0) {
+ _pam_log(LOG_ERR, "error setting the source ip information");
+ } else {
+ _pam_log(LOG_DEBUG, "source ip is set");
+ }
+ }
+}
diff --git a/support.h b/support.h
index 9cbd040..09b8a85 100644
--- a/support.h
+++ b/support.h
@@ -37,6 +37,7 @@ extern int tac_srv_no;
extern char tac_service[64];
extern char tac_protocol[64];
extern char tac_prompt[64];
+extern struct addrinfo *tac_source_addr;

int _pam_parse (int, const char **);
unsigned long _resolve_name (char *);
--
1.9.1

1 change: 1 addition & 0 deletions src/tacacs/pam/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% :
# Apply patch
git apply ../0001-Don-t-init-declarations-in-a-for-loop.patch
git apply ../0002-Fix-libtac2-bin-install-directory-error.patch
git apply ../0003-Add-support-for-source-ip-address.patch

dpkg-buildpackage -rfakeroot -b -us -uc
popd
Expand Down