static int usn_db_close( BackendDB *be, ConfigReply *cr ) { slap_overinst *on = (slap_overinst *)be->bd_info; usn_info_t *ui = on->on_bi.bi_private; Connection conn = {0}; OperationBuffer opbuf; Operation *op; SlapReply rs = {REP_RESULT}; void *thrctx; Modifications mod; slap_callback cb = {0}; char intbuf[64]; struct berval bv[2]; thrctx = ldap_pvt_thread_pool_context(); connection_fake_init( &conn, &opbuf, thrctx ); op = &opbuf.ob_op; op->o_bd = be; BER_BVZERO( &bv[1] ); bv[0].bv_len = snprintf( intbuf, sizeof(intbuf), "%d", ui->ui_current ); bv[0].bv_val = intbuf; mod.sml_numvals = 1; mod.sml_values = bv; mod.sml_nvalues = NULL; mod.sml_desc = ad_usnChanged; mod.sml_op = LDAP_MOD_REPLACE; mod.sml_flags = 0; mod.sml_next = NULL; cb.sc_response = slap_null_cb; op->o_tag = LDAP_REQ_MODIFY; op->o_callback = &cb; op->orm_modlist = &mod; op->orm_no_opattrs = 1; op->o_dn = be->be_rootdn; op->o_ndn = be->be_rootndn; op->o_req_dn = op->o_bd->be_suffix[0]; op->o_req_ndn = op->o_bd->be_nsuffix[0]; op->o_bd->bd_info = on->on_info->oi_orig; op->o_managedsait = SLAP_CONTROL_NONCRITICAL; op->o_no_schema_check = 1; op->o_bd->be_modify( op, &rs ); if ( mod.sml_next != NULL ) { slap_mods_free( mod.sml_next, 1 ); } return 0; }
static void nops_rm_mod( Modifications **mods, Modifications *mod ) { Modifications *next, *m; next = mod->sml_next; if (*mods == mod) { *mods = next; } else { Modifications *m; for (m = *mods; m; m = m->sml_next) { if (m->sml_next == mod) { m->sml_next = next; break; } } } mod->sml_next = NULL; slap_mods_free(mod, 1); return; }
static int pblock_set( Slapi_PBlock *pb, int param, void *value ) { int rc = PBLOCK_SUCCESS; pblock_lock( pb ); switch ( param ) { case SLAPI_OPERATION: pb->pb_op = (Operation *)value; break; case SLAPI_OPINITIATED_TIME: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_time = *((long *)value); break; case SLAPI_OPERATION_ID: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_opid = *((long *)value); break; case SLAPI_OPERATION_TYPE: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_tag = *((ber_tag_t *)value); break; case SLAPI_OPERATION_MSGID: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_msgid = *((long *)value); break; case SLAPI_X_OPERATION_DELETE_GLUE_PARENT: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_delete_glue_parent = *((int *)value); break; case SLAPI_X_OPERATION_NO_SCHEMA_CHECK: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_no_schema_check = *((int *)value); break; case SLAPI_X_OPERATION_NO_SUBORDINATE_GLUE: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_no_subordinate_glue = *((int *)value); break; case SLAPI_REQCONTROLS: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_ctrls = (LDAPControl **)value; break; case SLAPI_RESCONTROLS: { LDAPControl **ctrls = NULL; pblock_get_default( pb, param, (void **)&ctrls ); if ( ctrls != NULL ) { /* free old ones first */ ldap_controls_free( ctrls ); } rc = pblock_set_default( pb, param, value ); break; } case SLAPI_ADD_RESCONTROL: PBLOCK_ASSERT_OP( pb, 0 ); rc = pblock_add_control( pb, (LDAPControl *)value ); break; case SLAPI_REQUESTOR_DN: PBLOCK_ASSERT_OP( pb, 0 ); rc = pblock_set_dn( value, &pb->pb_op->o_dn, &pb->pb_op->o_ndn, pb->pb_op->o_tmpmemctx ); break; case SLAPI_MANAGEDSAIT: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_managedsait = *((int *)value); break; case SLAPI_X_RELAX: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_relax = *((int *)value); break; case SLAPI_BACKEND: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_op->o_bd = (BackendDB *)value; break; case SLAPI_CONNECTION: pb->pb_conn = (Connection *)value; break; case SLAPI_X_CONN_SSF: PBLOCK_ASSERT_CONN( pb ); PBLOCK_LOCK_CONN( pb ); pb->pb_conn->c_ssf = (slap_ssf_t)(long)value; PBLOCK_UNLOCK_CONN( pb ); break; case SLAPI_X_CONN_SASL_CONTEXT: PBLOCK_ASSERT_CONN( pb ); PBLOCK_LOCK_CONN( pb ); pb->pb_conn->c_sasl_authctx = value; PBLOCK_UNLOCK_CONN( pb ); break; case SLAPI_TARGET_DN: PBLOCK_ASSERT_OP( pb, 0 ); rc = pblock_set_dn( value, &pb->pb_op->o_req_dn, &pb->pb_op->o_req_ndn, pb->pb_op->o_tmpmemctx ); break; case SLAPI_CONN_ID: PBLOCK_ASSERT_CONN( pb ); PBLOCK_LOCK_CONN( pb ); pb->pb_conn->c_connid = *((long *)value); PBLOCK_UNLOCK_CONN( pb ); break; case SLAPI_CONN_DN: PBLOCK_ASSERT_CONN( pb ); PBLOCK_LOCK_CONN( pb ); rc = pblock_set_dn( value, &pb->pb_conn->c_dn, &pb->pb_conn->c_ndn, NULL ); PBLOCK_UNLOCK_CONN( pb ); break; case SLAPI_RESULT_CODE: case SLAPI_PLUGIN_INTOP_RESULT: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_rs->sr_err = *((int *)value); break; case SLAPI_RESULT_TEXT: PBLOCK_ASSERT_OP( pb, 0 ); snprintf( pb->pb_textbuf, sizeof( pb->pb_textbuf ), "%s", (char *)value ); pb->pb_rs->sr_text = pb->pb_textbuf; break; case SLAPI_RESULT_MATCHED: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_rs->sr_matched = (char *)value; /* XXX should dup? */ break; case SLAPI_ADD_ENTRY: PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_ADD ) pb->pb_op->ora_e = (Slapi_Entry *)value; else rc = PBLOCK_ERROR; break; case SLAPI_MODIFY_MODS: { Modifications **mlp; Modifications *newmods; PBLOCK_ASSERT_OP( pb, 0 ); rc = pblock_set_default( pb, param, value ); if ( rc != PBLOCK_SUCCESS ) { break; } if ( pb->pb_op->o_tag == LDAP_REQ_MODIFY ) { mlp = &pb->pb_op->orm_modlist; } else if ( pb->pb_op->o_tag == LDAP_REQ_ADD ) { mlp = &pb->pb_op->ora_modlist; } else if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) { mlp = &pb->pb_op->orr_modlist; } else { break; } newmods = slapi_int_ldapmods2modifications( pb->pb_op, (LDAPMod **)value ); if ( newmods != NULL ) { slap_mods_free( *mlp, 1 ); *mlp = newmods; } break; } case SLAPI_MODRDN_NEWRDN: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) { rc = pblock_set_dn( value, &pb->pb_op->orr_newrdn, &pb->pb_op->orr_nnewrdn, pb->pb_op->o_tmpmemctx ); if ( rc == LDAP_SUCCESS ) rc = rdn_validate( &pb->pb_op->orr_nnewrdn ); } else { rc = PBLOCK_ERROR; } break; case SLAPI_MODRDN_NEWSUPERIOR: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) { if ( value == NULL ) { if ( pb->pb_op->orr_newSup != NULL ) { pb->pb_op->o_tmpfree( pb->pb_op->orr_newSup, pb->pb_op->o_tmpmemctx ); BER_BVZERO( pb->pb_op->orr_newSup ); pb->pb_op->orr_newSup = NULL; } if ( pb->pb_op->orr_newSup != NULL ) { pb->pb_op->o_tmpfree( pb->pb_op->orr_nnewSup, pb->pb_op->o_tmpmemctx ); BER_BVZERO( pb->pb_op->orr_nnewSup ); pb->pb_op->orr_nnewSup = NULL; } } else { if ( pb->pb_op->orr_newSup == NULL ) { pb->pb_op->orr_newSup = (struct berval *)pb->pb_op->o_tmpalloc( sizeof(struct berval), pb->pb_op->o_tmpmemctx ); BER_BVZERO( pb->pb_op->orr_newSup ); } if ( pb->pb_op->orr_nnewSup == NULL ) { pb->pb_op->orr_nnewSup = (struct berval *)pb->pb_op->o_tmpalloc( sizeof(struct berval), pb->pb_op->o_tmpmemctx ); BER_BVZERO( pb->pb_op->orr_nnewSup ); } rc = pblock_set_dn( value, pb->pb_op->orr_newSup, pb->pb_op->orr_nnewSup, pb->pb_op->o_tmpmemctx ); } } else { rc = PBLOCK_ERROR; } break; case SLAPI_MODRDN_DELOLDRDN: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_MODRDN ) pb->pb_op->orr_deleteoldrdn = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_SEARCH_SCOPE: { int scope = *((int *)value); PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) { switch ( *((int *)value) ) { case LDAP_SCOPE_BASE: case LDAP_SCOPE_ONELEVEL: case LDAP_SCOPE_SUBTREE: case LDAP_SCOPE_SUBORDINATE: pb->pb_op->ors_scope = scope; break; default: rc = PBLOCK_ERROR; break; } } else { rc = PBLOCK_ERROR; } break; } case SLAPI_SEARCH_DEREF: PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) pb->pb_op->ors_deref = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_SEARCH_SIZELIMIT: PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) pb->pb_op->ors_slimit = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_SEARCH_TIMELIMIT: PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) pb->pb_op->ors_tlimit = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_SEARCH_FILTER: PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) pb->pb_op->ors_filter = (Slapi_Filter *)value; else rc = PBLOCK_ERROR; break; case SLAPI_SEARCH_STRFILTER: PBLOCK_ASSERT_OP( pb, 0 ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) { pb->pb_op->ors_filterstr.bv_val = (char *)value; pb->pb_op->ors_filterstr.bv_len = strlen((char *)value); } else { rc = PBLOCK_ERROR; } break; case SLAPI_SEARCH_ATTRS: { AttributeName *an = NULL; size_t i = 0, j = 0; char **attrs = (char **)value; PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag != LDAP_REQ_SEARCH ) { rc = PBLOCK_ERROR; break; } /* also set mapped attrs */ rc = pblock_set_default( pb, param, value ); if ( rc != PBLOCK_SUCCESS ) { break; } if ( pb->pb_op->ors_attrs != NULL ) { pb->pb_op->o_tmpfree( pb->pb_op->ors_attrs, pb->pb_op->o_tmpmemctx ); pb->pb_op->ors_attrs = NULL; } if ( attrs != NULL ) { for ( i = 0; attrs[i] != NULL; i++ ) ; } if ( i ) { an = (AttributeName *)pb->pb_op->o_tmpcalloc( i + 1, sizeof(AttributeName), pb->pb_op->o_tmpmemctx ); for ( i = 0; attrs[i] != NULL; i++ ) { an[j].an_desc = NULL; an[j].an_oc = NULL; an[j].an_flags = 0; an[j].an_name.bv_val = attrs[i]; an[j].an_name.bv_len = strlen( attrs[i] ); if ( slap_bv2ad( &an[j].an_name, &an[j].an_desc, &pb->pb_rs->sr_text ) == LDAP_SUCCESS ) { j++; } } an[j].an_name.bv_val = NULL; an[j].an_name.bv_len = 0; } pb->pb_op->ors_attrs = an; break; } case SLAPI_SEARCH_ATTRSONLY: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_SEARCH ) pb->pb_op->ors_attrsonly = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_SEARCH_RESULT_ENTRY: PBLOCK_ASSERT_OP( pb, 0 ); rs_replace_entry( pb->pb_op, pb->pb_rs, NULL, (Slapi_Entry *)value ); /* TODO: Should REP_ENTRY_MODIFIABLE be set? */ pb->pb_rs->sr_flags |= REP_ENTRY_MUSTBEFREED; break; case SLAPI_BIND_RET_SASLCREDS: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_rs->sr_sasldata = (struct berval *)value; break; case SLAPI_EXT_OP_REQ_OID: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_EXTENDED ) { pb->pb_op->ore_reqoid.bv_val = (char *)value; pb->pb_op->ore_reqoid.bv_len = strlen((char *)value); } else { rc = PBLOCK_ERROR; } break; case SLAPI_EXT_OP_REQ_VALUE: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_EXTENDED ) pb->pb_op->ore_reqdata = (struct berval *)value; else rc = PBLOCK_ERROR; break; case SLAPI_EXT_OP_RET_OID: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_rs->sr_rspoid = (char *)value; break; case SLAPI_EXT_OP_RET_VALUE: PBLOCK_ASSERT_OP( pb, 0 ); pb->pb_rs->sr_rspdata = (struct berval *)value; break; case SLAPI_BIND_METHOD: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_BIND ) pb->pb_op->orb_method = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_BIND_CREDENTIALS: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_BIND ) pb->pb_op->orb_cred = *((struct berval *)value); else rc = PBLOCK_ERROR; break; case SLAPI_COMPARE_TYPE: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE ) { const char *text; pb->pb_op->orc_ava->aa_desc = NULL; rc = slap_str2ad( (char *)value, &pb->pb_op->orc_ava->aa_desc, &text ); } else { rc = PBLOCK_ERROR; } break; case SLAPI_COMPARE_VALUE: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_COMPARE ) pb->pb_op->orc_ava->aa_value = *((struct berval *)value); else rc = PBLOCK_ERROR; break; case SLAPI_ABANDON_MSGID: PBLOCK_ASSERT_OP( pb, 0 ); PBLOCK_VALIDATE_IS_INTOP( pb ); if ( pb->pb_op->o_tag == LDAP_REQ_ABANDON) pb->pb_op->orn_msgid = *((int *)value); else rc = PBLOCK_ERROR; break; case SLAPI_REQUESTOR_ISROOT: case SLAPI_IS_REPLICATED_OPERATION: case SLAPI_CONN_AUTHTYPE: case SLAPI_CONN_AUTHMETHOD: case SLAPI_IS_INTERNAL_OPERATION: case SLAPI_X_CONN_IS_UDP: case SLAPI_CONN_CLIENTIP: case SLAPI_X_CONN_CLIENTPATH: case SLAPI_CONN_SERVERIP: case SLAPI_X_CONN_SERVERPATH: case SLAPI_X_ADD_STRUCTURAL_CLASS: /* These parameters cannot be set */ rc = PBLOCK_ERROR; break; default: rc = pblock_set_default( pb, param, value ); break; } pblock_unlock( pb ); return rc; }
int slapi_add_internal_pb( Slapi_PBlock *pb ) { SlapReply *rs; Slapi_Entry *entry_orig = NULL; OpExtraDB oex; int rc; if ( pb == NULL ) { return -1; } PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_ADD ); rs = pb->pb_rs; entry_orig = pb->pb_op->ora_e; pb->pb_op->ora_e = NULL; /* * The caller can specify a new entry, or a target DN and set * of modifications, but not both. */ if ( entry_orig != NULL ) { if ( pb->pb_op->ora_modlist != NULL || !BER_BVISNULL( &pb->pb_op->o_req_ndn )) { rs->sr_err = LDAP_PARAM_ERROR; goto cleanup; } assert( BER_BVISNULL( &pb->pb_op->o_req_dn ) ); /* shouldn't get set */ ber_dupbv( &pb->pb_op->o_req_dn, &entry_orig->e_name ); ber_dupbv( &pb->pb_op->o_req_ndn, &entry_orig->e_nname ); } else if ( pb->pb_op->ora_modlist == NULL || BER_BVISNULL( &pb->pb_op->o_req_ndn )) { rs->sr_err = LDAP_PARAM_ERROR; goto cleanup; } pb->pb_op->ora_e = (Entry *)slapi_ch_calloc( 1, sizeof(Entry) ); ber_dupbv( &pb->pb_op->ora_e->e_name, &pb->pb_op->o_req_dn ); ber_dupbv( &pb->pb_op->ora_e->e_nname, &pb->pb_op->o_req_ndn ); if ( entry_orig != NULL ) { assert( pb->pb_op->ora_modlist == NULL ); rs->sr_err = slap_entry2mods( entry_orig, &pb->pb_op->ora_modlist, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) ); if ( rs->sr_err != LDAP_SUCCESS ) { goto cleanup; } } else { assert( pb->pb_op->ora_modlist != NULL ); } rs->sr_err = slap_mods_check( pb->pb_op, pb->pb_op->ora_modlist, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ), NULL ); if ( rs->sr_err != LDAP_SUCCESS ) { goto cleanup; } /* Duplicate the values, because we may call slapi_entry_free() */ rs->sr_err = slap_mods2entry( pb->pb_op->ora_modlist, &pb->pb_op->ora_e, 1, 0, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) ); if ( rs->sr_err != LDAP_SUCCESS ) { goto cleanup; } oex.oe.oe_key = (void *)do_add; oex.oe_db = NULL; LDAP_SLIST_INSERT_HEAD(&pb->pb_op->o_extra, &oex.oe, oe_next); rc = slapi_int_func_internal_pb( pb, op_add ); LDAP_SLIST_REMOVE(&pb->pb_op->o_extra, &oex.oe, OpExtra, oe_next); if ( !rc ) { if ( pb->pb_op->ora_e != NULL && oex.oe_db != NULL ) { BackendDB *bd = pb->pb_op->o_bd; pb->pb_op->o_bd = oex.oe_db; be_entry_release_w( pb->pb_op, pb->pb_op->ora_e ); pb->pb_op->ora_e = NULL; pb->pb_op->o_bd = bd; } } cleanup: if ( pb->pb_op->ora_e != NULL ) { slapi_entry_free( pb->pb_op->ora_e ); pb->pb_op->ora_e = NULL; } if ( entry_orig != NULL ) { pb->pb_op->ora_e = entry_orig; slap_mods_free( pb->pb_op->ora_modlist, 1 ); pb->pb_op->ora_modlist = NULL; } return 0; }
void slapi_int_connection_done_pb( Slapi_PBlock *pb ) { Connection *conn; Operation *op; PBLOCK_ASSERT_INTOP( pb, 0 ); conn = pb->pb_conn; op = pb->pb_op; /* free allocated DNs */ if ( !BER_BVISNULL( &op->o_dn ) ) op->o_tmpfree( op->o_dn.bv_val, op->o_tmpmemctx ); if ( !BER_BVISNULL( &op->o_ndn ) ) op->o_tmpfree( op->o_ndn.bv_val, op->o_tmpmemctx ); if ( !BER_BVISNULL( &op->o_req_dn ) ) op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); if ( !BER_BVISNULL( &op->o_req_ndn ) ) op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); switch ( op->o_tag ) { case LDAP_REQ_MODRDN: if ( !BER_BVISNULL( &op->orr_newrdn )) op->o_tmpfree( op->orr_newrdn.bv_val, op->o_tmpmemctx ); if ( !BER_BVISNULL( &op->orr_nnewrdn )) op->o_tmpfree( op->orr_nnewrdn.bv_val, op->o_tmpmemctx ); if ( op->orr_newSup != NULL ) { assert( !BER_BVISNULL( op->orr_newSup ) ); op->o_tmpfree( op->orr_newSup->bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx ); } if ( op->orr_nnewSup != NULL ) { assert( !BER_BVISNULL( op->orr_nnewSup ) ); op->o_tmpfree( op->orr_nnewSup->bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx ); } slap_mods_free( op->orr_modlist, 1 ); break; case LDAP_REQ_ADD: slap_mods_free( op->ora_modlist, 0 ); break; case LDAP_REQ_MODIFY: slap_mods_free( op->orm_modlist, 1 ); break; case LDAP_REQ_SEARCH: if ( op->ors_attrs != NULL ) { op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx ); op->ors_attrs = NULL; } break; default: break; } slapi_ch_free_string( &conn->c_authmech.bv_val ); slapi_ch_free_string( &conn->c_dn.bv_val ); slapi_ch_free_string( &conn->c_ndn.bv_val ); slapi_ch_free_string( &conn->c_peer_domain.bv_val ); slapi_ch_free_string( &conn->c_peer_name.bv_val ); if ( conn->c_sb != NULL ) { ber_sockbuf_free( conn->c_sb ); } slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, op ); slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, conn ); slapi_ch_free( (void **)&pb->pb_op->o_callback ); slapi_ch_free( (void **)&pb->pb_op ); slapi_ch_free( (void **)&pb->pb_conn ); slapi_ch_free( (void **)&pb->pb_rs ); }
int do_modrdn( Operation *op, SlapReply *rs ) { struct berval dn = BER_BVNULL; struct berval newrdn = BER_BVNULL; struct berval newSuperior = BER_BVNULL; ber_int_t deloldrdn; struct berval pnewSuperior = BER_BVNULL; struct berval nnewSuperior = BER_BVNULL; ber_len_t length; Debug( LDAP_DEBUG_TRACE, "%s do_modrdn\n", op->o_log_prefix, 0, 0 ); /* * Parse the modrdn request. It looks like this: * * ModifyRDNRequest := SEQUENCE { * entry DistinguishedName, * newrdn RelativeDistinguishedName * deleteoldrdn BOOLEAN, * newSuperior [0] LDAPDN OPTIONAL (v3 Only!) * } */ if ( ber_scanf( op->o_ber, "{mmb", &dn, &newrdn, &deloldrdn ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: ber_scanf failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); return SLAPD_DISCONNECT; } /* Check for newSuperior parameter, if present scan it */ if ( ber_peek_tag( op->o_ber, &length ) == LDAP_TAG_NEWSUPERIOR ) { if ( op->o_protocol < LDAP_VERSION3 ) { /* Connection record indicates v2 but field * newSuperior is present: report error. */ Debug( LDAP_DEBUG_ANY, "%s do_modrdn: newSuperior requires LDAPv3\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "newSuperior requires LDAPv3" ); rs->sr_err = SLAPD_DISCONNECT; goto cleanup; } if ( ber_scanf( op->o_ber, "m", &newSuperior ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: ber_scanf(\"m\") failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); rs->sr_err = SLAPD_DISCONNECT; goto cleanup; } op->orr_newSup = &pnewSuperior; op->orr_nnewSup = &nnewSuperior; } Debug( LDAP_DEBUG_ARGS, "do_modrdn: dn (%s) newrdn (%s) newsuperior (%s)\n", dn.bv_val, newrdn.bv_val, newSuperior.bv_len ? newSuperior.bv_val : "" ); if ( ber_scanf( op->o_ber, /*{*/ "}") == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: ber_scanf failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); rs->sr_err = SLAPD_DISCONNECT; goto cleanup; } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: get_ctrls failed\n", op->o_log_prefix, 0, 0 ); /* get_ctrls has sent results. Now clean up. */ goto cleanup; } rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid dn (%s)\n", op->o_log_prefix, dn.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" ); goto cleanup; } /* FIXME: should have/use rdnPretty / rdnNormalize routines */ rs->sr_err = dnPrettyNormal( NULL, &newrdn, &op->orr_newrdn, &op->orr_nnewrdn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid newrdn (%s)\n", op->o_log_prefix, newrdn.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid new RDN" ); goto cleanup; } if( rdn_validate( &op->orr_newrdn ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid rdn (%s)\n", op->o_log_prefix, op->orr_newrdn.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid new RDN" ); goto cleanup; } if( op->orr_newSup ) { rs->sr_err = dnPrettyNormal( NULL, &newSuperior, &pnewSuperior, &nnewSuperior, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modrdn: invalid newSuperior (%s)\n", op->o_log_prefix, newSuperior.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid newSuperior" ); goto cleanup; } } Statslog( LDAP_DEBUG_STATS, "%s MODRDN dn=\"%s\"\n", op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 ); op->orr_deleteoldrdn = deloldrdn; op->orr_modlist = NULL; /* prepare modlist of modifications from old/new RDN */ rs->sr_err = slap_modrdn2mods( op, rs ); if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } op->o_bd = frontendDB; rs->sr_err = frontendDB->be_modrdn( op, rs ); #ifdef LDAP_X_TXN if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) { /* skip cleanup */ } #endif cleanup: op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->orr_newrdn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->orr_nnewrdn.bv_val, op->o_tmpmemctx ); if ( op->orr_modlist != NULL ) slap_mods_free( op->orr_modlist, 1 ); if ( !BER_BVISNULL( &pnewSuperior ) ) { op->o_tmpfree( pnewSuperior.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &nnewSuperior ) ) { op->o_tmpfree( nnewSuperior.bv_val, op->o_tmpmemctx ); } return rs->sr_err; }
int do_modify( Operation *op, SlapReply *rs ) { struct berval dn = BER_BVNULL; char textbuf[ SLAP_TEXT_BUFLEN ]; size_t textlen = sizeof( textbuf ); #ifdef LDAP_DEBUG Modifications *tmp; #endif Debug( LDAP_DEBUG_TRACE, "%s do_modify\n", op->o_log_prefix, 0, 0 ); /* * Parse the modify request. It looks like this: * * ModifyRequest := [APPLICATION 6] SEQUENCE { * name DistinguishedName, * mods SEQUENCE OF SEQUENCE { * operation ENUMERATED { * add (0), * delete (1), * replace (2) * }, * modification SEQUENCE { * type AttributeType, * values SET OF AttributeValue * } * } * } */ if ( ber_scanf( op->o_ber, "{m" /*}*/, &dn ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_modify: ber_scanf failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); return SLAPD_DISCONNECT; } Debug( LDAP_DEBUG_ARGS, "%s do_modify: dn (%s)\n", op->o_log_prefix, dn.bv_val, 0 ); rs->sr_err = slap_parse_modlist( op, rs, op->o_ber, &op->oq_modify ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modify: slap_parse_modlist failed err=%d msg=%s\n", op->o_log_prefix, rs->sr_err, rs->sr_text ); send_ldap_result( op, rs ); goto cleanup; } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modify: get_ctrls failed\n", op->o_log_prefix, 0, 0 ); /* get_ctrls has sent results. Now clean up. */ goto cleanup; } rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modify: invalid dn (%s)\n", op->o_log_prefix, dn.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" ); goto cleanup; } op->orm_no_opattrs = 0; #ifdef LDAP_DEBUG Debug( LDAP_DEBUG_ARGS, "%s modifications:\n", op->o_log_prefix, 0, 0 ); for ( tmp = op->orm_modlist; tmp != NULL; tmp = tmp->sml_next ) { Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n", tmp->sml_op == LDAP_MOD_ADD ? "add" : (tmp->sml_op == LDAP_MOD_INCREMENT ? "increment" : (tmp->sml_op == LDAP_MOD_DELETE ? "delete" : "replace")), tmp->sml_type.bv_val, 0 ); if ( tmp->sml_values == NULL ) { Debug( LDAP_DEBUG_ARGS, "%s\n", "\t\tno values", NULL, NULL ); } else if ( BER_BVISNULL( &tmp->sml_values[ 0 ] ) ) { Debug( LDAP_DEBUG_ARGS, "%s\n", "\t\tzero values", NULL, NULL ); } else if ( BER_BVISNULL( &tmp->sml_values[ 1 ] ) ) { Debug( LDAP_DEBUG_ARGS, "%s, length %ld\n", "\t\tone value", (long) tmp->sml_values[0].bv_len, NULL ); } else { Debug( LDAP_DEBUG_ARGS, "%s\n", "\t\tmultiple values", NULL, NULL ); } } if ( StatslogTest( LDAP_DEBUG_STATS ) ) { char abuf[BUFSIZ/2], *ptr = abuf; int len = 0; Statslog( LDAP_DEBUG_STATS, "%s MOD dn=\"%s\"\n", op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 ); for ( tmp = op->orm_modlist; tmp != NULL; tmp = tmp->sml_next ) { if (len + 1 + tmp->sml_type.bv_len > sizeof(abuf)) { Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); len = 0; ptr = abuf; if( 1 + tmp->sml_type.bv_len > sizeof(abuf)) { Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n", op->o_log_prefix, tmp->sml_type.bv_val, 0, 0, 0 ); continue; } } if (len) { *ptr++ = ' '; len++; } ptr = lutil_strcopy(ptr, tmp->sml_type.bv_val); len += tmp->sml_type.bv_len; } if (len) { Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); } } #endif /* LDAP_DEBUG */ rs->sr_err = slap_mods_check( op, op->orm_modlist, &rs->sr_text, textbuf, textlen, NULL ); if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } op->o_bd = frontendDB; rs->sr_err = frontendDB->be_modify( op, rs ); #ifdef LDAP_X_TXN if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) { /* skip cleanup */ return rs->sr_err; } #endif cleanup: op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); if ( op->orm_modlist != NULL ) slap_mods_free( op->orm_modlist, 1 ); return rs->sr_err; }
int slap_parse_modlist( Operation *op, SlapReply *rs, BerElement *ber, req_modify_s *ms ) { ber_tag_t tag; ber_len_t len; char *last; Modifications **modtail = &ms->rs_mods.rs_modlist; ms->rs_mods.rs_modlist = NULL; ms->rs_increment = 0; rs->sr_err = LDAP_SUCCESS; /* collect modifications & save for later */ for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT; tag = ber_next_element( ber, &len, last ) ) { ber_int_t mop; Modifications tmp, *mod; tmp.sml_nvalues = NULL; if ( ber_scanf( ber, "{e{m[W]}}", &mop, &tmp.sml_type, &tmp.sml_values ) == LBER_ERROR ) { rs->sr_text = "decoding modlist error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } mod = (Modifications *) ch_malloc( sizeof(Modifications) ); mod->sml_op = mop; mod->sml_flags = 0; mod->sml_type = tmp.sml_type; mod->sml_values = tmp.sml_values; mod->sml_nvalues = NULL; mod->sml_desc = NULL; mod->sml_next = NULL; *modtail = mod; switch( mop ) { case LDAP_MOD_ADD: if ( mod->sml_values == NULL ) { rs->sr_text = "modify/add operation requires values"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } /* fall through */ case LDAP_MOD_DELETE: case LDAP_MOD_REPLACE: break; case LDAP_MOD_INCREMENT: if( op->o_protocol >= LDAP_VERSION3 ) { ms->rs_increment++; if ( mod->sml_values == NULL ) { rs->sr_text = "modify/increment operation requires value"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } if ( !BER_BVISNULL( &mod->sml_values[ 1 ] ) ) { rs->sr_text = "modify/increment operation requires single value"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } break; } /* fall thru */ default: rs->sr_text = "unrecognized modify operation"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } modtail = &mod->sml_next; } *modtail = NULL; done: if ( rs->sr_err != LDAP_SUCCESS ) { slap_mods_free( ms->rs_mods.rs_modlist, 1 ); ms->rs_mods.rs_modlist = NULL; ms->rs_increment = 0; } return rs->sr_err; }
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 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); }
/* ** Adds all entries matching the passed filter to the specified group. ** If modify == 1, then we modify the group's entry in the database using be_modify. ** If modify == 0, then, we must supply a rw entry for the group, ** because we only modify the entry, without calling be_modify. ** e - the group entry, to which the members will be added ** age - the group ** agf - the filter */ static int autogroup_add_members_from_filter( Operation *op, Entry *e, autogroup_entry_t *age, autogroup_filter_t *agf, int modify) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; Operation o = *op; SlapReply rs = { REP_SEARCH }; slap_callback cb = { 0 }; slap_callback null_cb = { NULL, slap_null_cb, NULL, NULL }; autogroup_ga_t agg; Debug(LDAP_DEBUG_TRACE, "==> autogroup_add_members_from_filter <%s>\n", age->age_dn.bv_val, 0, 0); o.ors_attrsonly = 0; o.o_tag = LDAP_REQ_SEARCH; o.o_req_dn = agf->agf_dn; o.o_req_ndn = agf->agf_ndn; o.ors_filterstr = agf->agf_filterstr; o.ors_filter = agf->agf_filter; o.ors_scope = agf->agf_scope; o.ors_deref = LDAP_DEREF_NEVER; o.ors_limit = NULL; o.ors_tlimit = SLAP_NO_LIMIT; o.ors_slimit = SLAP_NO_LIMIT; o.ors_attrs = slap_anlist_no_attrs; agg.agg_group = age; agg.agg_mod = NULL; agg.agg_mod_last = NULL; agg.agg_entry = e; cb.sc_private = &agg; if ( modify == 1 ) { cb.sc_response = autogroup_member_search_modify_cb; } else { cb.sc_response = autogroup_member_search_cb; } cb.sc_cleanup = NULL; cb.sc_next = NULL; o.o_callback = &cb; o.o_bd->bd_info = (BackendInfo *)on->on_info; op->o_bd->be_search( &o, &rs ); o.o_bd->bd_info = (BackendInfo *)on; if ( modify == 1 ) { o = *op; o.o_callback = &null_cb; o.o_tag = LDAP_REQ_MODIFY; o.orm_modlist = agg.agg_mod; o.o_req_dn = age->age_dn; o.o_req_ndn = age->age_ndn; o.o_relax = SLAP_CONTROL_CRITICAL; o.o_managedsait = SLAP_CONTROL_NONCRITICAL; o.o_permissive_modify = 1; o.o_bd->bd_info = (BackendInfo *)on->on_info; (void)op->o_bd->be_modify( &o, &rs ); o.o_bd->bd_info = (BackendInfo *)on; slap_mods_free(agg.agg_mod, 1); } return 0; }
static int pguid_repair( BackendDB *be ) { slap_overinst *on = (slap_overinst *)be->bd_info; void *ctx = ldap_pvt_thread_pool_context(); Connection conn = { 0 }; OperationBuffer opbuf; Operation *op; slap_callback sc = { 0 }; pguid_repair_cb_t pcb = { 0 }; SlapReply rs = { REP_RESULT }; pguid_mod_t *pmod; int nrepaired = 0; connection_fake_init2( &conn, &opbuf, ctx, 0 ); op = &opbuf.ob_op; op->o_tag = LDAP_REQ_SEARCH; memset( &op->oq_search, 0, sizeof( op->oq_search ) ); op->o_bd = select_backend( &be->be_nsuffix[ 0 ], 0 ); op->o_req_dn = op->o_bd->be_suffix[ 0 ]; op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ]; op->o_dn = op->o_bd->be_rootdn; op->o_ndn = op->o_bd->be_rootndn; op->ors_scope = LDAP_SCOPE_SUBORDINATE; op->ors_tlimit = SLAP_NO_LIMIT; op->ors_slimit = SLAP_NO_LIMIT; op->ors_attrs = slap_anlist_no_attrs; op->ors_filterstr.bv_len = STRLENOF( "(!(=*))" ) + ad_parentUUID->ad_cname.bv_len; op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx ); snprintf( op->ors_filterstr.bv_val, op->ors_filterstr.bv_len + 1, "(!(%s=*))", ad_parentUUID->ad_cname.bv_val ); op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val ); if ( op->ors_filter == NULL ) { rs.sr_err = LDAP_OTHER; goto done_search; } op->o_callback = ≻ sc.sc_response = pguid_repair_cb; sc.sc_private = &pcb; pcb.on = on; (void)op->o_bd->bd_info->bi_op_search( op, &rs ); op->o_tag = LDAP_REQ_MODIFY; sc.sc_response = slap_null_cb; sc.sc_private = NULL; memset( &op->oq_modify, 0, sizeof( req_modify_s ) ); for ( pmod = pcb.mods; pmod != NULL; ) { pguid_mod_t *pnext; Modifications *mod; SlapReply rs2 = { REP_RESULT }; mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); mod->sml_flags = SLAP_MOD_INTERNAL; mod->sml_op = LDAP_MOD_REPLACE; mod->sml_desc = ad_parentUUID; mod->sml_type = ad_parentUUID->ad_cname; mod->sml_values = ch_malloc( sizeof( struct berval ) * 2 ); mod->sml_nvalues = NULL; mod->sml_numvals = 1; mod->sml_next = NULL; ber_dupbv( &mod->sml_values[0], &pmod->pguid ); BER_BVZERO( &mod->sml_values[1] ); op->o_req_dn = pmod->ndn; op->o_req_ndn = pmod->ndn; op->orm_modlist = mod; op->o_bd->be_modify( op, &rs2 ); slap_mods_free( op->orm_modlist, 1 ); if ( rs2.sr_err == LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "%s: pguid_repair: entry DN=\"%s\" repaired\n", op->o_log_prefix, pmod->ndn.bv_val, 0 ); nrepaired++; } else { Debug( LDAP_DEBUG_ANY, "%s: pguid_repair: entry DN=\"%s\" repair failed (%d)\n", op->o_log_prefix, pmod->ndn.bv_val, rs2.sr_err ); } pnext = pmod->next; op->o_tmpfree( pmod, op->o_tmpmemctx ); pmod = pnext; } done_search:; op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); filter_free_x( op, op->ors_filter, 1 ); Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO, "pguid: repaired=%d\n", nrepaired ); return rs.sr_err; }
static int slap_auxprop_store( void *glob_context, sasl_server_params_t *sparams, struct propctx *prctx, const char *user, unsigned ulen) { Operation op = {0}; Opheader oph; int rc, i; unsigned j; Connection *conn = NULL; const struct propval *pr; Modifications *modlist = NULL, **modtail = &modlist, *mod; slap_callback cb = { NULL, slap_null_cb, NULL, NULL }; char textbuf[SLAP_TEXT_BUFLEN]; const char *text; size_t textlen = sizeof(textbuf); #ifdef SLAP_AUXPROP_DONTUSECOPY int dontUseCopy = 0; BackendDB *dontUseCopy_bd = NULL; #endif /* SLAP_AUXPROP_DONTUSECOPY */ /* just checking if we are enabled */ if (!prctx) return SASL_OK; if (!sparams || !user) return SASL_BADPARAM; pr = sparams->utils->prop_get( sparams->propctx ); /* Find our DN and conn first */ for( i = 0; pr[i].name; i++ ) { if ( pr[i].name[0] == '*' ) { if ( !strcmp( pr[i].name, slap_propnames[SLAP_SASL_PROP_CONN] ) ) { if ( pr[i].values && pr[i].values[0] ) AC_MEMCPY( &conn, pr[i].values[0], sizeof( conn ) ); continue; } if ( !strcmp( pr[i].name, slap_propnames[SLAP_SASL_PROP_AUTHCLEN] )) { if ( pr[i].values && pr[i].values[0] ) AC_MEMCPY( &op.o_req_ndn.bv_len, pr[i].values[0], sizeof( op.o_req_ndn.bv_len ) ); } else if ( !strcmp( pr[i].name, slap_propnames[SLAP_SASL_PROP_AUTHC] ) ) { if ( pr[i].values ) op.o_req_ndn.bv_val = (char *)pr[i].values[0]; } #ifdef SLAP_AUXPROP_DONTUSECOPY if ( slap_dontUseCopy_propnames != NULL ) { struct berval bv; ber_str2bv( &pr[i].name[1], 0, 1, &bv ); for ( j = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ j ] ); j++ ) { if ( bvmatch( &bv, &slap_dontUseCopy_propnames[ j ] ) ) { dontUseCopy = 1; break; } } } #endif /* SLAP_AUXPROP_DONTUSECOPY */ } } if (!conn || !op.o_req_ndn.bv_val) return SASL_BADPARAM; op.o_bd = select_backend( &op.o_req_ndn, 1 ); if ( !op.o_bd || !op.o_bd->be_modify ) return SASL_FAIL; #ifdef SLAP_AUXPROP_DONTUSECOPY if ( SLAP_SHADOW( op.o_bd ) && dontUseCopy ) { dontUseCopy_bd = op.o_bd; op.o_bd = frontendDB; op.o_dontUseCopy = SLAP_CONTROL_CRITICAL; } #endif /* SLAP_AUXPROP_DONTUSECOPY */ pr = sparams->utils->prop_get( prctx ); if (!pr) return SASL_BADPARAM; for (i=0; pr[i].name; i++); if (!i) return SASL_BADPARAM; for (i=0; pr[i].name; i++) { mod = (Modifications *)ch_malloc( sizeof(Modifications) ); mod->sml_op = LDAP_MOD_REPLACE; mod->sml_flags = 0; ber_str2bv( pr[i].name, 0, 0, &mod->sml_type ); mod->sml_numvals = pr[i].nvalues; mod->sml_values = (struct berval *)ch_malloc( (pr[i].nvalues + 1) * sizeof(struct berval)); for (j=0; j<pr[i].nvalues; j++) { ber_str2bv( pr[i].values[j], 0, 1, &mod->sml_values[j]); } BER_BVZERO( &mod->sml_values[j] ); mod->sml_nvalues = NULL; mod->sml_desc = NULL; *modtail = mod; modtail = &mod->sml_next; } *modtail = NULL; rc = slap_mods_check( &op, modlist, &text, textbuf, textlen, NULL ); if ( rc == LDAP_SUCCESS ) { rc = slap_mods_no_user_mod_check( &op, modlist, &text, textbuf, textlen ); if ( rc == LDAP_SUCCESS ) { if ( conn->c_sasl_bindop ) { op.o_hdr = conn->c_sasl_bindop->o_hdr; } else { op.o_hdr = &oph; memset( &oph, 0, sizeof(oph) ); operation_fake_init( conn, &op, ldap_pvt_thread_pool_context(), 0 ); } op.o_tag = LDAP_REQ_MODIFY; op.o_ndn = op.o_req_ndn; op.o_callback = &cb; slap_op_time( &op.o_time, &op.o_tincr ); op.o_do_not_cache = 1; op.o_is_auth_check = 1; op.o_req_dn = op.o_req_ndn; op.orm_modlist = modlist; for (;;) { SlapReply rs = {REP_RESULT}; rc = op.o_bd->be_modify( &op, &rs ); #ifdef SLAP_AUXPROP_DONTUSECOPY if ( dontUseCopy && rs.sr_err == LDAP_UNAVAILABLE && slap_dontUseCopy_ignore ) { op.o_bd = dontUseCopy_bd; op.o_dontUseCopy = SLAP_CONTROL_NONE; dontUseCopy = 0; continue; } #endif /* SLAP_AUXPROP_DONTUSECOPY */ break; } } } slap_mods_free( modlist, 1 ); return rc != LDAP_SUCCESS ? SASL_FAIL : SASL_OK; }
int do_add( Connection *conn, Operation *op ) { BerElement *ber = op->o_ber; char *last; struct berval dn = { 0, NULL }; ber_len_t len; ber_tag_t tag; Entry *e; Backend *be; Modifications *modlist = NULL; Modifications **modtail = &modlist; Modifications tmp; const char *text; int rc = LDAP_SUCCESS; int manageDSAit; #ifdef LDAP_SLAPI Slapi_PBlock *pb = NULL; #endif /* LDAP_SLAPI */ #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ENTRY, "do_add: conn %d enter\n", conn->c_connid,0,0 ); #else Debug( LDAP_DEBUG_TRACE, "do_add\n", 0, 0, 0 ); #endif /* * Parse the add request. It looks like this: * * AddRequest := [APPLICATION 14] SEQUENCE { * name DistinguishedName, * attrs SEQUENCE OF SEQUENCE { * type AttributeType, * values SET OF AttributeValue * } * } */ /* get the name */ if ( ber_scanf( ber, "{m", /*}*/ &dn ) == LBER_ERROR ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "do_add: conn %d ber_scanf failed\n", conn->c_connid,0,0 ); #else Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 ); #endif send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, "decoding error" ); return -1; } e = (Entry *) ch_calloc( 1, sizeof(Entry) ); rc = dnPrettyNormal( NULL, &dn, &e->e_name, &e->e_nname ); if( rc != LDAP_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "do_add: conn %d invalid dn (%s)\n", conn->c_connid, dn.bv_val, 0 ); #else Debug( LDAP_DEBUG_ANY, "do_add: invalid dn (%s)\n", dn.bv_val, 0, 0 ); #endif send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL, "invalid DN", NULL, NULL ); goto done; } #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ARGS, "do_add: conn %d dn (%s)\n", conn->c_connid, e->e_dn, 0 ); #else Debug( LDAP_DEBUG_ARGS, "do_add: dn (%s)\n", e->e_dn, 0, 0 ); #endif /* get the attrs */ for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT; tag = ber_next_element( ber, &len, last ) ) { Modifications *mod; ber_tag_t rtag; rtag = ber_scanf( ber, "{m{W}}", &tmp.sml_type, &tmp.sml_bvalues ); if ( rtag == LBER_ERROR ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "do_add: conn %d decoding error \n", conn->c_connid, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "do_add: decoding error\n", 0, 0, 0 ); #endif send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, "decoding error" ); rc = -1; goto done; } if ( tmp.sml_bvalues == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "do_add: conn %d no values for type %s\n", conn->c_connid, tmp.sml_type.bv_val, 0 ); #else Debug( LDAP_DEBUG_ANY, "no values for type %s\n", tmp.sml_type.bv_val, 0, 0 ); #endif send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "no values for attribute type", NULL, NULL ); goto done; } mod = (Modifications *) ch_malloc( sizeof(Modifications) ); mod->sml_op = LDAP_MOD_ADD; mod->sml_next = NULL; mod->sml_desc = NULL; mod->sml_type = tmp.sml_type; mod->sml_bvalues = tmp.sml_bvalues; *modtail = mod; modtail = &mod->sml_next; } if ( ber_scanf( ber, /*{*/ "}") == LBER_ERROR ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, ERR, "do_add: conn %d ber_scanf failed\n", conn->c_connid, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 ); #endif send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, "decoding error" ); rc = -1; goto done; } if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) { #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "do_add: conn %d get_ctrls failed\n", conn->c_connid, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 ); #endif goto done; } if ( modlist == NULL ) { send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "no attributes provided", NULL, NULL ); goto done; } Statslog( LDAP_DEBUG_STATS, "conn=%lu op=%lu ADD dn=\"%s\"\n", op->o_connid, op->o_opid, e->e_dn, 0, 0 ); if( e->e_nname.bv_len == 0 ) { /* protocolError may be a more appropriate error */ send_ldap_result( conn, op, rc = LDAP_ALREADY_EXISTS, NULL, "root DSE already exists", NULL, NULL ); goto done; } else if ( bvmatch( &e->e_nname, &global_schemandn ) ) { send_ldap_result( conn, op, rc = LDAP_ALREADY_EXISTS, NULL, "subschema subentry already exists", NULL, NULL ); goto done; } manageDSAit = get_manageDSAit( op ); /* * 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. */ be = select_backend( &e->e_nname, manageDSAit, 0 ); if ( be == NULL ) { BerVarray ref = referral_rewrite( default_referral, NULL, &e->e_name, LDAP_SCOPE_DEFAULT ); if ( ref == NULL ) ref = default_referral; if ( ref != NULL ) { send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL, ref, NULL ); if ( ref != default_referral ) ber_bvarray_free( ref ); } else { send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL, "referral missing", NULL, NULL ); } goto done; } /* check restrictions */ rc = backend_check_restrictions( be, conn, op, NULL, &text ) ; if( rc != LDAP_SUCCESS ) { send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); goto done; } /* check for referrals */ rc = backend_check_referrals( be, conn, op, &e->e_name, &e->e_nname ); if ( rc != LDAP_SUCCESS ) { goto done; } #ifdef LDAP_SLAPI pb = initAddPlugin( be, conn, op, &dn, e, manageDSAit ); #endif /* LDAP_SLAPI */ /* * do the add if 1 && (2 || 3) * 1) there is an add function implemented in this backend; * 2) this backend is master for what it holds; * 3) it's a replica and the dn supplied is the updatedn. */ if ( be->be_add ) { /* do the update here */ int repl_user = be_isupdate(be, &op->o_ndn ); #ifndef SLAPD_MULTIMASTER if ( !be->be_update_ndn.bv_len || repl_user ) #endif { int update = be->be_update_ndn.bv_len; char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; rc = slap_mods_check( modlist, update, &text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); goto done; } if ( !repl_user ) { for( modtail = &modlist; *modtail != NULL; modtail = &(*modtail)->sml_next ) { assert( (*modtail)->sml_op == LDAP_MOD_ADD ); assert( (*modtail)->sml_desc != NULL ); } rc = slap_mods_opattrs( be, op, modlist, modtail, &text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); goto done; } } rc = slap_mods2entry( modlist, &e, repl_user, &text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); goto done; } #ifdef LDAP_SLAPI /* * Call the preoperation plugin here, because the entry * will actually contain something. */ rc = doPreAddPluginFNs( be, pb ); if ( rc != LDAP_SUCCESS ) { /* plugin will have sent result */ goto done; } #endif /* LDAP_SLAPI */ if ( (*be->be_add)( be, conn, op, e ) == 0 ) { #ifdef SLAPD_MULTIMASTER if ( !repl_user ) #endif { replog( be, op, &e->e_name, &e->e_nname, e ); } be_entry_release_w( be, conn, op, e ); e = NULL; } #ifndef SLAPD_MULTIMASTER } else { BerVarray defref; BerVarray ref; #ifdef LDAP_SLAPI /* * SLAPI_ADD_ENTRY will be empty, but this may be acceptable * on replicas (for now, it involves the minimum code intrusion). */ rc = doPreAddPluginFNs( be, pb ); if ( rc != LDAP_SUCCESS ) { /* plugin will have sent result */ goto done; } #endif /* LDAP_SLAPI */ defref = be->be_update_refs ? be->be_update_refs : default_referral; if ( defref ) { ref = referral_rewrite( defref, NULL, &e->e_name, LDAP_SCOPE_DEFAULT ); send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL, ref ? ref : defref, NULL ); if ( ref ) ber_bvarray_free( ref ); } else { send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL, "referral missing", NULL, NULL ); } #endif /* SLAPD_MULTIMASTER */ } } else { #ifdef LDAP_SLAPI rc = doPreAddPluginFNs( be, pb ); if ( rc != LDAP_SUCCESS ) { /* plugin will have sent result */ goto done; } #endif #ifdef NEW_LOGGING LDAP_LOG( OPERATION, INFO, "do_add: conn %d no backend support\n", conn->c_connid, 0, 0 ); #else Debug( LDAP_DEBUG_ARGS, " do_add: no backend support\n", 0, 0, 0 ); #endif send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL, "operation not supported within namingContext", NULL, NULL ); } #ifdef LDAP_SLAPI doPostAddPluginFNs( be, pb ); #endif /* LDAP_SLAPI */ done: if( modlist != NULL ) { slap_mods_free( modlist ); } if( e != NULL ) { entry_free( e ); } return rc; }
static int pam_sess(nssov_info *ni,TFILE *fp,Operation *op,int action) { struct berval dn, uid, svc, tty, rhost, ruser; int32_t tmpint32; char dnc[1024]; char svcc[256]; char uidc[32]; char ttyc[32]; char rhostc[256]; char ruserc[32]; slap_callback cb = {0}; SlapReply rs = {REP_RESULT}; char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE]; struct berval timestamp, bv[2], *nbv; time_t stamp; Modifications mod; 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,ttyc); tty.bv_val = ttyc; tty.bv_len = tmpint32; READ_STRING(fp,rhostc); rhost.bv_val = rhostc; rhost.bv_len = tmpint32; READ_STRING(fp,ruserc); ruser.bv_val = ruserc; ruser.bv_len = tmpint32; READ_INT32(fp,stamp); Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(%s)\n", action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', dn.bv_val,0); if (!dn.bv_len || !ni->ni_pam_sessions) return 0; { int i, found=0; for (i=0; !BER_BVISNULL(&ni->ni_pam_sessions[i]); i++) { if (ni->ni_pam_sessions[i].bv_len != svc.bv_len) continue; if (!strcasecmp(ni->ni_pam_sessions[i].bv_val, svc.bv_val)) { found = 1; break; } } if (!found) return 0; } slap_op_time( &op->o_time, &op->o_tincr ); timestamp.bv_len = sizeof(timebuf); timestamp.bv_val = timebuf; if (action == NSLCD_ACTION_PAM_SESS_O ) stamp = op->o_time; slap_timestamp( &stamp, ×tamp ); bv[0].bv_len = timestamp.bv_len + global_host_bv.bv_len + svc.bv_len + tty.bv_len + ruser.bv_len + rhost.bv_len + STRLENOF(" (@)"); bv[0].bv_val = op->o_tmpalloc( bv[0].bv_len+1, op->o_tmpmemctx ); sprintf(bv[0].bv_val, "%s %s %s %s (%s@%s)", timestamp.bv_val, global_host_bv.bv_val, svc.bv_val, tty.bv_val, ruser.bv_val, rhost.bv_val); mod.sml_numvals = 1; mod.sml_values = bv; BER_BVZERO(&bv[1]); attr_normalize( ad_loginStatus, bv, &nbv, op->o_tmpmemctx ); mod.sml_nvalues = nbv; mod.sml_desc = ad_loginStatus; mod.sml_op = action == NSLCD_ACTION_PAM_SESS_O ? LDAP_MOD_ADD : LDAP_MOD_DELETE; mod.sml_flags = SLAP_MOD_INTERNAL; mod.sml_next = NULL; cb.sc_response = slap_null_cb; op->o_callback = &cb; op->o_tag = LDAP_REQ_MODIFY; op->o_dn = op->o_bd->be_rootdn; op->o_ndn = op->o_bd->be_rootndn; op->orm_modlist = &mod; op->orm_no_opattrs = 1; op->o_req_dn = dn; op->o_req_ndn = dn; op->o_bd->be_modify( op, &rs ); if ( mod.sml_next ) { slap_mods_free( mod.sml_next, 1 ); } ber_bvarray_free_x( nbv, op->o_tmpmemctx ); WRITE_INT32(fp,NSLCD_VERSION); WRITE_INT32(fp,action); WRITE_INT32(fp,NSLCD_RESULT_BEGIN); WRITE_INT32(fp,op->o_time); return 0; }
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 vernum_repair( BackendDB *be ) { slap_overinst *on = (slap_overinst *)be->bd_info; vernum_t *vn = (vernum_t *)on->on_bi.bi_private; void *ctx = ldap_pvt_thread_pool_context(); Connection conn = { 0 }; OperationBuffer opbuf; Operation *op; BackendDB db; slap_callback sc = { 0 }; vernum_repair_cb_t rcb = { 0 }; SlapReply rs = { REP_RESULT }; vernum_mod_t *rmod; int nrepaired = 0; connection_fake_init2( &conn, &opbuf, ctx, 0 ); op = &opbuf.ob_op; op->o_tag = LDAP_REQ_SEARCH; memset( &op->oq_search, 0, sizeof( op->oq_search ) ); assert( !BER_BVISNULL( &be->be_nsuffix[ 0 ] ) ); op->o_bd = select_backend( &be->be_nsuffix[ 0 ], 0 ); assert( op->o_bd != NULL ); assert( op->o_bd->be_nsuffix != NULL ); op->o_req_dn = op->o_bd->be_suffix[ 0 ]; op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ]; op->o_dn = op->o_bd->be_rootdn; op->o_ndn = op->o_bd->be_rootndn; op->ors_scope = LDAP_SCOPE_SUBTREE; op->ors_tlimit = SLAP_NO_LIMIT; op->ors_slimit = SLAP_NO_LIMIT; op->ors_attrs = slap_anlist_no_attrs; op->ors_filterstr.bv_len = STRLENOF( "(&(=*)(!(=*)))" ) + vn->vn_attr->ad_cname.bv_len + vn->vn_vernum->ad_cname.bv_len; op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx ); snprintf( op->ors_filterstr.bv_val, op->ors_filterstr.bv_len + 1, "(&(%s=*)(!(%s=*)))", vn->vn_attr->ad_cname.bv_val, vn->vn_vernum->ad_cname.bv_val ); op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val ); if ( op->ors_filter == NULL ) { rs.sr_err = LDAP_OTHER; goto done_search; } op->o_callback = ≻ sc.sc_response = vernum_repair_cb; sc.sc_private = &rcb; rcb.bd = &db; db = *be; db.bd_info = (BackendInfo *)on; (void)op->o_bd->bd_info->bi_op_search( op, &rs ); op->o_tag = LDAP_REQ_MODIFY; sc.sc_response = slap_null_cb; sc.sc_private = NULL; memset( &op->oq_modify, 0, sizeof( req_modify_s ) ); for ( rmod = rcb.mods; rmod != NULL; ) { vernum_mod_t *rnext; Modifications mod; struct berval vals[2] = { BER_BVNULL }; SlapReply rs2 = { REP_RESULT }; mod.sml_flags = SLAP_MOD_INTERNAL; mod.sml_op = LDAP_MOD_REPLACE; mod.sml_desc = vn->vn_vernum; mod.sml_type = vn->vn_vernum->ad_cname; mod.sml_values = vals; mod.sml_values[0] = val_init; mod.sml_nvalues = NULL; mod.sml_numvals = 1; mod.sml_next = NULL; op->o_req_dn = rmod->ndn; op->o_req_ndn = rmod->ndn; op->orm_modlist = &mod; op->o_bd->be_modify( op, &rs2 ); slap_mods_free( op->orm_modlist->sml_next, 1 ); if ( rs2.sr_err == LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "%s: vernum_repair: entry DN=\"%s\" repaired\n", op->o_log_prefix, rmod->ndn.bv_val, 0 ); nrepaired++; } else { Debug( LDAP_DEBUG_ANY, "%s: vernum_repair: entry DN=\"%s\" repair failed (%d)\n", op->o_log_prefix, rmod->ndn.bv_val, rs2.sr_err ); } rnext = rmod->next; op->o_tmpfree( rmod, op->o_tmpmemctx ); rmod = rnext; } done_search:; op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); filter_free_x( op, op->ors_filter, 1 ); Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO, "vernum: repaired=%d\n", nrepaired ); return 0; }
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; }