nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at devShellTools-shell 260 lines 9.0 kB view raw
1{ 2 lib, 3 stdenv, 4 writeText, 5 fetchFromGitHub, 6 buildcatrust, 7 blacklist ? [ ], 8 extraCertificateFiles ? [ ], 9 extraCertificateStrings ? [ ], 10 11 # Used by update.sh 12 nssOverride ? null, 13 14 # Used for tests only 15 runCommand, 16 cacert, 17 openssl, 18}: 19 20let 21 blocklist = writeText "cacert-blocklist.txt" (lib.concatStringsSep "\n" blacklist); 22 extraCertificatesBundle = writeText "cacert-extra-certificates-bundle.crt" ( 23 lib.concatStringsSep "\n\n" extraCertificateStrings 24 ); 25 26 srcVersion = "3.113.1"; 27 version = if nssOverride != null then nssOverride.version else srcVersion; 28 meta = with lib; { 29 homepage = "https://curl.haxx.se/docs/caextract.html"; 30 description = "Bundle of X.509 certificates of public Certificate Authorities (CA)"; 31 platforms = platforms.all; 32 maintainers = with maintainers; [ 33 fpletz 34 lukegb 35 ]; 36 license = licenses.mpl20; 37 }; 38 certdata = stdenv.mkDerivation { 39 pname = "nss-cacert-certdata"; 40 inherit version; 41 42 src = 43 if nssOverride != null then 44 nssOverride.src 45 else 46 fetchFromGitHub { 47 owner = "nss-dev"; 48 repo = "nss"; 49 rev = "NSS_${lib.replaceStrings [ "." ] [ "_" ] version}_RTM"; 50 hash = "sha256-Yfs9Hh98ASJe1D4qyQEXaTC2xjeDI2Cdxp5Xgy0rYdQ="; 51 }; 52 53 dontBuild = true; 54 55 installPhase = '' 56 runHook preInstall 57 58 mkdir $out 59 cp lib/ckfw/builtins/certdata.txt $out 60 61 runHook postInstall 62 ''; 63 64 inherit meta; 65 }; 66in 67stdenv.mkDerivation { 68 pname = "nss-cacert"; 69 inherit version; 70 71 src = certdata; 72 73 outputs = [ 74 "out" 75 "unbundled" 76 "p11kit" 77 "hashed" 78 ]; 79 80 nativeBuildInputs = [ buildcatrust ]; 81 82 buildPhase = '' 83 mkdir unbundled hashed 84 buildcatrust \ 85 --certdata_input certdata.txt \ 86 --ca_bundle_input "${extraCertificatesBundle}" ${ 87 lib.escapeShellArgs (map (arg: "${arg}") extraCertificateFiles) 88 } \ 89 --blocklist "${blocklist}" \ 90 --ca_bundle_output ca-bundle.crt \ 91 --ca_standard_bundle_output ca-no-trust-rules-bundle.crt \ 92 --ca_unpacked_output unbundled \ 93 --ca_hashed_unpacked_output hashed \ 94 --p11kit_output ca-bundle.trust.p11-kit 95 ''; 96 97 installPhase = '' 98 install -D -t "$out/etc/ssl/certs" ca-bundle.crt 99 100 # install standard PEM compatible bundle 101 install -D -t "$out/etc/ssl/certs" ca-no-trust-rules-bundle.crt 102 103 # install p11-kit specific output to p11kit output 104 install -D -t "$p11kit/etc/ssl/trust-source" ca-bundle.trust.p11-kit 105 106 # install individual certs in unbundled output 107 install -D -t "$unbundled/etc/ssl/certs" unbundled/*.crt 108 109 # install hashed certs in hashed output 110 # use cp as install doesn't copy symlinks 111 mkdir -p $hashed/etc/ssl/certs/ 112 cp -P hashed/* $hashed/etc/ssl/certs/ 113 ''; 114 115 setupHook = ./setup-hook.sh; 116 117 passthru = { 118 updateScript = ./update.sh; 119 tests = 120 let 121 isTrusted = '' 122 isTrusted() { 123 # isTrusted <unbundled-dir> <ca name> <ca sha256 fingerprint> 124 for f in $1/etc/ssl/certs/*.crt; do 125 if ! [[ -s "$f" ]]; then continue; fi 126 fingerprint="$(openssl x509 -in "$f" -noout -fingerprint -sha256 | cut -f2 -d=)" 127 if [[ "x$fingerprint" == "x$3" ]]; then 128 # If the certificate is treated as rejected for TLS Web Server, then we consider it untrusted. 129 if openssl x509 -in "$f" -noout -text | grep -q '^Rejected Uses:'; then 130 if openssl x509 -in "$f" -noout -text | grep -A1 '^Rejected Uses:' | grep -q 'TLS Web Server'; then 131 return 1 132 fi 133 fi 134 return 0 135 fi 136 done 137 return 1 138 } 139 ''; 140 in 141 { 142 # Test that building this derivation with a blacklist works, and that UTF-8 is supported. 143 blacklist-utf8 = 144 let 145 blacklistCAToFingerprint = { 146 # "blacklist" uses the CA name from the NSS bundle, but we check for presence using the SHA256 fingerprint. 147 "CFCA EV ROOT" = 148 "5C:C3:D7:8E:4E:1D:5E:45:54:7A:04:E6:87:3E:64:F9:0C:F9:53:6D:1C:CC:2E:F8:00:F3:55:C4:C5:FD:70:FD"; 149 "NetLock Arany (Class Gold) Főtanúsítvány" = 150 "6C:61:DA:C3:A2:DE:F0:31:50:6B:E0:36:D2:A6:FE:40:19:94:FB:D1:3D:F9:C8:D4:66:59:92:74:C4:46:EC:98"; 151 }; 152 mapBlacklist = f: lib.concatStringsSep "\n" (lib.mapAttrsToList f blacklistCAToFingerprint); 153 in 154 runCommand "verify-the-cacert-filter-output" 155 { 156 cacert = cacert.unbundled; 157 cacertWithExcludes = 158 (cacert.override { 159 blacklist = builtins.attrNames blacklistCAToFingerprint; 160 }).unbundled; 161 162 nativeBuildInputs = [ openssl ]; 163 } 164 '' 165 ${isTrusted} 166 167 # Ensure that each certificate is in the main "cacert". 168 ${mapBlacklist ( 169 caName: caFingerprint: '' 170 isTrusted "$cacert" "${caName}" "${caFingerprint}" || ({ 171 echo "CA fingerprint ${caFingerprint} (${caName}) is missing from the CA bundle. Consider picking a different CA for the blacklist test." >&2 172 exit 1 173 }) 174 '' 175 )} 176 177 # Ensure that each certificate is NOT in the "cacertWithExcludes". 178 ${mapBlacklist ( 179 caName: caFingerprint: '' 180 isTrusted "$cacertWithExcludes" "${caName}" "${caFingerprint}" && ({ 181 echo "CA fingerprint ${caFingerprint} (${caName}) is present in the cacertWithExcludes bundle." >&2 182 exit 1 183 }) 184 '' 185 )} 186 187 touch "$out" 188 ''; 189 190 # Test that we can add additional certificates to the store, and have them be trusted. 191 extra-certificates = 192 let 193 extraCertificateStr = '' 194 -----BEGIN CERTIFICATE----- 195 MIIB5DCCAWqgAwIBAgIUItvsAYEIdYDkOIo5sdDYMcUaNuIwCgYIKoZIzj0EAwIw 196 KTEnMCUGA1UEAwweTml4T1MgY2FjZXJ0IGV4dHJhIGNlcnRpZmljYXRlMB4XDTIx 197 MDYxMjE5MDQzMFoXDTIyMDYxMjE5MDQzMFowKTEnMCUGA1UEAwweTml4T1MgY2Fj 198 ZXJ0IGV4dHJhIGNlcnRpZmljYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEuP8y 199 lAm6ZyQt9v/P6gTlV/a9R+D61WjucW04kaegOhg8csiluimYodiSv0Pbgymu+Zxm 200 A3Bz9QGmytaYTiJ16083rJkwwIhqoYl7kWsLzreSTaLz87KH+rdeol59+H0Oo1Mw 201 UTAdBgNVHQ4EFgQUCxuHfvqI4YVU5M+A0+aKvd1LrdswHwYDVR0jBBgwFoAUCxuH 202 fvqI4YVU5M+A0+aKvd1LrdswDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNo 203 ADBlAjEArgxgjdNmRlSEuai0dzlktmBEDZKy2Iiul+ttSoce9ohfEVYESwO602HW 204 keVvI56vAjBCro3dc3m2TuktiKO6lQV56PUEyxko4H/sR5pnHlduCGRDlFzQKXf/ 205 pMMmtj7cVb8= 206 -----END CERTIFICATE----- 207 ''; 208 extraCertificateFile = ./test-cert-file.crt; 209 extraCertificatesToFingerprint = { 210 # String above 211 "NixOS cacert extra certificate string" = 212 "A3:20:D0:84:96:97:25:FF:98:B8:A9:6D:A3:7C:89:95:6E:7A:77:21:92:F3:33:E9:31:AF:5E:03:CE:A9:E5:EE"; 213 214 # File 215 "NixOS cacert extra certificate file" = 216 "88:B8:BE:A7:57:AC:F1:FE:D6:98:8B:50:E0:BD:0A:AE:88:C7:DF:70:26:E1:67:5E:F5:F6:91:27:FF:02:D4:A5"; 217 }; 218 mapExtra = f: lib.concatStringsSep "\n" (lib.mapAttrsToList f extraCertificatesToFingerprint); 219 in 220 runCommand "verify-the-cacert-extra-output" 221 { 222 cacert = cacert.unbundled; 223 cacertWithExtras = 224 (cacert.override { 225 extraCertificateStrings = [ extraCertificateStr ]; 226 extraCertificateFiles = [ extraCertificateFile ]; 227 }).unbundled; 228 229 nativeBuildInputs = [ openssl ]; 230 } 231 '' 232 ${isTrusted} 233 234 # Ensure that the extra certificate is not in the main "cacert". 235 ${mapExtra ( 236 extraName: extraFingerprint: '' 237 isTrusted "$cacert" "${extraName}" "${extraFingerprint}" && ({ 238 echo "'extra' CA fingerprint ${extraFingerprint} (${extraName}) is present in the main CA bundle." >&2 239 exit 1 240 }) 241 '' 242 )} 243 244 # Ensure that the extra certificates ARE in the "cacertWithExtras". 245 ${mapExtra ( 246 extraName: extraFingerprint: '' 247 isTrusted "$cacertWithExtras" "${extraName}" "${extraFingerprint}" || ({ 248 echo "CA fingerprint ${extraFingerprint} (${extraName}) is not present in the cacertWithExtras bundle." >&2 249 exit 1 250 }) 251 '' 252 )} 253 254 touch "$out" 255 ''; 256 }; 257 }; 258 259 inherit meta; 260}