client-common-auth.c revision b9c76fe9d9ca194816606342da1ddbd9be6bc8ab
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "login-common.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "istream.h"
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen#include "ostream.h"
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen#include "str.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "safe-memset.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "login-proxy.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "auth-client.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "client-common.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <stdlib.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#define PROXY_FAILURE_MSG "Account is temporarily unavailable."
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#define LOGIN_DNS_CLIENT_SOCKET_PATH "dns-client"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen/* If we've been waiting auth server to respond for over this many milliseconds,
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen send a "waiting" message. */
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#define AUTH_WAITING_TIMEOUT_MSECS (30*1000)
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#define GREETING_WARNING_TIMEOUT_MSECS (10*1000)
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#define CLIENT_AUTH_BUF_MAX_SIZE 8192
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenvoid client_auth_failed(struct client *client)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen{
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen i_free_and_null(client->master_data_prefix);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen if (client->auth_initializing || client->destroyed)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen return;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen if (client->io != NULL)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen io_remove(&client->io);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen client->io = io_add(client->fd, IO_READ, client_input, client);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen client_input(client);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen}
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainenstatic void client_auth_waiting_timeout(struct client *client)
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen{
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen if (!client->greeting_sent) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_log_warn(client, "Auth process not responding, "
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen "delayed sending greeting");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_STATUS,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen client->master_tag == 0 ?
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen AUTH_SERVER_WAITING_MSG : AUTH_MASTER_WAITING_MSG);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen timeout_remove(&client->to_auth_waiting);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen}
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenvoid client_set_auth_waiting(struct client *client)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen{
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_assert(client->to_auth_waiting == NULL);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen client->to_auth_waiting =
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen timeout_add(!client->greeting_sent ?
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen GREETING_WARNING_TIMEOUT_MSECS :
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen AUTH_WAITING_TIMEOUT_MSECS,
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen client_auth_waiting_timeout, client);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen}
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainenstatic void client_auth_parse_args(struct client *client,
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen const char *const *args,
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen struct client_auth_reply *reply_r)
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen{
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen const char *key, *value, *p;
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen memset(reply_r, 0, sizeof(*reply_r));
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen for (; *args != NULL; args++) {
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen p = strchr(*args, '=');
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen if (p == NULL) {
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen key = *args;
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen value = "";
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen } else {
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen key = t_strdup_until(*args, p);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen value = p + 1;
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen }
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen if (strcmp(key, "nologin") == 0)
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen reply_r->nologin = TRUE;
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen else if (strcmp(key, "proxy") == 0)
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen reply_r->proxy = TRUE;
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen else if (strcmp(key, "temp") == 0)
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen reply_r->temp = TRUE;
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen else if (strcmp(key, "authz") == 0)
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen reply_r->authz_failure = TRUE;
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen else if (strcmp(key, "reason") == 0)
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen reply_r->reason = value;
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen else if (strcmp(key, "host") == 0)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen reply_r->host = value;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen else if (strcmp(key, "port") == 0)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen reply_r->port = atoi(value);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen else if (strcmp(key, "destuser") == 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen reply_r->destuser = value;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen else if (strcmp(key, "pass") == 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen reply_r->password = value;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen else if (strcmp(key, "proxy_timeout") == 0)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen reply_r->proxy_timeout_msecs = 1000*atoi(value);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen else if (strcmp(key, "proxy_refresh") == 0)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen reply_r->proxy_refresh_secs = atoi(value);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen else if (strcmp(key, "master") == 0)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen reply_r->master_user = value;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen else if (strcmp(key, "ssl") == 0) {
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_YES;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (strcmp(value, "any-cert") == 0)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (reply_r->port == 0)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen reply_r->port = login_binary->default_ssl_port;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen } else if (strcmp(key, "starttls") == 0) {
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_YES |
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen PROXY_SSL_FLAG_STARTTLS;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (strcmp(value, "any-cert") == 0)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen } else if (strcmp(key, "user") == 0) {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen /* already handled in login-common */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else if (client->set->auth_debug)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen i_debug("Ignoring unknown passdb extra field: %s", key);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (reply_r->port == 0)
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen reply_r->port = login_binary->default_port;
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen if (reply_r->destuser == NULL)
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen reply_r->destuser = client->virtual_user;
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen}
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void proxy_free_password(struct client *client)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (client->proxy_password == NULL)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return;
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen i_free_and_null(client->proxy_password);
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen}
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainenvoid client_proxy_finish_destroy_client(struct client *client)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen{
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen string_t *str = t_str_new(128);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen if (client->input->closed) {
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen /* input stream got closed in client_send_raw_data().
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen In most places we don't have to check for this explicitly,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen but login_proxy_detach() attempts to get and use the
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen istream's fd, which is now -1. */
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen client_destroy(client, "Disconnected");
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen return;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen }
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen str_printfa(str, "proxy(%s): started proxying to %s:%u",
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen client->virtual_user,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen login_proxy_get_host(client->login_proxy),
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen login_proxy_get_port(client->login_proxy));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (strcmp(client->virtual_user, client->proxy_user) != 0) {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen /* remote username is different, log it */
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen str_append_c(str, '/');
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen str_append(str, client->proxy_user);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen if (client->proxy_master_user != NULL)
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen str_printfa(str, " (master %s)", client->proxy_master_user);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen login_proxy_detach(client->login_proxy);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_destroy_success(client, str_c(str));
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen}
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainenvoid client_proxy_log_failure(struct client *client, const char *line)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen{
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen string_t *str = t_str_new(128);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen str_printfa(str, "proxy(%s): Login failed to %s:%u",
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen client->virtual_user,
7af4788b402346c94496095dd819f95ce03fe431Timo Sirainen login_proxy_get_host(client->login_proxy),
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen login_proxy_get_port(client->login_proxy));
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen if (strcmp(client->virtual_user, client->proxy_user) != 0) {
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen /* remote username is different, log it */
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen str_append_c(str, '/');
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen str_append(str, client->proxy_user);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen }
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (client->proxy_master_user != NULL)
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen str_printfa(str, " (master %s)", client->proxy_master_user);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen str_append(str, ": ");
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen str_append(str, line);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i_info("%s", str_c(str));
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen}
c24ef531ca58abad996482f5c2e8992be9ae8981Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainenvoid client_proxy_failed(struct client *client, bool send_line)
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen{
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen if (send_line) {
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen PROXY_FAILURE_MSG);
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen }
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen
2524ef7b34965a1b1895d6140fd8296bf57c78d2Timo Sirainen login_proxy_free(&client->login_proxy);
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen proxy_free_password(client);
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen i_free_and_null(client->proxy_user);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen i_free_and_null(client->proxy_master_user);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen /* call this last - it may destroy the client */
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen client_auth_failed(client);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenstatic const char *get_disconnect_reason(struct istream *input)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen{
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen errno = input->stream_errno;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return errno == 0 || errno == EPIPE ? "Connection closed" :
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen t_strdup_printf("Connection closed: %m");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen}
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenstatic void proxy_input(struct client *client)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen{
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen struct istream *input;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen const char *line;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen unsigned int duration;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (client->login_proxy == NULL) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen /* we're just freeing the proxy */
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen }
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen input = login_proxy_get_istream(client->login_proxy);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (input == NULL) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (client->destroyed) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen /* we came here from client_destroy() */
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen }
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen /* failed for some reason, probably server disconnected */
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen client_proxy_failed(client, TRUE);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen }
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen i_assert(!client->destroyed);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen switch (i_stream_read(input)) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen case -2:
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen client_log_err(client, "proxy: Remote input buffer full");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_proxy_failed(client, TRUE);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return;
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen case -1:
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen line = i_stream_next_line(input);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen duration = ioloop_time - client->created;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_log_err(client, t_strdup_printf(
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "proxy: Remote %s:%u disconnected: %s "
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "(state=%u, duration=%us)%s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen login_proxy_get_host(client->login_proxy),
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen login_proxy_get_port(client->login_proxy),
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen get_disconnect_reason(input),
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client->proxy_state, duration,
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen line == NULL ? "" : t_strdup_printf(
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen " - BUG: line not read: %s", line)));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_proxy_failed(client, TRUE);
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen return;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen }
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen while ((line = i_stream_next_line(input)) != NULL) {
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen if (client->v.proxy_parse_line(client, line) != 0)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen break;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen}
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenstatic int proxy_start(struct client *client,
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen const struct client_auth_reply *reply)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen{
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen struct login_proxy_settings proxy_set;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen i_assert(reply->destuser != NULL);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen i_assert(!client->destroyed);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen client->v.proxy_reset(client);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen if (reply->password == NULL) {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen client_log_err(client, "proxy: password not given");
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen PROXY_FAILURE_MSG);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen }
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen if (reply->host == NULL || *reply->host == '\0') {
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen client_log_err(client, "proxy: host not given");
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen PROXY_FAILURE_MSG);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen i_assert(client->refcount > 1);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen if (client->destroyed) {
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen /* connection_queue_add() decided that we were the oldest
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen connection and killed us. */
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen return -1;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen }
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (login_proxy_is_ourself(client, reply->host, reply->port,
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen reply->destuser)) {
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen client_log_err(client, "Proxying loops to itself");
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen PROXY_FAILURE_MSG);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen return -1;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen }
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen memset(&proxy_set, 0, sizeof(proxy_set));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen proxy_set.host = reply->host;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen proxy_set.port = reply->port;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen proxy_set.dns_client_socket_path = LOGIN_DNS_CLIENT_SOCKET_PATH;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen proxy_set.connect_timeout_msecs = reply->proxy_timeout_msecs;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen proxy_set.notify_refresh_secs = reply->proxy_refresh_secs;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen proxy_set.ssl_flags = reply->ssl_flags;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (login_proxy_new(client, &proxy_set, proxy_input) < 0) {
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen PROXY_FAILURE_MSG);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen return -1;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen }
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen client->proxy_user = i_strdup(reply->destuser);
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen client->proxy_master_user = i_strdup(reply->master_user);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen client->proxy_password = i_strdup(reply->password);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen /* disable input until authentication is finished */
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (client->io != NULL)
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen io_remove(&client->io);
548e394330621952db0f03dd667b70184c4a37b6Timo Sirainen return 0;
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen}
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainenstatic bool
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainenclient_auth_handle_reply(struct client *client,
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const struct client_auth_reply *reply, bool success)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen{
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (reply->proxy) {
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen /* we want to proxy the connection to another server.
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen don't do this unless authentication succeeded. with
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen master user proxying we can get FAIL with proxy still set.
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen proxy host=.. [port=..] [destuser=..] pass=.. */
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (!success)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return FALSE;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (proxy_start(client, reply) < 0)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen client_auth_failed(client);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen return TRUE;
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen }
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen return client->v.auth_handle_reply(client, reply);
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen}
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainenstatic int client_auth_read_line(struct client *client)
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen{
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen const unsigned char *data;
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen size_t i, size;
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen unsigned int len;
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen if (i_stream_read_data(client->input, &data, &size, 0) == -1) {
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen client_destroy(client, "Disconnected");
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen return -1;
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen }
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen /* see if we have a full line */
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen for (i = 0; i < size; i++) {
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen if (data[i] == '\n')
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen break;
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen }
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (str_len(client->auth_response) + i > CLIENT_AUTH_BUF_MAX_SIZE) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen client_destroy(client, "Authentication response too large");
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return -1;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen str_append_n(client->auth_response, data, i);
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen i_stream_skip(client->input, i == size ? size : i+1);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen /* drop trailing \r */
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen len = str_len(client->auth_response);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (len > 0 && str_c(client->auth_response)[len-1] == '\r')
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen str_truncate(client->auth_response, len-1);
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return i < size;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen}
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenint client_auth_parse_response(struct client *client)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen{
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen int ret;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if ((ret = client_auth_read_line(client)) <= 0)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return ret;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (strcmp(str_c(client->auth_response), "*") == 0) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen sasl_server_auth_abort(client);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen return -1;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen }
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return 1;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen}
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainenstatic void client_auth_input(struct client *client)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen{
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if (client->v.auth_parse_response(client) <= 0)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen return;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen client->auth_waiting = FALSE;
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen client_set_auth_waiting(client);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen auth_client_request_continue(client->auth_request,
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen str_c(client->auth_response));
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen io_remove(&client->io);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen memset(str_c_modifiable(client->auth_response), 0,
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen str_len(client->auth_response));
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen}
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid client_auth_send_challenge(struct client *client, const char *data)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct const_iovec iov[3];
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen iov[0].iov_base = "+ ";
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen iov[0].iov_len = 2;
df16c7e87511fed827e6890a2a47d13ca48716deTimo Sirainen iov[1].iov_base = data;
df16c7e87511fed827e6890a2a47d13ca48716deTimo Sirainen iov[1].iov_len = strlen(data);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen iov[2].iov_base = "\r\n";
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen iov[2].iov_len = 2;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen (void)o_stream_sendv(client->output, iov, 3);
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen}
b7651d283ca261015ef3c445f1f27f340f0864e2Timo Sirainen
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainenstatic void
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainensasl_callback(struct client *client, enum sasl_server_reply sasl_reply,
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen const char *data, const char *const *args)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen{
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen struct client_auth_reply reply;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(!client->destroyed ||
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen sasl_reply == SASL_SERVER_REPLY_AUTH_ABORTED ||
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen sasl_reply == SASL_SERVER_REPLY_MASTER_FAILED);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen switch (sasl_reply) {
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen case SASL_SERVER_REPLY_SUCCESS:
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen if (client->to_auth_waiting != NULL)
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen timeout_remove(&client->to_auth_waiting);
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen if (args != NULL) {
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen client_auth_parse_args(client, args, &reply);
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen if (client_auth_handle_reply(client, &reply, TRUE))
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen break;
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen }
c0b1543512bc3e0a3a9f526056a3678a07ce32f5Timo Sirainen client_destroy_success(client, "Login");
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen break;
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen case SASL_SERVER_REPLY_AUTH_FAILED:
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen case SASL_SERVER_REPLY_AUTH_ABORTED:
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen if (client->to_auth_waiting != NULL)
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen timeout_remove(&client->to_auth_waiting);
a0b6b441fc679e562e79be0fb2819ffc24ab5b74Timo Sirainen if (args != NULL) {
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen client_auth_parse_args(client, args, &reply);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen reply.nologin = TRUE;
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen if (client_auth_handle_reply(client, &reply, FALSE))
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen break;
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen }
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen if (sasl_reply == SASL_SERVER_REPLY_AUTH_ABORTED) {
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen client_send_line(client, CLIENT_CMD_REPLY_BAD,
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainen "Authentication aborted by client.");
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen } else if (data == NULL) {
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAILED,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen AUTH_FAILED_MSG);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen } else {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_send_line(client,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen CLIENT_CMD_REPLY_AUTH_FAIL_REASON,
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen data);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (!client->destroyed)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen client_auth_failed(client);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen break;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen case SASL_SERVER_REPLY_MASTER_FAILED:
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (data != NULL) {
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen /* authentication itself succeeded, we just hit some
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen internal failure. */
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen client_send_line(client,
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen CLIENT_CMD_REPLY_AUTH_FAIL_TEMP, data);
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen }
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen /* the fd may still be hanging somewhere in kernel or another
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen process. make sure the client gets disconnected. */
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen if (shutdown(client->fd, SHUT_RDWR) < 0 && errno != ENOTCONN)
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen i_error("shutdown() failed: %m");
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (data == NULL)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_destroy_internal_failure(client);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen else
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_destroy_success(client, data);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen break;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen case SASL_SERVER_REPLY_CONTINUE:
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client->v.auth_send_challenge(client, data);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (client->to_auth_waiting != NULL)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen timeout_remove(&client->to_auth_waiting);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen str_truncate(client->auth_response, 0);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen i_assert(client->io == NULL);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen client->auth_waiting = TRUE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client->io = io_add(client->fd, IO_READ,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_auth_input, client);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen client_auth_input(client);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return;
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen }
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen client_unref(&client);
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen}
37ab3cde96bfa4bc5304c0c348fc420aec79572dTimo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenint client_auth_begin(struct client *client, const char *mech_name,
f4bbeadda12fbd7c219063db68f3e78646d83c2cTimo Sirainen const char *init_resp)
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen{
0b47e9f5e0181053b4d9ca7b426b0e5c185e820eTimo Sirainen if (!client->secured && strcmp(client->set->ssl, "required") == 0) {
abe8754852e70763e92f74caabbcc13d0917714cTimo Sirainen if (client->set->verbose_auth) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_log(client, "Login failed: "
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen "SSL required for authentication");
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen }
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen client->auth_attempts++;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_NOSSL,
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen "Authentication not allowed until SSL/TLS is enabled.");
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen return 1;
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen }
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (client->auth_response == NULL)
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen client->auth_response = str_new(default_pool, 256);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen client_ref(client);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen client->auth_initializing = TRUE;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen sasl_server_auth_begin(client, login_binary->protocol, mech_name,
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen init_resp, sasl_callback);
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen client->auth_initializing = FALSE;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen if (!client->authenticating)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return 1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen /* don't handle input until we get the initial auth reply */
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen if (client->io != NULL)
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen io_remove(&client->io);
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen client_set_auth_waiting(client);
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen return 0;
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen}
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainenbool client_check_plaintext_auth(struct client *client, bool pass_sent)
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (client->secured || !client->set->disable_plaintext_auth)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen return TRUE;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen if (client->set->verbose_auth) {
97e62b2b36dda0acb3215667042f5c80cdee8155Timo Sirainen client_log(client, "Login failed: "
97e62b2b36dda0acb3215667042f5c80cdee8155Timo Sirainen "Plaintext authentication disabled");
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen }
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen if (pass_sent) {
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen client_send_line(client, CLIENT_CMD_REPLY_STATUS_BAD,
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen "Plaintext authentication not allowed "
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen "without SSL/TLS, but your client did it anyway. "
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen "If anyone was listening, the password was exposed.");
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen }
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_NOSSL,
97e62b2b36dda0acb3215667042f5c80cdee8155Timo Sirainen AUTH_PLAINTEXT_DISABLED_MSG);
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen client->auth_tried_disabled_plaintext = TRUE;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen client->auth_attempts++;
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen return FALSE;
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen}
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainenvoid clients_notify_auth_connected(void)
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen{
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen struct client *client, *next;
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen for (client = clients; client != NULL; client = next) {
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen next = client->next;
dd2df6a67f10792ce31a3666197c0b6885893a3aTimo Sirainen
dd2df6a67f10792ce31a3666197c0b6885893a3aTimo Sirainen if (client->to_auth_waiting != NULL)
14175321ddb88619015866978c05a27786ca4814Timo Sirainen timeout_remove(&client->to_auth_waiting);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen if (!client->greeting_sent)
14175321ddb88619015866978c05a27786ca4814Timo Sirainen client->v.send_greeting(client);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen if (client->input_blocked) {
14175321ddb88619015866978c05a27786ca4814Timo Sirainen client->input_blocked = FALSE;
14175321ddb88619015866978c05a27786ca4814Timo Sirainen client_input(client);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen }
14175321ddb88619015866978c05a27786ca4814Timo Sirainen }
14175321ddb88619015866978c05a27786ca4814Timo Sirainen}
14175321ddb88619015866978c05a27786ca4814Timo Sirainen