2 Unix SMB/CIFS implementation.
4 Copyright (C) Simo Sorce 2004
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.
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.
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.
22 #include "ldap_parse.h"
24 static char char_from_hex(char a, char b) {
27 if ('0' <= a && a <= '9') {
29 } else if ('A' <= a && a <= 'F') {
31 } else if ('a' <= a && a <= 'f') {
37 if ('0' <= b && b <= '9') {
39 } else if ('A' <= b && b <= 'F') {
41 } else if ('a' <= b && b <= 'f') {
47 return ((m << 4) + l);
50 static char *parse_slash(char *p, char *end) {
62 memmove(p, p + 1, end - (p + 1));
65 *p = char_from_hex(*(p + 1), *(p + 2));
66 memmove(p + 1, p + 3, end - (p + 3));
71 #define LDAP_PARSE_DN_INVALID(x) do {\
79 static void ldap_parse_attributetypedescription(struct ldap_schema *schema, DATA_BLOB *data)
83 desc = talloc_array(schema, char, data->lenght + 1);
84 memcpy(desc, data->data, data->lenght);
85 desc[data->lenght] = '\0';
89 static void ldap_parse_objectclassdescription(struct ldap_schema *schema, DATA_BLOB *data)
93 desc = talloc_array(schema, char, data->lenght + 1);
94 memcpy(desc, data->data, data->lenght);
95 desc[data->lenght] = '\0';
99 static struct ldap_schema *ldap_get_schema(void *mem_ctx, struct ldap_schema *schema, struct ldb_context *ldb)
102 struct ldap_schema *local_schema;
103 struct ldb_message **res;
105 const char *schema_dn = "cn=schema";
106 const char *attr_filter = "attributeTypeDescription=*";
107 const char *class_filter = "objectClassDescription=*";
108 const char *attrs = "attributeTypeDescription";
109 const char *classes = "objectClassDescription";
110 enum ldb_scope scope = LDAP_SCOPE_SUBTREE;
113 local_schema = schema;
114 if (local_schema == NULL) {
115 local_schema = talloc(mem_ctx, struct ldap_schema);
116 ALLOC_CHECK(local_schema);
119 count = ldb_search(ldb, schema_dn, scope, attr_filter, attrs, &res);
121 for (i = 0; i < count; i++) {
122 if (res[i]->num_elements == 0) {
125 for (j = 0; j < res[i]->num_elements; j++) {
126 for (k = 0; res[i]->elements[j].num_values; k++) {
127 ldap_parse_attributetypedescription(local_schema, &(res[i]->elements[j].values[k]));
133 count = ldb_search(ldb, schema_dn, scope, class_filter, classes, &res);
135 for (i = 0; i < count; i++) {
136 if (res[i]->num_elements == 0) {
139 for (j = 0; j < res[i]->num_elements; j++) {
140 for (k = 0; res[i]->elements[j].num_values; k++) {
141 ldap_parse_objectclassdescription(local_schema, &(res[i]->elements[j].values[k]));
151 struct ldap_dn *ldap_parse_dn(void *mem_ctx, const char *orig_dn)
154 struct dn_component *component;
155 struct dn_attribute *attribute;
156 char *p, *start, *separator, *src, *dest, *dn_copy, *dn_end;
157 int i, size, orig_len;
159 dn = talloc(mem_ctx, struct ldap_dn);
161 dn->components = talloc_array(dn, struct dn_component *, 1);
162 component = talloc(dn, struct dn_component);
163 component->attr_num = 0;
165 orig_len = strlen(orig_dn);
167 dn->dn = talloc_strdup(dn, orig_dn);
171 dn_copy = p = talloc_strdup(mem_ctx, orig_dn);
172 dn_end = dn_copy + orig_len + 1;
174 component->attributes = talloc_array(component, struct dn_attribute *, 1);
175 attribute = talloc(component, struct dn_attribute);
178 while (*p == ' ' || *p == '\n') {
182 /* start parsing this component */
186 /* find out key separator '=' */
187 while (*p && *p != '=') {
189 dn_end = parse_slash(p, dn_end);
196 while (*(p - 1) == ' ' || *(p - 1) == '\n') {
201 LDAP_PARSE_DN_INVALID((p - start) < 1);
202 attribute->name = talloc_strndup(attribute, start, p - start);
203 DEBUG(10, ("attribute name: [%s]\n", attribute->name));
207 /* skip spaces past the separator */
208 p = separator + strspn(p, " \n") + 1;
211 /* check if the value is enclosed in QUOTATION */
214 while (*p && *p != '"') {
216 dn_end = parse_slash(p, dn_end);
221 /* skip spaces until the separator */
222 separator = p + strspn(p, " \n");
224 if (*separator != ',' && *separator != ';' && *separator != '+') { /* there must be a separator here */
225 /* Error Malformed DN */
226 DEBUG (0, ("Error: Malformed DN!\n"));
230 while (*p && !(*p == ',' || *p == ';' || *p == '+')) {
232 dn_end = parse_slash(p, dn_end);
235 } /* found separator */
240 while (*(p - 1) == ' ' || *(p - 1) == '\n') {
246 LDAP_PARSE_DN_INVALID((p - start) < 1);
247 attribute->value = talloc_strndup(attribute, start, p - start);
248 DEBUG(10, ("attribute value: [%s]\n", attribute->value));
250 attribute->attribute = talloc_asprintf(attribute,"%s=%s", attribute->name, attribute->value);
251 DEBUG(10, ("attribute: [%s]\n", attribute->attribute));
253 /* save the attribute */
254 component->attributes[component->attr_num] = attribute;
255 component->attr_num++;
257 if (*separator == '+') { /* expect other attributes in this component */
258 component->attributes = talloc_realloc(component, component->attributes, struct dn_attribute *, component->attr_num + 1);
260 /* allocate new attribute structure */
261 attribute = talloc(component, struct dn_attribute);
263 /* skip spaces past the separator */
264 p = separator + strspn(p, " \n");
267 } while (*separator == '+');
269 /* found component bounds */
270 for (i = 0, size = 0; i < component->attr_num; i++) {
271 size = size + strlen(component->attributes[i]->attribute) + 1;
274 /* rebuild the normlaized component and put it here */
275 component->component = dest = talloc_size(component, size);
276 for (i = 0; i < component->attr_num; i++) {
281 src = component->attributes[i]->attribute;
283 *(dest++) = *(src++);
287 DEBUG(10, ("component: [%s]\n", component->component));
289 dn->components[dn->comp_num] = component;
292 if (*separator == ',' || *separator == ';') {
293 dn->components = talloc_realloc(dn, dn->components, struct dn_component *, dn->comp_num + 1);
294 component = talloc(dn, struct dn_component);
295 component->attr_num = 0;
299 } while(*separator == ',' || *separator == ';');
301 for (i = 0, size = 0; i < dn->comp_num; i++) {
302 size = size + strlen(dn->components[i]->component) + 1;
305 /* rebuild the normlaized dn and put it here */
306 dn->dn = dest = talloc_size(dn, size);
307 for (i = 0; i < dn->comp_num; i++) {
312 src = dn->components[i]->component;
314 *(dest++) = *(src++);
318 DEBUG(10, ("dn: [%s]\n", dn->dn));
320 talloc_free(dn_copy);