cb_controls.c 9.6 KB

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