├── .gitignore ├── CA-baka ├── LICENSE.TXT ├── Makefile └── README /.gitignore: -------------------------------------------------------------------------------- 1 | CA-baka.8 2 | -------------------------------------------------------------------------------- /CA-baka: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | ###################################################################### 3 | # 4 | # ++Copyright BAKA++ 5 | # 6 | # Copyright (c) 2012 The Authors. All right reserved. 7 | # 8 | # The source code is licensed to you under the terms of the file 9 | # LICENSE.TXT in this release for further details 10 | # 11 | # Send e-mail to for further information 12 | # 13 | # - -Copyright BAKA- - 14 | # 15 | # Certificate authority 16 | # 17 | =encoding utf8 18 | 19 | =cut 20 | 21 | #use 5.012; 22 | use strict; 23 | use utf8; 24 | #use autodie; 25 | use warnings; 26 | use warnings qw< FATAL utf8 >; 27 | no warnings qw< uninitialized >; 28 | use open qw< :std :utf8 >; 29 | #use charnames qw< :full >; 30 | #use feature qw< unicode_strings >; 31 | 32 | # use Encode qw< encode decode >; 33 | use Encode::Locale qw(decode_argv); 34 | use Unicode::Normalize qw< NFD NFC >; 35 | use Carp qw< carp croak confess cluck >; 36 | use File::Basename qw< basename >; 37 | use Getopt::Long; 38 | use FindBin; 39 | use File::Spec; 40 | use POSIX qw(strftime); 41 | use File::Copy; 42 | use Time::Local; 43 | 44 | Encode::Locale::decode_argv(); 45 | 46 | $0 = basename($0); # Shorter messages 47 | 48 | my($USAGE) = "Usage: $0: 49 | ## Specify location of CA dir. Default ../etc/CA from location of program ## 50 | [--workdir directory] 51 | 52 | ## X509 Subject overrides: Required when running --newca ## 53 | [--country|--C country] [--state|--ST state] [--locality|--L city] 54 | [--organization|--O company] [--organizationalunit|--OU department] 55 | 56 | ## Certificate length override. ## 57 | ### Default 365 days normally but 1825 days for CA certs ### 58 | [--days number] 59 | 60 | ## CRL validatity length override. ## 61 | ### Default 1825 days ### 62 | [--crldays number] 63 | 64 | ### Default, certificate start date one day ago 65 | [--start %Y%m%d%H%M%SZ] 66 | 67 | ## Certificate key length. Default 2048 bits ## 68 | [--keylen bitlen|curvename] 69 | 70 | ## Hash Algorithm 71 | [--md sha256|sha224|sha384|sha512|sha1] 72 | 73 | ## Public Key Algorithm 74 | [--pk rsa|ecc|dsa] 75 | 76 | ## Initialize certificate authority. Requires X509 subject fields set ## 77 | [--newca CN Email] 78 | 79 | ## Create subsidiary certificate authority. ## 80 | [--subca CN Email NewWorkDir] 81 | 82 | ## Create a server certificate. ## 83 | [--newserver CN [Email]] 84 | 85 | ## Create a client certificate. ## 86 | [--newclient CN [Email]] 87 | 88 | ## Create a mail certificate. ## 89 | [--newmail CN [Email]] 90 | 91 | ## Create a code signing certificate. ## 92 | [--newcoder CN [Email]] 93 | 94 | ## Specify certificate alternative names. Only one cert can be generated ## 95 | ### Examples: URL:http://w3.example.com IP:127.0.0.1 DNS:s2.example.com email:root\@example.com 96 | [--altnames TYPE:value]... 97 | 98 | ## Specify certificate name constraints, typically on ca or subca. ## 99 | ### Examples: permitted;URL:http://.example.com 100 | ### permitted;IP:127.0.0.0/255.0.0.0 permitted;DNS:.example.com 101 | ### permitted;email:.example.com excluded;email:.com 102 | [--constraints ;TYPE:value]... 103 | 104 | ## Revoke an existing certificate. ## 105 | [--revoke CN] 106 | 107 | ## Renew an existing non-CA 'CN'. Normally duplicate CNs are rejected ## 108 | [--renew] 109 | 110 | ## Verify that a certificate was properly signed ## 111 | [--verify filename] 112 | 113 | [--force] [--version] [--verbose]+ [-v]+ [--quiet] \n"; 114 | my(%OPTIONS,@CAinfo,%DefOpt); 115 | my (@NewServer,@NewClient,@NewMail,@NewCoder,@AltNames,@NameConstraints,@SubCA); 116 | 117 | $OPTIONS{'workdir'} = File::Spec->canonpath("$FindBin::Bin/../etc/CA"); 118 | $OPTIONS{'days'} = -1; 119 | $OPTIONS{'crldays'} = 1825; 120 | $DefOpt{'keylen'} = 0; 121 | $DefOpt{'md'} = "sha512"; 122 | $DefOpt{'pk'} = "rsa"; 123 | 124 | Getopt::Long::Configure("no_ignore_case", "no_auto_abbrev", "no_getopt_compat", "require_order"); 125 | GetOptions(\%OPTIONS, 'workdir=s', 'C|country=s', 'ST|state=s', 'L|locality=s', 'O|organization=s', 'OU|organizationalunit=s', 'revoke=s', 'verify=s', 'newserver=s{1,2}'=>\@NewServer, 'altnames=s'=>\@AltNames, 'constraints=s'=>\@NameConstraints, 'newclient=s{1,2}'=>\@NewClient, 'newmail=s{1,2}'=>\@NewMail, 'newcoder=s{1,2}'=>\@NewCoder, 'newca=s{2}'=>\@CAinfo, 'subca=s{3}'=>\@SubCA, 'renew', 'days=f', 'crldays=f', 'start=s', 'keylen=s', 'md=s', 'pk=s', 'force', 'version', 'verbose|v+', 'quiet') || die $USAGE; 126 | 127 | ################################################## 128 | # Look for parse errors (easy with optional arguments) 129 | die "Neither CN nor Email nor Code Signers may start with leading -\n" if (grep(/^-/,(@NewMail,@NewCoder,@NewClient,@NewServer,@CAinfo))); 130 | 131 | ################################################## 132 | # Look for illegal duplicative requests 133 | if (@NewServer > 2 || @NewClient > 2 || @NewMail > 2 || @NewCoder > 2 || @CAinfo > 2 || @SubCA > 3) 134 | { 135 | die "Must specify a specific certificate type to generate exactly once.\n$USAGE"; 136 | } 137 | 138 | ################################################## 139 | # Cannot specify subject alternative names if generating multiple certificates at one time 140 | if (@AltNames) 141 | { 142 | if (((@NewServer > 0) + (@NewClient > 0) + (@NewMail > 0) + (@NewCoder > 0) + (@CAinfo > 0) + (@SubCA > 0)) != 1) 143 | { 144 | die "Must specify one and only one certificate generation option when using --altnames\n$USAGE"; 145 | } 146 | } 147 | 148 | 149 | # Globalish variables 150 | my ($C,$ST,$L,$O,$OU) = ($OPTIONS{'C'},$OPTIONS{'ST'},$OPTIONS{'L'},$OPTIONS{'O'},$OPTIONS{'OU'}); 151 | my ($CA_CN,$CA_EM); 152 | my ($CA_DIR) = $OPTIONS{'workdir'}; 153 | my ($ARCHIVE_BASE) = "$CA_DIR/archive"; 154 | my ($ARCHIVE_DIR); 155 | my ($TRUSTED_DIR) = "$CA_DIR/trusted-certs"; 156 | my ($CA_KEY) = "$CA_DIR/ca.key"; 157 | my ($CA_CRT) = "$CA_DIR/ca.crt"; 158 | my ($CA_CRL) = "$CA_DIR/ca.crl"; 159 | my ($CA_INFO) = "$CA_DIR/.cainfo"; 160 | my ($TMPCONF) = "$CA_DIR/tmp/ssl.conf"; 161 | my ($TMP_SERIAL) = "$CA_DIR/tmp/tmp-serial"; 162 | 163 | my ($StartDate) = $OPTIONS{'start'} || strftime("%Y%m%d%H%M%SZ", gmtime(time - 86400)); 164 | 165 | 166 | 167 | ###################################################################### 168 | # 169 | # Find unique serial number for this request 170 | # 171 | sub genserial() 172 | { 173 | my $old; 174 | 175 | # Consider locking against multiple updaters, something like 176 | # system("lockfile $TMP_SERIAL.lock"); 177 | # die "Multiple access restriction: serial number locked\n" if ($?); 178 | if (open(R,"<",$TMP_SERIAL)) 179 | { 180 | $old = ; 181 | chomp($old); 182 | close(R); 183 | $old = hex($old); 184 | } 185 | my $new = time; 186 | $new = $old + 1 if ($new <= $old); 187 | open(W,">","$TMP_SERIAL") || die "Cannot open serial number: $!"; 188 | printf W ("%8x\n",$new); 189 | close(W); 190 | # unlink("$TMP_SERIAL.lock"); 191 | } 192 | 193 | 194 | 195 | ###################################################################### 196 | # 197 | # Make ssl configuration for this request 198 | # 199 | sub gensslconf($$$$$$) 200 | { 201 | my ($extensions,$cn,$email,$altnames,$constraints,$base) = @_; 202 | 203 | my ($san_line) = ""; 204 | $san_line = qq^subjectAltName = \@alt_name_section\n^ if ($altnames && @$altnames); 205 | 206 | my ($nc_line) = ""; 207 | if ($constraints && @$constraints) 208 | { 209 | $nc_line = qq^nameConstraints = critical, \@constrained_trees\n^; 210 | } 211 | 212 | 213 | 214 | # Consider locking against multiple updaters, see genserial for example 215 | open(W,">",$TMPCONF) || die "Cannot open temporary ssl configuration file $TMPCONF: $!"; 216 | 217 | print W <","$dir/REVOKED"); 515 | print X "Certificate revoked.\n"; 516 | close(X); 517 | 518 | my ($serial) = openssl(qq^x509 -in '$dir/$type.crt' -serial -noout^); 519 | die "Could not find serial number in old certificate--already revoked but not moved away\n" unless ($serial =~ /^serial=([A-F0-9]+)$/); 520 | $serial = $1; 521 | my ($newdir) = "$dir-revoked-$serial"; 522 | die "Revoked certificate serial directory already exists: $newdir\n" if ( -e $newdir); 523 | File::Copy::move($dir,$newdir); 524 | 525 | if ($autodays) 526 | { 527 | $OPTIONS{'days'} = -1; 528 | } 529 | } 530 | 531 | 532 | 533 | ###################################################################### 534 | # 535 | # Validate names with renew support 536 | # 537 | sub validate_names($$) 538 | { 539 | my ($namesref,$type) = @_; 540 | 541 | # Check against directory attacks 542 | for(my $x=0;$x<=$#{$namesref};$x++) 543 | { 544 | my ($name) = $namesref->[$x]; 545 | sane_name($name,$x,$type); 546 | 547 | # XXX - A real script would need to deal with IDN homographs or other control character attacks here 548 | } 549 | 550 | my ($dir) = $ARCHIVE_BASE."/".$namesref->[0]; 551 | print STDERR "Checking dir $dir\n" unless ($OPTIONS{'quiet'}); 552 | if (-d $dir && $OPTIONS{'renew'}) 553 | { 554 | # We already checked that we are in --renew mode 555 | 556 | if (! -f "$dir/$type.crt") 557 | { 558 | die "Cannot renew to a different certificate type ($dir/$type)\n"; 559 | } 560 | 561 | revoke($namesref->[0],$dir); 562 | } 563 | } 564 | 565 | 566 | 567 | ###################################################################### 568 | # 569 | # Validate subject alternative names 570 | # 571 | sub validate_altnames(@) 572 | { 573 | foreach my $saname (@_) 574 | { 575 | my ($type,$value) = split(/:/,$saname,2); 576 | die "Invalid alternative name type $type\n" if ($type !~ /^(email|IP|DNS|URI)$/); 577 | sane_name($value,1,undef); 578 | } 579 | } 580 | 581 | 582 | 583 | ###################################################################### 584 | # 585 | # Validate contraint names 586 | # 587 | sub validate_constraints(@) 588 | { 589 | foreach my $saname (@_) 590 | { 591 | my ($decision,$other) = split(/;/,$saname,2); 592 | my ($type,$value) = split(/:/,$other,2); 593 | die "Invalid contraint decision type $decision\n" if ($decision !~ /^(permitted|excluded)$/); 594 | die "Invalid contraint name type $type\n" if ($type !~ /^(email|IP|DNS|URI|dirName)$/); 595 | sane_name($value,1,undef); 596 | } 597 | } 598 | 599 | 600 | 601 | ###################################################################### 602 | # 603 | # Generate certificates 604 | # 605 | sub gencert($$$$) 606 | { 607 | my ($namelist,$extensions,$dirent,$username) = @_; 608 | 609 | my ($autodays) = $OPTIONS{'days'} == -1; 610 | if ($autodays) 611 | { 612 | if ($username eq "New CA") 613 | { 614 | $OPTIONS{'days'} = 1825; 615 | } 616 | else 617 | { 618 | $OPTIONS{'days'} = 365; 619 | } 620 | } 621 | 622 | print STDERR "Generating $username certificate\n" unless ($OPTIONS{'quiet'}); 623 | 624 | my ($enddate); 625 | 626 | if (!$OPTIONS{'force'} && -f $CA_CRT) 627 | { 628 | # Check to make sure requested lifetime is not longer than 629 | # possible (CA's) lifetime 630 | 631 | # Could there be a locale problem interpreting -enddate output? 632 | 633 | $OPTIONS{'quiet'}++; 634 | my ($caexp) = openssl("x509 -in $CA_CRT -noout -enddate"); 635 | $OPTIONS{'quiet'}--; 636 | die "Could not parse attempt to get CA expiration date: $caexp" 637 | unless ($caexp =~ /^notAfter=(\S+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\d+) GMT$/); 638 | 639 | my ($camo) = {'Jan'=>0,'Feb'=>1,'Mar'=>2,'Apr'=>3,'May'=>4,'Jun'=>5, 640 | 'Jul'=>6,'Aug'=>7,'Sep'=>8,'Oct'=>9,'Nov'=>10,'Dec'=>11}; 641 | $camo = $camo->{$1}; 642 | 643 | die "Bad expiration date (locale bug?)\n" unless (defined($camo)); 644 | 645 | my ($caexptime) = timegm($5,$4,$3,$2,$camo,$6); 646 | my ($newexptime) = time + 86400*$OPTIONS{'days'}; 647 | 648 | if ($newexptime > $caexptime) 649 | { 650 | warn "\nERROR: Requested expiration --days $OPTIONS{'days'} greater than CA expiration of:\n ${caexp} Use --force to override, switching to CA expiration date.\n"; 651 | $enddate = sprintf("%04d%02d%02d%02d%02d%02dZ",$6,$camo+1,$2,$3,$4,$5); 652 | } 653 | } 654 | 655 | # Validate for sanity 656 | validate_names($namelist,$dirent); 657 | 658 | # Choose serial for certificate 659 | genserial(); 660 | 661 | # Prepare configuration file for generation 662 | gensslconf($extensions,$namelist->[0],$namelist->[1],\@AltNames,\@NameConstraints,$CA_DIR); 663 | 664 | # Prepare directory to dump all of this information 665 | $ARCHIVE_DIR="$ARCHIVE_BASE/$namelist->[0]"; 666 | die "Existing CN: ".($namelist->[0])."\n" if (-e "$ARCHIVE_DIR" && !$OPTIONS{'force'}); 667 | mkdir($ARCHIVE_DIR); 668 | 669 | # Generate certificate 670 | my ($mask) = umask(077); 671 | if ($OPTIONS{'pk'} eq "rsa") 672 | { 673 | openssl("genrsa -out '$ARCHIVE_DIR/$dirent.key' '$OPTIONS{'keylen'}'"); 674 | } 675 | elsif ($OPTIONS{'pk'} eq "ecc") 676 | { 677 | openssl("ecparam -out '$ARCHIVE_DIR/$dirent.key' -name '$OPTIONS{'keylen'}' -genkey"); 678 | } 679 | elsif ($OPTIONS{'pk'} eq "dsa") 680 | { 681 | openssl("dsaparam -out '$ARCHIVE_DIR/$dirent.key' -genkey '$OPTIONS{'keylen'}'"); 682 | print "WARNING: dsa certificates do not appear to be fully working. req -x509 works while req->ca does not\n"; 683 | } 684 | else 685 | { 686 | die "Unimplemented algorithm"; 687 | } 688 | umask($mask); 689 | openssl("req -batch -config '$TMPCONF' -new -key '$ARCHIVE_DIR/$dirent.key' -out '$CA_DIR/tmp/$dirent.csr' -extensions csr"); 690 | 691 | my ($other) = ""; 692 | if ($extensions eq "v3_ca" && ! -f $CA_CRT) 693 | { 694 | $other .= " -selfsign"; 695 | link("$ARCHIVE_DIR/$dirent.key",$CA_KEY) || die "Cannot move $dirent.key into position: $!\n"; 696 | } 697 | 698 | my ($openssl_cmd) = "ca -batch -startdate $StartDate -config '$TMPCONF' $other -key '$CA_KEY' -out '$ARCHIVE_DIR/$dirent.crt' -extensions $extensions"; 699 | if ($enddate) 700 | { 701 | $openssl_cmd .= " -enddate $enddate"; 702 | } 703 | else 704 | { 705 | $openssl_cmd .= " -days '$OPTIONS{'days'}'"; 706 | } 707 | # Must be last argument 708 | $openssl_cmd .= " -infiles '$CA_DIR/tmp/$dirent.csr'"; 709 | openssl($openssl_cmd); 710 | 711 | 712 | if ($extensions !~ /_ca$/) 713 | { 714 | my ($mask) = umask(077); 715 | openssl("pkcs12 -nodes -password pass:mypass -export -out '$ARCHIVE_DIR/$dirent.p12' -inkey '$ARCHIVE_DIR/$dirent.key' -in '$ARCHIVE_DIR/$dirent.crt' -certfile '$CA_CRT'"); 716 | umask($mask); 717 | } 718 | 719 | print "$username Certificates may be found in $ARCHIVE_DIR\n" unless ($OPTIONS{'quiet'}); 720 | 721 | if ($autodays) 722 | { 723 | $OPTIONS{'days'} = -1; 724 | } 725 | } 726 | 727 | 728 | 729 | ###################################################################### 730 | # 731 | # Gen certificate authority (both initial and subsidiary) 732 | # 733 | sub genca($$$$$$$$$) 734 | { 735 | my ($C,$ST,$L,$O,$OU,$CA_CN,$CA_EM,$CA_DIR,$CA_PARENT) = @_; 736 | 737 | die "Bad certificate information" unless ($CA_CN); 738 | 739 | # Check for sane arguments 740 | sane_name($C,1,undef); 741 | sane_name($ST,1,undef); 742 | sane_name($L,1,undef); 743 | sane_name($O,1,undef); 744 | sane_name($OU,1,undef) if ($OU); 745 | validate_names([$CA_CN,$CA_EM],"ca"); 746 | 747 | # Set up cert directory 748 | if (! -d $CA_DIR) 749 | { 750 | mkdir($CA_DIR) || die "Cannot make working directory $CA_DIR: $!"; 751 | } 752 | mkdir($CA_DIR."/tmp",0700) || die "Cannot make tmp working directory: $!"; 753 | 754 | # Save legacy ARCHIVE_BASE in case this is a subCA case 755 | my ($REAL_ARCHIVE_DIR) = "$ARCHIVE_BASE/$CA_CN"; 756 | 757 | # Make normal archive directory 758 | my ($ARCHIVE_BASE) = "$CA_DIR/archive"; 759 | mkdir($ARCHIVE_BASE) || die "Cannot make tmp working directory: $!"; 760 | 761 | # Store default x509 subject information 762 | my ($CA_INFO) = "$CA_DIR/.cainfo"; 763 | open(CA,">",$CA_INFO) || die "Cannot write certificate information file: $!\n"; 764 | print CA "$C\n$ST\n$L\n$O\n$OU\n$CA_CN\n$CA_EM\n"; 765 | print CA "$OPTIONS{'md'}\n$OPTIONS{'pk'}\n$OPTIONS{'keylen'}\n"; 766 | close(CA); 767 | 768 | # Set up trusted certificate directory 769 | mkdir("$CA_DIR/trusted-certs"); 770 | open(CA,">","$CA_DIR/trusted-certs/index.txt") || die "Cannot create index: $!"; 771 | close(CA); 772 | 773 | # What type of cert are we generating 774 | my ($extension) = "v3_ca"; 775 | my ($dirent) = "ca"; 776 | 777 | # Override for subca case 778 | if ($CA_PARENT) 779 | { 780 | $extension = "sub_ca"; 781 | $dirent = "subca"; 782 | } 783 | 784 | # Generate certificate 785 | gencert([$CA_CN,$CA_EM],$extension,$dirent,"New CA"); 786 | 787 | # Link certificate into CA root. Key (non-sub case) has already been linked in 788 | link("$ARCHIVE_DIR/$dirent.crt","$CA_DIR/ca.crt") || die "Cannot archive ca.crt: $!\n"; 789 | 790 | # Set up correct archive 791 | my ($ARCHIVE_DIR) = "$ARCHIVE_BASE/$CA_CN"; 792 | 793 | # Prepare local variable in case it changes with subCA 794 | my ($TRUSTED_DIR) = $TRUSTED_DIR; 795 | 796 | if ($CA_PARENT) 797 | { 798 | # Move the subsidiary CA certificate into the new subdir 799 | mkdir($ARCHIVE_DIR) || die "Cannot create directory '$ARCHIVE_DIR': $!\n"; 800 | link("$REAL_ARCHIVE_DIR/$dirent.crt","$ARCHIVE_DIR/ca.crt") || die "Cannot link ca.crt: $!\n"; 801 | link("$REAL_ARCHIVE_DIR/$dirent.key","$ARCHIVE_DIR/ca.key") || die "Cannot link ca.key: $!\n"; 802 | link("$REAL_ARCHIVE_DIR/$dirent.key","$CA_DIR/ca.key") || die "Cannot link ca.key: $!\n"; 803 | } 804 | 805 | # Place ca cert in trusted directory (twice for subCA case) 806 | if ($CA_PARENT) 807 | { 808 | hash("$REAL_ARCHIVE_DIR/$dirent.crt","x509",$TRUSTED_DIR); 809 | $TRUSTED_DIR="$CA_DIR/trusted-certs"; 810 | 811 | # Regenerate SSL configuration with new directories 812 | gensslconf($extension,$CA_CN,$CA_EM,\@AltNames,\@NameConstraints,$CA_DIR); 813 | hash("$CA_PARENT/ca.crt","x509",$TRUSTED_DIR); 814 | 815 | # Link parent CRL into place 816 | hash($CA_CRL,"crl",$TRUSTED_DIR); 817 | } 818 | hash("$REAL_ARCHIVE_DIR/$dirent.crt","x509",$TRUSTED_DIR); 819 | 820 | # Pick correct location for CRL 821 | my ($CA_CRL) = "$CA_DIR/ca.crl"; 822 | 823 | # Prepare for certificate revocation 824 | openssl("ca -batch -gencrl -out '$CA_CRL' -config '$TMPCONF'"); 825 | hash($CA_CRL,"crl",$TRUSTED_DIR); 826 | 827 | my ($CA_CRT) = "$ARCHIVE_DIR/ca.crt"; 828 | 829 | # Create alternate formats of certificate 830 | openssl("pkcs12 -nokeys -password pass:mypass -export -out '$ARCHIVE_DIR/ca.p12' -in '$CA_CRT'"); 831 | openssl("x509 -in '$CA_CRT' -out '$ARCHIVE_DIR/ca.der' -outform DER"); 832 | openssl("x509 -in '$CA_CRT' -out '$ARCHIVE_DIR/ca.pem' -outform PEM"); 833 | run("keytool -import -storepass mypass -alias cacert -noprompt -trustcacerts -keystore '$ARCHIVE_DIR/ca.jks' -file '$ARCHIVE_DIR/ca.der'",1); 834 | } 835 | 836 | 837 | sub cryptocheck() 838 | { 839 | ################################################## 840 | # Check public key algorithm for sanity 841 | if ($OPTIONS{'pk'} eq "rsa") 842 | { 843 | if (!$OPTIONS{'keylen'}) 844 | { 845 | $OPTIONS{'keylen'} = 2048; 846 | } 847 | die "Inappropriate keylen\n$USAGE" if ($OPTIONS{'keylen'} < 1024); 848 | } 849 | elsif ($OPTIONS{'pk'} eq "dsa") 850 | { 851 | if (!$OPTIONS{'keylen'}) 852 | { 853 | $OPTIONS{'keylen'} = 2048; 854 | } 855 | die "Inappropriate keylen\n$USAGE" if ($OPTIONS{'keylen'} < 1024); 856 | } 857 | elsif ($OPTIONS{'pk'} eq "ecc") 858 | { 859 | sub check_curve($) 860 | { 861 | my ($qkey) = quotemeta($_[0]); 862 | my ($lines) = openssl("ecparam -list_curves", 1); 863 | $lines =~ /^ $qkey\s*:/m; 864 | } 865 | 866 | if (!$OPTIONS{'keylen'}) 867 | { 868 | foreach my $kl ("secp224k1", "secp384r1") 869 | { 870 | next unless check_curve($kl); 871 | $OPTIONS{'keylen'} = $kl; 872 | last; 873 | } 874 | } 875 | die "Inappropriate key length/(really curvename) $OPTIONS{'keylen'}. Values\n@{[`openssl ecparam -list_curves`]}\n$USAGE" unless check_curve($OPTIONS{'keylen'}); 876 | } 877 | else 878 | { 879 | die "Must specify either RSA, DSA, or ECC public key algorithm.\n$USAGE"; 880 | } 881 | } 882 | 883 | 884 | # Support version display 885 | if ($OPTIONS{'version'}) 886 | { 887 | my $version = "{UNTAGGED}"; 888 | 889 | # If the version string is still UNTAGGED, try to run the local 890 | # git commands to get the current hash and possibly tag; this is used by 891 | # Makefile to get the correct string to replace it with. Otherwise, the 892 | # installation has replaced it with a version; don't mess with it. Use 893 | # string concatenation to keep this check from getting replaced. 894 | 895 | if ($version eq "{" . "UNTAGGED" . "}" && -x basename($0)) 896 | { 897 | my ($desc) = `git describe --dirty --candidates=1 --tags 2>/dev/null`; 898 | if ($?) 899 | { 900 | $desc = `git rev-parse HEAD`; 901 | chomp($desc); 902 | $desc = "Untagged ($desc)"; 903 | } 904 | else 905 | { 906 | # strip out leading tag alphabetic and space, get just the numbers 907 | $desc =~ s/^.*?([0-9][0-9._-]*[0-9])(?:-g[a-f0-9]*)?/$1/; 908 | $desc =~ y=/_=--=; 909 | } 910 | chomp($desc); 911 | $version = $desc; 912 | } 913 | print "$version\n"; 914 | exit(0); 915 | } 916 | 917 | 918 | sub load_defaults() 919 | { 920 | # Set up defaults, if needed 921 | open(CA,"<","$CA_INFO") || die "Cannot open certificate information file\n"; 922 | my (@C) = ; 923 | close(CA); 924 | chomp(@C); 925 | $C = $C[0] unless (defined($C)); 926 | $ST = $C[1] unless (defined($ST)); 927 | $L = $C[2] unless (defined($L)); 928 | $O = $C[3] unless (defined($O)); 929 | $OU = $C[4] unless (defined($OU)); 930 | sane_name($C,1, undef); 931 | sane_name($ST,1, undef); 932 | sane_name($L,1, undef); 933 | sane_name($O,1, undef); 934 | sane_name($OU,1, undef) if ($OU); 935 | ($CA_CN,$CA_EM) = @C[5..6]; 936 | $OPTIONS{'md'} = $C[7] || $DefOpt{'md'} unless (defined($OPTIONS{'md'})); 937 | $OPTIONS{'pk'} = $C[8] || $DefOpt{'pk'} unless (defined($OPTIONS{'pk'})); 938 | $OPTIONS{'keylen'} = $C[9] || $DefOpt{'keylen'} unless (defined($OPTIONS{'keylen'})); 939 | cryptocheck(); 940 | die "Bad certificate information in $CA_INFO\n" unless ($CA_CN); 941 | } 942 | 943 | 944 | # Older versions of OpenSSL do not support four digit years 945 | my ($opensslversion) = openssl("version"); 946 | if ($opensslversion =~ /\b0\.9\.[^9]/) 947 | { 948 | ($StartDate) = strftime("%y%m%d%H%M%SZ", gmtime(time - 86400)); 949 | } 950 | 951 | 952 | ################################################## 953 | # Check that subject alternative names are sane 954 | if (@AltNames) 955 | { 956 | validate_altnames(@AltNames); 957 | } 958 | 959 | 960 | ################################################## 961 | # Check that subject alternative names are sane 962 | if (@NameConstraints) 963 | { 964 | validate_constraints(@NameConstraints); 965 | } 966 | 967 | ################################################## 968 | # Check for initialized working directory 969 | if (! -f $CA_INFO || (! -f "$CA_CRT" && @CAinfo)) 970 | { 971 | # Not initialized, check for sanity and set it up (must have --newca) 972 | if (-e $CA_DIR) 973 | { 974 | die "Must delete certificate directory\n" if (-e $CA_DIR && -f "$CA_CRT"); 975 | load_defaults(); 976 | } 977 | else 978 | { 979 | $OPTIONS{'md'} = $DefOpt{'md'} unless $OPTIONS{'md'}; 980 | $OPTIONS{'pk'} = $DefOpt{'pk'} unless $OPTIONS{'pk'}; 981 | $OPTIONS{'keylen'} = $DefOpt{'keylen'} unless $OPTIONS{'keylen'}; 982 | cryptocheck(); 983 | } 984 | 985 | die "Missing --newca certificate information\n" unless (@CAinfo); 986 | print STDERR "Generating certificate authority certificate\n" unless ($OPTIONS{'quiet'}); 987 | die "Must set x509 subject information (--C --ST --L --O, plus optionally --OU)\n" unless (defined($C) && defined($ST) && defined($L) && defined($O)); 988 | 989 | genca($C,$ST,$L,$O,$OU,$CAinfo[0],$CAinfo[1],$CA_DIR,undef); 990 | 991 | undef(@CAinfo); 992 | } 993 | 994 | # Check for attempts to recreate CA after initialization 995 | die "Already have CA initialized\n" if (@CAinfo); 996 | die "Only partially initialized. Check for missing $CA_CRT\n" unless (-f "$CA_CRT"); 997 | die "Only partially initialized. Check for missing $TRUSTED_DIR/index.txt\n" unless (-f "$TRUSTED_DIR/index.txt"); 998 | 999 | load_defaults(); 1000 | 1001 | ################################################## 1002 | # Create subsidiary CA signed by this one 1003 | if (@SubCA) 1004 | { 1005 | genca($C,$ST,$L,$O,$OU,$SubCA[0],$SubCA[1],$SubCA[2],$CA_DIR); 1006 | } 1007 | 1008 | ################################################## 1009 | # Create server certificate 1010 | if (@NewServer) 1011 | { 1012 | gencert(\@NewServer,"server","server","Server"); 1013 | } 1014 | 1015 | ################################################## 1016 | # Create client certificate 1017 | if (@NewClient) 1018 | { 1019 | gencert(\@NewClient,"client","client","Client"); 1020 | } 1021 | 1022 | ################################################## 1023 | # Create user/mail certificate 1024 | if (@NewMail) 1025 | { 1026 | if ($OPTIONS{'pk'} ne "rsa") 1027 | { 1028 | print "WARNING: email certificates currently require RSA signatures for encryption, apparently. Pressing on dangerously.\n"; 1029 | } 1030 | gencert(\@NewMail,"mail_cert","mail","Mail"); 1031 | } 1032 | 1033 | ################################################## 1034 | # Create code signing certificate 1035 | if (@NewCoder) 1036 | { 1037 | gencert(\@NewCoder,"coder_cert","coder","Coder"); 1038 | } 1039 | 1040 | ################################################## 1041 | # Revoke a certificate 1042 | if ($OPTIONS{'revoke'}) 1043 | { 1044 | $ARCHIVE_DIR="$ARCHIVE_BASE/$OPTIONS{'revoke'}"; 1045 | die "Cannot find $OPTIONS{'revoke'} to revoke!\n" if (!-d $ARCHIVE_DIR); 1046 | revoke($OPTIONS{'revoke'},$ARCHIVE_DIR); 1047 | } 1048 | 1049 | ################################################## 1050 | # Validate/verify that a certificate is good 1051 | if ($OPTIONS{'verify'}) 1052 | { 1053 | $OPTIONS{'verify'} = findtypes($OPTIONS{'verify'}) unless (-f $OPTIONS{'verify'}); 1054 | 1055 | $_ = openssl("verify -CApath '$TRUSTED_DIR' -crl_check_all '$OPTIONS{'verify'}'"); 1056 | die "Certificate not valid\n" if (/error/); 1057 | 1058 | print "Certificate valid for the following purposes: "; 1059 | 1060 | foreach my $purpose ("any", "crlsign", "nssslserver", "ocsphelper", "smimeencrypt", "smimesign", "sslclient", "sslserver", "timestampsign") 1061 | { 1062 | $_ = openssl("verify -CApath '$TRUSTED_DIR' -crl_check_all -purpose $purpose '$OPTIONS{'verify'}'", 1); 1063 | print " $purpose" if ($? == 0 && !/error/); 1064 | } 1065 | print "\n"; 1066 | openssl("x509 -in '$OPTIONS{'verify'}' -noout -purpose"); 1067 | } 1068 | 1069 | 1070 | =head1 NAME 1071 | 1072 | CA-baka - Simple X509 Certificate Authority/Generation Script 1073 | 1074 | The sysadmin's and network security developer's best friend. 1075 | 1076 | 1077 | =head1 SYNOPSIS 1078 | 1079 | CA-baka 1080 | S< [--workdir directory]> 1081 | S< [--country|--C country] [--state|--ST state] [--locality|--L city]> 1082 | S< [--organization|--O company] [--organizationalunit|--OU department]> 1083 | S< [--days number]> 1084 | S< [--keylen bitlen]> 1085 | S< [--md sha256|sha224|sha384|sha512|sha1]> 1086 | S< [--pk rsa|ecc|dsa]> 1087 | S< [--newca CN Email]> 1088 | S< [--subca CN Email NewWorkDir]> 1089 | S< [--newserver CN [Email]]> 1090 | S< [--newclient CN [Email]]> 1091 | S< [--newmail CN [Email]]> 1092 | S< [--newcoder CN [Email]]> 1093 | S< [--altnames TYPE:value]...> 1094 | S< [--constraints METHOD;TYPE:value]...> 1095 | S< [--revoke CN]> 1096 | S< [--renew]> 1097 | S< [--verify filename]> 1098 | S< [--force]> 1099 | S< [--verbose]+ [-v]+ [--quiet]> 1100 | 1101 | 1102 | =head1 DESCRIPTION 1103 | 1104 | This Certificate Authority is designed for use by a skilled, trusted 1105 | human who is generating full cryptographic packages for clients, 1106 | servers, or peoples to blindly install without thought, without having 1107 | to modify any configuration files or do special things with your shell 1108 | before running commands, or the like. The very model of a centralized 1109 | CA dictatorship (I'll just keep those keys for backup purposes in case 1110 | you happen to lose them, I won't use them to decrypt your future 1111 | traffic, or forge your signatures, honest!). 1112 | 1113 | Everyone and their dog seems to have a certificate 1114 | authority/generation script, but all of the ones I have seen so far, 1115 | frankly, suck donkey balls for usability, documentation, and sanity. 1116 | The most common ones "Easy CA" and the rather anonymously named "CA" 1117 | used by RHEL, are particularly annoying. This one does what I have 1118 | wanted to do each and every time I have wanted to generate 1119 | certificates, simply and cleanly. 1120 | 1121 | All of the most common certificate authority needs are provided: 1122 | initial master certificate authority key/crt generation, subsidiary 1123 | certificate authority key/crt generation, server key/crt generation, 1124 | client key/crt generation, email key/crt generation, and certificate 1125 | revocation. 1126 | 1127 | There is limited ability to modify the most popular information, 1128 | including X509 subject identifier material, validity length, and key 1129 | length. Defaults are available for all values (except for X509 1130 | subject identifier material during the initial setup of the master 1131 | certificate authority). 1132 | 1133 | The first invocation of CA-baka (per --workdir) requires that you use 1134 | C<--newca> with C<--country>, C<--state>, C<--locality>, and 1135 | C<--organization> set to properly initialize the certificate 1136 | authority. Afterwards (or indeed at the same time as the C<--newca> 1137 | invocation, you can issue other certificates using one or more of 1138 | C<--subca>, C<--newserver>, C<--newclient>, C<--newmail>, 1139 | C<--newcoder> or revoke other certificates using C<--revoke>. Other 1140 | arguments modify the behavior of the system. 1141 | 1142 | 1143 | =head1 OPTIONS 1144 | 1145 | The options control everything, and the script is not going to do 1146 | anything (except perhaps error out depending on configuration) if you 1147 | do not provide arguments. 1148 | 1149 | =over 1150 | 1151 | =item B<--workdir I> 1152 | 1153 | Set the certificate authority working directory. If this is not 1154 | specified, the directory ../etc/CA relative to the location of the 1155 | "CA-baka" program will be used. When first configuring the system 1156 | C<--newca> the working directory must not exist. 1157 | 1158 | =item B<--country|C I> 1159 | 1160 | Set the X509 C country code. This is required when using C<--newca>. 1161 | Other executions, it may be specified or the value from the C<--newca> 1162 | call will be used. You may use quotes to send empty/complex/multiword 1163 | identifiers. 1164 | 1165 | =item B<--state|ST I> 1166 | 1167 | Set the X509 ST state. This is required when using C<--newca>. Other 1168 | executions, it may be specified or the value from the C<--newca> call 1169 | will be used. You may use quotes to send empty/complex/multiword 1170 | identifiers. 1171 | 1172 | =item B<--locality|L I> 1173 | 1174 | Set the X509 L locality, typically the city name. This is required 1175 | when using C<--newca>. Other executions, it may be specified or the 1176 | value from the C<--newca> call will be used. You may use quotes to 1177 | send empty/complex/multiword identifiers. 1178 | 1179 | =item B<--organization|O I> 1180 | 1181 | Set the X509 O organization, typically the company name. This is 1182 | required when using C<--newca>. Other executions, it may be specified 1183 | or the value from the C<--newca> call will be used. You may use 1184 | quotes to send empty/complex/multiword identifiers. 1185 | 1186 | =item B<--organizationalunit|OU I> 1187 | 1188 | Set the X509 OU organizational unit, typically the department name. 1189 | This is also optional. Non-initial executions, it may be specified or 1190 | the (possibly empty) value from the C<--newca> call will be used. You 1191 | may use quotes to send empty/complex/multiword identifiers. 1192 | 1193 | =item B<--newca I> 1194 | 1195 | Request that the initial certificate authority be set up with the 1196 | indicated common name and email address. You may use quotes to send 1197 | empty/complex/multiword identifiers. 1198 | 1199 | The generated certificate, key, and various alternate forms of that 1200 | data will be available in the work directory's archive subdirectory, 1201 | in a further subdirectory named by the CN. Distribution of this 1202 | material is left as an exercise to the reader. 1203 | 1204 | =item B<--subca I> 1205 | 1206 | Request that a subsidiary certificate authority be set up with the 1207 | indicated common name and email address, in the new work directory 1208 | specified. This is much like creating an entirely distinct 1209 | certificate authority with C<--newca> except: (1) the certificate is 1210 | signed by the parent certificate, (2) you cannot create lower level 1211 | subsidiary certificates authorities, (3) the X509 subject identifier 1212 | material is defaulted from the C<--newca> call (but of course may be 1213 | overridden on this execution, the values in play at the time of 1214 | C<--subca> will be the new defaults for the C<--subca>'s work 1215 | directory. You may use quotes to send empty/complex/multiword 1216 | identifiers. 1217 | 1218 | The generated certificate, key, and various alternate forms of that 1219 | data will be available in the work directory's archive subdirectory, 1220 | in a further subdirectory named by the CN. Distribution of this 1221 | material is left as an exercise to the reader. 1222 | 1223 | =item B<--newserver I> 1224 | 1225 | Request that a server certificate be generated with the indicated 1226 | common name and the optional email address. You may use quotes to 1227 | send empty/complex/multiword identifiers (and if you have other 1228 | command line options after this one, you B specify an email 1229 | address, though it may be empty. 1230 | 1231 | The generated certificate, key, and various alternate forms of that 1232 | data will be available in the work directory's archive subdirectory, 1233 | in a further subdirectory named by the CN. Distribution of this 1234 | material is left as an exercise to the reader. 1235 | 1236 | =item B<--newclient I> 1237 | 1238 | Request that a client certificate be generated with the indicated 1239 | common name and the optional email address. You may use quotes to 1240 | send empty/complex/multiword identifiers (and if you have other 1241 | command line options after this one, you B specify an email 1242 | address, though it may be empty. 1243 | 1244 | The generated certificate, key, and various alternate forms of that 1245 | data will be available in the work directory's archive subdirectory, 1246 | in a further subdirectory named by the CN. Distribution of this 1247 | material is left as an exercise to the reader. 1248 | 1249 | =item B<--newmail I> 1250 | 1251 | Request that a user mail certificate be generated with the indicated 1252 | common name and the optional(recommended) email address. You may use 1253 | quotes to send empty/complex/multiword identifiers (and if you have 1254 | other command line options after this one, you B specify an 1255 | email address, though it may be empty. 1256 | 1257 | The generated certificate, key, and various alternate forms of that 1258 | data will be available in the work directory's archive subdirectory, 1259 | in a further subdirectory named by the CN. Distribution of this 1260 | material is left as an exercise to the reader. 1261 | 1262 | =item B<--newcoder I> 1263 | 1264 | Request that a code signing certificate be generated with the indicated 1265 | common name and the optional(recommended) email address. You may use 1266 | quotes to send empty/complex/multiword identifiers (and if you have 1267 | other command line options after this one, you B specify an 1268 | email address, though it may be empty. 1269 | 1270 | The generated certificate, key, and various alternate forms of that 1271 | data will be available in the work directory's archive subdirectory, 1272 | in a further subdirectory named by the CN. Distribution of this 1273 | material is left as an exercise to the reader. 1274 | 1275 | =item B<--altnames I> 1276 | 1277 | Request that the certificate being generated on this execution be 1278 | given the listed subject alternate name (SAN). You may only generate 1279 | one certificate per execution if you have C<--altnames> specified. 1280 | This can be used to provide, eg, alternate hostnames for HTTPS server 1281 | certificates (for multisite hosted domains) or alternate email address 1282 | for mail certificates. 1283 | 1284 | Valid TYPEs are "email", "URI", "DNS", and "IP". Typically "DNS" and 1285 | "IP" are used for server certificates, and "email" is used for mail 1286 | certificates. 1287 | 1288 | When using C<--altnames> you B specify the data (CN, email) you 1289 | might have expected to be authories as part of the primary subject 1290 | name as an alternate. So if you set the CN to host1.example.com, you 1291 | must also provide DNS:host1.example.com as an SAN). 1292 | 1293 | You must specify this argument multiple times, one per SAN you are 1294 | attempting provide. 1295 | 1296 | =item B<--constraints I> 1297 | 1298 | Request that the certificate being generated on this execution be 1299 | given the listed name constraints. This is typically done for CA 1300 | and sub-CA certificates to limit the scope of what damage a compromised 1301 | certificate might do. 1302 | 1303 | Valid METHODs are "permitted" and "excluded". 1304 | 1305 | Valid TYPEs are "email", "URI", "DNS", and "IP". Typically "DNS" and 1306 | "IP" are used for server certificates, and "email" is used for mail 1307 | certificates. 1308 | 1309 | Name contraints are not fully supported by all ssl implementations, 1310 | and indeed OpenSSL seems to only really support it if there is a 1311 | subject alternative name in the nominally constrainted certificate 1312 | absent specific investigation by the client app. You should test your 1313 | clients and servers with nameConstraints before you put them in 1314 | production. 1315 | 1316 | You must specify this argument multiple times, one per constraint you 1317 | are attempting provide. 1318 | 1319 | permitted;URL:http://.example.com 1320 | permitted;IP:127.0.0.0/255.0.0.0 1321 | permitted;DNS:.example.com 1322 | permitted;email:.example.com 1323 | excluded;email:.com 1324 | 1325 | 1326 | =item B<--revoke I> 1327 | 1328 | Specify a desire to revoke a currently valid certificate. The 1329 | existing certificate directory will be moved away to an alternate name 1330 | and the certificate revocation list (CRL) will be regenerated. 1331 | Distribution of said CRL is left as an exercise to the reader. 1332 | 1333 | =item B<--days I> 1334 | 1335 | Override the default number of days a certificate will be valid for, 1336 | relative to today. By default, normal certificates are valid for 365 1337 | days (1 year) and CA certificates are valid for 1825 days (5 years). 1338 | 1339 | Note that issued certificates cannot by default have an expiration 1340 | date greater than the certifying authority's certificate expiration 1341 | date (you can use --force to bypass this check, but it is a bad idea 1342 | to do so, since after that date the issued certificate will no longer 1343 | validate). The corollary is that Certificate Authority Certificates 1344 | should probably have a fairly long lifetime. The corollary's corollary 1345 | is that your should protect your CA key well. 1346 | 1347 | =item B<--crldays I> 1348 | 1349 | Override the default number of days the Certificate Revocation List 1350 | (CRL) will be valid for, relative to today. By default, CRL 1351 | Certificates are valid for 1825 days (5 years). 1352 | 1353 | Unless you have an automated process to renew and manage the CRL 1354 | (unlikely if you are using this program!!), you likely will want the 1355 | CRL valid for as long as the CA is valid; since correct applications 1356 | will stop validating certificates if the CRL has expired. 1357 | 1358 | =item B<--start I> 1359 | 1360 | Override the default certificate validity start date (24 hours ago 1361 | from "now"). A suitable way to specify a desired start timestamp is 1362 | using a command like: `date -d 'May 15 last year' +%Y%m%d%H%M%SZ` 1363 | 1364 | =item B<--md I> 1365 | 1366 | Override the default hash algorithm for a certificate. The default 1367 | algorithm is currently sha256. See `openssl dgst -h` to see a list of 1368 | supported hash algorithms. 1369 | 1370 | =item B<--pk I> 1371 | 1372 | Override the default public key algorithm for a certificate. The 1373 | default algorithm is currently RSA. Use `CA-baka --pk list` to see a 1374 | list of supported public key algorithms. 1375 | 1376 | =item B<--keylen I|I> 1377 | 1378 | Override the default key length of a certificate. The default key 1379 | length for RSA and DSA is 2048 bits, for ECC the default curve is 1380 | secp224k1, secp384r1 (in order of preference, not that I am ecstatic 1381 | with either curve). For ecc pk algorithms, the key length is used to 1382 | communicate the curvename. 1383 | 1384 | `openssl ecparam -list_curves` shows you what curves are available. 1385 | 1386 | =item B<--renew> 1387 | 1388 | Normally you are forbidden to generate a certificate for a CN you have 1389 | generated a certificate for previously. However, as a special case, 1390 | you may pass in the --renew option which will cause the existing 1391 | certificate to be revoked, so that a fresh certificate can be 1392 | generated. 1393 | 1394 | You use this option with the option(s) to generate a "new" certificate 1395 | with an existing name. 1396 | 1397 | Doing this for your CA certificate (eg revoking your CA certificate) 1398 | is a very bad idea, nothing good will come from it. You should 1399 | instead just rotate/archive/rename/delete your CA working directory and start 1400 | over, this time perhaps with a longer validity range and perhaps a 1401 | rotating sub-CA system (which you can --renew, but should also 1402 | just rotate/archive/rename/delete the sub-CA's working directory). 1403 | 1404 | 1405 | =item B<--verify I> 1406 | 1407 | Attempt to verify a certificate given a file to the certificate or the 1408 | CN of the certificate (the latter using the saved certificate 1409 | material). The CRL is checked to verify whether the certificate was 1410 | revoked or not. The purposes the certificates are valid for are 1411 | displayed. 1412 | 1413 | =item B<--force> 1414 | 1415 | Bypass certain sanity checks (eg maximum certificate lifetime) 1416 | 1417 | =item B<--version> 1418 | 1419 | Print the version of this program. 1420 | 1421 | =item B<--verbose|v> 1422 | 1423 | Print more information when generating certificates. 1424 | 1425 | =item B<--quiet> 1426 | 1427 | Print less information when generating certificates. 1428 | 1429 | =back 1430 | 1431 | 1432 | =head1 EXAMPLES 1433 | 1434 | A typical usage goes something like: 1435 | 1436 | # Create certificate authority 1437 | CA-baka --workdir /etc/CA -C US --ST NY -L "New York" -O "Mythical NY Company" --newca ca.example.com "" 1438 | 1439 | # Create web server certificate 1440 | CA-baka --workdir /etc/CA --newserver www.example.com webmaster\@example.com 1441 | 1442 | # Create mail certificate plus all common aliases 1443 | CA-baka --workdir /etc/CA --newserver mail.example.com postmaster\@example.com --altnames DNS:mail.example.com --altnames DNS:pop.example.com --altnames DNS:imap.example.com --altnames:smtp.example.com 1444 | 1445 | # Create VPN server certificate 1446 | CA-baka --workdir /etc/CA --newserver vpn.example.com "" 1447 | 1448 | # Create specific user certificate for VPN 1449 | CA-baka --workdir /etc/CA --OU VPN --newclient "Joe Luser" joe\@example.com 1450 | CA-baka --workdir /etc/CA --OU VPN --newclient "Bob 6pack" bob\@example.com 1451 | CA-baka --workdir /etc/CA --OU VPN --newclient "Martha Stewardess" mstew\@example.com 1452 | 1453 | # Revoke bad certificate 1454 | CA-baka --workdir /etc/CA --OU VPN --revoke "Martha Stewardess" 1455 | 1456 | # Issue a certificate with non-default hash and longer rsa key 1457 | CA-baka --md sha512 --keylen 8192 --workdir /etc/CA --OU VPN --newclient "Paranoid Pete" pete\@example.com 1458 | 1459 | # Issue a certificate with a different public key algorithms 1460 | CA-baka --md sha512 --pk ecc --workdir /etc/CA --OU VPN --newclient "Eccentric Eliptical Chuck" chuck\@example.com 1461 | 1462 | 1463 | =head1 FILES/DIRECTORIES 1464 | 1465 | Within the workdirectory, you will see 1466 | 1467 | =over 1468 | 1469 | =item B Certificate revocation list 1470 | 1471 | =item B Certificate Authority Certificate 1472 | 1473 | =item B Certificate Authority Key 1474 | 1475 | =item B Archive of all files generated 1476 | 1477 | =item B Junk used in the production of certificates 1478 | 1479 | =item B Directory of trusted certificates ala C for verification purposes. 1480 | 1481 | =back 1482 | 1483 | Under C you will have a bunch of directories, one per common 1484 | name. Under those directories you will see files like "ca.crt" 1485 | "server.crt" "client.crt" "mail.crt" or "subca.crt" for the various 1486 | forms of certificates, plus ".key" variants of these files which 1487 | contain the private key. There will typically also be several other 1488 | files with names like ".der" ".jks" ".p12" and ".pem" which provide 1489 | variants of these same certificates or keys and certificates. If you 1490 | need those variants, feel free to take them. The ".p12" has a 1491 | required password, which is "mypass". 1492 | 1493 | 1494 | =head1 BUGS 1495 | 1496 | This Certificate Authority is designed for use by a skilled, trusted 1497 | human who is generating or validating the inputs to the script. 1498 | The remaining items are specific instances of this. 1499 | 1500 | =head2 Separation of key/csr generation from crt signing 1501 | 1502 | The key and csr is generated by the CA-baka instants before the signed 1503 | crt is generated. There is no prevision to accept CSRs from the 1504 | outside world and sign them. This probably wouldn't be too difficult. 1505 | 1506 | =head2 CRL 1507 | 1508 | The CRL is not a rotating window of short-lived valid CRLs, and there 1509 | is no particular method to attempt to publish the CRL when it is 1510 | generated. The CRLs are generally valid as long (or longer!!) as the 1511 | certificates which it purports to revoke, and this means attacks 1512 | trying to prevent a client from ever getting an updated CRL might be 1513 | very successful. 1514 | 1515 | =head2 Unsanitized input 1516 | 1517 | The script does not attempt to deal with "IDN Homograph Attacks" or 1518 | "CN attacks against system tools". For example, the system uses a 1519 | Cyrillic "а" (← I typed the right character which looks identical to 1520 | an "a". Your processing may vary.) instead of an ASCII "a", well 1521 | that is just too bad. Likewise, you might experience problems if the 1522 | user attempts to use a CN which contains ";" or "&" or "$" or perhaps 1523 | certain characters which attack the terminal by stuffing characters if 1524 | you C<`ls`> the wrong directory. 1525 | 1526 | The system does attempt to do B sanitization, specifically 1527 | forbidding "'" or ^A-^Z control characters, and passing CN around in 1528 | single quotes. It has not been carefully audited to be free from 1529 | defects. 1530 | 1531 | =head2 Key Encryption 1532 | 1533 | Basically none of the keys or other files generated have encrypted 1534 | keys, except in cases where the format/tool (I'm looking at you 1535 | pkcs12) forces a key. Even then the key is static and stupid 1536 | ("mypass"). 1537 | 1538 | =head2 Ability to generate multipurpose certificates 1539 | 1540 | You cannot generate a certificate for being both an SSL server and a 1541 | SSL client. 1542 | 1543 | =head2 Ability to generate multiple certificates per CA 1544 | 1545 | Even though would be no filename conflict (so this could be added) you 1546 | cannot generate a server certificate for CN:hosta.example.com and a 1547 | client certificate for the same CN. 1548 | 1549 | =head2 Other CA best practices 1550 | 1551 | Most likely there are other best practices by CAs which are not being 1552 | followed. 1553 | 1554 | =head2 Crypto modification caching 1555 | 1556 | The public key algorithm, hash length, and key length/curvename is not 1557 | cached when you create the CA and it should be. Any crypto changes 1558 | will only apply to whatever certificate you set them on and all 1559 | furture certs will be back to default crypto. 1560 | 1561 | =head1 COPYRIGHT 1562 | 1563 | Copyright ⓒ 2012-2015 BAKA - See LICENSE.TXT 1564 | 1565 | If you think of it as a GPL2 without the ability to upgrade or the 1566 | linkage restriction, you will not go far wrong. 1567 | 1568 | 1569 | =head2 Disclaimer 1570 | 1571 | This is covered in stronger and more binding detail in the license, 1572 | but the copyright holders make no representation about the suitability 1573 | of this program for any purpose. It is provided “as is” without 1574 | expressed or implied warranty. 1575 | 1576 | 1577 | =head1 AUTHORS 1578 | 1579 | Seth Robertson L 1580 | 1581 | CA-baka home: L<< http://github.com/SethRobertson/CA-baka >> 1582 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | 2 | This license was created as a derivative of the "GNU LESSER GENERAL 3 | PUBLIC LICENSE Version 2.1, February 1999" however, it is NOT 4 | identical to that license. Specifically, the terms of the GNU LESSER 5 | GENERAL PUBLIC LICENSE Version 2.1 section 3 and 13 are not 6 | applicable. 7 | 8 | ---------------------------------------------------------------------- 9 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 10 | 11 | 0. This License Agreement applies to any software library or other 12 | program which contains a notice placed by the copyright holder or 13 | other authorized party saying it may be distributed under the terms of 14 | this License. Each licensee is addressed as "you". 15 | 16 | A "library" means a collection of software functions and/or data 17 | prepared so as to be conveniently linked with application programs 18 | (which use some of those functions and data) to form executables. 19 | 20 | The "Library", below, refers to any such software library or work 21 | which has been distributed under these terms. A "work based on the 22 | Library" means either the Library or any derivative work under 23 | copyright law: that is to say, a work containing the Library or a 24 | portion of it, either verbatim or with modifications and/or translated 25 | straightforwardly into another language. (Hereinafter, translation is 26 | included without limitation in the term "modification".) 27 | 28 | "Source code" for a work means the preferred form of the work for 29 | making modifications to it. For a library, complete source code means 30 | all the source code for all modules it contains, plus any associated 31 | interface definition files, plus the scripts used to control compilation 32 | and installation of the library. 33 | 34 | Activities other than copying, distribution and modification are not 35 | covered by this License; they are outside its scope. The act of 36 | running a program using the Library is not restricted, and output from 37 | such a program is covered only if its contents constitute a work based 38 | on the Library (independent of the use of the Library in a tool for 39 | writing it). Whether that is true depends on what the Library does 40 | and what the program that uses the Library does. 41 | 42 | 1. You may copy and distribute verbatim copies of the Library's 43 | complete source code as you receive it, in any medium, provided that 44 | you conspicuously and appropriately publish on each copy an 45 | appropriate copyright notice and disclaimer of warranty; keep intact 46 | all the notices that refer to this License and to the absence of any 47 | warranty; and distribute a copy of this License along with the 48 | Library. 49 | 50 | You may charge a fee for the physical act of transferring a copy, 51 | and you may at your option offer warranty protection in exchange for a 52 | fee. 53 | 54 | 2. You may modify your copy or copies of the Library or any portion 55 | of it, thus forming a work based on the Library, and copy and 56 | distribute such modifications or work under the terms of Section 1 57 | above, provided that you also meet all of these conditions: 58 | 59 | a) The modified work must itself be a software library. 60 | 61 | b) You must cause the files modified to carry prominent notices 62 | stating that you changed the files and the date of any change. 63 | 64 | c) You must cause the whole of the work to be licensed at no 65 | charge to all third parties under the terms of this License. 66 | 67 | d) If a facility in the modified Library refers to a function or a 68 | table of data to be supplied by an application program that uses 69 | the facility, other than as an argument passed when the facility 70 | is invoked, then you must make a good faith effort to ensure that, 71 | in the event an application does not supply such function or 72 | table, the facility still operates, and performs whatever part of 73 | its purpose remains meaningful. 74 | 75 | (For example, a function in a library to compute square roots has 76 | a purpose that is entirely well-defined independent of the 77 | application. Therefore, Subsection 2d requires that any 78 | application-supplied function or table used by this function must 79 | be optional: if the application does not supply it, the square 80 | root function must still compute square roots.) 81 | 82 | These requirements apply to the modified work as a whole. If 83 | identifiable sections of that work are not derived from the Library, 84 | and can be reasonably considered independent and separate works in 85 | themselves, then this License, and its terms, do not apply to those 86 | sections when you distribute them as separate works. But when you 87 | distribute the same sections as part of a whole which is a work based 88 | on the Library, the distribution of the whole must be on the terms of 89 | this License, whose permissions for other licensees extend to the 90 | entire whole, and thus to each and every part regardless of who wrote 91 | it. 92 | 93 | Thus, it is not the intent of this section to claim rights or contest 94 | your rights to work written entirely by you; rather, the intent is to 95 | exercise the right to control the distribution of derivative or 96 | collective works based on the Library. 97 | 98 | In addition, mere aggregation of another work not based on the Library 99 | with the Library (or with a work based on the Library) on a volume of 100 | a storage or distribution medium does not bring the other work under 101 | the scope of this License. 102 | 103 | 3. SECTION THREE HAS BEEN ELIDED. 104 | 105 | 4. You may copy and distribute the Library (or a portion or 106 | derivative of it, under Section 2) in object code or executable form 107 | under the terms of Sections 1 and 2 above provided that you accompany 108 | it with the complete corresponding machine-readable source code, which 109 | must be distributed under the terms of Sections 1 and 2 above on a 110 | medium customarily used for software interchange. 111 | 112 | If distribution of object code is made by offering access to copy 113 | from a designated place, then offering equivalent access to copy the 114 | source code from the same place satisfies the requirement to 115 | distribute the source code, even though third parties are not 116 | compelled to copy the source along with the object code. 117 | 118 | 5. A program that contains no derivative of any portion of the 119 | Library, but is designed to work with the Library by being compiled or 120 | linked with it, is called a "work that uses the Library". Such a 121 | work, in isolation, is not a derivative work of the Library, and 122 | therefore falls outside the scope of this License. 123 | 124 | However, linking a "work that uses the Library" with the Library 125 | creates an executable that is a derivative of the Library (because it 126 | contains portions of the Library), rather than a "work that uses the 127 | library". The executable is therefore covered by this License. 128 | Section 6 states terms for distribution of such executables. 129 | 130 | When a "work that uses the Library" uses material from a header file 131 | that is part of the Library, the object code for the work may be a 132 | derivative work of the Library even though the source code is not. 133 | Whether this is true is especially significant if the work can be 134 | linked without the Library, or if the work is itself a library. The 135 | threshold for this to be true is not precisely defined by law. 136 | 137 | If such an object file uses only numerical parameters, data 138 | structure layouts and accessors, and small macros and small inline 139 | functions (ten lines or less in length), then the use of the object 140 | file is unrestricted, regardless of whether it is legally a derivative 141 | work. (Executables containing this object code plus portions of the 142 | Library will still fall under Section 6.) 143 | 144 | Otherwise, if the work is a derivative of the Library, you may 145 | distribute the object code for the work under the terms of Section 6. 146 | Any executables containing that work also fall under Section 6, 147 | whether or not they are linked directly with the Library itself. 148 | 149 | 6. As an exception to the Sections above, you may also combine or 150 | link a "work that uses the Library" with the Library to produce a 151 | work containing portions of the Library, and distribute that work 152 | under terms of your choice, provided that the terms permit 153 | modification of the work for the customer's own use and reverse 154 | engineering for debugging such modifications. 155 | 156 | You must give prominent notice with each copy of the work that the 157 | Library is used in it and that the Library and its use are covered by 158 | this License. You must supply a copy of this License. If the work 159 | during execution displays copyright notices, you must include the 160 | copyright notice for the Library among them, as well as a reference 161 | directing the user to the copy of this License. Also, you must do one 162 | of these things: 163 | 164 | a) Accompany the work with the complete corresponding 165 | machine-readable source code for the Library including whatever 166 | changes were used in the work (which must be distributed under 167 | Sections 1 and 2 above); and, if the work is an executable linked 168 | with the Library, with the complete machine-readable "work that 169 | uses the Library", as object code and/or source code, so that the 170 | user can modify the Library and then relink to produce a modified 171 | executable containing the modified Library. (It is understood 172 | that the user who changes the contents of definitions files in the 173 | Library will not necessarily be able to recompile the application 174 | to use the modified definitions.) 175 | 176 | b) Use a suitable shared library mechanism for linking with the 177 | Library. A suitable mechanism is one that (1) uses at run time a 178 | copy of the library already present on the user's computer system, 179 | rather than copying library functions into the executable, and (2) 180 | will operate properly with a modified version of the library, if 181 | the user installs one, as long as the modified version is 182 | interface-compatible with the version that the work was made with. 183 | 184 | c) Accompany the work with a written offer, valid for at 185 | least three years, to give the same user the materials 186 | specified in Subsection 6a, above, for a charge no more 187 | than the cost of performing this distribution. 188 | 189 | d) If distribution of the work is made by offering access to copy 190 | from a designated place, offer equivalent access to copy the above 191 | specified materials from the same place. 192 | 193 | e) Verify that the user has already received a copy of these 194 | materials or that you have already sent this user a copy. 195 | 196 | For an executable, the required form of the "work that uses the 197 | Library" must include any data and utility programs needed for 198 | reproducing the executable from it. However, as a special exception, 199 | the materials to be distributed need not include anything that is 200 | normally distributed (in either source or binary form) with the major 201 | components (compiler, kernel, and so on) of the operating system on 202 | which the executable runs, unless that component itself accompanies 203 | the executable. 204 | 205 | It may happen that this requirement contradicts the license 206 | restrictions of other proprietary libraries that do not normally 207 | accompany the operating system. Such a contradiction means you cannot 208 | use both them and the Library together in an executable that you 209 | distribute. 210 | 211 | 7. You may place library facilities that are a work based on the 212 | Library side-by-side in a single library together with other library 213 | facilities not covered by this License, and distribute such a combined 214 | library, provided that the separate distribution of the work based on 215 | the Library and of the other library facilities is otherwise 216 | permitted, and provided that you do these two things: 217 | 218 | a) Accompany the combined library with a copy of the same work 219 | based on the Library, uncombined with any other library 220 | facilities. This must be distributed under the terms of the 221 | Sections above. 222 | 223 | b) Give prominent notice with the combined library of the fact 224 | that part of it is a work based on the Library, and explaining 225 | where to find the accompanying uncombined form of the same work. 226 | 227 | 8. You may not copy, modify, sublicense, link with, or distribute 228 | the Library except as expressly provided under this License. Any 229 | attempt otherwise to copy, modify, sublicense, link with, or 230 | distribute the Library is void, and will automatically terminate your 231 | rights under this License. However, parties who have received copies, 232 | or rights, from you under this License will not have their licenses 233 | terminated so long as such parties remain in full compliance. 234 | 235 | 9. You are not required to accept this License, since you have not 236 | signed it. However, nothing else grants you permission to modify or 237 | distribute the Library or its derivative works. These actions are 238 | prohibited by law if you do not accept this License. Therefore, by 239 | modifying or distributing the Library (or any work based on the 240 | Library), you indicate your acceptance of this License to do so, and 241 | all its terms and conditions for copying, distributing or modifying 242 | the Library or works based on it. 243 | 244 | 10. Each time you redistribute the Library (or any work based on the 245 | Library), the recipient automatically receives a license from the 246 | original licensor to copy, distribute, link with or modify the Library 247 | subject to these terms and conditions. You may not impose any further 248 | restrictions on the recipients' exercise of the rights granted herein. 249 | You are not responsible for enforcing compliance by third parties with 250 | this License. 251 | 252 | 11. If, as a consequence of a court judgment or allegation of patent 253 | infringement or for any other reason (not limited to patent issues), 254 | conditions are imposed on you (whether by court order, agreement or 255 | otherwise) that contradict the conditions of this License, they do not 256 | excuse you from the conditions of this License. If you cannot 257 | distribute so as to satisfy simultaneously your obligations under this 258 | License and any other pertinent obligations, then as a consequence you 259 | may not distribute the Library at all. For example, if a patent 260 | license would not permit royalty-free redistribution of the Library by 261 | all those who receive copies directly or indirectly through you, then 262 | the only way you could satisfy both it and this License would be to 263 | refrain entirely from distribution of the Library. 264 | 265 | If any portion of this section is held invalid or unenforceable under any 266 | particular circumstance, the balance of the section is intended to apply, 267 | and the section as a whole is intended to apply in other circumstances. 268 | 269 | It is not the purpose of this section to induce you to infringe any 270 | patents or other property right claims or to contest validity of any 271 | such claims; this section has the sole purpose of protecting the 272 | integrity of the free software distribution system which is 273 | implemented by public license practices. Many people have made 274 | generous contributions to the wide range of software distributed 275 | through that system in reliance on consistent application of that 276 | system; it is up to the author/donor to decide if he or she is willing 277 | to distribute software through any other system and a licensee cannot 278 | impose that choice. 279 | 280 | This section is intended to make thoroughly clear what is believed to 281 | be a consequence of the rest of this License. 282 | 283 | 12. If the distribution and/or use of the Library is restricted in 284 | certain countries either by patents or by copyrighted interfaces, the 285 | original copyright holder who places the Library under this License may add 286 | an explicit geographical distribution limitation excluding those countries, 287 | so that distribution is permitted only in or among countries not thus 288 | excluded. In such case, this License incorporates the limitation as if 289 | written in the body of this License. 290 | 291 | 13. SECTION THIRTEEN HAS BEEN ELIDED 292 | 293 | 14. If you wish to incorporate parts of the Library into other free 294 | programs whose distribution conditions are incompatible with these, 295 | write to the author to ask for permission. For software which is 296 | copyrighted by the Free Software Foundation, write to the Free 297 | Software Foundation; we sometimes make exceptions for this. Our 298 | decision will be guided by the two goals of preserving the free status 299 | of all derivatives of our free software and of promoting the sharing 300 | and reuse of software generally. 301 | 302 | NO WARRANTY 303 | 304 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 305 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 306 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 307 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 308 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 309 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 310 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 311 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 312 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 313 | 314 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 315 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 316 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 317 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 318 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 319 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 320 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 321 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 322 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 323 | DAMAGES. 324 | 325 | END OF TERMS AND CONDITIONS 326 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | prefix=/usr/local 2 | bindir=${prefix}/sbin 3 | mandir=${prefix}/share/man 4 | man8dir=${mandir}/man8 5 | 6 | PROG=CA-baka 7 | MAN=$(PROG).8 8 | TARGETS=$(PROG) $(MAN) 9 | 10 | default: README test 11 | 12 | README: $(PROG) 13 | pod2text < $^ > $@ 14 | 15 | install: $(TARGETS) 16 | mkdir -p $(DESTDIR)$(man8dir) $(DESTDIR)$(bindir) 17 | install -m 444 $(MAN) $(DESTDIR)$(man8dir) 18 | if [ -d .git ]; then \ 19 | VERSION=`./$(PROG) --version`; \ 20 | sed "s/{UNTAGGED}/$${VERSION}/" $(PROG) > $(DESTDIR)$(bindir)/$(PROG); \ 21 | chmod 755 $(DESTDIR)$(bindir)/$(PROG); \ 22 | else \ 23 | install -m 755 $(PROG) $(DESTDIR)$(bindir)/; \ 24 | fi 25 | 26 | $(MAN): $(PROG) 27 | pod2man < $^ > $@ 28 | 29 | clean: 30 | rm -rf *~ $(MAN) test-workdir 31 | 32 | .PHONY: test test1 test2 test3 test4 test5 test6 test7 test8 test9 testN default install clean 33 | 34 | 35 | 36 | test: test1 test2 test3 test4 test5 test6 test7 test8 testN 37 | 38 | test1: 39 | rm -rf test-workdir 40 | ./CA-baka --quiet --workdir test-workdir -C US --ST NY -L "New York" -O "Mythical NY Company" --newca ca.example.com "" 41 | ./CA-baka --quiet --workdir test-workdir --newserver server.example.com 42 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/server.example.com/server.crt 43 | ./CA-baka --quiet --workdir test-workdir --newclient client.example.com 44 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/client.example.com/client.crt 45 | ./CA-baka --quiet --workdir test-workdir --newmail mail.example.com 46 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/mail.example.com/mail.crt 47 | ./CA-baka --quiet --workdir test-workdir --newcoder coder.example.com 48 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/coder.example.com/coder.crt 49 | ./CA-baka --quiet --workdir test-workdir --newserver server2.example.com --altnames URI:http://server2.example.com --altnames IP:127.0.0.1 --altnames DNS:server20-example-com 50 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/server2.example.com/server.crt 51 | ./CA-baka --quiet --workdir test-workdir --newclient unwanted.example.com 52 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/unwanted.example.com/client.crt 53 | ./CA-baka --quiet --workdir test-workdir --revoke unwanted.example.com 54 | @echo "Next command should generate errors" 55 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/unwanted.example.com-revoked-*/client.crt && exit 1 || exit 0 56 | @echo "Previous revoke test succeeded" 57 | rm -rf test-workdir 58 | 59 | test2: 60 | rm -rf test-workdir 61 | @echo "Next command should generate errors" 62 | ./CA-baka --quiet --workdir test-workdir -C US --ST NY -L "New York" -O "Mythical NY Company" --newca ca.example.com "" --newserver server.example.com "" --newclient client.example.com "" --newmail mail.example.com "" --newcoder coder.example.com "" --newclient unwanted.example.com "" && exit 1 || exit 0 63 | @echo "Previous bad-options test succeeded" 64 | ./CA-baka --quiet --workdir test-workdir -C US --ST NY -L "New York" -O "Mythical NY Company" --newca ca.example.com "" --newserver server.example.com "" --newclient client.example.com "" --newmail mail.example.com "" --newcoder coder.example.com "" 65 | ./CA-baka --quiet --workdir test-workdir --newclient unwanted.example.com 66 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/server.example.com/server.crt --verify test-workdir/archive/client.example.com/client.crt --verify test-workdir/archive/mail.example.com/mail.crt --verify test-workdir/archive/coder.example.com/coder.crt --verify test-workdir/archive/server2.example.com/server.crt --verify test-workdir/archive/unwanted.example.com/client.crt 67 | ./CA-baka --quiet --workdir test-workdir --newserver server2.example.com --altnames URI:http://server2.example.com --altnames IP:127.0.0.1 --altnames DNS:server20-example-com 68 | @echo "Next command should generate errors" 69 | ./CA-baka --quiet --workdir test-workdir --newserver server2.example.com --altnames URI:http://server2.example.com --altnames IP:127.0.0.1 --altnames DNS:server20-example-com --newclient client2.example.com && exit 1 || exit 0 70 | @echo "Previous bad-options test succeeded" 71 | ./CA-baka --quiet --workdir test-workdir --revoke unwanted.example.com 72 | @echo "Next command should generate errors" 73 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/unwanted.example.com-revoked-*/client.crt && exit 1 || exit 0 74 | @echo "Previous revoke test succeeded" 75 | for f in test-workdir/archive/server.example.com/server.crt test-workdir/archive/client.example.com/client.crt test-workdir/archive/mail.example.com/mail.crt test-workdir/archive/coder.example.com/coder.crt; do ./CA-baka --quiet --workdir test-workdir --verify $$f; done 76 | rm -rf test-workdir 77 | 78 | test3: 79 | rm -rf test-workdir 80 | ./CA-baka --quiet --workdir test-workdir -C US --ST NY -L "New York" -O "Mythical NY Company" --newca ca.example.com "" --keylen 4096 --md sha512 81 | ./CA-baka --quiet --workdir test-workdir --keylen 4096 --md sha512 --newserver server.example.com 82 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/server.example.com/server.crt 83 | openssl x509 -in test-workdir/ca.crt -text -noout | grep sha512 84 | openssl x509 -in test-workdir/ca.crt -text -noout | grep "4096 bit" 85 | rm -rf test-workdir 86 | 87 | test4: 88 | rm -rf test-workdir 89 | ./CA-baka --quiet --workdir test-workdir -C US --ST NY -L "New York" -O "Mythical NY Company" --newca ca.example.com "" --pk ecc 90 | ./CA-baka --quiet --workdir test-workdir --pk ecc --newserver server.example.com 91 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/server.example.com/server.crt 92 | ./CA-baka --quiet --workdir test-workdir --pk ecc --keylen prime256v1 --newserver server2.example.com 93 | openssl x509 -in test-workdir/ca.crt -text -noout | grep ecdsa 94 | openssl x509 -in test-workdir/archive/server2.example.com/server.crt -text -noout | grep ecdsa 95 | rm -rf test-workdir 96 | 97 | test5: 98 | echo dsa seems to not be working any more 99 | # rm -rf test-workdir 100 | # ./CA-baka -verbose --workdir test-workdir -C US --ST NY -L "New York" -O "Mythical NY Company" --newca ca.example.com "" --pk dsa 101 | # ./CA-baka --quiet --workdir test-workdir --pk dsa --newserver server.example.com 102 | # ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/server.example.com/server.crt 103 | # ./CA-baka --quiet --workdir test-workdir --pk dsa --keylen 4096 --newserver server2.example.com 104 | # openssl x509 -in test-workdir/ca.crt -text -noout | egrep " dsaWith| dsa_with" 105 | # rm -rf test-workdir 106 | 107 | test6: 108 | rm -rf test-workdir 109 | ./CA-baka --quiet --workdir test-workdir -C US --ST NY -L "New York" -O "Mythical NY Company" --newca ca.example.com "" --constraints "permitted;DNS:example.com" 110 | ./CA-baka --quiet --workdir test-workdir --altnames DNS:server.example.com --newserver server.example.com 111 | ./CA-baka --quiet --workdir test-workdir --altnames DNS:badserver.example.org --newserver badserver.example.org 112 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/server.example.com/server.crt 113 | @echo The following test should fail as out-of-permitted-subtree 114 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/badserver.example.org/server.crt && exit 1 || echo 0 115 | rm -rf test-workdir 116 | 117 | test7: 118 | rm -rf test-workdir 119 | ./CA-baka --quiet --workdir test-workdir -C US --ST NY -L "New York" -O "Mythical NY Company" --newca ca.example.com "" --constraints "permitted;DNS:example.com" --constraints "permitted;DNS:example2.com" --constraints "excluded;DNS:x.example.com" 120 | ./CA-baka --quiet --workdir test-workdir --altnames DNS:server.example.com --newserver server.example.com 121 | ./CA-baka --quiet --workdir test-workdir --altnames DNS:server.x.example2.com --newserver server.x.example2.com 122 | ./CA-baka --quiet --workdir test-workdir --altnames DNS:x.example.com --newserver x.example.com 123 | ./CA-baka --quiet --workdir test-workdir --altnames DNS:badserver.example.org --newserver badserver.example.org 124 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/server.example.com/server.crt 125 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/server.x.example2.com/server.crt 126 | @echo The following test should fail as out-of-permitted-subtree 127 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/x.example.com/server.crt && exit 1 || echo 0 128 | @echo The following test should fail as out-of-permitted-subtree 129 | ./CA-baka --quiet --workdir test-workdir --verify test-workdir/archive/badserver.example.org/server.crt && exit 1 || echo 0 130 | rm -rf test-workdir 131 | 132 | test8: 133 | rm -rf test-workdir 134 | @echo The following test should fail with certificate not yet valid 135 | ./CA-baka --quiet --start `date -d 'tomorrow' +%Y%m%d%H%M%SZ` --workdir test-workdir -C US --ST NY -L "New York" -O "Mythical NY Company" --newca ca.example.com "" 136 | ./CA-baka --quiet --workdir test-workdir --altnames DNS:server.example.com --newserver server.example.com 137 | openssl verify -CAfile test-workdir/ca.crt -CRLfile test-workdir/ca.crl test-workdir/archive/server.example.com/server.crt && echo 1 || echo 0 138 | rm -rf test-workdir 139 | ./CA-baka --quiet --start 19700303233134Z --workdir test-workdir -C US --ST NY -L "New York" -O "Mythical NY Company" --newca ca.example.com "" 140 | ./CA-baka --quiet --workdir test-workdir --altnames DNS:server.example.com --newserver server.example.com 141 | openssl verify -CAfile test-workdir/ca.crt -CRLfile test-workdir/ca.crl test-workdir/archive/server.example.com/server.crt 142 | rm -rf test-workdir 143 | 144 | 145 | # If you add more tests, add them to the test: line above 146 | testN: 147 | @echo All previous tests successful. 148 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | NAME 2 | CA-baka - Simple X509 Certificate Authority/Generation Script 3 | 4 | The sysadmin's and network security developer's best friend. 5 | 6 | SYNOPSIS 7 | CA-baka [--workdir directory] 8 | [--country|--C country] [--state|--ST state] [--locality|--L city] 9 | [--organization|--O company] [--organizationalunit|--OU department] 10 | [--days number] [--keylen bitlen] 11 | [--md sha256|sha224|sha384|sha512|sha1] [--pk rsa|ecc|dsa] 12 | [--newca CN Email] [--subca CN Email NewWorkDir] 13 | [--newserver CN [Email]] [--newclient CN [Email]] 14 | [--newmail CN [Email]] [--newcoder CN [Email]] 15 | [--altnames TYPE:value]... [--constraints METHOD;TYPE:value]... 16 | [--revoke CN] [--renew] [--verify filename] [--force] 17 | [--verbose]+ [-v]+ [--quiet] 18 | 19 | DESCRIPTION 20 | This Certificate Authority is designed for use by a skilled, trusted 21 | human who is generating full cryptographic packages for clients, 22 | servers, or peoples to blindly install without thought, without having 23 | to modify any configuration files or do special things with your shell 24 | before running commands, or the like. The very model of a centralized CA 25 | dictatorship (I'll just keep those keys for backup purposes in case you 26 | happen to lose them, I won't use them to decrypt your future traffic, or 27 | forge your signatures, honest!). 28 | 29 | Everyone and their dog seems to have a certificate authority/generation 30 | script, but all of the ones I have seen so far, frankly, suck donkey 31 | balls for usability, documentation, and sanity. The most common ones 32 | "Easy CA" and the rather anonymously named "CA" used by RHEL, are 33 | particularly annoying. This one does what I have wanted to do each and 34 | every time I have wanted to generate certificates, simply and cleanly. 35 | 36 | All of the most common certificate authority needs are provided: initial 37 | master certificate authority key/crt generation, subsidiary certificate 38 | authority key/crt generation, server key/crt generation, client key/crt 39 | generation, email key/crt generation, and certificate revocation. 40 | 41 | There is limited ability to modify the most popular information, 42 | including X509 subject identifier material, validity length, and key 43 | length. Defaults are available for all values (except for X509 subject 44 | identifier material during the initial setup of the master certificate 45 | authority). 46 | 47 | The first invocation of CA-baka (per --workdir) requires that you use 48 | "--newca" with "--country", "--state", "--locality", and 49 | "--organization" set to properly initialize the certificate authority. 50 | Afterwards (or indeed at the same time as the "--newca" invocation, you 51 | can issue other certificates using one or more of "--subca", 52 | "--newserver", "--newclient", "--newmail", "--newcoder" or revoke other 53 | certificates using "--revoke". Other arguments modify the behavior of 54 | the system. 55 | 56 | OPTIONS 57 | The options control everything, and the script is not going to do 58 | anything (except perhaps error out depending on configuration) if you do 59 | not provide arguments. 60 | 61 | --workdir *directory* 62 | Set the certificate authority working directory. If this is not 63 | specified, the directory ../etc/CA relative to the location of the 64 | "CA-baka" program will be used. When first configuring the system 65 | "--newca" the working directory must not exist. 66 | 67 | --country|C *countrycode* 68 | Set the X509 C country code. This is required when using "--newca". 69 | Other executions, it may be specified or the value from the 70 | "--newca" call will be used. You may use quotes to send 71 | empty/complex/multiword identifiers. 72 | 73 | --state|ST *state* 74 | Set the X509 ST state. This is required when using "--newca". Other 75 | executions, it may be specified or the value from the "--newca" call 76 | will be used. You may use quotes to send empty/complex/multiword 77 | identifiers. 78 | 79 | --locality|L *city* 80 | Set the X509 L locality, typically the city name. This is required 81 | when using "--newca". Other executions, it may be specified or the 82 | value from the "--newca" call will be used. You may use quotes to 83 | send empty/complex/multiword identifiers. 84 | 85 | --organization|O *company* 86 | Set the X509 O organization, typically the company name. This is 87 | required when using "--newca". Other executions, it may be specified 88 | or the value from the "--newca" call will be used. You may use 89 | quotes to send empty/complex/multiword identifiers. 90 | 91 | --organizationalunit|OU *department* 92 | Set the X509 OU organizational unit, typically the department name. 93 | This is also optional. Non-initial executions, it may be specified 94 | or the (possibly empty) value from the "--newca" call will be used. 95 | You may use quotes to send empty/complex/multiword identifiers. 96 | 97 | --newca *CN Email* 98 | Request that the initial certificate authority be set up with the 99 | indicated common name and email address. You may use quotes to send 100 | empty/complex/multiword identifiers. 101 | 102 | The generated certificate, key, and various alternate forms of that 103 | data will be available in the work directory's archive subdirectory, 104 | in a further subdirectory named by the CN. Distribution of this 105 | material is left as an exercise to the reader. 106 | 107 | --subca *CN Email NewWorkDirectory* 108 | Request that a subsidiary certificate authority be set up with the 109 | indicated common name and email address, in the new work directory 110 | specified. This is much like creating an entirely distinct 111 | certificate authority with "--newca" except: (1) the certificate is 112 | signed by the parent certificate, (2) you cannot create lower level 113 | subsidiary certificates authorities, (3) the X509 subject identifier 114 | material is defaulted from the "--newca" call (but of course may be 115 | overridden on this execution, the values in play at the time of 116 | "--subca" will be the new defaults for the "--subca"'s work 117 | directory. You may use quotes to send empty/complex/multiword 118 | identifiers. 119 | 120 | The generated certificate, key, and various alternate forms of that 121 | data will be available in the work directory's archive subdirectory, 122 | in a further subdirectory named by the CN. Distribution of this 123 | material is left as an exercise to the reader. 124 | 125 | --newserver *CN [Email]* 126 | Request that a server certificate be generated with the indicated 127 | common name and the optional email address. You may use quotes to 128 | send empty/complex/multiword identifiers (and if you have other 129 | command line options after this one, you must specify an email 130 | address, though it may be empty. 131 | 132 | The generated certificate, key, and various alternate forms of that 133 | data will be available in the work directory's archive subdirectory, 134 | in a further subdirectory named by the CN. Distribution of this 135 | material is left as an exercise to the reader. 136 | 137 | --newclient *CN [Email]* 138 | Request that a client certificate be generated with the indicated 139 | common name and the optional email address. You may use quotes to 140 | send empty/complex/multiword identifiers (and if you have other 141 | command line options after this one, you must specify an email 142 | address, though it may be empty. 143 | 144 | The generated certificate, key, and various alternate forms of that 145 | data will be available in the work directory's archive subdirectory, 146 | in a further subdirectory named by the CN. Distribution of this 147 | material is left as an exercise to the reader. 148 | 149 | --newmail *CN [Email]* 150 | Request that a user mail certificate be generated with the indicated 151 | common name and the optional(recommended) email address. You may use 152 | quotes to send empty/complex/multiword identifiers (and if you have 153 | other command line options after this one, you must specify an email 154 | address, though it may be empty. 155 | 156 | The generated certificate, key, and various alternate forms of that 157 | data will be available in the work directory's archive subdirectory, 158 | in a further subdirectory named by the CN. Distribution of this 159 | material is left as an exercise to the reader. 160 | 161 | --newcoder *CN [Email]* 162 | Request that a code signing certificate be generated with the 163 | indicated common name and the optional(recommended) email address. 164 | You may use quotes to send empty/complex/multiword identifiers (and 165 | if you have other command line options after this one, you must 166 | specify an email address, though it may be empty. 167 | 168 | The generated certificate, key, and various alternate forms of that 169 | data will be available in the work directory's archive subdirectory, 170 | in a further subdirectory named by the CN. Distribution of this 171 | material is left as an exercise to the reader. 172 | 173 | --altnames *TYPE:value* 174 | Request that the certificate being generated on this execution be 175 | given the listed subject alternate name (SAN). You may only generate 176 | one certificate per execution if you have "--altnames" specified. 177 | This can be used to provide, eg, alternate hostnames for HTTPS 178 | server certificates (for multisite hosted domains) or alternate 179 | email address for mail certificates. 180 | 181 | Valid TYPEs are "email", "URI", "DNS", and "IP". Typically "DNS" and 182 | "IP" are used for server certificates, and "email" is used for mail 183 | certificates. 184 | 185 | When using "--altnames" you must specify the data (CN, email) you 186 | might have expected to be authories as part of the primary subject 187 | name as an alternate. So if you set the CN to host1.example.com, you 188 | must also provide DNS:host1.example.com as an SAN). 189 | 190 | You must specify this argument multiple times, one per SAN you are 191 | attempting provide. 192 | 193 | --constraints *METHOD;TYPE:value* 194 | Request that the certificate being generated on this execution be 195 | given the listed name constraints. This is typically done for CA and 196 | sub-CA certificates to limit the scope of what damage a compromised 197 | certificate might do. 198 | 199 | Valid METHODs are "permitted" and "excluded". 200 | 201 | Valid TYPEs are "email", "URI", "DNS", and "IP". Typically "DNS" and 202 | "IP" are used for server certificates, and "email" is used for mail 203 | certificates. 204 | 205 | Name contraints are not fully supported by all ssl implementations, 206 | and indeed OpenSSL seems to only really support it if there is a 207 | subject alternative name in the nominally constrainted certificate 208 | absent specific investigation by the client app. You should test 209 | your clients and servers with nameConstraints before you put them in 210 | production. 211 | 212 | You must specify this argument multiple times, one per constraint 213 | you are attempting provide. 214 | 215 | permitted;URL:http://.example.com permitted;IP:127.0.0.0/255.0.0.0 216 | permitted;DNS:.example.com permitted;email:.example.com 217 | excluded;email:.com 218 | 219 | --revoke *CN* 220 | Specify a desire to revoke a currently valid certificate. The 221 | existing certificate directory will be moved away to an alternate 222 | name and the certificate revocation list (CRL) will be regenerated. 223 | Distribution of said CRL is left as an exercise to the reader. 224 | 225 | --days *number* 226 | Override the default number of days a certificate will be valid for, 227 | relative to today. By default, normal certificates are valid for 365 228 | days (1 year) and CA certificates are valid for 1825 days (5 years). 229 | 230 | Note that issued certificates cannot by default have an expiration 231 | date greater than the certifying authority's certificate expiration 232 | date (you can use --force to bypass this check, but it is a bad idea 233 | to do so, since after that date the issued certificate will no 234 | longer validate). The corollary is that Certificate Authority 235 | Certificates should probably have a fairly long lifetime. The 236 | corollary's corollary is that your should protect your CA key well. 237 | 238 | --crldays *number* 239 | Override the default number of days the Certificate Revocation List 240 | (CRL) will be valid for, relative to today. By default, CRL 241 | Certificates are valid for 1825 days (5 years). 242 | 243 | Unless you have an automated process to renew and manage the CRL 244 | (unlikely if you are using this program!!), you likely will want the 245 | CRL valid for as long as the CA is valid; since correct applications 246 | will stop validating certificates if the CRL has expired. 247 | 248 | --start *timestamp* 249 | Override the default certificate validity start date (24 hours ago 250 | from "now"). A suitable way to specify a desired start timestamp is 251 | using a command like: `date -d 'May 15 last year' +%Y%m%d%H%M%SZ` 252 | 253 | --md *hash algorthms* 254 | Override the default hash algorithm for a certificate. The default 255 | algorithm is currently sha256. See `openssl dgst -h` to see a list 256 | of supported hash algorithms. 257 | 258 | --pk *public key algorthm* 259 | Override the default public key algorithm for a certificate. The 260 | default algorithm is currently RSA. Use `CA-baka --pk list` to see a 261 | list of supported public key algorithms. 262 | 263 | --keylen *bitlen*|*curvename* 264 | Override the default key length of a certificate. The default key 265 | length for RSA and DSA is 2048 bits, for ECC the default curve is 266 | secp224k1, secp384r1 (in order of preference, not that I am ecstatic 267 | with either curve). For ecc pk algorithms, the key length is used to 268 | communicate the curvename. 269 | 270 | `openssl ecparam -list_curves` shows you what curves are available. 271 | 272 | --renew 273 | Normally you are forbidden to generate a certificate for a CN you 274 | have generated a certificate for previously. However, as a special 275 | case, you may pass in the --renew option which will cause the 276 | existing certificate to be revoked, so that a fresh certificate can 277 | be generated. 278 | 279 | You use this option with the option(s) to generate a "new" 280 | certificate with an existing name. 281 | 282 | Doing this for your CA certificate (eg revoking your CA certificate) 283 | is a very bad idea, nothing good will come from it. You should 284 | instead just rotate/archive/rename/delete your CA working directory 285 | and start over, this time perhaps with a longer validity range and 286 | perhaps a rotating sub-CA system (which you can --renew, but should 287 | also just rotate/archive/rename/delete the sub-CA's working 288 | directory). 289 | 290 | --verify *filename|CN* 291 | Attempt to verify a certificate given a file to the certificate or 292 | the CN of the certificate (the latter using the saved certificate 293 | material). The CRL is checked to verify whether the certificate was 294 | revoked or not. The purposes the certificates are valid for are 295 | displayed. 296 | 297 | --force 298 | Bypass certain sanity checks (eg maximum certificate lifetime) 299 | 300 | --version 301 | Print the version of this program. 302 | 303 | --verbose|v 304 | Print more information when generating certificates. 305 | 306 | --quiet 307 | Print less information when generating certificates. 308 | 309 | EXAMPLES 310 | A typical usage goes something like: 311 | 312 | # Create certificate authority 313 | CA-baka --workdir /etc/CA -C US --ST NY -L "New York" -O "Mythical NY Company" --newca ca.example.com "" 314 | 315 | # Create web server certificate 316 | CA-baka --workdir /etc/CA --newserver www.example.com webmaster\@example.com 317 | 318 | # Create mail certificate plus all common aliases 319 | CA-baka --workdir /etc/CA --newserver mail.example.com postmaster\@example.com --altnames DNS:mail.example.com --altnames DNS:pop.example.com --altnames DNS:imap.example.com --altnames:smtp.example.com 320 | 321 | # Create VPN server certificate 322 | CA-baka --workdir /etc/CA --newserver vpn.example.com "" 323 | 324 | # Create specific user certificate for VPN 325 | CA-baka --workdir /etc/CA --OU VPN --newclient "Joe Luser" joe\@example.com 326 | CA-baka --workdir /etc/CA --OU VPN --newclient "Bob 6pack" bob\@example.com 327 | CA-baka --workdir /etc/CA --OU VPN --newclient "Martha Stewardess" mstew\@example.com 328 | 329 | # Revoke bad certificate 330 | CA-baka --workdir /etc/CA --OU VPN --revoke "Martha Stewardess" 331 | 332 | # Issue a certificate with non-default hash and longer rsa key 333 | CA-baka --md sha512 --keylen 8192 --workdir /etc/CA --OU VPN --newclient "Paranoid Pete" pete\@example.com 334 | 335 | # Issue a certificate with a different public key algorithms 336 | CA-baka --md sha512 --pk ecc --workdir /etc/CA --OU VPN --newclient "Eccentric Eliptical Chuck" chuck\@example.com 337 | 338 | FILES/DIRECTORIES 339 | Within the workdirectory, you will see 340 | 341 | ca.crl Certificate revocation list 342 | ca.crt Certificate Authority Certificate 343 | ca.key Certificate Authority Key 344 | archive/ Archive of all files generated 345 | tmp/ Junk used in the production of certificates 346 | trusted-certs/ Directory of trusted certificates ala "CApath" for 347 | verification purposes. 348 | 349 | Under "archive" you will have a bunch of directories, one per common 350 | name. Under those directories you will see files like "ca.crt" 351 | "server.crt" "client.crt" "mail.crt" or "subca.crt" for the various 352 | forms of certificates, plus ".key" variants of these files which contain 353 | the private key. There will typically also be several other files with 354 | names like ".der" ".jks" ".p12" and ".pem" which provide variants of 355 | these same certificates or keys and certificates. If you need those 356 | variants, feel free to take them. The ".p12" has a required password, 357 | which is "mypass". 358 | 359 | BUGS 360 | This Certificate Authority is designed for use by a skilled, trusted 361 | human who is generating or validating the inputs to the script. The 362 | remaining items are specific instances of this. 363 | 364 | Separation of key/csr generation from crt signing 365 | The key and csr is generated by the CA-baka instants before the signed 366 | crt is generated. There is no prevision to accept CSRs from the outside 367 | world and sign them. This probably wouldn't be too difficult. 368 | 369 | CRL 370 | The CRL is not a rotating window of short-lived valid CRLs, and there is 371 | no particular method to attempt to publish the CRL when it is generated. 372 | The CRLs are generally valid as long (or longer!!) as the certificates 373 | which it purports to revoke, and this means attacks trying to prevent a 374 | client from ever getting an updated CRL might be very successful. 375 | 376 | Unsanitized input 377 | The script does not attempt to deal with "IDN Homograph Attacks" or "CN 378 | attacks against system tools". For example, the system uses a Cyrillic 379 | "а" (← I typed the right character which looks identical to an "a". Your 380 | processing may vary.) instead of an ASCII "a", well that is just too 381 | bad. Likewise, you might experience problems if the user attempts to use 382 | a CN which contains ";" or "&" or "$" or perhaps certain characters 383 | which attack the terminal by stuffing characters if you `ls` the wrong 384 | directory. 385 | 386 | The system does attempt to do some sanitization, specifically forbidding 387 | "'" or ^A-^Z control characters, and passing CN around in single quotes. 388 | It has not been carefully audited to be free from defects. 389 | 390 | Key Encryption 391 | Basically none of the keys or other files generated have encrypted keys, 392 | except in cases where the format/tool (I'm looking at you pkcs12) forces 393 | a key. Even then the key is static and stupid ("mypass"). 394 | 395 | Ability to generate multipurpose certificates 396 | You cannot generate a certificate for being both an SSL server and a SSL 397 | client. 398 | 399 | Ability to generate multiple certificates per CA 400 | Even though would be no filename conflict (so this could be added) you 401 | cannot generate a server certificate for CN:hosta.example.com and a 402 | client certificate for the same CN. 403 | 404 | Other CA best practices 405 | Most likely there are other best practices by CAs which are not being 406 | followed. 407 | 408 | Crypto modification caching 409 | The public key algorithm, hash length, and key length/curvename is not 410 | cached when you create the CA and it should be. Any crypto changes will 411 | only apply to whatever certificate you set them on and all furture certs 412 | will be back to default crypto. 413 | 414 | COPYRIGHT 415 | Copyright ⓒ 2012-2015 BAKA - See LICENSE.TXT 416 | 417 | If you think of it as a GPL2 without the ability to upgrade or the 418 | linkage restriction, you will not go far wrong. 419 | 420 | Disclaimer 421 | This is covered in stronger and more binding detail in the license, but 422 | the copyright holders make no representation about the suitability of 423 | this program for any purpose. It is provided “as is” without expressed 424 | or implied warranty. 425 | 426 | AUTHORS 427 | Seth Robertson 428 | 429 | CA-baka home: 430 | 431 | --------------------------------------------------------------------------------