+ #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: