cis.c 45 KB

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