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