X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Faci.c;h=28b99388ea2381f791e423411a116c095f774b8f;hb=72d2ee4d19ee76e7d81d402c4056ce665f797045;hp=3d587cd9e661bb7d69ae376b534fb657fbcb8c86;hpb=ec49990d51658542eff1461366806cbfb58eb63f;p=openldap diff --git a/servers/slapd/aci.c b/servers/slapd/aci.c index 3d587cd9e6..28b99388ea 100644 --- a/servers/slapd/aci.c +++ b/servers/slapd/aci.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2005 The OpenLDAP Foundation. + * Copyright 1998-2006 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -40,7 +40,114 @@ #include "lber_pvt.h" #include "lutil.h" -#define ACI_BUF_SIZE 1024 /* use most appropriate size */ +/* use most appropriate size */ +#define ACI_BUF_SIZE 1024 + +/* move to "stable" when no longer experimental */ +#define SLAPD_ACI_SYNTAX "1.3.6.1.4.1.4203.666.2.1" + +/* change this to "OpenLDAPset" */ +#define SLAPD_ACI_SET_ATTR "template" + +typedef enum slap_aci_scope_t { + SLAP_ACI_SCOPE_ENTRY = 0x1, + SLAP_ACI_SCOPE_CHILDREN = 0x2, + SLAP_ACI_SCOPE_SUBTREE = ( SLAP_ACI_SCOPE_ENTRY | SLAP_ACI_SCOPE_CHILDREN ) +} slap_aci_scope_t; + +enum { + ACI_BV_ENTRY, + ACI_BV_CHILDREN, + ACI_BV_ONELEVEL, + ACI_BV_SUBTREE, + + ACI_BV_BR_ENTRY, + ACI_BV_BR_ALL, + + ACI_BV_ACCESS_ID, + ACI_BV_PUBLIC, + ACI_BV_USERS, + ACI_BV_SELF, + ACI_BV_DNATTR, + ACI_BV_GROUP, + ACI_BV_ROLE, + ACI_BV_SET, + ACI_BV_SET_REF, + + ACI_BV_GRANT, + ACI_BV_DENY, + + ACI_BV_GROUP_CLASS, + ACI_BV_GROUP_ATTR, + ACI_BV_ROLE_CLASS, + ACI_BV_ROLE_ATTR, + + ACI_BV_SET_ATTR, + + ACI_BV_LAST +}; + +static const struct berval aci_bv[] = { + /* scope */ + BER_BVC("entry"), + BER_BVC("children"), + BER_BVC("onelevel"), + BER_BVC("subtree"), + + /* */ + BER_BVC("[entry]"), + BER_BVC("[all]"), + + /* type */ + BER_BVC("access-id"), + BER_BVC("public"), + BER_BVC("users"), + BER_BVC("self"), + BER_BVC("dnattr"), + BER_BVC("group"), + BER_BVC("role"), + BER_BVC("set"), + BER_BVC("set-ref"), + + /* actions */ + BER_BVC("grant"), + BER_BVC("deny"), + + /* schema */ + BER_BVC(SLAPD_GROUP_CLASS), + BER_BVC(SLAPD_GROUP_ATTR), + BER_BVC(SLAPD_ROLE_CLASS), + BER_BVC(SLAPD_ROLE_ATTR), + + BER_BVC(SLAPD_ACI_SET_ATTR), + + BER_BVNULL +}; + +static AttributeDescription *slap_ad_aci; + +static int +OpenLDAPaciValidate( + Syntax *syntax, + struct berval *val ); + +static int +OpenLDAPaciPretty( + Syntax *syntax, + struct berval *val, + struct berval *out, + void *ctx ); + +static int +OpenLDAPaciNormalize( + slap_mask_t use, + Syntax *syntax, + MatchingRule *mr, + struct berval *val, + struct berval *out, + void *ctx ); + +#define OpenLDAPaciMatch octetStringMatch static int aci_list_map_rights( @@ -57,6 +164,20 @@ aci_list_map_rights( } switch ( *bv.bv_val ) { + case 'x': + /* **** NOTE: draft-ietf-ldapext-aci-model-0.3.txt does not + * define any equivalent to the AUTH right, so I've just used + * 'x' for now. + */ + ACL_PRIV_SET(mask, ACL_PRIV_AUTH); + break; + case 'd': + /* **** NOTE: draft-ietf-ldapext-aci-model-0.3.txt defines + * the right 'd' to mean "delete"; we hijack it to mean + * "disclose" for consistency wuith the rest of slapd. + */ + ACL_PRIV_SET(mask, ACL_PRIV_DISCLOSE); + break; case 'c': ACL_PRIV_SET(mask, ACL_PRIV_COMPARE); break; @@ -74,13 +195,6 @@ aci_list_map_rights( case 'w': ACL_PRIV_SET(mask, ACL_PRIV_WRITE); break; - case 'x': - /* **** NOTE: draft-ietf-ldapext-aci-model-0.3.txt does not - * define any equivalent to the AUTH right, so I've just used - * 'x' for now. - */ - ACL_PRIV_SET(mask, ACL_PRIV_AUTH); - break; default: break; } @@ -239,7 +353,7 @@ aci_group_member ( const char *text; int rc; - /* format of string is "group/objectClassValue/groupAttrName" */ + /* format of string is "{group|role}/objectClassValue/groupAttrName" */ if ( acl_get_part( subj, 0, '/', &subjdn ) < 0 ) { return 0; } @@ -286,7 +400,7 @@ done: return rc; } -int +static int aci_mask( Operation *op, Entry *e, @@ -299,7 +413,12 @@ aci_mask( slap_access_t *deny, slap_aci_scope_t asserted_scope ) { - struct berval bv, scope, perms, type, sdn; + struct berval bv, + scope, + perms, + type, + opts, + sdn; int rc; @@ -348,8 +467,7 @@ aci_mask( * both match "subtree" */ switch ( asserted_scope ) { case SLAP_ACI_SCOPE_ENTRY: - /* TODO: use ber_bvcmp */ - if ( ber_bvstrcasecmp( &scope, &aci_bv[ ACI_BV_ENTRY ] ) != 0 + if ( ber_bvcmp( &scope, &aci_bv[ ACI_BV_ENTRY ] ) != 0 && ber_bvstrcasecmp( &scope, &aci_bv[ ACI_BV_SUBTREE ] ) != 0 ) { return 0; @@ -357,22 +475,21 @@ aci_mask( break; case SLAP_ACI_SCOPE_CHILDREN: - /* TODO: use ber_bvcmp */ - if ( ber_bvstrcasecmp( &scope, &aci_bv[ ACI_BV_CHILDREN ] ) != 0 + if ( ber_bvcmp( &scope, &aci_bv[ ACI_BV_CHILDREN ] ) != 0 && ber_bvstrcasecmp( &scope, &aci_bv[ ACI_BV_SUBTREE ] ) != 0 ) { return 0; } break; - default: - /* TODO: add assertion */ + case SLAP_ACI_SCOPE_SUBTREE: + /* TODO: add assertion? */ return 0; } /* get the list of permissions clauses, bail if empty */ if ( acl_get_part( aci, 2, '#', &perms ) <= 0 ) { - /* TODO: add assertion */ + assert( 0 ); return 0; } @@ -383,13 +500,12 @@ aci_mask( /* see if we have a DN match */ if ( acl_get_part( aci, 3, '#', &type ) < 0 ) { - /* TODO: add assertion */ + assert( 0 ); return 0; } /* see if we have a public (i.e. anonymous) access */ - /* TODO: use ber_bvcmp */ - if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_PUBLIC ], &type ) == 0 ) { + if ( ber_bvcmp( &aci_bv[ ACI_BV_PUBLIC ], &type ) == 0 ) { return 1; } @@ -399,8 +515,7 @@ aci_mask( } /* see if we have a users access */ - /* TODO: use ber_bvcmp */ - if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_USERS ], &type ) == 0 ) { + if ( ber_bvcmp( &aci_bv[ ACI_BV_USERS ], &type ) == 0 ) { return 1; } @@ -417,95 +532,41 @@ aci_mask( sdn.bv_val = type.bv_val + type.bv_len + STRLENOF( "#" ); sdn.bv_len = aci->bv_len - ( sdn.bv_val - aci->bv_val ); - /* TODO: use ber_bvcmp */ - if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_ACCESS_ID ], &type ) == 0 ) { - struct berval ndn; - - /* TODO: don't normalize */ - rc = dnNormalize( 0, NULL, NULL, &sdn, &ndn, op->o_tmpmemctx ); - if ( rc != LDAP_SUCCESS ) { - return 0; - } + /* get the type options, if any */ + if ( acl_get_part( &type, 1, '/', &opts ) > 0 ) { + opts.bv_len = type.bv_len - ( opts.bv_val - type.bv_val ); + type.bv_len = opts.bv_val - type.bv_val - 1; - if ( dn_match( &op->o_ndn, &ndn ) ) { - rc = 1; - } - slap_sl_free( ndn.bv_val, op->o_tmpmemctx ); - - return rc; - - /* TODO: use ber_bvcmp */ - } else if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_SUBTREE ], &type ) == 0 ) { - struct berval ndn; - - /* TODO: don't normalize */ - rc = dnNormalize( 0, NULL, NULL, &sdn, &ndn, op->o_tmpmemctx ); - if ( rc != LDAP_SUCCESS ) { - return 0; - } - - if ( dnIsSuffix( &op->o_ndn, &ndn ) ) { - rc = 1; - } - slap_sl_free( ndn.bv_val, op->o_tmpmemctx ); - - return rc; - - /* TODO: use ber_bvcmp */ - } else if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_ONELEVEL ], &type ) == 0 ) { - struct berval ndn, pndn; - - /* TODO: don't normalize */ - rc = dnNormalize( 0, NULL, NULL, &sdn, &ndn, op->o_tmpmemctx ); - if ( rc != LDAP_SUCCESS ) { - return 0; - } + } else { + BER_BVZERO( &opts ); + } - dnParent( &ndn, &pndn ); + if ( ber_bvcmp( &aci_bv[ ACI_BV_ACCESS_ID ], &type ) == 0 ) { + return dn_match( &op->o_ndn, &sdn ); - if ( dn_match( &op->o_ndn, &pndn ) ) { - rc = 1; - } - slap_sl_free( ndn.bv_val, op->o_tmpmemctx ); - - return rc; + } else if ( ber_bvcmp( &aci_bv[ ACI_BV_SUBTREE ], &type ) == 0 ) { + return dnIsSuffix( &op->o_ndn, &sdn ); - /* TODO: use ber_bvcmp */ - } else if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_CHILDREN ], &type ) == 0 ) { - struct berval ndn; + } else if ( ber_bvcmp( &aci_bv[ ACI_BV_ONELEVEL ], &type ) == 0 ) { + struct berval pdn; - /* TODO: don't normalize */ - rc = dnNormalize( 0, NULL, NULL, &sdn, &ndn, op->o_tmpmemctx ); - if ( rc != LDAP_SUCCESS ) { - return 0; - } + dnParent( &sdn, &pdn ); - if ( !dn_match( &op->o_ndn, &ndn ) - && dnIsSuffix( &op->o_ndn, &ndn ) ) - { - rc = 1; - } - slap_sl_free( ndn.bv_val, op->o_tmpmemctx ); + return dn_match( &op->o_ndn, &pdn ); - return rc; + } else if ( ber_bvcmp( &aci_bv[ ACI_BV_CHILDREN ], &type ) == 0 ) { + return ( !dn_match( &op->o_ndn, &sdn ) && dnIsSuffix( &op->o_ndn, &sdn ) ); - /* TODO: use ber_bvcmp */ - } else if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_SELF ], &type ) == 0 ) { - if ( dn_match( &op->o_ndn, &e->e_nname ) ) { - return 1; - } + } else if ( ber_bvcmp( &aci_bv[ ACI_BV_SELF ], &type ) == 0 ) { + return dn_match( &op->o_ndn, &e->e_nname ); - /* TODO: use ber_bvcmp */ - } else if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_DNATTR ], &type ) == 0 ) { + } else if ( ber_bvcmp( &aci_bv[ ACI_BV_DNATTR ], &type ) == 0 ) { Attribute *at; AttributeDescription *ad = NULL; const char *text; rc = slap_bv2ad( &sdn, &ad, &text ); - if ( rc != LDAP_SUCCESS ) { - /* TODO: add assertion */ - return 0; - } + assert( rc == LDAP_SUCCESS ); rc = 0; for ( at = attrs_find( e->e_attrs, ad ); @@ -525,46 +586,165 @@ aci_mask( return rc; - /* TODO: use ber_bvcmp */ - } else if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_GROUP ], &type ) == 0 ) { - if ( aci_group_member( &sdn, &aci_bv[ ACI_BV_GROUP_CLASS ], - &aci_bv[ ACI_BV_GROUP_ATTR ], op, e, nmatch, matches ) ) + } else if ( ber_bvcmp( &aci_bv[ ACI_BV_GROUP ], &type ) == 0 ) { + struct berval oc, + at; + + if ( BER_BVISNULL( &opts ) ) { + oc = aci_bv[ ACI_BV_GROUP_CLASS ]; + at = aci_bv[ ACI_BV_GROUP_ATTR ]; + + } else { + if ( acl_get_part( &opts, 0, '/', &oc ) < 0 ) { + assert( 0 ); + } + + if ( acl_get_part( &opts, 1, '/', &at ) < 0 ) { + at = aci_bv[ ACI_BV_GROUP_ATTR ]; + } + } + + if ( aci_group_member( &sdn, &oc, &at, op, e, nmatch, matches ) ) { return 1; } - /* TODO: use ber_bvcmp */ - } else if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_ROLE ], &type ) == 0 ) { - if ( aci_group_member( &sdn, &aci_bv[ ACI_BV_ROLE_CLASS ], - &aci_bv[ ACI_BV_ROLE_ATTR ], op, e, nmatch, matches ) ) + } else if ( ber_bvcmp( &aci_bv[ ACI_BV_ROLE ], &type ) == 0 ) { + struct berval oc, + at; + + if ( BER_BVISNULL( &opts ) ) { + oc = aci_bv[ ACI_BV_ROLE_CLASS ]; + at = aci_bv[ ACI_BV_ROLE_ATTR ]; + + } else { + if ( acl_get_part( &opts, 0, '/', &oc ) < 0 ) { + assert( 0 ); + } + + if ( acl_get_part( &opts, 1, '/', &at ) < 0 ) { + at = aci_bv[ ACI_BV_ROLE_ATTR ]; + } + } + + if ( aci_group_member( &sdn, &oc, &at, op, e, nmatch, matches ) ) { return 1; } - /* TODO: use ber_bvcmp */ - } else if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_SET ], &type ) == 0 ) { - if ( acl_match_set( &sdn, op, e, 0 ) ) { + } else if ( ber_bvcmp( &aci_bv[ ACI_BV_SET ], &type ) == 0 ) { + if ( acl_match_set( &sdn, op, e, NULL ) ) { return 1; } - /* TODO: use ber_bvcmp */ - } else if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_SET_REF ], &type ) == 0 ) { - if ( acl_match_set( &sdn, op, e, 1 ) ) { + } else if ( ber_bvcmp( &aci_bv[ ACI_BV_SET_REF ], &type ) == 0 ) { + if ( acl_match_set( &sdn, op, e, (struct berval *)&aci_bv[ ACI_BV_SET_ATTR ] ) ) { return 1; } + + } else { + /* it passed normalization! */ + assert( 0 ); } return 0; } -#ifdef SLAP_DYNACL -/* - * FIXME: there is a silly dependence that makes it difficult - * to move ACIs in a run-time loadable module under the "dynacl" - * umbrella, because sets share some helpers with ACIs. - */ static int -dynacl_aci_parse( const char *fname, int lineno, slap_style_t sty, const char *right, void **privp ) +aci_init( void ) +{ + /* OpenLDAP eXperimental Syntax */ + static slap_syntax_defs_rec aci_syntax_def = { + "( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )", + SLAP_SYNTAX_HIDE, + OpenLDAPaciValidate, + OpenLDAPaciPretty + }; + static slap_mrule_defs_rec aci_mr_def = { + "( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' " + "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )", + SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, + NULL, OpenLDAPaciNormalize, OpenLDAPaciMatch, + NULL, NULL, + NULL + }; + static struct { + char *name; + char *desc; + slap_mask_t flags; + AttributeDescription **ad; + } aci_at = { + "OpenLDAPaci", "( 1.3.6.1.4.1.4203.666.1.5 " + "NAME 'OpenLDAPaci' " + "DESC 'OpenLDAP access control information (experimental)' " + "EQUALITY OpenLDAPaciMatch " + "SYNTAX 1.3.6.1.4.1.4203.666.2.1 " + "USAGE directoryOperation )", + SLAP_AT_HIDE, + &slap_ad_aci + }; + + LDAPAttributeType *at; + AttributeType *sat; + int rc; + const char *text; + + /* ACI syntax */ + rc = register_syntax( &aci_syntax_def ); + if ( rc != 0 ) { + return rc; + } + + /* ACI equality rule */ + rc = register_matching_rule( &aci_mr_def ); + if ( rc != 0 ) { + return rc; + } + + /* ACI attribute */ + at = ldap_str2attributetype( aci_at.desc, + &rc, &text, LDAP_SCHEMA_ALLOW_ALL ); + if ( !at ) { + Debug( LDAP_DEBUG_ANY, + "aci_init: AttributeType \"%s\" parse failed: %s %s\n", + aci_at.name, ldap_scherr2str( rc ), text ); + return rc; + } + + rc = at_add( at, 0, &sat, &text ); + if ( rc != LDAP_SUCCESS ) { + ldap_attributetype_free( at ); + Debug( LDAP_DEBUG_ANY, + "aci_init: AttributeType \"%s\" load failed: %s %s\n", + aci_at.name, scherr2str( rc ), text ); + return rc; + } + ldap_memfree( at ); + + rc = slap_str2ad( aci_at.name, + aci_at.ad, &text ); + if ( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_ANY, + "aci_init: unable to find AttributeDescription " + "\"%s\": %d (%s)\n", + aci_at.name, rc, text ); + return 1; + } + + /* install flags */ + sat->sat_flags |= aci_at.flags; + + return rc; +} + +static int +dynacl_aci_parse( + const char *fname, + int lineno, + const char *opts, + slap_style_t sty, + const char *right, + void **privp ) { AttributeDescription *ad = NULL; const char *text = NULL; @@ -585,7 +765,7 @@ dynacl_aci_parse( const char *fname, int lineno, slap_style_t sty, const char *r } } else { - ad = slap_schema.si_ad_aci; + ad = slap_ad_aci; } if ( !is_at_syntax( ad->ad_type, SLAPD_ACI_SYNTAX) ) { @@ -637,6 +817,11 @@ dynacl_aci_mask( char accessmaskbuf1[ACCESSMASK_MAXLEN]; #endif /* LDAP_DEBUG */ + if ( BER_BVISEMPTY( &e->e_nname ) ) { + /* no ACIs in the root DSE */ + return -1; + } + /* start out with nothing granted, nothing denied */ ACL_INIT(tgrant); ACL_INIT(tdeny); @@ -660,7 +845,7 @@ dynacl_aci_mask( } } - Debug( LDAP_DEBUG_ACL, "<= aci_mask grant %s deny %s\n", + Debug( LDAP_DEBUG_ACL, " <= aci_mask grant %s deny %s\n", accessmask2str( tgrant, accessmaskbuf, 1 ), accessmask2str( tdeny, accessmaskbuf1, 1 ), 0 ); } @@ -672,35 +857,41 @@ dynacl_aci_mask( if ( tgrant == ACL_PRIV_NONE && tdeny == ACL_PRIV_NONE ) { struct berval parent_ndn; -#if 1 - /* to solve the chicken'n'egg problem of accessing - * the OpenLDAPaci attribute, the direct access - * to the entry's attribute is unchecked; however, - * further accesses to OpenLDAPaci values in the - * ancestors occur through backend_attribute(), i.e. - * with the identity of the operation, requiring - * further access checking. For uniformity, this - * makes further requests occur as the rootdn, if - * any, i.e. searching for the OpenLDAPaci attribute - * is considered an internal search. If this is not - * acceptable, then the same check needs be performed - * when accessing the entry's attribute. */ - Operation op2 = *op; - - if ( !BER_BVISNULL( &op->o_bd->be_rootndn ) ) { - op2.o_dn = op->o_bd->be_rootdn; - op2.o_ndn = op->o_bd->be_rootndn; - } -#endif - dnParent( &e->e_nname, &parent_ndn ); while ( !BER_BVISEMPTY( &parent_ndn ) ){ int i; BerVarray bvals = NULL; int ret, stop; - Debug( LDAP_DEBUG_ACL, "checking ACI of \"%s\"\n", parent_ndn.bv_val, 0, 0 ); - ret = backend_attribute( &op2, NULL, &parent_ndn, ad, &bvals, ACL_AUTH ); + /* to solve the chicken'n'egg problem of accessing + * the OpenLDAPaci attribute, the direct access + * to the entry's attribute is unchecked; however, + * further accesses to OpenLDAPaci values in the + * ancestors occur through backend_attribute(), i.e. + * with the identity of the operation, requiring + * further access checking. For uniformity, this + * makes further requests occur as the rootdn, if + * any, i.e. searching for the OpenLDAPaci attribute + * is considered an internal search. If this is not + * acceptable, then the same check needs be performed + * when accessing the entry's attribute. */ + struct berval save_o_dn, save_o_ndn; + + if ( !BER_BVISNULL( &op->o_bd->be_rootndn ) ) { + save_o_dn = op->o_dn; + save_o_ndn = op->o_ndn; + + op->o_dn = op->o_bd->be_rootdn; + op->o_ndn = op->o_bd->be_rootndn; + } + + Debug( LDAP_DEBUG_ACL, " checking ACI of \"%s\"\n", parent_ndn.bv_val, 0, 0 ); + ret = backend_attribute( op, NULL, &parent_ndn, ad, &bvals, ACL_AUTH ); + + if ( !BER_BVISNULL( &op->o_bd->be_rootndn ) ) { + op->o_dn = save_o_dn; + op->o_ndn = save_o_ndn; + } switch ( ret ) { case LDAP_SUCCESS : @@ -777,10 +968,17 @@ static slap_dynacl_t dynacl_aci = { int dynacl_aci_init( void ) { - return slap_dynacl_register( &dynacl_aci ); + int rc; + + rc = aci_init(); + + if ( rc == 0 ) { + rc = slap_dynacl_register( &dynacl_aci ); + } + + return rc; } -#endif /* SLAP_DYNACL */ /* ACI syntax validation */ @@ -849,11 +1047,12 @@ OpenLDAPaciValidatePerms( for ( i = 0; i < perms->bv_len; ) { switch ( perms->bv_val[ i ] ) { + case 'x': + case 'd': case 'c': case 's': case 'r': case 'w': - case 'x': break; default: @@ -1079,6 +1278,7 @@ OpenLDAPaciNormalizeRights( static const struct berval *OpenLDAPaciscopes[] = { &aci_bv[ ACI_BV_ENTRY ], &aci_bv[ ACI_BV_CHILDREN ], + &aci_bv[ ACI_BV_SUBTREE ], NULL }; @@ -1110,7 +1310,7 @@ static const struct berval *OpenLDAPacitypes[] = { NULL }; -int +static int OpenLDAPaciValidate( Syntax *syntax, struct berval *val ) @@ -1202,11 +1402,13 @@ OpenLDAPaciValidate( struct berval ocbv = BER_BVNULL, atbv = BER_BVNULL; - ocbv.bv_val = strchr( type.bv_val, '/' ); + ocbv.bv_val = ber_bvchr( &type, '/' ); if ( ocbv.bv_val != NULL ) { ocbv.bv_val++; + ocbv.bv_len = type.bv_len + - ( ocbv.bv_val - type.bv_val ); - atbv.bv_val = strchr( ocbv.bv_val, '/' ); + atbv.bv_val = ber_bvchr( &ocbv, '/' ); if ( atbv.bv_val != NULL ) { AttributeDescription *ad = NULL; const char *text = NULL; @@ -1221,10 +1423,6 @@ OpenLDAPaciValidate( if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } - - } else { - ocbv.bv_len = type.bv_len - - ( ocbv.bv_val - type.bv_val ); } if ( oc_bvfind( &ocbv ) == NULL ) { @@ -1261,7 +1459,7 @@ OpenLDAPaciPrettyNormal( subject = BER_BVNULL, nsubject = BER_BVNULL; int idx, - rc, + rc = LDAP_SUCCESS, freesubject = 0, freetype = 0; char *ptr; @@ -1353,7 +1551,7 @@ OpenLDAPaciPrettyNormal( struct berval ocbv = BER_BVNULL, atbv = BER_BVNULL; - ocbv.bv_val = strchr( type.bv_val, '/' ); + ocbv.bv_val = ber_bvchr( &type, '/' ); if ( ocbv.bv_val != NULL ) { ObjectClass *oc = NULL; AttributeDescription *ad = NULL; @@ -1364,8 +1562,9 @@ OpenLDAPaciPrettyNormal( bv.bv_len = ntype.bv_len; ocbv.bv_val++; + ocbv.bv_len = type.bv_len - ( ocbv.bv_val - type.bv_val ); - atbv.bv_val = strchr( ocbv.bv_val, '/' ); + atbv.bv_val = ber_bvchr( &ocbv, '/' ); if ( atbv.bv_val != NULL ) { atbv.bv_val++; atbv.bv_len = type.bv_len @@ -1379,13 +1578,10 @@ OpenLDAPaciPrettyNormal( } bv.bv_len += STRLENOF( "/" ) + ad->ad_cname.bv_len; - - } else { - ocbv.bv_len = type.bv_len - - ( ocbv.bv_val - type.bv_val ); } - if ( oc_bvfind( &ocbv ) == NULL ) { + oc = oc_bvfind( &ocbv ); + if ( oc == NULL ) { rc = LDAP_INVALID_SYNTAX; goto cleanup; } @@ -1476,7 +1672,7 @@ cleanup:; return rc; } -int +static int OpenLDAPaciPretty( Syntax *syntax, struct berval *val, @@ -1486,7 +1682,7 @@ OpenLDAPaciPretty( return OpenLDAPaciPrettyNormal( val, out, ctx, 0 ); } -int +static int OpenLDAPaciNormalize( slap_mask_t use, Syntax *syntax, @@ -1498,5 +1694,17 @@ OpenLDAPaciNormalize( return OpenLDAPaciPrettyNormal( val, out, ctx, 1 ); } +#if SLAPD_ACI_ENABLED == SLAPD_MOD_DYNAMIC +/* + * FIXME: need config and Makefile.am code to ease building + * as dynamic module + */ +int +init_module( int argc, char *argv[] ) +{ + return dynacl_aci_init(); +} +#endif /* SLAPD_ACI_ENABLED == SLAPD_MOD_DYNAMIC */ + #endif /* SLAPD_ACI_ENABLED */