From cf318d2340fe0523729cfaae7a2e767c52afdb24 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Wed, 9 Oct 2002 02:56:46 +0000 Subject: [PATCH] Add ditContentRule routines --- include/ldap_schema.h | 41 +++++ libraries/libldap/schema.c | 354 ++++++++++++++++++++++++++++++++++++- 2 files changed, 391 insertions(+), 4 deletions(-) diff --git a/include/ldap_schema.h b/include/ldap_schema.h index 4c8e5fb448..d72c801c46 100644 --- a/include/ldap_schema.h +++ b/include/ldap_schema.h @@ -96,6 +96,23 @@ typedef struct ldap_objectclass { LDAPSchemaExtensionItem **oc_extensions; /* OPTIONAL */ } LDAPObjectClass; +typedef struct ldap_contentrule { + char *cr_oid; /* REQUIRED */ + char **cr_names; /* OPTIONAL */ + char *cr_desc; /* OPTIONAL */ + char **cr_sup_oids; /* OPTIONAL */ + int cr_obsolete; /* 0=no, 1=yes */ + char **cr_oc_oids_aux; /* OPTIONAL */ + char **cr_at_oids_must; /* OPTIONAL */ + char **cr_at_oids_may; /* OPTIONAL */ + char **cr_at_oids_not; /* OPTIONAL */ + LDAPSchemaExtensionItem **cr_extensions; /* OPTIONAL */ +} LDAPContentRule; + + +/* + * Misc macros + */ #define LDAP_SCHEMA_NO 0 #define LDAP_SCHEMA_YES 1 @@ -108,6 +125,7 @@ typedef struct ldap_objectclass { #define LDAP_SCHEMA_STRUCTURAL 1 #define LDAP_SCHEMA_AUXILIARY 2 + /* * Flags that control how liberal the parsing routines are. */ @@ -140,6 +158,10 @@ LDAP_F( LDAP_CONST char * ) ldap_objectclass2name LDAP_P(( LDAPObjectClass * oc )); +LDAP_F( LDAP_CONST char * ) +ldap_contentrule2name LDAP_P(( + LDAPContentRule * cr )); + LDAP_F( void ) ldap_syntax_free LDAP_P(( LDAPSyntax * syn )); @@ -160,6 +182,10 @@ LDAP_F( void ) ldap_objectclass_free LDAP_P(( LDAPObjectClass * oc )); +LDAP_F( void ) +ldap_contentrule_free LDAP_P(( + LDAPContentRule * cr )); + LDAP_F( LDAPObjectClass * ) ldap_str2objectclass LDAP_P(( LDAP_CONST char * s, @@ -167,6 +193,13 @@ ldap_str2objectclass LDAP_P(( LDAP_CONST char ** errp, LDAP_CONST int flags )); +LDAP_F( LDAPContentRule * ) +ldap_str2contentrule LDAP_P(( + LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST int flags )); + LDAP_F( LDAPAttributeType * ) ldap_str2attributetype LDAP_P(( LDAP_CONST char * s, @@ -203,6 +236,14 @@ LDAP_F( struct berval * ) ldap_objectclass2bv LDAP_P(( LDAPObjectClass * oc, struct berval *bv )); +LDAP_F( char * ) +ldap_contentrule2str LDAP_P(( + LDAPContentRule * cr )); + +LDAP_F( struct berval * ) +ldap_contentrule2bv LDAP_P(( + LDAPContentRule * cr, struct berval *bv )); + LDAP_F( char * ) ldap_attributetype2str LDAP_P(( LDAPAttributeType * at )); diff --git a/libraries/libldap/schema.c b/libraries/libldap/schema.c index 93a1daf381..417b4bdba6 100644 --- a/libraries/libldap/schema.c +++ b/libraries/libldap/schema.c @@ -56,6 +56,11 @@ ldap_objectclass2name( LDAPObjectClass * oc ) return( choose_name( oc->oc_names, oc->oc_oid ) ); } +LDAP_CONST char * +ldap_contentrule2name( LDAPContentRule * cr ) +{ + return( choose_name( cr->cr_names, cr->cr_oid ) ); +} /* * When pretty printing the entities we will be appending to a buffer. @@ -383,7 +388,7 @@ ldap_matchingrule2bv( LDAPMatchingRule * mr, struct berval *bv ) print_qdstring(ss,mr->mr_desc); } - if ( mr->mr_obsolete == LDAP_SCHEMA_YES ) { + if ( mr->mr_obsolete ) { print_literal(ss, "OBSOLETE"); print_whsp(ss); } @@ -442,7 +447,7 @@ ldap_matchingruleuse2bv( LDAPMatchingRuleUse * mru, struct berval *bv ) print_qdstring(ss,mru->mru_desc); } - if ( mru->mru_obsolete == LDAP_SCHEMA_YES ) { + if ( mru->mru_obsolete ) { print_literal(ss, "OBSOLETE"); print_whsp(ss); } @@ -501,7 +506,7 @@ ldap_objectclass2bv( LDAPObjectClass * oc, struct berval *bv ) print_qdstring(ss,oc->oc_desc); } - if ( oc->oc_obsolete == LDAP_SCHEMA_YES ) { + if ( oc->oc_obsolete ) { print_literal(ss, "OBSOLETE"); print_whsp(ss); } @@ -555,6 +560,85 @@ ldap_objectclass2bv( LDAPObjectClass * oc, struct berval *bv ) return(bv); } +char * +ldap_contentrule2str( LDAPContentRule * cr ) +{ + struct berval bv; + if (ldap_contentrule2bv( cr, &bv )) + return(bv.bv_val); + else + return NULL; +} + +struct berval * +ldap_contentrule2bv( LDAPContentRule * cr, struct berval *bv ) +{ + safe_string * ss; + + ss = new_safe_string(256); + if ( !ss ) + return NULL; + + print_literal(ss,"("/*)*/); + print_whsp(ss); + + print_numericoid(ss, cr->cr_oid); + print_whsp(ss); + + if ( cr->cr_names ) { + print_literal(ss,"NAME"); + print_qdescrs(ss,cr->cr_names); + } + + if ( cr->cr_desc ) { + print_literal(ss,"DESC"); + print_qdstring(ss,cr->cr_desc); + } + + if ( cr->cr_obsolete ) { + print_literal(ss, "OBSOLETE"); + print_whsp(ss); + } + + if ( cr->cr_oc_oids_aux ) { + print_literal(ss,"AUX"); + print_whsp(ss); + print_oids(ss,cr->cr_oc_oids_aux); + print_whsp(ss); + } + + if ( cr->cr_at_oids_must ) { + print_literal(ss,"MUST"); + print_whsp(ss); + print_oids(ss,cr->cr_at_oids_must); + print_whsp(ss); + } + + if ( cr->cr_at_oids_may ) { + print_literal(ss,"MAY"); + print_whsp(ss); + print_oids(ss,cr->cr_at_oids_may); + print_whsp(ss); + } + + if ( cr->cr_at_oids_not ) { + print_literal(ss,"NOT"); + print_whsp(ss); + print_oids(ss,cr->cr_at_oids_not); + print_whsp(ss); + } + + print_whsp(ss); + print_extensions(ss, cr->cr_extensions); + + print_literal(ss, /*(*/")"); + + bv->bv_val = safe_strdup(ss); + bv->bv_len = ss->pos; + safe_string_free(ss); + return(bv); +} + char * ldap_attributetype2str( LDAPAttributeType * at ) { @@ -590,7 +674,7 @@ ldap_attributetype2bv( LDAPAttributeType * at, struct berval *bv ) print_qdstring(ss,at->at_desc); } - if ( at->at_obsolete == LDAP_SCHEMA_YES ) { + if ( at->at_obsolete ) { print_literal(ss, "OBSOLETE"); print_whsp(ss); } @@ -2124,6 +2208,7 @@ ldap_str2objectclass( LDAP_CONST char * s, !strcmp(sval, "STRUCTURAL") || !strcmp(sval, "AUXILIARY") || !strcmp(sval, "MUST") || + !strcmp(sval, "MAY") || !strncmp(sval, "X-", 2) ) { /* Missing OID, backtrack */ ss = savepos; @@ -2324,6 +2409,267 @@ ldap_str2objectclass( LDAP_CONST char * s, } } +void +ldap_contentrule_free(LDAPContentRule * cr) +{ + LDAP_FREE(cr->cr_oid); + if (cr->cr_names) LDAP_VFREE(cr->cr_names); + if (cr->cr_desc) LDAP_FREE(cr->cr_desc); + if (cr->cr_oc_oids_aux) LDAP_VFREE(cr->cr_oc_oids_aux); + if (cr->cr_at_oids_must) LDAP_VFREE(cr->cr_at_oids_must); + if (cr->cr_at_oids_may) LDAP_VFREE(cr->cr_at_oids_may); + if (cr->cr_at_oids_not) LDAP_VFREE(cr->cr_at_oids_not); + free_extensions(cr->cr_extensions); + LDAP_FREE(cr); +} + +LDAPContentRule * +ldap_str2contentrule( LDAP_CONST char * s, + int * code, + LDAP_CONST char ** errp, + LDAP_CONST int flags ) +{ + int kind; + const char * ss = s; + char * sval; + int seen_name = 0; + int seen_desc = 0; + int seen_obsolete = 0; + int seen_aux = 0; + int seen_must = 0; + int seen_may = 0; + int seen_not = 0; + LDAPContentRule * cr; + char ** ext_vals; + const char * savepos; + + if ( !s ) { + *code = LDAP_SCHERR_EMPTY; + *errp = ""; + return NULL; + } + + *errp = s; + cr = LDAP_CALLOC(1,sizeof(LDAPContentRule)); + + if ( !cr ) { + *code = LDAP_SCHERR_OUTOFMEM; + return NULL; + } + + kind = get_token(&ss,&sval); + if ( kind != TK_LEFTPAREN ) { + *code = LDAP_SCHERR_NOLEFTPAREN; + LDAP_FREE(sval); + ldap_contentrule_free(cr); + return NULL; + } + + /* + * Definitions MUST begin with an OID in the numericoid format. + * However, this routine is used by clients to parse the response + * from servers and very well known servers will provide an OID + * in the wrong format or even no OID at all. We do our best to + * extract info from those servers. + */ + parse_whsp(&ss); + savepos = ss; + cr->cr_oid = ldap_int_parse_numericoid(&ss,code,0); + if ( !cr->cr_oid ) { + if ( (flags & LDAP_SCHEMA_ALLOW_ALL) && (ss == savepos) ) { + /* Backtracking */ + ss = savepos; + kind = get_token(&ss,&sval); + if ( kind == TK_BAREWORD ) { + if ( !strcmp(sval, "NAME") || + !strcmp(sval, "DESC") || + !strcmp(sval, "OBSOLETE") || + !strcmp(sval, "AUX") || + !strcmp(sval, "MUST") || + !strcmp(sval, "MAY") || + !strcmp(sval, "NOT") || + !strncmp(sval, "X-", 2) ) { + /* Missing OID, backtrack */ + ss = savepos; + } else if ( flags & + LDAP_SCHEMA_ALLOW_OID_MACRO ) { + /* Non-numerical OID, ignore */ + int len = ss-savepos; + cr->cr_oid = LDAP_MALLOC(len+1); + strncpy(cr->cr_oid, savepos, len); + cr->cr_oid[len] = 0; + } + } + LDAP_FREE(sval); + } else { + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + } + parse_whsp(&ss); + + /* + * Beyond this point we will be liberal an accept the items + * in any order. + */ + while (1) { + kind = get_token(&ss,&sval); + switch (kind) { + case TK_EOS: + *code = LDAP_SCHERR_NORIGHTPAREN; + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + case TK_RIGHTPAREN: + return cr; + case TK_BAREWORD: + if ( !strcmp(sval,"NAME") ) { + LDAP_FREE(sval); + if ( seen_name ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_name = 1; + cr->cr_names = parse_qdescrs(&ss,code); + if ( !cr->cr_names ) { + if ( *code != LDAP_SCHERR_OUTOFMEM ) + *code = LDAP_SCHERR_BADNAME; + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + } else if ( !strcmp(sval,"DESC") ) { + LDAP_FREE(sval); + if ( seen_desc ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_desc = 1; + parse_whsp(&ss); + kind = get_token(&ss,&sval); + if ( kind != TK_QDSTRING ) { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_contentrule_free(cr); + return NULL; + } + cr->cr_desc = sval; + parse_whsp(&ss); + } else if ( !strcmp(sval,"OBSOLETE") ) { + LDAP_FREE(sval); + if ( seen_obsolete ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_obsolete = 1; + cr->cr_obsolete = LDAP_SCHEMA_YES; + parse_whsp(&ss); + } else if ( !strcmp(sval,"AUX") ) { + LDAP_FREE(sval); + if ( seen_aux ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_aux = 1; + cr->cr_oc_oids_aux = parse_oids(&ss,code,0); + if ( !cr->cr_oc_oids_aux ) { + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + parse_whsp(&ss); + } else if ( !strcmp(sval,"MUST") ) { + LDAP_FREE(sval); + if ( seen_must ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_must = 1; + cr->cr_at_oids_must = parse_oids(&ss,code,0); + if ( !cr->cr_at_oids_must ) { + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + parse_whsp(&ss); + } else if ( !strcmp(sval,"MAY") ) { + LDAP_FREE(sval); + if ( seen_may ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_may = 1; + cr->cr_at_oids_may = parse_oids(&ss,code,0); + if ( !cr->cr_at_oids_may ) { + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + parse_whsp(&ss); + } else if ( !strcmp(sval,"NOT") ) { + LDAP_FREE(sval); + if ( seen_not ) { + *code = LDAP_SCHERR_DUPOPT; + *errp = ss; + ldap_contentrule_free(cr); + return(NULL); + } + seen_not = 1; + cr->cr_at_oids_not = parse_oids(&ss,code,0); + if ( !cr->cr_at_oids_not ) { + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + parse_whsp(&ss); + } else if ( sval[0] == 'X' && sval[1] == '-' ) { + /* Should be parse_qdstrings */ + ext_vals = parse_qdescrs(&ss, code); + if ( !ext_vals ) { + *errp = ss; + ldap_contentrule_free(cr); + return NULL; + } + if ( add_extension(&cr->cr_extensions, + sval, ext_vals) ) { + *code = LDAP_SCHERR_OUTOFMEM; + *errp = ss; + LDAP_FREE(sval); + ldap_contentrule_free(cr); + return NULL; + } + } else { + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_contentrule_free(cr); + return NULL; + } + break; + default: + *code = LDAP_SCHERR_UNEXPTOKEN; + *errp = ss; + LDAP_FREE(sval); + ldap_contentrule_free(cr); + return NULL; + } + } +} + static char *const err2text[] = { "Success", "Out of memory", -- 2.39.5