summaryrefslogtreecommitdiffstats
path: root/src/auth/passdb-blocking.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/auth/passdb-blocking.c')
-rw-r--r--src/auth/passdb-blocking.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/src/auth/passdb-blocking.c b/src/auth/passdb-blocking.c
new file mode 100644
index 0000000..6b7030c
--- /dev/null
+++ b/src/auth/passdb-blocking.c
@@ -0,0 +1,173 @@
+/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
+
+#include "auth-common.h"
+#include "str.h"
+#include "strescape.h"
+#include "auth-worker-server.h"
+#include "password-scheme.h"
+#include "passdb.h"
+#include "passdb-blocking.h"
+
+
+static void
+auth_worker_reply_parse_args(struct auth_request *request,
+ const char *const *args)
+{
+ if (**args != '\0')
+ request->passdb_password = p_strdup(request->pool, *args);
+ args++;
+
+ if (*args != NULL)
+ auth_request_set_fields(request, args, NULL);
+}
+
+enum passdb_result
+passdb_blocking_auth_worker_reply_parse(struct auth_request *request, const char *reply)
+{
+ enum passdb_result ret;
+ const char *const *args;
+
+ args = t_strsplit_tabescaped(reply);
+
+ if (strcmp(*args, "OK") == 0 && args[1] != NULL && args[2] != NULL) {
+ /* OK \t user \t password [\t extra] */
+ if (args[1][0] != '\0')
+ auth_request_set_field(request, "user", args[1], NULL);
+ auth_worker_reply_parse_args(request, args + 2);
+ return PASSDB_RESULT_OK;
+ }
+
+ if (strcmp(*args, "NEXT") == 0 && args[1] != NULL) {
+ /* NEXT \t user [\t extra] */
+ if (args[1][0] != '\0')
+ auth_request_set_field(request, "user", args[1], NULL);
+ auth_worker_reply_parse_args(request, args + 1);
+ return PASSDB_RESULT_NEXT;
+ }
+
+ if (strcmp(*args, "FAIL") == 0 && args[1] != NULL) {
+ int result;
+ /* FAIL \t result [\t user \t password [\t extra]] */
+ if (str_to_int(args[1], &result) < 0) {
+ /* shouldn't happen */
+ } else {
+ ret = (enum passdb_result)result;
+ if (ret == PASSDB_RESULT_OK) {
+ /* shouldn't happen */
+ } else if (args[2] == NULL) {
+ /* internal failure most likely */
+ return ret;
+ } else if (args[3] != NULL) {
+ if (*args[2] != '\0') {
+ auth_request_set_field(request, "user",
+ args[2], NULL);
+ }
+ auth_worker_reply_parse_args(request, args + 3);
+ return ret;
+ }
+ }
+ }
+
+ e_error(authdb_event(request),
+ "Received invalid reply from worker: %s", reply);
+ return PASSDB_RESULT_INTERNAL_FAILURE;
+}
+
+static bool
+verify_plain_callback(struct auth_worker_connection *conn ATTR_UNUSED,
+ const char *reply, void *context)
+{
+ struct auth_request *request = context;
+ enum passdb_result result;
+
+ result = passdb_blocking_auth_worker_reply_parse(request, reply);
+ auth_request_verify_plain_callback(result, request);
+ auth_request_unref(&request);
+ return TRUE;
+}
+
+void passdb_blocking_verify_plain(struct auth_request *request)
+{
+ string_t *str;
+
+ str = t_str_new(128);
+ str_printfa(str, "PASSV\t%u\t", request->passdb->passdb->id);
+ str_append_tabescaped(str, request->mech_password);
+ str_append_c(str, '\t');
+ auth_request_export(request, str);
+
+ auth_request_ref(request);
+ auth_worker_call(request->pool, request->fields.user, str_c(str),
+ verify_plain_callback, request);
+}
+
+static bool
+lookup_credentials_callback(struct auth_worker_connection *conn ATTR_UNUSED,
+ const char *reply, void *context)
+{
+ struct auth_request *request = context;
+ enum passdb_result result;
+ const char *password = NULL, *scheme = NULL;
+
+ result = passdb_blocking_auth_worker_reply_parse(request, reply);
+ if (result == PASSDB_RESULT_OK && request->passdb_password != NULL) {
+ password = request->passdb_password;
+ scheme = password_get_scheme(&password);
+ if (scheme == NULL) {
+ e_error(authdb_event(request),
+ "Received reply from worker without "
+ "password scheme");
+ result = PASSDB_RESULT_INTERNAL_FAILURE;
+ }
+ }
+
+ passdb_handle_credentials(result, password, scheme,
+ auth_request_lookup_credentials_callback,
+ request);
+ auth_request_unref(&request);
+ return TRUE;
+}
+
+void passdb_blocking_lookup_credentials(struct auth_request *request)
+{
+ string_t *str;
+
+ str = t_str_new(128);
+ str_printfa(str, "PASSL\t%u\t", request->passdb->passdb->id);
+ str_append_tabescaped(str, request->wanted_credentials_scheme);
+ str_append_c(str, '\t');
+ auth_request_export(request, str);
+
+ auth_request_ref(request);
+ auth_worker_call(request->pool, request->fields.user, str_c(str),
+ lookup_credentials_callback, request);
+}
+
+static bool
+set_credentials_callback(struct auth_worker_connection *conn ATTR_UNUSED,
+ const char *reply, void *context)
+{
+ struct auth_request *request = context;
+ bool success;
+
+ success = strcmp(reply, "OK") == 0 || str_begins(reply, "OK\t");
+ request->private_callback.set_credentials(success, request);
+ auth_request_unref(&request);
+ return TRUE;
+}
+
+void passdb_blocking_set_credentials(struct auth_request *request,
+ const char *new_credentials)
+{
+ string_t *str;
+
+ str = t_str_new(128);
+ str_printfa(str, "SETCRED\t%u\t", request->passdb->passdb->id);
+ str_append_tabescaped(str, new_credentials);
+ str_append_c(str, '\t');
+ auth_request_export(request, str);
+
+ auth_request_ref(request);
+ auth_worker_call(request->pool, request->fields.user, str_c(str),
+ set_credentials_callback, request);
+}