sasl-server.c revision b6fbc235f981b10333403e2fd6d333fd351c7a3c
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen "Maximum number of connections from user+IP exceeded " \
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen "(mail_max_userip_connections=%u)"
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen unsigned char cookie[MASTER_AUTH_COOKIE_SIZE];
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainensasl_server_get_advertised_mechs(struct client *client, unsigned int *count_r)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen unsigned int i, j, count;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mech = auth_client_get_available_mechs(auth_client, &count);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen strcmp(client->ssl_set->ssl, "required") == 0)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret_mech = t_new(struct auth_mech_desc, count);
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen for (i = j = 0; i < count; i++) {
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen /* a) transport is secured
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen b) auth mechanism isn't plaintext
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen c) we allow insecure authentication
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen (client->secured || !client->set->disable_plaintext_auth ||
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen ssl_proxy_has_valid_client_cert(client->ssl_proxy))
c3b36993785d9567a63bdad1933031060c9460cfTimo Sirainen auth_flags |= AUTH_REQUEST_FLAG_VALID_CLIENT_CERT;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_flags |= AUTH_REQUEST_FLAG_SUPPORT_FINAL_RESP;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainencall_client_callback(struct client *client, enum sasl_server_reply reply,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(reply != SASL_SERVER_REPLY_CONTINUE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* NOTE: client may be destroyed now */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmaster_auth_callback(const struct master_auth_reply *reply, void *context)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum sasl_server_reply sasl_reply = SASL_SERVER_REPLY_MASTER_FAILED;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen auth_client_send_cancel(auth_client, client->master_auth_id);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen call_client_callback(client, sasl_reply, data, NULL);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainenstatic void master_send_request(struct anvil_request *anvil_request)
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen struct client *client = anvil_request->client;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen const unsigned char *data;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen const char *session_id = client_get_session_id(client);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen ssl_proxy_get_compression(client->ssl_proxy) != NULL)
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen req.flags |= MAIL_AUTH_REQUEST_FLAG_TLS_COMPRESSION;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen memcpy(req.cookie, anvil_request->cookie, sizeof(req.cookie));
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), 256);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen /* session ID */
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen buffer_append(buf, session_id, strlen(session_id)+1);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen /* protocol specific data (e.g. IMAP tag) */
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen buffer_append(buf, client->master_data_prefix,
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen /* buffered client input */
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen data = i_stream_get_data(client->input, &size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen params.socket_path = client->postlogin_socket_path;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen master_auth_request_full(master_auth, ¶ms, master_auth_callback,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenanvil_lookup_callback(const char *reply, void *context)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct login_settings *set = client->set;
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen if (reply != NULL && str_to_uint(reply, &conn_count) < 0)
06fb99af33bd380b382d2d4f2994cf9a5bf0bbaeTimo Sirainen i_fatal("Received invalid reply from anvil: %s", reply);
06fb99af33bd380b382d2d4f2994cf9a5bf0bbaeTimo Sirainen /* reply=NULL if we didn't need to do anvil lookup,
06fb99af33bd380b382d2d4f2994cf9a5bf0bbaeTimo Sirainen or if the anvil lookup failed. allow failed anvil lookups in. */
06fb99af33bd380b382d2d4f2994cf9a5bf0bbaeTimo Sirainen if (reply == NULL || conn_count < set->mail_max_userip_connections)
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen auth_client_send_cancel(auth_client, req->auth_id);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen errmsg = t_strdup_printf(ERR_TOO_MANY_USERIP_CONNECTIONS,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen call_client_callback(client, SASL_SERVER_REPLY_MASTER_FAILED,
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainenanvil_check_too_many_connections(struct client *client,
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen req->auth_pid = auth_client_request_get_server_pid(request);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen req->auth_id = auth_client_request_get_id(request);
5529671faac3c5672a948be93091056736c7afffTimo Sirainen buffer_create_from_data(&buf, req->cookie, sizeof(req->cookie));
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen cookie = auth_client_request_get_cookie(request);
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen if (strlen(cookie) == MASTER_AUTH_COOKIE_SIZE*2)
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen client->set->mail_max_userip_connections == 0) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen query = t_strconcat("LOOKUP\t", login_binary->protocol, "/",
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen anvil_client_query(anvil, query, anvil_lookup_callback, req);
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainenauthenticate_callback(struct auth_client_request *request,
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen enum auth_request_status status, const char *data_base64,
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen unsigned int i;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen /* client aborted */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* continue */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->sasl_callback(client, SASL_SERVER_REPLY_CONTINUE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->auth_passdb_args = p_strarray_dup(client->pool, args);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (strncmp(args[i], "original_user=", 14) == 0) {
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen client->virtual_user_orig = i_strdup(args[i] + 14);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (strncmp(args[i], "auth_user=", 10) == 0) {
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen } else if (strncmp(args[i], "postlogin_socket=", 17) == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* user can't login */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (strncmp(args[i], "resp=", 5) == 0 &&
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen call_client_callback(client, SASL_SERVER_REPLY_SUCCESS,
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen anvil_check_too_many_connections(client, request);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* fall through */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* parse our username if it's there */
24815ed8224a0647926b49b9a1f716efb2a57148Timo Sirainen } else if (strncmp(args[i], "original_user=", 14) == 0) {
06a5ffa611efd86ffb9acc8beb0fe66e7bd844e4Timo Sirainen } else if (strncmp(args[i], "auth_user=", 10) == 0) {
b0a446671b8f09a1d2ed1d8c86a47298309e989dTimo Sirainen call_client_callback(client, SASL_SERVER_REPLY_AUTH_FAILED,
06a5ffa611efd86ffb9acc8beb0fe66e7bd844e4Timo Sirainenvoid sasl_server_auth_begin(struct client *client,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(auth_client_is_connected(auth_client));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->auth_mech_name = str_ucase(i_strdup(mech_name));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mech = auth_client_find_mech(auth_client, mech_name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Unsupported authentication mechanism.",
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (!client->secured && client->set->disable_plaintext_auth &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Plaintext authentication disabled.",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen info.session_id = client_get_session_id(client);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen info.cert_username = client->client_cert_common_name;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen info.cert_username = ssl_proxy_get_peer_name(client->ssl_proxy);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen info.real_local_port = client->real_local_port;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen info.real_remote_port = client->real_remote_port;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen info.forward_fields = str_c(client->forward_fields);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen info.initial_resp_base64 = initial_resp_base64;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainensasl_server_auth_cancel(struct client *client, const char *reason,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen const char *code, enum sasl_server_reply reply)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (client->set->auth_verbose && reason != NULL) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen "Authenticate %s failed: %s", auth_name, reason));
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen auth_client_request_abort(&client->auth_request);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen call_client_callback(client, reply, reason, args);
bb2b91b4c5363348b737237893d414639510a561Timo Sirainen call_client_callback(client, reply, reason, NULL);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenvoid sasl_server_auth_failed(struct client *client, const char *reason,
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen sasl_server_auth_cancel(client, reason, code, SASL_SERVER_REPLY_AUTH_FAILED);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid sasl_server_auth_abort(struct client *client)