client-authenticate.c revision 97db4761382024093f441e4bc78ba8b6a056504d
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "common.h"
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen#include "base64.h"
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen#include "buffer.h"
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen#include "hex-binary.h"
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen#include "ioloop.h"
6dc4af35c045e10609b13fe80f9cf33f3a06c3ceTimo Sirainen#include "istream.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "ostream.h"
8ed8c821ba8aab0b4ed0375f87d48737ef0e0d8eTimo Sirainen#include "safe-memset.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "str.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "str-sanitize.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "auth-client.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "../pop3/pop3-capability.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "ssl-proxy.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "client.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "client-authenticate.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "pop3-proxy.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <stdlib.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#define POP3_SERVICE_NAME "pop3"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#define AUTH_FAILURE_DELAY_INCREASE_MSECS 5000
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenconst char *capability_string = POP3_CAPABILITY_REPLY;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenbool cmd_capa(struct pop3_client *client, const char *args ATTR_UNUSED)
9d6dec796909384293006e4289436579089d88d5Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const struct auth_mech_desc *mech;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen unsigned int i, count;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen string_t *str;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen str = t_str_new(128);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen str_append(str, "+OK\r\n");
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen str_append(str, capability_string);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (ssl_initialized && !client->common.tls)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen str_append(str, "STLS\r\n");
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (!client->common.set->disable_plaintext_auth ||
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client->common.secured)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen str_append(str, "USER\r\n");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen str_append(str, "SASL");
8e047750fa23706e883b14584d0ed7c4bfde3892Timo Sirainen mech = auth_client_get_available_mechs(auth_client, &count);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen for (i = 0; i < count; i++) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* a) transport is secured
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen b) auth mechanism isn't plaintext
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen c) we allow insecure authentication
181c1aff950e6f8e0556f8974e79d0747845ac0fTimo Sirainen */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen (client->common.secured ||
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen !client->common.set->disable_plaintext_auth ||
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen (mech[i].flags & MECH_SEC_PLAINTEXT) == 0)) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen str_append_c(str, ' ');
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen str_append(str, mech[i].name);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen str_append(str, "\r\n.");
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen client_send_line(client, str_c(str));
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return TRUE;
9d6dec796909384293006e4289436579089d88d5Timo Sirainen}
9d6dec796909384293006e4289436579089d88d5Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic void client_auth_input(struct pop3_client *client)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen char *line;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (!client_read(client))
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* @UNSAFE */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen line = i_stream_next_line(client->common.input);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (line == NULL)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (strcmp(line, "*") == 0) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen sasl_server_auth_client_error(&client->common,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen "Authentication aborted");
ab0d9eecd85f74acae18fe88529302e0776cc500Timo Sirainen } else {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen auth_client_request_continue(client->common.auth_request, line);
9d6dec796909384293006e4289436579089d88d5Timo Sirainen io_remove(&client->io);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* clear sensitive data */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen safe_memset(line, 0, strlen(line));
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainenstatic void client_authfail_delay_timeout(struct pop3_client *client)
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen{
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen timeout_remove(&client->to_authfail_delay);
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen /* get back to normal client input. */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_assert(client->io == NULL);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen client->io = io_add(client->common.fd, IO_READ, client_input, client);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen client_input(client);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenvoid client_auth_failed(struct pop3_client *client, bool nodelay)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen unsigned int delay_msecs;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (client->auth_initializing)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (client->io != NULL)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen io_remove(&client->io);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (nodelay) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen client->io = io_add(client->common.fd, IO_READ,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen client_input, client);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen client_input(client);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* increase the timeout after each unsuccessful attempt, but don't
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen increase it so high that the idle timeout would be triggered */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen delay_msecs = client->common.auth_attempts *
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen AUTH_FAILURE_DELAY_INCREASE_MSECS;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (delay_msecs > CLIENT_LOGIN_IDLE_TIMEOUT_MSECS)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen delay_msecs = CLIENT_LOGIN_IDLE_TIMEOUT_MSECS - 1000;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen i_assert(client->to_authfail_delay == NULL);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen client->to_authfail_delay =
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen timeout_add(delay_msecs, client_authfail_delay_timeout, client);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic bool client_handle_args(struct pop3_client *client,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const char *const *args, bool success,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen bool *nodelay_r)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen const char *reason = NULL, *host = NULL, *destuser = NULL, *pass = NULL;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const char *master_user = NULL;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char *key, *value, *p;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen enum login_proxy_ssl_flags ssl_flags = 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen string_t *reply;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen unsigned int port = 110;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen bool proxy = FALSE, temp = FALSE, nologin = !success;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen *nodelay_r = FALSE;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen for (; *args != NULL; args++) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen p = strchr(*args, '=');
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (p == NULL) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen key = *args;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen value = "";
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen } else {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen key = t_strdup_until(*args, p);
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen value = p + 1;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen if (strcmp(key, "nologin") == 0)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen nologin = TRUE;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen else if (strcmp(key, "nodelay") == 0)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen *nodelay_r = TRUE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else if (strcmp(key, "proxy") == 0)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen proxy = TRUE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else if (strcmp(key, "temp") == 0)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen temp = TRUE;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen else if (strcmp(key, "reason") == 0)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen reason = value;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else if (strcmp(key, "host") == 0)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen host = value;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else if (strcmp(key, "port") == 0)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen port = atoi(value);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else if (strcmp(key, "destuser") == 0)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen destuser = value;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen else if (strcmp(key, "pass") == 0)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen pass = value;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen else if (strcmp(key, "master") == 0)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen master_user = value;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen else if (strcmp(key, "user") == 0) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* already handled in login-common */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen } else if (client->common.set->auth_debug)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_info("Ignoring unknown passdb extra field: %s", key);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
08ea8b302b62bc688f6b34f89f674e08eda7828cTimo Sirainen if (destuser == NULL)
08ea8b302b62bc688f6b34f89f674e08eda7828cTimo Sirainen destuser = client->common.virtual_user;
08ea8b302b62bc688f6b34f89f674e08eda7828cTimo Sirainen
08ea8b302b62bc688f6b34f89f674e08eda7828cTimo Sirainen if (proxy) {
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen /* we want to proxy the connection to another server.
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen don't do this unless authentication succeeded. with
d22301419109ed4a38351715e6760011421dadecTimo Sirainen master user proxying we can get FAIL with proxy still set.
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen proxy host=.. [port=..] [destuser=..] pass=.. */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (!success)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return FALSE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (pop3_proxy_new(client, host, port, destuser, master_user,
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen pass, ssl_flags) < 0)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen client_auth_failed(client, TRUE);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return TRUE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (!nologin)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return FALSE;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen reply = t_str_new(128);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_append(reply, "-ERR ");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (reason != NULL)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_append(reply, reason);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen else if (temp)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_append(reply, "[IN-USE] "AUTH_TEMP_FAILED_MSG);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen else
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_append(reply, AUTH_FAILED_MSG);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen client_send_line(client, str_c(reply));
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (!client->destroyed)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client_auth_failed(client, *nodelay_r);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return TRUE;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainenstatic void sasl_callback(struct client *_client, enum sasl_server_reply reply,
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen const char *data, const char *const *args)
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen{
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen struct pop3_client *client = (struct pop3_client *)_client;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen struct const_iovec iov[3];
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char *msg;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen size_t data_len;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen bool nodelay;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen i_assert(!client->destroyed ||
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen reply == SASL_SERVER_REPLY_CLIENT_ERROR ||
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen reply == SASL_SERVER_REPLY_MASTER_FAILED);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen switch (reply) {
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen case SASL_SERVER_REPLY_SUCCESS:
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen if (args != NULL) {
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen if (client_handle_args(client, args, TRUE, &nodelay))
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen break;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen }
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen client_destroy_success(client, "Login");
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen break;
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen case SASL_SERVER_REPLY_AUTH_FAILED:
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen case SASL_SERVER_REPLY_CLIENT_ERROR:
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (args != NULL) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (client_handle_args(client, args, FALSE, &nodelay))
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen break;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen msg = t_strconcat("-ERR ", data != NULL ?
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen data : AUTH_FAILED_MSG, NULL);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client_send_line(client, msg);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (!client->destroyed)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client_auth_failed(client, nodelay);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen break;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen case SASL_SERVER_REPLY_MASTER_FAILED:
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (data == NULL)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen client_destroy_internal_failure(client);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen else {
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen client_send_line(client,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen t_strconcat("-ERR [IN-USE] ", data, NULL));
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen client_destroy_success(client, data);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen break;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen case SASL_SERVER_REPLY_CONTINUE:
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen data_len = strlen(data);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen iov[0].iov_base = "+ ";
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen iov[0].iov_len = 2;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen iov[1].iov_base = data;
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen iov[1].iov_len = data_len;
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen iov[2].iov_base = "\r\n";
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen iov[2].iov_len = 2;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen /* don't check return value here. it gets tricky if we try
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen to call client_destroy() in here. */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen (void)o_stream_sendv(client->output, iov, 3);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen i_assert(client->io == NULL);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client->io = io_add(client->common.fd, IO_READ,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client_auth_input, client);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client_auth_input(client);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen }
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client_unref(client);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen}
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainenbool cmd_auth(struct pop3_client *client, const char *args)
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen{
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen const struct auth_mech_desc *mech;
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen const char *mech_name, *p;
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen if (!client->common.secured &&
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen strcmp(client->common.set->ssl, "required") == 0) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (client->common.set->verbose_auth) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client_syslog(&client->common, "Login failed: "
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen "SSL required for authentication");
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client->common.auth_attempts++;
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen client_send_line(client, "-ERR Authentication not allowed "
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen "until SSL/TLS is enabled.");
af8b1248fed8529d26985460acdc4b1e4b7de675Timo Sirainen return TRUE;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (*args == '\0') {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen /* Old-style SASL discovery, used by MS Outlook */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen unsigned int i, count;
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client_send_line(client, "+OK");
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen mech = auth_client_get_available_mechs(auth_client, &count);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen for (i = 0; i < count; i++) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen (client->common.secured ||
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client->common.set->disable_plaintext_auth ||
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen (mech[i].flags & MECH_SEC_PLAINTEXT) == 0))
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client_send_line(client, mech[i].name);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen client_send_line(client, ".");
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen return TRUE;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen }
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen /* <mechanism name> <initial response> */
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen p = strchr(args, ' ');
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if (p == NULL) {
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen mech_name = args;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen args = "";
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen } else {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen mech_name = t_strdup_until(args, p);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen args = p+1;
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen }
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen client_ref(client);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen sasl_server_auth_begin(&client->common, POP3_SERVICE_NAME, mech_name,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen args, sasl_callback);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (!client->common.authenticating)
0ff28df76775a0740faa4370ec72d5a6a97534bfTimo Sirainen return TRUE;
0ff28df76775a0740faa4370ec72d5a6a97534bfTimo Sirainen
0ff28df76775a0740faa4370ec72d5a6a97534bfTimo Sirainen /* don't handle input until we get the initial auth reply */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (client->io != NULL)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen io_remove(&client->io);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return TRUE;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen}
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainenstatic bool check_plaintext_auth(struct pop3_client *client)
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen{
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen if (client->common.secured ||
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen !client->common.set->disable_plaintext_auth)
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen return TRUE;
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if (client->common.set->verbose_auth) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client_syslog(&client->common, "Login failed: "
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen "Plaintext authentication disabled");
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen }
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen client_send_line(client, "-ERR "AUTH_PLAINTEXT_DISABLED_MSG);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen client->common.auth_tried_disabled_plaintext = TRUE;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen client->common.auth_attempts++;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen return FALSE;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen}
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainenbool cmd_user(struct pop3_client *client, const char *args)
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen{
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if (!check_plaintext_auth(client))
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen return TRUE;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
fbb324fedccfd1cff9fb41b64f715ca77e5d588fTimo Sirainen i_free(client->last_user);
fbb324fedccfd1cff9fb41b64f715ca77e5d588fTimo Sirainen client->last_user = i_strdup(args);
fbb324fedccfd1cff9fb41b64f715ca77e5d588fTimo Sirainen
fbb324fedccfd1cff9fb41b64f715ca77e5d588fTimo Sirainen client_send_line(client, "+OK");
fbb324fedccfd1cff9fb41b64f715ca77e5d588fTimo Sirainen return TRUE;
6fbd30cc189c5acb4cfce841e17ed0eeff5056f4Timo Sirainen}
6fbd30cc189c5acb4cfce841e17ed0eeff5056f4Timo Sirainen
6fbd30cc189c5acb4cfce841e17ed0eeff5056f4Timo Sirainenbool cmd_pass(struct pop3_client *client, const char *args)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen{
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen string_t *plain_login, *base64;
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen if (client->last_user == NULL) {
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen /* client may ignore the USER reply and only display the error
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen message from PASS */
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen if (!check_plaintext_auth(client))
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen return TRUE;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen client_send_line(client, "-ERR No username given.");
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen return TRUE;
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen }
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen /* authorization ID \0 authentication ID \0 pass */
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen plain_login = t_str_new(128);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen str_append_c(plain_login, '\0');
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen str_append(plain_login, client->last_user);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen str_append_c(plain_login, '\0');
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen str_append(plain_login, args);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen i_free(client->last_user);
9d6dec796909384293006e4289436579089d88d5Timo Sirainen client->last_user = NULL;
9d6dec796909384293006e4289436579089d88d5Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen base64 = buffer_create_dynamic(pool_datastack_create(),
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen MAX_BASE64_ENCODED_SIZE(plain_login->used));
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen base64_encode(plain_login->data, plain_login->used, base64);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen client_ref(client);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen client->auth_initializing = TRUE;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen sasl_server_auth_begin(&client->common, POP3_SERVICE_NAME, "PLAIN",
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_c(base64), sasl_callback);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen client->auth_initializing = FALSE;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if (!client->common.authenticating)
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen return TRUE;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen /* don't read any input from client until login is finished */
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if (client->io != NULL)
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen io_remove(&client->io);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen return TRUE;
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen}
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainenbool cmd_apop(struct pop3_client *client, const char *args)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen{
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen buffer_t *apop_data, *base64;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen const char *p;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (client->apop_challenge == NULL) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (client->common.set->verbose_auth) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen client_syslog(&client->common,
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen "APOP failed: APOP not enabled");
a9a3687619f38c862849f38db45506cc1d2f8f75Phil Carmody }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen client_send_line(client, "-ERR APOP not enabled.");
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch return TRUE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen /* <username> <md5 sum in hex> */
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen p = strchr(args, ' ');
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (p == NULL || strlen(p+1) != 32) {
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen if (client->common.set->verbose_auth) {
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen client_syslog(&client->common,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen "APOP failed: Invalid parameters");
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen client_send_line(client, "-ERR Invalid parameters.");
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen return TRUE;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen }
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen /* APOP challenge \0 username \0 APOP response */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen apop_data = buffer_create_dynamic(pool_datastack_create(), 128);
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen buffer_append(apop_data, client->apop_challenge,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen strlen(client->apop_challenge)+1);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen buffer_append(apop_data, args, (size_t)(p-args));
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen buffer_append_c(apop_data, '\0');
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen if (hex_to_binary(p+1, apop_data) < 0) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (client->common.set->verbose_auth) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen client_syslog(&client->common, "APOP failed: "
9d6dec796909384293006e4289436579089d88d5Timo Sirainen "Invalid characters in MD5 response");
9d6dec796909384293006e4289436579089d88d5Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen client_send_line(client,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen "-ERR Invalid characters in MD5 response.");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return TRUE;
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen }
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen base64 = buffer_create_dynamic(pool_datastack_create(),
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen MAX_BASE64_ENCODED_SIZE(apop_data->used));
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen base64_encode(apop_data->data, apop_data->used, base64);
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen client_ref(client);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen sasl_server_auth_begin(&client->common, POP3_SERVICE_NAME, "APOP",
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_c(base64), sasl_callback);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (!client->common.authenticating)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return TRUE;
9d6dec796909384293006e4289436579089d88d5Timo Sirainen
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen /* don't read any input from client until login is finished */
9d6dec796909384293006e4289436579089d88d5Timo Sirainen if (client->io != NULL)
9d6dec796909384293006e4289436579089d88d5Timo Sirainen io_remove(&client->io);
9d6dec796909384293006e4289436579089d88d5Timo Sirainen return TRUE;
9d6dec796909384293006e4289436579089d88d5Timo Sirainen}
9d6dec796909384293006e4289436579089d88d5Timo Sirainen