&1",'r'); $line = ''; while (! feof($handle)) { $chr = fread($handle, 1); $line .= $chr; if ($chr == "\n") { print str_replace("\n", "
\n", $line); $line = ''; flush(); } elseif (strlen($line) > $line_length) { print $line."
\n"; $line = ''; flush(); } } print $line."
\n"; flush(); return; } $version = PHPKI_VERSION; # Who does the webserver run as (apache,www-data,etc)? $uid = posix_getuid(); $pwdinfo = posix_getpwuid($uid); $uname = $pwdinfo['name']; # Permissions on the file store. $store_perms=0770; # Where are we? $here = dirname($_SERVER['SCRIPT_FILENAME']); $submit = gpvar('submit'); $stage = gpvar('stage'); $organization = gpvar('organization'); $unit = gpvar('unit'); $contact = gpvar('contact'); $locality = gpvar('locality'); $province = gpvar('province'); $country = gpvar('country'); $common_name = gpvar('common_name'); $passwd = gpvar('passwd'); $passwdv = gpvar('passwdv'); $expiry = gpvar('expiry'); $keysize = gpvar('keysize'); $base_url = gpvar('base_url'); $crl_distrib = gpvar('crl_distrib'); $revoke_url = gpvar('revoke_url'); $policy_url = gpvar('policy_url'); $comment_root = gpvar('comment_root'); $comment_email = gpvar('comment_email'); $comment_sign = gpvar('comment_sign'); $comment_srv = gpvar('comment_srv'); $comment_stamp = gpvar('comment_stamp'); $openssl_bin = gpvar('openssl_bin'); $passwd_file = gpvar('passwd_file'); $getting_help = gpvar('getting_help'); $ca_prefix = gpvar('ca_prefix'); $header_title = gpvar('header_title'); $store_dir = gpvar('store_dir'); if ($base_url && substr($base_url,-1) != '/') $base_url .= '/'; $hidden_fields = ' '; switch ($stage) { case 'validate': $er = ''; if (! $country) $er .= 'Missing Country
'; if (! $province) $er .= 'Missing State/Province
'; if (! $locality) $er .= 'Missing Locality
'; if (! $organization) $er .= 'Missing Organization
'; if (! $unit) $er .= 'Missing Unit/Department
'; if (! $contact) $er .= 'Missing Contact E-mail Address
'; if (! $common_name) $er .= 'Missing Common Name
'; if (! $passwd) $er .= 'Missing Certificate Password
'; if (! $passwdv) $er .= 'Missing Certificate Password Verification "Again"
'; if (! $header_title) $er .= 'Missing Header Title
'; if (! $passwd_file) $er .= 'Missing User Password File Location'; if (! $store_dir) $er .= 'Missing Storage Directory
'; $countrycode = strtoupper($country); if (! preg_match("/\b[A-Z][A-Z]\b/", $countrycode, $match) ) { $er .= 'Country Code must be ISO 3166 two letters
'; } if ( $passwd && strlen($passwd) < 8 ) $er .= 'Certificate password is too short.
'; if ( $passwd and $passwd != $passwdv ) $er .= 'Password and password verification do not match.
'; if ( $contact && ! is_email($contact) ) $er .= 'E-mail address ('. htvar($contact) . ') may be invalid.
'; if (strpos($store_dir,$_SERVER['DOCUMENT_ROOT']) === 0) $er .= 'Store directory must exist somewhere outside of DOCUMENT_ROOT ('.$_SERVER['DOCUMENT_ROOT'].').
'; if (strpos($store_dir,dirname($_SERVER['SCRIPT_FILENAME'])) === 0) $er .= 'Store directory cannot exist within the PHPki installation directory ('.dirname($_SERVER['SCRIPT_FILENAME']).').
'; if (! $er) { if (! file_exists($store_dir) ) { if ( ! mkdir("$store_dir",$store_perms)) $er .= "Could not create the store directory \"$store_dir\"
"; } if (file_exists($store_dir)) { if (! chmod($store_dir, $store_perms)) $er .= "Could not change permissions on the store directory \"$store_dir\"
"; if (! is_readable($store_dir)) $er .= "The store directory \"$store_dir\" is not readable by the web server user \"$uname\"
"; if (! is_writeable($store_dir)) $er .= "The store directory \"$store_dir\: is not writeable by the web server user \"$uname\"
"; } else { $er .= "Store directory \"$store_dir\" does not exist. You will have to manually create it as desribed in the setup form.
"; } } if ( $er ) $er = '

