static int add_aa_entry( int index, char* aliasing_at_name, char* aliased_at_name, char* mr_name, char* component_filter ) { char text[1][128]; int rc; struct berval type; /* get and store aliasing AttributeDescription */ type.bv_val = aliasing_at_name; type.bv_len = strlen ( aliasing_at_name ); rc = slap_bv2ad ( &type, &aa_table[index].aa_aliasing_ad,(const char**)text ); if ( rc != LDAP_SUCCESS ) return rc; /* get and store aliased AttributeDescription */ type.bv_val = aliased_at_name; type.bv_len = strlen ( aliased_at_name ); rc = slap_bv2ad ( &type, &aa_table[index].aa_aliased_ad,(const char**)text ); if ( rc != LDAP_SUCCESS ) return rc; /* get and store componentFilterMatch */ type.bv_val = mr_name; type.bv_len = strlen ( mr_name); aa_table[index].aa_mr = mr_bvfind ( &type ); /* get and store a component filter */ type.bv_val = component_filter; type.bv_len = strlen ( component_filter ); rc = get_comp_filter( NULL, &type, &aa_table[index].aa_cf,(const char**)text); aa_table[index].aa_cf_str = component_filter; return rc; }
static int LDAPRDN_validate( LDAPRDN rdn ) { int iAVA; int rc; assert( rdn != NULL ); for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; AttributeDescription *ad; slap_syntax_validate_func *validate = NULL; assert( ava != NULL ); if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) { const char *text = NULL; rc = slap_bv2ad( &ava->la_attr, &ad, &text ); if ( rc != LDAP_SUCCESS ) { rc = slap_bv2undef_ad( &ava->la_attr, &ad, &text, SLAP_AD_PROXIED|slap_DN_strict ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } ava->la_private = ( void * )ad; } /* * Do not allow X-ORDERED 'VALUES' naming attributes */ if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) { return LDAP_INVALID_SYNTAX; } /* * Replace attr oid/name with the canonical name */ ava->la_attr = ad->ad_cname; validate = ad->ad_type->sat_syntax->ssyn_validate; if ( validate ) { /* * validate value by validate function */ rc = ( *validate )( ad->ad_type->sat_syntax, &ava->la_value ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } } return LDAP_SUCCESS; }
/* * In-place, schema-aware validation of the * structural representation of a distinguished name. */ static int LDAPDN_validate( LDAPDN *dn ) { int iRDN; int rc; assert( dn ); for ( iRDN = 0; dn[ 0 ][ iRDN ]; iRDN++ ) { LDAPRDN *rdn = dn[ 0 ][ iRDN ]; int iAVA; assert( rdn ); for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ 0 ][ iAVA ]; AttributeDescription *ad; slap_syntax_validate_func *validate = NULL; assert( ava ); if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) { const char *text = NULL; rc = slap_bv2ad( &ava->la_attr, &ad, &text ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } ava->la_private = ( void * )ad; } /* * Replace attr oid/name with the canonical name */ ava->la_attr = ad->ad_cname; validate = ad->ad_type->sat_syntax->ssyn_validate; if ( validate ) { /* * validate value by validate function */ rc = ( *validate )( ad->ad_type->sat_syntax, &ava->la_value ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } } } return LDAP_SUCCESS; }
int slap_str2ad( const char *str, AttributeDescription **ad, const char **text ) { struct berval bv; bv.bv_val = (char *) str; bv.bv_len = strlen( str ); return slap_bv2ad( &bv, ad, text ); }
int mdb_ad_read( struct mdb_info *mdb, MDB_txn *txn ) { int i, rc; MDB_cursor *mc; MDB_val key, data; struct berval bdata; const char *text; AttributeDescription *ad; rc = mdb_cursor_open( txn, mdb->mi_ad2id, &mc ); if ( rc ) { Debug( LDAP_DEBUG_ANY, "mdb_ad_read: cursor_open failed %s(%d)\n", mdb_strerror(rc), rc, 0); return rc; } /* our array is 1-based, an index of 0 means no data */ i = mdb->mi_numads+1; key.mv_size = sizeof(int); key.mv_data = &i; rc = mdb_cursor_get( mc, &key, &data, MDB_SET ); while ( rc == MDB_SUCCESS ) { bdata.bv_len = data.mv_size; bdata.bv_val = data.mv_data; ad = NULL; rc = slap_bv2ad( &bdata, &ad, &text ); if ( rc ) { rc = slap_bv2undef_ad( &bdata, &mdb->mi_ads[i], &text, 0 ); } else { if ( ad->ad_index >= MDB_MAXADS ) { Debug( LDAP_DEBUG_ANY, "mdb_adb_read: too many AttributeDescriptions in use\n", 0, 0, 0 ); return LDAP_OTHER; } mdb->mi_adxs[ad->ad_index] = i; mdb->mi_ads[i] = ad; } i++; rc = mdb_cursor_get( mc, &key, &data, MDB_NEXT ); } mdb->mi_numads = i-1; done: if ( rc == MDB_NOTFOUND ) rc = 0; mdb_cursor_close( mc ); return rc; }
Entry * monitor_entry_stub( struct berval *pdn, struct berval *pndn, struct berval *rdn, ObjectClass *oc, struct berval *create, struct berval *modify ) { monitor_info_t *mi; AttributeDescription *nad = NULL; Entry *e; struct berval nat; char *ptr; const char *text; int rc; mi = ( monitor_info_t * )be_monitor->be_private; nat = *rdn; ptr = strchr( nat.bv_val, '=' ); nat.bv_len = ptr - nat.bv_val; rc = slap_bv2ad( &nat, &nad, &text ); if ( rc ) return NULL; e = entry_alloc(); if ( e ) { struct berval nrdn; rdnNormalize( 0, NULL, NULL, rdn, &nrdn, NULL ); build_new_dn( &e->e_name, pdn, rdn, NULL ); build_new_dn( &e->e_nname, pndn, &nrdn, NULL ); ber_memfree( nrdn.bv_val ); nat.bv_val = ptr + 1; nat.bv_len = rdn->bv_len - ( nat.bv_val - rdn->bv_val ); attr_merge_normalize_one( e, slap_schema.si_ad_objectClass, &oc->soc_cname, NULL ); attr_merge_normalize_one( e, slap_schema.si_ad_structuralObjectClass, &oc->soc_cname, NULL ); attr_merge_normalize_one( e, nad, &nat, NULL ); attr_merge_one( e, slap_schema.si_ad_creatorsName, &mi->mi_creatorsName, &mi->mi_ncreatorsName ); attr_merge_one( e, slap_schema.si_ad_modifiersName, &mi->mi_creatorsName, &mi->mi_ncreatorsName ); attr_merge_normalize_one( e, slap_schema.si_ad_createTimestamp, create ? create : &mi->mi_startTime, NULL ); attr_merge_normalize_one( e, slap_schema.si_ad_modifyTimestamp, modify ? modify : &mi->mi_startTime, NULL ); } return e; }
/* Rewrite an LDAP DN in DER form * Input must be valid DN, therefore no error checking is done here. */ static int autoca_dnbv2der( Operation *op, struct berval *bv, struct berval *der ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; LDAPDN dn; LDAPRDN rdn; LDAPAVA *ava; AttributeDescription *ad; int irdn, iava; ldap_bv2dn_x( bv, &dn, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ); ber_init2( ber, NULL, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); /* count RDNs, we need them in reverse order */ for (irdn = 0; dn[irdn]; irdn++); irdn--; /* DN is a SEQuence of RDNs */ ber_start_seq( ber, LBER_SEQUENCE ); for (; irdn >=0; irdn--) { /* RDN is a SET of AVAs */ ber_start_set( ber, LBER_SET ); rdn = dn[irdn]; for (iava = 0; rdn[iava]; iava++) { const char *text; char oid[1024]; struct berval bvo = { sizeof(oid), oid }; struct berval bva; /* AVA is a SEQuence of attr and value */ ber_start_seq( ber, LBER_SEQUENCE ); ava = rdn[iava]; ad = NULL; slap_bv2ad( &ava->la_attr, &ad, &text ); ber_str2bv( ad->ad_type->sat_oid, 0, 0, &bva ); ber_encode_oid( &bva, &bvo ); ber_put_berval( ber, &bvo, LBER_TAG_OID ); ber_put_berval( ber, &ava->la_value, LBER_TAG_UTF8 ); ber_put_seq( ber ); } ber_put_set( ber ); } ber_put_seq( ber ); ber_flatten2( ber, der, 0 ); ldap_dnfree_x( dn, op->o_tmpmemctx ); return 0; }
/* Find or create an NdbAttrInfo */ extern "C" NdbAttrInfo * ndb_ai_get( struct ndb_info *ni, struct berval *aname ) { NdbAttrInfo atmp, *ai; atmp.na_name = *aname; ai = (NdbAttrInfo *)avl_find( ni->ni_ai_tree, &atmp, ndb_name_cmp ); if ( !ai ) { const char *text; AttributeDescription *ad = NULL; if ( slap_bv2ad( aname, &ad, &text )) return NULL; ai = (NdbAttrInfo *)ch_malloc( sizeof( NdbAttrInfo )); ai->na_desc = ad; ai->na_attr = ai->na_desc->ad_type; ai->na_name = ai->na_attr->sat_cname; ai->na_oi = NULL; ai->na_flag = 0; ai->na_ixcol = 0; ai->na_len = ai->na_attr->sat_atype.at_syntax_len; /* Reasonable default */ if ( !ai->na_len ) { if ( ai->na_attr->sat_syntax == slap_schema.si_syn_distinguishedName ) ai->na_len = 1024; else ai->na_len = 128; } /* Arbitrary limit */ if ( ai->na_len > 1024 ) ai->na_len = 1024; avl_insert( &ni->ni_ai_tree, ai, ndb_name_cmp, avl_dup_error ); } return ai; }
int slap_modrdn2mods( Operation *op, SlapReply *rs ) { int a_cnt, d_cnt; LDAPRDN old_rdn = NULL; LDAPRDN new_rdn = NULL; assert( !BER_BVISEMPTY( &op->oq_modrdn.rs_newrdn ) ); /* if requestDN is empty, silently reset deleteOldRDN */ if ( BER_BVISEMPTY( &op->o_req_dn ) ) op->orr_deleteoldrdn = 0; if ( ldap_bv2rdn_x( &op->oq_modrdn.rs_newrdn, &new_rdn, (char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) { Debug( LDAP_DEBUG_TRACE, "%s slap_modrdn2mods: can't figure out " "type(s)/value(s) of newrdn\n", op->o_log_prefix, 0, 0 ); rs->sr_err = LDAP_INVALID_DN_SYNTAX; rs->sr_text = "unknown type(s)/value(s) used in RDN"; goto done; } if ( op->oq_modrdn.rs_deleteoldrdn ) { if ( ldap_bv2rdn_x( &op->o_req_dn, &old_rdn, (char **)&rs->sr_text, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ) ) { Debug( LDAP_DEBUG_TRACE, "%s slap_modrdn2mods: can't figure out " "type(s)/value(s) of oldrdn\n", op->o_log_prefix, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "cannot parse RDN from old DN"; goto done; } } rs->sr_text = NULL; /* Add new attribute values to the entry */ for ( a_cnt = 0; new_rdn[a_cnt]; a_cnt++ ) { AttributeDescription *desc = NULL; Modifications *mod_tmp; rs->sr_err = slap_bv2ad( &new_rdn[a_cnt]->la_attr, &desc, &rs->sr_text ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "%s slap_modrdn2mods: %s: %s (new)\n", op->o_log_prefix, rs->sr_text, new_rdn[ a_cnt ]->la_attr.bv_val ); goto done; } if ( !desc->ad_type->sat_equality ) { Debug( LDAP_DEBUG_TRACE, "%s slap_modrdn2mods: %s: %s (new)\n", op->o_log_prefix, rs->sr_text, new_rdn[ a_cnt ]->la_attr.bv_val ); rs->sr_text = "naming attribute has no equality matching rule"; rs->sr_err = LDAP_NAMING_VIOLATION; goto done; } /* Apply modification */ mod_tmp = ( Modifications * )ch_malloc( sizeof( Modifications ) ); mod_tmp->sml_desc = desc; BER_BVZERO( &mod_tmp->sml_type ); mod_tmp->sml_numvals = 1; mod_tmp->sml_values = ( BerVarray )ch_malloc( 2 * sizeof( struct berval ) ); ber_dupbv( &mod_tmp->sml_values[0], &new_rdn[a_cnt]->la_value ); mod_tmp->sml_values[1].bv_val = NULL; if( desc->ad_type->sat_equality->smr_normalize) { mod_tmp->sml_nvalues = ( BerVarray )ch_malloc( 2 * sizeof( struct berval ) ); rs->sr_err = desc->ad_type->sat_equality->smr_normalize( SLAP_MR_EQUALITY|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, desc->ad_type->sat_syntax, desc->ad_type->sat_equality, &mod_tmp->sml_values[0], &mod_tmp->sml_nvalues[0], NULL ); if (rs->sr_err != LDAP_SUCCESS) { ch_free(mod_tmp->sml_nvalues); ch_free(mod_tmp->sml_values[0].bv_val); ch_free(mod_tmp->sml_values); ch_free(mod_tmp); goto done; } mod_tmp->sml_nvalues[1].bv_val = NULL; } else { mod_tmp->sml_nvalues = NULL; } mod_tmp->sml_op = SLAP_MOD_SOFTADD; mod_tmp->sml_flags = 0; mod_tmp->sml_next = op->orr_modlist; op->orr_modlist = mod_tmp; } /* Remove old rdn value if required */ if ( op->orr_deleteoldrdn ) { for ( d_cnt = 0; old_rdn[d_cnt]; d_cnt++ ) { AttributeDescription *desc = NULL; Modifications *mod_tmp; rs->sr_err = slap_bv2ad( &old_rdn[d_cnt]->la_attr, &desc, &rs->sr_text ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "%s slap_modrdn2mods: %s: %s (old)\n", op->o_log_prefix, rs->sr_text, old_rdn[d_cnt]->la_attr.bv_val ); goto done; } /* Apply modification */ mod_tmp = ( Modifications * )ch_malloc( sizeof( Modifications ) ); mod_tmp->sml_desc = desc; BER_BVZERO( &mod_tmp->sml_type ); mod_tmp->sml_numvals = 1; mod_tmp->sml_values = ( BerVarray )ch_malloc( 2 * sizeof( struct berval ) ); ber_dupbv( &mod_tmp->sml_values[0], &old_rdn[d_cnt]->la_value ); mod_tmp->sml_values[1].bv_val = NULL; if( desc->ad_type->sat_equality->smr_normalize) { mod_tmp->sml_nvalues = ( BerVarray )ch_malloc( 2 * sizeof( struct berval ) ); (void) (*desc->ad_type->sat_equality->smr_normalize)( SLAP_MR_EQUALITY|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, desc->ad_type->sat_syntax, desc->ad_type->sat_equality, &mod_tmp->sml_values[0], &mod_tmp->sml_nvalues[0], NULL ); mod_tmp->sml_nvalues[1].bv_val = NULL; } else { mod_tmp->sml_nvalues = NULL; } mod_tmp->sml_op = LDAP_MOD_DELETE; mod_tmp->sml_flags = 0; mod_tmp->sml_next = op->orr_modlist; op->orr_modlist = mod_tmp; } } done: /* LDAP v2 supporting correct attribute handling. */ if ( rs->sr_err != LDAP_SUCCESS && op->orr_modlist != NULL ) { Modifications *tmp; for ( ; op->orr_modlist != NULL; op->orr_modlist = tmp ) { tmp = op->orr_modlist->sml_next; ch_free( op->orr_modlist ); } } if ( new_rdn != NULL ) { ldap_rdnfree_x( new_rdn, op->o_tmpmemctx ); } if ( old_rdn != NULL ) { ldap_rdnfree_x( old_rdn, op->o_tmpmemctx ); } return rs->sr_err; }
static int pblock_set( Slapi_PBlock *pb, int param, void *value ) { int rc = PBLOCK_SUCCESS; pblock_lock( pb ); switch ( param ) { case SLAPI_OPERATION: pb->pb_op = (Operation *)value; break; case SLAPI_OPINITIATED_TIME: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_time = *((long *)value); break; case SLAPI_OPERATION_ID: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_opid = *((long *)value); break; case SLAPI_OPERATION_TYPE: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_tag = *((ber_tag_t *)value); break; case SLAPI_OPERATION_MSGID: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_msgid = *((long *)value); break; case SLAPI_X_OPERATION_DELETE_GLUE_PARENT: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_delete_glue_parent = *((int *)value); break; case SLAPI_X_OPERATION_NO_SCHEMA_CHECK: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_no_schema_check = *((int *)value); break; case SLAPI_X_OPERATION_NO_SUBORDINATE_GLUE: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_no_subordinate_glue = *((int *)value); break; case SLAPI_REQCONTROLS: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_ctrls = (LDAPControl **)value; break; case SLAPI_RESCONTROLS: { LDAPControl **ctrls = NULL; pblock_get_default( pb, param, (void **)&ctrls ); if ( ctrls != NULL ) { /* free old ones first */ ldap_controls_free( ctrls ); } rc = pblock_set_default( pb, param, value ); break; } case SLAPI_ADD_RESCONTROL: PBLOCK_ASSERT_OP( pb, 0 ); rc = pblock_add_control( pb, (LDAPControl *)value ); break; case SLAPI_REQUESTOR_DN: PBLOCK_ASSERT_OP( pb, 0 ); rc = pblock_set_dn( value, &pb->pb_op->o_dn, &pb->pb_op->o_ndn, pb->pb_op->o_tmpmemctx ); break; case SLAPI_MANAGEDSAIT: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_managedsait = *((int *)value); break; case SLAPI_X_RELAX: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_relax = *((int *)value); break; case SLAPI_BACKEND: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_bd = (BackendDB *)value; break; case SLAPI_CONNECTION: pb->pb_conn = (Connection *)value; break; case SLAPI_X_CONN_SSF: PBLOCK_ASSERT_CONN( pb ); PBLOCK_LOCK_CONN( pb ); pb->pb_conn->c_ssf = (slap_ssf_t)(long)value; PBLOCK_UNLOCK_CONN( pb ); break; case SLAPI_X_CONN_SASL_CONTEXT: PBLOCK_ASSERT_CONN( pb ); PBLOCK_LOCK_CONN( pb ); pb->pb_conn->c_sasl_authctx = value; PBLOCK_UNLOCK_CONN( pb ); break; case SLAPI_TARGET_DN: PBLOCK_ASSERT_OP( pb, 0 ); rc = pblock_set_dn( value, &pb->pb_op->o_req_dn, &pb->pb_op->o_req_ndn, pb->pb_op->o_tmpmemctx ); break; case SLAPI_CONN_ID: PBLOCK_ASSERT_CONN( pb ); PBLOCK_LOCK_CONN( pb ); pb->pb_conn->c_connid = *((long *)value); PBLOCK_UNLOCK_CONN( pb ); break; case SLAPI_CONN_DN: PBLOCK_ASSERT_CONN( pb ); PBLOCK_LOCK_CONN( pb ); rc = pblock_set_dn( value, &pb->pb_conn->c_dn, &pb->pb_conn->c_ndn, NULL ); PBLOCK_UNLOCK_CONN( pb ); break; case SLAPI_RESULT_CODE: case SLAPI_PLUGIN_INTOP_RESULT: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_rs->sr_err = *((int *)value); break; case SLAPI_RESULT_TEXT: PBLOCK_ASSERT_OP( pb, 0 ); snprintf( pb->pb_textbuf, sizeof( pb->pb_textbuf ), "%s", (char *)value ); pb->pb_rs->sr_text = pb->pb_textbuf; break; case SLAPI_RESULT_MATCHED: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_rs->sr_matched = (char *)value; /* XXX should dup? */ break; case SLAPI_ADD_ENTRY: PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_ADD ) pb->pb_op->ora_e = (Slapi_Entry *)value; else rc = PBLOCK_ERROR; break; case SLAPI_MODIFY_MODS: { Modifications **mlp; Modifications *newmods; PBLOCK_ASSERT_OP( pb, 0 ); rc = pblock_set_default( pb, param, value ); if ( rc != PBLOCK_SUCCESS ) { break; } if ( pb->pb_op->o_tag == LDAP_REQ_MODIFY ) { mlp = &pb->pb_op->orm_modlist; } else if ( pb->pb_op->o_tag == LDAP_REQ_ADD ) { mlp = &pb->pb_op->ora_modlist; } else if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) { mlp = &pb->pb_op->orr_modlist; } else { break; } newmods = slapi_int_ldapmods2modifications( pb->pb_op, (LDAPMod **)value ); if ( newmods != NULL ) { slap_mods_free( *mlp, 1 ); *mlp = newmods; } break; } case SLAPI_MODRDN_NEWRDN: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) { rc = pblock_set_dn( value, &pb->pb_op->orr_newrdn, &pb->pb_op->orr_nnewrdn, pb->pb_op->o_tmpmemctx ); if ( rc == LDAP_SUCCESS ) rc = rdn_validate( &pb->pb_op->orr_nnewrdn ); } else { rc = PBLOCK_ERROR; } break; case SLAPI_MODRDN_NEWSUPERIOR: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) { if ( value == NULL ) { if ( pb->pb_op->orr_newSup != NULL ) { pb->pb_op->o_tmpfree( pb->pb_op->orr_newSup, pb->pb_op->o_tmpmemctx ); BER_BVZERO( pb->pb_op->orr_newSup ); pb->pb_op->orr_newSup = NULL; } if ( pb->pb_op->orr_newSup != NULL ) { pb->pb_op->o_tmpfree( pb->pb_op->orr_nnewSup, pb->pb_op->o_tmpmemctx ); BER_BVZERO( pb->pb_op->orr_nnewSup ); pb->pb_op->orr_nnewSup = NULL; } } else { if ( pb->pb_op->orr_newSup == NULL ) { pb->pb_op->orr_newSup = (struct berval *)pb->pb_op->o_tmpalloc( sizeof(struct berval), pb->pb_op->o_tmpmemctx ); BER_BVZERO( pb->pb_op->orr_newSup ); } if ( pb->pb_op->orr_nnewSup == NULL ) { pb->pb_op->orr_nnewSup = (struct berval *)pb->pb_op->o_tmpalloc( sizeof(struct berval), pb->pb_op->o_tmpmemctx ); BER_BVZERO( pb->pb_op->orr_nnewSup ); } rc = pblock_set_dn( value, pb->pb_op->orr_newSup, pb->pb_op->orr_nnewSup, pb->pb_op->o_tmpmemctx ); } } else { rc = PBLOCK_ERROR; } break; case SLAPI_MODRDN_DELOLDRDN: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) pb->pb_op->orr_deleteoldrdn = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_SEARCH_SCOPE: { int scope = *((int *)value); PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) { switch ( *((int *)value) ) { case LDAP_SCOPE_BASE: case LDAP_SCOPE_ONELEVEL: case LDAP_SCOPE_SUBTREE: case LDAP_SCOPE_SUBORDINATE: pb->pb_op->ors_scope = scope; break; default: rc = PBLOCK_ERROR; break; } } else { rc = PBLOCK_ERROR; } break; } case SLAPI_SEARCH_DEREF: PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) pb->pb_op->ors_deref = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_SEARCH_SIZELIMIT: PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) pb->pb_op->ors_slimit = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_SEARCH_TIMELIMIT: PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) pb->pb_op->ors_tlimit = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_SEARCH_FILTER: PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) pb->pb_op->ors_filter = (Slapi_Filter *)value; else rc = PBLOCK_ERROR; break; case SLAPI_SEARCH_STRFILTER: PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) { pb->pb_op->ors_filterstr.bv_val = (char *)value; pb->pb_op->ors_filterstr.bv_len = strlen((char *)value); } else { rc = PBLOCK_ERROR; } break; case SLAPI_SEARCH_ATTRS: { AttributeName *an = NULL; size_t i = 0, j = 0; char **attrs = (char **)value; PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag != LDAP_REQ_SEARCH ) { rc = PBLOCK_ERROR; break; } /* also set mapped attrs */ rc = pblock_set_default( pb, param, value ); if ( rc != PBLOCK_SUCCESS ) { break; } if ( pb->pb_op->ors_attrs != NULL ) { pb->pb_op->o_tmpfree( pb->pb_op->ors_attrs, pb->pb_op->o_tmpmemctx ); pb->pb_op->ors_attrs = NULL; } if ( attrs != NULL ) { for ( i = 0; attrs[i] != NULL; i++ ) ; } if ( i ) { an = (AttributeName *)pb->pb_op->o_tmpcalloc( i + 1, sizeof(AttributeName), pb->pb_op->o_tmpmemctx ); for ( i = 0; attrs[i] != NULL; i++ ) { an[j].an_desc = NULL; an[j].an_oc = NULL; an[j].an_flags = 0; an[j].an_name.bv_val = attrs[i]; an[j].an_name.bv_len = strlen( attrs[i] ); if ( slap_bv2ad( &an[j].an_name, &an[j].an_desc, &pb->pb_rs->sr_text ) == LDAP_SUCCESS ) { j++; } } an[j].an_name.bv_val = NULL; an[j].an_name.bv_len = 0; } pb->pb_op->ors_attrs = an; break; } case SLAPI_SEARCH_ATTRSONLY: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) pb->pb_op->ors_attrsonly = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_SEARCH_RESULT_ENTRY: PBLOCK_ASSERT_OP( pb, 0 ); rs_replace_entry( pb->pb_op, pb->pb_rs, NULL, (Slapi_Entry *)value ); /* TODO: Should REP_ENTRY_MODIFIABLE be set? */ pb->pb_rs->sr_flags |= REP_ENTRY_MUSTBEFREED; break; case SLAPI_BIND_RET_SASLCREDS: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_rs->sr_sasldata = (struct berval *)value; break; case SLAPI_EXT_OP_REQ_OID: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_EXTENDED ) { pb->pb_op->ore_reqoid.bv_val = (char *)value; pb->pb_op->ore_reqoid.bv_len = strlen((char *)value); } else { rc = PBLOCK_ERROR; } break; case SLAPI_EXT_OP_REQ_VALUE: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_EXTENDED ) pb->pb_op->ore_reqdata = (struct berval *)value; else rc = PBLOCK_ERROR; break; case SLAPI_EXT_OP_RET_OID: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_rs->sr_rspoid = (char *)value; break; case SLAPI_EXT_OP_RET_VALUE: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_rs->sr_rspdata = (struct berval *)value; break; case SLAPI_BIND_METHOD: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_BIND ) pb->pb_op->orb_method = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_BIND_CREDENTIALS: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_BIND ) pb->pb_op->orb_cred = *((struct berval *)value); else rc = PBLOCK_ERROR; break; case SLAPI_COMPARE_TYPE: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE ) { const char *text; pb->pb_op->orc_ava->aa_desc = NULL; rc = slap_str2ad( (char *)value, &pb->pb_op->orc_ava->aa_desc, &text ); } else { rc = PBLOCK_ERROR; } break; case SLAPI_COMPARE_VALUE: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE ) pb->pb_op->orc_ava->aa_value = *((struct berval *)value); else rc = PBLOCK_ERROR; break; case SLAPI_ABANDON_MSGID: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_ABANDON) pb->pb_op->orn_msgid = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_REQUESTOR_ISROOT: case SLAPI_IS_REPLICATED_OPERATION: case SLAPI_CONN_AUTHTYPE: case SLAPI_CONN_AUTHMETHOD: case SLAPI_IS_INTERNAL_OPERATION: case SLAPI_X_CONN_IS_UDP: case SLAPI_CONN_CLIENTIP: case SLAPI_X_CONN_CLIENTPATH: case SLAPI_CONN_SERVERIP: case SLAPI_X_CONN_SERVERPATH: case SLAPI_X_ADD_STRUCTURAL_CLASS: /* These parameters cannot be set */ rc = PBLOCK_ERROR; break; default: rc = pblock_set_default( pb, param, value ); break; } pblock_unlock( pb ); return rc; }
static int dl_cfgen( ConfigArgs *c ) { slap_overinst *on = (slap_overinst *)c->bi; dynlist_info_t *dli = (dynlist_info_t *)on->on_bi.bi_private; int rc = 0, i; if ( c->op == SLAP_CONFIG_EMIT ) { switch( c->type ) { case DL_ATTRSET: for ( i = 0; dli; i++, dli = dli->dli_next ) { struct berval bv; char *ptr = c->cr_msg; dynlist_map_t *dlm; assert( dli->dli_oc != NULL ); assert( dli->dli_ad != NULL ); /* FIXME: check buffer overflow! */ ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ), SLAP_X_ORDERED_FMT "%s", i, dli->dli_oc->soc_cname.bv_val ); if ( !BER_BVISNULL( &dli->dli_uri ) ) { *ptr++ = ' '; *ptr++ = '"'; ptr = lutil_strncopy( ptr, dli->dli_uri.bv_val, dli->dli_uri.bv_len ); *ptr++ = '"'; } *ptr++ = ' '; ptr = lutil_strncopy( ptr, dli->dli_ad->ad_cname.bv_val, dli->dli_ad->ad_cname.bv_len ); for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { ptr[ 0 ] = ' '; ptr++; if ( dlm->dlm_mapped_ad ) { ptr = lutil_strcopy( ptr, dlm->dlm_mapped_ad->ad_cname.bv_val ); ptr[ 0 ] = ':'; ptr++; } ptr = lutil_strcopy( ptr, dlm->dlm_member_ad->ad_cname.bv_val ); } bv.bv_val = c->cr_msg; bv.bv_len = ptr - bv.bv_val; value_add_one( &c->rvalue_vals, &bv ); } break; case DL_ATTRPAIR_COMPAT: case DL_ATTRPAIR: rc = 1; break; default: rc = 1; break; } return rc; } else if ( c->op == LDAP_MOD_DELETE ) { switch( c->type ) { case DL_ATTRSET: if ( c->valx < 0 ) { dynlist_info_t *dli_next; for ( dli_next = dli; dli_next; dli = dli_next ) { dynlist_map_t *dlm = dli->dli_dlm; dynlist_map_t *dlm_next; dli_next = dli->dli_next; if ( !BER_BVISNULL( &dli->dli_uri ) ) { ch_free( dli->dli_uri.bv_val ); } if ( dli->dli_lud != NULL ) { ldap_free_urldesc( dli->dli_lud ); } if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) { ber_memfree( dli->dli_uri_nbase.bv_val ); } if ( dli->dli_uri_filter != NULL ) { filter_free( dli->dli_uri_filter ); } ch_free( dli->dli_default_filter.bv_val ); while ( dlm != NULL ) { dlm_next = dlm->dlm_next; ch_free( dlm ); dlm = dlm_next; } ch_free( dli ); } on->on_bi.bi_private = NULL; } else { dynlist_info_t **dlip; dynlist_map_t *dlm; dynlist_map_t *dlm_next; for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private; i < c->valx; i++ ) { if ( *dlip == NULL ) { return 1; } dlip = &(*dlip)->dli_next; } dli = *dlip; *dlip = dli->dli_next; if ( !BER_BVISNULL( &dli->dli_uri ) ) { ch_free( dli->dli_uri.bv_val ); } if ( dli->dli_lud != NULL ) { ldap_free_urldesc( dli->dli_lud ); } if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) { ber_memfree( dli->dli_uri_nbase.bv_val ); } if ( dli->dli_uri_filter != NULL ) { filter_free( dli->dli_uri_filter ); } ch_free( dli->dli_default_filter.bv_val ); dlm = dli->dli_dlm; while ( dlm != NULL ) { dlm_next = dlm->dlm_next; ch_free( dlm ); dlm = dlm_next; } ch_free( dli ); dli = (dynlist_info_t *)on->on_bi.bi_private; } break; case DL_ATTRPAIR_COMPAT: case DL_ATTRPAIR: rc = 1; break; default: rc = 1; break; } return rc; } switch( c->type ) { case DL_ATTRSET: { dynlist_info_t **dlip, *dli_next = NULL; ObjectClass *oc = NULL; AttributeDescription *ad = NULL; int attridx = 2; LDAPURLDesc *lud = NULL; struct berval nbase = BER_BVNULL; Filter *filter = NULL; struct berval uri = BER_BVNULL; dynlist_map_t *dlm = NULL, *dlml = NULL; const char *text; oc = oc_find( c->argv[ 1 ] ); if ( oc == NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to find ObjectClass \"%s\"", c->argv[ 1 ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } if ( strncasecmp( c->argv[ attridx ], "ldap://", STRLENOF("ldap://") ) == 0 ) { if ( ldap_url_parse( c->argv[ attridx ], &lud ) != LDAP_URL_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to parse URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } if ( lud->lud_host != NULL ) { if ( lud->lud_host[0] == '\0' ) { ch_free( lud->lud_host ); lud->lud_host = NULL; } else { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "host not allowed in URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } } if ( lud->lud_attrs != NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "attrs not allowed in URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } if ( lud->lud_exts != NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "extensions not allowed in URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } if ( lud->lud_dn != NULL && lud->lud_dn[ 0 ] != '\0' ) { struct berval dn; ber_str2bv( lud->lud_dn, 0, 0, &dn ); rc = dnNormalize( 0, NULL, NULL, &dn, &nbase, NULL ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "DN normalization failed in URI \"%s\"", c->argv[ attridx ] ); goto done_uri; } } if ( lud->lud_filter != NULL && lud->lud_filter[ 0 ] != '\0' ) { filter = str2filter( lud->lud_filter ); if ( filter == NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "filter parsing failed in URI \"%s\"", c->argv[ attridx ] ); rc = 1; goto done_uri; } } ber_str2bv( c->argv[ attridx ], 0, 1, &uri ); done_uri:; if ( rc ) { if ( lud ) { ldap_free_urldesc( lud ); } if ( !BER_BVISNULL( &nbase ) ) { ber_memfree( nbase.bv_val ); } if ( filter != NULL ) { filter_free( filter ); } while ( dlm != NULL ) { dlml = dlm; dlm = dlm->dlm_next; ch_free( dlml ); } Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return rc; } attridx++; } rc = slap_str2ad( c->argv[ attridx ], &ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to find AttributeDescription \"%s\"", c->argv[ attridx ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "AttributeDescription \"%s\" " "must be a subtype of \"labeledURI\"", c->argv[ attridx ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } attridx++; for ( i = attridx; i < c->argc; i++ ) { char *arg; char *cp; AttributeDescription *member_ad = NULL; AttributeDescription *mapped_ad = NULL; dynlist_map_t *dlmp; /* * If no mapped attribute is given, dn is used * for backward compatibility. */ arg = c->argv[i]; if ( ( cp = strchr( arg, ':' ) ) != NULL ) { struct berval bv; ber_str2bv( arg, cp - arg, 0, &bv ); rc = slap_bv2ad( &bv, &mapped_ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to find mapped AttributeDescription #%d \"%s\"\n", i - 3, c->argv[ i ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } arg = cp + 1; } rc = slap_str2ad( arg, &member_ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "unable to find AttributeDescription #%d \"%s\"\n", i - 3, c->argv[ i ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } dlmp = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) ); if ( dlm == NULL ) { dlm = dlmp; } dlmp->dlm_member_ad = member_ad; dlmp->dlm_mapped_ad = mapped_ad; dlmp->dlm_next = NULL; if ( dlml != NULL ) dlml->dlm_next = dlmp; dlml = dlmp; } if ( c->valx > 0 ) { int i; for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private; i < c->valx; i++ ) { if ( *dlip == NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "invalid index {%d}\n", c->valx ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); rc = 1; goto done_uri; } dlip = &(*dlip)->dli_next; } dli_next = *dlip; } else { for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private; *dlip; dlip = &(*dlip)->dli_next ) /* goto last */; } *dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) ); (*dlip)->dli_oc = oc; (*dlip)->dli_ad = ad; (*dlip)->dli_dlm = dlm; (*dlip)->dli_next = dli_next; (*dlip)->dli_lud = lud; (*dlip)->dli_uri_nbase = nbase; (*dlip)->dli_uri_filter = filter; (*dlip)->dli_uri = uri; rc = dynlist_build_def_filter( *dlip ); } break; case DL_ATTRPAIR_COMPAT: snprintf( c->cr_msg, sizeof( c->cr_msg ), "warning: \"attrpair\" only supported for limited " "backward compatibility with overlay \"dyngroup\"" ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); /* fallthru */ case DL_ATTRPAIR: { dynlist_info_t **dlip; ObjectClass *oc = NULL; AttributeDescription *ad = NULL, *member_ad = NULL; const char *text; oc = oc_find( "groupOfURLs" ); if ( oc == NULL ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"dynlist-attrpair <member-ad> <URL-ad>\": " "unable to find default ObjectClass \"groupOfURLs\"" ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } rc = slap_str2ad( c->argv[ 1 ], &member_ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"dynlist-attrpair <member-ad> <URL-ad>\": " "unable to find AttributeDescription \"%s\"", c->argv[ 1 ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } rc = slap_str2ad( c->argv[ 2 ], &ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"dynlist-attrpair <member-ad> <URL-ad>\": " "unable to find AttributeDescription \"%s\"\n", c->argv[ 2 ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE "AttributeDescription \"%s\" " "must be a subtype of \"labeledURI\"", c->argv[ 2 ] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); return 1; } for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private; *dlip; dlip = &(*dlip)->dli_next ) { /* * The same URL attribute / member attribute pair * cannot be repeated, but we enforce this only * when the member attribute is unique. Performing * the check for multiple values would require * sorting and comparing the lists, which is left * as a future improvement */ if ( (*dlip)->dli_ad == ad && (*dlip)->dli_dlm->dlm_next == NULL && member_ad == (*dlip)->dli_dlm->dlm_member_ad ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "\"dynlist-attrpair <member-ad> <URL-ad>\": " "URL attributeDescription \"%s\" already mapped.\n", ad->ad_cname.bv_val ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); #if 0 /* make it a warning... */ return 1; #endif } } *dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) ); (*dlip)->dli_oc = oc; (*dlip)->dli_ad = ad; (*dlip)->dli_dlm = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) ); (*dlip)->dli_dlm->dlm_member_ad = member_ad; (*dlip)->dli_dlm->dlm_mapped_ad = NULL; rc = dynlist_build_def_filter( *dlip ); } break; default: rc = 1; break; } return rc; }
static int aci_mask( Operation *op, Entry *e, AttributeDescription *desc, struct berval *val, struct berval *aci, int nmatch, regmatch_t *matches, slap_access_t *grant, slap_access_t *deny, slap_aci_scope_t asserted_scope ) { struct berval bv, scope, perms, type, opts, sdn; int rc; ACL_INIT( *grant ); ACL_INIT( *deny ); assert( !BER_BVISNULL( &desc->ad_cname ) ); /* parse an aci of the form: oid # scope # action;rights;attr;rights;attr $ action;rights;attr;rights;attr # type # subject [NOTE: the following comment is very outdated, as the draft version it refers to (Ando, 2004-11-20)]. See draft-ietf-ldapext-aci-model-04.txt section 9.1 for a full description of the format for this attribute. Differences: "this" in the draft is "self" here, and "self" and "public" is in the position of type. <scope> = {entry|children|subtree} <type> = {public|users|access-id|subtree|onelevel|children| self|dnattr|group|role|set|set-ref} This routine now supports scope={ENTRY,CHILDREN} with the semantics: - ENTRY applies to "entry" and "subtree"; - CHILDREN applies to "children" and "subtree" */ /* check that the aci has all 5 components */ if ( acl_get_part( aci, 4, '#', NULL ) < 0 ) { return 0; } /* check that the aci family is supported */ /* FIXME: the OID is ignored? */ if ( acl_get_part( aci, 0, '#', &bv ) < 0 ) { return 0; } /* check that the scope matches */ if ( acl_get_part( aci, 1, '#', &scope ) < 0 ) { return 0; } /* note: scope can be either ENTRY or CHILDREN; * they respectively match "entry" and "children" in bv * both match "subtree" */ switch ( asserted_scope ) { case SLAP_ACI_SCOPE_ENTRY: if ( ber_bvcmp( &scope, &aci_bv[ ACI_BV_ENTRY ] ) != 0 && ber_bvstrcasecmp( &scope, &aci_bv[ ACI_BV_SUBTREE ] ) != 0 ) { return 0; } break; case SLAP_ACI_SCOPE_CHILDREN: if ( ber_bvcmp( &scope, &aci_bv[ ACI_BV_CHILDREN ] ) != 0 && ber_bvstrcasecmp( &scope, &aci_bv[ ACI_BV_SUBTREE ] ) != 0 ) { return 0; } break; 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 ) { LDAP_BUG(); return 0; } /* check if any permissions allow desired access */ if ( aci_list_get_rights( &perms, &desc->ad_cname, val, grant, deny ) == 0 ) { return 0; } /* see if we have a DN match */ if ( acl_get_part( aci, 3, '#', &type ) < 0 ) { LDAP_BUG(); return 0; } /* see if we have a public (i.e. anonymous) access */ if ( ber_bvcmp( &aci_bv[ ACI_BV_PUBLIC ], &type ) == 0 ) { return 1; } /* otherwise require an identity */ if ( BER_BVISNULL( &op->o_ndn ) || BER_BVISEMPTY( &op->o_ndn ) ) { return 0; } /* see if we have a users access */ if ( ber_bvcmp( &aci_bv[ ACI_BV_USERS ], &type ) == 0 ) { return 1; } /* NOTE: this may fail if a DN contains a valid '#' (unescaped); * just grab all the berval up to its end (ITS#3303). * NOTE: the problem could be solved by providing the DN with * the embedded '#' encoded as hexpairs: "cn=Foo#Bar" would * become "cn=Foo\23Bar" and be safely used by aci_mask(). */ #if 0 if ( acl_get_part( aci, 4, '#', &sdn ) < 0 ) { return 0; } #endif sdn.bv_val = type.bv_val + type.bv_len + STRLENOF( "#" ); sdn.bv_len = aci->bv_len - ( sdn.bv_val - aci->bv_val ); /* 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; } else { BER_BVZERO( &opts ); } if ( ber_bvcmp( &aci_bv[ ACI_BV_ACCESS_ID ], &type ) == 0 ) { return dn_match( &op->o_ndn, &sdn ); } else if ( ber_bvcmp( &aci_bv[ ACI_BV_SUBTREE ], &type ) == 0 ) { return dnIsSuffix( &op->o_ndn, &sdn ); } else if ( ber_bvcmp( &aci_bv[ ACI_BV_ONELEVEL ], &type ) == 0 ) { struct berval pdn; dnParent( &sdn, &pdn ); return dn_match( &op->o_ndn, &pdn ); } else if ( ber_bvcmp( &aci_bv[ ACI_BV_CHILDREN ], &type ) == 0 ) { return ( !dn_match( &op->o_ndn, &sdn ) && dnIsSuffix( &op->o_ndn, &sdn ) ); } else if ( ber_bvcmp( &aci_bv[ ACI_BV_SELF ], &type ) == 0 ) { return dn_match( &op->o_ndn, &e->e_nname ); } 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 ); assert( rc == LDAP_SUCCESS ); rc = 0; for ( at = attrs_find( e->e_attrs, ad ); at != NULL; at = attrs_find( at->a_next, ad ) ) { if ( attr_valfind( at, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, &op->o_ndn, NULL, op->o_tmpmemctx ) == 0 ) { rc = 1; break; } } return rc; } 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 ) { LDAP_BUG(); } 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; } } 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 ) { LDAP_BUG(); } 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; } } else if ( ber_bvcmp( &aci_bv[ ACI_BV_SET ], &type ) == 0 ) { if ( acl_match_set( &sdn, op, e, NULL ) ) { return 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! */ LDAP_BUG(); } return 0; }
static int OpenLDAPaciPrettyNormal( struct berval *val, struct berval *out, void *ctx, int normalize ) { struct berval oid = BER_BVNULL, scope = BER_BVNULL, rights = BER_BVNULL, nrights = BER_BVNULL, type = BER_BVNULL, ntype = BER_BVNULL, subject = BER_BVNULL, nsubject = BER_BVNULL; int idx, rc = LDAP_SUCCESS, freesubject = 0, freetype = 0; char *ptr; BER_BVZERO( out ); if ( BER_BVISEMPTY( val ) ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: value is empty\n" ); return LDAP_INVALID_SYNTAX; } /* oid: if valid, it's already normalized */ if ( acl_get_part( val, 0, '#', &oid ) < 0 || numericoidValidate( NULL, &oid ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid oid '%s'\n", oid.bv_val ); return LDAP_INVALID_SYNTAX; } /* scope: normalize by replacing with OpenLDAPaciscopes */ if ( acl_get_part( val, 1, '#', &scope ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing scope in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } idx = bv_getcaseidx( &scope, OpenLDAPaciscopes ); if ( idx == -1 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid scope '%s'\n", scope.bv_val ); return LDAP_INVALID_SYNTAX; } scope = *OpenLDAPaciscopes[ idx ]; /* rights */ if ( acl_get_part( val, 2, '#', &rights ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing rights in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } if ( OpenLDAPaciNormalizeRights( &rights, &nrights, ctx ) != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } /* type */ if ( acl_get_part( val, 3, '#', &type ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing type in '%s'\n", val->bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } idx = bv_getcaseidx( &type, OpenLDAPacitypes ); if ( idx == -1 ) { struct berval isgr; if ( acl_get_part( &type, 0, '/', &isgr ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", type.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } idx = bv_getcaseidx( &isgr, OpenLDAPacitypes ); if ( idx == -1 || idx >= LAST_OPTIONAL ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", isgr.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } } ntype = *OpenLDAPacitypes[ idx ]; /* subject */ bv_get_tail( val, &type, &subject ); if ( BER_BVISEMPTY( &subject ) || subject.bv_val[ 0 ] != '#' ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing subject in '%s'\n", val->bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } subject.bv_val++; subject.bv_len--; if ( idx < LAST_DNVALUED ) { /* FIXME: pass DN syntax? */ if ( normalize ) { rc = dnNormalize( 0, NULL, NULL, &subject, &nsubject, ctx ); } else { rc = dnPretty( NULL, &subject, &nsubject, ctx ); } if ( rc == LDAP_SUCCESS ) { freesubject = 1; } else { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid subject dn '%s'\n", subject.bv_val ); goto cleanup; } if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_GROUP ] || OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_ROLE ] ) { /* do {group|role}/oc/at check */ struct berval ocbv = BER_BVNULL, atbv = BER_BVNULL; ocbv.bv_val = ber_bvchr( &type, '/' ); if ( ocbv.bv_val != NULL ) { ObjectClass *oc = NULL; AttributeDescription *ad = NULL; const char *text = NULL; int rc; struct berval bv; bv.bv_len = ntype.bv_len; ocbv.bv_val++; ocbv.bv_len = type.bv_len - ( ocbv.bv_val - type.bv_val ); atbv.bv_val = ber_bvchr( &ocbv, '/' ); if ( atbv.bv_val != NULL ) { atbv.bv_val++; atbv.bv_len = type.bv_len - ( atbv.bv_val - type.bv_val ); ocbv.bv_len = atbv.bv_val - ocbv.bv_val - 1; rc = slap_bv2ad( &atbv, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown group attribute '%s'\n", atbv.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } bv.bv_len += STRLENOF( "/" ) + ad->ad_cname.bv_len; } oc = oc_bvfind( &ocbv ); if ( oc == NULL ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid group '%s'\n", ocbv.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } bv.bv_len += STRLENOF( "/" ) + oc->soc_cname.bv_len; bv.bv_val = ber_memalloc_x( bv.bv_len + 1, ctx ); ptr = bv.bv_val; ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len ); ptr[ 0 ] = '/'; ptr++; ptr = lutil_strncopy( ptr, oc->soc_cname.bv_val, oc->soc_cname.bv_len ); if ( ad != NULL ) { ptr[ 0 ] = '/'; ptr++; ptr = lutil_strncopy( ptr, ad->ad_cname.bv_val, ad->ad_cname.bv_len ); } ptr[ 0 ] = '\0'; ntype = bv; freetype = 1; } } } else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_DNATTR ] ) { AttributeDescription *ad = NULL; const char *text = NULL; int rc; rc = slap_bv2ad( &subject, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown dn attribute '%s'\n", subject.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } if ( ad->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) { /* FIXME: allow nameAndOptionalUID? */ Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: wrong syntax for dn attribute '%s'\n", subject.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } nsubject = ad->ad_cname; } else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET ] || OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET_REF ] ) { /* NOTE: dunno how to normalize it... */ nsubject = subject; } out->bv_len = oid.bv_len + STRLENOF( "#" ) + scope.bv_len + STRLENOF( "#" ) + nrights.bv_len + STRLENOF( "#" ) + ntype.bv_len + STRLENOF( "#" ) + nsubject.bv_len; out->bv_val = ber_memalloc_x( out->bv_len + 1, ctx ); ptr = lutil_strncopy( out->bv_val, oid.bv_val, oid.bv_len ); ptr[ 0 ] = '#'; ptr++; ptr = lutil_strncopy( ptr, scope.bv_val, scope.bv_len ); ptr[ 0 ] = '#'; ptr++; ptr = lutil_strncopy( ptr, nrights.bv_val, nrights.bv_len ); ptr[ 0 ] = '#'; ptr++; ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len ); ptr[ 0 ] = '#'; ptr++; if ( !BER_BVISNULL( &nsubject ) ) { ptr = lutil_strncopy( ptr, nsubject.bv_val, nsubject.bv_len ); } ptr[ 0 ] = '\0'; cleanup:; if ( freesubject ) { ber_memfree_x( nsubject.bv_val, ctx ); } if ( freetype ) { ber_memfree_x( ntype.bv_val, ctx ); } if ( !BER_BVISNULL( &nrights ) ) { ber_memfree_x( nrights.bv_val, ctx ); } return rc; }
static int OpenLDAPaciNormalizeRight( struct berval *action, struct berval *naction, void *ctx ) { struct berval grantdeny, perms = BER_BVNULL, bv = BER_BVNULL; int idx, i; /* grant|deny */ if ( acl_get_part( action, 0, ';', &grantdeny ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: missing ';' in '%s'\n", action->bv_val ); return LDAP_INVALID_SYNTAX; } idx = bv_getcaseidx( &grantdeny, ACIgrantdeny ); if ( idx == -1 ) { Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: '%s' must be grant or deny\n", grantdeny.bv_val ); return LDAP_INVALID_SYNTAX; } ber_dupbv_x( naction, (struct berval *)ACIgrantdeny[ idx ], ctx ); for ( i = 1; acl_get_part( action, i, ';', &bv ) >= 0; i++ ) { struct berval nattrs = BER_BVNULL; int freenattrs = 1; if ( i & 1 ) { /* perms */ if ( OpenLDAPaciValidatePerms( &bv ) != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } perms = bv; } else { /* attr */ char *ptr; /* could be "[all]" or an attribute description */ if ( ber_bvstrcasecmp( &bv, &aci_bv[ ACI_BV_BR_ALL ] ) == 0 ) { nattrs = aci_bv[ ACI_BV_BR_ALL ]; freenattrs = 0; } else { AttributeDescription *ad = NULL; AttributeDescription adstatic= { 0 }; const char *text = NULL; struct berval attr, left, right; int j; int len; for ( j = 0; acl_get_part( &bv, j, ',', &attr ) >= 0; j++ ) { ad = NULL; text = NULL; /* openldap 2.1 aci compabitibility [entry] -> entry */ if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_ENTRY ] ) == 0 ) { ad = &adstatic; adstatic.ad_cname = aci_bv[ ACI_BV_ENTRY ]; /* openldap 2.1 aci compabitibility [children] -> children */ } else if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_CHILDREN ] ) == 0 ) { ad = &adstatic; adstatic.ad_cname = aci_bv[ ACI_BV_CHILDREN ]; /* openldap 2.1 aci compabitibility [all] -> only [all] */ } else if ( ber_bvstrcasecmp( &attr, &aci_bv[ ACI_BV_BR_ALL ] ) == 0 ) { ber_memfree_x( nattrs.bv_val, ctx ); nattrs = aci_bv[ ACI_BV_BR_ALL ]; freenattrs = 0; break; } else if ( acl_get_part( &attr, 0, '=', &left ) < 0 || acl_get_part( &attr, 1, '=', &right ) < 0 ) { if ( slap_bv2ad( &attr, &ad, &text ) != LDAP_SUCCESS ) { ber_memfree_x( nattrs.bv_val, ctx ); Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: unknown attribute: '%s'\n", attr.bv_val ); return LDAP_INVALID_SYNTAX; } } else { if ( slap_bv2ad( &left, &ad, &text ) != LDAP_SUCCESS ) { ber_memfree_x( nattrs.bv_val, ctx ); Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: unknown attribute: '%s'\n", left.bv_val ); return LDAP_INVALID_SYNTAX; } } len = nattrs.bv_len + ( !BER_BVISEMPTY( &nattrs ) ? STRLENOF( "," ) : 0 ) + ad->ad_cname.bv_len; nattrs.bv_val = ber_memrealloc_x( nattrs.bv_val, len + 1, ctx ); ptr = &nattrs.bv_val[ nattrs.bv_len ]; if ( !BER_BVISEMPTY( &nattrs ) ) { *ptr++ = ','; } ptr = lutil_strncopy( ptr, ad->ad_cname.bv_val, ad->ad_cname.bv_len ); ptr[ 0 ] = '\0'; nattrs.bv_len = len; } } naction->bv_val = ber_memrealloc_x( naction->bv_val, naction->bv_len + STRLENOF( ";" ) + perms.bv_len + STRLENOF( ";" ) + nattrs.bv_len + 1, ctx ); ptr = &naction->bv_val[ naction->bv_len ]; ptr[ 0 ] = ';'; ptr++; ptr = lutil_strncopy( ptr, perms.bv_val, perms.bv_len ); ptr[ 0 ] = ';'; ptr++; ptr = lutil_strncopy( ptr, nattrs.bv_val, nattrs.bv_len ); ptr[ 0 ] = '\0'; naction->bv_len += STRLENOF( ";" ) + perms.bv_len + STRLENOF( ";" ) + nattrs.bv_len; if ( freenattrs ) { ber_memfree_x( nattrs.bv_val, ctx ); } } } /* perms;attr go in pairs */ if ( i > 1 && ( i & 1 ) ) { return LDAP_SUCCESS; } else { Debug( LDAP_DEBUG_ACL, "aciNormalizeRight: perms:attr need to be pairs in '%s'\n", action->bv_val ); return LDAP_INVALID_SYNTAX; } }
int do_search( Operation *op, /* info about the op to which we're responding */ SlapReply *rs /* all the response data we'll send */ ) { struct berval base = BER_BVNULL; ber_len_t siz, off, i; Debug( LDAP_DEBUG_TRACE, "%s do_search\n", op->o_log_prefix, 0, 0 ); /* * Parse the search request. It looks like this: * * SearchRequest := [APPLICATION 3] SEQUENCE { * baseObject DistinguishedName, * scope ENUMERATED { * baseObject (0), * singleLevel (1), * wholeSubtree (2), * subordinate (3) -- OpenLDAP extension * }, * derefAliases ENUMERATED { * neverDerefaliases (0), * derefInSearching (1), * derefFindingBaseObj (2), * alwaysDerefAliases (3) * }, * sizelimit INTEGER (0 .. 65535), * timelimit INTEGER (0 .. 65535), * attrsOnly BOOLEAN, * filter Filter, * attributes SEQUENCE OF AttributeType * } */ /* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */ if ( ber_scanf( op->o_ber, "{miiiib" /*}*/, &base, &op->ors_scope, &op->ors_deref, &op->ors_slimit, &op->ors_tlimit, &op->ors_attrsonly ) == LBER_ERROR ) { send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); rs->sr_err = SLAPD_DISCONNECT; goto return_results; } if ( op->ors_tlimit < 0 || op->ors_tlimit > SLAP_MAX_LIMIT ) { send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid time limit" ); goto return_results; } if ( op->ors_slimit < 0 || op->ors_slimit > SLAP_MAX_LIMIT ) { send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid size limit" ); goto return_results; } switch( op->ors_scope ) { case LDAP_SCOPE_BASE: case LDAP_SCOPE_ONELEVEL: case LDAP_SCOPE_SUBTREE: case LDAP_SCOPE_SUBORDINATE: break; default: send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid scope" ); goto return_results; } switch( op->ors_deref ) { case LDAP_DEREF_NEVER: case LDAP_DEREF_FINDING: case LDAP_DEREF_SEARCHING: case LDAP_DEREF_ALWAYS: break; default: send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid deref" ); goto return_results; } rs->sr_err = dnPrettyNormal( NULL, &base, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_search: invalid dn: \"%s\"\n", op->o_log_prefix, base.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" ); goto return_results; } Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d", base.bv_val, op->ors_scope, op->ors_deref ); Debug( LDAP_DEBUG_ARGS, " %d %d %d\n", op->ors_slimit, op->ors_tlimit, op->ors_attrsonly); /* filter - returns a "normalized" version */ rs->sr_err = get_filter( op, op->o_ber, &op->ors_filter, &rs->sr_text ); if( rs->sr_err != LDAP_SUCCESS ) { if( rs->sr_err == SLAPD_DISCONNECT ) { rs->sr_err = LDAP_PROTOCOL_ERROR; send_ldap_disconnect( op, rs ); rs->sr_err = SLAPD_DISCONNECT; } else { send_ldap_result( op, rs ); } goto return_results; } filter2bv_x( op, op->ors_filter, &op->ors_filterstr ); Debug( LDAP_DEBUG_ARGS, " filter: %s\n", !BER_BVISEMPTY( &op->ors_filterstr ) ? op->ors_filterstr.bv_val : "empty", 0, 0 ); /* attributes */ siz = sizeof(AttributeName); off = offsetof(AttributeName,an_name); if ( ber_scanf( op->o_ber, "{M}}", &op->ors_attrs, &siz, off ) == LBER_ERROR ) { send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding attrs error" ); rs->sr_err = SLAPD_DISCONNECT; goto return_results; } for ( i=0; i<siz; i++ ) { const char *dummy; /* ignore msgs from bv2ad */ op->ors_attrs[i].an_desc = NULL; op->ors_attrs[i].an_oc = NULL; op->ors_attrs[i].an_flags = 0; if ( slap_bv2ad( &op->ors_attrs[i].an_name, &op->ors_attrs[i].an_desc, &dummy ) != LDAP_SUCCESS ) { if ( slap_bv2undef_ad( &op->ors_attrs[i].an_name, &op->ors_attrs[i].an_desc, &dummy, SLAP_AD_PROXIED|SLAP_AD_NOINSERT ) ) { struct berval *bv = &op->ors_attrs[i].an_name; /* RFC 4511 LDAPv3: All User Attributes */ if ( bvmatch( bv, slap_bv_all_user_attrs ) ) { continue; } /* RFC 3673 LDAPv3: All Operational Attributes */ if ( bvmatch( bv, slap_bv_all_operational_attrs ) ) { continue; } /* RFC 4529 LDAP: Requesting Attributes by Object Class */ if ( bv->bv_len > 1 && bv->bv_val[0] == '@' ) { /* FIXME: check if remaining is valid oc name? */ continue; } /* add more "exceptions" to RFC 4511 4.5.1.8. */ /* invalid attribute description? remove */ if ( ad_keystring( bv ) ) { /* NOTE: parsed in-place, don't modify; * rather add "1.1", which must be ignored */ BER_BVSTR( &op->ors_attrs[i].an_name, LDAP_NO_ATTRS ); } /* otherwise leave in place... */ } } } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_search: get_ctrls failed\n", op->o_log_prefix, 0, 0 ); goto return_results; } Debug( LDAP_DEBUG_ARGS, " attrs:", 0, 0, 0 ); if ( siz != 0 ) { for ( i = 0; i<siz; i++ ) { Debug( LDAP_DEBUG_ARGS, " %s", op->ors_attrs[i].an_name.bv_val, 0, 0 ); } } Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 ); if ( StatslogTest( LDAP_DEBUG_STATS ) ) { char abuf[BUFSIZ/2], *ptr = abuf; unsigned len = 0, alen; sprintf(abuf, "scope=%d deref=%d", op->ors_scope, op->ors_deref); Statslog( LDAP_DEBUG_STATS, "%s SRCH base=\"%s\" %s filter=\"%s\"\n", op->o_log_prefix, op->o_req_dn.bv_val, abuf, op->ors_filterstr.bv_val, 0 ); for ( i = 0; i<siz; i++ ) { alen = op->ors_attrs[i].an_name.bv_len; if (alen >= sizeof(abuf)) { alen = sizeof(abuf)-1; } if (len && (len + 1 + alen >= sizeof(abuf))) { Statslog( LDAP_DEBUG_STATS, "%s SRCH attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); len = 0; ptr = abuf; } if (len) { *ptr++ = ' '; len++; } ptr = lutil_strncopy(ptr, op->ors_attrs[i].an_name.bv_val, alen); len += alen; *ptr = '\0'; } if (len) { Statslog( LDAP_DEBUG_STATS, "%s SRCH attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); } } op->o_bd = frontendDB; rs->sr_err = frontendDB->be_search( op, rs ); return_results:; if ( !BER_BVISNULL( &op->o_req_dn ) ) { slap_sl_free( op->o_req_dn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &op->o_req_ndn ) ) { slap_sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &op->ors_filterstr ) ) { op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); } if ( op->ors_filter != NULL) { filter_free_x( op, op->ors_filter, 1 ); } if ( op->ors_attrs != NULL ) { op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx ); } return rs->sr_err; }
int passwd_back_search( Operation *op, SlapReply *rs ) { struct passwd *pw; time_t stoptime = (time_t)-1; LDAPRDN rdn = NULL; struct berval parent = BER_BVNULL; AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; if ( op->ors_tlimit != SLAP_NO_LIMIT ) { stoptime = op->o_time + op->ors_tlimit; } /* Handle a query for the base of this backend */ if ( be_issuffix( op->o_bd, &op->o_req_ndn ) ) { struct berval val; rs->sr_matched = op->o_req_dn.bv_val; if( op->ors_scope != LDAP_SCOPE_ONELEVEL ) { AttributeDescription *desc = NULL; char *next; Entry e = { 0 }; /* Create an entry corresponding to the base DN */ e.e_name.bv_val = ch_strdup( op->o_req_dn.bv_val ); e.e_name.bv_len = op->o_req_dn.bv_len; e.e_nname.bv_val = ch_strdup( op->o_req_ndn.bv_val ); e.e_nname.bv_len = op->o_req_ndn.bv_len; /* Use the first attribute of the DN * as an attribute within the entry itself. */ if( ldap_bv2rdn( &op->o_req_dn, &rdn, &next, LDAP_DN_FORMAT_LDAP ) ) { rs->sr_err = LDAP_INVALID_DN_SYNTAX; goto done; } if( slap_bv2ad( &rdn[0]->la_attr, &desc, &rs->sr_text )) { rs->sr_err = LDAP_NO_SUCH_OBJECT; ldap_rdnfree(rdn); goto done; } attr_merge_normalize_one( &e, desc, &rdn[0]->la_value, NULL ); ldap_rdnfree(rdn); rdn = NULL; /* Every entry needs an objectclass. We don't really * know if our hardcoded choice here agrees with the * DN that was configured for this backend, but it's * better than nothing. * * should be a configuratable item */ BER_BVSTR( &val, "organizationalUnit" ); attr_merge_one( &e, ad_objectClass, &val, NULL ); if ( test_filter( op, &e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { rs->sr_entry = &e; rs->sr_attrs = op->ors_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); rs->sr_flags = 0; rs->sr_attrs = NULL; } entry_clean( &e ); } if ( op->ors_scope != LDAP_SCOPE_BASE ) { /* check all our "children" */ ldap_pvt_thread_mutex_lock( &passwd_mutex ); pw_start( op->o_bd ); for ( pw = getpwent(); pw != NULL; pw = getpwent() ) { Entry e = { 0 }; /* check for abandon */ if ( op->o_abandon ) { endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); return( SLAPD_ABANDON ); } /* check time limit */ if ( op->ors_tlimit != SLAP_NO_LIMIT && slap_get_time() > stoptime ) { send_ldap_error( op, rs, LDAP_TIMELIMIT_EXCEEDED, NULL ); endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); return( 0 ); } if ( pw2entry( op->o_bd, pw, &e ) ) { rs->sr_err = LDAP_OTHER; endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); goto done; } if ( test_filter( op, &e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { /* check size limit */ if ( --op->ors_slimit == -1 ) { send_ldap_error( op, rs, LDAP_SIZELIMIT_EXCEEDED, NULL ); endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); return( 0 ); } rs->sr_entry = &e; rs->sr_attrs = op->ors_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); rs->sr_flags = 0; rs->sr_entry = NULL; } entry_clean( &e ); } endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); } } else { char *next; Entry e = { 0 }; int rc; if (! be_issuffix( op->o_bd, &op->o_req_ndn ) ) { dnParent( &op->o_req_ndn, &parent ); } /* This backend is only one layer deep. Don't answer requests for * anything deeper than that. */ if( !be_issuffix( op->o_bd, &parent ) ) { int i; for( i=0; op->o_bd->be_nsuffix[i].bv_val != NULL; i++ ) { if( dnIsSuffix( &op->o_req_ndn, &op->o_bd->be_nsuffix[i] ) ) { rs->sr_matched = op->o_bd->be_suffix[i].bv_val; break; } } rs->sr_err = LDAP_NO_SUCH_OBJECT; goto done; } if( op->ors_scope == LDAP_SCOPE_ONELEVEL ) { goto done; } if ( ldap_bv2rdn( &op->o_req_dn, &rdn, &next, LDAP_DN_FORMAT_LDAP )) { rs->sr_err = LDAP_OTHER; goto done; } ldap_pvt_thread_mutex_lock( &passwd_mutex ); pw_start( op->o_bd ); pw = getpwnam( rdn[0]->la_value.bv_val ); if ( pw == NULL ) { rs->sr_matched = parent.bv_val; rs->sr_err = LDAP_NO_SUCH_OBJECT; ldap_pvt_thread_mutex_unlock( &passwd_mutex ); goto done; } rc = pw2entry( op->o_bd, pw, &e ); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); if ( rc ) { rs->sr_err = LDAP_OTHER; goto done; } if ( test_filter( op, &e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { rs->sr_entry = &e; rs->sr_attrs = op->ors_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); rs->sr_flags = 0; rs->sr_entry = NULL; rs->sr_attrs = NULL; } entry_clean( &e ); } done: if( rs->sr_err != LDAP_NO_SUCH_OBJECT ) rs->sr_matched = NULL; send_ldap_result( op, rs ); if( rdn != NULL ) ldap_rdnfree( rdn ); return( 0 ); }
/* * Do basic attribute type checking and syntax validation. */ int slap_mods_check( Operation *op, Modifications *ml, const char **text, char *textbuf, size_t textlen, void *ctx ) { int rc; for( ; ml != NULL; ml = ml->sml_next ) { AttributeDescription *ad = NULL; /* convert to attribute description */ if ( ml->sml_desc == NULL ) { rc = slap_bv2ad( &ml->sml_type, &ml->sml_desc, text ); if( rc != LDAP_SUCCESS ) { if ( get_no_schema_check( op )) { rc = slap_bv2undef_ad( &ml->sml_type, &ml->sml_desc, text, 0 ); } } if( rc != LDAP_SUCCESS ) { snprintf( textbuf, textlen, "%s: %s", ml->sml_type.bv_val, *text ); *text = textbuf; return rc; } } ad = ml->sml_desc; if( slap_syntax_is_binary( ad->ad_type->sat_syntax ) && !slap_ad_is_binary( ad )) { /* attribute requires binary transfer */ snprintf( textbuf, textlen, "%s: requires ;binary transfer", ml->sml_type.bv_val ); *text = textbuf; return LDAP_UNDEFINED_TYPE; } if( !slap_syntax_is_binary( ad->ad_type->sat_syntax ) && slap_ad_is_binary( ad )) { /* attribute does not require binary transfer */ snprintf( textbuf, textlen, "%s: disallows ;binary transfer", ml->sml_type.bv_val ); *text = textbuf; return LDAP_UNDEFINED_TYPE; } if( slap_ad_is_tag_range( ad )) { /* attribute requires binary transfer */ snprintf( textbuf, textlen, "%s: inappropriate use of tag range option", ml->sml_type.bv_val ); *text = textbuf; return LDAP_UNDEFINED_TYPE; } #if 0 if ( is_at_obsolete( ad->ad_type ) && (( ml->sml_op != LDAP_MOD_REPLACE && ml->sml_op != LDAP_MOD_DELETE ) || ml->sml_values != NULL )) { /* * attribute is obsolete, * only allow replace/delete with no values */ snprintf( textbuf, textlen, "%s: attribute is obsolete", ml->sml_type.bv_val ); *text = textbuf; return LDAP_CONSTRAINT_VIOLATION; } #endif if ( ml->sml_op == LDAP_MOD_INCREMENT && #ifdef SLAPD_REAL_SYNTAX !is_at_syntax( ad->ad_type, SLAPD_REAL_SYNTAX ) && #endif !is_at_syntax( ad->ad_type, SLAPD_INTEGER_SYNTAX ) ) { /* * attribute values must be INTEGER or REAL */ snprintf( textbuf, textlen, "%s: attribute syntax inappropriate for increment", ml->sml_type.bv_val ); *text = textbuf; return LDAP_CONSTRAINT_VIOLATION; } /* * check values */ if( ml->sml_values != NULL ) { ber_len_t nvals; slap_syntax_validate_func *validate = ad->ad_type->sat_syntax->ssyn_validate; slap_syntax_transform_func *pretty = ad->ad_type->sat_syntax->ssyn_pretty; if( !pretty && !validate ) { *text = "no validator for syntax"; snprintf( textbuf, textlen, "%s: no validator for syntax %s", ml->sml_type.bv_val, ad->ad_type->sat_syntax->ssyn_oid ); *text = textbuf; return LDAP_INVALID_SYNTAX; } /* * check that each value is valid per syntax * and pretty if appropriate */ for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) { struct berval pval; if ( pretty ) { rc = ordered_value_pretty( ad, &ml->sml_values[nvals], &pval, ctx ); } else { rc = ordered_value_validate( ad, &ml->sml_values[nvals], ml->sml_op ); } if( rc != 0 ) { snprintf( textbuf, textlen, "%s: value #%ld invalid per syntax", ml->sml_type.bv_val, (long) nvals ); *text = textbuf; return LDAP_INVALID_SYNTAX; } if( pretty ) { ber_memfree_x( ml->sml_values[nvals].bv_val, ctx ); ml->sml_values[nvals] = pval; } } ml->sml_values[nvals].bv_len = 0; ml->sml_numvals = nvals; /* * a rough single value check... an additional check is needed * to catch add of single value to existing single valued attribute */ if ((ml->sml_op == LDAP_MOD_ADD || ml->sml_op == LDAP_MOD_REPLACE) && nvals > 1 && is_at_single_value( ad->ad_type )) { snprintf( textbuf, textlen, "%s: multiple values provided", ml->sml_type.bv_val ); *text = textbuf; return LDAP_CONSTRAINT_VIOLATION; } /* if the type has a normalizer, generate the * normalized values. otherwise leave them NULL. * * this is different from the rule for attributes * in an entry - in an attribute list, the normalized * value is set equal to the non-normalized value * when there is no normalizer. */ if( nvals && ad->ad_type->sat_equality && ad->ad_type->sat_equality->smr_normalize ) { ml->sml_nvalues = ber_memalloc_x( (nvals+1)*sizeof(struct berval), ctx ); for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) { rc = ordered_value_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, ad, ad->ad_type->sat_equality, &ml->sml_values[nvals], &ml->sml_nvalues[nvals], ctx ); if ( rc ) { Debug( LDAP_DEBUG_ANY, "<= str2entry NULL (ssyn_normalize %d)\n", rc, 0, 0 ); snprintf( textbuf, textlen, "%s: value #%ld normalization failed", ml->sml_type.bv_val, (long) nvals ); *text = textbuf; BER_BVZERO( &ml->sml_nvalues[nvals] ); return rc; } } BER_BVZERO( &ml->sml_nvalues[nvals] ); } /* check for duplicates, but ignore Deletes. */ if( nvals > 1 && ml->sml_op != LDAP_MOD_DELETE ) { int i; rc = slap_sort_vals( ml, text, &i, ctx ); if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { /* value exists already */ snprintf( textbuf, textlen, "%s: value #%d provided more than once", ml->sml_desc->ad_cname.bv_val, i ); *text = textbuf; } if ( rc ) return rc; } } else { ml->sml_numvals = 0; } } return LDAP_SUCCESS; }
static int LDAPRDN_rewrite( LDAPRDN rdn, unsigned flags, void *ctx ) { int rc, iAVA, do_sort = 0; for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; AttributeDescription *ad; slap_syntax_validate_func *validf = NULL; slap_mr_normalize_func *normf = NULL; slap_syntax_transform_func *transf = NULL; MatchingRule *mr = NULL; struct berval bv = BER_BVNULL; assert( ava != NULL ); if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) { const char *text = NULL; rc = slap_bv2ad( &ava->la_attr, &ad, &text ); if ( rc != LDAP_SUCCESS ) { rc = slap_bv2undef_ad( &ava->la_attr, &ad, &text, SLAP_AD_PROXIED|slap_DN_strict ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } ava->la_private = ( void * )ad; do_sort = 1; } /* * Replace attr oid/name with the canonical name */ ava->la_attr = ad->ad_cname; if( ava->la_flags & LDAP_AVA_BINARY ) { /* AVA is binary encoded, not supported */ return LDAP_INVALID_SYNTAX; /* Do not allow X-ORDERED 'VALUES' naming attributes */ } else if( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) { return LDAP_INVALID_SYNTAX; } else if( flags & SLAP_LDAPDN_PRETTY ) { transf = ad->ad_type->sat_syntax->ssyn_pretty; if( !transf ) { validf = ad->ad_type->sat_syntax->ssyn_validate; } } else { /* normalization */ validf = ad->ad_type->sat_syntax->ssyn_validate; mr = ad->ad_type->sat_equality; if( mr && (!( mr->smr_usage & SLAP_MR_MUTATION_NORMALIZER ))) { normf = mr->smr_normalize; } } if ( validf ) { /* validate value before normalization */ rc = ( *validf )( ad->ad_type->sat_syntax, ava->la_value.bv_len ? &ava->la_value : (struct berval *) &slap_empty_bv ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } if ( transf ) { /* * transform value by pretty function * if value is empty, use empty_bv */ rc = ( *transf )( ad->ad_type->sat_syntax, ava->la_value.bv_len ? &ava->la_value : (struct berval *) &slap_empty_bv, &bv, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } if ( normf ) { /* * normalize value * if value is empty, use empty_bv */ rc = ( *normf )( SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, ad->ad_type->sat_syntax, mr, ava->la_value.bv_len ? &ava->la_value : (struct berval *) &slap_empty_bv, &bv, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } if( bv.bv_val ) { if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) ber_memfree_x( ava->la_value.bv_val, ctx ); ava->la_value = bv; ava->la_flags |= LDAP_AVA_FREE_VALUE; } /* reject empty values */ if (!ava->la_value.bv_len) { return LDAP_INVALID_SYNTAX; } } rc = LDAP_SUCCESS; if ( do_sort ) { rc = AVA_Sort( rdn, iAVA ); } return rc; }
int schema_info( Entry **entry, const char **text ) { AttributeDescription *ad_structuralObjectClass = slap_schema.si_ad_structuralObjectClass; AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; AttributeDescription *ad_createTimestamp = slap_schema.si_ad_createTimestamp; AttributeDescription *ad_modifyTimestamp = slap_schema.si_ad_modifyTimestamp; Entry *e; struct berval vals[5]; struct berval nvals[5]; e = entry_alloc(); if( e == NULL ) { /* Out of memory, do something about it */ Debug( LDAP_DEBUG_ANY, "schema_info: entry_alloc failed - out of memory.\n", 0, 0, 0 ); *text = "out of memory"; return LDAP_OTHER; } e->e_attrs = NULL; /* backend-specific schema info should be created by the * backend itself */ ber_dupbv( &e->e_name, &frontendDB->be_schemadn ); ber_dupbv( &e->e_nname, &frontendDB->be_schemandn ); e->e_private = NULL; BER_BVSTR( &vals[0], "subentry" ); if( attr_merge_one( e, ad_structuralObjectClass, vals, NULL ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } BER_BVSTR( &vals[0], "top" ); BER_BVSTR( &vals[1], "subentry" ); BER_BVSTR( &vals[2], "subschema" ); BER_BVSTR( &vals[3], "extensibleObject" ); BER_BVZERO( &vals[4] ); if ( attr_merge( e, ad_objectClass, vals, NULL ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } { int rc; AttributeDescription *desc = NULL; struct berval rdn = frontendDB->be_schemadn; vals[0].bv_val = ber_bvchr( &rdn, '=' ); if( vals[0].bv_val == NULL ) { *text = "improperly configured subschema subentry"; return LDAP_OTHER; } vals[0].bv_val++; vals[0].bv_len = rdn.bv_len - (vals[0].bv_val - rdn.bv_val); rdn.bv_len -= vals[0].bv_len + 1; rc = slap_bv2ad( &rdn, &desc, text ); if( rc != LDAP_SUCCESS ) { entry_free( e ); *text = "improperly configured subschema subentry"; return LDAP_OTHER; } nvals[0].bv_val = ber_bvchr( &frontendDB->be_schemandn, '=' ); assert( nvals[0].bv_val != NULL ); nvals[0].bv_val++; nvals[0].bv_len = frontendDB->be_schemandn.bv_len - (nvals[0].bv_val - frontendDB->be_schemandn.bv_val); if ( attr_merge_one( e, desc, vals, nvals ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } } { char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; /* * According to RFC 4512: Servers SHOULD maintain the 'creatorsName', 'createTimestamp', 'modifiersName', and 'modifyTimestamp' attributes for all entries of the DIT. * to be conservative, we declare schema created * AND modified at server startup time ... */ vals[0].bv_val = timebuf; vals[0].bv_len = sizeof( timebuf ); slap_timestamp( &starttime, vals ); if( attr_merge_one( e, ad_createTimestamp, vals, NULL ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } if( attr_merge_one( e, ad_modifyTimestamp, vals, NULL ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } } if ( syn_schema_info( e ) || mr_schema_info( e ) || mru_schema_info( e ) || at_schema_info( e ) || oc_schema_info( e ) || cr_schema_info( e ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } *entry = e; return LDAP_SUCCESS; }
int limits_parse( Backend *be, const char *fname, int lineno, int argc, char **argv ) { int flags = SLAP_LIMITS_UNDEFINED; char *pattern; struct slap_limits_set limit; int i, rc = 0; ObjectClass *group_oc = NULL; AttributeDescription *group_ad = NULL; assert( be != NULL ); if ( argc < 3 ) { Debug( LDAP_DEBUG_ANY, "%s : line %d: missing arg(s) in " "\"limits <pattern> <limits>\" line.\n%s", fname, lineno, "" ); return( -1 ); } limit = be->be_def_limit; /* * syntax: * * "limits" <pattern> <limit> [ ... ] * * * <pattern>: * * "anonymous" * "users" * [ "dn" [ "." { "this" | "self" } ] [ "." { "exact" | "base" | * "onelevel" | "subtree" | "children" | "regex" | "anonymous" } ] * "=" ] <dn pattern> * * Note: * "this" is the baseobject, "self" (the default) is the bound DN * "exact" and "base" are the same (exact match); * "onelevel" means exactly one rdn below, NOT including pattern * "subtree" means any rdn below, including pattern * "children" means any rdn below, NOT including pattern * * "anonymous" may be deprecated in favour * of the pattern = "anonymous" form * * "group[/objectClass[/attributeType]]" "=" "<dn pattern>" * * <limit>: * * "time" [ "." { "soft" | "hard" } ] "=" <integer> * * "size" [ "." { "soft" | "hard" | "unchecked" } ] "=" <integer> */ pattern = argv[1]; if ( strcmp( pattern, "*" ) == 0) { flags = SLAP_LIMITS_ANY; } else if ( strcasecmp( pattern, "anonymous" ) == 0 ) { flags = SLAP_LIMITS_ANONYMOUS; } else if ( strcasecmp( pattern, "users" ) == 0 ) { flags = SLAP_LIMITS_USERS; } else if ( STRSTART( pattern, "dn" ) ) { pattern += STRLENOF( "dn" ); flags = SLAP_LIMITS_TYPE_SELF; if ( pattern[0] == '.' ) { pattern++; if ( STRSTART( pattern, "this" ) ) { flags = SLAP_LIMITS_TYPE_THIS; pattern += STRLENOF( "this" ); } else if ( STRSTART( pattern, "self" ) ) { pattern += STRLENOF( "self" ); } else { goto got_dn_dot; } } if ( pattern[0] == '.' ) { pattern++; got_dn_dot: if ( STRSTART( pattern, "exact" ) ) { flags |= SLAP_LIMITS_EXACT; pattern += STRLENOF( "exact" ); } else if ( STRSTART( pattern, "base" ) ) { flags |= SLAP_LIMITS_BASE; pattern += STRLENOF( "base" ); } else if ( STRSTART( pattern, "one" ) ) { flags |= SLAP_LIMITS_ONE; pattern += STRLENOF( "one" ); if ( STRSTART( pattern, "level" ) ) { pattern += STRLENOF( "level" ); } else { Debug( LDAP_DEBUG_ANY, "%s : line %d: deprecated \"one\" style " "\"limits <pattern> <limits>\" line; " "use \"onelevel\" instead.\n", fname, lineno, 0 ); } } else if ( STRSTART( pattern, "sub" ) ) { flags |= SLAP_LIMITS_SUBTREE; pattern += STRLENOF( "sub" ); if ( STRSTART( pattern, "tree" ) ) { pattern += STRLENOF( "tree" ); } else { Debug( LDAP_DEBUG_ANY, "%s : line %d: deprecated \"sub\" style " "\"limits <pattern> <limits>\" line; " "use \"subtree\" instead.\n", fname, lineno, 0 ); } } else if ( STRSTART( pattern, "children" ) ) { flags |= SLAP_LIMITS_CHILDREN; pattern += STRLENOF( "children" ); } else if ( STRSTART( pattern, "regex" ) ) { flags |= SLAP_LIMITS_REGEX; pattern += STRLENOF( "regex" ); /* * this could be deprecated in favour * of the pattern = "anonymous" form */ } else if ( STRSTART( pattern, "anonymous" ) && flags == SLAP_LIMITS_TYPE_SELF ) { flags = SLAP_LIMITS_ANONYMOUS; pattern = NULL; } else { /* force error below */ if ( *pattern == '=' ) --pattern; } } /* pre-check the data */ if ( pattern != NULL ) { if ( pattern[0] != '=' ) { Debug( LDAP_DEBUG_ANY, "%s : line %d: %s in " "\"dn[.{this|self}][.{exact|base" "|onelevel|subtree|children|regex" "|anonymous}]=<pattern>\" in " "\"limits <pattern> <limits>\" line.\n", fname, lineno, isalnum( (unsigned char)pattern[0] ) ? "unknown DN modifier" : "missing '='" ); return( -1 ); } /* skip '=' (required) */ pattern++; /* trim obvious cases */ if ( strcmp( pattern, "*" ) == 0 ) { flags = SLAP_LIMITS_ANY; pattern = NULL; } else if ( (flags & SLAP_LIMITS_MASK) == SLAP_LIMITS_REGEX && strcmp( pattern, ".*" ) == 0 ) { flags = SLAP_LIMITS_ANY; pattern = NULL; } } } else if (STRSTART( pattern, "group" ) ) { pattern += STRLENOF( "group" ); if ( pattern[0] == '/' ) { struct berval oc, ad; oc.bv_val = pattern + 1; pattern = strchr( pattern, '=' ); if ( pattern == NULL ) { return -1; } ad.bv_val = strchr( oc.bv_val, '/' ); if ( ad.bv_val != NULL ) { const char *text = NULL; oc.bv_len = ad.bv_val - oc.bv_val; ad.bv_val++; ad.bv_len = pattern - ad.bv_val; rc = slap_bv2ad( &ad, &group_ad, &text ); if ( rc != LDAP_SUCCESS ) { goto no_ad; } } else { oc.bv_len = pattern - oc.bv_val; } group_oc = oc_bvfind( &oc ); if ( group_oc == NULL ) { goto no_oc; } } if ( group_oc == NULL ) { group_oc = oc_find( SLAPD_GROUP_CLASS ); if ( group_oc == NULL ) { no_oc:; return( -1 ); } } if ( group_ad == NULL ) { const char *text = NULL; rc = slap_str2ad( SLAPD_GROUP_ATTR, &group_ad, &text ); if ( rc != LDAP_SUCCESS ) { no_ad:; return( -1 ); } } flags = SLAP_LIMITS_TYPE_GROUP | SLAP_LIMITS_EXACT; if ( pattern[0] != '=' ) { Debug( LDAP_DEBUG_ANY, "%s : line %d: missing '=' in " "\"group[/objectClass[/attributeType]]" "=<pattern>\" in " "\"limits <pattern> <limits>\" line.\n", fname, lineno, 0 ); return( -1 ); } /* skip '=' (required) */ pattern++; } /* get the limits */ for ( i = 2; i < argc; i++ ) { if ( limits_parse_one( argv[i], &limit ) ) { Debug( LDAP_DEBUG_ANY, "%s : line %d: unknown limit values \"%s\" in " "\"limits <pattern> <limits>\" line.\n", fname, lineno, argv[i] ); return( 1 ); } } /* * sanity checks ... * * FIXME: add warnings? */ if ( limit.lms_t_hard > 0 && ( limit.lms_t_hard < limit.lms_t_soft || limit.lms_t_soft == -1 ) ) { limit.lms_t_hard = limit.lms_t_soft; } if ( limit.lms_s_hard > 0 && ( limit.lms_s_hard < limit.lms_s_soft || limit.lms_s_soft == -1 ) ) { limit.lms_s_hard = limit.lms_s_soft; } /* * defaults ... * * lms_t_hard: * -1 => no limits * 0 => same as soft * > 0 => limit (in seconds) * * lms_s_hard: * -1 => no limits * 0 0> same as soft * > 0 => limit (in entries) * * lms_s_pr_total: * -2 => disable the control * -1 => no limits * 0 => same as soft * > 0 => limit (in entries) * * lms_s_pr: * -1 => no limits * 0 => no limits? * > 0 => limit size (in entries) */ if ( limit.lms_s_pr_total > 0 && limit.lms_s_pr > limit.lms_s_pr_total ) { limit.lms_s_pr = limit.lms_s_pr_total; } rc = limits_add( be, flags, pattern, group_oc, group_ad, &limit ); if ( rc ) { Debug( LDAP_DEBUG_ANY, "%s : line %d: unable to add limit in " "\"limits <pattern> <limits>\" line.\n", fname, lineno, 0 ); } return( rc ); }
static int retcode_db_open( BackendDB *be, ConfigReply *cr) { slap_overinst *on = (slap_overinst *)be->bd_info; retcode_t *rd = (retcode_t *)on->on_bi.bi_private; retcode_item_t *rdi; for ( rdi = rd->rd_item; rdi; rdi = rdi->rdi_next ) { LDAPRDN rdn = NULL; int rc, j; char* p; struct berval val[ 3 ]; char buf[ SLAP_TEXT_BUFLEN ]; /* DN */ rdi->rdi_e.e_name = rdi->rdi_dn; rdi->rdi_e.e_nname = rdi->rdi_ndn; /* objectClass */ val[ 0 ] = oc_errObject->soc_cname; val[ 1 ] = slap_schema.si_oc_extensibleObject->soc_cname; BER_BVZERO( &val[ 2 ] ); attr_merge( &rdi->rdi_e, slap_schema.si_ad_objectClass, val, NULL ); /* RDN avas */ rc = ldap_bv2rdn( &rdi->rdi_dn, &rdn, (char **) &p, LDAP_DN_FORMAT_LDAP ); assert( rc == LDAP_SUCCESS ); for ( j = 0; rdn[ j ]; j++ ) { LDAPAVA *ava = rdn[ j ]; AttributeDescription *ad = NULL; const char *text; rc = slap_bv2ad( &ava->la_attr, &ad, &text ); assert( rc == LDAP_SUCCESS ); attr_merge_normalize_one( &rdi->rdi_e, ad, &ava->la_value, NULL ); } ldap_rdnfree( rdn ); /* error code */ snprintf( buf, sizeof( buf ), "%d", rdi->rdi_err ); ber_str2bv( buf, 0, 0, &val[ 0 ] ); attr_merge_one( &rdi->rdi_e, ad_errCode, &val[ 0 ], NULL ); if ( rdi->rdi_ref != NULL ) { attr_merge_normalize( &rdi->rdi_e, slap_schema.si_ad_ref, rdi->rdi_ref, NULL ); } /* text */ if ( !BER_BVISNULL( &rdi->rdi_text ) ) { val[ 0 ] = rdi->rdi_text; attr_merge_normalize_one( &rdi->rdi_e, ad_errText, &val[ 0 ], NULL ); } /* matched */ if ( !BER_BVISNULL( &rdi->rdi_matched ) ) { val[ 0 ] = rdi->rdi_matched; attr_merge_normalize_one( &rdi->rdi_e, ad_errMatchedDN, &val[ 0 ], NULL ); } /* sleep time */ if ( rdi->rdi_sleeptime ) { snprintf( buf, sizeof( buf ), "%d", rdi->rdi_sleeptime ); ber_str2bv( buf, 0, 0, &val[ 0 ] ); attr_merge_one( &rdi->rdi_e, ad_errSleepTime, &val[ 0 ], NULL ); } /* operations */ if ( rdi->rdi_mask & SN_DG_OP_ADD ) { BER_BVSTR( &val[ 0 ], "add" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_OP_BIND ) { BER_BVSTR( &val[ 0 ], "bind" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_OP_COMPARE ) { BER_BVSTR( &val[ 0 ], "compare" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_OP_DELETE ) { BER_BVSTR( &val[ 0 ], "delete" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_EXTENDED ) { BER_BVSTR( &val[ 0 ], "extended" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_OP_MODIFY ) { BER_BVSTR( &val[ 0 ], "modify" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_OP_RENAME ) { BER_BVSTR( &val[ 0 ], "rename" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_OP_SEARCH ) { BER_BVSTR( &val[ 0 ], "search" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } } return 0; }
static int asyncmeta_send_entry( Operation *op, SlapReply *rs, a_metaconn_t *mc, int target, LDAPMessage *e ) { a_metainfo_t *mi = mc->mc_info; struct berval a, mapped = BER_BVNULL; int check_sorted_attrs = 0; Entry ent = {0}; BerElement ber = *ldap_get_message_ber( e ); Attribute *attr, **attrp; struct berval bdn, dn = BER_BVNULL; const char *text; a_dncookie dc; ber_len_t len; int rc; void *mem_mark; mem_mark = slap_sl_mark( op->o_tmpmemctx ); ber_set_option( &ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); if ( ber_scanf( &ber, "l{", &len ) == LBER_ERROR ) { return LDAP_DECODING_ERROR; } if ( ber_set_option( &ber, LBER_OPT_REMAINING_BYTES, &len ) != LBER_OPT_SUCCESS ) { return LDAP_OTHER; } if ( ber_scanf( &ber, "m{", &bdn ) == LBER_ERROR ) { return LDAP_DECODING_ERROR; } /* * Rewrite the dn of the result, if needed */ dc.op = op; dc.target = mi->mi_targets[ target ]; dc.memctx = op->o_tmpmemctx; dc.to_from = MASSAGE_REP; asyncmeta_dn_massage( &dc, &bdn, &dn ); /* * Note: this may fail if the target host(s) schema differs * from the one known to the meta, and a DN with unknown * attributes is returned. * * FIXME: should we log anything, or delegate to dnNormalize? */ rc = dnPrettyNormal( NULL, &dn, &ent.e_name, &ent.e_nname, op->o_tmpmemctx ); if ( dn.bv_val != bdn.bv_val ) { op->o_tmpfree( dn.bv_val, op->o_tmpmemctx ); } BER_BVZERO( &dn ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s asyncmeta_send_entry(\"%s\"): " "invalid DN syntax\n", op->o_log_prefix, ent.e_name.bv_val ); rc = LDAP_INVALID_DN_SYNTAX; goto done; } /* * cache dn */ if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) { ( void )asyncmeta_dncache_update_entry( &mi->mi_cache, &ent.e_nname, target ); } attrp = &ent.e_attrs; while ( ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) { int last = 0; slap_syntax_validate_func *validate; slap_syntax_transform_func *pretty; if ( ber_pvt_ber_remaining( &ber ) < 0 ) { Debug( LDAP_DEBUG_ANY, "%s asyncmeta_send_entry(\"%s\"): " "unable to parse attr \"%s\".\n", op->o_log_prefix, ent.e_name.bv_val, a.bv_val ); rc = LDAP_OTHER; goto done; } if ( ber_pvt_ber_remaining( &ber ) == 0 ) { break; } attr = op->o_tmpcalloc( 1, sizeof(Attribute), op->o_tmpmemctx ); if ( slap_bv2ad( &a, &attr->a_desc, &text ) != LDAP_SUCCESS) { if ( slap_bv2undef_ad( &a, &attr->a_desc, &text, SLAP_AD_PROXIED ) != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_ANY, "%s meta_send_entry(\"%s\"): " "slap_bv2undef_ad(%s): %s\n", op->o_log_prefix, ent.e_name.bv_val, mapped.bv_val, text ); ( void )ber_scanf( &ber, "x" /* [W] */ ); op->o_tmpfree( attr, op->o_tmpmemctx ); continue; } } if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) check_sorted_attrs = 1; /* no subschemaSubentry */ if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry || attr->a_desc == slap_schema.si_ad_entryDN ) { /* * We eat target's subschemaSubentry because * a search for this value is likely not * to resolve to the appropriate backend; * later, the local subschemaSubentry is * added. * * We also eat entryDN because the frontend * will reattach it without checking if already * present... */ ( void )ber_scanf( &ber, "x" /* [W] */ ); op->o_tmpfree( attr, op->o_tmpmemctx ); continue; } if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR || attr->a_vals == NULL ) { attr->a_vals = (struct berval *)&slap_dummy_bv; } else { for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); ++last ) ; } attr->a_numvals = last; validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate; pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty; if ( !validate && !pretty ) { ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx ); op->o_tmpfree( attr, op->o_tmpmemctx ); goto next_attr; } /* * It is necessary to try to rewrite attributes with * dn syntax because they might be used in ACLs as * members of groups; since ACLs are applied to the * rewritten stuff, no dn-based subecj clause could * be used at the ldap backend side (see * http://www.OpenLDAP.org/faq/data/cache/452.html) * The problem can be overcome by moving the dn-based * ACLs to the target directory server, and letting * everything pass thru the ldap backend. */ { int i; if ( attr->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) { asyncmeta_dnattr_result_rewrite( &dc, attr->a_vals ); } else if ( attr->a_desc == slap_schema.si_ad_ref ) { asyncmeta_referral_result_rewrite( &dc, attr->a_vals ); } for ( i = 0; i < last; i++ ) { struct berval pval; int rc; if ( pretty ) { rc = ordered_value_pretty( attr->a_desc, &attr->a_vals[i], &pval, op->o_tmpmemctx ); } else { rc = ordered_value_validate( attr->a_desc, &attr->a_vals[i], 0 ); } if ( rc ) { ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx ); if ( --last == i ) { BER_BVZERO( &attr->a_vals[ i ] ); break; } attr->a_vals[i] = attr->a_vals[last]; BER_BVZERO( &attr->a_vals[last] ); i--; continue; } if ( pretty ) { ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx ); attr->a_vals[i] = pval; } } if ( last == 0 && attr->a_vals != &slap_dummy_bv ) { ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx ); op->o_tmpfree( attr, op->o_tmpmemctx ); goto next_attr; } } if ( last && attr->a_desc->ad_type->sat_equality && attr->a_desc->ad_type->sat_equality->smr_normalize ) { int i; attr->a_nvals = op->o_tmpalloc( ( last + 1 ) * sizeof( struct berval ), op->o_tmpmemctx ); for ( i = 0; i<last; i++ ) { /* if normalizer fails, drop this value */ if ( ordered_value_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, attr->a_desc, attr->a_desc->ad_type->sat_equality, &attr->a_vals[i], &attr->a_nvals[i], op->o_tmpmemctx )) { ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx ); if ( --last == i ) { BER_BVZERO( &attr->a_vals[ i ] ); break; } attr->a_vals[i] = attr->a_vals[last]; BER_BVZERO( &attr->a_vals[last] ); i--; } } BER_BVZERO( &attr->a_nvals[i] ); if ( last == 0 ) { ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx ); ber_bvarray_free_x( attr->a_nvals, op->o_tmpmemctx ); op->o_tmpfree( attr, op->o_tmpmemctx ); goto next_attr; } } else { attr->a_nvals = attr->a_vals; } attr->a_numvals = last; *attrp = attr; attrp = &attr->a_next; next_attr:; } /* Check for sorted attributes */ if ( check_sorted_attrs ) { for ( attr = ent.e_attrs; attr; attr = attr->a_next ) { if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { while ( attr->a_numvals > 1 ) { int i; int rc = slap_sort_vals( (Modifications *)attr, &text, &i, op->o_tmpmemctx ); if ( rc != LDAP_TYPE_OR_VALUE_EXISTS ) break; /* Strip duplicate values */ if ( attr->a_nvals != attr->a_vals ) ber_memfree_x( attr->a_nvals[i].bv_val, op->o_tmpmemctx ); ber_memfree_x( attr->a_vals[i].bv_val, op->o_tmpmemctx ); attr->a_numvals--; if ( (unsigned)i < attr->a_numvals ) { attr->a_vals[i] = attr->a_vals[attr->a_numvals]; if ( attr->a_nvals != attr->a_vals ) attr->a_nvals[i] = attr->a_nvals[attr->a_numvals]; } BER_BVZERO(&attr->a_vals[attr->a_numvals]); if ( attr->a_nvals != attr->a_vals ) BER_BVZERO(&attr->a_nvals[attr->a_numvals]); } attr->a_flags |= SLAP_ATTR_SORTED_VALS; } } } Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_send_entry(\"%s\"): " ".\n", op->o_log_prefix, ent.e_name.bv_val ); ldap_get_entry_controls( mc->mc_conns[target].msc_ldr, e, &rs->sr_ctrls ); rs->sr_entry = &ent; rs->sr_attrs = op->ors_attrs; rs->sr_operational_attrs = NULL; rs->sr_flags = mi->mi_targets[ target ]->mt_rep_flags; rs->sr_err = LDAP_SUCCESS; rc = send_search_entry( op, rs ); switch ( rc ) { case LDAP_UNAVAILABLE: rc = LDAP_OTHER; break; } done:; if ( rs->sr_ctrls != NULL ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } #if 0 while ( ent.e_attrs ) { attr = ent.e_attrs; ent.e_attrs = attr->a_next; if ( attr->a_nvals != attr->a_vals ) ber_bvarray_free_x( attr->a_nvals, op->o_tmpmemctx ); ber_bvarray_free_x( attr->a_vals, op->o_tmpmemctx ); op->o_tmpfree( attr, op->o_tmpmemctx ); } if (ent.e_name.bv_val != NULL) { op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx ); } if (ent.e_nname.bv_val != NULL) { op->o_tmpfree( ent.e_nname.bv_val, op->o_tmpmemctx ); } if (rs->sr_entry && rs->sr_entry != &ent) { entry_free( rs->sr_entry ); } #endif slap_sl_release( mem_mark, op->o_tmpmemctx ); rs->sr_entry = NULL; rs->sr_attrs = NULL; return rc; }
static int OpenLDAPaciValidateRight( struct berval *action ) { struct berval bv = BER_BVNULL; int i; /* grant|deny */ if ( acl_get_part( action, 0, ';', &bv ) < 0 || bv_getcaseidx( &bv, ACIgrantdeny ) == -1 ) { Debug( LDAP_DEBUG_ACL, "aciValidateRight: '%s' must be either 'grant' or 'deny'\n", bv.bv_val ); return LDAP_INVALID_SYNTAX; } for ( i = 0; acl_get_part( action, i + 1, ';', &bv ) >= 0; i++ ) { if ( i & 1 ) { /* perms */ if ( OpenLDAPaciValidatePerms( &bv ) != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } else { /* attr */ AttributeDescription *ad; const char *text; struct berval attr, left, right; int j; /* could be "[all]" or an attribute description */ if ( ber_bvstrcasecmp( &bv, &aci_bv[ ACI_BV_BR_ALL ] ) == 0 ) { continue; } for ( j = 0; acl_get_part( &bv, j, ',', &attr ) >= 0; j++ ) { ad = NULL; text = NULL; if ( acl_get_part( &attr, 0, '=', &left ) < 0 || acl_get_part( &attr, 1, '=', &right ) < 0 ) { if ( slap_bv2ad( &attr, &ad, &text ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciValidateRight: unknown attribute: '%s'\n", attr.bv_val ); return LDAP_INVALID_SYNTAX; } } else { if ( slap_bv2ad( &left, &ad, &text ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciValidateRight: unknown attribute: '%s'\n", left.bv_val ); return LDAP_INVALID_SYNTAX; } } } } } /* "perms;attr" go in pairs */ if ( i > 0 && ( i & 1 ) == 0 ) { return LDAP_SUCCESS; } else { Debug( LDAP_DEBUG_ACL, "aciValidateRight: perms:attr need to be pairs in '%s'\n", action->bv_val ); return LDAP_INVALID_SYNTAX; } return LDAP_SUCCESS; }
int get_filter( Operation *op, BerElement *ber, Filter **filt, const char **text ) { ber_tag_t tag; ber_len_t len; int err; Filter f; Debug( LDAP_DEBUG_FILTER, "begin get_filter\n", 0, 0, 0 ); /* * A filter looks like this coming in: * Filter ::= CHOICE { * and [0] SET OF Filter, * or [1] SET OF Filter, * not [2] Filter, * equalityMatch [3] AttributeValueAssertion, * substrings [4] SubstringFilter, * greaterOrEqual [5] AttributeValueAssertion, * lessOrEqual [6] AttributeValueAssertion, * present [7] AttributeType, * approxMatch [8] AttributeValueAssertion, * extensibleMatch [9] MatchingRuleAssertion * } * * SubstringFilter ::= SEQUENCE { * type AttributeType, * SEQUENCE OF CHOICE { * initial [0] IA5String, * any [1] IA5String, * final [2] IA5String * } * } * * MatchingRuleAssertion ::= SEQUENCE { * matchingRule [1] MatchingRuleId OPTIONAL, * type [2] AttributeDescription OPTIONAL, * matchValue [3] AssertionValue, * dnAttributes [4] BOOLEAN DEFAULT FALSE * } * */ tag = ber_peek_tag( ber, &len ); if( tag == LBER_ERROR ) { *text = "error decoding filter"; return SLAPD_DISCONNECT; } err = LDAP_SUCCESS; f.f_next = NULL; f.f_choice = tag; switch ( f.f_choice ) { case LDAP_FILTER_EQUALITY: Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 ); err = get_ava( op, ber, &f, SLAP_MR_EQUALITY, text ); if ( err != LDAP_SUCCESS ) { break; } assert( f.f_ava != NULL ); break; case LDAP_FILTER_SUBSTRINGS: Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 ); err = get_ssa( op, ber, &f, text ); if( err != LDAP_SUCCESS ) { break; } assert( f.f_sub != NULL ); break; case LDAP_FILTER_GE: Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 ); err = get_ava( op, ber, &f, SLAP_MR_ORDERING, text ); if ( err != LDAP_SUCCESS ) { break; } assert( f.f_ava != NULL ); break; case LDAP_FILTER_LE: Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 ); err = get_ava( op, ber, &f, SLAP_MR_ORDERING, text ); if ( err != LDAP_SUCCESS ) { break; } assert( f.f_ava != NULL ); break; case LDAP_FILTER_PRESENT: { struct berval type; Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 ); if ( ber_scanf( ber, "m", &type ) == LBER_ERROR ) { err = SLAPD_DISCONNECT; *text = "error decoding filter"; break; } f.f_desc = NULL; err = slap_bv2ad( &type, &f.f_desc, text ); if( err != LDAP_SUCCESS ) { f.f_choice |= SLAPD_FILTER_UNDEFINED; err = slap_bv2undef_ad( &type, &f.f_desc, text, SLAP_AD_PROXIED|SLAP_AD_NOINSERT ); if ( err != LDAP_SUCCESS ) { /* unrecognized attribute description or other error */ Debug( LDAP_DEBUG_ANY, "get_filter: conn %lu unknown attribute " "type=%s (%d)\n", op->o_connid, type.bv_val, err ); err = LDAP_SUCCESS; f.f_desc = slap_bv2tmp_ad( &type, op->o_tmpmemctx ); } *text = NULL; } assert( f.f_desc != NULL ); } break; case LDAP_FILTER_APPROX: Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 ); err = get_ava( op, ber, &f, SLAP_MR_EQUALITY_APPROX, text ); if ( err != LDAP_SUCCESS ) { break; } assert( f.f_ava != NULL ); break; case LDAP_FILTER_AND: Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 ); err = get_filter_list( op, ber, &f.f_and, text ); if ( err != LDAP_SUCCESS ) { break; } if ( f.f_and == NULL ) { f.f_choice = SLAPD_FILTER_COMPUTED; f.f_result = LDAP_COMPARE_TRUE; } /* no assert - list could be empty */ break; case LDAP_FILTER_OR: Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 ); err = get_filter_list( op, ber, &f.f_or, text ); if ( err != LDAP_SUCCESS ) { break; } if ( f.f_or == NULL ) { f.f_choice = SLAPD_FILTER_COMPUTED; f.f_result = LDAP_COMPARE_FALSE; } /* no assert - list could be empty */ break; case LDAP_FILTER_NOT: Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 ); (void) ber_skip_tag( ber, &len ); err = get_filter( op, ber, &f.f_not, text ); if ( err != LDAP_SUCCESS ) { break; } assert( f.f_not != NULL ); if ( f.f_not->f_choice == SLAPD_FILTER_COMPUTED ) { int fresult = f.f_not->f_result; f.f_choice = SLAPD_FILTER_COMPUTED; op->o_tmpfree( f.f_not, op->o_tmpmemctx ); f.f_not = NULL; switch( fresult ) { case LDAP_COMPARE_TRUE: f.f_result = LDAP_COMPARE_FALSE; break; case LDAP_COMPARE_FALSE: f.f_result = LDAP_COMPARE_TRUE; break; default: ; /* (!Undefined) is Undefined */ } } break; case LDAP_FILTER_EXT: Debug( LDAP_DEBUG_FILTER, "EXTENSIBLE\n", 0, 0, 0 ); err = get_mra( op, ber, &f, text ); if ( err != LDAP_SUCCESS ) { break; } assert( f.f_mra != NULL ); break; default: (void) ber_scanf( ber, "x" ); /* skip the element */ Debug( LDAP_DEBUG_ANY, "get_filter: unknown filter type=%lu\n", f.f_choice, 0, 0 ); f.f_choice = SLAPD_FILTER_COMPUTED; f.f_result = SLAPD_COMPARE_UNDEFINED; break; } if( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) { /* ignore error */ *text = NULL; f.f_choice = SLAPD_FILTER_COMPUTED; f.f_result = SLAPD_COMPARE_UNDEFINED; err = LDAP_SUCCESS; } if ( err == LDAP_SUCCESS ) { *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx ); **filt = f; } Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 ); return( err ); }
static int OpenLDAPaciValidate( Syntax *syntax, struct berval *val ) { struct berval oid = BER_BVNULL, scope = BER_BVNULL, rights = BER_BVNULL, type = BER_BVNULL, subject = BER_BVNULL; int idx; int rc; if ( BER_BVISEMPTY( val ) ) { Debug( LDAP_DEBUG_ACL, "aciValidatet: value is empty\n" ); return LDAP_INVALID_SYNTAX; } /* oid */ if ( acl_get_part( val, 0, '#', &oid ) < 0 || numericoidValidate( NULL, &oid ) != LDAP_SUCCESS ) { /* NOTE: the numericoidValidate() is rather pedantic; * I'd replace it with X-ORDERED VALUES so that * it's guaranteed values are maintained and used * in the desired order */ Debug( LDAP_DEBUG_ACL, "aciValidate: invalid oid '%s'\n", oid.bv_val ); return LDAP_INVALID_SYNTAX; } /* scope */ if ( acl_get_part( val, 1, '#', &scope ) < 0 || bv_getcaseidx( &scope, OpenLDAPaciscopes ) == -1 ) { Debug( LDAP_DEBUG_ACL, "aciValidate: invalid scope '%s'\n", scope.bv_val ); return LDAP_INVALID_SYNTAX; } /* rights */ if ( acl_get_part( val, 2, '#', &rights ) < 0 || OpenLDAPaciValidateRights( &rights ) != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } /* type */ if ( acl_get_part( val, 3, '#', &type ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciValidate: missing type in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } idx = bv_getcaseidx( &type, OpenLDAPacitypes ); if ( idx == -1 ) { struct berval isgr; if ( acl_get_part( &type, 0, '/', &isgr ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciValidate: invalid type '%s'\n", type.bv_val ); return LDAP_INVALID_SYNTAX; } idx = bv_getcaseidx( &isgr, OpenLDAPacitypes ); if ( idx == -1 || idx >= LAST_OPTIONAL ) { Debug( LDAP_DEBUG_ACL, "aciValidate: invalid type '%s'\n", isgr.bv_val ); return LDAP_INVALID_SYNTAX; } } /* subject */ bv_get_tail( val, &type, &subject ); if ( subject.bv_val[ 0 ] != '#' ) { Debug( LDAP_DEBUG_ACL, "aciValidate: missing subject in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } if ( idx >= LAST_DNVALUED ) { if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_DNATTR ] ) { AttributeDescription *ad = NULL; const char *text = NULL; rc = slap_bv2ad( &subject, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciValidate: unknown dn attribute '%s'\n", subject.bv_val ); return LDAP_INVALID_SYNTAX; } if ( ad->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) { /* FIXME: allow nameAndOptionalUID? */ Debug( LDAP_DEBUG_ACL, "aciValidate: wrong syntax for dn attribute '%s'\n", subject.bv_val ); return LDAP_INVALID_SYNTAX; } } /* not a DN */ return LDAP_SUCCESS; } else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_GROUP ] || OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_ROLE ] ) { /* do {group|role}/oc/at check */ struct berval ocbv = BER_BVNULL, atbv = BER_BVNULL; 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 = ber_bvchr( &ocbv, '/' ); if ( atbv.bv_val != NULL ) { AttributeDescription *ad = NULL; const char *text = NULL; int rc; atbv.bv_val++; atbv.bv_len = type.bv_len - ( atbv.bv_val - type.bv_val ); ocbv.bv_len = atbv.bv_val - ocbv.bv_val - 1; rc = slap_bv2ad( &atbv, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciValidate: unknown group attribute '%s'\n", atbv.bv_val ); return LDAP_INVALID_SYNTAX; } } if ( oc_bvfind( &ocbv ) == NULL ) { Debug( LDAP_DEBUG_ACL, "aciValidate: unknown group '%s'\n", ocbv.bv_val ); return LDAP_INVALID_SYNTAX; } } } if ( BER_BVISEMPTY( &subject ) ) { /* empty DN invalid */ Debug( LDAP_DEBUG_ACL, "aciValidate: missing dn in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } subject.bv_val++; subject.bv_len--; /* FIXME: pass DN syntax? */ rc = dnValidate( NULL, &subject ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciValidate: invalid dn '%s'\n", subject.bv_val ); } return rc; }
static int aa_operational( Operation *op, SlapReply *rs ) { Attribute *a, **ap; AccessControlState acl_state = ACL_STATE_INIT; struct berval *v; AttributeType **atp = NULL; ObjectClass **ocp = NULL; #define GOT_NONE (0x0U) #define GOT_C (0x1U) #define GOT_CE (0x2U) #define GOT_A (0x4U) #define GOT_AE (0x8U) #define GOT_ALL (GOT_C|GOT_CE|GOT_A|GOT_AE) int got = GOT_NONE; /* only add if requested */ if ( SLAP_OPATTRS( rs->sr_attr_flags ) ) { got = GOT_ALL; } else { if ( ad_inlist( ad_allowedChildClasses, rs->sr_attrs ) ) { got |= GOT_C; } if ( ad_inlist( ad_allowedChildClassesEffective, rs->sr_attrs ) ) { got |= GOT_CE; } if ( ad_inlist( ad_allowedAttributes, rs->sr_attrs ) ) { got |= GOT_A; } if ( ad_inlist( ad_allowedAttributesEffective, rs->sr_attrs ) ) { got |= GOT_AE; } } if ( got == GOT_NONE ) { return SLAP_CB_CONTINUE; } /* shouldn't be called without an entry; please check */ assert( rs->sr_entry != NULL ); for ( ap = &rs->sr_operational_attrs; *ap != NULL; ap = &(*ap)->a_next ) /* go to last */ ; /* see caveats; this is not guaranteed for all backends */ a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_objectClass ); if ( a == NULL ) { goto do_oc; } /* if client has no access to objectClass attribute; don't compute */ if ( !access_allowed( op, rs->sr_entry, slap_schema.si_ad_objectClass, NULL, ACL_READ, &acl_state ) ) { return SLAP_CB_CONTINUE; } for ( v = a->a_nvals; !BER_BVISNULL( v ); v++ ) { ObjectClass *oc = oc_bvfind( v ); assert( oc != NULL ); /* if client has no access to specific value, don't compute */ if ( !access_allowed( op, rs->sr_entry, slap_schema.si_ad_objectClass, &oc->soc_cname, ACL_READ, &acl_state ) ) { continue; } aa_add_oc( oc, &ocp, &atp ); if ( oc->soc_sups ) { int i; for ( i = 0; oc->soc_sups[ i ] != NULL; i++ ) { aa_add_oc( oc->soc_sups[ i ], &ocp, &atp ); } } } ch_free( ocp ); if ( atp != NULL ) { BerVarray bv_allowed = NULL, bv_effective = NULL; int i, ja = 0, je = 0; for ( i = 0; atp[ i ] != NULL; i++ ) /* just count */ ; if ( got & GOT_A ) { bv_allowed = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) ); } if ( got & GOT_AE ) { bv_effective = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) ); } for ( i = 0, ja = 0, je = 0; atp[ i ] != NULL; i++ ) { if ( got & GOT_A ) { ber_dupbv( &bv_allowed[ ja ], &atp[ i ]->sat_cname ); ja++; } if ( got & GOT_AE ) { AttributeDescription *ad = NULL; const char *text = NULL; if ( slap_bv2ad( &atp[ i ]->sat_cname, &ad, &text ) ) { /* log? */ continue; } if ( access_allowed( op, rs->sr_entry, ad, NULL, ACL_WRITE, NULL ) ) { ber_dupbv( &bv_effective[ je ], &atp[ i ]->sat_cname ); je++; } } } ch_free( atp ); if ( ( got & GOT_A ) && ja > 0 ) { BER_BVZERO( &bv_allowed[ ja ] ); *ap = attr_alloc( ad_allowedAttributes ); (*ap)->a_vals = bv_allowed; (*ap)->a_nvals = bv_allowed; (*ap)->a_numvals = ja; ap = &(*ap)->a_next; } if ( ( got & GOT_AE ) && je > 0 ) { BER_BVZERO( &bv_effective[ je ] ); *ap = attr_alloc( ad_allowedAttributesEffective ); (*ap)->a_vals = bv_effective; (*ap)->a_nvals = bv_effective; (*ap)->a_numvals = je; ap = &(*ap)->a_next; } *ap = NULL; } do_oc:; if ( ( got & GOT_C ) || ( got & GOT_CE ) ) { BerVarray bv_allowed = NULL, bv_effective = NULL; int i, ja = 0, je = 0; ObjectClass *oc; for ( oc_start( &oc ); oc != NULL; oc_next( &oc ) ) { /* we can only add AUXILIARY objectClasses */ if ( oc->soc_kind != LDAP_SCHEMA_AUXILIARY ) { continue; } i++; } if ( got & GOT_C ) { bv_allowed = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) ); } if ( got & GOT_CE ) { bv_effective = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) ); } for ( oc_start( &oc ); oc != NULL; oc_next( &oc ) ) { /* we can only add AUXILIARY objectClasses */ if ( oc->soc_kind != LDAP_SCHEMA_AUXILIARY ) { continue; } if ( got & GOT_C ) { ber_dupbv( &bv_allowed[ ja ], &oc->soc_cname ); ja++; } if ( got & GOT_CE ) { if ( !access_allowed( op, rs->sr_entry, slap_schema.si_ad_objectClass, &oc->soc_cname, ACL_WRITE, NULL ) ) { goto done_ce; } if ( oc->soc_required ) { for ( i = 0; oc->soc_required[ i ] != NULL; i++ ) { AttributeDescription *ad = NULL; const char *text = NULL; if ( slap_bv2ad( &oc->soc_required[ i ]->sat_cname, &ad, &text ) ) { /* log? */ continue; } if ( !access_allowed( op, rs->sr_entry, ad, NULL, ACL_WRITE, NULL ) ) { goto done_ce; } } } ber_dupbv( &bv_effective[ je ], &oc->soc_cname ); je++; } done_ce:; } if ( ( got & GOT_C ) && ja > 0 ) { BER_BVZERO( &bv_allowed[ ja ] ); *ap = attr_alloc( ad_allowedChildClasses ); (*ap)->a_vals = bv_allowed; (*ap)->a_nvals = bv_allowed; (*ap)->a_numvals = ja; ap = &(*ap)->a_next; } if ( ( got & GOT_CE ) && je > 0 ) { BER_BVZERO( &bv_effective[ je ] ); *ap = attr_alloc( ad_allowedChildClassesEffective ); (*ap)->a_vals = bv_effective; (*ap)->a_nvals = bv_effective; (*ap)->a_numvals = je; ap = &(*ap)->a_next; } *ap = NULL; } return SLAP_CB_CONTINUE; }
static int aci_group_member ( struct berval *subj, const struct berval *defgrpoc, const struct berval *defgrpat, Operation *op, Entry *e, int nmatch, regmatch_t *matches ) { struct berval subjdn; struct berval grpoc; struct berval grpat; ObjectClass *grp_oc = NULL; AttributeDescription *grp_ad = NULL; const char *text; int rc; /* format of string is "{group|role}/objectClassValue/groupAttrName" */ if ( acl_get_part( subj, 0, '/', &subjdn ) < 0 ) { return 0; } if ( acl_get_part( subj, 1, '/', &grpoc ) < 0 ) { grpoc = *defgrpoc; } if ( acl_get_part( subj, 2, '/', &grpat ) < 0 ) { grpat = *defgrpat; } rc = slap_bv2ad( &grpat, &grp_ad, &text ); if ( rc != LDAP_SUCCESS ) { rc = 0; goto done; } rc = 0; grp_oc = oc_bvfind( &grpoc ); if ( grp_oc != NULL && grp_ad != NULL ) { char buf[ ACI_BUF_SIZE ]; struct berval bv, ndn; AclRegexMatches amatches = { 0 }; amatches.dn_count = nmatch; memcpy( amatches.dn_data, matches, sizeof( amatches.dn_data ) ); bv.bv_len = sizeof( buf ) - 1; bv.bv_val = (char *)&buf; if ( acl_string_expand( &bv, &subjdn, &e->e_nname, NULL, &amatches ) ) { rc = LDAP_OTHER; goto done; } if ( dnNormalize( 0, NULL, NULL, &bv, &ndn, op->o_tmpmemctx ) == LDAP_SUCCESS ) { rc = ( backend_group( op, e, &ndn, &op->o_ndn, grp_oc, grp_ad ) == 0 ); slap_sl_free( ndn.bv_val, op->o_tmpmemctx ); } } done: return rc; }
int rwm_map_config( struct ldapmap *oc_map, struct ldapmap *at_map, const char *fname, int lineno, int argc, char **argv ) { struct ldapmap *map; struct ldapmapping *mapping; char *src, *dst; int is_oc = 0; int rc = 0; if ( argc < 3 || argc > 4 ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: syntax is \"map {objectclass | attribute} [<local> | *] {<foreign> | *}\"\n", fname, lineno, 0 ); return 1; } if ( strcasecmp( argv[1], "objectclass" ) == 0 ) { map = oc_map; is_oc = 1; } else if ( strcasecmp( argv[1], "attribute" ) == 0 ) { map = at_map; } else { Debug( LDAP_DEBUG_ANY, "%s: line %d: syntax is " "\"map {objectclass | attribute} [<local> | *] " "{<foreign> | *}\"\n", fname, lineno, 0 ); return 1; } if ( !is_oc && map->map == NULL ) { /* only init if required */ if ( rwm_map_init( map, &mapping ) != LDAP_SUCCESS ) { return 1; } } if ( strcmp( argv[2], "*" ) == 0 ) { if ( argc < 4 || strcmp( argv[3], "*" ) == 0 ) { map->drop_missing = ( argc < 4 ); goto success_return; } src = dst = argv[3]; } else if ( argc < 4 ) { src = ""; dst = argv[2]; } else { src = argv[2]; dst = ( strcmp( argv[3], "*" ) == 0 ? src : argv[3] ); } if ( ( map == at_map ) && ( strcasecmp( src, "objectclass" ) == 0 || strcasecmp( dst, "objectclass" ) == 0 ) ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: objectclass attribute cannot be mapped\n", fname, lineno, 0 ); return 1; } mapping = (struct ldapmapping *)ch_calloc( 2, sizeof(struct ldapmapping) ); if ( mapping == NULL ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: out of memory\n", fname, lineno, 0 ); return 1; } ber_str2bv( src, 0, 1, &mapping[0].m_src ); ber_str2bv( dst, 0, 1, &mapping[0].m_dst ); mapping[1].m_src = mapping[0].m_dst; mapping[1].m_dst = mapping[0].m_src; mapping[0].m_flags = RWMMAP_F_NONE; mapping[1].m_flags = RWMMAP_F_NONE; /* * schema check */ if ( is_oc ) { if ( src[0] != '\0' ) { mapping[0].m_src_oc = oc_bvfind( &mapping[0].m_src ); if ( mapping[0].m_src_oc == NULL ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: warning, source objectClass '%s' " "should be defined in schema\n", fname, lineno, src ); /* * FIXME: this should become an err */ mapping[0].m_src_oc = ch_malloc( sizeof( ObjectClass ) ); memset( mapping[0].m_src_oc, 0, sizeof( ObjectClass ) ); mapping[0].m_src_oc->soc_cname = mapping[0].m_src; mapping[0].m_flags |= RWMMAP_F_FREE_SRC; } mapping[1].m_dst_oc = mapping[0].m_src_oc; } mapping[0].m_dst_oc = oc_bvfind( &mapping[0].m_dst ); if ( mapping[0].m_dst_oc == NULL ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: warning, destination objectClass '%s' " "is not defined in schema\n", fname, lineno, dst ); mapping[0].m_dst_oc = oc_bvfind_undef( &mapping[0].m_dst ); if ( mapping[0].m_dst_oc == NULL ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: unable to mimic destination objectClass '%s'\n", fname, lineno, dst ); goto error_return; } } mapping[1].m_src_oc = mapping[0].m_dst_oc; mapping[0].m_flags |= RWMMAP_F_IS_OC; mapping[1].m_flags |= RWMMAP_F_IS_OC; } else { int rc; const char *text = NULL; if ( src[0] != '\0' ) { rc = slap_bv2ad( &mapping[0].m_src, &mapping[0].m_src_ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: warning, source attributeType '%s' " "should be defined in schema\n", fname, lineno, src ); /* * we create a fake "proxied" ad * and add it here. */ rc = slap_bv2undef_ad( &mapping[0].m_src, &mapping[0].m_src_ad, &text, SLAP_AD_PROXIED ); if ( rc != LDAP_SUCCESS ) { char prefix[1024]; snprintf( prefix, sizeof(prefix), "%s: line %d: source attributeType '%s': %d", fname, lineno, src, rc ); Debug( LDAP_DEBUG_ANY, "%s (%s)\n", prefix, text ? text : "null", 0 ); goto error_return; } } mapping[1].m_dst_ad = mapping[0].m_src_ad; } rc = slap_bv2ad( &mapping[0].m_dst, &mapping[0].m_dst_ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: warning, destination attributeType '%s' " "is not defined in schema\n", fname, lineno, dst ); rc = slap_bv2undef_ad( &mapping[0].m_dst, &mapping[0].m_dst_ad, &text, SLAP_AD_PROXIED ); if ( rc != LDAP_SUCCESS ) { char prefix[1024]; snprintf( prefix, sizeof(prefix), "%s: line %d: destination attributeType '%s': %d", fname, lineno, dst, rc ); Debug( LDAP_DEBUG_ANY, "%s (%s)\n", prefix, text ? text : "null", 0 ); goto error_return; } } mapping[1].m_src_ad = mapping[0].m_dst_ad; } if ( ( src[0] != '\0' && avl_find( map->map, (caddr_t)mapping, rwm_mapping_cmp ) != NULL) || avl_find( map->remap, (caddr_t)&mapping[1], rwm_mapping_cmp ) != NULL) { Debug( LDAP_DEBUG_ANY, "%s: line %d: duplicate mapping found.\n", fname, lineno, 0 ); /* FIXME: free stuff */ goto error_return; } if ( src[0] != '\0' ) { avl_insert( &map->map, (caddr_t)&mapping[0], rwm_mapping_cmp, rwm_mapping_dup ); } avl_insert( &map->remap, (caddr_t)&mapping[1], rwm_mapping_cmp, rwm_mapping_dup ); success_return:; return rc; error_return:; if ( mapping ) { rwm_mapping_free( mapping ); } return 1; }
static int create_baseObject( BackendDB *be, const char *fname, int lineno ) { backsql_info *bi = (backsql_info *)be->be_private; LDAPRDN rdn; char *p; int rc, iAVA; char buf[1024]; snprintf( buf, sizeof(buf), "dn: %s\n" "objectClass: extensibleObject\n" "description: builtin baseObject for back-sql\n" "description: all entries mapped " "in table \"ldap_entries\" " "must have " "\"" BACKSQL_BASEOBJECT_IDSTR "\" " "in the \"parent\" column", be->be_suffix[0].bv_val ); bi->sql_baseObject = str2entry( buf ); if ( bi->sql_baseObject == NULL ) { Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): " "unable to parse baseObject entry\n", fname, lineno, 0 ); return 1; } if ( BER_BVISEMPTY( &be->be_suffix[ 0 ] ) ) { return 0; } rc = ldap_bv2rdn( &be->be_suffix[ 0 ], &rdn, (char **)&p, LDAP_DN_FORMAT_LDAP ); if ( rc != LDAP_SUCCESS ) { snprintf( buf, sizeof(buf), "unable to extract RDN " "from baseObject DN \"%s\" (%d: %s)", be->be_suffix[ 0 ].bv_val, rc, ldap_err2string( rc ) ); Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): %s\n", fname, lineno, buf ); return 1; } for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; AttributeDescription *ad = NULL; slap_syntax_transform_func *transf = NULL; struct berval bv = BER_BVNULL; const char *text = NULL; assert( ava != NULL ); rc = slap_bv2ad( &ava->la_attr, &ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( buf, sizeof(buf), "AttributeDescription of naming " "attribute #%d from baseObject " "DN \"%s\": %d: %s", iAVA, be->be_suffix[ 0 ].bv_val, rc, ldap_err2string( rc ) ); Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): %s\n", fname, lineno, buf ); return 1; } transf = ad->ad_type->sat_syntax->ssyn_pretty; if ( transf ) { /* * transform value by pretty function * if value is empty, use empty_bv */ rc = ( *transf )( ad->ad_type->sat_syntax, ava->la_value.bv_len ? &ava->la_value : (struct berval *) &slap_empty_bv, &bv, NULL ); if ( rc != LDAP_SUCCESS ) { snprintf( buf, sizeof(buf), "prettying of attribute #%d " "from baseObject " "DN \"%s\" failed: %d: %s", iAVA, be->be_suffix[ 0 ].bv_val, rc, ldap_err2string( rc ) ); Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): " "%s\n", fname, lineno, buf ); return 1; } } if ( !BER_BVISNULL( &bv ) ) { if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) { ber_memfree( ava->la_value.bv_val ); } ava->la_value = bv; ava->la_flags |= LDAP_AVA_FREE_VALUE; } attr_merge_normalize_one( bi->sql_baseObject, ad, &ava->la_value, NULL ); } ldap_rdnfree( rdn ); return 0; }
static int deref_parseCtrl ( Operation *op, SlapReply *rs, LDAPControl *ctrl ) { ber_tag_t tag; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_len_t len; char *last; DerefSpec *dshead = NULL, **dsp = &dshead; BerVarray attributes = NULL; if ( op->o_deref != SLAP_CONTROL_NONE ) { rs->sr_text = "Dereference control specified multiple times"; return LDAP_PROTOCOL_ERROR; } if ( BER_BVISNULL( &ctrl->ldctl_value ) ) { rs->sr_text = "Dereference control value is absent"; return LDAP_PROTOCOL_ERROR; } if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) { rs->sr_text = "Dereference control value is empty"; return LDAP_PROTOCOL_ERROR; } ber_init2( ber, &ctrl->ldctl_value, 0 ); for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT; tag = ber_next_element( ber, &len, last ) ) { struct berval derefAttr; DerefSpec *ds, *dstmp; const char *text; int rc; ber_len_t cnt = sizeof(struct berval); ber_len_t off = 0; if ( ber_scanf( ber, "{m{M}}", &derefAttr, &attributes, &cnt, off ) == LBER_ERROR || !cnt ) { rs->sr_text = "Dereference control: derefSpec decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } ds = (DerefSpec *)op->o_tmpcalloc( 1, sizeof(DerefSpec) + sizeof(AttributeDescription *)*(cnt + 1), op->o_tmpmemctx ); ds->ds_attributes = (AttributeDescription **)&ds[ 1 ]; ds->ds_nattrs = cnt; rc = slap_bv2ad( &derefAttr, &ds->ds_derefAttr, &text ); if ( rc != LDAP_SUCCESS ) { rs->sr_text = "Dereference control: derefAttr decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } for ( dstmp = dshead; dstmp && dstmp != ds; dstmp = dstmp->ds_next ) { if ( dstmp->ds_derefAttr == ds->ds_derefAttr ) { rs->sr_text = "Dereference control: derefAttr must be unique within control"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } if ( !( ds->ds_derefAttr->ad_type->sat_syntax->ssyn_flags & SLAP_SYNTAX_DN )) { if ( ctrl->ldctl_iscritical ) { rs->sr_text = "Dereference control: derefAttr syntax not distinguishedName"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } rs->sr_err = LDAP_SUCCESS; goto justcleanup; } for ( cnt = 0; !BER_BVISNULL( &attributes[ cnt ] ); cnt++ ) { rc = slap_bv2ad( &attributes[ cnt ], &ds->ds_attributes[ cnt ], &text ); if ( rc != LDAP_SUCCESS ) { rs->sr_text = "Dereference control: attribute decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } ber_memfree_x( attributes, op->o_tmpmemctx ); attributes = NULL; *dsp = ds; dsp = &ds->ds_next; } op->o_ctrlderef = (void *)dshead; op->o_deref = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; rs->sr_err = LDAP_SUCCESS; done:; if ( rs->sr_err != LDAP_SUCCESS ) { justcleanup:; for ( ; dshead; ) { DerefSpec *dsnext = dshead->ds_next; op->o_tmpfree( dshead, op->o_tmpmemctx ); dshead = dsnext; } } if ( attributes != NULL ) { ber_memfree_x( attributes, op->o_tmpmemctx ); } return rs->sr_err; }