cb_controls.c 9.2 KB

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