Package: tacacs+
Version: 4.0.4.19-7
Severity: wishlist
Tags: ipv6 patch

Hello,
  While looking at the source code of tacacs+ I noticed that it uses
gethostbyname().  This has two problems:
  * It's an obsolete call, see gethostbyname()
  * Depending on the libc6, you may get IPv6 addresses returned which
    will mean you will try to wedge a IPv6 address into an IPv4 sockaddr
    and you end up with a horrible mess.

See http://lists.debian.org/debian-ipv6/2010/05/msg00000.html for some
discussion about this.

The attached patch uses getaddrinfo() and fixes it to IPv4 addresses
only.  It could probably work with IPv6 too with some more checking.

 - Craig


-- System Information:
Debian Release: squeeze/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.32-trunk-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_AU.UTF-8, LC_CTYPE=en_AU.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages tacacs+ depends on:
ii  adduser                       3.112      add and remove users and groups
ii  libc6                         2.10.2-8   Embedded GNU C Library: Shared lib
ii  libpam0g                      1.1.1-3    Pluggable Authentication Modules l
ii  libtacacs+1                   4.0.4.19-7 TACACS+ authentication daemon
ii  libwrap0                      7.6.q-18   Wietse Venema's TCP wrappers libra
ii  python                        2.5.4-9    An interactive high-level object-o

tacacs+ recommends no packages.

tacacs+ suggests no packages.

-- Configuration Files:
/etc/tacacs+/tac_plus.conf [Errno 13] Permission denied: 
u'/etc/tacacs+/tac_plus.conf'

-- no debconf information
#! /bin/sh /usr/share/dpatch/dpatch-run
## gethostbyname.dpatch by  <csm...@debian.org>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: uses getaddrinfo instead of gethostbyname

@DPATCH@
diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' tacacs+-4.0.4.19~/maxsess.c tacacs+-4.0.4.19/maxsess.c
--- tacacs+-4.0.4.19~/maxsess.c	2010-05-20 11:18:17.000000000 +1000
+++ tacacs+-4.0.4.19/maxsess.c	2010-05-20 11:18:50.000000000 +1000
@@ -351,39 +351,22 @@
 static int
 ckfinger(char *user, char *nas, struct identity *idp)
 {
-    struct sockaddr_in sin;
-    struct servent *serv;
-    int count, s, bufsize;
+    struct addrinfo hints, *res;
+    int count, s, bufsize, errcode;
     char *buf, *p, *pn;
     int incr = 4096, slop = 32;
-    u_long inaddr;
     char *curport = portname(idp->NAS_port);
     char *name;
 
-    /* The finger service, aka port 79 */
-    serv = getservbyname("finger", "tcp");
-    if (serv) {
-	sin.sin_port = serv->s_port;
-    } else {
-	sin.sin_port = 79;
-    }
 
-    /* Get IP addr for the NAS */
-    inaddr = inet_addr(nas);
-    if (inaddr != -1) {
-	/* A dotted decimal address */
-	memcpy(&sin.sin_addr, &inaddr, sizeof(inaddr));
-	sin.sin_family = AF_INET;
-    } else {
-	struct hostent *host = gethostbyname(nas);
+    memset(&hints, 0, sizeof(struct addrinfo));
+    hints.ai_family = AF_INET; /* IPv4 only until all code is checked */
+    hints.ai_socktype = SOCK_STREAM;
 
-	if (host == NULL) {
-	    report(LOG_ERR, "ckfinger: gethostbyname %s failure: %s",
-		   nas, strerror(errno));
+    if ( (errcode = getaddrinfo(nas, "finger", &hints, &res)) != 0) {
+	    report(LOG_ERR, "ckfinger: getaddrinfo %s failure: %s",
+		   nas, gai_strerror(errcode));
 	    return(0);
-	}
-	memcpy(&sin.sin_addr, host->h_addr, host->h_length);
-	sin.sin_family = host->h_addrtype;
     }
 
     s = socket(AF_INET, SOCK_STREAM, 0);
@@ -391,11 +374,19 @@
 	report(LOG_ERR, "ckfinger: socket: %s", strerror(errno));
 	return(0);
     }
-    if (connect(s, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
+    errcode=-1;
+    while (res) {
+        if ( (errcode = connect(s,res->ai_addr,res->ai_addrlen)) == 0)
+          break;
+        res = res->ai_next;
+    }
+    freeaddrinfo(res);
+    if (errcode != 0) {
 	report(LOG_ERR, "ckfinger: connect failure %s", strerror(errno));
 	close(s);
 	return(0);
     }
+
     /* Read in the finger output into a single flat buffer */
     buf = NULL;
     bufsize = 0;

Reply via email to