ERROR(S) IN FORM:

' . $er . '

'; if ($er) { printHeader('setup'); ?>

"; printFooter(); break; } case 'write': printHeader('about'); # #Create the file store directory structure. # print 'Creating PHPki file store...
'; flush(); if (! file_exists("$store_dir/config")) mkdir("$store_dir/config",$store_perms); if (! file_exists("$store_dir/tmp")) mkdir("$store_dir/tmp",$store_perms); if (! file_exists("$store_dir/CA")) mkdir("$store_dir/CA",$store_perms); if (! file_exists("$store_dir/CA/certs")) mkdir("$store_dir/CA/certs",$store_perms); if (! file_exists("$store_dir/CA/private")) mkdir("$store_dir/CA/private",$store_perms); if (! file_exists("$store_dir/CA/newcerts")) mkdir("$store_dir/CA/newcerts",$store_perms); if (! file_exists("$store_dir/CA/requests")) mkdir("$store_dir/CA/requests",$store_perms); if (! file_exists("$store_dir/CA/crl")) mkdir("$store_dir/CA/crl",$store_perms); if (! file_exists("$store_dir/CA/pfx")) mkdir("$store_dir/CA/pfx",$store_perms); # # Create the PHPki CA configuration. # print 'Writing configuration files...
'; flush(); $config_txt = << EOS; # # Write out the CA configuration file. # $fd = fopen("$store_dir/config/config.php",'w'); fwrite($fd, $config_txt); fclose($fd); # # Create the bootstrap configuration # $config_txt = << EOS; # # Write out the bootstrap config # $fd = fopen('./config.php','w'); fwrite($fd, $config_txt); fclose($fd); # Re-read the CA config file so the openssl_functions # can be used to create a CA root certificate. include("$store_dir/config/config.php"); # # Now create a temporary openssl.cnf for creating a self-signed # CA root certificate, and create a generic openssl.cnf file # in the CA home # $config_txt1 = <<< EOS HOME = $config[home_dir] RANDFILE = $config[random] dir = $config[ca_dir] certs = $config[cert_dir] crl_dir = $config[crl_dir] database = $config[index] new_certs_dir = $config[new_certs_dir] private_dir = $config[private_dir] serial = $config[serial] certificate = $config[cacert_pem] crl = $config[cacrl_pem] private_key = $config[cakey] crl_extensions = crl_ext default_days = 365 default_crl_days= 30 preserve = no default_md = sha512 [ ca ] default_ca = email_cert [ root_cert ] x509_extensions = root_ext default_days = 3650 policy = policy_supplied [ email_cert ] x509_extensions = email_ext default_days = 365 policy = policy_supplied [ email_signing_cert ] x509_extensions = email_signing_ext default_days = 365 policy = policy_supplied [ server_cert ] x509_extensions = server_ext default_days = 365 policy = policy_supplied [ vpn_cert ] x509_extensions = vpn_client_server_ext default_days = 365 policy = policy_supplied [ time_stamping_cert ] x509_extensions = time_stamping_ext default_days = 365 policy = policy_supplied [ policy_supplied ] countryName = supplied stateOrProvinceName = supplied localityName = supplied organizationName = supplied organizationalUnitName = supplied commonName = supplied emailAddress = supplied [ root_ext ] basicConstraints = CA:true keyUsage = cRLSign, keyCertSign nsCertType = sslCA, emailCA, objCA subjectKeyIdentifier = hash subjectAltName = email:copy crlDistributionPoints = URI:$config[base_url]$config[crl_distrib] nsComment = $config[comment_root] #nsCaRevocationUrl = nsCaPolicyUrl = $config[base_url]$config[policy_url] [ email_ext ] basicConstraints = critical, CA:false keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = critical, emailProtection, clientAuth nsCertType = critical, client, email subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = email:copy issuerAltName = issuer:copy crlDistributionPoints = URI:$config[base_url]$config[crl_distrib] nsComment = $config[comment_email] nsBaseUrl = $config[base_url] nsRevocationUrl = $config[revoke_url] #nsRenewalUrl = nsCaPolicyUrl = $config[base_url]$config[policy_url] #nsSslServerName = [ email_signing_ext ] basicConstraints = critical, CA:false keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = critical, emailProtection, clientAuth, codeSigning nsCertType = critical, client, email subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = email:copy issuerAltName = issuer:copy crlDistributionPoints = URI:$config[base_url]$config[crl_distrib] nsComment = $config[comment_sign] nsBaseUrl = $config[base_url] nsRevocationUrl = $config[revoke_url] #nsRenewalUrl = nsCaPolicyUrl = $config[base_url]$config[policy_url] #nsSslServerName = [ server_ext ] basicConstraints = CA:false keyUsage = critical, digitalSignature, keyEncipherment nsCertType = critical, server extendedKeyUsage = critical, serverAuth, 1.3.6.1.5.5.7.3.1 subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = DNS:$common_name,email:copy issuerAltName = issuer:copy crlDistributionPoints = URI:$config[base_url]$config[crl_distrib] nsComment = $config[comment_srv] nsBaseUrl = $config[base_url] nsRevocationUrl = $config[revoke_url] nsCaPolicyUrl = $config[base_url]$config[policy_url] [ time_stamping_ext ] basicConstraints = CA:false keyUsage = critical, nonRepudiation, digitalSignature extendedKeyUsage = timeStamping subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = DNS:$common_name,email:copy issuerAltName = issuer:copy crlDistributionPoints = URI:$config[base_url]$config[crl_distrib] nsComment = $config[comment_stamp] nsBaseUrl = $config[base_url] nsRevocationUrl = $config[revoke_url] nsCaPolicyUrl = $config[base_url]$config[policy_url] [ vpn_client_ext ] basicConstraints = critical, CA:false keyUsage = critical, digitalSignature extendedKeyUsage = critical, clientAuth nsCertType = critical, client subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = DNS:$common_name,email:copy [ vpn_server_ext ] basicConstraints = critical, CA:false keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = critical, serverAuth nsCertType = critical, server subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = DNS:$common_name,email:copy [ vpn_client_server_ext ] basicConstraints = critical, CA:false keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = critical, serverAuth, clientAuth nsCertType = critical, server, client subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always subjectAltName = DNS:$common_name,email:copy [ crl_ext ] issuerAltName=issuer:copy authorityKeyIdentifier=keyid:always,issuer:always EOS; $config_txt2 = <<< EOS [ req ] default_bits = 2048 default_keyfile = privkey.pem distinguished_name = req_name string_mask = nombstr req_extensions = req_ext [ req_name] countryName = Country Name (2 letter code) countryName_default = US countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = localityName = Locality Name (eg, city) localityName_default = 0.organizationName = Organization Name (eg, company) 0.organizationName_default = 1.organizationName = Second Organization Name (eg, company) 1.organizationName_default = organizationalUnitName = Organizational Unit Name (eg, section) organizationalUnitName_default = commonName = Common Name (eg, YOUR name) emailAddress = Email Address or Web URL [ req_ext ] basicConstraints = critical, CA:false EOS; $config_txt3 = <<< EOS [ req ] default_bits = 2048 default_keyfile = privkey.pem distinguished_name = req_name string_mask = nombstr req_extensions = req_ext prompt = no [ req_name ] C = $config[country] ST = $config[province] L = $config[locality] O = $config[organization] OU = $config[unit] CN = $config[common_name] emailAddress = $config[contact] [ req_ext ] basicConstraints = critical, CA:true EOS; # # Write the permanent OpenSSL config # $fd = fopen($config['openssl_cnf'],'w'); fwrite($fd, $config_txt1 . $config_txt2); fclose($fd); # # Write the temporary OpenSSL config # $tmp_cnf = "$config[home_dir]/tmp/openssl.cnf"; $fd = fopen($tmp_cnf,'w'); fwrite($fd, $config_txt1 . $config_txt3); fclose($fd); # # Intialize index.txt and serial files # $fd = fopen($config['index'],'w'); fwrite($fd, ""); fclose($fd); # $fd = fopen($config['serial'],'w'); fwrite($fd, "100001"); fclose($fd); # # Convert expiry years to approximate days. # $days = $config['expiry'] * 365.25; # # Create a new self-signed CA certificate in PEM format. # print 'Creating root certificate...
'; flush(); // .rnd created here exec(REQ . " -x509 -config $tmp_cnf -extensions root_ext -newkey rsa:$keysize -keyout $config[cakey] -out $config[cacert_pem] -passout pass:'$config[ca_pwd]' -days $days 2>&1"); # **** DISABLED ***** # It appears that both IE and Netscape accept PEM formatted root certificates # # Create a copy of the CA certificate in DER format. # #exec(X509 . " -in ca/$config[cacert_pem] -inform PEM -out ca/$config[cacert_der] -outform DER 2>&1"); # # Generate the initial CRL. # print 'Generating certificate revocation list...
'; flush(); exec(CA . " -gencrl -config $config[openssl_cnf] -out $config[cacrl_pem] -passin pass:'$config[ca_pwd]'"); # Make a copy of the CRL in DER format. # exec(CRL . " -in $config[cacrl_pem] -out $config[cacrl_der] -inform PEM -outform DER"); # # Clean up. # if (! unlink("$store_dir/tmp/openssl.cnf")) print "Can't unlink $store_dir/tmp/openssl.cnf"; # # Create dhparam files for OpenVPN and others. # print '

