[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#570024: cfingerd: Making Cfingerd IPv6-enabled



Package: cfingerd
Version: 1.4.3-2.2
Severity: normal
Tags: patch

I would like to publish a patch that makes Cfingerd able
to use IPv4 and IPv6 in arbitrary mixture. The patch is
a debdiff against the presently latest package edition.

For testing the patched Cfingerd I can recommend the very
latest Debian package finger_0.17-14, from the bsd-finger
source, since that package is now fully IPv6-enabled.


Kind regards,

Mats Erik Andersson
diff -u cfingerd-1.4.3/debian/cron cfingerd-1.4.3/debian/cron
--- cfingerd-1.4.3/debian/cron
+++ cfingerd-1.4.3/debian/cron
@@ -7,7 +7,7 @@
 cd /var/log
 for LOG in cfingerd.log
 do
-   if [ -f $LOG ]; then
+   if [ -f "$LOG" ]; then
       savelog -g adm -m 644 -u root -c 4 $LOG >/dev/null
    fi
 done
diff -u cfingerd-1.4.3/debian/rules cfingerd-1.4.3/debian/rules
--- cfingerd-1.4.3/debian/rules
+++ cfingerd-1.4.3/debian/rules
@@ -95,6 +95,7 @@
 	$(installbin) -d debian/tmp/usr/share/doc/$(package)/examples
 	$(installdoc) debian/{ping,uptime} debian/tmp/usr/share/doc/$(package)/examples
 	$(installdoc) scripts/trace debian/tmp/usr/share/doc/$(package)/examples
+	$(installdoc) debian/cfingerd.xinetd debian/tmp/usr/share/doc/$(package)/examples
 	#
 	dpkg-shlibdeps debian/tmp/usr/sbin/{cfingerd,userlist}
 	dpkg-gencontrol -isp
diff -u cfingerd-1.4.3/debian/changelog cfingerd-1.4.3/debian/changelog
--- cfingerd-1.4.3/debian/changelog
+++ cfingerd-1.4.3/debian/changelog
@@ -1,3 +1,11 @@
+cfingerd (1.4.3-2.2) unstable; urgency=low
+
+  * Non-maintainer upload.
+  * Implement IPv6-capability.
+  * debian/cfingerd.xinetd: New file, configuration example.
+
+ -- Mats Erik Andersson <mats.andersson@gisladisker.se>  Mon, 15 Feb 2010 22:27:09 +0100
+
 cfingerd (1.4.3-2.1) unstable; urgency=medium
 
   * Non-maintainer upload.
diff -u cfingerd-1.4.3/src/rfc1413.c cfingerd-1.4.3/src/rfc1413.c
--- cfingerd-1.4.3/src/rfc1413.c
+++ cfingerd-1.4.3/src/rfc1413.c
@@ -25,11 +25,15 @@
  * the implementation.  Completely rewritten by yours truly to be self-
  * contained in a single program.  Simple, easy to use.
  */
-#define BUFLEN	256
-char *get_rfc1413_data( struct sockaddr_in local_addr )
+#define BUFLEN	(2 * INET6_ADDRSTRLEN)
+char *get_rfc1413_data(struct sockaddr_storage * local_addr,
+			struct sockaddr_storage * peer_addr )
 {
     int i, j;
-    struct sockaddr_in sin;
+    unsigned short newport;
+    struct sockaddr_storage sin;
+    struct sockaddr_in *sa4 = (struct sockaddr_in *) &sin;
+    struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &sin;
     char buffer[1024], buf[BUFLEN], uname[64], *bleah;
     char *cp, *xp;
     struct servent *serv;
@@ -37,33 +41,57 @@
     bleah = (char *) malloc(BUFLEN);
     memset(bleah, 0, BUFLEN);
 
-    j = socket(AF_INET, SOCK_STREAM, 0);
+    j = socket(local_addr->ss_family, SOCK_STREAM, 0);
     if (j < 2) {
 	snprintf(bleah, BUFLEN, "unknown@%s", remote_addr);
 	syslog(LOG_ERR, "rfc1413-socket: %s", strerror(errno));
 	return(bleah);
     }
 
-    sin.sin_family = AF_INET;
-    sin.sin_addr.s_addr = local_addr.sin_addr.s_addr;
-    sin.sin_port = 0;
-    i = bind(j, (struct sockaddr *) &sin, sizeof(sin));
+    memcpy(&sin, local_addr, sizeof(sin));
+    switch (sin.ss_family) {
+	case AF_INET6:
+	    sa6->sin6_port = 0;
+	    break;
+	case AF_INET:
+	default:
+	    sa4->sin_port = 0;
+    }
+
+    i = bind(j, (struct sockaddr *) &sin, 
+		    (sin.ss_family == AF_INET6 )
+			? sizeof(struct sockaddr_in6)
+			: sizeof(struct sockaddr_in));
+
     if (i < 0) {
 	snprintf(bleah, BUFLEN, "unknown@%s", remote_addr);
 	syslog(LOG_ERR, "rfc1413-socket: %s", strerror(errno));
 	return(bleah);
     }
 
-    sin.sin_family = AF_INET;
     if ((serv = getservbyname("auth","tcp")) != NULL)
-	sin.sin_port = serv->s_port;
+	newport = serv->s_port;
     else
-	sin.sin_port = htons(113);
-    sin.sin_addr.s_addr = inet_addr(ip_address);
+	newport = htons(113);
+
+    memcpy(&sin, peer_addr, sizeof(sin));
+    switch (sin.ss_family) {
+	case AF_INET6:
+	    sa6->sin6_port = newport;
+	    break;
+	case AF_INET:
+	default:
+	    sa4->sin_port = newport;
+    }
+
     signal(SIGALRM, rfc1413_alarm);
     alarm(5);
 
-    i = connect(j, (struct sockaddr *) &sin, sizeof(sin));
+    i = connect(j, (struct sockaddr *) &sin,
+		    (sin.ss_family == AF_INET6 )
+			? sizeof(struct sockaddr_in6)
+			: sizeof(struct sockaddr_in));
+
     if (i < 0) {
 	syslog(LOG_ERR, "rfc1413-connect: %s", strerror(errno));
 	close(j);
diff -u cfingerd-1.4.3/src/main.c cfingerd-1.4.3/src/main.c
--- cfingerd-1.4.3/src/main.c
+++ cfingerd-1.4.3/src/main.c
@@ -20,11 +20,13 @@
 #include "privs.h"
 
 CONFIG prog_config;
-char *remote_addr, *localhost, *ident_user, *ip_address;
+char *localhost, *ident_user;
+char ip_address[INET6_ADDRSTRLEN] = "";
+char remote_addr[INET6_ADDRSTRLEN] = "";
 FILE *top_display, *bottom_display, *noname_display, *nouser_display,
      *rejected_display, *identd_display;
 BOOL local_finger, emulated; 
-int local_port, remote_port;
+unsigned short local_port, remote_port;
 unsigned short listen_port;
 unsigned long listen_addr;
 
@@ -62,14 +64,15 @@
     char line[100], username[80], syslog_str[200];
     int un_type;
     char *cp;
-    struct sockaddr_in local_addr;
+    struct sockaddr_storage local_addr;
+    struct sockaddr_in *sloc4 = (struct sockaddr_in *) &local_addr;
+    struct sockaddr_in6 *sloc6 = (struct sockaddr_in6 *) &local_addr;
     struct servent *serv;
 
     if ((serv = getservbyname("finger","tcp")) != NULL)
 	listen_port = serv->s_port;
     else
 	listen_port = htons(79);
-    listen_addr = htonl(INADDR_ANY);
 
     /* Initialize CFINGERD */
     start_handler();
@@ -108,7 +111,7 @@
     /* Make sure there is actually data waiting in the finger port */
     if (!emulated) {
 	if (!fgets(username, sizeof(username), stdin)) {
-	  if (remote_addr != NULL) {
+	  if (remote_addr != NULL && *remote_addr) {
 	    syslog(LOG_ERR, "Null query from %s: %m", remote_addr);
 	    mylog(LOG_ERROR, remote_addr, strerror(errno));
 	  } else {
@@ -147,33 +150,64 @@
     /* If we're not doing emulated stuff, we can assume that we are running
        either as a daemon, or under INETD.  In that case... */
     if (!emulated) {
-	struct sockaddr_in socket_addr;
+	struct sockaddr_storage socket_addr;
+	struct sockaddr_in *srem4 = (struct sockaddr_in *) &socket_addr;
+	struct sockaddr_in6 *srem6 = (struct sockaddr_in6 *) &socket_addr;
 	struct hostent *host_ent;
-	int psize = 0;
+	socklen_t locsize = 0, remsize = 0;
 
 	/* Can't run from command line (but this should already be checked) */
-	psize = sizeof(socket_addr);
+	locsize = sizeof(local_addr);
 
-	if (getsockname(0, (struct sockaddr *) &local_addr, &psize)) {
+	if (getsockname(0, (struct sockaddr *) &local_addr, &locsize)) {
 	    syslog(LOG_WARNING, "getsockname: %s", strerror(errno));
 	    local_port = 0;
 	} else
-	    local_port = ntohs(local_addr.sin_port);
+	    switch (local_addr.ss_family) {
+		case AF_INET6:
+		    local_port = ntohs(sloc6->sin6_port);
+		    break;
+		case AF_INET:
+		default:
+		    local_port = ntohs(sloc4->sin_port);
+	    }
+
+	remsize = sizeof(socket_addr);
 
-	if (getpeername(0, (struct sockaddr *) &socket_addr, &psize)) {
+	if (getpeername(0, (struct sockaddr *) &socket_addr, &remsize)) {
 	    printf("Internal error - not running as either a daemon or under INETD.\n");
 	    printf("Fatal - getpeername: %s\n", strerror(errno));
 	    closelog();
 	    mylog(LOG_ERROR, "getpeername: ", strerror(errno));
 	    exit(PROGRAM_BUG);
 	} else
-	    remote_port = ntohs(socket_addr.sin_port);
+	    switch (socket_addr.ss_family) {
+		case AF_INET6:
+		    remote_port = ntohs(srem6->sin6_port);
+		    break;
+		case AF_INET:
+		default:
+		    remote_port = ntohs(srem4->sin_port);
+	    }
 
-	ip_address = inet_ntoa (socket_addr.sin_addr);
+	inet_ntop(socket_addr.ss_family, &socket_addr,
+			ip_address, INET6_ADDRSTRLEN);
 
 	/* Get our host entry */
-	host_ent = (struct hostent *) gethostbyaddr((char *) &socket_addr.sin_addr,
-		   sizeof(socket_addr.sin_addr), AF_INET);
+	switch (socket_addr.ss_family) {
+	    case AF_INET6:
+		host_ent = (struct hostent *)
+				gethostbyaddr((char *) &srem6->sin6_addr,
+					sizeof(struct in6_addr),
+					socket_addr.ss_family);
+		break;
+	    case AF_INET:
+	    default:
+		host_ent = (struct hostent *)
+				gethostbyaddr((char *) &srem4->sin_addr,
+					sizeof(struct in_addr),
+					socket_addr.ss_family);
+	}
 
 	/* And get our local-host name */
 #ifndef	ACTUAL_HOSTNAME
@@ -184,14 +218,14 @@
 
 	/* Make sure we can get the remote host's address name */
 	if (host_ent == NULL) {
-	    remote_addr = inettos(socket_addr.sin_addr.s_addr);
+	    strncpy(remote_addr, ip_address, INET6_ADDRSTRLEN);
 	    syslog(LOG_WARNING, "%s %s", 
 		prog_config.p_strings[D_IP_NO_MATCH],
 		remote_addr);
 	    if (!(prog_config.config_bits2 & SHOW_IP_MATCH))
 		CF_ERROR(E_NOIP);
 	} else
-	    remote_addr = (char *) host_ent->h_name;
+	    strncpy(remote_addr, host_ent->h_name, INET6_ADDRSTRLEN);
 
 	/* Convert any uppercase letters in the hostname to lowercase */
 	for (cp = remote_addr; *cp; cp++)
@@ -200,14 +234,17 @@
 
 	/* And find out if this is a local finger */
 	if (!strncasecmp(remote_addr, "127.0.0.1", 9) ||
+	    !strncasecmp(remote_addr, "::1", 3) ||
 	    !strncasecmp(remote_addr, "localhost", 9) ||
+	    !strncasecmp(remote_addr, "ip6-localhost", 9) ||
+	    !strncasecmp(remote_addr, "ip6-loopback", 9) ||
 	    !strncasecmp(remote_addr, "127.0.0.0", 9) || /* KTH 07/26/96 */
 	    !strncasecmp(remote_addr, localhost, strlen(localhost)))
 	    local_finger = TRUE;
 	else
 	    local_finger = FALSE;
 
-	ident_user = get_rfc1413_data(local_addr);
+	ident_user = get_rfc1413_data(&local_addr, &socket_addr);
 	set_time_format();
 
     } else
@@ -220,9 +257,9 @@
 	memset (ident_user, 0, sizeof (ident_user));
 	strcpy (ident_user, "emulated");
 #ifndef	ACTUAL_LOOPBACK
-	remote_addr = "127.0.0.1";
+	strcpy(remote_addr,"127.0.0.1");
 #else
-	remote_addr = ACTUAL_LOOPBACK;
+	strcpy(remote_addr, ACTUAL_LOOPBACK);
 #endif
     }
 
diff -u cfingerd-1.4.3/src/proto.h cfingerd-1.4.3/src/proto.h
--- cfingerd-1.4.3/src/proto.h
+++ cfingerd-1.4.3/src/proto.h
@@ -45,7 +45,7 @@
 void become_nobody(void);
 void become_user(char *);
 int wildmat(char *, char *);
-char *get_rfc1413_data(struct sockaddr_in );
+char *get_rfc1413_data(struct sockaddr_storage *, struct sockaddr_storage *);
 void check_unknown(char *);
 void mylog(int, char *, char *);
 void userlog(uid_t, gid_t, char *, char *);
only in patch2:
unchanged:
--- cfingerd-1.4.3.orig/src/cfingerd.h
+++ cfingerd-1.4.3/src/cfingerd.h
@@ -278,10 +278,11 @@
 
 extern CONFIG prog_config;
 extern ECRUFT errors[];
-extern char *remote_addr, *localhost, *ident_user, *ip_address;
+extern char remote_addr[], ip_address[];
+extern char *localhost, *ident_user;
 extern int trusted_host_num, rejected_host_num, forward_host_num,
-	   fakeuser_num, num_finger_sites, num_headers, local_port,
-	   remote_port, can_log;
+	   fakeuser_num, num_finger_sites, num_headers, can_log;
+extern unsigned short local_port, remote_port;
 extern FILE *top_display, *bottom_display, *noname_display, *nouser_display,
 	    *rejected_display, *identd_display;
 extern BOOL local_finger, emulated;
@@ -293,4 +294,4 @@
 
 #include "defines.h"
 
-#endif _CFINGERD_H_
+#endif /* _CFINGERD_H_ */
only in patch2:
unchanged:
--- cfingerd-1.4.3.orig/docs/cfingerd.conf.5
+++ cfingerd-1.4.3/docs/cfingerd.conf.5
@@ -8,8 +8,8 @@
 .SH DESCRIPTION
 .I cfingerd.conf
 is the configuration file for cfingerd.
-+.I cfingerd
-+has been totally rewritten
+.I cfingerd
+has been totally rewritten
 to support a more readable configuration file.  This version of the new 
 configuration file is
 .B NOT
only in patch2:
unchanged:
--- cfingerd-1.4.3.orig/debian/cfingerd.xinetd
+++ cfingerd-1.4.3/debian/cfingerd.xinetd
@@ -0,0 +1,14 @@
+service finger
+{
+	disable = no
+	socket_type = stream
+	protocol = tcp
+	flags = IPv6
+	wait = no
+	user = root
+	server = /usr/sbin/cfingerd
+	log_type = SYSLOG daemon info
+	log_on_success = HOST
+	log_on_failure = HOST
+}
+

Reply to: