int cfg_value(const char* filename, const char* header, const char* name, char* value, void* data) { config_ctx* ctx = (config_ctx*)data; ASSERT(filename); ASSERT(ctx); /* A little setup where necessary */ if(!ctx->confname) ctx->confname = filename; /* Called like this after each file */ if(!header) { config_done(ctx); ctx->confname = NULL; return 0; } ASSERT(ctx->confname); ASSERT(name && value && header); log_debug("config: %s: [%s] %s = %s", ctx->confname, header, name, value); config_value(header, name, value, ctx); return 0; }
pid_t ca(void) { pid_t pid; struct passwd *pw; struct event ev_sigint; struct event ev_sigterm; switch (pid = fork()) { case -1: fatal("ca: cannot fork"); case 0: post_fork(PROC_CA); break; default: return (pid); } purge_config(PURGE_LISTENERS|PURGE_TABLES|PURGE_RULES); if ((pw = getpwnam(SMTPD_USER)) == NULL) fatalx("unknown user " SMTPD_USER); if (chroot(PATH_CHROOT) == -1) fatal("ca: chroot"); if (chdir("/") == -1) fatal("ca: chdir(\"/\")"); config_process(PROC_CA); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("ca: cannot drop privileges"); imsg_callback = ca_imsg; event_init(); signal_set(&ev_sigint, SIGINT, ca_sig_handler, NULL); signal_set(&ev_sigterm, SIGTERM, ca_sig_handler, NULL); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); config_peer(PROC_CONTROL); config_peer(PROC_PARENT); config_peer(PROC_PONY); config_done(); /* Ignore them until we get our config */ mproc_disable(p_pony); if (event_dispatch() < 0) fatal("event_dispatch"); ca_shutdown(); return (0); }
/* a backdoor for the console driver */ static int gdc_configure(int flags) { probe_adapters(); biosadapter[0].va_flags |= V_ADP_INITIALIZED; if (!config_done(&biosadapter[0])) { if (vid_register(&biosadapter[0]) < 0) return 1; biosadapter[0].va_flags |= V_ADP_REGISTERED; } return 1; }
pid_t queue(void) { pid_t pid; struct passwd *pw; struct timeval tv; struct event ev_qload; struct event ev_sigint; struct event ev_sigterm; switch (pid = fork()) { case -1: fatal("queue: cannot fork"); case 0: post_fork(PROC_QUEUE); break; default: return (pid); } purge_config(PURGE_EVERYTHING); if ((pw = getpwnam(SMTPD_QUEUE_USER)) == NULL) if ((pw = getpwnam(SMTPD_USER)) == NULL) fatalx("unknown user " SMTPD_USER); env->sc_queue_flags |= QUEUE_EVPCACHE; env->sc_queue_evpcache_size = 1024; if (chroot(PATH_SPOOL) == -1) fatal("queue: chroot"); if (chdir("/") == -1) fatal("queue: chdir(\"/\")"); config_process(PROC_QUEUE); if (env->sc_queue_flags & QUEUE_COMPRESSION) log_info("queue: queue compression enabled"); if (env->sc_queue_key) { if (! crypto_setup(env->sc_queue_key, strlen(env->sc_queue_key))) fatalx("crypto_setup: invalid key for queue encryption"); log_info("queue: queue encryption enabled"); } if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("queue: cannot drop privileges"); imsg_callback = queue_imsg; event_init(); signal_set(&ev_sigint, SIGINT, queue_sig_handler, NULL); signal_set(&ev_sigterm, SIGTERM, queue_sig_handler, NULL); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); config_peer(PROC_PARENT); config_peer(PROC_CONTROL); config_peer(PROC_LKA); config_peer(PROC_SCHEDULER); config_peer(PROC_PONY); config_done(); /* setup queue loading task */ evtimer_set(&ev_qload, queue_timeout, &ev_qload); tv.tv_sec = 0; tv.tv_usec = 10; evtimer_add(&ev_qload, &tv); if (event_dispatch() < 0) fatal("event_dispatch"); queue_shutdown(); return (0); }
pid_t control(void) { pid_t pid; struct passwd *pw; struct event ev_sigint; struct event ev_sigterm; switch (pid = fork()) { case -1: fatal("control: cannot fork"); case 0: post_fork(PROC_CONTROL); break; default: return (pid); } purge_config(PURGE_EVERYTHING); if ((pw = getpwnam(SMTPD_USER)) == NULL) fatalx("unknown user " SMTPD_USER); stat_backend = env->sc_stat; stat_backend->init(); if (chroot(PATH_CHROOT) == -1) fatal("control: chroot"); if (chdir("/") == -1) fatal("control: chdir(\"/\")"); config_process(PROC_CONTROL); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("control: cannot drop privileges"); imsg_callback = control_imsg; event_init(); signal_set(&ev_sigint, SIGINT, control_sig_handler, NULL); signal_set(&ev_sigterm, SIGTERM, control_sig_handler, NULL); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); tree_init(&ctl_conns); tree_init(&ctl_count); memset(&digest, 0, sizeof digest); digest.startup = time(NULL); config_peer(PROC_SCHEDULER); config_peer(PROC_QUEUE); config_peer(PROC_PARENT); config_peer(PROC_LKA); config_peer(PROC_PONY); config_peer(PROC_CA); config_done(); control_listen(); if (event_dispatch() < 0) fatal("event_dispatch"); control_shutdown(); return (0); }
pid_t lka(void) { pid_t pid; struct passwd *pw; struct event ev_sigint; struct event ev_sigterm; struct event ev_sigchld; switch (pid = fork()) { case -1: fatal("lka: cannot fork"); case 0: break; default: return (pid); } purge_config(PURGE_EVERYTHING); if ((pw = getpwnam(SMTPD_USER)) == NULL) fatalx("unknown user " SMTPD_USER); config_process(PROC_LKA); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("lka: cannot drop privileges"); imsg_callback = lka_imsg; event_init(); signal_set(&ev_sigint, SIGINT, lka_sig_handler, NULL); signal_set(&ev_sigterm, SIGTERM, lka_sig_handler, NULL); signal_set(&ev_sigchld, SIGCHLD, lka_sig_handler, NULL); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal_add(&ev_sigchld, NULL); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); /* * lka opens all kinds of files and sockets, so bump the limit to max. * XXX: need to analyse the exact hard limit. */ fdlimit(1.0); config_peer(PROC_PARENT); config_peer(PROC_QUEUE); config_peer(PROC_SMTP); config_peer(PROC_MDA); config_peer(PROC_MTA); config_peer(PROC_CONTROL); config_done(); /* Ignore them until we get our config */ mproc_disable(p_mda); mproc_disable(p_mta); mproc_disable(p_smtp); if (event_dispatch() < 0) fatal("event_dispatch"); lka_shutdown(); return (0); }
pid_t pony(void) { pid_t pid; struct passwd *pw; struct event ev_sigint; struct event ev_sigterm; switch (pid = fork()) { case -1: fatal("pony: cannot fork"); case 0: post_fork(PROC_PONY); break; default: return (pid); } mda_postfork(); mta_postfork(); smtp_postfork(); filter_postfork(); /* do not purge listeners and pki, they are purged * in smtp_configure() */ purge_config(PURGE_TABLES|PURGE_RULES); if ((pw = getpwnam(SMTPD_USER)) == NULL) fatalx("unknown user " SMTPD_USER); if (chroot(PATH_CHROOT) == -1) fatal("pony: chroot"); if (chdir("/") == -1) fatal("pony: chdir(\"/\")"); config_process(PROC_PONY); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("pony: cannot drop privileges"); imsg_callback = pony_imsg; event_init(); mda_postprivdrop(); mta_postprivdrop(); smtp_postprivdrop(); signal_set(&ev_sigint, SIGINT, pony_sig_handler, NULL); signal_set(&ev_sigterm, SIGTERM, pony_sig_handler, NULL); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); config_peer(PROC_PARENT); config_peer(PROC_QUEUE); config_peer(PROC_LKA); config_peer(PROC_CONTROL); config_peer(PROC_CA); config_done(); ca_engine_init(); if (event_dispatch() < 0) fatal("event_dispatch"); pony_shutdown(); return (0); }
pid_t mfa(void) { pid_t pid; struct passwd *pw; struct event ev_sigint; struct event ev_sigterm; struct event ev_sigchld; switch (pid = fork()) { case -1: fatal("filter: cannot fork"); case 0: break; default: return (pid); } mfa_filter_prepare(); purge_config(PURGE_EVERYTHING); if ((pw = getpwnam(SMTPD_USER)) == NULL) fatalx("unknown user " SMTPD_USER); config_process(PROC_MFA); if (chroot(PATH_CHROOT) == -1) fatal("scheduler: chroot"); if (chdir("/") == -1) fatal("scheduler: chdir(\"/\")"); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("filter: cannot drop privileges"); imsg_callback = mfa_imsg; event_init(); signal_set(&ev_sigint, SIGINT, mfa_sig_handler, NULL); signal_set(&ev_sigterm, SIGTERM, mfa_sig_handler, NULL); signal_set(&ev_sigchld, SIGCHLD, mfa_sig_handler, NULL); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal_add(&ev_sigchld, NULL); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); config_peer(PROC_PARENT); config_peer(PROC_SMTP); config_peer(PROC_CONTROL); config_done(); mproc_disable(p_smtp); if (event_dispatch() < 0) fatal("event_dispatch"); mfa_shutdown(); return (0); }
pid_t control(void) { struct sockaddr_un sun; int fd; mode_t old_umask; pid_t pid; struct passwd *pw; struct event ev_sigint; struct event ev_sigterm; switch (pid = fork()) { case -1: fatal("control: cannot fork"); case 0: break; default: return (pid); } purge_config(PURGE_EVERYTHING); pw = env->sc_pw; if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) fatal("control: socket"); bzero(&sun, sizeof(sun)); sun.sun_family = AF_UNIX; if (strlcpy(sun.sun_path, SMTPD_SOCKET, sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) fatal("control: socket name too long"); if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == 0) fatalx("control socket already listening"); if (unlink(SMTPD_SOCKET) == -1) if (errno != ENOENT) fatal("control: cannot unlink socket"); old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH); if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { (void)umask(old_umask); fatal("control: bind"); } (void)umask(old_umask); if (chmod(SMTPD_SOCKET, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) == -1) { (void)unlink(SMTPD_SOCKET); fatal("control: chmod"); } session_socket_blockmode(fd, BM_NONBLOCK); control_state.fd = fd; stat_backend = env->sc_stat; stat_backend->init(); if (chroot(PATH_CHROOT) == -1) fatal("control: chroot"); if (chdir("/") == -1) fatal("control: chdir(\"/\")"); config_process(PROC_CONTROL); if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("control: cannot drop privileges"); imsg_callback = control_imsg; event_init(); signal_set(&ev_sigint, SIGINT, control_sig_handler, NULL); signal_set(&ev_sigterm, SIGTERM, control_sig_handler, NULL); signal_add(&ev_sigint, NULL); signal_add(&ev_sigterm, NULL); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); tree_init(&ctl_conns); bzero(&digest, sizeof digest); digest.startup = time(NULL); config_peer(PROC_SCHEDULER); config_peer(PROC_QUEUE); config_peer(PROC_SMTP); config_peer(PROC_MFA); config_peer(PROC_PARENT); config_peer(PROC_LKA); config_peer(PROC_MDA); config_peer(PROC_MTA); config_done(); control_listen(); if (event_dispatch() < 0) fatal("event_dispatch"); control_shutdown(); return (0); }