PkixNameConstraintValidator.cs 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861
  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