From 293c765c1143851dbfe029b1184410da26a6819e Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Wed, 22 Jan 2003 09:00:06 +0000 Subject: [PATCH] Added slapi_access_allowed() and slapi_acl_check_mods() API for Sun ONE DS 5.x compat This required exposing the mods array conversion functions so they are now in slapi/slapi_utils.[ch] --- servers/slapd/modify.c | 165 +----------------- servers/slapd/slapi/slapi.h | 13 ++ servers/slapd/slapi/slapi_utils.c | 273 +++++++++++++++++++++++++++++- servers/slapd/slapi/slapi_utils.h | 7 + 4 files changed, 296 insertions(+), 162 deletions(-) diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c index 03c4c05537..ae2efd3351 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -30,12 +30,6 @@ #include "slap.h" #include "slapi.h" -#ifdef LDAP_SLAPI -static LDAPMod **Modifications2LDAPMods (Modifications **modlist); -static Modifications *LDAPMods2Modifications (LDAPMod **mods); -static void FreeLDAPMods (LDAPMod **mods); -#endif /* LDAP_SLAPI */ - int do_modify( Connection *conn, @@ -345,7 +339,7 @@ do_modify( slapi_x_operation_set_pb( pb, op ); slapi_pblock_set( pb, SLAPI_MODIFY_TARGET, (void *)dn.bv_val ); slapi_pblock_set( pb, SLAPI_MANAGEDSAIT, (void *)(1) ); - modv = Modifications2LDAPMods( &modlist ); + modv = slapi_x_modifications2ldapmods( &modlist ); slapi_pblock_set( pb, SLAPI_MODIFY_MODS, (void *)modv ); rc = doPluginFNs( be, SLAPI_PLUGIN_PRE_MODIFY_FN, pb ); @@ -374,11 +368,11 @@ do_modify( * modification array, so we need to convert it back to * a Modification list. * - * Calling Modifications2LDAPMods() destroyed modlist so + * Calling slapi_x_modifications2ldapmods() destroyed modlist so * we don't need to free it. */ slapi_pblock_get( pb, SLAPI_MODIFY_MODS, (void **)&modv ); - modlist = LDAPMods2Modifications( modv ); + modlist = slapi_x_ldapmods2modifications( modv ); #endif /* defined( LDAP_SLAPI ) */ /* @@ -475,7 +469,7 @@ cleanup: free( ndn.bv_val ); if ( modlist != NULL ) slap_mods_free( modlist ); #if defined( LDAP_SLAPI ) - if ( modv != NULL ) FreeLDAPMods( modv ); + if ( modv != NULL ) slapi_x_free_ldapmods( modv ); #endif return rc; } @@ -772,154 +766,3 @@ int slap_mods_opattrs( return LDAP_SUCCESS; } -#ifdef LDAP_SLAPI -/* - * Synthesise an LDAPMod array from a Modifications list to pass - * to SLAPI. This synthesis is destructive and as such the - * Modifications list may not be used after calling this - * function. - * - * This function must also be called before slap_mods_check(). - */ -static LDAPMod **Modifications2LDAPMods(Modifications **pmodlist) -{ - Modifications *ml, *modlist; - LDAPMod **mods, *modp; - int i, j; - - modlist = *pmodlist; - - for( i = 0, ml = modlist; ml != NULL; i++, ml = ml->sml_next ) - ; - - mods = (LDAPMod **)ch_malloc( (i + 1) * sizeof(LDAPMod *) ); - - for( i = 0, ml = modlist; ml != NULL; ml = ml->sml_next ) { - modp = mods[i]; - modp->mod_op = ml->sml_op | LDAP_MOD_BVALUES; - - /* Take ownership of original type. */ - modp->mod_type = ml->sml_type.bv_val; - ml->sml_type.bv_val = NULL; - - if ( ml->sml_bvalues != NULL ) { - for( j = 0; ml->sml_bvalues[j].bv_val != NULL; j++ ) - ; - modp->mod_bvalues = (struct berval **)ch_malloc( (j + 1) * - sizeof(struct berval *) ); - for( j = 0; ml->sml_bvalues[j].bv_val != NULL; j++ ) { - /* Take ownership of original values. */ - modp->mod_bvalues[j] = (struct berval *)ch_malloc( sizeof(struct berval) ); - modp->mod_bvalues[j]->bv_len = ml->sml_bvalues[j].bv_len; - modp->mod_bvalues[j]->bv_val = ml->sml_bvalues[j].bv_val; - ml->sml_bvalues[j].bv_len = 0; - ml->sml_bvalues[j].bv_val = NULL; - } - modp->mod_bvalues[j] = NULL; - } else { - modp->mod_bvalues = NULL; - } - i++; - } - - mods[i] = NULL; - - slap_mods_free( modlist ); - *pmodlist = NULL; - - return mods; -} - -/* - * Convert a potentially modified array of LDAPMods back to a - * Modification list. - * - * The returned Modification list contains pointers into the - * LDAPMods array; the latter MUST be freed with FreeLDAPMods() - * (see below). - */ -static Modifications *LDAPMods2Modifications (LDAPMod **mods) -{ - Modifications *modlist, **modtail; - LDAPMod **modp; - - modtail = &modlist; - - for( modp = mods; *modp != NULL; modp++ ) { - Modifications *mod; - int i; - char **p; - struct berval **bvp; - - mod = (Modifications *) ch_malloc( sizeof(Modifications) ); - mod->sml_op = (*modp)->mod_op & (~LDAP_MOD_BVALUES); - mod->sml_type.bv_val = (*modp)->mod_type; - mod->sml_type.bv_len = strlen( mod->sml_type.bv_val ); - mod->sml_desc = NULL; - mod->sml_next = NULL; - - if ( (*modp)->mod_op & LDAP_MOD_BVALUES ) { - for( i = 0, bvp = (*modp)->mod_bvalues; *bvp != NULL; bvp++, i++ ) - ; - } else { - for( i = 0, p = (*modp)->mod_values; *p != NULL; p++, i++ ) - ; - } - - mod->sml_bvalues = (BerVarray) ch_malloc( (i + 1) * sizeof(struct berval) ); - - /* NB: This implicitly trusts a plugin to return valid modifications. */ - if ( (*modp)->mod_op & LDAP_MOD_BVALUES ) { - for( i = 0, bvp = (*modp)->mod_bvalues; *bvp != NULL; bvp++, i++ ) { - mod->sml_bvalues[i].bv_val = (*bvp)->bv_val; - mod->sml_bvalues[i].bv_len = (*bvp)->bv_len; - } - } else { - for( i = 0, p = (*modp)->mod_values; *p != NULL; p++, i++ ) { - mod->sml_bvalues[i].bv_val = *p; - mod->sml_bvalues[i].bv_len = strlen( *p ); - } - } - mod->sml_bvalues[i].bv_val = NULL; - - *modtail = mod; - modtail = &mod->sml_next; - } - - return modlist; -} - -/* - * This function only frees the parts of the mods array that - * are not shared with the Modification list that was created - * by LDAPMods2Modifications. - * - */ -static void FreeLDAPMods (LDAPMod **mods) -{ - int i, j; - - if (mods == NULL) - return; - - for ( i = 0; mods[i] != NULL; i++ ) { - /* - * Don't free values themselves; they're owned by the - * Modification list. Do free the containing array. - */ - if ( mods[i]->mod_op & LDAP_MOD_BVALUES ) { - for ( j = 0; mods[i]->mod_bvalues[j] != NULL; j++ ) { - ch_free( mods[i]->mod_bvalues[j] ); - } - ch_free( mods[i]->mod_bvalues ); - } else { - ch_free( mods[i]->mod_values ); - } - /* Don't free type, for same reasons. */ - ch_free( mods[i] ); - } - ch_free( mods ); -} - -#endif /* LDAP_SLAPI */ - diff --git a/servers/slapd/slapi/slapi.h b/servers/slapd/slapi/slapi.h index aae64082fc..d8c9e938b4 100644 --- a/servers/slapd/slapi/slapi.h +++ b/servers/slapd/slapi/slapi.h @@ -50,6 +50,19 @@ LDAP_BEGIN_DECL #define SLAPI_ATTR_FLAG_COLLECTIVE 0x0080 #define SLAPI_ATTR_FLAG_NOUSERMOD 0x0100 +/* + * ACL levels + */ +#define SLAPI_ACL_COMPARE 0x01 +#define SLAPI_ACL_SEARCH 0x02 +#define SLAPI_ACL_READ 0x04 +#define SLAPI_ACL_WRITE 0x08 +#define SLAPI_ACL_DELETE 0x10 +#define SLAPI_ACL_ADD 0x20 +#define SLAPI_ACL_SELF 0x40 +#define SLAPI_ACL_PROXY 0x80 +#define SLAPI_ACL_ALL 0x7f + /* * Plugin types universally supported by SLAPI * implementations diff --git a/servers/slapd/slapi/slapi_utils.c b/servers/slapd/slapi/slapi_utils.c index 4887da032b..fe15ffd277 100644 --- a/servers/slapd/slapi/slapi_utils.c +++ b/servers/slapd/slapi/slapi_utils.c @@ -423,6 +423,14 @@ slapi_ch_free( void **ptr ) #endif /* defined(LDAP_SLAPI) */ } +void +slapi_ch_free_string( char **ptr ) +{ +#if defined(LDAP_SLAPI) + slapi_ch_free( (void **)ptr ); +#endif /* defined(LDAP_SLAPI) */ +} + char * slapi_ch_calloc( unsigned long nelem, @@ -2064,9 +2072,113 @@ void slapi_valueset_set_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2) #endif } +int slapi_access_allowed( Slapi_PBlock *pb, Slapi_Entry *e, char *attr, + struct berval *val, int access ) +{ +#ifdef LDAPI_SLAPI + Backend *be; + Connection *conn; + Operation *op; + int ret; + slap_access_t slap_access; + AttributeDescription *ad = NULL; + char *text; + + ret = slap_str2ad( attr, &ad, &text ); + if ( ret != LDAP_SUCCESS ) { + return ret; + } + + switch ( access & SLAPI_ACL_ALL ) { + case SLAPI_ACL_COMPARE: + slap_access = ACL_COMPARE; + break; + case SLAPI_ACL_SEARCH: + slap_access = ACL_SEARCH; + break; + case SLAPI_ACL_READ: + slap_access = ACL_READ; + break; + case SLAPI_ACL_WRITE: + case SLAPI_ACL_DELETE: + case SLAPI_ACL_ADD: + case SLAPI_ACL_SELF: + slap_access = ACL_WRITE; + break; + default: + return LDAP_INSUFFICIENT_ACCESS; + break; + } + + if ( slapi_pblock_get( pb, SLAPI_BACKEND, (void *)&be ) != 0 ) { + return LDAP_PARAM_ERROR; + } + + if ( slapi_pblock_get( pb, SLAPI_CONNECTION, (void *)&conn ) != 0 ) { + return LDAP_PARAM_ERROR; + } + + if ( slapi_pblock_get( pb, SLAPI_OPERATION, (void *)&op ) != 0 ) { + return LDAP_PARAM_ERROR; + } + + ret = access_allowed( be, conn, op, e, desc, val, slap_access, NULL ); + + return ret ? LDAP_SUCCESS : LDAP_INSUFFICIENT_ACCESS; +#else + return LDAP_UNWILLING_TO_PERFORM; +#endif +} + +int slapi_acl_check_mods(Slapi_PBlock *pb, Slapi_Entry *e, LDAPMod **mods, char **errbuf) +{ +#ifdef LDAP_SLAPI + Backend *be; + Connection *conn; + Operation *op; + int ret; + Modifications *ml; + Modifications *next; + + if ( slapi_pblock_get( pb, SLAPI_BACKEND, (void *)&be ) != 0 ) { + return LDAP_PARAM_ERROR; + } + + if ( slapi_pblock_get( pb, SLAPI_CONNECTION, (void *)&conn ) != 0 ) { + return LDAP_PARAM_ERROR; + } + + if ( slapi_pblock_get( pb, SLAPI_OPERATION, (void *)&op ) != 0 ) { + return LDAP_PARAM_ERROR; + } + + ml = slapi_x_ldapmods2modifications( mods ); + if ( ml == NULL ) { + return LDAP_OTHER; + } + + ret = acl_check_modlist( be, conn, op, e, ml ); + + /* Careful when freeing the modlist because it has pointers into the mods array. */ + for ( ; ml != NULL; ml = next ) { + next = ml->sml_next; + + /* just free the containing array */ + slapi_ch_free( (void **)&ml->sml_bvalues ); + slapi_ch_free( (void **)&ml ); + } + + return ret ? LDAP_SUCCESS : LDAP_INSUFFICIENT_ACCESS; +#else + return LDAP_UNWILLING_TO_PERFORM; +#endif +} + /* * Attribute sets are an OpenLDAP extension for the - * virtual operational attribute coalescing plugin + * virtual operational attribute coalescing plugin + * + * Subject to going away very soon; do not use */ Slapi_AttrSet *slapi_x_attrset_new( void ) { @@ -2264,3 +2376,162 @@ int slapi_x_attrset_delete( Slapi_AttrSet *as, const char *type ) return -1; #endif } + +/* + * Synthesise an LDAPMod array from a Modifications list to pass + * to SLAPI. This synthesis is destructive and as such the + * Modifications list may not be used after calling this + * function. + * + * This function must also be called before slap_mods_check(). + */ +LDAPMod **slapi_x_modifications2ldapmods(Modifications **pmodlist) +{ +#ifdef LDAP_SLAPI + Modifications *ml, *modlist; + LDAPMod **mods, *modp; + int i, j; + + modlist = *pmodlist; + + for( i = 0, ml = modlist; ml != NULL; i++, ml = ml->sml_next ) + ; + + mods = (LDAPMod **)ch_malloc( (i + 1) * sizeof(LDAPMod *) ); + + for( i = 0, ml = modlist; ml != NULL; ml = ml->sml_next ) { + modp = mods[i]; + modp->mod_op = ml->sml_op | LDAP_MOD_BVALUES; + + /* Take ownership of original type. */ + modp->mod_type = ml->sml_type.bv_val; + ml->sml_type.bv_val = NULL; + + if ( ml->sml_bvalues != NULL ) { + for( j = 0; ml->sml_bvalues[j].bv_val != NULL; j++ ) + ; + modp->mod_bvalues = (struct berval **)ch_malloc( (j + 1) * + sizeof(struct berval *) ); + for( j = 0; ml->sml_bvalues[j].bv_val != NULL; j++ ) { + /* Take ownership of original values. */ + modp->mod_bvalues[j] = (struct berval *)ch_malloc( sizeof(struct berval) ); + modp->mod_bvalues[j]->bv_len = ml->sml_bvalues[j].bv_len; + modp->mod_bvalues[j]->bv_val = ml->sml_bvalues[j].bv_val; + ml->sml_bvalues[j].bv_len = 0; + ml->sml_bvalues[j].bv_val = NULL; + } + modp->mod_bvalues[j] = NULL; + } else { + modp->mod_bvalues = NULL; + } + i++; + } + + mods[i] = NULL; + + slap_mods_free( modlist ); + *pmodlist = NULL; + + return mods; +#else + return NULL; +#endif +} + +/* + * Convert a potentially modified array of LDAPMods back to a + * Modification list. + * + * The returned Modification list contains pointers into the + * LDAPMods array; the latter MUST be freed with + * slapi_x_free_ldapmods() (see below). + */ +Modifications *slapi_x_ldapmods2modifications (LDAPMod **mods) +{ +#ifdef LDAP_SLAPI + Modifications *modlist, **modtail; + LDAPMod **modp; + + modtail = &modlist; + + for( modp = mods; *modp != NULL; modp++ ) { + Modifications *mod; + int i; + char **p; + struct berval **bvp; + + mod = (Modifications *) ch_malloc( sizeof(Modifications) ); + mod->sml_op = (*modp)->mod_op & (~LDAP_MOD_BVALUES); + mod->sml_type.bv_val = (*modp)->mod_type; + mod->sml_type.bv_len = strlen( mod->sml_type.bv_val ); + mod->sml_desc = NULL; + mod->sml_next = NULL; + + if ( (*modp)->mod_op & LDAP_MOD_BVALUES ) { + for( i = 0, bvp = (*modp)->mod_bvalues; *bvp != NULL; bvp++, i++ ) + ; + } else { + for( i = 0, p = (*modp)->mod_values; *p != NULL; p++, i++ ) + ; + } + + mod->sml_bvalues = (BerVarray) ch_malloc( (i + 1) * sizeof(struct berval) ); + + /* NB: This implicitly trusts a plugin to return valid modifications. */ + if ( (*modp)->mod_op & LDAP_MOD_BVALUES ) { + for( i = 0, bvp = (*modp)->mod_bvalues; *bvp != NULL; bvp++, i++ ) { + mod->sml_bvalues[i].bv_val = (*bvp)->bv_val; + mod->sml_bvalues[i].bv_len = (*bvp)->bv_len; + } + } else { + for( i = 0, p = (*modp)->mod_values; *p != NULL; p++, i++ ) { + mod->sml_bvalues[i].bv_val = *p; + mod->sml_bvalues[i].bv_len = strlen( *p ); + } + } + mod->sml_bvalues[i].bv_val = NULL; + + *modtail = mod; + modtail = &mod->sml_next; + } + + return modlist; +#else + return NULL; +#endif +} + +/* + * This function only frees the parts of the mods array that + * are not shared with the Modification list that was created + * by slapi_x_ldapmods2modifications(). + * + */ +void slapi_x_free_ldapmods (LDAPMod **mods) +{ +#ifdef LDAP_SLAPI + int i, j; + + if (mods == NULL) + return; + + for ( i = 0; mods[i] != NULL; i++ ) { + /* + * Don't free values themselves; they're owned by the + * Modification list. Do free the containing array. + */ + if ( mods[i]->mod_op & LDAP_MOD_BVALUES ) { + for ( j = 0; mods[i]->mod_bvalues[j] != NULL; j++ ) { + ch_free( mods[i]->mod_bvalues[j] ); + } + ch_free( mods[i]->mod_bvalues ); + } else { + ch_free( mods[i]->mod_values ); + } + /* Don't free type, for same reasons. */ + ch_free( mods[i] ); + } + ch_free( mods ); +#endif /* LDAP_SLAPI */ +} + diff --git a/servers/slapd/slapi/slapi_utils.h b/servers/slapd/slapi/slapi_utils.h index 0b97dfb683..5c70db6750 100644 --- a/servers/slapd/slapi/slapi_utils.h +++ b/servers/slapd/slapi/slapi_utils.h @@ -69,6 +69,8 @@ int slapi_x_attrset_merge_bervals( Slapi_AttrSet *as, const char *type, struct b int slapi_x_attrset_delete( Slapi_AttrSet *as, const char *type ); /* DS 5.x SLAPI */ +int slapi_access_allowed( Slapi_PBlock *pb, Slapi_Entry *e, char *attr, struct berval *val, int access ); +int slapi_acl_check_mods( Slapi_PBlock *pb, Slapi_Entry *e, LDAPMod **mods, char **errbuf ); Slapi_Attr *slapi_attr_new( void ); Slapi_Attr *slapi_attr_init( Slapi_Attr *a, const char *type ); void slapi_attr_free( Slapi_Attr **a ); @@ -128,6 +130,7 @@ void slapi_valueset_set_valueset(Slapi_ValueSet *vs1, const Slapi_ValueSet *vs2) char *slapi_ch_malloc( unsigned long size ); void slapi_ch_free( void **ptr ); +void slapi_ch_free_string( char **s ); char *slapi_ch_calloc( unsigned long nelem, unsigned long size ); char *slapi_ch_realloc( char *block, unsigned long size ); char *slapi_ch_strdup( char *s ); @@ -186,6 +189,10 @@ int slapi_x_backend_set_pb( Slapi_PBlock *pb, Backend *be ); int slapi_x_connection_set_pb( Slapi_PBlock *pb, Connection *conn ); int slapi_x_operation_set_pb( Slapi_PBlock *pb, Operation *op ); +LDAPMod **slapi_x_modifications2ldapmods(Modifications **); +Modifications *slapi_x_ldapmods2modifications(LDAPMod **); +void slapi_x_free_ldapmods(LDAPMod **); + extern ldap_pvt_thread_mutex_t slapi_hn_mutex; extern ldap_pvt_thread_mutex_t slapi_time_mutex; extern ldap_pvt_thread_mutex_t slapi_printmessage_mutex; -- 2.39.5