5b2e92cf36a178e5b19fb0e4bc5d37e857375b02
[ira/wip.git] / source4 / torture / rpc / drsuapi.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    DRSUapi tests
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Stefan (metze) Metzmacher 2004
8    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2006
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "librpc/gen_ndr/ndr_drsuapi_c.h"
27 #include "torture/rpc/rpc.h"
28
29 #define TEST_MACHINE_NAME "torturetest"
30
31 BOOL test_DsBind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
32                  struct DsPrivate *priv)
33 {
34         NTSTATUS status;
35         struct drsuapi_DsBind r;
36         BOOL ret = True;
37
38         GUID_from_string(DRSUAPI_DS_BIND_GUID, &priv->bind_guid);
39
40         r.in.bind_guid = &priv->bind_guid;
41         r.in.bind_info = NULL;
42         r.out.bind_handle = &priv->bind_handle;
43
44         printf("testing DsBind\n");
45
46         status = dcerpc_drsuapi_DsBind(p, mem_ctx, &r);
47         if (!NT_STATUS_IS_OK(status)) {
48                 const char *errstr = nt_errstr(status);
49                 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
50                         errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
51                 }
52                 printf("dcerpc_drsuapi_DsBind failed - %s\n", errstr);
53                 ret = False;
54         } else if (!W_ERROR_IS_OK(r.out.result)) {
55                 printf("DsBind failed - %s\n", win_errstr(r.out.result));
56                 ret = False;
57         }
58
59         return ret;
60 }
61
62 static BOOL test_DsGetDomainControllerInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
63                       struct DsPrivate *priv)
64 {
65         NTSTATUS status;
66         struct drsuapi_DsGetDomainControllerInfo r;
67         BOOL ret = True;
68         BOOL found = False;
69         int i, j, k;
70         
71         struct {
72                 const char *name;
73                 WERROR expected;
74         } names[] = { 
75                 {       
76                         .name = torture_join_dom_netbios_name(priv->join),
77                         .expected = WERR_OK
78                 },
79                 {
80                         .name = torture_join_dom_dns_name(priv->join),
81                         .expected = WERR_OK
82                 },
83                 {
84                         .name = "__UNKNOWN_DOMAIN__",
85                         .expected = WERR_DS_OBJ_NOT_FOUND
86                 },
87                 {
88                         .name = "unknown.domain.samba.example.com",
89                         .expected = WERR_DS_OBJ_NOT_FOUND
90                 },
91         };
92         int levels[] = {1, 2};
93         int level;
94
95         for (i=0; i < ARRAY_SIZE(levels); i++) {
96                 for (j=0; j < ARRAY_SIZE(names); j++) {
97                         level = levels[i];
98                         r.in.bind_handle = &priv->bind_handle;
99                         r.in.level = 1;
100                         
101                         r.in.req.req1.domain_name = names[j].name;
102                         r.in.req.req1.level = level;
103                         
104                         printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
105                                r.in.req.req1.level, r.in.req.req1.domain_name);
106                 
107                         status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
108                         if (!NT_STATUS_IS_OK(status)) {
109                                 const char *errstr = nt_errstr(status);
110                                 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
111                                         errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
112                                 }
113                                 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
114                                        "    with dns domain failed - %s\n",
115                                        r.in.req.req1.level, errstr);
116                                 ret = False;
117                         } else if (!W_ERROR_EQUAL(r.out.result, names[j].expected)) {
118                                 printf("DsGetDomainControllerInfo level %d\n"
119                                        "    with dns domain failed - %s, expected %s\n",
120                                        r.in.req.req1.level, win_errstr(r.out.result),
121                                        win_errstr(names[j].expected));
122                                 ret = False;
123                         }
124                 
125                         if (!W_ERROR_IS_OK(r.out.result)) {
126                                 /* If this was an error, we can't read the result structure */
127                                 continue;
128                         }
129
130                         if (r.in.req.req1.level != r.out.level_out) {
131                                 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level in (%d) != out (%d)\n",
132                                        r.in.req.req1.level, r.out.level_out);
133                                 ret = False;
134                                 /* We can't safely read the result structure */
135                                 continue;
136                         }
137                         switch (level) {
138                         case 1:
139                                 for (k=0; k < r.out.ctr.ctr1.count; k++) {
140                                         if (strcasecmp_m(r.out.ctr.ctr1.array[k].netbios_name, 
141                                                          torture_join_netbios_name(priv->join)) == 0) {
142                                                 found = True;
143                                                 break;
144                                         }
145                                 }
146                                 break;
147                         case 2:
148                                 for (k=0; k < r.out.ctr.ctr2.count; k++) {
149                                         if (strcasecmp_m(r.out.ctr.ctr2.array[k].netbios_name, 
150                                                          torture_join_netbios_name(priv->join)) == 0) {
151                                                 found = True;
152                                                 priv->dcinfo    = r.out.ctr.ctr2.array[k];
153                                                 break;
154                                         }
155                                 }
156                                 break;
157                         }
158                         if (!found) {
159                                 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d: Failed to find the domain controller (%s) we just created during the join\n",
160                                        r.in.req.req1.level,
161                                        torture_join_netbios_name(priv->join));
162                                 ret = False;
163                         }
164                 }
165         }
166
167         if (lp_parm_bool(-1, "torture", "samba4", False)) {
168                 printf("skipping DsGetDomainControllerInfo level -1 test against Samba4\n");
169                 return ret;
170         }
171
172         r.in.bind_handle = &priv->bind_handle;
173         r.in.level = 1;
174         
175         r.in.req.req1.domain_name = "__UNKNOWN_DOMAIN__"; /* This is clearly ignored for this level */
176         r.in.req.req1.level = -1;
177         
178         printf("testing DsGetDomainControllerInfo level %d on domainname '%s'\n",
179                r.in.req.req1.level, r.in.req.req1.domain_name);
180         
181         status = dcerpc_drsuapi_DsGetDomainControllerInfo(p, mem_ctx, &r);
182         if (!NT_STATUS_IS_OK(status)) {
183                 const char *errstr = nt_errstr(status);
184                 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
185                         errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
186                 }
187                 printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d\n"
188                        "    with dns domain failed - %s\n",
189                                        r.in.req.req1.level, errstr);
190                 ret = False;
191         } else if (!W_ERROR_IS_OK(r.out.result)) {
192                 printf("DsGetDomainControllerInfo level %d\n"
193                        "    with dns domain failed - %s\n",
194                        r.in.req.req1.level, win_errstr(r.out.result));
195                 ret = False;
196         }
197         
198         {
199                 const char *dc_account = talloc_asprintf(mem_ctx, "%s\\%s$",
200                                                          torture_join_dom_netbios_name(priv->join), 
201                                                          priv->dcinfo.netbios_name);
202                 for (k=0; k < r.out.ctr.ctr01.count; k++) {
203                         if (strcasecmp_m(r.out.ctr.ctr01.array[k].client_account, 
204                                          dc_account)) {
205                                 found = True;
206                                 break;
207                         }
208                 }
209                 if (!found) {
210                         printf("dcerpc_drsuapi_DsGetDomainControllerInfo level %d: Failed to find the domain controller (%s) in last logon records\n",
211                                r.in.req.req1.level,
212                                dc_account);
213                         ret = False;
214                 }
215         }
216
217
218         return ret;
219 }
220
221 static BOOL test_DsWriteAccountSpn(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
222                                    struct DsPrivate *priv)
223 {
224         NTSTATUS status;
225         struct drsuapi_DsWriteAccountSpn r;
226         struct drsuapi_DsNameString names[2];
227         BOOL ret = True;
228
229         r.in.bind_handle                = &priv->bind_handle;
230         r.in.level                      = 1;
231
232         printf("testing DsWriteAccountSpn\n");
233
234         r.in.req.req1.operation = DRSUAPI_DS_SPN_OPERATION_ADD;
235         r.in.req.req1.unknown1  = 0;
236         r.in.req.req1.object_dn = priv->dcinfo.computer_dn;
237         r.in.req.req1.count     = 2;
238         r.in.req.req1.spn_names = names;
239         names[0].str = talloc_asprintf(mem_ctx, "smbtortureSPN/%s",priv->dcinfo.netbios_name);
240         names[1].str = talloc_asprintf(mem_ctx, "smbtortureSPN/%s",priv->dcinfo.dns_name);
241
242         status = dcerpc_drsuapi_DsWriteAccountSpn(p, mem_ctx, &r);
243         if (!NT_STATUS_IS_OK(status)) {
244                 const char *errstr = nt_errstr(status);
245                 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
246                         errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
247                 }
248                 printf("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
249                 ret = False;
250         } else if (!W_ERROR_IS_OK(r.out.result)) {
251                 printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
252                 ret = False;
253         }
254
255         r.in.req.req1.operation = DRSUAPI_DS_SPN_OPERATION_DELETE;
256         r.in.req.req1.unknown1  = 0;
257
258         status = dcerpc_drsuapi_DsWriteAccountSpn(p, mem_ctx, &r);
259         if (!NT_STATUS_IS_OK(status)) {
260                 const char *errstr = nt_errstr(status);
261                 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
262                         errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
263                 }
264                 printf("dcerpc_drsuapi_DsWriteAccountSpn failed - %s\n", errstr);
265                 ret = False;
266         } else if (!W_ERROR_IS_OK(r.out.result)) {
267                 printf("DsWriteAccountSpn failed - %s\n", win_errstr(r.out.result));
268                 ret = False;
269         }
270
271         return ret;
272 }
273
274 static BOOL test_DsReplicaGetInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
275                         struct DsPrivate *priv)
276 {
277         NTSTATUS status;
278         struct drsuapi_DsReplicaGetInfo r;
279         BOOL ret = True;
280         int i;
281         struct {
282                 int32_t level;
283                 int32_t infotype;
284                 const char *obj_dn;
285         } array[] = {
286                 {       
287                         DRSUAPI_DS_REPLICA_GET_INFO,
288                         DRSUAPI_DS_REPLICA_INFO_NEIGHBORS,
289                         NULL
290                 },{
291                         DRSUAPI_DS_REPLICA_GET_INFO,
292                         DRSUAPI_DS_REPLICA_INFO_CURSORS,
293                         NULL
294                 },{
295                         DRSUAPI_DS_REPLICA_GET_INFO,
296                         DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA,
297                         NULL
298                 },{
299                         DRSUAPI_DS_REPLICA_GET_INFO,
300                         DRSUAPI_DS_REPLICA_INFO_KCC_DSA_CONNECT_FAILURES,
301                         NULL
302                 },{
303                         DRSUAPI_DS_REPLICA_GET_INFO,
304                         DRSUAPI_DS_REPLICA_INFO_KCC_DSA_LINK_FAILURES,
305                         NULL
306                 },{
307                         DRSUAPI_DS_REPLICA_GET_INFO,
308                         DRSUAPI_DS_REPLICA_INFO_PENDING_OPS,
309                         NULL
310                 },{
311                         DRSUAPI_DS_REPLICA_GET_INFO2,
312                         DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA,
313                         NULL
314                 },{
315                         DRSUAPI_DS_REPLICA_GET_INFO2,
316                         DRSUAPI_DS_REPLICA_INFO_CURSORS2,
317                         NULL
318                 },{
319                         DRSUAPI_DS_REPLICA_GET_INFO2,
320                         DRSUAPI_DS_REPLICA_INFO_CURSORS3,
321                         NULL
322                 },{
323                         DRSUAPI_DS_REPLICA_GET_INFO2,
324                         DRSUAPI_DS_REPLICA_INFO_OBJ_METADATA2,
325                         NULL
326                 },{
327                         DRSUAPI_DS_REPLICA_GET_INFO2,
328                         DRSUAPI_DS_REPLICA_INFO_ATTRIBUTE_VALUE_METADATA2,
329                         NULL
330                 },{
331                         DRSUAPI_DS_REPLICA_GET_INFO2,
332                         DRSUAPI_DS_REPLICA_INFO_NEIGHBORS02,
333                         NULL
334                 },{
335                         DRSUAPI_DS_REPLICA_GET_INFO2,
336                         DRSUAPI_DS_REPLICA_INFO_CONNECTIONS04,
337                         "__IGNORED__"
338                 },{
339                         DRSUAPI_DS_REPLICA_GET_INFO2,
340                         DRSUAPI_DS_REPLICA_INFO_CURSORS05,
341                         NULL
342                 },{
343                         DRSUAPI_DS_REPLICA_GET_INFO2,
344                         DRSUAPI_DS_REPLICA_INFO_06,
345                         NULL
346                 }
347         };
348
349         if (lp_parm_bool(-1, "torture", "samba4", False)) {
350                 printf("skipping DsReplicaGetInfo test against Samba4\n");
351                 return True;
352         }
353
354         r.in.bind_handle        = &priv->bind_handle;
355
356         for (i=0; i < ARRAY_SIZE(array); i++) {
357                 const char *object_dn;
358
359                 printf("testing DsReplicaGetInfo level %d infotype %d\n",
360                         array[i].level, array[i].infotype);
361
362                 object_dn = (array[i].obj_dn ? array[i].obj_dn : priv->domain_obj_dn);
363
364                 r.in.level = array[i].level;
365                 switch(r.in.level) {
366                 case DRSUAPI_DS_REPLICA_GET_INFO:
367                         r.in.req.req1.info_type = array[i].infotype;
368                         r.in.req.req1.object_dn = object_dn;
369                         ZERO_STRUCT(r.in.req.req1.guid1);
370                         break;
371                 case DRSUAPI_DS_REPLICA_GET_INFO2:
372                         r.in.req.req2.info_type = array[i].infotype;
373                         r.in.req.req2.object_dn = object_dn;
374                         ZERO_STRUCT(r.in.req.req1.guid1);
375                         r.in.req.req2.unknown1  = 0;
376                         r.in.req.req2.string1   = NULL;
377                         r.in.req.req2.string2   = NULL;
378                         r.in.req.req2.unknown2  = 0;
379                         break;
380                 }
381
382                 status = dcerpc_drsuapi_DsReplicaGetInfo(p, mem_ctx, &r);
383                 if (!NT_STATUS_IS_OK(status)) {
384                         const char *errstr = nt_errstr(status);
385                         if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
386                                 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
387                         }
388                         if (p->last_fault_code != DCERPC_FAULT_INVALID_TAG) {
389                                 printf("dcerpc_drsuapi_DsReplicaGetInfo failed - %s\n", errstr);
390                                 ret = False;
391                         } else {
392                                 printf("DsReplicaGetInfo level %d and/or infotype %d not supported by server\n",
393                                         array[i].level, array[i].infotype);
394                         }
395                 } else if (!W_ERROR_IS_OK(r.out.result)) {
396                         printf("DsReplicaGetInfo failed - %s\n", win_errstr(r.out.result));
397                         ret = False;
398                 }
399         }
400
401         return ret;
402 }
403
404 static BOOL test_DsReplicaSync(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
405                         struct DsPrivate *priv)
406 {
407         NTSTATUS status;
408         BOOL ret = True;
409         int i;
410         struct drsuapi_DsReplicaSync r;
411         struct drsuapi_DsReplicaObjectIdentifier nc;
412         struct GUID null_guid;
413         struct dom_sid null_sid;
414         struct {
415                 int32_t level;
416         } array[] = {
417                 {       
418                         1
419                 }
420         };
421
422         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
423                 printf("DsReplicaSync disabled - enable dangerous tests to use\n");
424                 return True;
425         }
426
427         if (lp_parm_bool(-1, "torture", "samba4", False)) {
428                 printf("skipping DsReplicaSync test against Samba4\n");
429                 return True;
430         }
431
432         ZERO_STRUCT(null_guid);
433         ZERO_STRUCT(null_sid);
434
435         r.in.bind_handle        = &priv->bind_handle;
436
437         for (i=0; i < ARRAY_SIZE(array); i++) {
438                 printf("testing DsReplicaSync level %d\n",
439                         array[i].level);
440
441                 r.in.level = array[i].level;
442                 switch(r.in.level) {
443                 case 1:
444                         nc.guid                                 = null_guid;
445                         nc.sid                                  = null_sid;
446                         nc.dn                                   = priv->domain_obj_dn?priv->domain_obj_dn:"";
447
448                         r.in.req.req1.naming_context            = &nc;
449                         r.in.req.req1.source_dsa_guid           = priv->dcinfo.ntds_guid;
450                         r.in.req.req1.other_info                = NULL;
451                         r.in.req.req1.options                   = 16;
452                         break;
453                 }
454
455                 status = dcerpc_drsuapi_DsReplicaSync(p, mem_ctx, &r);
456                 if (!NT_STATUS_IS_OK(status)) {
457                         const char *errstr = nt_errstr(status);
458                         if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
459                                 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
460                         }
461                         printf("dcerpc_drsuapi_DsReplicaSync failed - %s\n", errstr);
462                         ret = False;
463                 } else if (!W_ERROR_IS_OK(r.out.result)) {
464                         printf("DsReplicaSync failed - %s\n", win_errstr(r.out.result));
465                         ret = False;
466                 }
467         }
468
469         return ret;
470 }
471
472 static BOOL test_DsReplicaUpdateRefs(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
473                         struct DsPrivate *priv)
474 {
475         NTSTATUS status;
476         BOOL ret = True;
477         int i;
478         struct drsuapi_DsReplicaUpdateRefs r;
479         struct drsuapi_DsReplicaObjectIdentifier nc;
480         struct GUID null_guid;
481         struct dom_sid null_sid;
482         struct {
483                 int32_t level;
484         } array[] = {
485                 {       
486                         1
487                 }
488         };
489
490         if (lp_parm_bool(-1, "torture", "samba4", False)) {
491                 printf("skipping DsReplicaUpdateRefs test against Samba4\n");
492                 return True;
493         }
494
495         ZERO_STRUCT(null_guid);
496         ZERO_STRUCT(null_sid);
497
498         r.in.bind_handle        = &priv->bind_handle;
499
500         for (i=0; i < ARRAY_SIZE(array); i++) {
501                 printf("testing DsReplicaUpdateRefs level %d\n",
502                         array[i].level);
503
504                 r.in.level = array[i].level;
505                 switch(r.in.level) {
506                 case 1:
507                         nc.guid                         = null_guid;
508                         nc.sid                          = null_sid;
509                         nc.dn                           = priv->domain_obj_dn?priv->domain_obj_dn:"";
510
511                         r.in.req.req1.naming_context    = &nc;
512                         r.in.req.req1.dest_dsa_dns_name = talloc_asprintf(mem_ctx, "__some_dest_dsa_guid_string._msdn.%s",
513                                                                                 priv->domain_dns_name);
514                         r.in.req.req1.dest_dsa_guid     = null_guid;
515                         r.in.req.req1.options           = 0;
516                         break;
517                 }
518
519                 status = dcerpc_drsuapi_DsReplicaUpdateRefs(p, mem_ctx, &r);
520                 if (!NT_STATUS_IS_OK(status)) {
521                         const char *errstr = nt_errstr(status);
522                         if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
523                                 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
524                         }
525                         printf("dcerpc_drsuapi_DsReplicaUpdateRefs failed - %s\n", errstr);
526                         ret = False;
527                 } else if (!W_ERROR_IS_OK(r.out.result)) {
528                         printf("DsReplicaUpdateRefs failed - %s\n", win_errstr(r.out.result));
529                         ret = False;
530                 }
531         }
532
533         return ret;
534 }
535
536 static BOOL test_DsGetNCChanges(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
537                         struct DsPrivate *priv)
538 {
539         NTSTATUS status;
540         BOOL ret = True;
541         int i;
542         struct drsuapi_DsGetNCChanges r;
543         struct drsuapi_DsReplicaObjectIdentifier nc;
544         struct GUID null_guid;
545         struct dom_sid null_sid;
546         struct {
547                 int32_t level;
548         } array[] = {
549                 {       
550                         5
551                 },
552                 {       
553                         8
554                 }
555         };
556
557         if (lp_parm_bool(-1, "torture", "samba4", False)) {
558                 printf("skipping DsGetNCChanges test against Samba4\n");
559                 return True;
560         }
561
562         ZERO_STRUCT(null_guid);
563         ZERO_STRUCT(null_sid);
564
565         for (i=0; i < ARRAY_SIZE(array); i++) {
566                 printf("testing DsGetNCChanges level %d\n",
567                         array[i].level);
568
569                 r.in.bind_handle        = &priv->bind_handle;
570                 r.in.level              = &array[i].level;
571
572                 switch (*r.in.level) {
573                 case 5:
574                         nc.guid = null_guid;
575                         nc.sid  = null_sid;
576                         nc.dn   = priv->domain_obj_dn?priv->domain_obj_dn:"";
577
578                         r.in.req.req5.destination_dsa_guid              = GUID_random();
579                         r.in.req.req5.source_dsa_invocation_id          = null_guid;
580                         r.in.req.req5.naming_context                    = &nc;
581                         r.in.req.req5.highwatermark.tmp_highest_usn     = 0;
582                         r.in.req.req5.highwatermark.reserved_usn        = 0;
583                         r.in.req.req5.highwatermark.highest_usn         = 0;
584                         r.in.req.req5.uptodateness_vector               = NULL;
585                         r.in.req.req5.replica_flags                     = 0;
586                         if (lp_parm_bool(-1, "drsuapi","compression", False)) {
587                                 r.in.req.req5.replica_flags             |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
588                         }
589                         r.in.req.req5.max_object_count                  = 0;
590                         r.in.req.req5.max_ndr_size                      = 0;
591                         r.in.req.req5.unknown4                          = 0;
592                         r.in.req.req5.h1                                = 0;
593
594                         break;
595                 case 8:
596                         nc.guid = null_guid;
597                         nc.sid  = null_sid;
598                         nc.dn   = priv->domain_obj_dn?priv->domain_obj_dn:"";
599
600                         r.in.req.req8.destination_dsa_guid              = GUID_random();
601                         r.in.req.req8.source_dsa_invocation_id          = null_guid;
602                         r.in.req.req8.naming_context                    = &nc;
603                         r.in.req.req8.highwatermark.tmp_highest_usn     = 0;
604                         r.in.req.req8.highwatermark.reserved_usn        = 0;
605                         r.in.req.req8.highwatermark.highest_usn         = 0;
606                         r.in.req.req8.uptodateness_vector               = NULL;
607                         r.in.req.req8.replica_flags                     = 0;
608                         if (lp_parm_bool(-1,"drsuapi","compression",False)) {
609                                 r.in.req.req8.replica_flags             |= DRSUAPI_DS_REPLICA_NEIGHBOUR_COMPRESS_CHANGES;
610                         }
611                         if (lp_parm_bool(-1,"drsuapi","neighbour_writeable",True)) {
612                                 r.in.req.req8.replica_flags             |= DRSUAPI_DS_REPLICA_NEIGHBOUR_WRITEABLE;
613                         }
614                         r.in.req.req8.replica_flags                     |= DRSUAPI_DS_REPLICA_NEIGHBOUR_SYNC_ON_STARTUP
615                                                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_DO_SCHEDULED_SYNCS
616                                                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_RETURN_OBJECT_PARENTS
617                                                                         | DRSUAPI_DS_REPLICA_NEIGHBOUR_NEVER_SYNCED
618                                                                         ;
619                         r.in.req.req8.max_object_count                  = 402;
620                         r.in.req.req8.max_ndr_size                      = 402116;
621                         r.in.req.req8.unknown4                          = 0;
622                         r.in.req.req8.h1                                = 0;
623                         r.in.req.req8.unique_ptr1                       = 0;
624                         r.in.req.req8.unique_ptr2                       = 0;
625                         r.in.req.req8.mapping_ctr.num_mappings          = 0;
626                         r.in.req.req8.mapping_ctr.mappings              = NULL;
627
628                         break;
629                 }
630
631                 status = dcerpc_drsuapi_DsGetNCChanges(p, mem_ctx, &r);
632                 if (!NT_STATUS_IS_OK(status)) {
633                         const char *errstr = nt_errstr(status);
634                         if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
635                                 errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
636                         }
637                         printf("dcerpc_drsuapi_DsGetNCChanges failed - %s\n", errstr);
638                         ret = False;
639                 } else if (!W_ERROR_IS_OK(r.out.result)) {
640                         printf("DsGetNCChanges failed - %s\n", win_errstr(r.out.result));
641                         ret = False;
642                 }
643         }
644
645         return ret;
646 }
647
648 BOOL test_QuerySitesByCost(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
649                            struct DsPrivate *priv)
650 {
651         NTSTATUS status;
652         struct drsuapi_QuerySitesByCost r;
653         BOOL ret = True;
654
655         const char *my_site = "Default-First-Site-Name";
656         const char *remote_site1 = "smbtorture-nonexisting-site1";
657         const char *remote_site2 = "smbtorture-nonexisting-site2";
658
659         r.in.bind_handle = &priv->bind_handle;
660         r.in.level = 1;
661         r.in.req.req1.site_from = talloc_strdup(mem_ctx, my_site);
662         r.in.req.req1.num_req = 2;
663         r.in.req.req1.site_to = talloc_zero_array(mem_ctx, const char *, r.in.req.req1.num_req);
664         r.in.req.req1.site_to[0] = talloc_strdup(mem_ctx, remote_site1);
665         r.in.req.req1.site_to[1] = talloc_strdup(mem_ctx, remote_site2);
666         r.in.req.req1.flags = 0;
667
668         status = dcerpc_drsuapi_QuerySitesByCost(p, mem_ctx, &r);
669         if (!NT_STATUS_IS_OK(status)) {
670                 const char *errstr = nt_errstr(status);
671                 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
672                         errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
673                 }
674                 printf("drsuapi_QuerySitesByCost - %s\n", errstr);
675                 ret = False;
676         } else if (!W_ERROR_IS_OK(r.out.result)) {
677                 printf("QuerySitesByCost failed - %s\n", win_errstr(r.out.result));
678                 ret = False;
679         }
680
681         if (W_ERROR_IS_OK(r.out.result)) {
682
683                 if (!W_ERROR_EQUAL(r.out.ctr.ctr1.info[0].error_code, WERR_DS_OBJ_NOT_FOUND) ||
684                     !W_ERROR_EQUAL(r.out.ctr.ctr1.info[1].error_code, WERR_DS_OBJ_NOT_FOUND)) { 
685                         printf("expected error_code WERR_DS_OBJ_NOT_FOUND, got %s\n", 
686                                 win_errstr(r.out.ctr.ctr1.info[0].error_code));
687                         ret = False;
688                 }
689
690                 if ((r.out.ctr.ctr1.info[0].site_cost != (uint32_t) -1) ||
691                     (r.out.ctr.ctr1.info[1].site_cost != (uint32_t) -1)) {
692                         printf("expected site_cost %d, got %d\n", 
693                                 (uint32_t) -1, r.out.ctr.ctr1.info[0].site_cost);
694                         ret = False;
695                 }
696         }
697
698         return ret;
699
700
701 }
702
703 BOOL test_DsUnbind(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
704                    struct DsPrivate *priv)
705 {
706         NTSTATUS status;
707         struct drsuapi_DsUnbind r;
708         BOOL ret = True;
709
710         r.in.bind_handle = &priv->bind_handle;
711         r.out.bind_handle = &priv->bind_handle;
712
713         printf("testing DsUnbind\n");
714
715         status = dcerpc_drsuapi_DsUnbind(p, mem_ctx, &r);
716         if (!NT_STATUS_IS_OK(status)) {
717                 const char *errstr = nt_errstr(status);
718                 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
719                         errstr = dcerpc_errstr(mem_ctx, p->last_fault_code);
720                 }
721                 printf("dcerpc_drsuapi_DsUnbind failed - %s\n", errstr);
722                 ret = False;
723         } else if (!W_ERROR_IS_OK(r.out.result)) {
724                 printf("DsBind failed - %s\n", win_errstr(r.out.result));
725                 ret = False;
726         }
727
728         return ret;
729 }
730
731 BOOL torture_rpc_drsuapi(struct torture_context *torture)
732 {
733         NTSTATUS status;
734         struct dcerpc_pipe *p;
735         TALLOC_CTX *mem_ctx;
736         BOOL ret = True;
737         struct DsPrivate priv;
738         struct cli_credentials *machine_credentials;
739
740         mem_ctx = talloc_init("torture_rpc_drsuapi");
741
742         ZERO_STRUCT(priv);
743
744         priv.join = torture_join_domain(TEST_MACHINE_NAME, ACB_SVRTRUST, 
745                                        &machine_credentials);
746         if (!priv.join) {
747                 talloc_free(mem_ctx);
748                 printf("Failed to join as BDC\n");
749                 return False;
750         }
751
752         status = torture_rpc_connection(mem_ctx, 
753                                         &p, 
754                                         &dcerpc_table_drsuapi);
755         if (!NT_STATUS_IS_OK(status)) {
756                 torture_leave_domain(priv.join);
757                 talloc_free(mem_ctx);
758                 return False;
759         }
760
761         ret &= test_DsBind(p, mem_ctx, &priv);
762 #if 0
763         ret &= test_QuerySitesByCost(p, mem_ctx, &priv);
764 #endif
765         ret &= test_DsGetDomainControllerInfo(p, mem_ctx, &priv);
766
767         ret &= test_DsCrackNames(p, mem_ctx, &priv);
768
769         ret &= test_DsWriteAccountSpn(p, mem_ctx, &priv);
770
771         ret &= test_DsReplicaGetInfo(p, mem_ctx, &priv);
772
773         ret &= test_DsReplicaSync(p, mem_ctx, &priv);
774
775         ret &= test_DsReplicaUpdateRefs(p, mem_ctx, &priv);
776
777         ret &= test_DsGetNCChanges(p, mem_ctx, &priv);
778
779         ret &= test_DsUnbind(p, mem_ctx, &priv);
780
781         talloc_free(mem_ctx);
782
783         torture_leave_domain(priv.join);
784
785         return ret;
786 }
787
788
789 BOOL torture_rpc_drsuapi_cracknames(struct torture_context *torture)
790 {
791         NTSTATUS status;
792         struct dcerpc_pipe *p;
793         TALLOC_CTX *mem_ctx;
794         BOOL ret = True;
795         struct DsPrivate priv;
796         struct cli_credentials *machine_credentials;
797
798         mem_ctx = talloc_init("torture_rpc_drsuapi");
799
800         printf("Connected to DRAUAPI pipe\n");
801
802         ZERO_STRUCT(priv);
803
804         priv.join = torture_join_domain(TEST_MACHINE_NAME, ACB_SVRTRUST, 
805                                        &machine_credentials);
806         if (!priv.join) {
807                 talloc_free(mem_ctx);
808                 printf("Failed to join as BDC\n");
809                 return False;
810         }
811
812         status = torture_rpc_connection(mem_ctx, 
813                                         &p, 
814                                         &dcerpc_table_drsuapi);
815         if (!NT_STATUS_IS_OK(status)) {
816                 torture_leave_domain(priv.join);
817                 talloc_free(mem_ctx);
818                 return False;
819         }
820
821         ret &= test_DsBind(p, mem_ctx, &priv);
822
823         if (ret) {
824                 /* We don't care if this fails, we just need some info from it */
825                 test_DsGetDomainControllerInfo(p, mem_ctx, &priv);
826                 
827                 ret &= test_DsCrackNames(p, mem_ctx, &priv);
828                 
829                 ret &= test_DsUnbind(p, mem_ctx, &priv);
830         }
831         talloc_free(mem_ctx);
832
833         torture_leave_domain(priv.join);
834
835         return ret;
836 }
837