phpki-0.82

This commit is contained in:
2025-09-10 23:01:43 -04:00
parent 02a6566061
commit 66ea908568
78 changed files with 5094 additions and 1 deletions

373
root/ca/help.php Normal file
View File

@@ -0,0 +1,373 @@
<?php
include('../config.php');
include(STORE_DIR.'/config/config.php');
include('../include/my_functions.php');
include('../include/common.php');
printHeader(false);
?>
<p>
<center>
<table class=menu>
<th class=menu style="font-size: 24px;">PHPki HELP FILE<br>TABLE OF CONTENTS</th>
<tr><td class=menu style="padding: 1em;">
<a href=#WHY>Why PHPki</a><br>
<a href=#OVERVIEW>Overview</a><br>
<a href=#MAIN-MENU>Main Menu</a><br>
<a href=#REQUEST-FORM>Requesting a New Certificate</a><br>
<a href=#MANAGE>Managing Your Certificate With The Control Panel</a><br>
<a href=#REVOKE>Revoking a Certificate</a><br>
<a href=#DISPLAY>Displaying Certificate Details</a><br>
<a href=#RENEW>Renewing a Cettificate</a><br>
<a href=#DOWNLOAD>Downloading a Certificate</a><br>
<a href=../help.php target=help>End User Help Documents</a><br>
<a href=#GLOSSARY>The PHPki Glossary of Terms</a><br>
<a href=#GETTING-HELP>Getting Additional Help</a><br>
</td></tr>
</table>
</center>
<br><br><br><br><br><br>
<p>
<h2><a name="WHY">WHY PHPki</a></h2>
<blockquote>
PHPki is an <a href=http://www.opensource.org target=_blank>Open Source</a>
Web based application for managing a
<a href=../help/glossary.html#PKI target=glossary> "Public Key Infrastructure"</a>
within a small organization.
PHPki may be used to create and manage
<a href=../help/glossary.html#CERTIFICATE target=glossary>digital certificates</a>
for use with <a href=../help/glossary.html#SMIME target=glossary>S/MIME</a> enabled
e-mail clients, SSL servers, and VPN applications.
<p>
Most commercial
<a href=../help/glossary.html#CA target=glossary>certificate authorities (CA)</a>
require that certificates be issued to individual workstations, one at a time.
The transaction required to obtain a commercial certificate must usually take
place at the workstation on which the certifcate is to be installed, and can be
complicated, confusing, and time consuming. Such a process does not allow for
easy centralized administration of groups of certificates, where a single
person within an organization or department must request, create, and install
certificates on a number of workstations.
<p>
PHPki creates standard <a href=../help/glossary.html#X509 target=glossary>X.509</a>
digital certificates which should work with most e-mail clients.
It packages private certificates in the <a href=../help/glossary.html#PKCS12 target=glossary>PKCS#12</a> format accepted by Microsoft
e-mail clients <a href=../help/glossary.html#PEM target=glossary>PEM</a> used by certain web servers.
PKCS #12 certificates usually have a <cite>.P12</cite>
filename extension. Since most PKCS #12 certificates usually include the
certificate's private key, they should never be distributed to the general
public. PHPki's publicly distributable certificates are packaged in
standard <a href=../help/glossary.html#DER target=glossary>DER</a> format.
<p>
Server
</blockquote>
<p>
<h2><a name="OVERVIEW">OVERVIEW</a></h2>
<blockquote>
The process of creating and using digital certificates with PHPki is
fairly easy.
<ul>
<li>
First you must download and install our
<a href=../help/glossary.html#ROOT-CERT target=glossary>root certificate</a>
on your computer. Everyone else you intend to exchange encrypted e-mail
with must also install our root certificate.
Everyone who installs our root certificate becomes a member of our
"circle of trust". The PHPki main menu contains an option for downloading
our root certificate. Root certificates are not private and should be widely
distributed and published on the Internet in a conspicuous location.
The more widely published a root certificate is, the more difficult it becomes
to forge.
</li>
<p><li>
You must request and download a digital certificate for each person who will
<strong>RECEIVE</strong> encrypted e-mail at your agency. Remember, having a
digital certificate does not enable one to <strong>send</strong> encrypted
e-mail, but only to <strong>receive</strong> it. Each of the certificates
you download must be installed on the respective users' workstations.
If you wish to send encrypted e-mail to someone, you must install that person's
public certificate on your computer. You can obtain another person's public
certificate simply by having them send you a
<a href=../help/glossary.html#SIGNATURE target=glossary>digitally signed</a> e-mail message. When you receive the message, your e-mail
program should give you the option to add the sender's public key to your
address book or key ring. Once you have installed your digital certificates,
your users should send digitally signed messages to each person who will need
to send encrypted e-mail to them.
</li>
<p><li>
Users come and go, passwords are compromised, and files are lost, such is life.
PHPki includes a certificate management system for handling these situations.
The certificate management control panel gives you the ability to
display certificates in excruciating detail, revoke a certificate when its
e-mail address is no longer valid or its public key has been compromised,
renew certificates which have or will expire, and re-download a previously
issued certificate if you've lost the original.
</li>
<p><li>
There must be a method for letting outside entities know which of your
certificates have been revoked. The mechanism for doing this is the
<cite>Certificate Revocation List</cite> or CRL. A CRL is a digitally signed
list of certificates which have been revoked by a Certificate Authority.
Our CRL is updated periodically, and can be downloaded from the PHPki
Main Menu. Many e-mail clients will automatically download and install CRLs
using information embedded in certificates. However, there is no widely
adopted standard for automatic CRL checking, so it is not unusual to have
to manually install and update CRLs.
</li>
<p><li>
PHPki provides a public interface for Internet users to download our root
certificate and certificate revokation list. A certificate search feature
is also provided to allow easy distribution of public certificates over the
Internet.
</li>
</ul>
</blockquote>
<p>
<h2><a name=MAIN-MENU>THE MAIN MENU</a></h2>
<p>
<blockquote>
<center><img src=../images/main-menu.png width=700 ></center>
<p>
All of the PHPki primary functions can be accessed from the Main Menu.
It is possible to navigate back to the Main Menu from any screen by clicking the
"Menu" link in the upper right corner of each page. Clicking the <cite>Public</cite> link will open a new browser window to the public content menu where
the general public may search for certificates and download the
<a href=../help/glossary.html#ROOT-CERT target=glossary>Root Certificate</a> and <a href=../help/glossary.html#CRL target=glossary>Certificate Revocation List.</a>
</blockquote>
<p>
<h2><a name=REQUEST-FORM>REQUESTING A NEW CERTIFICATE</a></h2>
<blockquote>
When you select "Request a New Certificate" from the Main Menu, you will be
presented with the Certificate Request Form.<br>
<p>
<center><img src=../images/cert-request-form.png width=700 ></center>
<p>
This form is used to collect the minimum necessary information required to
issued a new digital certificate. All fields must be completed.
<blockquote><ul>
<li>
<u>E-mail User's Full Name:</u> Enter the full name of the user for which the certificate will be issued.
</li>
<p><li>
<u>E-mail Address:</u> Enter the e-mail address of the user for which the certificate is to be issued. This field will be checked for proper e-mail address
format, but the e-mail address is not verified otherwise.
</li>
<p><li>
<u>Organization:</u> Enter the full name of your organization (i.e. ACME Shoe Repair).
</li>
<p><li>
<u>Department/Unit:</u> Enter the name of the department or unit in which the
user works. (i.e. Accounting Department).
</li>
<p><li>
<u>Locality:</u> Enter the name of the City or County in which the organization
is located.
</li>
<p><li>
<u>State/Province:</u> Enter the name of the State or Province in which the organization
is located.
</li>
<p><li>
<u>Country:</u> Enter the name of the Country in which the organization
is located.
</li>
<p><li>
<u>Certificate Password:</u> Enter a password to protect the certificate.
If you enter a password, it must ben enter twice for verification.
This password will be used to encrypt the private key which will be packaged
with the completed certificate. It may also be required when installing a PKCS#12
certificate. <strong>This password should be handled with the
utmost security and should never be lost, as it cannot be recovered under
any circumstance.</strong> If this password is lost, you must immediately
revoke the certificate and request/create a new certificate for the user.
</li>
<p><li>
<u>Certificate Life:</u> Select the number of years you want the certificate to
be valid. Although it is common practice to issue certificates which are valid
for only one year, the option to issue certificates for a longer period is
available should you wish to be rebel. The certificate may be revoked or
renewed at any point during its life.
</li>
<p><li>
<u>Key Size:</u> Select this size of your private key in bits. Larger
keys are considered more secure. However, certain VPN applications may
have difficulty with keys larger than 1024 bits.
</li>
<p><li>
<u>Certificate Use:</u> Select the purpose for which the certificate will
be use. E-mail certifcates have different attributes from SSL server
certifcates and may not be interchangeable. Some IPSEC/VPN applications
may be sensitive to large certificates, so those certificates contain less
embedded information to keep them small.
</li>
</ul></blockquote>
<p>
When you have complete filling in the form, click the "Submit Request" button.
The information you submitted will be checked for errors, and a confirmation
screen will be displayed.
<p>
<center><img src=../images/request-confirm-form.png width=700></center>
<p>
Clicking the "Yes! Create and Download" button will cause a file download
window to open in your browser, allowing you to save the certificate on your
computer under whatever name you choose. The default name for each certificate
is derived from the e-mail address provided in the certificate request form.
You may download the certificate as many time as you wish as long as your
browser remains on this page. If you navigate from this page, you will have
to use the <cite>Certificate Management Control Panel</cite> to download the certificate
again. Be sure to save all of your certificates in a safe and secure
place. Doing so will make it easier for you to re-install a certificate on a
user's workstation should the need arise.<br>
<p>
After the download window closes, you may click the "Back" button to return
to the form and request another certificate. All of the data you previously
entered will be retained. This is to allow you to issue a large number of
certificates without having to re-enter much of the form. As well, your
form input will be saved as your default values for the future sessions<br>
</blockquote>
<p>
<h2><a name="MANAGE">MANAGING YOUR CERTIFICATES WITH THE CONTROL PANEL</a></h2>
<blockquote>
PHPki provides one convenient place to manage your certificates.
It is called the <cite>Certificate Management Control Panel</cite>.
<p>
<center><img src=../images/ctrl-panel-before.png width=700></center>
<p>
With the <cite>Control Panel</cite> you can display, download, revoke, and
renew your certificates by simply clicking on the appropriate button to the
right of each certificate entry. Your certificates are listed in columnar
format, with the left-most color coded "Status" column showing whether a
certificate is "<font color=green>Valid</font>" or
"<font color=red>Revoked</font>". The listing can be sorted in any order
by clicking on the column headings. An arrow graphic
&nbsp<img src=../images/uparrow-blue.gif height=12>&nbsp beside a column heading
indicates which column is being used to sort the listing. Clicking on the
arrow graphic will cause the listing to alternate between ascending and
descending sort order. You may find these sort features particularly useful if
you are careful to plan and utilize the <cite>Department/Unit</cite> and
<cite>Locality</cite> fields to categorize your certificates according to
your particular organizational needs.
</blockquote
<p>
<h2><a name="REVOKE">REVOKING A CERTIFICATE</a></h2>
<blockquote>
At times it may become necessary to revoke or invalidate a certificate. This
usually happens when an e-mail address is no longer valid, or the certificate's
private key has been lost or compromised.
<p>
To revoke a certificate, click on the <img src=../images/revoke.png align=top>&nbsp icon next to the certificate entry in the <cite>Control Panel</cite>.
<p>
<center><img src=../images/revoke-confirm.png width=700></center>
<p>
You will then be asked to confirm or cancel the revocation. Be absolutely
sure of what you wish to do before clicking the "Yes" button. Once a
certificate is revoked, it cannot be un-revoked. Well, this isn't completely
true, as a revoked certificate can be renewed. Renewing a revoked certificate
results in a <strong>new</strong> certificate being issued. Certificate
renewal is covererd later.
<p>
<center><img src=../images/ctrl-panel-after-revoke.png width=700></center>
<p>
If you click the "Yes" button, the certificate is revoked with no further
interaction. The certificate's status in the <cite>Control Panel</cite>
will change to <font color=red>Revoked</font>.
</blockquote>
<p>
<h2><a name="DISPLAY">DISPLAYING CERTIFICATE DETAILS</a></h2>
<blockquote>
Certificates may be displayed in full detail by clicking the
<img src=../images/display.png align=top>&nbsp icon next to a certificate's
entry in the <cite>Control Panel</cite>. Although some users may find this
feature useful, many will not find anything of interest in it.
<p>
<center><img src=../images/display-revoked.png width=700></center>
</blockquote>
<p>
<h2><a name="RENEW">RENEWING A CERTIFICATE</a></h2>
<blockquote>
Certificates expire periodically. The usually length a time for which a
certificate is valid is one year. With PHPki, you have the option to
issue certificates with a more extended life span. Regardless, sooner or later
your certificates will begin to expire.
<p>To renew a certificate which has expired or is near expiration, simply click
the <img src=../images/renew.png align=top>&nbsp icon next to the
certifcate's <cite>Control Panel</cite> entry. You will then be presented
with a certificate renewal form.
<p>
<center><img src=../images/renewal-form.png width=700></center>
<p>
The certificate renewal form takes the values for <cite>Common Name,
E-mail Address, Organization, etc.</cite> from the original certificate.
Those fields are disabled in the form, and cannot be changed.
You are required to enter the original certificate's password and select
a life span for the new certificate. If you do not enter the correct
password that was assigned to the original certificate when it was created,
you will not be able to renew the certificate. You may cancel this operation
by clicking the "Back" button, which will take you back to the
<cite>Control Panel</cite>.
<p>
<center><img src=../images/ctrl-panel-after-renew.png width=700></center>
<p>
If you click the "Submit Request" button to renew the certificate, it is
renewed with no further interaction, and you will be returned to the
<cite>Control Panel</cite>. You will notice a new
<font color=green>Valid</font> certificate in the <cite>Control Panel</cite>,
and the old expired certificate is marked <font color=red>Revoked</font>.
</blockquote>
<p>
<h2><a name=DOWNLOAD>DOWNLOADING A CERTIFICATE</a></h2>
<blockquote>
If you lose the original file you downloaded when you first created a
certificate, you may download another copy of a certificate at any time by
clicking the
<img src=../images/download.png align=top>&nbsp icon next to the certificate's entry
in the <cite>Control Panel</cite>. When downloading a certificate, you will
be reminded that the certificate is a
<strong><font color=red>PRIVATE</font> certificate, which <font color=red>
SHOULD NEVER BE DISTRIBUTED TO THE PUBLIC</font></strong>.
You may choose to download <a href=../help/glossary.html#PKCS12 target=glossary>PKCS #12</a> or <a href=../help/glossary.html#PEM target=glossary>PEM</a> formatted bundles.
<p>
<center><img src=../images/confirm-download.png width=700></center>
</blockquote>
<p>
<h2><a name=GLOSSARY>GLOSSARY</a></h2>
<blockquote>
Click <a href=../help/glossary.html#TOP target=glossary>here</a> to view the complete
PHPki glossary of terms.
</blockquote>
<p>
<h2><a name="GETTING-HELP">GETTING ADDITIONAL HELP</a></h2>
<blockquote>
<?=$config[getting_help]?>
</blockquote>
<br>
<?
printFooter();
?>

