2 Unix SMB/CIFS mplementation.
5 Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "dsdb/samdb/samdb.h"
25 #include "lib/util/binsearch.h"
27 static const char **dsdb_full_attribute_list_internal(TALLOC_CTX *mem_ctx,
28 const struct dsdb_schema *schema,
29 const char **class_list,
30 enum dsdb_attr_list_query query);
32 static int uint32_cmp(uint32_t c1, uint32_t c2)
34 if (c1 == c2) return 0;
35 return c1 > c2 ? 1 : -1;
38 static int strcasecmp_with_ldb_val(const struct ldb_val *target, const char *str)
40 int ret = strncasecmp((const char *)target->data, str, target->length);
42 return (target->length - strlen(str));
47 const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema,
50 struct dsdb_attribute *c;
53 * 0xFFFFFFFF is used as value when no mapping table is available,
54 * so don't try to match with it
56 if (id == 0xFFFFFFFF) return NULL;
58 BINARY_ARRAY_SEARCH_P(schema->attributes_by_attributeID_id,
59 schema->num_attributes, attributeID_id, id, uint32_cmp, c);
63 const struct dsdb_attribute *dsdb_attribute_by_attributeID_oid(const struct dsdb_schema *schema,
66 struct dsdb_attribute *c;
68 if (!oid) return NULL;
70 BINARY_ARRAY_SEARCH_P(schema->attributes_by_attributeID_oid,
71 schema->num_attributes, attributeID_oid, oid, strcasecmp, c);
75 const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb_schema *schema,
78 struct dsdb_attribute *c;
80 if (!name) return NULL;
82 BINARY_ARRAY_SEARCH_P(schema->attributes_by_lDAPDisplayName,
83 schema->num_attributes, lDAPDisplayName, name, strcasecmp, c);
87 const struct dsdb_attribute *dsdb_attribute_by_linkID(const struct dsdb_schema *schema,
90 struct dsdb_attribute *c;
92 BINARY_ARRAY_SEARCH_P(schema->attributes_by_linkID,
93 schema->num_attributes, linkID, linkID, uint32_cmp, c);
97 const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *schema,
100 struct dsdb_class *c;
103 * 0xFFFFFFFF is used as value when no mapping table is available,
104 * so don't try to match with it
106 if (id == 0xFFFFFFFF) return NULL;
108 BINARY_ARRAY_SEARCH_P(schema->classes_by_governsID_id,
109 schema->num_classes, governsID_id, id, uint32_cmp, c);
113 const struct dsdb_class *dsdb_class_by_governsID_oid(const struct dsdb_schema *schema,
116 struct dsdb_class *c;
117 if (!oid) return NULL;
118 BINARY_ARRAY_SEARCH_P(schema->classes_by_governsID_oid,
119 schema->num_classes, governsID_oid, oid, strcasecmp, c);
123 const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema *schema,
126 struct dsdb_class *c;
127 if (!name) return NULL;
128 BINARY_ARRAY_SEARCH_P(schema->classes_by_lDAPDisplayName,
129 schema->num_classes, lDAPDisplayName, name, strcasecmp, c);
133 const struct dsdb_class *dsdb_class_by_lDAPDisplayName_ldb_val(const struct dsdb_schema *schema,
134 const struct ldb_val *name)
136 struct dsdb_class *c;
137 if (!name) return NULL;
138 BINARY_ARRAY_SEARCH_P(schema->classes_by_lDAPDisplayName,
139 schema->num_classes, lDAPDisplayName, name, strcasecmp_with_ldb_val, c);
143 const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema,
146 struct dsdb_class *c;
147 if (!cn) return NULL;
148 BINARY_ARRAY_SEARCH_P(schema->classes_by_cn,
149 schema->num_classes, cn, cn, strcasecmp, c);
153 const struct dsdb_class *dsdb_class_by_cn_ldb_val(const struct dsdb_schema *schema,
154 const struct ldb_val *cn)
156 struct dsdb_class *c;
157 if (!cn) return NULL;
158 BINARY_ARRAY_SEARCH_P(schema->classes_by_cn,
159 schema->num_classes, cn, cn, strcasecmp_with_ldb_val, c);
163 const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema,
166 const struct dsdb_attribute *a;
167 const struct dsdb_class *c;
169 a = dsdb_attribute_by_attributeID_id(schema, id);
171 return a->lDAPDisplayName;
174 c = dsdb_class_by_governsID_id(schema, id);
176 return c->lDAPDisplayName;
183 Return a list of linked attributes, in lDAPDisplayName format.
185 This may be used to determine if a modification would require
186 backlinks to be updated, for example
189 WERROR dsdb_linked_attribute_lDAPDisplayName_list(const struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, const char ***attr_list_ret)
191 const char **attr_list = NULL;
192 struct dsdb_attribute *cur;
194 for (cur = schema->attributes; cur; cur = cur->next) {
195 if (cur->linkID == 0) continue;
197 attr_list = talloc_realloc(mem_ctx, attr_list, const char *, i+2);
201 attr_list[i] = cur->lDAPDisplayName;
205 *attr_list_ret = attr_list;
209 const char **merge_attr_list(TALLOC_CTX *mem_ctx,
210 const char **attrs, const char * const*new_attrs)
212 const char **ret_attrs;
214 size_t new_len, orig_len = str_list_length(attrs);
219 ret_attrs = talloc_realloc(mem_ctx,
220 attrs, const char *, orig_len + str_list_length(new_attrs) + 1);
222 for (i=0; i < str_list_length(new_attrs); i++) {
223 ret_attrs[orig_len + i] = new_attrs[i];
225 new_len = orig_len + str_list_length(new_attrs);
227 ret_attrs[new_len] = NULL;
234 Return a merged list of the attributes of exactly one class (not
235 considering subclasses, auxillary classes etc)
238 const char **dsdb_attribute_list(TALLOC_CTX *mem_ctx, const struct dsdb_class *sclass, enum dsdb_attr_list_query query)
240 const char **attr_list = NULL;
242 case DSDB_SCHEMA_ALL_MAY:
243 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->mayContain);
244 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->systemMayContain);
247 case DSDB_SCHEMA_ALL_MUST:
248 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->mustContain);
249 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->systemMustContain);
252 case DSDB_SCHEMA_SYS_MAY:
253 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->systemMayContain);
256 case DSDB_SCHEMA_SYS_MUST:
257 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->systemMustContain);
260 case DSDB_SCHEMA_MAY:
261 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->mayContain);
264 case DSDB_SCHEMA_MUST:
265 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->mustContain);
268 case DSDB_SCHEMA_ALL:
269 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->mayContain);
270 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->systemMayContain);
271 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->mustContain);
272 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->systemMustContain);
278 static const char **attribute_list_from_class(TALLOC_CTX *mem_ctx,
279 const struct dsdb_schema *schema,
280 const struct dsdb_class *sclass,
281 enum dsdb_attr_list_query query)
283 const char **this_class_list;
284 const char **system_recursive_list;
285 const char **recursive_list;
286 const char **attr_list;
288 this_class_list = dsdb_attribute_list(mem_ctx, sclass, query);
290 recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema,
291 sclass->systemAuxiliaryClass,
294 system_recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema,
295 sclass->auxiliaryClass,
298 attr_list = this_class_list;
299 attr_list = merge_attr_list(mem_ctx, attr_list, recursive_list);
300 attr_list = merge_attr_list(mem_ctx, attr_list, system_recursive_list);
304 /* Return a full attribute list for a given class list (as a ldb_message_element)
306 Via attribute_list_from_class() this calls itself when recursing on auxiliary classes
308 static const char **dsdb_full_attribute_list_internal(TALLOC_CTX *mem_ctx,
309 const struct dsdb_schema *schema,
310 const char **class_list,
311 enum dsdb_attr_list_query query)
314 const char **attr_list = NULL;
316 for (i=0; class_list && class_list[i]; i++) {
317 const char **sclass_list
318 = attribute_list_from_class(mem_ctx, schema,
319 dsdb_class_by_lDAPDisplayName(schema, class_list[i]),
322 attr_list = merge_attr_list(mem_ctx, attr_list, sclass_list);
327 /* Return a full attribute list for a given class list (as a ldb_message_element)
329 Using the ldb_message_element ensures we do length-limited
330 comparisons, rather than casting the possibly-unterminated string
332 Via attribute_list_from_class() this calls
333 dsdb_full_attribute_list_internal() when recursing on auxiliary classes
335 static const char **dsdb_full_attribute_list_internal_el(TALLOC_CTX *mem_ctx,
336 const struct dsdb_schema *schema,
337 const struct ldb_message_element *el,
338 enum dsdb_attr_list_query query)
341 const char **attr_list = NULL;
343 for (i=0; i < el->num_values; i++) {
344 const char **sclass_list
345 = attribute_list_from_class(mem_ctx, schema,
346 dsdb_class_by_lDAPDisplayName_ldb_val(schema, &el->values[i]),
349 attr_list = merge_attr_list(mem_ctx, attr_list, sclass_list);
354 static int qsort_string(const void *v1,
357 char * const *s1 = v1;
358 char * const *s2 = v2;
359 return strcasecmp(*s1, *s2);
362 /* Helper function to remove duplicates from the attribute list to be returned */
363 static const char **dedup_attr_list(const char **attr_list)
365 size_t new_len = str_list_length(attr_list);
366 /* Remove duplicates */
369 qsort(attr_list, new_len,
371 (comparison_fn_t)qsort_string);
373 for (i=1 ; i < new_len; i++) {
374 const char **val1 = &attr_list[i-1];
375 const char **val2 = &attr_list[i];
376 if (ldb_attr_cmp(*val1, *val2) == 0) {
377 memmove(val1, val2, (new_len - i) * sizeof( *attr_list));
378 attr_list[new_len-1] = NULL;
387 /* Return a full attribute list for a given class list (as a ldb_message_element)
389 Using the ldb_message_element ensures we do length-limited
390 comparisons, rather than casting the possibly-unterminated string
392 The result contains only unique values
394 const char **dsdb_full_attribute_list(TALLOC_CTX *mem_ctx,
395 const struct dsdb_schema *schema,
396 const struct ldb_message_element *class_list,
397 enum dsdb_attr_list_query query)
399 const char **attr_list = dsdb_full_attribute_list_internal_el(mem_ctx, schema, class_list, query);
400 return dedup_attr_list(attr_list);
403 /* Return the schemaIDGUID of a class */
405 const struct GUID *class_schemaid_guid_by_lDAPDisplayName(const struct dsdb_schema *schema,
408 const struct dsdb_class *object_class = dsdb_class_by_lDAPDisplayName(schema, name);
412 return &object_class->schemaIDGUID;
415 const struct GUID *attribute_schemaid_guid_by_lDAPDisplayName(const struct dsdb_schema *schema,
418 const struct dsdb_attribute *attr = dsdb_attribute_by_lDAPDisplayName(schema, name);
422 return &attr->schemaIDGUID;