static int dds_op_rename( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; dds_info_t *di = on->on_bi.bi_private; if ( DDS_OFF( di ) ) { return SLAP_CB_CONTINUE; } /* we don't allow dynamicObjects to have static subordinates */ if ( op->orr_nnewSup != NULL ) { Entry *e = NULL; BackendInfo *bi = op->o_bd->bd_info; int is_dynamicObject = 0, rc; rs->sr_err = LDAP_SUCCESS; op->o_bd->bd_info = (BackendInfo *)on->on_info; rc = be_entry_get_rw( op, &op->o_req_ndn, slap_schema.si_oc_dynamicObject, NULL, 0, &e ); if ( rc == LDAP_SUCCESS && e != NULL ) { be_entry_release_r( op, e ); e = NULL; is_dynamicObject = 1; } rc = be_entry_get_rw( op, op->orr_nnewSup, slap_schema.si_oc_dynamicObject, NULL, 0, &e ); if ( rc == LDAP_SUCCESS && e != NULL ) { if ( !is_dynamicObject ) { /* return referral only if "disclose" * is granted on the object */ if ( ! access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; send_ldap_result( op, rs ); } else { send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION, "static entry cannot have dynamicObject as newSuperior" ); } } be_entry_release_r( op, e ); } op->o_bd->bd_info = bi; if ( rs->sr_err != LDAP_SUCCESS ) { return rs->sr_err; } } return SLAP_CB_CONTINUE; }
static int dds_op_delete( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; dds_info_t *di = on->on_bi.bi_private; /* if required, install counter callback */ if ( !DDS_OFF( di ) && di->di_max_dynamicObjects > 0 ) { Entry *e = NULL; BackendInfo *bi = op->o_bd->bd_info; op->o_bd->bd_info = (BackendInfo *)on->on_info; rs->sr_err = be_entry_get_rw( op, &op->o_req_ndn, slap_schema.si_oc_dynamicObject, NULL, 0, &e ); /* FIXME: couldn't the entry be added before deletion? */ if ( rs->sr_err == LDAP_SUCCESS && e != NULL ) { slap_callback *sc; be_entry_release_r( op, e ); e = NULL; sc = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx ); sc->sc_cleanup = dds_freeit_cb; sc->sc_response = dds_counter_cb; sc->sc_private = di; sc->sc_next = op->o_callback; op->o_callback = sc; } op->o_bd->bd_info = bi; } return SLAP_CB_CONTINUE; }
idattr_check_applyto ( Operation *op, Entry *target, AttributeDescription *searchAttr, idattr_t *id) { int rc = LDAP_INSUFFICIENT_ACCESS; int entry_rc = LDAP_NO_SUCH_OBJECT; Entry *theEntry = NULL; // is target a member of APPLYTO group // retrieve and cache dn of APPLYTO group if (BER_BVISNULL(&id->idattr_applyto_dn)) { idattr_id_to_dn (op,searchAttr, &(id->idattr_applyto_uuid), &(id->idattr_applyto_dn)); Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: len[%d] idattr_applyto_dn[%s] \n", id->idattr_applyto_dn.bv_len, id->idattr_applyto_dn.bv_val, 0 ); } if (!BER_BVISNULL(&id->idattr_applyto_dn)) { entry_rc = be_entry_get_rw( op, &target->e_nname, NULL , idattr_uuid, 0, &theEntry ); if (entry_rc == LDAP_SUCCESS && theEntry) { Attribute *uuidAttr = NULL; u_int32_t isMember = 0; uuidAttr = attr_find( theEntry->e_attrs, idattr_uuid); if (uuidAttr) { entry_rc = value_find_ex( idattr_uuid, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, uuidAttr->a_nvals, &(id->idattr_applyto_uuid), op->o_tmpmemctx ); if (entry_rc == LDAP_SUCCESS) { // TARGET == APPLYTO_TARGET rc = LDAP_SUCCESS; } else { // TARGET == MEMBEROF(APPLYTO) idattr_is_member ( op, &(id->idattr_applyto_dn), idattr_memberships, uuidAttr->a_nvals , &isMember); // flat list if (isMember) { rc = LDAP_SUCCESS; } } } } } exitonerror: if (theEntry) be_entry_release_r(op, theEntry); return rc; }
/* return 1 on success */ int nssov_dn2uid(Operation *op,nssov_info *ni,struct berval *dn,struct berval *uid) { nssov_mapinfo *mi = &ni->ni_maps[NM_passwd]; AttributeDescription *ad = mi->mi_attrs[UID_KEY].an_desc; Entry *e; /* check for empty string */ if (!dn->bv_len) return 0; /* try to look up uid within DN string */ if (!strncmp(dn->bv_val,ad->ad_cname.bv_val,ad->ad_cname.bv_len) && dn->bv_val[ad->ad_cname.bv_len] == '=') { struct berval bv, rdn; dnRdn(dn, &rdn); /* check if it is valid */ bv.bv_val = dn->bv_val + ad->ad_cname.bv_len + 1; bv.bv_len = rdn.bv_len - ad->ad_cname.bv_len - 1; if (!isvalidusername(&bv)) return 0; ber_dupbv_x( uid, &bv, op->o_tmpmemctx ); return 1; } /* look up the uid from the entry itself */ if (be_entry_get_rw( op, dn, NULL, ad, 0, &e) == LDAP_SUCCESS) { Attribute *a = attr_find(e->e_attrs, ad); if (a) { ber_dupbv_x(uid, &a->a_vals[0], op->o_tmpmemctx); } be_entry_release_r(op, e); if (a) return 1; } return 0; }
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 ); if ( pb->pb_rs->sr_flags & REP_ENTRY_MUSTBEFREED ) { entry_free( pb->pb_rs->sr_entry ); } else if ( pb->pb_rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { be_entry_release_r( pb->pb_op, pb->pb_rs->sr_entry ); pb->pb_rs->sr_flags ^= REP_ENTRY_MUSTRELEASE; } pb->pb_rs->sr_entry = (Slapi_Entry *)value; 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; }
idattr_check_isowner ( Operation *op, Entry *user, Entry *target, AttributeDescription *searchAttr, idattr_t *id) { int rc = LDAP_INSUFFICIENT_ACCESS; int entry_rc = LDAP_INSUFFICIENT_ACCESS; Entry *targetEntry = NULL; Entry *requestEntry = NULL; Attribute *ownerIDAttr = NULL; if (op->o_conn->c_authz.c_sai_krb5_auth_data_provisioned) { entry_rc = be_entry_get_rw( op, &target->e_nname, NULL, idattr_owneruuid, 0, &targetEntry ); // check target for owner if (entry_rc == LDAP_SUCCESS && targetEntry != NULL) { Attribute *theOwnerIDAttr = NULL; theOwnerIDAttr = attr_find( targetEntry->e_attrs, idattr_owneruuid); if (theOwnerIDAttr && ber_bvcmp(&op->o_conn->c_authz.c_sai_krb5_pac_id , &theOwnerIDAttr->a_nvals[0]) == 0) { rc = LDAP_SUCCESS; Debug(LDAP_DEBUG_ACL, "idattr_check_isowner by request[%s] - PROXYUSER BY TARGET\n", op->o_req_ndn.bv_val, 0, 0); } else { rc = LDAP_INSUFFICIENT_ACCESS; } } // check entry for owner if ((rc != LDAP_SUCCESS) && !BER_BVISNULL(&op->o_req_ndn)) { entry_rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, idattr_owneruuid, 0, &requestEntry ); if (entry_rc == LDAP_SUCCESS && requestEntry != NULL) { Attribute *theOwnerIDAttr = NULL; theOwnerIDAttr = attr_find( requestEntry->e_attrs, idattr_owneruuid); if (theOwnerIDAttr == NULL) { rc = LDAP_INSUFFICIENT_ACCESS; goto exitonerror; } if (ber_bvcmp(&op->o_conn->c_authz.c_sai_krb5_pac_id , &theOwnerIDAttr->a_nvals[0]) == 0) { rc = LDAP_SUCCESS; Debug(LDAP_DEBUG_ACL, "idattr_check_isowner by request[%s] - PROXYUSER BY ENTRY\n", op->o_req_ndn.bv_val, 0, 0); } } } } else { if (user == NULL) { rc = LDAP_INSUFFICIENT_ACCESS; goto exitonerror; } ownerIDAttr = attr_find( user->e_attrs, searchAttr); if (ownerIDAttr == NULL) { rc = LDAP_INSUFFICIENT_ACCESS; goto exitonerror; } entry_rc = be_entry_get_rw( op, &target->e_nname, NULL, idattr_owneruuid, 0, &targetEntry ); if (entry_rc == LDAP_SUCCESS && targetEntry != NULL) { Attribute *theAttr = NULL; theAttr = attr_find( targetEntry->e_attrs, idattr_owneruuid); if (theAttr) { entry_rc = value_find_ex( idattr_owneruuid, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, theAttr->a_nvals, ownerIDAttr->a_nvals, op->o_tmpmemctx ); if (entry_rc == LDAP_SUCCESS) { rc = LDAP_SUCCESS; Debug(LDAP_DEBUG_ACL, "idattr_check_isowner by target[%s]\n", target->e_nname.bv_val, 0, 0); } // check group membership if applicable if (rc != LDAP_SUCCESS) { u_int32_t isMember = 0; if (BER_BVISNULL(&id->idattr_owner_dn)) { idattr_id_to_dn (op,searchAttr, theAttr->a_nvals, &id->idattr_owner_dn); } if (!BER_BVISNULL(&id->idattr_owner_dn) && strstr(id->idattr_owner_dn.bv_val, group_subtree) != NULL) { Debug( LDAP_DEBUG_ACL, "idattr_check_isowner: len[%d] idattr_owner_dn[%s] \n", id->idattr_owner_dn.bv_len, id->idattr_owner_dn.bv_val, 0 ); idattr_is_member ( op, &id->idattr_owner_dn, idattr_memberships, ownerIDAttr->a_nvals , &isMember); if (isMember) { Debug( LDAP_DEBUG_ACL, "idattr_check_isowner: user is member of Group (from target)\n", 0, 0, 0 ); rc = LDAP_SUCCESS; } } } } } // check op->o_req_ndn // target: cn=record,dc=com // request_dn: cn=myrecord,cn=record,dc=com // access to the parent (target) is required prior to requesting right access to the child (request_dn) // lookahead at the child to check for ownership if ((rc != LDAP_SUCCESS) && !BER_BVISNULL(&op->o_req_ndn)) { entry_rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, idattr_owneruuid, 0, &requestEntry ); if (entry_rc == LDAP_SUCCESS && requestEntry != NULL) { Attribute *theAttr = NULL; theAttr = attr_find( requestEntry->e_attrs, idattr_owneruuid); if (theAttr) { entry_rc = value_find_ex( idattr_owneruuid, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, theAttr->a_nvals, ownerIDAttr->a_nvals, op->o_tmpmemctx ); if (entry_rc == LDAP_SUCCESS) { rc = LDAP_SUCCESS; Debug(LDAP_DEBUG_ACL, "idattr_check_isowner by request[%s]\n", op->o_req_ndn.bv_val, 0, 0); } // check group membership if applicable u_int32_t isMember = 0; if (BER_BVISNULL(&id->idattr_owner_dn)) { idattr_id_to_dn (op,searchAttr, theAttr->a_nvals, &id->idattr_owner_dn); } if (!BER_BVISNULL(&id->idattr_owner_dn) && strstr(id->idattr_owner_dn.bv_val, group_subtree) != NULL) { Debug( LDAP_DEBUG_ACL, "idattr_check_isowner: len[%d] id->idattr_owner_dn[%s] \n", id->idattr_owner_dn.bv_len, id->idattr_owner_dn.bv_val, 0 ); idattr_is_member ( op, &id->idattr_owner_dn, idattr_memberships, ownerIDAttr->a_nvals , &isMember); if (isMember) { Debug( LDAP_DEBUG_ACL, "idattr_check_isowner: user is member of Group (by parent)\n", 0, 0, 0 ); rc = LDAP_SUCCESS; } } } } } } exitonerror: if (targetEntry) be_entry_release_r(op, targetEntry); if (requestEntry) be_entry_release_r(op, requestEntry); return rc; }
idattr_check_selfwrite ( Operation *op, Entry *target, Entry *user, struct berval* val, idattr_t *id) { int rc = LDAP_INSUFFICIENT_ACCESS; int entry_rc = LDAP_INSUFFICIENT_ACCESS; int bool_rc = LDAP_INSUFFICIENT_ACCESS; Entry *targetEntry = NULL; Attribute *theAttr = NULL; int match = 0; const char *dummy = NULL; struct berval bool_true_val; if ( val == NULL || user == NULL ) { rc = LDAP_INSUFFICIENT_ACCESS; goto exitonerror; } if (op->o_conn->c_authz.c_sai_krb5_auth_data_provisioned) { rc = LDAP_INSUFFICIENT_ACCESS; goto exitonerror; } if (id->idattr_boolattrDesc) { entry_rc = be_entry_get_rw( op, &target->e_nname, NULL, id->idattr_boolattrDesc, 0, &targetEntry ); if (entry_rc == LDAP_SUCCESS && targetEntry != NULL) { theAttr = attr_find( targetEntry->e_attrs, id->idattr_boolattrDesc); if (theAttr != NULL) { ber_str2bv( "1", 0, 0, &bool_true_val ); bool_rc = value_match( &match, id->idattr_boolattrDesc, id->idattr_boolattrDesc->ad_type->sat_equality, 0, &bool_true_val, &theAttr->a_nvals[ 0 ], &dummy ); if ( bool_rc != LDAP_SUCCESS || match != 0 ) { rc = LDAP_INSUFFICIENT_ACCESS; goto exitonerror; } } else { rc = LDAP_INSUFFICIENT_ACCESS; goto exitonerror; } } else { rc = LDAP_INSUFFICIENT_ACCESS; goto exitonerror; } } theAttr = attr_find( user->e_attrs, id->idattr_selfattrDesc); // user unique ID if ( !theAttr || !BER_BVISNULL( &theAttr->a_nvals[ 1 ] ) ) { rc = LDAP_NO_SUCH_ATTRIBUTE; } else { rc = value_match( &match, id->idattr_selfattrDesc, id->idattr_selfattrDesc->ad_type->sat_equality, 0, val, &theAttr->a_nvals[ 0 ], &dummy ); if ( rc != LDAP_SUCCESS || match != 0 ) rc = LDAP_INSUFFICIENT_ACCESS; } Debug(LDAP_DEBUG_ACL, "[%d]idattr_check_selfwrite match[%d]\n", rc, match, 0); exitonerror: if (targetEntry) be_entry_release_r(op, targetEntry); return rc; }
static int translucent_search_cb(Operation *op, SlapReply *rs) { trans_ctx *tc; BackendDB *db; slap_overinst *on; translucent_info *ov; Entry *le, *re; Attribute *a, *ax, *an, *as = NULL; int rc; int test_f = 0; tc = op->o_callback->sc_private; /* Don't let the op complete while we're gathering data */ if ( rs->sr_type == REP_RESULT && ( tc->step & USE_LIST )) return 0; if(rs->sr_type != REP_SEARCH || !rs->sr_entry) return(SLAP_CB_CONTINUE); Debug(LDAP_DEBUG_TRACE, "==> translucent_search_cb: %s\n", rs->sr_entry->e_name.bv_val, 0, 0); op->ors_slimit = tc->slimit + ( tc->slimit > 0 ? 1 : 0 ); if ( op->ors_attrs == slap_anlist_all_attributes ) { op->ors_attrs = tc->attrs; rs->sr_attrs = tc->attrs; rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs ); } on = tc->on; ov = on->on_bi.bi_private; db = op->o_bd; re = NULL; /* If we have local, get remote */ if ( tc->step & LCL_SIDE ) { le = rs->sr_entry; /* If entry is already on list, use it */ if ( tc->step & USE_LIST ) { re = tavl_delete( &tc->list, le, entry_dn_cmp ); if ( re ) { rs_flush_entry( op, rs, on ); rc = test_filter( op, re, tc->orig ); if ( rc == LDAP_COMPARE_TRUE ) { rs->sr_flags |= REP_ENTRY_MUSTBEFREED; rs->sr_entry = re; if ( tc->slimit >= 0 && rs->sr_nentries >= tc->slimit ) { return LDAP_SIZELIMIT_EXCEEDED; } return SLAP_CB_CONTINUE; } else { entry_free( re ); rs->sr_entry = NULL; return 0; } } } op->o_bd = &ov->db; rc = be_entry_get_rw( op, &rs->sr_entry->e_nname, NULL, NULL, 0, &re ); if ( rc == LDAP_SUCCESS && re ) { Entry *tmp = entry_dup( re ); be_entry_release_r( op, re ); re = tmp; test_f = 1; } } else { /* Else we have remote, get local */ op->o_bd = tc->db; le = NULL; rc = overlay_entry_get_ov(op, &rs->sr_entry->e_nname, NULL, NULL, 0, &le, on); if ( rc == LDAP_SUCCESS && le ) { re = entry_dup( rs->sr_entry ); rs_flush_entry( op, rs, on ); } else { le = NULL; } } /* ** if we got remote and local entry: ** foreach local attr: ** foreach remote attr: ** if match, remote attr with local attr; ** if new local, add to list; ** append new local attrs to remote; ** */ if ( re && le ) { for(ax = le->e_attrs; ax; ax = ax->a_next) { for(a = re->e_attrs; a; a = a->a_next) { if(a->a_desc == ax->a_desc) { test_f = 1; if(a->a_vals != a->a_nvals) ber_bvarray_free(a->a_nvals); ber_bvarray_free(a->a_vals); ber_bvarray_dup_x( &a->a_vals, ax->a_vals, NULL ); if ( ax->a_vals == ax->a_nvals ) { a->a_nvals = a->a_vals; } else { ber_bvarray_dup_x( &a->a_nvals, ax->a_nvals, NULL ); } break; } } if(a) continue; an = attr_dup(ax); an->a_next = as; as = an; } /* Dispose of local entry */ if ( tc->step & LCL_SIDE ) { rs_flush_entry(op, rs, on); } else { overlay_entry_release_ov(op, le, 0, on); } /* literally append, so locals are always last */ if(as) { if(re->e_attrs) { for(ax = re->e_attrs; ax->a_next; ax = ax->a_next); ax->a_next = as; } else { re->e_attrs = as; } } /* If both filters, save entry for later */ if ( tc->step == (USE_LIST|RMT_SIDE) ) { tavl_insert( &tc->list, re, entry_dn_cmp, avl_dup_error ); rs->sr_entry = NULL; rc = 0; } else { /* send it now */ rs->sr_entry = re; rs->sr_flags |= REP_ENTRY_MUSTBEFREED; if ( test_f ) { rc = test_filter( op, rs->sr_entry, tc->orig ); if ( rc == LDAP_COMPARE_TRUE ) { rc = SLAP_CB_CONTINUE; } else { rc = 0; } } else { rc = SLAP_CB_CONTINUE; } } } else if ( le ) { /* Only a local entry: remote was deleted * Ought to delete the local too... */ rc = 0; } else if ( tc->step & USE_LIST ) { /* Only a remote entry, but both filters: * Test the complete filter */ rc = test_filter( op, rs->sr_entry, tc->orig ); if ( rc == LDAP_COMPARE_TRUE ) { rc = SLAP_CB_CONTINUE; } else { rc = 0; } } else { /* Only a remote entry, only remote filter: * just pass thru */ rc = SLAP_CB_CONTINUE; } op->o_bd = db; if ( rc == SLAP_CB_CONTINUE && tc->slimit >= 0 && rs->sr_nentries >= tc->slimit ) { return LDAP_SIZELIMIT_EXCEEDED; } return rc; }
static int idattr_dynacl_mask( void *priv, Operation *op, Entry *target, AttributeDescription *desc, struct berval *val, int nmatch, regmatch_t *matches, slap_access_t *grant, slap_access_t *deny ) { idattr_t *id = (idattr_t *)priv; Entry *user = NULL; int rc = LDAP_INSUFFICIENT_ACCESS; int user_rc = LDAP_INSUFFICIENT_ACCESS; int target_rc = LDAP_INSUFFICIENT_ACCESS; Backend *be = op->o_bd, *group_be = NULL, *user_be = NULL; AttributeDescription *searchAttr = NULL; ObjectClass *searchObject = NULL; struct berval *searchTarget = NULL; Entry *searchEntry = NULL; ACL_INVALIDATE( *deny ); Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: pat(%s) type(%d) op(%d)\n", id->idattr_pat.bv_val, id->idattr_type, id->idattr_ops ); Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: target(%s) op->o_ndn(%s)\n", target->e_nname.bv_val, op->o_ndn.bv_val, 0 ); if (id->idattr_ops && (id->idattr_ops != op->o_tag)) { Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: Operation Not Allowed - Ops allowed (%d), Requested Op (%d)\n", id->idattr_ops, op->o_tag, 0 ); // LDAP_INSUFFICIENT_ACCESS return 0; } if (!op->o_conn->c_authz.c_sai_krb5_auth_data_provisioned) { user_be = op->o_bd = select_backend( &op->o_ndn, 0); if ( op->o_bd == NULL ) { Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: op->o_bd == NULL \n", 0, 0, 0 ); op->o_bd = be; return 0; } } // check ACL TYPE Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: idattr_type(%d)\n", id->idattr_type, 0, 0 ); if (id->idattr_type == UUID_TYPE || id->idattr_type == OWNER_TYPE) { searchAttr = idattr_uuid; searchObject = idattr_extensible_object; searchTarget = &op->o_ndn; } else if (id->idattr_type == SID_TYPE) { searchAttr = idattr_sid; searchObject = idattr_extensible_object; searchTarget = &op->o_conn->c_authz.sai_ndn; } else if (id->idattr_type == SELFWRITE_TYPE) { searchAttr = id->idattr_selfattrDesc; searchObject = idattr_extensible_object; searchTarget = &op->o_ndn; } else if (id->idattr_type == USERS_TYPE) { if (BER_BVISEMPTY( &op->o_ndn )) { // LDAP_INSUFFICIENT_ACCESS op->o_bd = be; return 0; } else { // check for APPLYTO clause if (id->idattr_applyto) { rc = idattr_check_applyto(op, target, searchAttr, id); } else { rc = LDAP_SUCCESS; } goto assignaccess; } } else { Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: unknown idattr_type(%s)\n", id->idattr_type, 0, 0 ); // LDAP_INSUFFICIENT_ACCESS return 0; } if (op->o_conn->c_authz.c_sai_krb5_auth_data_provisioned) { user_rc = LDAP_SUCCESS; } else if (searchAttr) { // lookup user record user_rc = be_entry_get_rw( op, searchTarget, NULL, searchAttr, 0, &user ); Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: be_entry_get_rw user_rc(%d) user(%x) \n", user_rc, user, 0 ); if ( user_rc != LDAP_SUCCESS || user == NULL ) { op->o_bd = be; return 0; } } if ( user_rc == LDAP_SUCCESS || user != NULL ) { user_rc = idattr_check_isuser(op, user, searchAttr, id); if (user_rc == LDAP_SUCCESS) { switch ( id->idattr_type ) { case SELFWRITE_TYPE: user_rc = idattr_check_selfwrite(op, target, user, val, id); break; case OWNER_TYPE: user_rc = idattr_check_isowner(op, user, target, searchAttr, id); break; case UUID_TYPE: case SID_TYPE: user_rc = LDAP_SUCCESS; break; default: break; } if (user_rc == LDAP_SUCCESS) { if (id->idattr_applyto) { rc = idattr_check_applyto(op, target, searchAttr, id); } else { rc = LDAP_SUCCESS; } } } } else { rc = LDAP_NO_SUCH_OBJECT; } assignaccess: if ( rc == LDAP_SUCCESS ) { ACL_LVL_ASSIGN_WRITE( *grant ); } cleanup: if ( user != NULL) { op->o_bd = user_be; be_entry_release_r( op, user ); op->o_bd = be; } op->o_bd = be; return 0; }
static int dds_op_add( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; dds_info_t *di = on->on_bi.bi_private; int is_dynamicObject; if ( DDS_OFF( di ) ) { return SLAP_CB_CONTINUE; } is_dynamicObject = is_entry_dynamicObject( op->ora_e ); /* FIXME: do not allow this right now, pending clarification */ if ( is_dynamicObject ) { rs->sr_err = LDAP_SUCCESS; if ( is_entry_referral( op->ora_e ) ) { rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION; rs->sr_text = "a referral cannot be a dynamicObject"; } else if ( is_entry_alias( op->ora_e ) ) { rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION; rs->sr_text = "an alias cannot be a dynamicObject"; } if ( rs->sr_err != LDAP_SUCCESS ) { op->o_bd->bd_info = (BackendInfo *)on->on_info; send_ldap_result( op, rs ); return rs->sr_err; } } /* we don't allow dynamicObjects to have static subordinates */ if ( !dn_match( &op->o_req_ndn, &op->o_bd->be_nsuffix[ 0 ] ) ) { struct berval p_ndn; Entry *e = NULL; int rc; BackendInfo *bi = op->o_bd->bd_info; dnParent( &op->o_req_ndn, &p_ndn ); op->o_bd->bd_info = (BackendInfo *)on->on_info; rc = be_entry_get_rw( op, &p_ndn, slap_schema.si_oc_dynamicObject, NULL, 0, &e ); if ( rc == LDAP_SUCCESS && e != NULL ) { if ( !is_dynamicObject ) { /* return referral only if "disclose" * is granted on the object */ if ( ! access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rc = rs->sr_err = LDAP_NO_SUCH_OBJECT; send_ldap_result( op, rs ); } else { rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION; send_ldap_error( op, rs, rc, "no static subordinate entries allowed for dynamicObject" ); } } be_entry_release_r( op, e ); if ( rc != LDAP_SUCCESS ) { return rc; } } op->o_bd->bd_info = bi; } /* handle dynamic object operational attr(s) */ if ( is_dynamicObject ) { time_t ttl, expire; char ttlbuf[STRLENOF("31557600") + 1]; char tsbuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; struct berval bv; if ( !be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) { ldap_pvt_thread_mutex_lock( &di->di_mutex ); rs->sr_err = ( di->di_max_dynamicObjects && di->di_num_dynamicObjects >= di->di_max_dynamicObjects ); ldap_pvt_thread_mutex_unlock( &di->di_mutex ); if ( rs->sr_err ) { op->o_bd->bd_info = (BackendInfo *)on->on_info; send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "too many dynamicObjects in context" ); return rs->sr_err; } } ttl = DDS_DEFAULT_TTL( di ); /* assert because should be checked at configure */ assert( ttl <= DDS_RF2589_MAX_TTL ); bv.bv_val = ttlbuf; bv.bv_len = snprintf( ttlbuf, sizeof( ttlbuf ), "%ld", ttl ); assert( bv.bv_len < sizeof( ttlbuf ) ); /* FIXME: apparently, values in op->ora_e are malloc'ed * on the thread's slab; works fine by chance, * only because the attribute doesn't exist yet. */ assert( attr_find( op->ora_e->e_attrs, slap_schema.si_ad_entryTtl ) == NULL ); attr_merge_one( op->ora_e, slap_schema.si_ad_entryTtl, &bv, &bv ); expire = slap_get_time() + ttl; bv.bv_val = tsbuf; bv.bv_len = sizeof( tsbuf ); slap_timestamp( &expire, &bv ); assert( attr_find( op->ora_e->e_attrs, ad_entryExpireTimestamp ) == NULL ); attr_merge_one( op->ora_e, ad_entryExpireTimestamp, &bv, &bv ); /* if required, install counter callback */ if ( di->di_max_dynamicObjects > 0) { slap_callback *sc; sc = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx ); sc->sc_cleanup = dds_freeit_cb; sc->sc_response = dds_counter_cb; sc->sc_private = di; sc->sc_next = op->o_callback; op->o_callback = sc; } } return SLAP_CB_CONTINUE; }
static int translucent_pwmod(Operation *op, SlapReply *rs) { SlapReply nrs = { REP_RESULT }; Operation nop; slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; translucent_info *ov = on->on_bi.bi_private; Entry *e = NULL, *re = NULL; BackendDB *db; int rc = 0; slap_callback cb = { 0 }; if (!ov->pwmod_local) { rs->sr_err = LDAP_CONSTRAINT_VIOLATION, rs->sr_text = "attempt to modify password in local database"; return rs->sr_err; } /* ** fetch entry from the captive backend; ** if it did not exist, fail; ** release it, if captive backend supports this; ** */ db = op->o_bd; op->o_bd = &ov->db; ov->db.be_acl = op->o_bd->be_acl; rc = ov->db.bd_info->bi_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &re); if(rc != LDAP_SUCCESS || re == NULL ) { send_ldap_error((op), rs, LDAP_NO_SUCH_OBJECT, "attempt to modify nonexistent local record"); return(rs->sr_err); } op->o_bd = db; /* ** fetch entry from local backend; ** if it exists: ** return CONTINUE; */ op->o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig; rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &e); op->o_bd->bd_info = (BackendInfo *) on; if(e && rc == LDAP_SUCCESS) { if(re) { if(ov->db.bd_info->bi_entry_release_rw) { op->o_bd = &ov->db; ov->db.bd_info->bi_entry_release_rw(op, re, 0); op->o_bd = db; } else { entry_free(re); } } op->o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig; be_entry_release_r(op, e); op->o_bd->bd_info = (BackendInfo *) on; return SLAP_CB_CONTINUE; } /* don't leak remote entry copy */ if(re) { if(ov->db.bd_info->bi_entry_release_rw) { op->o_bd = &ov->db; ov->db.bd_info->bi_entry_release_rw(op, re, 0); op->o_bd = db; } else { entry_free(re); } } /* ** glue_parent() for this Entry; ** call bi_op_add() in local backend; ** */ e = entry_alloc(); ber_dupbv( &e->e_name, &op->o_req_dn ); ber_dupbv( &e->e_nname, &op->o_req_ndn ); e->e_attrs = NULL; nop = *op; nop.o_tag = LDAP_REQ_ADD; cb.sc_response = slap_null_cb; nop.oq_add.rs_e = e; glue_parent(&nop); nop.o_callback = &cb; rc = on->on_info->oi_orig->bi_op_add(&nop, &nrs); if ( nop.ora_e == e ) { entry_free( e ); } if ( rc == LDAP_SUCCESS ) { return SLAP_CB_CONTINUE; } return rc; }
static int slapi_over_acl_group( Operation *op, Entry *target, struct berval *gr_ndn, struct berval *op_ndn, ObjectClass *group_oc, AttributeDescription *group_at ) { Slapi_Entry *e; int rc; Slapi_PBlock *pb; BackendDB *be = op->o_bd; GroupAssertion *g; SlapReply rs = { REP_RESULT }; op->o_bd = select_backend( gr_ndn, 0 ); for ( g = op->o_groups; g; g = g->ga_next ) { if ( g->ga_be != op->o_bd || g->ga_oc != group_oc || g->ga_at != group_at || g->ga_len != gr_ndn->bv_len ) { continue; } if ( strcmp( g->ga_ndn, gr_ndn->bv_val ) == 0 ) { break; } } if ( g != NULL ) { rc = g->ga_res; goto done; } if ( target != NULL && dn_match( &target->e_nname, gr_ndn ) ) { e = target; rc = 0; } else { rc = be_entry_get_rw( op, gr_ndn, group_oc, group_at, 0, &e ); } if ( e != NULL ) { int internal_op; slap_callback cb; internal_op = slapi_op_internal_p( op, &rs, &cb ); cb.sc_response = NULL; cb.sc_cleanup = NULL; pb = SLAPI_OPERATION_PBLOCK( op ); slapi_pblock_set( pb, SLAPI_X_GROUP_ENTRY, (void *)e ); slapi_pblock_set( pb, SLAPI_X_GROUP_OPERATION_DN, (void *)op_ndn->bv_val ); slapi_pblock_set( pb, SLAPI_X_GROUP_ATTRIBUTE, (void *)group_at->ad_cname.bv_val ); slapi_pblock_set( pb, SLAPI_X_GROUP_TARGET_ENTRY, (void *)target ); rc = slapi_over_call_plugins( pb, SLAPI_X_PLUGIN_PRE_GROUP_FN ); if ( rc >= 0 ) /* 1 means no plugins called */ rc = SLAP_CB_CONTINUE; else rc = pb->pb_rs->sr_err; slapi_pblock_delete_param( pb, SLAPI_X_GROUP_ENTRY ); slapi_pblock_delete_param( pb, SLAPI_X_GROUP_OPERATION_DN ); slapi_pblock_delete_param( pb, SLAPI_X_GROUP_ATTRIBUTE ); slapi_pblock_delete_param( pb, SLAPI_X_GROUP_TARGET_ENTRY ); if ( !internal_op ) slapi_pblock_destroy( pb ); if ( e != target ) { be_entry_release_r( op, e ); } op->o_callback = cb.sc_next; } else { rc = LDAP_NO_SUCH_OBJECT; /* return SLAP_CB_CONTINUE for correctness? */ } if ( op->o_tag != LDAP_REQ_BIND && !op->o_do_not_cache && rc != SLAP_CB_CONTINUE ) { g = op->o_tmpalloc( sizeof( GroupAssertion ) + gr_ndn->bv_len, op->o_tmpmemctx ); g->ga_be = op->o_bd; g->ga_oc = group_oc; g->ga_at = group_at; g->ga_res = rc; g->ga_len = gr_ndn->bv_len; strcpy( g->ga_ndn, gr_ndn->bv_val ); g->ga_next = op->o_groups; op->o_groups = g; } /* * XXX don't call POST_GROUP_FN, I have no idea what the point of * that plugin function was anyway */ done: op->o_bd = be; return rc; }
int slapschema( int argc, char **argv ) { ID id; int rc = EXIT_SUCCESS; const char *progname = "slapschema"; Connection conn = { 0 }; OperationBuffer opbuf; Operation *op = NULL; void *thrctx; int requestBSF = 0; int doBSF = 0; slap_tool_init( progname, SLAPCAT, argc, argv ); requestBSF = ( sub_ndn.bv_len || filter ); #ifdef SIGPIPE (void) SIGNAL( SIGPIPE, slapcat_sig ); #endif #ifdef SIGHUP (void) SIGNAL( SIGHUP, slapcat_sig ); #endif (void) SIGNAL( SIGINT, slapcat_sig ); (void) SIGNAL( SIGTERM, slapcat_sig ); if( !be->be_entry_open || !be->be_entry_close || !( be->be_entry_first || be->be_entry_first_x ) || !be->be_entry_next || !be->be_entry_get ) { fprintf( stderr, "%s: database doesn't support necessary operations.\n", progname ); exit( EXIT_FAILURE ); } if( be->be_entry_open( be, 0 ) != 0 ) { fprintf( stderr, "%s: could not open database.\n", progname ); exit( EXIT_FAILURE ); } thrctx = ldap_pvt_thread_pool_context(); connection_fake_init( &conn, &opbuf, thrctx ); op = &opbuf.ob_op; op->o_tmpmemctx = NULL; op->o_bd = be; if ( !requestBSF && be->be_entry_first ) { id = be->be_entry_first( be ); } else { if ( be->be_entry_first_x ) { id = be->be_entry_first_x( be, sub_ndn.bv_len ? &sub_ndn : NULL, scope, filter ); } else { assert( be->be_entry_first != NULL ); doBSF = 1; id = be->be_entry_first( be ); } } for ( ; id != NOID; id = be->be_entry_next( be ) ) { Entry* e; char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof(textbuf); const char *text = NULL; if ( gotsig ) break; e = be->be_entry_get( be, id ); if ( e == NULL ) { printf("# no data for entry id=%08lx\n\n", (long) id ); rc = EXIT_FAILURE; if( continuemode ) continue; break; } if ( doBSF ) { if ( sub_ndn.bv_len && !dnIsSuffixScope( &e->e_nname, &sub_ndn, scope ) ) { be_entry_release_r( op, e ); continue; } if ( filter != NULL ) { int rc = test_filter( NULL, e, filter ); if ( rc != LDAP_COMPARE_TRUE ) { be_entry_release_r( op, e ); continue; } } } if( verbose ) { printf( "# id=%08lx\n", (long) id ); } rc = entry_schema_check( op, e, NULL, 0, 0, NULL, &text, textbuf, textlen ); if ( rc != LDAP_SUCCESS ) { fprintf( ldiffp->fp, "# (%d) %s%s%s\n", rc, ldap_err2string( rc ), text ? ": " : "", text ? text : "" ); fprintf( ldiffp->fp, "dn: %s\n\n", e->e_name.bv_val ); } be_entry_release_r( op, e ); } be->be_entry_close( be ); if ( slap_tool_destroy() ) rc = EXIT_FAILURE; return rc; }
static int pg_dynacl_mask( void *priv, Operation *op, Entry *target, AttributeDescription *desc, struct berval *val, int nmatch, regmatch_t *matches, slap_access_t *grant, slap_access_t *deny ) { pg_t *pg = (pg_t *)priv; Entry *group = NULL, *user = NULL; int rc; Backend *be = op->o_bd, *group_be = NULL, *user_be = NULL; struct berval group_ndn; ACL_INVALIDATE( *deny ); /* get user */ if ( target && dn_match( &target->e_nname, &op->o_ndn ) ) { user = target; rc = LDAP_SUCCESS; } else { user_be = op->o_bd = select_backend( &op->o_ndn, 0 ); if ( op->o_bd == NULL ) { op->o_bd = be; return 0; } rc = be_entry_get_rw( op, &op->o_ndn, pg_posixAccount, pg_uidNumber, 0, &user ); } if ( rc != LDAP_SUCCESS || user == NULL ) { op->o_bd = be; return 0; } /* get target */ if ( pg->pg_style == ACL_STYLE_EXPAND ) { char buf[ 1024 ]; struct berval bv; AclRegexMatches amatches = { 0 }; amatches.dn_count = nmatch; AC_MEMCPY( amatches.dn_data, matches, sizeof( amatches.dn_data ) ); bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; if ( acl_string_expand( &bv, &pg->pg_pat, &target->e_nname, NULL, &amatches ) ) { goto cleanup; } if ( dnNormalize( 0, NULL, NULL, &bv, &group_ndn, op->o_tmpmemctx ) != LDAP_SUCCESS ) { /* did not expand to a valid dn */ goto cleanup; } } else { group_ndn = pg->pg_pat; } if ( target && dn_match( &target->e_nname, &group_ndn ) ) { group = target; rc = LDAP_SUCCESS; } else { group_be = op->o_bd = select_backend( &group_ndn, 0 ); if ( op->o_bd == NULL ) { goto cleanup; } rc = be_entry_get_rw( op, &group_ndn, pg_posixGroup, pg_memberUid, 0, &group ); } if ( group_ndn.bv_val != pg->pg_pat.bv_val ) { op->o_tmpfree( group_ndn.bv_val, op->o_tmpmemctx ); } if ( rc == LDAP_SUCCESS && group != NULL ) { Attribute *a_uid, *a_member; a_uid = attr_find( user->e_attrs, pg_uidNumber ); if ( !a_uid || !BER_BVISNULL( &a_uid->a_nvals[ 1 ] ) ) { rc = LDAP_NO_SUCH_ATTRIBUTE; } else { a_member = attr_find( group->e_attrs, pg_memberUid ); if ( !a_member ) { rc = LDAP_NO_SUCH_ATTRIBUTE; } else { rc = value_find_ex( pg_memberUid, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, a_member->a_nvals, &a_uid->a_nvals[ 0 ], op->o_tmpmemctx ); } } } else { rc = LDAP_NO_SUCH_OBJECT; } if ( rc == LDAP_SUCCESS ) { ACL_LVL_ASSIGN_WRITE( *grant ); } cleanup:; if ( group != NULL && group != target ) { op->o_bd = group_be; be_entry_release_r( op, group ); op->o_bd = be; } if ( user != NULL && user != target ) { op->o_bd = user_be; be_entry_release_r( op, user ); op->o_bd = be; } return 0; }
static int nops_modify( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; Backend *be = op->o_bd; Entry *target_entry = NULL; Modifications *m; int rc; if ((m = op->orm_modlist) == NULL) { op->o_bd->bd_info = (BackendInfo *)(on->on_info); send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, "nops() got null orm_modlist"); return(rs->sr_err); } op->o_bd = on->on_info->oi_origdb; rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &target_entry); op->o_bd = be; if (rc != 0 || target_entry == NULL) return 0; /* * For each attribute modification, check if the * modification and the old entry are the same. */ while (m) { int i, j; int found; Attribute *a; BerVarray bm; BerVarray bt; Modifications *mc; mc = m; m = m->sml_next; /* Check only replace sub-operations */ if ((mc->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE) continue; /* If there is no values, skip */ if (((bm = mc->sml_values ) == NULL ) || (bm[0].bv_val == NULL)) continue; /* If the attribute does not exist in old entry, skip */ if ((a = attr_find(target_entry->e_attrs, mc->sml_desc)) == NULL) continue; if ((bt = a->a_vals) == NULL) continue; /* For each value replaced, do we find it in old entry? */ found = 0; for (i = 0; bm[i].bv_val; i++) { for (j = 0; bt[j].bv_val; j++) { if (bm[i].bv_len != bt[j].bv_len) continue; if (memcmp(bm[i].bv_val, bt[j].bv_val, bt[j].bv_len) != 0) continue; found++; break; } } /* Did we find as many values as we had in old entry? */ if (i != a->a_numvals || found != a->a_numvals) continue; /* This is a nop, remove it */ Debug(LDAP_DEBUG_TRACE, "removing nop on %s%s%s", a->a_desc->ad_cname.bv_val, "", ""); nops_rm_mod(&op->orm_modlist, mc); } if (target_entry) { op->o_bd = on->on_info->oi_origdb; be_entry_release_r(op, target_entry); op->o_bd = be; } if ((m = op->orm_modlist) == NULL) { slap_callback *cb = op->o_callback; op->o_bd->bd_info = (BackendInfo *)(on->on_info); op->o_callback = NULL; send_ldap_error(op, rs, LDAP_SUCCESS, ""); op->o_callback = cb; return (rs->sr_err); } return SLAP_CB_CONTINUE; }
static int constraint_update( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; Backend *be = op->o_bd; constraint *c = on->on_bi.bi_private, *cp; Entry *target_entry = NULL, *target_entry_copy = NULL; Modifications *modlist, *m; BerVarray b = NULL; int i; struct berval rsv = BER_BVC("modify breaks constraint"); int rc; char *msg = NULL; if (get_relax(op)) { return SLAP_CB_CONTINUE; } switch ( op->o_tag ) { case LDAP_REQ_MODIFY: modlist = op->orm_modlist; break; case LDAP_REQ_MODRDN: modlist = op->orr_modlist; break; default: /* impossible! assert? */ return LDAP_OTHER; } Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "constraint_update()\n", 0,0,0); if ((m = modlist) == NULL) { op->o_bd->bd_info = (BackendInfo *)(on->on_info); send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, "constraint_update() got null modlist"); return(rs->sr_err); } /* Do we need to count attributes? */ for(cp = c; cp; cp = cp->ap_next) { if (cp->count != 0 || cp->set || cp->restrict_lud != 0) { op->o_bd = on->on_info->oi_origdb; rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &target_entry ); op->o_bd = be; if (rc != 0 || target_entry == NULL) { Debug(LDAP_DEBUG_TRACE, "==> constraint_update rc = %d DN=\"%s\"%s\n", rc, op->o_req_ndn.bv_val, target_entry ? "" : " not found" ); if ( rc == 0 ) rc = LDAP_CONSTRAINT_VIOLATION; goto mod_violation; } break; } } rc = LDAP_CONSTRAINT_VIOLATION; for(;m; m = m->sml_next) { unsigned ce = 0; if (is_at_operational( m->sml_desc->ad_type )) continue; if ((( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_ADD) && (( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_REPLACE) && (( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_DELETE)) continue; /* we only care about ADD and REPLACE modifications */ /* and DELETE are used to track attribute count */ if ((( b = m->sml_values ) == NULL ) || (b[0].bv_val == NULL)) continue; /* Get this attribute count, if needed */ if (target_entry) ce = constraint_count_attr(target_entry, m->sml_desc); for(cp = c; cp; cp = cp->ap_next) { int j; for (j = 0; cp->ap[j]; j++) { if (cp->ap[j] == m->sml_desc) { break; } } if (cp->ap[j] == NULL) continue; if (cp->restrict_lud != NULL && constraint_check_restrict(op, cp, target_entry) == 0) { continue; } if (cp->count != 0) { unsigned ca; if (m->sml_op == LDAP_MOD_DELETE) ce = 0; for (ca = 0; b[ca].bv_val; ++ca); Debug(LDAP_DEBUG_TRACE, "==> constraint_update ce = %u, " "ca = %u, cp->count = %lu\n", ce, ca, (unsigned long) cp->count); if (m->sml_op == LDAP_MOD_ADD) { if (ca + ce > cp->count) { rc = LDAP_CONSTRAINT_VIOLATION; goto mod_violation; } } if (m->sml_op == LDAP_MOD_REPLACE) { if (ca > cp->count) { rc = LDAP_CONSTRAINT_VIOLATION; goto mod_violation; } ce = ca; } } /* DELETE are to be ignored beyond this point */ if (( m->sml_op & LDAP_MOD_OP ) == LDAP_MOD_DELETE) continue; for ( i = 0; b[i].bv_val; i++ ) { rc = constraint_violation( cp, &b[i], op, rs ); if ( rc ) { goto mod_violation; } } if (cp->set && target_entry) { if (target_entry_copy == NULL) { Modifications *ml; target_entry_copy = entry_dup(target_entry); /* if rename, set the new entry's name * (in normalized form only) */ if ( op->o_tag == LDAP_REQ_MODRDN ) { struct berval pdn, ndn = BER_BVNULL; if ( op->orr_nnewSup ) { pdn = *op->orr_nnewSup; } else { dnParent( &target_entry_copy->e_nname, &pdn ); } build_new_dn( &ndn, &pdn, &op->orr_nnewrdn, NULL ); ber_memfree( target_entry_copy->e_nname.bv_val ); target_entry_copy->e_nname = ndn; ber_bvreplace( &target_entry_copy->e_name, &ndn ); } /* apply modifications, in an attempt * to estimate what the entry would * look like in case all modifications * pass */ for ( ml = modlist; ml; ml = ml->sml_next ) { Modification *mod = &ml->sml_mod; const char *text; char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof(textbuf); int err; switch ( mod->sm_op ) { case LDAP_MOD_ADD: err = modify_add_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); break; case LDAP_MOD_DELETE: err = modify_delete_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); break; case LDAP_MOD_REPLACE: err = modify_replace_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); break; case LDAP_MOD_INCREMENT: err = modify_increment_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); break; case SLAP_MOD_SOFTADD: mod->sm_op = LDAP_MOD_ADD; err = modify_add_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); mod->sm_op = SLAP_MOD_SOFTADD; if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) { err = LDAP_SUCCESS; } break; case SLAP_MOD_SOFTDEL: mod->sm_op = LDAP_MOD_ADD; err = modify_delete_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); mod->sm_op = SLAP_MOD_SOFTDEL; if ( err == LDAP_NO_SUCH_ATTRIBUTE ) { err = LDAP_SUCCESS; } break; case SLAP_MOD_ADD_IF_NOT_PRESENT: if ( attr_find( target_entry_copy->e_attrs, mod->sm_desc ) ) { err = LDAP_SUCCESS; break; } mod->sm_op = LDAP_MOD_ADD; err = modify_add_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); mod->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT; break; default: err = LDAP_OTHER; break; } if ( err != LDAP_SUCCESS ) { rc = err; goto mod_violation; } } } if ( acl_match_set(&cp->val, op, target_entry_copy, NULL) == 0) { rc = LDAP_CONSTRAINT_VIOLATION; goto mod_violation; } } } } if (target_entry) { op->o_bd = on->on_info->oi_origdb; be_entry_release_r(op, target_entry); op->o_bd = be; } if (target_entry_copy) { entry_free(target_entry_copy); } return SLAP_CB_CONTINUE; mod_violation: /* violation */ if (target_entry) { op->o_bd = on->on_info->oi_origdb; be_entry_release_r(op, target_entry); op->o_bd = be; } if (target_entry_copy) { entry_free(target_entry_copy); } op->o_bd->bd_info = (BackendInfo *)(on->on_info); if ( rc == LDAP_CONSTRAINT_VIOLATION ) { msg = print_message( &rsv, m->sml_desc ); } send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION, msg ); ch_free(msg); return (rs->sr_err); }
int pam_authz(nssov_info *ni,TFILE *fp,Operation *op) { struct berval dn, uid, svc, ruser, rhost, tty; struct berval authzmsg = BER_BVNULL; int32_t tmpint32; char dnc[1024]; char uidc[32]; char svcc[256]; char ruserc[32]; char rhostc[256]; char ttyc[256]; int rc; Entry *e = NULL; Attribute *a; slap_callback cb = {0}; READ_STRING(fp,uidc); uid.bv_val = uidc; uid.bv_len = tmpint32; READ_STRING(fp,dnc); dn.bv_val = dnc; dn.bv_len = tmpint32; READ_STRING(fp,svcc); svc.bv_val = svcc; svc.bv_len = tmpint32; READ_STRING(fp,ruserc); ruser.bv_val = ruserc; ruser.bv_len = tmpint32; READ_STRING(fp,rhostc); rhost.bv_val = rhostc; rhost.bv_len = tmpint32; READ_STRING(fp,ttyc); tty.bv_val = ttyc; tty.bv_len = tmpint32; Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(%s)\n",dn.bv_val,0,0); /* If we didn't do authc, we don't have a DN yet */ if (BER_BVISEMPTY(&dn)) { struct paminfo pi; pi.uid = uid; pi.svc = svc; rc = pam_uid2dn(ni, op, &pi); if (rc) goto finish; dn = pi.dn; } /* See if they have access to the host and service */ if ((ni->ni_pam_opts & NI_PAM_HOSTSVC) && nssov_pam_svc_ad) { AttributeAssertion ava = ATTRIBUTEASSERTION_INIT; struct berval hostdn = BER_BVNULL; struct berval odn = op->o_ndn; SlapReply rs = {REP_RESULT}; op->o_dn = dn; op->o_ndn = dn; { nssov_mapinfo *mi = &ni->ni_maps[NM_host]; char fbuf[1024]; struct berval filter = {sizeof(fbuf),fbuf}; SlapReply rs2 = {REP_RESULT}; /* Lookup the host entry */ nssov_filter_byname(mi,0,&global_host_bv,&filter); cb.sc_private = &hostdn; cb.sc_response = nssov_name2dn_cb; op->o_callback = &cb; op->o_req_dn = mi->mi_base; op->o_req_ndn = mi->mi_base; op->ors_scope = mi->mi_scope; op->ors_filterstr = filter; op->ors_filter = str2filter_x(op, filter.bv_val); op->ors_attrs = slap_anlist_no_attrs; op->ors_tlimit = SLAP_NO_LIMIT; op->ors_slimit = 2; rc = op->o_bd->be_search(op, &rs2); filter_free_x(op, op->ors_filter, 1); if (BER_BVISEMPTY(&hostdn) && !BER_BVISEMPTY(&ni->ni_pam_defhost)) { filter.bv_len = sizeof(fbuf); filter.bv_val = fbuf; rs_reinit(&rs2, REP_RESULT); nssov_filter_byname(mi,0,&ni->ni_pam_defhost,&filter); op->ors_filterstr = filter; op->ors_filter = str2filter_x(op, filter.bv_val); rc = op->o_bd->be_search(op, &rs2); filter_free_x(op, op->ors_filter, 1); } /* no host entry, no default host -> deny */ if (BER_BVISEMPTY(&hostdn)) { rc = NSLCD_PAM_PERM_DENIED; authzmsg = hostmsg; goto finish; } } cb.sc_response = pam_compare_cb; cb.sc_private = NULL; op->o_tag = LDAP_REQ_COMPARE; op->o_req_dn = hostdn; op->o_req_ndn = hostdn; ava.aa_desc = nssov_pam_svc_ad; ava.aa_value = svc; op->orc_ava = &ava; rc = op->o_bd->be_compare( op, &rs ); if ( cb.sc_private == NULL ) { authzmsg = svcmsg; rc = NSLCD_PAM_PERM_DENIED; goto finish; } op->o_dn = odn; op->o_ndn = odn; } /* See if they're a member of the group */ if ((ni->ni_pam_opts & NI_PAM_USERGRP) && !BER_BVISEMPTY(&ni->ni_pam_group_dn) && ni->ni_pam_group_ad) { AttributeAssertion ava = ATTRIBUTEASSERTION_INIT; SlapReply rs = {REP_RESULT}; op->o_callback = &cb; cb.sc_response = slap_null_cb; op->o_tag = LDAP_REQ_COMPARE; op->o_req_dn = ni->ni_pam_group_dn; op->o_req_ndn = ni->ni_pam_group_dn; ava.aa_desc = ni->ni_pam_group_ad; ava.aa_value = dn; op->orc_ava = &ava; rc = op->o_bd->be_compare( op, &rs ); if ( rs.sr_err != LDAP_COMPARE_TRUE ) { authzmsg = grpmsg; rc = NSLCD_PAM_PERM_DENIED; goto finish; } } /* We need to check the user's entry for these bits */ if ((ni->ni_pam_opts & (NI_PAM_USERHOST|NI_PAM_USERSVC)) || ni->ni_pam_template_ad || ni->ni_pam_min_uid || ni->ni_pam_max_uid ) { rc = be_entry_get_rw( op, &dn, NULL, NULL, 0, &e ); if (rc != LDAP_SUCCESS) { rc = NSLCD_PAM_USER_UNKNOWN; goto finish; } } if ((ni->ni_pam_opts & NI_PAM_USERHOST) && nssov_pam_host_ad) { a = attr_find(e->e_attrs, nssov_pam_host_ad); if (!a || attr_valfind( a, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_VALUE_OF_SYNTAX, &global_host_bv, NULL, op->o_tmpmemctx )) { rc = NSLCD_PAM_PERM_DENIED; authzmsg = hostmsg; goto finish; } } if ((ni->ni_pam_opts & NI_PAM_USERSVC) && nssov_pam_svc_ad) { a = attr_find(e->e_attrs, nssov_pam_svc_ad); if (!a || attr_valfind( a, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_VALUE_OF_SYNTAX, &svc, NULL, op->o_tmpmemctx )) { rc = NSLCD_PAM_PERM_DENIED; authzmsg = svcmsg; goto finish; } } /* from passwd.c */ #define UIDN_KEY 2 if (ni->ni_pam_min_uid || ni->ni_pam_max_uid) { int id; char *tmp; nssov_mapinfo *mi = &ni->ni_maps[NM_passwd]; a = attr_find(e->e_attrs, mi->mi_attrs[UIDN_KEY].an_desc); if (!a) { rc = NSLCD_PAM_PERM_DENIED; authzmsg = uidmsg; goto finish; } id = (int)strtol(a->a_vals[0].bv_val,&tmp,0); if (a->a_vals[0].bv_val[0] == '\0' || *tmp != '\0') { rc = NSLCD_PAM_PERM_DENIED; authzmsg = uidmsg; goto finish; } if ((ni->ni_pam_min_uid && id < ni->ni_pam_min_uid) || (ni->ni_pam_max_uid && id > ni->ni_pam_max_uid)) { rc = NSLCD_PAM_PERM_DENIED; authzmsg = uidmsg; goto finish; } } if (ni->ni_pam_template_ad) { a = attr_find(e->e_attrs, ni->ni_pam_template_ad); if (a) uid = a->a_vals[0]; else if (!BER_BVISEMPTY(&ni->ni_pam_template)) uid = ni->ni_pam_template; } rc = NSLCD_PAM_SUCCESS; finish: WRITE_INT32(fp,NSLCD_VERSION); WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ); WRITE_INT32(fp,NSLCD_RESULT_BEGIN); WRITE_BERVAL(fp,&uid); WRITE_BERVAL(fp,&dn); WRITE_INT32(fp,rc); WRITE_BERVAL(fp,&authzmsg); if (e) { be_entry_release_r(op, e); } return 0; }
static int lastbind_bind_response( Operation *op, SlapReply *rs ) { Modifications *mod = NULL; BackendInfo *bi = op->o_bd->bd_info; Entry *e; int rc; /* we're only interested if the bind was successful */ if ( rs->sr_err != LDAP_SUCCESS ) return SLAP_CB_CONTINUE; rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); op->o_bd->bd_info = bi; if ( rc != LDAP_SUCCESS ) { return SLAP_CB_CONTINUE; } { lastbind_info *lbi = (lastbind_info *) op->o_callback->sc_private; time_t now, bindtime = (time_t)-1; Attribute *a; Modifications *m; char nowstr[ LDAP_LUTIL_GENTIME_BUFSIZE ]; struct berval timestamp; /* get the current time */ now = slap_get_time(); /* get authTimestamp attribute, if it exists */ if ((a = attr_find( e->e_attrs, ad_authTimestamp)) != NULL) { bindtime = parse_time( a->a_nvals[0].bv_val ); if (bindtime != (time_t)-1) { /* if the recorded bind time is within our precision, we're done * it doesn't need to be updated (save a write for nothing) */ if ((now - bindtime) < lbi->timestamp_precision) { goto done; } } } /* update the authTimestamp in the user's entry with the current time */ timestamp.bv_val = nowstr; timestamp.bv_len = sizeof(nowstr); slap_timestamp( &now, ×tamp ); m = ch_calloc( sizeof(Modifications), 1 ); m->sml_op = LDAP_MOD_REPLACE; m->sml_flags = 0; m->sml_type = ad_authTimestamp->ad_cname; m->sml_desc = ad_authTimestamp; m->sml_numvals = 1; m->sml_values = ch_calloc( sizeof(struct berval), 2 ); m->sml_nvalues = ch_calloc( sizeof(struct berval), 2 ); ber_dupbv( &m->sml_values[0], ×tamp ); ber_dupbv( &m->sml_nvalues[0], ×tamp ); m->sml_next = mod; mod = m; } done: be_entry_release_r( op, e ); /* perform the update, if necessary */ if ( mod ) { Operation op2 = *op; SlapReply r2 = { REP_RESULT }; slap_callback cb = { NULL, slap_null_cb, NULL, NULL }; /* This is a DSA-specific opattr, it never gets replicated. */ op2.o_tag = LDAP_REQ_MODIFY; op2.o_callback = &cb; op2.orm_modlist = mod; op2.o_dn = op->o_bd->be_rootdn; op2.o_ndn = op->o_bd->be_rootndn; op2.o_dont_replicate = 1; rc = op->o_bd->be_modify( &op2, &r2 ); slap_mods_free( mod, 1 ); } op->o_bd->bd_info = bi; return SLAP_CB_CONTINUE; }
static int dds_op_extended( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; dds_info_t *di = on->on_bi.bi_private; if ( DDS_OFF( di ) ) { return SLAP_CB_CONTINUE; } if ( bvmatch( &op->ore_reqoid, &slap_EXOP_REFRESH ) ) { Entry *e = NULL; time_t ttl; BackendDB db = *op->o_bd; SlapReply rs2 = { REP_RESULT }; Operation op2 = *op; slap_callback sc = { 0 }; Modifications ttlmod = { { 0 } }; struct berval ttlvalues[ 2 ]; char ttlbuf[STRLENOF("31557600") + 1]; rs->sr_err = slap_parse_refresh( op->ore_reqdata, NULL, &ttl, &rs->sr_text, NULL ); assert( rs->sr_err == LDAP_SUCCESS ); if ( ttl <= 0 || ttl > DDS_RF2589_MAX_TTL ) { rs->sr_err = LDAP_PROTOCOL_ERROR; rs->sr_text = "invalid time-to-live for dynamicObject"; return rs->sr_err; } if ( ttl > di->di_max_ttl ) { /* FIXME: I don't understand if this has to be an error, * or an indication that the requested Ttl has been * shortened to di->di_max_ttl >= 1 day */ rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; rs->sr_text = "time-to-live for dynamicObject exceeds limit"; return rs->sr_err; } if ( di->di_min_ttl && ttl < di->di_min_ttl ) { ttl = di->di_min_ttl; } /* This does not apply to multi-master case */ if ( !( !SLAP_SINGLE_SHADOW( op->o_bd ) || be_isupdate( op ) ) ) { /* we SHOULD return a referral in this case */ BerVarray defref = op->o_bd->be_update_refs ? op->o_bd->be_update_refs : default_referral; if ( defref != NULL ) { rs->sr_ref = referral_rewrite( op->o_bd->be_update_refs, NULL, NULL, LDAP_SCOPE_DEFAULT ); if ( rs->sr_ref ) { rs->sr_flags |= REP_REF_MUSTBEFREED; } else { rs->sr_ref = defref; } rs->sr_err = LDAP_REFERRAL; } else { rs->sr_text = "shadow context; no update referral"; rs->sr_err = LDAP_UNWILLING_TO_PERFORM; } return rs->sr_err; } assert( !BER_BVISNULL( &op->o_req_ndn ) ); /* check if exists but not dynamicObject */ op->o_bd->bd_info = (BackendInfo *)on->on_info; rs->sr_err = be_entry_get_rw( op, &op->o_req_ndn, slap_schema.si_oc_dynamicObject, NULL, 0, &e ); if ( rs->sr_err != LDAP_SUCCESS ) { rs->sr_err = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); if ( rs->sr_err == LDAP_SUCCESS && e != NULL ) { /* return referral only if "disclose" * is granted on the object */ if ( ! access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION; rs->sr_text = "refresh operation only applies to dynamic objects"; } be_entry_release_r( op, e ); } else { rs->sr_err = LDAP_NO_SUCH_OBJECT; } return rs->sr_err; } else if ( e != NULL ) { be_entry_release_r( op, e ); } /* we require manage privileges on the entryTtl, * and fake a Relax control */ op2.o_tag = LDAP_REQ_MODIFY; op2.o_bd = &db; db.bd_info = (BackendInfo *)on->on_info; op2.o_callback = ≻ sc.sc_response = slap_null_cb; op2.o_relax = SLAP_CONTROL_CRITICAL; op2.orm_modlist = &ttlmod; ttlmod.sml_op = LDAP_MOD_REPLACE; ttlmod.sml_flags = SLAP_MOD_MANAGING; ttlmod.sml_desc = slap_schema.si_ad_entryTtl; ttlmod.sml_values = ttlvalues; ttlmod.sml_numvals = 1; ttlvalues[ 0 ].bv_val = ttlbuf; ttlvalues[ 0 ].bv_len = snprintf( ttlbuf, sizeof( ttlbuf ), "%ld", ttl ); BER_BVZERO( &ttlvalues[ 1 ] ); /* the entryExpireTimestamp is added by modify */ rs->sr_err = slap_biglock_call_be( op_modify, &op2, &rs2 ); if ( ttlmod.sml_next != NULL ) { slap_mods_free( ttlmod.sml_next, 1 ); } if ( rs->sr_err == LDAP_SUCCESS ) { int rc; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_init_w_nullc( ber, LBER_USE_DER ); rc = ber_printf( ber, "{tiN}", LDAP_TAG_EXOP_REFRESH_RES_TTL, (int)ttl ); if ( rc < 0 ) { rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; } else { (void)ber_flatten( ber, &rs->sr_rspdata ); rs->sr_rspoid = ch_strdup( slap_EXOP_REFRESH.bv_val ); Log3( LDAP_DEBUG_TRACE, LDAP_LEVEL_INFO, "%s REFRESH dn=\"%s\" TTL=%ld\n", op->o_log_prefix, op->o_req_ndn.bv_val, ttl ); } ber_free_buf( ber ); } return rs->sr_err; } return SLAP_CB_CONTINUE; }
static int dds_op_modify( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; dds_info_t *di = (dds_info_t *)on->on_bi.bi_private; Modifications *mod; Entry *e = NULL; BackendInfo *bi = op->o_bd->bd_info; int was_dynamicObject = 0, is_dynamicObject = 0; struct berval bv_entryTtl = BER_BVNULL; time_t entryTtl = 0; char textbuf[ SLAP_TEXT_BUFLEN ]; if ( DDS_OFF( di ) ) { return SLAP_CB_CONTINUE; } /* bv_entryTtl stores the string representation of the entryTtl * across modifies for consistency checks of the final value; * the bv_val points to a static buffer; the bv_len is zero when * the attribute is deleted. * entryTtl stores the integer representation of the entryTtl; * its value is -1 when the attribute is deleted; it is 0 only * if no modifications of the entryTtl occurred, as an entryTtl * of 0 is invalid. */ bv_entryTtl.bv_val = textbuf; op->o_bd->bd_info = (BackendInfo *)on->on_info; rs->sr_err = be_entry_get_rw( op, &op->o_req_ndn, slap_schema.si_oc_dynamicObject, slap_schema.si_ad_entryTtl, 0, &e ); if ( rs->sr_err == LDAP_SUCCESS && e != NULL ) { Attribute *a = attr_find( e->e_attrs, slap_schema.si_ad_entryTtl ); /* the value of the entryTtl is saved for later checks */ if ( a != NULL ) { unsigned long ttl; int rc; bv_entryTtl.bv_len = a->a_nvals[ 0 ].bv_len; memcpy( bv_entryTtl.bv_val, a->a_nvals[ 0 ].bv_val, bv_entryTtl.bv_len ); bv_entryTtl.bv_val[ bv_entryTtl.bv_len ] = '\0'; rc = lutil_atoul( &ttl, bv_entryTtl.bv_val ); assert( rc == 0 ); entryTtl = (time_t)ttl; } be_entry_release_r( op, e ); e = NULL; was_dynamicObject = is_dynamicObject = 1; } op->o_bd->bd_info = bi; rs->sr_err = LDAP_SUCCESS; for ( mod = op->orm_modlist; mod; mod = mod->sml_next ) { if ( mod->sml_desc == slap_schema.si_ad_objectClass ) { int i; ObjectClass *oc; switch ( mod->sml_op ) { case LDAP_MOD_DELETE: if ( mod->sml_values == NULL ) { is_dynamicObject = 0; break; } for ( i = 0; !BER_BVISNULL( &mod->sml_values[ i ] ); i++ ) { oc = oc_bvfind( &mod->sml_values[ i ] ); if ( oc == slap_schema.si_oc_dynamicObject ) { is_dynamicObject = 0; break; } } break; case LDAP_MOD_REPLACE: if ( mod->sml_values == NULL ) { is_dynamicObject = 0; break; } /* fallthru */ case LDAP_MOD_ADD: for ( i = 0; !BER_BVISNULL( &mod->sml_values[ i ] ); i++ ) { oc = oc_bvfind( &mod->sml_values[ i ] ); if ( oc == slap_schema.si_oc_dynamicObject ) { is_dynamicObject = 1; break; } } break; } } else if ( mod->sml_desc == slap_schema.si_ad_entryTtl ) { unsigned long uttl; time_t ttl; int rc; switch ( mod->sml_op ) { case LDAP_MOD_DELETE: case SLAP_MOD_SOFTDEL: /* FIXME? */ if ( mod->sml_values != NULL ) { if ( BER_BVISEMPTY( &bv_entryTtl ) || !bvmatch( &bv_entryTtl, &mod->sml_values[ 0 ] ) ) { rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE ); if ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE; } goto done; } } bv_entryTtl.bv_len = 0; entryTtl = -1; break; case LDAP_MOD_REPLACE: bv_entryTtl.bv_len = 0; entryTtl = -1; /* fallthru */ case LDAP_MOD_ADD: case SLAP_MOD_SOFTADD: /* FIXME? */ case SLAP_MOD_ADD_IF_NOT_PRESENT: /* FIXME? */ assert( mod->sml_values != NULL ); assert( BER_BVISNULL( &mod->sml_values[ 1 ] ) ); if ( !BER_BVISEMPTY( &bv_entryTtl ) ) { rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE ); if ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { rs->sr_text = "attribute 'entryTtl' cannot have multiple values"; rs->sr_err = LDAP_CONSTRAINT_VIOLATION; } goto done; } rc = lutil_atoul( &uttl, mod->sml_values[ 0 ].bv_val ); ttl = (time_t)uttl; assert( rc == 0 ); if ( ttl > DDS_RF2589_MAX_TTL ) { rs->sr_err = LDAP_PROTOCOL_ERROR; rs->sr_text = "invalid time-to-live for dynamicObject"; goto done; } if ( ttl <= 0 || ttl > di->di_max_ttl ) { /* FIXME: I don't understand if this has to be an error, * or an indication that the requested Ttl has been * shortened to di->di_max_ttl >= 1 day */ rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; rs->sr_text = "time-to-live for dynamicObject exceeds administrative limit"; goto done; } entryTtl = ttl; bv_entryTtl.bv_len = mod->sml_values[ 0 ].bv_len; memcpy( bv_entryTtl.bv_val, mod->sml_values[ 0 ].bv_val, bv_entryTtl.bv_len ); bv_entryTtl.bv_val[ bv_entryTtl.bv_len ] = '\0'; break; case LDAP_MOD_INCREMENT: if ( BER_BVISEMPTY( &bv_entryTtl ) ) { rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE ); if ( rs->sr_err == LDAP_INSUFFICIENT_ACCESS ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE; rs->sr_text = "modify/increment: entryTtl: no such attribute"; } goto done; } entryTtl++; if ( entryTtl > DDS_RF2589_MAX_TTL ) { rs->sr_err = LDAP_PROTOCOL_ERROR; rs->sr_text = "invalid time-to-live for dynamicObject"; } else if ( entryTtl <= 0 || entryTtl > di->di_max_ttl ) { /* FIXME: I don't understand if this has to be an error, * or an indication that the requested Ttl has been * shortened to di->di_max_ttl >= 1 day */ rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; rs->sr_text = "time-to-live for dynamicObject exceeds administrative limit"; } if ( rs->sr_err != LDAP_SUCCESS ) { rc = backend_attribute( op, NULL, &op->o_req_ndn, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE ); if ( rc == LDAP_INSUFFICIENT_ACCESS ) { rs->sr_text = NULL; rs->sr_err = LDAP_NO_SUCH_OBJECT; } goto done; } bv_entryTtl.bv_len = snprintf( textbuf, sizeof( textbuf ), "%ld", entryTtl ); break; default: LDAP_BUG(); break; } } else if ( mod->sml_desc == ad_entryExpireTimestamp ) { /* should have been trapped earlier */ assert( mod->sml_flags & SLAP_MOD_INTERNAL ); } } done:; if ( rs->sr_err == LDAP_SUCCESS ) { int rc; /* FIXME: this could be allowed when the Relax control is used... * in that case: * * TODO * * static => dynamic: * entryTtl must be provided; add * entryExpireTimestamp accordingly * * dynamic => static: * entryTtl must be removed; remove * entryTimestamp accordingly * * ... but we need to make sure that there are no subordinate * issues... */ rc = is_dynamicObject - was_dynamicObject; if ( rc ) { #if 0 /* fix subordinate issues first */ if ( get_relax( op ) ) { switch ( rc ) { case -1: /* need to delete entryTtl to have a consistent entry */ if ( entryTtl != -1 ) { rs->sr_text = "objectClass modification from dynamicObject to static entry requires entryTtl deletion"; rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION; } break; case 1: /* need to add entryTtl to have a consistent entry */ if ( entryTtl <= 0 ) { rs->sr_text = "objectClass modification from static entry to dynamicObject requires entryTtl addition"; rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION; } break; } } else #endif { switch ( rc ) { case -1: rs->sr_text = "objectClass modification cannot turn dynamicObject into static entry"; break; case 1: rs->sr_text = "objectClass modification cannot turn static entry into dynamicObject"; break; } rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION; } if ( rc != LDAP_SUCCESS ) { rc = backend_attribute( op, NULL, &op->o_req_ndn, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE ); if ( rc == LDAP_INSUFFICIENT_ACCESS ) { rs->sr_text = NULL; rs->sr_err = LDAP_NO_SUCH_OBJECT; } } } } if ( rs->sr_err == LDAP_SUCCESS && entryTtl != 0 ) { Modifications *tmpmod = NULL, **modp; for ( modp = &op->orm_modlist; *modp; modp = &(*modp)->sml_next ) ; tmpmod = ch_calloc( 1, sizeof( Modifications ) ); tmpmod->sml_flags = SLAP_MOD_INTERNAL; tmpmod->sml_type = ad_entryExpireTimestamp->ad_cname; tmpmod->sml_desc = ad_entryExpireTimestamp; *modp = tmpmod; if ( entryTtl == -1 ) { /* delete entryExpireTimestamp */ tmpmod->sml_op = LDAP_MOD_DELETE; } else { time_t expire; char tsbuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; struct berval bv; /* keep entryExpireTimestamp consistent * with entryTtl */ expire = slap_get_time() + entryTtl; bv.bv_val = tsbuf; bv.bv_len = sizeof( tsbuf ); slap_timestamp( &expire, &bv ); tmpmod->sml_op = LDAP_MOD_REPLACE; value_add_one( &tmpmod->sml_values, &bv ); value_add_one( &tmpmod->sml_nvalues, &bv ); tmpmod->sml_numvals = 1; } } if ( rs->sr_err ) { op->o_bd->bd_info = (BackendInfo *)on->on_info; send_ldap_result( op, rs ); return rs->sr_err; } return SLAP_CB_CONTINUE; }
int fe_op_compare( Operation *op, SlapReply *rs ) { Entry *entry = NULL; AttributeAssertion *ava = op->orc_ava; BackendDB *bd = op->o_bd; if( strcasecmp( op->o_req_ndn.bv_val, LDAP_ROOT_DSE ) == 0 ) { if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } rs->sr_err = root_dse_info( op->o_conn, &entry, &rs->sr_text ); if( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } } else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) { if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); rs->sr_err = 0; goto cleanup; } rs->sr_err = schema_info( &entry, &rs->sr_text ); if( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); rs->sr_err = 0; goto cleanup; } } if( entry ) { rs->sr_err = slap_compare_entry( op, entry, ava ); entry_free( entry ); send_ldap_result( op, rs ); if( rs->sr_err == LDAP_COMPARE_TRUE || rs->sr_err == LDAP_COMPARE_FALSE ) { rs->sr_err = LDAP_SUCCESS; } goto cleanup; } /* * We could be serving multiple database backends. Select the * appropriate one, or send a referral to our "referral server" * if we don't hold it. */ op->o_bd = select_backend( &op->o_req_ndn, 0 ); if ( op->o_bd == NULL ) { rs->sr_ref = referral_rewrite( default_referral, NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); rs->sr_err = LDAP_REFERRAL; if (!rs->sr_ref) rs->sr_ref = default_referral; op->o_bd = bd; send_ldap_result( op, rs ); if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref ); rs->sr_err = 0; goto cleanup; } /* check restrictions */ if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } /* check for referrals */ if( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) { goto cleanup; } if ( SLAP_SHADOW(op->o_bd) && get_dontUseCopy(op) ) { /* don't use shadow copy */ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "copy not used" ); } else if ( ava->aa_desc == slap_schema.si_ad_entryDN ) { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "entryDN compare not supported" ); } else if ( ava->aa_desc == slap_schema.si_ad_subschemaSubentry ) { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "subschemaSubentry compare not supported" ); #ifndef SLAP_COMPARE_IN_FRONTEND } else if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates && op->o_bd->be_has_subordinates ) { int rc, hasSubordinates = LDAP_SUCCESS; rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &entry ); if ( rc == 0 && entry ) { if ( ! access_allowed( op, entry, ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) ) { rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS; } else { rc = rs->sr_err = op->o_bd->be_has_subordinates( op, entry, &hasSubordinates ); be_entry_release_r( op, entry ); } } if ( rc == 0 ) { int asserted; asserted = bvmatch( &ava->aa_value, &slap_true_bv ) ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE; if ( hasSubordinates == asserted ) { rs->sr_err = LDAP_COMPARE_TRUE; } else { rs->sr_err = LDAP_COMPARE_FALSE; } } else { /* return error only if "disclose" * is granted on the object */ if ( backend_access( op, NULL, &op->o_req_ndn, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) == LDAP_INSUFFICIENT_ACCESS ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } } send_ldap_result( op, rs ); if ( rc == 0 ) { rs->sr_err = LDAP_SUCCESS; } } else if ( op->o_bd->be_compare ) { rs->sr_err = op->o_bd->be_compare( op, rs ); #endif /* ! SLAP_COMPARE_IN_FRONTEND */ } else { rs->sr_err = SLAP_CB_CONTINUE; } if ( rs->sr_err == SLAP_CB_CONTINUE ) { /* do our best to compare that AVA * * NOTE: this code is used only * if SLAP_COMPARE_IN_FRONTEND * is #define'd (it's not by default) * or if op->o_bd->be_compare is NULL. * * FIXME: one potential issue is that * if SLAP_COMPARE_IN_FRONTEND overlays * are not executed for compare. */ BerVarray vals = NULL; int rc = LDAP_OTHER; rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn, ava->aa_desc, &vals, ACL_COMPARE ); switch ( rs->sr_err ) { default: /* return error only if "disclose" * is granted on the object */ if ( backend_access( op, NULL, &op->o_req_ndn, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) == LDAP_INSUFFICIENT_ACCESS ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } break; case LDAP_SUCCESS: if ( value_find_ex( op->oq_compare.rs_ava->aa_desc, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, vals, &ava->aa_value, op->o_tmpmemctx ) == 0 ) { rs->sr_err = LDAP_COMPARE_TRUE; break; } else { rs->sr_err = LDAP_COMPARE_FALSE; } rc = LDAP_SUCCESS; break; } send_ldap_result( op, rs ); if ( rc == 0 ) { rs->sr_err = LDAP_SUCCESS; } if ( vals ) { ber_bvarray_free_x( vals, op->o_tmpmemctx ); } } cleanup:; op->o_bd = bd; return rs->sr_err; }
int main( int argc, char **argv ) { ID id; int rc = EXIT_SUCCESS; slap_tool_init( "slapcat", SLAPCAT, argc, argv ); if( !be->be_entry_open || !be->be_entry_close || !be->be_entry_first || !be->be_entry_next || !be->be_entry_get ) { fprintf( stderr, "%s: database doesn't support necessary operations.\n", progname ); exit( EXIT_FAILURE ); } if( be->be_entry_open( be, 0 ) != 0 ) { fprintf( stderr, "%s: could not open database.\n", progname ); exit( EXIT_FAILURE ); } for ( id = be->be_entry_first( be ); id != NOID; id = be->be_entry_next( be ) ) { char *data; int len; Entry* e = be->be_entry_get( be, id ); if( verbose ) { printf( "# id=%08lx\n", (long) id ); } if ( e == NULL ) { printf("# no data for entry id=%08lx\n\n", (long) id ); rc = EXIT_FAILURE; if( continuemode ) continue; break; } data = entry2str( e, &len ); be_entry_release_r( be, 0L, 0L, e ); if ( data == NULL ) { printf("# bad data for entry id=%08lx\n\n", (long) id ); rc = EXIT_FAILURE; if( continuemode ) continue; break; } fputs( data, ldiffp ); fputs( "\n", ldiffp ); } be->be_entry_close( be ); slap_tool_destroy(); return rc; }
int slapcat( int argc, char **argv ) { ID id; int rc = EXIT_SUCCESS; Operation op = {0}; const char *progname = "slapcat"; int requestBSF; int doBSF = 0; slap_tool_init( progname, SLAPCAT, argc, argv ); requestBSF = ( sub_ndn.bv_len || filter ); #ifdef SIGPIPE (void) SIGNAL( SIGPIPE, slapcat_sig ); #endif #ifdef SIGHUP (void) SIGNAL( SIGHUP, slapcat_sig ); #endif (void) SIGNAL( SIGINT, slapcat_sig ); (void) SIGNAL( SIGTERM, slapcat_sig ); if( !be->be_entry_open || !be->be_entry_close || !( be->be_entry_first_x || be->be_entry_first ) || !be->be_entry_next || !be->be_entry_get ) { fprintf( stderr, "%s: database doesn't support necessary operations.\n", progname ); exit( EXIT_FAILURE ); } if( be->be_entry_open( be, 0 ) != 0 ) { fprintf( stderr, "%s: could not open database.\n", progname ); exit( EXIT_FAILURE ); } op.o_bd = be; if ( !requestBSF && be->be_entry_first ) { id = be->be_entry_first( be ); } else { if ( be->be_entry_first_x ) { id = be->be_entry_first_x( be, sub_ndn.bv_len ? &sub_ndn : NULL, scope, filter ); } else { assert( be->be_entry_first != NULL ); doBSF = 1; id = be->be_entry_first( be ); } } for ( ; id != NOID; id = be->be_entry_next( be ) ) { char *data; int len; Entry* e; if ( gotsig ) break; e = be->be_entry_get( be, id ); if ( e == NULL ) { printf("# no data for entry id=%08lx\n\n", (long) id ); rc = EXIT_FAILURE; if ( continuemode == 0 ) { break; } else if ( continuemode == 1 ) { continue; } /* this is a last resort: linearly scan all ids * trying to recover as much as possible (ITS#6482) */ while ( ++id != NOID ) { e = be->be_entry_get( be, id ); if ( e != NULL ) break; printf("# no data for entry id=%08lx\n\n", (long) id ); } if ( e == NULL ) break; } if ( doBSF ) { if ( sub_ndn.bv_len && !dnIsSuffixScope( &e->e_nname, &sub_ndn, scope ) ) { be_entry_release_r( &op, e ); continue; } if ( filter != NULL ) { int rc = test_filter( NULL, e, filter ); if ( rc != LDAP_COMPARE_TRUE ) { be_entry_release_r( &op, e ); continue; } } } if ( verbose ) { printf( "# id=%08lx\n", (long) id ); } data = entry2str( e, &len ); be_entry_release_r( &op, e ); if ( data == NULL ) { printf("# bad data for entry id=%08lx\n\n", (long) id ); rc = EXIT_FAILURE; if( continuemode ) continue; break; } if ( fputs( data, ldiffp->fp ) == EOF || fputs( "\n", ldiffp->fp ) == EOF ) { fprintf(stderr, "%s: error writing output.\n", progname); rc = EXIT_FAILURE; break; } } be->be_entry_close( be ); if ( slap_tool_destroy()) rc = EXIT_FAILURE; return rc; }
static int translucent_modify(Operation *op, SlapReply *rs) { SlapReply nrs = { REP_RESULT }; slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; translucent_info *ov = on->on_bi.bi_private; Entry *e = NULL, *re = NULL; Attribute *a, *ax; Modifications *m, **mm; BackendDB *db; int del, rc, erc = 0; slap_callback cb = { 0 }; Debug(LDAP_DEBUG_TRACE, "==> translucent_modify: %s\n", op->o_req_dn.bv_val, 0, 0); if(ov->defer_db_open) { send_ldap_error(op, rs, LDAP_UNAVAILABLE, "remote DB not available"); return(rs->sr_err); } /* ** fetch entry from the captive backend; ** if it did not exist, fail; ** release it, if captive backend supports this; ** */ db = op->o_bd; op->o_bd = &ov->db; ov->db.be_acl = op->o_bd->be_acl; rc = ov->db.bd_info->bi_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &re); op->o_bd = db; if(rc != LDAP_SUCCESS || re == NULL ) { send_ldap_error((op), rs, LDAP_NO_SUCH_OBJECT, "attempt to modify nonexistent local record"); return(rs->sr_err); } /* ** fetch entry from local backend; ** if it exists: ** foreach Modification: ** if attr not present in local: ** if Mod == LDAP_MOD_DELETE: ** if remote attr not present, return NO_SUCH; ** if remote attr present, drop this Mod; ** else force this Mod to LDAP_MOD_ADD; ** return CONTINUE; ** */ op->o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig; rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0, &e); op->o_bd->bd_info = (BackendInfo *) on; if(e && rc == LDAP_SUCCESS) { Debug(LDAP_DEBUG_TRACE, "=> translucent_modify: found local entry\n", 0, 0, 0); for(mm = &op->orm_modlist; *mm; ) { m = *mm; for(a = e->e_attrs; a; a = a->a_next) if(a->a_desc == m->sml_desc) break; if(a) { mm = &m->sml_next; continue; /* found local attr */ } if(m->sml_op == LDAP_MOD_DELETE) { for(a = re->e_attrs; a; a = a->a_next) if(a->a_desc == m->sml_desc) break; /* not found remote attr */ if(!a) { erc = LDAP_NO_SUCH_ATTRIBUTE; goto release; } if(ov->strict) { erc = LDAP_CONSTRAINT_VIOLATION; goto release; } Debug(LDAP_DEBUG_TRACE, "=> translucent_modify: silently dropping delete: %s\n", m->sml_desc->ad_cname.bv_val, 0, 0); *mm = m->sml_next; m->sml_next = NULL; slap_mods_free(m, 1); continue; } m->sml_op = LDAP_MOD_ADD; mm = &m->sml_next; } erc = SLAP_CB_CONTINUE; release: if(re) { if(ov->db.bd_info->bi_entry_release_rw) { op->o_bd = &ov->db; ov->db.bd_info->bi_entry_release_rw(op, re, 0); op->o_bd = db; } else entry_free(re); } op->o_bd->bd_info = (BackendInfo *) on->on_info->oi_orig; be_entry_release_r(op, e); op->o_bd->bd_info = (BackendInfo *) on; if(erc == SLAP_CB_CONTINUE) { return(erc); } else if(erc) { send_ldap_error(op, rs, erc, "attempt to delete nonexistent attribute"); return(erc); } } /* don't leak remote entry copy */ if(re) { if(ov->db.bd_info->bi_entry_release_rw) { op->o_bd = &ov->db; ov->db.bd_info->bi_entry_release_rw(op, re, 0); op->o_bd = db; } else entry_free(re); } /* ** foreach Modification: ** if MOD_ADD or MOD_REPLACE, add Attribute; ** if no Modifications were suitable: ** if strict, throw CONSTRAINT_VIOLATION; ** else, return early SUCCESS; ** fabricate Entry with new Attribute chain; ** glue_parent() for this Entry; ** call bi_op_add() in local backend; ** */ Debug(LDAP_DEBUG_TRACE, "=> translucent_modify: fabricating local add\n", 0, 0, 0); a = NULL; for(del = 0, ax = NULL, m = op->orm_modlist; m; m = m->sml_next) { Attribute atmp; if(((m->sml_op & LDAP_MOD_OP) != LDAP_MOD_ADD) && ((m->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE)) { Debug(LDAP_DEBUG_ANY, "=> translucent_modify: silently dropped modification(%d): %s\n", m->sml_op, m->sml_desc->ad_cname.bv_val, 0); if((m->sml_op & LDAP_MOD_OP) == LDAP_MOD_DELETE) del++; continue; } atmp.a_desc = m->sml_desc; atmp.a_vals = m->sml_values; atmp.a_nvals = m->sml_nvalues ? m->sml_nvalues : atmp.a_vals; atmp.a_numvals = m->sml_numvals; atmp.a_flags = 0; a = attr_dup( &atmp ); a->a_next = ax; ax = a; } if(del && ov->strict) { attrs_free( a ); send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, "attempt to delete attributes from local database"); return(rs->sr_err); } if(!ax) { if(ov->strict) { send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, "modification contained other than ADD or REPLACE"); return(rs->sr_err); } /* rs->sr_text = "no valid modification found"; */ rs->sr_err = LDAP_SUCCESS; send_ldap_result(op, rs); return(rs->sr_err); } e = entry_alloc(); ber_dupbv( &e->e_name, &op->o_req_dn ); ber_dupbv( &e->e_nname, &op->o_req_ndn ); e->e_attrs = a; op->o_tag = LDAP_REQ_ADD; cb.sc_response = translucent_tag_cb; cb.sc_private = op->orm_modlist; op->oq_add.rs_e = e; glue_parent(op); cb.sc_next = op->o_callback; op->o_callback = &cb; rc = on->on_info->oi_orig->bi_op_add(op, &nrs); if ( op->ora_e == e ) entry_free( e ); op->o_callback = cb.sc_next; return(rc); }
int passwd_extop( Operation *op, SlapReply *rs ) { struct berval id = {0, NULL}, hash, *rsp = NULL; req_pwdexop_s *qpw = &op->oq_pwdexop; req_extended_s qext = op->oq_extended; Modifications *ml; slap_callback cb = { NULL, slap_null_cb, NULL, NULL }; int i, nhash; char **hashes, idNul; int rc; BackendDB *op_be; int freenewpw = 0; struct berval dn = BER_BVNULL, ndn = BER_BVNULL; assert( ber_bvcmp( &slap_EXOP_MODIFY_PASSWD, &op->ore_reqoid ) == 0 ); if( op->o_dn.bv_len == 0 ) { Statslog( LDAP_DEBUG_STATS, "%s PASSMOD\n", op->o_log_prefix, 0, 0, 0, 0 ); rs->sr_text = "only authenticated users may change passwords"; return LDAP_STRONG_AUTH_REQUIRED; } qpw->rs_old.bv_len = 0; qpw->rs_old.bv_val = NULL; qpw->rs_new.bv_len = 0; qpw->rs_new.bv_val = NULL; qpw->rs_mods = NULL; qpw->rs_modtail = NULL; rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id, &qpw->rs_old, &qpw->rs_new, &rs->sr_text ); if ( !BER_BVISNULL( &id )) { idNul = id.bv_val[id.bv_len]; id.bv_val[id.bv_len] = '\0'; } if ( rs->sr_err == LDAP_SUCCESS && !BER_BVISEMPTY( &id ) ) { Statslog( LDAP_DEBUG_STATS, "%s PASSMOD id=\"%s\"%s%s\n", op->o_log_prefix, id.bv_val, qpw->rs_old.bv_val ? " old" : "", qpw->rs_new.bv_val ? " new" : "", 0 ); } else { Statslog( LDAP_DEBUG_STATS, "%s PASSMOD%s%s\n", op->o_log_prefix, qpw->rs_old.bv_val ? " old" : "", qpw->rs_new.bv_val ? " new" : "", 0, 0 ); } if ( rs->sr_err != LDAP_SUCCESS ) { if ( !BER_BVISNULL( &id )) id.bv_val[id.bv_len] = idNul; return rs->sr_err; } if ( !BER_BVISEMPTY( &id ) ) { rs->sr_err = dnPrettyNormal( NULL, &id, &dn, &ndn, op->o_tmpmemctx ); id.bv_val[id.bv_len] = idNul; if ( rs->sr_err != LDAP_SUCCESS ) { rs->sr_text = "Invalid DN"; rc = rs->sr_err; goto error_return; } op->o_req_dn = dn; op->o_req_ndn = ndn; op->o_bd = select_backend( &op->o_req_ndn, 1 ); } else { ber_dupbv_x( &dn, &op->o_dn, op->o_tmpmemctx ); ber_dupbv_x( &ndn, &op->o_ndn, op->o_tmpmemctx ); op->o_req_dn = dn; op->o_req_ndn = ndn; ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); op->o_bd = op->o_conn->c_authz_backend; ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); } if( op->o_bd == NULL ) { if ( qpw->rs_old.bv_val != NULL ) { rs->sr_text = "unwilling to verify old password"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } #ifdef HAVE_CYRUS_SASL rc = slap_sasl_setpass( op, rs ); #else rs->sr_text = "no authz backend"; rc = LDAP_OTHER; #endif goto error_return; } if ( op->o_req_ndn.bv_len == 0 ) { rs->sr_text = "no password is associated with the Root DSE"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } /* If we've got a glued backend, check the real backend */ op_be = op->o_bd; if ( SLAP_GLUE_INSTANCE( op->o_bd )) { op->o_bd = select_backend( &op->o_req_ndn, 0 ); } if (backend_check_restrictions( op, rs, (struct berval *)&slap_EXOP_MODIFY_PASSWD ) != LDAP_SUCCESS) { rc = rs->sr_err; goto error_return; } /* check for referrals */ if ( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) { rc = rs->sr_err; goto error_return; } /* This does not apply to multi-master case */ if(!( !SLAP_SINGLE_SHADOW( op->o_bd ) || be_isupdate( op ))) { /* we SHOULD return a referral in this case */ BerVarray defref = op->o_bd->be_update_refs ? op->o_bd->be_update_refs : default_referral; if( defref != NULL ) { rs->sr_ref = referral_rewrite( op->o_bd->be_update_refs, NULL, NULL, LDAP_SCOPE_DEFAULT ); if(rs->sr_ref) { rs->sr_flags |= REP_REF_MUSTBEFREED; } else { rs->sr_ref = defref; } rc = LDAP_REFERRAL; goto error_return; } rs->sr_text = "shadow context; no update referral"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } /* generate a new password if none was provided */ if ( qpw->rs_new.bv_len == 0 ) { slap_passwd_generate( &qpw->rs_new ); if ( qpw->rs_new.bv_len ) { rsp = slap_passwd_return( &qpw->rs_new ); freenewpw = 1; } } if ( qpw->rs_new.bv_len == 0 ) { rs->sr_text = "password generation failed"; rc = LDAP_OTHER; goto error_return; } op->o_bd = op_be; /* Give the backend a chance to handle this itself */ if ( op->o_bd->be_extended ) { rs->sr_err = op->o_bd->be_extended( op, rs ); if ( rs->sr_err != LDAP_UNWILLING_TO_PERFORM && rs->sr_err != SLAP_CB_CONTINUE ) { rc = rs->sr_err; if ( rsp ) { rs->sr_rspdata = rsp; rsp = NULL; } goto error_return; } } /* The backend didn't handle it, so try it here */ if( op->o_bd && !op->o_bd->be_modify ) { rs->sr_text = "operation not supported for current user"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } if ( qpw->rs_old.bv_val != NULL ) { Entry *e = NULL; rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, slap_schema.si_ad_userPassword, 0, &e ); if ( rc == LDAP_SUCCESS && e ) { Attribute *a = attr_find( e->e_attrs, slap_schema.si_ad_userPassword ); if ( a ) rc = slap_passwd_check( op, e, a, &qpw->rs_old, &rs->sr_text ); else rc = 1; be_entry_release_r( op, e ); if ( rc == LDAP_SUCCESS ) goto old_good; } rs->sr_text = "unwilling to verify old password"; rc = LDAP_UNWILLING_TO_PERFORM; goto error_return; } old_good: ml = ch_malloc( sizeof(Modifications) ); if ( !qpw->rs_modtail ) qpw->rs_modtail = &ml->sml_next; if ( default_passwd_hash ) { for ( nhash = 0; default_passwd_hash[nhash]; nhash++ ); hashes = default_passwd_hash; } else { nhash = 1; hashes = (char **)defhash; } ml->sml_numvals = nhash; ml->sml_values = ch_malloc( (nhash+1)*sizeof(struct berval) ); for ( i=0; hashes[i]; i++ ) { slap_passwd_hash_type( &qpw->rs_new, &hash, hashes[i], &rs->sr_text ); if ( hash.bv_len == 0 ) { if ( !rs->sr_text ) { rs->sr_text = "password hash failed"; } break; } ml->sml_values[i] = hash; } ml->sml_values[i].bv_val = NULL; ml->sml_nvalues = NULL; ml->sml_desc = slap_schema.si_ad_userPassword; ml->sml_type = ml->sml_desc->ad_cname; ml->sml_op = LDAP_MOD_REPLACE; ml->sml_flags = 0; ml->sml_next = qpw->rs_mods; qpw->rs_mods = ml; if ( hashes[i] ) { rs->sr_err = LDAP_OTHER; } else { slap_callback *sc = op->o_callback; op->o_tag = LDAP_REQ_MODIFY; op->o_callback = &cb; op->orm_modlist = qpw->rs_mods; op->orm_no_opattrs = 0; cb.sc_private = qpw; /* let Modify know this was pwdMod, * if it cares... */ rs->sr_err = op->o_bd->be_modify( op, rs ); /* be_modify() might have shuffled modifications */ qpw->rs_mods = op->orm_modlist; if ( rs->sr_err == LDAP_SUCCESS ) { rs->sr_rspdata = rsp; } else if ( rsp ) { ber_bvfree( rsp ); rsp = NULL; } op->o_tag = LDAP_REQ_EXTENDED; op->o_callback = sc; } rc = rs->sr_err; op->oq_extended = qext; error_return:; if ( qpw->rs_mods ) { slap_mods_free( qpw->rs_mods, 1 ); } if ( freenewpw ) { free( qpw->rs_new.bv_val ); } if ( !BER_BVISNULL( &dn ) ) { op->o_tmpfree( dn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &op->o_req_dn ); } if ( !BER_BVISNULL( &ndn ) ) { op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &op->o_req_ndn ); } return rc; }
static int adremap_search_resp( Operation *op, SlapReply *rs ) { adremap_ctx *ctx = op->o_callback->sc_private; slap_overinst *on = ctx->on; adremap_info *ai = on->on_bi.bi_private; adremap_case *ac; adremap_dnv *ad; Attribute *a; Entry *e; if (rs->sr_type != REP_SEARCH) return SLAP_CB_CONTINUE; /* we munged the attr list, restore it to original */ if (ctx->an_swap) { int i; ctx->an_swap = 0; for (i=0; rs->sr_attrs[i].an_name.bv_val; i++) { if (rs->sr_attrs[i].an_desc == ctx->ad) { rs->sr_attrs[i] = ctx->an; break; } } /* Usually rs->sr_attrs is just op->ors_attrs, but * overlays like rwm may make a new copy. Fix both * if needed. */ if (op->ors_attrs != rs->sr_attrs) { for (i=0; op->ors_attrs[i].an_name.bv_val; i++) { if (op->ors_attrs[i].an_desc == ctx->ad) { op->ors_attrs[i] = ctx->an; break; } } } } e = rs->sr_entry; for (ac = ai->ai_case; ac; ac = ac->ac_next) { a = attr_find(e->e_attrs, ac->ac_attr); if (a) { int i, j; if (!(rs->sr_flags & REP_ENTRY_MODIFIABLE)) { e = entry_dup(e); rs_replace_entry(op, rs, on, e); rs->sr_flags |= REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED; a = attr_find(e->e_attrs, ac->ac_attr); } for (i=0; i<a->a_numvals; i++) { unsigned char *c = a->a_vals[i].bv_val; for (j=0; j<a->a_vals[i].bv_len; j++) if (isupper(c[j])) c[j] = tolower(c[j]); } } } for (ad = ai->ai_dnv; ad; ad = ad->ad_next) { a = attr_find(e->e_attrs, ad->ad_dnattr); if (a) { Entry *n; Attribute *dr; int i, rc; if (!(rs->sr_flags & REP_ENTRY_MODIFIABLE)) { e = entry_dup(e); rs_replace_entry(op, rs, on, e); rs->sr_flags |= REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED; a = attr_find(e->e_attrs, ad->ad_dnattr); } for (i=0; i<a->a_numvals; i++) { struct berval dv; dv = ad->ad_deref->ad_cname; /* If the RDN uses the deref attr, just use it directly */ if (a->a_nvals[i].bv_val[dv.bv_len] == '=' && !memcmp(a->a_nvals[i].bv_val, dv.bv_val, dv.bv_len)) { struct berval bv, nv; char *ptr; bv = a->a_vals[i]; nv = a->a_nvals[i]; bv.bv_val += dv.bv_len + 1; ptr = strchr(bv.bv_val, ','); if (ptr) bv.bv_len = ptr - bv.bv_val; else bv.bv_len -= dv.bv_len+1; nv.bv_val += dv.bv_len + 1; ptr = strchr(nv.bv_val, ','); if (ptr) nv.bv_len = ptr - nv.bv_val; else nv.bv_len -= dv.bv_len+1; attr_merge_one(e, ad->ad_newattr, &bv, &nv); } else { /* otherwise look up the deref attr */ n = NULL; rc = be_entry_get_rw(op, &a->a_nvals[i], NULL, ad->ad_deref, 0, &n); if (!rc && n) { dr = attr_find(n->e_attrs, ad->ad_deref); if (dr) attr_merge_one(e, ad->ad_newattr, dr->a_vals, dr->a_nvals); be_entry_release_r(op, n); } } } } } return SLAP_CB_CONTINUE; }