static int pguid_db_init( BackendDB *be, ConfigReply *cr) { if ( SLAP_ISGLOBALOVERLAY( be ) ) { Log0( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR, "pguid_db_init: pguid cannot be used as global overlay.\n" ); return 1; } if ( be->be_nsuffix == NULL ) { Log0( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR, "pguid_db_init: database must have suffix\n" ); return 1; } if ( BER_BVISNULL( &be->be_rootndn ) || BER_BVISEMPTY( &be->be_rootndn ) ) { Log1( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR, "pguid_db_init: missing rootdn for database DN=\"%s\", YMMV\n", be->be_suffix[ 0 ].bv_val ); } return 0; }
int slapi_modify_internal_pb( Slapi_PBlock *pb ) { SlapReply *rs; if ( pb == NULL ) { return -1; } PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_MODIFY ); rs = pb->pb_rs; if ( pb->pb_op->orm_modlist == NULL ) { rs->sr_err = LDAP_PARAM_ERROR; goto cleanup; } if ( BER_BVISEMPTY( &pb->pb_op->o_req_ndn ) ) { rs->sr_err = LDAP_UNWILLING_TO_PERFORM; goto cleanup; } rs->sr_err = slap_mods_check( pb->pb_op, pb->pb_op->orm_modlist, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ), NULL ); if ( rs->sr_err != LDAP_SUCCESS ) { goto cleanup; } slapi_int_func_internal_pb( pb, op_modify ); cleanup: return 0; }
void rwm_mapping_dst_free( void *v_mapping ) { struct ldapmapping *mapping = v_mapping; if ( BER_BVISEMPTY( &mapping[0].m_dst ) ) { rwm_mapping_free( &mapping[ -1 ] ); } }
static void mapping_dst_free( void *v_mapping ) { struct ldapmapping *mapping = v_mapping; if ( BER_BVISEMPTY( &mapping->dst ) ) { mapping_free( &mapping[ -1 ] ); } }
int fe_op_bind_success( Operation *op, SlapReply *rs ) { ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); if( op->o_conn->c_authz_backend == NULL ) { op->o_conn->c_authz_backend = op->o_bd; } /* be_bind returns regular/global edn */ if( !BER_BVISEMPTY( &op->orb_edn ) ) { op->o_conn->c_dn = op->orb_edn; } else { ber_dupbv(&op->o_conn->c_dn, &op->o_req_dn); } ber_dupbv( &op->o_conn->c_ndn, &op->o_req_ndn ); /* op->o_conn->c_sb may be 0 for internal operations */ if( !BER_BVISEMPTY( &op->o_conn->c_dn ) && op->o_conn->c_sb != 0 ) { ber_len_t max = sockbuf_max_incoming_auth; ber_sockbuf_ctrl( op->o_conn->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max ); } /* log authorization identity */ Statslog( LDAP_DEBUG_STATS, "%s BIND dn=\"%s\" mech=%s ssf=0\n", op->o_log_prefix, op->o_conn->c_dn.bv_val, op->orb_mech.bv_val ); Debug( LDAP_DEBUG_TRACE, "do_bind: v%d bind: \"%s\" to \"%s\"\n", op->o_protocol, op->o_req_dn.bv_val, op->o_conn->c_dn.bv_val ); ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); /* send this here to avoid a race condition */ send_ldap_result( op, rs ); return LDAP_SUCCESS; }
int slapi_search_internal_callback_pb( Slapi_PBlock *pb, void *callback_data, plugin_result_callback prc, plugin_search_entry_callback psec, plugin_referral_entry_callback prec ) { int free_filter = 0; SlapReply *rs; if ( pb == NULL ) { return -1; } PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_SEARCH ); rs = pb->pb_rs; /* search callback and arguments */ slapi_pblock_set( pb, SLAPI_X_INTOP_RESULT_CALLBACK, (void *)prc ); slapi_pblock_set( pb, SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK, (void *)psec ); slapi_pblock_set( pb, SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK, (void *)prec ); slapi_pblock_set( pb, SLAPI_X_INTOP_CALLBACK_DATA, (void *)callback_data ); if ( BER_BVISEMPTY( &pb->pb_op->ors_filterstr )) { rs->sr_err = LDAP_PARAM_ERROR; goto cleanup; } if ( pb->pb_op->ors_filter == NULL ) { pb->pb_op->ors_filter = slapi_str2filter( pb->pb_op->ors_filterstr.bv_val ); if ( pb->pb_op->ors_filter == NULL ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto cleanup; } free_filter = 1; } slapi_int_func_internal_pb( pb, op_search ); cleanup: if ( free_filter ) { slapi_filter_free( pb->pb_op->ors_filter, 1 ); pb->pb_op->ors_filter = NULL; } slapi_pblock_delete_param( pb, SLAPI_X_INTOP_RESULT_CALLBACK ); slapi_pblock_delete_param( pb, SLAPI_X_INTOP_SEARCH_ENTRY_CALLBACK ); slapi_pblock_delete_param( pb, SLAPI_X_INTOP_REFERRAL_ENTRY_CALLBACK ); slapi_pblock_delete_param( pb, SLAPI_X_INTOP_CALLBACK_DATA ); return 0; }
static int pam_uid2dn(nssov_info *ni, Operation *op, struct paminfo *pi) { struct berval sdn; BER_BVZERO(&pi->dn); if (!isvalidusername(&pi->uid)) { Debug(LDAP_DEBUG_ANY,"nssov_pam_uid2dn(%s): invalid user name\n", pi->uid.bv_val,0,0); return NSLCD_PAM_USER_UNKNOWN; } if (ni->ni_pam_opts & NI_PAM_SASL2DN) { int hlen = global_host_bv.bv_len; /* cn=<service>+uid=<user>,cn=<host>,cn=pam,cn=auth */ sdn.bv_len = pi->uid.bv_len + pi->svc.bv_len + hlen + STRLENOF( "cn=+uid=,cn=,cn=pam,cn=auth" ); sdn.bv_val = op->o_tmpalloc( sdn.bv_len + 1, op->o_tmpmemctx ); sprintf(sdn.bv_val, "cn=%s+uid=%s,cn=%s,cn=pam,cn=auth", pi->svc.bv_val, pi->uid.bv_val, global_host_bv.bv_val); slap_sasl2dn(op, &sdn, &pi->dn, 0); op->o_tmpfree( sdn.bv_val, op->o_tmpmemctx ); } /* If no luck, do a basic uid search */ if (BER_BVISEMPTY(&pi->dn) && (ni->ni_pam_opts & NI_PAM_UID2DN)) { nssov_uid2dn(op, ni, &pi->uid, &pi->dn); if (!BER_BVISEMPTY(&pi->dn)) { sdn = pi->dn; dnNormalize( 0, NULL, NULL, &sdn, &pi->dn, op->o_tmpmemctx ); } } if (BER_BVISEMPTY(&pi->dn)) { return NSLCD_PAM_USER_UNKNOWN; } return 0; }
/* Conforms to RFC4510 re: Criticality, original RFC2891 spec is broken * Also see ITS#7253 for discussion */ static int sss_parseCtrl( Operation *op, SlapReply *rs, LDAPControl *ctrl ) { BerElementBuffer berbuf; BerElement *ber; ber_tag_t tag; ber_len_t len; int i; sort_ctrl *sc; rs->sr_err = LDAP_PROTOCOL_ERROR; if ( op->o_ctrlflag[sss_cid] > SLAP_CONTROL_IGNORED ) { rs->sr_text = "sorted results control specified multiple times"; } else if ( BER_BVISNULL( &ctrl->ldctl_value ) ) { rs->sr_text = "sorted results control value is absent"; } else if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) { rs->sr_text = "sorted results control value is empty"; } else { rs->sr_err = LDAP_SUCCESS; } if ( rs->sr_err != LDAP_SUCCESS ) return rs->sr_err; op->o_ctrlflag[sss_cid] = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; ber = (BerElement *)&berbuf; ber_init2( ber, &ctrl->ldctl_value, 0 ); i = count_key( ber ); sc = op->o_tmpalloc( sizeof(sort_ctrl) + (i-1) * sizeof(sort_key), op->o_tmpmemctx ); sc->sc_nkeys = i; op->o_controls[sss_cid] = sc; /* peel off initial sequence */ ber_scanf( ber, "{" ); i = 0; do { if ( build_key( ber, rs, &sc->sc_keys[i] ) != LDAP_SUCCESS ) break; i++; tag = ber_peek_tag( ber, &len ); } while ( tag != LBER_DEFAULT ); return rs->sr_err; }
ID ndb_tool_dn2id_get( Backend *be, struct berval *dn ) { struct ndb_info *ni = (struct ndb_info *) be->be_private; NdbArgs NA; NdbRdns rdns; Entry e; char text[1024]; Operation op = {0}; Opheader ohdr = {0}; int rc; if ( BER_BVISEMPTY(dn) ) return 0; NA.ndb = myNdb; NA.txn = myNdb->startTransaction(); if ( !NA.txn ) { snprintf( text, sizeof(text), "startTransaction failed: %s (%d)", myNdb->getNdbError().message, myNdb->getNdbError().code ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(ndb_tool_dn2id_get) ": %s\n", text, 0, 0 ); return NOID; } if ( myOcList ) { ber_bvarray_free( myOcList ); myOcList = NULL; } op.o_hdr = &ohdr; op.o_bd = be; op.o_tmpmemctx = NULL; op.o_tmpmfuncs = &ch_mfuncs; NA.e = &e; e.e_name = *dn; NA.rdns = &rdns; NA.ocs = NULL; rc = ndb_entry_get_info( &op, &NA, 0, NULL ); myOcList = NA.ocs; NA.txn->close(); if ( rc ) return NOID; myDn = *dn; return e.e_id; }
int unload_extop( const struct berval *ext_oid, SLAP_EXTOP_MAIN_FN *ext_main, unsigned flags ) { struct berval oidm = BER_BVNULL; struct extop_list *ext, **extp; /* oid must be given */ if ( ext_oid == NULL || BER_BVISNULL( ext_oid ) || BER_BVISEMPTY( ext_oid ) ) { return -1; } /* if it's not an oid, check if it's a macto */ if ( numericoidValidate( NULL, (struct berval *)ext_oid ) != LDAP_SUCCESS ) { oidm.bv_val = oidm_find( ext_oid->bv_val ); if ( oidm.bv_val == NULL ) { return -1; } oidm.bv_len = strlen( oidm.bv_val ); ext_oid = &oidm; } /* lookup the oid */ for ( extp = &supp_ext_list; *extp; extp = &(*extp)->next ) { if ( bvmatch( ext_oid, &(*extp)->oid ) ) { /* if ext_main is given, only remove if it matches */ if ( ext_main != NULL && (*extp)->ext_main != ext_main ) { return -1; } break; } } if ( *extp == NULL ) { return -1; } ext = *extp; *extp = (*extp)->next; ch_free( ext ); return 0; }
static int slapi_op_bind_callback( Operation *op, SlapReply *rs, int prc ) { switch ( prc ) { case SLAPI_BIND_SUCCESS: /* Continue with backend processing */ break; case SLAPI_BIND_FAIL: /* Failure, frontend (that's us) sends result */ rs->sr_err = LDAP_INVALID_CREDENTIALS; send_ldap_result( op, rs ); return rs->sr_err; break; case SLAPI_BIND_ANONYMOUS: /* undocumented */ default: /* plugin sent result or no plugins called */ BER_BVZERO( &op->orb_edn ); if ( rs->sr_err == LDAP_SUCCESS ) { /* * Plugin will have called slapi_pblock_set(LDAP_CONN_DN) which * will have set conn->c_dn and conn->c_ndn */ if ( BER_BVISNULL( &op->o_conn->c_ndn ) && prc == 1 ) { /* No plugins were called; continue processing */ return LDAP_SUCCESS; } ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); if ( !BER_BVISEMPTY( &op->o_conn->c_ndn ) ) { ber_len_t max = sockbuf_max_incoming_auth; ber_sockbuf_ctrl( op->o_conn->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max ); } ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); /* log authorization identity */ Statslog( LDAP_DEBUG_STATS, "%s BIND dn=\"%s\" mech=%s (SLAPI) ssf=0\n", op->o_log_prefix, BER_BVISNULL( &op->o_conn->c_dn ) ? "<empty>" : op->o_conn->c_dn.bv_val, BER_BVISNULL( &op->orb_mech ) ? "<empty>" : op->orb_mech.bv_val, 0, 0 ); return -1; } break; } return rs->sr_err; }
static int rdnval_is_valid( AttributeDescription *desc, struct berval *value ) { if ( desc->ad_type->sat_syntax == slap_schema.si_syn_directoryString ) { return 1; } if ( desc->ad_type->sat_syntax == syn_IA5String && !BER_BVISEMPTY( value ) ) { return 1; } return 0; }
static int aci_list_get_rights( struct berval *list, struct berval *attr, struct berval *val, slap_access_t *grant, slap_access_t *deny ) { struct berval perm, actn, baseattr; slap_access_t *mask; int i, found; if ( attr == NULL || BER_BVISEMPTY( attr ) ) { attr = (struct berval *)&aci_bv[ ACI_BV_ENTRY ]; } else if ( acl_get_part( attr, 0, ';', &baseattr ) > 0 ) { attr = &baseattr; } found = 0; ACL_INIT(*grant); ACL_INIT(*deny); /* loop through each permissions clause */ for ( i = 0; acl_get_part( list, i, '$', &perm ) >= 0; i++ ) { if ( acl_get_part( &perm, 0, ';', &actn ) < 0 ) { continue; } if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_GRANT ], &actn ) == 0 ) { mask = grant; } else if ( ber_bvstrcasecmp( &aci_bv[ ACI_BV_DENY ], &actn ) == 0 ) { mask = deny; } else { continue; } *mask |= aci_list_get_attr_rights( &perm, attr, val ); *mask |= aci_list_get_attr_rights( &perm, &aci_bv[ ACI_BV_BR_ALL ], NULL ); if ( *mask != ACL_PRIV_NONE ) { found = 1; } } return found; }
int dnssrv_back_bind( Operation *op, SlapReply *rs ) { Debug( LDAP_DEBUG_TRACE, "DNSSRV: bind dn=\"%s\" (%d)\n", BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val, op->orb_method, 0 ); /* allow rootdn as a means to auth without the need to actually * contact the proxied DSA */ switch ( be_rootdn_bind( op, NULL ) ) { case LDAP_SUCCESS: /* frontend will send result */ return rs->sr_err; default: /* treat failure and like any other bind, otherwise * it could reveal the DN of the rootdn */ break; } if ( !BER_BVISNULL( &op->orb_cred ) && !BER_BVISEMPTY( &op->orb_cred ) ) { /* simple bind */ Statslog( LDAP_DEBUG_STATS, "%s DNSSRV BIND dn=\"%s\" provided cleartext passwd\n", op->o_log_prefix, BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val , 0, 0, 0 ); send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "you shouldn't send strangers your password" ); } else { /* unauthenticated bind */ /* NOTE: we're not going to get here anyway: * unauthenticated bind is dealt with by the frontend */ Debug( LDAP_DEBUG_TRACE, "DNSSRV: BIND dn=\"%s\"\n", BER_BVISNULL( &op->o_req_dn ) ? "" : op->o_req_dn.bv_val, 0, 0 ); send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "anonymous bind expected" ); } return 1; }
/* * Matches given berval to array of bervals * Returns: * >=0 if one if the array elements equals to this berval * -1 if string was not found in array */ static int bv_getcaseidx( struct berval *bv, const struct berval *arr[] ) { int i; if ( BER_BVISEMPTY( bv ) ) { return -1; } for ( i = 0; arr[ i ] != NULL ; i++ ) { if ( ber_bvstrcasecmp( bv, arr[ i ] ) == 0 ) { return i; } } return -1; }
int slapi_modrdn_internal_pb( Slapi_PBlock *pb ) { if ( pb == NULL ) { return -1; } PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_MODRDN ); if ( BER_BVISEMPTY( &pb->pb_op->o_req_ndn ) ) { pb->pb_rs->sr_err = LDAP_UNWILLING_TO_PERFORM; goto cleanup; } slapi_int_func_internal_pb( pb, op_modrdn ); cleanup: return 0; }
int ldap_back_map_attrs( struct ldapmap *at_map, AttributeName *an, int remap, char ***mapped_attrs, void *memctx ) { int i, j; char **na; struct berval mapped; if ( an == NULL ) { *mapped_attrs = NULL; return LDAP_SUCCESS; } for ( i = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) /* */ ; na = (char **)ber_memcalloc_x( i + 1, sizeof(char *), memctx ); if ( na == NULL ) { *mapped_attrs = NULL; return LDAP_NO_MEMORY; } for ( i = j = 0; !BER_BVISNULL( &an[i].an_name ); i++ ) { ldap_back_map( at_map, &an[i].an_name, &mapped, remap ); if ( !BER_BVISNULL( &mapped ) && !BER_BVISEMPTY( &mapped ) ) { na[j++] = mapped.bv_val; } } if ( j == 0 && i != 0 ) { na[j++] = LDAP_NO_ATTRS; } na[j] = NULL; *mapped_attrs = na; return LDAP_SUCCESS; }
static int rdnval_op_add( Operation *op, SlapReply *rs ) { Attribute *a, **ap; int numvals = 0; BerVarray vals = NULL, nvals = NULL; int rc; /* NOTE: should we accept an entry still in mods format? */ assert( op->ora_e != NULL ); if ( BER_BVISEMPTY( &op->ora_e->e_nname ) ) { return SLAP_CB_CONTINUE; } a = attr_find( op->ora_e->e_attrs, ad_rdnValue ); if ( a != NULL ) { /* TODO: check consistency? */ return SLAP_CB_CONTINUE; } rc = rdnval_rdn2vals( op, rs, &op->ora_e->e_name, &op->ora_e->e_nname, &vals, &nvals, &numvals ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); } a = attr_alloc( ad_rdnValue ); a->a_vals = vals; a->a_nvals = nvals; a->a_numvals = numvals; for ( ap = &op->ora_e->e_attrs; *ap != NULL; ap = &(*ap)->a_next ) /* goto tail */ ; *ap = a; return SLAP_CB_CONTINUE; }
static int vernum_op_add( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; vernum_t *vn = (vernum_t *)on->on_bi.bi_private; Attribute *a, **ap; int rc; /* NOTE: should we accept an entry still in mods format? */ assert( op->ora_e != NULL ); if ( BER_BVISEMPTY( &op->ora_e->e_nname ) ) { return SLAP_CB_CONTINUE; } a = attr_find( op->ora_e->e_attrs, vn->vn_attr ); if ( a == NULL ) { return SLAP_CB_CONTINUE; } if ( attr_find( op->ora_e->e_attrs, vn->vn_vernum ) != NULL ) { /* already present - leave it alone */ return SLAP_CB_CONTINUE; } a = attr_alloc( vn->vn_vernum ); value_add_one( &a->a_vals, &val_init ); a->a_nvals = a->a_vals; a->a_numvals = 1; for ( ap = &op->ora_e->e_attrs; *ap != NULL; ap = &(*ap)->a_next ) /* goto tail */ ; *ap = a; return SLAP_CB_CONTINUE; }
static int dynlist_make_filter( Operation *op, Entry *e, const char *url, struct berval *oldf, struct berval *newf ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; dynlist_info_t *dli = (dynlist_info_t *)on->on_bi.bi_private; char *ptr; int needBrackets = 0; assert( oldf != NULL ); assert( newf != NULL ); assert( !BER_BVISNULL( oldf ) ); assert( !BER_BVISEMPTY( oldf ) ); if ( oldf->bv_val[0] != '(' ) { Debug( LDAP_DEBUG_ANY, "%s: dynlist, DN=\"%s\": missing brackets in URI=\"%s\" filter\n", op->o_log_prefix, e->e_name.bv_val, url ); needBrackets = 2; } newf->bv_len = STRLENOF( "(&(!(objectClass=" "))" ")" ) + dli->dli_oc->soc_cname.bv_len + oldf->bv_len + needBrackets; newf->bv_val = op->o_tmpalloc( newf->bv_len + 1, op->o_tmpmemctx ); if ( newf->bv_val == NULL ) { return -1; } ptr = lutil_strcopy( newf->bv_val, "(&(!(objectClass=" ); ptr = lutil_strcopy( ptr, dli->dli_oc->soc_cname.bv_val ); ptr = lutil_strcopy( ptr, "))" ); if ( needBrackets ) *ptr++ = '('; ptr = lutil_strcopy( ptr, oldf->bv_val ); if ( needBrackets ) *ptr++ = ')'; ptr = lutil_strcopy( ptr, ")" ); newf->bv_len = ptr - newf->bv_val; return 0; }
int meta_back_modify( Operation *op, SlapReply *rs ) { metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; metatarget_t *mt; metaconn_t *mc; int rc = 0; LDAPMod **modv = NULL; LDAPMod *mods = NULL; Modifications *ml; int candidate = -1, i; int isupdate; struct berval mdn = BER_BVNULL; struct berval mapped; dncookie dc; int msgid; ldap_back_send_t retrying = LDAP_BACK_RETRYING; LDAPControl **ctrls = NULL; mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR ); if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) { return rs->sr_err; } assert( mc->mc_conns[ candidate ].msc_ld != NULL ); /* * Rewrite the modify dn, if needed */ mt = mi->mi_targets[ candidate ]; dc.target = mt; dc.conn = op->o_conn; dc.rs = rs; dc.ctx = "modifyDN"; if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) { send_ldap_result( op, rs ); goto cleanup; } for ( i = 0, ml = op->orm_modlist; ml; i++ ,ml = ml->sml_next ) ; mods = ch_malloc( sizeof( LDAPMod )*i ); if ( mods == NULL ) { rs->sr_err = LDAP_OTHER; send_ldap_result( op, rs ); goto cleanup; } modv = ( LDAPMod ** )ch_malloc( ( i + 1 )*sizeof( LDAPMod * ) ); if ( modv == NULL ) { rs->sr_err = LDAP_OTHER; send_ldap_result( op, rs ); goto cleanup; } dc.ctx = "modifyAttrDN"; isupdate = be_shadow_update( op ); for ( i = 0, ml = op->orm_modlist; ml; ml = ml->sml_next ) { int j, is_oc = 0; if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod ) { continue; } if ( ml->sml_desc == slap_schema.si_ad_objectClass || ml->sml_desc == slap_schema.si_ad_structuralObjectClass ) { is_oc = 1; mapped = ml->sml_desc->ad_cname; } else { ldap_back_map( &mt->mt_rwmap.rwm_at, &ml->sml_desc->ad_cname, &mapped, BACKLDAP_MAP ); if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) { continue; } } modv[ i ] = &mods[ i ]; mods[ i ].mod_op = ml->sml_op | LDAP_MOD_BVALUES; mods[ i ].mod_type = mapped.bv_val; /* * FIXME: dn-valued attrs should be rewritten * to allow their use in ACLs at the back-ldap * level. */ if ( ml->sml_values != NULL ) { if ( is_oc ) { for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) ; mods[ i ].mod_bvalues = (struct berval **)ch_malloc( ( j + 1 ) * sizeof( struct berval * ) ); for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); ) { struct ldapmapping *mapping; ldap_back_mapping( &mt->mt_rwmap.rwm_oc, &ml->sml_values[ j ], &mapping, BACKLDAP_MAP ); if ( mapping == NULL ) { if ( mt->mt_rwmap.rwm_oc.drop_missing ) { continue; } mods[ i ].mod_bvalues[ j ] = &ml->sml_values[ j ]; } else { mods[ i ].mod_bvalues[ j ] = &mapping->dst; } j++; } mods[ i ].mod_bvalues[ j ] = NULL; } else { if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) { ( void )ldap_dnattr_rewrite( &dc, ml->sml_values ); if ( ml->sml_values == NULL ) { continue; } } for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) ; mods[ i ].mod_bvalues = (struct berval **)ch_malloc( ( j + 1 ) * sizeof( struct berval * ) ); for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) { mods[ i ].mod_bvalues[ j ] = &ml->sml_values[ j ]; } mods[ i ].mod_bvalues[ j ] = NULL; } } else { mods[ i ].mod_bvalues = NULL; } i++; } modv[ i ] = 0; retry:; ctrls = op->o_ctrls; rc = meta_back_controls_add( op, rs, mc, candidate, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } rs->sr_err = ldap_modify_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val, modv, ctrls, NULL, &msgid ); rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid, mt->mt_timeout[ SLAP_OP_MODIFY ], ( LDAP_BACK_SENDRESULT | retrying ) ); if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) { retrying &= ~LDAP_BACK_RETRYING; if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls ); goto retry; } } cleanup:; (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls ); if ( mdn.bv_val != op->o_req_dn.bv_val ) { free( mdn.bv_val ); BER_BVZERO( &mdn ); } if ( modv != NULL ) { for ( i = 0; modv[ i ]; i++ ) { free( modv[ i ]->mod_bvalues ); } } free( mods ); free( modv ); if ( mc ) { meta_back_release_conn( mi, mc ); } return rs->sr_err; }
static int dynacl_aci_mask( void *priv, Operation *op, Entry *e, AttributeDescription *desc, struct berval *val, int nmatch, regmatch_t *matches, slap_access_t *grantp, slap_access_t *denyp ) { AttributeDescription *ad = ( AttributeDescription * )priv; Attribute *at; slap_access_t tgrant, tdeny, grant, deny; #ifdef LDAP_DEBUG char accessmaskbuf[ACCESSMASK_MAXLEN]; char accessmaskbuf1[ACCESSMASK_MAXLEN]; #endif /* LDAP_DEBUG */ if ( BER_BVISEMPTY( &e->e_nname ) ) { /* no ACIs in the root DSE */ return -1; } /* start out with nothing granted, nothing denied */ ACL_INIT(tgrant); ACL_INIT(tdeny); /* get the aci attribute */ at = attr_find( e->e_attrs, ad ); if ( at != NULL ) { int i; /* the aci is an multi-valued attribute. The * rights are determined by OR'ing the individual * rights given by the acis. */ for ( i = 0; !BER_BVISNULL( &at->a_nvals[i] ); i++ ) { if ( aci_mask( op, e, desc, val, &at->a_nvals[i], nmatch, matches, &grant, &deny, SLAP_ACI_SCOPE_ENTRY ) != 0 ) { tgrant |= grant; tdeny |= deny; } } Debug( LDAP_DEBUG_ACL, " <= aci_mask grant %s deny %s\n", accessmask2str( tgrant, accessmaskbuf, 1 ), accessmask2str( tdeny, accessmaskbuf1, 1 ) ); } /* If the entry level aci didn't contain anything valid for the * current operation, climb up the tree and evaluate the * acis with scope set to subtree */ if ( tgrant == ACL_PRIV_NONE && tdeny == ACL_PRIV_NONE ) { struct berval parent_ndn; dnParent( &e->e_nname, &parent_ndn ); while ( !BER_BVISEMPTY( &parent_ndn ) ){ int i; BerVarray bvals = NULL; int ret, stop; /* to solve the chicken'n'egg problem of accessing * the OpenLDAPaci attribute, the direct access * to the entry's attribute is unchecked; however, * further accesses to OpenLDAPaci values in the * ancestors occur through backend_attribute(), i.e. * with the identity of the operation, requiring * further access checking. For uniformity, this * makes further requests occur as the rootdn, if * any, i.e. searching for the OpenLDAPaci attribute * is considered an internal search. If this is not * acceptable, then the same check needs be performed * when accessing the entry's attribute. */ struct berval save_o_dn = {0}, save_o_ndn = {0}; if ( !BER_BVISNULL( &op->o_bd->be_rootndn ) ) { save_o_dn = op->o_dn; save_o_ndn = op->o_ndn; op->o_dn = op->o_bd->be_rootdn; op->o_ndn = op->o_bd->be_rootndn; } Debug( LDAP_DEBUG_ACL, " checking ACI of \"%s\"\n", parent_ndn.bv_val ); ret = backend_attribute( op, NULL, &parent_ndn, ad, &bvals, ACL_AUTH ); if ( !BER_BVISNULL( &op->o_bd->be_rootndn ) ) { op->o_dn = save_o_dn; op->o_ndn = save_o_ndn; } switch ( ret ) { case LDAP_SUCCESS : stop = 0; if ( !bvals ) { break; } for ( i = 0; !BER_BVISNULL( &bvals[i] ); i++ ) { if ( aci_mask( op, e, desc, val, &bvals[i], nmatch, matches, &grant, &deny, SLAP_ACI_SCOPE_CHILDREN ) != 0 ) { tgrant |= grant; tdeny |= deny; /* evaluation stops as soon as either a "deny" or a * "grant" directive matches. */ if ( tgrant != ACL_PRIV_NONE || tdeny != ACL_PRIV_NONE ) { stop = 1; } } Debug( LDAP_DEBUG_ACL, "<= aci_mask grant %s deny %s\n", accessmask2str( tgrant, accessmaskbuf, 1 ), accessmask2str( tdeny, accessmaskbuf1, 1 ) ); } break; case LDAP_NO_SUCH_ATTRIBUTE: /* just go on if the aci-Attribute is not present in * the current entry */ Debug( LDAP_DEBUG_ACL, "no such attribute\n" ); stop = 0; break; case LDAP_NO_SUCH_OBJECT: /* We have reached the base object */ Debug( LDAP_DEBUG_ACL, "no such object\n" ); stop = 1; break; default: stop = 1; break; } if ( stop ) { break; } dnParent( &parent_ndn, &parent_ndn ); } } *grantp = tgrant; *denyp = tdeny; return 0; }
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 process_ldif_rec( char *rbuf, int linenum ) { char *line, *dn, *newrdn, *newsup; int rc, modop; int expect_modop, expect_sep; int deleteoldrdn; int new_entry, delete_entry, got_all; LDAPMod **pmods, *lm = NULL; int version; LDAPControl **pctrls; int i, j, k, lines, idn, nmods; struct berval *btype, *vals, **bvl, bv; char *freeval; unsigned char *mops = NULL; new_entry = ldapadd; rc = got_all = delete_entry = modop = expect_modop = 0; expect_sep = 0; version = 0; deleteoldrdn = 1; pmods = NULL; pctrls = NULL; dn = newrdn = newsup = NULL; lines = ldif_countlines( rbuf ); btype = ber_memcalloc( 1, (lines+1)*2*sizeof(struct berval)+lines ); if ( !btype ) return LDAP_NO_MEMORY; vals = btype+lines+1; freeval = (char *)(vals+lines+1); i = -1; while ( rc == 0 && ( line = ldif_getline( &rbuf )) != NULL ) { int freev; if ( *line == '\n' || *line == '\0' ) { break; } ++i; if ( line[0] == '-' && !line[1] ) { BER_BVZERO( btype+i ); freeval[i] = 0; continue; } if ( ( rc = ldif_parse_line2( line, btype+i, vals+i, &freev ) ) < 0 ) { fprintf( stderr, _("%s: invalid format (line %d) entry: \"%s\"\n"), prog, linenum+i, dn == NULL ? "" : dn ); rc = LDAP_PARAM_ERROR; break; } freeval[i] = freev; if ( dn == NULL ) { if ( linenum+i == 1 && BV_CASEMATCH( btype+i, &BV_VERSION )) { int v; if( vals[i].bv_len == 0 || lutil_atoi( &v, vals[i].bv_val) != 0 || v != 1 ) { fprintf( stderr, _("%s: invalid version %s, line %d (ignored)\n"), prog, vals[i].bv_val, linenum ); } version++; } else if ( BV_CASEMATCH( btype+i, &BV_DN )) { dn = vals[i].bv_val; idn = i; } /* skip all lines until we see "dn:" */ } } /* check to make sure there was a dn: line */ if ( !dn ) { rc = 0; goto leave; } lines = i+1; if( lines == 0 ) { rc = 0; goto leave; } if( version && lines == 1 ) { rc = 0; goto leave; } i = idn+1; /* Check for "control" tag after dn and before changetype. */ if ( BV_CASEMATCH( btype+i, &BV_CONTROL )) { /* Parse and add it to the list of controls */ rc = parse_ldif_control( vals+i, &pctrls ); if (rc != 0) { fprintf( stderr, _("%s: Error processing %s line, line %d: %s\n"), prog, BV_CONTROL.bv_val, linenum+i, ldap_err2string(rc) ); } i++; if ( i>= lines ) { short_input: fprintf( stderr, _("%s: Expecting more input after %s line, line %d\n"), prog, btype[i-1].bv_val, linenum+i ); rc = LDAP_PARAM_ERROR; goto leave; } } /* Check for changetype */ if ( BV_CASEMATCH( btype+i, &BV_CHANGETYPE )) { #ifdef LIBERAL_CHANGETYPE_MODOP /* trim trailing spaces (and log warning ...) */ int icnt; for ( icnt = vals[i].bv_len; --icnt > 0; ) { if ( !isspace( (unsigned char) vals[i].bv_val[icnt] ) ) { break; } } if ( ++icnt != vals[i].bv_len ) { fprintf( stderr, _("%s: illegal trailing space after" " \"%s: %s\" trimmed (line %d, entry \"%s\")\n"), prog, BV_CHANGETYPE.bv_val, vals[i].bv_val, linenum+i, dn ); vals[i].bv_val[icnt] = '\0'; } #endif /* LIBERAL_CHANGETYPE_MODOP */ if ( BV_CASEMATCH( vals+i, &BV_MODIFYCT )) { new_entry = 0; expect_modop = 1; } else if ( BV_CASEMATCH( vals+i, &BV_ADDCT )) { new_entry = 1; modop = LDAP_MOD_ADD; } else if ( BV_CASEMATCH( vals+i, &BV_MODRDNCT ) || BV_CASEMATCH( vals+i, &BV_MODDNCT ) || BV_CASEMATCH( vals+i, &BV_RENAMECT )) { i++; if ( i >= lines ) goto short_input; if ( !BV_CASEMATCH( btype+i, &BV_NEWRDN )) { fprintf( stderr, _("%s: expecting \"%s:\" but saw" " \"%s:\" (line %d, entry \"%s\")\n"), prog, BV_NEWRDN.bv_val, btype[i].bv_val, linenum+i, dn ); rc = LDAP_PARAM_ERROR; goto leave; } newrdn = vals[i].bv_val; i++; if ( i >= lines ) goto short_input; if ( !BV_CASEMATCH( btype+i, &BV_DELETEOLDRDN )) { fprintf( stderr, _("%s: expecting \"%s:\" but saw" " \"%s:\" (line %d, entry \"%s\")\n"), prog, BV_DELETEOLDRDN.bv_val, btype[i].bv_val, linenum+i, dn ); rc = LDAP_PARAM_ERROR; goto leave; } deleteoldrdn = ( vals[i].bv_val[0] == '0' ) ? 0 : 1; i++; if ( i < lines ) { if ( !BV_CASEMATCH( btype+i, &BV_NEWSUP )) { fprintf( stderr, _("%s: expecting \"%s:\" but saw" " \"%s:\" (line %d, entry \"%s\")\n"), prog, BV_NEWSUP.bv_val, btype[i].bv_val, linenum+i, dn ); rc = LDAP_PARAM_ERROR; goto leave; } newsup = vals[i].bv_val; i++; } got_all = 1; } else if ( BV_CASEMATCH( vals+i, &BV_DELETECT )) { got_all = delete_entry = 1; } else { fprintf( stderr, _("%s: unknown %s \"%s\" (line %d, entry \"%s\")\n"), prog, BV_CHANGETYPE.bv_val, vals[i].bv_val, linenum+i, dn ); rc = LDAP_PARAM_ERROR; goto leave; } i++; } else if ( ldapadd ) { /* missing changetype => add */ new_entry = 1; modop = LDAP_MOD_ADD; } else { expect_modop = 1; /* missing changetype => modify */ } if ( got_all ) { if ( i < lines ) { fprintf( stderr, _("%s: extra lines at end (line %d, entry \"%s\")\n"), prog, linenum+i, dn ); rc = LDAP_PARAM_ERROR; goto leave; } goto doit; } nmods = lines - i; idn = i; if ( new_entry ) { int fv; /* Make sure all attributes with multiple values are contiguous */ for (; i<lines; i++) { for (j=i+1; j<lines; j++) { if ( BV_CASEMATCH( btype+i, btype+j )) { nmods--; /* out of order, move intervening attributes down */ if ( j != i+1 ) { bv = vals[j]; fv = freeval[j]; for (k=j; k>i; k--) { btype[k] = btype[k-1]; vals[k] = vals[k-1]; freeval[k] = freeval[k-1]; } k++; btype[k] = btype[i]; vals[k] = bv; freeval[k] = fv; } i++; } } } /* Allocate space for array of mods, array of pointers to mods, * and array of pointers to values, allowing for NULL terminators * for the pointer arrays... */ lm = ber_memalloc( nmods * sizeof(LDAPMod) + (nmods+1) * sizeof(LDAPMod*) + (lines + nmods - idn) * sizeof(struct berval *)); pmods = (LDAPMod **)(lm+nmods); bvl = (struct berval **)(pmods+nmods+1); j = 0; k = -1; BER_BVZERO(&bv); for (i=idn; i<lines; i++) { if ( BV_CASEMATCH( btype+i, &BV_DN )) { fprintf( stderr, _("%s: attributeDescription \"%s\":" " (possible missing newline" " after line %d, entry \"%s\"?)\n"), prog, btype[i].bv_val, linenum+i - 1, dn ); } if ( !BV_CASEMATCH( btype+i, &bv )) { bvl[k++] = NULL; bv = btype[i]; lm[j].mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES; lm[j].mod_type = bv.bv_val; lm[j].mod_bvalues = bvl+k; pmods[j] = lm+j; j++; } bvl[k++] = vals+i; } bvl[k] = NULL; pmods[j] = NULL; goto doit; } mops = ber_memalloc( lines+1 ); mops[lines] = M_SEP; mops[i-1] = M_SEP; for ( ; i<lines; i++ ) { if ( expect_modop ) { #ifdef LIBERAL_CHANGETYPE_MODOP /* trim trailing spaces (and log warning ...) */ int icnt; for ( icnt = vals[i].bv_len; --icnt > 0; ) { if ( !isspace( (unsigned char) vals[i].bv_val[icnt] ) ) break; } if ( ++icnt != vals[i].bv_len ) { fprintf( stderr, _("%s: illegal trailing space after" " \"%s: %s\" trimmed (line %d, entry \"%s\")\n"), prog, type, vals[i].bv_val, linenum+i, dn ); vals[i].bv_val[icnt] = '\0'; } #endif /* LIBERAL_CHANGETYPE_MODOP */ expect_modop = 0; expect_sep = 1; if ( BV_CASEMATCH( btype+i, &BV_MODOPADD )) { modop = LDAP_MOD_ADD; mops[i] = M_SEP; nmods--; } else if ( BV_CASEMATCH( btype+i, &BV_MODOPREPLACE )) { /* defer handling these since they might have no values. * Use the BVALUES flag to signal that these were * deferred. If values are provided later, this * flag will be switched off. */ modop = LDAP_MOD_REPLACE; mops[i] = modop | LDAP_MOD_BVALUES; btype[i] = vals[i]; } else if ( BV_CASEMATCH( btype+i, &BV_MODOPDELETE )) { modop = LDAP_MOD_DELETE; mops[i] = modop | LDAP_MOD_BVALUES; btype[i] = vals[i]; } else if ( BV_CASEMATCH( btype+i, &BV_MODOPINCREMENT )) { modop = LDAP_MOD_INCREMENT; mops[i] = M_SEP; nmods--; } else { /* no modify op: invalid LDIF */ fprintf( stderr, _("%s: modify operation type is missing at" " line %d, entry \"%s\"\n"), prog, linenum+i, dn ); rc = LDAP_PARAM_ERROR; goto leave; } bv = vals[i]; } else if ( expect_sep && BER_BVISEMPTY( btype+i )) { mops[i] = M_SEP; expect_sep = 0; expect_modop = 1; nmods--; } else { if ( !BV_CASEMATCH( btype+i, &bv )) { fprintf( stderr, _("%s: wrong attributeType at" " line %d, entry \"%s\"\n"), prog, linenum+i, dn ); rc = LDAP_PARAM_ERROR; goto leave; } mops[i] = modop; /* If prev op was deferred and matches this type, * clear the flag */ if ( (mops[i-1] & LDAP_MOD_BVALUES) && BV_CASEMATCH( btype+i, btype+i-1 )) { mops[i-1] = M_SEP; nmods--; } } } #if 0 /* we should faithfully encode the LDIF, not combine */ /* Make sure all modops with multiple values are contiguous */ for (i=idn; i<lines; i++) { if ( mops[i] == M_SEP ) continue; for (j=i+1; j<lines; j++) { if ( mops[j] == M_SEP || mops[i] != mops[j] ) continue; if ( BV_CASEMATCH( btype+i, btype+j )) { nmods--; /* out of order, move intervening attributes down */ if ( j != i+1 ) { int c; struct berval bv; char fv; c = mops[j]; bv = vals[j]; fv = freeval[j]; for (k=j; k>i; k--) { btype[k] = btype[k-1]; vals[k] = vals[k-1]; freeval[k] = freeval[k-1]; mops[k] = mops[k-1]; } k++; btype[k] = btype[i]; vals[k] = bv; freeval[k] = fv; mops[k] = c; } i++; } } } #endif /* Allocate space for array of mods, array of pointers to mods, * and array of pointers to values, allowing for NULL terminators * for the pointer arrays... */ lm = ber_memalloc( nmods * sizeof(LDAPMod) + (nmods+1) * sizeof(LDAPMod*) + (lines + nmods - idn) * sizeof(struct berval *)); pmods = (LDAPMod **)(lm+nmods); bvl = (struct berval **)(pmods+nmods+1); j = 0; k = -1; BER_BVZERO(&bv); mops[idn-1] = M_SEP; for (i=idn; i<lines; i++) { if ( mops[i] == M_SEP ) continue; if ( mops[i] != mops[i-1] || !BV_CASEMATCH( btype+i, &bv )) { bvl[k++] = NULL; bv = btype[i]; lm[j].mod_op = mops[i] | LDAP_MOD_BVALUES; lm[j].mod_type = bv.bv_val; if ( mops[i] & LDAP_MOD_BVALUES ) { lm[j].mod_bvalues = NULL; } else { lm[j].mod_bvalues = bvl+k; } pmods[j] = lm+j; j++; } bvl[k++] = vals+i; } bvl[k] = NULL; pmods[j] = NULL; doit: /* If default controls are set (as with -M option) and controls are specified in the LDIF file, we must add the default controls to the list of controls sent with the ldap operation. */ if ( rc == 0 ) { if (pctrls) { LDAPControl **defctrls = NULL; /* Default server controls */ LDAPControl **newctrls = NULL; ldap_get_option(ld, LDAP_OPT_SERVER_CONTROLS, &defctrls); if (defctrls) { int npc=0; /* Num of LDIF controls */ int ndefc=0; /* Num of default controls */ while (pctrls[npc]) npc++; /* Count LDIF controls */ while (defctrls[ndefc]) ndefc++; /* Count default controls */ newctrls = ber_memrealloc(pctrls, (npc+ndefc+1)*sizeof(LDAPControl*)); if (newctrls == NULL) { rc = LDAP_NO_MEMORY; } else { int i; pctrls = newctrls; for (i=npc; i<npc+ndefc; i++) { pctrls[i] = ldap_control_dup(defctrls[i-npc]); if (pctrls[i] == NULL) { rc = LDAP_NO_MEMORY; break; } } pctrls[npc+ndefc] = NULL; } ldap_controls_free(defctrls); /* Must be freed by library */ } } } if ( rc == 0 ) { if ( delete_entry ) { rc = dodelete( dn, pctrls ); } else if ( newrdn != NULL ) { rc = dorename( dn, newrdn, newsup, deleteoldrdn, pctrls ); } else { rc = domodify( dn, pmods, pctrls, new_entry ); } if ( rc == LDAP_SUCCESS ) { rc = 0; } } leave: if (pctrls != NULL) { ldap_controls_free( pctrls ); } if ( lm != NULL ) { ber_memfree( lm ); } if ( mops != NULL ) { ber_memfree( mops ); } for (i=lines-1; i>=0; i--) if ( freeval[i] ) ber_memfree( vals[i].bv_val ); ber_memfree( btype ); return( rc ); }
int dnssrv_back_referrals( Operation *op, SlapReply *rs ) { int i; int rc = LDAP_OTHER; char *domain = NULL; char *hostlist = NULL; char **hosts = NULL; BerVarray urls = NULL; if ( BER_BVISEMPTY( &op->o_req_dn ) ) { /* FIXME: need some means to determine whether the database * is a glue instance */ if ( SLAP_GLUE_INSTANCE( op->o_bd ) ) { return LDAP_SUCCESS; } rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed"; return LDAP_UNWILLING_TO_PERFORM; } if( get_manageDSAit( op ) ) { if( op->o_tag == LDAP_REQ_SEARCH ) { return LDAP_SUCCESS; } rs->sr_text = "DNS SRV problem processing manageDSAit control"; return LDAP_OTHER; } if( ldap_dn2domain( op->o_req_dn.bv_val, &domain ) || domain == NULL ) { rs->sr_err = LDAP_REFERRAL; rs->sr_ref = default_referral; send_ldap_result( op, rs ); rs->sr_ref = NULL; return LDAP_REFERRAL; } Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n", op->o_req_dn.bv_val, domain, 0 ); i = ldap_domain2hostlist( domain, &hostlist ); if ( i ) { Debug( LDAP_DEBUG_TRACE, "DNSSRV: domain2hostlist(%s) returned %d\n", domain, i, 0 ); rs->sr_text = "no DNS SRV RR available for DN"; rc = LDAP_NO_SUCH_OBJECT; goto done; } hosts = ldap_str2charray( hostlist, " " ); if( hosts == NULL ) { Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charrary error\n", 0, 0, 0 ); rs->sr_text = "problem processing DNS SRV records for DN"; goto done; } for( i=0; hosts[i] != NULL; i++) { struct berval url; url.bv_len = STRLENOF( "ldap://" ) + strlen( hosts[i] ); url.bv_val = ch_malloc( url.bv_len + 1 ); strcpy( url.bv_val, "ldap://" ); strcpy( &url.bv_val[STRLENOF( "ldap://" )], hosts[i] ); if ( ber_bvarray_add( &urls, &url ) < 0 ) { free( url.bv_val ); rs->sr_text = "problem processing DNS SRV records for DN"; goto done; } } Statslog( LDAP_DEBUG_STATS, "%s DNSSRV p=%d dn=\"%s\" url=\"%s\"\n", op->o_log_prefix, op->o_protocol, op->o_req_dn.bv_val, urls[0].bv_val, 0 ); Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> url=\"%s\"\n", op->o_req_dn.bv_val, urls[0].bv_val, 0 ); rs->sr_ref = urls; send_ldap_error( op, rs, LDAP_REFERRAL, "DNS SRV generated referrals" ); rs->sr_ref = NULL; rc = LDAP_REFERRAL; done: if( domain != NULL ) ch_free( domain ); if( hostlist != NULL ) ch_free( hostlist ); if( hosts != NULL ) ldap_charray_free( hosts ); ber_bvarray_free( urls ); return rc; }
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 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 dnssrv_back_search( Operation *op, SlapReply *rs ) { int i; int rc; char *domain = NULL; char *hostlist = NULL; char **hosts = NULL; char *refdn; struct berval nrefdn = BER_BVNULL; BerVarray urls = NULL; int manageDSAit; rs->sr_ref = NULL; if ( BER_BVISEMPTY( &op->o_req_ndn ) ) { /* FIXME: need some means to determine whether the database * is a glue instance; if we got here with empty DN, then * we passed this same test in dnssrv_back_referrals() */ if ( !SLAP_GLUE_INSTANCE( op->o_bd ) ) { rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed"; } else { rs->sr_err = LDAP_SUCCESS; } goto done; } manageDSAit = get_manageDSAit( op ); /* * FIXME: we may return a referral if manageDSAit is not set */ if ( !manageDSAit ) { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "manageDSAit must be set" ); goto done; } if( ldap_dn2domain( op->o_req_dn.bv_val, &domain ) || domain == NULL ) { rs->sr_err = LDAP_REFERRAL; rs->sr_ref = default_referral; send_ldap_result( op, rs ); rs->sr_ref = NULL; goto done; } Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n", op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", domain ); if( ( rc = ldap_domain2hostlist( domain, &hostlist ) ) ) { Debug( LDAP_DEBUG_TRACE, "DNSSRV: domain2hostlist returned %d\n", rc ); send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT, "no DNS SRV RR available for DN" ); goto done; } hosts = ldap_str2charray( hostlist, " " ); if( hosts == NULL ) { Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charray error\n" ); send_ldap_error( op, rs, LDAP_OTHER, "problem processing DNS SRV records for DN" ); goto done; } for( i=0; hosts[i] != NULL; i++) { struct berval url; url.bv_len = STRLENOF( "ldap://" ) + strlen(hosts[i]); url.bv_val = ch_malloc( url.bv_len + 1 ); strcpy( url.bv_val, "ldap://" ); strcpy( &url.bv_val[STRLENOF( "ldap://" )], hosts[i] ); if( ber_bvarray_add( &urls, &url ) < 0 ) { free( url.bv_val ); send_ldap_error( op, rs, LDAP_OTHER, "problem processing DNS SRV records for DN" ); goto done; } } Debug( LDAP_DEBUG_STATS, "%s DNSSRV p=%d dn=\"%s\" url=\"%s\"\n", op->o_log_prefix, op->o_protocol, op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", urls[0].bv_val ); Debug( LDAP_DEBUG_TRACE, "DNSSRV: ManageDSAit scope=%d dn=\"%s\" -> url=\"%s\"\n", op->oq_search.rs_scope, op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", urls[0].bv_val ); rc = ldap_domain2dn(domain, &refdn); if( rc != LDAP_SUCCESS ) { send_ldap_error( op, rs, LDAP_OTHER, "DNS SRV problem processing manageDSAit control" ); goto done; } else { struct berval bv; bv.bv_val = refdn; bv.bv_len = strlen( refdn ); rc = dnNormalize( 0, NULL, NULL, &bv, &nrefdn, op->o_tmpmemctx ); if( rc != LDAP_SUCCESS ) { send_ldap_error( op, rs, LDAP_OTHER, "DNS SRV problem processing manageDSAit control" ); goto done; } } if( !dn_match( &nrefdn, &op->o_req_ndn ) ) { /* requested dn is subordinate */ Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" subordinate to refdn=\"%s\"\n", op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", refdn == NULL ? "" : refdn ); rs->sr_matched = refdn; rs->sr_err = LDAP_NO_SUCH_OBJECT; send_ldap_result( op, rs ); rs->sr_matched = NULL; } else if ( op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL ) { send_ldap_error( op, rs, LDAP_SUCCESS, NULL ); } else { Entry e = { 0 }; AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; AttributeDescription *ad_ref = slap_schema.si_ad_ref; 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; e.e_attrs = NULL; e.e_private = NULL; attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_referral->soc_cname, NULL ); attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_extensibleObject->soc_cname, NULL ); if ( ad_dc ) { char *p; struct berval bv; bv.bv_val = domain; p = strchr( bv.bv_val, '.' ); if ( p == bv.bv_val ) { bv.bv_len = 1; } else if ( p != NULL ) { bv.bv_len = p - bv.bv_val; } else { bv.bv_len = strlen( bv.bv_val ); } attr_merge_normalize_one( &e, ad_dc, &bv, NULL ); } if ( ad_associatedDomain ) { struct berval bv; ber_str2bv( domain, 0, 0, &bv ); attr_merge_normalize_one( &e, ad_associatedDomain, &bv, NULL ); } attr_merge_normalize_one( &e, ad_ref, urls, NULL ); rc = test_filter( op, &e, op->oq_search.rs_filter ); if( rc == LDAP_COMPARE_TRUE ) { rs->sr_entry = &e; rs->sr_attrs = op->oq_search.rs_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); rs->sr_entry = NULL; rs->sr_attrs = NULL; rs->sr_flags = 0; } entry_clean( &e ); rs->sr_err = LDAP_SUCCESS; send_ldap_result( op, rs ); } free( refdn ); if ( nrefdn.bv_val ) free( nrefdn.bv_val ); done: if( domain != NULL ) ch_free( domain ); if( hostlist != NULL ) ch_free( hostlist ); if( hosts != NULL ) ldap_charray_free( hosts ); if( urls != NULL ) ber_bvarray_free( urls ); return 0; }
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; }