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