client-authenticate.c revision d1414c09cf0d58ac983054e2f4e1a1f329272dcf
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (C) 2002 Timo Sirainen */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "common.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "base64.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "buffer.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "ioloop.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "istream.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "ostream.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "safe-memset.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "str.h"
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen#include "auth-client.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "../pop3/capability.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "ssl-proxy.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "master.h"
ef332139cd9eba92c37b14df6723f896dba8fcd0Aki Tuomi#include "auth-common.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "client.h"
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen#include "client-authenticate.h"
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen#include "ssl-proxy.h"
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainenint cmd_capa(struct pop3_client *client, const char *args __attr_unused__)
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen{
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen const struct auth_mech_desc *mech;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen unsigned int i, count;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen string_t *str;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen str = t_str_new(128);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen str_append(str, "SASL");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen mech = auth_client_get_available_mechs(auth_client, &count);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen for (i = 0; i < count; i++) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen /* a) transport is secured
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen b) auth mechanism isn't plaintext
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen c) we allow insecure authentication
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen - but don't advertise AUTH=PLAIN, as RFC 2595 requires
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen */
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen if (mech[i].advertise &&
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen (client->secured || !mech[i].plaintext)) {
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen str_append_c(str, ' ');
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen str_append(str, "AUTH=");
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen str_append(str, mech[i].name);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_send_line(client, t_strconcat("+OK\r\n" POP3_CAPABILITY_REPLY,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen (ssl_initialized && !client->tls) ?
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen "STLS\r\n" : "",
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen str_c(str),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen "\r\n.", NULL));
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen return TRUE;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen}
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenstatic void client_auth_abort(struct pop3_client *client, const char *msg)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen{
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (client->common.auth_request != NULL) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen auth_client_request_abort(client->common.auth_request);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client->common.auth_request = NULL;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_send_line(client, msg != NULL ? t_strconcat("-ERR ", msg, NULL) :
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen "-ERR Authentication failed.");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen o_stream_flush(client->output);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen /* get back to normal client input */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (client->common.io != NULL)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen io_remove(client->common.io);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client->common.io = client->common.fd == -1 ? NULL :
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen io_add(client->common.fd, IO_READ, client_input, client);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_unref(client);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen}
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenstatic void master_callback(struct client *_client, int success)
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen{
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen struct pop3_client *client = (struct pop3_client *) _client;
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen const char *reason = NULL;
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (success) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen reason = t_strconcat("Login: ", client->common.virtual_user,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen NULL);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen } else {
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen reason = t_strconcat("Internal login failure: ",
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen client->common.virtual_user, NULL);
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen client_send_line(client, "* BYE Internal login failure.");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen client_destroy(client, reason);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen}
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenstatic void client_send_auth_data(struct pop3_client *client,
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen const unsigned char *data, size_t size)
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen{
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen buffer_t *buf;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen t_push();
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen size*2, (size_t)-1);
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen buffer_append(buf, "+ ", 2);
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen base64_encode(data, size, buf);
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen buffer_append(buf, "\r\n", 2);
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen o_stream_send(client->output, buffer_get_data(buf, NULL),
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen buffer_get_used_size(buf));
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen o_stream_flush(client->output);
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen t_pop();
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen}
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenstatic enum auth_client_request_new_flags
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenclient_get_auth_flags(struct pop3_client *client)
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen{
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen enum auth_client_request_new_flags auth_flags = 0;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen if (client->common.proxy != NULL &&
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen ssl_proxy_has_valid_client_cert(client->common.proxy))
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen auth_flags |= AUTH_CLIENT_FLAG_SSL_VALID_CLIENT_CERT;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen return auth_flags;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen}
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainenstatic void login_callback(struct auth_request *request,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen struct auth_client_request_reply *reply,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen const unsigned char *data, void *context)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen{
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen struct pop3_client *client = context;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen const char *error;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen switch (auth_callback(request, reply, data, &client->common,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen master_callback, &error)) {
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen case -1:
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen case 0:
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen /* login failed */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_auth_abort(client, error);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen break;
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen default:
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen /* success, we should be able to log in. if we fail, just
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen disconnect the client. */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_send_line(client, "+OK Logged in.");
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen client_unref(client);
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen }
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen}
f89eb8f2cda0bd6d40a9f96db1c92517f0593871Martti Rannanjärvi
f89eb8f2cda0bd6d40a9f96db1c92517f0593871Martti Rannanjärviint cmd_user(struct pop3_client *client, const char *args)
f89eb8f2cda0bd6d40a9f96db1c92517f0593871Martti Rannanjärvi{
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen if (!client->secured && disable_plaintext_auth) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_send_line(client,
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen "-ERR Plaintext authentication disabled.");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen return TRUE;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen
88339cce70862ea6c6fac5615975e1e94a52a72eTimo Sirainen /* authorization ID \0 authentication ID \0 pass */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen buffer_set_used_size(client->plain_login, 0);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen buffer_append_c(client->plain_login, '\0');
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen buffer_append(client->plain_login, args, strlen(args));
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen client_send_line(client, "+OK");
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen return TRUE;
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen}
3c3002ee03e2c20034f73cfec80c6647320bd27cTimo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenint cmd_pass(struct pop3_client *client, const char *args)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen{
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen const char *error;
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen if (buffer_get_used_size(client->plain_login) == 0) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_send_line(client, "-ERR No username given.");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen return TRUE;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen buffer_append_c(client->plain_login, '\0');
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen buffer_append(client->plain_login, args, strlen(args));
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_ref(client);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client->common.auth_request =
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen auth_client_request_new(auth_client, "PLAIN", "POP3",
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_get_auth_flags(client),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen str_data(client->plain_login),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen str_len(client->plain_login),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen login_callback, client, &error);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen buffer_set_used_size(client->plain_login, 0);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (client->common.auth_request != NULL) {
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen /* don't read any input from client until login is finished */
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen if (client->common.io != NULL) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen io_remove(client->common.io);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client->common.io = NULL;
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen return TRUE;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen } else {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_send_line(client,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen t_strconcat("-ERR Login failed: ", error, NULL));
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_unref(client);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen return TRUE;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen}
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenstatic void authenticate_callback(struct auth_request *request,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen struct auth_client_request_reply *reply,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen const unsigned char *data, void *context)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen{
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen struct pop3_client *client = context;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen const char *error;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen switch (auth_callback(request, reply, data, &client->common,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen master_callback, &error)) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen case -1:
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen /* login failed */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_auth_abort(client, error);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen break;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen case 0:
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_send_auth_data(client, data, reply->data_size);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen break;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen default:
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen /* success, we should be able to log in. if we fail, just
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen disconnect the client. */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_send_line(client, "+OK Logged in.");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_unref(client);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen}
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenstatic void client_auth_input(void *context)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen{
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen struct pop3_client *client = context;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen buffer_t *buf;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen char *line;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen size_t linelen, bufsize;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (!client_read(client)) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_unref(client);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen return;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch /* @UNSAFE */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen line = i_stream_next_line(client->input);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (line == NULL)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen return;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (strcmp(line, "*") == 0) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_auth_abort(client, "Authentication aborted");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen return;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen linelen = strlen(line);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen buf = buffer_create_static_hard(pool_datastack_create(), linelen);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (base64_decode((const unsigned char *) line, linelen,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen NULL, buf) <= 0) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen /* failed */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_auth_abort(client, "Invalid base64 data");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen } else if (client->common.auth_request == NULL) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_auth_abort(client, "Don't send unrequested data");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen } else {
6264b51bcce8ae98efdcda3e55a765d7a13d15edTimo Sirainen auth_client_request_continue(client->common.auth_request,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen buffer_get_data(buf, NULL),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen buffer_get_used_size(buf));
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen /* clear sensitive data */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen safe_memset(line, 0, linelen);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen bufsize = buffer_get_used_size(buf);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen safe_memset(buffer_free_without_data(buf), 0, bufsize);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen}
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenint cmd_auth(struct pop3_client *client, const char *args)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen{
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen const struct auth_mech_desc *mech;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen const char *mech_name, *error, *p;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen string_t *buf;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen size_t argslen;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen /* <mechanism name> <initial response> */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen p = strchr(args, ' ');
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (p == NULL) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen mech_name = args;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen args = "";
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen } else {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen mech_name = t_strdup_until(args, p);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen args = p+1;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen mech = auth_client_find_mech(auth_client, mech_name);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (mech == NULL) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_send_line(client,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen "-ERR Unsupported authentication mechanism.");
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen return TRUE;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (!client->secured && mech->plaintext && disable_plaintext_auth) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_send_line(client,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen "-ERR Plaintext authentication disabled.");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen return TRUE;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen argslen = strlen(args);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen buf = buffer_create_static_hard(pool_datastack_create(), argslen);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (base64_decode((const unsigned char *)args, argslen,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen NULL, buf) <= 0) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen /* failed */
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_send_line(client, "-ERR Invalid base64 data.");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen return TRUE;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_ref(client);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client->common.auth_request =
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen auth_client_request_new(auth_client, mech->name, "POP3",
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_get_auth_flags(client),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen str_data(buf), str_len(buf),
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen authenticate_callback, client, &error);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (client->common.auth_request != NULL) {
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen /* following input data will go to authentication */
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen if (client->common.io != NULL)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen io_remove(client->common.io);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client->common.io = io_add(client->common.fd, IO_READ,
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_auth_input, client);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen } else {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_send_line(client, t_strconcat(
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen "-ERR Authentication failed: ", error, NULL));
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen client_unref(client);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen return TRUE;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen}
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen