Mercurial > dovecot > core-2.2
view src/imap-login/client-authenticate.c @ 19552:0f22db71df7a
global: freshen copyright
git ls-files | xargs perl -p -i -e 's/(\d+)-201[0-5]/$1-2016/g;s/ (201[0-5]) Dovecot/ $1-2016 Dovecot/'
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Wed, 13 Jan 2016 12:24:03 +0200 |
parents | 06908dbcee62 |
children | 5bad98da9310 |
line wrap: on
line source
/* Copyright (c) 2002-2016 Dovecot authors, see the included COPYING file */ #include "login-common.h" #include "base64.h" #include "buffer.h" #include "ioloop.h" #include "istream.h" #include "ostream.h" #include "safe-memset.h" #include "str.h" #include "str-sanitize.h" #include "net.h" #include "imap-resp-code.h" #include "imap-parser.h" #include "imap-url.h" #include "auth-client.h" #include "client.h" #include "client-authenticate.h" #include "imap-proxy.h" void client_authenticate_get_capabilities(struct client *client, string_t *str) { const struct auth_mech_desc *mech; unsigned int i, count; mech = sasl_server_get_advertised_mechs(client, &count); for (i = 0; i < count; i++) { str_append_c(str, ' '); str_append(str, "AUTH="); str_append(str, mech[i].name); } } void imap_client_auth_result(struct client *client, enum client_auth_result result, const struct client_auth_reply *reply, const char *text) { struct imap_url url; string_t *referral; switch (result) { case CLIENT_AUTH_RESULT_SUCCESS: /* nothing to be done for IMAP */ break; case CLIENT_AUTH_RESULT_REFERRAL_SUCCESS: case CLIENT_AUTH_RESULT_REFERRAL_NOLOGIN: /* IMAP referral [nologin] referral host=.. [port=..] [destuser=..] [reason=..] NO [REFERRAL imap://destuser;AUTH=..@host:port/] Can't login. OK [...] Logged in, but you should use this server instead. .. [REFERRAL ..] (Reason from auth server) */ referral = t_str_new(128); memset(&url, 0, sizeof(url)); url.userid = reply->destuser; url.auth_type = client->auth_mech_name; url.host_name = reply->host; if (reply->port != 143) { url.have_port = TRUE; url.port = reply->port; } str_append(referral, "REFERRAL "); str_append(referral, imap_url_create(&url)); if (result == CLIENT_AUTH_RESULT_REFERRAL_SUCCESS) { client_send_reply_code(client, IMAP_CMD_REPLY_OK, str_c(referral), text); } else { client_send_reply_code(client, IMAP_CMD_REPLY_NO, str_c(referral), text); } break; case CLIENT_AUTH_RESULT_ABORTED: client_send_reply(client, IMAP_CMD_REPLY_BAD, text); break; case CLIENT_AUTH_RESULT_AUTHFAILED_REASON: if (text[0] == '[') client_send_reply(client, IMAP_CMD_REPLY_NO, text); else { client_send_reply_code(client, IMAP_CMD_REPLY_NO, "ALERT", text); } break; case CLIENT_AUTH_RESULT_AUTHZFAILED: client_send_reply_code(client, IMAP_CMD_REPLY_NO, IMAP_RESP_CODE_AUTHZFAILED, text); break; case CLIENT_AUTH_RESULT_TEMPFAIL: client_send_reply_code(client, IMAP_CMD_REPLY_NO, IMAP_RESP_CODE_UNAVAILABLE, text); break; case CLIENT_AUTH_RESULT_SSL_REQUIRED: client_send_reply_code(client, IMAP_CMD_REPLY_NO, IMAP_RESP_CODE_PRIVACYREQUIRED, text); break; case CLIENT_AUTH_RESULT_AUTHFAILED: client_send_reply_code(client, IMAP_CMD_REPLY_NO, IMAP_RESP_CODE_AUTHFAILED, text); break; } } static int imap_client_auth_begin(struct imap_client *imap_client, const char *mech_name, const char *init_resp) { char *prefix; prefix = i_strdup_printf("%d%s", imap_client->client_ignores_capability_resp_code, imap_client->cmd_tag); i_free(imap_client->common.master_data_prefix); imap_client->common.master_data_prefix = (void *)prefix; imap_client->common.master_data_prefix_len = strlen(prefix)+1; return client_auth_begin(&imap_client->common, mech_name, init_resp); } int cmd_authenticate(struct imap_client *imap_client, bool *parsed_r) { /* NOTE: This command's input is handled specially because the SASL-IR can be large. */ struct client *client = &imap_client->common; const unsigned char *data; size_t i, size; int ret; *parsed_r = FALSE; /* <auth mechanism name> [<initial SASL response>] */ if (!imap_client->auth_mech_name_parsed) { data = i_stream_get_data(client->input, &size); for (i = 0; i < size; i++) { if (data[i] == ' ' || data[i] == '\r' || data[i] == '\n') break; } if (i == size) return 0; if (i == 0) { /* empty mechanism name */ imap_client->skip_line = TRUE; return -1; } i_free(client->auth_mech_name); client->auth_mech_name = i_strndup(data, i); imap_client->auth_mech_name_parsed = TRUE; if (data[i] == ' ') i++; i_stream_skip(client->input, i); } /* get SASL-IR, if any */ if ((ret = client_auth_read_line(client)) <= 0) return ret; *parsed_r = TRUE; imap_client->auth_mech_name_parsed = FALSE; return imap_client_auth_begin(imap_client, t_strdup(client->auth_mech_name), t_strdup(str_c(client->auth_response))); } int cmd_login(struct imap_client *imap_client, const struct imap_arg *args) { struct client *client = &imap_client->common; const char *user, *pass; string_t *plain_login, *base64; /* two arguments: username and password */ if (!imap_arg_get_astring(&args[0], &user) || !imap_arg_get_astring(&args[1], &pass) || !IMAP_ARG_IS_EOL(&args[2])) return -1; if (!client_check_plaintext_auth(client, TRUE)) { if (client->virtual_user == NULL) client->virtual_user = i_strdup(user); return 1; } /* authorization ID \0 authentication ID \0 pass */ plain_login = buffer_create_dynamic(pool_datastack_create(), 64); buffer_append_c(plain_login, '\0'); buffer_append(plain_login, user, strlen(user)); buffer_append_c(plain_login, '\0'); buffer_append(plain_login, pass, strlen(pass)); base64 = buffer_create_dynamic(pool_datastack_create(), MAX_BASE64_ENCODED_SIZE(plain_login->used)); base64_encode(plain_login->data, plain_login->used, base64); return imap_client_auth_begin(imap_client, "PLAIN", str_c(base64)); }