client-authenticate.c revision 02ccba3d3be96444abd15b5254864c9151bbeb30
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2007 Dovecot authors, see the included COPYING file */
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenconst char *client_authenticate_get_capabilities(bool secured)
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen unsigned int i, count;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen mech = auth_client_get_available_mechs(auth_client, &count);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen for (i = 0; i < count; i++) {
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen /* a) transport is secured
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen b) auth mechanism isn't plaintext
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen c) we allow insecure authentication
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic void client_auth_input(struct imap_client *client)
b3fc5293379feb3640b23622bcc8f5f8d7f1e81dJosef 'Jeff' Sipek if (i_stream_next_line(client->input) == NULL)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* @UNSAFE */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen sasl_server_auth_client_error(&client->common,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Authentication aborted");
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen auth_client_request_continue(client->common.auth_request, line);
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen /* clear sensitive data */
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainenstatic bool client_handle_args(struct imap_client *client,
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen const char *reason = NULL, *host = NULL, *destuser = NULL, *pass = NULL;
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen bool proxy = FALSE, temp = FALSE, nologin = !success;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen !login_proxy_is_ourself(&client->common, host, port, destuser)) {
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen /* we want to proxy the connection to another server.
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen don't do this unless authentication succeeded. with
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen master user proxying we can get FAIL with proxy still set.
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen proxy host=.. [port=..] [destuser=..] pass=.. */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (imap_proxy_new(client, host, port, destuser, pass) < 0)
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen /* IMAP referral
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen [nologin] referral host=.. [port=..] [destuser=..]
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen NO [REFERRAL imap://destuser;AUTH=..@host:port/] Can't login.
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen OK [...] Logged in, but you should use this server instead.
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen .. [REFERRAL ..] (Reason from auth server)
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen str_printfa(reply, "[REFERRAL imap://%s;AUTH=%s@%s",
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen destuser, client->common.auth_mech_name, host);
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainen str_append(reply, "Try this server instead.");
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen str_append(reply, "Logged in, but you should use "
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen "this server instead.");
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen client_destroy(client, "Login with referral");
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen } else if (nologin) {
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen /* Authentication went ok, but for some reason user isn't
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen allowed to log in. Shouldn't probably happen. */
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen /* get back to normal client input. */
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen client->io = io_add(client->common.fd, IO_READ,
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenstatic void sasl_callback(struct client *_client, enum sasl_server_reply reply,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct imap_client *client = (struct imap_client *)_client;
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen const char *msg;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen msg = reply == SASL_SERVER_REPLY_AUTH_FAILED ? "NO " : "BAD ";
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen msg = t_strconcat(msg, data != NULL ? data : AUTH_FAILED_MSG,
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen /* get back to normal client input. */
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen client->io = io_add(client->common.fd, IO_READ,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* don't check return value here. it gets tricky if we try
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen to call client_destroy() in here. */
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen client->io = io_add(client->common.fd, IO_READ,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenint cmd_authenticate(struct imap_client *client, const struct imap_arg *args)
66dc739bb67d678770e1b7a7bc75f4f6f9523d2aTimo Sirainen /* we want only one argument: authentication mechanism name */
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen /* optional SASL initial response */
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen sasl_server_auth_begin(&client->common, IMAP_SERVICE_NAME, mech_name,
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainen /* don't handle input until we get the initial auth reply */
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainenint cmd_login(struct imap_client *client, const struct imap_arg *args)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen /* two arguments: username and password */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen if (args[1].type != IMAP_ARG_ATOM && args[1].type != IMAP_ARG_STRING)
54bd0fec0be357266e299466a582f3c9269884e9Timo Sirainen if (!client->common.secured && disable_plaintext_auth) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen client_syslog(&client->common, "Login failed: "
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "Plaintext authentication disabled");
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen client->common.auth_tried_disabled_plaintext = TRUE;
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen "* BAD [ALERT] Plaintext authentication is disabled, "
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "but your client sent password in plaintext anyway. "
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "If anyone was listening, the password was exposed.");
52041ed691a26ca80e4e805765e9f55ec097c8f1Martti Rannanjärvi client_send_tagline(client, "NO "AUTH_PLAINTEXT_DISABLED_MSG);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* authorization ID \0 authentication ID \0 pass */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen plain_login = buffer_create_dynamic(pool_datastack_create(), 64);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen buffer_append(plain_login, user, strlen(user));
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen buffer_append(plain_login, pass, strlen(pass));
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen base64 = buffer_create_dynamic(pool_datastack_create(),
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen base64_encode(plain_login->data, plain_login->used, base64);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen sasl_server_auth_begin(&client->common, IMAP_SERVICE_NAME, "PLAIN",
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen /* don't read any input from client until login is finished */