userdb-blocking.c revision e9371f899a3d4207a0ffd3923ea5ec7250cf5e75
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2005-2011 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#include <stdlib.h>
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;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen const char *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;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen args = reply + 3;
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
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen if (*args != '\0') {
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen request->userdb_reply = auth_stream_reply_init(request->pool);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen auth_stream_reply_import(request->userdb_reply, args);
88e9835c4d8973c62cd4db1ec7324ff46dd3ff15Timo Sirainen if (auth_stream_reply_find(request->userdb_reply,
88e9835c4d8973c62cd4db1ec7324ff46dd3ff15Timo Sirainen "tempfail") != NULL)
88e9835c4d8973c62cd4db1ec7324ff46dd3ff15Timo Sirainen request->userdb_lookup_failed = 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{
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct auth_stream_reply *reply;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "USER", NULL);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->userdb->userdb->id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_request_export(request, reply);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen auth_request_ref(request);
1d22eaac93de41319918a1fc6de42bb302e25c1aTimo Sirainen auth_worker_call(request->pool, reply, 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) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->next = FALSE;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->ctx.callback(reply + 2, ctx->ctx.context);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return ctx->next;
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;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct auth_stream_reply *reply;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen auth_stream_reply_add(reply, "LIST", NULL);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen auth_stream_reply_add(reply, NULL,
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen dec2str(request->userdb->userdb->id));
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen auth_request_export(request, reply);
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);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen ctx->conn = auth_worker_call(request->pool, reply, 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;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return ret;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}