search.c 12 KB

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