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