client-common-auth.c revision 5a250816ffc4cc5db203f9410ea99b6601c7b91a
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "login-common.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "istream.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "ostream.h"
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen#include "str.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "safe-memset.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "login-proxy.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "auth-client.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "client-common.h"
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <stdlib.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define PROXY_FAILURE_MSG "Account is temporarily unavailable."
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define LOGIN_DNS_CLIENT_SOCKET_PATH "dns-client"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* If we've been waiting auth server to respond for over this many milliseconds,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen send a "waiting" message. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define AUTH_WAITING_TIMEOUT_MSECS (30*1000)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define CLIENT_AUTH_BUF_MAX_SIZE 8192
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid client_auth_failed(struct client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_free_and_null(client->master_data_prefix);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->auth_initializing || client->destroyed)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen if (client->io != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_remove(&client->io);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client->io = io_add(client->fd, IO_READ, client_input, client);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_input(client);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainenstatic void client_auth_waiting_timeout(struct client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_STATUS,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->master_tag == 0 ?
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen AUTH_SERVER_WAITING_MSG : AUTH_MASTER_WAITING_MSG);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen timeout_remove(&client->to_auth_waiting);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid client_set_auth_waiting(struct client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(client->to_auth_waiting == NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->to_auth_waiting =
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen timeout_add(AUTH_WAITING_TIMEOUT_MSECS,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_auth_waiting_timeout, client);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void client_auth_parse_args(struct client *client,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *const *args,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct client_auth_reply *reply_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *key, *value, *p;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen memset(reply_r, 0, sizeof(*reply_r));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (; *args != NULL; args++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen p = strchr(*args, '=');
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (p == NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen key = *args;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen value = "";
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen key = t_strdup_until(*args, p);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen value = p + 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strcmp(key, "nologin") == 0)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen reply_r->nologin = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen else if (strcmp(key, "proxy") == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen reply_r->proxy = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen else if (strcmp(key, "temp") == 0)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen reply_r->temp = TRUE;
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen else if (strcmp(key, "authz") == 0)
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen reply_r->authz_failure = TRUE;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen else if (strcmp(key, "reason") == 0)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen reply_r->reason = value;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen else if (strcmp(key, "host") == 0)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen reply_r->host = value;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen else if (strcmp(key, "port") == 0)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen reply_r->port = atoi(value);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen else if (strcmp(key, "destuser") == 0)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen reply_r->destuser = value;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen else if (strcmp(key, "pass") == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen reply_r->password = value;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen else if (strcmp(key, "proxy_timeout") == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen reply_r->proxy_timeout_msecs = 1000*atoi(value);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen else if (strcmp(key, "proxy_refresh") == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen reply_r->proxy_refresh_secs = atoi(value);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen else if (strcmp(key, "master") == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen reply_r->master_user = value;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen else if (strcmp(key, "ssl") == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_YES;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strcmp(value, "any-cert") == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (reply_r->port == 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen reply_r->port = login_binary->default_ssl_port;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else if (strcmp(key, "starttls") == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_YES |
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen PROXY_SSL_FLAG_STARTTLS;
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen if (strcmp(value, "any-cert") == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else if (strcmp(key, "user") == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* already handled in login-common */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else if (client->set->auth_debug)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_debug("Ignoring unknown passdb extra field: %s", key);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (reply_r->port == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen reply_r->port = login_binary->default_port;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (reply_r->destuser == NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen reply_r->destuser = client->virtual_user;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen}
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenstatic void proxy_free_password(struct client *client)
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen{
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (client->proxy_password == NULL)
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen return;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_free_and_null(client->proxy_password);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid client_proxy_finish_destroy_client(struct client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen string_t *str = t_str_new(128);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_printfa(str, "proxy(%s): started proxying to %s:%u",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->virtual_user,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen login_proxy_get_host(client->login_proxy),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen login_proxy_get_port(client->login_proxy));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strcmp(client->virtual_user, client->proxy_user) != 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* remote username is different, log it */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_append_c(str, '/');
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_append(str, client->proxy_user);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->proxy_master_user != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_printfa(str, " (master %s)", client->proxy_master_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen login_proxy_detach(client->login_proxy);
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen client_destroy_success(client, str_c(str));
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen}
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainenvoid client_proxy_log_failure(struct client *client, const char *line)
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen string_t *str = t_str_new(128);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_printfa(str, "proxy(%s): Login failed to %s:%u",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->virtual_user,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen login_proxy_get_host(client->login_proxy),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen login_proxy_get_port(client->login_proxy));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strcmp(client->virtual_user, client->proxy_user) != 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* remote username is different, log it */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_append_c(str, '/');
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_append(str, client->proxy_user);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (client->proxy_master_user != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_printfa(str, " (master %s)", client->proxy_master_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_append(str, ": ");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_append(str, line);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_info("%s", str_c(str));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid client_proxy_failed(struct client *client, bool send_line)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (send_line) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen PROXY_FAILURE_MSG);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen login_proxy_free(&client->login_proxy);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen proxy_free_password(client);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_free_and_null(client->proxy_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_free_and_null(client->proxy_master_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* call this last - it may destroy the client */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_auth_failed(client);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic const char *get_disconnect_reason(struct istream *input)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen errno = input->stream_errno;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return errno == 0 || errno == EPIPE ? "Connection closed" :
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen t_strdup_printf("Connection closed: %m");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void proxy_input(struct client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream *input;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *line;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen if (client->login_proxy == NULL) {
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen /* we're just freeing the proxy */
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen return;
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen }
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen input = login_proxy_get_istream(client->login_proxy);
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen if (input == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (client->destroyed) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* we came here from client_destroy() */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* failed for some reason, probably server disconnected */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_proxy_failed(client, TRUE);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(!client->destroyed);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen switch (i_stream_read(input)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case -2:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_log_err(client, "proxy: Remote input buffer full");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_proxy_failed(client, TRUE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case -1:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_log_err(client, t_strdup_printf(
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "proxy: Remote %s:%u disconnected: %s (state=%u)",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen login_proxy_get_host(client->login_proxy),
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen login_proxy_get_port(client->login_proxy),
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen get_disconnect_reason(input), client->proxy_state));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_proxy_failed(client, TRUE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen while ((line = i_stream_next_line(input)) != NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (client->v.proxy_parse_line(client, line) != 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
7f13786e6a18a846376e46d77349528d99935871Timo Sirainen }
7f13786e6a18a846376e46d77349528d99935871Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int proxy_start(struct client *client,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct client_auth_reply *reply)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct login_proxy_settings proxy_set;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(reply->destuser != NULL);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(!client->destroyed);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client->v.proxy_reset(client);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (reply->password == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_log_err(client, "proxy: password not given");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen PROXY_FAILURE_MSG);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (reply->host == NULL || *reply->host == '\0') {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_log_err(client, "proxy: host not given");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen PROXY_FAILURE_MSG);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(client->refcount > 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (client->destroyed) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* connection_queue_add() decided that we were the oldest
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen connection and killed us. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (login_proxy_is_ourself(client, reply->host, reply->port,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen reply->destuser)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_log_err(client, "Proxying loops to itself");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen PROXY_FAILURE_MSG);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen memset(&proxy_set, 0, sizeof(proxy_set));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen proxy_set.host = reply->host;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen proxy_set.port = reply->port;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen proxy_set.dns_client_socket_path = LOGIN_DNS_CLIENT_SOCKET_PATH;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen proxy_set.connect_timeout_msecs = reply->proxy_timeout_msecs;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen proxy_set.notify_refresh_secs = reply->proxy_refresh_secs;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen proxy_set.ssl_flags = reply->ssl_flags;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (login_proxy_new(client, &proxy_set, proxy_input) < 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen PROXY_FAILURE_MSG);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client->proxy_user = i_strdup(reply->destuser);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client->proxy_master_user = i_strdup(reply->master_user);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->proxy_password = i_strdup(reply->password);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* disable input until authentication is finished */
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen if (client->io != NULL)
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen io_remove(&client->io);
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen return 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic bool
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenclient_auth_handle_reply(struct client *client,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct client_auth_reply *reply, bool success)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (reply->proxy) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* we want to proxy the connection to another server.
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen don't do this unless authentication succeeded. with
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen master user proxying we can get FAIL with proxy still set.
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen proxy host=.. [port=..] [destuser=..] pass=.. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!success)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (proxy_start(client, reply) < 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_auth_failed(client);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return client->v.auth_handle_reply(client, reply);
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen}
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainenstatic int client_auth_read_line(struct client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const unsigned char *data;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen size_t i, size;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int len;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (i_stream_read_data(client->input, &data, &size, 0) == -1) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_destroy(client, "Disconnected");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* see if we have a full line */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for (i = 0; i < size; i++) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (data[i] == '\n')
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (str_len(client->auth_response) + i > CLIENT_AUTH_BUF_MAX_SIZE) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_destroy(client, "Authentication response too large");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_append_n(client->auth_response, data, i);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_skip(client->input, i == size ? size : i+1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* drop trailing \r */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen len = str_len(client->auth_response);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (len > 0 && str_c(client->auth_response)[len-1] == '\r')
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_truncate(client->auth_response, len-1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return i < size;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint client_auth_parse_response(struct client *client)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if ((ret = client_auth_read_line(client)) <= 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (strcmp(str_c(client->auth_response), "*") == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen sasl_server_auth_abort(client);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void client_auth_input(struct client *client)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->v.auth_parse_response(client) <= 0)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_set_auth_waiting(client);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen auth_client_request_continue(client->auth_request,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_c(client->auth_response));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_remove(&client->io);
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen memset(str_c_modifiable(client->auth_response), 0,
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen str_len(client->auth_response));
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen}
b2d562f9c7fd13f9a16e9b3bcee904630b80b1feTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid client_auth_send_challenge(struct client *client, const char *data)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct const_iovec iov[3];
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen iov[0].iov_base = "+ ";
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen iov[0].iov_len = 2;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen iov[1].iov_base = data;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen iov[1].iov_len = strlen(data);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen iov[2].iov_base = "\r\n";
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen iov[2].iov_len = 2;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (void)o_stream_sendv(client->output, iov, 3);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenstatic void
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainensasl_callback(struct client *client, enum sasl_server_reply sasl_reply,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen const char *data, const char *const *args)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen struct client_auth_reply reply;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen i_assert(!client->destroyed ||
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen sasl_reply == SASL_SERVER_REPLY_AUTH_ABORTED ||
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen sasl_reply == SASL_SERVER_REPLY_MASTER_FAILED);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen switch (sasl_reply) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen case SASL_SERVER_REPLY_SUCCESS:
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (client->to_auth_waiting != NULL)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen timeout_remove(&client->to_auth_waiting);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (args != NULL) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen client_auth_parse_args(client, args, &reply);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (client_auth_handle_reply(client, &reply, TRUE))
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen }
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen client_destroy_success(client, "Login");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case SASL_SERVER_REPLY_AUTH_FAILED:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case SASL_SERVER_REPLY_AUTH_ABORTED:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (client->to_auth_waiting != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen timeout_remove(&client->to_auth_waiting);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (args != NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_auth_parse_args(client, args, &reply);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen reply.nologin = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (client_auth_handle_reply(client, &reply, FALSE))
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (sasl_reply == SASL_SERVER_REPLY_AUTH_ABORTED) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_BAD,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Authentication aborted by client.");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else if (data == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAILED,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen AUTH_FAILED_MSG);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_send_line(client,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen CLIENT_CMD_REPLY_AUTH_FAIL_REASON,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen data);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!client->destroyed)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_auth_failed(client);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case SASL_SERVER_REPLY_MASTER_FAILED:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (data != NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* authentication itself succeeded, we just hit some
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen internal failure. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_send_line(client,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen CLIENT_CMD_REPLY_AUTH_FAIL_TEMP, data);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* the fd may still be hanging somewhere in kernel or another
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen process. make sure the client gets disconnected. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (shutdown(client->fd, SHUT_RDWR) < 0 && errno != ENOTCONN)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("shutdown() failed: %m");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (data == NULL)
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen client_destroy_internal_failure(client);
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen else
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_destroy_success(client, data);
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen break;
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen case SASL_SERVER_REPLY_CONTINUE:
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen client->v.auth_send_challenge(client, data);
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->to_auth_waiting != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen timeout_remove(&client->to_auth_waiting);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_truncate(client->auth_response, 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(client->io == NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->io = io_add(client->fd, IO_READ,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_auth_input, client);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_auth_input(client);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_unref(&client);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint client_auth_begin(struct client *client, const char *mech_name,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *init_resp)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!client->secured && strcmp(client->set->ssl, "required") == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (client->set->verbose_auth) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_log(client, "Login failed: "
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "SSL required for authentication");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client->auth_attempts++;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_NOSSL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Authentication not allowed until SSL/TLS is enabled.");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (client->auth_response == NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client->auth_response = str_new(default_pool, 256);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen client_ref(client);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen client->auth_initializing = TRUE;
e3540e734a79fd4f971652925079c2e26a4b5524Timo Sirainen sasl_server_auth_begin(client, login_binary->protocol, mech_name,
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen init_resp, sasl_callback);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen client->auth_initializing = FALSE;
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (!client->authenticating)
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen return 1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen /* don't handle input until we get the initial auth reply */
e4eb49e29197c6783ec93b868100394e189f4e0cTimo Sirainen if (client->io != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_remove(&client->io);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_set_auth_waiting(client);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenbool client_check_plaintext_auth(struct client *client, bool pass_sent)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (client->secured || !client->set->disable_plaintext_auth)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (client->set->verbose_auth) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_log(client, "Login failed: "
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Plaintext authentication disabled");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (pass_sent) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_STATUS_BAD,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Plaintext authentication not allowed "
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "without SSL/TLS, but your client did it anyway. "
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "If anyone was listening, the password was exposed.");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_NOSSL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen AUTH_PLAINTEXT_DISABLED_MSG);
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen client->auth_tried_disabled_plaintext = TRUE;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen client->auth_attempts++;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen return FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid clients_notify_auth_connected(void)
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen{
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen struct client *client, *next;
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen for (client = clients; client != NULL; client = next) {
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen next = client->next;
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (client->to_auth_waiting != NULL)
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen timeout_remove(&client->to_auth_waiting);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (!client->greeting_sent)
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen client->v.send_greeting(client);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen if (client->input_blocked) {
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen client->input_blocked = FALSE;
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen client_input(client);
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen }
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen }
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen}
2ac0a22865272cb4311a1bd09eb69b475625b3ebTimo Sirainen