Dear all, Two weeks ago AFRINIC was placed under receivership by the Supreme Court of Mauritius [1]. This event prompted me to rethink our trust and threat model and associated risk surface.
The RPKI technology was designed to be versatile and flexible to accommodate a myriad of real-world deployment scenarios including multiple trust anchors existing, inter-registry transfers, multiple transports, and permissionless innovation for signed objects, for example. All good and well ... but there is a fine print. Over the years various people have expressed astonishment about each RIR having issued so-called 'all-resources' (0.0.0.0/0 + ::/0) trust anchor certificates, but this aspect often is misunderstood: the risk is not necessarily in the listing of 'all-resources' itself, it is in the RIR being able to issue an 'all-resources' certificate in the first place. RPKI trust anchor operators indeed can voluntarily reduce the scope of subordinate Internet Number Resources, but just as easily increase the scope of their authority. In other words, a trust anchor cannot truly constrain itself. Upon reconsideration on how exactly RPKI hooks into the real world; I concluded trust anchors do not require unbounded trust in order to provide constructive services in the realm of BGP routing security. Some examples: ARIN does not support inter-RIR IPv6 transfers, so it would not make any sense to see a ROA subordinate to ARIN's trust anchor covering RIPE-managed IPv6 space. Conversely, it wouldn't make sense to observe a ROA covering ARIN-managed IPv6 space under APNIC's, LACNIC's, or RIPE's trust anchor - even if a cryptographically valid certificate path existed. Along these lines AFRINIC doesn't support inter-RIR transfers of any kind, and none of the RIRs have authority over private resources like 10.0.0.0/8. Theo Buehler and myself have worked diligently over the last 2 weeks to research RIR transfer policies, untangle the history of the IANA->RIR and RIR->RIR allocation spaghetti, design & implement a maintainable constraints mechanism for rpki-client(8), and publicly document the concept. https://www.ietf.org/archive/id/draft-snijders-constraining-rpki-trust-anchors-00.html I believe our approach is feasible and beneficial. The constraints are simple text files and parsed in a restricted subprocess. Operators can trivially disable the imposition of constraints by deleting /etc/rpki/*.constraints, if need be. I do regret to have to propose this giant diff so close to release, but here we are. Your help is welcome. Kind regards, Job [1]: https://mybroadband.co.za/news/internet/507882-africas-internet-registry-placed-under-receivership.html Index: etc/Makefile =================================================================== RCS file: /cvs/src/etc/Makefile,v retrieving revision 1.486 diff -u -p -r1.486 Makefile --- etc/Makefile 28 Jun 2022 18:46:00 -0000 1.486 +++ etc/Makefile 26 Sep 2023 14:27:45 -0000 @@ -157,6 +157,8 @@ distribution-etc-root-var: distrib-dirs cd rpki; \ ${INSTALL} -c -o root -g wheel -m 644 \ afrinic.tal apnic.tal lacnic.tal ripe.tal \ + arin.constraints afrinic.constraints apnic.constraints \ + lacnic.constraints ripe.constraints \ ${DESTDIR}/etc/rpki cd examples; \ ${INSTALL} -c -o root -g wheel -m 644 ${EXAMPLES} \ Index: etc/changelist =================================================================== RCS file: /cvs/src/etc/changelist,v retrieving revision 1.137 diff -u -p -r1.137 changelist --- etc/changelist 19 Sep 2023 15:02:54 -0000 1.137 +++ etc/changelist 26 Sep 2023 14:27:45 -0000 @@ -112,10 +112,15 @@ /etc/resolv.conf /etc/ripd.conf /etc/rpc +/etc/rpki/afrinic.constraints /etc/rpki/afrinic.tal +/etc/rpki/apnic.constraints /etc/rpki/apnic.tal +/etc/rpki/arin.constraints /etc/rpki/arin.tal +/etc/rpki/lacnic.constraints /etc/rpki/lacnic.tal +/etc/rpki/ripe.constraints /etc/rpki/ripe.tal /etc/rpki/skiplist /etc/sasyncd.conf Index: etc/rpki/afrinic.constraints =================================================================== RCS file: etc/rpki/afrinic.constraints diff -N etc/rpki/afrinic.constraints --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ etc/rpki/afrinic.constraints 26 Sep 2023 14:27:45 -0000 @@ -0,0 +1,612 @@ +# From https://www.iana.org/assignments/ipv4-address-space/ +allow 41.0.0.0/8 +allow 102.0.0.0/8 +allow 105.0.0.0/8 +allow 154.0.0.0/8 +allow 196.0.0.0/7 + +# From https://www.iana.org/assignments/ipv6-address-space/ +allow 2001:4200::/23 +allow 2c00::/12 + +# From https://www.iana.org/assignments/as-numbers/ +allow 36864 - 37887 +allow 327680 - 328703 +allow 328704 - 329727 + +# Holes +deny 154.8.48.0 - 154.8.255.255 # APNIC +deny 154.10.0.0/16 # APNIC +deny 154.33.0.0 - 154.34.255.255 # APNIC +deny 196.1.1.0/24 # APNIC +deny 196.1.68.0/24 # APNIC +deny 196.1.104.0 - 196.1.106.255 # APNIC +deny 196.1.108.0/22 # APNIC +deny 196.1.113.0 - 196.1.114.255 # APNIC +deny 196.1.134.0/24 # APNIC +deny 196.3.65.0/24 # APNIC +deny 196.3.72.0/24 # APNIC +deny 196.12.32.0/19 # APNIC +deny 196.15.16.0/20 # APNIC +deny 154.5.0.0/16 # ARIN +deny 154.11.0.0/16 # ARIN +deny 154.20.0.0/16 # ARIN +deny 196.32.32.0/19 # LACNIC +deny 196.29.64.0/19 # LACNIC +deny 196.40.0.0 - 196.40.95.255 # LACNIC +deny 196.32.64.0/19 # LACNIC + +# From https://www.iana.org/assignments/ipv4-recovered-address-space +allow 45.96.0.0 - 45.111.255.255 +allow 45.192.0.0 - 45.222.255.255 +allow 45.240.0.0 - 45.247.255.255 +allow 66.251.128.0 - 66.251.191.255 +allow 139.26.0.0 - 139.26.255.255 +allow 146.196.128.0 - 146.196.255.255 +# 154.16.0.0 - 154.16.255.255 # already contained within 154/8 +allow 160.19.36.0 - 160.19.39.255 +allow 160.19.60.0 - 160.19.63.255 +allow 160.19.96.0 - 160.19.103.255 +allow 160.19.112.0 - 160.19.143.255 +allow 160.19.152.0 - 160.19.155.255 +allow 160.19.188.0 - 160.19.191.255 +allow 160.19.192.0 - 160.19.199.255 +allow 160.19.232.0 - 160.19.239.255 +allow 160.20.24.0 - 160.20.31.255 +allow 160.20.112.0 - 160.20.115.255 +allow 160.20.213.0 - 160.20.213.255 +allow 160.20.217.0 - 160.20.217.255 +allow 160.20.221.0 - 160.20.221.255 +allow 160.20.226.0 - 160.20.227.255 +allow 160.20.252.0 - 160.20.255.255 +allow 160.238.11.0 - 160.238.11.255 +allow 160.238.48.0 - 160.238.49.255 +allow 160.238.50.0 - 160.238.50.255 +allow 160.238.57.0 - 160.238.57.255 +allow 160.238.101.0 - 160.238.101.255 +allow 161.123.0.0 - 161.123.255.255 +allow 164.160.0.0 - 164.160.255.255 +allow 192.12.110.0 - 192.12.111.255 +allow 192.12.116.0 - 192.12.117.255 +allow 192.47.36.0 - 192.47.36.255 +allow 192.51.240.0 - 192.51.240.255 +allow 192.70.200.0 - 192.70.201.255 +allow 192.75.236.0 - 192.75.236.255 +allow 192.83.208.0 - 192.83.215.255 +allow 192.91.200.0 - 192.91.200.255 +allow 192.142.0.0 - 192.143.255.255 +allow 192.145.128.0 - 192.145.191.255 +allow 192.145.230.0 - 192.145.230.255 +allow 204.8.204.0 - 204.8.207.255 +allow 208.85.156.0 - 208.85.159.255 + +# From https://web.archive.org/web/20131120040037/http://www.ripe.net/lir-services/resource-management/erx/transferred-resources +# From https://afrinic.net/fr/library/policies/220-erx-transfer +allow 2561 +allow 3208 +allow 5536 +allow 6127 +allow 6713 +allow 6879 +allow 8524 +allow 8770 +allow 9129 +allow 11380 +allow 12455 +allow 12556 +allow 13224 +allow 15399 +allow 13569 +allow 15475 +allow 15706 +allow 15804 +allow 15825 +allow 15834 +allow 15964 +allow 16058 +allow 16214 +allow 16284 +allow 16853 +allow 16907 +allow 17652 +allow 19676 +allow 20294 +allow 20484 +allow 20858 +allow 20928 +allow 21003 +allow 21152 +allow 21242 +allow 21271 +allow 21278 +allow 21280 +allow 21391 +allow 21452 +allow 23549 +allow 23889 +allow 24736 +allow 24757 +allow 24788 +allow 24801 +allow 24835 +allow 24863 +allow 24878 +allow 24987 +allow 25163 +allow 25250 +allow 25362 +allow 25364 +allow 25543 +allow 25568 +allow 25576 +allow 28683 +allow 28698 +allow 28913 +allow 29091 +allow 29338 +allow 29340 +allow 29428 +allow 29495 +allow 29544 +allow 29571 +allow 29614 +allow 29674 +allow 30896 +allow 31065 +allow 31245 +allow 31619 +allow 83.143.24.0 - 83.143.31.255 +allow 84.205.96.0 - 84.205.127.255 +allow 131.176.0.0 - 131.176.255.255 +allow 163.121.0.0 - 163.121.255.255 +allow 165.231.0.0 - 165.231.255.255 +allow 192.52.232.0 - 192.52.232.255 +allow 193.17.215.0 - 193.17.215.255 +allow 193.19.232.0 - 193.19.235.255 +allow 193.41.146.0 - 193.41.147.255 +allow 193.108.23.0 - 193.108.23.255 +allow 193.108.28.0 - 193.108.28.255 +allow 193.109.66.0 - 193.109.67.255 +allow 193.110.104.0 - 193.110.105.255 +allow 193.194.128.0 - 193.194.128.255 +allow 193.227.128.0 - 193.227.128.255 +allow 194.9.64.0 - 194.9.65.255 +allow 194.9.82.0 - 194.9.83.255 +allow 195.24.80.0 - 195.24.87.255 +allow 195.39.218.0 - 195.39.219.255 +allow 195.234.120.0 - 195.234.123.255 +allow 195.234.168.0 - 195.234.168.255 +allow 195.234.185.0 - 195.234.185.255 +allow 195.234.252.0 - 195.234.255.255 + +# From https://www.ripe.net/participate/internet-governance/internet-technical-community/the-rir-system/afrinic/ripe-ncc-to-afrinic-transition +allow 30980 +allow 30982 - 30999 + +# From https://afrinic.net/ast/pdf/afrinic-whois-audit-report-full-20210121.pdf +# 12.3 Appendix A3 +allow 193.188.7.0/24 +allow 193.189.0.0/18 +allow 193.189.128.0/24 +allow 193.194.160.0/19 +allow 193.221.218.0/24 + +# From https://ftp.arin.net/afrinic/afrinic-transfers-by-resource.txt +# Feb 21, 2005 +allow 1228 - 1232 +allow 2018 +allow 2905 +allow 3067 +allow 3068 +allow 3741 +allow 4178 +allow 4571 +allow 5713 +allow 5734 +allow 6083 +allow 6089 +allow 6149 +allow 6180 +allow 6187 +allow 6351 +allow 6529 +allow 6560 +allow 6968 +allow 7020 +allow 7154 +allow 7231 +allow 7390 +allow 7420 +allow 7460 +allow 7971 +allow 7972 +allow 8094 +allow 10247 +allow 10262 +allow 10331 +allow 10393 +allow 10474 +allow 10505 +allow 10540 +allow 10575 +allow 10798 +allow 10803 +allow 10898 +allow 10922 +allow 11125 +allow 11157 +allow 11201 +allow 11259 +allow 11265 +allow 11569 +allow 11645 +allow 11744 +allow 11845 +allow 11909 +allow 12091 +allow 12143 +allow 12258 +allow 13402 +allow 13519 +allow 13854 +allow 14029 +allow 14115 +allow 14331 +allow 14360 +allow 14429 +allow 14516 +allow 14988 +allow 15022 +allow 15159 +allow 16416 +allow 16547 +allow 16630 +allow 16637 +allow 16800 +allow 17148 +allow 17220 +allow 17260 +allow 17312 +allow 17400 +allow 18775 +allow 18922 +allow 18931 +allow 19136 +allow 19232 +allow 19711 +allow 19832 +allow 19847 +allow 20011 +allow 20086 +allow 20095 +allow 20180 +allow 20459 +allow 21739 +allow 21819 +allow 22354 +allow 22355 +allow 22386 +allow 22572 +allow 22690 +allow 22735 +allow 22750 +allow 22939 +allow 23058 +allow 25695 +allow 25726 +allow 25793 +allow 25818 +allow 26106 +allow 26130 +allow 26422 +allow 26625 +allow 26754 +allow 27576 +allow 27598 +allow 29918 +allow 29975 +allow 30073 +allow 30306 +allow 30429 +allow 30619 +allow 31810 +allow 31856 +allow 31960 +allow 32017 +allow 32279 +allow 32398 +allow 32437 +allow 32653 +allow 32714 +allow 32717 +allow 32842 +allow 32860 +allow 33567 +allow 33579 +allow 33762 - 33791 +allow 64.57.112.0 - 64.57.127.255 +allow 66.8.0.0 - 66.8.127.255 +allow 66.18.64.0 - 66.18.95.255 +allow 69.63.64.0 - 69.63.79.255 +allow 69.67.32.0 - 69.67.47.255 +allow 137.158.0.0 - 137.158.255.255 +allow 137.214.0.0 - 137.214.255.255 +allow 137.215.0.0 - 137.215.255.255 +allow 139.53.0.0 - 139.53.255.255 +allow 143.128.0.0 - 143.128.255.255 +allow 143.160.0.0 - 143.160.255.255 +allow 146.64.0.0 - 146.64.255.255 +allow 146.141.0.0 - 146.141.255.255 +allow 146.182.0.0 - 146.182.255.255 +allow 146.230.0.0 - 146.230.255.255 +allow 146.231.0.0 - 146.231.255.255 +allow 146.232.0.0 - 146.232.255.255 +allow 147.110.0.0 - 147.110.255.255 +allow 152.106.0.0 - 152.106.255.255 +allow 152.107.0.0 - 152.107.255.255 +allow 152.108.0.0 - 152.108.255.255 +allow 152.109.0.0 - 152.109.255.255 +allow 152.110.0.0 - 152.110.255.255 +allow 152.111.0.0 - 152.111.255.255 +allow 152.112.0.0 - 152.112.255.255 +allow 155.159.0.0 - 155.159.255.255 +allow 155.232.0.0 - 155.232.255.255 +allow 155.233.0.0 - 155.233.255.255 +allow 155.234.0.0 - 155.234.255.255 +allow 155.235.0.0 - 155.235.255.255 +allow 155.236.0.0 - 155.236.255.255 +allow 155.237.0.0 - 155.237.255.255 +allow 155.238.0.0 - 155.238.255.255 +allow 155.239.0.0 - 155.239.255.255 +allow 155.240.0.0 - 155.240.255.255 +allow 156.8.0.0 - 156.8.255.255 +allow 160.115.0.0 - 160.115.255.255 +allow 160.116.0.0 - 160.116.255.255 +allow 160.117.0.0 - 160.117.255.255 +allow 160.118.0.0 - 160.118.255.255 +allow 160.119.0.0 - 160.119.255.255 +allow 160.120.0.0 - 160.120.255.255 +allow 160.121.0.0 - 160.121.255.255 +allow 160.122.0.0 - 160.122.255.255 +allow 160.123.0.0 - 160.123.255.255 +allow 160.124.0.0 - 160.124.255.255 +allow 163.195.0.0 - 163.195.255.255 +allow 163.196.0.0 - 163.196.255.255 +allow 163.197.0.0 - 163.197.255.255 +allow 163.198.0.0 - 163.198.255.255 +allow 163.199.0.0 - 163.199.255.255 +allow 163.200.0.0 - 163.200.255.255 +allow 163.201.0.0 - 163.201.255.255 +allow 163.202.0.0 - 163.202.255.255 +allow 163.203.0.0 - 163.203.255.255 +allow 164.88.0.0 - 164.88.255.255 +allow 164.146.0.0 - 164.151.255.255 +allow 164.155.0.0 - 164.155.255.255 +allow 165.3.0.0 - 165.5.255.255 +allow 165.8.0.0 - 165.11.255.255 +allow 165.25.0.0 - 165.25.255.255 +allow 165.143.0.0 - 165.149.255.255 +allow 165.165.0.0 - 165.165.255.255 +allow 165.180.0.0 - 165.180.255.255 +allow 165.233.0.0 - 165.233.255.255 +allow 166.85.0.0 - 166.85.255.255 +allow 168.76.0.0 - 168.76.255.255 +allow 168.80.0.0 - 168.81.255.255 +allow 168.89.0.0 - 168.89.255.255 +allow 168.128.0.0 - 168.128.255.255 +allow 168.142.0.0 - 168.142.255.255 +allow 168.155.0.0 - 168.155.255.255 +allow 168.164.0.0 - 168.164.255.255 +allow 168.167.0.0 - 168.167.255.255 +allow 168.172.0.0 - 168.172.255.255 +allow 168.206.0.0 - 168.206.255.255 +allow 168.209.0.0 - 168.210.255.255 +allow 169.129.0.0 - 169.129.255.255 +allow 169.202.0.0 - 169.202.255.255 +allow 192.33.10.0 - 192.33.10.255 +allow 192.42.99.0 - 192.42.99.255 +allow 192.48.253.0 - 192.48.253.255 +allow 192.68.138.0 - 192.68.138.255 +allow 192.70.237.0 - 192.70.237.255 +allow 192.82.142.0 - 192.82.142.255 +allow 192.84.244.0 - 192.84.244.255 +allow 192.94.61.0 - 192.94.61.255 +allow 192.94.210.0 - 192.94.210.255 +allow 192.94.240.0 - 192.94.240.255 +allow 192.94.241.0 - 192.94.241.255 +allow 192.94.246.0 - 192.94.246.255 +allow 192.96.0.0 - 192.96.255.255 +allow 192.100.1.0 - 192.100.1.255 +allow 192.101.142.0 - 192.101.142.255 +allow 192.102.9.0 - 192.102.9.255 +allow 192.133.250.0 - 192.133.250.255 +allow 192.136.55.0 - 192.136.55.255 +allow 192.136.56.0 - 192.136.56.255 +allow 192.136.57.0 - 192.136.57.255 +allow 192.157.190.0 - 192.157.190.255 +allow 192.188.164.0 - 192.188.167.255 +allow 192.189.75.0 - 192.189.75.255 +allow 192.189.139.0 - 192.189.140.255 +allow 192.231.237.0 - 192.231.237.255 +allow 192.231.254.0 - 192.231.254.255 +allow 192.245.148.0 - 192.245.148.255 +allow 192.251.202.0 - 192.251.202.255 +allow 198.54.0.0 - 198.54.255.255 +allow 200.16.8.0 - 200.16.15.255 +allow 204.12.128.0 - 204.12.143.255 +allow 204.87.179.0 - 204.87.179.255 +allow 204.152.14.0 - 204.152.15.255 +allow 204.235.32.0 - 204.235.43.255 +allow 205.159.79.0 - 205.159.79.255 +allow 206.223.136.0 - 206.223.136.255 +allow 209.203.0.0 - 209.203.63.255 +allow 209.212.96.0 - 209.212.127.255 +allow 216.236.176.0 - 216.236.191.255 + +# From rpki.afrinic.net/repository/04E8B0D80F4D11E0B657D8931367AE7D/apnic-to-afrinic.cer +# CN=APNICTOAFRINIC/serialNumber=6F1A103E1427FF03483ABFD9E34DACBE1524FF8B +# Not Before: Mar 30 14:17:08 2020 GMT / Not After : Mar 30 00:00:00 2025 GMT +# SHA256:B6w5P1mkoNyJtM99GfGLaaKkGfSkQ6+4eC4tPijBLyM= +allow 202.123.0.0/19 + +# From rpki.afrinic.net/repository/04E8B0D80F4D11E0B657D8931367AE7D/ripe-to-afrinic.cer +# CN=RIPETOAFRINIC/serialNumber=7F7AC180897983E29E937C0A187803C072755545 +# Not Before: Mar 30 14:17:12 2020 GMT / Not After : Mar 30 00:00:00 2025 GMT +# SHA256:64eh2w7qQrFQVPaQrRJ4kA83gUgE3EDvm0D0AWHCXHM= +allow 62.8.64.0/19 +allow 62.12.96.0/19 +allow 62.24.96.0/19 +allow 62.61.192.0/18 +allow 62.68.32.0/19 +allow 62.68.224.0/19 +allow 62.114.0.0/16 +allow 62.117.32.0/19 +allow 62.135.0.0/17 +allow 62.139.0.0/16 +allow 62.140.64.0/18 +allow 62.173.32.0/19 +allow 62.193.64.0/18 +allow 62.193.160.0/19 +allow 62.240.32.0/19 +allow 62.240.96.0/19 +allow 62.241.128.0/19 +allow 62.251.128.0/17 +allow 77.220.0.0/19 +allow 80.67.128.0/20 +allow 80.72.96.0/20 +allow 80.75.160.0/19 +allow 80.87.64.0/19 +allow 80.88.0.0/20 +allow 80.95.0.0/20 +allow 80.240.192.0/20 +allow 80.246.0.0/20 +allow 80.248.0.0/20 +allow 80.248.64.0/20 +allow 80.249.64.0/20 +allow 80.250.32.0/20 +allow 81.4.0.0/18 +allow 81.10.0.0/17 +allow 81.21.96.0/20 +allow 81.22.64.0/19 +allow 81.26.64.0/20 +allow 81.29.96.0/20 +allow 81.91.224.0/20 +allow 81.192.0.0/16 +allow 82.101.128.0/18 +allow 82.128.0.0/17 +allow 82.129.128.0/17 +allow 82.151.64.0/19 +allow 82.201.128.0/17 +allow 84.36.0.0/16 +allow 84.233.0.0/17 +allow 87.255.96.0/19 +allow 193.95.0.0/17 +allow 193.108.214.0/24 +allow 193.108.252.0/22 +allow 193.189.64.0 - 193.189.65.255 +allow 193.194.1.0 - 193.194.5.255 +allow 193.194.32.0 - 193.194.95.255 +allow 193.227.0.0/18 +allow 194.6.224.0/24 +allow 194.79.96.0/19 +allow 194.204.192.0/18 +allow 195.24.192.0/19 +allow 195.43.0.0/19 +allow 195.166.224.0/19 +allow 195.202.64.0/19 +allow 195.246.32.0/19 +allow 212.0.128.0/19 +allow 212.12.224.0/19 +allow 212.22.160.0/19 +allow 212.49.64.0/19 +allow 212.52.128.0/19 +allow 212.60.64.0/19 +allow 212.85.192.0/19 +allow 212.88.96.0/19 +allow 212.96.0.0/19 +allow 212.100.64.0/19 +allow 212.103.160.0/19 +allow 212.122.224.0/19 +allow 212.217.0.0/17 +allow 213.55.64.0/18 +allow 213.131.64.0/19 +allow 213.136.96.0/19 +allow 213.147.64.0/19 +allow 213.150.96.0/19 +allow 213.150.160.0 - 213.150.223.255 +allow 213.152.64.0/19 +allow 213.154.32.0 - 213.154.95.255 +allow 213.158.160.0/19 +allow 213.172.128.0/19 +allow 213.179.160.0/19 +allow 213.181.224.0/19 +allow 213.193.32.0/19 +allow 213.212.192.0/18 +allow 213.247.0.0/19 +allow 213.255.128.0/19 +allow 217.14.80.0/20 +allow 217.20.224.0/20 +allow 217.21.112.0/20 +allow 217.29.128.0/20 +allow 217.29.208.0/20 +allow 217.52.0.0/14 +allow 217.64.96.0/20 +allow 217.77.64.0/20 +allow 217.78.64.0/20 +allow 217.117.0.0/20 +allow 217.139.0.0/16 +allow 217.170.144.0/20 +allow 217.199.144.0/20 + +# From rpki.afrinic.net/repository/04E8B0D80F4D11E0B657D8931367AE7D/arin-to-afrinic.cer +# CN=ARINTOAFRINIC/serialNumber=B87C5A75F3D957413AB998646946D4541D511455 +# Not Before: Mar 30 14:17:09 2020 GMT / Not After : Mar 30 00:00:00 2025 GMT +# SHA256:wmJV3qcwiPcLtEMLBcvvyjs4V1Lz690bK3b8cv5v8F8= +allow 129.0.0.0/16 +allow 129.18.0.0/16 +allow 129.45.0.0/16 +allow 129.56.0.0/16 +allow 129.122.0.0/16 +allow 129.140.0.0/16 +allow 129.205.0.0/16 +allow 129.232.0.0/16 +allow 137.63.0.0 - 137.64.255.255 +allow 137.115.0.0/16 +allow 137.171.0.0/16 +allow 137.196.0.0/16 +allow 137.255.0.0/16 +allow 155.0.0.0/16 +allow 155.11.0.0 - 155.12.255.255 +allow 155.89.0.0/16 +allow 155.93.0.0/16 +allow 155.196.0.0/16 +allow 155.251.0.0/16 +allow 155.255.0.0 - 156.0.255.255 +allow 156.38.0.0/16 +allow 156.155.0.0 - 156.255.255.255 +allow 160.0.0.0/16 +allow 160.77.0.0/16 +allow 160.89.0.0 - 160.90.255.255 +allow 160.105.0.0/16 +allow 160.113.0.0/16 +allow 160.152.0.0/16 +allow 160.154.0.0 - 160.179.255.255 +allow 160.181.0.0 - 160.184.255.255 +allow 160.224.0.0 - 160.226.255.255 +allow 160.242.0.0/16 +allow 160.255.0.0/16 +allow 165.0.0.0/16 +allow 165.16.0.0/16 +allow 165.49.0.0 - 165.63.255.255 +allow 165.73.0.0/16 +allow 165.90.0.0/16 +allow 165.169.0.0/16 +allow 165.210.0.0/15 +allow 165.255.0.0/16 +allow 168.211.0.0 - 168.211.255.255 +allow 168.253.0.0/16 +allow 169.0.0.0/15 +allow 169.159.0.0/16 +allow 169.239.0.0/16 +allow 169.255.0.0/16 +allow 192.109.242.0/24 Index: etc/rpki/apnic.constraints =================================================================== RCS file: etc/rpki/apnic.constraints diff -N etc/rpki/apnic.constraints --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ etc/rpki/apnic.constraints 26 Sep 2023 14:27:45 -0000 @@ -0,0 +1,98 @@ +# From https://www.iana.org/assignments/ipv6-unicast-address-assignments +# ARIN IPv6 resources should not appear subordinate to non-ARIN TAs +deny 2001:400::/23 +deny 2001:1800::/23 +deny 2001:4800::/23 +deny 2600::/12 +deny 2610::/23 +deny 2620::/23 +deny 2630::/12 + +# AFRINIC Internet Number Resources cannot be transferred +# From https://www.iana.org/assignments/ipv4-address-space/ +deny 41.0.0.0/8 +deny 102.0.0.0/8 +deny 105.0.0.0/8 +# Holes due to historical reasons +deny 154.0.0.0 - 154.4.255.255 +# hole for 154.5.0.0/16 +deny 154.6.0.0 - 154.8.47.255 +# hole for 154.8.48.0 - 154.8.255.255 +deny 154.9.0.0/16 +# hole for 154.10.0.0/15 +deny 154.12.0.0 - 154.19.255.255 +# hole for 154.20.0.0/16 +deny 154.21.0.0 - 154.32.255.255 +# hole for 154.33.0.0 - 154.34.255.255 +deny 154.35.0.0 - 154.255.255.255 +deny 196.0.0.0/16 +deny 196.1.0.0/24 +# hole for 196.1.1.0/24 +deny 196.1.2.0 - 196.1.67.255 +# hole for 196.1.68.0/24 +deny 196.1.69.0 - 196.1.103.255 +# hole for 196.1.104.0 - 196.1.106.255 +deny 196.1.107.0/24 +# hole for 196.1.108.0/22 +deny 196.1.112.0/24 +# hole for 196.1.113.0 - 196.1.114.255 +deny 196.1.115.0 - 196.1.133.255 +# hole for 196.1.134.0/24 +deny 196.1.135.0 - 196.3.64.255 +# hole for 196.3.65.0/24 +deny 196.3.66.0 - 196.3.71.255 +# hole for 196.3.72.0/24 +deny 196.3.73.0 - 196.12.31.255 +# hole for 196.12.32.0/19 +deny 196.12.64.0 - 196.15.15.255 +# hole for 196.15.16.0/20 +deny 196.15.32.0 - 196.29.63.255 +# hole for 196.29.64.0/19 +deny 196.29.96.0 - 196.32.31.255 +# hole for 196.32.32.0/19 +# hole for 196.32.64.0/19 +deny 196.32.96.0 - 196.39.255.255 +# hole for 196.40.0.0 - 196.40.95.255 +deny 196.40.96.0 - 197.255.255.254 + +# From https://www.iana.org/assignments/ipv6-address-space/ +deny 2001:4200::/23 +deny 2c00::/12 +# From https://www.iana.org/assignments/as-numbers/ +deny 36864 - 37887 +deny 327680 - 328703 +deny 328704 - 329727 + +# Private use IPv4 & IPv6 addresses and ASNs +deny 0.0.0.0/8 # RFC 1122 Local Identification +deny 10.0.0.0/8 # RFC 1918 private space +deny 100.64.0.0/10 # RFC 6598 Carrier Grade NAT +deny 127.0.0.0/8 # RFC 1122 localhost +deny 169.254.0.0/16 # RFC 3927 link local +deny 172.16.0.0/12 # RFC 1918 private space +deny 192.0.2.0/24 # RFC 5737 TEST-NET-1 +deny 192.88.99.0/24 # RFC 7526 6to4 anycast relay +deny 192.168.0.0/16 # RFC 1918 private space +deny 198.18.0.0/15 # RFC 2544 benchmarking +deny 198.51.100.0/24 # RFC 5737 TEST-NET-2 +deny 203.0.113.0/24 # RFC 5737 TEST-NET-3 +deny 224.0.0.0/4 # Multicast +deny 240.0.0.0/4 # Reserved +deny 2001:2::/48 # RFC 5180 BMWG +deny 2001:10::/28 # RFC 4843 ORCHID +deny 2001:db8::/32 # RFC 3849 Documentation +deny 2002::/16 # RFC 7526 6to4 anycast relay +deny 3ffe::/16 # Deprecated 6bone +deny 23456 # RFC 4893 AS_TRANS +deny 64496 - 64511 # RFC 5398 +deny 64512 - 65534 # RFC 6996 +deny 65535 # RFC 7300 +deny 65536 - 65551 # RFC 5398 +deny 65552 - 131071 # IANA Reserved +deny 4200000000 - 4294967294 # RFC 6996 +deny 4294967295 # RFC 7300 + +# Allow the complement of what is denied +allow 0.0.0.0/0 +allow 2000::/3 +allow 1 - 4199999999 Index: etc/rpki/arin.constraints =================================================================== RCS file: etc/rpki/arin.constraints diff -N etc/rpki/arin.constraints --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ etc/rpki/arin.constraints 26 Sep 2023 14:27:45 -0000 @@ -0,0 +1,95 @@ +# From https://www.iana.org/assignments/ipv6-unicast-address-assignments +# For IPv6, nothing other than ARIN's own IPv6 blocks are permitted. +allow 2001:400::/23 +allow 2001:1800::/23 +allow 2001:4800::/23 +allow 2600::/12 +allow 2610::/23 +allow 2620::/23 +allow 2630::/12 + +# AFRINIC Internet Number Resources cannot be transferred +# From https://www.iana.org/assignments/ipv4-address-space/ +deny 41.0.0.0/8 +deny 102.0.0.0/8 +deny 105.0.0.0/8 + +# Holes due to historical reasons +deny 154.0.0.0 - 154.4.255.255 +# hole for 154.5.0.0/16 +deny 154.6.0.0 - 154.8.47.255 +# hole for 154.8.48.0 - 154.8.255.255 +deny 154.9.0.0/16 +# hole for 154.10.0.0/15 +deny 154.12.0.0 - 154.19.255.255 +# hole for 154.20.0.0/16 +deny 154.21.0.0 - 154.32.255.255 +# hole for 154.33.0.0 - 154.34.255.255 +deny 154.35.0.0 - 154.255.255.255 +deny 196.0.0.0/16 +deny 196.1.0.0/24 +# hole for 196.1.1.0/24 +deny 196.1.2.0 - 196.1.67.255 +# hole for 196.1.68.0/24 +deny 196.1.69.0 - 196.1.103.255 +# hole for 196.1.104.0 - 196.1.106.255 +deny 196.1.107.0/24 +# hole for 196.1.108.0/22 +deny 196.1.112.0/24 +# hole for 196.1.113.0 - 196.1.114.255 +deny 196.1.115.0 - 196.1.133.255 +# hole for 196.1.134.0/24 +deny 196.1.135.0 - 196.3.64.255 +# hole for 196.3.65.0/24 +deny 196.3.66.0 - 196.3.71.255 +# hole for 196.3.72.0/24 +deny 196.3.73.0 - 196.12.31.255 +# hole for 196.12.32.0/19 +deny 196.12.64.0 - 196.15.15.255 +# hole for 196.15.16.0/20 +deny 196.15.32.0 - 196.29.63.255 +# hole for 196.29.64.0/19 +deny 196.29.96.0 - 196.32.31.255 +# hole for 196.32.32.0/19 +# hole for 196.32.64.0/19 +deny 196.32.96.0 - 196.39.255.255 +# hole for 196.40.0.0 - 196.40.95.255 +deny 196.40.96.0 - 197.255.255.254 + +# From https://www.iana.org/assignments/as-numbers/ +deny 36864 - 37887 +deny 327680 - 328703 +deny 328704 - 329727 + +# Private use IPv4 & IPv6 addresses and ASNs +deny 0.0.0.0/8 # RFC 1122 Local Identification +deny 10.0.0.0/8 # RFC 1918 private space +deny 100.64.0.0/10 # RFC 6598 Carrier Grade NAT +deny 127.0.0.0/8 # RFC 1122 localhost +deny 169.254.0.0/16 # RFC 3927 link local +deny 172.16.0.0/12 # RFC 1918 private space +deny 192.0.2.0/24 # RFC 5737 TEST-NET-1 +deny 192.88.99.0/24 # RFC 7526 6to4 anycast relay +deny 192.168.0.0/16 # RFC 1918 private space +deny 198.18.0.0/15 # RFC 2544 benchmarking +deny 198.51.100.0/24 # RFC 5737 TEST-NET-2 +deny 203.0.113.0/24 # RFC 5737 TEST-NET-3 +deny 224.0.0.0/4 # Multicast +deny 240.0.0.0/4 # Reserved +deny 2001:2::/48 # RFC 5180 BMWG +deny 2001:10::/28 # RFC 4843 ORCHID +deny 2001:db8::/32 # RFC 3849 Documentation +deny 2002::/16 # RFC 7526 6to4 anycast relay +deny 3ffe::/16 # Deprecated 6bone +deny 23456 # RFC 4893 AS_TRANS +deny 64496 - 64511 # RFC 5398 +deny 64512 - 65534 # RFC 6996 +deny 65535 # RFC 7300 +deny 65536 - 65551 # RFC 5398 +deny 65552 - 131071 # IANA Reserved +deny 4200000000 - 4294967294 # RFC 6996 +deny 4294967295 # RFC 7300 + +# Allow the complement of what is denied +allow 0.0.0.0/0 +allow 1 - 4199999999 Index: etc/rpki/lacnic.constraints =================================================================== RCS file: etc/rpki/lacnic.constraints diff -N etc/rpki/lacnic.constraints --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ etc/rpki/lacnic.constraints 26 Sep 2023 14:27:45 -0000 @@ -0,0 +1,99 @@ +# From https://www.iana.org/assignments/ipv6-unicast-address-assignments +# ARIN IPv6 resources should not appear subordinate to non-ARIN TAs +deny 2001:400::/23 +deny 2001:1800::/23 +deny 2001:4800::/23 +deny 2600::/12 +deny 2610::/23 +deny 2620::/23 +deny 2630::/12 + +# AFRINIC Internet Number Resources cannot be transferred +# From https://www.iana.org/assignments/ipv4-address-space/ +deny 41.0.0.0/8 +deny 102.0.0.0/8 +deny 105.0.0.0/8 +# Holes due to historical reasons +deny 154.0.0.0 - 154.4.255.255 +# hole for 154.5.0.0/16 +deny 154.6.0.0 - 154.8.47.255 +# hole for 154.8.48.0 - 154.8.255.255 +deny 154.9.0.0/16 +# hole for 154.10.0.0/15 +deny 154.12.0.0 - 154.19.255.255 +# hole for 154.20.0.0/16 +deny 154.21.0.0 - 154.32.255.255 +# hole for 154.33.0.0 - 154.34.255.255 +deny 154.35.0.0 - 154.255.255.255 +deny 196.0.0.0/16 +deny 196.1.0.0/24 +# hole for 196.1.1.0/24 +deny 196.1.2.0 - 196.1.67.255 +# hole for 196.1.68.0/24 +deny 196.1.69.0 - 196.1.103.255 +# hole for 196.1.104.0 - 196.1.106.255 +deny 196.1.107.0/24 +# hole for 196.1.108.0/22 +deny 196.1.112.0/24 +# hole for 196.1.113.0 - 196.1.114.255 +deny 196.1.115.0 - 196.1.133.255 +# hole for 196.1.134.0/24 +deny 196.1.135.0 - 196.3.64.255 +# hole for 196.3.65.0/24 +deny 196.3.66.0 - 196.3.71.255 +# hole for 196.3.72.0/24 +deny 196.3.73.0 - 196.12.31.255 +# hole for 196.12.32.0/19 +deny 196.12.64.0 - 196.15.15.255 +# hole for 196.15.16.0/20 +deny 196.15.32.0 - 196.29.63.255 +# hole for 196.29.64.0/19 +deny 196.29.96.0 - 196.32.31.255 +# hole for 196.32.32.0/19 +# hole for 196.32.64.0/19 +deny 196.32.96.0 - 196.39.255.255 +# hole for 196.40.0.0 - 196.40.95.255 +deny 196.40.96.0 - 197.255.255.254 + +# From https://www.iana.org/assignments/ipv6-address-space/ +deny 2001:4200::/23 +deny 2c00::/12 + +# From https://www.iana.org/assignments/as-numbers/ +deny 36864 - 37887 +deny 327680 - 328703 +deny 328704 - 329727 + +# Private use IPv4 & IPv6 addresses and ASNs +deny 0.0.0.0/8 # RFC 1122 Local Identification +deny 10.0.0.0/8 # RFC 1918 private space +deny 100.64.0.0/10 # RFC 6598 Carrier Grade NAT +deny 127.0.0.0/8 # RFC 1122 localhost +deny 169.254.0.0/16 # RFC 3927 link local +deny 172.16.0.0/12 # RFC 1918 private space +deny 192.0.2.0/24 # RFC 5737 TEST-NET-1 +deny 192.88.99.0/24 # RFC 7526 6to4 anycast relay +deny 192.168.0.0/16 # RFC 1918 private space +deny 198.18.0.0/15 # RFC 2544 benchmarking +deny 198.51.100.0/24 # RFC 5737 TEST-NET-2 +deny 203.0.113.0/24 # RFC 5737 TEST-NET-3 +deny 224.0.0.0/4 # Multicast +deny 240.0.0.0/4 # Reserved +deny 2001:2::/48 # RFC 5180 BMWG +deny 2001:10::/28 # RFC 4843 ORCHID +deny 2001:db8::/32 # RFC 3849 Documentation +deny 2002::/16 # RFC 7526 6to4 anycast relay +deny 3ffe::/16 # Deprecated 6bone +deny 23456 # RFC 4893 AS_TRANS +deny 64496 - 64511 # RFC 5398 +deny 64512 - 65534 # RFC 6996 +deny 65535 # RFC 7300 +deny 65536 - 65551 # RFC 5398 +deny 65552 - 131071 # IANA Reserved +deny 4200000000 - 4294967294 # RFC 6996 +deny 4294967295 # RFC 7300 + +# Allow the complement of what is denied +allow 0.0.0.0/0 +allow 2000::/3 +allow 1 - 4199999999 Index: etc/rpki/ripe.constraints =================================================================== RCS file: etc/rpki/ripe.constraints diff -N etc/rpki/ripe.constraints --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ etc/rpki/ripe.constraints 26 Sep 2023 14:27:45 -0000 @@ -0,0 +1,99 @@ +# From https://www.iana.org/assignments/ipv6-unicast-address-assignments +# ARIN IPv6 resources should not appear subordinate to non-ARIN TAs +deny 2001:400::/23 +deny 2001:1800::/23 +deny 2001:4800::/23 +deny 2600::/12 +deny 2610::/23 +deny 2620::/23 +deny 2630::/12 + +# AFRINIC Internet Number Resources cannot be transferred +# From https://www.iana.org/assignments/ipv4-address-space/ +deny 41.0.0.0/8 +deny 102.0.0.0/8 +deny 105.0.0.0/8 +# Holes due to historical reasons +deny 154.0.0.0 - 154.4.255.255 +# hole for 154.5.0.0/16 +deny 154.6.0.0 - 154.8.47.255 +# hole for 154.8.48.0 - 154.8.255.255 +deny 154.9.0.0/16 +# hole for 154.10.0.0/15 +deny 154.12.0.0 - 154.19.255.255 +# hole for 154.20.0.0/16 +deny 154.21.0.0 - 154.32.255.255 +# hole for 154.33.0.0 - 154.34.255.255 +deny 154.35.0.0 - 154.255.255.255 +deny 196.0.0.0/16 +deny 196.1.0.0/24 +# hole for 196.1.1.0/24 +deny 196.1.2.0 - 196.1.67.255 +# hole for 196.1.68.0/24 +deny 196.1.69.0 - 196.1.103.255 +# hole for 196.1.104.0 - 196.1.106.255 +deny 196.1.107.0/24 +# hole for 196.1.108.0/22 +deny 196.1.112.0/24 +# hole for 196.1.113.0 - 196.1.114.255 +deny 196.1.115.0 - 196.1.133.255 +# hole for 196.1.134.0/24 +deny 196.1.135.0 - 196.3.64.255 +# hole for 196.3.65.0/24 +deny 196.3.66.0 - 196.3.71.255 +# hole for 196.3.72.0/24 +deny 196.3.73.0 - 196.12.31.255 +# hole for 196.12.32.0/19 +deny 196.12.64.0 - 196.15.15.255 +# hole for 196.15.16.0/20 +deny 196.15.32.0 - 196.29.63.255 +# hole for 196.29.64.0/19 +deny 196.29.96.0 - 196.32.31.255 +# hole for 196.32.32.0/19 +# hole for 196.32.64.0/19 +deny 196.32.96.0 - 196.39.255.255 +# hole for 196.40.0.0 - 196.40.95.255 +deny 196.40.96.0 - 197.255.255.254 + +# From https://www.iana.org/assignments/ipv6-address-space/ +deny 2001:4200::/23 +deny 2c00::/12 + +# From https://www.iana.org/assignments/as-numbers/ +deny 36864 - 37887 +deny 327680 - 328703 +deny 328704 - 329727 + +# Private use IPv4 & IPv6 addresses and ASNs +deny 0.0.0.0/8 # RFC 1122 Local Identification +deny 10.0.0.0/8 # RFC 1918 private space +deny 100.64.0.0/10 # RFC 6598 Carrier Grade NAT +deny 127.0.0.0/8 # RFC 1122 localhost +deny 169.254.0.0/16 # RFC 3927 link local +deny 172.16.0.0/12 # RFC 1918 private space +deny 192.0.2.0/24 # RFC 5737 TEST-NET-1 +deny 192.88.99.0/24 # RFC 7526 6to4 anycast relay +deny 192.168.0.0/16 # RFC 1918 private space +deny 198.18.0.0/15 # RFC 2544 benchmarking +deny 198.51.100.0/24 # RFC 5737 TEST-NET-2 +deny 203.0.113.0/24 # RFC 5737 TEST-NET-3 +deny 224.0.0.0/4 # Multicast +deny 240.0.0.0/4 # Reserved +deny 2001:2::/48 # RFC 5180 BMWG +deny 2001:10::/28 # RFC 4843 ORCHID +deny 2001:db8::/32 # RFC 3849 Documentation +deny 2002::/16 # RFC 7526 6to4 anycast relay +deny 3ffe::/16 # Deprecated 6bone +deny 23456 # RFC 4893 AS_TRANS +deny 64496 - 64511 # RFC 5398 +deny 64512 - 65534 # RFC 6996 +deny 65535 # RFC 7300 +deny 65536 - 65551 # RFC 5398 +deny 65552 - 131071 # IANA Reserved +deny 4200000000 - 4294967294 # RFC 6996 +deny 4294967295 # RFC 7300 + +# Allow the complement of what is denied +allow 0.0.0.0/0 +allow 2000::/3 +allow 1 - 4199999999 Index: usr.sbin/rpki-client/as.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/as.c,v retrieving revision 1.12 diff -u -p -r1.12 as.c --- usr.sbin/rpki-client/as.c 23 May 2023 06:39:31 -0000 1.12 +++ usr.sbin/rpki-client/as.c 26 Sep 2023 14:27:45 -0000 @@ -135,3 +135,23 @@ as_check_covered(uint32_t min, uint32_t return -1; } + +void +as_warn(const char *fn, const struct cert_as *cert, const char *msg) +{ + switch (cert->type) { + case CERT_AS_ID: + warnx("%s: AS %u: %s", fn, cert->id, msg); + break; + case CERT_AS_INHERIT: + warnx("%s: AS (inherit): %s", fn, msg); + break; + case CERT_AS_RANGE: + warnx("%s: AS range %u--%u: %s", fn, cert->range.min, + cert->range.max, msg); + break; + default: + warnx("%s: corrupt cert", fn); + break; + } +} Index: usr.sbin/rpki-client/aspa.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/aspa.c,v retrieving revision 1.23 diff -u -p -r1.23 aspa.c --- usr.sbin/rpki-client/aspa.c 25 Sep 2023 11:08:45 -0000 1.23 +++ usr.sbin/rpki-client/aspa.c 26 Sep 2023 14:27:45 -0000 @@ -215,7 +215,7 @@ aspa_parse(X509 **x509, const char *fn, if (!aspa_parse_econtent(cms, cmsz, &p)) goto out; - if ((cert = cert_parse_ee_cert(fn, *x509)) == NULL) + if ((cert = cert_parse_ee_cert(fn, talid, *x509)) == NULL) goto out; p.res->valid = valid_aspa(fn, cert, p.res); Index: usr.sbin/rpki-client/cert.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v retrieving revision 1.117 diff -u -p -r1.117 cert.c --- usr.sbin/rpki-client/cert.c 25 Sep 2023 15:33:08 -0000 1.117 +++ usr.sbin/rpki-client/cert.c 26 Sep 2023 14:27:45 -0000 @@ -446,8 +446,8 @@ sbgp_parse_ipaddrblk(const char *fn, con static int sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext) { - STACK_OF(IPAddressFamily) *addrblk = NULL; - int rc = 0; + IPAddrBlocks *addrblk = NULL; + int rc = 0; if (!X509_EXTENSION_get_critical(ext)) { warnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: " @@ -471,7 +471,7 @@ sbgp_ipaddrblk(struct parse *p, X509_EXT rc = 1; out: - sk_IPAddressFamily_pop_free(addrblk, IPAddressFamily_free); + IPAddrBlocks_free(addrblk); return rc; } @@ -641,7 +641,7 @@ certificate_policies(struct parse *p, X5 * Returns cert on success and NULL on failure. */ struct cert * -cert_parse_ee_cert(const char *fn, X509 *x) +cert_parse_ee_cert(const char *fn, int talid, X509 *x) { struct parse p; X509_EXTENSION *ext; @@ -690,6 +690,11 @@ cert_parse_ee_cert(const char *fn, X509 } p.res->x509 = x; + p.res->talid = talid; + + if (!constraints_validate(fn, p.res)) + goto out; + return p.res; out: Index: usr.sbin/rpki-client/constraints.c =================================================================== RCS file: usr.sbin/rpki-client/constraints.c diff -N usr.sbin/rpki-client/constraints.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ usr.sbin/rpki-client/constraints.c 26 Sep 2023 14:27:46 -0000 @@ -0,0 +1,584 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2023 Job Snijders <j...@openbsd.org> + * Copyright (c) 2023 Theo Buehler <t...@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/socket.h> + +#include <arpa/inet.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <openssl/asn1.h> +#include <openssl/x509v3.h> + +#include "extern.h" + +struct tal_constraints { + int fd; /* constraints file descriptor or -1. */ + char *fn; /* constraints filename */ + struct cert_ip *allow_ips; /* list of allowed IP address ranges */ + size_t allow_ipsz; /* length of "allow_ips" */ + struct cert_as *allow_as; /* allowed AS numbers and ranges */ + size_t allow_asz; /* length of "allow_as" */ + struct cert_ip *deny_ips; /* forbidden IP address ranges */ + size_t deny_ipsz; /* length of "deny_ips" */ + struct cert_as *deny_as; /* forbidden AS numbers and ranges */ + size_t deny_asz; /* length of "deny_as" */ +} tal_constraints[TALSZ_MAX]; + +/* + * If there is a .constraints file next to a .tal file, load its contents + * into into tal_constraints[talid]. The load function only opens the fd + * and stores the filename. The actual parsing happens in constraints_parse(). + * Resources of EE certs can then be constrained using constraints_validate(). + */ + +static void +constraints_load_talid(int talid) +{ + const char *tal = tals[talid]; + char *constraints = NULL; + int fd; + size_t len; + int saved_errno; + + tal_constraints[talid].fd = -1; + + if (rtype_from_file_extension(tal) != RTYPE_TAL) + return; + + /* Replace .tal suffix with .constraints. */ + len = strlen(tal) - 4; + if (asprintf(&constraints, "%.*s.constraints", (int)len, tal) == -1) + errx(1, NULL); + + saved_errno = errno; + + fd = open(constraints, O_RDONLY); + if (fd == -1 && errno != ENOENT) + err(1, "failed to load constraints for %s", tal); + + tal_constraints[talid].fn = constraints; + tal_constraints[talid].fd = fd; + + errno = saved_errno; +} + +/* + * Iterate over all TALs and load the corresponding constraints files. + */ +void +constraints_load(void) +{ + int talid; + + for (talid = 0; talid < talsz; talid++) + constraints_load_talid(talid); +} + +void +constraints_unload(void) +{ + int saved_errno, talid; + + saved_errno = errno; + for (talid = 0; talid < talsz; talid++) { + if (tal_constraints[talid].fd != -1) + close(tal_constraints[talid].fd); + free(tal_constraints[talid].fn); + tal_constraints[talid].fd = -1; + tal_constraints[talid].fn = NULL; + } + errno = saved_errno; +} + +/* + * Split a string at '-' and trim whitespace around the '-'. + * Assumes leading and trailing whitespace in p has already been trimmed. + */ +static int +constraints_split_range(char *p, const char **min, const char **max) +{ + char *pp; + + *min = p; + if ((*max = pp = strchr(p, '-')) == NULL) + return 0; + + /* Trim whitespace before '-'. */ + while (pp > *min && isspace((unsigned char)pp[-1])) + pp--; + *pp = '\0'; + + /* Skip past '-' and whitespace following it. */ + (*max)++; + while (isspace((unsigned char)**max)) + (*max)++; + + return 1; +} + +/* + * Helper functions to parse textual representations of IP prefixes or ranges. + * The RFC 3779 API has poor error reporting, so as a debugging aid, we call + * the prohibitively expensive X509v3_addr_canonize() in high verbosity mode. + */ + +static void +constraints_parse_ip_prefix(const char *fn, const char *prefix, enum afi afi, + IPAddrBlocks *addrs) +{ + unsigned char addr[16] = { 0 }; + int af = afi == AFI_IPV4 ? AF_INET : AF_INET6; + int plen; + + if ((plen = inet_net_pton(af, prefix, addr, sizeof(addr))) == -1) + errx(1, "%s: failed to parse %s", fn, prefix); + + if (!X509v3_addr_add_prefix(addrs, afi, NULL, addr, plen)) + errx(1, "%s: failed to add prefix %s", fn, prefix); + + if (verbose < 3) + return; + + if (!X509v3_addr_canonize(addrs)) + errx(1, "%s: failed to canonize with prefix %s", fn, prefix); +} + +static void +constraints_parse_ip_range(const char *fn, const char *min, const char *max, + enum afi afi, IPAddrBlocks *addrs) +{ + unsigned char min_addr[16] = {0}, max_addr[16] = {0}; + int af = afi == AFI_IPV4 ? AF_INET : AF_INET6; + + if (inet_pton(af, min, min_addr) != 1) + errx(1, "%s: failed to parse %s", fn, min); + if (inet_pton(af, max, max_addr) != 1) + errx(1, "%s: failed to parse %s", fn, max); + + if (!X509v3_addr_add_range(addrs, afi, NULL, min_addr, max_addr)) + errx(1, "%s: failed to add range %s--%s", fn, min, max); + + if (verbose < 3) + return; + + if (!X509v3_addr_canonize(addrs)) + errx(1, "%s: failed to canonize with range %s--%s", fn, + min, max); +} + +static void +constraints_parse_ip(const char *fn, char *p, enum afi afi, IPAddrBlocks *addrs) +{ + const char *min, *max; + + if (strchr(p, '-') == NULL) { + constraints_parse_ip_prefix(fn, p, afi, addrs); + return; + } + + if (!constraints_split_range(p, &min, &max)) + errx(1, "%s: failed to split range: %s", fn, p); + + constraints_parse_ip_range(fn, min, max, afi, addrs); +} + +/* + * Helper functions to parse textual representations of AS numbers or ranges. + * The RFC 3779 API has poor error reporting, so as a debugging aid, we call + * the prohibitively expensive X509v3_asid_canonize() in high verbosity mode. + */ + +static void +constraints_parse_asn(const char *fn, const char *asn, ASIdentifiers *asids) +{ + ASN1_INTEGER *id; + + if ((id = s2i_ASN1_INTEGER(NULL, asn)) == NULL) + errx(1, "%s: failed to parse AS %s", fn, asn); + + if (!X509v3_asid_add_id_or_range(asids, V3_ASID_ASNUM, id, NULL)) + errx(1, "%s: failed to add AS %s", fn, asn); + + if (verbose < 3) + return; + + if (!X509v3_asid_canonize(asids)) + errx(1, "%s: failed to canonize with AS %s", fn, asn); +} + +static void +constraints_parse_asn_range(const char *fn, const char *min, const char *max, + ASIdentifiers *asids) +{ + ASN1_INTEGER *min_as, *max_as; + + if ((min_as = s2i_ASN1_INTEGER(NULL, min)) == NULL) + errx(1, "%s: failed to parse AS %s", fn, min); + if ((max_as = s2i_ASN1_INTEGER(NULL, max)) == NULL) + errx(1, "%s: failed to parse AS %s", fn, max); + + if (!X509v3_asid_add_id_or_range(asids, V3_ASID_ASNUM, min_as, max_as)) + errx(1, "%s: failed to add AS range %s--%s", fn, min, max); + + if (verbose < 3) + return; + + if (!X509v3_asid_canonize(asids)) + errx(1, "%s: failed to canonize with AS range %s--%s", fn, + min, max); +} + +static void +constraints_parse_as(const char *fn, char *p, ASIdentifiers *asids) +{ + const char *min, *max; + + if (strchr(p, '-') == NULL) { + constraints_parse_asn(fn, p, asids); + return; + } + + if (!constraints_split_range(p, &min, &max)) + errx(1, "%s: failed to split range: %s", fn, p); + + constraints_parse_asn_range(fn, min, max, asids); +} + +/* + * Work around an annoying bug in X509v3_addr_add_range(). The upper bound + * of a range can have unused bits set in its ASN1_BIT_STRING representation. + * This triggers a check in ip_addr_parse(). A round trip through DER fixes + * this mess up. For extra special fun, {d2i,i2d}_IPAddrBlocks() isn't part + * of the API and implementing them for OpenSSL 3 is hairy, so do the round + * tripping once per address family. + */ +static void +constraints_normalize_ip_addrblocks(const char *fn, IPAddrBlocks **addrs) +{ + IPAddrBlocks *new_addrs; + IPAddressFamily *af; + const unsigned char *p; + unsigned char *der; + int der_len, i; + + if ((new_addrs = IPAddrBlocks_new()) == NULL) + err(1, NULL); + + for (i = 0; i < sk_IPAddressFamily_num(*addrs); i++) { + af = sk_IPAddressFamily_value(*addrs, i); + + der = NULL; + if ((der_len = i2d_IPAddressFamily(af, &der)) <= 0) + errx(1, "%s: failed to convert to DER", fn); + p = der; + if ((af = d2i_IPAddressFamily(NULL, &p, der_len)) == NULL) + errx(1, "%s: failed to convert from DER", fn); + free(der); + + if (!sk_IPAddressFamily_push(new_addrs, af)) + errx(1, "%s: failed to push constraints", fn); + } + + IPAddrBlocks_free(*addrs); + *addrs = new_addrs; +} + +/* + * If there is a constraints file for tals[talid], load it into a buffer + * and parse it line by line. Leverage the above parse helpers to build up + * IPAddrBlocks and ASIdentifiers. We use the RFC 3779 API to benefit from + * the limited abilities of X509v3_{addr,asid}_canonize() to sort and merge + * adjacent ranges. This doesn't deal with overlaps or duplicates, but it's + * better than nothing. + */ + +static void +constraints_parse_talid(int talid) +{ + IPAddrBlocks *allow_addrs, *deny_addrs; + ASIdentifiers *allow_asids, *deny_asids; + FILE *f; + char *fn, *p, *pp; + struct cert_as *allow_as = NULL, *deny_as = NULL; + struct cert_ip *allow_ips = NULL, *deny_ips = NULL; + size_t allow_asz = 0, allow_ipsz = 0, + deny_asz = 0, deny_ipsz = 0; + char *line = NULL; + size_t len = 0; + ssize_t n; + int fd, have_allow_as = 0, have_allow_ips = 0, + have_deny_as = 0, have_deny_ips = 0; + + fd = tal_constraints[talid].fd; + fn = tal_constraints[talid].fn; + tal_constraints[talid].fd = -1; + tal_constraints[talid].fn = NULL; + + if (fd == -1) { + free(fn); + return; + } + + if ((f = fdopen(fd, "r")) == NULL) + err(1, "fdopen"); + + if ((allow_addrs = IPAddrBlocks_new()) == NULL) + err(1, NULL); + if ((allow_asids = ASIdentifiers_new()) == NULL) + err(1, NULL); + if ((deny_addrs = IPAddrBlocks_new()) == NULL) + err(1, NULL); + if ((deny_asids = ASIdentifiers_new()) == NULL) + err(1, NULL); + + while ((n = getline(&line, &len, f)) != -1) { + if (line[n - 1] == '\n') + line[n - 1] = '\0'; + + p = line; + + /* Zap leading whitespace */ + while (isspace((unsigned char)*p)) + p++; + + /* Zap comments */ + if ((pp = strchr(p, '#')) != NULL) + *pp = '\0'; + + /* Zap trailing whitespace */ + if (pp == NULL) + pp = p + strlen(p); + while (pp > p && isspace((unsigned char)pp[-1])) + pp--; + *pp = '\0'; + + if (strlen(p) == 0) + continue; + + if (strncmp(p, "allow ", strlen("allow ")) == 0) { + p += strlen("allow "); + if (strchr(p, '.') != NULL) { + constraints_parse_ip(fn, p, AFI_IPV4, + allow_addrs); + have_allow_ips = 1; + } else if (strchr(p, ':') != NULL) { + constraints_parse_ip(fn, p, AFI_IPV6, + allow_addrs); + have_allow_ips = 1; + } else { + constraints_parse_as(fn, p, allow_asids); + have_allow_as = 1; + } + } else if (strncmp(p, "deny ", strlen("deny ")) == 0) { + p += strlen("deny "); + if (strchr(p, '.') != NULL) { + constraints_parse_ip(fn, p, AFI_IPV4, + deny_addrs); + have_deny_ips = 1; + } else if (strchr(p, ':') != NULL) { + constraints_parse_ip(fn, p, AFI_IPV6, + deny_addrs); + have_deny_ips = 1; + } else { + constraints_parse_as(fn, p, deny_asids); + have_deny_as = 1; + } + } else + errx(1, "%s: failed to parse %s", fn, p); + } + free(line); + + if (ferror(f)) + err(1, "%s", fn); + fclose(f); + + if (!X509v3_addr_canonize(allow_addrs)) + errx(1, "%s: failed to canonize IP addresses allowlist", fn); + if (!X509v3_asid_canonize(allow_asids)) + errx(1, "%s: failed to canonize AS numbers allowlist", fn); + if (!X509v3_addr_canonize(deny_addrs)) + errx(1, "%s: failed to canonize IP addresses denylist", fn); + if (!X509v3_asid_canonize(deny_asids)) + errx(1, "%s: failed to canonize AS numbers denylist", fn); + + if (have_allow_as) { + if (!sbgp_parse_assysnum(fn, allow_asids, &allow_as, + &allow_asz)) + errx(1, "%s: failed to parse AS identifiers allowlist", + fn); + } + if (have_deny_as) { + if (!sbgp_parse_assysnum(fn, deny_asids, &deny_as, + &deny_asz)) + errx(1, "%s: failed to parse AS identifiers denylist", + fn); + } + if (have_allow_ips) { + constraints_normalize_ip_addrblocks(fn, &allow_addrs); + + if (!sbgp_parse_ipaddrblk(fn, allow_addrs, &allow_ips, + &allow_ipsz)) + errx(1, "%s: failed to parse IP addresses allowlist", + fn); + } + if (have_deny_ips) { + constraints_normalize_ip_addrblocks(fn, &deny_addrs); + + if (!sbgp_parse_ipaddrblk(fn, deny_addrs, &deny_ips, + &deny_ipsz)) + errx(1, "%s: failed to parse IP addresses denylist", + fn); + } + + tal_constraints[talid].allow_as = allow_as; + tal_constraints[talid].allow_asz = allow_asz; + tal_constraints[talid].allow_ips = allow_ips; + tal_constraints[talid].allow_ipsz = allow_ipsz; + tal_constraints[talid].deny_as = deny_as; + tal_constraints[talid].deny_asz = deny_asz; + tal_constraints[talid].deny_ips = deny_ips; + tal_constraints[talid].deny_ipsz = deny_ipsz; + + IPAddrBlocks_free(allow_addrs); + IPAddrBlocks_free(deny_addrs); + ASIdentifiers_free(allow_asids); + ASIdentifiers_free(deny_asids); + + free(fn); +} + +/* + * Iterate over all TALs and parse the constraints files loaded previously. + */ +void +constraints_parse(void) +{ + int talid; + + for (talid = 0; talid < talsz; talid++) + constraints_parse_talid(talid); +} + +static int +constraints_check_as(struct cert_as *cert, const struct cert_as *allow_as, + size_t allow_asz, const struct cert_as *deny_as, size_t deny_asz) +{ + uint32_t min, max; + + /* Inheriting EE resources are not to be constrained. */ + if (cert->type == CERT_AS_INHERIT) + return 1; + + if (cert->type == CERT_AS_ID) { + min = cert->id; + max = cert->id; + } else { + min = cert->range.min; + max = cert->range.max; + } + + if (deny_as != NULL) { + if (as_check_covered(min, max, deny_as, deny_asz) >= 0) + return 0; + } + if (allow_as != NULL) { + if (as_check_covered(min, max, allow_as, allow_asz) <= 0) + return 0; + } + return 1; +} + +static int +constraints_check_ips(struct cert_ip *cert, const struct cert_ip *allow_ips, + size_t allow_ipsz, const struct cert_ip *deny_ips, size_t deny_ipsz) +{ + /* Inheriting EE resources are not to be constrained. */ + if (cert->type == CERT_IP_INHERIT) + return 1; + + if (deny_ips != NULL) { + if (ip_addr_check_covered(cert->afi, cert->min, cert->max, + deny_ips, deny_ipsz) >= 0) + return 0; + } + if (allow_ips != NULL) { + if (ip_addr_check_covered(cert->afi, cert->min, cert->max, + allow_ips, allow_ipsz) <= 0) + return 0; + } + return 1; +} + +/* + * Check whether an EE cert's resources are covered by its TAL's constraints. + * We accept certs with a negative talid as "unknown TAL" for filemode. The + * logic nearly duplicates valid_cert(). + */ +int +constraints_validate(const char *fn, const struct cert *cert) +{ + int talid = cert->talid; + struct cert_as *allow_as, *deny_as; + struct cert_ip *allow_ips, *deny_ips; + size_t i, allow_asz, allow_ipsz, deny_asz, deny_ipsz; + + /* Accept negative talid to bypass validation. */ + if (talid < 0) + return 1; + if (talid >= talsz) + errx(1, "%s: talid out of range %d", fn, talid); + + allow_as = tal_constraints[talid].allow_as; + allow_asz = tal_constraints[talid].allow_asz; + deny_as = tal_constraints[talid].deny_as; + deny_asz = tal_constraints[talid].deny_asz; + + for (i = 0; i < cert->asz; i++) { + if (constraints_check_as(&cert->as[i], allow_as, allow_asz, + deny_as, deny_asz)) + continue; + + as_warn(fn, &cert->as[i], "violates trust anchor constraints"); + return 0; + } + + allow_ips = tal_constraints[talid].allow_ips; + allow_ipsz = tal_constraints[talid].allow_ipsz; + deny_ips = tal_constraints[talid].deny_ips; + deny_ipsz = tal_constraints[talid].deny_ipsz; + + for (i = 0; i < cert->ipsz; i++) { + if (constraints_check_ips(&cert->ips[i], allow_ips, allow_ipsz, + deny_ips, deny_ipsz)) + continue; + + ip_warn(fn, &cert->ips[i], "violates trust anchor constraints"); + return 0; + } + + return 1; +} Index: usr.sbin/rpki-client/filemode.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/filemode.c,v retrieving revision 1.35 diff -u -p -r1.35 filemode.c --- usr.sbin/rpki-client/filemode.c 25 Sep 2023 11:08:45 -0000 1.35 +++ usr.sbin/rpki-client/filemode.c 26 Sep 2023 14:27:46 -0000 @@ -468,6 +468,17 @@ proc_parser_file(char *file, unsigned ch break; } } + if (status && cert == NULL) { + struct cert *eecert; + + eecert = cert_parse_ee_cert(file, a->cert->talid, x509); + if (eecert == NULL) + status = 0; + cert_free(eecert); + } else if (status) { + cert->talid = a->cert->talid; + status = constraints_validate(file, cert); + } } else if (is_ta) { if ((tal = find_tal(cert)) != NULL) { cert = ta_parse(file, cert, tal->pkey, tal->pkeysz); @@ -648,6 +659,7 @@ proc_filemode(int fd) OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); x509_init_oid(); + constraints_parse(); if ((ctx = X509_STORE_CTX_new()) == NULL) err(1, "X509_STORE_CTX_new"); Index: usr.sbin/rpki-client/gbr.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/gbr.c,v retrieving revision 1.28 diff -u -p -r1.28 gbr.c --- usr.sbin/rpki-client/gbr.c 25 Sep 2023 11:08:45 -0000 1.28 +++ usr.sbin/rpki-client/gbr.c 26 Sep 2023 14:27:46 -0000 @@ -88,7 +88,7 @@ gbr_parse(X509 **x509, const char *fn, i goto out; } - if ((cert = cert_parse_ee_cert(fn, *x509)) == NULL) + if ((cert = cert_parse_ee_cert(fn, talid, *x509)) == NULL) goto out; return p.res; Index: usr.sbin/rpki-client/geofeed.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/geofeed.c,v retrieving revision 1.14 diff -u -p -r1.14 geofeed.c --- usr.sbin/rpki-client/geofeed.c 25 Sep 2023 11:08:45 -0000 1.14 +++ usr.sbin/rpki-client/geofeed.c 26 Sep 2023 14:27:46 -0000 @@ -252,7 +252,7 @@ geofeed_parse(X509 **x509, const char *f if (!x509_get_notafter(*x509, fn, &p.res->notafter)) goto out; - if ((cert = cert_parse_ee_cert(fn, *x509)) == NULL) + if ((cert = cert_parse_ee_cert(fn, talid, *x509)) == NULL) goto out; if (x509_any_inherits(*x509)) { Index: usr.sbin/rpki-client/ip.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/ip.c,v retrieving revision 1.28 diff -u -p -r1.28 ip.c --- usr.sbin/rpki-client/ip.c 25 Sep 2023 08:48:14 -0000 1.28 +++ usr.sbin/rpki-client/ip.c 26 Sep 2023 14:27:46 -0000 @@ -342,3 +342,26 @@ ip_roa_compose_ranges(struct roa_ip *p) if (sz > 0 && p->addr.prefixlen % 8 != 0) p->max[sz - 1] |= (1 << (8 - p->addr.prefixlen % 8)) - 1; } + +void +ip_warn(const char *fn, const struct cert_ip *cert, const char *msg) +{ + char buf[128]; + + switch (cert->type) { + case CERT_IP_ADDR: + ip_addr_print(&cert->ip, cert->afi, buf, sizeof(buf)); + warnx("%s: %s: %s", fn, buf, msg); + break; + case CERT_IP_INHERIT: + warnx("%s: (inherit): %s", fn, msg); + break; + case CERT_IP_RANGE: + ip_addr_range_print(&cert->range, cert->afi, buf, sizeof(buf)); + warnx("%s: %s: %s", fn, buf, msg); + break; + default: + warnx("%s: corrupt cert", fn); + break; + } +} Index: usr.sbin/rpki-client/main.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v retrieving revision 1.246 diff -u -p -r1.246 main.c --- usr.sbin/rpki-client/main.c 30 Aug 2023 10:02:28 -0000 1.246 +++ usr.sbin/rpki-client/main.c 26 Sep 2023 14:27:46 -0000 @@ -1094,6 +1094,9 @@ main(int argc, char *argv[]) if (talsz == 0) err(1, "no TAL files found in %s", "/etc/rpki"); + /* Load optional constraint files sitting next to the TALs. */ + constraints_load(); + /* * Create the file reader as a jailed child process. * It will be responsible for reading all of the files (ROAs, @@ -1107,6 +1110,9 @@ main(int argc, char *argv[]) else proc_filemode(proc); } + + /* Constraints are only needed in the filemode and parser processes. */ + constraints_unload(); /* * Create a process that will do the rsync'ing. Index: usr.sbin/rpki-client/mft.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v retrieving revision 1.98 diff -u -p -r1.98 mft.c --- usr.sbin/rpki-client/mft.c 25 Sep 2023 11:08:45 -0000 1.98 +++ usr.sbin/rpki-client/mft.c 26 Sep 2023 14:27:46 -0000 @@ -428,7 +428,7 @@ mft_parse(X509 **x509, const char *fn, i if (mft_parse_econtent(cms, cmsz, &p) == 0) goto out; - if ((cert = cert_parse_ee_cert(fn, *x509)) == NULL) + if ((cert = cert_parse_ee_cert(fn, talid, *x509)) == NULL) goto out; if (p.res->signtime > p.res->nextupdate) { Index: usr.sbin/rpki-client/parser.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v retrieving revision 1.99 diff -u -p -r1.99 parser.c --- usr.sbin/rpki-client/parser.c 25 Sep 2023 11:08:45 -0000 1.99 +++ usr.sbin/rpki-client/parser.c 26 Sep 2023 14:27:46 -0000 @@ -441,6 +441,13 @@ proc_parser_cert(char *file, const unsig cert->talid = a->cert->talid; + if (cert->purpose == CERT_PURPOSE_BGPSEC_ROUTER) { + if (!constraints_validate(file, cert)) { + cert_free(cert); + return NULL; + } + } + /* * Add validated CA certs to the RPKI auth tree. */ @@ -813,6 +820,7 @@ proc_parser(int fd) OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); x509_init_oid(); + constraints_parse(); if ((ctx = X509_STORE_CTX_new()) == NULL) err(1, "X509_STORE_CTX_new"); Index: usr.sbin/rpki-client/rfc3779.c =================================================================== RCS file: usr.sbin/rpki-client/rfc3779.c diff -N usr.sbin/rpki-client/rfc3779.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ usr.sbin/rpki-client/rfc3779.c 26 Sep 2023 14:27:46 -0000 @@ -0,0 +1,52 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2021 Theo Buehler <t...@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <err.h> +#include <stddef.h> + +#include <openssl/x509v3.h> + +#include "extern.h" + +/* + * These should really have been part of the public OpenSSL RFC 3779 API... + */ + +IPAddrBlocks * +IPAddrBlocks_new(void) +{ + IPAddrBlocks *addrs; + + /* + * XXX The comparison function IPAddressFamily_cmp() isn't public. + * Install it using a side effect of the lovely X509v3_addr_canonize(). + */ + if ((addrs = sk_IPAddressFamily_new_null()) == NULL) + return NULL; + if (!X509v3_addr_canonize(addrs)) { + IPAddrBlocks_free(addrs); + return NULL; + } + + return addrs; +} + +void +IPAddrBlocks_free(IPAddrBlocks *addr) +{ + sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free); +} Index: usr.sbin/rpki-client/roa.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/roa.c,v retrieving revision 1.70 diff -u -p -r1.70 roa.c --- usr.sbin/rpki-client/roa.c 25 Sep 2023 11:08:45 -0000 1.70 +++ usr.sbin/rpki-client/roa.c 26 Sep 2023 14:27:46 -0000 @@ -257,7 +257,7 @@ roa_parse(X509 **x509, const char *fn, i goto out; } - if ((cert = cert_parse_ee_cert(fn, *x509)) == NULL) + if ((cert = cert_parse_ee_cert(fn, talid, *x509)) == NULL) goto out; if (cert->asz > 0) { Index: usr.sbin/rpki-client/rsc.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/rsc.c,v retrieving revision 1.28 diff -u -p -r1.28 rsc.c --- usr.sbin/rpki-client/rsc.c 25 Sep 2023 11:08:45 -0000 1.28 +++ usr.sbin/rpki-client/rsc.c 26 Sep 2023 14:27:46 -0000 @@ -423,7 +423,7 @@ rsc_parse(X509 **x509, const char *fn, i if (!rsc_parse_econtent(cms, cmsz, &p)) goto out; - if ((cert = cert_parse_ee_cert(fn, *x509)) == NULL) + if ((cert = cert_parse_ee_cert(fn, talid, *x509)) == NULL) goto out; p.res->valid = valid_rsc(fn, cert, p.res); Index: usr.sbin/rpki-client/tak.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/tak.c,v retrieving revision 1.12 diff -u -p -r1.12 tak.c --- usr.sbin/rpki-client/tak.c 25 Sep 2023 11:08:45 -0000 1.12 +++ usr.sbin/rpki-client/tak.c 26 Sep 2023 14:27:46 -0000 @@ -274,7 +274,7 @@ tak_parse(X509 **x509, const char *fn, i if (!tak_parse_econtent(cms, cmsz, &p)) goto out; - if ((cert = cert_parse_ee_cert(fn, *x509)) == NULL) + if ((cert = cert_parse_ee_cert(fn, talid, *x509)) == NULL) goto out; if (strcmp(p.res->aki, p.res->current->ski) != 0) { Index: usr.sbin/rpki-client/extern.h =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v retrieving revision 1.192 diff -u -p -r1.192 extern.h --- usr.sbin/rpki-client/extern.h 25 Sep 2023 14:56:20 -0000 1.192 +++ usr.sbin/rpki-client/extern.h 26 Sep 2023 14:27:46 -0000 @@ -613,7 +613,7 @@ struct tal *tal_read(struct ibuf *); void cert_buffer(struct ibuf *, const struct cert *); void cert_free(struct cert *); void auth_tree_free(struct auth_tree *); -struct cert *cert_parse_ee_cert(const char *, X509 *); +struct cert *cert_parse_ee_cert(const char *, int, X509 *); struct cert *cert_parse_pre(const char *, const unsigned char *, size_t); struct cert *cert_parse(const char *, struct cert *); struct cert *ta_parse(const char *, struct cert *, const unsigned char *, @@ -717,6 +717,7 @@ int ip_addr_check_covered(enum afi, co const unsigned char *, const struct cert_ip *, size_t); int ip_cert_compose_ranges(struct cert_ip *); void ip_roa_compose_ranges(struct roa_ip *); +void ip_warn(const char *, const struct cert_ip *, const char *); int sbgp_addr(const char *, struct cert_ip *, size_t *, enum afi, const ASN1_BIT_STRING *); @@ -733,6 +734,7 @@ int as_check_overlap(const struct cert const struct cert_as *, size_t); int as_check_covered(uint32_t, uint32_t, const struct cert_as *, size_t); +void as_warn(const char *, const struct cert_as *, const char *); int sbgp_as_id(const char *, struct cert_as *, size_t *, const ASN1_INTEGER *); @@ -742,6 +744,12 @@ int sbgp_as_range(const char *, struct int sbgp_parse_assysnum(const char *, const ASIdentifiers *, struct cert_as **, size_t *); +/* Constraints-specific */ +void constraints_load(void); +void constraints_unload(void); +void constraints_parse(void); +int constraints_validate(const char *, const struct cert *); + /* Parser-specific */ void entity_free(struct entity *); void entity_read_req(struct ibuf *, struct entity *); @@ -805,6 +813,7 @@ void rrdp_http_done(unsigned int, enum /* Encoding functions for hex and base64. */ +unsigned char *load_fd(int, size_t *); unsigned char *load_file(const char *, size_t *); int base64_decode_len(size_t, size_t *); int base64_decode(const unsigned char *, size_t, @@ -863,6 +872,10 @@ void rsc_print(const X509 *, const str void aspa_print(const X509 *, const struct aspa *); void tak_print(const X509 *, const struct tak *); void geofeed_print(const X509 *, const struct geofeed *); + +/* Missing RFC 3779 API */ +IPAddrBlocks *IPAddrBlocks_new(void); +void IPAddrBlocks_free(IPAddrBlocks *); /* Output! */