This repository has been archived by the owner on Mar 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Fixed 415 Unsupported Media Type error caused by ACME protocol divergence. - Fixed certificate revocation problem addressed in issue #25. - Set default acmeURL to the production environment. - Implemented option to bypass local DNS/HTTP verification verifyPendingOrderAuthorization($identifier, $type, $localcheck = true). It is still making a local verification by default. Documentation is to be updated.
- Loading branch information
Showing
7 changed files
with
36 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,7 +39,7 @@ | |
* @author Youri van Weegberg <[email protected]> | ||
* @copyright 2018 Youri van Weegberg | ||
* @license https://opensource.org/licenses/mit-license.php MIT License | ||
* @version 1.1.0 | ||
* @version 1.1.1 | ||
* @link https://github.com/yourivw/LEClient | ||
* @since Class available since Release 1.0.0 | ||
*/ | ||
|
@@ -67,11 +67,11 @@ class LEClient | |
* @param boolean $acmeURL ACME URL, can be string or one of predefined values: LE_STAGING or LE_PRODUCTION. Defaults to LE_STAGING. | ||
* @param int $log The level of logging. Defaults to no logging. LOG_OFF, LOG_STATUS, LOG_DEBUG accepted. Defaults to LOG_OFF. (optional) | ||
* @param string $certificateKeys The main directory in which all keys (and certificates), including account keys, are stored. Defaults to 'keys/'. (optional) | ||
* @param array $certificateKeys Optional array containing location of all certificate files. Required paths are public_key, private_key, order and certificate/fullchain_certificate (you can use both or only one of them) | ||
* @param array $certificateKeys Optional array containing location of all certificate files. Required paths are public_key, private_key, order and certificate/fullchain_certificate (you can use both or only one of them) | ||
* @param string $accountKeys The directory in which the account keys are stored. Is a subdir inside $certificateKeys. Defaults to '__account/'.(optional) | ||
* @param array $accountKeys Optional array containing location of account private and public keys. Required paths are private_key, public_key. | ||
* @param array $accountKeys Optional array containing location of account private and public keys. Required paths are private_key, public_key. | ||
*/ | ||
public function __construct($email, $acmeURL = LEClient::LE_STAGING, $log = LEClient::LOG_OFF, $certificateKeys = 'keys/', $accountKeys = '__account/') | ||
public function __construct($email, $acmeURL = LEClient::LE_PRODUCTION, $log = LEClient::LOG_OFF, $certificateKeys = 'keys/', $accountKeys = '__account/') | ||
{ | ||
|
||
$this->log = $log; | ||
|
@@ -85,14 +85,13 @@ public function __construct($email, $acmeURL = LEClient::LE_STAGING, $log = LECl | |
{ | ||
$this->baseURL = $acmeURL; | ||
} | ||
else throw new \RuntimeException('acmeURL must be set to string or bool (legacy)'); | ||
else throw new \RuntimeException('acmeURL must be set to string or bool (legacy).'); | ||
|
||
if (is_array($certificateKeys) && is_string($accountKeys)) throw new \RuntimeException('when certificateKeys is array, accountKeys must be array also'); | ||
elseif (is_array($accountKeys) && is_string($certificateKeys)) throw new \RuntimeException('when accountKeys is array, certificateKeys must be array also'); | ||
if (is_array($certificateKeys) && is_string($accountKeys)) throw new \RuntimeException('When certificateKeys is array, accountKeys must be array too.'); | ||
elseif (is_array($accountKeys) && is_string($certificateKeys)) throw new \RuntimeException('When accountKeys is array, certificateKeys must be array too.'); | ||
|
||
if (is_string($certificateKeys)) | ||
{ | ||
|
||
$certificateKeysDir = $certificateKeys; | ||
|
||
if(!file_exists($certificateKeys)) | ||
|
@@ -108,32 +107,28 @@ public function __construct($email, $acmeURL = LEClient::LE_STAGING, $log = LECl | |
"fullchain_certificate" => $certificateKeys.'/fullchain.crt', | ||
"order" => $certificateKeys.'/order' | ||
); | ||
|
||
} | ||
elseif (is_array($certificateKeys)) | ||
{ | ||
|
||
if (!isset($certificateKeys['certificate']) && !isset($certificateKeys['fullchain_certificate'])) throw new \RuntimeException('certificateKeys[certificate] or certificateKeys[fullchain_certificate] file path must be set'); | ||
if (!isset($certificateKeys['private_key'])) throw new \RuntimeException('certificateKeys[private_key] file path must be set'); | ||
if (!isset($certificateKeys['certificate']) && !isset($certificateKeys['fullchain_certificate'])) throw new \RuntimeException('certificateKeys[certificate] or certificateKeys[fullchain_certificate] file path must be set.'); | ||
if (!isset($certificateKeys['private_key'])) throw new \RuntimeException('certificateKeys[private_key] file path must be set.'); | ||
if (!isset($certificateKeys['order'])) $certificateKeys['order'] = dirname($certificateKeys['private_key']).'/order'; | ||
if (!isset($certificateKeys['public_key'])) $certificateKeys['public_key'] = dirname($certificateKeys['private_key']).'/public.pem'; | ||
|
||
foreach ($certificateKeys as $param => $file) { | ||
$parentDir = dirname($file); | ||
if (!is_dir($parentDir)) throw new \RuntimeException($parentDir.' directory not found'); | ||
if (!is_dir($parentDir)) throw new \RuntimeException($parentDir.' directory not found.'); | ||
} | ||
|
||
$this->certificateKeys = $certificateKeys; | ||
|
||
} | ||
else | ||
{ | ||
throw new \RuntimeException('certificateKeys must be string or array'); | ||
throw new \RuntimeException('certificateKeys must be string or array.'); | ||
} | ||
|
||
if (is_string($accountKeys)) | ||
{ | ||
|
||
$accountKeys = $certificateKeysDir.'/'.$accountKeys; | ||
|
||
if(!file_exists($accountKeys)) | ||
|
@@ -149,12 +144,12 @@ public function __construct($email, $acmeURL = LEClient::LE_STAGING, $log = LECl | |
} | ||
elseif (is_array($accountKeys)) | ||
{ | ||
if (!isset($accountKeys['private_key'])) throw new \RuntimeException('accountKeys[private_key] file path must be set'); | ||
if (!isset($accountKeys['public_key'])) throw new \RuntimeException('accountKeys[public_key] file path must be set'); | ||
if (!isset($accountKeys['private_key'])) throw new \RuntimeException('accountKeys[private_key] file path must be set.'); | ||
if (!isset($accountKeys['public_key'])) throw new \RuntimeException('accountKeys[public_key] file path must be set.'); | ||
|
||
foreach ($accountKeys as $param => $file) { | ||
$parentDir = dirname($file); | ||
if (!is_dir($parentDir)) throw new \RuntimeException($parentDir.' directory not found'); | ||
if (!is_dir($parentDir)) throw new \RuntimeException($parentDir.' directory not found.'); | ||
} | ||
|
||
$this->accountKeys = $accountKeys; | ||
|
@@ -167,7 +162,7 @@ public function __construct($email, $acmeURL = LEClient::LE_STAGING, $log = LECl | |
|
||
$this->connector = new LEConnector($this->log, $this->baseURL, $this->accountKeys); | ||
$this->account = new LEAccount($this->connector, $this->log, $email, $this->accountKeys); | ||
if($this->log) LEFunctions::log('LEClient finished constructing', 'function LEClient __construct'); | ||
if($this->log >= LECLient::LOG_STATUS) LEFunctions::log('LEClient finished constructing', 'function LEClient __construct'); | ||
} | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ | |
* @author Youri van Weegberg <[email protected]> | ||
* @copyright 2018 Youri van Weegberg | ||
* @license https://opensource.org/licenses/mit-license.php MIT License | ||
* @version 1.1.0 | ||
* @version 1.1.1 | ||
* @link https://github.com/yourivw/LEClient | ||
* @since Class available since Release 1.0.0 | ||
*/ | ||
|
@@ -178,7 +178,7 @@ public function changeAccountKeys() | |
LEFunctions::RSAgenerateKeys(null, $this->accountKeys['private_key'].'.new', $this->accountKeys['public_key'].'.new'); | ||
$privateKey = openssl_pkey_get_private(file_get_contents($this->accountKeys['private_key'].'.new')); | ||
$details = openssl_pkey_get_details($privateKey); | ||
$innerPayload = array('account' => $this->connector->accountURL, 'newKey' => array( | ||
$innerPayload = array('account' => $this->connector->accountURL, 'newKey' => array( | ||
"kty" => "RSA", | ||
"n" => LEFunctions::Base64UrlSafeEncode($details["rsa"]["n"]), | ||
"e" => LEFunctions::Base64UrlSafeEncode($details["rsa"]["e"]) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ | |
* @author Youri van Weegberg <[email protected]> | ||
* @copyright 2018 Youri van Weegberg | ||
* @license https://opensource.org/licenses/mit-license.php MIT License | ||
* @version 1.1.0 | ||
* @version 1.1.1 | ||
* @link https://github.com/yourivw/LEClient | ||
* @since Class available since Release 1.0.0 | ||
*/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ | |
* @author Youri van Weegberg <[email protected]> | ||
* @copyright 2018 Youri van Weegberg | ||
* @license https://opensource.org/licenses/mit-license.php MIT License | ||
* @version 1.1.0 | ||
* @version 1.1.1 | ||
* @link https://github.com/yourivw/LEClient | ||
* @since Class available since Release 1.0.0 | ||
*/ | ||
|
@@ -102,7 +102,7 @@ private function request($method, $URL, $data = null) | |
{ | ||
if($this->accountDeactivated) throw new \RuntimeException('The account was deactivated. No further requests can be made.'); | ||
|
||
$headers = array('Accept: application/json', 'Content-Type: application/json'); | ||
$headers = array('Accept: application/json', 'Content-Type: application/jose+json'); | ||
$requestURL = preg_match('~^http~', $URL) ? $URL : $this->baseURL . $URL; | ||
$handle = curl_init(); | ||
curl_setopt($handle, CURLOPT_URL, $requestURL); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ | |
* @author Youri van Weegberg <[email protected]> | ||
* @copyright 2018 Youri van Weegberg | ||
* @license https://opensource.org/licenses/mit-license.php MIT License | ||
* @version 1.1.0 | ||
* @version 1.1.1 | ||
* @link https://github.com/yourivw/LEClient | ||
* @since Class available since Release 1.0.0 | ||
*/ | ||
|
@@ -47,7 +47,7 @@ class LEFunctions | |
public static function RSAGenerateKeys($directory, $privateKeyFile = 'private.pem', $publicKeyFile = 'public.pem', $keySize = 4096) | ||
{ | ||
|
||
if ($keySize < 2048 || $keySize > 4096) throw new \RuntimeException("RSA key size must be between 2048 and 4096"); | ||
if ($keySize < 2048 || $keySize > 4096) throw new \RuntimeException("RSA key size must be between 2048 and 4096."); | ||
|
||
$res = openssl_pkey_new(array( | ||
"private_key_type" => OPENSSL_KEYTYPE_RSA, | ||
|
@@ -82,9 +82,8 @@ public static function RSAGenerateKeys($directory, $privateKeyFile = 'private.pe | |
*/ | ||
public static function ECGenerateKeys($directory, $privateKeyFile = 'private.pem', $publicKeyFile = 'public.pem', $keySize = 256) | ||
{ | ||
if (version_compare(PHP_VERSION, '7.1.0') == -1) throw new \RuntimeException("PHP 7.1+ required for EC keys"); | ||
|
||
|
||
if (version_compare(PHP_VERSION, '7.1.0') == -1) throw new \RuntimeException("PHP 7.1+ required for EC keys."); | ||
|
||
if ($keySize == 256) | ||
{ | ||
$res = openssl_pkey_new(array( | ||
|
@@ -99,7 +98,7 @@ public static function ECGenerateKeys($directory, $privateKeyFile = 'private.pem | |
"curve_name" => "secp384r1", | ||
)); | ||
} | ||
else throw new \RuntimeException("EC key size must be 256 or 384"); | ||
else throw new \RuntimeException("EC key size must be 256 or 384."); | ||
|
||
|
||
if(!openssl_pkey_export($res, $privateKey)) throw new \RuntimeException("EC keypair export failed!"); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ | |
* @author Youri van Weegberg <[email protected]> | ||
* @copyright 2018 Youri van Weegberg | ||
* @license https://opensource.org/licenses/mit-license.php MIT License | ||
* @version 1.1.0 | ||
* @version 1.1.1 | ||
* @link https://github.com/yourivw/LEClient | ||
* @since Class available since Release 1.0.0 | ||
*/ | ||
|
@@ -339,10 +339,11 @@ public function getPendingAuthorizations($type) | |
* | ||
* @param string $identifier The domain name to verify. | ||
* @param int $type The type of verification. Supporting LEOrder::CHALLENGE_TYPE_HTTP and LEOrder::CHALLENGE_TYPE_DNS. | ||
* @param boolean $localcheck Whether to verify the authorization locally before making the authorization request to LE. Optional, default to true. | ||
* | ||
* @return boolean Returns true when the verification request was successful, false if not. | ||
*/ | ||
public function verifyPendingOrderAuthorization($identifier, $type) | ||
public function verifyPendingOrderAuthorization($identifier, $type, $localcheck = true) | ||
{ | ||
$privateKey = openssl_pkey_get_private(file_get_contents($this->connector->accountKeys['private_key'])); | ||
$details = openssl_pkey_get_details($privateKey); | ||
|
@@ -368,13 +369,13 @@ public function verifyPendingOrderAuthorization($identifier, $type) | |
switch($type) | ||
{ | ||
case LEOrder::CHALLENGE_TYPE_HTTP: | ||
if(LEFunctions::checkHTTPChallenge($identifier, $challenge['token'], $keyAuthorization)) | ||
if($localcheck == false OR LEFunctions::checkHTTPChallenge($identifier, $challenge['token'], $keyAuthorization)) | ||
{ | ||
$sign = $this->connector->signRequestKid(array('keyAuthorization' => $keyAuthorization), $this->connector->accountURL, $challenge['url']); | ||
$post = $this->connector->post($challenge['url'], $sign); | ||
if(strpos($post['header'], "200 OK") !== false) | ||
{ | ||
if($this->log >= LECLient::LOG_STATUS) LEFunctions::log('HTTP challenge for \'' . $identifier . '\' valid.', 'function verifyPendingOrderAuthorization'); | ||
if($localcheck && $this->log >= LECLient::LOG_STATUS) LEFunctions::log('HTTP challenge for \'' . $identifier . '\' valid.', 'function verifyPendingOrderAuthorization'); | ||
while($auth->status == 'pending') | ||
{ | ||
sleep(1); | ||
|
@@ -385,18 +386,18 @@ public function verifyPendingOrderAuthorization($identifier, $type) | |
} | ||
else | ||
{ | ||
if($this->log >= LECLient::LOG_STATUS) LEFunctions::log('HTTP challenge for \'' . $identifier . '\' tested, found invalid.', 'function verifyPendingOrderAuthorization'); | ||
if($this->log >= LECLient::LOG_STATUS) LEFunctions::log('HTTP challenge for \'' . $identifier . '\' tested locally, found invalid.', 'function verifyPendingOrderAuthorization'); | ||
} | ||
break; | ||
case LEOrder::CHALLENGE_TYPE_DNS: | ||
$DNSDigest = LEFunctions::Base64UrlSafeEncode(hash('sha256', $keyAuthorization, true)); | ||
if(LEFunctions::checkDNSChallenge($identifier, $DNSDigest)) | ||
if($localcheck == false OR LEFunctions::checkDNSChallenge($identifier, $DNSDigest)) | ||
{ | ||
$sign = $this->connector->signRequestKid(array('keyAuthorization' => $keyAuthorization), $this->connector->accountURL, $challenge['url']); | ||
$post = $this->connector->post($challenge['url'], $sign); | ||
if(strpos($post['header'], "200 OK") !== false) | ||
{ | ||
if($this->log >= LECLient::LOG_STATUS) LEFunctions::log('DNS challenge for \'' . $identifier . '\' valid.', 'function verifyPendingOrderAuthorization'); | ||
if($localcheck && $this->log >= LECLient::LOG_STATUS) LEFunctions::log('DNS challenge for \'' . $identifier . '\' valid.', 'function verifyPendingOrderAuthorization'); | ||
while($auth->status == 'pending') | ||
{ | ||
sleep(1); | ||
|
@@ -407,7 +408,7 @@ public function verifyPendingOrderAuthorization($identifier, $type) | |
} | ||
else | ||
{ | ||
if($this->log >= LECLient::LOG_STATUS) LEFunctions::log('DNS challenge for \'' . $identifier . '\' tested, found invalid.', 'function verifyPendingOrderAuthorization'); | ||
if($this->log >= LECLient::LOG_STATUS) LEFunctions::log('DNS challenge for \'' . $identifier . '\' tested locally, found invalid.', 'function verifyPendingOrderAuthorization'); | ||
} | ||
break; | ||
} | ||
|
@@ -629,7 +630,7 @@ public function revokeCertificate($reason = 0) | |
preg_match('~-----BEGIN\sCERTIFICATE-----(.*)-----END\sCERTIFICATE-----~s', $certificate, $matches); | ||
$certificate = trim(LEFunctions::Base64UrlSafeEncode(base64_decode(trim($matches[1])))); | ||
|
||
$sign = $this->connector->signRequestJWK(array('certificate' => $certificate, 'reason' => $reason), $this->connector->revokeCert); | ||
$sign = $this->connector->signRequestJWK(array('certificate' => $certificate, 'reason' => $reason), $this->connector->revokeCert, $this->certificateKeys['private_key']); | ||
$post = $this->connector->post($this->connector->revokeCert, $sign); | ||
if(strpos($post['header'], "200 OK") !== false) | ||
{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters