1
0

cb_controls.c 11 KB

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