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