sasl-server.c revision 9c3577aeb78a27920439ad9f1e62ee03699378c3
280a8a0544b4aeb52414d20e8c6e6c5b1108562eTinderbox User/* Copyright (C) 2002-2004 Timo Sirainen */
59602f2a7c4e4809941583bed3e94cd26e628f1aTinderbox User
6fe48fb46e53ffc37542853a1edb74cb481b7d94Automatic Updater#include "common.h"
5affecff6e148a8e124d03f5dbac0da11e30dcc5Tinderbox User#include "base64.h"
19558a04decde0e7261d489d92d04ad88104217bTinderbox User#include "buffer.h"
827f8cccb5280f4da66c46186e792d1cb9d73503Mark Andrews#include "str-sanitize.h"
827f8cccb5280f4da66c46186e792d1cb9d73503Mark Andrews#include "auth-client.h"
969eaf7df8ac651946f76b6631ff5db568c11ef6Tinderbox User#include "ssl-proxy.h"
03ebc228ee3725738b067b6bd7082a9a731822a1Tinderbox User#include "client-common.h"
f4ee48be3994797a8332b86c101db4d7b54799ceTinderbox User#include "master.h"
a2c370ca12bb0360ff7e969474ead3f788c65fffTinderbox User
8de3f14f1c300c3e1ed99084cc03485b42c92bf1Tinderbox Userstatic enum auth_request_flags
e5a6871cd0635ecdb2bf792316a2d8c53206f4b2Tinderbox Userclient_get_auth_flags(struct client *client)
950d203b64f512b85fcc093ee1e9e3e531a1aea3Tinderbox User{
b886b04d8d2b085cbf3e1bf4442dee87f43ba5e4Tinderbox User enum auth_request_flags auth_flags = 0;
03ebc228ee3725738b067b6bd7082a9a731822a1Tinderbox User
3759f10fc543747668b1ca4b4671f35b0dea8445Francis Dupont if (client->proxy != NULL &&
e676a596869d8a80a644c99a848afb53d1c5975eMark Andrews ssl_proxy_has_valid_client_cert(client->proxy))
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews auth_flags |= AUTH_REQUEST_FLAG_VALID_CLIENT_CERT;
b91d11bfcc30b96f2c80f3a76d12e3dcc8597a68Mark Andrews if (client->secured)
d5637bdbb931ff79fced3d4858d83212ea58ed15Tinderbox User auth_flags |= AUTH_REQUEST_FLAG_SECURED;
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews return auth_flags;
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews}
3759f10fc543747668b1ca4b4671f35b0dea8445Francis Dupont
d5637bdbb931ff79fced3d4858d83212ea58ed15Tinderbox Userstatic void
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrewscall_client_callback(struct client *client, enum sasl_server_reply reply,
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User const char *data, const char *const *args)
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews{
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User sasl_server_callback_t *sasl_callback;
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt i_assert(reply != SASL_SERVER_REPLY_CONTINUE);
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User sasl_callback = client->sasl_callback;
efb0e886f18894a1d2489f1ad74ad14b579e11c7Mark Andrews client->sasl_callback = NULL;
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt sasl_callback(client, reply, data, args);
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews /* NOTE: client may be destroyed now */
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User}
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox Userstatic void
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrewsmaster_callback(struct client *client, enum master_login_status status)
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt{
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews enum sasl_server_reply reply = SASL_SERVER_REPLY_MASTER_FAILED;
015055b6e23f5c08f6a5b34726f90b62597e9e45Tinderbox User const char *data = NULL;
03ebc228ee3725738b067b6bd7082a9a731822a1Tinderbox User
aa9c561961e9d877946ebaa8795fa2be054ab7bfEvan Hunt client->authenticating = FALSE;
dc238a06bffa79de141ee7655765e2df91498a8aTinderbox User switch (status) {
827f8cccb5280f4da66c46186e792d1cb9d73503Mark Andrews case MASTER_LOGIN_STATUS_OK:
aa9c561961e9d877946ebaa8795fa2be054ab7bfEvan Hunt reply = SASL_SERVER_REPLY_SUCCESS;
9513a2a6670951f5cf5477fcfec9f933fcaff628Automatic Updater break;
3759f10fc543747668b1ca4b4671f35b0dea8445Francis Dupont case MASTER_LOGIN_STATUS_INTERNAL_ERROR:
9513a2a6670951f5cf5477fcfec9f933fcaff628Automatic Updater break;
aa9c561961e9d877946ebaa8795fa2be054ab7bfEvan Hunt case MASTER_LOGIN_STATUS_MAX_CONNECTIONS:
dc238a06bffa79de141ee7655765e2df91498a8aTinderbox User data = "Maximum number of connections exceeded";
827f8cccb5280f4da66c46186e792d1cb9d73503Mark Andrews break;
aa9c561961e9d877946ebaa8795fa2be054ab7bfEvan Hunt }
710bce1a85c96e85ca1a90471382055acd29d51fTinderbox User call_client_callback(client, reply, data, NULL);
9513a2a6670951f5cf5477fcfec9f933fcaff628Automatic Updater}
3759f10fc543747668b1ca4b4671f35b0dea8445Francis Dupont
9513a2a6670951f5cf5477fcfec9f933fcaff628Automatic Updaterstatic void authenticate_callback(struct auth_request *request, int status,
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews const char *data_base64,
cdfc81e048bd34c1d628380247bda6b80a89e20eAutomatic Updater const char *const *args, void *context)
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews{
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt struct client *client = context;
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews unsigned int i;
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews bool nologin;
9513a2a6670951f5cf5477fcfec9f933fcaff628Automatic Updater
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews if (!client->authenticating) {
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews /* client aborted */
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt i_assert(status < 0);
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews return;
9513a2a6670951f5cf5477fcfec9f933fcaff628Automatic Updater }
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews
eabc9c3c07cd956d3c436bd7614cb162dabdda76Mark Andrews i_assert(client->auth_request == request);
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews client->waiting_auth_reply = FALSE;
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt switch (status) {
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews case 0:
015055b6e23f5c08f6a5b34726f90b62597e9e45Tinderbox User /* continue */
03ebc228ee3725738b067b6bd7082a9a731822a1Tinderbox User client->sasl_callback(client, SASL_SERVER_REPLY_CONTINUE,
fec6e13f2d1e69fe1c2b8fac36f732f124cf5398Mark Andrews data_base64, NULL);
b91d11bfcc30b96f2c80f3a76d12e3dcc8597a68Mark Andrews break;
b91d11bfcc30b96f2c80f3a76d12e3dcc8597a68Mark Andrews case 1:
fec6e13f2d1e69fe1c2b8fac36f732f124cf5398Mark Andrews client->auth_request = NULL;
2ae159b376dac23870d8005563c585acf85a4b5aEvan Hunt
2ae159b376dac23870d8005563c585acf85a4b5aEvan Hunt nologin = FALSE;
2ae159b376dac23870d8005563c585acf85a4b5aEvan Hunt for (i = 0; args[i] != NULL; i++) {
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews if (strncmp(args[i], "user=", 5) == 0) {
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt i_free(client->virtual_user);
2ae159b376dac23870d8005563c585acf85a4b5aEvan Hunt client->virtual_user = i_strdup(args[i] + 5);
7cc0a5d21ef046bfd630c4769943d896a7d7472cTinderbox User }
e76dfff967cfbe00f4d1540434832e4499a9cd83Tinderbox User if (strcmp(args[i], "nologin") == 0 ||
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews strcmp(args[i], "proxy") == 0) {
549c517e2ecad52bb1d32f08920e29d4e8cda71eTinderbox User /* user can't login */
549c517e2ecad52bb1d32f08920e29d4e8cda71eTinderbox User nologin = TRUE;
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews }
549c517e2ecad52bb1d32f08920e29d4e8cda71eTinderbox User }
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews
e40c4e4c17d4df338e2a7db0f84d8dbb3858964cTinderbox User if (nologin) {
827f8cccb5280f4da66c46186e792d1cb9d73503Mark Andrews client->authenticating = FALSE;
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews call_client_callback(client, SASL_SERVER_REPLY_SUCCESS,
b91d11bfcc30b96f2c80f3a76d12e3dcc8597a68Mark Andrews NULL, args);
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews } else {
e40c4e4c17d4df338e2a7db0f84d8dbb3858964cTinderbox User master_request_login(client, master_callback,
aef6cf0f147a5014d4891c9689b9f463399e16e7Tinderbox User auth_client_request_get_server_pid(request),
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews auth_client_request_get_id(request));
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User }
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson break;
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User case -1:
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews client->auth_request = NULL;
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews if (args != NULL) {
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User /* parse our username if it's there */
efb0e886f18894a1d2489f1ad74ad14b579e11c7Mark Andrews for (i = 0; args[i] != NULL; i++) {
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews if (strncmp(args[i], "user=", 5) == 0) {
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt i_free(client->virtual_user);
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews client->virtual_user =
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User i_strdup(args[i] + 5);
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson }
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User }
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews }
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews client->authenticating = FALSE;
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User call_client_callback(client, SASL_SERVER_REPLY_AUTH_FAILED,
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson NULL, args);
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User break;
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews }
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt}
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews
28a5dd720187fddb16055a0f64b63a7b66f29f64Mark Andrewsvoid sasl_server_auth_begin(struct client *client,
03ebc228ee3725738b067b6bd7082a9a731822a1Tinderbox User const char *service, const char *mech_name,
78f3ed4bc2fcd3d270bfd599804f3b27a1db4d91Mark Andrews const char *initial_resp_base64,
e40c4e4c17d4df338e2a7db0f84d8dbb3858964cTinderbox User sasl_server_callback_t *callback)
a450977e98155f6e828fe6f8d52cf24674231831Mark Andrews{
78f3ed4bc2fcd3d270bfd599804f3b27a1db4d91Mark Andrews struct auth_request_info info;
fec6e13f2d1e69fe1c2b8fac36f732f124cf5398Mark Andrews const struct auth_mech_desc *mech;
e40c4e4c17d4df338e2a7db0f84d8dbb3858964cTinderbox User const char *error;
827f8cccb5280f4da66c46186e792d1cb9d73503Mark Andrews
fec6e13f2d1e69fe1c2b8fac36f732f124cf5398Mark Andrews client->authenticating = TRUE;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont i_free(client->auth_mech_name);
e40c4e4c17d4df338e2a7db0f84d8dbb3858964cTinderbox User client->auth_mech_name = str_ucase(i_strdup(mech_name));
827f8cccb5280f4da66c46186e792d1cb9d73503Mark Andrews client->sasl_callback = callback;
2a31bd531072824ef252c18303859d6af7451b00Francis Dupont
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews mech = auth_client_find_mech(auth_client, mech_name);
e40c4e4c17d4df338e2a7db0f84d8dbb3858964cTinderbox User if (mech == NULL) {
5747235bf35e7398984fd6b4632743396895ea7aTinderbox User sasl_server_auth_client_error(client,
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews "Unsupported authentication mechanism.");
78f3ed4bc2fcd3d270bfd599804f3b27a1db4d91Mark Andrews return;
a03cb08d0c4f1ca5fbc121d2f02bdffa7eb52286Mark Andrews }
827f8cccb5280f4da66c46186e792d1cb9d73503Mark Andrews
78f3ed4bc2fcd3d270bfd599804f3b27a1db4d91Mark Andrews if (!client->secured && disable_plaintext_auth &&
78f3ed4bc2fcd3d270bfd599804f3b27a1db4d91Mark Andrews (mech->flags & MECH_SEC_PLAINTEXT) != 0) {
7f9e2fff07b9c17e0d7a0ea7abc9304ce9d01b61Tinderbox User sasl_server_auth_client_error(client,
5747235bf35e7398984fd6b4632743396895ea7aTinderbox User "Plaintext authentication disabled.");
78f3ed4bc2fcd3d270bfd599804f3b27a1db4d91Mark Andrews return;
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews }
549c517e2ecad52bb1d32f08920e29d4e8cda71eTinderbox User
827f8cccb5280f4da66c46186e792d1cb9d73503Mark Andrews memset(&info, 0, sizeof(info));
c651f15b30f1dae5cc2f00878fb5da5b3a35a468Mark Andrews info.mech = mech->name;
fec6e13f2d1e69fe1c2b8fac36f732f124cf5398Mark Andrews info.service = service;
e40c4e4c17d4df338e2a7db0f84d8dbb3858964cTinderbox User info.cert_username = client->proxy == NULL ? NULL :
827f8cccb5280f4da66c46186e792d1cb9d73503Mark Andrews ssl_proxy_get_peer_name(client->proxy);
01a5c5503482fb3ba52088bf0178a7213273bf96Mark Andrews info.flags = client_get_auth_flags(client);
e40c4e4c17d4df338e2a7db0f84d8dbb3858964cTinderbox User info.local_ip = client->local_ip;
e40c4e4c17d4df338e2a7db0f84d8dbb3858964cTinderbox User info.remote_ip = client->ip;
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User info.local_port = client->local_port;
cdfc81e048bd34c1d628380247bda6b80a89e20eAutomatic Updater info.remote_port = client->remote_port;
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews info.initial_resp_base64 = initial_resp_base64;
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews client->auth_request =
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User auth_client_request_new(auth_client, NULL, &info,
fe80a4909bf62b602feaf246866e9d29f7654194Automatic Updater authenticate_callback, client, &error);
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User if (client->auth_request == NULL) {
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews sasl_server_auth_failed(client,
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt t_strconcat("Authentication failed: ", error, NULL));
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews }
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User}
fa0326cc2cf428f67575b6ba3b97b528a31b0010Tinderbox User
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox Userstatic void sasl_server_auth_cancel(struct client *client, const char *reason,
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews enum sasl_server_reply reply)
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt{
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews i_assert(client->authenticating);
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User
fe80a4909bf62b602feaf246866e9d29f7654194Automatic Updater if (verbose_auth && reason != NULL) {
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User const char *auth_name =
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt client_syslog(client,
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews t_strdup_printf("Authenticate %s failed: %s",
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User auth_name, reason));
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafsson }
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews client->authenticating = FALSE;
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt client->waiting_auth_reply = FALSE;
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User if (client->auth_request != NULL) {
dd65eb1efb40b1c47d57963192bfc54873b219beAutomatic Updater auth_client_request_abort(client->auth_request);
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User client->auth_request = NULL;
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews }
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews call_client_callback(client, reply, reason, NULL);
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User}
133e6d43fa82e80d3798be4de00f4540f485ec6cAutomatic Updater
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox Uservoid sasl_server_auth_failed(struct client *client, const char *reason)
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews{
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt sasl_server_auth_cancel(client, reason, SASL_SERVER_REPLY_AUTH_FAILED);
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews}
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User
91216cff91b34c9ff6e846dc23f248219cafe660Andreas Gustafssonvoid sasl_server_auth_client_error(struct client *client, const char *reason)
9ecb5d33470ebfb3719a1b8d56bcefdf4b27f7b2Tinderbox User{
e813f036c8251b6d9d2a72fa84f80c2c9d2795afMark Andrews sasl_server_auth_cancel(client, reason, SASL_SERVER_REPLY_CLIENT_ERROR);
30370d905e9be3be7d9b947fd432bacecbb13bb9Evan Hunt}
0eb371ca0dab50ae3462e98794a6126198c52f4bMark Andrews