Exemplo n.º 1
0
static void set_cipher_grade(SMTP_TLS_POLICY *tls)
{
    const char *mand_exclude = "";
    const char *also_exclude = "";

    /*
     * Use main.cf cipher level if no per-destination value specified. With
     * mandatory encryption at least encrypt, and with mandatory verification
     * at least authenticate!
     */
    switch (tls->level) {
    case TLS_LEV_INVALID:
    case TLS_LEV_NONE:
	return;

    case TLS_LEV_MAY:
	if (tls->grade == 0)
	    tls->grade = mystrdup(var_smtp_tls_ciph);
	break;

    case TLS_LEV_ENCRYPT:
	if (tls->grade == 0)
	    tls->grade = mystrdup(var_smtp_tls_mand_ciph);
	mand_exclude = var_smtp_tls_mand_excl;
	also_exclude = "eNULL";
	break;

    case TLS_LEV_DANE:
    case TLS_LEV_FPRINT:
    case TLS_LEV_VERIFY:
    case TLS_LEV_SECURE:
	if (tls->grade == 0)
	    tls->grade = mystrdup(var_smtp_tls_mand_ciph);
	mand_exclude = var_smtp_tls_mand_excl;
	also_exclude = "aNULL";
	break;
    }

#define ADD_EXCLUDE(vstr, str) \
    do { \
	if (*(str)) \
	    vstring_sprintf_append((vstr), "%s%s", \
				   VSTRING_LEN(vstr) ? " " : "", (str)); \
    } while (0)

    /*
     * The "exclude" policy table attribute overrides main.cf exclusion
     * lists.
     */
    if (tls->exclusions == 0) {
	tls->exclusions = vstring_alloc(10);
	ADD_EXCLUDE(tls->exclusions, var_smtp_tls_excl_ciph);
	ADD_EXCLUDE(tls->exclusions, mand_exclude);
    }
    ADD_EXCLUDE(tls->exclusions, also_exclude);
}
Exemplo n.º 2
0
static void tlsp_start_tls(TLSP_STATE *state)
{
    TLS_SERVER_START_PROPS props;
    static char *cipher_grade;
    static VSTRING *cipher_exclusions;

    /*
     * The code in this routine is pasted literally from smtpd(8). I am not
     * going to sanitize this because doing so surely will break things in
     * unexpected ways.
     */

    /*
     * Perform the before-handshake portion of the per-session initalization.
     * Pass a null VSTREAM to indicate that this program, will do the
     * ciphertext I/O, not libtls.
     *
     * The cipher grade and exclusions don't change between sessions. Compute
     * just once and cache.
     */
#define ADD_EXCLUDE(vstr, str) \
    do { \
	if (*(str)) \
	    vstring_sprintf_append((vstr), "%s%s", \
				   VSTRING_LEN(vstr) ? " " : "", (str)); \
    } while (0)

    if (cipher_grade == 0) {
        cipher_grade =
            var_tlsp_enforce_tls ? var_tlsp_tls_mand_ciph : var_tlsp_tls_ciph;
        cipher_exclusions = vstring_alloc(10);
        ADD_EXCLUDE(cipher_exclusions, var_tlsp_tls_excl_ciph);
        if (var_tlsp_enforce_tls)
            ADD_EXCLUDE(cipher_exclusions, var_tlsp_tls_mand_excl);
        if (ask_client_cert)
            ADD_EXCLUDE(cipher_exclusions, "aNULL");
    }
    state->tls_context =
        TLS_SERVER_START(&props,
                         ctx = tlsp_server_ctx,
                         stream = (VSTREAM *) 0,/* unused */
                         fd = state->ciphertext_fd,
                         timeout = 0,		/* unused */
                         requirecert = (var_tlsp_tls_req_ccert
                                        && var_tlsp_enforce_tls),
                         serverid = state->server_id,
                         namaddr = state->remote_endpt,
                         cipher_grade = cipher_grade,
                         cipher_exclusions = STR(cipher_exclusions),
                         mdalg = var_tlsp_tls_fpt_dgst);

    if (state->tls_context == 0) {
        tlsp_state_free(state);
        return;
    }

    /*
     * XXX Do we care about TLS session rate limits? Good postscreen(8)
     * clients will occasionally require the tlsproxy to renew their
     * whitelist status, but bad clients hammering the server can suck up
     * lots of CPU cycles. Per-client concurrency limits in postscreen(8)
     * will divert only naive security "researchers".
     *
     * XXX Do we care about certificate verification results? Not as long as
     * postscreen(8) doesn't actually receive email.
     */
}