Merge branch 'master' of ssh://git.samba.org/data/git/samba
[ira/wip.git] / source4 / dsdb / schema / schema_description.c
1 /* 
2    Unix SMB/CIFS mplementation.
3    Print schema info into string format
4    
5    Copyright (C) Andrew Bartlett 2006-2008
6     
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19    
20 */
21 #include "includes.h"
22 #include "dsdb/samdb/samdb.h"
23 #include "librpc/ndr/libndr.h"
24
25 #define IF_NULL_FAIL_RET(x) do {     \
26                 if (!x) {               \
27                         return NULL;    \
28                 }                       \
29         } while (0) 
30
31
32 char *schema_attribute_description(TALLOC_CTX *mem_ctx, 
33                                           enum dsdb_schema_convert_target target,
34                                           const char *seperator,
35                                           const char *oid, 
36                                           const char *name,
37                                           const char *equality, 
38                                           const char *substring, 
39                                           const char *syntax,
40                                           bool single_value, bool operational,
41                                           uint32_t *range_lower,
42                                           uint32_t *range_upper,
43                                           const char *property_guid,
44                                           const char *property_set_guid,
45                                           bool indexed, bool system_only)
46 {
47         char *schema_entry = talloc_asprintf(mem_ctx, 
48                                              "(%s%s%s", seperator, oid, seperator);
49         
50         schema_entry = talloc_asprintf_append(schema_entry, 
51                                               "NAME '%s'%s", name, seperator);
52         IF_NULL_FAIL_RET(schema_entry);
53         
54         if (equality) {
55                 schema_entry = talloc_asprintf_append(schema_entry, 
56                                                       "EQUALITY %s%s", equality, seperator);
57                 IF_NULL_FAIL_RET(schema_entry);
58         }
59         if (substring) {
60                 schema_entry = talloc_asprintf_append(schema_entry, 
61                                                       "SUBSTR %s%s", substring, seperator);
62                 IF_NULL_FAIL_RET(schema_entry);
63         }
64
65         if (syntax) {
66                 schema_entry = talloc_asprintf_append(schema_entry,
67                                                       "SYNTAX %s%s", syntax, seperator);
68                 IF_NULL_FAIL_RET(schema_entry);
69         }
70
71         if (single_value) {
72                 schema_entry = talloc_asprintf_append(schema_entry, 
73                                                       "SINGLE-VALUE%s", seperator);
74                 IF_NULL_FAIL_RET(schema_entry);
75         }
76         
77         if (operational) {
78                 schema_entry = talloc_asprintf_append(schema_entry, 
79                                                       "NO-USER-MODIFICATION%s", seperator);
80                 IF_NULL_FAIL_RET(schema_entry);
81         }
82
83         if (range_lower) {
84                 schema_entry = talloc_asprintf_append(schema_entry,
85                                                       "RANGE-LOWER '%u'%s",
86                                                       *range_lower, seperator);
87                 IF_NULL_FAIL_RET(schema_entry);
88         }
89
90         if (range_upper) {
91                 schema_entry = talloc_asprintf_append(schema_entry,
92                                                       "RANGE-UPPER '%u'%s",
93                                                       *range_upper, seperator);
94                 IF_NULL_FAIL_RET(schema_entry);
95         }
96
97         if (property_guid) {
98                 schema_entry = talloc_asprintf_append(schema_entry,
99                                                       "PROPERTY-GUID '%s'%s",
100                                                       property_guid, seperator);
101                 IF_NULL_FAIL_RET(schema_entry);
102         }
103
104         if (property_set_guid) {
105                 schema_entry = talloc_asprintf_append(schema_entry,
106                                                       "PROPERTY-SET-GUID '%s'%s",
107                                                       property_set_guid, seperator);
108                 IF_NULL_FAIL_RET(schema_entry);
109         }
110
111         if (indexed) {
112                 schema_entry = talloc_asprintf_append(schema_entry,
113                                                       "INDEXED%s", seperator);
114                 IF_NULL_FAIL_RET(schema_entry);
115         }
116
117         if (system_only) {
118                 schema_entry = talloc_asprintf_append(schema_entry,
119                                                       "SYSTEM-ONLY%s", seperator);
120                 IF_NULL_FAIL_RET(schema_entry);
121         }
122
123         schema_entry = talloc_asprintf_append(schema_entry, 
124                                               ")");
125         return schema_entry;
126 }
127
128 char *schema_attribute_to_description(TALLOC_CTX *mem_ctx, const struct dsdb_attribute *attribute) 
129 {
130         char *schema_description;
131         const char *syntax = attribute->syntax->ldap_oid;
132         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
133         if (!tmp_ctx) {
134                 return NULL;
135         }
136
137         schema_description 
138                 = schema_attribute_description(mem_ctx, 
139                                                TARGET_AD_SCHEMA_SUBENTRY,
140                                                " ",
141                                                attribute->attributeID_oid,
142                                                attribute->lDAPDisplayName,
143                                                NULL, NULL, talloc_asprintf(tmp_ctx, "'%s'", syntax),
144                                                attribute->isSingleValued,
145                                                attribute->systemOnly,/* TODO: is this correct? */
146                                                NULL, NULL, NULL, NULL,
147                                                false, false);
148         talloc_free(tmp_ctx);
149         return schema_description;
150 }
151
152 char *schema_attribute_to_extendedInfo(TALLOC_CTX *mem_ctx, const struct dsdb_attribute *attribute)
153 {
154         char *schema_description;
155         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
156         if (!tmp_ctx) {
157                 return NULL;
158         }
159
160         schema_description
161                 = schema_attribute_description(mem_ctx,
162                                                TARGET_AD_SCHEMA_SUBENTRY,
163                                                " ",
164                                                attribute->attributeID_oid,
165                                                attribute->lDAPDisplayName,
166                                                NULL, NULL, NULL,
167                                                false, false,
168                                                attribute->rangeLower,
169                                                attribute->rangeUpper,
170                                                GUID_hexstring(tmp_ctx, &attribute->schemaIDGUID),
171                                                GUID_hexstring(tmp_ctx, &attribute->attributeSecurityGUID),
172                                                (attribute->searchFlags & SEARCH_FLAG_ATTINDEX),
173                                                attribute->systemOnly);
174         talloc_free(tmp_ctx);
175         return schema_description;
176 }
177
178 #define APPEND_ATTRS(attributes)                                \
179         do {                                                            \
180                 int k;                                                  \
181                 for (k=0; attributes && attributes[k]; k++) {           \
182                         const char *attr_name = attributes[k];          \
183                                                                         \
184                         schema_entry = talloc_asprintf_append(schema_entry, \
185                                                               "%s ",    \
186                                                               attr_name); \
187                         IF_NULL_FAIL_RET(schema_entry);                 \
188                         if (attributes[k+1]) {                          \
189                                 IF_NULL_FAIL_RET(schema_entry);         \
190                                 if (target == TARGET_OPENLDAP && ((k+1)%5 == 0)) { \
191                                         schema_entry = talloc_asprintf_append(schema_entry, \
192                                                                               "$%s ", seperator); \
193                                         IF_NULL_FAIL_RET(schema_entry); \
194                                 } else {                                \
195                                         schema_entry = talloc_asprintf_append(schema_entry, \
196                                                                               "$ "); \
197                                 }                                       \
198                         }                                               \
199                 }                                                       \
200         } while (0)
201         
202
203 /* Print a schema class or dITContentRule as a string.  
204  *
205  * To print a scheam class, specify objectClassCategory but not auxillary_classes
206  * To print a dITContentRule, specify auxillary_classes but set objectClassCategory == -1
207  *
208  */
209
210 char *schema_class_description(TALLOC_CTX *mem_ctx, 
211                                enum dsdb_schema_convert_target target,
212                                const char *seperator,
213                                const char *oid, 
214                                const char *name,
215                                const char **auxillary_classes,
216                                const char *subClassOf,
217                                int objectClassCategory,
218                                char **must,
219                                char **may,
220                                const char *schemaHexGUID)
221 {
222         char *schema_entry = talloc_asprintf(mem_ctx, 
223                                              "(%s%s%s", seperator, oid, seperator);
224         
225         IF_NULL_FAIL_RET(schema_entry);
226
227         schema_entry = talloc_asprintf_append(schema_entry, 
228                                               "NAME '%s'%s", name, seperator);
229         IF_NULL_FAIL_RET(schema_entry);
230         
231         if (auxillary_classes) {
232                 schema_entry = talloc_asprintf_append(schema_entry, 
233                                                       "AUX ( ");
234                 IF_NULL_FAIL_RET(schema_entry);
235                 
236                 APPEND_ATTRS(auxillary_classes);
237                 
238                 schema_entry = talloc_asprintf_append(schema_entry, 
239                                                       ")%s", seperator);
240                 IF_NULL_FAIL_RET(schema_entry);
241         }
242
243         if (subClassOf && strcasecmp(subClassOf, name) != 0) {
244                 schema_entry = talloc_asprintf_append(schema_entry, 
245                                                       "SUP %s%s", subClassOf, seperator);
246                 IF_NULL_FAIL_RET(schema_entry);
247         }
248         
249         switch (objectClassCategory) {
250         case -1:
251                 break;
252                 /* Dummy case for when used for printing ditContentRules */
253         case 0:
254                 /*
255                  * NOTE: this is an type 88 class
256                  *       e.g. 2.5.6.6 NAME 'person'
257                  *       but w2k3 gives STRUCTURAL here!
258                  */
259                 schema_entry = talloc_asprintf_append(schema_entry, 
260                                                       "STRUCTURAL%s", seperator);
261                 IF_NULL_FAIL_RET(schema_entry);
262                 break;
263         case 1:
264                 schema_entry = talloc_asprintf_append(schema_entry, 
265                                                       "STRUCTURAL%s", seperator);
266                 IF_NULL_FAIL_RET(schema_entry);
267                 break;
268         case 2:
269                 schema_entry = talloc_asprintf_append(schema_entry, 
270                                                       "ABSTRACT%s", seperator);
271                 IF_NULL_FAIL_RET(schema_entry);
272                 break;
273         case 3:
274                 schema_entry = talloc_asprintf_append(schema_entry, 
275                                                       "AUXILIARY%s", seperator);
276                 IF_NULL_FAIL_RET(schema_entry);
277                 break;
278         }
279         
280         if (must) {
281                 schema_entry = talloc_asprintf_append(schema_entry, 
282                                                       "MUST (%s", target == TARGET_AD_SCHEMA_SUBENTRY ? "" : " ");
283                 IF_NULL_FAIL_RET(schema_entry);
284                 
285                 APPEND_ATTRS(must);
286                 
287                 schema_entry = talloc_asprintf_append(schema_entry, 
288                                                       ")%s", seperator);
289                 IF_NULL_FAIL_RET(schema_entry);
290         }
291         
292         if (may) {
293                 schema_entry = talloc_asprintf_append(schema_entry, 
294                                                       "MAY (%s", target == TARGET_AD_SCHEMA_SUBENTRY ? "" : " ");
295                 IF_NULL_FAIL_RET(schema_entry);
296                 
297                 APPEND_ATTRS(may);
298                 
299                 schema_entry = talloc_asprintf_append(schema_entry, 
300                                                       ")%s", seperator);
301                 IF_NULL_FAIL_RET(schema_entry);
302         }
303
304         if (schemaHexGUID) {
305                 schema_entry = talloc_asprintf_append(schema_entry,
306                                                       "CLASS-GUID '%s'%s",
307                                                       schemaHexGUID, seperator);
308                 IF_NULL_FAIL_RET(schema_entry);
309         }
310
311         schema_entry = talloc_asprintf_append(schema_entry, 
312                                               ")");
313         return schema_entry;
314 }
315
316 char *schema_class_to_description(TALLOC_CTX *mem_ctx, const struct dsdb_class *class) 
317 {
318         char *schema_description;
319         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
320         if (!tmp_ctx) {
321                 return NULL;
322         }
323         
324         schema_description
325                 = schema_class_description(mem_ctx, 
326                                            TARGET_AD_SCHEMA_SUBENTRY,
327                                            " ",
328                                            class->governsID_oid,
329                                            class->lDAPDisplayName,
330                                            NULL, 
331                                            class->subClassOf,
332                                            class->objectClassCategory,
333                                            dsdb_attribute_list(tmp_ctx, 
334                                                                class, DSDB_SCHEMA_ALL_MUST),
335                                            dsdb_attribute_list(tmp_ctx, 
336                                                                class, DSDB_SCHEMA_ALL_MAY),
337                                            NULL);
338         talloc_free(tmp_ctx);
339         return schema_description;
340 }
341 char *schema_class_to_dITContentRule(TALLOC_CTX *mem_ctx, const struct dsdb_class *class,
342                                      const struct dsdb_schema *schema) 
343 {
344         int i;
345         char *schema_description;
346         char **aux_class_list = NULL;
347         char **attrs;
348         char **must_attr_list = NULL;
349         char **may_attr_list = NULL;
350         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
351         const struct dsdb_class *aux_class;
352         if (!tmp_ctx) {
353                 return NULL;
354         }
355
356         aux_class_list = merge_attr_list(tmp_ctx, aux_class_list, class->systemAuxiliaryClass);
357         aux_class_list = merge_attr_list(tmp_ctx, aux_class_list, class->auxiliaryClass);
358
359         for (i=0; aux_class_list && aux_class_list[i]; i++) {
360                 aux_class = dsdb_class_by_lDAPDisplayName(schema, aux_class_list[i]);
361                 
362                 attrs = dsdb_attribute_list(mem_ctx, aux_class, DSDB_SCHEMA_ALL_MUST);
363                 must_attr_list = merge_attr_list(mem_ctx, must_attr_list, attrs);
364
365                 attrs = dsdb_attribute_list(mem_ctx, aux_class, DSDB_SCHEMA_ALL_MAY);
366                 may_attr_list = merge_attr_list(mem_ctx, may_attr_list, attrs);
367         }
368
369         schema_description
370                 = schema_class_description(mem_ctx, 
371                                            TARGET_AD_SCHEMA_SUBENTRY,
372                                            " ",
373                                            class->governsID_oid,
374                                            class->lDAPDisplayName,
375                                            (const char **)aux_class_list,
376                                            NULL, /* Must not specify a
377                                                   * SUP (subclass) in
378                                                   * ditContentRules
379                                                   * per MS-ADTS
380                                                   * 3.1.1.3.1.1.1 */
381                                            -1, must_attr_list, may_attr_list,
382                                            NULL);
383         talloc_free(tmp_ctx);
384         return schema_description;
385 }
386
387 char *schema_class_to_extendedInfo(TALLOC_CTX *mem_ctx, const struct dsdb_class *sclass)
388 {
389         char *schema_description = NULL;
390         DATA_BLOB guid_blob;
391         char *guid_hex;
392         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
393         if (!tmp_ctx) {
394                 return NULL;
395         }
396
397         schema_description
398                 = schema_class_description(mem_ctx,
399                                            TARGET_AD_SCHEMA_SUBENTRY,
400                                            " ",
401                                            sclass->governsID_oid,
402                                            sclass->lDAPDisplayName,
403                                            NULL,
404                                            NULL, /* Must not specify a
405                                                   * SUP (subclass) in
406                                                   * ditContentRules
407                                                   * per MS-ADTS
408                                                   * 3.1.1.3.1.1.1 */
409                                            -1, NULL, NULL,
410                                            GUID_hexstring(tmp_ctx, &sclass->schemaIDGUID));
411         talloc_free(tmp_ctx);
412         return schema_description;
413 }
414
415