| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /** BEGIN COPYRIGHT BLOCK
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- *
- * License: GPL (version 3 or any later version).
- * See LICENSE for details.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #include "cb.h"
- /*
- ** Controls that can't be forwarded due to the current implementation
- */
- static char * unsupported_ctrls[] = {LDAP_CONTROL_PERSISTENTSEARCH,NULL};
- int cb_is_control_forwardable(cb_backend * cb, char *controloid) {
- return (!(charray_inlist(unsupported_ctrls,controloid)));
- }
- void
- cb_register_supported_control( cb_backend * cb, char *controloid, unsigned long controlops )
- {
- /* For now, ignore controlops */
- if ( controloid != NULL ) {
- slapi_rwlock_wrlock(cb->config.rwl_config_lock);
- charray_add( &cb->config.forward_ctrls,slapi_ch_strdup( controloid ));
- slapi_rwlock_unlock(cb->config.rwl_config_lock);
- }
- }
- void
- cb_unregister_all_supported_control( cb_backend * cb ) {
- slapi_rwlock_wrlock(cb->config.rwl_config_lock);
- charray_free(cb->config.forward_ctrls);
- cb->config.forward_ctrls=NULL;
- slapi_rwlock_unlock(cb->config.rwl_config_lock);
- }
- void
- cb_unregister_supported_control( cb_backend * cb, char *controloid, unsigned long controlops )
- {
- /* For now, ignore controlops */
- if ( controloid != NULL ) {
- int i;
- slapi_rwlock_wrlock(cb->config.rwl_config_lock);
- for ( i = 0; cb->config.forward_ctrls != NULL && cb->config.forward_ctrls[i] != NULL; ++i ) {
- if ( strcmp( cb->config.forward_ctrls[i], controloid ) == 0 ) {
- break;
- }
- }
- if ( cb->config.forward_ctrls == NULL || cb->config.forward_ctrls[i] == NULL) {
- slapi_rwlock_unlock(cb->config.rwl_config_lock);
- return;
- }
- if ( controlops == 0 ) {
- charray_remove(cb->config.forward_ctrls,controloid,0/* free it */);
- }
- slapi_rwlock_unlock(cb->config.rwl_config_lock);
- }
- }
- int cb_create_loop_control (
- const ber_int_t hops,
- LDAPControl **ctrlp)
- {
- BerElement *ber;
- int rc;
- if ((ber = ber_alloc()) == NULL)
- return -1;
- if ( ber_printf( ber, "i", hops ) < 0) {
- ber_free(ber,1);
- return -1;
- }
- rc = slapi_build_control( CB_LDAP_CONTROL_CHAIN_SERVER, ber, 0, ctrlp);
- ber_free(ber,1);
- return rc;
- }
- /*
- ** Return the controls to be passed to the remote
- ** farm server and the LDAP error to return.
- **
- ** Add the Proxied Authorization control when impersonation
- ** is enabled. Other controls present in the request are added
- ** to the control list
- **
- ** #622885 .abandon should not inherit the to-be-abandoned-operation's controls
- ** .controls attached to abandon should not be critical
- */
- int cb_update_controls( Slapi_PBlock * pb,
- LDAP * ld,
- LDAPControl *** controls,
- int ctrl_flags
- )
- {
- int cCount=0;
- int dCount=0;
- int i;
- char * proxyDN=NULL;
- LDAPControl ** reqControls = NULL;
- LDAPControl ** ctrls = NULL;
- cb_backend_instance * cb;
- cb_backend * cbb;
- Slapi_Backend * be;
- int rc=LDAP_SUCCESS;
- ber_int_t hops=0;
- int useloop=0;
- int addauth = (ctrl_flags & CB_UPDATE_CONTROLS_ADDAUTH);
- int isabandon = (ctrl_flags & CB_UPDATE_CONTROLS_ISABANDON);
- int op_type = 0;
- *controls = NULL;
- slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &op_type);
- if (!isabandon || op_type == SLAPI_OPERATION_ABANDON) {
- /* if not abandon or abandon sent by client */
- slapi_pblock_get( pb, SLAPI_REQCONTROLS, &reqControls );
- }
- slapi_pblock_get( pb, SLAPI_BACKEND, &be );
- slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &cbb );
- cb = cb_get_instance(be);
- /*****************************************/
- /* First, check for unsupported controls */
- /* Return an error if critical control */
- /* else remove it from the control list */
- /*****************************************/
- for ( cCount=0; reqControls && reqControls[cCount]; cCount++ );
- ctrls = (LDAPControl **)slapi_ch_calloc(1,sizeof(LDAPControl *) * (cCount +3));
- slapi_rwlock_rdlock(cbb->config.rwl_config_lock);
- for ( cCount=0; reqControls && reqControls[cCount]; cCount++ ) {
- /* XXXSD CASCADING */
- /* For now, allow PROXY_AUTH control forwarding only when */
- /* local acl evaluation to prevent unauthorized access */
- if (!strcmp(reqControls[cCount]->ldctl_oid,LDAP_CONTROL_PROXYAUTH)) {
- /* we have to force remote acl checking if the associated backend to this
- chaining backend is disabled - disabled == no acl check possible */
- if (!cb->local_acl && !cb->associated_be_is_disabled) {
- slapi_log_error( SLAPI_LOG_PLUGIN,CB_PLUGIN_SUBSYSTEM,
- "local aci check required to handle proxied auth control. Deny access.\n");
- rc= LDAP_INSUFFICIENT_ACCESS;
- break;
- }
- /* XXXSD Not safe to use proxied authorization with Directory Manager */
- /* checked earlier when impersonation is on */
- if (!cb->impersonate) {
- char * requestor,*rootdn;
- char * requestorCopy=NULL;
- rootdn = cb_get_rootdn();
- slapi_pblock_get( pb, SLAPI_REQUESTOR_NDN, &requestor );
- requestorCopy = slapi_ch_strdup(requestor);
- slapi_dn_ignore_case(requestorCopy);
- if (!strcmp( requestorCopy, rootdn )) { /* UTF8- aware */
- slapi_log_error( SLAPI_LOG_PLUGIN,CB_PLUGIN_SUBSYSTEM,
- "Use of user <%s> incompatible with proxied auth. control\n",
- rootdn);
- rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
- slapi_ch_free_string(&rootdn);
- slapi_ch_free_string(&requestorCopy);
- break;
- }
- slapi_ch_free_string(&rootdn);
- slapi_ch_free_string(&requestorCopy);
- }
- addauth=0;
- ctrls[dCount]=slapi_dup_control(reqControls[cCount]);
- dCount++;
- } else if (!strcmp(reqControls[cCount]->ldctl_oid,CB_LDAP_CONTROL_CHAIN_SERVER) &&
- BV_HAS_DATA((&(reqControls[cCount]->ldctl_value)))) {
- /* Max hop count reached ? */
- /* Checked earlier by a call to cb_forward_operation() */
- BerElement *ber = NULL;
- ber = ber_init(&(reqControls[cCount]->ldctl_value));
- if (LBER_ERROR == ber_scanf(ber,"i",&hops)) {
- slapi_log_error( SLAPI_LOG_PLUGIN,CB_PLUGIN_SUBSYSTEM,
- "Unable to get number of hops from the chaining control\n");
- }
- ber_free(ber,1);
- useloop=1;
- /* Add to the control list later */
- } else {
- int i;
- for ( i = 0; cbb->config.forward_ctrls != NULL
- && cbb->config.forward_ctrls[i] != NULL; ++i ) {
- if ( strcmp( cbb->config.forward_ctrls[i], reqControls[cCount]->ldctl_oid ) == 0 ) {
- break;
- }
- }
- /* For now, ignore optype */
- if ( cbb->config.forward_ctrls == NULL || cbb->config.forward_ctrls[i] == NULL) {
- if (reqControls[cCount]->ldctl_iscritical) {
- rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
- break;
- }
- /* Skip it */
- } else {
- ctrls[dCount]=slapi_dup_control(reqControls[cCount]);
- dCount++;
- }
- }
- }
- slapi_rwlock_unlock(cbb->config.rwl_config_lock);
- if (LDAP_SUCCESS != rc) {
- ldap_controls_free(ctrls);
- return rc;
- }
- /***************************************/
- /* add impersonation control if needed */
- /***************************************/
- if ( !(cb->impersonate) ) {
- /* don't add proxy control */
- addauth=0;
- }
-
- if (addauth) {
- slapi_pblock_get( pb, SLAPI_REQUESTOR_DN, &proxyDN );
- if ( slapi_ldap_create_proxyauth_control(ld, proxyDN, isabandon?0:1, 0, &ctrls[dCount] )) {
- ldap_controls_free(ctrls);
- slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
- "LDAP_CONTROL_PROXYAUTH control encoding failed.\n");
- return LDAP_OPERATIONS_ERROR;
- }
- dCount++;
- }
- /***********************************************************/
- /* add loop control if needed */
- /* Don't add it if not in the list of forwardable controls */
- /***********************************************************/
- if (!useloop) {
- for ( i = 0; cbb->config.forward_ctrls != NULL
- && cbb->config.forward_ctrls[i] != NULL; ++i ) {
- if ( strcmp( cbb->config.forward_ctrls[i],
- CB_LDAP_CONTROL_CHAIN_SERVER) == 0 ) {
- break;
- }
- }
- }
- if ( useloop || (cbb->config.forward_ctrls !=NULL && cbb->config.forward_ctrls[i] !=NULL)){
-
- if (hops > 0) {
- hops--;
- } else {
- hops = cb->hoplimit;
- }
- /* loop control's critical flag is 0;
- * no special treatment is needed for abandon */
- cb_create_loop_control(hops,&ctrls[dCount]);
- dCount++;
- }
- if (dCount==0) {
- ldap_controls_free(ctrls);
- } else {
- *controls = ctrls;
- }
- return LDAP_SUCCESS;
- }
|