client-authenticate.c revision 97db4761382024093f441e4bc78ba8b6a056504d
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenconst char *capability_string = POP3_CAPABILITY_REPLY;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenbool cmd_capa(struct pop3_client *client, const char *args ATTR_UNUSED)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen unsigned int i, count;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if (!client->common.set->disable_plaintext_auth ||
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
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen !client->common.set->disable_plaintext_auth ||
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenstatic void client_auth_input(struct pop3_client *client)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* @UNSAFE */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen line = i_stream_next_line(client->common.input);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen sasl_server_auth_client_error(&client->common,
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen "Authentication aborted");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen auth_client_request_continue(client->common.auth_request, line);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen /* clear sensitive data */
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainenstatic void client_authfail_delay_timeout(struct pop3_client *client)
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen /* get back to normal client input. */
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen client->io = io_add(client->common.fd, IO_READ, client_input, client);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenvoid client_auth_failed(struct pop3_client *client, bool nodelay)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen client->io = io_add(client->common.fd, IO_READ,
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 if (delay_msecs > CLIENT_LOGIN_IDLE_TIMEOUT_MSECS)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen delay_msecs = CLIENT_LOGIN_IDLE_TIMEOUT_MSECS - 1000;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen timeout_add(delay_msecs, client_authfail_delay_timeout, client);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic bool client_handle_args(struct pop3_client *client,
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen const char *reason = NULL, *host = NULL, *destuser = NULL, *pass = NULL;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen bool proxy = FALSE, temp = FALSE, nologin = !success;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* already handled in login-common */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen i_info("Ignoring unknown passdb extra field: %s", key);
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 proxy host=.. [port=..] [destuser=..] pass=.. */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (pop3_proxy_new(client, host, port, destuser, master_user,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen str_append(reply, "[IN-USE] "AUTH_TEMP_FAILED_MSG);
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainenstatic void sasl_callback(struct client *_client, enum sasl_server_reply reply,
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen struct pop3_client *client = (struct pop3_client *)_client;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char *msg;
a505d1beb29cbffab724b92ad16d0c44ebbaffb9Timo Sirainen if (client_handle_args(client, args, TRUE, &nodelay))
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (client_handle_args(client, args, FALSE, &nodelay))
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen /* don't check return value here. it gets tricky if we try
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen to call client_destroy() in here. */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client->io = io_add(client->common.fd, IO_READ,
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainenbool cmd_auth(struct pop3_client *client, const char *args)
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen const char *mech_name, *p;
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen strcmp(client->common.set->ssl, "required") == 0) {
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client_syslog(&client->common, "Login failed: "
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen "SSL required for authentication");
0d16525a729011f4fced989a3da74d755ea49e6dTimo Sirainen client_send_line(client, "-ERR Authentication not allowed "
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen "until SSL/TLS is enabled.");
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen /* Old-style SASL discovery, used by MS Outlook */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen unsigned int i, count;
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 &&
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen /* <mechanism name> <initial response> */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen sasl_server_auth_begin(&client->common, POP3_SERVICE_NAME, mech_name,
0ff28df76775a0740faa4370ec72d5a6a97534bfTimo Sirainen /* don't handle input until we get the initial auth reply */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainenstatic bool check_plaintext_auth(struct pop3_client *client)
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen client_syslog(&client->common, "Login failed: "
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainen "Plaintext authentication disabled");
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen client_send_line(client, "-ERR "AUTH_PLAINTEXT_DISABLED_MSG);
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen client->common.auth_tried_disabled_plaintext = TRUE;
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainenbool cmd_user(struct pop3_client *client, const char *args)
6fbd30cc189c5acb4cfce841e17ed0eeff5056f4Timo Sirainenbool cmd_pass(struct pop3_client *client, const char *args)
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen /* client may ignore the USER reply and only display the error
dcf49e7ccf042982fde41ce256723f925fb9f1e4Timo Sirainen message from PASS */
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen client_send_line(client, "-ERR No username given.");
70afae43cc78ea6ecca83f6c587072c442a15ec1Timo Sirainen /* authorization ID \0 authentication ID \0 pass */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen base64 = buffer_create_dynamic(pool_datastack_create(),
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen base64_encode(plain_login->data, plain_login->used, base64);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen sasl_server_auth_begin(&client->common, POP3_SERVICE_NAME, "PLAIN",
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen /* don't read any input from client until login is finished */
7f97ca94363c9e38fbbaaef204d6d01c54af6fc4Timo Sirainenbool cmd_apop(struct pop3_client *client, const char *args)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen const char *p;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen "APOP failed: APOP not enabled");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen client_send_line(client, "-ERR APOP not enabled.");
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen /* <username> <md5 sum in hex> */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen "APOP failed: Invalid parameters");
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen client_send_line(client, "-ERR Invalid parameters.");
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,
62ccd8152d2f0142ab3301da4f5270b9d4f06718Timo Sirainen buffer_append(apop_data, args, (size_t)(p-args));
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen client_syslog(&client->common, "APOP failed: "
9d6dec796909384293006e4289436579089d88d5Timo Sirainen "Invalid characters in MD5 response");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen "-ERR Invalid characters in MD5 response.");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen base64 = buffer_create_dynamic(pool_datastack_create(),
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen base64_encode(apop_data->data, apop_data->used, base64);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen sasl_server_auth_begin(&client->common, POP3_SERVICE_NAME, "APOP",
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen /* don't read any input from client until login is finished */