summaryrefslogtreecommitdiffstats
path: root/ldap/servers/plugins/chainingdb/cb_controls.c
diff options
context:
space:
mode:
authorcvsadm <cvsadm>2005-01-21 00:44:34 +0000
committercvsadm <cvsadm>2005-01-21 00:44:34 +0000
commitb2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch)
treecf58939393a9032182c4fbc4441164a9456e82f8 /ldap/servers/plugins/chainingdb/cb_controls.c
downloadds-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.c289
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;
+
+}