1 /* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
2 
3 #include "login-common.h"
4 #include "str.h"
5 #include "base64.h"
6 #include "buffer.h"
7 #include "hex-binary.h"
8 #include "ioloop.h"
9 #include "istream.h"
10 #include "write-full.h"
11 #include "strescape.h"
12 #include "str-sanitize.h"
13 #include "anvil-client.h"
14 #include "auth-client.h"
15 #include "iostream-ssl.h"
16 #include "master-service.h"
17 #include "master-service-ssl-settings.h"
18 #include "master-interface.h"
19 #include "master-auth.h"
20 #include "client-common.h"
21 
22 #include <unistd.h>
23 
24 #define ERR_TOO_MANY_USERIP_CONNECTIONS \
25 	"Maximum number of connections from user+IP exceeded " \
26 	"(mail_max_userip_connections=%u)"
27 
28 struct anvil_request {
29 	struct client *client;
30 	unsigned int auth_pid;
31 	unsigned char cookie[MASTER_AUTH_COOKIE_SIZE];
32 };
33 
34 static bool
sasl_server_filter_mech(struct client * client,struct auth_mech_desc * mech)35 sasl_server_filter_mech(struct client *client, struct auth_mech_desc *mech)
36 {
37 	if (client->v.sasl_filter_mech != NULL &&
38 	    !client->v.sasl_filter_mech(client, mech))
39 		return FALSE;
40 	return ((mech->flags & MECH_SEC_ANONYMOUS) == 0 ||
41 		login_binary->anonymous_login_acceptable);
42 }
43 
44 const struct auth_mech_desc *
sasl_server_get_advertised_mechs(struct client * client,unsigned int * count_r)45 sasl_server_get_advertised_mechs(struct client *client, unsigned int *count_r)
46 {
47 	const struct auth_mech_desc *mech;
48 	struct auth_mech_desc *ret_mech;
49 	unsigned int i, j, count;
50 
51 	mech = auth_client_get_available_mechs(auth_client, &count);
52 	if (count == 0 || (!client->secured &&
53 			   strcmp(client->ssl_set->ssl, "required") == 0)) {
54 		*count_r = 0;
55 		return NULL;
56 	}
57 
58 	ret_mech = t_new(struct auth_mech_desc, count);
59 	for (i = j = 0; i < count; i++) {
60 		struct auth_mech_desc fmech = mech[i];
61 
62 		if (!sasl_server_filter_mech(client, &fmech))
63 			continue;
64 
65 		/* a) transport is secured
66 		   b) auth mechanism isn't plaintext
67 		   c) we allow insecure authentication
68 		*/
69 		if ((fmech.flags & MECH_SEC_PRIVATE) == 0 &&
70 		    (client->secured || !client->set->disable_plaintext_auth ||
71 		     (fmech.flags & MECH_SEC_PLAINTEXT) == 0))
72 			ret_mech[j++] = fmech;
73 	}
74 	*count_r = j;
75 	return ret_mech;
76 }
77 
78 const struct auth_mech_desc *
sasl_server_find_available_mech(struct client * client,const char * name)79 sasl_server_find_available_mech(struct client *client, const char *name)
80 {
81 	const struct auth_mech_desc *mech;
82 	struct auth_mech_desc fmech;
83 
84 	mech = auth_client_find_mech(auth_client, name);
85 	if (mech == NULL)
86 		return NULL;
87 
88 	fmech = *mech;
89 	if (!sasl_server_filter_mech(client, &fmech))
90 		return NULL;
91 	if (memcmp(&fmech, mech, sizeof(fmech)) != 0) {
92 		struct auth_mech_desc *nmech = t_new(struct auth_mech_desc, 1);
93 
94 		*nmech = fmech;
95 		mech = nmech;
96 	}
97 	return mech;
98 }
99 
100 static enum auth_request_flags
client_get_auth_flags(struct client * client)101 client_get_auth_flags(struct client *client)
102 {
103         enum auth_request_flags auth_flags = 0;
104 
105 	if (client->ssl_iostream != NULL &&
106 	    ssl_iostream_has_valid_client_cert(client->ssl_iostream))
107 		auth_flags |= AUTH_REQUEST_FLAG_VALID_CLIENT_CERT;
108 	if (client->tls || client->proxied_ssl)
109 		auth_flags |= AUTH_REQUEST_FLAG_TRANSPORT_SECURITY_TLS;
110 	if (client->secured)
111 		auth_flags |= AUTH_REQUEST_FLAG_SECURED;
112 	if (login_binary->sasl_support_final_reply)
113 		auth_flags |= AUTH_REQUEST_FLAG_SUPPORT_FINAL_RESP;
114 	return auth_flags;
115 }
116 
117 static void ATTR_NULL(3, 4)
call_client_callback(struct client * client,enum sasl_server_reply reply,const char * data,const char * const * args)118 call_client_callback(struct client *client, enum sasl_server_reply reply,
119 		     const char *data, const char *const *args)
120 {
121 	sasl_server_callback_t *sasl_callback;
122 
123 	i_assert(reply != SASL_SERVER_REPLY_CONTINUE);
124 
125 	sasl_callback = client->sasl_callback;
126 	client->sasl_callback = NULL;
127 
128 	sasl_callback(client, reply, data, args);
129 	/* NOTE: client may be destroyed now */
130 }
131 
132 static void
master_auth_callback(const struct master_auth_reply * reply,void * context)133 master_auth_callback(const struct master_auth_reply *reply, void *context)
134 {
135 	struct client *client = context;
136 	enum sasl_server_reply sasl_reply = SASL_SERVER_REPLY_MASTER_FAILED;
137 	const char *data = NULL;
138 
139 	client->master_tag = 0;
140 	client->authenticating = FALSE;
141 	if (reply != NULL) {
142 		switch (reply->status) {
143 		case MASTER_AUTH_STATUS_OK:
144 			sasl_reply = SASL_SERVER_REPLY_SUCCESS;
145 			break;
146 		case MASTER_AUTH_STATUS_INTERNAL_ERROR:
147 			sasl_reply = SASL_SERVER_REPLY_MASTER_FAILED;
148 			break;
149 		}
150 		client->mail_pid = reply->mail_pid;
151 	} else {
152 		auth_client_send_cancel(auth_client, client->master_auth_id);
153 	}
154 	call_client_callback(client, sasl_reply, data, NULL);
155 }
156 
master_send_request(struct anvil_request * anvil_request)157 static int master_send_request(struct anvil_request *anvil_request)
158 {
159 	struct client *client = anvil_request->client;
160 	struct master_auth_request_params params;
161 	struct master_auth_request req;
162 	const unsigned char *data;
163 	size_t size;
164 	buffer_t *buf;
165 	const char *session_id = client_get_session_id(client);
166 	int fd;
167 	bool close_fd;
168 
169 	if (client_get_plaintext_fd(client, &fd, &close_fd) < 0)
170 		return -1;
171 
172 	i_zero(&req);
173 	req.auth_pid = anvil_request->auth_pid;
174 	req.auth_id = client->master_auth_id;
175 	req.local_ip = client->local_ip;
176 	req.remote_ip = client->ip;
177 	req.local_port = client->local_port;
178 	req.remote_port = client->remote_port;
179 	req.client_pid = getpid();
180 	if (client->ssl_iostream != NULL &&
181 	    ssl_iostream_get_compression(client->ssl_iostream) != NULL)
182 		req.flags |= MAIL_AUTH_REQUEST_FLAG_TLS_COMPRESSION;
183 	if (client->secured)
184 		req.flags |= MAIL_AUTH_REQUEST_FLAG_CONN_SECURED;
185 	if (client->ssl_secured)
186 		req.flags |= MAIL_AUTH_REQUEST_FLAG_CONN_SSL_SECURED;
187 	memcpy(req.cookie, anvil_request->cookie, sizeof(req.cookie));
188 
189 	buf = t_buffer_create(256);
190 	/* session ID */
191 	buffer_append(buf, session_id, strlen(session_id)+1);
192 	/* protocol specific data (e.g. IMAP tag) */
193 	buffer_append(buf, client->master_data_prefix,
194 		      client->master_data_prefix_len);
195 	/* buffered client input */
196 	data = i_stream_get_data(client->input, &size);
197 	buffer_append(buf, data, size);
198 	req.data_size = buf->used;
199 	i_stream_skip(client->input, size);
200 
201 	client->auth_finished = ioloop_time;
202 
203 	i_zero(&params);
204 	params.client_fd = fd;
205 	params.socket_path = client->postlogin_socket_path;
206 	params.request = req;
207 	params.data = buf->data;
208 	master_auth_request_full(master_auth, &params, master_auth_callback,
209 				 client, &client->master_tag);
210 	if (close_fd)
211 		i_close_fd(&fd);
212 	return 0;
213 }
214 
215 static void ATTR_NULL(1)
anvil_lookup_callback(const char * reply,void * context)216 anvil_lookup_callback(const char *reply, void *context)
217 {
218 	struct anvil_request *req = context;
219 	struct client *client = req->client;
220 	const struct login_settings *set = client->set;
221 	const char *errmsg;
222 	unsigned int conn_count;
223 	int ret;
224 
225 	client->anvil_query = NULL;
226 	client->anvil_request = NULL;
227 
228 	conn_count = 0;
229 	if (reply != NULL && str_to_uint(reply, &conn_count) < 0)
230 		i_fatal("Received invalid reply from anvil: %s", reply);
231 
232 	/* reply=NULL if we didn't need to do anvil lookup,
233 	   or if the anvil lookup failed. allow failed anvil lookups in. */
234 	if (reply == NULL || conn_count < set->mail_max_userip_connections) {
235 		ret = master_send_request(req);
236 		errmsg = NULL; /* client will see internal error */
237 	} else {
238 		ret = -1;
239 		errmsg = t_strdup_printf(ERR_TOO_MANY_USERIP_CONNECTIONS,
240 					 set->mail_max_userip_connections);
241 	}
242 	if (ret < 0) {
243 		client->authenticating = FALSE;
244 		auth_client_send_cancel(auth_client, client->master_auth_id);
245 		call_client_callback(client, SASL_SERVER_REPLY_MASTER_FAILED,
246 				     errmsg, NULL);
247 	}
248 	i_free(req);
249 }
250 
251 static void
anvil_check_too_many_connections(struct client * client,struct auth_client_request * request)252 anvil_check_too_many_connections(struct client *client,
253 				 struct auth_client_request *request)
254 {
255 	struct anvil_request *req;
256 	const char *query, *cookie;
257 	buffer_t buf;
258 
259 	req = i_new(struct anvil_request, 1);
260 	req->client = client;
261 	req->auth_pid = auth_client_request_get_server_pid(request);
262 
263 	buffer_create_from_data(&buf, req->cookie, sizeof(req->cookie));
264 	cookie = auth_client_request_get_cookie(request);
265 	if (strlen(cookie) == MASTER_AUTH_COOKIE_SIZE*2)
266 		(void)hex_to_binary(cookie, &buf);
267 
268 	if (client->virtual_user == NULL ||
269 	    client->set->mail_max_userip_connections == 0) {
270 		anvil_lookup_callback(NULL, req);
271 		return;
272 	}
273 
274 	query = t_strconcat("LOOKUP\t", login_binary->protocol, "/",
275 			    net_ip2addr(&client->ip), "/",
276 			    str_tabescape(client->virtual_user), NULL);
277 	client->anvil_request = req;
278 	client->anvil_query =
279 		anvil_client_query(anvil, query, anvil_lookup_callback, req);
280 }
281 
282 static bool
sasl_server_check_login(struct client * client)283 sasl_server_check_login(struct client *client)
284 {
285 	if (client->v.sasl_check_login != NULL &&
286 	    !client->v.sasl_check_login(client))
287 		return FALSE;
288 	if (client->auth_anonymous &&
289 	    !login_binary->anonymous_login_acceptable) {
290 		sasl_server_auth_failed(client,
291 			"Anonymous login denied",
292 			AUTH_CLIENT_FAIL_CODE_ANONYMOUS_DENIED);
293 		return FALSE;
294 	}
295 	return TRUE;
296 }
297 
args_parse_user(struct client * client,const char * arg)298 static bool args_parse_user(struct client *client, const char *arg)
299 {
300 	if (str_begins(arg, "user=")) {
301 		i_free(client->virtual_user);
302 		i_free_and_null(client->virtual_user_orig);
303 		i_free_and_null(client->virtual_auth_user);
304 		client->virtual_user = i_strdup(arg + 5);
305 		event_add_str(client->event, "user", client->virtual_user);
306 	} else if (str_begins(arg, "original_user=")) {
307 		i_free(client->virtual_user_orig);
308 		client->virtual_user_orig = i_strdup(arg + 14);
309 	} else if (str_begins(arg, "auth_user=")) {
310 		i_free(client->virtual_auth_user);
311 		client->virtual_auth_user = i_strdup(arg + 10);
312 	} else {
313 		return FALSE;
314 	}
315 	return TRUE;
316 }
317 
318 static void
authenticate_callback(struct auth_client_request * request,enum auth_request_status status,const char * data_base64,const char * const * args,void * context)319 authenticate_callback(struct auth_client_request *request,
320 		      enum auth_request_status status, const char *data_base64,
321 		      const char *const *args, void *context)
322 {
323 	struct client *client = context;
324 	unsigned int i;
325 	bool nologin;
326 
327 	if (!client->authenticating) {
328 		/* client aborted */
329 		i_assert(status < 0);
330 		return;
331 	}
332 	client->auth_waiting = FALSE;
333 
334 	i_assert(client->auth_request == request);
335 	switch (status) {
336 	case AUTH_REQUEST_STATUS_CONTINUE:
337 		/* continue */
338 		client->sasl_callback(client, SASL_SERVER_REPLY_CONTINUE,
339 				      data_base64, NULL);
340 		break;
341 	case AUTH_REQUEST_STATUS_OK:
342 		client->master_auth_id = auth_client_request_get_id(request);
343 		client->auth_request = NULL;
344 		client->auth_successes++;
345 		client->auth_passdb_args = p_strarray_dup(client->pool, args);
346 		client->postlogin_socket_path = NULL;
347 
348 		nologin = FALSE;
349 		for (i = 0; args[i] != NULL; i++) {
350 			if (args_parse_user(client, args[i]))
351 				;
352 			else if (str_begins(args[i], "postlogin_socket=")) {
353 				client->postlogin_socket_path =
354 					p_strdup(client->pool, args[i] + 17);
355 			} else if (strcmp(args[i], "nologin") == 0 ||
356 				   strcmp(args[i], "proxy") == 0) {
357 				/* user can't login */
358 				nologin = TRUE;
359 			} else if (strcmp(args[i], "anonymous") == 0 ) {
360 				client->auth_anonymous = TRUE;
361 			} else if (str_begins(args[i], "resp=") &&
362 				   login_binary->sasl_support_final_reply) {
363 				client->sasl_final_resp =
364 					p_strdup(client->pool, args[i] + 5);
365 			}
366 		}
367 
368 		if (nologin) {
369 			client->authenticating = FALSE;
370 			call_client_callback(client, SASL_SERVER_REPLY_SUCCESS,
371 					     NULL, args);
372 		} else if (!sasl_server_check_login(client)) {
373 			i_assert(!client->authenticating);
374 		} else {
375 			anvil_check_too_many_connections(client, request);
376 		}
377 		break;
378 	case AUTH_REQUEST_STATUS_INTERNAL_FAIL:
379 		client->auth_process_comm_fail = TRUE;
380 		/* fall through */
381 	case AUTH_REQUEST_STATUS_FAIL:
382 	case AUTH_REQUEST_STATUS_ABORT:
383 		client->auth_request = NULL;
384 
385 		if (args != NULL) {
386 			/* parse our username if it's there */
387 			for (i = 0; args[i] != NULL; i++)
388 				(void)args_parse_user(client, args[i]);
389 		}
390 
391 		client->authenticating = FALSE;
392 		call_client_callback(client, SASL_SERVER_REPLY_AUTH_FAILED,
393 				     NULL, args);
394 		break;
395 	}
396 }
397 
get_cert_username(struct client * client,const char ** username_r,const char ** error_r)398 static bool get_cert_username(struct client *client, const char **username_r,
399 			      const char **error_r)
400 {
401 	/* this was proxied connection, so we use the name here */
402 	if (client->client_cert_common_name != NULL) {
403 		*username_r = client->client_cert_common_name;
404 		return TRUE;
405 	}
406 
407 	/* no SSL */
408 	if (client->ssl_iostream == NULL) {
409 		*username_r = NULL;
410 		return TRUE;
411 	}
412 
413 	/* no client certificate */
414 	if (!ssl_iostream_has_valid_client_cert(client->ssl_iostream)) {
415 		*username_r = NULL;
416 		return TRUE;
417 	}
418 
419 	/* get peer name */
420 	const char *username = ssl_iostream_get_peer_name(client->ssl_iostream);
421 
422 	/* if we wanted peer name, but it was not there, fail */
423 	if (client->set->auth_ssl_username_from_cert &&
424 	    (username == NULL || *username == '\0')) {
425 		if (client->set->auth_ssl_require_client_cert) {
426 			*error_r = "Missing username in certificate";
427 			return FALSE;
428 		}
429 	}
430 
431 	*username_r = username;
432 	return TRUE;
433 }
434 
sasl_server_auth_begin(struct client * client,const char * service,const char * mech_name,bool private,const char * initial_resp_base64,sasl_server_callback_t * callback)435 void sasl_server_auth_begin(struct client *client,
436 			    const char *service, const char *mech_name,
437 			    bool private, const char *initial_resp_base64,
438 			    sasl_server_callback_t *callback)
439 {
440 	struct auth_request_info info;
441 	const struct auth_mech_desc *mech;
442 	const char *error;
443 
444 	i_assert(auth_client_is_connected(auth_client));
445 
446 	client->auth_attempts++;
447 	client->authenticating = TRUE;
448 	client->master_auth_id = 0;
449 	if (client->auth_first_started == 0)
450 		client->auth_first_started = ioloop_time;
451 	i_free(client->auth_mech_name);
452 	client->auth_mech_name = str_ucase(i_strdup(mech_name));
453 	client->auth_anonymous = FALSE;
454 	client->sasl_callback = callback;
455 
456 	mech = sasl_server_find_available_mech(client, mech_name);
457 	if (mech == NULL ||
458 	    ((mech->flags & MECH_SEC_PRIVATE) != 0 && !private)) {
459 		sasl_server_auth_failed(client,
460 			"Unsupported authentication mechanism.",
461 			AUTH_CLIENT_FAIL_CODE_MECH_INVALID);
462 		return;
463 	}
464 
465 	i_assert(!private || (mech->flags & MECH_SEC_PRIVATE) != 0);
466 
467 	if (!client->secured && client->set->disable_plaintext_auth &&
468 	    (mech->flags & MECH_SEC_PLAINTEXT) != 0) {
469 		sasl_server_auth_failed(client,
470 			"Plaintext authentication disabled.",
471 			 AUTH_CLIENT_FAIL_CODE_MECH_SSL_REQUIRED);
472 		return;
473 	}
474 
475 	i_zero(&info);
476 	info.mech = mech->name;
477 	info.service = service;
478 	info.session_id = client_get_session_id(client);
479 
480 	if (!get_cert_username(client, &info.cert_username, &error)) {
481 		e_error(client->event,
482 			"Cannot get username from certificate: %s", error);
483 		sasl_server_auth_failed(client,
484 			"Unable to validate certificate",
485 			AUTH_CLIENT_FAIL_CODE_AUTHZFAILED);
486 		return;
487 	}
488 
489 	if (client->ssl_iostream != NULL) {
490 		info.cert_username = ssl_iostream_get_peer_name(client->ssl_iostream);
491 		info.ssl_cipher = ssl_iostream_get_cipher(client->ssl_iostream,
492 							 &info.ssl_cipher_bits);
493 		info.ssl_pfs = ssl_iostream_get_pfs(client->ssl_iostream);
494 		info.ssl_protocol =
495 			ssl_iostream_get_protocol_name(client->ssl_iostream);
496 	}
497 	info.flags = client_get_auth_flags(client);
498 	info.local_ip = client->local_ip;
499 	info.remote_ip = client->ip;
500 	info.local_port = client->local_port;
501 	info.local_name = client->local_name;
502 	info.remote_port = client->remote_port;
503 	info.real_local_ip = client->real_local_ip;
504 	info.real_remote_ip = client->real_remote_ip;
505 	info.real_local_port = client->real_local_port;
506 	info.real_remote_port = client->real_remote_port;
507 	if (client->client_id != NULL)
508 		info.client_id = str_c(client->client_id);
509 	if (client->forward_fields != NULL)
510 		info.forward_fields = str_c(client->forward_fields);
511 	info.initial_resp_base64 = initial_resp_base64;
512 
513 	client->auth_request =
514 		auth_client_request_new(auth_client, &info,
515 					authenticate_callback, client);
516 }
517 
518 static void ATTR_NULL(2, 3)
sasl_server_auth_cancel(struct client * client,const char * reason,const char * code,enum sasl_server_reply reply)519 sasl_server_auth_cancel(struct client *client, const char *reason,
520 			const char *code, enum sasl_server_reply reply)
521 {
522 	i_assert(client->authenticating);
523 
524 	if (client->set->auth_verbose && reason != NULL) {
525 		const char *auth_name =
526 			str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
527 		e_info(client->event, "Authenticate %s failed: %s",
528 		       auth_name, reason);
529 	}
530 
531 	client->authenticating = FALSE;
532 	if (client->auth_request != NULL)
533 		auth_client_request_abort(&client->auth_request, reason);
534 	if (client->master_auth_id != 0)
535 		auth_client_send_cancel(auth_client, client->master_auth_id);
536 
537 	if (code != NULL) {
538 		const char *args[2];
539 
540 		args[0] = t_strconcat("code=", code, NULL);
541 		args[1] = NULL;
542 		call_client_callback(client, reply, reason, args);
543 		return;
544 	}
545 
546 	call_client_callback(client, reply, reason, NULL);
547 }
548 
sasl_server_auth_failed(struct client * client,const char * reason,const char * code)549 void sasl_server_auth_failed(struct client *client, const char *reason,
550 	const char *code)
551 {
552 	sasl_server_auth_cancel(client, reason, code, SASL_SERVER_REPLY_AUTH_FAILED);
553 }
554 
sasl_server_auth_abort(struct client * client)555 void sasl_server_auth_abort(struct client *client)
556 {
557 	client->auth_try_aborted = TRUE;
558 	if (client->anvil_query != NULL) {
559 		anvil_client_query_abort(anvil, &client->anvil_query);
560 		i_free(client->anvil_request);
561 	}
562 	sasl_server_auth_cancel(client, NULL, NULL, SASL_SERVER_REPLY_AUTH_ABORTED);
563 }
564