Creating 1024 bit Diffie-Hellman parameters used by OpenVPN.
'; print "Saving to $config[private_dir]/dhparam1024.pem.

"; // $cmd = "openssl dhparam -rand '$config[random]' -out '$config[private_dir]/dhparam1024.pem' 1024"; // print $cmd.'
'; // This works but still the error exec(DH . "-rand '$config[random]' -out '$config[private_dir]/dhparam1024.pem' 1024"); // exec(DH . " -out '$config[private_dir]/dhparam1024.pem' 1024"); flush(); //flush_exec($cmd,100); print "Please ignore warnings about \"unable to write 'random state\'

"; # # Create a TLS auth key for OpenVPN if openvpn is installed # $command = 'which openvpn'; $command = escapeshellcmd($command); if (system ($command) == '/usr/sbin/openvpn') { print '

Creating a TLS authentication key used by OpenVPN.
'; print "Saving to $store_dir/takey.pem.

"; $cmd = $command . " --genkey --secret '$config[private_dir]/takey.pem'"; print $cmd.'
'; flush(); flush_exec($cmd); } else { echo "openvpn is required to generate a takey.pem
"; echo "You can create one later like this:
"; echo "openvpn --genkey --secret". $config[private_dir] . "/takey.pem
"; } #print '

Creating 2048 bit Diffie-Hellman parameters used by OpenVPN.
'; #print "Saving to $store_dir/dhparam2048.pem.

