Page MenuHomeFreeBSD

Introduce certctl(8)
AbandonedPublic

Authored by kevans on Aug 23 2018, 3:46 AM.

Details

Summary

A simple utility to hash all trusted certificates on the system into /etc/ssl/certs
Also allows the user to blacklist certificates they do not trust

Todo: create man page

Diff Detail

Repository
rS FreeBSD src repository
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes

Thanks for all of the feedback

usr.sbin/trustctl/trustctl.sh
72–75 ↗(On Diff #47148)

In this case $1 is the name of a function, we should still double quote that?

allanjude marked an inline comment as done.

Updated with extensive feedback from dteske@

usr.sbin/trustctl/trustctl.sh
31–32 ↗(On Diff #47148)

BLACKLISTPATH and TRUSTPATH are now colon-delimited. Need to update these defaults

72–75 ↗(On Diff #47148)

Yes. Prevents word splitting, so that you get expected results should someone try to overload the keyword in the scripts arguments

103 ↗(On Diff #47148)

Don't forget to mark this as done

30 ↗(On Diff #47211)

Add blank line after "#x60 CONFIGURATION" and before the first variable. This makes it easier to jump to the top of the variables using "{" and "}" paragraph navigation in nvi/vi/vim (if you use those editors) or something comparable in other editors.

37 ↗(On Diff #47211)

Add blank line after "#x60 GLOBALS"

38 ↗(On Diff #47211)

Add double-quotes around ${0##*/}

42 ↗(On Diff #47211)

Blank line after "#x60 FUNCTIONS"

204 ↗(On Diff #47211)

Add a blank line after "#x60 MAIN"

A bit of a meta comment: "trustctl" seems like a very generic name. This tool is managing the SSL certificate bundle, not handling various types of trust databases in some generic way. As such, I'd give it a more specific name like 'sslcertctl'.

Rename trustctl to certctl

Address additional feedback from dteske

allanjude retitled this revision from Introduce trustctl(8) to Introduce certctl(8).Aug 31 2018, 2:47 AM

The patch is showing usr.sbin/certctl/trustctl.sh -- is this a phab issue or did the file not get renamed in the patch?

usr.sbin/certctl/Makefile
3 ↗(On Diff #47515)

Rename to certctl.sh ?

Minor nit: could you please quote variables with {} (e.g. $VAR -> ${VAR})?

usr.sbin/Makefile
11 ↗(On Diff #47805)

Could you please make this dependent on MK_OPENSSL because the utility requires it?

usr.sbin/certctl/certctl.sh
36 ↗(On Diff #47805)

(Not a blocking issue) Although unlikely to happen in practice, it's probably a good idea to not assume there would be no collision.

79 ↗(On Diff #47805)

Why is this copied (instead of a symbolic link)?

127 ↗(On Diff #47805)

Minor nit: 127-134 and 136-143 are similar enough to be abstracted into a helper routine instead of duplicating most of the code. It would make the code easier to read as well.

144 ↗(On Diff #47805)

Arguably, I would expect the hash symbolic links be removed when the certificate was for any reason, gone. The current code in do_list would issue a warning, but would not take any action.

199 ↗(On Diff #47805)

Minor nit: you are rehashing both blacklisted and trusted certificates.

I don't think OpenSSL actually supports blacklists, were these for this script only?

usr.sbin/certctl/certctl.sh
36 ↗(On Diff #47805)

Allan quoted the globs here so they won't be expanded until CWD is a directory where those extensions are expected to be found. What might "collision" mean in this context?

127 ↗(On Diff #47805)

We can't boil it down to (where x is whatever name you give the function`):

x "$BLACKLISTPATH"
x "$CPATH"

Because the do_scan and echo arguments are different.

Reducing it down to the unique elements:

x "$BLACKLISTPATH" blacklisted create_blacklisted
x "$TRUSTPATH" trusted create_trusted_link

Doesn't appear to improve readability for me considering it doesn't tell you that the first argument is a colon-separated list of directories, second argument is part of a string that is echo'd, and that the last argument is a argument to the do_scan function.

Alternatives could be to add flags:

x -p "$BLACKLISTPATH" -t blacklisted -f create_blacklisted
x -p "$TRUSTPATH" -t trusted -f create_trusted_link

That's getting better. Maybe if we get the rest of the way there by using a good function name and longer arguments:

scanpath -t "Scanning %s for blacklisted certificates..." \
        -f create_blacklisted "$BLACKLISTPATH"
scanpath -t "Scanning %s for trusted certificates..." \
        -f create_trusted_link "$TRUSTPATH"

That looks pretty good.

But now we have to create the function to back that readable code. This could potentially impact the decision to refactor this code into a function. Let's take a look:

scanpath()
{
        local OPTIND=1 OPTARG flag
        local path text= func=
        while getopts t:f: flag; do
                case "$flag" in
                t) text="$OPTARG" ;;
                f) func="$OPTARG" ;;
                esac
        done
        shift $(( $OPTIND - 1 ))
        local oldIFS="$IFS" IFS=:
        set -- "$1"
        IFS="$oldIFS"
        for path in "$@"; do
                [ -d "$path" ] || continue
                [ "$text" ] && printf "$text\n" "$path"
                do_scan "$func" "$path"
        done
}

The function is 20 lines. Adding the calls (4 lines), thats 24 lines total.

Without the function, the two code segments mentioned amount to 16 lines of code.

So I throw it back at Allan (owner of the code and ultimate decision maker) and Xin (suggester of refactor) to decide.

Making it a function could cause the code to increase by 8 lines of code; but maybe the result is desirable.

allanjude marked 8 inline comments as done.

Address feedback from delphij

allanjude added inline comments.
usr.sbin/certctl/certctl.sh
79 ↗(On Diff #47805)

This was to deal with the fact that the user might have the 'bad' certificate in an ephemeral location, but that is their problem, so I switched it to symlink.

127 ↗(On Diff #47805)

I was able to refactor this in a way I think looks nicer.

144 ↗(On Diff #47805)

list is a read only command, so should not make changes. Doing a rehash would remove any missing certificates.

199 ↗(On Diff #47805)

Yes, the blacklist just prevents a certificate from getting hashed into the trust store by certctl

Note: I've not reviewed the shell script itself...

usr.sbin/Makefile
128 ↗(On Diff #48669)

Why not SUBDIR.${MK_OPENSSL}+= certctl here?

0mp requested changes to this revision.Oct 5 2018, 9:53 AM
0mp added a subscriber: 0mp.

igor and mandoc -Tlint report some problems with the manual page.

usr.sbin/certctl/certctl.8
109 ↗(On Diff #48673)

Do we want to cross reference this new manpage from existing ones (like openssl(1))?

This revision now requires changes to proceed.Oct 5 2018, 9:53 AM
kevans added a reviewer: allanjude.

Main changes:

  • Gate certctl build/installation on MK_CAROOT && MK_OPENSSL
  • Sprinkle some DESTDIR around
bcr added a subscriber: bcr.

OK for the man page.
Regarding @0mp's comment about the reference from openssl(1): we can do that later after this change has been committed. It's not critical to do that with this change.

This revision was not accepted when it landed; it landed in state Needs Review.Oct 2 2019, 1:06 AM
Closed by commit rS352949: [2/3] Add certctl(8) (authored by kevans). · Explain Why
This revision was automatically updated to reflect the committed changes.

I don't know how likely this is, but create_trusted_link may cause problems when you have two or more certs with the same subject. E.g., certs with overlapping validity dates. One expires, the other one starts one day before expiration of the former. You will overwrite those because you always assume .0. but it should be .0, .1, .2, and so forth (see https://docs.infor.com/ln/10.5/de-de/lnolh/help/tt/onlinemanual/https_soap_generate_hash.html). If you check "openssl s_client" with truss you'll see stuff like this

fstatat(AT_FDCWD,"/etc/ssl/certs/d7532a42.0",{ mode=-rw-r--r-- ,inode=1043996,size=2850,blksize=32768 },0x0) = 0 (0x0)
open("/etc/ssl/certs/d7532a42.0",O_RDONLY,0666)  = 4 (0x4)
fstat(4,{ mode=-rw-r--r-- ,inode=1043996,size=2850,blksize=32768 }) = 0 (0x0)
read(4,"-----BEGIN CERTIFICATE-----\r\nM"...,32768) = 2850 (0xb22)
read(4,0x800b55bc0,32768)            = 0 (0x0)
close(4)                     = 0 (0x0)
fstatat(AT_FDCWD,"/etc/ssl/certs/d7532a42.1",0x7fffffffd570,0x0) ERR#2 'No such file or directory'

If you don't plan to add this, at least update the manpage.

See reference for this: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_default_verify_paths.html

One more note: c_reshash properly handles this: https://github.com/openssl/openssl/blob/master/tools/c_rehash.in#L156-L181

Here is a test review from an huge enterprise user. I actually come from PR 160387 and D16352. I have been pointed to here by Helge Oldach.

We have a lot of CAs, partially depth 3. I did three tests:

  1. Use public CAs from Mozilla and added them to /usr/local/share/certs
  2. Use a Siemens server which is also reachable from the internet. This requires several CAs from QuoVadis and Siemens Intermediates
  3. Use a Siemens server which is only on the intranet. This requires Siemens Root CAs and Intermediate CAs.

Both QuoVadis CAs and Siemens CAs are in /usr/local/etc/ssl/certs.

After "certctl rehash:"

# certctl list
Listing Trusted Certificates:
02265526.0      Entrust Root Certification Authority - G2
03179a64.0      Staat der Nederlanden EV Root CA
062cdee6.0      GlobalSign
064e0aa9.0      QuoVadis Root CA 2 G3
06dc52d5.0      SSL.com EV Root Certification Authority RSA R2
080911ac.0      QuoVadis Root Certification Authority
09789157.0      Starfield Services Root Certificate Authority - G2
0a775a30.0      GTS Root R3
0b1b94ef.0      CFCA EV ROOT
0b7c536a.0      D-TRUST Root CA 3 2013
0bf05006.0      SSL.com Root Certification Authority ECC
0c4c9b6c.0      Global Chambersign Root - 2008
0f5dc4f3.0      UCA Extended Validation Root
0f6fa695.0      GDCA TrustAUTH R5 ROOT
1001acf7.0      GTS Root R1
106f3e4d.0      Entrust Root Certification Authority - EC1
116bf586.0      GeoTrust Primary Certification Authority - G2
128805a3.0      EE Certification Centre Root CA
1320b215.0      Symantec Class 2 Public Primary Certification Authority - G6
14bc7599.0      emSign ECC Root CA - G3
157753a5.0      AddTrust External CA Root
1636090b.0      Hellenic Academic and Research Institutions RootCA 2011
18856ac4.0      SecureSign RootCA11
1c7620aa.0      Siemens Issuing CA Internet Code Signing 2016
1d3472b9.0      GlobalSign
1e08bfd1.0      IdenTrust Public Sector Root CA 1
1e09d511.0      T-TeleSec GlobalRoot Class 2
244b5494.0      DigiCert High Assurance EV Root CA
26312675.0      Symantec Class 1 Public Primary Certification Authority - G6
2923b3f9.0      emSign Root CA - G1
2ae6433e.0      CA Disig Root R2
2b349938.0      AffirmTrust Commercial
2b9d74f0.0      Siemens Issuing CA EE Network Smartcard Auth 2016
2c543cd1.0      GeoTrust Global CA
2e4eed3c.0      thawte Primary Root CA
2e5ac55d.0      DST Root CA X3
32888f65.0      Hellenic Academic and Research Institutions RootCA 2015
349f2832.0      EC-ACC
3513523f.0      DigiCert Global Root CA
3bde41ac.0      Autoridad de Certificacion Firmaprofesional CIF A62634068
3e44d2f7.0      TrustCor RootCert CA-2
3e45d192.0      Hongkong Post Root CA 1
40193066.0      Certum Trusted Network CA 2
4042bcee.0      ISRG Root X1
40547a79.0      COMODO Certification Authority
406c9bb1.0      emSign Root CA - C1
4304c5e5.0      Network Solutions Certificate Authority
442adcac.0      Certum CA
480720ec.0      GeoTrust Primary Certification Authority
48bec511.0      Certum Trusted Network CA
4a6481c9.0      GlobalSign
4b718d9b.0      emSign ECC Root CA - C3
4bfab552.0      Starfield Root Certificate Authority - G2
4ca5f54b.0      QuoVadis Enterprise Trust CA 2 G3
4d4ba017.0      Symantec Class 2 Public Primary Certification Authority - G4
4f316efb.0      SwissSign Gold CA - G2
5273a94c.0      E-Tugra Certification Authority
5443e9e3.0      T-TeleSec GlobalRoot Class 3
54657681.0      Buypass Class 2 Root CA
57bcb2da.0      SwissSign Silver CA - G2
5a4d6896.0      Staat der Nederlanden Root CA - G3
5ad8a5d6.0      GlobalSign Root CA
5c44d531.0      Staat der Nederlanden Root CA - G2
5cd81ad7.0      TeliaSonera Root CA v1
5d3033c5.0      TrustCor RootCert CA-1
5e98733a.0      Entrust Root Certification Authority - G4
5f15c80c.0      TWCA Global Root CA
607986c7.0      DigiCert Global Root G2
626dceaf.0      GTS Root R2
62744ee1.0      Symantec Class 1 Public Primary Certification Authority - G4
6410666e.0      subject=C = TW, O = Government Root Certification Authority
653b494a.0      Baltimore CyberTrust Root
681ad634.0      Siemens Issuing CA Internet Server 2016
68dd7389.0      Hongkong Post Root CA 3
6b99d060.0      Entrust Root Certification Authority
6d41d539.0      Amazon Root CA 2
6fa5da56.0      SSL.com Root Certification Authority RSA
706f604c.0      XRamp Global Certification Authority
749e9e03.0      QuoVadis Root CA 1 G3
75d1b2ed.0      DigiCert Trusted Root G4
76cb8f92.0      Cybertrust Global Root
76faf6c0.0      QuoVadis Root CA 3
7719f463.0      Hellenic Academic and Research Institutions ECC RootCA 2015
773e07ad.0      OISTE WISeKey Global Root GC CA
7aaf71c0.0      TrustCor ECA-1
7d0b38bd.0      VeriSign Class 3 Public Primary Certification Authority - G4
7f3d5d1d.0      DigiCert Assured ID Root G3
8160b96c.0      Microsec e-Szigno Root CA 2009
861a399d.0      AddTrust Class 1 CA Root
8867006a.0      GeoTrust Universal CA 2
8cb5ee0f.0      Amazon Root CA 3
8d86cdd1.0      subject=C = RO, O = certSIGN, OU = certSIGN ROOT CA
8dc03e53.0      Siemens Internet CA V1.0
930ac5d2.0      Actalis Authentication Root CA
930b5fed.0      Siemens Issuing CA Multi Purpose 2016
93bc0acc.0      AffirmTrust Networking
988a38cb.0      NetLock Arany (Class Gold) F\U0151tan\FAs\EDtv\E1ny
9c2e7d30.0      Sonera Class2 CA
9c8dfbd4.0      AffirmTrust Premium ECC
9d04f354.0      DigiCert Assured ID Root G2
9ec27e42.0      Siemens Issuing CA Intranet Server 2016
a331fcb4.0      Siemens Issuing CA EE Auth 2016
a3418fda.0      GTS Root R4
a382b08f.0      Siemens Trust Center Root-CA V2.0
a8dee976.0      SwissSign Platinum CA - G2
a94d09e5.0      ACCVRAIZ1
ad088e1d.0      GeoTrust Universal CA
aee5f10d.0      Entrust.net Certification Authority (2048)
b0e59380.0      GlobalSign
b1159c4c.0      DigiCert Assured ID Root CA
b1b8a7f3.0      OISTE WISeKey Global Root GA CA
b204d74a.0      VeriSign Class 3 Public Primary Certification Authority - G5
b428065f.0      Siemens Issuing CA EE Enc 2016
b5d79467.0      QuoVadis Enterprise Trust CA 3 G3
b66938e9.0      Secure Global CA
b727005e.0      AffirmTrust Premium
b7a5b843.0      TWCA Root Certification Authority
ba89ed3b.0      thawte Primary Root CA - G3
c01cdfa2.0      VeriSign Universal Root Certification Authority
c01eb047.0      UCA Global G2 Root
c089bbbd.0      thawte Primary Root CA - G2
c0ff1f52.0      VeriSign Class 3 Public Primary Certification Authority - G3
c28a8a30.0      D-TRUST Root Class 3 CA 2 2009
c47d9980.0      Chambers of Commerce Root - 2008
ca6e4ad9.0      subject=C = TW, O = "Chunghwa Telecom Co., Ltd.", OU = ePKI Root Certification Authority
cb59f961.0      Global Chambersign Root
cbf06781.0      Go Daddy Root Certificate Authority - G2
cc450945.0      Izenpe.com
cd58d51e.0      subject=C = JP, O = "SECOM Trust Systems CO.,LTD.", OU = Security Communication RootCA2
cd8c0d63.0      subject=C = ES, O = FNMT-RCM, OU = AC RAIZ FNMT-RCM
ce5e74ef.0      Amazon Root CA 1
d4555404.0      Siemens Issuing CA Intranet Server 2017
d4dae3dd.0      D-TRUST Root Class 3 CA 2 EV 2009
d6325660.0      COMODO RSA Certification Authority
d7532a42.0      Siemens Issuing CA Internet Server 2017
d7e8dc79.0      QuoVadis Root CA 2
d853d49e.0      subject=C = GB, O = Trustis Limited, OU = Trustis FPS Root CA
d9d79a66.0      Siemens Root CA V3.0 2016
dc45b0bd.0      VeriSign Class 2 Public Primary Certification Authority - G3
dc4d6a89.0      GlobalSign
dd8e9d41.0      DigiCert Global Root G3
ddc2d14f.0      Siemens Issuing CA MSA Impersonalized Entities 2016
de6d66f3.0      Amazon Root CA 4
def36a68.0      LuxTrust Global Root 2
e113c810.0      Certigna
e18bfb83.0      QuoVadis Root CA 3 G3
e2799e36.0      GeoTrust Primary Certification Authority - G3
e36a6752.0      Atos TrustedRoot 2011
e6a60b73.0      Siemens Issuing CA Intranet Code Signing 2016
e73d606e.0      OISTE WISeKey Global Root GB CA
e8de2f56.0      Buypass Class 3 Root CA
ee1365c0.0      VeriSign Class 1 Public Primary Certification Authority - G3
ee64a828.0      AAA Certificate Services
eed8c118.0      COMODO ECC Certification Authority
ef954a4e.0      IdenTrust Commercial Root CA 1
f081611a.0      subject=C = US, O = "The Go Daddy Group, Inc.", OU = Go Daddy Class 2 Certification Authority
f0c70a8d.0      SSL.com EV Root Certification Authority ECC
f30dd6ad.0      USERTrust ECC Certification Authority
f3377b1b.0      subject=C = JP, O = SECOM Trust.net, OU = Security Communication RootCA1
f387163d.0      subject=C = US, O = "Starfield Technologies, Inc.", OU = Starfield Class 2 Certification Authority
f38f510d.0      Siemens Issuing CA Medium Strength Authentication 2016
f39fc864.0      SecureTrust CA
f51bb24c.0      Certigna Root CA
f90208f7.0      Chambers of Commerce Root
fc5a8f99.0      USERTrust RSA Certification Authority
fe8a2cd8.0      SZAFIR ROOT CA2
ff34af3f.0      TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1

Then used "openssl s_client", e.g.,

openssl s_client -connect heise.de:443 \
  -verify 5 -CApath /etc/ssl/certs -verify_return_error \
  -proxy de.coia.siemens.net:9400

Public domain:

CONNECTED(00000003)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = redirector.heise.de
verify return:1

Siemens external:

CONNECTED(00000003)
depth=3 C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2 G3
verify return:1
depth=2 C = BM, O = QuoVadis Limited, CN = QuoVadis Enterprise Trust CA 2 G3
verify return:1
depth=1 C = DE, ST = Bayern, L = Muenchen, O = Siemens, serialNumber = ZZZZZZB9, OU = Siemens Trust Center, CN = Siemens Issuing CA Internet Server 2017
verify return:1
depth=0 C = DE, ST = Bayern, L = Muenchen, O = Siemens, OU = SI BP R&D AS, CN = code.siemens.com
verify return:1

Siemens internal:

CONNECTED(00000003)
depth=2 C = DE, ST = Bayern, L = Muenchen, O = Siemens, serialNumber = ZZZZZZA1, OU = Siemens Trust Center, CN = Siemens Root CA V3.0 2016
verify return:1
depth=1 C = DE, ST = Bayern, L = Muenchen, O = Siemens, serialNumber = ZZZZZZB7, OU = Siemens Trust Center, CN = Siemens Issuing CA Intranet Server 2017
verify return:1
depth=0 C = DE, O = Siemens, OU = LDA DW, CN = deblndw028v.ad001.siemens.net
verify return:1

That all looks fine.

Here are now my questions:

  1. Why has the hash option selected? D16352 uses the common approach to concat PEM files into one PEM bundle which can be easily transported and distributed.
  2. From D23352 I know that something is in preparation for base, how are those PEMs from Mozilla going to be added to this solution? Currently they reside in /usr/src/secure/caroot/ which cannot really be used.
  3. Is OpenSSL from base going to be changed for this? And from ports?
  4. What about ports pointing to security/ca_root_nss, e.g., curl? Since the installed
root@deblndw011x:/etc/ssl
# ll cert.pem
lrwxr-xr-x  1 root  wheel  27 2020-01-27 11:25 cert.pem@ -> /usr/local/etc/ssl/cert.pem

would be obsolete.

I am currently running off D16352 on hosts and on jails and would desperately like to see this being finally in the system.

  1. Are there already any thoughts on how to integrate this into Java's cacerts? At best they are completely in sync as soon as "certctl rehash" is run. See https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=229329

That all looks fine.

Here are now my questions:

  1. Why has the hash option selected? D16352 uses the common approach to concat PEM files into one PEM bundle which can be easily transported and distributed.

I wasn't initially involved in this decision, but I find it more convenient to manually manage or identify what's being trusted as-is, since I can ls/grep around /etc/ssl/certs.

  1. From D23352 I know that something is in preparation for base, how are those PEMs from Mozilla going to be added to this solution? Currently they reside in /usr/src/secure/caroot/ which cannot really be used.

These reviews have actually already been committed ~5/6 months ago. I'm not entirely sure I understand the question- the Mozilla bundle gets committed to ^/secure/caroot/trusted which gets installed to /usr/share/certs/trusted and certctl rehash pushes anything from /usr/share/certs/{blacklisted,trusted} and /usr/local/share/certs or /usr/local/etc/ssl/certs (this is somewhat inconsistent between the two branches of hier(7), which might get fixed soon -- I think share/certs should match the base layout so one could install their own internal cert pkg that may include org-wide blacklist).

  1. Is OpenSSL from base going to be changed for this? And from ports?

What changes do we think need to be made to OpenSSL?

  1. What about ports pointing to security/ca_root_nss, e.g., curl? Since the installed
root@deblndw011x:/etc/ssl
# ll cert.pem
lrwxr-xr-x  1 root  wheel  27 2020-01-27 11:25 cert.pem@ -> /usr/local/etc/ssl/cert.pem

would be obsolete.

I am currently running off D16352 on hosts and on jails and would desperately like to see this being finally in the system.

Yes, I've tried to engage ports-secteam and get the ETCSYMLINK option defaulted to OFF for 13, but I haven't had any luck yet.

  1. Are there already any thoughts on how to integrate this into Java's cacerts? At best they are completely in sync as soon as "certctl rehash" is run. See https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=229329

I've not looked at how Java does it, but judging from this PR I suspect the answer is that the Java port maintainer(s) should point cacerts at /etc/ssl/certs

That all looks fine.

Here are now my questions:

  1. Why has the hash option selected? D16352 uses the common approach to concat PEM files into one PEM bundle which can be easily transported and distributed.

I wasn't initially involved in this decision, but I find it more convenient to manually manage or identify what's being trusted as-is, since I can ls/grep around /etc/ssl/certs.

I think it is also manageable if you drop single PEMs into one dir and the certctl combines them into one PEM file with prependening

subject=/C=DE/ST=Bayern/L=Muenchen/O=Siemens/serialNumber=ZZZZZZB7/OU=Siemens Trust Center/CN=Siemens Issuing CA Intranet Server 2017
issuer=/C=DE/ST=Bayern/L=Muenchen/O=Siemens/serialNumber=ZZZZZZA1/OU=Siemens Trust Center/CN=Siemens Root CA V3.0 2016
extended key usage:
  Transport Layer Security (TLS) World Wide Web (WWW) server authentication (1.3.6.1.5.5.7.3.1)
  Transport Layer Security (TLS) World Wide Web (WWW) client authentication (1.3.6.1.5.5.7.3.2)
  Signing Online Certificate Status Protocol (OCSP) responses (1.3.6.1.5.5.7.3.9)

That's at least what I do with our PEM bundles. Still greppable.

  1. From D23352 I know that something is in preparation for base, how are those PEMs from Mozilla going to be added to this solution? Currently they reside in /usr/src/secure/caroot/ which cannot really be used.

These reviews have actually already been committed ~5/6 months ago. I'm not entirely sure I understand the question- the Mozilla bundle gets committed to ^/secure/caroot/trusted which gets installed to /usr/share/certs/trusted and certctl rehash pushes anything from /usr/share/certs/{blacklisted,trusted} and /usr/local/share/certs or /usr/local/etc/ssl/certs (this is somewhat inconsistent between the two branches of hier(7), which might get fixed soon -- I think share/certs should match the base layout so one could install their own internal cert pkg that may include org-wide blacklist).

Unfortunately, I wasn't aware of this back then :-(

I think you properly understood the question.

^/secure/caroot/trusted which gets installed to /usr/share/certs/trusted

Purely my bad. I completely forgot to perform

root@deblndw011x:/usr/src/secure/caroot
# make install

I need to see during next installworld whether files change.

  1. Is OpenSSL from base going to be changed for this? And from ports?

What changes do we think need to be made to OpenSSL?

Thanks for pointing out. Purely my bad here too. I did move /etc/ssl/cert.pem for test purposes. As soon as I did this, I saw in truss that /etc/ssl/certs/ is used. Brilliant.
I did not try OpenSSL from ports, but "openssl version -a" output should point OPENSSLDIR to /etc/ssl or something which is linked to the new canonical CApath.

  1. What about ports pointing to security/ca_root_nss, e.g., curl? Since the installed
root@deblndw011x:/etc/ssl
# ll cert.pem
lrwxr-xr-x  1 root  wheel  27 2020-01-27 11:25 cert.pem@ -> /usr/local/etc/ssl/cert.pem

would be obsolete.

I am currently running off D16352 on hosts and on jails and would desperately like to see this being finally in the system.

Yes, I've tried to engage ports-secteam and get the ETCSYMLINK option defaulted to OFF for 13, but I haven't had any luck yet.

That'd be quite important. curl's default compilation still insists on

* successfully set certificate verify locations:
*   CAfile: /usr/local/etc/ssl/cert.pem
  CApath: none
  1. Are there already any thoughts on how to integrate this into Java's cacerts? At best they are completely in sync as soon as "certctl rehash" is run. See https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=229329

I've not looked at how Java does it, but judging from this PR I suspect the answer is that the Java port maintainer(s) should point cacerts at /etc/ssl/certs

Java uses a custom keystore format JKS, the Java devs at Oracle pursue to move to PKCS12 as truststore, I have pursued to move to PEM format: https://mail.openjdk.java.net/pipermail/security-dev/2020-February/021305.html but it is on on low priority and Weijun Wang claims that Base 64 poses an overhead during parsing that file. Even if introduced, it would be still incompatible with the hash approach. At the end someone needs to import those hashed PEMs into a keystore. The problem is even if Greg Hudson adds this ot the Java port, it has to be run for cacerts on each and every invocation of "certctl rehash". Look at D16352, it tries for Java and then rebuilds the cacerts file.

As far as I can see when certs in are in base security/ca_root_nss seems to be obsolete for me, these ports need to be changed:

# grep -r --include='**/Makefile*' security/ca_root_nss .
./lang/mono/Makefile:           ca_root_nss>=0:security/ca_root_nss
./textproc/py-sphinx/Makefile:          ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./textproc/py-asciinema/Makefile:RUN_DEPENDS=   ca_root_nss>=0:security/ca_root_nss
./devel/qca/Makefile:BUILD_DEPENDS=     ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./devel/qca/Makefile:RUN_DEPENDS=       ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./devel/php-composer/Makefile:RUN_DEPENDS=      ca_root_nss>0:security/ca_root_nss
./devel/gitlab-runner/Makefile:         ca_root_nss>=0:security/ca_root_nss \
./devel/mercurial/Makefile:CA_BUNDLE_RUN_DEPENDS=       ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./devel/brz/Makefile:CA_BUNDLE_RUN_DEPENDS=     ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./devel/py-libiocage/Makefile:          ca_root_nss>0:security/ca_root_nss \
./devel/osc/Makefile:CA_BUNDLE_RUN_DEPENDS=     ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./devel/bzr/Makefile:CA_BUNDLE_RUN_DEPENDS=     ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./devel/hs-hoogle/Makefile:RUN_DEPENDS= ca_root_nss>=0:security/ca_root_nss
./devel/stack/Makefile:RUN_DEPENDS=     ca_root_nss>0:security/ca_root_nss \
./devel/librest/Makefile:BUILD_DEPENDS= ca_root_nss>0:security/ca_root_nss
./devel/hs-spago/Makefile:RUN_DEPENDS=  ca_root_nss>0:security/ca_root_nss
./devel/py-libioc/Makefile:             ca_root_nss>0:security/ca_root_nss \
./security/py-volatility3/Makefile:RUN_DEPENDS= ca_root_nss>=0:security/ca_root_nss \
./security/gnome-keyring/Makefile:BUILD_DEPENDS=        ca_root_nss>=0:security/ca_root_nss \
./security/gnome-keyring/Makefile:RUN_DEPENDS=  ca_root_nss>=0:security/ca_root_nss \
./security/ca_root_nss/Makefile:# $FreeBSD: head/security/ca_root_nss/Makefile 524147 2020-01-26 00:20:01Z jbeich $
./security/go-cve-dictionary/Makefile:RUN_DEPENDS=      ca_root_nss>=0:security/ca_root_nss
./security/gnutls/Makefile:RUN_DEPENDS= ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./security/py-openssl/Makefile:         ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./security/py-plaso/Makefile:           ca_root_nss>=0:security/ca_root_nss
./security/py-dfvfs/Makefile:           ca_root_nss>=0:security/ca_root_nss
./security/p11-kit/Makefile:RUN_DEPENDS=        ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./security/p11-kit/Makefile:BUILD_DEPENDS=      ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./security/protonvpn-cli/Makefile:              ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./security/lego/Makefile:RUN_DEPENDS=   ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./security/pulledpork/Makefile:         ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./security/ssllabs-scan/Makefile:RUN_DEPENDS=   ca_root_nss>=0:security/ca_root_nss
./sysutils/iocage-devel/Makefile:               ca_root_nss>0:security/ca_root_nss \
./sysutils/osquery/Makefile:RUN_DEPENDS=        ca_root_nss>0:security/ca_root_nss
./sysutils/iocage/Makefile:             ca_root_nss>0:security/ca_root_nss \
./sysutils/cbsd/Makefile:               ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./sysutils/vagrant/Makefile:            ca_root_nss>=0:security/ca_root_nss \
./sysutils/minipot/Makefile:CACERTS_RUN_DEPENDS=        ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./sysutils/cinnamon-control-center/Makefile:BUILD_DEPENDS=      ca_root_nss>=0:security/ca_root_nss \
./sysutils/cinnamon-control-center/Makefile:            ca_root_nss>=0:security/ca_root_nss \
./sysutils/ucspi-ssl/Makefile:          ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./sysutils/vm-bhyve/Makefile:RUN_DEPENDS=       ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./sysutils/azure-agent/Makefile:                ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./sysutils/amazon-ssm-agent/Makefile:RUN_DEPENDS=       ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./multimedia/mps-youtube/Makefile:RUN_DEPENDS=  ca_root_nss>=3.17.3:security/ca_root_nss \
./multimedia/tautulli/Makefile:         ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./net/qt5-network/Makefile:RUN_DEPENDS= ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./net/boinc-client/Makefile:CLIENT_RUN_DEPENDS= ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./net/glib-networking/Makefile:BUILD_DEPENDS=   ca_root_nss>=0:security/ca_root_nss \
./net/glib-networking/Makefile:RUN_DEPENDS=     ca_root_nss>=0:security/ca_root_nss \
./net/mosquitto/Makefile:RUN_DEPENDS=   ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./net/rubygem-grpc/Makefile:RUN_DEPENDS=        ca_root_nss>=0:security/ca_root_nss \
./net/rubygem-grpc124/Makefile:RUN_DEPENDS=     ca_root_nss>=0:security/ca_root_nss \
./net/geoipupdate/Makefile:RUN_DEPENDS= ca_root_nss>=3:security/ca_root_nss
./net/openntpd/Makefile:RUN_DEPENDS=    ca_root_nss>=0:security/ca_root_nss
./net/bsdec2-image-upload/Makefile:RUN_DEPENDS= ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./net/s3ql/Makefile:            ca_root_nss>=0:security/ca_root_nss
./net/measurement-kit/Makefile:RUN_DEPENDS=     ca_root_nss>=0:security/ca_root_nss
./net/cloudflared/Makefile:RUN_DEPENDS= ca_root_nss>=0:security/ca_root_nss
./www/aria2/Makefile:CA_BUNDLE_RUN_DEPENDS=     ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./www/miniflux/Makefile:RUN_DEPENDS=    ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./www/node/Makefile:BUNDLED_SSL_RUN_DEPENDS_OFF=        ca_root_nss>=0:security/ca_root_nss
./www/node10/Makefile:BUNDLED_SSL_RUN_DEPENDS_OFF=      ca_root_nss>=0:security/ca_root_nss
./www/node12/Makefile:BUNDLED_SSL_RUN_DEPENDS_OFF=      ca_root_nss>=0:security/ca_root_nss
./www/node8/Makefile:BUNDLED_SSL_RUN_DEPENDS_OFF=       ca_root_nss>=0:security/ca_root_nss
./www/cliqz/Makefile:FETCH_DEPENDS=     ca_root_nss>=0:security/ca_root_nss
./www/py-weboob/Makefile:NSS_RUN_DEPENDS=       ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss \
./www/mattermost-server/Makefile:RUN_DEPENDS=   ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss \
./www/neon/Makefile:CA_BUNDLE_RUN_DEPENDS=      ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./www/netsurf/Makefile:         ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./www/gist/Makefile:RUN_DEPENDS=        ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./www/ffsend/Makefile:RUN_DEPENDS=      ca_root_nss>0:security/ca_root_nss \
./www/caddy/Makefile:RUN_DEPENDS=       ca_root_nss>=0:security/ca_root_nss
./www/midori/Makefile:RUN_DEPENDS=      ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./graphics/variety/Makefile:            ca_root_nss>=3.17.4:security/ca_root_nss \
./net-mgmt/netmagis-database/Makefile:          ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./net-mgmt/netmagis-www/Makefile:               ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./dns/void-zones-tools/Makefile:RUN_DEPENDS=    ca_root_nss>0:security/ca_root_nss
./dns/dnscrypt-proxy2/Makefile:RUN_DEPENDS=     ca_root_nss>=3.35:security/ca_root_nss
./dns/ddclient/Makefile:SSL_RUN_DEPENDS=ca_root_nss>0:security/ca_root_nss \
./dns/nextdns/Makefile:RUN_DEPENDS=     ca_root_nss>=3.35:security/ca_root_nss
./dns/libasr-devel/Makefile:CA_BUNDLE_RUN_DEPENDS=      ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./dns/libasr/Makefile:CA_BUNDLE_RUN_DEPENDS=    ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./mail/rspamd/Makefile:RUN_DEPENDS=     ca_root_nss>=3.*:security/ca_root_nss
./mail/rspamd-devel/Makefile:RUN_DEPENDS=       ca_root_nss>=3.*:security/ca_root_nss
./mail/msmtp/Makefile:RUN_DEPENDS+=     ${CERTSFILE}:security/ca_root_nss
./mail/fetchmail/Makefile:RUN_DEPENDS=  ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./mail/opensmtpd/Makefile:CA_BUNDLE_RUN_DEPENDS=        ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./mail/opensmtpd-devel/Makefile:CA_BUNDLE_RUN_DEPENDS=          ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./mail/courier/Makefile:                ca_root_nss>=3.*:security/ca_root_nss
./mail/sylpheed/Makefile:CA_BUNDLE_RUN_DEPENDS=         ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./mail/py-postfix-mta-sts-resolver/Makefile:            ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./audio/teamspeak3-server/Makefile:RUN_DEPENDS= ca_root_nss>=0:security/ca_root_nss
./x11/cinnamon/Makefile:BUILD_DEPENDS=  ca_root_nss>=0:security/ca_root_nss \
./x11/cinnamon/Makefile:                ca_root_nss>=0:security/ca_root_nss \
./net-im/py-matrix-synapse/Makefile:            ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./net-im/empathy/Makefile:              ca_root_nss>=0:security/ca_root_nss \
./net-im/empathy/Makefile:              ca_root_nss>=0:security/ca_root_nss \
./net-im/telepathy-gabble/Makefile:             ca_root_nss>=0:security/ca_root_nss
./net-im/telepathy-gabble/Makefile:RUN_DEPENDS= ca_root_nss>=0:security/ca_root_nss \
./net-im/loudmouth/Makefile:RUN_DEPENDS+=       ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./irc/hexchat/Makefile:CA_BUNDLE_RUN_DEPENDS=   ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./irc/weechat/Makefile:CA_BUNDLE_RUN_DEPENDS=   ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./irc/ircd-hybrid/Makefile:RUN_DEPENDS+=        ${CERTSFILE}:security/ca_root_nss
./ports-mgmt/poudriere-devel/Makefile:CERTS_RUN_DEPENDS+=       ca_root_nss>=0:security/ca_root_nss
./ports-mgmt/poudriere/Makefile:CERTS_RUN_DEPENDS+=     ca_root_nss>=0:security/ca_root_nss
./ports-mgmt/freebsd-bugzilla-cli/Makefile:RUN_DEPENDS= ca_root_nss>=0:security/ca_root_nss
./ftp/curl/Makefile:CA_BUNDLE_RUN_DEPENDS=      ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./ftp/curl/Makefile.orig:CA_BUNDLE_RUN_DEPENDS= ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
./ftp/curl/Makefile~:CA_BUNDLE_RUN_DEPENDS=     ${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss

As for curl, recompiling it w/o the CA_BUNDLE option gives:

* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs/

As far as I can see when certs in are in base security/ca_root_nss seems to be obsolete for me, these ports need to be changed:

Turning off the CA_BUNDLE option in many of these ports should just be fine if they use OpenSSL.

Ports with a fixed dependency on security/ca_root_nss can be turned into an optional CA_BUNDLE dependency easily, for example fetchmail.

That all looks fine.

Here are now my questions:

  1. Why has the hash option selected? D16352 uses the common approach to concat PEM files into one PEM bundle which can be easily transported and distributed.

I wasn't initially involved in this decision, but I find it more convenient to manually manage or identify what's being trusted as-is, since I can ls/grep around /etc/ssl/certs.

And of course it's a bit faster to just use the certificate hash as a selector into the file system instead of searching through a longish text file for a matching CA.

FWIW, sendmail (for example) has been expecting this since a long time.

That all looks fine.

Here are now my questions:

  1. Why has the hash option selected? D16352 uses the common approach to concat PEM files into one PEM bundle which can be easily transported and distributed.

I wasn't initially involved in this decision, but I find it more convenient to manually manage or identify what's being trusted as-is, since I can ls/grep around /etc/ssl/certs.

And of course it's a bit faster to just use the certificate hash as a selector into the file system instead of searching through a longish text file for a matching CA.

FWIW, sendmail (for example) has been expecting this since a long time.

This makes sense. I have also 167 of them. A waste of cycles for three chained CAs at the end.

Can someone tell me when this will land in RELEASE? I have jails running on 12.1-RELASE and can see that it is in STABLE only. 12.2-RELEASE?

Can someone tell me when this will land in RELEASE? I have jails running on 12.1-RELASE and can see that it is in STABLE only. 12.2-RELEASE?

Tentatively, the infrastructure has all been MFC'd to stable branches without any certs committed. I'm holding off on committing any certs to stable branches until I can test my freebsd-update addition in D21805 which seems to be requiring a little bit of a battle with freebsd-update-server.

Assuming I can figure that out in the next ~6-7 months, I'd like to ship 12.2-RELEASE with a bundle included. Since the original bundle was committed, we haven't had any that needed to be removed... I suspect that class of issue comes far enough apart that issuing SA for these just won't happen all that frequently.

Can someone tell me when this will land in RELEASE? I have jails running on 12.1-RELASE and can see that it is in STABLE only. 12.2-RELEASE?

Tentatively, the infrastructure has all been MFC'd to stable branches without any certs committed. I'm holding off on committing any certs to stable branches until I can test my freebsd-update addition in D21805 which seems to be requiring a little bit of a battle with freebsd-update-server.

Assuming I can figure that out in the next ~6-7 months, I'd like to ship 12.2-RELEASE with a bundle included. Since the original bundle was committed, we haven't had any that needed to be removed... I suspect that class of issue comes far enough apart that issuing SA for these just won't happen all that frequently.

This sounds great. If you need someone who can test with additional certs, please let me know. I will live with the patch in /usr/ports for security/ca_root_nss for now.

Trying to re-close it; following up on the issues presented separately.