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