aclplugin.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  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. /*
  7. * There are 3 ACL PLUGIN points
  8. * PREOP, POSTOP and ACL plugin
  9. *
  10. */
  11. #include "acl.h"
  12. #include "dirver.h"
  13. #include <dirlite_strings.h> /* PLUGIN_MAGIC_VENDOR_STR */
  14. static Slapi_PluginDesc pdesc = { "acl", PLUGIN_MAGIC_VENDOR_STR, PRODUCTTEXT, "acl access check plugin" };
  15. char *plugin_name = ACL_PLUGIN_NAME;
  16. /* Prototypes */
  17. static int aclplugin_preop_search ( Slapi_PBlock *pb );
  18. static int aclplugin_preop_modify ( Slapi_PBlock *pb );
  19. static int aclplugin_preop_common ( Slapi_PBlock *pb );
  20. /*******************************************************************************
  21. * ACL PLUGIN Architecture
  22. *
  23. * There are 3 registered plugins:
  24. *
  25. * 1) PREOP ACL Plugin
  26. * The preop plugin does all the initialization. It allocate the ACL
  27. * PBlock and copies stuff from the connection if it needs to.
  28. *
  29. * 2) POSTOP ACL Plugin
  30. * The Postop plugin cleans up the ACL PBlock. It copies Back to the
  31. * connection struct. The Postop bind & Unbind cleans up the
  32. * ACL CBlock ( struct hanging from conn struct ).
  33. *
  34. * 3) ACCESSCONTROL Plugin
  35. * Main module which does the access check. There are 5 entry point
  36. * from this plugin
  37. * a) Initilize the ACL system i.e read all the ACLs and generate the
  38. * the ACL List.
  39. * b) Check for ACI syntax.
  40. * c) Check for normal access.
  41. * d) Check for access to a mod request.
  42. * e) Update the in-memory ACL List.
  43. *
  44. *******************************************************************************/
  45. /*******************************************************************************
  46. * PREOP
  47. *******************************************************************************/
  48. /* Plugin identity is passed by the server in the plugin init function and must
  49. be supplied by the plugin to all internal operations it initiates
  50. */
  51. void* g_acl_preop_plugin_identity;
  52. int
  53. acl_preopInit (Slapi_PBlock *pb)
  54. {
  55. int rc = 0;
  56. /* save plugin identity to later pass to internal operations */
  57. rc = slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &g_acl_preop_plugin_identity);
  58. /* Declare plugin version */
  59. rc = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01);
  60. /* Provide descriptive information */
  61. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void*)&pdesc);
  62. /* Register functions */
  63. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_SEARCH_FN, (void*)aclplugin_preop_search);
  64. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_COMPARE_FN, (void*)aclplugin_preop_search);
  65. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN, (void*)aclplugin_preop_modify);
  66. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODIFY_FN, (void*)aclplugin_preop_modify);
  67. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODRDN_FN, (void*)aclplugin_preop_modify);
  68. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_DELETE_FN, (void*)aclplugin_preop_modify);
  69. #if 0
  70. /*
  71. * XXXmcs: In order to support access control checking from
  72. * extended operations, we need a SLAPI_PLUGIN_PRE_EXTENDED_FN hook.
  73. * But today no such entry point exists.
  74. */
  75. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_EXTENDED_FN, (void*)aclplugin_preop_modify);
  76. #endif
  77. slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "<= acl_preop_Init %d\n", rc, 0, 0 );
  78. return( rc );
  79. }
  80. /* For preop search we do two things:
  81. * 1) based on the search base, we preselect the acls.
  82. * 2) also get hold of a acl_pblock for use
  83. */
  84. static int
  85. aclplugin_preop_search ( Slapi_PBlock *pb )
  86. {
  87. int scope;
  88. char *base = NULL;
  89. int optype;
  90. int isRoot;
  91. int rc = 0;
  92. TNF_PROBE_0_DEBUG(aclplugin_preop_search_start ,"ACL","");
  93. slapi_pblock_get ( pb, SLAPI_OPERATION_TYPE, &optype );
  94. slapi_pblock_get ( pb, SLAPI_REQUESTOR_ISROOT, &isRoot );
  95. if ( isRoot ) {
  96. TNF_PROBE_1_DEBUG(aclplugin_preop_search_end ,"ACL","",
  97. tnf_string,isroot,"");
  98. return rc;
  99. }
  100. slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &base );
  101. /* For anonymous client doing search nothing needs to be set up */
  102. if ( optype == SLAPI_OPERATION_SEARCH && aclanom_is_client_anonymous ( pb ) &&
  103. ! slapi_dn_issuffix( base, "cn=monitor") ) {
  104. TNF_PROBE_1_DEBUG(aclplugin_preop_search_end ,"ACL","",
  105. tnf_string,anon,"");
  106. return rc;
  107. }
  108. if ( 0 == ( rc = aclplugin_preop_common( pb ))) {
  109. slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope );
  110. acllist_init_scan ( pb, scope, base );
  111. }
  112. TNF_PROBE_0_DEBUG(aclplugin_preop_search_end ,"ACL","");
  113. return rc;
  114. }
  115. /*
  116. * For rest of the opertion type, we get a hold of the acl
  117. * private Block.
  118. */
  119. static int
  120. aclplugin_preop_modify ( Slapi_PBlock *pb )
  121. {
  122. /*
  123. * Note: since we don't keep the anom profile for modifies, we have to go
  124. * through the regular process to check the access.
  125. */
  126. return aclplugin_preop_common( pb );
  127. }
  128. /*
  129. * Common function that is called by aclplugin_preop_search() and
  130. * aclplugin_preop_modify().
  131. *
  132. * Return values:
  133. * 0 - all is well; proceed.
  134. * 1 - fatal error; result has been sent to client.
  135. */
  136. static int
  137. aclplugin_preop_common( Slapi_PBlock *pb )
  138. {
  139. char *proxy_dn; /* id being assumed */
  140. char *dn; /* proxy master */
  141. char *errtext = NULL;
  142. int lderr;
  143. Acl_PBlock *aclpb;
  144. TNF_PROBE_0_DEBUG(aclplugin_preop_common_start ,"ACL","");
  145. aclpb = acl_get_aclpb ( pb, ACLPB_BINDDN_PBLOCK );
  146. /*
  147. * The following mallocs memory for proxy_dn, but not the dn.
  148. * The proxy_dn is the id being assumed, while dn
  149. * is the "proxy master".
  150. */
  151. proxy_dn = NULL;
  152. if ( LDAP_SUCCESS != ( lderr = acl_get_proxyauth_dn( pb, &proxy_dn,
  153. &errtext ))) {
  154. /*
  155. * Fatal error -- send a result to the client and arrange to skip
  156. * any further processing.
  157. */
  158. slapi_send_ldap_result( pb, lderr, NULL, errtext, 0, NULL );
  159. TNF_PROBE_1_DEBUG(aclplugin_preop_common_end ,"ACL","",
  160. tnf_string,proxid_error,"");
  161. return 1; /* skip any further processing */
  162. }
  163. slapi_pblock_get ( pb, SLAPI_REQUESTOR_DN, &dn );
  164. /*
  165. * The dn is copied into the aclpb during initialization.
  166. */
  167. if ( proxy_dn) {
  168. TNF_PROBE_0_DEBUG(proxyacpb_init_start,"ACL","");
  169. slapi_log_error( SLAPI_LOG_ACL, plugin_name,
  170. "proxied authorization dn is (%s)\n", proxy_dn );
  171. acl_init_aclpb ( pb, aclpb, proxy_dn, 1 );
  172. aclpb = acl_new_proxy_aclpb (pb );
  173. acl_init_aclpb ( pb, aclpb, dn, 0 );
  174. slapi_ch_free ( (void **) &proxy_dn );
  175. TNF_PROBE_0_DEBUG(proxyacpb_init_end,"ACL","");
  176. } else {
  177. TNF_PROBE_0_DEBUG(aclpb_init_start,"ACL","");
  178. acl_init_aclpb ( pb, aclpb, dn, 1 );
  179. TNF_PROBE_0_DEBUG(aclpb_init_end,"ACL","");
  180. }
  181. TNF_PROBE_0_DEBUG(aclplugin_preop_common_end ,"ACL","");
  182. return 0;
  183. }
  184. /*******************************************************************************
  185. * POSTOP
  186. *******************************************************************************/
  187. /*******************************************************************************
  188. * ACCESSCONTROL PLUGIN
  189. *******************************************************************************/
  190. void* g_acl_plugin_identity;
  191. /* For now, the acl component is implemented as 2 different plugins */
  192. /* Return the right plugin identity */
  193. void * aclplugin_get_identity(int plug) {
  194. if (plug == ACL_PLUGIN_IDENTITY)
  195. return g_acl_plugin_identity;
  196. if (plug == ACL_PREOP_PLUGIN_IDENTITY)
  197. return g_acl_preop_plugin_identity;
  198. return NULL;
  199. }
  200. int
  201. aclplugin_init (Slapi_PBlock *pb )
  202. {
  203. int rc = 0; /* OK */
  204. rc = aclinit_main ( pb );
  205. return rc;
  206. }
  207. int
  208. aclplugin_stop ( Slapi_PBlock *pb )
  209. {
  210. int rc = 0; /* OK */
  211. /* nothing to be done now */
  212. return rc;
  213. }
  214. int
  215. acl_init( Slapi_PBlock *pb )
  216. {
  217. int rc =0;
  218. slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "=> acl_init\n", 0, 0, 0 );
  219. if ( 0 != acl_init_ext() ) {
  220. slapi_log_error ( SLAPI_LOG_FATAL, plugin_name,
  221. "Unable to initialize the extensions\n");
  222. return 1;
  223. }
  224. /* save plugin identity to later pass to internal operations */
  225. rc = slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &g_acl_plugin_identity);
  226. rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
  227. (void *) SLAPI_PLUGIN_VERSION_01 );
  228. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
  229. (void *)&pdesc );
  230. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN, (void *) aclplugin_init );
  231. rc = slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, (void *) aclplugin_stop );
  232. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_ACL_SYNTAX_CHECK,
  233. (void *) acl_verify_aci_syntax );
  234. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_ACL_ALLOW_ACCESS,
  235. (void *) acl_access_allowed_main );
  236. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_ACL_MODS_ALLOWED,
  237. (void *) acl_check_mods );
  238. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_ACL_MODS_UPDATE,
  239. (void *) acl_modified );
  240. slapi_log_error( SLAPI_LOG_PLUGIN, plugin_name, "<= acl_init %d\n", rc, 0, 0 );
  241. return( rc );
  242. }
  243. /*
  244. *
  245. * acl_access_allowed_main
  246. * Main interface to the plugin. Calls different access check functions
  247. * based on the flag.
  248. *
  249. *
  250. * Returns:
  251. * LDAP_SUCCESS -- access is granted
  252. * LDAP_INSUFFICIENT_ACCESS -- access denied
  253. * <other ldap error> -- ex: opererations error
  254. *
  255. */
  256. int
  257. acl_access_allowed_main ( Slapi_PBlock *pb, Slapi_Entry *e, char **attrs,
  258. struct berval *val, int access , int flags, char **errbuf)
  259. {
  260. int rc =0;
  261. char *attr = NULL;
  262. TNF_PROBE_0_DEBUG(acl_access_allowed_main_start,"ACL","");
  263. if (attrs && *attrs) attr = attrs[0];
  264. if (ACLPLUGIN_ACCESS_READ_ON_ENTRY == flags)
  265. rc = acl_read_access_allowed_on_entry ( pb, e, attrs, access);
  266. else if ( ACLPLUGIN_ACCESS_READ_ON_ATTR == flags)
  267. rc = acl_read_access_allowed_on_attr ( pb, e, attr, val, access);
  268. else if ( ACLPLUGIN_ACCESS_READ_ON_VLV == flags)
  269. rc = acl_access_allowed_disjoint_resource ( pb, e, attr, val, access);
  270. else if ( ACLPLUGIN_ACCESS_MODRDN == flags)
  271. rc = acl_access_allowed_modrdn ( pb, e, attr, val, access);
  272. else if ( ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS == flags)
  273. rc = acl_get_effective_rights ( pb, e, attrs, val, access, errbuf );
  274. else
  275. rc = acl_access_allowed ( pb, e, attr, val, access);
  276. /* generate the appropriate error message */
  277. if ( ( rc != LDAP_SUCCESS ) && errbuf &&
  278. ( ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS != flags ) &&
  279. ( access & ( SLAPI_ACL_WRITE | SLAPI_ACL_ADD | SLAPI_ACL_DELETE ))) {
  280. char *edn = slapi_entry_get_dn ( e );
  281. acl_gen_err_msg(access, edn, attr, errbuf);
  282. }
  283. TNF_PROBE_0_DEBUG(acl_access_allowed_main_end,"ACL","");
  284. return rc;
  285. }
  286. #ifdef _WIN32
  287. int *module_ldap_debug = 0;
  288. void plugin_init_debug_level ( int *level_ptr )
  289. {
  290. module_ldap_debug = level_ptr;
  291. }
  292. #endif