Пример #1
0
void    psc_free_session_state(PSC_STATE *state)
{
    const char *myname = "psc_free_session_state";
    HTABLE_INFO *ht;

    /*
     * Update the per-client session count.
     */
    if ((ht = htable_locate(psc_client_concurrency,
			    state->smtp_client_addr)) == 0)
	msg_panic("%s: unknown client address: %s",
		  myname, state->smtp_client_addr);
    if (--(ht->value) == 0)
	htable_delete(psc_client_concurrency, state->smtp_client_addr,
		      (void (*) (char *)) 0);

    if (state->smtp_client_stream != 0) {
	event_server_disconnect(state->smtp_client_stream);
	psc_check_queue_length--;
    }
    if (state->smtp_server_fd >= 0) {
	close(state->smtp_server_fd);
	psc_post_queue_length--;
    }
    if (state->send_buf != 0)
	state->send_buf = vstring_free(state->send_buf);
    myfree(state->smtp_client_addr);
    myfree(state->smtp_client_port);
    myfree(state->smtp_server_addr);
    myfree(state->smtp_server_port);
    if (state->dnsbl_reply)
	vstring_free(state->dnsbl_reply);
    if (state->helo_name)
	myfree(state->helo_name);
    if (state->sender)
	myfree(state->sender);
    if (state->cmd_buffer)
	vstring_free(state->cmd_buffer);
    if (state->expand_buf)
	vstring_free(state->expand_buf);
    myfree((char *) state);

    if (psc_check_queue_length < 0 || psc_post_queue_length < 0)
	msg_panic("bad queue length: check_queue=%d, post_queue=%d",
		  psc_check_queue_length, psc_post_queue_length);

    /*
     * Update the stress level.
     */
    if (psc_stress != 0
	&& psc_check_queue_length <= psc_lowat_check_queue_length) {
	psc_stress = 0;
	msg_info("leaving STRESS mode with %d connections",
		 psc_check_queue_length);
    }
}
Пример #2
0
void    tlsp_state_free(TLSP_STATE *state)
{
    myfree(state->service);
    if (state->plaintext_buf)			/* turns off plaintext events */
	nbbio_free(state->plaintext_buf);
    event_server_disconnect(state->plaintext_stream);
    if (state->ciphertext_fd >= 0) {
	event_disable_readwrite(state->ciphertext_fd);
	(void) close(state->ciphertext_fd);
    }
    if (state->ciphertext_timer)
	event_cancel_timer(state->ciphertext_timer, (char *) state);
    if (state->remote_endpt) {
	msg_info("DISCONNECT %s", state->remote_endpt);
	myfree(state->remote_endpt);
    }
    if (state->server_id)
	myfree(state->server_id);
    if (state->tls_context)
	tls_free_context(state->tls_context);
    myfree((char *) state);
}
Пример #3
0
static void tlsp_service(VSTREAM *stream, char *unused_service,
                         char **unused_argv)
{
    msg_info("TLS support is not compiled in -- exiting");
    event_server_disconnect(stream);
}
Пример #4
0
static void psc_endpt_lookup_done(int endpt_status,
				          VSTREAM *smtp_client_stream,
				          MAI_HOSTADDR_STR *smtp_client_addr,
				          MAI_SERVPORT_STR *smtp_client_port,
				          MAI_HOSTADDR_STR *smtp_server_addr,
				          MAI_SERVPORT_STR *smtp_server_port)
{
    const char *myname = "psc_endpt_lookup_done";
    PSC_STATE *state;
    const char *stamp_str;
    int     saved_flags;

    /*
     * Best effort - if this non-blocking write(2) fails, so be it.
     */
    if (endpt_status < 0) {
	(void) write(vstream_fileno(smtp_client_stream),
		     "421 4.3.2 No system resources\r\n",
		     sizeof("421 4.3.2 No system resources\r\n") - 1);
	event_server_disconnect(smtp_client_stream);
	return;
    }
    if (msg_verbose > 1)
	msg_info("%s: sq=%d cq=%d connect from [%s]:%s",
		 myname, psc_post_queue_length, psc_check_queue_length,
		 smtp_client_addr->buf, smtp_client_port->buf);

    msg_info("CONNECT from [%s]:%s to [%s]:%s",
	     smtp_client_addr->buf, smtp_client_port->buf,
	     smtp_server_addr->buf, smtp_server_port->buf);

    /*
     * Bundle up all the loose session pieces. This zeroes all flags and time
     * stamps.
     */
    state = psc_new_session_state(smtp_client_stream, smtp_client_addr->buf,
				  smtp_client_port->buf,
				  smtp_server_addr->buf,
				  smtp_server_port->buf);

    /*
     * Reply with 421 when the client has too many open connections.
     */
    if (var_psc_cconn_limit > 0
	&& state->client_concurrency > var_psc_cconn_limit) {
	msg_info("NOQUEUE: reject: CONNECT from [%s]:%s: too many connections",
		 state->smtp_client_addr, state->smtp_client_port);
	PSC_DROP_SESSION_STATE(state,
			       "421 4.7.0 Error: too many connections\r\n");
	return;
    }

    /*
     * Reply with 421 when we can't forward more connections.
     */
    if (var_psc_post_queue_limit > 0
	&& psc_post_queue_length >= var_psc_post_queue_limit) {
	msg_info("NOQUEUE: reject: CONNECT from [%s]:%s: all server ports busy",
		 state->smtp_client_addr, state->smtp_client_port);
	PSC_DROP_SESSION_STATE(state,
			       "421 4.3.2 All server ports are busy\r\n");
	return;
    }

    /*
     * The permanent white/blacklist has highest precedence.
     */
    if (psc_acl != 0) {
	switch (psc_acl_eval(state, psc_acl, VAR_PSC_ACL)) {

	    /*
	     * Permanently blacklisted.
	     */
	case PSC_ACL_ACT_BLACKLIST:
	    msg_info("BLACKLISTED [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
	    PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_BLIST_FAIL);
	    switch (psc_blist_action) {
	    case PSC_ACT_DROP:
		PSC_DROP_SESSION_STATE(state,
			     "521 5.3.2 Service currently unavailable\r\n");
		return;
	    case PSC_ACT_ENFORCE:
		PSC_ENFORCE_SESSION_STATE(state,
			     "550 5.3.2 Service currently unavailable\r\n");
		break;
	    case PSC_ACT_IGNORE:
		PSC_UNFAIL_SESSION_STATE(state, PSC_STATE_FLAG_BLIST_FAIL);

		/*
		 * Not: PSC_PASS_SESSION_STATE. Repeat this test the next
		 * time.
		 */
		break;
	    default:
		msg_panic("%s: unknown blacklist action value %d",
			  myname, psc_blist_action);
	    }
	    break;

	    /*
	     * Permanently whitelisted.
	     */
	case PSC_ACL_ACT_WHITELIST:
	    msg_info("WHITELISTED [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
	    psc_conclude(state);
	    return;

	    /*
	     * Other: dunno (don't know) or error.
	     */
	default:
	    break;
	}
    }

    /*
     * The temporary whitelist (i.e. the postscreen cache) has the lowest
     * precedence. This cache contains information about the results of prior
     * tests. Whitelist the client when all enabled test results are still
     * valid.
     */
    if ((state->flags & PSC_STATE_MASK_ANY_FAIL) == 0
	&& psc_cache_map != 0
	&& (stamp_str = psc_cache_lookup(psc_cache_map, state->smtp_client_addr)) != 0) {
	saved_flags = state->flags;
	psc_parse_tests(state, stamp_str, event_time());
	state->flags |= saved_flags;
	if (msg_verbose)
	    msg_info("%s: cached + recent flags: %s",
		     myname, psc_print_state_flags(state->flags, myname));
	if ((state->flags & PSC_STATE_MASK_ANY_TODO_FAIL) == 0) {
	    msg_info("PASS OLD [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
	    psc_conclude(state);
	    return;
	}
    } else {
	saved_flags = state->flags;
	psc_new_tests(state);
	state->flags |= saved_flags;
	if (msg_verbose)
	    msg_info("%s: new + recent flags: %s",
		     myname, psc_print_state_flags(state->flags, myname));
    }

    /*
     * Don't whitelist clients that connect to backup MX addresses. Fail
     * "closed" on error.
     */
    if (addr_match_list_match(psc_wlist_if, smtp_server_addr->buf) == 0) {
	state->flags |= (PSC_STATE_FLAG_WLIST_FAIL | PSC_STATE_FLAG_NOFORWARD);
	msg_info("WHITELIST VETO [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
    }

    /*
     * Reply with 421 when we can't analyze more connections. That also means
     * no deep protocol tests when the noforward flag is raised.
     */
    if (var_psc_pre_queue_limit > 0
	&& psc_check_queue_length - psc_post_queue_length
	>= var_psc_pre_queue_limit) {
	msg_info("reject: connect from [%s]:%s: all screening ports busy",
		 state->smtp_client_addr, state->smtp_client_port);
	PSC_DROP_SESSION_STATE(state,
			       "421 4.3.2 All screening ports are busy\r\n");
	return;
    }

    /*
     * If the client has no up-to-date results for some tests, do those tests
     * first. Otherwise, skip the tests and hand off the connection.
     */
    if (state->flags & PSC_STATE_MASK_EARLY_TODO)
	psc_early_tests(state);
    else if (state->flags & (PSC_STATE_MASK_SMTPD_TODO | PSC_STATE_FLAG_NOFORWARD))
	psc_smtpd_tests(state);
    else
	psc_conclude(state);
}