client-authenticate.c revision cca4ba2a504d70a9fe9fee37f8433997359de52c
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "login-common.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "base64.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "buffer.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "ioloop.h"
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen#include "istream.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "ostream.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "safe-memset.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "str.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "str-sanitize.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "net.h"
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainen#include "imap-resp-code.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "imap-parser.h"
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainen#include "imap-url.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "auth-client.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "client.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "client-authenticate.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "imap-proxy.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include <stdlib.h>
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainenvoid client_authenticate_get_capabilities(struct client *client, string_t *str)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen{
a18335e18aac7fc219b6f18dde083359155cc524Timo Sirainen const struct auth_mech_desc *mech;
a18335e18aac7fc219b6f18dde083359155cc524Timo Sirainen unsigned int i, count;
a18335e18aac7fc219b6f18dde083359155cc524Timo Sirainen
a18335e18aac7fc219b6f18dde083359155cc524Timo Sirainen mech = sasl_server_get_advertised_mechs(client, &count);
a18335e18aac7fc219b6f18dde083359155cc524Timo Sirainen for (i = 0; i < count; i++) {
a18335e18aac7fc219b6f18dde083359155cc524Timo Sirainen str_append_c(str, ' ');
a18335e18aac7fc219b6f18dde083359155cc524Timo Sirainen str_append(str, "AUTH=");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen str_append(str, mech[i].name);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
499fec3443374cc89fb8c83b8027c1614097d7a3Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainenvoid imap_client_auth_result(struct client *client,
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainen enum client_auth_result result,
a18335e18aac7fc219b6f18dde083359155cc524Timo Sirainen const struct client_auth_reply *reply,
a18335e18aac7fc219b6f18dde083359155cc524Timo Sirainen const char *text)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen struct imap_url url;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen string_t *referral;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen switch (result) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen case CLIENT_AUTH_RESULT_SUCCESS:
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen /* nothing to be done for IMAP */
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen break;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen case CLIENT_AUTH_RESULT_REFERRAL_SUCCESS:
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen case CLIENT_AUTH_RESULT_REFERRAL_NOLOGIN:
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen /* IMAP referral
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen [nologin] referral host=.. [port=..] [destuser=..]
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen [reason=..]
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen NO [REFERRAL imap://destuser;AUTH=..@host:port/] Can't login.
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen OK [...] Logged in, but you should use this server instead.
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen .. [REFERRAL ..] (Reason from auth server)
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen */
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen referral = t_str_new(128);
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen memset(&url, 0, sizeof(url));
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen url.userid = reply->destuser;
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen url.auth_type = client->auth_mech_name;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen url.host_name = reply->host;
11352dc3e4b29f3d2763c82f8ea4f99e8daf4fa3Timo Sirainen if (reply->port != 143) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen url.have_port = TRUE;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen url.port = reply->port;
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen }
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen str_append(referral, "REFERRAL ");
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen str_append(referral, imap_url_create(&url));
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (result == CLIENT_AUTH_RESULT_REFERRAL_SUCCESS) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_send_reply_code(client, IMAP_CMD_REPLY_OK,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen str_c(referral), text);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } else {
cd8507179823de33d6e8242e10dbc15d136245b5Timo Sirainen client_send_reply_code(client, IMAP_CMD_REPLY_NO,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen str_c(referral), text);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen break;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen case CLIENT_AUTH_RESULT_ABORTED:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen client_send_reply(client, IMAP_CMD_REPLY_BAD, text);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case CLIENT_AUTH_RESULT_AUTHFAILED_REASON:
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen client_send_reply_code(client, IMAP_CMD_REPLY_NO,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen "ALERT", text);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen break;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen case CLIENT_AUTH_RESULT_AUTHZFAILED:
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen client_send_reply_code(client, IMAP_CMD_REPLY_NO,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen IMAP_RESP_CODE_AUTHZFAILED, text);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen break;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen case CLIENT_AUTH_RESULT_TEMPFAIL:
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen client_send_reply_code(client, IMAP_CMD_REPLY_NO,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen IMAP_RESP_CODE_UNAVAILABLE, text);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen break;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen case CLIENT_AUTH_RESULT_SSL_REQUIRED:
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen client_send_reply_code(client, IMAP_CMD_REPLY_NO,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen IMAP_RESP_CODE_PRIVACYREQUIRED, text);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen break;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen case CLIENT_AUTH_RESULT_AUTHFAILED:
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen client_send_reply_code(client, IMAP_CMD_REPLY_NO,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen IMAP_RESP_CODE_AUTHFAILED, text);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen break;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenimap_client_auth_begin(struct imap_client *imap_client, const char *mech_name,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *init_resp)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen char *prefix;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen prefix = i_strdup_printf("%d%s",
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen imap_client->client_ignores_capability_resp_code,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen imap_client->cmd_tag);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_free(imap_client->common.master_data_prefix);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen imap_client->common.master_data_prefix = (void *)prefix;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen imap_client->common.master_data_prefix_len = strlen(prefix)+1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return client_auth_begin(&imap_client->common, mech_name, init_resp);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenint cmd_authenticate(struct imap_client *imap_client, bool *parsed_r)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* NOTE: This command's input is handled specially because the
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen SASL-IR can be large. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct client *client = &imap_client->common;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const unsigned char *data;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen size_t i, size;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen int ret;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *parsed_r = FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* <auth mechanism name> [<initial SASL response>] */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!imap_client->auth_mech_name_parsed) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen data = i_stream_get_data(client->input, &size);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (i = 0; i < size; i++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (data[i] == ' ' ||
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen data[i] == '\r' || data[i] == '\n')
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (i == size)
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen return 0;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen if (i == 0) {
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen /* empty mechanism name */
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen imap_client->skip_line = TRUE;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen return -1;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen }
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen i_free(client->auth_mech_name);
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen client->auth_mech_name = i_strndup(data, i);
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen imap_client->auth_mech_name_parsed = TRUE;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen if (data[i] == ' ')
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen i++;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen i_stream_skip(client->input, i);
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen }
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen /* get SASL-IR, if any */
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen if ((ret = client_auth_read_line(client)) <= 0)
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen return ret;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen *parsed_r = TRUE;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen imap_client->auth_mech_name_parsed = FALSE;
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen return imap_client_auth_begin(imap_client,
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen t_strdup(client->auth_mech_name),
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen t_strdup(str_c(client->auth_response)));
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen}
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainenint cmd_login(struct imap_client *imap_client, const struct imap_arg *args)
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen{
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen struct client *client = &imap_client->common;
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen const char *user, *pass;
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen string_t *plain_login, *base64;
8305127d1074cf9a1e25dec9be2735276462079dTimo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen /* two arguments: username and password */
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen if (!imap_arg_get_astring(&args[0], &user) ||
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen !imap_arg_get_astring(&args[1], &pass) ||
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen !IMAP_ARG_IS_EOL(&args[2]))
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return -1;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!client_check_plaintext_auth(client, TRUE))
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return 1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen /* authorization ID \0 authentication ID \0 pass */
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen plain_login = buffer_create_dynamic(pool_datastack_create(), 64);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buffer_append_c(plain_login, '\0');
596433ccbca59ce2328dc1d029586154cd937155Timo Sirainen buffer_append(plain_login, user, strlen(user));
596433ccbca59ce2328dc1d029586154cd937155Timo Sirainen buffer_append_c(plain_login, '\0');
15b5076a239682277b44880e33ea23b55fff7e71Timo Sirainen buffer_append(plain_login, pass, strlen(pass));
15b5076a239682277b44880e33ea23b55fff7e71Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen base64 = buffer_create_dynamic(pool_datastack_create(),
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen MAX_BASE64_ENCODED_SIZE(plain_login->used));
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen base64_encode(plain_login->data, plain_login->used, base64);
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen return imap_client_auth_begin(imap_client, "PLAIN", str_c(base64));
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen}
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen