&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'); $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
'; 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 ( $email && ! 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 = md5 [ 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]index.php?stage=dl_crl nsComment = "PHPki/OpenSSL Generated Root Certificate Authority" #nsCaRevocationUrl = ns_revoke_query.php? nsCaPolicyUrl = $config[base_url]policy.html [ 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]index.php?stage=dl_crl nsComment = "PHPki/OpenSSL Generated Personal Certificate" nsBaseUrl = $config[base_url] nsRevocationUrl = ns_revoke_query.php? #nsRenewalUrl = nsCaPolicyUrl = $config[base_url]policy.html #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]index.php?stage=dl_crl nsComment = "PHPki/OpenSSL Generated Personal Certificate" nsBaseUrl = $config[base_url] nsRevocationUrl = ns_revoke_query.php? #nsRenewalUrl = nsCaPolicyUrl = $config[base_url]policy.html #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]index.php?stage=dl_crl nsComment = "PHPki/OpenSSL Generated Secure Server Certificate" nsBaseUrl = $config[base_url] nsRevocationUrl = ns_revoke_query.php? nsCaPolicyUrl = $config[base_url]policy.html [ 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]index.php?stage=dl_crl nsComment = \"PHPki/OpenSSL Generated Time Stamping Certificate\" nsBaseUrl = $config[base_url] nsRevocationUrl = ns_revoke_query.php? nsCaPolicyUrl = $config[base_url]policy.html [ 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 = 1024 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 = 1024 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(); 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 $store_dir/dhparam1024.pem.

"; $cmd = "openssl dhparam -rand '$config[random]' -out '$config[private_dir]/dhparam1024.pem' 1024"; print $cmd.'
'; flush(); flush_exec($cmd,100); #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 (! $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'); ?>
method=post>

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 *
Password *
This password will be used to protect your root certificate private key. 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.

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