11cb0ef41Sopenharmony_ci#!/usr/bin/perl -w
21cb0ef41Sopenharmony_ci# ***************************************************************************
31cb0ef41Sopenharmony_ci# *                                  _   _ ____  _
41cb0ef41Sopenharmony_ci# *  Project                     ___| | | |  _ \| |
51cb0ef41Sopenharmony_ci# *                             / __| | | | |_) | |
61cb0ef41Sopenharmony_ci# *                            | (__| |_| |  _ <| |___
71cb0ef41Sopenharmony_ci# *                             \___|\___/|_| \_\_____|
81cb0ef41Sopenharmony_ci# *
91cb0ef41Sopenharmony_ci# * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
101cb0ef41Sopenharmony_ci# *
111cb0ef41Sopenharmony_ci# * This software is licensed as described in the file COPYING, which
121cb0ef41Sopenharmony_ci# * you should have received as part of this distribution. The terms
131cb0ef41Sopenharmony_ci# * are also available at http://curl.haxx.se/docs/copyright.html.
141cb0ef41Sopenharmony_ci# *
151cb0ef41Sopenharmony_ci# * You may opt to use, copy, modify, merge, publish, distribute and/or sell
161cb0ef41Sopenharmony_ci# * copies of the Software, and permit persons to whom the Software is
171cb0ef41Sopenharmony_ci# * furnished to do so, under the terms of the COPYING file.
181cb0ef41Sopenharmony_ci# *
191cb0ef41Sopenharmony_ci# * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
201cb0ef41Sopenharmony_ci# * KIND, either express or implied.
211cb0ef41Sopenharmony_ci# *
221cb0ef41Sopenharmony_ci# ***************************************************************************
231cb0ef41Sopenharmony_ci# This Perl script creates a fresh ca-bundle.crt file for use with libcurl.
241cb0ef41Sopenharmony_ci# It downloads certdata.txt from Mozilla's source tree (see URL below),
251cb0ef41Sopenharmony_ci# then parses certdata.txt and extracts CA Root Certificates into PEM format.
261cb0ef41Sopenharmony_ci# These are then processed with the OpenSSL commandline tool to produce the
271cb0ef41Sopenharmony_ci# final ca-bundle.crt file.
281cb0ef41Sopenharmony_ci# The script is based on the parse-certs script written by Roland Krikava.
291cb0ef41Sopenharmony_ci# This Perl script works on almost any platform since its only external
301cb0ef41Sopenharmony_ci# dependency is the OpenSSL commandline tool for optional text listing.
311cb0ef41Sopenharmony_ci# Hacked by Guenter Knauf.
321cb0ef41Sopenharmony_ci#
331cb0ef41Sopenharmony_ciuse File::Basename 'dirname';
341cb0ef41Sopenharmony_ciuse Getopt::Std;
351cb0ef41Sopenharmony_ciuse MIME::Base64;
361cb0ef41Sopenharmony_ciuse strict;
371cb0ef41Sopenharmony_ciuse vars qw($opt_h $opt_i $opt_l $opt_p $opt_q $opt_s $opt_t $opt_v $opt_w);
381cb0ef41Sopenharmony_ciuse List::Util;
391cb0ef41Sopenharmony_ciuse Text::Wrap;
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci# If the OpenSSL commandline is not in search path you can configure it here!
421cb0ef41Sopenharmony_cimy $openssl = 'openssl';
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_cimy $version = '1.25';
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci$opt_w = 72; # default base64 encoded lines length
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci# default cert types to include in the output (default is to include CAs which may issue SSL server certs)
491cb0ef41Sopenharmony_cimy $default_mozilla_trust_purposes = "SERVER_AUTH";
501cb0ef41Sopenharmony_cimy $default_mozilla_trust_levels = "TRUSTED_DELEGATOR";
511cb0ef41Sopenharmony_ci$opt_p = $default_mozilla_trust_purposes . ":" . $default_mozilla_trust_levels;
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_cimy @valid_mozilla_trust_purposes = (
541cb0ef41Sopenharmony_ci  "DIGITAL_SIGNATURE",
551cb0ef41Sopenharmony_ci  "NON_REPUDIATION",
561cb0ef41Sopenharmony_ci  "KEY_ENCIPHERMENT",
571cb0ef41Sopenharmony_ci  "DATA_ENCIPHERMENT",
581cb0ef41Sopenharmony_ci  "KEY_AGREEMENT",
591cb0ef41Sopenharmony_ci  "KEY_CERT_SIGN",
601cb0ef41Sopenharmony_ci  "CRL_SIGN",
611cb0ef41Sopenharmony_ci  "SERVER_AUTH",
621cb0ef41Sopenharmony_ci  "CLIENT_AUTH",
631cb0ef41Sopenharmony_ci  "CODE_SIGNING",
641cb0ef41Sopenharmony_ci  "EMAIL_PROTECTION",
651cb0ef41Sopenharmony_ci  "IPSEC_END_SYSTEM",
661cb0ef41Sopenharmony_ci  "IPSEC_TUNNEL",
671cb0ef41Sopenharmony_ci  "IPSEC_USER",
681cb0ef41Sopenharmony_ci  "TIME_STAMPING",
691cb0ef41Sopenharmony_ci  "STEP_UP_APPROVED"
701cb0ef41Sopenharmony_ci);
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_cimy @valid_mozilla_trust_levels = (
731cb0ef41Sopenharmony_ci  "TRUSTED_DELEGATOR",    # CAs
741cb0ef41Sopenharmony_ci  "NOT_TRUSTED",          # Don't trust these certs.
751cb0ef41Sopenharmony_ci  "MUST_VERIFY_TRUST",    # This explicitly tells us that it ISN'T a CA but is otherwise ok. In other words, this should tell the app to ignore any other sources that claim this is a CA.
761cb0ef41Sopenharmony_ci  "TRUSTED"               # This cert is trusted, but only for itself and not for delegates (i.e. it is not a CA).
771cb0ef41Sopenharmony_ci);
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_cimy $default_signature_algorithms = $opt_s = "MD5";
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_cimy @valid_signature_algorithms = (
821cb0ef41Sopenharmony_ci  "MD5",
831cb0ef41Sopenharmony_ci  "SHA1",
841cb0ef41Sopenharmony_ci  "SHA256",
851cb0ef41Sopenharmony_ci  "SHA384",
861cb0ef41Sopenharmony_ci  "SHA512"
871cb0ef41Sopenharmony_ci);
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci$0 =~ s@.*(/|\\)@@;
901cb0ef41Sopenharmony_ci$Getopt::Std::STANDARD_HELP_VERSION = 1;
911cb0ef41Sopenharmony_cigetopts('bd:fhilnp:qs:tuvw:');
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ciif ($opt_i) {
941cb0ef41Sopenharmony_ci  print ("=" x 78 . "\n");
951cb0ef41Sopenharmony_ci  print "Script Version                   : $version\n";
961cb0ef41Sopenharmony_ci  print "Perl Version                     : $]\n";
971cb0ef41Sopenharmony_ci  print "Operating System Name            : $^O\n";
981cb0ef41Sopenharmony_ci  print "Getopt::Std.pm Version           : ${Getopt::Std::VERSION}\n";
991cb0ef41Sopenharmony_ci  print "MIME::Base64.pm Version          : ${MIME::Base64::VERSION}\n";
1001cb0ef41Sopenharmony_ci  print ("=" x 78 . "\n");
1011cb0ef41Sopenharmony_ci}
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_cisub HELP_MESSAGE() {
1041cb0ef41Sopenharmony_ci  print "Usage:\t${0} [-i] [-l] [-p<purposes:levels>] [-q] [-s<algorithms>] [-t] [-v] [-w<l>] [<outputfile>]\n";
1051cb0ef41Sopenharmony_ci  print "\t-i\tprint version info about used modules\n";
1061cb0ef41Sopenharmony_ci  print "\t-l\tprint license info about certdata.txt\n";
1071cb0ef41Sopenharmony_ci  print wrap("\t","\t\t", "-p\tlist of Mozilla trust purposes and levels for certificates to include in output. Takes the form of a comma separated list of purposes, a colon, and a comma separated list of levels. (default: $default_mozilla_trust_purposes:$default_mozilla_trust_levels)"), "\n";
1081cb0ef41Sopenharmony_ci  print "\t\t  Valid purposes are:\n";
1091cb0ef41Sopenharmony_ci  print wrap("\t\t    ","\t\t    ", join( ", ", "ALL", @valid_mozilla_trust_purposes ) ), "\n";
1101cb0ef41Sopenharmony_ci  print "\t\t  Valid levels are:\n";
1111cb0ef41Sopenharmony_ci  print wrap("\t\t    ","\t\t    ", join( ", ", "ALL", @valid_mozilla_trust_levels ) ), "\n";
1121cb0ef41Sopenharmony_ci  print "\t-q\tbe really quiet (no progress output at all)\n";
1131cb0ef41Sopenharmony_ci  print wrap("\t","\t\t", "-s\tcomma separated list of certificate signatures/hashes to output in plain text mode. (default: $default_signature_algorithms)\n");
1141cb0ef41Sopenharmony_ci  print "\t\t  Valid signature algorithms are:\n";
1151cb0ef41Sopenharmony_ci  print wrap("\t\t    ","\t\t    ", join( ", ", "ALL", @valid_signature_algorithms ) ), "\n";
1161cb0ef41Sopenharmony_ci  print "\t-t\tinclude plain text listing of certificates\n";
1171cb0ef41Sopenharmony_ci  print "\t-v\tbe verbose and print out processed CAs\n";
1181cb0ef41Sopenharmony_ci  print "\t-w <l>\twrap base64 output lines after <l> chars (default: ${opt_w})\n";
1191cb0ef41Sopenharmony_ci  exit;
1201cb0ef41Sopenharmony_ci}
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_cisub VERSION_MESSAGE() {
1231cb0ef41Sopenharmony_ci  print "${0} version ${version} running Perl ${]} on ${^O}\n";
1241cb0ef41Sopenharmony_ci}
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ciHELP_MESSAGE() if ($opt_h);
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_cisub report($@) {
1291cb0ef41Sopenharmony_ci  my $output = shift;
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  print STDERR $output . "\n" unless $opt_q;
1321cb0ef41Sopenharmony_ci}
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_cisub is_in_list($@) {
1351cb0ef41Sopenharmony_ci  my $target = shift;
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  return defined(List::Util::first { $target eq $_ } @_);
1381cb0ef41Sopenharmony_ci}
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci# Parses $param_string as a case insensitive comma separated list with optional whitespace
1411cb0ef41Sopenharmony_ci# validates that only allowed parameters are supplied
1421cb0ef41Sopenharmony_cisub parse_csv_param($$@) {
1431cb0ef41Sopenharmony_ci  my $description = shift;
1441cb0ef41Sopenharmony_ci  my $param_string = shift;
1451cb0ef41Sopenharmony_ci  my @valid_values = @_;
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci  my @values = map {
1481cb0ef41Sopenharmony_ci    s/^\s+//;  # strip leading spaces
1491cb0ef41Sopenharmony_ci    s/\s+$//;  # strip trailing spaces
1501cb0ef41Sopenharmony_ci    uc $_      # return the modified string as upper case
1511cb0ef41Sopenharmony_ci  } split( ',', $param_string );
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  # Find all values which are not in the list of valid values or "ALL"
1541cb0ef41Sopenharmony_ci  my @invalid = grep { !is_in_list($_,"ALL",@valid_values) } @values;
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci  if ( scalar(@invalid) > 0 ) {
1571cb0ef41Sopenharmony_ci    # Tell the user which parameters were invalid and print the standard help message which will exit
1581cb0ef41Sopenharmony_ci    print "Error: Invalid ", $description, scalar(@invalid) == 1 ? ": " : "s: ", join( ", ", map { "\"$_\"" } @invalid ), "\n";
1591cb0ef41Sopenharmony_ci    HELP_MESSAGE();
1601cb0ef41Sopenharmony_ci  }
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  @values = @valid_values if ( is_in_list("ALL",@values) );
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  return @values;
1651cb0ef41Sopenharmony_ci}
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ciif ( $opt_p !~ m/:/ ) {
1681cb0ef41Sopenharmony_ci  print "Error: Mozilla trust identifier list must include both purposes and levels\n";
1691cb0ef41Sopenharmony_ci  HELP_MESSAGE();
1701cb0ef41Sopenharmony_ci}
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci(my $included_mozilla_trust_purposes_string, my $included_mozilla_trust_levels_string) = split( ':', $opt_p );
1731cb0ef41Sopenharmony_cimy @included_mozilla_trust_purposes = parse_csv_param( "trust purpose", $included_mozilla_trust_purposes_string, @valid_mozilla_trust_purposes );
1741cb0ef41Sopenharmony_cimy @included_mozilla_trust_levels = parse_csv_param( "trust level", $included_mozilla_trust_levels_string, @valid_mozilla_trust_levels );
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_cimy @included_signature_algorithms = parse_csv_param( "signature algorithm", $opt_s, @valid_signature_algorithms );
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_cisub should_output_cert(%) {
1791cb0ef41Sopenharmony_ci  my %trust_purposes_by_level = @_;
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci  foreach my $level (@included_mozilla_trust_levels) {
1821cb0ef41Sopenharmony_ci    # for each level we want to output, see if any of our desired purposes are included
1831cb0ef41Sopenharmony_ci    return 1 if ( defined( List::Util::first { is_in_list( $_, @included_mozilla_trust_purposes ) } @{$trust_purposes_by_level{$level}} ) );
1841cb0ef41Sopenharmony_ci  }
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci  return 0;
1871cb0ef41Sopenharmony_ci}
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_cimy $crt = $ARGV[0] || dirname(__FILE__) . '/../src/node_root_certs.h';
1901cb0ef41Sopenharmony_cimy $txt = dirname(__FILE__) . '/certdata.txt';
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_cimy $stdout = $crt eq '-';
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ciif( $stdout ) {
1951cb0ef41Sopenharmony_ci    open(CRT, '> -') or die "Couldn't open STDOUT: $!\n";
1961cb0ef41Sopenharmony_ci} else {
1971cb0ef41Sopenharmony_ci    open(CRT,">$crt.~") or die "Couldn't open $crt.~: $!\n";
1981cb0ef41Sopenharmony_ci}
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_cimy $caname;
2011cb0ef41Sopenharmony_cimy $certnum = 0;
2021cb0ef41Sopenharmony_cimy $skipnum = 0;
2031cb0ef41Sopenharmony_cimy $start_of_cert = 0;
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ciopen(TXT,"$txt") or die "Couldn't open $txt: $!\n";
2061cb0ef41Sopenharmony_ciprint CRT "#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS\n";
2071cb0ef41Sopenharmony_ciwhile (<TXT>) {
2081cb0ef41Sopenharmony_ci  if (/\*\*\*\*\* BEGIN LICENSE BLOCK \*\*\*\*\*/) {
2091cb0ef41Sopenharmony_ci    print CRT;
2101cb0ef41Sopenharmony_ci    print if ($opt_l);
2111cb0ef41Sopenharmony_ci    while (<TXT>) {
2121cb0ef41Sopenharmony_ci      print CRT;
2131cb0ef41Sopenharmony_ci      print if ($opt_l);
2141cb0ef41Sopenharmony_ci      last if (/\*\*\*\*\* END LICENSE BLOCK \*\*\*\*\*/);
2151cb0ef41Sopenharmony_ci    }
2161cb0ef41Sopenharmony_ci  }
2171cb0ef41Sopenharmony_ci  next if /^#|^\s*$/;
2181cb0ef41Sopenharmony_ci  chomp;
2191cb0ef41Sopenharmony_ci  if (/^CVS_ID\s+\"(.*)\"/) {
2201cb0ef41Sopenharmony_ci    print CRT "/* $1 */\n";
2211cb0ef41Sopenharmony_ci  }
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci  # this is a match for the start of a certificate
2241cb0ef41Sopenharmony_ci  if (/^CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE/) {
2251cb0ef41Sopenharmony_ci    $start_of_cert = 1
2261cb0ef41Sopenharmony_ci  }
2271cb0ef41Sopenharmony_ci  if ($start_of_cert && /^CKA_LABEL UTF8 \"(.*)\"/) {
2281cb0ef41Sopenharmony_ci    $caname = $1;
2291cb0ef41Sopenharmony_ci  }
2301cb0ef41Sopenharmony_ci  my %trust_purposes_by_level;
2311cb0ef41Sopenharmony_ci  if ($start_of_cert && /^CKA_VALUE MULTILINE_OCTAL/) {
2321cb0ef41Sopenharmony_ci    my $data;
2331cb0ef41Sopenharmony_ci    while (<TXT>) {
2341cb0ef41Sopenharmony_ci      last if (/^END/);
2351cb0ef41Sopenharmony_ci      chomp;
2361cb0ef41Sopenharmony_ci      my @octets = split(/\\/);
2371cb0ef41Sopenharmony_ci      shift @octets;
2381cb0ef41Sopenharmony_ci      for (@octets) {
2391cb0ef41Sopenharmony_ci        $data .= chr(oct);
2401cb0ef41Sopenharmony_ci      }
2411cb0ef41Sopenharmony_ci    }
2421cb0ef41Sopenharmony_ci    # scan forwards until the trust part
2431cb0ef41Sopenharmony_ci    while (<TXT>) {
2441cb0ef41Sopenharmony_ci      last if (/^CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST/);
2451cb0ef41Sopenharmony_ci      chomp;
2461cb0ef41Sopenharmony_ci    }
2471cb0ef41Sopenharmony_ci    # now scan the trust part to determine how we should trust this cert
2481cb0ef41Sopenharmony_ci    while (<TXT>) {
2491cb0ef41Sopenharmony_ci      last if (/^#/);
2501cb0ef41Sopenharmony_ci      if (/^CKA_TRUST_([A-Z_]+)\s+CK_TRUST\s+CKT_NSS_([A-Z_]+)\s*$/) {
2511cb0ef41Sopenharmony_ci        if ( !is_in_list($1,@valid_mozilla_trust_purposes) ) {
2521cb0ef41Sopenharmony_ci          report "Warning: Unrecognized trust purpose for cert: $caname. Trust purpose: $1. Trust Level: $2";
2531cb0ef41Sopenharmony_ci        } elsif ( !is_in_list($2,@valid_mozilla_trust_levels) ) {
2541cb0ef41Sopenharmony_ci          report "Warning: Unrecognized trust level for cert: $caname. Trust purpose: $1. Trust Level: $2";
2551cb0ef41Sopenharmony_ci        } else {
2561cb0ef41Sopenharmony_ci          push @{$trust_purposes_by_level{$2}}, $1;
2571cb0ef41Sopenharmony_ci        }
2581cb0ef41Sopenharmony_ci      }
2591cb0ef41Sopenharmony_ci    }
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ci    if ( !should_output_cert(%trust_purposes_by_level) ) {
2621cb0ef41Sopenharmony_ci      $skipnum ++;
2631cb0ef41Sopenharmony_ci    } elsif ($caname =~ /TrustCor/) {
2641cb0ef41Sopenharmony_ci      $skipnum ++;
2651cb0ef41Sopenharmony_ci    } else {
2661cb0ef41Sopenharmony_ci      my $encoded = MIME::Base64::encode_base64($data, '');
2671cb0ef41Sopenharmony_ci      $encoded =~ s/(.{1,${opt_w}})/"$1\\n"\n/g;
2681cb0ef41Sopenharmony_ci      my $pem = "\"-----BEGIN CERTIFICATE-----\\n\"\n"
2691cb0ef41Sopenharmony_ci              . $encoded
2701cb0ef41Sopenharmony_ci              . "\"-----END CERTIFICATE-----\",\n";
2711cb0ef41Sopenharmony_ci      print CRT "\n/* $caname */\n";
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ci      my $maxStringLength = length($caname);
2741cb0ef41Sopenharmony_ci      if ($opt_t) {
2751cb0ef41Sopenharmony_ci        foreach my $key (keys %trust_purposes_by_level) {
2761cb0ef41Sopenharmony_ci           my $string = $key . ": " . join(", ", @{$trust_purposes_by_level{$key}});
2771cb0ef41Sopenharmony_ci           $maxStringLength = List::Util::max( length($string), $maxStringLength );
2781cb0ef41Sopenharmony_ci           print CRT $string . "\n";
2791cb0ef41Sopenharmony_ci        }
2801cb0ef41Sopenharmony_ci      }
2811cb0ef41Sopenharmony_ci      if (!$opt_t) {
2821cb0ef41Sopenharmony_ci        print CRT $pem;
2831cb0ef41Sopenharmony_ci      } else {
2841cb0ef41Sopenharmony_ci        my $pipe = "";
2851cb0ef41Sopenharmony_ci        foreach my $hash (@included_signature_algorithms) {
2861cb0ef41Sopenharmony_ci          $pipe = "|$openssl x509 -" . $hash . " -fingerprint -noout -inform PEM";
2871cb0ef41Sopenharmony_ci          if (!$stdout) {
2881cb0ef41Sopenharmony_ci            $pipe .= " >> $crt.~";
2891cb0ef41Sopenharmony_ci            close(CRT) or die "Couldn't close $crt.~: $!";
2901cb0ef41Sopenharmony_ci          }
2911cb0ef41Sopenharmony_ci          open(TMP, $pipe) or die "Couldn't open openssl pipe: $!";
2921cb0ef41Sopenharmony_ci          print TMP $pem;
2931cb0ef41Sopenharmony_ci          close(TMP) or die "Couldn't close openssl pipe: $!";
2941cb0ef41Sopenharmony_ci          if (!$stdout) {
2951cb0ef41Sopenharmony_ci            open(CRT, ">>$crt.~") or die "Couldn't open $crt.~: $!";
2961cb0ef41Sopenharmony_ci          }
2971cb0ef41Sopenharmony_ci        }
2981cb0ef41Sopenharmony_ci        $pipe = "|$openssl x509 -text -inform PEM";
2991cb0ef41Sopenharmony_ci        if (!$stdout) {
3001cb0ef41Sopenharmony_ci          $pipe .= " >> $crt.~";
3011cb0ef41Sopenharmony_ci          close(CRT) or die "Couldn't close $crt.~: $!";
3021cb0ef41Sopenharmony_ci        }
3031cb0ef41Sopenharmony_ci        open(TMP, $pipe) or die "Couldn't open openssl pipe: $!";
3041cb0ef41Sopenharmony_ci        print TMP $pem;
3051cb0ef41Sopenharmony_ci        close(TMP) or die "Couldn't close openssl pipe: $!";
3061cb0ef41Sopenharmony_ci        if (!$stdout) {
3071cb0ef41Sopenharmony_ci          open(CRT, ">>$crt.~") or die "Couldn't open $crt.~: $!";
3081cb0ef41Sopenharmony_ci        }
3091cb0ef41Sopenharmony_ci      }
3101cb0ef41Sopenharmony_ci      report "Parsing: $caname" if ($opt_v);
3111cb0ef41Sopenharmony_ci      $certnum ++;
3121cb0ef41Sopenharmony_ci      $start_of_cert = 0;
3131cb0ef41Sopenharmony_ci    }
3141cb0ef41Sopenharmony_ci  }
3151cb0ef41Sopenharmony_ci}
3161cb0ef41Sopenharmony_ciprint CRT "#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS\n";
3171cb0ef41Sopenharmony_ciclose(TXT) or die "Couldn't close $txt: $!\n";
3181cb0ef41Sopenharmony_ciclose(CRT) or die "Couldn't close $crt.~: $!\n";
3191cb0ef41Sopenharmony_ciunless( $stdout ) {
3201cb0ef41Sopenharmony_ci    rename "$crt.~", $crt or die "Failed to rename $crt.~ to $crt: $!\n";
3211cb0ef41Sopenharmony_ci}
3221cb0ef41Sopenharmony_cireport "Done ($certnum CA certs processed, $skipnum skipped).";
323