first commit
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) or die();
|
||||
|
||||
/**
|
||||
* @package DirectAdmin
|
||||
* @author Rogier Lankhorst
|
||||
* @copyright Copyright (C) 2021, Rogier Lankhorst
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License, version 3
|
||||
* @link https://really-simple-ssl.com
|
||||
* @since Class available since Release 5.0.0
|
||||
*
|
||||
*/
|
||||
|
||||
require_once( rsssl_le_path . 'integrations/directadmin/httpsocket.php' );
|
||||
require_once( rsssl_le_path . 'integrations/directadmin/functions.php' );
|
||||
|
||||
class rsssl_directadmin {
|
||||
public $host;
|
||||
private $login;
|
||||
private $password;
|
||||
public $ssl_installation_url;
|
||||
|
||||
/**
|
||||
* Initiates the directadmin class.
|
||||
*
|
||||
*/
|
||||
public function __construct() {
|
||||
$password = RSSSL_LE()->letsencrypt_handler->decode( rsssl_get_value( 'directadmin_password' ) );
|
||||
$host = rsssl_get_value( 'directadmin_host' );
|
||||
$this->host = str_replace( array( 'http://', 'https://', ':2222' ), '', $host );
|
||||
$this->login = rsssl_get_value( 'directadmin_username' );
|
||||
$this->password = $password;
|
||||
$this->ssl_installation_url = 'https://' . $this->host . "";
|
||||
}
|
||||
/**
|
||||
* Check if all creds are available
|
||||
* @return bool
|
||||
*/
|
||||
public function credentials_available(){
|
||||
if (!empty($this->host) && !empty($this->password) && !empty($this->login)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function installSSL( $domains ) {
|
||||
$response = false;
|
||||
if ( is_array($domains) && count($domains)>0 ) {
|
||||
foreach( $domains as $domain ) {
|
||||
$response_item = $this->installSSLPerDomain($domain);
|
||||
//set on first iteration
|
||||
if ( !$response ) {
|
||||
$response = $response_item;
|
||||
}
|
||||
|
||||
//override if not successfull, to always get the error.
|
||||
if ( $response->status !== 'success' ) {
|
||||
$response = $response_item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !$response ) {
|
||||
$response = new RSSSL_RESPONSE('error', 'stop', __("No valid list of domains.", "really-simple-ssl"));
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install certificate
|
||||
*
|
||||
* @param string $domain
|
||||
*
|
||||
* @return RSSSL_RESPONSE
|
||||
*/
|
||||
public function installSSLPerDomain( $domain ) {
|
||||
$key_file = get_option( 'rsssl_private_key_path' );
|
||||
$cert_file = get_option( 'rsssl_certificate_path' );
|
||||
$cabundle_file = get_option( 'rsssl_intermediate_path' );
|
||||
|
||||
try {
|
||||
$server_ssl=true;
|
||||
$server_port=2222;
|
||||
$sock = new HTTPSocket;
|
||||
if ($server_ssl){
|
||||
$sock->connect("ssl://".$this->host, $server_port);
|
||||
} else {
|
||||
$sock->connect($this->host, $server_port);
|
||||
}
|
||||
$sock->set_login($this->login, $this->password);
|
||||
$sock->method = "POST";
|
||||
$sock->query('/CMD_API_SSL',
|
||||
array(
|
||||
'domain' => $domain,
|
||||
'action' => 'save',
|
||||
'type' => 'paste',
|
||||
'certificate' => file_get_contents( $key_file ) . file_get_contents( $cert_file )
|
||||
));
|
||||
$response = $sock->fetch_parsed_body();
|
||||
error_log( print_r( $response, true ) );
|
||||
|
||||
//set a default error response
|
||||
$status = 'warning';
|
||||
$action = 'continue';
|
||||
$message = rsssl_get_manual_instructions_text($this->ssl_installation_url);
|
||||
|
||||
|
||||
//if successful, proceed to next step
|
||||
if ( empty($response['details']) && stripos($response[0], 'Error' ) ) {
|
||||
$sock->query('/CMD_SSL',
|
||||
array(
|
||||
'domain' => $domain,
|
||||
'action' => 'save',
|
||||
'type' => 'cacert',
|
||||
'active' => 'yes',
|
||||
'cacert' => file_get_contents( $cabundle_file )
|
||||
));
|
||||
$response = $sock->fetch_parsed_body();
|
||||
error_log( print_r( $response, true ) );
|
||||
if ( empty($response['details']) && stripos($response[0], 'Error' ) ) {
|
||||
$status = 'success';
|
||||
$action = 'finalize';
|
||||
$message = sprintf(__("SSL successfully installed on %s","really-simple-ssl"), $domain);
|
||||
update_option( 'rsssl_le_certificate_installed_by_rsssl', 'directadmin' );
|
||||
delete_option( 'rsssl_installation_error' );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
error_log( print_r( $e, true ) );
|
||||
update_option( 'rsssl_installation_error', 'directadmin' );
|
||||
$status = 'warning';
|
||||
$action = 'continue';
|
||||
$message = $e->getMessage();
|
||||
}
|
||||
|
||||
return new RSSSL_RESPONSE( $status, $action, $message );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
defined( 'ABSPATH' ) or die();
|
||||
|
||||
function rsssl_install_directadmin(){
|
||||
if (rsssl_is_ready_for('installation')) {
|
||||
$directadmin = new rsssl_directadmin();
|
||||
$domains = RSSSL_LE()->letsencrypt_handler->get_subjects();
|
||||
$response = $directadmin->installSSL($domains);
|
||||
if ( $response->status === 'success' ) {
|
||||
update_option('rsssl_le_certificate_installed_by_rsssl', 'directadmin');
|
||||
}
|
||||
return $response;
|
||||
} else {
|
||||
$status = 'error';
|
||||
$action = 'stop';
|
||||
$message = __("The system is not ready for the installation yet. Please run the wizard again.", "really-simple-ssl");
|
||||
return new RSSSL_RESPONSE($status, $action, $message);
|
||||
}
|
||||
}
|
||||
|
||||
function rsssl_directadmin_add_condition_actions($steps){
|
||||
$directadmin = new rsssl_directadmin();
|
||||
if ( $directadmin->credentials_available() ) {
|
||||
$index = array_search( 'installation', array_column( $steps['lets-encrypt'], 'id' ) );
|
||||
$index ++;
|
||||
//clear existing array
|
||||
$steps['lets-encrypt'][ $index ]['actions'] = array();
|
||||
$steps['lets-encrypt'][ $index ]['actions'][]
|
||||
= array(
|
||||
'description' => __( "Attempting to install certificate...", "really-simple-ssl" ),
|
||||
'action' => 'rsssl_install_directadmin',
|
||||
'attempts' => 1,
|
||||
'speed' => 'normal',
|
||||
);
|
||||
}
|
||||
|
||||
return $steps;
|
||||
}
|
||||
|
||||
add_filter( 'rsssl_steps', 'rsssl_directadmin_add_condition_actions' );
|
||||
@@ -0,0 +1,441 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Socket communication class.
|
||||
*
|
||||
* Originally designed for use with DirectAdmin's API, this class will fill any HTTP socket need.
|
||||
*
|
||||
* Very, very basic usage:
|
||||
* $Socket = new HTTPSocket;
|
||||
* echo $Socket->get('http://user:pass@somesite.com/somedir/some.file?query=string&this=that');
|
||||
*
|
||||
* @author Phi1 'l0rdphi1' Stier <l0rdphi1@liquenox.net>
|
||||
* @package HTTPSocket
|
||||
* @version 3.0.4
|
||||
*/
|
||||
class HTTPSocket {
|
||||
|
||||
var $version = '3.0.4';
|
||||
|
||||
/* all vars are private except $error, $query_cache, and $doFollowLocationHeader */
|
||||
|
||||
var $method = 'GET';
|
||||
|
||||
var $remote_host;
|
||||
var $remote_port;
|
||||
var $remote_uname;
|
||||
var $remote_passwd;
|
||||
|
||||
var $result;
|
||||
var $result_header;
|
||||
var $result_body;
|
||||
var $result_status_code;
|
||||
|
||||
var $lastTransferSpeed;
|
||||
|
||||
var $bind_host;
|
||||
|
||||
var $error = array();
|
||||
var $warn = array();
|
||||
var $query_cache = array();
|
||||
|
||||
var $doFollowLocationHeader = TRUE;
|
||||
var $redirectURL;
|
||||
var $max_redirects = 5;
|
||||
var $ssl_setting_message = 'DirectAdmin appears to be using SSL. Change your script to connect to ssl://';
|
||||
|
||||
var $extra_headers = array();
|
||||
|
||||
var $proxy = false;
|
||||
var $proxy_headers = array();
|
||||
|
||||
/**
|
||||
* Create server "connection".
|
||||
*
|
||||
*/
|
||||
function connect($host, $port = '' )
|
||||
{
|
||||
if (!is_numeric($port))
|
||||
{
|
||||
$port = 80;
|
||||
}
|
||||
|
||||
$this->remote_host = $host;
|
||||
$this->remote_port = $port;
|
||||
}
|
||||
|
||||
function bind( $ip = '' )
|
||||
{
|
||||
if ( $ip == '' )
|
||||
{
|
||||
$ip = $_SERVER['SERVER_ADDR'];
|
||||
}
|
||||
|
||||
$this->bind_host = $ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the method being used to communicate.
|
||||
*
|
||||
* @param string|null request method. supports GET, POST, and HEAD. default is GET
|
||||
*/
|
||||
function set_method( $method = 'GET' )
|
||||
{
|
||||
$this->method = strtoupper($method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a username and password.
|
||||
*
|
||||
* @param string|null username. defualt is null
|
||||
* @param string|null password. defualt is null
|
||||
*/
|
||||
function set_login( $uname = '', $passwd = '' )
|
||||
{
|
||||
if ( strlen($uname) > 0 )
|
||||
{
|
||||
$this->remote_uname = $uname;
|
||||
}
|
||||
|
||||
if ( strlen($passwd) > 0 )
|
||||
{
|
||||
$this->remote_passwd = $passwd;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* For pass through, this function writes the data in chunks.
|
||||
*/
|
||||
private function stream_chunk($ch, $data)
|
||||
{
|
||||
echo($data);
|
||||
return strlen($data);
|
||||
}
|
||||
private function stream_header($ch, $data)
|
||||
{
|
||||
if (!preg_match('/^HTTP/i', $data))
|
||||
{
|
||||
header($data);
|
||||
}
|
||||
return strlen($data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query the server
|
||||
*
|
||||
* @param string containing properly formatted server API. See DA API docs and examples. Http:// URLs O.K. too.
|
||||
* @param string|array query to pass to url
|
||||
* @param int if connection KB/s drops below value here, will drop connection
|
||||
*/
|
||||
function query( $request, $content = '', $doSpeedCheck = 0 )
|
||||
{
|
||||
$this->error = $this->warn = array();
|
||||
$this->result_status_code = NULL;
|
||||
|
||||
$is_ssl = FALSE;
|
||||
|
||||
// is our request a http:// ... ?
|
||||
if (preg_match('!^http://!i',$request) || preg_match('!^https://!i',$request))
|
||||
{
|
||||
$location = parse_url($request);
|
||||
if (preg_match('!^https://!i',$request))
|
||||
{
|
||||
$this->connect('https://'.$location['host'],$location['port']);
|
||||
}
|
||||
else
|
||||
$this->connect('http://'.$location['host'],$location['port']);
|
||||
|
||||
$this->set_login($location['user'],$location['pass']);
|
||||
|
||||
$request = $location['path'];
|
||||
$content = $location['query'];
|
||||
|
||||
if ( strlen($request) < 1 )
|
||||
{
|
||||
$request = '/';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (preg_match('!^ssl://!i', $this->remote_host))
|
||||
$this->remote_host = 'https://'.substr($this->remote_host, 6);
|
||||
|
||||
if (preg_match('!^tcp://!i', $this->remote_host))
|
||||
$this->remote_host = 'http://'.substr($this->remote_host, 6);
|
||||
|
||||
if (preg_match('!^https://!i', $this->remote_host))
|
||||
$is_ssl = TRUE;
|
||||
|
||||
$array_headers = array(
|
||||
'Host' => ( $this->remote_port == 80 ? $this->remote_host : "$this->remote_host:$this->remote_port" ),
|
||||
'Accept' => '*/*',
|
||||
'Connection' => 'Close' );
|
||||
|
||||
foreach ( $this->extra_headers as $key => $value )
|
||||
{
|
||||
$array_headers[$key] = $value;
|
||||
}
|
||||
|
||||
$this->result = $this->result_header = $this->result_body = '';
|
||||
|
||||
// was content sent as an array? if so, turn it into a string
|
||||
if (is_array($content))
|
||||
{
|
||||
$pairs = array();
|
||||
|
||||
foreach ( $content as $key => $value )
|
||||
{
|
||||
$pairs[] = "$key=".urlencode($value);
|
||||
}
|
||||
|
||||
$content = join('&',$pairs);
|
||||
unset($pairs);
|
||||
}
|
||||
|
||||
$OK = TRUE;
|
||||
|
||||
if ($this->method == 'GET' && isset($content) && $content != '')
|
||||
$request .= '?'.$content;
|
||||
|
||||
$ch = curl_init($this->remote_host.':'.$this->remote_port.$request);
|
||||
|
||||
if ($is_ssl)
|
||||
{
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //1
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //2
|
||||
//curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, "HTTPSocket/$this->version");
|
||||
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 100);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
|
||||
if ($this->proxy)
|
||||
{
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER,false);
|
||||
curl_setopt($ch, CURLOPT_HEADER, false);
|
||||
curl_setopt($ch, CURLINFO_HEADER_OUT, false);
|
||||
curl_setopt($ch, CURLOPT_BUFFERSIZE, 8192); // 8192
|
||||
curl_setopt($ch, CURLOPT_WRITEFUNCTION, array($this, "stream_chunk"));
|
||||
curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, "stream_header"));
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_LOW_SPEED_LIMIT, 512);
|
||||
curl_setopt($ch, CURLOPT_LOW_SPEED_TIME, 120);
|
||||
|
||||
// instance connection
|
||||
if ($this->bind_host)
|
||||
{
|
||||
curl_setopt($ch, CURLOPT_INTERFACE, $this->bind_host);
|
||||
}
|
||||
|
||||
// if we have a username and password, add the header
|
||||
if ( isset($this->remote_uname) && isset($this->remote_passwd) )
|
||||
{
|
||||
curl_setopt($ch, CURLOPT_USERPWD, $this->remote_uname.':'.$this->remote_passwd);
|
||||
}
|
||||
|
||||
// for DA skins: if $this->remote_passwd is NULL, try to use the login key system
|
||||
if ( isset($this->remote_uname) && $this->remote_passwd == NULL )
|
||||
{
|
||||
curl_setopt($ch, CURLOPT_COOKIE, "session={$_SERVER['SESSION_ID']}; key={$_SERVER['SESSION_KEY']}");
|
||||
}
|
||||
|
||||
// if method is POST, add content length & type headers
|
||||
if ( $this->method == 'POST' )
|
||||
{
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
|
||||
|
||||
//$array_headers['Content-type'] = 'application/x-www-form-urlencoded';
|
||||
$array_headers['Content-length'] = strlen($content);
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $array_headers);
|
||||
|
||||
|
||||
if( !($this->result = curl_exec($ch)) )
|
||||
{
|
||||
$this->error[] .= curl_error($ch);
|
||||
$OK = FALSE;
|
||||
}
|
||||
|
||||
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||
$this->result_header = substr($this->result, 0, $header_size);
|
||||
$this->result_body = substr($this->result, $header_size);
|
||||
$this->result_status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
$this->lastTransferSpeed = curl_getinfo($ch, CURLINFO_SPEED_DOWNLOAD) / 1024;
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
$this->query_cache[] = $this->remote_host.':'.$this->remote_port.$request;
|
||||
|
||||
$headers = $this->fetch_header();
|
||||
|
||||
// did we get the full file?
|
||||
if ( !empty($headers['content-length']) && $headers['content-length'] != strlen($this->result_body) )
|
||||
{
|
||||
$this->result_status_code = 206;
|
||||
}
|
||||
|
||||
// now, if we're being passed a location header, should we follow it?
|
||||
if ($this->doFollowLocationHeader)
|
||||
{
|
||||
//dont bother if we didn't even setup the script correctly
|
||||
if (isset($headers['x-use-https']) && $headers['x-use-https']=='yes')
|
||||
die($this->ssl_setting_message);
|
||||
|
||||
if (isset($headers['location']))
|
||||
{
|
||||
if ($this->max_redirects <= 0)
|
||||
die("Too many redirects on: ".$headers['location']);
|
||||
|
||||
$this->max_redirects--;
|
||||
$this->redirectURL = $headers['location'];
|
||||
$this->query($headers['location']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getTransferSpeed()
|
||||
{
|
||||
return $this->lastTransferSpeed;
|
||||
}
|
||||
|
||||
/**
|
||||
* The quick way to get a URL's content :)
|
||||
*
|
||||
* @param string URL
|
||||
* @param boolean return as array? (like PHP's file() command)
|
||||
* @return string result body
|
||||
*/
|
||||
function get($location, $asArray = FALSE )
|
||||
{
|
||||
$this->query($location);
|
||||
|
||||
if ( $this->get_status_code() == 200 )
|
||||
{
|
||||
if ($asArray)
|
||||
{
|
||||
return preg_split("/\n/",$this->fetch_body());
|
||||
}
|
||||
|
||||
return $this->fetch_body();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last status code.
|
||||
* 200 = OK;
|
||||
* 403 = FORBIDDEN;
|
||||
* etc.
|
||||
*
|
||||
* @return int status code
|
||||
*/
|
||||
function get_status_code()
|
||||
{
|
||||
return $this->result_status_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a header, sent with the next query.
|
||||
*
|
||||
* @param string header name
|
||||
* @param string header value
|
||||
*/
|
||||
function add_header($key,$value)
|
||||
{
|
||||
$this->extra_headers[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears any extra headers.
|
||||
*
|
||||
*/
|
||||
function clear_headers()
|
||||
{
|
||||
$this->extra_headers = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the result of a query.
|
||||
*
|
||||
* @return string result
|
||||
*/
|
||||
function fetch_result()
|
||||
{
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the header of result (stuff before body).
|
||||
*
|
||||
* @param string (optional) header to return
|
||||
* @return array result header
|
||||
*/
|
||||
function fetch_header( $header = '' )
|
||||
{
|
||||
if ($this->proxy)
|
||||
return $this->proxy_headers;
|
||||
|
||||
$array_headers = preg_split("/\r\n/",$this->result_header);
|
||||
|
||||
$array_return = array( 0 => $array_headers[0] );
|
||||
unset($array_headers[0]);
|
||||
|
||||
foreach ( $array_headers as $pair )
|
||||
{
|
||||
if ($pair == '' || $pair == "\r\n") continue;
|
||||
list($key,$value) = preg_split("/: /",$pair,2);
|
||||
$array_return[strtolower($key)] = $value;
|
||||
}
|
||||
|
||||
if ( $header != '' )
|
||||
{
|
||||
return $array_return[strtolower($header)];
|
||||
}
|
||||
|
||||
return $array_return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the body of result (stuff after header).
|
||||
*
|
||||
* @return string result body
|
||||
*/
|
||||
function fetch_body()
|
||||
{
|
||||
return $this->result_body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return parsed body in array format.
|
||||
*
|
||||
* @return array result parsed
|
||||
*/
|
||||
function fetch_parsed_body()
|
||||
{
|
||||
parse_str($this->result_body,$x);
|
||||
return $x;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a specifc message on how to change the SSL setting, in the event that it's not set correctly.
|
||||
*/
|
||||
function set_ssl_setting_message($str)
|
||||
{
|
||||
$this->ssl_setting_message = $str;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user