cis.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /* cis.c - caseignorestring syntax routines */
  13. /*
  14. * This file actually implements numerous syntax plugins:
  15. *
  16. * Boolean
  17. * CountryString
  18. * DirectoryString
  19. * GeneralizedTime
  20. * OID
  21. * PostalAddress
  22. * PrintableString
  23. */
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <sys/types.h>
  27. #include "syntax.h"
  28. static int cis_filter_ava( Slapi_PBlock *pb, struct berval *bvfilter,
  29. Slapi_Value **bvals, int ftype, Slapi_Value **retVal );
  30. static int cis_filter_sub( Slapi_PBlock *pb, char *initial, char **any,
  31. char *final, Slapi_Value **bvals );
  32. static int cis_values2keys( Slapi_PBlock *pb, Slapi_Value **val,
  33. Slapi_Value ***ivals, int ftype );
  34. static int cis_assertion2keys_ava( Slapi_PBlock *pb, Slapi_Value *val,
  35. Slapi_Value ***ivals, int ftype );
  36. static int cis_assertion2keys_sub( Slapi_PBlock *pb, char *initial, char **any,
  37. char *final, Slapi_Value ***ivals );
  38. static int cis_compare(struct berval *v1, struct berval *v2);
  39. static int dirstring_validate(struct berval *val);
  40. static int boolean_validate(struct berval *val);
  41. static int time_validate(struct berval *val);
  42. static int country_validate(struct berval *val);
  43. static int postal_validate(struct berval *val);
  44. static int oid_validate(struct berval *val);
  45. static int printable_validate(struct berval *val);
  46. static void cis_normalize(
  47. Slapi_PBlock *pb,
  48. char *s,
  49. int trim_spaces,
  50. char **alt
  51. );
  52. /*
  53. Even though the official RFC 4517 says that the postal syntax
  54. line values must contain at least 1 character (i.e. no $$), it
  55. seems that most, if not all, address book and other applications that
  56. use postal address syntax values expect to be able to store empty
  57. lines/values - so for now, allow it
  58. */
  59. static const int postal_allow_empty_lines = 1;
  60. /*
  61. * Attribute syntaxes. We treat all of these the same for now, even though
  62. * the specifications (e.g., RFC 2252) impose various constraints on the
  63. * the format for each of these.
  64. *
  65. * Note: the first name is the official one from RFC 2252.
  66. */
  67. static char *dirstring_names[] = { "DirectoryString", "cis",
  68. "caseignorestring", DIRSTRING_SYNTAX_OID, 0 };
  69. static char *boolean_names[] = { "Boolean", BOOLEAN_SYNTAX_OID, 0 };
  70. static char *time_names[] = { "GeneralizedTime", "time",
  71. GENERALIZEDTIME_SYNTAX_OID, 0 };
  72. #define GENERALIZEDTIMEMATCH_OID "2.5.13.27"
  73. #define GENERALIZEDTIMEORDERINGMATCH_OID "2.5.13.28"
  74. static char *country_names[] = { "Country String",
  75. COUNTRYSTRING_SYNTAX_OID, 0};
  76. static char *postal_names[] = { "Postal Address",
  77. POSTALADDRESS_SYNTAX_OID, 0};
  78. static char *oid_names[] = { "OID",
  79. OID_SYNTAX_OID, 0};
  80. static char *printable_names[] = { "Printable String",
  81. PRINTABLESTRING_SYNTAX_OID, 0};
  82. /*
  83. TBD (XXX)
  84. "1.3.6.1.4.1.1466.115.121.1.16 \"DIT Content Rule Description
  85. \" "
  86. "1.3.6.1.4.1.1466.115.121.1.17 \"DIT Structure Rule Descripti
  87. on\" "
  88. "1.3.6.1.4.1.1466.115.121.1.20 \"DSE Type\" "
  89. "1.3.6.1.4.1.1466.115.121.1.30 \"Matching Rule Description\"
  90. "
  91. "1.3.6.1.4.1.1466.115.121.1.31 \"Matching Rule Use Descriptio
  92. n\" "
  93. "1.3.6.1.4.1.1466.115.121.1.35 \"Name Form Description\" "
  94. "1.3.6.1.4.1.1466.115.121.1.44 \"Printable String\" "
  95. "1.3.6.1.4.1.1466.115.121.1.45 \"Subtree Specification\" "
  96. "1.3.6.1.4.1.1466.115.121.1.54 \"LDAP Syntax Description\" "
  97. "1.3.6.1.4.1.1466.115.121.1.55 \"Modify Rights\" "
  98. "1.3.6.1.4.1.1466.115.121.1.56 \"LDAP Schema Description\" "
  99. "1.3.6.1.4.1.1466.115.121.1.25 \"Guide\" "
  100. "1.3.6.1.4.1.1466.115.121.1.52 \"Telex Number\" "
  101. "1.3.6.1.4.1.1466.115.121.1.51 \"Teletex Terminal Identifier\
  102. " "
  103. "1.3.6.1.4.1.1466.115.121.1.14 \"Delivery Method\" "
  104. "1.3.6.1.4.1.1466.115.121.1.43 \"Presentation Address\" "
  105. "1.3.6.1.4.1.1466.115.121.1.21 \"Enhanced Guide\" "
  106. "1.3.6.1.4.1.1466.115.121.1.34 \"Name and Optional UID\" "
  107. "1.2.840.113556.1.4.905 \"CaseIgnoreString\" "
  108. "1.3.6.1.1.1.0.0 \"nisNetgroupTripleSyntax\" "
  109. "1.3.6.1.1.1.0.1 \"bootParameterSyntax\" ");
  110. */
  111. static Slapi_PluginDesc dirstring_pdesc = { "directorystring-syntax",
  112. VENDOR, DS_PACKAGE_VERSION,
  113. "DirectoryString attribute syntax plugin" };
  114. static Slapi_PluginDesc boolean_pdesc = { "boolean-syntax",
  115. VENDOR, DS_PACKAGE_VERSION,
  116. "Boolean attribute syntax plugin" };
  117. static Slapi_PluginDesc time_pdesc = { "time-syntax",
  118. VENDOR, DS_PACKAGE_VERSION,
  119. "GeneralizedTime attribute syntax plugin" };
  120. static Slapi_PluginDesc country_pdesc = { "countrystring-syntax",
  121. VENDOR, DS_PACKAGE_VERSION,
  122. "Country String attribute syntax plugin" };
  123. static Slapi_PluginDesc postal_pdesc = { "postaladdress-syntax",
  124. VENDOR, DS_PACKAGE_VERSION,
  125. "Postal Address attribute syntax plugin" };
  126. static Slapi_PluginDesc oid_pdesc = { "oid-syntax",
  127. VENDOR, DS_PACKAGE_VERSION,
  128. "OID attribute syntax plugin" };
  129. static Slapi_PluginDesc printable_pdesc = { "printablestring-syntax",
  130. VENDOR, DS_PACKAGE_VERSION,
  131. "Printable String attribtue syntax plugin" };
  132. static const char *generalizedTimeMatch_names[] = {"generalizedTimeMatch", GENERALIZEDTIMEMATCH_OID, NULL};
  133. static const char *generalizedTimeOrderingMatch_names[] = {"generalizedTimeOrderingMatch", GENERALIZEDTIMEORDERINGMATCH_OID, NULL};
  134. static const char *booleanMatch_names[] = {"booleanMatch", "2.5.13.13", NULL};
  135. static const char *caseIgnoreIA5Match_names[] = {"caseIgnoreIA5Match", "1.3.6.1.4.1.1466.109.114.2", NULL};
  136. static const char *caseIgnoreIA5SubstringsMatch_names[] = {"caseIgnoreIA5SubstringsMatch", "1.3.6.1.4.1.1466.109.114.3", NULL};
  137. static const char *caseIgnoreListMatch_names[] = {"caseIgnoreListMatch", "2.5.13.11", NULL};
  138. static const char *caseIgnoreListSubstringsMatch_names[] = {"caseIgnoreListSubstringsMatch", "2.5.13.12", NULL};
  139. static const char *caseIgnoreMatch_names[] = {"caseIgnoreMatch", "2.5.13.2", NULL};
  140. static const char *caseIgnoreOrderingMatch_names[] = {"caseIgnoreOrderingMatch", "2.5.13.3", NULL};
  141. static const char *caseIgnoreSubstringsMatch_names[] = {"caseIgnoreSubstringsMatch", "2.5.13.4", NULL};
  142. static const char *directoryStringFirstComponentMatch_names[] = {"directoryStringFirstComponentMatch", "2.5.13.31", NULL};
  143. static const char *objectIdentifierMatch_names[] = {"objectIdentifierMatch", "2.5.13.0", NULL};
  144. static const char *objectIdentifierFirstComponentMatch_names[] = {"objectIdentifierFirstComponentMatch", "2.5.13.30", NULL};
  145. static char *dirString_syntaxes[] = {COUNTRYSTRING_SYNTAX_OID,
  146. DIRSTRING_SYNTAX_OID,
  147. PRINTABLESTRING_SYNTAX_OID,NULL};
  148. static char *dirStringCompat_syntaxes[] = {COUNTRYSTRING_SYNTAX_OID,
  149. PRINTABLESTRING_SYNTAX_OID,NULL};
  150. static char *caseIgnoreIA5SubstringsMatch_syntaxes[] = {IA5STRING_SYNTAX_OID,NULL};
  151. static char *caseIgnoreListSubstringsMatch_syntaxes[] = {POSTALADDRESS_SYNTAX_OID,NULL};
  152. static char *objectIdentifierFirstComponentMatch_syntaxes[] = {DIRSTRING_SYNTAX_OID, NULL};
  153. static struct mr_plugin_def mr_plugin_table[] = {
  154. {
  155. {
  156. GENERALIZEDTIMEMATCH_OID,
  157. NULL /* no alias? */,
  158. "generalizedTimeMatch",
  159. "The rule evaluates to TRUE if and only if the attribute value represents the same universal coordinated time as the assertion value.",
  160. GENERALIZEDTIME_SYNTAX_OID,
  161. 0 /* not obsolete */,
  162. NULL /* no other syntaxes supported */
  163. },
  164. {
  165. "generalizedTimeMatch-mr",
  166. VENDOR,
  167. DS_PACKAGE_VERSION,
  168. "generalizedTimeMatch matching rule plugin"
  169. }, /* plugin desc */
  170. generalizedTimeMatch_names, /* matching rule name/oid/aliases */
  171. NULL,
  172. NULL,
  173. cis_filter_ava,
  174. NULL,
  175. cis_values2keys,
  176. cis_assertion2keys_ava,
  177. NULL,
  178. cis_compare,
  179. cis_normalize
  180. },
  181. {
  182. {
  183. GENERALIZEDTIMEORDERINGMATCH_OID,
  184. NULL /* no alias? */,
  185. "generalizedTimeOrderingMatch",
  186. "The rule evaluates to TRUE if and only if the attribute value represents a universal coordinated time that is earlier than the universal coordinated time represented by the assertion value.",
  187. GENERALIZEDTIME_SYNTAX_OID,
  188. 0 /* not obsolete */,
  189. NULL /* no other syntaxes supported */
  190. },
  191. {
  192. "generalizedTimeOrderingMatch-mr",
  193. VENDOR,
  194. DS_PACKAGE_VERSION,
  195. "generalizedTimeOrderingMatch matching rule plugin"
  196. }, /* plugin desc */
  197. generalizedTimeOrderingMatch_names, /* matching rule name/oid/aliases */
  198. NULL,
  199. NULL,
  200. cis_filter_ava,
  201. NULL,
  202. cis_values2keys,
  203. cis_assertion2keys_ava,
  204. NULL,
  205. cis_compare,
  206. cis_normalize
  207. },
  208. /* strictly speaking, boolean is case sensitive */
  209. {
  210. {
  211. "2.5.13.13",
  212. NULL,
  213. "booleanMatch",
  214. "The booleanMatch rule compares an assertion value of the Boolean "
  215. "syntax to an attribute value of a syntax (e.g., the Boolean syntax) "
  216. "whose corresponding ASN.1 type is BOOLEAN. "
  217. "The rule evaluates to TRUE if and only if the attribute value and the "
  218. "assertion value are both TRUE or both FALSE.",
  219. BOOLEAN_SYNTAX_OID,
  220. 0,
  221. NULL /* no other syntaxes supported */
  222. }, /* matching rule desc */
  223. {
  224. "booleanMatch-mr",
  225. VENDOR,
  226. DS_PACKAGE_VERSION,
  227. "booleanMatch matching rule plugin"
  228. }, /* plugin desc */
  229. booleanMatch_names, /* matching rule name/oid/aliases */
  230. NULL,
  231. NULL,
  232. cis_filter_ava,
  233. NULL,
  234. cis_values2keys,
  235. cis_assertion2keys_ava,
  236. NULL,
  237. cis_compare,
  238. cis_normalize
  239. },
  240. {
  241. {
  242. "1.3.6.1.4.1.1466.109.114.2",
  243. NULL,
  244. "caseIgnoreIA5Match",
  245. "The caseIgnoreIA5Match rule compares an assertion value of the IA5 "
  246. "String syntax to an attribute value of a syntax (e.g., the IA5 String "
  247. "syntax) whose corresponding ASN.1 type is IA5String. "
  248. "The rule evaluates to TRUE if and only if the prepared attribute "
  249. "value character string and the prepared assertion value character "
  250. "string have the same number of characters and corresponding "
  251. "characters have the same code point. "
  252. "In preparing the attribute value and assertion value for comparison, "
  253. "characters are case folded in the Map preparation step, and only "
  254. "Insignificant Space Handling is applied in the Insignificant "
  255. "Character Handling step.",
  256. IA5STRING_SYNTAX_OID,
  257. 0,
  258. NULL /* no other syntaxes supported */
  259. }, /* matching rule desc */
  260. {
  261. "caseIgnoreIA5Match-mr",
  262. VENDOR,
  263. DS_PACKAGE_VERSION,
  264. "caseIgnoreIA5Match matching rule plugin"
  265. }, /* plugin desc */
  266. caseIgnoreIA5Match_names, /* matching rule name/oid/aliases */
  267. NULL,
  268. NULL,
  269. cis_filter_ava,
  270. NULL,
  271. cis_values2keys,
  272. cis_assertion2keys_ava,
  273. NULL,
  274. cis_compare,
  275. cis_normalize
  276. },
  277. {
  278. {
  279. "1.3.6.1.4.1.1466.109.114.3",
  280. NULL,
  281. "caseIgnoreIA5SubstringsMatch",
  282. "The caseIgnoreIA5SubstringsMatch rule compares an assertion value of "
  283. "the Substring Assertion syntax to an attribute value of a syntax "
  284. "(e.g., the IA5 String syntax) whose corresponding ASN.1 type is "
  285. "IA5String. "
  286. "The rule evaluates to TRUE if and only if (1) the prepared substrings "
  287. "of the assertion value match disjoint portions of the prepared "
  288. "attribute value character string in the order of the substrings in "
  289. "the assertion value, (2) an <initial> substring, if present, matches "
  290. "the beginning of the prepared attribute value character string, and "
  291. "(3) a <final> substring, if present, matches the end of the prepared "
  292. "attribute value character string. A prepared substring matches a "
  293. "portion of the prepared attribute value character string if "
  294. "corresponding characters have the same code point. "
  295. "In preparing the attribute value and assertion value substrings for "
  296. "comparison, characters are case folded in the Map preparation step, "
  297. "and only Insignificant Space Handling is applied in the Insignificant "
  298. "Character Handling step.",
  299. "1.3.6.1.4.1.1466.115.121.1.58",
  300. 0,
  301. caseIgnoreIA5SubstringsMatch_syntaxes
  302. }, /* matching rule desc */
  303. {
  304. "caseIgnoreIA5SubstringsMatch-mr",
  305. VENDOR,
  306. DS_PACKAGE_VERSION,
  307. "caseIgnoreIA5SubstringsMatch matching rule plugin"
  308. }, /* plugin desc */
  309. caseIgnoreIA5SubstringsMatch_names, /* matching rule name/oid/aliases */
  310. NULL,
  311. NULL,
  312. NULL,
  313. cis_filter_sub,
  314. cis_values2keys,
  315. NULL,
  316. cis_assertion2keys_sub,
  317. NULL,
  318. cis_normalize
  319. },
  320. {
  321. {
  322. "2.5.13.2",
  323. NULL,
  324. "caseIgnoreMatch",
  325. "The caseIgnoreMatch rule compares an assertion value of the Directory "
  326. "String syntax to an attribute value of a syntax (e.g., the Directory "
  327. "String, Printable String, Country String, or Telephone Number syntax) "
  328. "whose corresponding ASN.1 type is DirectoryString or one of its "
  329. "alternative string types. "
  330. "The rule evaluates to TRUE if and only if the prepared attribute "
  331. "value character string and the prepared assertion value character "
  332. "string have the same number of characters and corresponding "
  333. "characters have the same code point. "
  334. "In preparing the attribute value and assertion value for comparison, "
  335. "characters are case folded in the Map preparation step, and only "
  336. "Insignificant Space Handling is applied in the Insignificant "
  337. "Character Handling step.",
  338. DIRSTRING_SYNTAX_OID,
  339. 0,
  340. dirStringCompat_syntaxes
  341. }, /* matching rule desc */
  342. {
  343. "caseIgnoreMatch-mr",
  344. VENDOR,
  345. DS_PACKAGE_VERSION,
  346. "caseIgnoreMatch matching rule plugin"
  347. }, /* plugin desc */
  348. caseIgnoreMatch_names, /* matching rule name/oid/aliases */
  349. NULL,
  350. NULL,
  351. cis_filter_ava,
  352. NULL,
  353. cis_values2keys,
  354. cis_assertion2keys_ava,
  355. NULL,
  356. cis_compare,
  357. cis_normalize
  358. },
  359. {
  360. {
  361. "2.5.13.3",
  362. NULL,
  363. "caseIgnoreOrderingMatch",
  364. "The caseIgnoreOrderingMatch rule compares an assertion value of the "
  365. "Directory String syntax to an attribute value of a syntax (e.g., the "
  366. "Directory String, Printable String, Country String, or Telephone "
  367. "Number syntax) whose corresponding ASN.1 type is DirectoryString or "
  368. "one of its alternative string types. "
  369. "The rule evaluates to TRUE if and only if, in the code point "
  370. "collation order, the prepared attribute value character string "
  371. "appears earlier than the prepared assertion value character string; "
  372. "i.e., the attribute value is \"less than\" the assertion value. "
  373. "In preparing the attribute value and assertion value for comparison, "
  374. "characters are case folded in the Map preparation step, and only "
  375. "Insignificant Space Handling is applied in the Insignificant "
  376. "Character Handling step.",
  377. DIRSTRING_SYNTAX_OID,
  378. 0,
  379. dirStringCompat_syntaxes
  380. }, /* matching rule desc */
  381. {
  382. "caseIgnoreOrderingMatch-mr",
  383. VENDOR,
  384. DS_PACKAGE_VERSION,
  385. "caseIgnoreOrderingMatch matching rule plugin"
  386. }, /* plugin desc */
  387. caseIgnoreOrderingMatch_names, /* matching rule name/oid/aliases */
  388. NULL,
  389. NULL,
  390. cis_filter_ava,
  391. NULL,
  392. cis_values2keys,
  393. cis_assertion2keys_ava,
  394. NULL,
  395. cis_compare,
  396. cis_normalize
  397. },
  398. {
  399. {
  400. "2.5.13.4",
  401. NULL,
  402. "caseIgnoreSubstringsMatch",
  403. "The caseIgnoreSubstringsMatch rule compares an assertion value of the "
  404. "Substring Assertion syntax to an attribute value of a syntax (e.g., "
  405. "the Directory String, Printable String, Country String, or Telephone "
  406. "Number syntax) whose corresponding ASN.1 type is DirectoryString or "
  407. "one of its alternative string types. "
  408. "The rule evaluates to TRUE if and only if (1) the prepared substrings "
  409. "of the assertion value match disjoint portions of the prepared "
  410. "attribute value character string in the order of the substrings in "
  411. "the assertion value, (2) an <initial> substring, if present, matches "
  412. "the beginning of the prepared attribute value character string, and "
  413. "(3) a <final> substring, if present, matches the end of the prepared "
  414. "attribute value character string. A prepared substring matches a "
  415. "portion of the prepared attribute value character string if "
  416. "corresponding characters have the same code point. "
  417. "In preparing the attribute value and assertion value substrings for "
  418. "comparison, characters are case folded in the Map preparation step, "
  419. "and only Insignificant Space Handling is applied in the Insignificant "
  420. "Character Handling step.",
  421. "1.3.6.1.4.1.1466.115.121.1.58",
  422. 0,
  423. dirString_syntaxes
  424. }, /* matching rule desc */
  425. {
  426. "caseIgnoreSubstringsMatch-mr",
  427. VENDOR,
  428. DS_PACKAGE_VERSION,
  429. "caseIgnoreSubstringsMatch matching rule plugin"
  430. }, /* plugin desc */
  431. caseIgnoreSubstringsMatch_names, /* matching rule name/oid/aliases */
  432. NULL,
  433. NULL,
  434. NULL,
  435. cis_filter_sub,
  436. cis_values2keys,
  437. NULL,
  438. cis_assertion2keys_sub,
  439. cis_compare,
  440. cis_normalize
  441. },
  442. {
  443. {
  444. "2.5.13.11",
  445. NULL,
  446. "caseIgnoreListMatch",
  447. "The caseIgnoreListMatch rule compares an assertion value that is a "
  448. "sequence of strings to an attribute value of a syntax (e.g., the "
  449. "Postal Address syntax) whose corresponding ASN.1 type is a SEQUENCE "
  450. "OF the DirectoryString ASN.1 type. "
  451. "The rule evaluates to TRUE if and only if the attribute value and the "
  452. "assertion value have the same number of strings and corresponding "
  453. "strings (by position) match according to the caseIgnoreMatch matching "
  454. "rule. "
  455. "In [X.520], the assertion syntax for this matching rule is defined to "
  456. "be: "
  457. " SEQUENCE OF DirectoryString {ub-match} "
  458. "That is, it is different from the corresponding type for the Postal "
  459. "Address syntax. The choice of the Postal Address syntax for the "
  460. "assertion syntax of the caseIgnoreListMatch in LDAP should not be "
  461. "seen as limiting the matching rule to apply only to attributes with "
  462. "the Postal Address syntax.",
  463. POSTALADDRESS_SYNTAX_OID,
  464. 0,
  465. NULL /* postal syntax only */
  466. }, /* matching rule desc */
  467. {
  468. "caseIgnoreListMatch-mr",
  469. VENDOR,
  470. DS_PACKAGE_VERSION,
  471. "caseIgnoreListMatch matching rule plugin"
  472. }, /* plugin desc */
  473. caseIgnoreListMatch_names, /* matching rule name/oid/aliases */
  474. NULL,
  475. NULL,
  476. cis_filter_ava,
  477. NULL,
  478. cis_values2keys,
  479. cis_assertion2keys_ava,
  480. NULL,
  481. cis_compare,
  482. cis_normalize
  483. },
  484. {
  485. {
  486. "2.5.13.12",
  487. NULL,
  488. "caseIgnoreListSubstringsMatch",
  489. "The caseIgnoreListSubstringsMatch rule compares an assertion value of "
  490. "the Substring Assertion syntax to an attribute value of a syntax "
  491. "(e.g., the Postal Address syntax) whose corresponding ASN.1 type is a "
  492. "SEQUENCE OF the DirectoryString ASN.1 type. "
  493. "The rule evaluates to TRUE if and only if the assertion value "
  494. "matches, per the caseIgnoreSubstringsMatch rule, the character string "
  495. "formed by concatenating the strings of the attribute value, except "
  496. "that none of the <initial>, <any>, or <final> substrings of the "
  497. "assertion value are considered to match a substring of the "
  498. "concatenated string which spans more than one of the original strings "
  499. "of the attribute value. "
  500. "Note that, in terms of the LDAP-specific encoding of the Postal "
  501. "Address syntax, the concatenated string omits the <DOLLAR> line "
  502. "separator and the escaping of \"\\\" and \"$\" characters.",
  503. "1.3.6.1.4.1.1466.115.121.1.58",
  504. 0,
  505. caseIgnoreListSubstringsMatch_syntaxes
  506. }, /* matching rule desc */
  507. {
  508. "caseIgnoreListSubstringsMatch-mr",
  509. VENDOR,
  510. DS_PACKAGE_VERSION,
  511. "caseIgnoreListSubstringsMatch matching rule plugin"
  512. }, /* plugin desc */
  513. caseIgnoreListSubstringsMatch_names, /* matching rule name/oid/aliases */
  514. NULL,
  515. NULL,
  516. NULL,
  517. cis_filter_sub,
  518. cis_values2keys,
  519. NULL,
  520. cis_assertion2keys_sub,
  521. cis_compare,
  522. cis_normalize
  523. },
  524. {
  525. {
  526. "2.5.13.0",
  527. NULL,
  528. "objectIdentifierMatch",
  529. "The objectIdentifierMatch rule compares an assertion value of the OID "
  530. "syntax to an attribute value of a syntax (e.g., the OID syntax) whose "
  531. "corresponding ASN.1 type is OBJECT IDENTIFIER. "
  532. "The rule evaluates to TRUE if and only if the assertion value and the "
  533. "attribute value represent the same object identifier; that is, the "
  534. "same sequence of integers, whether represented explicitly in the "
  535. "<numericoid> form of <oid> or implicitly in the <descr> form (see "
  536. "[RFC4512]). "
  537. "If an LDAP client supplies an assertion value in the <descr> form and "
  538. "the chosen descriptor is not recognized by the server, then the "
  539. "objectIdentifierMatch rule evaluates to Undefined.",
  540. OID_SYNTAX_OID,
  541. 0,
  542. NULL /* OID syntax only for now */
  543. }, /* matching rule desc */
  544. {
  545. "objectIdentifierMatch-mr",
  546. VENDOR,
  547. DS_PACKAGE_VERSION,
  548. "objectIdentifierMatch matching rule plugin"
  549. }, /* plugin desc */
  550. objectIdentifierMatch_names, /* matching rule name/oid/aliases */
  551. NULL,
  552. NULL,
  553. cis_filter_ava,
  554. NULL,
  555. cis_values2keys,
  556. cis_assertion2keys_ava,
  557. NULL,
  558. cis_compare,
  559. cis_normalize
  560. },
  561. {
  562. {
  563. "2.5.13.31",
  564. NULL,
  565. "directoryStringFirstComponentMatch",
  566. "The directoryStringFirstComponentMatch rule compares an assertion "
  567. "value of the Directory String syntax to an attribute value of a "
  568. "syntax whose corresponding ASN.1 type is a SEQUENCE with a mandatory "
  569. "first component of the DirectoryString ASN.1 type. "
  570. "Note that the assertion syntax of this matching rule differs from the "
  571. "attribute syntax of attributes for which this is the equality "
  572. "matching rule. "
  573. "The rule evaluates to TRUE if and only if the assertion value matches "
  574. "the first component of the attribute value using the rules of "
  575. "caseIgnoreMatch.",
  576. DIRSTRING_SYNTAX_OID,
  577. 0,
  578. dirStringCompat_syntaxes
  579. }, /* matching rule desc */
  580. {
  581. "directoryStringFirstComponentMatch-mr",
  582. VENDOR,
  583. DS_PACKAGE_VERSION,
  584. "directoryStringFirstComponentMatch matching rule plugin"
  585. }, /* plugin desc */
  586. directoryStringFirstComponentMatch_names, /* matching rule name/oid/aliases */
  587. NULL,
  588. NULL,
  589. cis_filter_ava,
  590. NULL,
  591. cis_values2keys,
  592. cis_assertion2keys_ava,
  593. NULL,
  594. NULL,
  595. cis_normalize
  596. },
  597. {
  598. {
  599. "2.5.13.30",
  600. NULL,
  601. "objectIdentifierFirstComponentMatch",
  602. "The objectIdentifierFirstComponentMatch rule compares an assertion "
  603. "value of the OID syntax to an attribute value of a syntax (e.g., the "
  604. "Attribute Type Description, DIT Content Rule Description, LDAP Syntax "
  605. "Description, Matching Rule Description, Matching Rule Use "
  606. "Description, Name Form Description, or Object Class Description "
  607. "syntax) whose corresponding ASN.1 type is a SEQUENCE with a mandatory "
  608. "first component of the OBJECT IDENTIFIER ASN.1 type. "
  609. "Note that the assertion syntax of this matching rule differs from the "
  610. "attribute syntax of attributes for which this is the equality "
  611. "matching rule. "
  612. "The rule evaluates to TRUE if and only if the assertion value matches "
  613. "the first component of the attribute value using the rules of "
  614. "objectIdentifierMatch.",
  615. OID_SYNTAX_OID,
  616. 0,
  617. objectIdentifierFirstComponentMatch_syntaxes
  618. }, /* matching rule desc */
  619. {
  620. "objectIdentifierFirstComponentMatch-mr",
  621. VENDOR,
  622. DS_PACKAGE_VERSION,
  623. "objectIdentifierFirstComponentMatch matching rule plugin"
  624. }, /* plugin desc */
  625. objectIdentifierFirstComponentMatch_names, /* matching rule name/oid/aliases */
  626. NULL,
  627. NULL,
  628. cis_filter_ava,
  629. NULL,
  630. cis_values2keys,
  631. cis_assertion2keys_ava,
  632. NULL,
  633. NULL,
  634. cis_normalize
  635. }
  636. };
  637. static size_t mr_plugin_table_size = sizeof(mr_plugin_table)/sizeof(mr_plugin_table[0]);
  638. static int
  639. matching_rule_plugin_init(Slapi_PBlock *pb)
  640. {
  641. return syntax_matching_rule_plugin_init(pb, mr_plugin_table, mr_plugin_table_size);
  642. }
  643. static int
  644. register_matching_rule_plugins()
  645. {
  646. return syntax_register_matching_rule_plugins(mr_plugin_table, mr_plugin_table_size, matching_rule_plugin_init);
  647. }
  648. /*
  649. * register_cis_like_plugin(): register all items for a cis-like plugin.
  650. */
  651. static int
  652. register_cis_like_plugin( Slapi_PBlock *pb, Slapi_PluginDesc *pdescp,
  653. char **names, char *oid, void *validate_fn )
  654. {
  655. int rc, flags;
  656. rc = slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
  657. (void *) SLAPI_PLUGIN_VERSION_01 );
  658. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
  659. (void *) pdescp );
  660. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_AVA,
  661. (void *) cis_filter_ava );
  662. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FILTER_SUB,
  663. (void *) cis_filter_sub );
  664. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALUES2KEYS,
  665. (void *) cis_values2keys );
  666. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_AVA,
  667. (void *) cis_assertion2keys_ava );
  668. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_ASSERTION2KEYS_SUB,
  669. (void *) cis_assertion2keys_sub );
  670. flags = SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING;
  671. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_FLAGS,
  672. (void *) &flags );
  673. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NAMES,
  674. (void *) names );
  675. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_OID,
  676. (void *) oid );
  677. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_COMPARE,
  678. (void *) cis_compare );
  679. if (validate_fn != NULL) {
  680. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_VALIDATE,
  681. (void *)validate_fn );
  682. }
  683. rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_SYNTAX_NORMALIZE,
  684. (void *) cis_normalize );
  685. return( rc );
  686. }
  687. int
  688. cis_init( Slapi_PBlock *pb )
  689. {
  690. int rc;
  691. LDAPDebug( LDAP_DEBUG_PLUGIN, "=> cis_init\n", 0, 0, 0 );
  692. rc = register_cis_like_plugin( pb, &dirstring_pdesc, dirstring_names,
  693. DIRSTRING_SYNTAX_OID, dirstring_validate );
  694. rc |= register_matching_rule_plugins();
  695. LDAPDebug( LDAP_DEBUG_PLUGIN, "<= cis_init %d\n", rc, 0, 0 );
  696. return( rc );
  697. }
  698. int
  699. boolean_init( Slapi_PBlock *pb )
  700. {
  701. int rc;
  702. LDAPDebug( LDAP_DEBUG_PLUGIN, "=> boolean_init\n", 0, 0, 0 );
  703. rc = register_cis_like_plugin( pb, &boolean_pdesc, boolean_names,
  704. BOOLEAN_SYNTAX_OID, boolean_validate );
  705. LDAPDebug( LDAP_DEBUG_PLUGIN, "<= boolean_init %d\n", rc, 0, 0 );
  706. return( rc );
  707. }
  708. int
  709. time_init( Slapi_PBlock *pb )
  710. {
  711. int rc;
  712. LDAPDebug( LDAP_DEBUG_PLUGIN, "=> time_init\n", 0, 0, 0 );
  713. rc = register_cis_like_plugin( pb, &time_pdesc, time_names,
  714. GENERALIZEDTIME_SYNTAX_OID, time_validate );
  715. LDAPDebug( LDAP_DEBUG_PLUGIN, "<= time_init %d\n", rc, 0, 0 );
  716. return( rc );
  717. }
  718. int
  719. country_init( Slapi_PBlock *pb )
  720. {
  721. int rc;
  722. LDAPDebug( LDAP_DEBUG_PLUGIN, "=> country_init\n", 0, 0, 0 );
  723. rc = register_cis_like_plugin( pb, &country_pdesc, country_names,
  724. COUNTRYSTRING_SYNTAX_OID, country_validate );
  725. LDAPDebug( LDAP_DEBUG_PLUGIN, "<= country_init %d\n", rc, 0, 0 );
  726. return( rc );
  727. }
  728. int
  729. postal_init( Slapi_PBlock *pb )
  730. {
  731. int rc;
  732. LDAPDebug( LDAP_DEBUG_PLUGIN, "=> postal_init\n", 0, 0, 0 );
  733. rc = register_cis_like_plugin( pb, &postal_pdesc, postal_names,
  734. POSTALADDRESS_SYNTAX_OID, postal_validate );
  735. LDAPDebug( LDAP_DEBUG_PLUGIN, "<= postal_init %d\n", rc, 0, 0 );
  736. return( rc );
  737. }
  738. int
  739. oid_init( Slapi_PBlock *pb )
  740. {
  741. int rc;
  742. LDAPDebug( LDAP_DEBUG_PLUGIN, "=> oid_init\n", 0, 0, 0 );
  743. rc = register_cis_like_plugin( pb, &oid_pdesc, oid_names, OID_SYNTAX_OID, oid_validate );
  744. LDAPDebug( LDAP_DEBUG_PLUGIN, "<= oid_init %d\n", rc, 0, 0 );
  745. return( rc );
  746. }
  747. int
  748. printable_init( Slapi_PBlock *pb )
  749. {
  750. int rc;
  751. LDAPDebug( LDAP_DEBUG_PLUGIN, "=> printable_init\n", 0, 0, 0 );
  752. rc = register_cis_like_plugin( pb, &printable_pdesc, printable_names,
  753. PRINTABLESTRING_SYNTAX_OID, printable_validate );
  754. LDAPDebug( LDAP_DEBUG_PLUGIN, "<= printable_init %d\n", rc, 0, 0 );
  755. return( rc );
  756. }
  757. static int
  758. cis_filter_ava(
  759. Slapi_PBlock *pb,
  760. struct berval *bvfilter,
  761. Slapi_Value **bvals,
  762. int ftype,
  763. Slapi_Value **retVal
  764. )
  765. {
  766. int filter_normalized = 0;
  767. int syntax = SYNTAX_CIS;
  768. if (pb) {
  769. slapi_pblock_get( pb, SLAPI_PLUGIN_SYNTAX_FILTER_NORMALIZED,
  770. &filter_normalized );
  771. if (filter_normalized) {
  772. syntax |= SYNTAX_NORM_FILT;
  773. }
  774. }
  775. return( string_filter_ava( bvfilter, bvals, syntax, ftype,
  776. retVal ) );
  777. }
  778. static int
  779. cis_filter_sub(
  780. Slapi_PBlock *pb,
  781. char *initial,
  782. char **any,
  783. char *final,
  784. Slapi_Value **bvals
  785. )
  786. {
  787. return( string_filter_sub( pb, initial, any, final, bvals, SYNTAX_CIS ) );
  788. }
  789. static int
  790. cis_values2keys(
  791. Slapi_PBlock *pb,
  792. Slapi_Value **vals,
  793. Slapi_Value ***ivals,
  794. int ftype
  795. )
  796. {
  797. return( string_values2keys( pb, vals, ivals, SYNTAX_CIS, ftype ) );
  798. }
  799. static int
  800. cis_assertion2keys_ava(
  801. Slapi_PBlock *pb,
  802. Slapi_Value *val,
  803. Slapi_Value ***ivals,
  804. int ftype
  805. )
  806. {
  807. return(string_assertion2keys_ava( pb, val, ivals, SYNTAX_CIS, ftype ));
  808. }
  809. static int
  810. cis_assertion2keys_sub(
  811. Slapi_PBlock *pb,
  812. char *initial,
  813. char **any,
  814. char *final,
  815. Slapi_Value ***ivals
  816. )
  817. {
  818. return( string_assertion2keys_sub( pb, initial, any, final, ivals,
  819. SYNTAX_CIS ) );
  820. }
  821. static int cis_compare(
  822. struct berval *v1,
  823. struct berval *v2
  824. )
  825. {
  826. return value_cmp(v1,v2,SYNTAX_CIS,3 /* Normalise both values */);
  827. }
  828. static int dirstring_validate(
  829. struct berval *val
  830. )
  831. {
  832. int rc = 0; /* assume the value is valid */
  833. char *p = NULL;
  834. char *end = NULL;
  835. /* Per RFC4517:
  836. *
  837. * DirectoryString = 1*UTF8
  838. */
  839. if ((val != NULL) && (val->bv_len > 0)) {
  840. p = val->bv_val;
  841. end = &(val->bv_val[val->bv_len - 1]);
  842. rc = utf8string_validate(p, end, NULL);
  843. } else {
  844. rc = 1;
  845. goto exit;
  846. }
  847. exit:
  848. return( rc );
  849. }
  850. static int boolean_validate(
  851. struct berval *val
  852. )
  853. {
  854. int rc = 0; /* assume the value is valid */
  855. /* Per RFC4517:
  856. *
  857. * Boolean = "TRUE" / "FALSE"
  858. */
  859. if (val != NULL) {
  860. if (val->bv_len == 4) {
  861. if (strncmp(val->bv_val, "TRUE", 4) != 0) {
  862. rc = 1;
  863. goto exit;
  864. }
  865. } else if (val->bv_len == 5) {
  866. if (strncmp(val->bv_val, "FALSE", 5) != 0) {
  867. rc = 1;
  868. goto exit;
  869. }
  870. } else {
  871. rc = 1;
  872. goto exit;
  873. }
  874. } else {
  875. rc = 1;
  876. }
  877. exit:
  878. return(rc);
  879. }
  880. static int time_validate(
  881. struct berval *val
  882. )
  883. {
  884. int rc = 0; /* assume the value is valid */
  885. int i = 0;
  886. const char *p = NULL;
  887. char *end = NULL;
  888. /* Per RFC4517:
  889. *
  890. * GeneralizedTime = century year month day hour
  891. * [ minute [ second / leap-second ] ]
  892. * [ fraction ]
  893. * g-time-zone
  894. *
  895. * century = 2(%x30-39) ; "00" to "99"
  896. * year = 2(%x30-39) ; "00" to "99"
  897. * month = ( %x30 %x31-39 ) ; "01" (January) to "09"
  898. * / ( %x31 %x30-32 ) ; "10 to "12"
  899. * day = ( %x30 %x31-39 ) ; "01" to "09"
  900. * / ( %x31-x32 %x30-39 ) ; "10" to "29"
  901. * / ( %x33 %x30-31 ) ; "30" to "31"
  902. * hour = ( %x30-31 %x30-39 ) / ( %x32 %x30-33 ) ; "00" to "23"
  903. * minute = %x30-35 %x30-39 ; "00" to "59"
  904. *
  905. * second = ( %x30-35 - %x30-39 ) ; "00" to "59"
  906. * leap-second = ( %x36 %x30 ) ; "60"
  907. *
  908. * fraction = ( DOT / COMMA ) 1*(%x30-39)
  909. * g-time-zone = %x5A ; "Z"
  910. * / g-differential
  911. * g-differential = ( MINUS / PLUS ) hour [ minute ]
  912. */
  913. if (val != NULL) {
  914. /* A valid GeneralizedTime should be at least 11 characters. There
  915. * is no upper bound due to the variable length of "fraction". */
  916. if (val->bv_len < 11) {
  917. rc = 1;
  918. goto exit;
  919. }
  920. /* We're guaranteed that the value is at least 11 characters, so we
  921. * don't need to bother checking if we're at the end of the value
  922. * until we start processing the "minute" part of the value. */
  923. p = val->bv_val;
  924. end = &(val->bv_val[val->bv_len - 1]);
  925. /* Process "century year". First 4 characters can be any valid digit. */
  926. for (i=0; i<4; i++) {
  927. if (!isdigit(*p)) {
  928. rc = 1;
  929. goto exit;
  930. }
  931. p++;
  932. }
  933. /* Process "month". Next character can be "0" or "1". */
  934. if (*p == '0') {
  935. p++;
  936. /* any LDIGIT is valid now */
  937. if (!IS_LDIGIT(*p)) {
  938. rc = 1;
  939. goto exit;
  940. }
  941. p++;
  942. } else if (*p == '1') {
  943. p++;
  944. /* only "0"-"2" are valid now */
  945. if ((*p < '0') || (*p > '2')) {
  946. rc = 1;
  947. goto exit;
  948. }
  949. p++;
  950. } else {
  951. rc = 1;
  952. goto exit;
  953. }
  954. /* Process "day". Next character can be "0"-"3". */
  955. if (*p == '0') {
  956. p++;
  957. /* any LDIGIT is valid now */
  958. if (!IS_LDIGIT(*p)) {
  959. rc = 1;
  960. goto exit;
  961. }
  962. p++;
  963. } else if ((*p == '1') || (*p == '2')) {
  964. p++;
  965. /* any digit is valid now */
  966. if (!isdigit(*p)) {
  967. rc = 1;
  968. goto exit;
  969. }
  970. p++;
  971. } else if (*p == '3') {
  972. p++;
  973. /* only "0"-"1" are valid now */
  974. if ((*p != '0') && (*p != '1')) {
  975. rc = 1;
  976. goto exit;
  977. }
  978. p++;
  979. } else {
  980. rc = 1;
  981. goto exit;
  982. }
  983. /* Process "hour". Next character can be "0"-"2". */
  984. if ((*p == '0') || (*p == '1')) {
  985. p++;
  986. /* any digit is valid now */
  987. if (!isdigit(*p)) {
  988. rc = 1;
  989. goto exit;
  990. }
  991. p++;
  992. } else if (*p == '2') {
  993. p++;
  994. /* only "0"-"3" are valid now */
  995. if ((*p < '0') || (*p > '3')) {
  996. rc = 1;
  997. goto exit;
  998. }
  999. p++;
  1000. } else {
  1001. rc = 1;
  1002. goto exit;
  1003. }
  1004. /* Time for the optional stuff. We know we have at least one character here, but
  1005. * we need to start checking for the end of the string afterwards.
  1006. *
  1007. * See if a "minute" was specified. */
  1008. if ((*p >= '0') && (*p <= '5')) {
  1009. p++;
  1010. /* any digit is valid for the second char of a minute */
  1011. if ((p > end) || (!isdigit(*p))) {
  1012. rc = 1;
  1013. goto exit;
  1014. }
  1015. p++;
  1016. /* At this point, there has to at least be a "g-time-zone" left.
  1017. * Make sure we're not at the end of the string. */
  1018. if (p > end) {
  1019. rc = 1;
  1020. goto exit;
  1021. }
  1022. /* See if a "second" or "leap-second" was specified. */
  1023. if ((*p >= '0') && (*p <= '5')) {
  1024. p++;
  1025. /* any digit is valid now */
  1026. if ((p > end) || (!isdigit(*p))) {
  1027. rc = 1;
  1028. goto exit;
  1029. }
  1030. p++;
  1031. } else if (*p == '6') {
  1032. p++;
  1033. /* only a '0' is valid now */
  1034. if ((p > end) || (*p != '0')) {
  1035. rc = 1;
  1036. goto exit;
  1037. }
  1038. p++;
  1039. }
  1040. /* At this point, there has to at least be a "g-time-zone" left.
  1041. * Make sure we're not at the end of the string. */
  1042. if (p > end) {
  1043. rc = 1;
  1044. goto exit;
  1045. }
  1046. }
  1047. /* See if a fraction was specified. */
  1048. if ((*p == '.') || (*p == ',')) {
  1049. p++;
  1050. /* An arbitrary length string of digit chars is allowed here.
  1051. * Ensure we have at least one digit character. */
  1052. if ((p >= end) || (!isdigit(*p))) {
  1053. rc = 1;
  1054. goto exit;
  1055. }
  1056. /* Just loop through the rest of the fraction until we encounter a non-digit */
  1057. p++;
  1058. while ((p < end) && (isdigit(*p))) {
  1059. p++;
  1060. }
  1061. }
  1062. /* Process "g-time-zone". We either end with 'Z', or have a differential. */
  1063. if (p == end) {
  1064. if (*p != 'Z') {
  1065. rc = 1;
  1066. goto exit;
  1067. }
  1068. } else if (p < end) {
  1069. if ((*p != '-') && (*p != '+')) {
  1070. rc = 1;
  1071. goto exit;
  1072. } else {
  1073. /* A "g-differential" was specified. An "hour" must be present now. */
  1074. p++;
  1075. if ((*p == '0') || (*p == '1')) {
  1076. p++;
  1077. /* any digit is valid now */
  1078. if ((p > end) || !isdigit(*p)) {
  1079. rc = 1;
  1080. goto exit;
  1081. }
  1082. p++;
  1083. } else if (*p == '2') {
  1084. p++;
  1085. /* only "0"-"3" are valid now */
  1086. if ((p > end) || (*p < '0') || (*p > '3')) {
  1087. rc = 1;
  1088. goto exit;
  1089. }
  1090. p++;
  1091. } else {
  1092. rc = 1;
  1093. goto exit;
  1094. }
  1095. /* See if an optional minute is present ("00"-"59"). */
  1096. if (p <= end) {
  1097. /* "0"-"5" are valid now */
  1098. if ((*p < '0') || (*p > '5')) {
  1099. rc = 1;
  1100. goto exit;
  1101. }
  1102. p++;
  1103. /* We should be at the last character of the string
  1104. * now, which must be a valid digit. */
  1105. if ((p != end) || !isdigit(*p)) {
  1106. rc = 1;
  1107. goto exit;
  1108. }
  1109. }
  1110. }
  1111. } else {
  1112. /* Premature end of string */
  1113. rc = 1;
  1114. goto exit;
  1115. }
  1116. } else {
  1117. rc = 1;
  1118. goto exit;
  1119. }
  1120. exit:
  1121. return( rc );
  1122. }
  1123. static int country_validate(
  1124. struct berval *val
  1125. )
  1126. {
  1127. int rc = 0; /* assume the value is valid */
  1128. /* Per RFC4517:
  1129. *
  1130. * CountryString = 2(PrintableCharacter)
  1131. */
  1132. if (val != NULL) {
  1133. if ((val->bv_len != 2) || !IS_PRINTABLE(val->bv_val[0]) || !IS_PRINTABLE(val->bv_val[1])) {
  1134. rc = 1;
  1135. goto exit;
  1136. }
  1137. } else {
  1138. rc = 1;
  1139. }
  1140. exit:
  1141. return(rc);
  1142. }
  1143. static int postal_validate(
  1144. struct berval *val
  1145. )
  1146. {
  1147. int rc = 0; /* assume the value is valid */
  1148. const char *p = NULL;
  1149. const char *start = NULL;
  1150. char *end = NULL;
  1151. /* Per RFC4517:
  1152. * PostalAddress = line *( DOLLAR line )
  1153. * line = 1*line-char
  1154. * line-char = %x00-23
  1155. * / (%x5C "24") ; escaped "$"
  1156. * / %x25-5B
  1157. * / (%x5C "5C") ; escaped "\"
  1158. * / %x5D-7F
  1159. * / UTFMB
  1160. */
  1161. if ((val != NULL) && (val->bv_val != NULL) && (val->bv_len > 0)) {
  1162. start = val->bv_val;
  1163. end = &(val->bv_val[val->bv_len - 1]);
  1164. for (p = start; p <= end; p++) {
  1165. /* look for a '\' and make sure it's only used to escape a '$' or a '\' */
  1166. if (*p == '\\') {
  1167. p++;
  1168. /* ensure that we're not at the end of the value */
  1169. if ((p > end) || ((strncmp(p, "24", 2) != 0) && (strncasecmp(p, "5C", 2) != 0))) {
  1170. rc = 1;
  1171. goto exit;
  1172. } else {
  1173. /* advance the pointer to point to the end
  1174. * of the hex code for the escaped character */
  1175. p++;
  1176. }
  1177. } else if ((*p == '$') || (p == end)) {
  1178. /* This signifies the end of a line. We need
  1179. * to ensure that the line is not empty. */
  1180. /* make sure the value doesn't end with a '$' */
  1181. if ((p == start) || ((*p == '$') && (p == end))) {
  1182. if (!postal_allow_empty_lines) {
  1183. rc = 1;
  1184. goto exit;
  1185. } /* else allow it */
  1186. } else if ((rc = utf8string_validate(start, p, NULL)) != 0) {
  1187. /* Make sure the line (start to p) is valid UTF-8. */
  1188. goto exit;
  1189. }
  1190. /* make the start pointer point to the
  1191. * beginning of the next line */
  1192. start = p + 1;
  1193. }
  1194. }
  1195. } else {
  1196. rc = 1;
  1197. }
  1198. exit:
  1199. return(rc);
  1200. }
  1201. static int oid_validate(
  1202. struct berval *val
  1203. )
  1204. {
  1205. int rc = 0; /* assume the value is valid */
  1206. const char *p = NULL;
  1207. const char *end = NULL;
  1208. /* Per RFC4512:
  1209. *
  1210. * oid = descr / numericoid
  1211. * descr = keystring
  1212. */
  1213. if ((val != NULL) && (val->bv_len > 0)) {
  1214. p = val->bv_val;
  1215. end = &(val->bv_val[val->bv_len - 1]);
  1216. /* check if the value matches the descr form */
  1217. if (IS_LEADKEYCHAR(*p)) {
  1218. rc = keystring_validate(p, end);
  1219. /* check if the value matches the numericoid form */
  1220. } else if (isdigit(*p)) {
  1221. rc = numericoid_validate(p, end);
  1222. } else {
  1223. rc = 1;
  1224. goto exit;
  1225. }
  1226. } else {
  1227. rc = 1;
  1228. }
  1229. exit:
  1230. return( rc );
  1231. }
  1232. static int printable_validate(
  1233. struct berval *val
  1234. )
  1235. {
  1236. int rc = 0; /* assume the value is valid */
  1237. uint i = 0;
  1238. /* Per RFC4517:
  1239. *
  1240. * PrintableString = 1*PrintableCharacter
  1241. */
  1242. if ((val != NULL) && (val->bv_len > 0)) {
  1243. /* Make sure all chars are a PrintableCharacter */
  1244. for (i=0; i < val->bv_len; i++) {
  1245. if (!IS_PRINTABLE(val->bv_val[i])) {
  1246. rc = 1;
  1247. goto exit;
  1248. }
  1249. }
  1250. } else {
  1251. rc = 1;
  1252. }
  1253. exit:
  1254. return( rc );
  1255. }
  1256. static void cis_normalize(
  1257. Slapi_PBlock *pb,
  1258. char *s,
  1259. int trim_spaces,
  1260. char **alt
  1261. )
  1262. {
  1263. value_normalize_ext(s, SYNTAX_CIS, trim_spaces, alt);
  1264. return;
  1265. }