1 /* $NetBSD: schemaparse.c,v 1.1.1.4 2014/05/28 09:58:47 tron Exp $ */ 2 3 /* schemaparse.c - routines to parse config file objectclass definitions */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2014 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 19 #include "portable.h" 20 21 #include <stdio.h> 22 23 #include <ac/ctype.h> 24 #include <ac/string.h> 25 #include <ac/socket.h> 26 27 #include "slap.h" 28 #include "ldap_schema.h" 29 #include "config.h" 30 31 static void oc_usage(void); 32 static void at_usage(void); 33 34 static char *const err2text[] = { 35 "Success", 36 "Out of memory", 37 "ObjectClass not found", 38 "user-defined ObjectClass includes operational attributes", 39 "user-defined ObjectClass has inappropriate SUPerior", 40 "Duplicate objectClass", 41 "Inconsistent duplicate objectClass", 42 "AttributeType not found", 43 "AttributeType inappropriate matching rule", 44 "AttributeType inappropriate USAGE", 45 "AttributeType inappropriate SUPerior", 46 "AttributeType SYNTAX or SUPerior required", 47 "Duplicate attributeType", 48 "Inconsistent duplicate attributeType", 49 "MatchingRule not found", 50 "MatchingRule incomplete", 51 "Duplicate matchingRule", 52 "Syntax not found", 53 "Duplicate ldapSyntax", 54 "Superior syntax not found", 55 "Substitute syntax not specified", 56 "Substitute syntax not found", 57 "OID or name required", 58 "Qualifier not supported", 59 "Invalid NAME", 60 "OID could not be expanded", 61 "Duplicate Content Rule", 62 "Content Rule not for STRUCTURAL object class", 63 "Content Rule AUX contains inappropriate object class", 64 "Content Rule attribute type list contains duplicate", 65 NULL 66 }; 67 68 char * 69 scherr2str(int code) 70 { 71 if ( code < 0 || SLAP_SCHERR_LAST <= code ) { 72 return "Unknown error"; 73 } else { 74 return err2text[code]; 75 } 76 } 77 78 /* check schema descr validity */ 79 int slap_valid_descr( const char *descr ) 80 { 81 int i=0; 82 83 if( !DESC_LEADCHAR( descr[i] ) ) { 84 return 0; 85 } 86 87 while( descr[++i] ) { 88 if( !DESC_CHAR( descr[i] ) ) { 89 return 0; 90 } 91 } 92 93 return 1; 94 } 95 96 97 /* OID Macros */ 98 99 /* String compare with delimiter check. Return 0 if not 100 * matched, otherwise return length matched. 101 */ 102 int 103 dscompare(const char *s1, const char *s2, char delim) 104 { 105 const char *orig = s1; 106 while (*s1++ == *s2++) 107 if (!s1[-1]) break; 108 --s1; 109 --s2; 110 if (!*s1 && (!*s2 || *s2 == delim)) 111 return s1 - orig; 112 return 0; 113 } 114 115 static void 116 cr_usage( void ) 117 { 118 fprintf( stderr, 119 "DITContentRuleDescription = \"(\" whsp\n" 120 " numericoid whsp ; StructuralObjectClass identifier\n" 121 " [ \"NAME\" qdescrs ]\n" 122 " [ \"DESC\" qdstring ]\n" 123 " [ \"OBSOLETE\" whsp ]\n" 124 " [ \"AUX\" oids ] ; Auxiliary ObjectClasses\n" 125 " [ \"MUST\" oids ] ; AttributeTypes\n" 126 " [ \"MAY\" oids ] ; AttributeTypes\n" 127 " [ \"NOT\" oids ] ; AttributeTypes\n" 128 " whsp \")\"\n" ); 129 } 130 131 int 132 parse_cr( 133 struct config_args_s *c, 134 ContentRule **scr ) 135 { 136 LDAPContentRule *cr; 137 int code; 138 const char *err; 139 char *line = strchr( c->line, '(' ); 140 141 cr = ldap_str2contentrule( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL ); 142 if ( !cr ) { 143 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s", 144 c->argv[0], ldap_scherr2str( code ), err ); 145 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 146 "%s %s\n", c->log, c->cr_msg, 0 ); 147 cr_usage(); 148 return 1; 149 } 150 151 if ( cr->cr_oid == NULL ) { 152 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing", 153 c->argv[0] ); 154 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 155 "%s %s\n", c->log, c->cr_msg, 0 ); 156 cr_usage(); 157 code = 1; 158 goto done; 159 } 160 161 code = cr_add( cr, 1, scr, &err ); 162 if ( code ) { 163 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"", 164 c->argv[0], scherr2str(code), err); 165 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 166 "%s %s\n", c->log, c->cr_msg, 0 ); 167 code = 1; 168 goto done; 169 } 170 171 done:; 172 if ( code ) { 173 ldap_contentrule_free( cr ); 174 175 } else { 176 ldap_memfree( cr ); 177 } 178 179 return code; 180 } 181 182 int 183 parse_oc( 184 struct config_args_s *c, 185 ObjectClass **soc, 186 ObjectClass *prev ) 187 { 188 LDAPObjectClass *oc; 189 int code; 190 const char *err; 191 char *line = strchr( c->line, '(' ); 192 193 oc = ldap_str2objectclass(line, &code, &err, LDAP_SCHEMA_ALLOW_ALL ); 194 if ( !oc ) { 195 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s", 196 c->argv[0], ldap_scherr2str( code ), err ); 197 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 198 "%s %s\n", c->log, c->cr_msg, 0 ); 199 oc_usage(); 200 return 1; 201 } 202 203 if ( oc->oc_oid == NULL ) { 204 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing", 205 c->argv[0] ); 206 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 207 "%s %s\n", c->log, c->cr_msg, 0 ); 208 oc_usage(); 209 code = 1; 210 goto done; 211 } 212 213 code = oc_add( oc, 1, soc, prev, &err ); 214 if ( code ) { 215 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"", 216 c->argv[0], scherr2str(code), err); 217 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 218 "%s %s\n", c->log, c->cr_msg, 0 ); 219 code = 1; 220 goto done; 221 } 222 223 done:; 224 if ( code ) { 225 ldap_objectclass_free( oc ); 226 227 } else { 228 ldap_memfree( oc ); 229 } 230 231 return code; 232 } 233 234 static void 235 oc_usage( void ) 236 { 237 fprintf( stderr, 238 "ObjectClassDescription = \"(\" whsp\n" 239 " numericoid whsp ; ObjectClass identifier\n" 240 " [ \"NAME\" qdescrs ]\n" 241 " [ \"DESC\" qdstring ]\n" 242 " [ \"OBSOLETE\" whsp ]\n" 243 " [ \"SUP\" oids ] ; Superior ObjectClasses\n" 244 " [ ( \"ABSTRACT\" / \"STRUCTURAL\" / \"AUXILIARY\" ) whsp ]\n" 245 " ; default structural\n" 246 " [ \"MUST\" oids ] ; AttributeTypes\n" 247 " [ \"MAY\" oids ] ; AttributeTypes\n" 248 " whsp \")\"\n" ); 249 } 250 251 static void 252 at_usage( void ) 253 { 254 fprintf( stderr, "%s%s%s", 255 "AttributeTypeDescription = \"(\" whsp\n" 256 " numericoid whsp ; AttributeType identifier\n" 257 " [ \"NAME\" qdescrs ] ; name used in AttributeType\n" 258 " [ \"DESC\" qdstring ] ; description\n" 259 " [ \"OBSOLETE\" whsp ]\n" 260 " [ \"SUP\" woid ] ; derived from this other\n" 261 " ; AttributeType\n", 262 " [ \"EQUALITY\" woid ] ; Matching Rule name\n" 263 " [ \"ORDERING\" woid ] ; Matching Rule name\n" 264 " [ \"SUBSTR\" woid ] ; Matching Rule name\n" 265 " [ \"SYNTAX\" whsp noidlen whsp ] ; see section 4.3\n" 266 " [ \"SINGLE-VALUE\" whsp ] ; default multi-valued\n" 267 " [ \"COLLECTIVE\" whsp ] ; default not collective\n", 268 " [ \"NO-USER-MODIFICATION\" whsp ]; default user modifiable\n" 269 " [ \"USAGE\" whsp AttributeUsage ]; default userApplications\n" 270 " ; userApplications\n" 271 " ; directoryOperation\n" 272 " ; distributedOperation\n" 273 " ; dSAOperation\n" 274 " whsp \")\"\n"); 275 } 276 277 int 278 parse_at( 279 struct config_args_s *c, 280 AttributeType **sat, 281 AttributeType *prev ) 282 { 283 LDAPAttributeType *at; 284 int code; 285 const char *err; 286 char *line = strchr( c->line, '(' ); 287 288 at = ldap_str2attributetype( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL ); 289 if ( !at ) { 290 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s", 291 c->argv[0], ldap_scherr2str(code), err ); 292 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 293 "%s %s\n", c->log, c->cr_msg, 0 ); 294 at_usage(); 295 return 1; 296 } 297 298 if ( at->at_oid == NULL ) { 299 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing", 300 c->argv[0] ); 301 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 302 "%s %s\n", c->log, c->cr_msg, 0 ); 303 at_usage(); 304 code = 1; 305 goto done; 306 } 307 308 /* operational attributes should be defined internally */ 309 if ( at->at_usage ) { 310 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: \"%s\" is operational", 311 c->argv[0], at->at_oid ); 312 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 313 "%s %s\n", c->log, c->cr_msg, 0 ); 314 code = 1; 315 goto done; 316 } 317 318 code = at_add( at, 1, sat, prev, &err); 319 if ( code ) { 320 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"", 321 c->argv[0], scherr2str(code), err); 322 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 323 "%s %s\n", c->log, c->cr_msg, 0 ); 324 code = 1; 325 goto done; 326 } 327 328 done:; 329 if ( code ) { 330 ldap_attributetype_free( at ); 331 332 } else { 333 ldap_memfree( at ); 334 } 335 336 return code; 337 } 338 339 static void 340 syn_usage( void ) 341 { 342 fprintf( stderr, "%s", 343 "SyntaxDescription = \"(\" whsp\n" 344 " numericoid whsp ; object identifier\n" 345 " [ whsp \"DESC\" whsp qdstring ] ; description\n" 346 " extensions whsp \")\" ; extensions\n" 347 " whsp \")\"\n"); 348 } 349 350 int 351 parse_syn( 352 struct config_args_s *c, 353 Syntax **ssyn, 354 Syntax *prev ) 355 { 356 LDAPSyntax *syn; 357 slap_syntax_defs_rec def = { 0 }; 358 int code; 359 const char *err; 360 char *line = strchr( c->line, '(' ); 361 362 syn = ldap_str2syntax( line, &code, &err, LDAP_SCHEMA_ALLOW_ALL ); 363 if ( !syn ) { 364 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s before %s", 365 c->argv[0], ldap_scherr2str(code), err ); 366 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 367 "%s %s\n", c->log, c->cr_msg, 0 ); 368 syn_usage(); 369 return 1; 370 } 371 372 if ( syn->syn_oid == NULL ) { 373 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: OID is missing", 374 c->argv[0] ); 375 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 376 "%s %s\n", c->log, c->cr_msg, 0 ); 377 syn_usage(); 378 code = 1; 379 goto done; 380 } 381 382 code = syn_add( syn, 1, &def, ssyn, prev, &err ); 383 if ( code ) { 384 snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s: %s: \"%s\"", 385 c->argv[0], scherr2str(code), err); 386 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, 387 "%s %s\n", c->log, c->cr_msg, 0 ); 388 code = 1; 389 goto done; 390 } 391 392 done:; 393 if ( code ) { 394 ldap_syntax_free( syn ); 395 396 } else { 397 ldap_memfree( syn ); 398 } 399 400 return code; 401 } 402 403