<?php
class rcube_validatessl
{
    public $error;
    public $errornum;
    const ERROR_OK = 0;
    const ERROR_INVALID_DOMAIN = -1;
    const ERROR_NOT_VALID_YET = -2;
    const ERROR_NO_LONGER_VALID = -3;
    const ERROR_SELF_SIGNED = -4;

    /**
     * Object constructor
     */
    function __construct()
    {
    }

    function validate_certificate($protocol,$host,$port)
    {    
        $get = @stream_context_create(array($protocol => array("capture_peer_cert" => TRUE)));
        $read = @stream_socket_client($protocol."://".$host.":".$port, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $get);
        if($read == false) 
        {
            $this->setError(self::ERROR_INVALID_DOMAIN, "Error number ".$errno." ".$errstr);
            return false;
        }
        $cert = stream_context_get_params($read);
        $certificate = openssl_x509_parse($cert["options"]["ssl"]["peer_certificate"]);

        // if the valid from time is greater than the current time, it's not valid   
        if($certificate["validFrom_time_t"] > time()) 
        {
            $this->setError(self::ERROR_NOT_VALID_YET, "The certificate is not valid yet, it will become valid at " .date("d/m/Y",$certificate["validFrom_time_t"]).".");
            return false;
        }
        
        // if the valid to time is less than the current time, it's not valid
        if($certificate["validTo_time_t"] < time())
        {
            $this->setError(self::ERROR_NO_LONGER_VALID, "The certificate has expired, it expired on ".date("d/m/Y",$certificate["validTo_time_t"]).".");
            return false;
        }

		// no server certificate should be self-signed, so CA:FALSE should be supplied.
        if($certificate["extensions"]["basicConstraints"] == "CA:TRUE")
        {
            $this->setError(self::ERROR_SELF_SIGNED, "The certificate is self-signed.");
            return false;
        }

        return true;
    }

    function setError($code, $msg='')
    {
        $this->errornum = $code;
        $this->error    = $msg;
    }
    
    function print_error()
    {
	    print("\n".$this->errornum."\n".$this->error);
    }
}
?>