patches applied from our bz and from sourceforge tickets

phpki-0.82.bz10622.fixphpwarnings.patch         phpki-0.82-empty_pass_php_5.2.patch      phpki-0.82-remove_email_from_upload_file_name.patch
phpki-0.82-ca_admin_users.patch                 phpki-0.82-expirey.patch                 phpki-0.82-remove_security_warning.patch
phpki-0.82-ca_help.patch                        phpki-0.82-fix-dates-2.patch             phpki-0.82-sme_admin_user.patch
phpki-0.82-disable_download_after_create.patch  phpki-0.82-fix-dates-3.patch             phpki-0.82-sme_openvpn_bridge_compat.patch
phpki-0.82-display_root_pem.patch               phpki-0.82-fix-dates.patch               phpki-0.82-update_crl_via_cron.patch
phpki-0.82-dl_crl_in_pem.patch                  phpki-0.82-fix-preg_match.patch          phpki-0.82-use_sha1.patch
phpki-0.82-dl_display_ta_dh.patch               phpki-0.82-openvpn_static_key.patch
phpki-0.82-email_signing.patch                  phpki-0.82-potential_xss_php_self.patch
This commit is contained in:
2025-09-10 23:04:01 -04:00
parent 66ea908568
commit 245e1bcd0b
12 changed files with 299 additions and 123 deletions

View File

@@ -28,7 +28,7 @@ case 'list_users':
case 'add_user_form'; case 'add_user_form';
printHeader('admin'); printHeader('admin');
?> ?>
<body onLoad="self.focus();document.form.login.focus()"> <body onLoad="self.focus();document.form.login.focus();">
<form action=<?=$PHP_SELF?> method=post name=form> <form action=<?=$PHP_SELF?> method=post name=form>
<table> <table>
<th colspan=2><h3>Add User or Change Password</h3></th> <th colspan=2><h3>Add User or Change Password</h3></th>
@@ -76,7 +76,7 @@ case 'add_user':
case 'del_user_form'; case 'del_user_form';
printHeader('admin'); printHeader('admin');
?> ?>
<body onLoad="self.focus();document.form.login.focus()"> <body onLoad="self.focus();document.form.login.focus();">
<form action=<?=$PHP_SELF?> method=post name=form> <form action=<?=$PHP_SELF?> method=post name=form>
<table> <table>
<th colspan=2><h3>Remove User</h3></th> <th colspan=2><h3>Remove User</h3></th>

View File

@@ -10,6 +10,14 @@ $stage = gpvar('stage');
switch($stage) { switch($stage) {
case 'dl_takey':
upload("$config[private_dir]/takey.pem", "$config[ca_prefix]takey.pem", 'application/octet-stream');
break;
case 'dl_dhparam':
upload("$config[private_dir]/dhparam1024.pem", "$config[ca_prefix]dhparam1024.pem", 'application/octet-stream');
break;
case 'dl_root': case 'dl_root':
upload("$config[cacert_pem]", "$config[ca_prefix]cacert.crt", 'application/x-x509-ca-cert'); upload("$config[cacert_pem]", "$config[ca_prefix]cacert.crt", 'application/x-x509-ca-cert');
break; break;
@@ -18,6 +26,10 @@ case 'dl_crl':
upload("$config[cacrl_der]", "$config[ca_prefix]cacrl.crl", 'application/pkix-crl'); upload("$config[cacrl_der]", "$config[ca_prefix]cacrl.crl", 'application/pkix-crl');
break; break;
case 'dl_crl_pem':
upload("$config[cacrl_pem]", "$config[ca_prefix]cacrl.crl", 'application/octet-stream');
break;
case 'gen_crl': case 'gen_crl':
list($ret,$errtxt) = CA_generate_crl(); list($ret,$errtxt) = CA_generate_crl();
@@ -50,6 +62,46 @@ case 'gen_crl':
} }
break; break;
case 'display_takey':
printHeader(false);
?>
<center><h2>OpenVPN pre-shared Key</h2></center>
<p>
<form action=<?=$PHP_SELF?> method=post>
<input type=submit name=submit value="Back to Menu">
</form>
<?
print '<pre>'.ta_key_text().'</pre>';
break;
case 'display_dhparam':
printHeader(false);
?>
<center><h2>OpenVPN Diffie-Helman parameters</h2></center>
<p>
<form action=<?=$PHP_SELF?> method=post>
<input type=submit name=submit value="Back to Menu">
</form>
<?
print '<pre>'.dhparam_text().'</pre>';
break;
case 'display_root_pem':
printHeader(false);
?>
<center><h2>Root certificate file (PEM Encoded)</h2></center>
<p>
<form action=<?=$PHP_SELF?> method=post>
<input type=submit name=submit value="Back to Menu">
</form>
<?
print '<pre>'.root_pem_text().'</pre>';
break;
default: default:
printHeader('ca'); printHeader('ca');
?> ?>
@@ -74,18 +126,31 @@ default:
<td>Some applications automagically reference the Certificate Revocation List to determine <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 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. 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> <a href=../ca/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;"> <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> <a href=<?=$PHP_SELF?>?stage=dl_root>Download the Root Certificate</a><br><br>
<a href=<?=$PHP_SELF?>?stage=display_root_pem>Display the Root Certificate (PEM Encoded)</a></td>
<td>The "Root" certificate must be installed before using any of the <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> certificates issued here. <a href=../ca/help.php target=_help>Read the online help</a>
to learn more about this.</td></tr> to learn more about this.</td></tr>
<tr><td style="text-align: center; vertical-align: middle; font-weight: bold;"> <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> <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 <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> browser application is optional. Some applications will automagically reference this list.
(<a href="<?=$PHP_SELF?>?stage=dl_crl_pem">Some will need it in PEM format.</a>)</td></tr>
<tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
<a href=<?=$PHP_SELF?>?stage=dl_takey>Download the static pre-shared key</a><br><br>
<a href=<?=$PHP_SELF?>?stage=display_takey>Display the static pre-shared key</a></td>
<td>This key can be used with OpenVPN as a standalone auth mecanism, or as an additionnal TLS authentication.</td></tr>
<tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
<a href=<?=$PHP_SELF?>?stage=dl_dhparam>Download the Diffie-Hellman parameters</a><br><br>
<a href=<?=$PHP_SELF?>?stage=display_dhparam>Display the Diffie-Hellman parameters</a></td>
<td>This file is used by OpenVPN for the hand-shake. The Diffie-Hellman key agreement
protocol enables two communication partners to exchange a secret key safely.</td></tr>
</table> </table>
</center> </center>

