client-common-auth.c revision 2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74c
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2016 Dovecot authors, see the included COPYING file */
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen#define PROXY_FAILURE_MSG "Account is temporarily unavailable."
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen/* If we've been waiting auth server to respond for over this many milliseconds,
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen send a "waiting" message. */
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen#define AUTH_WAITING_WARNING_TIMEOUT_MSECS (10*1000)
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen const char *id;
2a325b952fe47346d76221d2c07a3fe02faf8800Timo Sirainenstatic const struct client_auth_fail_code_id client_auth_fail_codes[] = {
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainenclient_auth_fail_code_lookup(const char *fail_code)
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen const struct client_auth_fail_code_id *fail = client_auth_fail_codes;
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainenstatic void client_auth_failed(struct client *client)
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen if (client->auth_initializing || client->destroyed)
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen client->io = io_add(client->fd, IO_READ, client_input, client);
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainenstatic void client_auth_waiting_timeout(struct client *client)
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen client_log_warn(client, "Auth process not responding, "
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen "delayed sending initial response (greeting)");
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen client_notify_status(client, FALSE, client->master_tag == 0 ?
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen AUTH_SERVER_WAITING_MSG : AUTH_MASTER_WAITING_MSG);
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainenvoid client_set_auth_waiting(struct client *client)
c7713320cd35e77543f1bdc7229988a160dae322Timo Sirainenstatic void alt_username_set(ARRAY_TYPE(const_string) *alt_usernames, pool_t pool,
7237f2f0a577413e12662228ee2039425fd2f5b0Timo Sirainen char *const *fields;
7237f2f0a577413e12662228ee2039425fd2f5b0Timo Sirainen unsigned int i, count;
7237f2f0a577413e12662228ee2039425fd2f5b0Timo Sirainen fields = array_get(&global_alt_usernames, &count);
7237f2f0a577413e12662228ee2039425fd2f5b0Timo Sirainen for (i = 0; i < count; i++) {
27bb267255b36d34c638c34a1ade611962f00772Timo Sirainen array_append(&global_alt_usernames, &new_key, 1);
27bb267255b36d34c638c34a1ade611962f00772Timo Sirainen /* array is NULL-terminated, so if there are unused fields in
27bb267255b36d34c638c34a1ade611962f00772Timo Sirainen the middle set them as "" */
27bb267255b36d34c638c34a1ade611962f00772Timo Sirainenstatic void client_auth_parse_args(struct client *client, bool success,
27bb267255b36d34c638c34a1ade611962f00772Timo Sirainen const char *const *args,
eba7f36feec8d02c4c394e55ff4effd47e33d311Timo Sirainen reply_r->fail_code = CLIENT_AUTH_FAIL_CODE_LOGIN_DISABLED;
eba7f36feec8d02c4c394e55ff4effd47e33d311Timo Sirainen if (net_str2port(value, &reply_r->port) < 0) {
77a41c18e6c37ea9d88a300173672746e29fe61bTimo Sirainen if (str_to_uint(value, &reply_r->proxy_timeout_msecs) < 0) {
eba7f36feec8d02c4c394e55ff4effd47e33d311Timo Sirainen } else if (strcmp(key, "proxy_refresh") == 0) {
eba7f36feec8d02c4c394e55ff4effd47e33d311Timo Sirainen if (str_to_uint(value, &reply_r->proxy_refresh_secs) < 0) {
eba7f36feec8d02c4c394e55ff4effd47e33d311Timo Sirainen else if (strcmp(key, "proxy_nopipelining") == 0)
eba7f36feec8d02c4c394e55ff4effd47e33d311Timo Sirainen else if (strcmp(key, "proxy_not_trusted") == 0)
eba7f36feec8d02c4c394e55ff4effd47e33d311Timo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
eba7f36feec8d02c4c394e55ff4effd47e33d311Timo Sirainen reply_r->port = login_binary->default_ssl_port;
d78f1ac9dc0f3e6c64cebe9ee331ec6b3c160e89Timo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
d78f1ac9dc0f3e6c64cebe9ee331ec6b3c160e89Timo Sirainen if (reply_r->fail_code != CLIENT_AUTH_FAIL_CODE_NONE) {
d78f1ac9dc0f3e6c64cebe9ee331ec6b3c160e89Timo Sirainen /* code already assigned */
d78f1ac9dc0f3e6c64cebe9ee331ec6b3c160e89Timo Sirainen reply_r->fail_code = client_auth_fail_code_lookup(value);
d78f1ac9dc0f3e6c64cebe9ee331ec6b3c160e89Timo Sirainen /* already handled in sasl-server.c */
d78f1ac9dc0f3e6c64cebe9ee331ec6b3c160e89Timo Sirainen alt_username_set(&alt_usernames, client->pool,
d78f1ac9dc0f3e6c64cebe9ee331ec6b3c160e89Timo Sirainen i_debug("Ignoring unknown passdb extra field: %s", key);
d78f1ac9dc0f3e6c64cebe9ee331ec6b3c160e89Timo Sirainen const char **alt;
d78f1ac9dc0f3e6c64cebe9ee331ec6b3c160e89Timo Sirainenstatic void proxy_free_password(struct client *client)
68cc278710182485b6c09e9a9ff8db90a727f343Aki Tuomi safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainenvoid client_proxy_finish_destroy_client(struct client *client)
68cc278710182485b6c09e9a9ff8db90a727f343Aki Tuomi /* input stream got closed in client_send_raw_data().
68cc278710182485b6c09e9a9ff8db90a727f343Aki Tuomi In most places we don't have to check for this explicitly,
68cc278710182485b6c09e9a9ff8db90a727f343Aki Tuomi but login_proxy_detach() attempts to get and use the
169b1488b6eea7a968021afa4f929b2e26d75d98Timo Sirainen istream's fd, which is now -1. */
c7713320cd35e77543f1bdc7229988a160dae322Timo Sirainen str_printfa(str, "proxy(%s): started proxying to %s:%u",
c7713320cd35e77543f1bdc7229988a160dae322Timo Sirainen if (strcmp(client->virtual_user, client->proxy_user) != 0) {
eba7f36feec8d02c4c394e55ff4effd47e33d311Timo Sirainen /* remote username is different, log it */
eba7f36feec8d02c4c394e55ff4effd47e33d311Timo Sirainen str_printfa(str, " (master %s)", client->proxy_master_user);
d78f1ac9dc0f3e6c64cebe9ee331ec6b3c160e89Timo Sirainenstatic void client_proxy_error(struct client *client, const char *text)
d78f1ac9dc0f3e6c64cebe9ee331ec6b3c160e89Timo Sirainenvoid client_proxy_log_failure(struct client *client, const char *line)
if (send_line) {
const char *line;
unsigned int duration;
} else if (login_source_ips_count > 0) {
if (!success)
return FALSE;
return TRUE;
const char *reason;
return TRUE;
return FALSE;
return TRUE;
const unsigned char *data;
for (i = 0; i < size; i++) {
switch (sasl_reply) {
data);
const char *init_resp)
!ssl_required))
return TRUE;
if (pass_sent) {
if (ssl_required) {
return FALSE;
void clients_notify_auth_connected(void)