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 0 : NTSTATUS status;
61 0 : struct cldap_netlogon search, empty_search;
62 0 : struct netlogon_samlogon_response n1;
63 0 : struct GUID guid;
64 0 : 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 0 : NTSTATUS status;
300 0 : struct cldap_netlogon search;
301 0 : 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 2 : printf("NBT_SERVER_DS_8 ");
351 2 : if (server_type & NBT_SERVER_DS_9)
352 2 : printf("NBT_SERVER_DS_9 ");
353 2 : if (server_type & NBT_SERVER_DS_10)
354 2 : printf("NBT_SERVER_DS_10 ");
355 2 : if (server_type & NBT_SERVER_HAS_DNS_NAME)
356 0 : printf("NBT_SERVER_HAS_DNS_NAME ");
357 2 : if (server_type & NBT_SERVER_IS_DEFAULT_NC)
358 0 : printf("NBT_SERVER_IS_DEFAULT_NC ");
359 2 : if (server_type & NBT_SERVER_FOREST_ROOT)
360 0 : printf("NBT_SERVER_FOREST_ROOT ");
361 :
362 2 : printf("\n");
363 :
364 2 : return true;
365 : }
366 :
367 311 : static NTSTATUS tcp_ldap_rootdse(void *data,
368 : TALLOC_CTX *mem_ctx,
369 : struct cldap_search *io)
370 : {
371 311 : struct ldap_connection *conn = talloc_get_type(data,
372 : struct ldap_connection);
373 0 : struct ldap_message *msg, *result;
374 0 : struct ldap_request *req;
375 0 : int i;
376 0 : NTSTATUS status;
377 :
378 311 : msg = new_ldap_message(mem_ctx);
379 311 : if (!msg) {
380 0 : return NT_STATUS_NO_MEMORY;
381 : }
382 :
383 311 : msg->type = LDAP_TAG_SearchRequest;
384 311 : msg->r.SearchRequest.basedn = "";
385 311 : msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
386 311 : msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
387 311 : msg->r.SearchRequest.timelimit = 0;
388 311 : msg->r.SearchRequest.sizelimit = 0;
389 311 : msg->r.SearchRequest.attributesonly = false;
390 311 : msg->r.SearchRequest.tree = ldb_parse_tree(msg, io->in.filter);
391 311 : msg->r.SearchRequest.num_attributes = str_list_length(io->in.attributes);
392 311 : msg->r.SearchRequest.attributes = io->in.attributes;
393 :
394 311 : req = ldap_request_send(conn, msg);
395 311 : if (req == NULL) {
396 0 : printf("Could not setup ldap search\n");
397 0 : return NT_STATUS_UNSUCCESSFUL;
398 : }
399 :
400 311 : ZERO_STRUCT(io->out);
401 618 : for (i = 0; i < 2; ++i) {
402 618 : status = ldap_result_n(req, i, &result);
403 618 : if (!NT_STATUS_IS_OK(status)) {
404 0 : return status;
405 : }
406 618 : switch (result->type) {
407 307 : case LDAP_TAG_SearchResultEntry:
408 307 : if (i != 0) {
409 0 : return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
410 : }
411 307 : io->out.response = &result->r.SearchResultEntry;
412 307 : break;
413 311 : case LDAP_TAG_SearchResultDone:
414 311 : io->out.result = &result->r.SearchResultDone;
415 311 : if (io->out.result->resultcode != LDAP_SUCCESS) {
416 0 : return NT_STATUS_LDAP(io->out.result->resultcode);
417 : }
418 :
419 311 : return NT_STATUS_OK;
420 0 : default:
421 0 : return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
422 : }
423 : }
424 :
425 0 : return NT_STATUS_OK;
426 : }
427 :
428 308 : static NTSTATUS tcp_ldap_netlogon(void *conn,
429 : TALLOC_CTX *mem_ctx,
430 : struct cldap_netlogon *io)
431 : {
432 0 : struct cldap_search search;
433 0 : struct ldap_SearchResEntry *res;
434 0 : NTSTATUS status;
435 0 : DATA_BLOB *blob;
436 :
437 308 : ZERO_STRUCT(search);
438 308 : search.in.attributes = (const char *[]) { "netlogon", NULL };
439 308 : search.in.filter = cldap_netlogon_create_filter(mem_ctx, io);
440 308 : if (search.in.filter == NULL) {
441 0 : return NT_STATUS_NO_MEMORY;
442 : }
443 :
444 308 : status = tcp_ldap_rootdse(conn, mem_ctx, &search);
445 308 : if (!NT_STATUS_IS_OK(status)) {
446 0 : return status;
447 : }
448 :
449 308 : res = search.out.response;
450 308 : if (res == NULL) {
451 3 : return NT_STATUS_NOT_FOUND;
452 : }
453 :
454 305 : if (res->num_attributes != 1 ||
455 305 : strcasecmp(res->attributes[0].name, "netlogon") != 0 ||
456 305 : res->attributes[0].num_values != 1 ||
457 305 : res->attributes[0].values->length < 2) {
458 0 : return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
459 : }
460 :
461 305 : blob = res->attributes[0].values;
462 305 : status = pull_netlogon_samlogon_response(blob, mem_ctx,
463 : &io->out.netlogon);
464 305 : if (!NT_STATUS_IS_OK(status)) {
465 0 : return status;
466 : }
467 :
468 305 : if (io->in.map_response) {
469 305 : map_netlogon_samlogon_response(&io->out.netlogon);
470 : }
471 :
472 305 : return NT_STATUS_OK;
473 : }
474 :
475 4 : static NTSTATUS udp_ldap_rootdse(void *data, TALLOC_CTX *mem_ctx,
476 : struct cldap_search *io)
477 : {
478 4 : struct cldap_socket *cldap = talloc_get_type(data,
479 : struct cldap_socket);
480 :
481 4 : return cldap_search(cldap, mem_ctx, io);
482 : }
483 :
484 2 : static bool test_netlogon_extra_attrs(struct torture_context *tctx,
485 : request_rootdse_t request_rootdse,
486 : void *conn)
487 : {
488 0 : struct cldap_search io;
489 0 : NTSTATUS status;
490 2 : const char *attrs[] = {
491 : "netlogon",
492 : "supportedCapabilities",
493 : NULL
494 : };
495 2 : const char *attrs2[] = { "netlogon", "*", NULL };
496 2 : struct ldb_message ldbmsg = { NULL, 0, NULL };
497 :
498 2 : ZERO_STRUCT(io);
499 2 : io.in.dest_address = NULL;
500 2 : io.in.dest_port = 0;
501 2 : io.in.timeout = 2;
502 2 : io.in.retries = 2;
503 : /* Additional attributes may be requested next to netlogon */
504 2 : torture_comment(tctx, "Requesting netlogon with additional attribute\n");
505 2 : io.in.filter =
506 2 : talloc_asprintf(tctx, "(&"
507 : "(NtVer=%s)(AAC=%s)"
508 : /* Query for LDAP_CAP_ACTIVE_DIRECTORY_OID */
509 : "(supportedCapabilities=1.2.840.113556.1.4.800)"
510 : ")",
511 : ldap_encode_ndr_uint32(tctx,
512 : NETLOGON_NT_VERSION_5EX),
513 : ldap_encode_ndr_uint32(tctx, 0));
514 2 : torture_assert(tctx, io.in.filter != NULL, "OOM");
515 2 : io.in.attributes = attrs;
516 2 : status = request_rootdse(conn, tctx, &io);
517 2 : CHECK_STATUS(status, NT_STATUS_OK);
518 2 : torture_assert(tctx, io.out.response != NULL, "No Entries found.");
519 2 : CHECK_VAL(io.out.response->num_attributes, 2);
520 :
521 : /* netlogon + '*' attr return zero results */
522 2 : torture_comment(tctx, "Requesting netlogon and '*' attributes\n");
523 2 : io.in.attributes = attrs2;
524 2 : status = request_rootdse(conn, tctx, &io);
525 2 : CHECK_STATUS(status, NT_STATUS_OK);
526 2 : torture_assert(tctx, io.out.response != NULL, "No Entries found.");
527 2 : ldbmsg.num_elements = io.out.response->num_attributes;
528 2 : ldbmsg.elements = io.out.response->attributes;
529 2 : torture_assert(tctx, ldb_msg_find_element(&ldbmsg, "netlogon") != NULL,
530 : "Attribute netlogon not found in Result Entry\n");
531 :
532 : /* Wildcards are not allowed in filters when netlogon is requested. */
533 2 : torture_comment(tctx, "Requesting netlogon with invalid attr filter\n");
534 2 : io.in.filter =
535 2 : talloc_asprintf(tctx,
536 : "(&(NtVer=%s)(AAC=%s)(supportedCapabilities=*))",
537 : ldap_encode_ndr_uint32(tctx,
538 : NETLOGON_NT_VERSION_5EX),
539 : ldap_encode_ndr_uint32(tctx, 0));
540 2 : torture_assert(tctx, io.in.filter != NULL, "OOM");
541 2 : io.in.attributes = attrs;
542 2 : status = request_rootdse(conn, tctx, &io);
543 2 : CHECK_STATUS(status, NT_STATUS_OK);
544 2 : torture_assert(tctx, io.out.response == NULL,
545 : "A wildcard filter should return no entries.");
546 :
547 2 : return true;
548 : }
549 :
550 : /*
551 : Bug #11392: Huawei Unified Storage System S5500 V3 sends no NtVer
552 : [MS-ADTS] Section 7.3.3.2 "Domain Controller Response to an LDAP Ping"
553 : */
554 1 : static bool test_netlogon_huawei(struct torture_context *tctx,
555 : request_rootdse_t request_rootdse,
556 : void *conn)
557 : {
558 0 : struct cldap_search io;
559 0 : struct netlogon_samlogon_response n1;
560 0 : NTSTATUS status;
561 1 : const char *attrs[] = {
562 : "netlogon",
563 : NULL
564 : };
565 1 : struct ldb_message ldbmsg = { NULL, 0, NULL };
566 :
567 1 : ZERO_STRUCT(io);
568 1 : io.in.dest_address = NULL;
569 1 : io.in.dest_port = 0;
570 1 : io.in.timeout = 2;
571 1 : io.in.retries = 2;
572 :
573 1 : torture_comment(tctx, "Requesting netlogon without NtVer filter\n");
574 1 : io.in.filter = talloc_asprintf(tctx, "(&(DnsDomain=%s))",
575 : lpcfg_dnsdomain(tctx->lp_ctx));
576 1 : torture_assert(tctx, io.in.filter != NULL, "OOM");
577 1 : io.in.attributes = attrs;
578 1 : status = request_rootdse(conn, tctx, &io);
579 1 : CHECK_STATUS(status, NT_STATUS_OK);
580 1 : torture_assert(tctx, io.out.response != NULL, "No Entries found.");
581 1 : CHECK_VAL(io.out.response->num_attributes, 1);
582 :
583 1 : ldbmsg.num_elements = io.out.response->num_attributes;
584 1 : ldbmsg.elements = io.out.response->attributes;
585 1 : torture_assert(tctx, ldb_msg_find_element(&ldbmsg, "netlogon") != NULL,
586 : "Attribute netlogon not found in Result Entry\n");
587 :
588 1 : status = pull_netlogon_samlogon_response(
589 1 : io.out.response->attributes[0].values,
590 : tctx,
591 : &n1);
592 1 : CHECK_STATUS(status, NT_STATUS_OK);
593 1 : CHECK_VAL(n1.ntver, NETLOGON_NT_VERSION_5);
594 :
595 1 : return true;
596 : }
597 :
598 1 : bool torture_netlogon_tcp(struct torture_context *tctx)
599 : {
600 1 : const char *host = torture_setting_string(tctx, "host", NULL);
601 1 : bool ret = true;
602 0 : NTSTATUS status;
603 0 : struct ldap_connection *conn;
604 0 : TALLOC_CTX *mem_ctx;
605 0 : const char *url;
606 :
607 1 : mem_ctx = talloc_init("torture_ldap_netlogon");
608 :
609 1 : url = talloc_asprintf(mem_ctx, "ldap://%s/", host);
610 :
611 1 : status = torture_ldap_connection(tctx, &conn, url);
612 1 : if (!NT_STATUS_IS_OK(status)) {
613 0 : return false;
614 : }
615 :
616 1 : ret &= test_ldap_netlogon(tctx, tcp_ldap_netlogon, conn, host);
617 1 : ret &= test_ldap_netlogon_flags(tctx, tcp_ldap_netlogon, conn, host);
618 1 : ret &= test_netlogon_extra_attrs(tctx, tcp_ldap_rootdse, conn);
619 :
620 1 : return ret;
621 : }
622 :
623 308 : static NTSTATUS udp_ldap_netlogon(void *data,
624 : TALLOC_CTX *mem_ctx,
625 : struct cldap_netlogon *io)
626 : {
627 308 : struct cldap_socket *cldap = talloc_get_type(data,
628 : struct cldap_socket);
629 :
630 308 : return cldap_netlogon(cldap, mem_ctx, io);
631 : }
632 :
633 1 : bool torture_netlogon_udp(struct torture_context *tctx)
634 : {
635 1 : const char *host = torture_setting_string(tctx, "host", NULL);
636 0 : const char *ip;
637 0 : struct nbt_name nbt_name;
638 1 : bool ret = true;
639 0 : int r;
640 0 : struct cldap_socket *cldap;
641 0 : NTSTATUS status;
642 0 : struct tsocket_address *dest_addr;
643 :
644 1 : make_nbt_name_server(&nbt_name, host);
645 :
646 1 : status = resolve_name_ex(lpcfg_resolve_context(tctx->lp_ctx),
647 : 0, 0, &nbt_name, tctx, &ip, tctx->ev);
648 1 : torture_assert_ntstatus_ok(tctx, status,
649 : talloc_asprintf(tctx,"Failed to resolve %s: %s",
650 : nbt_name.name, nt_errstr(status)));
651 :
652 1 : r = tsocket_address_inet_from_strings(tctx, "ip",
653 : ip,
654 : lpcfg_cldap_port(tctx->lp_ctx),
655 : &dest_addr);
656 1 : CHECK_VAL(r, 0);
657 :
658 : /* cldap_socket_init should now know about the dest. address */
659 1 : status = cldap_socket_init(tctx, NULL, dest_addr, &cldap);
660 1 : CHECK_STATUS(status, NT_STATUS_OK);
661 :
662 1 : ret &= test_ldap_netlogon(tctx, udp_ldap_netlogon, cldap, host);
663 1 : ret &= test_ldap_netlogon_flags(tctx, udp_ldap_netlogon, cldap, host);
664 1 : ret &= test_netlogon_extra_attrs(tctx, udp_ldap_rootdse, cldap);
665 1 : ret &= test_netlogon_huawei(tctx, udp_ldap_rootdse, cldap);
666 :
667 1 : return ret;
668 : }
|