f737cc6fdc0fc62d5ace7cab629c5604bcd8e351
[jra/samba/.git] / source4 / dsdb / samdb / ldb_modules / schema_syntax.c
1 /* 
2    ldb database library
3
4    Copyright (C) Simo Sorce  2004-2006
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /*
21  *  Name: ldb
22  *
23  *  Component: ldb schema module
24  *
25  *  Description: add schema syntax functionality
26  *
27  *  Author: Simo Sorce
28  *
29  *  License: GNU GPL v2 or Later
30  */
31
32 #include "includes.h"
33 #include "ldb/include/ldb.h"
34 #include "ldb/include/ldb_errors.h"
35 #include "schema_syntax.h"
36
37 int map_schema_syntax(uint32_t om_syntax, const char *attr_syntax, const struct ldb_val *om_class, enum schema_internal_syntax *syntax)
38 {
39         int ret;
40
41         ret = LDB_SUCCESS;
42
43         switch(om_syntax) {
44         case 1:
45                 *syntax = SCHEMA_AS_BOOLEAN;
46                 break;
47         case 2:
48                 *syntax = SCHEMA_AS_INTEGER;
49                 break;
50         case 4:
51                 if (strcmp(attr_syntax, "2.5.5.10") == 0) {
52                         *syntax = SCHEMA_AS_OCTET_STRING;
53                         break;
54                 }
55                 if (strcmp(attr_syntax, "2.5.5.17") == 0) {
56                         *syntax = SCHEMA_AS_SID;
57                         break;
58                 }
59                 ret = LDB_ERR_OPERATIONS_ERROR;
60                 break;
61         case 6:
62                 *syntax = SCHEMA_AS_OID;
63                 break;
64         case 10:
65                 *syntax = SCHEMA_AS_ENUMERATION;
66                 break;
67         case 18:
68                 *syntax = SCHEMA_AS_NUMERIC_STRING;
69                 break;
70         case 19:
71                 *syntax = SCHEMA_AS_PRINTABLE_STRING;
72                 break;
73         case 20:
74                 *syntax = SCHEMA_AS_CASE_IGNORE_STRING;
75                 break;
76         case 22:
77                 *syntax = SCHEMA_AS_IA5_STRING;
78                 break;
79         case 23:
80                 *syntax = SCHEMA_AS_UTC_TIME;
81                 break;
82         case 24:
83                 *syntax = SCHEMA_AS_GENERALIZED_TIME;
84                 break;
85         case 27:
86                 *syntax = SCHEMA_AS_CASE_SENSITIVE_STRING;
87                 break;
88         case 64:
89                 *syntax = SCHEMA_AS_DIRECTORY_STRING;
90                 break;
91         case 65:
92                 *syntax = SCHEMA_AS_LARGE_INTEGER;
93                 break;
94         case 66:
95                 *syntax = SCHEMA_AS_OBJECT_SECURITY_DESCRIPTOR;
96                 break;
97         case 127:
98                 if (!om_class) {
99                         ret = LDB_ERR_OPERATIONS_ERROR;
100                         break;
101                 }
102                 
103                 if (memcmp(om_class->data, "\x2b\x0c\x02\x87\x73\x1c\x00\x85\x4a\x00", MIN(om_class->length, 10)) == 0) {
104                         *syntax = SCHEMA_AS_DN;
105                         break;
106                 }
107                 if (memcmp(om_class->data, "\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0b", MIN(om_class->length, 10)) == 0) {
108                         *syntax = SCHEMA_AS_DN_BINARY;
109                         break;
110                 }
111                 if (memcmp(om_class->data, "\x56\x06\x01\x02\x05\x0b\x1d\x00\x00\x00", MIN(om_class->length, 10)) == 0) {
112                         *syntax = SCHEMA_AS_OR_NAME;
113                         break;
114                 }
115                 if (memcmp(om_class->data, "\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x06", MIN(om_class->length, 10)) == 0) {
116                         *syntax = SCHEMA_AS_REPLICA_LINK;
117                         break;
118                 }
119                 if (memcmp(om_class->data, "\x2b\x0c\x02\x87\x73\x1c\x00\x85\x5c\x00", MIN(om_class->length, 10)) == 0) {
120                         *syntax = SCHEMA_AS_PRESENTATION_ADDRESS;
121                         break;
122                 }
123                 if (memcmp(om_class->data, "\x2b\x0c\x02\x87\x73\x1c\x00\x85\x3e\x00", MIN(om_class->length, 10)) == 0) {
124                         *syntax = SCHEMA_AS_ACCESS_POINT;
125                         break;
126                 }
127                 if (memcmp(om_class->data, "\x2a\x86\x48\x86\xf7\x14\x01\x01\x01\x0c", MIN(om_class->length, 10)) == 0) {
128                         *syntax = SCHEMA_AS_DN_STRING;
129                         break;
130                 }
131                 /* not found will error in default: */
132         default:
133                 ret = LDB_ERR_OPERATIONS_ERROR;
134         }
135
136         return ret;
137 }
138
139 static int schema_validate_boolean(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
140 {
141
142         if ((strncmp("TRUE", (const char *)val->data, val->length) != 0) &&
143             (strncmp("FALSE", (const char *)val->data, val->length) != 0)) {
144                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
145         }
146
147         return LDB_SUCCESS;
148 }
149
150 static int schema_validate_integer(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
151 {
152         int value;
153         char *endptr;
154
155         errno = 0;
156         value = strtol((const char *)val->data, &endptr, 0);
157         if (errno) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
158         if (endptr[0] != '\0') return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
159         if ((min > INT_MIN) && (value < min)) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
160         if ((max < INT_MAX) && (value > max)) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
161
162         return LDB_SUCCESS;
163 }
164
165 static int schema_validate_binary_blob(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
166 {
167         /* is there anythign we should check in a binary blob ? */
168         return LDB_SUCCESS;
169 }
170
171 static int schema_validate_sid(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
172 {
173         /* TODO: validate binary form of objectSid */
174         return LDB_SUCCESS;     
175 }
176
177 static int schema_validate_oid(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
178 {
179         if (strspn((const char *)val->data, "0123456789.") != val->length)
180                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
181
182         return LDB_SUCCESS;
183 }
184
185 static int schema_validate_numeric_string(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
186 {
187         if (strspn((const char *)val->data, "0123456789") != val->length)
188                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
189
190         return LDB_SUCCESS;
191 }
192
193 static int schema_validate_printable_string(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
194 {
195         /* TODO: find out what constitutes the printable character set */
196         return LDB_SUCCESS;
197 }
198
199 static int schema_validate_teletext_string(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
200 {
201         /* TODO: find out what constitutes the teletext character set */
202         return LDB_SUCCESS;
203 }
204
205 static int schema_validate_ia5_string(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
206 {
207         /* TODO: find out what constitutes the IA5 character set */
208         return LDB_SUCCESS;
209 }
210
211 static int schema_validate_utc_time(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
212 {
213         /* TODO: validate syntax of UTC Time string */
214         return LDB_SUCCESS;
215 }
216
217 static int schema_validate_generalized_time(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
218 {
219         /* TODO: validate syntax of Generalized Time string */
220         return LDB_SUCCESS;
221 }
222
223 /* NOTE: not a single attribute has this syntax in the basic w2k3 schema */
224 static int schema_validate_sensitive_string(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
225 {
226         /* TODO: find out what constitutes a "case sensitive string" */
227         return LDB_SUCCESS;
228 }
229
230 static int schema_validate_unicode_string(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
231 {
232         /* TODO: validate utf8 string */
233         return LDB_SUCCESS;
234 }
235
236 static int schema_validate_large_integer(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
237 {
238         /* TODO: validate large integer/interval */
239         return LDB_SUCCESS;
240 }
241
242 static int schema_validate_object_sd(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
243 {
244         /* TODO: validate object Security Descriptor */
245         return LDB_SUCCESS;
246 }
247
248 static int schema_validate_dn(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
249 {
250         struct ldb_dn *dn;
251         int ret = LDB_SUCCESS;
252
253         dn = ldb_dn_new(ldb, ldb, (const char *)val->data);
254         if ( ! ldb_dn_validate(dn)) {
255                 ret = LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
256         }
257
258         talloc_free(dn);
259         return ret;
260 }
261
262 static int schema_validate_binary_plus_dn(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
263 {
264         int ret = LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
265         TALLOC_CTX *memctx;
266         struct ldb_dn *dn;
267         char *str, *p;
268         char *endptr;
269         int num;
270        
271         memctx = talloc_new(NULL);
272         if (!memctx) return LDB_ERR_OPERATIONS_ERROR;
273
274         str = talloc_strdup(memctx, (const char *)val->data);
275         if (!str) {
276                 ret = LDB_ERR_OPERATIONS_ERROR;
277                 goto done;
278         }
279         if (strncasecmp(str, "B:", 2) != 0) {
280                 goto done;
281         }
282
283         /* point at the number of chars in the string */
284         str = strchr(&str[2], ':');
285         if (!str) {
286                 goto done;
287         }
288         str++;
289
290         errno = 0;
291         num = strtol(str, &endptr, 0);
292         if (errno) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
293         if (endptr[0] != ':') return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
294         if ((min > INT_MIN) && (num < min)) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
295         if ((max < INT_MAX) && (num > max)) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
296
297         /* point at the string */
298         str = strchr(str, ':');
299         if (!str) {
300                 goto done;
301         }
302         str++;
303
304         /* terminate the string */
305         p = strchr(str, ':');
306         if (!p) {
307                 goto done;
308         }
309         *p = '\0';
310
311         if (strlen(str) != 2*num) {
312                 goto done;
313         }
314
315         str = p + 1;
316
317         dn = ldb_dn_new(memctx, ldb, str);
318         if (ldb_dn_validate(dn)) {
319                 ret = LDB_SUCCESS;
320         }
321
322 done:
323         talloc_free(memctx);
324         return ret;
325 }
326
327 static int schema_validate_x400_or_name(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
328 {
329         /* TODO: find out what is the syntax of an X400 OR NAME */
330         return LDB_SUCCESS;
331 }
332
333 static int schema_validate_presentation_address(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
334 {
335         /* TODO: find out what is the syntax of a presentation address */
336         return LDB_SUCCESS;
337 }
338
339 static int schema_validate_x400_access_point(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
340 {
341         /* TODO: find out what is the syntax of an X400 Access Point */
342         return LDB_SUCCESS;
343 }
344
345 /* NOTE: seem there isn't a single attribute defined like this in the base w2k3 schema */
346 static int schema_validate_string_plus_dn(struct ldb_context *ldb, struct ldb_val *val, int min, int max)
347 {
348         int ret = LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
349         TALLOC_CTX *memctx;
350         struct ldb_dn *dn;
351         char *str, *p;
352         char *endptr;
353         int num;
354        
355         memctx = talloc_new(NULL);
356         if (!memctx) return LDB_ERR_OPERATIONS_ERROR;
357
358         str = talloc_strdup(memctx, (const char *)val->data);
359         if (!str) {
360                 ret = LDB_ERR_OPERATIONS_ERROR;
361                 goto done;
362         }
363         if (strncasecmp(str, "S:", 2) != 0) {
364                 goto done;
365         }
366
367         /* point at the number of chars in the string */
368         str = strchr(&str[2], ':');
369         if (!str) {
370                 goto done;
371         }
372         str++;
373
374         errno = 0;
375         num = strtol(str, &endptr, 0);
376         if (errno) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
377         if (endptr[0] != ':') return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
378         if ((min > INT_MIN) && (num < min)) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
379         if ((max < INT_MAX) && (num > max)) return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
380
381         /* point at the string */
382         str = strchr(str, ':');
383         if (!str) {
384                 goto done;
385         }
386         str++;
387
388         /* terminate the string */
389         p = strchr(str, ':');
390         if (!p) {
391                 goto done;
392         }
393         *p = '\0';
394
395         if (strlen(str) != num) {
396                 goto done;
397         }
398
399         str = p + 1;
400
401         dn = ldb_dn_new(memctx, ldb, str);
402         if (ldb_dn_validate(dn)) {
403                 ret = LDB_SUCCESS;
404         }
405
406 done:
407         talloc_free(memctx);
408         return ret;
409 }
410
411 struct schema_syntax_validator {
412         enum schema_internal_syntax type;
413         int (*validate)(struct ldb_context *ldb, struct ldb_val *, int, int);
414 };
415
416 struct schema_syntax_validator schema_syntax_validators[] = {
417         { SCHEMA_AS_BOOLEAN, schema_validate_boolean },
418         { SCHEMA_AS_INTEGER, schema_validate_integer },
419         { SCHEMA_AS_OCTET_STRING, schema_validate_binary_blob },
420         { SCHEMA_AS_SID, schema_validate_sid },
421         { SCHEMA_AS_OID, schema_validate_oid },
422         { SCHEMA_AS_ENUMERATION, schema_validate_integer },
423         { SCHEMA_AS_NUMERIC_STRING, schema_validate_numeric_string },
424         { SCHEMA_AS_PRINTABLE_STRING, schema_validate_printable_string },
425         { SCHEMA_AS_CASE_IGNORE_STRING, schema_validate_teletext_string },
426         { SCHEMA_AS_IA5_STRING, schema_validate_ia5_string },
427         { SCHEMA_AS_UTC_TIME, schema_validate_utc_time },
428         { SCHEMA_AS_GENERALIZED_TIME, schema_validate_generalized_time },
429         { SCHEMA_AS_CASE_SENSITIVE_STRING, schema_validate_sensitive_string },
430         { SCHEMA_AS_DIRECTORY_STRING, schema_validate_unicode_string },
431         { SCHEMA_AS_LARGE_INTEGER, schema_validate_large_integer },
432         { SCHEMA_AS_OBJECT_SECURITY_DESCRIPTOR, schema_validate_object_sd },
433         { SCHEMA_AS_DN, schema_validate_dn },
434         { SCHEMA_AS_DN_BINARY, schema_validate_binary_plus_dn },
435         { SCHEMA_AS_OR_NAME, schema_validate_x400_or_name },
436         { SCHEMA_AS_REPLICA_LINK, schema_validate_binary_blob },
437         { SCHEMA_AS_PRESENTATION_ADDRESS, schema_validate_presentation_address }, /* see rfc1278 ? */
438         { SCHEMA_AS_ACCESS_POINT, schema_validate_x400_access_point },
439         { SCHEMA_AS_DN_STRING, schema_validate_string_plus_dn },
440         { -1, NULL }
441 };
442
443 int schema_validate(struct ldb_context *ldb,
444                     struct ldb_message_element *el,
445                     enum schema_internal_syntax type,
446                     bool single, int min, int max)
447 {
448         struct schema_syntax_validator *v;
449         int i, ret;
450
451         if (single && (el->num_values > 1)) {
452                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
453         }
454
455         for (i = 0; schema_syntax_validators[i].type != 0; i++) {
456                 if (schema_syntax_validators[i].type == type)
457                         break;
458         }
459         if (schema_syntax_validators[i].type == 0) {
460                 return LDB_ERR_OPERATIONS_ERROR;
461         }
462         v = &schema_syntax_validators[i];
463         
464         for (i = 0; i < el->num_values; i++) {
465                 ret = v->validate(ldb, &el->values[i], min, max);
466         }
467
468         return LDB_SUCCESS;
469 }
470
471