001bc45ee1ad5fecf9f0b29a686e8803e26b735b
[sfrench/samba-autobuild/.git] / source4 / lib / ldb / common / ldb_attributes.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2005
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 3 of the License, or (at your option) any later version.
14
15    This library 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 GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 */
23 /*
24   register handlers for specific attributes and objectclass relationships
25
26   this allows a backend to store its schema information in any format
27   it likes (or to not have any schema information at all) while keeping the 
28   message matching logic generic
29 */
30
31 #include "ldb_includes.h"
32
33 /*
34   add a attribute to the ldb_schema
35
36   if flags contains LDB_ATTR_FLAG_ALLOCATED
37   the attribute name string will be copied using
38   talloc_strdup(), otherwise it needs to be a static const
39   string at least with a lifetime longer than the ldb struct!
40   
41   the ldb_schema_syntax structure should be a pointer
42   to a static const struct or at least it needs to be
43   a struct with a longer lifetime than the ldb context!
44
45 */
46 int ldb_schema_attribute_add_with_syntax(struct ldb_context *ldb, 
47                                          const char *attribute,
48                                          unsigned flags,
49                                          const struct ldb_schema_syntax *syntax)
50 {
51         int i, n;
52         struct ldb_schema_attribute *a;
53
54         if (!syntax) {
55                 return LDB_ERR_OPERATIONS_ERROR;
56         }
57
58         n = ldb->schema.num_attributes + 1;
59
60         a = talloc_realloc(ldb, ldb->schema.attributes,
61                            struct ldb_schema_attribute, n);
62         if (a == NULL) {
63                 ldb_oom(ldb);
64                 return -1;
65         }
66         ldb->schema.attributes = a;
67
68         for (i = 0; i < ldb->schema.num_attributes; i++) {
69                 int cmp = ldb_attr_cmp(attribute, a[i].name);
70                 if (cmp == 0) {
71                         /* silently ignore attempts to overwrite fixed attributes */
72                         if (a[i].flags & LDB_ATTR_FLAG_FIXED) {
73                                 return 0;
74                         }
75                         if (a[i].flags & LDB_ATTR_FLAG_ALLOCATED) {
76                                 talloc_free(discard_const_p(char, a[i].name));
77                         }
78                         /* To cancel out increment below */
79                         ldb->schema.num_attributes--;
80                         break;
81                 } else if (cmp < 0) {
82                         memmove(a+i+1, a+i, sizeof(*a) * (ldb->schema.num_attributes-i));
83                         break;
84                 }
85         }
86         ldb->schema.num_attributes++;
87
88         a[i].name       = attribute;
89         a[i].flags      = flags;
90         a[i].syntax     = syntax;
91
92         if (a[i].flags & LDB_ATTR_FLAG_ALLOCATED) {
93                 a[i].name = talloc_strdup(a, a[i].name);
94                 if (a[i].name == NULL) {
95                         ldb_oom(ldb);
96                         return -1;
97                 }
98         }
99
100         return 0;
101 }
102
103 static const struct ldb_schema_syntax ldb_syntax_default = {
104         .name            = LDB_SYNTAX_OCTET_STRING,
105         .ldif_read_fn    = ldb_handler_copy,
106         .ldif_write_fn   = ldb_handler_copy,
107         .canonicalise_fn = ldb_handler_copy,
108         .comparison_fn   = ldb_comparison_binary
109 };
110
111 static const struct ldb_schema_attribute ldb_attribute_default = {
112         .name   = NULL,
113         .flags  = 0,
114         .syntax = &ldb_syntax_default
115 };
116
117 /*
118   return the attribute handlers for a given attribute
119 */
120 const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_context *ldb,
121                                                                 const char *name)
122 {
123         int i, e, b = 0, r;
124         const struct ldb_schema_attribute *def = &ldb_attribute_default;
125
126         /* as handlers are sorted, '*' must be the first if present */
127         if (strcmp(ldb->schema.attributes[0].name, "*") == 0) {
128                 def = &ldb->schema.attributes[0];
129                 b = 1;
130         }
131
132         /* do a binary search on the array */
133         e = ldb->schema.num_attributes - 1;
134
135         while (b <= e) {
136
137                 i = (b + e) / 2;
138
139                 r = ldb_attr_cmp(name, ldb->schema.attributes[i].name);
140                 if (r == 0) {
141                         return &ldb->schema.attributes[i];
142                 }
143                 if (r < 0) {
144                         e = i - 1;
145                 } else {
146                         b = i + 1;
147                 }
148
149         }
150
151         return def;
152 }
153
154
155 /*
156   add to the list of ldif handlers for this ldb context
157 */
158 void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name)
159 {
160         const struct ldb_schema_attribute *a;
161         int i;
162
163         a = ldb_schema_attribute_by_name(ldb, name);
164         if (a == NULL || a->name == NULL) {
165                 return;
166         }
167
168         /* FIXED attributes are never removed */
169         if (a->flags & LDB_ATTR_FLAG_FIXED) {
170                 return;
171         }
172
173         if (a->flags & LDB_ATTR_FLAG_ALLOCATED) {
174                 talloc_free(discard_const_p(char, a->name));
175         }
176
177         i = a - ldb->schema.attributes;
178         if (i < ldb->schema.num_attributes - 1) {
179                 memmove(&ldb->schema.attributes[i], 
180                         a+1, sizeof(*a) * (ldb->schema.num_attributes-(i+1)));
181         }
182
183         ldb->schema.num_attributes--;
184 }
185
186 /*
187   setup a attribute handler using a standard syntax
188 */
189 int ldb_schema_attribute_add(struct ldb_context *ldb,
190                              const char *attribute,
191                              unsigned flags,
192                              const char *syntax)
193 {
194         const struct ldb_schema_syntax *s = ldb_standard_syntax_by_name(ldb, syntax);
195         return ldb_schema_attribute_add_with_syntax(ldb, attribute, flags, s);
196 }
197
198 /*
199   setup the attribute handles for well known attributes
200 */
201 int ldb_setup_wellknown_attributes(struct ldb_context *ldb)
202 {
203         const struct {
204                 const char *attr;
205                 const char *syntax;
206         } wellknown[] = {
207                 { "dn", LDB_SYNTAX_DN },
208                 { "distinguishedName", LDB_SYNTAX_DN },
209                 { "cn", LDB_SYNTAX_DIRECTORY_STRING },
210                 { "dc", LDB_SYNTAX_DIRECTORY_STRING },
211                 { "ou", LDB_SYNTAX_DIRECTORY_STRING },
212                 { "objectClass", LDB_SYNTAX_OBJECTCLASS }
213         };
214         int i;
215         int ret;
216
217         for (i=0;i<ARRAY_SIZE(wellknown);i++) {
218                 ret = ldb_schema_attribute_add(ldb, wellknown[i].attr, 0,
219                                                wellknown[i].syntax);
220                 if (ret != LDB_SUCCESS) {
221                         return ret;
222                 }
223         }
224
225         return LDB_SUCCESS;
226 }
227
228
229 /*
230   add a extended dn syntax to the ldb_schema
231 */
232 int ldb_dn_extended_add_syntax(struct ldb_context *ldb, 
233                                unsigned flags,
234                                const struct ldb_dn_extended_syntax *syntax)
235 {
236         int n;
237         struct ldb_dn_extended_syntax *a;
238
239         if (!syntax) {
240                 return LDB_ERR_OPERATIONS_ERROR;
241         }
242
243         n = ldb->schema.num_dn_extended_syntax + 1;
244
245         a = talloc_realloc(ldb, ldb->schema.dn_extended_syntax,
246                            struct ldb_dn_extended_syntax, n);
247
248         if (!a) {
249                 return LDB_ERR_OPERATIONS_ERROR;
250         }
251
252         a[ldb->schema.num_dn_extended_syntax] = *syntax;
253         ldb->schema.dn_extended_syntax = a;
254
255         ldb->schema.num_dn_extended_syntax = n;
256
257         return LDB_SUCCESS;
258 }
259
260 /*
261   return the extended dn syntax for a given name
262 */
263 const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_context *ldb,
264                                                                     const char *name)
265 {
266         int i;
267         for (i=0; i < ldb->schema.num_dn_extended_syntax; i++) {
268                 if (ldb_attr_cmp(ldb->schema.dn_extended_syntax[i].name, name) == 0) {
269                         return &ldb->schema.dn_extended_syntax[i];
270                 }
271         }
272         return NULL;
273 }
274