diff --git a/webmail/classes/class_smtp.php b/webmail/classes/class_smtp.php index 08d67df..c59e137 100644 --- a/webmail/classes/class_smtp.php +++ b/webmail/classes/class_smtp.php @@ -14,7 +14,7 @@ * * @package NOCC * @license http://www.gnu.org/licenses/ GNU General Public License - * @version SVN: $Id: class_smtp.php 3093 2023-07-21 17:05:24Z oheil $ + * @version SVN: $Id: class_smtp.php 3097 2023-09-05 10:44:26Z oheil $ */ require_once 'exception.php'; @@ -193,6 +193,39 @@ class smtp { } return (true); break; + case 'NTLM': + fputs($smtp, "helo " . $_SERVER['SERVER_NAME'] . "\r\n"); + $response=""; + if( $this->check_response("STARTTLS HELO",$smtp,$response) ) { + return new NoccException($html_smtp_error_unexpected . ' : ' . $response); + } + fputs($smtp, "AUTH NTLM\r\n"); + $response=""; + if( $this->check_response("STARTTLS AUTH NTLM",$smtp,$response) ) { + return new NoccException($html_smtp_error_unexpected . ' : ' . $response); + } + + $message=NTLM_type1message(); + fputs($smtp, base64_encode($message)."\r\n"); + $response=""; + if( $this->check_response("NTLMSSP",$smtp,$response) ) { + return new NoccException($html_smtp_error_unexpected . ' : ' . $response); + } + $matches=array(); + if( preg_match("/^NTLMSSP:334\s+(.*)\s+|$/",$response,$matches) ) { + $response=$matches[1]; + } + $response=base64_decode($response); + + $message=NTLM_type3message($response,"","",$user, $password); + fputs($smtp, base64_encode($message)."\r\n"); + $response=""; + if( $this->check_response("NTLMSSP",$smtp,$response) ) { + return new NoccException($html_smtp_error_unexpected . ' : ' . $response); + } + + return(true); + break; case 'TLS': fputs($smtp, "STARTTLS\r\n"); $response=""; diff --git a/webmail/utils/crypt.php b/webmail/utils/crypt.php index 3416254..2eae570 100644 --- a/webmail/utils/crypt.php +++ b/webmail/utils/crypt.php @@ -14,9 +14,180 @@ * @package NOCC * @subpackage Utilities * @license http://www.gnu.org/licenses/ GNU General Public License - * @version SVN: $Id: crypt.php 3016 2022-08-25 11:00:42Z oheil $ + * @version SVN: $Id: crypt.php 3097 2023-09-05 10:44:26Z oheil $ */ + +/** + * Returns NTLM Type 3 message + * @param string $type2message the Type 2 message from the server as a binary string + * @param string $realm the clients realm/domain (not empty) + * @param string $workstation the clients host name (not empty) + * @param string $user the SMTP user name + * @param string $password the users password + * @return string $message the binary string composed NTLM Type 3 message to send to the server + */ +function NTLM_type3message($type2message="", $realm="", $workstation="", $user="", $password="") { + // https://davenport.sourceforge.net/ntlm.html + if( strlen($realm)==0 ) { + $realm="unknown"; + } + if( strlen($workstation)==0 ) { + $workstation="unknown"; + } + if( strlen($type2message)==0 ) { + return ""; + } + + $tn_sbuffer=unpack("vlength/vsize/Voffset",substr($type2message,12,8)); + $flags=substr($type2message,20,4); + + $domain=$realm; + if( $flags && 0x0100 ) { // Flag Target Type Domain (0x00010000) in little endian: 0x00000100 + $tn_data=substr($type2message,$tn_sbuffer['offset'],$tn_sbuffer['size']); + $domain=mb_convert_encoding($tn_data,"ASCII","UCS-2LE"); + } + + $challenge=substr($type2message,24,8); + + $pw_uni=mb_convert_encoding($password,"UCS-2LE"); + + $message=""; + + if( extension_loaded("openssl") && function_exists("openssl_encrypt") + && extension_loaded("hash") && function_exists("hash") + && in_array("md4",hash_algos()) + && count( preg_grep("/^des-ecb$/i",openssl_get_cipher_methods(true)) ) > 0 + ) { + $md4=hash("md4", $pw_uni, false); + $md4=hex2bin($md4); + $pad=$md4.str_repeat(chr(0),21-strlen($md4)); + + $iv_size=openssl_cipher_iv_length("des-ecb"); + $iv=""; + for($i=0;$i<21;$i+=7) { + $packed=""; + for($p=$i;$p<$i+7;$p++) { + $packed.=str_pad(decbin(ord(substr($pad,$p,1))),8,"0",STR_PAD_LEFT); + } + $key=""; + for($p=0;$p