search.c revision 1.3 1 1.3 christos /* $NetBSD: search.c,v 1.3 2021/08/14 16:14:56 christos Exp $ */
2 1.2 christos
3 1.2 christos /* $OpenLDAP$ */
4 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 1.1 lukem *
6 1.3 christos * Copyright 1998-2021 The OpenLDAP Foundation.
7 1.1 lukem * All rights reserved.
8 1.1 lukem *
9 1.1 lukem * Redistribution and use in source and binary forms, with or without
10 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
11 1.1 lukem * Public License.
12 1.1 lukem *
13 1.1 lukem * A copy of this license is available in the file LICENSE in the
14 1.1 lukem * top-level directory of the distribution or, alternatively, at
15 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
16 1.1 lukem */
17 1.1 lukem /* Portions Copyright (c) 1990 Regents of the University of Michigan.
18 1.1 lukem * All rights reserved.
19 1.1 lukem */
20 1.1 lukem
21 1.2 christos #include <sys/cdefs.h>
22 1.3 christos __RCSID("$NetBSD: search.c,v 1.3 2021/08/14 16:14:56 christos Exp $");
23 1.2 christos
24 1.1 lukem #include "portable.h"
25 1.1 lukem
26 1.1 lukem #include <stdio.h>
27 1.1 lukem
28 1.1 lukem #include <ac/stdlib.h>
29 1.1 lukem
30 1.1 lukem #include <ac/socket.h>
31 1.1 lukem #include <ac/string.h>
32 1.1 lukem #include <ac/time.h>
33 1.1 lukem
34 1.1 lukem #include "ldap-int.h"
35 1.1 lukem #include "ldap_log.h"
36 1.1 lukem
37 1.1 lukem /*
38 1.1 lukem * ldap_search_ext - initiate an ldap search operation.
39 1.1 lukem *
40 1.1 lukem * Parameters:
41 1.1 lukem *
42 1.1 lukem * ld LDAP descriptor
43 1.1 lukem * base DN of the base object
44 1.1 lukem * scope the search scope - one of
45 1.1 lukem * LDAP_SCOPE_BASE (baseObject),
46 1.1 lukem * LDAP_SCOPE_ONELEVEL (oneLevel),
47 1.1 lukem * LDAP_SCOPE_SUBTREE (subtree), or
48 1.1 lukem * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension
49 1.1 lukem * filter a string containing the search filter
50 1.1 lukem * (e.g., "(|(cn=bob)(sn=bob))")
51 1.1 lukem * attrs list of attribute types to return for matches
52 1.1 lukem * attrsonly 1 => attributes only 0 => attributes and values
53 1.1 lukem *
54 1.1 lukem * Example:
55 1.1 lukem * char *attrs[] = { "mail", "title", 0 };
56 1.1 lukem * ldap_search_ext( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob",
57 1.1 lukem * attrs, attrsonly, sctrls, ctrls, timeout, sizelimit,
58 1.1 lukem * &msgid );
59 1.1 lukem */
60 1.1 lukem int
61 1.1 lukem ldap_search_ext(
62 1.1 lukem LDAP *ld,
63 1.1 lukem LDAP_CONST char *base,
64 1.1 lukem int scope,
65 1.1 lukem LDAP_CONST char *filter,
66 1.1 lukem char **attrs,
67 1.1 lukem int attrsonly,
68 1.1 lukem LDAPControl **sctrls,
69 1.1 lukem LDAPControl **cctrls,
70 1.1 lukem struct timeval *timeout,
71 1.1 lukem int sizelimit,
72 1.1 lukem int *msgidp )
73 1.1 lukem {
74 1.2 christos return ldap_pvt_search( ld, base, scope, filter, attrs,
75 1.2 christos attrsonly, sctrls, cctrls, timeout, sizelimit, -1, msgidp );
76 1.2 christos }
77 1.2 christos
78 1.2 christos int
79 1.2 christos ldap_pvt_search(
80 1.2 christos LDAP *ld,
81 1.2 christos LDAP_CONST char *base,
82 1.2 christos int scope,
83 1.2 christos LDAP_CONST char *filter,
84 1.2 christos char **attrs,
85 1.2 christos int attrsonly,
86 1.2 christos LDAPControl **sctrls,
87 1.2 christos LDAPControl **cctrls,
88 1.2 christos struct timeval *timeout,
89 1.2 christos int sizelimit,
90 1.2 christos int deref,
91 1.2 christos int *msgidp )
92 1.2 christos {
93 1.1 lukem int rc;
94 1.1 lukem BerElement *ber;
95 1.1 lukem int timelimit;
96 1.1 lukem ber_int_t id;
97 1.1 lukem
98 1.3 christos Debug0( LDAP_DEBUG_TRACE, "ldap_search_ext\n" );
99 1.1 lukem
100 1.1 lukem assert( ld != NULL );
101 1.1 lukem assert( LDAP_VALID( ld ) );
102 1.1 lukem
103 1.1 lukem /* check client controls */
104 1.1 lukem rc = ldap_int_client_controls( ld, cctrls );
105 1.1 lukem if( rc != LDAP_SUCCESS ) return rc;
106 1.1 lukem
107 1.1 lukem /*
108 1.1 lukem * if timeout is provided, both tv_sec and tv_usec must
109 1.1 lukem * not be zero
110 1.1 lukem */
111 1.1 lukem if( timeout != NULL ) {
112 1.1 lukem if( timeout->tv_sec == 0 && timeout->tv_usec == 0 ) {
113 1.1 lukem return LDAP_PARAM_ERROR;
114 1.1 lukem }
115 1.1 lukem
116 1.1 lukem /* timelimit must be non-zero if timeout is provided */
117 1.1 lukem timelimit = timeout->tv_sec != 0 ? timeout->tv_sec : 1;
118 1.1 lukem
119 1.1 lukem } else {
120 1.1 lukem /* no timeout, no timelimit */
121 1.1 lukem timelimit = -1;
122 1.1 lukem }
123 1.1 lukem
124 1.1 lukem ber = ldap_build_search_req( ld, base, scope, filter, attrs,
125 1.2 christos attrsonly, sctrls, cctrls, timelimit, sizelimit, deref, &id );
126 1.1 lukem
127 1.1 lukem if ( ber == NULL ) {
128 1.1 lukem return ld->ld_errno;
129 1.1 lukem }
130 1.1 lukem
131 1.1 lukem
132 1.1 lukem /* send the message */
133 1.1 lukem *msgidp = ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id );
134 1.1 lukem
135 1.1 lukem if( *msgidp < 0 )
136 1.1 lukem return ld->ld_errno;
137 1.1 lukem
138 1.1 lukem return LDAP_SUCCESS;
139 1.1 lukem }
140 1.1 lukem
141 1.1 lukem int
142 1.1 lukem ldap_search_ext_s(
143 1.1 lukem LDAP *ld,
144 1.1 lukem LDAP_CONST char *base,
145 1.1 lukem int scope,
146 1.1 lukem LDAP_CONST char *filter,
147 1.1 lukem char **attrs,
148 1.1 lukem int attrsonly,
149 1.1 lukem LDAPControl **sctrls,
150 1.1 lukem LDAPControl **cctrls,
151 1.1 lukem struct timeval *timeout,
152 1.1 lukem int sizelimit,
153 1.1 lukem LDAPMessage **res )
154 1.1 lukem {
155 1.2 christos return ldap_pvt_search_s( ld, base, scope, filter, attrs,
156 1.2 christos attrsonly, sctrls, cctrls, timeout, sizelimit, -1, res );
157 1.2 christos }
158 1.2 christos
159 1.2 christos int
160 1.2 christos ldap_pvt_search_s(
161 1.2 christos LDAP *ld,
162 1.2 christos LDAP_CONST char *base,
163 1.2 christos int scope,
164 1.2 christos LDAP_CONST char *filter,
165 1.2 christos char **attrs,
166 1.2 christos int attrsonly,
167 1.2 christos LDAPControl **sctrls,
168 1.2 christos LDAPControl **cctrls,
169 1.2 christos struct timeval *timeout,
170 1.2 christos int sizelimit,
171 1.2 christos int deref,
172 1.2 christos LDAPMessage **res )
173 1.2 christos {
174 1.1 lukem int rc;
175 1.1 lukem int msgid;
176 1.1 lukem
177 1.2 christos *res = NULL;
178 1.2 christos
179 1.2 christos rc = ldap_pvt_search( ld, base, scope, filter, attrs, attrsonly,
180 1.2 christos sctrls, cctrls, timeout, sizelimit, deref, &msgid );
181 1.1 lukem
182 1.1 lukem if ( rc != LDAP_SUCCESS ) {
183 1.1 lukem return( rc );
184 1.1 lukem }
185 1.1 lukem
186 1.1 lukem rc = ldap_result( ld, msgid, LDAP_MSG_ALL, timeout, res );
187 1.1 lukem
188 1.1 lukem if( rc <= 0 ) {
189 1.1 lukem /* error(-1) or timeout(0) */
190 1.2 christos if ( ld->ld_errno == LDAP_TIMEOUT ) {
191 1.2 christos /* cleanup request */
192 1.2 christos (void) ldap_abandon( ld, msgid );
193 1.2 christos ld->ld_errno = LDAP_TIMEOUT;
194 1.2 christos }
195 1.1 lukem return( ld->ld_errno );
196 1.1 lukem }
197 1.1 lukem
198 1.1 lukem if( rc == LDAP_RES_SEARCH_REFERENCE || rc == LDAP_RES_INTERMEDIATE ) {
199 1.1 lukem return( ld->ld_errno );
200 1.1 lukem }
201 1.1 lukem
202 1.1 lukem return( ldap_result2error( ld, *res, 0 ) );
203 1.1 lukem }
204 1.1 lukem
205 1.1 lukem /*
206 1.1 lukem * ldap_search - initiate an ldap search operation.
207 1.1 lukem *
208 1.1 lukem * Parameters:
209 1.1 lukem *
210 1.1 lukem * ld LDAP descriptor
211 1.1 lukem * base DN of the base object
212 1.1 lukem * scope the search scope - one of
213 1.1 lukem * LDAP_SCOPE_BASE (baseObject),
214 1.1 lukem * LDAP_SCOPE_ONELEVEL (oneLevel),
215 1.1 lukem * LDAP_SCOPE_SUBTREE (subtree), or
216 1.1 lukem * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension
217 1.1 lukem * filter a string containing the search filter
218 1.1 lukem * (e.g., "(|(cn=bob)(sn=bob))")
219 1.1 lukem * attrs list of attribute types to return for matches
220 1.1 lukem * attrsonly 1 => attributes only 0 => attributes and values
221 1.1 lukem *
222 1.1 lukem * Example:
223 1.1 lukem * char *attrs[] = { "mail", "title", 0 };
224 1.1 lukem * msgid = ldap_search( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob",
225 1.1 lukem * attrs, attrsonly );
226 1.1 lukem */
227 1.1 lukem int
228 1.1 lukem ldap_search(
229 1.1 lukem LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter,
230 1.1 lukem char **attrs, int attrsonly )
231 1.1 lukem {
232 1.1 lukem BerElement *ber;
233 1.1 lukem ber_int_t id;
234 1.1 lukem
235 1.3 christos Debug0( LDAP_DEBUG_TRACE, "ldap_search\n" );
236 1.1 lukem
237 1.1 lukem assert( ld != NULL );
238 1.1 lukem assert( LDAP_VALID( ld ) );
239 1.1 lukem
240 1.1 lukem ber = ldap_build_search_req( ld, base, scope, filter, attrs,
241 1.2 christos attrsonly, NULL, NULL, -1, -1, -1, &id );
242 1.1 lukem
243 1.1 lukem if ( ber == NULL ) {
244 1.1 lukem return( -1 );
245 1.1 lukem }
246 1.1 lukem
247 1.1 lukem
248 1.1 lukem /* send the message */
249 1.1 lukem return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id ));
250 1.1 lukem }
251 1.1 lukem
252 1.1 lukem
253 1.1 lukem BerElement *
254 1.1 lukem ldap_build_search_req(
255 1.1 lukem LDAP *ld,
256 1.1 lukem LDAP_CONST char *base,
257 1.1 lukem ber_int_t scope,
258 1.1 lukem LDAP_CONST char *filter,
259 1.1 lukem char **attrs,
260 1.1 lukem ber_int_t attrsonly,
261 1.1 lukem LDAPControl **sctrls,
262 1.1 lukem LDAPControl **cctrls,
263 1.1 lukem ber_int_t timelimit,
264 1.1 lukem ber_int_t sizelimit,
265 1.2 christos ber_int_t deref,
266 1.1 lukem ber_int_t *idp)
267 1.1 lukem {
268 1.1 lukem BerElement *ber;
269 1.1 lukem int err;
270 1.1 lukem
271 1.1 lukem /*
272 1.1 lukem * Create the search request. It looks like this:
273 1.1 lukem * SearchRequest := [APPLICATION 3] SEQUENCE {
274 1.1 lukem * baseObject DistinguishedName,
275 1.1 lukem * scope ENUMERATED {
276 1.1 lukem * baseObject (0),
277 1.1 lukem * singleLevel (1),
278 1.1 lukem * wholeSubtree (2)
279 1.1 lukem * },
280 1.1 lukem * derefAliases ENUMERATED {
281 1.1 lukem * neverDerefaliases (0),
282 1.1 lukem * derefInSearching (1),
283 1.1 lukem * derefFindingBaseObj (2),
284 1.1 lukem * alwaysDerefAliases (3)
285 1.1 lukem * },
286 1.1 lukem * sizelimit INTEGER (0 .. 65535),
287 1.1 lukem * timelimit INTEGER (0 .. 65535),
288 1.1 lukem * attrsOnly BOOLEAN,
289 1.1 lukem * filter Filter,
290 1.1 lukem * attributes SEQUENCE OF AttributeType
291 1.1 lukem * }
292 1.1 lukem * wrapped in an ldap message.
293 1.1 lukem */
294 1.1 lukem
295 1.1 lukem /* create a message to send */
296 1.1 lukem if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
297 1.1 lukem return( NULL );
298 1.1 lukem }
299 1.1 lukem
300 1.1 lukem if ( base == NULL ) {
301 1.1 lukem /* no base provided, use session default base */
302 1.1 lukem base = ld->ld_options.ldo_defbase;
303 1.1 lukem
304 1.1 lukem if ( base == NULL ) {
305 1.1 lukem /* no session default base, use top */
306 1.1 lukem base = "";
307 1.1 lukem }
308 1.1 lukem }
309 1.1 lukem
310 1.1 lukem LDAP_NEXT_MSGID( ld, *idp );
311 1.1 lukem #ifdef LDAP_CONNECTIONLESS
312 1.1 lukem if ( LDAP_IS_UDP(ld) ) {
313 1.2 christos struct sockaddr_storage sa = {0};
314 1.1 lukem /* dummy, filled with ldo_peer in request.c */
315 1.2 christos err = ber_write( ber, (char *) &sa, sizeof( sa ), 0 );
316 1.1 lukem }
317 1.1 lukem if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) {
318 1.1 lukem char *dn = ld->ld_options.ldo_cldapdn;
319 1.1 lukem if (!dn) dn = "";
320 1.1 lukem err = ber_printf( ber, "{ist{seeiib", *idp, dn,
321 1.2 christos LDAP_REQ_SEARCH, base, (ber_int_t) scope,
322 1.2 christos (deref < 0) ? ld->ld_deref : deref,
323 1.1 lukem (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
324 1.1 lukem (timelimit < 0) ? ld->ld_timelimit : timelimit,
325 1.1 lukem attrsonly );
326 1.1 lukem } else
327 1.1 lukem #endif
328 1.1 lukem {
329 1.1 lukem err = ber_printf( ber, "{it{seeiib", *idp,
330 1.2 christos LDAP_REQ_SEARCH, base, (ber_int_t) scope,
331 1.2 christos (deref < 0) ? ld->ld_deref : deref,
332 1.1 lukem (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
333 1.1 lukem (timelimit < 0) ? ld->ld_timelimit : timelimit,
334 1.1 lukem attrsonly );
335 1.1 lukem }
336 1.1 lukem
337 1.1 lukem if ( err == -1 ) {
338 1.1 lukem ld->ld_errno = LDAP_ENCODING_ERROR;
339 1.1 lukem ber_free( ber, 1 );
340 1.1 lukem return( NULL );
341 1.1 lukem }
342 1.1 lukem
343 1.1 lukem if( filter == NULL ) {
344 1.1 lukem filter = "(objectclass=*)";
345 1.1 lukem }
346 1.1 lukem
347 1.1 lukem err = ldap_pvt_put_filter( ber, filter );
348 1.1 lukem
349 1.1 lukem if ( err == -1 ) {
350 1.1 lukem ld->ld_errno = LDAP_FILTER_ERROR;
351 1.1 lukem ber_free( ber, 1 );
352 1.1 lukem return( NULL );
353 1.1 lukem }
354 1.1 lukem
355 1.1 lukem #ifdef LDAP_DEBUG
356 1.1 lukem if ( ldap_debug & LDAP_DEBUG_ARGS ) {
357 1.2 christos char buf[ BUFSIZ ], *ptr = " *";
358 1.1 lukem
359 1.1 lukem if ( attrs != NULL ) {
360 1.2 christos int i, len, rest = sizeof( buf );
361 1.1 lukem
362 1.2 christos for ( i = 0; attrs[ i ] != NULL && rest > 0; i++ ) {
363 1.2 christos ptr = &buf[ sizeof( buf ) - rest ];
364 1.2 christos len = snprintf( ptr, rest, " %s", attrs[ i ] );
365 1.2 christos rest -= (len >= 0 ? len : (int) sizeof( buf ));
366 1.1 lukem }
367 1.1 lukem
368 1.2 christos if ( rest <= 0 ) {
369 1.1 lukem AC_MEMCPY( &buf[ sizeof( buf ) - STRLENOF( "...(truncated)" ) - 1 ],
370 1.1 lukem "...(truncated)", STRLENOF( "...(truncated)" ) + 1 );
371 1.1 lukem }
372 1.2 christos ptr = buf;
373 1.1 lukem }
374 1.1 lukem
375 1.3 christos Debug1( LDAP_DEBUG_ARGS, "ldap_build_search_req ATTRS:%s\n", ptr );
376 1.1 lukem }
377 1.1 lukem #endif /* LDAP_DEBUG */
378 1.1 lukem
379 1.1 lukem if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) {
380 1.1 lukem ld->ld_errno = LDAP_ENCODING_ERROR;
381 1.1 lukem ber_free( ber, 1 );
382 1.1 lukem return( NULL );
383 1.1 lukem }
384 1.1 lukem
385 1.1 lukem /* Put Server Controls */
386 1.1 lukem if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
387 1.1 lukem ber_free( ber, 1 );
388 1.1 lukem return( NULL );
389 1.1 lukem }
390 1.1 lukem
391 1.1 lukem if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
392 1.1 lukem ld->ld_errno = LDAP_ENCODING_ERROR;
393 1.1 lukem ber_free( ber, 1 );
394 1.1 lukem return( NULL );
395 1.1 lukem }
396 1.1 lukem
397 1.1 lukem return( ber );
398 1.1 lukem }
399 1.1 lukem
400 1.1 lukem int
401 1.1 lukem ldap_search_st(
402 1.1 lukem LDAP *ld, LDAP_CONST char *base, int scope,
403 1.1 lukem LDAP_CONST char *filter, char **attrs,
404 1.1 lukem int attrsonly, struct timeval *timeout, LDAPMessage **res )
405 1.1 lukem {
406 1.1 lukem int msgid;
407 1.1 lukem
408 1.2 christos *res = NULL;
409 1.2 christos
410 1.1 lukem if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
411 1.1 lukem == -1 )
412 1.1 lukem return( ld->ld_errno );
413 1.1 lukem
414 1.1 lukem if ( ldap_result( ld, msgid, LDAP_MSG_ALL, timeout, res ) == -1 || !*res )
415 1.1 lukem return( ld->ld_errno );
416 1.1 lukem
417 1.1 lukem if ( ld->ld_errno == LDAP_TIMEOUT ) {
418 1.1 lukem (void) ldap_abandon( ld, msgid );
419 1.1 lukem ld->ld_errno = LDAP_TIMEOUT;
420 1.1 lukem return( ld->ld_errno );
421 1.1 lukem }
422 1.1 lukem
423 1.1 lukem return( ldap_result2error( ld, *res, 0 ) );
424 1.1 lukem }
425 1.1 lukem
426 1.1 lukem int
427 1.1 lukem ldap_search_s(
428 1.1 lukem LDAP *ld,
429 1.1 lukem LDAP_CONST char *base,
430 1.1 lukem int scope,
431 1.1 lukem LDAP_CONST char *filter,
432 1.1 lukem char **attrs,
433 1.1 lukem int attrsonly,
434 1.1 lukem LDAPMessage **res )
435 1.1 lukem {
436 1.1 lukem int msgid;
437 1.1 lukem
438 1.2 christos *res = NULL;
439 1.2 christos
440 1.1 lukem if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
441 1.1 lukem == -1 )
442 1.1 lukem return( ld->ld_errno );
443 1.1 lukem
444 1.1 lukem if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, res ) == -1 || !*res )
445 1.1 lukem return( ld->ld_errno );
446 1.1 lukem
447 1.1 lukem return( ldap_result2error( ld, *res, 0 ) );
448 1.1 lukem }
449 1.1 lukem
450 1.1 lukem static char escape[128] = {
451 1.1 lukem 1, 1, 1, 1, 1, 1, 1, 1,
452 1.1 lukem 1, 1, 1, 1, 1, 1, 1, 1,
453 1.1 lukem 1, 1, 1, 1, 1, 1, 1, 1,
454 1.1 lukem 1, 1, 1, 1, 1, 1, 1, 1,
455 1.1 lukem
456 1.1 lukem 0, 0, 0, 0, 0, 0, 0, 0,
457 1.1 lukem 1, 1, 1, 0, 0, 0, 0, 0,
458 1.1 lukem 0, 0, 0, 0, 0, 0, 0, 0,
459 1.1 lukem 0, 0, 0, 0, 0, 0, 0, 0,
460 1.1 lukem
461 1.1 lukem 0, 0, 0, 0, 0, 0, 0, 0,
462 1.1 lukem 0, 0, 0, 0, 0, 0, 0, 0,
463 1.1 lukem 0, 0, 0, 0, 0, 0, 0, 0,
464 1.1 lukem 0, 0, 0, 0, 1, 0, 0, 0,
465 1.1 lukem
466 1.1 lukem 0, 0, 0, 0, 0, 0, 0, 0,
467 1.1 lukem 0, 0, 0, 0, 0, 0, 0, 0,
468 1.1 lukem 0, 0, 0, 0, 0, 0, 0, 0,
469 1.1 lukem 0, 0, 0, 0, 0, 0, 0, 1
470 1.1 lukem };
471 1.1 lukem #define NEEDFLTESCAPE(c) ((c) & 0x80 || escape[ (unsigned)(c) ])
472 1.1 lukem
473 1.1 lukem /*
474 1.1 lukem * compute the length of the escaped value
475 1.1 lukem */
476 1.1 lukem ber_len_t
477 1.1 lukem ldap_bv2escaped_filter_value_len( struct berval *in )
478 1.1 lukem {
479 1.1 lukem ber_len_t i, l;
480 1.1 lukem
481 1.1 lukem assert( in != NULL );
482 1.1 lukem
483 1.1 lukem if ( in->bv_len == 0 ) {
484 1.1 lukem return 0;
485 1.1 lukem }
486 1.1 lukem
487 1.1 lukem for( l = 0, i = 0; i < in->bv_len; l++, i++ ) {
488 1.1 lukem char c = in->bv_val[ i ];
489 1.1 lukem if ( NEEDFLTESCAPE( c ) ) {
490 1.1 lukem l += 2;
491 1.1 lukem }
492 1.1 lukem }
493 1.1 lukem
494 1.1 lukem return l;
495 1.1 lukem }
496 1.1 lukem
497 1.1 lukem int
498 1.1 lukem ldap_bv2escaped_filter_value( struct berval *in, struct berval *out )
499 1.1 lukem {
500 1.1 lukem return ldap_bv2escaped_filter_value_x( in, out, 0, NULL );
501 1.1 lukem }
502 1.1 lukem
503 1.1 lukem int
504 1.1 lukem ldap_bv2escaped_filter_value_x( struct berval *in, struct berval *out, int inplace, void *ctx )
505 1.1 lukem {
506 1.1 lukem ber_len_t i, l;
507 1.1 lukem
508 1.1 lukem assert( in != NULL );
509 1.1 lukem assert( out != NULL );
510 1.1 lukem
511 1.1 lukem BER_BVZERO( out );
512 1.1 lukem
513 1.1 lukem if ( in->bv_len == 0 ) {
514 1.1 lukem return 0;
515 1.1 lukem }
516 1.1 lukem
517 1.1 lukem /* assume we'll escape everything */
518 1.1 lukem l = ldap_bv2escaped_filter_value_len( in );
519 1.1 lukem if ( l == in->bv_len ) {
520 1.1 lukem if ( inplace ) {
521 1.1 lukem *out = *in;
522 1.1 lukem } else {
523 1.1 lukem ber_dupbv( out, in );
524 1.1 lukem }
525 1.1 lukem return 0;
526 1.1 lukem }
527 1.1 lukem out->bv_val = LDAP_MALLOCX( l + 1, ctx );
528 1.1 lukem if ( out->bv_val == NULL ) {
529 1.1 lukem return -1;
530 1.1 lukem }
531 1.1 lukem
532 1.1 lukem for ( i = 0; i < in->bv_len; i++ ) {
533 1.1 lukem char c = in->bv_val[ i ];
534 1.1 lukem if ( NEEDFLTESCAPE( c ) ) {
535 1.1 lukem assert( out->bv_len < l - 2 );
536 1.1 lukem out->bv_val[out->bv_len++] = '\\';
537 1.1 lukem out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & (c>>4)];
538 1.1 lukem out->bv_val[out->bv_len++] = "0123456789ABCDEF"[0x0f & c];
539 1.1 lukem
540 1.1 lukem } else {
541 1.1 lukem assert( out->bv_len < l );
542 1.1 lukem out->bv_val[out->bv_len++] = c;
543 1.1 lukem }
544 1.1 lukem }
545 1.1 lukem
546 1.1 lukem out->bv_val[out->bv_len] = '\0';
547 1.1 lukem
548 1.1 lukem return 0;
549 1.1 lukem }
550 1.1 lukem
551