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