summaryrefslogtreecommitdiffstats
path: root/src/auth/auth-request.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:51:24 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 09:51:24 +0000
commitf7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch)
treea3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /src/auth/auth-request.h
parentInitial commit. (diff)
downloaddovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.tar.xz
dovecot-f7548d6d28c313cf80e6f3ef89aed16a19815df1.zip
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/auth/auth-request.h')
-rw-r--r--src/auth/auth-request.h394
1 files changed, 394 insertions, 0 deletions
diff --git a/src/auth/auth-request.h b/src/auth/auth-request.h
new file mode 100644
index 0000000..6a458d9
--- /dev/null
+++ b/src/auth/auth-request.h
@@ -0,0 +1,394 @@
+#ifndef AUTH_REQUEST_H
+#define AUTH_REQUEST_H
+
+#ifndef AUTH_REQUEST_FIELDS_CONST
+# define AUTH_REQUEST_FIELDS_CONST const
+#endif
+
+#include "array.h"
+#include "net.h"
+#include "var-expand.h"
+#include "mech.h"
+#include "userdb.h"
+#include "passdb.h"
+#include "auth-request-var-expand.h"
+#include "password-scheme.h"
+
+#define AUTH_REQUEST_USER_KEY_IGNORE " "
+
+struct auth_client_connection;
+
+enum auth_request_state {
+ AUTH_REQUEST_STATE_NEW,
+ AUTH_REQUEST_STATE_PASSDB,
+ AUTH_REQUEST_STATE_MECH_CONTINUE,
+ AUTH_REQUEST_STATE_FINISHED,
+ AUTH_REQUEST_STATE_USERDB,
+
+ AUTH_REQUEST_STATE_MAX
+};
+
+enum auth_request_secured {
+ AUTH_REQUEST_SECURED_NONE,
+ AUTH_REQUEST_SECURED,
+ AUTH_REQUEST_SECURED_TLS,
+};
+
+enum auth_request_cache_result {
+ AUTH_REQUEST_CACHE_NONE,
+ AUTH_REQUEST_CACHE_MISS,
+ AUTH_REQUEST_CACHE_HIT,
+};
+
+/* All auth request fields are exported to auth-worker process. */
+struct auth_request_fields {
+ /* user contains the user who is being authenticated.
+ When master user is logging in as someone else, it gets more
+ complicated. Initially user is set to master's username and the
+ requested_login_user is set to destination username. After masterdb
+ has validated user as a valid master user, master_user is set to
+ user and user is set to requested_login_user. */
+ char *user, *requested_login_user, *master_user;
+ /* original_username contains the username exactly as given by the
+ client. this is needed at least with DIGEST-MD5 for password
+ verification. however with master logins the master username has
+ been dropped from it. */
+ const char *original_username;
+ /* the username after doing all internal translations, but before
+ being changed by a db lookup */
+ const char *translated_username;
+ /* realm for the request, may be specified by some auth mechanisms */
+ const char *realm;
+
+ const char *service, *mech_name, *session_id, *local_name, *client_id;
+ struct ip_addr local_ip, remote_ip, real_local_ip, real_remote_ip;
+ in_port_t local_port, remote_port, real_local_port, real_remote_port;
+
+ /* extra_fields are returned in authentication reply. Fields prefixed
+ with "userdb_" are automatically placed to userdb_reply instead. */
+ struct auth_fields *extra_fields;
+ /* the whole userdb result reply */
+ struct auth_fields *userdb_reply;
+
+ /* Credentials from the first successful passdb lookup. These are used
+ as the final credentials, unless overridden by later passdb
+ lookups. Note that the requests in auth-worker processes see these
+ only as 1 byte sized \0 strings. */
+ const unsigned char *delayed_credentials;
+ size_t delayed_credentials_size;
+
+ enum auth_request_secured secured;
+
+ /* Authentication was successfully finished, including policy checks
+ and such. There may still be some final delay or final SASL
+ response. */
+ bool successful:1;
+ /* Password was verified successfully by a passdb. The following
+ passdbs shouldn't attempt to verify the password again. Note that
+ this differs from passdb_success, which may be set to FALSE due to
+ the result_* rules. */
+ bool skip_password_check:1;
+
+ /* flags received from auth client: */
+ bool final_resp_ok:1;
+ bool no_penalty:1;
+ bool valid_client_cert:1;
+ bool cert_username:1;
+};
+
+struct auth_request {
+ int refcount;
+
+ pool_t pool;
+
+ struct event *event;
+ struct event *mech_event;
+ ARRAY(struct event *) authdb_event;
+
+ enum auth_request_state state;
+ char *mech_password; /* set if verify_plain() is called */
+ char *passdb_password; /* set after password lookup if successful */
+ struct auth_request_proxy_dns_lookup_ctx *dns_lookup_ctx;
+ /* The final result of passdb lookup (delayed due to asynchronous
+ proxy DNS lookups) */
+ enum passdb_result passdb_result;
+
+ const struct mech_module *mech;
+ const struct auth_settings *set;
+ struct auth_passdb *passdb;
+ struct auth_userdb *userdb;
+
+ struct stats *stats;
+
+ /* passdb lookups have a handler, userdb lookups don't */
+ struct auth_request_handler *handler;
+ struct auth_master_connection *master;
+
+ /* FIXME: Remove this once mech-oauth2 correctly does the processing */
+ const char *openid_config_url;
+
+ unsigned int connect_uid;
+ unsigned int client_pid;
+ unsigned int id;
+ time_t last_access;
+ time_t delay_until;
+ pid_t session_pid;
+
+ /* These are const for most of the code, so they don't try to modify
+ the fields directly. Only auth-request-fields.c and unit tests have
+ the fields writable. This way it's more difficult to make them
+ out-of-sync with events. */
+ AUTH_REQUEST_FIELDS_CONST struct auth_request_fields fields;
+
+ struct timeout *to_abort, *to_penalty;
+ unsigned int policy_penalty;
+ unsigned int last_penalty;
+ size_t initial_response_len;
+ const unsigned char *initial_response;
+
+ union {
+ verify_plain_callback_t *verify_plain;
+ lookup_credentials_callback_t *lookup_credentials;
+ set_credentials_callback_t *set_credentials;
+ userdb_callback_t *userdb;
+ } private_callback;
+ /* Used by passdb's credentials lookup to determine which scheme is
+ wanted by the caller. For example CRAM-MD5 SASL mechanism wants
+ CRAM-MD5 scheme for passwords.
+
+ When doing a PASS lookup (without authenticating), this is set to ""
+ to imply that caller accepts any kind of credentials. After the
+ credentials lookup is finished, this is set to the scheme that was
+ actually received.
+
+ Otherwise, this is kept as NULL. */
+ const char *wanted_credentials_scheme;
+
+ void *context;
+
+ enum auth_request_cache_result passdb_cache_result;
+ enum auth_request_cache_result userdb_cache_result;
+
+ /* this is a lookup on auth socket (not login socket).
+ skip any proxying stuff if enabled. */
+ bool auth_only:1;
+ /* we're doing a userdb lookup now (we may have done passdb lookup
+ earlier) */
+ bool userdb_lookup:1;
+ /* DIGEST-MD5 kludge */
+ bool domain_is_realm:1;
+
+ bool request_auth_token:1;
+
+ /* success/failure states: */
+ bool failed:1; /* overrides any other success */
+ bool internal_failure:1;
+ bool passdbs_seen_user_unknown:1;
+ bool passdbs_seen_internal_failure:1;
+ bool userdbs_seen_internal_failure:1;
+
+ /* current state: */
+ bool handler_pending_reply:1;
+ bool accept_cont_input:1;
+ bool prefer_plain_credentials:1;
+ bool in_delayed_failure_queue:1;
+ bool removed_from_handler:1;
+ bool snapshot_have_userdb_prefetch_set:1;
+ /* username was changed by this passdb/userdb lookup. Used by
+ auth-workers to determine whether to send back a changed username. */
+ bool user_changed_by_lookup:1;
+ /* each passdb lookup can update the current success-status using the
+ result_* rules. the authentication succeeds only if this is TRUE
+ at the end. mechanisms that don't require passdb, but do a passdb
+ lookup anyway (e.g. GSSAPI) need to set this to TRUE by default. */
+ bool passdb_success:1;
+ /* userdb equivalent of passdb_success */
+ bool userdb_success:1;
+ /* the last userdb lookup failed either due to "tempfail" extra field
+ or because one of the returned uid/gid fields couldn't be translated
+ to a number */
+ bool userdb_lookup_tempfailed:1;
+ /* userdb_* fields have been set by the passdb lookup, userdb prefetch
+ will work. */
+ bool userdb_prefetch_set:1;
+ bool stats_sent:1;
+ bool policy_refusal:1;
+ bool policy_processed:1;
+
+ bool event_finished_sent:1;
+
+ /* ... mechanism specific data ... */
+};
+
+typedef void auth_request_proxy_cb_t(bool success, struct auth_request *);
+
+extern unsigned int auth_request_state_count[AUTH_REQUEST_STATE_MAX];
+
+extern const char auth_default_subsystems[2];
+#define AUTH_SUBSYS_DB &auth_default_subsystems[0]
+#define AUTH_SUBSYS_MECH &auth_default_subsystems[1]
+
+struct auth_request *
+auth_request_new(const struct mech_module *mech, struct event *parent_event);
+struct auth_request *auth_request_new_dummy(struct event *parent_event);
+void auth_request_init(struct auth_request *request);
+struct auth *auth_request_get_auth(struct auth_request *request);
+
+void auth_request_set_state(struct auth_request *request,
+ enum auth_request_state state);
+
+void auth_request_ref(struct auth_request *request);
+void auth_request_unref(struct auth_request **request);
+
+void auth_request_success(struct auth_request *request,
+ const void *data, size_t data_size);
+void auth_request_fail(struct auth_request *request);
+void auth_request_internal_failure(struct auth_request *request);
+
+void auth_request_export(struct auth_request *request, string_t *dest);
+bool auth_request_import(struct auth_request *request,
+ const char *key, const char *value);
+bool auth_request_import_info(struct auth_request *request,
+ const char *key, const char *value);
+bool auth_request_import_auth(struct auth_request *request,
+ const char *key, const char *value);
+bool auth_request_import_master(struct auth_request *request,
+ const char *key, const char *value);
+
+void auth_request_initial(struct auth_request *request);
+void auth_request_continue(struct auth_request *request,
+ const unsigned char *data, size_t data_size);
+
+void auth_request_verify_plain(struct auth_request *request,
+ const char *password,
+ verify_plain_callback_t *callback);
+void auth_request_lookup_credentials(struct auth_request *request,
+ const char *scheme,
+ lookup_credentials_callback_t *callback);
+void auth_request_lookup_user(struct auth_request *request,
+ userdb_callback_t *callback);
+
+bool auth_request_set_username(struct auth_request *request,
+ const char *username, const char **error_r);
+/* Change the username without any translations or checks. */
+void auth_request_set_username_forced(struct auth_request *request,
+ const char *username);
+bool auth_request_set_login_username(struct auth_request *request,
+ const char *username,
+ const char **error_r);
+/* Change the login username without any translations or checks. */
+void auth_request_set_login_username_forced(struct auth_request *request,
+ const char *username);
+void auth_request_set_realm(struct auth_request *request, const char *realm);
+/* Request was fully successfully authenticated, including policy checks etc. */
+void auth_request_set_auth_successful(struct auth_request *request);
+/* Password was successfully verified by a passdb. */
+void auth_request_set_password_verified(struct auth_request *request);
+/* Save credentials from a successful passdb lookup. */
+void auth_request_set_delayed_credentials(struct auth_request *request,
+ const unsigned char *credentials,
+ size_t size);
+
+void auth_request_set_field(struct auth_request *request,
+ const char *name, const char *value,
+ const char *default_scheme) ATTR_NULL(4);
+void auth_request_set_null_field(struct auth_request *request, const char *name);
+void auth_request_set_field_keyvalue(struct auth_request *request,
+ const char *field,
+ const char *default_scheme) ATTR_NULL(3);
+void auth_request_set_fields(struct auth_request *request,
+ const char *const *fields,
+ const char *default_scheme) ATTR_NULL(3);
+
+void auth_request_init_userdb_reply(struct auth_request *request,
+ bool add_default_fields);
+void auth_request_set_userdb_field(struct auth_request *request,
+ const char *name, const char *value);
+void auth_request_set_userdb_field_values(struct auth_request *request,
+ const char *name,
+ const char *const *values);
+/* returns -1 = failed, 0 = callback is called later, 1 = finished */
+int auth_request_proxy_finish(struct auth_request *request,
+ auth_request_proxy_cb_t *callback);
+void auth_request_proxy_finish_failure(struct auth_request *request);
+
+void auth_request_log_password_mismatch(struct auth_request *request,
+ const char *subsystem);
+int auth_request_password_verify(struct auth_request *request,
+ const char *plain_password,
+ const char *crypted_password,
+ const char *scheme, const char *subsystem);
+int auth_request_password_verify_log(struct auth_request *request,
+ const char *plain_password,
+ const char *crypted_password,
+ const char *scheme, const char *subsystem,
+ bool log_password_mismatch);
+enum passdb_result auth_request_password_missing(struct auth_request *request);
+
+void auth_request_get_log_prefix(string_t *str, struct auth_request *auth_request,
+ const char *subsystem);
+
+void auth_request_log_debug(struct auth_request *auth_request,
+ const char *subsystem,
+ const char *format, ...) ATTR_FORMAT(3, 4);
+void auth_request_log_info(struct auth_request *auth_request,
+ const char *subsystem,
+ const char *format, ...) ATTR_FORMAT(3, 4);
+void auth_request_log_warning(struct auth_request *auth_request,
+ const char *subsystem,
+ const char *format, ...) ATTR_FORMAT(3, 4);
+void auth_request_log_error(struct auth_request *auth_request,
+ const char *subsystem,
+ const char *format, ...) ATTR_FORMAT(3, 4);
+void auth_request_log_unknown_user(struct auth_request *auth_request,
+ const char *subsystem);
+
+void auth_request_log_login_failure(struct auth_request *request,
+ const char *subsystem,
+ const char *message);
+void
+auth_request_verify_plain_callback_finish(enum passdb_result result,
+ struct auth_request *request);
+void auth_request_verify_plain_callback(enum passdb_result result,
+ struct auth_request *request);
+void auth_request_lookup_credentials_callback(enum passdb_result result,
+ const unsigned char *credentials,
+ size_t size,
+ struct auth_request *request);
+void auth_request_set_credentials(struct auth_request *request,
+ const char *scheme, const char *data,
+ set_credentials_callback_t *callback);
+void auth_request_userdb_callback(enum userdb_result result,
+ struct auth_request *request);
+void auth_request_default_verify_plain_continue(struct auth_request *request,
+ verify_plain_callback_t *callback);
+
+void auth_request_refresh_last_access(struct auth_request *request);
+void auth_str_append(string_t *dest, const char *key, const char *value);
+bool auth_request_username_accepted(const char *const *filter, const char *username);
+struct event_passthrough *
+auth_request_finished_event(struct auth_request *request, struct event *event);
+void auth_request_log_finished(struct auth_request *request);
+void auth_request_master_user_login_finish(struct auth_request *request);
+const char *auth_request_get_log_prefix_db(struct auth_request *auth_request);
+void auth_request_fields_init(struct auth_request *request);
+
+void auth_request_passdb_lookup_begin(struct auth_request *request);
+void auth_request_passdb_lookup_end(struct auth_request *request,
+ enum passdb_result result);
+void auth_request_userdb_lookup_begin(struct auth_request *request);
+void auth_request_userdb_lookup_end(struct auth_request *request,
+ enum userdb_result result);
+
+/* Fetches the current authdb event, this is done because
+ some lookups can recurse into new lookups, requiring new event,
+ which will be returned here. */
+static inline struct event *authdb_event(const struct auth_request *request)
+{
+ if (array_count(&request->authdb_event) == 0)
+ return request->event;
+ struct event **e = array_back_modifiable(&request->authdb_event);
+ return *e;
+}
+
+#endif