client-common-auth.c revision 2b96880f2d789d125aff6a95eaa7b51f558a6a1c
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#define PROXY_FAILURE_MSG "Account is temporarily unavailable."
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen/* If we've been waiting auth server to respond for over this many milliseconds,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen send a "waiting" message. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen#define AUTH_WAITING_WARNING_TIMEOUT_MSECS (10*1000)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *id;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic const struct client_auth_fail_code_id client_auth_fail_codes[] = {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenclient_auth_fail_code_lookup(const char *fail_code)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const struct client_auth_fail_code_id *fail = client_auth_fail_codes;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void client_auth_failed(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->auth_initializing || client->destroyed)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->io = io_add(client->fd, IO_READ, client_input, client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void client_auth_waiting_timeout(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_log_warn(client, "Auth process not responding, "
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "delayed sending initial response (greeting)");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_notify_status(client, FALSE, client->master_tag == 0 ?
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen AUTH_SERVER_WAITING_MSG : AUTH_MASTER_WAITING_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_set_auth_waiting(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void alt_username_set(ARRAY_TYPE(const_string) *alt_usernames, pool_t pool,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen char *const *fields;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen unsigned int i, count;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen fields = array_get(&global_alt_usernames, &count);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen for (i = 0; i < count; i++) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen array_append(&global_alt_usernames, &new_key, 1);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* array is NULL-terminated, so if there are unused fields in
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen the middle set them as "" */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void client_auth_parse_args(struct client *client, bool success,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *const *args,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->fail_code = CLIENT_AUTH_FAIL_CODE_LOGIN_DISABLED;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (net_str2port(value, &reply_r->port) < 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (str_to_uint(value, &reply_r->proxy_timeout_msecs) < 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (strcmp(key, "proxy_refresh") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (str_to_uint(value, &reply_r->proxy_refresh_secs) < 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "proxy_nopipelining") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen else if (strcmp(key, "proxy_not_trusted") == 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->port = login_binary->default_ssl_port;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->ssl_flags |= PROXY_SSL_FLAG_ANY_CERT;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply_r->fail_code != CLIENT_AUTH_FAIL_CODE_NONE) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* code already assigned */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reply_r->fail_code = client_auth_fail_code_lookup(value);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* already handled in sasl-server.c */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen alt_username_set(&alt_usernames, client->pool,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_debug("Ignoring unknown passdb extra field: %s", key);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char **alt;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void proxy_free_password(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen safe_memset(client->proxy_password, 0, strlen(client->proxy_password));
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_proxy_finish_destroy_client(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* input stream got closed in client_send_raw_data().
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen In most places we don't have to check for this explicitly,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen but login_proxy_detach() attempts to get and use the
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen istream's fd, which is now -1. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_printfa(str, "proxy(%s): started proxying to %s:%u",
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (strcmp(client->virtual_user, client->proxy_user) != 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* remote username is different, log it */
bda082b4c7d06cd8ed83794318930385673b7eeeTeemu Huovila str_printfa(str, " (master %s)", client->proxy_master_user);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void client_proxy_error(struct client *client, const char *text)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenconst char *client_proxy_get_state(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_proxy_log_failure(struct client *client, const char *line)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_printfa(str, "proxy(%s): Login failed to %s:%u",
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (strcmp(client->virtual_user, client->proxy_user) != 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* remote username is different, log it */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen str_printfa(str, " (master %s)", client->proxy_master_user);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_proxy_failed(struct client *client, bool send_line)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_error(client, PROXY_FAILURE_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen dsasl_client_free(&client->proxy_sasl_client);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* call this last - it may destroy the client */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* we're just freeing the proxy */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen input = login_proxy_get_istream(client->login_proxy);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* we came here from client_destroy() */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* failed for some reason, probably server disconnected */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_log_err(client, "proxy: Remote input buffer full");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "proxy: Remote %s:%u disconnected: %s "
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "(state=%s, duration=%us)%s",
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen while ((line = i_stream_next_line(input)) != NULL) {
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi if (client->v.proxy_parse_line(client, line) != 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const struct dsasl_client_mech *sasl_mech = NULL;
18efe79858a7b4a794c11bc1867fc313c7c07bbeTimo Sirainen client_log_err(client, "proxy: password not given");
18efe79858a7b4a794c11bc1867fc313c7c07bbeTimo Sirainen client_proxy_error(client, PROXY_FAILURE_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (reply->host == NULL || *reply->host == '\0') {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_log_err(client, "proxy: host not given");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_error(client, PROXY_FAILURE_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sasl_mech = dsasl_client_mech_find(reply->proxy_mech);
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi "proxy: Unsupported SASL mechanism %s",
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_error(client, PROXY_FAILURE_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* have to use PLAIN authentication with master user logins */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* connection_queue_add() decided that we were the oldest
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen connection and killed us. */
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi if (login_proxy_is_ourself(client, reply->host, reply->port,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_log_err(client, "Proxying loops to itself");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_error(client, PROXY_FAILURE_MSG);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen net_addr2ip(reply->hostip, &proxy_set.ip) < 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (net_addr2ip(reply->source_ip, &proxy_set.source_ip) < 0)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen } else if (login_source_ips_count > 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* select the next source IP with round robin. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen proxy_set.source_ip = login_source_ips[login_source_ips_idx];
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen (login_source_ips_idx + 1) % login_source_ips_count;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen proxy_set.connect_timeout_msecs = reply->proxy_timeout_msecs;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen proxy_set.connect_timeout_msecs = PROXY_DEFAULT_TIMEOUT_MSECS;
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen proxy_set.notify_refresh_secs = reply->proxy_refresh_secs;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (login_proxy_new(client, &proxy_set, proxy_input) < 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_proxy_error(client, PROXY_FAILURE_MSG);
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen client->proxy_user = i_strdup(reply->destuser);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->proxy_master_user = i_strdup(reply->master_user);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->proxy_password = i_strdup(reply->password);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->proxy_nopipelining = reply->proxy_nopipelining;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->proxy_not_trusted = reply->proxy_not_trusted;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* disable input until authentication is finished */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenclient_auth_result(struct client *client, enum client_auth_result result,
cddfd1355db6b60c71d7ee3c0b4f23b3efcc9ad1Timo Sirainen const struct client_auth_reply *reply, const char *text)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->v.auth_result(client, result, reply, text);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenclient_auth_handle_reply(struct client *client,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const struct client_auth_reply *reply, bool success)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* we want to proxy the connection to another server.
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen don't do this unless authentication succeeded. with
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen master user proxying we can get FAIL with proxy still set.
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen proxy host=.. [port=..] [destuser=..] pass=.. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* this for plugins being able th hook into auth reply
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen when proxying is used */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_SUCCESS,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reason = "Logged in, but you should use this server instead.";
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen enum client_auth_result result = CLIENT_AUTH_RESULT_AUTHFAILED;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const char *timestamp, *reason = reply->reason;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* Either failed or user login is disabled */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen timestamp = t_strflocaltime("%Y-%m-%d %H:%M:%S", ioloop_time);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen reason = t_strdup_printf(AUTH_TEMP_FAILED_MSG" [%s:%s]",
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen result = CLIENT_AUTH_RESULT_MECH_SSL_REQUIRED;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen result = CLIENT_AUTH_RESULT_AUTHFAILED_REASON;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, result, reply, reason);
61cf001f1944d92eb25f113ba4c08985d6e30d53Timo Sirainenvoid client_auth_respond(struct client *client, const char *response)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen auth_client_request_continue(client->auth_request, response);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_auth_fail(struct client *client, const char *text)
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärviint client_auth_read_line(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen const unsigned char *data;
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi if (i_stream_read_more(client->input, &data, &size) == -1) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* see if we have a full line */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen for (i = 0; i < size; i++) {
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi client->auth_response = str_new(default_pool, I_MAX(i+1, 256));
7bc3126bb62589fe373f40aa40132e671e4a363dAki Tuomi if (str_len(client->auth_response) + i > LOGIN_MAX_AUTH_BUF_SIZE) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_destroy(client, "Authentication response too large");
6028ef7bd1a453212b815b608e1c7b1b21ebca49Aki Tuomi i_stream_skip(client->input, i == size ? size : i+1);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* drop trailing \r */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (len > 0 && str_c(client->auth_response)[len-1] == '\r')
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi str_truncate(client->auth_response, len-1);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenvoid client_auth_parse_response(struct client *client)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (strcmp(str_c(client->auth_response), "*") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_respond(client, str_c(client->auth_response));
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen memset(str_c_modifiable(client->auth_response), 0,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenstatic void client_auth_input(struct client *client)
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainen i_assert(client->v.auth_parse_response != NULL);
551fef69c0633ae3c7738038e047a7c0762d9599Timo Sirainenvoid client_auth_send_challenge(struct client *client, const char *data)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainensasl_callback(struct client *client, enum sasl_server_reply sasl_reply,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sasl_reply == SASL_SERVER_REPLY_AUTH_ABORTED ||
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sasl_reply == SASL_SERVER_REPLY_MASTER_FAILED);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client->last_auth_fail = CLIENT_AUTH_FAIL_CODE_NONE;
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_parse_args(client, TRUE, args, &reply);
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi client->last_auth_fail = reply.fail_code;
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi if (client_auth_handle_reply(client, &reply, TRUE))
f32c6ed9db6f4c535f97a2020401572efc8abf86Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_SUCCESS,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_parse_args(client, FALSE, args, &reply);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client_auth_handle_reply(client, &reply, FALSE))
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (sasl_reply == SASL_SERVER_REPLY_AUTH_ABORTED) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_ABORTED,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* authentication itself succeeded, we just hit some
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen internal failure. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_TEMPFAIL,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* the fd may still be hanging somewhere in kernel or another
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen process. make sure the client gets disconnected. */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (shutdown(client->fd, SHUT_RDWR) < 0 && errno != ENOTCONN)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen i_assert(client->v.auth_send_challenge != NULL);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenint client_auth_begin(struct client *client, const char *mech_name,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (!client->secured && strcmp(client->ssl_set->ssl, "required") == 0) {
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "SSL required for authentication");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_SSL_REQUIRED, NULL,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "Authentication not allowed until SSL/TLS is enabled.");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen sasl_server_auth_begin(client, login_binary->protocol, mech_name,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen /* don't handle input until we get the initial auth reply */
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainenbool client_check_plaintext_auth(struct client *client, bool pass_sent)
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen bool ssl_required = (strcmp(client->ssl_set->ssl, "required") == 0);
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen if (client->secured || (!client->set->disable_plaintext_auth &&
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "Plaintext authentication disabled");
2933174a1d7af52678eb5d2bf581e8c2a995f6dfTimo Sirainen "Plaintext authentication not allowed "
2933174a1d7af52678eb5d2bf581e8c2a995f6dfTimo Sirainen "without SSL/TLS, but your client did it anyway. "
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen "If anyone was listening, the password was exposed.");
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_SSL_REQUIRED, NULL,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen client_auth_result(client, CLIENT_AUTH_RESULT_MECH_SSL_REQUIRED, NULL,
5ef28f68edef46f69961b19b7c1dcd8ec5a955e8Timo Sirainen for (client = clients; client != NULL; client = next) {