View File

@@ -20,12 +20,6 @@ $show_valid = gpvar('show_valid');
$show_revoked = gpvar('show_revoked'); $show_revoked = gpvar('show_revoked');
$show_expired = gpvar('show_expired'); $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) ) { if ( !($show_valid.$show_revoked.$show_expired) ) {
$show_valid = 'V'; $show_valid = 'V';
$show_revoked = 'R'; $show_revoked = 'R';
@@ -92,19 +86,19 @@ case 'download':
switch ($dl_type) { switch ($dl_type) {
case 'PKCS#12': case 'PKCS#12':
upload("$config[pfx_dir]/$serial.pfx", "$rec[common_name] ($rec[email]).p12", 'application/x-pkcs12'); upload("$config[pfx_dir]/$serial.pfx", "$rec[common_name].p12", 'application/x-pkcs12');
break; break;
case 'PEMCERT': case 'PEMCERT':
upload("$config[new_certs_dir]/$serial.pem", "$rec[common_name] ($rec[email]).pem",'application/pkix-cert'); upload("$config[new_certs_dir]/$serial.pem", "$rec[common_name]-cert.pem",'application/pkix-cert');
break; break;
case 'PEMKEY': case 'PEMKEY':
upload("$config[private_dir]/$serial-key.pem", "$rec[common_name] ($rec[email])-key.pem",'application/octet-stream'); upload("$config[private_dir]/$serial-key.pem", "$rec[common_name]-key.pem",'application/octet-stream');
break; break;
case 'PEMBUNDLE': 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'); upload(array("$config[private_dir]/$serial-key.pem","$config[new_certs_dir]/$serial.pem"), "$rec[common_name]-bundle.pem",'application/octet-stream');
break; break;
case 'PEMCABUNDLE': 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'); upload(array("$config[private_dir]/$serial-key.pem","$config[new_certs_dir]/$serial.pem",$config['cacert_pem']), "$rec[common_name]-bundle-root.pem",'application/octet-stream');
break; break;
default: default:
header("Location: ${PHP_SELF}?$qstr_sort&$qstr_filter"); header("Location: ${PHP_SELF}?$qstr_sort&$qstr_filter");
@@ -129,6 +123,7 @@ case 'revoke-form':
Locality<br> Locality<br>
State/Province<br> State/Province<br>
Country<br> Country<br>
</p>
</td> </td>
<? <?
@@ -145,7 +140,7 @@ case 'revoke-form':
</td> </td>
</tr></table> </tr></table>
<h4>Are you sure?</h4> <h4>Are you sure?</h4>
<p><form action="'.$PHP_SELF.'?'.$qstr_sort.'&'.$qstr_filter.'" method=post> <form action="'.$PHP_SELF.'?'.$qstr_sort.'&'.$qstr_filter.'" method=post>
<input type=hidden name=stage value=revoke > <input type=hidden name=stage value=revoke >
<input type=hidden name=serial value='.$serial.' > <input type=hidden name=serial value='.$serial.' >
<input type=submit name=submit value=Yes >&nbsp <input type=submit name=submit value=Yes >&nbsp
@@ -204,7 +199,7 @@ case 'renew-form':
printHeader('ca'); printHeader('ca');
?> ?>
<body onLoad="self.focus();document.form.passwd.focus()"> <body onLoad="self.focus();document.form.passwd.focus();">
<form action="<?=$PHP_SELF.'?'.$qstr_sort.'&'.$qstr_filter?>" method=post name=form> <form action="<?=$PHP_SELF.'?'.$qstr_sort.'&'.$qstr_filter?>" method=post name=form>
<table width=99%> <table width=99%>
@@ -252,8 +247,10 @@ case 'renew-form':
<td><select name=expiry> <td><select name=expiry>
<? <?
print "<option value=0.25 ". ($expiry == 0.25 ? "selected='selected'" : "") . " >3 Months</option>\n" ;
print "<option value=0.5 ". ($expiry == 0.5 ? "selected='selected'" : "") . " >6 Months</option>\n" ;
print "<option value=1 " . ($expiry == 1 ? "selected='selected'" : "") . " >1 Year</option>\n" ; print "<option value=1 " . ($expiry == 1 ? "selected='selected'" : "") . " >1 Year</option>\n" ;
for ( $i = 2 ; $i < 6 ; $i++ ) { for ( $i = 2 ; $i <= 5 ; $i++ ) {
print "<option value=$i " . ($expiry == $i ? "selected='selected'" : "") . " >$i Years</option>\n" ; print "<option value=$i " . ($expiry == $i ? "selected='selected'" : "") . " >$i Years</option>\n" ;
} }
@@ -289,8 +286,7 @@ case 'renew':
print "<form action=\"$PHP_SELF?stage=renew-form&serial=$serial&$qstr_sort&$qstr_filter\" method=post>"; print "<form action=\"$PHP_SELF?stage=renew-form&serial=$serial&$qstr_sort&$qstr_filter\" method=post>";
?> ?>
<font color=#ff0000> <font color=#ff0000>
<h2>There was an error creating your certificate <h2>There was an error creating your certificate.</h2></font><br>
.</h2></font><br>
<blockquote> <blockquote>
<h3>Debug Info:</h3> <h3>Debug Info:</h3>
<pre><?=$errtxt?></pre> <pre><?=$errtxt?></pre>
@@ -312,14 +308,13 @@ default:
printHeader('ca'); printHeader('ca');
?> ?>
<body onLoad="self.focus();document.filter.search.focus()"> <body onLoad="self.focus();document.filter.search.focus();">
<table> <table>
<tr><th colspan=8><big>CERTIFICATE MANAGEMENT CONTROL PANEL</big></th></tr> <tr><th colspan=8><big>CERTIFICATE MANAGEMENT CONTROL PANEL</big></th></tr>
<tr><td colspan=8><center> <tr><td colspan=8><center>
<form action="<?="$PHP_SELF?$qstr_sort"?>" method=get name=filter> <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> 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' &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp<input type=checkbox name=show_valid value="V" <?=($show_valid?'checked':'')?>>Valid
:'')?>>Valid
&nbsp&nbsp<input type=checkbox name=show_revoked value="R" <?=($show_revoked?'checked':'')?>>Revoked &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<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;"> &nbsp&nbsp&nbsp&nbsp&nbsp<input type=submit name=submit value="Apply Filter" style="font-size: 11px;">
@@ -364,12 +359,7 @@ default:
$x = "^[$show_valid$show_revoked$show_expired]"; $x = "^[$show_valid$show_revoked$show_expired]";
if (in_array($PHPki_user, $PHPki_admins)) {
$x = "$x.*$search"; $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)); $db = csort(CAdb_to_array($x), $sortfield, ($ascdec=='A'?SORT_ASC:SORT_DESC));

View File

@@ -141,7 +141,7 @@ case 'confirm':
<p><form action='<?=$PHP_SELF?>' method=post> <p><form action='<?=$PHP_SELF?>' method=post>
<?= $hidden_fields ?> <?= $hidden_fields ?>
<input type=hidden name=form_stage value=final> <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='Yes' >&nbsp;
<input type=submit name=submit value='Go Back'> <input type=submit name=submit value='Go Back'>
</form> </form>
@@ -165,7 +165,7 @@ case 'confirm':
break; break;
case 'final': case 'final':
if ($submit == "Yes! Create and Download") { if ($submit == "Yes") {
if (! $serial = CAdb_in($email,$common_name)) { 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); list($ret,$errtxt) = CA_create_cert($cert_type,$country, $province, $locality, $organization, $unit, $common_name, $email, $expiry, $passwd, $keysize);
@@ -194,22 +194,9 @@ case 'final':
$serial = $errtxt; $serial = $errtxt;
} }
} }
# CLear common_name fiels
$common_name = '';
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:
# #
@@ -229,7 +216,7 @@ default:
printHeader(); printHeader();
?> ?>
<body onLoad="self.focus();document.request.common_name.focus()"> <body onLoad="self.focus();document.request.common_name.focus();">
<form action="<?=$PHP_SELF?>" method=post name=request> <form action="<?=$PHP_SELF?>" method=post name=request>
<table width=99%> <table width=99%>
<th colspan=2><h3>Certificate Request Form</h3></th> <th colspan=2><h3>Certificate Request Form</h3></th>
@@ -276,8 +263,10 @@ default:
<td><select name=expiry> <td><select name=expiry>
<? <?
print "<option value=0.25 ". ($expiry == 0.25 ? "selected='selected'" : "") . " >3 Months</option>\n" ;
print "<option value=0.5 ". ($expiry == 0.5 ? "selected='selected'" : "") . " >6 Months</option>\n" ;
print "<option value=1 " . ($expiry == 1 ? "selected='selected'" : "") . " >1 Year</option>\n" ; print "<option value=1 " . ($expiry == 1 ? "selected='selected'" : "") . " >1 Year</option>\n" ;
for ( $i = 2 ; $i < 6 ; $i++ ) { for ( $i = 2 ; $i <= 5 ; $i++ ) {
print "<option value=$i " . ($expiry == $i ? "selected='selected'" : "") . " >$i Years</option>\n" ; print "<option value=$i " . ($expiry == $i ? "selected='selected'" : "") . " >$i Years</option>\n" ;
} }
@@ -290,7 +279,7 @@ default:
<td>Key Size </td> <td>Key Size </td>
<td><select name=keysize> <td><select name=keysize>
<? <?
for ( $i = 512 ; $i < 4096 ; $i+= 512 ) { for ( $i = 512 ; $i <= 4096 ; $i+= 512 ) {
print "<option value=$i " . ($keysize == $i ? "selected='selected'" : "") . " >$i bits</option>\n" ; print "<option value=$i " . ($keysize == $i ? "selected='selected'" : "") . " >$i bits</option>\n" ;
} }