"; #$cmd = "openssl dhparam -rand '$config[random]' -out '$config[private_dir]/dhparam2048.pem' 2048"; #print $cmd.'
'; #flush(); #flush_exec($cmd,200); # # Step aside and let the users in (create index.php files). # if (! unlink('index.php')) print "Can't unlink index.php"; if (! unlink('setup.php')) print "Can't unlink setup.php";; if (! unlink('ca/index.php')) print "Can't unlink ca/index.php"; if (! symlink('main.php','index.php')) print "Can't symlink main.php"; if (! symlink('main.php','ca/index.php')) print "Can't symlink ca/main.php"; ?>

Setup is complete. Your CA root certificate as been created.

SECURITY WARNING!   Be sure to run the secure.sh shell script as the root user.'; } ?>



Contact:
First-Name Last-Name
Company/Organization Name
Address Line #1
Address Line #2
City, State, ZipCode

Phone: (000) 000-0000
E-mail: someone@somewhere.com   E-mail is preferred.
'; if (! $store_dir) $store_dir = dirname($_SERVER['DOCUMENT_ROOT']).'/phpki-store'; if (! $base_url) $base_url = $config['base_url']; if (! $base_url) $base_url = 'http://www.somewhere.com/phpki/'; if (! $crl_distrib) $crl_distrib = 'index.php?stage=dl_crl'; if (! $revoke_url) $revoke_url = 'ns_revoke_query.php?'; if (! $policy_url) $policy_url = 'policy.html'; if (! $comment_root) $comment_root = 'PHPki/OpenSSL Generated Root Certificate Authority'; if (! $comment_email) $comment_email = 'PHPki/OpenSSL Generated Personal Certificate'; if (! $comment_sign) $comment_sign = 'PHPki/OpenSSL Generated Personal Certificate'; if (! $comment_srv) $comment_srv = 'PHPki/OpenSSL Generated Secure Server Certificate'; if (! $comment_stamp) $comment_stamp = 'PHPki/OpenSSL Generated Time Stamping Certificate'; if (! $ca_prefix) $ca_prefix = $config['ca_prefix']; if (! $openssl_bin) $openssl_bin = $config['openssl_bin']; if (! $openssl_bin) $openssl_bin = '/usr/bin/openssl'; if (! $passwd_file) $passwd_file = $config['passwd_file']; if (! $passwd_file) $passwd_file = dirname($_SERVER['DOCUMENT_ROOT']).'/phpkipasswd'; if (! $header_title) $header_title = $config['header_title']; if (! $header_title) $header_title = 'Certificate Authority'; printHeader('setup'); ?>

