• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source4/dsdb/schema/
1/*
2   Unix SMB/CIFS mplementation.
3   DSDB schema syntaxes
4
5   Copyright (C) Stefan Metzmacher <metze@samba.org> 2006
6   Copyright (C) Simo Sorce 2005
7   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 3 of the License, or
12   (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22*/
23#include "includes.h"
24#include "dsdb/samdb/samdb.h"
25#include "librpc/gen_ndr/ndr_drsuapi.h"
26#include "librpc/gen_ndr/ndr_security.h"
27#include "librpc/gen_ndr/ndr_misc.h"
28#include "lib/ldb/include/ldb.h"
29#include "lib/ldb/include/ldb_errors.h"
30#include "system/time.h"
31#include "../lib/util/charset/charset.h"
32#include "librpc/ndr/libndr.h"
33
34static WERROR dsdb_syntax_FOOBAR_drsuapi_to_ldb(struct ldb_context *ldb,
35						const struct dsdb_schema *schema,
36						const struct dsdb_attribute *attr,
37						const struct drsuapi_DsReplicaAttribute *in,
38						TALLOC_CTX *mem_ctx,
39						struct ldb_message_element *out)
40{
41	uint32_t i;
42
43	out->flags	= 0;
44	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
45	W_ERROR_HAVE_NO_MEMORY(out->name);
46
47	out->num_values	= in->value_ctr.num_values;
48	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
49	W_ERROR_HAVE_NO_MEMORY(out->values);
50
51	for (i=0; i < out->num_values; i++) {
52		char *str;
53
54		if (in->value_ctr.values[i].blob == NULL) {
55			return WERR_FOOBAR;
56		}
57
58		str = talloc_asprintf(out->values, "%s: not implemented",
59				      attr->syntax->name);
60		W_ERROR_HAVE_NO_MEMORY(str);
61
62		out->values[i] = data_blob_string_const(str);
63	}
64
65	return WERR_OK;
66}
67
68static WERROR dsdb_syntax_FOOBAR_ldb_to_drsuapi(struct ldb_context *ldb,
69						const struct dsdb_schema *schema,
70						const struct dsdb_attribute *attr,
71						const struct ldb_message_element *in,
72						TALLOC_CTX *mem_ctx,
73						struct drsuapi_DsReplicaAttribute *out)
74{
75	return WERR_FOOBAR;
76}
77
78static WERROR dsdb_syntax_BOOL_drsuapi_to_ldb(struct ldb_context *ldb,
79					      const struct dsdb_schema *schema,
80					      const struct dsdb_attribute *attr,
81					      const struct drsuapi_DsReplicaAttribute *in,
82					      TALLOC_CTX *mem_ctx,
83					      struct ldb_message_element *out)
84{
85	uint32_t i;
86
87	out->flags	= 0;
88	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
89	W_ERROR_HAVE_NO_MEMORY(out->name);
90
91	out->num_values	= in->value_ctr.num_values;
92	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
93	W_ERROR_HAVE_NO_MEMORY(out->values);
94
95	for (i=0; i < out->num_values; i++) {
96		uint32_t v;
97		char *str;
98
99		if (in->value_ctr.values[i].blob == NULL) {
100			return WERR_FOOBAR;
101		}
102
103		if (in->value_ctr.values[i].blob->length != 4) {
104			return WERR_FOOBAR;
105		}
106
107		v = IVAL(in->value_ctr.values[i].blob->data, 0);
108
109		if (v != 0) {
110			str = talloc_strdup(out->values, "TRUE");
111			W_ERROR_HAVE_NO_MEMORY(str);
112		} else {
113			str = talloc_strdup(out->values, "FALSE");
114			W_ERROR_HAVE_NO_MEMORY(str);
115		}
116
117		out->values[i] = data_blob_string_const(str);
118	}
119
120	return WERR_OK;
121}
122
123static WERROR dsdb_syntax_BOOL_ldb_to_drsuapi(struct ldb_context *ldb,
124					      const struct dsdb_schema *schema,
125					      const struct dsdb_attribute *attr,
126					      const struct ldb_message_element *in,
127					      TALLOC_CTX *mem_ctx,
128					      struct drsuapi_DsReplicaAttribute *out)
129{
130	uint32_t i;
131	DATA_BLOB *blobs;
132
133	if (attr->attributeID_id == 0xFFFFFFFF) {
134		return WERR_FOOBAR;
135	}
136
137	out->attid			= attr->attributeID_id;
138	out->value_ctr.num_values	= in->num_values;
139	out->value_ctr.values		= talloc_array(mem_ctx,
140						       struct drsuapi_DsAttributeValue,
141						       in->num_values);
142	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
143
144	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
145	W_ERROR_HAVE_NO_MEMORY(blobs);
146
147	for (i=0; i < in->num_values; i++) {
148		out->value_ctr.values[i].blob	= &blobs[i];
149
150		blobs[i] = data_blob_talloc(blobs, NULL, 4);
151		W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
152
153		if (strcmp("TRUE", (const char *)in->values[i].data) == 0) {
154			SIVAL(blobs[i].data, 0, 0x00000001);
155		} else if (strcmp("FALSE", (const char *)in->values[i].data) == 0) {
156			SIVAL(blobs[i].data, 0, 0x00000000);
157		} else {
158			return WERR_FOOBAR;
159		}
160	}
161
162	return WERR_OK;
163}
164
165static WERROR dsdb_syntax_INT32_drsuapi_to_ldb(struct ldb_context *ldb,
166					       const struct dsdb_schema *schema,
167					       const struct dsdb_attribute *attr,
168					       const struct drsuapi_DsReplicaAttribute *in,
169					       TALLOC_CTX *mem_ctx,
170					       struct ldb_message_element *out)
171{
172	uint32_t i;
173
174	out->flags	= 0;
175	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
176	W_ERROR_HAVE_NO_MEMORY(out->name);
177
178	out->num_values	= in->value_ctr.num_values;
179	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
180	W_ERROR_HAVE_NO_MEMORY(out->values);
181
182	for (i=0; i < out->num_values; i++) {
183		int32_t v;
184		char *str;
185
186		if (in->value_ctr.values[i].blob == NULL) {
187			return WERR_FOOBAR;
188		}
189
190		if (in->value_ctr.values[i].blob->length != 4) {
191			return WERR_FOOBAR;
192		}
193
194		v = IVALS(in->value_ctr.values[i].blob->data, 0);
195
196		str = talloc_asprintf(out->values, "%d", v);
197		W_ERROR_HAVE_NO_MEMORY(str);
198
199		out->values[i] = data_blob_string_const(str);
200	}
201
202	return WERR_OK;
203}
204
205static WERROR dsdb_syntax_INT32_ldb_to_drsuapi(struct ldb_context *ldb,
206					       const struct dsdb_schema *schema,
207					       const struct dsdb_attribute *attr,
208					       const struct ldb_message_element *in,
209					       TALLOC_CTX *mem_ctx,
210					       struct drsuapi_DsReplicaAttribute *out)
211{
212	uint32_t i;
213	DATA_BLOB *blobs;
214
215	if (attr->attributeID_id == 0xFFFFFFFF) {
216		return WERR_FOOBAR;
217	}
218
219	out->attid			= attr->attributeID_id;
220	out->value_ctr.num_values	= in->num_values;
221	out->value_ctr.values		= talloc_array(mem_ctx,
222						       struct drsuapi_DsAttributeValue,
223						       in->num_values);
224	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
225
226	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
227	W_ERROR_HAVE_NO_MEMORY(blobs);
228
229	for (i=0; i < in->num_values; i++) {
230		int32_t v;
231
232		out->value_ctr.values[i].blob	= &blobs[i];
233
234		blobs[i] = data_blob_talloc(blobs, NULL, 4);
235		W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
236
237		/* We've to use "strtoll" here to have the intended overflows.
238		 * Otherwise we may get "LONG_MAX" and the conversion is wrong. */
239		v = (int32_t) strtoll((char *)in->values[i].data, NULL, 0);
240
241		SIVALS(blobs[i].data, 0, v);
242	}
243
244	return WERR_OK;
245}
246
247static WERROR dsdb_syntax_INT64_drsuapi_to_ldb(struct ldb_context *ldb,
248					       const struct dsdb_schema *schema,
249					       const struct dsdb_attribute *attr,
250					       const struct drsuapi_DsReplicaAttribute *in,
251					       TALLOC_CTX *mem_ctx,
252					       struct ldb_message_element *out)
253{
254	uint32_t i;
255
256	out->flags	= 0;
257	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
258	W_ERROR_HAVE_NO_MEMORY(out->name);
259
260	out->num_values	= in->value_ctr.num_values;
261	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
262	W_ERROR_HAVE_NO_MEMORY(out->values);
263
264	for (i=0; i < out->num_values; i++) {
265		int64_t v;
266		char *str;
267
268		if (in->value_ctr.values[i].blob == NULL) {
269			return WERR_FOOBAR;
270		}
271
272		if (in->value_ctr.values[i].blob->length != 8) {
273			return WERR_FOOBAR;
274		}
275
276		v = BVALS(in->value_ctr.values[i].blob->data, 0);
277
278		str = talloc_asprintf(out->values, "%lld", (long long int)v);
279		W_ERROR_HAVE_NO_MEMORY(str);
280
281		out->values[i] = data_blob_string_const(str);
282	}
283
284	return WERR_OK;
285}
286
287static WERROR dsdb_syntax_INT64_ldb_to_drsuapi(struct ldb_context *ldb,
288					       const struct dsdb_schema *schema,
289					       const struct dsdb_attribute *attr,
290					       const struct ldb_message_element *in,
291					       TALLOC_CTX *mem_ctx,
292					       struct drsuapi_DsReplicaAttribute *out)
293{
294	uint32_t i;
295	DATA_BLOB *blobs;
296
297	if (attr->attributeID_id == 0xFFFFFFFF) {
298		return WERR_FOOBAR;
299	}
300
301	out->attid			= attr->attributeID_id;
302	out->value_ctr.num_values	= in->num_values;
303	out->value_ctr.values		= talloc_array(mem_ctx,
304						       struct drsuapi_DsAttributeValue,
305						       in->num_values);
306	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
307
308	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
309	W_ERROR_HAVE_NO_MEMORY(blobs);
310
311	for (i=0; i < in->num_values; i++) {
312		int64_t v;
313
314		out->value_ctr.values[i].blob	= &blobs[i];
315
316		blobs[i] = data_blob_talloc(blobs, NULL, 8);
317		W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
318
319		v = strtoll((const char *)in->values[i].data, NULL, 10);
320
321		SBVALS(blobs[i].data, 0, v);
322	}
323
324	return WERR_OK;
325}
326
327static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(struct ldb_context *ldb,
328						    const struct dsdb_schema *schema,
329						    const struct dsdb_attribute *attr,
330						    const struct drsuapi_DsReplicaAttribute *in,
331						    TALLOC_CTX *mem_ctx,
332						    struct ldb_message_element *out)
333{
334	uint32_t i;
335
336	out->flags	= 0;
337	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
338	W_ERROR_HAVE_NO_MEMORY(out->name);
339
340	out->num_values	= in->value_ctr.num_values;
341	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
342	W_ERROR_HAVE_NO_MEMORY(out->values);
343
344	for (i=0; i < out->num_values; i++) {
345		NTTIME v;
346		time_t t;
347		char *str;
348
349		if (in->value_ctr.values[i].blob == NULL) {
350			return WERR_FOOBAR;
351		}
352
353		if (in->value_ctr.values[i].blob->length != 8) {
354			return WERR_FOOBAR;
355		}
356
357		v = BVAL(in->value_ctr.values[i].blob->data, 0);
358		v *= 10000000;
359		t = nt_time_to_unix(v);
360
361		/*
362		 * NOTE: On a w2k3 server you can set a GeneralizedTime string
363		 *       via LDAP, but you get back an UTCTime string,
364		 *       but via DRSUAPI you get back the NTTIME_1sec value
365		 *       that represents the GeneralizedTime value!
366		 *
367		 *       So if we store the UTCTime string in our ldb
368		 *       we'll loose information!
369		 */
370		str = ldb_timestring_utc(out->values, t);
371		W_ERROR_HAVE_NO_MEMORY(str);
372		out->values[i] = data_blob_string_const(str);
373	}
374
375	return WERR_OK;
376}
377
378static WERROR dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi(struct ldb_context *ldb,
379						    const struct dsdb_schema *schema,
380						    const struct dsdb_attribute *attr,
381						    const struct ldb_message_element *in,
382						    TALLOC_CTX *mem_ctx,
383						    struct drsuapi_DsReplicaAttribute *out)
384{
385	uint32_t i;
386	DATA_BLOB *blobs;
387
388	if (attr->attributeID_id == 0xFFFFFFFF) {
389		return WERR_FOOBAR;
390	}
391
392	out->attid			= attr->attributeID_id;
393	out->value_ctr.num_values	= in->num_values;
394	out->value_ctr.values		= talloc_array(mem_ctx,
395						       struct drsuapi_DsAttributeValue,
396						       in->num_values);
397	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
398
399	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
400	W_ERROR_HAVE_NO_MEMORY(blobs);
401
402	for (i=0; i < in->num_values; i++) {
403		NTTIME v;
404		time_t t;
405
406		out->value_ctr.values[i].blob	= &blobs[i];
407
408		blobs[i] = data_blob_talloc(blobs, NULL, 8);
409		W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
410
411		t = ldb_string_utc_to_time((const char *)in->values[i].data);
412		unix_to_nt_time(&v, t);
413		v /= 10000000;
414
415		SBVAL(blobs[i].data, 0, v);
416	}
417
418	return WERR_OK;
419}
420
421static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(struct ldb_context *ldb,
422						const struct dsdb_schema *schema,
423						const struct dsdb_attribute *attr,
424						const struct drsuapi_DsReplicaAttribute *in,
425						TALLOC_CTX *mem_ctx,
426						struct ldb_message_element *out)
427{
428	uint32_t i;
429
430	out->flags	= 0;
431	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
432	W_ERROR_HAVE_NO_MEMORY(out->name);
433
434	out->num_values	= in->value_ctr.num_values;
435	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
436	W_ERROR_HAVE_NO_MEMORY(out->values);
437
438	for (i=0; i < out->num_values; i++) {
439		NTTIME v;
440		time_t t;
441		char *str;
442
443		if (in->value_ctr.values[i].blob == NULL) {
444			return WERR_FOOBAR;
445		}
446
447		if (in->value_ctr.values[i].blob->length != 8) {
448			return WERR_FOOBAR;
449		}
450
451		v = BVAL(in->value_ctr.values[i].blob->data, 0);
452		v *= 10000000;
453		t = nt_time_to_unix(v);
454
455		str = ldb_timestring(out->values, t);
456		W_ERROR_HAVE_NO_MEMORY(str);
457
458		out->values[i] = data_blob_string_const(str);
459	}
460
461	return WERR_OK;
462}
463
464static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(struct ldb_context *ldb,
465						const struct dsdb_schema *schema,
466						const struct dsdb_attribute *attr,
467						const struct ldb_message_element *in,
468						TALLOC_CTX *mem_ctx,
469						struct drsuapi_DsReplicaAttribute *out)
470{
471	uint32_t i;
472	DATA_BLOB *blobs;
473
474	if (attr->attributeID_id == 0xFFFFFFFF) {
475		return WERR_FOOBAR;
476	}
477
478	out->attid			= attr->attributeID_id;
479	out->value_ctr.num_values	= in->num_values;
480	out->value_ctr.values		= talloc_array(mem_ctx,
481						       struct drsuapi_DsAttributeValue,
482						       in->num_values);
483	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
484
485	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
486	W_ERROR_HAVE_NO_MEMORY(blobs);
487
488	for (i=0; i < in->num_values; i++) {
489		NTTIME v;
490		time_t t;
491
492		out->value_ctr.values[i].blob	= &blobs[i];
493
494		blobs[i] = data_blob_talloc(blobs, NULL, 8);
495		W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
496
497		t = ldb_string_to_time((const char *)in->values[i].data);
498		unix_to_nt_time(&v, t);
499		v /= 10000000;
500
501		SBVAL(blobs[i].data, 0, v);
502	}
503
504	return WERR_OK;
505}
506
507static WERROR dsdb_syntax_DATA_BLOB_drsuapi_to_ldb(struct ldb_context *ldb,
508						   const struct dsdb_schema *schema,
509						   const struct dsdb_attribute *attr,
510						   const struct drsuapi_DsReplicaAttribute *in,
511						   TALLOC_CTX *mem_ctx,
512						   struct ldb_message_element *out)
513{
514	uint32_t i;
515
516	out->flags	= 0;
517	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
518	W_ERROR_HAVE_NO_MEMORY(out->name);
519
520	out->num_values	= in->value_ctr.num_values;
521	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
522	W_ERROR_HAVE_NO_MEMORY(out->values);
523
524	for (i=0; i < out->num_values; i++) {
525		if (in->value_ctr.values[i].blob == NULL) {
526			return WERR_FOOBAR;
527		}
528
529		if (in->value_ctr.values[i].blob->length == 0) {
530			return WERR_FOOBAR;
531		}
532
533		out->values[i] = data_blob_dup_talloc(out->values,
534						      in->value_ctr.values[i].blob);
535		W_ERROR_HAVE_NO_MEMORY(out->values[i].data);
536	}
537
538	return WERR_OK;
539}
540
541static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(struct ldb_context *ldb,
542						   const struct dsdb_schema *schema,
543						   const struct dsdb_attribute *attr,
544						   const struct ldb_message_element *in,
545						   TALLOC_CTX *mem_ctx,
546						   struct drsuapi_DsReplicaAttribute *out)
547{
548	uint32_t i;
549	DATA_BLOB *blobs;
550
551	if (attr->attributeID_id == 0xFFFFFFFF) {
552		return WERR_FOOBAR;
553	}
554
555	out->attid			= attr->attributeID_id;
556	out->value_ctr.num_values	= in->num_values;
557	out->value_ctr.values		= talloc_array(mem_ctx,
558						       struct drsuapi_DsAttributeValue,
559						       in->num_values);
560	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
561
562	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
563	W_ERROR_HAVE_NO_MEMORY(blobs);
564
565	for (i=0; i < in->num_values; i++) {
566		out->value_ctr.values[i].blob	= &blobs[i];
567
568		blobs[i] = data_blob_dup_talloc(blobs, &in->values[i]);
569		W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
570	}
571
572	return WERR_OK;
573}
574
575static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(struct ldb_context *ldb,
576						  const struct dsdb_schema *schema,
577						  const struct dsdb_attribute *attr,
578						  const struct drsuapi_DsReplicaAttribute *in,
579						  TALLOC_CTX *mem_ctx,
580						  struct ldb_message_element *out)
581{
582	uint32_t i;
583
584	out->flags	= 0;
585	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
586	W_ERROR_HAVE_NO_MEMORY(out->name);
587
588	out->num_values	= in->value_ctr.num_values;
589	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
590	W_ERROR_HAVE_NO_MEMORY(out->values);
591
592	for (i=0; i < out->num_values; i++) {
593		uint32_t v;
594		const struct dsdb_class *c;
595		const char *str;
596
597		if (in->value_ctr.values[i].blob == NULL) {
598			return WERR_FOOBAR;
599		}
600
601		if (in->value_ctr.values[i].blob->length != 4) {
602			return WERR_FOOBAR;
603		}
604
605		v = IVAL(in->value_ctr.values[i].blob->data, 0);
606
607		c = dsdb_class_by_governsID_id(schema, v);
608		if (!c) {
609			return WERR_FOOBAR;
610		}
611
612		str = talloc_strdup(out->values, c->lDAPDisplayName);
613		W_ERROR_HAVE_NO_MEMORY(str);
614
615		/* the values need to be reversed */
616		out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
617	}
618
619	return WERR_OK;
620}
621
622static WERROR _dsdb_syntax_OID_attr_drsuapi_to_ldb(struct ldb_context *ldb,
623						   const struct dsdb_schema *schema,
624						   const struct dsdb_attribute *attr,
625						   const struct drsuapi_DsReplicaAttribute *in,
626						   TALLOC_CTX *mem_ctx,
627						   struct ldb_message_element *out)
628{
629	uint32_t i;
630
631	out->flags	= 0;
632	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
633	W_ERROR_HAVE_NO_MEMORY(out->name);
634
635	out->num_values	= in->value_ctr.num_values;
636	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
637	W_ERROR_HAVE_NO_MEMORY(out->values);
638
639	for (i=0; i < out->num_values; i++) {
640		uint32_t v;
641		const struct dsdb_attribute *a;
642		const char *str;
643
644		if (in->value_ctr.values[i].blob == NULL) {
645			return WERR_FOOBAR;
646		}
647
648		if (in->value_ctr.values[i].blob->length != 4) {
649			return WERR_FOOBAR;
650		}
651
652		v = IVAL(in->value_ctr.values[i].blob->data, 0);
653
654		a = dsdb_attribute_by_attributeID_id(schema, v);
655		if (!a) {
656			return WERR_FOOBAR;
657		}
658
659		str = talloc_strdup(out->values, a->lDAPDisplayName);
660		W_ERROR_HAVE_NO_MEMORY(str);
661
662		/* the values need to be reversed */
663		out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
664	}
665
666	return WERR_OK;
667}
668
669static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(struct ldb_context *ldb,
670						  const struct dsdb_schema *schema,
671						  const struct dsdb_attribute *attr,
672						  const struct drsuapi_DsReplicaAttribute *in,
673						  TALLOC_CTX *mem_ctx,
674						  struct ldb_message_element *out)
675{
676	uint32_t i;
677
678	out->flags	= 0;
679	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
680	W_ERROR_HAVE_NO_MEMORY(out->name);
681
682	out->num_values	= in->value_ctr.num_values;
683	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
684	W_ERROR_HAVE_NO_MEMORY(out->values);
685
686	for (i=0; i < out->num_values; i++) {
687		uint32_t v;
688		WERROR status;
689		const char *str;
690
691		if (in->value_ctr.values[i].blob == NULL) {
692			return WERR_FOOBAR;
693		}
694
695		if (in->value_ctr.values[i].blob->length != 4) {
696			return WERR_FOOBAR;
697		}
698
699		v = IVAL(in->value_ctr.values[i].blob->data, 0);
700
701		status = dsdb_map_int2oid(schema, v, out->values, &str);
702		W_ERROR_NOT_OK_RETURN(status);
703
704		out->values[i] = data_blob_string_const(str);
705	}
706
707	return WERR_OK;
708}
709
710static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(struct ldb_context *ldb,
711						  const struct dsdb_schema *schema,
712						  const struct dsdb_attribute *attr,
713						  const struct ldb_message_element *in,
714						  TALLOC_CTX *mem_ctx,
715						  struct drsuapi_DsReplicaAttribute *out)
716{
717        uint32_t i;
718        DATA_BLOB *blobs;
719
720        out->attid= attr->attributeID_id;
721        out->value_ctr.num_values= in->num_values;
722        out->value_ctr.values= talloc_array(mem_ctx,
723                                            struct drsuapi_DsAttributeValue,
724                                            in->num_values);
725        W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
726
727        blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
728        W_ERROR_HAVE_NO_MEMORY(blobs);
729
730        for (i=0; i < in->num_values; i++) {
731		const struct dsdb_class *obj_class;
732
733		out->value_ctr.values[i].blob= &blobs[i];
734
735		blobs[i] = data_blob_talloc(blobs, NULL, 4);
736		W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
737
738		obj_class = dsdb_class_by_lDAPDisplayName(schema, (const char *)in->values[i].data);
739		if (!obj_class) {
740			return WERR_FOOBAR;
741		}
742		SIVAL(blobs[i].data, 0, obj_class->governsID_id);
743        }
744
745
746        return WERR_OK;
747}
748
749static WERROR _dsdb_syntax_OID_attr_ldb_to_drsuapi(struct ldb_context *ldb,
750						   const struct dsdb_schema *schema,
751						   const struct dsdb_attribute *attr,
752						   const struct ldb_message_element *in,
753						   TALLOC_CTX *mem_ctx,
754						   struct drsuapi_DsReplicaAttribute *out)
755{
756        uint32_t i;
757        DATA_BLOB *blobs;
758
759        out->attid= attr->attributeID_id;
760        out->value_ctr.num_values= in->num_values;
761        out->value_ctr.values= talloc_array(mem_ctx,
762                                            struct drsuapi_DsAttributeValue,
763                                            in->num_values);
764        W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
765
766        blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
767        W_ERROR_HAVE_NO_MEMORY(blobs);
768
769        for (i=0; i < in->num_values; i++) {
770		const struct dsdb_attribute *obj_attr;
771
772		out->value_ctr.values[i].blob= &blobs[i];
773
774		blobs[i] = data_blob_talloc(blobs, NULL, 4);
775		W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
776
777		obj_attr = dsdb_attribute_by_lDAPDisplayName(schema, (const char *)in->values[i].data);
778		if (!obj_attr) {
779			return WERR_FOOBAR;
780		}
781		SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
782        }
783
784
785        return WERR_OK;
786}
787
788static WERROR _dsdb_syntax_OID_oid_ldb_to_drsuapi(struct ldb_context *ldb,
789						  const struct dsdb_schema *schema,
790						  const struct dsdb_attribute *attr,
791						  const struct ldb_message_element *in,
792						  TALLOC_CTX *mem_ctx,
793						  struct drsuapi_DsReplicaAttribute *out)
794{
795	uint32_t i;
796	DATA_BLOB *blobs;
797
798	out->attid= attr->attributeID_id;
799	out->value_ctr.num_values= in->num_values;
800	out->value_ctr.values= talloc_array(mem_ctx,
801					    struct drsuapi_DsAttributeValue,
802					    in->num_values);
803	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
804
805	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
806	W_ERROR_HAVE_NO_MEMORY(blobs);
807
808	for (i=0; i < in->num_values; i++) {
809		uint32_t v;
810		WERROR status;
811
812		out->value_ctr.values[i].blob= &blobs[i];
813
814		blobs[i] = data_blob_talloc(blobs, NULL, 4);
815		W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
816
817		status = dsdb_map_oid2int(schema,
818					  (const char *)in->values[i].data,
819					  &v);
820		W_ERROR_NOT_OK_RETURN(status);
821
822		SIVAL(blobs[i].data, 0, v);
823	}
824
825	return WERR_OK;
826}
827
828static WERROR dsdb_syntax_OID_drsuapi_to_ldb(struct ldb_context *ldb,
829					     const struct dsdb_schema *schema,
830					     const struct dsdb_attribute *attr,
831					     const struct drsuapi_DsReplicaAttribute *in,
832					     TALLOC_CTX *mem_ctx,
833					     struct ldb_message_element *out)
834{
835	uint32_t i;
836
837	switch (attr->attributeID_id) {
838	case DRSUAPI_ATTRIBUTE_objectClass:
839	case DRSUAPI_ATTRIBUTE_subClassOf:
840	case DRSUAPI_ATTRIBUTE_auxiliaryClass:
841	case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
842	case DRSUAPI_ATTRIBUTE_possSuperiors:
843		return _dsdb_syntax_OID_obj_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
844	case DRSUAPI_ATTRIBUTE_systemMustContain:
845	case DRSUAPI_ATTRIBUTE_systemMayContain:
846	case DRSUAPI_ATTRIBUTE_mustContain:
847	case DRSUAPI_ATTRIBUTE_mayContain:
848		return _dsdb_syntax_OID_attr_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
849	case DRSUAPI_ATTRIBUTE_governsID:
850	case DRSUAPI_ATTRIBUTE_attributeID:
851	case DRSUAPI_ATTRIBUTE_attributeSyntax:
852		return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
853	}
854
855	out->flags	= 0;
856	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
857	W_ERROR_HAVE_NO_MEMORY(out->name);
858
859	out->num_values	= in->value_ctr.num_values;
860	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
861	W_ERROR_HAVE_NO_MEMORY(out->values);
862
863	for (i=0; i < out->num_values; i++) {
864		uint32_t v;
865		const char *name;
866		char *str;
867
868		if (in->value_ctr.values[i].blob == NULL) {
869			return WERR_FOOBAR;
870		}
871
872		if (in->value_ctr.values[i].blob->length != 4) {
873			return WERR_FOOBAR;
874		}
875
876		v = IVAL(in->value_ctr.values[i].blob->data, 0);
877
878		name = dsdb_lDAPDisplayName_by_id(schema, v);
879		if (!name) {
880			return WERR_FOOBAR;
881		}
882
883		str = talloc_strdup(out->values, name);
884		W_ERROR_HAVE_NO_MEMORY(str);
885
886		out->values[i] = data_blob_string_const(str);
887	}
888
889	return WERR_OK;
890}
891
892static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb,
893					     const struct dsdb_schema *schema,
894					     const struct dsdb_attribute *attr,
895					     const struct ldb_message_element *in,
896					     TALLOC_CTX *mem_ctx,
897					     struct drsuapi_DsReplicaAttribute *out)
898{
899	uint32_t i;
900	DATA_BLOB *blobs;
901
902	if (attr->attributeID_id == 0xFFFFFFFF) {
903		return WERR_FOOBAR;
904	}
905
906	switch (attr->attributeID_id) {
907	case DRSUAPI_ATTRIBUTE_objectClass:
908	case DRSUAPI_ATTRIBUTE_subClassOf:
909	case DRSUAPI_ATTRIBUTE_auxiliaryClass:
910	case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
911	case DRSUAPI_ATTRIBUTE_possSuperiors:
912		return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
913	case DRSUAPI_ATTRIBUTE_systemMustContain:
914	case DRSUAPI_ATTRIBUTE_systemMayContain:
915	case DRSUAPI_ATTRIBUTE_mustContain:
916	case DRSUAPI_ATTRIBUTE_mayContain:
917		return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
918	case DRSUAPI_ATTRIBUTE_governsID:
919	case DRSUAPI_ATTRIBUTE_attributeID:
920	case DRSUAPI_ATTRIBUTE_attributeSyntax:
921		return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
922	}
923
924	out->attid			= attr->attributeID_id;
925	out->value_ctr.num_values	= in->num_values;
926	out->value_ctr.values		= talloc_array(mem_ctx,
927						       struct drsuapi_DsAttributeValue,
928						       in->num_values);
929	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
930
931	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
932	W_ERROR_HAVE_NO_MEMORY(blobs);
933
934	for (i=0; i < in->num_values; i++) {
935		uint32_t v;
936
937		out->value_ctr.values[i].blob	= &blobs[i];
938
939		blobs[i] = data_blob_talloc(blobs, NULL, 4);
940		W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
941
942		v = strtol((const char *)in->values[i].data, NULL, 10);
943
944		SIVAL(blobs[i].data, 0, v);
945	}
946
947	return WERR_OK;
948}
949
950static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(struct ldb_context *ldb,
951						 const struct dsdb_schema *schema,
952						 const struct dsdb_attribute *attr,
953						 const struct drsuapi_DsReplicaAttribute *in,
954						 TALLOC_CTX *mem_ctx,
955						 struct ldb_message_element *out)
956{
957	uint32_t i;
958
959	out->flags	= 0;
960	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
961	W_ERROR_HAVE_NO_MEMORY(out->name);
962
963	out->num_values	= in->value_ctr.num_values;
964	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
965	W_ERROR_HAVE_NO_MEMORY(out->values);
966
967	for (i=0; i < out->num_values; i++) {
968		char *str;
969
970		if (in->value_ctr.values[i].blob == NULL) {
971			return WERR_FOOBAR;
972		}
973
974		if (in->value_ctr.values[i].blob->length == 0) {
975			return WERR_FOOBAR;
976		}
977
978		if (!convert_string_talloc_convenience(out->values,
979						schema->iconv_convenience,
980									CH_UTF16, CH_UNIX,
981					    in->value_ctr.values[i].blob->data,
982					    in->value_ctr.values[i].blob->length,
983					    (void **)&str, NULL, false)) {
984			return WERR_FOOBAR;
985		}
986
987		out->values[i] = data_blob_string_const(str);
988	}
989
990	return WERR_OK;
991}
992
993static WERROR dsdb_syntax_UNICODE_ldb_to_drsuapi(struct ldb_context *ldb,
994						 const struct dsdb_schema *schema,
995						 const struct dsdb_attribute *attr,
996						 const struct ldb_message_element *in,
997						 TALLOC_CTX *mem_ctx,
998						 struct drsuapi_DsReplicaAttribute *out)
999{
1000	uint32_t i;
1001	DATA_BLOB *blobs;
1002
1003	if (attr->attributeID_id == 0xFFFFFFFF) {
1004		return WERR_FOOBAR;
1005	}
1006
1007	out->attid			= attr->attributeID_id;
1008	out->value_ctr.num_values	= in->num_values;
1009	out->value_ctr.values		= talloc_array(mem_ctx,
1010						       struct drsuapi_DsAttributeValue,
1011						       in->num_values);
1012	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1013
1014	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1015	W_ERROR_HAVE_NO_MEMORY(blobs);
1016
1017	for (i=0; i < in->num_values; i++) {
1018		out->value_ctr.values[i].blob	= &blobs[i];
1019
1020		if (!convert_string_talloc_convenience(blobs,
1021			schema->iconv_convenience, CH_UNIX, CH_UTF16,
1022			in->values[i].data, in->values[i].length,
1023			(void **)&blobs[i].data, &blobs[i].length, false)) {
1024				return WERR_FOOBAR;
1025		}
1026	}
1027
1028	return WERR_OK;
1029}
1030
1031static WERROR dsdb_syntax_DN_drsuapi_to_ldb(struct ldb_context *ldb,
1032					    const struct dsdb_schema *schema,
1033					    const struct dsdb_attribute *attr,
1034					    const struct drsuapi_DsReplicaAttribute *in,
1035					    TALLOC_CTX *mem_ctx,
1036					    struct ldb_message_element *out)
1037{
1038	uint32_t i;
1039	int ret;
1040
1041	out->flags	= 0;
1042	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1043	W_ERROR_HAVE_NO_MEMORY(out->name);
1044
1045	out->num_values	= in->value_ctr.num_values;
1046	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
1047	W_ERROR_HAVE_NO_MEMORY(out->values);
1048
1049	for (i=0; i < out->num_values; i++) {
1050		struct drsuapi_DsReplicaObjectIdentifier3 id3;
1051		enum ndr_err_code ndr_err;
1052		DATA_BLOB guid_blob;
1053		struct ldb_dn *dn;
1054		TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1055		if (!tmp_ctx) {
1056			W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1057		}
1058
1059		if (in->value_ctr.values[i].blob == NULL) {
1060			talloc_free(tmp_ctx);
1061			return WERR_FOOBAR;
1062		}
1063
1064		if (in->value_ctr.values[i].blob->length == 0) {
1065			talloc_free(tmp_ctx);
1066			return WERR_FOOBAR;
1067		}
1068
1069
1070		/* windows sometimes sends an extra two pad bytes here */
1071		ndr_err = ndr_pull_struct_blob(in->value_ctr.values[i].blob,
1072					       tmp_ctx, schema->iconv_convenience, &id3,
1073					       (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3);
1074		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1075			NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1076			talloc_free(tmp_ctx);
1077			return ntstatus_to_werror(status);
1078		}
1079
1080		dn = ldb_dn_new(tmp_ctx, ldb, id3.dn);
1081		if (!dn) {
1082			talloc_free(tmp_ctx);
1083			/* If this fails, it must be out of memory, as it does not do much parsing */
1084			W_ERROR_HAVE_NO_MEMORY(dn);
1085		}
1086
1087		ndr_err = ndr_push_struct_blob(&guid_blob, tmp_ctx, schema->iconv_convenience, &id3.guid,
1088					       (ndr_push_flags_fn_t)ndr_push_GUID);
1089		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1090			NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1091			talloc_free(tmp_ctx);
1092			return ntstatus_to_werror(status);
1093		}
1094
1095		ret = ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
1096		if (ret != LDB_SUCCESS) {
1097			talloc_free(tmp_ctx);
1098			return WERR_FOOBAR;
1099		}
1100
1101		talloc_free(guid_blob.data);
1102
1103		if (id3.__ndr_size_sid) {
1104			DATA_BLOB sid_blob;
1105			ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, schema->iconv_convenience, &id3.sid,
1106						       (ndr_push_flags_fn_t)ndr_push_dom_sid);
1107			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1108				NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1109				talloc_free(tmp_ctx);
1110				return ntstatus_to_werror(status);
1111			}
1112
1113			ret = ldb_dn_set_extended_component(dn, "SID", &sid_blob);
1114			if (ret != LDB_SUCCESS) {
1115				talloc_free(tmp_ctx);
1116				return WERR_FOOBAR;
1117			}
1118		}
1119
1120		out->values[i] = data_blob_string_const(ldb_dn_get_extended_linearized(out->values, dn, 1));
1121		talloc_free(tmp_ctx);
1122	}
1123
1124	return WERR_OK;
1125}
1126
1127static WERROR dsdb_syntax_DN_ldb_to_drsuapi(struct ldb_context *ldb,
1128					    const struct dsdb_schema *schema,
1129					    const struct dsdb_attribute *attr,
1130					    const struct ldb_message_element *in,
1131					    TALLOC_CTX *mem_ctx,
1132					    struct drsuapi_DsReplicaAttribute *out)
1133{
1134	uint32_t i;
1135	DATA_BLOB *blobs;
1136
1137	if (attr->attributeID_id == 0xFFFFFFFF) {
1138		return WERR_FOOBAR;
1139	}
1140
1141	out->attid			= attr->attributeID_id;
1142	out->value_ctr.num_values	= in->num_values;
1143	out->value_ctr.values		= talloc_array(mem_ctx,
1144						       struct drsuapi_DsAttributeValue,
1145						       in->num_values);
1146	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1147
1148	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1149	W_ERROR_HAVE_NO_MEMORY(blobs);
1150
1151	for (i=0; i < in->num_values; i++) {
1152		struct drsuapi_DsReplicaObjectIdentifier3 id3;
1153		enum ndr_err_code ndr_err;
1154		const DATA_BLOB *guid_blob, *sid_blob;
1155		struct ldb_dn *dn;
1156		TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1157		W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1158
1159		out->value_ctr.values[i].blob	= &blobs[i];
1160
1161		dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &in->values[i]);
1162
1163		W_ERROR_HAVE_NO_MEMORY(dn);
1164
1165		guid_blob = ldb_dn_get_extended_component(dn, "GUID");
1166
1167		ZERO_STRUCT(id3);
1168
1169		if (guid_blob) {
1170			ndr_err = ndr_pull_struct_blob_all(guid_blob,
1171							   tmp_ctx, schema->iconv_convenience, &id3.guid,
1172							   (ndr_pull_flags_fn_t)ndr_pull_GUID);
1173			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1174				NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1175				talloc_free(tmp_ctx);
1176				return ntstatus_to_werror(status);
1177			}
1178		}
1179
1180		sid_blob = ldb_dn_get_extended_component(dn, "SID");
1181		if (sid_blob) {
1182
1183			ndr_err = ndr_pull_struct_blob_all(sid_blob,
1184							   tmp_ctx, schema->iconv_convenience, &id3.sid,
1185							   (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1186			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1187				NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1188				talloc_free(tmp_ctx);
1189				return ntstatus_to_werror(status);
1190			}
1191		}
1192
1193		id3.dn = ldb_dn_get_linearized(dn);
1194
1195		ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3, (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3);
1196		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1197			NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1198			talloc_free(tmp_ctx);
1199			return ntstatus_to_werror(status);
1200		}
1201		talloc_free(tmp_ctx);
1202	}
1203
1204	return WERR_OK;
1205}
1206
1207static WERROR dsdb_syntax_DN_BINARY_drsuapi_to_ldb(struct ldb_context *ldb,
1208						   const struct dsdb_schema *schema,
1209						   const struct dsdb_attribute *attr,
1210						   const struct drsuapi_DsReplicaAttribute *in,
1211						   TALLOC_CTX *mem_ctx,
1212						   struct ldb_message_element *out)
1213{
1214	uint32_t i;
1215
1216	out->flags	= 0;
1217	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1218	W_ERROR_HAVE_NO_MEMORY(out->name);
1219
1220	out->num_values	= in->value_ctr.num_values;
1221	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
1222	W_ERROR_HAVE_NO_MEMORY(out->values);
1223
1224	for (i=0; i < out->num_values; i++) {
1225		struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
1226		char *binary;
1227		char *str;
1228		enum ndr_err_code ndr_err;
1229
1230		if (in->value_ctr.values[i].blob == NULL) {
1231			return WERR_FOOBAR;
1232		}
1233
1234		if (in->value_ctr.values[i].blob->length == 0) {
1235			return WERR_FOOBAR;
1236		}
1237
1238		ndr_err = ndr_pull_struct_blob_all(in->value_ctr.values[i].blob,
1239						   out->values, schema->iconv_convenience, &id3b,
1240						   (ndr_pull_flags_fn_t)ndr_pull_drsuapi_DsReplicaObjectIdentifier3Binary);
1241		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1242			NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1243			return ntstatus_to_werror(status);
1244		}
1245
1246		/* TODO: handle id3.guid and id3.sid */
1247		binary = data_blob_hex_string(out->values, &id3b.binary);
1248		W_ERROR_HAVE_NO_MEMORY(binary);
1249
1250		str = talloc_asprintf(out->values, "B:%u:%s:%s",
1251				      (unsigned int)(id3b.binary.length * 2), /* because of 2 hex chars per byte */
1252				      binary,
1253				      id3b.dn);
1254		W_ERROR_HAVE_NO_MEMORY(str);
1255
1256		/* TODO: handle id3.guid and id3.sid */
1257		out->values[i] = data_blob_string_const(str);
1258	}
1259
1260	return WERR_OK;
1261}
1262
1263static WERROR dsdb_syntax_DN_BINARY_ldb_to_drsuapi(struct ldb_context *ldb,
1264						   const struct dsdb_schema *schema,
1265						   const struct dsdb_attribute *attr,
1266						   const struct ldb_message_element *in,
1267						   TALLOC_CTX *mem_ctx,
1268						   struct drsuapi_DsReplicaAttribute *out)
1269{
1270	uint32_t i;
1271	DATA_BLOB *blobs;
1272
1273	if (attr->attributeID_id == 0xFFFFFFFF) {
1274		return WERR_FOOBAR;
1275	}
1276
1277	out->attid			= attr->attributeID_id;
1278	out->value_ctr.num_values	= in->num_values;
1279	out->value_ctr.values		= talloc_array(mem_ctx,
1280						       struct drsuapi_DsAttributeValue,
1281						       in->num_values);
1282	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1283
1284	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1285	W_ERROR_HAVE_NO_MEMORY(blobs);
1286
1287	for (i=0; i < in->num_values; i++) {
1288		struct drsuapi_DsReplicaObjectIdentifier3Binary id3b;
1289		enum ndr_err_code ndr_err;
1290
1291		out->value_ctr.values[i].blob	= &blobs[i];
1292
1293		/* TODO: handle id3b.guid and id3b.sid, id3.binary */
1294		ZERO_STRUCT(id3b);
1295		id3b.dn		= (const char *)in->values[i].data;
1296		id3b.binary	= data_blob(NULL, 0);
1297
1298		ndr_err = ndr_push_struct_blob(&blobs[i], blobs, schema->iconv_convenience, &id3b,
1299					       (ndr_push_flags_fn_t)ndr_push_drsuapi_DsReplicaObjectIdentifier3Binary);
1300		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1301			NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
1302			return ntstatus_to_werror(status);
1303		}
1304	}
1305
1306	return WERR_OK;
1307}
1308
1309static WERROR dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb(struct ldb_context *ldb,
1310							      const struct dsdb_schema *schema,
1311							      const struct dsdb_attribute *attr,
1312							      const struct drsuapi_DsReplicaAttribute *in,
1313							      TALLOC_CTX *mem_ctx,
1314							      struct ldb_message_element *out)
1315{
1316	uint32_t i;
1317
1318	out->flags	= 0;
1319	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
1320	W_ERROR_HAVE_NO_MEMORY(out->name);
1321
1322	out->num_values	= in->value_ctr.num_values;
1323	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
1324	W_ERROR_HAVE_NO_MEMORY(out->values);
1325
1326	for (i=0; i < out->num_values; i++) {
1327		uint32_t len;
1328		char *str;
1329
1330		if (in->value_ctr.values[i].blob == NULL) {
1331			return WERR_FOOBAR;
1332		}
1333
1334		if (in->value_ctr.values[i].blob->length < 4) {
1335			return WERR_FOOBAR;
1336		}
1337
1338		len = IVAL(in->value_ctr.values[i].blob->data, 0);
1339
1340		if (len != in->value_ctr.values[i].blob->length) {
1341			return WERR_FOOBAR;
1342		}
1343
1344		if (!convert_string_talloc_convenience(out->values, schema->iconv_convenience, CH_UTF16, CH_UNIX,
1345					    in->value_ctr.values[i].blob->data+4,
1346					    in->value_ctr.values[i].blob->length-4,
1347					    (void **)&str, NULL, false)) {
1348			return WERR_FOOBAR;
1349		}
1350
1351		out->values[i] = data_blob_string_const(str);
1352	}
1353
1354	return WERR_OK;
1355}
1356
1357static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(struct ldb_context *ldb,
1358							      const struct dsdb_schema *schema,
1359							      const struct dsdb_attribute *attr,
1360							      const struct ldb_message_element *in,
1361							      TALLOC_CTX *mem_ctx,
1362							      struct drsuapi_DsReplicaAttribute *out)
1363{
1364	uint32_t i;
1365	DATA_BLOB *blobs;
1366
1367	if (attr->attributeID_id == 0xFFFFFFFF) {
1368		return WERR_FOOBAR;
1369	}
1370
1371	out->attid			= attr->attributeID_id;
1372	out->value_ctr.num_values	= in->num_values;
1373	out->value_ctr.values		= talloc_array(mem_ctx,
1374						       struct drsuapi_DsAttributeValue,
1375						       in->num_values);
1376	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
1377
1378	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
1379	W_ERROR_HAVE_NO_MEMORY(blobs);
1380
1381	for (i=0; i < in->num_values; i++) {
1382		uint8_t *data;
1383		size_t ret;
1384
1385		out->value_ctr.values[i].blob	= &blobs[i];
1386
1387		if (!convert_string_talloc_convenience(blobs, schema->iconv_convenience, CH_UNIX, CH_UTF16,
1388					    in->values[i].data,
1389					    in->values[i].length,
1390					    (void **)&data, &ret, false)) {
1391			return WERR_FOOBAR;
1392		}
1393
1394		blobs[i] = data_blob_talloc(blobs, NULL, 4 + ret);
1395		W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
1396
1397		SIVAL(blobs[i].data, 0, 4 + ret);
1398
1399		if (ret > 0) {
1400			memcpy(blobs[i].data + 4, data, ret);
1401			talloc_free(data);
1402		}
1403	}
1404
1405	return WERR_OK;
1406}
1407
1408#define OMOBJECTCLASS(val) { .length = sizeof(val) - 1, .data = discard_const_p(uint8_t, val) }
1409
1410static const struct dsdb_syntax dsdb_syntaxes[] = {
1411	{
1412		.name			= "Boolean",
1413		.ldap_oid		= LDB_SYNTAX_BOOLEAN,
1414		.oMSyntax		= 1,
1415		.attributeSyntax_oid	= "2.5.5.8",
1416		.drsuapi_to_ldb		= dsdb_syntax_BOOL_drsuapi_to_ldb,
1417		.ldb_to_drsuapi		= dsdb_syntax_BOOL_ldb_to_drsuapi,
1418		.equality               = "booleanMatch",
1419		.comment                = "Boolean"
1420	},{
1421		.name			= "Integer",
1422		.ldap_oid		= LDB_SYNTAX_INTEGER,
1423		.oMSyntax		= 2,
1424		.attributeSyntax_oid	= "2.5.5.9",
1425		.drsuapi_to_ldb		= dsdb_syntax_INT32_drsuapi_to_ldb,
1426		.ldb_to_drsuapi		= dsdb_syntax_INT32_ldb_to_drsuapi,
1427		.equality               = "integerMatch",
1428		.comment                = "Integer",
1429		.ldb_syntax		= LDB_SYNTAX_SAMBA_INT32
1430	},{
1431		.name			= "String(Octet)",
1432		.ldap_oid		= LDB_SYNTAX_OCTET_STRING,
1433		.oMSyntax		= 4,
1434		.attributeSyntax_oid	= "2.5.5.10",
1435		.drsuapi_to_ldb		= dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1436		.ldb_to_drsuapi		= dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1437		.equality               = "octetStringMatch",
1438		.comment                = "Octet String",
1439	},{
1440		.name			= "String(Sid)",
1441		.ldap_oid		= LDB_SYNTAX_OCTET_STRING,
1442		.oMSyntax		= 4,
1443		.attributeSyntax_oid	= "2.5.5.17",
1444		.drsuapi_to_ldb		= dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1445		.ldb_to_drsuapi		= dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1446		.equality               = "octetStringMatch",
1447		.comment                = "Octet String - Security Identifier (SID)",
1448		.ldb_syntax             = LDB_SYNTAX_SAMBA_SID
1449	},{
1450		.name			= "String(Object-Identifier)",
1451		.ldap_oid		= "1.3.6.1.4.1.1466.115.121.1.38",
1452		.oMSyntax		= 6,
1453		.attributeSyntax_oid	= "2.5.5.2",
1454		.drsuapi_to_ldb		= dsdb_syntax_OID_drsuapi_to_ldb,
1455		.ldb_to_drsuapi		= dsdb_syntax_OID_ldb_to_drsuapi,
1456		.equality               = "caseIgnoreMatch", /* Would use "objectIdentifierMatch" but most are ldap attribute/class names */
1457		.comment                = "OID String",
1458		.ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING
1459	},{
1460		.name			= "Enumeration",
1461		.ldap_oid		= LDB_SYNTAX_INTEGER,
1462		.oMSyntax		= 10,
1463		.attributeSyntax_oid	= "2.5.5.9",
1464		.drsuapi_to_ldb		= dsdb_syntax_INT32_drsuapi_to_ldb,
1465		.ldb_to_drsuapi		= dsdb_syntax_INT32_ldb_to_drsuapi,
1466		.ldb_syntax		= LDB_SYNTAX_SAMBA_INT32
1467	},{
1468	/* not used in w2k3 forest */
1469		.name			= "String(Numeric)",
1470		.ldap_oid		= "1.3.6.1.4.1.1466.115.121.1.36",
1471		.oMSyntax		= 18,
1472		.attributeSyntax_oid	= "2.5.5.6",
1473		.drsuapi_to_ldb		= dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1474		.ldb_to_drsuapi		= dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1475		.equality               = "numericStringMatch",
1476		.substring              = "numericStringSubstringsMatch",
1477		.comment                = "Numeric String",
1478		.ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1479	},{
1480		.name			= "String(Printable)",
1481		.ldap_oid		= "1.3.6.1.4.1.1466.115.121.1.44",
1482		.oMSyntax		= 19,
1483		.attributeSyntax_oid	= "2.5.5.5",
1484		.drsuapi_to_ldb		= dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1485		.ldb_to_drsuapi		= dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1486		.ldb_syntax		= LDB_SYNTAX_OCTET_STRING,
1487	},{
1488		.name			= "String(Teletex)",
1489		.ldap_oid		= "1.2.840.113556.1.4.905",
1490		.oMSyntax		= 20,
1491		.attributeSyntax_oid	= "2.5.5.4",
1492		.drsuapi_to_ldb		= dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1493		.ldb_to_drsuapi		= dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1494		.equality               = "caseIgnoreMatch",
1495		.substring              = "caseIgnoreSubstringsMatch",
1496		.comment                = "Case Insensitive String",
1497		.ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1498	},{
1499		.name			= "String(IA5)",
1500		.ldap_oid		= "1.3.6.1.4.1.1466.115.121.1.26",
1501		.oMSyntax		= 22,
1502		.attributeSyntax_oid	= "2.5.5.5",
1503		.drsuapi_to_ldb		= dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1504		.ldb_to_drsuapi		= dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1505		.equality               = "caseExactIA5Match",
1506		.comment                = "Printable String",
1507		.ldb_syntax		= LDB_SYNTAX_OCTET_STRING,
1508	},{
1509		.name			= "String(UTC-Time)",
1510		.ldap_oid		= "1.3.6.1.4.1.1466.115.121.1.53",
1511		.oMSyntax		= 23,
1512		.attributeSyntax_oid	= "2.5.5.11",
1513		.drsuapi_to_ldb		= dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb,
1514		.ldb_to_drsuapi		= dsdb_syntax_NTTIME_UTC_ldb_to_drsuapi,
1515		.equality               = "generalizedTimeMatch",
1516		.comment                = "UTC Time",
1517	},{
1518		.name			= "String(Generalized-Time)",
1519		.ldap_oid		= "1.3.6.1.4.1.1466.115.121.1.24",
1520		.oMSyntax		= 24,
1521		.attributeSyntax_oid	= "2.5.5.11",
1522		.drsuapi_to_ldb		= dsdb_syntax_NTTIME_drsuapi_to_ldb,
1523		.ldb_to_drsuapi		= dsdb_syntax_NTTIME_ldb_to_drsuapi,
1524		.equality               = "generalizedTimeMatch",
1525		.comment                = "Generalized Time",
1526		.ldb_syntax             = LDB_SYNTAX_UTC_TIME,
1527	},{
1528	/* not used in w2k3 schema */
1529		.name			= "String(Case Sensitive)",
1530		.ldap_oid		= "1.2.840.113556.1.4.1362",
1531		.oMSyntax		= 27,
1532		.attributeSyntax_oid	= "2.5.5.3",
1533		.drsuapi_to_ldb		= dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1534		.ldb_to_drsuapi		= dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1535	},{
1536		.name			= "String(Unicode)",
1537		.ldap_oid		= LDB_SYNTAX_DIRECTORY_STRING,
1538		.oMSyntax		= 64,
1539		.attributeSyntax_oid	= "2.5.5.12",
1540		.drsuapi_to_ldb		= dsdb_syntax_UNICODE_drsuapi_to_ldb,
1541		.ldb_to_drsuapi		= dsdb_syntax_UNICODE_ldb_to_drsuapi,
1542		.equality               = "caseIgnoreMatch",
1543		.substring              = "caseIgnoreSubstringsMatch",
1544		.comment                = "Directory String",
1545	},{
1546		.name			= "Interval/LargeInteger",
1547		.ldap_oid		= "1.2.840.113556.1.4.906",
1548		.oMSyntax		= 65,
1549		.attributeSyntax_oid	= "2.5.5.16",
1550		.drsuapi_to_ldb		= dsdb_syntax_INT64_drsuapi_to_ldb,
1551		.ldb_to_drsuapi		= dsdb_syntax_INT64_ldb_to_drsuapi,
1552		.equality               = "integerMatch",
1553		.comment                = "Large Integer",
1554		.ldb_syntax             = LDB_SYNTAX_INTEGER,
1555	},{
1556		.name			= "String(NT-Sec-Desc)",
1557		.ldap_oid		= LDB_SYNTAX_SAMBA_SECURITY_DESCRIPTOR,
1558		.oMSyntax		= 66,
1559		.attributeSyntax_oid	= "2.5.5.15",
1560		.drsuapi_to_ldb		= dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1561		.ldb_to_drsuapi		= dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1562	},{
1563		.name			= "Object(DS-DN)",
1564		.ldap_oid		= LDB_SYNTAX_DN,
1565		.oMSyntax		= 127,
1566		.oMObjectClass		= OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a"),
1567		.attributeSyntax_oid	= "2.5.5.1",
1568		.drsuapi_to_ldb		= dsdb_syntax_DN_drsuapi_to_ldb,
1569		.ldb_to_drsuapi		= dsdb_syntax_DN_ldb_to_drsuapi,
1570		.equality               = "distinguishedNameMatch",
1571		.comment                = "Object(DS-DN) == a DN",
1572	},{
1573		.name			= "Object(DN-Binary)",
1574		.ldap_oid		= "1.2.840.113556.1.4.903",
1575		.oMSyntax		= 127,
1576		.oMObjectClass		= OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b"),
1577		.attributeSyntax_oid	= "2.5.5.7",
1578		.drsuapi_to_ldb		= dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1579		.ldb_to_drsuapi		= dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1580		.equality               = "octetStringMatch",
1581		.comment                = "OctetString: Binary+DN",
1582		.ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1583	},{
1584	/* not used in w2k3 schema */
1585		.name			= "Object(OR-Name)",
1586		.ldap_oid		= "1.2.840.113556.1.4.1221",
1587		.oMSyntax		= 127,
1588		.oMObjectClass		= OMOBJECTCLASS("\x56\x06\x01\x02\x05\x0b\x1D"),
1589		.attributeSyntax_oid	= "2.5.5.7",
1590		.drsuapi_to_ldb		= dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1591		.ldb_to_drsuapi		= dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1592	},{
1593	/*
1594	 * TODO: verify if DATA_BLOB is correct here...!
1595	 *
1596	 *       repsFrom and repsTo are the only attributes using
1597	 *       this attribute syntax, but they're not replicated...
1598	 */
1599		.name			= "Object(Replica-Link)",
1600		.ldap_oid		= "1.3.6.1.4.1.1466.115.121.1.40",
1601		.oMSyntax		= 127,
1602		.oMObjectClass		= OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06"),
1603		.attributeSyntax_oid	= "2.5.5.10",
1604		.drsuapi_to_ldb		= dsdb_syntax_DATA_BLOB_drsuapi_to_ldb,
1605		.ldb_to_drsuapi		= dsdb_syntax_DATA_BLOB_ldb_to_drsuapi,
1606	},{
1607		.name			= "Object(Presentation-Address)",
1608		.ldap_oid		= "1.3.6.1.4.1.1466.115.121.1.43",
1609		.oMSyntax		= 127,
1610		.oMObjectClass		= OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c"),
1611		.attributeSyntax_oid	= "2.5.5.13",
1612		.drsuapi_to_ldb		= dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb,
1613		.ldb_to_drsuapi		= dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi,
1614		.comment                = "Presentation Address",
1615		.ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1616	},{
1617	/* not used in w2k3 schema */
1618		.name			= "Object(Access-Point)",
1619		.ldap_oid		= "1.3.6.1.4.1.1466.115.121.1.2",
1620		.oMSyntax		= 127,
1621		.oMObjectClass		= OMOBJECTCLASS("\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e"),
1622		.attributeSyntax_oid	= "2.5.5.14",
1623		.drsuapi_to_ldb		= dsdb_syntax_FOOBAR_drsuapi_to_ldb,
1624		.ldb_to_drsuapi		= dsdb_syntax_FOOBAR_ldb_to_drsuapi,
1625		.ldb_syntax             = LDB_SYNTAX_DIRECTORY_STRING,
1626	},{
1627	/* not used in w2k3 schema */
1628		.name			= "Object(DN-String)",
1629		.ldap_oid		= "1.2.840.113556.1.4.904",
1630		.oMSyntax		= 127,
1631		.oMObjectClass		= OMOBJECTCLASS("\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c"),
1632		.attributeSyntax_oid	= "2.5.5.14",
1633		.drsuapi_to_ldb		= dsdb_syntax_DN_BINARY_drsuapi_to_ldb,
1634		.ldb_to_drsuapi		= dsdb_syntax_DN_BINARY_ldb_to_drsuapi,
1635		.equality               = "octetStringMatch",
1636		.comment                = "OctetString: String+DN",
1637		.ldb_syntax             = LDB_SYNTAX_OCTET_STRING,
1638	}
1639};
1640
1641const struct dsdb_syntax *find_syntax_map_by_ad_oid(const char *ad_oid)
1642{
1643	int i;
1644	for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1645		if (strcasecmp(ad_oid, dsdb_syntaxes[i].attributeSyntax_oid) == 0) {
1646			return &dsdb_syntaxes[i];
1647		}
1648	}
1649	return NULL;
1650}
1651
1652const struct dsdb_syntax *find_syntax_map_by_ad_syntax(int oMSyntax)
1653{
1654	int i;
1655	for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1656		if (oMSyntax == dsdb_syntaxes[i].oMSyntax) {
1657			return &dsdb_syntaxes[i];
1658		}
1659	}
1660	return NULL;
1661}
1662
1663const struct dsdb_syntax *find_syntax_map_by_standard_oid(const char *standard_oid)
1664{
1665	int i;
1666	for (i=0; dsdb_syntaxes[i].ldap_oid; i++) {
1667		if (strcasecmp(standard_oid, dsdb_syntaxes[i].ldap_oid) == 0) {
1668			return &dsdb_syntaxes[i];
1669		}
1670	}
1671	return NULL;
1672}
1673const struct dsdb_syntax *dsdb_syntax_for_attribute(const struct dsdb_attribute *attr)
1674{
1675	uint32_t i;
1676
1677	for (i=0; i < ARRAY_SIZE(dsdb_syntaxes); i++) {
1678		if (attr->oMSyntax != dsdb_syntaxes[i].oMSyntax) continue;
1679
1680		if (attr->oMObjectClass.length != dsdb_syntaxes[i].oMObjectClass.length) continue;
1681
1682		if (attr->oMObjectClass.length) {
1683			int ret;
1684			ret = memcmp(attr->oMObjectClass.data,
1685				     dsdb_syntaxes[i].oMObjectClass.data,
1686				     attr->oMObjectClass.length);
1687			if (ret != 0) continue;
1688		}
1689
1690		if (strcmp(attr->attributeSyntax_oid, dsdb_syntaxes[i].attributeSyntax_oid) != 0) continue;
1691
1692		return &dsdb_syntaxes[i];
1693	}
1694
1695	return NULL;
1696}
1697
1698WERROR dsdb_attribute_drsuapi_to_ldb(struct ldb_context *ldb,
1699				     const struct dsdb_schema *schema,
1700				     const struct drsuapi_DsReplicaAttribute *in,
1701				     TALLOC_CTX *mem_ctx,
1702				     struct ldb_message_element *out)
1703{
1704	const struct dsdb_attribute *sa;
1705
1706	sa = dsdb_attribute_by_attributeID_id(schema, in->attid);
1707	if (!sa) {
1708		return WERR_FOOBAR;
1709	}
1710
1711	return sa->syntax->drsuapi_to_ldb(ldb, schema, sa, in, mem_ctx, out);
1712}
1713
1714WERROR dsdb_attribute_ldb_to_drsuapi(struct ldb_context *ldb,
1715				     const struct dsdb_schema *schema,
1716				     const struct ldb_message_element *in,
1717				     TALLOC_CTX *mem_ctx,
1718				     struct drsuapi_DsReplicaAttribute *out)
1719{
1720	const struct dsdb_attribute *sa;
1721
1722	sa = dsdb_attribute_by_lDAPDisplayName(schema, in->name);
1723	if (!sa) {
1724		return WERR_FOOBAR;
1725	}
1726
1727	return sa->syntax->ldb_to_drsuapi(ldb, schema, sa, in, mem_ctx, out);
1728}
1729