1 /* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "lib.h"
4 #include "settings-parser.h"
5 #include "master-service-private.h"
6 #include "master-service-ssl-settings.h"
7 #include "iostream-ssl.h"
8 
9 #include <stddef.h>
10 
11 #undef DEF
12 #define DEF(type, name) \
13 	SETTING_DEFINE_STRUCT_##type(#name, name, struct master_service_ssl_settings)
14 
15 static bool
16 master_service_ssl_settings_check(void *_set, pool_t pool, const char **error_r);
17 
18 static const struct setting_define master_service_ssl_setting_defines[] = {
19 	DEF(ENUM, ssl),
20 	DEF(STR, ssl_ca),
21 	DEF(STR, ssl_client_ca_file),
22 	DEF(STR, ssl_client_ca_dir),
23 	DEF(STR, ssl_client_cert),
24 	DEF(STR, ssl_client_key),
25 	DEF(STR, ssl_cipher_list),
26 	DEF(STR, ssl_cipher_suites),
27 	DEF(STR, ssl_curve_list),
28 	DEF(STR, ssl_min_protocol),
29 	DEF(STR, ssl_cert_username_field),
30 	DEF(STR, ssl_crypto_device),
31 	DEF(BOOL, ssl_verify_client_cert),
32 	DEF(BOOL, ssl_client_require_valid_cert),
33 	DEF(BOOL, ssl_require_crl),
34 	DEF(BOOL, verbose_ssl),
35 	DEF(BOOL, ssl_prefer_server_ciphers),
36 	DEF(STR, ssl_options), /* parsed as a string to set bools */
37 
38 	SETTING_DEFINE_LIST_END
39 };
40 
41 static const struct master_service_ssl_settings master_service_ssl_default_settings = {
42 #ifdef HAVE_SSL
43 	.ssl = "yes:no:required",
44 #else
45 	.ssl = "no:yes:required",
46 #endif
47 	.ssl_ca = "",
48 	.ssl_client_ca_file = "",
49 	.ssl_client_ca_dir = "",
50 	.ssl_client_cert = "",
51 	.ssl_client_key = "",
52 	.ssl_cipher_list = "ALL:!kRSA:!SRP:!kDHd:!DSS:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK:!RC4:!ADH:!LOW@STRENGTH",
53 	.ssl_cipher_suites = "", /* Use TLS library provided value */
54 	.ssl_curve_list = "",
55 	.ssl_min_protocol = "TLSv1.2",
56 	.ssl_cert_username_field = "commonName",
57 	.ssl_crypto_device = "",
58 	.ssl_verify_client_cert = FALSE,
59 	.ssl_client_require_valid_cert = TRUE,
60 	.ssl_require_crl = TRUE,
61 	.verbose_ssl = FALSE,
62 	.ssl_prefer_server_ciphers = FALSE,
63 	.ssl_options = "",
64 };
65 
66 const struct setting_parser_info master_service_ssl_setting_parser_info = {
67 	.module_name = "ssl",
68 	.defines = master_service_ssl_setting_defines,
69 	.defaults = &master_service_ssl_default_settings,
70 
71 	.type_offset = SIZE_MAX,
72 	.struct_size = sizeof(struct master_service_ssl_settings),
73 
74 	.parent_offset = SIZE_MAX,
75 	.check_func = master_service_ssl_settings_check
76 };
77 
78 #undef DEF
79 #define DEF(type, name) \
80 	SETTING_DEFINE_STRUCT_##type(#name, name, struct master_service_ssl_server_settings)
81 
82 static const struct setting_define master_service_ssl_server_setting_defines[] = {
83 	DEF(STR, ssl_cert),
84 	DEF(STR, ssl_key),
85 	DEF(STR, ssl_alt_cert),
86 	DEF(STR, ssl_alt_key),
87 	DEF(STR, ssl_key_password),
88 	DEF(STR, ssl_dh),
89 
90 	SETTING_DEFINE_LIST_END
91 };
92 
93 static const struct master_service_ssl_server_settings master_service_ssl_server_default_settings = {
94 	.ssl_cert = "",
95 	.ssl_key = "",
96 	.ssl_alt_cert = "",
97 	.ssl_alt_key = "",
98 	.ssl_key_password = "",
99 	.ssl_dh = "",
100 };
101 
102 static const struct setting_parser_info *master_service_ssl_server_setting_dependencies[] = {
103 	&master_service_ssl_setting_parser_info,
104 	NULL
105 };
106 
107 const struct setting_parser_info master_service_ssl_server_setting_parser_info = {
108 	.module_name = "ssl-server",
109 	.defines = master_service_ssl_server_setting_defines,
110 	.defaults = &master_service_ssl_server_default_settings,
111 
112 	.type_offset = SIZE_MAX,
113 	.struct_size = sizeof(struct master_service_ssl_server_settings),
114 
115 	.parent_offset = SIZE_MAX,
116 	.dependencies = master_service_ssl_server_setting_dependencies,
117 };
118 
119 /* <settings checks> */
120 static bool
master_service_ssl_settings_check(void * _set,pool_t pool ATTR_UNUSED,const char ** error_r)121 master_service_ssl_settings_check(void *_set, pool_t pool ATTR_UNUSED,
122 				  const char **error_r)
123 {
124 	struct master_service_ssl_settings *set = _set;
125 
126 	if (strcmp(set->ssl, "no") == 0) {
127 		/* disabled */
128 		return TRUE;
129 	}
130 #ifndef HAVE_SSL
131 	*error_r = t_strdup_printf("SSL support not compiled in but ssl=%s",
132 				   set->ssl);
133 	return FALSE;
134 #else
135 	/* we get called from many different tools, possibly with -O parameter,
136 	   and few of those tools care about SSL settings. so don't check
137 	   ssl_cert/ssl_key/etc validity here except in doveconf, because it
138 	   usually is just an extra annoyance. */
139 #ifdef CONFIG_BINARY
140 	if (*set->ssl_cert == '\0') {
141 		*error_r = "ssl enabled, but ssl_cert not set";
142 		return FALSE;
143 	}
144 	if (*set->ssl_key == '\0') {
145 		*error_r = "ssl enabled, but ssl_key not set";
146 		return FALSE;
147 	}
148 #endif
149 	if (set->ssl_verify_client_cert && *set->ssl_ca == '\0') {
150 		*error_r = "ssl_verify_client_cert set, but ssl_ca not";
151 		return FALSE;
152 	}
153 
154 	/* Now explode the ssl_options string into individual flags */
155 	/* First set them all to defaults */
156 	set->parsed_opts.compression = FALSE;
157 	set->parsed_opts.tickets = TRUE;
158 
159 	/* Then modify anything specified in the string */
160 	const char **opts = t_strsplit_spaces(set->ssl_options, ", ");
161 	const char *opt;
162 	while ((opt = *opts++) != NULL) {
163 		if (strcasecmp(opt, "compression") == 0) {
164 			set->parsed_opts.compression = TRUE;
165 		} else if (strcasecmp(opt, "no_compression") == 0) {
166 #ifdef CONFIG_BINARY
167 			i_warning("DEPRECATED: no_compression is default, "
168 				  "so it is redundant in ssl_options");
169 #endif
170 		} else if (strcasecmp(opt, "no_ticket") == 0) {
171 			set->parsed_opts.tickets = FALSE;
172 		} else {
173 			*error_r = t_strdup_printf("ssl_options: unknown flag: '%s'",
174 						   opt);
175 			return FALSE;
176 		}
177 	}
178 
179 #ifndef HAVE_SSL_CTX_SET1_CURVES_LIST
180 	if (*set->ssl_curve_list != '\0') {
181 		*error_r = "ssl_curve_list is set, but the linked openssl "
182 			   "version does not support it";
183 		return FALSE;
184 	}
185 #endif
186 
187 	return TRUE;
188 #endif
189 }
190 /* </settings checks> */
191 
192 const struct master_service_ssl_settings *
master_service_ssl_settings_get(struct master_service * service)193 master_service_ssl_settings_get(struct master_service *service)
194 {
195 	return master_service_ssl_settings_get_from_parser(service->set_parser);
196 }
197 
198 const struct master_service_ssl_settings *
master_service_ssl_settings_get_from_parser(struct setting_parser_context * set_parser)199 master_service_ssl_settings_get_from_parser(struct setting_parser_context *set_parser)
200 {
201 	void **sets;
202 
203 	sets = settings_parser_get_list(set_parser);
204 	return sets[1];
205 }
206 
207 const struct master_service_ssl_server_settings *
master_service_ssl_server_settings_get(struct master_service * service)208 master_service_ssl_server_settings_get(struct master_service *service)
209 {
210 	void **sets;
211 
212 	i_assert(service->want_ssl_server);
213 	sets = settings_parser_get_list(service->set_parser);
214 	return sets[2];
215 }
216 
master_service_ssl_common_settings_to_iostream_set(const struct master_service_ssl_settings * ssl_set,pool_t pool,struct ssl_iostream_settings * set_r)217 static void master_service_ssl_common_settings_to_iostream_set(
218 	const struct master_service_ssl_settings *ssl_set, pool_t pool,
219 	struct ssl_iostream_settings *set_r)
220 {
221 	i_zero(set_r);
222 	set_r->min_protocol = p_strdup(pool, ssl_set->ssl_min_protocol);
223 	set_r->cipher_list = p_strdup(pool, ssl_set->ssl_cipher_list);
224 	/* leave NULL if empty - let library decide */
225 	set_r->ciphersuites = p_strdup_empty(pool, ssl_set->ssl_cipher_suites);
226 	/* NOTE: It's a bit questionable whether ssl_ca should be used for
227 	   clients. But at least for now it's needed for login-proxy. */
228 	set_r->ca = p_strdup_empty(pool, ssl_set->ssl_ca);
229 
230 	set_r->crypto_device = p_strdup(pool, ssl_set->ssl_crypto_device);
231 	set_r->cert_username_field = p_strdup(pool, ssl_set->ssl_cert_username_field);
232 
233 	set_r->verbose = ssl_set->verbose_ssl;
234 	set_r->verbose_invalid_cert = ssl_set->verbose_ssl;
235 	set_r->skip_crl_check = !ssl_set->ssl_require_crl;
236 	set_r->prefer_server_ciphers = ssl_set->ssl_prefer_server_ciphers;
237 	set_r->compression = ssl_set->parsed_opts.compression;
238 	set_r->tickets = ssl_set->parsed_opts.tickets;
239 	set_r->curve_list = p_strdup(pool, ssl_set->ssl_curve_list);
240 }
241 
master_service_ssl_client_settings_to_iostream_set(const struct master_service_ssl_settings * ssl_set,pool_t pool,struct ssl_iostream_settings * set_r)242 void master_service_ssl_client_settings_to_iostream_set(
243 	const struct master_service_ssl_settings *ssl_set, pool_t pool,
244 	struct ssl_iostream_settings *set_r)
245 {
246 	master_service_ssl_common_settings_to_iostream_set(ssl_set, pool, set_r);
247 
248 	set_r->ca_file = p_strdup_empty(pool, ssl_set->ssl_client_ca_file);
249 	set_r->ca_dir = p_strdup_empty(pool, ssl_set->ssl_client_ca_dir);
250 	set_r->cert.cert = p_strdup_empty(pool, ssl_set->ssl_client_cert);
251 	set_r->cert.key = p_strdup_empty(pool, ssl_set->ssl_client_key);
252 	set_r->verify_remote_cert = ssl_set->ssl_client_require_valid_cert;
253 	set_r->allow_invalid_cert = !set_r->verify_remote_cert;
254 }
255 
master_service_ssl_server_settings_to_iostream_set(const struct master_service_ssl_settings * ssl_set,const struct master_service_ssl_server_settings * ssl_server_set,pool_t pool,struct ssl_iostream_settings * set_r)256 void master_service_ssl_server_settings_to_iostream_set(
257 	const struct master_service_ssl_settings *ssl_set,
258 	const struct master_service_ssl_server_settings *ssl_server_set,
259 	pool_t pool, struct ssl_iostream_settings *set_r)
260 {
261 	master_service_ssl_common_settings_to_iostream_set(ssl_set, pool, set_r);
262 
263 	set_r->cert.cert = p_strdup(pool, ssl_server_set->ssl_cert);
264 	set_r->cert.key = p_strdup(pool, ssl_server_set->ssl_key);
265 	set_r->cert.key_password = p_strdup(pool, ssl_server_set->ssl_key_password);
266 	if (ssl_server_set->ssl_alt_cert != NULL &&
267 	    *ssl_server_set->ssl_alt_cert != '\0') {
268 		set_r->alt_cert.cert = p_strdup(pool, ssl_server_set->ssl_alt_cert);
269 		set_r->alt_cert.key = p_strdup(pool, ssl_server_set->ssl_alt_key);
270 		set_r->alt_cert.key_password = p_strdup(pool, ssl_server_set->ssl_key_password);
271 	}
272 	set_r->dh = p_strdup(pool, ssl_server_set->ssl_dh);
273 	set_r->verify_remote_cert = ssl_set->ssl_verify_client_cert;
274 	set_r->allow_invalid_cert = !set_r->verify_remote_cert;
275 }
276