1
0

posix-group-task.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. #include "slapi-plugin.h"
  2. #include "nspr.h"
  3. #include "posix-wsp-ident.h"
  4. #include "posix-group-func.h"
  5. typedef struct _task_data
  6. {
  7. char *dn; /* search base */
  8. char *filter_str; /* search filter */
  9. } task_data;
  10. typedef struct _cb_data
  11. {
  12. char *dn;
  13. void *txn;
  14. } cb_data;
  15. /*
  16. typedef struct _posix_group_task_data
  17. {
  18. POSIX_WinSync_Config *config;
  19. Slapi_Value *memberdn_val;
  20. Slapi_ValueSet **uidvals;
  21. void *txn;
  22. } posix_group_data_data;
  23. */
  24. /* interface function */
  25. int
  26. posix_group_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int *returncode,
  27. char *returntext, void *arg);
  28. static void
  29. posix_group_task_destructor(Slapi_Task *task);
  30. static void
  31. posix_group_fixup_task_thread(void *arg);
  32. static int
  33. posix_group_fix_memberuid_callback(Slapi_Entry *e, void *callback_data);
  34. /* extract a single value from the entry (as a string) -- if it's not in the
  35. * entry, the default will be returned (which can be NULL).
  36. * you do not need to free anything returned by this.
  37. */
  38. static const char *
  39. fetch_attr(Slapi_Entry *e, const char *attrname, const char *default_val)
  40. {
  41. Slapi_Attr *attr;
  42. Slapi_Value *val = NULL;
  43. if (slapi_entry_attr_find(e, attrname, &attr) != 0)
  44. return default_val;
  45. slapi_attr_first_value(attr, &val);
  46. return slapi_value_get_string(val);
  47. }
  48. /* e configEntry */
  49. int
  50. posix_group_task_add(Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Entry *eAfter, int *returncode,
  51. char *returntext, void *arg)
  52. {
  53. PRThread *thread = NULL;
  54. int rv = SLAPI_DSE_CALLBACK_OK;
  55. task_data *mytaskdata = NULL;
  56. Slapi_Task *task = NULL;
  57. const char *filter;
  58. const char *dn = 0;
  59. *returncode = LDAP_SUCCESS;
  60. /* get arg(s) */
  61. /* default: set replication basedn */
  62. if ((dn = fetch_attr(e, "basedn", slapi_sdn_get_dn(posix_winsync_config_get_suffix()))) == NULL) {
  63. *returncode = LDAP_OBJECT_CLASS_VIOLATION;
  64. rv = SLAPI_DSE_CALLBACK_ERROR;
  65. goto out;
  66. }
  67. if ((filter = fetch_attr(e, "filter", "(&(objectclass=posixGroup)(uniquemember=*))")) == NULL) {
  68. *returncode = LDAP_OBJECT_CLASS_VIOLATION;
  69. rv = SLAPI_DSE_CALLBACK_ERROR;
  70. goto out;
  71. }
  72. /* setup our task data */
  73. mytaskdata = (task_data*) slapi_ch_malloc(sizeof(task_data));
  74. if (mytaskdata == NULL) {
  75. *returncode = LDAP_OPERATIONS_ERROR;
  76. rv = SLAPI_DSE_CALLBACK_ERROR;
  77. goto out;
  78. }
  79. mytaskdata->dn = slapi_ch_strdup(dn);
  80. mytaskdata->filter_str = slapi_ch_strdup(filter);
  81. /* allocate new task now */
  82. task = slapi_new_task(slapi_entry_get_ndn(e));
  83. /* register our destructor for cleaning up our private data */
  84. slapi_task_set_destructor_fn(task, posix_group_task_destructor);
  85. /* Stash a pointer to our data in the task */
  86. slapi_task_set_data(task, mytaskdata);
  87. /* start the sample task as a separate thread */
  88. thread = PR_CreateThread(PR_USER_THREAD, posix_group_fixup_task_thread, (void *) task,
  89. PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD,
  90. SLAPD_DEFAULT_THREAD_STACKSIZE);
  91. if (thread == NULL) {
  92. slapi_log_error(SLAPI_LOG_FATAL, POSIX_WINSYNC_PLUGIN_NAME,
  93. "unable to create task thread!\n");
  94. *returncode = LDAP_OPERATIONS_ERROR;
  95. rv = SLAPI_DSE_CALLBACK_ERROR;
  96. slapi_task_finish(task, *returncode);
  97. } else {
  98. rv = SLAPI_DSE_CALLBACK_OK;
  99. }
  100. out: return rv;
  101. }
  102. static void
  103. posix_group_task_destructor(Slapi_Task *task)
  104. {
  105. if (task) {
  106. task_data *mydata = (task_data *) slapi_task_get_data(task);
  107. if (mydata) {
  108. slapi_ch_free_string(&mydata->dn);
  109. slapi_ch_free_string(&mydata->filter_str);
  110. /* Need to cast to avoid a compiler warning */
  111. slapi_ch_free((void **) &mydata);
  112. }
  113. }
  114. }
  115. static int
  116. posix_group_del_memberuid_callback(Slapi_Entry *e, void *callback_data)
  117. {
  118. int rc = 0;
  119. LDAPMod mod;
  120. LDAPMod *mods[2];
  121. char *val[2];
  122. Slapi_PBlock *mod_pb = 0;
  123. cb_data *the_cb_data = (cb_data *) callback_data;
  124. mod_pb = slapi_pblock_new();
  125. mods[0] = &mod;
  126. mods[1] = 0;
  127. val[0] = 0; /* all */
  128. val[1] = 0;
  129. mod.mod_op = LDAP_MOD_DELETE;
  130. mod.mod_type = "memberuid";
  131. mod.mod_values = val;
  132. slapi_modify_internal_set_pb_ext(mod_pb, slapi_entry_get_sdn(e), mods, 0, 0,
  133. posix_winsync_get_plugin_identity(), 0);
  134. slapi_pblock_set(mod_pb, SLAPI_TXN, the_cb_data->txn);
  135. slapi_modify_internal_pb(mod_pb);
  136. slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  137. slapi_pblock_destroy(mod_pb);
  138. return rc;
  139. }
  140. static int
  141. posix_group_fix_memberuid(char *dn, char *filter_str, void *txn)
  142. {
  143. int rc = 0;
  144. struct _cb_data callback_data = { dn, txn };
  145. Slapi_PBlock *search_pb = slapi_pblock_new();
  146. /* char *attrs[]={"uniquemember","memberuid",NULL}; */
  147. slapi_search_internal_set_pb(search_pb, dn, LDAP_SCOPE_SUBTREE, filter_str, 0, 0, 0, 0,
  148. posix_winsync_get_plugin_identity(), 0);
  149. slapi_pblock_set(search_pb, SLAPI_TXN, txn); /* set transaction id */
  150. rc = slapi_search_internal_callback_pb(search_pb, &callback_data, 0,
  151. posix_group_fix_memberuid_callback, 0);
  152. slapi_pblock_destroy(search_pb);
  153. return rc;
  154. }
  155. /* posix_group_fix_memberuid_callback()
  156. * Add initial and/or fix up broken group list in entry
  157. *
  158. * 1. forall uniquemember search if posixAccount ? add uid : ""
  159. */
  160. static int
  161. posix_group_fix_memberuid_callback(Slapi_Entry *e, void *callback_data)
  162. {
  163. int rc = 0;
  164. char *dn = slapi_entry_get_dn(e);
  165. Slapi_DN *sdn = slapi_entry_get_sdn(e);
  166. Slapi_Attr *obj_attr = NULL;
  167. rc = slapi_entry_attr_find(e, "uniquemember", &obj_attr);
  168. if (rc == 0) { /* Found uniquemember, so... */
  169. int i;
  170. Slapi_Value * value = slapi_value_new(); /* new memberuid Attribute values */
  171. Slapi_Value * uniqval = NULL; /* uniquemeber Attribute values */
  172. Slapi_ValueSet *uids = slapi_valueset_new();
  173. slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME,
  174. "_fix_memberuid scan uniquemember, group %s\n", dn);
  175. for (i = slapi_attr_first_value(obj_attr, &uniqval); i != -1;
  176. i = slapi_attr_next_value(obj_attr, i, &uniqval)) {
  177. const char *member = NULL;
  178. char * uid = NULL;
  179. member = slapi_value_get_string(uniqval);
  180. /* search uid for member (DN) */
  181. slapi_log_error(SLAPI_LOG_PLUGIN, POSIX_WINSYNC_PLUGIN_NAME, "search %s\n", member);
  182. if ((uid = searchUid(member)) != NULL) {
  183. slapi_value_set_string(value, uid);
  184. /* add uids ValueSet */
  185. slapi_valueset_add_value(uids, value);
  186. }
  187. }
  188. slapi_value_free(&value);
  189. /* If we found some posix members, replace the existing memberuid attribute
  190. * with the found values. */
  191. if (uids && slapi_valueset_count(uids)) {
  192. Slapi_PBlock *mod_pb = slapi_pblock_new();
  193. Slapi_Value *val = 0;
  194. Slapi_Mod *smod;
  195. LDAPMod **mods = (LDAPMod **) slapi_ch_malloc(2 * sizeof(LDAPMod *));
  196. int hint = 0;
  197. cb_data *the_cb_data = (cb_data *) callback_data;
  198. smod = slapi_mod_new();
  199. slapi_mod_init(smod, 0);
  200. slapi_mod_set_operation(smod, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
  201. slapi_mod_set_type(smod, "memberuid");
  202. /* Loop through all of our values and add them to smod */
  203. hint = slapi_valueset_first_value(uids, &val);
  204. while (val) {
  205. /* this makes a copy of the berval */
  206. slapi_mod_add_value(smod, slapi_value_get_berval(val));
  207. hint = slapi_valueset_next_value(uids, hint, &val);
  208. }
  209. mods[0] = slapi_mod_get_ldapmod_passout(smod);
  210. mods[1] = 0;
  211. slapi_modify_internal_set_pb_ext(mod_pb, sdn, mods, 0, 0,
  212. posix_winsync_get_plugin_identity(), 0);
  213. slapi_pblock_set(mod_pb, SLAPI_TXN, the_cb_data->txn);
  214. slapi_modify_internal_pb(mod_pb);
  215. slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  216. ldap_mods_free(mods, 1);
  217. slapi_mod_free(&smod);
  218. slapi_pblock_destroy(mod_pb);
  219. } else {
  220. /* No member were found, so remove the memberuid attribute
  221. * from this entry. */
  222. posix_group_del_memberuid_callback(e, callback_data);
  223. }
  224. slapi_valueset_free(uids);
  225. }
  226. return rc;
  227. }
  228. static void
  229. posix_group_fixup_task_thread(void *arg)
  230. {
  231. Slapi_Task *task = (Slapi_Task *) arg;
  232. task_data *td = NULL;
  233. int rc = 0;
  234. /* Fetch our task data from the task */
  235. td = (task_data *) slapi_task_get_data(task);
  236. slapi_task_begin(task, 1);
  237. slapi_task_log_notice(task, "posix_group task starts (arg: %s) ...\n", td->filter_str);
  238. /* get the memberOf operation lock */
  239. memberUidLock();
  240. /* do real work */
  241. rc = posix_group_fix_memberuid(td->dn, td->filter_str, NULL /* no txn? */);
  242. /* release the memberOf operation lock */
  243. memberUidUnlock();
  244. slapi_task_log_notice(task, "posix_group task finished.");
  245. slapi_task_log_status(task, "posix_group task finished.");
  246. slapi_task_inc_progress(task);
  247. /* this will queue the destruction of the task */
  248. slapi_task_finish(task, rc);
  249. }