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 32char *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 128char *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 152char *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 210char *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 const char **must, 219 const 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 316char *schema_class_to_description(TALLOC_CTX *mem_ctx, const struct dsdb_class *sclass) 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 sclass->governsID_oid, 329 sclass->lDAPDisplayName, 330 NULL, 331 sclass->subClassOf, 332 sclass->objectClassCategory, 333 dsdb_attribute_list(tmp_ctx, 334 sclass, DSDB_SCHEMA_ALL_MUST), 335 dsdb_attribute_list(tmp_ctx, 336 sclass, DSDB_SCHEMA_ALL_MAY), 337 NULL); 338 talloc_free(tmp_ctx); 339 return schema_description; 340} 341 342char *schema_class_to_dITContentRule(TALLOC_CTX *mem_ctx, const struct dsdb_class *sclass, 343 const struct dsdb_schema *schema) 344{ 345 int i; 346 char *schema_description; 347 const char **aux_class_list = NULL; 348 const char **attrs; 349 const char **must_attr_list = NULL; 350 const char **may_attr_list = NULL; 351 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 352 const struct dsdb_class *aux_class; 353 if (!tmp_ctx) { 354 return NULL; 355 } 356 357 aux_class_list = merge_attr_list(tmp_ctx, aux_class_list, sclass->systemAuxiliaryClass); 358 aux_class_list = merge_attr_list(tmp_ctx, aux_class_list, sclass->auxiliaryClass); 359 360 for (i=0; aux_class_list && aux_class_list[i]; i++) { 361 aux_class = dsdb_class_by_lDAPDisplayName(schema, aux_class_list[i]); 362 363 attrs = dsdb_attribute_list(mem_ctx, aux_class, DSDB_SCHEMA_ALL_MUST); 364 must_attr_list = merge_attr_list(mem_ctx, must_attr_list, attrs); 365 366 attrs = dsdb_attribute_list(mem_ctx, aux_class, DSDB_SCHEMA_ALL_MAY); 367 may_attr_list = merge_attr_list(mem_ctx, may_attr_list, attrs); 368 } 369 370 schema_description 371 = schema_class_description(mem_ctx, 372 TARGET_AD_SCHEMA_SUBENTRY, 373 " ", 374 sclass->governsID_oid, 375 sclass->lDAPDisplayName, 376 (const char **)aux_class_list, 377 NULL, /* Must not specify a 378 * SUP (subclass) in 379 * ditContentRules 380 * per MS-ADTS 381 * 3.1.1.3.1.1.1 */ 382 -1, must_attr_list, may_attr_list, 383 NULL); 384 talloc_free(tmp_ctx); 385 return schema_description; 386} 387 388char *schema_class_to_extendedInfo(TALLOC_CTX *mem_ctx, const struct dsdb_class *sclass) 389{ 390 char *schema_description = NULL; 391 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 392 if (!tmp_ctx) { 393 return NULL; 394 } 395 396 schema_description 397 = schema_class_description(mem_ctx, 398 TARGET_AD_SCHEMA_SUBENTRY, 399 " ", 400 sclass->governsID_oid, 401 sclass->lDAPDisplayName, 402 NULL, 403 NULL, /* Must not specify a 404 * SUP (subclass) in 405 * ditContentRules 406 * per MS-ADTS 407 * 3.1.1.3.1.1.1 */ 408 -1, NULL, NULL, 409 GUID_hexstring(tmp_ctx, &sclass->schemaIDGUID)); 410 talloc_free(tmp_ctx); 411 return schema_description; 412} 413 414 415