#ifndef LINT static char *rcsid="$Id: whosond.c,v 1.24 2003/08/14 12:50:35 crosser Exp $"; #endif /* $Log: whosond.c,v $ Revision 1.24 2003/08/14 12:50:35 crosser Memory leak in the client code (ilya@glas.net) Changes to recent autoconf/automake (woods@weird.com) use pidfile() if it exists (woods@weird.com) Revision 1.23 2001/09/23 13:29:17 crosser change gid to uid in setreuid Revision 1.22 2001/09/21 21:31:38 crosser even more paranoia added Revision 1.21 2001/09/21 06:15:56 crosser more cleanup in revoking privileges, warnings in configure, version change Revision 1.20 2001/09/20 21:24:28 crosser Some cleanup of security measures Revision 1.19 2001/09/20 06:09:36 crosser clear suppliementary groups in whosond Revision 1.18 2001/09/20 05:56:39 crosser chroot() for whosond Revision 1.17 1999/12/28 13:25:34 crosser check for setreuid; added getopt to cvs Revision 1.16 1999/11/26 17:18:57 crosser tune for sunos4 Revision 1.15 1999/10/06 11:19:52 crosser Handle SIGPIPE in the server Fix (kludge) for private fields in the config struct Make beta3 version Revision 1.14 1999/07/27 17:17:18 crosser remove include version.h Revision 1.13 1998/07/28 17:51:53 crosser make 64bit architecure happy Revision 1.12 1998/07/05 00:26:18 crosser Change copyright Revision 1.11 1998/07/05 00:01:27 crosser add user and group set Revision 1.10 1998/07/03 09:32:48 crosser autoconf for signal and detach Revision 1.9 1998/07/02 18:17:12 crosser fix proc. of -v option Revision 1.8 1998/07/02 18:01:15 crosser change error reporting to syslog Revision 1.7 1998/07/01 21:55:16 crosser cosmetics Revision 1.6 1998/07/01 13:39:18 crosser make it work on Solaris Revision 1.5 1998/07/01 05:18:09 crosser minor warnings fix Revision 1.4 1998/07/01 05:01:22 crosser Big reorganization */ /* WHAT IS IT: Implementation of experimental "whoson" protocol AUTHOR: Eugene G. Crosser COPYRIGHT: Public domain */ #include "config.h" #include #include #ifdef HAVE_SYS_SELECT_H #include #endif #include #include #include #include #include #include #ifndef OPTARG_DEFINED #include #endif #include "whosond.h" #include "serv_common.h" #include "rtconfig.h" #include "report.h" int wso_verbose=0; static void showver(char *name) { fprintf(stderr,"%s Version %s Build %s\n",name,VERSION,__DATE__); } static void showhelp(char *name) { fprintf(stderr,"Usage: %s -I configfile -V -v -h\n",name); fprintf(stderr,"\t-I configfile\t- replacement config [default: %s]\n",DEFAULT_CONFIG); fprintf(stderr,"\t-d\t\t- do not go to background\n"); fprintf(stderr,"\t-V\t\t- print version\n"); fprintf(stderr,"\t-v\t\t- increase verbosity\n"); fprintf(stderr,"\t-h\t\t- print this help message\n"); } int main(int argc, char *argv[]) { struct _evdesc (*evvec[FD_SETSIZE]) (int fd, void *priv); void *priv[FD_SETSIZE]; struct _evdesc evdesc; struct _servdesc *servdesc; int i; char *configfile=DEFAULT_CONFIG; int daemon=1; while ((i=getopt(argc,argv,"I:dvVh")) != EOF) switch (i) { case 'I': /* if someone decides to modify the name displayed in the "ps" output it may be useful to copy the arg... */ configfile=(char *)malloc(strlen(optarg)+1); strcpy(configfile,optarg); break; case 'd': daemon=0; break; case 'V': showver(argv[0]); return 0; case 'v': wso_verbose++; break; case 'h': showhelp(argv[0]); return 0; default: showhelp(argv[0]); return 1; } if (daemon) { int child; if ((child=fork()) > 0) { sleep(1); return 0; } else if (child < 0) { ERRLOG((LOG_ERR,"fork error: %m")) return 1; } else { fflush(stdin); fflush(stdout); fflush(stderr); setbuf(stdin,NULL); setbuf(stdout,NULL); setbuf(stderr,NULL); close(0); close(1); close(2); open("/dev/null",O_RDWR); dup(0); dup(0); #ifdef HAVE_SETSID setsid(); #else #ifdef HAVE_SETPGRP #ifdef SETPGRP_VOID setpgrp(); #else setpgrp(0,0); #endif #endif #endif #ifdef HAVE_PIDFILE pidfile((char *) NULL); #endif } } #ifdef HAVE_SYSLOG tzset(); /* will not work automatically from chrooted environment */ openlog("whosond",LOG_CONS|LOG_PID #ifdef LOG_NDELAY |LOG_NDELAY #endif ,LOG_DAEMON); #endif for (i=0;inext) { evdesc=(servdesc->root.init)(servdesc->priv); if (evdesc.fd >= 0) { evvec[evdesc.fd]=evdesc.evproc; priv[evdesc.fd]=evdesc.priv; i++; } } if (i == 0) { ERRLOG((LOG_ERR,"No initialized servers\n")) return 1; } if (newroot) { #ifdef HAVE_CHROOT if (chdir(newroot) == 0) { if (chroot(newroot)) { ERRLOG((LOG_ERR,"chroot(%s): %m\n",newroot)) return 1; } } else { ERRLOG((LOG_ERR,"chdir(%s): %m\n",newroot)) return 1; } #else ERRLOG((LOG_ERR,"function chroot() not present,\n")) ERRLOG((LOG_ERR,"remove it from the config file\n")) return 1; #endif } if (rungid) { #ifdef HAVE_SETGROUPS /* Solar Designer says (quoting DJB) that there are systems where you cannot set null list of supplementary groups, and also there are systems where gid_t is short but setgroups accepts array of int-s. Weird. BTW I suspect that we may run into SIGBUS in the latter case... */ gid_t groups[2]; groups[0]=groups[1]=rungid; if (setgroups(1,groups) == -1) { ERRLOG((LOG_ERR,"setgroups() failed: %m\n")) return 1; } #endif #ifdef HAVE_SETREUID setregid(rungid,rungid); #else setegid(rungid); setgid(rungid); #endif } if (runuid) { #ifdef HAVE_SETREUID setreuid(runuid,runuid); #else seteuid(runuid); setuid(runuid); #endif } /* In case the client disconnects before reading our responce */ (void)signal(SIGPIPE,SIG_IGN); /* is this setting saved after raising the signal on SysV? User signal handlers are reset to SIG_DFL. Let us hope that SIG_IGN is a special setting and is kept forever. */ mainloop(evvec,priv); return 0; }