summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Russell <brussell@mail.eng.vyatta.net>2019-11-13 14:15:01 +0000
committerBrian Russell <brussell@mail.eng.vyatta.net>2019-11-13 14:15:01 +0000
commit8696a1ff70bbdca3b20dc3e48fd5394fa49efa0c (patch)
tree7adbb6a7d893836eb597f32c804ba05a78721466
parentdb09c62ce678dc292a328f7e982dcb8773194fad (diff)
downloadpam_tacplus-master.tar.gz
pam_tacplus-master.zip
-rw-r--r--debian/changelog6
-rw-r--r--debian/control22
-rw-r--r--debian/gbp.conf3
-rw-r--r--debian/libtac-dev.install2
-rw-r--r--debian/libtac3.install (renamed from debian/libtac1.install)0
-rw-r--r--debian/patches/connect_timeout_socket_leak.patch34
-rw-r--r--debian/patches/read_timeout.patch170
-rw-r--r--debian/patches/series8
-rw-r--r--debian/patches/tac_add_attrib_pair_arg_cnt_overflow.patch47
-rw-r--r--debian/patches/tac_add_attrib_pair_strlen_overflow.patch57
-rw-r--r--debian/patches/tac_add_attrib_return_error.patch101
-rw-r--r--debian/patches/tac_add_attrib_truncate.patch76
-rw-r--r--debian/patches/tac_connect_set_dscp.patch51
-rw-r--r--debian/patches/tac_connect_single_individual-timeout.patch69
-rwxr-xr-xdebian/rules4
15 files changed, 642 insertions, 8 deletions
diff --git a/debian/changelog b/debian/changelog
index 5ba2e14..1f80157 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+libpam-tacplus (1.3.9-0vyatta12) unstable; urgency=medium
+
+ * DANOS import master
+
+ -- Vyatta Package Maintainers <DL-vyatta-help@att.com> Wed, 13 Nov 2019 11:34:29 +0000
+
libpam-tacplus (1.3.8-2) unstable; urgency=low
* Added postinst and prerm scripts for pam-auth-update. Closes: #739274
diff --git a/debian/control b/debian/control
index 6dde527..73ac3d4 100644
--- a/debian/control
+++ b/debian/control
@@ -1,30 +1,40 @@
Source: libpam-tacplus
Section: admin
Priority: extra
-Maintainer: Jeroen Nijhof <jeroen@jeroennijhof.nl>
-Build-Depends: debhelper (>= 9), libpam-dev, dh-autoreconf, autoconf-archive
+Maintainer: Vyatta Package Maintainers <DL-vyatta-help@att.com>
+Build-Depends: debhelper (>= 9), libpam-dev, dh-autoreconf, autoconf-archive,
+ libevent-dev
Standards-Version: 3.9.5
Homepage: https://github.com/jeroennijhof/pam_tacplus
Package: libpam-tacplus
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, libpam-runtime, libtac1
+Depends: ${shlibs:Depends}, ${misc:Depends}, libpam-runtime, libtac3
Description: PAM module for using TACACS+ as an authentication service
This PAM module support authentication, authorization (account management) and
accounting (session management) performed using TACACS+ protocol designed by
Cisco.
-Package: libtac1
+Package: libtac3
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: TACACS+ protocol library
- This library implemenents the fundamentls of the TACACS+ protocol and supports
+ This library implemenents the fundamentals of the TACACS+ protocol and supports
authentication, authorization (account management) and accounting (session management).
Package: libtac-dev
Section: libdevel
Architecture: any
-Depends: ${misc:Depends}, libtac1 (= ${binary:Version}), libc6-dev|libc-dev
+Depends: ${misc:Depends}, libtac3 (= ${binary:Version}), libevent-dev,
+ libc6-dev|libc-dev
Description: Development files for TACACS+ protocol library
Contains C header files and development files for libtac, a TACACS+ protocol
implementation.
+
+Package: libpam-tacplus-dbg
+Architecture: any
+Section: debug
+Priority: extra
+Depends: ${misc:Depends}, libtac3 (= ${binary:Version})
+Description: libpam-tacplus and libtac3 debugging symbols
+ The debugging symbols for libpam-tacplus and libtac3 packages.
diff --git a/debian/gbp.conf b/debian/gbp.conf
new file mode 100644
index 0000000..aa1e8fe
--- /dev/null
+++ b/debian/gbp.conf
@@ -0,0 +1,3 @@
+[DEFAULT]
+upstream-tree=db09c62ce678dc292a328f7e982dcb8773194fad
+#upstream-branch=origin/upstream
diff --git a/debian/libtac-dev.install b/debian/libtac-dev.install
index 8bad7da..8ee9e2f 100644
--- a/debian/libtac-dev.install
+++ b/debian/libtac-dev.install
@@ -1,3 +1,3 @@
usr/lib/*/*.so
-usr/lib/*/pkgconfig/libtac.pc
+usr/lib/*/pkgconfig/libtac*.pc
usr/include/
diff --git a/debian/libtac1.install b/debian/libtac3.install
index 3de3b10..3de3b10 100644
--- a/debian/libtac1.install
+++ b/debian/libtac3.install
diff --git a/debian/patches/connect_timeout_socket_leak.patch b/debian/patches/connect_timeout_socket_leak.patch
new file mode 100644
index 0000000..95500a7
--- /dev/null
+++ b/debian/patches/connect_timeout_socket_leak.patch
@@ -0,0 +1,34 @@
+--- a/libtac/lib/connect.c
++++ b/libtac/lib/connect.c
+@@ -136,6 +136,7 @@
+
+ /* timeout */
+ if ( rc == 0 ) {
++ close(fd);
+ return LIBTAC_STATUS_CONN_TIMEOUT;
+ }
+
+@@ -143,6 +144,7 @@
+ if ( rc < 0 ) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: connection failed with %s: %m", __FUNCTION__, ip))
++ close(fd);
+ return LIBTAC_STATUS_CONN_ERR;
+ }
+
+@@ -151,6 +153,7 @@
+ if(getpeername(fd, (struct sockaddr*)&addr, &len) == -1) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: connection failed with %s: %m", __FUNCTION__, ip))
++ close(fd);
+ return LIBTAC_STATUS_CONN_ERR;
+ }
+
+@@ -158,6 +161,7 @@
+ if(fcntl(fd, F_SETFL, flags) == -1) {
+ TACSYSLOG((LOG_ERR, "%s: cannot restore socket flags: %m",\
+ __FUNCTION__))
++ close(fd);
+ return LIBTAC_STATUS_CONN_ERR;
+ }
+
diff --git a/debian/patches/read_timeout.patch b/debian/patches/read_timeout.patch
new file mode 100644
index 0000000..4962e3e
--- /dev/null
+++ b/debian/patches/read_timeout.patch
@@ -0,0 +1,170 @@
+--- a/libtac/include/libtac.h
++++ b/libtac/include/libtac.h
+@@ -131,6 +131,7 @@
+ extern int tac_timeout;
+
+ void tac_set_dscp(uint8_t val);
++void tac_enable_readtimeout(int enable);
+ int tac_connect(struct addrinfo **, char **, int);
+ int tac_connect_single(struct addrinfo *, const char *, struct addrinfo *, int);
+ char *tac_ntop(const struct sockaddr *);
+@@ -138,6 +139,7 @@
+ int tac_authen_send(int, const char *, char *, char *,
+ char *);
+ int tac_authen_read(int);
++int tac_authen_read_timeout(int, int);
+ int tac_cont_send(int, char *);
+ HDR *_tac_req_header(u_char, int);
+ void _tac_crypt(u_char *, HDR *, int);
+@@ -148,6 +150,7 @@
+ int tac_acct_send(int, int, const char *, char *, char *,
+ struct tac_attrib *);
+ int tac_acct_read(int, struct areply *);
++int tac_acct_read_timeout(int, struct areply *, int);
+ void *xcalloc(size_t, size_t);
+ void *xrealloc(void *, size_t);
+ char *xstrcpy(char *, const char *, size_t);
+@@ -155,6 +158,7 @@
+ int tac_author_send(int, const char *, char *, char *,
+ struct tac_attrib *);
+ int tac_author_read(int, struct areply *);
++int tac_author_read_timeout(int, struct areply *, int);
+ int tac_add_attrib_pair(struct tac_attrib **, char *, char,
+ char *);
+ int tac_add_attrib_truncate(struct tac_attrib **attr, char *name, char *value);
+--- a/libtac/lib/acct_r.c
++++ b/libtac/lib/acct_r.c
+@@ -32,7 +32,7 @@
+ * LIBTAC_STATUS_PROTOCOL_ERR
+ * >= 0 : server response, see TAC_PLUS_AUTHEN_STATUS_...
+ */
+-int tac_acct_read(int fd, struct areply *re) {
++int tac_acct_read_timeout(int fd, struct areply *re, int timeout) {
+ HDR th;
+ struct acct_reply *tb = NULL;
+ int len_from_header, r, len_from_body;
+@@ -42,9 +42,9 @@
+ re->msg = NULL;
+
+ if (tac_readtimeout_enable &&
+- tac_read_wait(fd,tac_timeout*1000, TAC_PLUS_HDR_SIZE,&timeleft) < 0 ) {
++ tac_read_wait(fd,timeout*1000, TAC_PLUS_HDR_SIZE,&timeleft) < 0 ) {
+ TACSYSLOG((LOG_ERR,\
+- "%s: reply timeout after %d secs", __FUNCTION__, tac_timeout))
++ "%s: reply timeout after %d secs", __FUNCTION__, timeout))
+ re->msg = xstrdup(acct_syserr_msg);
+ re->status = LIBTAC_STATUS_READ_TIMEOUT;
+ free(tb);
+@@ -80,7 +80,7 @@
+ if (tac_readtimeout_enable &&
+ tac_read_wait(fd,timeleft,len_from_header,NULL) < 0 ) {
+ TACSYSLOG((LOG_ERR,\
+- "%s: reply timeout after %d secs", __FUNCTION__, tac_timeout))
++ "%s: reply timeout after %d secs", __FUNCTION__, timeout))
+ re->msg = xstrdup(acct_syserr_msg);
+ re->status = LIBTAC_STATUS_READ_TIMEOUT;
+ free(tb);
+@@ -156,3 +156,7 @@
+ free(tb);
+ return re->status;
+ }
++
++int tac_acct_read(int fd, struct areply *re) {
++ return tac_acct_read_timeout(fd, re, tac_timeout);
++}
+--- a/libtac/lib/authen_r.c
++++ b/libtac/lib/authen_r.c
+@@ -34,7 +34,7 @@
+ * LIBTAC_STATUS_PROTOCOL_ERR
+ * >= 0 : server response, see TAC_PLUS_AUTHEN_STATUS_...
+ */
+-int tac_authen_read(int fd) {
++int tac_authen_read_timeout(int fd, int timeout) {
+ HDR th;
+ struct authen_reply *tb = NULL;
+ int len_from_header, r, len_from_body;
+@@ -44,9 +44,9 @@
+
+ /* read the reply header */
+ if (tac_readtimeout_enable &&
+- tac_read_wait(fd,tac_timeout*1000,TAC_PLUS_HDR_SIZE,&timeleft) < 0 ) {
++ tac_read_wait(fd,timeout*1000,TAC_PLUS_HDR_SIZE,&timeleft) < 0 ) {
+ TACSYSLOG((LOG_ERR,\
+- "%s: reply timeout after %d secs", __FUNCTION__, tac_timeout))
++ "%s: reply timeout after %d secs", __FUNCTION__, timeout))
+ status=LIBTAC_STATUS_READ_TIMEOUT;
+ free(tb);
+ return status;
+@@ -77,7 +77,7 @@
+ if (tac_readtimeout_enable &&
+ tac_read_wait(fd,timeleft,len_from_header,NULL) < 0 ) {
+ TACSYSLOG((LOG_ERR,\
+- "%s: reply timeout after %d secs", __FUNCTION__, tac_timeout))
++ "%s: reply timeout after %d secs", __FUNCTION__, timeout))
+ status=LIBTAC_STATUS_READ_TIMEOUT;
+ }
+ r = read(fd, tb, len_from_header);
+@@ -136,3 +136,7 @@
+ free(tb);
+ return status;
+ } /* tac_authen_read */
++
++int tac_authen_read(int fd) {
++ return tac_authen_read_timeout(fd, tac_timeout);
++}
+--- a/libtac/lib/author_r.c
++++ b/libtac/lib/author_r.c
+@@ -38,7 +38,8 @@
+ * LIBTAC_STATUS_PROTOCOL_ERR
+ * >= 0 : server response, see TAC_PLUS_AUTHOR_STATUS_...
+ */
+-int tac_author_read(int fd, struct areply *re) {
++
++int tac_author_read_timeout(int fd, struct areply *re, int timeout) {
+ HDR th;
+ struct author_reply *tb = NULL;
+ int len_from_header, r, len_from_body;
+@@ -49,10 +50,10 @@
+
+ bzero(re, sizeof(struct areply));
+ if (tac_readtimeout_enable &&
+- tac_read_wait(fd,tac_timeout*1000,TAC_PLUS_HDR_SIZE,&timeleft) < 0 ) {
++ tac_read_wait(fd,timeout*1000,TAC_PLUS_HDR_SIZE,&timeleft) < 0 ) {
+
+ TACSYSLOG((LOG_ERR,\
+- "%s: reply timeout after %d secs", __FUNCTION__, tac_timeout))
++ "%s: reply timeout after %d secs", __FUNCTION__, timeout))
+ re->msg = xstrdup(author_syserr_msg);
+ re->status = LIBTAC_STATUS_READ_TIMEOUT;
+ free(tb);
+@@ -88,7 +89,7 @@
+ tac_read_wait(fd,timeleft,len_from_header,NULL) < 0 ) {
+
+ TACSYSLOG((LOG_ERR,\
+- "%s: reply timeout after %d secs", __FUNCTION__, tac_timeout))
++ "%s: reply timeout after %d secs", __FUNCTION__, timeout))
+ re->msg = xstrdup(author_syserr_msg);
+ re->status = LIBTAC_STATUS_READ_TIMEOUT;
+ free(tb);
+@@ -240,3 +241,7 @@
+ free(tb);
+ return re->status;
+ }
++
++int tac_author_read(int fd, struct areply *re) {
++ return tac_author_read_timeout(fd, re, tac_timeout);
++}
+--- a/libtac/lib/connect.c
++++ b/libtac/lib/connect.c
+@@ -41,6 +41,11 @@
+ tac_dscp = val;
+ }
+
++
++void tac_enable_readtimeout(int enable) {
++ tac_readtimeout_enable = !!enable;
++}
++
+ /* Returns file descriptor of open connection
+ to the first available server from list passed
+ in server table.
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..cd7d47b
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,8 @@
+connect_timeout_socket_leak.patch
+tac_connect_single_individual-timeout.patch
+tac_add_attrib_pair_strlen_overflow.patch
+tac_add_attrib_return_error.patch
+tac_add_attrib_truncate.patch
+tac_add_attrib_pair_arg_cnt_overflow.patch
+tac_connect_set_dscp.patch
+read_timeout.patch
diff --git a/debian/patches/tac_add_attrib_pair_arg_cnt_overflow.patch b/debian/patches/tac_add_attrib_pair_arg_cnt_overflow.patch
new file mode 100644
index 0000000..55686ba
--- /dev/null
+++ b/debian/patches/tac_add_attrib_pair_arg_cnt_overflow.patch
@@ -0,0 +1,47 @@
+--- a/libtac/include/libtac.h
++++ b/libtac/include/libtac.h
+@@ -67,6 +67,7 @@
+ #endif
+
+ #define TAC_PLUS_ATTRIB_MAX_LEN 255
++#define TAC_PLUS_ATTRIB_MAX_CNT 255
+
+ struct tac_attrib {
+ char *attr;
+@@ -105,6 +106,7 @@
+ #define LIBTAC_STATUS_CONN_TIMEOUT -8
+ #define LIBTAC_STATUS_CONN_ERR -9
+ #define LIBTAC_STATUS_ATTRIB_TOO_LONG -10
++#define LIBTAC_STATUS_ATTRIB_TOO_MANY -11
+
+ /* Runtime flags */
+
+--- a/libtac/lib/attrib.c
++++ b/libtac/lib/attrib.c
+@@ -31,6 +31,7 @@
+ struct tac_attrib *a;
+ size_t l1 = strlen(name);
+ size_t l2;
++ unsigned int attr_cnt = 0;
+ int total_len;
+
+ if (l1 > TAC_PLUS_ATTRIB_MAX_LEN-1) { /* take sep into account */
+@@ -69,8 +70,17 @@
+ } else {
+ /* find the last allocated block */
+ a = *attr;
+- while(a->next != NULL)
++ while(a->next != NULL) {
+ a = a->next; /* a holds last allocated block */
++ attr_cnt++;
++ }
++
++ if (attr_cnt+1 >= TAC_PLUS_ATTRIB_MAX_CNT) { /* take new attrib into account */
++ TACSYSLOG((LOG_WARNING,\
++ "%s: Maximum number of attributes exceeded, skipping",\
++ __FUNCTION__))
++ return LIBTAC_STATUS_ATTRIB_TOO_MANY;
++ }
+
+ a->next = (struct tac_attrib *) xcalloc(1, sizeof(struct tac_attrib));
+ a = a->next; /* set current block pointer to the new one */
diff --git a/debian/patches/tac_add_attrib_pair_strlen_overflow.patch b/debian/patches/tac_add_attrib_pair_strlen_overflow.patch
new file mode 100644
index 0000000..8f7632b
--- /dev/null
+++ b/debian/patches/tac_add_attrib_pair_strlen_overflow.patch
@@ -0,0 +1,57 @@
+--- a/libtac/include/libtac.h
++++ b/libtac/include/libtac.h
+@@ -66,6 +66,8 @@ extern int logmsg __P((int, const char*,
+ typedef unsigned int u_int32_t;
+ #endif
+
++#define TAC_PLUS_ATTRIB_MAX_LEN 255
++
+ struct tac_attrib {
+ char *attr;
+ u_char attr_len;
+--- a/libtac/lib/attrib.c
++++ b/libtac/lib/attrib.c
+@@ -29,24 +29,34 @@ void tac_add_attrib(struct tac_attrib **
+
+ void tac_add_attrib_pair(struct tac_attrib **attr, char *name, char sep, char *value) {
+ struct tac_attrib *a;
+- u_char l1 = (u_char) strlen(name);
+- u_char l2;
++ size_t l1 = strlen(name);
++ size_t l2;
+ int total_len;
+-
++
++ if (l1 > TAC_PLUS_ATTRIB_MAX_LEN-1) { /* take sep into account */
++ TACSYSLOG((LOG_WARNING,\
++ "%s: attribute `%s' exceeds max. %d characters, skipping",\
++ __FUNCTION__, name, TAC_PLUS_ATTRIB_MAX_LEN-1))
++ return;
++ }
++
++ total_len = l1 + 1; /* "name" + "sep" */
++
+ if (value == NULL) {
+ l2 = 0;
+ } else {
+- l2 = (u_char) strlen(value);
++ l2 = strlen(value);
+ }
+- total_len = l1 + l2 + 1; /* "name" + "=" + "value" */
+
+- if (total_len > 255) {
++ if (l2 > TAC_PLUS_ATTRIB_MAX_LEN-total_len) {
+ TACSYSLOG((LOG_WARNING,\
+- "%s: attribute `%s' total length exceeds 255 characters, skipping",\
+- __FUNCTION__, name))
++ "%s: attribute `%s' total length exceeds %d characters, skipping",\
++ __FUNCTION__, name, TAC_PLUS_ATTRIB_MAX_LEN))
+ return;
+ }
+-
++
++ total_len += l2;
++
+ /* initialize the list if application passed us a null pointer */
+ if(*attr == NULL) {
+ *attr = (struct tac_attrib *) xcalloc(1, sizeof(struct tac_attrib));
diff --git a/debian/patches/tac_add_attrib_return_error.patch b/debian/patches/tac_add_attrib_return_error.patch
new file mode 100644
index 0000000..a886698
--- /dev/null
+++ b/debian/patches/tac_add_attrib_return_error.patch
@@ -0,0 +1,101 @@
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -41,7 +41,7 @@ libtac/lib/xalloc.c \
+ libtac/lib/xalloc.h \
+ $(libtac_include_HEADERS)
+ libtac_la_CFLAGS = $(AM_CFLAGS) -Ilibtac/include
+-libtac_la_LDFLAGS = -version-info 1:0:0 -shared
++libtac_la_LDFLAGS = -version-info 3:0:0 -shared
+
+ moduledir = @pamdir@
+ module_LTLIBRARIES = pam_tacplus.la
+--- a/libtac/include/libtac.h
++++ b/libtac/include/libtac.h
+@@ -95,15 +95,16 @@ struct areply {
+ * all negative, tacplus status codes are >= 0
+ */
+
+-#define LIBTAC_STATUS_ASSEMBLY_ERR -1
+-#define LIBTAC_STATUS_PROTOCOL_ERR -2
+-#define LIBTAC_STATUS_READ_TIMEOUT -3
+-#define LIBTAC_STATUS_WRITE_TIMEOUT -4
+-#define LIBTAC_STATUS_WRITE_ERR -5
+-#define LIBTAC_STATUS_SHORT_HDR -6
+-#define LIBTAC_STATUS_SHORT_BODY -7
+-#define LIBTAC_STATUS_CONN_TIMEOUT -8
+-#define LIBTAC_STATUS_CONN_ERR -9
++#define LIBTAC_STATUS_ASSEMBLY_ERR -1
++#define LIBTAC_STATUS_PROTOCOL_ERR -2
++#define LIBTAC_STATUS_READ_TIMEOUT -3
++#define LIBTAC_STATUS_WRITE_TIMEOUT -4
++#define LIBTAC_STATUS_WRITE_ERR -5
++#define LIBTAC_STATUS_SHORT_HDR -6
++#define LIBTAC_STATUS_SHORT_BODY -7
++#define LIBTAC_STATUS_CONN_TIMEOUT -8
++#define LIBTAC_STATUS_CONN_ERR -9
++#define LIBTAC_STATUS_ATTRIB_TOO_LONG -10
+
+ /* Runtime flags */
+
+@@ -138,7 +139,7 @@ int tac_cont_send(int, char *);
+ HDR *_tac_req_header(u_char, int);
+ void _tac_crypt(u_char *, HDR *, int);
+ u_char *_tac_md5_pad(int, HDR *);
+-void tac_add_attrib(struct tac_attrib **, char *, char *);
++int tac_add_attrib(struct tac_attrib **, char *, char *);
+ void tac_free_attrib(struct tac_attrib **);
+ char *tac_acct_flag2str(int);
+ int tac_acct_send(int, int, const char *, char *, char *,
+@@ -151,7 +152,7 @@ char *_tac_check_header(HDR *, int);
+ int tac_author_send(int, const char *, char *, char *,
+ struct tac_attrib *);
+ int tac_author_read(int, struct areply *);
+-void tac_add_attrib_pair(struct tac_attrib **, char *, char,
++int tac_add_attrib_pair(struct tac_attrib **, char *, char,
+ char *);
+ int tac_read_wait(int, int, int, int *);
+
+--- a/libtac/lib/attrib.c
++++ b/libtac/lib/attrib.c
+@@ -23,11 +23,11 @@
+ #include "libtac.h"
+ #include "xalloc.h"
+
+-void tac_add_attrib(struct tac_attrib **attr, char *name, char *value) {
+- tac_add_attrib_pair(attr, name, '=', value);
++int tac_add_attrib(struct tac_attrib **attr, char *name, char *value) {
++ return tac_add_attrib_pair(attr, name, '=', value);
+ }
+
+-void tac_add_attrib_pair(struct tac_attrib **attr, char *name, char sep, char *value) {
++int tac_add_attrib_pair(struct tac_attrib **attr, char *name, char sep, char *value) {
+ struct tac_attrib *a;
+ size_t l1 = strlen(name);
+ size_t l2;
+@@ -37,7 +37,7 @@ void tac_add_attrib_pair(struct tac_attr
+ TACSYSLOG((LOG_WARNING,\
+ "%s: attribute `%s' exceeds max. %d characters, skipping",\
+ __FUNCTION__, name, TAC_PLUS_ATTRIB_MAX_LEN-1))
+- return;
++ return LIBTAC_STATUS_ATTRIB_TOO_LONG;
+ }
+
+ total_len = l1 + 1; /* "name" + "sep" */
+@@ -52,7 +52,7 @@ void tac_add_attrib_pair(struct tac_attr
+ TACSYSLOG((LOG_WARNING,\
+ "%s: attribute `%s' total length exceeds %d characters, skipping",\
+ __FUNCTION__, name, TAC_PLUS_ATTRIB_MAX_LEN))
+- return;
++ return LIBTAC_STATUS_ATTRIB_TOO_LONG;
+ }
+
+ total_len += l2;
+@@ -85,6 +85,8 @@ void tac_add_attrib_pair(struct tac_attr
+ }
+ *(a->attr+total_len) = '\0'; /* add 0 for safety */
+ a->next = NULL; /* make sure it's null */
++
++ return 0;
+ }
+
+ void tac_free_attrib(struct tac_attrib **attr) {
diff --git a/debian/patches/tac_add_attrib_truncate.patch b/debian/patches/tac_add_attrib_truncate.patch
new file mode 100644
index 0000000..ee64fff
--- /dev/null
+++ b/debian/patches/tac_add_attrib_truncate.patch
@@ -0,0 +1,76 @@
+--- a/libtac/include/libtac.h
++++ b/libtac/include/libtac.h
+@@ -154,6 +154,8 @@ int tac_author_send(int, const char *, c
+ int tac_author_read(int, struct areply *);
+ int tac_add_attrib_pair(struct tac_attrib **, char *, char,
+ char *);
++int tac_add_attrib_truncate(struct tac_attrib **attr, char *name, char *value);
++int tac_add_attrib_pair_truncate(struct tac_attrib **attr, char *name, char sep, char *value);
+ int tac_read_wait(int, int, int, int *);
+
+ /* magic.c */
+--- a/libtac/lib/attrib.c
++++ b/libtac/lib/attrib.c
+@@ -20,14 +20,14 @@
+ * See `CHANGES' file for revision history.
+ */
+
++#include <stdbool.h>
++
+ #include "libtac.h"
+ #include "xalloc.h"
+
+-int tac_add_attrib(struct tac_attrib **attr, char *name, char *value) {
+- return tac_add_attrib_pair(attr, name, '=', value);
+-}
+-
+-int tac_add_attrib_pair(struct tac_attrib **attr, char *name, char sep, char *value) {
++static int _tac_add_attrib_pair(struct tac_attrib **attr, char *name,
++ char sep, char *value, bool truncate)
++{
+ struct tac_attrib *a;
+ size_t l1 = strlen(name);
+ size_t l2;
+@@ -49,10 +49,15 @@ int tac_add_attrib_pair(struct tac_attri
+ }
+
+ if (l2 > TAC_PLUS_ATTRIB_MAX_LEN-total_len) {
+- TACSYSLOG((LOG_WARNING,\
+- "%s: attribute `%s' total length exceeds %d characters, skipping",\
+- __FUNCTION__, name, TAC_PLUS_ATTRIB_MAX_LEN))
+- return LIBTAC_STATUS_ATTRIB_TOO_LONG;
++ if (truncate) {
++ l2 = TAC_PLUS_ATTRIB_MAX_LEN-total_len;
++ }
++ else {
++ TACSYSLOG((LOG_WARNING,\
++ "%s: attribute `%s' total length exceeds %d characters, skipping",\
++ __FUNCTION__, name, TAC_PLUS_ATTRIB_MAX_LEN))
++ return LIBTAC_STATUS_ATTRIB_TOO_LONG;
++ }
+ }
+
+ total_len += l2;
+@@ -89,6 +94,22 @@ int tac_add_attrib_pair(struct tac_attri
+ return 0;
+ }
+
++int tac_add_attrib(struct tac_attrib **attr, char *name, char *value) {
++ return tac_add_attrib_pair(attr, name, '=', value);
++}
++
++int tac_add_attrib_pair(struct tac_attrib **attr, char *name, char sep, char *value) {
++ return _tac_add_attrib_pair(attr, name, sep, value, false);
++}
++
++int tac_add_attrib_truncate(struct tac_attrib **attr, char *name, char *value) {
++ return tac_add_attrib_pair_truncate(attr, name, '=', value);
++}
++
++int tac_add_attrib_pair_truncate(struct tac_attrib **attr, char *name, char sep, char *value) {
++ return _tac_add_attrib_pair(attr, name, sep, value, true);
++}
++
+ void tac_free_attrib(struct tac_attrib **attr) {
+ struct tac_attrib *a;
+ struct tac_attrib *b;
diff --git a/debian/patches/tac_connect_set_dscp.patch b/debian/patches/tac_connect_set_dscp.patch
new file mode 100644
index 0000000..3eea978
--- /dev/null
+++ b/debian/patches/tac_connect_set_dscp.patch
@@ -0,0 +1,51 @@
+--- a/libtac/include/libtac.h
++++ b/libtac/include/libtac.h
+@@ -130,6 +130,7 @@ extern int tac_readtimeout_enable;
+ /* connect.c */
+ extern int tac_timeout;
+
++void tac_set_dscp(uint8_t val);
+ int tac_connect(struct addrinfo **, char **, int);
+ int tac_connect_single(struct addrinfo *, const char *, struct addrinfo *, int);
+ char *tac_ntop(const struct sockaddr *);
+--- a/libtac/lib/connect.c
++++ b/libtac/lib/connect.c
+@@ -34,6 +34,13 @@
+ /* Pointer to TACACS+ connection timeout */
+ int tac_timeout = 5;
+
++unsigned int tac_dscp = 0;
++
++void tac_set_dscp(uint8_t val) {
++ /* Value should already be left shifted by 2 bits (those are used for ECN) */
++ tac_dscp = val;
++}
++
+ /* Returns file descriptor of open connection
+ to the first available server from list passed
+ in server table.
+@@ -91,6 +98,24 @@ int tac_connect_single(struct addrinfo *
+ return LIBTAC_STATUS_CONN_ERR;
+ }
+
++ switch (server->ai_family) {
++ case AF_INET:
++ rc = setsockopt(fd, IPPROTO_IP, IP_TOS, &tac_dscp, sizeof tac_dscp);
++ break;
++ case AF_INET6:
++ rc = setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &tac_dscp, sizeof tac_dscp);
++ break;
++ default:
++ rc = 0;
++ }
++ if (rc < 0) {
++ TACSYSLOG((LOG_ERR,"%s: setsockopt(%s) error: %s", __FUNCTION__,
++ server->ai_family == AF_INET ? "IP_TOS" : "IPV6_TCLASS",
++ strerror(errno)))
++ close(fd);
++ return LIBTAC_STATUS_CONN_ERR;
++ }
++
+ /* get flags for restoration later */
+ flags = fcntl(fd, F_GETFL, 0);
+
diff --git a/debian/patches/tac_connect_single_individual-timeout.patch b/debian/patches/tac_connect_single_individual-timeout.patch
new file mode 100644
index 0000000..3df2617
--- /dev/null
+++ b/debian/patches/tac_connect_single_individual-timeout.patch
@@ -0,0 +1,69 @@
+--- a/libtac/include/libtac.h
++++ b/libtac/include/libtac.h
+@@ -126,7 +126,7 @@
+ extern int tac_timeout;
+
+ int tac_connect(struct addrinfo **, char **, int);
+-int tac_connect_single(struct addrinfo *, const char *, struct addrinfo *);
++int tac_connect_single(struct addrinfo *, const char *, struct addrinfo *, int);
+ char *tac_ntop(const struct sockaddr *);
+
+ int tac_authen_send(int, const char *, char *, char *,
+--- a/libtac/lib/connect.c
++++ b/libtac/lib/connect.c
+@@ -50,7 +50,7 @@
+ TACSYSLOG((LOG_ERR, "%s: no TACACS+ servers defined", __FUNCTION__))
+ } else {
+ for ( tries = 0; tries < servers; tries++ ) {
+- if((fd=tac_connect_single(server[tries], key[tries], NULL)) >= 0 ) {
++ if((fd=tac_connect_single(server[tries], key[tries], NULL, tac_timeout)) >= 0 ) {
+ /* tac_secret was set in tac_connect_single on success */
+ break;
+ }
+@@ -67,7 +67,7 @@
+ * >= 0 : valid fd
+ * < 0 : error status code, see LIBTAC_STATUS_...
+ */
+-int tac_connect_single(struct addrinfo *server, const char *key, struct addrinfo *srcaddr) {
++int tac_connect_single(struct addrinfo *server, const char *key, struct addrinfo *srcaddr, int timeout) {
+ int retval = LIBTAC_STATUS_CONN_ERR; /* default retval */
+ int fd = -1;
+ int flags, rc;
+@@ -128,7 +128,7 @@
+ FD_SET(fd, &writefds);
+
+ /* set timeout seconds */
+- tv.tv_sec = tac_timeout;
++ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ /* check if socket is ready for read and write */
+--- a/pam_tacplus.c
++++ b/pam_tacplus.c
+@@ -169,7 +169,7 @@
+
+ status = PAM_SESSION_ERR;
+ for(srv_i = 0; srv_i < tac_srv_no; srv_i++) {
+- tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL);
++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout);
+ if (tac_fd < 0) {
+ _pam_log(LOG_WARNING, "%s: error sending %s (fd)",
+ __FUNCTION__, typemsg);
+@@ -266,7 +266,7 @@
+ if (ctrl & PAM_TAC_DEBUG)
+ syslog(LOG_DEBUG, "%s: trying srv %d", __FUNCTION__, srv_i );
+
+- tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL);
++ tac_fd = tac_connect_single(tac_srv[srv_i].addr, tac_srv[srv_i].key, NULL, tac_timeout);
+ if (tac_fd < 0) {
+ _pam_log(LOG_ERR, "connection failed srv %d: %m", srv_i);
+ continue;
+@@ -487,7 +487,7 @@
+ if(tac_protocol != NULL && tac_protocol[0] != '\0')
+ tac_add_attrib(&attr, "protocol", tac_protocol);
+
+- tac_fd = tac_connect_single(active_server.addr, active_server.key, NULL);
++ tac_fd = tac_connect_single(active_server.addr, active_server.key, NULL, tac_timeout);
+ if(tac_fd < 0) {
+ _pam_log (LOG_ERR, "TACACS+ server unavailable");
+ if(arep.msg != NULL)
diff --git a/debian/rules b/debian/rules
index 0fa1f54..82b372d 100755
--- a/debian/rules
+++ b/debian/rules
@@ -17,10 +17,12 @@ override_dh_clean:
dh_clean
override_dh_auto_configure:
- dh_auto_configure -- --enable-pamdir=/lib/$(DEB_HOST_MULTIARCH)/security --docdir=/usr/share/doc/libpam-tacplus
+ dh_auto_configure -- --enable-pamdir=/lib/$(DEB_HOST_MULTIARCH)/security --docdir=/usr/share/doc/libpam-tacplus --with-libevent
override_dh_install:
mkdir -p debian/libpam-tacplus/usr/share/pam-configs
cp debian/tacplus debian/libpam-tacplus/usr/share/pam-configs/
dh_install
+override_dh_strip:
+ dh_strip --dbg-package=libpam-tacplus-dbg