From 5971004f796d8ba96c959161ea85237c2d631654 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Sat, 24 Feb 2024 13:30:21 +0200 Subject: [PATCH] auth: Add generic configuration for passdb/userdb fields 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 | 106 +++++++++++++++++++++++++++++++++++++++ src/auth/auth-request.h | 5 ++ src/auth/auth-settings.c | 10 ++++ src/auth/auth-settings.h | 4 ++ src/auth/passdb.h | 1 + src/auth/userdb.h | 1 + 6 files changed, 127 insertions(+) diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c index 76bdb07469..41af0cbdad 100644 --- a/src/auth/auth-request.c +++ b/src/auth/auth-request.c @@ -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); diff --git a/src/auth/auth-request.h b/src/auth/auth-request.h index f77d1f2b4c..6893bfce09 100644 --- a/src/auth/auth-request.h +++ b/src/auth/auth-request.h @@ -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); diff --git a/src/auth/auth-settings.c b/src/auth/auth-settings.c index 19c6290dc1..018b806711 100644 --- a/src/auth/auth-settings.c +++ b/src/auth/auth-settings.c @@ -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, }; diff --git a/src/auth/auth-settings.h b/src/auth/auth-settings.h index cbb5c07e53..feb1fe7535 100644 --- a/src/auth/auth-settings.h +++ b/src/auth/auth-settings.h @@ -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; diff --git a/src/auth/passdb.h b/src/auth/passdb.h index a2b48ecaa5..baab008ac6 100644 --- a/src/auth/passdb.h +++ b/src/auth/passdb.h @@ -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. */ diff --git a/src/auth/userdb.h b/src/auth/userdb.h index 3343595722..828bdb2c56 100644 --- a/src/auth/userdb.h +++ b/src/auth/userdb.h @@ -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. */ -- 2.47.3