Skip to content
Merged
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
8 changes: 4 additions & 4 deletions files/image_config/hostcfgd/common-auth-sonic.j2
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# THIS IS AN AUTO-GENERATED FILE
#THIS IS AN AUTO-GENERATED FILE
#
# /etc/pam.d/common-auth- authentication settings common to all services
# This file is included from other service-specific PAM config files,
Expand All @@ -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 }} {% if server.vrf %} vrf={{ server.vrf }} {% endif %} 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 }} {% if server.vrf %} vrf={{ last_server.vrf }} {% endif %} 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 }} {%if server.vrf %} vrf={{ server.vrf }} {% endif %} try_first_pass
{% endfor %}
auth [success=1 default=ignore] pam_unix.so nullok try_first_pass

Expand Down
2 changes: 1 addition & 1 deletion files/image_config/hostcfgd/tacplus_nss.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ debug=on
# Default: None (no TACACS+ server)
# server=1.1.1.1:49,secret=test,timeout=3
{% for server in servers %}
server={{ server.ip }}:{{ server.tcp_port }},secret={{ server.passkey }},timeout={{ server.timeout }}
server={{ server.ip }}:{{ server.tcp_port }},secret={{ server.passkey }},timeout={{ server.timeout }}{% if server.vrf %},vrf={{ server.vrf }}{% endif %}{{''}}
{% endfor %}

# user_priv - set the map between TACACS+ user privilege and local user's passwd
Expand Down
43 changes: 43 additions & 0 deletions src/tacacs/nss/0003-management-vrf-support.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
From b20aad31e186e27cc83432b405555420f94c6049 Mon Sep 17 00:00:00 2001
From: Kannan KVS <[email protected]>
Date: Mon, 8 Oct 2018 03:10:55 -0700
Subject: [PATCH] MANAGEMENT_VRF_TACACS_NSS_CHANGES

---
nss_tacplus.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/nss_tacplus.c b/nss_tacplus.c
index 6e4fddd..1e222dd 100644
--- a/nss_tacplus.c
+++ b/nss_tacplus.c
@@ -76,6 +76,7 @@ static useradd_info_t useradd_grp_list[MAX_TACACS_USER_PRIV + 1];

static char *tac_service = "shell";
static char *tac_protocol = "ssh";
+static char vrfname[64];
static bool debug = false;
static bool many_to_one = false;

@@ -124,6 +125,9 @@ static int parse_tac_server(char *srv_buf)
return -1;
}
}
+ else if(!strncmp(token, "vrf=", 4)){
+ strncpy(vrfname, token + 4, sizeof(vrfname));
+ }
else if(!strncmp(token, "secret=", 7)) {
if(tac_srv[tac_srv_no].key)
free(tac_srv[tac_srv_no].key);
@@ -633,7 +637,7 @@ connect_tacacs(struct tac_attrib **attr, int srvr)
return -1;

fd = tac_connect_single(tac_srv[srvr].addr, tac_srv[srvr].key, NULL,
- tac_srv[srvr].timeout);
+ tac_srv[srvr].timeout, vrfname[0] ? vrfname : NULL);
if(fd >= 0) {
*attr = NULL; /* so tac_add_attr() allocates memory */
tac_add_attrib(attr, "service", tac_service);
--
2.7.4

1 change: 1 addition & 0 deletions src/tacacs/nss/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% :
# Apply patch
git am ../0001-Modify-user-map-profile.patch
git am ../0002-Enable-modifying-local-user-permission.patch
git am ../0003-management-vrf-support.patch

dpkg-buildpackage -rfakeroot -b -us -uc
popd
Expand Down
240 changes: 240 additions & 0 deletions src/tacacs/pam/0004-management-vrf-support.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
From 6005f4a884f250787bdc070235879b14186ade2c Mon Sep 17 00:00:00 2001
From: Kannan KVS <[email protected]>
Date: Mon, 8 Oct 2018 02:58:42 -0700
Subject: [PATCH] MANAGEMENT_VRF_TACACS_PAM_CHANGES

---
libtac/include/libtac.h | 4 ++--
libtac/lib/connect.c | 21 +++++++++++++++++----
pam_tacplus.c | 12 +++++++-----
support.c | 3 +++
tacc.c | 15 ++++++++++-----
5 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/libtac/include/libtac.h b/libtac/include/libtac.h
index 6dc42ab..0c9d3d2 100644
--- a/libtac/include/libtac.h
+++ b/libtac/include/libtac.h
@@ -135,8 +135,8 @@ extern int tac_readtimeout_enable;
/* connect.c */
extern int tac_timeout;

-int tac_connect(struct addrinfo **, char **, int);
-int tac_connect_single(const struct addrinfo *, const char *, struct addrinfo *, int);
+int tac_connect(struct addrinfo **, char **, int, char *);
+int tac_connect_single(const struct addrinfo *, const char *, struct addrinfo *, int, char *);
char *tac_ntop(const struct sockaddr *);

int tac_authen_send(int, const char *, const char *, const char *,
diff --git a/libtac/lib/connect.c b/libtac/lib/connect.c
index 47f598a..5035135 100644
--- a/libtac/lib/connect.c
+++ b/libtac/lib/connect.c
@@ -42,7 +42,7 @@ int tac_timeout = 5;
* >= 0 : valid fd
* < 0 : error status code, see LIBTAC_STATUS_...
*/
-int tac_connect(struct addrinfo **server, char **key, int servers) {
+int tac_connect(struct addrinfo **server, char **key, int servers, char *iface) {
int tries;
int fd=-1;

@@ -50,7 +50,7 @@ int tac_connect(struct addrinfo **server, char **key, int servers) {
TACSYSLOG((LOG_ERR, "%s: no TACACS+ servers defined", __FUNCTION__))
} else {
for ( tries = 0; tries < servers; tries++ ) {
- if((fd=tac_connect_single(server[tries], key[tries], NULL, tac_timeout)) >= 0 ) {
+ if((fd=tac_connect_single(server[tries], key[tries], NULL, tac_timeout, iface)) >= 0 ) {
/* tac_secret was set in tac_connect_single on success */
break;
}
@@ -66,8 +66,9 @@ int tac_connect(struct addrinfo **server, char **key, int servers) {
/* return value:
* >= 0 : valid fd
* < 0 : error status code, see LIBTAC_STATUS_...
+ * If iface is non-null, try to BIND to that interface, to support specific routing, including VRF.
*/
-int tac_connect_single(const struct addrinfo *server, const char *key, struct addrinfo *srcaddr, int timeout) {
+int tac_connect_single(const struct addrinfo *server, const char *key, struct addrinfo *srcaddr, int timeout, char *iface) {
int retval = LIBTAC_STATUS_CONN_ERR; /* default retval */
int fd = -1;
int flags, rc;
@@ -91,6 +92,19 @@ int tac_connect_single(const struct addrinfo *server, const char *key, struct ad
return LIBTAC_STATUS_CONN_ERR;
}

+ if (iface) {
+ /* do not fail if the bind fails, connection may still succeed */
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, iface,
+ strlen(iface)+1) < 0) {
+ TACSYSLOG((LOG_WARNING, ":%s: Binding socket to device %s failed.",
+ __FUNCTION__, iface))
+ } else {
+ TACDEBUG((LOG_DEBUG, "%s: Binding socket to device %s succeeded.",
+ __FUNCTION__, iface))
+ }
+
+ }
+
/* get flags for restoration later */
flags = fcntl(fd, F_GETFL, 0);

@@ -166,7 +180,6 @@ int tac_connect_single(const struct addrinfo *server, const char *key, struct ad
}

/* connected ok */
- TACDEBUG((LOG_DEBUG, "%s: connected to %s", __FUNCTION__, ip))
retval = fd;

/* set current tac_secret */
diff --git a/pam_tacplus.c b/pam_tacplus.c
index 2b7d2cd..38e2a70 100644
--- a/pam_tacplus.c
+++ b/pam_tacplus.c
@@ -53,6 +53,8 @@ static tacplus_server_t active_server;
/* accounting task identifier */
static short int task_id = 0;

+extern char *__vrfname;
+

/* Helper functions */
int _pam_send_account(int tac_fd, int type, const char *user, char *tty,
@@ -175,7 +177,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, NULL, tac_timeout, __vrfname);
if (tac_fd < 0) {
_pam_log(LOG_WARNING, "%s: error sending %s (fd)",
__FUNCTION__, typemsg);
@@ -274,9 +276,9 @@ 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, NULL, tac_timeout, __vrfname);
if (tac_fd < 0) {
- _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i);
+ _pam_log(LOG_ERR, "%s: connection to srv %d failed", __FUNCTION__, srv_i);
continue;
}
if (tac_authen_send(tac_fd, user, pass, tty, r_addr, TAC_PLUS_AUTHEN_LOGIN) < 0) {
@@ -577,7 +579,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, NULL, tac_timeout, __vrfname);
if(tac_fd < 0) {
_pam_log (LOG_ERR, "TACACS+ server unavailable");
if(arep.msg != NULL)
@@ -760,7 +762,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, NULL, tac_timeout, __vrfname);
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..be0142d 100644
--- a/support.c
+++ b/support.c
@@ -36,6 +36,7 @@ int tac_srv_no = 0;
char tac_service[64];
char tac_protocol[64];
char tac_prompt[64];
+char *__vrfname=NULL;

void _pam_log(int err, const char *format,...) {
char msg[256];
@@ -271,6 +272,8 @@ int _pam_parse (int argc, const char **argv) {
} else {
tac_readtimeout_enable = 1;
}
+ } else if(!strncmp(*argv, "vrf=", 4)) {
+ __vrfname = strdup(*argv + 4);
} else {
_pam_log (LOG_WARNING, "unrecognized option: %s", *argv);
}
diff --git a/tacc.c b/tacc.c
index d7c6e1a..fcc7d8c 100644
--- a/tacc.c
+++ b/tacc.c
@@ -76,6 +76,7 @@ int tac_encryption = 1;
typedef unsigned char flag;
flag quiet = 0;
char *user = NULL; /* global, because of signal handler */
+char *iface = NULL; /* -I interface or VRF to use for connection */

/* command line options */
static struct option long_options[] = {
@@ -97,6 +98,7 @@ static struct option long_options[] = {
{ "service", required_argument, NULL, 'S' },
{ "protocol", required_argument, NULL, 'P' },
{ "remote", required_argument, NULL, 'r' },
+ { "interface", required_argument, NULL, 'I' },
{ "login", required_argument, NULL, 'L' },

/* modifiers */
@@ -107,7 +109,7 @@ static struct option long_options[] = {
{ 0, 0, 0, 0 } };

/* command line letters */
-char *opt_string = "TRAVhu:p:s:k:c:qr:wnS:P:L:";
+char *opt_string = "TRAVIhu:p:s:k:c:qr:wnS:P:L:";

int main(int argc, char **argv) {
char *pass = NULL;
@@ -168,6 +170,9 @@ int main(int argc, char **argv) {
showversion(argv[0]);
case 'h':
showusage(argv[0]);
+ case 'I':
+ iface = optarg;
+ break;
case 'u':
user = optarg;
break;
@@ -283,7 +288,7 @@ int main(int argc, char **argv) {
tac_add_attrib(&attr, "service", service);
tac_add_attrib(&attr, "protocol", protocol);

- tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60);
+ tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60, iface);
if (tac_fd < 0) {
if (!quiet)
printf("Error connecting to TACACS+ server: %m\n");
@@ -321,7 +326,7 @@ int main(int argc, char **argv) {
tac_add_attrib(&attr, "service", service);
tac_add_attrib(&attr, "protocol", protocol);

- tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60);
+ tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60, iface);
if (tac_fd < 0) {
if (!quiet)
printf("Error connecting to TACACS+ server: %m\n");
@@ -404,7 +409,7 @@ int main(int argc, char **argv) {
sprintf(buf, "%hu", task_id);
tac_add_attrib(&attr, "task_id", buf);

- tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60);
+ tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60, iface);
if (tac_fd < 0) {
if (!quiet)
printf("Error connecting to TACACS+ server: %m\n");
@@ -445,7 +450,7 @@ void authenticate(const struct addrinfo *tac_server, const char *tac_secret,
int ret;
struct areply arep;

- tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60);
+ tac_fd = tac_connect_single(tac_server, tac_secret, NULL, 60, iface);
if (tac_fd < 0) {
if (!quiet)
printf("Error connecting to TACACS+ server: %m\n");
--
2.7.4

1 change: 1 addition & 0 deletions src/tacacs/pam/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% :
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-Obfuscate-key-before-printing-to-syslog.patch
git apply ../0004-management-vrf-support.patch

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