You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
4.6 KiB
152 lines
4.6 KiB
2 years ago
|
<?php
|
||
|
|
||
|
/**
|
||
|
* library/create_ssl_certificate.php
|
||
|
*
|
||
|
* @package OpenEMR
|
||
|
* @link https://www.open-emr.org
|
||
|
* @author visolve <vicareplus_engg@visolve.com>
|
||
|
* @author Brady Miller <brady.g.miller@gmail.com>
|
||
|
* @author Jerry Padgett <sjpadgett@gmail.com>
|
||
|
* @copyright Copyright (c) visolve <vicareplus_engg@visolve.com>
|
||
|
* @copyright Copyright (c) 2020 Brady Miller <brady.g.miller@gmail.com>
|
||
|
* @copyright Copyright (c) 2020 Jerry Padgett <sjpadgett@gmail.com>
|
||
|
* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
|
||
|
*/
|
||
|
|
||
|
/* This file contains routines for creating SSL certificates */
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Create a Certificate Signing Request (CSR) with the given values
|
||
|
* @param $commonName - The username/hostname
|
||
|
* @param $emailAddress - The email of the username
|
||
|
* @param $countryName - Two letter country code, like "US"
|
||
|
* @param $stateOrProvinceName - State name
|
||
|
* @param $localityName - City name
|
||
|
* @param $organizationName - Organization Name
|
||
|
* @param $organizationalUnitName - Organization Unit Name
|
||
|
* @return array [ CSR data, privatekey ], or 'false' on error.
|
||
|
*/
|
||
|
function create_csr(
|
||
|
$commonName,
|
||
|
$emailAddress,
|
||
|
$countryName,
|
||
|
$stateOrProvinceName,
|
||
|
$localityName,
|
||
|
$organizationName,
|
||
|
$organizationalUnitName
|
||
|
) {
|
||
|
|
||
|
if ($commonName == "") {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Build the Distinguished Name (DN) for the certificate */
|
||
|
$dn = array("commonName" => $commonName);
|
||
|
|
||
|
if ($emailAddress) {
|
||
|
$dn = array_merge($dn, array("emailAddress" => $emailAddress));
|
||
|
}
|
||
|
|
||
|
if ($countryName) {
|
||
|
$dn = array_merge($dn, array("countryName" => $countryName));
|
||
|
}
|
||
|
|
||
|
if ($stateOrProvinceName) {
|
||
|
$dn = array_merge($dn, array("stateOrProvinceName" => $stateOrProvinceName));
|
||
|
}
|
||
|
|
||
|
if ($localityName) {
|
||
|
$dn = array_merge($dn, array("localityName" => $localityName));
|
||
|
}
|
||
|
|
||
|
if ($organizationName) {
|
||
|
$dn = array_merge($dn, array("organizationName" => $organizationName));
|
||
|
}
|
||
|
|
||
|
if ($organizationalUnitName) {
|
||
|
$dn = array_merge($dn, array("organizationalUnitName" => $organizationalUnitName));
|
||
|
}
|
||
|
|
||
|
/* Create the public/private key pair */
|
||
|
$privkey = openssl_pkey_new();
|
||
|
if ($privkey === false) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$csr = openssl_csr_new($dn, $privkey);
|
||
|
if ($csr === false) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return array($csr, $privkey);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Create a certificate, signed by the given Certificate Authority.
|
||
|
* @param $csr - The certificate signing request
|
||
|
* @param $cacert - The Certificate Authority to sign with, or NULL if not used.
|
||
|
* @param $cakey - The Certificate Authority private key data to sign with.
|
||
|
* @return data - A signed certificate, or false on error.
|
||
|
*/
|
||
|
function create_crt($csr, $cacert, $cakey)
|
||
|
{
|
||
|
$cert = openssl_csr_sign($csr, $cacert, $cakey, 3650, ['digest_alg' => 'sha256'], rand(1000, 9999));
|
||
|
return $cert;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Create a new client certificate for a username or client hostname.
|
||
|
* @param $commonName - The username or hostname
|
||
|
* @param $emailAddress - The user's email address
|
||
|
* @param $serial - The serial number
|
||
|
* @param $cacert - Path to Certificate Authority cert file.
|
||
|
* @param $cakey - Path to Certificate Authority key file.
|
||
|
* @param $valid_days - validity in number of days for the user certificate
|
||
|
* @return string - The client certificate signed by the Certificate Authority, or false on error.
|
||
|
*/
|
||
|
function create_user_certificate($commonName, $emailAddress, $serial, $cacert, $cakey, $valid_days)
|
||
|
{
|
||
|
/* Generate a certificate signing request */
|
||
|
$arr = create_csr($commonName, $emailAddress, "", "", "", "", "");
|
||
|
if ($arr === false) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$csr = $arr[0];
|
||
|
$privkey = $arr[1];
|
||
|
|
||
|
/* user id is used as serial number to sign a certificate */
|
||
|
$serial = (is_int($serial)) ? $serial : 0;
|
||
|
$res = sqlStatement("SELECT id FROM users WHERE username = ?", array($commonName));
|
||
|
if ($row = sqlFetchArray($res)) {
|
||
|
$serial = $row['id'];
|
||
|
}
|
||
|
|
||
|
$cert = openssl_csr_sign(
|
||
|
$csr,
|
||
|
file_get_contents($cacert),
|
||
|
file_get_contents($cakey),
|
||
|
$valid_days,
|
||
|
['digest_alg' => 'sha256'],
|
||
|
$serial
|
||
|
);
|
||
|
|
||
|
if ($cert === false) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Convert the user certificate to .p12 (PKCS 12) format, which is the
|
||
|
* standard format used by browsers.
|
||
|
*/
|
||
|
$clientPassPhrase = trim($_POST['clientPassPhrase']);
|
||
|
if (openssl_pkcs12_export($cert, $p12Out, $privkey, $clientPassPhrase) === false) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return $p12Out;
|
||
|
}
|