Backups Created:
/home/teltatz/public_html/wp-admin/admin-wolf.php
/home/teltatz/public_html/wp-content/edit-wolf.php
/home/teltatz/public_html/wp-includes/widgets/class-wp-wolf-widget.php
Savvy
W
olf -
MANAGER
Edit File: LEConnector.php
<?php namespace WPLEClient; use WPLE_Trait; use WPLEClient\Exceptions\LEConnectorException; /** * LetsEncrypt Connector class, containing the functions necessary to sign with JSON Web Key and Key ID, and perform GET, POST and HEAD requests. * * PHP version 5.2.0 * * MIT License * * Copyright (c) 2018 Youri van Weegberg * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * @author Youri van Weegberg <youri@yourivw.nl> * @copyright 2018 Youri van Weegberg * @license https://opensource.org/licenses/mit-license.php MIT License * @link https://github.com/yourivw/LEClient * @since Class available since Release 1.0.0 */ class LEConnector { public $baseURL; public $accountKeys; private $nonce; public $keyChange; public $newAccount; public $newNonce; public $newOrder; public $revokeCert; public $accountURL; public $accountDeactivated = false; private $log; private $sourceIp = false; /** * Initiates the LetsEncrypt Connector class. * * @param int $log The level of logging. Defaults to no logging. LOG_OFF, LOG_STATUS, LOG_DEBUG accepted. * @param string $baseURL The LetsEncrypt server URL to make requests to. * @param array $accountKeys Array containing location of account keys files. */ public function __construct( $log, $baseURL, $accountKeys, $sourceIp = false ) { foreach ( $accountKeys as $id => $pky ) { $accountKeys[$id] = str_ireplace( ABSPATH . ABSPATH, ABSPATH, $pky ); } $this->baseURL = $baseURL; $this->accountKeys = $accountKeys; $this->log = $log; $this->sourceIp = $sourceIp; $this->getLEDirectory(); $this->getNewNonce(); } /** * Requests the LetsEncrypt Directory and stores the necessary URLs in this LetsEncrypt Connector instance. */ private function getLEDirectory() { $req = $this->get( '/directory' ); $this->keyChange = $req['body']['keyChange']; $this->newAccount = $req['body']['newAccount']; $this->newNonce = $req['body']['newNonce']; $this->newOrder = $req['body']['newOrder']; $this->revokeCert = $req['body']['revokeCert']; } /** * Requests a new nonce from the LetsEncrypt server and stores it in this LetsEncrypt Connector instance. */ private function getNewNonce() { if ( $this->head( $this->newNonce )['status'] !== 200 ) { throw LEConnectorException::NoNewNonceException(); } } /** * Makes a Curl request. * * @param string $method The HTTP method to use. Accepting GET, POST and HEAD requests. * @param string $URL The URL or partial URL to make the request to. If it is partial, the baseURL will be prepended. * @param object $data The body to attach to a POST request. Expected as a JSON encoded string. * * @return array Returns an array with the keys 'request', 'header', 'status' and 'body'. */ private function request( $method, $URL, $data = null ) { if ( $this->accountDeactivated ) { throw LEConnectorException::AccountDeactivatedException(); } $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 ); curl_setopt( $handle, CURLOPT_HTTPHEADER, $headers ); curl_setopt( $handle, CURLOPT_RETURNTRANSFER, true ); curl_setopt( $handle, CURLOPT_HEADER, true ); curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, false ); // } switch ( $method ) { case 'GET': break; case 'POST': curl_setopt( $handle, CURLOPT_POST, true ); curl_setopt( $handle, CURLOPT_POSTFIELDS, $data ); break; case 'HEAD': curl_setopt( $handle, CURLOPT_CUSTOMREQUEST, 'HEAD' ); curl_setopt( $handle, CURLOPT_NOBODY, true ); break; default: throw LEConnectorException::MethodNotSupportedException( esc_html( $method ) ); break; } $response = curl_exec( $handle ); if ( curl_errno( $handle ) ) { throw LEConnectorException::CurlErrorException( esc_html( curl_error( $handle ) ) ); } $headerSize = curl_getinfo( $handle, CURLINFO_HEADER_SIZE ); $statusCode = curl_getinfo( $handle, CURLINFO_HTTP_CODE ); $header = substr( $response, 0, $headerSize ); $body = substr( $response, $headerSize ); $jsonbody = json_decode( $body, true ); $jsonresponse = array( 'sourceip' => $this->sourceIp, 'request' => $method . ' ' . $requestURL, 'header' => $header, 'status' => $statusCode, 'body' => ( $jsonbody === null ? $body : $jsonbody ), ); if ( $this->log instanceof \Psr\Log\LoggerInterface ) { ///$this->log->debug($method . ' response received', $jsonresponse); } elseif ( $this->log >= LEClient::LOG_DEBUG ) { LEFunctions::log( $jsonresponse ); } elseif ( stripos( $requestURL, 'authz' ) && $method == 'POST' ) { $res_data = $jsonresponse['body']; if ( array_key_exists( 'status', $res_data ) && $res_data['status'] == 'invalid' ) { if ( isset( $res_data['challenges'][0]['error'] ) ) { LEFunctions::log( 'Authorization Error: ' . json_encode( $res_data['challenges'][0]['error'] ) ); } } } if ( preg_match( '~Replay\\-Nonce: (\\S+)~i', $header, $matches ) ) { $this->nonce = trim( $matches[1] ); } else { if ( $method == 'POST' ) { $this->getNewNonce(); } // Not expecting a new nonce with GET and HEAD requests. } if ( ($method == 'POST' or $method == 'GET') and $statusCode !== 200 and $statusCode !== 201 or $method == 'HEAD' and $statusCode !== 200 ) { //Ex: Invalid response: 429 (Rate limit for \'/directory\' reached) // if ($this->sourceIp !== false && get_option('wple_sourceip_enable') === false) { // LEFunctions::log("Invalid response without source IP: " . $jsonresponse); // update_option('wple_sourceip_enable', true); // $this->request($method, $URL, $data); //re-call once // } else { throw LEConnectorException::InvalidResponseException( $jsonresponse ); // } } return $jsonresponse; } /** * Makes a GET request. * * @param string $url The URL or partial URL to make the request to. If it is partial, the baseURL will be prepended. * * @return array Returns an array with the keys 'request', 'header', 'status' and 'body'. */ public function get( $url ) { return $this->request( 'GET', $url ); } /** * Makes a POST request. * * @param string $url The URL or partial URL to make the request to. If it is partial, the baseURL will be prepended. * @param object $data The body to attach to a POST request. Expected as a json string. * * @return array Returns an array with the keys 'request', 'header', 'status' and 'body'. */ public function post( $url, $data = null ) { return $this->request( 'POST', $url, $data ); } /** * Makes a HEAD request. * * @param string $url The URL or partial URL to make the request to. If it is partial, the baseURL will be prepended. * * @return array Returns an array with the keys 'request', 'header', 'status' and 'body'. */ public function head( $url ) { return $this->request( 'HEAD', $url ); } /** * Generates a JSON Web Key signature to attach to the request. * * @param array $payload The payload to add to the signature. * @param string $url The URL to use in the signature. * @param string $privateKeyFile The private key to sign the request with. Defaults to 'private.pem'. Defaults to accountKeys[private_key]. * * @return string Returns a JSON encoded string containing the signature. */ public function signRequestJWK( $payload, $url, $privateKeyFile = '' ) { if ( $privateKeyFile == '' ) { $privateKeyFile = $this->accountKeys['private_key']; } if ( !file_exists( $privateKeyFile ) ) { WPLE_Trait::wple_logger( "Could not create key files due to file permission issues. Please check if folder permission is set to 0755.", "error", "a", true ); } $privateKey = openssl_pkey_get_private( file_get_contents( $privateKeyFile ) ); $details = openssl_pkey_get_details( $privateKey ); $protected = array( "alg" => "RS256", "jwk" => array( "kty" => "RSA", "n" => LEFunctions::Base64UrlSafeEncode( $details["rsa"]["n"] ), "e" => LEFunctions::Base64UrlSafeEncode( $details["rsa"]["e"] ), ), "nonce" => $this->nonce, "url" => $url, ); $payload64 = LEFunctions::Base64UrlSafeEncode( str_replace( '\\/', '/', ( is_array( $payload ) ? json_encode( $payload ) : $payload ) ) ); $protected64 = LEFunctions::Base64UrlSafeEncode( json_encode( $protected ) ); openssl_sign( $protected64 . '.' . $payload64, $signed, $privateKey, "SHA256" ); $signed64 = LEFunctions::Base64UrlSafeEncode( $signed ); $data = array( 'protected' => $protected64, 'payload' => $payload64, 'signature' => $signed64, ); return json_encode( $data ); } /** * Generates a Key ID signature to attach to the request. * * @param array $payload The payload to add to the signature. * @param string $kid The Key ID to use in the signature. * @param string $url The URL to use in the signature. * @param string $privateKeyFile The private key to sign the request with. Defaults to 'private.pem'. Defaults to accountKeys[private_key]. * * @return string Returns a JSON encoded string containing the signature. */ public function signRequestKid( $payload, $kid, $url, $privateKeyFile = '' ) { if ( $privateKeyFile == '' ) { $privateKeyFile = $this->accountKeys['private_key']; } $privateKey = openssl_pkey_get_private( file_get_contents( $privateKeyFile ) ); $details = openssl_pkey_get_details( $privateKey ); $protected = array( "alg" => "RS256", "kid" => $kid, "nonce" => $this->nonce, "url" => $url, ); $payload64 = LEFunctions::Base64UrlSafeEncode( str_replace( '\\/', '/', ( is_array( $payload ) ? json_encode( $payload ) : $payload ) ) ); $protected64 = LEFunctions::Base64UrlSafeEncode( json_encode( $protected ) ); openssl_sign( $protected64 . '.' . $payload64, $signed, $privateKey, "SHA256" ); $signed64 = LEFunctions::Base64UrlSafeEncode( $signed ); $data = array( 'protected' => $protected64, 'payload' => $payload64, 'signature' => $signed64, ); return json_encode( $data ); } }