3
root/ca/index.php Normal file
View File

@@ -0,0 +1,3 @@
<?php
header("Location: ./../index.php");
?>

97
root/ca/main.php Normal file
View File

@@ -0,0 +1,97 @@
<?php
include("../config.php");
include(STORE_DIR.'/config/config.php');
include("../include/my_functions.php");
include("../include/common.php") ;
include("../include/openssl_functions.php");
$stage = gpvar('stage');
switch($stage) {
case 'dl_root':
upload("$config[cacert_pem]", "$config[ca_prefix]cacert.crt", 'application/x-x509-ca-cert');
break;
case 'dl_crl':
upload("$config[cacrl_der]", "$config[ca_prefix]cacrl.crl", 'application/pkix-crl');
break;
case 'gen_crl':
list($ret,$errtxt) = CA_generate_crl();
printHeader(false);
if ($ret) {
?>
<center><h2>Certificate Revocation List Updated</h2></center>
<p>
<form action=<?=$PHP_SELF?> method=post>
<input type=submit name=submit value="Back to Menu">
</form>
<?
print '<pre>'.CA_crl_text().'</pre>';
}
else {
?>
<font color=#ff0000>
<h2>There was an error updating the Certificate Revocation List.</h2></font><br>
<blockquote>
<h3>Debug Info:</h3>
<pre><?=$errtxt?></pre>
</blockquote>
<form action=<?=$PHP_SELF?> method=post>
<p>
<input type=submit name=submit value="Back to Menu">
<p>
</form>
<?
}
break;
default:
printHeader('ca');
?>
<br>
<br>
<center>
<table class=menu width=600><th class=menu colspan=2><big>CERTIFICATE MANAGEMENT MENU</big></th>
<tr><td style="text-align: center; vertical-align: middle; font-weight: bold;" width=33%>
<a href=request_cert.php>Create a New Certificate</a></td>
<td>Use the <strong><cite>Certificate Request Form</cite></strong> to create and download new digital certificates.
You may create certificates in succession without re-entering the entire form
by clicking the "<strong>Go Back</strong>" button after each certificate is created.</td></tr>
<tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
<a href=manage_certs.php>Manage Certificates</a></td>
<td>Conveniently view, download, revoke, and renew your existing certificates using the
<strong><cite>Certificate Management Control Panel</cite></strong>.</td></tr>
<tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
<a href=<?=$PHP_SELF?>?stage=gen_crl>Update & View the Certificate Revocation List</a></td>
<td>Some applications automagically reference the Certificate Revocation List to determine
certificate validity. It is not necessary to perform this update function, as the CRL is
updated when certificates are revoked. However, doing so is harmless.
<a href=../help.php target=_help>Read the online help</a> to learn more about this.</td></tr>
<tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
<a href=<?=$PHP_SELF?>?stage=dl_root>Download the Root Certificate</a></td>
<td>The "Root" certificate must be installed before using any of the
certificates issued here. <a href=../help.php target=_help>Read the online help</a>
to learn more about this.</td></tr>
<tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
<a href=<?=$PHP_SELF?>?stage=dl_crl>Download the Certificate Revocation List</a></td>
<td>This is the official list of revoked certificates. Using this list with your e-mail or
browser application is optional. Some applications will automagically reference this list. </td></tr>
</table>
</center>
<br><br>
<?
printFooter();
}
?>

408
root/ca/manage_certs.php Normal file
View File

@@ -0,0 +1,408 @@
<?php
include('../config.php');
include(STORE_DIR.'/config/config.php');
include('../include/my_functions.php');
include('../include/common.php');
include('../include/openssl_functions.php');
$stage = gpvar('stage');
$serial = gpvar('serial');
$sortfield = gpvar('sortfield');
$ascdec = gpvar('ascdec');
$passwd = gpvar('passwd');
$expiry = gpvar('expiry');
$submit = gpvar('submit');
$dl_type = gpvar('dl_type');
$search = gpvar('search');
$show_valid = gpvar('show_valid');
$show_revoked = gpvar('show_revoked');
$show_expired = gpvar('show_expired');
# Prevent handling certs that don't belong to user
if ($serial && CAdb_issuer($serial) != $PHPki_user && ! in_array($PHPki_user, $PHPki_admins)) {
$stage = 'goaway';
}
if ( !($show_valid.$show_revoked.$show_expired) ) {
$show_valid = 'V';
$show_revoked = 'R';
$show_expired = 'E';
}
$qstr_filter = 'search='.htvar($search).'&'.
"show_valid=$show_valid&".
"show_revoked=$show_revoked&".
"show_expired=$show_expired&";
$qstr_sort = "sortfield=$sortfield&ascdec=$ascdec";
switch ($stage) {
case 'goaway':
printHeader(false);
?> <p><center><h1><font color=red>YOU ARE A VERY BAD BOY!</font></h2></center> <?
break;
case 'display':
printHeader(false);
?>
<center><h2>Certificate Details</h2></center>
<center><font color=#0000AA><h3>(#<?=$serial?>)<br><?=htvar(CA_cert_cname($serial).' <'.CA_cert_email($serial).'>')?> </h3></font></center>
<?
if ($revoke_date = CAdb_is_revoked($serial))
print '<center><font color=red><h2>REVOKED '.$revoke_date.'</h2></font></center>';
print '<pre>'.CA_cert_text($serial).'</pre>';
break;
case 'dl-confirm':
printHeader('ca');
$rec = CAdb_get_entry($serial);
?>
<h3>You are about to download the <font color=red>PRIVATE</font> certificate key for <?=$rec['common_name'].' &lt;'.$rec['email'].'&gt; '?></h3>
<h3><font color=red>DO NOT DISTRIBUTE THIS FILE TO THE PUBLIC!</font></h3>
<form action="<?=$PHP_SELF.'?stage=download&serial='.$serial.'&'.$qstr_sort.'&'.$qstr_filter?>" method=post>
<strong>File type: </strong>
<td><select name=dl_type>
<option value="PKCS#12">PKCS#12 Bundle</option>
<option value="PEMCERT">PEM Certificate</option>
<option value="PEMKEY">PEM Key</option>
<option value="PEMBUNDLE">PEM Bundle</option>
<option value="PEMCABUNDLE">PEM Bundle w/Root</option>
</select>
<input type=submit name=submit value="Download">
&nbsp; or &nbsp;
<input type=submit name=submit value="Go Back">
</form>
<?
break;
case 'download':
if (strstr($submit, "Back")) $dl_type = '';
$rec = CAdb_get_entry($serial);
switch ($dl_type) {
case 'PKCS#12':
upload("$config[pfx_dir]/$serial.pfx", "$rec[common_name] ($rec[email]).p12", 'application/x-pkcs12');
break;
case 'PEMCERT':
upload("$config[new_certs_dir]/$serial.pem", "$rec[common_name] ($rec[email]).pem",'application/pkix-cert');
break;
case 'PEMKEY':
upload("$config[private_dir]/$serial-key.pem", "$rec[common_name] ($rec[email])-key.pem",'application/octet-stream');
break;
case 'PEMBUNDLE':
upload(array("$config[private_dir]/$serial-key.pem","$config[new_certs_dir]/$serial.pem"), "$rec[common_name] ($rec[email]).pem",'application/octet-stream');
break;
case 'PEMCABUNDLE':
upload(array("$config[private_dir]/$serial-key.pem","$config[new_certs_dir]/$serial.pem",$config['cacert_pem']), "$rec[common_name] ($rec[email]).pem",'application/octet-stream');
break;
default:
header("Location: ${PHP_SELF}?$qstr_sort&$qstr_filter");
}
break;
case 'revoke-form':
$rec = CAdb_get_entry($serial);
printHeader('ca');
?>
<h4>You are about to <font color=red>REVOKE</font> the following certificate:</hr>
<table width=500><tr>
<td width=25% style='white-space: nowrap'>
<p align=right>
Serial Number<br>
User's Name<br>
Email Address<br>
Organization<br>
Department/Unit<br>
Locality<br>
State/Province<br>
Country<br>
</td>
<?
print '
<td>
'.htvar($rec[serial]).'<br>
'.htvar($rec[common_name]).'<br>
'.htvar($rec[email]).'<br>
'.htvar($rec[organization]).'<br>
'.htvar($rec[unit]).'<br>
'.htvar($rec[locality]).'<br>
'.htvar($rec[province]).'<br>
'.htvar($rec[country]).'<br>
</td>
</tr></table>
<h4>Are you sure?</h4>
<p><form action="'.$PHP_SELF.'?'.$qstr_sort.'&'.$qstr_filter.'" method=post>
<input type=hidden name=stage value=revoke >
<input type=hidden name=serial value='.$serial.' >
<input type=submit name=submit value=Yes >&nbsp
<input type=submit name=submit value=Cancel>
</form>';
break;
case 'revoke':
$ret = true;
if ($submit == 'Yes')
list($ret, $errtxt) = CA_revoke_cert($serial);
if (! $ret) {
printHeader('ca');
print "<form action=\"$PHP_SELF?stage=revoke-form&serial=$serial&$qstr_sort&$qstr_filter\" method=post>";
?>
<font color=#ff0000>
<h2>There was an error revoking your certificate
.</h2></font><br>
<blockquote>
<h3>Debug Info:</h3>
<pre><?=$errtxt?></pre>
</blockquote>
<p>
<input type=submit name=submit value=Back>
<p>
</form>
<?
}
else
header("Location: ${PHP_SELF}?$qstr_sort&$qstr_filter");
break;
case 'renew-form':
#
# Get last known values submitted by this user. We only really
# need the expiry value, but the old cert values will override
# the rest.
#
if (! $submit and file_exists("config/user-${PHPki_user}.php"))
include("config/user-${PHPki_user}.php");
#
# Get values from the old certificate.
#
$rec = CAdb_get_entry($serial);
$country = $rec['country'];
$province = $rec['province'];
$locality = $rec['locality'];
$organization = $rec['organization'];
$unit = $rec['unit'];
$common_name = $rec['common_name'];
$email = $rec['email'];
printHeader('ca');
?>
<body onLoad="self.focus();document.form.passwd.focus()">
<form action="<?=$PHP_SELF.'?'.$qstr_sort.'&'.$qstr_filter?>" method=post name=form>
<table width=99%>
<th colspan=2><h3>Certificate Renewal Form</h3></th>
<tr>
<td width=25%>Common Name </td>
<td><input type=text name=common_name value="<?= htvar($common_name)?>" size=50 maxlength=60 disabled></td>
</tr>
<tr>
<td>E-mail Address </td>
<td><input type=text name=email value="<?=htvar($email)?>" size=50 maxlength=60 disabled></td>
</tr>
<tr>
<td>Organization </td>
<td><input type=text name=organization value="<?=htvar($organization)?>" size=60 maxlength=60 disabled></td>
</tr>
<tr>
<td>Department/Unit </td><td><input type=text name=unit value="<?= htvar($unit) ?>" size=40 maxlength=60 disabled></td>
</tr>
<tr>
<td>Locality</td><td><input type=text name=locality value="<?= htvar($locality) ?>" size=30 maxlength=30 disabled></td>
</tr>
<tr>
<td>State/Province</td><td><input type=text name=province value="<?= htvar($province) ?>" size=30 maxlength=30 disabled></td>
</tr>
<tr>
<td>Country</td>
<td><input type=text name=country value="<?= htvar($country) ?>" size=2 maxlength=2 disabled></td>
</tr>
<tr>
<td>Certificate Password </td>
<td><input type=password name=passwd value="<?= htvar($passwd) ?>" size=30></td>
</tr>
<tr>
<td>Certificate Life </td>
<td><select name=expiry>
<?
print "<option value=1 " . ($expiry == 1 ? "selected='selected'" : "") . " >1 Year</option>\n" ;
for ( $i = 2 ; $i < 6 ; $i++ ) {
print "<option value=$i " . ($expiry == $i ? "selected='selected'" : "") . " >$i Years</option>\n" ;
}
?>
</select></td>
</tr>
<tr>
<td>
<center><input type=submit name=submit value="Submit Request">&nbsp
<input type=submit name=submit value="Back"></center>
</td>
<td>
<input type=hidden name=stage value=renew>
<input type=hidden name=serial value=<?=$serial?>>
</td>
</tr>
</table>
</form>
<?
printFooter();
break;
case 'renew':
$ret = true;
if ($submit == "Submit Request")
list($ret, $errtxt) = CA_renew_cert($serial, $expiry, $passwd);
if (! $ret) {
printHeader('ca');
print "<form action=\"$PHP_SELF?stage=renew-form&serial=$serial&$qstr_sort&$qstr_filter\" method=post>";
?>
<font color=#ff0000>
<h2>There was an error creating your certificate
.</h2></font><br>
<blockquote>
<h3>Debug Info:</h3>
<pre><?=$errtxt?></pre>
</blockquote>
<p>
<input type=submit name=submit value=Back>
<p>
</form>
<?
}
else {
header("Location: $PHP_SELF?$qstr_sort&$qstr_filter");
}
break;
default:
printHeader('ca');
?>
<body onLoad="self.focus();document.filter.search.focus()">
<table>
<tr><th colspan=8><big>CERTIFICATE MANAGEMENT CONTROL PANEL</big></th></tr>
<tr><td colspan=8><center>
<form action="<?="$PHP_SELF?$qstr_sort"?>" method=get name=filter>
Search: <input type=text name=search value="<?=htvar($search)?>" style="font-size: 11px;" maxlength=60 size=30>
&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp<input type=checkbox name=show_valid value="V" <?=($show_valid?'checked'
:'')?>>Valid
&nbsp&nbsp<input type=checkbox name=show_revoked value="R" <?=($show_revoked?'checked':'')?>>Revoked
&nbsp&nbsp<input type=checkbox name=show_expired value="E" <?=($show_expired?'checked':'')?>>Expired
&nbsp&nbsp&nbsp&nbsp&nbsp<input type=submit name=submit value="Apply Filter" style="font-size: 11px;">
</form>
</center></td>
</tr>
<?
if (! $sortfield) {
$sortfield = 'email' ;
$ascdec = 'A';
}
if ($ascdec == 'A') {
$arrow_gif = '../images/uparrow-blue.gif';
$ht_ascdec = 'D';
}
else {
$arrow_gif = '../images/downarrow-blue.gif';
$ht_ascdec = 'A';
}
print '<tr>';
$headings = array(
status=>"Status", issued=>"Issued", expires=>"Expires",
common_name=>"User's Name", email=>"E-mail",
organization=>"Organization", unit=>"Department",
locality=>"Locality"
);
foreach($headings as $field=>$head) {
print '<th><a href="'.$PHP_SELF.'?sortfield='.$field.'&ascdec=A&'.$qstr_filter.'" title="Click to sort on this column."><u>'.$head.'</u></a>';
if ($sortfield == $field) {
print '&nbsp<a href="'.$PHP_SELF.'?sortfield='.$field.'&ascdec='.$ht_ascdec.'&'.$qstr_filter.'" >'.
'<img src='.$arrow_gif.' height=12 alt=\'Change sort order.\' title=\'Click to reverse sort order.\'></a>';
}
print '</th>';
}
print '</tr>';
$x = "^[$show_valid$show_revoked$show_expired]";
if (in_array($PHPki_user, $PHPki_admins)) {
$x = "$x.*$search";
}
else {
$x = "$x.*$search.*$PHPki_user|$x.*$PHPki_user.*$search";
}
$db = csort(CAdb_to_array($x), $sortfield, ($ascdec=='A'?SORT_ASC:SORT_DESC));
$stcolor = array(Valid=>'green',Revoked=>'red',Expired=>'orange');
foreach($db as $rec) {
print '<tr style="font-size: 11px;">
<td><font color='.$stcolor[$rec['status']].'><b>' .$rec[status].'</b></font></td>
<td style="white-space: nowrap">'.$rec[issued].'</td>
<td style="white-space: nowrap">'.$rec[expires].'</td>
<td>'.$rec[common_name].'</td>
<td style="white-space: nowrap"><a href="mailto:' . htvar($rec['common_name']) . ' <' . htvar($rec['email']) . '>" >' . htvar($rec['email']) . '</a></td>
<td>'.htvar($rec[organization]).'</td>
<td>'.htvar($rec[unit]).'</td>
<td>'.htvar($rec[locality]).'</td>
<td><a href="'.$PHP_SELF.'?stage=display&serial='.$rec[serial].'" target=_certdisp>'.
'<img src=../images/display.png alt="Display" title="Display complete certificate details."></a>';
if ($rec['status'] == 'Valid') {
print '
<a href="'.$PHP_SELF.'?stage=dl-confirm&serial='.$rec[serial].'&'.$qstr_sort.'&'.$qstr_filter.'">'.
'<img src=../images/download.png alt="Download" title="Download the PRIVATE certificate. DO NOT DISTRIBUTE THIS TO THE PUBLIC!"></a>
<a href="'.$PHP_SELF.'?stage=revoke-form&serial='.$rec[serial].'&'.$qstr_sort.'&'.$qstr_filter.'">'.
'<img src=../images/revoke.png alt="Revoke" title="Revoke the certificate when the e-mail address is no longer valid or the certificate password or private key has been compromised."></a>';
}
print '
<a href="'.$PHP_SELF.'?stage=renew-form&serial='.$rec[serial].'&'.$qstr_sort.'&'.$qstr_filter.'">'.
'<img src=../images/renew.png alt="Renew" title="Renew the certificate by revoking it, if necessary, and creating a replacement with a new expiration date."></a></td></tr>';
}
print '</table>';
printFooter();
}
?>