Certificate Authority Initial Setup

Root Certificate Data

Organization *
Department/Unit *
Common Name * This is embeded in certificates, and is most often displayed in e-mail clients as the Issued By: text. This is usually the full name of your certificate authority (i.e. ACME Certificate Authority).
Technical Contact E-mail Address *
Enter an e-mail address where users should send correspondence regarding your certificate authority and the certificates you issue.
Locality *
State/Province *
Country Code ISO 3166 - 2 Characters *
Password *
This password will be used to protect your root certificate private key.
Can't contain single quote ! Do not lose or forget this password.
   Again
Certificate Life *
Enter the number of years you wish your root certificate to be valid.
Key Size *
Enter the size of your certificate key.
Certificate Authority Base URL
Enter the public Web address where your Certificate Authority will reside. The address should end with a trailing slash (/) character. This address will be embeded in all certficates issued by your CA, for informational purposes.
Certificate Authority CRL Distribution Points
Provide the public URL where Certificate Revocation List (CRL) of your CA will reside. This path is relative to Base URL above. You may leave it by default if your clients have direct access to PHPki.
Certificate Authority Revocation Check URL
Provide the public URL where clients of your CA can check if the requested certificate has been revoked. This path is relative to Base URL above. You may leave it by default if your clients have direct access to PHPki.
Certificate Authority Policy URL
Provide the public URL where your CA policy will reside. This path is relative to Base URL above. You may leave it by default or adjust to your environment.
Root Certificate Comment
Root certificate Comment attribute. You may change it to something or use the default value set by PHPki.
Email Certificate Comment
Email certificate Comment attribute. You may change it to something or use the default value set by PHPki.
Email/Signing Certificate Comment
Email and signing certificate Comment attribute. You may change it to something or use the default value set by PHPki.
SSL Server Certificate Comment
SSL server certificate Comment attribute. You may change it to something or use the default value set by PHPki.
Time Stamping Certificate Comment
Time stamping certificate Comment attribute. You may change it to something or use the default value set by PHPki.

Configuration Options

Storage Directory *
Enter the location where PHPki will store its files. This should be a directory where the web server has full read/write access (chown ; chmod 700), and is preferably outside of DOCUMENT_ROOT (). You may have to manually create the directory before completing this form.
Location of OpenSSL Executable *
Enter the location of your OpenSSL binary. The default is usually ok.
Location of HTTP password file *
Enter the location of your PHPki user password file. The default is usually ok.
File Upload Prefix
This is an optional prefix which will be added to root certificate and certificate revocation list file uploads. Normally the root certificate is uploaded as caroot.crt. With a prefix like "acme_", the root certificate would be uploaded as "acme_caroot.crt".
Page Header Title
This title will be displayed superimposed over the PHPki logo at the top of every page.
Help Document Contact Info
This text will be inserted into the online help document under the "Getting Additional Help" section. Include full contact info for the convenience of your users. Use HTML tags to improve presentation.
* Required field