1 /* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
2
3 #include "lib.h"
4 #include "module-dir.h"
5 #include "iostream-ssl-private.h"
6
7 #define OFFSET(name) offsetof(struct ssl_iostream_settings, name)
8 static const size_t ssl_iostream_settings_string_offsets[] = {
9 OFFSET(min_protocol),
10 OFFSET(cipher_list),
11 OFFSET(ciphersuites),
12 OFFSET(curve_list),
13 OFFSET(ca),
14 OFFSET(ca_file),
15 OFFSET(ca_dir),
16 OFFSET(cert.cert),
17 OFFSET(cert.key),
18 OFFSET(cert.key_password),
19 OFFSET(alt_cert.cert),
20 OFFSET(alt_cert.key),
21 OFFSET(alt_cert.key_password),
22 OFFSET(dh),
23 OFFSET(cert_username_field),
24 OFFSET(crypto_device),
25 };
26
27 static bool ssl_module_loaded = FALSE;
28 #ifdef HAVE_SSL
29 static struct module *ssl_module = NULL;
30 #endif
31 static const struct iostream_ssl_vfuncs *ssl_vfuncs = NULL;
32
33 #ifdef HAVE_SSL
ssl_module_unload(void)34 static void ssl_module_unload(void)
35 {
36 ssl_iostream_context_cache_free();
37 module_dir_unload(&ssl_module);
38 }
39 #endif
40
iostream_ssl_module_init(const struct iostream_ssl_vfuncs * vfuncs)41 void iostream_ssl_module_init(const struct iostream_ssl_vfuncs *vfuncs)
42 {
43 ssl_vfuncs = vfuncs;
44 ssl_module_loaded = TRUE;
45 }
46
ssl_module_load(const char ** error_r)47 int ssl_module_load(const char **error_r)
48 {
49 #ifdef HAVE_SSL
50 const char *plugin_name = "ssl_iostream_openssl";
51 struct module_dir_load_settings mod_set;
52
53 i_zero(&mod_set);
54 mod_set.abi_version = DOVECOT_ABI_VERSION;
55 mod_set.setting_name = "<built-in lib-ssl-iostream lookup>";
56 mod_set.require_init_funcs = TRUE;
57 ssl_module = module_dir_load(MODULE_DIR, plugin_name, &mod_set);
58 if (module_dir_try_load_missing(&ssl_module, MODULE_DIR, plugin_name,
59 &mod_set, error_r) < 0)
60 return -1;
61 module_dir_init(ssl_module);
62 if (!ssl_module_loaded) {
63 *error_r = t_strdup_printf(
64 "%s didn't call iostream_ssl_module_init() - SSL not initialized",
65 plugin_name);
66 module_dir_unload(&ssl_module);
67 return -1;
68 }
69
70 /* Destroy SSL module after (most of) the others. Especially lib-fs
71 backends may still want to access SSL module in their own
72 atexit-callbacks. */
73 lib_atexit_priority(ssl_module_unload, LIB_ATEXIT_PRIORITY_LOW);
74 return 0;
75 #else
76 *error_r = "SSL support not compiled in";
77 return -1;
78 #endif
79 }
80
io_stream_ssl_global_init(const struct ssl_iostream_settings * set,const char ** error_r)81 int io_stream_ssl_global_init(const struct ssl_iostream_settings *set,
82 const char **error_r)
83 {
84 return ssl_vfuncs->global_init(set, error_r);
85 }
86
ssl_iostream_context_init_client(const struct ssl_iostream_settings * set,struct ssl_iostream_context ** ctx_r,const char ** error_r)87 int ssl_iostream_context_init_client(const struct ssl_iostream_settings *set,
88 struct ssl_iostream_context **ctx_r,
89 const char **error_r)
90 {
91 struct ssl_iostream_settings set_copy = *set;
92
93 /* ensure this is set to TRUE */
94 set_copy.verify_remote_cert = TRUE;
95
96 if (!ssl_module_loaded) {
97 if (ssl_module_load(error_r) < 0)
98 return -1;
99 }
100 if (io_stream_ssl_global_init(&set_copy, error_r) < 0)
101 return -1;
102 return ssl_vfuncs->context_init_client(&set_copy, ctx_r, error_r);
103 }
104
ssl_iostream_context_init_server(const struct ssl_iostream_settings * set,struct ssl_iostream_context ** ctx_r,const char ** error_r)105 int ssl_iostream_context_init_server(const struct ssl_iostream_settings *set,
106 struct ssl_iostream_context **ctx_r,
107 const char **error_r)
108 {
109 if (!ssl_module_loaded) {
110 if (ssl_module_load(error_r) < 0)
111 return -1;
112 }
113 if (io_stream_ssl_global_init(set, error_r) < 0)
114 return -1;
115 return ssl_vfuncs->context_init_server(set, ctx_r, error_r);
116 }
117
ssl_iostream_context_ref(struct ssl_iostream_context * ctx)118 void ssl_iostream_context_ref(struct ssl_iostream_context *ctx)
119 {
120 ssl_vfuncs->context_ref(ctx);
121 }
122
ssl_iostream_context_unref(struct ssl_iostream_context ** _ctx)123 void ssl_iostream_context_unref(struct ssl_iostream_context **_ctx)
124 {
125 struct ssl_iostream_context *ctx = *_ctx;
126
127 if (*_ctx == NULL)
128 return;
129 *_ctx = NULL;
130 ssl_vfuncs->context_unref(ctx);
131 }
132
io_stream_create_ssl_client(struct ssl_iostream_context * ctx,const char * host,const struct ssl_iostream_settings * set,struct istream ** input,struct ostream ** output,struct ssl_iostream ** iostream_r,const char ** error_r)133 int io_stream_create_ssl_client(struct ssl_iostream_context *ctx, const char *host,
134 const struct ssl_iostream_settings *set,
135 struct istream **input, struct ostream **output,
136 struct ssl_iostream **iostream_r,
137 const char **error_r)
138 {
139 struct ssl_iostream_settings set_copy = *set;
140 set_copy.verify_remote_cert = TRUE;
141 return ssl_vfuncs->create(ctx, host, &set_copy, input, output,
142 iostream_r, error_r);
143 }
144
io_stream_create_ssl_server(struct ssl_iostream_context * ctx,const struct ssl_iostream_settings * set,struct istream ** input,struct ostream ** output,struct ssl_iostream ** iostream_r,const char ** error_r)145 int io_stream_create_ssl_server(struct ssl_iostream_context *ctx,
146 const struct ssl_iostream_settings *set,
147 struct istream **input, struct ostream **output,
148 struct ssl_iostream **iostream_r,
149 const char **error_r)
150 {
151 return ssl_vfuncs->create(ctx, NULL, set, input, output,
152 iostream_r, error_r);
153 }
154
ssl_iostream_unref(struct ssl_iostream ** _ssl_io)155 void ssl_iostream_unref(struct ssl_iostream **_ssl_io)
156 {
157 struct ssl_iostream *ssl_io = *_ssl_io;
158
159 *_ssl_io = NULL;
160 ssl_vfuncs->unref(ssl_io);
161 }
162
ssl_iostream_destroy(struct ssl_iostream ** _ssl_io)163 void ssl_iostream_destroy(struct ssl_iostream **_ssl_io)
164 {
165 struct ssl_iostream *ssl_io;
166
167 if (_ssl_io == NULL || *_ssl_io == NULL)
168 return;
169
170 ssl_io = *_ssl_io;
171 *_ssl_io = NULL;
172 ssl_vfuncs->destroy(ssl_io);
173 }
174
ssl_iostream_set_log_prefix(struct ssl_iostream * ssl_io,const char * prefix)175 void ssl_iostream_set_log_prefix(struct ssl_iostream *ssl_io,
176 const char *prefix)
177 {
178 ssl_vfuncs->set_log_prefix(ssl_io, prefix);
179 }
180
ssl_iostream_handshake(struct ssl_iostream * ssl_io)181 int ssl_iostream_handshake(struct ssl_iostream *ssl_io)
182 {
183 return ssl_vfuncs->handshake(ssl_io);
184 }
185
ssl_iostream_set_handshake_callback(struct ssl_iostream * ssl_io,ssl_iostream_handshake_callback_t * callback,void * context)186 void ssl_iostream_set_handshake_callback(struct ssl_iostream *ssl_io,
187 ssl_iostream_handshake_callback_t *callback,
188 void *context)
189 {
190 ssl_vfuncs->set_handshake_callback(ssl_io, callback, context);
191 }
192
ssl_iostream_set_sni_callback(struct ssl_iostream * ssl_io,ssl_iostream_sni_callback_t * callback,void * context)193 void ssl_iostream_set_sni_callback(struct ssl_iostream *ssl_io,
194 ssl_iostream_sni_callback_t *callback,
195 void *context)
196 {
197 ssl_vfuncs->set_sni_callback(ssl_io, callback, context);
198 }
199
ssl_iostream_change_context(struct ssl_iostream * ssl_io,struct ssl_iostream_context * ctx)200 void ssl_iostream_change_context(struct ssl_iostream *ssl_io,
201 struct ssl_iostream_context *ctx)
202 {
203 ssl_vfuncs->change_context(ssl_io, ctx);
204 }
205
ssl_iostream_is_handshaked(const struct ssl_iostream * ssl_io)206 bool ssl_iostream_is_handshaked(const struct ssl_iostream *ssl_io)
207 {
208 return ssl_vfuncs->is_handshaked(ssl_io);
209 }
210
ssl_iostream_has_handshake_failed(const struct ssl_iostream * ssl_io)211 bool ssl_iostream_has_handshake_failed(const struct ssl_iostream *ssl_io)
212 {
213 return ssl_vfuncs->has_handshake_failed(ssl_io);
214 }
215
ssl_iostream_has_valid_client_cert(const struct ssl_iostream * ssl_io)216 bool ssl_iostream_has_valid_client_cert(const struct ssl_iostream *ssl_io)
217 {
218 return ssl_vfuncs->has_valid_client_cert(ssl_io);
219 }
220
ssl_iostream_has_broken_client_cert(struct ssl_iostream * ssl_io)221 bool ssl_iostream_has_broken_client_cert(struct ssl_iostream *ssl_io)
222 {
223 return ssl_vfuncs->has_broken_client_cert(ssl_io);
224 }
225
ssl_iostream_cert_match_name(struct ssl_iostream * ssl_io,const char * name,const char ** reason_r)226 bool ssl_iostream_cert_match_name(struct ssl_iostream *ssl_io, const char *name,
227 const char **reason_r)
228 {
229 return ssl_vfuncs->cert_match_name(ssl_io, name, reason_r);
230 }
231
ssl_iostream_check_cert_validity(struct ssl_iostream * ssl_io,const char * host,const char ** error_r)232 int ssl_iostream_check_cert_validity(struct ssl_iostream *ssl_io,
233 const char *host, const char **error_r)
234 {
235 const char *reason;
236
237 if (!ssl_iostream_has_valid_client_cert(ssl_io)) {
238 if (!ssl_iostream_has_broken_client_cert(ssl_io))
239 *error_r = "SSL certificate not received";
240 else {
241 *error_r = t_strdup(ssl_iostream_get_last_error(ssl_io));
242 if (*error_r == NULL)
243 *error_r = "Received invalid SSL certificate";
244 }
245 return -1;
246 } else if (!ssl_iostream_cert_match_name(ssl_io, host, &reason)) {
247 *error_r = t_strdup_printf(
248 "SSL certificate doesn't match expected host name %s: %s",
249 host, reason);
250 return -1;
251 }
252 return 0;
253 }
254
ssl_iostream_get_peer_name(struct ssl_iostream * ssl_io)255 const char *ssl_iostream_get_peer_name(struct ssl_iostream *ssl_io)
256 {
257 return ssl_vfuncs->get_peer_name(ssl_io);
258 }
259
ssl_iostream_get_server_name(struct ssl_iostream * ssl_io)260 const char *ssl_iostream_get_server_name(struct ssl_iostream *ssl_io)
261 {
262 return ssl_vfuncs->get_server_name(ssl_io);
263 }
264
ssl_iostream_get_compression(struct ssl_iostream * ssl_io)265 const char *ssl_iostream_get_compression(struct ssl_iostream *ssl_io)
266 {
267 return ssl_vfuncs->get_compression(ssl_io);
268 }
269
ssl_iostream_get_security_string(struct ssl_iostream * ssl_io)270 const char *ssl_iostream_get_security_string(struct ssl_iostream *ssl_io)
271 {
272 return ssl_vfuncs->get_security_string(ssl_io);
273 }
274
ssl_iostream_get_last_error(struct ssl_iostream * ssl_io)275 const char *ssl_iostream_get_last_error(struct ssl_iostream *ssl_io)
276 {
277 return ssl_vfuncs->get_last_error(ssl_io);
278 }
279
ssl_iostream_settings_dup(pool_t pool,const struct ssl_iostream_settings * old_set)280 struct ssl_iostream_settings *ssl_iostream_settings_dup(pool_t pool,
281 const struct ssl_iostream_settings *old_set)
282 {
283 struct ssl_iostream_settings *new_set;
284
285 new_set = p_new(pool, struct ssl_iostream_settings, 1);
286 ssl_iostream_settings_init_from(pool, new_set, old_set);
287 return new_set;
288 }
289
ssl_iostream_settings_init_from(pool_t pool,struct ssl_iostream_settings * dest,const struct ssl_iostream_settings * src)290 void ssl_iostream_settings_init_from(pool_t pool,
291 struct ssl_iostream_settings *dest,
292 const struct ssl_iostream_settings *src)
293 {
294 unsigned int i;
295
296 *dest = *src;
297 for (i = 0; i < N_ELEMENTS(ssl_iostream_settings_string_offsets); i++) {
298 const size_t offset = ssl_iostream_settings_string_offsets[i];
299 const char *const *src_str = CONST_PTR_OFFSET(src, offset);
300 const char **dest_str = PTR_OFFSET(dest, offset);
301 *dest_str = p_strdup(pool, *src_str);
302 }
303 }
304
ssl_iostream_settings_equals(const struct ssl_iostream_settings * set1,const struct ssl_iostream_settings * set2)305 bool ssl_iostream_settings_equals(const struct ssl_iostream_settings *set1,
306 const struct ssl_iostream_settings *set2)
307 {
308 struct ssl_iostream_settings set1_nonstr, set2_nonstr;
309 unsigned int i;
310
311 set1_nonstr = *set1;
312 set2_nonstr = *set2;
313 for (i = 0; i < N_ELEMENTS(ssl_iostream_settings_string_offsets); i++) {
314 const size_t offset = ssl_iostream_settings_string_offsets[i];
315 const char **str1 = PTR_OFFSET(&set1_nonstr, offset);
316 const char **str2 = PTR_OFFSET(&set2_nonstr, offset);
317
318 if (null_strcmp(*str1, *str2) != 0)
319 return FALSE;
320
321 /* clear away the string pointer from the settings struct */
322 *str1 = NULL;
323 *str2 = NULL;
324 }
325 /* The set*_nonstr no longer have any pointers, so we can compare them
326 directly. */
327 return memcmp(&set1_nonstr, &set2_nonstr, sizeof(set1_nonstr)) == 0;
328 }
329
ssl_iostream_settings_drop_stream_only(struct ssl_iostream_settings * set)330 void ssl_iostream_settings_drop_stream_only(struct ssl_iostream_settings *set)
331 {
332 set->verbose = FALSE;
333 set->verbose_invalid_cert = FALSE;
334 set->allow_invalid_cert = FALSE;
335 }
336
ssl_iostream_get_cipher(struct ssl_iostream * ssl_io,unsigned int * bits_r)337 const char *ssl_iostream_get_cipher(struct ssl_iostream *ssl_io,
338 unsigned int *bits_r)
339 {
340 return ssl_vfuncs->get_cipher(ssl_io, bits_r);
341 }
342
ssl_iostream_get_pfs(struct ssl_iostream * ssl_io)343 const char *ssl_iostream_get_pfs(struct ssl_iostream *ssl_io)
344 {
345 return ssl_vfuncs->get_pfs(ssl_io);
346 }
347
ssl_iostream_get_protocol_name(struct ssl_iostream * ssl_io)348 const char *ssl_iostream_get_protocol_name(struct ssl_iostream *ssl_io)
349 {
350 return ssl_vfuncs->get_protocol_name(ssl_io);
351 }
352