diff options
author | cvsadm <cvsadm> | 2005-01-21 00:44:34 +0000 |
---|---|---|
committer | cvsadm <cvsadm> | 2005-01-21 00:44:34 +0000 |
commit | b2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch) | |
tree | cf58939393a9032182c4fbc4441164a9456e82f8 /ldap/servers/plugins/chainingdb/cb_controls.c | |
download | ds-ldapserver7x.tar.gz ds-ldapserver7x.tar.xz ds-ldapserver7x.zip |
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'ldap/servers/plugins/chainingdb/cb_controls.c')
-rw-r--r-- | ldap/servers/plugins/chainingdb/cb_controls.c | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/ldap/servers/plugins/chainingdb/cb_controls.c b/ldap/servers/plugins/chainingdb/cb_controls.c new file mode 100644 index 00000000..ab612099 --- /dev/null +++ b/ldap/servers/plugins/chainingdb/cb_controls.c @@ -0,0 +1,289 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ +#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 ) { + PR_RWLock_Wlock(cb->config.rwl_config_lock); + charray_add( &cb->config.forward_ctrls,slapi_ch_strdup( controloid )); + PR_RWLock_Unlock(cb->config.rwl_config_lock); + } +} + + +void +cb_unregister_all_supported_control( cb_backend * cb ) { + + PR_RWLock_Wlock(cb->config.rwl_config_lock); + charray_free(cb->config.forward_ctrls); + cb->config.forward_ctrls=NULL; + PR_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; + PR_RWLock_Wlock(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) { + PR_RWLock_Unlock(cb->config.rwl_config_lock); + return; + } + if ( controlops == 0 ) { + charray_remove(cb->config.forward_ctrls,controloid); + } + PR_RWLock_Unlock(cb->config.rwl_config_lock); + } +} + +int cb_create_loop_control ( + const int 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; + int 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)); + + PR_RWLock_Rlock(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_DN, &requestor ); + requestorCopy=slapi_ch_strdup(requestor); + slapi_dn_normalize_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((void **)&requestorCopy); + break; + } + slapi_ch_free((void **)&rootdn); + slapi_ch_free((void **)&requestorCopy); + } + + addauth=0; + ctrls[dCount]=slapi_dup_control(reqControls[cCount]); + dCount++; + + } else + if (!strcmp(reqControls[cCount]->ldctl_oid,CB_LDAP_CONTROL_CHAIN_SERVER)) { + + /* Max hop count reached ? */ + /* Checked realier by a call to cb_forward_operation() */ + + BerElement *ber = NULL; + + ber = ber_init(&(reqControls[cCount]->ldctl_value)); + ber_scanf(ber,"i",&hops); + 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++; + } + } + } + + PR_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 ( ldap_create_proxyauth_control(ld, proxyDN, isabandon?0:1, &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; + +} |