diff options
Diffstat (limited to 'Emby.Server.Implementations/IO/SharpCifs/Smb/NtlmPasswordAuthentication.cs')
| -rw-r--r-- | Emby.Server.Implementations/IO/SharpCifs/Smb/NtlmPasswordAuthentication.cs | 807 |
1 files changed, 0 insertions, 807 deletions
diff --git a/Emby.Server.Implementations/IO/SharpCifs/Smb/NtlmPasswordAuthentication.cs b/Emby.Server.Implementations/IO/SharpCifs/Smb/NtlmPasswordAuthentication.cs deleted file mode 100644 index ec3899fe9..000000000 --- a/Emby.Server.Implementations/IO/SharpCifs/Smb/NtlmPasswordAuthentication.cs +++ /dev/null @@ -1,807 +0,0 @@ -// This code is derived from jcifs smb client library <jcifs at samba dot org> -// Ported by J. Arturo <webmaster at komodosoft dot net> -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -using System; -using SharpCifs.Util; -using SharpCifs.Util.Sharpen; - -namespace SharpCifs.Smb -{ - /// <summary>This class stores and encrypts NTLM user credentials.</summary> - /// <remarks> - /// This class stores and encrypts NTLM user credentials. The default - /// credentials are retrieved from the <tt>jcifs.smb.client.domain</tt>, - /// <tt>jcifs.smb.client.username</tt>, and <tt>jcifs.smb.client.password</tt> - /// properties. - /// <p> - /// Read <a href="../../../authhandler.html">jCIFS Exceptions and - /// NtlmAuthenticator</a> for related information. - /// </remarks> - - public sealed class NtlmPasswordAuthentication : Principal - { - private static readonly int LmCompatibility = Config.GetInt("jcifs.smb.lmCompatibility" - , 3); - - private static readonly Random Random = new Random(); - - private static LogStream _log = LogStream.GetInstance(); - - private static readonly byte[] S8 = { unchecked(unchecked(0x4b)), unchecked(unchecked(0x47)), unchecked(unchecked(0x53)), unchecked(unchecked(0x21)), unchecked(unchecked(0x40)), unchecked(unchecked(0x23)), unchecked(unchecked(0x24)), unchecked(unchecked(0x25)) }; - - // KGS!@#$% - private static void E(byte[] key, byte[] data, byte[] e) - { - byte[] key7 = new byte[7]; - byte[] e8 = new byte[8]; - for (int i = 0; i < key.Length / 7; i++) - { - Array.Copy(key, i * 7, key7, 0, 7); - DES des = new DES(key7); - des.Encrypt(data, e8); - Array.Copy(e8, 0, e, i * 8, 8); - } - } - - internal static string DefaultDomain; - - internal static string DefaultUsername; - - internal static string DefaultPassword; - - internal static readonly string Blank = string.Empty; - - public static readonly NtlmPasswordAuthentication Anonymous = new NtlmPasswordAuthentication - (string.Empty, string.Empty, string.Empty); - - internal static void InitDefaults() - { - if (DefaultDomain != null) - { - return; - } - DefaultDomain = Config.GetProperty("jcifs.smb.client.domain", "?"); - DefaultUsername = Config.GetProperty("jcifs.smb.client.username", "GUEST"); - DefaultPassword = Config.GetProperty("jcifs.smb.client.password", Blank); - } - - /// <summary>Generate the ANSI DES hash for the password associated with these credentials. - /// </summary> - /// <remarks>Generate the ANSI DES hash for the password associated with these credentials. - /// </remarks> - public static byte[] GetPreNtlmResponse(string password, byte[] challenge) - { - byte[] p14 = new byte[14]; - byte[] p21 = new byte[21]; - byte[] p24 = new byte[24]; - byte[] passwordBytes; - try - { - passwordBytes = Runtime.GetBytesForString(password.ToUpper(), SmbConstants.OemEncoding); - } - catch (UnsupportedEncodingException uee) - { - throw new RuntimeException("Try setting jcifs.encoding=US-ASCII", uee); - } - int passwordLength = passwordBytes.Length; - // Only encrypt the first 14 bytes of the password for Pre 0.12 NT LM - if (passwordLength > 14) - { - passwordLength = 14; - } - Array.Copy(passwordBytes, 0, p14, 0, passwordLength); - E(p14, S8, p21); - E(p21, challenge, p24); - return p24; - } - - /// <summary>Generate the Unicode MD4 hash for the password associated with these credentials. - /// </summary> - /// <remarks>Generate the Unicode MD4 hash for the password associated with these credentials. - /// </remarks> - public static byte[] GetNtlmResponse(string password, byte[] challenge) - { - byte[] uni = null; - byte[] p21 = new byte[21]; - byte[] p24 = new byte[24]; - try - { - uni = Runtime.GetBytesForString(password, SmbConstants.UniEncoding); - } - catch (UnsupportedEncodingException uee) - { - if (_log.Level > 0) - { - Runtime.PrintStackTrace(uee, _log); - } - } - Md4 md4 = new Md4(); - md4.Update(uni); - try - { - md4.Digest(p21, 0, 16); - } - catch (Exception ex) - { - if (_log.Level > 0) - { - Runtime.PrintStackTrace(ex, _log); - } - } - E(p21, challenge, p24); - return p24; - } - - /// <summary>Creates the LMv2 response for the supplied information.</summary> - /// <remarks>Creates the LMv2 response for the supplied information.</remarks> - /// <param name="domain">The domain in which the username exists.</param> - /// <param name="user">The username.</param> - /// <param name="password">The user's password.</param> - /// <param name="challenge">The server challenge.</param> - /// <param name="clientChallenge">The client challenge (nonce).</param> - public static byte[] GetLMv2Response(string domain, string user, string password, - byte[] challenge, byte[] clientChallenge) - { - try - { - byte[] hash = new byte[16]; - byte[] response = new byte[24]; - // The next 2-1/2 lines of this should be placed with nTOWFv1 in place of password - Md4 md4 = new Md4(); - md4.Update(Runtime.GetBytesForString(password, SmbConstants.UniEncoding) - ); - Hmact64 hmac = new Hmact64(md4.Digest()); - hmac.Update(Runtime.GetBytesForString(user.ToUpper(), SmbConstants.UniEncoding - )); - hmac.Update(Runtime.GetBytesForString(domain.ToUpper(), SmbConstants.UniEncoding - )); - hmac = new Hmact64(hmac.Digest()); - hmac.Update(challenge); - hmac.Update(clientChallenge); - hmac.Digest(response, 0, 16); - Array.Copy(clientChallenge, 0, response, 16, 8); - return response; - } - catch (Exception ex) - { - if (_log.Level > 0) - { - Runtime.PrintStackTrace(ex, _log); - } - return null; - } - } - - public static byte[] GetNtlm2Response(byte[] nTowFv1, byte[] serverChallenge, byte - [] clientChallenge) - { - byte[] sessionHash = new byte[8]; - try - { - MessageDigest md5; - md5 = MessageDigest.GetInstance("MD5"); - md5.Update(serverChallenge); - md5.Update(clientChallenge, 0, 8); - Array.Copy(md5.Digest(), 0, sessionHash, 0, 8); - } - catch (Exception gse) - { - if (_log.Level > 0) - { - Runtime.PrintStackTrace(gse, _log); - } - throw new RuntimeException("MD5", gse); - } - byte[] key = new byte[21]; - Array.Copy(nTowFv1, 0, key, 0, 16); - byte[] ntResponse = new byte[24]; - E(key, sessionHash, ntResponse); - return ntResponse; - } - - public static byte[] NtowFv1(string password) - { - if (password == null) - { - throw new RuntimeException("Password parameter is required"); - } - try - { - Md4 md4 = new Md4(); - md4.Update(Runtime.GetBytesForString(password, SmbConstants.UniEncoding) - ); - return md4.Digest(); - } - catch (UnsupportedEncodingException uee) - { - throw new RuntimeException(uee.Message); - } - } - - public static byte[] NtowFv2(string domain, string username, string password) - { - try - { - Md4 md4 = new Md4(); - md4.Update(Runtime.GetBytesForString(password, SmbConstants.UniEncoding) - ); - Hmact64 hmac = new Hmact64(md4.Digest()); - hmac.Update(Runtime.GetBytesForString(username.ToUpper(), SmbConstants.UniEncoding - )); - hmac.Update(Runtime.GetBytesForString(domain, SmbConstants.UniEncoding)); - return hmac.Digest(); - } - catch (UnsupportedEncodingException uee) - { - throw new RuntimeException(uee.Message); - } - } - - internal static byte[] ComputeResponse(byte[] responseKey, byte[] serverChallenge - , byte[] clientData, int offset, int length) - { - Hmact64 hmac = new Hmact64(responseKey); - hmac.Update(serverChallenge); - hmac.Update(clientData, offset, length); - byte[] mac = hmac.Digest(); - byte[] ret = new byte[mac.Length + clientData.Length]; - Array.Copy(mac, 0, ret, 0, mac.Length); - Array.Copy(clientData, 0, ret, mac.Length, clientData.Length); - return ret; - } - - public static byte[] GetLMv2Response(byte[] responseKeyLm, byte[] serverChallenge - , byte[] clientChallenge) - { - return ComputeResponse(responseKeyLm, serverChallenge - , clientChallenge, 0, clientChallenge.Length); - } - - public static byte[] GetNtlMv2Response(byte[] responseKeyNt, byte[] serverChallenge - , byte[] clientChallenge, long nanos1601, byte[] targetInfo) - { - int targetInfoLength = targetInfo != null ? targetInfo.Length : 0; - byte[] temp = new byte[28 + targetInfoLength + 4]; - Encdec.Enc_uint32le(unchecked(0x00000101), temp, 0); - // Header - Encdec.Enc_uint32le(unchecked(0x00000000), temp, 4); - // Reserved - Encdec.Enc_uint64le(nanos1601, temp, 8); - Array.Copy(clientChallenge, 0, temp, 16, 8); - Encdec.Enc_uint32le(unchecked(0x00000000), temp, 24); - // Unknown - if (targetInfo != null) - { - Array.Copy(targetInfo, 0, temp, 28, targetInfoLength); - } - Encdec.Enc_uint32le(unchecked(0x00000000), temp, 28 + targetInfoLength); - // mystery bytes! - return ComputeResponse(responseKeyNt, serverChallenge - , temp, 0, temp.Length); - } - - internal static readonly NtlmPasswordAuthentication Null = new NtlmPasswordAuthentication - (string.Empty, string.Empty, string.Empty); - - internal static readonly NtlmPasswordAuthentication Guest = new NtlmPasswordAuthentication - ("?", "GUEST", string.Empty); - - internal static readonly NtlmPasswordAuthentication Default = new NtlmPasswordAuthentication - (null); - - internal string Domain; - - internal string Username; - - internal string Password; - - internal byte[] AnsiHash; - - internal byte[] UnicodeHash; - - internal bool HashesExternal; - - internal byte[] ClientChallenge; - - internal byte[] Challenge; - - /// <summary> - /// Create an <tt>NtlmPasswordAuthentication</tt> object from the userinfo - /// component of an SMB URL like "<tt>domain;user:pass</tt>". - /// </summary> - /// <remarks> - /// Create an <tt>NtlmPasswordAuthentication</tt> object from the userinfo - /// component of an SMB URL like "<tt>domain;user:pass</tt>". This constructor - /// is used internally be jCIFS when parsing SMB URLs. - /// </remarks> - public NtlmPasswordAuthentication(string userInfo) - { - Domain = Username = Password = null; - if (userInfo != null) - { - try - { - userInfo = Unescape(userInfo); - } - catch (UnsupportedEncodingException) - { - } - int i; - int u; - int end; - char c; - end = userInfo.Length; - for (i = 0, u = 0; i < end; i++) - { - c = userInfo[i]; - if (c == ';') - { - Domain = Runtime.Substring(userInfo, 0, i); - u = i + 1; - } - else - { - if (c == ':') - { - Password = Runtime.Substring(userInfo, i + 1); - break; - } - } - } - Username = Runtime.Substring(userInfo, u, i); - } - InitDefaults(); - if (Domain == null) - { - Domain = DefaultDomain; - } - if (Username == null) - { - Username = DefaultUsername; - } - if (Password == null) - { - Password = DefaultPassword; - } - } - - /// <summary> - /// Create an <tt>NtlmPasswordAuthentication</tt> object from a - /// domain, username, and password. - /// </summary> - /// <remarks> - /// Create an <tt>NtlmPasswordAuthentication</tt> object from a - /// domain, username, and password. Parameters that are <tt>null</tt> - /// will be substituted with <tt>jcifs.smb.client.domain</tt>, - /// <tt>jcifs.smb.client.username</tt>, <tt>jcifs.smb.client.password</tt> - /// property values. - /// </remarks> - public NtlmPasswordAuthentication(string domain, string username, string password - ) - { - int ci; - if (username != null) - { - ci = username.IndexOf('@'); - if (ci > 0) - { - domain = Runtime.Substring(username, ci + 1); - username = Runtime.Substring(username, 0, ci); - } - else - { - ci = username.IndexOf('\\'); - if (ci > 0) - { - domain = Runtime.Substring(username, 0, ci); - username = Runtime.Substring(username, ci + 1); - } - } - } - this.Domain = domain; - this.Username = username; - this.Password = password; - InitDefaults(); - if (domain == null) - { - this.Domain = DefaultDomain; - } - if (username == null) - { - this.Username = DefaultUsername; - } - if (password == null) - { - this.Password = DefaultPassword; - } - } - - /// <summary> - /// Create an <tt>NtlmPasswordAuthentication</tt> object with raw password - /// hashes. - /// </summary> - /// <remarks> - /// Create an <tt>NtlmPasswordAuthentication</tt> object with raw password - /// hashes. This is used exclusively by the <tt>jcifs.http.NtlmSsp</tt> - /// class which is in turn used by NTLM HTTP authentication functionality. - /// </remarks> - public NtlmPasswordAuthentication(string domain, string username, byte[] challenge - , byte[] ansiHash, byte[] unicodeHash) - { - if (domain == null || username == null || ansiHash == null || unicodeHash == null) - { - throw new ArgumentException("External credentials cannot be null"); - } - this.Domain = domain; - this.Username = username; - Password = null; - this.Challenge = challenge; - this.AnsiHash = ansiHash; - this.UnicodeHash = unicodeHash; - HashesExternal = true; - } - - /// <summary>Returns the domain.</summary> - /// <remarks>Returns the domain.</remarks> - public string GetDomain() - { - return Domain; - } - - /// <summary>Returns the username.</summary> - /// <remarks>Returns the username.</remarks> - public string GetUsername() - { - return Username; - } - - /// <summary> - /// Returns the password in plain text or <tt>null</tt> if the raw password - /// hashes were used to construct this <tt>NtlmPasswordAuthentication</tt> - /// object which will be the case when NTLM HTTP Authentication is - /// used. - /// </summary> - /// <remarks> - /// Returns the password in plain text or <tt>null</tt> if the raw password - /// hashes were used to construct this <tt>NtlmPasswordAuthentication</tt> - /// object which will be the case when NTLM HTTP Authentication is - /// used. There is no way to retrieve a users password in plain text unless - /// it is supplied by the user at runtime. - /// </remarks> - public string GetPassword() - { - return Password; - } - - /// <summary> - /// Return the domain and username in the format: - /// <tt>domain\\username</tt>. - /// </summary> - /// <remarks> - /// Return the domain and username in the format: - /// <tt>domain\\username</tt>. This is equivalent to <tt>toString()</tt>. - /// </remarks> - public new string GetName() - { - bool d = Domain.Length > 0 && Domain.Equals("?") == false; - return d ? Domain + "\\" + Username : Username; - } - - /// <summary>Computes the 24 byte ANSI password hash given the 8 byte server challenge. - /// </summary> - /// <remarks>Computes the 24 byte ANSI password hash given the 8 byte server challenge. - /// </remarks> - public byte[] GetAnsiHash(byte[] challenge) - { - if (HashesExternal) - { - return AnsiHash; - } - switch (LmCompatibility) - { - case 0: - case 1: - { - return GetPreNtlmResponse(Password, challenge); - } - - case 2: - { - return GetNtlmResponse(Password, challenge); - } - - case 3: - case 4: - case 5: - { - if (ClientChallenge == null) - { - ClientChallenge = new byte[8]; - Random.NextBytes(ClientChallenge); - } - return GetLMv2Response(Domain, Username, Password, challenge, ClientChallenge); - } - - default: - { - return GetPreNtlmResponse(Password, challenge); - } - } - } - - /// <summary>Computes the 24 byte Unicode password hash given the 8 byte server challenge. - /// </summary> - /// <remarks>Computes the 24 byte Unicode password hash given the 8 byte server challenge. - /// </remarks> - public byte[] GetUnicodeHash(byte[] challenge) - { - if (HashesExternal) - { - return UnicodeHash; - } - switch (LmCompatibility) - { - case 0: - case 1: - case 2: - { - return GetNtlmResponse(Password, challenge); - } - - case 3: - case 4: - case 5: - { - return new byte[0]; - } - - default: - { - return GetNtlmResponse(Password, challenge); - } - } - } - - /// <exception cref="SharpCifs.Smb.SmbException"></exception> - public byte[] GetSigningKey(byte[] challenge) - { - switch (LmCompatibility) - { - case 0: - case 1: - case 2: - { - byte[] signingKey = new byte[40]; - GetUserSessionKey(challenge, signingKey, 0); - Array.Copy(GetUnicodeHash(challenge), 0, signingKey, 16, 24); - return signingKey; - } - - case 3: - case 4: - case 5: - { - throw new SmbException("NTLMv2 requires extended security (jcifs.smb.client.useExtendedSecurity must be true if jcifs.smb.lmCompatibility >= 3)" - ); - } - } - return null; - } - - /// <summary>Returns the effective user session key.</summary> - /// <remarks>Returns the effective user session key.</remarks> - /// <param name="challenge">The server challenge.</param> - /// <returns> - /// A <code>byte[]</code> containing the effective user session key, - /// used in SMB MAC signing and NTLMSSP signing and sealing. - /// </returns> - public byte[] GetUserSessionKey(byte[] challenge) - { - if (HashesExternal) - { - return null; - } - byte[] key = new byte[16]; - try - { - GetUserSessionKey(challenge, key, 0); - } - catch (Exception ex) - { - if (_log.Level > 0) - { - Runtime.PrintStackTrace(ex, _log); - } - } - return key; - } - - /// <summary>Calculates the effective user session key.</summary> - /// <remarks>Calculates the effective user session key.</remarks> - /// <param name="challenge">The server challenge.</param> - /// <param name="dest"> - /// The destination array in which the user session key will be - /// placed. - /// </param> - /// <param name="offset"> - /// The offset in the destination array at which the - /// session key will start. - /// </param> - /// <exception cref="SharpCifs.Smb.SmbException"></exception> - internal void GetUserSessionKey(byte[] challenge, byte[] dest, int offset) - { - if (HashesExternal) - { - return; - } - try - { - Md4 md4 = new Md4(); - md4.Update(Runtime.GetBytesForString(Password, SmbConstants.UniEncoding) - ); - switch (LmCompatibility) - { - case 0: - case 1: - case 2: - { - md4.Update(md4.Digest()); - md4.Digest(dest, offset, 16); - break; - } - - case 3: - case 4: - case 5: - { - if (ClientChallenge == null) - { - ClientChallenge = new byte[8]; - Random.NextBytes(ClientChallenge); - } - Hmact64 hmac = new Hmact64(md4.Digest()); - hmac.Update(Runtime.GetBytesForString(Username.ToUpper(), SmbConstants.UniEncoding - )); - hmac.Update(Runtime.GetBytesForString(Domain.ToUpper(), SmbConstants.UniEncoding - )); - byte[] ntlmv2Hash = hmac.Digest(); - hmac = new Hmact64(ntlmv2Hash); - hmac.Update(challenge); - hmac.Update(ClientChallenge); - Hmact64 userKey = new Hmact64(ntlmv2Hash); - userKey.Update(hmac.Digest()); - userKey.Digest(dest, offset, 16); - break; - } - - default: - { - md4.Update(md4.Digest()); - md4.Digest(dest, offset, 16); - break; - } - } - } - catch (Exception e) - { - throw new SmbException(string.Empty, e); - } - } - - /// <summary> - /// Compares two <tt>NtlmPasswordAuthentication</tt> objects for - /// equality. - /// </summary> - /// <remarks> - /// Compares two <tt>NtlmPasswordAuthentication</tt> objects for - /// equality. Two <tt>NtlmPasswordAuthentication</tt> objects are equal if - /// their caseless domain and username fields are equal and either both hashes are external and they are equal or both internally supplied passwords are equal. If one <tt>NtlmPasswordAuthentication</tt> object has external hashes (meaning negotiated via NTLM HTTP Authentication) and the other does not they will not be equal. This is technically not correct however the server 8 byte challage would be required to compute and compare the password hashes but that it not available with this method. - /// </remarks> - public override bool Equals(object obj) - { - if (obj is NtlmPasswordAuthentication) - { - NtlmPasswordAuthentication ntlm = (NtlmPasswordAuthentication - )obj; - if (ntlm.Domain.ToUpper().Equals(Domain.ToUpper()) && ntlm.Username.ToUpper().Equals - (Username.ToUpper())) - { - if (HashesExternal && ntlm.HashesExternal) - { - - return Arrays.Equals(AnsiHash, ntlm.AnsiHash) && Arrays.Equals(UnicodeHash, ntlm. - UnicodeHash); - } - if (!HashesExternal && Password.Equals(ntlm.Password)) - { - return true; - } - } - } - return false; - } - - /// <summary>Return the upcased username hash code.</summary> - /// <remarks>Return the upcased username hash code.</remarks> - public override int GetHashCode() - { - return GetName().ToUpper().GetHashCode(); - } - - /// <summary> - /// Return the domain and username in the format: - /// <tt>domain\\username</tt>. - /// </summary> - /// <remarks> - /// Return the domain and username in the format: - /// <tt>domain\\username</tt>. This is equivalent to <tt>getName()</tt>. - /// </remarks> - public override string ToString() - { - return GetName(); - } - - /// <exception cref="System.FormatException"></exception> - /// <exception cref="UnsupportedEncodingException"></exception> - internal static string Unescape(string str) - { - char ch; - int i; - int j; - int state; - int len; - char[] @out; - byte[] b = new byte[1]; - if (str == null) - { - return null; - } - len = str.Length; - @out = new char[len]; - state = 0; - for (i = j = 0; i < len; i++) - { - switch (state) - { - case 0: - { - ch = str[i]; - if (ch == '%') - { - state = 1; - } - else - { - @out[j++] = ch; - } - break; - } - - case 1: - { - b[0] = unchecked((byte)(Convert.ToInt32(Runtime.Substring(str, i, - i + 2), 16) & unchecked(0xFF))); - @out[j++] = (Runtime.GetStringForBytes(b, 0, 1, "ASCII"))[0]; - i++; - state = 0; - break; - } - } - } - return new string(@out, 0, j); - } - } -} |
