]> git.sur5r.net Git - openldap/blob - servers/slapd/slapi/slapi_ops.c
fcfa6fe5bb642dec2f8e28a4a2a936c24593d46e
[openldap] / servers / slapd / slapi / slapi_ops.c
1 /*\r
2  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.\r
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file\r
4  */\r
5 /*\r
6  * (C) Copyright IBM Corp. 1997,2002\r
7  * Redistribution and use in source and binary forms are permitted\r
8  * provided that this notice is preserved and that due credit is\r
9  * given to IBM Corporation. This software is provided ``as is''\r
10  * without express or implied warranty.\r
11  */\r
12 \r
13 #include "portable.h"\r
14 #include "slapi_common.h"\r
15 #include <slap.h>\r
16 #include <slapi.h>\r
17 #include <lber.h>\r
18 #include "../../../libraries/liblber/lber-int.h"\r
19 \r
20 \r
21 int bvptr2obj( struct berval **bvptr, struct berval **bvobj );\r
22 \r
23 static void\r
24 internal_result_v3(\r
25         Connection      *conn, \r
26         Operation       *op, \r
27         ber_int_t       err,\r
28         const char      *matched, \r
29         const char      *text, \r
30         BerVarray       referrals,\r
31         LDAPControl     **ctrls )\r
32 {\r
33         return;\r
34 }\r
35 \r
36 static int\r
37 internal_search_entry(\r
38         Backend         *be, \r
39         Connection      *conn, \r
40         Operation       *op, \r
41         Entry           *e, \r
42         AttributeName   *attrs, \r
43         int             attrsonly, \r
44         LDAPControl     **ctrls ) \r
45 {\r
46         char *ent2str = NULL;\r
47         int nentries = 0, len = 0, i = 0;\r
48         Slapi_Entry **head = NULL, **tp;\r
49         \r
50         ent2str = slapi_entry2str( e, &len );\r
51         if ( ent2str == NULL ) {\r
52                 return 1;\r
53         }\r
54 \r
55         slapi_pblock_get( (Slapi_PBlock *)op->o_pb,\r
56                         SLAPI_NENTRIES, &nentries );\r
57         slapi_pblock_get( (Slapi_PBlock *)op->o_pb,\r
58                         SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head );\r
59         \r
60         i = nentries + 1;\r
61         if ( nentries == 0 ) {\r
62                 tp = (Slapi_Entry **)slapi_ch_malloc( 2 * sizeof(Slapi_Entry *) );\r
63                 if ( tp == NULL ) {\r
64                         return 1;\r
65                 }\r
66 \r
67                 tp[ 0 ] = (Slapi_Entry *)str2entry( ent2str );\r
68                 if ( tp[ 0 ] == NULL ) { \r
69                         return 1;\r
70                 }\r
71 \r
72         } else {\r
73                 tp = (Slapi_Entry **)slapi_ch_realloc( (char *)head,\r
74                                 sizeof(Slapi_Entry *) * ( i + 1 ) );\r
75                 if ( tp == NULL ) {\r
76                         return 1;\r
77                 }\r
78                 tp[ i - 1 ] = (Slapi_Entry *)str2entry( ent2str );\r
79                 if ( tp[ i - 1 ] == NULL ) { \r
80                         return 1;\r
81                 }\r
82         }\r
83         tp[ i ] = NULL;\r
84                   \r
85         slapi_pblock_set( (Slapi_PBlock *)op->o_pb,\r
86                         SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, (void *)tp );\r
87         slapi_pblock_set( (Slapi_PBlock *)op->o_pb,\r
88                         SLAPI_NENTRIES, (void *)i );\r
89 \r
90         return LDAP_SUCCESS;\r
91 }\r
92 \r
93 static void\r
94 internal_search_result(\r
95         Connection      *conn, \r
96         Operation       *op,\r
97         ber_int_t       err, \r
98         const char      *matched, \r
99         const char      *text, \r
100         BerVarray       refs,\r
101         LDAPControl     **ctrls,\r
102         int             nentries ) \r
103 {\r
104         slapi_pblock_set( (Slapi_PBlock *)op->o_pb,\r
105                         SLAPI_NENTRIES, (void *)nentries );\r
106 \r
107         return;\r
108 }\r
109 \r
110 static void\r
111 internal_result_ext(\r
112         Connection      *conn, \r
113         Operation       *op, \r
114         ber_int_t       errnum, \r
115         const char      *matched,\r
116         const char      *text,\r
117         BerVarray       refs,\r
118         const char      *rspoid,\r
119         struct berval   *rspdata,\r
120         LDAPControl     **ctrls )\r
121 {\r
122         return;\r
123 }\r
124 \r
125 static int\r
126 internal_search_reference(\r
127         Backend         *be,\r
128         Connection      *conn, \r
129         Operation       *op, \r
130         Entry           *e,\r
131         BerVarray       refs,\r
132         LDAPControl     **ctrls,\r
133         BerVarray       *v2refs )\r
134 {\r
135         return LDAP_SUCCESS;\r
136 }\r
137 \r
138 static Connection *\r
139 fakeConnection(\r
140         char *DN, \r
141         int OpType ) \r
142\r
143         Connection *pConn, *c;\r
144         ber_len_t max = sockbuf_max_incoming;\r
145 \r
146         pConn = (Connection *) slapi_ch_calloc(1, sizeof(Connection));\r
147         if (pConn == NULL) {\r
148                 return (Connection *)NULL;\r
149         }\r
150 \r
151         LDAP_STAILQ_INIT( &pConn->c_pending_ops );\r
152 \r
153         pConn->c_pending_ops.stqh_first =\r
154                 (Operation *) slapi_ch_calloc( 1, sizeof(Operation) );\r
155         if ( pConn->c_pending_ops.stqh_first == NULL ) { \r
156                 slapi_ch_free( (void **)&pConn );\r
157                 return (Connection *)NULL;\r
158         }\r
159 \r
160         pConn->c_pending_ops.stqh_first->o_pb = \r
161                 (Slapi_PBlock *) slapi_pblock_new();\r
162         if ( pConn->c_pending_ops.stqh_first->o_pb == NULL ) {\r
163                 slapi_ch_free( (void **)&pConn->c_pending_ops.stqh_first );\r
164                 slapi_ch_free( (void **)&pConn );\r
165                 return (Connection *)NULL;\r
166         }\r
167 \r
168         c = pConn;\r
169 \r
170         /* operation object */\r
171         c->c_pending_ops.stqh_first->o_tag = OpType;\r
172         c->c_pending_ops.stqh_first->o_protocol = LDAP_VERSION3; \r
173         c->c_pending_ops.stqh_first->o_authmech.bv_val = NULL; \r
174         c->c_pending_ops.stqh_first->o_authmech.bv_len = 0; \r
175         c->c_pending_ops.stqh_first->o_time = slap_get_time();\r
176         c->c_pending_ops.stqh_first->o_do_not_cache = 1;\r
177         c->c_pending_ops.stqh_first->o_threadctx = ldap_pvt_thread_pool_context( &connection_pool );\r
178 \r
179         /* connection object */\r
180         c->c_authmech.bv_val = NULL;\r
181         c->c_authmech.bv_len = 0;\r
182         c->c_dn.bv_val = NULL;\r
183         c->c_dn.bv_len = 0;\r
184         c->c_ndn.bv_val = NULL;\r
185         c->c_ndn.bv_len = 0;\r
186         c->c_groups = NULL;\r
187 \r
188         c->c_listener = NULL;\r
189         c->c_peer_domain.bv_val = NULL;\r
190         c->c_peer_domain.bv_len = 0;\r
191         c->c_peer_name.bv_val = NULL;\r
192         c->c_peer_name.bv_len = 0;\r
193 \r
194         LDAP_STAILQ_INIT( &c->c_ops );\r
195 \r
196         c->c_sasl_bind_mech.bv_val = NULL;\r
197         c->c_sasl_bind_mech.bv_len = 0;\r
198         c->c_sasl_context = NULL;\r
199         c->c_sasl_extra = NULL;\r
200 \r
201         c->c_sb = ber_sockbuf_alloc( );\r
202 \r
203         ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );\r
204 \r
205         c->c_currentber = NULL;\r
206 \r
207         /* should check status of thread calls */\r
208         ldap_pvt_thread_mutex_init( &c->c_mutex );\r
209         ldap_pvt_thread_mutex_init( &c->c_write_mutex );\r
210         ldap_pvt_thread_cond_init( &c->c_write_cv );\r
211 \r
212         c->c_n_ops_received = 0;\r
213         c->c_n_ops_executing = 0;\r
214         c->c_n_ops_pending = 0;\r
215         c->c_n_ops_completed = 0;\r
216 \r
217         c->c_n_get = 0;\r
218         c->c_n_read = 0;\r
219         c->c_n_write = 0;\r
220 \r
221         c->c_protocol = LDAP_VERSION3; \r
222 \r
223         c->c_activitytime = c->c_starttime = slap_get_time();\r
224 \r
225         c->c_connid = 0;\r
226 \r
227         c->c_conn_state  = 0x01;        /* SLAP_C_ACTIVE */\r
228         c->c_struct_state = 0x02;       /* SLAP_C_USED */\r
229 \r
230         c->c_ssf = c->c_transport_ssf = 0;\r
231         c->c_tls_ssf = 0;\r
232 \r
233         backend_connection_init( c );\r
234 \r
235         pConn->c_send_ldap_result = internal_result_v3;\r
236         pConn->c_send_search_entry = internal_search_entry;\r
237         pConn->c_send_search_result = internal_search_result;\r
238         pConn->c_send_ldap_extended = internal_result_ext;\r
239         pConn->c_send_search_reference = internal_search_reference;\r
240 \r
241         return pConn;\r
242 }\r
243 \r
244 /* \r
245  * Function : ValuestoBValues \r
246  * Convert an array of char ptrs to an array of berval ptrs.\r
247  * return value : LDAP_SUCCESS\r
248  *                LDAP_NO_MEMORY\r
249  *                LDAP_OTHER\r
250 */\r
251 \r
252 static int \r
253 ValuesToBValues(\r
254         char **ppValue, \r
255         struct berval ***pppBV )\r
256 {\r
257         int  rc = LDAP_SUCCESS;\r
258         int  i;\r
259         struct berval *pTmpBV;\r
260         struct berval **ppNewBV;\r
261 \r
262         /* count the number of char ptrs. */\r
263         for ( i = 0; ppValue != NULL && ppValue[i] != NULL; i++ ) {\r
264                 ;       /* NULL */\r
265         }\r
266 \r
267         if ( i == 0 ) {\r
268                 rc = LDAP_OTHER;\r
269         } else {\r
270                 *pppBV = ppNewBV = (struct berval **)slapi_ch_malloc( (i+1)*(sizeof(struct berval *)) );\r
271                 if ( *pppBV == NULL ) {\r
272                         rc = LDAP_NO_MEMORY;\r
273                 } else {\r
274                         while ( ppValue != NULL && *ppValue != NULL && rc == LDAP_SUCCESS ) {\r
275                                 pTmpBV = (struct berval *)slapi_ch_malloc(sizeof(struct berval));\r
276                                 if ( pTmpBV == NULL) {\r
277                                         rc = LDAP_NO_MEMORY;\r
278                                 } else {\r
279                                         pTmpBV->bv_val = slapi_ch_strdup(*ppValue);\r
280                                         if ( pTmpBV->bv_val == NULL ) {\r
281                                                 rc = LDAP_NO_MEMORY;\r
282                                         } else {\r
283                                                 pTmpBV->bv_len = strlen(*ppValue);\r
284                                                 *ppNewBV = pTmpBV;\r
285                                                 ppNewBV++;\r
286                                         }\r
287                                         ppValue++;\r
288                                 }\r
289                         }\r
290                         /* null terminate the array of berval ptrs */\r
291                         *ppNewBV = NULL;\r
292                 }\r
293         }\r
294         return( rc );\r
295 }\r
296 \r
297 \r
298 /*\r
299  * Function : LDAPModToEntry \r
300  * convert a dn plus an array of LDAPMod struct ptrs to an entry structure\r
301  * with a link list of the correspondent attributes.\r
302  * Return value : LDAP_SUCCESS\r
303  *                LDAP_NO_MEMORY\r
304  *                LDAP_OTHER\r
305 */\r
306 Entry *\r
307 LDAPModToEntry(\r
308         char *ldn, \r
309         LDAPMod **mods )\r
310 {\r
311         struct berval           dn = { 0, NULL };\r
312         Entry                   *pEntry=NULL;\r
313         LDAPMod                 *pMod;\r
314         struct berval           *bv;\r
315         struct berval           **ppBV;\r
316         Backend                 *be;\r
317         Operation               *op;\r
318 \r
319         Modifications           *modlist = NULL;\r
320         Modifications           **modtail = &modlist;\r
321         Modifications           tmp;\r
322 \r
323         int                     rc = LDAP_SUCCESS;\r
324         int                     i;\r
325 \r
326         const char              *text = NULL;\r
327 \r
328 \r
329         op = (Operation *) slapi_ch_calloc(1, sizeof(Operation));\r
330         if ( pEntry == NULL) {\r
331                 rc = LDAP_NO_MEMORY;\r
332                 goto cleanup;\r
333         }  \r
334         op->o_tag = LDAP_REQ_ADD;\r
335 \r
336         pEntry = (Entry *) ch_calloc( 1, sizeof(Entry) );\r
337         if ( pEntry == NULL) {\r
338                 rc = LDAP_NO_MEMORY;\r
339                 goto cleanup;\r
340         } \r
341 \r
342         dn.bv_val = slapi_ch_strdup(ldn);\r
343         dn.bv_len = strlen(ldn);\r
344 \r
345         rc = dnPrettyNormal( NULL, &dn, &pEntry->e_name, &pEntry->e_nname );\r
346         if (rc != LDAP_SUCCESS) goto cleanup;\r
347 \r
348         if ( rc == LDAP_SUCCESS ) {\r
349                 for ( i=0, pMod=mods[0]; rc == LDAP_SUCCESS && pMod != NULL; pMod=mods[++i]) {\r
350                         Modifications *mod;\r
351                         if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {\r
352                                 /* attr values are in berval format */\r
353                                 /* convert an array of pointers to bervals to an array of bervals */\r
354                                 rc = bvptr2obj(pMod->mod_bvalues, &bv);\r
355                                 if (rc != LDAP_SUCCESS) goto cleanup;\r
356                                 tmp.sml_type.bv_val = slapi_ch_strdup(pMod->mod_type);\r
357                                 tmp.sml_type.bv_len = slapi_ch_stlen(pMod->mod_type);\r
358                                 tmp.sml_bvalues = bv;\r
359                 \r
360                                 mod  = (Modifications *) ch_malloc( sizeof(Modifications) );\r
361 \r
362                                 mod->sml_op = LDAP_MOD_ADD;\r
363                                 mod->sml_next = NULL;\r
364                                 mod->sml_desc = NULL;\r
365                                 mod->sml_type = tmp.sml_type;\r
366                                 mod->sml_bvalues = tmp.sml_bvalues;\r
367 \r
368                                 *modtail = mod;\r
369                                 modtail = &mod->sml_next;\r
370 \r
371                         } else {\r
372                                 /* attr values are in string format, need to be converted */\r
373                                 /* to an array of bervals */ \r
374                                 if ( pMod->mod_values == NULL ) {\r
375                                         rc = LDAP_OTHER;\r
376                                 } else {\r
377                                         rc = ValuesToBValues( pMod->mod_values, &ppBV );\r
378                                         if (rc != LDAP_SUCCESS) goto cleanup;\r
379                                         rc = bvptr2obj(ppBV, &bv);\r
380                                         if (rc != LDAP_SUCCESS) goto cleanup;\r
381                                         tmp.sml_type.bv_val = slapi_ch_strdup(pMod->mod_type);\r
382                                         tmp.sml_type.bv_len = slapi_ch_stlen(pMod->mod_type);\r
383                                         tmp.sml_bvalues = bv;\r
384                 \r
385                                         mod  = (Modifications *) ch_malloc( sizeof(Modifications) );\r
386 \r
387                                         mod->sml_op = LDAP_MOD_ADD;\r
388                                         mod->sml_next = NULL;\r
389                                         mod->sml_desc = NULL;\r
390                                         mod->sml_type = tmp.sml_type;\r
391                                         mod->sml_bvalues = tmp.sml_bvalues;\r
392 \r
393                                         *modtail = mod;\r
394                                         modtail = &mod->sml_next;\r
395 \r
396                                         if ( ppBV != NULL ) {\r
397                                                 ber_bvecfree( ppBV );\r
398                                         }\r
399                                 }\r
400                         }\r
401                 } /* for each LDAPMod */\r
402         }\r
403 \r
404         be = select_backend(&dn, 0, 0);\r
405         if ( be == NULL ) {\r
406                 rc =  LDAP_PARTIAL_RESULTS;\r
407                 goto cleanup;\r
408         }\r
409 \r
410         if ( be ) {\r
411                 int repl_user = be_isupdate(be, &be->be_rootdn );\r
412                 if ( !be->be_update_ndn.bv_len || repl_user ) {\r
413                         int update = be->be_update_ndn.bv_len;\r
414                         char textbuf[SLAP_TEXT_BUFLEN];\r
415                         size_t textlen = sizeof textbuf;\r
416 \r
417                         rc = slap_mods_check( modlist, update, &text, \r
418                                         textbuf, textlen );\r
419                         if ( rc != LDAP_SUCCESS) {\r
420                                 goto cleanup;\r
421                         }\r
422 \r
423                         if ( !repl_user ) {\r
424                                 rc = slap_mods_opattrs( be, op,\r
425                                                 modlist, modtail, &text, \r
426                                                 textbuf, textlen );\r
427                                 if ( rc != LDAP_SUCCESS) {\r
428                                         goto cleanup;\r
429                                 }\r
430                         }\r
431 \r
432                         /*\r
433                          * FIXME: slap_mods2entry is declared static \r
434                          * in servers/slapd/add.c\r
435                          */\r
436                         rc = slap_mods2entry( modlist, &pEntry, repl_user,\r
437                                         &text, textbuf, textlen );\r
438                         if (rc != LDAP_SUCCESS) {\r
439                                 goto cleanup;\r
440                         }\r
441 \r
442                 } else {\r
443                         rc = LDAP_REFERRAL;\r
444                 }\r
445         } else {\r
446                 rc = LDAP_UNWILLING_TO_PERFORM;\r
447         }\r
448 \r
449 cleanup:\r
450 \r
451         if ( dn.bv_val ) slapi_ch_free( (void **)&dn.bv_val );\r
452         if ( op ) slapi_ch_free( (void **)&op );\r
453         if ( modlist != NULL ) slap_mods_free( modlist );\r
454         if ( rc != LDAP_SUCCESS ) {\r
455                 if ( pEntry != NULL ) {\r
456                         slapi_entry_free( pEntry );\r
457                 }\r
458                 pEntry = NULL;\r
459         }\r
460 \r
461         return( pEntry );\r
462 }\r
463 \r
464 /* Function : slapi_delete_internal\r
465  *\r
466  * Description : Plugin functions call this routine to delete an entry \r
467  *               in the backend directly\r
468  * Return values : LDAP_SUCCESS\r
469  *                 LDAP_PARAM_ERROR\r
470  *                 LDAP_NO_MEMORY\r
471  *                 LDAP_OTHER\r
472  *                 LDAP_UNWILLING_TO_PERFORM\r
473 */\r
474 Slapi_PBlock *\r
475 slapi_delete_internal(\r
476         char *ldn, \r
477         LDAPControl **controls, \r
478         int log_change )\r
479 {\r
480 #if defined(LDAP_SLAPI)\r
481         Backend                 *be;\r
482         Connection              *pConn = NULL;\r
483         Operation               *op = NULL;\r
484         Slapi_PBlock            *pPB = NULL;\r
485         Slapi_PBlock            *pSavePB = NULL;\r
486 \r
487         struct berval dn  = { 0, NULL };\r
488         struct berval pdn = { 0, NULL };\r
489         struct berval ndn = { 0, NULL };\r
490 \r
491         int                             rc=LDAP_SUCCESS;\r
492         int                             manageDsaIt = 0;\r
493         int                             isCritical;\r
494 \r
495         if ( ldn == NULL ) {\r
496                 rc = LDAP_PARAM_ERROR; \r
497                 goto cleanup;\r
498         }\r
499 \r
500         pConn = fakeConnection( NULL,  LDAP_REQ_DELETE );\r
501         if (pConn == NULL) {\r
502                 rc = LDAP_NO_MEMORY;\r
503                 goto cleanup;\r
504         }\r
505 \r
506         op = (Operation *)pConn->c_pending_ops.stqh_first;\r
507         pPB = (Slapi_PBlock *)op->o_pb;\r
508         op->o_ctrls = controls;\r
509 \r
510         dn.bv_val = slapi_ch_strdup(ldn);\r
511         dn.bv_len = slapi_strlen(ldn);\r
512         rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );\r
513         if ( rc != LDAP_SUCCESS ) goto cleanup;\r
514 \r
515         if ( slapi_control_present( controls, \r
516                         SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical) ) {\r
517                 manageDsaIt = 1; \r
518         }\r
519 \r
520         be = select_backend( &dn, manageDsaIt, 0 );\r
521         if ( be == NULL ) {\r
522                 rc =  LDAP_PARTIAL_RESULTS;\r
523                 goto cleanup;\r
524         }\r
525 \r
526         op->o_ndn.bv_val = slapi_ch_strdup(be->be_rootdn.bv_val);\r
527         op->o_ndn.bv_len = be->be_rootdn.bv_len;\r
528         pConn->c_dn.bv_val = slapi_ch_strdup(be->be_rootdn.bv_val);\r
529         pConn->c_dn.bv_len = be->be_rootdn.bv_len;\r
530 \r
531         suffix_alias( be, &ndn );\r
532 \r
533         if ( be->be_delete ) {\r
534                 int repl_user = be_isupdate( be, &op->o_ndn );\r
535                 if ( !be->be_update_ndn.bv_len || repl_user ) {\r
536                         rc = (*be->be_delete)( be, pConn, op, &pdn, &ndn );\r
537                         if ( rc == 0 ) {\r
538                                 if (log_change) {\r
539                                         replog( be, op, &pdn, &ndn, NULL );\r
540                                 }\r
541                                 rc = LDAP_SUCCESS;\r
542                         } else {\r
543                                 rc = LDAP_OPERATIONS_ERROR;\r
544                         }\r
545                 } else {\r
546                         rc = LDAP_REFERRAL;\r
547                 }\r
548         } else {\r
549                 rc = LDAP_UNWILLING_TO_PERFORM;\r
550         }\r
551 \r
552 cleanup:\r
553         if (pPB != NULL) \r
554                 slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );\r
555 \r
556         if (dn.bv_val) slapi_ch_free( (void **)&dn.bv_val );\r
557         if (pdn.bv_val) slapi_ch_free( (void **)&pdn.bv_val );\r
558         if (ndn.bv_val) slapi_ch_free( (void **)&ndn.bv_val );\r
559 \r
560         if ( pConn != NULL ) {\r
561                 if ( pConn->c_sb != NULL ) ber_sockbuf_free( pConn->c_sb );\r
562                 if ( pConn->c_dn.bv_val ) slapi_ch_free( (void **)&pConn->c_dn.bv_val );\r
563                 if ( op->o_dn.bv_val ) slapi_ch_free( (void **)&op->o_dn.bv_val );\r
564                 if ( op ) slapi_ch_free( (void **)&op );\r
565                 pSavePB = pPB;\r
566                 free( pConn );\r
567         }\r
568         \r
569         return (pSavePB);\r
570 #endif /* LDAP_SLAPI */\r
571         return NULL;\r
572 }\r
573 \r
574 Slapi_PBlock * \r
575 slapi_add_entry_internal(\r
576         Slapi_Entry *e, \r
577         LDAPControl **controls, \r
578         int log_changes ) \r
579 {\r
580 #if defined(LDAP_SLAPI)\r
581         Connection              *pConn = NULL;\r
582         Operation               *op = NULL;\r
583         Slapi_PBlock            *pPB = NULL, *pSavePB = NULL;\r
584         Backend                 *be;\r
585 \r
586         int                     manageDsaIt = 0;\r
587         int                     isCritical;\r
588         int                     rc = LDAP_SUCCESS;\r
589 \r
590         if ( e == NULL ) {\r
591                 rc = LDAP_PARAM_ERROR;\r
592                 goto cleanup;\r
593         }\r
594         \r
595         pConn = fakeConnection( NULL, LDAP_REQ_ADD );\r
596         if ( pConn == NULL ) {\r
597                 rc = LDAP_NO_MEMORY;\r
598                 goto cleanup;\r
599         }\r
600 \r
601         if ( slapi_control_present( controls, LDAP_CONTROL_MANAGEDSAIT,\r
602                                 NULL, &isCritical ) ) {\r
603                 manageDsaIt = 1; \r
604         }\r
605 \r
606         op = (Operation *)pConn->c_pending_ops.stqh_first;\r
607         pPB = (Slapi_PBlock *)op->o_pb;\r
608         op->o_ctrls = controls;\r
609 \r
610         be = select_backend( &e->e_nname, manageDsaIt, 0 );\r
611         if ( be == NULL ) {\r
612                 rc = LDAP_PARTIAL_RESULTS;\r
613                 goto cleanup;\r
614         }\r
615 \r
616         op->o_ndn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );\r
617         op->o_ndn.bv_len = be->be_rootdn.bv_len;\r
618         pConn->c_dn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );\r
619         pConn->c_dn.bv_len = be->be_rootdn.bv_len;\r
620 \r
621         if ( be->be_add ) {\r
622                 int repl_user = be_isupdate( be, &op->o_ndn );\r
623                 if ( !be->be_update_ndn.bv_len || repl_user ){\r
624                         if ( (*be->be_add)( be, pConn, op, e ) == 0 ) {\r
625                                 if ( log_changes ) {\r
626                                         replog( be, op, &e->e_name, \r
627                                                         &e->e_nname, e );\r
628                                 }\r
629                                 rc = LDAP_SUCCESS;\r
630                         }\r
631                 } else {\r
632                         rc = LDAP_REFERRAL;\r
633                 }\r
634         } else {\r
635                 rc = LDAP_UNWILLING_TO_PERFORM;\r
636         }\r
637 \r
638 cleanup:\r
639 \r
640         if ( pPB != NULL ) {\r
641                 slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );\r
642         }\r
643 \r
644         if ( pConn != NULL ) {\r
645                 if ( pConn->c_sb != NULL ) ber_sockbuf_free( pConn->c_sb );\r
646                 if ( pConn->c_dn.bv_val ) slapi_ch_free( (void **)&pConn->c_dn.bv_val );\r
647                 if ( op ) {\r
648                         if ( op->o_ndn.bv_val ) {\r
649                                 slapi_ch_free( (void **)&op->o_ndn.bv_val );\r
650                         }\r
651                         free(op);\r
652                 }\r
653                 pSavePB = pPB;\r
654                 free( pConn );\r
655         }\r
656         return( pSavePB );\r
657 #endif /* LDAP_SLAPI */\r
658         return NULL;\r
659 }\r
660 \r
661 \r
662 Slapi_PBlock *\r
663 slapi_add_internal(\r
664         char *dn, \r
665         LDAPMod **mods, \r
666         LDAPControl **controls, \r
667         int log_changes  ) \r
668 {\r
669 #if defined(LDAP_SLAPI)\r
670         LDAPMod                 *pMod = NULL;\r
671         Slapi_PBlock            *pb = NULL;\r
672         Entry                   *pEntry = NULL;\r
673         int                     i, rc=LDAP_SUCCESS;\r
674 \r
675         if ( mods == NULL || *mods == NULL || dn == NULL || *dn == '\0' ) {\r
676                 rc = LDAP_PARAM_ERROR ;\r
677         }\r
678 \r
679         if ( rc == LDAP_SUCCESS ) {\r
680                 for ( i = 0, pMod = mods[0]; pMod != NULL; pMod = mods[++i] ) {\r
681                         if ( (pMod->mod_op & ~LDAP_MOD_BVALUES) != LDAP_MOD_ADD ) {\r
682                                 rc = LDAP_OTHER;\r
683                                 break;\r
684                         }\r
685                 }\r
686         }\r
687 \r
688         if ( rc == LDAP_SUCCESS ) {\r
689                 if((pEntry = LDAPModToEntry( dn, mods )) == NULL) {\r
690                         rc = LDAP_OTHER;\r
691                 }\r
692         }\r
693 \r
694         if ( rc != LDAP_SUCCESS ) {\r
695                 pb = slapi_pblock_new();\r
696                 slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );\r
697         } else {\r
698                 pb = slapi_add_entry_internal( pEntry, controls, log_changes );\r
699         }\r
700 \r
701         if ( pEntry ) {\r
702                 slapi_entry_free(pEntry);\r
703         }\r
704 \r
705         return(pb);\r
706 #endif /* LDAP_SLAPI */\r
707         return NULL;\r
708 }\r
709 \r
710 /* Function : slapi_modrdn_internal\r
711  *\r
712  * Description : Plugin functions call this routine to modify the rdn \r
713  *                               of an entry in the backend directly\r
714  * Return values : LDAP_SUCCESS\r
715  *                 LDAP_PARAM_ERROR\r
716  *                 LDAP_OPERATIONS_ERROR\r
717  *                 LDAP_NO_MEMORY\r
718  *                 LDAP_OTHER\r
719  *                 LDAP_UNWILLING_TO_PERFORM\r
720  *\r
721  * NOTE: This function does not support the "newSuperior" option from LDAP V3.\r
722  */\r
723 Slapi_PBlock *\r
724 slapi_modrdn_internal(\r
725         char *olddn, \r
726         char *lnewrdn, \r
727         int deloldrdn, \r
728         LDAPControl **controls, \r
729         int log_change )\r
730 {\r
731 #if defined(LDAP_SLAPI)\r
732         int                     rc = LDAP_SUCCESS;\r
733 \r
734         struct berval           dn = { 0, NULL };\r
735         struct berval           pdn = { 0, NULL };\r
736         struct berval           ndn = { 0, NULL };\r
737 \r
738         struct berval           newrdn = { 0, NULL };\r
739         struct berval           pnewrdn = { 0, NULL };\r
740         struct berval           nnewrdn = { 0, NULL };\r
741 \r
742 #if 0 /* currently unused */\r
743         struct berval           newSuperior = { 0, NULL };\r
744 #endif\r
745         struct berval           pnewSuperior = { 0, NULL }; \r
746 #if 0 /* currently unused */\r
747         struct berval           nnewSuperior = { 0, NULL }; \r
748 #endif\r
749 \r
750         struct berval           *pnewS = NULL;\r
751         struct berval           *nnewS = NULL;\r
752 \r
753         Connection              *pConn = NULL;\r
754         Operation               *op = NULL;\r
755         Slapi_PBlock            *pPB = NULL;\r
756         Slapi_PBlock            *pSavePB = NULL;\r
757 \r
758         Backend                 *be;\r
759 #if 0 /* currently unused */\r
760         Backend                 *newSuperior_be = NULL;\r
761 #endif\r
762 \r
763         int                     manageDsaIt = 0;\r
764         int                     isCritical;\r
765 #if 0 /* currently unused */\r
766         const char              *text = NULL;\r
767 #endif\r
768 \r
769         dn.bv_val = slapi_ch_strdup(olddn);\r
770         dn.bv_len = slapi_ch_stlen(olddn);\r
771 \r
772         rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );\r
773 \r
774         if ( rc != LDAP_SUCCESS ) goto cleanup;\r
775 \r
776         if ( ndn.bv_len == 0 ) {\r
777                 rc = LDAP_UNWILLING_TO_PERFORM;\r
778                 goto cleanup;\r
779         }\r
780 \r
781         newrdn.bv_val = slapi_ch_strdup( lnewrdn );\r
782         newrdn.bv_len = slapi_ch_stlen( lnewrdn );\r
783 \r
784         rc = dnPrettyNormal( NULL, &newrdn, &pnewrdn, &nnewrdn );\r
785 \r
786         if ( rc != LDAP_SUCCESS ) goto cleanup;\r
787 \r
788         if ( rdnValidate( &pnewrdn ) != LDAP_SUCCESS ) goto cleanup;\r
789 \r
790         pConn = fakeConnection( NULL,  LDAP_REQ_MODRDN);\r
791         if ( pConn == NULL) {\r
792                 rc = LDAP_NO_MEMORY;\r
793                 goto cleanup;\r
794         }\r
795 \r
796         op = (Operation *)pConn->c_pending_ops.stqh_first;\r
797         pPB = (Slapi_PBlock *)op->o_pb;\r
798         op->o_ctrls = controls;\r
799 \r
800         if ( slapi_control_present( controls, \r
801                         SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical ) ) {\r
802                 manageDsaIt = 1;\r
803         }\r
804 \r
805         be = select_backend( &dn, manageDsaIt, 0 );\r
806         if ( be == NULL ) {\r
807                 rc =  LDAP_PARTIAL_RESULTS;\r
808                 goto cleanup;\r
809         }\r
810 \r
811         op->o_ndn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );\r
812         op->o_ndn.bv_len = be->be_rootdn.bv_len;\r
813         pConn->c_dn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );\r
814         pConn->c_dn.bv_len = be->be_rootdn.bv_len;\r
815 \r
816         suffix_alias( be, &ndn );\r
817 \r
818         if ( be->be_modrdn ) {\r
819                 int repl_user = be_isupdate( be, &op->o_ndn );\r
820                 if ( !be->be_update_ndn.bv_len || repl_user ) {\r
821                         rc = (*be->be_modrdn)( be, pConn, op, &pdn, &ndn,\r
822                                         &pnewrdn, &nnewrdn, deloldrdn, pnewS,\r
823                                         nnewS );\r
824                         if ( rc == 0 ) {\r
825                                 struct slap_replog_moddn moddn;\r
826                                 moddn.newrdn = &pnewrdn;\r
827                                 moddn.deloldrdn = deloldrdn;\r
828                                 moddn.newsup = &pnewSuperior;\r
829                                 if ( log_change ) {\r
830                                         replog( be, op, &pdn, &ndn, &moddn );\r
831                                 }\r
832                                 rc = LDAP_SUCCESS;\r
833 \r
834                         } else {\r
835                                 rc = LDAP_OPERATIONS_ERROR;\r
836                         }\r
837 \r
838                 } else {\r
839                         rc = LDAP_REFERRAL;\r
840                 }\r
841 \r
842         } else {\r
843                 rc = LDAP_UNWILLING_TO_PERFORM;\r
844         }\r
845 \r
846 cleanup:\r
847 \r
848         if ( pPB != NULL ) {\r
849                 slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );\r
850         }\r
851         \r
852         if ( dn.bv_val ) ch_free( dn.bv_val );\r
853         if ( pdn.bv_val ) ch_free( pdn.bv_val );\r
854         if ( ndn.bv_val ) ch_free( ndn.bv_val );\r
855 \r
856         if ( newrdn.bv_val ) ch_free( newrdn.bv_val );\r
857         if ( pnewrdn.bv_val ) ch_free( newrdn.bv_val );\r
858         if ( nnewrdn.bv_val ) ch_free( newrdn.bv_val );\r
859 \r
860         if ( pConn != NULL ) {\r
861                 if ( pConn->c_sb != NULL ) ber_sockbuf_free( pConn->c_sb );\r
862                 if ( pConn->c_dn.bv_val ) slapi_ch_free( (void **)&pConn->c_dn.bv_val );\r
863                 if ( op ) {\r
864                         if ( op->o_dn.bv_val ) slapi_ch_free( (void **)&op->o_dn.bv_val );\r
865                         slapi_ch_free( (void **)&op );\r
866                 }\r
867                 pSavePB = pPB;\r
868                 free( pConn );\r
869         }\r
870 \r
871         return( pSavePB );\r
872 #endif /* LDAP_SLAPI */\r
873         return NULL;\r
874 }\r
875 \r
876 /* Function : slapi_modify_internal\r
877  *\r
878  * Description: Plugin functions call this routine to modify an entry \r
879  *                              in the backend directly\r
880  * Return values : LDAP_SUCCESS\r
881  *                 LDAP_PARAM_ERROR\r
882  *                 LDAP_NO_MEMORY\r
883  *                 LDAP_OPERATIONS_ERROR\r
884  *                 LDAP_OTHER\r
885  *                 LDAP_UNWILLING_TO_PERFORM\r
886 */\r
887 Slapi_PBlock *\r
888 slapi_modify_internal(\r
889         char *ldn,      \r
890         LDAPMod **mods, \r
891         LDAPControl **controls, \r
892         int log_change )\r
893 {\r
894 #if defined(LDAP_SLAPI)\r
895         int                     i, rc = LDAP_SUCCESS;\r
896         Connection              *pConn = NULL;\r
897         Operation               *op = NULL;\r
898         Slapi_PBlock            *pPB = NULL;\r
899         Slapi_PBlock            *pSavePB = NULL;\r
900 \r
901         struct berval dn = { 0, NULL };\r
902         struct berval pdn = { 0, NULL };\r
903         struct berval ndn = { 0, NULL };\r
904 \r
905         int                     manageDsaIt = 0;\r
906         int                     isCritical;\r
907         Backend                 *be;\r
908         struct berval           *bv;\r
909         struct berval           **ppBV;\r
910         LDAPMod                 *pMod;\r
911 \r
912         Modifications           *modlist = NULL;\r
913         Modifications           **modtail = &modlist;\r
914         Modifications           tmp;\r
915 \r
916         if ( mods == NULL || *mods == NULL || ldn == NULL ) {\r
917                 rc = LDAP_PARAM_ERROR ;\r
918                 goto cleanup;\r
919         }\r
920 \r
921         pConn = fakeConnection( NULL,  LDAP_REQ_MODIFY );\r
922         if ( pConn == NULL ) {\r
923                 rc = LDAP_NO_MEMORY;\r
924                 goto cleanup;\r
925         }\r
926 \r
927         op = (Operation *)pConn->c_pending_ops.stqh_first;\r
928         pPB = (Slapi_PBlock *)op->o_pb;\r
929         op->o_ctrls = controls;\r
930 \r
931         dn.bv_val = slapi_ch_strdup( ldn );\r
932         dn.bv_len = slapi_strlen( ldn );\r
933         rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );\r
934         if ( rc != LDAP_SUCCESS ) goto cleanup;\r
935 \r
936         if ( slapi_control_present( controls, \r
937                         SLAPI_CONTROL_MANAGEDSAIT_OID, NULL, &isCritical ) ) {\r
938                 manageDsaIt = 1;\r
939         }\r
940 \r
941         be = select_backend( &dn, manageDsaIt, 0 );\r
942         if ( be == NULL ) {\r
943                 rc =  LDAP_PARTIAL_RESULTS;\r
944                 goto cleanup;\r
945         }\r
946 \r
947         op->o_ndn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );\r
948         op->o_ndn.bv_len = be->be_rootdn.bv_len;\r
949         pConn->c_dn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );\r
950         pConn->c_dn.bv_len = be->be_rootdn.bv_len;\r
951 \r
952         suffix_alias( be, &ndn );\r
953 \r
954         for ( i = 0, pMod = mods[0]; rc == LDAP_SUCCESS && pMod != NULL; \r
955                         pMod = mods[++i] ) {\r
956                 Modifications *mod;\r
957                 if ( (pMod->mod_op & LDAP_MOD_BVALUES) != 0 ) {\r
958                         /*\r
959                          * attr values are in berval format\r
960                          * convert an array of pointers to bervals\r
961                          * to an array of bervals\r
962                          */\r
963                         rc = bvptr2obj( pMod->mod_bvalues, &bv );\r
964                         if ( rc != LDAP_SUCCESS ) goto cleanup;\r
965                         tmp.sml_type.bv_val = slapi_ch_strdup( pMod->mod_type );\r
966                         tmp.sml_type.bv_len = slapi_ch_stlen( pMod->mod_type );\r
967                         tmp.sml_bvalues = bv;\r
968 \r
969                         mod  = (Modifications *)ch_malloc( sizeof(Modifications) );\r
970 \r
971                         mod->sml_op = pMod->mod_op;\r
972                         mod->sml_next = NULL;\r
973                         mod->sml_desc = NULL;\r
974                         mod->sml_type = tmp.sml_type;\r
975                         mod->sml_bvalues = tmp.sml_bvalues;\r
976                 } else { \r
977                         rc = ValuesToBValues( pMod->mod_values, &ppBV );\r
978                         if ( rc != LDAP_SUCCESS ) goto cleanup;\r
979                         rc = bvptr2obj( ppBV, &bv );\r
980                         if ( rc != LDAP_SUCCESS ) goto cleanup;\r
981                         tmp.sml_type.bv_val = slapi_ch_strdup( pMod->mod_type );\r
982                         tmp.sml_type.bv_len = slapi_ch_stlen( pMod->mod_type );\r
983                         tmp.sml_bvalues = bv;\r
984 \r
985                         mod  = (Modifications *) ch_malloc( sizeof(Modifications) );\r
986 \r
987                         mod->sml_op = pMod->mod_op;\r
988                         mod->sml_next = NULL;\r
989                         mod->sml_desc = NULL;\r
990                         mod->sml_type = tmp.sml_type;\r
991                         mod->sml_bvalues = tmp.sml_bvalues;\r
992 \r
993                         if ( ppBV != NULL ) {\r
994                                 ber_bvecfree( ppBV );\r
995                         }\r
996                 }\r
997                 *modtail = mod;\r
998                 modtail = &mod->sml_next;\r
999 \r
1000                 switch( pMod->mod_op ) {\r
1001                 case LDAP_MOD_ADD:\r
1002                 if ( mod->sml_bvalues == NULL ) {\r
1003                         rc = LDAP_PROTOCOL_ERROR;\r
1004                         goto cleanup;\r
1005                 }\r
1006 \r
1007                 /* fall through */\r
1008                 case LDAP_MOD_DELETE:\r
1009                 case LDAP_MOD_REPLACE:\r
1010                 break;\r
1011 \r
1012                 default:\r
1013                         rc = LDAP_PROTOCOL_ERROR;\r
1014                         goto cleanup;\r
1015                 }\r
1016         } \r
1017         *modtail = NULL;\r
1018 \r
1019         if ( ndn.bv_len == 0 ) {\r
1020                 rc = LDAP_UNWILLING_TO_PERFORM;\r
1021                 goto cleanup;\r
1022         }\r
1023 \r
1024         if ( be->be_modify ) {\r
1025                 int repl_user = be_isupdate( be, &op->o_ndn );\r
1026                 if ( !be->be_update_ndn.bv_len || repl_user ) {\r
1027                         int update = be->be_update_ndn.bv_len;\r
1028                         const char *text = NULL;\r
1029                         char textbuf[SLAP_TEXT_BUFLEN];\r
1030                         size_t textlen = sizeof( textbuf );\r
1031 \r
1032                         rc = slap_mods_check( modlist, update,\r
1033                                         &text, textbuf, textlen );\r
1034                         if (rc != LDAP_SUCCESS) {\r
1035                                 goto cleanup;\r
1036                         }\r
1037 \r
1038                         if ( !repl_user ) {\r
1039                                 rc = slap_mods_opattrs( be, op, modlist,\r
1040                                                 modtail, &text, textbuf, \r
1041                                                 textlen );\r
1042                                 if (rc != LDAP_SUCCESS) {\r
1043                                         goto cleanup;\r
1044                                 }\r
1045                         }\r
1046                         rc = (*be->be_modify)( be, pConn, op,\r
1047                                         &pdn, &ndn, modlist );\r
1048                         if ( rc == 0 ) {\r
1049                                 if ( log_change ) {\r
1050                                         replog( be, op, &pdn, &ndn, modlist );\r
1051                                 }\r
1052                                 rc = LDAP_SUCCESS;\r
1053                         } else {\r
1054                                 rc = LDAP_OPERATIONS_ERROR;\r
1055                         }\r
1056                 } else {\r
1057                         rc = LDAP_REFERRAL;\r
1058                 }\r
1059         } else {\r
1060                 rc = LDAP_UNWILLING_TO_PERFORM;\r
1061         }\r
1062 \r
1063 cleanup:\r
1064 \r
1065         if ( pPB != NULL ) \r
1066                 slapi_pblock_set( pPB, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );\r
1067 \r
1068         if ( dn.bv_val ) ch_free( dn.bv_val );\r
1069         if ( pdn.bv_val ) ch_free( pdn.bv_val );\r
1070         if ( ndn.bv_val ) ch_free( ndn.bv_val );\r
1071 \r
1072         if ( modlist != NULL ) slap_mods_free( modlist );\r
1073 \r
1074         if ( pConn != NULL ) {\r
1075                 if ( pConn->c_sb != NULL ) ber_sockbuf_free( pConn->c_sb );\r
1076                 if ( pConn->c_dn.bv_val ) slapi_ch_free( (void **)&pConn->c_dn.bv_val );\r
1077                 if ( op ) {\r
1078                         if ( op->o_dn.bv_val ) slapi_ch_free( (void **)&op->o_dn.bv_val );\r
1079                         slapi_ch_free( (void **)&op );\r
1080                 }\r
1081                 pSavePB = pPB;\r
1082                 free( pConn );\r
1083         }\r
1084 \r
1085         return ( pSavePB );\r
1086 \r
1087 #endif /* LDAP_SLAPI */\r
1088         return NULL;\r
1089 }\r
1090 \r
1091 Slapi_PBlock *\r
1092 slapi_search_internal_bind(\r
1093         char *bindDN, \r
1094         char *ldn, \r
1095         int scope, \r
1096         char *filStr, \r
1097         LDAPControl **controls, \r
1098         char **attrs, \r
1099         int attrsonly ) \r
1100 {       \r
1101 #if defined(LDAP_SLAPI)\r
1102         Backend                 *be;\r
1103         Connection              *c;\r
1104         Operation               *op = NULL;\r
1105         Slapi_PBlock            *ptr = NULL;            \r
1106         Slapi_PBlock            *pSavePB = NULL;                \r
1107         struct berval           dn = { 0, NULL };\r
1108         struct berval           pdn = { 0, NULL };\r
1109         struct berval           ndn = { 0, NULL };\r
1110         Filter                  *filter=NULL;\r
1111         struct berval           fstr = { 0, NULL };\r
1112         AttributeName           *an = NULL;\r
1113         const char              *text = NULL;\r
1114 \r
1115         int                     deref=0;\r
1116         int                     sizelimit=-1, timelimit=-1;\r
1117 \r
1118         int                     manageDsaIt = 0; \r
1119         int                     isCritical;\r
1120 \r
1121         int                     i, rc = LDAP_SUCCESS;\r
1122         \r
1123         c = fakeConnection( NULL, LDAP_REQ_SEARCH );\r
1124         if (c == NULL) {\r
1125                 rc = LDAP_NO_MEMORY;\r
1126                 goto cleanup;\r
1127         }\r
1128 \r
1129         op = (Operation *)c->c_pending_ops.stqh_first;\r
1130         ptr = (Slapi_PBlock *)op->o_pb;\r
1131         op->o_ctrls = controls;\r
1132 \r
1133         dn.bv_val = slapi_ch_strdup(ldn);\r
1134         dn.bv_len = slapi_strlen(ldn);\r
1135 \r
1136         rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn );\r
1137         if (rc != LDAP_SUCCESS) goto cleanup;\r
1138 \r
1139         if ( scope != LDAP_SCOPE_BASE && \r
1140                         scope != LDAP_SCOPE_ONELEVEL && \r
1141                         scope != LDAP_SCOPE_SUBTREE ) {\r
1142                 rc = LDAP_PROTOCOL_ERROR;\r
1143                 goto cleanup;\r
1144         }\r
1145 \r
1146         filter = slapi_str2filter(filStr);\r
1147         if ( filter == NULL ) {\r
1148                 rc = LDAP_PROTOCOL_ERROR;\r
1149                 goto cleanup;\r
1150         }\r
1151 \r
1152         filter2bv( filter, &fstr );\r
1153 \r
1154         for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ ) {\r
1155                 ; /* count the number of attributes */\r
1156         }\r
1157 \r
1158         if (i > 0) {\r
1159                 an = (AttributeName *)slapi_ch_calloc(1, sizeof(AttributeName));\r
1160                 for (i = 0; attrs[i] != 0; i++) {\r
1161                         an[i].an_desc = NULL;\r
1162                         an[i].an_oc = NULL;\r
1163                         an[i].an_name.bv_val = slapi_ch_strdup(attrs[i]);\r
1164                         an[i].an_name.bv_len = slapi_strlen(attrs[i]);\r
1165                         slap_bv2ad( &an[i].an_name, &an[i].an_desc, &text );\r
1166                 }\r
1167         }\r
1168 \r
1169         if ( scope == LDAP_SCOPE_BASE ) {\r
1170                 Entry *entry = NULL;\r
1171 \r
1172                 if ( ndn.bv_len == 0 ) {\r
1173                         rc = root_dse_info( c, &entry, &text );\r
1174                 }\r
1175 \r
1176                 if( rc != LDAP_SUCCESS ) {\r
1177                         send_ldap_result( c, op, rc, NULL, text, NULL, NULL );\r
1178                         goto cleanup;\r
1179                 } else if ( entry != NULL ) {\r
1180                         rc = test_filter( NULL, c, op, entry, filter );\r
1181 \r
1182                         if( rc == LDAP_COMPARE_TRUE ) {\r
1183                                 send_search_entry( NULL, c, op, entry,\r
1184                                                 an, attrsonly, NULL );\r
1185                         }\r
1186 \r
1187                         entry_free( entry );\r
1188 \r
1189                         send_ldap_result( c, op, LDAP_SUCCESS, \r
1190                                         NULL, NULL, NULL, NULL );\r
1191 \r
1192                         rc = LDAP_SUCCESS;\r
1193 \r
1194                         goto cleanup;\r
1195                 }\r
1196         }\r
1197 \r
1198         if ( !ndn.bv_len && default_search_nbase.bv_len ) {\r
1199                 ch_free( pdn.bv_val );\r
1200                 ch_free( ndn.bv_val );\r
1201 \r
1202                 ber_dupbv( &pdn, &default_search_base );\r
1203                 ber_dupbv( &ndn, &default_search_nbase );\r
1204         }\r
1205 \r
1206         if ( slapi_control_present( controls,\r
1207                         LDAP_CONTROL_MANAGEDSAIT, NULL, &isCritical ) ) {\r
1208                 manageDsaIt = 1;\r
1209         }\r
1210 \r
1211         be = select_backend( &ndn, manageDsaIt, 0 );\r
1212         if ( be == NULL ) {\r
1213                 if ( manageDsaIt == 1 ) {\r
1214                         rc = LDAP_NO_SUCH_OBJECT;\r
1215                 } else {\r
1216                         rc = LDAP_PARTIAL_RESULTS;\r
1217                 }\r
1218                 goto cleanup;\r
1219         } \r
1220 \r
1221         op->o_ndn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );\r
1222         op->o_ndn.bv_len = be->be_rootdn.bv_len;\r
1223         c->c_dn.bv_val = slapi_ch_strdup( be->be_rootdn.bv_val );\r
1224         c->c_dn.bv_len = be->be_rootdn.bv_len;\r
1225 \r
1226         if ( be->be_search ) {\r
1227                 rc = (*be->be_search)( be, c, op, &pdn, &ndn,\r
1228                         scope, deref, sizelimit, timelimit,\r
1229                         filter, &fstr, an, attrsonly );\r
1230                 if ( rc == 0 ) {\r
1231                         rc = LDAP_SUCCESS;\r
1232                 } else {\r
1233                         rc = LDAP_OPERATIONS_ERROR;\r
1234                 }\r
1235         } else {\r
1236                 rc = LDAP_UNWILLING_TO_PERFORM;\r
1237         }\r
1238 \r
1239 cleanup:\r
1240 \r
1241         if ( ptr != NULL )\r
1242                 slapi_pblock_set( ptr, SLAPI_PLUGIN_INTOP_RESULT, (void *)rc );\r
1243 \r
1244         if ( dn.bv_val ) free( dn.bv_val );\r
1245         if ( ndn.bv_val ) free( ndn.bv_val );\r
1246         if ( pdn.bv_val ) free( pdn.bv_val );\r
1247 \r
1248         if ( filter ) slapi_filter_free( filter, 1 );\r
1249         if ( fstr.bv_val ) free ( fstr.bv_val );\r
1250 \r
1251         if ( an != NULL ) free( an );\r
1252 \r
1253         if ( c != NULL ) {\r
1254                 if ( c->c_sb != NULL ) ber_sockbuf_free( c->c_sb );\r
1255                 if ( c->c_dn.bv_val ) slapi_ch_free( (void **)&c->c_dn.bv_val );\r
1256                 if ( op ) {\r
1257                         if ( op->o_ndn.bv_val ) slapi_ch_free( (void **)&op->o_ndn.bv_val );\r
1258                         free( op );\r
1259                 }\r
1260                 pSavePB = ptr;\r
1261                 free( c );\r
1262         }\r
1263         return( pSavePB );\r
1264 #endif /* LDAP_SLAPI */\r
1265         return NULL;\r
1266 }\r
1267 \r
1268 Slapi_PBlock * \r
1269 slapi_search_internal(\r
1270         char *base,\r
1271         int scope,\r
1272         char *filStr, \r
1273         LDAPControl **controls,\r
1274         char **attrs,\r
1275         int attrsonly ) \r
1276 {\r
1277 #if defined(LDAP_SLAPI)\r
1278         return slapi_search_internal_bind( NULL, base, scope, filStr,\r
1279                         controls, attrs, attrsonly );\r
1280 #else\r
1281         return NULL;\r
1282 #endif /* LDAP_SLAPI */\r
1283 }\r
1284 \r