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); }
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. */ }