From: Marco Bettini Date: Wed, 10 May 2023 15:54:32 +0000 (+0000) Subject: auth: db-ldap - Add %{ldap_multi} X-Git-Tag: 2.4.0~2718 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c43b93bae91b28ef09ceed9ca27b4ddd16178768;p=thirdparty%2Fdovecot%2Fcore.git auth: db-ldap - Add %{ldap_multi} --- diff --git a/src/auth/db-ldap.c b/src/auth/db-ldap.c index d636673e9c..bbc5aec2be 100644 --- a/src/auth/db-ldap.c +++ b/src/auth/db-ldap.c @@ -1429,6 +1429,7 @@ void db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist, { static struct var_expand_func_table var_funcs_table[] = { { "ldap", db_ldap_field_find }, + { "ldap_multi", db_ldap_field_find }, { "ldap_ptr", db_ldap_field_find }, { NULL, NULL } }; @@ -1712,6 +1713,88 @@ db_ldap_field_expand(const char *data, void *context, return 1; } +void db_ldap_field_multi_expand_parse_data( + const char *data, const char **field_name_r, + const char **separator_r, const char **default_r) +{ + /* start with the defaults */ + *separator_r = " "; + *default_r = ""; + + *field_name_r = t_strcut(data, ':'); + const char *ptr = i_strchr_to_next(data, ':'); + + if (ptr == NULL || ptr[0] == '\0') { + /* Handling here the cases: + attrName -> *sep_r = (default), *default_r = (default) + attrName: -> *sep_r = (default), *default_r = (default) + */ + return; + } + + if (ptr[0] == ':' && (ptr[1] == '\0' || ptr[1] == ':')) { + /* Handling here the cases (exceptions dealing with ':'): + attrName:: -> *sep_r = ":", *default_r = (default) + attrName::: -> *sep_r = ":", *default_r = (default) + attrName:::defl -> *sep_r = ":", *default_r = "defl" + */ + *separator_r = ":"; + + /* The current ':' was not a field separator, but just datum. + Advance paste it */ + if (*++ptr == ':') + ++ptr; + } else { + /* Handling here the cases (the normal ones): + attrName::defl -> *sep_r = (default), *default_r = "defl" + attrName:sep -> *sep_r = "sep", *default_r = (default) + attrName:sep:defl -> *sep_r = "sep", *default_r = "defl" + */ + const char *sep = t_strcut(ptr, ':'); + ptr = i_strchr_to_next(ptr, ':'); + if (*sep != '\0') + *separator_r = sep; + } + + if (ptr == NULL || ptr[0] == '\0') + return; + + *default_r = ptr; +} + +static int +db_ldap_field_multi_expand(const char *data, void *context, + const char **value_r, const char **error_r ATTR_UNUSED) +{ + struct db_ldap_result_iterate_context *ctx = context; + struct db_ldap_value *ldap_value; + + const char *field_name; + const char *field_separator; + const char *field_default; + + db_ldap_field_multi_expand_parse_data(data, &field_name, + &field_separator, + &field_default); + *value_r = field_default; + + ldap_value = hash_table_lookup(ctx->ldap_attrs, field_name); + if (ldap_value == NULL) { + /* requested ldap attribute wasn't returned at all */ + str_printfa(ctx->debug, "; %s missing", field_name); + return 1; + } + ldap_value->used = TRUE; + + if (ldap_value->values[0] == NULL) { + /* no value for ldap attribute */ + return 1; + } + + *value_r = t_strarray_join(ldap_value->values, field_separator); + return 1; +} + static int db_ldap_field_ptr_expand(const char *data, void *context, const char **value_r, const char **error_r) @@ -1743,6 +1826,7 @@ db_ldap_field_dn_expand(const char *data ATTR_UNUSED, void *context ATTR_UNUSED, static struct var_expand_func_table ldap_var_funcs_table[] = { { "ldap", db_ldap_field_expand }, + { "ldap_multi", db_ldap_field_multi_expand }, { "ldap_ptr", db_ldap_field_ptr_expand }, { "ldap_dn", db_ldap_field_dn_expand }, { NULL, NULL } diff --git a/src/auth/db-ldap.h b/src/auth/db-ldap.h index 1ccc47e76a..bc19b5d4bf 100644 --- a/src/auth/db-ldap.h +++ b/src/auth/db-ldap.h @@ -223,4 +223,8 @@ void db_ldap_result_iterate_deinit(struct db_ldap_result_iterate_context **ctx); const char *const *db_ldap_parse_attrs(const char *cstr); +void db_ldap_field_multi_expand_parse_data( + const char *data, const char **field_name_r, + const char **separator_r, const char **default_r); + #endif diff --git a/src/auth/test-auth.h b/src/auth/test-auth.h index 195ff9c279..625860f013 100644 --- a/src/auth/test-auth.h +++ b/src/auth/test-auth.h @@ -22,6 +22,7 @@ void passdb_mock_mod_init(void); void passdb_mock_mod_deinit(void); void test_db_ldap_parse_attrs(void); +void test_db_ldap_field_multi_expand_parse_data(void); #endif diff --git a/src/auth/test-db-ldap.c b/src/auth/test-db-ldap.c index 35bc416847..2b87a6fb76 100644 --- a/src/auth/test-db-ldap.c +++ b/src/auth/test-db-ldap.c @@ -58,3 +58,43 @@ void test_db_ldap_parse_attrs(void) } test_end(); } + +void test_db_ldap_field_multi_expand_parse_data(void) +{ + struct vectors { + const char *inp; + const char *field; + const char *sep; + const char *defl; + } vectors[] = { + {.inp="", .field="", .sep=" ", .defl="" }, + {.inp="f", .field="f", .sep=" ", .defl="" }, + {.inp="f:", .field="f", .sep=" ", .defl="" }, + {.inp="f::", .field="f", .sep=":", .defl="" }, + {.inp="f:::", .field="f", .sep=":", .defl="" }, + {.inp="f:s", .field="f", .sep="s", .defl="" }, + {.inp="f:s:", .field="f", .sep="s", .defl="" }, + {.inp="f:s::", .field="f", .sep="s", .defl=":" }, + {.inp="f::d", .field="f", .sep=" ", .defl="d" }, + {.inp="f:::d", .field="f", .sep=":", .defl="d" }, + {.inp="f::d:", .field="f", .sep=" ", .defl="d:" }, + {.inp="f:::d:", .field="f", .sep=":", .defl="d:" }, + {} + }; + + test_begin("db ldap field multi expand parse data"); + unsigned int index = 0; + for (struct vectors *vector = vectors; vector->inp != NULL; vector++, index++) { + const char *field = NULL; + const char *sep = NULL; + const char *defl = NULL; + + db_ldap_field_multi_expand_parse_data( + vector->inp, &field, &sep, &defl); + + test_assert_strcmp_idx(vector->field, field, index); + test_assert_strcmp_idx(vector->sep, sep, index); + test_assert_strcmp_idx(vector->defl, defl, index); + } + test_end(); +} diff --git a/src/auth/test-main.c b/src/auth/test-main.c index f149eaa56a..e1201cfb27 100644 --- a/src/auth/test-main.c +++ b/src/auth/test-main.c @@ -13,6 +13,7 @@ int main(int argc, const char *argv[]) int ret; static const struct named_test test_functions[] = { TEST_NAMED(test_db_ldap_parse_attrs) + TEST_NAMED(test_db_ldap_field_multi_expand_parse_data) TEST_NAMED(test_auth_request_var_expand) TEST_NAMED(test_auth_request_fields) TEST_NAMED(test_db_dict_parse_cache_key)