client-authenticate.c revision b12eeefe58793031ebf4cff240a39ca33680b6e8
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (C) 2002-2004 Timo Sirainen */
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen/* Used only for string sanitization while verbose_auth is set. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenconst char *client_authenticate_get_capabilities(int secured)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen unsigned int i, count;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mech = auth_client_get_available_mechs(auth_client, &count);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (i = 0; i < count; i++) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* a) transport is secured
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen b) auth mechanism isn't plaintext
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen c) we allow insecure authentication
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen - but don't advertise AUTH=PLAIN, as RFC 2595 requires
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic void client_auth_abort(struct imap_client *client, const char *msg)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen auth_client_request_abort(client->common.auth_request);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen client_syslog(client, "Authentication failed: %s", msg);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "NO Authentication failed.");
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* get back to normal client input */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen client->common.io = client->common.fd == -1 ? NULL :
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen io_add(client->common.fd, IO_READ, client_input, client);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void master_callback(struct client *_client, int success)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct imap_client *client = (struct imap_client *) _client;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen reason = t_strconcat("Login: ", client->common.virtual_user,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen reason = t_strconcat("Internal login failure: ",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen client_send_line(client, "* BYE Internal login failure. "
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "Error report written to server log.");
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void client_send_auth_data(struct imap_client *client,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if ((ret = o_stream_send(client->output, buf_data, buf_size)) < 0)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen client_destroy(client, "Transmit buffer full");
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainenstatic void login_callback(struct auth_request *request,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen switch (auth_callback(request, reply, data, &client->common,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* login failed */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* success, we should be able to log in. if we fail, just
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen disconnect the client. */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainenclient_get_auth_flags(struct imap_client *client)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen enum auth_client_request_new_flags auth_flags = 0;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen ssl_proxy_has_valid_client_cert(client->common.proxy))
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen auth_flags |= AUTH_CLIENT_FLAG_SSL_VALID_CLIENT_CERT;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint cmd_login(struct imap_client *client, struct imap_arg *args)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* two arguments: username and password */
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (args[1].type != IMAP_ARG_ATOM && args[1].type != IMAP_ARG_STRING)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (!client->secured && disable_plaintext_auth) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen "Plaintext authentication disabled");
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen "* BAD [ALERT] Plaintext authentication is disabled, "
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen "but your client sent password in plaintext anyway. "
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen "If anyone was listening, the password was exposed.");
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen "NO Plaintext authentication disabled.");
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* authorization ID \0 authentication ID \0 pass */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen info.initial_resp_size = str_len(plain_login);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen auth_client_request_new(auth_client, NULL, &info,
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen client_syslog(client, "Login failed: %s", error);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* don't read any input from client until login is finished */
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainenstatic void authenticate_callback(struct auth_request *request,
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen /* client aborted */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen switch (auth_callback(request, reply, data, &client->common,
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen /* login failed */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen /* continue */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen client_send_auth_data(client, data, reply->data_size);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen /* success, we should be able to log in. if we fail, just
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen disconnect the client. */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (i_stream_next_line(client->input) == NULL)
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen /* @UNSAFE */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen client_auth_abort(client, "Authentication aborted");
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen buf = buffer_create_static_hard(pool_datastack_create(), linelen);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (base64_decode(line, linelen, NULL, buf) <= 0) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen client_auth_abort(client, "Invalid base64 data");
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen } else if (client->common.auth_request == NULL) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen client_auth_abort(client, "Don't send unrequested data");
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen auth_client_request_continue(client->common.auth_request,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* clear sensitive data */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen safe_memset(buffer_free_without_data(buf), 0, bufsize);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainenint cmd_authenticate(struct imap_client *client, struct imap_arg *args)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen /* we want only one argument: authentication mechanism name */
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen mech = auth_client_find_mech(auth_client, mech_name);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen client_syslog(client, "Authenticate %s failed: "
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen "Unsupported mechanism",
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen "NO Unsupported authentication mechanism.");
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen if (!client->secured && mech->plaintext && disable_plaintext_auth) {
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen client_syslog(client, "Authenticate %s failed: "
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen "Plaintext authentication disabled",
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen "NO Plaintext authentication disabled.");
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen auth_client_request_new(auth_client, NULL, &info,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* following input data will go to authentication */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen client->common.io = io_add(client->common.fd, IO_READ,
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen client_syslog(client, "Authenticate %s failed: %s",