예제 #1
0
static void
session_respond_delayed(int fd, short event, void *p)
{
	struct session	*s = p;

	io_resume(&s->s_io, IO_PAUSE_OUT);
}
예제 #2
0
static void
filter_io_out(struct io *io, int evt)
{
	struct filter_session    *s = io->arg;

	log_trace(TRACE_FILTERS, "filter-api:%s %016"PRIx64" filter_io_out(%s)",
	    filter_name, s->id, io_strevent(evt));

	switch (evt) {
	case IO_TIMEOUT:
	case IO_DISCONNECTED:
	case IO_ERROR:
		log_trace(TRACE_FILTERS, "filter-api:%s %016"PRIx64" io error on output pipe",
		    filter_name, s->id);
		s->pipe.error = 1;
		break;

	case IO_LOWAT:
		/* flow control */
		if (s->pipe.iev.sock != -1 && s->pipe.iev.flags & IO_PAUSE_IN) {
			io_resume(&s->pipe.iev, IO_PAUSE_IN);
			return;
		}

		/* if the input is done and there is a response we are done */
		if (s->pipe.iev.sock == -1 && s->response.ready)
			break;

		/* just wait for more data to send */
		return;

	default:
		fatalx("filter_io_out()");
	}

	io_clear(&s->pipe.oev);
	iobuf_clear(&s->pipe.obuf);
	if (s->pipe.error) {
		io_clear(&s->pipe.iev);
		iobuf_clear(&s->pipe.ibuf);
	}
	filter_trigger_eom(s);
}
예제 #3
0
void
mta_session_imsg(struct mproc *p, struct imsg *imsg)
{
	struct ca_vrfy_resp_msg	*resp_ca_vrfy;
	struct ca_cert_resp_msg	*resp_ca_cert;
	struct mta_session	*s;
	struct mta_host		*h;
	struct msg		 m;
	uint64_t		 reqid;
	const char		*name;
	void			*ssl;
	int			 dnserror, status;

	switch (imsg->hdr.type) {

	case IMSG_QUEUE_MESSAGE_FD:
		m_msg(&m, imsg);
		m_get_id(&m, &reqid);
		m_end(&m);

		s = mta_tree_pop(&wait_fd, reqid);
		if (s == NULL) {
			if (imsg->fd != -1)
				close(imsg->fd);
			return;
		}

		if (imsg->fd == -1) {
			log_debug("debug: mta: failed to obtain msg fd");
			mta_flush_task(s, IMSG_DELIVERY_TEMPFAIL,
			    "Could not get message fd", 0, 0);
			mta_enter_state(s, MTA_READY);
			io_reload(&s->io);
			return;
		}

		s->datafp = fdopen(imsg->fd, "r");
		if (s->datafp == NULL)
			fatal("mta: fdopen");

		if (mta_check_loop(s->datafp)) {
			log_debug("debug: mta: loop detected");
			fclose(s->datafp);
			s->datafp = NULL;
			mta_flush_task(s, IMSG_DELIVERY_LOOP,
			    "Loop detected", 0, 0);
			mta_enter_state(s, MTA_READY);
		} else {
			mta_enter_state(s, MTA_MAIL);
		}
		io_reload(&s->io);
		return;

	case IMSG_DNS_PTR:
		m_msg(&m, imsg);
		m_get_id(&m, &reqid);
		m_get_int(&m, &dnserror);
		if (dnserror)
			name = NULL;
		else
			m_get_string(&m, &name);
		m_end(&m);
		s = mta_tree_pop(&wait_ptr, reqid);
		if (s == NULL)
			return;

		h = s->route->dst;
		h->lastptrquery = time(NULL);
		if (name)
			h->ptrname = xstrdup(name, "mta: ptr");
		waitq_run(&h->ptrname, h->ptrname);
		return;

	case IMSG_LKA_SSL_INIT:
		resp_ca_cert = imsg->data;
		s = mta_tree_pop(&wait_ssl_init, resp_ca_cert->reqid);
		if (s == NULL)
			return;

		if (resp_ca_cert->status == CA_FAIL) {
			if (s->relay->pki_name) {
				log_info("smtp-out: Disconnecting session %016"PRIx64
				    ": CA failure", s->id);
				mta_free(s);
				return;
			}
			else {
				ssl = ssl_mta_init(NULL, 0, NULL, 0);
				if (ssl == NULL)
					fatal("mta: ssl_mta_init");
				io_start_tls(&s->io, ssl);
				return;
			}
		}

		resp_ca_cert = xmemdup(imsg->data, sizeof *resp_ca_cert, "mta:ca_cert");
		resp_ca_cert->cert = xstrdup((char *)imsg->data +
		    sizeof *resp_ca_cert, "mta:ca_cert");
		resp_ca_cert->key = xstrdup((char *)imsg->data +
		    sizeof *resp_ca_cert + resp_ca_cert->cert_len,
		    "mta:ca_key");
		ssl = ssl_mta_init(resp_ca_cert->cert, resp_ca_cert->cert_len,
		    resp_ca_cert->key, resp_ca_cert->key_len);
		if (ssl == NULL)
			fatal("mta: ssl_mta_init");
		io_start_tls(&s->io, ssl);

		memset(resp_ca_cert->cert, 0, resp_ca_cert->cert_len);
		memset(resp_ca_cert->key, 0, resp_ca_cert->key_len);
		free(resp_ca_cert->cert);
		free(resp_ca_cert->key);
		free(resp_ca_cert);
		return;

	case IMSG_LKA_SSL_VERIFY:
		resp_ca_vrfy = imsg->data;
		s = mta_tree_pop(&wait_ssl_verify, resp_ca_vrfy->reqid);
		if (s == NULL)
			return;

		if (resp_ca_vrfy->status == CA_OK)
			s->flags |= MTA_VERIFIED;
		else if (s->relay->flags & F_TLS_VERIFY) {
			errno = 0;
			mta_error(s, "SSL certificate check failed");
			mta_free(s);
			return;
		}

		mta_io(&s->io, IO_TLSVERIFIED);
		io_resume(&s->io, IO_PAUSE_IN);
		io_reload(&s->io);
		return;

	case IMSG_LKA_HELO:
		m_msg(&m, imsg);
		m_get_id(&m, &reqid);
		m_get_int(&m, &status);
		if (status == LKA_OK)
			m_get_string(&m, &name);
		m_end(&m);

		s = mta_tree_pop(&wait_helo, reqid);
		if (s == NULL)
			return;

		if (status == LKA_OK) {
			s->helo = xstrdup(name, "mta_session_imsg");
			mta_connect(s);
		} else {
			mta_source_error(s->relay, s->route,
			    "Failed to retrieve helo string");
			mta_free(s);
		}
		return;

	default:
		errx(1, "mta_session_imsg: unexpected %s imsg",
		    imsg_to_str(imsg->hdr.type));
	}
}