📄 chain.c
字号:
/* Something for the chain database? */ if ( strncasecmp( argv[ 0 ], "chain-", STRLENOF( "chain-" ) ) == 0 ) { char *save_argv0 = argv[ 0 ]; BackendInfo *bd_info = be->bd_info; void *be_private = be->be_private; ConfigOCs *be_cf_ocs = be->be_cf_ocs; static char *allowed_argv[] = { /* special: put URI here, so in the meanwhile * it detects whether a new URI is being provided */ "uri", "nretries", "timeout", /* flags */ "tls", /* FIXME: maybe rebind-as-user should be allowed * only within known URIs... */ "rebind-as-user", "chase-referrals", "t-f-support", "proxy-whoami", NULL }; int which_argv = -1; argv[ 0 ] += STRLENOF( "chain-" ); for ( which_argv = 0; allowed_argv[ which_argv ]; which_argv++ ) { if ( strcasecmp( argv[ 0 ], allowed_argv[ which_argv ] ) == 0 ) { break; } } if ( allowed_argv[ which_argv ] == NULL ) { which_argv = -1; if ( lc->lc_cfg_li == lc->lc_common_li ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: " "\"%s\" only allowed within a URI directive.\n.", fname, lineno, argv[ 0 ] ); return 1; } } if ( which_argv == 0 ) { rc = ldap_chain_db_init_one( be ); if ( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: " "underlying slapd-ldap initialization failed.\n.", fname, lineno, 0 ); return 1; } lc->lc_cfg_li = be->be_private; } /* TODO: add checks on what other slapd-ldap(5) args * should be put in the template; this is not quite * harmful, because attributes that shouldn't don't * get actually used, but the user should at least * be warned. */ be->bd_info = lback; be->be_private = (void *)lc->lc_cfg_li; be->be_cf_ocs = lback->bi_cf_ocs; rc = config_generic_wrapper( be, fname, lineno, argc, argv ); argv[ 0 ] = save_argv0; be->be_cf_ocs = be_cf_ocs; be->be_private = be_private; be->bd_info = bd_info; if ( which_argv == 0 ) {private_destroy:; if ( rc != 0 ) { BackendDB db = *be; db.bd_info = lback; db.be_private = (void *)lc->lc_cfg_li; ldap_chain_db_destroy_one( &db ); lc->lc_cfg_li = NULL; } else { if ( lc->lc_cfg_li->li_bvuri == NULL || BER_BVISNULL( &lc->lc_cfg_li->li_bvuri[ 0 ] ) || !BER_BVISNULL( &lc->lc_cfg_li->li_bvuri[ 1 ] ) ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: " "no URI list allowed in slapo-chain.\n", fname, lineno, 0 ); rc = 1; goto private_destroy; } if ( avl_insert( &lc->lc_lai.lai_tree, (caddr_t)lc->lc_cfg_li, ldap_chain_uri_cmp, ldap_chain_uri_dup ) ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: " "duplicate URI in slapo-chain.\n", fname, lineno, 0 ); rc = 1; goto private_destroy; } } } } return rc;}enum db_which { db_open = 0, db_close, db_destroy, db_last};typedef struct ldap_chain_db_apply_t { BackendDB *be; BI_db_func *func;} ldap_chain_db_apply_t;static intldap_chain_db_apply( void *datum, void *arg ){ ldapinfo_t *li = (ldapinfo_t *)datum; ldap_chain_db_apply_t *lca = (ldap_chain_db_apply_t *)arg; lca->be->be_private = (void *)li; return lca->func( lca->be );}static intldap_chain_db_func( BackendDB *be, enum db_which which){ slap_overinst *on = (slap_overinst *)be->bd_info; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; int rc = 0; if ( lc ) { BI_db_func *func = (&lback->bi_db_open)[ which ]; if ( func != NULL && lc->lc_common_li != NULL ) { BackendDB db = *be; db.bd_info = lback; db.be_private = lc->lc_common_li; rc = func( &db ); if ( rc != 0 ) { return rc; } if ( lc->lc_lai.lai_tree != NULL ) { ldap_chain_db_apply_t lca; lca.be = &db; lca.func = func; rc = avl_apply( lc->lc_lai.lai_tree, ldap_chain_db_apply, (void *)&lca, 1, AVL_INORDER ) != AVL_NOMORE; } } } return rc;}static intldap_chain_db_open( BackendDB *be ){ slap_overinst *on = (slap_overinst *) be->bd_info; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; int rc = 0;#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR rc = overlay_register_control( be, LDAP_CONTROL_X_CHAINING_BEHAVIOR ); if ( rc != 0 ) { return rc; }#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ if ( lc->lc_common_li == NULL ) { void *be_private = be->be_private; ldap_chain_db_init_common( be ); lc->lc_common_li = lc->lc_cfg_li = (ldapinfo_t *)be->be_private; be->be_private = be_private; } /* filter out and restore monitoring */ rc = ldap_chain_db_func( be, db_open ); return rc;}static intldap_chain_db_close( BackendDB *be ){ return ldap_chain_db_func( be, db_close );}static intldap_chain_db_destroy( BackendDB *be ){ slap_overinst *on = (slap_overinst *) be->bd_info; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; int rc; rc = ldap_chain_db_func( be, db_destroy ); if ( lc ) { avl_free( lc->lc_lai.lai_tree, NULL ); ldap_pvt_thread_mutex_destroy( &lc->lc_lai.lai_mutex ); ch_free( lc ); } return rc;}/* * inits one instance of the slapd-ldap backend, and stores * the private info in be_private of the arg */static intldap_chain_db_init_common( BackendDB *be ){ BackendInfo *bi = be->bd_info; ldapinfo_t *li; int rc; be->bd_info = lback; be->be_private = NULL; rc = lback->bi_db_init( be ); if ( rc != 0 ) { return rc; } li = (ldapinfo_t *)be->be_private; be->bd_info = bi; return 0;}/* * inits one instance of the slapd-ldap backend, stores * the private info in be_private of the arg and fills * selected fields with data from the template. * * NOTE: add checks about the other fields of the template, * which are ignored and SHOULD NOT be configured by the user. */static intldap_chain_db_init_one( BackendDB *be ){ slap_overinst *on = (slap_overinst *)be->bd_info; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; BackendInfo *bi = be->bd_info; ldapinfo_t *li; slap_op_t t; be->bd_info = lback; be->be_private = NULL; t = lback->bi_db_init( be ); if ( t != 0 ) { return t; } li = (ldapinfo_t *)be->be_private; /* copy common data */ li->li_nretries = lc->lc_common_li->li_nretries; li->li_flags = lc->lc_common_li->li_flags; li->li_version = lc->lc_common_li->li_version; for ( t = 0; t < SLAP_OP_LAST; t++ ) { li->li_timeout[ t ] = lc->lc_common_li->li_timeout[ t ]; } be->bd_info = bi; return 0;}static intldap_chain_db_open_one( BackendDB *be ){ return lback->bi_db_open( be );}typedef struct ldap_chain_conn_apply_t { BackendDB *be; Connection *conn;} ldap_chain_conn_apply_t;static intldap_chain_conn_apply( void *datum, void *arg ){ ldapinfo_t *li = (ldapinfo_t *)datum; ldap_chain_conn_apply_t *lca = (ldap_chain_conn_apply_t *)arg; lca->be->be_private = (void *)li; return lback->bi_connection_destroy( lca->be, lca->conn );}static intldap_chain_connection_destroy( BackendDB *be, Connection *conn){ slap_overinst *on = (slap_overinst *) be->bd_info; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; void *private = be->be_private; ldap_chain_conn_apply_t lca; int rc; be->be_private = NULL; lca.be = be; lca.conn = conn; ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex ); rc = avl_apply( lc->lc_lai.lai_tree, ldap_chain_conn_apply, (void *)&lca, 1, AVL_INORDER ) != AVL_NOMORE; ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex ); be->be_private = private; return rc;}#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIORstatic intldap_chain_parse_ctrl( Operation *op, SlapReply *rs, LDAPControl *ctrl ){ ber_tag_t tag; BerElement *ber; ber_int_t mode, behavior; if ( get_chaining( op ) != SLAP_CONTROL_NONE ) { rs->sr_text = "Chaining behavior control specified multiple times"; return LDAP_PROTOCOL_ERROR; } if ( op->o_pagedresults != SLAP_CONTROL_NONE ) { rs->sr_text = "Chaining behavior control specified with pagedResults control"; return LDAP_PROTOCOL_ERROR; } if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) { mode = (SLAP_CH_RESOLVE_DEFAULT|SLAP_CH_CONTINUATION_DEFAULT); } else { ber_len_t len; /* Parse the control value * ChainingBehavior ::= SEQUENCE { * resolveBehavior Behavior OPTIONAL, * continuationBehavior Behavior OPTIONAL } * * Behavior :: = ENUMERATED { * chainingPreferred (0), * chainingRequired (1), * referralsPreferred (2), * referralsRequired (3) } */ ber = ber_init( &ctrl->ldctl_value ); if( ber == NULL ) { rs->sr_text = "internal error"; return LDAP_OTHER; } tag = ber_scanf( ber, "{e" /* } */, &behavior ); /* FIXME: since the whole SEQUENCE is optional, * should we accept no enumerations at all? */ if ( tag != LBER_ENUMERATED ) { rs->sr_text = "Chaining behavior control: resolveBehavior decoding error"; return LDAP_PROTOCOL_ERROR; } switch ( behavior ) { case LDAP_CHAINING_PREFERRED: mode = SLAP_CH_RESOLVE_CHAINING_PREFERRED; break; case LDAP_CHAINING_REQUIRED: mode = SLAP_CH_RESOLVE_CHAINING_REQUIRED; break; case LDAP_REFERRALS_PREFERRED: mode = SLAP_CH_RESOLVE_REFERRALS_PREFERRED; break; case LDAP_REFERRALS_REQUIRED: mode = SLAP_CH_RESOLVE_REFERRALS_REQUIRED; break; default: rs->sr_text = "Chaining behavior control: unknown resolveBehavior"; return LDAP_PROTOCOL_ERROR; } tag = ber_peek_tag( ber, &len ); if ( tag == LBER_ENUMERATED ) { tag = ber_scanf( ber, "e", &behavior ); if ( tag == LBER_ERROR ) { rs->sr_text = "Chaining behavior control: continuationBehavior decoding error"; return LDAP_PROTOCOL_ERROR; } } if ( tag == LBER_DEFAULT ) { mode |= SLAP_CH_CONTINUATION_DEFAULT; } else { switch ( behavior ) { case LDAP_CHAINING_PREFERRED: mode |= SLAP_CH_CONTINUATION_CHAINING_PREFERRED; break; case LDAP_CHAINING_REQUIRED: mode |= SLAP_CH_CONTINUATION_CHAINING_REQUIRED; break; case LDAP_REFERRALS_PREFERRED: mode |= SLAP_CH_CONTINUATION_REFERRALS_PREFERRED; break; case LDAP_REFERRALS_REQUIRED: mode |= SLAP_CH_CONTINUATION_REFERRALS_REQUIRED; break; default: rs->sr_text = "Chaining behavior control: unknown continuationBehavior"; return LDAP_PROTOCOL_ERROR; } } if ( ( ber_scanf( ber, /* { */ "}") ) == LBER_ERROR ) { rs->sr_text = "Chaining behavior control: decoding error"; return LDAP_PROTOCOL_ERROR; } (void) ber_free( ber, 1 ); } op->o_chaining = mode | ( ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL ); return LDAP_SUCCESS;}#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */static slap_overinst ldapchain;intchain_init( void ){ int rc; /* Make sure we don't exceed the bits reserved for userland */ config_check_userland( CH_LAST );#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR rc = register_supported_control( LDAP_CONTROL_X_CHAINING_BEHAVIOR, /* SLAP_CTRL_GLOBAL| */ SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE, NULL, ldap_chain_parse_ctrl, &sc_chainingBehavior ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "slapd-chain: " "unable to register chaining behavior control: %d.\n", rc, 0, 0 ); return rc; }#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ ldapchain.on_bi.bi_type = "chain"; ldapchain.on_bi.bi_db_init = ldap_chain_db_init; ldapchain.on_bi.bi_db_config = ldap_chain_db_config; ldapchain.on_bi.bi_db_open = ldap_chain_db_open; ldapchain.on_bi.bi_db_close = ldap_chain_db_close; ldapchain.on_bi.bi_db_destroy = ldap_chain_db_destroy; ldapchain.on_bi.bi_connection_destroy = ldap_chain_connection_destroy; ldapchain.on_response = ldap_chain_response; ldapchain.on_bi.bi_cf_ocs = chainocs; rc = config_register_schema( chaincfg, chainocs ); if ( rc ) { return rc; } return overlay_register( &ldapchain );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -