📄 chain.c
字号:
*/enum { CH_CHAINING = 1, CH_CACHE_URI, CH_MAX_DEPTH, CH_RETURN_ERR, CH_LAST};static ConfigDriver chain_cf_gen;static ConfigCfAdd chain_cfadd;static ConfigLDAPadd chain_ldadd;static ConfigTable chaincfg[] = {#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR { "chain-chaining", "args", 2, 4, 0, ARG_MAGIC|ARG_BERVAL|CH_CHAINING, chain_cf_gen, "( OLcfgOvAt:3.1 NAME 'olcChainingBehavior' " "DESC 'Chaining behavior control parameters (draft-sermersheim-ldap-chaining)' " "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ { "chain-cache-uri", "TRUE/FALSE", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|CH_CACHE_URI, chain_cf_gen, "( OLcfgOvAt:3.2 NAME 'olcChainCacheURI' " "DESC 'Enables caching of URIs not present in configuration' " "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, { "chain-max-depth", "args", 2, 2, 0, ARG_MAGIC|ARG_INT|CH_MAX_DEPTH, chain_cf_gen, "( OLcfgOvAt:3.3 NAME 'olcChainMaxReferralDepth' " "DESC 'max referral depth' " "SYNTAX OMsInteger " "EQUALITY integerMatch " "SINGLE-VALUE )", NULL, NULL }, { "chain-return-error", "TRUE/FALSE", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|CH_RETURN_ERR, chain_cf_gen, "( OLcfgOvAt:3.4 NAME 'olcChainReturnError' " "DESC 'Errors are returned instead of the original referral' " "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, { NULL, NULL, 0, 0, 0, ARG_IGNORED }};static ConfigOCs chainocs[] = { { "( OLcfgOvOc:3.1 " "NAME 'olcChainConfig' " "DESC 'Chain configuration' " "SUP olcOverlayConfig " "MAY ( "#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR "olcChainingBehavior $ "#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ "olcChainCacheURI $ " "olcChainMaxReferralDepth $ " "olcChainReturnError " ") )", Cft_Overlay, chaincfg, NULL, chain_cfadd }, { "( OLcfgOvOc:3.2 " "NAME 'olcChainDatabase' " "DESC 'Chain remote server configuration' " "AUXILIARY )", Cft_Misc, chaincfg, chain_ldadd }, { NULL, 0, NULL }};static intchain_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca ){ slap_overinst *on; ldap_chain_t *lc; ldapinfo_t *li; AttributeDescription *ad = NULL; Attribute *at; const char *text; int rc; if ( p->ce_type != Cft_Overlay || !p->ce_bi || p->ce_bi->bi_cf_ocs != chainocs ) { return LDAP_CONSTRAINT_VIOLATION; } on = (slap_overinst *)p->ce_bi; lc = (ldap_chain_t *)on->on_bi.bi_private; assert( ca->be == NULL ); ca->be = (BackendDB *)ch_calloc( 1, sizeof( BackendDB ) ); ca->be->bd_info = (BackendInfo *)on; rc = slap_str2ad( "olcDbURI", &ad, &text ); assert( rc == LDAP_SUCCESS ); at = attr_find( e->e_attrs, ad ); if ( lc->lc_common_li == NULL && at != NULL ) { /* FIXME: we should generate an empty default entry * if none is supplied */ Debug( LDAP_DEBUG_ANY, "slapd-chain: " "first underlying database \"%s\" " "cannot contain attribute \"%s\".\n", e->e_name.bv_val, ad->ad_cname.bv_val, 0 ); rc = LDAP_CONSTRAINT_VIOLATION; goto done; } else if ( lc->lc_common_li != NULL && at == NULL ) { /* FIXME: we should generate an empty default entry * if none is supplied */ Debug( LDAP_DEBUG_ANY, "slapd-chain: " "subsequent underlying database \"%s\" " "must contain attribute \"%s\".\n", e->e_name.bv_val, ad->ad_cname.bv_val, 0 ); rc = LDAP_CONSTRAINT_VIOLATION; goto done; } if ( lc->lc_common_li == NULL ) { rc = ldap_chain_db_init_common( ca->be ); } else { rc = ldap_chain_db_init_one( ca->be ); } if ( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "slapd-chain: " "unable to init %sunderlying database \"%s\".\n", lc->lc_common_li == NULL ? "common " : "", e->e_name.bv_val, 0 ); return LDAP_CONSTRAINT_VIOLATION; } li = ca->be->be_private; if ( lc->lc_common_li == NULL ) { lc->lc_common_li = li; } else { li->li_uri = ch_strdup( at->a_vals[ 0 ].bv_val ); value_add_one( &li->li_bvuri, &at->a_vals[ 0 ] ); if ( avl_insert( &lc->lc_lai.lai_tree, (caddr_t)li, ldap_chain_uri_cmp, ldap_chain_uri_dup ) ) { Debug( LDAP_DEBUG_ANY, "slapd-chain: " "database \"%s\" insert failed.\n", e->e_name.bv_val, 0, 0 ); rc = LDAP_CONSTRAINT_VIOLATION; goto done; } }done:; if ( rc != LDAP_SUCCESS ) { (void)ldap_chain_db_destroy_one( ca->be ); ch_free( ca->be ); ca->be = NULL; } return rc;}typedef struct ldap_chain_cfadd_apply_t { Operation *op; SlapReply *rs; Entry *p; ConfigArgs *ca; int count;} ldap_chain_cfadd_apply_t;static intldap_chain_cfadd_apply( void *datum, void *arg ){ ldapinfo_t *li = (ldapinfo_t *)datum; ldap_chain_cfadd_apply_t *lca = (ldap_chain_cfadd_apply_t *)arg; struct berval bv; /* FIXME: should not hardcode "olcDatabase" here */ bv.bv_len = snprintf( lca->ca->msg, sizeof( lca->ca->msg ), "olcDatabase={%d}%s", lca->count, lback->bi_type ); bv.bv_val = lca->ca->msg; lca->ca->be->be_private = (void *)li; config_build_entry( lca->op, lca->rs, lca->p->e_private, lca->ca, &bv, lback->bi_cf_ocs, &chainocs[1] ); lca->count++; return 0;}static intchain_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca ){ CfEntryInfo *pe = p->e_private; slap_overinst *on = (slap_overinst *)pe->ce_bi; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; void *priv = (void *)ca->be->be_private; if ( lback->bi_cf_ocs ) { ldap_chain_cfadd_apply_t lca = { 0 }; lca.op = op; lca.rs = rs; lca.p = p; lca.ca = ca; lca.count = 0; (void)ldap_chain_cfadd_apply( (void *)lc->lc_common_li, (void *)&lca ); (void)avl_apply( lc->lc_lai.lai_tree, ldap_chain_cfadd_apply, &lca, 1, AVL_INORDER ); ca->be->be_private = priv; } return 0;}#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIORstatic slap_verbmasks chaining_mode[] = { { BER_BVC("referralsRequired"), LDAP_REFERRALS_REQUIRED }, { BER_BVC("referralsPreferred"), LDAP_REFERRALS_PREFERRED }, { BER_BVC("chainingRequired"), LDAP_CHAINING_REQUIRED }, { BER_BVC("chainingPreferred"), LDAP_CHAINING_PREFERRED }, { BER_BVNULL, 0 }};#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */static intchain_cf_gen( ConfigArgs *c ){ slap_overinst *on = (slap_overinst *)c->bi; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; int rc = 0; if ( c->op == SLAP_CONFIG_EMIT ) { switch( c->type ) {#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR case CH_CHAINING: { struct berval resolve = BER_BVNULL, continuation = BER_BVNULL; if ( !LDAP_CHAIN_CHAINING( lc ) ) { return 1; } enum_to_verb( chaining_mode, ( ( lc->lc_chaining_ctrlflag & SLAP_CH_RESOLVE_MASK ) >> SLAP_CH_RESOLVE_SHIFT ), &resolve ); enum_to_verb( chaining_mode, ( ( lc->lc_chaining_ctrlflag & SLAP_CH_CONTINUATION_MASK ) >> SLAP_CH_CONTINUATION_SHIFT ), &continuation ); c->value_bv.bv_len = STRLENOF( "resolve=" ) + resolve.bv_len + STRLENOF( " " ) + STRLENOF( "continuation=" ) + continuation.bv_len; c->value_bv.bv_val = ch_malloc( c->value_bv.bv_len + 1 ); snprintf( c->value_bv.bv_val, c->value_bv.bv_len + 1, "resolve=%s continuation=%s", resolve.bv_val, continuation.bv_val ); if ( lc->lc_chaining_ctrl.ldctl_iscritical ) { c->value_bv.bv_val = ch_realloc( c->value_bv.bv_val, c->value_bv.bv_len + STRLENOF( " critical" ) + 1 ); AC_MEMCPY( &c->value_bv.bv_val[ c->value_bv.bv_len ], " critical", STRLENOF( " critical" ) + 1 ); c->value_bv.bv_len += STRLENOF( " critical" ); } break; }#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ case CH_CACHE_URI: c->value_int = LDAP_CHAIN_CACHE_URI( lc ); break; case CH_MAX_DEPTH: c->value_int = lc->lc_max_depth; break; case CH_RETURN_ERR: c->value_int = LDAP_CHAIN_RETURN_ERR( lc ); break; default: assert( 0 ); rc = 1; } return rc; } else if ( c->op == LDAP_MOD_DELETE ) { switch( c->type ) { case CH_CHAINING: return 1; case CH_CACHE_URI: lc->lc_flags &= ~LDAP_CHAIN_F_CACHE_URI; break; case CH_MAX_DEPTH: c->value_int = 0; break; case CH_RETURN_ERR: lc->lc_flags &= ~LDAP_CHAIN_F_RETURN_ERR; break; default: return 1; } return rc; } switch( c->type ) { case CH_CHAINING: {#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR char **argv = c->argv; int argc = c->argc; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; int resolve = -1, continuation = -1, iscritical = 0; Operation op = { 0 }; SlapReply rs = { 0 }; lc->lc_chaining_ctrlflag = 0; for ( argc--, argv++; argc > 0; argc--, argv++ ) { if ( strncasecmp( argv[ 0 ], "resolve=", STRLENOF( "resolve=" ) ) == 0 ) { resolve = str2chain( argv[ 0 ] + STRLENOF( "resolve=" ) ); if ( resolve == -1 ) { Debug( LDAP_DEBUG_ANY, "%s: " "illegal <resolve> value %s " "in \"chain-chaining>\".\n", c->log, argv[ 0 ], 0 ); return 1; } } else if ( strncasecmp( argv[ 0 ], "continuation=", STRLENOF( "continuation=" ) ) == 0 ) { continuation = str2chain( argv[ 0 ] + STRLENOF( "continuation=" ) ); if ( continuation == -1 ) { Debug( LDAP_DEBUG_ANY, "%s: " "illegal <continuation> value %s " "in \"chain-chaining\".\n", c->log, argv[ 0 ], 0 ); return 1; } } else if ( strcasecmp( argv[ 0 ], "critical" ) == 0 ) { iscritical = 1; } else { Debug( LDAP_DEBUG_ANY, "%s: " "unknown option in \"chain-chaining\".\n", c->log, 0, 0 ); return 1; } } if ( resolve != -1 || continuation != -1 ) { int err; if ( resolve == -1 ) { /* default */ resolve = SLAP_CHAINING_DEFAULT; } ber_init2( ber, NULL, LBER_USE_DER ); err = ber_printf( ber, "{e" /* } */, resolve ); if ( err == -1 ) { ber_free( ber, 1 ); Debug( LDAP_DEBUG_ANY, "%s: " "chaining behavior control encoding error!\n", c->log, 0, 0 ); return 1; } if ( continuation > -1 ) { err = ber_printf( ber, "e", continuation ); if ( err == -1 ) { ber_free( ber, 1 ); Debug( LDAP_DEBUG_ANY, "%s: " "chaining behavior control encoding error!\n", c->log, 0, 0 ); return 1; } } err = ber_printf( ber, /* { */ "N}" ); if ( err == -1 ) { ber_free( ber, 1 ); Debug( LDAP_DEBUG_ANY, "%s: " "chaining behavior control encoding error!\n", c->log, 0, 0 ); return 1; } if ( ber_flatten2( ber, &lc->lc_chaining_ctrl.ldctl_value, 0 ) == -1 ) { exit( EXIT_FAILURE ); } } else { BER_BVZERO( &lc->lc_chaining_ctrl.ldctl_value ); } lc->lc_chaining_ctrl.ldctl_oid = LDAP_CONTROL_X_CHAINING_BEHAVIOR; lc->lc_chaining_ctrl.ldctl_iscritical = iscritical; if ( ldap_chain_parse_ctrl( &op, &rs, &lc->lc_chaining_ctrl ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s: " "unable to parse chaining control%s%s.\n", c->log, rs.sr_text ? ": " : "", rs.sr_text ? rs.sr_text : "" ); return 1; } lc->lc_chaining_ctrlflag = op.o_chaining; lc->lc_flags |= LDAP_CHAIN_F_CHAINING; rc = 0;#else /* ! LDAP_CONTROL_X_CHAINING_BEHAVIOR */ Debug( LDAP_DEBUG_ANY, "%s: " "\"chaining\" control unsupported (ignored).\n", c->log, 0, 0 );#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ } break; case CH_CACHE_URI: if ( c->value_int ) { lc->lc_flags |= LDAP_CHAIN_F_CACHE_URI; } else { lc->lc_flags &= ~LDAP_CHAIN_F_CACHE_URI; } break; case CH_MAX_DEPTH: if ( c->value_int < 0 ) { snprintf( c->msg, sizeof( c->msg ), "<%s> invalid max referral depth %d", c->argv[0], c->value_int ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); rc = 1; break; } lc->lc_max_depth = c->value_int; case CH_RETURN_ERR: if ( c->value_int ) { lc->lc_flags |= LDAP_CHAIN_F_RETURN_ERR; } else { lc->lc_flags &= ~LDAP_CHAIN_F_RETURN_ERR; } break; default: assert( 0 ); return 1; } return rc;}static intldap_chain_db_init( BackendDB *be ){ slap_overinst *on = (slap_overinst *)be->bd_info; ldap_chain_t *lc = NULL; if ( lback == NULL ) { static BackendInfo lback2; lback = backend_info( "ldap" ); if ( lback == NULL ) { return 1; } lback2 = *lback; lback2.bi_type = ldapchain.on_bi.bi_type; lback = &lback2; } lc = ch_malloc( sizeof( ldap_chain_t ) ); if ( lc == NULL ) { return 1; } memset( lc, 0, sizeof( ldap_chain_t ) ); lc->lc_max_depth = 1; ldap_pvt_thread_mutex_init( &lc->lc_lai.lai_mutex ); on->on_bi.bi_private = (void *)lc; return 0;}static intldap_chain_db_config( BackendDB *be, const char *fname, int lineno, int argc, char **argv ){ slap_overinst *on = (slap_overinst *)be->bd_info; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; int rc = SLAP_CONF_UNKNOWN; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -