sasl-server.c revision b55f914c0ade77252cfd798ea8eb9a84bda56315
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen#include "login-common.h"
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen#include "base64.h"
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen#include "buffer.h"
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen#include "hex-binary.h"
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen#include "ioloop.h"
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen#include "istream.h"
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#include "write-full.h"
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen#include "strescape.h"
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen#include "str-sanitize.h"
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen#include "anvil-client.h"
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen#include "auth-client.h"
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen#include "ssl-proxy.h"
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen#include "master-service.h"
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen#include "master-interface.h"
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen#include "master-auth.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "client-common.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include <stdlib.h>
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#include <unistd.h>
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen#define ERR_TOO_MANY_USERIP_CONNECTIONS \
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen "Maximum number of connections from user+IP exceeded " \
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen "(mail_max_userip_connections=%u)"
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenstruct anvil_request {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen struct client *client;
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen unsigned int auth_pid, auth_id;
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen unsigned char cookie[MASTER_AUTH_COOKIE_SIZE];
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen};
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenconst struct auth_mech_desc *
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainensasl_server_get_advertised_mechs(struct client *client, unsigned int *count_r)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen{
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen const struct auth_mech_desc *mech;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen struct auth_mech_desc *ret_mech;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen unsigned int i, j, count;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen mech = auth_client_get_available_mechs(auth_client, &count);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (count == 0) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen *count_r = 0;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen return NULL;
82b990b0bb2a1dad5c2634a508a5ad87715db402Timo Sirainen }
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen
1f6c210c30992e95b806d2f517e2b3625ed941c5Timo Sirainen ret_mech = t_new(struct auth_mech_desc, count);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen for (i = j = 0; i < count; i++) {
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen /* a) transport is secured
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen b) auth mechanism isn't plaintext
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen c) we allow insecure authentication
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen (client->secured || !client->set->disable_plaintext_auth ||
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen (mech[i].flags & MECH_SEC_PLAINTEXT) == 0))
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen ret_mech[j++] = mech[i];
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen }
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen *count_r = j;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen return ret_mech;
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen}
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainenstatic enum auth_request_flags
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenclient_get_auth_flags(struct client *client)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen{
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen enum auth_request_flags auth_flags = 0;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (client->ssl_proxy != NULL &&
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen ssl_proxy_has_valid_client_cert(client->ssl_proxy))
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen auth_flags |= AUTH_REQUEST_FLAG_VALID_CLIENT_CERT;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (client->secured)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen auth_flags |= AUTH_REQUEST_FLAG_SECURED;
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen if (client->trusted) {
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen /* e.g. webmail */
1f6c210c30992e95b806d2f517e2b3625ed941c5Timo Sirainen auth_flags |= AUTH_REQUEST_FLAG_NO_PENALTY;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen }
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (login_binary->sasl_support_final_reply)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen auth_flags |= AUTH_REQUEST_FLAG_SUPPORT_FINAL_RESP;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen return auth_flags;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen}
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenstatic void
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainencall_client_callback(struct client *client, enum sasl_server_reply reply,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen const char *data, const char *const *args)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen{
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen sasl_server_callback_t *sasl_callback;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen i_assert(reply != SASL_SERVER_REPLY_CONTINUE);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen sasl_callback = client->sasl_callback;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->sasl_callback = NULL;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen sasl_callback(client, reply, data, args);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* NOTE: client may be destroyed now */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen}
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
1f6c210c30992e95b806d2f517e2b3625ed941c5Timo Sirainenstatic void
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenmaster_auth_callback(const struct master_auth_reply *reply, void *context)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen{
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen struct client *client = context;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen enum sasl_server_reply sasl_reply = SASL_SERVER_REPLY_MASTER_FAILED;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen const char *data = NULL;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
f6c1297c26b355c4aec2a08978f51ec3efecb351Timo Sirainen client->master_tag = 0;
f6c1297c26b355c4aec2a08978f51ec3efecb351Timo Sirainen client->authenticating = FALSE;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (reply != NULL) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen switch (reply->status) {
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen case MASTER_AUTH_STATUS_OK:
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen sasl_reply = SASL_SERVER_REPLY_SUCCESS;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen break;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen case MASTER_AUTH_STATUS_INTERNAL_ERROR:
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen sasl_reply = SASL_SERVER_REPLY_MASTER_FAILED;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen break;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen client->mail_pid = reply->mail_pid;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen } else {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen auth_client_send_cancel(auth_client, client->master_auth_id);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen call_client_callback(client, sasl_reply, data, NULL);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen}
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenstatic void master_send_request(struct anvil_request *anvil_request)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen{
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen struct client *client = anvil_request->client;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen struct master_auth_request req;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen const unsigned char *data;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen size_t size;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen buffer_t *buf;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen const char *session_id = client_get_session_id(client);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen memset(&req, 0, sizeof(req));
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen req.auth_pid = anvil_request->auth_pid;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen req.auth_id = anvil_request->auth_id;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen req.local_ip = client->local_ip;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen req.remote_ip = client->ip;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen req.client_pid = getpid();
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (client->ssl_proxy != NULL &&
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen ssl_proxy_get_compression(client->ssl_proxy))
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen req.flags |= MAIL_AUTH_REQUEST_FLAG_TLS_COMPRESSION;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen memcpy(req.cookie, anvil_request->cookie, sizeof(req.cookie));
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), 256);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* session ID */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen buffer_append(buf, session_id, strlen(session_id)+1);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* protocol specific data (e.g. IMAP tag) */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen buffer_append(buf, client->master_data_prefix,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->master_data_prefix_len);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* buffered client input */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen data = i_stream_get_data(client->input, &size);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen buffer_append(buf, data, size);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen req.data_size = buf->used;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->auth_finished = ioloop_time;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->master_auth_id = req.auth_id;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen master_auth_request(master_auth, client->fd, &req, buf->data,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen master_auth_callback, client, &client->master_tag);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen}
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenstatic void anvil_lookup_callback(const char *reply, void *context)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen{
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen struct anvil_request *req = context;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen struct client *client = req->client;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen const struct login_settings *set = client->set;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen const char *errmsg;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (reply == NULL ||
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen strtoul(reply, NULL, 10) < set->mail_max_userip_connections)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen master_send_request(req);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen else {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->authenticating = FALSE;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen auth_client_send_cancel(auth_client, req->auth_id);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen errmsg = t_strdup_printf(ERR_TOO_MANY_USERIP_CONNECTIONS,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen set->mail_max_userip_connections);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen call_client_callback(client, SASL_SERVER_REPLY_MASTER_FAILED,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen errmsg, NULL);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen }
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen i_free(req);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen}
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenstatic void
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenanvil_check_too_many_connections(struct client *client,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen struct auth_client_request *request)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen{
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen struct anvil_request *req;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen const char *query, *cookie;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen buffer_t buf;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen req = i_new(struct anvil_request, 1);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen req->client = client;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen req->auth_pid = auth_client_request_get_server_pid(request);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen req->auth_id = auth_client_request_get_id(request);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen buffer_create_data(&buf, req->cookie, sizeof(req->cookie));
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen cookie = auth_client_request_get_cookie(request);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (strlen(cookie) == MASTER_AUTH_COOKIE_SIZE*2)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen (void)hex_to_binary(cookie, &buf);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (client->virtual_user == NULL ||
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->set->mail_max_userip_connections == 0) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen anvil_lookup_callback(NULL, req);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen return;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen }
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen query = t_strconcat("LOOKUP\t", login_binary->protocol, "/",
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen net_ip2addr(&client->ip), "/",
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen str_tabescape(client->virtual_user), NULL);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen anvil_client_query(anvil, query, anvil_lookup_callback, req);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen}
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenstatic void
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenauthenticate_callback(struct auth_client_request *request,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen enum auth_request_status status, const char *data_base64,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen const char *const *args, void *context)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen{
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen struct client *client = context;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen unsigned int i;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen bool nologin;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (!client->authenticating) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* client aborted */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen i_assert(status < 0);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen return;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen }
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->auth_waiting = FALSE;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen i_assert(client->auth_request == request);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen switch (status) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen case AUTH_REQUEST_STATUS_CONTINUE:
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* continue */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->sasl_callback(client, SASL_SERVER_REPLY_CONTINUE,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen data_base64, NULL);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen break;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen case AUTH_REQUEST_STATUS_OK:
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->auth_request = NULL;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->auth_successes++;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen nologin = FALSE;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen for (i = 0; args[i] != NULL; i++) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (strncmp(args[i], "user=", 5) == 0) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen i_free(client->virtual_user);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->virtual_user = i_strdup(args[i] + 5);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen } else if (strcmp(args[i], "nologin") == 0 ||
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen strcmp(args[i], "proxy") == 0) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* user can't login */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen nologin = TRUE;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen } else if (strncmp(args[i], "resp=", 5) == 0 &&
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen login_binary->sasl_support_final_reply) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->sasl_final_resp =
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen p_strdup(client->pool, args[i] + 5);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen }
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen }
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (nologin) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->authenticating = FALSE;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen call_client_callback(client, SASL_SERVER_REPLY_SUCCESS,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen NULL, args);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen } else {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen anvil_check_too_many_connections(client, request);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen }
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen break;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen case AUTH_REQUEST_STATUS_INTERNAL_FAIL:
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen client->auth_process_comm_fail = TRUE;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen /* fall through */
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen case AUTH_REQUEST_STATUS_FAIL:
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen case AUTH_REQUEST_STATUS_ABORT:
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->auth_request = NULL;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen if (args != NULL) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* parse our username if it's there */
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen for (i = 0; args[i] != NULL; i++) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (strncmp(args[i], "user=", 5) == 0) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen i_free(client->virtual_user);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->virtual_user =
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen i_strdup(args[i] + 5);
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen }
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen }
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen }
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen client->authenticating = FALSE;
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen call_client_callback(client, SASL_SERVER_REPLY_AUTH_FAILED,
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen NULL, args);
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen break;
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen }
70ed959d547ae7ff8bbe14c30c45caca3b43322cTimo Sirainen}
70ed959d547ae7ff8bbe14c30c45caca3b43322cTimo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenvoid sasl_server_auth_begin(struct client *client,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen const char *service, const char *mech_name,
70ed959d547ae7ff8bbe14c30c45caca3b43322cTimo Sirainen const char *initial_resp_base64,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen sasl_server_callback_t *callback)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen{
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen struct auth_request_info info;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen const struct auth_mech_desc *mech;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen i_assert(auth_client_is_connected(auth_client));
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->auth_attempts++;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->authenticating = TRUE;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen if (client->auth_first_started == 0)
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->auth_first_started = ioloop_time;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen i_free(client->auth_mech_name);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->auth_mech_name = str_ucase(i_strdup(mech_name));
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->sasl_callback = callback;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen mech = auth_client_find_mech(auth_client, mech_name);
1f6c210c30992e95b806d2f517e2b3625ed941c5Timo Sirainen if (mech == NULL) {
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->auth_tried_unsupported_mech = TRUE;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen sasl_server_auth_failed(client,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen "Unsupported authentication mechanism.");
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen return;
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen }
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen if (!client->secured && client->set->disable_plaintext_auth &&
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen (mech->flags & MECH_SEC_PLAINTEXT) != 0) {
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen client->auth_tried_disabled_plaintext = TRUE;
3320f4770d1f6c2cdd10f3c4ca5a324beb335339Timo Sirainen sasl_server_auth_failed(client,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen "Plaintext authentication disabled.");
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen return;
e8cd58b9d4fbbca77a1c83107bd8dc5307a4eb95Timo Sirainen }
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen memset(&info, 0, sizeof(info));
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen info.mech = mech->name;
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen info.service = service;
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen info.cert_username = client->ssl_proxy == NULL ? NULL :
39afc7584d935b2dc7332c21966a7b20da03f1ecTimo Sirainen ssl_proxy_get_peer_name(client->ssl_proxy);
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen info.flags = client_get_auth_flags(client);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen info.local_ip = client->local_ip;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen info.remote_ip = client->ip;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen info.local_port = client->local_port;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen info.remote_port = client->remote_port;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen info.initial_resp_base64 = initial_resp_base64;
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen client->auth_request =
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen auth_client_request_new(auth_client, &info,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen authenticate_callback, client);
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen}
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainenstatic void sasl_server_auth_cancel(struct client *client, const char *reason,
cb1fd563e6000153d1be76fd8722a096bd144b77Timo Sirainen enum sasl_server_reply reply)
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen{
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen i_assert(client->authenticating);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen if (client->set->auth_verbose && reason != NULL) {
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen const char *auth_name =
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen client_log(client, t_strdup_printf(
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen "Authenticate %s failed: %s", auth_name, reason));
70ed959d547ae7ff8bbe14c30c45caca3b43322cTimo Sirainen }
70ed959d547ae7ff8bbe14c30c45caca3b43322cTimo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen client->authenticating = FALSE;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (client->auth_request != NULL)
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen auth_client_request_abort(&client->auth_request);
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen call_client_callback(client, reply, reason, NULL);
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen}
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainenvoid sasl_server_auth_failed(struct client *client, const char *reason)
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen sasl_server_auth_cancel(client, reason, SASL_SERVER_REPLY_AUTH_FAILED);
15780ce9a9aaf06b585f43850a60b89bf1ea3e1fTimo Sirainen}
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen
15780ce9a9aaf06b585f43850a60b89bf1ea3e1fTimo Sirainenvoid sasl_server_auth_abort(struct client *client)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen{
df02611c44e9432e7961223bf9bfa3fb233b1789Timo Sirainen client->auth_try_aborted = TRUE;
15780ce9a9aaf06b585f43850a60b89bf1ea3e1fTimo Sirainen sasl_server_auth_cancel(client, NULL, SASL_SERVER_REPLY_AUTH_ABORTED);
15780ce9a9aaf06b585f43850a60b89bf1ea3e1fTimo Sirainen}
15780ce9a9aaf06b585f43850a60b89bf1ea3e1fTimo Sirainen