userdb-blocking.c revision 75b4cc30566e22675b9e7b19b15a7fd929d8f54c
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (c) 2005-2015 Dovecot authors, see the included COPYING file */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "auth-common.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "str.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "auth-worker-server.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "userdb.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "userdb-blocking.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstruct blocking_userdb_iterate_context {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct userdb_iterate_context ctx;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct auth_worker_connection *conn;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen bool next;
91e2dc36b9c0c91f0af716be81dc2aa6cbbed6c2Timo Sirainen bool destroyed;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen};
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic bool user_callback(const char *reply, void *context)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct auth_request *request = context;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen enum userdb_result result;
75b4cc30566e22675b9e7b19b15a7fd929d8f54cTimo Sirainen const char *username, *args;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen if (strncmp(reply, "FAIL\t", 5) == 0) {
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen result = USERDB_RESULT_INTERNAL_FAILURE;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen args = reply + 5;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen } else if (strncmp(reply, "NOTFOUND\t", 9) == 0) {
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen result = USERDB_RESULT_USER_UNKNOWN;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen args = reply + 9;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen } else if (strncmp(reply, "OK\t", 3) == 0) {
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen result = USERDB_RESULT_OK;
75b4cc30566e22675b9e7b19b15a7fd929d8f54cTimo Sirainen username = reply + 3;
75b4cc30566e22675b9e7b19b15a7fd929d8f54cTimo Sirainen args = strchr(username, '\t');
75b4cc30566e22675b9e7b19b15a7fd929d8f54cTimo Sirainen if (args == NULL)
75b4cc30566e22675b9e7b19b15a7fd929d8f54cTimo Sirainen args = "";
75b4cc30566e22675b9e7b19b15a7fd929d8f54cTimo Sirainen else
75b4cc30566e22675b9e7b19b15a7fd929d8f54cTimo Sirainen username = t_strdup_until(username, args++);
75b4cc30566e22675b9e7b19b15a7fd929d8f54cTimo Sirainen if (strcmp(request->user, username) != 0)
75b4cc30566e22675b9e7b19b15a7fd929d8f54cTimo Sirainen request->user = p_strdup(request->pool, username);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen } else {
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen result = USERDB_RESULT_INTERNAL_FAILURE;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen i_error("BUG: auth-worker sent invalid user reply");
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen args = "";
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen }
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen
5c253723e8ef84cb71a80ced19efe597e8a90ea6Timo Sirainen request->userdb_reply = auth_fields_init(request->pool);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen if (*args != '\0') {
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen auth_fields_import(request->userdb_reply, args, 0);
ee6df9526e9716b3f1734d85b566e00fc41208bcTimo Sirainen if (auth_fields_exists(request->userdb_reply, "tempfail"))
cd75c360f244c96b9ee10e01ee3a66fad13183c8Timo Sirainen request->userdb_lookup_tempfailed = TRUE;
58bc77731bb25e900498a28409337e747f622722Timo Sirainen }
c2f24d55319fad0b6c03425f402f0cb0cb1a318bTimo Sirainen
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen auth_request_userdb_callback(result, request);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen auth_request_unref(&request);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainenvoid userdb_blocking_lookup(struct auth_request *request)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen string_t *str;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str = t_str_new(128);
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str_printfa(str, "USER\t%u\t", request->userdb->userdb->id);
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen auth_request_export(request, str);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen auth_request_ref(request);
f08c6da58d4cffc5b4777485ebc475dff614e491Timo Sirainen auth_worker_call(request->pool, request->user,
f08c6da58d4cffc5b4777485ebc475dff614e491Timo Sirainen str_c(str), user_callback, request);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic bool iter_callback(const char *reply, void *context)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct blocking_userdb_iterate_context *ctx = context;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (strncmp(reply, "*\t", 2) == 0) {
f3c4f76a22b71b3c76c7f586db40b04e75564c2cTimo Sirainen if (ctx->destroyed)
f3c4f76a22b71b3c76c7f586db40b04e75564c2cTimo Sirainen return TRUE;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->next = FALSE;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->ctx.callback(reply + 2, ctx->ctx.context);
f3c4f76a22b71b3c76c7f586db40b04e75564c2cTimo Sirainen return ctx->next || ctx->destroyed;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
1aad8ad0590bee2d09d5fdb5413af72e2a8e156aTimo Sirainen
1aad8ad0590bee2d09d5fdb5413af72e2a8e156aTimo Sirainen if (strcmp(reply, "OK") != 0)
1aad8ad0590bee2d09d5fdb5413af72e2a8e156aTimo Sirainen ctx->ctx.failed = TRUE;
91e2dc36b9c0c91f0af716be81dc2aa6cbbed6c2Timo Sirainen if (!ctx->destroyed)
91e2dc36b9c0c91f0af716be81dc2aa6cbbed6c2Timo Sirainen ctx->ctx.callback(NULL, ctx->ctx.context);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen auth_request_unref(&ctx->ctx.auth_request);
1aad8ad0590bee2d09d5fdb5413af72e2a8e156aTimo Sirainen return TRUE;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstruct userdb_iterate_context *
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainenuserdb_blocking_iter_init(struct auth_request *request,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen userdb_iter_callback_t *callback, void *context)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct blocking_userdb_iterate_context *ctx;
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen string_t *str;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str = t_str_new(128);
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen str_printfa(str, "LIST\t%u\t", request->userdb->userdb->id);
b0e9375a1ff97c9c7d40655922af5ccc73ecaa76Timo Sirainen auth_request_export(request, str);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen ctx = p_new(request->pool, struct blocking_userdb_iterate_context, 1);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen ctx->ctx.auth_request = request;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->ctx.callback = callback;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->ctx.context = context;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen auth_request_ref(request);
f08c6da58d4cffc5b4777485ebc475dff614e491Timo Sirainen ctx->conn = auth_worker_call(request->pool, "*",
f08c6da58d4cffc5b4777485ebc475dff614e491Timo Sirainen str_c(str), iter_callback, ctx);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return &ctx->ctx;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenvoid userdb_blocking_iter_next(struct userdb_iterate_context *_ctx)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct blocking_userdb_iterate_context *ctx =
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen (struct blocking_userdb_iterate_context *)_ctx;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->next = TRUE;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen auth_worker_server_resume_input(ctx->conn);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenint userdb_blocking_iter_deinit(struct userdb_iterate_context **_ctx)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct blocking_userdb_iterate_context *ctx =
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen (struct blocking_userdb_iterate_context *)*_ctx;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen int ret = ctx->ctx.failed ? -1 : 0;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen *_ctx = NULL;
91e2dc36b9c0c91f0af716be81dc2aa6cbbed6c2Timo Sirainen
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen /* iter_callback() may still be called */
91e2dc36b9c0c91f0af716be81dc2aa6cbbed6c2Timo Sirainen ctx->destroyed = TRUE;
f3c4f76a22b71b3c76c7f586db40b04e75564c2cTimo Sirainen
f3c4f76a22b71b3c76c7f586db40b04e75564c2cTimo Sirainen auth_worker_server_resume_input(ctx->conn);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return ret;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}