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