PkixNameConstraintValidator.cs 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Text;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X500;
  8. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X500.Style;
  9. using BestHTTP.SecureProtocol.Org.BouncyCastle.Asn1.X509;
  10. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  11. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Encoders;
  12. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Pkix
  13. {
  14. public class PkixNameConstraintValidator
  15. {
  16. private static readonly DerObjectIdentifier SerialNumberOid = X509Name.SerialNumber;
  17. private ISet<Asn1Sequence> excludedSubtreesDN = new HashSet<Asn1Sequence>();
  18. private ISet<string> excludedSubtreesDns = new HashSet<string>();
  19. private ISet<string> excludedSubtreesEmail = new HashSet<string>();
  20. private ISet<string> excludedSubtreesUri = new HashSet<string>();
  21. private ISet<byte[]> excludedSubtreesIP = new HashSet<byte[]>();
  22. private ISet<OtherName> excludedSubtreesOtherName = new HashSet<OtherName>();
  23. private ISet<Asn1Sequence> permittedSubtreesDN;
  24. private ISet<string> permittedSubtreesDns;
  25. private ISet<string> permittedSubtreesEmail;
  26. private ISet<string> permittedSubtreesUri;
  27. private ISet<byte[]> permittedSubtreesIP;
  28. private ISet<OtherName> permittedSubtreesOtherName;
  29. public PkixNameConstraintValidator()
  30. {
  31. }
  32. private static bool WithinDNSubtree(
  33. Asn1Sequence dns,
  34. Asn1Sequence subtree)
  35. {
  36. if (subtree.Count < 1 || subtree.Count > dns.Count)
  37. return false;
  38. int start = 0;
  39. Rdn subtreeRdnStart = Rdn.GetInstance(subtree[0]);
  40. for (int j = 0; j < dns.Count; j++)
  41. {
  42. start = j;
  43. Rdn dnsRdn = Rdn.GetInstance(dns[j]);
  44. if (IetfUtilities.RdnAreEqual(subtreeRdnStart, dnsRdn))
  45. break;
  46. }
  47. if (subtree.Count > dns.Count - start)
  48. return false;
  49. for (int j = 0; j < subtree.Count; ++j)
  50. {
  51. // both subtree and dns are a ASN.1 Name and the elements are a RDN
  52. Rdn subtreeRdn = Rdn.GetInstance(subtree[j]);
  53. Rdn dnsRdn = Rdn.GetInstance(dns[start + j]);
  54. // check if types and values of all naming attributes are matching, other types which are not restricted are allowed, see https://tools.ietf.org/html/rfc5280#section-7.1
  55. // Two relative distinguished names
  56. // RDN1 and RDN2 match if they have the same number of naming attributes
  57. // and for each naming attribute in RDN1 there is a matching naming attribute in RDN2.
  58. // NOTE: this is checking the attributes in the same order, which might be not necessary, if this is a problem also IETFUtils.rDNAreEqual mus tbe changed.
  59. // use new RFC 5280 comparison, NOTE: this is now different from with RFC 3280, where only binary comparison is used
  60. // obey RFC 5280 7.1
  61. // special treatment of serialNumber for GSMA SGP.22 RSP specification
  62. if (subtreeRdn.Count == 1 && dnsRdn.Count == 1
  63. && subtreeRdn.GetFirst().GetType().Equals(SerialNumberOid)
  64. && dnsRdn.GetFirst().GetType().Equals(SerialNumberOid))
  65. {
  66. if (!Org.BouncyCastle.Utilities.Platform.StartsWith(dnsRdn.GetFirst().Value.ToString(), subtreeRdn.GetFirst().Value.ToString()))
  67. return false;
  68. }
  69. else if (!IetfUtilities.RdnAreEqual(subtreeRdn, dnsRdn))
  70. {
  71. return false;
  72. }
  73. }
  74. return true;
  75. }
  76. public void CheckPermittedDN(Asn1Sequence dn)
  77. {
  78. CheckPermittedDirectory(permittedSubtreesDN, dn);
  79. }
  80. public void CheckExcludedDN(Asn1Sequence dn)
  81. {
  82. CheckExcludedDirectory(excludedSubtreesDN, dn);
  83. }
  84. private ISet<Asn1Sequence> IntersectDN(ISet<Asn1Sequence> permitted, ISet<GeneralSubtree> dns)
  85. {
  86. var intersect = new HashSet<Asn1Sequence>();
  87. foreach (GeneralSubtree subtree1 in dns)
  88. {
  89. Asn1Sequence dn1 = Asn1Sequence.GetInstance(subtree1.Base.Name);
  90. if (permitted == null)
  91. {
  92. if (dn1 != null)
  93. {
  94. intersect.Add(dn1);
  95. }
  96. }
  97. else
  98. {
  99. foreach (var dn2 in permitted)
  100. {
  101. if (WithinDNSubtree(dn1, dn2))
  102. {
  103. intersect.Add(dn1);
  104. }
  105. else if (WithinDNSubtree(dn2, dn1))
  106. {
  107. intersect.Add(dn2);
  108. }
  109. }
  110. }
  111. }
  112. return intersect;
  113. }
  114. private ISet<Asn1Sequence> UnionDN(ISet<Asn1Sequence> excluded, Asn1Sequence dn)
  115. {
  116. if (excluded.Count < 1)
  117. {
  118. if (dn == null)
  119. return excluded;
  120. excluded.Add(dn);
  121. return excluded;
  122. }
  123. var union = new HashSet<Asn1Sequence>();
  124. foreach (var subtree in excluded)
  125. {
  126. if (WithinDNSubtree(dn, subtree))
  127. {
  128. union.Add(subtree);
  129. }
  130. else if (WithinDNSubtree(subtree, dn))
  131. {
  132. union.Add(dn);
  133. }
  134. else
  135. {
  136. union.Add(subtree);
  137. union.Add(dn);
  138. }
  139. }
  140. return union;
  141. }
  142. private ISet<OtherName> IntersectOtherName(ISet<OtherName> permitted, ISet<GeneralSubtree> otherNames)
  143. {
  144. var intersect = new HashSet<OtherName>();
  145. foreach (GeneralSubtree subtree1 in otherNames)
  146. {
  147. OtherName otherName1 = OtherName.GetInstance(subtree1.Base.Name);
  148. if (otherName1 == null)
  149. continue;
  150. if (permitted == null)
  151. {
  152. intersect.Add(otherName1);
  153. }
  154. else
  155. {
  156. foreach (OtherName otherName2 in permitted)
  157. {
  158. IntersectOtherName(otherName1, otherName2, intersect);
  159. }
  160. }
  161. }
  162. return intersect;
  163. }
  164. private void IntersectOtherName(OtherName otherName1, OtherName otherName2, ISet<OtherName> intersect)
  165. {
  166. if (otherName1.Equals(otherName2))
  167. {
  168. intersect.Add(otherName1);
  169. }
  170. }
  171. private ISet<OtherName> UnionOtherName(ISet<OtherName> permitted, OtherName otherName)
  172. {
  173. var union = permitted != null ? new HashSet<OtherName>(permitted) : new HashSet<OtherName>();
  174. union.Add(otherName);
  175. return union;
  176. }
  177. private ISet<string> IntersectEmail(ISet<string> permitted, ISet<GeneralSubtree> emails)
  178. {
  179. var intersect = new HashSet<string>();
  180. foreach (GeneralSubtree subtree1 in emails)
  181. {
  182. string email = ExtractNameAsString(subtree1.Base);
  183. if (permitted == null)
  184. {
  185. if (email != null)
  186. {
  187. intersect.Add(email);
  188. }
  189. }
  190. else
  191. {
  192. foreach (string _permitted in permitted)
  193. {
  194. IntersectEmail(email, _permitted, intersect);
  195. }
  196. }
  197. }
  198. return intersect;
  199. }
  200. private ISet<string> UnionEmail(ISet<string> excluded, string email)
  201. {
  202. if (excluded.Count < 1)
  203. {
  204. if (email == null)
  205. return excluded;
  206. excluded.Add(email);
  207. return excluded;
  208. }
  209. var union = new HashSet<string>();
  210. foreach (string _excluded in excluded)
  211. {
  212. UnionEmail(_excluded, email, union);
  213. }
  214. return union;
  215. }
  216. /**
  217. * Returns the intersection of the permitted IP ranges in
  218. * <code>permitted</code> with <code>ip</code>.
  219. *
  220. * @param permitted A <code>Set</code> of permitted IP addresses with
  221. * their subnet mask as byte arrays.
  222. * @param ips The IP address with its subnet mask.
  223. * @return The <code>Set</code> of permitted IP ranges intersected with
  224. * <code>ip</code>.
  225. */
  226. private ISet<byte[]> IntersectIP(ISet<byte[]> permitted, ISet<GeneralSubtree> ips)
  227. {
  228. var intersect = new HashSet<byte[]>();
  229. foreach (GeneralSubtree subtree in ips)
  230. {
  231. byte[] ip = Asn1OctetString.GetInstance(subtree.Base.Name).GetOctets();
  232. if (permitted == null)
  233. {
  234. if (ip != null)
  235. {
  236. intersect.Add(ip);
  237. }
  238. }
  239. else
  240. {
  241. foreach (byte[] _permitted in permitted)
  242. {
  243. intersect.UnionWith(IntersectIPRange(_permitted, ip));
  244. }
  245. }
  246. }
  247. return intersect;
  248. }
  249. /**
  250. * Returns the union of the excluded IP ranges in <code>excluded</code>
  251. * with <code>ip</code>.
  252. *
  253. * @param excluded A <code>Set</code> of excluded IP addresses with their
  254. * subnet mask as byte arrays.
  255. * @param ip The IP address with its subnet mask.
  256. * @return The <code>Set</code> of excluded IP ranges unified with
  257. * <code>ip</code> as byte arrays.
  258. */
  259. private ISet<byte[]> UnionIP(ISet<byte[]> excluded, byte[] ip)
  260. {
  261. if (excluded.Count < 1)
  262. {
  263. if (ip == null)
  264. return excluded;
  265. excluded.Add(ip);
  266. return excluded;
  267. }
  268. var union = new HashSet<byte[]>();
  269. foreach (byte[] _excluded in excluded)
  270. {
  271. union.UnionWith(UnionIPRange(_excluded, ip));
  272. }
  273. return union;
  274. }
  275. /**
  276. * Calculates the union if two IP ranges.
  277. *
  278. * @param ipWithSubmask1 The first IP address with its subnet mask.
  279. * @param ipWithSubmask2 The second IP address with its subnet mask.
  280. * @return A <code>Set</code> with the union of both addresses.
  281. */
  282. private ISet<byte[]> UnionIPRange(byte[] ipWithSubmask1, byte[] ipWithSubmask2)
  283. {
  284. var set = new HashSet<byte[]>();
  285. // difficult, adding always all IPs is not wrong
  286. if (Arrays.AreEqual(ipWithSubmask1, ipWithSubmask2))
  287. {
  288. set.Add(ipWithSubmask1);
  289. }
  290. else
  291. {
  292. set.Add(ipWithSubmask1);
  293. set.Add(ipWithSubmask2);
  294. }
  295. return set;
  296. }
  297. /**
  298. * Calculates the interesction if two IP ranges.
  299. *
  300. * @param ipWithSubmask1 The first IP address with its subnet mask.
  301. * @param ipWithSubmask2 The second IP address with its subnet mask.
  302. * @return A <code>Set</code> with the single IP address with its subnet
  303. * mask as a byte array or an empty <code>Set</code>.
  304. */
  305. private ISet<byte[]> IntersectIPRange(byte[] ipWithSubmask1, byte[] ipWithSubmask2)
  306. {
  307. if (ipWithSubmask1.Length != ipWithSubmask2.Length)
  308. {
  309. //Collections.EMPTY_SET;
  310. return new HashSet<byte[]>();
  311. }
  312. byte[][] temp = ExtractIPsAndSubnetMasks(ipWithSubmask1, ipWithSubmask2);
  313. byte[] ip1 = temp[0];
  314. byte[] subnetmask1 = temp[1];
  315. byte[] ip2 = temp[2];
  316. byte[] subnetmask2 = temp[3];
  317. byte[][] minMax = MinMaxIPs(ip1, subnetmask1, ip2, subnetmask2);
  318. byte[] min;
  319. byte[] max;
  320. max = Min(minMax[1], minMax[3]);
  321. min = Max(minMax[0], minMax[2]);
  322. // minimum IP address must be bigger than max
  323. if (CompareTo(min, max) == 1)
  324. {
  325. //return Collections.EMPTY_SET;
  326. return new HashSet<byte[]>();
  327. }
  328. // OR keeps all significant bits
  329. byte[] ip = Or(minMax[0], minMax[2]);
  330. byte[] subnetmask = Or(subnetmask1, subnetmask2);
  331. //return new HashSet( ICollectionsingleton(IpWithSubnetMask(ip, subnetmask));
  332. var hs = new HashSet<byte[]>();
  333. hs.Add(IpWithSubnetMask(ip, subnetmask));
  334. return hs;
  335. }
  336. /**
  337. * Concatenates the IP address with its subnet mask.
  338. *
  339. * @param ip The IP address.
  340. * @param subnetMask Its subnet mask.
  341. * @return The concatenated IP address with its subnet mask.
  342. */
  343. private byte[] IpWithSubnetMask(byte[] ip, byte[] subnetMask)
  344. {
  345. int ipLength = ip.Length;
  346. byte[] temp = new byte[ipLength * 2];
  347. Array.Copy(ip, 0, temp, 0, ipLength);
  348. Array.Copy(subnetMask, 0, temp, ipLength, ipLength);
  349. return temp;
  350. }
  351. /**
  352. * Splits the IP addresses and their subnet mask.
  353. *
  354. * @param ipWithSubmask1 The first IP address with the subnet mask.
  355. * @param ipWithSubmask2 The second IP address with the subnet mask.
  356. * @return An array with two elements. Each element contains the IP address
  357. * and the subnet mask in this order.
  358. */
  359. private byte[][] ExtractIPsAndSubnetMasks(
  360. byte[] ipWithSubmask1,
  361. byte[] ipWithSubmask2)
  362. {
  363. int ipLength = ipWithSubmask1.Length / 2;
  364. byte[] ip1 = new byte[ipLength];
  365. byte[] subnetmask1 = new byte[ipLength];
  366. Array.Copy(ipWithSubmask1, 0, ip1, 0, ipLength);
  367. Array.Copy(ipWithSubmask1, ipLength, subnetmask1, 0, ipLength);
  368. byte[] ip2 = new byte[ipLength];
  369. byte[] subnetmask2 = new byte[ipLength];
  370. Array.Copy(ipWithSubmask2, 0, ip2, 0, ipLength);
  371. Array.Copy(ipWithSubmask2, ipLength, subnetmask2, 0, ipLength);
  372. return new byte[][]{ ip1, subnetmask1, ip2, subnetmask2 };
  373. }
  374. /**
  375. * Based on the two IP addresses and their subnet masks the IP range is
  376. * computed for each IP address - subnet mask pair and returned as the
  377. * minimum IP address and the maximum address of the range.
  378. *
  379. * @param ip1 The first IP address.
  380. * @param subnetmask1 The subnet mask of the first IP address.
  381. * @param ip2 The second IP address.
  382. * @param subnetmask2 The subnet mask of the second IP address.
  383. * @return A array with two elements. The first/second element contains the
  384. * min and max IP address of the first/second IP address and its
  385. * subnet mask.
  386. */
  387. private byte[][] MinMaxIPs(
  388. byte[] ip1,
  389. byte[] subnetmask1,
  390. byte[] ip2,
  391. byte[] subnetmask2)
  392. {
  393. int ipLength = ip1.Length;
  394. byte[] min1 = new byte[ipLength];
  395. byte[] max1 = new byte[ipLength];
  396. byte[] min2 = new byte[ipLength];
  397. byte[] max2 = new byte[ipLength];
  398. for (int i = 0; i < ipLength; i++)
  399. {
  400. min1[i] = (byte)(ip1[i] & subnetmask1[i]);
  401. max1[i] = (byte)(ip1[i] & subnetmask1[i] | ~subnetmask1[i]);
  402. min2[i] = (byte)(ip2[i] & subnetmask2[i]);
  403. max2[i] = (byte)(ip2[i] & subnetmask2[i] | ~subnetmask2[i]);
  404. }
  405. return new byte[][]{ min1, max1, min2, max2 };
  406. }
  407. private bool IsOtherNameConstrained(OtherName constraint, OtherName otherName)
  408. {
  409. return constraint.Equals(otherName);
  410. }
  411. private bool IsOtherNameConstrained(ISet<OtherName> constraints, OtherName otherName)
  412. {
  413. foreach (OtherName constraint in constraints)
  414. {
  415. if (IsOtherNameConstrained(constraint, otherName))
  416. return true;
  417. }
  418. return false;
  419. }
  420. private void CheckPermittedOtherName(ISet<OtherName> permitted, OtherName name)
  421. {
  422. if (permitted != null && !IsOtherNameConstrained(permitted, name))
  423. throw new PkixNameConstraintValidatorException("Subject OtherName is not from a permitted subtree.");
  424. }
  425. private void CheckExcludedOtherName(ISet<OtherName> excluded, OtherName name)
  426. {
  427. if (IsOtherNameConstrained(excluded, name))
  428. throw new PkixNameConstraintValidatorException("OtherName is from an excluded subtree.");
  429. }
  430. private bool IsEmailConstrained(string constraint, string email)
  431. {
  432. string sub = email.Substring(email.IndexOf('@') + 1);
  433. // a particular mailbox
  434. if (constraint.IndexOf('@') != -1)
  435. {
  436. if (string.Equals(email, constraint, StringComparison.OrdinalIgnoreCase))
  437. return true;
  438. }
  439. // on particular host
  440. else if (constraint[0] != '.')
  441. {
  442. if (string.Equals(sub, constraint, StringComparison.OrdinalIgnoreCase))
  443. return true;
  444. }
  445. // address in sub domain
  446. else if (WithinDomain(sub, constraint))
  447. {
  448. return true;
  449. }
  450. return false;
  451. }
  452. private bool IsEmailConstrained(ISet<string> constraints, string email)
  453. {
  454. foreach (string constraint in constraints)
  455. {
  456. if (IsEmailConstrained(constraint, email))
  457. return true;
  458. }
  459. return false;
  460. }
  461. private void CheckPermittedEmail(ISet<string> permitted, string email)
  462. {
  463. if (permitted != null
  464. && !(email.Length == 0 && permitted.Count < 1)
  465. && !IsEmailConstrained(permitted, email))
  466. {
  467. throw new PkixNameConstraintValidatorException(
  468. "Subject email address is not from a permitted subtree.");
  469. }
  470. }
  471. private void CheckExcludedEmail(ISet<string> excluded, string email)
  472. {
  473. if (IsEmailConstrained(excluded, email))
  474. throw new PkixNameConstraintValidatorException("Email address is from an excluded subtree.");
  475. }
  476. private bool IsDnsConstrained(string constraint, string dns)
  477. {
  478. return WithinDomain(dns, constraint) || Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(dns, constraint);
  479. }
  480. private bool IsDnsConstrained(ISet<string> constraints, string dns)
  481. {
  482. foreach (var constraint in constraints)
  483. {
  484. if (IsDnsConstrained(constraint, dns))
  485. return true;
  486. }
  487. return false;
  488. }
  489. private void CheckPermittedDns(ISet<string> permitted, string dns)
  490. {
  491. if (permitted != null
  492. && !(dns.Length == 0 && permitted.Count < 1)
  493. && !IsDnsConstrained(permitted, dns))
  494. {
  495. throw new PkixNameConstraintValidatorException("DNS is not from a permitted subtree.");
  496. }
  497. }
  498. private void CheckExcludedDns(ISet<string> excluded, string dns)
  499. {
  500. if (IsDnsConstrained(excluded, dns))
  501. throw new PkixNameConstraintValidatorException("DNS is from an excluded subtree.");
  502. }
  503. private bool IsDirectoryConstrained(ISet<Asn1Sequence> constraints, Asn1Sequence directory)
  504. {
  505. foreach (var constraint in constraints)
  506. {
  507. if (WithinDNSubtree(directory, constraint))
  508. return true;
  509. }
  510. return false;
  511. }
  512. private void CheckPermittedDirectory(ISet<Asn1Sequence> permitted, Asn1Sequence directory)
  513. {
  514. if (permitted != null
  515. && !(directory.Count == 0 && permitted.Count < 1)
  516. && !IsDirectoryConstrained(permitted, directory))
  517. {
  518. throw new PkixNameConstraintValidatorException(
  519. "Subject distinguished name is not from a permitted subtree");
  520. }
  521. }
  522. private void CheckExcludedDirectory(ISet<Asn1Sequence> excluded, Asn1Sequence directory)
  523. {
  524. if (IsDirectoryConstrained(excluded, directory))
  525. {
  526. throw new PkixNameConstraintValidatorException(
  527. "Subject distinguished name is from an excluded subtree");
  528. }
  529. }
  530. private bool IsUriConstrained(string constraint, string uri)
  531. {
  532. string host = ExtractHostFromURL(uri);
  533. if (Org.BouncyCastle.Utilities.Platform.StartsWith(constraint, "."))
  534. {
  535. // in sub domain or domain
  536. return WithinDomain(host, constraint);
  537. }
  538. // a host
  539. return Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(host, constraint);
  540. }
  541. private bool IsUriConstrained(ISet<string> constraints, string uri)
  542. {
  543. foreach (string constraint in constraints)
  544. {
  545. if (IsUriConstrained(constraint, uri))
  546. return true;
  547. }
  548. return false;
  549. }
  550. private void CheckPermittedUri(ISet<string> permitted, string uri)
  551. {
  552. if (permitted != null
  553. && !(uri.Length == 0 && permitted.Count < 1)
  554. && !IsUriConstrained(permitted, uri))
  555. {
  556. throw new PkixNameConstraintValidatorException("URI is not from a permitted subtree.");
  557. }
  558. }
  559. private void CheckExcludedUri(ISet<string> excluded, string uri)
  560. {
  561. if (IsUriConstrained(excluded, uri))
  562. throw new PkixNameConstraintValidatorException("URI is from an excluded subtree.");
  563. }
  564. /**
  565. * Checks if the IP address <code>ip</code> is constrained by
  566. * <code>constraint</code>.
  567. *
  568. * @param constraint The constraint. This is an IP address concatenated with
  569. * its subnetmask.
  570. * @param ip The IP address.
  571. * @return <code>true</code> if constrained, <code>false</code>
  572. * otherwise.
  573. */
  574. private bool IsIPConstrained(byte[] constraint, byte[] ip)
  575. {
  576. int ipLength = ip.Length;
  577. if (ipLength != (constraint.Length / 2))
  578. return false;
  579. byte[] subnetMask = new byte[ipLength];
  580. Array.Copy(constraint, ipLength, subnetMask, 0, ipLength);
  581. byte[] permittedSubnetAddress = new byte[ipLength];
  582. byte[] ipSubnetAddress = new byte[ipLength];
  583. // the resulting IP address by applying the subnet mask
  584. for (int i = 0; i < ipLength; i++)
  585. {
  586. permittedSubnetAddress[i] = (byte)(constraint[i] & subnetMask[i]);
  587. ipSubnetAddress[i] = (byte)(ip[i] & subnetMask[i]);
  588. }
  589. return Arrays.AreEqual(permittedSubnetAddress, ipSubnetAddress);
  590. }
  591. private bool IsIPConstrained(ISet<byte[]> constraints, byte[] ip)
  592. {
  593. foreach (byte[] constraint in constraints)
  594. {
  595. if (IsIPConstrained(constraint, ip))
  596. return true;
  597. }
  598. return false;
  599. }
  600. /**
  601. * Checks if the IP <code>ip</code> is included in the permitted ISet
  602. * <code>permitted</code>.
  603. *
  604. * @param permitted A <code>Set</code> of permitted IP addresses with
  605. * their subnet mask as byte arrays.
  606. * @param ip The IP address.
  607. * @throws PkixNameConstraintValidatorException
  608. * if the IP is not permitted.
  609. */
  610. private void CheckPermittedIP(ISet<byte[]> permitted, byte[] ip)
  611. {
  612. if (permitted != null
  613. && !(ip.Length == 0 && permitted.Count < 1)
  614. && !IsIPConstrained(permitted, ip))
  615. {
  616. throw new PkixNameConstraintValidatorException("IP is not from a permitted subtree.");
  617. }
  618. }
  619. /**
  620. * Checks if the IP <code>ip</code> is included in the excluded ISet
  621. * <code>excluded</code>.
  622. *
  623. * @param excluded A <code>Set</code> of excluded IP addresses with their
  624. * subnet mask as byte arrays.
  625. * @param ip The IP address.
  626. * @throws PkixNameConstraintValidatorException
  627. * if the IP is excluded.
  628. */
  629. private void CheckExcludedIP(ISet<byte[]> excluded, byte[] ip)
  630. {
  631. if (IsIPConstrained(excluded, ip))
  632. throw new PkixNameConstraintValidatorException("IP is from an excluded subtree.");
  633. }
  634. private bool WithinDomain(string testDomain, string domain)
  635. {
  636. string tempDomain = domain;
  637. if (Org.BouncyCastle.Utilities.Platform.StartsWith(tempDomain, "."))
  638. {
  639. tempDomain = tempDomain.Substring(1);
  640. }
  641. string[] domainParts = tempDomain.Split('.'); // Strings.split(tempDomain, '.');
  642. string[] testDomainParts = testDomain.Split('.'); // Strings.split(testDomain, '.');
  643. // must have at least one subdomain
  644. if (testDomainParts.Length <= domainParts.Length)
  645. return false;
  646. int d = testDomainParts.Length - domainParts.Length;
  647. for (int i = -1; i < domainParts.Length; i++)
  648. {
  649. if (i == -1)
  650. {
  651. if (testDomainParts[i + d].Length < 1)
  652. {
  653. return false;
  654. }
  655. }
  656. else if (!Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(testDomainParts[i + d], domainParts[i]))
  657. {
  658. return false;
  659. }
  660. }
  661. return true;
  662. }
  663. /**
  664. * The common part of <code>email1</code> and <code>email2</code> is
  665. * added to the union <code>union</code>. If <code>email1</code> and
  666. * <code>email2</code> have nothing in common they are added both.
  667. *
  668. * @param email1 Email address constraint 1.
  669. * @param email2 Email address constraint 2.
  670. * @param union The union.
  671. */
  672. private void UnionEmail(string email1, string email2, ISet<string> union)
  673. {
  674. // email1 is a particular address
  675. if (email1.IndexOf('@') != -1)
  676. {
  677. string _sub = email1.Substring(email1.IndexOf('@') + 1);
  678. // both are a particular mailbox
  679. if (email2.IndexOf('@') != -1)
  680. {
  681. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(email1, email2))
  682. {
  683. union.Add(email1);
  684. }
  685. else
  686. {
  687. union.Add(email1);
  688. union.Add(email2);
  689. }
  690. }
  691. // email2 specifies a domain
  692. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email2, "."))
  693. {
  694. if (WithinDomain(_sub, email2))
  695. {
  696. union.Add(email2);
  697. }
  698. else
  699. {
  700. union.Add(email1);
  701. union.Add(email2);
  702. }
  703. }
  704. // email2 specifies a particular host
  705. else
  706. {
  707. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(_sub, email2))
  708. {
  709. union.Add(email2);
  710. }
  711. else
  712. {
  713. union.Add(email1);
  714. union.Add(email2);
  715. }
  716. }
  717. }
  718. // email1 specifies a domain
  719. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email1, "."))
  720. {
  721. if (email2.IndexOf('@') != -1)
  722. {
  723. string _sub = email2.Substring(email1.IndexOf('@') + 1);
  724. if (WithinDomain(_sub, email1))
  725. {
  726. union.Add(email1);
  727. }
  728. else
  729. {
  730. union.Add(email1);
  731. union.Add(email2);
  732. }
  733. }
  734. // email2 specifies a domain
  735. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email2, "."))
  736. {
  737. if (WithinDomain(email1, email2) || Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(email1, email2))
  738. {
  739. union.Add(email2);
  740. }
  741. else if (WithinDomain(email2, email1))
  742. {
  743. union.Add(email1);
  744. }
  745. else
  746. {
  747. union.Add(email1);
  748. union.Add(email2);
  749. }
  750. }
  751. else
  752. {
  753. if (WithinDomain(email2, email1))
  754. {
  755. union.Add(email1);
  756. }
  757. else
  758. {
  759. union.Add(email1);
  760. union.Add(email2);
  761. }
  762. }
  763. }
  764. // email specifies a host
  765. else
  766. {
  767. if (email2.IndexOf('@') != -1)
  768. {
  769. string _sub = email2.Substring(email1.IndexOf('@') + 1);
  770. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(_sub, email1))
  771. {
  772. union.Add(email1);
  773. }
  774. else
  775. {
  776. union.Add(email1);
  777. union.Add(email2);
  778. }
  779. }
  780. // email2 specifies a domain
  781. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email2, "."))
  782. {
  783. if (WithinDomain(email1, email2))
  784. {
  785. union.Add(email2);
  786. }
  787. else
  788. {
  789. union.Add(email1);
  790. union.Add(email2);
  791. }
  792. }
  793. // email2 specifies a particular host
  794. else
  795. {
  796. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(email1, email2))
  797. {
  798. union.Add(email1);
  799. }
  800. else
  801. {
  802. union.Add(email1);
  803. union.Add(email2);
  804. }
  805. }
  806. }
  807. }
  808. private void UnionUri(string email1, string email2, ISet<string> union)
  809. {
  810. // email1 is a particular address
  811. if (email1.IndexOf('@') != -1)
  812. {
  813. string _sub = email1.Substring(email1.IndexOf('@') + 1);
  814. // both are a particular mailbox
  815. if (email2.IndexOf('@') != -1)
  816. {
  817. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(email1, email2))
  818. {
  819. union.Add(email1);
  820. }
  821. else
  822. {
  823. union.Add(email1);
  824. union.Add(email2);
  825. }
  826. }
  827. // email2 specifies a domain
  828. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email2, "."))
  829. {
  830. if (WithinDomain(_sub, email2))
  831. {
  832. union.Add(email2);
  833. }
  834. else
  835. {
  836. union.Add(email1);
  837. union.Add(email2);
  838. }
  839. }
  840. // email2 specifies a particular host
  841. else
  842. {
  843. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(_sub, email2))
  844. {
  845. union.Add(email2);
  846. }
  847. else
  848. {
  849. union.Add(email1);
  850. union.Add(email2);
  851. }
  852. }
  853. }
  854. // email1 specifies a domain
  855. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email1, "."))
  856. {
  857. if (email2.IndexOf('@') != -1)
  858. {
  859. string _sub = email2.Substring(email1.IndexOf('@') + 1);
  860. if (WithinDomain(_sub, email1))
  861. {
  862. union.Add(email1);
  863. }
  864. else
  865. {
  866. union.Add(email1);
  867. union.Add(email2);
  868. }
  869. }
  870. // email2 specifies a domain
  871. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email2, "."))
  872. {
  873. if (WithinDomain(email1, email2) || Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(email1, email2))
  874. {
  875. union.Add(email2);
  876. }
  877. else if (WithinDomain(email2, email1))
  878. {
  879. union.Add(email1);
  880. }
  881. else
  882. {
  883. union.Add(email1);
  884. union.Add(email2);
  885. }
  886. }
  887. else
  888. {
  889. if (WithinDomain(email2, email1))
  890. {
  891. union.Add(email1);
  892. }
  893. else
  894. {
  895. union.Add(email1);
  896. union.Add(email2);
  897. }
  898. }
  899. }
  900. // email specifies a host
  901. else
  902. {
  903. if (email2.IndexOf('@') != -1)
  904. {
  905. string _sub = email2.Substring(email1.IndexOf('@') + 1);
  906. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(_sub, email1))
  907. {
  908. union.Add(email1);
  909. }
  910. else
  911. {
  912. union.Add(email1);
  913. union.Add(email2);
  914. }
  915. }
  916. // email2 specifies a domain
  917. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email2, "."))
  918. {
  919. if (WithinDomain(email1, email2))
  920. {
  921. union.Add(email2);
  922. }
  923. else
  924. {
  925. union.Add(email1);
  926. union.Add(email2);
  927. }
  928. }
  929. // email2 specifies a particular host
  930. else
  931. {
  932. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(email1, email2))
  933. {
  934. union.Add(email1);
  935. }
  936. else
  937. {
  938. union.Add(email1);
  939. union.Add(email2);
  940. }
  941. }
  942. }
  943. }
  944. private ISet<string> IntersectDns(ISet<string> permitted, ISet<GeneralSubtree> dnss)
  945. {
  946. var intersect = new HashSet<string>();
  947. foreach (GeneralSubtree subtree in dnss)
  948. {
  949. string dns = ExtractNameAsString(subtree.Base);
  950. if (permitted == null)
  951. {
  952. if (dns != null)
  953. {
  954. intersect.Add(dns);
  955. }
  956. }
  957. else
  958. {
  959. foreach (string _permitted in permitted)
  960. {
  961. if (WithinDomain(_permitted, dns))
  962. {
  963. intersect.Add(_permitted);
  964. }
  965. else if (WithinDomain(dns, _permitted))
  966. {
  967. intersect.Add(dns);
  968. }
  969. }
  970. }
  971. }
  972. return intersect;
  973. }
  974. private ISet<string> UnionDns(ISet<string> excluded, string dns)
  975. {
  976. if (excluded.Count < 1)
  977. {
  978. if (dns == null)
  979. return excluded;
  980. excluded.Add(dns);
  981. return excluded;
  982. }
  983. var union = new HashSet<string>();
  984. foreach (string _excluded in excluded)
  985. {
  986. if (WithinDomain(_excluded, dns))
  987. {
  988. union.Add(dns);
  989. }
  990. else if (WithinDomain(dns, _excluded))
  991. {
  992. union.Add(_excluded);
  993. }
  994. else
  995. {
  996. union.Add(_excluded);
  997. union.Add(dns);
  998. }
  999. }
  1000. return union;
  1001. }
  1002. /**
  1003. * The most restricting part from <code>email1</code> and
  1004. * <code>email2</code> is added to the intersection <code>intersect</code>.
  1005. *
  1006. * @param email1 Email address constraint 1.
  1007. * @param email2 Email address constraint 2.
  1008. * @param intersect The intersection.
  1009. */
  1010. private void IntersectEmail(string email1, string email2, ISet<string> intersect)
  1011. {
  1012. // email1 is a particular address
  1013. if (email1.IndexOf('@') != -1)
  1014. {
  1015. string _sub = email1.Substring(email1.IndexOf('@') + 1);
  1016. // both are a particular mailbox
  1017. if (email2.IndexOf('@') != -1)
  1018. {
  1019. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(email1, email2))
  1020. {
  1021. intersect.Add(email1);
  1022. }
  1023. }
  1024. // email2 specifies a domain
  1025. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email2, "."))
  1026. {
  1027. if (WithinDomain(_sub, email2))
  1028. {
  1029. intersect.Add(email1);
  1030. }
  1031. }
  1032. // email2 specifies a particular host
  1033. else
  1034. {
  1035. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(_sub, email2))
  1036. {
  1037. intersect.Add(email1);
  1038. }
  1039. }
  1040. }
  1041. // email specifies a domain
  1042. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email1, "."))
  1043. {
  1044. if (email2.IndexOf('@') != -1)
  1045. {
  1046. string _sub = email2.Substring(email1.IndexOf('@') + 1);
  1047. if (WithinDomain(_sub, email1))
  1048. {
  1049. intersect.Add(email2);
  1050. }
  1051. }
  1052. // email2 specifies a domain
  1053. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email2, "."))
  1054. {
  1055. if (WithinDomain(email1, email2) || Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(email1, email2))
  1056. {
  1057. intersect.Add(email1);
  1058. }
  1059. else if (WithinDomain(email2, email1))
  1060. {
  1061. intersect.Add(email2);
  1062. }
  1063. }
  1064. else
  1065. {
  1066. if (WithinDomain(email2, email1))
  1067. {
  1068. intersect.Add(email2);
  1069. }
  1070. }
  1071. }
  1072. // email1 specifies a host
  1073. else
  1074. {
  1075. if (email2.IndexOf('@') != -1)
  1076. {
  1077. string _sub = email2.Substring(email2.IndexOf('@') + 1);
  1078. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(_sub, email1))
  1079. {
  1080. intersect.Add(email2);
  1081. }
  1082. }
  1083. // email2 specifies a domain
  1084. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email2, "."))
  1085. {
  1086. if (WithinDomain(email1, email2))
  1087. {
  1088. intersect.Add(email1);
  1089. }
  1090. }
  1091. // email2 specifies a particular host
  1092. else
  1093. {
  1094. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(email1, email2))
  1095. {
  1096. intersect.Add(email1);
  1097. }
  1098. }
  1099. }
  1100. }
  1101. private ISet<string> IntersectUri(ISet<string> permitted, ISet<GeneralSubtree> uris)
  1102. {
  1103. var intersect = new HashSet<string>();
  1104. foreach (GeneralSubtree subtree in uris)
  1105. {
  1106. string uri = ExtractNameAsString(subtree.Base);
  1107. if (permitted == null)
  1108. {
  1109. if (uri != null)
  1110. {
  1111. intersect.Add(uri);
  1112. }
  1113. }
  1114. else
  1115. {
  1116. foreach (string _permitted in permitted)
  1117. {
  1118. IntersectUri(_permitted, uri, intersect);
  1119. }
  1120. }
  1121. }
  1122. return intersect;
  1123. }
  1124. private ISet<string> UnionUri(ISet<string> excluded, string uri)
  1125. {
  1126. if (excluded.Count < 1)
  1127. {
  1128. if (uri == null)
  1129. return excluded;
  1130. excluded.Add(uri);
  1131. return excluded;
  1132. }
  1133. var union = new HashSet<string>();
  1134. foreach (string _excluded in excluded)
  1135. {
  1136. UnionUri(_excluded, uri, union);
  1137. }
  1138. return union;
  1139. }
  1140. private void IntersectUri(string email1, string email2, ISet<string> intersect)
  1141. {
  1142. // email1 is a particular address
  1143. if (email1.IndexOf('@') != -1)
  1144. {
  1145. string _sub = email1.Substring(email1.IndexOf('@') + 1);
  1146. // both are a particular mailbox
  1147. if (email2.IndexOf('@') != -1)
  1148. {
  1149. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(email1, email2))
  1150. {
  1151. intersect.Add(email1);
  1152. }
  1153. }
  1154. // email2 specifies a domain
  1155. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email2, "."))
  1156. {
  1157. if (WithinDomain(_sub, email2))
  1158. {
  1159. intersect.Add(email1);
  1160. }
  1161. }
  1162. // email2 specifies a particular host
  1163. else
  1164. {
  1165. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(_sub, email2))
  1166. {
  1167. intersect.Add(email1);
  1168. }
  1169. }
  1170. }
  1171. // email specifies a domain
  1172. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email1, "."))
  1173. {
  1174. if (email2.IndexOf('@') != -1)
  1175. {
  1176. string _sub = email2.Substring(email1.IndexOf('@') + 1);
  1177. if (WithinDomain(_sub, email1))
  1178. {
  1179. intersect.Add(email2);
  1180. }
  1181. }
  1182. // email2 specifies a domain
  1183. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email2, "."))
  1184. {
  1185. if (WithinDomain(email1, email2) || Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(email1, email2))
  1186. {
  1187. intersect.Add(email1);
  1188. }
  1189. else if (WithinDomain(email2, email1))
  1190. {
  1191. intersect.Add(email2);
  1192. }
  1193. }
  1194. else
  1195. {
  1196. if (WithinDomain(email2, email1))
  1197. {
  1198. intersect.Add(email2);
  1199. }
  1200. }
  1201. }
  1202. // email1 specifies a host
  1203. else
  1204. {
  1205. if (email2.IndexOf('@') != -1)
  1206. {
  1207. string _sub = email2.Substring(email2.IndexOf('@') + 1);
  1208. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(_sub, email1))
  1209. {
  1210. intersect.Add(email2);
  1211. }
  1212. }
  1213. // email2 specifies a domain
  1214. else if (Org.BouncyCastle.Utilities.Platform.StartsWith(email2, "."))
  1215. {
  1216. if (WithinDomain(email1, email2))
  1217. {
  1218. intersect.Add(email1);
  1219. }
  1220. }
  1221. // email2 specifies a particular host
  1222. else
  1223. {
  1224. if (Org.BouncyCastle.Utilities.Platform.EqualsIgnoreCase(email1, email2))
  1225. {
  1226. intersect.Add(email1);
  1227. }
  1228. }
  1229. }
  1230. }
  1231. private static string ExtractHostFromURL(string url)
  1232. {
  1233. // see RFC 1738
  1234. // remove ':' after protocol, e.g. http:
  1235. string sub = url.Substring(url.IndexOf(':') + 1);
  1236. // extract host from Common Internet Scheme Syntax, e.g. http://
  1237. int idxOfSlashes = Org.BouncyCastle.Utilities.Platform.IndexOf(sub, "//");
  1238. if (idxOfSlashes != -1)
  1239. {
  1240. sub = sub.Substring(idxOfSlashes + 2);
  1241. }
  1242. // first remove port, e.g. http://test.com:21
  1243. if (sub.LastIndexOf(':') != -1)
  1244. {
  1245. sub = sub.Substring(0, sub.LastIndexOf(':'));
  1246. }
  1247. // remove user and password, e.g. http://john:password@test.com
  1248. sub = sub.Substring(sub.IndexOf(':') + 1);
  1249. sub = sub.Substring(sub.IndexOf('@') + 1);
  1250. // remove local parts, e.g. http://test.com/bla
  1251. if (sub.IndexOf('/') != -1)
  1252. {
  1253. sub = sub.Substring(0, sub.IndexOf('/'));
  1254. }
  1255. return sub;
  1256. }
  1257. /**
  1258. * Checks if the given GeneralName is in the permitted ISet.
  1259. *
  1260. * @param name The GeneralName
  1261. * @throws PkixNameConstraintValidatorException
  1262. * If the <code>name</code>
  1263. */
  1264. public void checkPermitted(GeneralName name)
  1265. //throws PkixNameConstraintValidatorException
  1266. {
  1267. switch (name.TagNo)
  1268. {
  1269. case GeneralName.OtherName:
  1270. CheckPermittedOtherName(permittedSubtreesOtherName, OtherName.GetInstance(name.Name));
  1271. break;
  1272. case GeneralName.Rfc822Name:
  1273. CheckPermittedEmail(permittedSubtreesEmail, ExtractNameAsString(name));
  1274. break;
  1275. case GeneralName.DnsName:
  1276. CheckPermittedDns(permittedSubtreesDns, ExtractNameAsString(name));
  1277. break;
  1278. case GeneralName.DirectoryName:
  1279. CheckPermittedDN(Asn1Sequence.GetInstance(name.Name.ToAsn1Object()));
  1280. break;
  1281. case GeneralName.UniformResourceIdentifier:
  1282. CheckPermittedUri(permittedSubtreesUri, ExtractNameAsString(name));
  1283. break;
  1284. case GeneralName.IPAddress:
  1285. CheckPermittedIP(permittedSubtreesIP, Asn1OctetString.GetInstance(name.Name).GetOctets());
  1286. break;
  1287. }
  1288. }
  1289. /**
  1290. * Check if the given GeneralName is contained in the excluded ISet.
  1291. *
  1292. * @param name The GeneralName.
  1293. * @throws PkixNameConstraintValidatorException
  1294. * If the <code>name</code> is
  1295. * excluded.
  1296. */
  1297. public void checkExcluded(GeneralName name)
  1298. //throws PkixNameConstraintValidatorException
  1299. {
  1300. switch (name.TagNo)
  1301. {
  1302. case GeneralName.OtherName:
  1303. CheckExcludedOtherName(excludedSubtreesOtherName, OtherName.GetInstance(name.Name));
  1304. break;
  1305. case GeneralName.Rfc822Name:
  1306. CheckExcludedEmail(excludedSubtreesEmail, ExtractNameAsString(name));
  1307. break;
  1308. case GeneralName.DnsName:
  1309. CheckExcludedDns(excludedSubtreesDns, ExtractNameAsString(name));
  1310. break;
  1311. case GeneralName.DirectoryName:
  1312. CheckExcludedDN(Asn1Sequence.GetInstance(name.Name.ToAsn1Object()));
  1313. break;
  1314. case GeneralName.UniformResourceIdentifier:
  1315. CheckExcludedUri(excludedSubtreesUri, ExtractNameAsString(name));
  1316. break;
  1317. case GeneralName.IPAddress:
  1318. CheckExcludedIP(excludedSubtreesIP, Asn1OctetString.GetInstance(name.Name).GetOctets());
  1319. break;
  1320. }
  1321. }
  1322. /**
  1323. * Updates the permitted ISet of these name constraints with the intersection
  1324. * with the given subtree.
  1325. *
  1326. * @param permitted The permitted subtrees
  1327. */
  1328. public void IntersectPermittedSubtree(Asn1Sequence permitted)
  1329. {
  1330. var subtreesMap = new Dictionary<int, ISet<GeneralSubtree>>();
  1331. // group in ISets in a map ordered by tag no.
  1332. foreach (var element in permitted)
  1333. {
  1334. GeneralSubtree subtree = GeneralSubtree.GetInstance(element);
  1335. int tagNo = subtree.Base.TagNo;
  1336. ISet<GeneralSubtree> subtrees;
  1337. if (!subtreesMap.TryGetValue(tagNo, out subtrees))
  1338. {
  1339. subtrees = new HashSet<GeneralSubtree>();
  1340. subtreesMap[tagNo] = subtrees;
  1341. }
  1342. subtrees.Add(subtree);
  1343. }
  1344. foreach (var entry in subtreesMap)
  1345. {
  1346. // go through all subtree groups
  1347. switch (entry.Key)
  1348. {
  1349. case GeneralName.OtherName:
  1350. permittedSubtreesOtherName = IntersectOtherName(permittedSubtreesOtherName, entry.Value);
  1351. break;
  1352. case GeneralName.Rfc822Name:
  1353. permittedSubtreesEmail = IntersectEmail(permittedSubtreesEmail, entry.Value);
  1354. break;
  1355. case GeneralName.DnsName:
  1356. permittedSubtreesDns = IntersectDns(permittedSubtreesDns, entry.Value);
  1357. break;
  1358. case GeneralName.DirectoryName:
  1359. permittedSubtreesDN = IntersectDN(permittedSubtreesDN, entry.Value);
  1360. break;
  1361. case GeneralName.UniformResourceIdentifier:
  1362. permittedSubtreesUri = IntersectUri(permittedSubtreesUri, entry.Value);
  1363. break;
  1364. case GeneralName.IPAddress:
  1365. permittedSubtreesIP = IntersectIP(permittedSubtreesIP, entry.Value);
  1366. break;
  1367. }
  1368. }
  1369. }
  1370. private string ExtractNameAsString(GeneralName name)
  1371. {
  1372. return DerIA5String.GetInstance(name.Name).GetString();
  1373. }
  1374. public void IntersectEmptyPermittedSubtree(int nameType)
  1375. {
  1376. switch (nameType)
  1377. {
  1378. case GeneralName.OtherName:
  1379. permittedSubtreesOtherName = new HashSet<OtherName>();
  1380. break;
  1381. case GeneralName.Rfc822Name:
  1382. permittedSubtreesEmail = new HashSet<string>();
  1383. break;
  1384. case GeneralName.DnsName:
  1385. permittedSubtreesDns = new HashSet<string>();
  1386. break;
  1387. case GeneralName.DirectoryName:
  1388. permittedSubtreesDN = new HashSet<Asn1Sequence>();
  1389. break;
  1390. case GeneralName.UniformResourceIdentifier:
  1391. permittedSubtreesUri = new HashSet<string>();
  1392. break;
  1393. case GeneralName.IPAddress:
  1394. permittedSubtreesIP = new HashSet<byte[]>();
  1395. break;
  1396. }
  1397. }
  1398. /**
  1399. * Adds a subtree to the excluded ISet of these name constraints.
  1400. *
  1401. * @param subtree A subtree with an excluded GeneralName.
  1402. */
  1403. public void AddExcludedSubtree(GeneralSubtree subtree)
  1404. {
  1405. GeneralName subTreeBase = subtree.Base;
  1406. switch (subTreeBase.TagNo)
  1407. {
  1408. case GeneralName.OtherName:
  1409. excludedSubtreesOtherName = UnionOtherName(excludedSubtreesOtherName,
  1410. OtherName.GetInstance(subTreeBase.Name));
  1411. break;
  1412. case GeneralName.Rfc822Name:
  1413. excludedSubtreesEmail = UnionEmail(excludedSubtreesEmail,
  1414. ExtractNameAsString(subTreeBase));
  1415. break;
  1416. case GeneralName.DnsName:
  1417. excludedSubtreesDns = UnionDns(excludedSubtreesDns,
  1418. ExtractNameAsString(subTreeBase));
  1419. break;
  1420. case GeneralName.DirectoryName:
  1421. excludedSubtreesDN = UnionDN(excludedSubtreesDN,
  1422. (Asn1Sequence)subTreeBase.Name.ToAsn1Object());
  1423. break;
  1424. case GeneralName.UniformResourceIdentifier:
  1425. excludedSubtreesUri = UnionUri(excludedSubtreesUri,
  1426. ExtractNameAsString(subTreeBase));
  1427. break;
  1428. case GeneralName.IPAddress:
  1429. excludedSubtreesIP = UnionIP(excludedSubtreesIP,
  1430. Asn1OctetString.GetInstance(subTreeBase.Name).GetOctets());
  1431. break;
  1432. }
  1433. }
  1434. /**
  1435. * Returns the maximum IP address.
  1436. *
  1437. * @param ip1 The first IP address.
  1438. * @param ip2 The second IP address.
  1439. * @return The maximum IP address.
  1440. */
  1441. private static byte[] Max(byte[] ip1, byte[] ip2)
  1442. {
  1443. for (int i = 0; i < ip1.Length; i++)
  1444. {
  1445. if ((ip1[i] & 0xFFFF) > (ip2[i] & 0xFFFF))
  1446. {
  1447. return ip1;
  1448. }
  1449. }
  1450. return ip2;
  1451. }
  1452. /**
  1453. * Returns the minimum IP address.
  1454. *
  1455. * @param ip1 The first IP address.
  1456. * @param ip2 The second IP address.
  1457. * @return The minimum IP address.
  1458. */
  1459. private static byte[] Min(byte[] ip1, byte[] ip2)
  1460. {
  1461. for (int i = 0; i < ip1.Length; i++)
  1462. {
  1463. if ((ip1[i] & 0xFFFF) < (ip2[i] & 0xFFFF))
  1464. {
  1465. return ip1;
  1466. }
  1467. }
  1468. return ip2;
  1469. }
  1470. /**
  1471. * Compares IP address <code>ip1</code> with <code>ip2</code>. If ip1
  1472. * is equal to ip2 0 is returned. If ip1 is bigger 1 is returned, -1
  1473. * otherwise.
  1474. *
  1475. * @param ip1 The first IP address.
  1476. * @param ip2 The second IP address.
  1477. * @return 0 if ip1 is equal to ip2, 1 if ip1 is bigger, -1 otherwise.
  1478. */
  1479. private static int CompareTo(byte[] ip1, byte[] ip2)
  1480. {
  1481. if (BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Arrays.AreEqual(ip1, ip2))
  1482. {
  1483. return 0;
  1484. }
  1485. if (BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Arrays.AreEqual(Max(ip1, ip2), ip1))
  1486. {
  1487. return 1;
  1488. }
  1489. return -1;
  1490. }
  1491. /**
  1492. * Returns the logical OR of the IP addresses <code>ip1</code> and
  1493. * <code>ip2</code>.
  1494. *
  1495. * @param ip1 The first IP address.
  1496. * @param ip2 The second IP address.
  1497. * @return The OR of <code>ip1</code> and <code>ip2</code>.
  1498. */
  1499. private static byte[] Or(byte[] ip1, byte[] ip2)
  1500. {
  1501. byte[] temp = new byte[ip1.Length];
  1502. for (int i = 0; i < ip1.Length; i++)
  1503. {
  1504. temp[i] = (byte)(ip1[i] | ip2[i]);
  1505. }
  1506. return temp;
  1507. }
  1508. public override int GetHashCode()
  1509. {
  1510. return HashCollection(excludedSubtreesDN)
  1511. + HashCollection(excludedSubtreesDns)
  1512. + HashCollection(excludedSubtreesEmail)
  1513. + HashCollection(excludedSubtreesIP)
  1514. + HashCollection(excludedSubtreesUri)
  1515. + HashCollection(excludedSubtreesOtherName)
  1516. + HashCollection(permittedSubtreesDN)
  1517. + HashCollection(permittedSubtreesDns)
  1518. + HashCollection(permittedSubtreesEmail)
  1519. + HashCollection(permittedSubtreesIP)
  1520. + HashCollection(permittedSubtreesUri)
  1521. + HashCollection(permittedSubtreesOtherName);
  1522. }
  1523. private int HashCollection(IEnumerable<byte[]> c)
  1524. {
  1525. int hash = 0;
  1526. if (c != null)
  1527. {
  1528. foreach (byte[] o in c)
  1529. {
  1530. hash += Arrays.GetHashCode(o);
  1531. }
  1532. }
  1533. return hash;
  1534. }
  1535. private int HashCollection(IEnumerable<object> c)
  1536. {
  1537. int hash = 0;
  1538. if (c != null)
  1539. {
  1540. foreach (object o in c)
  1541. {
  1542. hash += o.GetHashCode();
  1543. }
  1544. }
  1545. return hash;
  1546. }
  1547. public override bool Equals(object o)
  1548. {
  1549. if (!(o is PkixNameConstraintValidator that))
  1550. return false;
  1551. return AreEqualSets(that.excludedSubtreesDN, excludedSubtreesDN)
  1552. && AreEqualSets(that.excludedSubtreesDns, excludedSubtreesDns)
  1553. && AreEqualSets(that.excludedSubtreesEmail, excludedSubtreesEmail)
  1554. && AreEqualSets(that.excludedSubtreesIP, excludedSubtreesIP)
  1555. && AreEqualSets(that.excludedSubtreesUri, excludedSubtreesUri)
  1556. && AreEqualSets(that.excludedSubtreesOtherName, excludedSubtreesOtherName)
  1557. && AreEqualSets(that.permittedSubtreesDN, permittedSubtreesDN)
  1558. && AreEqualSets(that.permittedSubtreesDns, permittedSubtreesDns)
  1559. && AreEqualSets(that.permittedSubtreesEmail, permittedSubtreesEmail)
  1560. && AreEqualSets(that.permittedSubtreesIP, permittedSubtreesIP)
  1561. && AreEqualSets(that.permittedSubtreesUri, permittedSubtreesUri)
  1562. && AreEqualSets(that.permittedSubtreesOtherName, permittedSubtreesOtherName);
  1563. }
  1564. private bool AreEqualSets(ISet<byte[]> set1, ISet<byte[]> set2)
  1565. {
  1566. if (set1 == set2)
  1567. return true;
  1568. if (set1 == null || set2 == null || set1.Count != set2.Count)
  1569. return false;
  1570. foreach (byte[] a in set1)
  1571. {
  1572. bool found = false;
  1573. foreach (byte[] b in set2)
  1574. {
  1575. if (Arrays.AreEqual(a, b))
  1576. {
  1577. found = true;
  1578. break;
  1579. }
  1580. }
  1581. if (!found)
  1582. return false;
  1583. }
  1584. return true;
  1585. }
  1586. private bool AreEqualSets<T>(ISet<T> set1, ISet<T> set2)
  1587. {
  1588. if (set1 == set2)
  1589. return true;
  1590. if (set1 == null || set2 == null || set1.Count != set2.Count)
  1591. return false;
  1592. foreach (T a in set1)
  1593. {
  1594. if (!set2.Contains(a))
  1595. return false;
  1596. }
  1597. return true;
  1598. }
  1599. /**
  1600. * Stringifies an IPv4 or v6 address with subnet mask.
  1601. *
  1602. * @param ip The IP with subnet mask.
  1603. * @return The stringified IP address.
  1604. */
  1605. private string StringifyIP(byte[] ip)
  1606. {
  1607. string temp = "";
  1608. for (int i = 0; i < ip.Length / 2; i++)
  1609. {
  1610. temp += (ip[i] & 0x00FF) + ".";
  1611. }
  1612. temp = temp.Substring(0, temp.Length - 1);
  1613. temp += "/";
  1614. for (int i = ip.Length / 2; i < ip.Length; i++)
  1615. {
  1616. temp += (ip[i] & 0x00FF) + ".";
  1617. }
  1618. temp = temp.Substring(0, temp.Length - 1);
  1619. return temp;
  1620. }
  1621. private string StringifyIPCollection(ISet<byte[]> ips)
  1622. {
  1623. string temp = "";
  1624. temp += "[";
  1625. foreach (byte[] ip in ips)
  1626. {
  1627. temp += StringifyIP(ip) + ",";
  1628. }
  1629. if (temp.Length > 1)
  1630. {
  1631. temp = temp.Substring(0, temp.Length - 1);
  1632. }
  1633. temp += "]";
  1634. return temp;
  1635. }
  1636. private string StringifyOtherNameCollection(ISet<OtherName> otherNames)
  1637. {
  1638. StringBuilder sb = new StringBuilder('[');
  1639. foreach (OtherName name in otherNames)
  1640. {
  1641. if (sb.Length > 1)
  1642. {
  1643. sb.Append(',');
  1644. }
  1645. sb.Append(name.TypeID.Id);
  1646. sb.Append(':');
  1647. sb.Append(Hex.ToHexString(name.Value.GetEncoded()));
  1648. }
  1649. sb.Append(']');
  1650. return sb.ToString();
  1651. }
  1652. public override string ToString()
  1653. {
  1654. StringBuilder sb = new StringBuilder("permitted:\n");
  1655. if (permittedSubtreesDN != null)
  1656. {
  1657. Append(sb, "DN", permittedSubtreesDN);
  1658. }
  1659. if (permittedSubtreesDns != null)
  1660. {
  1661. Append(sb, "DNS", permittedSubtreesDns);
  1662. }
  1663. if (permittedSubtreesEmail != null)
  1664. {
  1665. Append(sb, "Email", permittedSubtreesEmail);
  1666. }
  1667. if (permittedSubtreesUri != null)
  1668. {
  1669. Append(sb, "URI", permittedSubtreesUri);
  1670. }
  1671. if (permittedSubtreesIP != null)
  1672. {
  1673. Append(sb, "IP", StringifyIPCollection(permittedSubtreesIP));
  1674. }
  1675. if (permittedSubtreesOtherName != null)
  1676. {
  1677. Append(sb, "OtherName", StringifyOtherNameCollection(permittedSubtreesOtherName));
  1678. }
  1679. sb.Append("excluded:\n");
  1680. if (excludedSubtreesDN.Count > 0)
  1681. {
  1682. Append(sb, "DN", excludedSubtreesDN);
  1683. }
  1684. if (excludedSubtreesDns.Count > 0)
  1685. {
  1686. Append(sb, "DNS", excludedSubtreesDns);
  1687. }
  1688. if (excludedSubtreesEmail.Count > 0)
  1689. {
  1690. Append(sb, "Email", excludedSubtreesEmail);
  1691. }
  1692. if (excludedSubtreesUri.Count > 0)
  1693. {
  1694. Append(sb, "URI", excludedSubtreesUri);
  1695. }
  1696. if (excludedSubtreesIP.Count > 0)
  1697. {
  1698. Append(sb, "IP", StringifyIPCollection(excludedSubtreesIP));
  1699. }
  1700. if (excludedSubtreesOtherName.Count > 0)
  1701. {
  1702. Append(sb, "OtherName", StringifyOtherNameCollection(excludedSubtreesOtherName));
  1703. }
  1704. return sb.ToString();
  1705. }
  1706. private static void Append(StringBuilder sb, string name, object value)
  1707. {
  1708. sb.Append(name);
  1709. sb.AppendLine(":");
  1710. sb.Append(value);
  1711. sb.AppendLine();
  1712. }
  1713. }
  1714. }
  1715. #pragma warning restore
  1716. #endif