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)
37 static int strcasecmp_with_ldb_val(const struct ldb_val *target, const char *str)
39 int ret = strncasecmp((const char *)target->data, str, target->length);
41 return (target->length - strlen(str));
46 const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema,
49 struct dsdb_attribute *c;
52 * 0xFFFFFFFF is used as value when no mapping table is available,
53 * so don't try to match with it
55 if (id == 0xFFFFFFFF) return NULL;
57 BINARY_ARRAY_SEARCH_P(schema->attributes_by_attributeID_id,
58 schema->num_attributes, attributeID_id, id, uint32_cmp, c);
62 const struct dsdb_attribute *dsdb_attribute_by_attributeID_oid(const struct dsdb_schema *schema,
65 struct dsdb_attribute *c;
67 if (!oid) return NULL;
69 BINARY_ARRAY_SEARCH_P(schema->attributes_by_attributeID_oid,
70 schema->num_attributes, attributeID_oid, oid, strcasecmp, c);
74 const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb_schema *schema,
77 struct dsdb_attribute *c;
79 if (!name) return NULL;
81 BINARY_ARRAY_SEARCH_P(schema->attributes_by_lDAPDisplayName,
82 schema->num_attributes, lDAPDisplayName, name, strcasecmp, c);
86 const struct dsdb_attribute *dsdb_attribute_by_linkID(const struct dsdb_schema *schema,
89 struct dsdb_attribute *c;
91 BINARY_ARRAY_SEARCH_P(schema->attributes_by_linkID,
92 schema->num_attributes, linkID, linkID, uint32_cmp, c);
96 const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *schema,
102 * 0xFFFFFFFF is used as value when no mapping table is available,
103 * so don't try to match with it
105 if (id == 0xFFFFFFFF) return NULL;
107 BINARY_ARRAY_SEARCH_P(schema->classes_by_governsID_id,
108 schema->num_classes, governsID_id, id, uint32_cmp, c);
112 const struct dsdb_class *dsdb_class_by_governsID_oid(const struct dsdb_schema *schema,
115 struct dsdb_class *c;
116 if (!oid) return NULL;
117 BINARY_ARRAY_SEARCH_P(schema->classes_by_governsID_oid,
118 schema->num_classes, governsID_oid, oid, strcasecmp, c);
122 const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema *schema,
125 struct dsdb_class *c;
126 if (!name) return NULL;
127 BINARY_ARRAY_SEARCH_P(schema->classes_by_lDAPDisplayName,
128 schema->num_classes, lDAPDisplayName, name, strcasecmp, c);
132 const struct dsdb_class *dsdb_class_by_lDAPDisplayName_ldb_val(const struct dsdb_schema *schema,
133 const struct ldb_val *name)
135 struct dsdb_class *c;
136 if (!name) return NULL;
137 BINARY_ARRAY_SEARCH_P(schema->classes_by_lDAPDisplayName,
138 schema->num_classes, lDAPDisplayName, name, strcasecmp_with_ldb_val, c);
142 const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema,
145 struct dsdb_class *c;
146 if (!cn) return NULL;
147 BINARY_ARRAY_SEARCH_P(schema->classes_by_cn,
148 schema->num_classes, cn, cn, strcasecmp, c);
152 const struct dsdb_class *dsdb_class_by_cn_ldb_val(const struct dsdb_schema *schema,
153 const struct ldb_val *cn)
155 struct dsdb_class *c;
156 if (!cn) return NULL;
157 BINARY_ARRAY_SEARCH_P(schema->classes_by_cn,
158 schema->num_classes, cn, cn, strcasecmp_with_ldb_val, c);
162 const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema,
165 const struct dsdb_attribute *a;
166 const struct dsdb_class *c;
168 a = dsdb_attribute_by_attributeID_id(schema, id);
170 return a->lDAPDisplayName;
173 c = dsdb_class_by_governsID_id(schema, id);
175 return c->lDAPDisplayName;
182 Return a list of linked attributes, in lDAPDisplayName format.
184 This may be used to determine if a modification would require
185 backlinks to be updated, for example
188 WERROR dsdb_linked_attribute_lDAPDisplayName_list(const struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, const char ***attr_list_ret)
190 const char **attr_list = NULL;
191 struct dsdb_attribute *cur;
193 for (cur = schema->attributes; cur; cur = cur->next) {
194 if (cur->linkID == 0) continue;
196 attr_list = talloc_realloc(mem_ctx, attr_list, const char *, i+2);
200 attr_list[i] = cur->lDAPDisplayName;
204 *attr_list_ret = attr_list;
208 const char **merge_attr_list(TALLOC_CTX *mem_ctx,
209 const char **attrs, const char * const*new_attrs)
211 const char **ret_attrs;
213 size_t new_len, orig_len = str_list_length(attrs);
218 ret_attrs = talloc_realloc(mem_ctx,
219 attrs, const char *, orig_len + str_list_length(new_attrs) + 1);
221 for (i=0; i < str_list_length(new_attrs); i++) {
222 ret_attrs[orig_len + i] = new_attrs[i];
224 new_len = orig_len + str_list_length(new_attrs);
226 ret_attrs[new_len] = NULL;
233 Return a merged list of the attributes of exactly one class (not
234 considering subclasses, auxillary classes etc)
237 const char **dsdb_attribute_list(TALLOC_CTX *mem_ctx, const struct dsdb_class *sclass, enum dsdb_attr_list_query query)
239 const char **attr_list = NULL;
241 case DSDB_SCHEMA_ALL_MAY:
242 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->mayContain);
243 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->systemMayContain);
246 case DSDB_SCHEMA_ALL_MUST:
247 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->mustContain);
248 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->systemMustContain);
251 case DSDB_SCHEMA_SYS_MAY:
252 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->systemMayContain);
255 case DSDB_SCHEMA_SYS_MUST:
256 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->systemMustContain);
259 case DSDB_SCHEMA_MAY:
260 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->mayContain);
263 case DSDB_SCHEMA_MUST:
264 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->mustContain);
267 case DSDB_SCHEMA_ALL:
268 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->mayContain);
269 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->systemMayContain);
270 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->mustContain);
271 attr_list = merge_attr_list(mem_ctx, attr_list, sclass->systemMustContain);
277 static const char **attribute_list_from_class(TALLOC_CTX *mem_ctx,
278 const struct dsdb_schema *schema,
279 const struct dsdb_class *sclass,
280 enum dsdb_attr_list_query query)
282 const char **this_class_list;
283 const char **system_recursive_list;
284 const char **recursive_list;
285 const char **attr_list;
287 this_class_list = dsdb_attribute_list(mem_ctx, sclass, query);
289 recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema,
290 sclass->systemAuxiliaryClass,
293 system_recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema,
294 sclass->auxiliaryClass,
297 attr_list = this_class_list;
298 attr_list = merge_attr_list(mem_ctx, attr_list, recursive_list);
299 attr_list = merge_attr_list(mem_ctx, attr_list, system_recursive_list);
303 /* Return a full attribute list for a given class list (as a ldb_message_element)
305 Via attribute_list_from_class() this calls itself when recursing on auxiliary classes
307 static const char **dsdb_full_attribute_list_internal(TALLOC_CTX *mem_ctx,
308 const struct dsdb_schema *schema,
309 const char **class_list,
310 enum dsdb_attr_list_query query)
313 const char **attr_list = NULL;
315 for (i=0; class_list && class_list[i]; i++) {
316 const char **sclass_list
317 = attribute_list_from_class(mem_ctx, schema,
318 dsdb_class_by_lDAPDisplayName(schema, class_list[i]),
321 attr_list = merge_attr_list(mem_ctx, attr_list, sclass_list);
326 /* Return a full attribute list for a given class list (as a ldb_message_element)
328 Using the ldb_message_element ensures we do length-limited
329 comparisons, rather than casting the possibly-unterminated string
331 Via attribute_list_from_class() this calls
332 dsdb_full_attribute_list_internal() when recursing on auxiliary classes
334 static const char **dsdb_full_attribute_list_internal_el(TALLOC_CTX *mem_ctx,
335 const struct dsdb_schema *schema,
336 const struct ldb_message_element *el,
337 enum dsdb_attr_list_query query)
340 const char **attr_list = NULL;
342 for (i=0; i < el->num_values; i++) {
343 const char **sclass_list
344 = attribute_list_from_class(mem_ctx, schema,
345 dsdb_class_by_lDAPDisplayName_ldb_val(schema, &el->values[i]),
348 attr_list = merge_attr_list(mem_ctx, attr_list, sclass_list);
353 /* Helper function to remove duplicates from the attribute list to be returned */
354 static const char **dedup_attr_list(const char **attr_list)
356 size_t new_len = str_list_length(attr_list);
357 /* Remove duplicates */
360 qsort(attr_list, new_len,
362 (comparison_fn_t)strcasecmp);
364 for (i=1 ; i < new_len; i++) {
365 const char **val1 = &attr_list[i-1];
366 const char **val2 = &attr_list[i];
367 if (ldb_attr_cmp(*val1, *val2) == 0) {
368 memmove(val1, val2, (new_len - i) * sizeof( *attr_list));
377 /* Return a full attribute list for a given class list (as a ldb_message_element)
379 Using the ldb_message_element ensures we do length-limited
380 comparisons, rather than casting the possibly-unterminated string
382 The result contains only unique values
384 const char **dsdb_full_attribute_list(TALLOC_CTX *mem_ctx,
385 const struct dsdb_schema *schema,
386 const struct ldb_message_element *class_list,
387 enum dsdb_attr_list_query query)
389 const char **attr_list = dsdb_full_attribute_list_internal_el(mem_ctx, schema, class_list, query);
390 return dedup_attr_list(attr_list);
393 /* Return the schemaIDGUID of a class */
395 const struct GUID *class_schemaid_guid_by_lDAPDisplayName(const struct dsdb_schema *schema,
398 const struct dsdb_class *object_class = dsdb_class_by_lDAPDisplayName(schema, name);
402 return &object_class->schemaIDGUID;
405 const struct GUID *attribute_schemaid_guid_by_lDAPDisplayName(const struct dsdb_schema *schema,
408 const struct dsdb_attribute *attr = dsdb_attribute_by_lDAPDisplayName(schema, name);
412 return &attr->schemaIDGUID;