passdb-blocking.c revision 5d4855d7b4dcffb6975ed8e3c9c376dac74e5c8a
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (C) 2005 Timo Sirainen */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
5254d77805cd35b9356d072ba325c356c43b0d51Timo Sirainen#include "common.h"
5254d77805cd35b9356d072ba325c356c43b0d51Timo Sirainen#include "str.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "auth-worker-server.h"
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen#include "password-scheme.h"
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen#include "passdb.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "passdb-blocking.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include <stdlib.h>
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainenstatic void
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenauth_worker_reply_parse_args(struct auth_request *request,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *const *args)
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen{
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen if (**args != '\0')
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen request->passdb_password = p_strdup(request->pool, *args);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen args++;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (*args != NULL) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert(auth_stream_is_empty(request->extra_fields) ||
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen request->master_user != NULL);
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen auth_request_set_fields(request, args, NULL);
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen }
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
2c25e1360d4b5cc55eda969a3a7204d950de5a8fTimo Sirainenstatic enum passdb_result
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenauth_worker_reply_parse(struct auth_request *request, const char *reply)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen enum passdb_result ret;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen const char *const *args;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen args = t_strsplit(reply, "\t");
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen if (strcmp(*args, "OK") == 0 && args[1] != NULL && args[2] != NULL) {
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen /* OK \t user \t password [\t extra] */
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen auth_request_set_field(request, "user", args[1], NULL);
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen auth_worker_reply_parse_args(request, args + 2);
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen return PASSDB_RESULT_OK;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen }
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen if (strcmp(*args, "FAIL") == 0 && args[1] != NULL && args[2] != NULL) {
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen /* FAIL \t result \t password [\t extra] */
bf132be3fe1c9e8de84f10d0b05c0b46ca542ac4Timo Sirainen ret = atoi(args[1]);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (ret != PASSDB_RESULT_OK) {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen auth_worker_reply_parse_args(request, args + 2);
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen return ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
dd2df6a67f10792ce31a3666197c0b6885893a3aTimo Sirainen auth_request_log_error(request, "blocking",
14175321ddb88619015866978c05a27786ca4814Timo Sirainen "Received invalid reply from worker: %s", reply);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return PASSDB_RESULT_INTERNAL_FAILURE;
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen}
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainenstatic void
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainenverify_plain_callback(struct auth_request *request, const char *reply)
09801f106cd531a28b4e03ec665e44c421264560Timo Sirainen{
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen enum passdb_result result;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen result = auth_worker_reply_parse(request, reply);
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen auth_request_verify_plain_callback(result, request);
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen}
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainenvoid passdb_blocking_verify_plain(struct auth_request *request)
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen{
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen string_t *str;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen i_assert(auth_stream_is_empty(request->extra_fields) ||
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen request->master_user != NULL);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen str = t_str_new(64);
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen str_printfa(str, "PASSV\t%u\t", request->passdb->id);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen str_append(str, request->mech_password);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen str_append_c(str, '\t');
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen auth_request_export(request, str);
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen auth_worker_call(request, str_c(str), verify_plain_callback);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen}
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic void
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainenlookup_credentials_callback(struct auth_request *request, const char *reply)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen{
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen enum passdb_result result;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen const char *password = NULL, *scheme = NULL;
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen result = auth_worker_reply_parse(request, reply);
9f131c8b6d88ffc65d94eae63e0b3c11d7c24cb9Timo Sirainen if (result == PASSDB_RESULT_OK && request->passdb_password != NULL) {
9f131c8b6d88ffc65d94eae63e0b3c11d7c24cb9Timo Sirainen password = request->passdb_password;
9f131c8b6d88ffc65d94eae63e0b3c11d7c24cb9Timo Sirainen scheme = password_get_scheme(&password);
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen if (scheme == NULL) {
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen auth_request_log_error(request, "blocking",
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen "Received reply from worker without "
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen "password scheme");
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen result = PASSDB_RESULT_INTERNAL_FAILURE;
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen }
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen }
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen passdb_handle_credentials(result, password, scheme,
5024c4799b324ea15270152b775c67ccfc72d5bcTimo Sirainen auth_request_lookup_credentials_callback,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen request);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenvoid passdb_blocking_lookup_credentials(struct auth_request *request)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen string_t *str;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen i_assert(auth_stream_is_empty(request->extra_fields) ||
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen request->master_user != NULL);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen str = t_str_new(64);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen str_printfa(str, "PASSL\t%u\t%s\t",
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen request->passdb->id, request->credentials_scheme);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen auth_request_export(request, str);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen auth_worker_call(request, str_c(str), lookup_credentials_callback);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic void
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenset_credentials_callback(struct auth_request *request, const char *reply)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
1060afdc2fcdf647dbb3bc11647401f1b44a3a8aTimo Sirainen bool success;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen success = strcmp(reply, "OK") == 0 || strncmp(reply, "OK\t", 3) == 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen request->private_callback.set_credentials(success, request);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenvoid passdb_blocking_set_credentials(struct auth_request *request,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const char *new_credentials)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen string_t *str;
411d6baa37f31d90730e90c4a28c43e1974bbe58Timo Sirainen
4ae354df6e08998137b527f495bfaaf3daf9eddcTimo Sirainen str = t_str_new(64);
4ae354df6e08998137b527f495bfaaf3daf9eddcTimo Sirainen str_printfa(str, "SETCRED\t%u\t%s\t",
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen request->passdb->id, new_credentials);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen auth_request_export(request, str);
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen auth_worker_call(request, str_c(str), set_credentials_callback);
143cb2e0744e647f8fc637bbdea1106c1587a4bfTimo Sirainen}
8edc373587d75f8040e3c4416e50638aa2a32188Timo Sirainen