client-authenticate.c revision 2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "common.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "base64.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "buffer.h"
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen#include "ioloop.h"
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen#include "istream.h"
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen#include "ostream.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "safe-memset.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "str.h"
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen#include "imap-parser.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "auth-client.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "../auth/auth-mech-desc.h"
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen#include "client.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "client-authenticate.h"
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen#include "auth-common.h"
7891c8e6debdcfec552cb1beea2a0230fe89957bTimo Sirainen#include "master.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenconst char *client_authenticate_get_capabilities(int tls)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen static enum auth_mech cached_auth_mechs = 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen static char *cached_capability = NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen enum auth_mech auth_mechs;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen string_t *str;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int i;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen auth_mechs = auth_client_get_available_mechs(auth_client);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (auth_mechs == cached_auth_mechs)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return cached_capability;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen cached_auth_mechs = auth_mechs;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_free(cached_capability);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen str = t_str_new(128);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen for (i = 0; i < AUTH_MECH_COUNT; i++) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if ((auth_mechs & auth_mech_desc[i].mech) &&
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen auth_mech_desc[i].name != NULL &&
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen (tls || !auth_mech_desc[i].plaintext ||
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen !disable_plaintext_auth)) {
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen str_append_c(str, ' ');
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen str_append(str, "AUTH=");
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen str_append(str, auth_mech_desc[i].name);
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen }
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen }
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen cached_capability = i_strdup_empty(str_c(str));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return cached_capability;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
104318260228780a5c6b3181b3401e8e504e2776Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic struct auth_mech_desc *auth_mech_find(const char *name)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int i;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = 0; i < AUTH_MECH_COUNT; i++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (auth_mech_desc[i].name != NULL &&
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen strcasecmp(auth_mech_desc[i].name, name) == 0)
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen return &auth_mech_desc[i];
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainenstatic void client_auth_abort(struct imap_client *client, const char *msg)
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen{
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen client->authenticating = FALSE;
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen if (client->common.auth_request != NULL) {
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen auth_client_request_abort(client->common.auth_request);
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen client->common.auth_request = NULL;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen }
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen client_send_tagline(client, msg != NULL ?
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen t_strconcat("NO ", msg, NULL) :
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen "NO Authentication failed.");
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen o_stream_flush(client->output);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen /* get back to normal client input */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (client->common.io != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_remove(client->common.io);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->common.io = client->common.fd == -1 ? NULL :
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_add(client->common.fd, IO_READ, client_input, client);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic void master_callback(struct client *_client, int success)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen{
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct imap_client *client = (struct imap_client *) _client;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen const char *reason = NULL;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (success) {
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen reason = t_strconcat("Login: ", client->common.virtual_user,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen reason = t_strconcat("Internal login failure: ",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->common.virtual_user, NULL);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_send_line(client, "* BYE Internal login failure.");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
7fe37c2b0e4cd2a39896ab16e47eb418a59e3934Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_destroy(client, reason);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void client_send_auth_data(struct imap_client *client,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const unsigned char *data, size_t size)
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen buffer_t *buf;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen t_push();
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen buf = buffer_create_dynamic(data_stack_pool, size*2, (size_t)-1);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen buffer_append(buf, "+ ", 2);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen base64_encode(data, size, buf);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen buffer_append(buf, "\r\n", 2);
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen o_stream_send(client->output, buffer_get_data(buf, NULL),
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen buffer_get_used_size(buf));
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen o_stream_flush(client->output);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen t_pop();
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen}
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenstatic void login_callback(struct auth_request *request,
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen struct auth_client_request_reply *reply,
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen const unsigned char *data, void *context)
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen{
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen struct imap_client *client = context;
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen const char *error;
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen const void *ptr;
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen size_t size;
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen switch (auth_callback(request, reply, data, &client->common,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen master_callback, &error)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case -1:
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* login failed */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_auth_abort(client, error);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen case 0:
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen /* continue */
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen ptr = buffer_get_data(client->plain_login, &size);
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen auth_client_request_continue(request, ptr, size);
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen buffer_set_used_size(client->plain_login, 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen default:
cd2ed64888b42b481cde6bb9548c8520516fa3e9Timo Sirainen /* success, we should be able to log in. if we fail, just
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen disconnect the client. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client->authenticating = FALSE;
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen client_send_tagline(client, "OK Logged in.");
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenint cmd_login(struct imap_client *client, struct imap_arg *args)
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen{
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen const char *user, *pass, *error;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* two arguments: username and password */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen return FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (args[1].type != IMAP_ARG_ATOM && args[1].type != IMAP_ARG_STRING)
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen return FALSE;
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen if (args[2].type != IMAP_ARG_EOL)
96d19229e5f322411eb84446e5477d8170cfa5afTimo Sirainen return FALSE;
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen user = IMAP_ARG_STR(&args[0]);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen pass = IMAP_ARG_STR(&args[1]);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!client->tls && disable_plaintext_auth) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_send_line(client,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "* BAD [ALERT] Plaintext authentication is disabled, "
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen "but your client sent password in plaintext anyway."
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "If anyone was listening, the password was exposed.");
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen client_send_tagline(client,
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen "NO Plaintext authentication disabled.");
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen return TRUE;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen }
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen /* authorization ID \0 authentication ID \0 pass */
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen buffer_set_used_size(client->plain_login, 0);
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen buffer_append_c(client->plain_login, '\0');
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen buffer_append(client->plain_login, user, strlen(user));
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen buffer_append_c(client->plain_login, '\0');
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen buffer_append(client->plain_login, pass, strlen(pass));
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen client->common.auth_request =
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen auth_client_request_new(auth_client, AUTH_MECH_PLAIN,
32b78da5dfbbf6a06b3dbdc9278c60b55714f9bcTimo Sirainen AUTH_PROTOCOL_IMAP, login_callback,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client, &error);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->common.auth_request == NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_send_tagline(client, t_strconcat(
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "NO Login failed: ", error, NULL));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return TRUE;
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen }
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen /* don't read any input from client until login is finished */
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen if (client->common.io != NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_remove(client->common.io);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen client->common.io = NULL;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen }
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen client->authenticating = TRUE;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen return TRUE;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen}
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainenstatic void authenticate_callback(struct auth_request *request,
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen struct auth_client_request_reply *reply,
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen const unsigned char *data, void *context)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen{
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen struct imap_client *client = context;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen const char *error;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen switch (auth_callback(request, reply, data, &client->common,
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen master_callback, &error)) {
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen case -1:
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen /* login failed */
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen client_auth_abort(client, error);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen break;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen case 0:
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen /* continue */
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen client_send_auth_data(client, data, reply->data_size);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen break;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen default:
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen /* success, we should be able to log in. if we fail, just
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen disconnect the client. */
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen client->authenticating = FALSE;
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen client_send_tagline(client, "OK Logged in.");
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen }
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen}
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainenstatic void client_auth_input(void *context)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen{
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen struct imap_client *client = context;
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen buffer_t *buf;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen char *line;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen size_t linelen, bufsize;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen if (!client_read(client))
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen return;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen if (client->skip_line) {
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen if (i_stream_next_line(client->input) == NULL)
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen return;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen client->skip_line = FALSE;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen }
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen /* @UNSAFE */
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen line = i_stream_next_line(client->input);
e0740628f6ca05f4bc79a9d8a90b650f4d38d4d0Timo Sirainen if (line == NULL)
e0740628f6ca05f4bc79a9d8a90b650f4d38d4d0Timo Sirainen return;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (strcmp(line, "*") == 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_auth_abort(client, "Authentication aborted");
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen return;
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen }
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen linelen = strlen(line);
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen buf = buffer_create_static_hard(data_stack_pool, linelen);
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (base64_decode((const unsigned char *) line, linelen,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen NULL, buf) <= 0) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* failed */
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen client_auth_abort(client, "Invalid base64 data");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else if (client->common.auth_request == NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_auth_abort(client, "Don't send unrequested data");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen auth_client_request_continue(client->common.auth_request,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen buffer_get_data(buf, NULL),
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen buffer_get_used_size(buf));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen /* clear sensitive data */
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen safe_memset(line, 0, linelen);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen bufsize = buffer_get_used_size(buf);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen safe_memset(buffer_free_without_data(buf), 0, bufsize);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen}
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainenint cmd_authenticate(struct imap_client *client, struct imap_arg *args)
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen{
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen struct auth_mech_desc *mech;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const char *mech_name, *error;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* we want only one argument: authentication mechanism name */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (args[1].type != IMAP_ARG_EOL)
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen return FALSE;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen mech_name = IMAP_ARG_STR(&args[0]);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen if (*mech_name == '\0')
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen return FALSE;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen mech = auth_mech_find(mech_name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (mech == NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client_send_tagline(client,
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen "NO Unsupported authentication mechanism.");
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen return TRUE;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen }
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen if (!client->tls && mech->plaintext && disable_plaintext_auth) {
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen client_send_tagline(client,
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen "NO Plaintext authentication disabled.");
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen return TRUE;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen }
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen client->common.auth_request =
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen auth_client_request_new(auth_client, mech->mech,
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen AUTH_PROTOCOL_IMAP,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen authenticate_callback,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen client, &error);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (client->common.auth_request != NULL) {
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen /* following input data will go to authentication */
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen if (client->common.io != NULL)
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen io_remove(client->common.io);
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen client->common.io = io_add(client->common.fd, IO_READ,
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen client_auth_input, client);
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen client->authenticating = TRUE;
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen } else {
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen client_send_tagline(client, t_strconcat(
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen "NO Authentication failed: ", error, NULL));
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen }
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen return TRUE;
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen}
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen