Exemple #1
0
int fakeidentd_main(int argc, char **argv)
{
    memset(conns, 0, sizeof(conns));
    memset(&G, 0, sizeof(G));
    FD_ZERO(&G.readfds);
    FD_SET(0, &G.readfds);

    /* handle -b <ip> parameter */
    bb_getopt_ulflags(argc, argv, "b:", &bind_ip_address);
    /* handle optional REPLY STRING */
    if (optind < argc)
        G.identuser = argv[optind];
    else
        G.identuser = nobodystr;

    /* daemonize and have the parent return */
    if (godaemon() == 0)
        return 0;

    /* main loop where we process all events and never exit */
    while (1) {
        fd_set rfds = G.readfds;
        struct timeval tv = { 15, 0 };
        int i;
        int tim = time(NULL);

        select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL);

        for (i = G.conncnt - 1; i >= 0; i--) {
            int s = i + FCS;

            if (FD_ISSET(s, &rfds)) {
                char *buf = conns[i].buf;
                unsigned int len = conns[i].len;
                unsigned int l;

                if ((l = read(s, buf + len, sizeof(conns[0].buf) - len)) > 0) {
                    if (checkInput(buf, len, l)) {
                        reply(s, buf);
                        goto deleteconn;
                    } else if (len + l >= sizeof(conns[0].buf)) {
                        replyError(s, "X-INVALID-REQUEST");
                        goto deleteconn;
                    } else {
                        conns[i].len += l;
                    }
                } else {
                    goto deleteconn;
                }

                conns[i].lasttime = tim;
                continue;

deleteconn:
                deleteConn(s);
            } else {
                /* implement as time_after() in linux kernel sources ... */
                if (conns[i].lasttime + MAXIDLETIME <= tim) {
                    replyError(s, "X-TIMEOUT");
                    deleteConn(s);
                }
            }
        }

        if (FD_ISSET(0, &rfds)) {
            int s = accept(0, NULL, 0);

            if (s < 0) {
                if (errno != EINTR) /* EINTR */
                    syslog(LOG_ERR, "accept: %s", strerror(errno));
            } else {
                if (G.conncnt == MAXCONNS)
                    i = closeOldest();
                else
                    i = G.conncnt++;

                movefd(s, i + FCS); /* move if not already there */
                FD_SET(i + FCS, &G.readfds);

                conns[i].len = 0;
                conns[i].lasttime = time(NULL);
            }
        }
    } /* end of while(1) */

    return 0;
}
Exemple #2
0
int fakeidentd_main(int argc, char **argv)
{
	int fd;
	pid_t pid;

	/* FD_ZERO(&G.readfds); - in bss, already zeroed */
	FD_SET(0, &G.readfds);

	/* handle -b <ip> parameter */
	getopt32(argc, argv, "b:", &bind_ip_address);
	/* handle optional REPLY STRING */
	if (optind < argc)
		G.identuser = argv[optind];
	else
		G.identuser = "******";

	writepid();
	signal(SIGTERM, handlexitsigs);
	signal(SIGINT,  handlexitsigs);
	signal(SIGQUIT, handlexitsigs);
	signal(SIGHUP, SIG_IGN);
	signal(SIGPIPE, SIG_IGN); /* ignore closed connections when writing */

	fd = create_and_bind_stream_or_die(bind_ip_address, bb_lookup_port("identd", "tcp", 113));
	xlisten(fd, 5);

	pid = fork();
	if (pid < 0)
		bb_perror_msg_and_die("fork");
	if (pid != 0) /* parent */
		exit(0);
	/* child */
	setsid();
	movefd(fd, 0);
	while (fd)
		close(fd--);
	openlog(applet_name, 0, LOG_DAEMON);
	logmode = LOGMODE_SYSLOG;

	/* main loop where we process all events and never exit */
	while (1) {
		fd_set rfds = G.readfds;
		struct timeval tv = { 15, 0 };
		int i;
		int tim = time(NULL);

		select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL);

		for (i = G.conncnt - 1; i >= 0; i--) {
			int s = i + FCS;

			if (FD_ISSET(s, &rfds)) {
				char *buf = conns[i].buf;
				unsigned len = conns[i].len;
				unsigned l;

				l = read(s, buf + len, sizeof(conns[0].buf) - len);
				if (l > 0) {
					if (checkInput(buf, len, l)) {
						reply(s, buf);
						goto deleteconn;
					} else if (len + l >= sizeof(conns[0].buf)) {
						replyError(s, "X-INVALID-REQUEST");
						goto deleteconn;
					} else {
						conns[i].len += l;
					}
				} else {
					goto deleteconn;
				}
				conns[i].lasttime = tim;
				continue;
deleteconn:
				deleteConn(s);
			} else {
				/* implement as time_after() in linux kernel sources ... */
				if (conns[i].lasttime + MAXIDLETIME <= tim) {
					replyError(s, "X-TIMEOUT");
					deleteConn(s);
				}
			}
		}

		if (FD_ISSET(0, &rfds)) {
			int s = accept(0, NULL, 0);

			if (s < 0) {
				if (errno != EINTR)
					bb_perror_msg("accept");
			} else {
				if (G.conncnt == MAXCONNS)
					i = closeOldest();
				else
					i = G.conncnt++;

				movefd(s, i + FCS); /* move if not already there */
				FD_SET(i + FCS, &G.readfds);
				conns[i].len = 0;
				conns[i].lasttime = time(NULL);
			}
		}
	} /* end of while (1) */

	return 0;
}
int main(int argc, char * argv[])
{
  uid_t nobody, nogrp;
  
  memset(conns, 0, sizeof conns);
  memset(&G, 0, sizeof G);
  FD_ZERO(&G.readfds);
  FD_SET(0, &G.readfds);
  
  if (argv[1])
  {
      if (argv[1][0] == '-')
      {
	  if (argv[1][1] == 'V')
	  {
	      printversion('.');
	      return 0;
	  }
	  else
	  {
	      fdprintf(2, "%s: invalid option -- %c\n", argv[0], argv[1][1]);
	      fdprintf(2, "Usage: %s [-V] " IU_IN_USAGESTR "\n", argv[0]);
	      return 1;
	  }
      }
      else
      {
	  SET_IU(argv[1], argc - 1);
      }
  }
  else
  {
      SET_IU(nobodystr, 1);
  }
  
  
#ifndef DEBUG
  close(1); /* not debugging, openlog() hopefully uses fd 1. */
#else
  close(3); /* debugging, TRACE uses fd 1, openlog() hopefully fd 3 */
#endif
  
  openlog("identd", LOG_CONS, LOG_DAEMON);
  
  {
      struct passwd * pw = getpwnam(nobodystr);
      
      if (pw)
      {
	  nobody = pw->pw_uid;
	  nogrp = pw->pw_gid;
      }
      else
      {
	  syslog(LOG_CRIT, "Cannot find user `nobody': %s", strerrno());
	  return -1;
      }
  }
  
  if (inetbind(getport()) < 0)
  {
      return -1;
  }
  
  /* */
  {
      int			 i;
      
      for (i = FCS; i < MAXCONNS + FCS; i++)
      {
	  close(i);
      }
  }
  
#ifdef DEBUG
#ifndef LOG_PERROR
#define LOG_PERROR 0
#endif
  openlog("identd", LOG_PERROR, LOG_DAEMON);
#else /* not DEBUG */
  godaemon();
  openlog("identd", 0, LOG_DAEMON);
  close(2);
  signal(SIGHUP, SIG_IGN);
#endif /* DEBUG */
  
  signal(SIGPIPE, SIG_IGN); /* connection closed when writing (raises ???) */
  
  writepid(nobody, nogrp);
  
  setegid(nogrp); setgid(nogrp); setuid(nobody); seteuid(nobody);
  
  {
      int i;
      
      for (i = 0; i < 4; i++)
      {
	  char *	id = (char)NULL;
	  unsigned int	rv = 0;
	  
	  switch (i)
	  {
	  case 0:
	    rv = (unsigned int)getegid();
	    id = "egid";
	    break;
	  case 1:
	    rv = (unsigned int)getgid();
	    id = "gid";
	    break;
	  case 2:
	    rv = (unsigned int)geteuid();
	    id = "euid";
	    break;
	  case 3:
	    rv = (unsigned int)getuid();
	    id = "uid";
	    break;
	  }
	  
	  if (rv == 0)
	  {
	      syslog(LOG_ERR,
		     "Can not drop all root privileges (%s) !!! %s !!!",
		     id, strerrno());
	      delpidfile();
	      return -1;
	  }
      }
  }
  
  while (2)
  {
      fd_set		rfds = G.readfds;
      struct timeval	tv = { 15, 0 };
      int		i;
      int		tim = time(NULL);
      
      TRACE(("calling select(): n = %d, rfds = 0x%x\n\n",
	     G.conncnt + FCS, *(int *)&rfds));
      
      select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL);
      
      for (i = G.conncnt - 1; i >= 0; i--)
      {
	  int s = i + FCS;
	  
	  if (FD_ISSET(s, &rfds))
	  {
	      char *		buf = conns[i].buf;
	      unsigned int	len = conns[i].len;
	      unsigned int	l;
	      
	      TRACE(("data socket fd_isset %d\n", s));
	      
	      if ((int)(l = read(s, buf + len, sizeof conns[0].buf - len)) > 0)
	      {
		  if (checkInput(buf, len, l))
		  {
		      reply(s, buf);
		      goto deleteconn;
		  }
		  else if (len + l >= sizeof conns[0].buf)
		  {
		      replyError(s, "X-INVALID-REQUEST");
		      goto deleteconn;
		  }
		  else
		  {
		      conns[i].len += l;
		  }
	      }
	      else
	      {
		  goto deleteconn;
	      }
	      
	      conns[i].lasttime = tim;
	      continue;
	      
	  deleteconn:
	      deleteConn(s);
	  }
	  else
	  {
	      /* implement as time_after() in linux kernel sources ... */
	      if (conns[i].lasttime + MAXIDLETIME <= tim)
	      {
		  replyError(s, "X-TIMEOUT");
		  deleteConn(s);
	      }
	  }
      }
      
      if (FD_ISSET(0, &rfds))
      {
	  int s = accept(0, NULL, 0);
	  
	  TRACE(("server socket fd_isset, %d accepted\n", s));
	  
	  if (s < 0)
	  {
	      if (errno != EINTR) /* EINTR */
	      {
		  syslog(LOG_ERR, "accept: %s", strerrno());
	      }
	  }
	  else
	  {
	      if (G.conncnt == MAXCONNS)
	      {
		  i = closeOldest();
	      }
	      else
	      {
		  i = G.conncnt++;
	      }
	      
	      if (s != i + FCS)
	      {
		  movesocket(s, i + FCS);
	      }
	      
	      FD_SET(i + FCS, &G.readfds);
	      
	      conns[i].len = 0;
	      conns[i].lasttime = time(NULL);
	  }
      }
  }
}