dse.c 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404
  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. /*
  42. * dse.c - DSE (DSA-Specific Entry) persistent storage.
  43. *
  44. * The DSE store is an LDIF file contained in the file dse.ldif.
  45. * The file is located in the directory specified with '-D'
  46. * when staring the server.
  47. *
  48. * In core, the DSEs are stored in an AVL tree, keyed on
  49. * DN. Whenever a modification is made to a DSE, the
  50. * in-core entry is updated, then dse_write_file() is
  51. * called to commit the changes to disk.
  52. *
  53. * This is designed for a small number of DSEs, say
  54. * a maximum of 10 or 20. If large numbers of DSEs
  55. * need to be stored, this approach of writing out
  56. * the entire contents on every modification will
  57. * be insufficient.
  58. *
  59. */
  60. #include <sys/types.h>
  61. #include <sys/stat.h>
  62. #include <fcntl.h>
  63. #include <errno.h>
  64. #include <prio.h>
  65. #include <prcountr.h>
  66. #include "slap.h"
  67. #if !defined (_WIN32)
  68. #include <pwd.h>
  69. #endif /* _WIN32 */
  70. /* #define SLAPI_DSE_DEBUG */ /* define this to force trace log */
  71. /* messages to always be logged */
  72. #ifdef SLAPI_DSE_DEBUG
  73. #define SLAPI_DSE_TRACELEVEL LDAP_DEBUG_ANY
  74. #else /* SLAPI_DSE_DEBUG */
  75. #define SLAPI_DSE_TRACELEVEL LDAP_DEBUG_TRACE
  76. #endif /* SLAPI_DSE_DEBUG */
  77. #define STOP_TRAVERSAL -2
  78. /* This is returned by dupentry_replace if the duplicate entry was found and
  79. replaced. This is returned up through the avl_insert() in
  80. dse_replace_entry(). Otherwise, if avl_insert() returns 0, the
  81. entry was added i.e. a duplicate was not found.
  82. */
  83. #define DSE_ENTRY_WAS_REPLACED -3
  84. /* This is returned by dupentry_merge if the duplicate entry was found and
  85. merged. This is returned up through the avl_insert() in dse_add_entry_pb().
  86. Otherwise, if avl_insert() returns 0, the
  87. entry was added i.e. a duplicate was not found.
  88. */
  89. #define DSE_ENTRY_WAS_MERGED -4
  90. /* some functions can be used either from within a lock or "standalone" */
  91. #define DSE_USE_LOCK 1
  92. #define DSE_NO_LOCK 0
  93. struct dse_callback
  94. {
  95. int operation;
  96. int flags;
  97. Slapi_DN *base;
  98. int scope;
  99. char *filter; /* NULL means match all entries */
  100. Slapi_Filter *slapifilter; /* NULL means match all entries */
  101. int (*fn)(Slapi_PBlock *,Slapi_Entry *,Slapi_Entry *,int*,char*,void *);
  102. void *fn_arg;
  103. struct dse_callback *next;
  104. };
  105. struct dse
  106. {
  107. char *dse_filename; /* these are the primary files which get read from */
  108. char *dse_tmpfile; /* and written to when changes are made via LDAP */
  109. char *dse_fileback; /* contain the latest info, just before a new change */
  110. char *dse_filestartOK; /* contain the latest info with which the server has successfully started */
  111. Avlnode *dse_tree;
  112. struct dse_callback *dse_callback;
  113. PRRWLock *dse_rwlock; /* a read-write lock to protect the whole dse backend */
  114. char **dse_filelist; /* these are additional read only files used to */
  115. /* initialize the dse */
  116. int dse_is_updateable; /* if non-zero, this DSE can be written to */
  117. int dse_readonly_error_reported; /* used to ensure that read-only errors are logged only once */
  118. };
  119. struct dse_node
  120. {
  121. Slapi_Entry *entry;
  122. };
  123. /* search set stuff - used to pass search results to the frontend */
  124. typedef struct dse_search_set
  125. {
  126. DataList dl;
  127. int current_entry;
  128. } dse_search_set;
  129. static int dse_permission_to_write(struct dse* pdse, int loglevel);
  130. static int dse_write_file_nolock(struct dse* pdse);
  131. static int dse_apply_nolock(struct dse* pdse, IFP fp, caddr_t arg);
  132. static int dse_replace_entry( struct dse* pdse, Slapi_Entry *e, int write_file, int use_lock );
  133. static dse_search_set* dse_search_set_new ();
  134. static void dse_search_set_delete (dse_search_set *ss);
  135. static void dse_search_set_clean (dse_search_set *ss);
  136. static void dse_free_entry (void **data);
  137. static void dse_search_set_add_entry (dse_search_set *ss, Slapi_Entry *e);
  138. static Slapi_Entry* dse_search_set_get_next_entry (dse_search_set *ss);
  139. static int dse_add_entry_pb(struct dse* pdse, Slapi_Entry *e, Slapi_PBlock *pb);
  140. static struct dse_node *dse_find_node( struct dse* pdse, const Slapi_DN *dn );
  141. /*
  142. richm: In almost all modes e.g. db2ldif, ldif2db, etc. we do not need/want
  143. to write out the dse.ldif and ldbm.ldif files. The only mode which really
  144. needs to write out the file is the regular server mode. The variable
  145. dont_ever_write_dse_files tells dse_write_file_nolock whether or not to write
  146. the .ldif file for the entry. The default is 1, which means never write the
  147. file. The server, when it starts up in regular mode, must call
  148. dse_unset_dont_ever_write_dse_files() to enable this file to be written
  149. */
  150. static int dont_ever_write_dse_files = 1;
  151. /* Forward declarations */
  152. static int entry_dn_cmp( caddr_t d1, caddr_t d2 );
  153. static int dupentry_disallow( caddr_t d1, caddr_t d2 );
  154. static int dupentry_merge( caddr_t d1, caddr_t d2 );
  155. static int dse_write_entry( caddr_t data, caddr_t arg );
  156. static int ldif_record_end( char *p );
  157. static int dse_call_callback(struct dse* pdse, Slapi_PBlock *pb, int operation, int flags, Slapi_Entry *entryBefore, Slapi_Entry *entryAfter, int *returncode, char* returntext);
  158. /*
  159. * Map a DN onto a dse_node.
  160. * Returns NULL if not found.
  161. * You must have a read or write lock on the dse_rwlock while
  162. * using the returned node.
  163. */
  164. static struct dse_node *
  165. dse_find_node( struct dse* pdse, const Slapi_DN *dn )
  166. {
  167. struct dse_node *n = NULL;
  168. if ( NULL != dn )
  169. {
  170. struct dse_node searchNode;
  171. Slapi_Entry *fe= slapi_entry_alloc();
  172. slapi_entry_init(fe, NULL, NULL);
  173. slapi_entry_set_sdn(fe,dn);
  174. searchNode.entry= fe;
  175. n = (struct dse_node *)avl_find( pdse->dse_tree, &searchNode, entry_dn_cmp );
  176. slapi_entry_free(fe);
  177. }
  178. return n;
  179. }
  180. static int counters_created= 0;
  181. PR_DEFINE_COUNTER(dse_entries_exist);
  182. /*
  183. * Map a DN onto a real Entry.
  184. * Returns NULL if not found.
  185. */
  186. static Slapi_Entry *
  187. dse_get_entry_copy( struct dse* pdse, const Slapi_DN *dn, int use_lock )
  188. {
  189. Slapi_Entry *e= NULL;
  190. struct dse_node *n;
  191. if (use_lock == DSE_USE_LOCK && pdse->dse_rwlock)
  192. PR_RWLock_Rlock(pdse->dse_rwlock);
  193. n = dse_find_node( pdse, dn );
  194. if(n!=NULL)
  195. {
  196. e = slapi_entry_dup(n->entry);
  197. }
  198. if (use_lock == DSE_USE_LOCK && pdse->dse_rwlock)
  199. PR_RWLock_Unlock(pdse->dse_rwlock);
  200. return e;
  201. }
  202. static struct dse_callback *
  203. dse_callback_new(int operation, int flags, const Slapi_DN *base, int scope, const char *filter, dseCallbackFn fn, void *fn_arg)
  204. {
  205. struct dse_callback *p= NULL;
  206. p = (struct dse_callback *)slapi_ch_malloc(sizeof(struct dse_callback));
  207. if (p!=NULL) {
  208. p->operation= operation;
  209. p->flags = flags;
  210. p->base= slapi_sdn_dup(base);
  211. p->scope= scope;
  212. if ( NULL == filter ) {
  213. p->filter= NULL;
  214. p->slapifilter= NULL;
  215. } else {
  216. p->filter= slapi_ch_strdup(filter);
  217. p->slapifilter= slapi_str2filter( p->filter );
  218. filter_normalize(p->slapifilter);
  219. }
  220. p->fn= fn;
  221. p->fn_arg= fn_arg;
  222. p->next= NULL;
  223. }
  224. return p;
  225. }
  226. static void
  227. dse_callback_delete(struct dse_callback **pp)
  228. {
  229. if (pp!=NULL) {
  230. slapi_sdn_free(&((*pp)->base));
  231. slapi_ch_free((void**)&((*pp)->filter));
  232. slapi_filter_free((*pp)->slapifilter,1);
  233. slapi_ch_free((void**)pp);
  234. }
  235. }
  236. static void
  237. dse_callback_deletelist(struct dse_callback **pp)
  238. {
  239. if(pp!=NULL)
  240. {
  241. struct dse_callback *p, *n;
  242. for(p= *pp;p!=NULL;)
  243. {
  244. n= p->next;
  245. dse_callback_delete(&p);
  246. p= n;
  247. }
  248. }
  249. }
  250. /*
  251. Makes a copy of the entry passed in, so it's const
  252. */
  253. static struct dse_node *
  254. dse_node_new(const Slapi_Entry *entry)
  255. {
  256. struct dse_node *p= NULL;
  257. p= (struct dse_node *)slapi_ch_malloc(sizeof(struct dse_node));
  258. if(p!=NULL)
  259. {
  260. p->entry= slapi_entry_dup(entry);
  261. }
  262. if(!counters_created)
  263. {
  264. PR_CREATE_COUNTER(dse_entries_exist,"DSE","entries","");
  265. counters_created= 1;
  266. }
  267. PR_INCREMENT_COUNTER(dse_entries_exist);
  268. return p;
  269. }
  270. static void
  271. dse_node_delete(struct dse_node **pp)
  272. {
  273. slapi_entry_free((*pp)->entry);
  274. slapi_ch_free((void **)&(*pp));
  275. PR_DECREMENT_COUNTER(dse_entries_exist);
  276. }
  277. static void
  278. dse_callback_addtolist(struct dse_callback **pplist, struct dse_callback *p)
  279. {
  280. if(pplist!=NULL)
  281. {
  282. p->next= NULL;
  283. if(*pplist==NULL)
  284. {
  285. *pplist= p;
  286. }
  287. else
  288. {
  289. struct dse_callback *t= *pplist;
  290. for(;t->next!=NULL;t= t->next);
  291. t->next= p;
  292. }
  293. }
  294. }
  295. static void
  296. dse_callback_removefromlist(struct dse_callback **pplist, int operation, int flags, const Slapi_DN *base, int scope, const char *filter, dseCallbackFn fn)
  297. {
  298. if (pplist != NULL) {
  299. struct dse_callback *t= *pplist;
  300. struct dse_callback *prev= NULL;
  301. for(; t!=NULL; ) {
  302. if ((t->operation == operation) && (t->flags == flags) &&
  303. (t->fn == fn) && (scope == t->scope) &&
  304. (slapi_sdn_compare(base,t->base) == 0) &&
  305. (( NULL == filter && NULL == t->filter ) ||
  306. (strcasecmp(filter, t->filter) == 0))) {
  307. if (prev == NULL) {
  308. *pplist= t->next;
  309. } else {
  310. prev->next= t->next;
  311. }
  312. dse_callback_delete(&t);
  313. t= NULL;
  314. } else {
  315. prev= t;
  316. t= t->next;
  317. }
  318. }
  319. }
  320. }
  321. /*
  322. * Create a new dse structure.
  323. */
  324. struct dse *
  325. dse_new( char *filename, char *tmpfilename, char *backfilename, char *startokfilename, const char *configdir)
  326. {
  327. struct dse *pdse= NULL;
  328. char *realconfigdir = NULL;
  329. if (configdir!=NULL)
  330. {
  331. realconfigdir = slapi_ch_strdup(configdir);
  332. }
  333. else
  334. {
  335. realconfigdir = config_get_configdir();
  336. }
  337. if(realconfigdir!=NULL)
  338. {
  339. pdse= (struct dse *)slapi_ch_calloc(1, sizeof(struct dse));
  340. if(pdse!=NULL)
  341. {
  342. pdse->dse_rwlock = PR_NewRWLock(PR_RWLOCK_RANK_NONE,"dse lock");
  343. /* Set the full path name for the config DSE entry */
  344. if (!strstr(filename, realconfigdir))
  345. {
  346. pdse->dse_filename = slapi_ch_smprintf("%s/%s", realconfigdir, filename );
  347. }
  348. else
  349. pdse->dse_filename = slapi_ch_strdup(filename);
  350. if (!strstr(tmpfilename, realconfigdir)) {
  351. pdse->dse_tmpfile = slapi_ch_smprintf("%s/%s", realconfigdir, tmpfilename );
  352. }
  353. else
  354. pdse->dse_tmpfile = slapi_ch_strdup(tmpfilename);
  355. if ( backfilename != NULL )
  356. {
  357. if (!strstr(backfilename, realconfigdir)) {
  358. pdse->dse_fileback = slapi_ch_smprintf("%s/%s", realconfigdir, backfilename );
  359. }
  360. else
  361. pdse->dse_fileback = slapi_ch_strdup(backfilename);
  362. }
  363. else
  364. pdse->dse_fileback = NULL;
  365. if ( startokfilename != NULL )
  366. {
  367. if (!strstr(startokfilename, realconfigdir)) {
  368. pdse->dse_filestartOK = slapi_ch_smprintf("%s/%s", realconfigdir, startokfilename );
  369. }
  370. else
  371. pdse->dse_filestartOK = slapi_ch_strdup(startokfilename);
  372. }
  373. else
  374. pdse->dse_filestartOK = NULL;
  375. pdse->dse_tree= NULL;
  376. pdse->dse_callback= NULL;
  377. pdse->dse_is_updateable = dse_permission_to_write(pdse,
  378. SLAPI_LOG_TRACE);
  379. }
  380. slapi_ch_free( (void **) &realconfigdir );
  381. }
  382. return pdse;
  383. }
  384. /*
  385. * Create a new dse structure with a file list
  386. */
  387. struct dse *
  388. dse_new_with_filelist(char *filename, char *tmpfilename, char *backfilename, char *startokfilename, const char *configdir,
  389. char **filelist)
  390. {
  391. struct dse *newdse = dse_new(filename, tmpfilename, backfilename, startokfilename, configdir);
  392. newdse->dse_filelist = filelist;
  393. return newdse;
  394. }
  395. static int
  396. dse_internal_delete_entry( caddr_t data, caddr_t arg )
  397. {
  398. struct dse_node *n = (struct dse_node *)data;
  399. dse_node_delete(&n);
  400. return 0;
  401. }
  402. /*
  403. * Get rid of a dse structure.
  404. */
  405. int
  406. dse_destroy(struct dse *pdse)
  407. {
  408. int nentries = 0;
  409. if (pdse->dse_rwlock)
  410. PR_RWLock_Wlock(pdse->dse_rwlock);
  411. slapi_ch_free((void **)&(pdse->dse_filename));
  412. slapi_ch_free((void **)&(pdse->dse_tmpfile));
  413. slapi_ch_free((void **)&(pdse->dse_fileback));
  414. slapi_ch_free((void **)&(pdse->dse_filestartOK));
  415. dse_callback_deletelist(&pdse->dse_callback);
  416. charray_free(pdse->dse_filelist);
  417. nentries = avl_free(pdse->dse_tree, dse_internal_delete_entry);
  418. if (pdse->dse_rwlock) {
  419. PR_RWLock_Unlock(pdse->dse_rwlock);
  420. PR_DestroyRWLock(pdse->dse_rwlock);
  421. }
  422. slapi_ch_free((void **)&pdse);
  423. LDAPDebug( SLAPI_DSE_TRACELEVEL, "Removed [%d] entries from the dse tree.\n",
  424. nentries,0,0 );
  425. return 0; /* no one checks this return value */
  426. }
  427. /*
  428. * Get rid of a dse structure.
  429. */
  430. int
  431. dse_deletedse(Slapi_PBlock *pb)
  432. {
  433. struct dse *pdse = NULL;
  434. slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &pdse);
  435. if (pdse)
  436. {
  437. dse_destroy(pdse);
  438. }
  439. /* data is freed, so make sure no one tries to use it */
  440. slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, NULL);
  441. return 0;
  442. }
  443. static char* subordinatecount = "numsubordinates";
  444. /*
  445. * Get the number of subordinates for this entry.
  446. */
  447. static size_t
  448. dse_numsubordinates(Slapi_Entry *entry)
  449. {
  450. int ret= 0;
  451. Slapi_Attr *read_attr = NULL;
  452. size_t current_sub_count = 0;
  453. /* Get the present value of the subcount attr, or 0 if not present */
  454. ret = slapi_entry_attr_find(entry,subordinatecount,&read_attr);
  455. if (0 == ret)
  456. {
  457. /* decode the value */
  458. Slapi_Value *sval;
  459. slapi_attr_first_value( read_attr,&sval );
  460. if (sval!=NULL)
  461. {
  462. const struct berval *bval = slapi_value_get_berval( sval );
  463. if( NULL != bval )
  464. current_sub_count = atol(bval->bv_val);
  465. }
  466. }
  467. return current_sub_count;
  468. }
  469. /*
  470. * Update the numsubordinates count.
  471. * mod_op is either an Add or Delete.
  472. */
  473. static void
  474. dse_updateNumSubordinates(Slapi_Entry *entry, int op)
  475. {
  476. int ret= 0;
  477. int mod_op = 0;
  478. Slapi_Attr *read_attr = NULL;
  479. size_t current_sub_count = 0;
  480. int already_present = 0;
  481. /* For now, we're only interested in subordinatecount.
  482. We first examine the present value for the attribute.
  483. If it isn't present and we're adding, we assign value 1 to the attribute and add it.
  484. If it is present, we increment or decrement depending upon whether we're adding or deleting.
  485. If the value after decrementing is zero, we remove it.
  486. */
  487. /* Get the present value of the subcount attr, or 0 if not present */
  488. ret = slapi_entry_attr_find(entry,subordinatecount,&read_attr);
  489. if (0 == ret)
  490. {
  491. /* decode the value */
  492. Slapi_Value *sval;
  493. slapi_attr_first_value( read_attr,&sval );
  494. if (sval!=NULL)
  495. {
  496. const struct berval *bval = slapi_value_get_berval( sval );
  497. if (bval!=NULL)
  498. {
  499. already_present = 1;
  500. current_sub_count = atol(bval->bv_val);
  501. }
  502. }
  503. }
  504. /* are we adding ? */
  505. if ( (SLAPI_OPERATION_ADD == op) && !already_present)
  506. {
  507. /* If so, and the parent entry does not already have a subcount attribute, we need to add it */
  508. mod_op = LDAP_MOD_ADD;
  509. }
  510. else
  511. {
  512. if (SLAPI_OPERATION_DELETE == op)
  513. {
  514. if (!already_present)
  515. {
  516. /* This means that something is wrong---deleting a child but no subcount present on parent */
  517. slapi_log_error( SLAPI_LOG_FATAL, "dse",
  518. "numsubordinates assertion failure\n" );
  519. return;
  520. }
  521. else
  522. {
  523. if (current_sub_count == 1)
  524. {
  525. mod_op = LDAP_MOD_DELETE;
  526. }
  527. else
  528. {
  529. mod_op = LDAP_MOD_REPLACE;
  530. }
  531. }
  532. }
  533. else
  534. {
  535. mod_op = LDAP_MOD_REPLACE;
  536. }
  537. }
  538. /* Now compute the new value */
  539. if (SLAPI_OPERATION_ADD == op)
  540. {
  541. current_sub_count++;
  542. }
  543. else
  544. {
  545. current_sub_count--;
  546. }
  547. {
  548. char value_buffer[20]; /* enough digits for 2^64 children */
  549. struct berval *vals[2];
  550. struct berval val;
  551. vals[0] = &val;
  552. vals[1] = NULL;
  553. sprintf(value_buffer,"%lu",current_sub_count);
  554. val.bv_val = value_buffer;
  555. val.bv_len = strlen (val.bv_val);
  556. switch(mod_op)
  557. {
  558. case LDAP_MOD_ADD:
  559. attrlist_merge( &entry->e_attrs, subordinatecount, vals);
  560. break;
  561. case LDAP_MOD_REPLACE:
  562. attrlist_replace( &entry->e_attrs, subordinatecount, vals);
  563. break;
  564. case LDAP_MOD_DELETE:
  565. attrlist_delete( &entry->e_attrs, subordinatecount);
  566. break;
  567. }
  568. }
  569. }
  570. /* the write lock should always be acquired before calling this function */
  571. static void
  572. dse_updateNumSubOfParent(struct dse *pdse, const Slapi_DN *child, int op)
  573. {
  574. Slapi_DN parent;
  575. slapi_sdn_init(&parent);
  576. slapi_sdn_get_parent(child, &parent);
  577. if ( !slapi_sdn_isempty(&parent) )
  578. {
  579. /* no lock because caller should already have the write lock */
  580. Slapi_Entry *parententry= dse_get_entry_copy( pdse, &parent, DSE_NO_LOCK );
  581. if( parententry!=NULL )
  582. {
  583. /* Decrement the numsubordinate count of the parent entry */
  584. dse_updateNumSubordinates(parententry, op);
  585. /* no lock because caller should always have the write lock */
  586. dse_replace_entry( pdse, parententry, 0, DSE_NO_LOCK );
  587. slapi_entry_free(parententry);
  588. }
  589. }
  590. slapi_sdn_done(&parent);
  591. }
  592. static int
  593. dse_read_one_file(struct dse *pdse, const char *filename, Slapi_PBlock *pb,
  594. int primary_file )
  595. {
  596. Slapi_Entry *e= NULL;
  597. char *entrystr= NULL;
  598. char *buf = NULL;
  599. char *lastp = NULL;
  600. int rc= 0; /* Fail */
  601. PRInt32 nr = 0;
  602. PRFileInfo prfinfo;
  603. PRFileDesc *prfd = 0;
  604. int schema_flags = 0;
  605. slapi_pblock_get(pb, SLAPI_SCHEMA_FLAGS, &schema_flags);
  606. if ( (NULL != pdse) && (NULL != filename) )
  607. {
  608. if ( (rc = PR_GetFileInfo( filename, &prfinfo )) != PR_SUCCESS )
  609. {
  610. /* the "real" file does not exist; see if there is a tmpfile */
  611. if ( pdse->dse_tmpfile &&
  612. PR_GetFileInfo( pdse->dse_tmpfile, &prfinfo ) == PR_SUCCESS ) {
  613. rc = PR_Rename(pdse->dse_tmpfile, filename);
  614. if (rc == PR_SUCCESS) {
  615. slapi_log_error(SLAPI_LOG_FATAL, "dse",
  616. "The configuration file %s was restored from backup %s\n",
  617. filename, pdse->dse_tmpfile);
  618. rc = 1;
  619. } else {
  620. slapi_log_error(SLAPI_LOG_FATAL, "dse",
  621. "The configuration file %s was not restored from backup %s, error %d\n",
  622. filename, pdse->dse_tmpfile, rc);
  623. rc = 0;
  624. }
  625. } else {
  626. rc = 0; /* fail */
  627. }
  628. }
  629. if ( (rc = PR_GetFileInfo( filename, &prfinfo )) != PR_SUCCESS )
  630. {
  631. slapi_log_error(SLAPI_LOG_FATAL, "dse",
  632. "The configuration file %s could not be accessed, error %d\n",
  633. filename, rc);
  634. rc = 0; /* Fail */
  635. }
  636. else if (( prfd = PR_Open( filename, PR_RDONLY, SLAPD_DEFAULT_FILE_MODE )) == NULL )
  637. {
  638. slapi_log_error(SLAPI_LOG_FATAL, "dse",
  639. "The configuration file %s could not be read. "
  640. SLAPI_COMPONENT_NAME_NSPR " %d (%s)\n",
  641. filename,
  642. PR_GetError(), slapd_pr_strerror(PR_GetError()));
  643. rc = 0; /* Fail */
  644. }
  645. else
  646. {
  647. int done= 0;
  648. /* read the entire file into core */
  649. buf = slapi_ch_malloc( prfinfo.size + 1 );
  650. if (( nr = slapi_read_buffer( prfd, buf, prfinfo.size )) < 0 )
  651. {
  652. slapi_log_error(SLAPI_LOG_FATAL, "dse",
  653. "Could only read %d of %d bytes from config file %s\n",
  654. nr, prfinfo.size, filename);
  655. rc = 0; /* Fail */
  656. done= 1;
  657. }
  658. (void)PR_Close( prfd );
  659. buf[ nr ] = '\0';
  660. if(!done)
  661. {
  662. int dont_check_dups = 0;
  663. int str2entry_flags = SLAPI_STR2ENTRY_EXPAND_OBJECTCLASSES |
  664. SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF ;
  665. if (schema_flags & DSE_SCHEMA_LOCKED)
  666. str2entry_flags |= SLAPI_STR2ENTRY_NO_SCHEMA_LOCK;
  667. PR_ASSERT(pb);
  668. slapi_pblock_get(pb, SLAPI_DSE_DONT_CHECK_DUPS, &dont_check_dups);
  669. if ( !dont_check_dups ) {
  670. str2entry_flags |= SLAPI_STR2ENTRY_REMOVEDUPVALS;
  671. }
  672. /* Convert LDIF to entry structures */
  673. rc= 1; /* assume we will succeed */
  674. while (( entrystr = dse_read_next_entry( buf, &lastp )) != NULL )
  675. {
  676. e = slapi_str2entry( entrystr, str2entry_flags );
  677. if ( e != NULL )
  678. {
  679. int returncode = 0;
  680. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= {0};
  681. LDAPDebug(SLAPI_DSE_TRACELEVEL, "dse_read_one_file"
  682. " processing entry \"%s\" in file %s%s\n",
  683. slapi_entry_get_dn_const(e), filename,
  684. primary_file ? " (primary file)" : "" );
  685. /* remove the numsubordinates attr, which may be bogus */
  686. slapi_entry_attr_delete(e, subordinatecount);
  687. /* set the "primary file" flag if appropriate */
  688. slapi_pblock_set( pb, SLAPI_DSE_IS_PRIMARY_FILE, &primary_file );
  689. if(dse_call_callback(pdse, pb, DSE_OPERATION_READ,
  690. DSE_FLAG_PREOP, e, NULL, &returncode,
  691. returntext) == SLAPI_DSE_CALLBACK_OK)
  692. {
  693. /* this will free the entry if not added, so it is
  694. definitely consumed by this call */
  695. dse_add_entry_pb(pdse, e, pb);
  696. }
  697. else /* free entry if not used */
  698. {
  699. slapi_log_error(SLAPI_LOG_FATAL, "dse",
  700. "The entry %s in file %s is invalid, error code %d (%s) - %s\n",
  701. slapi_entry_get_dn_const(e),
  702. filename, returncode,
  703. ldap_err2string(returncode),
  704. returntext);
  705. slapi_entry_free(e);
  706. rc = 0; /* failure */
  707. }
  708. } else {
  709. slapi_log_error( SLAPI_LOG_FATAL, "dse",
  710. "parsing dse entry [%s]\n", entrystr );
  711. rc = 0; /* failure */
  712. }
  713. }
  714. }
  715. slapi_ch_free((void **)&buf);
  716. }
  717. }
  718. return rc;
  719. }
  720. /*
  721. * Read the file we were initialised with into memory.
  722. * If not NULL call entry_filter_fn on each entry as it's read.
  723. * The function is free to modify the entry before it's places
  724. * into the AVL tree. True means add the entry. False means don't.
  725. *
  726. * Return 1 for OK, 0 for Fail.
  727. */
  728. int
  729. dse_read_file(struct dse *pdse, Slapi_PBlock *pb)
  730. {
  731. int rc= 1; /* Good */
  732. int ii;
  733. char **filelist = 0;
  734. char *filename = 0;
  735. filelist = charray_dup(pdse->dse_filelist);
  736. filename = slapi_ch_strdup(pdse->dse_filename);
  737. for (ii = 0; rc && filelist && filelist[ii]; ++ii)
  738. {
  739. if (strcasecmp(filename, filelist[ii])!=0)
  740. {
  741. rc = dse_read_one_file(pdse, filelist[ii], pb, 0 /* not primary */);
  742. }
  743. }
  744. if (rc)
  745. {
  746. rc = dse_read_one_file(pdse, filename, pb, 1 /* primary file */);
  747. }
  748. charray_free(filelist);
  749. slapi_ch_free((void **)&filename);
  750. return rc;
  751. }
  752. /*
  753. * Structure to carry context information whilst
  754. * traversing the tree writing the entries to disk.
  755. */
  756. typedef struct _fpw
  757. {
  758. PRFileDesc *fpw_prfd;
  759. int fpw_rc;
  760. struct dse *fpw_pdse;
  761. } FPWrapper;
  762. static int
  763. dse_rw_permission_to_one_file(const char *name, int loglevel)
  764. {
  765. PRErrorCode prerr = 0;
  766. const char *accesstype = "";
  767. if ( NULL == name ) {
  768. return 1; /* file won't be used -- return "sufficient permission" */
  769. }
  770. if ( PR_Access( name, PR_ACCESS_EXISTS ) == PR_SUCCESS ) {
  771. /* file exists: check for read and write permission */
  772. if ( PR_Access( name, PR_ACCESS_WRITE_OK ) != PR_SUCCESS ) {
  773. prerr = PR_GetError();
  774. accesstype = "write";
  775. } else if ( PR_Access( name, PR_ACCESS_READ_OK ) != PR_SUCCESS ) {
  776. prerr = PR_GetError();
  777. accesstype = "read";
  778. }
  779. } else {
  780. /* file does not exist: make sure we can create it */
  781. PRFileDesc *prfd;
  782. prfd = PR_Open( name, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE,
  783. SLAPD_DEFAULT_FILE_MODE );
  784. if ( NULL == prfd ) {
  785. prerr = PR_GetError();
  786. accesstype = "create";
  787. } else {
  788. PR_Close( prfd );
  789. PR_Delete( name );
  790. }
  791. }
  792. if ( prerr != 0 ) {
  793. slapi_log_error( loglevel, "dse", "Unable to %s \"%s\": "
  794. SLAPI_COMPONENT_NAME_NSPR " error %d (%s)\n",
  795. accesstype, name, prerr, slapd_pr_strerror(prerr));
  796. return 0; /* insufficient permission */
  797. } else {
  798. return 1; /* sufficient permission */
  799. }
  800. }
  801. /*
  802. * Check that we have permission to write to all the files that
  803. * dse_write_file_nolock() uses.
  804. * Returns a non-zero value if sufficient permission and 0 if not.
  805. */
  806. static int
  807. dse_permission_to_write(struct dse* pdse, int loglevel)
  808. {
  809. int rc = 1; /* sufficient permission */
  810. if ( NULL != pdse->dse_filename ) {
  811. if ( !dse_rw_permission_to_one_file( pdse->dse_filename, loglevel ) ||
  812. !dse_rw_permission_to_one_file( pdse->dse_fileback, loglevel ) ||
  813. !dse_rw_permission_to_one_file( pdse->dse_tmpfile, loglevel )) {
  814. rc = 0; /* insufficient permission */
  815. }
  816. }
  817. return rc;
  818. }
  819. /*
  820. * Check for read-only status and return an appropriate error to the
  821. * LDAP client.
  822. * Returns 0 if no error was returned and non-zero if one was.
  823. */
  824. static int
  825. dse_check_for_readonly_error(Slapi_PBlock *pb, struct dse* pdse)
  826. {
  827. int rc = 0; /* default: no error */
  828. if (pdse->dse_rwlock)
  829. PR_RWLock_Rlock(pdse->dse_rwlock);
  830. if ( !pdse->dse_is_updateable ) {
  831. if ( !pdse->dse_readonly_error_reported ) {
  832. if ( NULL != pdse->dse_filename ) {
  833. slapi_log_error( SLAPI_LOG_FATAL, "dse",
  834. "The DSE database stored in \"%s\" is not writeable\n",
  835. pdse->dse_filename );
  836. /* log the details too */
  837. (void)dse_permission_to_write(pdse, SLAPI_LOG_FATAL);
  838. }
  839. pdse->dse_readonly_error_reported = 1;
  840. }
  841. rc = 1; /* return an error to the client */
  842. }
  843. if (pdse->dse_rwlock)
  844. PR_RWLock_Unlock(pdse->dse_rwlock);
  845. if ( rc != 0 ) {
  846. slapi_send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
  847. "DSE database is read-only", 0, NULL );
  848. }
  849. return rc; /* no error */
  850. }
  851. /*
  852. * Write the AVL tree of entries back to the LDIF file.
  853. */
  854. static int
  855. dse_write_file_nolock(struct dse* pdse)
  856. {
  857. FPWrapper fpw;
  858. int rc = 0;
  859. if (dont_ever_write_dse_files)
  860. return rc;
  861. fpw.fpw_rc = 0;
  862. fpw.fpw_prfd = NULL;
  863. if ( NULL != pdse->dse_filename )
  864. {
  865. if (( fpw.fpw_prfd = PR_Open( pdse->dse_tmpfile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, SLAPD_DEFAULT_FILE_MODE )) == NULL )
  866. {
  867. rc = PR_GetOSError();
  868. slapi_log_error( SLAPI_LOG_FATAL, "dse", "Cannot open "
  869. "temporary DSE file \"%s\" for update: OS error %d (%s)\n",
  870. pdse->dse_tmpfile, rc, slapd_system_strerror( rc ));
  871. }
  872. else
  873. {
  874. fpw.fpw_pdse = pdse;
  875. if ( avl_apply( pdse->dse_tree, dse_write_entry, &fpw, STOP_TRAVERSAL, AVL_INORDER ) == STOP_TRAVERSAL )
  876. {
  877. rc = fpw.fpw_rc;
  878. slapi_log_error( SLAPI_LOG_FATAL, "dse", "Cannot write "
  879. " temporary DSE file \"%s\": OS error %d (%s)\n",
  880. pdse->dse_tmpfile, rc, slapd_system_strerror( rc ));
  881. (void)PR_Close( fpw.fpw_prfd );
  882. fpw.fpw_prfd = NULL;
  883. }
  884. else
  885. {
  886. (void)PR_Close( fpw.fpw_prfd );
  887. fpw.fpw_prfd = NULL;
  888. if ( pdse->dse_fileback != NULL )
  889. {
  890. rc = slapi_destructive_rename( pdse->dse_filename, pdse->dse_fileback );
  891. if ( rc != 0 )
  892. {
  893. slapi_log_error( SLAPI_LOG_FATAL, "dse", "Cannot backup"
  894. " DSE file \"%s\" to \"%s\": OS error %d (%s)\n",
  895. pdse->dse_filename, pdse->dse_fileback,
  896. rc, slapd_system_strerror( rc ));
  897. }
  898. }
  899. rc = slapi_destructive_rename( pdse->dse_tmpfile, pdse->dse_filename );
  900. if ( rc != 0 )
  901. {
  902. slapi_log_error( SLAPI_LOG_FATAL, "dse", "Cannot rename"
  903. " temporary DSE file \"%s\" to \"%s\":"
  904. " OS error %d (%s)\n",
  905. pdse->dse_tmpfile, pdse->dse_filename,
  906. rc, slapd_system_strerror( rc ));
  907. }
  908. }
  909. }
  910. if (fpw.fpw_prfd)
  911. (void)PR_Close(fpw.fpw_prfd);
  912. }
  913. return rc;
  914. }
  915. /*
  916. * Local function for writing an entry to a file.
  917. * Called by the AVL code during traversal.
  918. */
  919. static int
  920. dse_write_entry( caddr_t data, caddr_t arg )
  921. {
  922. struct dse_node *n = (struct dse_node *)data;
  923. FPWrapper *fpw = (FPWrapper *)arg;
  924. char *s;
  925. PRInt32 len;
  926. if ( NULL != n && NULL != n->entry )
  927. {
  928. int returncode;
  929. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= "";
  930. /* need to make a duplicate here for two reasons:
  931. 1) we don't want to hold on to the raw data in the node for any longer
  932. than we have to; we will usually be inside the dse write lock, but . . .
  933. 2) the write callback may modify the entry, so we want to pass it a
  934. writeable copy rather than the raw avl tree data pointer
  935. */
  936. Slapi_Entry *ec = slapi_entry_dup(n->entry);
  937. if(dse_call_callback(fpw->fpw_pdse, NULL, DSE_OPERATION_WRITE,
  938. DSE_FLAG_PREOP, ec, NULL, &returncode, returntext)
  939. == SLAPI_DSE_CALLBACK_OK)
  940. {
  941. /*
  942. * 3-August-2000 mcs: We used to pass the SLAPI_DUMP_NOOPATTRS
  943. * option to slapi_entry2str_with_options() so that operational
  944. * attributes were NOT stored in the DSE LDIF files. But now
  945. * we store all attribute types.
  946. */
  947. if (( s = slapi_entry2str_with_options( ec, &len, 0 )) != NULL )
  948. {
  949. if ( slapi_write_buffer( fpw->fpw_prfd, s, len ) != len )
  950. {
  951. fpw->fpw_rc = PR_GetOSError();;
  952. slapi_ch_free((void **) &s);
  953. return STOP_TRAVERSAL;
  954. }
  955. if ( slapi_write_buffer( fpw->fpw_prfd, "\n", 1 ) != 1 )
  956. {
  957. fpw->fpw_rc = PR_GetOSError();;
  958. slapi_ch_free((void **) &s);
  959. return STOP_TRAVERSAL;
  960. }
  961. slapi_ch_free((void **) &s);
  962. }
  963. }
  964. slapi_entry_free(ec);
  965. }
  966. return 0;
  967. }
  968. /*
  969. * Adds an entry to the dse backend. The passed in entry will be
  970. * free'd upon success. If we don't return 0, the caller is responsible
  971. * for freeing the entry.
  972. */
  973. static int
  974. dse_add_entry_pb(struct dse* pdse, Slapi_Entry *e, Slapi_PBlock *pb)
  975. {
  976. int dont_write_file = 0, merge = 0; /* defaults */
  977. int rc= 0;
  978. struct dse_node *n = dse_node_new(e); /* copies e */
  979. Slapi_Entry *schemacheckentry= NULL; /* to use for schema checking */
  980. PR_ASSERT(pb);
  981. slapi_pblock_get(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &dont_write_file);
  982. slapi_pblock_get(pb, SLAPI_DSE_MERGE_WHEN_ADDING, &merge);
  983. /* keep write lock during both tree update and file write operations */
  984. if (pdse->dse_rwlock)
  985. PR_RWLock_Wlock(pdse->dse_rwlock);
  986. if (merge)
  987. {
  988. rc= avl_insert( &(pdse->dse_tree), n, entry_dn_cmp, dupentry_merge );
  989. }
  990. else
  991. {
  992. rc= avl_insert( &(pdse->dse_tree), n, entry_dn_cmp, dupentry_disallow );
  993. }
  994. if (-1 != rc) {
  995. /* update num sub of parent with no lock; we already hold the write lock */
  996. if (0 == rc) { /* entry was added, not merged; update numsub */
  997. dse_updateNumSubOfParent(pdse, slapi_entry_get_sdn_const(e),
  998. SLAPI_OPERATION_ADD);
  999. } else { /* entry was merged, free temp unused data */
  1000. dse_node_delete(&n);
  1001. }
  1002. if (!dont_write_file) {
  1003. dse_write_file_nolock(pdse);
  1004. }
  1005. } else { /* duplicate entry ignored */
  1006. dse_node_delete(&n); /* This also deletes the contained entry */
  1007. }
  1008. if (pdse->dse_rwlock)
  1009. PR_RWLock_Unlock(pdse->dse_rwlock);
  1010. if (rc == -1)
  1011. {
  1012. /* duplicate entry ignored */
  1013. schemacheckentry = dse_get_entry_copy( pdse,
  1014. slapi_entry_get_sdn_const(e),
  1015. DSE_USE_LOCK );
  1016. }
  1017. else /* entry added or merged */
  1018. {
  1019. /* entry was added or merged */
  1020. if (0 == rc) /* 0 return means entry was added, not merged */
  1021. {
  1022. /* save a search of the tree, since we added the entry, the
  1023. contents of e should be the same as what is in the tree */
  1024. schemacheckentry = slapi_entry_dup(e);
  1025. }
  1026. else /* merged */
  1027. {
  1028. /* schema check the new merged entry, so get it from the tree */
  1029. schemacheckentry = dse_get_entry_copy( pdse,
  1030. slapi_entry_get_sdn_const(e),
  1031. DSE_USE_LOCK );
  1032. }
  1033. }
  1034. if ( NULL != schemacheckentry )
  1035. {
  1036. /*
  1037. * Verify that the new or merged entry conforms to the schema.
  1038. * Errors are logged by slapi_entry_schema_check().
  1039. */
  1040. (void)slapi_entry_schema_check( pb, schemacheckentry );
  1041. slapi_entry_free(schemacheckentry);
  1042. }
  1043. /* Callers expect e (SLAPI_ADD_ENTRY) to be freed or otherwise
  1044. * consumed if the add was successful. */
  1045. if (rc == 0) {
  1046. slapi_entry_free(e);
  1047. }
  1048. return rc;
  1049. }
  1050. /*
  1051. * Local function for comparing two entries by DN. Store the entries
  1052. * so that when they are printed out, the child entries are below their
  1053. * ancestor entries
  1054. */
  1055. static int
  1056. entry_dn_cmp( caddr_t d1, caddr_t d2 )
  1057. {
  1058. struct dse_node *n1 = (struct dse_node *)d1;
  1059. struct dse_node *n2 = (struct dse_node *)d2;
  1060. const Slapi_DN *dn1 = slapi_entry_get_sdn_const(n1->entry);
  1061. const Slapi_DN *dn2 = slapi_entry_get_sdn_const(n2->entry);
  1062. int retval = slapi_sdn_compare(dn1, dn2);
  1063. if (retval != 0)
  1064. {
  1065. if (slapi_sdn_issuffix(dn1, dn2))
  1066. {
  1067. retval = 1;
  1068. }
  1069. else if (slapi_sdn_issuffix(dn2, dn1))
  1070. {
  1071. retval = -1;
  1072. }
  1073. else
  1074. {
  1075. /* put fewer rdns before more rdns */
  1076. int rc = 0;
  1077. char **dnlist1 = ldap_explode_dn(slapi_sdn_get_ndn(dn1), 0);
  1078. char **dnlist2 = ldap_explode_dn(slapi_sdn_get_ndn(dn2), 0);
  1079. int len1 = 0;
  1080. int len2 = 0;
  1081. if (dnlist1)
  1082. for (len1 = 0; dnlist1[len1]; ++len1);
  1083. if (dnlist2)
  1084. for (len2 = 0; dnlist2[len2]; ++len2);
  1085. if (len1 == len2)
  1086. {
  1087. len1--;
  1088. for (; (rc == 0) && (len1 >= 0); --len1)
  1089. {
  1090. rc = strcmp(dnlist1[len1], dnlist2[len1]);
  1091. }
  1092. if (rc)
  1093. retval = rc;
  1094. }
  1095. else
  1096. retval = len1 - len2;
  1097. if (dnlist1)
  1098. slapi_ldap_value_free(dnlist1);
  1099. if (dnlist2)
  1100. slapi_ldap_value_free(dnlist2);
  1101. }
  1102. }
  1103. /* else entries are equal if dns are equal */
  1104. return retval;
  1105. }
  1106. static int
  1107. dupentry_disallow( caddr_t d1, caddr_t d2 )
  1108. {
  1109. return -1;
  1110. }
  1111. static int
  1112. dupentry_replace( caddr_t d1, caddr_t d2 )
  1113. {
  1114. /*
  1115. * Hack attack: since we don't have the address of the pointer
  1116. * in the avl node, we have to replace the e_dn and e_attrs
  1117. * members of the entry which is in the AVL tree with our
  1118. * new entry DN and attrs. We then point the "new" entry's
  1119. * e_dn and e_attrs pointers to point to the values we just
  1120. * replaced, on the assumption that the caller will be freeing
  1121. * these.
  1122. */
  1123. struct dse_node *n1 = (struct dse_node *)d1; /* OLD */
  1124. struct dse_node *n2 = (struct dse_node *)d2; /* NEW */
  1125. Slapi_Entry *e= n1->entry;
  1126. n1->entry= n2->entry;
  1127. n2->entry= e;
  1128. return DSE_ENTRY_WAS_REPLACED;
  1129. }
  1130. static int
  1131. dupentry_merge( caddr_t d1, caddr_t d2 )
  1132. {
  1133. struct dse_node *n1 = (struct dse_node *)d1; /* OLD */
  1134. struct dse_node *n2 = (struct dse_node *)d2; /* NEW */
  1135. Slapi_Entry *e1= n1->entry;
  1136. Slapi_Entry *e2= n2->entry;
  1137. int rc = 0;
  1138. Slapi_Attr *newattr = 0;
  1139. for (rc = slapi_entry_first_attr(e2, &newattr);
  1140. !rc && newattr;
  1141. rc = slapi_entry_next_attr(e2, newattr, &newattr)) {
  1142. char *type = 0;
  1143. slapi_attr_get_type(newattr, &type);
  1144. if (type) {
  1145. /* insure there are no duplicate values in e1 */
  1146. rc = slapi_entry_merge_values_sv(e1, type,
  1147. attr_get_present_values(newattr));
  1148. }
  1149. }
  1150. return DSE_ENTRY_WAS_MERGED;
  1151. }
  1152. /*
  1153. * Add an entry to the DSE without locking the DSE avl tree.
  1154. * Replaces the entry if it already exists.
  1155. *
  1156. * The given entry e is never consumed. It is the responsibility of the
  1157. * caller to free it when it is no longer needed.
  1158. *
  1159. * The write_file flag is used if we want to update the entry in memory
  1160. * but we do not want to write out the file. For example, if we update
  1161. * the numsubordinates in the entry, this is an operational attribute that
  1162. * we do not want saved to disk.
  1163. */
  1164. static int
  1165. dse_replace_entry( struct dse* pdse, Slapi_Entry *e, int write_file, int use_lock )
  1166. {
  1167. int rc= -1;
  1168. if ( NULL != e )
  1169. {
  1170. struct dse_node *n= dse_node_new(e);
  1171. if (use_lock && pdse->dse_rwlock)
  1172. PR_RWLock_Wlock(pdse->dse_rwlock);
  1173. rc = avl_insert( &(pdse->dse_tree), n, entry_dn_cmp, dupentry_replace );
  1174. if (write_file)
  1175. dse_write_file_nolock(pdse);
  1176. /* If the entry was replaced i.e. not added as a new entry, we need to
  1177. free the old data, which is set in dupentry_replace */
  1178. if (DSE_ENTRY_WAS_REPLACED == rc) {
  1179. dse_node_delete(&n);
  1180. rc = 0; /* for return to caller */
  1181. }
  1182. if (use_lock && pdse->dse_rwlock)
  1183. PR_RWLock_Unlock(pdse->dse_rwlock);
  1184. }
  1185. return rc;
  1186. }
  1187. /*
  1188. * Return -1 if p does not point to a valid LDIF
  1189. * end-of-record delimiter (a NULL, two newlines, or two
  1190. * pairs of CRLF). Otherwise, return the length of
  1191. * the delimiter found.
  1192. */
  1193. static int
  1194. ldif_record_end( char *p )
  1195. {
  1196. if ( NULL != p )
  1197. {
  1198. if ( '\0' == *p )
  1199. {
  1200. return 0;
  1201. }
  1202. else if ( '\n' == *p && '\n' == *( p + 1 ))
  1203. {
  1204. return 2;
  1205. }
  1206. else if ( '\r' == *p && '\n' == *( p + 1 ) && '\r' == *( p + 2 ) && '\n' == *( p + 3 ))
  1207. {
  1208. return 4;
  1209. }
  1210. }
  1211. return -1;
  1212. }
  1213. char *
  1214. dse_read_next_entry( char *buf, char **lastp )
  1215. {
  1216. char *p, *start;
  1217. if ( NULL == buf )
  1218. {
  1219. *lastp = NULL;
  1220. return NULL;
  1221. }
  1222. p = start = ( NULL == *lastp ) ? buf : *lastp;
  1223. /* Skip over any leading record delimiters */
  1224. while ( '\n' == *p || '\r' == *p )
  1225. {
  1226. p++;
  1227. }
  1228. if ( '\0' == *p )
  1229. {
  1230. *lastp = NULL;
  1231. return NULL;
  1232. }
  1233. while ( '\0' != *p )
  1234. {
  1235. int rc;
  1236. if (( rc = ldif_record_end( p )) >= 0 )
  1237. {
  1238. /* Found end of LDIF record */
  1239. *p = '\0';
  1240. p += rc;
  1241. break;
  1242. }
  1243. else
  1244. {
  1245. p++;
  1246. }
  1247. }
  1248. *lastp = p;
  1249. return start;
  1250. }
  1251. /*
  1252. * Apply the function to each entry. The caller is responsible for locking
  1253. * the rwlock in the dse for the appropriate type of operation e.g. for
  1254. * searching, a read lock, for modifying in place, a write lock
  1255. */
  1256. static int
  1257. dse_apply_nolock(struct dse* pdse,IFP fp,caddr_t arg)
  1258. {
  1259. avl_apply( pdse->dse_tree, fp, arg, STOP_TRAVERSAL, AVL_INORDER );
  1260. return 1;
  1261. }
  1262. /*
  1263. * Remove the entry from the tree.
  1264. * Returns 1 if entry is removed and 0 if not.
  1265. */
  1266. static int
  1267. dse_delete_entry(struct dse* pdse, Slapi_PBlock *pb, const Slapi_Entry *e)
  1268. {
  1269. int dont_write_file = 0;
  1270. struct dse_node *n= dse_node_new(e);
  1271. struct dse_node *deleted_node = NULL;
  1272. slapi_pblock_get(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &dont_write_file);
  1273. /* keep write lock for both tree deleting and file writing */
  1274. if (pdse->dse_rwlock)
  1275. PR_RWLock_Wlock(pdse->dse_rwlock);
  1276. if ((deleted_node = (struct dse_node *)avl_delete(&pdse->dse_tree,
  1277. n, entry_dn_cmp)))
  1278. dse_node_delete(&deleted_node);
  1279. dse_node_delete(&n);
  1280. if (!dont_write_file)
  1281. {
  1282. /* Decrement the numsubordinate count of the parent entry */
  1283. dse_updateNumSubOfParent(pdse, slapi_entry_get_sdn_const(e),
  1284. SLAPI_OPERATION_DELETE);
  1285. dse_write_file_nolock(pdse);
  1286. }
  1287. if (pdse->dse_rwlock)
  1288. PR_RWLock_Unlock(pdse->dse_rwlock);
  1289. return 1;
  1290. }
  1291. /*
  1292. * Returns a SLAPI_BIND_xxx retun code.
  1293. */
  1294. int
  1295. dse_bind( Slapi_PBlock *pb ) /* JCM There should only be one exit point from this function! */
  1296. {
  1297. char *dn; /* The bind DN */
  1298. int method; /* The bind method */
  1299. struct berval *cred; /* The bind credentials */
  1300. Slapi_Value **bvals;
  1301. struct dse* pdse;
  1302. Slapi_Attr *attr;
  1303. Slapi_DN sdn;
  1304. Slapi_Entry *ec= NULL;
  1305. /*Get the parameters*/
  1306. if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &pdse ) < 0 ||
  1307. slapi_pblock_get( pb, SLAPI_BIND_TARGET, &dn ) < 0 ||
  1308. slapi_pblock_get( pb, SLAPI_BIND_METHOD, &method ) < 0 ||
  1309. slapi_pblock_get( pb, SLAPI_BIND_CREDENTIALS, &cred ) < 0){
  1310. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1311. return SLAPI_BIND_FAIL;
  1312. }
  1313. /* always allow noauth simple binds */
  1314. if ( method == LDAP_AUTH_SIMPLE && cred->bv_len == 0 )
  1315. {
  1316. /*
  1317. * report success to client, but return
  1318. * SLAPI_BIND_FAIL so we don't
  1319. * authorize based on noauth credentials
  1320. */
  1321. slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, NULL, 0, NULL );
  1322. return( SLAPI_BIND_FAIL );
  1323. }
  1324. /* Find the entry that the person is attempting to bind as */
  1325. slapi_sdn_init_dn_byref(&sdn,dn);
  1326. ec = dse_get_entry_copy(pdse,&sdn,DSE_USE_LOCK);
  1327. if ( ec == NULL )
  1328. {
  1329. slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
  1330. slapi_sdn_done(&sdn);
  1331. return( SLAPI_BIND_FAIL );
  1332. }
  1333. switch ( method )
  1334. {
  1335. case LDAP_AUTH_SIMPLE:
  1336. {
  1337. Slapi_Value cv;
  1338. if ( slapi_entry_attr_find( ec, "userpassword", &attr ) != 0 )
  1339. {
  1340. slapi_send_ldap_result( pb, LDAP_INAPPROPRIATE_AUTH, NULL, NULL, 0, NULL );
  1341. slapi_entry_free(ec);
  1342. slapi_sdn_done(&sdn);
  1343. return SLAPI_BIND_FAIL;
  1344. }
  1345. bvals= attr_get_present_values( attr );
  1346. slapi_value_init_berval(&cv,cred);
  1347. if ( slapi_pw_find_sv( bvals, &cv ) != 0 )
  1348. {
  1349. slapi_send_ldap_result( pb, LDAP_INVALID_CREDENTIALS, NULL, NULL, 0, NULL );
  1350. slapi_entry_free(ec);
  1351. slapi_sdn_done(&sdn);
  1352. value_done(&cv);
  1353. return SLAPI_BIND_FAIL;
  1354. }
  1355. value_done(&cv);
  1356. }
  1357. break;
  1358. default:
  1359. slapi_send_ldap_result( pb, LDAP_STRONG_AUTH_NOT_SUPPORTED, NULL, "auth method not supported", 0, NULL );
  1360. slapi_entry_free(ec);
  1361. slapi_sdn_done(&sdn);
  1362. return SLAPI_BIND_FAIL;
  1363. }
  1364. slapi_entry_free(ec);
  1365. slapi_sdn_done(&sdn);
  1366. /* success: front end will send result */
  1367. return SLAPI_BIND_SUCCESS;
  1368. }
  1369. int
  1370. dse_unbind( Slapi_PBlock *pb )
  1371. {
  1372. return 0;
  1373. }
  1374. /*
  1375. * This structure is simply to pass parameters to dse_search_filter_entry.
  1376. */
  1377. struct magicSearchStuff
  1378. {
  1379. Slapi_PBlock *pb;
  1380. struct dse *pdse;
  1381. int scope;
  1382. const Slapi_DN *basedn;
  1383. Slapi_Filter *filter;
  1384. int nentries;
  1385. char **attrs; /*Attributes*/
  1386. int attrsonly; /*Should we just return the attributes found?*/
  1387. dse_search_set *ss; /* for the temporary results - to pass to the dse search callbacks */
  1388. };
  1389. /*
  1390. * The function which is called on each node of the AVL tree.
  1391. */
  1392. static int
  1393. dse_search_filter_entry(caddr_t data, caddr_t arg)
  1394. {
  1395. struct dse_node *n = (struct dse_node *)data;
  1396. struct magicSearchStuff *p= (struct magicSearchStuff *)arg;
  1397. if(slapi_sdn_scope_test( slapi_entry_get_sdn_const(n->entry), p->basedn, p->scope))
  1398. {
  1399. if(slapi_vattr_filter_test( p->pb, n->entry, p->filter, 1 /* verify access */ )==0)
  1400. {
  1401. Slapi_Entry *ec = slapi_entry_dup( n->entry );
  1402. p->nentries++;
  1403. if (!p->ss)
  1404. {
  1405. p->ss = dse_search_set_new();
  1406. }
  1407. dse_search_set_add_entry(p->ss, ec); /* consumes the entry */
  1408. } else {
  1409. /*
  1410. slapd_log_error_proc("dse_search_filter_entry",
  1411. "filter test failed: dn %s did not match filter %d\n",
  1412. slapi_entry_get_dn_const(n->entry), p->filter->f_choice);
  1413. */
  1414. }
  1415. } else {
  1416. /*
  1417. slapd_log_error_proc("dse_search_filter_entry",
  1418. "scope test failed: dn %s is not in scope %d of dn [%s]\n",
  1419. slapi_entry_get_dn_const(n->entry), p->scope,
  1420. slapi_sdn_get_dn(p->basedn));
  1421. */
  1422. }
  1423. return 0;
  1424. }
  1425. /*
  1426. * The function which kicks off the traversal of the AVL tree.
  1427. * Returns the number of entries returned.
  1428. */
  1429. /* jcm: Not very efficient if there are many DSE entries. */
  1430. /* jcm: It applies the filter to every node in the tree regardless */
  1431. static int
  1432. do_dse_search(struct dse* pdse, Slapi_PBlock *pb, int scope, const Slapi_DN *basedn, Slapi_Filter *filter, char **attrs, int attrsonly)
  1433. {
  1434. struct magicSearchStuff stuff;
  1435. stuff.pb= pb;
  1436. stuff.pdse= pdse;
  1437. stuff.scope= scope;
  1438. stuff.basedn= basedn;
  1439. stuff.filter= filter;
  1440. stuff.nentries= 0;
  1441. stuff.attrs= attrs;
  1442. stuff.attrsonly= attrsonly;
  1443. stuff.ss = NULL;
  1444. /*
  1445. * If this is a persistent search and the client is only interested in
  1446. * entries that change, we skip looking through the DSE entries.
  1447. */
  1448. if ( pb->pb_op == NULL
  1449. || !operation_is_flag_set( pb->pb_op, OP_FLAG_PS_CHANGESONLY )) {
  1450. if (pdse->dse_rwlock)
  1451. PR_RWLock_Rlock(pdse->dse_rwlock);
  1452. dse_apply_nolock(pdse,dse_search_filter_entry,(caddr_t)&stuff);
  1453. if (pdse->dse_rwlock)
  1454. PR_RWLock_Unlock(pdse->dse_rwlock);
  1455. }
  1456. if (stuff.ss) /* something was found which matched our criteria */
  1457. {
  1458. Slapi_Entry *e = NULL;
  1459. for (e = dse_search_set_get_next_entry(stuff.ss);
  1460. e;
  1461. e = dse_search_set_get_next_entry(stuff.ss))
  1462. {
  1463. int returncode = 0;
  1464. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= "";
  1465. if(dse_call_callback(pdse, pb, SLAPI_OPERATION_SEARCH,
  1466. DSE_FLAG_PREOP, e, NULL, &returncode, returntext)
  1467. == SLAPI_DSE_CALLBACK_OK)
  1468. {
  1469. dse_search_set *ss = NULL;
  1470. slapi_pblock_get (pb, SLAPI_SEARCH_RESULT_SET, &ss);
  1471. /* if this is the first entry - allocate dse_search_set structure */
  1472. if (ss == NULL)
  1473. {
  1474. ss = dse_search_set_new ();
  1475. slapi_pblock_set (pb, SLAPI_SEARCH_RESULT_SET, ss);
  1476. }
  1477. /* make another reference to e (stuff.ss references it too)
  1478. the stuff.ss reference is removed by dse_search_set_clean()
  1479. below, leaving ss as the sole owner of the memory */
  1480. dse_search_set_add_entry(ss, e);
  1481. } else {
  1482. stuff.nentries--; /* rejected entry */
  1483. /* this leaves a freed pointer in stuff.ss, but that's ok because
  1484. it should never be referenced, and the reference is removed by
  1485. the call to dse_search_set_clean() below */
  1486. slapi_entry_free(e);
  1487. }
  1488. }
  1489. dse_search_set_clean(stuff.ss);
  1490. }
  1491. /* the pblock ss now contains the "real" search result set and the copies of
  1492. the entries allocated in dse_search_filter_entry; any entries rejected by
  1493. the search callback were freed above by the call to slapi_entry_free() */
  1494. return stuff.nentries;
  1495. }
  1496. /*
  1497. * -1 means something went wrong.
  1498. * 0 means everything went ok.
  1499. */
  1500. int
  1501. dse_search(Slapi_PBlock *pb) /* JCM There should only be one exit point from this function! */
  1502. {
  1503. char *base; /*Base of the search*/
  1504. int scope; /*Scope of the search*/
  1505. Slapi_Filter *filter; /*The filter*/
  1506. char **attrs; /*Attributes*/
  1507. int attrsonly; /*Should we just return the attributes found?*/
  1508. /*int nentries= 0; Number of entries found thus far*/
  1509. struct dse* pdse;
  1510. int returncode= LDAP_SUCCESS;
  1511. int isrootdse= 0;
  1512. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= "";
  1513. Slapi_DN basesdn;
  1514. /*
  1515. * Get private information created in the init routine.
  1516. * Also get the parameters of the search operation. These come
  1517. * more or less directly from the client.
  1518. */
  1519. if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &pdse ) < 0 ||
  1520. slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &base ) < 0 ||
  1521. slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope ) < 0 ||
  1522. slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter ) < 0 ||
  1523. slapi_pblock_get( pb, SLAPI_SEARCH_ATTRS, &attrs ) < 0 ||
  1524. slapi_pblock_get( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly ) <0)
  1525. {
  1526. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1527. return(-1);
  1528. }
  1529. slapi_sdn_init_dn_byref(&basesdn,base);
  1530. /*
  1531. * Sadly the root dse is still a special case. We must not allow
  1532. * acl checks on it, or allow onelevel or subtree searches on it.
  1533. */
  1534. isrootdse= slapi_sdn_isempty(&basesdn);
  1535. switch(scope)
  1536. {
  1537. case LDAP_SCOPE_BASE:
  1538. {
  1539. Slapi_Entry *baseentry= NULL;
  1540. baseentry = dse_get_entry_copy(pdse,&basesdn,DSE_USE_LOCK);
  1541. if ( baseentry == NULL )
  1542. {
  1543. slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
  1544. slapi_log_error(SLAPI_LOG_PLUGIN,"dse_search", "node %s was not found\n",
  1545. slapi_sdn_get_dn(&basesdn));
  1546. slapi_sdn_done(&basesdn);
  1547. return -1;
  1548. }
  1549. /*
  1550. * We don't want to do an acl check for the root dse... because the acl
  1551. * code thinks it's a suffix of every target... so every acl applies to
  1552. * the root dse... which is wrong.
  1553. */
  1554. if(slapi_vattr_filter_test( pb, baseentry, filter, !isrootdse /* verify access */ )==0)
  1555. {
  1556. /* Callbacks modify a copy of the entry */
  1557. if(dse_call_callback(pdse, pb, SLAPI_OPERATION_SEARCH,
  1558. DSE_FLAG_PREOP, baseentry, NULL, &returncode, returntext)
  1559. == SLAPI_DSE_CALLBACK_OK)
  1560. {
  1561. dse_search_set *ss;
  1562. ss = dse_search_set_new ();
  1563. slapi_pblock_set (pb, SLAPI_SEARCH_RESULT_SET, ss);
  1564. dse_search_set_add_entry (ss, baseentry); /* consumes the entry */
  1565. baseentry= NULL;
  1566. }
  1567. }
  1568. slapi_entry_free(baseentry);
  1569. }
  1570. break;
  1571. case LDAP_SCOPE_ONELEVEL:
  1572. /* FALL THROUGH */
  1573. case LDAP_SCOPE_SUBTREE:
  1574. if(!isrootdse)
  1575. {
  1576. do_dse_search(pdse, pb, scope, &basesdn, filter, attrs, attrsonly);
  1577. }
  1578. break;
  1579. }
  1580. /* Search is done, send LDAP_SUCCESS */
  1581. slapi_sdn_done(&basesdn);
  1582. return 0;
  1583. }
  1584. /*
  1585. * -1 means something went wrong.
  1586. * 0 means everything went ok.
  1587. */
  1588. static int
  1589. dse_modify_return( int rv, Slapi_Entry *ec, Slapi_Entry *ecc )
  1590. {
  1591. slapi_entry_free(ec);
  1592. slapi_entry_free(ecc);
  1593. return rv;
  1594. }
  1595. int
  1596. dse_modify(Slapi_PBlock *pb) /* JCM There should only be one exit point from this function! */
  1597. {
  1598. int err; /*House keeping stuff*/
  1599. LDAPMod **mods; /*Used to apply the modifications*/
  1600. char *dn; /*Storage for the dn*/
  1601. char *errbuf = NULL; /* To get error back */
  1602. struct dse* pdse;
  1603. Slapi_Entry *ec= NULL;
  1604. Slapi_Entry *ecc= NULL;
  1605. int returncode= LDAP_SUCCESS;
  1606. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= "";
  1607. Slapi_DN sdn;
  1608. int dont_write_file = 0; /* default */
  1609. PR_ASSERT(pb);
  1610. if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &pdse ) < 0 ||
  1611. slapi_pblock_get( pb, SLAPI_MODIFY_TARGET, &dn ) < 0 ||
  1612. slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods ) < 0 || (NULL == pdse))
  1613. {
  1614. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1615. return( -1 );
  1616. }
  1617. slapi_pblock_get(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &dont_write_file);
  1618. if ( !dont_write_file && dse_check_for_readonly_error(pb,pdse)) {
  1619. return( -1 );
  1620. }
  1621. slapi_sdn_init_dn_byref(&sdn,dn);
  1622. /* Find the entry we are about to modify. */
  1623. ec = dse_get_entry_copy(pdse,&sdn,DSE_USE_LOCK);
  1624. if ( ec == NULL )
  1625. {
  1626. slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
  1627. slapi_sdn_done(&sdn);
  1628. return dse_modify_return( -1, ec, ecc );
  1629. }
  1630. /* Check acl */
  1631. err = plugin_call_acl_mods_access ( pb, ec, mods, &errbuf );
  1632. if ( err != LDAP_SUCCESS )
  1633. {
  1634. slapi_send_ldap_result( pb, err, NULL, errbuf, 0, NULL );
  1635. if (errbuf) slapi_ch_free ((void**)&errbuf);
  1636. slapi_sdn_done(&sdn);
  1637. return dse_modify_return( -1, ec, ecc );
  1638. }
  1639. /* Save away a copy of the entry, before modifications */
  1640. slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( ec )); /* JCM - When does this get free'd? */
  1641. /* richm - it is freed in modify.c */
  1642. /* Modify a copy of the entry*/
  1643. ecc = slapi_entry_dup( ec );
  1644. err = entry_apply_mods( ecc, mods );
  1645. /* XXXmcs: should we expand objectclass values here?? */
  1646. switch(dse_call_callback(pdse, pb, SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, ec, ecc, &returncode, returntext))
  1647. {
  1648. case SLAPI_DSE_CALLBACK_ERROR:
  1649. {
  1650. /* Error occured in the callback -- return error code from callback */
  1651. slapi_send_ldap_result( pb, returncode, NULL, returntext, 0, NULL );
  1652. slapi_sdn_done(&sdn);
  1653. return dse_modify_return( -1, ec, ecc );
  1654. }
  1655. case SLAPI_DSE_CALLBACK_DO_NOT_APPLY:
  1656. {
  1657. /* Callback says don't apply the changes -- return Success */
  1658. slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, NULL, 0, NULL );
  1659. slapi_sdn_done(&sdn);
  1660. return dse_modify_return( 0, ec, ecc );
  1661. }
  1662. case SLAPI_DSE_CALLBACK_OK:
  1663. {
  1664. /* The callback may alter the mods in the pblock. This happens
  1665. for example in the schema code. Since the schema attributes
  1666. are managed exclusively by the schema code, we should not
  1667. apply those mods. However, for reasons unknown to me, we
  1668. must in the general case call entry_apply_mods before calling
  1669. the modify callback above. In the case of schema, the schema
  1670. code will remove the schema attributes from the mods. So, we
  1671. reapply the mods to the entry for the attributes we manage in
  1672. the dse code (e.g. aci)
  1673. */
  1674. int reapply_mods = 0; /* default is to not reapply entry_apply_mods */
  1675. slapi_pblock_get(pb, SLAPI_DSE_REAPPLY_MODS, &reapply_mods);
  1676. /* Callback says apply the changes */
  1677. if ( reapply_mods )
  1678. {
  1679. LDAPMod **modsagain = NULL; /*Used to apply the modifications*/
  1680. slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &modsagain );
  1681. if (NULL != modsagain)
  1682. {
  1683. /* the dse modify callback must have modified ecc back to it's
  1684. original state, before the earlier apply_mods, but without the
  1685. attributes it did not want us to apply mods to */
  1686. err = entry_apply_mods( ecc, modsagain );
  1687. }
  1688. }
  1689. if (err != 0)
  1690. {
  1691. /* entry_apply_mods() failed above, so return an error now */
  1692. slapi_send_ldap_result( pb, err, NULL, NULL, 0, NULL );
  1693. slapi_sdn_done(&sdn);
  1694. return dse_modify_return( -1, ec, ecc );
  1695. }
  1696. break;
  1697. }
  1698. }
  1699. /* We're applying the mods... check that the entry still obeys the schema */
  1700. if ( slapi_entry_schema_check( pb, ecc ) != 0 )
  1701. {
  1702. char *errtext;
  1703. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &errtext);
  1704. slapi_send_ldap_result( pb, LDAP_OBJECT_CLASS_VIOLATION, NULL, errtext, 0, NULL );
  1705. slapi_sdn_done(&sdn);
  1706. return dse_modify_return( -1, ec, ecc );
  1707. }
  1708. /* Check if the attribute values in the mods obey the syntaxes */
  1709. if ( slapi_mods_syntax_check( pb, mods, 0 ) != 0 )
  1710. {
  1711. char *errtext;
  1712. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &errtext);
  1713. slapi_send_ldap_result( pb, LDAP_INVALID_SYNTAX, NULL, errtext, 0, NULL );
  1714. slapi_sdn_done(&sdn);
  1715. return dse_modify_return( -1, ec, ecc );
  1716. }
  1717. /* Change the entry itself both on disk and in the AVL tree */
  1718. /* dse_replace_entry free's the existing entry. */
  1719. if (dse_replace_entry( pdse, ecc, !dont_write_file, DSE_USE_LOCK )!=0 )
  1720. {
  1721. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1722. slapi_sdn_done(&sdn);
  1723. return dse_modify_return( -1, ec, ecc );
  1724. }
  1725. slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, slapi_entry_dup(ecc) ); /* JCM - When does this get free'd? */
  1726. /* richm - it is freed in modify.c */
  1727. dse_call_callback(pdse, pb, SLAPI_OPERATION_MODIFY, DSE_FLAG_POSTOP, ec, ecc, &returncode, returntext);
  1728. slapi_send_ldap_result( pb, returncode, NULL, returntext, 0, NULL );
  1729. slapi_sdn_done(&sdn);
  1730. return dse_modify_return(0, ec, ecc);
  1731. }
  1732. static int
  1733. dse_add_return( int rv, Slapi_Entry *e)
  1734. {
  1735. slapi_entry_free(e);
  1736. return rv;
  1737. }
  1738. /*
  1739. * -1 means something went wrong.
  1740. * 0 means everything went ok.
  1741. */
  1742. int
  1743. dse_add(Slapi_PBlock *pb) /* JCM There should only be one exit point from this function! */
  1744. {
  1745. char *dn = NULL;
  1746. Slapi_Entry *e; /*The new entry to add*/
  1747. Slapi_Entry *e_copy = NULL; /* copy of added entry */
  1748. char *errbuf = NULL;
  1749. int rc = LDAP_SUCCESS;
  1750. int error = -1;
  1751. int dont_write_file = 0; /* default */
  1752. struct dse* pdse;
  1753. int returncode= LDAP_SUCCESS;
  1754. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= "";
  1755. Slapi_DN sdn;
  1756. Slapi_DN parent;
  1757. /*
  1758. * Get the database, the dn and the entry to add
  1759. */
  1760. if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &pdse ) < 0 ||
  1761. slapi_pblock_get( pb, SLAPI_ADD_TARGET, &dn ) < 0 ||
  1762. slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e ) < 0 || (NULL == pdse))
  1763. {
  1764. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1765. return error;
  1766. }
  1767. slapi_pblock_get(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &dont_write_file);
  1768. if ( !dont_write_file && dse_check_for_readonly_error(pb,pdse)) {
  1769. return( error );
  1770. }
  1771. slapi_sdn_init_dn_byref(&sdn,dn);
  1772. /*
  1773. * Check to make sure the entry passes the schema check
  1774. */
  1775. if ( slapi_entry_schema_check( pb, e ) != 0 )
  1776. {
  1777. char *errtext;
  1778. LDAPDebug( SLAPI_DSE_TRACELEVEL,
  1779. "dse_add: entry failed schema check\n", 0, 0, 0 );
  1780. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &errtext);
  1781. slapi_send_ldap_result( pb, LDAP_OBJECT_CLASS_VIOLATION, NULL, errtext, 0, NULL );
  1782. slapi_sdn_done(&sdn);
  1783. return error;
  1784. }
  1785. /* Check if the attribute values in the entry obey the syntaxes */
  1786. if ( slapi_entry_syntax_check( pb, e, 0 ) != 0 )
  1787. {
  1788. char *errtext;
  1789. LDAPDebug( SLAPI_DSE_TRACELEVEL,
  1790. "dse_add: entry failed syntax check\n", 0, 0, 0 );
  1791. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &errtext);
  1792. slapi_send_ldap_result( pb, LDAP_INVALID_SYNTAX, NULL, errtext, 0, NULL );
  1793. slapi_sdn_done(&sdn);
  1794. return error;
  1795. }
  1796. /*
  1797. * Attempt to find this dn.
  1798. */
  1799. {
  1800. Slapi_Entry *existingentry= dse_get_entry_copy( pdse, &sdn, DSE_USE_LOCK );
  1801. if(existingentry!=NULL)
  1802. {
  1803. /*
  1804. * If we've reached this code, there is an entry
  1805. * whose dn matches dn, so tell the user and return
  1806. */
  1807. slapi_send_ldap_result( pb, LDAP_ALREADY_EXISTS, NULL, NULL, 0, NULL );
  1808. slapi_sdn_done(&sdn);
  1809. slapi_entry_free(existingentry);
  1810. return dse_add_return(error, NULL);
  1811. }
  1812. }
  1813. /*
  1814. * Get the parent dn and see if the corresponding entry exists.
  1815. * If the parent does not exist, only allow the "root" user to
  1816. * add the entry.
  1817. */
  1818. slapi_sdn_init(&parent);
  1819. slapi_sdn_get_parent(&sdn,&parent);
  1820. if ( !slapi_sdn_isempty(&parent) )
  1821. {
  1822. Slapi_Entry *parententry= NULL;
  1823. parententry= dse_get_entry_copy( pdse, &parent, DSE_USE_LOCK );
  1824. if( parententry==NULL )
  1825. {
  1826. slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
  1827. LDAPDebug( SLAPI_DSE_TRACELEVEL, "dse_add: parent does not exist\n", 0, 0, 0 );
  1828. slapi_sdn_done(&sdn);
  1829. slapi_sdn_done(&parent);
  1830. return dse_add_return(error, NULL);
  1831. }
  1832. rc= plugin_call_acl_plugin ( pb, parententry, NULL, NULL, SLAPI_ACL_ADD, ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
  1833. slapi_entry_free(parententry);
  1834. if ( rc!=LDAP_SUCCESS )
  1835. {
  1836. LDAPDebug( SLAPI_DSE_TRACELEVEL, "dse_add: no access to parent\n", 0, 0, 0 );
  1837. slapi_send_ldap_result( pb, rc, NULL, NULL, 0, NULL );
  1838. slapi_ch_free((void**)&errbuf);
  1839. slapi_sdn_done(&sdn);
  1840. slapi_sdn_done(&parent);
  1841. return dse_add_return(rc, NULL);
  1842. }
  1843. }
  1844. else
  1845. {
  1846. /* no parent */
  1847. int isroot;
  1848. slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
  1849. if ( !isroot )
  1850. {
  1851. LDAPDebug( SLAPI_DSE_TRACELEVEL, "dse_add: no parent and not root\n", 0, 0, 0 );
  1852. slapi_send_ldap_result( pb, LDAP_INSUFFICIENT_ACCESS, NULL, NULL, 0, NULL );
  1853. slapi_sdn_done(&sdn);
  1854. slapi_sdn_done(&parent);
  1855. return dse_add_return(error, NULL);
  1856. }
  1857. }
  1858. slapi_sdn_done(&parent);
  1859. /*
  1860. * Before we add the entry, find out if the syntax of the aci
  1861. * aci attribute values are correct or not. We don't want to add
  1862. * the entry if the syntax is incorrect.
  1863. */
  1864. if ( plugin_call_acl_verify_syntax (pb, e, &errbuf) != 0 )
  1865. {
  1866. slapi_send_ldap_result( pb, LDAP_INVALID_SYNTAX, NULL, errbuf, 0, NULL );
  1867. slapi_ch_free((void**)&errbuf);
  1868. return dse_add_return(error, NULL);
  1869. }
  1870. if(dse_call_callback(pdse, pb, SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, e,
  1871. NULL, &returncode, returntext)!=SLAPI_DSE_CALLBACK_OK)
  1872. {
  1873. slapi_send_ldap_result( pb, returncode, NULL, returntext, 0, NULL );
  1874. slapi_sdn_done(&sdn);
  1875. return dse_add_return(error, NULL);
  1876. }
  1877. /* make copy for postop fns because add_entry_pb consumes e */
  1878. e_copy = slapi_entry_dup(e);
  1879. if ( dse_add_entry_pb(pdse, e, pb) != 0)
  1880. {
  1881. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1882. slapi_sdn_done(&sdn);
  1883. return dse_add_return(error, e_copy);
  1884. }
  1885. /* e has been consumed, so use the copy for the post ops */
  1886. slapi_pblock_set(pb, SLAPI_ADD_ENTRY, e_copy);
  1887. /* The postop must be called after the write lock is released. */
  1888. dse_call_callback(pdse, pb, SLAPI_OPERATION_ADD, DSE_FLAG_POSTOP, e_copy, NULL, &returncode, returntext);
  1889. /* We have been successful. Tell the user */
  1890. slapi_send_ldap_result( pb, returncode, NULL, NULL, 0, NULL );
  1891. slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, slapi_entry_dup( e_copy ));
  1892. /* entry has been freed, so make sure no one tries to use it later */
  1893. slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL);
  1894. /* Free the dn, and return */
  1895. slapi_sdn_done(&sdn);
  1896. return dse_add_return(rc, e_copy);
  1897. }
  1898. /*
  1899. * -1 means something went wrong.
  1900. * 0 means everything went ok.
  1901. */
  1902. static int
  1903. dse_delete_return( int rv, Slapi_Entry *ec)
  1904. {
  1905. slapi_entry_free(ec);
  1906. return rv;
  1907. }
  1908. int
  1909. dse_delete(Slapi_PBlock *pb) /* JCM There should only be one exit point from this function! */
  1910. {
  1911. char *dn = NULL;
  1912. int rc= -1;
  1913. int dont_write_file = 0; /* default */
  1914. struct dse* pdse = NULL;
  1915. int returncode= LDAP_SUCCESS;
  1916. char returntext[SLAPI_DSE_RETURNTEXT_SIZE]= "";
  1917. char *entry_str = "entry";
  1918. char *errbuf = NULL;
  1919. char *attrs[2] = { NULL, NULL };
  1920. Slapi_DN sdn;
  1921. Slapi_Entry *ec = NULL; /* copy of entry to delete */
  1922. /*
  1923. * Get the database and the dn
  1924. */
  1925. if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &pdse ) < 0 ||
  1926. slapi_pblock_get( pb, SLAPI_DELETE_TARGET, &dn ) < 0 || (pdse == NULL))
  1927. {
  1928. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  1929. return rc;
  1930. }
  1931. slapi_pblock_get(pb, SLAPI_DSE_DONT_WRITE_WHEN_ADDING, &dont_write_file);
  1932. if ( !dont_write_file && dse_check_for_readonly_error(pb,pdse)) {
  1933. return( rc );
  1934. }
  1935. slapi_sdn_init_dn_byref(&sdn,dn);
  1936. ec= dse_get_entry_copy( pdse, &sdn, DSE_USE_LOCK );
  1937. if (ec == NULL)
  1938. {
  1939. slapi_send_ldap_result( pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL );
  1940. slapi_sdn_done(&sdn);
  1941. return dse_delete_return( rc, ec );
  1942. }
  1943. /*
  1944. * Check if this node has any children.
  1945. */
  1946. if(dse_numsubordinates(ec)>0)
  1947. {
  1948. slapi_send_ldap_result( pb, LDAP_NOT_ALLOWED_ON_NONLEAF, NULL, NULL, 0, NULL );
  1949. slapi_sdn_done(&sdn);
  1950. return dse_delete_return( rc, ec );
  1951. }
  1952. /*
  1953. * Check the access
  1954. */
  1955. attrs[0] = entry_str;
  1956. attrs[1] = NULL;
  1957. returncode= plugin_call_acl_plugin ( pb, ec, attrs, NULL, SLAPI_ACL_DELETE, ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
  1958. if ( returncode!=LDAP_SUCCESS)
  1959. {
  1960. slapi_send_ldap_result( pb, returncode, NULL, NULL, 0, NULL );
  1961. slapi_ch_free ( (void**)&errbuf );
  1962. slapi_sdn_done(&sdn);
  1963. return dse_delete_return( rc, ec );
  1964. }
  1965. if(dse_call_callback(pdse, pb, SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, ec, NULL, &returncode,returntext)==SLAPI_DSE_CALLBACK_OK)
  1966. {
  1967. if(dse_delete_entry(pdse, pb, ec)==0)
  1968. {
  1969. returncode= LDAP_OPERATIONS_ERROR;
  1970. }
  1971. }
  1972. else
  1973. {
  1974. slapi_send_ldap_result( pb, returncode, NULL, NULL, 0, NULL );
  1975. slapi_sdn_done(&sdn);
  1976. return dse_delete_return( rc, ec );
  1977. }
  1978. dse_call_callback(pdse, pb, SLAPI_OPERATION_DELETE, DSE_FLAG_POSTOP, ec, NULL, &returncode, returntext);
  1979. slapi_send_ldap_result( pb, returncode, NULL, returntext, 0, NULL );
  1980. slapi_pblock_set( pb, SLAPI_ENTRY_PRE_OP, slapi_entry_dup( ec ));
  1981. slapi_sdn_done(&sdn);
  1982. return dse_delete_return(0, ec);
  1983. }
  1984. struct dse_callback *
  1985. dse_register_callback(struct dse* pdse, int operation, int flags, const Slapi_DN *base, int scope, const char *filter, dseCallbackFn fn, void *fn_arg)
  1986. {
  1987. struct dse_callback *callback = dse_callback_new(operation, flags, base, scope, filter, fn, fn_arg);
  1988. dse_callback_addtolist(&pdse->dse_callback, callback);
  1989. return callback;
  1990. }
  1991. void
  1992. dse_remove_callback(struct dse* pdse, int operation, int flags, const Slapi_DN *base, int scope, const char *filter, dseCallbackFn fn)
  1993. {
  1994. dse_callback_removefromlist(&pdse->dse_callback, operation, flags, base, scope, filter, fn);
  1995. }
  1996. /*
  1997. * Return values:
  1998. * SLAPI_DSE_CALLBACK_ERROR -- Callback failed.
  1999. * SLAPI_DSE_CALLBACK_OK -- OK, do it.
  2000. * SLAPI_DSE_CALLBACK_DO_NOT_APPLY -- No error, but don't apply changes.
  2001. */
  2002. static int
  2003. dse_call_callback(struct dse* pdse, Slapi_PBlock *pb, int operation, int flags, Slapi_Entry *entryBefore, Slapi_Entry *entryAfter, int *returncode, char *returntext)
  2004. {
  2005. /* ONREPL callbacks can potentially modify pblock parameters like backend
  2006. * which would cause problems during request processing. We need to save
  2007. * "important" fields before calls and restoring them afterwards */
  2008. int r = SLAPI_DSE_CALLBACK_OK;
  2009. if (pdse->dse_callback != NULL) {
  2010. struct dse_callback *p;
  2011. p=pdse->dse_callback;
  2012. while (p!=NULL) {
  2013. struct dse_callback *p_next = p->next;
  2014. if ((p->operation & operation) && (p->flags & flags)) {
  2015. if(slapi_sdn_scope_test(slapi_entry_get_sdn_const(entryBefore), p->base, p->scope))
  2016. {
  2017. if(NULL == p->slapifilter ||
  2018. slapi_vattr_filter_test(pb, entryBefore, p->slapifilter,
  2019. 0 /* !verify access */ )==0)
  2020. {
  2021. int result= (*p->fn)(pb, entryBefore,entryAfter,returncode,returntext,p->fn_arg);
  2022. if(result<r)
  2023. {
  2024. r= result;
  2025. }
  2026. }
  2027. }
  2028. }
  2029. p = p_next;
  2030. }
  2031. }
  2032. return r;
  2033. }
  2034. int
  2035. slapi_config_register_callback(int operation, int flags, const char *base, int scope, const char *filter, dseCallbackFn fn, void *fn_arg)
  2036. {
  2037. int rc= 0;
  2038. Slapi_Backend *be= slapi_be_select_by_instance_name(DSE_BACKEND);
  2039. if (be != NULL) {
  2040. struct dse* pdse= (struct dse*)be->be_database->plg_private;
  2041. if (pdse!=NULL) {
  2042. Slapi_DN dn;
  2043. slapi_sdn_init_dn_byref(&dn,base);
  2044. rc = (NULL != dse_register_callback(pdse, operation, flags, &dn, scope, filter, fn, fn_arg));
  2045. slapi_sdn_done(&dn);
  2046. }
  2047. }
  2048. return rc;
  2049. }
  2050. int
  2051. slapi_config_remove_callback(int operation, int flags, const char *base, int scope, const char *filter, dseCallbackFn fn)
  2052. {
  2053. int rc= 0;
  2054. Slapi_Backend *be= slapi_be_select_by_instance_name(DSE_BACKEND);
  2055. if(be != NULL) {
  2056. struct dse* pdse = (struct dse*)be->be_database->plg_private;
  2057. if (pdse != NULL) {
  2058. Slapi_DN dn;
  2059. slapi_sdn_init_dn_byref(&dn,base);
  2060. dse_remove_callback(pdse, operation, flags, &dn, scope, filter, fn);
  2061. slapi_sdn_done(&dn);
  2062. rc= 1;
  2063. }
  2064. }
  2065. return rc;
  2066. }
  2067. void
  2068. dse_set_dont_ever_write_dse_files()
  2069. {
  2070. dont_ever_write_dse_files = 1;
  2071. }
  2072. void
  2073. dse_unset_dont_ever_write_dse_files()
  2074. {
  2075. dont_ever_write_dse_files = 0;
  2076. }
  2077. static dse_search_set*
  2078. dse_search_set_new ()
  2079. {
  2080. dse_search_set *ss;
  2081. ss = (dse_search_set *)slapi_ch_malloc (sizeof (*ss));
  2082. if (ss)
  2083. {
  2084. dl_init (&ss->dl, 0);
  2085. ss->current_entry = -1;
  2086. }
  2087. return ss;
  2088. }
  2089. /* This is similar to delete, but it does not free the entries contained in the
  2090. search set. This is useful in do_dse_search when we copy the entries from
  2091. 1 search set to the other. */
  2092. static void
  2093. dse_search_set_clean(dse_search_set *ss)
  2094. {
  2095. if (ss)
  2096. {
  2097. dl_cleanup(&ss->dl, NULL);
  2098. slapi_ch_free((void **)&ss);
  2099. }
  2100. }
  2101. void
  2102. dse_search_set_release (void **ss)
  2103. {
  2104. dse_search_set_delete(*(dse_search_set **)ss);
  2105. }
  2106. void
  2107. dse_prev_search_results (void *vp)
  2108. {
  2109. Slapi_PBlock *pb = (Slapi_PBlock *)vp;
  2110. dse_search_set *ss;
  2111. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &ss);
  2112. if (ss) {
  2113. dl_get_prev (&ss->dl, &ss->current_entry);
  2114. }
  2115. }
  2116. static void
  2117. dse_search_set_delete (dse_search_set *ss)
  2118. {
  2119. if (ss)
  2120. {
  2121. dl_cleanup (&ss->dl, dse_free_entry);
  2122. slapi_ch_free ((void**)&ss);
  2123. }
  2124. }
  2125. static void
  2126. dse_free_entry (void **data)
  2127. {
  2128. Slapi_Entry **e;
  2129. if (data)
  2130. {
  2131. e = (Slapi_Entry **)data;
  2132. if (*e)
  2133. slapi_entry_free (*e);
  2134. }
  2135. }
  2136. static void
  2137. dse_search_set_add_entry (dse_search_set *ss, Slapi_Entry *e)
  2138. {
  2139. PR_ASSERT (ss && e);
  2140. dl_add (&ss->dl, e);
  2141. }
  2142. static Slapi_Entry*
  2143. dse_search_set_get_next_entry (dse_search_set *ss)
  2144. {
  2145. PR_ASSERT (ss);
  2146. if (ss->current_entry == -1)
  2147. return (dl_get_first (&ss->dl, &ss->current_entry));
  2148. else
  2149. return (dl_get_next (&ss->dl, &ss->current_entry));
  2150. }
  2151. int
  2152. dse_next_search_entry (Slapi_PBlock *pb)
  2153. {
  2154. dse_search_set *ss;
  2155. Slapi_Entry *e;
  2156. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &ss);
  2157. /* no entries to return */
  2158. if (ss == NULL)
  2159. {
  2160. slapi_pblock_set (pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  2161. return 0;
  2162. }
  2163. e = dse_search_set_get_next_entry (ss);
  2164. slapi_pblock_set (pb, SLAPI_SEARCH_RESULT_ENTRY, e);
  2165. /* we reached the end of the list */
  2166. if (e == NULL)
  2167. {
  2168. dse_search_set_delete (ss);
  2169. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
  2170. }
  2171. return 0;
  2172. }