void
filter_api_loop(void)
{
	if (register_done)
		errx(1, "filter_api_loop already called");

	filter_api_init();

	register_done = 1;

	mproc_enable(&fi.p);

	usleep(1000000);

	if (fi.rootpath) {
		if (chroot(fi.rootpath) == -1)
			err(1, "chroot");
		if (chdir("/") == -1)
			err(1, "chdir");
	}

	if (setgroups(1, &fi.gid) ||
            setresgid(fi.gid, fi.gid, fi.gid) ||
            setresuid(fi.uid, fi.uid, fi.uid))
                err(1, "cannot drop privileges");

	if (event_dispatch() < 0)
		errx(1, "event_dispatch");
}
Beispiel #2
0
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");
}
Beispiel #3
0
void
config_peer(enum smtp_proc_type proc)
{
	struct mproc	*p;

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

	if (proc == PROC_CONTROL)
		p = p_control;
	else if (proc == PROC_LKA)
		p = p_lka;
	else if (proc == PROC_PARENT)
		p = p_parent;
	else if (proc == PROC_QUEUE)
		p = p_queue;
	else if (proc == PROC_SCHEDULER)
		p = p_scheduler;
	else if (proc == PROC_PONY)
		p = p_pony;
	else if (proc == PROC_CA)
		p = p_ca;
	else
		fatalx("bad peer");

	mproc_enable(p);
}
Beispiel #4
0
void
queue_flow_control(void)
{
	size_t	bufsz;
	int	oldlimit = limit;
	int	set, unset;

	bufsz = p_mda->bytes_queued + p_mta->bytes_queued;
	if (bufsz <= flow_agent_lowat)
		limit &= ~LIMIT_AGENT;
	else if (bufsz > flow_agent_hiwat)
		limit |= LIMIT_AGENT;

	if (p_scheduler->bytes_queued <= flow_scheduler_lowat)
		limit &= ~LIMIT_SCHEDULER;
	else if (p_scheduler->bytes_queued > flow_scheduler_hiwat)
		limit |= LIMIT_SCHEDULER;

	set = limit & (limit ^ oldlimit);
	unset = oldlimit & (limit ^ oldlimit);

	if (set & LIMIT_SCHEDULER) {
		log_warnx("warn: queue: Hiwat reached on scheduler buffer: "
		    "suspending transfer, delivery and lookup input");
		mproc_disable(p_mta);
		mproc_disable(p_mda);
		mproc_disable(p_lka);
	}
	else if (unset & LIMIT_SCHEDULER) {
		log_warnx("warn: queue: Down to lowat on scheduler buffer: "
		    "resuming transfer, delivery and lookup input");
		mproc_enable(p_mta);
		mproc_enable(p_mda);
		mproc_enable(p_lka);
	}

	if (set & LIMIT_AGENT) {
		log_warnx("warn: queue: Hiwat reached on transfer and delivery "
		    "buffers: suspending scheduler input");
		mproc_disable(p_scheduler);
	}
	else if (unset & LIMIT_AGENT) {
		log_warnx("warn: queue: Down to lowat on transfer and delivery "
		    "buffers: resuming scheduler input");
		mproc_enable(p_scheduler);
	}
}
Beispiel #5
0
/* 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);
}
Beispiel #6
0
void
filter_api_loop(void)
{
	if (register_done) {
		log_warnx("warn: filter-api:%s filter_api_loop() already called", filter_name);
		fatalx("filter-api: exiting");
	}

	filter_api_init();

	register_done = 1;

	mproc_enable(&fi.p);

	if (fi.rootpath) {
		if (chroot(fi.rootpath) == -1) {
			log_warn("warn: filter-api:%s chroot", filter_name);
			fatalx("filter-api: exiting");
		}
		if (chdir("/") == -1) {
			log_warn("warn: filter-api:%s chdir", filter_name);
			fatalx("filter-api: exiting");
		}
	}

	if (setgroups(1, &fi.gid) ||
	    setresgid(fi.gid, fi.gid, fi.gid) ||
	    setresuid(fi.uid, fi.uid, fi.uid)) {
		log_warn("warn: filter-api:%s cannot drop privileges", filter_name);
		fatalx("filter-api: exiting");
	}

	if (event_dispatch() < 0) {
		log_warn("warn: filter-api:%s event_dispatch", filter_name);
		fatalx("filter-api: exiting");
	}
}
Beispiel #7
0
static void
lka_imsg(struct mproc *p, struct imsg *imsg)
{
    struct rule		*rule;
    struct table		*table;
    void			*tmp;
    int			 ret;
    const char		*key, *val;
    struct ssl		*ssl;
    struct iovec		iov[3];
    static struct dict	*ssl_dict;
    static struct dict	*tables_dict;
    static struct table	*table_last;
    static struct ca_vrfy_req_msg	*req_ca_vrfy_smtp = NULL;
    static struct ca_vrfy_req_msg	*req_ca_vrfy_mta = NULL;
    struct ca_vrfy_req_msg		*req_ca_vrfy_chain;
    struct ca_vrfy_resp_msg		resp_ca_vrfy;
    struct ca_cert_req_msg		*req_ca_cert;
    struct ca_cert_resp_msg		 resp_ca_cert;
    struct sockaddr_storage	 ss;
    struct userinfo		 userinfo;
    struct addrname		 addrname;
    struct envelope		 evp;
    struct msg		 m;
    union lookup		 lk;
    char			 buf[SMTPD_MAXLINESIZE];
    const char		*tablename, *username, *password, *label;
    uint64_t		 reqid;
    size_t			 i;
    int			 v;

    if (imsg->hdr.type == IMSG_DNS_HOST ||
            imsg->hdr.type == IMSG_DNS_PTR ||
            imsg->hdr.type == IMSG_DNS_MX ||
            imsg->hdr.type == IMSG_DNS_MX_PREFERENCE) {
        dns_imsg(p, imsg);
        return;
    }

    if (p->proc == PROC_SMTP) {
        switch (imsg->hdr.type) {
        case IMSG_LKA_EXPAND_RCPT:
            m_msg(&m, imsg);
            m_get_id(&m, &reqid);
            m_get_envelope(&m, &evp);
            m_end(&m);
            lka_session(reqid, &evp);
            return;

        case IMSG_LKA_SSL_INIT:
            req_ca_cert = imsg->data;
            resp_ca_cert.reqid = req_ca_cert->reqid;

            ssl = dict_get(env->sc_ssl_dict, req_ca_cert->name);
            if (ssl == NULL) {
                resp_ca_cert.status = CA_FAIL;
                m_compose(p, IMSG_LKA_SSL_INIT, 0, 0, -1, &resp_ca_cert,
                          sizeof(resp_ca_cert));
                return;
            }
            resp_ca_cert.status = CA_OK;
            resp_ca_cert.cert_len = ssl->ssl_cert_len;
            resp_ca_cert.key_len = ssl->ssl_key_len;
            iov[0].iov_base = &resp_ca_cert;
            iov[0].iov_len = sizeof(resp_ca_cert);
            iov[1].iov_base = ssl->ssl_cert;
            iov[1].iov_len = ssl->ssl_cert_len;
            iov[2].iov_base = ssl->ssl_key;
            iov[2].iov_len = ssl->ssl_key_len;
            m_composev(p, IMSG_LKA_SSL_INIT, 0, 0, -1, iov, nitems(iov));
            return;

        case IMSG_LKA_SSL_VERIFY_CERT:
            req_ca_vrfy_smtp = xmemdup(imsg->data, sizeof *req_ca_vrfy_smtp, "lka:ca_vrfy");
            if (req_ca_vrfy_smtp == NULL)
                fatal(NULL);
            req_ca_vrfy_smtp->cert = xmemdup((char *)imsg->data +
                                             sizeof *req_ca_vrfy_smtp, req_ca_vrfy_smtp->cert_len, "lka:ca_vrfy");
            req_ca_vrfy_smtp->chain_cert = xcalloc(req_ca_vrfy_smtp->n_chain,
                                                   sizeof (unsigned char *), "lka:ca_vrfy");
            req_ca_vrfy_smtp->chain_cert_len = xcalloc(req_ca_vrfy_smtp->n_chain,
                                               sizeof (off_t), "lka:ca_vrfy");
            return;

        case IMSG_LKA_SSL_VERIFY_CHAIN:
            if (req_ca_vrfy_smtp == NULL)
                fatalx("lka:ca_vrfy: chain without a certificate");
            req_ca_vrfy_chain = imsg->data;
            req_ca_vrfy_smtp->chain_cert[req_ca_vrfy_smtp->chain_offset] = xmemdup((char *)imsg->data +
                    sizeof *req_ca_vrfy_chain, req_ca_vrfy_chain->cert_len, "lka:ca_vrfy");
            req_ca_vrfy_smtp->chain_cert_len[req_ca_vrfy_smtp->chain_offset] = req_ca_vrfy_chain->cert_len;
            req_ca_vrfy_smtp->chain_offset++;
            return;

        case IMSG_LKA_SSL_VERIFY:
            if (req_ca_vrfy_smtp == NULL)
                fatalx("lka:ca_vrfy: verify without a certificate");

            resp_ca_vrfy.reqid = req_ca_vrfy_smtp->reqid;

            if (! lka_X509_verify(req_ca_vrfy_smtp, CA_FILE, NULL))
                resp_ca_vrfy.status = CA_FAIL;
            else
                resp_ca_vrfy.status = CA_OK;

            m_compose(p, IMSG_LKA_SSL_VERIFY, 0, 0, -1, &resp_ca_vrfy,
                      sizeof resp_ca_vrfy);

            for (i = 0; i < req_ca_vrfy_smtp->n_chain; ++i)
                free(req_ca_vrfy_smtp->chain_cert[i]);
            free(req_ca_vrfy_smtp->chain_cert);
            free(req_ca_vrfy_smtp->chain_cert_len);
            free(req_ca_vrfy_smtp->cert);
            free(req_ca_vrfy_smtp);
            return;

        case IMSG_LKA_AUTHENTICATE:
            m_msg(&m, imsg);
            m_get_id(&m, &reqid);
            m_get_string(&m, &tablename);
            m_get_string(&m, &username);
            m_get_string(&m, &password);
            m_end(&m);

            if (!tablename[0]) {
                m_create(p_parent, IMSG_LKA_AUTHENTICATE,
                         0, 0, -1);
                m_add_id(p_parent, reqid);
                m_add_string(p_parent, username);
                m_add_string(p_parent, password);
                m_close(p_parent);
                return;
            }

            ret = lka_authenticate(tablename, username, password);

            m_create(p, IMSG_LKA_AUTHENTICATE, 0, 0, -1);
            m_add_id(p, reqid);
            m_add_int(p, ret);
            m_close(p);
            return;
        }
    }

    if (p->proc == PROC_MDA) {
        switch (imsg->hdr.type) {
        case IMSG_LKA_USERINFO:
            m_msg(&m, imsg);
            m_get_string(&m, &tablename);
            m_get_string(&m, &username);
            m_end(&m);

            ret = lka_userinfo(tablename, username, &userinfo);

            m_create(p, IMSG_LKA_USERINFO, 0, 0, -1);
            m_add_string(p, tablename);
            m_add_string(p, username);
            m_add_int(p, ret);
            if (ret == LKA_OK)
                m_add_data(p, &userinfo, sizeof(userinfo));
            m_close(p);
            return;
        }
    }

    if (p->proc == PROC_MTA) {
        switch (imsg->hdr.type) {

        case IMSG_LKA_SSL_INIT:
            req_ca_cert = imsg->data;
            resp_ca_cert.reqid = req_ca_cert->reqid;

            ssl = dict_get(env->sc_ssl_dict, req_ca_cert->name);
            if (ssl == NULL) {
                resp_ca_cert.status = CA_FAIL;
                m_compose(p, IMSG_LKA_SSL_INIT, 0, 0, -1, &resp_ca_cert,
                          sizeof(resp_ca_cert));
                return;
            }
            resp_ca_cert.status = CA_OK;
            resp_ca_cert.cert_len = ssl->ssl_cert_len;
            resp_ca_cert.key_len = ssl->ssl_key_len;
            iov[0].iov_base = &resp_ca_cert;
            iov[0].iov_len = sizeof(resp_ca_cert);
            iov[1].iov_base = ssl->ssl_cert;
            iov[1].iov_len = ssl->ssl_cert_len;
            iov[2].iov_base = ssl->ssl_key;
            iov[2].iov_len = ssl->ssl_key_len;
            m_composev(p, IMSG_LKA_SSL_INIT, 0, 0, -1, iov, nitems(iov));
            return;

        case IMSG_LKA_SSL_VERIFY_CERT:
            req_ca_vrfy_mta = xmemdup(imsg->data, sizeof *req_ca_vrfy_mta, "lka:ca_vrfy");
            if (req_ca_vrfy_mta == NULL)
                fatal(NULL);
            req_ca_vrfy_mta->cert = xmemdup((char *)imsg->data +
                                            sizeof *req_ca_vrfy_mta, req_ca_vrfy_mta->cert_len, "lka:ca_vrfy");
            req_ca_vrfy_mta->chain_cert = xcalloc(req_ca_vrfy_mta->n_chain,
                                                  sizeof (unsigned char *), "lka:ca_vrfy");
            req_ca_vrfy_mta->chain_cert_len = xcalloc(req_ca_vrfy_mta->n_chain,
                                              sizeof (off_t), "lka:ca_vrfy");
            return;

        case IMSG_LKA_SSL_VERIFY_CHAIN:
            if (req_ca_vrfy_mta == NULL)
                fatalx("lka:ca_vrfy: verify without a certificate");

            req_ca_vrfy_chain = imsg->data;
            req_ca_vrfy_mta->chain_cert[req_ca_vrfy_mta->chain_offset] = xmemdup((char *)imsg->data +
                    sizeof *req_ca_vrfy_chain, req_ca_vrfy_chain->cert_len, "lka:ca_vrfy");
            req_ca_vrfy_mta->chain_cert_len[req_ca_vrfy_mta->chain_offset] = req_ca_vrfy_chain->cert_len;
            req_ca_vrfy_mta->chain_offset++;
            return;

        case IMSG_LKA_SSL_VERIFY:
            if (req_ca_vrfy_mta == NULL)
                fatalx("lka:ca_vrfy: verify without a certificate");

            resp_ca_vrfy.reqid = req_ca_vrfy_mta->reqid;

            if (! lka_X509_verify(req_ca_vrfy_mta, CA_FILE, NULL))
                resp_ca_vrfy.status = CA_FAIL;
            else
                resp_ca_vrfy.status = CA_OK;

            m_compose(p, IMSG_LKA_SSL_VERIFY, 0, 0, -1, &resp_ca_vrfy,
                      sizeof resp_ca_vrfy);

            for (i = 0; i < req_ca_vrfy_mta->n_chain; ++i)
                free(req_ca_vrfy_mta->chain_cert[i]);
            free(req_ca_vrfy_mta->chain_cert);
            free(req_ca_vrfy_mta->chain_cert_len);
            free(req_ca_vrfy_mta->cert);
            free(req_ca_vrfy_mta);
            return;

        case IMSG_LKA_SECRET:
            m_msg(&m, imsg);
            m_get_id(&m, &reqid);
            m_get_string(&m, &tablename);
            m_get_string(&m, &label);
            m_end(&m);

            lka_credentials(tablename, label, buf, sizeof(buf));

            m_create(p, IMSG_LKA_SECRET, 0, 0, -1);
            m_add_id(p, reqid);
            m_add_string(p, buf);
            m_close(p);
            return;

        case IMSG_LKA_SOURCE:
            m_msg(&m, imsg);
            m_get_id(&m, &reqid);
            m_get_string(&m, &tablename);

            table = table_find(tablename, NULL);

            m_create(p, IMSG_LKA_SOURCE, 0, 0, -1);
            m_add_id(p, reqid);

            if (table == NULL) {
                log_warn("warn: source address table %s missing",
                         tablename);
                m_add_int(p, LKA_TEMPFAIL);
            }
            else {
                ret = table_fetch(table, K_SOURCE, &lk);
                if (ret == -1)
                    m_add_int(p, LKA_TEMPFAIL);
                else if (ret == 0)
                    m_add_int(p, LKA_PERMFAIL);
                else {
                    m_add_int(p, LKA_OK);
                    m_add_sockaddr(p,
                                   (struct sockaddr *)&lk.source.addr);
                }
            }
            m_close(p);
            return;

        case IMSG_LKA_HELO:
            m_msg(&m, imsg);
            m_get_id(&m, &reqid);
            m_get_string(&m, &tablename);
            m_get_sockaddr(&m, (struct sockaddr *)&ss);
            m_end(&m);

            ret = lka_addrname(tablename, (struct sockaddr*)&ss,
                               &addrname);

            m_create(p, IMSG_LKA_HELO, 0, 0, -1);
            m_add_id(p, reqid);
            m_add_int(p, ret);
            if (ret == LKA_OK)
                m_add_string(p, addrname.name);
            m_close(p);
            return;

        }
    }

    if (p->proc == PROC_PARENT) {
        switch (imsg->hdr.type) {
        case IMSG_CONF_START:
            env->sc_rules_reload = xcalloc(1,
                                           sizeof *env->sc_rules, "lka:sc_rules_reload");
            tables_dict = xcalloc(1,
                                  sizeof *tables_dict, "lka:tables_dict");

            ssl_dict = calloc(1, sizeof *ssl_dict);
            if (ssl_dict == NULL)
                fatal(NULL);
            dict_init(ssl_dict);
            dict_init(tables_dict);
            TAILQ_INIT(env->sc_rules_reload);

            return;

        case IMSG_CONF_SSL:
            ssl = calloc(1, sizeof *ssl);
            if (ssl == NULL)
                fatal(NULL);
            *ssl = *(struct ssl *)imsg->data;
            ssl->ssl_cert = xstrdup((char *)imsg->data +
                                    sizeof *ssl, "smtp:ssl_cert");
            ssl->ssl_key = xstrdup((char *)imsg->data +
                                   sizeof *ssl + ssl->ssl_cert_len, "smtp:ssl_key");
            if (ssl->ssl_dhparams_len) {
                ssl->ssl_dhparams = xstrdup((char *)imsg->data
                                            + sizeof *ssl + ssl->ssl_cert_len +
                                            ssl->ssl_key_len, "smtp:ssl_dhparams");
            }
            if (ssl->ssl_ca_len) {
                ssl->ssl_ca = xstrdup((char *)imsg->data
                                      + sizeof *ssl + ssl->ssl_cert_len +
                                      ssl->ssl_key_len + ssl->ssl_dhparams_len,
                                      "smtp:ssl_ca");
            }
            dict_set(ssl_dict, ssl->ssl_name, ssl);
            return;

        case IMSG_CONF_RULE:
            rule = xmemdup(imsg->data, sizeof *rule, "lka:rule");
            TAILQ_INSERT_TAIL(env->sc_rules_reload, rule, r_entry);
            return;

        case IMSG_CONF_TABLE:
            table_last = table = xmemdup(imsg->data, sizeof *table,
                                         "lka:table");
            dict_init(&table->t_dict);
            dict_set(tables_dict, table->t_name, table);
            return;

        case IMSG_CONF_RULE_SOURCE:
            rule = TAILQ_LAST(env->sc_rules_reload, rulelist);
            tmp = env->sc_tables_dict;
            env->sc_tables_dict = tables_dict;
            rule->r_sources = table_find(imsg->data, NULL);
            if (rule->r_sources == NULL)
                fatalx("lka: tables inconsistency");
            env->sc_tables_dict = tmp;
            return;

        case IMSG_CONF_RULE_SENDER:
            rule = TAILQ_LAST(env->sc_rules_reload, rulelist);
            tmp = env->sc_tables_dict;
            env->sc_tables_dict = tables_dict;
            rule->r_senders = table_find(imsg->data, NULL);
            if (rule->r_senders == NULL)
                fatalx("lka: tables inconsistency");
            env->sc_tables_dict = tmp;
            return;

        case IMSG_CONF_RULE_DESTINATION:
            rule = TAILQ_LAST(env->sc_rules_reload, rulelist);
            tmp = env->sc_tables_dict;
            env->sc_tables_dict = tables_dict;
            rule->r_destination = table_find(imsg->data, NULL);
            if (rule->r_destination == NULL)
                fatalx("lka: tables inconsistency");
            env->sc_tables_dict = tmp;
            return;

        case IMSG_CONF_RULE_MAPPING:
            rule = TAILQ_LAST(env->sc_rules_reload, rulelist);
            tmp = env->sc_tables_dict;
            env->sc_tables_dict = tables_dict;
            rule->r_mapping = table_find(imsg->data, NULL);
            if (rule->r_mapping == NULL)
                fatalx("lka: tables inconsistency");
            env->sc_tables_dict = tmp;
            return;

        case IMSG_CONF_RULE_USERS:
            rule = TAILQ_LAST(env->sc_rules_reload, rulelist);
            tmp = env->sc_tables_dict;
            env->sc_tables_dict = tables_dict;
            rule->r_userbase = table_find(imsg->data, NULL);
            if (rule->r_userbase == NULL)
                fatalx("lka: tables inconsistency");
            env->sc_tables_dict = tmp;
            return;

        case IMSG_CONF_TABLE_CONTENT:
            table = table_last;
            if (table == NULL)
                fatalx("lka: tables inconsistency");

            key = imsg->data;
            if (table->t_type == T_HASH)
                val = key + strlen(key) + 1;
            else
                val = NULL;

            dict_set(&table->t_dict, key,
                     val ? xstrdup(val, "lka:dict_set") : NULL);
            return;

        case IMSG_CONF_END:

            if (env->sc_rules)
                purge_config(PURGE_RULES);
            if (env->sc_tables_dict) {
                table_close_all();
                purge_config(PURGE_TABLES);
            }
            env->sc_rules = env->sc_rules_reload;
            env->sc_ssl_dict = ssl_dict;
            env->sc_tables_dict = tables_dict;
            if (verbose & TRACE_TABLES)
                table_dump_all();
            table_open_all();

            ssl_dict = NULL;
            table_last = NULL;
            tables_dict = NULL;

            /* Start fulfilling requests */
            mproc_enable(p_mda);
            mproc_enable(p_mta);
            mproc_enable(p_smtp);
            return;

        case IMSG_CTL_VERBOSE:
            m_msg(&m, imsg);
            m_get_int(&m, &v);
            m_end(&m);
            log_verbose(v);
            return;

        case IMSG_CTL_PROFILE:
            m_msg(&m, imsg);
            m_get_int(&m, &v);
            m_end(&m);
            profiling = v;
            return;

        case IMSG_PARENT_FORWARD_OPEN:
            lka_session_forward_reply(imsg->data, imsg->fd);
            return;

        case IMSG_LKA_AUTHENTICATE:
            m_forward(p_smtp, imsg);
            return;
        }
    }

    if (p->proc == PROC_CONTROL) {
        switch (imsg->hdr.type) {
        case IMSG_LKA_UPDATE_TABLE:
            table = table_find(imsg->data, NULL);
            if (table == NULL) {
                log_warnx("warn: Lookup table not found: "
                          "\"%s\"", (char *)imsg->data);
                return;
            }
            table_update(table);
            return;
        }
    }

    errx(1, "lka_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
}
Beispiel #8
0
void
mfa_ready(void)
{
	log_debug("debug: mfa ready");
	mproc_enable(p_smtp);
}
Beispiel #9
0
void
ca_imsg(struct mproc *p, struct imsg *imsg)
{
	RSA			*rsa;
	const void		*from = NULL;
	unsigned char		*to = NULL;
	struct msg		 m;
	const char		*pkiname;
	size_t			 flen, tlen, padding;
	struct pki		*pki;
	int			 ret = 0;
	uint64_t		 id;
	int			 v;

	if (p->proc == PROC_PARENT) {
		switch (imsg->hdr.type) {
		case IMSG_CONF_START:
			return;
		case IMSG_CONF_END:
			ca_init();

			/* Start fulfilling requests */
			mproc_enable(p_pony);
			return;
		}
	}

	if (p->proc == PROC_CONTROL) {
		switch (imsg->hdr.type) {
		case IMSG_CTL_VERBOSE:
			m_msg(&m, imsg);
			m_get_int(&m, &v);
			m_end(&m);
			log_verbose(v);
			return;
		case IMSG_CTL_PROFILE:
			m_msg(&m, imsg);
			m_get_int(&m, &v);
			m_end(&m);
			profiling = v;
			return;
		}
	}

	if (p->proc == PROC_PONY) {
		switch (imsg->hdr.type) {
		case IMSG_CA_PRIVENC:
		case IMSG_CA_PRIVDEC:
			m_msg(&m, imsg);
			m_get_id(&m, &id);
			m_get_string(&m, &pkiname);
			m_get_data(&m, &from, &flen);
			m_get_size(&m, &tlen);
			m_get_size(&m, &padding);
			m_end(&m);

			pki = dict_get(env->sc_pki_dict, pkiname);
			if (pki == NULL || pki->pki_pkey == NULL ||
			    (rsa = EVP_PKEY_get1_RSA(pki->pki_pkey)) == NULL)
				fatalx("ca_imsg: invalid pki");

			if ((to = calloc(1, tlen)) == NULL)
				fatalx("ca_imsg: calloc");

			switch (imsg->hdr.type) {
			case IMSG_CA_PRIVENC:
				ret = RSA_private_encrypt(flen, from, to, rsa,
				    padding);
				break;
			case IMSG_CA_PRIVDEC:
				ret = RSA_private_decrypt(flen, from, to, rsa,
				    padding);
				break;
			}

			m_create(p, imsg->hdr.type, 0, 0, -1);
			m_add_id(p, id);
			m_add_int(p, ret);
			if (ret > 0)
				m_add_data(p, to, (size_t)ret);
			m_close(p);

			free(to);
			RSA_free(rsa);

			return;
		}
	}

	errx(1, "ca_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
}
Beispiel #10
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);
}