client-authenticate.c revision afe367fbbb7e1c7b3d1f82eae517bfee80a00738
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void client_auth_failed(struct imap_client *client);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconst char *client_authenticate_get_capabilities(bool secured)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int i, count;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mech = auth_client_get_available_mechs(auth_client, &count);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (i = 0; i < count; i++) {
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen /* a) transport is secured
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen b) auth mechanism isn't plaintext
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen c) we allow insecure authentication
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void client_auth_input(struct imap_client *client)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (i_stream_next_line(client->input) == NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* @UNSAFE */
73a87c2ff65c6116cde6fb158dfddb8ef7346901Timo Sirainen sasl_server_auth_client_error(&client->common,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "Authentication aborted");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen auth_client_request_continue(client->common.auth_request, line);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* clear sensitive data */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void client_auth_failed(struct imap_client *client)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* get back to normal client input. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen client->io = io_add(client->common.fd, IO_READ,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic bool client_handle_args(struct imap_client *client,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *reason = NULL, *host = NULL, *destuser = NULL, *pass = NULL;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen bool proxy = FALSE, temp = FALSE, nologin = !success;
637455ebee0453f860c9bce0626c485e35fb83deTimo Sirainen !login_proxy_is_ourself(&client->common, host, port, destuser)) {
637455ebee0453f860c9bce0626c485e35fb83deTimo Sirainen /* we want to proxy the connection to another server.
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen don't do this unless authentication succeeded. with
637455ebee0453f860c9bce0626c485e35fb83deTimo Sirainen master user proxying we can get FAIL with proxy still set.
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen proxy host=.. [port=..] [destuser=..] pass=.. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (imap_proxy_new(client, host, port, destuser, pass) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* IMAP referral
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen [nologin] referral host=.. [port=..] [destuser=..]
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen NO [REFERRAL imap://destuser;AUTH=..@host:port/] Can't login.
e790c9b1fc56bca7ebd59dc289cb5035e3afcee5Timo Sirainen OK [...] Logged in, but you should use this server instead.
e790c9b1fc56bca7ebd59dc289cb5035e3afcee5Timo Sirainen .. [REFERRAL ..] (Reason from auth server)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_printfa(reply, "[REFERRAL imap://%s;AUTH=%s@%s",
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen destuser, client->common.auth_mech_name, host);
65b94e73c305dcb209cf958f938b93ec061c67a9Timo Sirainen str_append(reply, "Try this server instead.");
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen str_append(reply, "Logged in, but you should use "
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen "this server instead.");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen client_destroy(client, "Login with referral");
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen } else if (nologin) {
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen /* Authentication went ok, but for some reason user isn't
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen allowed to log in. Shouldn't probably happen. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void sasl_callback(struct client *_client, enum sasl_server_reply reply,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct imap_client *client = (struct imap_client *)_client;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *msg;
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen msg = reply == SASL_SERVER_REPLY_AUTH_FAILED ? "NO " : "BAD ";
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen msg = t_strconcat(msg, data != NULL ? data : AUTH_FAILED_MSG,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* don't check return value here. it gets tricky if we try
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen to call client_destroy() in here. */
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen client->io = io_add(client->common.fd, IO_READ,
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainenstatic int client_auth_begin(struct imap_client *client, const char *mech_name,
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen sasl_server_auth_begin(&client->common, IMAP_SERVICE_NAME, mech_name,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* don't handle input until we get the initial auth reply */
ddb018bc886680f462463b2c87f983fdedbf6cf0Timo Sirainenint cmd_authenticate(struct imap_client *client, const struct imap_arg *args)
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen /* we want only one argument: authentication mechanism name */
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
37ee89f3cba22cd975912a882f0d3097fa5031e1Timo Sirainen /* optional SASL initial response */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return client_auth_begin(client, mech_name, init_resp);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint cmd_login(struct imap_client *client, const struct imap_arg *args)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* two arguments: username and password */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (args[1].type != IMAP_ARG_ATOM && args[1].type != IMAP_ARG_STRING)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!client->common.secured && disable_plaintext_auth) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen client_syslog(&client->common, "Login failed: "
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "Plaintext authentication disabled");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen client->common.auth_tried_disabled_plaintext = TRUE;
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen "* BAD [ALERT] Plaintext authentication is disabled, "
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen "but your client sent password in plaintext anyway. "
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "If anyone was listening, the password was exposed.");
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen client_send_tagline(client, "NO "AUTH_PLAINTEXT_DISABLED_MSG);
4fded1eec06aba9ce37887ac30619768760cd0d0Timo Sirainen /* authorization ID \0 authentication ID \0 pass */
4fded1eec06aba9ce37887ac30619768760cd0d0Timo Sirainen plain_login = buffer_create_dynamic(pool_datastack_create(), 64);
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen buffer_append(plain_login, user, strlen(user));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen buffer_append(plain_login, pass, strlen(pass));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen base64 = buffer_create_dynamic(pool_datastack_create(),
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen base64_encode(plain_login->data, plain_login->used, base64);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return client_auth_begin(client, "PLAIN", str_c(base64));