From 00e98675044d60a94b5bde8d702ac6250e7c67aa Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Tue, 31 Aug 2021 10:34:42 +0800 Subject: [PATCH 01/12] [TACACS+]: Add TACACS support library and fix memory leak issue. --- ...rt-library-and-fix-memory-leak-issue.patch | 742 ++++++++++++++++++ src/tacacs/pam/Makefile | 1 + 2 files changed, 743 insertions(+) create mode 100644 src/tacacs/pam/0007-Add-TACACS-support-library-and-fix-memory-leak-issue.patch diff --git a/src/tacacs/pam/0007-Add-TACACS-support-library-and-fix-memory-leak-issue.patch b/src/tacacs/pam/0007-Add-TACACS-support-library-and-fix-memory-leak-issue.patch new file mode 100644 index 000000000000..5d5dd38155a0 --- /dev/null +++ b/src/tacacs/pam/0007-Add-TACACS-support-library-and-fix-memory-leak-issue.patch @@ -0,0 +1,742 @@ +From fd90bf227416a5c0be14a5ad18e6d620c6faee10 Mon Sep 17 00:00:00 2001 +From: liuh +Date: Thu, 19 Aug 2021 15:40:59 +0800 +Subject: [PATCH] Add TACACS+ support library and fix memory leak issue. + +--- + Makefile.am | 16 +- + configure.ac | 3 +- + libtacsupport.pc.in | 11 ++ + pam_tacplus.c | 59 ++++--- + pam_tacplus.h | 6 - + support.c | 381 +++++++++++++++++++++++++++----------------- + support.h | 23 ++- + 7 files changed, 311 insertions(+), 188 deletions(-) + create mode 100644 libtacsupport.pc.in + +diff --git a/Makefile.am b/Makefile.am +index c90c582..2ac9ea0 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -20,7 +20,7 @@ libtac/include/tacplus.h \ + libtac/include/libtac.h \ + libtac/include/cdefs.h + +-lib_LTLIBRARIES = libtac.la ++lib_LTLIBRARIES = libtac.la libtacsupport.la + libtac_la_SOURCES = \ + libtac/lib/acct_r.c \ + libtac/lib/acct_s.c \ +@@ -48,6 +48,16 @@ $(libtac_include_HEADERS) + libtac_la_CFLAGS = $(AM_CFLAGS) -I $(top_srcdir)/libtac/include + libtac_la_LDFLAGS = -version-info 2:0:0 -shared + ++libtacsupport_includedir = $(includedir)/libtac ++libtacsupport_include_HEADERS = \ ++support.h ++ ++libtacsupport_la_SOURCES = \ ++support.c \ ++$(libtacsupport_include_HEADERS) ++libtacsupport_la_CFLAGS = $(AM_CFLAGS) -I $(top_srcdir) -I $(top_srcdir)/libtac/include ++libtacsupport_la_LDFLAGS = -version-info 2:0:0 -shared ++ + moduledir = @pamdir@ + module_LTLIBRARIES = pam_tacplus.la + pam_tacplus_la_SOURCES = pam_tacplus.h \ +@@ -58,7 +68,7 @@ pam_tacplus_la_CFLAGS = $(AM_CFLAGS) -I $(top_srcdir)/libtac/include + pam_tacplus_la_LDFLAGS = -module -avoid-version + pam_tacplus_la_LIBADD = libtac.la + +-EXTRA_DIST = pam_tacplus.spec libtac.pc.in ++EXTRA_DIST = pam_tacplus.spec libtac.pc.in libtacsupport.pc.in + if DOC + dist_doc_DATA = sample.pam README.md AUTHORS ChangeLog + endif +@@ -68,5 +78,5 @@ MAINTAINERCLEANFILES = Makefile.in config.h.in configure aclocal.m4 \ + config/install-sh config/ltmain.sh config/missing + + pkgconfigdir = $(libdir)/pkgconfig +-pkgconfig_DATA = libtac.pc ++pkgconfig_DATA = libtac.pc libtacsupport.pc + +diff --git a/configure.ac b/configure.ac +index f67e2ba..0f917a8 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -95,6 +95,7 @@ AM_CONDITIONAL(DOC, test "x$enable_doc" != "xno") + dnl -------------------------------------------------------------------- + dnl Generate made files + AC_CONFIG_FILES([Makefile +- libtac.pc ++ libtac.pc ++ libtacsupport.pc + pam_tacplus.spec]) + AC_OUTPUT +diff --git a/libtacsupport.pc.in b/libtacsupport.pc.in +new file mode 100644 +index 0000000..1f12fe0 +--- /dev/null ++++ b/libtacsupport.pc.in +@@ -0,0 +1,11 @@ ++prefix=@prefix@ ++exec_prefix=@exec_prefix@ ++libdir=@libdir@ ++includedir=@includedir@/libtac ++ ++Name: libtacsupport ++Description: TACACS+ support lib implementation ++URL: https://github.com/jeroennijhof/pam_tacplus ++Version: @VERSION@ ++Libs: -L${libdir} -ltacsupport ++Cflags: -I${includedir} +diff --git a/pam_tacplus.c b/pam_tacplus.c +index 9fc6be7..916b4d0 100644 +--- a/pam_tacplus.c ++++ b/pam_tacplus.c +@@ -51,10 +51,7 @@ + static tacplus_server_t active_server; + + /* accounting task identifier */ +-static short int task_id = 0; +- +-extern char *__vrfname; +- ++static short int task_id = 0; + + /* Helper functions */ + int _pam_send_account(int tac_fd, int type, const char *user, char *tty, +@@ -136,10 +133,12 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, + syslog (LOG_DEBUG, "%s: [%s] called (pam_tacplus v%u.%u.%u)", + __FUNCTION__, typemsg, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); + syslog(LOG_DEBUG, "%s: tac_srv_no=%d", __FUNCTION__, tac_srv_no); +- } ++ } ++ ++ if ((user = _pam_get_user(pamh)) == NULL) { ++ return PAM_USER_UNKNOWN; ++ } + +- if ((user = _pam_get_user(pamh)) == NULL) +- return PAM_USER_UNKNOWN; + + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: username [%s] obtained", __FUNCTION__, user); +@@ -177,7 +176,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, tac_source_addr, tac_timeout, __vrfname); ++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); + if (tac_fd < 0) { + _pam_log(LOG_WARNING, "%s: error sending %s (fd)", + __FUNCTION__, typemsg); +@@ -208,6 +207,7 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, SIG_DFL); + } ++ + return status; + } + +@@ -238,8 +238,9 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, + syslog(LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)", + __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); + +- if ((user = _pam_get_user(pamh)) == NULL) +- return PAM_USER_UNKNOWN; ++ if ((user = _pam_get_user(pamh)) == NULL) { ++ return PAM_USER_UNKNOWN; ++ } + + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: user [%s] obtained", __FUNCTION__, user); +@@ -276,7 +277,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, tac_source_addr, tac_timeout, __vrfname); ++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); + if (tac_fd < 0) { + _pam_log(LOG_ERR, "%s: connection to srv %d failed", __FUNCTION__, srv_i); + continue; +@@ -322,8 +323,9 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, + } + status = PAM_SUCCESS; + communicating = 0; +- active_server.addr = tac_srv[srv_i].addr; +- active_server.key = tac_srv[srv_i].key; ++ active_server.addr = tac_srv[srv_i].addr; ++ /* copy secret to key */ ++ snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); + + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); +@@ -537,8 +539,9 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, + syslog (LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)" + , __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); + +- if ((user = _pam_get_user(pamh)) == NULL) +- return PAM_USER_UNKNOWN; ++ if ((user = _pam_get_user(pamh)) == NULL) { ++ return PAM_USER_UNKNOWN; ++ } + + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: username obtained [%s]", __FUNCTION__, user); +@@ -579,11 +582,13 @@ 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, tac_source_addr, tac_timeout, __vrfname); ++ tac_fd = tac_connect_single(active_server.addr, active_server.key, &tac_source_addr, tac_timeout, __vrfname); + if(tac_fd < 0) { + _pam_log (LOG_ERR, "TACACS+ server unavailable"); +- if(arep.msg != NULL) +- free (arep.msg); ++ if(arep.msg != NULL) { ++ free (arep.msg); ++ } ++ + return PAM_AUTH_ERR; + } + +@@ -664,7 +669,6 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, + free (arep.msg); + + close(tac_fd); +- + return status; + } /* pam_sm_acct_mgmt */ + +@@ -725,9 +729,10 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + syslog(LOG_DEBUG, "%s(flags=%d, argc=%d)", __func__, flags, argc); + + if ( (pam_get_item(pamh, PAM_OLDAUTHTOK, &pam_pass) == PAM_SUCCESS) +- && (pam_pass != NULL) ) { +- if ((pass = strdup(pam_pass)) == NULL) +- return PAM_BUF_ERR; ++ && (pam_pass != NULL) ) { ++ if ((pass = strdup(pam_pass)) == NULL) { ++ return PAM_BUF_ERR; ++ } + } else { + pass = strdup(""); + } +@@ -735,7 +740,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + if ((user = _pam_get_user(pamh)) == NULL) { + if(pass) { + free(pass); +- } ++ } ++ + return PAM_USER_UNKNOWN; + } + +@@ -762,7 +768,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, tac_source_addr, tac_timeout, __vrfname); ++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); + if (tac_fd < 0) { + _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i); + continue; +@@ -819,8 +825,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + status = PAM_SUCCESS; + communicating = 0; + +- active_server.addr = tac_srv[srv_i].addr; +- active_server.key = tac_srv[srv_i].key; ++ active_server.addr = tac_srv[srv_i].addr; ++ /* copy secret to key */ ++ snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); + + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); +diff --git a/pam_tacplus.h b/pam_tacplus.h +index bc71b54..e7b30f7 100644 +--- a/pam_tacplus.h ++++ b/pam_tacplus.h +@@ -31,12 +31,6 @@ + #include + #include + +-/* pam_tacplus command line options */ +-#define PAM_TAC_DEBUG 0x01 +-#define PAM_TAC_ACCT 0x02 /* account on all specified servers */ +-#define PAM_TAC_USE_FIRST_PASS 0x04 +-#define PAM_TAC_TRY_FIRST_PASS 0x08 +- + /* pam_tacplus major, minor and patchlevel version numbers */ + #define PAM_TAC_VMAJ 1 + #define PAM_TAC_VMIN 3 +diff --git a/support.c b/support.c +index be1f21b..2cc85f4 100644 +--- a/support.c ++++ b/support.c +@@ -29,16 +29,26 @@ + + #include + #include ++#include /* isspace() */ + ++/* tacacs server information */ + tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; ++struct addrinfo tac_srv_addr[TAC_PLUS_MAXSERVERS]; ++struct sockaddr tac_sock_addr[TAC_PLUS_MAXSERVERS]; ++struct sockaddr_in6 tac_sock6_addr[TAC_PLUS_MAXSERVERS]; ++ + int tac_srv_no = 0; + + char tac_service[64]; + char tac_protocol[64]; + char tac_prompt[64]; + char *__vrfname=NULL; +-char tac_source_ip[64]; +-struct addrinfo *tac_source_addr = NULL; ++char tac_source_ip[64]; ++ ++/* source address */ ++struct addrinfo tac_source_addr; ++struct sockaddr tac_source_sock_addr; ++struct sockaddr_in6 tac_source_sock6_addr; + + void _pam_log(int err, const char *format,...) { + char msg[256]; +@@ -172,159 +182,236 @@ int tacacs_get_password (pam_handle_t * pamh, int flags + + return PAM_SUCCESS; + } +- +-int _pam_parse (int argc, const char **argv) { +- int ctrl = 0; +- const char *current_secret = NULL; +- +- /* otherwise the list will grow with each call */ +- memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); +- tac_srv_no = 0; +- +- tac_service[0] = 0; +- tac_protocol[0] = 0; +- tac_prompt[0] = 0; +- tac_login[0] = 0; +- tac_source_ip[0] = 0; + +- if (tac_source_addr != NULL) { +- freeaddrinfo(tac_source_addr); +- tac_source_addr = NULL; ++/* ++ * Set tacacs server addrinfo. ++ */ ++void set_tacacs_server_addr(int tac_srv_no, struct addrinfo* server) { ++ tac_srv[tac_srv_no].addr = &(tac_srv_addr[tac_srv_no]); ++ memcpy(tac_srv[tac_srv_no].addr, server, sizeof(struct addrinfo)); ++ ++ if (server->ai_family == AF_INET6) { ++ tac_srv[tac_srv_no].addr->ai_addr = (struct sockaddr *)&(tac_sock6_addr[tac_srv_no]); ++ memcpy(tac_srv[tac_srv_no].addr->ai_addr, server->ai_addr, sizeof(struct sockaddr_in6)); + } ++ else { ++ tac_srv[tac_srv_no].addr->ai_addr = &(tac_sock_addr[tac_srv_no]); ++ memcpy(tac_srv[tac_srv_no].addr->ai_addr, server->ai_addr, sizeof(struct sockaddr)); ++ } ++ ++ tac_srv[tac_srv_no].addr->ai_canonname = NULL; ++ tac_srv[tac_srv_no].addr->ai_next = NULL; ++} + +- for (ctrl = 0; argc-- > 0; ++argv) { +- if (!strcmp (*argv, "debug")) { /* all */ +- ctrl |= PAM_TAC_DEBUG; +- } else if (!strcmp (*argv, "use_first_pass")) { +- ctrl |= PAM_TAC_USE_FIRST_PASS; +- } else if (!strcmp (*argv, "try_first_pass")) { +- ctrl |= PAM_TAC_TRY_FIRST_PASS; +- } else if (!strncmp (*argv, "service=", 8)) { /* author & acct */ +- xstrcpy (tac_service, *argv + 8, sizeof(tac_service)); +- } else if (!strncmp (*argv, "protocol=", 9)) { /* author & acct */ +- xstrcpy (tac_protocol, *argv + 9, sizeof(tac_protocol)); +- } else if (!strncmp (*argv, "prompt=", 7)) { /* authentication */ +- xstrcpy (tac_prompt, *argv + 7, sizeof(tac_prompt)); +- /* Replace _ with space */ +- int chr; +- for (chr = 0; chr < strlen(tac_prompt); chr++) { +- if (tac_prompt[chr] == '_') { +- tac_prompt[chr] = ' '; +- } +- } +- } else if (!strncmp (*argv, "login=", 6)) { +- xstrcpy (tac_login, *argv + 6, sizeof(tac_login)); +- } else if (!strcmp (*argv, "acct_all")) { +- ctrl |= PAM_TAC_ACCT; +- } else if (!strncmp (*argv, "server=", 7)) { /* authen & acct */ +- if(tac_srv_no < TAC_PLUS_MAXSERVERS) { +- struct addrinfo hints, *servers, *server; +- int rv; +- char *close_bracket, *server_name, *port, server_buf[256]; +- +- memset(&hints, 0, sizeof hints); +- hints.ai_family = AF_UNSPEC; /* use IPv4 or IPv6, whichever */ +- hints.ai_socktype = SOCK_STREAM; +- +- if (strlen(*argv + 7) >= sizeof(server_buf)) { +- _pam_log(LOG_ERR, "server address too long, sorry"); +- continue; +- } +- strcpy(server_buf, *argv + 7); +- +- if (*server_buf == '[' && (close_bracket = strchr(server_buf, ']')) != NULL) { /* Check for URI syntax */ +- server_name = server_buf + 1; +- port = strrchr(close_bracket, ':'); +- *close_bracket = '\0'; +- } else { /* Fall back to traditional syntax */ +- server_name = server_buf; +- port = strrchr(server_buf, ':'); +- } +- if (port != NULL) { +- *port = '\0'; +- port++; +- } +- if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { +- for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { +- tac_srv[tac_srv_no].addr = server; +- tac_srv[tac_srv_no].key = current_secret; +- tac_srv_no++; +- } +- } else { +- _pam_log (LOG_ERR, +- "skip invalid server: %s (getaddrinfo: %s)", +- server_name, gai_strerror(rv)); +- } +- } else { +- _pam_log(LOG_ERR, "maximum number of servers (%d) exceeded, skipping", +- TAC_PLUS_MAXSERVERS); +- } +- } else if (!strncmp (*argv, "secret=", 7)) { +- int i; +- +- current_secret = *argv + 7; /* points right into argv (which is const) */ +- +- /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ +- for(i = tac_srv_no-1; i >= 0; i--) { +- if (tac_srv[i].key != NULL) +- break; +- +- tac_srv[i].key = current_secret; +- } +- } else if (!strncmp (*argv, "timeout=", 8)) { +- /* FIXME atoi() doesn't handle invalid numeric strings well */ +- tac_timeout = atoi(*argv + 8); +- +- if (tac_timeout < 0) { +- tac_timeout = 0; +- } else { +- tac_readtimeout_enable = 1; +- } +- } else if(!strncmp(*argv, "vrf=", 4)) { +- __vrfname = strdup(*argv + 4); +- } 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); +- } +- } +- +- if (ctrl & PAM_TAC_DEBUG) { +- int n; +- +- _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); ++/* set source ip address for the outgoing tacacs packets */ ++void set_source_ip(const char *tac_source_ip) { + +- for(n = 0; n < tac_srv_no; n++) { +- _pam_log(LOG_DEBUG, "server[%d] { addr=%s, key='%c*****' }", n, tac_ntop(tac_srv[n].addr->ai_addr), tac_srv[n].key[0]); +- } ++ struct addrinfo hints, *source_address; ++ int rv; + +- _pam_log(LOG_DEBUG, "tac_service='%s'", tac_service); +- _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); ++ /* set the source ip address for the tacacs packets */ ++ 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 { ++ memcpy(&tac_source_addr, source_address, sizeof(struct addrinfo)); ++ ++ if (source_address->ai_family == AF_INET6) { ++ tac_source_addr.ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); ++ memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); ++ } ++ else { ++ tac_source_addr.ai_addr = &(tac_source_sock_addr); ++ memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); ++ } ++ ++ ++ freeaddrinfo(source_address); ++ _pam_log(LOG_DEBUG, "source ip is set"); + } +- +- 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) { ++} ++ ++/* ++ * Parse one arguments. ++ * Use this method for both: ++ * 1. command line parameter ++ * 2. config file ++ */ ++int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_buffer_size) { ++ int ctrl = 0; ++ ++ if (!strcmp (arg, "debug")) { /* all */ ++ ctrl |= PAM_TAC_DEBUG; ++ } else if (!strcmp (arg, "use_first_pass")) { ++ ctrl |= PAM_TAC_USE_FIRST_PASS; ++ } else if (!strcmp (arg, "try_first_pass")) { ++ ctrl |= PAM_TAC_TRY_FIRST_PASS; ++ } else if (!strncmp (arg, "service=", 8)) { /* author & acct */ ++ xstrcpy (tac_service, arg + 8, sizeof(tac_service)); ++ } else if (!strncmp (arg, "protocol=", 9)) { /* author & acct */ ++ xstrcpy (tac_protocol, arg + 9, sizeof(tac_protocol)); ++ } else if (!strncmp (arg, "prompt=", 7)) { /* authentication */ ++ xstrcpy (tac_prompt, arg + 7, sizeof(tac_prompt)); ++ /* Replace _ with space */ ++ int chr; ++ for (chr = 0; chr < strlen(tac_prompt); chr++) { ++ if (tac_prompt[chr] == '_') { ++ tac_prompt[chr] = ' '; ++ } ++ } ++ } else if (!strncmp (arg, "login=", 6)) { ++ xstrcpy (tac_login, arg + 6, sizeof(tac_login)); ++ } else if (!strcmp (arg, "acct_all")) { ++ ctrl |= PAM_TAC_ACCT; ++ } else if (!strncmp (arg, "server=", 7)) { /* authen & acct */ ++ if(tac_srv_no < TAC_PLUS_MAXSERVERS) { ++ struct addrinfo hints, *servers, *server; ++ int rv; ++ char *close_bracket, *server_name, *port, server_buf[256]; ++ ++ memset(&hints, 0, sizeof hints); ++ hints.ai_family = AF_UNSPEC; /* use IPv4 or IPv6, whichever */ ++ hints.ai_socktype = SOCK_STREAM; ++ ++ if (strlen(arg + 7) >= sizeof(server_buf)) { ++ _pam_log(LOG_ERR, "server address too long, sorry"); ++ return ctrl; ++ } ++ strcpy(server_buf, arg + 7); ++ ++ if (*server_buf == '[' && (close_bracket = strchr(server_buf, ']')) != NULL) { /* Check for URI syntax */ ++ server_name = server_buf + 1; ++ port = strchr(close_bracket, ':'); ++ *close_bracket = '\0'; ++ } else { /* Fall back to traditional syntax */ ++ server_name = server_buf; ++ port = strchr(server_buf, ':'); ++ } ++ if (port != NULL) { ++ *port = '\0'; ++ port++; ++ } ++ if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { ++ for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { ++ /* set server address with allocate memory */ ++ set_tacacs_server_addr(tac_srv_no, server); + +- struct addrinfo hints; +- int rv; ++ /* copy secret to key */ ++ snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); ++ tac_srv_no++; ++ } + +- /* set the source ip address for the tacacs packets */ +- 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"); ++ /* release servers memory */ ++ freeaddrinfo(servers); ++ } else { ++ _pam_log (LOG_ERR, ++ "skip invalid server: %s (getaddrinfo: %s)", ++ server_name, gai_strerror(rv)); ++ } ++ } else { ++ _pam_log(LOG_ERR, "maximum number of servers (%d) exceeded, skipping", ++ TAC_PLUS_MAXSERVERS); ++ } ++ } else if (!strncmp (arg, "secret=", 7)) { ++ int i; ++ ++ /* points right into arg (which is const) */ ++ snprintf(current_secret, current_secret_buffer_size, "%s", arg + 7); ++ ++ /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ ++ for(i = tac_srv_no-1; i >= 0; i--) { ++ if (tac_srv[i].key != NULL) ++ break; ++ ++ /* copy secret to key */ ++ snprintf(tac_srv[i].key, sizeof(tac_srv[i].key), "%s", current_secret); ++ } ++ } else if (!strncmp (arg, "timeout=", 8)) { ++ /* FIXME atoi() doesn't handle invalid numeric strings well */ ++ tac_timeout = atoi(arg + 8); ++ ++ if (tac_timeout < 0) { ++ tac_timeout = 0; ++ } else { ++ tac_readtimeout_enable = 1; ++ } ++ } else if(!strncmp(arg, "vrf=", 4)) { ++ __vrfname = strdup(arg + 4); ++ } else if (!strncmp (arg, "source_ip=", strlen("source_ip="))) { ++ /* source ip for the packets */ ++ strncpy (tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); ++ set_source_ip (tac_source_ip); + } else { +- _pam_log(LOG_DEBUG, "source ip is set"); ++ _pam_log (LOG_WARNING, "unrecognized option: %s", arg); + } ++ ++ return ctrl; ++} /* _pam_parse_arg */ ++ ++ ++/* ++ * Parse config file. ++ */ ++int parse_config_file(const char *file) { ++ FILE *config_file; ++ char line_buffer[256]; ++ int ctrl = 0; ++ ++ config_file = fopen(file, "r"); ++ if(config_file == NULL) { ++ _pam_log(LOG_ERR, "Failed to open config file %s: %m", file); ++ return 0; ++ } ++ ++ char current_secret[256]; ++ memset(current_secret, 0, sizeof(current_secret)); ++ while (fgets(line_buffer, sizeof line_buffer, config_file)) { ++ if(*line_buffer == '#' || isspace(*line_buffer)) ++ continue; /* skip comments and blank line. */ ++ strtok(line_buffer, " \t\n\r\f"); ++ ctrl |= _pam_parse_arg(line_buffer, current_secret, sizeof(current_secret)); ++ } ++ ++ fclose(config_file); ++ return ctrl; + } ++int _pam_parse (int argc, const char **argv) { ++ int ctrl = 0; ++ char current_secret[256]; ++ memset(current_secret, 0, sizeof(current_secret)); ++ ++ /* otherwise the list will grow with each call */ ++ memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); ++ tac_srv_no = 0; ++ ++ tac_service[0] = 0; ++ tac_protocol[0] = 0; ++ tac_prompt[0] = 0; ++ tac_login[0] = 0; ++ tac_source_ip[0] = 0; ++ ++ for (ctrl = 0; argc-- > 0; ++argv) { ++ ctrl |= _pam_parse_arg(*argv, current_secret, sizeof(current_secret)); ++ } ++ ++ if (ctrl & PAM_TAC_DEBUG) { ++ int n; ++ ++ _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); ++ ++ for(n = 0; n < tac_srv_no; n++) { ++ _pam_log(LOG_DEBUG, "server[%d] { addr=%s, key='%c*****' }", n, tac_ntop(tac_srv[n].addr->ai_addr), tac_srv[n].key[0]); ++ } ++ ++ _pam_log(LOG_DEBUG, "tac_service='%s'", tac_service); ++ _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 */ +diff --git a/support.h b/support.h +index b1faf43..bdb60b4 100644 +--- a/support.h ++++ b/support.h +@@ -24,20 +24,28 @@ + + #include "libtac.h" + +-#include ++#include ++ ++/* pam_tacplus command line options */ ++#define PAM_TAC_DEBUG 0x01 ++#define PAM_TAC_ACCT 0x02 /* account on all specified servers */ ++#define PAM_TAC_USE_FIRST_PASS 0x04 ++#define PAM_TAC_TRY_FIRST_PASS 0x08 + + typedef struct { +- struct addrinfo *addr; +- const char *key; ++ struct addrinfo *addr; ++ char key[256]; + } tacplus_server_t; + + extern tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; ++ + extern int tac_srv_no; ++extern char *__vrfname; + + extern char tac_service[64]; + extern char tac_protocol[64]; + extern char tac_prompt[64]; +-extern struct addrinfo *tac_source_addr; ++extern struct addrinfo tac_source_addr; + + int _pam_parse (int, const char **); + unsigned long _resolve_name (char *); +@@ -48,7 +56,12 @@ void _pam_log (int, const char *, ...); + void *_xcalloc (size_t); + char *_pam_get_user(pam_handle_t *); + char *_pam_get_terminal(pam_handle_t *); +-char *_pam_get_rhost(pam_handle_t *); ++char *_pam_get_rhost(pam_handle_t *); ++ ++/* ++ * Parse config file. ++ */ ++int parse_config_file(const char *file); + + #endif /* PAM_TACPLUS_SUPPORT_H */ + +-- +2.17.1.windows.2 + diff --git a/src/tacacs/pam/Makefile b/src/tacacs/pam/Makefile index 503bdcb864f0..f942a5b4daa5 100644 --- a/src/tacacs/pam/Makefile +++ b/src/tacacs/pam/Makefile @@ -20,6 +20,7 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : git apply ../0004-management-vrf-support.patch git apply ../0005-pam-Modify-parsing-of-IP-address-and-port-number-to-.patch git apply ../0006-Add-support-for-source-ip-address.patch + git apply ../0007-Add-TACACS-support-library-and-fix-memory-leak-issue.patch dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) popd From 2f636c5de97a917951f7f9f34ffb557077918a9d Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Fri, 10 Sep 2021 17:37:28 +0800 Subject: [PATCH 02/12] Improve PR. --- ...memory-leak-when-parse-configuration.patch | 314 ++++++++++ ...cacs-support-functions-into-library.patch} | 559 ++++++++---------- src/tacacs/pam/Makefile | 3 +- 3 files changed, 554 insertions(+), 322 deletions(-) create mode 100644 src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch rename src/tacacs/pam/{0007-Add-TACACS-support-library-and-fix-memory-leak-issue.patch => 0008-Extract-tacacs-support-functions-into-library.patch} (70%) diff --git a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch new file mode 100644 index 000000000000..e83a82971344 --- /dev/null +++ b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch @@ -0,0 +1,314 @@ +From 95f09ea41d7179bbc321fad476cfe47cbdabdcab Mon Sep 17 00:00:00 2001 +From: liuh-80 <58683130+liuh-80@users.noreply.github.com> +Date: Fri, 10 Sep 2021 17:27:05 +0800 +Subject: [PATCH 1/2] Fix memory leak when parse configuration. + +--- + pam_tacplus.c | 34 +++++++++++++-------- + support.c | 81 ++++++++++++++++++++++++++++++++++----------------- + support.h | 4 +-- + 3 files changed, 78 insertions(+), 41 deletions(-) + +diff --git a/pam_tacplus.c b/pam_tacplus.c +index 9fc6be7..8a93c9b 100644 +--- a/pam_tacplus.c ++++ b/pam_tacplus.c +@@ -138,8 +138,10 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, + syslog(LOG_DEBUG, "%s: tac_srv_no=%d", __FUNCTION__, tac_srv_no); + } + +- if ((user = _pam_get_user(pamh)) == NULL) ++ if ((user = _pam_get_user(pamh)) == NULL) { + return PAM_USER_UNKNOWN; ++ } ++ + + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: username [%s] obtained", __FUNCTION__, user); +@@ -177,7 +179,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, tac_source_addr, tac_timeout, __vrfname); ++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); + if (tac_fd < 0) { + _pam_log(LOG_WARNING, "%s: error sending %s (fd)", + __FUNCTION__, typemsg); +@@ -208,6 +210,7 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, SIG_DFL); + } ++ + return status; + } + +@@ -238,8 +241,9 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, + syslog(LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)", + __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); + +- if ((user = _pam_get_user(pamh)) == NULL) ++ if ((user = _pam_get_user(pamh)) == NULL) { + return PAM_USER_UNKNOWN; ++ } + + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: user [%s] obtained", __FUNCTION__, user); +@@ -276,7 +280,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, tac_source_addr, tac_timeout, __vrfname); ++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); + if (tac_fd < 0) { + _pam_log(LOG_ERR, "%s: connection to srv %d failed", __FUNCTION__, srv_i); + continue; +@@ -323,7 +327,8 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, + status = PAM_SUCCESS; + communicating = 0; + active_server.addr = tac_srv[srv_i].addr; +- active_server.key = tac_srv[srv_i].key; ++ /* copy secret to key */ ++ snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); + + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); +@@ -537,8 +542,9 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, + syslog (LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)" + , __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); + +- if ((user = _pam_get_user(pamh)) == NULL) ++ if ((user = _pam_get_user(pamh)) == NULL) { + return PAM_USER_UNKNOWN; ++ } + + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: username obtained [%s]", __FUNCTION__, user); +@@ -579,11 +585,13 @@ 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, tac_source_addr, tac_timeout, __vrfname); ++ tac_fd = tac_connect_single(active_server.addr, active_server.key, &tac_source_addr, tac_timeout, __vrfname); + if(tac_fd < 0) { + _pam_log (LOG_ERR, "TACACS+ server unavailable"); +- if(arep.msg != NULL) ++ if(arep.msg != NULL) { + free (arep.msg); ++ } ++ + return PAM_AUTH_ERR; + } + +@@ -664,7 +672,6 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, + free (arep.msg); + + close(tac_fd); +- + return status; + } /* pam_sm_acct_mgmt */ + +@@ -726,8 +733,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + + if ( (pam_get_item(pamh, PAM_OLDAUTHTOK, &pam_pass) == PAM_SUCCESS) + && (pam_pass != NULL) ) { +- if ((pass = strdup(pam_pass)) == NULL) ++ if ((pass = strdup(pam_pass)) == NULL) { + return PAM_BUF_ERR; ++ } + } else { + pass = strdup(""); + } +@@ -736,6 +744,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + if(pass) { + free(pass); + } ++ + return PAM_USER_UNKNOWN; + } + +@@ -762,7 +771,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, tac_source_addr, tac_timeout, __vrfname); ++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); + if (tac_fd < 0) { + _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i); + continue; +@@ -820,7 +829,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + communicating = 0; + + active_server.addr = tac_srv[srv_i].addr; +- active_server.key = tac_srv[srv_i].key; ++ /* copy secret to key */ ++ snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); + + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); +diff --git a/support.c b/support.c +index be1f21b..3d38f24 100644 +--- a/support.c ++++ b/support.c +@@ -30,7 +30,12 @@ + #include + #include + ++/* tacacs server information */ + tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; ++struct addrinfo tac_srv_addr[TAC_PLUS_MAXSERVERS]; ++struct sockaddr tac_sock_addr[TAC_PLUS_MAXSERVERS]; ++struct sockaddr_in6 tac_sock6_addr[TAC_PLUS_MAXSERVERS]; ++ + int tac_srv_no = 0; + + char tac_service[64]; +@@ -38,7 +43,11 @@ char tac_protocol[64]; + char tac_prompt[64]; + char *__vrfname=NULL; + char tac_source_ip[64]; +-struct addrinfo *tac_source_addr = NULL; ++ ++/* source address */ ++struct addrinfo tac_source_addr; ++struct sockaddr tac_source_sock_addr; ++struct sockaddr_in6 tac_source_sock6_addr; + + void _pam_log(int err, const char *format,...) { + char msg[256]; +@@ -173,9 +182,38 @@ int tacacs_get_password (pam_handle_t * pamh, int flags + return PAM_SUCCESS; + } + ++} ++/* set source ip address for the outgoing tacacs packets */ ++void set_source_ip(const char *tac_source_ip) { ++ struct addrinfo hints, *source_address; ++ int rv; ++ /* set the source ip address for the tacacs packets */ ++ 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 { ++ memcpy(&tac_source_addr, source_address, sizeof(struct addrinfo)); ++ if (source_address->ai_family == AF_INET6) { ++ tac_source_addr.ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); ++ memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); ++ } ++ else { ++ tac_source_addr.ai_addr = &(tac_source_sock_addr); ++ memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); ++ } ++ ++ ++ freeaddrinfo(source_address); ++ _pam_log(LOG_DEBUG, "source ip is set"); ++ } ++} + int _pam_parse (int argc, const char **argv) { + int ctrl = 0; +- const char *current_secret = NULL; ++ char current_secret[256]; ++ memset(current_secret, 0, sizeof(current_secret)); + + /* otherwise the list will grow with each call */ + memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); +@@ -246,10 +284,16 @@ int _pam_parse (int argc, const char **argv) { + } + if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { + for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { +- tac_srv[tac_srv_no].addr = server; +- tac_srv[tac_srv_no].key = current_secret; ++ /* set server address with allocate memory */ ++ set_tacacs_server_addr(tac_srv_no, server); ++ ++ /* copy secret to key */ ++ snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); + tac_srv_no++; + } ++ ++ /* release servers memory */ ++ freeaddrinfo(servers); + } else { + _pam_log (LOG_ERR, + "skip invalid server: %s (getaddrinfo: %s)", +@@ -262,14 +306,16 @@ int _pam_parse (int argc, const char **argv) { + } else if (!strncmp (*argv, "secret=", 7)) { + int i; + +- current_secret = *argv + 7; /* points right into argv (which is const) */ ++ /* points right into arg (which is const) */ ++ snprintf(current_secret, sizeof(current_secret), "%s", arg + 7); + + /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ + for(i = tac_srv_no-1; i >= 0; i--) { + if (tac_srv[i].key != NULL) + break; + +- tac_srv[i].key = current_secret; ++ /* copy secret to key */ ++ snprintf(tac_srv[i].key, sizeof(tac_srv[i].key), "%s", current_secret); + } + } else if (!strncmp (*argv, "timeout=", 8)) { + /* FIXME atoi() doesn't handle invalid numeric strings well */ +@@ -284,8 +330,8 @@ int _pam_parse (int argc, const char **argv) { + __vrfname = strdup(*argv + 4); + } 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); ++ strncpy (tac_source_ip, *argv + strlen("source_ip="), sizeof(tac_source_ip)); ++ set_source_ip (tac_source_ip); + } else { + _pam_log (LOG_WARNING, "unrecognized option: %s", *argv); + } +@@ -309,22 +355,3 @@ int _pam_parse (int argc, const char **argv) { + + 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; +- +- /* set the source ip address for the tacacs packets */ +- 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 b1faf43..feadbf5 100644 +--- a/support.h ++++ b/support.h +@@ -28,7 +28,7 @@ + + typedef struct { + struct addrinfo *addr; +- const char *key; ++ char key[256]; + } tacplus_server_t; + + extern tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; +@@ -37,7 +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; ++extern struct addrinfo tac_source_addr; + + int _pam_parse (int, const char **); + unsigned long _resolve_name (char *); +-- +2.17.1.windows.2 + diff --git a/src/tacacs/pam/0007-Add-TACACS-support-library-and-fix-memory-leak-issue.patch b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch similarity index 70% rename from src/tacacs/pam/0007-Add-TACACS-support-library-and-fix-memory-leak-issue.patch rename to src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch index 5d5dd38155a0..7ebbe3f6dce7 100644 --- a/src/tacacs/pam/0007-Add-TACACS-support-library-and-fix-memory-leak-issue.patch +++ b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch @@ -1,17 +1,17 @@ -From fd90bf227416a5c0be14a5ad18e6d620c6faee10 Mon Sep 17 00:00:00 2001 -From: liuh -Date: Thu, 19 Aug 2021 15:40:59 +0800 -Subject: [PATCH] Add TACACS+ support library and fix memory leak issue. +From 8e48036b7379896dbef720401fb084254ffd1966 Mon Sep 17 00:00:00 2001 +From: liuh-80 <58683130+liuh-80@users.noreply.github.com> +Date: Fri, 10 Sep 2021 17:30:18 +0800 +Subject: [PATCH 2/2] Extract tacacs support functions into library --- Makefile.am | 16 +- configure.ac | 3 +- libtacsupport.pc.in | 11 ++ - pam_tacplus.c | 59 ++++--- + pam_tacplus.c | 27 ++-- pam_tacplus.h | 6 - - support.c | 381 +++++++++++++++++++++++++++----------------- - support.h | 23 ++- - 7 files changed, 311 insertions(+), 188 deletions(-) + support.c | 363 +++++++++++++++++++++++++------------------- + support.h | 19 ++- + 7 files changed, 265 insertions(+), 180 deletions(-) create mode 100644 libtacsupport.pc.in diff --git a/Makefile.am b/Makefile.am @@ -91,7 +91,7 @@ index 0000000..1f12fe0 +Libs: -L${libdir} -ltacsupport +Cflags: -I${includedir} diff --git a/pam_tacplus.c b/pam_tacplus.c -index 9fc6be7..916b4d0 100644 +index 8a93c9b..916b4d0 100644 --- a/pam_tacplus.c +++ b/pam_tacplus.c @@ -51,10 +51,7 @@ @@ -106,154 +106,86 @@ index 9fc6be7..916b4d0 100644 /* Helper functions */ int _pam_send_account(int tac_fd, int type, const char *user, char *tty, -@@ -136,10 +133,12 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, +@@ -136,10 +133,10 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, syslog (LOG_DEBUG, "%s: [%s] called (pam_tacplus v%u.%u.%u)", __FUNCTION__, typemsg, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); syslog(LOG_DEBUG, "%s: tac_srv_no=%d", __FUNCTION__, tac_srv_no); - } +- + } + -+ if ((user = _pam_get_user(pamh)) == NULL) { -+ return PAM_USER_UNKNOWN; -+ } - -- if ((user = _pam_get_user(pamh)) == NULL) + if ((user = _pam_get_user(pamh)) == NULL) { - return PAM_USER_UNKNOWN; - - if (ctrl & PAM_TAC_DEBUG) - syslog(LOG_DEBUG, "%s: username [%s] obtained", __FUNCTION__, user); -@@ -177,7 +176,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, tac_source_addr, tac_timeout, __vrfname); -+ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); - if (tac_fd < 0) { - _pam_log(LOG_WARNING, "%s: error sending %s (fd)", - __FUNCTION__, typemsg); -@@ -208,6 +207,7 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, - signal(SIGCHLD, SIG_DFL); - signal(SIGHUP, SIG_DFL); ++ return PAM_USER_UNKNOWN; } -+ - return status; - } -@@ -238,8 +238,9 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, - syslog(LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)", + +@@ -242,7 +239,7 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); -- if ((user = _pam_get_user(pamh)) == NULL) + if ((user = _pam_get_user(pamh)) == NULL) { - return PAM_USER_UNKNOWN; -+ if ((user = _pam_get_user(pamh)) == NULL) { + return PAM_USER_UNKNOWN; -+ } + } if (ctrl & PAM_TAC_DEBUG) - syslog(LOG_DEBUG, "%s: user [%s] obtained", __FUNCTION__, user); -@@ -276,7 +277,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, tac_source_addr, tac_timeout, __vrfname); -+ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); - if (tac_fd < 0) { - _pam_log(LOG_ERR, "%s: connection to srv %d failed", __FUNCTION__, srv_i); - continue; -@@ -322,8 +323,9 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, +@@ -326,7 +323,7 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, } status = PAM_SUCCESS; communicating = 0; - active_server.addr = tac_srv[srv_i].addr; -- active_server.key = tac_srv[srv_i].key; + active_server.addr = tac_srv[srv_i].addr; -+ /* copy secret to key */ -+ snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); + /* copy secret to key */ + snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); - if (ctrl & PAM_TAC_DEBUG) - syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); -@@ -537,8 +539,9 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, - syslog (LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)" +@@ -543,7 +540,7 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, , __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); -- if ((user = _pam_get_user(pamh)) == NULL) + if ((user = _pam_get_user(pamh)) == NULL) { - return PAM_USER_UNKNOWN; -+ if ((user = _pam_get_user(pamh)) == NULL) { + return PAM_USER_UNKNOWN; -+ } + } if (ctrl & PAM_TAC_DEBUG) - syslog(LOG_DEBUG, "%s: username obtained [%s]", __FUNCTION__, user); -@@ -579,11 +582,13 @@ 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, tac_source_addr, tac_timeout, __vrfname); -+ tac_fd = tac_connect_single(active_server.addr, active_server.key, &tac_source_addr, tac_timeout, __vrfname); +@@ -589,7 +586,7 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, if(tac_fd < 0) { _pam_log (LOG_ERR, "TACACS+ server unavailable"); -- if(arep.msg != NULL) + if(arep.msg != NULL) { - free (arep.msg); -+ if(arep.msg != NULL) { + free (arep.msg); -+ } -+ - return PAM_AUTH_ERR; - } - -@@ -664,7 +669,6 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, - free (arep.msg); - - close(tac_fd); -- - return status; - } /* pam_sm_acct_mgmt */ + } -@@ -725,9 +729,10 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + return PAM_AUTH_ERR; +@@ -732,9 +729,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, syslog(LOG_DEBUG, "%s(flags=%d, argc=%d)", __func__, flags, argc); if ( (pam_get_item(pamh, PAM_OLDAUTHTOK, &pam_pass) == PAM_SUCCESS) - && (pam_pass != NULL) ) { -- if ((pass = strdup(pam_pass)) == NULL) -- return PAM_BUF_ERR; + && (pam_pass != NULL) ) { -+ if ((pass = strdup(pam_pass)) == NULL) { + if ((pass = strdup(pam_pass)) == NULL) { +- return PAM_BUF_ERR; + return PAM_BUF_ERR; -+ } + } } else { pass = strdup(""); - } -@@ -735,7 +740,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, +@@ -743,7 +740,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if ((user = _pam_get_user(pamh)) == NULL) { if(pass) { free(pass); - } + } -+ + return PAM_USER_UNKNOWN; } - -@@ -762,7 +768,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, tac_source_addr, tac_timeout, __vrfname); -+ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); - if (tac_fd < 0) { - _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i); - continue; -@@ -819,8 +825,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, +@@ -828,7 +825,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, status = PAM_SUCCESS; communicating = 0; - active_server.addr = tac_srv[srv_i].addr; -- active_server.key = tac_srv[srv_i].key; + active_server.addr = tac_srv[srv_i].addr; -+ /* copy secret to key */ -+ snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); + /* copy secret to key */ + snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); - if (ctrl & PAM_TAC_DEBUG) - syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); diff --git a/pam_tacplus.h b/pam_tacplus.h index bc71b54..e7b30f7 100644 --- a/pam_tacplus.h @@ -272,60 +204,32 @@ index bc71b54..e7b30f7 100644 #define PAM_TAC_VMAJ 1 #define PAM_TAC_VMIN 3 diff --git a/support.c b/support.c -index be1f21b..2cc85f4 100644 +index 3d38f24..6b2e72d 100644 --- a/support.c +++ b/support.c -@@ -29,16 +29,26 @@ +@@ -29,6 +29,7 @@ #include #include +#include /* isspace() */ -+/* tacacs server information */ + /* tacacs server information */ tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; -+struct addrinfo tac_srv_addr[TAC_PLUS_MAXSERVERS]; -+struct sockaddr tac_sock_addr[TAC_PLUS_MAXSERVERS]; -+struct sockaddr_in6 tac_sock6_addr[TAC_PLUS_MAXSERVERS]; -+ - int tac_srv_no = 0; - - char tac_service[64]; +@@ -42,7 +43,7 @@ char tac_service[64]; char tac_protocol[64]; char tac_prompt[64]; char *__vrfname=NULL; -char tac_source_ip[64]; --struct addrinfo *tac_source_addr = NULL; +char tac_source_ip[64]; -+ -+/* source address */ -+struct addrinfo tac_source_addr; -+struct sockaddr tac_source_sock_addr; -+struct sockaddr_in6 tac_source_sock6_addr; - void _pam_log(int err, const char *format,...) { - char msg[256]; -@@ -172,159 +182,236 @@ int tacacs_get_password (pam_handle_t * pamh, int flags + /* source address */ + struct addrinfo tac_source_addr; +@@ -181,12 +182,33 @@ int tacacs_get_password (pam_handle_t * pamh, int flags return PAM_SUCCESS; } - --int _pam_parse (int argc, const char **argv) { -- int ctrl = 0; -- const char *current_secret = NULL; -- -- /* otherwise the list will grow with each call */ -- memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); -- tac_srv_no = 0; -- -- tac_service[0] = 0; -- tac_protocol[0] = 0; -- tac_prompt[0] = 0; -- tac_login[0] = 0; -- tac_source_ip[0] = 0; - -- if (tac_source_addr != NULL) { -- freeaddrinfo(tac_source_addr); -- tac_source_addr = NULL; ++ +/* + * Set tacacs server addrinfo. + */ @@ -336,7 +240,7 @@ index be1f21b..2cc85f4 100644 + if (server->ai_family == AF_INET6) { + tac_srv[tac_srv_no].addr->ai_addr = (struct sockaddr *)&(tac_sock6_addr[tac_srv_no]); + memcpy(tac_srv[tac_srv_no].addr->ai_addr, server->ai_addr, sizeof(struct sockaddr_in6)); - } ++ } + else { + tac_srv[tac_srv_no].addr->ai_addr = &(tac_sock_addr[tac_srv_no]); + memcpy(tac_srv[tac_srv_no].addr->ai_addr, server->ai_addr, sizeof(struct sockaddr)); @@ -344,156 +248,59 @@ index be1f21b..2cc85f4 100644 + + tac_srv[tac_srv_no].addr->ai_canonname = NULL; + tac_srv[tac_srv_no].addr->ai_next = NULL; -+} - -- for (ctrl = 0; argc-- > 0; ++argv) { -- if (!strcmp (*argv, "debug")) { /* all */ -- ctrl |= PAM_TAC_DEBUG; -- } else if (!strcmp (*argv, "use_first_pass")) { -- ctrl |= PAM_TAC_USE_FIRST_PASS; -- } else if (!strcmp (*argv, "try_first_pass")) { -- ctrl |= PAM_TAC_TRY_FIRST_PASS; -- } else if (!strncmp (*argv, "service=", 8)) { /* author & acct */ -- xstrcpy (tac_service, *argv + 8, sizeof(tac_service)); -- } else if (!strncmp (*argv, "protocol=", 9)) { /* author & acct */ -- xstrcpy (tac_protocol, *argv + 9, sizeof(tac_protocol)); -- } else if (!strncmp (*argv, "prompt=", 7)) { /* authentication */ -- xstrcpy (tac_prompt, *argv + 7, sizeof(tac_prompt)); -- /* Replace _ with space */ -- int chr; -- for (chr = 0; chr < strlen(tac_prompt); chr++) { -- if (tac_prompt[chr] == '_') { -- tac_prompt[chr] = ' '; -- } -- } -- } else if (!strncmp (*argv, "login=", 6)) { -- xstrcpy (tac_login, *argv + 6, sizeof(tac_login)); -- } else if (!strcmp (*argv, "acct_all")) { -- ctrl |= PAM_TAC_ACCT; -- } else if (!strncmp (*argv, "server=", 7)) { /* authen & acct */ -- if(tac_srv_no < TAC_PLUS_MAXSERVERS) { -- struct addrinfo hints, *servers, *server; -- int rv; -- char *close_bracket, *server_name, *port, server_buf[256]; -- -- memset(&hints, 0, sizeof hints); -- hints.ai_family = AF_UNSPEC; /* use IPv4 or IPv6, whichever */ -- hints.ai_socktype = SOCK_STREAM; -- -- if (strlen(*argv + 7) >= sizeof(server_buf)) { -- _pam_log(LOG_ERR, "server address too long, sorry"); -- continue; -- } -- strcpy(server_buf, *argv + 7); -- -- if (*server_buf == '[' && (close_bracket = strchr(server_buf, ']')) != NULL) { /* Check for URI syntax */ -- server_name = server_buf + 1; -- port = strrchr(close_bracket, ':'); -- *close_bracket = '\0'; -- } else { /* Fall back to traditional syntax */ -- server_name = server_buf; -- port = strrchr(server_buf, ':'); -- } -- if (port != NULL) { -- *port = '\0'; -- port++; -- } -- if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { -- for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { -- tac_srv[tac_srv_no].addr = server; -- tac_srv[tac_srv_no].key = current_secret; -- tac_srv_no++; -- } -- } else { -- _pam_log (LOG_ERR, -- "skip invalid server: %s (getaddrinfo: %s)", -- server_name, gai_strerror(rv)); -- } -- } else { -- _pam_log(LOG_ERR, "maximum number of servers (%d) exceeded, skipping", -- TAC_PLUS_MAXSERVERS); -- } -- } else if (!strncmp (*argv, "secret=", 7)) { -- int i; -- -- current_secret = *argv + 7; /* points right into argv (which is const) */ -- -- /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ -- for(i = tac_srv_no-1; i >= 0; i--) { -- if (tac_srv[i].key != NULL) -- break; -- -- tac_srv[i].key = current_secret; -- } -- } else if (!strncmp (*argv, "timeout=", 8)) { -- /* FIXME atoi() doesn't handle invalid numeric strings well */ -- tac_timeout = atoi(*argv + 8); -- -- if (tac_timeout < 0) { -- tac_timeout = 0; -- } else { -- tac_readtimeout_enable = 1; -- } -- } else if(!strncmp(*argv, "vrf=", 4)) { -- __vrfname = strdup(*argv + 4); -- } 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); -- } -- } -- -- if (ctrl & PAM_TAC_DEBUG) { -- int n; -- -- _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); -+/* set source ip address for the outgoing tacacs packets */ -+void set_source_ip(const char *tac_source_ip) { - -- for(n = 0; n < tac_srv_no; n++) { -- _pam_log(LOG_DEBUG, "server[%d] { addr=%s, key='%c*****' }", n, tac_ntop(tac_srv[n].addr->ai_addr), tac_srv[n].key[0]); -- } -+ struct addrinfo hints, *source_address; -+ int rv; - -- _pam_log(LOG_DEBUG, "tac_service='%s'", tac_service); -- _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); -+ /* set the source ip address for the tacacs packets */ -+ 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 { -+ memcpy(&tac_source_addr, source_address, sizeof(struct addrinfo)); -+ -+ if (source_address->ai_family == AF_INET6) { -+ tac_source_addr.ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); -+ memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); -+ } -+ else { -+ tac_source_addr.ai_addr = &(tac_source_sock_addr); -+ memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); -+ } -+ -+ -+ freeaddrinfo(source_address); -+ _pam_log(LOG_DEBUG, "source ip is set"); + } ++ + /* set source ip address for the outgoing tacacs packets */ + void set_source_ip(const char *tac_source_ip) { ++ + struct addrinfo hints, *source_address; + int rv; ++ + /* set the source ip address for the tacacs packets */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; +@@ -195,163 +217,200 @@ void set_source_ip(const char *tac_source_ip) { + &source_address)) != 0) { + _pam_log(LOG_ERR, "error setting the source ip information"); + } else { +- memcpy(&tac_source_addr, source_address, sizeof(struct addrinfo)); +- if (source_address->ai_family == AF_INET6) { +- tac_source_addr.ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); +- memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); +- } +- else { +- tac_source_addr.ai_addr = &(tac_source_sock_addr); +- memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); +- } +- +- ++ memcpy(&tac_source_addr, source_address, sizeof(struct addrinfo)); ++ ++ if (source_address->ai_family == AF_INET6) { ++ tac_source_addr.ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); ++ memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); ++ } ++ else { ++ tac_source_addr.ai_addr = &(tac_source_sock_addr); ++ memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); ++ } ++ + freeaddrinfo(source_address); + _pam_log(LOG_DEBUG, "source ip is set"); } + } +-int _pam_parse (int argc, const char **argv) { +- int ctrl = 0; +- char current_secret[256]; +- memset(current_secret, 0, sizeof(current_secret)); - -- return ctrl; --} /* _pam_parse */ +- /* otherwise the list will grow with each call */ +- memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); +- tac_srv_no = 0; - --/* set source ip address for the outgoing tacacs packets */ --void set_source_ip(const char *tac_source_ip, -- struct addrinfo **source_address) { -+} +- tac_service[0] = 0; +- tac_protocol[0] = 0; +- tac_prompt[0] = 0; + +/* + * Parse one arguments. @@ -557,24 +364,15 @@ index be1f21b..2cc85f4 100644 + } + if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { + for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { -+ /* set server address with allocate memory */ ++ /* set server address with allocate memory */ + set_tacacs_server_addr(tac_srv_no, server); - -- struct addrinfo hints; -- int rv; ++ + /* copy secret to key */ + snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); + tac_srv_no++; + } - -- /* set the source ip address for the tacacs packets */ -- 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"); -+ /* release servers memory */ ++ ++ /* release servers memory */ + freeaddrinfo(servers); + } else { + _pam_log (LOG_ERR, @@ -614,10 +412,9 @@ index be1f21b..2cc85f4 100644 + /* source ip for the packets */ + strncpy (tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); + set_source_ip (tac_source_ip); - } else { -- _pam_log(LOG_DEBUG, "source ip is set"); ++ } else { + _pam_log (LOG_WARNING, "unrecognized option: %s", arg); - } ++ } + + return ctrl; +} /* _pam_parse_arg */ @@ -648,7 +445,7 @@ index be1f21b..2cc85f4 100644 + + fclose(config_file); + return ctrl; - } ++} +int _pam_parse (int argc, const char **argv) { + int ctrl = 0; + char current_secret[256]; @@ -661,12 +458,129 @@ index be1f21b..2cc85f4 100644 + tac_service[0] = 0; + tac_protocol[0] = 0; + tac_prompt[0] = 0; -+ tac_login[0] = 0; -+ tac_source_ip[0] = 0; -+ + tac_login[0] = 0; + tac_source_ip[0] = 0; + +- if (tac_source_addr != NULL) { +- freeaddrinfo(tac_source_addr); +- tac_source_addr = NULL; + for (ctrl = 0; argc-- > 0; ++argv) { + ctrl |= _pam_parse_arg(*argv, current_secret, sizeof(current_secret)); -+ } + } +- +- for (ctrl = 0; argc-- > 0; ++argv) { +- if (!strcmp (*argv, "debug")) { /* all */ +- ctrl |= PAM_TAC_DEBUG; +- } else if (!strcmp (*argv, "use_first_pass")) { +- ctrl |= PAM_TAC_USE_FIRST_PASS; +- } else if (!strcmp (*argv, "try_first_pass")) { +- ctrl |= PAM_TAC_TRY_FIRST_PASS; +- } else if (!strncmp (*argv, "service=", 8)) { /* author & acct */ +- xstrcpy (tac_service, *argv + 8, sizeof(tac_service)); +- } else if (!strncmp (*argv, "protocol=", 9)) { /* author & acct */ +- xstrcpy (tac_protocol, *argv + 9, sizeof(tac_protocol)); +- } else if (!strncmp (*argv, "prompt=", 7)) { /* authentication */ +- xstrcpy (tac_prompt, *argv + 7, sizeof(tac_prompt)); +- /* Replace _ with space */ +- int chr; +- for (chr = 0; chr < strlen(tac_prompt); chr++) { +- if (tac_prompt[chr] == '_') { +- tac_prompt[chr] = ' '; +- } +- } +- } else if (!strncmp (*argv, "login=", 6)) { +- xstrcpy (tac_login, *argv + 6, sizeof(tac_login)); +- } else if (!strcmp (*argv, "acct_all")) { +- ctrl |= PAM_TAC_ACCT; +- } else if (!strncmp (*argv, "server=", 7)) { /* authen & acct */ +- if(tac_srv_no < TAC_PLUS_MAXSERVERS) { +- struct addrinfo hints, *servers, *server; +- int rv; +- char *close_bracket, *server_name, *port, server_buf[256]; +- +- memset(&hints, 0, sizeof hints); +- hints.ai_family = AF_UNSPEC; /* use IPv4 or IPv6, whichever */ +- hints.ai_socktype = SOCK_STREAM; +- +- if (strlen(*argv + 7) >= sizeof(server_buf)) { +- _pam_log(LOG_ERR, "server address too long, sorry"); +- continue; +- } +- strcpy(server_buf, *argv + 7); +- +- if (*server_buf == '[' && (close_bracket = strchr(server_buf, ']')) != NULL) { /* Check for URI syntax */ +- server_name = server_buf + 1; +- port = strrchr(close_bracket, ':'); +- *close_bracket = '\0'; +- } else { /* Fall back to traditional syntax */ +- server_name = server_buf; +- port = strrchr(server_buf, ':'); +- } +- if (port != NULL) { +- *port = '\0'; +- port++; +- } +- if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { +- for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { +- /* set server address with allocate memory */ +- set_tacacs_server_addr(tac_srv_no, server); +- +- /* copy secret to key */ +- snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); +- tac_srv_no++; +- } +- +- /* release servers memory */ +- freeaddrinfo(servers); +- } else { +- _pam_log (LOG_ERR, +- "skip invalid server: %s (getaddrinfo: %s)", +- server_name, gai_strerror(rv)); +- } +- } else { +- _pam_log(LOG_ERR, "maximum number of servers (%d) exceeded, skipping", +- TAC_PLUS_MAXSERVERS); +- } +- } else if (!strncmp (*argv, "secret=", 7)) { +- int i; +- +- /* points right into arg (which is const) */ +- snprintf(current_secret, sizeof(current_secret), "%s", arg + 7); +- +- /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ +- for(i = tac_srv_no-1; i >= 0; i--) { +- if (tac_srv[i].key != NULL) +- break; +- +- /* copy secret to key */ +- snprintf(tac_srv[i].key, sizeof(tac_srv[i].key), "%s", current_secret); +- } +- } else if (!strncmp (*argv, "timeout=", 8)) { +- /* FIXME atoi() doesn't handle invalid numeric strings well */ +- tac_timeout = atoi(*argv + 8); +- +- if (tac_timeout < 0) { +- tac_timeout = 0; +- } else { +- tac_readtimeout_enable = 1; +- } +- } else if(!strncmp(*argv, "vrf=", 4)) { +- __vrfname = strdup(*argv + 4); +- } 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); +- } else { +- _pam_log (LOG_WARNING, "unrecognized option: %s", *argv); +- } +- } +- +- if (ctrl & PAM_TAC_DEBUG) { +- int n; +- +- _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); +- +- for(n = 0; n < tac_srv_no; n++) { + + if (ctrl & PAM_TAC_DEBUG) { + int n; @@ -674,23 +588,33 @@ index be1f21b..2cc85f4 100644 + _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); + + for(n = 0; n < tac_srv_no; n++) { -+ _pam_log(LOG_DEBUG, "server[%d] { addr=%s, key='%c*****' }", n, tac_ntop(tac_srv[n].addr->ai_addr), tac_srv[n].key[0]); + _pam_log(LOG_DEBUG, "server[%d] { addr=%s, key='%c*****' }", n, tac_ntop(tac_srv[n].addr->ai_addr), tac_srv[n].key[0]); +- } +- +- _pam_log(LOG_DEBUG, "tac_service='%s'", tac_service); +- _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_service='%s'", tac_service); + _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); + _pam_log(LOG_DEBUG, "tac_source_ip='%s'", tac_source_ip); +- } +- +- return ctrl; +-} /* _pam_parse */ + } + + return ctrl; +} /* _pam_parse */ diff --git a/support.h b/support.h -index b1faf43..bdb60b4 100644 +index feadbf5..bdb60b4 100644 --- a/support.h +++ b/support.h -@@ -24,20 +24,28 @@ +@@ -24,15 +24,23 @@ #include "libtac.h" @@ -705,9 +629,8 @@ index b1faf43..bdb60b4 100644 typedef struct { - struct addrinfo *addr; -- const char *key; + struct addrinfo *addr; -+ char key[256]; + char key[256]; } tacplus_server_t; extern tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; @@ -717,12 +640,6 @@ index b1faf43..bdb60b4 100644 extern char tac_service[64]; extern char tac_protocol[64]; - extern char tac_prompt[64]; --extern struct addrinfo *tac_source_addr; -+extern struct addrinfo tac_source_addr; - - int _pam_parse (int, const char **); - unsigned long _resolve_name (char *); @@ -48,7 +56,12 @@ void _pam_log (int, const char *, ...); void *_xcalloc (size_t); char *_pam_get_user(pam_handle_t *); diff --git a/src/tacacs/pam/Makefile b/src/tacacs/pam/Makefile index f942a5b4daa5..e6520e6ef479 100644 --- a/src/tacacs/pam/Makefile +++ b/src/tacacs/pam/Makefile @@ -20,7 +20,8 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : git apply ../0004-management-vrf-support.patch git apply ../0005-pam-Modify-parsing-of-IP-address-and-port-number-to-.patch git apply ../0006-Add-support-for-source-ip-address.patch - git apply ../0007-Add-TACACS-support-library-and-fix-memory-leak-issue.patch + git apply ../0007-Fix-memory-leak-when-parse-configuration.patch + git apply ../0008-Extract-tacacs-support-functions-into-library.patch dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) popd From bb9fec39c53ee1c5343821d1083d52017c9ecc4a Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Wed, 29 Sep 2021 15:35:36 +0800 Subject: [PATCH 03/12] Add setting flag for authorization and accounting. --- ...lag-for-authorization-and-accounting.patch | 60 +++++++++++++++++++ src/tacacs/pam/Makefile | 1 + 2 files changed, 61 insertions(+) create mode 100644 src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch diff --git a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch new file mode 100644 index 000000000000..0e4bd8e5ac7b --- /dev/null +++ b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch @@ -0,0 +1,60 @@ +From 73ac227e4924027d46e39c4f657d71aae5aa05b8 Mon Sep 17 00:00:00 2001 +From: liuh-80 <58683130+liuh-80@users.noreply.github.com> +Date: Wed, 29 Sep 2021 15:32:10 +0800 +Subject: [PATCH 3/3] Add setting flag for authorization and accounting. + +--- + support.c | 8 ++++++++ + support.h | 10 +++++++++- + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/support.c b/support.c +index 6b2e72d..e94c79b 100644 +--- a/support.c ++++ b/support.c +@@ -343,6 +343,14 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b + /* source ip for the packets */ + strncpy (tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); + set_source_ip (tac_source_ip); ++ } else if (!strcmp (arg, "local_accounting")) { ++ ctrl |= ACCOUNTING_FLAG_LOCAL; ++ } else if (!strcmp (arg, "tacacs_accounting")) { ++ ctrl |= ACCOUNTING_FLAG_TACACS; ++ } else if (!strcmp (arg, "local_authorization")) { ++ ctrl |= AUTHORIZATION_FLAG_LOCAL; ++ } else if (!strcmp (arg, "tacacs_authorization")) { ++ ctrl |= AUTHORIZATION_FLAG_TACACS; + } else { + _pam_log (LOG_WARNING, "unrecognized option: %s", arg); + } +diff --git a/support.h b/support.h +index bdb60b4..5fce87e 100644 +--- a/support.h ++++ b/support.h +@@ -32,6 +32,14 @@ + #define PAM_TAC_USE_FIRST_PASS 0x04 + #define PAM_TAC_TRY_FIRST_PASS 0x08 + ++/* accounting setting flag */ ++#define ACCOUNTING_FLAG_LOCAL 0x10 ++#define ACCOUNTING_FLAG_TACACS 0x20 ++ ++/* authorization setting flag */ ++#define AUTHORIZATION_FLAG_LOCAL 0x40 ++#define AUTHORIZATION_FLAG_TACACS 0x80 ++ + typedef struct { + struct addrinfo *addr; + char key[256]; +@@ -45,7 +53,7 @@ extern char *__vrfname; + extern char tac_service[64]; + extern char tac_protocol[64]; + extern char tac_prompt[64]; +-extern struct addrinfo tac_source_addr; ++extern struct addrinfo tac_source_addr; + + int _pam_parse (int, const char **); + unsigned long _resolve_name (char *); +-- +2.17.1.windows.2 + diff --git a/src/tacacs/pam/Makefile b/src/tacacs/pam/Makefile index e6520e6ef479..cc3a8fcbca41 100644 --- a/src/tacacs/pam/Makefile +++ b/src/tacacs/pam/Makefile @@ -22,6 +22,7 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : git apply ../0006-Add-support-for-source-ip-address.patch git apply ../0007-Fix-memory-leak-when-parse-configuration.patch git apply ../0008-Extract-tacacs-support-functions-into-library.patch + git apply ../0009-Add-setting-flag-for-authorization-and-accounting.patch dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $(SONIC_DPKG_ADMINDIR) popd From 7022bb35ed9c138cc67f2507426e3f8672994e25 Mon Sep 17 00:00:00 2001 From: liuh Date: Fri, 1 Oct 2021 18:09:21 +0800 Subject: [PATCH 04/12] Fix source address code issue.. --- ...memory-leak-when-parse-configuration.patch | 315 +++++++++--------- ...acacs-support-functions-into-library.patch | 250 +++----------- ...lag-for-authorization-and-accounting.patch | 73 ++-- 3 files changed, 247 insertions(+), 391 deletions(-) diff --git a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch index e83a82971344..85bb96bd9959 100644 --- a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch +++ b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch @@ -1,160 +1,145 @@ -From 95f09ea41d7179bbc321fad476cfe47cbdabdcab Mon Sep 17 00:00:00 2001 -From: liuh-80 <58683130+liuh-80@users.noreply.github.com> -Date: Fri, 10 Sep 2021 17:27:05 +0800 -Subject: [PATCH 1/2] Fix memory leak when parse configuration. +From a8b8c662b1520cbf0aafffb65ae108b4aa1bb73b Mon Sep 17 00:00:00 2001 +From: liuh +Date: Fri, 1 Oct 2021 17:40:14 +0800 +Subject: [PATCH 1/3] Fix memory leak when parse configuration. --- - pam_tacplus.c | 34 +++++++++++++-------- - support.c | 81 ++++++++++++++++++++++++++++++++++----------------- - support.h | 4 +-- - 3 files changed, 78 insertions(+), 41 deletions(-) + pam_tacplus.c | 28 +++++------- + support.c | 115 ++++++++++++++++++++++++++++++-------------------- + support.h | 6 +-- + 3 files changed, 83 insertions(+), 66 deletions(-) diff --git a/pam_tacplus.c b/pam_tacplus.c -index 9fc6be7..8a93c9b 100644 +index 4a6f714..d062359 100644 --- a/pam_tacplus.c +++ b/pam_tacplus.c -@@ -138,8 +138,10 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, +@@ -138,10 +138,8 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, syslog(LOG_DEBUG, "%s: tac_srv_no=%d", __FUNCTION__, tac_srv_no); } -- if ((user = _pam_get_user(pamh)) == NULL) -+ if ((user = _pam_get_user(pamh)) == NULL) { +- if ((user = _pam_get_user(pamh)) == NULL) { ++ if ((user = _pam_get_user(pamh)) == NULL) return PAM_USER_UNKNOWN; -+ } -+ +- } +- if (ctrl & PAM_TAC_DEBUG) syslog(LOG_DEBUG, "%s: username [%s] obtained", __FUNCTION__, user); -@@ -177,7 +179,7 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, +@@ -179,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, tac_source_addr, tac_timeout, __vrfname); -+ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); +- tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); ++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, tac_source_addr, tac_timeout, __vrfname); if (tac_fd < 0) { _pam_log(LOG_WARNING, "%s: error sending %s (fd)", __FUNCTION__, typemsg); -@@ -208,6 +210,7 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, +@@ -210,7 +208,6 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, signal(SIGCHLD, SIG_DFL); signal(SIGHUP, SIG_DFL); } -+ +- return status; } -@@ -238,8 +241,9 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, +@@ -241,9 +238,8 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, syslog(LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)", __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); -- if ((user = _pam_get_user(pamh)) == NULL) -+ if ((user = _pam_get_user(pamh)) == NULL) { +- if ((user = _pam_get_user(pamh)) == NULL) { ++ if ((user = _pam_get_user(pamh)) == NULL) return PAM_USER_UNKNOWN; -+ } +- } if (ctrl & PAM_TAC_DEBUG) syslog(LOG_DEBUG, "%s: user [%s] obtained", __FUNCTION__, user); -@@ -276,7 +280,7 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, +@@ -280,7 +276,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, tac_source_addr, tac_timeout, __vrfname); -+ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); +- tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); ++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, tac_source_addr, tac_timeout, __vrfname); if (tac_fd < 0) { _pam_log(LOG_ERR, "%s: connection to srv %d failed", __FUNCTION__, srv_i); continue; -@@ -323,7 +327,8 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, - status = PAM_SUCCESS; - communicating = 0; - active_server.addr = tac_srv[srv_i].addr; -- active_server.key = tac_srv[srv_i].key; -+ /* copy secret to key */ -+ snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); - - if (ctrl & PAM_TAC_DEBUG) - syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); -@@ -537,8 +542,9 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, +@@ -542,9 +538,8 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, syslog (LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)" , __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); -- if ((user = _pam_get_user(pamh)) == NULL) -+ if ((user = _pam_get_user(pamh)) == NULL) { +- if ((user = _pam_get_user(pamh)) == NULL) { ++ if ((user = _pam_get_user(pamh)) == NULL) return PAM_USER_UNKNOWN; -+ } +- } if (ctrl & PAM_TAC_DEBUG) syslog(LOG_DEBUG, "%s: username obtained [%s]", __FUNCTION__, user); -@@ -579,11 +585,13 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, +@@ -585,13 +580,11 @@ 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, tac_source_addr, tac_timeout, __vrfname); -+ tac_fd = tac_connect_single(active_server.addr, active_server.key, &tac_source_addr, tac_timeout, __vrfname); +- tac_fd = tac_connect_single(active_server.addr, active_server.key, &tac_source_addr, tac_timeout, __vrfname); ++ tac_fd = tac_connect_single(active_server.addr, active_server.key, tac_source_addr, tac_timeout, __vrfname); if(tac_fd < 0) { _pam_log (LOG_ERR, "TACACS+ server unavailable"); -- if(arep.msg != NULL) -+ if(arep.msg != NULL) { +- if(arep.msg != NULL) { ++ if(arep.msg != NULL) free (arep.msg); -+ } -+ +- } +- return PAM_AUTH_ERR; } -@@ -664,7 +672,6 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, +@@ -672,6 +665,7 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, free (arep.msg); close(tac_fd); -- ++ return status; } /* pam_sm_acct_mgmt */ -@@ -726,8 +733,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, +@@ -733,9 +727,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if ( (pam_get_item(pamh, PAM_OLDAUTHTOK, &pam_pass) == PAM_SUCCESS) && (pam_pass != NULL) ) { -- if ((pass = strdup(pam_pass)) == NULL) -+ if ((pass = strdup(pam_pass)) == NULL) { +- if ((pass = strdup(pam_pass)) == NULL) { ++ if ((pass = strdup(pam_pass)) == NULL) return PAM_BUF_ERR; -+ } +- } } else { pass = strdup(""); } -@@ -736,6 +744,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, +@@ -744,7 +737,6 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, if(pass) { free(pass); } -+ +- return PAM_USER_UNKNOWN; } -@@ -762,7 +771,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, +@@ -771,7 +763,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, tac_source_addr, tac_timeout, __vrfname); -+ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); +- tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, &tac_source_addr, tac_timeout, __vrfname); ++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, tac_source_addr, tac_timeout, __vrfname); if (tac_fd < 0) { _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i); continue; -@@ -820,7 +829,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, - communicating = 0; - - active_server.addr = tac_srv[srv_i].addr; -- active_server.key = tac_srv[srv_i].key; -+ /* copy secret to key */ -+ snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); - - if (ctrl & PAM_TAC_DEBUG) - syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); diff --git a/support.c b/support.c -index be1f21b..3d38f24 100644 +index d2ed770..ce3f18d 100644 --- a/support.c +++ b/support.c -@@ -30,7 +30,12 @@ +@@ -30,23 +30,24 @@ #include #include +-/* tacacs server information */ +/* tacacs server information */ tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; +-struct addrinfo tac_srv_addr[TAC_PLUS_MAXSERVERS]; +-struct sockaddr tac_sock_addr[TAC_PLUS_MAXSERVERS]; +-struct sockaddr_in6 tac_sock6_addr[TAC_PLUS_MAXSERVERS]; +- +struct addrinfo tac_srv_addr[TAC_PLUS_MAXSERVERS]; +struct sockaddr tac_sock_addr[TAC_PLUS_MAXSERVERS]; +struct sockaddr_in6 tac_sock6_addr[TAC_PLUS_MAXSERVERS]; @@ -162,28 +147,80 @@ index be1f21b..3d38f24 100644 int tac_srv_no = 0; char tac_service[64]; -@@ -38,7 +43,11 @@ char tac_protocol[64]; + char tac_protocol[64]; char tac_prompt[64]; char *__vrfname=NULL; - char tac_source_ip[64]; --struct addrinfo *tac_source_addr = NULL; +-char tac_source_ip[64]; +- ++char tac_source_ip[64]; + -+/* source address */ -+struct addrinfo tac_source_addr; + /* source address */ +-struct addrinfo tac_source_addr; +-struct sockaddr tac_source_sock_addr; ++struct addrinfo *tac_source_addr=NULL; ++struct addrinfo tac_source_address; +struct sockaddr tac_source_sock_addr; -+struct sockaddr_in6 tac_source_sock6_addr; + struct sockaddr_in6 tac_source_sock6_addr; void _pam_log(int err, const char *format,...) { - char msg[256]; -@@ -173,9 +182,38 @@ int tacacs_get_password (pam_handle_t * pamh, int flags +@@ -181,35 +182,59 @@ int tacacs_get_password (pam_handle_t * pamh, int flags + return PAM_SUCCESS; } - +- +-} +-/* set source ip address for the outgoing tacacs packets */ +-void set_source_ip(const char *tac_source_ip) { +- struct addrinfo hints, *source_address; +- int rv; +- /* set the source ip address for the tacacs packets */ +- 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 { +- memcpy(&tac_source_addr, source_address, sizeof(struct addrinfo)); +- if (source_address->ai_family == AF_INET6) { +- tac_source_addr.ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); +- memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); +- } +- else { +- tac_source_addr.ai_addr = &(tac_source_sock_addr); +- memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); +- } +- +- +- freeaddrinfo(source_address); +- _pam_log(LOG_DEBUG, "source ip is set"); ++ ++/* ++ * Set tacacs server addrinfo. ++ */ ++void set_tacacs_server_addr(int tac_srv_no, struct addrinfo* server) { ++ tac_srv[tac_srv_no].addr = &(tac_srv_addr[tac_srv_no]); ++ memcpy(tac_srv[tac_srv_no].addr, server, sizeof(struct addrinfo)); ++ ++ if (server->ai_family == AF_INET6) { ++ tac_srv[tac_srv_no].addr->ai_addr = (struct sockaddr *)&(tac_sock6_addr[tac_srv_no]); ++ memcpy(tac_srv[tac_srv_no].addr->ai_addr, server->ai_addr, sizeof(struct sockaddr_in6)); ++ } ++ else { ++ tac_srv[tac_srv_no].addr->ai_addr = &(tac_sock_addr[tac_srv_no]); ++ memcpy(tac_srv[tac_srv_no].addr->ai_addr, server->ai_addr, sizeof(struct sockaddr)); + } ++ ++ tac_srv[tac_srv_no].addr->ai_canonname = NULL; ++ tac_srv[tac_srv_no].addr->ai_next = NULL; +} ++ +/* set source ip address for the outgoing tacacs packets */ +void set_source_ip(const char *tac_source_ip) { ++ + struct addrinfo hints, *source_address; + int rv; ++ + /* set the source ip address for the tacacs packets */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; @@ -192,35 +229,36 @@ index be1f21b..3d38f24 100644 + &source_address)) != 0) { + _pam_log(LOG_ERR, "error setting the source ip information"); + } else { -+ memcpy(&tac_source_addr, source_address, sizeof(struct addrinfo)); -+ if (source_address->ai_family == AF_INET6) { -+ tac_source_addr.ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); -+ memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); -+ } -+ else { -+ tac_source_addr.ai_addr = &(tac_source_sock_addr); -+ memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); -+ } -+ -+ ++ tac_source_addr = &tac_source_address; ++ memcpy(tac_source_addr, source_address, sizeof(struct addrinfo)); ++ ++ if (source_address->ai_family == AF_INET6) { ++ tac_source_addr->ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); ++ memcpy(tac_source_addr->ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); ++ } ++ else { ++ tac_source_addr->ai_addr = &(tac_source_sock_addr); ++ memcpy(tac_source_addr->ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); ++ } ++ ++ + freeaddrinfo(source_address); + _pam_log(LOG_DEBUG, "source ip is set"); + } -+} + } ++ int _pam_parse (int argc, const char **argv) { int ctrl = 0; -- const char *current_secret = NULL; -+ char current_secret[256]; -+ memset(current_secret, 0, sizeof(current_secret)); - - /* otherwise the list will grow with each call */ - memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); -@@ -246,10 +284,16 @@ int _pam_parse (int argc, const char **argv) { + char current_secret[256]; +@@ -284,11 +309,11 @@ int _pam_parse (int argc, const char **argv) { } if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { -- tac_srv[tac_srv_no].addr = server; -- tac_srv[tac_srv_no].key = current_secret; +- /* set server address with allocate memory */ +- set_tacacs_server_addr(tac_srv_no, server); +- +- /* copy secret to key */ +- snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); + /* set server address with allocate memory */ + set_tacacs_server_addr(tac_srv_no, server); + @@ -228,74 +266,33 @@ index be1f21b..3d38f24 100644 + snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); tac_srv_no++; } -+ -+ /* release servers memory */ -+ freeaddrinfo(servers); - } else { - _pam_log (LOG_ERR, - "skip invalid server: %s (getaddrinfo: %s)", -@@ -262,14 +306,16 @@ int _pam_parse (int argc, const char **argv) { - } else if (!strncmp (*argv, "secret=", 7)) { - int i; - -- current_secret = *argv + 7; /* points right into argv (which is const) */ -+ /* points right into arg (which is const) */ -+ snprintf(current_secret, sizeof(current_secret), "%s", arg + 7); - /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ - for(i = tac_srv_no-1; i >= 0; i--) { - if (tac_srv[i].key != NULL) - break; - -- tac_srv[i].key = current_secret; -+ /* copy secret to key */ -+ snprintf(tac_srv[i].key, sizeof(tac_srv[i].key), "%s", current_secret); +@@ -328,10 +353,10 @@ int _pam_parse (int argc, const char **argv) { } - } else if (!strncmp (*argv, "timeout=", 8)) { - /* FIXME atoi() doesn't handle invalid numeric strings well */ -@@ -284,8 +330,8 @@ int _pam_parse (int argc, const char **argv) { + } else if(!strncmp(*argv, "vrf=", 4)) { __vrfname = strdup(*argv + 4); - } else if (!strncmp (*argv, "source_ip=", strlen("source_ip="))) { - /* source ip for the packets */ +- } 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); -+ strncpy (tac_source_ip, *argv + strlen("source_ip="), sizeof(tac_source_ip)); -+ set_source_ip (tac_source_ip); +- set_source_ip (tac_source_ip); ++ } else if (!strncmp (*argv, "source_ip=", strlen("source_ip="))) { ++ /* source ip for the packets */ ++ strncpy(tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); ++ set_source_ip(tac_source_ip); } else { _pam_log (LOG_WARNING, "unrecognized option: %s", *argv); } -@@ -309,22 +355,3 @@ int _pam_parse (int argc, const char **argv) { - - 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; -- -- /* set the source ip address for the tacacs packets */ -- 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 b1faf43..feadbf5 100644 +index e88463e..097c349 100644 --- a/support.h +++ b/support.h -@@ -28,7 +28,7 @@ +@@ -27,8 +27,8 @@ + #include typedef struct { - struct addrinfo *addr; -- const char *key; +- struct addrinfo *addr; +- char key[256]; ++ struct addrinfo *addr; + char key[256]; } tacplus_server_t; @@ -304,11 +301,11 @@ index b1faf43..feadbf5 100644 extern char tac_service[64]; extern char tac_protocol[64]; extern char tac_prompt[64]; --extern struct addrinfo *tac_source_addr; -+extern struct addrinfo tac_source_addr; +-extern struct addrinfo tac_source_addr; ++extern struct addrinfo *tac_source_addr; int _pam_parse (int, const char **); unsigned long _resolve_name (char *); -- -2.17.1.windows.2 +2.27.0.windows.1 diff --git a/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch index 7ebbe3f6dce7..ee75ea6267de 100644 --- a/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch +++ b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch @@ -1,18 +1,16 @@ -From 8e48036b7379896dbef720401fb084254ffd1966 Mon Sep 17 00:00:00 2001 -From: liuh-80 <58683130+liuh-80@users.noreply.github.com> -Date: Fri, 10 Sep 2021 17:30:18 +0800 -Subject: [PATCH 2/2] Extract tacacs support functions into library +From 45be06055b9040e53d0718f0893ff35571b2c2ad Mon Sep 17 00:00:00 2001 +From: liuh +Date: Fri, 1 Oct 2021 17:45:33 +0800 +Subject: [PATCH 2/3] Extract tacacs support functions into library. --- - Makefile.am | 16 +- - configure.ac | 3 +- - libtacsupport.pc.in | 11 ++ - pam_tacplus.c | 27 ++-- - pam_tacplus.h | 6 - - support.c | 363 +++++++++++++++++++++++++------------------- - support.h | 19 ++- - 7 files changed, 265 insertions(+), 180 deletions(-) - create mode 100644 libtacsupport.pc.in + Makefile.am | 16 ++- + configure.ac | 3 +- + pam_tacplus.c | 5 +- + pam_tacplus.h | 6 - + support.c | 309 ++++++++++++++++++++++++++++---------------------- + support.h | 19 +++- + 6 files changed, 206 insertions(+), 152 deletions(-) diff --git a/Makefile.am b/Makefile.am index c90c582..2ac9ea0 100644 @@ -73,25 +71,8 @@ index f67e2ba..0f917a8 100644 + libtacsupport.pc pam_tacplus.spec]) AC_OUTPUT -diff --git a/libtacsupport.pc.in b/libtacsupport.pc.in -new file mode 100644 -index 0000000..1f12fe0 ---- /dev/null -+++ b/libtacsupport.pc.in -@@ -0,0 +1,11 @@ -+prefix=@prefix@ -+exec_prefix=@exec_prefix@ -+libdir=@libdir@ -+includedir=@includedir@/libtac -+ -+Name: libtacsupport -+Description: TACACS+ support lib implementation -+URL: https://github.com/jeroennijhof/pam_tacplus -+Version: @VERSION@ -+Libs: -L${libdir} -ltacsupport -+Cflags: -I${includedir} diff --git a/pam_tacplus.c b/pam_tacplus.c -index 8a93c9b..916b4d0 100644 +index d062359..9ffbdcf 100644 --- a/pam_tacplus.c +++ b/pam_tacplus.c @@ -51,10 +51,7 @@ @@ -106,86 +87,6 @@ index 8a93c9b..916b4d0 100644 /* Helper functions */ int _pam_send_account(int tac_fd, int type, const char *user, char *tty, -@@ -136,10 +133,10 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, - syslog (LOG_DEBUG, "%s: [%s] called (pam_tacplus v%u.%u.%u)", - __FUNCTION__, typemsg, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); - syslog(LOG_DEBUG, "%s: tac_srv_no=%d", __FUNCTION__, tac_srv_no); -- } -- -+ } -+ - if ((user = _pam_get_user(pamh)) == NULL) { -- return PAM_USER_UNKNOWN; -+ return PAM_USER_UNKNOWN; - } - - -@@ -242,7 +239,7 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, - __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); - - if ((user = _pam_get_user(pamh)) == NULL) { -- return PAM_USER_UNKNOWN; -+ return PAM_USER_UNKNOWN; - } - - if (ctrl & PAM_TAC_DEBUG) -@@ -326,7 +323,7 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, - } - status = PAM_SUCCESS; - communicating = 0; -- active_server.addr = tac_srv[srv_i].addr; -+ active_server.addr = tac_srv[srv_i].addr; - /* copy secret to key */ - snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); - -@@ -543,7 +540,7 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, - , __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); - - if ((user = _pam_get_user(pamh)) == NULL) { -- return PAM_USER_UNKNOWN; -+ return PAM_USER_UNKNOWN; - } - - if (ctrl & PAM_TAC_DEBUG) -@@ -589,7 +586,7 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, - if(tac_fd < 0) { - _pam_log (LOG_ERR, "TACACS+ server unavailable"); - if(arep.msg != NULL) { -- free (arep.msg); -+ free (arep.msg); - } - - return PAM_AUTH_ERR; -@@ -732,9 +729,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, - syslog(LOG_DEBUG, "%s(flags=%d, argc=%d)", __func__, flags, argc); - - if ( (pam_get_item(pamh, PAM_OLDAUTHTOK, &pam_pass) == PAM_SUCCESS) -- && (pam_pass != NULL) ) { -+ && (pam_pass != NULL) ) { - if ((pass = strdup(pam_pass)) == NULL) { -- return PAM_BUF_ERR; -+ return PAM_BUF_ERR; - } - } else { - pass = strdup(""); -@@ -743,7 +740,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, - if ((user = _pam_get_user(pamh)) == NULL) { - if(pass) { - free(pass); -- } -+ } - - return PAM_USER_UNKNOWN; - } -@@ -828,7 +825,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, - status = PAM_SUCCESS; - communicating = 0; - -- active_server.addr = tac_srv[srv_i].addr; -+ active_server.addr = tac_srv[srv_i].addr; - /* copy secret to key */ - snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); - diff --git a/pam_tacplus.h b/pam_tacplus.h index bc71b54..e7b30f7 100644 --- a/pam_tacplus.h @@ -204,7 +105,7 @@ index bc71b54..e7b30f7 100644 #define PAM_TAC_VMAJ 1 #define PAM_TAC_VMIN 3 diff --git a/support.c b/support.c -index 3d38f24..6b2e72d 100644 +index ce3f18d..789533e 100644 --- a/support.c +++ b/support.c @@ -29,6 +29,7 @@ @@ -215,93 +116,12 @@ index 3d38f24..6b2e72d 100644 /* tacacs server information */ tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; -@@ -42,7 +43,7 @@ char tac_service[64]; - char tac_protocol[64]; - char tac_prompt[64]; - char *__vrfname=NULL; --char tac_source_ip[64]; -+char tac_source_ip[64]; - - /* source address */ - struct addrinfo tac_source_addr; -@@ -181,12 +182,33 @@ int tacacs_get_password (pam_handle_t * pamh, int flags - - return PAM_SUCCESS; - } -- -+ -+/* -+ * Set tacacs server addrinfo. -+ */ -+void set_tacacs_server_addr(int tac_srv_no, struct addrinfo* server) { -+ tac_srv[tac_srv_no].addr = &(tac_srv_addr[tac_srv_no]); -+ memcpy(tac_srv[tac_srv_no].addr, server, sizeof(struct addrinfo)); -+ -+ if (server->ai_family == AF_INET6) { -+ tac_srv[tac_srv_no].addr->ai_addr = (struct sockaddr *)&(tac_sock6_addr[tac_srv_no]); -+ memcpy(tac_srv[tac_srv_no].addr->ai_addr, server->ai_addr, sizeof(struct sockaddr_in6)); -+ } -+ else { -+ tac_srv[tac_srv_no].addr->ai_addr = &(tac_sock_addr[tac_srv_no]); -+ memcpy(tac_srv[tac_srv_no].addr->ai_addr, server->ai_addr, sizeof(struct sockaddr)); -+ } -+ -+ tac_srv[tac_srv_no].addr->ai_canonname = NULL; -+ tac_srv[tac_srv_no].addr->ai_next = NULL; - } -+ - /* set source ip address for the outgoing tacacs packets */ - void set_source_ip(const char *tac_source_ip) { -+ - struct addrinfo hints, *source_address; - int rv; -+ - /* set the source ip address for the tacacs packets */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; -@@ -195,163 +217,200 @@ void set_source_ip(const char *tac_source_ip) { - &source_address)) != 0) { - _pam_log(LOG_ERR, "error setting the source ip information"); - } else { -- memcpy(&tac_source_addr, source_address, sizeof(struct addrinfo)); -- if (source_address->ai_family == AF_INET6) { -- tac_source_addr.ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); -- memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); -- } -- else { -- tac_source_addr.ai_addr = &(tac_source_sock_addr); -- memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); -- } -- -- -+ memcpy(&tac_source_addr, source_address, sizeof(struct addrinfo)); -+ -+ if (source_address->ai_family == AF_INET6) { -+ tac_source_addr.ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); -+ memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); -+ } -+ else { -+ tac_source_addr.ai_addr = &(tac_source_sock_addr); -+ memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); -+ } -+ - freeaddrinfo(source_address); - _pam_log(LOG_DEBUG, "source ip is set"); +@@ -235,148 +236,184 @@ void set_source_ip(const char *tac_source_ip) { } } + -int _pam_parse (int argc, const char **argv) { - int ctrl = 0; -- char current_secret[256]; -- memset(current_secret, 0, sizeof(current_secret)); -- -- /* otherwise the list will grow with each call */ -- memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); -- tac_srv_no = 0; -- -- tac_service[0] = 0; -- tac_protocol[0] = 0; -- tac_prompt[0] = 0; -+ +/* + * Parse one arguments. + * Use this method for both: @@ -364,7 +184,7 @@ index 3d38f24..6b2e72d 100644 + } + if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { + for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { -+ /* set server address with allocate memory */ ++ /* set server address with allocate memory */ + set_tacacs_server_addr(tac_srv_no, server); + + /* copy secret to key */ @@ -372,7 +192,7 @@ index 3d38f24..6b2e72d 100644 + tac_srv_no++; + } + -+ /* release servers memory */ ++ /* release servers memory */ + freeaddrinfo(servers); + } else { + _pam_log (LOG_ERR, @@ -434,8 +254,16 @@ index 3d38f24..6b2e72d 100644 + return 0; + } + -+ char current_secret[256]; -+ memset(current_secret, 0, sizeof(current_secret)); + char current_secret[256]; + memset(current_secret, 0, sizeof(current_secret)); +- +- /* otherwise the list will grow with each call */ +- memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); +- tac_srv_no = 0; +- +- tac_service[0] = 0; +- tac_protocol[0] = 0; +- tac_prompt[0] = 0; + while (fgets(line_buffer, sizeof line_buffer, config_file)) { + if(*line_buffer == '#' || isspace(*line_buffer)) + continue; /* skip comments and blank line. */ @@ -529,7 +357,7 @@ index 3d38f24..6b2e72d 100644 - snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); - tac_srv_no++; - } -- + - /* release servers memory */ - freeaddrinfo(servers); - } else { @@ -568,8 +396,8 @@ index 3d38f24..6b2e72d 100644 - __vrfname = strdup(*argv + 4); - } 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); +- strncpy(tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); +- set_source_ip(tac_source_ip); - } else { - _pam_log (LOG_WARNING, "unrecognized option: %s", *argv); - } @@ -581,7 +409,6 @@ index 3d38f24..6b2e72d 100644 - _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); - - for(n = 0; n < tac_srv_no; n++) { -+ + if (ctrl & PAM_TAC_DEBUG) { + int n; + @@ -611,10 +438,10 @@ index 3d38f24..6b2e72d 100644 + return ctrl; +} /* _pam_parse */ diff --git a/support.h b/support.h -index feadbf5..bdb60b4 100644 +index 097c349..24436ad 100644 --- a/support.h +++ b/support.h -@@ -24,15 +24,23 @@ +@@ -24,7 +24,15 @@ #include "libtac.h" @@ -623,14 +450,15 @@ index feadbf5..bdb60b4 100644 + +/* pam_tacplus command line options */ +#define PAM_TAC_DEBUG 0x01 -+#define PAM_TAC_ACCT 0x02 /* account on all specified servers */ ++#define PAM_TAC_ACCT 0x02 ++ ++/* account on all specified servers */ +#define PAM_TAC_USE_FIRST_PASS 0x04 +#define PAM_TAC_TRY_FIRST_PASS 0x08 typedef struct { -- struct addrinfo *addr; -+ struct addrinfo *addr; - char key[256]; + struct addrinfo *addr; +@@ -32,7 +40,9 @@ typedef struct { } tacplus_server_t; extern tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; @@ -640,7 +468,7 @@ index feadbf5..bdb60b4 100644 extern char tac_service[64]; extern char tac_protocol[64]; -@@ -48,7 +56,12 @@ void _pam_log (int, const char *, ...); +@@ -48,7 +58,12 @@ void _pam_log (int, const char *, ...); void *_xcalloc (size_t); char *_pam_get_user(pam_handle_t *); char *_pam_get_terminal(pam_handle_t *); @@ -655,5 +483,5 @@ index feadbf5..bdb60b4 100644 #endif /* PAM_TACPLUS_SUPPORT_H */ -- -2.17.1.windows.2 +2.27.0.windows.1 diff --git a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch index 0e4bd8e5ac7b..83d2addc79e7 100644 --- a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch +++ b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch @@ -1,18 +1,55 @@ -From 73ac227e4924027d46e39c4f657d71aae5aa05b8 Mon Sep 17 00:00:00 2001 -From: liuh-80 <58683130+liuh-80@users.noreply.github.com> -Date: Wed, 29 Sep 2021 15:32:10 +0800 +From 953857b6a43d659f441d7d9341c003559f68ac9c Mon Sep 17 00:00:00 2001 +From: liuh +Date: Fri, 1 Oct 2021 17:56:54 +0800 Subject: [PATCH 3/3] Add setting flag for authorization and accounting. --- - support.c | 8 ++++++++ - support.h | 10 +++++++++- - 2 files changed, 17 insertions(+), 1 deletion(-) + libtacsupport.pc.in | 11 +++++++++++ + support.c | 12 ++++++++++-- + support.h | 10 +++++++++- + 3 files changed, 30 insertions(+), 3 deletions(-) + create mode 100644 libtacsupport.pc.in +diff --git a/libtacsupport.pc.in b/libtacsupport.pc.in +new file mode 100644 +index 0000000..1f12fe0 +--- /dev/null ++++ b/libtacsupport.pc.in +@@ -0,0 +1,11 @@ ++prefix=@prefix@ ++exec_prefix=@exec_prefix@ ++libdir=@libdir@ ++includedir=@includedir@/libtac ++ ++Name: libtacsupport ++Description: TACACS+ support lib implementation ++URL: https://github.com/jeroennijhof/pam_tacplus ++Version: @VERSION@ ++Libs: -L${libdir} -ltacsupport ++Cflags: -I${includedir} diff --git a/support.c b/support.c -index 6b2e72d..e94c79b 100644 +index 789533e..f7498f6 100644 --- a/support.c +++ b/support.c -@@ -343,6 +343,14 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b +@@ -298,7 +298,7 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b + } + if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { + for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { +- /* set server address with allocate memory */ ++ /* set server address with allocate memory */ + set_tacacs_server_addr(tac_srv_no, server); + + /* copy secret to key */ +@@ -306,7 +306,7 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b + tac_srv_no++; + } + +- /* release servers memory */ ++ /* release servers memory */ + freeaddrinfo(servers); + } else { + _pam_log (LOG_ERR, +@@ -346,6 +346,14 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b /* source ip for the packets */ strncpy (tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); set_source_ip (tac_source_ip); @@ -28,12 +65,15 @@ index 6b2e72d..e94c79b 100644 _pam_log (LOG_WARNING, "unrecognized option: %s", arg); } diff --git a/support.h b/support.h -index bdb60b4..5fce87e 100644 +index 24436ad..01033b8 100644 --- a/support.h +++ b/support.h -@@ -32,6 +32,14 @@ +@@ -32,8 +32,16 @@ + + /* account on all specified servers */ #define PAM_TAC_USE_FIRST_PASS 0x04 - #define PAM_TAC_TRY_FIRST_PASS 0x08 +-#define PAM_TAC_TRY_FIRST_PASS 0x08 ++#define PAM_TAC_TRY_FIRST_PASS 0x08 +/* accounting setting flag */ +#define ACCOUNTING_FLAG_LOCAL 0x10 @@ -46,15 +86,6 @@ index bdb60b4..5fce87e 100644 typedef struct { struct addrinfo *addr; char key[256]; -@@ -45,7 +53,7 @@ extern char *__vrfname; - extern char tac_service[64]; - extern char tac_protocol[64]; - extern char tac_prompt[64]; --extern struct addrinfo tac_source_addr; -+extern struct addrinfo tac_source_addr; - - int _pam_parse (int, const char **); - unsigned long _resolve_name (char *); -- -2.17.1.windows.2 +2.27.0.windows.1 From 19f27fade7052fbbf33970de02f4d2e97e5b38ab Mon Sep 17 00:00:00 2001 From: liuh Date: Fri, 1 Oct 2021 21:49:04 +0800 Subject: [PATCH 05/12] Fix trailing whitespace. --- .../pam/0007-Fix-memory-leak-when-parse-configuration.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch index 85bb96bd9959..607dceeab6b7 100644 --- a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch +++ b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch @@ -240,8 +240,8 @@ index d2ed770..ce3f18d 100644 + tac_source_addr->ai_addr = &(tac_source_sock_addr); + memcpy(tac_source_addr->ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); + } -+ -+ ++ ++ + freeaddrinfo(source_address); + _pam_log(LOG_DEBUG, "source ip is set"); + } From 8e3d88f18be7c70c69f8c9713b00aac1f3d1008a Mon Sep 17 00:00:00 2001 From: liuh Date: Fri, 1 Oct 2021 22:59:30 +0800 Subject: [PATCH 06/12] Fix apply patch issue. --- ...memory-leak-when-parse-configuration.patch | 270 ++++--------- ...acacs-support-functions-into-library.patch | 370 ++++++++++-------- ...lag-for-authorization-and-accounting.patch | 64 +-- 3 files changed, 295 insertions(+), 409 deletions(-) diff --git a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch index 607dceeab6b7..79f7c9591e76 100644 --- a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch +++ b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch @@ -1,145 +1,52 @@ -From a8b8c662b1520cbf0aafffb65ae108b4aa1bb73b Mon Sep 17 00:00:00 2001 +From e2ddc43a78fc5b534c6e6623b1f2c795a029c470 Mon Sep 17 00:00:00 2001 From: liuh -Date: Fri, 1 Oct 2021 17:40:14 +0800 +Date: Fri, 1 Oct 2021 22:31:26 +0800 Subject: [PATCH 1/3] Fix memory leak when parse configuration. --- - pam_tacplus.c | 28 +++++------- - support.c | 115 ++++++++++++++++++++++++++++++-------------------- - support.h | 6 +-- - 3 files changed, 83 insertions(+), 66 deletions(-) + pam_tacplus.c | 10 +++--- + support.c | 87 ++++++++++++++++++++++++++++++++++++++++++++------- + support.h | 4 +-- + 3 files changed, 83 insertions(+), 18 deletions(-) diff --git a/pam_tacplus.c b/pam_tacplus.c -index 4a6f714..d062359 100644 +index 9fc6be7..6d6a7a9 100644 --- a/pam_tacplus.c +++ b/pam_tacplus.c -@@ -138,10 +138,8 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, - syslog(LOG_DEBUG, "%s: tac_srv_no=%d", __FUNCTION__, tac_srv_no); - } - -- if ((user = _pam_get_user(pamh)) == NULL) { -+ if ((user = _pam_get_user(pamh)) == NULL) - return PAM_USER_UNKNOWN; -- } -- - - if (ctrl & PAM_TAC_DEBUG) - syslog(LOG_DEBUG, "%s: username [%s] obtained", __FUNCTION__, user); -@@ -179,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, &tac_source_addr, tac_timeout, __vrfname); -+ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, tac_source_addr, tac_timeout, __vrfname); - if (tac_fd < 0) { - _pam_log(LOG_WARNING, "%s: error sending %s (fd)", - __FUNCTION__, typemsg); -@@ -210,7 +208,6 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, - signal(SIGCHLD, SIG_DFL); - signal(SIGHUP, SIG_DFL); - } -- - return status; - } - -@@ -241,9 +238,8 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, - syslog(LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)", - __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); - -- if ((user = _pam_get_user(pamh)) == NULL) { -+ if ((user = _pam_get_user(pamh)) == NULL) - return PAM_USER_UNKNOWN; -- } - - if (ctrl & PAM_TAC_DEBUG) - syslog(LOG_DEBUG, "%s: user [%s] obtained", __FUNCTION__, user); -@@ -280,7 +276,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, &tac_source_addr, tac_timeout, __vrfname); -+ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, tac_source_addr, tac_timeout, __vrfname); - if (tac_fd < 0) { - _pam_log(LOG_ERR, "%s: connection to srv %d failed", __FUNCTION__, srv_i); - continue; -@@ -542,9 +538,8 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, - syslog (LOG_DEBUG, "%s: called (pam_tacplus v%u.%u.%u)" - , __FUNCTION__, PAM_TAC_VMAJ, PAM_TAC_VMIN, PAM_TAC_VPAT); - -- if ((user = _pam_get_user(pamh)) == NULL) { -+ if ((user = _pam_get_user(pamh)) == NULL) - return PAM_USER_UNKNOWN; -- } - - if (ctrl & PAM_TAC_DEBUG) - syslog(LOG_DEBUG, "%s: username obtained [%s]", __FUNCTION__, user); -@@ -585,13 +580,11 @@ 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, &tac_source_addr, tac_timeout, __vrfname); -+ tac_fd = tac_connect_single(active_server.addr, active_server.key, tac_source_addr, tac_timeout, __vrfname); - if(tac_fd < 0) { - _pam_log (LOG_ERR, "TACACS+ server unavailable"); -- if(arep.msg != NULL) { -+ if(arep.msg != NULL) - free (arep.msg); -- } -- - return PAM_AUTH_ERR; - } - -@@ -672,6 +665,7 @@ int pam_sm_acct_mgmt (pam_handle_t * pamh, int flags, - free (arep.msg); - - close(tac_fd); -+ - return status; - } /* pam_sm_acct_mgmt */ - -@@ -733,9 +727,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, - - if ( (pam_get_item(pamh, PAM_OLDAUTHTOK, &pam_pass) == PAM_SUCCESS) - && (pam_pass != NULL) ) { -- if ((pass = strdup(pam_pass)) == NULL) { -+ if ((pass = strdup(pam_pass)) == NULL) - return PAM_BUF_ERR; -- } - } else { - pass = strdup(""); - } -@@ -744,7 +737,6 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, - if(pass) { - free(pass); - } -- - return PAM_USER_UNKNOWN; - } - -@@ -771,7 +763,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, &tac_source_addr, tac_timeout, __vrfname); -+ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, tac_source_addr, tac_timeout, __vrfname); - if (tac_fd < 0) { - _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i); - continue; +@@ -322,8 +322,9 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, + } + status = PAM_SUCCESS; + communicating = 0; +- active_server.addr = tac_srv[srv_i].addr; +- active_server.key = tac_srv[srv_i].key; ++ active_server.addr = tac_srv[srv_i].addr; ++ /* copy secret to key */ ++ snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); + + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); +@@ -819,8 +820,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, + status = PAM_SUCCESS; + communicating = 0; + +- active_server.addr = tac_srv[srv_i].addr; +- active_server.key = tac_srv[srv_i].key; ++ active_server.addr = tac_srv[srv_i].addr; ++ /* copy secret to key */ ++ snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); + + if (ctrl & PAM_TAC_DEBUG) + syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); diff --git a/support.c b/support.c -index d2ed770..ce3f18d 100644 +index be1f21b..29a7691 100644 --- a/support.c +++ b/support.c -@@ -30,23 +30,24 @@ +@@ -30,15 +30,25 @@ #include #include --/* tacacs server information */ +/* tacacs server information */ tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; --struct addrinfo tac_srv_addr[TAC_PLUS_MAXSERVERS]; --struct sockaddr tac_sock_addr[TAC_PLUS_MAXSERVERS]; --struct sockaddr_in6 tac_sock6_addr[TAC_PLUS_MAXSERVERS]; -- +struct addrinfo tac_srv_addr[TAC_PLUS_MAXSERVERS]; +struct sockaddr tac_sock_addr[TAC_PLUS_MAXSERVERS]; +struct sockaddr_in6 tac_sock6_addr[TAC_PLUS_MAXSERVERS]; @@ -151,49 +58,21 @@ index d2ed770..ce3f18d 100644 char tac_prompt[64]; char *__vrfname=NULL; -char tac_source_ip[64]; -- +-struct addrinfo *tac_source_addr = NULL; +char tac_source_ip[64]; + - /* source address */ --struct addrinfo tac_source_addr; --struct sockaddr tac_source_sock_addr; ++/* source address */ +struct addrinfo *tac_source_addr=NULL; +struct addrinfo tac_source_address; +struct sockaddr tac_source_sock_addr; - struct sockaddr_in6 tac_source_sock6_addr; ++struct sockaddr_in6 tac_source_sock6_addr; void _pam_log(int err, const char *format,...) { -@@ -181,35 +182,59 @@ int tacacs_get_password (pam_handle_t * pamh, int flags + char msg[256]; +@@ -172,6 +182,57 @@ int tacacs_get_password (pam_handle_t * pamh, int flags return PAM_SUCCESS; } -- --} --/* set source ip address for the outgoing tacacs packets */ --void set_source_ip(const char *tac_source_ip) { -- struct addrinfo hints, *source_address; -- int rv; -- /* set the source ip address for the tacacs packets */ -- 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 { -- memcpy(&tac_source_addr, source_address, sizeof(struct addrinfo)); -- if (source_address->ai_family == AF_INET6) { -- tac_source_addr.ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); -- memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); -- } -- else { -- tac_source_addr.ai_addr = &(tac_source_sock_addr); -- memcpy(tac_source_addr.ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); -- } -- -- -- freeaddrinfo(source_address); -- _pam_log(LOG_DEBUG, "source ip is set"); + +/* + * Set tacacs server addrinfo. @@ -209,7 +88,7 @@ index d2ed770..ce3f18d 100644 + else { + tac_srv[tac_srv_no].addr->ai_addr = &(tac_sock_addr[tac_srv_no]); + memcpy(tac_srv[tac_srv_no].addr->ai_addr, server->ai_addr, sizeof(struct sockaddr)); - } ++ } + + tac_srv[tac_srv_no].addr->ai_canonname = NULL; + tac_srv[tac_srv_no].addr->ai_next = NULL; @@ -241,24 +120,31 @@ index d2ed770..ce3f18d 100644 + memcpy(tac_source_addr->ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); + } + -+ + freeaddrinfo(source_address); + _pam_log(LOG_DEBUG, "source ip is set"); + } - } -+ ++} + int _pam_parse (int argc, const char **argv) { int ctrl = 0; - char current_secret[256]; -@@ -284,11 +309,11 @@ int _pam_parse (int argc, const char **argv) { +@@ -186,11 +247,6 @@ int _pam_parse (int argc, const char **argv) { + tac_prompt[0] = 0; + tac_login[0] = 0; + tac_source_ip[0] = 0; +- +- if (tac_source_addr != NULL) { +- freeaddrinfo(tac_source_addr); +- tac_source_addr = NULL; +- } + + for (ctrl = 0; argc-- > 0; ++argv) { + if (!strcmp (*argv, "debug")) { /* all */ +@@ -246,10 +302,16 @@ int _pam_parse (int argc, const char **argv) { } if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { -- /* set server address with allocate memory */ -- set_tacacs_server_addr(tac_srv_no, server); -- -- /* copy secret to key */ -- snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); +- tac_srv[tac_srv_no].addr = server; +- tac_srv[tac_srv_no].key = current_secret; + /* set server address with allocate memory */ + set_tacacs_server_addr(tac_srv_no, server); + @@ -266,24 +152,35 @@ index d2ed770..ce3f18d 100644 + snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); tac_srv_no++; } - -@@ -328,10 +353,10 @@ int _pam_parse (int argc, const char **argv) { ++ ++ /* release servers memory */ ++ freeaddrinfo(servers); + } else { + _pam_log (LOG_ERR, + "skip invalid server: %s (getaddrinfo: %s)", +@@ -269,7 +331,8 @@ int _pam_parse (int argc, const char **argv) { + if (tac_srv[i].key != NULL) + break; + +- tac_srv[i].key = current_secret; ++ /* copy secret to key */ ++ snprintf(tac_srv[i].key, sizeof(tac_srv[i].key), "%s", current_secret); } - } else if(!strncmp(*argv, "vrf=", 4)) { + } else if (!strncmp (*argv, "timeout=", 8)) { + /* FIXME atoi() doesn't handle invalid numeric strings well */ +@@ -284,8 +347,8 @@ int _pam_parse (int argc, const char **argv) { __vrfname = strdup(*argv + 4); -- } else if (!strncmp (*argv, "source_ip=", strlen("source_ip="))) { -- /* source ip for the packets */ + } 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); -+ } else if (!strncmp (*argv, "source_ip=", strlen("source_ip="))) { -+ /* source ip for the packets */ -+ strncpy(tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); -+ set_source_ip(tac_source_ip); +- set_source_ip (tac_source_ip, &tac_source_addr); ++ 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); } diff --git a/support.h b/support.h -index e88463e..097c349 100644 +index b1faf43..097c349 100644 --- a/support.h +++ b/support.h @@ -27,8 +27,8 @@ @@ -291,21 +188,12 @@ index e88463e..097c349 100644 typedef struct { - struct addrinfo *addr; -- char key[256]; +- const char *key; + struct addrinfo *addr; + char key[256]; } tacplus_server_t; extern tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; -@@ -37,7 +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; -+extern struct addrinfo *tac_source_addr; - - int _pam_parse (int, const char **); - unsigned long _resolve_name (char *); -- 2.27.0.windows.1 diff --git a/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch index ee75ea6267de..416b6a9437fd 100644 --- a/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch +++ b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch @@ -1,16 +1,18 @@ -From 45be06055b9040e53d0718f0893ff35571b2c2ad Mon Sep 17 00:00:00 2001 +From ad348a42acfa3da49ae5e2151e37668b91c6de32 Mon Sep 17 00:00:00 2001 From: liuh -Date: Fri, 1 Oct 2021 17:45:33 +0800 +Date: Fri, 1 Oct 2021 22:37:20 +0800 Subject: [PATCH 2/3] Extract tacacs support functions into library. --- - Makefile.am | 16 ++- - configure.ac | 3 +- - pam_tacplus.c | 5 +- - pam_tacplus.h | 6 - - support.c | 309 ++++++++++++++++++++++++++++---------------------- - support.h | 19 +++- - 6 files changed, 206 insertions(+), 152 deletions(-) + Makefile.am | 16 ++- + configure.ac | 3 +- + libtacsupport.pc.in | 11 ++ + pam_tacplus.c | 5 +- + pam_tacplus.h | 6 - + support.c | 332 ++++++++++++++++++++++++-------------------- + support.h | 17 ++- + 7 files changed, 221 insertions(+), 169 deletions(-) + create mode 100644 libtacsupport.pc.in diff --git a/Makefile.am b/Makefile.am index c90c582..2ac9ea0 100644 @@ -71,8 +73,25 @@ index f67e2ba..0f917a8 100644 + libtacsupport.pc pam_tacplus.spec]) AC_OUTPUT +diff --git a/libtacsupport.pc.in b/libtacsupport.pc.in +new file mode 100644 +index 0000000..1f12fe0 +--- /dev/null ++++ b/libtacsupport.pc.in +@@ -0,0 +1,11 @@ ++prefix=@prefix@ ++exec_prefix=@exec_prefix@ ++libdir=@libdir@ ++includedir=@includedir@/libtac ++ ++Name: libtacsupport ++Description: TACACS+ support lib implementation ++URL: https://github.com/jeroennijhof/pam_tacplus ++Version: @VERSION@ ++Libs: -L${libdir} -ltacsupport ++Cflags: -I${includedir} diff --git a/pam_tacplus.c b/pam_tacplus.c -index d062359..9ffbdcf 100644 +index 6d6a7a9..3b88c83 100644 --- a/pam_tacplus.c +++ b/pam_tacplus.c @@ -51,10 +51,7 @@ @@ -105,7 +124,7 @@ index bc71b54..e7b30f7 100644 #define PAM_TAC_VMAJ 1 #define PAM_TAC_VMIN 3 diff --git a/support.c b/support.c -index ce3f18d..789533e 100644 +index 29a7691..4be5339 100644 --- a/support.c +++ b/support.c @@ -29,6 +29,7 @@ @@ -116,12 +135,156 @@ index ce3f18d..789533e 100644 /* tacacs server information */ tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; -@@ -235,148 +236,184 @@ void set_source_ip(const char *tac_source_ip) { +@@ -233,161 +234,186 @@ void set_source_ip(const char *tac_source_ip) { + _pam_log(LOG_DEBUG, "source ip is set"); } } - +- -int _pam_parse (int argc, const char **argv) { - int ctrl = 0; +- const char *current_secret = NULL; +- +- /* otherwise the list will grow with each call */ +- memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); +- tac_srv_no = 0; +- +- tac_service[0] = 0; +- tac_protocol[0] = 0; +- tac_prompt[0] = 0; +- tac_login[0] = 0; +- tac_source_ip[0] = 0; +- +- for (ctrl = 0; argc-- > 0; ++argv) { +- if (!strcmp (*argv, "debug")) { /* all */ +- ctrl |= PAM_TAC_DEBUG; +- } else if (!strcmp (*argv, "use_first_pass")) { +- ctrl |= PAM_TAC_USE_FIRST_PASS; +- } else if (!strcmp (*argv, "try_first_pass")) { +- ctrl |= PAM_TAC_TRY_FIRST_PASS; +- } else if (!strncmp (*argv, "service=", 8)) { /* author & acct */ +- xstrcpy (tac_service, *argv + 8, sizeof(tac_service)); +- } else if (!strncmp (*argv, "protocol=", 9)) { /* author & acct */ +- xstrcpy (tac_protocol, *argv + 9, sizeof(tac_protocol)); +- } else if (!strncmp (*argv, "prompt=", 7)) { /* authentication */ +- xstrcpy (tac_prompt, *argv + 7, sizeof(tac_prompt)); +- /* Replace _ with space */ +- int chr; +- for (chr = 0; chr < strlen(tac_prompt); chr++) { +- if (tac_prompt[chr] == '_') { +- tac_prompt[chr] = ' '; +- } +- } +- } else if (!strncmp (*argv, "login=", 6)) { +- xstrcpy (tac_login, *argv + 6, sizeof(tac_login)); +- } else if (!strcmp (*argv, "acct_all")) { +- ctrl |= PAM_TAC_ACCT; +- } else if (!strncmp (*argv, "server=", 7)) { /* authen & acct */ +- if(tac_srv_no < TAC_PLUS_MAXSERVERS) { +- struct addrinfo hints, *servers, *server; +- int rv; +- char *close_bracket, *server_name, *port, server_buf[256]; +- +- memset(&hints, 0, sizeof hints); +- hints.ai_family = AF_UNSPEC; /* use IPv4 or IPv6, whichever */ +- hints.ai_socktype = SOCK_STREAM; +- +- if (strlen(*argv + 7) >= sizeof(server_buf)) { +- _pam_log(LOG_ERR, "server address too long, sorry"); +- continue; +- } +- strcpy(server_buf, *argv + 7); +- +- if (*server_buf == '[' && (close_bracket = strchr(server_buf, ']')) != NULL) { /* Check for URI syntax */ +- server_name = server_buf + 1; +- port = strrchr(close_bracket, ':'); +- *close_bracket = '\0'; +- } else { /* Fall back to traditional syntax */ +- server_name = server_buf; +- port = strrchr(server_buf, ':'); +- } +- if (port != NULL) { +- *port = '\0'; +- port++; +- } +- if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { +- for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { +- /* set server address with allocate memory */ +- set_tacacs_server_addr(tac_srv_no, server); +- +- /* copy secret to key */ +- snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); +- tac_srv_no++; +- } +- +- /* release servers memory */ +- freeaddrinfo(servers); +- } else { +- _pam_log (LOG_ERR, +- "skip invalid server: %s (getaddrinfo: %s)", +- server_name, gai_strerror(rv)); +- } +- } else { +- _pam_log(LOG_ERR, "maximum number of servers (%d) exceeded, skipping", +- TAC_PLUS_MAXSERVERS); +- } +- } else if (!strncmp (*argv, "secret=", 7)) { +- int i; +- +- current_secret = *argv + 7; /* points right into argv (which is const) */ +- +- /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ +- for(i = tac_srv_no-1; i >= 0; i--) { +- if (tac_srv[i].key != NULL) +- break; +- +- /* copy secret to key */ +- snprintf(tac_srv[i].key, sizeof(tac_srv[i].key), "%s", current_secret); +- } +- } else if (!strncmp (*argv, "timeout=", 8)) { +- /* FIXME atoi() doesn't handle invalid numeric strings well */ +- tac_timeout = atoi(*argv + 8); +- +- if (tac_timeout < 0) { +- tac_timeout = 0; +- } else { +- tac_readtimeout_enable = 1; +- } +- } else if(!strncmp(*argv, "vrf=", 4)) { +- __vrfname = strdup(*argv + 4); +- } 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); +- } +- } +- +- if (ctrl & PAM_TAC_DEBUG) { +- int n; +- +- _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); +- +- for(n = 0; n < tac_srv_no; n++) { +- _pam_log(LOG_DEBUG, "server[%d] { addr=%s, key='%c*****' }", n, tac_ntop(tac_srv[n].addr->ai_addr), tac_srv[n].key[0]); +- } +- +- _pam_log(LOG_DEBUG, "tac_service='%s'", tac_service); +- _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; +/* + * Parse one arguments. + * Use this method for both: @@ -208,7 +371,14 @@ index ce3f18d..789533e 100644 + + /* points right into arg (which is const) */ + snprintf(current_secret, current_secret_buffer_size, "%s", arg + 7); -+ + +- /* set the source ip address for the tacacs packets */ +- 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"); + /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ + for(i = tac_srv_no-1; i >= 0; i--) { + if (tac_srv[i].key != NULL) @@ -232,7 +402,8 @@ index ce3f18d..789533e 100644 + /* source ip for the packets */ + strncpy (tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); + set_source_ip (tac_source_ip); -+ } else { + } else { +- _pam_log(LOG_DEBUG, "source ip is set"); + _pam_log (LOG_WARNING, "unrecognized option: %s", arg); + } + @@ -254,26 +425,19 @@ index ce3f18d..789533e 100644 + return 0; + } + - char current_secret[256]; - memset(current_secret, 0, sizeof(current_secret)); -- -- /* otherwise the list will grow with each call */ -- memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); -- tac_srv_no = 0; -- -- tac_service[0] = 0; -- tac_protocol[0] = 0; -- tac_prompt[0] = 0; ++ char current_secret[256]; ++ memset(current_secret, 0, sizeof(current_secret)); + while (fgets(line_buffer, sizeof line_buffer, config_file)) { + if(*line_buffer == '#' || isspace(*line_buffer)) + continue; /* skip comments and blank line. */ + strtok(line_buffer, " \t\n\r\f"); + ctrl |= _pam_parse_arg(line_buffer, current_secret, sizeof(current_secret)); -+ } + } + + fclose(config_file); + return ctrl; -+} + } ++ +int _pam_parse (int argc, const char **argv) { + int ctrl = 0; + char current_secret[256]; @@ -286,162 +450,36 @@ index ce3f18d..789533e 100644 + tac_service[0] = 0; + tac_protocol[0] = 0; + tac_prompt[0] = 0; - tac_login[0] = 0; - tac_source_ip[0] = 0; - -- if (tac_source_addr != NULL) { -- freeaddrinfo(tac_source_addr); -- tac_source_addr = NULL; ++ tac_login[0] = 0; ++ tac_source_ip[0] = 0; ++ + for (ctrl = 0; argc-- > 0; ++argv) { + ctrl |= _pam_parse_arg(*argv, current_secret, sizeof(current_secret)); - } -- -- for (ctrl = 0; argc-- > 0; ++argv) { -- if (!strcmp (*argv, "debug")) { /* all */ -- ctrl |= PAM_TAC_DEBUG; -- } else if (!strcmp (*argv, "use_first_pass")) { -- ctrl |= PAM_TAC_USE_FIRST_PASS; -- } else if (!strcmp (*argv, "try_first_pass")) { -- ctrl |= PAM_TAC_TRY_FIRST_PASS; -- } else if (!strncmp (*argv, "service=", 8)) { /* author & acct */ -- xstrcpy (tac_service, *argv + 8, sizeof(tac_service)); -- } else if (!strncmp (*argv, "protocol=", 9)) { /* author & acct */ -- xstrcpy (tac_protocol, *argv + 9, sizeof(tac_protocol)); -- } else if (!strncmp (*argv, "prompt=", 7)) { /* authentication */ -- xstrcpy (tac_prompt, *argv + 7, sizeof(tac_prompt)); -- /* Replace _ with space */ -- int chr; -- for (chr = 0; chr < strlen(tac_prompt); chr++) { -- if (tac_prompt[chr] == '_') { -- tac_prompt[chr] = ' '; -- } -- } -- } else if (!strncmp (*argv, "login=", 6)) { -- xstrcpy (tac_login, *argv + 6, sizeof(tac_login)); -- } else if (!strcmp (*argv, "acct_all")) { -- ctrl |= PAM_TAC_ACCT; -- } else if (!strncmp (*argv, "server=", 7)) { /* authen & acct */ -- if(tac_srv_no < TAC_PLUS_MAXSERVERS) { -- struct addrinfo hints, *servers, *server; -- int rv; -- char *close_bracket, *server_name, *port, server_buf[256]; -- -- memset(&hints, 0, sizeof hints); -- hints.ai_family = AF_UNSPEC; /* use IPv4 or IPv6, whichever */ -- hints.ai_socktype = SOCK_STREAM; -- -- if (strlen(*argv + 7) >= sizeof(server_buf)) { -- _pam_log(LOG_ERR, "server address too long, sorry"); -- continue; -- } -- strcpy(server_buf, *argv + 7); -- -- if (*server_buf == '[' && (close_bracket = strchr(server_buf, ']')) != NULL) { /* Check for URI syntax */ -- server_name = server_buf + 1; -- port = strrchr(close_bracket, ':'); -- *close_bracket = '\0'; -- } else { /* Fall back to traditional syntax */ -- server_name = server_buf; -- port = strrchr(server_buf, ':'); -- } -- if (port != NULL) { -- *port = '\0'; -- port++; -- } -- if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { -- for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { -- /* set server address with allocate memory */ -- set_tacacs_server_addr(tac_srv_no, server); -- -- /* copy secret to key */ -- snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); -- tac_srv_no++; -- } - -- /* release servers memory */ -- freeaddrinfo(servers); -- } else { -- _pam_log (LOG_ERR, -- "skip invalid server: %s (getaddrinfo: %s)", -- server_name, gai_strerror(rv)); -- } -- } else { -- _pam_log(LOG_ERR, "maximum number of servers (%d) exceeded, skipping", -- TAC_PLUS_MAXSERVERS); -- } -- } else if (!strncmp (*argv, "secret=", 7)) { -- int i; -- -- /* points right into arg (which is const) */ -- snprintf(current_secret, sizeof(current_secret), "%s", arg + 7); -- -- /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ -- for(i = tac_srv_no-1; i >= 0; i--) { -- if (tac_srv[i].key != NULL) -- break; -- -- /* copy secret to key */ -- snprintf(tac_srv[i].key, sizeof(tac_srv[i].key), "%s", current_secret); -- } -- } else if (!strncmp (*argv, "timeout=", 8)) { -- /* FIXME atoi() doesn't handle invalid numeric strings well */ -- tac_timeout = atoi(*argv + 8); -- -- if (tac_timeout < 0) { -- tac_timeout = 0; -- } else { -- tac_readtimeout_enable = 1; -- } -- } else if(!strncmp(*argv, "vrf=", 4)) { -- __vrfname = strdup(*argv + 4); -- } else if (!strncmp (*argv, "source_ip=", strlen("source_ip="))) { -- /* source ip for the packets */ -- strncpy(tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); -- set_source_ip(tac_source_ip); -- } else { -- _pam_log (LOG_WARNING, "unrecognized option: %s", *argv); -- } -- } -- -- if (ctrl & PAM_TAC_DEBUG) { -- int n; -- -- _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); -- -- for(n = 0; n < tac_srv_no; n++) { ++ } ++ + if (ctrl & PAM_TAC_DEBUG) { + int n; + + _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); + + for(n = 0; n < tac_srv_no; n++) { - _pam_log(LOG_DEBUG, "server[%d] { addr=%s, key='%c*****' }", n, tac_ntop(tac_srv[n].addr->ai_addr), tac_srv[n].key[0]); -- } -- -- _pam_log(LOG_DEBUG, "tac_service='%s'", tac_service); -- _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, "server[%d] { addr=%s, key='%c*****' }", n, tac_ntop(tac_srv[n].addr->ai_addr), tac_srv[n].key[0]); + } + + _pam_log(LOG_DEBUG, "tac_service='%s'", tac_service); + _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 */ ++ _pam_log(LOG_DEBUG, "tac_source_ip='%s'", tac_source_ip); + } + + return ctrl; +} /* _pam_parse */ diff --git a/support.h b/support.h -index 097c349..24436ad 100644 +index 097c349..6820be3 100644 --- a/support.h +++ b/support.h -@@ -24,7 +24,15 @@ +@@ -24,7 +24,13 @@ #include "libtac.h" @@ -450,15 +488,13 @@ index 097c349..24436ad 100644 + +/* pam_tacplus command line options */ +#define PAM_TAC_DEBUG 0x01 -+#define PAM_TAC_ACCT 0x02 -+ -+/* account on all specified servers */ ++#define PAM_TAC_ACCT 0x02 /* account on all specified servers */ +#define PAM_TAC_USE_FIRST_PASS 0x04 +#define PAM_TAC_TRY_FIRST_PASS 0x08 typedef struct { struct addrinfo *addr; -@@ -32,7 +40,9 @@ typedef struct { +@@ -32,7 +38,9 @@ typedef struct { } tacplus_server_t; extern tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; @@ -468,7 +504,7 @@ index 097c349..24436ad 100644 extern char tac_service[64]; extern char tac_protocol[64]; -@@ -48,7 +58,12 @@ void _pam_log (int, const char *, ...); +@@ -48,7 +56,12 @@ void _pam_log (int, const char *, ...); void *_xcalloc (size_t); char *_pam_get_user(pam_handle_t *); char *_pam_get_terminal(pam_handle_t *); diff --git a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch index 83d2addc79e7..6e0a152acb66 100644 --- a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch +++ b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch @@ -1,58 +1,23 @@ -From 953857b6a43d659f441d7d9341c003559f68ac9c Mon Sep 17 00:00:00 2001 +From 6707a9a947894cdfd0abe680812a2a62488a6d57 Mon Sep 17 00:00:00 2001 From: liuh -Date: Fri, 1 Oct 2021 17:56:54 +0800 +Date: Fri, 1 Oct 2021 22:49:01 +0800 Subject: [PATCH 3/3] Add setting flag for authorization and accounting. --- - libtacsupport.pc.in | 11 +++++++++++ - support.c | 12 ++++++++++-- - support.h | 10 +++++++++- - 3 files changed, 30 insertions(+), 3 deletions(-) - create mode 100644 libtacsupport.pc.in + support.c | 10 +++++++++- + support.h | 8 ++++++++ + 2 files changed, 17 insertions(+), 1 deletion(-) -diff --git a/libtacsupport.pc.in b/libtacsupport.pc.in -new file mode 100644 -index 0000000..1f12fe0 ---- /dev/null -+++ b/libtacsupport.pc.in -@@ -0,0 +1,11 @@ -+prefix=@prefix@ -+exec_prefix=@exec_prefix@ -+libdir=@libdir@ -+includedir=@includedir@/libtac -+ -+Name: libtacsupport -+Description: TACACS+ support lib implementation -+URL: https://github.com/jeroennijhof/pam_tacplus -+Version: @VERSION@ -+Libs: -L${libdir} -ltacsupport -+Cflags: -I${includedir} diff --git a/support.c b/support.c -index 789533e..f7498f6 100644 +index 4be5339..27dd27a 100644 --- a/support.c +++ b/support.c -@@ -298,7 +298,7 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b - } - if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { - for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { -- /* set server address with allocate memory */ -+ /* set server address with allocate memory */ - set_tacacs_server_addr(tac_srv_no, server); - - /* copy secret to key */ -@@ -306,7 +306,7 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b - tac_srv_no++; - } - -- /* release servers memory */ -+ /* release servers memory */ - freeaddrinfo(servers); - } else { - _pam_log (LOG_ERR, -@@ -346,6 +346,14 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b +@@ -344,7 +344,15 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b + } else if (!strncmp (arg, "source_ip=", strlen("source_ip="))) { /* source ip for the packets */ strncpy (tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); - set_source_ip (tac_source_ip); +- set_source_ip (tac_source_ip); ++ set_source_ip (tac_source_ip); + } else if (!strcmp (arg, "local_accounting")) { + ctrl |= ACCOUNTING_FLAG_LOCAL; + } else if (!strcmp (arg, "tacacs_accounting")) { @@ -65,15 +30,12 @@ index 789533e..f7498f6 100644 _pam_log (LOG_WARNING, "unrecognized option: %s", arg); } diff --git a/support.h b/support.h -index 24436ad..01033b8 100644 +index 6820be3..7862e58 100644 --- a/support.h +++ b/support.h -@@ -32,8 +32,16 @@ - - /* account on all specified servers */ +@@ -32,6 +32,14 @@ #define PAM_TAC_USE_FIRST_PASS 0x04 --#define PAM_TAC_TRY_FIRST_PASS 0x08 -+#define PAM_TAC_TRY_FIRST_PASS 0x08 + #define PAM_TAC_TRY_FIRST_PASS 0x08 +/* accounting setting flag */ +#define ACCOUNTING_FLAG_LOCAL 0x10 From b30ace51a3fb3b0ada85092b4a2570b47167fa99 Mon Sep 17 00:00:00 2001 From: liuh Date: Sat, 2 Oct 2021 20:03:30 +0800 Subject: [PATCH 07/12] Fix secret key issue. --- ...lag-for-authorization-and-accounting.patch | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch index 6e0a152acb66..a73c344df192 100644 --- a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch +++ b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch @@ -1,17 +1,26 @@ -From 6707a9a947894cdfd0abe680812a2a62488a6d57 Mon Sep 17 00:00:00 2001 +From ad4136ca0e9f37861b17e15ec69860486ac00268 Mon Sep 17 00:00:00 2001 From: liuh Date: Fri, 1 Oct 2021 22:49:01 +0800 -Subject: [PATCH 3/3] Add setting flag for authorization and accounting. +Subject: [PATCH] Add setting flag for authorization and accounting. --- - support.c | 10 +++++++++- + support.c | 12 ++++++++++-- support.h | 8 ++++++++ - 2 files changed, 17 insertions(+), 1 deletion(-) + 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/support.c b/support.c -index 4be5339..27dd27a 100644 +index 4be5339..d065023 100644 --- a/support.c +++ b/support.c +@@ -324,7 +324,7 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b + + /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ + for(i = tac_srv_no-1; i >= 0; i--) { +- if (tac_srv[i].key != NULL) ++ if (tac_srv[i].key[0] != 0) + break; + + /* copy secret to key */ @@ -344,7 +344,15 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b } else if (!strncmp (arg, "source_ip=", strlen("source_ip="))) { /* source ip for the packets */ From 761c1cfdef5b794599e05bcf39b4c5830389dccc Mon Sep 17 00:00:00 2001 From: liuh Date: Sun, 3 Oct 2021 12:52:45 +0800 Subject: [PATCH 08/12] Improve patch file. --- ...memory-leak-when-parse-configuration.patch | 16 +++++---- ...acacs-support-functions-into-library.patch | 30 ++++++++-------- ...lag-for-authorization-and-accounting.patch | 34 +++++++++---------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch index 79f7c9591e76..72a3c61f6978 100644 --- a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch +++ b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch @@ -1,13 +1,13 @@ -From e2ddc43a78fc5b534c6e6623b1f2c795a029c470 Mon Sep 17 00:00:00 2001 +From e2364848d97f36b103893a27c8e833b1829b6383 Mon Sep 17 00:00:00 2001 From: liuh Date: Fri, 1 Oct 2021 22:31:26 +0800 Subject: [PATCH 1/3] Fix memory leak when parse configuration. --- pam_tacplus.c | 10 +++--- - support.c | 87 ++++++++++++++++++++++++++++++++++++++++++++------- + support.c | 89 +++++++++++++++++++++++++++++++++++++++++++-------- support.h | 4 +-- - 3 files changed, 83 insertions(+), 18 deletions(-) + 3 files changed, 84 insertions(+), 19 deletions(-) diff --git a/pam_tacplus.c b/pam_tacplus.c index 9fc6be7..6d6a7a9 100644 @@ -38,7 +38,7 @@ index 9fc6be7..6d6a7a9 100644 if (ctrl & PAM_TAC_DEBUG) syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); diff --git a/support.c b/support.c -index be1f21b..29a7691 100644 +index be1f21b..2e85bc0 100644 --- a/support.c +++ b/support.c @@ -30,15 +30,25 @@ @@ -158,8 +158,12 @@ index be1f21b..29a7691 100644 } else { _pam_log (LOG_ERR, "skip invalid server: %s (getaddrinfo: %s)", -@@ -269,7 +331,8 @@ int _pam_parse (int argc, const char **argv) { - if (tac_srv[i].key != NULL) +@@ -266,10 +328,11 @@ int _pam_parse (int argc, const char **argv) { + + /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ + for(i = tac_srv_no-1; i >= 0; i--) { +- if (tac_srv[i].key != NULL) ++ if (tac_srv[i].key[0] != 0) break; - tac_srv[i].key = current_secret; diff --git a/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch index 416b6a9437fd..8123b09ba7a6 100644 --- a/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch +++ b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch @@ -1,6 +1,6 @@ -From ad348a42acfa3da49ae5e2151e37668b91c6de32 Mon Sep 17 00:00:00 2001 +From 7f560af088f3398885bbcc6996dfccfb06673a59 Mon Sep 17 00:00:00 2001 From: liuh -Date: Fri, 1 Oct 2021 22:37:20 +0800 +Date: Sun, 3 Oct 2021 12:49:05 +0800 Subject: [PATCH 2/3] Extract tacacs support functions into library. --- @@ -10,8 +10,8 @@ Subject: [PATCH 2/3] Extract tacacs support functions into library. pam_tacplus.c | 5 +- pam_tacplus.h | 6 - support.c | 332 ++++++++++++++++++++++++-------------------- - support.h | 17 ++- - 7 files changed, 221 insertions(+), 169 deletions(-) + support.h | 16 ++- + 7 files changed, 220 insertions(+), 169 deletions(-) create mode 100644 libtacsupport.pc.in diff --git a/Makefile.am b/Makefile.am @@ -124,7 +124,7 @@ index bc71b54..e7b30f7 100644 #define PAM_TAC_VMAJ 1 #define PAM_TAC_VMIN 3 diff --git a/support.c b/support.c -index 29a7691..4be5339 100644 +index 2e85bc0..da7a58b 100644 --- a/support.c +++ b/support.c @@ -29,6 +29,7 @@ @@ -234,7 +234,7 @@ index 29a7691..4be5339 100644 - - /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ - for(i = tac_srv_no-1; i >= 0; i--) { -- if (tac_srv[i].key != NULL) +- if (tac_srv[i].key[0] != 0) - break; - - /* copy secret to key */ @@ -335,11 +335,11 @@ index 29a7691..4be5339 100644 + + if (*server_buf == '[' && (close_bracket = strchr(server_buf, ']')) != NULL) { /* Check for URI syntax */ + server_name = server_buf + 1; -+ port = strchr(close_bracket, ':'); ++ port = strrchr(close_bracket, ':'); + *close_bracket = '\0'; + } else { /* Fall back to traditional syntax */ + server_name = server_buf; -+ port = strchr(server_buf, ':'); ++ port = strrchr(server_buf, ':'); + } + if (port != NULL) { + *port = '\0'; @@ -347,7 +347,7 @@ index 29a7691..4be5339 100644 + } + if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { + for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { -+ /* set server address with allocate memory */ ++ /* set server address with allocate memory */ + set_tacacs_server_addr(tac_srv_no, server); + + /* copy secret to key */ @@ -355,7 +355,7 @@ index 29a7691..4be5339 100644 + tac_srv_no++; + } + -+ /* release servers memory */ ++ /* release servers memory */ + freeaddrinfo(servers); + } else { + _pam_log (LOG_ERR, @@ -381,7 +381,7 @@ index 29a7691..4be5339 100644 - _pam_log(LOG_ERR, "error setting the source ip information"); + /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ + for(i = tac_srv_no-1; i >= 0; i--) { -+ if (tac_srv[i].key != NULL) ++ if (tac_srv[i].key[0] != 0) + break; + + /* copy secret to key */ @@ -476,7 +476,7 @@ index 29a7691..4be5339 100644 + return ctrl; +} /* _pam_parse */ diff --git a/support.h b/support.h -index 097c349..6820be3 100644 +index 097c349..bccc034 100644 --- a/support.h +++ b/support.h @@ -24,7 +24,13 @@ @@ -494,17 +494,15 @@ index 097c349..6820be3 100644 typedef struct { struct addrinfo *addr; -@@ -32,7 +38,9 @@ typedef struct { - } tacplus_server_t; +@@ -33,6 +39,7 @@ typedef struct { extern tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; -+ extern int tac_srv_no; +extern char *__vrfname; extern char tac_service[64]; extern char tac_protocol[64]; -@@ -48,7 +56,12 @@ void _pam_log (int, const char *, ...); +@@ -48,7 +55,12 @@ void _pam_log (int, const char *, ...); void *_xcalloc (size_t); char *_pam_get_user(pam_handle_t *); char *_pam_get_terminal(pam_handle_t *); diff --git a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch index a73c344df192..fb16575b9405 100644 --- a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch +++ b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch @@ -1,26 +1,17 @@ -From ad4136ca0e9f37861b17e15ec69860486ac00268 Mon Sep 17 00:00:00 2001 +From 436df1bd7841154f979872653558748a4033fdba Mon Sep 17 00:00:00 2001 From: liuh -Date: Fri, 1 Oct 2021 22:49:01 +0800 -Subject: [PATCH] Add setting flag for authorization and accounting. +Date: Sun, 3 Oct 2021 12:51:28 +0800 +Subject: [PATCH 3/3] Add setting flag for authorization and accounting. --- - support.c | 12 ++++++++++-- - support.h | 8 ++++++++ - 2 files changed, 18 insertions(+), 2 deletions(-) + support.c | 10 +++++++++- + support.h | 12 +++++++++++- + 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/support.c b/support.c -index 4be5339..d065023 100644 +index da7a58b..10d9749 100644 --- a/support.c +++ b/support.c -@@ -324,7 +324,7 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b - - /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ - for(i = tac_srv_no-1; i >= 0; i--) { -- if (tac_srv[i].key != NULL) -+ if (tac_srv[i].key[0] != 0) - break; - - /* copy secret to key */ @@ -344,7 +344,15 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b } else if (!strncmp (arg, "source_ip=", strlen("source_ip="))) { /* source ip for the packets */ @@ -39,10 +30,17 @@ index 4be5339..d065023 100644 _pam_log (LOG_WARNING, "unrecognized option: %s", arg); } diff --git a/support.h b/support.h -index 6820be3..7862e58 100644 +index bccc034..920689c 100644 --- a/support.h +++ b/support.h -@@ -32,6 +32,14 @@ +@@ -28,10 +28,20 @@ + + /* pam_tacplus command line options */ + #define PAM_TAC_DEBUG 0x01 +-#define PAM_TAC_ACCT 0x02 /* account on all specified servers */ ++#define PAM_TAC_ACCT 0x02 ++ ++/* account on all specified servers */ #define PAM_TAC_USE_FIRST_PASS 0x04 #define PAM_TAC_TRY_FIRST_PASS 0x08 From 14ea9aa5d9123d0011a3a8eff1c892acd53f3327 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Fri, 8 Oct 2021 13:08:28 +0800 Subject: [PATCH 09/12] Fix PR comments. --- ...memory-leak-when-parse-configuration.patch | 55 ++- ...acacs-support-functions-into-library.patch | 377 +++++++----------- ...lag-for-authorization-and-accounting.patch | 33 +- 3 files changed, 206 insertions(+), 259 deletions(-) diff --git a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch index 72a3c61f6978..cedadc955f56 100644 --- a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch +++ b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch @@ -1,16 +1,16 @@ -From e2364848d97f36b103893a27c8e833b1829b6383 Mon Sep 17 00:00:00 2001 +From a706774c8aa51bdbef4ab17c7792699d576c532b Mon Sep 17 00:00:00 2001 From: liuh Date: Fri, 1 Oct 2021 22:31:26 +0800 Subject: [PATCH 1/3] Fix memory leak when parse configuration. --- - pam_tacplus.c | 10 +++--- - support.c | 89 +++++++++++++++++++++++++++++++++++++++++++-------- - support.h | 4 +-- - 3 files changed, 84 insertions(+), 19 deletions(-) + pam_tacplus.c | 10 +++-- + support.c | 108 +++++++++++++++++++++++++++++++++++--------------- + support.h | 4 +- + 3 files changed, 84 insertions(+), 38 deletions(-) diff --git a/pam_tacplus.c b/pam_tacplus.c -index 9fc6be7..6d6a7a9 100644 +index 9fc6be7..79d8e34 100644 --- a/pam_tacplus.c +++ b/pam_tacplus.c @@ -322,8 +322,9 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, @@ -38,10 +38,10 @@ index 9fc6be7..6d6a7a9 100644 if (ctrl & PAM_TAC_DEBUG) syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); diff --git a/support.c b/support.c -index be1f21b..2e85bc0 100644 +index be1f21b..b940a40 100644 --- a/support.c +++ b/support.c -@@ -30,15 +30,25 @@ +@@ -30,7 +30,12 @@ #include #include @@ -54,12 +54,11 @@ index be1f21b..2e85bc0 100644 int tac_srv_no = 0; char tac_service[64]; - char tac_protocol[64]; +@@ -38,7 +43,12 @@ char tac_protocol[64]; char tac_prompt[64]; char *__vrfname=NULL; --char tac_source_ip[64]; + char tac_source_ip[64]; -struct addrinfo *tac_source_addr = NULL; -+char tac_source_ip[64]; + +/* source address */ +struct addrinfo *tac_source_addr=NULL; @@ -178,13 +177,39 @@ index be1f21b..2e85bc0 100644 /* 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); -+ strncpy(tac_source_ip, *argv + strlen("source_ip="), sizeof(tac_source_ip)); -+ set_source_ip(tac_source_ip, &tac_source_addr); ++ strncpy (tac_source_ip, *argv + strlen("source_ip="), sizeof(tac_source_ip)); ++ set_source_ip (tac_source_ip); } else { _pam_log (LOG_WARNING, "unrecognized option: %s", *argv); } +@@ -308,23 +371,4 @@ int _pam_parse (int argc, const char **argv) { + } + + 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; +- +- /* set the source ip address for the tacacs packets */ +- 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"); +- } +-} ++} /* _pam_parse */ +\ No newline at end of file diff --git a/support.h b/support.h -index b1faf43..097c349 100644 +index b1faf43..e20e227 100644 --- a/support.h +++ b/support.h @@ -27,8 +27,8 @@ @@ -199,5 +224,5 @@ index b1faf43..097c349 100644 extern tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; -- -2.27.0.windows.1 +2.17.1.windows.2 diff --git a/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch index 8123b09ba7a6..c1bae498af7b 100644 --- a/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch +++ b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch @@ -1,17 +1,17 @@ -From 7f560af088f3398885bbcc6996dfccfb06673a59 Mon Sep 17 00:00:00 2001 -From: liuh -Date: Sun, 3 Oct 2021 12:49:05 +0800 +From 80d195aa6e3a67d8080835102645622211f34d32 Mon Sep 17 00:00:00 2001 +From: liuh-80 <58683130+liuh-80@users.noreply.github.com> +Date: Fri, 8 Oct 2021 13:06:22 +0800 Subject: [PATCH 2/3] Extract tacacs support functions into library. --- Makefile.am | 16 ++- configure.ac | 3 +- libtacsupport.pc.in | 11 ++ - pam_tacplus.c | 5 +- - pam_tacplus.h | 6 - - support.c | 332 ++++++++++++++++++++++++-------------------- - support.h | 16 ++- - 7 files changed, 220 insertions(+), 169 deletions(-) + pam_tacplus.c | 3 - + pam_tacplus.h | 6 -- + support.c | 255 ++++++++++++++++++++++++++------------------ + support.h | 14 +++ + 7 files changed, 190 insertions(+), 118 deletions(-) create mode 100644 libtacsupport.pc.in diff --git a/Makefile.am b/Makefile.am @@ -91,21 +91,19 @@ index 0000000..1f12fe0 +Libs: -L${libdir} -ltacsupport +Cflags: -I${includedir} diff --git a/pam_tacplus.c b/pam_tacplus.c -index 6d6a7a9..3b88c83 100644 +index 79d8e34..4e6b3bb 100644 --- a/pam_tacplus.c +++ b/pam_tacplus.c -@@ -51,10 +51,7 @@ - static tacplus_server_t active_server; - +@@ -53,9 +53,6 @@ static tacplus_server_t active_server; /* accounting task identifier */ --static short int task_id = 0; -- + static short int task_id = 0; + -extern char *__vrfname; - -+static short int task_id = 0; - +- /* Helper functions */ int _pam_send_account(int tac_fd, int type, const char *user, char *tty, + char *r_addr, char *cmd) { diff --git a/pam_tacplus.h b/pam_tacplus.h index bc71b54..e7b30f7 100644 --- a/pam_tacplus.h @@ -124,7 +122,7 @@ index bc71b54..e7b30f7 100644 #define PAM_TAC_VMAJ 1 #define PAM_TAC_VMIN 3 diff --git a/support.c b/support.c -index 2e85bc0..da7a58b 100644 +index b940a40..8f08370 100644 --- a/support.c +++ b/support.c @@ -29,6 +29,7 @@ @@ -135,156 +133,10 @@ index 2e85bc0..da7a58b 100644 /* tacacs server information */ tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; -@@ -233,161 +234,186 @@ void set_source_ip(const char *tac_source_ip) { - _pam_log(LOG_DEBUG, "source ip is set"); +@@ -234,9 +235,155 @@ void set_source_ip(const char *tac_source_ip) { } } -- --int _pam_parse (int argc, const char **argv) { -- int ctrl = 0; -- const char *current_secret = NULL; -- -- /* otherwise the list will grow with each call */ -- memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); -- tac_srv_no = 0; -- -- tac_service[0] = 0; -- tac_protocol[0] = 0; -- tac_prompt[0] = 0; -- tac_login[0] = 0; -- tac_source_ip[0] = 0; -- -- for (ctrl = 0; argc-- > 0; ++argv) { -- if (!strcmp (*argv, "debug")) { /* all */ -- ctrl |= PAM_TAC_DEBUG; -- } else if (!strcmp (*argv, "use_first_pass")) { -- ctrl |= PAM_TAC_USE_FIRST_PASS; -- } else if (!strcmp (*argv, "try_first_pass")) { -- ctrl |= PAM_TAC_TRY_FIRST_PASS; -- } else if (!strncmp (*argv, "service=", 8)) { /* author & acct */ -- xstrcpy (tac_service, *argv + 8, sizeof(tac_service)); -- } else if (!strncmp (*argv, "protocol=", 9)) { /* author & acct */ -- xstrcpy (tac_protocol, *argv + 9, sizeof(tac_protocol)); -- } else if (!strncmp (*argv, "prompt=", 7)) { /* authentication */ -- xstrcpy (tac_prompt, *argv + 7, sizeof(tac_prompt)); -- /* Replace _ with space */ -- int chr; -- for (chr = 0; chr < strlen(tac_prompt); chr++) { -- if (tac_prompt[chr] == '_') { -- tac_prompt[chr] = ' '; -- } -- } -- } else if (!strncmp (*argv, "login=", 6)) { -- xstrcpy (tac_login, *argv + 6, sizeof(tac_login)); -- } else if (!strcmp (*argv, "acct_all")) { -- ctrl |= PAM_TAC_ACCT; -- } else if (!strncmp (*argv, "server=", 7)) { /* authen & acct */ -- if(tac_srv_no < TAC_PLUS_MAXSERVERS) { -- struct addrinfo hints, *servers, *server; -- int rv; -- char *close_bracket, *server_name, *port, server_buf[256]; -- -- memset(&hints, 0, sizeof hints); -- hints.ai_family = AF_UNSPEC; /* use IPv4 or IPv6, whichever */ -- hints.ai_socktype = SOCK_STREAM; -- -- if (strlen(*argv + 7) >= sizeof(server_buf)) { -- _pam_log(LOG_ERR, "server address too long, sorry"); -- continue; -- } -- strcpy(server_buf, *argv + 7); -- -- if (*server_buf == '[' && (close_bracket = strchr(server_buf, ']')) != NULL) { /* Check for URI syntax */ -- server_name = server_buf + 1; -- port = strrchr(close_bracket, ':'); -- *close_bracket = '\0'; -- } else { /* Fall back to traditional syntax */ -- server_name = server_buf; -- port = strrchr(server_buf, ':'); -- } -- if (port != NULL) { -- *port = '\0'; -- port++; -- } -- if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { -- for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { -- /* set server address with allocate memory */ -- set_tacacs_server_addr(tac_srv_no, server); -- -- /* copy secret to key */ -- snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); -- tac_srv_no++; -- } -- -- /* release servers memory */ -- freeaddrinfo(servers); -- } else { -- _pam_log (LOG_ERR, -- "skip invalid server: %s (getaddrinfo: %s)", -- server_name, gai_strerror(rv)); -- } -- } else { -- _pam_log(LOG_ERR, "maximum number of servers (%d) exceeded, skipping", -- TAC_PLUS_MAXSERVERS); -- } -- } else if (!strncmp (*argv, "secret=", 7)) { -- int i; -- -- current_secret = *argv + 7; /* points right into argv (which is const) */ -- -- /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ -- for(i = tac_srv_no-1; i >= 0; i--) { -- if (tac_srv[i].key[0] != 0) -- break; -- -- /* copy secret to key */ -- snprintf(tac_srv[i].key, sizeof(tac_srv[i].key), "%s", current_secret); -- } -- } else if (!strncmp (*argv, "timeout=", 8)) { -- /* FIXME atoi() doesn't handle invalid numeric strings well */ -- tac_timeout = atoi(*argv + 8); -- -- if (tac_timeout < 0) { -- tac_timeout = 0; -- } else { -- tac_readtimeout_enable = 1; -- } -- } else if(!strncmp(*argv, "vrf=", 4)) { -- __vrfname = strdup(*argv + 4); -- } 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); -- } -- } -- -- if (ctrl & PAM_TAC_DEBUG) { -- int n; -- -- _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); -- -- for(n = 0; n < tac_srv_no; n++) { -- _pam_log(LOG_DEBUG, "server[%d] { addr=%s, key='%c*****' }", n, tac_ntop(tac_srv[n].addr->ai_addr), tac_srv[n].key[0]); -- } -- -- _pam_log(LOG_DEBUG, "tac_service='%s'", tac_service); -- _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; +/* + * Parse one arguments. + * Use this method for both: @@ -371,14 +223,7 @@ index 2e85bc0..da7a58b 100644 + + /* points right into arg (which is const) */ + snprintf(current_secret, current_secret_buffer_size, "%s", arg + 7); - -- /* set the source ip address for the tacacs packets */ -- 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"); ++ + /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ + for(i = tac_srv_no-1; i >= 0; i--) { + if (tac_srv[i].key[0] != 0) @@ -402,8 +247,7 @@ index 2e85bc0..da7a58b 100644 + /* source ip for the packets */ + strncpy (tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); + set_source_ip (tac_source_ip); - } else { -- _pam_log(LOG_DEBUG, "source ip is set"); ++ } else { + _pam_log (LOG_WARNING, "unrecognized option: %s", arg); + } + @@ -432,69 +276,158 @@ index 2e85bc0..da7a58b 100644 + continue; /* skip comments and blank line. */ + strtok(line_buffer, " \t\n\r\f"); + ctrl |= _pam_parse_arg(line_buffer, current_secret, sizeof(current_secret)); - } ++ } + + fclose(config_file); + return ctrl; - } ++} + -+int _pam_parse (int argc, const char **argv) { -+ int ctrl = 0; + int _pam_parse (int argc, const char **argv) { + int ctrl = 0; +- const char *current_secret = NULL; + char current_secret[256]; + memset(current_secret, 0, sizeof(current_secret)); -+ -+ /* otherwise the list will grow with each call */ -+ memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); -+ tac_srv_no = 0; -+ -+ tac_service[0] = 0; -+ tac_protocol[0] = 0; -+ tac_prompt[0] = 0; -+ tac_login[0] = 0; -+ tac_source_ip[0] = 0; -+ -+ for (ctrl = 0; argc-- > 0; ++argv) { + + /* otherwise the list will grow with each call */ + memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); +@@ -249,109 +396,7 @@ int _pam_parse (int argc, const char **argv) { + tac_source_ip[0] = 0; + + for (ctrl = 0; argc-- > 0; ++argv) { +- if (!strcmp (*argv, "debug")) { /* all */ +- ctrl |= PAM_TAC_DEBUG; +- } else if (!strcmp (*argv, "use_first_pass")) { +- ctrl |= PAM_TAC_USE_FIRST_PASS; +- } else if (!strcmp (*argv, "try_first_pass")) { +- ctrl |= PAM_TAC_TRY_FIRST_PASS; +- } else if (!strncmp (*argv, "service=", 8)) { /* author & acct */ +- xstrcpy (tac_service, *argv + 8, sizeof(tac_service)); +- } else if (!strncmp (*argv, "protocol=", 9)) { /* author & acct */ +- xstrcpy (tac_protocol, *argv + 9, sizeof(tac_protocol)); +- } else if (!strncmp (*argv, "prompt=", 7)) { /* authentication */ +- xstrcpy (tac_prompt, *argv + 7, sizeof(tac_prompt)); +- /* Replace _ with space */ +- int chr; +- for (chr = 0; chr < strlen(tac_prompt); chr++) { +- if (tac_prompt[chr] == '_') { +- tac_prompt[chr] = ' '; +- } +- } +- } else if (!strncmp (*argv, "login=", 6)) { +- xstrcpy (tac_login, *argv + 6, sizeof(tac_login)); +- } else if (!strcmp (*argv, "acct_all")) { +- ctrl |= PAM_TAC_ACCT; +- } else if (!strncmp (*argv, "server=", 7)) { /* authen & acct */ +- if(tac_srv_no < TAC_PLUS_MAXSERVERS) { +- struct addrinfo hints, *servers, *server; +- int rv; +- char *close_bracket, *server_name, *port, server_buf[256]; +- +- memset(&hints, 0, sizeof hints); +- hints.ai_family = AF_UNSPEC; /* use IPv4 or IPv6, whichever */ +- hints.ai_socktype = SOCK_STREAM; +- +- if (strlen(*argv + 7) >= sizeof(server_buf)) { +- _pam_log(LOG_ERR, "server address too long, sorry"); +- continue; +- } +- strcpy(server_buf, *argv + 7); +- +- if (*server_buf == '[' && (close_bracket = strchr(server_buf, ']')) != NULL) { /* Check for URI syntax */ +- server_name = server_buf + 1; +- port = strrchr(close_bracket, ':'); +- *close_bracket = '\0'; +- } else { /* Fall back to traditional syntax */ +- server_name = server_buf; +- port = strrchr(server_buf, ':'); +- } +- if (port != NULL) { +- *port = '\0'; +- port++; +- } +- if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { +- for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { +- /* set server address with allocate memory */ +- set_tacacs_server_addr(tac_srv_no, server); +- +- /* copy secret to key */ +- snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); +- tac_srv_no++; +- } +- +- /* release servers memory */ +- freeaddrinfo(servers); +- } else { +- _pam_log (LOG_ERR, +- "skip invalid server: %s (getaddrinfo: %s)", +- server_name, gai_strerror(rv)); +- } +- } else { +- _pam_log(LOG_ERR, "maximum number of servers (%d) exceeded, skipping", +- TAC_PLUS_MAXSERVERS); +- } +- } else if (!strncmp (*argv, "secret=", 7)) { +- int i; +- +- current_secret = *argv + 7; /* points right into argv (which is const) */ +- +- /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ +- for(i = tac_srv_no-1; i >= 0; i--) { +- if (tac_srv[i].key[0] != 0) +- break; +- +- /* copy secret to key */ +- snprintf(tac_srv[i].key, sizeof(tac_srv[i].key), "%s", current_secret); +- } +- } else if (!strncmp (*argv, "timeout=", 8)) { +- /* FIXME atoi() doesn't handle invalid numeric strings well */ +- tac_timeout = atoi(*argv + 8); +- +- if (tac_timeout < 0) { +- tac_timeout = 0; +- } else { +- tac_readtimeout_enable = 1; +- } +- } else if(!strncmp(*argv, "vrf=", 4)) { +- __vrfname = strdup(*argv + 4); +- } 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); +- } else { +- _pam_log (LOG_WARNING, "unrecognized option: %s", *argv); +- } + ctrl |= _pam_parse_arg(*argv, current_secret, sizeof(current_secret)); -+ } -+ -+ if (ctrl & PAM_TAC_DEBUG) { -+ int n; -+ -+ _pam_log(LOG_DEBUG, "%d servers defined", tac_srv_no); -+ -+ for(n = 0; n < tac_srv_no; n++) { -+ _pam_log(LOG_DEBUG, "server[%d] { addr=%s, key='%c*****' }", n, tac_ntop(tac_srv[n].addr->ai_addr), tac_srv[n].key[0]); -+ } -+ -+ _pam_log(LOG_DEBUG, "tac_service='%s'", tac_service); -+ _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; + } + + if (ctrl & PAM_TAC_DEBUG) { +@@ -371,4 +416,4 @@ int _pam_parse (int argc, const char **argv) { + } + + return ctrl; +-} /* _pam_parse */ +\ No newline at end of file +} /* _pam_parse */ diff --git a/support.h b/support.h -index 097c349..bccc034 100644 +index e20e227..3193168 100644 --- a/support.h +++ b/support.h -@@ -24,7 +24,13 @@ +@@ -26,6 +26,14 @@ - #include "libtac.h" + #include --#include -+#include -+ +/* pam_tacplus command line options */ +#define PAM_TAC_DEBUG 0x01 -+#define PAM_TAC_ACCT 0x02 /* account on all specified servers */ ++#define PAM_TAC_ACCT 0x02 ++ ++/* account on all specified servers */ +#define PAM_TAC_USE_FIRST_PASS 0x04 +#define PAM_TAC_TRY_FIRST_PASS 0x08 - ++ typedef struct { struct addrinfo *addr; -@@ -33,6 +39,7 @@ typedef struct { + char key[256]; +@@ -33,6 +41,7 @@ typedef struct { extern tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; extern int tac_srv_no; @@ -502,12 +435,10 @@ index 097c349..bccc034 100644 extern char tac_service[64]; extern char tac_protocol[64]; -@@ -48,7 +55,12 @@ void _pam_log (int, const char *, ...); - void *_xcalloc (size_t); +@@ -49,6 +58,11 @@ void *_xcalloc (size_t); char *_pam_get_user(pam_handle_t *); char *_pam_get_terminal(pam_handle_t *); --char *_pam_get_rhost(pam_handle_t *); -+char *_pam_get_rhost(pam_handle_t *); + char *_pam_get_rhost(pam_handle_t *); + +/* + * Parse config file. @@ -517,5 +448,5 @@ index 097c349..bccc034 100644 #endif /* PAM_TACPLUS_SUPPORT_H */ -- -2.27.0.windows.1 +2.17.1.windows.2 diff --git a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch index fb16575b9405..d9b79452453e 100644 --- a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch +++ b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch @@ -1,23 +1,21 @@ -From 436df1bd7841154f979872653558748a4033fdba Mon Sep 17 00:00:00 2001 -From: liuh -Date: Sun, 3 Oct 2021 12:51:28 +0800 +From f45e079f1f73e8c4ac315b62aa395754c1e53eb5 Mon Sep 17 00:00:00 2001 +From: liuh-80 <58683130+liuh-80@users.noreply.github.com> +Date: Fri, 8 Oct 2021 13:07:17 +0800 Subject: [PATCH 3/3] Add setting flag for authorization and accounting. --- - support.c | 10 +++++++++- - support.h | 12 +++++++++++- - 2 files changed, 20 insertions(+), 2 deletions(-) + support.c | 8 ++++++++ + support.h | 8 ++++++++ + 2 files changed, 16 insertions(+) diff --git a/support.c b/support.c -index da7a58b..10d9749 100644 +index 8f08370..890616c 100644 --- a/support.c +++ b/support.c -@@ -344,7 +344,15 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b - } else if (!strncmp (arg, "source_ip=", strlen("source_ip="))) { +@@ -345,6 +345,14 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b /* source ip for the packets */ strncpy (tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); -- set_source_ip (tac_source_ip); -+ set_source_ip (tac_source_ip); + set_source_ip (tac_source_ip); + } else if (!strcmp (arg, "local_accounting")) { + ctrl |= ACCOUNTING_FLAG_LOCAL; + } else if (!strcmp (arg, "tacacs_accounting")) { @@ -30,17 +28,10 @@ index da7a58b..10d9749 100644 _pam_log (LOG_WARNING, "unrecognized option: %s", arg); } diff --git a/support.h b/support.h -index bccc034..920689c 100644 +index 3193168..d5945a0 100644 --- a/support.h +++ b/support.h -@@ -28,10 +28,20 @@ - - /* pam_tacplus command line options */ - #define PAM_TAC_DEBUG 0x01 --#define PAM_TAC_ACCT 0x02 /* account on all specified servers */ -+#define PAM_TAC_ACCT 0x02 -+ -+/* account on all specified servers */ +@@ -34,6 +34,14 @@ #define PAM_TAC_USE_FIRST_PASS 0x04 #define PAM_TAC_TRY_FIRST_PASS 0x08 @@ -56,5 +47,5 @@ index bccc034..920689c 100644 struct addrinfo *addr; char key[256]; -- -2.27.0.windows.1 +2.17.1.windows.2 From 140e4d4e35e705cce9ad6e9b48217dc379c158f7 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Mon, 11 Oct 2021 16:08:08 +0800 Subject: [PATCH 10/12] Improve patches. --- ...06-Add-support-for-source-ip-address.patch | 99 +++++++----- ...memory-leak-when-parse-configuration.patch | 151 +++--------------- ...acacs-support-functions-into-library.patch | 37 ++--- ...lag-for-authorization-and-accounting.patch | 10 +- 4 files changed, 107 insertions(+), 190 deletions(-) diff --git a/src/tacacs/pam/0006-Add-support-for-source-ip-address.patch b/src/tacacs/pam/0006-Add-support-for-source-ip-address.patch index 280cfeee28fb..684ec5c64513 100644 --- a/src/tacacs/pam/0006-Add-support-for-source-ip-address.patch +++ b/src/tacacs/pam/0006-Add-support-for-source-ip-address.patch @@ -1,16 +1,16 @@ -From 9c26e734cf9e5cec950dc8b8f474f89d87833bcd Mon Sep 17 00:00:00 2001 +From 5777c81f86be4d10c14ca6f33280ef65c986c4a8 Mon Sep 17 00:00:00 2001 From: Venkatesan Mahalingam -Date: Wed, 1 Jul 2020 18:57:28 -0700 -Subject: [PATCH] Add support to specify source address for TACACS+ +Date: Thu, 2 Jul 2020 09:57:28 +0800 +Subject: [PATCH 1/4] Add support to specify source address for TACACS+ --- pam_tacplus.c | 8 ++++---- - support.c | 31 +++++++++++++++++++++++++++++++ + support.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++-- support.h | 1 + - 3 files changed, 36 insertions(+), 4 deletions(-) + 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/pam_tacplus.c b/pam_tacplus.c -index 38e2a70..ec8ea27 100644 +index 7544b2e..9fc6be7 100644 --- a/pam_tacplus.c +++ b/pam_tacplus.c @@ -177,7 +177,7 @@ int _pam_account(pam_handle_t *pamh, int argc, const char **argv, @@ -50,43 +50,86 @@ index 38e2a70..ec8ea27 100644 _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i); continue; diff --git a/support.c b/support.c -index 7c00618..3e55e2f 100644 +index 8f42a0c..893712e 100644 --- a/support.c +++ b/support.c -@@ -37,6 +37,8 @@ char tac_service[64]; +@@ -37,6 +37,13 @@ char tac_service[64]; char tac_protocol[64]; char tac_prompt[64]; char *__vrfname=NULL; +char tac_source_ip[64]; -+struct addrinfo *tac_source_addr = NULL; ++ ++/* source address */ ++struct addrinfo *tac_source_addr=NULL; ++struct addrinfo tac_source_address; ++struct sockaddr tac_source_sock_addr; ++struct sockaddr_in6 tac_source_sock6_addr; void _pam_log(int err, const char *format,...) { char msg[256]; -@@ -183,6 +185,12 @@ int _pam_parse (int argc, const char **argv) { +@@ -171,6 +178,37 @@ int tacacs_get_password (pam_handle_t * pamh, int flags + return PAM_SUCCESS; + } + ++/* set source ip address for the outgoing tacacs packets */ ++void set_source_ip(const char *tac_source_ip) { ++ ++ struct addrinfo hints, *source_address; ++ int rv; ++ ++ /* set the source ip address for the tacacs packets */ ++ 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 { ++ tac_source_addr = &tac_source_address; ++ memcpy(tac_source_addr, source_address, sizeof(struct addrinfo)); ++ ++ if (source_address->ai_family == AF_INET6) { ++ tac_source_addr->ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); ++ memcpy(tac_source_addr->ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); ++ } ++ else { ++ tac_source_addr->ai_addr = &(tac_source_sock_addr); ++ memcpy(tac_source_addr->ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); ++ } ++ ++ freeaddrinfo(source_address); ++ _pam_log(LOG_DEBUG, "source ip is set"); ++ } ++} ++ + int _pam_parse (int argc, const char **argv) { + int ctrl = 0; + const char *current_secret = NULL; +@@ -183,6 +221,12 @@ int _pam_parse (int argc, const char **argv) { tac_protocol[0] = 0; tac_prompt[0] = 0; tac_login[0] = 0; + tac_source_ip[0] = 0; + + if (tac_source_addr != NULL) { -+ freeaddrinfo(tac_source_addr); ++ /* reset source address */ + tac_source_addr = NULL; + } for (ctrl = 0; argc-- > 0; ++argv) { if (!strcmp (*argv, "debug")) { /* all */ -@@ -274,6 +282,10 @@ int _pam_parse (int argc, const char **argv) { +@@ -274,6 +318,10 @@ int _pam_parse (int argc, const char **argv) { } } else if(!strncmp(*argv, "vrf=", 4)) { __vrfname = strdup(*argv + 4); + } 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); ++ set_source_ip(tac_source_ip); } else { _pam_log (LOG_WARNING, "unrecognized option: %s", *argv); } -@@ -292,8 +304,27 @@ int _pam_parse (int argc, const char **argv) { +@@ -292,8 +340,8 @@ 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); @@ -94,28 +137,12 @@ index 7c00618..3e55e2f 100644 } 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; -+ -+ /* set the source ip address for the tacacs packets */ -+ 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"); -+ } -+} +-} /* _pam_parse */ +- ++} /* _pam_parse */ +\ No newline at end of file diff --git a/support.h b/support.h -index 9cbd040..09b8a85 100644 +index 9cbd040..b1faf43 100644 --- a/support.h +++ b/support.h @@ -37,6 +37,7 @@ extern int tac_srv_no; @@ -127,5 +154,5 @@ index 9cbd040..09b8a85 100644 int _pam_parse (int, const char **); unsigned long _resolve_name (char *); -- -2.7.4 +2.17.1.windows.2 diff --git a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch index cedadc955f56..bcfcd154847b 100644 --- a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch +++ b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch @@ -1,44 +1,40 @@ -From a706774c8aa51bdbef4ab17c7792699d576c532b Mon Sep 17 00:00:00 2001 -From: liuh -Date: Fri, 1 Oct 2021 22:31:26 +0800 -Subject: [PATCH 1/3] Fix memory leak when parse configuration. +From 3fe58149e32e9ccef64443d15d51052c5fedde13 Mon Sep 17 00:00:00 2001 +From: liuh-80 <58683130+liuh-80@users.noreply.github.com> +Date: Mon, 11 Oct 2021 15:53:17 +0800 +Subject: [PATCH 2/4] Fix memory leak when parse configuration. --- - pam_tacplus.c | 10 +++-- - support.c | 108 +++++++++++++++++++++++++++++++++++--------------- - support.h | 4 +- - 3 files changed, 84 insertions(+), 38 deletions(-) + pam_tacplus.c | 6 ++++-- + support.c | 37 +++++++++++++++++++++++++++++++++---- + support.h | 2 +- + 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/pam_tacplus.c b/pam_tacplus.c -index 9fc6be7..79d8e34 100644 +index 9fc6be7..d062359 100644 --- a/pam_tacplus.c +++ b/pam_tacplus.c -@@ -322,8 +322,9 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, - } +@@ -323,7 +323,8 @@ int pam_sm_authenticate (pam_handle_t * pamh, int flags, status = PAM_SUCCESS; communicating = 0; -- active_server.addr = tac_srv[srv_i].addr; + active_server.addr = tac_srv[srv_i].addr; - active_server.key = tac_srv[srv_i].key; -+ active_server.addr = tac_srv[srv_i].addr; + /* copy secret to key */ + snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); if (ctrl & PAM_TAC_DEBUG) syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); -@@ -819,8 +820,9 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, - status = PAM_SUCCESS; +@@ -820,7 +821,8 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags, communicating = 0; -- active_server.addr = tac_srv[srv_i].addr; + active_server.addr = tac_srv[srv_i].addr; - active_server.key = tac_srv[srv_i].key; -+ active_server.addr = tac_srv[srv_i].addr; + /* copy secret to key */ + snprintf(active_server.key, sizeof(active_server.key), "%s", tac_srv[srv_i].key); if (ctrl & PAM_TAC_DEBUG) syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); diff --git a/support.c b/support.c -index be1f21b..b940a40 100644 +index 893712e..c1ea21b 100644 --- a/support.c +++ b/support.c @@ -30,7 +30,12 @@ @@ -54,25 +50,10 @@ index be1f21b..b940a40 100644 int tac_srv_no = 0; char tac_service[64]; -@@ -38,7 +43,12 @@ char tac_protocol[64]; - char tac_prompt[64]; - char *__vrfname=NULL; - char tac_source_ip[64]; --struct addrinfo *tac_source_addr = NULL; -+ -+/* source address */ -+struct addrinfo *tac_source_addr=NULL; -+struct addrinfo tac_source_address; -+struct sockaddr tac_source_sock_addr; -+struct sockaddr_in6 tac_source_sock6_addr; - - void _pam_log(int err, const char *format,...) { - char msg[256]; -@@ -172,6 +182,57 @@ int tacacs_get_password (pam_handle_t * pamh, int flags - +@@ -178,6 +183,26 @@ int tacacs_get_password (pam_handle_t * pamh, int flags return PAM_SUCCESS; } -+ + +/* + * Set tacacs server addrinfo. + */ @@ -93,52 +74,10 @@ index be1f21b..b940a40 100644 + tac_srv[tac_srv_no].addr->ai_next = NULL; +} + -+/* set source ip address for the outgoing tacacs packets */ -+void set_source_ip(const char *tac_source_ip) { -+ -+ struct addrinfo hints, *source_address; -+ int rv; -+ -+ /* set the source ip address for the tacacs packets */ -+ 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 { -+ tac_source_addr = &tac_source_address; -+ memcpy(tac_source_addr, source_address, sizeof(struct addrinfo)); -+ -+ if (source_address->ai_family == AF_INET6) { -+ tac_source_addr->ai_addr = (struct sockaddr *)&(tac_source_sock6_addr); -+ memcpy(tac_source_addr->ai_addr, source_address->ai_addr, sizeof(struct sockaddr_in6)); -+ } -+ else { -+ tac_source_addr->ai_addr = &(tac_source_sock_addr); -+ memcpy(tac_source_addr->ai_addr, source_address->ai_addr, sizeof(struct sockaddr)); -+ } -+ -+ freeaddrinfo(source_address); -+ _pam_log(LOG_DEBUG, "source ip is set"); -+ } -+} - - int _pam_parse (int argc, const char **argv) { - int ctrl = 0; -@@ -186,11 +247,6 @@ int _pam_parse (int argc, const char **argv) { - tac_prompt[0] = 0; - tac_login[0] = 0; - tac_source_ip[0] = 0; -- -- if (tac_source_addr != NULL) { -- freeaddrinfo(tac_source_addr); -- tac_source_addr = NULL; -- } + /* set source ip address for the outgoing tacacs packets */ + void set_source_ip(const char *tac_source_ip) { - for (ctrl = 0; argc-- > 0; ++argv) { - if (!strcmp (*argv, "debug")) { /* all */ -@@ -246,10 +302,16 @@ int _pam_parse (int argc, const char **argv) { +@@ -282,8 +307,11 @@ int _pam_parse (int argc, const char **argv) { } if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { @@ -151,13 +90,8 @@ index be1f21b..b940a40 100644 + snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); tac_srv_no++; } -+ -+ /* release servers memory */ -+ freeaddrinfo(servers); } else { - _pam_log (LOG_ERR, - "skip invalid server: %s (getaddrinfo: %s)", -@@ -266,10 +328,11 @@ int _pam_parse (int argc, const char **argv) { +@@ -302,10 +330,11 @@ int _pam_parse (int argc, const char **argv) { /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ for(i = tac_srv_no-1; i >= 0; i--) { @@ -171,54 +105,15 @@ index be1f21b..b940a40 100644 } } else if (!strncmp (*argv, "timeout=", 8)) { /* FIXME atoi() doesn't handle invalid numeric strings well */ -@@ -284,8 +347,8 @@ int _pam_parse (int argc, const char **argv) { - __vrfname = strdup(*argv + 4); - } 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); -+ strncpy (tac_source_ip, *argv + strlen("source_ip="), sizeof(tac_source_ip)); -+ set_source_ip (tac_source_ip); - } else { - _pam_log (LOG_WARNING, "unrecognized option: %s", *argv); - } -@@ -308,23 +371,4 @@ int _pam_parse (int argc, const char **argv) { - } - - 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; -- -- /* set the source ip address for the tacacs packets */ -- 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"); -- } --} -+} /* _pam_parse */ -\ No newline at end of file diff --git a/support.h b/support.h -index b1faf43..e20e227 100644 +index b1faf43..6bcb07f 100644 --- a/support.h +++ b/support.h -@@ -27,8 +27,8 @@ - #include +@@ -28,7 +28,7 @@ typedef struct { -- struct addrinfo *addr; + struct addrinfo *addr; - const char *key; -+ struct addrinfo *addr; + char key[256]; } tacplus_server_t; diff --git a/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch index c1bae498af7b..3d0ce0976e56 100644 --- a/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch +++ b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch @@ -1,7 +1,7 @@ -From 80d195aa6e3a67d8080835102645622211f34d32 Mon Sep 17 00:00:00 2001 +From ed73b206f1303a75c03a1cb7d7a06c375519a4e0 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> -Date: Fri, 8 Oct 2021 13:06:22 +0800 -Subject: [PATCH 2/3] Extract tacacs support functions into library. +Date: Mon, 11 Oct 2021 15:58:49 +0800 +Subject: [PATCH 3/4] Extract tacacs support functions into library. --- Makefile.am | 16 ++- @@ -11,7 +11,7 @@ Subject: [PATCH 2/3] Extract tacacs support functions into library. pam_tacplus.h | 6 -- support.c | 255 ++++++++++++++++++++++++++------------------ support.h | 14 +++ - 7 files changed, 190 insertions(+), 118 deletions(-) + 7 files changed, 194 insertions(+), 114 deletions(-) create mode 100644 libtacsupport.pc.in diff --git a/Makefile.am b/Makefile.am @@ -91,7 +91,7 @@ index 0000000..1f12fe0 +Libs: -L${libdir} -ltacsupport +Cflags: -I${includedir} diff --git a/pam_tacplus.c b/pam_tacplus.c -index 79d8e34..4e6b3bb 100644 +index d062359..2a484f0 100644 --- a/pam_tacplus.c +++ b/pam_tacplus.c @@ -53,9 +53,6 @@ static tacplus_server_t active_server; @@ -122,7 +122,7 @@ index bc71b54..e7b30f7 100644 #define PAM_TAC_VMAJ 1 #define PAM_TAC_VMIN 3 diff --git a/support.c b/support.c -index b940a40..8f08370 100644 +index c1ea21b..e4b667d 100644 --- a/support.c +++ b/support.c @@ -29,6 +29,7 @@ @@ -133,7 +133,7 @@ index b940a40..8f08370 100644 /* tacacs server information */ tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; -@@ -234,9 +235,155 @@ void set_source_ip(const char *tac_source_ip) { +@@ -234,9 +235,160 @@ void set_source_ip(const char *tac_source_ip) { } } @@ -269,6 +269,11 @@ index b940a40..8f08370 100644 + return 0; + } + ++ if (tac_source_addr != NULL) { ++ /* reset source address */ ++ tac_source_addr = NULL; ++ } ++ + char current_secret[256]; + memset(current_secret, 0, sizeof(current_secret)); + while (fgets(line_buffer, sizeof line_buffer, config_file)) { @@ -290,8 +295,8 @@ index b940a40..8f08370 100644 /* otherwise the list will grow with each call */ memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); -@@ -249,109 +396,7 @@ int _pam_parse (int argc, const char **argv) { - tac_source_ip[0] = 0; +@@ -254,106 +406,7 @@ int _pam_parse (int argc, const char **argv) { + } for (ctrl = 0; argc-- > 0; ++argv) { - if (!strcmp (*argv, "debug")) { /* all */ @@ -354,9 +359,6 @@ index b940a40..8f08370 100644 - snprintf(tac_srv[tac_srv_no].key, sizeof(tac_srv[tac_srv_no].key), "%s", current_secret); - tac_srv_no++; - } -- -- /* release servers memory */ -- freeaddrinfo(servers); - } else { - _pam_log (LOG_ERR, - "skip invalid server: %s (getaddrinfo: %s)", @@ -393,7 +395,7 @@ index b940a40..8f08370 100644 - } 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); +- set_source_ip(tac_source_ip); - } else { - _pam_log (LOG_WARNING, "unrecognized option: %s", *argv); - } @@ -401,15 +403,8 @@ index b940a40..8f08370 100644 } if (ctrl & PAM_TAC_DEBUG) { -@@ -371,4 +416,4 @@ int _pam_parse (int argc, const char **argv) { - } - - return ctrl; --} /* _pam_parse */ -\ No newline at end of file -+} /* _pam_parse */ diff --git a/support.h b/support.h -index e20e227..3193168 100644 +index 6bcb07f..201ae55 100644 --- a/support.h +++ b/support.h @@ -26,6 +26,14 @@ diff --git a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch index d9b79452453e..ff6bf55cb8e6 100644 --- a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch +++ b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch @@ -1,7 +1,7 @@ -From f45e079f1f73e8c4ac315b62aa395754c1e53eb5 Mon Sep 17 00:00:00 2001 +From a14c6557cf473e6367ace3905147dad24133b681 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> -Date: Fri, 8 Oct 2021 13:07:17 +0800 -Subject: [PATCH 3/3] Add setting flag for authorization and accounting. +Date: Mon, 11 Oct 2021 16:01:22 +0800 +Subject: [PATCH 4/4] Add setting flag for authorization and accounting. --- support.c | 8 ++++++++ @@ -9,7 +9,7 @@ Subject: [PATCH 3/3] Add setting flag for authorization and accounting. 2 files changed, 16 insertions(+) diff --git a/support.c b/support.c -index 8f08370..890616c 100644 +index e4b667d..820f1d0 100644 --- a/support.c +++ b/support.c @@ -345,6 +345,14 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b @@ -28,7 +28,7 @@ index 8f08370..890616c 100644 _pam_log (LOG_WARNING, "unrecognized option: %s", arg); } diff --git a/support.h b/support.h -index 3193168..d5945a0 100644 +index 201ae55..dbd85e1 100644 --- a/support.h +++ b/support.h @@ -34,6 +34,14 @@ From 15168a1fb356ca5fd682dcdbf7a5ef2ea9dd35a7 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Tue, 12 Oct 2021 10:14:27 +0800 Subject: [PATCH 11/12] Fix PR comments. --- ...06-Add-support-for-source-ip-address.patch | 32 ++++++++++--------- ...memory-leak-when-parse-configuration.patch | 15 +++++---- ...acacs-support-functions-into-library.patch | 19 ++++++----- ...lag-for-authorization-and-accounting.patch | 10 +++--- 4 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/tacacs/pam/0006-Add-support-for-source-ip-address.patch b/src/tacacs/pam/0006-Add-support-for-source-ip-address.patch index 684ec5c64513..affb9e760e80 100644 --- a/src/tacacs/pam/0006-Add-support-for-source-ip-address.patch +++ b/src/tacacs/pam/0006-Add-support-for-source-ip-address.patch @@ -1,13 +1,13 @@ -From 5777c81f86be4d10c14ca6f33280ef65c986c4a8 Mon Sep 17 00:00:00 2001 +From 49526a27e90647ed4e48c1d1d88e0c75a1ce221b Mon Sep 17 00:00:00 2001 From: Venkatesan Mahalingam Date: Thu, 2 Jul 2020 09:57:28 +0800 Subject: [PATCH 1/4] Add support to specify source address for TACACS+ --- pam_tacplus.c | 8 ++++---- - support.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++-- + support.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++-- support.h | 1 + - 3 files changed, 55 insertions(+), 6 deletions(-) + 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/pam_tacplus.c b/pam_tacplus.c index 7544b2e..9fc6be7 100644 @@ -50,29 +50,31 @@ index 7544b2e..9fc6be7 100644 _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i); continue; diff --git a/support.c b/support.c -index 8f42a0c..893712e 100644 +index 8f42a0c..164df62 100644 --- a/support.c +++ b/support.c -@@ -37,6 +37,13 @@ char tac_service[64]; +@@ -37,6 +37,8 @@ char tac_service[64]; char tac_protocol[64]; char tac_prompt[64]; char *__vrfname=NULL; +char tac_source_ip[64]; -+ -+/* source address */ -+struct addrinfo *tac_source_addr=NULL; -+struct addrinfo tac_source_address; -+struct sockaddr tac_source_sock_addr; -+struct sockaddr_in6 tac_source_sock6_addr; ++struct addrinfo *tac_source_addr = NULL; void _pam_log(int err, const char *format,...) { char msg[256]; -@@ -171,6 +178,37 @@ int tacacs_get_password (pam_handle_t * pamh, int flags +@@ -171,6 +173,44 @@ int tacacs_get_password (pam_handle_t * pamh, int flags return PAM_SUCCESS; } +/* set source ip address for the outgoing tacacs packets */ +void set_source_ip(const char *tac_source_ip) { ++ /* ++ addrinfo created by getaddrinfo must be released with freeaddrinfo. ++ so source ip address will be stored in following static variables. ++ */ ++ static struct addrinfo tac_source_address; ++ static struct sockaddr tac_source_sock_addr; ++ static struct sockaddr_in6 tac_source_sock6_addr; + + struct addrinfo hints, *source_address; + int rv; @@ -105,7 +107,7 @@ index 8f42a0c..893712e 100644 int _pam_parse (int argc, const char **argv) { int ctrl = 0; const char *current_secret = NULL; -@@ -183,6 +221,12 @@ int _pam_parse (int argc, const char **argv) { +@@ -183,6 +223,12 @@ int _pam_parse (int argc, const char **argv) { tac_protocol[0] = 0; tac_prompt[0] = 0; tac_login[0] = 0; @@ -118,7 +120,7 @@ index 8f42a0c..893712e 100644 for (ctrl = 0; argc-- > 0; ++argv) { if (!strcmp (*argv, "debug")) { /* all */ -@@ -274,6 +318,10 @@ int _pam_parse (int argc, const char **argv) { +@@ -274,6 +320,10 @@ int _pam_parse (int argc, const char **argv) { } } else if(!strncmp(*argv, "vrf=", 4)) { __vrfname = strdup(*argv + 4); @@ -129,7 +131,7 @@ index 8f42a0c..893712e 100644 } else { _pam_log (LOG_WARNING, "unrecognized option: %s", *argv); } -@@ -292,8 +340,8 @@ int _pam_parse (int argc, const char **argv) { +@@ -292,8 +342,8 @@ 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); diff --git a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch index bcfcd154847b..f79521d9028d 100644 --- a/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch +++ b/src/tacacs/pam/0007-Fix-memory-leak-when-parse-configuration.patch @@ -1,7 +1,8 @@ -From 3fe58149e32e9ccef64443d15d51052c5fedde13 Mon Sep 17 00:00:00 2001 +From 99eeeccd14c905b7ad77210343bb07334eb0e8d1 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> -Date: Mon, 11 Oct 2021 15:53:17 +0800 +Date: Tue, 12 Oct 2021 10:05:28 +0800 Subject: [PATCH 2/4] Fix memory leak when parse configuration. +The fix code in this patch are copy from upstream project: https://github.com/kravietz/pam_tacplus/blob/master/support.c --- pam_tacplus.c | 6 ++++-- @@ -34,7 +35,7 @@ index 9fc6be7..d062359 100644 if (ctrl & PAM_TAC_DEBUG) syslog(LOG_DEBUG, "%s: active srv %d", __FUNCTION__, srv_i); diff --git a/support.c b/support.c -index 893712e..c1ea21b 100644 +index 164df62..e22fa31 100644 --- a/support.c +++ b/support.c @@ -30,7 +30,12 @@ @@ -50,7 +51,7 @@ index 893712e..c1ea21b 100644 int tac_srv_no = 0; char tac_service[64]; -@@ -178,6 +183,26 @@ int tacacs_get_password (pam_handle_t * pamh, int flags +@@ -173,6 +178,26 @@ int tacacs_get_password (pam_handle_t * pamh, int flags return PAM_SUCCESS; } @@ -76,8 +77,8 @@ index 893712e..c1ea21b 100644 + /* set source ip address for the outgoing tacacs packets */ void set_source_ip(const char *tac_source_ip) { - -@@ -282,8 +307,11 @@ int _pam_parse (int argc, const char **argv) { + /* +@@ -284,8 +309,11 @@ int _pam_parse (int argc, const char **argv) { } if ((rv = getaddrinfo(server_name, (port == NULL) ? "49" : port, &hints, &servers)) == 0) { for(server = servers; server != NULL && tac_srv_no < TAC_PLUS_MAXSERVERS; server = server->ai_next) { @@ -91,7 +92,7 @@ index 893712e..c1ea21b 100644 tac_srv_no++; } } else { -@@ -302,10 +330,11 @@ int _pam_parse (int argc, const char **argv) { +@@ -304,10 +332,11 @@ int _pam_parse (int argc, const char **argv) { /* if 'secret=' was given after a 'server=' parameter, fill in the current secret */ for(i = tac_srv_no-1; i >= 0; i--) { diff --git a/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch index 3d0ce0976e56..139c49564c00 100644 --- a/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch +++ b/src/tacacs/pam/0008-Extract-tacacs-support-functions-into-library.patch @@ -1,6 +1,6 @@ -From ed73b206f1303a75c03a1cb7d7a06c375519a4e0 Mon Sep 17 00:00:00 2001 +From d820001f60e0a9f5e5df83b1edb229be5212e0b5 Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> -Date: Mon, 11 Oct 2021 15:58:49 +0800 +Date: Tue, 12 Oct 2021 10:09:10 +0800 Subject: [PATCH 3/4] Extract tacacs support functions into library. --- @@ -122,7 +122,7 @@ index bc71b54..e7b30f7 100644 #define PAM_TAC_VMAJ 1 #define PAM_TAC_VMIN 3 diff --git a/support.c b/support.c -index c1ea21b..e4b667d 100644 +index e22fa31..5b6e1fa 100644 --- a/support.c +++ b/support.c @@ -29,6 +29,7 @@ @@ -133,7 +133,7 @@ index c1ea21b..e4b667d 100644 /* tacacs server information */ tacplus_server_t tac_srv[TAC_PLUS_MAXSERVERS]; -@@ -234,9 +235,160 @@ void set_source_ip(const char *tac_source_ip) { +@@ -236,9 +237,160 @@ void set_source_ip(const char *tac_source_ip) { } } @@ -295,7 +295,7 @@ index c1ea21b..e4b667d 100644 /* otherwise the list will grow with each call */ memset(tac_srv, 0, sizeof(tacplus_server_t) * TAC_PLUS_MAXSERVERS); -@@ -254,106 +406,7 @@ int _pam_parse (int argc, const char **argv) { +@@ -256,106 +408,7 @@ int _pam_parse (int argc, const char **argv) { } for (ctrl = 0; argc-- > 0; ++argv) { @@ -404,7 +404,7 @@ index c1ea21b..e4b667d 100644 if (ctrl & PAM_TAC_DEBUG) { diff --git a/support.h b/support.h -index 6bcb07f..201ae55 100644 +index 6bcb07f..569172e 100644 --- a/support.h +++ b/support.h @@ -26,6 +26,14 @@ @@ -430,16 +430,15 @@ index 6bcb07f..201ae55 100644 extern char tac_service[64]; extern char tac_protocol[64]; -@@ -49,6 +58,11 @@ void *_xcalloc (size_t); - char *_pam_get_user(pam_handle_t *); +@@ -50,5 +59,10 @@ char *_pam_get_user(pam_handle_t *); char *_pam_get_terminal(pam_handle_t *); char *_pam_get_rhost(pam_handle_t *); -+ + +/* + * Parse config file. + */ +int parse_config_file(const char *file); - ++ #endif /* PAM_TACPLUS_SUPPORT_H */ -- diff --git a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch index ff6bf55cb8e6..824db59f5ba0 100644 --- a/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch +++ b/src/tacacs/pam/0009-Add-setting-flag-for-authorization-and-accounting.patch @@ -1,6 +1,6 @@ -From a14c6557cf473e6367ace3905147dad24133b681 Mon Sep 17 00:00:00 2001 +From 8ffcdaf2154943c9034a32876571face842b805c Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> -Date: Mon, 11 Oct 2021 16:01:22 +0800 +Date: Tue, 12 Oct 2021 10:10:03 +0800 Subject: [PATCH 4/4] Add setting flag for authorization and accounting. --- @@ -9,10 +9,10 @@ Subject: [PATCH 4/4] Add setting flag for authorization and accounting. 2 files changed, 16 insertions(+) diff --git a/support.c b/support.c -index e4b667d..820f1d0 100644 +index 5b6e1fa..788ae22 100644 --- a/support.c +++ b/support.c -@@ -345,6 +345,14 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b +@@ -347,6 +347,14 @@ int _pam_parse_arg (const char *arg, char* current_secret, uint current_secret_b /* source ip for the packets */ strncpy (tac_source_ip, arg + strlen("source_ip="), sizeof(tac_source_ip)); set_source_ip (tac_source_ip); @@ -28,7 +28,7 @@ index e4b667d..820f1d0 100644 _pam_log (LOG_WARNING, "unrecognized option: %s", arg); } diff --git a/support.h b/support.h -index 201ae55..dbd85e1 100644 +index 569172e..2b556a7 100644 --- a/support.h +++ b/support.h @@ -34,6 +34,14 @@ From a0911fa2fabea5d8516b24ac278992637dd8d27e Mon Sep 17 00:00:00 2001 From: liuh-80 <58683130+liuh-80@users.noreply.github.com> Date: Wed, 13 Oct 2021 13:17:54 +0800 Subject: [PATCH 12/12] Fix tab issue in patch file. --- .../pam/0006-Add-support-for-source-ip-address.patch | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tacacs/pam/0006-Add-support-for-source-ip-address.patch b/src/tacacs/pam/0006-Add-support-for-source-ip-address.patch index affb9e760e80..8230b34e0d1a 100644 --- a/src/tacacs/pam/0006-Add-support-for-source-ip-address.patch +++ b/src/tacacs/pam/0006-Add-support-for-source-ip-address.patch @@ -69,12 +69,12 @@ index 8f42a0c..164df62 100644 +/* set source ip address for the outgoing tacacs packets */ +void set_source_ip(const char *tac_source_ip) { + /* -+ addrinfo created by getaddrinfo must be released with freeaddrinfo. -+ so source ip address will be stored in following static variables. ++ addrinfo created by getaddrinfo must be released with freeaddrinfo. ++ so source ip address will be stored in following static variables. + */ -+ static struct addrinfo tac_source_address; -+ static struct sockaddr tac_source_sock_addr; -+ static struct sockaddr_in6 tac_source_sock6_addr; ++ static struct addrinfo tac_source_address; ++ static struct sockaddr tac_source_sock_addr; ++ static struct sockaddr_in6 tac_source_sock6_addr; + + struct addrinfo hints, *source_address; + int rv;