client-authenticate.c revision 76b43e4417bab52e913da39b5f5bc2a130d3f149
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
51b979b6414b940f04677a7e2d064be119345954Timo Sirainenconst char *client_authenticate_get_capabilities(bool secured)
589a9c6e8ee22071c14171c04bfc6bfe17121871Timo Sirainen unsigned int i, count;
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen mech = auth_client_get_available_mechs(auth_client, &count);
ef5fb27361cc5e15766e85e28355750ff04b13c9Timo Sirainen for (i = 0; i < count; i++) {
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen /* a) transport is secured
a53cb86b4d733d9c48ee4d285bed477c80825804Timo Sirainen b) auth mechanism isn't plaintext
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen c) we allow insecure authentication
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenstatic void client_auth_input(struct imap_client *client)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (i_stream_next_line(client->input) == NULL)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen /* @UNSAFE */
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainen sasl_server_auth_client_error(&client->common,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Authentication aborted");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen auth_client_request_continue(client->common.auth_request, line);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* clear sensitive data */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool client_handle_args(struct imap_client *client,
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen const char *reason = NULL, *host = NULL, *destuser = NULL, *pass = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bool proxy = FALSE, temp = FALSE, nologin = !success;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen !login_proxy_is_ourself(&client->common, host, port, destuser)) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* we want to proxy the connection to another server.
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen don't do this unless authentication succeeded. with
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen master user proxying we can get FAIL with proxy still set.
b9c44feadade0481b957f2978640afb3317bd1dfTimo Sirainen proxy host=.. [port=..] [destuser=..] pass=.. */
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen if (imap_proxy_new(client, host, port, destuser, pass) < 0)
807b48fe1f6a57b01ed2cc20247d5b5e3facc562Timo Sirainen /* IMAP referral
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen [nologin] referral host=.. [port=..] [destuser=..]
e169102fb38ce788b76c2a344bee7d77079dea05Timo Sirainen NO [REFERRAL imap://destuser;AUTH=..@host:port/] Can't login.
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen OK [...] Logged in, but you should use this server instead.
db87d16551d1081ada01f787ea21aa3ed1402c31Timo Sirainen .. [REFERRAL ..] (Reason from auth server)
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen str_printfa(reply, "[REFERRAL imap://%s;AUTH=%s@%s",
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen destuser, client->common.auth_mech_name, host);
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen str_append(reply, "Try this server instead.");
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen str_append(reply, "Logged in, but you should use "
c8adec8db635f5efb13b9879a5f3fb523abdc969Timo Sirainen "this server instead.");
807b48fe1f6a57b01ed2cc20247d5b5e3facc562Timo Sirainen client_destroy(client, "Login with referral");
dc912088f84c263db1609435c2f5d7cb29bf1a33Timo Sirainen } else if (nologin) {
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen /* Authentication went ok, but for some reason user isn't
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen allowed to log in. Shouldn't probably happen. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* get back to normal client input. */
26ff8f8a4867bf8e9551a27a2de8c12cd138b065Timo Sirainen client->io = io_add(client->common.fd, IO_READ,
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainenstatic void sasl_callback(struct client *_client, enum sasl_server_reply reply,
1f43c8ac132c153c224c4fffe34b2c3075d87ef7Timo Sirainen struct imap_client *client = (struct imap_client *)_client;
020a39a395d2adb768e0179631b37bc78ecd9471Timo Sirainen const char *msg;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen msg = reply == SASL_SERVER_REPLY_AUTH_FAILED ? "NO " : "BAD ";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen msg = t_strconcat(msg, data != NULL ? data : AUTH_FAILED_MSG,
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen /* get back to normal client input. */
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen client->io = io_add(client->common.fd, IO_READ,
15cc66ca72982a43e3bfa58f307adc57e9caa52dTimo Sirainen /* don't check return value here. it gets tricky if we try
a045c3aba2610c6ed0bf1c346df1c6d8f7b9fbfdTimo Sirainen to call client_destroy() in here. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->io = io_add(client->common.fd, IO_READ,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint cmd_authenticate(struct imap_client *client, const struct imap_arg *args)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we want only one argument: authentication mechanism name */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* optional SASL initial response */
9404a7b90dcb80d31bd37ee2493f03751acdb1bdTimo Sirainen sasl_server_auth_begin(&client->common, IMAP_SERVICE_NAME, mech_name,
2674b4f0cf8f3c203d8e56b29735f5e267038dafTimo Sirainen /* don't handle input until we get the initial auth reply */
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainenint cmd_login(struct imap_client *client, const struct imap_arg *args)
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen /* two arguments: username and password */
e376693bfa3985232c41df99c7010fca22612c89Timo Sirainen if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (args[1].type != IMAP_ARG_ATOM && args[1].type != IMAP_ARG_STRING)
d6a1fa1d65c6d1996937802c2482c0f14dd821a7Timo Sirainen if (!client->common.secured && disable_plaintext_auth) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client_syslog(&client->common, "Login failed: "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Plaintext authentication disabled");
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen client->common.auth_tried_disabled_plaintext = TRUE;
b92813e2f96d4b28f989528ed5dd6115da7d9bdbTimo Sirainen "* BAD [ALERT] Plaintext authentication is disabled, "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "but your client sent password in plaintext anyway. "
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen "If anyone was listening, the password was exposed.");
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen client_send_tagline(client, "NO "AUTH_PLAINTEXT_DISABLED_MSG);
db5164c9a1129af0cfb11fc18d88da361a8011fbTimo Sirainen /* authorization ID \0 authentication ID \0 pass */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen plain_login = buffer_create_dynamic(pool_datastack_create(), 64);
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen buffer_append(plain_login, user, strlen(user));
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen buffer_append(plain_login, pass, strlen(pass));
d152ccd0d29fae1bc6092bf198ee7eb843202f96Timo Sirainen base64 = buffer_create_dynamic(pool_datastack_create(),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen base64_encode(plain_login->data, plain_login->used, base64);
aa0647f2debf0d48d504a321186f66c85596aaf4Timo Sirainen sasl_server_auth_begin(&client->common, IMAP_SERVICE_NAME, "PLAIN",
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen /* don't read any input from client until login is finished */