|         |      1 #!/usr/bin/perl | 
|         |      2 # geht ueberhaupt nicht | 
|         |      3 use 5.010; | 
|         |      4 use strict; | 
|         |      5 use warnings; | 
|         |      6  | 
|         |      7 use if $ENV{DEBUG} => "Smart::Comments"; | 
|         |      8 my $pfad = "./CA"; | 
|         |      9  | 
|         |     10  | 
|         |     11 sub menue() { | 
|         |     12     my $eg = ""; | 
|         |     13  | 
|         |     14     while (1) { | 
|         |     15 	system("clear"); | 
|         |     16         print | 
|         |     17 " Willkommen beim SSL-Certificator, Ihrem nuetzlichem Perlprogramm\n zum einfachen erstellen von SSL-Zertifikaten.\n\n\n"; | 
|         |     18         print " Menue\n\n"; | 
|         |     19         print | 
|         |     20 "  n - Neues Root-Zertifikat erstellen\n  r - Request erstellen\n  s - Request signieren\n  w - Zertifikat wiederrufen\n  a - Annulierungsliste erstellen\n\n  q - Beenden\n\n "; | 
|         |     21         chomp($eg = <STDIN>); | 
|         |     22  | 
|         |     23 	given ($eg) { | 
|         |     24 	    when("q") {	# $eg ~~ "q" | 
|         |     25 		system('clear'); | 
|         |     26 		exit; | 
|         |     27 	    } | 
|         |     28 	    when("n") { | 
|         |     29 		system('clear'); | 
|         |     30 		&rootca; | 
|         |     31 	    } | 
|         |     32 	    default { | 
|         |     33 	    } | 
|         |     34 	} | 
|         |     35  | 
|         |     36 #	SWITCH: { | 
|         |     37 #	    ($eg eq "q") and do { ….; last SWITCH; } | 
|         |     38 #	    ($eq eq "n") and do { …; last SWITCH; } | 
|         |     39 #	} | 
|         |     40  | 
|         |     41 #        } elsif ($eg eq 's') { | 
|         |     42 #            system('clear'); | 
|         |     43 #            &sign; | 
|         |     44 #        } elsif ($eg eq 'r') { | 
|         |     45 #            system('clear'); | 
|         |     46 #            &request; | 
|         |     47 #        } | 
|         |     48 #        if ($eg eq 'w') { | 
|         |     49 #            system('clear'); | 
|         |     50 #            &revoke; | 
|         |     51 #        } | 
|         |     52 #        if ($eg eq 'a') { | 
|         |     53 #            system('clear'); | 
|         |     54 #            &revlist; | 
|         |     55 #        } | 
|         |     56       } | 
|         |     57 } | 
|         |     58  | 
|         |     59 sub rootca { | 
|         |     60     my $days; | 
|         |     61     my $pk; | 
|         |     62     my $rca; | 
|         |     63     print " Ihr Zertifikat wird erstellt. Bitte warten Sie.\n"; | 
|         |     64     print " ...\n "; | 
|         |     65  | 
|         |     66     mkdir($_ = "$pfad/newcerts") or die "Can't mkdir $_: $!\n"; | 
|         |     67  | 
|         |     68     system("mkdir -p $pfad/newcerts");	# mkdir / File::Path::make_path | 
|         |     69     system("mkdir -p $pfad/private"); | 
|         |     70  | 
|         |     71     # system("echo '01' >$pfad/serial"); | 
|         |     72     { | 
|         |     73 	open(my $x, ">", "$pfad/serial") or die; | 
|         |     74 	print $x "01\n"; | 
|         |     75 	close($x); | 
|         |     76     } | 
|         |     77  | 
|         |     78     #if (-e "$pfad/index.txt") {		    # RACE CONDITION | 
|         |     79     #    system("/bin/rm $pfad/index.txt");	    # rm -f | 
|         |     80     #} | 
|         |     81 #    unlink "$pfad/index.txt"; | 
|         |     82 #    system("/bin/touch $pfad/index.txt"); | 
|         |     83     { | 
|         |     84 	open(my $x, ">", "$pfad/index.txt"); | 
|         |     85 	close($x); | 
|         |     86     } | 
|         |     87     open(CONF, ">$pfad/openssl.cnf"); | 
|         |     88     print CONF | 
|         |     89 "#\n# OpenSSL configuration file.\n#\n\n# Establish working directory.\n\ndir = $pfad\n\n[ req ]\ndefault_bits\t\t= 1024\t\t# Size of keys\ndefault_keyfile\t\t= key.pem\t\t# name of generated keys\ndefault_md\t\t= md5\t\t# message digest algorithm\nstring_mask\t\t= nombstr\t\t# permitted characters\ndistinguished_name\t= req_distinguished_name\n\n[ req_distinguished_name ]\n# Variable name\t\t\t  Prompt string\n#----------------------\t  ----------------------------------\n0.organizationName\t= Organization Name (company)\norganizationalUnitName\t= Organizational Unit Name (department, division)\nemailAddress\t\t= Email Address\nemailAddress_max\t= 40\nlocalityName\t\t= Locality Name (city, district)\nstateOrProvinceName\t= State or Province Name (full name)\ncountryName\t\t= Country Name (2 letter code)\ncountryName_min\t\t= 2\ncountryName_max\t\t= 2\ncommonName\t\t= Common Name (hostname, IP, or your name)\ncommonName_max\t\t= 64\n\n# Default values for the above, for consistency and less typing.\n# Variable name\t\t\t  Value\n#------------------------------\t  ------------------------------\n0.organizationName_default\t= Your Company\nlocalityName_default\t\t= Your City\nstateOrProvinceName_default\t= Your Province\ncountryName_default\t\t= OO\n\n[ v3_ca ]\nbasicConstraints\t= CA:TRUE\nsubjectKeyIdentifier\t= hash\nauthorityKeyIdentifier\t= keyid:always,issuer:always"; | 
|         |     90     print CONF <<_EOT; | 
|         |     91 127.0.0.1	localhost  | 
|         |     92 127.0.1.1	jumper.schlittermann.de	jumper | 
|         |     93 212.80.235.130  pu.schlittermann.de ssl.schlittermann.de pu | 
|         |     94  | 
|         |     95 # The following lines are desirable for IPv6 capable hosts | 
|         |     96 ::1     ip6-localhost ip6-loopback | 
|         |     97 fe00::0 ip6-localnet | 
|         |     98 ff00::0 ip6-mcastprefix | 
|         |     99 ff02::1 ip6-allnodes | 
|         |    100 ff02::2 ip6-allrouters | 
|         |    101 _EOT | 
|         |    102  | 
|         |    103     close CONF; | 
|         |    104     <STDIN>; | 
|         |    105     do { | 
|         |    106         system('clear'); | 
|         |    107         print | 
|         |    108           " Wie lange soll das Zertifikat gueltig sein? (Angabe in Tagen)\n "; | 
|         |    109         chomp($days = <STDIN>); | 
|         |    110     } while ($days !~ m/\d*/); | 
|         |    111     system('clear'); | 
|         |    112     print " Ihr Zertifikat wird $days Tage gueltig sein.\n "; | 
|         |    113     system( | 
|         |    114 "/usr/bin/openssl req -new -x509 -extensions v3_ca -keyout $pfad/private/cakey.pem -out $pfad/cacert.pem -days $days -config $pfad/openssl.cnf" | 
|         |    115     ); | 
|         |    116     <STDIN>; | 
|         |    117     do { | 
|         |    118         system('clear'); | 
|         |    119         print | 
|         |    120 " Moechten Sie sich den Private Key ansehen?\n\n  j - ja\n  n - nein\n\n "; | 
|         |    121         chomp($pk = <STDIN>); | 
|         |    122         system('clear'); | 
|         |    123         if ($pk eq 'j') { | 
|         |    124             system("/bin/cat $pfad/private/cakey.pem"); | 
|         |    125             <STDIN>; | 
|         |    126         } | 
|         |    127     } until ($pk ne 'j' | $pk ne 'n'); | 
|         |    128     do { | 
|         |    129         system('clear'); | 
|         |    130         print | 
|         |    131 " Moechten Sie sich das Zertifikat ansehen?\n\n  j - ja\n  n - nein\n\n "; | 
|         |    132         chomp($rca = <STDIN>); | 
|         |    133         system('clear'); | 
|         |    134         if ($rca eq 'j') { | 
|         |    135             system("/bin/cat $pfad/cacert.pem"); | 
|         |    136             <STDIN>; | 
|         |    137         } | 
|         |    138     } until ($rca ne 'j' | $rca ne 'n'); | 
|         |    139     system('clear'); | 
|         |    140     &menue; | 
|         |    141 } | 
|         |    142  | 
|         |    143 sub request { | 
|         |    144     my $egreq; | 
|         |    145     my $rootpf; | 
|         |    146     my $config; | 
|         |    147     my $eg; | 
|         |    148     do { | 
|         |    149         system('clear'); | 
|         |    150         print | 
|         |    151 " Konfigurationsdatei erstellen oder Pfad angeben?\n\n  e - erstellen\n  p - Pfad angeben\n\n "; | 
|         |    152         chomp($eg = <STDIN>); | 
|         |    153         system('clear'); | 
|         |    154     } until ($eg ne 'e' | $eg ne 'p'); | 
|         |    155     if ($eg eq 'e') { | 
|         |    156         if (-d $pfad) { | 
|         |    157             open(CONF, ">$pfad/openssl.cnf"); | 
|         |    158             print CONF | 
|         |    159 "#\n# OpenSSL configuration file.\n#\n\n# Establish working directory.\n\ndir = $pfad\n\n[ req ]\ndefault_bits\t\t= 1024\t\t# Size of keys\ndefault_keyfile\t\t= key.pem\t\t# name of generated keys\ndefault_md\t\t= md5\t\t# message digest algorithm\nstring_mask\t\t= nombstr\t\t# permitted characters\ndistinguished_name\t= req_distinguished_name\nreq_extensions\t\t= v3_req\n\n[ req_distinguished_name ]\n# Variable name\t\t\t  Prompt string\n#----------------------\t  ----------------------------------\n0.organizationName\t= Organization Name (company)\norganizationalUnitName\t= Organizational Unit Name (department, division)\nemailAddress\t\t= Email Address\nemailAddress_max\t= 40\nlocalityName\t\t= Locality Name (city, district)\nstateOrProvinceName\t= State or Province Name (full name)\ncountryName\t\t= Country Name (2 letter code)\ncountryName_min\t\t= 2\ncountryName_max\t\t= 2\ncommonName\t\t= Common Name (hostname, IP, or your name)\ncommonName_max\t\t= 64\n\n# Default values for the above, for consistency and less typing.\n# Variable name\t\t\t  Value\n#------------------------------\t  ------------------------------\n0.organizationName_default\t= Your Company\nlocalityName_default\t\t= Your City\nstateOrProvinceName_default\t= Your Province\ncountryName_default\t\t= OO\n\n[ v3_ca ]\nbasicConstraints\t\t= CA:TRUE\nsubjectKeyIdentifier\t\t= hash\nauthorityKeyIdentifier\t\t= keyid:always,issuer:always\n\n[ v3_req ]\nbasicConstraints\t\t= CA:FALSE\nsubjectKeyIdentifier\t\t= hash"; | 
|         |    160             close CONF; | 
|         |    161         } | 
|         |    162         else { | 
|         |    163             system("/bin/mkdir $pfad"); | 
|         |    164             open(CONF, ">$pfad/openssl.cnf"); | 
|         |    165             print CONF | 
|         |    166 "#\n# OpenSSL configuration file.\n#\n\n# Establish working directory.\n\ndir = $pfad\n\n[ req ]\ndefault_bits\t\t= 1024\t\t# Size of keys\ndefault_keyfile\t\t= key.pem\t\t# name of generated keys\ndefault_md\t\t= md5\t\t# message digest algorithm\nstring_mask\t\t= nombstr\t\t# permitted characters\ndistinguished_name\t= req_distinguished_name\nreq_extensions\t\t= v3_req\n\n[ req_distinguished_name ]\n# Variable name\t\t\t  Prompt string\n#----------------------\t  ----------------------------------\n0.organizationName\t= Organization Name (company)\norganizationalUnitName\t= Organizational Unit Name (department, division)\nemailAddress\t\t= Email Address\nemailAddress_max\t= 40\nlocalityName\t\t= Locality Name (city, district)\nstateOrProvinceName\t= State or Province Name (full name)\ncountryName\t\t= Country Name (2 letter code)\ncountryName_min\t\t= 2\ncountryName_max\t\t= 2\ncommonName\t\t= Common Name (hostname, IP, or your name)\ncommonName_max\t\t= 64\n\n# Default values for the above, for consistency and less typing.\n# Variable name\t\t\t  Value\n#------------------------------\t  ------------------------------\n0.organizationName_default\t= Your Company\nlocalityName_default\t\t= Your City\nstateOrProvinceName_default\t= Your Province\ncountryName_default\t\t= OO\n\n[ v3_ca ]\nbasicConstraints\t\t= CA:TRUE\nsubjectKeyIdentifier\t\t= hash\nauthorityKeyIdentifier\t\t= keyid:always,issuer:always\n\n[ v3_req ]\nbasicConstraints\t\t= CA:FALSE\nsubjectKeyIdentifier\t\t= hash"; | 
|         |    167             close CONF; | 
|         |    168         } | 
|         |    169         print " Konfigurationsdatei erstellt $pfad/openssl.cnf\n "; | 
|         |    170         <STDIN>; | 
|         |    171     } | 
|         |    172     if ($eg eq 'p') { | 
|         |    173         system('clear'); | 
|         |    174         print " Bitte geben Sie den Pfad zu Ihrer Konfigurationsdatei an.\n "; | 
|         |    175         chomp($config = <STDIN>); | 
|         |    176         system('clear'); | 
|         |    177         print | 
|         |    178 " Bitte achten Sie darauf, dass sie den Common Name aendern, sodass er zu Ihrer Domain passt.\n Bsp.:\n\n Domain: hostname.domainname\n         secure.yourdomain.de\n\n "; | 
|         |    179 	system("openssl", $pfad) | 
|         |    180         system(openssl => qw(req -new -nodes),   | 
|         |    181 	    -out => "$pfad/req.pem",  | 
|         |    182 	    -config => $config); | 
|         |    183     } | 
|         |    184     else { | 
|         |    185         system('clear'); | 
|         |    186         print | 
|         |    187 " Bitte achten Sie darauf, dass sie den Common Name aendern, sodass er zu Ihrer Domain passt.\n Bsp.:\n\n Domain: hostname.domainname\n         secure.yourdomain.de "; | 
|         |    188         system( | 
|         |    189 "/usr/bin/openssl req -new -nodes -out $pfad/req.pem -config $pfad/openssl.cnf" | 
|         |    190         ); | 
|         |    191     } | 
|         |    192     <STDIN>; | 
|         |    193     do { | 
|         |    194         system('clear'); | 
|         |    195         print " Request ueberpruefen?\n\n  j - ja\n  n - nein\n\n "; | 
|         |    196         chomp($egreq = <STDIN>); | 
|         |    197         if ($egreq eq 'j') { | 
|         |    198             system('clear'); | 
|         |    199             system( | 
|         |    200                 "/usr/bin/openssl req -in $pfad/req.pem -text -verify -noout"); | 
|         |    201             <STDIN>; | 
|         |    202         } | 
|         |    203     } until ($egreq ne 'j' | $egreq ne 'n'); | 
|         |    204     system('clear'); | 
|         |    205     &menue; | 
|         |    206 } | 
|         |    207  | 
|         |    208 sub sign { | 
|         |    209     my $eg; | 
|         |    210     open(CONF, ">$pfad/openssl.cnf"); | 
|         |    211     print CONF | 
|         |    212 "#\n# OpenSSL configuration file.\n#\n\n# Establish working directory.\n\ndir = $pfad\n\n[ ca ]\ndefault_ca\t\t= CA_default\n\n[ CA_default ]\nserial\t\t\t= \$dir/serial\ndatabase\t\t= \$dir/index.txt\nnew_certs_dir\t\t= \$dir/newcerts\ncertificate\t\t= \$dir/cacert.pem\nprivate_key\t\t= \$dir/private/cakey.pem\ndefault_days\t\t= 365\ndefault_md\t\t= md5\npreserve\t\t= no\nemail_in_dn\t\t= no\nnameopt\t\t\t= default_ca\ncertopt\t\t\t= default_ca\npolicy\t\t\t= policy_match\n\n[ policy_match ]\ncountryName\t\t= match\nstateOrProvinceName\t= match\norganizationName\t= match\norganizationalUnitName\t= optional\ncommonName\t\t= supplied\nemailAddress\t\t= optional\n\n[ req ]\ndefault_bits\t\t= 1024\t\t# Size of keys\ndefault_keyfile\t\t= key.pem\t\t# name of generated keys\ndefault_md\t\t= md5\t\t# message digest algorithm\nstring_mask\t\t= nombstr\t\t# permitted characters\ndistinguished_name\t= req_distinguished_name\nreq_extensions\t\t= v3_req\n\n[ req_distinguished_name ]\n# Variable name\t\t\t  Prompt string\n#----------------------\t  ----------------------------------\n0.organizationName\t= Organization Name (company)\norganizationalUnitName\t= Organizational Unit Name (department, division)\nemailAddress\t\t= Email Address\nemailAddress_max\t= 40\nlocalityName\t\t= Locality Name (city, district)\nstateOrProvinceName\t= State or Province Name (full name)\ncountryName\t\t= Country Name (2 letter code)\ncountryName_min\t\t= 2\ncountryName_max\t\t= 2\ncommonName\t\t= Common Name (hostname, IP, or your name)\ncommonName_max\t\t= 64\n\n# Default values for the above, for consistency and less typing.\n# Variable name\t\t\t  Value\n#------------------------------\t  ------------------------------\n0.organizationName_default\t= Your Company\nlocalityName_default\t\t= Your City\nstateOrProvinceName_default\t= Your Province\ncountryName_default\t\t= OO\n\n[ v3_ca ]\nbasicConstraints\t\t= CA:TRUE\nsubjectKeyIdentifier\t\t= hash\nauthorityKeyIdentifier\t\t= keyid:always,issuer:always\n[ v3_req ]\nbasicConstraints\t\t= CA:FALSE\nsubjectKeyIdentifier\t\t= hash"; | 
|         |    213     system( | 
|         |    214 "/usr/bin/openssl ca -out $pfad/cert.pem -config $pfad/openssl.cnf -infiles $pfad/req.pem" | 
|         |    215     ); | 
|         |    216     print "Zertifikat wurde unterzeichnet"; | 
|         |    217     <STDIN>; | 
|         |    218     do { | 
|         |    219         system('clear'); | 
|         |    220         print "Zertifikat ueberpruefen?\n\n  j - ja\n  n - nein\n\n"; | 
|         |    221         chomp($eg = <STDIN>); | 
|         |    222         if ($eg eq 'j') { | 
|         |    223             system( | 
|         |    224 "/usr/bin/openssl x509 -in $pfad/cert.pem -noout -text -purpose | /bin/more" | 
|         |    225             ); | 
|         |    226             <STDIN>; | 
|         |    227         } | 
|         |    228     } until ($eg ne 'j' | $eg ne 'n'); | 
|         |    229     $eg = ''; | 
|         |    230     do { | 
|         |    231         system('clear'); | 
|         |    232         print | 
|         |    233 "Sollen die lesbaren Elemente aus dem Zertifikat entfernt werden?\n\n  j - ja\n  n - nein\n\n"; | 
|         |    234         chomp($eg = <STDIN>); | 
|         |    235         if ($eg eq 'j') { | 
|         |    236             print "...\n"; | 
|         |    237 	    # rename() | 
|         |    238 	    # File::Copy | 
|         |    239             system("/bin/mv $pfad/cert.pem $pfad/tmp.pem"); | 
|         |    240             system( | 
|         |    241                 "/usr/bin/openssl x509 -in $pfad/tmp.pem -out $pfad/cert.pem"); | 
|         |    242             print "Alle lesbaren Elemente wurden entfernt."; | 
|         |    243             <STDIN>; | 
|         |    244         } | 
|         |    245     } until ($eg ne 'j' | $eg ne 'n'); | 
|         |    246     &menue; | 
|         |    247 } | 
|         |    248  | 
|         |    249 sub revoke { | 
|         |    250     my $eg; | 
|         |    251     do { | 
|         |    252         print | 
|         |    253 "Welches Zertifikat soll wiederrufen werden?\nFuer Informationen zu allen Zertifikaten, schauen\nSie in die Datei index.txt.\n"; | 
|         |    254         print "Datei öffnen?\n\nj - ja\nn - nein\n\n"; | 
|         |    255         chomp($eg = <STDIN>); | 
|         |    256         if ($eg eq 'j') { | 
|         |    257             open(INDEX, "<$pfad/index.txt"); | 
|         |    258             my @index = <INDEX>; | 
|         |    259             print sort @index; | 
|         |    260             <STDIN>; | 
|         |    261         } | 
|         |    262     } until ($eg eq 'j' | $eg eq 'n'); | 
|         |    263     print | 
|         |    264 "Welches Zertifikat soll wiederrufen werden?\n(Geben Sie die 2-stellige Nummer ein)\n"; | 
|         |    265     chomp($eg = <STDIN>); | 
|         |    266     system( | 
|         |    267 "/usr/bin/openssl ca -revoke $pfad/newcerts/$eg.pem -config $pfad/openssl.cnf" | 
|         |    268     ); | 
|         |    269     print "Zertifikat $eg wiederrufen."; | 
|         |    270     <STDIN>; | 
|         |    271     &menue; | 
|         |    272 } | 
|         |    273  | 
|         |    274 sub revlist { | 
|         |    275     system( | 
|         |    276 "/usr/bin/openssl ca -gencrl -crldays 31 -config $pfad/openssl.cnf -out $pfad/rootca.crl" | 
|         |    277     ); | 
|         |    278     print "Certicate Revocation List erstellt"; | 
|         |    279     <STDIN>; | 
|         |    280     &menue; | 
|         |    281 } | 
|         |    282  | 
|         |    283 sub main(@) { | 
|         |    284     menue(); | 
|         |    285     exit 0; | 
|         |    286 } | 
|         |    287  | 
|         |    288 main(@ARGV); |