| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- /** 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 __attribute__((unused)), char *controloid)
- {
- return (!(charray_inlist(unsupported_ctrls, controloid)));
- }
- void
- cb_register_supported_control(cb_backend *cb, char *controloid, unsigned long controlops __attribute__((unused)))
- {
- /* 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_err(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_err(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_err(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_err(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;
- }
|