1
0

cb_controls.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #include "cb.h"
  39. /*
  40. ** Controls that can't be forwarded due to the current implementation
  41. */
  42. static char * unsupported_ctrls[] = {LDAP_CONTROL_PERSISTENTSEARCH,NULL};
  43. int cb_is_control_forwardable(cb_backend * cb, char *controloid) {
  44. return (!(charray_inlist(unsupported_ctrls,controloid)));
  45. }
  46. void
  47. cb_register_supported_control( cb_backend * cb, char *controloid, unsigned long controlops )
  48. {
  49. /* For now, ignore controlops */
  50. if ( controloid != NULL ) {
  51. PR_RWLock_Wlock(cb->config.rwl_config_lock);
  52. charray_add( &cb->config.forward_ctrls,slapi_ch_strdup( controloid ));
  53. PR_RWLock_Unlock(cb->config.rwl_config_lock);
  54. }
  55. }
  56. void
  57. cb_unregister_all_supported_control( cb_backend * cb ) {
  58. PR_RWLock_Wlock(cb->config.rwl_config_lock);
  59. charray_free(cb->config.forward_ctrls);
  60. cb->config.forward_ctrls=NULL;
  61. PR_RWLock_Unlock(cb->config.rwl_config_lock);
  62. }
  63. void
  64. cb_unregister_supported_control( cb_backend * cb, char *controloid, unsigned long controlops )
  65. {
  66. /* For now, ignore controlops */
  67. if ( controloid != NULL ) {
  68. int i;
  69. PR_RWLock_Wlock(cb->config.rwl_config_lock);
  70. for ( i = 0; cb->config.forward_ctrls != NULL && cb->config.forward_ctrls[i] != NULL; ++i ) {
  71. if ( strcmp( cb->config.forward_ctrls[i], controloid ) == 0 ) {
  72. break;
  73. }
  74. }
  75. if ( cb->config.forward_ctrls == NULL || cb->config.forward_ctrls[i] == NULL) {
  76. PR_RWLock_Unlock(cb->config.rwl_config_lock);
  77. return;
  78. }
  79. if ( controlops == 0 ) {
  80. charray_remove(cb->config.forward_ctrls,controloid);
  81. }
  82. PR_RWLock_Unlock(cb->config.rwl_config_lock);
  83. }
  84. }
  85. int cb_create_loop_control (
  86. const ber_int_t hops,
  87. LDAPControl **ctrlp)
  88. {
  89. BerElement *ber;
  90. int rc;
  91. if ((ber = ber_alloc()) == NULL)
  92. return -1;
  93. if ( ber_printf( ber, "i", hops ) < 0) {
  94. ber_free(ber,1);
  95. return -1;
  96. }
  97. rc = slapi_build_control( CB_LDAP_CONTROL_CHAIN_SERVER, ber, 0, ctrlp);
  98. ber_free(ber,1);
  99. return rc;
  100. }
  101. /*
  102. ** Return the controls to be passed to the remote
  103. ** farm server and the LDAP error to return.
  104. **
  105. ** Add the Proxied Authorization control when impersonation
  106. ** is enabled. Other controls present in the request are added
  107. ** to the control list
  108. **
  109. ** #622885 .abandon should not inherit the to-be-abandoned-operation's controls
  110. ** .controls attached to abandon should not be critical
  111. */
  112. int cb_update_controls( Slapi_PBlock * pb,
  113. LDAP * ld,
  114. LDAPControl *** controls,
  115. int ctrl_flags
  116. )
  117. {
  118. int cCount=0;
  119. int dCount=0;
  120. int i;
  121. char * proxyDN=NULL;
  122. LDAPControl ** reqControls = NULL;
  123. LDAPControl ** ctrls = NULL;
  124. cb_backend_instance * cb;
  125. cb_backend * cbb;
  126. Slapi_Backend * be;
  127. int rc=LDAP_SUCCESS;
  128. ber_int_t hops=0;
  129. int useloop=0;
  130. int addauth = (ctrl_flags & CB_UPDATE_CONTROLS_ADDAUTH);
  131. int isabandon = (ctrl_flags & CB_UPDATE_CONTROLS_ISABANDON);
  132. int op_type = 0;
  133. *controls = NULL;
  134. slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &op_type);
  135. if (!isabandon || op_type == SLAPI_OPERATION_ABANDON) {
  136. /* if not abandon or abandon sent by client */
  137. slapi_pblock_get( pb, SLAPI_REQCONTROLS, &reqControls );
  138. }
  139. slapi_pblock_get( pb, SLAPI_BACKEND, &be );
  140. slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &cbb );
  141. cb = cb_get_instance(be);
  142. /*****************************************/
  143. /* First, check for unsupported controls */
  144. /* Return an error if critical control */
  145. /* else remove it from the control list */
  146. /*****************************************/
  147. for ( cCount=0; reqControls && reqControls[cCount]; cCount++ );
  148. ctrls = (LDAPControl **)slapi_ch_calloc(1,sizeof(LDAPControl *) * (cCount +3));
  149. PR_RWLock_Rlock(cbb->config.rwl_config_lock);
  150. for ( cCount=0; reqControls && reqControls[cCount]; cCount++ ) {
  151. /* XXXSD CASCADING */
  152. /* For now, allow PROXY_AUTH control forwarding only when */
  153. /* local acl evaluation to prevent unauthorized access */
  154. if (!strcmp(reqControls[cCount]->ldctl_oid,LDAP_CONTROL_PROXYAUTH)) {
  155. /* we have to force remote acl checking if the associated backend to this
  156. chaining backend is disabled - disabled == no acl check possible */
  157. if (!cb->local_acl && !cb->associated_be_is_disabled) {
  158. slapi_log_error( SLAPI_LOG_PLUGIN,CB_PLUGIN_SUBSYSTEM,
  159. "local aci check required to handle proxied auth control. Deny access.\n");
  160. rc= LDAP_INSUFFICIENT_ACCESS;
  161. break;
  162. }
  163. /* XXXSD Not safe to use proxied authorization with Directory Manager */
  164. /* checked earlier when impersonation is on */
  165. if (!cb->impersonate) {
  166. char * requestor,*rootdn;
  167. char * requestorCopy=NULL;
  168. rootdn=cb_get_rootdn();
  169. slapi_pblock_get( pb, SLAPI_REQUESTOR_DN, &requestor );
  170. requestorCopy=slapi_ch_strdup(requestor);
  171. slapi_dn_normalize_case(requestorCopy);
  172. if (!strcmp( requestorCopy, rootdn )) { /* UTF8- aware */
  173. slapi_log_error( SLAPI_LOG_PLUGIN,CB_PLUGIN_SUBSYSTEM,
  174. "Use of user <%s> incompatible with proxied auth. control\n",rootdn);
  175. rc=LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  176. slapi_ch_free((void **)&requestorCopy);
  177. break;
  178. }
  179. slapi_ch_free((void **)&rootdn);
  180. slapi_ch_free((void **)&requestorCopy);
  181. }
  182. addauth=0;
  183. ctrls[dCount]=slapi_dup_control(reqControls[cCount]);
  184. dCount++;
  185. } else
  186. if (!strcmp(reqControls[cCount]->ldctl_oid,CB_LDAP_CONTROL_CHAIN_SERVER)) {
  187. /* Max hop count reached ? */
  188. /* Checked realier by a call to cb_forward_operation() */
  189. BerElement *ber = NULL;
  190. ber = ber_init(&(reqControls[cCount]->ldctl_value));
  191. ber_scanf(ber,"i",&hops);
  192. ber_free(ber,1);
  193. useloop=1;
  194. /* Add to the control list later */
  195. } else {
  196. int i;
  197. for ( i = 0; cbb->config.forward_ctrls != NULL
  198. && cbb->config.forward_ctrls[i] != NULL; ++i ) {
  199. if ( strcmp( cbb->config.forward_ctrls[i], reqControls[cCount]->ldctl_oid ) == 0 ) {
  200. break;
  201. }
  202. }
  203. /* For now, ignore optype */
  204. if ( cbb->config.forward_ctrls == NULL || cbb->config.forward_ctrls[i] == NULL) {
  205. if (reqControls[cCount]->ldctl_iscritical) {
  206. rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  207. break;
  208. }
  209. /* Skip it */
  210. } else {
  211. ctrls[dCount]=slapi_dup_control(reqControls[cCount]);
  212. dCount++;
  213. }
  214. }
  215. }
  216. PR_RWLock_Unlock(cbb->config.rwl_config_lock);
  217. if (LDAP_SUCCESS != rc) {
  218. ldap_controls_free(ctrls);
  219. return rc;
  220. }
  221. /***************************************/
  222. /* add impersonation control if needed */
  223. /***************************************/
  224. if ( !(cb->impersonate) ) {
  225. /* don't add proxy control */
  226. addauth=0;
  227. }
  228. if (addauth) {
  229. slapi_pblock_get( pb, SLAPI_REQUESTOR_DN, &proxyDN );
  230. if ( ldap_create_proxyauth_control(ld, proxyDN, isabandon?0:1, &ctrls[dCount] )) {
  231. ldap_controls_free(ctrls);
  232. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  233. "LDAP_CONTROL_PROXYAUTH control encoding failed.\n");
  234. return LDAP_OPERATIONS_ERROR;
  235. }
  236. dCount++;
  237. }
  238. /***********************************************************/
  239. /* add loop control if needed */
  240. /* Don't add it if not in the list of forwardable controls */
  241. /***********************************************************/
  242. if (!useloop) {
  243. for ( i = 0; cbb->config.forward_ctrls != NULL
  244. && cbb->config.forward_ctrls[i] != NULL; ++i ) {
  245. if ( strcmp( cbb->config.forward_ctrls[i],
  246. CB_LDAP_CONTROL_CHAIN_SERVER) == 0 ) {
  247. break;
  248. }
  249. }
  250. }
  251. if ( useloop || (cbb->config.forward_ctrls !=NULL && cbb->config.forward_ctrls[i] !=NULL)){
  252. if (hops > 0) {
  253. hops--;
  254. } else {
  255. hops = cb->hoplimit;
  256. }
  257. /* loop control's critical flag is 0;
  258. * no special treatment is needed for abandon */
  259. cb_create_loop_control(hops,&ctrls[dCount]);
  260. dCount++;
  261. }
  262. if (dCount==0) {
  263. ldap_controls_free(ctrls);
  264. } else {
  265. *controls = ctrls;
  266. }
  267. return LDAP_SUCCESS;
  268. }