78
root/ca/policy.html Normal file
View File

@@ -0,0 +1,78 @@
<html>
<head>
<title>Certificate Authority Agreement</title>
</head>
<body>
<h2 align=center>Certificate Authority Agreement</h2>
<h3 align=center>Policy and Practices</h3>
<br><br>
<p>This is a statement of practices by this Digital Certificate Authority.
Your use of this Certificate Authority constitutes your and/or your agency's
understanding and full acceptance of these practices and all associated risks.
<strong>Please have an authorized person at your agency sign this document and fax it to 000-000-0000</strong>
<p>This document may not be all encompassing, and we reserve the right to modify it at any time.
<ul>
<li> The sole role of this Certificate Authority is
to provide and maintain a password protected software application for the easy
and instant creation and management of standard x.509 personal digital
certificates for e-mail encryption. We assume no responsibility for
verifying the identity of any persons other than that of the limited number of
authorized users of the software.
We accept no liability for damages resulting from the use, misuse,
or compromise of the software application or its host server.
<p><li>As an authorized user of the software, you are in effect <strong>THE</strong> Certificate Authority for your
agency. As such, you are solely
responsible for authenticating the identity of the persons for whom you obtain
certificates. We accept no
responsibility or liability for non-repudiation in any digital certificate
created by this software. You agree that
password protection to the application by authorized certificate managers,
and personal identity management by
those managers is sufficient to create a chain of trust for non-repudiation
in all digital certificates created using the software.
<p><li>No more than two(2)
users at your agency should have access to your agency's Certificate Authority
password. We should be notified
immediately, via e-mail, when the employment of any
authorized user at your agency is terminated so that a new password can be
issued.
<p><li>This Certificate
Authority software application is accessed via the Internet using standard SSL
or Secure Server encryption mechanisms.
Although steps have been taken to protect the security and availability
of the host server and application, its exposure to the Internet as well as any
presently unknown security flaws could lead to potential compromise of the
software and your certificates.
<p><li>No promise is made as
to the availability of the software in the event of hardware, software, or
telecommunications failure or maintenance.<2E>
No advanced notice will be given when the software must be temporarily
taken off line for service.
<p><li>In order to provide
software which can easily create &quot;instant&quot; certificates it is
necessary to store all private keys on the host server. As such, all private keys are potentially exposed
to the Internet and suffer some risk of unauthorized access. However, since all private keys <strong>ARE
ENCRYPTED</strong> using a password provided by you, they are unlikely to be usable by
any intruder.
<p><li>A publicly accessible
web page is provided for interested Internet users to download the Certificate
Authority root certificate, certificate revocation list, and search for the
e-mail addresses and public certificates of users. So as to avoid e-mail address scraping by spammers, no static
content with users' e-mail addresses is available.
</ul>
</body>
</html>

