1 /* syntax.c - routines to manage syntax definitions */ 2 /* $OpenLDAP: pkg/ldap/servers/slapd/syntax.c,v 1.43.2.3 2008/02/11 23:26:45 kurt Exp $ */ 3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2008 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16 17 #include "portable.h" 18 19 #include <stdio.h> 20 21 #include <ac/ctype.h> 22 #include <ac/string.h> 23 #include <ac/socket.h> 24 25 #include "slap.h" 26 27 struct sindexrec { 28 char *sir_name; 29 Syntax *sir_syn; 30 }; 31 32 static Avlnode *syn_index = NULL; 33 static LDAP_SLIST_HEAD(SyntaxList, Syntax) syn_list 34 = LDAP_SLIST_HEAD_INITIALIZER(&syn_list); 35 36 static int 37 syn_index_cmp( 38 const void *v_sir1, 39 const void *v_sir2 40 ) 41 { 42 const struct sindexrec *sir1 = v_sir1, *sir2 = v_sir2; 43 return (strcmp( sir1->sir_name, sir2->sir_name )); 44 } 45 46 static int 47 syn_index_name_cmp( 48 const void *name, 49 const void *sir 50 ) 51 { 52 return (strcmp( name, ((const struct sindexrec *)sir)->sir_name )); 53 } 54 55 Syntax * 56 syn_find( const char *synname ) 57 { 58 struct sindexrec *sir = NULL; 59 60 if ( (sir = avl_find( syn_index, synname, syn_index_name_cmp )) != NULL ) { 61 return( sir->sir_syn ); 62 } 63 return( NULL ); 64 } 65 66 Syntax * 67 syn_find_desc( const char *syndesc, int *len ) 68 { 69 Syntax *synp; 70 71 LDAP_SLIST_FOREACH(synp, &syn_list, ssyn_next) { 72 if ((*len = dscompare( synp->ssyn_syn.syn_desc, syndesc, '{' /*'}'*/ ))) { 73 return synp; 74 } 75 } 76 return( NULL ); 77 } 78 79 int 80 syn_is_sup( Syntax *syn, Syntax *sup ) 81 { 82 int i; 83 84 assert( syn != NULL ); 85 assert( sup != NULL ); 86 87 if ( syn == sup ) { 88 return 1; 89 } 90 91 if ( syn->ssyn_sups == NULL ) { 92 return 0; 93 } 94 95 for ( i = 0; syn->ssyn_sups[i]; i++ ) { 96 if ( syn->ssyn_sups[i] == sup ) { 97 return 1; 98 } 99 100 if ( syn_is_sup( syn->ssyn_sups[i], sup ) ) { 101 return 1; 102 } 103 } 104 105 return 0; 106 } 107 108 void 109 syn_destroy( void ) 110 { 111 Syntax *s; 112 113 avl_free( syn_index, ldap_memfree ); 114 while( !LDAP_SLIST_EMPTY( &syn_list ) ) { 115 s = LDAP_SLIST_FIRST( &syn_list ); 116 LDAP_SLIST_REMOVE_HEAD( &syn_list, ssyn_next ); 117 if ( s->ssyn_sups ) { 118 SLAP_FREE( s->ssyn_sups ); 119 } 120 ldap_syntax_free( (LDAPSyntax *)s ); 121 } 122 } 123 124 static int 125 syn_insert( 126 Syntax *ssyn, 127 const char **err 128 ) 129 { 130 struct sindexrec *sir; 131 132 LDAP_SLIST_NEXT( ssyn, ssyn_next ) = NULL; 133 LDAP_SLIST_INSERT_HEAD( &syn_list, ssyn, ssyn_next ); 134 135 if ( ssyn->ssyn_oid ) { 136 sir = (struct sindexrec *) 137 SLAP_CALLOC( 1, sizeof(struct sindexrec) ); 138 if( sir == NULL ) { 139 Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 ); 140 return LDAP_OTHER; 141 } 142 sir->sir_name = ssyn->ssyn_oid; 143 sir->sir_syn = ssyn; 144 if ( avl_insert( &syn_index, (caddr_t) sir, 145 syn_index_cmp, avl_dup_error ) ) { 146 *err = ssyn->ssyn_oid; 147 ldap_memfree(sir); 148 return SLAP_SCHERR_SYN_DUP; 149 } 150 /* FIX: temporal consistency check */ 151 syn_find(sir->sir_name); 152 } 153 return 0; 154 } 155 156 int 157 syn_add( 158 LDAPSyntax *syn, 159 slap_syntax_defs_rec *def, 160 const char **err 161 ) 162 { 163 Syntax *ssyn; 164 int code = 0; 165 166 ssyn = (Syntax *) SLAP_CALLOC( 1, sizeof(Syntax) ); 167 if ( ssyn == NULL ) { 168 Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 ); 169 return SLAP_SCHERR_OUTOFMEM; 170 } 171 172 AC_MEMCPY( &ssyn->ssyn_syn, syn, sizeof(LDAPSyntax) ); 173 174 LDAP_SLIST_NEXT(ssyn,ssyn_next) = NULL; 175 176 /* 177 * note: ssyn_bvoid uses the same memory of ssyn_syn.syn_oid; 178 * ssyn_oidlen is #defined as ssyn_bvoid.bv_len 179 */ 180 ssyn->ssyn_bvoid.bv_val = ssyn->ssyn_syn.syn_oid; 181 ssyn->ssyn_oidlen = strlen(syn->syn_oid); 182 ssyn->ssyn_flags = def->sd_flags; 183 ssyn->ssyn_validate = def->sd_validate; 184 ssyn->ssyn_pretty = def->sd_pretty; 185 186 ssyn->ssyn_sups = NULL; 187 188 #ifdef SLAPD_BINARY_CONVERSION 189 ssyn->ssyn_ber2str = def->sd_ber2str; 190 ssyn->ssyn_str2ber = def->sd_str2ber; 191 #endif 192 193 if ( def->sd_sups != NULL ) { 194 int cnt; 195 196 for ( cnt = 0; def->sd_sups[cnt] != NULL; cnt++ ) 197 ; 198 199 ssyn->ssyn_sups = (Syntax **)SLAP_CALLOC( cnt + 1, 200 sizeof( Syntax * ) ); 201 if ( ssyn->ssyn_sups == NULL ) { 202 Debug( LDAP_DEBUG_ANY, "SLAP_CALLOC Error\n", 0, 0, 0 ); 203 code = SLAP_SCHERR_OUTOFMEM; 204 205 } else { 206 for ( cnt = 0; def->sd_sups[cnt] != NULL; cnt++ ) { 207 ssyn->ssyn_sups[cnt] = syn_find( def->sd_sups[cnt] ); 208 if ( ssyn->ssyn_sups[cnt] == NULL ) { 209 *err = def->sd_sups[cnt]; 210 code = SLAP_SCHERR_SYN_SUP_NOT_FOUND; 211 } 212 } 213 } 214 } 215 216 if ( code == 0 ) { 217 code = syn_insert( ssyn, err ); 218 219 } 220 221 if ( code != 0 && ssyn != NULL ) { 222 if ( ssyn->ssyn_sups != NULL ) { 223 SLAP_FREE( ssyn->ssyn_sups ); 224 } 225 SLAP_FREE( ssyn ); 226 } 227 228 return code; 229 } 230 231 int 232 register_syntax( 233 slap_syntax_defs_rec *def ) 234 { 235 LDAPSyntax *syn; 236 int code; 237 const char *err; 238 239 syn = ldap_str2syntax( def->sd_desc, &code, &err, LDAP_SCHEMA_ALLOW_ALL); 240 if ( !syn ) { 241 Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s before %s in %s\n", 242 ldap_scherr2str(code), err, def->sd_desc ); 243 244 return( -1 ); 245 } 246 247 code = syn_add( syn, def, &err ); 248 249 if ( code ) { 250 Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s %s in %s\n", 251 scherr2str(code), err, def->sd_desc ); 252 ldap_syntax_free( syn ); 253 254 return( -1 ); 255 } 256 257 ldap_memfree( syn ); 258 259 return( 0 ); 260 } 261 262 int 263 syn_schema_info( Entry *e ) 264 { 265 AttributeDescription *ad_ldapSyntaxes = slap_schema.si_ad_ldapSyntaxes; 266 Syntax *syn; 267 struct berval val; 268 struct berval nval; 269 270 LDAP_SLIST_FOREACH(syn, &syn_list, ssyn_next ) { 271 if ( ! syn->ssyn_validate ) { 272 /* skip syntaxes without validators */ 273 continue; 274 } 275 if ( syn->ssyn_flags & SLAP_SYNTAX_HIDE ) { 276 /* hide syntaxes */ 277 continue; 278 } 279 280 if ( ldap_syntax2bv( &syn->ssyn_syn, &val ) == NULL ) { 281 return -1; 282 } 283 #if 0 284 Debug( LDAP_DEBUG_TRACE, "Merging syn [%ld] %s\n", 285 (long) val.bv_len, val.bv_val, 0 ); 286 #endif 287 288 nval.bv_val = syn->ssyn_oid; 289 nval.bv_len = strlen(syn->ssyn_oid); 290 291 if( attr_merge_one( e, ad_ldapSyntaxes, &val, &nval ) ) 292 { 293 return -1; 294 } 295 ldap_memfree( val.bv_val ); 296 } 297 return 0; 298 } 299 300