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