326
root/ca/request_cert.php Normal file
View File

@@ -0,0 +1,326 @@
<?php
include('../config.php');
include(STORE_DIR.'/config/config.php');
include('../include/my_functions.php');
include('../include/common.php') ;
include('../include/openssl_functions.php') ;
# User's preferences file
$user_cnf = "$config[home_dir]/config/user-".strtr($PHPki_user,'/\\','|#').'.php';
# Retrieve GET/POST values
$form_stage = gpvar('form_stage');
$submit = gpvar('submit');
$country = gpvar('country');
$province = gpvar('province');
$locality = gpvar('locality');
$organization = gpvar('organization');
$unit = gpvar('unit');
$common_name = gpvar('common_name');
$email = gpvar('email');
$passwd = gpvar('passwd');
$passwdv = gpvar('passwdv');
$expiry = gpvar('expiry');
$keysize = gpvar('keysize');
$cert_type = gpvar('cert_type');
# To repopulate form after error.
$hidden_fields = '
<input type=hidden name=country value="' . htvar($country) . '">
<input type=hidden name=province value="' . htvar($province) . '">
<input type=hidden name=locality value="' . htvar($locality) . '">
<input type=hidden name=organization value="' . htvar($organization) . '">
<input type=hidden name=unit value="' . htvar($unit) . '">
<input type=hidden name=common_name value="' . htvar($common_name) . '">
<input type=hidden name=email value="' . htvar($email) . '">
<input type=hidden name=passwd value="' . htvar($passwd) . '">
<input type=hidden name=passwdv value="' . htvar($passwdv) . '">
<input type=hidden name=expiry value="' . htvar($expiry) . '">
<input type=hidden name=keysize value="' . htvar($keysize) . '">
<input type=hidden name=cert_type value="' . htvar($cert_type) . '">
';
switch ($form_stage) {
case 'validate':
$er = '';
if (! $country) $er .= 'Missing Country<br>';
if (! $province) $er .= 'Missing State/Province<br>';
if (! $locality) $er .= 'Missing Locality (City/County)<br>';
if (! $organization) $er .= 'Missing Organization (Company/Agency)<br>';
if (! $unit) $er .= 'Missing Unit/Department<br>';
if (! $common_name) $er .= 'Missing E-mail User\'s Full Name<br>';
if (! $email) $er .= 'Missing E-mail Address<br>';
if (($cert_type == 'email' || $cert_type == 'email_signing') && ! $passwd) $er .= 'Missing Certificate Password<br>';
if (($cert_type == 'email' || $cert_type == 'email_signing') && ! $passwdv) $er .= 'Missing Certificate Password Verification "Again"<br>';
if ( $passwd && strlen($passwd) < 8 )
$er .= 'Certificate password is too short.<br>';
if ( $passwd and $passwd != $passwdv )
$er .= 'Password and password verification do not match.<br>';
//if ( ! is_alnum($passwd) or ! is_alnum($passwdv) )
// $er .= 'Password contains invalid characters.<br>';
if ( $email && ! is_email($email) )
$er .= 'E-mail address ('. htvar($email) . ') may be invalid.<br>';
if ( $er )
$er = '<h2>ERROR(S) IN FORM:</h2><h4><blockquote>' . $er . '</blockquote></h4>';
if ($email && ($serial = CAdb_in($email,$common_name))) {
$er = '';
$certtext = CA_cert_text($serial);
$er .= '<h2>A valid certificate already exists for ' . htvar("$common_name <$email>") . '</h2>';
$er .= '</font><blockquote><pre> ' . htvar($certtext) . ' </pre></blockquote>';
}
if ($er) {
printHeader();
?>
<form action='<?=$PHP_SELF?>' method=post>
<input type=submit name=submit value='Go Back'>
<font color=#ff0000><?=$er?></font>
<br><input type=submit name=submit value='Go Back'>
<?
print $hidden_fields;
print "</form>";
printFooter();
break;
}
case 'confirm':
printHeader();
?>
<h4>You are about to create a certificate using the following information:</h4>
<table width=500><tr>
<td width=25% style='white-space: nowrap'>
<p align=right>
User's Name<br>
E-mail Address<br>
Organization<br>
Department/Unit<br>
Locality<br>
State/Province<br>
Country<br>
Certificate Life<br>
Key Size<br>
Certificate Use<br>
</td>
<td>
<?
print htvar($common_name) . '<br>';
print htvar($email) . '<br>';
print htvar($organization) . '<br>';
print htvar($unit) . '<br>';
print htvar($locality) . '<br>';
print htvar($province) . '<br>';
print htvar($country) . '<br>';
print htvar($expiry). ' Year'.($expiry == 1 ? '' : 's').'<br>';
print htvar($keysize). ' bits<br>';
print htvar($cert_type). '<br>';
?>
</td>
</tr></table>
<h4>Are you sure?</h4>
<p><form action='<?=$PHP_SELF?>' method=post>
<?= $hidden_fields ?>
<input type=hidden name=form_stage value=final>
<input type=submit name=submit value='Yes! Create and Download' >&nbsp;
<input type=submit name=submit value='Go Back'>
</form>
<?
printFooter();
# Save user's defaults
$fp = fopen($user_cnf,'w');
$x = '<?php
$country = \''.addslashes($country).'\';
$locality = \''.addslashes($locality).'\';
$province = \''.addslashes($province).'\';
$organization = \''.addslashes($organization).'\';
$unit = \''.addslashes($unit).'\';
$expiry = \''.addslashes($expiry).'\';
$keysize = \''.addslashes($keysize).'\';
?>';
fwrite($fp,$x);
fclose($fp);
break;
case 'final':
if ($submit == "Yes! Create and Download") {
if (! $serial = CAdb_in($email,$common_name)) {
list($ret,$errtxt) = CA_create_cert($cert_type,$country, $province, $locality, $organization, $unit, $common_name, $email, $expiry, $passwd, $keysize);
if (! $ret) {
printHeader();
?>
<form action=<?=$PHP_SELF?> method=post>
<font color=#ff0000>
<h2>There was an error creating your certificate.</h2></font><br>
<blockquote>
<h3>Debug Info:</h3>
<pre><?=$errtxt?></pre>
</blockquote>
<p>
<?=$hidden_fields?>
<input type=submit name=submit value=Back>
<p>
</form>
<?
printFooter();
break;
}
else {
$serial = $errtxt;
}
}
switch($cert_type) {
case 'server':
upload(array("$config[private_dir]/$serial-key.pem","$config[new_certs_dir]/$serial.pem",$config['cacert_pem']), "$common_name ($email).pem",'application/pkix-cert');
break;
case 'email':
case 'email_signing':
case 'time_stamping':
case 'vpn_client_server':
case 'vpn_client':
case 'vpn_server':
upload("$config[pfx_dir]/$serial.pfx", "$common_name ($email).p12", 'application/x-pkcs12');
break;
}
break;
}
default:
#
# Default fields to reasonable values if necessary.
#
if (! $submit and file_exists($user_cnf)) include($user_cnf);
if (! $country) $country = $config['country'];
if (! $province) $province = $config['province'];
if (! $locality) $locality = "";
if (! $organization) $organization = "";
if (! $unit) $unit = "";
if (! $email) $email = "";
if (! $expiry) $expiry = 1;
if (! $keysize) $keysize = 1024;
if (! $cert_type) $cert_type = 'email';
printHeader();
?>
<body onLoad="self.focus();document.request.common_name.focus()">
<form action="<?=$PHP_SELF?>" method=post name=request>
<table width=99%>
<th colspan=2><h3>Certificate Request Form</h3></th>
<tr>
<td width=30%>Common Name<br>(i.e. User real name or computer hostname) </td>
<td><input type=text name=common_name value="<?= htvar($common_name)?>" size=50 maxlength=60></td>
</tr>
<tr>
<td>E-mail Address </td>
<td><input type=text name=email value="<?=htvar($email)?>" size=50 maxlength=60></td>
</tr>
<tr>
<td>Organization (Company/Agency)</td>
<td><input type=text name=organization value="<?=htvar($organization)?>" size=60 maxlength=60></td>
</tr>
<tr>
<td>Department/Unit </td><td><input type=text name=unit value="<?= htvar($unit) ?>" size=40 maxlength=60></td>
</tr>
<tr>
<td>Locality (City/County)</td><td><input type=text name=locality value="<?= htvar($locality) ?>" size=30 maxlength=30></td>
</tr>
<tr>
<td>State/Province</td><td><input type=text name=province value="<?= htvar($province) ?>" size=30 maxlength=30></td>
</tr>
<tr>
<td>Country</td>
<td><input type=text name=country value="<?= htvar($country) ?>" size=2 maxlength=2></td>
</tr>
<tr>
<td>Certificate Password </td>
<td><input type=password name=passwd value="<?= htvar($passwd) ?>" size=30>&nbsp;&nbsp; Again <input type=password name=passwdv value="<?= htvar($passwdv) ?>" size=30></td>
</tr>
<tr>
<td>Certificate Life </td>
<td><select name=expiry>
<?
print "<option value=1 " . ($expiry == 1 ? "selected='selected'" : "") . " >1 Year</option>\n" ;
for ( $i = 2 ; $i < 6 ; $i++ ) {
print "<option value=$i " . ($expiry == $i ? "selected='selected'" : "") . " >$i Years</option>\n" ;
}
?>
</select></td>
</tr>
<tr>
<td>Key Size </td>
<td><select name=keysize>
<?
for ( $i = 512 ; $i < 4096 ; $i+= 512 ) {
print "<option value=$i " . ($keysize == $i ? "selected='selected'" : "") . " >$i bits</option>\n" ;
}
?>
</select></td>
</tr>
<tr>
<td>Certificate Use: </td>
<td><select name=cert_type>
<?
print '<option value="email" '.($cert_type=='email'?'selected':'').'>E-mail, SSL Client</option>';
print '<option value="email_signing" '.($cert_type=='email_signing'?'selected':'').'>E-mail, SSL Client, Code Signing</option>';
print '<option value="server" '.($cert_type=='server'?'selected':'').'>SSL Server</option>';
print '<option value="vpn_client" '.($cert_type=='vpn_client'?'selected':'').'>VPN Client Only</option>';
print '<option value="vpn_server" '.($cert_type=='vpn_server'?'selected':'').'>VPN Server Only</option>';
print '<option value="vpn_client_server" '.($cert_type=='vpn_client_server'?'selected':'').'>VPN Client, VPN Server</option>';
print '<option value="time_stamping" '.($cert_type=='time_stamping'?'selected':'').'>Time Stamping</option>';
?>
</select></td>
</tr>
<tr>
<td><center><input type=submit name=submit value='Submit Request'></center><input type=hidden name=form_stage value='validate'></td><td><font color=red size=3>* All fields are required</td>
</tr>
</table>
</form>
<?
printFooter();
}
?>