master-service-ssl-settings.c revision 02c335c23bf5fa225a467c19f2c063fb0dc7b8c3
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
cf1797248b02eadfd7d63aabc0b64678a4239540Timo Sirainen#include "settings-parser.h"
cf1797248b02eadfd7d63aabc0b64678a4239540Timo Sirainen#include "master-service-private.h"
2423da95ee20fd4b3c260c1389cf2952d25f099cTimo Sirainen#include "master-service-ssl-settings.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a8fe899601735459641edae975c0fa08be8482e2Timo Sirainen#include <stddef.h>
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#undef DEF
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#define DEF(type, name) \
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen { type, #name, offsetof(struct master_service_ssl_settings, name), NULL }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainenstatic bool
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainenmaster_service_ssl_settings_check(void *_set, pool_t pool, const char **error_r);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenstatic const struct setting_define master_service_ssl_setting_defines[] = {
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen DEF(SET_ENUM, ssl),
bdb026e2dc8a7c77585ed5ba489f0056df8074d4Timo Sirainen DEF(SET_STR, ssl_ca),
bdb026e2dc8a7c77585ed5ba489f0056df8074d4Timo Sirainen DEF(SET_STR, ssl_cert),
bdb026e2dc8a7c77585ed5ba489f0056df8074d4Timo Sirainen DEF(SET_STR, ssl_key),
bdb026e2dc8a7c77585ed5ba489f0056df8074d4Timo Sirainen DEF(SET_STR, ssl_key_password),
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen DEF(SET_STR, ssl_cipher_list),
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen DEF(SET_STR, ssl_protocols),
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen DEF(SET_STR, ssl_cert_username_field),
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen DEF(SET_STR, ssl_crypto_device),
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen DEF(SET_BOOL, ssl_verify_client_cert),
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen DEF(SET_BOOL, ssl_require_crl),
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen DEF(SET_BOOL, verbose_ssl),
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen DEF(SET_BOOL, ssl_prefer_server_ciphers),
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen DEF(SET_STR, ssl_options), /* parsed as a string to set bools */
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen SETTING_DEFINE_LIST_END
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen};
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic const struct master_service_ssl_settings master_service_ssl_default_settings = {
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen#ifdef HAVE_SSL
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen .ssl = "yes:no:required",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#else
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen .ssl = "no:yes:required",
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#endif
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen .ssl_ca = "",
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen .ssl_cert = "",
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen .ssl_key = "",
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen .ssl_key_password = "",
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen .ssl_cipher_list = "ALL:!LOW:!SSLv2:!EXP:!aNULL",
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen .ssl_protocols = "!SSLv2",
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen .ssl_cert_username_field = "commonName",
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen .ssl_crypto_device = "",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen .ssl_verify_client_cert = FALSE,
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen .ssl_require_crl = TRUE,
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen .verbose_ssl = FALSE,
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen .ssl_prefer_server_ciphers = FALSE,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen .ssl_options = "",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen};
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainen
d92f33f13830ba23d814342bf3ea8db721a15bb1Timo Sirainenconst struct setting_parser_info master_service_ssl_setting_parser_info = {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen .module_name = "ssl",
61e84692827b6a64912343f515c984853021483aTimo Sirainen .defines = master_service_ssl_setting_defines,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen .defaults = &master_service_ssl_default_settings,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen .type_offset = (size_t)-1,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen .struct_size = sizeof(struct master_service_ssl_settings),
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen .parent_offset = (size_t)-1,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen .check_func = master_service_ssl_settings_check
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen};
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen/* <settings checks> */
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenstatic bool
4ba962c3e78f140facdcfb1e093c4c46de75ae24Timo Sirainenmaster_service_ssl_settings_check(void *_set, pool_t pool ATTR_UNUSED,
4ba962c3e78f140facdcfb1e093c4c46de75ae24Timo Sirainen const char **error_r)
4ba962c3e78f140facdcfb1e093c4c46de75ae24Timo Sirainen{
4ba962c3e78f140facdcfb1e093c4c46de75ae24Timo Sirainen struct master_service_ssl_settings *set = _set;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (strcmp(set->ssl, "no") == 0) {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* disabled */
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen return TRUE;
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen }
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen#ifndef HAVE_SSL
71e88fae3be360e9a93b3398e743f99a6f05d2edTimo Sirainen *error_r = t_strdup_printf("SSL support not compiled in but ssl=%s",
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen set->ssl);
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen return FALSE;
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen#else
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen /* we get called from many different tools, possibly with -O parameter,
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen and few of those tools care about SSL settings. so don't check
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen ssl_cert/ssl_key/etc validity here except in doveconf, because it
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen usually is just an extra annoyance. */
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen#ifdef CONFIG
8854395cdd21ca521b37ce669f3acb8445792b20Timo Sirainen if (*set->ssl_cert == '\0') {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *error_r = "ssl enabled, but ssl_cert not set";
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (*set->ssl_key == '\0') {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen *error_r = "ssl enabled, but ssl_key not set";
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return FALSE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#endif
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (set->ssl_verify_client_cert && *set->ssl_ca == '\0') {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen *error_r = "ssl_verify_client_cert set, but ssl_ca not";
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
bbd0a870f8639767e4e4011d2aedadac08d5c66fTimo Sirainen /* Now explode the ssl_options string into individual flags */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* First set them all to defaults */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen set->parsed_opts.compression = TRUE;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen set->parsed_opts.tickets = TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* Then modify anything specified in the string */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char **opts = t_strsplit_spaces(set->ssl_options, ", ");
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen const char *opt;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen while ((opt = *opts++) != NULL) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (strcasecmp(opt, "no_compression") == 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen set->parsed_opts.compression = FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else if (strcasecmp(opt, "no_ticket") == 0) {
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen set->parsed_opts.tickets = FALSE;
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen } else {
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen *error_r = t_strdup_printf("ssl_options: unknown flag: '%s'",
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen opt);
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen return FALSE;
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen }
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen }
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen return TRUE;
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen#endif
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen}
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen/* </settings checks> */
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenconst struct master_service_ssl_settings *
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainenmaster_service_ssl_settings_get(struct master_service *service)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen void **sets;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen sets = settings_parser_get_list(service->set_parser);
4d84348ffcbb60de566108562c95ad64629e7a53Timo Sirainen return sets[1];
4c0aff96fc7e6d779be43458f96cbf015849a3deTimo Sirainen}
d6499957ea59e6d9729d3350d9ac5eae992635f6Timo Sirainen