passdb-blocking.c revision 47bb4a7615c85f212f061499f04f121d6d625387
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch/* Copyright (C) 2005 Timo Sirainen */
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch#include "common.h"
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch#include "str.h"
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch#include "auth-worker-server.h"
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch#include "password-scheme.h"
833bed942977673526c72e79bccc09314fc57104Phil Carmody#include "passdb.h"
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch#include "passdb-blocking.h"
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch#include <stdlib.h>
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschstatic enum passdb_result
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschcheck_failure(struct auth_request *request, const char **reply)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch enum passdb_result ret;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch const char *p;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch /* OK / FAIL */
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (strncmp(*reply, "OK\t", 3) == 0) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch *reply += 3;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return PASSDB_RESULT_OK;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch /* FAIL \t result \t password */
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (strncmp(*reply, "FAIL\t", 5) == 0) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch *reply += 5;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch ret = atoi(t_strcut(*reply, '\t'));
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch p = strchr(*reply, '\t');
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (p == NULL)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch *reply += strlen(*reply);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch else
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch *reply = p + 1;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (ret != PASSDB_RESULT_OK)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return ret;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch auth_request_log_error(request, "blocking",
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch "Received invalid FAIL result from worker: %d", ret);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return PASSDB_RESULT_INTERNAL_FAILURE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch } else {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch auth_request_log_error(request, "blocking",
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch "Received unknown reply from worker: %s", *reply);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return PASSDB_RESULT_INTERNAL_FAILURE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschstatic int get_pass_reply(struct auth_request *request, const char *reply,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch const char **password_r, const char **scheme_r)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch const char *p, *p2, **tmp;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch /* user \t {scheme}password [\t extra] */
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch p = strchr(reply, '\t');
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch /* username may have changed, update it */
7c7117e542b6a44c1db7fc91c0180bdace6dbce7Stephan Bosch auth_request_set_field(request, "user", p == NULL ? reply :
7c7117e542b6a44c1db7fc91c0180bdace6dbce7Stephan Bosch t_strdup_until(reply, p), NULL);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (p == NULL) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch /* we didn't get a password. */
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch *password_r = NULL;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch *scheme_r = NULL;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return 0;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch p2 = strchr(++p, '\t');
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (p2 == NULL) {
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch *password_r = p;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch reply = "";
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch } else {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch *password_r = t_strdup_until(p, p2);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch reply = p2 + 1;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (**password_r == '\0') {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch *password_r = NULL;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch *scheme_r = NULL;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch } else {
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch request->passdb_password =
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch p_strdup(request->pool, *password_r);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch *scheme_r = password_get_scheme(password_r);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (*scheme_r == NULL) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch auth_request_log_error(request, "blocking",
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch "Received reply from worker without "
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch "password scheme");
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return -1;
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch }
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (*reply != '\0') {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_assert(request->extra_fields == NULL);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch for (tmp = t_strsplit(reply, "\t"); *tmp != NULL; tmp++) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch p = strchr(*tmp, '=');
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (p == NULL)
14bd2410de3a0261d9c53c6120915027262216bdTimo Sirainen p = "";
14bd2410de3a0261d9c53c6120915027262216bdTimo Sirainen else {
b37e11d37fb1ebf50511eef5d9d96d1205818458Stephan Bosch *tmp = t_strdup_until(*tmp, p);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch p++;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch auth_request_set_field(request, *tmp, p, NULL);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return 0;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschstatic void
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschverify_plain_callback(struct auth_request *request, const char *reply)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch enum passdb_result result;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch const char *password, *scheme;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch result = check_failure(request, &reply);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (result > 0) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (get_pass_reply(request, reply, &password, &scheme) < 0)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch result = PASSDB_RESULT_INTERNAL_FAILURE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch auth_request_verify_plain_callback(result, request);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschvoid passdb_blocking_verify_plain(struct auth_request *request)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch string_t *str;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_assert(request->extra_fields == NULL);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch str = t_str_new(64);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch str_printfa(str, "PASSV\t%u\t", request->passdb->id);
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch str_append(str, request->mech_password);
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch str_append_c(str, '\t');
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch auth_request_export(request, str);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch auth_worker_call(request, str_c(str), verify_plain_callback);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschstatic void
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschlookup_credentials_callback(struct auth_request *request, const char *reply)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch enum passdb_result result;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch const char *password = NULL, *scheme = NULL;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
e1a4ea6ad3e799ef8df7395e765c0ae9218e6c5dStephan Bosch result = check_failure(request, &reply);
e1a4ea6ad3e799ef8df7395e765c0ae9218e6c5dStephan Bosch if (result > 0) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (get_pass_reply(request, reply, &password, &scheme) < 0)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch result = PASSDB_RESULT_INTERNAL_FAILURE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch passdb_handle_credentials(result, password, scheme,
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch auth_request_lookup_credentials_callback,
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch request);
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch}
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Boschvoid passdb_blocking_lookup_credentials(struct auth_request *request)
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch{
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch string_t *str;
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_assert(request->extra_fields == NULL);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch str = t_str_new(64);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch str_printfa(str, "PASSL\t%u\t%d\t",
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch request->passdb->id, request->credentials);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch auth_request_export(request, str);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch auth_worker_call(request, str_c(str), lookup_credentials_callback);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch