void debug(int level, char *format, ...) { va_list ap; va_start(ap, format); if (_loghost != NULL) vsyslog(sysloglevel(level), format, ap); else if (level > FLIDEBUG_NONE && level <= _loglevel) { fprintf(stderr, LOGPREFIX ": "); vfprintf(stderr, format, ap); fprintf(stderr, "\n"); } va_end(ap); return; }
void setdebuglevel(char *host, long level) { _loghost = host; _loglevel = level; if (level == FLIDEBUG_NONE) { debugclose(); _logopen = 0; return; } if (!_logopen) { debugopen(host); _logopen = 1; } if (host != NULL) setlogmask(LOG_UPTO(sysloglevel(level))); return; }
int main( int ac, char *av[] ) { struct sigaction sa, osahup, osachld; struct sockaddr_in sin; struct servent *se; SNET *pushersn = NULL; int c, s, err = 0, fd; socklen_t sinlen; int dontrun = 0, fds[ 2 ]; int reuseaddr = 1, status; pid_t pid; char *prog; int facility = _COSIGN_LOG; int level = LOG_INFO; int fg = 0; extern int optind; extern char *optarg; if (( prog = strrchr( av[ 0 ], '/' )) == NULL ) { prog = av[ 0 ]; } else { prog++; } #define COSIGN_OPTS "b:c:dD:F:fg:h:i:L:np:VXx:y:z:" while (( c = getopt( ac, av, COSIGN_OPTS )) != -1 ) { switch ( c ) { case 'c' : /* config file */ cosign_conf = optarg; break; default : break; } } if ( cosign_config( cosign_conf ) < 0 ) { exit( 1 ); } daemon_configure(); /* reset optind to parse all other args */ optind = 1; while (( c = getopt( ac, av, COSIGN_OPTS )) != -1 ) { switch ( c ) { case 'b' : /* listen backlog */ backlog = atoi( optarg ); break; case 'c' : /* already have conf file */ break; case 'd' : /* debug */ debug = 1; break; case 'D' : /* directory to store cookies*/ cosign_dir = optarg; break; case 'F' : /* syslog facility */ if (( facility = syslogfacility( optarg )) == -1 ) { fprintf( stderr, "%s: %s: unknown syslog facility\n", prog, optarg ); exit( 1 ); } break; case 'f' : /* run in foreground */ fg = 1; break; case 'g' : /* grey window for logouts/replication */ grey_time = atoi( optarg ); break; case 'h' : /* host to replicate to*/ replhost = optarg; break; case 'i' : /* idle timeout in seconds */ idle_out_time = atoi( optarg ); break; case 'L' : /* syslog level */ if (( level = sysloglevel( optarg )) == -1 ) { fprintf( stderr, "%s: %s: unknown syslog level\n", prog, optarg ); exit( 1 ); } break; case 'n' : /* don't run, just syntax check */ dontrun = 1; break; case 'p' : /* TCP port */ cosign_port = htons( atoi( optarg )); break; case 'V' : /* version */ printf( "%s\n", cosign_version ); exit( 0 ); case 'X' : /* no required tls/ssl for debugging */ tlsopt = 1; break; case 'x' : /* ca dir */ cadir = optarg; break; case 'y' : /* cert */ certfile = optarg; break; case 'z' : /* private key file */ cryptofile = optarg; break; default : err++; } } if ( err || optind != ac ) { fprintf( stderr, "Usage: cosignd [ -dV ] [ -b backlog ] "); fprintf( stderr, "[ -c conf-file ] [ -D database-dir ] " ); fprintf( stderr, "[ -F syslog-facility] " ); fprintf( stderr, "[ -g greywindowinsecs ] [ -h replication_host] " ); fprintf( stderr, "[ -i idletimeinsecs] [ -L syslog-level] " ); fprintf( stderr, "[ -p port ] [ -x ca dir ] " ); fprintf( stderr, "[ -y cert file] [ -z private key file ]\n" ); exit( 1 ); } SSL_load_error_strings(); SSL_library_init(); if ( cosign_ssl( cryptofile, certfile, cadir, &ctx ) != 0 ) { fprintf( stderr, "cosignd: ssl setup error.\n" ); exit( 1 ); } if ( dontrun ) { exit( 0 ); } if ( cosign_port == 0 ) { if (( se = getservbyname( "cosign", "tcp" )) == NULL ) { fprintf( stderr, "%s: can't find cosign service\n" "%s: continuing...\n", prog, prog ); cosign_port = htons( 6663 ); } else { cosign_port = se->s_port; } } /* * Set up listener. */ if (( s = socket( PF_INET, SOCK_STREAM, 0 )) < 0 ) { perror( "socket" ); exit( 1 ); } if ( reuseaddr ) { if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (void*)&reuseaddr, sizeof( int )) < 0 ) { perror("setsockopt"); } } memset( &sin, 0, sizeof( struct sockaddr_in )); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = cosign_port; if ( bind( s, (struct sockaddr *)&sin, sizeof( struct sockaddr_in )) < 0 ) { perror( "bind" ); exit( 1 ); } if ( listen( s, backlog ) < 0 ) { perror( "listen" ); exit( 1 ); } if ( chdir( cosign_dir ) < 0 ) { perror( cosign_dir ); exit( 1 ); } if ( replhost != NULL ) { if ( pusherhosts( ) != 0 ) { fprintf( stderr, "unhappy with lookup of %s\n", replhost ); exit( 1 ); } } /* * Disassociate from controlling tty. */ if ( !fg && !debug ) { int i, dt; switch ( fork()) { case 0 : if ( setsid() < 0 ) { perror( "setsid" ); exit( 1 ); } if (( fd = open( "/", O_RDONLY, 0 )) < 0 ) { perror( "open" ); exit( 1 ); } dt = getdtablesize(); for ( i = 0; i < dt; i++ ) { if (( i != s ) && ( i != fd )) { /* keep socket open */ (void)close( i ); } } (void)dup2( fd, 0 ); (void)dup2( fd, 1 ); (void)dup2( fd, 2 ); (void)close( fd ); break; case -1 : perror( "fork" ); exit( 1 ); default : exit( 0 ); } } /* * Start logging. */ openlog( prog, LOG_NDELAY|LOG_NOWAIT|LOG_PID, facility ); setlogmask( LOG_UPTO( level )); syslog( LOG_INFO, "restart %s", cosign_version ); if ( replhost != NULL ) { if ( pipe( fds ) < 0 ) { syslog( LOG_ERR, "pusher pipe: %m" ); exit( 1 ); } switch ( pusherpid = fork()) { case 0 : if ( close( fds[ 1 ] ) != 0 ) { syslog( LOG_ERR, "pusher parent pipe: %m" ); exit( 1 ); } pusherparent( fds[ 0 ] ); exit( 0 ); case -1 : syslog( LOG_ERR, "pusher fork: %m" ); exit( 1 ); default : if ( close( fds[ 0 ] ) != 0 ) { syslog( LOG_ERR, "pusher main pipe: %m" ); exit( 1 ); } if (( pushersn = snet_attach( fds[ 1 ], 1024 * 1024 ) ) == NULL ) { syslog( LOG_ERR, "pusherfork: snet_attach failed\n" ); exit( 1 ); } break; } } /* catch SIGHUP */ memset( &sa, 0, sizeof( struct sigaction )); sa.sa_handler = hup; if ( sigaction( SIGHUP, &sa, &osahup ) < 0 ) { syslog( LOG_ERR, "sigaction: %m" ); exit( 1 ); } /* catch SIGCHLD */ memset( &sa, 0, sizeof( struct sigaction )); sa.sa_handler = chld; if ( sigaction( SIGCHLD, &sa, &osachld ) < 0 ) { syslog( LOG_ERR, "sigaction: %m" ); exit( 1 ); } /* * Begin accepting connections. */ for (;;) { /* ssl stuff here later, but for now this is HUP */ if ( reconfig > 0 ) { reconfig = 0; syslog( LOG_DEBUG, "reload cosign_config %s", cosign_version ); if ( cosign_config( cosign_conf ) < 0 ) { syslog( LOG_ERR, "%s: re-read failed, continuing with" " old config", cosign_conf ); } /* XXX need to reprocess command line args here */ syslog( LOG_DEBUG, "reload cosign_ssl %s", cosign_version ); if ( cosign_ssl( cryptofile, certfile, cadir, &ctx ) != 0 ) { syslog( LOG_ERR, "%s: ssl re-config failed, continuing with" " old ssl config", cosign_conf ); } syslog( LOG_DEBUG, "reload kill %s", cosign_version ); if (pusherpid) { if ( kill( pusherpid, SIGHUP ) < 0 ) { syslog( LOG_CRIT, "kill pusherpid: %m" ); exit( 1 ); } } syslog( LOG_INFO, "reload %s", cosign_version ); } if ( child_signal > 0 ) { child_signal = 0; while (( pid = waitpid( 0, &status, WNOHANG )) > 0 ) { if ( WIFEXITED( status )) { if ( WEXITSTATUS( status )) { syslog( LOG_ERR, "child %d exited with %d", pid, WEXITSTATUS( status )); } } else if ( WIFSIGNALED( status )) { syslog( LOG_ERR, "child %d died on signal %d", pid, WTERMSIG( status )); } else { syslog( LOG_ERR, "child %d died", pid ); } if ( pid == pusherpid ) { syslog( LOG_CRIT, "pusherpid %d died!", pusherpid ); exit( 1 ); } } if ( pid < 0 && errno != ECHILD ) { syslog( LOG_ERR, "wait3: %m" ); exit( 1 ); } } sinlen = sizeof( struct sockaddr_in ); if (( fd = accept( s, (struct sockaddr *)&cosign_sin, &sinlen )) < 0 ) { if ( errno != EINTR ) { syslog( LOG_ERR, "accept: %m" ); } continue; } /* start child */ switch ( c = fork()) { case 0 : syslog( LOG_INFO, "connect: %s", inet_ntoa( cosign_sin.sin_addr )); (void)close( s ); /* reset CHLD and HUP */ if ( sigaction( SIGCHLD, &osachld, 0 ) < 0 ) { syslog( LOG_ERR, "sigaction: %m" ); exit( 1 ); } if ( sigaction( SIGHUP, &osahup, 0 ) < 0 ) { syslog( LOG_ERR, "sigaction: %m" ); exit( 1 ); } exit( command( fd, pushersn )); case -1 : close( fd ); syslog( LOG_ERR, "fork: %m" ); break; default : close( fd ); break; } } }