filter.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. /* filter.c - routines for parsing and dealing with filters */
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <sys/types.h>
  42. #ifndef _WIN32
  43. #include <sys/socket.h>
  44. #endif
  45. #include "slap.h"
  46. #include "slapi-plugin.h"
  47. static int
  48. get_filter_list( Connection *conn, BerElement *ber,
  49. struct slapi_filter **f, char **fstr, int maxdepth, int curdepth,
  50. int *subentry_dont_rewrite, int *has_tombstone_filter);
  51. static int get_substring_filter();
  52. static int get_extensible_filter( BerElement *ber, mr_filter_t* );
  53. static int get_filter_internal( Connection *conn, BerElement *ber,
  54. struct slapi_filter **filt, char **fstr, int maxdepth, int curdepth,
  55. int *subentry_dont_rewrite, int *has_tombstone_filter);
  56. static int tombstone_check_filter(Slapi_Filter *f);
  57. static void filter_optimize(Slapi_Filter *f);
  58. /*
  59. * Read a filter off the wire and create a slapi_filter and string representation.
  60. * Both filt and fstr are allocated by this function, so must be freed by the caller.
  61. *
  62. * If the scope is not base and (objectclass=ldapsubentry) does not occur
  63. * in the filter then we add (!(objectclass=ldapsubentry)) to the filter
  64. * so that subentries are not returned.
  65. * If the scope is base or (objectclass=ldapsubentry) occurs in the filter,
  66. * then the caller is explicitly handling subentries himself and so we leave
  67. * the filter as is.
  68. */
  69. int
  70. get_filter( Connection *conn, BerElement *ber, int scope,
  71. struct slapi_filter **filt, char **fstr )
  72. {
  73. int subentry_dont_rewrite = 0; /* Re-write unless we're told not to */
  74. int has_tombstone_filter = 0; /* Check if nsTombstone appears */
  75. int return_value = 0;
  76. char *logbuf = NULL;
  77. size_t logbufsize = 0;
  78. return_value = get_filter_internal(conn, ber, filt, fstr,
  79. config_get_max_filter_nest_level(), /* maximum depth */
  80. 0, /* current depth */
  81. &subentry_dont_rewrite, &has_tombstone_filter);
  82. if (0 == return_value) { /* Don't try to re-write if there was an error */
  83. if (subentry_dont_rewrite || scope == LDAP_SCOPE_BASE)
  84. (*filt)->f_flags |= SLAPI_FILTER_LDAPSUBENTRY;
  85. if (has_tombstone_filter)
  86. (*filt)->f_flags |= SLAPI_FILTER_TOMBSTONE;
  87. }
  88. if (LDAPDebugLevelIsSet( LDAP_DEBUG_FILTER ) && *filt != NULL
  89. && *fstr != NULL) {
  90. logbufsize = strlen(*fstr) + 1;
  91. logbuf = slapi_ch_malloc(logbufsize);
  92. *logbuf = '\0';
  93. slapi_log_error( SLAPI_LOG_FATAL, "get_filter", "before optimize: %s\n",
  94. slapi_filter_to_string(*filt, logbuf, logbufsize), 0, 0 );
  95. }
  96. filter_optimize(*filt);
  97. if (NULL != logbuf) {
  98. slapi_log_error( SLAPI_LOG_FATAL, "get_filter", " after optimize: %s\n",
  99. slapi_filter_to_string(*filt, logbuf, logbufsize), 0, 0 );
  100. slapi_ch_free_string( &logbuf );
  101. }
  102. return return_value;
  103. }
  104. #define FILTER_EQ_FMT "(%s=%s)"
  105. #define FILTER_GE_FMT "(%s>=%s)"
  106. #define FILTER_LE_FMT "(%s<=%s)"
  107. #define FILTER_APROX_FMT "(%s~=%s)"
  108. #define FILTER_EXTENDED_FMT "(%s%s%s%s:=%s)"
  109. #define FILTER_EQ_LEN 4
  110. #define FILTER_GE_LEN 5
  111. #define FILTER_LE_LEN 5
  112. #define FILTER_APROX_LEN 5
  113. /* returns escaped filter string for extended filters only*/
  114. static char *
  115. filter_escape_filter_value_extended(struct slapi_filter *f)
  116. {
  117. char ebuf[BUFSIZ], *ptr;
  118. const char *estr;
  119. estr = escape_filter_value( f->f_mr_value.bv_val, f->f_mr_value.bv_len, ebuf );
  120. ptr = slapi_ch_smprintf(FILTER_EXTENDED_FMT,
  121. f->f_mr_type ? f->f_mr_type : "",
  122. f->f_mr_dnAttrs ? ":dn" : "",
  123. f->f_mr_oid ? ":" : "",
  124. f->f_mr_oid ? f->f_mr_oid : "",
  125. estr );
  126. return ptr;
  127. }
  128. /* returns escaped filter string for EQ, LE, GE and APROX filters */
  129. static char *
  130. filter_escape_filter_value(struct slapi_filter *f, const char *fmt, size_t len)
  131. {
  132. char ebuf[BUFSIZ], *ptr;
  133. const char *estr;
  134. estr = escape_filter_value( f->f_avvalue.bv_val, f->f_avvalue.bv_len, ebuf );
  135. filter_compute_hash(f);
  136. ptr = slapi_ch_smprintf(fmt, f->f_avtype, estr );
  137. return ptr;
  138. }
  139. /*
  140. * get_filter_internal(): extract an LDAP filter from a BerElement and create
  141. * a slapi_filter structure (*filt) and a string equivalent (*fstr).
  142. *
  143. * This function is recursive. It calls itself (to process NOT filters) and
  144. * it calls get_filter_list() for AND and OR filters, and get_filter_list()
  145. * calls this function again.
  146. */
  147. static int
  148. get_filter_internal( Connection *conn, BerElement *ber,
  149. struct slapi_filter **filt, char **fstr, int maxdepth, int curdepth,
  150. int *subentry_dont_rewrite, int *has_tombstone_filter )
  151. {
  152. unsigned long len;
  153. int err;
  154. struct slapi_filter *f;
  155. char *ftmp, *type;
  156. LDAPDebug( LDAP_DEBUG_FILTER, "=> get_filter_internal\n", 0, 0, 0 );
  157. /*
  158. * Track and check the depth of nesting. Use post-increment on
  159. * current depth here because this function is called for the
  160. * top-level filter (which does not count towards the maximum depth).
  161. */
  162. if ( ( curdepth++ > maxdepth ) && ( maxdepth > 0 )) {
  163. *filt = NULL;
  164. *fstr = NULL;
  165. err = LDAP_UNWILLING_TO_PERFORM;
  166. LDAPDebug( LDAP_DEBUG_FILTER, "<= get_filter_internal %d"
  167. " (maximum nesting level of %d exceeded)\n",
  168. err, maxdepth, 0 );
  169. return( err );
  170. }
  171. /*
  172. * A filter looks like this coming in:
  173. * Filter ::= CHOICE {
  174. * and [0] SET OF Filter,
  175. * or [1] SET OF Filter,
  176. * not [2] Filter,
  177. * equalityMatch [3] AttributeValueAssertion,
  178. * substrings [4] SubstringFilter,
  179. * greaterOrEqual [5] AttributeValueAssertion,
  180. * lessOrEqual [6] AttributeValueAssertion,
  181. * present [7] AttributeType,
  182. * approxMatch [8] AttributeValueAssertion,
  183. * extensibleMatch [9] MatchingRuleAssertion --v3 only
  184. * }
  185. *
  186. * SubstringFilter ::= SEQUENCE {
  187. * type AttributeType,
  188. * SEQUENCE OF CHOICE {
  189. * initial [0] IA5String,
  190. * any [1] IA5String,
  191. * final [2] IA5String
  192. * }
  193. * }
  194. *
  195. * The extensibleMatch was added in LDAPv3:
  196. *
  197. * MatchingRuleAssertion ::= SEQUENCE {
  198. * matchingRule [1] MatchingRuleID OPTIONAL,
  199. * type [2] AttributeDescription OPTIONAL,
  200. * matchValue [3] AssertionValue,
  201. * dnAttributes [4] BOOLEAN DEFAULT FALSE
  202. * }
  203. */
  204. f = (struct slapi_filter *) slapi_ch_calloc( 1, sizeof(struct slapi_filter) );
  205. err = 0;
  206. *fstr = NULL;
  207. f->f_choice = ber_peek_tag( ber, &len );
  208. switch ( f->f_choice ) {
  209. case LDAP_FILTER_EQUALITY:
  210. LDAPDebug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
  211. if ( (err = get_ava( ber, &f->f_ava )) == 0 ) {
  212. if ( 0 == strcasecmp ( f->f_avtype, "objectclass")) {
  213. /* Process objectclass oid's here */
  214. if (strchr (f->f_avvalue.bv_val, '.')) {
  215. char *ocname = oc_find_name( f->f_avvalue.bv_val );
  216. if ( NULL != ocname ) {
  217. slapi_ch_free((void**)&f->f_avvalue.bv_val );
  218. f->f_avvalue.bv_val = ocname;
  219. f->f_avvalue.bv_len = strlen ( f->f_avvalue.bv_val );
  220. }
  221. }
  222. /*
  223. * Process subentry searches here.
  224. * Only set (*subentry_dont_rewrite) if it's not already set.
  225. */
  226. if (!(*subentry_dont_rewrite)) {
  227. *subentry_dont_rewrite = subentry_check_filter(f);
  228. }
  229. /*
  230. * Check if it's a Tomstone filter.
  231. * We need to do it once per filter, so if flag is already set,
  232. * don't bother doing it
  233. */
  234. if (!(*has_tombstone_filter)) {
  235. *has_tombstone_filter = tombstone_check_filter(f);
  236. }
  237. }
  238. *fstr=filter_escape_filter_value(f, FILTER_EQ_FMT, FILTER_EQ_LEN);
  239. }
  240. break;
  241. case LDAP_FILTER_SUBSTRINGS:
  242. LDAPDebug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
  243. err = get_substring_filter( conn, ber, f, fstr );
  244. break;
  245. case LDAP_FILTER_GE:
  246. LDAPDebug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
  247. if ( (err = get_ava( ber, &f->f_ava )) == 0 ) {
  248. *fstr=filter_escape_filter_value(f, FILTER_GE_FMT, FILTER_GE_LEN);
  249. }
  250. break;
  251. case LDAP_FILTER_LE:
  252. LDAPDebug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
  253. if ( (err = get_ava( ber, &f->f_ava )) == 0 ) {
  254. *fstr=filter_escape_filter_value(f, FILTER_LE_FMT, FILTER_LE_LEN);
  255. }
  256. break;
  257. case LDAP_FILTER_PRESENT:
  258. LDAPDebug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
  259. if ( ber_scanf( ber, "a", &type ) == LBER_ERROR ) {
  260. err = LDAP_PROTOCOL_ERROR;
  261. } else {
  262. err = LDAP_SUCCESS;
  263. f->f_type = slapi_attr_syntax_normalize( type );
  264. free( type );
  265. filter_compute_hash(f);
  266. *fstr = slapi_ch_smprintf( "(%s=*)", f->f_type );
  267. }
  268. break;
  269. case LDAP_FILTER_APPROX:
  270. LDAPDebug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
  271. if ( (err = get_ava( ber, &f->f_ava )) == 0 ) {
  272. *fstr=filter_escape_filter_value(f, FILTER_APROX_FMT, FILTER_APROX_LEN);
  273. }
  274. break;
  275. case LDAP_FILTER_EXTENDED:
  276. LDAPDebug( LDAP_DEBUG_FILTER, "EXTENDED\n", 0, 0, 0 );
  277. if ( conn->c_ldapversion < 3 ) {
  278. LDAPDebug( LDAP_DEBUG_ANY,
  279. "extensible filter received from v2 client\n",
  280. 0, 0, 0 );
  281. err = LDAP_PROTOCOL_ERROR;
  282. } else if ( (err = get_extensible_filter( ber, &f->f_mr )) == LDAP_SUCCESS ) {
  283. *fstr=filter_escape_filter_value_extended(f);
  284. LDAPDebug (LDAP_DEBUG_FILTER, "%s\n", *fstr, 0, 0);
  285. if(f->f_mr_oid==NULL) {
  286. /*
  287. * We accept:
  288. * A) attr ":=" value
  289. * B) attr ":dn" ":=" value
  290. */
  291. err = LDAP_SUCCESS;
  292. } else {
  293. err = plugin_mr_filter_create (&f->f_mr);
  294. }
  295. }
  296. break;
  297. case LDAP_FILTER_AND:
  298. LDAPDebug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 );
  299. if ( (err = get_filter_list( conn, ber, &f->f_and, &ftmp, maxdepth,
  300. curdepth, subentry_dont_rewrite, has_tombstone_filter ))
  301. == 0 ) {
  302. filter_compute_hash(f);
  303. *fstr = slapi_ch_smprintf( "(&%s)", ftmp );
  304. slapi_ch_free((void**)&ftmp );
  305. }
  306. break;
  307. case LDAP_FILTER_OR:
  308. LDAPDebug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 );
  309. if ( (err = get_filter_list( conn, ber, &f->f_or, &ftmp, maxdepth,
  310. curdepth, subentry_dont_rewrite, has_tombstone_filter ))
  311. == 0 ) {
  312. filter_compute_hash(f);
  313. *fstr = slapi_ch_smprintf( "(|%s)", ftmp );
  314. slapi_ch_free((void**)&ftmp );
  315. }
  316. break;
  317. case LDAP_FILTER_NOT:
  318. LDAPDebug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 );
  319. (void) ber_skip_tag( ber, &len );
  320. if ( (err = get_filter_internal( conn, ber, &f->f_not, &ftmp, maxdepth,
  321. curdepth, subentry_dont_rewrite, has_tombstone_filter ))
  322. == 0 ) {
  323. filter_compute_hash(f);
  324. *fstr = slapi_ch_smprintf( "(!%s)", ftmp );
  325. slapi_ch_free((void**)&ftmp );
  326. }
  327. break;
  328. default:
  329. LDAPDebug( LDAP_DEBUG_ANY, "get_filter_internal: unknown type 0x%lX\n",
  330. f->f_choice, 0, 0 );
  331. err = LDAP_PROTOCOL_ERROR;
  332. break;
  333. }
  334. if ( err != 0 ) {
  335. slapi_filter_free( f, 1 );
  336. f = NULL;
  337. slapi_ch_free( (void**)fstr );
  338. }
  339. *filt = f;
  340. LDAPDebug( LDAP_DEBUG_FILTER, "<= get_filter_internal %d\n", err, 0, 0 );
  341. return( err );
  342. }
  343. static int
  344. get_filter_list( Connection *conn, BerElement *ber,
  345. struct slapi_filter **f, char **fstr, int maxdepth,
  346. int curdepth, int *subentry_dont_rewrite,
  347. int *has_tombstone_filter)
  348. {
  349. struct slapi_filter **new;
  350. int err;
  351. unsigned long tag, len;
  352. char *last;
  353. LDAPDebug( LDAP_DEBUG_FILTER, "=> get_filter_list\n", 0, 0, 0 );
  354. *fstr = NULL;
  355. new = f;
  356. for ( tag = ber_first_element( ber, &len, &last );
  357. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  358. tag = ber_next_element( ber, &len, last ) ) {
  359. char *ftmp;
  360. if ( (err = get_filter_internal( conn, ber, new, &ftmp, maxdepth,
  361. curdepth, subentry_dont_rewrite, has_tombstone_filter))
  362. != 0 ) {
  363. if ( *fstr != NULL ) {
  364. slapi_ch_free((void**)fstr );
  365. }
  366. return( err );
  367. }
  368. if ( *fstr == NULL ) {
  369. *fstr = ftmp;
  370. } else {
  371. *fstr = slapi_ch_realloc( *fstr, strlen( *fstr ) +
  372. strlen( ftmp ) + 1 );
  373. strcat( *fstr, ftmp );
  374. slapi_ch_free((void**)&ftmp );
  375. }
  376. new = &(*new)->f_next;
  377. }
  378. *new = NULL;
  379. if ( tag == LBER_ERROR && *fstr != NULL ) {
  380. slapi_ch_free((void**)fstr );
  381. }
  382. LDAPDebug( LDAP_DEBUG_FILTER, "<= get_filter_list\n", 0, 0, 0 );
  383. return(( *fstr == NULL ) ? LDAP_PROTOCOL_ERROR : 0 );
  384. }
  385. static int
  386. get_substring_filter(
  387. Connection *conn,
  388. BerElement *ber,
  389. struct slapi_filter *f,
  390. char **fstr
  391. )
  392. {
  393. unsigned long tag, len, rc;
  394. char *val, *last, *type;
  395. char ebuf[BUFSIZ];
  396. LDAPDebug( LDAP_DEBUG_FILTER, "=> get_substring_filter\n", 0, 0, 0 );
  397. if ( ber_scanf( ber, "{a", &type ) == LBER_ERROR ) {
  398. return( LDAP_PROTOCOL_ERROR );
  399. }
  400. f->f_sub_type = slapi_attr_syntax_normalize( type );
  401. free( type );
  402. f->f_sub_initial = NULL;
  403. f->f_sub_any = NULL;
  404. f->f_sub_final = NULL;
  405. *fstr = slapi_ch_malloc( strlen( f->f_sub_type ) + 3 );
  406. sprintf( *fstr, "(%s=", f->f_sub_type );
  407. for ( tag = ber_first_element( ber, &len, &last );
  408. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  409. tag = ber_next_element( ber, &len, last ) )
  410. {
  411. rc = ber_scanf( ber, "a", &val );
  412. if ( rc == LBER_ERROR ) {
  413. return( LDAP_PROTOCOL_ERROR );
  414. }
  415. if ( val == NULL || *val == '\0' ) {
  416. if ( val != NULL ) {
  417. free( val );
  418. }
  419. return( LDAP_INVALID_SYNTAX );
  420. }
  421. switch ( tag ) {
  422. case LDAP_SUBSTRING_INITIAL:
  423. LDAPDebug( LDAP_DEBUG_FILTER, " INITIAL\n", 0, 0, 0 );
  424. if ( f->f_sub_initial != NULL ) {
  425. return( LDAP_PROTOCOL_ERROR );
  426. }
  427. f->f_sub_initial = val;
  428. /* jcm: Had to cast away a const */
  429. val = (char*)escape_filter_value( val, -1, ebuf );
  430. *fstr = slapi_ch_realloc( *fstr, strlen( *fstr ) +
  431. strlen( val ) + 1 );
  432. strcat( *fstr, val );
  433. break;
  434. case LDAP_SUBSTRING_ANY:
  435. LDAPDebug( LDAP_DEBUG_FILTER, " ANY\n", 0, 0, 0 );
  436. charray_add( &f->f_sub_any, val );
  437. /* jcm: Had to cast away a const */
  438. val = (char*)escape_filter_value( val, -1, ebuf );
  439. *fstr = slapi_ch_realloc( *fstr, strlen( *fstr ) +
  440. strlen( val ) + 2 );
  441. strcat( *fstr, "*" );
  442. strcat( *fstr, val );
  443. break;
  444. case LDAP_SUBSTRING_FINAL:
  445. LDAPDebug( LDAP_DEBUG_FILTER, " FINAL\n", 0, 0, 0 );
  446. if ( f->f_sub_final != NULL ) {
  447. return( LDAP_PROTOCOL_ERROR );
  448. }
  449. f->f_sub_final = val;
  450. /* jcm: Had to cast away a const */
  451. val = (char*)escape_filter_value( val, -1, ebuf );
  452. *fstr = slapi_ch_realloc( *fstr, strlen( *fstr ) +
  453. strlen( val ) + 2 );
  454. strcat( *fstr, "*" );
  455. strcat( *fstr, val );
  456. break;
  457. default:
  458. LDAPDebug( LDAP_DEBUG_FILTER, " unknown tag 0x%lX\n", tag, 0, 0 );
  459. return( LDAP_PROTOCOL_ERROR );
  460. }
  461. }
  462. if ( tag == LBER_ERROR ) {
  463. return( LDAP_PROTOCOL_ERROR );
  464. }
  465. if ( f->f_sub_initial == NULL && f->f_sub_any == NULL &&
  466. f->f_sub_final == NULL ) {
  467. return( LDAP_PROTOCOL_ERROR );
  468. }
  469. filter_compute_hash(f);
  470. *fstr = slapi_ch_realloc( *fstr, strlen( *fstr ) + 3 );
  471. if ( f->f_sub_final == NULL ) {
  472. strcat( *fstr, "*" );
  473. }
  474. strcat( *fstr, ")" );
  475. LDAPDebug( LDAP_DEBUG_FILTER, "<= get_substring_filter\n", 0, 0, 0 );
  476. return( 0 );
  477. }
  478. static int
  479. get_extensible_filter( BerElement *ber, mr_filter_t* mrf )
  480. {
  481. int gotelem, gotoid, gotvalue;
  482. unsigned long tag, len;
  483. char *last;
  484. int rc = LDAP_PROTOCOL_ERROR;
  485. LDAPDebug( LDAP_DEBUG_FILTER, "=> get_extensible_filter\n", 0, 0, 0 );
  486. memset (mrf, 0, sizeof (mr_filter_t));
  487. gotelem = gotoid = gotvalue = 0;
  488. for ( tag = ber_first_element( ber, &len, &last );
  489. tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET;
  490. tag = ber_next_element( ber, &len, last ) ) {
  491. /*
  492. * order of elements goes like this:
  493. *
  494. * [oid][type]value[dnattr]
  495. *
  496. * where either oid or type is required.
  497. */
  498. switch ( tag ) {
  499. case LDAP_TAG_MRA_OID:
  500. if ( gotelem != 0 ) {
  501. goto parsing_error;
  502. }
  503. rc = ber_scanf( ber, "a", &mrf->mrf_oid );
  504. gotoid = 1;
  505. gotelem++;
  506. break;
  507. case LDAP_TAG_MRA_TYPE:
  508. if ( gotelem != 0 ) {
  509. if ( gotelem != 1 || gotoid != 1 ) {
  510. goto parsing_error;
  511. }
  512. }
  513. {
  514. char* type;
  515. if (ber_scanf( ber, "a", &type ) == LBER_ERROR) {
  516. rc = LDAP_PROTOCOL_ERROR;
  517. } else {
  518. mrf->mrf_type = slapi_attr_syntax_normalize(type);
  519. free (type);
  520. }
  521. }
  522. gotelem++;
  523. break;
  524. case LDAP_TAG_MRA_VALUE:
  525. if ( gotelem != 1 && gotelem != 2 ) {
  526. goto parsing_error;
  527. }
  528. rc = ber_scanf( ber, "o", &mrf->mrf_value );
  529. gotvalue = 1;
  530. gotelem++;
  531. break;
  532. case LDAP_TAG_MRA_DNATTRS:
  533. if ( gotvalue != 1 ) {
  534. goto parsing_error;
  535. }
  536. rc = ber_scanf( ber, "b", &mrf->mrf_dnAttrs );
  537. gotelem++;
  538. break;
  539. default:
  540. goto parsing_error;
  541. }
  542. if ( rc == -1 ) {
  543. goto parsing_error;
  544. }
  545. rc = LDAP_SUCCESS;
  546. }
  547. if ( tag == LBER_ERROR ) {
  548. goto parsing_error;
  549. }
  550. LDAPDebug( LDAP_DEBUG_FILTER, "<= get_extensible_filter %i\n", rc, 0, 0 );
  551. return rc;
  552. parsing_error:;
  553. LDAPDebug( LDAP_DEBUG_ANY, "error parsing extensible filter\n",
  554. 0, 0, 0 );
  555. return( LDAP_PROTOCOL_ERROR );
  556. }
  557. Slapi_Filter *
  558. slapi_filter_dup(Slapi_Filter *f)
  559. {
  560. Slapi_Filter *out = 0;
  561. struct slapi_filter *fl = 0;
  562. struct slapi_filter **outl = 0;
  563. struct slapi_filter *lastout = 0;
  564. if ( f == NULL ) {
  565. return NULL;
  566. }
  567. out = (struct slapi_filter*)calloc(1, sizeof(struct slapi_filter));
  568. if ( out == NULL ) {
  569. LDAPDebug(LDAP_DEBUG_ANY, "slapi_filter_dup: memory allocation error\n",
  570. 0, 0, 0 );
  571. return NULL;
  572. }
  573. out->f_choice = f->f_choice;
  574. out->f_hash = f->f_hash;
  575. LDAPDebug( LDAP_DEBUG_FILTER, "slapi_filter_dup type 0x%lX\n", f->f_choice, 0, 0 );
  576. switch ( f->f_choice ) {
  577. case LDAP_FILTER_EQUALITY:
  578. case LDAP_FILTER_GE:
  579. case LDAP_FILTER_LE:
  580. case LDAP_FILTER_APPROX:
  581. out->f_ava.ava_type = slapi_ch_strdup(f->f_ava.ava_type);
  582. out->f_ava.ava_value.bv_val = slapi_ch_malloc(f->f_ava.ava_value.bv_len+1);
  583. memcpy(out->f_ava.ava_value.bv_val,f->f_ava.ava_value.bv_val,f->f_ava.ava_value.bv_len);
  584. out->f_ava.ava_value.bv_val[f->f_ava.ava_value.bv_len] = 0; /* terminate */
  585. out->f_ava.ava_value.bv_len = f->f_ava.ava_value.bv_len;
  586. break;
  587. case LDAP_FILTER_SUBSTRINGS:
  588. out->f_sub_type = slapi_ch_strdup(f->f_sub_type);
  589. out->f_sub_initial = slapi_ch_strdup(f->f_sub_initial );
  590. out->f_sub_any = charray_dup( f->f_sub_any );
  591. out->f_sub_final = slapi_ch_strdup(f->f_sub_final );
  592. break;
  593. case LDAP_FILTER_PRESENT:
  594. out->f_type = slapi_ch_strdup( f->f_type );
  595. break;
  596. case LDAP_FILTER_AND:
  597. case LDAP_FILTER_OR:
  598. case LDAP_FILTER_NOT:
  599. outl = &out->f_list;
  600. /* out->f_list = slapi_filter_dup(f->f_list);
  601. */
  602. for (fl = f->f_list; fl != NULL; fl = fl->f_next) {
  603. (*outl) = slapi_filter_dup( fl );
  604. (*outl)->f_next = 0;
  605. if(lastout)
  606. lastout->f_next = *outl;
  607. lastout = *outl;
  608. outl = &((*outl)->f_next);
  609. }
  610. break;
  611. case LDAP_FILTER_EXTENDED:
  612. /* something needs to be done here, but Im not sure how to do it
  613. slapi_ch_free((void**)&f->f_mr_oid);
  614. slapi_ch_free((void**)&f->f_mr_type);
  615. slapi_ch_free((void **)&f->f_mr_value.bv_val );
  616. if (f->f_mr.mrf_destroy != NULL) {
  617. Slapi_PBlock pb;
  618. pblock_init (&pb);
  619. if ( ! slapi_pblock_set (&pb, SLAPI_PLUGIN_OBJECT, f->f_mr.mrf_object)) {
  620. f->f_mr.mrf_destroy (&pb);
  621. }
  622. }
  623. */
  624. break;
  625. default:
  626. LDAPDebug(LDAP_DEBUG_FILTER, "slapi_filter_dup: unknown type 0x%lX\n",
  627. f->f_choice, 0, 0 );
  628. break;
  629. }
  630. return out;
  631. }
  632. void
  633. slapi_filter_free( struct slapi_filter *f, int recurse )
  634. {
  635. if ( f == NULL ) {
  636. return;
  637. }
  638. LDAPDebug( LDAP_DEBUG_FILTER, "slapi_filter_free type 0x%lX\n", f->f_choice, 0, 0 );
  639. switch ( f->f_choice ) {
  640. case LDAP_FILTER_EQUALITY:
  641. case LDAP_FILTER_GE:
  642. case LDAP_FILTER_LE:
  643. case LDAP_FILTER_APPROX:
  644. ava_done( &f->f_ava );
  645. break;
  646. case LDAP_FILTER_SUBSTRINGS:
  647. slapi_ch_free((void**)&f->f_sub_type );
  648. slapi_ch_free((void**)&f->f_sub_initial );
  649. charray_free( f->f_sub_any );
  650. slapi_ch_free((void**)&f->f_sub_final );
  651. break;
  652. case LDAP_FILTER_PRESENT:
  653. slapi_ch_free((void**)&f->f_type );
  654. break;
  655. case LDAP_FILTER_AND:
  656. case LDAP_FILTER_OR:
  657. case LDAP_FILTER_NOT:
  658. if ( recurse ) {
  659. struct slapi_filter *fl, *next;
  660. for (fl = f->f_list; fl != NULL; fl = next) {
  661. next = fl->f_next;
  662. fl->f_next = NULL;
  663. slapi_filter_free( fl, recurse );
  664. fl = next;
  665. }
  666. }
  667. break;
  668. case LDAP_FILTER_EXTENDED:
  669. slapi_ch_free((void**)&f->f_mr_oid);
  670. slapi_ch_free((void**)&f->f_mr_type);
  671. slapi_ch_free((void **)&f->f_mr_value.bv_val );
  672. if (f->f_mr.mrf_destroy != NULL) {
  673. Slapi_PBlock pb;
  674. pblock_init (&pb);
  675. if ( ! slapi_pblock_set (&pb, SLAPI_PLUGIN_OBJECT, f->f_mr.mrf_object)) {
  676. f->f_mr.mrf_destroy (&pb);
  677. }
  678. }
  679. break;
  680. default:
  681. LDAPDebug( LDAP_DEBUG_ANY, "slapi_filter_free: unknown type 0x%lX\n",
  682. f->f_choice, 0, 0 );
  683. break;
  684. }
  685. slapi_ch_free((void**)&f);
  686. }
  687. #if 0
  688. static void
  689. filter_list_insert( struct slapi_filter **into, struct slapi_filter *from )
  690. {
  691. struct slapi_filter *f;
  692. if (into == NULL || from == NULL) return;
  693. if (*into != NULL) {
  694. for (f = from; f->f_next != NULL; f = f->f_next);
  695. f->f_next = *into;
  696. }
  697. *into = from;
  698. }
  699. #endif
  700. struct slapi_filter *
  701. slapi_filter_join( int ftype, struct slapi_filter *f1, struct slapi_filter *f2)
  702. {
  703. return slapi_filter_join_ex( ftype, f1, f2, 1 );
  704. }
  705. struct slapi_filter *
  706. slapi_filter_join_ex( int ftype, struct slapi_filter *f1, struct slapi_filter *f2, int recurse_always )
  707. {
  708. struct slapi_filter *fjoin;
  709. struct slapi_filter *add_to;
  710. struct slapi_filter *add_this;
  711. struct slapi_filter *return_this;
  712. int insert = 0;
  713. if(!recurse_always)
  714. {
  715. /* try to optimise the filter join */
  716. switch(ftype)
  717. {
  718. case LDAP_FILTER_AND:
  719. case LDAP_FILTER_OR:
  720. if(ftype == (int)f1->f_choice)
  721. {
  722. add_to = f1;
  723. add_this = f2;
  724. insert = 1;
  725. }
  726. else if(ftype == (int)f2->f_choice)
  727. {
  728. add_to = f2;
  729. add_this = f1;
  730. insert = 1;
  731. }
  732. default:
  733. break;
  734. }
  735. }
  736. if(insert)
  737. {
  738. /* try to avoid ! filters as the first arg */
  739. if(add_to->f_list->f_choice == LDAP_FILTER_NOT)
  740. {
  741. add_this->f_next = add_to->f_list;
  742. add_to->f_list = add_this;
  743. filter_compute_hash(add_to);
  744. return_this = add_to;
  745. }
  746. else
  747. {
  748. /* find end of list, add the filter */
  749. for (fjoin = add_to->f_list; fjoin != NULL; fjoin = fjoin->f_next) {
  750. if(fjoin->f_next == NULL)
  751. {
  752. fjoin->f_next = add_this;
  753. filter_compute_hash(add_to);
  754. return_this = add_to;
  755. break;
  756. }
  757. }
  758. }
  759. }
  760. else
  761. {
  762. fjoin = (struct slapi_filter *) slapi_ch_calloc( 1, sizeof(struct slapi_filter) );
  763. fjoin->f_choice = ftype;
  764. fjoin->f_next = NULL;
  765. /* try to ensure ! filters dont cause allid search */
  766. if(f1->f_choice == LDAP_FILTER_NOT && f2)
  767. {
  768. fjoin->f_list = f2;
  769. f2->f_next = f1;
  770. }
  771. else
  772. {
  773. fjoin->f_list = f1;
  774. f1->f_next = f2;
  775. }
  776. filter_compute_hash(fjoin);
  777. return_this = fjoin;
  778. }
  779. return( return_this );
  780. }
  781. int
  782. slapi_filter_get_choice( struct slapi_filter *f )
  783. {
  784. return( f->f_choice );
  785. }
  786. int
  787. slapi_filter_get_ava( struct slapi_filter *f, char **type, struct berval **bval )
  788. {
  789. switch ( f->f_choice ) {
  790. case LDAP_FILTER_EQUALITY:
  791. case LDAP_FILTER_GE:
  792. case LDAP_FILTER_LE:
  793. case LDAP_FILTER_APPROX:
  794. break;
  795. default:
  796. *type = NULL;
  797. *bval = NULL;
  798. return( -1 );
  799. }
  800. *type = f->f_avtype;
  801. *bval = &f->f_avvalue;
  802. return( 0 );
  803. }
  804. /* Deprecated--use slapi_filter_get_attribute_type() now */
  805. SLAPI_DEPRECATED int
  806. slapi_filter_get_type( struct slapi_filter *f, char **type )
  807. {
  808. if ( f->f_choice != LDAP_FILTER_PRESENT ) {
  809. return( -1 );
  810. }
  811. *type = f->f_type;
  812. return( 0 );
  813. }
  814. /*
  815. * Return the attribute type for all simple filter choices into type.
  816. * ie. for all except LDAP_FILTER_AND, LDAP_FILTER_OR and LDAP_FILTER_NOT.
  817. *
  818. * The returned type is "as is" and so may not be normalized.
  819. * Returns 0 for success, -1 otherwise.
  820. */
  821. int
  822. slapi_filter_get_attribute_type( Slapi_Filter *f, char **type )
  823. {
  824. if ( f == NULL ) {
  825. return -1;
  826. }
  827. switch ( f->f_choice ) {
  828. case LDAP_FILTER_GE:
  829. case LDAP_FILTER_LE:
  830. case LDAP_FILTER_APPROX:
  831. case LDAP_FILTER_EQUALITY:
  832. *type = f->f_ava.ava_type;
  833. break;
  834. case LDAP_FILTER_SUBSTRINGS:
  835. *type = f->f_sub_type;
  836. break;
  837. case LDAP_FILTER_PRESENT:
  838. *type = f->f_type;
  839. break;
  840. case LDAP_FILTER_EXTENDED:
  841. *type = f->f_mr_type;
  842. break;
  843. case LDAP_FILTER_AND:
  844. case LDAP_FILTER_OR:
  845. case LDAP_FILTER_NOT:
  846. return(-1);
  847. default:
  848. /* Unknown filter choice */
  849. return -1;
  850. }
  851. /* success */
  852. return(0);
  853. }
  854. struct slapi_filter *
  855. slapi_filter_list_first( struct slapi_filter *f )
  856. {
  857. if ( f->f_choice != LDAP_FILTER_AND && f->f_choice != LDAP_FILTER_OR
  858. && f->f_choice != LDAP_FILTER_NOT ) {
  859. return( NULL );
  860. }
  861. return( f->f_list );
  862. }
  863. struct slapi_filter *
  864. slapi_filter_list_next( struct slapi_filter *f, struct slapi_filter *fprev )
  865. {
  866. return( fprev->f_next );
  867. }
  868. int
  869. slapi_filter_get_subfilt(
  870. struct slapi_filter *f,
  871. char **type,
  872. char **initial,
  873. char ***any,
  874. char **final
  875. )
  876. {
  877. if ( f->f_choice != LDAP_FILTER_SUBSTRINGS ) {
  878. return( -1 );
  879. }
  880. *type = f->f_sub_type;
  881. *initial = f->f_sub_initial;
  882. *any = f->f_sub_any;
  883. *final = f->f_sub_final;
  884. return( 0 );
  885. }
  886. static void
  887. filter_normalize_ava( struct ava *ava, int ftype )
  888. {
  889. char *tmp;
  890. if ( ava == NULL ) {
  891. return;
  892. }
  893. tmp = ava->ava_type;
  894. ava->ava_type = slapi_attr_syntax_normalize(tmp);
  895. slapi_ch_free((void**)&tmp );
  896. /* value will be normalized later */
  897. }
  898. void filter_normalize( struct slapi_filter *f );
  899. static void
  900. filter_normalize_list( struct slapi_filter *flist )
  901. {
  902. struct slapi_filter *f;
  903. for ( f = flist; f != NULL; f = f->f_next ) {
  904. filter_normalize( f );
  905. }
  906. }
  907. /*
  908. * Normalize all values and types in a filter. This isn't necessary
  909. * when we've read the slapi_filter off the wire, but if we've hand-constructed
  910. * a filter inside slapd (e.g. when calling the routines in wrapper.c),
  911. * we've called slapi_str2filter on something which *didn't* come over the wire,
  912. * so the attribute names and filters in the filter struct aren't
  913. * normalized.
  914. */
  915. void
  916. filter_normalize( struct slapi_filter *f )
  917. {
  918. char *tmp;
  919. if ( f == NULL ) {
  920. return;
  921. }
  922. switch ( f->f_choice ) {
  923. case LDAP_FILTER_GE:
  924. case LDAP_FILTER_LE:
  925. case LDAP_FILTER_APPROX:
  926. case LDAP_FILTER_EQUALITY:
  927. filter_normalize_ava( &f->f_ava, f->f_choice );
  928. break;
  929. case LDAP_FILTER_SUBSTRINGS:
  930. tmp = f->f_sub_type;
  931. f->f_sub_type = slapi_attr_syntax_normalize(tmp);
  932. slapi_ch_free((void**)&tmp );
  933. /* value will be normalized later */
  934. break;
  935. case LDAP_FILTER_PRESENT:
  936. tmp = f->f_type;
  937. f->f_type = slapi_attr_syntax_normalize(tmp);
  938. slapi_ch_free((void**)&tmp );
  939. break;
  940. case LDAP_FILTER_EXTENDED:
  941. tmp = f->f_mr_type;
  942. f->f_mr_type = slapi_attr_syntax_normalize(tmp);
  943. slapi_ch_free((void**)&tmp );
  944. break;
  945. case LDAP_FILTER_AND:
  946. filter_normalize_list( f->f_and );
  947. break;
  948. case LDAP_FILTER_OR:
  949. filter_normalize_list( f->f_or );
  950. break;
  951. case LDAP_FILTER_NOT:
  952. filter_normalize_list( f->f_not );
  953. break;
  954. default:
  955. return;
  956. }
  957. }
  958. void
  959. filter_print( struct slapi_filter *f )
  960. {
  961. int i;
  962. struct slapi_filter *p;
  963. if ( f == NULL ) {
  964. printf( "NULL" );
  965. return;
  966. }
  967. switch ( f->f_choice ) {
  968. case LDAP_FILTER_EQUALITY:
  969. printf( "(%s=%s)", f->f_ava.ava_type,
  970. f->f_ava.ava_value.bv_val );
  971. break;
  972. case LDAP_FILTER_GE:
  973. printf( "(%s>=%s)", f->f_ava.ava_type,
  974. f->f_ava.ava_value.bv_val );
  975. break;
  976. case LDAP_FILTER_LE:
  977. printf( "(%s<=%s)", f->f_ava.ava_type,
  978. f->f_ava.ava_value.bv_val );
  979. break;
  980. case LDAP_FILTER_APPROX:
  981. printf( "(%s~=%s)", f->f_ava.ava_type,
  982. f->f_ava.ava_value.bv_val );
  983. break;
  984. case LDAP_FILTER_SUBSTRINGS:
  985. printf( "(%s=", f->f_sub_type );
  986. if ( f->f_sub_initial != NULL ) {
  987. printf( "%s", f->f_sub_initial );
  988. }
  989. if ( f->f_sub_any != NULL ) {
  990. for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
  991. printf( "*%s", f->f_sub_any[i] );
  992. }
  993. }
  994. if ( f->f_sub_final != NULL ) {
  995. printf( "*%s", f->f_sub_final );
  996. }
  997. printf( ")" );
  998. break;
  999. case LDAP_FILTER_PRESENT:
  1000. printf( "(%s=*)", f->f_type );
  1001. break;
  1002. case LDAP_FILTER_AND:
  1003. case LDAP_FILTER_OR:
  1004. case LDAP_FILTER_NOT:
  1005. printf( "(%c", f->f_choice == LDAP_FILTER_AND ? '&' :
  1006. f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
  1007. for ( p = f->f_list; p != NULL; p = p->f_next ) {
  1008. filter_print( p );
  1009. }
  1010. printf( ")" );
  1011. break;
  1012. default:
  1013. printf( "unknown type 0x%lX", f->f_choice );
  1014. break;
  1015. }
  1016. fflush( stdout );
  1017. }
  1018. /* filter_to_string
  1019. * ----------------
  1020. * translates the supplied filter to
  1021. * the string representation and places
  1022. * the result in buf
  1023. *
  1024. * NOTE: intended for debug purposes, buffer must be
  1025. * large enough to contain filter string
  1026. */
  1027. char *
  1028. slapi_filter_to_string_internal( const struct slapi_filter *f, char *buf, size_t *bufsize )
  1029. {
  1030. int i;
  1031. char *return_buf = buf;
  1032. struct slapi_filter *p;
  1033. size_t size;
  1034. char *operator = ""; /* for comparison operators */
  1035. if(buf == NULL)
  1036. return 0;
  1037. else
  1038. *buf = 0; /* make sure buf is null terminated */
  1039. if ( f == NULL ) {
  1040. sprintf( buf, "NULL" );
  1041. return 0;
  1042. }
  1043. switch ( f->f_choice ) {
  1044. case LDAP_FILTER_EQUALITY:
  1045. operator = "=";
  1046. break;
  1047. case LDAP_FILTER_GE:
  1048. operator = ">=";
  1049. break;
  1050. case LDAP_FILTER_LE:
  1051. operator = "<=";
  1052. break;
  1053. case LDAP_FILTER_APPROX:
  1054. operator = "~=";
  1055. break;
  1056. default: break;
  1057. }
  1058. switch ( f->f_choice ) {
  1059. case LDAP_FILTER_EQUALITY:
  1060. case LDAP_FILTER_GE:
  1061. case LDAP_FILTER_LE:
  1062. case LDAP_FILTER_APPROX:
  1063. /* +3 -> 1 for (, 1 for ), and one for the trailing null */
  1064. size = strlen(f->f_ava.ava_type) + f->f_ava.ava_value.bv_len + strlen(operator) + 3;
  1065. if(size < *bufsize)
  1066. {
  1067. /* bv_val may not be null terminated, so use the max field width
  1068. specifier .* with the bv_len as the length to avoid reading
  1069. past bv_len in bv_val */
  1070. sprintf( buf, "(%s%s%.*s)", f->f_ava.ava_type, operator,
  1071. (int)f->f_ava.ava_value.bv_len,
  1072. f->f_ava.ava_value.bv_val );
  1073. *bufsize -= size;
  1074. }
  1075. break;
  1076. case LDAP_FILTER_SUBSTRINGS:
  1077. size = strlen(f->f_sub_type) + 2;
  1078. if(size < *bufsize)
  1079. {
  1080. sprintf( buf, "(%s=", f->f_sub_type );
  1081. *bufsize -= size;
  1082. if ( f->f_sub_initial != NULL ) {
  1083. size = strlen(f->f_sub_initial);
  1084. if(size < *bufsize)
  1085. {
  1086. buf += strlen(buf);
  1087. sprintf( buf, "%s", f->f_sub_initial );
  1088. *bufsize -= size;
  1089. }
  1090. }
  1091. if ( f->f_sub_any != NULL ) {
  1092. for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
  1093. size = strlen(f->f_sub_any[i]) + 1;
  1094. if(size < *bufsize)
  1095. {
  1096. buf += strlen(buf);
  1097. sprintf( buf, "*%s", f->f_sub_any[i] );
  1098. *bufsize -= size;
  1099. }
  1100. }
  1101. }
  1102. if ( f->f_sub_final != NULL ) {
  1103. size = strlen(f->f_sub_final) + 1;
  1104. if(size < *bufsize)
  1105. {
  1106. buf += strlen(buf);
  1107. sprintf( buf, "*%s", f->f_sub_final );
  1108. *bufsize -= size;
  1109. }
  1110. }
  1111. buf += strlen(buf);
  1112. if(1 < *bufsize)
  1113. {
  1114. sprintf( buf, ")" );
  1115. *bufsize--;
  1116. }
  1117. }
  1118. break;
  1119. case LDAP_FILTER_PRESENT:
  1120. size = strlen(f->f_type) + 4;
  1121. if(size < *bufsize)
  1122. {
  1123. sprintf( buf, "(%s=*)", f->f_type );
  1124. *bufsize -= size;
  1125. }
  1126. break;
  1127. case LDAP_FILTER_AND:
  1128. case LDAP_FILTER_OR:
  1129. case LDAP_FILTER_NOT:
  1130. if(2 < *bufsize)
  1131. {
  1132. sprintf( buf, "(%c", f->f_choice == LDAP_FILTER_AND ? '&' :
  1133. f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
  1134. *bufsize -= 2;
  1135. for ( p = f->f_list; p != NULL; p = p->f_next ) {
  1136. buf += strlen(buf);
  1137. slapi_filter_to_string_internal( p, buf, bufsize );
  1138. }
  1139. buf += strlen(buf);
  1140. if(1 < *bufsize)
  1141. {
  1142. sprintf( buf, ")" );
  1143. *bufsize--;
  1144. }
  1145. }
  1146. break;
  1147. default:
  1148. size = 25;
  1149. if(size < *bufsize)
  1150. {
  1151. sprintf( buf, "unsupported type 0x%lX", f->f_choice );
  1152. *bufsize -= 25;
  1153. }
  1154. break;
  1155. }
  1156. return return_buf;
  1157. }
  1158. char *
  1159. slapi_filter_to_string( const struct slapi_filter *f, char *buf, size_t bufsize )
  1160. {
  1161. size_t size = bufsize;
  1162. return slapi_filter_to_string_internal( f, buf, &size );
  1163. }
  1164. /* rbyrne */
  1165. static int
  1166. filter_apply_list( struct slapi_filter *flist, FILTER_APPLY_FN fn, caddr_t arg,
  1167. int *error_code )
  1168. {
  1169. struct slapi_filter *f;
  1170. int rc;
  1171. for ( f = flist; f != NULL; f = f->f_next ) {
  1172. rc = slapi_filter_apply( f, fn, arg, error_code );
  1173. if ( rc == SLAPI_FILTER_SCAN_STOP || rc == SLAPI_FILTER_SCAN_ERROR) {
  1174. return(rc);
  1175. }
  1176. }
  1177. /* If we get here we've applied the whole list sucessfully so return 0 */
  1178. return(SLAPI_FILTER_SCAN_NOMORE);
  1179. }
  1180. /*
  1181. *
  1182. * The idea here is to apply, fn() to each "simple filter" in f as follows:
  1183. * fn( Slapi_Filter *simple_filter, caddr_t arg).
  1184. *
  1185. * A 'simple filter' is anything other than AND, OR or NOT.
  1186. *
  1187. * If fn() wants the seasrch to abort it returns FILTER_SCAN_STOP.
  1188. * In this case, FILTER_SCAN_STOP is returned by slapi_filter_apply().
  1189. * Otherwise fn() should return FILTER_SCAN_CONTINUE.
  1190. *
  1191. * If the whole filter is traversed, FILTER_SCAN_NO_MORE is returned.
  1192. * If an error occurred during the traverse, the scan is aborted and
  1193. * FILTER_SCAN_ERROR is returned, and in this case error_code can be checked
  1194. * for more details--right now the only error is
  1195. * SLAPI_FILTER_UNKNOWN_FILTER_TYPE.
  1196. *
  1197. *
  1198. */
  1199. int
  1200. slapi_filter_apply( struct slapi_filter *f, FILTER_APPLY_FN fn, void *arg,
  1201. int *error_code)
  1202. {
  1203. int rc = SLAPI_FILTER_SCAN_ERROR;
  1204. if ( f == NULL ) {
  1205. return SLAPI_FILTER_SCAN_NOMORE;
  1206. }
  1207. switch ( f->f_choice ) {
  1208. case LDAP_FILTER_GE:
  1209. case LDAP_FILTER_LE:
  1210. case LDAP_FILTER_APPROX:
  1211. case LDAP_FILTER_EQUALITY:
  1212. rc = (*fn)(f, arg );
  1213. break;
  1214. case LDAP_FILTER_SUBSTRINGS:
  1215. rc = (*fn)(f, arg);
  1216. /* value will be normalized later */
  1217. break;
  1218. case LDAP_FILTER_PRESENT:
  1219. rc = (*fn)(f, arg);
  1220. break;
  1221. case LDAP_FILTER_EXTENDED:
  1222. rc = (*fn)(f, arg);
  1223. break;
  1224. case LDAP_FILTER_AND:
  1225. rc = filter_apply_list( f->f_and, fn, arg, error_code );
  1226. break;
  1227. case LDAP_FILTER_OR:
  1228. rc = filter_apply_list( f->f_or, fn, arg, error_code );
  1229. break;
  1230. case LDAP_FILTER_NOT:
  1231. rc = filter_apply_list( f->f_not, fn, arg, error_code );
  1232. break;
  1233. default:
  1234. /* Unknown filter choice */
  1235. *error_code = SLAPI_FILTER_UNKNOWN_FILTER_TYPE;
  1236. rc = SLAPI_FILTER_SCAN_ERROR;
  1237. }
  1238. /*
  1239. * We propagate back FILTER_SCAN_ERROR and
  1240. * FILTER_SCAN_STOP, anything else is success.
  1241. */
  1242. if (rc != SLAPI_FILTER_SCAN_ERROR && rc != SLAPI_FILTER_SCAN_STOP) {
  1243. rc = SLAPI_FILTER_SCAN_NOMORE;
  1244. }
  1245. return(rc);
  1246. }
  1247. int
  1248. filter_flag_is_set(const Slapi_Filter *f, unsigned char flag) {
  1249. return(f->f_flags & flag);
  1250. }
  1251. static int
  1252. tombstone_check_filter(Slapi_Filter *f)
  1253. {
  1254. if ( 0 == strcasecmp ( f->f_avvalue.bv_val, SLAPI_ATTR_VALUE_TOMBSTONE)) {
  1255. return 1; /* Contains a nsTombstone filter */
  1256. }
  1257. return 0; /* Not nsTombstone filter */
  1258. }
  1259. /* filter_optimize
  1260. * ---------------
  1261. * takes a filter and optimizes it for fast evaluation
  1262. * currently this merely ensures that any AND or OR
  1263. * does not start with a NOT sub-filter if possible
  1264. */
  1265. static void
  1266. filter_optimize(Slapi_Filter *f)
  1267. {
  1268. if(!f)
  1269. return;
  1270. switch(f->f_choice)
  1271. {
  1272. case LDAP_FILTER_AND:
  1273. case LDAP_FILTER_OR:
  1274. {
  1275. /* first optimize children */
  1276. filter_optimize(f->f_list);
  1277. /* optimize this */
  1278. if(f->f_list->f_choice == LDAP_FILTER_NOT)
  1279. {
  1280. Slapi_Filter *f_prev = 0;
  1281. Slapi_Filter *f_child = 0;
  1282. /* grab a non not filter to place at start */
  1283. for(f_child = f->f_list; f_child != 0; f_child = f_child->f_next)
  1284. {
  1285. if(f_child->f_choice != LDAP_FILTER_NOT)
  1286. {
  1287. /* we have a winner, do swap */
  1288. f_prev->f_next = f_child->f_next;
  1289. f_child->f_next = f->f_list;
  1290. f->f_list = f_child;
  1291. break;
  1292. }
  1293. f_prev = f_child;
  1294. }
  1295. }
  1296. }
  1297. default:
  1298. filter_optimize(f->f_next);
  1299. break;
  1300. }
  1301. }
  1302. /* slapi_filter_changetype
  1303. * ------------------------
  1304. * changes the type used in equality/>/</approx filters
  1305. * handy for features that do type mapping
  1306. */
  1307. int slapi_filter_changetype(Slapi_Filter *f, const char *newtype)
  1308. {
  1309. char **target = 0;
  1310. switch ( f->f_choice ) {
  1311. case LDAP_FILTER_EQUALITY:
  1312. case LDAP_FILTER_GE:
  1313. case LDAP_FILTER_LE:
  1314. case LDAP_FILTER_APPROX:
  1315. target = &f->f_ava.ava_type;
  1316. break;
  1317. case LDAP_FILTER_SUBSTRINGS:
  1318. target = &f->f_sub_type;
  1319. break;
  1320. case LDAP_FILTER_PRESENT:
  1321. target = &f->f_type;
  1322. break;
  1323. case LDAP_FILTER_AND:
  1324. case LDAP_FILTER_OR:
  1325. case LDAP_FILTER_NOT:
  1326. default:
  1327. goto bail;
  1328. break;
  1329. }
  1330. slapi_ch_free_string(target);
  1331. *target = slapi_ch_strdup(newtype);
  1332. bail:
  1333. return (!target);
  1334. }