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
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 "librpc/gen_ndr/ndr_drsuapi_c.h"
26 #include "torture/rpc/torture_rpc.h"
27 #include <ldb.h>
28 #include "libcli/security/security.h"
29 
30 struct DsCrackNamesPrivate {
31 	struct DsPrivate base;
32 
33 	/* following names are used in Crack Names Matrix test */
34 	const char *fqdn_name;
35 	const char *user_principal_name;
36 	const char *service_principal_name;
37 };
38 
39 static bool test_DsCrackNamesMatrix(struct torture_context *tctx,
40 				    struct DsPrivate *priv, const char *dn,
41 				    const char *user_principal_name, const char *service_principal_name)
42 {
43 	NTSTATUS status;
44 	const char *err_msg;
45 	struct drsuapi_DsCrackNames r;
46 	union drsuapi_DsNameRequest req;
47 	uint32_t level_out;
48 	union drsuapi_DsNameCtr ctr;
49 	struct dcerpc_pipe *p = priv->drs_pipe;
50 	TALLOC_CTX *mem_ctx = priv;
51 
52 	enum drsuapi_DsNameFormat formats[] = {
53 		DRSUAPI_DS_NAME_FORMAT_UNKNOWN,
54 		DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
55 		DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
56 		DRSUAPI_DS_NAME_FORMAT_DISPLAY,
57 		DRSUAPI_DS_NAME_FORMAT_GUID,
58 		DRSUAPI_DS_NAME_FORMAT_CANONICAL,
59 		DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
60 		DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
61 		DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
62 		DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
63 		DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN
64 	};
65 	struct drsuapi_DsNameString names[ARRAY_SIZE(formats)];
66 	int i, j;
67 
68 	const char *n_matrix[ARRAY_SIZE(formats)][ARRAY_SIZE(formats)];
69 	const char *n_from[ARRAY_SIZE(formats)];
70 
71 	ZERO_STRUCT(r);
72 	r.in.bind_handle		= &priv->bind_handle;
73 	r.in.level			= 1;
74 	r.in.req			= &req;
75 	r.in.req->req1.codepage		= 1252; /* german */
76 	r.in.req->req1.language		= 0x00000407; /* german */
77 	r.in.req->req1.count		= 1;
78 	r.in.req->req1.names		= names;
79 	r.in.req->req1.format_flags	= DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
80 
81 	r.out.level_out			= &level_out;
82 	r.out.ctr			= &ctr;
83 
84 	n_matrix[0][0] = dn;
85 
86 	for (i = 0; i < ARRAY_SIZE(formats); i++) {
87 		r.in.req->req1.format_offered	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
88 		r.in.req->req1.format_desired	= formats[i];
89 		names[0].str = dn;
90 		torture_comment(tctx, "Testing DsCrackNames (matrix prep) with name '%s'"
91 				      " offered format: %d desired format:%d\n",
92 				names[0].str,
93 				r.in.req->req1.format_offered,
94 				r.in.req->req1.format_desired);
95 		status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r);
96 		if (!NT_STATUS_IS_OK(status)) {
97 			const char *errstr = nt_errstr(status);
98 			err_msg = talloc_asprintf(mem_ctx,
99 					"testing DsCrackNames (matrix prep) with name '%s' from format: %d desired format:%d failed - %s",
100 					names[0].str, r.in.req->req1.format_offered, r.in.req->req1.format_desired, errstr);
101 			torture_fail(tctx, err_msg);
102 		} else if (!W_ERROR_IS_OK(r.out.result)) {
103 			err_msg = talloc_asprintf(mem_ctx,
104 					"testing DsCrackNames (matrix prep) with name '%s' from format: %d desired format:%d failed - %s",
105 			       names[0].str, r.in.req->req1.format_offered, r.in.req->req1.format_desired, win_errstr(r.out.result));
106 			torture_fail(tctx, err_msg);
107 		}
108 
109 		switch (formats[i]) {
110 		case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL:
111 			if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE) {
112 				err_msg = talloc_asprintf(mem_ctx,
113 						"Unexpected error (%d): This name lookup should fail",
114 						r.out.ctr->ctr1->array[0].status);
115 				torture_fail(tctx, err_msg);
116 			}
117 			torture_comment(tctx, __location__ ": (expected) error\n");
118 			break;
119 		case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL:
120 			if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_NO_MAPPING) {
121 				err_msg = talloc_asprintf(mem_ctx,
122 						"Unexpected error (%d): This name lookup should fail",
123 						r.out.ctr->ctr1->array[0].status);
124 				torture_fail(tctx, err_msg);
125 			}
126 			torture_comment(tctx, __location__ ": (expected) error\n");
127 			break;
128 		case DRSUAPI_DS_NAME_FORMAT_UNKNOWN:	/* should fail as we ask server to convert to Unknown format */
129 		case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN:
130 		case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY:
131 			if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR) {
132 				err_msg = talloc_asprintf(mem_ctx,
133 						"Unexpected error (%d): This name lookup should fail",
134 						r.out.ctr->ctr1->array[0].status);
135 				torture_fail(tctx, err_msg);
136 			}
137 			torture_comment(tctx, __location__ ": (expected) error\n");
138 			break;
139 		default:
140 			if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
141 				err_msg = talloc_asprintf(mem_ctx,
142 						"DsCrackNames error: %d",
143 						r.out.ctr->ctr1->array[0].status);
144 				torture_fail(tctx, err_msg);
145 			}
146 			break;
147 		}
148 
149 		switch (formats[i]) {
150 		case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL:
151 			n_from[i] = user_principal_name;
152 			break;
153 		case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL:
154 			n_from[i] = service_principal_name;
155 			break;
156 		case DRSUAPI_DS_NAME_FORMAT_UNKNOWN:
157 		case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY:
158 		case DRSUAPI_DS_NAME_FORMAT_DNS_DOMAIN:
159 			n_from[i] = NULL;
160 			break;
161 		default:
162 			n_from[i] = r.out.ctr->ctr1->array[0].result_name;
163 			printf("%s\n", n_from[i]);
164 			break;
165 		}
166 	}
167 
168 	for (i = 0; i < ARRAY_SIZE(formats); i++) {
169 		for (j = 0; j < ARRAY_SIZE(formats); j++) {
170 			r.in.req->req1.format_offered	= formats[i];
171 			r.in.req->req1.format_desired	= formats[j];
172 			if (!n_from[i]) {
173 				n_matrix[i][j] = NULL;
174 				continue;
175 			}
176 			names[0].str = n_from[i];
177 			status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r);
178 			if (!NT_STATUS_IS_OK(status)) {
179 				const char *errstr = nt_errstr(status);
180 				err_msg = talloc_asprintf(mem_ctx,
181 						"testing DsCrackNames (matrix) with name '%s' from format: %d desired format:%d failed - %s",
182 						names[0].str, r.in.req->req1.format_offered, r.in.req->req1.format_desired, errstr);
183 				torture_fail(tctx, err_msg);
184 			} else if (!W_ERROR_IS_OK(r.out.result)) {
185 				err_msg = talloc_asprintf(mem_ctx,
186 						"testing DsCrackNames (matrix) with name '%s' from format: %d desired format:%d failed - %s",
187 						names[0].str, r.in.req->req1.format_offered, r.in.req->req1.format_desired,
188 						win_errstr(r.out.result));
189 				torture_fail(tctx, err_msg);
190 			}
191 
192 			if (r.out.ctr->ctr1->array[0].status == DRSUAPI_DS_NAME_STATUS_OK) {
193 				n_matrix[i][j] = r.out.ctr->ctr1->array[0].result_name;
194 			} else {
195 				n_matrix[i][j] = NULL;
196 			}
197 		}
198 	}
199 
200 	for (i = 0; i < ARRAY_SIZE(formats); i++) {
201 		for (j = 0; j < ARRAY_SIZE(formats); j++) {
202 			torture_comment(tctx, "Converting %s (format %d)"
203 						" to %d gave %s\n",
204 						n_from[i], formats[i],
205 						formats[j], n_matrix[i][j]);
206 			if (n_matrix[i][j] == n_from[j]) {
207 
208 			/* We don't have a from name for these yet (and we can't map to them to find it out) */
209 			} else if (n_matrix[i][j] == NULL && n_from[i] == NULL) {
210 
211 			/* we can't map to these two */
212 			} else if (n_matrix[i][j] == NULL && formats[j] == DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL) {
213 			} else if (n_matrix[i][j] == NULL && formats[j] == DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL) {
214 			} else if (n_matrix[i][j] == NULL && n_from[j] != NULL) {
215 				err_msg = talloc_asprintf(mem_ctx,
216 						"dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: should be %s",
217 						formats[i], formats[j], n_from[j]);
218 				torture_fail(tctx, err_msg);
219 			} else if (n_matrix[i][j] != NULL && n_from[j] == NULL) {
220 				err_msg = talloc_asprintf(mem_ctx,
221 						"dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: should be %s",
222 						formats[i], formats[j], n_matrix[i][j]);
223 				torture_fail(tctx, err_msg);
224 			} else if (strcmp(n_matrix[i][j], n_from[j]) != 0) {
225 				err_msg = talloc_asprintf(mem_ctx,
226 						"dcerpc_drsuapi_DsCrackNames mismatch - from %d to %d: %s should be %s",
227 						formats[i], formats[j], n_matrix[i][j], n_from[j]);
228 				torture_fail(tctx, err_msg);
229 			}
230 		}
231 	}
232 
233 	return true;
234 }
235 
236 bool test_DsCrackNames(struct torture_context *tctx,
237 		       struct DsPrivate *priv)
238 {
239 	NTSTATUS status;
240 	const char *err_msg;
241 	struct drsuapi_DsCrackNames r;
242 	union drsuapi_DsNameRequest req;
243 	uint32_t level_out;
244 	union drsuapi_DsNameCtr ctr;
245 	struct drsuapi_DsNameString names[1];
246 	const char *dns_domain;
247 	const char *nt4_domain;
248 	const char *FQDN_1779_name;
249 	struct ldb_context *ldb;
250 	struct ldb_dn *FQDN_1779_dn;
251 	struct ldb_dn *realm_dn;
252 	const char *realm_dn_str;
253 	const char *realm_canonical;
254 	const char *realm_canonical_ex;
255 	const char *user_principal_name;
256 	char *user_principal_name_short;
257 	const char *service_principal_name;
258 	const char *canonical_name;
259 	const char *canonical_ex_name;
260 	const char *dom_sid;
261 	const char *test_dc = torture_join_netbios_name(priv->join);
262 	struct dcerpc_pipe *p = priv->drs_pipe;
263 	TALLOC_CTX *mem_ctx = priv;
264 
265 	ZERO_STRUCT(r);
266 	r.in.bind_handle		= &priv->bind_handle;
267 	r.in.level			= 1;
268 	r.in.req			= &req;
269 	r.in.req->req1.codepage		= 1252; /* german */
270 	r.in.req->req1.language		= 0x00000407; /* german */
271 	r.in.req->req1.count		= 1;
272 	r.in.req->req1.names		= names;
273 	r.in.req->req1.format_flags	= DRSUAPI_DS_NAME_FLAG_NO_FLAGS;
274 
275 	r.in.req->req1.format_offered	= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY;
276 	r.in.req->req1.format_desired	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
277 
278 	r.out.level_out			= &level_out;
279 	r.out.ctr			= &ctr;
280 
281 	dom_sid = dom_sid_string(mem_ctx, torture_join_sid(priv->join));
282 
283 	names[0].str = dom_sid;
284 
285 	torture_comment(tctx, "Testing DsCrackNames with name '%s'"
286 			      " offered format: %d desired format:%d\n",
287 			names[0].str,
288 			r.in.req->req1.format_offered,
289 			r.in.req->req1.format_desired);
290 
291 	status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r);
292 	if (!NT_STATUS_IS_OK(status)) {
293 		const char *errstr = nt_errstr(status);
294 		err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
295 		torture_fail(tctx, err_msg);
296 	} else if (!W_ERROR_IS_OK(r.out.result)) {
297 		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
298 		torture_fail(tctx, err_msg);
299 	} else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
300 		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
301 					  r.out.ctr->ctr1->array[0].status);
302 		torture_fail(tctx, err_msg);
303 	}
304 
305 	dns_domain = r.out.ctr->ctr1->array[0].dns_domain_name;
306 	nt4_domain = r.out.ctr->ctr1->array[0].result_name;
307 
308 	r.in.req->req1.format_desired	= DRSUAPI_DS_NAME_FORMAT_GUID;
309 
310 	torture_comment(tctx, "Testing DsCrackNames with name '%s'"
311 			      " offered format: %d desired format:%d\n",
312 			names[0].str,
313 			r.in.req->req1.format_offered,
314 			r.in.req->req1.format_desired);
315 
316 	status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r);
317 	if (!NT_STATUS_IS_OK(status)) {
318 		const char *errstr = nt_errstr(status);
319 		err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
320 		torture_fail(tctx, err_msg);
321 	} else if (!W_ERROR_IS_OK(r.out.result)) {
322 		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
323 		torture_fail(tctx, err_msg);
324 	} else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
325 		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
326 					  r.out.ctr->ctr1->array[0].status);
327 		torture_fail(tctx, err_msg);
328 	}
329 
330 	priv->domain_dns_name = r.out.ctr->ctr1->array[0].dns_domain_name;
331 	priv->domain_guid_str = r.out.ctr->ctr1->array[0].result_name;
332 	GUID_from_string(priv->domain_guid_str, &priv->domain_guid);
333 
334 	r.in.req->req1.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
335 
336 	torture_comment(tctx, "Testing DsCrackNames with name '%s'"
337 			      " offered format: %d desired format:%d\n",
338 			names[0].str,
339 			r.in.req->req1.format_offered,
340 			r.in.req->req1.format_desired);
341 
342 	status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r);
343 	if (!NT_STATUS_IS_OK(status)) {
344 		const char *errstr = nt_errstr(status);
345 		err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
346 		torture_fail(tctx, err_msg);
347 	} else if (!W_ERROR_IS_OK(r.out.result)) {
348 		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
349 		torture_fail(tctx, err_msg);
350 	} else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
351 		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
352 					  r.out.ctr->ctr1->array[0].status);
353 		torture_fail(tctx, err_msg);
354 	}
355 
356 	ldb = ldb_init(mem_ctx, tctx->ev);
357 
358 	realm_dn_str = r.out.ctr->ctr1->array[0].result_name;
359 	realm_dn =  ldb_dn_new(mem_ctx, ldb, realm_dn_str);
360 	realm_canonical = ldb_dn_canonical_string(mem_ctx, realm_dn);
361 
362 	if (strcmp(realm_canonical,
363 		   talloc_asprintf(mem_ctx, "%s/", dns_domain))!= 0) {
364 		err_msg = talloc_asprintf(mem_ctx, "local Round trip on canonical name failed: %s != %s!",
365 				          realm_canonical,
366 				          talloc_asprintf(mem_ctx, "%s/", dns_domain));
367 		torture_fail(tctx, err_msg);
368 	};
369 
370 	realm_canonical_ex = ldb_dn_canonical_ex_string(mem_ctx, realm_dn);
371 
372 	if (strcmp(realm_canonical_ex,
373 		   talloc_asprintf(mem_ctx, "%s\n", dns_domain))!= 0) {
374 		err_msg = talloc_asprintf(mem_ctx, "local Round trip on canonical ex name failed: %s != %s!",
375 				          realm_canonical_ex,
376 				          talloc_asprintf(mem_ctx, "%s\n", dns_domain));
377 		torture_fail(tctx, err_msg);
378 	};
379 
380 	r.in.req->req1.format_offered	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
381 	r.in.req->req1.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
382 	names[0].str = nt4_domain;
383 
384 	torture_comment(tctx, "Testing DsCrackNames with name '%s'"
385 			      " offered format: %d desired format:%d\n",
386 			names[0].str,
387 			r.in.req->req1.format_offered,
388 			r.in.req->req1.format_desired);
389 
390 	status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r);
391 	if (!NT_STATUS_IS_OK(status)) {
392 		const char *errstr = nt_errstr(status);
393 		err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
394 		torture_fail(tctx, err_msg);
395 	} else if (!W_ERROR_IS_OK(r.out.result)) {
396 		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
397 		torture_fail(tctx, err_msg);
398 	} else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
399 		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
400 					  r.out.ctr->ctr1->array[0].status);
401 		torture_fail(tctx, err_msg);
402 	}
403 
404 	priv->domain_obj_dn = r.out.ctr->ctr1->array[0].result_name;
405 
406 	r.in.req->req1.format_offered	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT;
407 	r.in.req->req1.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
408 	names[0].str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, test_dc);
409 
410 	torture_comment(tctx, "Testing DsCrackNames with name '%s'"
411 			      " offered format: %d desired format:%d\n",
412 			names[0].str,
413 			r.in.req->req1.format_offered,
414 			r.in.req->req1.format_desired);
415 
416 	status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r);
417 	if (!NT_STATUS_IS_OK(status)) {
418 		const char *errstr = nt_errstr(status);
419 		err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
420 		torture_fail(tctx, err_msg);
421 	} else if (!W_ERROR_IS_OK(r.out.result)) {
422 		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
423 		torture_fail(tctx, err_msg);
424 	} else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
425 		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
426 					  r.out.ctr->ctr1->array[0].status);
427 		torture_fail(tctx, err_msg);
428 	}
429 
430 	FQDN_1779_name = r.out.ctr->ctr1->array[0].result_name;
431 
432 	r.in.req->req1.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID;
433 	r.in.req->req1.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779;
434 	names[0].str = priv->domain_guid_str;
435 
436 	torture_comment(tctx, "Testing DsCrackNames with name '%s'"
437 			      " offered format: %d desired format:%d\n",
438 			names[0].str,
439 			r.in.req->req1.format_offered,
440 			r.in.req->req1.format_desired);
441 
442 	status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r);
443 	if (!NT_STATUS_IS_OK(status)) {
444 		const char *errstr = nt_errstr(status);
445 		err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
446 		torture_fail(tctx, err_msg);
447 	} else if (!W_ERROR_IS_OK(r.out.result)) {
448 		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
449 		torture_fail(tctx, err_msg);
450 	} else if (r.out.ctr->ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) {
451 		err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed on name - %d",
452 					  r.out.ctr->ctr1->array[0].status);
453 		torture_fail(tctx, err_msg);
454 	}
455 
456 	if (strcmp(priv->domain_dns_name, r.out.ctr->ctr1->array[0].dns_domain_name) != 0) {
457 		err_msg = talloc_asprintf(mem_ctx,
458 				"DsCrackNames failed to return same DNS name - expected %s got %s",
459 				priv->domain_dns_name, r.out.ctr->ctr1->array[0].dns_domain_name);
460 		torture_fail(tctx, err_msg);
461 	}
462 
463 	FQDN_1779_dn = ldb_dn_new(mem_ctx, ldb, FQDN_1779_name);
464 
465 	canonical_name = ldb_dn_canonical_string(mem_ctx, FQDN_1779_dn);
466 	canonical_ex_name = ldb_dn_canonical_ex_string(mem_ctx, FQDN_1779_dn);
467 
468 	user_principal_name = talloc_asprintf(mem_ctx, "%s$@%s", test_dc, dns_domain);
469 
470 	/* form up a user@DOMAIN */
471 	user_principal_name_short = talloc_asprintf(mem_ctx, "%s$@%s", test_dc, nt4_domain);
472 	/* variable nt4_domain includs a trailing \ */
473 	user_principal_name_short[strlen(user_principal_name_short) - 1] = '\0';
474 
475 	service_principal_name = talloc_asprintf(mem_ctx, "HOST/%s", test_dc);
476 	{
477 
478 		struct {
479 			enum drsuapi_DsNameFormat format_offered;
480 			enum drsuapi_DsNameFormat format_desired;
481 			const char *comment;
482 			const char *str;
483 			const char *expected_str;
484 			const char *expected_dns;
485 			enum drsuapi_DsNameStatus status;
486 			enum drsuapi_DsNameStatus alternate_status;
487 			enum drsuapi_DsNameFlags flags;
488 			bool skip;
489 		} crack[] = {
490 			{
491 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
492 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
493 				.str = user_principal_name,
494 				.expected_str = FQDN_1779_name,
495 				.status = DRSUAPI_DS_NAME_STATUS_OK
496 			},
497 			{
498 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
499 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
500 				.str = user_principal_name_short,
501 				.expected_str = FQDN_1779_name,
502 				.status = DRSUAPI_DS_NAME_STATUS_OK
503 			},
504 			{
505 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
506 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
507 				.str = FQDN_1779_name,
508 				.status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING
509 			},
510 			{
511 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
512 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
513 				.str = service_principal_name,
514 				.expected_str = FQDN_1779_name,
515 				.status = DRSUAPI_DS_NAME_STATUS_OK
516 			},
517 			{
518 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
519 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
520 				.str = talloc_asprintf(mem_ctx, "cifs/%s.%s", test_dc, dns_domain),
521 				.comment = "ServicePrincipal Name",
522 				.expected_str = FQDN_1779_name,
523 				.status = DRSUAPI_DS_NAME_STATUS_OK
524 			},
525 			{
526 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
527 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_CANONICAL,
528 				.str = FQDN_1779_name,
529 				.expected_str = canonical_name,
530 				.status = DRSUAPI_DS_NAME_STATUS_OK
531 			},
532 			{
533 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_CANONICAL,
534 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
535 				.str = canonical_name,
536 				.expected_str = FQDN_1779_name,
537 				.status = DRSUAPI_DS_NAME_STATUS_OK
538 			},
539 			{
540 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
541 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
542 				.str = FQDN_1779_name,
543 				.expected_str = canonical_ex_name,
544 				.status = DRSUAPI_DS_NAME_STATUS_OK
545 			},
546 			{
547 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
548 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
549 				.str = canonical_ex_name,
550 				.expected_str = FQDN_1779_name,
551 				.status = DRSUAPI_DS_NAME_STATUS_OK
552 			},
553 			{
554 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
555 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_CANONICAL,
556 				.str = FQDN_1779_name,
557 				.comment = "DN to cannoical syntactial only",
558 				.status = DRSUAPI_DS_NAME_STATUS_OK,
559 				.expected_str = canonical_name,
560 				.flags = DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY
561 			},
562 			{
563 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
564 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
565 				.str = FQDN_1779_name,
566 				.comment = "DN to cannoical EX syntactial only",
567 				.status = DRSUAPI_DS_NAME_STATUS_OK,
568 				.expected_str = canonical_ex_name,
569 				.flags = DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY
570 			},
571 			{
572 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
573 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_DISPLAY,
574 				.str = FQDN_1779_name,
575 				.status = DRSUAPI_DS_NAME_STATUS_OK
576 			},
577 			{
578 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
579 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_GUID,
580 				.str = FQDN_1779_name,
581 				.status = DRSUAPI_DS_NAME_STATUS_OK
582 			},
583 			{
584 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID,
585 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
586 				.str = priv->domain_guid_str,
587 				.comment = "Domain GUID to NT4 ACCOUNT",
588 				.expected_str = nt4_domain,
589 				.status = DRSUAPI_DS_NAME_STATUS_OK
590 			},
591 			{
592 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID,
593 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_CANONICAL,
594 				.str = priv->domain_guid_str,
595 				.comment = "Domain GUID to Canonical",
596 				.expected_str = talloc_asprintf(mem_ctx, "%s/", dns_domain),
597 				.status = DRSUAPI_DS_NAME_STATUS_OK
598 			},
599 			{
600 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID,
601 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX,
602 				.str = priv->domain_guid_str,
603 				.comment = "Domain GUID to Canonical EX",
604 				.expected_str = talloc_asprintf(mem_ctx, "%s\n", dns_domain),
605 				.status = DRSUAPI_DS_NAME_STATUS_OK
606 			},
607 			{
608 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_DISPLAY,
609 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
610 				.str = "CN=Microsoft Corporation,L=Redmond,S=Washington,C=US",
611 				.comment = "display name for Microsoft Support Account",
612 				.status = DRSUAPI_DS_NAME_STATUS_OK,
613 				.alternate_status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE,
614 				.skip = torture_setting_bool(tctx, "samba4", false)
615 			},
616 			{
617 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID,
618 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
619 				.str = GUID_string2(mem_ctx, torture_join_user_guid(priv->join)),
620 				.comment = "Account GUID -> DN",
621 				.expected_str = FQDN_1779_name,
622 				.status = DRSUAPI_DS_NAME_STATUS_OK
623 			},
624 			{
625 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID,
626 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
627 				.str = GUID_string2(mem_ctx, torture_join_user_guid(priv->join)),
628 				.comment = "Account GUID -> NT4 Account",
629 				.expected_str = talloc_asprintf(mem_ctx, "%s%s$", nt4_domain, test_dc),
630 				.status = DRSUAPI_DS_NAME_STATUS_OK
631 			},
632 			{
633 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID,
634 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
635 				.str = GUID_string2(mem_ctx, &priv->dcinfo.site_guid),
636 				.comment = "Site GUID",
637 				.expected_str = priv->dcinfo.site_dn,
638 				.status = DRSUAPI_DS_NAME_STATUS_OK
639 			},
640 			{
641 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID,
642 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
643 				.str = GUID_string2(mem_ctx, &priv->dcinfo.computer_guid),
644 				.comment = "Computer GUID",
645 				.expected_str = priv->dcinfo.computer_dn,
646 				.status = DRSUAPI_DS_NAME_STATUS_OK
647 			},
648 			{
649 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID,
650 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
651 				.str = GUID_string2(mem_ctx, &priv->dcinfo.computer_guid),
652 				.comment = "Computer GUID -> NT4 Account",
653 				.status = DRSUAPI_DS_NAME_STATUS_OK
654 			},
655 			{
656 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID,
657 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
658 				.str = GUID_string2(mem_ctx, &priv->dcinfo.server_guid),
659 				.comment = "Server GUID",
660 				.expected_str = priv->dcinfo.server_dn,
661 				.status = DRSUAPI_DS_NAME_STATUS_OK
662 			},
663 			{
664 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID,
665 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
666 				.str = GUID_string2(mem_ctx, &priv->dcinfo.ntds_guid),
667 				.comment = "NTDS GUID",
668 				.expected_str = priv->dcinfo.ntds_dn,
669 				.status = DRSUAPI_DS_NAME_STATUS_OK,
670 				.skip = GUID_all_zero(&priv->dcinfo.ntds_guid)
671 			},
672 			{
673 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_DISPLAY,
674 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
675 				.str = test_dc,
676 				.comment = "DISPLAY NAME search for DC short name",
677 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
678 			},
679 			{
680 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
681 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
682 				.str = talloc_asprintf(mem_ctx, "krbtgt/%s", dns_domain),
683 				.comment = "Looking for KRBTGT as a service principal",
684 				.status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY,
685 				.expected_dns = dns_domain
686 			},
687 			{
688 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
689 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
690 				.str = talloc_asprintf(mem_ctx, "bogus/%s", dns_domain),
691 				.comment = "Looking for bogus service principal",
692 				.status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY,
693 				.expected_dns = dns_domain
694 			},
695 			{
696 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
697 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
698 				.str = talloc_asprintf(mem_ctx, "bogus/%s.%s", test_dc, dns_domain),
699 				.comment = "Looking for bogus service on test DC",
700 				.status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY,
701 				.expected_dns = talloc_asprintf(mem_ctx, "%s.%s", test_dc, dns_domain)
702 			},
703 			{
704 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
705 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
706 				.str = talloc_asprintf(mem_ctx, "krbtgt"),
707 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
708 			},
709 			{
710 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
711 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
712 				.comment = "Looking for the kadmin/changepw service as a service principal",
713 				.str = talloc_asprintf(mem_ctx, "kadmin/changepw"),
714 				.status = DRSUAPI_DS_NAME_STATUS_OK,
715 				.expected_str = talloc_asprintf(mem_ctx, "CN=krbtgt,CN=Users,%s", realm_dn_str),
716 				.alternate_status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE
717 			},
718 			{
719 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
720 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
721 				.str = talloc_asprintf(mem_ctx, "cifs/%s.%s@%s",
722 						       test_dc, dns_domain,
723 						       dns_domain),
724 				.status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY
725 			},
726 			{
727 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
728 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
729 				.str = talloc_asprintf(mem_ctx, "cifs/%s.%s@%s",
730 						       test_dc, dns_domain,
731 						       "BOGUS"),
732 				.status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY,
733 				.expected_dns = "BOGUS"
734 			},
735 			{
736 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
737 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
738 				.str = talloc_asprintf(mem_ctx, "cifs/%s.%s@%s",
739 						       test_dc, "REALLY",
740 						       "BOGUS"),
741 				.status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY,
742 				.expected_dns = "BOGUS"
743 			},
744 			{
745 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
746 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
747 				.str = talloc_asprintf(mem_ctx, "cifs/%s.%s",
748 						       test_dc, dns_domain),
749 				.status = DRSUAPI_DS_NAME_STATUS_OK
750 			},
751 			{
752 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
753 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
754 				.str = talloc_asprintf(mem_ctx, "cifs/%s",
755 						       test_dc),
756 				.status = DRSUAPI_DS_NAME_STATUS_OK
757 			},
758 			{
759 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID,
760 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
761 				.str = "NOT A GUID",
762 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
763 			},
764 			{
765 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
766 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
767 				.str = "NOT A SID",
768 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
769 			},
770 			{
771 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
772 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
773 				.str = "NOT AN NT4 NAME",
774 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
775 			},
776 			{
777 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
778 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_GUID,
779 				.comment = "Unparsable DN",
780 				.str = "NOT A DN",
781 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
782 			},
783 			{
784 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
785 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
786 				.comment = "Unparsable user principal",
787 				.str = "NOT A PRINCIPAL",
788 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
789 			},
790 			{
791 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
792 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
793 				.comment = "Unparsable service principal",
794 				.str = "NOT A SERVICE PRINCIPAL",
795 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
796 			},
797 			{
798 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_GUID,
799 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
800 				.comment = "BIND GUID (ie, not in the directory)",
801 				.str = GUID_string2(mem_ctx, &priv->bind_guid),
802 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
803 			},
804 			{
805 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
806 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
807 				.comment = "Unqualified Machine account as user principal",
808 				.str = talloc_asprintf(mem_ctx, "%s$", test_dc),
809 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
810 			},
811 			{
812 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
813 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
814 				.comment = "Machine account as service principal",
815 				.str = talloc_asprintf(mem_ctx, "%s$", test_dc),
816 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
817 			},
818 			{
819 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
820 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
821 				.comment = "Full Machine account as service principal",
822 				.str = user_principal_name,
823 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
824 			},
825 			{
826 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
827 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
828 				.comment = "Realm as an NT4 domain lookup",
829 				.str = talloc_asprintf(mem_ctx, "%s\\", dns_domain),
830 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
831 			},
832 			{
833 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
834 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
835 				.comment = "BUILTIN\\ -> DN",
836 				.str = "BUILTIN\\",
837 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
838 			},
839 			{
840 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
841 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
842 				.comment = "NT AUTHORITY\\ -> DN",
843 				.str = "NT AUTHORITY\\",
844 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
845 			},
846 			{
847 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
848 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
849 				.comment = "NT AUTHORITY\\ANONYMOUS LOGON -> DN",
850 				.str = "NT AUTHORITY\\ANONYMOUS LOGON",
851 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
852 			},
853 			{
854 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
855 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
856 				.comment = "NT AUTHORITY\\SYSTEM -> DN",
857 				.str = "NT AUTHORITY\\SYSTEM",
858 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
859 			},
860 			{
861 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
862 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
863 				.comment = "BUILTIN SID -> NT4 account",
864 				.str = SID_BUILTIN,
865 				.status = DRSUAPI_DS_NAME_STATUS_NO_MAPPING,
866 				.alternate_status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE
867 			},
868 			{
869 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
870 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
871 				.str = SID_BUILTIN,
872 				.comment = "Builtin Domain SID -> DN",
873 				.status = DRSUAPI_DS_NAME_STATUS_OK,
874 				.expected_str = talloc_asprintf(mem_ctx, "CN=Builtin,%s", realm_dn_str),
875 				.alternate_status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE
876 			},
877 			{
878 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
879 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
880 				.str = SID_BUILTIN_ADMINISTRATORS,
881 				.comment = "Builtin Administrors SID -> DN",
882 				.status = DRSUAPI_DS_NAME_STATUS_OK,
883 				.alternate_status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE
884 			},
885 			{
886 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
887 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
888 				.str = SID_BUILTIN_ADMINISTRATORS,
889 				.comment = "Builtin Administrors SID -> NT4 Account",
890 				.status = DRSUAPI_DS_NAME_STATUS_OK,
891 				.alternate_status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE
892 			},
893 			{
894 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
895 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
896 				.str = SID_NT_ANONYMOUS,
897 				.comment = "NT Anonymous SID -> NT4 Account",
898 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
899 			},
900 			{
901 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
902 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
903 				.str = SID_NT_SYSTEM,
904 				.comment = "NT SYSTEM SID -> NT4 Account",
905 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
906 			},
907 			{
908 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
909 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
910 				.comment = "Domain SID -> DN",
911 				.str = dom_sid,
912 				.expected_str = realm_dn_str,
913 				.status = DRSUAPI_DS_NAME_STATUS_OK
914 			},
915 			{
916 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
917 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT,
918 				.comment = "Domain SID -> NT4 account",
919 				.str = dom_sid,
920 				.expected_str = nt4_domain,
921 				.status = DRSUAPI_DS_NAME_STATUS_OK
922 			},
923 			{
924 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
925 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
926 				.comment = "invalid user principal name",
927 				.str = "foo@bar",
928 				.status = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY,
929 				.expected_dns = "bar"
930 			},
931 			{
932 				.format_offered	= DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
933 				.format_desired	= DRSUAPI_DS_NAME_FORMAT_FQDN_1779,
934 				.comment = "invalid user principal name in valid domain",
935 				.str = talloc_asprintf(mem_ctx, "invalidusername@%s", dns_domain),
936 				.status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND
937 			}
938 		};
939 		int i;
940 
941 		for (i=0; i < ARRAY_SIZE(crack); i++) {
942 			const char *comment;
943 
944 			torture_comment(tctx, "Testing DsCrackNames with name '%s'"
945 					" offered format: %d desired format:%d\n",
946 					crack[i].str,
947 					crack[i].format_offered,
948 					crack[i].format_desired);
949 
950 			r.in.req->req1.format_flags   = crack[i].flags;
951 			r.in.req->req1.format_offered = crack[i].format_offered;
952 			r.in.req->req1.format_desired = crack[i].format_desired;
953 			names[0].str = crack[i].str;
954 
955 			if (crack[i].comment) {
956 				comment = talloc_asprintf(mem_ctx,
957 							  "'%s' with name '%s' offered format:%d desired format:%d\n",
958 							  crack[i].comment, names[0].str,
959 							  r.in.req->req1.format_offered,
960 							  r.in.req->req1.format_desired);
961 			} else {
962 				comment = talloc_asprintf(mem_ctx, "'%s' offered format:%d desired format:%d\n",
963 							  names[0].str,
964 							  r.in.req->req1.format_offered,
965 							  r.in.req->req1.format_desired);
966 			}
967 			if (crack[i].skip) {
968 				torture_comment(tctx, "skipping: %s", comment);
969 				continue;
970 			}
971 			status = dcerpc_drsuapi_DsCrackNames_r(p->binding_handle, mem_ctx, &r);
972 			if (!NT_STATUS_IS_OK(status)) {
973 				const char *errstr = nt_errstr(status);
974 				err_msg = talloc_asprintf(mem_ctx, "dcerpc_drsuapi_DsCrackNames failed - %s", errstr);
975 				torture_fail(tctx, err_msg);
976 			} else if (!W_ERROR_IS_OK(r.out.result)) {
977 				err_msg = talloc_asprintf(mem_ctx, "DsCrackNames failed - %s", win_errstr(r.out.result));
978 				torture_fail(tctx, err_msg);
979 			} else if (r.out.ctr->ctr1->array[0].status != crack[i].status) {
980 				if (crack[i].alternate_status) {
981 					if (r.out.ctr->ctr1->array[0].status != crack[i].alternate_status) {
982 						err_msg = talloc_asprintf(mem_ctx,
983 								"DsCrackNames unexpected status %d, wanted %d or %d on: %s",
984 								r.out.ctr->ctr1->array[0].status,
985 								crack[i].status,
986 								crack[i].alternate_status,
987 								comment);
988 						torture_fail(tctx, err_msg);
989 					}
990 				} else {
991 					err_msg = talloc_asprintf(mem_ctx,
992 							"DsCrackNames unexpected status %d, wanted %d on: %s\n",
993 							r.out.ctr->ctr1->array[0].status,
994 							crack[i].status,
995 							comment);
996 					torture_fail(tctx, err_msg);
997 				}
998 			} else if (crack[i].expected_str &&
999 				   (!r.out.ctr->ctr1->count ||
1000 				    !r.out.ctr->ctr1->array[0].result_name))
1001 			{
1002 				if (!r.out.ctr->ctr1->count) {
1003 					err_msg = talloc_asprintf(mem_ctx,
1004 								  "DsCrackNames failed - got 0 entries, expected %s on %s",
1005 								  crack[i].expected_str, comment);
1006 					torture_fail(tctx, err_msg);
1007 				} else {
1008 					err_msg = talloc_asprintf(mem_ctx,
1009 								  "DsCrackNames failed - got NULL pointer, expected %s on %s",
1010 								  crack[i].expected_str, comment);
1011 					torture_fail(tctx, err_msg);
1012 				}
1013 			} else if (crack[i].expected_str
1014 				   && (strcmp(r.out.ctr->ctr1->array[0].result_name,
1015 					      crack[i].expected_str) != 0))
1016 			{
1017 				if (strcasecmp(r.out.ctr->ctr1->array[0].result_name,
1018 					       crack[i].expected_str) != 0) {
1019 					err_msg = talloc_asprintf(mem_ctx,
1020 							"DsCrackNames failed - got %s, expected %s on %s",
1021 							r.out.ctr->ctr1->array[0].result_name,
1022 							crack[i].expected_str, comment);
1023 					torture_fail(tctx, err_msg);
1024 				} else {
1025 					torture_comment(tctx,
1026 							"(warning) DsCrackNames returned different case - got %s, expected %s on %s\n",
1027 							r.out.ctr->ctr1->array[0].result_name,
1028 							crack[i].expected_str, comment);
1029 				}
1030 			} else if (crack[i].expected_dns
1031 				   && (strcmp(r.out.ctr->ctr1->array[0].dns_domain_name,
1032 					      crack[i].expected_dns) != 0)) {
1033 				err_msg = talloc_asprintf(mem_ctx,
1034 						"DsCrackNames failed - got DNS name %s, expected %s on %s",
1035 						r.out.ctr->ctr1->array[0].result_name,
1036 						crack[i].expected_str, comment);
1037 				torture_fail(tctx, err_msg);
1038 			}
1039 
1040 		        torture_comment(tctx, "Testing DsCrackNames got %s\n", r.out.ctr->ctr1->array[0].result_name);
1041 		}
1042 	}
1043 
1044 	return test_DsCrackNamesMatrix(tctx, priv, FQDN_1779_name,
1045 					user_principal_name, service_principal_name);
1046 }
1047 
1048 /**
1049  * Test case setup for CrackNames
1050  */
1051 static bool torture_drsuapi_cracknames_setup(struct torture_context *tctx, void **data)
1052 {
1053 	struct DsCrackNamesPrivate *priv;
1054 
1055 	*data = priv = talloc_zero(tctx, struct DsCrackNamesPrivate);
1056 
1057 	return torture_drsuapi_tcase_setup_common(tctx, &priv->base);
1058 }
1059 
1060 /**
1061  * Test case tear-down for CrackNames
1062  */
1063 static bool torture_drsuapi_cracknames_teardown(struct torture_context *tctx, void *data)
1064 {
1065 	struct DsCrackNamesPrivate *priv = talloc_get_type(data, struct DsCrackNamesPrivate);
1066 
1067 	return torture_drsuapi_tcase_teardown_common(tctx, &priv->base);
1068 }
1069 
1070 /**
1071  * CRACKNAMES test suite implementation
1072  */
1073 void torture_rpc_drsuapi_cracknames_tcase(struct torture_suite *suite)
1074 {
1075 	typedef bool (*run_func) (struct torture_context *test, void *tcase_data);
1076 
1077 	struct torture_tcase *tcase = torture_suite_add_tcase(suite, "cracknames");
1078 
1079 	torture_tcase_set_fixture(tcase,
1080 				  torture_drsuapi_cracknames_setup,
1081 				  torture_drsuapi_cracknames_teardown);
1082 
1083 	torture_tcase_add_simple_test(tcase, "cracknames-test", (run_func)test_DsCrackNames);
1084 }
1085