예제 #1
0
static void
filter_api_init(void)
{
	extern const char *__progname;
	struct passwd  *pw;
	static int	init = 0;

	if (init)
		return;

	init = 1;

	pw = getpwnam(SMTPD_USER);
	if (pw == NULL)
		err(1, "getpwnam");

	smtpd_process = PROC_FILTER;
	filter_name = __progname;

	tree_init(&queries);
	event_init();

	bzero(&fi, sizeof(fi));
	fi.p.proc = PROC_MFA;
	fi.p.name = "filter";
	fi.p.handler = filter_dispatch;
	fi.uid = pw->pw_uid;
	fi.gid = pw->pw_gid;
	fi.rootpath = PATH_CHROOT;
	
	mproc_init(&fi.p, 0);
}
예제 #2
0
파일: config.c 프로젝트: gunhu/OpenSMTPD
void
config_peer(enum smtp_proc_type proc)
{
    struct mproc	*p;

    if (proc == smtpd_process)
        fatal("config_peers: cannot peer with oneself");

    p = xcalloc(1, sizeof *p, "config_peer");
    p->proc = proc;
    p->name = xstrdup(proc_name(proc), "config_peer");
    p->handler = imsg_dispatch;

    mproc_init(p, pipes[smtpd_process][proc]);
    mproc_enable(p);
    pipes[smtpd_process][proc] = -1;

    if (proc == PROC_CONTROL)
        p_control = p;
    else if (proc == PROC_LKA)
        p_lka = p;
    else if (proc == PROC_PARENT)
        p_parent = p;
    else if (proc == PROC_QUEUE)
        p_queue = p;
    else if (proc == PROC_SCHEDULER)
        p_scheduler = p;
    else if (proc == PROC_PONY)
        p_pony = p;
    else if (proc == PROC_CA)
        p_ca = p;
    else
        fatalx("bad peer");
}
예제 #3
0
파일: mproc.c 프로젝트: OpenSMTPD/OpenSMTPD
int
mproc_fork(struct mproc *p, const char *path, char *argv[])
{
	int sp[2];

	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) < 0)
		return (-1);

	io_set_nonblocking(sp[0]);
	io_set_nonblocking(sp[1]);

	if ((p->pid = fork()) == -1)
		goto err;

	if (p->pid == 0) {
		/* child process */
		dup2(sp[0], STDIN_FILENO);
		if (closefrom(STDERR_FILENO + 1) < 0)
			exit(1);

		execv(path, argv);
		err(1, "execv: %s", path);
	}

	/* parent process */
	close(sp[0]);
	mproc_init(p, sp[1]);
	return (0);

err:
	log_warn("warn: Failed to start process %s, instance of %s", argv[0], path);
	close(sp[0]);
	close(sp[1]);
	return (-1);
}
예제 #4
0
파일: control.c 프로젝트: mmitton/OpenSMTPD
/* ARGSUSED */
static void
control_accept(int listenfd, short event, void *arg)
{
	int			 connfd;
	socklen_t		 len;
	struct sockaddr_un	 sun;
	struct ctl_conn		*c;

	if (getdtablesize() - getdtablecount() < CONTROL_FD_RESERVE)
		goto pause;

	len = sizeof(sun);
	if ((connfd = accept(listenfd, (struct sockaddr *)&sun, &len)) == -1) {
		if (errno == ENFILE || errno == EMFILE)
			goto pause;
		if (errno == EINTR || errno == EWOULDBLOCK ||
		    errno == ECONNABORTED)
			return;
		fatal("control_accept: accept");
	}

	session_socket_blockmode(connfd, BM_NONBLOCK);

	c = xcalloc(1, sizeof(*c), "control_accept");
	if (getpeereid(connfd, &c->euid, &c->egid) == -1)
		fatal("getpeereid");
	c->id = ++connid;
	c->mproc.proc = PROC_CLIENT;
	c->mproc.handler = control_dispatch_ext;
	c->mproc.data = c;
	mproc_init(&c->mproc, connfd);
	mproc_enable(&c->mproc);
	tree_xset(&ctl_conns, c->id, c);

	stat_backend->increment("control.session", 1);
	return;

pause:
	log_warnx("warn: ctl client limit hit, disabling new connections");
	event_del(&control_state.ev);
}
예제 #5
0
static void
filter_api_init(void)
{
	extern const char *__progname;
	struct passwd  *pw;
	static int	init = 0;

	if (init)
		return;

	init = 1;

	log_init(-1);
	log_verbose(1);

	pw = getpwnam(SMTPD_USER);
	if (pw == NULL) {
		log_warn("warn: filter-api:%s getpwnam", filter_name);
		fatalx("filter-api: exiting");
	}

	smtpd_process = PROC_FILTER;
	filter_name = __progname;

	tree_init(&queries);
	tree_init(&sessions);
	event_init();

	memset(&fi, 0, sizeof(fi));
	fi.p.proc = PROC_PONY;
	fi.p.name = "filter";
	fi.p.handler = filter_dispatch;
	fi.uid = pw->pw_uid;
	fi.gid = pw->pw_gid;
	fi.rootpath = PATH_CHROOT;

	/* XXX just for now */
	fi.hooks = ~0;

	mproc_init(&fi.p, 0);
}
예제 #6
0
/* ARGSUSED */
static void
control_accept(int listenfd, short event, void *arg)
{
	int			 connfd;
	socklen_t		 len;
	struct sockaddr_un	 s_un;
	struct ctl_conn		*c;
	size_t			*count;
	uid_t			 euid;
	gid_t			 egid;

	if (getdtablesize() - getdtablecount() < CONTROL_FD_RESERVE)
		goto pause;

	len = sizeof(s_un);
	if ((connfd = accept(listenfd, (struct sockaddr *)&s_un, &len)) == -1) {
		if (errno == ENFILE || errno == EMFILE)
			goto pause;
		if (errno == EINTR || errno == EWOULDBLOCK ||
		    errno == ECONNABORTED)
			return;
		fatal("control_accept: accept");
	}

	io_set_nonblocking(connfd);

	if (getpeereid(connfd, &euid, &egid) == -1)
		fatal("getpeereid");

	count = tree_get(&ctl_count, euid);
	if (count == NULL) {
		count = xcalloc(1, sizeof *count, "control_accept");
		tree_xset(&ctl_count, euid, count);
	}

	if (*count == CONTROL_MAXCONN_PER_CLIENT) {
		close(connfd);
		log_warnx("warn: too many connections to control socket "
		    "from user with uid %lu", (unsigned long int)euid);
		return;
	}
	(*count)++;

	do {
		++connid;
	} while (tree_get(&ctl_conns, connid));

	c = xcalloc(1, sizeof(*c), "control_accept");
	c->euid = euid;
	c->egid = egid;
	c->id = connid;
	c->mproc.proc = PROC_CLIENT;
	c->mproc.handler = control_dispatch_ext;
	c->mproc.data = c;
	mproc_init(&c->mproc, connfd);
	mproc_enable(&c->mproc);
	tree_xset(&ctl_conns, c->id, c);

	stat_backend->increment("control.session", 1);
	return;

pause:
	log_warnx("warn: ctl client limit hit, disabling new connections");
	event_del(&control_state.ev);
}