12
root/gen_crl.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
include('../html/config.php');
include(STORE_DIR.'/config/config.php');
include('../html/include/my_functions.php');
include('../html/include/common.php') ;
include('../html/include/openssl_functions.php') ;
CA_generate_crl();
?>

View File

@@ -2,13 +2,12 @@
umask(0007); umask(0007);
if ($HTTP_SERVER_VARS['PHP_AUTH_USER']) if ($HTTP_SERVER_VARS['REMOTE_USER'])
$PHPki_user = md5($HTTP_SERVER_VARS['PHP_AUTH_USER']); $PHPki_user = md5($HTTP_SERVER_VARS['REMOTE_USER']);
else else
$PHPki_user = md5('default'); $PHPki_user = md5('default');
$PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF']; $PHP_SELF = htmlspecialchars($HTTP_SERVER_VARS['PHP_SELF'], ENT_QUOTES, "utf-8");
function printHeader($withmenu="default") { function printHeader($withmenu="default") {
global $config; global $config;

View File

@@ -1,6 +1,6 @@
<?php <?php
$PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF']; $PHP_SELF = htmlspecialchars($HTTP_SERVER_VARS['PHP_SELF'], ENT_QUOTES, "utf-8");
# #
# Returns TRUE if browser is Internet Explorer. # Returns TRUE if browser is Internet Explorer.
@@ -74,11 +74,23 @@ function gpvar($v) {
# Sort a two multidimensional array by one of it's columns # Sort a two multidimensional array by one of it's columns
# #
function csort($array, $column, $ascdec=SORT_ASC){ function csort($array, $column, $ascdec=SORT_ASC){
if (sizeof($array) == 0) return $array; if (sizeof($array) == 0) return $array;
// Sort by digital date rather than text date
if ($column == 'issued') $column = "issuedSort";
if ($column == 'expires') $column = 'expiresSort';
if ($column == 'status') {
foreach($array as $x) {
$sortarr[]=$x[$column];
$sortdate[] = $x['expiresSort'];
}
array_multisort($sortarr, $ascdec, $sortdate, SORT_ASC, $array);
} else {
foreach($array as $x) $sortarr[]=$x[$column]; foreach($array as $x) $sortarr[]=$x[$column];
array_multisort($sortarr, $ascdec, $array); array_multisort($sortarr, $ascdec, $array);
}
return $array; return $array;
} }
@@ -160,42 +172,53 @@ function undo_magic_quotes(&$a) {
# Returns TRUE if argument contains only alphabetic characters. # Returns TRUE if argument contains only alphabetic characters.
# #
function is_alpha($v) { function is_alpha($v) {
return (eregi('[^A-Z]',$v) ? false : true) ; #return (eregi('[^A-Z]',$v) ? false : true) ;
#return (preg_match('/[^A-Z]'.'/i',$v,PCRE_CASELESS) ? false : true) ; # Replaced eregi() with preg_match()
return (preg_match('/[^A-Z]/i',$v) ? false : true) ;
} }
# #
# Returns TRUE if argument contains only numeric characters. # Returns TRUE if argument contains only numeric characters.
# #
function is_num($v) { function is_num($v) {
return (eregi('[^0-9]',$v) ? false : true) ; #return (eregi('[^0-9]',$v) ? false : true) ;
return (preg_match('/[^0-9]/',$v) ? false : true) ; # Replaced eregi() with preg_match()
} }
# #
# Returns TRUE if argument contains only alphanumeric characters. # Returns TRUE if argument contains only alphanumeric characters.
# #
function is_alnum($v) { function is_alnum($v) {
return (eregi('[^A-Z0-9]',$v) ? false : true) ; #return (eregi('[^A-Z0-9]',$v) ? false : true) ;
return (preg_match('/[^A-Z0-9]/i',$v) ? false : true) ; # Replaced eregi() with preg_match()
} }
# #
# Returns TRUE if argument is in proper e-mail address format. # Returns TRUE if argument is in proper e-mail address format.
# #
function is_email($v) { function is_email($v) {
return (eregi('^[^@ ]+\@[^@ ]+\.[A-Z]{2,3}$',$v) ? true : false); #return (eregi('^[^@ ]+\@[^@ ]+\.[A-Z]{2,4}$',$v) ? true : false);
return (preg_match('/^[^@ ]+\@[^@ ]+\.[A-Z]{2,4}$'.'/i',$v) ? true : false); # Replaced eregi() with preg_match()
} }
# #
# Checks regexp in every element of an array, returns TRUE as soon # Checks regexp in every element of an array, returns TRUE as soon
# as a match is found. # as a match is found.
# #
function eregi_array($regexp, $a) {
foreach($a as $e) { function eregi_array($regexp, $arr) {
if (eregi($regexp,$e)) return true;
foreach ($arr as $elem) {
#if (eregi($regexp,$elem))
if (! preg_match('/^\/.*\/$/', $regexp)) # if it doesn't begin and end with '/'
$regexp = '/'.$regexp.'/'; # pad the $regexp with '/' to prepare for preg_match()
if (preg_match($regexp.'i',$elem)) # Replaced eregi() with preg_match()
return true;
} }
return false; return false;
} }
# #
# Reads entire file into a string # Reads entire file into a string
# Same as file_get_contents in php >= 4.3.0 # Same as file_get_contents in php >= 4.3.0

View File

@@ -27,7 +27,7 @@ crl_extentions = crl_ext
default_days = 365 default_days = 365
default_crl_days = 30 default_crl_days = 30
preserve = no preserve = no
default_md = md5 default_md = sha1
[ req ] [ req ]
default_bits = $keysize default_bits = $keysize
@@ -59,8 +59,8 @@ x509_extensions = email_ext
default_days = 365 default_days = 365
policy = policy_supplied policy = policy_supplied
[ email_codesigning_cert ] [ email_signing_cert ]
x509_extensions = email_codesigning_ext x509_extensions = email_signing_ext
default_days = 365 default_days = 365
policy = policy_supplied policy = policy_supplied
@@ -122,7 +122,7 @@ nsBaseUrl = $config[base_url]
nsRevocationUrl = ns_revoke_query.php? nsRevocationUrl = ns_revoke_query.php?
nsCaPolicyUrl = $config[base_url]policy.html nsCaPolicyUrl = $config[base_url]policy.html
[ email_codesigning_ext ] [ email_signing_ext ]
basicConstraints = critical, CA:false basicConstraints = critical, CA:false
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, emailProtection, clientAuth, codeSigning extendedKeyUsage = critical, emailProtection, clientAuth, codeSigning
@@ -194,7 +194,7 @@ subjectAltName = DNS:$common_name,email:copy
"; ";
# Write out the config file. # Write out the config file.
$cnf_file = tempnam('./tmp','cnf-'); $cnf_file = tempnam('../../tmp','cnf-');
$handle = fopen($cnf_file,"w"); $handle = fopen($cnf_file,"w");
fwrite($handle, $cnf_contents); fwrite($handle, $cnf_contents);
fclose($handle); fclose($handle);
@@ -212,18 +212,22 @@ function CAdb_to_array($search = '.*') {
global $config; global $config;
# Prepend a default status to search string if missing. # Prepend a default status to search string if missing.
if (! ereg('^\^\[.*\]', $search)) $search = '^[VRE].*'.$search; #if (! ereg('^\^\[.*\]', $search)) $search = '^[VRE].*'.$search;
if (! preg_match("/^\^\[.*\]/", $search)) $search = '^[VRE].*'.$search;
# Include valid certs? # Include valid certs?
if (ereg('^\^\[.*V.*\]',$search)) $inclval = true; #if (ereg('^\^\[.*V.*\]',$search)) $inclval = true;
if (preg_match('/^\^\[.*V.*\]/',$search)) $inclval = true;
# Include revoked certs? # Include revoked certs?
if (ereg('^\^\[.*R.*\]',$search)) $inclrev = true; #if (ereg('^\^\[.*R.*\]',$search)) $inclrev = true;
if (preg_match('/^\^\[.*R.*\]/',$search)) $inclrev = true;
# Include expired certs? # Include expired certs?
if (ereg('^\^\[.*E.*\]',$search)) $inclexp = true; #if (ereg('^\^\[.*E.*\]',$search)) $inclexp = true;
if (preg_match('/^\^\[.*E.*\]/',$search)) $inclexp = true;
# There isn't really a status of 'E' in the openssl index. # There isn't really a status of 'E' in the openssl index.
# Change (E)xpired to (V)alid within the search string. # Change (E)xpired to (V)alid within the search string.
$search = ereg_replace('^(\^\[.*)E(.*\])','\\1V\\2',$search); #$search = ereg_replace('^(\^\[.*)E(.*\])','\\1V\\2',$search);
$search = preg_replace('/^(\^\[.*)E(.*\])/','${1}V${2}',$search);
$db = array(); $db = array();
exec('egrep -i '.escshellarg($search).' '.$config['index'], $x); exec('egrep -i '.escshellarg($search).' '.$config['index'], $x);
@@ -315,15 +319,49 @@ function CAdb_explode_entry($dbentry) {
break; break;
} }
// CA_cert_start/enddate
// A date will be returned in this format
// Feb 27 16:00:09 2020 GMT
// Add a 'digital' sort key for digital date sorting later
sscanf(CA_cert_startdate($a[3]),"%s%s%s%s", $mm,$dd,$tt,$yy); sscanf(CA_cert_startdate($a[3]),"%s%s%s%s", $mm,$dd,$tt,$yy);
$db['issued'] = strftime("%y-%b-%d", strtotime("$dd $mm $yy")); $db['issued'] = strftime("%Y-%b-%d", strtotime("$yy-$mm-$dd"));
$db['issuedSort'] = strftime("%Y-%m-%d", strtotime("$yy-$mm-$dd"));
sscanf($a[1], "%2s%2s%2s",$yy,$mm,$dd); sscanf(CA_cert_enddate($a[3]), "%s%s%s%s",$mm,$dd,$tt,$yy);
$db['expires'] = strftime("%y-%b-%d", strtotime("$mm/$dd/$yy")); $db['expires'] = strftime("%Y-%b-%d", strtotime("$yy-$mm-$dd"));
$db['expiresSort'] = strftime("%Y-%m-%d", strtotime("$yy-$mm-$dd"));
if (time() > strtotime("$mm/$dd/$yy")) if (time() > strtotime("$yy-$mm-$dd")) {
$db['status'] = "Expired"; $db['status'] = "Expired";
}
// Compatibility with migrated certs from openvpn-bridge
if(count($b) == 7){
$db['serial'] = $a[3];
$db['country'] = $b[1];
$db['province'] = $b[2];
$db['locality'] = '';
$db['organization'] = $b[3];
$db['issuer'] = '';
$db['unit'] = $b[4];
$db['common_name'] = $b[5];
$db['email'] = $b[6];
}
// Compatibility with renewed certs from openvpn-bridge
elseif(count($b) == 8){
$db['serial'] = $a[3];
$db['country'] = $b[1];
$db['province'] = $b[2];
$db['locality'] = $b[3];
$db['organization'] = $b[4];
$db['issuer'] = '';
$db['unit'] = $b[5];
$db['common_name'] = $b[6];
$db['email'] = $b[7];
}
// Else, it's a certificate created with phpki
else{
$db['serial'] = $a[3]; $db['serial'] = $a[3];
$db['country'] = $b[1]; $db['country'] = $b[1];
$db['province'] = $b[2]; $db['province'] = $b[2];
@@ -333,6 +371,7 @@ function CAdb_explode_entry($dbentry) {
$db['unit'] = $b[6]; $db['unit'] = $b[6];
$db['common_name'] = $b[7]; $db['common_name'] = $b[7];
$db['email'] = $b[8]; $db['email'] = $b[8];
}
return $db; return $db;
} }
@@ -349,7 +388,7 @@ function CAdb_is_revoked($serial) {
if ($x) { if ($x) {
list($j,$j,$revoke_date,$j,$j,$j) = explode("\t", $x); list($j,$j,$revoke_date,$j,$j,$j) = explode("\t", $x);
sscanf($revoke_date, "%2s%2s%2s",$yy,$mm,$dd); sscanf($revoke_date, "%2s%2s%2s",$yy,$mm,$dd);
return strftime("%b %d, %Y", strtotime("$mm/$dd/$yy")); return strftime("%b %d, %Y", strtotime("$yy-$mm-$dd"));
} }
else else
return false; return false;
@@ -388,6 +427,24 @@ function CA_crl_text() {
return(shell_exec(CRL.' -in '.escshellarg($crlfile).' -text 2>&1')); return(shell_exec(CRL.' -in '.escshellarg($crlfile).' -text 2>&1'));
} }
// Returns the static takey.pem file
function ta_key_text() {
global $config;
return(shell_exec('cat '.escshellarg($config['private_dir']).'/takey.pem 2>&1'));
}
// Returns the dhparam file
function dhparam_text() {
global $config;
return(shell_exec('cat '.escshellarg($config['private_dir']).'/dhparam1024.pem 2>&1'));
}
// Returns the root CA certificate file (PEM Encoded)
function root_pem_text() {
global $config;
return(shell_exec('cat '.escshellarg($config['cacert_pem']).' 2>&1'));
}
// //
// Returns the subject of a certificate. // Returns the subject of a certificate.
// //
@@ -403,7 +460,9 @@ function CA_cert_subject($serial) {
// //
function CA_cert_cname($serial) { function CA_cert_cname($serial) {
global $config; global $config;
return(ereg_replace('^.*/CN=(.*)/.*','\\1',CA_cert_subject($serial))); #return(ereg_replace('^.*/CN=(.*)/.*','\\1',CA_cert_subject($serial)));
return(preg_replace('/^.*\/CN=(.*)\/.*/','${1}',CA_cert_subject($serial)));
} }
// //
@@ -497,7 +556,7 @@ function CA_create_cert($cert_type='email',$country,$province,$locality,$organiz
unset($cmd_output); unset($cmd_output);
$cmd_output[] = 'Creating certifcate request.'; $cmd_output[] = 'Creating certifcate request.';
if ($passwd) { if (($passwd) && ($passwd != "''")) {
exec(REQ." -new -newkey rsa:$keysize -keyout '$userkey' -out '$userreq' -config '$cnf_file' -days '$expiry_days' -passout pass:$passwd 2>&1", $cmd_output, $ret); exec(REQ." -new -newkey rsa:$keysize -keyout '$userkey' -out '$userreq' -config '$cnf_file' -days '$expiry_days' -passout pass:$passwd 2>&1", $cmd_output, $ret);
} }
else { else {
@@ -665,6 +724,14 @@ function CA_renew_cert($old_serial,$expiry,$passwd) {
#Unlock the CA database #Unlock the CA database
fclose($fd); fclose($fd);
# https://github.com/radicand/phpki/issues/14
if (preg_match('E-mail Protection', $certtext) && preg_match('Code Signing', $certtest)) {
$cert_type = 'email_signing';
}
if (preg_match('E-mail Protection', $certtext)) {
$cert_type = 'email';
}
#Remove temporary openssl config file. #Remove temporary openssl config file.
if (file_exists($cnf_file)) unlink($cnf_file); if (file_exists($cnf_file)) unlink($cnf_file);
@@ -748,25 +815,32 @@ function CA_cert_type($serial) {
$certtext = CA_cert_text($serial); $certtext = CA_cert_text($serial);
if (ereg('OpenSSL.* (E.?mail|Personal) .*Certificate', $certtext) && ereg('Code Signing', $certtest)) { #if (ereg('OpenSSL.* (E.?mail|Personal) .*Certificate', $certtext) && ereg('Code Signing', $certtest)) {
if (preg_match('~OpenSSL.* (E.?mail|Personal) .*Certificate~', $certtext) && preg_match('~Code Signing~', $certtest)) {
$cert_type = 'email_codesigning'; $cert_type = 'email_codesigning';
} }
if (ereg('OpenSSL.* (E.?mail|Personal) .*Certificate', $certtext)) { #if (ereg('OpenSSL.* (E.?mail|Personal) .*Certificate', $certtext)) {
if (preg_match('~OpenSSL.* (E.?mail|Personal) .*Certificate~', $certtext)) {
$cert_type = 'email'; $cert_type = 'email';
} }
elseif (ereg('OpenSSL.* Server .*Certificate', $certtext)) { #elseif (ereg('OpenSSL.* Server .*Certificate', $certtext)) {
elseif (preg_match('~OpenSSL.* Server .*Certificate~', $certtext)) {
$cert_type = 'server'; $cert_type = 'server';
} }
elseif (ereg('timeStamping|Time Stamping', $certtext)) { #elseif (ereg('timeStamping|Time Stamping', $certtext)) {
elseif (preg_match('~timeStamping|Time Stamping~', $certtext)) {
$cert_type = 'time_stamping'; $cert_type = 'time_stamping';
} }
elseif (ereg('TLS Web Client Authentication', $certtext) && ereg('TLS Web Server Authentication', $certtext)) { #elseif (ereg('TLS Web Client Authentication', $certtext) && ereg('TLS Web Server Authentication', $certtext)) {
elseif (preg_match('~TLS Web Client Authentication~', $certtext) && preg_match('~TLS Web Server Authentication~', $certtext)) {
$cert_type = 'vpn_client_server'; $cert_type = 'vpn_client_server';
} }
elseif (ereg('TLS Web Client Authentication', $certtext)) { #elseif (ereg('TLS Web Client Authentication', $certtext)) {
elseif (preg_match('~TLS Web Client Authentication~', $certtext)) {
$cert_type = 'vpn_client'; $cert_type = 'vpn_client';
} }
elseif (ereg('TLS Web Server Authentication', $certtext)) { #elseif (ereg('TLS Web Server Authentication', $certtext)) {
elseif (preg_match('~TLS Web Server Authentication~', $certtext)) {
$cert_type = 'vpn_server'; $cert_type = 'vpn_server';
} }
else { else {

View File

@@ -17,6 +17,10 @@ case 'dl_crl':
upload("$config[cacrl_der]", "$config[ca_prefix]cacrl.crl", 'application/pkix-crl'); upload("$config[cacrl_der]", "$config[ca_prefix]cacrl.crl", 'application/pkix-crl');
break; break;
case 'dl_crl_pem':
upload("$config[cacrl_pem]", "$config[ca_prefix]cacrl.crl", 'application/octet-stream');
break;
default: default:
printHeader('public'); printHeader('public');
@@ -39,7 +43,8 @@ default:
<tr><td style="text-align: center; vertical-align: middle; font-weight: bold;"> <tr><td style="text-align: center; vertical-align: middle; font-weight: bold;">
<a href=<?=$PHP_SELF?>?stage=dl_crl>Download Our Certificate Revocation List</a></td> <a href=<?=$PHP_SELF?>?stage=dl_crl>Download Our Certificate Revocation List</a></td>
<td>The official list of certificates revoked by this site. Installation and use of <td>The official list of certificates revoked by this site. Installation and use of
this list is optional. Some e-mail programs will reference this list automagically. </td></tr> this list is optional. Some e-mail programs will reference this list automagically.
(<a href="<?=$PHP_SELF?>?stage=dl_crl_pem">Some will need it in PEM format.</a>)</td></tr>
</table> </table>
</center> </center>

View File

@@ -14,7 +14,7 @@ crl_extensions = crl_ext
default_days = 365 default_days = 365
default_crl_days = 30 default_crl_days = 30
preserve = no preserve = no
default_md = md5 default_md = sha1
[ ca ] [ ca ]
default_ca = email_cert default_ca = email_cert
@@ -29,8 +29,8 @@ x509_extensions = email_ext
default_days = 365 default_days = 365
policy = policy_supplied policy = policy_supplied
[ email_codesigning_cert ] [ email_signing_cert ]
x509_extensions = email_codesigning_ext x509_extensions = email_signing_ext
default_days = 365 default_days = 365
policy = policy_supplied policy = policy_supplied
@@ -82,7 +82,7 @@ nsRevocationUrl = ns_revoke_query.php?
nsCaPolicyUrl = http://www.somewhere.com/phpki/policy.html nsCaPolicyUrl = http://www.somewhere.com/phpki/policy.html
#nsSslServerName = #nsSslServerName =
[ email_codesigning_ext ] [ email_signing_ext ]
basicConstraints = critical, CA:false basicConstraints = critical, CA:false
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = critical, emailProtection, clientAuth, codeSigning extendedKeyUsage = critical, emailProtection, clientAuth, codeSigning

View File

@@ -36,7 +36,12 @@ case display:
case 'download': case 'download':
$rec = CAdb_get_entry($serial); $rec = CAdb_get_entry($serial);
upload("$config[cert_dir]/$serial.der", "$rec[common_name] ($rec[email]).cer", 'application/pkix-cert'); upload("$config[cert_dir]/$serial.der", "$rec[common_name].cer", 'application/pkix-cert');
break;
case 'download_pem':
$rec = CAdb_get_entry($serial);
upload("$config[new_certs_dir]/$serial.pem", "$rec[common_name].pem", 'application/pkix-cert');
break; break;
case search: case search:
@@ -44,7 +49,7 @@ case search:
$db = CAdb_to_array("^[${show_valid}${show_revoked}${show_expired}].*$search"); $db = CAdb_to_array("^[${show_valid}${show_revoked}${show_expired}].*$search");
print '<body onLoad="self.focus();document.form.submit.focus()">'; print '<body onLoad="self.focus();document.form.submit.focus();">';
if (sizeof($db) == 0) { if (sizeof($db) == 0) {
?> ?>
<center> <center>
@@ -97,6 +102,7 @@ case search:
if ($rec['status'] != 'Revoked') { if ($rec['status'] != 'Revoked') {
?> ?>
<a href=<?=$PHP_SELF?>?stage=download&serial=<?=htvar($rec['serial'])?>><img src=images/download.png alt="Download" title="Download the certificate so that you may send encrypted e-mail"></a> <a href=<?=$PHP_SELF?>?stage=download&serial=<?=htvar($rec['serial'])?>><img src=images/download.png alt="Download" title="Download the certificate so that you may send encrypted e-mail"></a>
<a href=<?=$PHP_SELF?>?stage=download_pem&serial=<?=htvar($rec['serial'])?>><img src=images/download.png alt="Download (in PEM format)" title="Download in PEM format"></a>
<? <?
} }
print '</td></tr>'; print '</td></tr>';
@@ -121,7 +127,7 @@ default:
printHeader('public'); printHeader('public');
?> ?>
<body onLoad="self.focus();document.search.search.focus()"> <body onLoad="self.focus();document.search.search.focus();">
<center><h2>Certificate Search</h2> <center><h2>Certificate Search</h2>
<form action=<?=$PHP_SELF?> method=post name=search> <form action=<?=$PHP_SELF?> method=post name=search>
<input type=text name=search value="<?=htvar($search)?>" maxlength=60 size=40> <input type=text name=search value="<?=htvar($search)?>" maxlength=60 size=40>

View File

@@ -102,6 +102,11 @@ case 'validate':
if (! $passwd_file) $er .= 'Missing User Password File Location'; if (! $passwd_file) $er .= 'Missing User Password File Location';
if (! $store_dir) $er .= 'Missing Storage Directory<br>'; if (! $store_dir) $er .= 'Missing Storage Directory<br>';
$countrycode = strtoupper($country);
if (! preg_match("/\b[A-Z][A-Z]\b/", $countrycode, $match) ) {
$er .= 'Country Code must be ISO 3166 two letters <br>';
}
if ( $passwd && strlen($passwd) < 8 ) if ( $passwd && strlen($passwd) < 8 )
$er .= 'Certificate password is too short.<br>'; $er .= 'Certificate password is too short.<br>';
@@ -248,7 +253,7 @@ case 'write':
# Default OpenSSL Config File. # Default OpenSSL Config File.
\$config['openssl_cnf'] = \$config['home_dir'] . '/config/openssl.cnf'; \$config['openssl_cnf'] = \$config['home_dir'] . '/config/openssl.cnf';
\$PHPki_admins = Array(md5('pkiadmin')); \$PHPki_admins = Array(md5('admin'));
define('OPENSSL',\$config['openssl_bin'].' '); define('OPENSSL',\$config['openssl_bin'].' ');
define('X509', OPENSSL . ' x509 '); define('X509', OPENSSL . ' x509 ');
@@ -314,7 +319,7 @@ crl_extensions = crl_ext
default_days = 365 default_days = 365
default_crl_days = 30 default_crl_days = 30
preserve = no preserve = no
default_md = md5 default_md = sha1
[ ca ] [ ca ]
default_ca = email_cert default_ca = email_cert
@@ -604,6 +609,17 @@ EOS;
flush(); flush();
flush_exec($cmd,100); flush_exec($cmd,100);
#
# Create a TLS auth key for OpenVPN.
#
print '<p><strong>Creating a TLS authentication key used by OpenVPN.<br>';
print "Saving to $store_dir/takey.pem.</strong><br>";
$cmd = "openvpn --genkey --secret '$config[private_dir]/takey.pem'";
print $cmd.'<br>';
flush();
flush_exec($cmd);
#print '<p><strong>Creating 2048 bit Diffie-Hellman parameters used by OpenVPN.<br>'; #print '<p><strong>Creating 2048 bit Diffie-Hellman parameters used by OpenVPN.<br>';
#print "Saving to $store_dir/dhparam2048.pem.</strong><br>"; #print "Saving to $store_dir/dhparam2048.pem.</strong><br>";
@@ -624,7 +640,6 @@ EOS;
?> ?>
<center> <center>
<h2>Setup is complete. Your CA root certificate as been created.</h2> <h2>Setup is complete. Your CA root certificate as been created.</h2>
<h3><font color=red>SECURITY WARNING!&nbsp;&nbsp; Be sure to run the <cite>secure.sh</cite> shell script as the <strong>root</strong> user.</font></h3>
<p><br><br> <p><br><br>
<form action=index.php> <form action=index.php>
<input type=submit name=submit value="Proceed To The PHPki Main Menu"> <input type=submit name=submit value="Proceed To The PHPki Main Menu">
@@ -752,9 +767,8 @@ E-mail: <a href=mailto:someone@somewhere.com>someone@somewhere.com</a>&nbsp;&nbs
<td><select name=expiry> <td><select name=expiry>
<? <?
for ( $i = 5 ; $i < 20 ; $i+=5 ) { for ( $i = 5 ; $i <= 20 ; $i+=5 ) {
print "<option value=$i " . ($expiry == $i ? "selected='selected print "<option value=$i " . ($expiry == $i ? "selected='selected'" : "") . " >$i Years</option>\n" ;
'" : "") . " >$i Years</option>\n" ;
} }
?> ?>
@@ -770,8 +784,7 @@ E-mail: <a href=mailto:someone@somewhere.com>someone@somewhere.com</a>&nbsp;&nbs
<? <?
for ( $i = 512 ; $i <= 4096 ; $i+=512 ) { for ( $i = 512 ; $i <= 4096 ; $i+=512 ) {
print "<option value=$i " . ($keysize == $i ? "selected='selected print "<option value=$i " . ($keysize == $i ? "selected='selected'" : "") . " >$i bits</option>\n" ;
'" : "") . " >$i bits</option>\n" ;
} }
?> ?>