static void bb_acceptor_bind(struct bb_acceptor *acceptor) { int server = socket(acceptor->addr.in.sa_family, SOCK_STREAM, 0); if (server < 0) { bb_error_exit("socket()"); } int on = 1; if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int))) { bb_error_exit("setsockopt()"); } if (setsockopt(server, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(int))) { bb_error_exit("setsockopt()"); } if (bind(server, &acceptor->addr.in, sizeof(union bb_addr))) { bb_error_exit("unable to bind to address: bind()"); } if (listen(server, 100) < 0) { bb_error_exit("unable to put socket in listen mode: listen()"); } if (bb_nonblock(server)) { fprintf(stderr,"unable to put socket in non-blocking mode\n"); exit(1); } ev_io_init(&acceptor->acceptor, accept_callback, server, EV_READ); ev_io_start(blastbeat.loop, &acceptor->acceptor); struct bb_virtualhost *vhost = acceptor->vhosts; while(vhost) { vhost->pinger.vhost = vhost; ev_timer_init(&vhost->pinger.pinger, pinger_cb, blastbeat.ping_freq, blastbeat.ping_freq); ev_timer_start(blastbeat.loop, &vhost->pinger.pinger); vhost = vhost->next; } }
static void drop_privileges() { if (getuid() != 0) goto print; // setgid struct group *grp = getgrnam(blastbeat.gid); if (grp) { if (setgid(grp->gr_gid)) { bb_error_exit("unable to drop privileges: setgid()"); } } else { if (setgid((gid_t)atoi(blastbeat.gid))) { bb_error_exit("unable to drop privileges: setgid()"); } } // setuid struct passwd *pwd = getpwnam(blastbeat.uid); if (pwd) { if (setuid(pwd->pw_uid)) { bb_error_exit("unable to drop privileges: setuid()"); } } else { if (setuid((uid_t)atoi(blastbeat.uid))) { bb_error_exit("unable to drop privileges: setuid()"); } } print: fprintf(stdout,"\nuid: %d\n", (int) getuid()); fprintf(stdout,"gid: %d\n", (int) getgid()); };
int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "syntax: blastbeat <configfile>\n"); exit(1); } signal(SIGPIPE, SIG_IGN); // set default values blastbeat.ping_freq = 3.0; blastbeat.sht_size = 65536; blastbeat.uid = "nobody"; blastbeat.gid = "nogroup"; blastbeat.max_hops = 10; bb_ini_config(argv[1]); // validate config if (!blastbeat.acceptors) { fprintf(stderr, "config error: please specify at least one 'bind' directive\n"); exit(1); } // fix acceptors/vhosts bb_acceptors_fix(); struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl)) { bb_error_exit("unable to get the maximum file descriptors number: getrlimit()"); } blastbeat.max_fd = rl.rlim_cur; blastbeat.sht = malloc(sizeof(struct bb_session_entry) * blastbeat.sht_size); if (!blastbeat.sht) { bb_error_exit("unable to allocate sessions hashtable: malloc()"); } memset(blastbeat.sht, 0, sizeof(struct bb_session_entry) * blastbeat.sht_size); blastbeat.loop = EV_DEFAULT; // report config, bind sockets and assign ssl keys/certificates struct bb_acceptor *acceptor = blastbeat.acceptors; fprintf(stdout,"*** starting BlastBeat ***\n"); while(acceptor) { fprintf(stdout, "\n[acceptor %s]\n", acceptor->name); bb_acceptor_bind(acceptor); struct bb_virtualhost *vhost = acceptor->vhosts; while(vhost) { fprintf(stdout, "%s\n", vhost->name); bb_assign_ssl(acceptor, vhost); vhost = vhost->next; } acceptor = acceptor->next; } void *context = zmq_init (1); blastbeat.router = zmq_socket(context, ZMQ_ROUTER); if (zmq_bind(blastbeat.router, blastbeat.zmq)) { bb_error_exit("unable to bind to zmq socket: zmq_bind()"); } size_t opt_len = sizeof(int); if (zmq_getsockopt(blastbeat.router, ZMQ_FD, &blastbeat.zmq_fd, &opt_len)) { bb_error_exit("unable to configure zmq socket: zmq_getsockopt()"); } drop_privileges(); ev_io_init(&blastbeat.event_zmq, bb_zmq_receiver, blastbeat.zmq_fd, EV_READ); ev_io_start(blastbeat.loop, &blastbeat.event_zmq); fprintf(stdout,"\n*** BlastBeat is ready ***\n"); ev_loop(blastbeat.loop, 0); return 0; }