sasl-server.c revision 9137c55411aa39d41c1e705ddc34d5bd26c65021
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "common.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "base64.h"
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include "buffer.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "istream.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "write-full.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "strescape.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "str-sanitize.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "auth-client.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "ssl-proxy.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "master-service.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "master-interface.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "master-auth.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "client-common.h"
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include <stdlib.h>
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include <unistd.h>
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#define ERR_TOO_MANY_USERIP_CONNECTIONS \
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "Maximum number of connections from user+IP exceeded " \
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "(mail_max_userip_connections)"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenconst struct auth_mech_desc *
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainensasl_server_get_advertised_mechs(struct client *client, unsigned int *count_r)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const struct auth_mech_desc *mech;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct auth_mech_desc *ret_mech;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned int i, j, count;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mech = auth_client_get_available_mechs(auth_client, &count);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (count == 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *count_r = 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen ret_mech = t_new(struct auth_mech_desc, count);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (i = j = 0; i < count; i++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* a) transport is secured
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen b) auth mechanism isn't plaintext
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen c) we allow insecure authentication
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen (client->secured || !client->set->disable_plaintext_auth ||
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen (mech[i].flags & MECH_SEC_PLAINTEXT) == 0))
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ret_mech[j++] = mech[i];
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *count_r = j;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return ret_mech;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic enum auth_request_flags
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenclient_get_auth_flags(struct client *client)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen enum auth_request_flags auth_flags = 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (client->ssl_proxy != NULL &&
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ssl_proxy_has_valid_client_cert(client->ssl_proxy))
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen auth_flags |= AUTH_REQUEST_FLAG_VALID_CLIENT_CERT;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (client->secured)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen auth_flags |= AUTH_REQUEST_FLAG_SECURED;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return auth_flags;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenstatic void
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainencall_client_callback(struct client *client, enum sasl_server_reply reply,
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen const char *data, const char *const *args)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen sasl_server_callback_t *sasl_callback;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_assert(reply != SASL_SERVER_REPLY_CONTINUE);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen sasl_callback = client->sasl_callback;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->sasl_callback = NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen sasl_callback(client, reply, data, args);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* NOTE: client may be destroyed now */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenmaster_auth_callback(const struct master_auth_reply *reply, void *context)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct client *client = context;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen enum sasl_server_reply sasl_reply = SASL_SERVER_REPLY_MASTER_FAILED;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *data = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->master_tag = 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->authenticating = FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen switch (reply->status) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MASTER_AUTH_STATUS_OK:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen sasl_reply = SASL_SERVER_REPLY_SUCCESS;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MASTER_AUTH_STATUS_INTERNAL_ERROR:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client->mail_pid = reply->mail_pid;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen call_client_callback(client, sasl_reply, data, NULL);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic void
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenmaster_send_request(struct client *client, struct auth_client_request *request)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen struct master_auth_request req;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen const unsigned char *data;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen size_t size;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen buffer_t *buf;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen memset(&req, 0, sizeof(req));
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen req.auth_pid = auth_client_request_get_server_pid(request);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen req.auth_id = auth_client_request_get_id(request);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen req.local_ip = client->local_ip;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen req.remote_ip = client->ip;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(), 256);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen buffer_append(buf, client->master_data_prefix,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen client->master_data_prefix_len);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen data = i_stream_get_data(client->input, &size);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buffer_append(buf, data, size);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen req.data_size = buf->used;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen client->master_tag =
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen master_auth_request(master_service, client->fd, &req, buf->data,
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen master_auth_callback, client);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic bool anvil_has_too_many_connections(struct client *client)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *ident;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen char buf[64];
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ssize_t ret;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->virtual_user == NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->set->mail_max_userip_connections == 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ident = t_strconcat("LOOKUP\t", net_ip2addr(&client->ip), "/",
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen str_tabescape(client->virtual_user), "/",
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen login_protocol, "\n", NULL);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (write_full(anvil_fd, ident, strlen(ident)) < 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (errno == EPIPE) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* anvil process was probably recreated, don't bother
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen logging an error about losing connection to it */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_fatal("write(anvil) failed: %m");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ret = read(anvil_fd, buf, sizeof(buf)-1);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (ret < 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_fatal("read(anvil) failed: %m");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen else if (ret == 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_fatal("read(anvil) failed: EOF");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (buf[ret-1] != '\n')
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_fatal("anvil lookup failed: Invalid input in reply");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen buf[ret-1] = '\0';
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen return strtoul(buf, NULL, 10) >=
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->set->mail_max_userip_connections;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic void
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenauthenticate_callback(struct auth_client_request *request,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen enum auth_request_status status, const char *data_base64,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *const *args, void *context)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct client *client = context;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned int i;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen bool nologin;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (!client->authenticating) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* client aborted */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(status < 0);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(client->auth_request == request);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen switch (status) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen case AUTH_REQUEST_STATUS_CONTINUE:
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* continue */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->sasl_callback(client, SASL_SERVER_REPLY_CONTINUE,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen data_base64, NULL);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen break;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen case AUTH_REQUEST_STATUS_OK:
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->auth_request = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen nologin = FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (i = 0; args[i] != NULL; i++) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (strncmp(args[i], "user=", 5) == 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free(client->virtual_user);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->virtual_user = i_strdup(args[i] + 5);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (strcmp(args[i], "nologin") == 0 ||
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen strcmp(args[i], "proxy") == 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* user can't login */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen nologin = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (nologin) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->authenticating = FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen call_client_callback(client, SASL_SERVER_REPLY_SUCCESS,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen NULL, args);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } else if (anvil_has_too_many_connections(client)) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->authenticating = FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen call_client_callback(client,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen SASL_SERVER_REPLY_MASTER_FAILED,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ERR_TOO_MANY_USERIP_CONNECTIONS, NULL);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen } else {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen master_send_request(client, request);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen break;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen case AUTH_REQUEST_STATUS_FAIL:
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->auth_request = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (args != NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* parse our username if it's there */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (i = 0; args[i] != NULL; i++) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (strncmp(args[i], "user=", 5) == 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free(client->virtual_user);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->virtual_user =
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_strdup(args[i] + 5);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->authenticating = FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen call_client_callback(client, SASL_SERVER_REPLY_AUTH_FAILED,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen NULL, args);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen break;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid sasl_server_auth_begin(struct client *client,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *service, const char *mech_name,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *initial_resp_base64,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sasl_server_callback_t *callback)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct auth_request_info info;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const struct auth_mech_desc *mech;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->auth_attempts++;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->authenticating = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free(client->auth_mech_name);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->auth_mech_name = str_ucase(i_strdup(mech_name));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->sasl_callback = callback;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mech = auth_client_find_mech(auth_client, mech_name);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (mech == NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->auth_tried_unsupported_mech = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sasl_server_auth_failed(client,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Unsupported authentication mechanism.");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (!client->secured && client->set->disable_plaintext_auth &&
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen (mech->flags & MECH_SEC_PLAINTEXT) != 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->auth_tried_disabled_plaintext = TRUE;
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen sasl_server_auth_failed(client,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Plaintext authentication disabled.");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen memset(&info, 0, sizeof(info));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen info.mech = mech->name;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen info.service = service;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen info.cert_username = client->ssl_proxy == NULL ? NULL :
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ssl_proxy_get_peer_name(client->ssl_proxy);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen info.flags = client_get_auth_flags(client);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen info.local_ip = client->local_ip;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen info.remote_ip = client->ip;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen info.local_port = client->local_port;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen info.remote_port = client->remote_port;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen info.initial_resp_base64 = initial_resp_base64;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->auth_request =
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen auth_client_request_new(auth_client, &info,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen authenticate_callback, client);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic void sasl_server_auth_cancel(struct client *client, const char *reason,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen enum sasl_server_reply reply)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(client->authenticating);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->set->verbose_auth && reason != NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const char *auth_name =
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client_log(client, t_strdup_printf(
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "Authenticate %s failed: %s", auth_name, reason));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->authenticating = FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (client->auth_request != NULL)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen auth_client_request_abort(&client->auth_request);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen call_client_callback(client, reply, reason, NULL);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid sasl_server_auth_failed(struct client *client, const char *reason)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sasl_server_auth_cancel(client, reason, SASL_SERVER_REPLY_AUTH_FAILED);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvoid sasl_server_auth_abort(struct client *client)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen client->auth_try_aborted = TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen sasl_server_auth_cancel(client, NULL, SASL_SERVER_REPLY_AUTH_ABORTED);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen