Line data Source code
1 : /*
2 : Unix SMB/CIFS Implementation.
3 :
4 : test CLDAP/LDAP netlogon operations
5 :
6 : Copyright (C) Andrew Tridgell 2005
7 : Copyright (C) Matthias Dieter Wallnöfer 2009
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 :
22 : */
23 :
24 : #include "includes.h"
25 : #include "libcli/cldap/cldap.h"
26 : #include "libcli/ldap/ldap_client.h"
27 : #include "libcli/ldap/ldap_ndr.h"
28 : #include "libcli/resolve/resolve.h"
29 : #include "librpc/gen_ndr/netlogon.h"
30 : #include "param/param.h"
31 : #include "../lib/tsocket/tsocket.h"
32 :
33 : #include "torture/torture.h"
34 : #include "torture/ldap/proto.h"
35 :
36 : #undef strcasecmp
37 :
38 : #define CHECK_STATUS(status, correct) torture_assert_ntstatus_equal(tctx, status, correct, "incorrect status")
39 :
40 : #define CHECK_VAL(v, correct) torture_assert_int_equal(tctx, (v), (correct), "incorrect value");
41 :
42 : #define CHECK_STRING(v, correct) torture_assert_str_equal(tctx, v, correct, "incorrect value");
43 :
44 : typedef NTSTATUS (*request_netlogon_t)(void *con,
45 : TALLOC_CTX *mem_ctx,
46 : struct cldap_netlogon *io);
47 :
48 : typedef NTSTATUS (*request_rootdse_t)(void *con,
49 : TALLOC_CTX *mem_ctx,
50 : struct cldap_search *io);
51 :
52 : /*
53 : test netlogon operations
54 : */
55 2 : static bool test_ldap_netlogon(struct torture_context *tctx,
56 : request_netlogon_t request_netlogon,
57 : void *cldap,
58 : const char *dest)
59 : {
60 : NTSTATUS status;
61 : struct cldap_netlogon search, empty_search;
62 : struct netlogon_samlogon_response n1;
63 : struct GUID guid;
64 : int i;
65 :
66 2 : ZERO_STRUCT(search);
67 2 : search.in.dest_address = NULL;
68 2 : search.in.dest_port = 0;
69 2 : search.in.acct_control = -1;
70 2 : search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
71 2 : search.in.map_response = true;
72 :
73 2 : empty_search = search;
74 :
75 2 : printf("Trying without any attributes\n");
76 2 : search = empty_search;
77 2 : status = request_netlogon(cldap, tctx, &search);
78 2 : CHECK_STATUS(status, NT_STATUS_OK);
79 :
80 2 : n1 = search.out.netlogon;
81 :
82 2 : search.in.user = "Administrator";
83 2 : search.in.realm = n1.data.nt5_ex.dns_domain;
84 2 : search.in.host = "__cldap_torture__";
85 :
86 2 : printf("Scanning for netlogon levels\n");
87 514 : for (i=0;i<256;i++) {
88 512 : search.in.version = i;
89 512 : printf("Trying netlogon level %d\n", i);
90 512 : status = request_netlogon(cldap, tctx, &search);
91 512 : CHECK_STATUS(status, NT_STATUS_OK);
92 : }
93 :
94 2 : printf("Scanning for netlogon level bits\n");
95 64 : for (i=0;i<31;i++) {
96 62 : search.in.version = (1<<i);
97 62 : printf("Trying netlogon level 0x%x\n", i);
98 62 : status = request_netlogon(cldap, tctx, &search);
99 62 : CHECK_STATUS(status, NT_STATUS_OK);
100 : }
101 :
102 2 : search.in.version = NETLOGON_NT_VERSION_5|NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_IP;
103 2 : status = request_netlogon(cldap, tctx, &search);
104 2 : CHECK_STATUS(status, NT_STATUS_OK);
105 :
106 2 : printf("Trying with User=NULL\n");
107 2 : search.in.user = NULL;
108 2 : status = request_netlogon(cldap, tctx, &search);
109 2 : CHECK_STATUS(status, NT_STATUS_OK);
110 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
111 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
112 2 : torture_assert(tctx,
113 : strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") == NULL,
114 : "PDC name should not be in UNC form");
115 :
116 2 : printf("Trying with User=Administrator\n");
117 2 : search.in.user = "Administrator";
118 2 : status = request_netlogon(cldap, tctx, &search);
119 2 : CHECK_STATUS(status, NT_STATUS_OK);
120 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
121 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
122 2 : torture_assert(tctx,
123 : strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") == NULL,
124 : "PDC name should not be in UNC form");
125 :
126 2 : search.in.version = NETLOGON_NT_VERSION_5;
127 2 : status = request_netlogon(cldap, tctx, &search);
128 2 : CHECK_STATUS(status, NT_STATUS_OK);
129 :
130 2 : printf("Trying with User=NULL\n");
131 2 : search.in.user = NULL;
132 2 : status = request_netlogon(cldap, tctx, &search);
133 2 : CHECK_STATUS(status, NT_STATUS_OK);
134 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE);
135 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
136 2 : torture_assert(tctx,
137 : strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
138 : "PDC name should be in UNC form");
139 :
140 2 : printf("Trying with User=Administrator\n");
141 2 : search.in.user = "Administrator";
142 2 : status = request_netlogon(cldap, tctx, &search);
143 2 : CHECK_STATUS(status, NT_STATUS_OK);
144 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN);
145 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
146 2 : torture_assert(tctx,
147 : strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") != NULL,
148 : "PDC name should be in UNC form");
149 :
150 2 : search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
151 :
152 2 : printf("Trying with a GUID\n");
153 2 : search.in.realm = NULL;
154 2 : search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid);
155 2 : status = request_netlogon(cldap, tctx, &search);
156 2 : CHECK_STATUS(status, NT_STATUS_OK);
157 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
158 2 : CHECK_STRING(GUID_string(tctx, &search.out.netlogon.data.nt5_ex.domain_uuid), search.in.domain_guid);
159 2 : torture_assert(tctx,
160 : strstr(search.out.netlogon.data.nt5_ex.pdc_name, "\\\\") == NULL,
161 : "PDC name should not be in UNC form");
162 :
163 2 : printf("Trying with a incorrect GUID\n");
164 2 : guid = GUID_random();
165 2 : search.in.user = NULL;
166 2 : search.in.domain_guid = GUID_string(tctx, &guid);
167 2 : status = request_netlogon(cldap, tctx, &search);
168 2 : CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
169 :
170 2 : printf("Trying with a AAC\n");
171 2 : search.in.acct_control = ACB_WSTRUST|ACB_SVRTRUST;
172 2 : search.in.realm = n1.data.nt5_ex.dns_domain;
173 2 : status = request_netlogon(cldap, tctx, &search);
174 2 : CHECK_STATUS(status, NT_STATUS_OK);
175 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
176 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
177 :
178 2 : printf("Trying with a zero AAC\n");
179 2 : search.in.acct_control = 0x0;
180 2 : search.in.realm = n1.data.nt5_ex.dns_domain;
181 2 : status = request_netlogon(cldap, tctx, &search);
182 2 : CHECK_STATUS(status, NT_STATUS_OK);
183 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
184 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
185 :
186 2 : printf("Trying with a zero AAC and user=Administrator\n");
187 2 : search.in.acct_control = 0x0;
188 2 : search.in.user = "Administrator";
189 2 : search.in.realm = n1.data.nt5_ex.dns_domain;
190 2 : status = request_netlogon(cldap, tctx, &search);
191 2 : CHECK_STATUS(status, NT_STATUS_OK);
192 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
193 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "Administrator");
194 :
195 2 : printf("Trying with a bad AAC\n");
196 2 : search.in.user = NULL;
197 2 : search.in.acct_control = 0xFF00FF00;
198 2 : search.in.realm = n1.data.nt5_ex.dns_domain;
199 2 : status = request_netlogon(cldap, tctx, &search);
200 2 : CHECK_STATUS(status, NT_STATUS_OK);
201 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
202 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
203 :
204 2 : printf("Trying with a user only\n");
205 2 : search = empty_search;
206 2 : search.in.user = "Administrator";
207 2 : status = request_netlogon(cldap, tctx, &search);
208 2 : CHECK_STATUS(status, NT_STATUS_OK);
209 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain);
210 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
211 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name);
212 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name);
213 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
214 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site);
215 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site);
216 :
217 2 : printf("Trying with just a bad username\n");
218 2 : search.in.user = "___no_such_user___";
219 2 : status = request_netlogon(cldap, tctx, &search);
220 2 : CHECK_STATUS(status, NT_STATUS_OK);
221 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
222 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain);
223 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
224 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name);
225 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name);
226 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
227 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site);
228 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site);
229 :
230 2 : printf("Trying with just a bad domain\n");
231 2 : search = empty_search;
232 2 : search.in.realm = "___no_such_domain___";
233 2 : status = request_netlogon(cldap, tctx, &search);
234 2 : CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
235 :
236 2 : printf("Trying with a incorrect domain and correct guid\n");
237 2 : search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid);
238 2 : status = request_netlogon(cldap, tctx, &search);
239 2 : CHECK_STATUS(status, NT_STATUS_OK);
240 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
241 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain);
242 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
243 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name);
244 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name);
245 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
246 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site);
247 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site);
248 :
249 2 : printf("Trying with a incorrect domain and incorrect guid\n");
250 2 : search.in.domain_guid = GUID_string(tctx, &guid);
251 2 : status = request_netlogon(cldap, tctx, &search);
252 2 : CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
253 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
254 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain);
255 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
256 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name);
257 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name);
258 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
259 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site);
260 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site);
261 :
262 2 : printf("Trying with a incorrect GUID and correct domain\n");
263 2 : search.in.domain_guid = GUID_string(tctx, &guid);
264 2 : search.in.realm = n1.data.nt5_ex.dns_domain;
265 2 : status = request_netlogon(cldap, tctx, &search);
266 2 : CHECK_STATUS(status, NT_STATUS_OK);
267 2 : CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
268 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain);
269 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
270 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name);
271 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name);
272 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
273 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site);
274 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site);
275 :
276 2 : printf("Proof other results\n");
277 2 : search.in.user = "Administrator";
278 2 : status = request_netlogon(cldap, tctx, &search);
279 2 : CHECK_STATUS(status, NT_STATUS_OK);
280 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.forest, n1.data.nt5_ex.dns_domain);
281 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
282 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.domain_name, n1.data.nt5_ex.domain_name);
283 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.pdc_name, n1.data.nt5_ex.pdc_name);
284 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
285 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.server_site, n1.data.nt5_ex.server_site);
286 2 : CHECK_STRING(search.out.netlogon.data.nt5_ex.client_site, n1.data.nt5_ex.client_site);
287 :
288 2 : return true;
289 : }
290 :
291 : /*
292 : test cldap netlogon server type flags
293 : */
294 2 : static bool test_ldap_netlogon_flags(struct torture_context *tctx,
295 : request_netlogon_t request_netlogon,
296 : void *cldap,
297 : const char *dest)
298 : {
299 : NTSTATUS status;
300 : struct cldap_netlogon search;
301 : struct netlogon_samlogon_response n1;
302 2 : uint32_t server_type = 0;
303 :
304 2 : printf("Printing out netlogon server type flags: %s\n", dest);
305 :
306 2 : ZERO_STRUCT(search);
307 2 : search.in.dest_address = NULL;
308 2 : search.in.dest_port = 0;
309 2 : search.in.acct_control = -1;
310 2 : search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
311 2 : search.in.map_response = true;
312 :
313 2 : status = request_netlogon(cldap, tctx, &search);
314 2 : CHECK_STATUS(status, NT_STATUS_OK);
315 :
316 2 : n1 = search.out.netlogon;
317 2 : if (n1.ntver == NETLOGON_NT_VERSION_5)
318 0 : server_type = n1.data.nt5.server_type;
319 2 : else if (n1.ntver == NETLOGON_NT_VERSION_5EX)
320 2 : server_type = n1.data.nt5_ex.server_type;
321 :
322 2 : printf("The word is: %i\n", server_type);
323 2 : if (server_type & NBT_SERVER_PDC)
324 2 : printf("NBT_SERVER_PDC ");
325 2 : if (server_type & NBT_SERVER_GC)
326 2 : printf("NBT_SERVER_GC ");
327 2 : if (server_type & NBT_SERVER_LDAP)
328 2 : printf("NBT_SERVER_LDAP ");
329 2 : if (server_type & NBT_SERVER_DS)
330 2 : printf("NBT_SERVER_DS ");
331 2 : if (server_type & NBT_SERVER_KDC)
332 2 : printf("NBT_SERVER_KDC ");
333 2 : if (server_type & NBT_SERVER_TIMESERV)
334 2 : printf("NBT_SERVER_TIMESERV ");
335 2 : if (server_type & NBT_SERVER_CLOSEST)
336 2 : printf("NBT_SERVER_CLOSEST ");
337 2 : if (server_type & NBT_SERVER_WRITABLE)
338 2 : printf("NBT_SERVER_WRITABLE ");
339 2 : if (server_type & NBT_SERVER_GOOD_TIMESERV)
340 2 : printf("NBT_SERVER_GOOD_TIMESERV ");
341 2 : if (server_type & NBT_SERVER_NDNC)
342 0 : printf("NBT_SERVER_NDNC ");
343 2 : if (server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6)
344 0 : printf("NBT_SERVER_SELECT_SECRET_DOMAIN_6");
345 2 : if (server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6)
346 2 : printf("NBT_SERVER_FULL_SECRET_DOMAIN_6");
347 2 : if (server_type & NBT_SERVER_ADS_WEB_SERVICE)
348 0 : printf("NBT_SERVER_ADS_WEB_SERVICE ");
349 2 : if (server_type & NBT_SERVER_DS_8)
350 0 : printf("NBT_SERVER_DS_8 ");
351 2 : if (server_type & DS_DNS_CONTROLLER)
352 0 : printf("DS_DNS_CONTROLLER ");
353 2 : if (server_type & DS_DNS_DOMAIN)
354 0 : printf("DS_DNS_DOMAIN ");
355 2 : if (server_type & DS_DNS_FOREST_ROOT)
356 0 : printf("DS_DNS_FOREST_ROOT ");
357 :
358 2 : printf("\n");
359 :
360 2 : return true;
361 : }
362 :
363 311 : static NTSTATUS tcp_ldap_rootdse(void *data,
364 : TALLOC_CTX *mem_ctx,
365 : struct cldap_search *io)
366 : {
367 311 : struct ldap_connection *conn = talloc_get_type(data,
368 : struct ldap_connection);
369 : struct ldap_message *msg, *result;
370 : struct ldap_request *req;
371 : int i;
372 : NTSTATUS status;
373 :
374 311 : msg = new_ldap_message(mem_ctx);
375 311 : if (!msg) {
376 0 : return NT_STATUS_NO_MEMORY;
377 : }
378 :
379 311 : msg->type = LDAP_TAG_SearchRequest;
380 311 : msg->r.SearchRequest.basedn = "";
381 311 : msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
382 311 : msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
383 311 : msg->r.SearchRequest.timelimit = 0;
384 311 : msg->r.SearchRequest.sizelimit = 0;
385 311 : msg->r.SearchRequest.attributesonly = false;
386 311 : msg->r.SearchRequest.tree = ldb_parse_tree(msg, io->in.filter);
387 311 : msg->r.SearchRequest.num_attributes = str_list_length(io->in.attributes);
388 311 : msg->r.SearchRequest.attributes = io->in.attributes;
389 :
390 311 : req = ldap_request_send(conn, msg);
391 311 : if (req == NULL) {
392 0 : printf("Could not setup ldap search\n");
393 0 : return NT_STATUS_UNSUCCESSFUL;
394 : }
395 :
396 311 : ZERO_STRUCT(io->out);
397 618 : for (i = 0; i < 2; ++i) {
398 618 : status = ldap_result_n(req, i, &result);
399 618 : if (!NT_STATUS_IS_OK(status)) {
400 0 : return status;
401 : }
402 618 : switch (result->type) {
403 307 : case LDAP_TAG_SearchResultEntry:
404 307 : if (i != 0) {
405 0 : return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
406 : }
407 307 : io->out.response = &result->r.SearchResultEntry;
408 307 : break;
409 311 : case LDAP_TAG_SearchResultDone:
410 311 : io->out.result = &result->r.SearchResultDone;
411 311 : if (io->out.result->resultcode != LDAP_SUCCESS) {
412 0 : return NT_STATUS_LDAP(io->out.result->resultcode);
413 : }
414 :
415 311 : return NT_STATUS_OK;
416 0 : default:
417 0 : return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
418 : }
419 : }
420 :
421 0 : return NT_STATUS_OK;
422 : }
423 :
424 308 : static NTSTATUS tcp_ldap_netlogon(void *conn,
425 : TALLOC_CTX *mem_ctx,
426 : struct cldap_netlogon *io)
427 : {
428 : struct cldap_search search;
429 : struct ldap_SearchResEntry *res;
430 : NTSTATUS status;
431 : DATA_BLOB *blob;
432 :
433 308 : ZERO_STRUCT(search);
434 308 : search.in.attributes = (const char *[]) { "netlogon", NULL };
435 308 : search.in.filter = cldap_netlogon_create_filter(mem_ctx, io);
436 308 : if (search.in.filter == NULL) {
437 0 : return NT_STATUS_NO_MEMORY;
438 : }
439 :
440 308 : status = tcp_ldap_rootdse(conn, mem_ctx, &search);
441 308 : if (!NT_STATUS_IS_OK(status)) {
442 0 : return status;
443 : }
444 :
445 308 : res = search.out.response;
446 308 : if (res == NULL) {
447 3 : return NT_STATUS_NOT_FOUND;
448 : }
449 :
450 610 : if (res->num_attributes != 1 ||
451 610 : strcasecmp(res->attributes[0].name, "netlogon") != 0 ||
452 610 : res->attributes[0].num_values != 1 ||
453 305 : res->attributes[0].values->length < 2) {
454 0 : return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
455 : }
456 :
457 305 : blob = res->attributes[0].values;
458 305 : status = pull_netlogon_samlogon_response(blob, mem_ctx,
459 : &io->out.netlogon);
460 305 : if (!NT_STATUS_IS_OK(status)) {
461 0 : return status;
462 : }
463 :
464 305 : if (io->in.map_response) {
465 305 : map_netlogon_samlogon_response(&io->out.netlogon);
466 : }
467 :
468 305 : return NT_STATUS_OK;
469 : }
470 :
471 4 : static NTSTATUS udp_ldap_rootdse(void *data, TALLOC_CTX *mem_ctx,
472 : struct cldap_search *io)
473 : {
474 4 : struct cldap_socket *cldap = talloc_get_type(data,
475 : struct cldap_socket);
476 :
477 4 : return cldap_search(cldap, mem_ctx, io);
478 : }
479 :
480 2 : static bool test_netlogon_extra_attrs(struct torture_context *tctx,
481 : request_rootdse_t request_rootdse,
482 : void *conn)
483 : {
484 : struct cldap_search io;
485 : NTSTATUS status;
486 2 : const char *attrs[] = {
487 : "netlogon",
488 : "supportedCapabilities",
489 : NULL
490 : };
491 2 : const char *attrs2[] = { "netlogon", "*", NULL };
492 2 : struct ldb_message ldbmsg = { NULL, 0, NULL };
493 :
494 2 : ZERO_STRUCT(io);
495 2 : io.in.dest_address = NULL;
496 2 : io.in.dest_port = 0;
497 2 : io.in.timeout = 2;
498 2 : io.in.retries = 2;
499 : /* Additional attributes may be requested next to netlogon */
500 2 : torture_comment(tctx, "Requesting netlogon with additional attribute\n");
501 2 : io.in.filter =
502 2 : talloc_asprintf(tctx, "(&"
503 : "(NtVer=%s)(AAC=%s)"
504 : /* Query for LDAP_CAP_ACTIVE_DIRECTORY_OID */
505 : "(supportedCapabilities=1.2.840.113556.1.4.800)"
506 : ")",
507 : ldap_encode_ndr_uint32(tctx,
508 : NETLOGON_NT_VERSION_5EX),
509 : ldap_encode_ndr_uint32(tctx, 0));
510 2 : torture_assert(tctx, io.in.filter != NULL, "OOM");
511 2 : io.in.attributes = attrs;
512 2 : status = request_rootdse(conn, tctx, &io);
513 2 : CHECK_STATUS(status, NT_STATUS_OK);
514 2 : torture_assert(tctx, io.out.response != NULL, "No Entries found.");
515 2 : CHECK_VAL(io.out.response->num_attributes, 2);
516 :
517 : /* netlogon + '*' attr return zero results */
518 2 : torture_comment(tctx, "Requesting netlogon and '*' attributes\n");
519 2 : io.in.attributes = attrs2;
520 2 : status = request_rootdse(conn, tctx, &io);
521 2 : CHECK_STATUS(status, NT_STATUS_OK);
522 2 : torture_assert(tctx, io.out.response != NULL, "No Entries found.");
523 2 : ldbmsg.num_elements = io.out.response->num_attributes;
524 2 : ldbmsg.elements = io.out.response->attributes;
525 2 : torture_assert(tctx, ldb_msg_find_element(&ldbmsg, "netlogon") != NULL,
526 : "Attribute netlogon not found in Result Entry\n");
527 :
528 : /* Wildcards are not allowed in filters when netlogon is requested. */
529 2 : torture_comment(tctx, "Requesting netlogon with invalid attr filter\n");
530 2 : io.in.filter =
531 2 : talloc_asprintf(tctx,
532 : "(&(NtVer=%s)(AAC=%s)(supportedCapabilities=*))",
533 : ldap_encode_ndr_uint32(tctx,
534 : NETLOGON_NT_VERSION_5EX),
535 : ldap_encode_ndr_uint32(tctx, 0));
536 2 : torture_assert(tctx, io.in.filter != NULL, "OOM");
537 2 : io.in.attributes = attrs;
538 2 : status = request_rootdse(conn, tctx, &io);
539 2 : CHECK_STATUS(status, NT_STATUS_OK);
540 2 : torture_assert(tctx, io.out.response == NULL,
541 : "A wildcard filter should return no entries.");
542 :
543 2 : return true;
544 : }
545 :
546 : /*
547 : Bug #11392: Huawei Unified Storage System S5500 V3 sends no NtVer
548 : [MS-ADTS] Section 7.3.3.2 "Domain Controller Response to an LDAP Ping"
549 : */
550 1 : static bool test_netlogon_huawei(struct torture_context *tctx,
551 : request_rootdse_t request_rootdse,
552 : void *conn)
553 : {
554 : struct cldap_search io;
555 : struct netlogon_samlogon_response n1;
556 : NTSTATUS status;
557 1 : const char *attrs[] = {
558 : "netlogon",
559 : NULL
560 : };
561 1 : struct ldb_message ldbmsg = { NULL, 0, NULL };
562 :
563 1 : ZERO_STRUCT(io);
564 1 : io.in.dest_address = NULL;
565 1 : io.in.dest_port = 0;
566 1 : io.in.timeout = 2;
567 1 : io.in.retries = 2;
568 :
569 1 : torture_comment(tctx, "Requesting netlogon without NtVer filter\n");
570 1 : io.in.filter = talloc_asprintf(tctx, "(&(DnsDomain=%s))",
571 : lpcfg_dnsdomain(tctx->lp_ctx));
572 1 : torture_assert(tctx, io.in.filter != NULL, "OOM");
573 1 : io.in.attributes = attrs;
574 1 : status = request_rootdse(conn, tctx, &io);
575 1 : CHECK_STATUS(status, NT_STATUS_OK);
576 1 : torture_assert(tctx, io.out.response != NULL, "No Entries found.");
577 1 : CHECK_VAL(io.out.response->num_attributes, 1);
578 :
579 1 : ldbmsg.num_elements = io.out.response->num_attributes;
580 1 : ldbmsg.elements = io.out.response->attributes;
581 1 : torture_assert(tctx, ldb_msg_find_element(&ldbmsg, "netlogon") != NULL,
582 : "Attribute netlogon not found in Result Entry\n");
583 :
584 1 : status = pull_netlogon_samlogon_response(
585 1 : io.out.response->attributes[0].values,
586 : tctx,
587 : &n1);
588 1 : CHECK_STATUS(status, NT_STATUS_OK);
589 1 : CHECK_VAL(n1.ntver, NETLOGON_NT_VERSION_5);
590 :
591 1 : return true;
592 : }
593 :
594 1 : bool torture_netlogon_tcp(struct torture_context *tctx)
595 : {
596 1 : const char *host = torture_setting_string(tctx, "host", NULL);
597 1 : bool ret = true;
598 : NTSTATUS status;
599 : struct ldap_connection *conn;
600 : TALLOC_CTX *mem_ctx;
601 : const char *url;
602 :
603 1 : mem_ctx = talloc_init("torture_ldap_netlogon");
604 :
605 1 : url = talloc_asprintf(mem_ctx, "ldap://%s/", host);
606 :
607 1 : status = torture_ldap_connection(tctx, &conn, url);
608 1 : if (!NT_STATUS_IS_OK(status)) {
609 0 : return false;
610 : }
611 :
612 1 : ret &= test_ldap_netlogon(tctx, tcp_ldap_netlogon, conn, host);
613 1 : ret &= test_ldap_netlogon_flags(tctx, tcp_ldap_netlogon, conn, host);
614 1 : ret &= test_netlogon_extra_attrs(tctx, tcp_ldap_rootdse, conn);
615 :
616 1 : return ret;
617 : }
618 :
619 308 : static NTSTATUS udp_ldap_netlogon(void *data,
620 : TALLOC_CTX *mem_ctx,
621 : struct cldap_netlogon *io)
622 : {
623 308 : struct cldap_socket *cldap = talloc_get_type(data,
624 : struct cldap_socket);
625 :
626 308 : return cldap_netlogon(cldap, mem_ctx, io);
627 : }
628 :
629 1 : bool torture_netlogon_udp(struct torture_context *tctx)
630 : {
631 1 : const char *host = torture_setting_string(tctx, "host", NULL);
632 : const char *ip;
633 : struct nbt_name nbt_name;
634 1 : bool ret = true;
635 : int r;
636 : struct cldap_socket *cldap;
637 : NTSTATUS status;
638 : struct tsocket_address *dest_addr;
639 :
640 1 : make_nbt_name_server(&nbt_name, host);
641 :
642 1 : status = resolve_name_ex(lpcfg_resolve_context(tctx->lp_ctx),
643 : 0, 0, &nbt_name, tctx, &ip, tctx->ev);
644 1 : torture_assert_ntstatus_ok(tctx, status,
645 : talloc_asprintf(tctx,"Failed to resolve %s: %s",
646 : nbt_name.name, nt_errstr(status)));
647 :
648 1 : r = tsocket_address_inet_from_strings(tctx, "ip",
649 : ip,
650 : lpcfg_cldap_port(tctx->lp_ctx),
651 : &dest_addr);
652 1 : CHECK_VAL(r, 0);
653 :
654 : /* cldap_socket_init should now know about the dest. address */
655 1 : status = cldap_socket_init(tctx, NULL, dest_addr, &cldap);
656 1 : CHECK_STATUS(status, NT_STATUS_OK);
657 :
658 1 : ret &= test_ldap_netlogon(tctx, udp_ldap_netlogon, cldap, host);
659 1 : ret &= test_ldap_netlogon_flags(tctx, udp_ldap_netlogon, cldap, host);
660 1 : ret &= test_netlogon_extra_attrs(tctx, udp_ldap_rootdse, cldap);
661 1 : ret &= test_netlogon_huawei(tctx, udp_ldap_rootdse, cldap);
662 :
663 1 : return ret;
664 : }
|