📄 slapi_overlay.c
字号:
/* slapi_overlay.c - SLAPI overlay *//* $OpenLDAP: pkg/ldap/servers/slapd/slapi/slapi_overlay.c,v 1.34.2.6 2007/01/02 21:44:11 kurt Exp $ *//* This work is part of OpenLDAP Software <http://www.openldap.org/>. * * Copyright 2001-2007 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * <http://www.OpenLDAP.org/license.html>. *//* ACKNOWLEDGEMENTS: * This work was initially developed by Luke Howard for inclusion * in OpenLDAP Software. */#include "portable.h"#include <stdio.h>#include <ac/string.h>#include <ac/socket.h>#include "slap.h"#include "slapi.h"#ifdef LDAP_SLAPIstatic slap_overinst slapi;static int slapi_over_initialized = 0;static int slapi_over_response( Operation *op, SlapReply *rs );static int slapi_over_cleanup( Operation *op, SlapReply *rs );static Slapi_PBlock *slapi_over_pblock_new( Operation *op, SlapReply *rs ){ Slapi_PBlock *pb; pb = slapi_pblock_new(); pb->pb_op = op; pb->pb_conn = op->o_conn; pb->pb_rs = rs; pb->pb_intop = 0; PBLOCK_ASSERT_OP( pb, op->o_tag ); return pb;}static intslapi_op_internal_p( Operation *op, SlapReply *rs, slap_callback *cb ){ int internal_op = 0; Slapi_PBlock *pb = NULL; slap_callback *pcb; /* * Abstraction violating check for SLAPI internal operations * allows pblock to remain consistent when invoking internal * op plugins */ for ( pcb = op->o_callback; pcb != NULL; pcb = pcb->sc_next ) { if ( pcb->sc_response == slapi_int_response ) { pb = (Slapi_PBlock *)pcb->sc_private; PBLOCK_ASSERT_INTOP( pb, 0 ); internal_op = 1; break; } } if ( cb != NULL ) { if ( pb == NULL ) { pb = slapi_over_pblock_new( op, rs ); } cb->sc_response = slapi_over_response; cb->sc_cleanup = slapi_over_cleanup; cb->sc_private = pb; cb->sc_next = op->o_callback; op->o_callback = cb; } return internal_op;}static intslapi_over_compute_output( computed_attr_context *c, Slapi_Attr *attribute, Slapi_Entry *entry){ Attribute **a; AttributeDescription *desc; SlapReply *rs = (SlapReply *)c->cac_private; if ( c == NULL || attribute == NULL || entry == NULL ) { return 0; } assert( rs->sr_entry == entry ); desc = attribute->a_desc; if ( rs->sr_attrs == NULL ) { /* All attrs request, skip operational attributes */ if ( is_at_operational( desc->ad_type ) ) { return 0; } } else { /* Specific attributes requested */ if ( is_at_operational( desc->ad_type ) ) { if ( !SLAP_OPATTRS( rs->sr_attr_flags ) && !ad_inlist( desc, rs->sr_attrs ) ) { return 0; } } else { if ( !SLAP_USERATTRS( rs->sr_attr_flags ) && !ad_inlist( desc, rs->sr_attrs ) ) { return 0; } } } /* XXX perhaps we should check for existing attributes and merge */ for ( a = &rs->sr_operational_attrs; *a != NULL; a = &(*a)->a_next ) ; *a = slapi_attr_dup( attribute ); return 0;}static intslapi_over_aux_operational( Operation *op, SlapReply *rs ){ /* Support for computed attribute plugins */ computed_attr_context ctx; AttributeName *anp; if ( slapi_op_internal_p( op, rs, NULL ) ) { return SLAP_CB_CONTINUE; } ctx.cac_pb = slapi_over_pblock_new( op, rs ); ctx.cac_op = op; ctx.cac_private = rs; if ( rs->sr_entry != NULL ) { /* * For each client requested attribute, call the plugins. */ if ( rs->sr_attrs != NULL ) { for ( anp = rs->sr_attrs; anp->an_name.bv_val != NULL; anp++ ) { if ( compute_evaluator( &ctx, anp->an_name.bv_val, rs->sr_entry, slapi_over_compute_output ) == 1 ) { break; } } } else { /* * Technically we shouldn't be returning operational attributes * when the user requested only user attributes. We'll let the * plugin decide whether to be naughty or not. */ compute_evaluator( &ctx, "*", rs->sr_entry, slapi_over_compute_output ); } } slapi_pblock_destroy( ctx.cac_pb ); return SLAP_CB_CONTINUE;}/* * We need this function to call frontendDB (global) plugins before * database plugins, if we are invoked by a slap_callback. */static intslapi_over_call_plugins( Slapi_PBlock *pb, int type ){ int rc = 1; /* means no plugins called */ Operation *op; PBLOCK_ASSERT_OP( pb, 0 ); op = pb->pb_op; if ( !be_match( op->o_bd, frontendDB ) ) { rc = slapi_int_call_plugins( frontendDB, type, pb ); } if ( rc >= 0 ) { rc = slapi_int_call_plugins( op->o_bd, type, pb ); } return rc;}static intslapi_over_search( Operation *op, SlapReply *rs, int type ){ int rc; Slapi_PBlock *pb; assert( rs->sr_type == REP_SEARCH || rs->sr_type == REP_SEARCHREF ); /* create a new pblock to not trample on result controls */ pb = slapi_over_pblock_new( op, rs ); rc = slapi_over_call_plugins( pb, type ); if ( rc >= 0 ) /* 1 means no plugins called */ rc = SLAP_CB_CONTINUE; else rc = LDAP_SUCCESS; /* confusing: don't abort, but don't send */ slapi_pblock_destroy(pb); return rc;}/* * Call pre- and post-result plugins */static intslapi_over_result( Operation *op, SlapReply *rs, int type ){ Slapi_PBlock *pb = SLAPI_OPERATION_PBLOCK( op ); assert( rs->sr_type == REP_RESULT ); slapi_over_call_plugins( pb, type ); return SLAP_CB_CONTINUE;}static intslapi_op_bind_callback( Operation *op, SlapReply *rs, int prc ){ switch ( prc ) { case SLAPI_BIND_SUCCESS: /* Continue with backend processing */ break; case SLAPI_BIND_FAIL: /* Failure, frontend (that's us) sends result */ rs->sr_err = LDAP_INVALID_CREDENTIALS; send_ldap_result( op, rs ); return rs->sr_err; break; case SLAPI_BIND_ANONYMOUS: /* undocumented */ default: /* plugin sent result or no plugins called */ BER_BVZERO( &op->orb_edn ); if ( rs->sr_err == LDAP_SUCCESS ) { /* * Plugin will have called slapi_pblock_set(LDAP_CONN_DN) which * will have set conn->c_dn and conn->c_ndn */ if ( BER_BVISNULL( &op->o_conn->c_ndn ) && prc == 1 ) { /* No plugins were called; continue processing */ return LDAP_SUCCESS; } ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); if ( !BER_BVISEMPTY( &op->o_conn->c_ndn ) ) { ber_len_t max = sockbuf_max_incoming_auth; ber_sockbuf_ctrl( op->o_conn->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max ); } ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); /* log authorization identity */ Statslog( LDAP_DEBUG_STATS, "%s BIND dn=\"%s\" mech=%s (SLAPI) ssf=0\n", op->o_log_prefix, BER_BVISNULL( &op->o_conn->c_dn ) ? "<empty>" : op->o_conn->c_dn.bv_val, BER_BVISNULL( &op->orb_tmp_mech ) ? "<empty>" : op->orb_tmp_mech.bv_val, 0, 0 ); return -1; } break; } return rs->sr_err;}static intslapi_op_search_callback( Operation *op, SlapReply *rs, int prc ){ Slapi_PBlock *pb = SLAPI_OPERATION_PBLOCK( op ); /* check preoperation result code */ if ( prc < 0 ) { return rs->sr_err; } rs->sr_err = LDAP_SUCCESS; if ( slapi_int_call_plugins( op->o_bd, SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN, pb ) == 0 ) { /* * The plugin can set the SLAPI_SEARCH_FILTER. * SLAPI_SEARCH_STRFILER is not normative. */ op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); filter2bv_x( op, op->ors_filter, &op->ors_filterstr ); } return LDAP_SUCCESS;}struct slapi_op_info { int soi_preop; /* preoperation plugin parameter */ int soi_postop; /* postoperation plugin parameter */ int soi_internal_preop; /* internal preoperation plugin parameter */ int soi_internal_postop; /* internal postoperation plugin parameter */ int (*soi_callback)(Operation *, SlapReply *, int); /* preoperation result handler */} slapi_op_dispatch_table[] = { { SLAPI_PLUGIN_PRE_BIND_FN, SLAPI_PLUGIN_POST_BIND_FN, 0, 0, slapi_op_bind_callback }, { SLAPI_PLUGIN_PRE_UNBIND_FN, SLAPI_PLUGIN_POST_UNBIND_FN, 0, 0, NULL }, { SLAPI_PLUGIN_PRE_SEARCH_FN, SLAPI_PLUGIN_POST_SEARCH_FN, 0, 0, slapi_op_search_callback }, { SLAPI_PLUGIN_PRE_COMPARE_FN, SLAPI_PLUGIN_POST_COMPARE_FN, 0, 0, NULL }, { SLAPI_PLUGIN_PRE_MODIFY_FN, SLAPI_PLUGIN_POST_MODIFY_FN, SLAPI_PLUGIN_INTERNAL_PRE_MODIFY_FN, SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN, NULL }, { SLAPI_PLUGIN_PRE_MODRDN_FN, SLAPI_PLUGIN_POST_MODRDN_FN, SLAPI_PLUGIN_INTERNAL_PRE_MODRDN_FN, SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN, NULL }, { SLAPI_PLUGIN_PRE_ADD_FN, SLAPI_PLUGIN_POST_ADD_FN, SLAPI_PLUGIN_INTERNAL_PRE_ADD_FN, SLAPI_PLUGIN_INTERNAL_POST_ADD_FN, NULL }, { SLAPI_PLUGIN_PRE_DELETE_FN, SLAPI_PLUGIN_POST_DELETE_FN, SLAPI_PLUGIN_INTERNAL_PRE_DELETE_FN, SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN, NULL }, { SLAPI_PLUGIN_PRE_ABANDON_FN, SLAPI_PLUGIN_POST_ABANDON_FN, 0, 0, NULL }, { 0, 0, 0, 0, NULL }};slap_operation_tslapi_tag2op( ber_tag_t tag ){ slap_operation_t op; switch ( tag ) { case LDAP_REQ_BIND: op = op_bind; break; case LDAP_REQ_ADD: op = op_add; break; case LDAP_REQ_DELETE: op = op_delete; break; case LDAP_REQ_MODRDN: op = op_modrdn; break; case LDAP_REQ_MODIFY: op = op_modify; break; case LDAP_REQ_COMPARE: op = op_compare; break; case LDAP_REQ_SEARCH: op = op_search; break; case LDAP_REQ_UNBIND: op = op_unbind; break; default: op = op_last; break; } return op;}/* Add SLAPI_RESCONTROLS to rs->sr_ctrls, with care, because * rs->sr_ctrls could be allocated on the stack */static intslapi_over_merge_controls( Operation *op, SlapReply *rs ){ Slapi_PBlock *pb = SLAPI_OPERATION_PBLOCK( op ); LDAPControl **ctrls = NULL; LDAPControl **slapi_ctrls = NULL; size_t n_slapi_ctrls = 0; size_t n_rs_ctrls = 0; size_t i; slapi_pblock_get( pb, SLAPI_RESCONTROLS, (void **)&slapi_ctrls ); n_slapi_ctrls = slapi_int_count_controls( slapi_ctrls ); n_rs_ctrls = slapi_int_count_controls( rs->sr_ctrls ); slapi_pblock_set( pb, SLAPI_X_OLD_RESCONTROLS, (void *)rs->sr_ctrls );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -