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

<?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;
}