From unknown Sat Jun 21 10:39:42 2025 X-Loop: help-debbugs@gnu.org Subject: bug#21358: 25.0.50; Add support for NTLMv2 authentication Resent-From: Thomas Fitzsimmons Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 27 Aug 2015 03:23:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 21358 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: To: 21358@debbugs.gnu.org X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Received: via spool by submit@debbugs.gnu.org id=B.144064577118842 (code B ref -1); Thu, 27 Aug 2015 03:23:02 +0000 Received: (at submit) by debbugs.gnu.org; 27 Aug 2015 03:22:51 +0000 Received: from localhost ([127.0.0.1]:39441 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1ZUnm6-0004tp-QE for submit@debbugs.gnu.org; Wed, 26 Aug 2015 23:22:51 -0400 Received: from eggs.gnu.org ([208.118.235.92]:45191) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1ZUnm4-0004th-Hk for submit@debbugs.gnu.org; Wed, 26 Aug 2015 23:22:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZUnm2-0003Cd-O1 for submit@debbugs.gnu.org; Wed, 26 Aug 2015 23:22:48 -0400 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,LOTS_OF_MONEY autolearn=disabled version=3.3.2 Received: from lists.gnu.org ([2001:4830:134:3::11]:55170) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZUnm2-0003CZ-Kt for submit@debbugs.gnu.org; Wed, 26 Aug 2015 23:22:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55189) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZUnm0-0006Ey-R8 for bug-gnu-emacs@gnu.org; Wed, 26 Aug 2015 23:22:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZUnlx-0003AM-MC for bug-gnu-emacs@gnu.org; Wed, 26 Aug 2015 23:22:44 -0400 Received: from mail-io0-f170.google.com ([209.85.223.170]:34265) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZUnlx-00039j-Gi for bug-gnu-emacs@gnu.org; Wed, 26 Aug 2015 23:22:41 -0400 Received: by iodb91 with SMTP id b91so42743231iod.1 for ; Wed, 26 Aug 2015 20:22:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:user-agent :mime-version:content-type; bh=kM1pWwaVmxhitdKrLCfpJCzxb8PKu/sgq++tU+3yQy4=; b=fdLmKIn33KJh5+jHZeqJKFWOjsGj4usbf8mrMfPQRHgpBN2mSVOP/Ej91c0aBIywIz yOa+RE3Xc1voYNLhoP6drtMdS33XB5htO2w8GXOQXusNfory9e9wXBu8kgyumNq83KrB rPJwiLdzsFd6lHE+OsGJDkdmgZuBa5wG62GKwDTLmoH/+xo8uHSy/zfLWA9287M/NUD+ pSFAoHOB2+nQuPABzanyBEGX1DSiRs17WZmKzNR9oj7fXwM7daxYGG0ILQhgnzUft6EF lSrqL3QCMHE/G6r25wDv1pCpBg5h1cNg34zygxRbIfz3kD5/MhFFKKWRx+vCU31dh6bc Mciw== X-Gm-Message-State: ALoCoQm6cWSxhbEd1UQfyzBkjkjV0+a80R4hnoILPqyqHOir5eSBE1DKZfLE/r/MEWrhv2Cdnwor X-Received: by 10.107.47.193 with SMTP id v62mr8007408iov.13.1440645760598; Wed, 26 Aug 2015 20:22:40 -0700 (PDT) Received: from hp-dv5t (69-165-165-189.dsl.teksavvy.com. [69.165.165.189]) by smtp.gmail.com with ESMTPSA id gz1sm849788igb.16.2015.08.26.20.22.39 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Aug 2015 20:22:39 -0700 (PDT) From: Thomas Fitzsimmons Date: Wed, 26 Aug 2015 23:22:39 -0400 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:4830:134:3::11 X-Spam-Score: -5.0 (-----) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -5.0 (-----) --=-=-= Content-Type: text/plain Hi, This patch implements NTLMv2 authentication in ntlm.el. OK to push? Thanks, Thomas --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Add-support-for-NTLMv2-authentication.patch >From eebf3ec560545f8a1cfa0eb4139eda20b71d90e3 Mon Sep 17 00:00:00 2001 From: Thomas Fitzsimmons Date: Wed, 26 Aug 2015 23:05:25 -0400 Subject: [PATCH] Add support for NTLMv2 authentication * net/ntlm.el (ntlm): New customization group. (ntlm-compatibility-level): New defcustom. (ntlm-compute-timestamp): New function. (ntlm-generate-nonce): Likewise. (ntlm-build-auth-response): Add support for NTLMv2 authentication. --- lisp/net/ntlm.el | 154 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 121 insertions(+), 33 deletions(-) diff --git a/lisp/net/ntlm.el b/lisp/net/ntlm.el index 5f02e29..0a1aaad 100644 --- a/lisp/net/ntlm.el +++ b/lisp/net/ntlm.el @@ -65,6 +65,27 @@ ;;; Code: (require 'md4) +(require 'hmac-md5) +(require 'calc) + +(defgroup ntlm nil + "NTLM (NT LanManager) authentication." + :version "25.1" + :group 'comm) + +(defcustom ntlm-compatibility-level 5 + "The NTLM compatibility level. +Ordered from 0, the oldest, least-secure level through 5, the +newest, most-secure level. Newer servers may reject lower +levels. At levels 3 through 5, send LMv2 and NTLMv2 responses. +At levels 0, 1 and 2, send LM and NTLM responses. + +In this implementation, levels 0, 1 and 2 are the same (old, +insecure), and levels 3, 4 and 5 are the same (new, secure). If +NTLM authentication isn't working at level 5, try level 0. The +other levels are only present because other clients have six +levels." + :type '(choice (const 0) (const 1) (const 2) (const 3) (const 4) (const 5))) ;;; ;;; NTLM authentication interface functions @@ -112,6 +133,39 @@ (eval-when-compile `(string-as-unibyte ,string) string))) +(defun ntlm-compute-timestamp () + "Compute an NTLMv2 timestamp. +Return a unibyte string representing the number of tenths of a +microsecond since January 1, 1601 as a 64-bit little-endian +signed integer." + (let* ((s-to-tenths-of-us "mul(add(lsh($1,16),$2),10000000)") + (us-to-tenths-of-us "mul($3,10)") + (ps-to-tenths-of-us "idiv($4,100000)") + (tenths-of-us-since-jan-1-1601 + (apply 'calc-eval (concat "add(add(add(" + s-to-tenths-of-us "," + us-to-tenths-of-us ")," + ps-to-tenths-of-us ")," + ;; tenths of microseconds between + ;; 1601-01-01 and 1970-01-01 + "116444736000000000)") + ;; add trailing zeros to support old current-time formats + 'rawnum (append (current-time) '(0 0)))) + result-bytes) + (dotimes (byte 8) + (push (calc-eval "and($1,16#FF)" 'rawnum tenths-of-us-since-jan-1-1601) + result-bytes) + (setq tenths-of-us-since-jan-1-1601 + (calc-eval "rsh($1,8,64)" 'rawnum tenths-of-us-since-jan-1-1601))) + (apply 'unibyte-string (nreverse result-bytes)))) + +(defun ntlm-generate-nonce () + "Generate a random nonce, not to be used more than once. +Return a random eight byte unibyte string." + (unibyte-string + (random 256) (random 256) (random 256) (random 256) + (random 256) (random 256) (random 256) (random 256))) + (defun ntlm-build-auth-response (challenge user password-hashes) "Return the response string to a challenge string CHALLENGE given by the NTLM based server for the user USER and the password hash list @@ -128,9 +182,9 @@ (defun ntlm-build-auth-response (challenge user password-hashes) uDomain-len uDomain-offs ;; response struct and its fields lmRespData ;lmRespData, 24 bytes - ntRespData ;ntRespData, 24 bytes + ntRespData ;ntRespData, variable length domain ;ascii domain string - lu ld off-lm off-nt off-d off-u off-w off-s) + lu ld ln off-lm off-nt off-d off-u off-w off-s) ;; extract domain string from challenge string (setq uDomain-len (md4-unpack-int16 (substring uDomain 0 2))) (setq uDomain-offs (md4-unpack-int32 (substring uDomain 4 8))) @@ -144,30 +198,63 @@ (defun ntlm-build-auth-response (challenge user password-hashes) (setq domain (substring user (1+ (match-beginning 0)))) (setq user (substring user 0 (match-beginning 0)))) - ;; check if "negotiate NTLM2 key" flag is set in type 2 message - (if (not (zerop (logand (aref flags 2) 8))) - (let (randomString - sessionHash) - ;; generate NTLM2 session response data - (setq randomString (string-make-unibyte - (concat - (make-string 1 (random 256)) - (make-string 1 (random 256)) - (make-string 1 (random 256)) - (make-string 1 (random 256)) - (make-string 1 (random 256)) - (make-string 1 (random 256)) - (make-string 1 (random 256)) - (make-string 1 (random 256))))) - (setq sessionHash (secure-hash 'md5 - (concat challengeData randomString) - nil nil t)) - (setq sessionHash (substring sessionHash 0 8)) - - (setq lmRespData (concat randomString (make-string 16 0))) - (setq ntRespData (ntlm-smb-owf-encrypt - (cadr password-hashes) sessionHash))) - (progn + (unless (and (integerp ntlm-compatibility-level) + (>= ntlm-compatibility-level 0) + (<= ntlm-compatibility-level 5)) + (error "Invalid ntlm-compatibility-level value")) + (if (and (>= ntlm-compatibility-level 3) + (<= ntlm-compatibility-level 5)) + ;; extract target information block, if it is present + (if (< (cdr uDomain-offs) 48) + (error "Failed to find target information block") + (let* ((targetInfo-len (md4-unpack-int16 (substring rchallenge + 40 42))) + (targetInfo-offs (md4-unpack-int32 (substring rchallenge + 44 48))) + (targetInfo (substring rchallenge + (cdr targetInfo-offs) + (+ (cdr targetInfo-offs) + targetInfo-len))) + (upcase-user (upcase (ntlm-ascii2unicode user (length user)))) + (ntlmv2-hash (hmac-md5 (concat upcase-user + (ntlm-ascii2unicode + domain (length domain))) + (cadr password-hashes))) + (nonce (ntlm-generate-nonce)) + (blob (concat (make-string 2 1) + (make-string 2 0) ; blob signature + (make-string 4 0) ; reserved value + (ntlm-compute-timestamp) ; timestamp + nonce ; client nonce + (make-string 4 0) ; unknown + targetInfo ; target info + (make-string 4 0))) ; unknown + ;; for reference: LMv2 interim calculation + ;; (lm-interim (hmac-md5 (concat challengeData nonce) + ;; ntlmv2-hash)) + (nt-interim (hmac-md5 (concat challengeData blob) + ntlmv2-hash))) + ;; for reference: LMv2 field, but match other clients that + ;; send all zeros + ;; (setq lmRespData (concat lm-interim nonce)) + (setq lmRespData (make-string 24 0)) + (setq ntRespData (concat nt-interim blob)))) + ;; compatibility level is 2, 1 or 0 + ;; level 2 should be treated specially but it's not clear how, + ;; so just treat it the same as levels 0 and 1 + ;; check if "negotiate NTLM2 key" flag is set in type 2 message + (if (not (zerop (logand (aref flags 2) 8))) + (let (randomString + sessionHash) + ;; generate NTLM2 session response data + (setq randomString (ntlm-generate-nonce)) + (setq sessionHash (secure-hash 'md5 + (concat challengeData randomString) + nil nil t)) + (setq sessionHash (substring sessionHash 0 8)) + (setq lmRespData (concat randomString (make-string 16 0))) + (setq ntRespData (ntlm-smb-owf-encrypt + (cadr password-hashes) sessionHash))) ;; generate response data (setq lmRespData (ntlm-smb-owf-encrypt (car password-hashes) challengeData)) @@ -177,12 +264,13 @@ (defun ntlm-build-auth-response (challenge user password-hashes) ;; get offsets to fields to pack the response struct in a string (setq lu (length user)) (setq ld (length domain)) + (setq ln (length ntRespData)) (setq off-lm 64) ;offset to string 'lmResponse (setq off-nt (+ 64 24)) ;offset to string 'ntResponse - (setq off-d (+ 64 48)) ;offset to string 'uDomain - (setq off-u (+ 64 48 (* 2 ld))) ;offset to string 'uUser - (setq off-w (+ 64 48 (* 2 (+ ld lu)))) ;offset to string 'uWks - (setq off-s (+ 64 48 (* 2 (+ ld lu lu)))) ;offset to string 'sessionKey + (setq off-d (+ 64 24 ln)) ;offset to string 'uDomain + (setq off-u (+ 64 24 ln (* 2 ld))) ;offset to string 'uUser + (setq off-w (+ 64 24 ln (* 2 (+ ld lu)))) ;offset to string 'uWks + (setq off-s (+ 64 24 ln (* 2 (+ ld lu lu)))) ;offset to string 'sessionKey ;; pack the response struct in a string (concat "NTLMSSP\0" ;response ident field, 8 bytes (md4-pack-int32 '(0 . 3)) ;response msgType field, 4 bytes @@ -194,9 +282,9 @@ (defun ntlm-build-auth-response (challenge user password-hashes) (md4-pack-int32 (cons 0 off-lm)) ;field offset ;; ntResponse field, 8 bytes - ;;AddBytes(response,ntResponse,ntRespData,24); - (md4-pack-int16 24) ;len field - (md4-pack-int16 24) ;maxlen field + ;;AddBytes(response,ntResponse,ntRespData,ln); + (md4-pack-int16 ln) ;len field + (md4-pack-int16 ln) ;maxlen field (md4-pack-int32 (cons 0 off-nt)) ;field offset ;; uDomain field, 8 bytes -- 2.4.2 --=-=-=-- From unknown Sat Jun 21 10:39:42 2025 X-Loop: help-debbugs@gnu.org Subject: bug#21358: 25.0.50; Add support for NTLMv2 authentication Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 29 Aug 2015 15:26:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 21358 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch To: Thomas Fitzsimmons Cc: 21358@debbugs.gnu.org Received: via spool by 21358-submit@debbugs.gnu.org id=B21358.14408619539229 (code B ref 21358); Sat, 29 Aug 2015 15:26:01 +0000 Received: (at 21358) by debbugs.gnu.org; 29 Aug 2015 15:25:53 +0000 Received: from localhost ([127.0.0.1]:42217 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1ZVi0v-0002On-5Q for submit@debbugs.gnu.org; Sat, 29 Aug 2015 11:25:53 -0400 Received: from ironport2-out.teksavvy.com ([206.248.154.181]:28168) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1ZVi0t-0002Of-Dk for 21358@debbugs.gnu.org; Sat, 29 Aug 2015 11:25:51 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0A2FgA731xV/8Fw3mhcgxCEAoVVu0CEfoJNBAICgTw7EgEBAQEBAQGBCkEFg10BAQMBViMFCwsOJhIUGA0kiDcIzyMBAQEBAQEEAQEBAR6LOoUFB4QtBbUEI4QUIoJ4AQEB X-IPAS-Result: A0A2FgA731xV/8Fw3mhcgxCEAoVVu0CEfoJNBAICgTw7EgEBAQEBAQGBCkEFg10BAQMBViMFCwsOJhIUGA0kiDcIzyMBAQEBAQEEAQEBAR6LOoUFB4QtBbUEI4QUIoJ4AQEB X-IronPort-AV: E=Sophos;i="5.13,465,1427774400"; d="scan'208";a="161793366" Received: from 104-222-112-193.cpe.teksavvy.com (HELO ceviche.home) ([104.222.112.193]) by ironport2-out.teksavvy.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 29 Aug 2015 11:25:50 -0400 Received: by ceviche.home (Postfix, from userid 20848) id BD2766615C; Sat, 29 Aug 2015 11:25:50 -0400 (EDT) From: Stefan Monnier Message-ID: References: Date: Sat, 29 Aug 2015 11:25:50 -0400 In-Reply-To: (Thomas Fitzsimmons's message of "Wed, 26 Aug 2015 23:22:39 -0400") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 0.3 (/) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 0.3 (/) > This patch implements NTLMv2 authentication in ntlm.el. OK to push? According to the Git log, this file has seen no local changes other than cosmetic tweaks like updating the copyright years. So I suspect that noone knows any better than you do. IOW, I think it's OK to push, Stefan From unknown Sat Jun 21 10:39:42 2025 MIME-Version: 1.0 X-Mailer: MIME-tools 5.503 (Entity 5.503) X-Loop: help-debbugs@gnu.org From: help-debbugs@gnu.org (GNU bug Tracking System) To: Thomas Fitzsimmons Subject: bug#21358: closed (Re: bug#21358: 25.0.50; Add support for NTLMv2 authentication) Message-ID: References: X-Gnu-PR-Message: they-closed 21358 X-Gnu-PR-Package: emacs X-Gnu-PR-Keywords: patch Reply-To: 21358@debbugs.gnu.org Date: Sun, 06 Sep 2015 22:37:02 +0000 Content-Type: multipart/mixed; boundary="----------=_1441579022-5985-1" This is a multi-part message in MIME format... ------------=_1441579022-5985-1 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Your bug report #21358: 25.0.50; Add support for NTLMv2 authentication which was filed against the emacs package, has been closed. The explanation is attached below, along with your original report. If you require more details, please reply to 21358@debbugs.gnu.org. --=20 21358: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=3D21358 GNU Bug Tracking System Contact help-debbugs@gnu.org with problems ------------=_1441579022-5985-1 Content-Type: message/rfc822 Content-Disposition: inline Content-Transfer-Encoding: 7bit Received: (at 21358-done) by debbugs.gnu.org; 6 Sep 2015 22:36:05 +0000 Received: from localhost ([127.0.0.1]:50990 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1ZYiXc-0001XG-W2 for submit@debbugs.gnu.org; Sun, 06 Sep 2015 18:36:05 -0400 Received: from mail-io0-f181.google.com ([209.85.223.181]:36015) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1ZYiXb-0001X6-8R for 21358-done@debbugs.gnu.org; Sun, 06 Sep 2015 18:36:03 -0400 Received: by ioii196 with SMTP id i196so72122673ioi.3 for <21358-done@debbugs.gnu.org>; Sun, 06 Sep 2015 15:36:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version:content-type; bh=rMQmxcBx1w/FsMSDEORkduUa1s2xV9nMrOdeVEnsop8=; b=Tlak5pjl6angbfTgcGwDhE2URAxz1bq8n7kAXdxdiU2XpvUFFEjnFmjb0llWzzlx5c cbV5vZcop2poYvwxNJjWZSXJRCO8tKnmhnNS3bsD5/Lr5RwFhBeadelRpXJXkNDqhmAM r+aEvLYvcFw1Uy6PDr6fIxPPX0EUZt+c7lVLFvlzhVPlORJfZEPtyHV6FspRnMfNCLUD 6m9YKuBXvlcjz8hhPAWuoQIvUlzu0n42nat07ltfHVOuaZ7TcZhM8CUE74t8J1gSwH2S vFA2EQ8VNKxsLudg204pKxHvg/FdDtU6meJfUBGmjJMvgO3LtSso0njCl7YUwzmPCSnR ypeQ== X-Gm-Message-State: ALoCoQkPevpYr+8pyuGgW2z/27ugHw/cOnSF67gtriBNlcaYv6GRww8svBgf3Jz0XatcTz8tIslM X-Received: by 10.107.6.65 with SMTP id 62mr26679923iog.147.1441578962692; Sun, 06 Sep 2015 15:36:02 -0700 (PDT) Received: from hp-dv5t (69-165-165-189.dsl.teksavvy.com. [69.165.165.189]) by smtp.gmail.com with ESMTPSA id s14sm1953167ioe.12.2015.09.06.15.36.01 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 06 Sep 2015 15:36:02 -0700 (PDT) From: Thomas Fitzsimmons To: Stefan Monnier Subject: Re: bug#21358: 25.0.50; Add support for NTLMv2 authentication References: Date: Sun, 06 Sep 2015 18:36:00 -0400 In-Reply-To: (Stefan Monnier's message of "Sat, 29 Aug 2015 11:25:50 -0400") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 21358-done Cc: 21358-done@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.7 (/) fixed 21358 25.1 thanks Stefan Monnier writes: >> This patch implements NTLMv2 authentication in ntlm.el. OK to push? > > According to the Git log, this file has seen no local changes other than > cosmetic tweaks like updating the copyright years. So I suspect that > noone knows any better than you do. > > IOW, I think it's OK to push, Pushed, closing. I'm also going to bump the version to 2.00, add the "comm" keyword and add myself as the maintainer, then push the same file to GNU ELPA for use by pre-25.1 versions of Emacs. Thanks, Thomas ------------=_1441579022-5985-1 Content-Type: message/rfc822 Content-Disposition: inline Content-Transfer-Encoding: 7bit Received: (at submit) by debbugs.gnu.org; 27 Aug 2015 03:22:51 +0000 Received: from localhost ([127.0.0.1]:39441 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1ZUnm6-0004tp-QE for submit@debbugs.gnu.org; Wed, 26 Aug 2015 23:22:51 -0400 Received: from eggs.gnu.org ([208.118.235.92]:45191) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1ZUnm4-0004th-Hk for submit@debbugs.gnu.org; Wed, 26 Aug 2015 23:22:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZUnm2-0003Cd-O1 for submit@debbugs.gnu.org; Wed, 26 Aug 2015 23:22:48 -0400 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,LOTS_OF_MONEY autolearn=disabled version=3.3.2 Received: from lists.gnu.org ([2001:4830:134:3::11]:55170) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZUnm2-0003CZ-Kt for submit@debbugs.gnu.org; Wed, 26 Aug 2015 23:22:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55189) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZUnm0-0006Ey-R8 for bug-gnu-emacs@gnu.org; Wed, 26 Aug 2015 23:22:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZUnlx-0003AM-MC for bug-gnu-emacs@gnu.org; Wed, 26 Aug 2015 23:22:44 -0400 Received: from mail-io0-f170.google.com ([209.85.223.170]:34265) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZUnlx-00039j-Gi for bug-gnu-emacs@gnu.org; Wed, 26 Aug 2015 23:22:41 -0400 Received: by iodb91 with SMTP id b91so42743231iod.1 for ; Wed, 26 Aug 2015 20:22:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:user-agent :mime-version:content-type; bh=kM1pWwaVmxhitdKrLCfpJCzxb8PKu/sgq++tU+3yQy4=; b=fdLmKIn33KJh5+jHZeqJKFWOjsGj4usbf8mrMfPQRHgpBN2mSVOP/Ej91c0aBIywIz yOa+RE3Xc1voYNLhoP6drtMdS33XB5htO2w8GXOQXusNfory9e9wXBu8kgyumNq83KrB rPJwiLdzsFd6lHE+OsGJDkdmgZuBa5wG62GKwDTLmoH/+xo8uHSy/zfLWA9287M/NUD+ pSFAoHOB2+nQuPABzanyBEGX1DSiRs17WZmKzNR9oj7fXwM7daxYGG0ILQhgnzUft6EF lSrqL3QCMHE/G6r25wDv1pCpBg5h1cNg34zygxRbIfz3kD5/MhFFKKWRx+vCU31dh6bc Mciw== X-Gm-Message-State: ALoCoQm6cWSxhbEd1UQfyzBkjkjV0+a80R4hnoILPqyqHOir5eSBE1DKZfLE/r/MEWrhv2Cdnwor X-Received: by 10.107.47.193 with SMTP id v62mr8007408iov.13.1440645760598; Wed, 26 Aug 2015 20:22:40 -0700 (PDT) Received: from hp-dv5t (69-165-165-189.dsl.teksavvy.com. [69.165.165.189]) by smtp.gmail.com with ESMTPSA id gz1sm849788igb.16.2015.08.26.20.22.39 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 26 Aug 2015 20:22:39 -0700 (PDT) From: Thomas Fitzsimmons To: bug-gnu-emacs@gnu.org Subject: 25.0.50; Add support for NTLMv2 authentication Date: Wed, 26 Aug 2015 23:22:39 -0400 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:4830:134:3::11 X-Spam-Score: -5.0 (-----) X-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -5.0 (-----) --=-=-= Content-Type: text/plain Hi, This patch implements NTLMv2 authentication in ntlm.el. OK to push? Thanks, Thomas --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Add-support-for-NTLMv2-authentication.patch >From eebf3ec560545f8a1cfa0eb4139eda20b71d90e3 Mon Sep 17 00:00:00 2001 From: Thomas Fitzsimmons Date: Wed, 26 Aug 2015 23:05:25 -0400 Subject: [PATCH] Add support for NTLMv2 authentication * net/ntlm.el (ntlm): New customization group. (ntlm-compatibility-level): New defcustom. (ntlm-compute-timestamp): New function. (ntlm-generate-nonce): Likewise. (ntlm-build-auth-response): Add support for NTLMv2 authentication. --- lisp/net/ntlm.el | 154 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 121 insertions(+), 33 deletions(-) diff --git a/lisp/net/ntlm.el b/lisp/net/ntlm.el index 5f02e29..0a1aaad 100644 --- a/lisp/net/ntlm.el +++ b/lisp/net/ntlm.el @@ -65,6 +65,27 @@ ;;; Code: (require 'md4) +(require 'hmac-md5) +(require 'calc) + +(defgroup ntlm nil + "NTLM (NT LanManager) authentication." + :version "25.1" + :group 'comm) + +(defcustom ntlm-compatibility-level 5 + "The NTLM compatibility level. +Ordered from 0, the oldest, least-secure level through 5, the +newest, most-secure level. Newer servers may reject lower +levels. At levels 3 through 5, send LMv2 and NTLMv2 responses. +At levels 0, 1 and 2, send LM and NTLM responses. + +In this implementation, levels 0, 1 and 2 are the same (old, +insecure), and levels 3, 4 and 5 are the same (new, secure). If +NTLM authentication isn't working at level 5, try level 0. The +other levels are only present because other clients have six +levels." + :type '(choice (const 0) (const 1) (const 2) (const 3) (const 4) (const 5))) ;;; ;;; NTLM authentication interface functions @@ -112,6 +133,39 @@ (eval-when-compile `(string-as-unibyte ,string) string))) +(defun ntlm-compute-timestamp () + "Compute an NTLMv2 timestamp. +Return a unibyte string representing the number of tenths of a +microsecond since January 1, 1601 as a 64-bit little-endian +signed integer." + (let* ((s-to-tenths-of-us "mul(add(lsh($1,16),$2),10000000)") + (us-to-tenths-of-us "mul($3,10)") + (ps-to-tenths-of-us "idiv($4,100000)") + (tenths-of-us-since-jan-1-1601 + (apply 'calc-eval (concat "add(add(add(" + s-to-tenths-of-us "," + us-to-tenths-of-us ")," + ps-to-tenths-of-us ")," + ;; tenths of microseconds between + ;; 1601-01-01 and 1970-01-01 + "116444736000000000)") + ;; add trailing zeros to support old current-time formats + 'rawnum (append (current-time) '(0 0)))) + result-bytes) + (dotimes (byte 8) + (push (calc-eval "and($1,16#FF)" 'rawnum tenths-of-us-since-jan-1-1601) + result-bytes) + (setq tenths-of-us-since-jan-1-1601 + (calc-eval "rsh($1,8,64)" 'rawnum tenths-of-us-since-jan-1-1601))) + (apply 'unibyte-string (nreverse result-bytes)))) + +(defun ntlm-generate-nonce () + "Generate a random nonce, not to be used more than once. +Return a random eight byte unibyte string." + (unibyte-string + (random 256) (random 256) (random 256) (random 256) + (random 256) (random 256) (random 256) (random 256))) + (defun ntlm-build-auth-response (challenge user password-hashes) "Return the response string to a challenge string CHALLENGE given by the NTLM based server for the user USER and the password hash list @@ -128,9 +182,9 @@ (defun ntlm-build-auth-response (challenge user password-hashes) uDomain-len uDomain-offs ;; response struct and its fields lmRespData ;lmRespData, 24 bytes - ntRespData ;ntRespData, 24 bytes + ntRespData ;ntRespData, variable length domain ;ascii domain string - lu ld off-lm off-nt off-d off-u off-w off-s) + lu ld ln off-lm off-nt off-d off-u off-w off-s) ;; extract domain string from challenge string (setq uDomain-len (md4-unpack-int16 (substring uDomain 0 2))) (setq uDomain-offs (md4-unpack-int32 (substring uDomain 4 8))) @@ -144,30 +198,63 @@ (defun ntlm-build-auth-response (challenge user password-hashes) (setq domain (substring user (1+ (match-beginning 0)))) (setq user (substring user 0 (match-beginning 0)))) - ;; check if "negotiate NTLM2 key" flag is set in type 2 message - (if (not (zerop (logand (aref flags 2) 8))) - (let (randomString - sessionHash) - ;; generate NTLM2 session response data - (setq randomString (string-make-unibyte - (concat - (make-string 1 (random 256)) - (make-string 1 (random 256)) - (make-string 1 (random 256)) - (make-string 1 (random 256)) - (make-string 1 (random 256)) - (make-string 1 (random 256)) - (make-string 1 (random 256)) - (make-string 1 (random 256))))) - (setq sessionHash (secure-hash 'md5 - (concat challengeData randomString) - nil nil t)) - (setq sessionHash (substring sessionHash 0 8)) - - (setq lmRespData (concat randomString (make-string 16 0))) - (setq ntRespData (ntlm-smb-owf-encrypt - (cadr password-hashes) sessionHash))) - (progn + (unless (and (integerp ntlm-compatibility-level) + (>= ntlm-compatibility-level 0) + (<= ntlm-compatibility-level 5)) + (error "Invalid ntlm-compatibility-level value")) + (if (and (>= ntlm-compatibility-level 3) + (<= ntlm-compatibility-level 5)) + ;; extract target information block, if it is present + (if (< (cdr uDomain-offs) 48) + (error "Failed to find target information block") + (let* ((targetInfo-len (md4-unpack-int16 (substring rchallenge + 40 42))) + (targetInfo-offs (md4-unpack-int32 (substring rchallenge + 44 48))) + (targetInfo (substring rchallenge + (cdr targetInfo-offs) + (+ (cdr targetInfo-offs) + targetInfo-len))) + (upcase-user (upcase (ntlm-ascii2unicode user (length user)))) + (ntlmv2-hash (hmac-md5 (concat upcase-user + (ntlm-ascii2unicode + domain (length domain))) + (cadr password-hashes))) + (nonce (ntlm-generate-nonce)) + (blob (concat (make-string 2 1) + (make-string 2 0) ; blob signature + (make-string 4 0) ; reserved value + (ntlm-compute-timestamp) ; timestamp + nonce ; client nonce + (make-string 4 0) ; unknown + targetInfo ; target info + (make-string 4 0))) ; unknown + ;; for reference: LMv2 interim calculation + ;; (lm-interim (hmac-md5 (concat challengeData nonce) + ;; ntlmv2-hash)) + (nt-interim (hmac-md5 (concat challengeData blob) + ntlmv2-hash))) + ;; for reference: LMv2 field, but match other clients that + ;; send all zeros + ;; (setq lmRespData (concat lm-interim nonce)) + (setq lmRespData (make-string 24 0)) + (setq ntRespData (concat nt-interim blob)))) + ;; compatibility level is 2, 1 or 0 + ;; level 2 should be treated specially but it's not clear how, + ;; so just treat it the same as levels 0 and 1 + ;; check if "negotiate NTLM2 key" flag is set in type 2 message + (if (not (zerop (logand (aref flags 2) 8))) + (let (randomString + sessionHash) + ;; generate NTLM2 session response data + (setq randomString (ntlm-generate-nonce)) + (setq sessionHash (secure-hash 'md5 + (concat challengeData randomString) + nil nil t)) + (setq sessionHash (substring sessionHash 0 8)) + (setq lmRespData (concat randomString (make-string 16 0))) + (setq ntRespData (ntlm-smb-owf-encrypt + (cadr password-hashes) sessionHash))) ;; generate response data (setq lmRespData (ntlm-smb-owf-encrypt (car password-hashes) challengeData)) @@ -177,12 +264,13 @@ (defun ntlm-build-auth-response (challenge user password-hashes) ;; get offsets to fields to pack the response struct in a string (setq lu (length user)) (setq ld (length domain)) + (setq ln (length ntRespData)) (setq off-lm 64) ;offset to string 'lmResponse (setq off-nt (+ 64 24)) ;offset to string 'ntResponse - (setq off-d (+ 64 48)) ;offset to string 'uDomain - (setq off-u (+ 64 48 (* 2 ld))) ;offset to string 'uUser - (setq off-w (+ 64 48 (* 2 (+ ld lu)))) ;offset to string 'uWks - (setq off-s (+ 64 48 (* 2 (+ ld lu lu)))) ;offset to string 'sessionKey + (setq off-d (+ 64 24 ln)) ;offset to string 'uDomain + (setq off-u (+ 64 24 ln (* 2 ld))) ;offset to string 'uUser + (setq off-w (+ 64 24 ln (* 2 (+ ld lu)))) ;offset to string 'uWks + (setq off-s (+ 64 24 ln (* 2 (+ ld lu lu)))) ;offset to string 'sessionKey ;; pack the response struct in a string (concat "NTLMSSP\0" ;response ident field, 8 bytes (md4-pack-int32 '(0 . 3)) ;response msgType field, 4 bytes @@ -194,9 +282,9 @@ (defun ntlm-build-auth-response (challenge user password-hashes) (md4-pack-int32 (cons 0 off-lm)) ;field offset ;; ntResponse field, 8 bytes - ;;AddBytes(response,ntResponse,ntRespData,24); - (md4-pack-int16 24) ;len field - (md4-pack-int16 24) ;maxlen field + ;;AddBytes(response,ntResponse,ntRespData,ln); + (md4-pack-int16 ln) ;len field + (md4-pack-int16 ln) ;maxlen field (md4-pack-int32 (cons 0 off-nt)) ;field offset ;; uDomain field, 8 bytes -- 2.4.2 --=-=-=-- ------------=_1441579022-5985-1--