2 ; IPv6 patch for cfingerd 1.4.3 daemon.
3 ; System with working getaddrinfo(), getnameinfo(),
4 ; functions and defined struct sockaddr_storage required
5 ; (ie. Linux 2.2.x with glibc 2.1.1 or *BSD/KAME)
7 ; Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>, PLD/Linux
9 Index: cfingerd/CHANGES
10 diff -u cfingerd/CHANGES:1.1.1.1 cfingerd/CHANGES:1.2
11 --- cfingerd/CHANGES:1.1.1.1 Sun Dec 12 12:23:27 1999
12 +++ cfingerd/CHANGES Sun Dec 12 13:07:49 1999
14 +CFINGERD 1.4.4 ??/??/??
15 + - full IPv6 support !
17 CFINGERD 1.4.3 09/29/99
18 - Security update, fixes buffer overflows introduced with sscanf(),
19 exploitable under FreeBSD
20 Index: cfingerd/src/cfingerd.h
21 diff -u cfingerd/src/cfingerd.h:1.1.1.1 cfingerd/src/cfingerd.h:1.2
22 --- cfingerd/src/cfingerd.h:1.1.1.1 Sun Dec 12 12:23:27 1999
23 +++ cfingerd/src/cfingerd.h Sun Dec 12 13:07:49 1999
32 #include <netinet/in.h>
33 #include <sys/socket.h>
36 extern CONFIG prog_config;
37 extern ECRUFT errors[];
39 +extern char *localhost, *ident_user;
40 +extern char remote_addr[100], ip_address[100];
42 extern char *remote_addr, *localhost, *ident_user, *ip_address;
44 extern int trusted_host_num, rejected_host_num, forward_host_num,
46 fakeuser_num, num_finger_sites, num_headers, local_port,
49 + fakeuser_num, num_finger_sites, num_headers, can_log;
50 +extern char local_port[32], remote_port[32];
52 extern FILE *top_display, *bottom_display, *noname_display, *nouser_display,
53 *rejected_display, *identd_display;
54 extern BOOL local_finger, emulated;
55 Index: cfingerd/src/main.c
56 diff -u cfingerd/src/main.c:1.1.1.1 cfingerd/src/main.c:1.2
57 --- cfingerd/src/main.c:1.1.1.1 Sun Dec 12 12:23:27 1999
58 +++ cfingerd/src/main.c Sun Dec 12 13:07:49 1999
63 + * IPv6 code Copyright (C) 1999 Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
65 * This program is free software; you can redistribute it and/or modify
66 * it under the terms of the GNU General Public License as published by
72 +char *localhost, *ident_user;
73 +char remote_addr[100];
74 +char ip_address[100];
76 char *remote_addr, *localhost, *ident_user, *ip_address;
78 FILE *top_display, *bottom_display, *noname_display, *nouser_display,
79 *rejected_display, *identd_display;
80 BOOL local_finger, emulated;
82 +char local_port[32], remote_port[32];
84 int local_port, remote_port;
86 unsigned short listen_port;
87 unsigned long listen_addr;
90 char line[100], username[80], syslog_str[200];
94 struct sockaddr_in local_addr;
99 listen_port = htons(79);
100 listen_addr = htonl(INADDR_ANY);
102 + struct sockaddr_storage local_addr;
105 /* Initialize CFINGERD */
108 /* If we're not doing emulated stuff, we can assume that we are running
109 either as a daemon, or under INETD. In that case... */
112 + struct sockaddr_storage socket_addr;
114 struct sockaddr_in socket_addr;
115 struct hostent *host_ent;
119 /* Can't run from command line (but this should already be checked) */
122 if (getsockname(0, (struct sockaddr *) &local_addr, &psize)) {
123 syslog(LOG_WARNING, "getsockname: %s", strerror(errno));
127 local_port = ntohs(local_addr.sin_port);
129 + snprintf(local_port, sizeof(local_port), "0");
131 + getnameinfo((struct sockaddr *)&local_addr,
132 + (socket_addr.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in),
133 + NULL, 0, local_port, sizeof(local_port),
134 + NI_NUMERICHOST|NI_NUMERICSERV);
138 if (getpeername(0, (struct sockaddr *) &socket_addr, &psize)) {
139 printf("Internal error - not running as either a daemon or under INETD.\n");
142 log(LOG_ERROR, "getpeername: ", strerror(errno));
146 remote_port = ntohs(socket_addr.sin_port);
149 /* Get our host entry */
150 host_ent = (struct hostent *) gethostbyaddr((char *) &socket_addr.sin_addr,
151 sizeof(socket_addr.sin_addr), AF_INET);
155 + getnameinfo((struct sockaddr *)&socket_addr,
156 + (socket_addr.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in),
157 + ip_address, sizeof(ip_address), remote_port, sizeof(remote_port),
158 + NI_NUMERICHOST|NI_NUMERICSERV);
161 /* And get our local-host name */
162 #ifndef ACTUAL_HOSTNAME
163 localhost = get_localhost();
164 @@ -182,16 +219,31 @@
165 localhost = ACTUAL_HOSTNAME;
169 /* Make sure we can get the remote host's address name */
170 if (host_ent == NULL) {
171 remote_addr = inettos(socket_addr.sin_addr.s_addr);
173 + /* Get our host entry and make sure we can get the remote host's address name */
174 + if (getnameinfo((struct sockaddr *)&socket_addr,
175 + (socket_addr.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in),
176 + remote_addr, sizeof(remote_addr), NULL, 0, NI_NAMEREQD) != 0) {
177 + getnameinfo((struct sockaddr *)&socket_addr,
178 + (socket_addr.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in),
179 + remote_addr, sizeof(remote_addr),
180 + NULL, 0, NI_NUMERICHOST);
182 syslog(LOG_WARNING, "%s %s",
183 prog_config.p_strings[D_IP_NO_MATCH],
185 if (!(prog_config.config_bits2 & SHOW_IP_MATCH))
189 remote_addr = (char *) host_ent->h_name;
194 /* Convert any uppercase letters in the hostname to lowercase */
195 for (cp = remote_addr; *cp; cp++)
197 if (!strncasecmp(remote_addr, "127.0.0.1", 9) ||
198 !strncasecmp(remote_addr, "localhost", 9) ||
199 !strncasecmp(remote_addr, "127.0.0.0", 9) || /* KTH 07/26/96 */
201 + !strncasecmp(remote_addr, "::1", 3) ||
203 !strncasecmp(remote_addr, localhost, strlen(localhost)))
206 @@ -220,11 +275,25 @@
207 memset (ident_user, 0, sizeof (ident_user));
208 strcpy (ident_user, "emulated");
209 #ifndef ACTUAL_LOOPBACK
211 + sprintf(remote_addr, "127.0.0.1");
213 remote_addr = "127.0.0.1";
217 + sprintf(remote_addr, ACTUAL_LOOPBACK);
219 remote_addr = ACTUAL_LOOPBACK;
225 + /* If IPv4-mapped IPv6 address convert it to clean IPv4 */
226 + if (strncmp(remote_addr, "::ffff:", 7) == 0)
227 + strncpy(remote_addr, remote_addr + 7, sizeof(remote_addr));
230 /* Now, let's check to make sure this site is trusted */
231 if ((!local_finger) && !emulated)
232 Index: cfingerd/src/options.c
233 diff -u cfingerd/src/options.c:1.1.1.1 cfingerd/src/options.c:1.2
234 --- cfingerd/src/options.c:1.1.1.1 Sun Dec 12 12:23:27 1999
235 +++ cfingerd/src/options.c Sun Dec 12 13:07:49 1999
239 * Starting option routines
240 + * IPv6 code Copyright (C) 1999 Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
242 * This program is free software; you can redistribute it and/or modify
243 * it under the terms of the GNU General Public License as published by
247 int i, lsock, fd, clen;
253 + struct sockaddr_storage caddr;
254 + struct addrinfo hints, *res, *res0;
256 struct sockaddr caddr;
257 struct sockaddr_in laddr;
261 if ((lsock = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
262 syslog (LOG_ERR,"can't open socket: %m");
265 syslog (LOG_ERR,"can't bind: %m");
269 + memset(&hints, 0, sizeof(hints));
270 + hints.ai_family = AF_UNSPEC;
271 + hints.ai_socktype = SOCK_STREAM;
272 + hints.ai_flags = AI_PASSIVE;
273 + if(getaddrinfo(NULL, "79", &hints, &res0) < 0) {
274 + syslog(LOG_ERR, "getaddrinfo() failed");
277 + for (res = res0; res; res = res->ai_next) {
278 + if (res->ai_family == AF_UNIX)
280 + if ((lsock = socket (res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
282 + if (bind (lsock, res->ai_addr, res->ai_addrlen) == 0) {
287 + freeaddrinfo(res0);
289 + syslog (LOG_ERR,"can't create socket or bind: %m");
294 if ((pid = fork()) < 0) {
295 syslog (LOG_ERR, "can't fork(): %m");
301 + fd = accept (lsock, (struct sockaddr *)&caddr, &clen);
303 fd = accept (lsock, &caddr, &clen);
307 if (errno == EPROTO) {
309 if (errno == EPROTOTYPE) {
310 #endif /* !__FreeBSD__ */
312 + getnameinfo((struct sockaddr *)&caddr, (caddr.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in),
313 + remote_addr, sizeof(remote_addr), NULL, 0, NI_NUMERICHOST);
314 + /* If IPv4-mapped IPv6 address convert it to clean IPv4 */
315 + if (strncmp(remote_addr, "::ffff:", 7) == 0)
316 + strncpy(remote_addr, remote_addr + 7, sizeof(remote_addr));
318 remote_addr = inet_ntoa (((struct sockaddr_in *)&caddr)->sin_addr);
320 syslog(LOG_ERR,"failed connect (possible port scan) from %s: %m",
327 + getnameinfo((struct sockaddr *)&caddr, (caddr.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in),
328 + remote_addr, sizeof(remote_addr), NULL, 0, NI_NUMERICHOST);
329 + /* If IPv4-mapped IPv6 address convert it to clean IPv4 */
330 + if (strncmp(remote_addr, "::ffff:", 7) == 0)
331 + strncpy(remote_addr, remote_addr + 7, sizeof(remote_addr));
333 remote_addr = inet_ntoa (((struct sockaddr_in *)&caddr)->sin_addr);
337 * FIXME: Support for tcp wrapper via hosts.allow and .deny is missing
338 Index: cfingerd/src/proto.h
339 diff -u cfingerd/src/proto.h:1.1.1.1 cfingerd/src/proto.h:1.2
340 --- cfingerd/src/proto.h:1.1.1.1 Sun Dec 12 12:23:27 1999
341 +++ cfingerd/src/proto.h Sun Dec 12 13:07:49 1999
343 void become_nobody(void);
344 void become_user(char *);
345 int wildmat(char *, char *);
347 +char *get_rfc1413_data(struct sockaddr_storage );
349 char *get_rfc1413_data(struct sockaddr_in );
351 void check_unknown(char *);
352 void log(int, char *, char *);
353 void userlog(uid_t, gid_t, char *, char *);
354 Index: cfingerd/src/rfc1413.c
355 diff -u cfingerd/src/rfc1413.c:1.1.1.1 cfingerd/src/rfc1413.c:1.2
356 --- cfingerd/src/rfc1413.c:1.1.1.1 Sun Dec 12 12:23:27 1999
357 +++ cfingerd/src/rfc1413.c Sun Dec 12 13:07:49 1999
361 * RFC1413 implementation
362 + * IPv6 code Copyright (C) 1999 Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
364 * This program is free software; you can redistribute it and/or modify
365 * it under the terms of the GNU General Public License as published by
368 #include "cfingerd.h"
371 +static jmp_buf ident_alarm;
374 void rfc1413_alarm(int signal)
377 + siglongjmp(ident_alarm, 1);
379 if (signal == SIGALRM)
380 ident_user = "unknown@alarm.signal";
384 /* Self contained RFC1413 implementation. Thanks to Joel Katz for parts of
386 * contained in a single program. Simple, easy to use.
390 +char *get_rfc1413_data( struct sockaddr_storage local_addr )
392 + static int j = -1, err = -1;
394 char *get_rfc1413_data( struct sockaddr_in local_addr )
397 struct sockaddr_in sin;
399 char buffer[1024], buf[BUFLEN], uname[64], *bleah;
402 + struct addrinfo hints, *res, *res0;
404 struct servent *serv;
407 bleah = (char *) malloc(BUFLEN);
408 memset(bleah, 0, BUFLEN);
411 j = socket(AF_INET, SOCK_STREAM, 0);
413 snprintf(bleah, BUFLEN, "unknown@%s", remote_addr);
419 + snprintf(buffer, sizeof(buffer), "%d,%d\n", remote_port, local_port);
421 + memset(&hints, 0, sizeof(hints));
422 + hints.ai_family = local_addr.ss_family;
423 + hints.ai_socktype = SOCK_STREAM;
424 + if((err = getaddrinfo(ip_address, "113", &hints, &res0)) < 0) {
425 + syslog(LOG_ERR, "rfc1413-getaddrinfo: %s", gai_strerror(err));
426 + snprintf(bleah, BUFLEN, "unknown@%s", remote_addr);
431 + if (sigsetjmp(ident_alarm, 1) != 0) {
432 + snprintf(bleah, BUFLEN, "alarm.signal@%s", remote_addr);
435 + signal(SIGALRM, rfc1413_alarm);
437 + for (res = res0; res; res = res->ai_next) {
438 + if ((j = socket(res->ai_family, res->ai_socktype, res->ai_protocol)))
440 + switch(local_addr.ss_family) {
442 + ((struct sockaddr_in *)&local_addr)->sin_port = 0;
445 + ((struct sockaddr_in6 *)&local_addr)->sin6_port = 0;
448 + bind(j, (struct sockaddr *)&local_addr, (local_addr.ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
449 + if (connect(j, res->ai_addr, res->ai_addrlen) < 0)
456 + freeaddrinfo(res0);
458 + syslog(LOG_ERR, "rfc1413-socket-or-connect problem");
459 + snprintf(bleah, BUFLEN, "unknown@%s", remote_addr);
464 - snprintf(buffer, sizeof(buffer), "%d,%d\n", remote_port, local_port);
465 + snprintf(buffer, sizeof(buffer), "%s,%s\n", remote_port, local_port);
467 write(j, buffer, strlen(buffer));
469 memset(buf, 0, sizeof(buf));
470 Index: cfingerd/userlist/display.c
471 diff -u cfingerd/userlist/display.c:1.1.1.1 cfingerd/userlist/display.c:1.2
472 --- cfingerd/userlist/display.c:1.1.1.1 Sun Dec 12 12:23:27 1999
473 +++ cfingerd/userlist/display.c Sun Dec 12 13:06:29 1999
480 our_host = get_localhost();