cb_instance.c 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911
  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. #include "plstr.h"
  43. /*
  44. ** 1 set/get function for each parameter of a backend instance
  45. ** NOTE: Some parameters won't be taken into account until the server has restarted
  46. ** In such cases, the internal conf is not updated but the new value is stored in the
  47. ** dse.ldif file.
  48. **/
  49. /* Get functions */
  50. static void *cb_instance_hosturl_get(void *arg);
  51. static void *cb_instance_binduser_get(void *arg);
  52. static void *cb_instance_userpassword_get(void *arg);
  53. static void *cb_instance_maxbconn_get(void *arg);
  54. static void *cb_instance_maxconn_get(void *arg);
  55. static void *cb_instance_abandonto_get(void *arg);
  56. static void *cb_instance_maxbconc_get(void *arg);
  57. static void *cb_instance_maxconc_get(void *arg);
  58. static void *cb_instance_imperson_get(void *arg);
  59. static void *cb_instance_connlife_get(void *arg);
  60. static void *cb_instance_bindto_get(void *arg);
  61. static void *cb_instance_opto_get(void *arg);
  62. static void *cb_instance_ref_get(void *arg);
  63. static void *cb_instance_acl_get(void *arg);
  64. static void *cb_instance_bindretry_get(void *arg);
  65. static void *cb_instance_sizelimit_get(void *arg);
  66. static void *cb_instance_timelimit_get(void *arg);
  67. static void *cb_instance_hoplimit_get(void *arg);
  68. static void *cb_instance_max_idle_get(void *arg);
  69. static void *cb_instance_max_test_get(void *arg);
  70. /* Set functions */
  71. static int cb_instance_hosturl_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  72. static int cb_instance_binduser_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  73. static int cb_instance_userpassword_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  74. static int cb_instance_maxbconn_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  75. static int cb_instance_maxconn_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  76. static int cb_instance_abandonto_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  77. static int cb_instance_maxbconc_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  78. static int cb_instance_maxconc_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  79. static int cb_instance_imperson_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  80. static int cb_instance_connlife_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  81. static int cb_instance_bindto_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  82. static int cb_instance_opto_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  83. static int cb_instance_ref_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  84. static int cb_instance_acl_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  85. static int cb_instance_bindretry_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  86. static int cb_instance_sizelimit_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  87. static int cb_instance_timelimit_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  88. static int cb_instance_hoplimit_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  89. static int cb_instance_max_idle_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  90. static int cb_instance_max_test_set(void *arg, void *value, char *errorbuf, int phase, int apply);
  91. /* Default hardwired values */
  92. cb_instance_config_info cb_the_instance_config[] = {
  93. {CB_CONFIG_HOSTURL,CB_CONFIG_TYPE_STRING,"",&cb_instance_hosturl_get,&cb_instance_hosturl_set,CB_ALWAYS_SHOW},
  94. {CB_CONFIG_BINDUSER, CB_CONFIG_TYPE_STRING, "", &cb_instance_binduser_get, &cb_instance_binduser_set,CB_ALWAYS_SHOW},
  95. {CB_CONFIG_USERPASSWORD,CB_CONFIG_TYPE_STRING,"",&cb_instance_userpassword_get,&cb_instance_userpassword_set,CB_ALWAYS_SHOW},
  96. {CB_CONFIG_MAXBINDCONNECTIONS,CB_CONFIG_TYPE_INT,CB_DEF_BIND_MAXCONNECTIONS,&cb_instance_maxbconn_get, &cb_instance_maxbconn_set,CB_ALWAYS_SHOW},
  97. {CB_CONFIG_MAXCONNECTIONS,CB_CONFIG_TYPE_INT,CB_DEF_MAXCONNECTIONS,&cb_instance_maxconn_get, &cb_instance_maxconn_set,CB_ALWAYS_SHOW},
  98. {CB_CONFIG_ABANDONTIMEOUT,CB_CONFIG_TYPE_INT,CB_DEF_ABANDON_TIMEOUT,&cb_instance_abandonto_get, &cb_instance_abandonto_set,CB_ALWAYS_SHOW},
  99. {CB_CONFIG_MAXBINDCONCURRENCY,CB_CONFIG_TYPE_INT,CB_DEF_BIND_MAXCONCURRENCY,&cb_instance_maxbconc_get, &cb_instance_maxbconc_set,CB_ALWAYS_SHOW},
  100. {CB_CONFIG_MAXCONCURRENCY,CB_CONFIG_TYPE_INT,CB_DEF_MAXCONCURRENCY,&cb_instance_maxconc_get, &cb_instance_maxconc_set,CB_ALWAYS_SHOW},
  101. {CB_CONFIG_IMPERSONATION,CB_CONFIG_TYPE_ONOFF,CB_DEF_IMPERSONATION,&cb_instance_imperson_get, &cb_instance_imperson_set,CB_ALWAYS_SHOW},
  102. {CB_CONFIG_CONNLIFETIME,CB_CONFIG_TYPE_INT,CB_DEF_CONNLIFETIME,&cb_instance_connlife_get, &cb_instance_connlife_set,CB_ALWAYS_SHOW},
  103. {CB_CONFIG_BINDTIMEOUT,CB_CONFIG_TYPE_INT,CB_DEF_BINDTIMEOUT,&cb_instance_bindto_get, &cb_instance_bindto_set,CB_ALWAYS_SHOW},
  104. {CB_CONFIG_TIMEOUT,CB_CONFIG_TYPE_INT,"0",&cb_instance_opto_get, &cb_instance_opto_set,0},
  105. {CB_CONFIG_REFERRAL,CB_CONFIG_TYPE_ONOFF,CB_DEF_SEARCHREFERRAL,&cb_instance_ref_get, &cb_instance_ref_set,CB_ALWAYS_SHOW},
  106. {CB_CONFIG_LOCALACL,CB_CONFIG_TYPE_ONOFF,CB_DEF_LOCALACL,&cb_instance_acl_get, &cb_instance_acl_set,CB_ALWAYS_SHOW},
  107. {CB_CONFIG_BINDRETRY,CB_CONFIG_TYPE_INT,CB_DEF_BINDRETRY,&cb_instance_bindretry_get, &cb_instance_bindretry_set,CB_ALWAYS_SHOW},
  108. {CB_CONFIG_SIZELIMIT,CB_CONFIG_TYPE_INT,CB_DEF_SIZELIMIT,&cb_instance_sizelimit_get, &cb_instance_sizelimit_set,CB_ALWAYS_SHOW},
  109. {CB_CONFIG_TIMELIMIT,CB_CONFIG_TYPE_INT,CB_DEF_TIMELIMIT,&cb_instance_timelimit_get, &cb_instance_timelimit_set,CB_ALWAYS_SHOW},
  110. {CB_CONFIG_HOPLIMIT,CB_CONFIG_TYPE_INT,CB_DEF_HOPLIMIT,&cb_instance_hoplimit_get, &cb_instance_hoplimit_set,CB_ALWAYS_SHOW},
  111. {CB_CONFIG_MAX_IDLE_TIME,CB_CONFIG_TYPE_INT,CB_DEF_MAX_IDLE_TIME,&cb_instance_max_idle_get, &cb_instance_max_idle_set,CB_ALWAYS_SHOW},
  112. {CB_CONFIG_MAX_TEST_TIME,CB_CONFIG_TYPE_INT,CB_DEF_MAX_TEST_TIME,&cb_instance_max_test_get, &cb_instance_max_test_set,CB_ALWAYS_SHOW},
  113. {NULL, 0, NULL, NULL, NULL, 0}
  114. };
  115. /* Others forward declarations */
  116. int cb_instance_delete_config_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* e2,
  117. int *returncode, char *returntext, void *arg);
  118. int cb_instance_search_config_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
  119. int *returncode, char *returntext, void *arg);
  120. int cb_instance_add_config_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* e2,
  121. int *returncode, char *returntext, void *arg);
  122. static int
  123. cb_instance_config_set(void *arg, char *attr_name, cb_instance_config_info *config_array,
  124. struct berval *bval, char *err_buf, int phase, int apply_mod);
  125. int
  126. cb_dont_allow_that(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
  127. int *returncode, char *returntext, void *arg)
  128. {
  129. *returncode=LDAP_UNWILLING_TO_PERFORM;
  130. return SLAPI_DSE_CALLBACK_ERROR;
  131. }
  132. static char *cb_skeleton_entries[] =
  133. {
  134. "dn:cn=monitor, cn=%s, cn=%s, cn=plugins, cn=config\n"
  135. "objectclass:top\n"
  136. "objectclass:extensibleObject\n"
  137. "cn:monitor\n",
  138. ""
  139. };
  140. /*
  141. ** Initialize a backend instance with a default configuration
  142. */
  143. static void cb_instance_config_set_default(cb_backend_instance *inst)
  144. {
  145. cb_instance_config_info *config;
  146. char err_buf[SLAPI_DSE_RETURNTEXT_SIZE];
  147. for (config = cb_the_instance_config; config->config_name != NULL; config++) {
  148. cb_instance_config_set((void *)inst,
  149. config->config_name, cb_the_instance_config, NULL /* use default */, err_buf,
  150. CB_CONFIG_PHASE_INITIALIZATION, 1 /* apply */);
  151. }
  152. /* Set backend instance flags */
  153. if (inst->inst_be)
  154. slapi_be_set_flag(inst->inst_be,SLAPI_BE_FLAG_REMOTE_DATA);
  155. }
  156. /*
  157. ** Allocate a new chaining backend instance. Internal structure
  158. */
  159. static cb_backend_instance * cb_instance_alloc(cb_backend * cb, char * name, char * basedn) {
  160. int i;
  161. cb_backend_instance * inst =
  162. (cb_backend_instance *)slapi_ch_calloc(1, sizeof(cb_backend_instance));
  163. /* associated_be_is_disabled defaults to 0 - this may be a problem if the associated
  164. be is disabled at instance creation time
  165. */
  166. inst->inst_name = slapi_ch_strdup(name);
  167. inst->monitor.mutex = slapi_new_mutex();
  168. inst->monitor_availability.cpt_lock = slapi_new_mutex();
  169. inst->monitor_availability.lock_timeLimit = slapi_new_mutex();
  170. inst->pool= (cb_conn_pool *) slapi_ch_calloc(1,sizeof(cb_conn_pool));
  171. inst->pool->conn.conn_list_mutex = slapi_new_mutex();
  172. inst->pool->conn.conn_list_cv = slapi_new_condvar(inst->pool->conn.conn_list_mutex);
  173. inst->pool->bindit=1;
  174. inst->bind_pool= (cb_conn_pool *) slapi_ch_calloc(1,sizeof(cb_conn_pool));
  175. inst->bind_pool->conn.conn_list_mutex = slapi_new_mutex();
  176. inst->bind_pool->conn.conn_list_cv = slapi_new_condvar(inst->bind_pool->conn.conn_list_mutex);
  177. inst->backend_type=cb;
  178. /* initialize monitor_availability */
  179. inst->monitor_availability.farmserver_state = FARMSERVER_AVAILABLE ; /* we expect the farm to be available */
  180. inst->monitor_availability.cpt = 0 ; /* set up the failed conn counter to 0 */
  181. /* create RW lock to protect the config */
  182. inst->rwl_config_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, slapi_ch_strdup(name));
  183. /* quick hack */
  184. /* put a ref to the config lock in the pool */
  185. /* so that the connection mgmt module can */
  186. /* access the config safely */
  187. inst->pool->rwl_config_lock = inst->rwl_config_lock;
  188. inst->bind_pool->rwl_config_lock = inst->rwl_config_lock;
  189. for (i=0; i < MAX_CONN_ARRAY; i++) {
  190. inst->pool->connarray[i] = NULL;
  191. inst->bind_pool->connarray[i] = NULL;
  192. }
  193. /* Config is now merged with the backend entry */
  194. inst->configDn=slapi_ch_strdup(basedn);
  195. inst->monitorDn=slapi_ch_smprintf("cn=monitor,%s",basedn);
  196. inst->eq_ctx = NULL;
  197. return inst;
  198. }
  199. void cb_instance_free(cb_backend_instance * inst) {
  200. if (inst) {
  201. PR_RWLock_Wlock(inst->rwl_config_lock);
  202. if ( inst->eq_ctx != NULL )
  203. {
  204. slapi_eq_cancel(inst->eq_ctx);
  205. inst->eq_ctx = NULL;
  206. }
  207. if (inst->bind_pool)
  208. cb_close_conn_pool(inst->bind_pool);
  209. if (inst->pool)
  210. cb_close_conn_pool(inst->pool);
  211. slapi_destroy_condvar(inst->bind_pool->conn.conn_list_cv);
  212. slapi_destroy_condvar(inst->pool->conn.conn_list_cv);
  213. slapi_destroy_mutex(inst->monitor.mutex);
  214. slapi_destroy_mutex(inst->bind_pool->conn.conn_list_mutex);
  215. slapi_destroy_mutex(inst->pool->conn.conn_list_mutex);
  216. slapi_destroy_mutex(inst->monitor_availability.cpt_lock);
  217. slapi_destroy_mutex(inst->monitor_availability.lock_timeLimit);
  218. slapi_ch_free((void **) &inst->configDn);
  219. slapi_ch_free((void **) &inst->monitorDn);
  220. slapi_ch_free((void **) &inst->inst_name);
  221. charray_free(inst->every_attribute);
  222. slapi_ch_free((void **) &inst->bind_pool);
  223. slapi_ch_free((void **) &inst->pool);
  224. PR_RWLock_Unlock(inst->rwl_config_lock);
  225. PR_DestroyRWLock(inst->rwl_config_lock);
  226. slapi_ch_free((void **) &inst);
  227. }
  228. /* XXXSD */
  229. }
  230. /*
  231. ** Check the change the configuration of an existing chaining
  232. ** backend instance.
  233. */
  234. int cb_instance_modify_config_check_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
  235. int *returncode, char *returntext, void *arg) {
  236. cb_backend_instance * inst = (cb_backend_instance *) arg;
  237. LDAPMod **mods;
  238. int rc = LDAP_SUCCESS;
  239. int i;
  240. char * attr_name;
  241. returntext[0] = '\0';
  242. CB_ASSERT(inst!=NULL);
  243. slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
  244. /* First pass to validate input */
  245. for (i = 0; mods[i] && LDAP_SUCCESS == rc; i++) {
  246. attr_name = mods[i]->mod_type;
  247. /* specific processing for multi-valued attributes */
  248. if ( !strcasecmp ( attr_name, CB_CONFIG_SUFFIX )) {
  249. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "suffix modification not allowed\n");
  250. rc = LDAP_UNWILLING_TO_PERFORM;
  251. continue;
  252. } else
  253. if ( !strcasecmp ( attr_name, CB_CONFIG_ILLEGAL_ATTRS )) {
  254. continue;
  255. } else
  256. if ( !strcasecmp ( attr_name, CB_CONFIG_CHAINING_COMPONENTS )) {
  257. continue;
  258. } else
  259. /* CB_CONFIG_BINDUSER & CB_CONFIG_USERPASSWORD may be added */
  260. /* or deleted */
  261. if ( !strcasecmp ( attr_name, CB_CONFIG_USERPASSWORD )) {
  262. continue;
  263. } else
  264. if ( !strcasecmp ( attr_name, CB_CONFIG_BINDUSER )) {
  265. /* Make sure value is not forbidden */
  266. if ((mods[i]->mod_op & LDAP_MOD_REPLACE) ||
  267. ((mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_ADD)) {
  268. rc = cb_instance_config_set((void *) inst, attr_name,
  269. cb_the_instance_config, mods[i]->mod_bvalues[0], returntext,
  270. CB_CONFIG_PHASE_RUNNING, 0);
  271. continue;
  272. }
  273. }
  274. if ((mods[i]->mod_op & LDAP_MOD_DELETE) ||
  275. ((mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_ADD)) {
  276. rc= LDAP_UNWILLING_TO_PERFORM;
  277. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s attributes is not allowed",
  278. (mods[i]->mod_op & LDAP_MOD_DELETE) ? "Deleting" : "Adding");
  279. } else if (mods[i]->mod_op & LDAP_MOD_REPLACE) {
  280. /* This assumes there is only one bval for this mod. */
  281. rc = cb_instance_config_set((void *) inst, attr_name,
  282. cb_the_instance_config, mods[i]->mod_bvalues[0], returntext,
  283. CB_CONFIG_PHASE_RUNNING, 0);
  284. }
  285. }
  286. *returncode= rc;
  287. return ((LDAP_SUCCESS == rc) ? 1:-1);
  288. }
  289. /*
  290. ** Change the configuration of an existing chaining
  291. ** backend instance.
  292. */
  293. int cb_instance_modify_config_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e,
  294. int *returncode, char *returntext, void *arg) {
  295. cb_backend_instance * inst = (cb_backend_instance *) arg;
  296. LDAPMod **mods;
  297. int rc = LDAP_SUCCESS;
  298. int i;
  299. int reopen_conn=0;
  300. char * attr_name;
  301. returntext[0] = '\0';
  302. CB_ASSERT(inst!=NULL);
  303. slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
  304. /* input checked in the preop modify callback */
  305. for (i = 0; mods[i] && LDAP_SUCCESS == rc; i++) {
  306. attr_name = mods[i]->mod_type;
  307. /* specific processing for multi-valued attributes */
  308. if ( !strcasecmp ( attr_name, CB_CONFIG_ILLEGAL_ATTRS )) {
  309. char * config_attr_value;
  310. int done=0;
  311. int j;
  312. PR_RWLock_Wlock(inst->rwl_config_lock);
  313. for (j = 0; mods[i]->mod_bvalues && mods[i]->mod_bvalues[j]; j++) {
  314. config_attr_value = (char *) mods[i]->mod_bvalues[j]->bv_val;
  315. if ( mods[i]->mod_op & LDAP_MOD_REPLACE) {
  316. if (!done) {
  317. charray_free(inst->illegal_attributes);
  318. inst->illegal_attributes=NULL;
  319. done=1;
  320. }
  321. charray_add(&inst->illegal_attributes,
  322. slapi_ch_strdup(config_attr_value));
  323. } else
  324. if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_ADD) {
  325. charray_add(&inst->illegal_attributes,
  326. slapi_ch_strdup(config_attr_value));
  327. } else
  328. if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) {
  329. charray_remove(inst->illegal_attributes,
  330. slapi_ch_strdup(config_attr_value),
  331. 0 /* freeit */);
  332. }
  333. }
  334. if (NULL == mods[i]->mod_bvalues) {
  335. charray_free(inst->illegal_attributes);
  336. inst->illegal_attributes=NULL;
  337. }
  338. PR_RWLock_Unlock(inst->rwl_config_lock);
  339. continue;
  340. }
  341. if ( !strcasecmp ( attr_name, CB_CONFIG_CHAINING_COMPONENTS )) {
  342. char * config_attr_value;
  343. int done=0;
  344. int j;
  345. PR_RWLock_Wlock(inst->rwl_config_lock);
  346. for (j = 0; mods[i]->mod_bvalues && mods[i]->mod_bvalues[j]; j++) {
  347. config_attr_value = (char *) mods[i]->mod_bvalues[j]->bv_val;
  348. if ( mods[i]->mod_op & LDAP_MOD_REPLACE) {
  349. if (!done) {
  350. charray_free(inst->chaining_components);
  351. inst->chaining_components=NULL;
  352. done=1;
  353. }
  354. /* XXXSD assume dns */
  355. charray_add(&inst->chaining_components,
  356. slapi_dn_normalize(slapi_ch_strdup(config_attr_value)));
  357. } else
  358. if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_ADD) {
  359. charray_add(&inst->chaining_components,
  360. slapi_dn_normalize(slapi_ch_strdup(config_attr_value)));
  361. } else
  362. if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) {
  363. charray_remove(inst->chaining_components,
  364. slapi_dn_normalize(slapi_ch_strdup(config_attr_value)),
  365. 0 /* freeit */);
  366. }
  367. }
  368. if (NULL == mods[i]->mod_bvalues) {
  369. charray_free(inst->chaining_components);
  370. inst->chaining_components=NULL;
  371. }
  372. PR_RWLock_Unlock(inst->rwl_config_lock);
  373. continue;
  374. }
  375. if ((mods[i]->mod_op & LDAP_MOD_DELETE) ||
  376. ((mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_ADD)) {
  377. /* Special processing for binddn & password */
  378. /* because they are optional */
  379. if (( !strcasecmp ( attr_name, CB_CONFIG_BINDUSER )) ||
  380. ( !strcasecmp ( attr_name, CB_CONFIG_USERPASSWORD ))) {
  381. if (mods[i]->mod_op & LDAP_MOD_DELETE) {
  382. rc = cb_instance_config_set((void *) inst, attr_name,
  383. cb_the_instance_config, NULL, returntext,
  384. CB_CONFIG_PHASE_RUNNING, 1); }
  385. else {
  386. rc = cb_instance_config_set((void *) inst, attr_name,
  387. cb_the_instance_config, mods[i]->mod_bvalues[0], returntext,
  388. CB_CONFIG_PHASE_RUNNING, 1);
  389. }
  390. if (rc==CB_REOPEN_CONN) {
  391. reopen_conn=1;
  392. rc=LDAP_SUCCESS;
  393. }
  394. continue;
  395. }
  396. rc= LDAP_UNWILLING_TO_PERFORM;
  397. PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s attributes is not allowed",
  398. (mods[i]->mod_op & LDAP_MOD_DELETE) ? "Deleting" : "Adding");
  399. } else if (mods[i]->mod_op & LDAP_MOD_REPLACE) {
  400. /* This assumes there is only one bval for this mod. */
  401. rc = cb_instance_config_set((void *) inst, attr_name,
  402. cb_the_instance_config, mods[i]->mod_bvalues[0], returntext,
  403. CB_CONFIG_PHASE_RUNNING, 1);
  404. /* Update requires to reopen connections */
  405. /* Expensive operation so do it only once */
  406. if (rc==CB_REOPEN_CONN) {
  407. reopen_conn=1;
  408. rc=LDAP_SUCCESS;
  409. }
  410. }
  411. }
  412. *returncode= rc;
  413. if (reopen_conn) {
  414. cb_stale_all_connections(inst);
  415. }
  416. return ((LDAP_SUCCESS == rc) ? SLAPI_DSE_CALLBACK_OK:SLAPI_DSE_CALLBACK_ERROR);
  417. }
  418. /*
  419. ** Parse and instantiate backend instances
  420. */
  421. int
  422. cb_parse_instance_config_entry(cb_backend * cb, Slapi_Entry * e) {
  423. int rc =LDAP_SUCCESS;
  424. Slapi_Attr *attr = NULL;
  425. Slapi_Value *sval;
  426. const struct berval *attrValue;
  427. cb_backend_instance *inst=NULL;
  428. char *instname;
  429. char retmsg[CB_BUFSIZE];
  430. CB_ASSERT(e!=NULL);
  431. /*
  432. ** Retrieve the instance name and make sure it is not
  433. ** already declared.
  434. */
  435. if ( 0 == slapi_entry_attr_find( e, CB_CONFIG_INSTNAME, &attr )) {
  436. slapi_attr_first_value(attr, &sval);
  437. attrValue = slapi_value_get_berval(sval);
  438. instname=attrValue->bv_val;
  439. } else {
  440. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  441. "Malformed backend instance (<%s> missing)>\n", CB_CONFIG_INSTNAME);
  442. return LDAP_LOCAL_ERROR;
  443. }
  444. /* Allocate a new backend internal data structure */
  445. inst = cb_instance_alloc(cb,instname,slapi_entry_get_dn(e));
  446. /* Emulate a add config entry to configure */
  447. /* this backend instance. */
  448. cb_instance_add_config_callback(NULL,e,NULL,&rc,retmsg,inst);
  449. if ( rc != LDAP_SUCCESS ) {
  450. cb_instance_free(inst);
  451. }
  452. return rc;
  453. }
  454. /*
  455. ** Update the instance configuration
  456. */
  457. static int
  458. cb_instance_config_initialize(cb_backend_instance * inst, Slapi_Entry * e , int phase, int apply) {
  459. int rc =LDAP_SUCCESS;
  460. Slapi_Attr *attr = NULL;
  461. Slapi_Value *sval;
  462. struct berval * bval;
  463. int using_def_connlifetime,i;
  464. char err_buf[SLAPI_DSE_RETURNTEXT_SIZE];
  465. int urlfound=0;
  466. char *rootdn;
  467. using_def_connlifetime=1;
  468. for (slapi_entry_first_attr(e, &attr); attr; slapi_entry_next_attr(e, attr, &attr)) {
  469. char * attr_name=NULL;
  470. slapi_attr_get_type(attr, &attr_name);
  471. if ( !strcasecmp ( attr_name, CB_CONFIG_SUFFIX )) {
  472. if (apply && ( inst->inst_be != NULL )) {
  473. Slapi_DN *suffix;
  474. suffix = slapi_sdn_new();
  475. i = slapi_attr_first_value(attr, &sval);
  476. while (i != -1 ) {
  477. bval = (struct berval *) slapi_value_get_berval(sval);
  478. slapi_sdn_init_dn_byref(suffix, bval->bv_val);
  479. if (!slapi_be_issuffix(inst->inst_be, suffix)) {
  480. slapi_be_addsuffix(inst->inst_be, suffix);
  481. }
  482. slapi_sdn_done(suffix);
  483. slapi_sdn_free(&suffix);
  484. i = slapi_attr_next_value(attr, i, &sval);
  485. }
  486. }
  487. continue;
  488. } else
  489. if ( !strcasecmp ( attr_name, CB_CONFIG_CHAINING_COMPONENTS )) {
  490. if (apply) {
  491. PR_RWLock_Wlock(inst->rwl_config_lock);
  492. i = slapi_attr_first_value(attr, &sval);
  493. charray_free(inst->chaining_components);
  494. inst->chaining_components=NULL;
  495. while (i != -1 ) {
  496. bval = (struct berval *) slapi_value_get_berval(sval);
  497. charray_add(&inst->chaining_components,
  498. slapi_dn_normalize(slapi_ch_strdup(bval->bv_val)));
  499. i = slapi_attr_next_value(attr, i, &sval);
  500. }
  501. PR_RWLock_Unlock(inst->rwl_config_lock);
  502. }
  503. continue;
  504. } else
  505. if ( !strcasecmp ( attr_name, CB_CONFIG_ILLEGAL_ATTRS )) {
  506. if (apply) {
  507. PR_RWLock_Wlock(inst->rwl_config_lock);
  508. i = slapi_attr_first_value(attr, &sval);
  509. charray_free(inst->illegal_attributes);
  510. inst->illegal_attributes=NULL;
  511. while (i != -1 ) {
  512. bval = (struct berval *) slapi_value_get_berval(sval);
  513. charray_add(&inst->illegal_attributes,
  514. slapi_ch_strdup(bval->bv_val));
  515. i = slapi_attr_next_value(attr, i, &sval);
  516. }
  517. PR_RWLock_Unlock(inst->rwl_config_lock);
  518. }
  519. continue;
  520. }
  521. if ( !strcasecmp ( attr_name, CB_CONFIG_HOSTURL )) {
  522. urlfound=1;
  523. }
  524. /* We are assuming that each of these attributes are to have
  525. * only one value. If they have more than one value, like
  526. * the nsslapd-suffix attribute, then they need to be
  527. * handled differently. */
  528. slapi_attr_first_value(attr, &sval);
  529. bval = (struct berval *) slapi_value_get_berval(sval);
  530. if (cb_instance_config_set((void *) inst, attr_name,
  531. cb_the_instance_config, bval, err_buf, phase, apply ) != LDAP_SUCCESS) {
  532. slapi_log_error( SLAPI_LOG_FATAL,
  533. CB_PLUGIN_SUBSYSTEM,"Error with config attribute %s : %s\n",
  534. attr_name, err_buf);
  535. rc=LDAP_LOCAL_ERROR;
  536. break;
  537. }
  538. if ( !strcasecmp ( attr_name, CB_CONFIG_CONNLIFETIME )) {
  539. using_def_connlifetime=0;
  540. }
  541. }
  542. /*
  543. ** Check for mandatory attributes
  544. ** Post-Processing
  545. */
  546. if (LDAP_SUCCESS == rc) {
  547. if (!urlfound) {
  548. slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM,
  549. "Malformed backend instance entry. Mandatory attr <%s> missing\n",
  550. CB_CONFIG_HOSTURL);
  551. rc= LDAP_LOCAL_ERROR;
  552. }
  553. if (apply ) {
  554. if ( using_def_connlifetime &&
  555. strchr( inst->pool->hostname, ' ' ) != NULL ) {
  556. cb_instance_config_set((void *)inst, CB_CONFIG_CONNLIFETIME,
  557. cb_the_instance_config, NULL /* use default */, err_buf,
  558. CB_CONFIG_PHASE_INITIALIZATION, 1 );
  559. }
  560. }
  561. }
  562. /*
  563. ** Additional checks
  564. ** It is forbidden to use directory manager as proxy user
  565. ** due to a bug in the acl check
  566. */
  567. rootdn=cb_get_rootdn();
  568. if (inst->impersonate && inst->pool && inst->pool->binddn &&
  569. !strcmp(inst->pool->binddn,rootdn)) { /* UTF8 aware */
  570. slapi_log_error( SLAPI_LOG_FATAL,
  571. CB_PLUGIN_SUBSYSTEM,"Error with config attribute %s (%s: forbidden value)\n",
  572. CB_CONFIG_BINDUSER, rootdn);
  573. rc=LDAP_LOCAL_ERROR;
  574. }
  575. slapi_ch_free((void **)&rootdn);
  576. return rc;
  577. }
  578. /********************************************************
  579. ** Get and set functions for chaining backend instances *
  580. *********************************************************
  581. */
  582. static void *cb_instance_hosturl_get(void *arg)
  583. {
  584. cb_backend_instance * inst=(cb_backend_instance *) arg;
  585. char * data;
  586. PR_RWLock_Rlock(inst->rwl_config_lock);
  587. data = slapi_ch_strdup(inst->pool->url);
  588. PR_RWLock_Unlock(inst->rwl_config_lock);
  589. return data;
  590. }
  591. static int cb_instance_hosturl_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  592. {
  593. cb_backend_instance *inst=(cb_backend_instance *) arg;
  594. char *url = (char *) value;
  595. LDAPURLDesc *ludp=NULL;
  596. int rc=LDAP_SUCCESS;
  597. if (( rc = ldap_url_parse( url, &ludp )) != 0 ) {
  598. PL_strncpyz(errorbuf,cb_urlparse_err2string( rc ), SLAPI_DSE_RETURNTEXT_SIZE);
  599. if (CB_CONFIG_PHASE_INITIALIZATION == phase)
  600. inst->pool->url=slapi_ch_strdup("");
  601. return(LDAP_INVALID_SYNTAX);
  602. }
  603. if (apply) {
  604. PR_RWLock_Wlock(inst->rwl_config_lock);
  605. if (( phase != CB_CONFIG_PHASE_INITIALIZATION ) &&
  606. ( phase != CB_CONFIG_PHASE_STARTUP )) {
  607. /* Dynamic modification */
  608. /* Don't free char * pointer now */
  609. /* STore them in a waste basket */
  610. /* Will be relesase when the backend stops */
  611. if (inst->pool->hostname)
  612. charray_add(&inst->pool->waste_basket,inst->pool->hostname);
  613. if (inst->pool->url)
  614. charray_add(&inst->pool->waste_basket,inst->pool->url);
  615. if (inst->bind_pool->hostname)
  616. charray_add(&inst->bind_pool->waste_basket,inst->bind_pool->hostname);
  617. if (inst->bind_pool->url)
  618. charray_add(&inst->bind_pool->waste_basket,inst->bind_pool->url);
  619. /* Require connection cleanup */
  620. rc=CB_REOPEN_CONN;
  621. }
  622. /* Normal case. Extract useful data from */
  623. /* the url and update the configuration */
  624. if ((ludp->lud_host==NULL) || (strlen(ludp->lud_host)==0)) {
  625. inst->pool->hostname=(char *)slapi_ch_strdup((char *)get_localhost_DNS());
  626. } else {
  627. inst->pool->hostname = slapi_ch_strdup( ludp->lud_host );
  628. }
  629. inst->pool->url = slapi_ch_strdup( url);
  630. inst->pool->secure = (( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 );
  631. if ((ludp->lud_port==0) && inst->pool->secure)
  632. inst->pool->port=CB_LDAP_SECURE_PORT;
  633. else
  634. inst->pool->port = ludp->lud_port;
  635. /* Build a charray of <host>:<port> */
  636. /* hostname is of the form <host>[:port] <host>[:port] */
  637. { char * aBufCopy, * aHostName;
  638. char * iter = NULL;
  639. aBufCopy=slapi_ch_strdup(inst->pool->hostname);
  640. aHostName=ldap_utf8strtok_r(aBufCopy," ", &iter);
  641. charray_free(inst->url_array);
  642. inst->url_array=NULL;
  643. while (aHostName) {
  644. char * aHostPort;
  645. if ( NULL == strstr(aHostName,":")) {
  646. aHostPort = slapi_ch_smprintf("%s://%s:%d/",
  647. inst->pool->secure ? "ldaps" : "ldap",
  648. aHostName,inst->pool->port);
  649. } else {
  650. aHostPort = slapi_ch_smprintf("%s://%s/",
  651. inst->pool->secure ? "ldaps" : "ldap",
  652. aHostName);
  653. }
  654. charray_add(&inst->url_array,aHostPort);
  655. aHostName=ldap_utf8strtok_r(NULL," ", &iter);
  656. }
  657. slapi_ch_free((void **) &aBufCopy);
  658. }
  659. inst->bind_pool->port=inst->pool->port;
  660. inst->bind_pool->secure=inst->pool->secure;
  661. inst->bind_pool->hostname=slapi_ch_strdup(inst->pool->hostname);
  662. PR_RWLock_Unlock(inst->rwl_config_lock);
  663. }
  664. if ( ludp != NULL ) {
  665. ldap_free_urldesc( ludp );
  666. }
  667. return rc;
  668. }
  669. static void *cb_instance_binduser_get(void *arg)
  670. {
  671. cb_backend_instance * inst=(cb_backend_instance *) arg;
  672. char * data;
  673. PR_RWLock_Rlock(inst->rwl_config_lock);
  674. data = slapi_ch_strdup(inst->pool->binddn2); /* not normalized */
  675. PR_RWLock_Unlock(inst->rwl_config_lock);
  676. return data;
  677. }
  678. static int cb_instance_binduser_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  679. {
  680. cb_backend_instance * inst=(cb_backend_instance *) arg;
  681. int rc=LDAP_SUCCESS;
  682. if (apply) {
  683. PR_RWLock_Wlock(inst->rwl_config_lock);
  684. if (( phase != CB_CONFIG_PHASE_INITIALIZATION ) &&
  685. ( phase != CB_CONFIG_PHASE_STARTUP )) {
  686. /* Dynamic modif */
  687. /* Free user later */
  688. charray_add(&inst->pool->waste_basket,inst->pool->binddn);
  689. charray_add(&inst->pool->waste_basket,inst->pool->binddn2);
  690. rc=CB_REOPEN_CONN;
  691. }
  692. inst->pool->binddn=slapi_ch_strdup((char *) value);
  693. inst->pool->binddn2=slapi_ch_strdup((char *) value);
  694. slapi_dn_normalize_case(inst->pool->binddn);
  695. PR_RWLock_Unlock(inst->rwl_config_lock);
  696. } else {
  697. /* Security check */
  698. /* directory manager of the farm server should not be used as */
  699. /* proxing user. This is hard to check, so assume same directory */
  700. /* manager across servers. */
  701. char * rootdn = cb_get_rootdn();
  702. char * theValueCopy = NULL;
  703. if (value) {
  704. theValueCopy=slapi_ch_strdup((char *) value);
  705. slapi_dn_normalize_case(theValueCopy);
  706. }
  707. PR_RWLock_Rlock(inst->rwl_config_lock);
  708. if (inst->impersonate && theValueCopy &&
  709. !strcmp(theValueCopy,rootdn)) { /* UTF8-aware. See cb_get_dn() */
  710. rc=LDAP_UNWILLING_TO_PERFORM;
  711. if (errorbuf) {
  712. PR_snprintf(errorbuf,SLAPI_DSE_RETURNTEXT_SIZE, "value %s not allowed",rootdn);
  713. }
  714. }
  715. PR_RWLock_Unlock(inst->rwl_config_lock);
  716. slapi_ch_free((void **)&theValueCopy);
  717. slapi_ch_free((void **)&rootdn);
  718. }
  719. return rc;
  720. }
  721. static void *cb_instance_userpassword_get(void *arg)
  722. {
  723. cb_backend_instance * inst=(cb_backend_instance *) arg;
  724. char * data;
  725. PR_RWLock_Rlock(inst->rwl_config_lock);
  726. data = slapi_ch_strdup(inst->pool->password);
  727. PR_RWLock_Unlock(inst->rwl_config_lock);
  728. return data;
  729. }
  730. static int cb_instance_userpassword_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  731. {
  732. cb_backend_instance * inst=(cb_backend_instance *) arg;
  733. int rc=LDAP_SUCCESS;
  734. if (apply) {
  735. PR_RWLock_Wlock(inst->rwl_config_lock);
  736. if (( phase != CB_CONFIG_PHASE_INITIALIZATION ) &&
  737. ( phase != CB_CONFIG_PHASE_STARTUP )) {
  738. /* Dynamic modif */
  739. charray_add(&inst->pool->waste_basket,inst->pool->password);
  740. rc=CB_REOPEN_CONN;
  741. }
  742. inst->pool->password=slapi_ch_strdup((char *) value);
  743. PR_RWLock_Unlock(inst->rwl_config_lock);
  744. }
  745. return rc;
  746. }
  747. static void *cb_instance_sizelimit_get(void *arg)
  748. {
  749. cb_backend_instance * inst=(cb_backend_instance *) arg;
  750. uintptr_t data;
  751. PR_RWLock_Rlock(inst->rwl_config_lock);
  752. data = inst->sizelimit;
  753. PR_RWLock_Unlock(inst->rwl_config_lock);
  754. return (void *) data;
  755. }
  756. static int cb_instance_sizelimit_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  757. {
  758. cb_backend_instance * inst=(cb_backend_instance *) arg;
  759. if (apply) {
  760. PR_RWLock_Wlock(inst->rwl_config_lock);
  761. inst->sizelimit=(int) ((uintptr_t)value);
  762. PR_RWLock_Unlock(inst->rwl_config_lock);
  763. if (inst->inst_be)
  764. be_set_sizelimit(inst->inst_be, (int) ((uintptr_t)value));
  765. }
  766. return LDAP_SUCCESS;
  767. }
  768. static void *cb_instance_timelimit_get(void *arg)
  769. {
  770. cb_backend_instance * inst=(cb_backend_instance *) arg;
  771. uintptr_t data;
  772. PR_RWLock_Rlock(inst->rwl_config_lock);
  773. data = inst->timelimit;
  774. PR_RWLock_Unlock(inst->rwl_config_lock);
  775. return (void *) data;
  776. }
  777. static int cb_instance_timelimit_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  778. {
  779. cb_backend_instance * inst=(cb_backend_instance *) arg;
  780. if (apply) {
  781. PR_RWLock_Wlock(inst->rwl_config_lock);
  782. inst->timelimit=(int) ((uintptr_t)value);
  783. PR_RWLock_Unlock(inst->rwl_config_lock);
  784. if (inst->inst_be)
  785. be_set_timelimit(inst->inst_be, (int) ((uintptr_t)value));
  786. }
  787. return LDAP_SUCCESS;
  788. }
  789. static void *cb_instance_max_test_get(void *arg)
  790. {
  791. cb_backend_instance * inst=(cb_backend_instance *) arg;
  792. uintptr_t data;
  793. PR_RWLock_Rlock(inst->rwl_config_lock);
  794. data = inst->max_test_time;
  795. PR_RWLock_Unlock(inst->rwl_config_lock);
  796. return (void *) data;
  797. }
  798. static int cb_instance_max_test_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  799. {
  800. cb_backend_instance * inst=(cb_backend_instance *) arg;
  801. if (apply) {
  802. PR_RWLock_Wlock(inst->rwl_config_lock);
  803. inst->max_test_time=(int) ((uintptr_t)value);
  804. PR_RWLock_Unlock(inst->rwl_config_lock);
  805. }
  806. return LDAP_SUCCESS;
  807. }
  808. static void *cb_instance_max_idle_get(void *arg)
  809. {
  810. cb_backend_instance * inst=(cb_backend_instance *) arg;
  811. uintptr_t data;
  812. PR_RWLock_Rlock(inst->rwl_config_lock);
  813. data = inst->max_idle_time;
  814. PR_RWLock_Unlock(inst->rwl_config_lock);
  815. return (void *) data;
  816. }
  817. static int cb_instance_max_idle_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  818. {
  819. cb_backend_instance * inst=(cb_backend_instance *) arg;
  820. if (apply) {
  821. PR_RWLock_Wlock(inst->rwl_config_lock);
  822. inst->max_idle_time=(int) ((uintptr_t)value);
  823. PR_RWLock_Unlock(inst->rwl_config_lock);
  824. }
  825. return LDAP_SUCCESS;
  826. }
  827. static void *cb_instance_hoplimit_get(void *arg)
  828. {
  829. cb_backend_instance * inst=(cb_backend_instance *) arg;
  830. uintptr_t data;
  831. PR_RWLock_Rlock(inst->rwl_config_lock);
  832. data = inst->hoplimit;
  833. PR_RWLock_Unlock(inst->rwl_config_lock);
  834. return (void *) data;
  835. }
  836. static int cb_instance_hoplimit_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  837. {
  838. cb_backend_instance * inst=(cb_backend_instance *) arg;
  839. if (apply) {
  840. PR_RWLock_Wlock(inst->rwl_config_lock);
  841. inst->hoplimit=(int) ((uintptr_t)value);
  842. PR_RWLock_Unlock(inst->rwl_config_lock);
  843. }
  844. return LDAP_SUCCESS;
  845. }
  846. static void *cb_instance_maxbconn_get(void *arg)
  847. {
  848. cb_backend_instance * inst=(cb_backend_instance *) arg;
  849. uintptr_t data;
  850. PR_RWLock_Rlock(inst->rwl_config_lock);
  851. data = inst->bind_pool->conn.maxconnections;
  852. PR_RWLock_Unlock(inst->rwl_config_lock);
  853. return (void *) data;
  854. }
  855. static int cb_instance_maxbconn_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  856. {
  857. cb_backend_instance * inst=(cb_backend_instance *) arg;
  858. if (apply) {
  859. PR_RWLock_Wlock(inst->rwl_config_lock);
  860. inst->bind_pool->conn.maxconnections=(int) ((uintptr_t)value);
  861. PR_RWLock_Unlock(inst->rwl_config_lock);
  862. }
  863. return LDAP_SUCCESS;
  864. }
  865. static void *cb_instance_maxconn_get(void *arg)
  866. {
  867. cb_backend_instance * inst=(cb_backend_instance *) arg;
  868. uintptr_t data;
  869. PR_RWLock_Rlock(inst->rwl_config_lock);
  870. data = inst->pool->conn.maxconnections;
  871. PR_RWLock_Unlock(inst->rwl_config_lock);
  872. return (void *) data;
  873. }
  874. static int cb_instance_maxconn_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  875. {
  876. cb_backend_instance * inst=(cb_backend_instance *) arg;
  877. if (apply) {
  878. PR_RWLock_Wlock(inst->rwl_config_lock);
  879. inst->pool->conn.maxconnections=(int) ((uintptr_t)value);
  880. PR_RWLock_Unlock(inst->rwl_config_lock);
  881. }
  882. return LDAP_SUCCESS;
  883. }
  884. static void *cb_instance_abandonto_get(void *arg)
  885. {
  886. cb_backend_instance * inst=(cb_backend_instance *) arg;
  887. uintptr_t data;
  888. PR_RWLock_Rlock(inst->rwl_config_lock);
  889. data = inst->abandon_timeout.tv_sec;
  890. PR_RWLock_Unlock(inst->rwl_config_lock);
  891. return (void *) data;
  892. }
  893. static int cb_instance_abandonto_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  894. {
  895. cb_backend_instance * inst=(cb_backend_instance *) arg;
  896. if (apply) {
  897. if (( phase != CB_CONFIG_PHASE_INITIALIZATION ) &&
  898. ( phase != CB_CONFIG_PHASE_STARTUP )) {
  899. /* Dynamic modif not supported */
  900. /* Stored in ldif only */
  901. return LDAP_SUCCESS;
  902. }
  903. PR_RWLock_Wlock(inst->rwl_config_lock);
  904. inst->abandon_timeout.tv_sec=(int) ((uintptr_t)value);
  905. inst->abandon_timeout.tv_usec=0;
  906. PR_RWLock_Unlock(inst->rwl_config_lock);
  907. }
  908. return LDAP_SUCCESS;
  909. }
  910. static void *cb_instance_maxbconc_get(void *arg)
  911. {
  912. cb_backend_instance * inst=(cb_backend_instance *) arg;
  913. uintptr_t data;
  914. PR_RWLock_Rlock(inst->rwl_config_lock);
  915. data = inst->bind_pool->conn.maxconcurrency;
  916. PR_RWLock_Unlock(inst->rwl_config_lock);
  917. return (void *) data;
  918. }
  919. static int cb_instance_maxbconc_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  920. {
  921. cb_backend_instance * inst=(cb_backend_instance *) arg;
  922. if (apply) {
  923. PR_RWLock_Wlock(inst->rwl_config_lock);
  924. inst->bind_pool->conn.maxconcurrency=(int) ((uintptr_t)value);
  925. PR_RWLock_Unlock(inst->rwl_config_lock);
  926. }
  927. return LDAP_SUCCESS;
  928. }
  929. static void *cb_instance_maxconc_get(void *arg)
  930. {
  931. cb_backend_instance * inst=(cb_backend_instance *) arg;
  932. uintptr_t data;
  933. PR_RWLock_Rlock(inst->rwl_config_lock);
  934. data = inst->pool->conn.maxconcurrency;
  935. PR_RWLock_Unlock(inst->rwl_config_lock);
  936. return (void *) data;
  937. }
  938. static int cb_instance_maxconc_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  939. {
  940. cb_backend_instance * inst=(cb_backend_instance *) arg;
  941. if (apply) {
  942. PR_RWLock_Wlock(inst->rwl_config_lock);
  943. inst->pool->conn.maxconcurrency=(int) ((uintptr_t)value);
  944. PR_RWLock_Unlock(inst->rwl_config_lock);
  945. }
  946. return LDAP_SUCCESS;
  947. }
  948. static void *cb_instance_imperson_get(void *arg)
  949. {
  950. cb_backend_instance * inst=(cb_backend_instance *) arg;
  951. uintptr_t data;
  952. PR_RWLock_Rlock(inst->rwl_config_lock);
  953. data = inst->impersonate;
  954. PR_RWLock_Unlock(inst->rwl_config_lock);
  955. return (void *) data;
  956. }
  957. static int cb_instance_imperson_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  958. {
  959. cb_backend_instance * inst=(cb_backend_instance *) arg;
  960. int rc=LDAP_SUCCESS;
  961. if (apply) {
  962. PR_RWLock_Wlock(inst->rwl_config_lock);
  963. inst->impersonate=(int) ((uintptr_t)value);
  964. PR_RWLock_Unlock(inst->rwl_config_lock);
  965. } else {
  966. /* Security check: Make sure the proxing user is */
  967. /* not the directory manager. */
  968. char * rootdn=cb_get_rootdn();
  969. PR_RWLock_Rlock(inst->rwl_config_lock);
  970. if (((int) ((uintptr_t)value)) && inst->pool && inst->pool->binddn &&
  971. !strcmp(inst->pool->binddn,rootdn)) { /* UTF-8 aware */
  972. rc=LDAP_UNWILLING_TO_PERFORM;
  973. if (errorbuf)
  974. PR_snprintf(errorbuf,SLAPI_DSE_RETURNTEXT_SIZE, "Proxy mode incompatible with %s value (%s not allowed)",
  975. CB_CONFIG_BINDUSER,rootdn);
  976. }
  977. PR_RWLock_Unlock(inst->rwl_config_lock);
  978. slapi_ch_free((void **)&rootdn);
  979. }
  980. return rc;
  981. }
  982. static void *cb_instance_connlife_get(void *arg)
  983. {
  984. cb_backend_instance * inst=(cb_backend_instance *) arg;
  985. uintptr_t data;
  986. PR_RWLock_Rlock(inst->rwl_config_lock);
  987. data=inst->pool->conn.connlifetime;
  988. PR_RWLock_Unlock(inst->rwl_config_lock);
  989. return (void *) data;
  990. }
  991. static int cb_instance_connlife_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  992. {
  993. cb_backend_instance * inst=(cb_backend_instance *) arg;
  994. if (apply) {
  995. PR_RWLock_Wlock(inst->rwl_config_lock);
  996. inst->pool->conn.connlifetime=(int) ((uintptr_t)value);
  997. PR_RWLock_Unlock(inst->rwl_config_lock);
  998. }
  999. return LDAP_SUCCESS;
  1000. }
  1001. static void *cb_instance_bindto_get(void *arg)
  1002. {
  1003. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1004. uintptr_t data;
  1005. PR_RWLock_Rlock(inst->rwl_config_lock);
  1006. data=inst->bind_pool->conn.op_timeout.tv_sec;
  1007. PR_RWLock_Unlock(inst->rwl_config_lock);
  1008. return (void *) data;
  1009. }
  1010. static int cb_instance_bindto_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  1011. {
  1012. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1013. if (apply) {
  1014. PR_RWLock_Wlock(inst->rwl_config_lock);
  1015. inst->bind_pool->conn.op_timeout.tv_sec=(int) ((uintptr_t)value);
  1016. inst->bind_pool->conn.op_timeout.tv_usec=0;
  1017. inst->bind_pool->conn.bind_timeout.tv_sec=(int) ((uintptr_t)value);
  1018. inst->bind_pool->conn.bind_timeout.tv_usec=0;
  1019. /* Used to bind to the farm server */
  1020. inst->pool->conn.bind_timeout.tv_sec=(int) ((uintptr_t)value);
  1021. inst->pool->conn.bind_timeout.tv_usec=0;
  1022. PR_RWLock_Unlock(inst->rwl_config_lock);
  1023. }
  1024. return LDAP_SUCCESS;
  1025. }
  1026. static void *cb_instance_opto_get(void *arg)
  1027. {
  1028. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1029. uintptr_t data;
  1030. PR_RWLock_Rlock(inst->rwl_config_lock);
  1031. data=inst->pool->conn.op_timeout.tv_sec;
  1032. PR_RWLock_Unlock(inst->rwl_config_lock);
  1033. return (void *) data;
  1034. }
  1035. static int cb_instance_opto_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  1036. {
  1037. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1038. if (apply) {
  1039. PR_RWLock_Wlock(inst->rwl_config_lock);
  1040. inst->pool->conn.op_timeout.tv_sec=(int) ((uintptr_t)value);
  1041. inst->pool->conn.op_timeout.tv_usec=0;
  1042. PR_RWLock_Unlock(inst->rwl_config_lock);
  1043. }
  1044. return LDAP_SUCCESS;
  1045. }
  1046. static void *cb_instance_ref_get(void *arg)
  1047. {
  1048. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1049. uintptr_t data;
  1050. PR_RWLock_Rlock(inst->rwl_config_lock);
  1051. data=inst->searchreferral;
  1052. PR_RWLock_Unlock(inst->rwl_config_lock);
  1053. return (void *) data;
  1054. }
  1055. static int cb_instance_ref_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  1056. {
  1057. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1058. if (apply) {
  1059. PR_RWLock_Wlock(inst->rwl_config_lock);
  1060. inst->searchreferral=(int) ((uintptr_t)value);
  1061. PR_RWLock_Unlock(inst->rwl_config_lock);
  1062. }
  1063. return LDAP_SUCCESS;
  1064. }
  1065. static void *cb_instance_acl_get(void *arg)
  1066. {
  1067. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1068. uintptr_t data;
  1069. PR_RWLock_Rlock(inst->rwl_config_lock);
  1070. data=inst->local_acl;
  1071. PR_RWLock_Unlock(inst->rwl_config_lock);
  1072. return (void *) data;
  1073. }
  1074. static int cb_instance_acl_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  1075. {
  1076. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1077. if (apply) {
  1078. if (( phase != CB_CONFIG_PHASE_INITIALIZATION ) &&
  1079. ( phase != CB_CONFIG_PHASE_STARTUP )) {
  1080. /* Dynamic modif not supported */
  1081. /* Stored in ldif only */
  1082. return LDAP_SUCCESS;
  1083. }
  1084. PR_RWLock_Wlock(inst->rwl_config_lock);
  1085. inst->local_acl=(int) ((uintptr_t)value);
  1086. PR_RWLock_Unlock(inst->rwl_config_lock);
  1087. }
  1088. return LDAP_SUCCESS;
  1089. }
  1090. static void *cb_instance_bindretry_get(void *arg)
  1091. {
  1092. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1093. uintptr_t data;
  1094. PR_RWLock_Rlock(inst->rwl_config_lock);
  1095. data=inst->bind_retry;
  1096. PR_RWLock_Unlock(inst->rwl_config_lock);
  1097. return (void *) data;
  1098. }
  1099. static int cb_instance_bindretry_set(void *arg, void *value, char *errorbuf, int phase, int apply)
  1100. {
  1101. cb_backend_instance * inst=(cb_backend_instance *) arg;
  1102. if (apply) {
  1103. PR_RWLock_Wlock(inst->rwl_config_lock);
  1104. inst->bind_retry=(int) ((uintptr_t)value);
  1105. PR_RWLock_Unlock(inst->rwl_config_lock);
  1106. }
  1107. return LDAP_SUCCESS;
  1108. }
  1109. /* Finds an entry in a config_info array with the given name. Returns
  1110. * the entry on success and NULL when not found.
  1111. */
  1112. static cb_instance_config_info *cb_get_config_info(cb_instance_config_info *config_array, char *attr_name)
  1113. {
  1114. int x;
  1115. for(x = 0; config_array[x].config_name != NULL; x++) {
  1116. if (!strcasecmp(config_array[x].config_name, attr_name)) {
  1117. return &(config_array[x]);
  1118. }
  1119. }
  1120. return NULL;
  1121. }
  1122. /*
  1123. ** Update an attribute value
  1124. ** For now, unknown attributes are ignored
  1125. ** Return a LDAP error code OR CB_REOPEN_CONN when the
  1126. ** update requires to close open connections.
  1127. ** err_buf is size SLAPI_DSE_RETURNTEXT_SIZE
  1128. */
  1129. static int
  1130. cb_instance_config_set(void *arg, char *attr_name, cb_instance_config_info *config_array,
  1131. struct berval *bval, char *err_buf, int phase, int apply_mod)
  1132. {
  1133. cb_instance_config_info *config;
  1134. int use_default;
  1135. int int_val;
  1136. long long_val;
  1137. int retval=LDAP_LOCAL_ERROR;
  1138. config = cb_get_config_info(config_array, attr_name);
  1139. if (NULL == config) {
  1140. /* Ignore unknown attributes */
  1141. return LDAP_SUCCESS;
  1142. }
  1143. /* If the config phase is initialization or if bval is NULL, we will use
  1144. * the default value for the attribute. */
  1145. if (CB_CONFIG_PHASE_INITIALIZATION == phase || NULL == bval) {
  1146. use_default = 1;
  1147. } else {
  1148. use_default = 0;
  1149. /* Since we are setting the value for the config attribute, we
  1150. * need to turn on the CB_PREVIOUSLY_SET flag to make
  1151. * sure this attribute is shown. */
  1152. config->config_flags |= CB_PREVIOUSLY_SET;
  1153. }
  1154. switch(config->config_type) {
  1155. case CB_CONFIG_TYPE_INT:
  1156. if (use_default) {
  1157. int_val = cb_atoi(config->config_default_value);
  1158. } else {
  1159. int_val = cb_atoi((char *)bval->bv_val);
  1160. }
  1161. retval = config->config_set_fn(arg, (void *) ((uintptr_t)int_val), err_buf, phase, apply_mod);
  1162. break;
  1163. case CB_CONFIG_TYPE_INT_OCTAL:
  1164. if (use_default) {
  1165. int_val = (int) strtol(config->config_default_value, NULL, 8);
  1166. } else {
  1167. int_val = (int) strtol((char *)bval->bv_val, NULL, 8);
  1168. }
  1169. retval = config->config_set_fn(arg, (void *) ((uintptr_t)int_val), err_buf, phase, apply_mod);
  1170. break;
  1171. case CB_CONFIG_TYPE_LONG:
  1172. if (use_default) {
  1173. long_val = cb_atol(config->config_default_value);
  1174. } else {
  1175. long_val = cb_atol((char *)bval->bv_val);
  1176. }
  1177. retval = config->config_set_fn(arg, (void *) long_val, err_buf, phase, apply_mod);
  1178. break;
  1179. case CB_CONFIG_TYPE_STRING:
  1180. if (use_default) {
  1181. retval = config->config_set_fn(arg, config->config_default_value, err_buf, phase, apply_mod);
  1182. } else {
  1183. retval = config->config_set_fn(arg, bval->bv_val, err_buf, phase, apply_mod);
  1184. }
  1185. break;
  1186. case CB_CONFIG_TYPE_ONOFF:
  1187. if (use_default) {
  1188. int_val = !strcasecmp(config->config_default_value, "on");
  1189. } else {
  1190. int_val = !strcasecmp((char *) bval->bv_val, "on");
  1191. }
  1192. retval = config->config_set_fn(arg, (void *) ((uintptr_t)int_val), err_buf, phase, apply_mod);
  1193. break;
  1194. }
  1195. return retval;
  1196. }
  1197. /* Utility function used in creating config entries. Using the
  1198. * config_info, this function gets info and formats in the correct
  1199. * way.
  1200. * buf is CB_BUFSIZE size
  1201. */
  1202. void cb_instance_config_get(void *arg, cb_instance_config_info *config, char *buf)
  1203. {
  1204. char *tmp_string;
  1205. if (config == NULL) {
  1206. buf[0] = '\0';
  1207. }
  1208. switch(config->config_type) {
  1209. case CB_CONFIG_TYPE_INT:
  1210. sprintf(buf, "%d", (int) ((uintptr_t)config->config_get_fn(arg)));
  1211. break;
  1212. case CB_CONFIG_TYPE_INT_OCTAL:
  1213. sprintf(buf, "%o", (int) ((uintptr_t)config->config_get_fn(arg)));
  1214. break;
  1215. case CB_CONFIG_TYPE_LONG:
  1216. sprintf(buf, "%ld", (long) config->config_get_fn(arg));
  1217. break;
  1218. case CB_CONFIG_TYPE_STRING:
  1219. /* Remember the get function for strings returns memory
  1220. * that must be freed. */
  1221. tmp_string = (char *) config->config_get_fn(arg);
  1222. PR_snprintf(buf, CB_BUFSIZE, "%s", (char *) tmp_string);
  1223. slapi_ch_free((void **)&tmp_string);
  1224. break;
  1225. case CB_CONFIG_TYPE_ONOFF:
  1226. if ((int) ((uintptr_t)config->config_get_fn(arg))) {
  1227. sprintf(buf,"%s","on");
  1228. } else {
  1229. sprintf(buf,"%s","off");
  1230. }
  1231. break;
  1232. default:
  1233. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  1234. "Invalid attribute syntax.\n");
  1235. }
  1236. }
  1237. /*
  1238. ** Search for instance config entry
  1239. ** Always return 'active' values because some configuration changes
  1240. ** won't be taken into account until the server restarts
  1241. */
  1242. int cb_instance_search_config_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter,
  1243. int *returncode, char *returntext, void *arg) {
  1244. char buf[CB_BUFSIZE];
  1245. struct berval val;
  1246. struct berval *vals[2];
  1247. int i = 0;
  1248. cb_backend_instance *inst = (cb_backend_instance *)arg;
  1249. cb_instance_config_info * config;
  1250. vals[0] = &val;
  1251. vals[1] = NULL;
  1252. /* suffixes */
  1253. PR_RWLock_Rlock(inst->rwl_config_lock);
  1254. {
  1255. const Slapi_DN *aSuffix;
  1256. i=0;
  1257. if (inst->inst_be) {
  1258. while ((aSuffix=slapi_be_getsuffix(inst->inst_be,i))) {
  1259. val.bv_val = (char *)slapi_sdn_get_dn(aSuffix);
  1260. val.bv_len = strlen( val.bv_val );
  1261. if (val.bv_len) {
  1262. if (i==0)
  1263. slapi_entry_attr_replace(e,CB_CONFIG_SUFFIX,(struct berval **)vals );
  1264. else
  1265. slapi_entry_attr_merge(e,CB_CONFIG_SUFFIX,(struct berval **)vals );
  1266. }
  1267. i++;
  1268. }
  1269. }
  1270. }
  1271. for (i=0; inst->chaining_components && inst->chaining_components[i]; i++) {
  1272. val.bv_val = inst->chaining_components[i];
  1273. val.bv_len = strlen( val.bv_val );
  1274. if (val.bv_len) {
  1275. if (i==0)
  1276. slapi_entry_attr_replace(e,CB_CONFIG_CHAINING_COMPONENTS,(struct berval **)vals );
  1277. else
  1278. slapi_entry_attr_merge(e,CB_CONFIG_CHAINING_COMPONENTS,(struct berval **)vals );
  1279. }
  1280. }
  1281. for (i=0; inst->illegal_attributes && inst->illegal_attributes[i]; i++) {
  1282. val.bv_val = inst->illegal_attributes[i];
  1283. val.bv_len = strlen( val.bv_val );
  1284. if (val.bv_len) {
  1285. if (i==0)
  1286. slapi_entry_attr_replace(e,CB_CONFIG_ILLEGAL_ATTRS,(struct berval **)vals );
  1287. else
  1288. slapi_entry_attr_merge(e,CB_CONFIG_ILLEGAL_ATTRS,(struct berval **)vals );
  1289. }
  1290. }
  1291. PR_RWLock_Unlock(inst->rwl_config_lock);
  1292. /* standard attributes */
  1293. for(config = cb_the_instance_config; config->config_name != NULL; config++) {
  1294. if (!(config->config_flags & (CB_ALWAYS_SHOW | CB_PREVIOUSLY_SET))) {
  1295. /* This config option shouldn't be shown */
  1296. continue;
  1297. }
  1298. cb_instance_config_get((void *) inst, config, buf);
  1299. val.bv_val = buf;
  1300. val.bv_len = strlen(buf);
  1301. if (val.bv_len)
  1302. slapi_entry_attr_replace(e, config->config_name, vals);
  1303. }
  1304. *returncode = LDAP_SUCCESS;
  1305. return SLAPI_DSE_CALLBACK_OK;
  1306. }
  1307. /*
  1308. ** Ooops!!! The backend instance is beeing deleted
  1309. */
  1310. int cb_instance_delete_config_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* e2,
  1311. int *returncode, char *returntext, void *arg) {
  1312. cb_backend_instance * inst = (cb_backend_instance *) arg;
  1313. int rc;
  1314. Slapi_Entry * anEntry=NULL;
  1315. Slapi_DN * aDn;
  1316. CB_ASSERT( inst!=NULL );
  1317. /* notify the front-end */
  1318. slapi_mtn_be_stopping(inst->inst_be);
  1319. /* Now it is safe to stop */
  1320. /* No pending op */
  1321. /* unregister callbacks */
  1322. slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, inst->configDn,
  1323. LDAP_SCOPE_BASE, "(objectclass=*)", cb_instance_search_config_callback);
  1324. slapi_config_remove_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_POSTOP, inst->configDn,
  1325. LDAP_SCOPE_BASE, "(objectclass=*)", cb_instance_delete_config_callback);
  1326. slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, inst->configDn,
  1327. LDAP_SCOPE_BASE, "(objectclass=*)", cb_instance_modify_config_check_callback);
  1328. slapi_config_remove_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_POSTOP, inst->configDn,
  1329. LDAP_SCOPE_BASE, "(objectclass=*)", cb_instance_modify_config_callback);
  1330. /* At this point, the monitor entry should have been removed */
  1331. /* If not, manually call delete callback */
  1332. aDn = slapi_sdn_new_dn_byref(inst->monitorDn);
  1333. if ( LDAP_SUCCESS==(slapi_search_internal_get_entry(aDn,NULL, &anEntry,inst->backend_type->identity))) {
  1334. cb_delete_monitor_callback( NULL, anEntry, NULL, &rc , NULL, inst );
  1335. if (anEntry)
  1336. slapi_entry_free(anEntry);
  1337. }
  1338. slapi_sdn_done(aDn);
  1339. slapi_sdn_free(&aDn);
  1340. /* free resources */
  1341. cb_close_conn_pool(inst->bind_pool);
  1342. cb_close_conn_pool(inst->pool);
  1343. slapi_be_free(&(inst->inst_be));
  1344. cb_instance_free(inst);
  1345. return SLAPI_DSE_CALLBACK_OK;
  1346. }
  1347. static void cb_instance_add_monitor_later(time_t when, void *arg) {
  1348. cb_backend_instance * inst = (cb_backend_instance *) arg;
  1349. if ( inst != NULL )
  1350. {
  1351. PR_RWLock_Rlock(inst->rwl_config_lock);
  1352. /* create the monitor entry if it is not there yet */
  1353. if (LDAP_SUCCESS == cb_config_add_dse_entries(inst->backend_type, cb_skeleton_entries,
  1354. inst->inst_name,CB_PLUGIN_NAME, NULL))
  1355. {
  1356. /* add monitor callbacks */
  1357. slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, inst->monitorDn, LDAP_SCOPE_BASE,
  1358. "(objectclass=*)", cb_search_monitor_callback, (void *) inst);
  1359. slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, inst->monitorDn, LDAP_SCOPE_BASE,
  1360. "(objectclass=*)", cb_dont_allow_that, (void *) NULL);
  1361. slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP , inst->monitorDn, LDAP_SCOPE_BASE,
  1362. "(objectclass=*)", cb_delete_monitor_callback, (void *) inst);
  1363. }
  1364. PR_RWLock_Unlock(inst->rwl_config_lock);
  1365. }
  1366. }
  1367. int cb_instance_add_config_check_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* e2,
  1368. int *returncode, char *returntext, void *arg) {
  1369. int rc=LDAP_SUCCESS;
  1370. cb_backend_instance *inst;
  1371. cb_backend *cb=(cb_backend *) arg;
  1372. Slapi_Attr *attr = NULL;
  1373. Slapi_Value *sval;
  1374. const struct berval *attrValue;
  1375. char *instname=NULL;
  1376. if (returntext)
  1377. returntext[0]='\0';
  1378. /* Basic entry check */
  1379. if ( 0 == slapi_entry_attr_find( e, CB_CONFIG_INSTNAME, &attr )) {
  1380. slapi_attr_first_value(attr, &sval);
  1381. attrValue = slapi_value_get_berval(sval);
  1382. instname=attrValue->bv_val;
  1383. }
  1384. if ( instname == NULL ) {
  1385. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  1386. "Malformed backend instance (<%s> missing)>\n", CB_CONFIG_INSTNAME);
  1387. *returncode = LDAP_LOCAL_ERROR;
  1388. return SLAPI_DSE_CALLBACK_ERROR;
  1389. }
  1390. /* Allocate a new backend internal data structure */
  1391. inst = cb_instance_alloc(cb,instname,slapi_entry_get_dn(e));
  1392. /* build the backend instance from the default hardcoded conf, */
  1393. /* the default instance config and the specific entry specified */
  1394. if ((rc=cb_build_backend_instance_config(inst,e,0))
  1395. != LDAP_SUCCESS) {
  1396. slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM,
  1397. "Can't instantiate chaining backend instance %s.\n",inst->inst_name);
  1398. *returncode=rc;
  1399. cb_instance_free(inst);
  1400. return SLAPI_DSE_CALLBACK_ERROR;
  1401. }
  1402. /* Free the dummy instance */
  1403. *returncode=rc;
  1404. cb_instance_free(inst);
  1405. return SLAPI_DSE_CALLBACK_OK;
  1406. }
  1407. /* Create the default instance config from hard-coded values */
  1408. /*
  1409. ** Initialize the backend instance with the config entry
  1410. ** passed in arguments.
  1411. ** <arg> : (cb_backend *)
  1412. */
  1413. int cb_instance_add_config_callback(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* e2,
  1414. int *returncode, char *returntext, void *arg) {
  1415. int rc=LDAP_SUCCESS;
  1416. cb_backend_instance *inst;
  1417. cb_backend *cb=(cb_backend *) arg;
  1418. Slapi_Attr *attr = NULL;
  1419. Slapi_Value *sval;
  1420. const struct berval *attrValue;
  1421. char *instname=NULL;
  1422. if (returntext)
  1423. returntext[0]='\0';
  1424. /* Basic entry check */
  1425. if ( 0 == slapi_entry_attr_find( e, CB_CONFIG_INSTNAME, &attr )) {
  1426. slapi_attr_first_value(attr, &sval);
  1427. attrValue = slapi_value_get_berval(sval);
  1428. instname=attrValue->bv_val;
  1429. }
  1430. if ( instname == NULL ) {
  1431. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  1432. "Malformed backend instance (<%s> missing)>\n", CB_CONFIG_INSTNAME);
  1433. *returncode = LDAP_LOCAL_ERROR;
  1434. return SLAPI_DSE_CALLBACK_ERROR;
  1435. }
  1436. /* Allocate a new backend internal data structure */
  1437. inst = cb_instance_alloc(cb,instname,slapi_entry_get_dn(e));
  1438. /* build the backend instance from the default hardcoded conf, */
  1439. /* the default instance config and the specific entry specified */
  1440. if ((rc=cb_build_backend_instance_config(inst,e,0))
  1441. != LDAP_SUCCESS) {
  1442. slapi_log_error( SLAPI_LOG_FATAL, CB_PLUGIN_SUBSYSTEM,
  1443. "Can't instantiate chaining backend instance %s.\n",inst->inst_name);
  1444. *returncode=rc;
  1445. cb_instance_free(inst);
  1446. return SLAPI_DSE_CALLBACK_ERROR;
  1447. }
  1448. /* Instantiate a Slapi_Backend if necessary */
  1449. if (!inst->isconfigured) {
  1450. Slapi_PBlock *aPb=NULL;
  1451. inst->inst_be = slapi_be_new(CB_CHAINING_BACKEND_TYPE,slapi_ch_strdup(inst->inst_name),0,0);
  1452. aPb=slapi_pblock_new();
  1453. slapi_pblock_set(aPb, SLAPI_PLUGIN, inst->backend_type->plugin);
  1454. slapi_be_setentrypoint(inst->inst_be,0,(void *)NULL,aPb);
  1455. slapi_be_set_instance_info(inst->inst_be,inst);
  1456. slapi_pblock_set(aPb, SLAPI_PLUGIN, NULL);
  1457. slapi_pblock_destroy(aPb);
  1458. }
  1459. cb_build_backend_instance_config(inst,e,1);
  1460. /* kexcoff: the order of the following calls is very important to prevent the deletion of the
  1461. instance to happen before the creation of the monitor part of the config.
  1462. However, not sure it solves all the situations, but at least it is worth to maintain
  1463. this order. */
  1464. if (!inst->isconfigured)
  1465. {
  1466. /* Add monitor entry and callback on it
  1467. * called from an add...
  1468. * we can't call recursively into the DSE to do more adds, they'll
  1469. * silently fail. instead, schedule the adds to happen in 1 second.
  1470. */
  1471. inst->eq_ctx = slapi_eq_once(cb_instance_add_monitor_later, (void *)inst, time(NULL)+1);
  1472. }
  1473. /* Get the list of operational attrs defined in the schema */
  1474. /* see cb_search file for a reason for that */
  1475. inst->every_attribute=slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_OPATTR);
  1476. charray_add(&inst->every_attribute,slapi_ch_strdup(LDAP_ALL_USER_ATTRS));
  1477. if (!inst->isconfigured)
  1478. {
  1479. slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, inst->configDn,
  1480. LDAP_SCOPE_BASE,"(objectclass=*)",cb_instance_modify_config_check_callback, (void *) inst);
  1481. slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_POSTOP, inst->configDn,
  1482. LDAP_SCOPE_BASE,"(objectclass=*)",cb_instance_modify_config_callback, (void *) inst);
  1483. slapi_config_register_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, inst->configDn,
  1484. LDAP_SCOPE_BASE,"(objectclass=*)", cb_instance_search_config_callback, (void *) inst);
  1485. /* allow deletion otherwise impossible to remote a backend instance */
  1486. /* dynamically... */
  1487. slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_POSTOP, inst->configDn,
  1488. LDAP_SCOPE_BASE,"(objectclass=*)", cb_instance_delete_config_callback, (void *) inst);
  1489. }
  1490. /* Notify the front-end */
  1491. /* After the call below, we can receive ops */
  1492. slapi_mtn_be_started(inst->inst_be);
  1493. inst->isconfigured=1;
  1494. return SLAPI_DSE_CALLBACK_OK;
  1495. }
  1496. /* Create the default instance config from hard-coded values */
  1497. int cb_create_default_backend_instance_config(cb_backend * cb) {
  1498. int rc;
  1499. cb_backend_instance *dummy;
  1500. Slapi_Entry *e=slapi_entry_alloc();
  1501. char *defaultDn;
  1502. char *olddn;
  1503. struct berval val;
  1504. struct berval *vals[2];
  1505. Slapi_PBlock *pb;
  1506. dummy = cb_instance_alloc(cb, "dummy", "o=dummy");
  1507. cb_instance_config_set_default(dummy);
  1508. cb_instance_search_config_callback(NULL,e,NULL, &rc, NULL,(void *) dummy);
  1509. /* set right dn and objectclass */
  1510. defaultDn = PR_smprintf("cn=default instance config,%s",cb->pluginDN);
  1511. olddn = slapi_entry_get_dn(e);
  1512. slapi_ch_free((void **) &olddn);
  1513. slapi_entry_set_dn(e,slapi_ch_strdup(defaultDn));
  1514. vals[0] = &val;
  1515. vals[1] = NULL;
  1516. val.bv_val = "top";
  1517. val.bv_len = strlen( val.bv_val );
  1518. slapi_entry_attr_replace( e, "objectclass", (struct berval **)vals );
  1519. val.bv_val = CB_CONFIG_EXTENSIBLEOCL;
  1520. val.bv_len = strlen( val.bv_val );
  1521. slapi_entry_attr_merge( e, "objectclass", (struct berval **)vals );
  1522. val.bv_val = "default instance config";
  1523. val.bv_len = strlen( val.bv_val );
  1524. slapi_entry_attr_replace( e, "cn", (struct berval **)vals );
  1525. /* create entry */
  1526. pb = slapi_pblock_new();
  1527. slapi_add_entry_internal_set_pb(pb, e, NULL, cb->identity, 0);
  1528. slapi_add_internal_pb(pb);
  1529. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  1530. if ( LDAP_SUCCESS != rc ) {
  1531. slapi_log_error(SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  1532. "Add %s failed (%s)\n",defaultDn,ldap_err2string(rc));
  1533. }
  1534. slapi_pblock_destroy(pb);
  1535. /* cleanup */
  1536. cb_instance_free(dummy);
  1537. /* BEWARE: entry is consummed */
  1538. PR_smprintf_free(defaultDn);
  1539. return rc;
  1540. }
  1541. /* Extract backend instance configuration from the LDAP entry */
  1542. int cb_build_backend_instance_config(cb_backend_instance *inst, Slapi_Entry * conf, int apply) {
  1543. cb_backend *cb = inst->backend_type;
  1544. Slapi_PBlock *default_pb;
  1545. Slapi_Entry **default_entries = NULL;
  1546. Slapi_Entry *default_conf=NULL;
  1547. int default_res, rc;
  1548. char *defaultDn;
  1549. cb_backend_instance * current_inst;
  1550. rc=LDAP_SUCCESS;
  1551. if (apply)
  1552. current_inst=inst;
  1553. else
  1554. current_inst=cb_instance_alloc(cb,inst->inst_name,"cn=dummy");
  1555. /* set default configuration */
  1556. cb_instance_config_set_default(current_inst);
  1557. /* 2: Overwrite values present in the default instance config */
  1558. defaultDn = PR_smprintf("cn=default instance config,%s",cb->pluginDN);
  1559. default_pb = slapi_pblock_new();
  1560. slapi_search_internal_set_pb(default_pb, defaultDn, LDAP_SCOPE_BASE,
  1561. "objectclass=*", NULL, 0, NULL, NULL, cb->identity, 0);
  1562. slapi_search_internal_pb (default_pb);
  1563. PR_smprintf_free(defaultDn);
  1564. slapi_pblock_get(default_pb, SLAPI_PLUGIN_INTOP_RESULT, &default_res);
  1565. if ( LDAP_SUCCESS == default_res ) {
  1566. slapi_pblock_get(default_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &default_entries);
  1567. if (default_entries && default_entries[0] ) {
  1568. struct berval val;
  1569. struct berval *vals[2];
  1570. vals[0] = &val;
  1571. vals[1] = NULL;
  1572. default_conf=default_entries[0];
  1573. /* hack: add a dummy url (mandatory) to avoid error */
  1574. /* will be overwritten by the one in conf entry */
  1575. val.bv_val = "ldap://localhost/";
  1576. val.bv_len = strlen( val.bv_val );
  1577. slapi_entry_attr_replace( default_conf, CB_CONFIG_HOSTURL, (struct berval **)vals );
  1578. rc=cb_instance_config_initialize(current_inst,default_conf,CB_CONFIG_PHASE_STARTUP,1);
  1579. }
  1580. }
  1581. slapi_free_search_results_internal(default_pb);
  1582. slapi_pblock_destroy(default_pb);
  1583. if (rc == LDAP_SUCCESS)
  1584. rc=cb_instance_config_initialize(current_inst,conf,CB_CONFIG_PHASE_STARTUP,1);
  1585. if (!apply)
  1586. cb_instance_free(current_inst);
  1587. return rc;
  1588. }