- #No easy way for specifying the contain of subjectAltName without writing a config file...
- my ($fh, $v3extname) = tempfile ('/tmp/XXXXXXXX');
- print $fh <<END
- basicConstraints=CA:FALSE
- nsComment="OpenSSL Generated Certificate"
- subjectKeyIdentifier=hash
- authorityKeyIdentifier=keyid,issuer:always
- extendedKeyUsage = serverAuth
-END
-;
- print $fh "subjectAltName=$cgiparams{'SUBJECTALTNAME'}" if ($cgiparams{'SUBJECTALTNAME'});
- close ($fh);
-
- my $opt = " ca -days 999999";
- $opt .= " -batch -notext";
- $opt .= " -in ${General::swroot}/certs/hostreq.pem";
- $opt .= " -out ${General::swroot}/certs/hostcert.pem";
- $opt .= " -extfile $v3extname";
- $errormessage = &callssl ($opt);
- unlink ("${General::swroot}/certs/hostreq.pem"); #no more needed
- unlink ($v3extname);
- }
-
- # Create an empty CRL
- if (!$errormessage) {
- &General::log("ipsec", "Creating emptycrl...");
- my $opt = " ca -gencrl";
- $opt .= " -out ${General::swroot}/crls/cacrl.pem";
- $errormessage = &callssl ($opt);
- }
-
- # Successfully build CA / CERT!
- if (!$errormessage) {
- &cleanssldatabase();
- goto ROOTCERT_SUCCESS;
- }
-
- #Cleanup
- unlink ("${General::swroot}/ca/cacert.pem");
- unlink ("${General::swroot}/certs/hostkey.pem");
- unlink ("${General::swroot}/certs/hostcert.pem");
- unlink ("${General::swroot}/crls/cacrl.pem");
- &cleanssldatabase();
- }
-
- ROOTCERT_ERROR:
- &Header::showhttpheaders();
- &Header::openpage($Lang::tr{'ipsec'}, 1, '');
- &Header::openbigbox('100%', 'left', '', $errormessage);
- if ($errormessage) {
- &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
- print "<class name='base'>$errormessage";
- print " </class>";
- &Header::closebox();
- }
- &Header::openbox('100%', 'left', "$Lang::tr{'generate root/host certificates'}:");
- print <<END
- <form method='post' enctype='multipart/form-data' action='$ENV{'SCRIPT_NAME'}'>
- <table width='100%' border='0' cellspacing='1' cellpadding='0'>
- <tr><td width='40%' class='base'>$Lang::tr{'organization name'}:</td>
- <td width='60%' class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_ORGANIZATION' value='$cgiparams{'ROOTCERT_ORGANIZATION'}' size='32' /></td></tr>
- <tr><td class='base'>$Lang::tr{'ipfires hostname'}:</td>
- <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_HOSTNAME' value='$cgiparams{'ROOTCERT_HOSTNAME'}' size='32' /></td></tr>
- <tr><td class='base'>$Lang::tr{'your e-mail'}: <img src='/blob.gif' alt='*' /></td>
- <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_EMAIL' value='$cgiparams{'ROOTCERT_EMAIL'}' size='32' /></td></tr>
- <tr><td class='base'>$Lang::tr{'your department'}: <img src='/blob.gif' alt='*' /></td>
- <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_OU' value='$cgiparams{'ROOTCERT_OU'}' size='32' /></td></tr>
- <tr><td class='base'>$Lang::tr{'city'}: <img src='/blob.gif' alt='*' /></td>
- <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_CITY' value='$cgiparams{'ROOTCERT_CITY'}' size='32' /></td></tr>
- <tr><td class='base'>$Lang::tr{'state or province'}: <img src='/blob.gif' alt='*' /></td>
- <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_STATE' value='$cgiparams{'ROOTCERT_STATE'}' size='32' /></td></tr>
- <tr><td class='base'>$Lang::tr{'country'}:</td>
- <td class='base'><select name='ROOTCERT_COUNTRY'>
+ if (!$errormessage) {
+ &General::log("ipsec", "Moving private key...");
+ move("/tmp/newhostkey", "${General::swroot}/certs/hostkey.pem");
+ $errormessage = "$Lang::tr{'certificate file move failed'}: $!" if ($? ne 0);
+ }
+
+ #cleanup temp files
+ unlink ($filename);
+ unlink ('/tmp/newcacert');
+ unlink ('/tmp/newhostcert');
+ unlink ('/tmp/newhostkey');
+ if ($errormessage) {
+ unlink ("${General::swroot}/ca/cacert.pem");
+ unlink ("${General::swroot}/certs/hostcert.pem");
+ unlink ("${General::swroot}/certs/hostkey.pem");
+ goto ROOTCERT_ERROR;
+ }
+
+ # Create empty CRL cannot be done because we don't have
+ # the private key for this CAROOT
+ # IPFire can only import certificates
+
+ &General::log("ipsec", "p12 import completed!");
+ &cleanssldatabase();
+ goto ROOTCERT_SUCCESS;
+
+ } elsif ($cgiparams{'ROOTCERT_COUNTRY'} ne '') {
+
+ # Validate input since the form was submitted
+ if ($cgiparams{'ROOTCERT_ORGANIZATION'} eq ''){
+ $errormessage = $Lang::tr{'organization cant be empty'};
+ goto ROOTCERT_ERROR;
+ }
+ if (length($cgiparams{'ROOTCERT_ORGANIZATION'}) >60) {
+ $errormessage = $Lang::tr{'organization too long'};
+ goto ROOTCERT_ERROR;
+ }
+ if ($cgiparams{'ROOTCERT_ORGANIZATION'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
+ $errormessage = $Lang::tr{'invalid input for organization'};
+ goto ROOTCERT_ERROR;
+ }
+ if ($cgiparams{'ROOTCERT_HOSTNAME'} eq ''){
+ $errormessage = $Lang::tr{'hostname cant be empty'};
+ goto ROOTCERT_ERROR;
+ }
+ unless (&General::validfqdn($cgiparams{'ROOTCERT_HOSTNAME'}) || &General::validip($cgiparams{'ROOTCERT_HOSTNAME'})) {
+ $errormessage = $Lang::tr{'invalid input for hostname'};
+ goto ROOTCERT_ERROR;
+ }
+ if ($cgiparams{'ROOTCERT_EMAIL'} ne '' && (! &General::validemail($cgiparams{'ROOTCERT_EMAIL'}))) {
+ $errormessage = $Lang::tr{'invalid input for e-mail address'};
+ goto ROOTCERT_ERROR;
+ }
+ if (length($cgiparams{'ROOTCERT_EMAIL'}) > 40) {
+ $errormessage = $Lang::tr{'e-mail address too long'};
+ goto ROOTCERT_ERROR;
+ }
+ if ($cgiparams{'ROOTCERT_OU'} ne '' && $cgiparams{'ROOTCERT_OU'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
+ $errormessage = $Lang::tr{'invalid input for department'};
+ goto ROOTCERT_ERROR;
+ }
+ if ($cgiparams{'ROOTCERT_CITY'} ne '' && $cgiparams{'ROOTCERT_CITY'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
+ $errormessage = $Lang::tr{'invalid input for city'};
+ goto ROOTCERT_ERROR;
+ }
+ if ($cgiparams{'ROOTCERT_STATE'} ne '' && $cgiparams{'ROOTCERT_STATE'} !~ /^[a-zA-Z0-9 ,\.\-_]*$/) {
+ $errormessage = $Lang::tr{'invalid input for state or province'};
+ goto ROOTCERT_ERROR;
+ }
+ if ($cgiparams{'ROOTCERT_COUNTRY'} !~ /^[A-Z]*$/) {
+ $errormessage = $Lang::tr{'invalid input for country'};
+ goto ROOTCERT_ERROR;
+ }
+ #the exact syntax is a list comma separated of
+ # email:any-validemail
+ # URI: a uniform resource indicator
+ # DNS: a DNS domain name
+ # RID: a registered OBJECT IDENTIFIER
+ # IP: an IP address
+ # example: email:franck@foo.com,IP:10.0.0.10,DNS:franck.foo.com
+
+ if ($cgiparams{'SUBJECTALTNAME'} ne '' && $cgiparams{'SUBJECTALTNAME'} !~ /^(email|URI|DNS|RID|IP):[a-zA-Z0-9 :\/,\.\-_@]*$/) {
+ $errormessage = $Lang::tr{'vpn altname syntax'};
+ goto VPNCONF_ERROR;
+ }
+
+ # Copy the cgisettings to vpnsettings and save the configfile
+ $vpnsettings{'ROOTCERT_ORGANIZATION'} = $cgiparams{'ROOTCERT_ORGANIZATION'};
+ $vpnsettings{'ROOTCERT_HOSTNAME'} = $cgiparams{'ROOTCERT_HOSTNAME'};
+ $vpnsettings{'ROOTCERT_EMAIL'} = $cgiparams{'ROOTCERT_EMAIL'};
+ $vpnsettings{'ROOTCERT_OU'} = $cgiparams{'ROOTCERT_OU'};
+ $vpnsettings{'ROOTCERT_CITY'} = $cgiparams{'ROOTCERT_CITY'};
+ $vpnsettings{'ROOTCERT_STATE'} = $cgiparams{'ROOTCERT_STATE'};
+ $vpnsettings{'ROOTCERT_COUNTRY'} = $cgiparams{'ROOTCERT_COUNTRY'};
+ &General::writehash("${General::swroot}/vpn/settings", \%vpnsettings);
+
+ # Replace empty strings with a .
+ (my $ou = $cgiparams{'ROOTCERT_OU'}) =~ s/^\s*$/\./;
+ (my $city = $cgiparams{'ROOTCERT_CITY'}) =~ s/^\s*$/\./;
+ (my $state = $cgiparams{'ROOTCERT_STATE'}) =~ s/^\s*$/\./;
+
+ # Create the CA certificate
+ if (!$errormessage) {
+ &General::log("ipsec", "Creating cacert...");
+ if (open(STDIN, "-|")) {
+ my $opt = " req -x509 -sha256 -nodes";
+ $opt .= " -days 999999";
+ $opt .= " -newkey rsa:4096";
+ $opt .= " -keyout ${General::swroot}/private/cakey.pem";
+ $opt .= " -out ${General::swroot}/ca/cacert.pem";
+
+ $errormessage = &callssl ($opt);
+ } else { #child
+ print "$cgiparams{'ROOTCERT_COUNTRY'}\n";
+ print "$state\n";
+ print "$city\n";
+ print "$cgiparams{'ROOTCERT_ORGANIZATION'}\n";
+ print "$ou\n";
+ print "$cgiparams{'ROOTCERT_ORGANIZATION'} CA\n";
+ print "$cgiparams{'ROOTCERT_EMAIL'}\n";
+ exit (0);
+ }
+ }
+
+ # Create the Host certificate request
+ if (!$errormessage) {
+ &General::log("ipsec", "Creating host cert...");
+ if (open(STDIN, "-|")) {
+ my $opt = " req -sha256 -nodes";
+ $opt .= " -newkey rsa:2048";
+ $opt .= " -keyout ${General::swroot}/certs/hostkey.pem";
+ $opt .= " -out ${General::swroot}/certs/hostreq.pem";
+ $errormessage = &callssl ($opt);
+ } else { #child
+ print "$cgiparams{'ROOTCERT_COUNTRY'}\n";
+ print "$state\n";
+ print "$city\n";
+ print "$cgiparams{'ROOTCERT_ORGANIZATION'}\n";
+ print "$ou\n";
+ print "$cgiparams{'ROOTCERT_HOSTNAME'}\n";
+ print "$cgiparams{'ROOTCERT_EMAIL'}\n";
+ print ".\n";
+ print ".\n";
+ exit (0);
+ }
+ }
+
+ # Sign the host certificate request
+ if (!$errormessage) {
+ &General::log("ipsec", "Self signing host cert...");
+
+ #No easy way for specifying the contain of subjectAltName without writing a config file...
+ my ($fh, $v3extname) = tempfile ('/tmp/XXXXXXXX');
+ print $fh <<END
+ basicConstraints=CA:FALSE
+ nsComment="OpenSSL Generated Certificate"
+ subjectKeyIdentifier=hash
+ authorityKeyIdentifier=keyid,issuer:always
+ extendedKeyUsage = serverAuth
+END
+;
+ print $fh "subjectAltName=$cgiparams{'SUBJECTALTNAME'}" if ($cgiparams{'SUBJECTALTNAME'});
+ close ($fh);
+
+ my $opt = " ca -md sha256 -days 999999";
+ $opt .= " -batch -notext";
+ $opt .= " -in ${General::swroot}/certs/hostreq.pem";
+ $opt .= " -out ${General::swroot}/certs/hostcert.pem";
+ $opt .= " -extfile $v3extname";
+ $errormessage = &callssl ($opt);
+ unlink ("${General::swroot}/certs/hostreq.pem"); #no more needed
+ unlink ($v3extname);
+ }
+
+ # Create an empty CRL
+ if (!$errormessage) {
+ &General::log("ipsec", "Creating emptycrl...");
+ my $opt = " ca -gencrl";
+ $opt .= " -out ${General::swroot}/crls/cacrl.pem";
+ $errormessage = &callssl ($opt);
+ }
+
+ # Successfully build CA / CERT!
+ if (!$errormessage) {
+ &cleanssldatabase();
+ goto ROOTCERT_SUCCESS;
+ }
+
+ #Cleanup
+ unlink ("${General::swroot}/ca/cacert.pem");
+ unlink ("${General::swroot}/certs/hostkey.pem");
+ unlink ("${General::swroot}/certs/hostcert.pem");
+ unlink ("${General::swroot}/crls/cacrl.pem");
+ &cleanssldatabase();
+ }
+
+ ROOTCERT_ERROR:
+ &Header::showhttpheaders();
+ &Header::openpage($Lang::tr{'ipsec'}, 1, '');
+ &Header::openbigbox('100%', 'left', '', $errormessage);
+ if ($errormessage) {
+ &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
+ print "<class name='base'>$errormessage";
+ print " </class>";
+ &Header::closebox();
+ }
+ &Header::openbox('100%', 'left', "$Lang::tr{'generate root/host certificates'}:");
+ print <<END
+ <form method='post' enctype='multipart/form-data' action='$ENV{'SCRIPT_NAME'}'>
+ <table width='100%' border='0' cellspacing='1' cellpadding='0'>
+ <tr><td width='40%' class='base'>$Lang::tr{'organization name'}: <img src='/blob.gif' alt='*' /></td>
+ <td width='60%' class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_ORGANIZATION' value='$cgiparams{'ROOTCERT_ORGANIZATION'}' size='32' /></td></tr>
+ <tr><td class='base'>$Lang::tr{'ipfires hostname'}: <img src='/blob.gif' alt='*' /></td>
+ <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_HOSTNAME' value='$cgiparams{'ROOTCERT_HOSTNAME'}' size='32' /></td></tr>
+ <tr><td class='base'>$Lang::tr{'your e-mail'}:</td>
+ <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_EMAIL' value='$cgiparams{'ROOTCERT_EMAIL'}' size='32' /></td></tr>
+ <tr><td class='base'>$Lang::tr{'your department'}:</td>
+ <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_OU' value='$cgiparams{'ROOTCERT_OU'}' size='32' /></td></tr>
+ <tr><td class='base'>$Lang::tr{'city'}:</td>
+ <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_CITY' value='$cgiparams{'ROOTCERT_CITY'}' size='32' /></td></tr>
+ <tr><td class='base'>$Lang::tr{'state or province'}:</td>
+ <td class='base' nowrap='nowrap'><input type='text' name='ROOTCERT_STATE' value='$cgiparams{'ROOTCERT_STATE'}' size='32' /></td></tr>
+ <tr><td class='base'>$Lang::tr{'country'}:</td>
+ <td class='base'><select name='ROOTCERT_COUNTRY'>