2 * Unit tests for ldap_message.
4 * Copyright (C) Catalyst.NET Ltd 2020
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 * These headers or their equivalents should be included prior to
31 * This allows test applications to use custom definitions of C standard
32 * library functions and types.
40 #include "lib/util/attr.h"
42 #include "lib/util/asn1.h"
43 #include "libcli/ldap/ldap_message.h"
44 #include "libcli/ldap/ldap_proto.h"
47 * declare the internal cmocka cm_print so we can output messages in
50 void cm_print_error(const char * const format
, ...);
52 * helper function and macro to compare an ldap error code constant with the
53 * coresponding nt_status code
55 #define NT_STATUS_LDAP_V(code) (0xF2000000 | code)
56 static void _assert_ldap_status_equal(
59 const char * const file
,
62 _assert_int_equal(NT_STATUS_LDAP_V(a
), NT_STATUS_V(b
), file
, line
);
65 #define assert_ldap_status_equal(a, b) \
66 _assert_ldap_status_equal((a), (b), __FILE__, __LINE__)
69 * helper function and macro to assert there were no errors in the last
72 static void _assert_not_ferror(
74 const char * const file
,
77 if (f
== NULL
|| ferror(f
)) {
78 cm_print_error("ferror (%d) %s\n", errno
, strerror(errno
));
83 #define assert_not_ferror(f) \
84 _assert_not_ferror((f), __FILE__, __LINE__)
89 static int setup(void **state
)
91 struct test_ctx
*test_ctx
;
93 test_ctx
= talloc_zero(NULL
, struct test_ctx
);
98 static int teardown(void **state
)
100 struct test_ctx
*test_ctx
= talloc_get_type_abort(*state
,
103 TALLOC_FREE(test_ctx
);
108 * Test that an empty request is handled correctly
110 static void test_empty_input(void **state
)
112 struct test_ctx
*test_ctx
= talloc_get_type_abort(
115 struct asn1_data
*asn1
;
116 struct ldap_message
*ldap_msg
;
120 struct ldap_request_limits limits
= {
121 .max_search_size
= 256000,
125 asn1
= asn1_init(test_ctx
, ASN1_MAX_TREE_DEPTH
);
126 assert_non_null(asn1
);
128 asn1_load_nocopy(asn1
, buf
, len
);
130 ldap_msg
= talloc(test_ctx
, struct ldap_message
);
131 assert_non_null(ldap_msg
);
133 status
= ldap_decode(
134 asn1
, &limits
, samba_ldap_control_handlers(), ldap_msg
);
135 assert_ldap_status_equal(LDAP_PROTOCOL_ERROR
, status
);
139 * Check that a request is rejected it it's recursion depth exceeds
140 * the maximum value specified. This test uses a very deeply nested query,
144 static void test_recursion_depth_large(void **state
)
146 struct test_ctx
*test_ctx
= talloc_get_type_abort(
149 struct asn1_data
*asn1
;
150 struct ldap_message
*ldap_msg
;
153 uint8_t *buffer
= NULL
;
154 const size_t BUFF_SIZE
= 1048576;
156 struct ldap_request_limits limits
= {
157 .max_search_size
= 256000,
162 * Load a test data file containg 10,000 or clauses in encoded as
165 buffer
= talloc_zero_array(test_ctx
, uint8_t, BUFF_SIZE
);
166 f
= fopen("./libcli/ldap/tests/data/10000-or.dat", "r");
167 assert_not_ferror(f
);
168 len
= fread(buffer
, sizeof(uint8_t), BUFF_SIZE
, f
);
169 assert_not_ferror(f
);
170 assert_true(len
> 0);
172 asn1
= asn1_init(test_ctx
, ASN1_MAX_TREE_DEPTH
);
173 assert_non_null(asn1
);
174 asn1_load_nocopy(asn1
, buffer
, len
);
176 ldap_msg
= talloc(test_ctx
, struct ldap_message
);
177 assert_non_null(ldap_msg
);
179 status
= ldap_decode(
180 asn1
, &limits
, samba_ldap_control_handlers(), ldap_msg
);
181 assert_ldap_status_equal(LDAP_PROTOCOL_ERROR
, status
);
185 * Check that a request is not rejected it it's recursion depth equals the
188 static void test_recursion_depth_equals_max(void **state
)
190 struct test_ctx
*test_ctx
= talloc_get_type_abort(
193 struct asn1_data
*asn1
;
194 struct ldap_message
*ldap_msg
;
197 uint8_t *buffer
= NULL
;
198 const size_t BUFF_SIZE
= 1048576;
200 struct ldap_request_limits limits
= {
201 .max_search_size
= 256000,
205 buffer
= talloc_zero_array(test_ctx
, uint8_t, BUFF_SIZE
);
206 f
= fopen("./libcli/ldap/tests/data/ldap-recursive.dat", "r");
207 assert_not_ferror(f
);
208 len
= fread(buffer
, sizeof(uint8_t), BUFF_SIZE
, f
);
209 assert_not_ferror(f
);
210 assert_true(len
> 0);
212 asn1
= asn1_init(test_ctx
, 4);
213 assert_non_null(asn1
);
214 asn1_load_nocopy(asn1
, buffer
, len
);
216 ldap_msg
= talloc(test_ctx
, struct ldap_message
);
217 assert_non_null(ldap_msg
);
219 status
= ldap_decode(
220 asn1
, &limits
, samba_ldap_control_handlers(), ldap_msg
);
221 assert_true(NT_STATUS_IS_OK(status
));
225 * Check that a request is rejected it it's recursion depth is greater than the
228 static void test_recursion_depth_greater_than_max(void **state
)
230 struct test_ctx
*test_ctx
= talloc_get_type_abort(
233 struct asn1_data
*asn1
;
234 struct ldap_message
*ldap_msg
;
237 uint8_t *buffer
= NULL
;
238 const size_t BUFF_SIZE
= 1048576;
240 struct ldap_request_limits limits
= {
241 .max_search_size
= 256000,
245 buffer
= talloc_zero_array(test_ctx
, uint8_t, BUFF_SIZE
);
246 f
= fopen("./libcli/ldap/tests/data/ldap-recursive.dat", "r");
247 assert_not_ferror(f
);
248 len
= fread(buffer
, sizeof(uint8_t), BUFF_SIZE
, f
);
249 assert_not_ferror(f
);
250 assert_true(len
> 0);
252 asn1
= asn1_init(test_ctx
, 3);
253 assert_non_null(asn1
);
254 asn1_load_nocopy(asn1
, buffer
, len
);
256 ldap_msg
= talloc(test_ctx
, struct ldap_message
);
257 assert_non_null(ldap_msg
);
259 status
= ldap_decode(
260 asn1
, &limits
, samba_ldap_control_handlers(), ldap_msg
);
261 assert_ldap_status_equal(LDAP_PROTOCOL_ERROR
, status
);
264 int main(_UNUSED_
int argc
, _UNUSED_
const char **argv
)
266 const struct CMUnitTest tests
[] = {
267 cmocka_unit_test_setup_teardown(
271 cmocka_unit_test_setup_teardown(
272 test_recursion_depth_large
,
275 cmocka_unit_test_setup_teardown(
276 test_recursion_depth_equals_max
,
279 cmocka_unit_test_setup_teardown(
280 test_recursion_depth_greater_than_max
,
285 cmocka_set_message_output(CM_OUTPUT_SUBUNIT
);
286 return cmocka_run_group_tests(tests
, NULL
, NULL
);