]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
auth: db-ldap - Add %{ldap_multi}
authorMarco Bettini <marco.bettini@open-xchange.com>
Wed, 10 May 2023 15:54:32 +0000 (15:54 +0000)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 31 May 2023 19:27:43 +0000 (19:27 +0000)
src/auth/db-ldap.c
src/auth/db-ldap.h
src/auth/test-auth.h
src/auth/test-db-ldap.c
src/auth/test-main.c

index d636673e9c0b8cc20e8e203089797b0b8e7436ef..bbc5aec2beff6a74d1da5c71b854bb0b49aed796 100644 (file)
@@ -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 }
index 1ccc47e76a4b85a02eed0f6c4ea26cf82e7b4916..bc19b5d4bf0e972fc6c5c39e88dc48a54efaa7d5 100644 (file)
@@ -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
index 195ff9c279d3b56ecb341e6eea9b7b20fefcf911..625860f01345cf7868e182d033706ddc29b6fd3d 100644 (file)
@@ -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
 
index 35bc416847571334202b4959a169043915fda728..2b87a6fb763eb4525f27a43c05b1c66120ed951e 100644 (file)
@@ -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();
+}
index f149eaa56ac1c501211793d04820a4a10b1b25d2..e1201cfb273b6a551c5476f637c4e7604833d559 100644 (file)
@@ -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)