--- /dev/null
+/* Copyright (c) 2002-2020 Dovecot authors, see the included COPYING file */
+
+#include "auth-common.h"
+#include "str.h"
+#include "strescape.h"
+#include "auth-request.h"
+
+static void
+auth_str_add_keyvalue(string_t *dest, const char *key, const char *value)
+{
+ str_append_c(dest, '\t');
+ str_append(dest, key);
+ if (value != NULL) {
+ str_append_c(dest, '=');
+ str_append_tabescaped(dest, value);
+ }
+}
+
+static void
+auth_request_export_fields(string_t *dest, struct auth_fields *auth_fields,
+ const char *prefix)
+{
+ const ARRAY_TYPE(auth_field) *fields = auth_fields_export(auth_fields);
+ const struct auth_field *field;
+
+ array_foreach(fields, field) {
+ str_printfa(dest, "\t%s%s", prefix, field->key);
+ if (field->value != NULL) {
+ str_append_c(dest, '=');
+ str_append_tabescaped(dest, field->value);
+ }
+ }
+}
+
+void auth_request_export(struct auth_request *request, string_t *dest)
+{
+ const struct auth_request_fields *fields = &request->fields;
+
+ str_append(dest, "user=");
+ str_append_tabescaped(dest, fields->user);
+
+ auth_str_add_keyvalue(dest, "service", fields->service);
+
+ if (fields->master_user != NULL)
+ auth_str_add_keyvalue(dest, "master-user", fields->master_user);
+ auth_str_add_keyvalue(dest, "original-username",
+ fields->original_username);
+ if (fields->requested_login_user != NULL) {
+ auth_str_add_keyvalue(dest, "requested-login-user",
+ fields->requested_login_user);
+ }
+
+ if (fields->local_ip.family != 0) {
+ auth_str_add_keyvalue(dest, "lip",
+ net_ip2addr(&fields->local_ip));
+ }
+ if (fields->remote_ip.family != 0) {
+ auth_str_add_keyvalue(dest, "rip",
+ net_ip2addr(&fields->remote_ip));
+ }
+ if (fields->local_port != 0)
+ str_printfa(dest, "\tlport=%u", fields->local_port);
+ if (fields->remote_port != 0)
+ str_printfa(dest, "\trport=%u", fields->remote_port);
+ if (fields->real_local_ip.family != 0) {
+ auth_str_add_keyvalue(dest, "real_lip",
+ net_ip2addr(&fields->real_local_ip));
+ }
+ if (fields->real_remote_ip.family != 0) {
+ auth_str_add_keyvalue(dest, "real_rip",
+ net_ip2addr(&fields->real_remote_ip));
+ }
+ if (fields->real_local_port != 0)
+ str_printfa(dest, "\treal_lport=%u", fields->real_local_port);
+ if (fields->real_remote_port != 0)
+ str_printfa(dest, "\treal_rport=%u", fields->real_remote_port);
+ if (fields->local_name != 0) {
+ str_append(dest, "\tlocal_name=");
+ str_append_tabescaped(dest, fields->local_name);
+ }
+ if (fields->session_id != NULL)
+ str_printfa(dest, "\tsession=%s", fields->session_id);
+ if (event_want_debug(request->event))
+ str_append(dest, "\tdebug");
+ switch (fields->secured) {
+ case AUTH_REQUEST_SECURED_NONE: break;
+ case AUTH_REQUEST_SECURED: str_append(dest, "\tsecured"); break;
+ case AUTH_REQUEST_SECURED_TLS: str_append(dest, "\tsecured=tls"); break;
+ default: break;
+ }
+ if (fields->skip_password_check)
+ str_append(dest, "\tskip-password-check");
+ if (fields->delayed_credentials != NULL)
+ str_append(dest, "\tdelayed-credentials");
+ if (fields->valid_client_cert)
+ str_append(dest, "\tvalid-client-cert");
+ if (fields->no_penalty)
+ str_append(dest, "\tno-penalty");
+ if (fields->successful)
+ str_append(dest, "\tsuccessful");
+ if (fields->mech_name != NULL)
+ auth_str_add_keyvalue(dest, "mech", fields->mech_name);
+ if (fields->client_id != NULL)
+ auth_str_add_keyvalue(dest, "client_id", fields->client_id);
+ /* export passdb extra fields */
+ auth_request_export_fields(dest, fields->extra_fields, "passdb_");
+ /* export any userdb fields */
+ if (fields->userdb_reply != NULL)
+ auth_request_export_fields(dest, fields->userdb_reply, "userdb_");
+}
+
+bool auth_request_import_info(struct auth_request *request,
+ const char *key, const char *value)
+{
+ struct auth_request_fields *fields = &request->fields;
+
+ i_assert(value != NULL);
+
+ /* authentication and user lookups may set these */
+ if (strcmp(key, "service") == 0)
+ fields->service = p_strdup(request->pool, value);
+ else if (strcmp(key, "lip") == 0) {
+ (void)net_addr2ip(value, &fields->local_ip);
+ if (fields->real_local_ip.family == 0)
+ fields->real_local_ip = fields->local_ip;
+ } else if (strcmp(key, "rip") == 0) {
+ (void)net_addr2ip(value, &fields->remote_ip);
+ if (fields->real_remote_ip.family == 0)
+ fields->real_remote_ip = fields->remote_ip;
+ } else if (strcmp(key, "lport") == 0) {
+ (void)net_str2port(value, &fields->local_port);
+ if (fields->real_local_port == 0)
+ fields->real_local_port = fields->local_port;
+ } else if (strcmp(key, "rport") == 0) {
+ (void)net_str2port(value, &fields->remote_port);
+ if (fields->real_remote_port == 0)
+ fields->real_remote_port = fields->remote_port;
+ }
+ else if (strcmp(key, "real_lip") == 0)
+ (void)net_addr2ip(value, &fields->real_local_ip);
+ else if (strcmp(key, "real_rip") == 0)
+ (void)net_addr2ip(value, &fields->real_remote_ip);
+ else if (strcmp(key, "real_lport") == 0)
+ (void)net_str2port(value, &fields->real_local_port);
+ else if (strcmp(key, "real_rport") == 0)
+ (void)net_str2port(value, &fields->real_remote_port);
+ else if (strcmp(key, "local_name") == 0)
+ fields->local_name = p_strdup(request->pool, value);
+ else if (strcmp(key, "session") == 0)
+ fields->session_id = p_strdup(request->pool, value);
+ else if (strcmp(key, "debug") == 0)
+ event_set_forced_debug(request->event, TRUE);
+ else if (strcmp(key, "client_id") == 0)
+ fields->client_id = p_strdup(request->pool, value);
+ else if (strcmp(key, "forward_fields") == 0) {
+ auth_fields_import_prefixed(fields->extra_fields,
+ "forward_", value, 0);
+ /* make sure the forward_ fields aren't deleted by
+ auth_fields_rollback() if the first passdb lookup fails. */
+ auth_fields_snapshot(fields->extra_fields);
+ } else
+ return FALSE;
+ /* NOTE: keep in sync with auth_request_export() */
+ return TRUE;
+}
+
+bool auth_request_import_auth(struct auth_request *request,
+ const char *key, const char *value)
+{
+ struct auth_request_fields *fields = &request->fields;
+
+ i_assert(value != NULL);
+
+ if (auth_request_import_info(request, key, value))
+ return TRUE;
+
+ /* auth client may set these */
+ if (strcmp(key, "secured") == 0) {
+ if (strcmp(value, "tls") == 0)
+ fields->secured = AUTH_REQUEST_SECURED_TLS;
+ else
+ fields->secured = AUTH_REQUEST_SECURED;
+ }
+ else if (strcmp(key, "final-resp-ok") == 0)
+ fields->final_resp_ok = TRUE;
+ else if (strcmp(key, "no-penalty") == 0)
+ fields->no_penalty = TRUE;
+ else if (strcmp(key, "valid-client-cert") == 0)
+ fields->valid_client_cert = TRUE;
+ else if (strcmp(key, "cert_username") == 0) {
+ if (request->set->ssl_username_from_cert && *value != '\0') {
+ /* get username from SSL certificate. it overrides
+ the username given by the auth mechanism. */
+ fields->user = p_strdup(request->pool, value);
+ fields->cert_username = TRUE;
+ }
+ } else {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool auth_request_import(struct auth_request *request,
+ const char *key, const char *value)
+{
+ struct auth_request_fields *fields = &request->fields;
+
+ i_assert(value != NULL);
+
+ if (auth_request_import_auth(request, key, value))
+ return TRUE;
+
+ /* for communication between auth master and worker processes */
+ if (strcmp(key, "user") == 0)
+ fields->user = p_strdup(request->pool, value);
+ else if (strcmp(key, "master-user") == 0)
+ fields->master_user = p_strdup(request->pool, value);
+ else if (strcmp(key, "original-username") == 0)
+ fields->original_username = p_strdup(request->pool, value);
+ else if (strcmp(key, "requested-login-user") == 0)
+ fields->requested_login_user = p_strdup(request->pool, value);
+ else if (strcmp(key, "successful") == 0)
+ fields->successful = TRUE;
+ else if (strcmp(key, "skip-password-check") == 0)
+ fields->skip_password_check = TRUE;
+ else if (strcmp(key, "delayed-credentials") == 0) {
+ /* just make passdb_handle_credentials() work identically in
+ auth-worker as it does in auth-master. the worker shouldn't
+ care about the actual contents of the credentials. */
+ fields->delayed_credentials = &uchar_nul;
+ fields->delayed_credentials_size = 1;
+ } else if (strcmp(key, "mech") == 0)
+ fields->mech_name = p_strdup(request->pool, value);
+ else if (str_begins(key, "passdb_"))
+ auth_fields_add(fields->extra_fields, key+7, value, 0);
+ else if (str_begins(key, "userdb_")) {
+ if (fields->userdb_reply == NULL)
+ fields->userdb_reply = auth_fields_init(request->pool);
+ auth_fields_add(fields->userdb_reply, key+7, value, 0);
+ } else
+ return FALSE;
+
+ return TRUE;
+}
pool_unref(&request->pool);
}
-static void
-auth_str_add_keyvalue(string_t *dest, const char *key, const char *value)
-{
- str_append_c(dest, '\t');
- str_append(dest, key);
- if (value != NULL) {
- str_append_c(dest, '=');
- str_append_tabescaped(dest, value);
- }
-}
-
-static void
-auth_request_export_fields(string_t *dest, struct auth_fields *auth_fields,
- const char *prefix)
-{
- const ARRAY_TYPE(auth_field) *fields = auth_fields_export(auth_fields);
- const struct auth_field *field;
-
- array_foreach(fields, field) {
- str_printfa(dest, "\t%s%s", prefix, field->key);
- if (field->value != NULL) {
- str_append_c(dest, '=');
- str_append_tabescaped(dest, field->value);
- }
- }
-}
-
-void auth_request_export(struct auth_request *request, string_t *dest)
-{
- const struct auth_request_fields *fields = &request->fields;
-
- str_append(dest, "user=");
- str_append_tabescaped(dest, fields->user);
-
- auth_str_add_keyvalue(dest, "service", fields->service);
-
- if (fields->master_user != NULL)
- auth_str_add_keyvalue(dest, "master-user", fields->master_user);
- auth_str_add_keyvalue(dest, "original-username",
- fields->original_username);
- if (fields->requested_login_user != NULL) {
- auth_str_add_keyvalue(dest, "requested-login-user",
- fields->requested_login_user);
- }
-
- if (fields->local_ip.family != 0) {
- auth_str_add_keyvalue(dest, "lip",
- net_ip2addr(&fields->local_ip));
- }
- if (fields->remote_ip.family != 0) {
- auth_str_add_keyvalue(dest, "rip",
- net_ip2addr(&fields->remote_ip));
- }
- if (fields->local_port != 0)
- str_printfa(dest, "\tlport=%u", fields->local_port);
- if (fields->remote_port != 0)
- str_printfa(dest, "\trport=%u", fields->remote_port);
- if (fields->real_local_ip.family != 0) {
- auth_str_add_keyvalue(dest, "real_lip",
- net_ip2addr(&fields->real_local_ip));
- }
- if (fields->real_remote_ip.family != 0) {
- auth_str_add_keyvalue(dest, "real_rip",
- net_ip2addr(&fields->real_remote_ip));
- }
- if (fields->real_local_port != 0)
- str_printfa(dest, "\treal_lport=%u", fields->real_local_port);
- if (fields->real_remote_port != 0)
- str_printfa(dest, "\treal_rport=%u", fields->real_remote_port);
- if (fields->local_name != 0) {
- str_append(dest, "\tlocal_name=");
- str_append_tabescaped(dest, fields->local_name);
- }
- if (fields->session_id != NULL)
- str_printfa(dest, "\tsession=%s", fields->session_id);
- if (event_want_debug(request->event))
- str_append(dest, "\tdebug");
- switch (fields->secured) {
- case AUTH_REQUEST_SECURED_NONE: break;
- case AUTH_REQUEST_SECURED: str_append(dest, "\tsecured"); break;
- case AUTH_REQUEST_SECURED_TLS: str_append(dest, "\tsecured=tls"); break;
- default: break;
- }
- if (fields->skip_password_check)
- str_append(dest, "\tskip-password-check");
- if (fields->delayed_credentials != NULL)
- str_append(dest, "\tdelayed-credentials");
- if (fields->valid_client_cert)
- str_append(dest, "\tvalid-client-cert");
- if (fields->no_penalty)
- str_append(dest, "\tno-penalty");
- if (fields->successful)
- str_append(dest, "\tsuccessful");
- if (fields->mech_name != NULL)
- auth_str_add_keyvalue(dest, "mech", fields->mech_name);
- if (fields->client_id != NULL)
- auth_str_add_keyvalue(dest, "client_id", fields->client_id);
- /* export passdb extra fields */
- auth_request_export_fields(dest, fields->extra_fields, "passdb_");
- /* export any userdb fields */
- if (fields->userdb_reply != NULL)
- auth_request_export_fields(dest, fields->userdb_reply, "userdb_");
-}
-
-bool auth_request_import_info(struct auth_request *request,
- const char *key, const char *value)
-{
- struct auth_request_fields *fields = &request->fields;
-
- i_assert(value != NULL);
-
- /* authentication and user lookups may set these */
- if (strcmp(key, "service") == 0)
- fields->service = p_strdup(request->pool, value);
- else if (strcmp(key, "lip") == 0) {
- (void)net_addr2ip(value, &fields->local_ip);
- if (fields->real_local_ip.family == 0)
- fields->real_local_ip = fields->local_ip;
- } else if (strcmp(key, "rip") == 0) {
- (void)net_addr2ip(value, &fields->remote_ip);
- if (fields->real_remote_ip.family == 0)
- fields->real_remote_ip = fields->remote_ip;
- } else if (strcmp(key, "lport") == 0) {
- (void)net_str2port(value, &fields->local_port);
- if (fields->real_local_port == 0)
- fields->real_local_port = fields->local_port;
- } else if (strcmp(key, "rport") == 0) {
- (void)net_str2port(value, &fields->remote_port);
- if (fields->real_remote_port == 0)
- fields->real_remote_port = fields->remote_port;
- }
- else if (strcmp(key, "real_lip") == 0)
- (void)net_addr2ip(value, &fields->real_local_ip);
- else if (strcmp(key, "real_rip") == 0)
- (void)net_addr2ip(value, &fields->real_remote_ip);
- else if (strcmp(key, "real_lport") == 0)
- (void)net_str2port(value, &fields->real_local_port);
- else if (strcmp(key, "real_rport") == 0)
- (void)net_str2port(value, &fields->real_remote_port);
- else if (strcmp(key, "local_name") == 0)
- fields->local_name = p_strdup(request->pool, value);
- else if (strcmp(key, "session") == 0)
- fields->session_id = p_strdup(request->pool, value);
- else if (strcmp(key, "debug") == 0)
- event_set_forced_debug(request->event, TRUE);
- else if (strcmp(key, "client_id") == 0)
- fields->client_id = p_strdup(request->pool, value);
- else if (strcmp(key, "forward_fields") == 0) {
- auth_fields_import_prefixed(fields->extra_fields,
- "forward_", value, 0);
- /* make sure the forward_ fields aren't deleted by
- auth_fields_rollback() if the first passdb lookup fails. */
- auth_fields_snapshot(fields->extra_fields);
- } else
- return FALSE;
- /* NOTE: keep in sync with auth_request_export() */
- return TRUE;
-}
-
-bool auth_request_import_auth(struct auth_request *request,
- const char *key, const char *value)
-{
- struct auth_request_fields *fields = &request->fields;
-
- i_assert(value != NULL);
-
- if (auth_request_import_info(request, key, value))
- return TRUE;
-
- /* auth client may set these */
- if (strcmp(key, "secured") == 0) {
- if (strcmp(value, "tls") == 0)
- fields->secured = AUTH_REQUEST_SECURED_TLS;
- else
- fields->secured = AUTH_REQUEST_SECURED;
- }
- else if (strcmp(key, "final-resp-ok") == 0)
- fields->final_resp_ok = TRUE;
- else if (strcmp(key, "no-penalty") == 0)
- fields->no_penalty = TRUE;
- else if (strcmp(key, "valid-client-cert") == 0)
- fields->valid_client_cert = TRUE;
- else if (strcmp(key, "cert_username") == 0) {
- if (request->set->ssl_username_from_cert && *value != '\0') {
- /* get username from SSL certificate. it overrides
- the username given by the auth mechanism. */
- fields->user = p_strdup(request->pool, value);
- fields->cert_username = TRUE;
- }
- } else {
- return FALSE;
- }
- return TRUE;
-}
-
bool auth_request_import_master(struct auth_request *request,
const char *key, const char *value)
{
return TRUE;
}
-bool auth_request_import(struct auth_request *request,
- const char *key, const char *value)
-{
- struct auth_request_fields *fields = &request->fields;
-
- i_assert(value != NULL);
-
- if (auth_request_import_auth(request, key, value))
- return TRUE;
-
- /* for communication between auth master and worker processes */
- if (strcmp(key, "user") == 0)
- fields->user = p_strdup(request->pool, value);
- else if (strcmp(key, "master-user") == 0)
- fields->master_user = p_strdup(request->pool, value);
- else if (strcmp(key, "original-username") == 0)
- fields->original_username = p_strdup(request->pool, value);
- else if (strcmp(key, "requested-login-user") == 0)
- fields->requested_login_user = p_strdup(request->pool, value);
- else if (strcmp(key, "successful") == 0)
- fields->successful = TRUE;
- else if (strcmp(key, "skip-password-check") == 0)
- fields->skip_password_check = TRUE;
- else if (strcmp(key, "delayed-credentials") == 0) {
- /* just make passdb_handle_credentials() work identically in
- auth-worker as it does in auth-master. the worker shouldn't
- care about the actual contents of the credentials. */
- fields->delayed_credentials = &uchar_nul;
- fields->delayed_credentials_size = 1;
- } else if (strcmp(key, "mech") == 0)
- fields->mech_name = p_strdup(request->pool, value);
- else if (str_begins(key, "passdb_"))
- auth_fields_add(fields->extra_fields, key+7, value, 0);
- else if (str_begins(key, "userdb_")) {
- if (fields->userdb_reply == NULL)
- fields->userdb_reply = auth_fields_init(request->pool);
- auth_fields_add(fields->userdb_reply, key+7, value, 0);
- } else
- return FALSE;
-
- return TRUE;
-}
-
static bool auth_request_fail_on_nuls(struct auth_request *request,
const unsigned char *data, size_t data_size)
{