cb_controls.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. #include "cb.h"
  13. /*
  14. ** Controls that can't be forwarded due to the current implementation
  15. */
  16. static char * unsupported_ctrls[] = {LDAP_CONTROL_PERSISTENTSEARCH,NULL};
  17. int cb_is_control_forwardable(cb_backend * cb, char *controloid) {
  18. return (!(charray_inlist(unsupported_ctrls,controloid)));
  19. }
  20. void
  21. cb_register_supported_control( cb_backend * cb, char *controloid, unsigned long controlops )
  22. {
  23. /* For now, ignore controlops */
  24. if ( controloid != NULL ) {
  25. slapi_rwlock_wrlock(cb->config.rwl_config_lock);
  26. charray_add( &cb->config.forward_ctrls,slapi_ch_strdup( controloid ));
  27. slapi_rwlock_unlock(cb->config.rwl_config_lock);
  28. }
  29. }
  30. void
  31. cb_unregister_all_supported_control( cb_backend * cb ) {
  32. slapi_rwlock_wrlock(cb->config.rwl_config_lock);
  33. charray_free(cb->config.forward_ctrls);
  34. cb->config.forward_ctrls=NULL;
  35. slapi_rwlock_unlock(cb->config.rwl_config_lock);
  36. }
  37. void
  38. cb_unregister_supported_control( cb_backend * cb, char *controloid, unsigned long controlops )
  39. {
  40. /* For now, ignore controlops */
  41. if ( controloid != NULL ) {
  42. int i;
  43. slapi_rwlock_wrlock(cb->config.rwl_config_lock);
  44. for ( i = 0; cb->config.forward_ctrls != NULL && cb->config.forward_ctrls[i] != NULL; ++i ) {
  45. if ( strcmp( cb->config.forward_ctrls[i], controloid ) == 0 ) {
  46. break;
  47. }
  48. }
  49. if ( cb->config.forward_ctrls == NULL || cb->config.forward_ctrls[i] == NULL) {
  50. slapi_rwlock_unlock(cb->config.rwl_config_lock);
  51. return;
  52. }
  53. if ( controlops == 0 ) {
  54. charray_remove(cb->config.forward_ctrls,controloid,0/* free it */);
  55. }
  56. slapi_rwlock_unlock(cb->config.rwl_config_lock);
  57. }
  58. }
  59. int cb_create_loop_control (
  60. const ber_int_t hops,
  61. LDAPControl **ctrlp)
  62. {
  63. BerElement *ber;
  64. int rc;
  65. if ((ber = ber_alloc()) == NULL)
  66. return -1;
  67. if ( ber_printf( ber, "i", hops ) < 0) {
  68. ber_free(ber,1);
  69. return -1;
  70. }
  71. rc = slapi_build_control( CB_LDAP_CONTROL_CHAIN_SERVER, ber, 0, ctrlp);
  72. ber_free(ber,1);
  73. return rc;
  74. }
  75. /*
  76. ** Return the controls to be passed to the remote
  77. ** farm server and the LDAP error to return.
  78. **
  79. ** Add the Proxied Authorization control when impersonation
  80. ** is enabled. Other controls present in the request are added
  81. ** to the control list
  82. **
  83. ** #622885 .abandon should not inherit the to-be-abandoned-operation's controls
  84. ** .controls attached to abandon should not be critical
  85. */
  86. int cb_update_controls( Slapi_PBlock * pb,
  87. LDAP * ld,
  88. LDAPControl *** controls,
  89. int ctrl_flags
  90. )
  91. {
  92. int cCount=0;
  93. int dCount=0;
  94. int i;
  95. char * proxyDN=NULL;
  96. LDAPControl ** reqControls = NULL;
  97. LDAPControl ** ctrls = NULL;
  98. cb_backend_instance * cb;
  99. cb_backend * cbb;
  100. Slapi_Backend * be;
  101. int rc=LDAP_SUCCESS;
  102. ber_int_t hops=0;
  103. int useloop=0;
  104. int addauth = (ctrl_flags & CB_UPDATE_CONTROLS_ADDAUTH);
  105. int isabandon = (ctrl_flags & CB_UPDATE_CONTROLS_ISABANDON);
  106. int op_type = 0;
  107. *controls = NULL;
  108. slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &op_type);
  109. if (!isabandon || op_type == SLAPI_OPERATION_ABANDON) {
  110. /* if not abandon or abandon sent by client */
  111. slapi_pblock_get( pb, SLAPI_REQCONTROLS, &reqControls );
  112. }
  113. slapi_pblock_get( pb, SLAPI_BACKEND, &be );
  114. slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &cbb );
  115. cb = cb_get_instance(be);
  116. /*****************************************/
  117. /* First, check for unsupported controls */
  118. /* Return an error if critical control */
  119. /* else remove it from the control list */
  120. /*****************************************/
  121. for ( cCount=0; reqControls && reqControls[cCount]; cCount++ );
  122. ctrls = (LDAPControl **)slapi_ch_calloc(1,sizeof(LDAPControl *) * (cCount +3));
  123. slapi_rwlock_rdlock(cbb->config.rwl_config_lock);
  124. for ( cCount=0; reqControls && reqControls[cCount]; cCount++ ) {
  125. /* XXXSD CASCADING */
  126. /* For now, allow PROXY_AUTH control forwarding only when */
  127. /* local acl evaluation to prevent unauthorized access */
  128. if (!strcmp(reqControls[cCount]->ldctl_oid,LDAP_CONTROL_PROXYAUTH)) {
  129. /* we have to force remote acl checking if the associated backend to this
  130. chaining backend is disabled - disabled == no acl check possible */
  131. if (!cb->local_acl && !cb->associated_be_is_disabled) {
  132. slapi_log_error( SLAPI_LOG_PLUGIN,CB_PLUGIN_SUBSYSTEM,
  133. "local aci check required to handle proxied auth control. Deny access.\n");
  134. rc= LDAP_INSUFFICIENT_ACCESS;
  135. break;
  136. }
  137. /* XXXSD Not safe to use proxied authorization with Directory Manager */
  138. /* checked earlier when impersonation is on */
  139. if (!cb->impersonate) {
  140. char * requestor,*rootdn;
  141. char * requestorCopy=NULL;
  142. rootdn = cb_get_rootdn();
  143. slapi_pblock_get( pb, SLAPI_REQUESTOR_NDN, &requestor );
  144. requestorCopy = slapi_ch_strdup(requestor);
  145. slapi_dn_ignore_case(requestorCopy);
  146. if (!strcmp( requestorCopy, rootdn )) { /* UTF8- aware */
  147. slapi_log_error( SLAPI_LOG_PLUGIN,CB_PLUGIN_SUBSYSTEM,
  148. "Use of user <%s> incompatible with proxied auth. control\n",
  149. rootdn);
  150. rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  151. slapi_ch_free_string(&rootdn);
  152. slapi_ch_free_string(&requestorCopy);
  153. break;
  154. }
  155. slapi_ch_free_string(&rootdn);
  156. slapi_ch_free_string(&requestorCopy);
  157. }
  158. addauth=0;
  159. ctrls[dCount]=slapi_dup_control(reqControls[cCount]);
  160. dCount++;
  161. } else if (!strcmp(reqControls[cCount]->ldctl_oid,CB_LDAP_CONTROL_CHAIN_SERVER) &&
  162. BV_HAS_DATA((&(reqControls[cCount]->ldctl_value)))) {
  163. /* Max hop count reached ? */
  164. /* Checked earlier by a call to cb_forward_operation() */
  165. BerElement *ber = NULL;
  166. ber = ber_init(&(reqControls[cCount]->ldctl_value));
  167. if (LBER_ERROR == ber_scanf(ber,"i",&hops)) {
  168. slapi_log_error( SLAPI_LOG_PLUGIN,CB_PLUGIN_SUBSYSTEM,
  169. "Unable to get number of hops from the chaining control\n");
  170. }
  171. ber_free(ber,1);
  172. useloop=1;
  173. /* Add to the control list later */
  174. } else {
  175. int i;
  176. for ( i = 0; cbb->config.forward_ctrls != NULL
  177. && cbb->config.forward_ctrls[i] != NULL; ++i ) {
  178. if ( strcmp( cbb->config.forward_ctrls[i], reqControls[cCount]->ldctl_oid ) == 0 ) {
  179. break;
  180. }
  181. }
  182. /* For now, ignore optype */
  183. if ( cbb->config.forward_ctrls == NULL || cbb->config.forward_ctrls[i] == NULL) {
  184. if (reqControls[cCount]->ldctl_iscritical) {
  185. rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  186. break;
  187. }
  188. /* Skip it */
  189. } else {
  190. ctrls[dCount]=slapi_dup_control(reqControls[cCount]);
  191. dCount++;
  192. }
  193. }
  194. }
  195. slapi_rwlock_unlock(cbb->config.rwl_config_lock);
  196. if (LDAP_SUCCESS != rc) {
  197. ldap_controls_free(ctrls);
  198. return rc;
  199. }
  200. /***************************************/
  201. /* add impersonation control if needed */
  202. /***************************************/
  203. if ( !(cb->impersonate) ) {
  204. /* don't add proxy control */
  205. addauth=0;
  206. }
  207. if (addauth) {
  208. slapi_pblock_get( pb, SLAPI_REQUESTOR_DN, &proxyDN );
  209. if ( slapi_ldap_create_proxyauth_control(ld, proxyDN, isabandon?0:1, 0, &ctrls[dCount] )) {
  210. ldap_controls_free(ctrls);
  211. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  212. "LDAP_CONTROL_PROXYAUTH control encoding failed.\n");
  213. return LDAP_OPERATIONS_ERROR;
  214. }
  215. dCount++;
  216. }
  217. /***********************************************************/
  218. /* add loop control if needed */
  219. /* Don't add it if not in the list of forwardable controls */
  220. /***********************************************************/
  221. if (!useloop) {
  222. for ( i = 0; cbb->config.forward_ctrls != NULL
  223. && cbb->config.forward_ctrls[i] != NULL; ++i ) {
  224. if ( strcmp( cbb->config.forward_ctrls[i],
  225. CB_LDAP_CONTROL_CHAIN_SERVER) == 0 ) {
  226. break;
  227. }
  228. }
  229. }
  230. if ( useloop || (cbb->config.forward_ctrls !=NULL && cbb->config.forward_ctrls[i] !=NULL)){
  231. if (hops > 0) {
  232. hops--;
  233. } else {
  234. hops = cb->hoplimit;
  235. }
  236. /* loop control's critical flag is 0;
  237. * no special treatment is needed for abandon */
  238. cb_create_loop_control(hops,&ctrls[dCount]);
  239. dCount++;
  240. }
  241. if (dCount==0) {
  242. ldap_controls_free(ctrls);
  243. } else {
  244. *controls = ctrls;
  245. }
  246. return LDAP_SUCCESS;
  247. }