Home | History | Annotate | Line # | Download | only in identd
identd.c revision 1.10
      1  1.10    jwise /*	$NetBSD: identd.c,v 1.10 1999/05/18 04:49:41 jwise Exp $	*/
      2   1.8      mrg 
      3   1.1      cgd /*
      4   1.1      cgd ** identd.c                       A TCP/IP link identification protocol server
      5   1.1      cgd **
      6   1.1      cgd ** This program is in the public domain and may be used freely by anyone
      7   1.1      cgd ** who wants to.
      8   1.1      cgd **
      9   1.9  msaitoh ** Last update: 7 Oct 1993
     10   1.1      cgd **
     11   1.1      cgd ** Please send bug fixes/bug reports to: Peter Eriksson <pen (at) lysator.liu.se>
     12   1.1      cgd */
     13   1.1      cgd 
     14   1.9  msaitoh #if !defined(__STDC__) && !defined(_AIX)
     15   1.9  msaitoh #define void int
     16   1.9  msaitoh #endif
     17   1.9  msaitoh 
     18   1.9  msaitoh #if defined(IRIX) || defined(SVR4) || defined(NeXT) || (defined(sco) && sco >= 42) || defined(_AIX4) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(ultrix)
     19   1.1      cgd #  define SIGRETURN_TYPE void
     20   1.1      cgd #  define SIGRETURN_TYPE_IS_VOID
     21   1.1      cgd #else
     22   1.1      cgd #  define SIGRETURN_TYPE int
     23   1.1      cgd #endif
     24   1.1      cgd 
     25   1.1      cgd #ifdef SVR4
     26   1.1      cgd #  define STRNET
     27   1.1      cgd #endif
     28   1.1      cgd 
     29   1.9  msaitoh #ifdef NeXT31
     30   1.9  msaitoh #  include <libc.h>
     31   1.9  msaitoh #endif
     32   1.9  msaitoh 
     33   1.9  msaitoh #ifdef sco
     34   1.9  msaitoh #  define USE_SIGALARM
     35   1.9  msaitoh #endif
     36   1.9  msaitoh 
     37   1.9  msaitoh #include <stdio.h>
     38   1.9  msaitoh #include <ctype.h>
     39   1.9  msaitoh #include <errno.h>
     40   1.9  msaitoh #include <netdb.h>
     41   1.9  msaitoh #include <signal.h>
     42   1.9  msaitoh #include <fcntl.h>
     43   1.9  msaitoh 
     44   1.1      cgd #include <sys/types.h>
     45   1.1      cgd #include <sys/param.h>
     46   1.1      cgd #include <sys/ioctl.h>
     47   1.1      cgd #include <sys/socket.h>
     48   1.1      cgd #ifndef _AUX_SOURCE
     49   1.1      cgd #  include <sys/file.h>
     50   1.1      cgd #endif
     51   1.1      cgd #include <sys/time.h>
     52   1.1      cgd #include <sys/wait.h>
     53   1.1      cgd 
     54   1.1      cgd #include <pwd.h>
     55   1.1      cgd #include <grp.h>
     56   1.1      cgd 
     57   1.1      cgd #include <netinet/in.h>
     58   1.1      cgd 
     59   1.1      cgd #ifndef HPUX7
     60   1.1      cgd #  include <arpa/inet.h>
     61   1.1      cgd #endif
     62   1.1      cgd 
     63   1.9  msaitoh #ifdef _AIX32
     64   1.9  msaitoh # include <sys/select.h>
     65   1.9  msaitoh #endif
     66   1.9  msaitoh 
     67   1.1      cgd #if defined(MIPS) || defined(BSD43)
     68   1.1      cgd extern int errno;
     69   1.1      cgd #endif
     70   1.1      cgd 
     71   1.9  msaitoh #if defined(SOLARIS) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(_AIX)
     72   1.9  msaitoh #  include <unistd.h>
     73   1.9  msaitoh #  include <stdlib.h>
     74   1.9  msaitoh #  include <string.h>
     75   1.9  msaitoh #endif
     76   1.9  msaitoh 
     77   1.1      cgd #include "identd.h"
     78   1.1      cgd #include "error.h"
     79   1.9  msaitoh #include "paths.h"
     80   1.9  msaitoh 
     81   1.1      cgd 
     82   1.1      cgd /* Antique unixes do not have these things defined... */
     83   1.1      cgd #ifndef FD_SETSIZE
     84   1.1      cgd #  define FD_SETSIZE 256
     85   1.1      cgd #endif
     86   1.1      cgd 
     87   1.1      cgd #ifndef FD_SET
     88   1.1      cgd #  ifndef NFDBITS
     89   1.1      cgd #    define NFDBITS   	(sizeof(int) * NBBY)  /* bits per mask */
     90   1.1      cgd #  endif
     91   1.1      cgd #  define FD_SET(n, p)  ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
     92   1.1      cgd #endif
     93   1.1      cgd 
     94   1.1      cgd #ifndef FD_ZERO
     95   1.1      cgd #  define FD_ZERO(p)        bzero((char *)(p), sizeof(*(p)))
     96   1.1      cgd #endif
     97   1.1      cgd 
     98   1.1      cgd 
     99   1.9  msaitoh char *path_unix = (char *) NULL;
    100   1.9  msaitoh char *path_kmem = (char *) NULL;
    101   1.1      cgd 
    102   1.1      cgd int verbose_flag = 0;
    103   1.1      cgd int debug_flag   = 0;
    104   1.1      cgd int syslog_flag  = 0;
    105   1.1      cgd int multi_flag   = 0;
    106   1.1      cgd int other_flag   = 0;
    107   1.1      cgd int unknown_flag = 0;
    108   1.1      cgd int noident_flag = 0;
    109   1.9  msaitoh int crypto_flag  = 0;
    110  1.10    jwise int liar_flag    = 0;
    111   1.1      cgd 
    112   1.1      cgd int lport = 0;
    113   1.1      cgd int fport = 0;
    114   1.1      cgd 
    115   1.9  msaitoh char *charset_name = (char *) NULL;
    116   1.9  msaitoh char *indirect_host = (char *) NULL;
    117   1.9  msaitoh char *indirect_password = (char *) NULL;
    118  1.10    jwise char *lie_string = (char *) NULL;
    119   1.9  msaitoh 
    120   1.9  msaitoh #ifdef ALLOW_FORMAT
    121   1.9  msaitoh     int format_flag = 0;
    122   1.9  msaitoh     char *format = "%u";
    123   1.9  msaitoh #endif
    124   1.1      cgd 
    125   1.1      cgd static int child_pid;
    126   1.1      cgd 
    127   1.1      cgd #ifdef LOG_DAEMON
    128   1.1      cgd static int syslog_facility = LOG_DAEMON;
    129   1.1      cgd #endif
    130   1.1      cgd 
    131   1.9  msaitoh static int comparemem __P((void *, void *, int));
    132   1.9  msaitoh char *clearmem __P((void *, int));
    133   1.9  msaitoh static SIGRETURN_TYPE child_handler __P((int));
    134   1.8      mrg int main __P((int, char *[]));
    135   1.8      mrg 
    136   1.1      cgd /*
    137   1.1      cgd ** The structure passing convention for GCC is incompatible with
    138   1.1      cgd ** Suns own C compiler, so we define our own inet_ntoa() function.
    139   1.1      cgd ** (This should only affect GCC version 1 I think, a well, this works
    140   1.1      cgd ** for version 2 also so why bother.. :-)
    141   1.1      cgd */
    142   1.9  msaitoh #if defined(__GNUC__) && defined(__sparc__) && !defined(NeXT)
    143   1.1      cgd 
    144   1.1      cgd #ifdef inet_ntoa
    145   1.1      cgd #undef inet_ntoa
    146   1.1      cgd #endif
    147   1.1      cgd 
    148   1.1      cgd char *inet_ntoa(ad)
    149   1.9  msaitoh     struct in_addr ad;
    150   1.1      cgd {
    151   1.9  msaitoh     unsigned long int s_ad;
    152   1.9  msaitoh     int a, b, c, d;
    153   1.9  msaitoh     static char addr[20];
    154   1.9  msaitoh 
    155   1.9  msaitoh     s_ad = ad.s_addr;
    156   1.9  msaitoh     d = s_ad % 256;
    157   1.9  msaitoh     s_ad /= 256;
    158   1.9  msaitoh     c = s_ad % 256;
    159   1.9  msaitoh     s_ad /= 256;
    160   1.9  msaitoh     b = s_ad % 256;
    161   1.9  msaitoh     a = s_ad / 256;
    162   1.9  msaitoh     sprintf(addr, "%d.%d.%d.%d", a, b, c, d);
    163   1.9  msaitoh 
    164   1.9  msaitoh     return addr;
    165   1.1      cgd }
    166   1.1      cgd #endif
    167   1.1      cgd 
    168   1.9  msaitoh static int comparemem(vp1, vp2, len)
    169   1.9  msaitoh      void *vp1;
    170   1.9  msaitoh      void *vp2;
    171   1.9  msaitoh      int len;
    172   1.9  msaitoh {
    173   1.9  msaitoh     unsigned char *p1 = (unsigned char *) vp1;
    174   1.9  msaitoh     unsigned char *p2 = (unsigned char *) vp2;
    175   1.9  msaitoh     int c;
    176   1.9  msaitoh 
    177   1.9  msaitoh     while (len-- > 0)
    178   1.9  msaitoh 	if ((c = (int) *p1++ - (int) *p2++) != 0)
    179   1.9  msaitoh 	    return c;
    180   1.9  msaitoh 
    181   1.9  msaitoh     return 0;
    182   1.9  msaitoh }
    183   1.1      cgd 
    184   1.1      cgd /*
    185   1.1      cgd ** Return the name of the connecting host, or the IP number as a string.
    186   1.1      cgd */
    187   1.1      cgd char *gethost(addr)
    188   1.9  msaitoh     struct in_addr *addr;
    189   1.1      cgd {
    190   1.9  msaitoh     int i;
    191   1.9  msaitoh     struct hostent *hp;
    192   1.1      cgd 
    193   1.1      cgd 
    194   1.9  msaitoh     hp = gethostbyaddr((char *) addr, sizeof(struct in_addr), AF_INET);
    195   1.9  msaitoh     if (hp)
    196   1.9  msaitoh     {
    197   1.9  msaitoh 	char *hname = strdup(hp->h_name);
    198   1.9  msaitoh 
    199   1.9  msaitoh 	if (! hname) {
    200   1.9  msaitoh 	    syslog(LOG_ERR, "strdup(%s): %m", hp->h_name);
    201   1.9  msaitoh 	    exit(1);
    202   1.9  msaitoh 	}
    203   1.9  msaitoh 	/* Found a IP -> Name match, now try the reverse for security reasons */
    204   1.9  msaitoh 	hp = gethostbyname(hname);
    205   1.9  msaitoh 	(void) free(hname);
    206   1.9  msaitoh 	if (hp)
    207   1.9  msaitoh #ifdef h_addr
    208   1.9  msaitoh 	    for (i = 0; hp->h_addr_list[i]; i++)
    209   1.9  msaitoh 		if (comparemem(hp->h_addr_list[i],
    210   1.9  msaitoh 			       (unsigned char *) addr,
    211   1.9  msaitoh 			       (int) sizeof(struct in_addr)) == 0)
    212   1.9  msaitoh 		    return (char *) hp->h_name;
    213   1.9  msaitoh #else
    214   1.9  msaitoh 	if (comparemem(hp->h_addr, addr, sizeof(struct in_addr)) == 0)
    215   1.9  msaitoh 	    return hp->h_name;
    216   1.9  msaitoh #endif
    217   1.9  msaitoh   }
    218   1.9  msaitoh 
    219   1.9  msaitoh   return inet_ntoa(*addr);
    220   1.1      cgd }
    221   1.1      cgd 
    222   1.9  msaitoh #ifdef USE_SIGALARM
    223   1.1      cgd /*
    224   1.1      cgd ** Exit cleanly after our time's up.
    225   1.1      cgd */
    226   1.1      cgd static SIGRETURN_TYPE
    227   1.9  msaitoh alarm_handler(int s)
    228   1.1      cgd {
    229   1.9  msaitoh     if (syslog_flag)
    230   1.9  msaitoh 	syslog(LOG_DEBUG, "SIGALRM triggered, exiting");
    231   1.9  msaitoh 
    232   1.9  msaitoh     exit(0);
    233   1.1      cgd }
    234   1.9  msaitoh #endif
    235   1.9  msaitoh 
    236   1.1      cgd 
    237   1.9  msaitoh #if !defined(hpux) && !defined(__hpux) && !defined(SVR4) && \
    238   1.9  msaitoh     !defined(_CRAY) && !defined(sco) && !defined(LINUX)
    239   1.1      cgd /*
    240   1.1      cgd ** This is used to clean up zombie child processes
    241   1.1      cgd ** if the -w or -b options are used.
    242   1.1      cgd */
    243   1.1      cgd static SIGRETURN_TYPE
    244   1.9  msaitoh child_handler(dummy)
    245   1.9  msaitoh 	int dummy;
    246   1.1      cgd {
    247   1.9  msaitoh #if defined(NeXT) || (defined(__sgi) && defined(__SVR3))
    248   1.9  msaitoh     union wait status;
    249   1.1      cgd #else
    250   1.9  msaitoh     int status;
    251   1.1      cgd #endif
    252   1.9  msaitoh     int saved_errno = errno;
    253   1.9  msaitoh 
    254   1.9  msaitoh     while (wait3(&status, WNOHANG, NULL) > 0)
    255   1.9  msaitoh 	;
    256   1.1      cgd 
    257   1.9  msaitoh     errno = saved_errno;
    258   1.9  msaitoh 
    259   1.1      cgd #ifndef SIGRETURN_TYPE_IS_VOID
    260   1.9  msaitoh     return 0;
    261   1.1      cgd #endif
    262   1.1      cgd }
    263   1.1      cgd #endif
    264   1.1      cgd 
    265   1.9  msaitoh 
    266   1.9  msaitoh char *clearmem(vbp, len)
    267   1.9  msaitoh      void *vbp;
    268   1.9  msaitoh      int len;
    269   1.1      cgd {
    270   1.9  msaitoh     char *bp = (char *) vbp;
    271   1.9  msaitoh     char *cp;
    272   1.1      cgd 
    273   1.9  msaitoh     cp = bp;
    274   1.9  msaitoh     while (len-- > 0)
    275   1.9  msaitoh 	*cp++ = 0;
    276   1.9  msaitoh 
    277   1.9  msaitoh     return bp;
    278   1.1      cgd }
    279   1.1      cgd 
    280   1.1      cgd 
    281   1.1      cgd /*
    282   1.1      cgd ** Main entry point into this daemon
    283   1.1      cgd */
    284   1.1      cgd int main(argc,argv)
    285   1.9  msaitoh     int argc;
    286   1.9  msaitoh     char *argv[];
    287   1.1      cgd {
    288   1.9  msaitoh     int i, len;
    289   1.9  msaitoh     struct sockaddr_in sin;
    290   1.9  msaitoh     struct in_addr laddr, faddr;
    291   1.9  msaitoh #ifndef USE_SIGALARM
    292   1.9  msaitoh     struct timeval tv;
    293   1.9  msaitoh #endif
    294   1.9  msaitoh     int one = 1;
    295   1.9  msaitoh 
    296   1.9  msaitoh     int background_flag = 0;
    297   1.9  msaitoh     int timeout = 0;
    298   1.9  msaitoh     char *portno = "113";
    299   1.9  msaitoh     char *bind_address = (char *) NULL;
    300   1.9  msaitoh     int set_uid = 0;
    301   1.9  msaitoh     int set_gid = 0;
    302   1.9  msaitoh     int inhibit_default_config = 0;
    303   1.9  msaitoh     int opt_count = 0;		/* Count of option flags */
    304   1.1      cgd 
    305   1.1      cgd #ifdef __convex__
    306   1.9  msaitoh     argc--;    /* get rid of extra argument passed by inetd */
    307   1.1      cgd #endif
    308   1.1      cgd 
    309   1.9  msaitoh 
    310   1.9  msaitoh     if (isatty(0))
    311   1.9  msaitoh 	background_flag = 1;
    312   1.9  msaitoh 
    313   1.9  msaitoh     /*
    314   1.9  msaitoh     ** Prescan the arguments for "-f<config-file>" switches
    315   1.9  msaitoh     */
    316   1.9  msaitoh     inhibit_default_config = 0;
    317   1.9  msaitoh     for (i = 1; i < argc && argv[i][0] == '-'; i++)
    318   1.9  msaitoh 	if (argv[i][1] == 'f')
    319   1.9  msaitoh 	    inhibit_default_config = 1;
    320   1.9  msaitoh 
    321   1.9  msaitoh     /*
    322   1.9  msaitoh     ** Parse the default config file - if it exists
    323   1.9  msaitoh     */
    324   1.9  msaitoh     if (!inhibit_default_config)
    325   1.9  msaitoh 	parse_config(NULL, 1);
    326   1.1      cgd 
    327   1.9  msaitoh     /*
    328   1.9  msaitoh     ** Parse the command line arguments
    329   1.9  msaitoh     */
    330   1.9  msaitoh     for (i = 1; i < argc && argv[i][0] == '-'; i++) {
    331   1.9  msaitoh 	opt_count++;
    332   1.9  msaitoh 	switch (argv[i][1])
    333   1.9  msaitoh 	{
    334   1.9  msaitoh 	  case 'b':    /* Start as standalone daemon */
    335   1.9  msaitoh 	    background_flag = 1;
    336   1.9  msaitoh 	    break;
    337   1.9  msaitoh 
    338   1.9  msaitoh 	  case 'w':    /* Start from Inetd, wait mode */
    339   1.9  msaitoh 	    background_flag = 2;
    340   1.9  msaitoh 	    break;
    341   1.9  msaitoh 
    342   1.9  msaitoh 	  case 'i':    /* Start from Inetd, nowait mode */
    343   1.9  msaitoh 	    background_flag = 0;
    344   1.9  msaitoh 	    break;
    345   1.9  msaitoh 
    346   1.9  msaitoh 	  case 't':
    347   1.9  msaitoh 	    timeout = atoi(argv[i]+2);
    348   1.9  msaitoh 	    break;
    349   1.9  msaitoh 
    350   1.9  msaitoh 	  case 'p':
    351   1.9  msaitoh 	    portno = argv[i]+2;
    352   1.9  msaitoh 	    break;
    353   1.9  msaitoh 
    354   1.9  msaitoh 	  case 'a':
    355   1.9  msaitoh 	    bind_address = argv[i]+2;
    356   1.9  msaitoh 	    break;
    357   1.9  msaitoh 
    358   1.9  msaitoh 	  case 'u':
    359   1.9  msaitoh 	    if (isdigit(argv[i][2]))
    360   1.9  msaitoh 		set_uid = atoi(argv[i]+2);
    361   1.9  msaitoh 	    else
    362   1.9  msaitoh 	    {
    363   1.9  msaitoh 		struct passwd *pwd;
    364   1.9  msaitoh 
    365   1.9  msaitoh 		pwd = getpwnam(argv[i]+2);
    366   1.9  msaitoh 		if (!pwd)
    367   1.9  msaitoh 		    ERROR1("no such user (%s) for -u option", argv[i]+2);
    368   1.9  msaitoh 		else
    369   1.9  msaitoh 		{
    370   1.9  msaitoh 		    set_uid = pwd->pw_uid;
    371   1.9  msaitoh 		    set_gid = pwd->pw_gid;
    372   1.9  msaitoh 		}
    373   1.9  msaitoh 	    }
    374   1.9  msaitoh 	    break;
    375   1.9  msaitoh 
    376   1.9  msaitoh 	  case 'g':
    377   1.9  msaitoh 	    if (isdigit(argv[i][2]))
    378   1.9  msaitoh 		set_gid = atoi(argv[i]+2);
    379   1.9  msaitoh 	    else
    380   1.9  msaitoh 	    {
    381   1.9  msaitoh 		struct group *grp;
    382   1.9  msaitoh 
    383   1.9  msaitoh 		grp = getgrnam(argv[i]+2);
    384   1.9  msaitoh 		if (!grp)
    385   1.9  msaitoh 		    ERROR1("no such group (%s) for -g option", argv[i]+2);
    386   1.9  msaitoh 		else
    387   1.9  msaitoh 		    set_gid = grp->gr_gid;
    388   1.9  msaitoh 	    }
    389   1.9  msaitoh 	    break;
    390   1.9  msaitoh 
    391   1.9  msaitoh 	  case 'c':
    392   1.9  msaitoh 	    charset_name = argv[i]+2;
    393   1.9  msaitoh 	    break;
    394   1.9  msaitoh 
    395   1.9  msaitoh 	  case 'r':
    396   1.9  msaitoh 	    indirect_host = argv[i]+2;
    397   1.9  msaitoh 	    break;
    398   1.9  msaitoh 
    399   1.9  msaitoh 	  case 'l':    /* Use the Syslog daemon for logging */
    400   1.9  msaitoh 	    syslog_flag++;
    401   1.9  msaitoh #ifdef LOG_DAEMON
    402   1.9  msaitoh 	    openlog("identd", LOG_PID, syslog_facility);
    403   1.9  msaitoh #else
    404   1.9  msaitoh 	    openlog("identd", LOG_PID);
    405   1.9  msaitoh #endif
    406   1.9  msaitoh 	    break;
    407   1.9  msaitoh 
    408   1.9  msaitoh 	  case 'o':
    409   1.9  msaitoh 	    other_flag = 1;
    410   1.9  msaitoh 	    break;
    411   1.9  msaitoh 
    412   1.9  msaitoh 	  case 'e':
    413   1.9  msaitoh 	    unknown_flag = 1;
    414   1.9  msaitoh 	    break;
    415   1.9  msaitoh 
    416   1.9  msaitoh 	  case 'V':    /* Give version of this daemon */
    417   1.9  msaitoh 	    printf("[in.identd, version %s]\r\n", version);
    418   1.9  msaitoh 	    exit(0);
    419   1.9  msaitoh 	    break;
    420   1.9  msaitoh 
    421   1.9  msaitoh 	  case 'v':    /* Be verbose */
    422   1.9  msaitoh 	    verbose_flag++;
    423   1.9  msaitoh 	    break;
    424   1.9  msaitoh 
    425   1.9  msaitoh 	  case 'd':    /* Enable debugging */
    426   1.9  msaitoh 	    debug_flag++;
    427   1.9  msaitoh 	    break;
    428   1.9  msaitoh 
    429   1.9  msaitoh 	  case 'm':    /* Enable multiline queries */
    430   1.9  msaitoh 	    multi_flag++;
    431   1.9  msaitoh 	    break;
    432   1.9  msaitoh 
    433   1.9  msaitoh 	  case 'N':    /* Enable users ".noident" files */
    434   1.9  msaitoh 	    noident_flag++;
    435   1.9  msaitoh 	    break;
    436   1.9  msaitoh 
    437   1.9  msaitoh #ifdef INCLUDE_CRYPT
    438   1.9  msaitoh           case 'C':    /* Enable encryption. */
    439   1.9  msaitoh 	    {
    440   1.9  msaitoh 		FILE *keyfile;
    441   1.9  msaitoh 
    442   1.9  msaitoh 		if (argv[i][2])
    443   1.9  msaitoh 		    keyfile = fopen(argv[i]+2, "r");
    444   1.9  msaitoh 		else
    445   1.9  msaitoh 		    keyfile = fopen(PATH_DESKEY, "r");
    446   1.9  msaitoh 
    447   1.9  msaitoh 		if (keyfile == NULL)
    448   1.9  msaitoh 		{
    449   1.9  msaitoh 		    ERROR("cannot open key file for option -C");
    450   1.9  msaitoh 		}
    451   1.9  msaitoh 		else
    452   1.9  msaitoh 		{
    453   1.9  msaitoh 		    char buf[1024];
    454   1.9  msaitoh 
    455   1.9  msaitoh 		    if (fgets(buf, 1024, keyfile) == NULL)
    456   1.9  msaitoh 		    {
    457   1.9  msaitoh 			ERROR("cannot read key file for option -C");
    458   1.9  msaitoh 		    }
    459   1.9  msaitoh 		    else
    460   1.9  msaitoh 		    {
    461   1.9  msaitoh 			init_encryption(buf);
    462   1.9  msaitoh 			crypto_flag++;
    463   1.9  msaitoh 		    }
    464   1.9  msaitoh 		    fclose(keyfile);
    465   1.9  msaitoh 		}
    466   1.9  msaitoh 	    }
    467   1.9  msaitoh             break;
    468   1.9  msaitoh #endif
    469   1.9  msaitoh 
    470   1.9  msaitoh #ifdef ALLOW_FORMAT
    471   1.9  msaitoh 	  case 'n': /* Compatibility flag - just send the user number */
    472   1.9  msaitoh 	    format_flag = 1;
    473   1.9  msaitoh 	    format = "%U";
    474   1.9  msaitoh 	    break;
    475   1.9  msaitoh 
    476   1.9  msaitoh           case 'F':    /* Output format */
    477   1.9  msaitoh 	    format_flag = 1;
    478   1.9  msaitoh 	    format = argv[i]+2;
    479   1.9  msaitoh 	    break;
    480   1.9  msaitoh #endif
    481  1.10    jwise 
    482  1.10    jwise 	  case 'L':	/* lie brazenly */
    483  1.10    jwise 	    liar_flag = 1;
    484  1.10    jwise 	    if (*(argv[i]+2) != '\0')
    485  1.10    jwise 		lie_string = argv[i]+2;
    486  1.10    jwise 	    else
    487  1.10    jwise #ifdef DEFAULT_LIE_USER
    488  1.10    jwise 		lie_string = DEFAULT_LIE_USER;
    489  1.10    jwise #else
    490  1.10    jwise 		ERROR("-L specified with no user name");
    491  1.10    jwise #endif
    492  1.10    jwise 	    break;
    493   1.9  msaitoh 
    494   1.9  msaitoh 	  default:
    495   1.9  msaitoh 	    ERROR1("Bad option %s", argv[i]);
    496   1.9  msaitoh 	    break;
    497   1.9  msaitoh 	}
    498   1.9  msaitoh     }
    499   1.9  msaitoh 
    500   1.9  msaitoh #if defined(_AUX_SOURCE) || defined (SUNOS35)
    501   1.9  msaitoh     /* A/UX 2.0* & SunOS 3.5 calls us with an argument XXXXXXXX.YYYY
    502   1.9  msaitoh     ** where XXXXXXXXX is the hexadecimal version of the callers
    503   1.9  msaitoh     ** IP number, and YYYY is the port/socket or something.
    504   1.9  msaitoh     ** It seems to be impossible to pass arguments to a daemon started
    505   1.9  msaitoh     ** by inetd.
    506   1.9  msaitoh     **
    507   1.9  msaitoh     ** Just in case it is started from something else, then we only
    508   1.9  msaitoh     ** skip the argument if no option flags have been seen.
    509   1.9  msaitoh     */
    510   1.9  msaitoh     if (opt_count == 0)
    511   1.9  msaitoh 	argc--;
    512   1.9  msaitoh #endif
    513   1.9  msaitoh 
    514   1.9  msaitoh     /*
    515   1.9  msaitoh     ** Path to kernel namelist file specified on command line
    516   1.9  msaitoh     */
    517   1.9  msaitoh     if (i < argc)
    518   1.9  msaitoh 	path_unix = argv[i++];
    519   1.9  msaitoh 
    520   1.9  msaitoh     /*
    521   1.9  msaitoh     ** Path to kernel memory device specified on command line
    522   1.9  msaitoh     */
    523   1.9  msaitoh     if (i < argc)
    524   1.9  msaitoh 	path_kmem = argv[i++];
    525   1.9  msaitoh 
    526   1.9  msaitoh 
    527   1.9  msaitoh     if (i < argc)
    528   1.9  msaitoh 	ERROR1("Too many arguments: ignored from %s", argv[i]);
    529   1.9  msaitoh 
    530   1.9  msaitoh 
    531   1.9  msaitoh     /*
    532   1.9  msaitoh     ** We used to call k_open here. But then the file descriptor
    533   1.9  msaitoh     ** kd->fd open on /dev/kmem is shared by all child processes.
    534   1.9  msaitoh     ** From the fork(2) man page:
    535   1.9  msaitoh     **      o  The child process has its own copy of the parent's descriptors.  These
    536   1.9  msaitoh     **         descriptors reference the same underlying objects.  For instance, file
    537   1.9  msaitoh     **         pointers in file objects are shared between the child and the parent
    538   1.9  msaitoh     **         so that an lseek(2) on a descriptor in the child process can affect a
    539   1.9  msaitoh     **         subsequent read(2) or write(2) by the parent.
    540   1.9  msaitoh     ** Thus with concurrent (simultaneous) identd client processes,
    541   1.9  msaitoh     ** they step on each other's toes when they use kvm_read.
    542   1.9  msaitoh     **
    543   1.9  msaitoh     ** Calling k_open here was a mistake for another reason too: we
    544   1.9  msaitoh     ** did not yet honor -u and -g options. Presumably we are
    545   1.9  msaitoh     ** running as root (unless the in.identd file is setuid), and
    546   1.9  msaitoh     ** then we can open kmem regardless of -u and -g values.
    547   1.9  msaitoh     **
    548   1.9  msaitoh     **
    549   1.9  msaitoh     ** Open the kernel memory device and read the nlist table
    550   1.9  msaitoh     **
    551   1.9  msaitoh     **     if (k_open() < 0)
    552   1.9  msaitoh     ** 		ERROR("main: k_open");
    553   1.9  msaitoh     */
    554   1.9  msaitoh 
    555   1.9  msaitoh     /*
    556   1.9  msaitoh     ** Do the special handling needed for the "-b" flag
    557   1.9  msaitoh     */
    558   1.9  msaitoh     if (background_flag == 1)
    559   1.1      cgd     {
    560   1.9  msaitoh 	struct sockaddr_in addr;
    561   1.9  msaitoh 	struct servent *sp;
    562   1.9  msaitoh 	int fd;
    563   1.9  msaitoh 
    564   1.9  msaitoh 
    565   1.9  msaitoh 	if (!debug_flag)
    566   1.9  msaitoh 	{
    567   1.9  msaitoh 	    if (fork())
    568   1.9  msaitoh 		exit(0);
    569   1.9  msaitoh 
    570   1.9  msaitoh 	    close(0);
    571   1.9  msaitoh 	    close(1);
    572   1.9  msaitoh 	    close(2);
    573   1.9  msaitoh 
    574   1.9  msaitoh 	    if (fork())
    575   1.9  msaitoh 		exit(0);
    576   1.9  msaitoh 	}
    577   1.9  msaitoh 
    578   1.9  msaitoh 	fd = socket(AF_INET, SOCK_STREAM, 0);
    579   1.9  msaitoh 	if (fd == -1)
    580   1.9  msaitoh 	    ERROR("main: socket");
    581   1.9  msaitoh 
    582   1.9  msaitoh 	if (fd != 0)
    583   1.9  msaitoh 	    dup2(fd, 0);
    584   1.9  msaitoh 
    585   1.9  msaitoh 	clearmem((void *) &addr, (int) sizeof(addr));
    586   1.9  msaitoh 
    587   1.9  msaitoh 	addr.sin_family = AF_INET;
    588   1.9  msaitoh 	if (bind_address == (char *) NULL)
    589   1.9  msaitoh 	    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    590   1.1      cgd 	else
    591   1.9  msaitoh 	{
    592   1.9  msaitoh 	    if (isdigit(bind_address[0]))
    593   1.9  msaitoh 		addr.sin_addr.s_addr = inet_addr(bind_address);
    594   1.9  msaitoh 	    else
    595   1.9  msaitoh 	    {
    596   1.9  msaitoh 		struct hostent *hp;
    597   1.9  msaitoh 
    598   1.9  msaitoh 		hp = gethostbyname(bind_address);
    599   1.9  msaitoh 		if (!hp)
    600   1.9  msaitoh 		    ERROR1("no such address (%s) for -a switch", bind_address);
    601   1.9  msaitoh 
    602   1.9  msaitoh 		/* This is ugly, should use memcpy() or bcopy() but... */
    603   1.9  msaitoh 		addr.sin_addr.s_addr = * (unsigned long *) (hp->h_addr);
    604   1.9  msaitoh 	    }
    605   1.1      cgd 	}
    606   1.1      cgd 
    607   1.9  msaitoh 	if (isdigit(portno[0]))
    608   1.9  msaitoh 	    addr.sin_port = htons(atoi(portno));
    609   1.1      cgd 	else
    610   1.9  msaitoh 	{
    611   1.9  msaitoh 	    sp = getservbyname(portno, "tcp");
    612   1.9  msaitoh 	    if (sp == (struct servent *) NULL)
    613   1.9  msaitoh 		ERROR1("main: getservbyname: %s", portno);
    614   1.9  msaitoh 	    addr.sin_port = sp->s_port;
    615   1.9  msaitoh 	}
    616   1.1      cgd 
    617   1.9  msaitoh #ifdef SO_REUSEADDR
    618   1.9  msaitoh 	setsockopt(0, SOL_SOCKET, SO_REUSEADDR, (void *) &one, sizeof(one));
    619   1.9  msaitoh #endif
    620   1.1      cgd 
    621   1.9  msaitoh 	if (bind(0, (struct sockaddr *) &addr, sizeof(addr)) < 0)
    622   1.9  msaitoh 	    ERROR("main: bind");
    623   1.1      cgd     }
    624   1.9  msaitoh 
    625   1.9  msaitoh     if (background_flag)
    626   1.9  msaitoh     {
    627   1.9  msaitoh       if (listen(0, 3) < 0)
    628   1.9  msaitoh 	ERROR("main: listen");
    629   1.9  msaitoh     }
    630   1.9  msaitoh 
    631   1.9  msaitoh     if (set_gid)
    632   1.1      cgd     {
    633   1.9  msaitoh 	if (setgid(set_gid) == -1)
    634   1.9  msaitoh 	    ERROR("main: setgid");
    635   1.9  msaitoh 	/* Call me paranoid... PSz */
    636   1.9  msaitoh 	if (getgid() != set_gid)
    637   1.9  msaitoh 	    ERROR2("main: setgid failed: wanted %d, got GID %d", set_gid, getgid());
    638   1.9  msaitoh 	if (getegid() != set_gid)
    639   1.9  msaitoh 	    ERROR2("main: setgid failed: wanted %d, got EGID %d", set_gid, getegid());
    640   1.1      cgd     }
    641   1.9  msaitoh 
    642   1.9  msaitoh     if (set_uid)
    643   1.1      cgd     {
    644   1.9  msaitoh 	if (setuid(set_uid) == -1)
    645   1.9  msaitoh 	    ERROR("main: setuid");
    646   1.9  msaitoh 	/* Call me paranoid... PSz */
    647   1.9  msaitoh 	if (getuid() != set_uid)
    648   1.9  msaitoh 	    ERROR2("main: setuid failed: wanted %d, got UID %d", set_uid, getuid());
    649   1.9  msaitoh 	if (geteuid() != set_uid)
    650   1.9  msaitoh 	    ERROR2("main: setuid failed: wanted %d, got EUID %d", set_uid, geteuid());
    651   1.1      cgd     }
    652   1.1      cgd 
    653   1.1      cgd     /*
    654   1.9  msaitoh     ** Do some special handling if the "-b" or "-w" flags are used
    655   1.9  msaitoh     */
    656   1.9  msaitoh     if (background_flag)
    657   1.9  msaitoh     {
    658   1.9  msaitoh 	int nfds, fd;
    659   1.9  msaitoh 	fd_set read_set;
    660   1.9  msaitoh 	struct sockaddr sad;
    661   1.9  msaitoh 	int sadlen;
    662   1.9  msaitoh 
    663   1.9  msaitoh 
    664   1.9  msaitoh 	/*
    665   1.9  msaitoh 	** Set up the SIGCHLD signal child termination handler so
    666   1.9  msaitoh 	** that we can avoid zombie processes hanging around and
    667   1.9  msaitoh 	** handle childs terminating before being able to complete the
    668   1.9  msaitoh 	** handshake.
    669   1.9  msaitoh 	*/
    670   1.9  msaitoh #if (defined(SVR4) || defined(hpux) || defined(__hpux) || defined(IRIX) || \
    671   1.9  msaitoh      defined(_CRAY) || defined(_AUX_SOURCE) || defined(sco) || \
    672   1.9  msaitoh 	 defined(LINUX))
    673   1.9  msaitoh 	signal(SIGCHLD, SIG_IGN);
    674   1.1      cgd #else
    675   1.9  msaitoh 	signal(SIGCHLD, child_handler);
    676   1.1      cgd #endif
    677   1.1      cgd 
    678   1.9  msaitoh 	/*
    679   1.9  msaitoh 	** Loop and dispatch client handling processes
    680   1.9  msaitoh 	*/
    681   1.9  msaitoh 	do
    682   1.9  msaitoh 	{
    683   1.9  msaitoh #ifdef USE_SIGALARM
    684   1.9  msaitoh 	    /*
    685   1.9  msaitoh 	    ** Terminate if we've been idle for 'timeout' seconds
    686   1.9  msaitoh 	    */
    687   1.9  msaitoh 	    if (background_flag == 2 && timeout)
    688   1.9  msaitoh 	    {
    689   1.9  msaitoh 		signal(SIGALRM, alarm_handler);
    690   1.9  msaitoh 		alarm(timeout);
    691   1.9  msaitoh 	    }
    692   1.9  msaitoh #endif
    693   1.1      cgd 
    694   1.9  msaitoh 	    /*
    695   1.9  msaitoh 	    ** Wait for a connection request to occur.
    696   1.9  msaitoh 	    ** Ignore EINTR (Interrupted System Call).
    697   1.9  msaitoh 	    */
    698   1.9  msaitoh 	    do
    699   1.9  msaitoh 	    {
    700   1.9  msaitoh 		FD_ZERO(&read_set);
    701   1.9  msaitoh 		FD_SET(0, &read_set);
    702   1.9  msaitoh 
    703   1.9  msaitoh #ifndef USE_SIGALARM
    704   1.9  msaitoh 		if (timeout)
    705   1.9  msaitoh 		{
    706   1.9  msaitoh 		    tv.tv_sec = timeout;
    707   1.9  msaitoh 		    tv.tv_usec = 0;
    708   1.9  msaitoh #ifdef __hpux
    709   1.9  msaitoh 		    nfds = select(FD_SETSIZE,
    710   1.9  msaitoh 				  (int *) &read_set, NULL, NULL, &tv);
    711   1.9  msaitoh #else
    712   1.9  msaitoh 		    nfds = select(FD_SETSIZE, &read_set, NULL, NULL, &tv);
    713   1.9  msaitoh #endif
    714   1.9  msaitoh 		}
    715   1.9  msaitoh 		else
    716   1.9  msaitoh #endif
    717   1.1      cgd 
    718   1.9  msaitoh #ifdef __hpux
    719   1.9  msaitoh 		nfds = select(FD_SETSIZE, (int *) &read_set, NULL, NULL, NULL);
    720   1.9  msaitoh #else
    721   1.9  msaitoh 		nfds = select(FD_SETSIZE, &read_set, NULL, NULL, NULL);
    722   1.9  msaitoh #endif
    723   1.9  msaitoh 	    } while (nfds < 0  && errno == EINTR);
    724   1.9  msaitoh 
    725   1.9  msaitoh 	    /*
    726   1.9  msaitoh 	    ** An error occured in select? Just die
    727   1.9  msaitoh 	    */
    728   1.9  msaitoh 	    if (nfds < 0)
    729   1.9  msaitoh 		ERROR("main: select");
    730   1.9  msaitoh 
    731   1.9  msaitoh 	    /*
    732   1.9  msaitoh 	    ** Timeout limit reached. Exit nicely
    733   1.9  msaitoh 	    */
    734   1.9  msaitoh 	    if (nfds == 0)
    735   1.9  msaitoh 		exit(0);
    736   1.1      cgd 
    737   1.9  msaitoh #ifdef USE_SIGALARM
    738   1.9  msaitoh 	    /*
    739   1.9  msaitoh 	    ** Disable the alarm timeout
    740   1.9  msaitoh 	    */
    741   1.9  msaitoh 	    alarm(0);
    742   1.9  msaitoh #endif
    743   1.1      cgd 
    744   1.9  msaitoh 	    /*
    745   1.9  msaitoh 	    ** Accept the new client
    746   1.9  msaitoh 	    */
    747   1.9  msaitoh 	    sadlen = sizeof(sad);
    748   1.9  msaitoh 	    errno = 0;
    749   1.9  msaitoh 	    fd = accept(0, &sad, &sadlen);
    750   1.9  msaitoh 	    if (fd == -1)
    751   1.9  msaitoh 		ERROR1("main: accept. errno = %d", errno);
    752   1.1      cgd 
    753   1.9  msaitoh 	    /*
    754   1.9  msaitoh 	    ** And fork, then close the fd if we are the parent.
    755   1.9  msaitoh 	    */
    756   1.9  msaitoh 	    child_pid = fork();
    757   1.9  msaitoh 	} while (child_pid && (close(fd), 1));
    758   1.9  msaitoh 
    759   1.9  msaitoh 	/*
    760   1.9  msaitoh 	** We are now in child, the parent has returned to "do" above.
    761   1.9  msaitoh 	*/
    762   1.9  msaitoh 	if (dup2(fd, 0) == -1)
    763   1.9  msaitoh 	    ERROR("main: dup2: failed fd 0");
    764   1.9  msaitoh 
    765   1.9  msaitoh 	if (dup2(fd, 1) == -1)
    766   1.9  msaitoh 	    ERROR("main: dup2: failed fd 1");
    767   1.9  msaitoh 
    768   1.9  msaitoh 	if (dup2(fd, 2) == -1)
    769   1.9  msaitoh 	    ERROR("main: dup2: failed fd 2");
    770   1.9  msaitoh     }
    771   1.9  msaitoh 
    772   1.1      cgd     /*
    773   1.9  msaitoh     ** Get foreign internet address
    774   1.1      cgd     */
    775   1.9  msaitoh     len = sizeof(sin);
    776   1.9  msaitoh     if (getpeername(0, (struct sockaddr *) &sin, &len) == -1)
    777   1.9  msaitoh     {
    778   1.9  msaitoh 	/*
    779   1.9  msaitoh 	** A user has tried to start us from the command line or
    780   1.9  msaitoh 	** the network link died, in which case this message won't
    781   1.9  msaitoh 	** reach to other end anyway, so lets give the poor user some
    782   1.9  msaitoh 	** errors.
    783   1.9  msaitoh 	*/
    784   1.9  msaitoh 	perror("in.identd: getpeername()");
    785   1.9  msaitoh 	exit(1);
    786   1.9  msaitoh     }
    787   1.9  msaitoh 
    788   1.9  msaitoh     faddr = sin.sin_addr;
    789   1.1      cgd 
    790   1.1      cgd 
    791   1.9  msaitoh #ifdef STRONG_LOG
    792   1.9  msaitoh     if (syslog_flag)
    793   1.9  msaitoh 	syslog(LOG_INFO, "Connection from %s", gethost(&faddr));
    794   1.9  msaitoh #endif
    795   1.1      cgd 
    796   1.9  msaitoh 
    797   1.9  msaitoh     /*
    798   1.9  msaitoh     ** Get local internet address
    799   1.1      cgd     */
    800   1.9  msaitoh     len = sizeof(sin);
    801   1.9  msaitoh #ifdef ATTSVR4
    802   1.9  msaitoh     if (t_getsockname(0, (struct sockaddr *) &sin, &len) == -1)
    803   1.1      cgd #else
    804   1.9  msaitoh     if (getsockname(0, (struct sockaddr *) &sin, &len) == -1)
    805   1.1      cgd #endif
    806   1.9  msaitoh     {
    807   1.9  msaitoh 	/*
    808   1.9  msaitoh 	** We can just die here, because if this fails then the
    809   1.9  msaitoh 	** network has died and we haven't got anyone to return
    810   1.9  msaitoh 	** errors to.
    811   1.9  msaitoh 	*/
    812   1.9  msaitoh 	exit(1);
    813   1.9  msaitoh     }
    814   1.9  msaitoh     laddr = sin.sin_addr;
    815   1.1      cgd 
    816   1.1      cgd 
    817   1.1      cgd     /*
    818   1.9  msaitoh     ** Get the local/foreign port pair from the luser
    819   1.1      cgd     */
    820   1.9  msaitoh     parse(stdin, &laddr, &faddr);
    821   1.1      cgd 
    822   1.9  msaitoh     exit(0);
    823   1.1      cgd }
    824