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