client-common-auth.c revision 2b96880f2d789d125aff6a95eaa7b51f558a6a1c
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "hostpid.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "login-common.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "array.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "iostream.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "istream.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "ostream.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "str.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "safe-memset.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "time-util.h"
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen#include "login-proxy.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "auth-client.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "dsasl-client.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "master-service-ssl-settings.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#include "client-common.h"
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#define PROXY_FAILURE_MSG "Account is temporarily unavailable."
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#define PROXY_DEFAULT_TIMEOUT_MSECS (1000*30)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen/* If we've been waiting auth server to respond for over this many milliseconds,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen send a "waiting" message. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#define AUTH_WAITING_TIMEOUT_MSECS (30*1000)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#define AUTH_WAITING_WARNING_TIMEOUT_MSECS (10*1000)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstruct client_auth_fail_code_id {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *id;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen enum client_auth_fail_code code;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen};
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic const struct client_auth_fail_code_id client_auth_fail_codes[] = {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen { AUTH_CLIENT_FAIL_CODE_AUTHZFAILED,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen CLIENT_AUTH_FAIL_CODE_AUTHZFAILED },
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen { AUTH_CLIENT_FAIL_CODE_TEMPFAIL,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen CLIENT_AUTH_FAIL_CODE_TEMPFAIL },
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen { AUTH_CLIENT_FAIL_CODE_USER_DISABLED,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen CLIENT_AUTH_FAIL_CODE_USER_DISABLED },
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen { AUTH_CLIENT_FAIL_CODE_PASS_EXPIRED,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen CLIENT_AUTH_FAIL_CODE_PASS_EXPIRED },
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen { AUTH_CLIENT_FAIL_CODE_INVALID_BASE64,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen CLIENT_AUTH_FAIL_CODE_INVALID_BASE64 },
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen { AUTH_CLIENT_FAIL_CODE_MECH_INVALID,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen CLIENT_AUTH_FAIL_CODE_MECH_INVALID },
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen { AUTH_CLIENT_FAIL_CODE_MECH_SSL_REQUIRED,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen CLIENT_AUTH_FAIL_CODE_MECH_SSL_REQUIRED },
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen { NULL, CLIENT_AUTH_FAIL_CODE_NONE }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen};
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic enum client_auth_fail_code
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenclient_auth_fail_code_lookup(const char *fail_code)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const struct client_auth_fail_code_id *fail = client_auth_fail_codes;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen while (fail->id != NULL) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (strcmp(fail->id, fail_code) == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return fail->code;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen fail++;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return CLIENT_AUTH_FAIL_CODE_NONE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void client_auth_failed(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_free_and_null(client->master_data_prefix);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->auth_response != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_truncate(client->auth_response, 0);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->auth_initializing || client->destroyed)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->io != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen io_remove(&client->io);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->io = io_add(client->fd, IO_READ, client_input, client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_input(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void client_auth_waiting_timeout(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (!client->notified_auth_ready) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_log_warn(client, "Auth process not responding, "
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "delayed sending initial response (greeting)");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_notify_status(client, FALSE, client->master_tag == 0 ?
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen AUTH_SERVER_WAITING_MSG : AUTH_MASTER_WAITING_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen timeout_remove(&client->to_auth_waiting);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_set_auth_waiting(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_assert(client->to_auth_waiting == NULL);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->to_auth_waiting =
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen timeout_add(!client->notified_auth_ready ?
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen AUTH_WAITING_WARNING_TIMEOUT_MSECS :
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen AUTH_WAITING_TIMEOUT_MSECS,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_waiting_timeout, client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void alt_username_set(ARRAY_TYPE(const_string) *alt_usernames, pool_t pool,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *key, const char *value)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen char *const *fields;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen unsigned int i, count;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen fields = array_get(&global_alt_usernames, &count);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen for (i = 0; i < count; i++) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (strcmp(fields[i], key) == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (i == count) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen char *new_key = i_strdup(key);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen array_append(&global_alt_usernames, &new_key, 1);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen value = p_strdup(pool, value);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (i < array_count(alt_usernames)) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen array_idx_set(alt_usernames, i, &value);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* array is NULL-terminated, so if there are unused fields in
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen the middle set them as "" */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen while (array_count(alt_usernames) < i) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *empty_str = "";
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen array_append(alt_usernames, &empty_str, 1);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen array_append(alt_usernames, &value, 1);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void client_auth_parse_args(struct client *client, bool success,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *const *args,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen struct client_auth_reply *reply_r)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *key, *value, *p;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen ARRAY_TYPE(const_string) alt_usernames;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen t_array_init(&alt_usernames, 4);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_zero(reply_r);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen for (; *args != NULL; args++) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen p = strchr(*args, '=');
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (p == NULL) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen key = *args;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen value = "";
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen key = t_strdup_until(*args, p);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen value = p + 1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (strcmp(key, "nologin") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->nologin = TRUE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->fail_code = CLIENT_AUTH_FAIL_CODE_LOGIN_DISABLED;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (strcmp(key, "proxy") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->proxy = TRUE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "reason") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->reason = value;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "host") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->host = value;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "hostip") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->hostip = value;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "source_ip") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->source_ip = value;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "port") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (net_str2port(value, &reply_r->port) < 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_error("Auth service returned invalid "
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "port number: %s", value);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (strcmp(key, "destuser") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->destuser = value;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "pass") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->password = value;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "proxy_timeout") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (str_to_uint(value, &reply_r->proxy_timeout_msecs) < 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_error("BUG: Auth service returned invalid "
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "proxy_timeout value: %s", value);
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi }
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi reply_r->proxy_timeout_msecs *= 1000;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (strcmp(key, "proxy_refresh") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (str_to_uint(value, &reply_r->proxy_refresh_secs) < 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_error("BUG: Auth service returned invalid "
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "proxy_refresh value: %s", value);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (strcmp(key, "proxy_mech") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->proxy_mech = value;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "proxy_nopipelining") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->proxy_nopipelining = TRUE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "proxy_not_trusted") == 0)
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi reply_r->proxy_not_trusted = TRUE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "master") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->master_user = value;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "ssl") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_YES;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (strcmp(value, "any-cert") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply_r->port == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->port = login_binary->default_ssl_port;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (strcmp(key, "starttls") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_YES |
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen PROXY_SSL_FLAG_STARTTLS;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (strcmp(value, "any-cert") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (strcmp(key, "code") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply_r->fail_code != CLIENT_AUTH_FAIL_CODE_NONE) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* code already assigned */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->fail_code = client_auth_fail_code_lookup(value);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (strcmp(key, "user") == 0 ||
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen strcmp(key, "postlogin_socket") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* already handled in sasl-server.c */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (strncmp(key, "user_", 5) == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (success) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen alt_username_set(&alt_usernames, client->pool,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen key, value);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
f3fa33be556fd5199dcc856b02b58128bdf693a5Timo Sirainen } else if (client->set->auth_debug)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_debug("Ignoring unknown passdb extra field: %s", key);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (array_count(&alt_usernames) > 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char **alt;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen alt = p_new(client->pool, const char *,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen array_count(&alt_usernames) + 1);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen memcpy(alt, array_idx(&alt_usernames, 0),
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sizeof(*alt) * array_count(&alt_usernames));
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->alt_usernames = alt;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi if (reply_r->port == 0)
f3fa33be556fd5199dcc856b02b58128bdf693a5Timo Sirainen reply_r->port = login_binary->default_port;
f3fa33be556fd5199dcc856b02b58128bdf693a5Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply_r->destuser == NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->destuser = client->virtual_user;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void proxy_free_password(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->proxy_password == NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_free_and_null(client->proxy_password);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_proxy_finish_destroy_client(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen string_t *str = t_str_new(128);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->input->closed) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* input stream got closed in client_send_raw_data().
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen In most places we don't have to check for this explicitly,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen but login_proxy_detach() attempts to get and use the
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen istream's fd, which is now -1. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_destroy(client, "Disconnected");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_printfa(str, "proxy(%s): started proxying to %s:%u",
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->virtual_user,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen login_proxy_get_host(client->login_proxy),
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen login_proxy_get_port(client->login_proxy));
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (strcmp(client->virtual_user, client->proxy_user) != 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* remote username is different, log it */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_append_c(str, '/');
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_append(str, client->proxy_user);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->proxy_master_user != NULL)
bda082b4c7d06cd8ed83794318930385673b7eeeTeemu Huovila str_printfa(str, " (master %s)", client->proxy_master_user);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen login_proxy_detach(client->login_proxy);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_destroy_success(client, str_c(str));
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void client_proxy_error(struct client *client, const char *text)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->v.proxy_error(client, text);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenconst char *client_proxy_get_state(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->v.proxy_get_state == NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return dec2str(client->proxy_state);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return client->v.proxy_get_state(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_proxy_log_failure(struct client *client, const char *line)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen string_t *str = t_str_new(128);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_printfa(str, "proxy(%s): Login failed to %s:%u",
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->virtual_user,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen login_proxy_get_host(client->login_proxy),
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen login_proxy_get_port(client->login_proxy));
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (strcmp(client->virtual_user, client->proxy_user) != 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* remote username is different, log it */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_append_c(str, '/');
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_append(str, client->proxy_user);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->proxy_master_user != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_printfa(str, " (master %s)", client->proxy_master_user);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_append(str, ": ");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_append(str, line);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_log(client, str_c(str));
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_proxy_failed(struct client *client, bool send_line)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (send_line) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_error(client, PROXY_FAILURE_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->proxy_sasl_client != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen dsasl_client_free(&client->proxy_sasl_client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen login_proxy_free(&client->login_proxy);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen proxy_free_password(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_free_and_null(client->proxy_user);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_free_and_null(client->proxy_master_user);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* call this last - it may destroy the client */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_failed(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void proxy_input(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen struct istream *input;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen struct ostream *output;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *line;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen unsigned int duration;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->login_proxy == NULL) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* we're just freeing the proxy */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen input = login_proxy_get_istream(client->login_proxy);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (input == NULL) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->destroyed) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* we came here from client_destroy() */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* failed for some reason, probably server disconnected */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_failed(client, TRUE);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_assert(!client->destroyed);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen switch (i_stream_read(input)) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case -2:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_log_err(client, "proxy: Remote input buffer full");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_failed(client, TRUE);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case -1:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen line = i_stream_next_line(input);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen duration = ioloop_time - client->created;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_log_err(client, t_strdup_printf(
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "proxy: Remote %s:%u disconnected: %s "
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "(state=%s, duration=%us)%s",
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen login_proxy_get_host(client->login_proxy),
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen login_proxy_get_port(client->login_proxy),
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen io_stream_get_disconnect_reason(input, NULL),
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_get_state(client), duration,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen line == NULL ? "" : t_strdup_printf(
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi " - BUG: line not read: %s", line)));
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi client_proxy_failed(client, TRUE);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen output = client->output;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen o_stream_ref(output);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen o_stream_cork(output);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen while ((line = i_stream_next_line(input)) != NULL) {
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi if (client->v.proxy_parse_line(client, line) != 0)
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen o_stream_uncork(output);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen o_stream_unref(&output);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic int proxy_start(struct client *client,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const struct client_auth_reply *reply)
18efe79858a7b4a794c11bc1867fc313c7c07bbeTimo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen struct login_proxy_settings proxy_set;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const struct dsasl_client_mech *sasl_mech = NULL;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_assert(reply->destuser != NULL);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_assert(!client->destroyed);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_assert(client->proxy_sasl_client == NULL);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->proxy_mech = NULL;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->v.proxy_reset(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply->password == NULL) {
18efe79858a7b4a794c11bc1867fc313c7c07bbeTimo Sirainen client_log_err(client, "proxy: password not given");
18efe79858a7b4a794c11bc1867fc313c7c07bbeTimo Sirainen client_proxy_error(client, PROXY_FAILURE_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return -1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply->host == NULL || *reply->host == '\0') {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_log_err(client, "proxy: host not given");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_error(client, PROXY_FAILURE_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return -1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply->proxy_mech != NULL) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sasl_mech = dsasl_client_mech_find(reply->proxy_mech);
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi if (sasl_mech == NULL) {
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi client_log_err(client, t_strdup_printf(
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi "proxy: Unsupported SASL mechanism %s",
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply->proxy_mech));
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_error(client, PROXY_FAILURE_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return -1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (reply->master_user != NULL) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* have to use PLAIN authentication with master user logins */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sasl_mech = &dsasl_client_mech_plain;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi i_assert(client->refcount > 1);
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi if (client->destroyed) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* connection_queue_add() decided that we were the oldest
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen connection and killed us. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return -1;
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi }
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi if (login_proxy_is_ourself(client, reply->host, reply->port,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply->destuser)) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_log_err(client, "Proxying loops to itself");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_error(client, PROXY_FAILURE_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return -1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_zero(&proxy_set);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen proxy_set.host = reply->host;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply->hostip != NULL &&
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen net_addr2ip(reply->hostip, &proxy_set.ip) < 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen proxy_set.ip.family = 0;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply->source_ip != NULL) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (net_addr2ip(reply->source_ip, &proxy_set.source_ip) < 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen proxy_set.source_ip.family = 0;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (login_source_ips_count > 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* select the next source IP with round robin. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen proxy_set.source_ip = login_source_ips[login_source_ips_idx];
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen login_source_ips_idx =
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen (login_source_ips_idx + 1) % login_source_ips_count;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen proxy_set.port = reply->port;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen proxy_set.connect_timeout_msecs = reply->proxy_timeout_msecs;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (proxy_set.connect_timeout_msecs == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen proxy_set.connect_timeout_msecs = PROXY_DEFAULT_TIMEOUT_MSECS;
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen proxy_set.notify_refresh_secs = reply->proxy_refresh_secs;
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen proxy_set.ssl_flags = reply->ssl_flags;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (login_proxy_new(client, &proxy_set, proxy_input) < 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_error(client, PROXY_FAILURE_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return -1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->proxy_mech = sasl_mech;
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen client->proxy_user = i_strdup(reply->destuser);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->proxy_master_user = i_strdup(reply->master_user);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->proxy_password = i_strdup(reply->password);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->proxy_nopipelining = reply->proxy_nopipelining;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->proxy_not_trusted = reply->proxy_not_trusted;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* disable input until authentication is finished */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->io != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen io_remove(&client->io);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return 0;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void ATTR_NULL(3, 4)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenclient_auth_result(struct client *client, enum client_auth_result result,
cddfd1355db6b60c71d7ee3c0b4f23b3efcc9ad1Timo Sirainen const struct client_auth_reply *reply, const char *text)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen o_stream_cork(client->output);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->v.auth_result(client, result, reply, text);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen o_stream_uncork(client->output);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic bool
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenclient_auth_handle_reply(struct client *client,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const struct client_auth_reply *reply, bool success)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply->proxy) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* we want to proxy the connection to another server.
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen don't do this unless authentication succeeded. with
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen master user proxying we can get FAIL with proxy still set.
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen proxy host=.. [port=..] [destuser=..] pass=.. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (!success)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return FALSE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (proxy_start(client, reply) < 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_failed(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* this for plugins being able th hook into auth reply
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen when proxying is used */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_SUCCESS,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply, NULL);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return TRUE;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply->host != NULL) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *reason;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply->reason != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reason = reply->reason;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (reply->nologin)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reason = "Try this server instead.";
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reason = "Logged in, but you should use this server instead.";
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply->nologin) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen CLIENT_AUTH_RESULT_REFERRAL_NOLOGIN,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply, reason);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen CLIENT_AUTH_RESULT_REFERRAL_SUCCESS,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply, reason);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return TRUE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (reply->nologin) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen enum client_auth_result result = CLIENT_AUTH_RESULT_AUTHFAILED;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *timestamp, *reason = reply->reason;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* Either failed or user login is disabled */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen switch (reply->fail_code) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case CLIENT_AUTH_FAIL_CODE_AUTHZFAILED:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen result = CLIENT_AUTH_RESULT_AUTHZFAILED;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reason == NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reason = "Authorization failed";
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case CLIENT_AUTH_FAIL_CODE_TEMPFAIL:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen result = CLIENT_AUTH_RESULT_TEMPFAIL;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen timestamp = t_strflocaltime("%Y-%m-%d %H:%M:%S", ioloop_time);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reason = t_strdup_printf(AUTH_TEMP_FAILED_MSG" [%s:%s]",
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen my_hostname, timestamp);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case CLIENT_AUTH_FAIL_CODE_PASS_EXPIRED:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen result = CLIENT_AUTH_RESULT_PASS_EXPIRED;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case CLIENT_AUTH_FAIL_CODE_INVALID_BASE64:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen result = CLIENT_AUTH_RESULT_INVALID_BASE64;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case CLIENT_AUTH_FAIL_CODE_MECH_INVALID:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen result = CLIENT_AUTH_RESULT_MECH_INVALID;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case CLIENT_AUTH_FAIL_CODE_MECH_SSL_REQUIRED:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen result = CLIENT_AUTH_RESULT_MECH_SSL_REQUIRED;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case CLIENT_AUTH_FAIL_CODE_LOGIN_DISABLED:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen result = CLIENT_AUTH_RESULT_LOGIN_DISABLED;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reason == NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reason = "Login disabled for this user";
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case CLIENT_AUTH_FAIL_CODE_USER_DISABLED:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen default:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reason != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen result = CLIENT_AUTH_RESULT_AUTHFAILED_REASON;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen result = CLIENT_AUTH_RESULT_AUTHFAILED;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen if (reason == NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reason = AUTH_FAILED_MSG;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, result, reply, reason);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* normal login/failure */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return FALSE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_assert(reply->nologin);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (!client->destroyed)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_failed(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return TRUE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
61cf001f1944d92eb25f113ba4c08985d6e30d53Timo Sirainenvoid client_auth_respond(struct client *client, const char *response)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->auth_waiting = FALSE;
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi client_set_auth_waiting(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen auth_client_request_continue(client->auth_request, response);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen io_remove(&client->io);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_auth_abort(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sasl_server_auth_abort(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_auth_fail(struct client *client, const char *text)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sasl_server_auth_failed(client, text, NULL);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärviint client_auth_read_line(struct client *client)
7bc3126bb62589fe373f40aa40132e671e4a363dAki Tuomi{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const unsigned char *data;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen size_t i, size, len;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi if (i_stream_read_more(client->input, &data, &size) == -1) {
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi client_destroy(client, "Disconnected");
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi return -1;
7bc3126bb62589fe373f40aa40132e671e4a363dAki Tuomi }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* see if we have a full line */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen for (i = 0; i < size; i++) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (data[i] == '\n')
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi if (client->auth_response == NULL)
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi client->auth_response = str_new(default_pool, I_MAX(i+1, 256));
7bc3126bb62589fe373f40aa40132e671e4a363dAki Tuomi if (str_len(client->auth_response) + i > LOGIN_MAX_AUTH_BUF_SIZE) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_destroy(client, "Authentication response too large");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return -1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi str_append_n(client->auth_response, data, i);
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi i_stream_skip(client->input, i == size ? size : i+1);
7bc3126bb62589fe373f40aa40132e671e4a363dAki Tuomi
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* drop trailing \r */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen len = str_len(client->auth_response);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (len > 0 && str_c(client->auth_response)[len-1] == '\r')
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi str_truncate(client->auth_response, len-1);
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi return i < size ? 1 : 0;
7bc3126bb62589fe373f40aa40132e671e4a363dAki Tuomi}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_auth_parse_response(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client_auth_read_line(client) <= 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (strcmp(str_c(client->auth_response), "*") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sasl_server_auth_abort(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_respond(client, str_c(client->auth_response));
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen memset(str_c_modifiable(client->auth_response), 0,
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi str_len(client->auth_response));
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi}
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void client_auth_input(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen i_assert(client->v.auth_parse_response != NULL);
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen client->v.auth_parse_response(client);
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen}
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainenvoid client_auth_send_challenge(struct client *client, const char *data)
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen{
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen struct const_iovec iov[3];
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen iov[0].iov_base = "+ ";
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen iov[0].iov_len = 2;
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen iov[1].iov_base = data;
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen iov[1].iov_len = strlen(data);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen iov[2].iov_base = "\r\n";
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen iov[2].iov_len = 2;
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen o_stream_nsendv(client->output, iov, 3);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainensasl_callback(struct client *client, enum sasl_server_reply sasl_reply,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *data, const char *const *args)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen struct client_auth_reply reply;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_assert(!client->destroyed ||
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sasl_reply == SASL_SERVER_REPLY_AUTH_ABORTED ||
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sasl_reply == SASL_SERVER_REPLY_MASTER_FAILED);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->last_auth_fail = CLIENT_AUTH_FAIL_CODE_NONE;
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen i_zero(&reply);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen switch (sasl_reply) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case SASL_SERVER_REPLY_SUCCESS:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->to_auth_waiting != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen timeout_remove(&client->to_auth_waiting);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (args != NULL) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_parse_args(client, TRUE, args, &reply);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply.all_fields = args;
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi client->last_auth_fail = reply.fail_code;
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi if (client_auth_handle_reply(client, &reply, TRUE))
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_SUCCESS,
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen &reply, NULL);
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen client_destroy_success(client, "Login");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case SASL_SERVER_REPLY_AUTH_FAILED:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case SASL_SERVER_REPLY_AUTH_ABORTED:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->to_auth_waiting != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen timeout_remove(&client->to_auth_waiting);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (args != NULL) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_parse_args(client, FALSE, args, &reply);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->last_auth_fail = reply.fail_code;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply.nologin = TRUE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply.all_fields = args;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client_auth_handle_reply(client, &reply, FALSE))
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (sasl_reply == SASL_SERVER_REPLY_AUTH_ABORTED) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_ABORTED,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen &reply, "Authentication aborted by client.");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (data == NULL) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen CLIENT_AUTH_RESULT_AUTHFAILED, &reply,
7f2cb2e5b258280af90ae99b6d07dfa44109e5beTimo Sirainen AUTH_FAILED_MSG);
7f2cb2e5b258280af90ae99b6d07dfa44109e5beTimo Sirainen } else {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client,
7f2cb2e5b258280af90ae99b6d07dfa44109e5beTimo Sirainen CLIENT_AUTH_RESULT_AUTHFAILED_REASON, &reply,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen data);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (!client->destroyed)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_failed(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case SASL_SERVER_REPLY_MASTER_FAILED:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (data != NULL) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* authentication itself succeeded, we just hit some
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen internal failure. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_TEMPFAIL,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen &reply, data);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* the fd may still be hanging somewhere in kernel or another
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen process. make sure the client gets disconnected. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (shutdown(client->fd, SHUT_RDWR) < 0 && errno != ENOTCONN)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_error("shutdown() failed: %m");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (data == NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_destroy_internal_failure(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_destroy_success(client, data);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen break;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen case SASL_SERVER_REPLY_CONTINUE:
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_assert(client->v.auth_send_challenge != NULL);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->v.auth_send_challenge(client, data);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->to_auth_waiting != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen timeout_remove(&client->to_auth_waiting);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->auth_response != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_truncate(client->auth_response, 0);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_assert(client->io == NULL);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->auth_waiting = TRUE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->io = io_add(client->fd, IO_READ,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_input, client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_input(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_unref(&client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenint client_auth_begin(struct client *client, const char *mech_name,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *init_resp)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (!client->secured && strcmp(client->ssl_set->ssl, "required") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->set->auth_verbose) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_log(client, "Login failed: "
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "SSL required for authentication");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->auth_attempts++;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_SSL_REQUIRED, NULL,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "Authentication not allowed until SSL/TLS is enabled.");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return 1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_ref(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->auth_initializing = TRUE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sasl_server_auth_begin(client, login_binary->protocol, mech_name,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen init_resp, sasl_callback);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->auth_initializing = FALSE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (!client->authenticating)
f24edebe360d3effe584a884aa7d119daf3fd371Aki Tuomi return 1;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* don't handle input until we get the initial auth reply */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->io != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen io_remove(&client->io);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_set_auth_waiting(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return 0;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenbool client_check_plaintext_auth(struct client *client, bool pass_sent)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen bool ssl_required = (strcmp(client->ssl_set->ssl, "required") == 0);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->secured || (!client->set->disable_plaintext_auth &&
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen !ssl_required))
1c02804cdc5f1ad830fec081100e951bc67204b4Timo Sirainen return TRUE;
1c02804cdc5f1ad830fec081100e951bc67204b4Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->set->auth_verbose) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_log(client, "Login failed: "
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "Plaintext authentication disabled");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (pass_sent) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_notify_status(client, TRUE,
2933174a1d7af52678eb5d2bf581e8c2a995f6dfTimo Sirainen "Plaintext authentication not allowed "
2933174a1d7af52678eb5d2bf581e8c2a995f6dfTimo Sirainen "without SSL/TLS, but your client did it anyway. "
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "If anyone was listening, the password was exposed.");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (ssl_required) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_SSL_REQUIRED, NULL,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen AUTH_PLAINTEXT_DISABLED_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_MECH_SSL_REQUIRED, NULL,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen AUTH_PLAINTEXT_DISABLED_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->auth_attempts++;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen return FALSE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid clients_notify_auth_connected(void)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen{
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen struct client *client, *next;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen for (client = clients; client != NULL; client = next) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen next = client->next;
8b9a69edc162362d47922521161e2cfa07218688Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->to_auth_waiting != NULL)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen timeout_remove(&client->to_auth_waiting);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_notify_auth_ready(client);
f24edebe360d3effe584a884aa7d119daf3fd371Aki Tuomi
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->input_blocked) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->input_blocked = FALSE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_input(client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen }
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen}
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen