]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: Add generic configuration for passdb/userdb fields
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Sat, 24 Feb 2024 11:30:21 +0000 (13:30 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Wed, 12 Feb 2025 10:34:12 +0000 (12:34 +0200)
The following commits will make these work like:

passdb foo {
  fields {
    key = %{passdb_driver:fieldname:default}
  }
}

And similarly for userdb. This will remove the need for default_fields and
override_fields settings. It's also possible to use
passdb/userdb_fields_import_all setting to import all fields, which is
going to be especially useful for passwd-file.

src/auth/auth-request.c
src/auth/auth-request.h
src/auth/auth-settings.c
src/auth/auth-settings.h
src/auth/passdb.h
src/auth/userdb.h

index 76bdb07469b4aa2ba7ddbbebade32d25bf4c561b..41af0cbdad91780ec82210cffa72289690d58891 100644 (file)
@@ -803,6 +803,93 @@ static void auth_request_passdb_internal_failure(struct auth_request *request)
        auth_request_unref(&request);
 }
 
+static int
+auth_request_fields_var_expand_lookup(const char *data, void *context,
+                                     const char **value_r,
+                                     const char **error_r ATTR_UNUSED)
+{
+       struct auth_fields *fields = context;
+       *value_r = NULL;
+
+       const char *default_value = strchr(data, ':');
+       if (default_value == NULL) {
+               if (fields != NULL)
+                       *value_r = auth_fields_find(fields, data);
+               else
+                       *value_r = "";
+               return 1;
+       }
+       /* If the fields are not initialized do not try to find fields. */
+       if (fields != NULL)
+               *value_r = auth_fields_find(fields,
+                               t_strdup_until(data, default_value));
+       default_value++;
+       if (*value_r == NULL)
+               *value_r = default_value;
+       return 1;
+}
+
+int auth_request_set_passdb_fields(struct auth_request *request,
+                                  struct auth_fields *fields)
+{
+       struct event *event = event_create(authdb_event(request));
+       const struct auth_passdb_post_settings *post_set;
+       const char *error;
+
+       const char *driver_name =
+               t_str_replace(request->passdb->passdb->iface.name, '-', '_');
+       struct var_expand_func_table auth_request_fields_funcs[] = {
+               { driver_name, auth_request_fields_var_expand_lookup },
+               { NULL, NULL }
+       };
+
+       event_set_ptr(event, SETTINGS_EVENT_VAR_EXPAND_FUNC_TABLE,
+                     auth_request_fields_funcs);
+       event_set_ptr(event, SETTINGS_EVENT_VAR_EXPAND_FUNC_CONTEXT, fields);
+
+       if (settings_get(event, &auth_passdb_post_setting_parser_info, 0,
+                        &post_set, &error) < 0) {
+               e_error(event, "%s", error);
+               event_unref(&event);
+               return -1;
+       }
+       auth_request_set_strlist(request, &post_set->fields,
+                                STATIC_PASS_SCHEME);
+       settings_free(post_set);
+       event_unref(&event);
+       return 0;
+}
+
+int auth_request_set_userdb_fields(struct auth_request *request,
+                                  struct auth_fields *fields)
+{
+       struct event *event = event_create(authdb_event(request));
+       const struct auth_userdb_post_settings *post_set;
+       const char *error;
+
+       const char *driver_name =
+               t_str_replace(request->userdb->userdb->iface->name, '-', '_');
+       struct var_expand_func_table auth_request_fields_funcs[] = {
+               { driver_name, auth_request_fields_var_expand_lookup },
+               { NULL, NULL }
+       };
+
+       event_set_ptr(event, SETTINGS_EVENT_VAR_EXPAND_FUNC_TABLE,
+                     auth_request_fields_funcs);
+       event_set_ptr(event, SETTINGS_EVENT_VAR_EXPAND_FUNC_CONTEXT, fields);
+
+       if (settings_get(event, &auth_userdb_post_setting_parser_info, 0,
+                        &post_set, &error) < 0) {
+               e_error(event, "%s", error);
+               event_unref(&event);
+               return -1;
+       }
+       auth_request_set_userdb_strlist(request, &post_set->fields);
+       settings_free(post_set);
+       event_unref(&event);
+       return 0;
+}
+
 static int auth_request_set_default_fields(struct auth_request *request)
 {
        struct event *event = authdb_event(request);
@@ -826,6 +913,15 @@ static int auth_request_set_override_fields(struct auth_request *request)
        const struct auth_passdb_post_settings *post_set;
        const char *error;
 
+       if (request->passdb->passdb->iface.fields_supported) {
+               /* passdb_fields was already processed. It may be referring to
+                  %{driver:*} fields that are not available currently, so just
+                  skip processing the passdb_override_fields. This setting
+                  will go away anyway once all passdbs are converted to use
+                  fields. */
+               return 0;
+       }
+
        if (settings_get(event, &auth_passdb_post_setting_parser_info, 0,
                         &post_set, &error) < 0) {
                e_error(event, "%s", error);
@@ -859,6 +955,16 @@ static int auth_request_set_userdb_override_fields(struct auth_request *request)
        const struct auth_userdb_post_settings *post_set;
        const char *error;
 
+       if (request->userdb->userdb->iface->fields_supported) {
+               /* userdb_fields was already processed. It may be referring to
+                  %{driver:*} fields that are not available currently, so just
+                  skip processing the userdb_override_fields. This setting
+                  will go away anyway once all userdbs are converted to use
+                  fields. */
+               return 0;
+       }
+
+
        if (settings_get(event, &auth_userdb_post_setting_parser_info, 0,
                         &post_set, &error) < 0) {
                e_error(event, "%s", error);
index f77d1f2b4cc8be76f3cd952e66a6eab5550dba5c..6893bfce09bacff87af72109d1da9226610a1c32 100644 (file)
@@ -327,6 +327,11 @@ void auth_request_set_strlist(struct auth_request *request,
                              const ARRAY_TYPE(const_string) *strlist,
                              const char *default_scheme);
 
+int auth_request_set_passdb_fields(struct auth_request *request,
+                                  struct auth_fields *fields);
+int auth_request_set_userdb_fields(struct auth_request *request,
+                                  struct auth_fields *fields);
+
 void auth_request_init_userdb_reply(struct auth_request *request);
 void auth_request_set_userdb_field(struct auth_request *request,
                                   const char *name, const char *value);
index 19c6290dc10bee4743f8fb160284b423c58a7d61..018b8067110612b1a5998b4de16f77a6d33c9e31 100644 (file)
@@ -107,6 +107,7 @@ static const struct setting_define auth_passdb_setting_defines[] = {
        DEF(STR, name),
        DEF(STR, driver),
        DEF(STR_NOVARS, args),
+       DEF(BOOL, fields_import_all),
        DEF(BOOLLIST, mechanisms),
        DEF(STR, username_filter),
 
@@ -129,6 +130,7 @@ static const struct auth_passdb_settings auth_passdb_default_settings = {
        .name = "",
        .driver = "",
        .args = "",
+       .fields_import_all = TRUE,
        .mechanisms = ARRAY_INIT,
        .username_filter = "",
 
@@ -179,6 +181,8 @@ const struct setting_parser_info auth_passdb_pre_setting_parser_info = {
 };
 
 static const struct setting_define auth_passdb_post_setting_defines[] = {
+       { .type = SET_STRLIST, .key = "passdb_fields",
+         .offset = offsetof(struct auth_passdb_post_settings, fields) },
        { .type = SET_STRLIST, .key = "passdb_override_fields",
          .offset = offsetof(struct auth_passdb_post_settings, override_fields) },
 
@@ -186,6 +190,7 @@ static const struct setting_define auth_passdb_post_setting_defines[] = {
 };
 
 static const struct auth_passdb_post_settings auth_passdb_post_default_settings = {
+       .fields = ARRAY_INIT,
        .override_fields = ARRAY_INIT,
 };
 
@@ -207,6 +212,7 @@ static const struct setting_define auth_userdb_setting_defines[] = {
        DEF(STR, name),
        DEF(STR, driver),
        DEF(STR_NOVARS, args),
+       DEF(BOOL, fields_import_all),
 
        DEF(ENUM, skip),
        DEF(ENUM, result_success),
@@ -224,6 +230,7 @@ static const struct auth_userdb_settings auth_userdb_default_settings = {
        .name = "",
        .driver = "",
        .args = "",
+       .fields_import_all = TRUE,
 
        .skip = "never:found:notfound",
        .result_success = "return-ok:return:return-fail:continue:continue-ok:continue-fail",
@@ -268,6 +275,8 @@ const struct setting_parser_info auth_userdb_pre_setting_parser_info = {
 };
 
 static const struct setting_define auth_userdb_post_setting_defines[] = {
+       { .type = SET_STRLIST, .key = "userdb_fields",
+         .offset = offsetof(struct auth_userdb_post_settings, fields) },
        { .type = SET_STRLIST, .key = "userdb_override_fields",
          .offset = offsetof(struct auth_userdb_post_settings, override_fields) },
 
@@ -275,6 +284,7 @@ static const struct setting_define auth_userdb_post_setting_defines[] = {
 };
 
 static const struct auth_userdb_post_settings auth_userdb_post_default_settings = {
+       .fields = ARRAY_INIT,
        .override_fields = ARRAY_INIT,
 };
 
index cbb5c07e53e98000fdffc5794dd5437e765568bc..feb1fe75351a89a3d3c9ffd3cf0a7ab487ee11c8 100644 (file)
@@ -11,6 +11,7 @@ struct auth_passdb_pre_settings {
 
 struct auth_passdb_post_settings {
        pool_t pool;
+       ARRAY_TYPE(const_string) fields;
        ARRAY_TYPE(const_string) override_fields;
 };
 
@@ -19,6 +20,7 @@ struct auth_passdb_settings {
        const char *name;
        const char *driver;
        const char *args;
+       bool fields_import_all;
        ARRAY_TYPE(const_string) mechanisms;
        const char *username_filter;
 
@@ -41,6 +43,7 @@ struct auth_userdb_pre_settings {
 
 struct auth_userdb_post_settings {
        pool_t pool;
+       ARRAY_TYPE(const_string) fields;
        ARRAY_TYPE(const_string) override_fields;
 };
 
@@ -49,6 +52,7 @@ struct auth_userdb_settings {
        const char *name;
        const char *driver;
        const char *args;
+       bool fields_import_all;
 
        const char *skip;
        const char *result_success;
index a2b48ecaa56d5d555d8ccdee2348a140f2a57e12..baab008ac649a80fa583366c88cfb439aa44cccb 100644 (file)
@@ -36,6 +36,7 @@ typedef void set_credentials_callback_t(bool success,
 
 struct passdb_module_interface {
        const char *name;
+       bool fields_supported:1; /* FIXME: temporary - remove */
 
        /* Create a new passdb_module based on the settings looked up via the
           given event. */
index 3343595722f644dc72e56cdd66127c80bd6106d5..828bdb2c560b7344efeab368a202cdb6042af4bf 100644 (file)
@@ -47,6 +47,7 @@ struct userdb_iterate_context {
 
 struct userdb_module_interface {
        const char *name;
+       bool fields_supported:1; /* FIXME: temporary - remove */
 
        /* Create a new userdb_module based on the settings looked up via the
           given event. */