diff --git a/Emby.Common.Implementations/IO/ManagedFileSystem.cs b/Emby.Common.Implementations/IO/ManagedFileSystem.cs index 4d7a868211..f1f044bc51 100644 --- a/Emby.Common.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Common.Implementations/IO/ManagedFileSystem.cs @@ -23,6 +23,8 @@ namespace Emby.Common.Implementations.IO private string _tempPath; + private SharpCifsFileSystem _sharpCifsFileSystem; + public ManagedFileSystem(ILogger logger, IEnvironmentInfo environmentInfo, string tempPath) { Logger = logger; @@ -34,6 +36,8 @@ namespace Emby.Common.Implementations.IO environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.OSX; SetInvalidFileNameChars(environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows); + + _sharpCifsFileSystem = new SharpCifsFileSystem(environmentInfo.OperatingSystem); } public void AddShortcutHandler(IShortcutHandler handler) @@ -168,6 +172,11 @@ namespace Emby.Common.Implementations.IO throw new ArgumentNullException("path"); } + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.GetFileSystemInfo(path); + } + // Take a guess to try and avoid two file system hits, but we'll double-check by calling Exists if (Path.HasExtension(path)) { @@ -208,6 +217,11 @@ namespace Emby.Common.Implementations.IO throw new ArgumentNullException("path"); } + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.GetFileInfo(path); + } + var fileInfo = new FileInfo(path); return GetFileSystemMetadata(fileInfo); @@ -228,6 +242,11 @@ namespace Emby.Common.Implementations.IO throw new ArgumentNullException("path"); } + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.GetDirectoryInfo(path); + } + var fileInfo = new DirectoryInfo(path); return GetFileSystemMetadata(fileInfo); @@ -374,6 +393,11 @@ namespace Emby.Common.Implementations.IO /// FileStream. public Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, bool isAsync = false) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.GetFileStream(path, mode, access, share); + } + if (_supportsAsyncFileStreams && isAsync) { return new FileStream(path, GetFileMode(mode), GetFileAccess(access), GetFileShare(share), 262144, true); @@ -386,8 +410,8 @@ namespace Emby.Common.Implementations.IO { switch (mode) { - case FileOpenMode.Append: - return FileMode.Append; + //case FileOpenMode.Append: + // return FileMode.Append; case FileOpenMode.Create: return FileMode.Create; case FileOpenMode.CreateNew: @@ -396,8 +420,8 @@ namespace Emby.Common.Implementations.IO return FileMode.Open; case FileOpenMode.OpenOrCreate: return FileMode.OpenOrCreate; - case FileOpenMode.Truncate: - return FileMode.Truncate; + //case FileOpenMode.Truncate: + // return FileMode.Truncate; default: throw new Exception("Unrecognized FileOpenMode"); } @@ -407,8 +431,8 @@ namespace Emby.Common.Implementations.IO { switch (mode) { - case FileAccessMode.ReadWrite: - return FileAccess.ReadWrite; + //case FileAccessMode.ReadWrite: + // return FileAccess.ReadWrite; case FileAccessMode.Write: return FileAccess.Write; case FileAccessMode.Read: @@ -437,6 +461,12 @@ namespace Emby.Common.Implementations.IO public void SetHidden(string path, bool isHidden) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + _sharpCifsFileSystem.SetHidden(path, isHidden); + return; + } + var info = GetFileInfo(path); if (info.Exists && info.IsHidden != isHidden) @@ -456,6 +486,12 @@ namespace Emby.Common.Implementations.IO public void SetReadOnly(string path, bool isReadOnly) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + _sharpCifsFileSystem.SetReadOnly(path, isReadOnly); + return; + } + var info = GetFileInfo(path); if (info.Exists && info.IsReadOnly != isReadOnly) @@ -609,6 +645,12 @@ namespace Emby.Common.Implementations.IO public void DeleteFile(string path) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + _sharpCifsFileSystem.DeleteFile(path); + return; + } + var fileInfo = GetFileInfo(path); if (fileInfo.Exists) @@ -628,11 +670,23 @@ namespace Emby.Common.Implementations.IO public void DeleteDirectory(string path, bool recursive) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + _sharpCifsFileSystem.DeleteDirectory(path, recursive); + return; + } + Directory.Delete(path, recursive); } public void CreateDirectory(string path) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + _sharpCifsFileSystem.CreateDirectory(path); + return; + } + Directory.CreateDirectory(path); } @@ -655,6 +709,11 @@ namespace Emby.Common.Implementations.IO public IEnumerable GetDirectories(string path, bool recursive = false) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.GetDirectories(path, recursive); + } + var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; return ToMetadata(new DirectoryInfo(path).EnumerateDirectories("*", searchOption)); @@ -667,6 +726,11 @@ namespace Emby.Common.Implementations.IO public IEnumerable GetFiles(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.GetFiles(path, extensions, enableCaseSensitiveExtensions, recursive); + } + var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; // On linux and osx the search pattern is case sensitive @@ -696,6 +760,11 @@ namespace Emby.Common.Implementations.IO public IEnumerable GetFileSystemEntries(string path, bool recursive = false) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.GetFileSystemEntries(path, recursive); + } + var directoryInfo = new DirectoryInfo(path); var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; @@ -715,76 +784,148 @@ namespace Emby.Common.Implementations.IO public string[] ReadAllLines(string path) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.ReadAllLines(path); + } return File.ReadAllLines(path); } public void WriteAllLines(string path, IEnumerable lines) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + _sharpCifsFileSystem.WriteAllLines(path, lines); + return; + } File.WriteAllLines(path, lines); } public Stream OpenRead(string path) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.OpenRead(path); + } return File.OpenRead(path); } public void CopyFile(string source, string target, bool overwrite) { + if (_sharpCifsFileSystem.IsEnabledForPath(source)) + { + _sharpCifsFileSystem.CopyFile(source, target, overwrite); + return; + } File.Copy(source, target, overwrite); } public void MoveFile(string source, string target) { + if (_sharpCifsFileSystem.IsEnabledForPath(source)) + { + _sharpCifsFileSystem.MoveFile(source, target); + return; + } File.Move(source, target); } public void MoveDirectory(string source, string target) { + if (_sharpCifsFileSystem.IsEnabledForPath(source)) + { + _sharpCifsFileSystem.MoveDirectory(source, target); + return; + } Directory.Move(source, target); } public bool DirectoryExists(string path) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.DirectoryExists(path); + } return Directory.Exists(path); } public bool FileExists(string path) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.FileExists(path); + } return File.Exists(path); } public string ReadAllText(string path) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.ReadAllText(path); + } return File.ReadAllText(path); } public byte[] ReadAllBytes(string path) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.ReadAllBytes(path); + } return File.ReadAllBytes(path); } public void WriteAllText(string path, string text, Encoding encoding) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + _sharpCifsFileSystem.WriteAllText(path, text, encoding); + return; + } + File.WriteAllText(path, text, encoding); } public void WriteAllText(string path, string text) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + _sharpCifsFileSystem.WriteAllText(path, text); + return; + } + File.WriteAllText(path, text); } public void WriteAllBytes(string path, byte[] bytes) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + _sharpCifsFileSystem.WriteAllBytes(path, bytes); + return; + } + File.WriteAllBytes(path, bytes); } public string ReadAllText(string path, Encoding encoding) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.ReadAllText(path, encoding); + } + return File.ReadAllText(path, encoding); } public IEnumerable GetDirectoryPaths(string path, bool recursive = false) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.GetDirectoryPaths(path, recursive); + } + var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; return Directory.EnumerateDirectories(path, "*", searchOption); } @@ -796,6 +937,11 @@ namespace Emby.Common.Implementations.IO public IEnumerable GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.GetFilePaths(path, extensions, enableCaseSensitiveExtensions, recursive); + } + var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; // On linux and osx the search pattern is case sensitive @@ -825,6 +971,11 @@ namespace Emby.Common.Implementations.IO public IEnumerable GetFileSystemEntryPaths(string path, bool recursive = false) { + if (_sharpCifsFileSystem.IsEnabledForPath(path)) + { + return _sharpCifsFileSystem.GetFileSystemEntryPaths(path, recursive); + } + var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; return Directory.EnumerateFileSystemEntries(path, "*", searchOption); } diff --git a/Emby.Common.Implementations/IO/SharpCifs/Config.cs b/Emby.Common.Implementations/IO/SharpCifs/Config.cs new file mode 100644 index 0000000000..3fd0e5bd64 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Config.cs @@ -0,0 +1,409 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using System.Net; +using System.Security; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs +{ + /// + /// This class uses a static + /// Sharpen.Properties + /// to act + /// as a cental repository for all jCIFS configuration properties. It cannot be + /// instantiated. Similar to System properties the namespace + /// is global therefore property names should be unique. Before use, + /// the load method should be called with the name of a + /// Properties file (or null indicating no + /// file) to initialize the Config. The System + /// properties will then populate the Config as well potentially + /// overwriting properties from the file. Thus properties provided on the + /// commandline with the -Dproperty.name=value VM parameter + /// will override properties from the configuration file. + /// + /// There are several ways to set jCIFS properties. See + /// the overview page of the API + /// documentation for details. + /// + public class Config + { + + /// The static Properties. + /// The static Properties. + private static Properties _prp = new Properties(); + + private static LogStream _log; + + public static string DefaultOemEncoding = "UTF-8"; //"Cp850"; + + static Config() + { + int level; + FileInputStream fis = null; + _log = LogStream.GetInstance(); + + try + { + string filename = Runtime.GetProperty("jcifs.properties"); + if (filename != null && filename.Length > 1) + { + fis = new FileInputStream(filename); + } + Load(fis); + if (fis != null) + { + fis.Close(); + } + } + catch (IOException ioe) + { + if (_log.Level > 0) + { + Runtime.PrintStackTrace(ioe, _log); + } + } + + if ((level = GetInt("jcifs.util.loglevel", -1)) != -1) + { + _log.SetLevel(level); + } + + try + { + Runtime.GetBytesForString(string.Empty, DefaultOemEncoding); + } + catch (Exception ex) + { + if (_log.Level >= 2) + { + _log.WriteLine("WARNING: The default OEM encoding " + DefaultOemEncoding + " does not appear to be supported by this JRE. The default encoding will be US-ASCII." + ); + } + + //DEFAULT_OEM_ENCODING = "US-ASCII"; + } + + if (_log.Level >= 4) + { + try + { + _prp.Store(_log); + } + catch (IOException) + { + } + } + } + + /// + /// This static method registers the SMB URL protocol handler which is + /// required to use SMB URLs with the java.net.URL class. + /// + /// + /// This static method registers the SMB URL protocol handler which is + /// required to use SMB URLs with the java.net.URL class. If this + /// method is not called before attempting to create an SMB URL with the + /// URL class the following exception will occur: + ///
+        /// Exception MalformedURLException: unknown protocol: smb
+        /// at java.net.URL.(URL.java:480)
+        /// at java.net.URL.(URL.java:376)
+        /// at java.net.URL.(URL.java:330)
+        /// at jcifs.smb.SmbFile.(SmbFile.java:355)
+        /// ...
+        /// 
+ /// + public static void RegisterSmbURLHandler() + { + throw new NotImplementedException(); + } + + // supress javadoc constructor summary by removing 'protected' + /// Set the default properties of the static Properties used by Config. + /// + /// + /// Set the default properties of the static Properties used by Config. This permits + /// a different Properties object/file to be used as the source of properties for + /// use by the jCIFS library. The Properties must be set before jCIFS + /// classes are accessed as most jCIFS classes load properties statically once. + /// Using this method will also override properties loaded + /// using the -Djcifs.properties= commandline parameter. + /// + public static void SetProperties(Properties prp) + { + Config._prp = new Properties(prp); + try + { + Config._prp.PutAll(Runtime.GetProperties()); + } + catch (SecurityException) + { + if (_log.Level > 1) + { + _log.WriteLine("SecurityException: jcifs will ignore System properties"); + } + } + } + + /// + /// Load the Config with properties from the stream + /// in from a Properties file. + /// + /// + /// Load the Config with properties from the stream + /// in from a Properties file. + /// + /// + public static void Load(InputStream input) + { + if (input != null) + { + _prp.Load(input); + } + try + { + _prp.PutAll(Runtime.GetProperties()); + } + catch (SecurityException) + { + if (_log.Level > 1) + { + _log.WriteLine("SecurityException: jcifs will ignore System properties"); + } + } + } + + /// + public static void Store(OutputStream output, string header) + { + _prp.Store(output); + } + + /// Add a property. + /// Add a property. + public static void SetProperty(string key, string value) + { + _prp.SetProperty(key, value); + } + + /// Retrieve a property as an Object. + /// Retrieve a property as an Object. + public static object Get(string key) + { + return _prp.GetProperty(key); + } + + /// Retrieve a String. + /// + /// Retrieve a String. If the key cannot be found, + /// the provided def default parameter will be returned. + /// + public static string GetProperty(string key, string def) + { + return (string)_prp.GetProperty(key, def); + } + + /// Retrieve a String. + /// Retrieve a String. If the property is not found, null is returned. + /// + public static string GetProperty(string key) + { + return (string)_prp.GetProperty(key); + } + + /// Retrieve an int. + /// + /// Retrieve an int. If the key does not exist or + /// cannot be converted to an int, the provided default + /// argument will be returned. + /// + public static int GetInt(string key, int def) + { + string s = (string)_prp.GetProperty(key); + if (s != null) + { + try + { + def = Convert.ToInt32(s); + } + catch (FormatException nfe) + { + if (_log.Level > 0) + { + Runtime.PrintStackTrace(nfe, _log); + } + } + } + return def; + } + + /// Retrieve an int. + /// Retrieve an int. If the property is not found, -1 is returned. + /// + public static int GetInt(string key) + { + string s = (string)_prp.GetProperty(key); + int result = -1; + if (s != null) + { + try + { + result = Convert.ToInt32(s); + } + catch (FormatException nfe) + { + if (_log.Level > 0) + { + Runtime.PrintStackTrace(nfe, _log); + } + } + } + return result; + } + + /// Retrieve a long. + /// + /// Retrieve a long. If the key does not exist or + /// cannot be converted to a long, the provided default + /// argument will be returned. + /// + public static long GetLong(string key, long def) + { + string s = (string)_prp.GetProperty(key); + if (s != null) + { + try + { + def = long.Parse(s); + } + catch (FormatException nfe) + { + if (_log.Level > 0) + { + Runtime.PrintStackTrace(nfe, _log); + } + } + } + return def; + } + + /// Retrieve an InetAddress. + /// + /// Retrieve an InetAddress. If the address is not + /// an IP address and cannot be resolved null will + /// be returned. + /// + public static IPAddress GetInetAddress(string key, IPAddress def) + { + string addr = (string)_prp.GetProperty(key); + if (addr != null) + { + try + { + def = Extensions.GetAddressByName(addr); + } + catch (UnknownHostException uhe) + { + if (_log.Level > 0) + { + _log.WriteLine(addr); + Runtime.PrintStackTrace(uhe, _log); + } + } + } + return def; + } + + public static IPAddress GetLocalHost() + { + string addr = (string)_prp.GetProperty("jcifs.smb.client.laddr"); + if (addr != null) + { + try + { + return Extensions.GetAddressByName(addr); + } + catch (UnknownHostException uhe) + { + if (_log.Level > 0) + { + _log.WriteLine("Ignoring jcifs.smb.client.laddr address: " + addr); + Runtime.PrintStackTrace(uhe, _log); + } + } + } + return null; + } + + /// Retrieve a boolean value. + /// Retrieve a boolean value. If the property is not found, the value of def is returned. + /// + public static bool GetBoolean(string key, bool def) + { + string b = GetProperty(key); + if (b != null) + { + def = b.ToLower().Equals("true"); + } + return def; + } + + /// + /// Retrieve an array of InetAddress created from a property + /// value containting a delim separated list of hostnames and/or + /// ipaddresses. + /// + /// + /// Retrieve an array of InetAddress created from a property + /// value containting a delim separated list of hostnames and/or + /// ipaddresses. + /// + public static IPAddress[] GetInetAddressArray(string key, string delim, IPAddress + [] def) + { + string p = GetProperty(key); + if (p != null) + { + StringTokenizer tok = new StringTokenizer(p, delim); + int len = tok.CountTokens(); + IPAddress[] arr = new IPAddress[len]; + for (int i = 0; i < len; i++) + { + string addr = tok.NextToken(); + try + { + arr[i] = Extensions.GetAddressByName(addr); + } + catch (UnknownHostException uhe) + { + if (_log.Level > 0) + { + _log.WriteLine(addr); + Runtime.PrintStackTrace(uhe, _log); + } + return def; + } + } + return arr; + } + return def; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcBind.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcBind.cs new file mode 100644 index 0000000000..1d8d13c08c --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcBind.cs @@ -0,0 +1,102 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Dcerpc.Ndr; +using SharpCifs.Util; + +namespace SharpCifs.Dcerpc +{ + public class DcerpcBind : DcerpcMessage + { + internal static readonly string[] ResultMessage = { "0", "DCERPC_BIND_ERR_ABSTRACT_SYNTAX_NOT_SUPPORTED" + , "DCERPC_BIND_ERR_PROPOSED_TRANSFER_SYNTAXES_NOT_SUPPORTED", "DCERPC_BIND_ERR_LOCAL_LIMIT_EXCEEDED" + }; + + internal static string GetResultMessage(int result) + { + return result < 4 ? ResultMessage[result] : "0x" + Hexdump.ToHexString(result, 4 + ); + } + + public override DcerpcException GetResult() + { + if (Result != 0) + { + return new DcerpcException(GetResultMessage(Result)); + } + return null; + } + + internal DcerpcBinding Binding; + + internal int MaxXmit; + + internal int MaxRecv; + + public DcerpcBind() + { + } + + internal DcerpcBind(DcerpcBinding binding, DcerpcHandle handle) + { + this.Binding = binding; + MaxXmit = handle.MaxXmit; + MaxRecv = handle.MaxRecv; + Ptype = 11; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + + public override int GetOpnum() + { + return 0; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + dst.Enc_ndr_short(MaxXmit); + dst.Enc_ndr_short(MaxRecv); + dst.Enc_ndr_long(0); + dst.Enc_ndr_small(1); + dst.Enc_ndr_small(0); + dst.Enc_ndr_short(0); + dst.Enc_ndr_short(0); + dst.Enc_ndr_small(1); + dst.Enc_ndr_small(0); + Binding.Uuid.Encode(dst); + dst.Enc_ndr_short(Binding.Major); + dst.Enc_ndr_short(Binding.Minor); + DcerpcConstants.DcerpcUuidSyntaxNdr.Encode(dst); + dst.Enc_ndr_long(2); + } + + /// + public override void Decode_out(NdrBuffer src) + { + src.Dec_ndr_short(); + src.Dec_ndr_short(); + src.Dec_ndr_long(); + int n = src.Dec_ndr_short(); + src.Advance(n); + src.Align(4); + src.Dec_ndr_small(); + src.Align(4); + Result = src.Dec_ndr_short(); + src.Dec_ndr_short(); + src.Advance(20); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcBinding.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcBinding.cs new file mode 100644 index 0000000000..2341506642 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcBinding.cs @@ -0,0 +1,122 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Dcerpc.Msrpc; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Dcerpc +{ + public class DcerpcBinding + { + private static Hashtable _interfaces; + + static DcerpcBinding() + { + _interfaces = new Hashtable(); + _interfaces.Put("srvsvc", Srvsvc.GetSyntax()); + _interfaces.Put("lsarpc", Lsarpc.GetSyntax()); + _interfaces.Put("samr", Samr.GetSyntax()); + _interfaces.Put("netdfs", Netdfs.GetSyntax()); + } + + public static void AddInterface(string name, string syntax) + { + _interfaces.Put(name, syntax); + } + + internal string Proto; + + internal string Server; + + internal string Endpoint; + + internal Hashtable Options; + + internal Uuid Uuid; + + internal int Major; + + internal int Minor; + + internal DcerpcBinding(string proto, string server) + { + this.Proto = proto; + this.Server = server; + } + + /// + internal virtual void SetOption(string key, object val) + { + if (key.Equals("endpoint")) + { + Endpoint = val.ToString().ToLower(); + if (Endpoint.StartsWith("\\pipe\\")) + { + string iface = (string)_interfaces.Get(Runtime.Substring(Endpoint, 6)); + if (iface != null) + { + int c; + int p; + c = iface.IndexOf(':'); + p = iface.IndexOf('.', c + 1); + Uuid = new Uuid(Runtime.Substring(iface, 0, c)); + Major = Convert.ToInt32(Runtime.Substring(iface, c + 1, p)); + Minor = Convert.ToInt32(Runtime.Substring(iface, p + 1)); + return; + } + } + throw new DcerpcException("Bad endpoint: " + Endpoint); + } + if (Options == null) + { + Options = new Hashtable(); + } + Options.Put(key, val); + } + + internal virtual object GetOption(string key) + { + if (key.Equals("endpoint")) + { + return Endpoint; + } + if (Options != null) + { + return Options.Get(key); + } + return null; + } + + public override string ToString() + { + /* string ret = proto + ":" + server + "[" + endpoint; + if (options != null) + { + Iterator iter = (Iterator) options.Keys.GetEnumerator(); + while (iter.HasNext()) + { + object key = iter.Next(); + object val = options.Get(key); + ret += "," + key + "=" + val; + } + } + ret += "]"; + return ret; */ + return null; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcConstants.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcConstants.cs new file mode 100644 index 0000000000..5b69c5c2ec --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcConstants.cs @@ -0,0 +1,40 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc +{ + public static class DcerpcConstants + { + public static Uuid DcerpcUuidSyntaxNdr = new Uuid("8a885d04-1ceb-11c9-9fe8-08002b104860" + ); + + public static int DcerpcFirstFrag = unchecked(0x01); + + public static int DcerpcLastFrag = unchecked(0x02); + + public static int DcerpcPendingCancel = unchecked(0x04); + + public static int DcerpcReserved1 = unchecked(0x08); + + public static int DcerpcConcMpx = unchecked(0x10); + + public static int DcerpcDidNotExecute = unchecked(0x20); + + public static int DcerpcMaybe = unchecked(0x40); + + public static int DcerpcObjectUuid = unchecked(0x80); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcError.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcError.cs new file mode 100644 index 0000000000..55c0610650 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcError.cs @@ -0,0 +1,48 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc +{ + public static class DcerpcError + { + public static int DcerpcFaultOther = unchecked(0x00000001); + + public static int DcerpcFaultAccessDenied = unchecked(0x00000005); + + public static int DcerpcFaultCantPerform = unchecked(0x000006D8); + + public static int DcerpcFaultNdr = unchecked(0x000006F7); + + public static int DcerpcFaultInvalidTag = unchecked(0x1C000006); + + public static int DcerpcFaultContextMismatch = unchecked(0x1C00001A); + + public static int DcerpcFaultOpRngError = unchecked(0x1C010002); + + public static int DcerpcFaultUnkIf = unchecked(0x1C010003); + + public static int DcerpcFaultProtoError = unchecked(0x1c01000b); + + public static int[] DcerpcFaultCodes = { DcerpcFaultOther, DcerpcFaultAccessDenied + , DcerpcFaultCantPerform, DcerpcFaultNdr, DcerpcFaultInvalidTag, DcerpcFaultContextMismatch + , DcerpcFaultOpRngError, DcerpcFaultUnkIf, DcerpcFaultProtoError }; + + public static string[] DcerpcFaultMessages = { "DCERPC_FAULT_OTHER" + , "DCERPC_FAULT_ACCESS_DENIED", "DCERPC_FAULT_CANT_PERFORM", "DCERPC_FAULT_NDR", + "DCERPC_FAULT_INVALID_TAG", "DCERPC_FAULT_CONTEXT_MISMATCH", "DCERPC_FAULT_OP_RNG_ERROR" + , "DCERPC_FAULT_UNK_IF", "DCERPC_FAULT_PROTO_ERROR" }; + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcException.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcException.cs new file mode 100644 index 0000000000..13c4f0d0cd --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcException.cs @@ -0,0 +1,93 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Dcerpc +{ + + public class DcerpcException : IOException + { + internal static string GetMessageByDcerpcError(int errcode) + { + int min = 0; + int max = DcerpcError.DcerpcFaultCodes.Length; + while (max >= min) + { + int mid = (min + max) / 2; + if (errcode > DcerpcError.DcerpcFaultCodes[mid]) + { + min = mid + 1; + } + else + { + if (errcode < DcerpcError.DcerpcFaultCodes[mid]) + { + max = mid - 1; + } + else + { + return DcerpcError.DcerpcFaultMessages[mid]; + } + } + } + return "0x" + Hexdump.ToHexString(errcode, 8); + } + + private int _error; + + private Exception _rootCause; + + internal DcerpcException(int error) : base(GetMessageByDcerpcError(error)) + { + this._error = error; + } + + public DcerpcException(string msg) : base(msg) + { + } + + public DcerpcException(string msg, Exception rootCause) : base(msg) + { + this._rootCause = rootCause; + } + + public virtual int GetErrorCode() + { + return _error; + } + + public virtual Exception GetRootCause() + { + return _rootCause; + } + + public override string ToString() + { + if (_rootCause != null) + { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + Runtime.PrintStackTrace(_rootCause, pw); + return base.ToString() + "\n" + sw; + } + return base.ToString(); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcHandle.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcHandle.cs new file mode 100644 index 0000000000..786b0ac122 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcHandle.cs @@ -0,0 +1,332 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using SharpCifs.Dcerpc.Ndr; +using SharpCifs.Smb; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Dcerpc +{ + public abstract class DcerpcHandle + { + /// + protected internal static DcerpcBinding ParseBinding(string str) + { + int state; + int mark; + int si; + char[] arr = str.ToCharArray(); + string proto = null; + string key = null; + DcerpcBinding binding = null; + state = mark = si = 0; + do + { + char ch = arr[si]; + switch (state) + { + case 0: + { + if (ch == ':') + { + proto = Runtime.Substring(str, mark, si); + mark = si + 1; + state = 1; + } + break; + } + + case 1: + { + if (ch == '\\') + { + mark = si + 1; + break; + } + state = 2; + goto case 2; + } + + case 2: + { + if (ch == '[') + { + string server = Runtime.Substring(str, mark, si).Trim(); + if (server.Length == 0) + { + server = "127.0.0.1"; + } + binding = new DcerpcBinding(proto, Runtime.Substring(str, mark, si)); + mark = si + 1; + state = 5; + } + break; + } + + case 5: + { + if (ch == '=') + { + key = Runtime.Substring(str, mark, si).Trim(); + mark = si + 1; + } + else + { + if (ch == ',' || ch == ']') + { + string val = Runtime.Substring(str, mark, si).Trim(); + if (key == null) + { + key = "endpoint"; + } + binding.SetOption(key, val); + key = null; + } + } + break; + } + + default: + { + si = arr.Length; + break; + } + } + si++; + } + while (si < arr.Length); + if (binding == null || binding.Endpoint == null) + { + throw new DcerpcException("Invalid binding URL: " + str); + } + return binding; + } + + protected internal DcerpcBinding Binding; + + protected internal int MaxXmit = 4280; + + protected internal int MaxRecv; + + protected internal int State; + + protected internal IDcerpcSecurityProvider SecurityProvider; + + private static int _callId = 1; + + /// + /// + /// + public static DcerpcHandle GetHandle(string url, NtlmPasswordAuthentication auth) + { + if (url.StartsWith("ncacn_np:")) + { + return new DcerpcPipeHandle(url, auth); + } + throw new DcerpcException("DCERPC transport not supported: " + url); + } + + /// + /// + public virtual void Bind() + { + lock (this) + { + try + { + State = 1; + DcerpcMessage bind = new DcerpcBind(Binding, this); + Sendrecv(bind); + } + catch (IOException ioe) + { + State = 0; + throw; + } + } + } + + /// + /// + public virtual void Sendrecv(DcerpcMessage msg) + { + byte[] stub; + byte[] frag; + NdrBuffer buf; + NdrBuffer fbuf; + bool isLast; + bool isDirect; + DcerpcException de; + if (State == 0) + { + Bind(); + } + isDirect = true; + stub = BufferCache.GetBuffer(); + try + { + int off; + int tot; + int n; + buf = new NdrBuffer(stub, 0); + msg.Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + msg.CallId = _callId++; + msg.Encode(buf); + if (SecurityProvider != null) + { + buf.SetIndex(0); + SecurityProvider.Wrap(buf); + } + tot = buf.GetLength() - 24; + off = 0; + while (off < tot) + { + n = tot - off; + if ((24 + n) > MaxXmit) + { + msg.Flags &= ~DcerpcConstants.DcerpcLastFrag; + n = MaxXmit - 24; + } + else + { + msg.Flags |= DcerpcConstants.DcerpcLastFrag; + isDirect = false; + msg.AllocHint = n; + } + msg.Length = 24 + n; + if (off > 0) + { + msg.Flags &= ~DcerpcConstants.DcerpcFirstFrag; + } + if ((msg.Flags & (DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag)) != (DcerpcConstants.DcerpcFirstFrag | + DcerpcConstants.DcerpcLastFrag)) + { + buf.Start = off; + buf.Reset(); + msg.Encode_header(buf); + buf.Enc_ndr_long(msg.AllocHint); + buf.Enc_ndr_short(0); + buf.Enc_ndr_short(msg.GetOpnum()); + } + DoSendFragment(stub, off, msg.Length, isDirect); + off += n; + } + DoReceiveFragment(stub, isDirect); + buf.Reset(); + buf.SetIndex(8); + buf.SetLength(buf.Dec_ndr_short()); + if (SecurityProvider != null) + { + SecurityProvider.Unwrap(buf); + } + buf.SetIndex(0); + msg.Decode_header(buf); + off = 24; + if (msg.Ptype == 2 && msg.IsFlagSet(DcerpcConstants.DcerpcLastFrag) == false) + { + off = msg.Length; + } + frag = null; + fbuf = null; + while (msg.IsFlagSet(DcerpcConstants.DcerpcLastFrag) == false) + { + int stubFragLen; + if (frag == null) + { + frag = new byte[MaxRecv]; + fbuf = new NdrBuffer(frag, 0); + } + DoReceiveFragment(frag, isDirect); + fbuf.Reset(); + fbuf.SetIndex(8); + fbuf.SetLength(fbuf.Dec_ndr_short()); + if (SecurityProvider != null) + { + SecurityProvider.Unwrap(fbuf); + } + fbuf.Reset(); + msg.Decode_header(fbuf); + stubFragLen = msg.Length - 24; + if ((off + stubFragLen) > stub.Length) + { + // shouldn't happen if alloc_hint is correct or greater + byte[] tmp = new byte[off + stubFragLen]; + Array.Copy(stub, 0, tmp, 0, off); + stub = tmp; + } + Array.Copy(frag, 24, stub, off, stubFragLen); + off += stubFragLen; + } + buf = new NdrBuffer(stub, 0); + msg.Decode(buf); + } + finally + { + BufferCache.ReleaseBuffer(stub); + } + if ((de = msg.GetResult()) != null) + { + throw de; + } + } + + public virtual void SetDcerpcSecurityProvider(IDcerpcSecurityProvider securityProvider + ) + { + this.SecurityProvider = securityProvider; + } + + public virtual string GetServer() + { + if (this is DcerpcPipeHandle) + { + return ((DcerpcPipeHandle)this).Pipe.GetServer(); + } + return null; + } + + public virtual Principal GetPrincipal() + { + if (this is DcerpcPipeHandle) + { + return ((DcerpcPipeHandle)this).Pipe.GetPrincipal(); + } + return null; + } + + public override string ToString() + { + return Binding.ToString(); + } + + /// + protected internal abstract void DoSendFragment(byte[] buf, int off, int length, + bool isDirect); + + /// + protected internal abstract void DoReceiveFragment(byte[] buf, bool isDirect); + + /// + public abstract void Close(); + + public DcerpcHandle() + { + MaxRecv = MaxXmit; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcMessage.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcMessage.cs new file mode 100644 index 0000000000..543dd72dd0 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcMessage.cs @@ -0,0 +1,150 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Dcerpc.Ndr; + +namespace SharpCifs.Dcerpc +{ + public abstract class DcerpcMessage : NdrObject + { + protected internal int Ptype = -1; + + protected internal int Flags; + + protected internal int Length; + + protected internal int CallId; + + protected internal int AllocHint; + + protected internal int Result; + + public virtual bool IsFlagSet(int flag) + { + return (Flags & flag) == flag; + } + + public virtual void UnsetFlag(int flag) + { + Flags &= ~flag; + } + + public virtual void SetFlag(int flag) + { + Flags |= flag; + } + + public virtual DcerpcException GetResult() + { + if (Result != 0) + { + return new DcerpcException(Result); + } + return null; + } + + internal virtual void Encode_header(NdrBuffer buf) + { + buf.Enc_ndr_small(5); + buf.Enc_ndr_small(0); + buf.Enc_ndr_small(Ptype); + buf.Enc_ndr_small(Flags); + buf.Enc_ndr_long(unchecked(0x00000010)); + buf.Enc_ndr_short(Length); + buf.Enc_ndr_short(0); + buf.Enc_ndr_long(CallId); + } + + /// + internal virtual void Decode_header(NdrBuffer buf) + { + if (buf.Dec_ndr_small() != 5 || buf.Dec_ndr_small() != 0) + { + throw new NdrException("DCERPC version not supported"); + } + Ptype = buf.Dec_ndr_small(); + Flags = buf.Dec_ndr_small(); + if (buf.Dec_ndr_long() != unchecked(0x00000010)) + { + throw new NdrException("Data representation not supported"); + } + Length = buf.Dec_ndr_short(); + if (buf.Dec_ndr_short() != 0) + { + throw new NdrException("DCERPC authentication not supported"); + } + CallId = buf.Dec_ndr_long(); + } + + /// + public override void Encode(NdrBuffer buf) + { + int start = buf.GetIndex(); + int allocHintIndex = 0; + buf.Advance(16); + if (Ptype == 0) + { + allocHintIndex = buf.GetIndex(); + buf.Enc_ndr_long(0); + buf.Enc_ndr_short(0); + buf.Enc_ndr_short(GetOpnum()); + } + Encode_in(buf); + Length = buf.GetIndex() - start; + if (Ptype == 0) + { + buf.SetIndex(allocHintIndex); + AllocHint = Length - allocHintIndex; + buf.Enc_ndr_long(AllocHint); + } + buf.SetIndex(start); + Encode_header(buf); + buf.SetIndex(start + Length); + } + + /// + public override void Decode(NdrBuffer buf) + { + Decode_header(buf); + if (Ptype != 12 && Ptype != 2 && Ptype != 3 && Ptype != 13) + { + throw new NdrException("Unexpected ptype: " + Ptype); + } + if (Ptype == 2 || Ptype == 3) + { + AllocHint = buf.Dec_ndr_long(); + buf.Dec_ndr_short(); + buf.Dec_ndr_short(); + } + if (Ptype == 3 || Ptype == 13) + { + Result = buf.Dec_ndr_long(); + } + else + { + Decode_out(buf); + } + } + + public abstract int GetOpnum(); + + /// + public abstract void Encode_in(NdrBuffer dst); + + /// + public abstract void Decode_out(NdrBuffer src); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcPipeHandle.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcPipeHandle.cs new file mode 100644 index 0000000000..0399578cd8 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcPipeHandle.cs @@ -0,0 +1,135 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using SharpCifs.Smb; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Dcerpc +{ + public class DcerpcPipeHandle : DcerpcHandle + { + internal SmbNamedPipe Pipe; + + internal SmbFileInputStream In; + + internal SmbFileOutputStream Out; + + internal bool IsStart = true; + + /// + /// + /// + public DcerpcPipeHandle(string url, NtlmPasswordAuthentication auth) + { + Binding = ParseBinding(url); + url = "smb://" + Binding.Server + "/IPC$/" + Runtime.Substring(Binding.Endpoint + , 6); + string @params = string.Empty; + string server; + string address; + server = (string)Binding.GetOption("server"); + if (server != null) + { + @params += "&server=" + server; + } + address = (string)Binding.GetOption("address"); + if (server != null) + { + @params += "&address=" + address; + } + if (@params.Length > 0) + { + url += "?" + Runtime.Substring(@params, 1); + } + Pipe = new SmbNamedPipe(url, (unchecked(0x2019F) << 16) | SmbNamedPipe.PipeTypeRdwr + | SmbNamedPipe.PipeTypeDceTransact, auth); + } + + /// + protected internal override void DoSendFragment(byte[] buf, int off, int length, + bool isDirect) + { + if (Out != null && Out.IsOpen() == false) + { + throw new IOException("DCERPC pipe is no longer open"); + } + if (In == null) + { + In = (SmbFileInputStream)Pipe.GetNamedPipeInputStream(); + } + if (Out == null) + { + Out = (SmbFileOutputStream)Pipe.GetNamedPipeOutputStream(); + } + if (isDirect) + { + Out.WriteDirect(buf, off, length, 1); + return; + } + Out.Write(buf, off, length); + } + + /// + protected internal override void DoReceiveFragment(byte[] buf, bool isDirect) + { + int off; + int flags; + int length; + if (buf.Length < MaxRecv) + { + throw new ArgumentException("buffer too small"); + } + if (IsStart && !isDirect) + { + // start of new frag, do trans + off = In.Read(buf, 0, 1024); + } + else + { + off = In.ReadDirect(buf, 0, buf.Length); + } + if (buf[0] != 5 && buf[1] != 0) + { + throw new IOException("Unexpected DCERPC PDU header"); + } + flags = buf[3] & unchecked(0xFF); + // next read is start of new frag + IsStart = (flags & DcerpcConstants.DcerpcLastFrag) == DcerpcConstants.DcerpcLastFrag; + length = Encdec.Dec_uint16le(buf, 8); + if (length > MaxRecv) + { + throw new IOException("Unexpected fragment length: " + length); + } + while (off < length) + { + off += In.ReadDirect(buf, off, length - off); + } + } + + /// + public override void Close() + { + State = 0; + if (Out != null) + { + Out.Close(); + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcSecurityProvider.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcSecurityProvider.cs new file mode 100644 index 0000000000..cc46902f11 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/DcerpcSecurityProvider.cs @@ -0,0 +1,29 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Dcerpc.Ndr; + +namespace SharpCifs.Dcerpc +{ + public interface IDcerpcSecurityProvider + { + /// + void Wrap(NdrBuffer outgoing); + + /// + void Unwrap(NdrBuffer incoming); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/LsaPolicyHandle.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/LsaPolicyHandle.cs new file mode 100644 index 0000000000..03964fcc77 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/LsaPolicyHandle.cs @@ -0,0 +1,43 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Smb; + +namespace SharpCifs.Dcerpc.Msrpc +{ + public class LsaPolicyHandle : Rpc.PolicyHandle + { + /// + public LsaPolicyHandle(DcerpcHandle handle, string server, int access) + { + if (server == null) + { + server = "\\\\"; + } + MsrpcLsarOpenPolicy2 rpc = new MsrpcLsarOpenPolicy2(server, access, this); + handle.Sendrecv(rpc); + if (rpc.Retval != 0) + { + throw new SmbException(rpc.Retval, false); + } + } + + /// + public virtual void Close() + { + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/LsarSidArrayX.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/LsarSidArrayX.cs new file mode 100644 index 0000000000..ef09bb16e4 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/LsarSidArrayX.cs @@ -0,0 +1,34 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Smb; + +namespace SharpCifs.Dcerpc.Msrpc +{ + internal class LsarSidArrayX : Lsarpc.LsarSidArray + { + internal LsarSidArrayX(Sid[] sids) + { + NumSids = sids.Length; + this.Sids = new Lsarpc.LsarSidPtr[sids.Length]; + for (int si = 0; si < sids.Length; si++) + { + this.Sids[si] = new Lsarpc.LsarSidPtr(); + this.Sids[si].Sid = sids[si]; + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/Lsarpc.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/Lsarpc.cs new file mode 100644 index 0000000000..1ae85c4730 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/Lsarpc.cs @@ -0,0 +1,1161 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Dcerpc.Ndr; + +namespace SharpCifs.Dcerpc.Msrpc +{ + public class Lsarpc + { + public static string GetSyntax() + { + return "12345778-1234-abcd-ef00-0123456789ab:0.0"; + } + + public class LsarQosInfo : NdrObject + { + public int Length; + + public short ImpersonationLevel; + + public byte ContextMode; + + public byte EffectiveOnly; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Length); + dst.Enc_ndr_short(ImpersonationLevel); + dst.Enc_ndr_small(ContextMode); + dst.Enc_ndr_small(EffectiveOnly); + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Length = src.Dec_ndr_long(); + ImpersonationLevel = (short)src.Dec_ndr_short(); + ContextMode = unchecked((byte)src.Dec_ndr_small()); + EffectiveOnly = unchecked((byte)src.Dec_ndr_small()); + } + } + + public class LsarObjectAttributes : NdrObject + { + public int Length; + + public NdrSmall RootDirectory; + + public Rpc.Unicode_string ObjectName; + + public int Attributes; + + public int SecurityDescriptor; + + public LsarQosInfo SecurityQualityOfService; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Length); + dst.Enc_ndr_referent(RootDirectory, 1); + dst.Enc_ndr_referent(ObjectName, 1); + dst.Enc_ndr_long(Attributes); + dst.Enc_ndr_long(SecurityDescriptor); + dst.Enc_ndr_referent(SecurityQualityOfService, 1); + if (RootDirectory != null) + { + dst = dst.Deferred; + RootDirectory.Encode(dst); + } + if (ObjectName != null) + { + dst = dst.Deferred; + ObjectName.Encode(dst); + } + if (SecurityQualityOfService != null) + { + dst = dst.Deferred; + SecurityQualityOfService.Encode(dst); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Length = src.Dec_ndr_long(); + int rootDirectoryp = src.Dec_ndr_long(); + int objectNamep = src.Dec_ndr_long(); + Attributes = src.Dec_ndr_long(); + SecurityDescriptor = src.Dec_ndr_long(); + int securityQualityOfServicep = src.Dec_ndr_long(); + if (rootDirectoryp != 0) + { + src = src.Deferred; + RootDirectory.Decode(src); + } + if (objectNamep != 0) + { + if (ObjectName == null) + { + ObjectName = new Rpc.Unicode_string(); + } + src = src.Deferred; + ObjectName.Decode(src); + } + if (securityQualityOfServicep != 0) + { + if (SecurityQualityOfService == null) + { + SecurityQualityOfService = new LsarQosInfo(); + } + src = src.Deferred; + SecurityQualityOfService.Decode(src); + } + } + } + + public class LsarDomainInfo : NdrObject + { + public Rpc.Unicode_string Name; + + public Rpc.SidT Sid; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_short(Name.Length); + dst.Enc_ndr_short(Name.MaximumLength); + dst.Enc_ndr_referent(Name.Buffer, 1); + dst.Enc_ndr_referent(Sid, 1); + if (Name.Buffer != null) + { + dst = dst.Deferred; + int nameBufferl = Name.Length / 2; + int nameBuffers = Name.MaximumLength / 2; + dst.Enc_ndr_long(nameBuffers); + dst.Enc_ndr_long(0); + dst.Enc_ndr_long(nameBufferl); + int nameBufferi = dst.Index; + dst.Advance(2 * nameBufferl); + dst = dst.Derive(nameBufferi); + for (int i = 0; i < nameBufferl; i++) + { + dst.Enc_ndr_short(Name.Buffer[i]); + } + } + if (Sid != null) + { + dst = dst.Deferred; + Sid.Encode(dst); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + src.Align(4); + if (Name == null) + { + Name = new Rpc.Unicode_string(); + } + Name.Length = (short)src.Dec_ndr_short(); + Name.MaximumLength = (short)src.Dec_ndr_short(); + int nameBufferp = src.Dec_ndr_long(); + int sidp = src.Dec_ndr_long(); + if (nameBufferp != 0) + { + src = src.Deferred; + int nameBuffers = src.Dec_ndr_long(); + src.Dec_ndr_long(); + int nameBufferl = src.Dec_ndr_long(); + int nameBufferi = src.Index; + src.Advance(2 * nameBufferl); + if (Name.Buffer == null) + { + if (nameBuffers < 0 || nameBuffers > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Name.Buffer = new short[nameBuffers]; + } + src = src.Derive(nameBufferi); + for (int i = 0; i < nameBufferl; i++) + { + Name.Buffer[i] = (short)src.Dec_ndr_short(); + } + } + if (sidp != 0) + { + if (Sid == null) + { + Sid = new Rpc.SidT(); + } + src = src.Deferred; + Sid.Decode(src); + } + } + } + + public class LsarDnsDomainInfo : NdrObject + { + public Rpc.Unicode_string Name; + + public Rpc.Unicode_string DnsDomain; + + public Rpc.Unicode_string DnsForest; + + public Rpc.UuidT DomainGuid; + + public Rpc.SidT Sid; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_short(Name.Length); + dst.Enc_ndr_short(Name.MaximumLength); + dst.Enc_ndr_referent(Name.Buffer, 1); + dst.Enc_ndr_short(DnsDomain.Length); + dst.Enc_ndr_short(DnsDomain.MaximumLength); + dst.Enc_ndr_referent(DnsDomain.Buffer, 1); + dst.Enc_ndr_short(DnsForest.Length); + dst.Enc_ndr_short(DnsForest.MaximumLength); + dst.Enc_ndr_referent(DnsForest.Buffer, 1); + dst.Enc_ndr_long(DomainGuid.TimeLow); + dst.Enc_ndr_short(DomainGuid.TimeMid); + dst.Enc_ndr_short(DomainGuid.TimeHiAndVersion); + dst.Enc_ndr_small(DomainGuid.ClockSeqHiAndReserved); + dst.Enc_ndr_small(DomainGuid.ClockSeqLow); + int domainGuidNodes = 6; + int domainGuidNodei = dst.Index; + dst.Advance(1 * domainGuidNodes); + dst.Enc_ndr_referent(Sid, 1); + if (Name.Buffer != null) + { + dst = dst.Deferred; + int nameBufferl = Name.Length / 2; + int nameBuffers = Name.MaximumLength / 2; + dst.Enc_ndr_long(nameBuffers); + dst.Enc_ndr_long(0); + dst.Enc_ndr_long(nameBufferl); + int nameBufferi = dst.Index; + dst.Advance(2 * nameBufferl); + dst = dst.Derive(nameBufferi); + for (int i = 0; i < nameBufferl; i++) + { + dst.Enc_ndr_short(Name.Buffer[i]); + } + } + if (DnsDomain.Buffer != null) + { + dst = dst.Deferred; + int dnsDomainBufferl = DnsDomain.Length / 2; + int dnsDomainBuffers = DnsDomain.MaximumLength / 2; + dst.Enc_ndr_long(dnsDomainBuffers); + dst.Enc_ndr_long(0); + dst.Enc_ndr_long(dnsDomainBufferl); + int dnsDomainBufferi = dst.Index; + dst.Advance(2 * dnsDomainBufferl); + dst = dst.Derive(dnsDomainBufferi); + for (int i = 0; i < dnsDomainBufferl; i++) + { + dst.Enc_ndr_short(DnsDomain.Buffer[i]); + } + } + if (DnsForest.Buffer != null) + { + dst = dst.Deferred; + int dnsForestBufferl = DnsForest.Length / 2; + int dnsForestBuffers = DnsForest.MaximumLength / 2; + dst.Enc_ndr_long(dnsForestBuffers); + dst.Enc_ndr_long(0); + dst.Enc_ndr_long(dnsForestBufferl); + int dnsForestBufferi = dst.Index; + dst.Advance(2 * dnsForestBufferl); + dst = dst.Derive(dnsForestBufferi); + for (int i = 0; i < dnsForestBufferl; i++) + { + dst.Enc_ndr_short(DnsForest.Buffer[i]); + } + } + dst = dst.Derive(domainGuidNodei); + for (int i1 = 0; i1 < domainGuidNodes; i1++) + { + dst.Enc_ndr_small(DomainGuid.Node[i1]); + } + if (Sid != null) + { + dst = dst.Deferred; + Sid.Encode(dst); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + src.Align(4); + if (Name == null) + { + Name = new Rpc.Unicode_string(); + } + Name.Length = (short)src.Dec_ndr_short(); + Name.MaximumLength = (short)src.Dec_ndr_short(); + int nameBufferp = src.Dec_ndr_long(); + src.Align(4); + if (DnsDomain == null) + { + DnsDomain = new Rpc.Unicode_string(); + } + DnsDomain.Length = (short)src.Dec_ndr_short(); + DnsDomain.MaximumLength = (short)src.Dec_ndr_short(); + int dnsDomainBufferp = src.Dec_ndr_long(); + src.Align(4); + if (DnsForest == null) + { + DnsForest = new Rpc.Unicode_string(); + } + DnsForest.Length = (short)src.Dec_ndr_short(); + DnsForest.MaximumLength = (short)src.Dec_ndr_short(); + int dnsForestBufferp = src.Dec_ndr_long(); + src.Align(4); + if (DomainGuid == null) + { + DomainGuid = new Rpc.UuidT(); + } + DomainGuid.TimeLow = src.Dec_ndr_long(); + DomainGuid.TimeMid = (short)src.Dec_ndr_short(); + DomainGuid.TimeHiAndVersion = (short)src.Dec_ndr_short(); + DomainGuid.ClockSeqHiAndReserved = unchecked((byte)src.Dec_ndr_small()); + DomainGuid.ClockSeqLow = unchecked((byte)src.Dec_ndr_small()); + int domainGuidNodes = 6; + int domainGuidNodei = src.Index; + src.Advance(1 * domainGuidNodes); + int sidp = src.Dec_ndr_long(); + if (nameBufferp != 0) + { + src = src.Deferred; + int nameBuffers = src.Dec_ndr_long(); + src.Dec_ndr_long(); + int nameBufferl = src.Dec_ndr_long(); + int nameBufferi = src.Index; + src.Advance(2 * nameBufferl); + if (Name.Buffer == null) + { + if (nameBuffers < 0 || nameBuffers > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Name.Buffer = new short[nameBuffers]; + } + src = src.Derive(nameBufferi); + for (int i = 0; i < nameBufferl; i++) + { + Name.Buffer[i] = (short)src.Dec_ndr_short(); + } + } + if (dnsDomainBufferp != 0) + { + src = src.Deferred; + int dnsDomainBuffers = src.Dec_ndr_long(); + src.Dec_ndr_long(); + int dnsDomainBufferl = src.Dec_ndr_long(); + int dnsDomainBufferi = src.Index; + src.Advance(2 * dnsDomainBufferl); + if (DnsDomain.Buffer == null) + { + if (dnsDomainBuffers < 0 || dnsDomainBuffers > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + DnsDomain.Buffer = new short[dnsDomainBuffers]; + } + src = src.Derive(dnsDomainBufferi); + for (int i = 0; i < dnsDomainBufferl; i++) + { + DnsDomain.Buffer[i] = (short)src.Dec_ndr_short(); + } + } + if (dnsForestBufferp != 0) + { + src = src.Deferred; + int dnsForestBuffers = src.Dec_ndr_long(); + src.Dec_ndr_long(); + int dnsForestBufferl = src.Dec_ndr_long(); + int dnsForestBufferi = src.Index; + src.Advance(2 * dnsForestBufferl); + if (DnsForest.Buffer == null) + { + if (dnsForestBuffers < 0 || dnsForestBuffers > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + DnsForest.Buffer = new short[dnsForestBuffers]; + } + src = src.Derive(dnsForestBufferi); + for (int i = 0; i < dnsForestBufferl; i++) + { + DnsForest.Buffer[i] = (short)src.Dec_ndr_short(); + } + } + if (DomainGuid.Node == null) + { + if (domainGuidNodes < 0 || domainGuidNodes > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + DomainGuid.Node = new byte[domainGuidNodes]; + } + src = src.Derive(domainGuidNodei); + for (int i1 = 0; i1 < domainGuidNodes; i1++) + { + DomainGuid.Node[i1] = unchecked((byte)src.Dec_ndr_small()); + } + if (sidp != 0) + { + if (Sid == null) + { + Sid = new Rpc.SidT(); + } + src = src.Deferred; + Sid.Decode(src); + } + } + } + + public const int PolicyInfoAuditEvents = 2; + + public const int PolicyInfoPrimaryDomain = 3; + + public const int PolicyInfoAccountDomain = 5; + + public const int PolicyInfoServerRole = 6; + + public const int PolicyInfoModification = 9; + + public const int PolicyInfoDnsDomain = 12; + + public class LsarSidPtr : NdrObject + { + public Rpc.SidT Sid; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_referent(Sid, 1); + if (Sid != null) + { + dst = dst.Deferred; + Sid.Encode(dst); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + int sidp = src.Dec_ndr_long(); + if (sidp != 0) + { + if (Sid == null) + { + Sid = new Rpc.SidT(); + } + src = src.Deferred; + Sid.Decode(src); + } + } + } + + public class LsarSidArray : NdrObject + { + public int NumSids; + + public LsarSidPtr[] Sids; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(NumSids); + dst.Enc_ndr_referent(Sids, 1); + if (Sids != null) + { + dst = dst.Deferred; + int sidss = NumSids; + dst.Enc_ndr_long(sidss); + int sidsi = dst.Index; + dst.Advance(4 * sidss); + dst = dst.Derive(sidsi); + for (int i = 0; i < sidss; i++) + { + Sids[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + NumSids = src.Dec_ndr_long(); + int sidsp = src.Dec_ndr_long(); + if (sidsp != 0) + { + src = src.Deferred; + int sidss = src.Dec_ndr_long(); + int sidsi = src.Index; + src.Advance(4 * sidss); + if (Sids == null) + { + if (sidss < 0 || sidss > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Sids = new LsarSidPtr[sidss]; + } + src = src.Derive(sidsi); + for (int i = 0; i < sidss; i++) + { + if (Sids[i] == null) + { + Sids[i] = new LsarSidPtr(); + } + Sids[i].Decode(src); + } + } + } + } + + public const int SidNameUseNone = 0; + + public const int SidNameUser = 1; + + public const int SidNameDomGrp = 2; + + public const int SidNameDomain = 3; + + public const int SidNameAlias = 4; + + public const int SidNameWknGrp = 5; + + public const int SidNameDeleted = 6; + + public const int SidNameInvalid = 7; + + public const int SidNameUnknown = 8; + + public class LsarTranslatedSid : NdrObject + { + public int SidType; + + public int Rid; + + public int SidIndex; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_short(SidType); + dst.Enc_ndr_long(Rid); + dst.Enc_ndr_long(SidIndex); + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + SidType = src.Dec_ndr_short(); + Rid = src.Dec_ndr_long(); + SidIndex = src.Dec_ndr_long(); + } + } + + public class LsarTransSidArray : NdrObject + { + public int Count; + + public LsarTranslatedSid[] Sids; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Count); + dst.Enc_ndr_referent(Sids, 1); + if (Sids != null) + { + dst = dst.Deferred; + int sidss = Count; + dst.Enc_ndr_long(sidss); + int sidsi = dst.Index; + dst.Advance(12 * sidss); + dst = dst.Derive(sidsi); + for (int i = 0; i < sidss; i++) + { + Sids[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Count = src.Dec_ndr_long(); + int sidsp = src.Dec_ndr_long(); + if (sidsp != 0) + { + src = src.Deferred; + int sidss = src.Dec_ndr_long(); + int sidsi = src.Index; + src.Advance(12 * sidss); + if (Sids == null) + { + if (sidss < 0 || sidss > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Sids = new LsarTranslatedSid[sidss]; + } + src = src.Derive(sidsi); + for (int i = 0; i < sidss; i++) + { + if (Sids[i] == null) + { + Sids[i] = new LsarTranslatedSid(); + } + Sids[i].Decode(src); + } + } + } + } + + public class LsarTrustInformation : NdrObject + { + public Rpc.Unicode_string Name; + + public Rpc.SidT Sid; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_short(Name.Length); + dst.Enc_ndr_short(Name.MaximumLength); + dst.Enc_ndr_referent(Name.Buffer, 1); + dst.Enc_ndr_referent(Sid, 1); + if (Name.Buffer != null) + { + dst = dst.Deferred; + int nameBufferl = Name.Length / 2; + int nameBuffers = Name.MaximumLength / 2; + dst.Enc_ndr_long(nameBuffers); + dst.Enc_ndr_long(0); + dst.Enc_ndr_long(nameBufferl); + int nameBufferi = dst.Index; + dst.Advance(2 * nameBufferl); + dst = dst.Derive(nameBufferi); + for (int i = 0; i < nameBufferl; i++) + { + dst.Enc_ndr_short(Name.Buffer[i]); + } + } + if (Sid != null) + { + dst = dst.Deferred; + Sid.Encode(dst); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + src.Align(4); + if (Name == null) + { + Name = new Rpc.Unicode_string(); + } + Name.Length = (short)src.Dec_ndr_short(); + Name.MaximumLength = (short)src.Dec_ndr_short(); + int nameBufferp = src.Dec_ndr_long(); + int sidp = src.Dec_ndr_long(); + if (nameBufferp != 0) + { + src = src.Deferred; + int nameBuffers = src.Dec_ndr_long(); + src.Dec_ndr_long(); + int nameBufferl = src.Dec_ndr_long(); + int nameBufferi = src.Index; + src.Advance(2 * nameBufferl); + if (Name.Buffer == null) + { + if (nameBuffers < 0 || nameBuffers > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Name.Buffer = new short[nameBuffers]; + } + src = src.Derive(nameBufferi); + for (int i = 0; i < nameBufferl; i++) + { + Name.Buffer[i] = (short)src.Dec_ndr_short(); + } + } + if (sidp != 0) + { + if (Sid == null) + { + Sid = new Rpc.SidT(); + } + src = src.Deferred; + Sid.Decode(src); + } + } + } + + public class LsarRefDomainList : NdrObject + { + public int Count; + + public LsarTrustInformation[] Domains; + + public int MaxCount; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Count); + dst.Enc_ndr_referent(Domains, 1); + dst.Enc_ndr_long(MaxCount); + if (Domains != null) + { + dst = dst.Deferred; + int domainss = Count; + dst.Enc_ndr_long(domainss); + int domainsi = dst.Index; + dst.Advance(12 * domainss); + dst = dst.Derive(domainsi); + for (int i = 0; i < domainss; i++) + { + Domains[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Count = src.Dec_ndr_long(); + int domainsp = src.Dec_ndr_long(); + MaxCount = src.Dec_ndr_long(); + if (domainsp != 0) + { + src = src.Deferred; + int domainss = src.Dec_ndr_long(); + int domainsi = src.Index; + src.Advance(12 * domainss); + if (Domains == null) + { + if (domainss < 0 || domainss > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Domains = new LsarTrustInformation[domainss]; + } + src = src.Derive(domainsi); + for (int i = 0; i < domainss; i++) + { + if (Domains[i] == null) + { + Domains[i] = new LsarTrustInformation(); + } + Domains[i].Decode(src); + } + } + } + } + + public class LsarTranslatedName : NdrObject + { + public short SidType; + + public Rpc.Unicode_string Name; + + public int SidIndex; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_short(SidType); + dst.Enc_ndr_short(Name.Length); + dst.Enc_ndr_short(Name.MaximumLength); + dst.Enc_ndr_referent(Name.Buffer, 1); + dst.Enc_ndr_long(SidIndex); + if (Name.Buffer != null) + { + dst = dst.Deferred; + int nameBufferl = Name.Length / 2; + int nameBuffers = Name.MaximumLength / 2; + dst.Enc_ndr_long(nameBuffers); + dst.Enc_ndr_long(0); + dst.Enc_ndr_long(nameBufferl); + int nameBufferi = dst.Index; + dst.Advance(2 * nameBufferl); + dst = dst.Derive(nameBufferi); + for (int i = 0; i < nameBufferl; i++) + { + dst.Enc_ndr_short(Name.Buffer[i]); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + SidType = (short)src.Dec_ndr_short(); + src.Align(4); + if (Name == null) + { + Name = new Rpc.Unicode_string(); + } + Name.Length = (short)src.Dec_ndr_short(); + Name.MaximumLength = (short)src.Dec_ndr_short(); + int nameBufferp = src.Dec_ndr_long(); + SidIndex = src.Dec_ndr_long(); + if (nameBufferp != 0) + { + src = src.Deferred; + int nameBuffers = src.Dec_ndr_long(); + src.Dec_ndr_long(); + int nameBufferl = src.Dec_ndr_long(); + int nameBufferi = src.Index; + src.Advance(2 * nameBufferl); + if (Name.Buffer == null) + { + if (nameBuffers < 0 || nameBuffers > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Name.Buffer = new short[nameBuffers]; + } + src = src.Derive(nameBufferi); + for (int i = 0; i < nameBufferl; i++) + { + Name.Buffer[i] = (short)src.Dec_ndr_short(); + } + } + } + } + + public class LsarTransNameArray : NdrObject + { + public int Count; + + public LsarTranslatedName[] Names; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Count); + dst.Enc_ndr_referent(Names, 1); + if (Names != null) + { + dst = dst.Deferred; + int namess = Count; + dst.Enc_ndr_long(namess); + int namesi = dst.Index; + dst.Advance(16 * namess); + dst = dst.Derive(namesi); + for (int i = 0; i < namess; i++) + { + Names[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Count = src.Dec_ndr_long(); + int namesp = src.Dec_ndr_long(); + if (namesp != 0) + { + src = src.Deferred; + int namess = src.Dec_ndr_long(); + int namesi = src.Index; + src.Advance(16 * namess); + if (Names == null) + { + if (namess < 0 || namess > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Names = new LsarTranslatedName[namess]; + } + src = src.Derive(namesi); + for (int i = 0; i < namess; i++) + { + if (Names[i] == null) + { + Names[i] = new LsarTranslatedName(); + } + Names[i].Decode(src); + } + } + } + } + + public class LsarClose : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x00); + } + + public int Retval; + + public Rpc.PolicyHandle Handle; + + public LsarClose(Rpc.PolicyHandle handle) + { + this.Handle = handle; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + Handle.Encode(dst); + } + + /// + public override void Decode_out(NdrBuffer src) + { + Handle.Decode(src); + Retval = src.Dec_ndr_long(); + } + } + + public class LsarQueryInformationPolicy : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x07); + } + + public int Retval; + + public Rpc.PolicyHandle Handle; + + public short Level; + + public NdrObject Info; + + public LsarQueryInformationPolicy(Rpc.PolicyHandle handle, short level, NdrObject + info) + { + this.Handle = handle; + this.Level = level; + this.Info = info; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + Handle.Encode(dst); + dst.Enc_ndr_short(Level); + } + + /// + public override void Decode_out(NdrBuffer src) + { + int infop = src.Dec_ndr_long(); + if (infop != 0) + { + src.Dec_ndr_short(); + Info.Decode(src); + } + Retval = src.Dec_ndr_long(); + } + } + + public class LsarLookupSids : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x0f); + } + + public int Retval; + + public Rpc.PolicyHandle Handle; + + public LsarSidArray Sids; + + public LsarRefDomainList Domains; + + public LsarTransNameArray Names; + + public short Level; + + public int Count; + + public LsarLookupSids(Rpc.PolicyHandle handle, LsarSidArray sids, LsarRefDomainList + domains, LsarTransNameArray names, short level, int count) + { + this.Handle = handle; + this.Sids = sids; + this.Domains = domains; + this.Names = names; + this.Level = level; + this.Count = count; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + Handle.Encode(dst); + Sids.Encode(dst); + Names.Encode(dst); + dst.Enc_ndr_short(Level); + dst.Enc_ndr_long(Count); + } + + /// + public override void Decode_out(NdrBuffer src) + { + int domainsp = src.Dec_ndr_long(); + if (domainsp != 0) + { + if (Domains == null) + { + Domains = new LsarRefDomainList(); + } + Domains.Decode(src); + } + Names.Decode(src); + Count = src.Dec_ndr_long(); + Retval = src.Dec_ndr_long(); + } + } + + public class LsarOpenPolicy2 : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x2c); + } + + public int Retval; + + public string SystemName; + + public LsarObjectAttributes ObjectAttributes; + + public int DesiredAccess; + + public Rpc.PolicyHandle PolicyHandle; + + public LsarOpenPolicy2(string systemName, LsarObjectAttributes objectAttributes + , int desiredAccess, Rpc.PolicyHandle policyHandle) + { + this.SystemName = systemName; + this.ObjectAttributes = objectAttributes; + this.DesiredAccess = desiredAccess; + this.PolicyHandle = policyHandle; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + dst.Enc_ndr_referent(SystemName, 1); + if (SystemName != null) + { + dst.Enc_ndr_string(SystemName); + } + ObjectAttributes.Encode(dst); + dst.Enc_ndr_long(DesiredAccess); + } + + /// + public override void Decode_out(NdrBuffer src) + { + PolicyHandle.Decode(src); + Retval = src.Dec_ndr_long(); + } + } + + public class LsarQueryInformationPolicy2 : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x2e); + } + + public int Retval; + + public Rpc.PolicyHandle Handle; + + public short Level; + + public NdrObject Info; + + public LsarQueryInformationPolicy2(Rpc.PolicyHandle handle, short level, NdrObject + info) + { + this.Handle = handle; + this.Level = level; + this.Info = info; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + Handle.Encode(dst); + dst.Enc_ndr_short(Level); + } + + /// + public override void Decode_out(NdrBuffer src) + { + int infop = src.Dec_ndr_long(); + if (infop != 0) + { + src.Dec_ndr_short(); + Info.Decode(src); + } + Retval = src.Dec_ndr_long(); + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcDfsRootEnum.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcDfsRootEnum.cs new file mode 100644 index 0000000000..6a9d4302a7 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcDfsRootEnum.cs @@ -0,0 +1,43 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Dcerpc.Ndr; +using SharpCifs.Smb; + +namespace SharpCifs.Dcerpc.Msrpc +{ + public class MsrpcDfsRootEnum : Netdfs.NetrDfsEnumEx + { + public MsrpcDfsRootEnum(string server) : base(server, 200, unchecked(0xFFFF), new Netdfs.DfsEnumStruct(), new NdrLong(0)) + { + Info.Level = Level; + Info.E = new Netdfs.DfsEnumArray200(); + Ptype = 0; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + + public virtual IFileEntry[] GetEntries() + { + Netdfs.DfsEnumArray200 a200 = (Netdfs.DfsEnumArray200)Info.E; + SmbShareInfo[] entries = new SmbShareInfo[a200.Count]; + for (int i = 0; i < a200.Count; i++) + { + entries[i] = new SmbShareInfo(a200.S[i].DfsName, 0, null); + } + return entries; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcEnumerateAliasesInDomain.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcEnumerateAliasesInDomain.cs new file mode 100644 index 0000000000..d9c0afb344 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcEnumerateAliasesInDomain.cs @@ -0,0 +1,29 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Msrpc +{ + public class MsrpcEnumerateAliasesInDomain : Samr.SamrEnumerateAliasesInDomain + { + public MsrpcEnumerateAliasesInDomain(SamrDomainHandle domainHandle, int acctFlags + , Samr.SamrSamArray sam) : base(domainHandle, 0, acctFlags, null, 0) + { + this.Sam = sam; + Ptype = 0; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcGetMembersInAlias.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcGetMembersInAlias.cs new file mode 100644 index 0000000000..77b2ee3751 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcGetMembersInAlias.cs @@ -0,0 +1,29 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Msrpc +{ + public class MsrpcGetMembersInAlias : Samr.SamrGetMembersInAlias + { + public MsrpcGetMembersInAlias(SamrAliasHandle aliasHandle, Lsarpc.LsarSidArray sids + ) : base(aliasHandle, sids) + { + this.Sids = sids; + Ptype = 0; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcLookupSids.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcLookupSids.cs new file mode 100644 index 0000000000..0aaf310267 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcLookupSids.cs @@ -0,0 +1,34 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Smb; + +namespace SharpCifs.Dcerpc.Msrpc +{ + public class MsrpcLookupSids : Lsarpc.LsarLookupSids + { + internal Sid[] sids; + + public MsrpcLookupSids(LsaPolicyHandle policyHandle, Sid[] sids) : base(policyHandle + , new LsarSidArrayX(sids), new Lsarpc.LsarRefDomainList(), new Lsarpc.LsarTransNameArray + (), 1, sids.Length) + { + this.sids = sids; + Ptype = 0; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcLsarOpenPolicy2.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcLsarOpenPolicy2.cs new file mode 100644 index 0000000000..9d2c2a0f40 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcLsarOpenPolicy2.cs @@ -0,0 +1,35 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Msrpc +{ + public class MsrpcLsarOpenPolicy2 : Lsarpc.LsarOpenPolicy2 + { + public MsrpcLsarOpenPolicy2(string server, int access, LsaPolicyHandle policyHandle + ) : base(server, new Lsarpc.LsarObjectAttributes(), access, policyHandle) + { + ObjectAttributes.Length = 24; + Lsarpc.LsarQosInfo qos = new Lsarpc.LsarQosInfo(); + qos.Length = 12; + qos.ImpersonationLevel = 2; + qos.ContextMode = 1; + qos.EffectiveOnly = 0; + ObjectAttributes.SecurityQualityOfService = qos; + Ptype = 0; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcQueryInformationPolicy.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcQueryInformationPolicy.cs new file mode 100644 index 0000000000..820d81ab24 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcQueryInformationPolicy.cs @@ -0,0 +1,30 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Dcerpc.Ndr; + +namespace SharpCifs.Dcerpc.Msrpc +{ + public class MsrpcQueryInformationPolicy : Lsarpc.LsarQueryInformationPolicy + { + public MsrpcQueryInformationPolicy(LsaPolicyHandle policyHandle, short level, NdrObject + info) : base(policyHandle, level, info) + { + Ptype = 0; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcSamrConnect2.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcSamrConnect2.cs new file mode 100644 index 0000000000..80c45257c2 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcSamrConnect2.cs @@ -0,0 +1,28 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Msrpc +{ + public class MsrpcSamrConnect2 : Samr.SamrConnect2 + { + public MsrpcSamrConnect2(string server, int access, SamrPolicyHandle policyHandle + ) : base(server, access, policyHandle) + { + Ptype = 0; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcSamrConnect4.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcSamrConnect4.cs new file mode 100644 index 0000000000..0f2603e9ce --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcSamrConnect4.cs @@ -0,0 +1,28 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Msrpc +{ + public class MsrpcSamrConnect4 : Samr.SamrConnect4 + { + public MsrpcSamrConnect4(string server, int access, SamrPolicyHandle policyHandle + ) : base(server, 2, access, policyHandle) + { + Ptype = 0; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcSamrOpenAlias.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcSamrOpenAlias.cs new file mode 100644 index 0000000000..e0b9b68d39 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcSamrOpenAlias.cs @@ -0,0 +1,28 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Msrpc +{ + public class MsrpcSamrOpenAlias : Samr.SamrOpenAlias + { + public MsrpcSamrOpenAlias(SamrDomainHandle handle, int access, int rid, SamrAliasHandle + aliasHandle) : base(handle, access, rid, aliasHandle) + { + Ptype = 0; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcSamrOpenDomain.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcSamrOpenDomain.cs new file mode 100644 index 0000000000..2ac6bceed0 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcSamrOpenDomain.cs @@ -0,0 +1,28 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Msrpc +{ + public class MsrpcSamrOpenDomain : Samr.SamrOpenDomain + { + public MsrpcSamrOpenDomain(SamrPolicyHandle handle, int access, Rpc.SidT sid, SamrDomainHandle + domainHandle) : base(handle, access, sid, domainHandle) + { + Ptype = 0; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcShareEnum.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcShareEnum.cs new file mode 100644 index 0000000000..7c7b64abff --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcShareEnum.cs @@ -0,0 +1,55 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Smb; + +namespace SharpCifs.Dcerpc.Msrpc +{ + public class MsrpcShareEnum : Srvsvc.ShareEnumAll + { + internal class MsrpcShareInfo1 : SmbShareInfo + { + internal MsrpcShareInfo1(MsrpcShareEnum enclosing, Srvsvc.ShareInfo1 info1) + { + this._enclosing = enclosing; + NetName = info1.Netname; + Type = info1.Type; + Remark = info1.Remark; + } + + private readonly MsrpcShareEnum _enclosing; + } + + public MsrpcShareEnum(string server) : base("\\\\" + server, 1, new Srvsvc.ShareInfoCtr1 + (), -1, 0, 0) + { + Ptype = 0; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + + public virtual IFileEntry[] GetEntries() + { + Srvsvc.ShareInfoCtr1 ctr = (Srvsvc.ShareInfoCtr1)Info; + MsrpcShareInfo1[] entries = new MsrpcShareInfo1[ctr + .Count]; + for (int i = 0; i < ctr.Count; i++) + { + entries[i] = new MsrpcShareInfo1(this, ctr.Array[i]); + } + return entries; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcShareGetInfo.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcShareGetInfo.cs new file mode 100644 index 0000000000..802ed61a3a --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/MsrpcShareGetInfo.cs @@ -0,0 +1,43 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Smb; + +namespace SharpCifs.Dcerpc.Msrpc +{ + public class MsrpcShareGetInfo : Srvsvc.ShareGetInfo + { + public MsrpcShareGetInfo(string server, string sharename) : base(server, sharename + , 502, new Srvsvc.ShareInfo502()) + { + Ptype = 0; + Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag; + } + + /// + public virtual Ace[] GetSecurity() + { + Srvsvc.ShareInfo502 info502 = (Srvsvc.ShareInfo502)Info; + if (info502.SecurityDescriptor != null) + { + SecurityDescriptor sd; + sd = new SecurityDescriptor(info502.SecurityDescriptor, 0, info502.SdSize); + return sd.Aces; + } + return null; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/Netdfs.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/Netdfs.cs new file mode 100644 index 0000000000..a338b28858 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/Netdfs.cs @@ -0,0 +1,616 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Dcerpc.Ndr; + +namespace SharpCifs.Dcerpc.Msrpc +{ + public class Netdfs + { + public static string GetSyntax() + { + return "4fc742e0-4a10-11cf-8273-00aa004ae673:3.0"; + } + + public const int DfsVolumeFlavorStandalone = unchecked(0x100); + + public const int DfsVolumeFlavorAdBlob = unchecked(0x200); + + public const int DfsStorageStateOffline = unchecked(0x0001); + + public const int DfsStorageStateOnline = unchecked(0x0002); + + public const int DfsStorageStateActive = unchecked(0x0004); + + public class DfsInfo1 : NdrObject + { + public string EntryPath; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_referent(EntryPath, 1); + if (EntryPath != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(EntryPath); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + int entryPathp = src.Dec_ndr_long(); + if (entryPathp != 0) + { + src = src.Deferred; + EntryPath = src.Dec_ndr_string(); + } + } + } + + public class DfsEnumArray1 : NdrObject + { + public int Count; + + public DfsInfo1[] S; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Count); + dst.Enc_ndr_referent(S, 1); + if (S != null) + { + dst = dst.Deferred; + int ss = Count; + dst.Enc_ndr_long(ss); + int si = dst.Index; + dst.Advance(4 * ss); + dst = dst.Derive(si); + for (int i = 0; i < ss; i++) + { + S[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Count = src.Dec_ndr_long(); + int sp = src.Dec_ndr_long(); + if (sp != 0) + { + src = src.Deferred; + int ss = src.Dec_ndr_long(); + int si = src.Index; + src.Advance(4 * ss); + if (S == null) + { + if (ss < 0 || ss > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + S = new DfsInfo1[ss]; + } + src = src.Derive(si); + for (int i = 0; i < ss; i++) + { + if (S[i] == null) + { + S[i] = new DfsInfo1(); + } + S[i].Decode(src); + } + } + } + } + + public class DfsStorageInfo : NdrObject + { + public int State; + + public string ServerName; + + public string ShareName; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(State); + dst.Enc_ndr_referent(ServerName, 1); + dst.Enc_ndr_referent(ShareName, 1); + if (ServerName != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(ServerName); + } + if (ShareName != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(ShareName); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + State = src.Dec_ndr_long(); + int serverNamep = src.Dec_ndr_long(); + int shareNamep = src.Dec_ndr_long(); + if (serverNamep != 0) + { + src = src.Deferred; + ServerName = src.Dec_ndr_string(); + } + if (shareNamep != 0) + { + src = src.Deferred; + ShareName = src.Dec_ndr_string(); + } + } + } + + public class DfsInfo3 : NdrObject + { + public string Path; + + public string Comment; + + public int State; + + public int NumStores; + + public DfsStorageInfo[] Stores; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_referent(Path, 1); + dst.Enc_ndr_referent(Comment, 1); + dst.Enc_ndr_long(State); + dst.Enc_ndr_long(NumStores); + dst.Enc_ndr_referent(Stores, 1); + if (Path != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(Path); + } + if (Comment != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(Comment); + } + if (Stores != null) + { + dst = dst.Deferred; + int storess = NumStores; + dst.Enc_ndr_long(storess); + int storesi = dst.Index; + dst.Advance(12 * storess); + dst = dst.Derive(storesi); + for (int i = 0; i < storess; i++) + { + Stores[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + int pathp = src.Dec_ndr_long(); + int commentp = src.Dec_ndr_long(); + State = src.Dec_ndr_long(); + NumStores = src.Dec_ndr_long(); + int storesp = src.Dec_ndr_long(); + if (pathp != 0) + { + src = src.Deferred; + Path = src.Dec_ndr_string(); + } + if (commentp != 0) + { + src = src.Deferred; + Comment = src.Dec_ndr_string(); + } + if (storesp != 0) + { + src = src.Deferred; + int storess = src.Dec_ndr_long(); + int storesi = src.Index; + src.Advance(12 * storess); + if (Stores == null) + { + if (storess < 0 || storess > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Stores = new DfsStorageInfo[storess]; + } + src = src.Derive(storesi); + for (int i = 0; i < storess; i++) + { + if (Stores[i] == null) + { + Stores[i] = new DfsStorageInfo(); + } + Stores[i].Decode(src); + } + } + } + } + + public class DfsEnumArray3 : NdrObject + { + public int Count; + + public DfsInfo3[] S; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Count); + dst.Enc_ndr_referent(S, 1); + if (S != null) + { + dst = dst.Deferred; + int ss = Count; + dst.Enc_ndr_long(ss); + int si = dst.Index; + dst.Advance(20 * ss); + dst = dst.Derive(si); + for (int i = 0; i < ss; i++) + { + S[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Count = src.Dec_ndr_long(); + int sp = src.Dec_ndr_long(); + if (sp != 0) + { + src = src.Deferred; + int ss = src.Dec_ndr_long(); + int si = src.Index; + src.Advance(20 * ss); + if (S == null) + { + if (ss < 0 || ss > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + S = new DfsInfo3[ss]; + } + src = src.Derive(si); + for (int i = 0; i < ss; i++) + { + if (S[i] == null) + { + S[i] = new DfsInfo3(); + } + S[i].Decode(src); + } + } + } + } + + public class DfsInfo200 : NdrObject + { + public string DfsName; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_referent(DfsName, 1); + if (DfsName != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(DfsName); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + int dfsNamep = src.Dec_ndr_long(); + if (dfsNamep != 0) + { + src = src.Deferred; + DfsName = src.Dec_ndr_string(); + } + } + } + + public class DfsEnumArray200 : NdrObject + { + public int Count; + + public DfsInfo200[] S; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Count); + dst.Enc_ndr_referent(S, 1); + if (S != null) + { + dst = dst.Deferred; + int ss = Count; + dst.Enc_ndr_long(ss); + int si = dst.Index; + dst.Advance(4 * ss); + dst = dst.Derive(si); + for (int i = 0; i < ss; i++) + { + S[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Count = src.Dec_ndr_long(); + int sp = src.Dec_ndr_long(); + if (sp != 0) + { + src = src.Deferred; + int ss = src.Dec_ndr_long(); + int si = src.Index; + src.Advance(4 * ss); + if (S == null) + { + if (ss < 0 || ss > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + S = new DfsInfo200[ss]; + } + src = src.Derive(si); + for (int i = 0; i < ss; i++) + { + if (S[i] == null) + { + S[i] = new DfsInfo200(); + } + S[i].Decode(src); + } + } + } + } + + public class DfsInfo300 : NdrObject + { + public int Flags; + + public string DfsName; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Flags); + dst.Enc_ndr_referent(DfsName, 1); + if (DfsName != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(DfsName); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Flags = src.Dec_ndr_long(); + int dfsNamep = src.Dec_ndr_long(); + if (dfsNamep != 0) + { + src = src.Deferred; + DfsName = src.Dec_ndr_string(); + } + } + } + + public class DfsEnumArray300 : NdrObject + { + public int Count; + + public DfsInfo300[] S; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Count); + dst.Enc_ndr_referent(S, 1); + if (S != null) + { + dst = dst.Deferred; + int ss = Count; + dst.Enc_ndr_long(ss); + int si = dst.Index; + dst.Advance(8 * ss); + dst = dst.Derive(si); + for (int i = 0; i < ss; i++) + { + S[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Count = src.Dec_ndr_long(); + int sp = src.Dec_ndr_long(); + if (sp != 0) + { + src = src.Deferred; + int ss = src.Dec_ndr_long(); + int si = src.Index; + src.Advance(8 * ss); + if (S == null) + { + if (ss < 0 || ss > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + S = new DfsInfo300[ss]; + } + src = src.Derive(si); + for (int i = 0; i < ss; i++) + { + if (S[i] == null) + { + S[i] = new DfsInfo300(); + } + S[i].Decode(src); + } + } + } + } + + public class DfsEnumStruct : NdrObject + { + public int Level; + + public NdrObject E; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Level); + int descr = Level; + dst.Enc_ndr_long(descr); + dst.Enc_ndr_referent(E, 1); + if (E != null) + { + dst = dst.Deferred; + E.Encode(dst); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Level = src.Dec_ndr_long(); + src.Dec_ndr_long(); + int ep = src.Dec_ndr_long(); + if (ep != 0) + { + if (E == null) + { + E = new DfsEnumArray1(); + } + src = src.Deferred; + E.Decode(src); + } + } + } + + public class NetrDfsEnumEx : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x15); + } + + public int Retval; + + public string DfsName; + + public int Level; + + public int Prefmaxlen; + + public DfsEnumStruct Info; + + public NdrLong Totalentries; + + public NetrDfsEnumEx(string dfsName, int level, int prefmaxlen, DfsEnumStruct + info, NdrLong totalentries) + { + this.DfsName = dfsName; + this.Level = level; + this.Prefmaxlen = prefmaxlen; + this.Info = info; + this.Totalentries = totalentries; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + dst.Enc_ndr_string(DfsName); + dst.Enc_ndr_long(Level); + dst.Enc_ndr_long(Prefmaxlen); + dst.Enc_ndr_referent(Info, 1); + if (Info != null) + { + Info.Encode(dst); + } + dst.Enc_ndr_referent(Totalentries, 1); + if (Totalentries != null) + { + Totalentries.Encode(dst); + } + } + + /// + public override void Decode_out(NdrBuffer src) + { + int infop = src.Dec_ndr_long(); + if (infop != 0) + { + if (Info == null) + { + Info = new DfsEnumStruct(); + } + Info.Decode(src); + } + int totalentriesp = src.Dec_ndr_long(); + if (totalentriesp != 0) + { + Totalentries.Decode(src); + } + Retval = src.Dec_ndr_long(); + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/Samr.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/Samr.cs new file mode 100644 index 0000000000..bdc71695ed --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/Samr.cs @@ -0,0 +1,579 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Dcerpc.Ndr; + +namespace SharpCifs.Dcerpc.Msrpc +{ + public class Samr + { + public static string GetSyntax() + { + return "12345778-1234-abcd-ef00-0123456789ac:1.0"; + } + + public const int AcbDisabled = 1; + + public const int AcbHomdirreq = 2; + + public const int AcbPwnotreq = 4; + + public const int AcbTempdup = 8; + + public const int AcbNormal = 16; + + public const int AcbMns = 32; + + public const int AcbDomtrust = 64; + + public const int AcbWstrust = 128; + + public const int AcbSvrtrust = 256; + + public const int AcbPwnoexp = 512; + + public const int AcbAutolock = 1024; + + public const int AcbEncTxtPwdAllowed = 2048; + + public const int AcbSmartcardRequired = 4096; + + public const int AcbTrustedForDelegation = 8192; + + public const int AcbNotDelegated = 16384; + + public const int AcbUseDesKeyOnly = 32768; + + public const int AcbDontRequirePreauth = 65536; + + public class SamrCloseHandle : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x01); + } + + public int Retval; + + public Rpc.PolicyHandle Handle; + + public SamrCloseHandle(Rpc.PolicyHandle handle) + { + this.Handle = handle; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + Handle.Encode(dst); + } + + /// + public override void Decode_out(NdrBuffer src) + { + Retval = src.Dec_ndr_long(); + } + } + + public class SamrConnect2 : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x39); + } + + public int Retval; + + public string SystemName; + + public int AccessMask; + + public Rpc.PolicyHandle Handle; + + public SamrConnect2(string systemName, int accessMask, Rpc.PolicyHandle handle + ) + { + this.SystemName = systemName; + this.AccessMask = accessMask; + this.Handle = handle; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + dst.Enc_ndr_referent(SystemName, 1); + if (SystemName != null) + { + dst.Enc_ndr_string(SystemName); + } + dst.Enc_ndr_long(AccessMask); + } + + /// + public override void Decode_out(NdrBuffer src) + { + Handle.Decode(src); + Retval = src.Dec_ndr_long(); + } + } + + public class SamrConnect4 : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x3e); + } + + public int Retval; + + public string SystemName; + + public int Unknown; + + public int AccessMask; + + public Rpc.PolicyHandle Handle; + + public SamrConnect4(string systemName, int unknown, int accessMask, Rpc.PolicyHandle + handle) + { + this.SystemName = systemName; + this.Unknown = unknown; + this.AccessMask = accessMask; + this.Handle = handle; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + dst.Enc_ndr_referent(SystemName, 1); + if (SystemName != null) + { + dst.Enc_ndr_string(SystemName); + } + dst.Enc_ndr_long(Unknown); + dst.Enc_ndr_long(AccessMask); + } + + /// + public override void Decode_out(NdrBuffer src) + { + Handle.Decode(src); + Retval = src.Dec_ndr_long(); + } + } + + public class SamrOpenDomain : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x07); + } + + public int Retval; + + public Rpc.PolicyHandle Handle; + + public int AccessMask; + + public Rpc.SidT Sid; + + public Rpc.PolicyHandle DomainHandle; + + public SamrOpenDomain(Rpc.PolicyHandle handle, int accessMask, Rpc.SidT sid, Rpc.PolicyHandle + domainHandle) + { + this.Handle = handle; + this.AccessMask = accessMask; + this.Sid = sid; + this.DomainHandle = domainHandle; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + Handle.Encode(dst); + dst.Enc_ndr_long(AccessMask); + Sid.Encode(dst); + } + + /// + public override void Decode_out(NdrBuffer src) + { + DomainHandle.Decode(src); + Retval = src.Dec_ndr_long(); + } + } + + public class SamrSamEntry : NdrObject + { + public int Idx; + + public Rpc.Unicode_string Name; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Idx); + dst.Enc_ndr_short(Name.Length); + dst.Enc_ndr_short(Name.MaximumLength); + dst.Enc_ndr_referent(Name.Buffer, 1); + if (Name.Buffer != null) + { + dst = dst.Deferred; + int nameBufferl = Name.Length / 2; + int nameBuffers = Name.MaximumLength / 2; + dst.Enc_ndr_long(nameBuffers); + dst.Enc_ndr_long(0); + dst.Enc_ndr_long(nameBufferl); + int nameBufferi = dst.Index; + dst.Advance(2 * nameBufferl); + dst = dst.Derive(nameBufferi); + for (int i = 0; i < nameBufferl; i++) + { + dst.Enc_ndr_short(Name.Buffer[i]); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Idx = src.Dec_ndr_long(); + src.Align(4); + if (Name == null) + { + Name = new Rpc.Unicode_string(); + } + Name.Length = (short)src.Dec_ndr_short(); + Name.MaximumLength = (short)src.Dec_ndr_short(); + int nameBufferp = src.Dec_ndr_long(); + if (nameBufferp != 0) + { + src = src.Deferred; + int nameBuffers = src.Dec_ndr_long(); + src.Dec_ndr_long(); + int nameBufferl = src.Dec_ndr_long(); + int nameBufferi = src.Index; + src.Advance(2 * nameBufferl); + if (Name.Buffer == null) + { + if (nameBuffers < 0 || nameBuffers > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Name.Buffer = new short[nameBuffers]; + } + src = src.Derive(nameBufferi); + for (int i = 0; i < nameBufferl; i++) + { + Name.Buffer[i] = (short)src.Dec_ndr_short(); + } + } + } + } + + public class SamrSamArray : NdrObject + { + public int Count; + + public SamrSamEntry[] Entries; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Count); + dst.Enc_ndr_referent(Entries, 1); + if (Entries != null) + { + dst = dst.Deferred; + int entriess = Count; + dst.Enc_ndr_long(entriess); + int entriesi = dst.Index; + dst.Advance(12 * entriess); + dst = dst.Derive(entriesi); + for (int i = 0; i < entriess; i++) + { + Entries[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Count = src.Dec_ndr_long(); + int entriesp = src.Dec_ndr_long(); + if (entriesp != 0) + { + src = src.Deferred; + int entriess = src.Dec_ndr_long(); + int entriesi = src.Index; + src.Advance(12 * entriess); + if (Entries == null) + { + if (entriess < 0 || entriess > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Entries = new SamrSamEntry[entriess]; + } + src = src.Derive(entriesi); + for (int i = 0; i < entriess; i++) + { + if (Entries[i] == null) + { + Entries[i] = new SamrSamEntry(); + } + Entries[i].Decode(src); + } + } + } + } + + public class SamrEnumerateAliasesInDomain : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x0f); + } + + public int Retval; + + public Rpc.PolicyHandle DomainHandle; + + public int ResumeHandle; + + public int AcctFlags; + + public SamrSamArray Sam; + + public int NumEntries; + + public SamrEnumerateAliasesInDomain(Rpc.PolicyHandle domainHandle, int resumeHandle + , int acctFlags, SamrSamArray sam, int numEntries) + { + this.DomainHandle = domainHandle; + this.ResumeHandle = resumeHandle; + this.AcctFlags = acctFlags; + this.Sam = sam; + this.NumEntries = numEntries; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + DomainHandle.Encode(dst); + dst.Enc_ndr_long(ResumeHandle); + dst.Enc_ndr_long(AcctFlags); + } + + /// + public override void Decode_out(NdrBuffer src) + { + ResumeHandle = src.Dec_ndr_long(); + int samp = src.Dec_ndr_long(); + if (samp != 0) + { + if (Sam == null) + { + Sam = new SamrSamArray(); + } + Sam.Decode(src); + } + NumEntries = src.Dec_ndr_long(); + Retval = src.Dec_ndr_long(); + } + } + + public class SamrOpenAlias : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x1b); + } + + public int Retval; + + public Rpc.PolicyHandle DomainHandle; + + public int AccessMask; + + public int Rid; + + public Rpc.PolicyHandle AliasHandle; + + public SamrOpenAlias(Rpc.PolicyHandle domainHandle, int accessMask, int rid, Rpc.PolicyHandle + aliasHandle) + { + this.DomainHandle = domainHandle; + this.AccessMask = accessMask; + this.Rid = rid; + this.AliasHandle = aliasHandle; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + DomainHandle.Encode(dst); + dst.Enc_ndr_long(AccessMask); + dst.Enc_ndr_long(Rid); + } + + /// + public override void Decode_out(NdrBuffer src) + { + AliasHandle.Decode(src); + Retval = src.Dec_ndr_long(); + } + } + + public class SamrGetMembersInAlias : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x21); + } + + public int Retval; + + public Rpc.PolicyHandle AliasHandle; + + public Lsarpc.LsarSidArray Sids; + + public SamrGetMembersInAlias(Rpc.PolicyHandle aliasHandle, Lsarpc.LsarSidArray + sids) + { + this.AliasHandle = aliasHandle; + this.Sids = sids; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + AliasHandle.Encode(dst); + } + + /// + public override void Decode_out(NdrBuffer src) + { + Sids.Decode(src); + Retval = src.Dec_ndr_long(); + } + } + + public const int SeGroupMandatory = 1; + + public const int SeGroupEnabledByDefault = 2; + + public const int SeGroupEnabled = 4; + + public const int SeGroupOwner = 8; + + public const int SeGroupUseForDenyOnly = 16; + + public const int SeGroupResource = 536870912; + + public const int SeGroupLogonId = -1073741824; + + public class SamrRidWithAttribute : NdrObject + { + public int Rid; + + public int Attributes; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Rid); + dst.Enc_ndr_long(Attributes); + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Rid = src.Dec_ndr_long(); + Attributes = src.Dec_ndr_long(); + } + } + + public class SamrRidWithAttributeArray : NdrObject + { + public int Count; + + public SamrRidWithAttribute[] Rids; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Count); + dst.Enc_ndr_referent(Rids, 1); + if (Rids != null) + { + dst = dst.Deferred; + int ridss = Count; + dst.Enc_ndr_long(ridss); + int ridsi = dst.Index; + dst.Advance(8 * ridss); + dst = dst.Derive(ridsi); + for (int i = 0; i < ridss; i++) + { + Rids[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Count = src.Dec_ndr_long(); + int ridsp = src.Dec_ndr_long(); + if (ridsp != 0) + { + src = src.Deferred; + int ridss = src.Dec_ndr_long(); + int ridsi = src.Index; + src.Advance(8 * ridss); + if (Rids == null) + { + if (ridss < 0 || ridss > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Rids = new SamrRidWithAttribute[ridss]; + } + src = src.Derive(ridsi); + for (int i = 0; i < ridss; i++) + { + if (Rids[i] == null) + { + Rids[i] = new SamrRidWithAttribute(); + } + Rids[i].Decode(src); + } + } + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/SamrAliasHandle.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/SamrAliasHandle.cs new file mode 100644 index 0000000000..d4ebdacc49 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/SamrAliasHandle.cs @@ -0,0 +1,40 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Smb; + +namespace SharpCifs.Dcerpc.Msrpc +{ + public class SamrAliasHandle : Rpc.PolicyHandle + { + /// + public SamrAliasHandle(DcerpcHandle handle, SamrDomainHandle domainHandle, int access + , int rid) + { + MsrpcSamrOpenAlias rpc = new MsrpcSamrOpenAlias(domainHandle, access, rid, this); + handle.Sendrecv(rpc); + if (rpc.Retval != 0) + { + throw new SmbException(rpc.Retval, false); + } + } + + /// + public virtual void Close() + { + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/SamrDomainHandle.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/SamrDomainHandle.cs new file mode 100644 index 0000000000..d44c798861 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/SamrDomainHandle.cs @@ -0,0 +1,41 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Smb; + +namespace SharpCifs.Dcerpc.Msrpc +{ + public class SamrDomainHandle : Rpc.PolicyHandle + { + /// + public SamrDomainHandle(DcerpcHandle handle, SamrPolicyHandle policyHandle, int access + , Rpc.SidT sid) + { + MsrpcSamrOpenDomain rpc = new MsrpcSamrOpenDomain(policyHandle, access, sid, this + ); + handle.Sendrecv(rpc); + if (rpc.Retval != 0) + { + throw new SmbException(rpc.Retval, false); + } + } + + /// + public virtual void Close() + { + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/SamrPolicyHandle.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/SamrPolicyHandle.cs new file mode 100644 index 0000000000..0cd3f9369c --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/SamrPolicyHandle.cs @@ -0,0 +1,49 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Msrpc +{ + public class SamrPolicyHandle : Rpc.PolicyHandle + { + /// + public SamrPolicyHandle(DcerpcHandle handle, string server, int access) + { + if (server == null) + { + server = "\\\\"; + } + MsrpcSamrConnect4 rpc = new MsrpcSamrConnect4(server, access, this); + try + { + handle.Sendrecv(rpc); + } + catch (DcerpcException de) + { + if (de.GetErrorCode() != DcerpcError.DcerpcFaultOpRngError) + { + throw; + } + MsrpcSamrConnect2 rpc2 = new MsrpcSamrConnect2(server, access, this); + handle.Sendrecv(rpc2); + } + } + + /// + public virtual void Close() + { + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/Srvsvc.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/Srvsvc.cs new file mode 100644 index 0000000000..f33f483278 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Msrpc/Srvsvc.cs @@ -0,0 +1,734 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Dcerpc.Ndr; + +namespace SharpCifs.Dcerpc.Msrpc +{ + public class Srvsvc + { + public static string GetSyntax() + { + return "4b324fc8-1670-01d3-1278-5a47bf6ee188:3.0"; + } + + public class ShareInfo0 : NdrObject + { + public string Netname; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_referent(Netname, 1); + if (Netname != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(Netname); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + int netnamep = src.Dec_ndr_long(); + if (netnamep != 0) + { + src = src.Deferred; + Netname = src.Dec_ndr_string(); + } + } + } + + public class ShareInfoCtr0 : NdrObject + { + public int Count; + + public ShareInfo0[] Array; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Count); + dst.Enc_ndr_referent(Array, 1); + if (Array != null) + { + dst = dst.Deferred; + int arrays = Count; + dst.Enc_ndr_long(arrays); + int arrayi = dst.Index; + dst.Advance(4 * arrays); + dst = dst.Derive(arrayi); + for (int i = 0; i < arrays; i++) + { + Array[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Count = src.Dec_ndr_long(); + int arrayp = src.Dec_ndr_long(); + if (arrayp != 0) + { + src = src.Deferred; + int arrays = src.Dec_ndr_long(); + int arrayi = src.Index; + src.Advance(4 * arrays); + if (Array == null) + { + if (arrays < 0 || arrays > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Array = new ShareInfo0[arrays]; + } + src = src.Derive(arrayi); + for (int i = 0; i < arrays; i++) + { + if (Array[i] == null) + { + Array[i] = new ShareInfo0(); + } + Array[i].Decode(src); + } + } + } + } + + public class ShareInfo1 : NdrObject + { + public string Netname; + + public int Type; + + public string Remark; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_referent(Netname, 1); + dst.Enc_ndr_long(Type); + dst.Enc_ndr_referent(Remark, 1); + if (Netname != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(Netname); + } + if (Remark != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(Remark); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + int netnamep = src.Dec_ndr_long(); + Type = src.Dec_ndr_long(); + int remarkp = src.Dec_ndr_long(); + if (netnamep != 0) + { + src = src.Deferred; + Netname = src.Dec_ndr_string(); + } + if (remarkp != 0) + { + src = src.Deferred; + Remark = src.Dec_ndr_string(); + } + } + } + + public class ShareInfoCtr1 : NdrObject + { + public int Count; + + public ShareInfo1[] Array; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Count); + dst.Enc_ndr_referent(Array, 1); + if (Array != null) + { + dst = dst.Deferred; + int arrays = Count; + dst.Enc_ndr_long(arrays); + int arrayi = dst.Index; + dst.Advance(12 * arrays); + dst = dst.Derive(arrayi); + for (int i = 0; i < arrays; i++) + { + Array[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Count = src.Dec_ndr_long(); + int arrayp = src.Dec_ndr_long(); + if (arrayp != 0) + { + src = src.Deferred; + int arrays = src.Dec_ndr_long(); + int arrayi = src.Index; + src.Advance(12 * arrays); + if (Array == null) + { + if (arrays < 0 || arrays > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Array = new ShareInfo1[arrays]; + } + src = src.Derive(arrayi); + for (int i = 0; i < arrays; i++) + { + if (Array[i] == null) + { + Array[i] = new ShareInfo1(); + } + Array[i].Decode(src); + } + } + } + } + + public class ShareInfo502 : NdrObject + { + public string Netname; + + public int Type; + + public string Remark; + + public int Permissions; + + public int MaxUses; + + public int CurrentUses; + + public string Path; + + public string Password; + + public int SdSize; + + public byte[] SecurityDescriptor; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_referent(Netname, 1); + dst.Enc_ndr_long(Type); + dst.Enc_ndr_referent(Remark, 1); + dst.Enc_ndr_long(Permissions); + dst.Enc_ndr_long(MaxUses); + dst.Enc_ndr_long(CurrentUses); + dst.Enc_ndr_referent(Path, 1); + dst.Enc_ndr_referent(Password, 1); + dst.Enc_ndr_long(SdSize); + dst.Enc_ndr_referent(SecurityDescriptor, 1); + if (Netname != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(Netname); + } + if (Remark != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(Remark); + } + if (Path != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(Path); + } + if (Password != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(Password); + } + if (SecurityDescriptor != null) + { + dst = dst.Deferred; + int securityDescriptors = SdSize; + dst.Enc_ndr_long(securityDescriptors); + int securityDescriptori = dst.Index; + dst.Advance(1 * securityDescriptors); + dst = dst.Derive(securityDescriptori); + for (int i = 0; i < securityDescriptors; i++) + { + dst.Enc_ndr_small(SecurityDescriptor[i]); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + int netnamep = src.Dec_ndr_long(); + Type = src.Dec_ndr_long(); + int remarkp = src.Dec_ndr_long(); + Permissions = src.Dec_ndr_long(); + MaxUses = src.Dec_ndr_long(); + CurrentUses = src.Dec_ndr_long(); + int pathp = src.Dec_ndr_long(); + int passwordp = src.Dec_ndr_long(); + SdSize = src.Dec_ndr_long(); + int securityDescriptorp = src.Dec_ndr_long(); + if (netnamep != 0) + { + src = src.Deferred; + Netname = src.Dec_ndr_string(); + } + if (remarkp != 0) + { + src = src.Deferred; + Remark = src.Dec_ndr_string(); + } + if (pathp != 0) + { + src = src.Deferred; + Path = src.Dec_ndr_string(); + } + if (passwordp != 0) + { + src = src.Deferred; + Password = src.Dec_ndr_string(); + } + if (securityDescriptorp != 0) + { + src = src.Deferred; + int securityDescriptors = src.Dec_ndr_long(); + int securityDescriptori = src.Index; + src.Advance(1 * securityDescriptors); + if (SecurityDescriptor == null) + { + if (securityDescriptors < 0 || securityDescriptors > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + SecurityDescriptor = new byte[securityDescriptors]; + } + src = src.Derive(securityDescriptori); + for (int i = 0; i < securityDescriptors; i++) + { + SecurityDescriptor[i] = unchecked((byte)src.Dec_ndr_small()); + } + } + } + } + + public class ShareInfoCtr502 : NdrObject + { + public int Count; + + public ShareInfo502[] Array; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Count); + dst.Enc_ndr_referent(Array, 1); + if (Array != null) + { + dst = dst.Deferred; + int arrays = Count; + dst.Enc_ndr_long(arrays); + int arrayi = dst.Index; + dst.Advance(40 * arrays); + dst = dst.Derive(arrayi); + for (int i = 0; i < arrays; i++) + { + Array[i].Encode(dst); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Count = src.Dec_ndr_long(); + int arrayp = src.Dec_ndr_long(); + if (arrayp != 0) + { + src = src.Deferred; + int arrays = src.Dec_ndr_long(); + int arrayi = src.Index; + src.Advance(40 * arrays); + if (Array == null) + { + if (arrays < 0 || arrays > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Array = new ShareInfo502[arrays]; + } + src = src.Derive(arrayi); + for (int i = 0; i < arrays; i++) + { + if (Array[i] == null) + { + Array[i] = new ShareInfo502(); + } + Array[i].Decode(src); + } + } + } + } + + public class ShareEnumAll : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x0f); + } + + public int Retval; + + public string Servername; + + public int Level; + + public NdrObject Info; + + public int Prefmaxlen; + + public int Totalentries; + + public int ResumeHandle; + + public ShareEnumAll(string servername, int level, NdrObject info, int prefmaxlen, + int totalentries, int resumeHandle) + { + this.Servername = servername; + this.Level = level; + this.Info = info; + this.Prefmaxlen = prefmaxlen; + this.Totalentries = totalentries; + this.ResumeHandle = resumeHandle; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + dst.Enc_ndr_referent(Servername, 1); + if (Servername != null) + { + dst.Enc_ndr_string(Servername); + } + dst.Enc_ndr_long(Level); + int descr = Level; + dst.Enc_ndr_long(descr); + dst.Enc_ndr_referent(Info, 1); + if (Info != null) + { + dst = dst.Deferred; + Info.Encode(dst); + } + dst.Enc_ndr_long(Prefmaxlen); + dst.Enc_ndr_long(ResumeHandle); + } + + /// + public override void Decode_out(NdrBuffer src) + { + Level = src.Dec_ndr_long(); + src.Dec_ndr_long(); + int infop = src.Dec_ndr_long(); + if (infop != 0) + { + if (Info == null) + { + Info = new ShareInfoCtr0(); + } + src = src.Deferred; + Info.Decode(src); + } + Totalentries = src.Dec_ndr_long(); + ResumeHandle = src.Dec_ndr_long(); + Retval = src.Dec_ndr_long(); + } + } + + public class ShareGetInfo : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x10); + } + + public int Retval; + + public string Servername; + + public string Sharename; + + public int Level; + + public NdrObject Info; + + public ShareGetInfo(string servername, string sharename, int level, NdrObject info + ) + { + this.Servername = servername; + this.Sharename = sharename; + this.Level = level; + this.Info = info; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + dst.Enc_ndr_referent(Servername, 1); + if (Servername != null) + { + dst.Enc_ndr_string(Servername); + } + dst.Enc_ndr_string(Sharename); + dst.Enc_ndr_long(Level); + } + + /// + public override void Decode_out(NdrBuffer src) + { + src.Dec_ndr_long(); + int infop = src.Dec_ndr_long(); + if (infop != 0) + { + if (Info == null) + { + Info = new ShareInfo0(); + } + src = src.Deferred; + Info.Decode(src); + } + Retval = src.Dec_ndr_long(); + } + } + + public class ServerInfo100 : NdrObject + { + public int PlatformId; + + public string Name; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(PlatformId); + dst.Enc_ndr_referent(Name, 1); + if (Name != null) + { + dst = dst.Deferred; + dst.Enc_ndr_string(Name); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + PlatformId = src.Dec_ndr_long(); + int namep = src.Dec_ndr_long(); + if (namep != 0) + { + src = src.Deferred; + Name = src.Dec_ndr_string(); + } + } + } + + public class ServerGetInfo : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x15); + } + + public int Retval; + + public string Servername; + + public int Level; + + public NdrObject Info; + + public ServerGetInfo(string servername, int level, NdrObject info) + { + this.Servername = servername; + this.Level = level; + this.Info = info; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + dst.Enc_ndr_referent(Servername, 1); + if (Servername != null) + { + dst.Enc_ndr_string(Servername); + } + dst.Enc_ndr_long(Level); + } + + /// + public override void Decode_out(NdrBuffer src) + { + src.Dec_ndr_long(); + int infop = src.Dec_ndr_long(); + if (infop != 0) + { + if (Info == null) + { + Info = new ServerInfo100(); + } + src = src.Deferred; + Info.Decode(src); + } + Retval = src.Dec_ndr_long(); + } + } + + public class TimeOfDayInfo : NdrObject + { + public int Elapsedt; + + public int Msecs; + + public int Hours; + + public int Mins; + + public int Secs; + + public int Hunds; + + public int Timezone; + + public int Tinterval; + + public int Day; + + public int Month; + + public int Year; + + public int Weekday; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Elapsedt); + dst.Enc_ndr_long(Msecs); + dst.Enc_ndr_long(Hours); + dst.Enc_ndr_long(Mins); + dst.Enc_ndr_long(Secs); + dst.Enc_ndr_long(Hunds); + dst.Enc_ndr_long(Timezone); + dst.Enc_ndr_long(Tinterval); + dst.Enc_ndr_long(Day); + dst.Enc_ndr_long(Month); + dst.Enc_ndr_long(Year); + dst.Enc_ndr_long(Weekday); + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Elapsedt = src.Dec_ndr_long(); + Msecs = src.Dec_ndr_long(); + Hours = src.Dec_ndr_long(); + Mins = src.Dec_ndr_long(); + Secs = src.Dec_ndr_long(); + Hunds = src.Dec_ndr_long(); + Timezone = src.Dec_ndr_long(); + Tinterval = src.Dec_ndr_long(); + Day = src.Dec_ndr_long(); + Month = src.Dec_ndr_long(); + Year = src.Dec_ndr_long(); + Weekday = src.Dec_ndr_long(); + } + } + + public class RemoteTod : DcerpcMessage + { + public override int GetOpnum() + { + return unchecked(0x1c); + } + + public int Retval; + + public string Servername; + + public TimeOfDayInfo Info; + + public RemoteTod(string servername, TimeOfDayInfo info) + { + this.Servername = servername; + this.Info = info; + } + + /// + public override void Encode_in(NdrBuffer dst) + { + dst.Enc_ndr_referent(Servername, 1); + if (Servername != null) + { + dst.Enc_ndr_string(Servername); + } + } + + /// + public override void Decode_out(NdrBuffer src) + { + int infop = src.Dec_ndr_long(); + if (infop != 0) + { + if (Info == null) + { + Info = new TimeOfDayInfo(); + } + Info.Decode(src); + } + Retval = src.Dec_ndr_long(); + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrBuffer.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrBuffer.cs new file mode 100644 index 0000000000..0a47de799e --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrBuffer.cs @@ -0,0 +1,305 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Dcerpc.Ndr +{ + public class NdrBuffer + { + internal int Referent; + + internal Hashtable Referents; + + internal class Entry + { + internal int Referent; + + internal object Obj; + } + + public byte[] Buf; + + public int Start; + + public int Index; + + public int Length; + + public NdrBuffer Deferred; + + public NdrBuffer(byte[] buf, int start) + { + this.Buf = buf; + this.Start = Index = start; + Length = 0; + Deferred = this; + } + + public virtual NdrBuffer Derive(int idx) + { + NdrBuffer nb = new NdrBuffer(Buf, Start); + nb.Index = idx; + nb.Deferred = Deferred; + return nb; + } + + public virtual void Reset() + { + Index = Start; + Length = 0; + Deferred = this; + } + + public virtual int GetIndex() + { + return Index; + } + + public virtual void SetIndex(int index) + { + this.Index = index; + } + + public virtual int GetCapacity() + { + return Buf.Length - Start; + } + + public virtual int GetTailSpace() + { + return Buf.Length - Index; + } + + public virtual byte[] GetBuffer() + { + return Buf; + } + + public virtual int Align(int boundary, byte value) + { + int n = Align(boundary); + int i = n; + while (i > 0) + { + Buf[Index - i] = value; + i--; + } + return n; + } + + public virtual void WriteOctetArray(byte[] b, int i, int l) + { + Array.Copy(b, i, Buf, Index, l); + Advance(l); + } + + public virtual void ReadOctetArray(byte[] b, int i, int l) + { + Array.Copy(Buf, Index, b, i, l); + Advance(l); + } + + public virtual int GetLength() + { + return Deferred.Length; + } + + public virtual void SetLength(int length) + { + Deferred.Length = length; + } + + public virtual void Advance(int n) + { + Index += n; + if ((Index - Start) > Deferred.Length) + { + Deferred.Length = Index - Start; + } + } + + public virtual int Align(int boundary) + { + int m = boundary - 1; + int i = Index - Start; + int n = ((i + m) & ~m) - i; + Advance(n); + return n; + } + + public virtual void Enc_ndr_small(int s) + { + Buf[Index] = unchecked((byte)(s & unchecked(0xFF))); + Advance(1); + } + + public virtual int Dec_ndr_small() + { + int val = Buf[Index] & unchecked(0xFF); + Advance(1); + return val; + } + + public virtual void Enc_ndr_short(int s) + { + Align(2); + Encdec.Enc_uint16le((short)s, Buf, Index); + Advance(2); + } + + public virtual int Dec_ndr_short() + { + Align(2); + int val = Encdec.Dec_uint16le(Buf, Index); + Advance(2); + return val; + } + + public virtual void Enc_ndr_long(int l) + { + Align(4); + Encdec.Enc_uint32le(l, Buf, Index); + Advance(4); + } + + public virtual int Dec_ndr_long() + { + Align(4); + int val = Encdec.Dec_uint32le(Buf, Index); + Advance(4); + return val; + } + + public virtual void Enc_ndr_hyper(long h) + { + Align(8); + Encdec.Enc_uint64le(h, Buf, Index); + Advance(8); + } + + public virtual long Dec_ndr_hyper() + { + Align(8); + long val = Encdec.Dec_uint64le(Buf, Index); + Advance(8); + return val; + } + + public virtual void Enc_ndr_string(string s) + { + Align(4); + int i = Index; + int len = s.Length; + Encdec.Enc_uint32le(len + 1, Buf, i); + i += 4; + Encdec.Enc_uint32le(0, Buf, i); + i += 4; + Encdec.Enc_uint32le(len + 1, Buf, i); + i += 4; + try + { + Array.Copy(Runtime.GetBytesForString(s, "UTF-16LE"), 0, Buf, i, len + * 2); + } + catch (UnsupportedEncodingException) + { + } + i += len * 2; + Buf[i++] = unchecked((byte)('\0')); + Buf[i++] = unchecked((byte)('\0')); + Advance(i - Index); + } + + /// + public virtual string Dec_ndr_string() + { + Align(4); + int i = Index; + string val = null; + int len = Encdec.Dec_uint32le(Buf, i); + i += 12; + if (len != 0) + { + len--; + int size = len * 2; + try + { + if (size < 0 || size > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + val = Runtime.GetStringForBytes(Buf, i, size, "UTF-16LE"); + i += size + 2; + } + catch (UnsupportedEncodingException) + { + } + } + Advance(i - Index); + return val; + } + + private int GetDceReferent(object obj) + { + Entry e; + if (Referents == null) + { + Referents = new Hashtable(); + Referent = 1; + } + if ((e = (Entry)Referents.Get(obj)) == null) + { + e = new Entry(); + e.Referent = Referent++; + e.Obj = obj; + Referents.Put(obj, e); + } + return e.Referent; + } + + public virtual void Enc_ndr_referent(object obj, int type) + { + if (obj == null) + { + Enc_ndr_long(0); + return; + } + switch (type) + { + case 1: + case 3: + { + Enc_ndr_long(Runtime.IdentityHashCode(obj)); + return; + } + + case 2: + { + Enc_ndr_long(GetDceReferent(obj)); + return; + } + } + } + + public override string ToString() + { + return "start=" + Start + ",index=" + Index + ",length=" + GetLength(); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrException.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrException.cs new file mode 100644 index 0000000000..7757735f8b --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrException.cs @@ -0,0 +1,32 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.IO; + +namespace SharpCifs.Dcerpc.Ndr +{ + + public class NdrException : IOException + { + public static readonly string NoNullRef = "ref pointer cannot be null"; + + public static readonly string InvalidConformance = "invalid array conformance"; + + public NdrException(string msg) : base(msg) + { + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrHyper.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrHyper.cs new file mode 100644 index 0000000000..9e2932337b --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrHyper.cs @@ -0,0 +1,40 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Ndr +{ + public class NdrHyper : NdrObject + { + public long Value; + + public NdrHyper(long value) + { + this.Value = value; + } + + /// + public override void Encode(NdrBuffer dst) + { + dst.Enc_ndr_hyper(Value); + } + + /// + public override void Decode(NdrBuffer src) + { + Value = src.Dec_ndr_hyper(); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrLong.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrLong.cs new file mode 100644 index 0000000000..74d90465e9 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrLong.cs @@ -0,0 +1,40 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Ndr +{ + public class NdrLong : NdrObject + { + public int Value; + + public NdrLong(int value) + { + this.Value = value; + } + + /// + public override void Encode(NdrBuffer dst) + { + dst.Enc_ndr_long(Value); + } + + /// + public override void Decode(NdrBuffer src) + { + Value = src.Dec_ndr_long(); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrObject.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrObject.cs new file mode 100644 index 0000000000..8951fa2024 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrObject.cs @@ -0,0 +1,27 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Ndr +{ + public abstract class NdrObject + { + /// + public abstract void Encode(NdrBuffer dst); + + /// + public abstract void Decode(NdrBuffer src); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrShort.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrShort.cs new file mode 100644 index 0000000000..e2ea8c65b4 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrShort.cs @@ -0,0 +1,40 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Ndr +{ + public class NdrShort : NdrObject + { + public int Value; + + public NdrShort(int value) + { + this.Value = value & unchecked(0xFF); + } + + /// + public override void Encode(NdrBuffer dst) + { + dst.Enc_ndr_short(Value); + } + + /// + public override void Decode(NdrBuffer src) + { + Value = src.Dec_ndr_short(); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrSmall.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrSmall.cs new file mode 100644 index 0000000000..8309dea660 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Ndr/NdrSmall.cs @@ -0,0 +1,40 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc.Ndr +{ + public class NdrSmall : NdrObject + { + public int Value; + + public NdrSmall(int value) + { + this.Value = value & unchecked(0xFF); + } + + /// + public override void Encode(NdrBuffer dst) + { + dst.Enc_ndr_small(Value); + } + + /// + public override void Decode(NdrBuffer src) + { + Value = src.Dec_ndr_small(); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Rpc.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Rpc.cs new file mode 100644 index 0000000000..aa33d35224 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/Rpc.cs @@ -0,0 +1,285 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Dcerpc.Ndr; + +namespace SharpCifs.Dcerpc +{ + public class Rpc + { + public class UuidT : NdrObject + { + public int TimeLow; + + public short TimeMid; + + public short TimeHiAndVersion; + + public byte ClockSeqHiAndReserved; + + public byte ClockSeqLow; + + public byte[] Node; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(TimeLow); + dst.Enc_ndr_short(TimeMid); + dst.Enc_ndr_short(TimeHiAndVersion); + dst.Enc_ndr_small(ClockSeqHiAndReserved); + dst.Enc_ndr_small(ClockSeqLow); + int nodes = 6; + int nodei = dst.Index; + dst.Advance(1 * nodes); + dst = dst.Derive(nodei); + for (int i = 0; i < nodes; i++) + { + dst.Enc_ndr_small(Node[i]); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + TimeLow = src.Dec_ndr_long(); + TimeMid = (short)src.Dec_ndr_short(); + TimeHiAndVersion = (short)src.Dec_ndr_short(); + ClockSeqHiAndReserved = unchecked((byte)src.Dec_ndr_small()); + ClockSeqLow = unchecked((byte)src.Dec_ndr_small()); + int nodes = 6; + int nodei = src.Index; + src.Advance(1 * nodes); + if (Node == null) + { + if (nodes < 0 || nodes > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Node = new byte[nodes]; + } + src = src.Derive(nodei); + for (int i = 0; i < nodes; i++) + { + Node[i] = unchecked((byte)src.Dec_ndr_small()); + } + } + } + + public class PolicyHandle : NdrObject + { + public int Type; + + public UuidT Uuid; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_long(Type); + dst.Enc_ndr_long(Uuid.TimeLow); + dst.Enc_ndr_short(Uuid.TimeMid); + dst.Enc_ndr_short(Uuid.TimeHiAndVersion); + dst.Enc_ndr_small(Uuid.ClockSeqHiAndReserved); + dst.Enc_ndr_small(Uuid.ClockSeqLow); + int uuidNodes = 6; + int uuidNodei = dst.Index; + dst.Advance(1 * uuidNodes); + dst = dst.Derive(uuidNodei); + for (int i = 0; i < uuidNodes; i++) + { + dst.Enc_ndr_small(Uuid.Node[i]); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Type = src.Dec_ndr_long(); + src.Align(4); + if (Uuid == null) + { + Uuid = new UuidT(); + } + Uuid.TimeLow = src.Dec_ndr_long(); + Uuid.TimeMid = (short)src.Dec_ndr_short(); + Uuid.TimeHiAndVersion = (short)src.Dec_ndr_short(); + Uuid.ClockSeqHiAndReserved = unchecked((byte)src.Dec_ndr_small()); + Uuid.ClockSeqLow = unchecked((byte)src.Dec_ndr_small()); + int uuidNodes = 6; + int uuidNodei = src.Index; + src.Advance(1 * uuidNodes); + if (Uuid.Node == null) + { + if (uuidNodes < 0 || uuidNodes > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Uuid.Node = new byte[uuidNodes]; + } + src = src.Derive(uuidNodei); + for (int i = 0; i < uuidNodes; i++) + { + Uuid.Node[i] = unchecked((byte)src.Dec_ndr_small()); + } + } + } + + public class Unicode_string : NdrObject + { + public short Length; + + public short MaximumLength; + + public short[] Buffer; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + dst.Enc_ndr_short(Length); + dst.Enc_ndr_short(MaximumLength); + dst.Enc_ndr_referent(Buffer, 1); + if (Buffer != null) + { + dst = dst.Deferred; + int bufferl = Length / 2; + int buffers = MaximumLength / 2; + dst.Enc_ndr_long(buffers); + dst.Enc_ndr_long(0); + dst.Enc_ndr_long(bufferl); + int bufferi = dst.Index; + dst.Advance(2 * bufferl); + dst = dst.Derive(bufferi); + for (int i = 0; i < bufferl; i++) + { + dst.Enc_ndr_short(Buffer[i]); + } + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + Length = (short)src.Dec_ndr_short(); + MaximumLength = (short)src.Dec_ndr_short(); + int bufferp = src.Dec_ndr_long(); + if (bufferp != 0) + { + src = src.Deferred; + int buffers = src.Dec_ndr_long(); + src.Dec_ndr_long(); + int bufferl = src.Dec_ndr_long(); + int bufferi = src.Index; + src.Advance(2 * bufferl); + if (Buffer == null) + { + if (buffers < 0 || buffers > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + Buffer = new short[buffers]; + } + src = src.Derive(bufferi); + for (int i = 0; i < bufferl; i++) + { + Buffer[i] = (short)src.Dec_ndr_short(); + } + } + } + } + + public class SidT : NdrObject + { + public byte Revision; + + public byte SubAuthorityCount; + + public byte[] IdentifierAuthority; + + public int[] SubAuthority; + + /// + public override void Encode(NdrBuffer dst) + { + dst.Align(4); + int subAuthoritys = SubAuthorityCount; + dst.Enc_ndr_long(subAuthoritys); + dst.Enc_ndr_small(Revision); + dst.Enc_ndr_small(SubAuthorityCount); + int identifierAuthoritys = 6; + int identifierAuthorityi = dst.Index; + dst.Advance(1 * identifierAuthoritys); + int subAuthorityi = dst.Index; + dst.Advance(4 * subAuthoritys); + dst = dst.Derive(identifierAuthorityi); + for (int i = 0; i < identifierAuthoritys; i++) + { + dst.Enc_ndr_small(IdentifierAuthority[i]); + } + dst = dst.Derive(subAuthorityi); + for (int i1 = 0; i1 < subAuthoritys; i1++) + { + dst.Enc_ndr_long(SubAuthority[i1]); + } + } + + /// + public override void Decode(NdrBuffer src) + { + src.Align(4); + int subAuthoritys = src.Dec_ndr_long(); + Revision = unchecked((byte)src.Dec_ndr_small()); + SubAuthorityCount = unchecked((byte)src.Dec_ndr_small()); + int identifierAuthoritys = 6; + int identifierAuthorityi = src.Index; + src.Advance(1 * identifierAuthoritys); + int subAuthorityi = src.Index; + src.Advance(4 * subAuthoritys); + if (IdentifierAuthority == null) + { + if (identifierAuthoritys < 0 || identifierAuthoritys > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + IdentifierAuthority = new byte[identifierAuthoritys]; + } + src = src.Derive(identifierAuthorityi); + for (int i = 0; i < identifierAuthoritys; i++) + { + IdentifierAuthority[i] = unchecked((byte)src.Dec_ndr_small()); + } + if (SubAuthority == null) + { + if (subAuthoritys < 0 || subAuthoritys > unchecked(0xFFFF)) + { + throw new NdrException(NdrException.InvalidConformance); + } + SubAuthority = new int[subAuthoritys]; + } + src = src.Derive(subAuthorityi); + for (int i1 = 0; i1 < subAuthoritys; i1++) + { + SubAuthority[i1] = src.Dec_ndr_long(); + } + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/UUID.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/UUID.cs new file mode 100644 index 0000000000..bef4be214d --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/UUID.cs @@ -0,0 +1,148 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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; + +namespace SharpCifs.Dcerpc +{ + public class Uuid : Rpc.UuidT + { + public static int Hex_to_bin(char[] arr, int offset, int length) + { + int value = 0; + int ai; + int count; + count = 0; + for (ai = offset; ai < arr.Length && count < length; ai++) + { + value <<= 4; + switch (arr[ai]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + value += arr[ai] - '0'; + break; + } + + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + { + value += 10 + (arr[ai] - 'A'); + break; + } + + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + { + value += 10 + (arr[ai] - 'a'); + break; + } + + default: + { + throw new ArgumentException(new string(arr, offset, length)); + } + } + count++; + } + return value; + } + + internal static readonly char[] Hexchars = { '0', '1', '2', '3', '4', + '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + public static string Bin_to_hex(int value, int length) + { + char[] arr = new char[length]; + int ai = arr.Length; + while (ai-- > 0) + { + arr[ai] = Hexchars[value & unchecked(0xF)]; + value = (int)(((uint)value) >> 4); + } + return new string(arr); + } + + private static byte B(int i) + { + return unchecked((byte)(i & unchecked(0xFF))); + } + + private static short S(int i) + { + return (short)(i & unchecked(0xFFFF)); + } + + public Uuid(Rpc.UuidT uuid) + { + TimeLow = uuid.TimeLow; + TimeMid = uuid.TimeMid; + TimeHiAndVersion = uuid.TimeHiAndVersion; + ClockSeqHiAndReserved = uuid.ClockSeqHiAndReserved; + ClockSeqLow = uuid.ClockSeqLow; + Node = new byte[6]; + Node[0] = uuid.Node[0]; + Node[1] = uuid.Node[1]; + Node[2] = uuid.Node[2]; + Node[3] = uuid.Node[3]; + Node[4] = uuid.Node[4]; + Node[5] = uuid.Node[5]; + } + + public Uuid(string str) + { + char[] arr = str.ToCharArray(); + TimeLow = Hex_to_bin(arr, 0, 8); + TimeMid = S(Hex_to_bin(arr, 9, 4)); + TimeHiAndVersion = S(Hex_to_bin(arr, 14, 4)); + ClockSeqHiAndReserved = B(Hex_to_bin(arr, 19, 2)); + ClockSeqLow = B(Hex_to_bin(arr, 21, 2)); + Node = new byte[6]; + Node[0] = B(Hex_to_bin(arr, 24, 2)); + Node[1] = B(Hex_to_bin(arr, 26, 2)); + Node[2] = B(Hex_to_bin(arr, 28, 2)); + Node[3] = B(Hex_to_bin(arr, 30, 2)); + Node[4] = B(Hex_to_bin(arr, 32, 2)); + Node[5] = B(Hex_to_bin(arr, 34, 2)); + } + + public override string ToString() + { + return Bin_to_hex(TimeLow, 8) + '-' + Bin_to_hex(TimeMid, 4) + '-' + Bin_to_hex + (TimeHiAndVersion, 4) + '-' + Bin_to_hex(ClockSeqHiAndReserved, 2) + Bin_to_hex + (ClockSeqLow, 2) + '-' + Bin_to_hex(Node[0], 2) + Bin_to_hex(Node[1], 2) + Bin_to_hex + (Node[2], 2) + Bin_to_hex(Node[3], 2) + Bin_to_hex(Node[4], 2) + Bin_to_hex(Node + [5], 2); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/UnicodeString.cs b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/UnicodeString.cs new file mode 100644 index 0000000000..b0c36898ca --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Dcerpc/UnicodeString.cs @@ -0,0 +1,65 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Dcerpc +{ + public class UnicodeString : Rpc.Unicode_string + { + internal bool Zterm; + + public UnicodeString(bool zterm) + { + this.Zterm = zterm; + } + + public UnicodeString(Rpc.Unicode_string rus, bool zterm) + { + Length = rus.Length; + MaximumLength = rus.MaximumLength; + Buffer = rus.Buffer; + this.Zterm = zterm; + } + + public UnicodeString(string str, bool zterm) + { + this.Zterm = zterm; + int len = str.Length; + int zt = zterm ? 1 : 0; + Length = MaximumLength = (short)((len + zt) * 2); + Buffer = new short[len + zt]; + int i; + for (i = 0; i < len; i++) + { + Buffer[i] = (short)str[i]; + } + if (zterm) + { + Buffer[i] = 0; + } + } + + public override string ToString() + { + int len = Length / 2 - (Zterm ? 1 : 0); + char[] ca = new char[len]; + for (int i = 0; i < len; i++) + { + ca[i] = (char)Buffer[i]; + } + return new string(ca, 0, len); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/Lmhosts.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/Lmhosts.cs new file mode 100644 index 0000000000..c94d0a2600 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/Lmhosts.cs @@ -0,0 +1,202 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.IO; +using SharpCifs.Smb; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Netbios +{ + public class Lmhosts + { + private static readonly string Filename = Config.GetProperty("jcifs.netbios.lmhosts" + ); + + private static readonly Hashtable Tab = new Hashtable(); + + private static long _lastModified = 1L; + + private static int _alt; + + private static LogStream _log = LogStream.GetInstance(); + + /// + /// This is really just for + /// Jcifs.UniAddress + /// . It does + /// not throw an + /// Sharpen.UnknownHostException + /// because this + /// is queried frequently and exceptions would be rather costly to + /// throw on a regular basis here. + /// + public static NbtAddress GetByName(string host) + { + lock (typeof(Lmhosts)) + { + return GetByName(new Name(host, 0x20, null)); + } + } + + internal static NbtAddress GetByName(Name name) + { + lock (typeof(Lmhosts)) + { + NbtAddress result = null; + try + { + if (Filename != null) + { + FilePath f = new FilePath(Filename); + long lm; + if ((lm = f.LastModified()) > _lastModified) + { + _lastModified = lm; + Tab.Clear(); + _alt = 0; + + //path -> fileStream + //Populate(new FileReader(f)); + Populate(new FileReader(new FileStream(f, FileMode.Open))); + } + result = (NbtAddress)Tab[name]; + } + } + catch (FileNotFoundException fnfe) + { + if (_log.Level > 1) + { + _log.WriteLine("lmhosts file: " + Filename); + Runtime.PrintStackTrace(fnfe, _log); + } + } + catch (IOException ioe) + { + if (_log.Level > 0) + { + Runtime.PrintStackTrace(ioe, _log); + } + } + return result; + } + } + + /// + internal static void Populate(StreamReader r) + { + string line; + BufferedReader br = new BufferedReader((InputStreamReader)r); + while ((line = br.ReadLine()) != null) + { + line = line.ToUpper().Trim(); + if (line.Length == 0) + { + } + else + { + if (line[0] == '#') + { + if (line.StartsWith("#INCLUDE ")) + { + line = Runtime.Substring(line, line.IndexOf('\\')); + string url = "smb:" + line.Replace('\\', '/'); + if (_alt > 0) + { + try + { + Populate(new InputStreamReader(new SmbFileInputStream(url))); + } + catch (IOException ioe) + { + _log.WriteLine("lmhosts URL: " + url); + Runtime.PrintStackTrace(ioe, _log); + continue; + } + _alt--; + while ((line = br.ReadLine()) != null) + { + line = line.ToUpper().Trim(); + if (line.StartsWith("#END_ALTERNATE")) + { + break; + } + } + } + else + { + Populate(new InputStreamReader(new SmbFileInputStream(url))); + } + } + else + { + if (line.StartsWith("#BEGIN_ALTERNATE")) + { + _alt++; + } + else + { + if (line.StartsWith("#END_ALTERNATE") && _alt > 0) + { + _alt--; + throw new IOException("no lmhosts alternate includes loaded"); + } + } + } + } + else + { + if (char.IsDigit(line[0])) + { + char[] data = line.ToCharArray(); + int ip; + int i; + int j; + Name name; + NbtAddress addr; + char c; + c = '.'; + ip = i = 0; + for (; i < data.Length && c == '.'; i++) + { + int b = unchecked(0x00); + for (; i < data.Length && (c = data[i]) >= 48 && c <= 57; i++) + { + b = b * 10 + c - '0'; + } + ip = (ip << 8) + b; + } + while (i < data.Length && char.IsWhiteSpace(data[i])) + { + i++; + } + j = i; + while (j < data.Length && char.IsWhiteSpace(data[j]) == false) + { + j++; + } + name = new Name(Runtime.Substring(line, i, j), unchecked(0x20), null + ); + addr = new NbtAddress(name, ip, false, NbtAddress.BNode, false, false, true, true + , NbtAddress.UnknownMacAddress); + Tab.Put(name, addr); + } + } + } + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/Name.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/Name.cs new file mode 100644 index 0000000000..6c37d57a46 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/Name.cs @@ -0,0 +1,269 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.Text; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Netbios +{ + public class Name + { + private const int TypeOffset = 31; + + private const int ScopeOffset = 33; + + private static readonly string DefaultScope = Config.GetProperty("jcifs.netbios.scope" + ); + + internal static readonly string OemEncoding = Config.GetProperty("jcifs.encoding" + , Runtime.GetProperty("file.encoding")); + + public string name; + + public string Scope; + + public int HexCode; + + internal int SrcHashCode; + + public Name() + { + } + + public Name(string name, int hexCode, string scope) + { + if (name.Length > 15) + { + name = Runtime.Substring(name, 0, 15); + } + this.name = name.ToUpper(); + this.HexCode = hexCode; + this.Scope = !string.IsNullOrEmpty(scope) ? scope : DefaultScope; + SrcHashCode = 0; + } + + internal virtual int WriteWireFormat(byte[] dst, int dstIndex) + { + // write 0x20 in first byte + dst[dstIndex] = unchecked(0x20); + // write name + try + { + byte[] tmp = Runtime.GetBytesForString(name, OemEncoding + ); + int i; + for (i = 0; i < tmp.Length; i++) + { + dst[dstIndex + (2 * i + 1)] = unchecked((byte)(((tmp[i] & unchecked(0xF0)) + >> 4) + unchecked(0x41))); + dst[dstIndex + (2 * i + 2)] = unchecked((byte)((tmp[i] & unchecked(0x0F)) + + unchecked(0x41))); + } + for (; i < 15; i++) + { + dst[dstIndex + (2 * i + 1)] = unchecked(unchecked(0x43)); + dst[dstIndex + (2 * i + 2)] = unchecked(unchecked(0x41)); + } + dst[dstIndex + TypeOffset] = unchecked((byte)(((HexCode & unchecked(0xF0) + ) >> 4) + unchecked(0x41))); + dst[dstIndex + TypeOffset + 1] = unchecked((byte)((HexCode & unchecked(0x0F)) + unchecked(0x41))); + } + catch (UnsupportedEncodingException) + { + } + return ScopeOffset + WriteScopeWireFormat(dst, dstIndex + ScopeOffset); + } + + internal virtual int ReadWireFormat(byte[] src, int srcIndex) + { + byte[] tmp = new byte[ScopeOffset]; + int length = 15; + for (int i = 0; i < 15; i++) + { + tmp[i] = unchecked((byte)(((src[srcIndex + (2 * i + 1)] & unchecked(0xFF)) + - unchecked(0x41)) << 4)); + tmp[i] |= unchecked((byte)(((src[srcIndex + (2 * i + 2)] & unchecked(0xFF) + ) - unchecked(0x41)) & unchecked(0x0F))); + if (tmp[i] != unchecked((byte)' ')) + { + length = i + 1; + } + } + try + { + name = Runtime.GetStringForBytes(tmp, 0, length, OemEncoding + ); + } + catch (UnsupportedEncodingException) + { + } + HexCode = ((src[srcIndex + TypeOffset] & unchecked(0xFF)) - unchecked(0x41)) << 4; + HexCode |= ((src[srcIndex + TypeOffset + 1] & unchecked(0xFF)) - unchecked( + 0x41)) & unchecked(0x0F); + return ScopeOffset + ReadScopeWireFormat(src, srcIndex + ScopeOffset); + } + + internal int ReadWireFormatDos(byte[] src, int srcIndex) + { + + int length = 15; + byte[] tmp = new byte[length]; + + Array.Copy(src, srcIndex, tmp, 0, length); + + try + { + name = Runtime.GetStringForBytes(tmp, 0, length).Trim(); + } + catch (Exception ex) + { + + } + + HexCode = src[srcIndex + length]; + + return length + 1; + } + + + internal virtual int WriteScopeWireFormat(byte[] dst, int dstIndex) + { + if (Scope == null) + { + dst[dstIndex] = unchecked(unchecked(0x00)); + return 1; + } + // copy new scope in + dst[dstIndex++] = unchecked((byte)('.')); + try + { + Array.Copy(Runtime.GetBytesForString(Scope, OemEncoding + ), 0, dst, dstIndex, Scope.Length); + } + catch (UnsupportedEncodingException) + { + } + dstIndex += Scope.Length; + dst[dstIndex++] = unchecked(unchecked(0x00)); + // now go over scope backwards converting '.' to label length + int i = dstIndex - 2; + int e = i - Scope.Length; + int c = 0; + do + { + if (dst[i] == '.') + { + dst[i] = unchecked((byte)c); + c = 0; + } + else + { + c++; + } + } + while (i-- > e); + return Scope.Length + 2; + } + + internal virtual int ReadScopeWireFormat(byte[] src, int srcIndex) + { + int start = srcIndex; + int n; + StringBuilder sb; + if ((n = src[srcIndex++] & unchecked(0xFF)) == 0) + { + Scope = null; + return 1; + } + try + { + sb = new StringBuilder(Runtime.GetStringForBytes(src, srcIndex, n, OemEncoding)); + srcIndex += n; + while ((n = src[srcIndex++] & unchecked(0xFF)) != 0) + { + sb.Append('.').Append(Runtime.GetStringForBytes(src, srcIndex, n, OemEncoding)); + srcIndex += n; + } + Scope = sb.ToString(); + } + catch (UnsupportedEncodingException) + { + } + return srcIndex - start; + } + + public override int GetHashCode() + { + int result; + result = name.GetHashCode(); + result += 65599 * HexCode; + result += 65599 * SrcHashCode; + if (Scope != null && Scope.Length != 0) + { + result += Scope.GetHashCode(); + } + return result; + } + + public override bool Equals(object obj) + { + Name n; + if (!(obj is Name)) + { + return false; + } + n = (Name)obj; + if (Scope == null && n.Scope == null) + { + return name.Equals(n.name) && HexCode == n.HexCode; + } + return name.Equals(n.name) && HexCode == n.HexCode && Scope.Equals(n.Scope); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + + //return ""; + + string n = name; + // fix MSBROWSE name + if (n == null) + { + n = "null"; + } + else + { + if (n[0] == unchecked(0x01)) + { + char[] c = n.ToCharArray(); + c[0] = '.'; + c[1] = '.'; + c[14] = '.'; + n = new string(c); + } + } + sb.Append(n).Append("<").Append(Hexdump.ToHexString(HexCode, 2)).Append(">"); + if (Scope != null) + { + sb.Append(".").Append(Scope); + } + return sb.ToString(); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryRequest.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryRequest.cs new file mode 100644 index 0000000000..646e65bf8d --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryRequest.cs @@ -0,0 +1,52 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Netbios +{ + internal class NameQueryRequest : NameServicePacket + { + internal NameQueryRequest(Name name) + { + QuestionName = name; + QuestionType = Nb; + } + + internal override int WriteBodyWireFormat(byte[] dst, int dstIndex) + { + return WriteQuestionSectionWireFormat(dst, dstIndex); + } + + internal override int ReadBodyWireFormat(byte[] src, int srcIndex) + { + return ReadQuestionSectionWireFormat(src, srcIndex); + } + + internal override int WriteRDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadRDataWireFormat(byte[] src, int srcIndex) + { + return 0; + } + + public override string ToString() + { + return "NameQueryRequest[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryResponse.cs new file mode 100644 index 0000000000..c7fac8e934 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryResponse.cs @@ -0,0 +1,68 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Netbios +{ + internal class NameQueryResponse : NameServicePacket + { + public NameQueryResponse() + { + RecordName = new Name(); + } + + internal override int WriteBodyWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadBodyWireFormat(byte[] src, int srcIndex) + { + return ReadResourceRecordWireFormat(src, srcIndex); + } + + internal override int WriteRDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadRDataWireFormat(byte[] src, int srcIndex) + { + if (ResultCode != 0 || OpCode != Query) + { + return 0; + } + bool groupName = ((src[srcIndex] & unchecked(0x80)) == unchecked(0x80)) ? true : false; + int nodeType = (src[srcIndex] & unchecked(0x60)) >> 5; + srcIndex += 2; + int address = ReadInt4(src, srcIndex); + if (address != 0) + { + AddrEntry[AddrIndex] = new NbtAddress(RecordName, address, groupName, nodeType); + } + else + { + AddrEntry[AddrIndex] = null; + } + return 6; + } + + public override string ToString() + { + return "NameQueryResponse[" + base.ToString() + ",addrEntry=" + AddrEntry + + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServiceClient.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServiceClient.cs new file mode 100644 index 0000000000..01700e64a5 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServiceClient.cs @@ -0,0 +1,660 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Linq; +using System.Threading; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +using Thread = SharpCifs.Util.Sharpen.Thread; + +namespace SharpCifs.Netbios +{ + internal class NameServiceClient : IRunnable + { + internal const int DefaultSoTimeout = 5000; + + internal const int DefaultRcvBufSize = 576; + + internal const int DefaultSndBufSize = 576; + + internal const int NameServiceUdpPort = 137; + + internal const int DefaultRetryCount = 2; + + internal const int DefaultRetryTimeout = 3000; + + internal const int ResolverLmhosts = 1; + + internal const int ResolverBcast = 2; + + internal const int ResolverWins = 3; + + private static readonly int SndBufSize = Config.GetInt("jcifs.netbios.snd_buf_size" + , DefaultSndBufSize); + + private static readonly int RcvBufSize = Config.GetInt("jcifs.netbios.rcv_buf_size" + , DefaultRcvBufSize); + + private static readonly int SoTimeout = Config.GetInt("jcifs.netbios.soTimeout", + DefaultSoTimeout); + + private static readonly int RetryCount = Config.GetInt("jcifs.netbios.retryCount" + , DefaultRetryCount); + + private static readonly int RetryTimeout = Config.GetInt("jcifs.netbios.retryTimeout" + , DefaultRetryTimeout); + + private static readonly int Lport = Config.GetInt("jcifs.netbios.lport", 137); + + private static readonly IPAddress Laddr = Config.GetInetAddress("jcifs.netbios.laddr" + , null); + + private static readonly string Ro = Config.GetProperty("jcifs.resolveOrder"); + + private static LogStream _log = LogStream.GetInstance(); + + private readonly object _lock = new object(); + + private int _lport; + + private int _closeTimeout; + + private byte[] _sndBuf; + + private byte[] _rcvBuf; + + private SocketEx _socket; + + private Hashtable _responseTable = new Hashtable(); + + private Thread _thread; + + private int _nextNameTrnId; + + private int[] _resolveOrder; + + private bool _waitResponse = true; + + private AutoResetEvent _autoResetWaitReceive; + + internal IPAddress laddr; + + internal IPAddress Baddr; + + public NameServiceClient() + : this(Lport, Laddr) + { + } + + internal NameServiceClient(int lport, IPAddress laddr) + { + this._lport = lport; + + this.laddr = laddr + ?? Config.GetLocalHost() + ?? Extensions.GetAddressesByName(Dns.GetHostName()).FirstOrDefault(); + + try + { + Baddr = Config.GetInetAddress("jcifs.netbios.baddr", Extensions.GetAddressByName("255.255.255.255")); + } + catch (Exception ex) + { + } + + _sndBuf = new byte[SndBufSize]; + _rcvBuf = new byte[RcvBufSize]; + + + if (string.IsNullOrEmpty(Ro)) + { + if (NbtAddress.GetWinsAddress() == null) + { + _resolveOrder = new int[2]; + _resolveOrder[0] = ResolverLmhosts; + _resolveOrder[1] = ResolverBcast; + } + else + { + _resolveOrder = new int[3]; + _resolveOrder[0] = ResolverLmhosts; + _resolveOrder[1] = ResolverWins; + _resolveOrder[2] = ResolverBcast; + } + } + else + { + int[] tmp = new int[3]; + StringTokenizer st = new StringTokenizer(Ro, ","); + int i = 0; + while (st.HasMoreTokens()) + { + string s = st.NextToken().Trim(); + if (Runtime.EqualsIgnoreCase(s, "LMHOSTS")) + { + tmp[i++] = ResolverLmhosts; + } + else + { + if (Runtime.EqualsIgnoreCase(s, "WINS")) + { + if (NbtAddress.GetWinsAddress() == null) + { + if (_log.Level > 1) + { + _log.WriteLine("NetBIOS resolveOrder specifies WINS however the " + "jcifs.netbios.wins property has not been set" + ); + } + continue; + } + tmp[i++] = ResolverWins; + } + else + { + if (Runtime.EqualsIgnoreCase(s, "BCAST")) + { + tmp[i++] = ResolverBcast; + } + else + { + if (Runtime.EqualsIgnoreCase(s, "DNS")) + { + } + else + { + // skip + if (_log.Level > 1) + { + _log.WriteLine("unknown resolver method: " + s); + } + } + } + } + } + } + _resolveOrder = new int[i]; + Array.Copy(tmp, 0, _resolveOrder, 0, i); + } + } + + internal virtual int GetNextNameTrnId() + { + if ((++_nextNameTrnId & unchecked(0xFFFF)) == 0) + { + _nextNameTrnId = 1; + } + return _nextNameTrnId; + } + + /// + internal virtual void EnsureOpen(int timeout) + { + _closeTimeout = 0; + if (SoTimeout != 0) + { + _closeTimeout = Math.Max(SoTimeout, timeout); + } + // If socket is still good, the new closeTimeout will + // be ignored; see tryClose comment. + if (_socket == null) + { + _socket = new SocketEx(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + + //IPAddress.`Address` property deleted + //_socket.Bind(new IPEndPoint(laddr.Address, _lport)); + _socket.Bind(new IPEndPoint(laddr, _lport)); + + if (_waitResponse) + { + _thread = new Thread(this); //new Sharpen.Thread(this, "JCIFS-NameServiceClient"); + _thread.SetDaemon(true); + _thread.Start(); + } + } + } + + internal virtual void TryClose() + { + lock (_lock) + { + if (_socket != null) + { + //Socket.`Close` method deleted + //_socket.Close(); + _socket.Dispose(); + _socket = null; + } + _thread = null; + + if (_waitResponse) + { + _responseTable.Clear(); + } else + { + _autoResetWaitReceive.Set(); + } + } + } + + public virtual void Run() + { + int nameTrnId; + NameServicePacket response; + + try + { + + while (_thread == Thread.CurrentThread()) + { + _socket.SoTimeOut = _closeTimeout; + + int len = _socket.Receive(_rcvBuf, 0, RcvBufSize); + + if (_log.Level > 3) + { + _log.WriteLine("NetBIOS: new data read from socket"); + } + nameTrnId = NameServicePacket.ReadNameTrnId(_rcvBuf, 0); + response = (NameServicePacket)_responseTable.Get(nameTrnId); + + + if (response == null || response.Received) + { + continue; + } + + lock (response) + { + response.ReadWireFormat(_rcvBuf, 0); + + if (_log.Level > 3) + { + _log.WriteLine(response); + Hexdump.ToHexdump(_log, _rcvBuf, 0, len); + } + + if (response.IsResponse) + { + response.Received = true; + + Runtime.Notify(response); + } + } + } + + } + catch (TimeoutException) { } + catch (Exception ex) + { + if (_log.Level > 2) + { + Runtime.PrintStackTrace(ex, _log); + } + } + finally + { + TryClose(); + } + } + + /// + internal virtual void Send(NameServicePacket request, NameServicePacket response, + int timeout) + { + int nid = 0; + int max = NbtAddress.Nbns.Length; + if (max == 0) + { + max = 1; + } + + lock (response) + { + + while (max-- > 0) + { + try + { + lock (_lock) + { + request.NameTrnId = GetNextNameTrnId(); + nid = request.NameTrnId; + response.Received = false; + _responseTable.Put(nid, response); + EnsureOpen(timeout + 1000); + int requestLenght = request.WriteWireFormat(_sndBuf, 0); + _socket.Send(_sndBuf, 0, requestLenght, new IPEndPoint(request.Addr, _lport)); + if (_log.Level > 3) + { + _log.WriteLine(request); + Hexdump.ToHexdump(_log, _sndBuf, 0, requestLenght); + } + + } + if (_waitResponse) + { + long start = Runtime.CurrentTimeMillis(); + while (timeout > 0) + { + Runtime.Wait(response, timeout); + if (response.Received && request.QuestionType == response.RecordType) + { + return; + } + response.Received = false; + timeout -= (int)(Runtime.CurrentTimeMillis() - start); + } + } + } + catch (Exception ie) + { + throw new IOException(ie.Message); + } + finally + { + //Sharpen.Collections.Remove(responseTable, nid); + if (_waitResponse) + { + _responseTable.Remove(nid); + } + } + if (_waitResponse) + { + lock (_lock) + { + if (NbtAddress.IsWins(request.Addr) == false) + { + break; + } + if (request.Addr == NbtAddress.GetWinsAddress()) + { + NbtAddress.SwitchWins(); + } + request.Addr = NbtAddress.GetWinsAddress(); + } + } + } + } + } + + /// + internal virtual NbtAddress[] GetAllByName(Name name, IPAddress addr) + { + int n; + NameQueryRequest request = new NameQueryRequest(name); + NameQueryResponse response = new NameQueryResponse(); + request.Addr = addr ?? NbtAddress.GetWinsAddress(); + request.IsBroadcast = request.Addr == null; + if (request.IsBroadcast) + { + request.Addr = Baddr; + n = RetryCount; + } + else + { + request.IsBroadcast = false; + n = 1; + } + do + { + try + { + Send(request, response, RetryTimeout); + } + catch (IOException ioe) + { + if (_log.Level > 1) + { + Runtime.PrintStackTrace(ioe, _log); + } + throw new UnknownHostException(ioe); + } + if (response.Received && response.ResultCode == 0) + { + return response.AddrEntry; + } + } + while (--n > 0 && request.IsBroadcast); + throw new UnknownHostException(); + } + + /// + internal virtual NbtAddress GetByName(Name name, IPAddress addr) + { + int n; + + NameQueryRequest request = new NameQueryRequest(name); + NameQueryResponse response = new NameQueryResponse(); + if (addr != null) + { + request.Addr = addr; + request.IsBroadcast = (addr.GetAddressBytes()[3] == unchecked(unchecked(0xFF))); + n = RetryCount; + do + { + try + { + Send(request, response, RetryTimeout); + } + catch (IOException ioe) + { + if (_log.Level > 1) + { + Runtime.PrintStackTrace(ioe, _log); + } + throw new UnknownHostException(ioe); + } + if (response.Received && response.ResultCode == 0 + && response.IsResponse) + { + int last = response.AddrEntry.Length - 1; + response.AddrEntry[last].HostName.SrcHashCode = addr.GetHashCode(); + return response.AddrEntry[last]; + } + } + while (--n > 0 && request.IsBroadcast); + throw new UnknownHostException(); + } + for (int i = 0; i < _resolveOrder.Length; i++) + { + try + { + switch (_resolveOrder[i]) + { + case ResolverLmhosts: + { + NbtAddress ans = Lmhosts.GetByName(name); + if (ans != null) + { + ans.HostName.SrcHashCode = 0; + // just has to be different + // from other methods + return ans; + } + break; + } + + case ResolverWins: + case ResolverBcast: + { + if (_resolveOrder[i] == ResolverWins && name.name != NbtAddress.MasterBrowserName + && name.HexCode != unchecked(0x1d)) + { + request.Addr = NbtAddress.GetWinsAddress(); + request.IsBroadcast = false; + } + else + { + request.Addr = Baddr; + request.IsBroadcast = true; + } + n = RetryCount; + while (n-- > 0) + { + try + { + Send(request, response, RetryTimeout); + } + catch (IOException ioe) + { + if (_log.Level > 1) + { + Runtime.PrintStackTrace(ioe, _log); + } + throw new UnknownHostException(ioe); + } + if (response.Received && response.ResultCode == 0 + && response.IsResponse) + { + + response.AddrEntry[0].HostName.SrcHashCode = request.Addr.GetHashCode(); + return response.AddrEntry[0]; + } + if (_resolveOrder[i] == ResolverWins) + { + break; + } + } + break; + } + } + } + catch (IOException) + { + } + } + throw new UnknownHostException(); + } + + /// + internal virtual NbtAddress[] GetNodeStatus(NbtAddress addr) + { + int n; + int srcHashCode; + NodeStatusRequest request; + NodeStatusResponse response; + response = new NodeStatusResponse(addr); + request = new NodeStatusRequest(new Name(NbtAddress.AnyHostsName, unchecked(0x00), null)); + request.Addr = addr.GetInetAddress(); + n = RetryCount; + while (n-- > 0) + { + try + { + Send(request, response, RetryTimeout); + } + catch (IOException ioe) + { + if (_log.Level > 1) + { + Runtime.PrintStackTrace(ioe, _log); + } + throw new UnknownHostException(ioe); + } + if (response.Received && response.ResultCode == 0) + { + srcHashCode = request.Addr.GetHashCode(); + for (int i = 0; i < response.AddressArray.Length; i++) + { + response.AddressArray[i].HostName.SrcHashCode = srcHashCode; + } + return response.AddressArray; + } + } + throw new UnknownHostException(); + } + + internal virtual NbtAddress[] GetHosts() + { + try + { + _waitResponse = false; + + byte[] bAddrBytes = laddr.GetAddressBytes(); + + for (int i = 1; i <= 254; i++) + { + NodeStatusRequest request; + NodeStatusResponse response; + + byte[] addrBytes = { + bAddrBytes[0], + bAddrBytes[1], + bAddrBytes[2], + (byte)i + }; + + IPAddress addr = new IPAddress(addrBytes); + + //response = new NodeStatusResponse(new NbtAddress(NbtAddress.UnknownName, + // (int)addr.Address, false, 0x20)); + response = new NodeStatusResponse(new NbtAddress(NbtAddress.UnknownName, + BitConverter.ToInt32(addr.GetAddressBytes(), 0) , false, 0x20)); + + request = new NodeStatusRequest(new Name(NbtAddress.AnyHostsName, unchecked(0x20), null)); + request.Addr = addr; + Send(request, response, 0); + } + + } + catch (IOException ioe) + { + if (_log.Level > 1) + { + Runtime.PrintStackTrace(ioe, _log); + } + throw new UnknownHostException(ioe); + } + + _autoResetWaitReceive = new AutoResetEvent(false); + _thread = new Thread(this); + _thread.SetDaemon(true); + _thread.Start(); + + _autoResetWaitReceive.WaitOne(); + + List result = new List(); + + foreach (var key in _responseTable.Keys) + { + NodeStatusResponse resp = (NodeStatusResponse)_responseTable[key]; + + if (resp.Received && resp.ResultCode == 0) + { + foreach (var entry in resp.AddressArray) + { + if (entry.HostName.HexCode == 0x20) + { + result.Add(entry); + } + } + } + } + + _responseTable.Clear(); + + _waitResponse = true; + + return result.Count > 0 ? result.ToArray() : null; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServicePacket.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServicePacket.cs new file mode 100644 index 0000000000..28e98406e4 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServicePacket.cs @@ -0,0 +1,448 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Net; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Netbios +{ + internal abstract class NameServicePacket + { + internal const int Query = 0; + + internal const int Wack = 7; + + internal const int FmtErr = 0x1; + + internal const int SrvErr = 0x2; + + internal const int ImpErr = 0x4; + + internal const int RfsErr = 0x5; + + internal const int ActErr = 0x6; + + internal const int CftErr = 0x7; + + internal const int NbIn = 0x00200001; + + internal const int NbstatIn = 0x00210001; + + internal const int Nb = 0x0020; + + internal const int Nbstat = 0x0021; + + internal const int In = 0x0001; + + internal const int A = 0x0001; + + internal const int Ns = 0x0002; + + internal const int Null = 0x000a; + + internal const int HeaderLength = 12; + + internal const int OpcodeOffset = 2; + + internal const int QuestionOffset = 4; + + internal const int AnswerOffset = 6; + + internal const int AuthorityOffset = 8; + + internal const int AdditionalOffset = 10; + + // opcode + // rcode + // type/class + // header field offsets + internal static void WriteInt2(int val, byte[] dst, int dstIndex) + { + dst[dstIndex++] = unchecked((byte)((val >> 8) & unchecked(0xFF))); + dst[dstIndex] = unchecked((byte)(val & unchecked(0xFF))); + } + + internal static void WriteInt4(int val, byte[] dst, int dstIndex) + { + dst[dstIndex++] = unchecked((byte)((val >> 24) & unchecked(0xFF))); + dst[dstIndex++] = unchecked((byte)((val >> 16) & unchecked(0xFF))); + dst[dstIndex++] = unchecked((byte)((val >> 8) & unchecked(0xFF))); + dst[dstIndex] = unchecked((byte)(val & unchecked(0xFF))); + } + + internal static int ReadInt2(byte[] src, int srcIndex) + { + return ((src[srcIndex] & unchecked(0xFF)) << 8) + (src[srcIndex + 1] & unchecked( + 0xFF)); + } + + internal static int ReadInt4(byte[] src, int srcIndex) + { + return ((src[srcIndex] & unchecked(0xFF)) << 24) + ((src[srcIndex + 1] & unchecked( + 0xFF)) << 16) + ((src[srcIndex + 2] & unchecked(0xFF)) << 8) + (src + [srcIndex + 3] & unchecked(0xFF)); + } + + internal static int ReadNameTrnId(byte[] src, int srcIndex) + { + return ReadInt2(src, srcIndex); + } + + internal int AddrIndex; + + internal NbtAddress[] AddrEntry; + + internal int NameTrnId; + + internal int OpCode; + + internal int ResultCode; + + internal int QuestionCount; + + internal int AnswerCount; + + internal int AuthorityCount; + + internal int AdditionalCount; + + internal bool Received; + + internal bool IsResponse; + + internal bool IsAuthAnswer; + + internal bool IsTruncated; + + internal bool IsRecurDesired; + + internal bool IsRecurAvailable; + + internal bool IsBroadcast; + + internal Name QuestionName; + + internal Name RecordName; + + internal int QuestionType; + + internal int QuestionClass; + + internal int RecordType; + + internal int RecordClass; + + internal int Ttl; + + internal int RDataLength; + + internal IPAddress Addr; + + public NameServicePacket() + { + IsRecurDesired = true; + IsBroadcast = true; + QuestionCount = 1; + QuestionClass = In; + } + + internal virtual int WriteWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + dstIndex += WriteHeaderWireFormat(dst, dstIndex); + dstIndex += WriteBodyWireFormat(dst, dstIndex); + return dstIndex - start; + } + + internal virtual int ReadWireFormat(byte[] src, int srcIndex) + { + int start = srcIndex; + srcIndex += ReadHeaderWireFormat(src, srcIndex); + srcIndex += ReadBodyWireFormat(src, srcIndex); + return srcIndex - start; + } + + internal virtual int WriteHeaderWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(NameTrnId, dst, dstIndex); + dst[dstIndex + OpcodeOffset] = unchecked((byte)((IsResponse ? unchecked(0x80) : unchecked(0x00)) + ((OpCode << 3) & unchecked(0x78)) + (IsAuthAnswer + ? unchecked(0x04) : unchecked(0x00)) + (IsTruncated ? unchecked(0x02) : unchecked(0x00)) + (IsRecurDesired ? unchecked(0x01) + : unchecked(0x00)))); + dst[dstIndex + OpcodeOffset + 1] = unchecked((byte)((IsRecurAvailable ? unchecked( + 0x80) : unchecked(0x00)) + (IsBroadcast ? unchecked(0x10) : + unchecked(0x00)) + (ResultCode & unchecked(0x0F)))); + WriteInt2(QuestionCount, dst, start + QuestionOffset); + WriteInt2(AnswerCount, dst, start + AnswerOffset); + WriteInt2(AuthorityCount, dst, start + AuthorityOffset); + WriteInt2(AdditionalCount, dst, start + AdditionalOffset); + return HeaderLength; + } + + internal virtual int ReadHeaderWireFormat(byte[] src, int srcIndex) + { + NameTrnId = ReadInt2(src, srcIndex); + IsResponse = ((src[srcIndex + OpcodeOffset] & unchecked(0x80)) == 0) ? false + : true; + OpCode = (src[srcIndex + OpcodeOffset] & unchecked(0x78)) >> 3; + IsAuthAnswer = ((src[srcIndex + OpcodeOffset] & unchecked(0x04)) == 0) ? + false : true; + IsTruncated = ((src[srcIndex + OpcodeOffset] & unchecked(0x02)) == 0) ? false + : true; + IsRecurDesired = ((src[srcIndex + OpcodeOffset] & unchecked(0x01)) == 0) ? + false : true; + IsRecurAvailable = ((src[srcIndex + OpcodeOffset + 1] & unchecked(0x80)) + == 0) ? false : true; + IsBroadcast = ((src[srcIndex + OpcodeOffset + 1] & unchecked(0x10)) == 0) + ? false : true; + ResultCode = src[srcIndex + OpcodeOffset + 1] & unchecked(0x0F); + QuestionCount = ReadInt2(src, srcIndex + QuestionOffset); + AnswerCount = ReadInt2(src, srcIndex + AnswerOffset); + AuthorityCount = ReadInt2(src, srcIndex + AuthorityOffset); + AdditionalCount = ReadInt2(src, srcIndex + AdditionalOffset); + return HeaderLength; + } + + internal virtual int WriteQuestionSectionWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + dstIndex += QuestionName.WriteWireFormat(dst, dstIndex); + WriteInt2(QuestionType, dst, dstIndex); + dstIndex += 2; + WriteInt2(QuestionClass, dst, dstIndex); + dstIndex += 2; + return dstIndex - start; + } + + internal virtual int ReadQuestionSectionWireFormat(byte[] src, int srcIndex) + { + int start = srcIndex; + srcIndex += QuestionName.ReadWireFormat(src, srcIndex); + QuestionType = ReadInt2(src, srcIndex); + srcIndex += 2; + QuestionClass = ReadInt2(src, srcIndex); + srcIndex += 2; + return srcIndex - start; + } + + internal virtual int WriteResourceRecordWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + if (RecordName == QuestionName) + { + dst[dstIndex++] = unchecked(unchecked(0xC0)); + // label string pointer to + dst[dstIndex++] = unchecked(unchecked(0x0C)); + } + else + { + // questionName (offset 12) + dstIndex += RecordName.WriteWireFormat(dst, dstIndex); + } + WriteInt2(RecordType, dst, dstIndex); + dstIndex += 2; + WriteInt2(RecordClass, dst, dstIndex); + dstIndex += 2; + WriteInt4(Ttl, dst, dstIndex); + dstIndex += 4; + RDataLength = WriteRDataWireFormat(dst, dstIndex + 2); + WriteInt2(RDataLength, dst, dstIndex); + dstIndex += 2 + RDataLength; + return dstIndex - start; + } + + internal virtual int ReadResourceRecordWireFormat(byte[] src, int srcIndex) + { + int start = srcIndex; + int end; + if ((src[srcIndex] & unchecked(0xC0)) == unchecked(0xC0)) + { + RecordName = QuestionName; + // label string pointer to questionName + srcIndex += 2; + } + else + { + srcIndex += RecordName.ReadWireFormat(src, srcIndex); + } + RecordType = ReadInt2(src, srcIndex); + srcIndex += 2; + RecordClass = ReadInt2(src, srcIndex); + srcIndex += 2; + Ttl = ReadInt4(src, srcIndex); + srcIndex += 4; + RDataLength = ReadInt2(src, srcIndex); + srcIndex += 2; + AddrEntry = new NbtAddress[RDataLength / 6]; + end = srcIndex + RDataLength; + for (AddrIndex = 0; srcIndex < end; AddrIndex++) + { + srcIndex += ReadRDataWireFormat(src, srcIndex); + } + return srcIndex - start; + } + + internal abstract int WriteBodyWireFormat(byte[] dst, int dstIndex); + + internal abstract int ReadBodyWireFormat(byte[] src, int srcIndex); + + internal abstract int WriteRDataWireFormat(byte[] dst, int dstIndex); + + internal abstract int ReadRDataWireFormat(byte[] src, int srcIndex); + + public override string ToString() + { + string opCodeString; + string resultCodeString; + string questionTypeString; + string recordTypeString; + + switch (OpCode) + { + case Query: + { + opCodeString = "QUERY"; + break; + } + + case Wack: + { + opCodeString = "WACK"; + break; + } + + default: + { + opCodeString = Extensions.ToString(OpCode); + break; + } + } + switch (ResultCode) + { + case FmtErr: + { + resultCodeString = "FMT_ERR"; + break; + } + + case SrvErr: + { + resultCodeString = "SRV_ERR"; + break; + } + + case ImpErr: + { + resultCodeString = "IMP_ERR"; + break; + } + + case RfsErr: + { + resultCodeString = "RFS_ERR"; + break; + } + + case ActErr: + { + resultCodeString = "ACT_ERR"; + break; + } + + case CftErr: + { + resultCodeString = "CFT_ERR"; + break; + } + + default: + { + resultCodeString = "0x" + Hexdump.ToHexString(ResultCode, 1); + break; + } + } + switch (QuestionType) + { + case Nb: + { + questionTypeString = "NB"; + break; + } + + case Nbstat: + { + questionTypeString = "NBSTAT"; + break; + } + + default: + { + questionTypeString = "0x" + Hexdump.ToHexString(QuestionType, 4); + break; + } + } + switch (RecordType) + { + case A: + { + recordTypeString = "A"; + break; + } + + case Ns: + { + recordTypeString = "NS"; + break; + } + + case Null: + { + recordTypeString = "NULL"; + break; + } + + case Nb: + { + recordTypeString = "NB"; + break; + } + + case Nbstat: + { + recordTypeString = "NBSTAT"; + break; + } + + default: + { + recordTypeString = "0x" + Hexdump.ToHexString(RecordType, 4); + break; + } + } + return "nameTrnId=" + NameTrnId + ",isResponse=" + IsResponse + ",opCode=" + + opCodeString + ",isAuthAnswer=" + IsAuthAnswer + ",isTruncated=" + IsTruncated + + ",isRecurAvailable=" + IsRecurAvailable + ",isRecurDesired=" + IsRecurDesired + + ",isBroadcast=" + IsBroadcast + ",resultCode=" + ResultCode + ",questionCount=" + + QuestionCount + ",answerCount=" + AnswerCount + ",authorityCount=" + AuthorityCount + + ",additionalCount=" + AdditionalCount + ",questionName=" + QuestionName + ",questionType=" + + questionTypeString + ",questionClass=" + (QuestionClass == In ? "IN" : "0x" + + Hexdump.ToHexString(QuestionClass, 4)) + ",recordName=" + RecordName + ",recordType=" + + recordTypeString + ",recordClass=" + (RecordClass == In ? "IN" : "0x" + Hexdump + .ToHexString(RecordClass, 4)) + ",ttl=" + Ttl + ",rDataLength=" + RDataLength; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtAddress.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtAddress.cs new file mode 100644 index 0000000000..c64d385f1b --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtAddress.cs @@ -0,0 +1,920 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.Linq; +using System.Net; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; +using Extensions = SharpCifs.Util.Sharpen.Extensions; + +namespace SharpCifs.Netbios +{ + /// This class represents a NetBIOS over TCP/IP address. + /// + /// This class represents a NetBIOS over TCP/IP address. Under normal + /// conditions, users of jCIFS need not be concerned with this class as + /// name resolution and session services are handled internally by the smb package. + ///

Applications can use the methods getLocalHost, + /// getByName, and + /// getAllByAddress to create a new NbtAddress instance. This + /// class is symmetric with + /// System.Net.IPAddress + /// . + ///

About NetBIOS: The NetBIOS name + /// service is a dynamic distributed service that allows hosts to resolve + /// names by broadcasting a query, directing queries to a server such as + /// Samba or WINS. NetBIOS is currently the primary networking layer for + /// providing name service, datagram service, and session service to the + /// Microsoft Windows platform. A NetBIOS name can be 15 characters long + /// and hosts usually registers several names on the network. From a + /// Windows command prompt you can see + /// what names a host registers with the nbtstat command. + ///

+	/// C:\>nbtstat -a 192.168.1.15
+	/// NetBIOS Remote Machine Name Table
+	/// Name               Type         Status
+	/// ---------------------------------------------
+	/// JMORRIS2        <00>  UNIQUE      Registered
+	/// BILLING-NY      <00>  GROUP       Registered
+	/// JMORRIS2        <03>  UNIQUE      Registered
+	/// JMORRIS2        <20>  UNIQUE      Registered
+	/// BILLING-NY      <1E>  GROUP       Registered
+	/// JMORRIS         <03>  UNIQUE      Registered
+	/// MAC Address = 00-B0-34-21-FA-3B
+	/// 
+ ///

The hostname of this machine is JMORRIS2. It is + /// a member of the group(a.k.a workgroup and domain) BILLING-NY. To + /// obtain an + /// System.Net.IPAddress + /// for a host one might do: + ///

+	/// InetAddress addr = NbtAddress.getByName( "jmorris2" ).getInetAddress();
+	/// 
+ ///

From a UNIX platform with Samba installed you can perform similar + /// diagnostics using the nmblookup utility. + /// + /// Michael B. Allen + /// System.Net.IPAddress + /// jcifs-0.1 + public sealed class NbtAddress + { + internal static readonly string AnyHostsName = "*\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000"; + + ///

+ /// This is a special name for querying the master browser that serves the + /// list of hosts found in "Network Neighborhood". + /// + /// + /// This is a special name for querying the master browser that serves the + /// list of hosts found in "Network Neighborhood". + /// + public static readonly string MasterBrowserName = "\u0001\u0002__MSBROWSE__\u0002"; + + /// + /// A special generic name specified when connecting to a host for which + /// a name is not known. + /// + /// + /// A special generic name specified when connecting to a host for which + /// a name is not known. Not all servers respond to this name. + /// + public static readonly string SmbserverName = "*SMBSERVER "; + + /// A B node only broadcasts name queries. + /// + /// A B node only broadcasts name queries. This is the default if a + /// nameserver such as WINS or Samba is not specified. + /// + public const int BNode = 0; + + /// + /// A Point-to-Point node, or P node, unicasts queries to a nameserver + /// only. + /// + /// + /// A Point-to-Point node, or P node, unicasts queries to a nameserver + /// only. Natrually the jcifs.netbios.nameserver property must + /// be set. + /// + public const int PNode = 1; + + /// + /// Try Broadcast queries first, then try to resolve the name using the + /// nameserver. + /// + /// + /// Try Broadcast queries first, then try to resolve the name using the + /// nameserver. + /// + public const int MNode = 2; + + /// A Hybrid node tries to resolve a name using the nameserver first. + /// + /// A Hybrid node tries to resolve a name using the nameserver first. If + /// that fails use the broadcast address. This is the default if a nameserver + /// is provided. This is the behavior of Microsoft Windows machines. + /// + public const int HNode = 3; + + internal static readonly IPAddress[] Nbns = Config.GetInetAddressArray("jcifs.netbios.wins" + , ",", new IPAddress[0]); + + private static readonly NameServiceClient Client = new NameServiceClient(); + + private const int DefaultCachePolicy = 30; + + private static readonly int CachePolicy = Config.GetInt("jcifs.netbios.cachePolicy" + , DefaultCachePolicy); + + private const int Forever = -1; + + private static int _nbnsIndex; + + private static readonly Hashtable AddressCache = new Hashtable(); + + private static readonly Hashtable LookupTable = new Hashtable(); + + internal static readonly Name UnknownName = new Name("0.0.0.0", unchecked(0x00), null); + + internal static readonly NbtAddress UnknownAddress = new NbtAddress + (UnknownName, 0, false, BNode); + + internal static readonly byte[] UnknownMacAddress = { unchecked(unchecked(0x00)), unchecked(unchecked(0x00)), unchecked(unchecked(0x00)), unchecked(unchecked(0x00)), unchecked(unchecked(0x00)), unchecked(unchecked(0x00)) }; + + internal sealed class CacheEntry + { + internal Name HostName; + + internal NbtAddress Address; + + internal long Expiration; + + internal CacheEntry(Name hostName, NbtAddress address, long expiration) + { + this.HostName = hostName; + this.Address = address; + this.Expiration = expiration; + } + } + + internal static NbtAddress Localhost; + + static NbtAddress() + { + IPAddress localInetAddress; + string localHostname; + Name localName; + AddressCache.Put(UnknownName, new CacheEntry(UnknownName, UnknownAddress + , Forever)); + localInetAddress = Client.laddr; + if (localInetAddress == null) + { + try + { + localInetAddress = Extensions.GetAddressByName("127.0.0.1"); + } + catch (UnknownHostException) + { + + } + } + localHostname = Config.GetProperty("jcifs.netbios.hostname", null); + if (string.IsNullOrEmpty(localHostname)) + { + byte[] addr = localInetAddress.GetAddressBytes(); + + /*localHostname = "JCIFS" + (addr[2] & unchecked((int)(0xFF))) + "_" + (addr[3] & unchecked( + (int)(0xFF))) + "_" + Hexdump.ToHexString((int)(new Random().NextDouble() * (double)unchecked( + (int)(0xFF))), 2);*/ + localHostname = "JCIFS_127_0_0_1"; + } + localName = new Name(localHostname, unchecked(0x00), Config.GetProperty("jcifs.netbios.scope" + , null)); + Localhost = new NbtAddress(localName, localInetAddress.GetHashCode(), false, BNode + , false, false, true, false, UnknownMacAddress); + CacheAddress(localName, Localhost, Forever); + } + + internal static void CacheAddress(Name hostName, NbtAddress addr) + { + if (CachePolicy == 0) + { + return; + } + long expiration = -1; + if (CachePolicy != Forever) + { + expiration = Runtime.CurrentTimeMillis() + CachePolicy * 1000; + } + CacheAddress(hostName, addr, expiration); + } + + internal static void CacheAddress(Name hostName, NbtAddress addr, long expiration + ) + { + if (CachePolicy == 0) + { + return; + } + lock (AddressCache) + { + CacheEntry entry = (CacheEntry)AddressCache.Get(hostName); + if (entry == null) + { + entry = new CacheEntry(hostName, addr, expiration); + AddressCache.Put(hostName, entry); + } + else + { + entry.Address = addr; + entry.Expiration = expiration; + } + } + } + + internal static void CacheAddressArray(NbtAddress[] addrs) + { + if (CachePolicy == 0) + { + return; + } + long expiration = -1; + if (CachePolicy != Forever) + { + expiration = Runtime.CurrentTimeMillis() + CachePolicy * 1000; + } + lock (AddressCache) + { + for (int i = 0; i < addrs.Length; i++) + { + CacheEntry entry = (CacheEntry)AddressCache.Get(addrs[i].HostName + ); + if (entry == null) + { + entry = new CacheEntry(addrs[i].HostName, addrs[i], expiration); + AddressCache.Put(addrs[i].HostName, entry); + } + else + { + entry.Address = addrs[i]; + entry.Expiration = expiration; + } + } + } + } + + internal static NbtAddress GetCachedAddress(Name hostName) + { + if (CachePolicy == 0) + { + return null; + } + lock (AddressCache) + { + CacheEntry entry = (CacheEntry)AddressCache.Get(hostName); + if (entry != null && entry.Expiration < Runtime.CurrentTimeMillis() && entry.Expiration + >= 0) + { + entry = null; + } + return entry != null ? entry.Address : null; + } + } + + /// + internal static NbtAddress DoNameQuery(Name name, IPAddress svr) + { + NbtAddress addr; + if (name.HexCode == unchecked(0x1d) && svr == null) + { + svr = Client.Baddr; + } + // bit of a hack but saves a lookup + name.SrcHashCode = svr != null ? svr.GetHashCode() : 0; + addr = GetCachedAddress(name); + if (addr == null) + { + if ((addr = (NbtAddress)CheckLookupTable(name)) == null) + { + try + { + addr = Client.GetByName(name, svr); + } + catch (UnknownHostException) + { + addr = UnknownAddress; + } + finally + { + CacheAddress(name, addr); + UpdateLookupTable(name); + } + } + } + if (addr == UnknownAddress) + { + throw new UnknownHostException(name.ToString()); + } + return addr; + } + + private static object CheckLookupTable(Name name) + { + object obj; + lock (LookupTable) + { + if (LookupTable.ContainsKey(name) == false) + { + LookupTable.Put(name, name); + return null; + } + while (LookupTable.ContainsKey(name)) + { + try + { + Runtime.Wait(LookupTable); + } + catch (Exception) + { + } + } + } + obj = GetCachedAddress(name); + if (obj == null) + { + lock (LookupTable) + { + LookupTable.Put(name, name); + } + } + return obj; + } + + private static void UpdateLookupTable(Name name) + { + lock (LookupTable) + { + //Sharpen.Collections.Remove(LOOKUP_TABLE, name); + LookupTable.Remove(name); + Runtime.NotifyAll(LookupTable); + } + } + + /// Retrieves the local host address. + /// Retrieves the local host address. + /// + /// This is not likely as the IP returned + /// by InetAddress should be available + /// + public static NbtAddress GetLocalHost() + { + return Localhost; + } + + public static NbtAddress[] GetHosts() + { + return new NameServiceClient().GetHosts(); + } + + public static Name GetLocalName() + { + return Localhost.HostName; + } + + /// Determines the address of a host given it's host name. + /// + /// Determines the address of a host given it's host name. The name can be a NetBIOS name like + /// "freto" or an IP address like "192.168.1.15". It cannot be a DNS name; + /// the analygous + /// Jcifs.UniAddress + /// or + /// System.Net.IPAddress + /// getByName methods can be used for that. + /// + /// hostname to resolve + /// if there is an error resolving the name + /// + public static NbtAddress GetByName(string host) + { + return GetByName(host, unchecked(0x00), null); + } + + /// Determines the address of a host given it's host name. + /// + /// Determines the address of a host given it's host name. NetBIOS + /// names also have a type. Types(aka Hex Codes) + /// are used to distiquish the various services on a host. <a + /// href="../../../nbtcodes.html">Here is + /// a fairly complete list of NetBIOS hex codes. Scope is not used but is + /// still functional in other NetBIOS products and so for completeness it has been + /// implemented. A scope of null or "" + /// signifies no scope. + /// + /// the name to resolve + /// the hex code of the name + /// the scope of the name + /// if there is an error resolving the name + /// + public static NbtAddress GetByName(string host, int type, string scope) + { + return GetByName(host, type, scope, null); + } + + /// + public static NbtAddress GetByName(string host, int type, string scope, IPAddress + svr) + { + if (string.IsNullOrEmpty(host)) + { + return GetLocalHost(); + } + if (!char.IsDigit(host[0])) + { + return DoNameQuery(new Name(host, type, scope), svr); + } + int ip = unchecked(0x00); + int hitDots = 0; + char[] data = host.ToCharArray(); + for (int i = 0; i < data.Length; i++) + { + char c = data[i]; + if (c < 48 || c > 57) + { + return DoNameQuery(new Name(host, type, scope), svr); + } + int b = unchecked(0x00); + while (c != '.') + { + if (c < 48 || c > 57) + { + return DoNameQuery(new Name(host, type, scope), svr); + } + b = b * 10 + c - '0'; + if (++i >= data.Length) + { + break; + } + c = data[i]; + } + if (b > unchecked(0xFF)) + { + return DoNameQuery(new Name(host, type, scope), svr); + } + ip = (ip << 8) + b; + hitDots++; + } + if (hitDots != 4 || host.EndsWith(".")) + { + return DoNameQuery(new Name(host, type, scope), svr); + } + return new NbtAddress(UnknownName, ip, false, BNode); + } + + /// + public static NbtAddress[] GetAllByName(string host, int type, string scope, IPAddress + svr) + { + return Client.GetAllByName(new Name(host, type, scope), svr); + } + + /// Retrieve all addresses of a host by it's address. + /// + /// Retrieve all addresses of a host by it's address. NetBIOS hosts can + /// have many names for a given IP address. The name and IP address make the + /// NetBIOS address. This provides a way to retrieve the other names for a + /// host with the same IP address. + /// + /// hostname to lookup all addresses for + /// if there is an error resolving the name + /// + public static NbtAddress[] GetAllByAddress(string host) + { + return GetAllByAddress(GetByName(host, unchecked(0x00), null)); + } + + /// Retrieve all addresses of a host by it's address. + /// + /// Retrieve all addresses of a host by it's address. NetBIOS hosts can + /// have many names for a given IP address. The name and IP address make + /// the NetBIOS address. This provides a way to retrieve the other names + /// for a host with the same IP address. See + /// GetByName(string) + /// for a description of type + /// and scope. + /// + /// hostname to lookup all addresses for + /// the hexcode of the name + /// the scope of the name + /// if there is an error resolving the name + /// + public static NbtAddress[] GetAllByAddress(string host, int type, string scope) + { + return GetAllByAddress(GetByName(host, type, scope)); + } + + /// Retrieve all addresses of a host by it's address. + /// + /// Retrieve all addresses of a host by it's address. NetBIOS hosts can + /// have many names for a given IP address. The name and IP address make the + /// NetBIOS address. This provides a way to retrieve the other names for a + /// host with the same IP address. + /// + /// the address to query + /// if address cannot be resolved + public static NbtAddress[] GetAllByAddress(NbtAddress addr) + { + try + { + NbtAddress[] addrs = Client.GetNodeStatus(addr); + CacheAddressArray(addrs); + return addrs; + } + catch (UnknownHostException) + { + throw new UnknownHostException("no name with type 0x" + Hexdump.ToHexString(addr. + HostName.HexCode, 2) + (((addr.HostName.Scope == null) || (addr.HostName.Scope.Length + == 0)) ? " with no scope" : " with scope " + addr.HostName.Scope) + " for host " + + addr.GetHostAddress()); + } + } + + public static IPAddress GetWinsAddress() + { + return Nbns.Length == 0 ? null : Nbns[_nbnsIndex]; + } + + public static bool IsWins(IPAddress svr) + { + for (int i = 0; svr != null && i < Nbns.Length; i++) + { + if (svr.GetHashCode() == Nbns[i].GetHashCode()) + { + return true; + } + } + return false; + } + + internal static IPAddress SwitchWins() + { + _nbnsIndex = (_nbnsIndex + 1) < Nbns.Length ? _nbnsIndex + 1 : 0; + return Nbns.Length == 0 ? null : Nbns[_nbnsIndex]; + } + + internal Name HostName; + + internal int Address; + + internal int NodeType; + + internal bool GroupName; + + internal bool isBeingDeleted; + + internal bool isInConflict; + + internal bool isActive; + + internal bool isPermanent; + + internal bool IsDataFromNodeStatus; + + internal byte[] MacAddress; + + internal string CalledName; + + internal NbtAddress(Name hostName, int address, bool groupName, int nodeType) + { + this.HostName = hostName; + this.Address = address; + this.GroupName = groupName; + this.NodeType = nodeType; + } + + internal NbtAddress(Name hostName, int address, bool groupName, int nodeType, bool + isBeingDeleted, bool isInConflict, bool isActive, bool isPermanent, byte[] macAddress + ) + { + this.HostName = hostName; + this.Address = address; + this.GroupName = groupName; + this.NodeType = nodeType; + this.isBeingDeleted = isBeingDeleted; + this.isInConflict = isInConflict; + this.isActive = isActive; + this.isPermanent = isPermanent; + this.MacAddress = macAddress; + IsDataFromNodeStatus = true; + } + + public string FirstCalledName() + { + CalledName = HostName.name; + if (char.IsDigit(CalledName[0])) + { + int i; + int len; + int dots; + char[] data; + i = dots = 0; + len = CalledName.Length; + data = CalledName.ToCharArray(); + while (i < len && char.IsDigit(data[i++])) + { + if (i == len && dots == 3) + { + // probably an IP address + CalledName = SmbserverName; + break; + } + if (i < len && data[i] == '.') + { + dots++; + i++; + } + } + } + else + { + switch (HostName.HexCode) + { + case unchecked(0x1B): + case unchecked(0x1C): + case unchecked(0x1D): + { + CalledName = SmbserverName; + break; + } + } + } + return CalledName; + } + + public string NextCalledName() + { + if (CalledName == HostName.name) + { + CalledName = SmbserverName; + } + else + { + if (CalledName == SmbserverName) + { + NbtAddress[] addrs; + try + { + addrs = Client.GetNodeStatus(this); + if (HostName.HexCode == unchecked(0x1D)) + { + for (int i = 0; i < addrs.Length; i++) + { + if (addrs[i].HostName.HexCode == unchecked(0x20)) + { + return addrs[i].HostName.name; + } + } + return null; + } + if (IsDataFromNodeStatus) + { + CalledName = null; + return HostName.name; + } + } + catch (UnknownHostException) + { + CalledName = null; + } + } + else + { + CalledName = null; + } + } + return CalledName; + } + + /// + internal void CheckData() + { + if (HostName == UnknownName) + { + GetAllByAddress(this); + } + } + + /// + internal void CheckNodeStatusData() + { + if (IsDataFromNodeStatus == false) + { + GetAllByAddress(this); + } + } + + /// Determines if the address is a group address. + /// + /// Determines if the address is a group address. This is also + /// known as a workgroup name or group name. + /// + /// if the host cannot be resolved to find out. + /// + public bool IsGroupAddress() + { + CheckData(); + return GroupName; + } + + /// Checks the node type of this address. + /// Checks the node type of this address. + /// + /// + /// B_NODE + /// , + /// P_NODE + /// , + /// M_NODE + /// , + /// H_NODE + /// + /// if the host cannot be resolved to find out. + /// + public int GetNodeType() + { + CheckData(); + return NodeType; + } + + /// Determines if this address in the process of being deleted. + /// Determines if this address in the process of being deleted. + /// if the host cannot be resolved to find out. + /// + public bool IsBeingDeleted() + { + CheckNodeStatusData(); + return isBeingDeleted; + } + + /// Determines if this address in conflict with another address. + /// Determines if this address in conflict with another address. + /// if the host cannot be resolved to find out. + /// + public bool IsInConflict() + { + CheckNodeStatusData(); + return isInConflict; + } + + /// Determines if this address is active. + /// Determines if this address is active. + /// if the host cannot be resolved to find out. + /// + public bool IsActive() + { + CheckNodeStatusData(); + return isActive; + } + + /// Determines if this address is set to be permanent. + /// Determines if this address is set to be permanent. + /// if the host cannot be resolved to find out. + /// + public bool IsPermanent() + { + CheckNodeStatusData(); + return isPermanent; + } + + /// Retrieves the MAC address of the remote network interface. + /// Retrieves the MAC address of the remote network interface. Samba returns all zeros. + /// + /// the MAC address as an array of six bytes + /// + /// if the host cannot be resolved to + /// determine the MAC address. + /// + public byte[] GetMacAddress() + { + CheckNodeStatusData(); + return MacAddress; + } + + /// The hostname of this address. + /// + /// The hostname of this address. If the hostname is null the local machines + /// IP address is returned. + /// + /// the text representation of the hostname associated with this address + public string GetHostName() + { + if (HostName == UnknownName) + { + return GetHostAddress(); + } + return HostName.name; + } + + /// Returns the raw IP address of this NbtAddress. + /// + /// Returns the raw IP address of this NbtAddress. The result is in network + /// byte order: the highest order byte of the address is in getAddress()[0]. + /// + /// a four byte array + public byte[] GetAddress() + { + byte[] addr = new byte[4]; + addr[0] = unchecked((byte)(((int)(((uint)Address) >> 24)) & unchecked(0xFF + ))); + addr[1] = unchecked((byte)(((int)(((uint)Address) >> 16)) & unchecked(0xFF + ))); + addr[2] = unchecked((byte)(((int)(((uint)Address) >> 8)) & unchecked(0xFF) + )); + addr[3] = unchecked((byte)(Address & unchecked(0xFF))); + return addr; + } + + /// To convert this address to an InetAddress. + /// To convert this address to an InetAddress. + /// + /// the + /// System.Net.IPAddress + /// representation of this address. + /// + /// + public IPAddress GetInetAddress() + { + return Extensions.GetAddressByName(GetHostAddress()); + } + + /// + /// Returns this IP adress as a + /// string + /// in the form "%d.%d.%d.%d". + /// + public string GetHostAddress() + { + return (((int)(((uint)Address) >> 24)) & unchecked(0xFF)) + "." + (((int)( + ((uint)Address) >> 16)) & unchecked(0xFF)) + "." + (((int)(((uint)Address + ) >> 8)) & unchecked(0xFF)) + "." + (((int)(((uint)Address) >> 0)) & unchecked( + 0xFF)); + } + + /// Returned the hex code associated with this name(e.g. + /// Returned the hex code associated with this name(e.g. 0x20 is for the file service) + /// + public int GetNameType() + { + return HostName.HexCode; + } + + /// Returns a hashcode for this IP address. + /// + /// Returns a hashcode for this IP address. The hashcode comes from the IP address + /// and is not generated from the string representation. So because NetBIOS nodes + /// can have many names, all names associated with an IP will have the same + /// hashcode. + /// + public override int GetHashCode() + { + return Address; + } + + /// Determines if this address is equal two another. + /// + /// Determines if this address is equal two another. Only the IP Addresses + /// are compared. Similar to the + /// GetHashCode() + /// method, the comparison + /// is based on the integer IP address and not the string representation. + /// + public override bool Equals(object obj) + { + return (obj != null) && (obj is NbtAddress) && (((NbtAddress)obj).Address == Address + ); + } + + /// + /// Returns the + /// string + /// representaion of this address. + /// + public override string ToString() + { + return HostName + "/" + GetHostAddress(); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtException.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtException.cs new file mode 100644 index 0000000000..e785c99433 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtException.cs @@ -0,0 +1,164 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.IO; + +namespace SharpCifs.Netbios +{ + + public class NbtException : IOException + { + public const int Success = 0; + + public const int ErrNamSrvc = unchecked(0x01); + + public const int ErrSsnSrvc = unchecked(0x02); + + public const int FmtErr = unchecked(0x1); + + public const int SrvErr = unchecked(0x2); + + public const int ImpErr = unchecked(0x4); + + public const int RfsErr = unchecked(0x5); + + public const int ActErr = unchecked(0x6); + + public const int CftErr = unchecked(0x7); + + public const int ConnectionRefused = -1; + + public const int NotListeningCalled = unchecked(0x80); + + public const int NotListeningCalling = unchecked(0x81); + + public const int CalledNotPresent = unchecked(0x82); + + public const int NoResources = unchecked(0x83); + + public const int Unspecified = unchecked(0x8F); + + public int ErrorClass; + + public int ErrorCode; + + // error classes + // name service error codes + // session service error codes + public static string GetErrorString(int errorClass, int errorCode) + { + string result = string.Empty; + switch (errorClass) + { + case Success: + { + result += "SUCCESS"; + break; + } + + case ErrNamSrvc: + { + result += "ERR_NAM_SRVC/"; + switch (errorCode) + { + case FmtErr: + { + result += "FMT_ERR: Format Error"; + goto default; + } + + default: + { + result += "Unknown error code: " + errorCode; + break; + } + } + break; + } + + case ErrSsnSrvc: + { + result += "ERR_SSN_SRVC/"; + switch (errorCode) + { + case ConnectionRefused: + { + result += "Connection refused"; + break; + } + + case NotListeningCalled: + { + result += "Not listening on called name"; + break; + } + + case NotListeningCalling: + { + result += "Not listening for calling name"; + break; + } + + case CalledNotPresent: + { + result += "Called name not present"; + break; + } + + case NoResources: + { + result += "Called name present, but insufficient resources"; + break; + } + + case Unspecified: + { + result += "Unspecified error"; + break; + } + + default: + { + result += "Unknown error code: " + errorCode; + break; + } + } + break; + } + + default: + { + result += "unknown error class: " + errorClass; + break; + } + } + return result; + } + + public NbtException(int errorClass, int errorCode) : base(GetErrorString(errorClass + , errorCode)) + { + this.ErrorClass = errorClass; + this.ErrorCode = errorCode; + } + + public override string ToString() + { + return "errorClass=" + ErrorClass + ",errorCode=" + ErrorCode + ",errorString=" + + GetErrorString(ErrorClass, ErrorCode); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusRequest.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusRequest.cs new file mode 100644 index 0000000000..66d3bb3e52 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusRequest.cs @@ -0,0 +1,59 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Netbios +{ + internal class NodeStatusRequest : NameServicePacket + { + internal NodeStatusRequest(Name name) + { + QuestionName = name; + QuestionType = Nbstat; + IsRecurDesired = false; + IsBroadcast = false; + } + + internal override int WriteBodyWireFormat(byte[] dst, int dstIndex) + { + int tmp = QuestionName.HexCode; + QuestionName.HexCode = unchecked(0x00); + // type has to be 0x00 for node status + int result = WriteQuestionSectionWireFormat(dst, dstIndex); + QuestionName.HexCode = tmp; + return result; + } + + internal override int ReadBodyWireFormat(byte[] src, int srcIndex) + { + return 0; + } + + internal override int WriteRDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadRDataWireFormat(byte[] src, int srcIndex) + { + return 0; + } + + public override string ToString() + { + return "NodeStatusRequest[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusResponse.cs new file mode 100644 index 0000000000..aa32144192 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusResponse.cs @@ -0,0 +1,140 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Sharpen; + +namespace SharpCifs.Netbios +{ + internal class NodeStatusResponse : NameServicePacket + { + private NbtAddress _queryAddress; + + private int _numberOfNames; + + private byte[] _macAddress; + + private byte[] _stats; + + internal NbtAddress[] AddressArray; + + internal NodeStatusResponse(NbtAddress queryAddress) + { + this._queryAddress = queryAddress; + RecordName = new Name(); + _macAddress = new byte[6]; + } + + internal override int WriteBodyWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadBodyWireFormat(byte[] src, int srcIndex) + { + return ReadResourceRecordWireFormat(src, srcIndex); + } + + internal override int WriteRDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadRDataWireFormat(byte[] src, int srcIndex) + { + int start = srcIndex; + _numberOfNames = src[srcIndex] & unchecked(0xFF); + int namesLength = _numberOfNames * 18; + int statsLength = RDataLength - namesLength - 1; + _numberOfNames = src[srcIndex++] & unchecked(0xFF); + // gotta read the mac first so we can populate addressArray with it + Array.Copy(src, srcIndex + namesLength, _macAddress, 0, 6); + srcIndex += ReadNodeNameArray(src, srcIndex); + _stats = new byte[statsLength]; + Array.Copy(src, srcIndex, _stats, 0, statsLength); + srcIndex += statsLength; + return srcIndex - start; + } + + private int ReadNodeNameArray(byte[] src, int srcIndex) + { + int start = srcIndex; + AddressArray = new NbtAddress[_numberOfNames]; + string n; + int hexCode; + string scope = _queryAddress.HostName.Scope; + bool groupName; + int ownerNodeType; + bool isBeingDeleted; + bool isInConflict; + bool isActive; + bool isPermanent; + int j; + bool addrFound = false; + try + { + for (int i = 0; i < _numberOfNames; srcIndex += 18, i++) + { + for (j = srcIndex + 14; src[j] == unchecked(0x20); j--) + { + } + n = Runtime.GetStringForBytes(src, srcIndex, j - srcIndex + 1, Name.OemEncoding + ); + hexCode = src[srcIndex + 15] & unchecked(0xFF); + groupName = ((src[srcIndex + 16] & unchecked(0x80)) == unchecked(0x80)) ? true : false; + ownerNodeType = (src[srcIndex + 16] & unchecked(0x60)) >> 5; + isBeingDeleted = ((src[srcIndex + 16] & unchecked(0x10)) == unchecked(0x10)) ? true : false; + isInConflict = ((src[srcIndex + 16] & unchecked(0x08)) == unchecked(0x08)) ? true : false; + isActive = ((src[srcIndex + 16] & unchecked(0x04)) == unchecked(0x04)) ? true : false; + isPermanent = ((src[srcIndex + 16] & unchecked(0x02)) == unchecked(0x02)) ? true : false; + if (!addrFound && _queryAddress.HostName.HexCode == hexCode && (_queryAddress.HostName + == NbtAddress.UnknownName || _queryAddress.HostName.name.Equals(n))) + { + if (_queryAddress.HostName == NbtAddress.UnknownName) + { + _queryAddress.HostName = new Name(n, hexCode, scope); + } + _queryAddress.GroupName = groupName; + _queryAddress.NodeType = ownerNodeType; + _queryAddress.isBeingDeleted = isBeingDeleted; + _queryAddress.isInConflict = isInConflict; + _queryAddress.isActive = isActive; + _queryAddress.isPermanent = isPermanent; + _queryAddress.MacAddress = _macAddress; + _queryAddress.IsDataFromNodeStatus = true; + addrFound = true; + AddressArray[i] = _queryAddress; + } + else + { + AddressArray[i] = new NbtAddress(new Name(n, hexCode, scope), _queryAddress.Address + , groupName, ownerNodeType, isBeingDeleted, isInConflict, isActive, isPermanent, + _macAddress); + } + } + } + catch (UnsupportedEncodingException) + { + } + return srcIndex - start; + } + + public override string ToString() + { + return "NodeStatusResponse[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRequestPacket.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRequestPacket.cs new file mode 100644 index 0000000000..a5243f7aa4 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRequestPacket.cs @@ -0,0 +1,63 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.IO; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Netbios +{ + public class SessionRequestPacket : SessionServicePacket + { + private Name _calledName; + + private Name _callingName; + + public SessionRequestPacket() + { + _calledName = new Name(); + _callingName = new Name(); + } + + public SessionRequestPacket(Name calledName, Name callingName) + { + Type = SessionRequest; + this._calledName = calledName; + this._callingName = callingName; + } + + internal override int WriteTrailerWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + dstIndex += _calledName.WriteWireFormat(dst, dstIndex); + dstIndex += _callingName.WriteWireFormat(dst, dstIndex); + return dstIndex - start; + } + + /// + internal override int ReadTrailerWireFormat(InputStream @in, byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + if (@in.Read(buffer, bufferIndex, Length) != Length) + { + throw new IOException("invalid session request wire format"); + } + bufferIndex += _calledName.ReadWireFormat(buffer, bufferIndex); + bufferIndex += _callingName.ReadWireFormat(buffer, bufferIndex); + return bufferIndex - start; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRetargetResponsePacket.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRetargetResponsePacket.cs new file mode 100644 index 0000000000..c901c6e263 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRetargetResponsePacket.cs @@ -0,0 +1,54 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.IO; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Netbios +{ + internal class SessionRetargetResponsePacket : SessionServicePacket + { + private NbtAddress _retargetAddress; + + private int _retargetPort; + + public SessionRetargetResponsePacket() + { + Type = SessionRetargetResponse; + Length = 6; + } + + internal override int WriteTrailerWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + /// + internal override int ReadTrailerWireFormat(InputStream @in, byte[] buffer, int bufferIndex + ) + { + if (@in.Read(buffer, bufferIndex, Length) != Length) + { + throw new IOException("unexpected EOF reading netbios retarget session response"); + } + int addr = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + _retargetAddress = new NbtAddress(null, addr, false, NbtAddress.BNode); + _retargetPort = ReadInt2(buffer, bufferIndex); + return Length; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionServicePacket.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionServicePacket.cs new file mode 100644 index 0000000000..c8d194222f --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionServicePacket.cs @@ -0,0 +1,156 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.IO; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Netbios +{ + public abstract class SessionServicePacket + { + internal const int SessionMessage = unchecked(0x00); + + internal const int SessionRequest = unchecked(0x81); + + public const int PositiveSessionResponse = unchecked(0x82); + + public const int NegativeSessionResponse = unchecked(0x83); + + internal const int SessionRetargetResponse = unchecked(0x84); + + internal const int SessionKeepAlive = unchecked(0x85); + + internal const int MaxMessageSize = unchecked(0x0001FFFF); + + internal const int HeaderLength = 4; + + // session service packet types + internal static void WriteInt2(int val, byte[] dst, int dstIndex) + { + dst[dstIndex++] = unchecked((byte)((val >> 8) & unchecked(0xFF))); + dst[dstIndex] = unchecked((byte)(val & unchecked(0xFF))); + } + + internal static void WriteInt4(int val, byte[] dst, int dstIndex) + { + dst[dstIndex++] = unchecked((byte)((val >> 24) & unchecked(0xFF))); + dst[dstIndex++] = unchecked((byte)((val >> 16) & unchecked(0xFF))); + dst[dstIndex++] = unchecked((byte)((val >> 8) & unchecked(0xFF))); + dst[dstIndex] = unchecked((byte)(val & unchecked(0xFF))); + } + + internal static int ReadInt2(byte[] src, int srcIndex) + { + return ((src[srcIndex] & unchecked(0xFF)) << 8) + (src[srcIndex + 1] & unchecked( + 0xFF)); + } + + internal static int ReadInt4(byte[] src, int srcIndex) + { + return ((src[srcIndex] & unchecked(0xFF)) << 24) + ((src[srcIndex + 1] & unchecked( + 0xFF)) << 16) + ((src[srcIndex + 2] & unchecked(0xFF)) << 8) + (src + [srcIndex + 3] & unchecked(0xFF)); + } + + internal static int ReadLength(byte[] src, int srcIndex) + { + srcIndex++; + return ((src[srcIndex++] & unchecked(0x01)) << 16) + ((src[srcIndex++] & unchecked( + 0xFF)) << 8) + (src[srcIndex++] & unchecked(0xFF)); + } + + /// + internal static int Readn(InputStream @in, byte[] b, int off, int len) + { + int i = 0; + int n; + while (i < len) + { + n = @in.Read(b, off + i, len - i); + if (n <= 0) + { + break; + } + i += n; + } + return i; + } + + /// + internal static int ReadPacketType(InputStream @in, byte[] buffer, int bufferIndex + ) + { + int n; + if ((n = Readn(@in, buffer, bufferIndex, HeaderLength)) != HeaderLength) + { + if (n == -1) + { + return -1; + } + throw new IOException("unexpected EOF reading netbios session header"); + } + int t = buffer[bufferIndex] & unchecked(0xFF); + return t; + } + + internal int Type; + + internal int Length; + + public virtual int WriteWireFormat(byte[] dst, int dstIndex) + { + Length = WriteTrailerWireFormat(dst, dstIndex + HeaderLength); + WriteHeaderWireFormat(dst, dstIndex); + return HeaderLength + Length; + } + + /// + internal virtual int ReadWireFormat(InputStream @in, byte[] buffer, int bufferIndex + ) + { + ReadHeaderWireFormat(@in, buffer, bufferIndex); + return HeaderLength + ReadTrailerWireFormat(@in, buffer, bufferIndex); + } + + internal virtual int WriteHeaderWireFormat(byte[] dst, int dstIndex) + { + dst[dstIndex++] = unchecked((byte)Type); + if (Length > unchecked(0x0000FFFF)) + { + dst[dstIndex] = unchecked(unchecked(0x01)); + } + dstIndex++; + WriteInt2(Length, dst, dstIndex); + return HeaderLength; + } + + /// + internal virtual int ReadHeaderWireFormat(InputStream @in, byte[] buffer, int bufferIndex + ) + { + Type = buffer[bufferIndex++] & unchecked(0xFF); + Length = ((buffer[bufferIndex] & unchecked(0x01)) << 16) + ReadInt2(buffer + , bufferIndex + 1); + return HeaderLength; + } + + internal abstract int WriteTrailerWireFormat(byte[] dst, int dstIndex); + + /// + internal abstract int ReadTrailerWireFormat(InputStream @in, byte[] buffer, int bufferIndex + ); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/NtlmFlags.cs b/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/NtlmFlags.cs new file mode 100644 index 0000000000..116f71b754 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/NtlmFlags.cs @@ -0,0 +1,197 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Ntlmssp +{ + /// Flags used during negotiation of NTLMSSP authentication. + /// Flags used during negotiation of NTLMSSP authentication. + public abstract class NtlmFlags + { + /// Indicates whether Unicode strings are supported or used. + /// Indicates whether Unicode strings are supported or used. + public const int NtlmsspNegotiateUnicode = unchecked(0x00000001); + + /// Indicates whether OEM strings are supported or used. + /// Indicates whether OEM strings are supported or used. + public const int NtlmsspNegotiateOem = unchecked(0x00000002); + + /// + /// Indicates whether the authentication target is requested from + /// the server. + /// + /// + /// Indicates whether the authentication target is requested from + /// the server. + /// + public const int NtlmsspRequestTarget = unchecked(0x00000004); + + /// + /// Specifies that communication across the authenticated channel + /// should carry a digital signature (message integrity). + /// + /// + /// Specifies that communication across the authenticated channel + /// should carry a digital signature (message integrity). + /// + public const int NtlmsspNegotiateSign = unchecked(0x00000010); + + /// + /// Specifies that communication across the authenticated channel + /// should be encrypted (message confidentiality). + /// + /// + /// Specifies that communication across the authenticated channel + /// should be encrypted (message confidentiality). + /// + public const int NtlmsspNegotiateSeal = unchecked(0x00000020); + + /// Indicates datagram authentication. + /// Indicates datagram authentication. + public const int NtlmsspNegotiateDatagramStyle = unchecked(0x00000040); + + /// + /// Indicates that the LAN Manager session key should be used for + /// signing and sealing authenticated communication. + /// + /// + /// Indicates that the LAN Manager session key should be used for + /// signing and sealing authenticated communication. + /// + public const int NtlmsspNegotiateLmKey = unchecked(0x00000080); + + public const int NtlmsspNegotiateNetware = unchecked(0x00000100); + + /// Indicates support for NTLM authentication. + /// Indicates support for NTLM authentication. + public const int NtlmsspNegotiateNtlm = unchecked(0x00000200); + + /// + /// Indicates whether the OEM-formatted domain name in which the + /// client workstation has membership is supplied in the Type-1 message. + /// + /// + /// Indicates whether the OEM-formatted domain name in which the + /// client workstation has membership is supplied in the Type-1 message. + /// This is used in the negotation of local authentication. + /// + public const int NtlmsspNegotiateOemDomainSupplied = unchecked(0x00001000); + + /// + /// Indicates whether the OEM-formatted workstation name is supplied + /// in the Type-1 message. + /// + /// + /// Indicates whether the OEM-formatted workstation name is supplied + /// in the Type-1 message. This is used in the negotiation of local + /// authentication. + /// + public const int NtlmsspNegotiateOemWorkstationSupplied = unchecked(0x00002000); + + /// + /// Sent by the server to indicate that the server and client are + /// on the same machine. + /// + /// + /// Sent by the server to indicate that the server and client are + /// on the same machine. This implies that the server will include + /// a local security context handle in the Type 2 message, for + /// use in local authentication. + /// + public const int NtlmsspNegotiateLocalCall = unchecked(0x00004000); + + /// + /// Indicates that authenticated communication between the client + /// and server should carry a "dummy" digital signature. + /// + /// + /// Indicates that authenticated communication between the client + /// and server should carry a "dummy" digital signature. + /// + public const int NtlmsspNegotiateAlwaysSign = unchecked(0x00008000); + + /// + /// Sent by the server in the Type 2 message to indicate that the + /// target authentication realm is a domain. + /// + /// + /// Sent by the server in the Type 2 message to indicate that the + /// target authentication realm is a domain. + /// + public const int NtlmsspTargetTypeDomain = unchecked(0x00010000); + + /// + /// Sent by the server in the Type 2 message to indicate that the + /// target authentication realm is a server. + /// + /// + /// Sent by the server in the Type 2 message to indicate that the + /// target authentication realm is a server. + /// + public const int NtlmsspTargetTypeServer = unchecked(0x00020000); + + /// + /// Sent by the server in the Type 2 message to indicate that the + /// target authentication realm is a share (presumably for share-level + /// authentication). + /// + /// + /// Sent by the server in the Type 2 message to indicate that the + /// target authentication realm is a share (presumably for share-level + /// authentication). + /// + public const int NtlmsspTargetTypeShare = unchecked(0x00040000); + + /// + /// Indicates that the NTLM2 signing and sealing scheme should be used + /// for protecting authenticated communications. + /// + /// + /// Indicates that the NTLM2 signing and sealing scheme should be used + /// for protecting authenticated communications. This refers to a + /// particular session security scheme, and is not related to the use + /// of NTLMv2 authentication. + /// + public const int NtlmsspNegotiateNtlm2 = unchecked(0x00080000); + + public const int NtlmsspRequestInitResponse = unchecked(0x00100000); + + public const int NtlmsspRequestAcceptResponse = unchecked(0x00200000); + + public const int NtlmsspRequestNonNtSessionKey = unchecked(0x00400000 + ); + + /// + /// Sent by the server in the Type 2 message to indicate that it is + /// including a Target Information block in the message. + /// + /// + /// Sent by the server in the Type 2 message to indicate that it is + /// including a Target Information block in the message. The Target + /// Information block is used in the calculation of the NTLMv2 response. + /// + public const int NtlmsspNegotiateTargetInfo = unchecked(0x00800000); + + /// Indicates that 128-bit encryption is supported. + /// Indicates that 128-bit encryption is supported. + public const int NtlmsspNegotiate128 = unchecked(0x20000000); + + public const int NtlmsspNegotiateKeyExch = unchecked(0x40000000); + + /// Indicates that 56-bit encryption is supported. + /// Indicates that 56-bit encryption is supported. + public const int NtlmsspNegotiate56 = unchecked((int)(0x80000000)); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/NtlmMessage.cs b/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/NtlmMessage.cs new file mode 100644 index 0000000000..02827d2d07 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/NtlmMessage.cs @@ -0,0 +1,140 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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; + +namespace SharpCifs.Ntlmssp +{ + /// Abstract superclass for all NTLMSSP messages. + /// Abstract superclass for all NTLMSSP messages. + public abstract class NtlmMessage : NtlmFlags + { + /// The NTLMSSP "preamble". + /// The NTLMSSP "preamble". + protected internal static readonly byte[] NtlmsspSignature = { unchecked( + (byte)('N')), unchecked((byte)('T')), unchecked((byte)('L')), + unchecked((byte)('M')), unchecked((byte)('S')), unchecked((byte + )('S')), unchecked((byte)('P')), unchecked(0) }; + + private static readonly string OemEncoding = Config.DefaultOemEncoding; + + protected internal static readonly string UniEncoding = "UTF-16LE"; + + private int _flags; + + /// Returns the flags currently in use for this message. + /// Returns the flags currently in use for this message. + /// + /// An int containing the flags in use for this + /// message. + /// + public virtual int GetFlags() + { + return _flags; + } + + /// Sets the flags for this message. + /// Sets the flags for this message. + /// The flags for this message. + public virtual void SetFlags(int flags) + { + this._flags = flags; + } + + /// Returns the status of the specified flag. + /// Returns the status of the specified flag. + /// The flag to test (i.e., NTLMSSP_NEGOTIATE_OEM). + /// A boolean indicating whether the flag is set. + public virtual bool GetFlag(int flag) + { + return (GetFlags() & flag) != 0; + } + + /// Sets or clears the specified flag. + /// Sets or clears the specified flag. + /// + /// The flag to set/clear (i.e., + /// NTLMSSP_NEGOTIATE_OEM). + /// + /// + /// Indicates whether to set (true) or + /// clear (false) the specified flag. + /// + public virtual void SetFlag(int flag, bool value) + { + SetFlags(value ? (GetFlags() | flag) : (GetFlags() & (unchecked((int)(0xffffffff) + ) ^ flag))); + } + + internal static int ReadULong(byte[] src, int index) + { + return (src[index] & unchecked(0xff)) | ((src[index + 1] & unchecked(0xff)) << 8) | ((src[index + 2] & unchecked(0xff)) << 16) | ((src[index + + 3] & unchecked(0xff)) << 24); + } + + internal static int ReadUShort(byte[] src, int index) + { + return (src[index] & unchecked(0xff)) | ((src[index + 1] & unchecked(0xff)) << 8); + } + + internal static byte[] ReadSecurityBuffer(byte[] src, int index) + { + int length = ReadUShort(src, index); + int offset = ReadULong(src, index + 4); + byte[] buffer = new byte[length]; + Array.Copy(src, offset, buffer, 0, length); + return buffer; + } + + internal static void WriteULong(byte[] dest, int offset, int value) + { + dest[offset] = unchecked((byte)(value & unchecked(0xff))); + dest[offset + 1] = unchecked((byte)(value >> 8 & unchecked(0xff))); + dest[offset + 2] = unchecked((byte)(value >> 16 & unchecked(0xff))); + dest[offset + 3] = unchecked((byte)(value >> 24 & unchecked(0xff))); + } + + internal static void WriteUShort(byte[] dest, int offset, int value) + { + dest[offset] = unchecked((byte)(value & unchecked(0xff))); + dest[offset + 1] = unchecked((byte)(value >> 8 & unchecked(0xff))); + } + + internal static void WriteSecurityBuffer(byte[] dest, int offset, int bodyOffset, + byte[] src) + { + int length = (src != null) ? src.Length : 0; + if (length == 0) + { + return; + } + WriteUShort(dest, offset, length); + WriteUShort(dest, offset + 2, length); + WriteULong(dest, offset + 4, bodyOffset); + Array.Copy(src, 0, dest, bodyOffset, length); + } + + internal static string GetOemEncoding() + { + return OemEncoding; + } + + /// Returns the raw byte representation of this message. + /// Returns the raw byte representation of this message. + /// A byte[] containing the raw message material. + public abstract byte[] ToByteArray(); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/Type1Message.cs b/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/Type1Message.cs new file mode 100644 index 0000000000..afcf5ec7e7 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/Type1Message.cs @@ -0,0 +1,249 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using SharpCifs.Netbios; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Ntlmssp +{ + /// Represents an NTLMSSP Type-1 message. + /// Represents an NTLMSSP Type-1 message. + public class Type1Message : NtlmMessage + { + private static readonly int DefaultFlags; + + private static readonly string DefaultDomain; + + private static readonly string DefaultWorkstation; + + private string _suppliedDomain; + + private string _suppliedWorkstation; + + static Type1Message() + { + DefaultFlags = NtlmsspNegotiateNtlm | (Config.GetBoolean("jcifs.smb.client.useUnicode" + , true) ? NtlmsspNegotiateUnicode : NtlmsspNegotiateOem); + DefaultDomain = Config.GetProperty("jcifs.smb.client.domain", null); + string defaultWorkstation = null; + try + { + defaultWorkstation = NbtAddress.GetLocalHost().GetHostName(); + } + catch (UnknownHostException) + { + } + DefaultWorkstation = defaultWorkstation; + } + + /// + /// Creates a Type-1 message using default values from the current + /// environment. + /// + /// + /// Creates a Type-1 message using default values from the current + /// environment. + /// + public Type1Message() : this(GetDefaultFlags(), GetDefaultDomain(), GetDefaultWorkstation + ()) + { + } + + /// Creates a Type-1 message with the specified parameters. + /// Creates a Type-1 message with the specified parameters. + /// The flags to apply to this message. + /// The supplied authentication domain. + /// The supplied workstation name. + public Type1Message(int flags, string suppliedDomain, string suppliedWorkstation) + { + SetFlags(GetDefaultFlags() | flags); + SetSuppliedDomain(suppliedDomain); + if (suppliedWorkstation == null) + { + suppliedWorkstation = GetDefaultWorkstation(); + } + SetSuppliedWorkstation(suppliedWorkstation); + } + + /// Creates a Type-1 message using the given raw Type-1 material. + /// Creates a Type-1 message using the given raw Type-1 material. + /// The raw Type-1 material used to construct this message. + /// If an error occurs while parsing the material. + /// + public Type1Message(byte[] material) + { + Parse(material); + } + + /// Returns the supplied authentication domain. + /// Returns the supplied authentication domain. + /// A String containing the supplied domain. + public virtual string GetSuppliedDomain() + { + return _suppliedDomain; + } + + /// Sets the supplied authentication domain for this message. + /// Sets the supplied authentication domain for this message. + /// The supplied domain for this message. + public virtual void SetSuppliedDomain(string suppliedDomain) + { + this._suppliedDomain = suppliedDomain; + } + + /// Returns the supplied workstation name. + /// Returns the supplied workstation name. + /// A String containing the supplied workstation name. + public virtual string GetSuppliedWorkstation() + { + return _suppliedWorkstation; + } + + /// Sets the supplied workstation name for this message. + /// Sets the supplied workstation name for this message. + /// The supplied workstation for this message. + public virtual void SetSuppliedWorkstation(string suppliedWorkstation) + { + this._suppliedWorkstation = suppliedWorkstation; + } + + public override byte[] ToByteArray() + { + try + { + string suppliedDomain = GetSuppliedDomain(); + string suppliedWorkstation = GetSuppliedWorkstation(); + int flags = GetFlags(); + bool hostInfo = false; + byte[] domain = new byte[0]; + if (!string.IsNullOrEmpty(suppliedDomain)) + { + hostInfo = true; + flags |= NtlmsspNegotiateOemDomainSupplied; + domain = Runtime.GetBytesForString(suppliedDomain.ToUpper(), GetOemEncoding + ()); + } + else + { + flags &= (NtlmsspNegotiateOemDomainSupplied ^ unchecked((int)(0xffffffff))); + } + byte[] workstation = new byte[0]; + if (!string.IsNullOrEmpty(suppliedWorkstation)) + { + hostInfo = true; + flags |= NtlmsspNegotiateOemWorkstationSupplied; + workstation = Runtime.GetBytesForString(suppliedWorkstation.ToUpper(), GetOemEncoding + ()); + } + else + { + flags &= (NtlmsspNegotiateOemWorkstationSupplied ^ unchecked((int)(0xffffffff + ))); + } + byte[] type1 = new byte[hostInfo ? (32 + domain.Length + workstation.Length) : 16 + ]; + Array.Copy(NtlmsspSignature, 0, type1, 0, 8); + WriteULong(type1, 8, 1); + WriteULong(type1, 12, flags); + if (hostInfo) + { + WriteSecurityBuffer(type1, 16, 32, domain); + WriteSecurityBuffer(type1, 24, 32 + domain.Length, workstation); + } + return type1; + } + catch (IOException ex) + { + throw new InvalidOperationException(ex.Message); + } + } + + public override string ToString() + { + string suppliedDomain = GetSuppliedDomain(); + string suppliedWorkstation = GetSuppliedWorkstation(); + return "Type1Message[suppliedDomain=" + (suppliedDomain ?? "null" + ) + ",suppliedWorkstation=" + (suppliedWorkstation ?? "null" + ) + ",flags=0x" + Hexdump.ToHexString(GetFlags(), 8) + "]"; + } + + /// + /// Returns the default flags for a generic Type-1 message in the + /// current environment. + /// + /// + /// Returns the default flags for a generic Type-1 message in the + /// current environment. + /// + /// An int containing the default flags. + public static int GetDefaultFlags() + { + return DefaultFlags; + } + + /// Returns the default domain from the current environment. + /// Returns the default domain from the current environment. + /// A String containing the default domain. + public static string GetDefaultDomain() + { + return DefaultDomain; + } + + /// Returns the default workstation from the current environment. + /// Returns the default workstation from the current environment. + /// A String containing the default workstation. + public static string GetDefaultWorkstation() + { + return DefaultWorkstation; + } + + /// + private void Parse(byte[] material) + { + for (int i = 0; i < 8; i++) + { + if (material[i] != NtlmsspSignature[i]) + { + throw new IOException("Not an NTLMSSP message."); + } + } + if (ReadULong(material, 8) != 1) + { + throw new IOException("Not a Type 1 message."); + } + int flags = ReadULong(material, 12); + string suppliedDomain = null; + if ((flags & NtlmsspNegotiateOemDomainSupplied) != 0) + { + byte[] domain = ReadSecurityBuffer(material, 16); + suppliedDomain = Runtime.GetStringForBytes(domain, GetOemEncoding()); + } + string suppliedWorkstation = null; + if ((flags & NtlmsspNegotiateOemWorkstationSupplied) != 0) + { + byte[] workstation = ReadSecurityBuffer(material, 24); + suppliedWorkstation = Runtime.GetStringForBytes(workstation, GetOemEncoding + ()); + } + SetFlags(flags); + SetSuppliedDomain(suppliedDomain); + SetSuppliedWorkstation(suppliedWorkstation); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/Type2Message.cs b/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/Type2Message.cs new file mode 100644 index 0000000000..104e5b0fdf --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/Type2Message.cs @@ -0,0 +1,438 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using SharpCifs.Netbios; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Ntlmssp +{ + /// Represents an NTLMSSP Type-2 message. + /// Represents an NTLMSSP Type-2 message. + public class Type2Message : NtlmMessage + { + private static readonly int DefaultFlags; + + private static readonly string DefaultDomain; + + private static readonly byte[] DefaultTargetInformation; + + private byte[] _challenge; + + private string _target; + + private byte[] _context; + + private byte[] _targetInformation; + + static Type2Message() + { + DefaultFlags = NtlmsspNegotiateNtlm | (Config.GetBoolean("jcifs.smb.client.useUnicode" + , true) ? NtlmsspNegotiateUnicode : NtlmsspNegotiateOem); + DefaultDomain = Config.GetProperty("jcifs.smb.client.domain", null); + byte[] domain = new byte[0]; + if (DefaultDomain != null) + { + try + { + domain = Runtime.GetBytesForString(DefaultDomain, UniEncoding); + } + catch (IOException) + { + } + } + int domainLength = domain.Length; + byte[] server = new byte[0]; + try + { + string host = NbtAddress.GetLocalHost().GetHostName(); + if (host != null) + { + try + { + server = Runtime.GetBytesForString(host, UniEncoding); + } + catch (IOException) + { + } + } + } + catch (UnknownHostException) + { + } + int serverLength = server.Length; + byte[] targetInfo = new byte[(domainLength > 0 ? domainLength + 4 : 0) + (serverLength + > 0 ? serverLength + 4 : 0) + 4]; + int offset = 0; + if (domainLength > 0) + { + WriteUShort(targetInfo, offset, 2); + offset += 2; + WriteUShort(targetInfo, offset, domainLength); + offset += 2; + Array.Copy(domain, 0, targetInfo, offset, domainLength); + offset += domainLength; + } + if (serverLength > 0) + { + WriteUShort(targetInfo, offset, 1); + offset += 2; + WriteUShort(targetInfo, offset, serverLength); + offset += 2; + Array.Copy(server, 0, targetInfo, offset, serverLength); + } + DefaultTargetInformation = targetInfo; + } + + /// + /// Creates a Type-2 message using default values from the current + /// environment. + /// + /// + /// Creates a Type-2 message using default values from the current + /// environment. + /// + public Type2Message() : this(GetDefaultFlags(), null, null) + { + } + + /// + /// Creates a Type-2 message in response to the given Type-1 message + /// using default values from the current environment. + /// + /// + /// Creates a Type-2 message in response to the given Type-1 message + /// using default values from the current environment. + /// + /// The Type-1 message which this represents a response to. + public Type2Message(Type1Message type1) : this(type1, null, null) + { + } + + /// Creates a Type-2 message in response to the given Type-1 message. + /// Creates a Type-2 message in response to the given Type-1 message. + /// The Type-1 message which this represents a response to. + /// The challenge from the domain controller/server. + /// The authentication target. + public Type2Message(Type1Message type1, byte[] challenge, string target) : this(GetDefaultFlags + (type1), challenge, (type1 != null && target == null && type1.GetFlag(NtlmsspRequestTarget + )) ? GetDefaultDomain() : target) + { + } + + /// Creates a Type-2 message with the specified parameters. + /// Creates a Type-2 message with the specified parameters. + /// The flags to apply to this message. + /// The challenge from the domain controller/server. + /// The authentication target. + public Type2Message(int flags, byte[] challenge, string target) + { + SetFlags(flags); + SetChallenge(challenge); + SetTarget(target); + if (target != null) + { + SetTargetInformation(GetDefaultTargetInformation()); + } + } + + /// Creates a Type-2 message using the given raw Type-2 material. + /// Creates a Type-2 message using the given raw Type-2 material. + /// The raw Type-2 material used to construct this message. + /// If an error occurs while parsing the material. + /// + public Type2Message(byte[] material) + { + Parse(material); + } + + /// Returns the challenge for this message. + /// Returns the challenge for this message. + /// A byte[] containing the challenge. + public virtual byte[] GetChallenge() + { + return _challenge; + } + + /// Sets the challenge for this message. + /// Sets the challenge for this message. + /// The challenge from the domain controller/server. + public virtual void SetChallenge(byte[] challenge) + { + this._challenge = challenge; + } + + /// Returns the authentication target. + /// Returns the authentication target. + /// A String containing the authentication target. + public virtual string GetTarget() + { + return _target; + } + + /// Sets the authentication target. + /// Sets the authentication target. + /// The authentication target. + public virtual void SetTarget(string target) + { + this._target = target; + } + + /// Returns the target information block. + /// Returns the target information block. + /// + /// A byte[] containing the target information block. + /// The target information block is used by the client to create an + /// NTLMv2 response. + /// + public virtual byte[] GetTargetInformation() + { + return _targetInformation; + } + + /// Sets the target information block. + /// + /// Sets the target information block. + /// The target information block is used by the client to create + /// an NTLMv2 response. + /// + /// The target information block. + public virtual void SetTargetInformation(byte[] targetInformation) + { + this._targetInformation = targetInformation; + } + + /// Returns the local security context. + /// Returns the local security context. + /// + /// A byte[] containing the local security + /// context. This is used by the client to negotiate local + /// authentication. + /// + public virtual byte[] GetContext() + { + return _context; + } + + /// Sets the local security context. + /// + /// Sets the local security context. This is used by the client + /// to negotiate local authentication. + /// + /// The local security context. + public virtual void SetContext(byte[] context) + { + this._context = context; + } + + public override byte[] ToByteArray() + { + try + { + string targetName = GetTarget(); + byte[] challenge = GetChallenge(); + byte[] context = GetContext(); + byte[] targetInformation = GetTargetInformation(); + int flags = GetFlags(); + byte[] target = new byte[0]; + if ((flags & NtlmsspRequestTarget) != 0) + { + if (!string.IsNullOrEmpty(targetName)) + { + target = (flags & NtlmsspNegotiateUnicode) != 0 ? Runtime.GetBytesForString + (targetName, UniEncoding) : Runtime.GetBytesForString(targetName.ToUpper + (), GetOemEncoding()); + } + else + { + flags &= (unchecked((int)(0xffffffff)) ^ NtlmsspRequestTarget); + } + } + if (targetInformation != null) + { + flags |= NtlmsspNegotiateTargetInfo; + // empty context is needed for padding when t.i. is supplied. + if (context == null) + { + context = new byte[8]; + } + } + int data = 32; + if (context != null) + { + data += 8; + } + if (targetInformation != null) + { + data += 8; + } + byte[] type2 = new byte[data + target.Length + (targetInformation != null ? targetInformation + .Length : 0)]; + Array.Copy(NtlmsspSignature, 0, type2, 0, 8); + WriteULong(type2, 8, 2); + WriteSecurityBuffer(type2, 12, data, target); + WriteULong(type2, 20, flags); + Array.Copy(challenge ?? new byte[8], 0, type2, 24, 8); + if (context != null) + { + Array.Copy(context, 0, type2, 32, 8); + } + if (targetInformation != null) + { + WriteSecurityBuffer(type2, 40, data + target.Length, targetInformation); + } + return type2; + } + catch (IOException ex) + { + throw new InvalidOperationException(ex.Message); + } + } + + public override string ToString() + { + string target = GetTarget(); + byte[] challenge = GetChallenge(); + byte[] context = GetContext(); + byte[] targetInformation = GetTargetInformation(); + return "Type2Message[target=" + target + ",challenge=" + (challenge == null ? "null" + : "<" + challenge.Length + " bytes>") + ",context=" + (context == null ? "null" + : "<" + context.Length + " bytes>") + ",targetInformation=" + (targetInformation + == null ? "null" : "<" + targetInformation.Length + " bytes>") + ",flags=0x" + + Hexdump.ToHexString(GetFlags(), 8) + "]"; + } + + /// + /// Returns the default flags for a generic Type-2 message in the + /// current environment. + /// + /// + /// Returns the default flags for a generic Type-2 message in the + /// current environment. + /// + /// An int containing the default flags. + public static int GetDefaultFlags() + { + return DefaultFlags; + } + + /// + /// Returns the default flags for a Type-2 message created in response + /// to the given Type-1 message in the current environment. + /// + /// + /// Returns the default flags for a Type-2 message created in response + /// to the given Type-1 message in the current environment. + /// + /// An int containing the default flags. + public static int GetDefaultFlags(Type1Message type1) + { + if (type1 == null) + { + return DefaultFlags; + } + int flags = NtlmsspNegotiateNtlm; + int type1Flags = type1.GetFlags(); + flags |= ((type1Flags & NtlmsspNegotiateUnicode) != 0) ? NtlmsspNegotiateUnicode + : NtlmsspNegotiateOem; + if ((type1Flags & NtlmsspRequestTarget) != 0) + { + string domain = GetDefaultDomain(); + if (domain != null) + { + flags |= NtlmsspRequestTarget | NtlmsspTargetTypeDomain; + } + } + return flags; + } + + /// Returns the default domain from the current environment. + /// Returns the default domain from the current environment. + /// A String containing the domain. + public static string GetDefaultDomain() + { + return DefaultDomain; + } + + public static byte[] GetDefaultTargetInformation() + { + return DefaultTargetInformation; + } + + /// + private void Parse(byte[] material) + { + for (int i = 0; i < 8; i++) + { + if (material[i] != NtlmsspSignature[i]) + { + throw new IOException("Not an NTLMSSP message."); + } + } + if (ReadULong(material, 8) != 2) + { + throw new IOException("Not a Type 2 message."); + } + int flags = ReadULong(material, 20); + SetFlags(flags); + string target = null; + byte[] bytes = ReadSecurityBuffer(material, 12); + if (bytes.Length != 0) + { + target = Runtime.GetStringForBytes(bytes, ((flags & NtlmsspNegotiateUnicode + ) != 0) ? UniEncoding : GetOemEncoding()); + } + SetTarget(target); + for (int i1 = 24; i1 < 32; i1++) + { + if (material[i1] != 0) + { + byte[] challenge = new byte[8]; + Array.Copy(material, 24, challenge, 0, 8); + SetChallenge(challenge); + break; + } + } + int offset = ReadULong(material, 16); + // offset of targetname start + if (offset == 32 || material.Length == 32) + { + return; + } + for (int i2 = 32; i2 < 40; i2++) + { + if (material[i2] != 0) + { + byte[] context = new byte[8]; + Array.Copy(material, 32, context, 0, 8); + SetContext(context); + break; + } + } + if (offset == 40 || material.Length == 40) + { + return; + } + bytes = ReadSecurityBuffer(material, 40); + if (bytes.Length != 0) + { + SetTargetInformation(bytes); + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/Type3Message.cs b/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/Type3Message.cs new file mode 100644 index 0000000000..9a2a37f3cf --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Ntlmssp/Type3Message.cs @@ -0,0 +1,677 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using SharpCifs.Netbios; +using SharpCifs.Smb; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Ntlmssp +{ + /// Represents an NTLMSSP Type-3 message. + /// Represents an NTLMSSP Type-3 message. + public class Type3Message : NtlmMessage + { + internal const long MillisecondsBetween1970And1601 = 11644473600000L; + + private static readonly int DefaultFlags; + + private static readonly string DefaultDomain; + + private static readonly string DefaultUser; + + private static readonly string DefaultPassword; + + private static readonly string DefaultWorkstation; + + private static readonly int LmCompatibility; + + //private static readonly SecureRandom RANDOM = new SecureRandom(); + + private byte[] _lmResponse; + + private byte[] _ntResponse; + + private string _domain; + + private string _user; + + private string _workstation; + + private byte[] _masterKey; + + private byte[] _sessionKey; + + static Type3Message() + { + DefaultFlags = NtlmsspNegotiateNtlm | (Config.GetBoolean("jcifs.smb.client.useUnicode" + , true) ? NtlmsspNegotiateUnicode : NtlmsspNegotiateOem); + DefaultDomain = Config.GetProperty("jcifs.smb.client.domain", null); + DefaultUser = Config.GetProperty("jcifs.smb.client.username", null); + DefaultPassword = Config.GetProperty("jcifs.smb.client.password", null); + string defaultWorkstation = null; + try + { + defaultWorkstation = NbtAddress.GetLocalHost().GetHostName(); + } + catch (UnknownHostException) + { + } + DefaultWorkstation = defaultWorkstation; + LmCompatibility = Config.GetInt("jcifs.smb.lmCompatibility", 3); + } + + /// + /// Creates a Type-3 message using default values from the current + /// environment. + /// + /// + /// Creates a Type-3 message using default values from the current + /// environment. + /// + public Type3Message() + { + SetFlags(GetDefaultFlags()); + SetDomain(GetDefaultDomain()); + SetUser(GetDefaultUser()); + SetWorkstation(GetDefaultWorkstation()); + } + + /// + /// Creates a Type-3 message in response to the given Type-2 message + /// using default values from the current environment. + /// + /// + /// Creates a Type-3 message in response to the given Type-2 message + /// using default values from the current environment. + /// + /// The Type-2 message which this represents a response to. + public Type3Message(Type2Message type2) + { + SetFlags(GetDefaultFlags(type2)); + SetWorkstation(GetDefaultWorkstation()); + string domain = GetDefaultDomain(); + SetDomain(domain); + string user = GetDefaultUser(); + SetUser(user); + string password = GetDefaultPassword(); + switch (LmCompatibility) + { + case 0: + case 1: + { + SetLmResponse(GetLMResponse(type2, password)); + SetNtResponse(GetNTResponse(type2, password)); + break; + } + + case 2: + { + byte[] nt = GetNTResponse(type2, password); + SetLmResponse(nt); + SetNtResponse(nt); + break; + } + + case 3: + case 4: + case 5: + { + byte[] clientChallenge = new byte[8]; + //RANDOM.NextBytes(clientChallenge); + SetLmResponse(GetLMv2Response(type2, domain, user, password, clientChallenge)); + break; + } + + default: + { + SetLmResponse(GetLMResponse(type2, password)); + SetNtResponse(GetNTResponse(type2, password)); + break; + } + } + } + + /// Creates a Type-3 message in response to the given Type-2 message. + /// Creates a Type-3 message in response to the given Type-2 message. + /// The Type-2 message which this represents a response to. + /// The password to use when constructing the response. + /// The domain in which the user has an account. + /// The username for the authenticating user. + /// + /// The workstation from which authentication is + /// taking place. + /// + public Type3Message(Type2Message type2, string password, string domain, string user + , string workstation, int flags) + { + SetFlags(flags | GetDefaultFlags(type2)); + if (workstation == null) + { + workstation = GetDefaultWorkstation(); + } + SetWorkstation(workstation); + SetDomain(domain); + SetUser(user); + switch (LmCompatibility) + { + case 0: + case 1: + { + if ((GetFlags() & NtlmsspNegotiateNtlm2) == 0) + { + SetLmResponse(GetLMResponse(type2, password)); + SetNtResponse(GetNTResponse(type2, password)); + } + else + { + // NTLM2 Session Response + byte[] clientChallenge = new byte[24]; + //RANDOM.NextBytes(clientChallenge); + Arrays.Fill(clientChallenge, 8, 24, unchecked((byte)unchecked(0x00))); + // NTLMv1 w/ NTLM2 session sec and key exch all been verified with a debug build of smbclient + byte[] responseKeyNt = NtlmPasswordAuthentication.NtowFv1(password); + byte[] ntlm2Response = NtlmPasswordAuthentication.GetNtlm2Response(responseKeyNt, + type2.GetChallenge(), clientChallenge); + SetLmResponse(clientChallenge); + SetNtResponse(ntlm2Response); + if ((GetFlags() & NtlmsspNegotiateSign) == NtlmsspNegotiateSign) + { + byte[] sessionNonce = new byte[16]; + Array.Copy(type2.GetChallenge(), 0, sessionNonce, 0, 8); + Array.Copy(clientChallenge, 0, sessionNonce, 8, 8); + Md4 md4 = new Md4(); + md4.Update(responseKeyNt); + byte[] userSessionKey = md4.Digest(); + Hmact64 hmac = new Hmact64(userSessionKey); + hmac.Update(sessionNonce); + byte[] ntlm2SessionKey = hmac.Digest(); + if ((GetFlags() & NtlmsspNegotiateKeyExch) != 0) + { + _masterKey = new byte[16]; + //RANDOM.NextBytes(masterKey); + byte[] exchangedKey = new byte[16]; + Rc4 rc4 = new Rc4(ntlm2SessionKey); + rc4.Update(_masterKey, 0, 16, exchangedKey, 0); + SetSessionKey(exchangedKey); + } + else + { + _masterKey = ntlm2SessionKey; + SetSessionKey(_masterKey); + } + } + } + break; + } + + case 2: + { + byte[] nt = GetNTResponse(type2, password); + SetLmResponse(nt); + SetNtResponse(nt); + break; + } + + case 3: + case 4: + case 5: + { + byte[] responseKeyNt1 = NtlmPasswordAuthentication.NtowFv2(domain, user, password + ); + byte[] clientChallenge1 = new byte[8]; + //RANDOM.NextBytes(clientChallenge_1); + SetLmResponse(GetLMv2Response(type2, domain, user, password, clientChallenge1)); + byte[] clientChallenge2 = new byte[8]; + //RANDOM.NextBytes(clientChallenge2); + SetNtResponse(GetNtlMv2Response(type2, responseKeyNt1, clientChallenge2)); + if ((GetFlags() & NtlmsspNegotiateSign) == NtlmsspNegotiateSign) + { + Hmact64 hmac = new Hmact64(responseKeyNt1); + hmac.Update(_ntResponse, 0, 16); + // only first 16 bytes of ntResponse + byte[] userSessionKey = hmac.Digest(); + if ((GetFlags() & NtlmsspNegotiateKeyExch) != 0) + { + _masterKey = new byte[16]; + //RANDOM.NextBytes(masterKey); + byte[] exchangedKey = new byte[16]; + Rc4 rc4 = new Rc4(userSessionKey); + rc4.Update(_masterKey, 0, 16, exchangedKey, 0); + SetSessionKey(exchangedKey); + } + else + { + _masterKey = userSessionKey; + SetSessionKey(_masterKey); + } + } + break; + } + + default: + { + SetLmResponse(GetLMResponse(type2, password)); + SetNtResponse(GetNTResponse(type2, password)); + break; + } + } + } + + /// Creates a Type-3 message with the specified parameters. + /// Creates a Type-3 message with the specified parameters. + /// The flags to apply to this message. + /// The LanManager/LMv2 response. + /// The NT/NTLMv2 response. + /// The domain in which the user has an account. + /// The username for the authenticating user. + /// + /// The workstation from which authentication is + /// taking place. + /// + public Type3Message(int flags, byte[] lmResponse, byte[] ntResponse, string domain + , string user, string workstation) + { + SetFlags(flags); + SetLmResponse(lmResponse); + SetNtResponse(ntResponse); + SetDomain(domain); + SetUser(user); + SetWorkstation(workstation); + } + + /// Creates a Type-3 message using the given raw Type-3 material. + /// Creates a Type-3 message using the given raw Type-3 material. + /// The raw Type-3 material used to construct this message. + /// If an error occurs while parsing the material. + /// + public Type3Message(byte[] material) + { + Parse(material); + } + + /// Returns the LanManager/LMv2 response. + /// Returns the LanManager/LMv2 response. + /// A byte[] containing the LanManager response. + public virtual byte[] GetLMResponse() + { + return _lmResponse; + } + + /// Sets the LanManager/LMv2 response for this message. + /// Sets the LanManager/LMv2 response for this message. + /// The LanManager response. + public virtual void SetLmResponse(byte[] lmResponse) + { + this._lmResponse = lmResponse; + } + + /// Returns the NT/NTLMv2 response. + /// Returns the NT/NTLMv2 response. + /// A byte[] containing the NT/NTLMv2 response. + public virtual byte[] GetNTResponse() + { + return _ntResponse; + } + + /// Sets the NT/NTLMv2 response for this message. + /// Sets the NT/NTLMv2 response for this message. + /// The NT/NTLMv2 response. + public virtual void SetNtResponse(byte[] ntResponse) + { + this._ntResponse = ntResponse; + } + + /// Returns the domain in which the user has an account. + /// Returns the domain in which the user has an account. + /// A String containing the domain for the user. + public virtual string GetDomain() + { + return _domain; + } + + /// Sets the domain for this message. + /// Sets the domain for this message. + /// The domain. + public virtual void SetDomain(string domain) + { + this._domain = domain; + } + + /// Returns the username for the authenticating user. + /// Returns the username for the authenticating user. + /// A String containing the user for this message. + public virtual string GetUser() + { + return _user; + } + + /// Sets the user for this message. + /// Sets the user for this message. + /// The user. + public virtual void SetUser(string user) + { + this._user = user; + } + + /// Returns the workstation from which authentication is being performed. + /// Returns the workstation from which authentication is being performed. + /// A String containing the workstation. + public virtual string GetWorkstation() + { + return _workstation; + } + + /// Sets the workstation for this message. + /// Sets the workstation for this message. + /// The workstation. + public virtual void SetWorkstation(string workstation) + { + this._workstation = workstation; + } + + /// + /// The real session key if the regular session key is actually + /// the encrypted version used for key exchange. + /// + /// + /// The real session key if the regular session key is actually + /// the encrypted version used for key exchange. + /// + /// A byte[] containing the session key. + public virtual byte[] GetMasterKey() + { + return _masterKey; + } + + /// Returns the session key. + /// Returns the session key. + /// A byte[] containing the session key. + public virtual byte[] GetSessionKey() + { + return _sessionKey; + } + + /// Sets the session key. + /// Sets the session key. + /// The session key. + public virtual void SetSessionKey(byte[] sessionKey) + { + this._sessionKey = sessionKey; + } + + public override byte[] ToByteArray() + { + try + { + int flags = GetFlags(); + bool unicode = (flags & NtlmsspNegotiateUnicode) != 0; + string oem = unicode ? null : GetOemEncoding(); + string domainName = GetDomain(); + byte[] domain = null; + if (!string.IsNullOrEmpty(domainName)) + { + domain = unicode ? Runtime.GetBytesForString(domainName, UniEncoding) : + Runtime.GetBytesForString(domainName, oem); + } + int domainLength = (domain != null) ? domain.Length : 0; + string userName = GetUser(); + byte[] user = null; + if (!string.IsNullOrEmpty(userName)) + { + user = unicode ? Runtime.GetBytesForString(userName, UniEncoding) : Runtime.GetBytesForString + (userName.ToUpper(), oem); + } + int userLength = (user != null) ? user.Length : 0; + string workstationName = GetWorkstation(); + byte[] workstation = null; + if (!string.IsNullOrEmpty(workstationName)) + { + workstation = unicode ? Runtime.GetBytesForString(workstationName, UniEncoding + ) : Runtime.GetBytesForString(workstationName.ToUpper(), oem); + } + int workstationLength = (workstation != null) ? workstation.Length : 0; + byte[] lmResponse = GetLMResponse(); + int lmLength = (lmResponse != null) ? lmResponse.Length : 0; + byte[] ntResponse = GetNTResponse(); + int ntLength = (ntResponse != null) ? ntResponse.Length : 0; + byte[] sessionKey = GetSessionKey(); + int keyLength = (sessionKey != null) ? sessionKey.Length : 0; + byte[] type3 = new byte[64 + domainLength + userLength + workstationLength + lmLength + + ntLength + keyLength]; + Array.Copy(NtlmsspSignature, 0, type3, 0, 8); + WriteULong(type3, 8, 3); + int offset = 64; + WriteSecurityBuffer(type3, 12, offset, lmResponse); + offset += lmLength; + WriteSecurityBuffer(type3, 20, offset, ntResponse); + offset += ntLength; + WriteSecurityBuffer(type3, 28, offset, domain); + offset += domainLength; + WriteSecurityBuffer(type3, 36, offset, user); + offset += userLength; + WriteSecurityBuffer(type3, 44, offset, workstation); + offset += workstationLength; + WriteSecurityBuffer(type3, 52, offset, sessionKey); + WriteULong(type3, 60, flags); + return type3; + } + catch (IOException ex) + { + throw new InvalidOperationException(ex.Message); + } + } + + public override string ToString() + { + string user = GetUser(); + string domain = GetDomain(); + string workstation = GetWorkstation(); + byte[] lmResponse = GetLMResponse(); + byte[] ntResponse = GetNTResponse(); + byte[] sessionKey = GetSessionKey(); + return "Type3Message[domain=" + domain + ",user=" + user + ",workstation=" + workstation + + ",lmResponse=" + (lmResponse == null ? "null" : "<" + lmResponse.Length + " bytes>" + ) + ",ntResponse=" + (ntResponse == null ? "null" : "<" + ntResponse.Length + " bytes>" + ) + ",sessionKey=" + (sessionKey == null ? "null" : "<" + sessionKey.Length + " bytes>" + ) + ",flags=0x" + Hexdump.ToHexString(GetFlags(), 8) + "]"; + } + + /// + /// Returns the default flags for a generic Type-3 message in the + /// current environment. + /// + /// + /// Returns the default flags for a generic Type-3 message in the + /// current environment. + /// + /// An int containing the default flags. + public static int GetDefaultFlags() + { + return DefaultFlags; + } + + /// + /// Returns the default flags for a Type-3 message created in response + /// to the given Type-2 message in the current environment. + /// + /// + /// Returns the default flags for a Type-3 message created in response + /// to the given Type-2 message in the current environment. + /// + /// An int containing the default flags. + public static int GetDefaultFlags(Type2Message type2) + { + if (type2 == null) + { + return DefaultFlags; + } + int flags = NtlmsspNegotiateNtlm; + flags |= ((type2.GetFlags() & NtlmsspNegotiateUnicode) != 0) ? NtlmsspNegotiateUnicode + : NtlmsspNegotiateOem; + return flags; + } + + /// + /// Constructs the LanManager response to the given Type-2 message using + /// the supplied password. + /// + /// + /// Constructs the LanManager response to the given Type-2 message using + /// the supplied password. + /// + /// The Type-2 message. + /// The password. + /// A byte[] containing the LanManager response. + public static byte[] GetLMResponse(Type2Message type2, string password) + { + if (type2 == null || password == null) + { + return null; + } + return NtlmPasswordAuthentication.GetPreNtlmResponse(password, type2.GetChallenge + ()); + } + + public static byte[] GetLMv2Response(Type2Message type2, string domain, string user + , string password, byte[] clientChallenge) + { + if (type2 == null || domain == null || user == null || password == null || clientChallenge + == null) + { + return null; + } + return NtlmPasswordAuthentication.GetLMv2Response(domain, user, password, type2.GetChallenge + (), clientChallenge); + } + + public static byte[] GetNtlMv2Response(Type2Message type2, byte[] responseKeyNt, + byte[] clientChallenge) + { + if (type2 == null || responseKeyNt == null || clientChallenge == null) + { + return null; + } + long nanos1601 = (Runtime.CurrentTimeMillis() + MillisecondsBetween1970And1601 + ) * 10000L; + return NtlmPasswordAuthentication.GetNtlMv2Response(responseKeyNt, type2.GetChallenge + (), clientChallenge, nanos1601, type2.GetTargetInformation()); + } + + /// + /// Constructs the NT response to the given Type-2 message using + /// the supplied password. + /// + /// + /// Constructs the NT response to the given Type-2 message using + /// the supplied password. + /// + /// The Type-2 message. + /// The password. + /// A byte[] containing the NT response. + public static byte[] GetNTResponse(Type2Message type2, string password) + { + if (type2 == null || password == null) + { + return null; + } + return NtlmPasswordAuthentication.GetNtlmResponse(password, type2.GetChallenge()); + } + + /// Returns the default domain from the current environment. + /// Returns the default domain from the current environment. + /// The default domain. + public static string GetDefaultDomain() + { + return DefaultDomain; + } + + /// Returns the default user from the current environment. + /// Returns the default user from the current environment. + /// The default user. + public static string GetDefaultUser() + { + return DefaultUser; + } + + /// Returns the default password from the current environment. + /// Returns the default password from the current environment. + /// The default password. + public static string GetDefaultPassword() + { + return DefaultPassword; + } + + /// Returns the default workstation from the current environment. + /// Returns the default workstation from the current environment. + /// The default workstation. + public static string GetDefaultWorkstation() + { + return DefaultWorkstation; + } + + /// + private void Parse(byte[] material) + { + for (int i = 0; i < 8; i++) + { + if (material[i] != NtlmsspSignature[i]) + { + throw new IOException("Not an NTLMSSP message."); + } + } + if (ReadULong(material, 8) != 3) + { + throw new IOException("Not a Type 3 message."); + } + byte[] lmResponse = ReadSecurityBuffer(material, 12); + int lmResponseOffset = ReadULong(material, 16); + byte[] ntResponse = ReadSecurityBuffer(material, 20); + int ntResponseOffset = ReadULong(material, 24); + byte[] domain = ReadSecurityBuffer(material, 28); + int domainOffset = ReadULong(material, 32); + byte[] user = ReadSecurityBuffer(material, 36); + int userOffset = ReadULong(material, 40); + byte[] workstation = ReadSecurityBuffer(material, 44); + int workstationOffset = ReadULong(material, 48); + int flags; + string charset; + byte[] _sessionKey = null; + if (lmResponseOffset == 52 || ntResponseOffset == 52 || domainOffset == 52 || userOffset + == 52 || workstationOffset == 52) + { + flags = NtlmsspNegotiateNtlm | NtlmsspNegotiateOem; + charset = GetOemEncoding(); + } + else + { + _sessionKey = ReadSecurityBuffer(material, 52); + flags = ReadULong(material, 60); + charset = ((flags & NtlmsspNegotiateUnicode) != 0) ? UniEncoding : GetOemEncoding + (); + } + SetSessionKey(_sessionKey); + SetFlags(flags); + SetLmResponse(lmResponse); + SetNtResponse(ntResponse); + SetDomain(Runtime.GetStringForBytes(domain, charset)); + SetUser(Runtime.GetStringForBytes(user, charset)); + SetWorkstation(Runtime.GetStringForBytes(workstation, charset)); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/ACE.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/ACE.cs new file mode 100644 index 0000000000..73b742cfb6 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/ACE.cs @@ -0,0 +1,287 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Text; +using SharpCifs.Util; + +namespace SharpCifs.Smb +{ + /// + /// An Access Control Entry (ACE) is an element in a security descriptor + /// such as those associated with files and directories. + /// + /// + /// An Access Control Entry (ACE) is an element in a security descriptor + /// such as those associated with files and directories. The Windows OS + /// determines which users have the necessary permissions to access objects + /// based on these entries. + ///

+ /// To fully understand the information exposed by this class a description + /// of the access check algorithm used by Windows is required. The following + /// is a basic description of the algorithm. For a more complete description + /// we recommend reading the section on Access Control in Keith Brown's + /// "The .NET Developer's Guide to Windows Security" (which is also + /// available online). + ///

+ /// Direct ACEs are evaluated first in order. The SID of the user performing + /// the operation and the desired access bits are compared to the SID + /// and access mask of each ACE. If the SID matches, the allow/deny flags + /// and access mask are considered. If the ACE is a "deny" + /// ACE and any of the desired access bits match bits in the access + /// mask of the ACE, the whole access check fails. If the ACE is an "allow" + /// ACE and all of the bits in the desired access bits match bits in + /// the access mask of the ACE, the access check is successful. Otherwise, + /// more ACEs are evaluated until all desired access bits (combined) + /// are "allowed". If all of the desired access bits are not "allowed" + /// the then same process is repeated for inherited ACEs. + ///

+ /// For example, if user WNET\alice tries to open a file + /// with desired access bits 0x00000003 (FILE_READ_DATA | + /// FILE_WRITE_DATA) and the target file has the following security + /// descriptor ACEs: + ///

+	/// Allow WNET\alice     0x001200A9  Direct
+	/// Allow Administrators 0x001F01FF  Inherited
+	/// Allow SYSTEM         0x001F01FF  Inherited
+	/// 
+ /// the access check would fail because the direct ACE has an access mask + /// of 0x001200A9 which doesn't have the + /// FILE_WRITE_DATA bit on (bit 0x00000002). Actually, this isn't quite correct. If + /// WNET\alice is in the local Administrators group the access check + /// will succeed because the inherited ACE allows local Administrators + /// both FILE_READ_DATA and FILE_WRITE_DATA access. + ///
+ public class Ace + { + public const int FileReadData = unchecked(0x00000001); + + public const int FileWriteData = unchecked(0x00000002); + + public const int FileAppendData = unchecked(0x00000004); + + public const int FileReadEa = unchecked(0x00000008); + + public const int FileWriteEa = unchecked(0x00000010); + + public const int FileExecute = unchecked(0x00000020); + + public const int FileDelete = unchecked(0x00000040); + + public const int FileReadAttributes = unchecked(0x00000080); + + public const int FileWriteAttributes = unchecked(0x00000100); + + public const int Delete = unchecked(0x00010000); + + public const int ReadControl = unchecked(0x00020000); + + public const int WriteDac = unchecked(0x00040000); + + public const int WriteOwner = unchecked(0x00080000); + + public const int Synchronize = unchecked(0x00100000); + + public const int GenericAll = unchecked(0x10000000); + + public const int GenericExecute = unchecked(0x20000000); + + public const int GenericWrite = unchecked(0x40000000); + + public const int GenericRead = unchecked((int)(0x80000000)); + + public const int FlagsObjectInherit = unchecked(0x01); + + public const int FlagsContainerInherit = unchecked(0x02); + + public const int FlagsNoPropagate = unchecked(0x04); + + public const int FlagsInheritOnly = unchecked(0x08); + + public const int FlagsInherited = unchecked(0x10); + + internal bool Allow; + + internal int Flags; + + internal int Access; + + internal Sid Sid; + + // 1 + // 2 + // 3 + // 4 + // 5 + // 6 + // 7 + // 8 + // 9 + // 16 + // 17 + // 18 + // 19 + // 20 + // 28 + // 29 + // 30 + // 31 + /// Returns true if this ACE is an allow ACE and false if it is a deny ACE. + /// Returns true if this ACE is an allow ACE and false if it is a deny ACE. + public virtual bool IsAllow() + { + return Allow; + } + + /// Returns true if this ACE is an inherited ACE and false if it is a direct ACE. + /// + /// + /// Returns true if this ACE is an inherited ACE and false if it is a direct ACE. + ///

+ /// Note: For reasons not fully understood, FLAGS_INHERITED may + /// not be set within all security descriptors even though the ACE was in + /// face inherited. If an inherited ACE is added to a parent the Windows + /// ACL editor will rebuild all children ACEs and set this flag accordingly. + /// + public virtual bool IsInherited() + { + return (Flags & FlagsInherited) != 0; + } + + ///

Returns the flags for this ACE. + /// + /// Returns the flags for this ACE. The isInherited() + /// method checks the FLAGS_INHERITED bit in these flags. + /// + public virtual int GetFlags() + { + return Flags; + } + + /// + /// Returns the 'Apply To' text for inheritance of ACEs on + /// directories such as 'This folder, subfolder and files'. + /// + /// + /// Returns the 'Apply To' text for inheritance of ACEs on + /// directories such as 'This folder, subfolder and files'. For + /// files the text is always 'This object only'. + /// + public virtual string GetApplyToText() + { + switch (Flags & (FlagsObjectInherit | FlagsContainerInherit | FlagsInheritOnly + )) + { + case unchecked(0x00): + { + return "This folder only"; + } + + case unchecked(0x03): + { + return "This folder, subfolders and files"; + } + + case unchecked(0x0B): + { + return "Subfolders and files only"; + } + + case unchecked(0x02): + { + return "This folder and subfolders"; + } + + case unchecked(0x0A): + { + return "Subfolders only"; + } + + case unchecked(0x01): + { + return "This folder and files"; + } + + case unchecked(0x09): + { + return "Files only"; + } + } + return "Invalid"; + } + + /// Returns the access mask accociated with this ACE. + /// + /// Returns the access mask accociated with this ACE. Use the + /// constants for FILE_READ_DATA, FILE_WRITE_DATA, + /// READ_CONTROL, GENERIC_ALL, etc with bitwise + /// operators to determine which bits of the mask are on or off. + /// + public virtual int GetAccessMask() + { + return Access; + } + + /// Return the SID associated with this ACE. + /// Return the SID associated with this ACE. + public virtual Sid GetSid() + { + return Sid; + } + + internal virtual int Decode(byte[] buf, int bi) + { + Allow = buf[bi++] == unchecked(unchecked(0x00)); + Flags = buf[bi++] & unchecked(0xFF); + int size = ServerMessageBlock.ReadInt2(buf, bi); + bi += 2; + Access = ServerMessageBlock.ReadInt4(buf, bi); + bi += 4; + Sid = new Sid(buf, bi); + return size; + } + + internal virtual void AppendCol(StringBuilder sb, string str, int width) + { + sb.Append(str); + int count = width - str.Length; + for (int i = 0; i < count; i++) + { + sb.Append(' '); + } + } + + /// Return a string represeting this ACE. + /// + /// Return a string represeting this ACE. + ///

+ /// Note: This function should probably be changed to return SDDL + /// fragments but currently it does not. + /// + public override string ToString() + { + int count; + int i; + string str; + StringBuilder sb = new StringBuilder(); + sb.Append(IsAllow() ? "Allow " : "Deny "); + AppendCol(sb, Sid.ToDisplayString(), 25); + sb.Append(" 0x").Append(Hexdump.ToHexString(Access, 8)).Append(' '); + sb.Append(IsInherited() ? "Inherited " : "Direct "); + AppendCol(sb, GetApplyToText(), 34); + return sb.ToString(); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/AllocInfo.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/AllocInfo.cs new file mode 100644 index 0000000000..6ebe882930 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/AllocInfo.cs @@ -0,0 +1,25 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal interface IAllocInfo + { + long GetCapacity(); + + long GetFree(); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/AndXServerMessageBlock.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/AndXServerMessageBlock.cs new file mode 100644 index 0000000000..e78bff9d0a --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/AndXServerMessageBlock.cs @@ -0,0 +1,221 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal abstract class AndXServerMessageBlock : ServerMessageBlock + { + private const int AndxCommandOffset = 1; + + private const int AndxReservedOffset = 2; + + private const int AndxOffsetOffset = 3; + + private byte _andxCommand = unchecked(unchecked(0xFF)); + + private int _andxOffset; + + internal ServerMessageBlock Andx; + + public AndXServerMessageBlock() + { + } + + internal AndXServerMessageBlock(ServerMessageBlock andx) + { + if (andx != null) + { + this.Andx = andx; + _andxCommand = andx.Command; + } + } + + internal virtual int GetBatchLimit(byte command) + { + return 0; + } + + internal override int Encode(byte[] dst, int dstIndex) + { + int start = HeaderStart = dstIndex; + dstIndex += WriteHeaderWireFormat(dst, dstIndex); + dstIndex += WriteAndXWireFormat(dst, dstIndex); + Length = dstIndex - start; + if (Digest != null) + { + Digest.Sign(dst, HeaderStart, Length, this, Response); + } + return Length; + } + + internal override int Decode(byte[] buffer, int bufferIndex) + { + int start = HeaderStart = bufferIndex; + bufferIndex += ReadHeaderWireFormat(buffer, bufferIndex); + bufferIndex += ReadAndXWireFormat(buffer, bufferIndex); + Length = bufferIndex - start; + return Length; + } + + internal virtual int WriteAndXWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WordCount = WriteParameterWordsWireFormat(dst, start + AndxOffsetOffset + 2); + WordCount += 4; + // for command, reserved, and offset + dstIndex += WordCount + 1; + WordCount /= 2; + dst[start] = unchecked((byte)(WordCount & unchecked(0xFF))); + ByteCount = WriteBytesWireFormat(dst, dstIndex + 2); + dst[dstIndex++] = unchecked((byte)(ByteCount & unchecked(0xFF))); + dst[dstIndex++] = unchecked((byte)((ByteCount >> 8) & unchecked(0xFF))); + dstIndex += ByteCount; + if (Andx == null || SmbConstants.UseBatching == false || BatchLevel >= GetBatchLimit(Andx.Command + )) + { + _andxCommand = unchecked(unchecked(0xFF)); + Andx = null; + dst[start + AndxCommandOffset] = unchecked(unchecked(0xFF)); + dst[start + AndxReservedOffset] = unchecked(unchecked(0x00)); + // dst[start + ANDX_OFFSET_OFFSET] = (byte)0x00; + // dst[start + ANDX_OFFSET_OFFSET + 1] = (byte)0x00; + dst[start + AndxOffsetOffset] = unchecked(unchecked(0xde)); + dst[start + AndxOffsetOffset + 1] = unchecked(unchecked(0xde)); + // andx not used; return + return dstIndex - start; + } + Andx.BatchLevel = BatchLevel + 1; + dst[start + AndxCommandOffset] = _andxCommand; + dst[start + AndxReservedOffset] = unchecked(unchecked(0x00)); + _andxOffset = dstIndex - HeaderStart; + WriteInt2(_andxOffset, dst, start + AndxOffsetOffset); + Andx.UseUnicode = UseUnicode; + if (Andx is AndXServerMessageBlock) + { + Andx.Uid = Uid; + dstIndex += ((AndXServerMessageBlock)Andx).WriteAndXWireFormat(dst, dstIndex + ); + } + else + { + // the andx smb is not of type andx so lets just write it here and + // were done. + int andxStart = dstIndex; + Andx.WordCount = Andx.WriteParameterWordsWireFormat(dst, dstIndex); + dstIndex += Andx.WordCount + 1; + Andx.WordCount /= 2; + dst[andxStart] = unchecked((byte)(Andx.WordCount & unchecked(0xFF))); + Andx.ByteCount = Andx.WriteBytesWireFormat(dst, dstIndex + 2); + dst[dstIndex++] = unchecked((byte)(Andx.ByteCount & unchecked(0xFF))); + dst[dstIndex++] = unchecked((byte)((Andx.ByteCount >> 8) & unchecked(0xFF) + )); + dstIndex += Andx.ByteCount; + } + return dstIndex - start; + } + + internal virtual int ReadAndXWireFormat(byte[] buffer, int bufferIndex) + { + int start = bufferIndex; + WordCount = buffer[bufferIndex++]; + if (WordCount != 0) + { + _andxCommand = buffer[bufferIndex]; + _andxOffset = ReadInt2(buffer, bufferIndex + 2); + if (_andxOffset == 0) + { + _andxCommand = unchecked(unchecked(0xFF)); + } + if (WordCount > 2) + { + ReadParameterWordsWireFormat(buffer, bufferIndex + 4); + if (Command == SmbComNtCreateAndx && ((SmbComNtCreateAndXResponse)this).IsExtended) + { + WordCount += 8; + } + } + bufferIndex = start + 1 + (WordCount * 2); + } + ByteCount = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + if (ByteCount != 0) + { + int n; + n = ReadBytesWireFormat(buffer, bufferIndex); + bufferIndex += ByteCount; + } + if (ErrorCode != 0 || _andxCommand == unchecked(unchecked(0xFF))) + { + _andxCommand = unchecked(unchecked(0xFF)); + Andx = null; + } + else + { + if (Andx == null) + { + _andxCommand = unchecked(unchecked(0xFF)); + throw new RuntimeException("no andx command supplied with response"); + } + bufferIndex = HeaderStart + _andxOffset; + Andx.HeaderStart = HeaderStart; + Andx.Command = _andxCommand; + Andx.ErrorCode = ErrorCode; + Andx.Flags = Flags; + Andx.Flags2 = Flags2; + Andx.Tid = Tid; + Andx.Pid = Pid; + Andx.Uid = Uid; + Andx.Mid = Mid; + Andx.UseUnicode = UseUnicode; + if (Andx is AndXServerMessageBlock) + { + bufferIndex += ((AndXServerMessageBlock)Andx).ReadAndXWireFormat(buffer + , bufferIndex); + } + else + { + buffer[bufferIndex++] = unchecked((byte)(Andx.WordCount & unchecked(0xFF)) + ); + if (Andx.WordCount != 0) + { + if (Andx.WordCount > 2) + { + bufferIndex += Andx.ReadParameterWordsWireFormat(buffer, bufferIndex); + } + } + Andx.ByteCount = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + if (Andx.ByteCount != 0) + { + Andx.ReadBytesWireFormat(buffer, bufferIndex); + bufferIndex += Andx.ByteCount; + } + } + Andx.Received = true; + } + return bufferIndex - start; + } + + public override string ToString() + { + return base.ToString() + ",andxCommand=0x" + Hexdump.ToHexString(_andxCommand + , 2) + ",andxOffset=" + _andxOffset; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/BufferCache.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/BufferCache.cs new file mode 100644 index 0000000000..b36816e269 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/BufferCache.cs @@ -0,0 +1,80 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + public class BufferCache + { + private static readonly int MaxBuffers = Config.GetInt("jcifs.smb.maxBuffers", 16 + ); + + internal static object[] Cache = new object[MaxBuffers]; + + private static int _freeBuffers; + + public static byte[] GetBuffer() + { + lock (Cache) + { + byte[] buf; + if (_freeBuffers > 0) + { + for (int i = 0; i < MaxBuffers; i++) + { + if (Cache[i] != null) + { + buf = (byte[])Cache[i]; + Cache[i] = null; + _freeBuffers--; + return buf; + } + } + } + buf = new byte[SmbComTransaction.TransactionBufSize]; + return buf; + } + } + + internal static void GetBuffers(SmbComTransaction req, SmbComTransactionResponse + rsp) + { + lock (Cache) + { + req.TxnBuf = GetBuffer(); + rsp.TxnBuf = GetBuffer(); + } + } + + public static void ReleaseBuffer(byte[] buf) + { + lock (Cache) + { + if (_freeBuffers < MaxBuffers) + { + for (int i = 0; i < MaxBuffers; i++) + { + if (Cache[i] == null) + { + Cache[i] = buf; + _freeBuffers++; + return; + } + } + } + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Dfs.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Dfs.cs new file mode 100644 index 0000000000..2f62e5b8d0 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Dfs.cs @@ -0,0 +1,389 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.IO; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + public class Dfs + { + internal class CacheEntry + { + internal long Expiration; + + internal Hashtable Map; + + internal CacheEntry(long ttl) + { + if (ttl == 0) + { + ttl = Ttl; + } + Expiration = Runtime.CurrentTimeMillis() + ttl * 1000L; + Map = new Hashtable(); + } + } + + internal static LogStream Log = LogStream.GetInstance(); + + internal static readonly bool StrictView = Config.GetBoolean("jcifs.smb.client.dfs.strictView" + , false); + + internal static readonly long Ttl = Config.GetLong("jcifs.smb.client.dfs.ttl", 300 + ); + + internal static readonly bool Disabled = Config.GetBoolean("jcifs.smb.client.dfs.disabled" + , false); + + internal static CacheEntry FalseEntry = new CacheEntry(0L); + + internal CacheEntry Domains; + + internal CacheEntry Referrals; + + /// + public virtual Hashtable GetTrustedDomains(NtlmPasswordAuthentication auth) + { + if (Disabled || auth.Domain == "?") + { + return null; + } + if (Domains != null && Runtime.CurrentTimeMillis() > Domains.Expiration) + { + Domains = null; + } + if (Domains != null) + { + return Domains.Map; + } + try + { + UniAddress addr = UniAddress.GetByName(auth.Domain, true); + SmbTransport trans = SmbTransport.GetSmbTransport(addr, 0); + CacheEntry entry = new CacheEntry(Ttl * 10L); + DfsReferral dr = trans.GetDfsReferrals(auth, string.Empty, 0); + if (dr != null) + { + DfsReferral start = dr; + do + { + string domain = dr.Server.ToLower(); + entry.Map.Put(domain, new Hashtable()); + dr = dr.Next; + } + while (dr != start); + Domains = entry; + return Domains.Map; + } + } + catch (IOException ioe) + { + if (Log.Level >= 3) + { + Runtime.PrintStackTrace(ioe, Log); + } + if (StrictView && ioe is SmbAuthException) + { + throw (SmbAuthException)ioe; + } + } + return null; + } + + /// + public virtual bool IsTrustedDomain(string domain, NtlmPasswordAuthentication auth + ) + { + Hashtable domains = GetTrustedDomains(auth); + if (domains == null) + { + return false; + } + domain = domain.ToLower(); + return domains.Get(domain) != null; + } + + /// + public virtual SmbTransport GetDc(string domain, NtlmPasswordAuthentication auth) + { + if (Disabled) + { + return null; + } + try + { + UniAddress addr = UniAddress.GetByName(domain, true); + SmbTransport trans = SmbTransport.GetSmbTransport(addr, 0); + DfsReferral dr = trans.GetDfsReferrals(auth, "\\" + domain, 1); + if (dr != null) + { + DfsReferral start = dr; + IOException e = null; + do + { + try + { + addr = UniAddress.GetByName(dr.Server); + return SmbTransport.GetSmbTransport(addr, 0); + } + catch (IOException ioe) + { + e = ioe; + } + dr = dr.Next; + } + while (dr != start); + throw e; + } + } + catch (IOException ioe) + { + if (Log.Level >= 3) + { + Runtime.PrintStackTrace(ioe, Log); + } + if (StrictView && ioe is SmbAuthException) + { + throw (SmbAuthException)ioe; + } + } + return null; + } + + /// + public virtual DfsReferral GetReferral(SmbTransport trans, string domain, string + root, string path, NtlmPasswordAuthentication auth) + { + if (Disabled) + { + return null; + } + try + { + string p = "\\" + domain + "\\" + root; + if (path != null) + { + p += path; + } + DfsReferral dr = trans.GetDfsReferrals(auth, p, 0); + if (dr != null) + { + return dr; + } + } + catch (IOException ioe) + { + if (Log.Level >= 4) + { + Runtime.PrintStackTrace(ioe, Log); + } + if (StrictView && ioe is SmbAuthException) + { + throw (SmbAuthException)ioe; + } + } + return null; + } + + /// + public virtual DfsReferral Resolve(string domain, string root, string path, NtlmPasswordAuthentication + auth) + { + lock (this) + { + DfsReferral dr = null; + long now = Runtime.CurrentTimeMillis(); + if (Disabled || root.Equals("IPC$")) + { + return null; + } + Hashtable domains = GetTrustedDomains(auth); + if (domains != null) + { + domain = domain.ToLower(); + Hashtable roots = (Hashtable)domains.Get(domain); + if (roots != null) + { + SmbTransport trans = null; + root = root.ToLower(); + CacheEntry links = (CacheEntry)roots.Get(root); + if (links != null && now > links.Expiration) + { + //Sharpen.Collections.Remove(roots, root); + roots.Remove(root); + links = null; + } + if (links == null) + { + if ((trans = GetDc(domain, auth)) == null) + { + return null; + } + dr = GetReferral(trans, domain, root, path, auth); + if (dr != null) + { + int len = 1 + domain.Length + 1 + root.Length; + links = new CacheEntry(0L); + DfsReferral tmp = dr; + do + { + if (path == null) + { + // TODO: fix this + //tmp.map = links.map; + tmp.Key = "\\"; + } + tmp.PathConsumed -= len; + tmp = tmp.Next; + } + while (tmp != dr); + if (dr.Key != null) + { + links.Map.Put(dr.Key, dr); + } + roots.Put(root, links); + } + else + { + if (path == null) + { + roots.Put(root, FalseEntry); + } + } + } + else + { + if (links == FalseEntry) + { + links = null; + } + } + if (links != null) + { + string link = "\\"; + dr = (DfsReferral)links.Map.Get(link); + if (dr != null && now > dr.Expiration) + { + //Sharpen.Collections.Remove(links.map, link); + links.Map.Remove(link); + dr = null; + } + if (dr == null) + { + if (trans == null) + { + if ((trans = GetDc(domain, auth)) == null) + { + return null; + } + } + dr = GetReferral(trans, domain, root, path, auth); + if (dr != null) + { + dr.PathConsumed -= 1 + domain.Length + 1 + root.Length; + dr.Link = link; + links.Map.Put(link, dr); + } + } + } + } + } + if (dr == null && path != null) + { + if (Referrals != null && now > Referrals.Expiration) + { + Referrals = null; + } + if (Referrals == null) + { + Referrals = new CacheEntry(0); + } + string key = "\\" + domain + "\\" + root; + if (path.Equals("\\") == false) + { + key += path; + } + key = key.ToLower(); + //ListIterator iter = new ListIterator(referrals.map.Keys.GetEnumerator(), 0); + foreach (var current in Referrals.Map.Keys) + { + string _key = (string)current; + int klen = _key.Length; + bool match = false; + if (klen == key.Length) + { + match = _key.Equals(key); + } + else + { + if (klen < key.Length) + { + match = _key.RegionMatches(false, 0, key, 0, klen) && key[klen] == '\\'; + } + } + if (match) + { + dr = (DfsReferral)Referrals.Map.Get(_key); + } + } + } + return dr; + } + } + + internal virtual void Insert(string path, DfsReferral dr) + { + lock (this) + { + int s1; + int s2; + string server; + string share; + string key; + if (Disabled) + { + return; + } + s1 = path.IndexOf('\\', 1); + s2 = path.IndexOf('\\', s1 + 1); + server = Runtime.Substring(path, 1, s1); + share = Runtime.Substring(path, s1 + 1, s2); + key = Runtime.Substring(path, 0, dr.PathConsumed).ToLower(); + int ki = key.Length; + while (ki > 1 && key[ki - 1] == '\\') + { + ki--; + } + if (ki < key.Length) + { + key = Runtime.Substring(key, 0, ki); + } + dr.PathConsumed -= 1 + server.Length + 1 + share.Length; + if (Referrals != null && (Runtime.CurrentTimeMillis() + 10000) > Referrals.Expiration) + { + Referrals = null; + } + if (Referrals == null) + { + Referrals = new CacheEntry(0); + } + Referrals.Map.Put(key, dr); + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/DfsReferral.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/DfsReferral.cs new file mode 100644 index 0000000000..3b6091f73c --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/DfsReferral.cs @@ -0,0 +1,67 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Collections.Generic; + +namespace SharpCifs.Smb +{ + + public class DfsReferral : SmbException + { + public int PathConsumed; + + public long Ttl; + + public string Server; + + public string Share; + + public string Link; + + public string Path; + + public bool ResolveHashes; + + public long Expiration; + + internal DfsReferral Next; + + internal IDictionary Map; + + internal string Key = null; + + public DfsReferral() + { + // Server + // Share + // Path relative to tree from which this referral was thrown + Next = this; + } + + internal virtual void Append(DfsReferral dr) + { + dr.Next = Next; + Next = dr; + } + + public override string ToString() + { + return "DfsReferral[pathConsumed=" + PathConsumed + ",server=" + Server + ",share=" + + Share + ",link=" + Link + ",path=" + Path + ",ttl=" + Ttl + ",expiration=" + + Expiration + ",resolveHashes=" + ResolveHashes + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/DosError.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/DosError.cs new file mode 100644 index 0000000000..d89e5bafac --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/DosError.cs @@ -0,0 +1,64 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + public static class DosError + { + public static int[][] DosErrorCodes = { new[] { unchecked(0x00000000), unchecked(0x00000000) }, new[] { unchecked(0x00010001), unchecked((int)(0xc0000002)) }, new[] { unchecked(0x00010002), unchecked( + (int)(0xc0000002)) }, new[] { unchecked(0x00020001), unchecked((int)( + 0xc000000f)) }, new[] { unchecked(0x00020002), unchecked((int)(0xc000006a + )) }, new[] { unchecked(0x00030001), unchecked((int)(0xc000003a)) }, + new[] { unchecked(0x00030002), unchecked((int)(0xc00000cb)) }, new[] { unchecked(0x00040002), unchecked((int)(0xc00000ca)) }, new[] { unchecked( + 0x00050001), unchecked((int)(0xc0000022)) }, new[] { unchecked(0x00050002), unchecked((int)(0xc000000d)) }, new[] { unchecked(0x00060001), unchecked((int)(0xc0000008)) }, new[] { unchecked(0x00060002), unchecked( + (int)(0xc00000cc)) }, new[] { unchecked(0x00080001), unchecked((int)( + 0xc000009a)) }, new[] { unchecked(0x00130003), unchecked((int)(0xc00000a2 + )) }, new[] { unchecked(0x00150003), unchecked((int)(0xc0000013)) }, + new[] { unchecked(0x001f0001), unchecked((int)(0xc0000001)) }, new[] { unchecked(0x001f0003), unchecked((int)(0xc0000001)) }, new[] { unchecked( + 0x00200001), unchecked((int)(0xc0000043)) }, new[] { unchecked(0x00200003), unchecked((int)(0xc0000043)) }, new[] { unchecked(0x00210003), unchecked((int)(0xc0000054)) }, new[] { unchecked(0x00270003), unchecked( + (int)(0xc000007f)) }, new[] { unchecked(0x00340001), unchecked((int)( + 0xC00000bd)) }, new[] { unchecked(0x00430001), unchecked((int)(0xc00000cc + )) }, new[] { unchecked(0x00470001), unchecked((int)(0xC00000d0)) }, + new[] { unchecked(0x00500001), unchecked((int)(0xc0000035)) }, new[] { unchecked(0x00570001), unchecked((int)(0xc0000003)) }, new[] { unchecked( + 0x005a0002), unchecked((int)(0xc00000ce)) }, new[] { unchecked(0x005b0002), unchecked((int)(0xc000000d)) }, new[] { unchecked(0x006d0001), unchecked((int)(0xC000014b)) }, new[] { unchecked(0x007b0001), unchecked( + (int)(0xc0000033)) }, new[] { unchecked(0x00910001), unchecked((int)( + 0xC0000101)) }, new[] { unchecked(0x00b70001), unchecked((int)(0xc0000035 + )) }, new[] { unchecked(0x00e70001), unchecked((int)(0xc00000ab)) }, + new[] { unchecked(0x00e80001), unchecked((int)(0xc00000b1)) }, new[] { unchecked(0x00e90001), unchecked((int)(0xc00000b0)) }, new[] { unchecked( + 0x00ea0001), unchecked((int)(0xc0000016)) }, new[] { unchecked(0x08bf0002), unchecked((int)(0xC0000193)) }, new[] { unchecked(0x08c00002), unchecked((int)(0xC0000070)) }, new[] { unchecked(0x08c10002), unchecked( + (int)(0xC000006f)) }, new[] { unchecked(0x08c20002), unchecked((int)( + 0xC0000071)) } }; + + public static string[] DosErrorMessages = { "The operation completed successfully." + , "Incorrect function.", "Incorrect function.", "The system cannot find the file specified." + , "Bad password.", "The system cannot find the path specified.", "reserved", "The client does not have the necessary access rights to perform the requested function." + , "Access is denied.", "The TID specified was invalid.", "The handle is invalid." + , "The network name cannot be found.", "Not enough storage is available to process this command." + , "The media is write protected.", "The device is not ready.", "A device attached to the system is not functioning." + , "A device attached to the system is not functioning.", "The process cannot access the file because it is being used by another process." + , "The process cannot access the file because it is being used by another process." + , "The process cannot access the file because another process has locked a portion of the file." + , "The disk is full.", "A duplicate name exists on the network.", "The network name cannot be found." + , "ERRnomoreconn.", "The file exists.", "The parameter is incorrect.", "Too many Uids active on this session." + , "The Uid is not known as a valid user identifier on this session.", "The pipe has been ended." + , "The filename, directory name, or volume label syntax is incorrect.", "The directory is not empty." + , "Cannot create a file when that file already exists.", "All pipe instances are busy." + , "The pipe is being closed.", "No process is on the other end of the pipe.", "More data is available." + , "This user account has expired.", "The user is not allowed to log on from this workstation." + , "The user is not allowed to log on at this time.", "The password of this user has expired." + }; + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/DosFileFilter.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/DosFileFilter.cs new file mode 100644 index 0000000000..bbf7882c8e --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/DosFileFilter.cs @@ -0,0 +1,37 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + public class DosFileFilter : ISmbFileFilter + { + protected internal string Wildcard; + + protected internal int Attributes; + + public DosFileFilter(string wildcard, int attributes) + { + this.Wildcard = wildcard; + this.Attributes = attributes; + } + + /// + public virtual bool Accept(SmbFile file) + { + return (file.GetAttributes() & Attributes) != 0; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/FileEntry.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/FileEntry.cs new file mode 100644 index 0000000000..bbf3e7cc41 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/FileEntry.cs @@ -0,0 +1,33 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + public interface IFileEntry + { + string GetName(); + + int GetType(); + + int GetAttributes(); + + long CreateTime(); + + long LastModified(); + + long Length(); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/IInfo.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/IInfo.cs new file mode 100644 index 0000000000..b0e40c5cdc --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/IInfo.cs @@ -0,0 +1,29 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal interface IInfo + { + int GetAttributes(); + + long GetCreateTime(); + + long GetLastWriteTime(); + + long GetSize(); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/NetServerEnum2.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/NetServerEnum2.cs new file mode 100644 index 0000000000..b4a02d8c36 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/NetServerEnum2.cs @@ -0,0 +1,122 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Sharpen; + +namespace SharpCifs.Smb +{ + internal class NetServerEnum2 : SmbComTransaction + { + internal const int SvTypeAll = unchecked((int)(0xFFFFFFFF)); + + internal const int SvTypeDomainEnum = unchecked((int)(0x80000000)); + + internal static readonly string[] Descr = { "WrLehDO\u0000B16BBDz\u0000" + , "WrLehDz\u0000B16BBDz\u0000" }; + + internal string Domain; + + internal string LastName; + + internal int ServerTypes; + + internal NetServerEnum2(string domain, int serverTypes) + { + this.Domain = domain; + this.ServerTypes = serverTypes; + Command = SmbComTransaction; + SubCommand = NetServerEnum2; + // not really true be used by upper logic + Name = "\\PIPE\\LANMAN"; + MaxParameterCount = 8; + MaxDataCount = 16384; + MaxSetupCount = unchecked(unchecked(0x00)); + SetupCount = 0; + Timeout = 5000; + } + + internal override void Reset(int key, string lastName) + { + base.Reset(); + this.LastName = lastName; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + byte[] descr; + int which = SubCommand == NetServerEnum2 ? 0 : 1; + try + { + descr = Runtime.GetBytesForString(Descr[which], "UTF-8"); //"ASCII"); + } + catch (UnsupportedEncodingException) + { + return 0; + } + WriteInt2(SubCommand & unchecked(0xFF), dst, dstIndex); + dstIndex += 2; + Array.Copy(descr, 0, dst, dstIndex, descr.Length); + dstIndex += descr.Length; + WriteInt2(unchecked(0x0001), dst, dstIndex); + dstIndex += 2; + WriteInt2(MaxDataCount, dst, dstIndex); + dstIndex += 2; + WriteInt4(ServerTypes, dst, dstIndex); + dstIndex += 4; + dstIndex += WriteString(Domain.ToUpper(), dst, dstIndex, false); + if (which == 1) + { + dstIndex += WriteString(LastName.ToUpper(), dst, dstIndex, false); + } + return dstIndex - start; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "NetServerEnum2[" + base.ToString() + ",name=" + Name + ",serverTypes=" + + (ServerTypes == SvTypeAll ? "SV_TYPE_ALL" : "SV_TYPE_DOMAIN_ENUM") + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/NetServerEnum2Response.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/NetServerEnum2Response.cs new file mode 100644 index 0000000000..9a0e5e3d57 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/NetServerEnum2Response.cs @@ -0,0 +1,157 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; + +namespace SharpCifs.Smb +{ + internal class NetServerEnum2Response : SmbComTransactionResponse + { + internal class ServerInfo1 : IFileEntry + { + internal string Name; + + internal int VersionMajor; + + internal int VersionMinor; + + internal int Type; + + internal string CommentOrMasterBrowser; + + public virtual string GetName() + { + return Name; + } + + public new virtual int GetType() + { + return (Type & unchecked((int)(0x80000000))) != 0 ? SmbFile.TypeWorkgroup : + SmbFile.TypeServer; + } + + public virtual int GetAttributes() + { + return SmbFile.AttrReadonly | SmbFile.AttrDirectory; + } + + public virtual long CreateTime() + { + return 0L; + } + + public virtual long LastModified() + { + return 0L; + } + + public virtual long Length() + { + return 0L; + } + + public override string ToString() + { + return "ServerInfo1[" + "name=" + Name + ",versionMajor=" + VersionMajor + ",versionMinor=" + VersionMinor + ",type=0x" + Hexdump.ToHexString + (Type, 8) + ",commentOrMasterBrowser=" + CommentOrMasterBrowser + "]"; + } + + internal ServerInfo1(NetServerEnum2Response enclosing) + { + this._enclosing = enclosing; + } + + private readonly NetServerEnum2Response _enclosing; + } + + private int _converter; + + private int _totalAvailableEntries; + + internal string LastName; + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + int start = bufferIndex; + Status = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + _converter = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + NumEntries = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + _totalAvailableEntries = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + return bufferIndex - start; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + int start = bufferIndex; + ServerInfo1 e = null; + Results = new ServerInfo1[NumEntries]; + for (int i = 0; i < NumEntries; i++) + { + Results[i] = e = new ServerInfo1(this); + e.Name = ReadString(buffer, bufferIndex, 16, false); + bufferIndex += 16; + e.VersionMajor = buffer[bufferIndex++] & unchecked(0xFF); + e.VersionMinor = buffer[bufferIndex++] & unchecked(0xFF); + e.Type = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + int off = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + off = (off & unchecked(0xFFFF)) - _converter; + off = start + off; + e.CommentOrMasterBrowser = ReadString(buffer, off, 48, false); + if (Log.Level >= 4) + { + Log.WriteLine(e); + } + } + LastName = NumEntries == 0 ? null : e.Name; + return bufferIndex - start; + } + + public override string ToString() + { + return "NetServerEnum2Response[" + base.ToString() + ",status=" + Status + + ",converter=" + _converter + ",entriesReturned=" + NumEntries + ",totalAvailableEntries=" + + _totalAvailableEntries + ",lastName=" + LastName + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/NetShareEnum.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/NetShareEnum.cs new file mode 100644 index 0000000000..1b0c6f9315 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/NetShareEnum.cs @@ -0,0 +1,95 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Sharpen; + +namespace SharpCifs.Smb +{ + internal class NetShareEnum : SmbComTransaction + { + private static readonly string Descr = "WrLeh\u0000B13BWz\u0000"; + + public NetShareEnum() + { + Command = SmbComTransaction; + SubCommand = NetShareEnum; + // not really true be used by upper logic + Name ="\\PIPE\\LANMAN"; + MaxParameterCount = 8; + // maxDataCount = 4096; why was this set? + MaxSetupCount = 0x00; + SetupCount = 0; + Timeout = 5000; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + byte[] descr; + try + { + //descr = Runtime.GetBytesForString(Descr, "ASCII"); + descr = Runtime.GetBytesForString(Descr, "UTF-8"); + } + catch (UnsupportedEncodingException) + { + return 0; + } + WriteInt2(NetShareEnum, dst, dstIndex); + dstIndex += 2; + Array.Copy(descr, 0, dst, dstIndex, descr.Length); + dstIndex += descr.Length; + WriteInt2(unchecked(0x0001), dst, dstIndex); + dstIndex += 2; + WriteInt2(MaxDataCount, dst, dstIndex); + dstIndex += 2; + return dstIndex - start; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "NetShareEnum[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/NetShareEnumResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/NetShareEnumResponse.cs new file mode 100644 index 0000000000..408f8e4d16 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/NetShareEnumResponse.cs @@ -0,0 +1,94 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class NetShareEnumResponse : SmbComTransactionResponse + { + private int _converter; + + private int _totalAvailableEntries; + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + int start = bufferIndex; + Status = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + _converter = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + NumEntries = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + _totalAvailableEntries = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + return bufferIndex - start; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + int start = bufferIndex; + SmbShareInfo e; + UseUnicode = false; + Results = new SmbShareInfo[NumEntries]; + for (int i = 0; i < NumEntries; i++) + { + Results[i] = e = new SmbShareInfo(); + e.NetName = ReadString(buffer, bufferIndex, 13, false); + bufferIndex += 14; + e.Type = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + int off = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + off = (off & unchecked(0xFFFF)) - _converter; + off = start + off; + e.Remark = ReadString(buffer, off, 128, false); + if (Log.Level >= 4) + { + Log.WriteLine(e); + } + } + return bufferIndex - start; + } + + public override string ToString() + { + return "NetShareEnumResponse[" + base.ToString() + ",status=" + Status + + ",converter=" + _converter + ",entriesReturned=" + NumEntries + ",totalAvailableEntries=" + + _totalAvailableEntries + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/NtStatus.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtStatus.cs new file mode 100644 index 0000000000..511e7ae84f --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtStatus.cs @@ -0,0 +1,202 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + public static class NtStatus + { + public const int NtStatusOk = unchecked(0x00000000); + + public const int NtStatusUnsuccessful = unchecked((int)(0xC0000001)); + + public const int NtStatusNotImplemented = unchecked((int)(0xC0000002)); + + public const int NtStatusInvalidInfoClass = unchecked((int)(0xC0000003)); + + public const int NtStatusAccessViolation = unchecked((int)(0xC0000005)); + + public const int NtStatusInvalidHandle = unchecked((int)(0xC0000008)); + + public const int NtStatusInvalidParameter = unchecked((int)(0xC000000d)); + + public const int NtStatusNoSuchDevice = unchecked((int)(0xC000000e)); + + public const int NtStatusNoSuchFile = unchecked((int)(0xC000000f)); + + public const int NtStatusMoreProcessingRequired = unchecked((int)(0xC0000016) + ); + + public const int NtStatusAccessDenied = unchecked((int)(0xC0000022)); + + public const int NtStatusBufferTooSmall = unchecked((int)(0xC0000023)); + + public const int NtStatusObjectNameInvalid = unchecked((int)(0xC0000033)); + + public const int NtStatusObjectNameNotFound = unchecked((int)(0xC0000034)); + + public const int NtStatusObjectNameCollision = unchecked((int)(0xC0000035)); + + public const int NtStatusPortDisconnected = unchecked((int)(0xC0000037)); + + public const int NtStatusObjectPathInvalid = unchecked((int)(0xC0000039)); + + public const int NtStatusObjectPathNotFound = unchecked((int)(0xC000003a)); + + public const int NtStatusObjectPathSyntaxBad = unchecked((int)(0xC000003b)); + + public const int NtStatusSharingViolation = unchecked((int)(0xC0000043)); + + public const int NtStatusDeletePending = unchecked((int)(0xC0000056)); + + public const int NtStatusNoLogonServers = unchecked((int)(0xC000005e)); + + public const int NtStatusUserExists = unchecked((int)(0xC0000063)); + + public const int NtStatusNoSuchUser = unchecked((int)(0xC0000064)); + + public const int NtStatusWrongPassword = unchecked((int)(0xC000006a)); + + public const int NtStatusLogonFailure = unchecked((int)(0xC000006d)); + + public const int NtStatusAccountRestriction = unchecked((int)(0xC000006e)); + + public const int NtStatusInvalidLogonHours = unchecked((int)(0xC000006f)); + + public const int NtStatusInvalidWorkstation = unchecked((int)(0xC0000070)); + + public const int NtStatusPasswordExpired = unchecked((int)(0xC0000071)); + + public const int NtStatusAccountDisabled = unchecked((int)(0xC0000072)); + + public const int NtStatusNoneMapped = unchecked((int)(0xC0000073)); + + public const int NtStatusInvalidSid = unchecked((int)(0xC0000078)); + + public const int NtStatusInstanceNotAvailable = unchecked((int)(0xC00000ab)); + + public const int NtStatusPipeNotAvailable = unchecked((int)(0xC00000ac)); + + public const int NtStatusInvalidPipeState = unchecked((int)(0xC00000ad)); + + public const int NtStatusPipeBusy = unchecked((int)(0xC00000ae)); + + public const int NtStatusPipeDisconnected = unchecked((int)(0xC00000b0)); + + public const int NtStatusPipeClosing = unchecked((int)(0xC00000b1)); + + public const int NtStatusPipeListening = unchecked((int)(0xC00000b3)); + + public const int NtStatusFileIsADirectory = unchecked((int)(0xC00000ba)); + + public const int NtStatusDuplicateName = unchecked((int)(0xC00000bd)); + + public const int NtStatusNetworkNameDeleted = unchecked((int)(0xC00000c9)); + + public const int NtStatusNetworkAccessDenied = unchecked((int)(0xC00000ca)); + + public const int NtStatusBadNetworkName = unchecked((int)(0xC00000cc)); + + public const int NtStatusRequestNotAccepted = unchecked((int)(0xC00000d0)); + + public const int NtStatusCantAccessDomainInfo = unchecked((int)(0xC00000da)); + + public const int NtStatusNoSuchDomain = unchecked((int)(0xC00000df)); + + public const int NtStatusNotADirectory = unchecked((int)(0xC0000103)); + + public const int NtStatusCannotDelete = unchecked((int)(0xC0000121)); + + public const int NtStatusInvalidComputerName = unchecked((int)(0xC0000122)); + + public const int NtStatusPipeBroken = unchecked((int)(0xC000014b)); + + public const int NtStatusNoSuchAlias = unchecked((int)(0xC0000151)); + + public const int NtStatusLogonTypeNotGranted = unchecked((int)(0xC000015b)); + + public const int NtStatusNoTrustSamAccount = unchecked((int)(0xC000018b)); + + public const int NtStatusTrustedDomainFailure = unchecked((int)(0xC000018c)); + + public const int NtStatusNologonWorkstationTrustAccount = unchecked((int)(0xC0000199 + )); + + public const int NtStatusPasswordMustChange = unchecked((int)(0xC0000224)); + + public const int NtStatusNotFound = unchecked((int)(0xC0000225)); + + public const int NtStatusAccountLockedOut = unchecked((int)(0xC0000234)); + + public const int NtStatusPathNotCovered = unchecked((int)(0xC0000257)); + + public const int NtStatusIoReparseTagNotHandled = unchecked((int)(0xC0000279 + )); + + public static int[] NtStatusCodes = { NtStatusOk, NtStatusUnsuccessful + , NtStatusNotImplemented, NtStatusInvalidInfoClass, NtStatusAccessViolation + , NtStatusInvalidHandle, NtStatusInvalidParameter, NtStatusNoSuchDevice + , NtStatusNoSuchFile, NtStatusMoreProcessingRequired, NtStatusAccessDenied + , NtStatusBufferTooSmall, NtStatusObjectNameInvalid, NtStatusObjectNameNotFound + , NtStatusObjectNameCollision, NtStatusPortDisconnected, NtStatusObjectPathInvalid + , NtStatusObjectPathNotFound, NtStatusObjectPathSyntaxBad, NtStatusSharingViolation + , NtStatusDeletePending, NtStatusNoLogonServers, NtStatusUserExists, NtStatusNoSuchUser + , NtStatusWrongPassword, NtStatusLogonFailure, NtStatusAccountRestriction + , NtStatusInvalidLogonHours, NtStatusInvalidWorkstation, NtStatusPasswordExpired + , NtStatusAccountDisabled, NtStatusNoneMapped, NtStatusInvalidSid, NtStatusInstanceNotAvailable + , NtStatusPipeNotAvailable, NtStatusInvalidPipeState, NtStatusPipeBusy + , NtStatusPipeDisconnected, NtStatusPipeClosing, NtStatusPipeListening, + NtStatusFileIsADirectory, NtStatusDuplicateName, NtStatusNetworkNameDeleted + , NtStatusNetworkAccessDenied, NtStatusBadNetworkName, NtStatusRequestNotAccepted + , NtStatusCantAccessDomainInfo, NtStatusNoSuchDomain, NtStatusNotADirectory + , NtStatusCannotDelete, NtStatusInvalidComputerName, NtStatusPipeBroken + , NtStatusNoSuchAlias, NtStatusLogonTypeNotGranted, NtStatusNoTrustSamAccount + , NtStatusTrustedDomainFailure, NtStatusNologonWorkstationTrustAccount, + NtStatusPasswordMustChange, NtStatusNotFound, NtStatusAccountLockedOut + , NtStatusPathNotCovered, NtStatusIoReparseTagNotHandled }; + + public static string[] NtStatusMessages = { "The operation completed successfully." + , "A device attached to the system is not functioning.", "Incorrect function.", + "The parameter is incorrect.", "Invalid access to memory location.", "The handle is invalid." + , "The parameter is incorrect.", "The system cannot find the file specified.", "The system cannot find the file specified." + , "More data is available.", "Access is denied.", "The data area passed to a system call is too small." + , "The filename, directory name, or volume label syntax is incorrect.", "The system cannot find the file specified." + , "Cannot create a file when that file already exists.", "The handle is invalid." + , "The specified path is invalid.", "The system cannot find the path specified." + , "The specified path is invalid.", "The process cannot access the file because it is being used by another process." + , "Access is denied.", "There are currently no logon servers available to service the logon request." + , "The specified user already exists.", "The specified user does not exist.", "The specified network password is not correct." + , "Logon failure: unknown user name or bad password.", "Logon failure: user account restriction." + , "Logon failure: account logon time restriction violation.", "Logon failure: user not allowed to log on to this computer." + , "Logon failure: the specified account password has expired.", "Logon failure: account currently disabled." + , "No mapping between account names and security IDs was done.", "The security ID structure is invalid." + , "All pipe instances are busy.", "All pipe instances are busy.", "The pipe state is invalid." + , "All pipe instances are busy.", "No process is on the other end of the pipe.", + "The pipe is being closed.", "Waiting for a process to open the other end of the pipe." + , "Access is denied.", "A duplicate name exists on the network.", "The specified network name is no longer available." + , "Network access is denied.", "The network name cannot be found.", "No more connections can be made to this remote computer at this time because there are already as many connections as the computer can accept." + , "Indicates a Windows NT Server could not be contacted or that objects within the domain are protected such that necessary information could not be retrieved." + , "The specified domain did not exist.", "The directory name is invalid.", "Access is denied." + , "The format of the specified computer name is invalid.", "The pipe has been ended." + , "The specified local group does not exist.", "Logon failure: the user has not been granted the requested logon type at this computer." + , "The SAM database on the Windows NT Server does not have a computer account for this workstation trust relationship." + , "The trust relationship between the primary domain and the trusted domain failed." + , "The account used is a Computer Account. Use your global user account or local user account to access this server." + , "The user must change his password before he logs on the first time.", "NT_STATUS_NOT_FOUND" + , "The referenced account is currently locked out and may not be logged on to.", + "The remote system is not reachable by the transport.", "NT_STATUS_IO_REPARSE_TAG_NOT_HANDLED" + }; + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/NtTransQuerySecurityDesc.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtTransQuerySecurityDesc.cs new file mode 100644 index 0000000000..6a83543b16 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtTransQuerySecurityDesc.cs @@ -0,0 +1,88 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; + +namespace SharpCifs.Smb +{ + internal class NtTransQuerySecurityDesc : SmbComNtTransaction + { + internal int Fid; + + internal int SecurityInformation; + + internal NtTransQuerySecurityDesc(int fid, int securityInformation) + { + this.Fid = fid; + this.SecurityInformation = securityInformation; + Command = SmbComNtTransact; + Function = NtTransactQuerySecurityDesc; + SetupCount = 0; + TotalDataCount = 0; + MaxParameterCount = 4; + MaxDataCount = 32768; + MaxSetupCount = unchecked(unchecked(0x00)); + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(Fid, dst, dstIndex); + dstIndex += 2; + dst[dstIndex++] = unchecked(unchecked(0x00)); + // Reserved + dst[dstIndex++] = unchecked(unchecked(0x00)); + // Reserved + WriteInt4(SecurityInformation, dst, dstIndex); + dstIndex += 4; + return dstIndex - start; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "NtTransQuerySecurityDesc[" + base.ToString() + ",fid=0x" + Hexdump + .ToHexString(Fid, 4) + ",securityInformation=0x" + Hexdump.ToHexString(SecurityInformation + , 8) + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/NtTransQuerySecurityDescResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtTransQuerySecurityDescResponse.cs new file mode 100644 index 0000000000..9365d51542 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtTransQuerySecurityDescResponse.cs @@ -0,0 +1,78 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.IO; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal class NtTransQuerySecurityDescResponse : SmbComNtTransactionResponse + { + internal SecurityDescriptor SecurityDescriptor; + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + Length = ReadInt4(buffer, bufferIndex); + return 4; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + int start = bufferIndex; + if (ErrorCode != 0) + { + return 4; + } + try + { + SecurityDescriptor = new SecurityDescriptor(); + bufferIndex += SecurityDescriptor.Decode(buffer, bufferIndex, len); + } + catch (IOException ioe) + { + throw new RuntimeException(ioe.Message); + } + return bufferIndex - start; + } + + public override string ToString() + { + return "NtTransQuerySecurityResponse[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/NtlmAuthenticator.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtlmAuthenticator.cs new file mode 100644 index 0000000000..853364f8ef --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtlmAuthenticator.cs @@ -0,0 +1,93 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + /// This class can be extended by applications that wish to trap authentication related exceptions and automatically retry the exceptional operation with different credentials. + /// + /// This class can be extended by applications that wish to trap authentication related exceptions and automatically retry the exceptional operation with different credentials. Read jCIFS Exceptions and NtlmAuthenticator for complete details. + /// + public abstract class NtlmAuthenticator + { + private static NtlmAuthenticator _auth; + + private string _url; + + private SmbAuthException _sae; + + private void Reset() + { + _url = null; + _sae = null; + } + + /// Set the default NtlmAuthenticator. + /// Set the default NtlmAuthenticator. Once the default authenticator is set it cannot be changed. Calling this metho again will have no effect. + /// + public static void SetDefault(NtlmAuthenticator a) + { + lock (typeof(NtlmAuthenticator)) + { + if (_auth != null) + { + return; + } + _auth = a; + } + } + + protected internal string GetRequestingUrl() + { + return _url; + } + + protected internal SmbAuthException GetRequestingException() + { + return _sae; + } + + /// Used internally by jCIFS when an SmbAuthException is trapped to retrieve new user credentials. + /// + /// Used internally by jCIFS when an SmbAuthException is trapped to retrieve new user credentials. + /// + public static NtlmPasswordAuthentication RequestNtlmPasswordAuthentication(string + url, SmbAuthException sae) + { + if (_auth == null) + { + return null; + } + lock (_auth) + { + _auth._url = url; + _auth._sae = sae; + return _auth.GetNtlmPasswordAuthentication(); + } + } + + /// An application extending this class must provide an implementation for this method that returns new user credentials try try when accessing SMB resources described by the getRequestingURL and getRequestingException methods. + /// + /// + /// An application extending this class must provide an implementation for this method that returns new user credentials try try when accessing SMB resources described by the getRequestingURL and getRequestingException methods. + /// If this method returns null the SmbAuthException that triggered the authenticator check will simply be rethrown. The default implementation returns null. + /// + protected internal virtual NtlmPasswordAuthentication GetNtlmPasswordAuthentication + () + { + return null; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/NtlmChallenge.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtlmChallenge.cs new file mode 100644 index 0000000000..745b1f6639 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtlmChallenge.cs @@ -0,0 +1,40 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; + +namespace SharpCifs.Smb +{ + + public sealed class NtlmChallenge + { + public byte[] Challenge; + + public UniAddress Dc; + + internal NtlmChallenge(byte[] challenge, UniAddress dc) + { + this.Challenge = challenge; + this.Dc = dc; + } + + public override string ToString() + { + return "NtlmChallenge[challenge=0x" + Hexdump.ToHexString(Challenge, 0, Challenge + .Length * 2) + ",dc=" + Dc + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/NtlmContext.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtlmContext.cs new file mode 100644 index 0000000000..44266f9740 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtlmContext.cs @@ -0,0 +1,206 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Ntlmssp; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + /// For initiating NTLM authentication (including NTLMv2). + /// For initiating NTLM authentication (including NTLMv2). If you want to add NTLMv2 authentication support to something this is what you want to use. See the code for details. Note that JCIFS does not implement the acceptor side of NTLM authentication. + /// + public class NtlmContext + { + internal NtlmPasswordAuthentication Auth; + + internal int NtlmsspFlags; + + internal string Workstation; + + internal bool isEstablished; + + internal byte[] ServerChallenge; + + internal byte[] SigningKey; + + internal string NetbiosName = null; + + internal int State = 1; + + internal LogStream Log; + + public NtlmContext(NtlmPasswordAuthentication auth, bool doSigning) + { + this.Auth = auth; + NtlmsspFlags = NtlmsspFlags | NtlmFlags.NtlmsspRequestTarget | NtlmFlags.NtlmsspNegotiateNtlm2 + | NtlmFlags.NtlmsspNegotiate128; + if (doSigning) + { + NtlmsspFlags |= NtlmFlags.NtlmsspNegotiateSign | NtlmFlags.NtlmsspNegotiateAlwaysSign + | NtlmFlags.NtlmsspNegotiateKeyExch; + } + Workstation = Type1Message.GetDefaultWorkstation(); + Log = LogStream.GetInstance(); + } + + public override string ToString() + { + string ret = "NtlmContext[auth=" + Auth + ",ntlmsspFlags=0x" + Hexdump.ToHexString + (NtlmsspFlags, 8) + ",workstation=" + Workstation + ",isEstablished=" + isEstablished + + ",state=" + State + ",serverChallenge="; + if (ServerChallenge == null) + { + ret += "null"; + } + else + { + ret += Hexdump.ToHexString(ServerChallenge, 0, ServerChallenge.Length * 2); + } + ret += ",signingKey="; + if (SigningKey == null) + { + ret += "null"; + } + else + { + ret += Hexdump.ToHexString(SigningKey, 0, SigningKey.Length * 2); + } + ret += "]"; + return ret; + } + + public virtual bool IsEstablished() + { + return isEstablished; + } + + public virtual byte[] GetServerChallenge() + { + return ServerChallenge; + } + + public virtual byte[] GetSigningKey() + { + return SigningKey; + } + + public virtual string GetNetbiosName() + { + return NetbiosName; + } + + private string GetNtlmsspListItem(byte[] type2Token, int id0) + { + int ri = 58; + for (; ; ) + { + int id = Encdec.Dec_uint16le(type2Token, ri); + int len = Encdec.Dec_uint16le(type2Token, ri + 2); + ri += 4; + if (id == 0 || (ri + len) > type2Token.Length) + { + break; + } + if (id == id0) + { + try + { + return Runtime.GetStringForBytes(type2Token, ri, len, SmbConstants.UniEncoding + ); + } + catch (UnsupportedEncodingException) + { + break; + } + } + ri += len; + } + return null; + } + + /// + public virtual byte[] InitSecContext(byte[] token, int offset, int len) + { + switch (State) + { + case 1: + { + Type1Message msg1 = new Type1Message(NtlmsspFlags, Auth.GetDomain(), Workstation); + token = msg1.ToByteArray(); + if (Log.Level >= 4) + { + Log.WriteLine(msg1); + if (Log.Level >= 6) + { + Hexdump.ToHexdump(Log, token, 0, token.Length); + } + } + State++; + break; + } + + case 2: + { + try + { + Type2Message msg2 = new Type2Message(token); + if (Log.Level >= 4) + { + Log.WriteLine(msg2); + if (Log.Level >= 6) + { + Hexdump.ToHexdump(Log, token, 0, token.Length); + } + } + ServerChallenge = msg2.GetChallenge(); + NtlmsspFlags &= msg2.GetFlags(); + // netbiosName = getNtlmsspListItem(token, 0x0001); + Type3Message msg3 = new Type3Message(msg2, Auth.GetPassword(), Auth.GetDomain(), + Auth.GetUsername(), Workstation, NtlmsspFlags); + token = msg3.ToByteArray(); + if (Log.Level >= 4) + { + Log.WriteLine(msg3); + if (Log.Level >= 6) + { + Hexdump.ToHexdump(Log, token, 0, token.Length); + } + } + if ((NtlmsspFlags & NtlmFlags.NtlmsspNegotiateSign) != 0) + { + SigningKey = msg3.GetMasterKey(); + } + isEstablished = true; + State++; + break; + } + catch (Exception e) + { + throw new SmbException(e.Message, e); + } + } + + default: + { + throw new SmbException("Invalid state"); + } + } + return token; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/NtlmPasswordAuthentication.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtlmPasswordAuthentication.cs new file mode 100644 index 0000000000..ec3899fe9b --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/NtlmPasswordAuthentication.cs @@ -0,0 +1,807 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +{ + /// This class stores and encrypts NTLM user credentials. + /// + /// This class stores and encrypts NTLM user credentials. The default + /// credentials are retrieved from the jcifs.smb.client.domain, + /// jcifs.smb.client.username, and jcifs.smb.client.password + /// properties. + ///

+ /// Read jCIFS Exceptions and + /// NtlmAuthenticator for related information. + /// + + 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); + } + + ///

Generate the ANSI DES hash for the password associated with these credentials. + /// + /// Generate the ANSI DES hash for the password associated with these credentials. + /// + 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; + } + + /// Generate the Unicode MD4 hash for the password associated with these credentials. + /// + /// Generate the Unicode MD4 hash for the password associated with these credentials. + /// + 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; + } + + /// Creates the LMv2 response for the supplied information. + /// Creates the LMv2 response for the supplied information. + /// The domain in which the username exists. + /// The username. + /// The user's password. + /// The server challenge. + /// The client challenge (nonce). + 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; + + /// + /// Create an NtlmPasswordAuthentication object from the userinfo + /// component of an SMB URL like "domain;user:pass". + /// + /// + /// Create an NtlmPasswordAuthentication object from the userinfo + /// component of an SMB URL like "domain;user:pass". This constructor + /// is used internally be jCIFS when parsing SMB URLs. + /// + 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; + } + } + + /// + /// Create an NtlmPasswordAuthentication object from a + /// domain, username, and password. + /// + /// + /// Create an NtlmPasswordAuthentication object from a + /// domain, username, and password. Parameters that are null + /// will be substituted with jcifs.smb.client.domain, + /// jcifs.smb.client.username, jcifs.smb.client.password + /// property values. + /// + 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; + } + } + + /// + /// Create an NtlmPasswordAuthentication object with raw password + /// hashes. + /// + /// + /// Create an NtlmPasswordAuthentication object with raw password + /// hashes. This is used exclusively by the jcifs.http.NtlmSsp + /// class which is in turn used by NTLM HTTP authentication functionality. + /// + 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; + } + + /// Returns the domain. + /// Returns the domain. + public string GetDomain() + { + return Domain; + } + + /// Returns the username. + /// Returns the username. + public string GetUsername() + { + return Username; + } + + /// + /// Returns the password in plain text or null if the raw password + /// hashes were used to construct this NtlmPasswordAuthentication + /// object which will be the case when NTLM HTTP Authentication is + /// used. + /// + /// + /// Returns the password in plain text or null if the raw password + /// hashes were used to construct this NtlmPasswordAuthentication + /// 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. + /// + public string GetPassword() + { + return Password; + } + + /// + /// Return the domain and username in the format: + /// domain\\username. + /// + /// + /// Return the domain and username in the format: + /// domain\\username. This is equivalent to toString(). + /// + public new string GetName() + { + bool d = Domain.Length > 0 && Domain.Equals("?") == false; + return d ? Domain + "\\" + Username : Username; + } + + /// Computes the 24 byte ANSI password hash given the 8 byte server challenge. + /// + /// Computes the 24 byte ANSI password hash given the 8 byte server challenge. + /// + 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); + } + } + } + + /// Computes the 24 byte Unicode password hash given the 8 byte server challenge. + /// + /// Computes the 24 byte Unicode password hash given the 8 byte server challenge. + /// + 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); + } + } + } + + /// + 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; + } + + /// Returns the effective user session key. + /// Returns the effective user session key. + /// The server challenge. + /// + /// A byte[] containing the effective user session key, + /// used in SMB MAC signing and NTLMSSP signing and sealing. + /// + 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; + } + + /// Calculates the effective user session key. + /// Calculates the effective user session key. + /// The server challenge. + /// + /// The destination array in which the user session key will be + /// placed. + /// + /// + /// The offset in the destination array at which the + /// session key will start. + /// + /// + 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); + } + } + + /// + /// Compares two NtlmPasswordAuthentication objects for + /// equality. + /// + /// + /// Compares two NtlmPasswordAuthentication objects for + /// equality. Two NtlmPasswordAuthentication 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 NtlmPasswordAuthentication 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. + /// + 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; + } + + /// Return the upcased username hash code. + /// Return the upcased username hash code. + public override int GetHashCode() + { + return GetName().ToUpper().GetHashCode(); + } + + /// + /// Return the domain and username in the format: + /// domain\\username. + /// + /// + /// Return the domain and username in the format: + /// domain\\username. This is equivalent to getName(). + /// + public override string ToString() + { + return GetName(); + } + + /// + /// + 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); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Principal.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Principal.cs new file mode 100644 index 0000000000..14a5479e31 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Principal.cs @@ -0,0 +1,28 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + public class Principal + { + private string _name = ""; + + public string GetName() + { + return _name; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SID.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SID.cs new file mode 100644 index 0000000000..a6ad59fb1a --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SID.cs @@ -0,0 +1,900 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.Collections; +using System.Collections.Generic; +using System.IO; +using SharpCifs.Dcerpc; +using SharpCifs.Dcerpc.Msrpc; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; +using Hashtable = SharpCifs.Util.Sharpen.Hashtable; //not System.Collections.Hashtable + +namespace SharpCifs.Smb +{ + /// + /// A Windows SID is a numeric identifier used to represent Windows + /// accounts. + /// + /// + /// A Windows SID is a numeric identifier used to represent Windows + /// accounts. SIDs are commonly represented using a textual format such as + /// S-1-5-21-1496946806-2192648263-3843101252-1029 but they may + /// also be resolved to yield the name of the associated Windows account + /// such as Administrators or MYDOM\alice. + ///

+ /// Consider the following output of examples/SidLookup.java: + ///

+	/// toString: S-1-5-21-4133388617-793952518-2001621813-512
+	/// toDisplayString: WNET\Domain Admins
+	/// getType: 2
+	/// getTypeText: Domain group
+	/// getDomainName: WNET
+	/// getAccountName: Domain Admins
+	/// 
+ ///
+ public class Sid : Rpc.SidT + { + public const int SidTypeUseNone = Lsarpc.SidNameUseNone; + + public const int SidTypeUser = Lsarpc.SidNameUser; + + public const int SidTypeDomGrp = Lsarpc.SidNameDomGrp; + + public const int SidTypeDomain = Lsarpc.SidNameDomain; + + public const int SidTypeAlias = Lsarpc.SidNameAlias; + + public const int SidTypeWknGrp = Lsarpc.SidNameWknGrp; + + public const int SidTypeDeleted = Lsarpc.SidNameDeleted; + + public const int SidTypeInvalid = Lsarpc.SidNameInvalid; + + public const int SidTypeUnknown = Lsarpc.SidNameUnknown; + + internal static readonly string[] SidTypeNames = { "0", "User", "Domain group" + , "Domain", "Local group", "Builtin group", "Deleted", "Invalid", "Unknown" }; + + public const int SidFlagResolveSids = unchecked(0x0001); + + public static Sid Everyone; + + public static Sid CreatorOwner; + + public static Sid SYSTEM; + + static Sid() + { + try + { + Everyone = new Sid("S-1-1-0"); + CreatorOwner = new Sid("S-1-3-0"); + SYSTEM = new Sid("S-1-5-18"); + } + catch (SmbException) + { + } + } + + internal static Hashtable SidCache = new Hashtable(); + + /// + internal static void ResolveSids(DcerpcHandle handle, LsaPolicyHandle policyHandle + , Sid[] sids) + { + MsrpcLookupSids rpc = new MsrpcLookupSids(policyHandle, sids); + handle.Sendrecv(rpc); + switch (rpc.Retval) + { + case 0: + case NtStatus.NtStatusNoneMapped: + case unchecked(0x00000107): + { + // NT_STATUS_SOME_NOT_MAPPED + break; + } + + default: + { + throw new SmbException(rpc.Retval, false); + } + } + for (int si = 0; si < sids.Length; si++) + { + sids[si].Type = rpc.Names.Names[si].SidType; + sids[si].DomainName = null; + switch (sids[si].Type) + { + case SidTypeUser: + case SidTypeDomGrp: + case SidTypeDomain: + case SidTypeAlias: + case SidTypeWknGrp: + { + int sidIndex = rpc.Names.Names[si].SidIndex; + Rpc.Unicode_string ustr = rpc.Domains.Domains[sidIndex].Name; + sids[si].DomainName = (new UnicodeString(ustr, false)).ToString(); + break; + } + } + sids[si].AcctName = (new UnicodeString(rpc.Names.Names[si].Name, false)).ToString + (); + sids[si].OriginServer = null; + sids[si].OriginAuth = null; + } + } + + /// + internal static void ResolveSids0(string authorityServerName, NtlmPasswordAuthentication + auth, Sid[] sids) + { + DcerpcHandle handle = null; + LsaPolicyHandle policyHandle = null; + lock (SidCache) + { + try + { + handle = DcerpcHandle.GetHandle("ncacn_np:" + authorityServerName + "[\\PIPE\\lsarpc]" + , auth); + string server = authorityServerName; + int dot = server.IndexOf('.'); + if (dot > 0 && char.IsDigit(server[0]) == false) + { + server = Runtime.Substring(server, 0, dot); + } + policyHandle = new LsaPolicyHandle(handle, "\\\\" + server, unchecked(0x00000800)); + ResolveSids(handle, policyHandle, sids); + } + finally + { + if (handle != null) + { + if (policyHandle != null) + { + policyHandle.Close(); + } + handle.Close(); + } + } + } + } + + /// + public static void ResolveSids(string authorityServerName, NtlmPasswordAuthentication + auth, Sid[] sids, int offset, int length) + { + List list = new List();//new List(sids.Length); + int si; + lock (SidCache) + { + for (si = 0; si < length; si++) + { + Sid sid = (Sid)SidCache.Get(sids[offset + si]); + if (sid != null) + { + sids[offset + si].Type = sid.Type; + sids[offset + si].DomainName = sid.DomainName; + sids[offset + si].AcctName = sid.AcctName; + } + else + { + list.Add(sids[offset + si]); + } + } + if (list.Count > 0) + { + //sids = (Jcifs.Smb.SID[])Sharpen.Collections.ToArray(list, new Jcifs.Smb.SID[0]); + sids = (Sid[])list.ToArray(); + ResolveSids0(authorityServerName, auth, sids); + for (si = 0; si < sids.Length; si++) + { + SidCache.Put(sids[si], sids[si]); + } + } + } + } + + /// Resolve an array of SIDs using a cache and at most one MSRPC request. + /// + /// Resolve an array of SIDs using a cache and at most one MSRPC request. + ///

+ /// This method will attempt + /// to resolve SIDs using a cache and cache the results of any SIDs that + /// required resolving with the authority. SID cache entries are currently not + /// expired because under normal circumstances SID information never changes. + /// + /// The hostname of the server that should be queried. For maximum efficiency this should be the hostname of a domain controller however a member server will work as well and a domain controller may not return names for SIDs corresponding to local accounts for which the domain controller is not an authority. + /// + /// The credentials that should be used to communicate with the named server. As usual, null indicates that default credentials should be used. + /// + /// The SIDs that should be resolved. After this function is called, the names associated with the SIDs may be queried with the toDisplayString, getDomainName, and getAccountName methods. + /// + /// + public static void ResolveSids(string authorityServerName, NtlmPasswordAuthentication + auth, Sid[] sids) + { + List list = new List();//new List(sids.Length); + int si; + lock (SidCache) + { + for (si = 0; si < sids.Length; si++) + { + Sid sid = (Sid)SidCache.Get(sids[si]); + if (sid != null) + { + sids[si].Type = sid.Type; + sids[si].DomainName = sid.DomainName; + sids[si].AcctName = sid.AcctName; + } + else + { + list.Add(sids[si]); + } + } + if (list.Count > 0) + { + //sids = (Jcifs.Smb.SID[])Sharpen.Collections.ToArray(list, new Jcifs.Smb.SID[0]); + sids = (Sid[]) list.ToArray(); + ResolveSids0(authorityServerName, auth, sids); + for (si = 0; si < sids.Length; si++) + { + SidCache.Put(sids[si], sids[si]); + } + } + } + } + + /// + public static Sid GetServerSid(string server, NtlmPasswordAuthentication + auth) + { + DcerpcHandle handle = null; + LsaPolicyHandle policyHandle = null; + Lsarpc.LsarDomainInfo info = new Lsarpc.LsarDomainInfo(); + MsrpcQueryInformationPolicy rpc; + lock (SidCache) + { + try + { + handle = DcerpcHandle.GetHandle("ncacn_np:" + server + "[\\PIPE\\lsarpc]", auth); + // NetApp doesn't like the 'generic' access mask values + policyHandle = new LsaPolicyHandle(handle, null, unchecked(0x00000001)); + rpc = new MsrpcQueryInformationPolicy(policyHandle, Lsarpc.PolicyInfoAccountDomain + , info); + handle.Sendrecv(rpc); + if (rpc.Retval != 0) + { + throw new SmbException(rpc.Retval, false); + } + return new Sid(info.Sid, SidTypeDomain, (new UnicodeString + (info.Name, false)).ToString(), null, false); + } + finally + { + if (handle != null) + { + if (policyHandle != null) + { + policyHandle.Close(); + } + handle.Close(); + } + } + } + } + + public static byte[] ToByteArray(Rpc.SidT sid) + { + byte[] dst = new byte[1 + 1 + 6 + sid.SubAuthorityCount * 4]; + int di = 0; + dst[di++] = sid.Revision; + dst[di++] = sid.SubAuthorityCount; + Array.Copy(sid.IdentifierAuthority, 0, dst, di, 6); + di += 6; + for (int ii = 0; ii < sid.SubAuthorityCount; ii++) + { + Encdec.Enc_uint32le(sid.SubAuthority[ii], dst, di); + di += 4; + } + return dst; + } + + internal int Type; + + internal string DomainName; + + internal string AcctName; + + internal string OriginServer; + + internal NtlmPasswordAuthentication OriginAuth; + + public Sid(byte[] src, int si) + { + Revision = src[si++]; + SubAuthorityCount = src[si++]; + IdentifierAuthority = new byte[6]; + Array.Copy(src, si, IdentifierAuthority, 0, 6); + si += 6; + if (SubAuthorityCount > 100) + { + throw new RuntimeException("Invalid SID sub_authority_count"); + } + SubAuthority = new int[SubAuthorityCount]; + for (int i = 0; i < SubAuthorityCount; i++) + { + SubAuthority[i] = ServerMessageBlock.ReadInt4(src, si); + si += 4; + } + } + + /// + /// Construct a SID from it's textual representation such as + /// S-1-5-21-1496946806-2192648263-3843101252-1029. + /// + /// + /// Construct a SID from it's textual representation such as + /// S-1-5-21-1496946806-2192648263-3843101252-1029. + /// + /// + public Sid(string textual) + { + StringTokenizer st = new StringTokenizer(textual, "-"); + if (st.CountTokens() < 3 || !st.NextToken().Equals("S")) + { + // need S-N-M + throw new SmbException("Bad textual SID format: " + textual); + } + Revision = byte.Parse(st.NextToken()); + string tmp = st.NextToken(); + long id = 0; + if (tmp.StartsWith("0x")) + { + //id = long.Parse(Sharpen.Runtime.Substring(tmp, 2), 16); + id = long.Parse(Runtime.Substring(tmp, 2)); + } + else + { + id = long.Parse(tmp); + } + IdentifierAuthority = new byte[6]; + for (int i = 5; id > 0; i--) + { + IdentifierAuthority[i] = unchecked((byte)(id % 256)); + id >>= 8; + } + SubAuthorityCount = unchecked((byte)st.CountTokens()); + if (SubAuthorityCount > 0) + { + SubAuthority = new int[SubAuthorityCount]; + for (int i1 = 0; i1 < SubAuthorityCount; i1++) + { + SubAuthority[i1] = (int)(long.Parse(st.NextToken()) & unchecked(0xFFFFFFFFL)); + } + } + } + + /// + /// Construct a SID from a domain SID and an RID + /// (relative identifier). + /// + /// + /// Construct a SID from a domain SID and an RID + /// (relative identifier). For example, a domain SID + /// S-1-5-21-1496946806-2192648263-3843101252 and RID 1029 would + /// yield the SID S-1-5-21-1496946806-2192648263-3843101252-1029. + /// + public Sid(Sid domsid, int rid) + { + Revision = domsid.Revision; + IdentifierAuthority = domsid.IdentifierAuthority; + SubAuthorityCount = unchecked((byte)(domsid.SubAuthorityCount + 1)); + SubAuthority = new int[SubAuthorityCount]; + int i; + for (i = 0; i < domsid.SubAuthorityCount; i++) + { + SubAuthority[i] = domsid.SubAuthority[i]; + } + SubAuthority[i] = rid; + } + + public Sid(Rpc.SidT sid, int type, string domainName, string acctName, bool decrementAuthority + ) + { + Revision = sid.Revision; + SubAuthorityCount = sid.SubAuthorityCount; + IdentifierAuthority = sid.IdentifierAuthority; + SubAuthority = sid.SubAuthority; + this.Type = type; + this.DomainName = domainName; + this.AcctName = acctName; + if (decrementAuthority) + { + SubAuthorityCount--; + SubAuthority = new int[SubAuthorityCount]; + for (int i = 0; i < SubAuthorityCount; i++) + { + SubAuthority[i] = sid.SubAuthority[i]; + } + } + } + + public virtual Sid GetDomainSid() + { + return new Sid(this, SidTypeDomain, DomainName, null, GetType() + != SidTypeDomain); + } + + public virtual int GetRid() + { + if (GetType() == SidTypeDomain) + { + throw new ArgumentException("This SID is a domain sid"); + } + return SubAuthority[SubAuthorityCount - 1]; + } + + /// Returns the type of this SID indicating the state or type of account. + /// + /// Returns the type of this SID indicating the state or type of account. + ///

+ /// SID types are described in the following table. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
TypeName
SID_TYPE_USE_NONE0
SID_TYPE_USERUser
SID_TYPE_DOM_GRPDomain group
SID_TYPE_DOMAINDomain
SID_TYPE_ALIASLocal group
SID_TYPE_WKN_GRPBuiltin group
SID_TYPE_DELETEDDeleted
SID_TYPE_INVALIDInvalid
SID_TYPE_UNKNOWNUnknown
+ ///
+ /// + public virtual int GetType() + { + if (OriginServer != null) + { + ResolveWeak(); + } + return Type; + } + + ///

+ /// Return text represeting the SID type suitable for display to + /// users. + /// + /// + /// Return text represeting the SID type suitable for display to + /// users. Text includes 'User', 'Domain group', 'Local group', etc. + /// + public virtual string GetTypeText() + { + if (OriginServer != null) + { + ResolveWeak(); + } + return SidTypeNames[Type]; + } + + /// + /// Return the domain name of this SID unless it could not be + /// resolved in which case the numeric representation is returned. + /// + /// + /// Return the domain name of this SID unless it could not be + /// resolved in which case the numeric representation is returned. + /// + public virtual string GetDomainName() + { + if (OriginServer != null) + { + ResolveWeak(); + } + if (Type == SidTypeUnknown) + { + string full = ToString(); + return Runtime.Substring(full, 0, full.Length - GetAccountName().Length - + 1); + } + return DomainName; + } + + /// + /// Return the sAMAccountName of this SID unless it could not + /// be resolved in which case the numeric RID is returned. + /// + /// + /// Return the sAMAccountName of this SID unless it could not + /// be resolved in which case the numeric RID is returned. If this + /// SID is a domain SID, this method will return an empty String. + /// + public virtual string GetAccountName() + { + if (OriginServer != null) + { + ResolveWeak(); + } + if (Type == SidTypeUnknown) + { + return string.Empty + SubAuthority[SubAuthorityCount - 1]; + } + if (Type == SidTypeDomain) + { + return string.Empty; + } + return AcctName; + } + + public override int GetHashCode() + { + int hcode = IdentifierAuthority[5]; + for (int i = 0; i < SubAuthorityCount; i++) + { + hcode += 65599 * SubAuthority[i]; + } + return hcode; + } + + public override bool Equals(object obj) + { + if (obj is Sid) + { + Sid sid = (Sid)obj; + if (sid == this) + { + return true; + } + if (sid.SubAuthorityCount == SubAuthorityCount) + { + int i = SubAuthorityCount; + while (i-- > 0) + { + if (sid.SubAuthority[i] != SubAuthority[i]) + { + return false; + } + } + for (i = 0; i < 6; i++) + { + if (sid.IdentifierAuthority[i] != IdentifierAuthority[i]) + { + return false; + } + } + return sid.Revision == Revision; + } + } + return false; + } + + /// + /// Return the numeric representation of this sid such as + /// S-1-5-21-1496946806-2192648263-3843101252-1029. + /// + /// + /// Return the numeric representation of this sid such as + /// S-1-5-21-1496946806-2192648263-3843101252-1029. + /// + public override string ToString() + { + string ret = "S-" + (Revision & unchecked(0xFF)) + "-"; + if (IdentifierAuthority[0] != unchecked(0) || IdentifierAuthority[1] != unchecked( + 0)) + { + ret += "0x"; + ret += Hexdump.ToHexString(IdentifierAuthority, 0, 6); + } + else + { + int shift = 0; + long id = 0; + for (int i = 5; i > 1; i--) + { + id += (IdentifierAuthority[i] & unchecked(0xFFL)) << shift; + shift += 8; + } + ret += id; + } + for (int i1 = 0; i1 < SubAuthorityCount; i1++) + { + ret += "-" + (SubAuthority[i1] & unchecked(0xFFFFFFFFL)); + } + return ret; + } + + /// + /// Return a String representing this SID ideal for display to + /// users. + /// + /// + /// Return a String representing this SID ideal for display to + /// users. This method should return the same text that the ACL + /// editor in Windows would display. + ///

+ /// Specifically, if the SID has + /// been resolved and it is not a domain SID or builtin account, + /// the full DOMAIN\name form of the account will be + /// returned (e.g. MYDOM\alice or MYDOM\Domain Users). + /// If the SID has been resolved but it is is a domain SID, + /// only the domain name will be returned (e.g. MYDOM). + /// If the SID has been resolved but it is a builtin account, + /// only the name component will be returned (e.g. SYSTEM). + /// If the sid cannot be resolved the numeric representation from + /// toString() is returned. + /// + public virtual string ToDisplayString() + { + if (OriginServer != null) + { + ResolveWeak(); + } + if (DomainName != null) + { + string str; + if (Type == SidTypeDomain) + { + str = DomainName; + } + else + { + if (Type == SidTypeWknGrp || DomainName.Equals("BUILTIN")) + { + if (Type == SidTypeUnknown) + { + str = ToString(); + } + else + { + str = AcctName; + } + } + else + { + str = DomainName + "\\" + AcctName; + } + } + return str; + } + return ToString(); + } + + ///

Manually resolve this SID. + /// + /// Manually resolve this SID. Normally SIDs are automatically + /// resolved. However, if a SID is constructed explicitly using a SID + /// constructor, JCIFS will have no knowledge of the server that created the + /// SID and therefore cannot possibly resolve it automatically. In this case, + /// this method will be necessary. + /// + /// The FQDN of the server that is an authority for the SID. + /// + /// Credentials suitable for accessing the SID's information. + /// + public virtual void Resolve(string authorityServerName, NtlmPasswordAuthentication + auth) + { + Sid[] sids = new Sid[1]; + sids[0] = this; + ResolveSids(authorityServerName, auth, sids); + } + + internal virtual void ResolveWeak() + { + if (OriginServer != null) + { + try + { + Resolve(OriginServer, OriginAuth); + } + catch (IOException) + { + } + finally + { + OriginServer = null; + OriginAuth = null; + } + } + } + + /// + internal static Sid[] GetGroupMemberSids0(DcerpcHandle handle, SamrDomainHandle + domainHandle, Sid domsid, int rid, int flags) + { + SamrAliasHandle aliasHandle = null; + Lsarpc.LsarSidArray sidarray = new Lsarpc.LsarSidArray(); + MsrpcGetMembersInAlias rpc = null; + try + { + aliasHandle = new SamrAliasHandle(handle, domainHandle, unchecked(0x0002000c), rid); + rpc = new MsrpcGetMembersInAlias(aliasHandle, sidarray); + handle.Sendrecv(rpc); + if (rpc.Retval != 0) + { + throw new SmbException(rpc.Retval, false); + } + Sid[] sids = new Sid[rpc.Sids.NumSids]; + string originServer = handle.GetServer(); + NtlmPasswordAuthentication originAuth = (NtlmPasswordAuthentication)handle.GetPrincipal + (); + for (int i = 0; i < sids.Length; i++) + { + sids[i] = new Sid(rpc.Sids.Sids[i].Sid, 0, null, null, false); + sids[i].OriginServer = originServer; + sids[i].OriginAuth = originAuth; + } + if (sids.Length > 0 && (flags & SidFlagResolveSids) != 0) + { + ResolveSids(originServer, originAuth, sids); + } + return sids; + } + finally + { + if (aliasHandle != null) + { + aliasHandle.Close(); + } + } + } + + /// + public virtual Sid[] GetGroupMemberSids(string authorityServerName, NtlmPasswordAuthentication + auth, int flags) + { + if (Type != SidTypeDomGrp && Type != SidTypeAlias) + { + return new Sid[0]; + } + DcerpcHandle handle = null; + SamrPolicyHandle policyHandle = null; + SamrDomainHandle domainHandle = null; + Sid domsid = GetDomainSid(); + lock (SidCache) + { + try + { + handle = DcerpcHandle.GetHandle("ncacn_np:" + authorityServerName + "[\\PIPE\\samr]" + , auth); + policyHandle = new SamrPolicyHandle(handle, authorityServerName, unchecked(0x00000030)); + domainHandle = new SamrDomainHandle(handle, policyHandle, unchecked(0x00000200), domsid); + return GetGroupMemberSids0(handle, domainHandle, domsid, GetRid(), + flags); + } + finally + { + if (handle != null) + { + if (policyHandle != null) + { + if (domainHandle != null) + { + domainHandle.Close(); + } + policyHandle.Close(); + } + handle.Close(); + } + } + } + } + + /// + /// This specialized method returns a Map of users and local groups for the + /// target server where keys are SIDs representing an account and each value + /// is an List of SIDs represents the local groups that the account is + /// a member of. + /// + /// + /// This specialized method returns a Map of users and local groups for the + /// target server where keys are SIDs representing an account and each value + /// is an List of SIDs represents the local groups that the account is + /// a member of. + ///

+ /// This method is designed to assist with computing access control for a + /// given user when the target object's ACL has local groups. Local groups + /// are not listed in a user's group membership (e.g. as represented by the + /// tokenGroups constructed attribute retrived via LDAP). + ///

+ /// Domain groups nested inside a local group are currently not expanded. In + /// this case the key (SID) type will be SID_TYPE_DOM_GRP rather than + /// SID_TYPE_USER. + /// + /// The server from which the local groups will be queried. + /// + /// The credentials required to query groups and group members. + /// + /// Flags that control the behavior of the operation. When all + /// name associated with SIDs will be required, the SID_FLAG_RESOLVE_SIDS + /// flag should be used which causes all group member SIDs to be resolved + /// together in a single more efficient operation. + /// + /// + internal static Hashtable GetLocalGroupsMap(string authorityServerName, NtlmPasswordAuthentication + auth, int flags) + { + Sid domsid = GetServerSid(authorityServerName, auth); + DcerpcHandle handle = null; + SamrPolicyHandle policyHandle = null; + SamrDomainHandle domainHandle = null; + Samr.SamrSamArray sam = new Samr.SamrSamArray(); + MsrpcEnumerateAliasesInDomain rpc; + lock (SidCache) + { + try + { + handle = DcerpcHandle.GetHandle("ncacn_np:" + authorityServerName + "[\\PIPE\\samr]" + , auth); + policyHandle = new SamrPolicyHandle(handle, authorityServerName, unchecked(0x02000000)); + domainHandle = new SamrDomainHandle(handle, policyHandle, unchecked(0x02000000), domsid); + rpc = new MsrpcEnumerateAliasesInDomain(domainHandle, unchecked(0xFFFF), sam + ); + handle.Sendrecv(rpc); + if (rpc.Retval != 0) + { + throw new SmbException(rpc.Retval, false); + } + Hashtable map = new Hashtable(); + for (int ei = 0; ei < rpc.Sam.Count; ei++) + { + Samr.SamrSamEntry entry = rpc.Sam.Entries[ei]; + Sid[] mems = GetGroupMemberSids0(handle, domainHandle, domsid + , entry.Idx, flags); + Sid groupSid = new Sid(domsid, entry.Idx); + groupSid.Type = SidTypeAlias; + groupSid.DomainName = domsid.GetDomainName(); + groupSid.AcctName = (new UnicodeString(entry.Name, false)).ToString(); + for (int mi = 0; mi < mems.Length; mi++) + { + List groups = (List)map.Get(mems[mi]); + if (groups == null) + { + groups = new List(); + map.Put(mems[mi], groups); + } + if (!groups.Contains(groupSid)) + { + groups.Add(groupSid); + } + } + } + return map; + } + finally + { + if (handle != null) + { + if (policyHandle != null) + { + if (domainHandle != null) + { + domainHandle.Close(); + } + policyHandle.Close(); + } + handle.Close(); + } + } + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SecurityDescriptor.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SecurityDescriptor.cs new file mode 100644 index 0000000000..8a424a0199 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SecurityDescriptor.cs @@ -0,0 +1,101 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.IO; + +namespace SharpCifs.Smb +{ + public class SecurityDescriptor + { + public int Type; + + public Ace[] Aces; + + public SecurityDescriptor() + { + } + + /// + public SecurityDescriptor(byte[] buffer, int bufferIndex, int len) + { + Decode(buffer, bufferIndex, len); + } + + /// + public virtual int Decode(byte[] buffer, int bufferIndex, int len) + { + int start = bufferIndex; + bufferIndex++; + // revision + bufferIndex++; + Type = ServerMessageBlock.ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + ServerMessageBlock.ReadInt4(buffer, bufferIndex); + // offset to owner sid + bufferIndex += 4; + ServerMessageBlock.ReadInt4(buffer, bufferIndex); + // offset to group sid + bufferIndex += 4; + ServerMessageBlock.ReadInt4(buffer, bufferIndex); + // offset to sacl + bufferIndex += 4; + int daclOffset = ServerMessageBlock.ReadInt4(buffer, bufferIndex); + bufferIndex = start + daclOffset; + bufferIndex++; + // revision + bufferIndex++; + int size = ServerMessageBlock.ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + int numAces = ServerMessageBlock.ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + if (numAces > 4096) + { + throw new IOException("Invalid SecurityDescriptor"); + } + if (daclOffset != 0) + { + Aces = new Ace[numAces]; + for (int i = 0; i < numAces; i++) + { + Aces[i] = new Ace(); + bufferIndex += Aces[i].Decode(buffer, bufferIndex); + } + } + else + { + Aces = null; + } + return bufferIndex - start; + } + + public override string ToString() + { + string ret = "SecurityDescriptor:\n"; + if (Aces != null) + { + for (int ai = 0; ai < Aces.Length; ai++) + { + ret += Aces[ai] + "\n"; + } + } + else + { + ret += "NULL"; + } + return ret; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/ServerMessageBlock.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/ServerMessageBlock.cs new file mode 100644 index 0000000000..cb38c89fa6 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/ServerMessageBlock.cs @@ -0,0 +1,692 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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; +using SharpCifs.Util.Transport; + +namespace SharpCifs.Smb +{ + public abstract class ServerMessageBlock: Response + { + internal static LogStream Log = LogStream.GetInstance(); + + internal static long Ticks1601 = new DateTime(1601, 1, 1).Ticks; + + internal static readonly byte[] Header = { 0xFF, (byte)('S'), (byte)('M'), + (byte)('B'), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + internal static void WriteInt2(long val, byte[] dst, int dstIndex) + { + dst[dstIndex] = unchecked((byte)(val)); + dst[++dstIndex] = unchecked((byte)(val >> 8)); + } + + internal static void WriteInt4(long val, byte[] dst, int dstIndex) + { + dst[dstIndex] = unchecked((byte)(val)); + dst[++dstIndex] = unchecked((byte)(val >>= 8)); + dst[++dstIndex] = unchecked((byte)(val >>= 8)); + dst[++dstIndex] = unchecked((byte)(val >> 8)); + } + + internal static int ReadInt2(byte[] src, int srcIndex) + { + return unchecked(src[srcIndex] & 0xFF) + ((src[srcIndex + 1] & 0xFF) << 8); + } + + internal static int ReadInt4(byte[] src, int srcIndex) + { + return unchecked(src[srcIndex] & 0xFF) + ((src[srcIndex + 1] & 0xFF) << 8) + ((src[srcIndex + 2] + & 0xFF) << 16) + ((src[srcIndex + 3] & 0xFF) << 24); + } + + internal static long ReadInt8(byte[] src, int srcIndex) + { + return unchecked(ReadInt4(src, srcIndex) & unchecked(0xFFFFFFFFL)) + unchecked((long)(ReadInt4 + (src, srcIndex + 4)) << 32); + } + + internal static void WriteInt8(long val, byte[] dst, int dstIndex) + { + dst[dstIndex] = unchecked((byte)(val)); + dst[++dstIndex] = unchecked((byte)(val >>= 8)); + dst[++dstIndex] = unchecked((byte)(val >>= 8)); + dst[++dstIndex] = unchecked((byte)(val >>= 8)); + dst[++dstIndex] = unchecked((byte)(val >>= 8)); + dst[++dstIndex] = unchecked((byte)(val >>= 8)); + dst[++dstIndex] = unchecked((byte)(val >>= 8)); + dst[++dstIndex] = unchecked((byte)(val >> 8)); + } + + internal static long ReadTime(byte[] src, int srcIndex) + { + int low = ReadInt4(src, srcIndex); + int hi = ReadInt4(src, srcIndex + 4); + long t = ((long)hi << (int)32L) | (low & unchecked((long)(0xFFFFFFFFL))); + t = (t / 10000L - SmbConstants.MillisecondsBetween1970And1601); + return t; + } + + internal static void WriteTime(long t, byte[] dst, int dstIndex) + { + if (t != 0L) + { + t = (t + SmbConstants.MillisecondsBetween1970And1601) * 10000L; + } + WriteInt8(t, dst, dstIndex); + } + + internal static long ReadUTime(byte[] buffer, int bufferIndex) + { + return ReadInt4(buffer, bufferIndex) * 1000L; + } + + internal static void WriteUTime(long t, byte[] dst, int dstIndex) + { + if (t == 0L || t == unchecked((long)(0xFFFFFFFFFFFFFFFFL))) + { + WriteInt4(unchecked((int)(0xFFFFFFFF)), dst, dstIndex); + return; + } + // t isn't in DST either + WriteInt4((int)(t / 1000L), dst, dstIndex); + } + + internal const byte SmbComCreateDirectory = 0x00; + + internal const byte SmbComDeleteDirectory = 0x01; + + internal const byte SmbComClose = 0x04; + + internal const byte SmbComDelete = 0x06; + + internal const byte SmbComRename = 0x07; + + internal const byte SmbComQueryInformation = 0x08; + + internal const byte SmbComWrite = 0x0B; + + internal const byte SmbComCheckDirectory = 0x10; + + internal const byte SmbComTransaction = 0x25; + + internal const byte SmbComTransactionSecondary = 0x26; + + internal const byte SmbComMove = 0x2A; + + internal const byte SmbComEcho = 0x2B; + + internal const byte SmbComOpenAndx = 0x2D; + + internal const byte SmbComReadAndx = 0x2E; + + internal const byte SmbComWriteAndx = 0x2F; + + internal const byte SmbComTransaction2 = 0x32; + + internal const byte SmbComFindClose2 = 0x34; + + internal const byte SmbComTreeDisconnect = 0x71; + + internal const byte SmbComNegotiate = 0x72; + + internal const byte SmbComSessionSetupAndx = 0x73; + + internal const byte SmbComLogoffAndx = 0x74; + + internal const byte SmbComTreeConnectAndx = 0x75; + + internal const byte SmbComNtTransact = 0xA0; + + internal const byte SmbComNtTransactSecondary = 0xA1; + + internal const byte SmbComNtCreateAndx = 0xA2; + + internal byte Command; + + internal byte Flags; + + internal int HeaderStart; + + internal int Length; + + internal int BatchLevel; + + internal int ErrorCode; + + internal int Flags2; + + internal int Tid; + + internal int Pid; + + internal int Uid; + + internal int Mid; + + internal int WordCount; + + internal int ByteCount; + + internal bool UseUnicode; + + internal bool Received; + + internal bool ExtendedSecurity; + + internal long ResponseTimeout = 1; + + internal int SignSeq; + + internal bool VerifyFailed; + + internal NtlmPasswordAuthentication Auth = null; + + internal string Path; + + internal SigningDigest Digest; + + internal ServerMessageBlock Response; + + public ServerMessageBlock() + { + Flags = unchecked((byte)(SmbConstants.FlagsPathNamesCaseless | SmbConstants.FlagsPathNamesCanonicalized + )); + Pid = SmbConstants.Pid; + BatchLevel = 0; + } + + internal virtual void Reset() + { + Flags = unchecked((byte)(SmbConstants.FlagsPathNamesCaseless | SmbConstants.FlagsPathNamesCanonicalized + )); + Flags2 = 0; + ErrorCode = 0; + Received = false; + Digest = null; + } + + internal virtual int WriteString(string str, byte[] dst, int dstIndex) + { + return WriteString(str, dst, dstIndex, UseUnicode); + } + + internal virtual int WriteString(string str, byte[] dst, int dstIndex, bool useUnicode + ) + { + int start = dstIndex; + try + { + if (useUnicode) + { + // Unicode requires word alignment + if (((dstIndex - HeaderStart) % 2) != 0) + { + dst[dstIndex++] = (byte)('\0'); + } + Array.Copy(Runtime.GetBytesForString(str, SmbConstants.UniEncoding), 0, dst, dstIndex + , str.Length * 2); + dstIndex += str.Length * 2; + dst[dstIndex++] = (byte)('\0'); + dst[dstIndex++] = (byte)('\0'); + } + else + { + byte[] b = Runtime.GetBytesForString(str, SmbConstants.OemEncoding); + Array.Copy(b, 0, dst, dstIndex, b.Length); + dstIndex += b.Length; + dst[dstIndex++] = (byte)('\0'); + } + } + catch (UnsupportedEncodingException uee) + { + if (Log.Level > 1) + { + Runtime.PrintStackTrace(uee, Log); + } + } + return dstIndex - start; + } + + internal virtual string ReadString(byte[] src, int srcIndex) + { + return ReadString(src, srcIndex, 256, UseUnicode); + } + + internal virtual string ReadString(byte[] src, int srcIndex, int maxLen, bool useUnicode + ) + { + int len = 0; + string str = null; + try + { + if (useUnicode) + { + // Unicode requires word alignment + if (((srcIndex - HeaderStart) % 2) != 0) + { + srcIndex++; + } + while (src[srcIndex + len] != 0x00 || src[srcIndex + + len + 1] != 0x00) + { + len += 2; + if (len > maxLen) + { + if (Log.Level > 0) + { + Hexdump.ToHexdump(Console.Error, src, srcIndex, maxLen < 128 ? maxLen + 8 : + 128); + } + throw new RuntimeException("zero termination not found"); + } + } + str = Runtime.GetStringForBytes(src, srcIndex, len, SmbConstants.UniEncoding); + } + else + { + while (src[srcIndex + len] != 0x00) + { + len++; + if (len > maxLen) + { + if (Log.Level > 0) + { + Hexdump.ToHexdump(Console.Error, src, srcIndex, maxLen < 128 ? maxLen + 8 : + 128); + } + throw new RuntimeException("zero termination not found"); + } + } + str = Runtime.GetStringForBytes(src, srcIndex, len, SmbConstants.OemEncoding); + } + } + catch (UnsupportedEncodingException uee) + { + if (Log.Level > 1) + { + Runtime.PrintStackTrace(uee, Log); + } + } + return str; + } + + internal virtual string ReadString(byte[] src, int srcIndex, int srcEnd, int maxLen + , bool useUnicode) + { + int len = 0; + string str = null; + try + { + if (useUnicode) + { + // Unicode requires word alignment + if (((srcIndex - HeaderStart) % 2) != 0) + { + srcIndex++; + } + for (len = 0; (srcIndex + len + 1) < srcEnd; len += 2) + { + if (src[srcIndex + len] == 0x00 && src[srcIndex + + len + 1] == 0x00) + { + break; + } + if (len > maxLen) + { + if (Log.Level > 0) + { + Hexdump.ToHexdump(Console.Error, src, srcIndex, maxLen < 128 ? maxLen + 8 : + 128); + } + throw new RuntimeException("zero termination not found"); + } + } + str = Runtime.GetStringForBytes(src, srcIndex, len, SmbConstants.UniEncoding); + } + else + { + for (len = 0; srcIndex < srcEnd; len++) + { + if (src[srcIndex + len] == 0x00) + { + break; + } + if (len > maxLen) + { + if (Log.Level > 0) + { + Hexdump.ToHexdump(Console.Error, src, srcIndex, maxLen < 128 ? maxLen + 8 : + 128); + } + throw new RuntimeException("zero termination not found"); + } + } + str = Runtime.GetStringForBytes(src, srcIndex, len, SmbConstants.OemEncoding); + } + } + catch (UnsupportedEncodingException uee) + { + if (Log.Level > 1) + { + Runtime.PrintStackTrace(uee, Log); + } + } + return str; + } + + internal virtual int StringWireLength(string str, int offset) + { + int len = str.Length + 1; + if (UseUnicode) + { + len = str.Length * 2 + 2; + len = (offset % 2) != 0 ? len + 1 : len; + } + return len; + } + + internal virtual int ReadStringLength(byte[] src, int srcIndex, int max) + { + int len = 0; + while (src[srcIndex + len] != 0x00) + { + if (len++ > max) + { + throw new RuntimeException("zero termination not found: " + this); + } + } + return len; + } + + internal virtual int Encode(byte[] dst, int dstIndex) + { + int start = HeaderStart = dstIndex; + dstIndex += WriteHeaderWireFormat(dst, dstIndex); + WordCount = WriteParameterWordsWireFormat(dst, dstIndex + 1); + dst[dstIndex++] = unchecked((byte)((WordCount / 2) & 0xFF)); + dstIndex += WordCount; + WordCount /= 2; + ByteCount = WriteBytesWireFormat(dst, dstIndex + 2); + dst[dstIndex++] = unchecked((byte)(ByteCount & 0xFF)); + dst[dstIndex++] = unchecked((byte)((ByteCount >> 8) & 0xFF)); + dstIndex += ByteCount; + Length = dstIndex - start; + if (Digest != null) + { + Digest.Sign(dst, HeaderStart, Length, this, Response); + } + return Length; + } + + internal virtual int Decode(byte[] buffer, int bufferIndex) + { + int start = HeaderStart = bufferIndex; + bufferIndex += ReadHeaderWireFormat(buffer, bufferIndex); + WordCount = buffer[bufferIndex++]; + if (WordCount != 0) + { + int n; + if ((n = ReadParameterWordsWireFormat(buffer, bufferIndex)) != WordCount * 2) + { + if (Log.Level >= 5) + { + Log.WriteLine("wordCount * 2=" + (WordCount * 2) + " but readParameterWordsWireFormat returned " + + n); + } + } + bufferIndex += WordCount * 2; + } + ByteCount = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + if (ByteCount != 0) + { + int n; + if ((n = ReadBytesWireFormat(buffer, bufferIndex)) != ByteCount) + { + if (Log.Level >= 5) + { + Log.WriteLine("byteCount=" + ByteCount + " but readBytesWireFormat returned " + n + ); + } + } + // Don't think we can rely on n being correct here. Must use byteCount. + // Last paragraph of section 3.13.3 eludes to this. + bufferIndex += ByteCount; + } + Length = bufferIndex - start; + return Length; + } + + internal virtual int WriteHeaderWireFormat(byte[] dst, int dstIndex) + { + Array.Copy(Header, 0, dst, dstIndex, Header.Length); + dst[dstIndex + SmbConstants.CmdOffset] = Command; + dst[dstIndex + SmbConstants.FlagsOffset] = Flags; + WriteInt2(Flags2, dst, dstIndex + SmbConstants.FlagsOffset + 1); + dstIndex += SmbConstants.TidOffset; + WriteInt2(Tid, dst, dstIndex); + WriteInt2(Pid, dst, dstIndex + 2); + WriteInt2(Uid, dst, dstIndex + 4); + WriteInt2(Mid, dst, dstIndex + 6); + return SmbConstants.HeaderLength; + } + + internal virtual int ReadHeaderWireFormat(byte[] buffer, int bufferIndex) + { + Command = buffer[bufferIndex + SmbConstants.CmdOffset]; + ErrorCode = ReadInt4(buffer, bufferIndex + SmbConstants.ErrorCodeOffset); + Flags = buffer[bufferIndex + SmbConstants.FlagsOffset]; + Flags2 = ReadInt2(buffer, bufferIndex + SmbConstants.FlagsOffset + 1); + Tid = ReadInt2(buffer, bufferIndex + SmbConstants.TidOffset); + Pid = ReadInt2(buffer, bufferIndex + SmbConstants.TidOffset + 2); + Uid = ReadInt2(buffer, bufferIndex + SmbConstants.TidOffset + 4); + Mid = ReadInt2(buffer, bufferIndex + SmbConstants.TidOffset + 6); + return SmbConstants.HeaderLength; + } + + internal virtual bool IsResponse() + { + return (Flags & SmbConstants.FlagsResponse) == SmbConstants.FlagsResponse; + } + + internal abstract int WriteParameterWordsWireFormat(byte[] dst, int dstIndex); + + internal abstract int WriteBytesWireFormat(byte[] dst, int dstIndex); + + internal abstract int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ); + + internal abstract int ReadBytesWireFormat(byte[] buffer, int bufferIndex); + + public override int GetHashCode() + { + return Mid; + } + + public override bool Equals(object obj) + { + return obj is ServerMessageBlock && ((ServerMessageBlock)obj) + .Mid == Mid; + } + + public override string ToString() + { + string c; + switch (Command) + { + case SmbComNegotiate: + { + c = "SMB_COM_NEGOTIATE"; + break; + } + + case SmbComSessionSetupAndx: + { + c = "SMB_COM_SESSION_SETUP_ANDX"; + break; + } + + case SmbComTreeConnectAndx: + { + c = "SMB_COM_TREE_CONNECT_ANDX"; + break; + } + + case SmbComQueryInformation: + { + c = "SMB_COM_QUERY_INFORMATION"; + break; + } + + case SmbComCheckDirectory: + { + c = "SMB_COM_CHECK_DIRECTORY"; + break; + } + + case SmbComTransaction: + { + c = "SMB_COM_TRANSACTION"; + break; + } + + case SmbComTransaction2: + { + c = "SMB_COM_TRANSACTION2"; + break; + } + + case SmbComTransactionSecondary: + { + c = "SMB_COM_TRANSACTION_SECONDARY"; + break; + } + + case SmbComFindClose2: + { + c = "SMB_COM_FIND_CLOSE2"; + break; + } + + case SmbComTreeDisconnect: + { + c = "SMB_COM_TREE_DISCONNECT"; + break; + } + + case SmbComLogoffAndx: + { + c = "SMB_COM_LOGOFF_ANDX"; + break; + } + + case SmbComEcho: + { + c = "SMB_COM_ECHO"; + break; + } + + case SmbComMove: + { + c = "SMB_COM_MOVE"; + break; + } + + case SmbComRename: + { + c = "SMB_COM_RENAME"; + break; + } + + case SmbComDelete: + { + c = "SMB_COM_DELETE"; + break; + } + + case SmbComDeleteDirectory: + { + c = "SMB_COM_DELETE_DIRECTORY"; + break; + } + + case SmbComNtCreateAndx: + { + c = "SMB_COM_NT_CREATE_ANDX"; + break; + } + + case SmbComOpenAndx: + { + c = "SMB_COM_OPEN_ANDX"; + break; + } + + case SmbComReadAndx: + { + c = "SMB_COM_READ_ANDX"; + break; + } + + case SmbComClose: + { + c = "SMB_COM_CLOSE"; + break; + } + + case SmbComWriteAndx: + { + c = "SMB_COM_WRITE_ANDX"; + break; + } + + case SmbComCreateDirectory: + { + c = "SMB_COM_CREATE_DIRECTORY"; + break; + } + + case SmbComNtTransact: + { + c = "SMB_COM_NT_TRANSACT"; + break; + } + + case SmbComNtTransactSecondary: + { + c = "SMB_COM_NT_TRANSACT_SECONDARY"; + break; + } + + default: + { + c = "UNKNOWN"; + break; + } + } + string str = ErrorCode == 0 ? "0" : SmbException.GetMessageByCode(ErrorCode); + return "command=" + c + ",received=" + Received + ",errorCode=" + str + + ",flags=0x" + Hexdump.ToHexString(Flags & 0xFF, 4) + ",flags2=0x" + + Hexdump.ToHexString(Flags2, 4) + ",signSeq=" + SignSeq + ",tid=" + Tid + ",pid=" + + Pid + ",uid=" + Uid + ",mid=" + Mid + ",wordCount=" + WordCount + ",byteCount=" + + ByteCount; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SigningDigest.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SigningDigest.cs new file mode 100644 index 0000000000..9f57e887b7 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SigningDigest.cs @@ -0,0 +1,257 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +{ + /// To filter 0 len updates and for debugging + public class SigningDigest + { + internal static LogStream Log = LogStream.GetInstance(); + + private MessageDigest _digest; + + private byte[] _macSigningKey; + + private bool _bypass; + + private int _updates; + + private int _signSequence; + + /// + public SigningDigest(byte[] macSigningKey, bool bypass) + { + try + { + _digest = MessageDigest.GetInstance("MD5"); + } + catch (NoSuchAlgorithmException ex) + { + if (Log.Level > 0) + { + Runtime.PrintStackTrace(ex, Log); + } + throw new SmbException("MD5", ex); + } + this._macSigningKey = macSigningKey; + this._bypass = bypass; + _updates = 0; + _signSequence = 0; + if (Log.Level >= 5) + { + Log.WriteLine("macSigningKey:"); + Hexdump.ToHexdump(Log, macSigningKey, 0, macSigningKey.Length); + } + } + + /// + public SigningDigest(SmbTransport transport, NtlmPasswordAuthentication auth) + { + try + { + _digest = MessageDigest.GetInstance("MD5"); + } + catch (NoSuchAlgorithmException ex) + { + if (Log.Level > 0) + { + Runtime.PrintStackTrace(ex, Log); + } + throw new SmbException("MD5", ex); + } + try + { + switch (SmbConstants.LmCompatibility) + { + case 0: + case 1: + case 2: + { + _macSigningKey = new byte[40]; + auth.GetUserSessionKey(transport.Server.EncryptionKey, _macSigningKey, 0); + Array.Copy(auth.GetUnicodeHash(transport.Server.EncryptionKey), 0, _macSigningKey + , 16, 24); + break; + } + + case 3: + case 4: + case 5: + { + _macSigningKey = new byte[16]; + auth.GetUserSessionKey(transport.Server.EncryptionKey, _macSigningKey, 0); + break; + } + + default: + { + _macSigningKey = new byte[40]; + auth.GetUserSessionKey(transport.Server.EncryptionKey, _macSigningKey, 0); + Array.Copy(auth.GetUnicodeHash(transport.Server.EncryptionKey), 0, _macSigningKey + , 16, 24); + break; + } + } + } + catch (Exception ex) + { + throw new SmbException(string.Empty, ex); + } + if (Log.Level >= 5) + { + Log.WriteLine("LM_COMPATIBILITY=" + SmbConstants.LmCompatibility); + Hexdump.ToHexdump(Log, _macSigningKey, 0, _macSigningKey.Length); + } + } + + public virtual void Update(byte[] input, int offset, int len) + { + if (Log.Level >= 5) + { + Log.WriteLine("update: " + _updates + " " + offset + ":" + len); + Hexdump.ToHexdump(Log, input, offset, Math.Min(len, 256)); + Log.Flush(); + } + if (len == 0) + { + return; + } + _digest.Update(input, offset, len); + _updates++; + } + + public virtual byte[] Digest() + { + byte[] b; + b = _digest.Digest(); + if (Log.Level >= 5) + { + Log.WriteLine("digest: "); + Hexdump.ToHexdump(Log, b, 0, b.Length); + Log.Flush(); + } + _updates = 0; + return b; + } + + /// Performs MAC signing of the SMB. + /// + /// Performs MAC signing of the SMB. This is done as follows. + /// The signature field of the SMB is overwritted with the sequence number; + /// The MD5 digest of the MAC signing key + the entire SMB is taken; + /// The first 8 bytes of this are placed in the signature field. + /// + /// The data. + /// The starting offset at which the SMB header begins. + /// The length of the SMB data starting at offset. + internal virtual void Sign(byte[] data, int offset, int length, ServerMessageBlock + request, ServerMessageBlock response) + { + request.SignSeq = _signSequence; + if (response != null) + { + response.SignSeq = _signSequence + 1; + response.VerifyFailed = false; + } + try + { + Update(_macSigningKey, 0, _macSigningKey.Length); + int index = offset + SmbConstants.SignatureOffset; + for (int i = 0; i < 8; i++) + { + data[index + i] = 0; + } + ServerMessageBlock.WriteInt4(_signSequence, data, index); + Update(data, offset, length); + Array.Copy(Digest(), 0, data, index, 8); + if (_bypass) + { + _bypass = false; + Array.Copy(Runtime.GetBytesForString("BSRSPYL "), 0, data, index, + 8); + } + } + catch (Exception ex) + { + if (Log.Level > 0) + { + Runtime.PrintStackTrace(ex, Log); + } + } + finally + { + _signSequence += 2; + } + } + + /// Performs MAC signature verification. + /// + /// Performs MAC signature verification. This calculates the signature + /// of the SMB and compares it to the signature field on the SMB itself. + /// + /// The data. + /// The starting offset at which the SMB header begins. + /// The length of the SMB data starting at offset. + internal virtual bool Verify(byte[] data, int offset, ServerMessageBlock response + ) + { + Update(_macSigningKey, 0, _macSigningKey.Length); + int index = offset; + Update(data, index, SmbConstants.SignatureOffset); + index += SmbConstants.SignatureOffset; + byte[] sequence = new byte[8]; + ServerMessageBlock.WriteInt4(response.SignSeq, sequence, 0); + Update(sequence, 0, sequence.Length); + index += 8; + if (response.Command == ServerMessageBlock.SmbComReadAndx) + { + SmbComReadAndXResponse raxr = (SmbComReadAndXResponse)response; + int length = response.Length - raxr.DataLength; + Update(data, index, length - SmbConstants.SignatureOffset - 8); + Update(raxr.B, raxr.Off, raxr.DataLength); + } + else + { + Update(data, index, response.Length - SmbConstants.SignatureOffset - 8); + } + byte[] signature = Digest(); + for (int i = 0; i < 8; i++) + { + if (signature[i] != data[offset + SmbConstants.SignatureOffset + i]) + { + if (Log.Level >= 2) + { + Log.WriteLine("signature verification failure"); + Hexdump.ToHexdump(Log, signature, 0, 8); + Hexdump.ToHexdump(Log, data, offset + SmbConstants.SignatureOffset, 8); + } + return response.VerifyFailed = true; + } + } + return response.VerifyFailed = false; + } + + public override string ToString() + { + return "LM_COMPATIBILITY=" + SmbConstants.LmCompatibility + " MacSigningKey=" + Hexdump.ToHexString + (_macSigningKey, 0, _macSigningKey.Length); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbAuthException.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbAuthException.cs new file mode 100644 index 0000000000..defaea71b4 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbAuthException.cs @@ -0,0 +1,36 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + /// + /// The SmbAuthException encapsulates the variety of + /// authentication related error codes returned by an SMB server. + /// + /// + /// The SmbAuthException encapsulates the variety of + /// authentication related error codes returned by an SMB server. + ///

+ /// See jCIFS Exceptions and NtlmAuthenticator for more information about SmbAuthException. + /// + + public class SmbAuthException : SmbException + { + internal SmbAuthException(int errcode) : base(errcode, null) + { + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComBlankResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComBlankResponse.cs new file mode 100644 index 0000000000..2295de5b9c --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComBlankResponse.cs @@ -0,0 +1,47 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComBlankResponse : ServerMessageBlock + { + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComBlankResponse[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComClose.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComClose.cs new file mode 100644 index 0000000000..4a160f5188 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComClose.cs @@ -0,0 +1,62 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComClose : ServerMessageBlock + { + private int _fid; + + private long _lastWriteTime; + + internal SmbComClose(int fid, long lastWriteTime) + { + this._fid = fid; + this._lastWriteTime = lastWriteTime; + Command = SmbComClose; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + WriteInt2(_fid, dst, dstIndex); + dstIndex += 2; + WriteUTime(_lastWriteTime, dst, dstIndex); + return 6; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComClose[" + base.ToString() + ",fid=" + _fid + ",lastWriteTime=" + + _lastWriteTime + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComCreateDirectory.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComCreateDirectory.cs new file mode 100644 index 0000000000..7549db01ab --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComCreateDirectory.cs @@ -0,0 +1,57 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComCreateDirectory : ServerMessageBlock + { + internal SmbComCreateDirectory(string directoryName) + { + Path = directoryName; + Command = SmbComCreateDirectory; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + dst[dstIndex++] = unchecked(unchecked(0x04)); + dstIndex += WriteString(Path, dst, dstIndex); + return dstIndex - start; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComCreateDirectory[" + base.ToString() + ",directoryName=" + + Path + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComDelete.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComDelete.cs new file mode 100644 index 0000000000..d055d2446d --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComDelete.cs @@ -0,0 +1,63 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; + +namespace SharpCifs.Smb +{ + internal class SmbComDelete : ServerMessageBlock + { + private int _searchAttributes; + + internal SmbComDelete(string fileName) + { + Path = fileName; + Command = SmbComDelete; + _searchAttributes = SmbConstants.AttrHidden | SmbConstants.AttrHidden | SmbConstants.AttrSystem; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + WriteInt2(_searchAttributes, dst, dstIndex); + return 2; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + dst[dstIndex++] = unchecked(unchecked(0x04)); + dstIndex += WriteString(Path, dst, dstIndex); + return dstIndex - start; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComDelete[" + base.ToString() + ",searchAttributes=0x" + Hexdump + .ToHexString(_searchAttributes, 4) + ",fileName=" + Path + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComDeleteDirectory.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComDeleteDirectory.cs new file mode 100644 index 0000000000..240139a173 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComDeleteDirectory.cs @@ -0,0 +1,57 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComDeleteDirectory : ServerMessageBlock + { + internal SmbComDeleteDirectory(string directoryName) + { + Path = directoryName; + Command = SmbComDeleteDirectory; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + dst[dstIndex++] = unchecked(unchecked(0x04)); + dstIndex += WriteString(Path, dst, dstIndex); + return dstIndex - start; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComDeleteDirectory[" + base.ToString() + ",directoryName=" + + Path + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComFindClose2.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComFindClose2.cs new file mode 100644 index 0000000000..9b7c0c7657 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComFindClose2.cs @@ -0,0 +1,56 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComFindClose2 : ServerMessageBlock + { + private int _sid; + + internal SmbComFindClose2(int sid) + { + this._sid = sid; + Command = SmbComFindClose2; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + WriteInt2(_sid, dst, dstIndex); + return 2; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComFindClose2[" + base.ToString() + ",sid=" + _sid + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComLogoffAndX.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComLogoffAndX.cs new file mode 100644 index 0000000000..8f88ccd579 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComLogoffAndX.cs @@ -0,0 +1,52 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComLogoffAndX : AndXServerMessageBlock + { + internal SmbComLogoffAndX(ServerMessageBlock andx) : base(andx) + { + Command = SmbComLogoffAndx; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComLogoffAndX[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNTCreateAndX.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNTCreateAndX.cs new file mode 100644 index 0000000000..26b5ba63af --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNTCreateAndX.cs @@ -0,0 +1,193 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; + +namespace SharpCifs.Smb +{ + internal class SmbComNtCreateAndX : AndXServerMessageBlock + { + internal const int FileSupersede = unchecked(0x0); + + internal const int FileOpen = unchecked(0x1); + + internal const int FileCreate = unchecked(0x2); + + internal const int FileOpenIf = unchecked(0x3); + + internal const int FileOverwrite = unchecked(0x4); + + internal const int FileOverwriteIf = unchecked(0x5); + + internal const int FileWriteThrough = unchecked(0x00000002); + + internal const int FileSequentialOnly = unchecked(0x00000004); + + internal const int FileSynchronousIoAlert = unchecked(0x00000010); + + internal const int FileSynchronousIoNonalert = unchecked(0x00000020); + + internal const int SecurityContextTracking = unchecked(0x01); + + internal const int SecurityEffectiveOnly = unchecked(0x02); + + private int _rootDirectoryFid; + + private int _extFileAttributes; + + private int _shareAccess; + + private int _createDisposition; + + private int _createOptions; + + private int _impersonationLevel; + + private long _allocationSize; + + private byte _securityFlags; + + private int _namelenIndex; + + internal int Flags0; + + internal int DesiredAccess; + + internal SmbComNtCreateAndX(string name, int flags, int access, int shareAccess, + int extFileAttributes, int createOptions, ServerMessageBlock andx) : base(andx) + { + // share access specified in SmbFile + // create disposition + // create options + // security flags + Path = name; + Command = SmbComNtCreateAndx; + DesiredAccess = access; + DesiredAccess |= SmbConstants.FileReadData | SmbConstants.FileReadEa | SmbConstants.FileReadAttributes; + // extFileAttributes + this._extFileAttributes = extFileAttributes; + // shareAccess + this._shareAccess = shareAccess; + // createDisposition + if ((flags & SmbFile.OTrunc) == SmbFile.OTrunc) + { + // truncate the file + if ((flags & SmbFile.OCreat) == SmbFile.OCreat) + { + // create it if necessary + _createDisposition = FileOverwriteIf; + } + else + { + _createDisposition = FileOverwrite; + } + } + else + { + // don't truncate the file + if ((flags & SmbFile.OCreat) == SmbFile.OCreat) + { + // create it if necessary + if ((flags & SmbFile.OExcl) == SmbFile.OExcl) + { + // fail if already exists + _createDisposition = FileCreate; + } + else + { + _createDisposition = FileOpenIf; + } + } + else + { + _createDisposition = FileOpen; + } + } + if ((createOptions & unchecked(0x0001)) == 0) + { + this._createOptions = createOptions | unchecked(0x0040); + } + else + { + this._createOptions = createOptions; + } + _impersonationLevel = unchecked(0x02); + // As seen on NT :~) + _securityFlags = unchecked(unchecked(0x03)); + } + + // SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + dst[dstIndex++] = unchecked(unchecked(0x00)); + // name length without counting null termination + _namelenIndex = dstIndex; + dstIndex += 2; + WriteInt4(Flags0, dst, dstIndex); + dstIndex += 4; + WriteInt4(_rootDirectoryFid, dst, dstIndex); + dstIndex += 4; + WriteInt4(DesiredAccess, dst, dstIndex); + dstIndex += 4; + WriteInt8(_allocationSize, dst, dstIndex); + dstIndex += 8; + WriteInt4(_extFileAttributes, dst, dstIndex); + dstIndex += 4; + WriteInt4(_shareAccess, dst, dstIndex); + dstIndex += 4; + WriteInt4(_createDisposition, dst, dstIndex); + dstIndex += 4; + WriteInt4(_createOptions, dst, dstIndex); + dstIndex += 4; + WriteInt4(_impersonationLevel, dst, dstIndex); + dstIndex += 4; + dst[dstIndex++] = _securityFlags; + return dstIndex - start; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + int n; + n = WriteString(Path, dst, dstIndex); + WriteInt2((UseUnicode ? Path.Length * 2 : n), dst, _namelenIndex); + return n; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComNTCreateAndX[" + base.ToString() + ",flags=0x" + Hexdump + .ToHexString(Flags0, 2) + ",rootDirectoryFid=" + _rootDirectoryFid + ",desiredAccess=0x" + + Hexdump.ToHexString(DesiredAccess, 4) + ",allocationSize=" + _allocationSize + + ",extFileAttributes=0x" + Hexdump.ToHexString(_extFileAttributes, 4) + ",shareAccess=0x" + + Hexdump.ToHexString(_shareAccess, 4) + ",createDisposition=0x" + Hexdump.ToHexString + (_createDisposition, 4) + ",createOptions=0x" + Hexdump.ToHexString(_createOptions + , 8) + ",impersonationLevel=0x" + Hexdump.ToHexString(_impersonationLevel, 4) + ",securityFlags=0x" + + Hexdump.ToHexString(_securityFlags, 2) + ",name=" + Path + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNTCreateAndXResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNTCreateAndXResponse.cs new file mode 100644 index 0000000000..4a007bdc5b --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNTCreateAndXResponse.cs @@ -0,0 +1,116 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal class SmbComNtCreateAndXResponse : AndXServerMessageBlock + { + internal const int ExclusiveOplockGranted = 1; + + internal const int BatchOplockGranted = 2; + + internal const int LevelIiOplockGranted = 3; + + internal byte OplockLevel; + + internal int Fid; + + internal int CreateAction; + + internal int ExtFileAttributes; + + internal int FileType; + + internal int DeviceState; + + internal long CreationTime; + + internal long LastAccessTime; + + internal long LastWriteTime; + + internal long ChangeTime; + + internal long AllocationSize; + + internal long EndOfFile; + + internal bool Directory; + + internal bool IsExtended; + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + OplockLevel = buffer[bufferIndex++]; + Fid = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + CreateAction = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + CreationTime = ReadTime(buffer, bufferIndex); + bufferIndex += 8; + LastAccessTime = ReadTime(buffer, bufferIndex); + bufferIndex += 8; + LastWriteTime = ReadTime(buffer, bufferIndex); + bufferIndex += 8; + ChangeTime = ReadTime(buffer, bufferIndex); + bufferIndex += 8; + ExtFileAttributes = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + AllocationSize = ReadInt8(buffer, bufferIndex); + bufferIndex += 8; + EndOfFile = ReadInt8(buffer, bufferIndex); + bufferIndex += 8; + FileType = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + DeviceState = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + Directory = (buffer[bufferIndex++] & unchecked(0xFF)) > 0; + return bufferIndex - start; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComNTCreateAndXResponse[" + base.ToString() + ",oplockLevel=" + + OplockLevel + ",fid=" + Fid + ",createAction=0x" + Hexdump.ToHexString(CreateAction + , 4) + ",creationTime=" + Extensions.CreateDate(CreationTime) + ",lastAccessTime=" + + Extensions.CreateDate(LastAccessTime) + ",lastWriteTime=" + Extensions.CreateDate + (LastWriteTime) + ",changeTime=" + Extensions.CreateDate(ChangeTime) + ",extFileAttributes=0x" + + Hexdump.ToHexString(ExtFileAttributes, 4) + ",allocationSize=" + AllocationSize + + ",endOfFile=" + EndOfFile + ",fileType=" + FileType + ",deviceState=" + DeviceState + + ",directory=" + Directory + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNegotiate.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNegotiate.cs new file mode 100644 index 0000000000..499bffbd9c --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNegotiate.cs @@ -0,0 +1,70 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Sharpen; + +namespace SharpCifs.Smb +{ + internal class SmbComNegotiate : ServerMessageBlock + { + private const string Dialects = "\u0002NT LM 0.12\u0000"; + + public SmbComNegotiate() + { + Command = SmbComNegotiate; + Flags2 = SmbConstants.DefaultFlags2; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + byte[] dialects; + try + { + //dialects = Runtime.GetBytesForString(Dialects, "ASCII"); + dialects = Runtime.GetBytesForString(Dialects, "UTF-8"); + } + catch (UnsupportedEncodingException) + { + return 0; + } + Array.Copy(dialects, 0, dst, dstIndex, dialects.Length); + return dialects.Length; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComNegotiate[" + base.ToString() + ",wordCount=" + WordCount + + ",dialects=NT LM 0.12]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNegotiateResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNegotiateResponse.cs new file mode 100644 index 0000000000..c4cd1c1297 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNegotiateResponse.cs @@ -0,0 +1,164 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +{ + internal class SmbComNegotiateResponse : ServerMessageBlock + { + internal int DialectIndex; + + internal SmbTransport.ServerData Server; + + internal SmbComNegotiateResponse(SmbTransport.ServerData server) + { + this.Server = server; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + DialectIndex = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + if (DialectIndex > 10) + { + return bufferIndex - start; + } + Server.SecurityMode = buffer[bufferIndex++] & unchecked(0xFF); + Server.Security = Server.SecurityMode & unchecked(0x01); + Server.EncryptedPasswords = (Server.SecurityMode & unchecked(0x02)) == unchecked( + 0x02); + Server.SignaturesEnabled = (Server.SecurityMode & unchecked(0x04)) == unchecked( + 0x04); + Server.SignaturesRequired = (Server.SecurityMode & unchecked(0x08)) == unchecked( + 0x08); + Server.MaxMpxCount = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + Server.MaxNumberVcs = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + Server.MaxBufferSize = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + Server.MaxRawSize = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + Server.SessionKey = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + Server.Capabilities = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + Server.ServerTime = ReadTime(buffer, bufferIndex); + bufferIndex += 8; + Server.ServerTimeZone = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + Server.EncryptionKeyLength = buffer[bufferIndex++] & unchecked(0xFF); + return bufferIndex - start; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + int start = bufferIndex; + if ((Server.Capabilities & SmbConstants.CapExtendedSecurity) == 0) + { + Server.EncryptionKey = new byte[Server.EncryptionKeyLength]; + Array.Copy(buffer, bufferIndex, Server.EncryptionKey, 0, Server.EncryptionKeyLength + ); + bufferIndex += Server.EncryptionKeyLength; + if (ByteCount > Server.EncryptionKeyLength) + { + int len = 0; + // TODO: we can use new string routine here + try + { + if ((Flags2 & SmbConstants.Flags2Unicode) == SmbConstants.Flags2Unicode) + { + while (buffer[bufferIndex + len] != unchecked(unchecked(0x00)) || buffer + [bufferIndex + len + 1] != unchecked(unchecked(0x00))) + { + len += 2; + if (len > 256) + { + throw new RuntimeException("zero termination not found"); + } + } + Server.OemDomainName = Runtime.GetStringForBytes(buffer, bufferIndex, len + , SmbConstants.UniEncoding); + } + else + { + while (buffer[bufferIndex + len] != unchecked(unchecked(0x00))) + { + len++; + if (len > 256) + { + throw new RuntimeException("zero termination not found"); + } + } + Server.OemDomainName = Runtime.GetStringForBytes(buffer, bufferIndex, len + , SmbConstants.OemEncoding); + } + } + catch (UnsupportedEncodingException uee) + { + if (Log.Level > 1) + { + Runtime.PrintStackTrace(uee, Log); + } + } + bufferIndex += len; + } + else + { + Server.OemDomainName = ""; + } + } + else + { + Server.Guid = new byte[16]; + Array.Copy(buffer, bufferIndex, Server.Guid, 0, 16); + Server.OemDomainName = ""; + } + // ignore SPNEGO token for now ... + return bufferIndex - start; + } + + public override string ToString() + { + return "SmbComNegotiateResponse[" + base.ToString() + ",wordCount=" + + WordCount + ",dialectIndex=" + DialectIndex + ",securityMode=0x" + Hexdump.ToHexString + (Server.SecurityMode, 1) + ",security=" + (Server.Security == SmbConstants.SecurityShare ? "share" + : "user") + ",encryptedPasswords=" + Server.EncryptedPasswords + ",maxMpxCount=" + + Server.MaxMpxCount + ",maxNumberVcs=" + Server.MaxNumberVcs + ",maxBufferSize=" + + Server.MaxBufferSize + ",maxRawSize=" + Server.MaxRawSize + ",sessionKey=0x" + + Hexdump.ToHexString(Server.SessionKey, 8) + ",capabilities=0x" + Hexdump.ToHexString + (Server.Capabilities, 8) + ",serverTime=" + Extensions.CreateDate(Server + .ServerTime) + ",serverTimeZone=" + Server.ServerTimeZone + ",encryptionKeyLength=" + + Server.EncryptionKeyLength + ",byteCount=" + ByteCount + ",oemDomainName=" + + Server.OemDomainName + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNtTransaction.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNtTransaction.cs new file mode 100644 index 0000000000..b5d2cf947e --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNtTransaction.cs @@ -0,0 +1,93 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal abstract class SmbComNtTransaction : SmbComTransaction + { + private const int NttPrimarySetupOffset = 69; + + private const int NttSecondaryParameterOffset = 51; + + internal const int NtTransactQuerySecurityDesc = 6; + + internal int Function; + + public SmbComNtTransaction() + { + // relative to headerStart + primarySetupOffset = NttPrimarySetupOffset; + secondaryParameterOffset = NttSecondaryParameterOffset; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + if (Command != SmbComNtTransactSecondary) + { + dst[dstIndex++] = MaxSetupCount; + } + else + { + dst[dstIndex++] = unchecked(unchecked(0x00)); + } + // Reserved + dst[dstIndex++] = unchecked(unchecked(0x00)); + // Reserved + dst[dstIndex++] = unchecked(unchecked(0x00)); + // Reserved + WriteInt4(TotalParameterCount, dst, dstIndex); + dstIndex += 4; + WriteInt4(TotalDataCount, dst, dstIndex); + dstIndex += 4; + if (Command != SmbComNtTransactSecondary) + { + WriteInt4(MaxParameterCount, dst, dstIndex); + dstIndex += 4; + WriteInt4(MaxDataCount, dst, dstIndex); + dstIndex += 4; + } + WriteInt4(ParameterCount, dst, dstIndex); + dstIndex += 4; + WriteInt4((ParameterCount == 0 ? 0 : ParameterOffset), dst, dstIndex); + dstIndex += 4; + if (Command == SmbComNtTransactSecondary) + { + WriteInt4(ParameterDisplacement, dst, dstIndex); + dstIndex += 4; + } + WriteInt4(DataCount, dst, dstIndex); + dstIndex += 4; + WriteInt4((DataCount == 0 ? 0 : DataOffset), dst, dstIndex); + dstIndex += 4; + if (Command == SmbComNtTransactSecondary) + { + WriteInt4(DataDisplacement, dst, dstIndex); + dstIndex += 4; + dst[dstIndex++] = unchecked(unchecked(0x00)); + } + else + { + // Reserved1 + dst[dstIndex++] = unchecked((byte)SetupCount); + WriteInt2(Function, dst, dstIndex); + dstIndex += 2; + dstIndex += WriteSetupWireFormat(dst, dstIndex); + } + return dstIndex - start; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNtTransactionResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNtTransactionResponse.cs new file mode 100644 index 0000000000..88d73528a1 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComNtTransactionResponse.cs @@ -0,0 +1,63 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal abstract class SmbComNtTransactionResponse : SmbComTransactionResponse + { + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + buffer[bufferIndex++] = unchecked(unchecked(0x00)); + // Reserved + buffer[bufferIndex++] = unchecked(unchecked(0x00)); + // Reserved + buffer[bufferIndex++] = unchecked(unchecked(0x00)); + // Reserved + TotalParameterCount = ReadInt4(buffer, bufferIndex); + if (BufDataStart == 0) + { + BufDataStart = TotalParameterCount; + } + bufferIndex += 4; + TotalDataCount = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + ParameterCount = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + ParameterOffset = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + ParameterDisplacement = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + DataCount = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + DataOffset = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + DataDisplacement = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + SetupCount = buffer[bufferIndex] & unchecked(0xFF); + bufferIndex += 2; + if (SetupCount != 0) + { + if (Log.Level >= 3) + { + Log.WriteLine("setupCount is not zero: " + SetupCount); + } + } + return bufferIndex - start; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComOpenAndX.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComOpenAndX.cs new file mode 100644 index 0000000000..de11e2a6a8 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComOpenAndX.cs @@ -0,0 +1,190 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal class SmbComOpenAndX : AndXServerMessageBlock + { + private const int FlagsReturnAdditionalInfo = 0x01; + + private const int FlagsRequestOplock = 0x02; + + private const int FlagsRequestBatchOplock = 0x04; + + private const int SharingCompatibility = 0x00; + + private const int SharingDenyReadWriteExecute = 0x10; + + private const int SharingDenyWrite = 0x20; + + private const int SharingDenyReadExecute = 0x30; + + private const int SharingDenyNone = 0x40; + + private const int DoNotCache = 0x1000; + + private const int WriteThrough = 0x4000; + + private const int OpenFnCreate = 0x10; + + private const int OpenFnFailIfExists = 0x00; + + private const int OpenFnOpen = 0x01; + + private const int OpenFnTrunc = 0x02; + + private static readonly int BatchLimit = Config.GetInt("jcifs.smb.client.OpenAndX.ReadAndX" + , 1); + + internal int flags; + + internal int DesiredAccess; + + internal int SearchAttributes; + + internal int FileAttributes; + + internal int CreationTime; + + internal int OpenFunction; + + internal int AllocationSize; + + internal SmbComOpenAndX(string fileName, int access, int flags, ServerMessageBlock + andx) : base(andx) + { + // flags (not the same as flags constructor argument) + // Access Mode Encoding for desiredAccess + // bit 12 + // bit 14 + // flags is NOT the same as flags member + Path = fileName; + Command = SmbComOpenAndx; + DesiredAccess = access & 0x3; + if (DesiredAccess == 0x3) + { + DesiredAccess = 0x2; + } + DesiredAccess |= SharingDenyNone; + DesiredAccess &= ~0x1; + // Win98 doesn't like GENERIC_READ ?! -- get Access Denied. + // searchAttributes + SearchAttributes = SmbConstants.AttrDirectory | SmbConstants.AttrHidden | SmbConstants.AttrSystem; + // fileAttributes + FileAttributes = 0; + // openFunction + if ((flags & SmbFile.OTrunc) == SmbFile.OTrunc) + { + // truncate the file + if ((flags & SmbFile.OCreat) == SmbFile.OCreat) + { + // create it if necessary + OpenFunction = OpenFnTrunc | OpenFnCreate; + } + else + { + OpenFunction = OpenFnTrunc; + } + } + else + { + // don't truncate the file + if ((flags & SmbFile.OCreat) == SmbFile.OCreat) + { + // create it if necessary + if ((flags & SmbFile.OExcl) == SmbFile.OExcl) + { + // fail if already exists + OpenFunction = OpenFnCreate | OpenFnFailIfExists; + } + else + { + OpenFunction = OpenFnCreate | OpenFnOpen; + } + } + else + { + OpenFunction = OpenFnOpen; + } + } + } + + internal override int GetBatchLimit(byte command) + { + return command == SmbComReadAndx ? BatchLimit : 0; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(flags, dst, dstIndex); + dstIndex += 2; + WriteInt2(DesiredAccess, dst, dstIndex); + dstIndex += 2; + WriteInt2(SearchAttributes, dst, dstIndex); + dstIndex += 2; + WriteInt2(FileAttributes, dst, dstIndex); + dstIndex += 2; + CreationTime = 0; + WriteInt4(CreationTime, dst, dstIndex); + dstIndex += 4; + WriteInt2(OpenFunction, dst, dstIndex); + dstIndex += 2; + WriteInt4(AllocationSize, dst, dstIndex); + dstIndex += 4; + for (int i = 0; i < 8; i++) + { + dst[dstIndex++] = 0x00; + } + return dstIndex - start; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + if (UseUnicode) + { + dst[dstIndex++] = (byte)('\0'); + } + dstIndex += WriteString(Path, dst, dstIndex); + return dstIndex - start; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComOpenAndX[" + base.ToString() + ",flags=0x" + Hexdump.ToHexString + (flags, 2) + ",desiredAccess=0x" + Hexdump.ToHexString(DesiredAccess, 4) + ",searchAttributes=0x" + + Hexdump.ToHexString(SearchAttributes, 4) + ",fileAttributes=0x" + Hexdump.ToHexString + (FileAttributes, 4) + ",creationTime=" + Extensions.CreateDate(CreationTime + ) + ",openFunction=0x" + Hexdump.ToHexString(OpenFunction, 2) + ",allocationSize=" + + AllocationSize + ",fileName=" + Path + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComOpenAndXResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComOpenAndXResponse.cs new file mode 100644 index 0000000000..9c49d19a83 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComOpenAndXResponse.cs @@ -0,0 +1,87 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComOpenAndXResponse : AndXServerMessageBlock + { + internal int Fid; + + internal int FileAttributes; + + internal int DataSize; + + internal int GrantedAccess; + + internal int FileType; + + internal int DeviceState; + + internal int Action; + + internal int ServerFid; + + internal long LastWriteTime; + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + Fid = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + FileAttributes = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + LastWriteTime = ReadUTime(buffer, bufferIndex); + bufferIndex += 4; + DataSize = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + GrantedAccess = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + FileType = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + DeviceState = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + Action = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + ServerFid = ReadInt4(buffer, bufferIndex); + bufferIndex += 6; + return bufferIndex - start; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComOpenAndXResponse[" + base.ToString() + ",fid=" + Fid + ",fileAttributes=" + + FileAttributes + ",lastWriteTime=" + LastWriteTime + ",dataSize=" + DataSize + + ",grantedAccess=" + GrantedAccess + ",fileType=" + FileType + ",deviceState=" + + DeviceState + ",action=" + Action + ",serverFid=" + ServerFid + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComQueryInformation.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComQueryInformation.cs new file mode 100644 index 0000000000..a528dbb111 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComQueryInformation.cs @@ -0,0 +1,57 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComQueryInformation : ServerMessageBlock + { + internal SmbComQueryInformation(string filename) + { + Path = filename; + Command = SmbComQueryInformation; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + dst[dstIndex++] = 0x04; + dstIndex += WriteString(Path, dst, dstIndex); + return dstIndex - start; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComQueryInformation[" + base.ToString() + ",filename=" + Path + + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComQueryInformationResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComQueryInformationResponse.cs new file mode 100644 index 0000000000..040f081f04 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComQueryInformationResponse.cs @@ -0,0 +1,95 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal class SmbComQueryInformationResponse : ServerMessageBlock, IInfo + { + private int _fileAttributes = 0x0000; + + private long _lastWriteTime; + + private long _serverTimeZoneOffset; + + private int _fileSize; + + internal SmbComQueryInformationResponse(long serverTimeZoneOffset) + { + this._serverTimeZoneOffset = serverTimeZoneOffset; + Command = SmbComQueryInformation; + } + + public virtual int GetAttributes() + { + return _fileAttributes; + } + + public virtual long GetCreateTime() + { + return _lastWriteTime + _serverTimeZoneOffset; + } + + public virtual long GetLastWriteTime() + { + return _lastWriteTime + _serverTimeZoneOffset; + } + + public virtual long GetSize() + { + return _fileSize; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + if (WordCount == 0) + { + return 0; + } + _fileAttributes = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + _lastWriteTime = ReadUTime(buffer, bufferIndex); + bufferIndex += 4; + _fileSize = ReadInt4(buffer, bufferIndex); + return 20; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComQueryInformationResponse[" + base.ToString() + ",fileAttributes=0x" + + Hexdump.ToHexString(_fileAttributes, 4) + ",lastWriteTime=" + Extensions.CreateDate + (_lastWriteTime) + ",fileSize=" + _fileSize + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComReadAndX.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComReadAndX.cs new file mode 100644 index 0000000000..e751797006 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComReadAndX.cs @@ -0,0 +1,107 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComReadAndX : AndXServerMessageBlock + { + private static readonly int BatchLimit = Config.GetInt("jcifs.smb.client.ReadAndX.Close" + , 1); + + private long _offset; + + private int _fid; + + private int _openTimeout; + + internal int MaxCount; + + internal int MinCount; + + internal int Remaining; + + public SmbComReadAndX() : base(null) + { + Command = SmbComReadAndx; + _openTimeout = unchecked((int)(0xFFFFFFFF)); + } + + internal SmbComReadAndX(int fid, long offset, int maxCount, ServerMessageBlock andx + ) : base(andx) + { + this._fid = fid; + this._offset = offset; + this.MaxCount = MinCount = maxCount; + Command = SmbComReadAndx; + _openTimeout = unchecked((int)(0xFFFFFFFF)); + } + + internal virtual void SetParam(int fid, long offset, int maxCount) + { + this._fid = fid; + this._offset = offset; + this.MaxCount = MinCount = maxCount; + } + + internal override int GetBatchLimit(byte command) + { + return command == SmbComClose ? BatchLimit : 0; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(_fid, dst, dstIndex); + dstIndex += 2; + WriteInt4(_offset, dst, dstIndex); + dstIndex += 4; + WriteInt2(MaxCount, dst, dstIndex); + dstIndex += 2; + WriteInt2(MinCount, dst, dstIndex); + dstIndex += 2; + WriteInt4(_openTimeout, dst, dstIndex); + dstIndex += 4; + WriteInt2(Remaining, dst, dstIndex); + dstIndex += 2; + WriteInt4(_offset >> 32, dst, dstIndex); + dstIndex += 4; + return dstIndex - start; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComReadAndX[" + base.ToString() + ",fid=" + _fid + ",offset=" + + _offset + ",maxCount=" + MaxCount + ",minCount=" + MinCount + ",openTimeout=" + + _openTimeout + ",remaining=" + Remaining + ",offset=" + _offset + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComReadAndXResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComReadAndXResponse.cs new file mode 100644 index 0000000000..4d857aa2c3 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComReadAndXResponse.cs @@ -0,0 +1,87 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComReadAndXResponse : AndXServerMessageBlock + { + internal byte[] B; + + internal int Off; + + internal int DataCompactionMode; + + internal int DataLength; + + internal int DataOffset; + + public SmbComReadAndXResponse() + { + } + + internal SmbComReadAndXResponse(byte[] b, int off) + { + this.B = b; + this.Off = off; + } + + internal virtual void SetParam(byte[] b, int off) + { + this.B = b; + this.Off = off; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + bufferIndex += 2; + // reserved + DataCompactionMode = ReadInt2(buffer, bufferIndex); + bufferIndex += 4; + // 2 reserved + DataLength = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + DataOffset = ReadInt2(buffer, bufferIndex); + bufferIndex += 12; + // 10 reserved + return bufferIndex - start; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + // handled special in SmbTransport.doRecv() + return 0; + } + + public override string ToString() + { + return "SmbComReadAndXResponse[" + base.ToString() + ",dataCompactionMode=" + + DataCompactionMode + ",dataLength=" + DataLength + ",dataOffset=" + DataOffset + + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComRename.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComRename.cs new file mode 100644 index 0000000000..0ac57dd3e4 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComRename.cs @@ -0,0 +1,75 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; + +namespace SharpCifs.Smb +{ + internal class SmbComRename : ServerMessageBlock + { + private int _searchAttributes; + + private string _oldFileName; + + private string _newFileName; + + internal SmbComRename(string oldFileName, string newFileName) + { + Command = SmbComRename; + this._oldFileName = oldFileName; + this._newFileName = newFileName; + _searchAttributes = SmbConstants.AttrHidden | SmbConstants.AttrSystem | SmbConstants.AttrDirectory; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + WriteInt2(_searchAttributes, dst, dstIndex); + return 2; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + dst[dstIndex++] = unchecked(unchecked(0x04)); + dstIndex += WriteString(_oldFileName, dst, dstIndex); + dst[dstIndex++] = unchecked(unchecked(0x04)); + if (UseUnicode) + { + dst[dstIndex++] = unchecked((byte)('\0')); + } + dstIndex += WriteString(_newFileName, dst, dstIndex); + return dstIndex - start; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComRename[" + base.ToString() + ",searchAttributes=0x" + Hexdump + .ToHexString(_searchAttributes, 4) + ",oldFileName=" + _oldFileName + ",newFileName=" + + _newFileName + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComSessionSetupAndX.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComSessionSetupAndX.cs new file mode 100644 index 0000000000..a1642391ca --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComSessionSetupAndX.cs @@ -0,0 +1,234 @@ +// This code is derived from jcifs smb client library +// +// 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 +// +// Ported to C# by J. Arturo +using System; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal class SmbComSessionSetupAndX : AndXServerMessageBlock + { + private static readonly int BatchLimit = Config.GetInt("jcifs.smb.client.SessionSetupAndX.TreeConnectAndX" + , 1); + + private static readonly bool DisablePlainTextPasswords = Config.GetBoolean("jcifs.smb.client.disablePlainTextPasswords" + , true); + + private byte[] _lmHash; + + private byte[] _ntHash; + + private byte[] _blob; + + private int _sessionKey; + + private int _capabilities; + + private string _accountName; + + private string _primaryDomain; + + internal SmbSession Session; + + internal object Cred; + + /// + internal SmbComSessionSetupAndX(SmbSession session, ServerMessageBlock andx, object + cred) : base(andx) + { + Command = SmbComSessionSetupAndx; + this.Session = session; + this.Cred = cred; + _sessionKey = session.transport.SessionKey; + _capabilities = session.transport.Capabilities; + if (session.transport.Server.Security == SmbConstants.SecurityUser) + { + if (cred is NtlmPasswordAuthentication) + { + NtlmPasswordAuthentication auth = (NtlmPasswordAuthentication)cred; + if (auth == NtlmPasswordAuthentication.Anonymous) + { + _lmHash = new byte[0]; + _ntHash = new byte[0]; + _capabilities &= ~SmbConstants.CapExtendedSecurity; + } + else + { + if (session.transport.Server.EncryptedPasswords) + { + _lmHash = auth.GetAnsiHash(session.transport.Server.EncryptionKey); + _ntHash = auth.GetUnicodeHash(session.transport.Server.EncryptionKey); + // prohibit HTTP auth attempts for the null session + if (_lmHash.Length == 0 && _ntHash.Length == 0) + { + throw new RuntimeException("Null setup prohibited."); + } + } + else + { + if (DisablePlainTextPasswords) + { + throw new RuntimeException("Plain text passwords are disabled"); + } + if (UseUnicode) + { + // plain text + string password = auth.GetPassword(); + _lmHash = new byte[0]; + _ntHash = new byte[(password.Length + 1) * 2]; + WriteString(password, _ntHash, 0); + } + else + { + // plain text + string password = auth.GetPassword(); + _lmHash = new byte[(password.Length + 1) * 2]; + _ntHash = new byte[0]; + WriteString(password, _lmHash, 0); + } + } + } + _accountName = auth.Username; + if (UseUnicode) + { + _accountName = _accountName.ToUpper(); + } + _primaryDomain = auth.Domain.ToUpper(); + } + else + { + if (cred is byte[]) + { + _blob = (byte[])cred; + } + else + { + throw new SmbException("Unsupported credential type"); + } + } + } + else + { + if (session.transport.Server.Security == SmbConstants.SecurityShare) + { + if (cred is NtlmPasswordAuthentication) + { + NtlmPasswordAuthentication auth = (NtlmPasswordAuthentication)cred; + _lmHash = new byte[0]; + _ntHash = new byte[0]; + _accountName = auth.Username; + if (UseUnicode) + { + _accountName = _accountName.ToUpper(); + } + _primaryDomain = auth.Domain.ToUpper(); + } + else + { + throw new SmbException("Unsupported credential type"); + } + } + else + { + throw new SmbException("Unsupported"); + } + } + } + + internal override int GetBatchLimit(byte command) + { + return command == SmbComTreeConnectAndx ? BatchLimit : 0; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(Session.transport.SndBufSize, dst, dstIndex); + dstIndex += 2; + WriteInt2(Session.transport.MaxMpxCount, dst, dstIndex); + dstIndex += 2; + WriteInt2(SmbConstants.VcNumber, dst, dstIndex); + dstIndex += 2; + WriteInt4(_sessionKey, dst, dstIndex); + dstIndex += 4; + if (_blob != null) + { + WriteInt2(_blob.Length, dst, dstIndex); + dstIndex += 2; + } + else + { + WriteInt2(_lmHash.Length, dst, dstIndex); + dstIndex += 2; + WriteInt2(_ntHash.Length, dst, dstIndex); + dstIndex += 2; + } + dst[dstIndex++] = unchecked(unchecked(0x00)); + dst[dstIndex++] = unchecked(unchecked(0x00)); + dst[dstIndex++] = unchecked(unchecked(0x00)); + dst[dstIndex++] = unchecked(unchecked(0x00)); + WriteInt4(_capabilities, dst, dstIndex); + dstIndex += 4; + return dstIndex - start; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + if (_blob != null) + { + Array.Copy(_blob, 0, dst, dstIndex, _blob.Length); + dstIndex += _blob.Length; + } + else + { + Array.Copy(_lmHash, 0, dst, dstIndex, _lmHash.Length); + dstIndex += _lmHash.Length; + Array.Copy(_ntHash, 0, dst, dstIndex, _ntHash.Length); + dstIndex += _ntHash.Length; + dstIndex += WriteString(_accountName, dst, dstIndex); + dstIndex += WriteString(_primaryDomain, dst, dstIndex); + } + dstIndex += WriteString(SmbConstants.NativeOs, dst, dstIndex); + dstIndex += WriteString(SmbConstants.NativeLanman, dst, dstIndex); + return dstIndex - start; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + string result = "SmbComSessionSetupAndX[" + base.ToString() + ",snd_buf_size=" + + Session.transport.SndBufSize + ",maxMpxCount=" + Session.transport.MaxMpxCount + + ",VC_NUMBER=" + SmbConstants.VcNumber + ",sessionKey=" + _sessionKey + ",lmHash.length=" + + (_lmHash == null ? 0 : _lmHash.Length) + ",ntHash.length=" + (_ntHash == null ? + 0 : _ntHash.Length) + ",capabilities=" + _capabilities + ",accountName=" + _accountName + + ",primaryDomain=" + _primaryDomain + ",NATIVE_OS=" + SmbConstants.NativeOs + + ",NATIVE_LANMAN=" + SmbConstants.NativeLanman + "]"; + return result; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComSessionSetupAndXResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComSessionSetupAndXResponse.cs new file mode 100644 index 0000000000..a3b80a669a --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComSessionSetupAndXResponse.cs @@ -0,0 +1,92 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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; + +namespace SharpCifs.Smb +{ + internal class SmbComSessionSetupAndXResponse : AndXServerMessageBlock + { + private string _nativeOs = string.Empty; + + private string _nativeLanMan = string.Empty; + + private string _primaryDomain = string.Empty; + + internal bool IsLoggedInAsGuest; + + internal byte[] Blob; + + internal SmbComSessionSetupAndXResponse(ServerMessageBlock andx) : base(andx) + { + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + IsLoggedInAsGuest = (buffer[bufferIndex] & 0x01) == 0x01 ? true : false; + bufferIndex += 2; + if (ExtendedSecurity) + { + int blobLength = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + Blob = new byte[blobLength]; + } + return bufferIndex - start; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + int start = bufferIndex; + if (ExtendedSecurity) + { + Array.Copy(buffer, bufferIndex, Blob, 0, Blob.Length); + bufferIndex += Blob.Length; + } + _nativeOs = ReadString(buffer, bufferIndex); + bufferIndex += StringWireLength(_nativeOs, bufferIndex); + _nativeLanMan = ReadString(buffer, bufferIndex, start + ByteCount, 255, UseUnicode + ); + bufferIndex += StringWireLength(_nativeLanMan, bufferIndex); + if (!ExtendedSecurity) + { + _primaryDomain = ReadString(buffer, bufferIndex, start + ByteCount, 255, UseUnicode + ); + bufferIndex += StringWireLength(_primaryDomain, bufferIndex); + } + return bufferIndex - start; + } + + public override string ToString() + { + string result = "SmbComSessionSetupAndXResponse[" + base.ToString() + + ",isLoggedInAsGuest=" + IsLoggedInAsGuest + ",nativeOs=" + _nativeOs + ",nativeLanMan=" + + _nativeLanMan + ",primaryDomain=" + _primaryDomain + "]"; + return result; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTransaction.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTransaction.cs new file mode 100644 index 0000000000..b3aeaaf7d0 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTransaction.cs @@ -0,0 +1,346 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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; + +namespace SharpCifs.Smb +{ + internal abstract class SmbComTransaction : ServerMessageBlock + { + private static readonly int DefaultMaxDataCount = Config.GetInt("jcifs.smb.client.transaction_buf_size" + , TransactionBufSize) - 512; + + private const int PrimarySetupOffset = 61; + + private const int SecondaryParameterOffset = 51; + + private const int DisconnectTid = unchecked(0x01); + + private const int OneWayTransaction = unchecked(0x02); + + private const int PaddingSize = 2; + + private int _flags = unchecked(0x00); + + private int _fid; + + private int _pad; + + private int _pad1; + + private bool _hasMore = true; + + private bool _isPrimary = true; + + private int _bufParameterOffset; + + private int _bufDataOffset; + + internal const int TransactionBufSize = unchecked(0xFFFF); + + internal const byte Trans2FindFirst2 = unchecked(unchecked(0x01)); + + internal const byte Trans2FindNext2 = unchecked(unchecked(0x02)); + + internal const byte Trans2QueryFsInformation = unchecked(unchecked(0x03)); + + internal const byte Trans2QueryPathInformation = unchecked(unchecked(0x05)); + + internal const byte Trans2GetDfsReferral = unchecked(unchecked(0x10)); + + internal const byte Trans2SetFileInformation = unchecked(unchecked(0x08)); + + internal const int NetShareEnum = unchecked(0x0000); + + internal const int NetServerEnum2 = unchecked(0x0068); + + internal const int NetServerEnum3 = unchecked(0x00D7); + + internal const byte TransPeekNamedPipe = unchecked(unchecked(0x23 + )); + + internal const byte TransWaitNamedPipe = unchecked(unchecked(0x53 + )); + + internal const byte TransCallNamedPipe = unchecked(unchecked(0x54 + )); + + internal const byte TransTransactNamedPipe = unchecked(unchecked(0x26)); + + protected internal int primarySetupOffset; + + protected internal int secondaryParameterOffset; + + protected internal int ParameterCount; + + protected internal int ParameterOffset; + + protected internal int ParameterDisplacement; + + protected internal int DataCount; + + protected internal int DataOffset; + + protected internal int DataDisplacement; + + internal int TotalParameterCount; + + internal int TotalDataCount; + + internal int MaxParameterCount; + + internal int MaxDataCount = DefaultMaxDataCount; + + internal byte MaxSetupCount; + + internal int Timeout = 0; + + internal int SetupCount = 1; + + internal byte SubCommand; + + internal string Name = string.Empty; + + internal int MaxBufferSize; + + internal byte[] TxnBuf; + + public SmbComTransaction() + { + // relative to headerStart + // set in SmbTransport.sendTransaction() before nextElement called + MaxParameterCount = 1024; + primarySetupOffset = PrimarySetupOffset; + secondaryParameterOffset = SecondaryParameterOffset; + } + + internal override void Reset() + { + base.Reset(); + _isPrimary = _hasMore = true; + } + + internal virtual void Reset(int key, string lastName) + { + Reset(); + } + + public virtual bool MoveNext() + { + return _hasMore; + } + + public virtual object Current() + { + if (_isPrimary) + { + _isPrimary = false; + ParameterOffset = primarySetupOffset + (SetupCount * 2) + 2; + if (Command != SmbComNtTransact) + { + if (Command == SmbComTransaction && IsResponse() == false) + { + ParameterOffset += StringWireLength(Name, ParameterOffset); + } + } + else + { + if (Command == SmbComNtTransact) + { + ParameterOffset += 2; + } + } + _pad = ParameterOffset % PaddingSize; + _pad = _pad == 0 ? 0 : PaddingSize - _pad; + ParameterOffset += _pad; + TotalParameterCount = WriteParametersWireFormat(TxnBuf, _bufParameterOffset); + _bufDataOffset = TotalParameterCount; + // data comes right after data + int available = MaxBufferSize - ParameterOffset; + ParameterCount = Math.Min(TotalParameterCount, available); + available -= ParameterCount; + DataOffset = ParameterOffset + ParameterCount; + _pad1 = DataOffset % PaddingSize; + _pad1 = _pad1 == 0 ? 0 : PaddingSize - _pad1; + DataOffset += _pad1; + TotalDataCount = WriteDataWireFormat(TxnBuf, _bufDataOffset); + DataCount = Math.Min(TotalDataCount, available); + } + else + { + if (Command != SmbComNtTransact) + { + Command = SmbComTransactionSecondary; + } + else + { + Command = SmbComNtTransactSecondary; + } + // totalParameterCount and totalDataCount are set ok from primary + ParameterOffset = SecondaryParameterOffset; + if ((TotalParameterCount - ParameterDisplacement) > 0) + { + _pad = ParameterOffset % PaddingSize; + _pad = _pad == 0 ? 0 : PaddingSize - _pad; + ParameterOffset += _pad; + } + // caclulate parameterDisplacement before calculating new parameterCount + ParameterDisplacement += ParameterCount; + int available = MaxBufferSize - ParameterOffset - _pad; + ParameterCount = Math.Min(TotalParameterCount - ParameterDisplacement, available); + available -= ParameterCount; + DataOffset = ParameterOffset + ParameterCount; + _pad1 = DataOffset % PaddingSize; + _pad1 = _pad1 == 0 ? 0 : PaddingSize - _pad1; + DataOffset += _pad1; + DataDisplacement += DataCount; + available -= _pad1; + DataCount = Math.Min(TotalDataCount - DataDisplacement, available); + } + if ((ParameterDisplacement + ParameterCount) >= TotalParameterCount && (DataDisplacement + + DataCount) >= TotalDataCount) + { + _hasMore = false; + } + return this; + + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(TotalParameterCount, dst, dstIndex); + dstIndex += 2; + WriteInt2(TotalDataCount, dst, dstIndex); + dstIndex += 2; + if (Command != SmbComTransactionSecondary) + { + WriteInt2(MaxParameterCount, dst, dstIndex); + dstIndex += 2; + WriteInt2(MaxDataCount, dst, dstIndex); + dstIndex += 2; + dst[dstIndex++] = MaxSetupCount; + dst[dstIndex++] = unchecked(unchecked(0x00)); + // Reserved1 + WriteInt2(_flags, dst, dstIndex); + dstIndex += 2; + WriteInt4(Timeout, dst, dstIndex); + dstIndex += 4; + dst[dstIndex++] = unchecked(unchecked(0x00)); + // Reserved2 + dst[dstIndex++] = unchecked(unchecked(0x00)); + } + WriteInt2(ParameterCount, dst, dstIndex); + dstIndex += 2; + // writeInt2(( parameterCount == 0 ? 0 : parameterOffset ), dst, dstIndex ); + WriteInt2(ParameterOffset, dst, dstIndex); + dstIndex += 2; + if (Command == SmbComTransactionSecondary) + { + WriteInt2(ParameterDisplacement, dst, dstIndex); + dstIndex += 2; + } + WriteInt2(DataCount, dst, dstIndex); + dstIndex += 2; + WriteInt2((DataCount == 0 ? 0 : DataOffset), dst, dstIndex); + dstIndex += 2; + if (Command == SmbComTransactionSecondary) + { + WriteInt2(DataDisplacement, dst, dstIndex); + dstIndex += 2; + } + else + { + dst[dstIndex++] = unchecked((byte)SetupCount); + dst[dstIndex++] = unchecked(unchecked(0x00)); + // Reserved3 + dstIndex += WriteSetupWireFormat(dst, dstIndex); + } + return dstIndex - start; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + int p = _pad; + if (Command == SmbComTransaction && IsResponse() == false) + { + dstIndex += WriteString(Name, dst, dstIndex); + } + if (ParameterCount > 0) + { + while (p-- > 0) + { + dst[dstIndex++] = unchecked(unchecked(0x00)); + } + // Pad + Array.Copy(TxnBuf, _bufParameterOffset, dst, dstIndex, ParameterCount); + dstIndex += ParameterCount; + } + if (DataCount > 0) + { + p = _pad1; + while (p-- > 0) + { + dst[dstIndex++] = unchecked(unchecked(0x00)); + } + // Pad1 + Array.Copy(TxnBuf, _bufDataOffset, dst, dstIndex, DataCount); + _bufDataOffset += DataCount; + dstIndex += DataCount; + } + return dstIndex - start; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + internal abstract int WriteSetupWireFormat(byte[] dst, int dstIndex); + + internal abstract int WriteParametersWireFormat(byte[] dst, int dstIndex); + + internal abstract int WriteDataWireFormat(byte[] dst, int dstIndex); + + internal abstract int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ); + + internal abstract int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len); + + internal abstract int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len); + + public override string ToString() + { + return base.ToString() + ",totalParameterCount=" + TotalParameterCount + + ",totalDataCount=" + TotalDataCount + ",maxParameterCount=" + MaxParameterCount + + ",maxDataCount=" + MaxDataCount + ",maxSetupCount=" + (int)MaxSetupCount + ",flags=0x" + + Hexdump.ToHexString(_flags, 2) + ",timeout=" + Timeout + ",parameterCount=" + + ParameterCount + ",parameterOffset=" + ParameterOffset + ",parameterDisplacement=" + + ParameterDisplacement + ",dataCount=" + DataCount + ",dataOffset=" + DataOffset + + ",dataDisplacement=" + DataDisplacement + ",setupCount=" + SetupCount + ",pad=" + + _pad + ",pad1=" + _pad1; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTransactionResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTransactionResponse.cs new file mode 100644 index 0000000000..35f87594d6 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTransactionResponse.cs @@ -0,0 +1,206 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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; + +namespace SharpCifs.Smb +{ + internal abstract class SmbComTransactionResponse : ServerMessageBlock + { + private const int SetupOffset = 61; + + private const int DisconnectTid = unchecked(0x01); + + private const int OneWayTransaction = unchecked(0x02); + + private int _pad; + + private int _pad1; + + private bool _parametersDone; + + private bool _dataDone; + + protected internal int TotalParameterCount; + + protected internal int TotalDataCount; + + protected internal int ParameterCount; + + protected internal int ParameterOffset; + + protected internal int ParameterDisplacement; + + protected internal int DataOffset; + + protected internal int DataDisplacement; + + protected internal int SetupCount; + + protected internal int BufParameterStart; + + protected internal int BufDataStart; + + internal int DataCount; + + internal byte SubCommand; + + internal bool HasMore = true; + + internal bool IsPrimary = true; + + internal byte[] TxnBuf; + + internal int Status; + + internal int NumEntries; + + internal IFileEntry[] Results; + + public SmbComTransactionResponse() + { + // relative to headerStart + TxnBuf = null; + } + + internal override void Reset() + { + base.Reset(); + BufDataStart = 0; + IsPrimary = HasMore = true; + _parametersDone = _dataDone = false; + } + + public virtual bool MoveNext() + { + return ErrorCode == 0 && HasMore; + } + + public virtual object Current() + { + if (IsPrimary) + { + IsPrimary = false; + } + return this; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + TotalParameterCount = ReadInt2(buffer, bufferIndex); + if (BufDataStart == 0) + { + BufDataStart = TotalParameterCount; + } + bufferIndex += 2; + TotalDataCount = ReadInt2(buffer, bufferIndex); + bufferIndex += 4; + // Reserved + ParameterCount = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + ParameterOffset = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + ParameterDisplacement = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + DataCount = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + DataOffset = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + DataDisplacement = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + SetupCount = buffer[bufferIndex] & unchecked(0xFF); + bufferIndex += 2; + if (SetupCount != 0) + { + if (Log.Level > 2) + { + Log.WriteLine("setupCount is not zero: " + SetupCount); + } + } + return bufferIndex - start; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + _pad = _pad1 = 0; + int n; + if (ParameterCount > 0) + { + bufferIndex += _pad = ParameterOffset - (bufferIndex - HeaderStart); + Array.Copy(buffer, bufferIndex, TxnBuf, BufParameterStart + ParameterDisplacement + , ParameterCount); + bufferIndex += ParameterCount; + } + if (DataCount > 0) + { + bufferIndex += _pad1 = DataOffset - (bufferIndex - HeaderStart); + Array.Copy(buffer, bufferIndex, TxnBuf, BufDataStart + DataDisplacement, + DataCount); + bufferIndex += DataCount; + } + if (!_parametersDone && (ParameterDisplacement + ParameterCount) == TotalParameterCount) + { + _parametersDone = true; + } + if (!_dataDone && (DataDisplacement + DataCount) == TotalDataCount) + { + _dataDone = true; + } + if (_parametersDone && _dataDone) + { + HasMore = false; + ReadParametersWireFormat(TxnBuf, BufParameterStart, TotalParameterCount); + ReadDataWireFormat(TxnBuf, BufDataStart, TotalDataCount); + } + return _pad + ParameterCount + _pad1 + DataCount; + } + + internal abstract int WriteSetupWireFormat(byte[] dst, int dstIndex); + + internal abstract int WriteParametersWireFormat(byte[] dst, int dstIndex); + + internal abstract int WriteDataWireFormat(byte[] dst, int dstIndex); + + internal abstract int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ); + + internal abstract int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len); + + internal abstract int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len); + + public override string ToString() + { + return base.ToString() + ",totalParameterCount=" + TotalParameterCount + + ",totalDataCount=" + TotalDataCount + ",parameterCount=" + ParameterCount + ",parameterOffset=" + + ParameterOffset + ",parameterDisplacement=" + ParameterDisplacement + ",dataCount=" + + DataCount + ",dataOffset=" + DataOffset + ",dataDisplacement=" + DataDisplacement + + ",setupCount=" + SetupCount + ",pad=" + _pad + ",pad1=" + _pad1; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTreeConnectAndX.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTreeConnectAndX.cs new file mode 100644 index 0000000000..67ad04f5f6 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTreeConnectAndX.cs @@ -0,0 +1,226 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +{ + internal class SmbComTreeConnectAndX : AndXServerMessageBlock + { + private static readonly bool DisablePlainTextPasswords = Config.GetBoolean("jcifs.smb.client.disablePlainTextPasswords" + , true); + + private SmbSession _session; + + private bool _disconnectTid = false; + + private string _service; + + private byte[] _password; + + private int _passwordLength; + + internal string path; + + private static byte[] _batchLimits = { 1, 1, 1, 1, 1, 1, 1, 1, 0 }; + + static SmbComTreeConnectAndX() + { + string s; + if ((s = Config.GetProperty("jcifs.smb.client.TreeConnectAndX.CheckDirectory")) != + null) + { + _batchLimits[0] = byte.Parse(s); + } + if ((s = Config.GetProperty("jcifs.smb.client.TreeConnectAndX.CreateDirectory")) + != null) + { + _batchLimits[2] = byte.Parse(s); + } + if ((s = Config.GetProperty("jcifs.smb.client.TreeConnectAndX.Delete")) != null) + { + _batchLimits[3] = byte.Parse(s); + } + if ((s = Config.GetProperty("jcifs.smb.client.TreeConnectAndX.DeleteDirectory")) + != null) + { + _batchLimits[4] = byte.Parse(s); + } + if ((s = Config.GetProperty("jcifs.smb.client.TreeConnectAndX.OpenAndX")) != null) + { + _batchLimits[5] = byte.Parse(s); + } + if ((s = Config.GetProperty("jcifs.smb.client.TreeConnectAndX.Rename")) != null) + { + _batchLimits[6] = byte.Parse(s); + } + if ((s = Config.GetProperty("jcifs.smb.client.TreeConnectAndX.Transaction")) != null) + { + _batchLimits[7] = byte.Parse(s); + } + if ((s = Config.GetProperty("jcifs.smb.client.TreeConnectAndX.QueryInformation")) + != null) + { + _batchLimits[8] = byte.Parse(s); + } + } + + internal SmbComTreeConnectAndX(SmbSession session, string path, string service, ServerMessageBlock + andx) : base(andx) + { + this._session = session; + this.path = path; + this._service = service; + Command = SmbComTreeConnectAndx; + } + + internal override int GetBatchLimit(byte command) + { + int c = command & unchecked(0xFF); + switch (c) + { + case SmbComCheckDirectory: + { + // why isn't this just return batchLimits[c]? + return _batchLimits[0]; + } + + case SmbComCreateDirectory: + { + return _batchLimits[2]; + } + + case SmbComDelete: + { + return _batchLimits[3]; + } + + case SmbComDeleteDirectory: + { + return _batchLimits[4]; + } + + case SmbComOpenAndx: + { + return _batchLimits[5]; + } + + case SmbComRename: + { + return _batchLimits[6]; + } + + case SmbComTransaction: + { + return _batchLimits[7]; + } + + case SmbComQueryInformation: + { + return _batchLimits[8]; + } + } + return 0; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + if (_session.transport.Server.Security == SmbConstants.SecurityShare && (_session.Auth.HashesExternal + || _session.Auth.Password.Length > 0)) + { + if (_session.transport.Server.EncryptedPasswords) + { + // encrypted + _password = _session.Auth.GetAnsiHash(_session.transport.Server.EncryptionKey); + _passwordLength = _password.Length; + } + else + { + if (DisablePlainTextPasswords) + { + throw new RuntimeException("Plain text passwords are disabled"); + } + // plain text + _password = new byte[(_session.Auth.Password.Length + 1) * 2]; + _passwordLength = WriteString(_session.Auth.Password, _password, 0); + } + } + else + { + // no password in tree connect + _passwordLength = 1; + } + dst[dstIndex++] = _disconnectTid ? unchecked((byte)unchecked(0x01)) : unchecked( + (byte)unchecked(0x00)); + dst[dstIndex++] = unchecked(unchecked(0x00)); + WriteInt2(_passwordLength, dst, dstIndex); + return 4; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + if (_session.transport.Server.Security == SmbConstants.SecurityShare && (_session.Auth.HashesExternal + || _session.Auth.Password.Length > 0)) + { + Array.Copy(_password, 0, dst, dstIndex, _passwordLength); + dstIndex += _passwordLength; + } + else + { + // no password in tree connect + dst[dstIndex++] = unchecked(unchecked(0x00)); + } + dstIndex += WriteString(path, dst, dstIndex); + try + { +// Array.Copy(Runtime.GetBytesForString(_service, "ASCII"), 0, dst, dstIndex + //, _service.Length); + Array.Copy(Runtime.GetBytesForString(_service, "UTF-8"), 0, dst, dstIndex + , _service.Length); + } + catch (UnsupportedEncodingException) + { + return 0; + } + dstIndex += _service.Length; + dst[dstIndex++] = unchecked((byte)('\0')); + return dstIndex - start; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + string result = "SmbComTreeConnectAndX[" + base.ToString() + ",disconnectTid=" + + _disconnectTid + ",passwordLength=" + _passwordLength + ",password=" + Hexdump. + ToHexString(_password, _passwordLength, 0) + ",path=" + path + ",service=" + _service + + "]"; + return result; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTreeConnectAndXResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTreeConnectAndXResponse.cs new file mode 100644 index 0000000000..add660b266 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTreeConnectAndXResponse.cs @@ -0,0 +1,84 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal class SmbComTreeConnectAndXResponse : AndXServerMessageBlock + { + private const int SmbSupportSearchBits = unchecked(0x0001); + + private const int SmbShareIsInDfs = unchecked(0x0002); + + internal bool SupportSearchBits; + + internal bool ShareIsInDfs; + + internal string Service; + + internal string NativeFileSystem = string.Empty; + + internal SmbComTreeConnectAndXResponse(ServerMessageBlock andx) : base(andx) + { + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + SupportSearchBits = (buffer[bufferIndex] & SmbSupportSearchBits) == SmbSupportSearchBits; + ShareIsInDfs = (buffer[bufferIndex] & SmbShareIsInDfs) == SmbShareIsInDfs; + return 2; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + int start = bufferIndex; + int len = ReadStringLength(buffer, bufferIndex, 32); + try + { + //Service = Runtime.GetStringForBytes(buffer, bufferIndex, len, "ASCII"); + Service = Runtime.GetStringForBytes(buffer, bufferIndex, len, "UTF-8"); + } + catch (UnsupportedEncodingException) + { + return 0; + } + bufferIndex += len + 1; + // win98 observed not returning nativeFileSystem + return bufferIndex - start; + } + + public override string ToString() + { + string result = "SmbComTreeConnectAndXResponse[" + base.ToString() + ",supportSearchBits=" + + SupportSearchBits + ",shareIsInDfs=" + ShareIsInDfs + ",service=" + Service + + ",nativeFileSystem=" + NativeFileSystem + "]"; + return result; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTreeDisconnect.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTreeDisconnect.cs new file mode 100644 index 0000000000..d9eb5b2ebe --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComTreeDisconnect.cs @@ -0,0 +1,52 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComTreeDisconnect : ServerMessageBlock + { + public SmbComTreeDisconnect() + { + Command = SmbComTreeDisconnect; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComTreeDisconnect[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComWrite.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComWrite.cs new file mode 100644 index 0000000000..418a69d1d3 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComWrite.cs @@ -0,0 +1,106 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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; + +namespace SharpCifs.Smb +{ + internal class SmbComWrite : ServerMessageBlock + { + private int _fid; + + private int _count; + + private int _offset; + + private int _remaining; + + private int _off; + + private byte[] _b; + + public SmbComWrite() + { + Command = SmbComWrite; + } + + internal SmbComWrite(int fid, int offset, int remaining, byte[] b, int off, int len + ) + { + this._fid = fid; + _count = len; + this._offset = offset; + this._remaining = remaining; + this._b = b; + this._off = off; + Command = SmbComWrite; + } + + internal virtual void SetParam(int fid, long offset, int remaining, byte[] b, int + off, int len) + { + this._fid = fid; + this._offset = (int)(offset & unchecked(0xFFFFFFFFL)); + this._remaining = remaining; + this._b = b; + this._off = off; + _count = len; + Digest = null; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(_fid, dst, dstIndex); + dstIndex += 2; + WriteInt2(_count, dst, dstIndex); + dstIndex += 2; + WriteInt4(_offset, dst, dstIndex); + dstIndex += 4; + WriteInt2(_remaining, dst, dstIndex); + dstIndex += 2; + return dstIndex - start; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + dst[dstIndex++] = 0x01; + WriteInt2(_count, dst, dstIndex); + dstIndex += 2; + Array.Copy(_b, _off, dst, dstIndex, _count); + dstIndex += _count; + return dstIndex - start; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComWrite[" + base.ToString() + ",fid=" + _fid + ",count=" + + _count + ",offset=" + _offset + ",remaining=" + _remaining + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComWriteAndX.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComWriteAndX.cs new file mode 100644 index 0000000000..b182fd7ffd --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComWriteAndX.cs @@ -0,0 +1,150 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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; + +namespace SharpCifs.Smb +{ + internal class SmbComWriteAndX : AndXServerMessageBlock + { + private static readonly int ReadAndxBatchLimit = Config.GetInt("jcifs.smb.client.WriteAndX.ReadAndX" + , 1); + + private static readonly int CloseBatchLimit = Config.GetInt("jcifs.smb.client.WriteAndX.Close" + , 1); + + private int _fid; + + private int _remaining; + + private int _dataLength; + + private int _dataOffset; + + private int _off; + + private byte[] _b; + + private long _offset; + + private int _pad; + + internal int WriteMode; + + public SmbComWriteAndX() : base(null) + { + Command = SmbComWriteAndx; + } + + internal SmbComWriteAndX(int fid, long offset, int remaining, byte[] b, int off, + int len, ServerMessageBlock andx) : base(andx) + { + this._fid = fid; + this._offset = offset; + this._remaining = remaining; + this._b = b; + this._off = off; + _dataLength = len; + Command = SmbComWriteAndx; + } + + internal virtual void SetParam(int fid, long offset, int remaining, byte[] b, int + off, int len) + { + this._fid = fid; + this._offset = offset; + this._remaining = remaining; + this._b = b; + this._off = off; + _dataLength = len; + Digest = null; + } + + internal override int GetBatchLimit(byte command) + { + if (command == SmbComReadAndx) + { + return ReadAndxBatchLimit; + } + if (command == SmbComClose) + { + return CloseBatchLimit; + } + return 0; + } + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + _dataOffset = (dstIndex - HeaderStart) + 26; + // 26 = off from here to pad + _pad = (_dataOffset - HeaderStart) % 4; + _pad = _pad == 0 ? 0 : 4 - _pad; + _dataOffset += _pad; + WriteInt2(_fid, dst, dstIndex); + dstIndex += 2; + WriteInt4(_offset, dst, dstIndex); + dstIndex += 4; + for (int i = 0; i < 4; i++) + { + dst[dstIndex++] = 0xFF; + } + WriteInt2(WriteMode, dst, dstIndex); + dstIndex += 2; + WriteInt2(_remaining, dst, dstIndex); + dstIndex += 2; + dst[dstIndex++] = 0x00; + dst[dstIndex++] =0x00; + WriteInt2(_dataLength, dst, dstIndex); + dstIndex += 2; + WriteInt2(_dataOffset, dst, dstIndex); + dstIndex += 2; + WriteInt4(_offset >> 32, dst, dstIndex); + dstIndex += 4; + return dstIndex - start; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + while (_pad-- > 0) + { + dst[dstIndex++] = 0xEE; + } + Array.Copy(_b, _off, dst, dstIndex, _dataLength); + dstIndex += _dataLength; + return dstIndex - start; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + return 0; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComWriteAndX[" + base.ToString() + ",fid=" + _fid + ",offset=" + + _offset + ",writeMode=" + WriteMode + ",remaining=" + _remaining + ",dataLength=" + + _dataLength + ",dataOffset=" + _dataOffset + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComWriteAndXResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComWriteAndXResponse.cs new file mode 100644 index 0000000000..c6749b6cbb --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComWriteAndXResponse.cs @@ -0,0 +1,50 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComWriteAndXResponse : AndXServerMessageBlock + { + internal long Count; + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + Count = ReadInt2(buffer, bufferIndex) & unchecked(0xFFFFL); + return 8; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComWriteAndXResponse[" + base.ToString() + ",count=" + Count + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComWriteResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComWriteResponse.cs new file mode 100644 index 0000000000..785d406c15 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbComWriteResponse.cs @@ -0,0 +1,50 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class SmbComWriteResponse : ServerMessageBlock + { + internal long Count; + + internal override int WriteParameterWordsWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteBytesWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParameterWordsWireFormat(byte[] buffer, int bufferIndex + ) + { + Count = ReadInt2(buffer, bufferIndex) & unchecked(0xFFFFL); + return 8; + } + + internal override int ReadBytesWireFormat(byte[] buffer, int bufferIndex) + { + return 0; + } + + public override string ToString() + { + return "SmbComWriteResponse[" + base.ToString() + ",count=" + Count + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbConstants.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbConstants.cs new file mode 100644 index 0000000000..0793c75415 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbConstants.cs @@ -0,0 +1,302 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.Collections.Generic; +using System.Net; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal static class SmbConstants + { + public static readonly int DefaultPort = 445; + + public static readonly int DefaultMaxMpxCount = 10; + + public static readonly int DefaultResponseTimeout = 30000; + + public static readonly int DefaultSoTimeout = 35000; + + public static readonly int DefaultRcvBufSize = 60416; + + public static readonly int DefaultSndBufSize = 16644; + + public static readonly int DefaultSsnLimit = 250; + + public static readonly int DefaultConnTimeout = 35000; + + public static readonly IPAddress Laddr = Config.GetLocalHost(); + + public static readonly int Lport = Config.GetInt("jcifs.smb.client.lport", 0); + + public static readonly int MaxMpxCount = Config.GetInt("jcifs.smb.client.maxMpxCount", DefaultMaxMpxCount + ); + + public static readonly int SndBufSize = Config.GetInt("jcifs.smb.client.snd_buf_size", DefaultSndBufSize + ); + + public static readonly int RcvBufSize = Config.GetInt("jcifs.smb.client.rcv_buf_size", DefaultRcvBufSize + ); + + public static readonly bool UseUnicode = Config.GetBoolean("jcifs.smb.client.useUnicode", + true); + + public static readonly bool ForceUnicode = Config.GetBoolean("jcifs.smb.client.useUnicode" + , false); + + public static readonly bool UseNtstatus = Config.GetBoolean("jcifs.smb.client.useNtStatus" + , true); + + public static readonly bool Signpref = Config.GetBoolean("jcifs.smb.client.signingPreferred" + , false); + + public static readonly bool UseNtsmbs = Config.GetBoolean("jcifs.smb.client.useNTSmbs", true + ); + + public static readonly bool UseExtsec = Config.GetBoolean("jcifs.smb.client.useExtendedSecurity" + , true); + + public static readonly string NetbiosHostname = Config.GetProperty("jcifs.netbios.hostname" + , null); + + public static readonly int LmCompatibility = Config.GetInt("jcifs.smb.lmCompatibility", 3); + + public static readonly int FlagsNone = unchecked(0x00); + + public static readonly int FlagsLockAndReadWriteAndUnlock = unchecked(0x01); + + public static readonly int FlagsReceiveBufferPosted = unchecked(0x02); + + public static readonly int FlagsPathNamesCaseless = unchecked(0x08); + + public static readonly int FlagsPathNamesCanonicalized = unchecked(0x10); + + public static readonly int FlagsOplockRequestedOrGranted = unchecked(0x20); + + public static readonly int FlagsNotifyOfModifyAction = unchecked(0x40); + + public static readonly int FlagsResponse = unchecked(0x80); + + public static readonly int Flags2None = unchecked(0x0000); + + public static readonly int Flags2LongFilenames = unchecked(0x0001); + + public static readonly int Flags2ExtendedAttributes = unchecked(0x0002); + + public static readonly int Flags2SecuritySignatures = unchecked(0x0004); + + public static readonly int Flags2ExtendedSecurityNegotiation = unchecked(0x0800); + + public static readonly int Flags2ResolvePathsInDfs = unchecked(0x1000); + + public static readonly int Flags2PermitReadIfExecutePerm = unchecked(0x2000); + + public static readonly int Flags2Status32 = unchecked(0x4000); + + public static readonly int Flags2Unicode = unchecked(0x8000); + + public static readonly int CapNone = unchecked(0x0000); + + public static readonly int CapRawMode = unchecked(0x0001); + + public static readonly int CapMpxMode = unchecked(0x0002); + + public static readonly int CapUnicode = unchecked(0x0004); + + public static readonly int CapLargeFiles = unchecked(0x0008); + + public static readonly int CapNtSmbs = unchecked(0x0010); + + public static readonly int CapRpcRemoteApis = unchecked(0x0020); + + public static readonly int CapStatus32 = unchecked(0x0040); + + public static readonly int CapLevelIiOplocks = unchecked(0x0080); + + public static readonly int CapLockAndRead = unchecked(0x0100); + + public static readonly int CapNtFind = unchecked(0x0200); + + public static readonly int CapDfs = unchecked(0x1000); + + public static readonly int CapExtendedSecurity = unchecked((int)(0x80000000)); + + public static readonly int AttrReadonly = unchecked(0x01); + + public static readonly int AttrHidden = unchecked(0x02); + + public static readonly int AttrSystem = unchecked(0x04); + + public static readonly int AttrVolume = unchecked(0x08); + + public static readonly int AttrDirectory = unchecked(0x10); + + public static readonly int AttrArchive = unchecked(0x20); + + public static readonly int AttrCompressed = unchecked(0x800); + + public static readonly int AttrNormal = unchecked(0x080); + + public static readonly int AttrTemporary = unchecked(0x100); + + public static readonly int FileReadData = unchecked(0x00000001); + + public static readonly int FileWriteData = unchecked(0x00000002); + + public static readonly int FileAppendData = unchecked(0x00000004); + + public static readonly int FileReadEa = unchecked(0x00000008); + + public static readonly int FileWriteEa = unchecked(0x00000010); + + public static readonly int FileExecute = unchecked(0x00000020); + + public static readonly int FileDelete = unchecked(0x00000040); + + public static readonly int FileReadAttributes = unchecked(0x00000080); + + public static readonly int FileWriteAttributes = unchecked(0x00000100); + + public static readonly int Delete = unchecked(0x00010000); + + public static readonly int ReadControl = unchecked(0x00020000); + + public static readonly int WriteDac = unchecked(0x00040000); + + public static readonly int WriteOwner = unchecked(0x00080000); + + public static readonly int Synchronize = unchecked(0x00100000); + + public static readonly int GenericAll = unchecked(0x10000000); + + public static readonly int GenericExecute = unchecked(0x20000000); + + public static readonly int GenericWrite = unchecked(0x40000000); + + public static readonly int GenericRead = unchecked((int)(0x80000000)); + + public static readonly int FlagsTargetMustBeFile = unchecked(0x0001); + + public static readonly int FlagsTargetMustBeDirectory = unchecked(0x0002); + + public static readonly int FlagsCopyTargetModeAscii = unchecked(0x0004); + + public static readonly int FlagsCopySourceModeAscii = unchecked(0x0008); + + public static readonly int FlagsVerifyAllWrites = unchecked(0x0010); + + public static readonly int FlagsTreeCopy = unchecked(0x0020); + + public static readonly int OpenFunctionFailIfExists = unchecked(0x0000); + + public static readonly int OpenFunctionOverwriteIfExists = unchecked(0x0020); + + public static readonly int Pid = (int)(new Random().NextDouble() * 65536d); + + public static readonly int SecurityShare = unchecked(0x00); + + public static readonly int SecurityUser = unchecked(0x01); + + public static readonly int CmdOffset = 4; + + public static readonly int ErrorCodeOffset = 5; + + public static readonly int FlagsOffset = 9; + + public static readonly int SignatureOffset = 14; + + public static readonly int TidOffset = 24; + + public static readonly int HeaderLength = 32; + + public static readonly long MillisecondsBetween1970And1601 = 11644473600000L; + + public static readonly TimeZoneInfo Tz = TimeZoneInfo.Local; + + public static readonly bool UseBatching = Config.GetBoolean("jcifs.smb.client.useBatching" + , true); + + public static readonly string OemEncoding = Config.GetProperty("jcifs.encoding", Config.DefaultOemEncoding + ); + + public static readonly string UniEncoding = "UTF-16LE"; + + public static readonly int DefaultFlags2 = Flags2LongFilenames | Flags2ExtendedAttributes + | (UseExtsec ? Flags2ExtendedSecurityNegotiation : 0) | (Signpref ? Flags2SecuritySignatures + : 0) | (UseNtstatus ? Flags2Status32 : 0) | (UseUnicode ? Flags2Unicode : 0 + ); + + public static readonly int DefaultCapabilities = (UseNtsmbs ? CapNtSmbs : 0) | (UseNtstatus + ? CapStatus32 : 0) | (UseUnicode ? CapUnicode : 0) | CapDfs; + + public static readonly int Flags2 = Config.GetInt("jcifs.smb.client.flags2", DefaultFlags2 + ); + + public static readonly int Capabilities = Config.GetInt("jcifs.smb.client.capabilities", DefaultCapabilities + ); + + public static readonly bool TcpNodelay = Config.GetBoolean("jcifs.smb.client.tcpNoDelay", + false); + + public static readonly int ResponseTimeout = Config.GetInt("jcifs.smb.client.responseTimeout" + , DefaultResponseTimeout); + + public static readonly List Connections = new List(); + + public static readonly int SsnLimit = Config.GetInt("jcifs.smb.client.ssnLimit", DefaultSsnLimit + ); + + public static readonly int SoTimeout = Config.GetInt("jcifs.smb.client.soTimeout", DefaultSoTimeout + ); + + public static readonly int ConnTimeout = Config.GetInt("jcifs.smb.client.connTimeout", DefaultConnTimeout + ); + + public static readonly string NativeOs = Config.GetProperty("jcifs.smb.client.nativeOs", Runtime + .GetProperty("os.name")); + + public static readonly string NativeLanman = Config.GetProperty("jcifs.smb.client.nativeLanMan" + , "jCIFS"); + + public static readonly int VcNumber = 1; + + public static SmbTransport NullTransport = new SmbTransport(null, 0, null, 0); + // file attribute encoding + // extended file attribute encoding(others same as above) + // access mask encoding + // 1 + // 2 + // 3 + // 4 + // 5 + // 6 + // 7 + // 8 + // 9 + // 16 + // 17 + // 18 + // 19 + // 20 + // 28 + // 29 + // 30 + // 31 + // flags for move and copy + // open function + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbException.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbException.cs new file mode 100644 index 0000000000..ea8a0b8466 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbException.cs @@ -0,0 +1,212 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + ///

+ /// There are hundreds of error codes that may be returned by a CIFS + /// server. + /// + /// + /// There are hundreds of error codes that may be returned by a CIFS + /// server. Rather than represent each with it's own Exception + /// class, this class represents all of them. For many of the popular + /// error codes, constants and text messages like "The device is not ready" + /// are provided. + ///

+ /// The jCIFS client maps DOS error codes to NTSTATUS codes. This means that + /// the user may recieve a different error from a legacy server than that of + /// a newer varient such as Windows NT and above. If you should encounter + /// such a case, please report it to jcifs at samba dot org and we will + /// change the mapping. + /// + + public class SmbException : IOException + { + + internal static string GetMessageByCode(int errcode) + { + if (errcode == 0) + { + return "NT_STATUS_SUCCESS"; + } + if ((errcode & unchecked((int)(0xC0000000))) == unchecked((int)(0xC0000000))) + { + int min = 1; + int max = NtStatus.NtStatusCodes.Length - 1; + while (max >= min) + { + int mid = (min + max) / 2; + if (errcode > NtStatus.NtStatusCodes[mid]) + { + min = mid + 1; + } + else + { + if (errcode < NtStatus.NtStatusCodes[mid]) + { + max = mid - 1; + } + else + { + return NtStatus.NtStatusMessages[mid]; + } + } + } + } + else + { + int min = 0; + int max = DosError.DosErrorCodes.Length - 1; + while (max >= min) + { + int mid = (min + max) / 2; + if (errcode > DosError.DosErrorCodes[mid][0]) + { + min = mid + 1; + } + else + { + if (errcode < DosError.DosErrorCodes[mid][0]) + { + max = mid - 1; + } + else + { + return DosError.DosErrorMessages[mid]; + } + } + } + } + return "0x" + Hexdump.ToHexString(errcode, 8); + } + + internal static int GetStatusByCode(int errcode) + { + if ((errcode & unchecked((int)(0xC0000000))) != 0) + { + return errcode; + } + int min = 0; + int max = DosError.DosErrorCodes.Length - 1; + while (max >= min) + { + int mid = (min + max) / 2; + if (errcode > DosError.DosErrorCodes[mid][0]) + { + min = mid + 1; + } + else + { + if (errcode < DosError.DosErrorCodes[mid][0]) + { + max = mid - 1; + } + else + { + return DosError.DosErrorCodes[mid][1]; + } + } + } + return NtStatus.NtStatusUnsuccessful; + } + + internal static string GetMessageByWinerrCode(int errcode) + { + int min = 0; + int max = WinError.WinerrCodes.Length - 1; + while (max >= min) + { + int mid = (min + max) / 2; + if (errcode > WinError.WinerrCodes[mid]) + { + min = mid + 1; + } + else + { + if (errcode < WinError.WinerrCodes[mid]) + { + max = mid - 1; + } + else + { + return WinError.WinerrMessages[mid]; + } + } + } + return errcode + string.Empty; + } + + private int _status; + + private Exception _rootCause; + + public SmbException() + { + } + + internal SmbException(int errcode, Exception rootCause) : base(GetMessageByCode(errcode + )) + { + _status = GetStatusByCode(errcode); + this._rootCause = rootCause; + } + + public SmbException(string msg) : base(msg) + { + _status = NtStatus.NtStatusUnsuccessful; + } + + public SmbException(string msg, Exception rootCause) : base(msg) + { + this._rootCause = rootCause; + _status = NtStatus.NtStatusUnsuccessful; + } + + public SmbException(int errcode, bool winerr) : base(winerr ? GetMessageByWinerrCode + (errcode) : GetMessageByCode(errcode)) + { + _status = winerr ? errcode : GetStatusByCode(errcode); + } + + public virtual int GetNtStatus() + { + return _status; + } + + public virtual Exception GetRootCause() + { + return _rootCause; + } + + public override string ToString() + { + if (_rootCause != null) + { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + Runtime.PrintStackTrace(_rootCause, pw); + return base.ToString() + "\n" + sw; + } + return base.ToString(); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFile.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFile.cs new file mode 100644 index 0000000000..151ec35c48 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFile.cs @@ -0,0 +1,3755 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.Collections.Generic; +using System.IO; +using System.Net; +using System.Text; +using SharpCifs.Dcerpc; +using SharpCifs.Dcerpc.Msrpc; +using SharpCifs.Netbios; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + ///

This class represents a resource on an SMB network. + /// + /// This class represents a resource on an SMB network. Mainly these + /// resources are files and directories however an SmbFile + /// may also refer to servers and workgroups. If the resource is a file or + /// directory the methods of SmbFile follow the behavior of + /// the well known + /// Sharpen.FilePath + /// class. One fundamental difference + /// is the usage of a URL scheme [1] to specify the target file or + /// directory. SmbFile URLs have the following syntax: + ///
+    /// smb://[[[domain;]username[:password]@]server[:port]/[[share/[dir/]file]]][?[param=value[param2=value2[...]]]
+    /// 
+ /// This example: + ///
+    /// smb://storage15/public/foo.txt
+    /// 
+ /// would reference the file foo.txt in the share + /// public on the server storage15. In addition + /// to referencing files and directories, jCIFS can also address servers, + /// and workgroups. + ///

+ /// Important: all SMB URLs that represent + /// workgroups, servers, shares, or directories require a trailing slash '/'. + /// + ///

+ /// When using the java.net.URL class with + /// 'smb://' URLs it is necessary to first call the static + /// jcifs.Config.registerSmbURLHandler(); method. This is required + /// to register the SMB protocol handler. + ///

+ /// The userinfo component of the SMB URL (domain;user:pass) must + /// be URL encoded if it contains reserved characters. According to RFC 2396 + /// these characters are non US-ASCII characters and most meta characters + /// however jCIFS will work correctly with anything but '@' which is used + /// to delimit the userinfo component from the server and '%' which is the + /// URL escape character itself. + ///

+ /// The server + /// component may a traditional NetBIOS name, a DNS name, or IP + /// address. These name resolution mechanisms and their resolution order + /// can be changed (See Setting Name + /// Resolution Properties). The servername and path components are + /// not case sensitive but the domain, username, and password components + /// are. It is also likely that properties must be specified for jcifs + /// to function (See Setting + /// JCIFS Properties). Here are some examples of SMB URLs with brief + /// descriptions of what they do: + ///

[1] This URL scheme is based largely on the SMB + /// Filesharing URL Scheme IETF draft. + ///

+ /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
SMB URL Examples
URLDescription
smb://users-nyc;miallen:mypass@angus/tmp/ + /// This URL references a share called tmp on the server + /// angus as user miallen who's password is + /// mypass. + ///
+ /// smb://Administrator:P%40ss@msmith1/c/WINDOWS/Desktop/foo.txt + /// A relativly sophisticated example that references a file + /// msmith1's desktop as user Administrator. Notice the '@' is URL encoded with the '%40' hexcode escape. + ///
smb://angus/ + /// This references only a server. The behavior of some methods is different + /// in this context(e.g. you cannot delete a server) however + /// as you might expect the list method will list the available + /// shares on this server. + ///
smb://myworkgroup/ + /// This syntactically is identical to the above example. However if + /// myworkgroup happends to be a workgroup(which is indeed + /// suggested by the name) the list method will return + /// a list of servers that have registered themselves as members of + /// myworkgroup. + ///
smb:// + /// Just as smb://server/ lists shares and + /// smb://workgroup/ lists servers, the smb:// + /// URL lists all available workgroups on a netbios LAN. Again, + /// in this context many methods are not valid and return default + /// values(e.g. isHidden will always return false). + ///
smb://angus.foo.net/d/jcifs/pipes.doc + /// The server name may also be a DNS name as it is in this example. See + /// Setting Name Resolution Properties + /// for details. + ///
smb://192.168.1.15/ADMIN$/ + /// The server name may also be an IP address. See <a + /// href="../../../resolver.html">Setting Name Resolution Properties + /// for details. + ///
+ /// smb://domain;username:password@server/share/path/to/file.txt + /// A prototypical example that uses all the fields. + ///
smb://myworkgroup/angus/ <-- ILLEGAL + /// Despite the hierarchial relationship between workgroups, servers, and + /// filesystems this example is not valid. + ///
+ /// smb://server/share/path/to/dir <-- ILLEGAL + /// URLs that represent workgroups, servers, shares, or directories require a trailing slash '/'. + ///
+ /// smb://MYGROUP/?SERVER=192.168.10.15 + /// SMB URLs support some query string parameters. In this example + /// the SERVER parameter is used to override the + /// server name service lookup to contact the server 192.168.10.15 + /// (presumably known to be a master + /// browser) for the server list in workgroup MYGROUP. + ///
+ ///

A second constructor argument may be specified to augment the URL + /// for better programmatic control when processing many files under + /// a common base. This is slightly different from the corresponding + /// java.io.File usage; a '/' at the beginning of the second + /// parameter will still use the server component of the first parameter. The + /// examples below illustrate the resulting URLs when this second contructor + /// argument is used. + ///

+ /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///
+ /// Examples Of SMB URLs When Augmented With A Second Constructor Parameter
+ /// First ParameterSecond ParameterResult
+ /// smb://host/share/a/b/ + /// + /// c/d/ + /// + /// smb://host/share/a/b/c/d/ + ///
+ /// smb://host/share/foo/bar/ + /// + /// /share2/zig/zag + /// + /// smb://host/share2/zig/zag + ///
+ /// smb://host/share/foo/bar/ + /// + /// ../zip/ + /// + /// smb://host/share/foo/zip/ + ///
+ /// smb://host/share/zig/zag + /// + /// smb://foo/bar/ + /// + /// smb://foo/bar/ + ///
+ /// smb://host/share/foo/ + /// + /// ../.././.././../foo/ + /// + /// smb://host/foo/ + ///
+ /// smb://host/share/zig/zag + /// + /// / + /// + /// smb://host/ + ///
+ /// smb://server/ + /// + /// ../ + /// + /// smb://server/ + ///
+ /// smb:// + /// + /// myworkgroup/ + /// + /// smb://myworkgroup/ + ///
+ /// smb://myworkgroup/ + /// + /// angus/ + /// + /// smb://myworkgroup/angus/ <-- ILLEGAL
(But if you first create an SmbFile with 'smb://workgroup/' and use and use it as the first parameter to a constructor that accepts it with a second String parameter jCIFS will factor out the 'workgroup'.) + ///
+ ///

Instances of the SmbFile class are immutable; that is, + /// once created, the abstract pathname represented by an SmbFile object + /// will never change. + /// + /// Sharpen.FilePath + public class SmbFile : UrlConnection + { + internal const int ORdonly = 0x01; + + internal const int OWronly = 0x02; + + internal const int ORdwr = 0x03; + + internal const int OAppend = 0x04; + + internal const int OCreat = 0x0010; + + internal const int OExcl = 0x0020; + + internal const int OTrunc = 0x0040; + + ///

+ /// When specified as the shareAccess constructor parameter, + /// other SMB clients (including other threads making calls into jCIFS) + /// will not be permitted to access the target file and will receive "The + /// file is being accessed by another process" message. + /// + /// + /// When specified as the shareAccess constructor parameter, + /// other SMB clients (including other threads making calls into jCIFS) + /// will not be permitted to access the target file and will receive "The + /// file is being accessed by another process" message. + /// + public const int FileNoShare = 0x00; + + /// + /// When specified as the shareAccess constructor parameter, + /// other SMB clients will be permitted to read from the target file while + /// this file is open. + /// + /// + /// When specified as the shareAccess constructor parameter, + /// other SMB clients will be permitted to read from the target file while + /// this file is open. This constant may be logically OR'd with other share + /// access flags. + /// + public const int FileShareRead = 0x01; + + /// + /// When specified as the shareAccess constructor parameter, + /// other SMB clients will be permitted to write to the target file while + /// this file is open. + /// + /// + /// When specified as the shareAccess constructor parameter, + /// other SMB clients will be permitted to write to the target file while + /// this file is open. This constant may be logically OR'd with other share + /// access flags. + /// + public const int FileShareWrite = 0x02; + + /// + /// When specified as the shareAccess constructor parameter, + /// other SMB clients will be permitted to delete the target file while + /// this file is open. + /// + /// + /// When specified as the shareAccess constructor parameter, + /// other SMB clients will be permitted to delete the target file while + /// this file is open. This constant may be logically OR'd with other share + /// access flags. + /// + public const int FileShareDelete = 0x04; + + /// + /// A file with this bit on as returned by getAttributes() or set + /// with setAttributes() will be read-only + /// + public const int AttrReadonly = 0x01; + + /// + /// A file with this bit on as returned by getAttributes() or set + /// with setAttributes() will be hidden + /// + public const int AttrHidden = 0x02; + + /// + /// A file with this bit on as returned by getAttributes() or set + /// with setAttributes() will be a system file + /// + public const int AttrSystem = 0x04; + + /// + /// A file with this bit on as returned by getAttributes() is + /// a volume + /// + public const int AttrVolume = 0x08; + + /// + /// A file with this bit on as returned by getAttributes() is + /// a directory + /// + public const int AttrDirectory = 0x10; + + /// + /// A file with this bit on as returned by getAttributes() or set + /// with setAttributes() is an archived file + /// + public const int AttrArchive = 0x20; + + internal const int AttrCompressed = 0x800; + + internal const int AttrNormal = 0x080; + + internal const int AttrTemporary = 0x100; + + internal const int AttrGetMask = 0x7FFF; + + internal const int AttrSetMask = 0x30A7; + + internal const int DefaultAttrExpirationPeriod = 5000; + + internal static readonly int HashDot = ".".GetHashCode(); + + internal static readonly int HashDotDot = "..".GetHashCode(); + + //internal static LogStream log = LogStream.GetInstance(); + public LogStream Log + { + get { return LogStream.GetInstance(); } + } + + internal static long AttrExpirationPeriod; + + internal static bool IgnoreCopyToException; + + static SmbFile() + { + // Open Function Encoding + // create if the file does not exist + // fail if the file exists + // truncate if the file exists + // share access + // file attribute encoding + // extended file attribute encoding(others same as above) + /*try + { + Sharpen.Runtime.GetType("jcifs.Config"); + } + catch (TypeLoadException cnfe) + { + Sharpen.Runtime.PrintStackTrace(cnfe); + }*/ + + AttrExpirationPeriod = Config.GetLong("jcifs.smb.client.attrExpirationPeriod", DefaultAttrExpirationPeriod + ); + IgnoreCopyToException = Config.GetBoolean("jcifs.smb.client.ignoreCopyToException" + , true); + Dfs = new Dfs(); + } + + /// + /// Returned by + /// GetType() + /// if the resource this SmbFile + /// represents is a regular file or directory. + /// + public const int TypeFilesystem = 0x01; + + /// + /// Returned by + /// GetType() + /// if the resource this SmbFile + /// represents is a workgroup. + /// + public const int TypeWorkgroup = 0x02; + + /// + /// Returned by + /// GetType() + /// if the resource this SmbFile + /// represents is a server. + /// + public const int TypeServer = 0x04; + + /// + /// Returned by + /// GetType() + /// if the resource this SmbFile + /// represents is a share. + /// + public const int TypeShare = 0x08; + + /// + /// Returned by + /// GetType() + /// if the resource this SmbFile + /// represents is a named pipe. + /// + public const int TypeNamedPipe = 0x10; + + /// + /// Returned by + /// GetType() + /// if the resource this SmbFile + /// represents is a printer. + /// + public const int TypePrinter = 0x20; + + /// + /// Returned by + /// GetType() + /// if the resource this SmbFile + /// represents is a communications device. + /// + public const int TypeComm = 0x40; + + private string _canon; + + private string _share; + + private long _createTime; + + private long _lastModified; + + private int _attributes; + + private long _attrExpiration; + + private long _size; + + private long _sizeExpiration; + + private bool _isExists; + + private int _shareAccess = FileShareRead | FileShareWrite | FileShareDelete; + + private bool _enableDfs = Config.GetBoolean("jcifs.smb.client.enabledfs", false); + + private SmbComBlankResponse _blankResp; + + private DfsReferral _dfsReferral; + + protected internal static Dfs Dfs; + + internal NtlmPasswordAuthentication Auth; + + internal SmbTree Tree; + + internal string Unc; + + internal int Fid; + + internal int Type; + + internal bool Opened; + + internal int TreeNum; + + public bool EnableDfs + { + get { return _enableDfs; } + set { _enableDfs = value; } + } + + /// + /// Constructs an SmbFile representing a resource on an SMB network such as + /// a file or directory. + /// + /// + /// Constructs an SmbFile representing a resource on an SMB network such as + /// a file or directory. See the description and examples of smb URLs above. + /// + /// A URL string + /// + /// If the parent and child parameters + /// do not follow the prescribed syntax + /// + public SmbFile(string url) + : this(new Uri(url)) + { + } + + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory. + /// + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory. The second parameter is a relative path from + /// the parent SmbFile. See the description above for examples + /// of using the second name parameter. + /// + /// A base SmbFile + /// A path string relative to the parent paremeter + /// + /// If the parent and child parameters + /// do not follow the prescribed syntax + /// + /// If the server or workgroup of the context file cannot be determined + /// + public SmbFile(SmbFile context, string name) + : this(context.IsWorkgroup0 + () ? new Uri("smb://" + name) : new Uri(context.Url.AbsoluteUri + name), + context.Auth) + { + + this._enableDfs = context.EnableDfs; + + if (!context.IsWorkgroup0()) + { + Addresses = context.Addresses; + + if (context._share != null) + { + Tree = context.Tree; + _dfsReferral = context._dfsReferral; + } + } + } + + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory. + /// + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory. The second parameter is a relative path from + /// the parent. See the description above for examples of + /// using the second chile parameter. + /// + /// A URL string + /// A path string relative to the context paremeter + /// + /// If the context and name parameters + /// do not follow the prescribed syntax + /// + /*public SmbFile(string context, string name) + : this(new Uri(new Uri(null, context), name)) + { + }*/ + + public SmbFile(string context, string name) + : this(new Uri(context + name)) + { + + } + + + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory. + /// + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory. + /// + /// A URL string + /// The credentials the client should use for authentication + /// If the url parameter does not follow the prescribed syntax + /// + public SmbFile(string url, NtlmPasswordAuthentication auth) + : this(new Uri(url, UriKind.RelativeOrAbsolute), + auth) + { + + } + + /// Constructs an SmbFile representing a file on an SMB network. + /// + /// Constructs an SmbFile representing a file on an SMB network. The + /// shareAccess parameter controls what permissions other + /// clients have when trying to access the same file while this instance + /// is still open. This value is either FILE_NO_SHARE or any + /// combination of FILE_SHARE_READ, FILE_SHARE_WRITE, + /// and FILE_SHARE_DELETE logically OR'd together. + /// + /// A URL string + /// The credentials the client should use for authentication + /// Specifies what access other clients have while this file is open. + /// + /// If the url parameter does not follow the prescribed syntax + /// + public SmbFile(string url, NtlmPasswordAuthentication auth, int shareAccess) + : this + (new Uri(url), auth) + { + // Initially null; set by getUncPath; dir must end with '/' + // Can be null + // For getDfsPath() and getServerWithDfs() + // Cannot be null + // Initially null + // Initially null; set by getUncPath; never ends with '/' + // Initially 0; set by open() + if ((shareAccess & ~(FileShareRead | FileShareWrite | FileShareDelete)) != + 0) + { + throw new RuntimeException("Illegal shareAccess parameter"); + } + this._shareAccess = shareAccess; + } + + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory. + /// + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory. The second parameter is a relative path from + /// the context. See the description above for examples of + /// using the second name parameter. + /// + /// A URL string + /// A path string relative to the context paremeter + /// The credentials the client should use for authentication + /// + /// If the context and name parameters + /// do not follow the prescribed syntax + /// + public SmbFile(string context, string name, NtlmPasswordAuthentication auth) + : this + (new Uri(context + name) + , auth) + { + + } + + + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory. + /// + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory. The second parameter is a relative path from + /// the context. See the description above for examples of + /// using the second name parameter. The shareAccess + /// parameter controls what permissions other clients have when trying + /// to access the same file while this instance is still open. This + /// value is either FILE_NO_SHARE or any combination + /// of FILE_SHARE_READ, FILE_SHARE_WRITE, and + /// FILE_SHARE_DELETE logically OR'd together. + /// + /// A URL string + /// A path string relative to the context paremeter + /// The credentials the client should use for authentication + /// Specifies what access other clients have while this file is open. + /// + /// + /// If the context and name parameters + /// do not follow the prescribed syntax + /// + public SmbFile(string context, string name, NtlmPasswordAuthentication auth, int + shareAccess) + : this(new Uri(context + name), auth) + { + if ((shareAccess & ~(FileShareRead | FileShareWrite | FileShareDelete)) != + 0) + { + throw new RuntimeException("Illegal shareAccess parameter"); + } + this._shareAccess = shareAccess; + } + + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory. + /// + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory. The second parameter is a relative path from + /// the context. See the description above for examples of + /// using the second name parameter. The shareAccess + /// parameter controls what permissions other clients have when trying + /// to access the same file while this instance is still open. This + /// value is either FILE_NO_SHARE or any combination + /// of FILE_SHARE_READ, FILE_SHARE_WRITE, and + /// FILE_SHARE_DELETE logically OR'd together. + /// + /// A base SmbFile + /// A path string relative to the context file path + /// Specifies what access other clients have while this file is open. + /// + /// + /// If the context and name parameters + /// do not follow the prescribed syntax + /// + /// + public SmbFile(SmbFile context, string name, int shareAccess) + : this(context.IsWorkgroup0() ? new Uri("smb://" + name) : new Uri( + context.Url.AbsoluteUri + name), context.Auth) + { + if ((shareAccess & ~(FileShareRead | FileShareWrite | FileShareDelete)) != + 0) + { + throw new RuntimeException("Illegal shareAccess parameter"); + } + + if (!context.IsWorkgroup0()) + { + this.Addresses = context.Addresses; + + if (context._share != null || context.Tree != null) + { + Tree = context.Tree; + _dfsReferral = context._dfsReferral; + } + } + + this._shareAccess = shareAccess; + this._enableDfs = context.EnableDfs; + } + + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory from a URL object. + /// + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory from a URL object. + /// + /// The URL of the target resource + protected SmbFile(Uri url) + : this(url, new NtlmPasswordAuthentication(url.GetUserInfo + ())) + { + } + + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory from a URL object and an + /// NtlmPasswordAuthentication object. + /// + /// + /// Constructs an SmbFile representing a resource on an SMB network such + /// as a file or directory from a URL object and an + /// NtlmPasswordAuthentication object. + /// + /// The URL of the target resource + /// The credentials the client should use for authentication + public SmbFile(Uri url, NtlmPasswordAuthentication auth) + { + this.Auth = auth ?? new NtlmPasswordAuthentication(url.GetUserInfo()); + Url = url; + GetUncPath0(); + } + + /// + /// + /*internal SmbFile(Jcifs.Smb.SmbFile context, string name, int type, int attributes + , long createTime, long lastModified, long size) + : this(context.IsWorkgroup0() ? + new Uri(null, "smb://" + name + "/") : new Uri(context.url, + name + ((attributes & ATTR_DIRECTORY) > 0 ? "/" : string.Empty)))*/ + internal SmbFile(SmbFile context, string name, int type, int attributes + , long createTime, long lastModified, long size) + : this(context.IsWorkgroup0() ? + new Uri("smb://" + name + "/") : new Uri(context.Url.AbsoluteUri + + name + ((attributes & AttrDirectory) > 0 ? "/" : string.Empty))) + { + Auth = context.Auth; + if (context._share != null) + { + Tree = context.Tree; + _dfsReferral = context._dfsReferral; + } + int last = name.Length - 1; + if (name[last] == '/') + { + name = Runtime.Substring(name, 0, last); + } + if (context._share == null) + { + Unc = "\\"; + } + else + { + if (context.Unc.Equals("\\")) + { + Unc = '\\' + name; + } + else + { + Unc = context.Unc + '\\' + name; + } + } + + if (!context.IsWorkgroup0()) + { + Addresses = context.Addresses; + } + + this._enableDfs = context.EnableDfs; + + this.Type = type; + this._attributes = attributes; + this._createTime = createTime; + this._lastModified = lastModified; + this._size = size; + _isExists = true; + _attrExpiration = _sizeExpiration = Runtime.CurrentTimeMillis() + AttrExpirationPeriod; + } + + private SmbComBlankResponse Blank_resp() + { + if (_blankResp == null) + { + _blankResp = new SmbComBlankResponse(); + } + return _blankResp; + } + + /// + internal virtual void ResolveDfs(ServerMessageBlock request) + { + if (!_enableDfs) + { + Connect0(); + return; + } + + if (request is SmbComClose) + { + return; + } + Connect0(); + DfsReferral dr = Dfs.Resolve(Tree.Session.transport.TconHostName, Tree.Share, Unc + , Auth); + if (dr != null) + { + string service = null; + if (request != null) + { + switch (request.Command) + { + case ServerMessageBlock.SmbComTransaction: + case ServerMessageBlock.SmbComTransaction2: + { + switch (((SmbComTransaction)request).SubCommand & 0xFF) + { + case SmbComTransaction.Trans2GetDfsReferral: + { + break; + } + + default: + { + service = "A:"; + break; + } + } + break; + } + + default: + { + service = "A:"; + break; + } + } + } + DfsReferral start = dr; + SmbException se = null; + do + { + try + { + if (Log.Level >= 2) + { + Log.WriteLine("DFS redirect: " + dr); + } + UniAddress addr = UniAddress.GetByName(dr.Server); + SmbTransport trans = SmbTransport.GetSmbTransport(addr, Url.Port); + trans.Connect(); + Tree = trans.GetSmbSession(Auth).GetSmbTree(dr.Share, service); + if (dr != start && dr.Key != null) + { + dr.Map.Put(dr.Key, dr); + } + se = null; + break; + } + catch (IOException ioe) + { + if (ioe is SmbException) + { + se = (SmbException)ioe; + } + else + { + se = new SmbException(dr.Server, ioe); + } + } + dr = dr.Next; + } + while (dr != start); + if (se != null) + { + throw se; + } + if (Log.Level >= 3) + { + Log.WriteLine(dr); + } + _dfsReferral = dr; + if (dr.PathConsumed < 0) + { + dr.PathConsumed = 0; + } + else + { + if (dr.PathConsumed > Unc.Length) + { + dr.PathConsumed = Unc.Length; + } + } + string dunc = Runtime.Substring(Unc, dr.PathConsumed); + if (dunc.Equals(string.Empty)) + { + dunc = "\\"; + } + if (!dr.Path.Equals(string.Empty)) + { + dunc = "\\" + dr.Path + dunc; + } + Unc = dunc; + if (request != null && request.Path != null && request.Path.EndsWith("\\") && dunc + .EndsWith("\\") == false) + { + dunc += "\\"; + } + if (request != null) + { + request.Path = dunc; + request.Flags2 |= SmbConstants.Flags2ResolvePathsInDfs; + } + } + else + { + if (Tree.InDomainDfs && !(request is NtTransQuerySecurityDesc) && !(request is SmbComClose + ) && !(request is SmbComFindClose2)) + { + throw new SmbException(NtStatus.NtStatusNotFound, false); + } + if (request != null) + { + request.Flags2 &= ~SmbConstants.Flags2ResolvePathsInDfs; + } + } + } + + /// + internal virtual void Send(ServerMessageBlock request, ServerMessageBlock response + ) + { + for (; ; ) + { + ResolveDfs(request); + try + { + Tree.Send(request, response); + break; + } + catch (DfsReferral dre) + { + if (dre.ResolveHashes) + { + throw; + } + request.Reset(); + } + } + } + + internal static string QueryLookup(string query, string param) + { + char[] instr = query.ToCharArray(); + int i; + int ch; + int st; + int eq; + st = eq = 0; + for (i = 0; i < instr.Length; i++) + { + ch = instr[i]; + if (ch == '&') + { + if (eq > st) + { + string p = new string(instr, st, eq - st); + if (Runtime.EqualsIgnoreCase(p, param)) + { + eq++; + return new string(instr, eq, i - eq); + } + } + st = i + 1; + } + else + { + if (ch == '=') + { + eq = i; + } + } + } + if (eq > st) + { + string p = new string(instr, st, eq - st); + if (Runtime.EqualsIgnoreCase(p, param)) + { + eq++; + return new string(instr, eq, instr.Length - eq); + } + } + return null; + } + + internal UniAddress[] Addresses; + + internal int AddressIndex; + + /// + internal virtual UniAddress GetAddress() + { + if (AddressIndex == 0) + { + return GetFirstAddress(); + } + return Addresses[AddressIndex - 1]; + } + + /// + internal virtual UniAddress GetFirstAddress() + { + AddressIndex = 0; + string host = Url.GetHost(); + string path = Url.AbsolutePath; + string query = Url.GetQuery(); + + if (Addresses != null && Addresses.Length > 0) + { + return GetNextAddress(); + } + + if (query != null) + { + string server = QueryLookup(query, "server"); + if (!string.IsNullOrEmpty(server)) + { + Addresses = new UniAddress[1]; + Addresses[0] = UniAddress.GetByName(server); + return GetNextAddress(); + } + string address = QueryLookup(query, "address"); + if (!string.IsNullOrEmpty(address)) + { + byte[] ip = Extensions.GetAddressByName(address).GetAddressBytes(); + Addresses = new UniAddress[1]; + //addresses[0] = new UniAddress(IPAddress.Parse(host, ip)); + Addresses[0] = new UniAddress(IPAddress.Parse(host)); + return GetNextAddress(); + } + } + if (host.Length == 0) + { + try + { + NbtAddress addr = NbtAddress.GetByName(NbtAddress.MasterBrowserName, 0x01, null); + Addresses = new UniAddress[1]; + Addresses[0] = UniAddress.GetByName(addr.GetHostAddress()); + } + catch (UnknownHostException uhe) + { + NtlmPasswordAuthentication.InitDefaults(); + if (NtlmPasswordAuthentication.DefaultDomain.Equals("?")) + { + throw; + } + Addresses = UniAddress.GetAllByName(NtlmPasswordAuthentication.DefaultDomain, true + ); + } + } + else + { + if (path.Length == 0 || path.Equals("/")) + { + Addresses = UniAddress.GetAllByName(host, true); + } + else + { + Addresses = UniAddress.GetAllByName(host, false); + } + } + return GetNextAddress(); + } + + internal virtual UniAddress GetNextAddress() + { + UniAddress addr = null; + if (AddressIndex < Addresses.Length) + { + addr = Addresses[AddressIndex++]; + } + return addr; + } + + internal virtual bool HasNextAddress() + { + return AddressIndex < Addresses.Length; + } + + /// + internal virtual void Connect0() + { + try + { + Connect(); + } + catch (UnknownHostException uhe) + { + throw new SmbException("Failed to connect to server", uhe); + } + catch (SmbException se) + { + throw; + } + catch (IOException ioe) + { + throw new SmbException("Failed to connect to server", ioe); + } + } + + /// + internal virtual void DoConnect() + { + SmbTransport trans; + UniAddress addr; + addr = GetAddress(); + + if (Tree != null && Tree.Session.transport.Address.Equals(addr)) + { + trans = Tree.Session.transport; + } + else + { + trans = SmbTransport.GetSmbTransport(addr, Url.Port); + Tree = trans.GetSmbSession(Auth).GetSmbTree(_share, null); + } + + + string hostName = GetServerWithDfs(); + if (_enableDfs) + { + Tree.InDomainDfs = Dfs.Resolve(hostName, Tree.Share, null, Auth) != null; + } + if (Tree.InDomainDfs) + { + Tree.ConnectionState = 2; + } + try + { + if (Log.Level >= 3) + { + Log.WriteLine("doConnect: " + addr); + } + Tree.TreeConnect(null, null); + } + catch (SmbAuthException sae) + { + NtlmPasswordAuthentication a; + SmbSession ssn; + if (_share == null) + { + // IPC$ - try "anonymous" credentials + ssn = trans.GetSmbSession(NtlmPasswordAuthentication.Null); + Tree = ssn.GetSmbTree(null, null); + Tree.TreeConnect(null, null); + } + else + { + if ((a = NtlmAuthenticator.RequestNtlmPasswordAuthentication(Url.ToString(), sae) + ) != null) + { + Auth = a; + ssn = trans.GetSmbSession(Auth); + Tree = ssn.GetSmbTree(_share, null); + Tree.InDomainDfs = Dfs.Resolve(hostName, Tree.Share, null, Auth) != null; + if (Tree.InDomainDfs) + { + Tree.ConnectionState = 2; + } + Tree.TreeConnect(null, null); + } + else + { + if (Log.Level >= 1 && HasNextAddress()) + { + Runtime.PrintStackTrace(sae, Log); + } + throw; + } + } + } + } + + /// It is not necessary to call this method directly. + /// + /// It is not necessary to call this method directly. This is the + /// URLConnection implementation of connect(). + /// + /// + public void Connect() + { + SmbTransport trans; + SmbSession ssn; + UniAddress addr; + if (IsConnected()) + { + return; + } + GetUncPath0(); + GetFirstAddress(); + for (; ; ) + { + try + { + DoConnect(); + return; + } + catch (SmbAuthException sae) + { + throw; + } + catch (SmbException se) + { + // Prevents account lockout on servers with multiple IPs + if (GetNextAddress() == null) + { + throw; + } + else + { + RemoveCurrentAddress(); + } + + if (Log.Level >= 3) + { + Runtime.PrintStackTrace(se, Log); + } + } + } + } + + internal virtual bool IsConnected() + { + return Tree != null && Tree.ConnectionState == 2; + } + + /// + internal virtual int Open0(int flags, int access, int attrs, int options) + { + int f; + Connect0(); + if (Log.Level >= 3) + { + Log.WriteLine("open0: " + Unc); + } + if (Tree.Session.transport.HasCapability(SmbConstants.CapNtSmbs)) + { + SmbComNtCreateAndXResponse response = new SmbComNtCreateAndXResponse(); + SmbComNtCreateAndX request = new SmbComNtCreateAndX(Unc, flags, access, _shareAccess + , attrs, options, null); + if (this is SmbNamedPipe) + { + request.Flags0 |= 0x16; + request.DesiredAccess |= 0x20000; + response.IsExtended = true; + } + Send(request, response); + f = response.Fid; + _attributes = response.ExtFileAttributes & AttrGetMask; + _attrExpiration = Runtime.CurrentTimeMillis() + AttrExpirationPeriod; + _isExists = true; + } + else + { + SmbComOpenAndXResponse response = new SmbComOpenAndXResponse(); + Send(new SmbComOpenAndX(Unc, access, flags, null), response); + f = response.Fid; + } + return f; + } + + /// + internal virtual void Open(int flags, int access, int attrs, int options) + { + if (IsOpen()) + { + return; + } + Fid = Open0(flags, access, attrs, options); + Opened = true; + TreeNum = Tree.TreeNum; + } + + internal virtual bool IsOpen() + { + bool ans = Opened && IsConnected() && TreeNum == Tree.TreeNum; + return ans; + } + + /// + internal virtual void Close(int f, long lastWriteTime) + { + if (Log.Level >= 3) + { + Log.WriteLine("close: " + f); + } + Send(new SmbComClose(f, lastWriteTime), Blank_resp()); + } + + /// + internal virtual void Close(long lastWriteTime) + { + if (IsOpen() == false) + { + return; + } + Close(Fid, lastWriteTime); + Opened = false; + } + + /// + internal virtual void Close() + { + Close(0L); + } + + /// + /// Returns the NtlmPasswordAuthentication object used as + /// credentials with this file or pipe. + /// + /// + /// Returns the NtlmPasswordAuthentication object used as + /// credentials with this file or pipe. This can be used to retrieve the + /// username for example: + /// + /// String username = f.getPrincipal().getName(); + /// + /// The Principal object returned will never be null + /// however the username can be null indication anonymous + /// credentials were used (e.g. some IPC$ services). + /// + public virtual Principal GetPrincipal() + { + return Auth; + } + + /// Returns the last component of the target URL. + /// + /// Returns the last component of the target URL. This will + /// effectively be the name of the file or directory represented by this + /// SmbFile or in the case of URLs that only specify a server + /// or workgroup, the server or workgroup will be returned. The name of + /// the root URL smb:// is also smb://. If this + /// SmbFile refers to a workgroup, server, share, or directory, + /// the name will include a trailing slash '/' so that composing new + /// SmbFiles will maintain the trailing slash requirement. + /// + /// + /// The last component of the URL associated with this SMB + /// resource or smb:// if the resource is smb:// + /// itself. + /// + public virtual string GetName() + { + GetUncPath0(); + if (_canon.Length > 1) + { + int i = _canon.Length - 2; + while (_canon[i] != '/') + { + i--; + } + return Runtime.Substring(_canon, i + 1); + } + if (_share != null) + { + return _share + '/'; + } + if (Url.GetHost().Length > 0) + { + return Url.GetHost() + '/'; + } + return "smb://"; + } + + /// + /// Everything but the last component of the URL representing this SMB + /// resource is effectivly it's parent. + /// + /// + /// Everything but the last component of the URL representing this SMB + /// resource is effectivly it's parent. The root URL smb:// + /// does not have a parent. In this case smb:// is returned. + /// + /// + /// The parent directory of this SMB resource or + /// smb:// if the resource refers to the root of the URL + /// hierarchy which incedentally is also smb://. + /// + public virtual string GetParent() + { + string str = Url.Authority; + if (str.Length > 0) + { + StringBuilder sb = new StringBuilder("smb://"); + sb.Append(str); + GetUncPath0(); + if (_canon.Length > 1) + { + sb.Append(_canon); + } + else + { + sb.Append('/'); + } + str = sb.ToString(); + int i = str.Length - 2; + while (str[i] != '/') + { + i--; + } + return Runtime.Substring(str, 0, i + 1); + } + return "smb://"; + } + + /// Returns the full uncanonicalized URL of this SMB resource. + /// + /// Returns the full uncanonicalized URL of this SMB resource. An + /// SmbFile constructed with the result of this method will + /// result in an SmbFile that is equal to the original. + /// + /// The uncanonicalized full URL of this SMB resource. + public virtual string GetPath() + { + return Url.ToString(); + } + + internal virtual string GetUncPath0() + { + if (Unc == null) + { + char[] instr = Url.LocalPath.ToCharArray(); + char[] outstr = new char[instr.Length]; + int length = instr.Length; + int i; + int o; + int state; + + state = 0; + o = 0; + for (i = 0; i < length; i++) + { + switch (state) + { + case 0: + { + if (instr[i] != '/') + { + return null; + } + outstr[o++] = instr[i]; + state = 1; + break; + } + + case 1: + { + if (instr[i] == '/') + { + break; + } + if (instr[i] == '.' && ((i + 1) >= length || instr[i + 1] == '/')) + { + i++; + break; + } + if ((i + 1) < length && instr[i] == '.' && instr[i + 1] == '.' && ((i + 2) >= length + || instr[i + 2] == '/')) + { + i += 2; + if (o == 1) + { + break; + } + do + { + o--; + } + while (o > 1 && outstr[o - 1] != '/'); + break; + } + state = 2; + goto case 2; + } + + case 2: + { + if (instr[i] == '/') + { + state = 1; + } + outstr[o++] = instr[i]; + break; + } + } + } + _canon = new string(outstr, 0, o); + if (o > 1) + { + o--; + i = _canon.IndexOf('/', 1); + if (i < 0) + { + _share = Runtime.Substring(_canon, 1); + Unc = "\\"; + } + else + { + if (i == o) + { + _share = Runtime.Substring(_canon, 1, i); + Unc = "\\"; + } + else + { + _share = Runtime.Substring(_canon, 1, i); + Unc = Runtime.Substring(_canon, i, outstr[o] == '/' ? o : o + 1); + Unc = Unc.Replace('/', '\\'); + } + } + } + else + { + _share = null; + Unc = "\\"; + } + } + return Unc; + } + + /// Retuns the Windows UNC style path with backslashs intead of forward slashes. + /// + /// Retuns the Windows UNC style path with backslashs intead of forward slashes. + /// + /// The UNC path. + public virtual string GetUncPath() + { + GetUncPath0(); + if (_share == null) + { + return "\\\\" + Url.GetHost(); + } + return "\\\\" + Url.GetHost() + _canon.Replace('/', '\\'); + } + + /// + /// Returns the full URL of this SMB resource with '.' and '..' components + /// factored out. + /// + /// + /// Returns the full URL of this SMB resource with '.' and '..' components + /// factored out. An SmbFile constructed with the result of + /// this method will result in an SmbFile that is equal to + /// the original. + /// + /// The canonicalized URL of this SMB resource. + public virtual string GetCanonicalPath() + { + string str = Url.Authority; + GetUncPath0(); + if (str.Length > 0) + { + return "smb://" + Url.Authority + _canon; + } + return "smb://"; + } + + /// Retrieves the share associated with this SMB resource. + /// + /// Retrieves the share associated with this SMB resource. In + /// the case of smb://, smb://workgroup/, + /// and smb://server/ URLs which do not specify a share, + /// null will be returned. + /// + /// The share component or null if there is no share + public virtual string GetShare() + { + return _share; + } + + internal virtual string GetServerWithDfs() + { + if (_dfsReferral != null) + { + return _dfsReferral.Server; + } + return GetServer(); + } + + /// Retrieve the hostname of the server for this SMB resource. + /// + /// Retrieve the hostname of the server for this SMB resource. If this + /// SmbFile references a workgroup, the name of the workgroup + /// is returned. If this SmbFile refers to the root of this + /// SMB network hierarchy, null is returned. + /// + /// + /// The server or workgroup name or null if this + /// SmbFile refers to the root smb:// resource. + /// + public virtual string GetServer() + { + string str = Url.GetHost(); + if (str.Length == 0) + { + return null; + } + return str; + } + + /// Returns type of of object this SmbFile represents. + /// Returns type of of object this SmbFile represents. + /// + /// TYPE_FILESYSTEM, TYPE_WORKGROUP, TYPE_SERVER, TYPE_SHARE, + /// TYPE_PRINTER, TYPE_NAMED_PIPE, or TYPE_COMM. + /// + /// + public new virtual int GetType() + { + if (Type == 0) + { + if (GetUncPath0().Length > 1) + { + Type = TypeFilesystem; + } + else + { + if (_share != null) + { + // treeConnect good enough to test service type + Connect0(); + if (_share.Equals("IPC$")) + { + Type = TypeNamedPipe; + } + else + { + if (Tree.Service.Equals("LPT1:")) + { + Type = TypePrinter; + } + else + { + if (Tree.Service.Equals("COMM")) + { + Type = TypeComm; + } + else + { + Type = TypeShare; + } + } + } + } + else + { + if (string.IsNullOrEmpty(Url.Authority)) + { + Type = TypeWorkgroup; + } + else + { + UniAddress addr; + try + { + addr = GetAddress(); + } + catch (UnknownHostException uhe) + { + throw new SmbException(Url.ToString(), uhe); + } + if (addr.GetAddress() is NbtAddress) + { + int code = ((NbtAddress)addr.GetAddress()).GetNameType(); + if (code == 0x1d || code == 0x1b) + { + Type = TypeWorkgroup; + return Type; + } + } + Type = TypeServer; + } + } + } + } + return Type; + } + + /// + internal virtual bool IsWorkgroup0() + { + if (Type == TypeWorkgroup || Url.GetHost().Length == 0) + { + Type = TypeWorkgroup; + return true; + } + GetUncPath0(); + if (_share == null) + { + UniAddress addr = GetAddress(); + if (addr.GetAddress() is NbtAddress) + { + int code = ((NbtAddress)addr.GetAddress()).GetNameType(); + if (code == 0x1d || code == 0x1b) + { + Type = TypeWorkgroup; + return true; + } + } + Type = TypeServer; + } + return false; + } + + /// + internal virtual IInfo QueryPath(string path, int infoLevel) + { + Connect0(); + if (Log.Level >= 3) + { + Log.WriteLine("queryPath: " + path); + } + if (Tree.Session.transport.HasCapability(SmbConstants.CapNtSmbs)) + { + Trans2QueryPathInformationResponse response = new Trans2QueryPathInformationResponse + (infoLevel); + Send(new Trans2QueryPathInformation(path, infoLevel), response); + return response.Info; + } + else + { + SmbComQueryInformationResponse response = new SmbComQueryInformationResponse(Tree + .Session.transport.Server.ServerTimeZone * 1000 * 60L); + Send(new SmbComQueryInformation(path), response); + return response; + } + } + + /// Tests to see if the SMB resource exists. + /// + /// Tests to see if the SMB resource exists. If the resource refers + /// only to a server, this method determines if the server exists on the + /// network and is advertising SMB services. If this resource refers to + /// a workgroup, this method determines if the workgroup name is valid on + /// the local SMB network. If this SmbFile refers to the root + /// smb:// resource true is always returned. If + /// this SmbFile is a traditional file or directory, it will + /// be queried for on the specified server as expected. + /// + /// + /// true if the resource exists or is alive or + /// false otherwise + /// + /// + public virtual bool Exists() + { + if (_attrExpiration > Runtime.CurrentTimeMillis()) + { + return _isExists; + } + _attributes = AttrReadonly | AttrDirectory; + _createTime = 0L; + _lastModified = 0L; + _isExists = false; + try + { + if (Url.GetHost().Length == 0) + { + } + else + { + if (_share == null) + { + if (GetType() == TypeWorkgroup) + { + UniAddress.GetByName(Url.GetHost(), true); + } + else + { + UniAddress.GetByName(Url.GetHost()).GetHostName(); + } + } + else + { + if (GetUncPath0().Length == 1 || Runtime.EqualsIgnoreCase(_share, "IPC$")) + { + Connect0(); + } + else + { + // treeConnect is good enough + IInfo info = QueryPath(GetUncPath0(), Trans2QueryPathInformationResponse.SMB_QUERY_FILE_BASIC_INFO + ); + _attributes = info.GetAttributes(); + _createTime = info.GetCreateTime(); + _lastModified = info.GetLastWriteTime(); + } + } + } + _isExists = true; + } + catch (UnknownHostException) + { + } + catch (SmbException se) + { + switch (se.GetNtStatus()) + { + case NtStatus.NtStatusNoSuchFile: + case NtStatus.NtStatusObjectNameInvalid: + case NtStatus.NtStatusObjectNameNotFound: + case NtStatus.NtStatusObjectPathNotFound: + { + break; + } + + default: + { + throw; + } + } + } + _attrExpiration = Runtime.CurrentTimeMillis() + AttrExpirationPeriod; + return _isExists; + } + + /// + /// Tests to see if the file this SmbFile represents can be + /// read. + /// + /// + /// Tests to see if the file this SmbFile represents can be + /// read. Because any file, directory, or other resource can be read if it + /// exists, this method simply calls the exists method. + /// + /// true if the file is read-only + /// + public virtual bool CanRead() + { + if (GetType() == TypeNamedPipe) + { + // try opening the pipe for reading? + return true; + } + return Exists(); + } + + // try opening and catch sharing violation? + /// + /// Tests to see if the file this SmbFile represents + /// exists and is not marked read-only. + /// + /// + /// Tests to see if the file this SmbFile represents + /// exists and is not marked read-only. By default, resources are + /// considered to be read-only and therefore for smb://, + /// smb://workgroup/, and smb://server/ resources + /// will be read-only. + /// + /// + /// true if the resource exists is not marked + /// read-only + /// + /// + public virtual bool CanWrite() + { + if (GetType() == TypeNamedPipe) + { + // try opening the pipe for writing? + return true; + } + return Exists() && (_attributes & AttrReadonly) == 0; + } + + /// Tests to see if the file this SmbFile represents is a directory. + /// + /// Tests to see if the file this SmbFile represents is a directory. + /// + /// true if this SmbFile is a directory + /// + public virtual bool IsDirectory() + { + if (GetUncPath0().Length == 1) + { + return true; + } + if (!Exists()) + { + return false; + } + return (_attributes & AttrDirectory) == AttrDirectory; + } + + /// Tests to see if the file this SmbFile represents is not a directory. + /// + /// Tests to see if the file this SmbFile represents is not a directory. + /// + /// true if this SmbFile is not a directory + /// + public virtual bool IsFile() + { + if (GetUncPath0().Length == 1) + { + return false; + } + Exists(); + return (_attributes & AttrDirectory) == 0; + } + + /// + /// Tests to see if the file this SmbFile represents is marked as + /// hidden. + /// + /// + /// Tests to see if the file this SmbFile represents is marked as + /// hidden. This method will also return true for shares with names that + /// end with '$' such as IPC$ or C$. + /// + /// true if the SmbFile is marked as being hidden + /// + public virtual bool IsHidden() + { + if (_share == null) + { + return false; + } + if (GetUncPath0().Length == 1) + { + if (_share.EndsWith("$")) + { + return true; + } + return false; + } + Exists(); + return (_attributes & AttrHidden) == AttrHidden; + } + + /// + /// If the path of this SmbFile falls within a DFS volume, + /// this method will return the referral path to which it maps. + /// + /// + /// If the path of this SmbFile falls within a DFS volume, + /// this method will return the referral path to which it maps. Otherwise + /// null is returned. + /// + /// + public virtual string GetDfsPath() + { + ResolveDfs(null); + if (_dfsReferral == null) + { + return null; + } + string path = "smb:/" + _dfsReferral.Server + "/" + _dfsReferral.Share + Unc; + path = path.Replace('\\', '/'); + if (IsDirectory()) + { + path += '/'; + } + return path; + } + + /// Retrieve the time this SmbFile was created. + /// + /// Retrieve the time this SmbFile was created. The value + /// returned is suitable for constructing a + /// System.DateTime + /// object + /// (i.e. seconds since Epoch 1970). Times should be the same as those + /// reported using the properties dialog of the Windows Explorer program. + /// For Win95/98/Me this is actually the last write time. It is currently + /// not possible to retrieve the create time from files on these systems. + /// + /// + /// The number of milliseconds since the 00:00:00 GMT, January 1, + /// 1970 as a long value + /// + /// + public virtual long CreateTime() + { + if (GetUncPath0().Length > 1) + { + Exists(); + return _createTime; + } + return 0L; + } + + /// + /// Retrieve the last time the file represented by this + /// SmbFile was modified. + /// + /// + /// Retrieve the last time the file represented by this + /// SmbFile was modified. The value returned is suitable for + /// constructing a + /// System.DateTime + /// object (i.e. seconds since Epoch + /// 1970). Times should be the same as those reported using the properties + /// dialog of the Windows Explorer program. + /// + /// + /// The number of milliseconds since the 00:00:00 GMT, January 1, + /// 1970 as a long value + /// + /// + public virtual long LastModified() + { + if (GetUncPath0().Length > 1) + { + Exists(); + return _lastModified; + } + return 0L; + } + + /// List the contents of this SMB resource. + /// + /// List the contents of this SMB resource. The list returned by this + /// method will be; + ///
    + ///
  • files and directories contained within this resource if the + /// resource is a normal disk file directory, + ///
  • all available NetBIOS workgroups or domains if this resource is + /// the top level URL smb://, + ///
  • all servers registered as members of a NetBIOS workgroup if this + /// resource refers to a workgroup in a smb://workgroup/ URL, + ///
  • all browseable shares of a server including printers, IPC + /// services, or disk volumes if this resource is a server URL in the form + /// smb://server/, + ///
  • or null if the resource cannot be resolved. + ///
+ ///
+ /// + /// A String[] array of files and directories, + /// workgroups, servers, or shares depending on the context of the + /// resource URL + /// + /// + public virtual string[] List() + { + return List("*", AttrDirectory | AttrHidden | AttrSystem, null, null); + } + + /// List the contents of this SMB resource. + /// + /// List the contents of this SMB resource. The list returned will be + /// identical to the list returned by the parameterless list() + /// method minus filenames filtered by the specified filter. + /// + /// a filename filter to exclude filenames from the results + /// # @return An array of filenames + /// + public virtual string[] List(ISmbFilenameFilter filter) + { + return List("*", AttrDirectory | AttrHidden | AttrSystem, filter, null); + } + + /// + /// List the contents of this SMB resource as an array of + /// SmbFile objects. + /// + /// + /// List the contents of this SMB resource as an array of + /// SmbFile objects. This method is much more efficient than + /// the regular list method when querying attributes of each + /// file in the result set. + ///

+ /// The list of SmbFiles returned by this method will be; + ///

    + ///
  • files and directories contained within this resource if the + /// resource is a normal disk file directory, + ///
  • all available NetBIOS workgroups or domains if this resource is + /// the top level URL smb://, + ///
  • all servers registered as members of a NetBIOS workgroup if this + /// resource refers to a workgroup in a smb://workgroup/ URL, + ///
  • all browseable shares of a server including printers, IPC + /// services, or disk volumes if this resource is a server URL in the form + /// smb://server/, + ///
  • or null if the resource cannot be resolved. + ///
+ ///
+ /// + /// An array of SmbFile objects representing file + /// and directories, workgroups, servers, or shares depending on the context + /// of the resource URL + /// + /// + public virtual SmbFile[] ListFiles() + { + return ListFiles("*", AttrDirectory | AttrHidden | AttrSystem, null, null); + } + + /// + /// The CIFS protocol provides for DOS "wildcards" to be used as + /// a performance enhancement. + /// + /// + /// The CIFS protocol provides for DOS "wildcards" to be used as + /// a performance enhancement. The client does not have to filter + /// the names and the server does not have to return all directory + /// entries. + ///

+ /// The wildcard expression may consist of two special meta + /// characters in addition to the normal filename characters. The '*' + /// character matches any number of characters in part of a name. If + /// the expression begins with one or more '?'s then exactly that + /// many characters will be matched whereas if it ends with '?'s + /// it will match that many characters or less. + ///

+ /// Wildcard expressions will not filter workgroup names or server names. + ///

+        /// winnt> ls c?o
+        /// clock.avi                  -rw--      82944 Mon Oct 14 1996 1:38 AM
+        /// Cookies                    drw--          0 Fri Nov 13 1998 9:42 PM
+        /// 2 items in 5ms
+        /// 
+ ///
+ /// a wildcard expression + /// SmbException + /// + /// An array of SmbFile objects representing file + /// and directories, workgroups, servers, or shares depending on the context + /// of the resource URL + /// + /// + public virtual SmbFile[] ListFiles(string wildcard) + { + return ListFiles(wildcard, AttrDirectory | AttrHidden | AttrSystem, null, null + ); + } + + /// List the contents of this SMB resource. + /// + /// List the contents of this SMB resource. The list returned will be + /// identical to the list returned by the parameterless listFiles() + /// method minus files filtered by the specified filename filter. + /// + /// a filter to exclude files from the results + /// An array of SmbFile objects + /// SmbException + /// + public virtual SmbFile[] ListFiles(ISmbFilenameFilter filter) + { + return ListFiles("*", AttrDirectory | AttrHidden | AttrSystem, filter, null); + } + + /// List the contents of this SMB resource. + /// + /// List the contents of this SMB resource. The list returned will be + /// identical to the list returned by the parameterless listFiles() + /// method minus filenames filtered by the specified filter. + /// + /// a file filter to exclude files from the results + /// An array of SmbFile objects + /// + public virtual SmbFile[] ListFiles(ISmbFileFilter filter) + { + return ListFiles("*", AttrDirectory | AttrHidden | AttrSystem, null, filter); + } + + /// + internal virtual string[] List(string wildcard, int searchAttributes, ISmbFilenameFilter + fnf, ISmbFileFilter ff) + { + List list = new List(); + DoEnum(list, false, wildcard, searchAttributes, fnf, ff); + + return Collections.ToArray(list); //Collections.ToArray(list); + } + + /// + internal virtual SmbFile[] ListFiles(string wildcard, int searchAttributes + , ISmbFilenameFilter fnf, ISmbFileFilter ff) + { + List list = new List(); + DoEnum(list, true, wildcard, searchAttributes, fnf, ff); + + return Collections.ToArray(list); //Collections.ToArray(list); + } + + /// + internal virtual void DoEnum(List list, bool files, string wildcard, int searchAttributes + , ISmbFilenameFilter fnf, ISmbFileFilter ff) + { + if (ff != null && ff is DosFileFilter) + { + DosFileFilter dff = (DosFileFilter)ff; + if (dff.Wildcard != null) + { + wildcard = dff.Wildcard; + } + searchAttributes = dff.Attributes; + } + try + { + int hostlen = Url.GetHost() != null ? Url.GetHost().Length : 0; + if (hostlen == 0 || GetType() == TypeWorkgroup) + { + DoNetServerEnum(list, files, wildcard, searchAttributes, fnf, ff); + } + else + { + if (_share == null) + { + DoShareEnum(list, files, wildcard, searchAttributes, fnf, ff); + } + else + { + DoFindFirstNext(list, files, wildcard, searchAttributes, fnf, ff); + } + } + } + catch (UnknownHostException uhe) + { + throw new SmbException(Url.ToString(), uhe); + } + catch (UriFormatException mue) + { + throw new SmbException(Url.ToString(), mue); + } + } + + private void RemoveCurrentAddress() + { + if (AddressIndex >= 1) + { + UniAddress[] aux = new UniAddress[Addresses.Length - 1]; + + Array.Copy(Addresses, 1, aux, 0, Addresses.Length - 1); + + Addresses = aux; + AddressIndex--; + } + } + + /// + /// + /// + internal virtual void DoShareEnum(List list, bool files, string wildcard, int + searchAttributes, ISmbFilenameFilter fnf, ISmbFileFilter ff) + { + string p = Url.AbsolutePath; + IOException last = null; + IFileEntry[] entries; + UniAddress addr; + IFileEntry e; + Hashtable map; + if (p.LastIndexOf('/') != (p.Length - 1)) + { + throw new SmbException(Url + " directory must end with '/'"); + } + if (GetType() != TypeServer) + { + throw new SmbException("The requested list operations is invalid: " + Url); + } + map = new Hashtable(); + if (_enableDfs && Dfs.IsTrustedDomain(GetServer(), Auth)) + { + try + { + entries = DoDfsRootEnum(); + for (int ei = 0; ei < entries.Length; ei++) + { + e = entries[ei]; + if (map.ContainsKey(e) == false) + { + map.Put(e, e); + } + } + } + catch (IOException ioe) + { + if (Log.Level >= 4) + { + Runtime.PrintStackTrace(ioe, Log); + } + } + } + addr = GetFirstAddress(); + while (addr != null) + { + try + { + last = null; + + DoConnect(); + try + { + entries = DoMsrpcShareEnum(); + } + catch (IOException ioe) + { + if (Log.Level >= 3) + { + Runtime.PrintStackTrace(ioe, Log); + } + entries = DoNetShareEnum(); + } + for (int ei = 0; ei < entries.Length; ei++) + { + e = entries[ei]; + if (map.ContainsKey(e) == false) + { + map.Put(e, e); + } + } + break; + } + catch (IOException ioe) + { + if (Log.Level >= 3) + { + Runtime.PrintStackTrace(ioe, Log); + } + last = ioe; + + if (!(ioe is SmbAuthException)) + { + RemoveCurrentAddress(); + + addr = GetNextAddress(); + } + else + { + break; + } + } + + } + if (last != null && map.Count == 0) + { + if (last is SmbException == false) + { + throw new SmbException(Url.ToString(), last); + } + throw (SmbException)last; + } + //Iterator iter = map.Keys.Iterator(); + //while (iter.HasNext()) + foreach (var item in map.Keys) + { + e = (IFileEntry)item; + string name = e.GetName(); + if (fnf != null && fnf.Accept(this, name) == false) + { + continue; + } + if (name.Length > 0) + { + // if !files we don't need to create SmbFiles here + SmbFile f = new SmbFile(this, name, e.GetType(), AttrReadonly + | AttrDirectory, 0L, 0L, 0L); + if (ff != null && ff.Accept(f) == false) + { + continue; + } + if (files) + { + list.Add(f); + } + else + { + list.Add(name); + } + } + } + } + + /// + internal virtual IFileEntry[] DoDfsRootEnum() + { + MsrpcDfsRootEnum rpc; + DcerpcHandle handle = null; + IFileEntry[] entries; + handle = DcerpcHandle.GetHandle("ncacn_np:" + GetAddress().GetHostAddress() + "[\\PIPE\\netdfs]" + , Auth); + try + { + rpc = new MsrpcDfsRootEnum(GetServer()); + handle.Sendrecv(rpc); + if (rpc.Retval != 0) + { + throw new SmbException(rpc.Retval, true); + } + return rpc.GetEntries(); + } + finally + { + try + { + handle.Close(); + } + catch (IOException ioe) + { + if (Log.Level >= 4) + { + Runtime.PrintStackTrace(ioe, Log); + } + } + } + } + + /// + internal virtual IFileEntry[] DoMsrpcShareEnum() + { + MsrpcShareEnum rpc; + DcerpcHandle handle; + rpc = new MsrpcShareEnum(Url.GetHost()); + handle = DcerpcHandle.GetHandle("ncacn_np:" + GetAddress().GetHostAddress() + "[\\PIPE\\srvsvc]" + , Auth); + try + { + handle.Sendrecv(rpc); + if (rpc.Retval != 0) + { + throw new SmbException(rpc.Retval, true); + } + return rpc.GetEntries(); + } + finally + { + try + { + handle.Close(); + } + catch (IOException ioe) + { + if (Log.Level >= 4) + { + Runtime.PrintStackTrace(ioe, Log); + } + } + } + } + + /// + internal virtual IFileEntry[] DoNetShareEnum() + { + SmbComTransaction req = new NetShareEnum(); + SmbComTransactionResponse resp = new NetShareEnumResponse(); + Send(req, resp); + if (resp.Status != WinError.ErrorSuccess) + { + throw new SmbException(resp.Status, true); + } + return resp.Results; + } + + /// + /// + /// + internal virtual void DoNetServerEnum(List list, bool files, string wildcard + , int searchAttributes, ISmbFilenameFilter fnf, ISmbFileFilter ff) + { + int listType = Url.GetHost().Length == 0 ? 0 : GetType(); + SmbComTransaction req; + SmbComTransactionResponse resp; + if (listType == 0) + { + Connect0(); + req = new NetServerEnum2(Tree.Session.transport.Server.OemDomainName, NetServerEnum2 + .SvTypeDomainEnum); + resp = new NetServerEnum2Response(); + } + else + { + if (listType == TypeWorkgroup) + { + req = new NetServerEnum2(Url.GetHost(), NetServerEnum2.SvTypeAll); + resp = new NetServerEnum2Response(); + } + else + { + throw new SmbException("The requested list operations is invalid: " + Url); + } + } + bool more; + do + { + int n; + Send(req, resp); + if (resp.Status != WinError.ErrorSuccess && resp.Status != WinError.ErrorMoreData) + { + throw new SmbException(resp.Status, true); + } + more = resp.Status == WinError.ErrorMoreData; + n = more ? resp.NumEntries - 1 : resp.NumEntries; + for (int i = 0; i < n; i++) + { + IFileEntry e = resp.Results[i]; + string name = e.GetName(); + if (fnf != null && fnf.Accept(this, name) == false) + { + continue; + } + if (name.Length > 0) + { + // if !files we don't need to create SmbFiles here + SmbFile f = new SmbFile(this, name, e.GetType(), AttrReadonly + | AttrDirectory, 0L, 0L, 0L); + if (ff != null && ff.Accept(f) == false) + { + continue; + } + if (files) + { + list.Add(f); + } + else + { + list.Add(name); + } + } + } + if (GetType() != TypeWorkgroup) + { + break; + } + req.SubCommand = unchecked(SmbComTransaction.NetServerEnum3); + req.Reset(0, ((NetServerEnum2Response)resp).LastName); + resp.Reset(); + } + while (more); + } + + /// + /// + /// + internal virtual void DoFindFirstNext(List list, bool files, string wildcard + , int searchAttributes, ISmbFilenameFilter fnf, ISmbFileFilter ff) + { + SmbComTransaction req; + Trans2FindFirst2Response resp; + int sid; + string path = GetUncPath0(); + string p = Url.AbsolutePath; + if (p.LastIndexOf('/') != (p.Length - 1)) + { + throw new SmbException(Url + " directory must end with '/'"); + } + req = new Trans2FindFirst2(path, wildcard, searchAttributes); + resp = new Trans2FindFirst2Response(); + if (Log.Level >= 3) + { + Log.WriteLine("doFindFirstNext: " + req.Path); + } + Send(req, resp); + sid = resp.Sid; + req = new Trans2FindNext2(sid, resp.ResumeKey, resp.LastName); + resp.SubCommand = SmbComTransaction.Trans2FindNext2; + for (; ; ) + { + for (int i = 0; i < resp.NumEntries; i++) + { + IFileEntry e = resp.Results[i]; + string name = e.GetName(); + if (name.Length < 3) + { + int h = name.GetHashCode(); + if (h == HashDot || h == HashDotDot) + { + if (name.Equals(".") || name.Equals("..")) + { + continue; + } + } + } + if (fnf != null && fnf.Accept(this, name) == false) + { + continue; + } + if (name.Length > 0) + { + SmbFile f = new SmbFile(this, name, TypeFilesystem, e.GetAttributes + (), e.CreateTime(), e.LastModified(), e.Length()); + if (ff != null && ff.Accept(f) == false) + { + continue; + } + if (files) + { + list.Add(f); + } + else + { + list.Add(name); + } + } + } + if (resp.IsEndOfSearch || resp.NumEntries == 0) + { + break; + } + req.Reset(resp.ResumeKey, resp.LastName); + resp.Reset(); + Send(req, resp); + } + try + { + Send(new SmbComFindClose2(sid), Blank_resp()); + } + catch (SmbException se) + { + if (Log.Level >= 4) + { + Runtime.PrintStackTrace(se, Log); + } + } + } + + /// + /// Changes the name of the file this SmbFile represents to the name + /// designated by the SmbFile argument. + /// + /// + /// Changes the name of the file this SmbFile represents to the name + /// designated by the SmbFile argument. + ///

+ /// Remember: SmbFiles are immutible and therefore + /// the path associated with this SmbFile object will not + /// change). To access the renamed file it is necessary to construct a + /// new SmbFile. + /// + /// An SmbFile that represents the new pathname + /// If the dest argument is null + /// + /// + public virtual void RenameTo(SmbFile dest) + { + if (GetUncPath0().Length == 1 || dest.GetUncPath0().Length == 1) + { + throw new SmbException("Invalid operation for workgroups, servers, or shares"); + } + ResolveDfs(null); + dest.ResolveDfs(null); + if (!Tree.Equals(dest.Tree)) + { + throw new SmbException("Invalid operation for workgroups, servers, or shares"); + } + if (Log.Level >= 3) + { + Log.WriteLine("renameTo: " + Unc + " -> " + dest.Unc); + } + _attrExpiration = _sizeExpiration = 0; + dest._attrExpiration = 0; + Send(new SmbComRename(Unc, dest.Unc), Blank_resp()); + } + + internal class WriterThread : Thread + { + internal byte[] B; + + internal int N; + + internal long Off; + + internal bool Ready; + + internal SmbFile Dest; + + internal SmbException E; + + internal bool UseNtSmbs; + + internal SmbComWriteAndX Reqx; + + internal SmbComWrite Req; + + internal ServerMessageBlock Resp; + + /// + public WriterThread(SmbFile enclosing) + : base("JCIFS-WriterThread") + { + this._enclosing = enclosing; + UseNtSmbs = this._enclosing.Tree.Session.transport.HasCapability(SmbConstants.CapNtSmbs); + if (UseNtSmbs) + { + Reqx = new SmbComWriteAndX(); + Resp = new SmbComWriteAndXResponse(); + } + else + { + Req = new SmbComWrite(); + Resp = new SmbComWriteResponse(); + } + Ready = false; + } + + internal virtual void Write(byte[] b, int n, SmbFile dest, long off) + { + lock (this) + { + this.B = b; + this.N = n; + this.Dest = dest; + this.Off = off; + Ready = false; + Runtime.Notify(this); + } + } + + public override void Run() + { + lock (this) + { + try + { + for (; ; ) + { + Runtime.Notify(this); + Ready = true; + while (Ready) + { + Runtime.Wait(this); + } + if (N == -1) + { + return; + } + if (UseNtSmbs) + { + Reqx.SetParam(Dest.Fid, Off, N, B, 0, N); + Dest.Send(Reqx, Resp); + } + else + { + Req.SetParam(Dest.Fid, Off, N, B, 0, N); + Dest.Send(Req, Resp); + } + } + } + catch (SmbException e) + { + this.E = e; + } + catch (Exception x) + { + E = new SmbException("WriterThread", x); + } + Runtime.Notify(this); + } + } + + private readonly SmbFile _enclosing; + } + + /// + internal virtual void CopyTo0(SmbFile dest, byte[][] b, int bsize, WriterThread + w, SmbComReadAndX req, SmbComReadAndXResponse resp) + { + int i; + if (_attrExpiration < Runtime.CurrentTimeMillis()) + { + _attributes = AttrReadonly | AttrDirectory; + _createTime = 0L; + _lastModified = 0L; + _isExists = false; + IInfo info = QueryPath(GetUncPath0(), Trans2QueryPathInformationResponse.SMB_QUERY_FILE_BASIC_INFO + ); + _attributes = info.GetAttributes(); + _createTime = info.GetCreateTime(); + _lastModified = info.GetLastWriteTime(); + _isExists = true; + _attrExpiration = Runtime.CurrentTimeMillis() + AttrExpirationPeriod; + } + if (IsDirectory()) + { + SmbFile[] files; + SmbFile ndest; + string path = dest.GetUncPath0(); + if (path.Length > 1) + { + try + { + dest.Mkdir(); + dest.SetPathInformation(_attributes, _createTime, _lastModified); + } + catch (SmbException se) + { + if (se.GetNtStatus() != NtStatus.NtStatusAccessDenied && se.GetNtStatus() != NtStatus + .NtStatusObjectNameCollision) + { + throw; + } + } + } + files = ListFiles("*", AttrDirectory | AttrHidden | AttrSystem, null, null); + try + { + for (i = 0; i < files.Length; i++) + { + ndest = new SmbFile(dest, files[i].GetName(), files[i].Type, files[i]._attributes, + files[i]._createTime, files[i]._lastModified, files[i]._size); + files[i].CopyTo0(ndest, b, bsize, w, req, resp); + } + } + catch (UnknownHostException uhe) + { + throw new SmbException(Url.ToString(), uhe); + } + catch (UriFormatException mue) + { + throw new SmbException(Url.ToString(), mue); + } + } + else + { + long off; + try + { + Open(ORdonly, 0, AttrNormal, 0); + try + { + dest.Open(OCreat | OWronly | OTrunc, SmbConstants.FileWriteData | + SmbConstants.FileWriteAttributes, _attributes, 0); + } + catch (SmbAuthException sae) + { + if ((dest._attributes & AttrReadonly) != 0) + { + dest.SetPathInformation(dest._attributes & ~AttrReadonly, 0L, 0L); + dest.Open(OCreat | OWronly | OTrunc, SmbConstants.FileWriteData | + SmbConstants.FileWriteAttributes, _attributes, 0); + } + else + { + throw; + } + } + i = 0; + off = 0L; + for (; ; ) + { + req.SetParam(Fid, off, bsize); + resp.SetParam(b[i], 0); + Send(req, resp); + lock (w) + { + if (w.E != null) + { + throw w.E; + } + while (!w.Ready) + { + try + { + Runtime.Wait(w); + } + catch (Exception ie) + { + throw new SmbException(dest.Url.ToString(), ie); + } + } + if (w.E != null) + { + throw w.E; + } + if (resp.DataLength <= 0) + { + break; + } + w.Write(b[i], resp.DataLength, dest, off); + } + i = i == 1 ? 0 : 1; + off += resp.DataLength; + } + dest.Send(new Trans2SetFileInformation(dest.Fid, _attributes, _createTime, _lastModified + ), new Trans2SetFileInformationResponse()); + dest.Close(0L); + } + catch (SmbException se) + { + if (IgnoreCopyToException == false) + { + throw new SmbException("Failed to copy file from [" + ToString() + "] to [" + + dest + "]", se); + } + if (Log.Level > 1) + { + Runtime.PrintStackTrace(se, Log); + } + } + finally + { + Close(); + } + } + } + + ///

+ /// This method will copy the file or directory represented by this + /// SmbFile and it's sub-contents to the location specified by the + /// dest parameter. + /// + /// + /// This method will copy the file or directory represented by this + /// SmbFile and it's sub-contents to the location specified by the + /// dest parameter. This file and the destination file do not + /// need to be on the same host. This operation does not copy extended + /// file attibutes such as ACLs but it does copy regular attributes as + /// well as create and last write times. This method is almost twice as + /// efficient as manually copying as it employs an additional write + /// thread to read and write data concurrently. + ///

+ /// It is not possible (nor meaningful) to copy entire workgroups or + /// servers. + /// + /// the destination file or directory + /// SmbException + /// + public virtual void CopyTo(SmbFile dest) + { + SmbComReadAndX req; + SmbComReadAndXResponse resp; + WriterThread w; + int bsize; + byte[][] b; + if (_share == null || dest._share == null) + { + throw new SmbException("Invalid operation for workgroups or servers"); + } + req = new SmbComReadAndX(); + resp = new SmbComReadAndXResponse(); + Connect0(); + dest.Connect0(); + ResolveDfs(null); + try + { + if (GetAddress().Equals(dest.GetAddress()) && _canon.RegionMatches(true, 0, dest._canon + , 0, Math.Min(_canon.Length, dest._canon.Length))) + { + throw new SmbException("Source and destination paths overlap."); + } + } + catch (UnknownHostException) + { + } + w = new WriterThread(this); + w.SetDaemon(true); + w.Start(); + SmbTransport t1 = Tree.Session.transport; + SmbTransport t2 = dest.Tree.Session.transport; + if (t1.SndBufSize < t2.SndBufSize) + { + t2.SndBufSize = t1.SndBufSize; + } + else + { + t1.SndBufSize = t2.SndBufSize; + } + bsize = Math.Min(t1.RcvBufSize - 70, t1.SndBufSize - 70); + b = new[] { new byte[bsize], new byte[bsize] }; + try + { + CopyTo0(dest, b, bsize, w, req, resp); + } + finally + { + w.Write(null, -1, null, 0); + } + } + + ///

+ /// This method will delete the file or directory specified by this + /// SmbFile. + /// + /// + /// This method will delete the file or directory specified by this + /// SmbFile. If the target is a directory, the contents of + /// the directory will be deleted as well. If a file within the directory or + /// it's sub-directories is marked read-only, the read-only status will + /// be removed and the file will be deleted. + /// + /// SmbException + /// + public virtual void Delete() + { + Exists(); + GetUncPath0(); + Delete(Unc); + } + + /// + internal virtual void Delete(string fileName) + { + if (GetUncPath0().Length == 1) + { + throw new SmbException("Invalid operation for workgroups, servers, or shares"); + } + if (Runtime.CurrentTimeMillis() > _attrExpiration) + { + _attributes = AttrReadonly | AttrDirectory; + _createTime = 0L; + _lastModified = 0L; + _isExists = false; + IInfo info = QueryPath(GetUncPath0(), Trans2QueryPathInformationResponse.SMB_QUERY_FILE_BASIC_INFO + ); + _attributes = info.GetAttributes(); + _createTime = info.GetCreateTime(); + _lastModified = info.GetLastWriteTime(); + _attrExpiration = Runtime.CurrentTimeMillis() + AttrExpirationPeriod; + _isExists = true; + } + if ((_attributes & AttrReadonly) != 0) + { + SetReadWrite(); + } + if (Log.Level >= 3) + { + Log.WriteLine("delete: " + fileName); + } + if ((_attributes & AttrDirectory) != 0) + { + try + { + SmbFile[] l = ListFiles("*", AttrDirectory | AttrHidden | AttrSystem, null, null + ); + for (int i = 0; i < l.Length; i++) + { + l[i].Delete(); + } + } + catch (SmbException se) + { + if (se.GetNtStatus() != NtStatus.NtStatusNoSuchFile) + { + throw; + } + } + Send(new SmbComDeleteDirectory(fileName), Blank_resp()); + } + else + { + Send(new SmbComDelete(fileName), Blank_resp()); + } + _attrExpiration = _sizeExpiration = 0; + } + + /// Returns the length of this SmbFile in bytes. + /// + /// Returns the length of this SmbFile in bytes. If this object + /// is a TYPE_SHARE the total capacity of the disk shared in + /// bytes is returned. If this object is a directory or a type other than + /// TYPE_SHARE, 0L is returned. + /// + /// + /// The length of the file in bytes or 0 if this + /// SmbFile is not a file. + /// + /// SmbException + /// + public virtual long Length() + { + if (_sizeExpiration > Runtime.CurrentTimeMillis()) + { + return _size; + } + if (GetType() == TypeShare) + { + Trans2QueryFsInformationResponse response; + int level = Trans2QueryFsInformationResponse.SMB_INFO_ALLOCATION; + response = new Trans2QueryFsInformationResponse(level); + Send(new Trans2QueryFsInformation(level), response); + _size = response.Info.GetCapacity(); + } + else + { + if (GetUncPath0().Length > 1 && Type != TypeNamedPipe) + { + IInfo info = QueryPath(GetUncPath0(), Trans2QueryPathInformationResponse.SMB_QUERY_FILE_STANDARD_INFO + ); + _size = info.GetSize(); + } + else + { + _size = 0L; + } + } + _sizeExpiration = Runtime.CurrentTimeMillis() + AttrExpirationPeriod; + return _size; + } + + /// + /// This method returns the free disk space in bytes of the drive this share + /// represents or the drive on which the directory or file resides. + /// + /// + /// This method returns the free disk space in bytes of the drive this share + /// represents or the drive on which the directory or file resides. Objects + /// other than TYPE_SHARE or TYPE_FILESYSTEM will result + /// in 0L being returned. + /// + /// + /// the free disk space in bytes of the drive on which this file or + /// directory resides + /// + /// + public virtual long GetDiskFreeSpace() + { + if (GetType() == TypeShare || Type == TypeFilesystem) + { + int level = Trans2QueryFsInformationResponse.SmbFsFullSizeInformation; + try + { + return QueryFsInformation(level); + } + catch (SmbException ex) + { + switch (ex.GetNtStatus()) + { + case NtStatus.NtStatusInvalidInfoClass: + case NtStatus.NtStatusUnsuccessful: + { + // NetApp Filer + // SMB_FS_FULL_SIZE_INFORMATION not supported by the server. + level = Trans2QueryFsInformationResponse.SMB_INFO_ALLOCATION; + return QueryFsInformation(level); + } + } + throw; + } + } + return 0L; + } + + /// + private long QueryFsInformation(int level) + { + Trans2QueryFsInformationResponse response; + response = new Trans2QueryFsInformationResponse(level); + Send(new Trans2QueryFsInformation(level), response); + if (Type == TypeShare) + { + _size = response.Info.GetCapacity(); + _sizeExpiration = Runtime.CurrentTimeMillis() + AttrExpirationPeriod; + } + return response.Info.GetFree(); + } + + /// + /// Creates a directory with the path specified by this + /// SmbFile. + /// + /// + /// Creates a directory with the path specified by this + /// SmbFile. For this method to be successful, the target + /// must not already exist. This method will fail when + /// used with smb://, smb://workgroup/, + /// smb://server/, or smb://server/share/ URLs + /// because workgroups, servers, and shares cannot be dynamically created + /// (although in the future it may be possible to create shares). + /// + /// SmbException + /// + public virtual void Mkdir() + { + string path = GetUncPath0(); + if (path.Length == 1) + { + throw new SmbException("Invalid operation for workgroups, servers, or shares"); + } + if (Log.Level >= 3) + { + Log.WriteLine("mkdir: " + path); + } + Send(new SmbComCreateDirectory(path), Blank_resp()); + _attrExpiration = _sizeExpiration = 0; + } + + /// + /// Creates a directory with the path specified by this SmbFile + /// and any parent directories that do not exist. + /// + /// + /// Creates a directory with the path specified by this SmbFile + /// and any parent directories that do not exist. This method will fail + /// when used with smb://, smb://workgroup/, + /// smb://server/, or smb://server/share/ URLs + /// because workgroups, servers, and shares cannot be dynamically created + /// (although in the future it may be possible to create shares). + /// + /// SmbException + /// + public virtual void Mkdirs() + { + SmbFile parent; + try + { + parent = new SmbFile(GetParent(), Auth); + } + catch (IOException) + { + return; + } + if (parent.Exists() == false) + { + parent.Mkdirs(); + } + Mkdir(); + } + + /// Create a new file but fail if it already exists. + /// + /// Create a new file but fail if it already exists. The check for + /// existance of the file and it's creation are an atomic operation with + /// respect to other filesystem activities. + /// + /// + public virtual void CreateNewFile() + { + if (GetUncPath0().Length == 1) + { + throw new SmbException("Invalid operation for workgroups, servers, or shares"); + } + Close(Open0(ORdwr | OCreat | OExcl, 0, AttrNormal, 0), 0L); + } + + /// + internal virtual void SetPathInformation(int attrs, long ctime, long mtime) + { + int f; + int dir; + Exists(); + dir = _attributes & AttrDirectory; + f = Open0(ORdonly, SmbConstants.FileWriteAttributes, dir, dir != 0 ? 0x0001 + : 0x0040); + Send(new Trans2SetFileInformation(f, attrs | dir, ctime, mtime), new Trans2SetFileInformationResponse + ()); + Close(f, 0L); + _attrExpiration = 0; + } + + /// Set the create time of the file. + /// + /// Set the create time of the file. The time is specified as milliseconds + /// from Jan 1, 1970 which is the same as that which is returned by the + /// createTime() method. + ///

+ /// This method does not apply to workgroups, servers, or shares. + /// + /// the create time as milliseconds since Jan 1, 1970 + /// + public virtual void SetCreateTime(long time) + { + if (GetUncPath0().Length == 1) + { + throw new SmbException("Invalid operation for workgroups, servers, or shares"); + } + SetPathInformation(0, time, 0L); + } + + ///

Set the last modified time of the file. + /// + /// Set the last modified time of the file. The time is specified as milliseconds + /// from Jan 1, 1970 which is the same as that which is returned by the + /// lastModified(), getLastModified(), and getDate() methods. + ///

+ /// This method does not apply to workgroups, servers, or shares. + /// + /// the last modified time as milliseconds since Jan 1, 1970 + /// + public virtual void SetLastModified(long time) + { + if (GetUncPath0().Length == 1) + { + throw new SmbException("Invalid operation for workgroups, servers, or shares"); + } + SetPathInformation(0, 0L, time); + } + + ///

Return the attributes of this file. + /// + /// Return the attributes of this file. Attributes are represented as a + /// bitset that must be masked with ATTR_* constants to determine + /// if they are set or unset. The value returned is suitable for use with + /// the setAttributes() method. + /// + /// the ATTR_* attributes associated with this file + /// SmbException + /// + public virtual int GetAttributes() + { + if (GetUncPath0().Length == 1) + { + return 0; + } + Exists(); + return _attributes & AttrGetMask; + } + + /// Set the attributes of this file. + /// + /// Set the attributes of this file. Attributes are composed into a + /// bitset by bitwise ORing the ATTR_* constants. Setting the + /// value returned by getAttributes will result in both files + /// having the same attributes. + /// + /// SmbException + /// + public virtual void SetAttributes(int attrs) + { + if (GetUncPath0().Length == 1) + { + throw new SmbException("Invalid operation for workgroups, servers, or shares"); + } + SetPathInformation(attrs & AttrSetMask, 0L, 0L); + } + + /// Make this file read-only. + /// + /// Make this file read-only. This is shorthand for setAttributes( + /// getAttributes() | ATTR_READ_ONLY ). + /// + /// SmbException + /// + public virtual void SetReadOnly() + { + SetAttributes(GetAttributes() | AttrReadonly); + } + + /// Turn off the read-only attribute of this file. + /// + /// Turn off the read-only attribute of this file. This is shorthand for + /// setAttributes( getAttributes() & ~ATTR_READONLY ). + /// + /// SmbException + /// + public virtual void SetReadWrite() + { + SetAttributes(GetAttributes() & ~AttrReadonly); + } + + /// + /// Returns a + /// System.Uri + /// for this SmbFile. The + /// URL may be used as any other URL might to + /// access an SMB resource. Currently only retrieving data and information + /// is supported (i.e. no doOutput). + /// + /// + /// A new + /// System.Uri + /// for this SmbFile + /// + /// System.UriFormatException + [Obsolete(@"Use getURL() instead")] + public virtual Uri ToUrl() + { + return Url; + } + + /// + /// Computes a hashCode for this file based on the URL string and IP + /// address if the server. + /// + /// + /// Computes a hashCode for this file based on the URL string and IP + /// address if the server. The hashing function uses the hashcode of the + /// server address, the canonical representation of the URL, and does not + /// compare authentication information. In essance, two + /// SmbFile objects that refer to + /// the same file should generate the same hashcode provided it is possible + /// to make such a determination. + /// + /// A hashcode for this abstract file + /// SmbException + public override int GetHashCode() + { + int hash; + try + { + hash = GetAddress().GetHashCode(); + } + catch (UnknownHostException) + { + hash = GetServer().ToUpper().GetHashCode(); + } + GetUncPath0(); + return hash + _canon.ToUpper().GetHashCode(); + } + + protected internal virtual bool PathNamesPossiblyEqual(string path1, string path2 + ) + { + int p1; + int p2; + int l1; + int l2; + // if unsure return this method returns true + p1 = path1.LastIndexOf('/'); + p2 = path2.LastIndexOf('/'); + l1 = path1.Length - p1; + l2 = path2.Length - p2; + // anything with dots voids comparison + if (l1 > 1 && path1[p1 + 1] == '.') + { + return true; + } + if (l2 > 1 && path2[p2 + 1] == '.') + { + return true; + } + return l1 == l2 && path1.RegionMatches(true, p1, path2, p2, l1); + } + + /// Tests to see if two SmbFile objects are equal. + /// + /// Tests to see if two SmbFile objects are equal. Two + /// SmbFile objects are equal when they reference the same SMB + /// resource. More specifically, two SmbFile objects are + /// equals if their server IP addresses are equal and the canonicalized + /// representation of their URLs, minus authentication parameters, are + /// case insensitivly and lexographically equal. + ///

+ /// For example, assuming the server angus resolves to the + /// 192.168.1.15 IP address, the below URLs would result in + /// SmbFiles that are equal. + ///

+        /// smb://192.168.1.15/share/DIR/foo.txt
+        /// smb://angus/share/data/../dir/foo.txt
+        /// 
+ ///
+ /// Another SmbFile object to compare for equality + /// + /// true if the two objects refer to the same SMB resource + /// and false otherwise + /// + /// SmbException + public override bool Equals(object obj) + { + if (obj is SmbFile) + { + SmbFile f = (SmbFile)obj; + bool ret; + if (this == f) + { + return true; + } + if (PathNamesPossiblyEqual(Url.AbsolutePath, f.Url.AbsolutePath)) + { + GetUncPath0(); + f.GetUncPath0(); + if (Runtime.EqualsIgnoreCase(_canon, f._canon)) + { + try + { + ret = GetAddress().Equals(f.GetAddress()); + } + catch (UnknownHostException) + { + ret = Runtime.EqualsIgnoreCase(GetServer(), f.GetServer()); + } + return ret; + } + } + } + return false; + } + + /// Returns the string representation of this SmbFile object. + /// + /// Returns the string representation of this SmbFile object. This will + /// be the same as the URL used to construct this SmbFile. + /// This method will return the same value + /// as getPath. + /// + /// The original URL representation of this SMB resource + /// SmbException + public override string ToString() + { + return Url.ToString(); + } + + /// This URLConnection method just returns the result of length(). + /// This URLConnection method just returns the result of length(). + /// the length of this file or 0 if it refers to a directory + public int GetContentLength() + { + try + { + return (int)(Length() & unchecked(0xFFFFFFFFL)); + } + catch (SmbException) + { + } + return 0; + } + + /// This URLConnection method just returns the result of lastModified. + /// + /// This URLConnection method just returns the result of lastModified. + /// + /// the last modified data as milliseconds since Jan 1, 1970 + public long GetDate() + { + try + { + return LastModified(); + } + catch (SmbException) + { + } + return 0L; + } + + /// This URLConnection method just returns the result of lastModified. + /// + /// This URLConnection method just returns the result of lastModified. + /// + /// the last modified data as milliseconds since Jan 1, 1970 + public long GetLastModified() + { + try + { + return LastModified(); + } + catch (SmbException) + { + } + return 0L; + } + + /// This URLConnection method just returns a new SmbFileInputStream created with this file. + /// + /// This URLConnection method just returns a new SmbFileInputStream created with this file. + /// + /// thrown by SmbFileInputStream constructor + /// + public InputStream GetInputStream() + { + return new SmbFileInputStream(this); + } + + /// This URLConnection method just returns a new SmbFileOutputStream created with this file. + /// + /// This URLConnection method just returns a new SmbFileOutputStream created with this file. + /// + /// thrown by SmbFileOutputStream constructor + /// + public OutputStream GetOutputStream() + { + return new SmbFileOutputStream(this); + } + + /// + private void ProcessAces(Ace[] aces, bool resolveSids) + { + string server = GetServerWithDfs(); + int ai; + if (resolveSids) + { + Sid[] sids = new Sid[aces.Length]; + string[] names = null; + for (ai = 0; ai < aces.Length; ai++) + { + sids[ai] = aces[ai].Sid; + } + for (int off = 0; off < sids.Length; off += 64) + { + int len = sids.Length - off; + if (len > 64) + { + len = 64; + } + Sid.ResolveSids(server, Auth, sids, off, len); + } + } + else + { + for (ai = 0; ai < aces.Length; ai++) + { + aces[ai].Sid.OriginServer = server; + aces[ai].Sid.OriginAuth = Auth; + } + } + } + + /// + /// Return an array of Access Control Entry (ACE) objects representing + /// the security descriptor associated with this file or directory. + /// + /// + /// Return an array of Access Control Entry (ACE) objects representing + /// the security descriptor associated with this file or directory. + /// If no DACL is present, null is returned. If the DACL is empty, an array with 0 elements is returned. + /// + /// + /// Attempt to resolve the SIDs within each ACE form + /// their numeric representation to their corresponding account names. + /// + /// + public virtual Ace[] GetSecurity(bool resolveSids) + { + int f; + Ace[] aces; + f = Open0(ORdonly, SmbConstants.ReadControl, 0, IsDirectory() ? 1 : 0); + NtTransQuerySecurityDesc request = new NtTransQuerySecurityDesc(f, 0x04); + NtTransQuerySecurityDescResponse response = new NtTransQuerySecurityDescResponse( + ); + try + { + Send(request, response); + } + finally + { + Close(f, 0L); + } + aces = response.SecurityDescriptor.Aces; + if (aces != null) + { + ProcessAces(aces, resolveSids); + } + return aces; + } + + /// + /// Return an array of Access Control Entry (ACE) objects representing + /// the share permissions on the share exporting this file or directory. + /// + /// + /// Return an array of Access Control Entry (ACE) objects representing + /// the share permissions on the share exporting this file or directory. + /// If no DACL is present, null is returned. If the DACL is empty, an array with 0 elements is returned. + ///

+ /// Note that this is different from calling getSecurity on a + /// share. There are actually two different ACLs for shares - the ACL on + /// the share and the ACL on the folder being shared. + /// Go to Computer Management + /// > System Tools > Shared Folders > Shares and + /// look at the Properties for a share. You will see two tabs - one + /// for "Share Permissions" and another for "Security". These correspond to + /// the ACLs returned by getShareSecurity and getSecurity + /// respectively. + /// + /// + /// Attempt to resolve the SIDs within each ACE form + /// their numeric representation to their corresponding account names. + /// + /// + public virtual Ace[] GetShareSecurity(bool resolveSids) + { + string p = Url.AbsolutePath; + MsrpcShareGetInfo rpc; + DcerpcHandle handle; + Ace[] aces; + ResolveDfs(null); + string server = GetServerWithDfs(); + rpc = new MsrpcShareGetInfo(server, Tree.Share); + handle = DcerpcHandle.GetHandle("ncacn_np:" + server + "[\\PIPE\\srvsvc]", Auth); + try + { + handle.Sendrecv(rpc); + if (rpc.Retval != 0) + { + throw new SmbException(rpc.Retval, true); + } + aces = rpc.GetSecurity(); + if (aces != null) + { + ProcessAces(aces, resolveSids); + } + } + finally + { + try + { + handle.Close(); + } + catch (IOException ioe) + { + if (Log.Level >= 1) + { + Runtime.PrintStackTrace(ioe, Log); + } + } + } + return aces; + } + + ///

+ /// Return an array of Access Control Entry (ACE) objects representing + /// the security descriptor associated with this file or directory. + /// + /// + /// Return an array of Access Control Entry (ACE) objects representing + /// the security descriptor associated with this file or directory. + ///

+ /// Initially, the SIDs within each ACE will not be resolved however when + /// getType(), getDomainName(), getAccountName(), + /// or toString() is called, the names will attempt to be + /// resolved. If the names cannot be resolved (e.g. due to temporary + /// network failure), the said methods will return default values (usually + /// S-X-Y-Z strings of fragments of). + ///

+ /// Alternatively getSecurity(true) may be used to resolve all + /// SIDs together and detect network failures. + /// + /// + public virtual Ace[] GetSecurity() + { + return GetSecurity(false); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFileExtensions.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFileExtensions.cs new file mode 100644 index 0000000000..2ebcfa20f4 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFileExtensions.cs @@ -0,0 +1,133 @@ +// SmbFileExtensions.cs implementation by J. Arturo +// +// 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 System.Threading.Tasks; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + public static class SmbFileExtensions + { + ///

+ /// Get file's creation date converted to local timezone + /// + /// + /// + public static DateTime GetLocalCreateTime(this SmbFile smbFile) + { + return TimeZoneInfo.ConvertTime(Extensions.CreateDateFromUTC(smbFile.CreateTime()), + TimeZoneInfo.Local); + } + + /// + /// Get file's last modified date converted to local timezone + /// + /// + /// + public static DateTime GetLocalLastModified(this SmbFile smbFile) + { + return TimeZoneInfo.ConvertTime(Extensions.CreateDateFromUTC(smbFile.LastModified()), + TimeZoneInfo.Local); + } + + + /// + /// List files async + /// + /// + /// + public static Task ListFilesAsync(this SmbFile smbFile) + { + return Task.Run(() => smbFile.ListFiles()); + } + + /// + /// List files async + /// + /// + /// + /// + public static Task ListFilesAsync(this SmbFile smbFile, string wildcard) + { + return Task.Run(() => smbFile.ListFiles(wildcard)); + } + + /// + /// List files async + /// + /// + /// + public static Task ListAsync(this SmbFile smbFile) + { + return Task.Run(() => smbFile.List()); + } + + /// + /// MkDir async method + /// + /// + /// + public static Task MkDirAsync(this SmbFile smbFile) + { + return Task.Run(() => smbFile.Mkdir()); + } + + + /// + /// Delete file async + /// + /// + /// + public static Task DeleteAsync(this SmbFile smbFile) + { + return Task.Run(() => smbFile.Delete()); + } + + /// + /// Rename file async + /// + /// + /// + /// + public static Task RenameToAsync(this SmbFile smbFile, SmbFile destination) + { + return Task.Run(() => smbFile.RenameTo(destination)); + } + + /// + /// Get input stream async + /// + /// + /// + public static Task GetInputStreamAsync(this SmbFile smbFile) + { + return Task.Run(() => smbFile.GetInputStream()); + } + + + /// + /// Get output stream async + /// + /// + /// + /// + public static Task GetOutputStreamAsync(this SmbFile smbFile, bool append = false) + { + return Task.Run(() => new SmbFileOutputStream(smbFile, append) as OutputStream); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFileFilter.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFileFilter.cs new file mode 100644 index 0000000000..196bfc1b6d --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFileFilter.cs @@ -0,0 +1,24 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + public interface ISmbFileFilter + { + /// + bool Accept(SmbFile file); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFileInputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFileInputStream.cs new file mode 100644 index 0000000000..a9a0ea1129 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFileInputStream.cs @@ -0,0 +1,339 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using SharpCifs.Util.Sharpen; +using SharpCifs.Util.Transport; + +namespace SharpCifs.Smb +{ + /// This InputStream can read bytes from a file on an SMB file server. + /// This InputStream can read bytes from a file on an SMB file server. Offsets are 64 bits. + /// + public class SmbFileInputStream : InputStream + { + private long _fp; + + private int _readSize; + + private int _openFlags; + + private int _access; + + private byte[] _tmp = new byte[1]; + + internal SmbFile File; + + /// + /// Creates an + /// System.IO.InputStream + /// for reading bytes from a file on + /// an SMB server addressed by the url parameter. See + /// SmbFile + /// for a detailed description and examples of the smb + /// URL syntax. + /// + /// An smb URL string representing the file to read from + /// + /// + /// + public SmbFileInputStream(string url) : this(new SmbFile(url)) + { + } + + /// + /// Creates an + /// System.IO.InputStream + /// for reading bytes from a file on + /// an SMB server represented by the + /// SmbFile + /// parameter. See + /// SmbFile + /// for a detailed description and examples of + /// the smb URL syntax. + /// + /// An SmbFile specifying the file to read from + /// + /// + /// + public SmbFileInputStream(SmbFile file) : this(file, SmbFile.ORdonly) + { + } + + /// + /// + /// + internal SmbFileInputStream(SmbFile file, int openFlags) + { + this.File = file; + this._openFlags = openFlags & 0xFFFF; + _access = ((int)(((uint)openFlags) >> 16)) & 0xFFFF; + if (file.Type != SmbFile.TypeNamedPipe) + { + file.Open(openFlags, _access, SmbFile.AttrNormal, 0); + this._openFlags &= ~(SmbFile.OCreat | SmbFile.OTrunc); + } + else + { + file.Connect0(); + } + _readSize = Math.Min(file.Tree.Session.transport.RcvBufSize - 70, file.Tree.Session + .transport.Server.MaxBufferSize - 70); + } + + protected internal virtual IOException SeToIoe(SmbException se) + { + IOException ioe = se; + Exception root = se.GetRootCause(); + if (root is TransportException) + { + ioe = (TransportException)root; + root = ((TransportException)ioe).GetRootCause(); + } + if (root is Exception) + { + ioe = new IOException(root.Message); + ioe.InitCause(root); + } + return ioe; + } + + /// Closes this input stream and releases any system resources associated with the stream. + /// + /// Closes this input stream and releases any system resources associated with the stream. + /// + /// if a network error occurs + public override void Close() + { + try + { + File.Close(); + _tmp = null; + } + catch (SmbException se) + { + throw SeToIoe(se); + } + } + + /// Reads a byte of data from this input stream. + /// Reads a byte of data from this input stream. + /// if a network error occurs + public override int Read() + { + // need oplocks to cache otherwise use BufferedInputStream + if (Read(_tmp, 0, 1) == -1) + { + return -1; + } + return _tmp[0] & unchecked(0xFF); + } + + /// Reads up to b.length bytes of data from this input stream into an array of bytes. + /// + /// Reads up to b.length bytes of data from this input stream into an array of bytes. + /// + /// if a network error occurs + public override int Read(byte[] b) + { + return Read(b, 0, b.Length); + } + + /// Reads up to len bytes of data from this input stream into an array of bytes. + /// + /// Reads up to len bytes of data from this input stream into an array of bytes. + /// + /// if a network error occurs + public override int Read(byte[] b, int off, int len) + { + return ReadDirect(b, off, len); + } + + /// + public virtual int ReadDirect(byte[] b, int off, int len) + { + if (len <= 0) + { + return 0; + } + + long start = _fp; + if (_tmp == null) + { + throw new IOException("Bad file descriptor"); + } + + // ensure file is open + File.Open(_openFlags, _access, SmbFile.AttrNormal, 0); + if (File.Log.Level >= 4) + { + File.Log.WriteLine("read: fid=" + File.Fid + ",off=" + off + ",len=" + len); + } + + SmbComReadAndXResponse response = new SmbComReadAndXResponse(b, off); + if (File.Type == SmbFile.TypeNamedPipe) + { + response.ResponseTimeout = 0; + } + + int r; + int n; + do + { + r = len > _readSize ? _readSize : len; + if (File.Log.Level >= 4) + { + File.Log.WriteLine("read: len=" + len + ",r=" + r + ",fp=" + _fp); + } + + try + { + SmbComReadAndX request = new SmbComReadAndX(File.Fid, _fp, r, null); + if (File.Type == SmbFile.TypeNamedPipe) + { + request.MinCount = request.MaxCount = request.Remaining = 1024; + } + //œǂݍł炵B + File.Send(request, response); + } + catch (SmbException se) + { + if (File.Type == SmbFile.TypeNamedPipe && se.GetNtStatus() == NtStatus.NtStatusPipeBroken) + { + return -1; + } + throw SeToIoe(se); + } + + if ((n = response.DataLength) <= 0) + { + return (int)((_fp - start) > 0L ? _fp - start : -1); + } + + _fp += n; + len -= n; + response.Off += n; + } + while (len > 0 && n == r); + + + return (int)(_fp - start); + } + + /// This stream class is unbuffered. + /// + /// This stream class is unbuffered. Therefore this method will always + /// return 0 for streams connected to regular files. However, a + /// stream created from a Named Pipe this method will query the server using a + /// "peek named pipe" operation and return the number of available bytes + /// on the server. + /// + /// + public override int Available() + { + SmbNamedPipe pipe; + TransPeekNamedPipe req; + TransPeekNamedPipeResponse resp; + if (File.Type != SmbFile.TypeNamedPipe) + { + return 0; + } + try + { + pipe = (SmbNamedPipe)File; + File.Open(SmbFile.OExcl, pipe.PipeType & 0xFF0000, SmbFile.AttrNormal + , 0); + req = new TransPeekNamedPipe(File.Unc, File.Fid); + resp = new TransPeekNamedPipeResponse(pipe); + pipe.Send(req, resp); + if (resp.status == TransPeekNamedPipeResponse.StatusDisconnected || resp.status + == TransPeekNamedPipeResponse.StatusServerEndClosed) + { + File.Opened = false; + return 0; + } + return resp.Available; + } + catch (SmbException se) + { + throw SeToIoe(se); + } + } + + /// Skip n bytes of data on this stream. + /// + /// Skip n bytes of data on this stream. This operation will not result + /// in any IO with the server. Unlink InputStream value less than + /// the one provided will not be returned if it exceeds the end of the file + /// (if this is a problem let us know). + /// + /// + public override long Skip(long n) + { + if (n > 0) + { + _fp += n; + return n; + } + return 0; + } + + + /// + /// Position in Stream + /// + /// + /// Add by dobes + /// mod interface to WrappedSystemStream readable, for random access. + /// + internal override long Position { + get { return this._fp; } + set + { + var tmpPos = value; + var length = File.Length(); + if (tmpPos < 0) + tmpPos = 0; + else if (length < tmpPos) + tmpPos = length; + this._fp = tmpPos; + } + } + + /// + /// + /// + /// + /// + /// Add by dobes + /// mod interface to WrappedSystemStream readable, for random access. + /// + internal override bool CanSeek() + { + return (File.Length() >= 0); + } + + /// + /// Get file length + /// + public override long Length + { + get { return File.Length(); } + } + + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFileOutputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFileOutputStream.cs new file mode 100644 index 0000000000..58c704dd70 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFileOutputStream.cs @@ -0,0 +1,335 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.IO; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + /// This OutputStream can write bytes to a file on an SMB file server. + /// + /// This OutputStream can write bytes to a file on an SMB file server. + /// + public class SmbFileOutputStream : OutputStream + { + private SmbFile _file; + + private bool _append; + + private bool _useNtSmbs; + + private int _openFlags; + + private int _access; + + private int _writeSize; + + private long _fp; + + private byte[] _tmp = new byte[1]; + + private SmbComWriteAndX _reqx; + + private SmbComWriteAndXResponse _rspx; + + private SmbComWrite _req; + + private SmbComWriteResponse _rsp; + + /// + /// Creates an + /// System.IO.OutputStream + /// for writing to a file + /// on an SMB server addressed by the URL parameter. See + /// SmbFile + /// for a detailed description and examples of + /// the smb URL syntax. + /// + /// An smb URL string representing the file to write to + /// + /// + /// + public SmbFileOutputStream(string url) : this(url, false) + { + } + + /// + /// Creates an + /// System.IO.OutputStream + /// for writing bytes to a file on + /// an SMB server represented by the + /// SmbFile + /// parameter. See + /// SmbFile + /// for a detailed description and examples of + /// the smb URL syntax. + /// + /// An SmbFile specifying the file to write to + /// + /// + /// + public SmbFileOutputStream(SmbFile file) : this(file, false) + { + } + + /// + /// Creates an + /// System.IO.OutputStream + /// for writing bytes to a file on an + /// SMB server addressed by the URL parameter. See + /// SmbFile + /// for a detailed description and examples of the smb URL syntax. If the + /// second argument is true, then bytes will be written to the + /// end of the file rather than the beginning. + /// + /// An smb URL string representing the file to write to + /// Append to the end of file + /// + /// + /// + public SmbFileOutputStream(string url, bool append) : this(new SmbFile(url), append + ) + { + } + + /// + /// Creates an + /// System.IO.OutputStream + /// for writing bytes to a file + /// on an SMB server addressed by the SmbFile parameter. See + /// SmbFile + /// for a detailed description and examples of + /// the smb URL syntax. If the second argument is true, then + /// bytes will be written to the end of the file rather than the beginning. + /// + /// An SmbFile representing the file to write to + /// Append to the end of file + /// + /// + /// + public SmbFileOutputStream(SmbFile file, bool append) : this(file, append, append + ? SmbFile.OCreat | SmbFile.OWronly | SmbFile.OAppend : SmbFile.OCreat | SmbFile + .OWronly | SmbFile.OTrunc) + { + } + + /// + /// Creates an + /// System.IO.OutputStream + /// for writing bytes to a file + /// on an SMB server addressed by the SmbFile parameter. See + /// SmbFile + /// for a detailed description and examples of + /// the smb URL syntax. + ///

+ /// The second parameter specifies how the file should be shared. If + /// SmbFile.FILE_NO_SHARE is specified the client will + /// have exclusive access to the file. An additional open command + /// from jCIFS or another application will fail with the "file is being + /// accessed by another process" error. The FILE_SHARE_READ, + /// FILE_SHARE_WRITE, and FILE_SHARE_DELETE may be + /// combined with the bitwise OR '|' to specify that other peocesses may read, + /// write, and/or delete the file while the jCIFS user has the file open. + ///

+ /// An smb URL representing the file to write to + /// File sharing flag: SmbFile.FILE_NOSHARE or any combination of SmbFile.FILE_READ, SmbFile.FILE_WRITE, and SmbFile.FILE_DELETE + /// + /// + /// + /// + public SmbFileOutputStream(string url, int shareAccess) : this(new SmbFile(url, string.Empty + , null, shareAccess), false) + { + } + + /// + /// + /// + internal SmbFileOutputStream(SmbFile file, bool append, int openFlags) + { + this._file = file; + this._append = append; + this._openFlags = openFlags; + _access = ((int)(((uint)openFlags) >> 16)) & 0xFFFF; + if (append) + { + try + { + _fp = file.Length(); + } + catch (SmbAuthException sae) + { + throw; + } + catch (SmbException) + { + _fp = 0L; + } + } + if (file is SmbNamedPipe && file.Unc.StartsWith("\\pipe\\")) + { + file.Unc = Runtime.Substring(file.Unc, 5); + file.Send(new TransWaitNamedPipe("\\pipe" + file.Unc), new TransWaitNamedPipeResponse + ()); + } + file.Open(openFlags, _access | SmbConstants.FileWriteData, SmbFile.AttrNormal, + 0); + this._openFlags &= ~(SmbFile.OCreat | SmbFile.OTrunc); + _writeSize = file.Tree.Session.transport.SndBufSize - 70; + _useNtSmbs = file.Tree.Session.transport.HasCapability(SmbConstants.CapNtSmbs + ); + if (_useNtSmbs) + { + _reqx = new SmbComWriteAndX(); + _rspx = new SmbComWriteAndXResponse(); + } + else + { + _req = new SmbComWrite(); + _rsp = new SmbComWriteResponse(); + } + } + + /// + /// Closes this output stream and releases any system resources associated + /// with it. + /// + /// + /// Closes this output stream and releases any system resources associated + /// with it. + /// + /// if a network error occurs + public override void Close() + { + _file.Close(); + _tmp = null; + } + + /// Writes the specified byte to this file output stream. + /// Writes the specified byte to this file output stream. + /// if a network error occurs + public override void Write(int b) + { + _tmp[0] = unchecked((byte)b); + Write(_tmp, 0, 1); + } + + /// + /// Writes b.length bytes from the specified byte array to this + /// file output stream. + /// + /// + /// Writes b.length bytes from the specified byte array to this + /// file output stream. + /// + /// if a network error occurs + public override void Write(byte[] b) + { + Write(b, 0, b.Length); + } + + public virtual bool IsOpen() + { + return _file.IsOpen(); + } + + /// + internal virtual void EnsureOpen() + { + // ensure file is open + if (_file.IsOpen() == false) + { + _file.Open(_openFlags, _access | SmbConstants.FileWriteData, SmbFile.AttrNormal, + 0); + if (_append) + { + _fp = _file.Length(); + } + } + } + + /// + /// Writes len bytes from the specified byte array starting at + /// offset off to this file output stream. + /// + /// + /// Writes len bytes from the specified byte array starting at + /// offset off to this file output stream. + /// + /// The array + /// if a network error occurs + public override void Write(byte[] b, int off, int len) + { + if (_file.IsOpen() == false && _file is SmbNamedPipe) + { + _file.Send(new TransWaitNamedPipe("\\pipe" + _file.Unc), new TransWaitNamedPipeResponse + ()); + } + WriteDirect(b, off, len, 0); + } + + /// Just bypasses TransWaitNamedPipe - used by DCERPC bind. + /// Just bypasses TransWaitNamedPipe - used by DCERPC bind. + /// + public virtual void WriteDirect(byte[] b, int off, int len, int flags) + { + if (len <= 0) + { + return; + } + if (_tmp == null) + { + throw new IOException("Bad file descriptor"); + } + EnsureOpen(); + /*if (file.log.level >= 4) + { + file.log.WriteLine("write: fid=" + file.fid + ",off=" + off + ",len=" + len); + }*/ + int w; + do + { + w = len > _writeSize ? _writeSize : len; + if (_useNtSmbs) + { + _reqx.SetParam(_file.Fid, _fp, len - w, b, off, w); + if ((flags & 1) != 0) + { + _reqx.SetParam(_file.Fid, _fp, len, b, off, w); + _reqx.WriteMode = 0x8; + } + else + { + _reqx.WriteMode = 0; + } + _file.Send(_reqx, _rspx); + _fp += _rspx.Count; + len -= (int)_rspx.Count; + off += (int)_rspx.Count; + } + else + { + _req.SetParam(_file.Fid, _fp, len - w, b, off, w); + _fp += _rsp.Count; + len -= (int)_rsp.Count; + off += (int)_rsp.Count; + _file.Send(_req, _rsp); + } + } + while (len > 0); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFilenameFilter.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFilenameFilter.cs new file mode 100644 index 0000000000..b66dc133a1 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbFilenameFilter.cs @@ -0,0 +1,24 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + public interface ISmbFilenameFilter + { + /// + bool Accept(SmbFile dir, string name); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbNamedPipe.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbNamedPipe.cs new file mode 100644 index 0000000000..f09e16cca4 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbNamedPipe.cs @@ -0,0 +1,210 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Sharpen; + +namespace SharpCifs.Smb +{ + /// + /// This class will allow a Java program to read and write data to Named + /// Pipes and Transact NamedPipes. + /// + /// + /// This class will allow a Java program to read and write data to Named + /// Pipes and Transact NamedPipes. + ///

There are three Win32 function calls provided by the Windows SDK + /// that are important in the context of using jCIFS. They are: + ///

    + ///
  • CallNamedPipe A message-type pipe call that opens, + /// writes to, reads from, and closes the pipe in a single operation. + ///
  • TransactNamedPipe A message-type pipe call that + /// writes to and reads from an existing pipe descriptor in one operation. + ///
  • CreateFile, ReadFile, + /// WriteFile, and CloseFile A byte-type pipe can + /// be opened, written to, read from and closed using the standard Win32 + /// file operations. + ///
+ ///

The jCIFS API maps all of these operations into the standard Java + /// XxxputStream interface. A special PIPE_TYPE + /// flags is necessary to distinguish which type of Named Pipe behavior + /// is desired. + ///

+ /// + /// + /// + /// + /// + /// + ///
SmbNamedPipe Constructor Examples
Code SampleDescription
+	/// new SmbNamedPipe( "smb://server/IPC$/PIPE/foo",
+	/// SmbNamedPipe.PIPE_TYPE_RDWR |
+	/// SmbNamedPipe.PIPE_TYPE_CALL );
+	/// 
+ /// Open the Named Pipe foo for reading and writing. The pipe will behave like the CallNamedPipe interface. + ///
+	/// new SmbNamedPipe( "smb://server/IPC$/foo",
+	/// SmbNamedPipe.PIPE_TYPE_RDWR |
+	/// SmbNamedPipe.PIPE_TYPE_TRANSACT );
+	/// 
+ /// Open the Named Pipe foo for reading and writing. The pipe will behave like the TransactNamedPipe interface. + ///
+	/// new SmbNamedPipe( "smb://server/IPC$/foo",
+	/// SmbNamedPipe.PIPE_TYPE_RDWR );
+	/// 
+ /// Open the Named Pipe foo for reading and writing. The pipe will + /// behave as though the CreateFile, ReadFile, + /// WriteFile, and CloseFile interface was + /// being used. + ///
+ ///

See Using jCIFS to Connect to Win32 + /// Named Pipes for a detailed description of how to use jCIFS with + /// Win32 Named Pipe server processes. + /// + public class SmbNamedPipe : SmbFile + { + ///

The pipe should be opened read-only. + /// The pipe should be opened read-only. + public const int PipeTypeRdonly = ORdonly; + + /// The pipe should be opened only for writing. + /// The pipe should be opened only for writing. + public const int PipeTypeWronly = OWronly; + + /// The pipe should be opened for both reading and writing. + /// The pipe should be opened for both reading and writing. + public const int PipeTypeRdwr = ORdwr; + + /// Pipe operations should behave like the CallNamedPipe Win32 Named Pipe function. + /// + /// Pipe operations should behave like the CallNamedPipe Win32 Named Pipe function. + /// + public const int PipeTypeCall = unchecked(0x0100); + + /// Pipe operations should behave like the TransactNamedPipe Win32 Named Pipe function. + /// + /// Pipe operations should behave like the TransactNamedPipe Win32 Named Pipe function. + /// + public const int PipeTypeTransact = unchecked(0x0200); + + public const int PipeTypeDceTransact = unchecked(0x0200) | unchecked(0x0400); + + internal InputStream PipeIn; + + internal OutputStream PipeOut; + + internal int PipeType; + + /// + /// Open the Named Pipe resource specified by the url + /// parameter. + /// + /// + /// Open the Named Pipe resource specified by the url + /// parameter. The pipeType parameter should be at least one of + /// the PIPE_TYPE flags combined with the bitwise OR + /// operator |. See the examples listed above. + /// + /// + /// + public SmbNamedPipe(string url, int pipeType) : base(url) + { + this.PipeType = pipeType; + Type = TypeNamedPipe; + } + + /// + /// + public SmbNamedPipe(string url, int pipeType, NtlmPasswordAuthentication auth) : + base(url, auth) + { + this.PipeType = pipeType; + Type = TypeNamedPipe; + } + + /// + /// + public SmbNamedPipe(Uri url, int pipeType, NtlmPasswordAuthentication auth) : base + (url, auth) + { + this.PipeType = pipeType; + Type = TypeNamedPipe; + } + + /// + /// Return the InputStream used to read information + /// from this pipe instance. + /// + /// + /// Return the InputStream used to read information + /// from this pipe instance. Presumably data would first be written + /// to the OutputStream associated with this Named + /// Pipe instance although this is not a requirement (e.g. a + /// read-only named pipe would write data to this stream on + /// connection). Reading from this stream may block. Therefore it + /// may be necessary that an addition thread be used to read and + /// write to a Named Pipe. + /// + /// + public virtual InputStream GetNamedPipeInputStream() + { + if (PipeIn == null) + { + if ((PipeType & PipeTypeCall) == PipeTypeCall || (PipeType & PipeTypeTransact + ) == PipeTypeTransact) + { + PipeIn = new TransactNamedPipeInputStream(this); + } + else + { + PipeIn = new SmbFileInputStream(this, (PipeType & unchecked((int)(0xFFFF00FF))) | + OExcl); + } + } + return PipeIn; + } + + /// + /// Return the OutputStream used to write + /// information to this pipe instance. + /// + /// + /// Return the OutputStream used to write + /// information to this pipe instance. The act of writing data + /// to this stream will result in response data recieved in the + /// InputStream associated with this Named Pipe + /// instance (unless of course it does not elicite a response or the pipe is write-only). + /// + /// + public virtual OutputStream GetNamedPipeOutputStream() + { + if (PipeOut == null) + { + if ((PipeType & PipeTypeCall) == PipeTypeCall || (PipeType & PipeTypeTransact + ) == PipeTypeTransact) + { + PipeOut = new TransactNamedPipeOutputStream(this); + } + else + { + PipeOut = new SmbFileOutputStream(this, false, (PipeType & unchecked((int)(0xFFFF00FF + ))) | OExcl); + } + } + return PipeOut; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbRandomAccessFile.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbRandomAccessFile.cs new file mode 100644 index 0000000000..445a0656c8 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbRandomAccessFile.cs @@ -0,0 +1,506 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using System.Text; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + public class SmbRandomAccessFile //: DataOutput, DataInput + { + private const int WriteOptions = unchecked(0x0842); + + private SmbFile _file; + + private long _fp; + + private int _openFlags; + + private int _access; + + private int _readSize; + + private int _writeSize; + + private int _ch; + + private int _options; + + private byte[] _tmp = new byte[8]; + + private SmbComWriteAndXResponse _writeAndxResp; + + /// + /// + /// + public SmbRandomAccessFile(string url, string mode, int shareAccess) : this(new SmbFile + (url, string.Empty, null, shareAccess), mode) + { + } + + /// + /// + /// + public SmbRandomAccessFile(SmbFile file, string mode) + { + this._file = file; + if (mode.Equals("r")) + { + _openFlags = SmbFile.OCreat | SmbFile.ORdonly; + } + else + { + if (mode.Equals("rw")) + { + _openFlags = SmbFile.OCreat | SmbFile.ORdwr | SmbFile.OAppend; + _writeAndxResp = new SmbComWriteAndXResponse(); + _options = WriteOptions; + _access = SmbConstants.FileReadData | SmbConstants.FileWriteData; + } + else + { + throw new ArgumentException("Invalid mode"); + } + } + file.Open(_openFlags, _access, SmbFile.AttrNormal, _options); + _readSize = file.Tree.Session.transport.RcvBufSize - 70; + _writeSize = file.Tree.Session.transport.SndBufSize - 70; + _fp = 0L; + } + + /// + public virtual int Read() + { + if (Read(_tmp, 0, 1) == -1) + { + return -1; + } + return _tmp[0] & unchecked(0xFF); + } + + /// + public virtual int Read(byte[] b) + { + return Read(b, 0, b.Length); + } + + /// + public virtual int Read(byte[] b, int off, int len) + { + if (len <= 0) + { + return 0; + } + long start = _fp; + // ensure file is open + if (_file.IsOpen() == false) + { + _file.Open(_openFlags, 0, SmbFile.AttrNormal, _options); + } + int r; + int n; + SmbComReadAndXResponse response = new SmbComReadAndXResponse(b, off); + do + { + r = len > _readSize ? _readSize : len; + _file.Send(new SmbComReadAndX(_file.Fid, _fp, r, null), response); + if ((n = response.DataLength) <= 0) + { + return (int)((_fp - start) > 0L ? _fp - start : -1); + } + _fp += n; + len -= n; + response.Off += n; + } + while (len > 0 && n == r); + return (int)(_fp - start); + } + + /// + public void ReadFully(byte[] b) + { + ReadFully(b, 0, b.Length); + } + + /// + public void ReadFully(byte[] b, int off, int len) + { + int n = 0; + int count; + do + { + count = Read(b, off + n, len - n); + if (count < 0) + { + throw new SmbException("EOF"); + } + n += count; + _fp += count; + } + while (n < len); + } + + /// + public virtual int SkipBytes(int n) + { + if (n > 0) + { + _fp += n; + return n; + } + return 0; + } + + /// + public virtual void Write(int b) + { + _tmp[0] = unchecked((byte)b); + Write(_tmp, 0, 1); + } + + /// + public virtual void Write(byte[] b) + { + Write(b, 0, b.Length); + } + + /// + public virtual void Write(byte[] b, int off, int len) + { + if (len <= 0) + { + return; + } + // ensure file is open + if (_file.IsOpen() == false) + { + _file.Open(_openFlags, 0, SmbFile.AttrNormal, _options); + } + int w; + do + { + w = len > _writeSize ? _writeSize : len; + _file.Send(new SmbComWriteAndX(_file.Fid, _fp, len - w, b, off, w, null), _writeAndxResp + ); + _fp += _writeAndxResp.Count; + len -= (int)_writeAndxResp.Count; + off += (int)_writeAndxResp.Count; + } + while (len > 0); + } + + /// + public virtual long GetFilePointer() + { + return _fp; + } + + /// + public virtual void Seek(long pos) + { + _fp = pos; + } + + /// + public virtual long Length() + { + return _file.Length(); + } + + /// + public virtual void SetLength(long newLength) + { + // ensure file is open + if (_file.IsOpen() == false) + { + _file.Open(_openFlags, 0, SmbFile.AttrNormal, _options); + } + SmbComWriteResponse rsp = new SmbComWriteResponse(); + _file.Send(new SmbComWrite(_file.Fid, (int)(newLength & unchecked(0xFFFFFFFFL)), 0, _tmp, 0, 0), rsp); + } + + /// + public virtual void Close() + { + _file.Close(); + } + + /// + public bool ReadBoolean() + { + if ((Read(_tmp, 0, 1)) < 0) + { + throw new SmbException("EOF"); + } + return _tmp[0] != unchecked(unchecked(0x00)); + } + + /// + public byte ReadByte() + { + if ((Read(_tmp, 0, 1)) < 0) + { + throw new SmbException("EOF"); + } + return _tmp[0]; + } + + /// + public int ReadUnsignedByte() + { + if ((Read(_tmp, 0, 1)) < 0) + { + throw new SmbException("EOF"); + } + return _tmp[0] & unchecked(0xFF); + } + + /// + public short ReadShort() + { + if ((Read(_tmp, 0, 2)) < 0) + { + throw new SmbException("EOF"); + } + return Encdec.Dec_uint16be(_tmp, 0); + } + + /// + public int ReadUnsignedShort() + { + if ((Read(_tmp, 0, 2)) < 0) + { + throw new SmbException("EOF"); + } + return Encdec.Dec_uint16be(_tmp, 0) & unchecked(0xFFFF); + } + + /// + public char ReadChar() + { + if ((Read(_tmp, 0, 2)) < 0) + { + throw new SmbException("EOF"); + } + return (char)Encdec.Dec_uint16be(_tmp, 0); + } + + /// + public int ReadInt() + { + if ((Read(_tmp, 0, 4)) < 0) + { + throw new SmbException("EOF"); + } + return Encdec.Dec_uint32be(_tmp, 0); + } + + /// + public long ReadLong() + { + if ((Read(_tmp, 0, 8)) < 0) + { + throw new SmbException("EOF"); + } + return Encdec.Dec_uint64be(_tmp, 0); + } + + /// + public float ReadFloat() + { + if ((Read(_tmp, 0, 4)) < 0) + { + throw new SmbException("EOF"); + } + return Encdec.Dec_floatbe(_tmp, 0); + } + + /// + public double ReadDouble() + { + if ((Read(_tmp, 0, 8)) < 0) + { + throw new SmbException("EOF"); + } + return Encdec.Dec_doublebe(_tmp, 0); + } + + /// + public string ReadLine() + { + StringBuilder input = new StringBuilder(); + int c = -1; + bool eol = false; + while (!eol) + { + switch (c = Read()) + { + case -1: + case '\n': + { + eol = true; + break; + } + + case '\r': + { + eol = true; + long cur = _fp; + if (Read() != '\n') + { + _fp = cur; + } + break; + } + + default: + { + input.Append((char)c); + break; + } + } + } + if ((c == -1) && (input.Length == 0)) + { + return null; + } + return input.ToString(); + } + + /// + public string ReadUtf() + { + int size = ReadUnsignedShort(); + byte[] b = new byte[size]; + Read(b, 0, size); + try + { + return Encdec.Dec_utf8(b, 0, size); + } + catch (IOException ioe) + { + throw new SmbException(string.Empty, ioe); + } + } + + /// + public void WriteBoolean(bool v) + { + _tmp[0] = unchecked((byte)(v ? 1 : 0)); + Write(_tmp, 0, 1); + } + + /// + public void WriteByte(int v) + { + _tmp[0] = unchecked((byte)v); + Write(_tmp, 0, 1); + } + + /// + public void WriteShort(int v) + { + Encdec.Enc_uint16be((short)v, _tmp, 0); + Write(_tmp, 0, 2); + } + + /// + public void WriteChar(int v) + { + Encdec.Enc_uint16be((short)v, _tmp, 0); + Write(_tmp, 0, 2); + } + + /// + public void WriteInt(int v) + { + Encdec.Enc_uint32be(v, _tmp, 0); + Write(_tmp, 0, 4); + } + + /// + public void WriteLong(long v) + { + Encdec.Enc_uint64be(v, _tmp, 0); + Write(_tmp, 0, 8); + } + + /// + public void WriteFloat(float v) + { + Encdec.Enc_floatbe(v, _tmp, 0); + Write(_tmp, 0, 4); + } + + /// + public void WriteDouble(double v) + { + Encdec.Enc_doublebe(v, _tmp, 0); + Write(_tmp, 0, 8); + } + + /// + public void WriteBytes(string s) + { + byte[] b = Runtime.GetBytesForString(s); + Write(b, 0, b.Length); + } + + /// + /* public void WriteChars(string s) + { + int clen = s.Length; + int blen = 2 * clen; + byte[] b = new byte[blen]; + char[] c = new char[clen]; + Sharpen.Runtime.GetCharsForString(s, 0, clen, c, 0); + for (int i = 0, j = 0; i < clen; i++) + { + b[j++] = unchecked((byte)((char)(((uchar)c[i]) >> 8))); + b[j++] = unchecked((byte)((char)(((uchar)c[i]) >> 0))); + } + Write(b, 0, blen); + }*/ + + /// + public void WriteUtf(string str) + { + int len = str.Length; + int ch; + int size = 0; + byte[] dst; + for (int i = 0; i < len; i++) + { + ch = str[i]; + size += ch > unchecked(0x07F) ? (ch > unchecked(0x7FF) ? 3 : 2) : 1; + } + dst = new byte[size]; + WriteShort(size); + try + { + Encdec.Enc_utf8(str, dst, 0, size); + } + catch (IOException ioe) + { + throw new SmbException(string.Empty, ioe); + } + Write(dst, 0, size); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbSession.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbSession.cs new file mode 100644 index 0000000000..6dc5087d0c --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbSession.cs @@ -0,0 +1,570 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.Collections.Generic; +using System.IO; +using System.Net; +using SharpCifs.Netbios; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + public sealed class SmbSession + { + private static readonly string LogonShare = Config.GetProperty("jcifs.smb.client.logonShare" + , null); + + private static readonly int LookupRespLimit = Config.GetInt("jcifs.netbios.lookupRespLimit" + , 3); + + private static readonly string Domain = Config.GetProperty("jcifs.smb.client.domain" + , null); + + private static readonly string Username = Config.GetProperty("jcifs.smb.client.username" + , null); + + private static readonly int CachePolicy = Config.GetInt("jcifs.netbios.cachePolicy" + , 60 * 10) * 60; + + internal static NbtAddress[] DcList; + + internal static long DcListExpiration; + + internal static int DcListCounter; + + /// + private static NtlmChallenge Interrogate(NbtAddress addr) + { + UniAddress dc = new UniAddress(addr); + SmbTransport trans = SmbTransport.GetSmbTransport(dc, 0); + if (Username == null) + { + trans.Connect(); + if (SmbTransport.LogStatic.Level >= 3) + { + SmbTransport.LogStatic.WriteLine("Default credentials (jcifs.smb.client.username/password)" + + " not specified. SMB signing may not work propertly." + " Skipping DC interrogation." + ); + } + } + else + { + SmbSession ssn = trans.GetSmbSession(NtlmPasswordAuthentication.Default + ); + ssn.GetSmbTree(LogonShare, null).TreeConnect(null, null); + } + return new NtlmChallenge(trans.Server.EncryptionKey, dc); + } + + /// + /// + public static NtlmChallenge GetChallengeForDomain() + { + if (Domain == null) + { + throw new SmbException("A domain was not specified"); + } + lock (Domain) + { + long now = Runtime.CurrentTimeMillis(); + int retry = 1; + do + { + if (DcListExpiration < now) + { + NbtAddress[] list = NbtAddress.GetAllByName(Domain, 0x1C, null, + null); + DcListExpiration = now + CachePolicy * 1000L; + if (list != null && list.Length > 0) + { + DcList = list; + } + else + { + DcListExpiration = now + 1000 * 60 * 15; + if (SmbTransport.LogStatic.Level >= 2) + { + SmbTransport.LogStatic.WriteLine("Failed to retrieve DC list from WINS"); + } + } + } + int max = Math.Min(DcList.Length, LookupRespLimit); + for (int j = 0; j < max; j++) + { + int i = DcListCounter++ % max; + if (DcList[i] != null) + { + try + { + return Interrogate(DcList[i]); + } + catch (SmbException se) + { + if (SmbTransport.LogStatic.Level >= 2) + { + SmbTransport.LogStatic.WriteLine("Failed validate DC: " + DcList[i]); + if (SmbTransport.LogStatic.Level > 2) + { + Runtime.PrintStackTrace(se, SmbTransport.LogStatic); + } + } + } + DcList[i] = null; + } + } + DcListExpiration = 0; + } + while (retry-- > 0); + DcListExpiration = now + 1000 * 60 * 15; + } + throw new UnknownHostException("Failed to negotiate with a suitable domain controller for " + + Domain); + } + + /// + /// + public static byte[] GetChallenge(UniAddress dc) + { + return GetChallenge(dc, 0); + } + + /// + /// + public static byte[] GetChallenge(UniAddress dc, int port) + { + SmbTransport trans = SmbTransport.GetSmbTransport(dc, port); + trans.Connect(); + return trans.Server.EncryptionKey; + } + + /// + /// Authenticate arbitrary credentials represented by the + /// NtlmPasswordAuthentication object against the domain controller + /// specified by the UniAddress parameter. + /// + /// + /// Authenticate arbitrary credentials represented by the + /// NtlmPasswordAuthentication object against the domain controller + /// specified by the UniAddress parameter. If the credentials are + /// not accepted, an SmbAuthException will be thrown. If an error + /// occurs an SmbException will be thrown. If the credentials are + /// valid, the method will return without throwing an exception. See the + /// last FAQ question. + ///

+ /// See also the jcifs.smb.client.logonShare property. + /// + /// + public static void Logon(UniAddress dc, NtlmPasswordAuthentication auth) + { + Logon(dc, -1, auth); + } + + /// + public static void Logon(UniAddress dc, int port, NtlmPasswordAuthentication auth + ) + { + SmbTree tree = SmbTransport.GetSmbTransport(dc, port).GetSmbSession(auth).GetSmbTree + (LogonShare, null); + if (LogonShare == null) + { + tree.TreeConnect(null, null); + } + else + { + Trans2FindFirst2 req = new Trans2FindFirst2("\\", "*", SmbFile.AttrDirectory); + Trans2FindFirst2Response resp = new Trans2FindFirst2Response(); + tree.Send(req, resp); + } + } + + internal int ConnectionState; + + internal int Uid; + + internal List Trees; + + private UniAddress _address; + + private int _port; + + private int _localPort; + + private IPAddress _localAddr; + + internal SmbTransport transport; + + internal NtlmPasswordAuthentication Auth; + + internal long Expiration; + + internal string NetbiosName; + + internal SmbSession(UniAddress address, int port, IPAddress localAddr, int localPort + , NtlmPasswordAuthentication auth) + { + // Transport parameters allows trans to be removed from CONNECTIONS + this._address = address; + this._port = port; + this._localAddr = localAddr; + this._localPort = localPort; + this.Auth = auth; + Trees = new List(); + ConnectionState = 0; + } + + internal SmbTree GetSmbTree(string share, string service) + { + lock (this) + { + SmbTree t; + if (share == null) + { + share = "IPC$"; + } + /*for (IEnumeration e = trees.GetEnumerator(); e.MoveNext(); ) + { + t = (SmbTree)e.Current; + if (t.Matches(share, service)) + { + return t; + } + }*/ + foreach (var e in Trees) + { + t = (SmbTree)e; + if (t.Matches(share, service)) + { + return t; + } + } + + t = new SmbTree(this, share, service); + Trees.Add(t); + return t; + } + } + + internal bool Matches(NtlmPasswordAuthentication auth) + { + return this.Auth == auth || this.Auth.Equals(auth); + } + + internal SmbTransport Transport() + { + lock (this) + { + if (transport == null) + { + transport = SmbTransport.GetSmbTransport(_address, _port, _localAddr, _localPort, null + ); + } + return transport; + } + } + + /// + internal void Send(ServerMessageBlock request, ServerMessageBlock response) + { + lock (Transport()) + { + if (response != null) + { + response.Received = false; + } + Expiration = Runtime.CurrentTimeMillis() + SmbConstants.SoTimeout; + SessionSetup(request, response); + if (response != null && response.Received) + { + return; + } + if (request is SmbComTreeConnectAndX) + { + SmbComTreeConnectAndX tcax = (SmbComTreeConnectAndX)request; + if (NetbiosName != null && tcax.path.EndsWith("\\IPC$")) + { + tcax.path = "\\\\" + NetbiosName + "\\IPC$"; + } + } + request.Uid = Uid; + request.Auth = Auth; + try + { + transport.Send(request, response); + } + catch (SmbException se) + { + if (request is SmbComTreeConnectAndX) + { + Logoff(true); + } + request.Digest = null; + throw; + } + } + } + + /// + internal void SessionSetup(ServerMessageBlock andx, ServerMessageBlock andxResponse + ) + { + lock (Transport()) + { + NtlmContext nctx = null; + SmbException ex = null; + SmbComSessionSetupAndX request; + SmbComSessionSetupAndXResponse response; + byte[] token = new byte[0]; + int state = 10; + while (ConnectionState != 0) + { + if (ConnectionState == 2 || ConnectionState == 3) + { + // connected or disconnecting + return; + } + try + { + Runtime.Wait(transport); + } + catch (Exception ie) + { + throw new SmbException(ie.Message, ie); + } + } + ConnectionState = 1; + // trying ... + try + { + transport.Connect(); + if (transport.Log.Level >= 4) + { + transport.Log.WriteLine("sessionSetup: accountName=" + Auth.Username + ",primaryDomain=" + + Auth.Domain); + } + Uid = 0; + do + { + switch (state) + { + case 10: + { + if (Auth != NtlmPasswordAuthentication.Anonymous && transport.HasCapability(SmbConstants + .CapExtendedSecurity)) + { + state = 20; + break; + } + request = new SmbComSessionSetupAndX(this, andx, Auth); + response = new SmbComSessionSetupAndXResponse(andxResponse); + if (transport.IsSignatureSetupRequired(Auth)) + { + if (Auth.HashesExternal && NtlmPasswordAuthentication.DefaultPassword != NtlmPasswordAuthentication + .Blank) + { + transport.GetSmbSession(NtlmPasswordAuthentication.Default).GetSmbTree(LogonShare + , null).TreeConnect(null, null); + } + else + { + byte[] signingKey = Auth.GetSigningKey(transport.Server.EncryptionKey); + request.Digest = new SigningDigest(signingKey, false); + } + } + request.Auth = Auth; + try + { + transport.Send(request, response); + } + catch (SmbAuthException sae) + { + throw; + } + catch (SmbException se) + { + ex = se; + } + if (response.IsLoggedInAsGuest && Runtime.EqualsIgnoreCase("GUEST", Auth. + Username) == false && transport.Server.Security != SmbConstants.SecurityShare && + Auth != NtlmPasswordAuthentication.Anonymous) + { + throw new SmbAuthException(NtStatus.NtStatusLogonFailure); + } + if (ex != null) + { + throw ex; + } + Uid = response.Uid; + if (request.Digest != null) + { + transport.Digest = request.Digest; + } + ConnectionState = 2; + state = 0; + break; + } + + case 20: + { + if (nctx == null) + { + bool doSigning = (transport.Flags2 & SmbConstants.Flags2SecuritySignatures + ) != 0; + nctx = new NtlmContext(Auth, doSigning); + } + if (SmbTransport.LogStatic.Level >= 4) + { + SmbTransport.LogStatic.WriteLine(nctx); + } + if (nctx.IsEstablished()) + { + NetbiosName = nctx.GetNetbiosName(); + ConnectionState = 2; + state = 0; + break; + } + try + { + token = nctx.InitSecContext(token, 0, token.Length); + } + catch (SmbException se) + { + try + { + transport.Disconnect(true); + } + catch (IOException) + { + } + Uid = 0; + throw; + } + if (token != null) + { + request = new SmbComSessionSetupAndX(this, null, token); + response = new SmbComSessionSetupAndXResponse(null); + if (transport.IsSignatureSetupRequired(Auth)) + { + byte[] signingKey = nctx.GetSigningKey(); + if (signingKey != null) + { + request.Digest = new SigningDigest(signingKey, true); + } + } + request.Uid = Uid; + Uid = 0; + try + { + transport.Send(request, response); + } + catch (SmbAuthException sae) + { + throw; + } + catch (SmbException se) + { + ex = se; + try + { + transport.Disconnect(true); + } + catch (Exception) + { + } + } + if (response.IsLoggedInAsGuest && Runtime.EqualsIgnoreCase("GUEST", Auth. + Username) == false) + { + throw new SmbAuthException(NtStatus.NtStatusLogonFailure); + } + if (ex != null) + { + throw ex; + } + Uid = response.Uid; + if (request.Digest != null) + { + transport.Digest = request.Digest; + } + token = response.Blob; + } + break; + } + + default: + { + throw new SmbException("Unexpected session setup state: " + state); + } + } + } + while (state != 0); + } + catch (SmbException se) + { + Logoff(true); + ConnectionState = 0; + throw; + } + finally + { + Runtime.NotifyAll(transport); + } + } + } + + internal void Logoff(bool inError) + { + lock (Transport()) + { + if (ConnectionState != 2) + { + // not-connected + return; + } + ConnectionState = 3; + // disconnecting + NetbiosName = null; + + foreach (SmbTree t in Trees) + { + t.TreeDisconnect(inError); + } + + if (!inError && transport.Server.Security != SmbConstants.SecurityShare) + { + SmbComLogoffAndX request = new SmbComLogoffAndX(null); + request.Uid = Uid; + try + { + transport.Send(request, null); + } + catch (SmbException) + { + } + Uid = 0; + } + ConnectionState = 0; + Runtime.NotifyAll(transport); + } + } + + public override string ToString() + { + return "SmbSession[accountName=" + Auth.Username + ",primaryDomain=" + Auth.Domain + + ",uid=" + Uid + ",connectionState=" + ConnectionState + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbShareInfo.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbShareInfo.cs new file mode 100644 index 0000000000..811c76794e --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbShareInfo.cs @@ -0,0 +1,104 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; + +namespace SharpCifs.Smb +{ + public class SmbShareInfo : IFileEntry + { + protected internal string NetName; + + protected internal int Type; + + protected internal string Remark; + + public SmbShareInfo() + { + } + + public SmbShareInfo(string netName, int type, string remark) + { + this.NetName = netName; + this.Type = type; + this.Remark = remark; + } + + public virtual string GetName() + { + return NetName; + } + + public new virtual int GetType() + { + switch (Type & unchecked(0xFFFF)) + { + case 1: + { + return SmbFile.TypePrinter; + } + + case 3: + { + return SmbFile.TypeNamedPipe; + } + } + return SmbFile.TypeShare; + } + + public virtual int GetAttributes() + { + return SmbFile.AttrReadonly | SmbFile.AttrDirectory; + } + + public virtual long CreateTime() + { + return 0L; + } + + public virtual long LastModified() + { + return 0L; + } + + public virtual long Length() + { + return 0L; + } + + public override bool Equals(object obj) + { + if (obj is SmbShareInfo) + { + SmbShareInfo si = (SmbShareInfo)obj; + return NetName.Equals(si.NetName); + } + return false; + } + + public override int GetHashCode() + { + int hashCode = NetName.GetHashCode(); + return hashCode; + } + + public override string ToString() + { + return "SmbShareInfo[" + "netName=" + NetName + ",type=0x" + Hexdump.ToHexString + (Type, 8) + ",remark=" + Remark + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTransport.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTransport.cs new file mode 100644 index 0000000000..800d6d9bc1 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTransport.cs @@ -0,0 +1,977 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using SharpCifs.Netbios; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; +using SharpCifs.Util.Transport; + +namespace SharpCifs.Smb +{ + public class SmbTransport : Transport + { + internal static readonly byte[] Buf = new byte[0xFFFF]; + + internal static readonly SmbComNegotiate NegotiateRequest = new SmbComNegotiate( + ); + + internal static LogStream LogStatic = LogStream.GetInstance(); + + internal static Hashtable DfsRoots = null; + + + internal static SmbTransport GetSmbTransport(UniAddress address, int port + ) + { + lock (typeof(SmbTransport)) + { + return GetSmbTransport(address, port, SmbConstants.Laddr, SmbConstants.Lport, null); + } + } + + internal static SmbTransport GetSmbTransport(UniAddress address, int port + , IPAddress localAddr, int localPort, string hostName) + { + lock (typeof(SmbTransport)) + { + SmbTransport conn; + + lock (SmbConstants.Connections) + { + if (SmbConstants.SsnLimit != 1) + { + conn = + SmbConstants.Connections.FirstOrDefault( + c => + c.Matches(address, port, localAddr, localPort, hostName) && + (SmbConstants.SsnLimit == + 0 || c.Sessions.Count < SmbConstants.SsnLimit)); + + if (conn != null) + { + return conn; + } + + } + + conn = new SmbTransport(address, port, localAddr, localPort); + SmbConstants.Connections.Insert(0, conn); + } + return conn; + } + } + + internal class ServerData + { + internal byte Flags; + + internal int Flags2; + + internal int MaxMpxCount; + + internal int MaxBufferSize; + + internal int SessionKey; + + internal int Capabilities; + + internal string OemDomainName; + + internal int SecurityMode; + + internal int Security; + + internal bool EncryptedPasswords; + + internal bool SignaturesEnabled; + + internal bool SignaturesRequired; + + internal int MaxNumberVcs; + + internal int MaxRawSize; + + internal long ServerTime; + + internal int ServerTimeZone; + + internal int EncryptionKeyLength; + + internal byte[] EncryptionKey; + + internal byte[] Guid; + + internal ServerData(SmbTransport enclosing) + { + this._enclosing = enclosing; + } + + private readonly SmbTransport _enclosing; + } + + internal IPAddress LocalAddr; + + internal int LocalPort; + + internal UniAddress Address; + + internal SocketEx Socket; + + internal int Port; + + internal int Mid; + + internal OutputStream Out; + + internal InputStream In; + + internal byte[] Sbuf = new byte[512]; + + internal SmbComBlankResponse Key = new SmbComBlankResponse(); + + internal long SessionExpiration = Runtime.CurrentTimeMillis() + SmbConstants.SoTimeout; + + internal List Referrals = new List(); + + internal SigningDigest Digest; + + internal List Sessions = new List(); + + internal ServerData Server; + + internal int Flags2 = SmbConstants.Flags2; + + internal int MaxMpxCount = SmbConstants.MaxMpxCount; + + internal int SndBufSize = SmbConstants.SndBufSize; + + internal int RcvBufSize = SmbConstants.RcvBufSize; + + internal int Capabilities = SmbConstants.Capabilities; + + internal int SessionKey = 0x00000000; + + internal bool UseUnicode = SmbConstants.UseUnicode; + + internal string TconHostName; + + internal SmbTransport(UniAddress address, int port, IPAddress localAddr, int localPort + ) + { + Server = new ServerData(this); + this.Address = address; + this.Port = port; + this.LocalAddr = localAddr; + this.LocalPort = localPort; + } + + internal virtual SmbSession GetSmbSession() + { + lock (this) + { + return GetSmbSession(new NtlmPasswordAuthentication(null, null, null)); + } + } + + internal virtual SmbSession GetSmbSession(NtlmPasswordAuthentication auth) + { + lock (this) + { + SmbSession ssn; + long now; + + ssn = Sessions.FirstOrDefault(s => s.Matches(auth)); + if (ssn != null) + { + ssn.Auth = auth; + return ssn; + } + + if (SmbConstants.SoTimeout > 0 && SessionExpiration < (now = Runtime.CurrentTimeMillis())) + { + SessionExpiration = now + SmbConstants.SoTimeout; + + foreach (var session in Sessions.Where(s => s.Expiration < now)) + { + session.Logoff(false); + } + } + ssn = new SmbSession(Address, Port, LocalAddr, LocalPort, auth); + ssn.transport = this; + Sessions.Add(ssn); + return ssn; + } + } + + internal virtual bool Matches(UniAddress address, int port, IPAddress localAddr, + int localPort, string hostName) + { + if (hostName == null) + { + hostName = address.GetHostName(); + } + return (TconHostName == null || Runtime.EqualsIgnoreCase(hostName, TconHostName)) && address.Equals(this.Address) && (port == -1 || port == this.Port + || (port == 445 && this.Port == 139)) && (localAddr == this.LocalAddr || (localAddr + != null && localAddr.Equals(this.LocalAddr))) && localPort == this.LocalPort; + } + + /// + internal virtual bool HasCapability(int cap) + { + try + { + Connect(SmbConstants.ResponseTimeout); + } + catch (IOException ioe) + { + throw new SmbException(ioe.Message, ioe); + } + return (Capabilities & cap) == cap; + } + + internal virtual bool IsSignatureSetupRequired(NtlmPasswordAuthentication auth) + { + return (Flags2 & SmbConstants.Flags2SecuritySignatures) != 0 && Digest == + null && auth != NtlmPasswordAuthentication.Null && NtlmPasswordAuthentication.Null + .Equals(auth) == false; + } + + /// + internal virtual void Ssn139() + { + Name calledName = new Name(Address.FirstCalledName(), 0x20, null + ); + do + { + Socket = new SocketEx(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + if (LocalAddr != null) + { + Socket.Bind2(new IPEndPoint(LocalAddr, LocalPort)); + } + + Socket.Connect(new IPEndPoint(IPAddress.Parse(Address.GetHostAddress()), 139), SmbConstants.ConnTimeout); + Socket.SoTimeOut = SmbConstants.SoTimeout; + + Out = Socket.GetOutputStream(); + In = Socket.GetInputStream(); + SessionServicePacket ssp = new SessionRequestPacket(calledName, NbtAddress.GetLocalName + ()); + Out.Write(Sbuf, 0, ssp.WriteWireFormat(Sbuf, 0)); + if (Readn(In, Sbuf, 0, 4) < 4) + { + try + { + //Socket.`Close` method deleted + //Socket.Close(); + Socket.Dispose(); + } + catch (IOException) + { + } + throw new SmbException("EOF during NetBIOS session request"); + } + switch (Sbuf[0] & 0xFF) + { + case SessionServicePacket.PositiveSessionResponse: + { + if (Log.Level >= 4) + { + Log.WriteLine("session established ok with " + Address); + } + return; + } + + case SessionServicePacket.NegativeSessionResponse: + { + int errorCode = In.Read() & 0xFF; + switch (errorCode) + { + case NbtException.CalledNotPresent: + case NbtException.NotListeningCalled: + { + //Socket.`Close` method deleted + //Socket.Close(); + Socket.Dispose(); + break; + } + + default: + { + Disconnect(true); + throw new NbtException(NbtException.ErrSsnSrvc, errorCode); + } + } + break; + } + + case -1: + { + Disconnect(true); + throw new NbtException(NbtException.ErrSsnSrvc, NbtException.ConnectionRefused + ); + } + + default: + { + Disconnect(true); + throw new NbtException(NbtException.ErrSsnSrvc, 0); + } + } + } + while ((calledName.name = Address.NextCalledName()) != null); + throw new IOException("Failed to establish session with " + Address); + } + + /// + private void Negotiate(int port, ServerMessageBlock resp) + { + lock (Sbuf) + { + if (port == 139) + { + Ssn139(); + } + else + { + if (port == -1) + { + port = SmbConstants.DefaultPort; + } + // 445 + Socket = new SocketEx(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + if (LocalAddr != null) + { + Socket.Bind2(new IPEndPoint(LocalAddr, LocalPort)); + } + + Socket.Connect(new IPEndPoint(IPAddress.Parse(Address.GetHostAddress()), port), SmbConstants.ConnTimeout); + Socket.SoTimeOut = SmbConstants.SoTimeout; + Out = Socket.GetOutputStream(); + In = Socket.GetInputStream(); + } + if (++Mid == 32000) + { + Mid = 1; + } + NegotiateRequest.Mid = Mid; + int n = NegotiateRequest.Encode(Sbuf, 4); + Encdec.Enc_uint32be(n & 0xFFFF, Sbuf, 0); + if (Log.Level >= 4) + { + Log.WriteLine(NegotiateRequest); + if (Log.Level >= 6) + { + Hexdump.ToHexdump(Log, Sbuf, 4, n); + } + } + Out.Write(Sbuf, 0, 4 + n); + Out.Flush(); + if (PeekKey() == null) + { + throw new IOException("transport closed in negotiate"); + } + int size = Encdec.Dec_uint16be(Sbuf, 2) & 0xFFFF; + if (size < 33 || (4 + size) > Sbuf.Length) + { + throw new IOException("Invalid payload size: " + size); + } + Readn(In, Sbuf, 4 + 32, size - 32); + resp.Decode(Sbuf, 4); + if (Log.Level >= 4) + { + Log.WriteLine(resp); + if (Log.Level >= 6) + { + Hexdump.ToHexdump(Log, Sbuf, 4, n); + } + } + } + } + + /// + public virtual void Connect() + { + try + { + base.Connect(SmbConstants.ResponseTimeout); + } + catch (TransportException te) + { + throw new SmbException("Failed to connect: " + Address, te); + } + } + + /// + protected internal override void DoConnect() + { + SmbComNegotiateResponse resp = new SmbComNegotiateResponse(Server); + try + { + Negotiate(Port, resp); + } + catch (ConnectException) + { + Port = (Port == -1 || Port == SmbConstants.DefaultPort) ? 139 : SmbConstants.DefaultPort; + Negotiate(Port, resp); + } + if (resp.DialectIndex > 10) + { + throw new SmbException("This client does not support the negotiated dialect."); + } + if ((Server.Capabilities & SmbConstants.CapExtendedSecurity) != SmbConstants.CapExtendedSecurity && Server + .EncryptionKeyLength != 8 && SmbConstants.LmCompatibility == 0) + { + throw new SmbException("Unexpected encryption key length: " + Server.EncryptionKeyLength + ); + } + TconHostName = Address.GetHostName(); + if (Server.SignaturesRequired || (Server.SignaturesEnabled && SmbConstants.Signpref)) + { + Flags2 |= SmbConstants.Flags2SecuritySignatures; + } + else + { + Flags2 &= 0xFFFF ^ SmbConstants.Flags2SecuritySignatures; + } + MaxMpxCount = Math.Min(MaxMpxCount, Server.MaxMpxCount); + if (MaxMpxCount < 1) + { + MaxMpxCount = 1; + } + SndBufSize = Math.Min(SndBufSize, Server.MaxBufferSize); + Capabilities &= Server.Capabilities; + if ((Server.Capabilities & SmbConstants.CapExtendedSecurity) == SmbConstants.CapExtendedSecurity) + { + Capabilities |= SmbConstants.CapExtendedSecurity; + } + // & doesn't copy high bit + if ((Capabilities & SmbConstants.CapUnicode) == 0) + { + // server doesn't want unicode + if (SmbConstants.ForceUnicode) + { + Capabilities |= SmbConstants.CapUnicode; + } + else + { + UseUnicode = false; + Flags2 &= 0xFFFF ^ SmbConstants.Flags2Unicode; + } + } + } + + /// + protected internal override void DoDisconnect(bool hard) + { + try + { + foreach (var ssn in Sessions) + { + ssn.Logoff(hard); + } + + Out.Close(); + In.Close(); + + //Socket.`Close` method deleted + //Socket.Close(); + Socket.Dispose(); + } + finally + { + Digest = null; + Socket = null; + TconHostName = null; + } + + } + + /// + protected internal override void MakeKey(ServerMessageBlock request) + { + if (++Mid == 32000) + { + Mid = 1; + } + request.Mid = Mid; + } + + /// + protected internal override ServerMessageBlock PeekKey() + { + int n; + do + { + if ((n = Readn(In, Sbuf, 0, 4)) < 4) + { + return null; + } + } + while (Sbuf[0] == 0x85); + if ((n = Readn(In, Sbuf, 4, 32)) < 32) + { + return null; + } + if (Log.Level >= 4) + { + Log.WriteLine("New data read: " + this); + Hexdump.ToHexdump(Log, Sbuf, 4, 32); + } + for (; ; ) + { + if (Sbuf[0] == 0x00 && Sbuf[1] == 0x00 && + Sbuf[4] == 0xFF && + Sbuf[5] == 'S' && + Sbuf[6] == 'M' && + Sbuf[7] == 'B') + { + break; + } + for (int i = 0; i < 35; i++) + { + Sbuf[i] = Sbuf[i + 1]; + } + int b; + if ((b = In.Read()) == -1) + { + return null; + } + Sbuf[35] = unchecked((byte)b); + } + Key.Mid = Encdec.Dec_uint16le(Sbuf, 34) & 0xFFFF; + return Key; + } + + /// + protected internal override void DoSend(ServerMessageBlock request) + { + lock (Buf) + { + ServerMessageBlock smb = request; + int n = smb.Encode(Buf, 4); + Encdec.Enc_uint32be(n & 0xFFFF, Buf, 0); + if (Log.Level >= 4) + { + do + { + Log.WriteLine(smb); + } + while (smb is AndXServerMessageBlock && (smb = ((AndXServerMessageBlock)smb).Andx + ) != null); + if (Log.Level >= 6) + { + Hexdump.ToHexdump(Log, Buf, 4, n); + } + } + Out.Write(Buf, 0, 4 + n); + } + } + + /// + protected internal virtual void DoSend0(ServerMessageBlock request) + { + try + { + DoSend(request); + } + catch (IOException ioe) + { + if (Log.Level > 2) + { + Runtime.PrintStackTrace(ioe, Log); + } + try + { + Disconnect(true); + } + catch (IOException ioe2) + { + Runtime.PrintStackTrace(ioe2, Log); + } + throw; + } + } + + /// + protected internal override void DoRecv(Response response) + { + ServerMessageBlock resp = (ServerMessageBlock)response; + resp.UseUnicode = UseUnicode; + resp.ExtendedSecurity = (Capabilities & SmbConstants.CapExtendedSecurity) == SmbConstants.CapExtendedSecurity; + lock (Buf) + { + Array.Copy(Sbuf, 0, Buf, 0, 4 + SmbConstants.HeaderLength); + int size = Encdec.Dec_uint16be(Buf, 2) & 0xFFFF; + if (size < (SmbConstants.HeaderLength + 1) || (4 + size) > RcvBufSize) + { + throw new IOException("Invalid payload size: " + size); + } + int errorCode = Encdec.Dec_uint32le(Buf, 9) & unchecked((int)(0xFFFFFFFF)); + if (resp.Command == ServerMessageBlock.SmbComReadAndx && (errorCode == 0 || errorCode + == unchecked((int)(0x80000005)))) + { + // overflow indicator normal for pipe + SmbComReadAndXResponse r = (SmbComReadAndXResponse)resp; + int off = SmbConstants.HeaderLength; + Readn(In, Buf, 4 + off, 27); + off += 27; + resp.Decode(Buf, 4); + int pad = r.DataOffset - off; + if (r.ByteCount > 0 && pad > 0 && pad < 4) + { + Readn(In, Buf, 4 + off, pad); + } + if (r.DataLength > 0) + { + Readn(In, r.B, r.Off, r.DataLength); + } + } + else + { + Readn(In, Buf, 4 + 32, size - 32); + resp.Decode(Buf, 4); + if (resp is SmbComTransactionResponse) + { + ((SmbComTransactionResponse)resp).Current(); + } + } + if (Digest != null && resp.ErrorCode == 0) + { + Digest.Verify(Buf, 4, resp); + } + if (Log.Level >= 4) + { + Log.WriteLine(response); + if (Log.Level >= 6) + { + Hexdump.ToHexdump(Log, Buf, 4, size); + } + } + } + } + + /// + protected internal override void DoSkip() + { + int size = Encdec.Dec_uint16be(Sbuf, 2) & 0xFFFF; + if (size < 33 || (4 + size) > RcvBufSize) + { + In.Skip(In.Available()); + } + else + { + In.Skip(size - 32); + } + } + + /// + internal virtual void CheckStatus(ServerMessageBlock req, ServerMessageBlock resp + ) + { + resp.ErrorCode = SmbException.GetStatusByCode(resp.ErrorCode); + switch (resp.ErrorCode) + { + case NtStatus.NtStatusOk: + { + break; + } + + case NtStatus.NtStatusAccessDenied: + case NtStatus.NtStatusWrongPassword: + case NtStatus.NtStatusLogonFailure: + case NtStatus.NtStatusAccountRestriction: + case NtStatus.NtStatusInvalidLogonHours: + case NtStatus.NtStatusInvalidWorkstation: + case NtStatus.NtStatusPasswordExpired: + case NtStatus.NtStatusAccountDisabled: + case NtStatus.NtStatusAccountLockedOut: + case NtStatus.NtStatusTrustedDomainFailure: + { + throw new SmbAuthException(resp.ErrorCode); + } + + case NtStatus.NtStatusPathNotCovered: + { + if (req.Auth == null) + { + throw new SmbException(resp.ErrorCode, null); + } + DfsReferral dr = GetDfsReferrals(req.Auth, req.Path, 1); + if (dr == null) + { + throw new SmbException(resp.ErrorCode, null); + } + SmbFile.Dfs.Insert(req.Path, dr); + throw dr; + } + + case unchecked((int)(0x80000005)): + { + break; + } + + case NtStatus.NtStatusMoreProcessingRequired: + { + break; + } + + default: + { + throw new SmbException(resp.ErrorCode, null); + } + } + if (resp.VerifyFailed) + { + throw new SmbException("Signature verification failed."); + } + } + + /// + internal virtual void Send(ServerMessageBlock request, ServerMessageBlock response + ) + { + Connect(); + request.Flags2 |= Flags2; + request.UseUnicode = UseUnicode; + request.Response = response; + if (request.Digest == null) + { + request.Digest = Digest; + } + try + { + if (response == null) + { + DoSend0(request); + return; + } + if (request is SmbComTransaction) + { + response.Command = request.Command; + SmbComTransaction req = (SmbComTransaction)request; + SmbComTransactionResponse resp = (SmbComTransactionResponse)response; + req.MaxBufferSize = SndBufSize; + resp.Reset(); + try + { + BufferCache.GetBuffers(req, resp); + req.Current(); + if (req.MoveNext()) + { + SmbComBlankResponse interim = new SmbComBlankResponse(); + Sendrecv(req, interim, SmbConstants.ResponseTimeout); + if (interim.ErrorCode != 0) + { + CheckStatus(req, interim); + } + req.Current(); + } + else + { + MakeKey(req); + } + lock (this) + { + response.Received = false; + resp.IsReceived = false; + try + { + ResponseMap.Put(req, resp); + do + { + DoSend0(req); + } + while (req.MoveNext() && req.Current() != null); + long timeout = SmbConstants.ResponseTimeout; + resp.Expiration = Runtime.CurrentTimeMillis() + timeout; + while (resp.MoveNext()) + { + Runtime.Wait(this, timeout); + timeout = resp.Expiration - Runtime.CurrentTimeMillis(); + if (timeout <= 0) + { + throw new TransportException(this + " timedout waiting for response to " + req); + } + } + if (response.ErrorCode != 0) + { + CheckStatus(req, resp); + } + } + catch (Exception ie) + { + if (ie is SmbException) + { + throw; + } + else + { + throw new TransportException(ie); + } + } + finally + { + //Sharpen.Collections.Remove(response_map, req); + ResponseMap.Remove(req); + } + } + } + finally + { + BufferCache.ReleaseBuffer(req.TxnBuf); + BufferCache.ReleaseBuffer(resp.TxnBuf); + } + } + else + { + response.Command = request.Command; + Sendrecv(request, response, SmbConstants.ResponseTimeout); + } + } + catch (SmbException se) + { + throw; + } + catch (IOException ioe) + { + throw new SmbException(ioe.Message, ioe); + } + CheckStatus(request, response); + } + + public override string ToString() + { + return base.ToString() + "[" + Address + ":" + Port + "]"; + } + + internal virtual void DfsPathSplit(string path, string[] result) + { + int ri = 0; + int rlast = result.Length - 1; + int i = 0; + int b = 0; + int len = path.Length; + do + { + if (ri == rlast) + { + result[rlast] = Runtime.Substring(path, b); + return; + } + if (i == len || path[i] == '\\') + { + result[ri++] = Runtime.Substring(path, b, i); + b = i + 1; + } + } + while (i++ < len); + while (ri < result.Length) + { + result[ri++] = string.Empty; + } + } + + /// + internal virtual DfsReferral GetDfsReferrals(NtlmPasswordAuthentication auth, string + path, int rn) + { + SmbTree ipc = GetSmbSession(auth).GetSmbTree("IPC$", null); + Trans2GetDfsReferralResponse resp = new Trans2GetDfsReferralResponse(); + ipc.Send(new Trans2GetDfsReferral(path), resp); + if (resp.NumReferrals == 0) + { + return null; + } + if (rn == 0 || resp.NumReferrals < rn) + { + rn = resp.NumReferrals; + } + DfsReferral dr = new DfsReferral(); + string[] arr = new string[4]; + long expiration = Runtime.CurrentTimeMillis() + Dfs.Ttl * 1000; + int di = 0; + for (; ; ) + { + dr.ResolveHashes = auth.HashesExternal; + dr.Ttl = resp.Referrals[di].Ttl; + dr.Expiration = expiration; + if (path.Equals(string.Empty)) + { + dr.Server = Runtime.Substring(resp.Referrals[di].Path, 1).ToLower(); + } + else + { + DfsPathSplit(resp.Referrals[di].Node, arr); + dr.Server = arr[1]; + dr.Share = arr[2]; + dr.Path = arr[3]; + } + dr.PathConsumed = resp.PathConsumed; + di++; + if (di == rn) + { + break; + } + dr.Append(new DfsReferral()); + dr = dr.Next; + } + return dr.Next; + } + + /// + internal virtual DfsReferral[] __getDfsReferrals(NtlmPasswordAuthentication auth, + string path, int rn) + { + SmbTree ipc = GetSmbSession(auth).GetSmbTree("IPC$", null); + Trans2GetDfsReferralResponse resp = new Trans2GetDfsReferralResponse(); + ipc.Send(new Trans2GetDfsReferral(path), resp); + if (rn == 0 || resp.NumReferrals < rn) + { + rn = resp.NumReferrals; + } + DfsReferral[] drs = new DfsReferral[rn]; + string[] arr = new string[4]; + long expiration = Runtime.CurrentTimeMillis() + Dfs.Ttl * 1000; + for (int di = 0; di < drs.Length; di++) + { + DfsReferral dr = new DfsReferral(); + dr.ResolveHashes = auth.HashesExternal; + dr.Ttl = resp.Referrals[di].Ttl; + dr.Expiration = expiration; + if (path.Equals(string.Empty)) + { + dr.Server = Runtime.Substring(resp.Referrals[di].Path, 1).ToLower(); + } + else + { + DfsPathSplit(resp.Referrals[di].Node, arr); + dr.Server = arr[1]; + dr.Share = arr[2]; + dr.Path = arr[3]; + } + dr.PathConsumed = resp.PathConsumed; + drs[di] = dr; + } + return drs; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTree.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTree.cs new file mode 100644 index 0000000000..8dc068c4c9 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/SmbTree.cs @@ -0,0 +1,250 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Sharpen; + +namespace SharpCifs.Smb +{ + class SmbTree + { + private static int _treeConnCounter; + + internal int ConnectionState; + + internal int Tid; + + internal string Share; + + internal string Service = "?????"; + + internal string Service0; + + internal SmbSession Session; + + internal bool InDfs; + + internal bool InDomainDfs; + + internal int TreeNum; + + internal SmbTree(SmbSession session, string share, string service) + { + // used by SmbFile.isOpen + this.Session = session; + this.Share = share.ToUpper(); + if (service != null && service.StartsWith("??") == false) + { + this.Service = service; + } + Service0 = this.Service; + ConnectionState = 0; + } + + internal virtual bool Matches(string share, string service) + { + return Runtime.EqualsIgnoreCase(this.Share, share) && (service == null || + service.StartsWith("??") || Runtime.EqualsIgnoreCase(this.Service, service + )); + } + + public override bool Equals(object obj) + { + if (obj is SmbTree) + { + SmbTree tree = (SmbTree)obj; + return Matches(tree.Share, tree.Service); + } + return false; + } + + /// + internal virtual void Send(ServerMessageBlock request, ServerMessageBlock response + ) + { + lock (Session.Transport()) + { + if (response != null) + { + response.Received = false; + } + TreeConnect(request, response); + if (request == null || (response != null && response.Received)) + { + return; + } + if (Service.Equals("A:") == false) + { + switch (request.Command) + { + case ServerMessageBlock.SmbComOpenAndx: + case ServerMessageBlock.SmbComNtCreateAndx: + case ServerMessageBlock.SmbComReadAndx: + case ServerMessageBlock.SmbComWriteAndx: + case ServerMessageBlock.SmbComClose: + case ServerMessageBlock.SmbComTreeDisconnect: + { + break; + } + + case ServerMessageBlock.SmbComTransaction: + case ServerMessageBlock.SmbComTransaction2: + { + switch (((SmbComTransaction)request).SubCommand & unchecked(0xFF)) + { + case SmbComTransaction.NetShareEnum: + case SmbComTransaction.NetServerEnum2: + case SmbComTransaction.NetServerEnum3: + case SmbComTransaction.TransPeekNamedPipe: + case SmbComTransaction.TransWaitNamedPipe: + case SmbComTransaction.TransCallNamedPipe: + case SmbComTransaction.TransTransactNamedPipe: + case SmbComTransaction.Trans2GetDfsReferral: + { + break; + } + + default: + { + throw new SmbException("Invalid operation for " + Service + " service"); + } + } + break; + } + + default: + { + throw new SmbException("Invalid operation for " + Service + " service" + request); + } + } + } + request.Tid = Tid; + if (InDfs && !Service.Equals("IPC") && !string.IsNullOrEmpty(request.Path)) + { + request.Flags2 = SmbConstants.Flags2ResolvePathsInDfs; + request.Path = '\\' + Session.Transport().TconHostName + '\\' + Share + request.Path; + } + try + { + Session.Send(request, response); + } + catch (SmbException se) + { + if (se.GetNtStatus() == NtStatus.NtStatusNetworkNameDeleted) + { + TreeDisconnect(true); + } + throw; + } + } + } + + /// + internal virtual void TreeConnect(ServerMessageBlock andx, ServerMessageBlock andxResponse + ) + { + lock (Session.Transport()) + { + string unc; + while (ConnectionState != 0) + { + if (ConnectionState == 2 || ConnectionState == 3) + { + // connected or disconnecting + return; + } + try + { + Runtime.Wait(Session.transport); + } + catch (Exception ie) + { + throw new SmbException(ie.Message, ie); + } + } + ConnectionState = 1; + // trying ... + try + { + Session.transport.Connect(); + unc = "\\\\" + Session.transport.TconHostName + '\\' + Share; + Service = Service0; + if (Session.transport.Log.Level >= 4) + { + Session.transport.Log.WriteLine("treeConnect: unc=" + unc + ",service=" + Service + ); + } + SmbComTreeConnectAndXResponse response = new SmbComTreeConnectAndXResponse(andxResponse + ); + SmbComTreeConnectAndX request = new SmbComTreeConnectAndX(Session, unc, Service, + andx); + Session.Send(request, response); + Tid = response.Tid; + Service = response.Service; + InDfs = response.ShareIsInDfs; + TreeNum = _treeConnCounter++; + ConnectionState = 2; + } + catch (SmbException se) + { + // connected + TreeDisconnect(true); + ConnectionState = 0; + throw; + } + } + } + + internal virtual void TreeDisconnect(bool inError) + { + lock (Session.Transport()) + { + if (ConnectionState != 2) + { + // not-connected + return; + } + ConnectionState = 3; + // disconnecting + if (!inError && Tid != 0) + { + try + { + Send(new SmbComTreeDisconnect(), null); + } + catch (SmbException se) + { + if (Session.transport.Log.Level > 1) + { + Runtime.PrintStackTrace(se, Session.transport.Log); + } + } + } + InDfs = false; + InDomainDfs = false; + ConnectionState = 0; + Runtime.NotifyAll(Session.transport); + } + } + + public override string ToString() + { + return "SmbTree[share=" + Share + ",service=" + Service + ",tid=" + Tid + ",inDfs=" + + InDfs + ",inDomainDfs=" + InDomainDfs + ",connectionState=" + ConnectionState + + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2FindFirst2.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2FindFirst2.cs new file mode 100644 index 0000000000..2ef874882f --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2FindFirst2.cs @@ -0,0 +1,146 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; + +namespace SharpCifs.Smb +{ + internal class Trans2FindFirst2 : SmbComTransaction + { + private const int FlagsCloseAfterThisRequest = unchecked(0x01); + + private const int FlagsCloseIfEndReached = unchecked(0x02); + + private const int FlagsReturnResumeKeys = unchecked(0x04); + + private const int FlagsResumeFromPreviousEnd = unchecked(0x08); + + private const int FlagsFindWithBackupIntent = unchecked(0x10); + + private const int DefaultListSize = 65535; + + private const int DefaultListCount = 200; + + private int _searchAttributes; + + private int _flags; + + private int _informationLevel; + + private int _searchStorageType = 0; + + private string _wildcard; + + internal const int SmbInfoStandard = 1; + + internal const int SmbInfoQueryEaSize = 2; + + internal const int SmbInfoQueryEasFromList = 3; + + internal const int SmbFindFileDirectoryInfo = unchecked(0x101); + + internal const int SmbFindFileFullDirectoryInfo = unchecked(0x102); + + internal const int SmbFileNamesInfo = unchecked(0x103); + + internal const int SmbFileBothDirectoryInfo = unchecked(0x104); + + internal static readonly int ListSize = Config.GetInt("jcifs.smb.client.listSize" + , DefaultListSize); + + internal static readonly int ListCount = Config.GetInt("jcifs.smb.client.listCount" + , DefaultListCount); + + internal Trans2FindFirst2(string filename, string wildcard, int searchAttributes) + { + // flags + // information levels + if (filename.Equals("\\")) + { + Path = filename; + } + else + { + Path = filename + "\\"; + } + this._wildcard = wildcard; + this._searchAttributes = searchAttributes & unchecked(0x37); + Command = SmbComTransaction2; + SubCommand = Trans2FindFirst2; + _flags = unchecked(0x00); + _informationLevel = SmbFileBothDirectoryInfo; + TotalDataCount = 0; + MaxParameterCount = 10; + MaxDataCount = ListSize; + MaxSetupCount = 0; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + dst[dstIndex++] = SubCommand; + dst[dstIndex++] = unchecked(unchecked(0x00)); + return 2; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(_searchAttributes, dst, dstIndex); + dstIndex += 2; + WriteInt2(ListCount, dst, dstIndex); + dstIndex += 2; + WriteInt2(_flags, dst, dstIndex); + dstIndex += 2; + WriteInt2(_informationLevel, dst, dstIndex); + dstIndex += 2; + WriteInt4(_searchStorageType, dst, dstIndex); + dstIndex += 4; + dstIndex += WriteString(Path + _wildcard, dst, dstIndex); + return dstIndex - start; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "Trans2FindFirst2[" + base.ToString() + ",searchAttributes=0x" + + Hexdump.ToHexString(_searchAttributes, 2) + ",searchCount=" + ListCount + ",flags=0x" + + Hexdump.ToHexString(_flags, 2) + ",informationLevel=0x" + Hexdump.ToHexString( + _informationLevel, 3) + ",searchStorageType=" + _searchStorageType + ",filename=" + + Path + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2FindFirst2Response.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2FindFirst2Response.cs new file mode 100644 index 0000000000..71f780ff38 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2FindFirst2Response.cs @@ -0,0 +1,262 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal class Trans2FindFirst2Response : SmbComTransactionResponse + { + internal const int SmbInfoStandard = 1; + + internal const int SmbInfoQueryEaSize = 2; + + internal const int SmbInfoQueryEasFromList = 3; + + internal const int SmbFindFileDirectoryInfo = unchecked(0x101); + + internal const int SmbFindFileFullDirectoryInfo = unchecked(0x102); + + internal const int SmbFileNamesInfo = unchecked(0x103); + + internal const int SmbFileBothDirectoryInfo = unchecked(0x104); + + internal class SmbFindFileBothDirectoryInfo : IFileEntry + { + internal int NextEntryOffset; + + internal int FileIndex; + + internal long CreationTime; + + internal long LastAccessTime; + + internal long LastWriteTime; + + internal long ChangeTime; + + internal long EndOfFile; + + internal long AllocationSize; + + internal int ExtFileAttributes; + + internal int FileNameLength; + + internal int EaSize; + + internal int ShortNameLength; + + internal string ShortName; + + internal string Filename; + + // information levels + public virtual string GetName() + { + return Filename; + } + + public virtual int GetType() + { + return SmbFile.TypeFilesystem; + } + + public virtual int GetAttributes() + { + return ExtFileAttributes; + } + + public virtual long CreateTime() + { + return CreationTime; + } + + public virtual long LastModified() + { + return LastWriteTime; + } + + public virtual long Length() + { + return EndOfFile; + } + + public override string ToString() + { + return "SmbFindFileBothDirectoryInfo[" + "nextEntryOffset=" + NextEntryOffset + + ",fileIndex=" + FileIndex + ",creationTime=" + Extensions.CreateDate + (CreationTime) + ",lastAccessTime=" + Extensions.CreateDate(LastAccessTime + ) + ",lastWriteTime=" + Extensions.CreateDate(LastWriteTime) + ",changeTime=" + + Extensions.CreateDate(ChangeTime) + ",endOfFile=" + EndOfFile + + ",allocationSize=" + AllocationSize + ",extFileAttributes=" + ExtFileAttributes + + ",fileNameLength=" + FileNameLength + ",eaSize=" + EaSize + ",shortNameLength=" + + ShortNameLength + ",shortName=" + ShortName + ",filename=" + Filename + + "]"; + } + + internal SmbFindFileBothDirectoryInfo(Trans2FindFirst2Response enclosing) + { + this._enclosing = enclosing; + } + + private readonly Trans2FindFirst2Response _enclosing; + } + + internal int Sid; + + internal bool IsEndOfSearch; + + internal int EaErrorOffset; + + internal int LastNameOffset; + + internal int LastNameBufferIndex; + + internal string LastName; + + internal int ResumeKey; + + public Trans2FindFirst2Response() + { + Command = SmbComTransaction2; + SubCommand = Smb.SmbComTransaction.Trans2FindFirst2; + } + + internal virtual string ReadString(byte[] src, int srcIndex, int len) + { + string str = null; + try + { + if (UseUnicode) + { + // should Unicode alignment be corrected for here? + str = Runtime.GetStringForBytes(src, srcIndex, len, SmbConstants.UniEncoding); + } + else + { + if (len > 0 && src[srcIndex + len - 1] == '\0') + { + len--; + } + str = Runtime.GetStringForBytes(src, srcIndex, len, SmbConstants.OemEncoding + ); + } + } + catch (UnsupportedEncodingException uee) + { + if (Log.Level > 1) + { + Runtime.PrintStackTrace(uee, Log); + } + } + return str; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + int start = bufferIndex; + if (SubCommand == Smb.SmbComTransaction.Trans2FindFirst2) + { + Sid = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + } + NumEntries = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + IsEndOfSearch = (buffer[bufferIndex] & unchecked(0x01)) == unchecked(0x01) ? true : false; + bufferIndex += 2; + EaErrorOffset = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + LastNameOffset = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + return bufferIndex - start; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + int start = bufferIndex; + SmbFindFileBothDirectoryInfo e; + LastNameBufferIndex = bufferIndex + LastNameOffset; + Results = new SmbFindFileBothDirectoryInfo[NumEntries]; + for (int i = 0; i < NumEntries; i++) + { + Results[i] = e = new SmbFindFileBothDirectoryInfo(this); + e.NextEntryOffset = ReadInt4(buffer, bufferIndex); + e.FileIndex = ReadInt4(buffer, bufferIndex + 4); + e.CreationTime = ReadTime(buffer, bufferIndex + 8); + // e.lastAccessTime = readTime( buffer, bufferIndex + 16 ); + e.LastWriteTime = ReadTime(buffer, bufferIndex + 24); + // e.changeTime = readTime( buffer, bufferIndex + 32 ); + e.EndOfFile = ReadInt8(buffer, bufferIndex + 40); + // e.allocationSize = readInt8( buffer, bufferIndex + 48 ); + e.ExtFileAttributes = ReadInt4(buffer, bufferIndex + 56); + e.FileNameLength = ReadInt4(buffer, bufferIndex + 60); + // e.eaSize = readInt4( buffer, bufferIndex + 64 ); + // e.shortNameLength = buffer[bufferIndex + 68] & 0xFF; + // e.shortName = readString( buffer, bufferIndex + 70, e.shortNameLength ); + e.Filename = ReadString(buffer, bufferIndex + 94, e.FileNameLength); + if (LastNameBufferIndex >= bufferIndex && (e.NextEntryOffset == 0 || LastNameBufferIndex + < (bufferIndex + e.NextEntryOffset))) + { + LastName = e.Filename; + ResumeKey = e.FileIndex; + } + bufferIndex += e.NextEntryOffset; + } + //return bufferIndex - start; + return DataCount; + } + + public override string ToString() + { + string c; + if (SubCommand == Smb.SmbComTransaction.Trans2FindFirst2) + { + c = "Trans2FindFirst2Response["; + } + else + { + c = "Trans2FindNext2Response["; + } + return c + base.ToString() + ",sid=" + Sid + ",searchCount=" + NumEntries + + ",isEndOfSearch=" + IsEndOfSearch + ",eaErrorOffset=" + EaErrorOffset + ",lastNameOffset=" + + LastNameOffset + ",lastName=" + LastName + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2FindNext2.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2FindNext2.cs new file mode 100644 index 0000000000..cb860f7993 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2FindNext2.cs @@ -0,0 +1,109 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; + +namespace SharpCifs.Smb +{ + internal class Trans2FindNext2 : SmbComTransaction + { + private int _sid; + + private int _informationLevel; + + private int _resumeKey; + + private int _flags; + + private string _filename; + + internal Trans2FindNext2(int sid, int resumeKey, string filename) + { + this._sid = sid; + this._resumeKey = resumeKey; + this._filename = filename; + Command = SmbComTransaction2; + SubCommand = Trans2FindNext2; + _informationLevel = Smb.Trans2FindFirst2.SmbFileBothDirectoryInfo; + _flags = unchecked(0x00); + MaxParameterCount = 8; + MaxDataCount = Smb.Trans2FindFirst2.ListSize; + MaxSetupCount = 0; + } + + internal override void Reset(int resumeKey, string lastName) + { + base.Reset(); + this._resumeKey = resumeKey; + _filename = lastName; + Flags2 = 0; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + dst[dstIndex++] = SubCommand; + dst[dstIndex++] = unchecked(unchecked(0x00)); + return 2; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(_sid, dst, dstIndex); + dstIndex += 2; + WriteInt2(Smb.Trans2FindFirst2.ListCount, dst, dstIndex); + dstIndex += 2; + WriteInt2(_informationLevel, dst, dstIndex); + dstIndex += 2; + WriteInt4(_resumeKey, dst, dstIndex); + dstIndex += 4; + WriteInt2(_flags, dst, dstIndex); + dstIndex += 2; + dstIndex += WriteString(_filename, dst, dstIndex); + return dstIndex - start; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "Trans2FindNext2[" + base.ToString() + ",sid=" + _sid + ",searchCount=" + + Smb.Trans2FindFirst2.ListSize + ",informationLevel=0x" + Hexdump.ToHexString(_informationLevel + , 3) + ",resumeKey=0x" + Hexdump.ToHexString(_resumeKey, 4) + ",flags=0x" + Hexdump + .ToHexString(_flags, 2) + ",filename=" + _filename + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2GetDfsReferral.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2GetDfsReferral.cs new file mode 100644 index 0000000000..c83de79737 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2GetDfsReferral.cs @@ -0,0 +1,78 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class Trans2GetDfsReferral : SmbComTransaction + { + private int _maxReferralLevel = 3; + + internal Trans2GetDfsReferral(string filename) + { + Path = filename; + Command = SmbComTransaction2; + SubCommand = Trans2GetDfsReferral; + TotalDataCount = 0; + MaxParameterCount = 0; + MaxDataCount = 4096; + MaxSetupCount = unchecked(unchecked(0x00)); + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + dst[dstIndex++] = SubCommand; + dst[dstIndex++] = unchecked(unchecked(0x00)); + return 2; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(_maxReferralLevel, dst, dstIndex); + dstIndex += 2; + dstIndex += WriteString(Path, dst, dstIndex); + return dstIndex - start; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "Trans2GetDfsReferral[" + base.ToString() + ",maxReferralLevel=0x" + + _maxReferralLevel + ",filename=" + Path + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2GetDfsReferralResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2GetDfsReferralResponse.cs new file mode 100644 index 0000000000..5fa4a795da --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2GetDfsReferralResponse.cs @@ -0,0 +1,179 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal class Trans2GetDfsReferralResponse : SmbComTransactionResponse + { + internal class Referral + { + private int _version; + + private int _size; + + private int _serverType; + + private int _flags; + + private int _proximity; + + private int _pathOffset; + + private int _altPathOffset; + + private int _nodeOffset; + + private string _altPath; + + internal int Ttl; + + internal string Path; + + internal string Node; + + internal virtual int ReadWireFormat(byte[] buffer, int bufferIndex, int len) + { + int start = bufferIndex; + _version = ReadInt2(buffer, bufferIndex); + if (_version != 3 && _version != 1) + { + throw new RuntimeException("Version " + _version + " referral not supported. Please report this to jcifs at samba dot org." + ); + } + bufferIndex += 2; + _size = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + _serverType = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + _flags = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + if (_version == 3) + { + _proximity = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + Ttl = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + _pathOffset = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + _altPathOffset = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + _nodeOffset = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + Path = _enclosing.ReadString(buffer, start + _pathOffset, len, (_enclosing.Flags2 & SmbConstants.Flags2Unicode) != 0); + if (_nodeOffset > 0) + { + Node = _enclosing.ReadString(buffer, start + _nodeOffset, len, (_enclosing.Flags2 & SmbConstants.Flags2Unicode) != 0); + } + } + else + { + if (_version == 1) + { + Node = _enclosing.ReadString(buffer, bufferIndex, len, (_enclosing + .Flags2 & SmbConstants.Flags2Unicode) != 0); + } + } + return _size; + } + + public override string ToString() + { + return "Referral[" + "version=" + _version + ",size=" + _size + + ",serverType=" + _serverType + ",flags=" + _flags + ",proximity=" + _proximity + ",ttl=" + Ttl + ",pathOffset=" + _pathOffset + ",altPathOffset=" + + _altPathOffset + ",nodeOffset=" + _nodeOffset + ",path=" + Path + + ",altPath=" + _altPath + ",node=" + Node + "]"; + } + + internal Referral(Trans2GetDfsReferralResponse enclosing) + { + this._enclosing = enclosing; + } + + private readonly Trans2GetDfsReferralResponse _enclosing; + } + + internal int PathConsumed; + + internal int NumReferrals; + + internal int flags; + + internal Referral[] Referrals; + + public Trans2GetDfsReferralResponse() + { + SubCommand = Smb.SmbComTransaction.Trans2GetDfsReferral; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + int start = bufferIndex; + PathConsumed = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + if ((Flags2 & SmbConstants.Flags2Unicode) != 0) + { + PathConsumed /= 2; + } + NumReferrals = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + flags = ReadInt2(buffer, bufferIndex); + bufferIndex += 4; + Referrals = new Referral[NumReferrals]; + for (int ri = 0; ri < NumReferrals; ri++) + { + Referrals[ri] = new Referral(this); + bufferIndex += Referrals[ri].ReadWireFormat(buffer, bufferIndex, len); + } + return bufferIndex - start; + } + + public override string ToString() + { + return "Trans2GetDfsReferralResponse[" + base.ToString() + ",pathConsumed=" + + PathConsumed + ",numReferrals=" + NumReferrals + ",flags=" + flags + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2QueryFSInformation.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2QueryFSInformation.cs new file mode 100644 index 0000000000..27b350e535 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2QueryFSInformation.cs @@ -0,0 +1,80 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; + +namespace SharpCifs.Smb +{ + internal class Trans2QueryFsInformation : SmbComTransaction + { + private int _informationLevel; + + internal Trans2QueryFsInformation(int informationLevel) + { + Command = SmbComTransaction2; + SubCommand = Trans2QueryFsInformation; + this._informationLevel = informationLevel; + TotalParameterCount = 2; + TotalDataCount = 0; + MaxParameterCount = 0; + MaxDataCount = 800; + MaxSetupCount = 0; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + dst[dstIndex++] = SubCommand; + dst[dstIndex++] = unchecked(unchecked(0x00)); + return 2; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(_informationLevel, dst, dstIndex); + dstIndex += 2; + return dstIndex - start; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "Trans2QueryFSInformation[" + base.ToString() + ",informationLevel=0x" + + Hexdump.ToHexString(_informationLevel, 3) + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2QueryFSInformationResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2QueryFSInformationResponse.cs new file mode 100644 index 0000000000..2253e7b6fc --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2QueryFSInformationResponse.cs @@ -0,0 +1,192 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class Trans2QueryFsInformationResponse : SmbComTransactionResponse + { + internal const int SMB_INFO_ALLOCATION = 1; + + internal const int SmbQueryFsSizeInfo = unchecked(0x103); + + internal const int SmbFsFullSizeInformation = 1007; + + internal class SmbInfoAllocation : IAllocInfo + { + internal long Alloc; + + internal long Free; + + internal int SectPerAlloc; + + internal int BytesPerSect; + + // information levels + // Also handles SmbQueryFSSizeInfo + public virtual long GetCapacity() + { + return Alloc * SectPerAlloc * BytesPerSect; + } + + public virtual long GetFree() + { + return Free * SectPerAlloc * BytesPerSect; + } + + public override string ToString() + { + return "SmbInfoAllocation[" + "alloc=" + Alloc + ",free=" + Free + ",sectPerAlloc=" + SectPerAlloc + ",bytesPerSect=" + BytesPerSect + + "]"; + } + + internal SmbInfoAllocation(Trans2QueryFsInformationResponse enclosing) + { + this._enclosing = enclosing; + } + + private readonly Trans2QueryFsInformationResponse _enclosing; + } + + private int _informationLevel; + + internal IAllocInfo Info; + + internal Trans2QueryFsInformationResponse(int informationLevel) + { + this._informationLevel = informationLevel; + Command = SmbComTransaction2; + SubCommand = Smb.SmbComTransaction.Trans2QueryFsInformation; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + switch (_informationLevel) + { + case SMB_INFO_ALLOCATION: + { + return ReadSmbInfoAllocationWireFormat(buffer, bufferIndex); + } + + case SmbQueryFsSizeInfo: + { + return ReadSmbQueryFsSizeInfoWireFormat(buffer, bufferIndex); + } + + case SmbFsFullSizeInformation: + { + return ReadFsFullSizeInformationWireFormat(buffer, bufferIndex); + } + + default: + { + return 0; + } + } + } + + internal virtual int ReadSmbInfoAllocationWireFormat(byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + SmbInfoAllocation info = new SmbInfoAllocation + (this); + bufferIndex += 4; + // skip idFileSystem + info.SectPerAlloc = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + info.Alloc = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + info.Free = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + info.BytesPerSect = ReadInt2(buffer, bufferIndex); + bufferIndex += 4; + this.Info = info; + return bufferIndex - start; + } + + internal virtual int ReadSmbQueryFsSizeInfoWireFormat(byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + SmbInfoAllocation info = new SmbInfoAllocation + (this); + info.Alloc = ReadInt8(buffer, bufferIndex); + bufferIndex += 8; + info.Free = ReadInt8(buffer, bufferIndex); + bufferIndex += 8; + info.SectPerAlloc = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + info.BytesPerSect = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + this.Info = info; + return bufferIndex - start; + } + + internal virtual int ReadFsFullSizeInformationWireFormat(byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + SmbInfoAllocation info = new SmbInfoAllocation + (this); + // Read total allocation units. + info.Alloc = ReadInt8(buffer, bufferIndex); + bufferIndex += 8; + // read caller available allocation units + info.Free = ReadInt8(buffer, bufferIndex); + bufferIndex += 8; + // skip actual free units + bufferIndex += 8; + info.SectPerAlloc = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + info.BytesPerSect = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + this.Info = info; + return bufferIndex - start; + } + + public override string ToString() + { + return "Trans2QueryFSInformationResponse[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2QueryPathInformation.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2QueryPathInformation.cs new file mode 100644 index 0000000000..b3db64790d --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2QueryPathInformation.cs @@ -0,0 +1,85 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; + +namespace SharpCifs.Smb +{ + internal class Trans2QueryPathInformation : SmbComTransaction + { + private int _informationLevel; + + internal Trans2QueryPathInformation(string filename, int informationLevel) + { + Path = filename; + this._informationLevel = informationLevel; + Command = SmbComTransaction2; + SubCommand = Trans2QueryPathInformation; + TotalDataCount = 0; + MaxParameterCount = 2; + MaxDataCount = 40; + MaxSetupCount = unchecked(unchecked(0x00)); + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + dst[dstIndex++] = SubCommand; + dst[dstIndex++] = unchecked(unchecked(0x00)); + return 2; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(_informationLevel, dst, dstIndex); + dstIndex += 2; + dst[dstIndex++] = unchecked(unchecked(0x00)); + dst[dstIndex++] = unchecked(unchecked(0x00)); + dst[dstIndex++] = unchecked(unchecked(0x00)); + dst[dstIndex++] = unchecked(unchecked(0x00)); + dstIndex += WriteString(Path, dst, dstIndex); + return dstIndex - start; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "Trans2QueryPathInformation[" + base.ToString() + ",informationLevel=0x" + + Hexdump.ToHexString(_informationLevel, 3) + ",filename=" + Path + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2QueryPathInformationResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2QueryPathInformationResponse.cs new file mode 100644 index 0000000000..50650df627 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2QueryPathInformationResponse.cs @@ -0,0 +1,227 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal class Trans2QueryPathInformationResponse : SmbComTransactionResponse + { + internal const int SMB_QUERY_FILE_BASIC_INFO = unchecked(0x101); + + internal const int SMB_QUERY_FILE_STANDARD_INFO = unchecked(0x102); + + internal class SmbQueryFileBasicInfo : IInfo + { + internal long CreateTime; + + internal long LastAccessTime; + + internal long LastWriteTime; + + internal long ChangeTime; + + internal int Attributes; + + // information levels + public virtual int GetAttributes() + { + return Attributes; + } + + public virtual long GetCreateTime() + { + return CreateTime; + } + + public virtual long GetLastWriteTime() + { + return LastWriteTime; + } + + public virtual long GetSize() + { + return 0L; + } + + public override string ToString() + { + return "SmbQueryFileBasicInfo[" + "createTime=" + Extensions.CreateDate + (CreateTime) + ",lastAccessTime=" + Extensions.CreateDate(LastAccessTime + ) + ",lastWriteTime=" + Extensions.CreateDate(LastWriteTime) + ",changeTime=" + + Extensions.CreateDate(ChangeTime) + ",attributes=0x" + Hexdump.ToHexString + (Attributes, 4) + "]"; + } + + internal SmbQueryFileBasicInfo(Trans2QueryPathInformationResponse enclosing) + { + this._enclosing = enclosing; + } + + private readonly Trans2QueryPathInformationResponse _enclosing; + } + + internal class SmbQueryFileStandardInfo : IInfo + { + internal long AllocationSize; + + internal long EndOfFile; + + internal int NumberOfLinks; + + internal bool DeletePending; + + internal bool Directory; + + public virtual int GetAttributes() + { + return 0; + } + + public virtual long GetCreateTime() + { + return 0L; + } + + public virtual long GetLastWriteTime() + { + return 0L; + } + + public virtual long GetSize() + { + return EndOfFile; + } + + public override string ToString() + { + return "SmbQueryInfoStandard[" + "allocationSize=" + AllocationSize + + ",endOfFile=" + EndOfFile + ",numberOfLinks=" + NumberOfLinks + ",deletePending=" + + DeletePending + ",directory=" + Directory + "]"; + } + + internal SmbQueryFileStandardInfo(Trans2QueryPathInformationResponse enclosing) + { + this._enclosing = enclosing; + } + + private readonly Trans2QueryPathInformationResponse _enclosing; + } + + private int _informationLevel; + + internal IInfo Info; + + internal Trans2QueryPathInformationResponse(int informationLevel) + { + this._informationLevel = informationLevel; + SubCommand = Smb.SmbComTransaction.Trans2QueryPathInformation; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + // observed two zero bytes here with at least win98 + return 2; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + switch (_informationLevel) + { + case SMB_QUERY_FILE_BASIC_INFO: + { + return ReadSmbQueryFileBasicInfoWireFormat(buffer, bufferIndex); + } + + case SMB_QUERY_FILE_STANDARD_INFO: + { + return ReadSmbQueryFileStandardInfoWireFormat(buffer, bufferIndex); + } + + default: + { + return 0; + } + } + } + + internal virtual int ReadSmbQueryFileStandardInfoWireFormat(byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + SmbQueryFileStandardInfo info = new SmbQueryFileStandardInfo + (this); + info.AllocationSize = ReadInt8(buffer, bufferIndex); + bufferIndex += 8; + info.EndOfFile = ReadInt8(buffer, bufferIndex); + bufferIndex += 8; + info.NumberOfLinks = ReadInt4(buffer, bufferIndex); + bufferIndex += 4; + info.DeletePending = (buffer[bufferIndex++] & unchecked(0xFF)) > 0; + info.Directory = (buffer[bufferIndex++] & unchecked(0xFF)) > 0; + this.Info = info; + return bufferIndex - start; + } + + internal virtual int ReadSmbQueryFileBasicInfoWireFormat(byte[] buffer, int bufferIndex + ) + { + int start = bufferIndex; + SmbQueryFileBasicInfo info = new SmbQueryFileBasicInfo + (this); + info.CreateTime = ReadTime(buffer, bufferIndex); + bufferIndex += 8; + info.LastAccessTime = ReadTime(buffer, bufferIndex); + bufferIndex += 8; + info.LastWriteTime = ReadTime(buffer, bufferIndex); + bufferIndex += 8; + info.ChangeTime = ReadTime(buffer, bufferIndex); + bufferIndex += 8; + info.Attributes = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + this.Info = info; + return bufferIndex - start; + } + + public override string ToString() + { + return "Trans2QueryPathInformationResponse[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2SetFileInformation.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2SetFileInformation.cs new file mode 100644 index 0000000000..289cab866b --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2SetFileInformation.cs @@ -0,0 +1,105 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class Trans2SetFileInformation : SmbComTransaction + { + internal const int SmbFileBasicInfo = unchecked(0x101); + + private int _fid; + + private int _attributes; + + private long _createTime; + + private long _lastWriteTime; + + internal Trans2SetFileInformation(int fid, int attributes, long createTime, long + lastWriteTime) + { + this._fid = fid; + this._attributes = attributes; + this._createTime = createTime; + this._lastWriteTime = lastWriteTime; + Command = SmbComTransaction2; + SubCommand = Trans2SetFileInformation; + MaxParameterCount = 6; + MaxDataCount = 0; + MaxSetupCount = unchecked(unchecked(0x00)); + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + dst[dstIndex++] = SubCommand; + dst[dstIndex++] = unchecked(unchecked(0x00)); + return 2; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteInt2(_fid, dst, dstIndex); + dstIndex += 2; + WriteInt2(SmbFileBasicInfo, dst, dstIndex); + dstIndex += 2; + WriteInt2(0, dst, dstIndex); + dstIndex += 2; + return dstIndex - start; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + int start = dstIndex; + WriteTime(_createTime, dst, dstIndex); + dstIndex += 8; + WriteInt8(0L, dst, dstIndex); + dstIndex += 8; + WriteTime(_lastWriteTime, dst, dstIndex); + dstIndex += 8; + WriteInt8(0L, dst, dstIndex); + dstIndex += 8; + WriteInt2(unchecked(0x80) | _attributes, dst, dstIndex); + dstIndex += 2; + WriteInt8(0L, dst, dstIndex); + dstIndex += 6; + return dstIndex - start; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "Trans2SetFileInformation[" + base.ToString() + ",fid=" + _fid + + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2SetFileInformationResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2SetFileInformationResponse.cs new file mode 100644 index 0000000000..b21f356b49 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/Trans2SetFileInformationResponse.cs @@ -0,0 +1,63 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class Trans2SetFileInformationResponse : SmbComTransactionResponse + { + public Trans2SetFileInformationResponse() + { + SubCommand = Smb.SmbComTransaction.Trans2SetFileInformation; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "Trans2SetFileInformationResponse[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/TransCallNamedPipe.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransCallNamedPipe.cs new file mode 100644 index 0000000000..404af0aaad --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransCallNamedPipe.cs @@ -0,0 +1,97 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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; + +namespace SharpCifs.Smb +{ + internal class TransCallNamedPipe : SmbComTransaction + { + private byte[] _pipeData; + + private int _pipeDataOff; + + private int _pipeDataLen; + + internal TransCallNamedPipe(string pipeName, byte[] data, int off, int len) + { + Name = pipeName; + _pipeData = data; + _pipeDataOff = off; + _pipeDataLen = len; + Command = SmbComTransaction; + SubCommand = TransCallNamedPipe; + Timeout = unchecked((int)(0xFFFFFFFF)); + MaxParameterCount = 0; + MaxDataCount = unchecked(0xFFFF); + MaxSetupCount = unchecked(unchecked(0x00)); + SetupCount = 2; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + dst[dstIndex++] = SubCommand; + dst[dstIndex++] = unchecked(unchecked(0x00)); + // this says "Transaction priority" in netmon + dst[dstIndex++] = unchecked(unchecked(0x00)); + // no FID + dst[dstIndex++] = unchecked(unchecked(0x00)); + return 4; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + if ((dst.Length - dstIndex) < _pipeDataLen) + { + if (Log.Level >= 3) + { + Log.WriteLine("TransCallNamedPipe data too long for buffer"); + } + return 0; + } + Array.Copy(_pipeData, _pipeDataOff, dst, dstIndex, _pipeDataLen); + return _pipeDataLen; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "TransCallNamedPipe[" + base.ToString() + ",pipeName=" + Name + + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/TransCallNamedPipeResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransCallNamedPipeResponse.cs new file mode 100644 index 0000000000..b86cc7fdb3 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransCallNamedPipeResponse.cs @@ -0,0 +1,77 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal class TransCallNamedPipeResponse : SmbComTransactionResponse + { + private SmbNamedPipe _pipe; + + internal TransCallNamedPipeResponse(SmbNamedPipe pipe) + { + this._pipe = pipe; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + if (_pipe.PipeIn != null) + { + TransactNamedPipeInputStream @in = (TransactNamedPipeInputStream)_pipe.PipeIn; + lock (@in.Lock) + { + @in.Receive(buffer, bufferIndex, len); + Runtime.Notify(@in.Lock); + } + } + return len; + } + + public override string ToString() + { + return "TransCallNamedPipeResponse[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/TransPeekNamedPipe.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransPeekNamedPipe.cs new file mode 100644 index 0000000000..9b80bbe1e2 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransPeekNamedPipe.cs @@ -0,0 +1,78 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class TransPeekNamedPipe : SmbComTransaction + { + private int _fid; + + internal TransPeekNamedPipe(string pipeName, int fid) + { + Name = pipeName; + this._fid = fid; + Command = SmbComTransaction; + SubCommand = TransPeekNamedPipe; + Timeout = unchecked((int)(0xFFFFFFFF)); + MaxParameterCount = 6; + MaxDataCount = 1; + MaxSetupCount = unchecked(unchecked(0x00)); + SetupCount = 2; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + dst[dstIndex++] = SubCommand; + dst[dstIndex++] = unchecked(unchecked(0x00)); + // this says "Transaction priority" in netmon + WriteInt2(_fid, dst, dstIndex); + return 4; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "TransPeekNamedPipe[" + base.ToString() + ",pipeName=" + Name + + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/TransPeekNamedPipeResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransPeekNamedPipeResponse.cs new file mode 100644 index 0000000000..6bcf2d07e3 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransPeekNamedPipeResponse.cs @@ -0,0 +1,84 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class TransPeekNamedPipeResponse : SmbComTransactionResponse + { + private SmbNamedPipe _pipe; + + private int _head; + + internal const int StatusDisconnected = 1; + + internal const int StatusListening = 2; + + internal const int StatusConnectionOk = 3; + + internal const int StatusServerEndClosed = 4; + + internal int status; + + internal int Available; + + internal TransPeekNamedPipeResponse(SmbNamedPipe pipe) + { + this._pipe = pipe; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + Available = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + _head = ReadInt2(buffer, bufferIndex); + bufferIndex += 2; + status = ReadInt2(buffer, bufferIndex); + return 6; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "TransPeekNamedPipeResponse[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/TransTransactNamedPipe.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransTransactNamedPipe.cs new file mode 100644 index 0000000000..1b6ec9cca5 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransTransactNamedPipe.cs @@ -0,0 +1,97 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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; + +namespace SharpCifs.Smb +{ + internal class TransTransactNamedPipe : SmbComTransaction + { + private byte[] _pipeData; + + private int _pipeFid; + + private int _pipeDataOff; + + private int _pipeDataLen; + + internal TransTransactNamedPipe(int fid, byte[] data, int off, int len) + { + _pipeFid = fid; + _pipeData = data; + _pipeDataOff = off; + _pipeDataLen = len; + Command = SmbComTransaction; + SubCommand = TransTransactNamedPipe; + MaxParameterCount = 0; + MaxDataCount = unchecked(0xFFFF); + MaxSetupCount = unchecked(unchecked(0x00)); + SetupCount = 2; + Name = "\\PIPE\\"; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + dst[dstIndex++] = SubCommand; + dst[dstIndex++] = unchecked(unchecked(0x00)); + WriteInt2(_pipeFid, dst, dstIndex); + dstIndex += 2; + return 4; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + if ((dst.Length - dstIndex) < _pipeDataLen) + { + if (Log.Level >= 3) + { + Log.WriteLine("TransTransactNamedPipe data too long for buffer"); + } + return 0; + } + Array.Copy(_pipeData, _pipeDataOff, dst, dstIndex, _pipeDataLen); + return _pipeDataLen; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "TransTransactNamedPipe[" + base.ToString() + ",pipeFid=" + _pipeFid + + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/TransTransactNamedPipeResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransTransactNamedPipeResponse.cs new file mode 100644 index 0000000000..b8d14781c8 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransTransactNamedPipeResponse.cs @@ -0,0 +1,77 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal class TransTransactNamedPipeResponse : SmbComTransactionResponse + { + private SmbNamedPipe _pipe; + + internal TransTransactNamedPipeResponse(SmbNamedPipe pipe) + { + this._pipe = pipe; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + if (_pipe.PipeIn != null) + { + TransactNamedPipeInputStream @in = (TransactNamedPipeInputStream)_pipe.PipeIn; + lock (@in.Lock) + { + @in.Receive(buffer, bufferIndex, len); + Runtime.Notify(@in.Lock); + } + } + return len; + } + + public override string ToString() + { + return "TransTransactNamedPipeResponse[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/TransWaitNamedPipe.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransWaitNamedPipe.cs new file mode 100644 index 0000000000..a184665aa1 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransWaitNamedPipe.cs @@ -0,0 +1,76 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class TransWaitNamedPipe : SmbComTransaction + { + internal TransWaitNamedPipe(string pipeName) + { + Name = pipeName; + Command = SmbComTransaction; + SubCommand = TransWaitNamedPipe; + Timeout = unchecked((int)(0xFFFFFFFF)); + MaxParameterCount = 0; + MaxDataCount = 0; + MaxSetupCount = unchecked(unchecked(0x00)); + SetupCount = 2; + } + + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + dst[dstIndex++] = SubCommand; + dst[dstIndex++] = unchecked(unchecked(0x00)); + dst[dstIndex++] = unchecked(unchecked(0x00)); + // no FID + dst[dstIndex++] = unchecked(unchecked(0x00)); + return 4; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "TransWaitNamedPipe[" + base.ToString() + ",pipeName=" + Name + + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/TransWaitNamedPipeResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransWaitNamedPipeResponse.cs new file mode 100644 index 0000000000..a62a82ec7a --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransWaitNamedPipeResponse.cs @@ -0,0 +1,59 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class TransWaitNamedPipeResponse : SmbComTransactionResponse + { + // not much to this one is there :~) + internal override int WriteSetupWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteParametersWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int WriteDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } + + internal override int ReadSetupWireFormat(byte[] buffer, int bufferIndex, int len + ) + { + return 0; + } + + internal override int ReadParametersWireFormat(byte[] buffer, int bufferIndex, int + len) + { + return 0; + } + + internal override int ReadDataWireFormat(byte[] buffer, int bufferIndex, int len) + { + return 0; + } + + public override string ToString() + { + return "TransWaitNamedPipeResponse[" + base.ToString() + "]"; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/TransactNamedPipeInputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransactNamedPipeInputStream.cs new file mode 100644 index 0000000000..46d4185829 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransactNamedPipeInputStream.cs @@ -0,0 +1,180 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Smb +{ + internal class TransactNamedPipeInputStream : SmbFileInputStream + { + private const int InitPipeSize = 4096; + + private byte[] _pipeBuf = new byte[InitPipeSize]; + + private int _begIdx; + + private int _nxtIdx; + + private int _used; + + private bool _dcePipe; + + internal object Lock; + + /// + /// + /// + internal TransactNamedPipeInputStream(SmbNamedPipe pipe) : base(pipe, (pipe.PipeType + & unchecked((int)(0xFFFF00FF))) | SmbFile.OExcl) + { + _dcePipe = (pipe.PipeType & SmbNamedPipe.PipeTypeDceTransact) != SmbNamedPipe + .PipeTypeDceTransact; + Lock = new object(); + } + + /// + public override int Read() + { + int result = -1; + lock (Lock) + { + try + { + while (_used == 0) + { + Runtime.Wait(Lock); + } + } + catch (Exception ie) + { + throw new IOException(ie.Message); + } + result = _pipeBuf[_begIdx] & unchecked(0xFF); + _begIdx = (_begIdx + 1) % _pipeBuf.Length; + } + return result; + } + + /// + public override int Read(byte[] b) + { + return Read(b, 0, b.Length); + } + + /// + public override int Read(byte[] b, int off, int len) + { + int result = -1; + int i; + if (len <= 0) + { + return 0; + } + lock (Lock) + { + try + { + while (_used == 0) + { + Runtime.Wait(Lock); + } + } + catch (Exception ie) + { + throw new IOException(ie.Message); + } + i = _pipeBuf.Length - _begIdx; + result = len > _used ? _used : len; + if (_used > i && result > i) + { + Array.Copy(_pipeBuf, _begIdx, b, off, i); + off += i; + Array.Copy(_pipeBuf, 0, b, off, result - i); + } + else + { + Array.Copy(_pipeBuf, _begIdx, b, off, result); + } + _used -= result; + _begIdx = (_begIdx + result) % _pipeBuf.Length; + } + return result; + } + + /// + public override int Available() + { + if (File.Log.Level >= 3) + { + File.Log.WriteLine("Named Pipe available() does not apply to TRANSACT Named Pipes" + ); + } + return 0; + } + + internal virtual int Receive(byte[] b, int off, int len) + { + int i; + if (len > (_pipeBuf.Length - _used)) + { + byte[] tmp; + int newSize; + newSize = _pipeBuf.Length * 2; + if (len > (newSize - _used)) + { + newSize = len + _used; + } + tmp = _pipeBuf; + _pipeBuf = new byte[newSize]; + i = tmp.Length - _begIdx; + if (_used > i) + { + Array.Copy(tmp, _begIdx, _pipeBuf, 0, i); + Array.Copy(tmp, 0, _pipeBuf, i, _used - i); + } + else + { + Array.Copy(tmp, _begIdx, _pipeBuf, 0, _used); + } + _begIdx = 0; + _nxtIdx = _used; + tmp = null; + } + i = _pipeBuf.Length - _nxtIdx; + if (len > i) + { + Array.Copy(b, off, _pipeBuf, _nxtIdx, i); + off += i; + Array.Copy(b, off, _pipeBuf, 0, len - i); + } + else + { + Array.Copy(b, off, _pipeBuf, _nxtIdx, len); + } + _nxtIdx = (_nxtIdx + len) % _pipeBuf.Length; + _used += len; + return len; + } + + /// + public virtual int Dce_read(byte[] b, int off, int len) + { + return base.Read(b, off, len); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/TransactNamedPipeOutputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransactNamedPipeOutputStream.cs new file mode 100644 index 0000000000..d3e8d3e1ad --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/TransactNamedPipeOutputStream.cs @@ -0,0 +1,86 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + internal class TransactNamedPipeOutputStream : SmbFileOutputStream + { + private string _path; + + private SmbNamedPipe _pipe; + + private byte[] _tmp = new byte[1]; + + private bool _dcePipe; + + /// + internal TransactNamedPipeOutputStream(SmbNamedPipe pipe) : base(pipe, false, (pipe + .PipeType & unchecked((int)(0xFFFF00FF))) | SmbFile.OExcl) + { + this._pipe = pipe; + _dcePipe = (pipe.PipeType & SmbNamedPipe.PipeTypeDceTransact) == SmbNamedPipe + .PipeTypeDceTransact; + _path = pipe.Unc; + } + + /// + public override void Close() + { + _pipe.Close(); + } + + /// + public override void Write(int b) + { + _tmp[0] = unchecked((byte)b); + Write(_tmp, 0, 1); + } + + /// + public override void Write(byte[] b) + { + Write(b, 0, b.Length); + } + + /// + public override void Write(byte[] b, int off, int len) + { + if (len < 0) + { + len = 0; + } + if ((_pipe.PipeType & SmbNamedPipe.PipeTypeCall) == SmbNamedPipe.PipeTypeCall) + { + _pipe.Send(new TransWaitNamedPipe(_path), new TransWaitNamedPipeResponse()); + _pipe.Send(new TransCallNamedPipe(_path, b, off, len), new TransCallNamedPipeResponse + (_pipe)); + } + else + { + if ((_pipe.PipeType & SmbNamedPipe.PipeTypeTransact) == SmbNamedPipe.PipeTypeTransact) + { + EnsureOpen(); + TransTransactNamedPipe req = new TransTransactNamedPipe(_pipe.Fid, b, off, len); + if (_dcePipe) + { + req.MaxDataCount = 1024; + } + _pipe.Send(req, new TransTransactNamedPipeResponse(_pipe)); + } + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Smb/WinError.cs b/Emby.Common.Implementations/IO/SharpCifs/Smb/WinError.cs new file mode 100644 index 0000000000..daecc54072 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Smb/WinError.cs @@ -0,0 +1,49 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Smb +{ + public static class WinError + { + public static int ErrorSuccess = 0; + + public static int ErrorAccessDenied = 5; + + public static int ErrorReqNotAccep = 71; + + public static int ErrorBadPipe = 230; + + public static int ErrorPipeBusy = 231; + + public static int ErrorNoData = 232; + + public static int ErrorPipeNotConnected = 233; + + public static int ErrorMoreData = 234; + + public static int ErrorNoBrowserServersFound = 6118; + + public static int[] WinerrCodes = { ErrorSuccess, ErrorAccessDenied, + ErrorReqNotAccep, ErrorBadPipe, ErrorPipeBusy, ErrorNoData, ErrorPipeNotConnected + , ErrorMoreData, ErrorNoBrowserServersFound }; + + public static string[] WinerrMessages = { "The operation completed successfully." + , "Access is denied.", "No more connections can be made to this remote computer at this time because there are already as many connections as the computer can accept." + , "The pipe state is invalid.", "All pipe instances are busy.", "The pipe is being closed." + , "No process is on the other end of the pipe.", "More data is available.", "The list of servers for this workgroup is not currently available." + }; + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/UniAddress.cs b/Emby.Common.Implementations/IO/SharpCifs/UniAddress.cs new file mode 100644 index 0000000000..816fbe7810 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/UniAddress.cs @@ -0,0 +1,591 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using System.Linq; +using System.Net; +using SharpCifs.Netbios; +using SharpCifs.Util; +using SharpCifs.Util.Sharpen; +using Extensions = SharpCifs.Util.Sharpen.Extensions; + +namespace SharpCifs +{ + /// + ///

Under normal conditions it is not necessary to use + /// this class to use jCIFS properly. + ///

+ /// + ///

Under normal conditions it is not necessary to use + /// this class to use jCIFS properly. Name resolusion is + /// handled internally to the jcifs.smb package. + ///

+ /// This class is a wrapper for both + /// Jcifs.Netbios.NbtAddress + /// and + /// System.Net.IPAddress + /// . The name resolution mechanisms + /// used will systematically query all available configured resolution + /// services including WINS, broadcasts, DNS, and LMHOSTS. See + /// Setting Name Resolution Properties + /// and the jcifs.resolveOrder property. Changing + /// jCIFS name resolution properties can greatly affect the behavior of + /// the client and may be necessary for proper operation. + ///

+ /// This class should be used in favor of InetAddress to resolve + /// hostnames on LANs and WANs that support a mixture of NetBIOS/WINS and + /// DNS resolvable hosts. + /// + public class UniAddress + { + private const int ResolverWins = 0; + + private const int ResolverBcast = 1; + + private const int ResolverDns = 2; + + private const int ResolverLmhosts = 3; + + private static int[] _resolveOrder; + + private static IPAddress _baddr; + + private static LogStream _log = LogStream.GetInstance(); + + static UniAddress() + { + string ro = Config.GetProperty("jcifs.resolveOrder"); + IPAddress nbns = NbtAddress.GetWinsAddress(); + try + { + _baddr = Config.GetInetAddress("jcifs.netbios.baddr", Extensions.GetAddressByName + ("255.255.255.255")); + } + catch (UnknownHostException) + { + } + if (string.IsNullOrEmpty(ro)) + { + if (nbns == null) + { + _resolveOrder = new int[3]; + _resolveOrder[0] = ResolverLmhosts; + _resolveOrder[1] = ResolverDns; + _resolveOrder[2] = ResolverBcast; + } + else + { + _resolveOrder = new int[4]; + _resolveOrder[0] = ResolverLmhosts; + _resolveOrder[1] = ResolverWins; + _resolveOrder[2] = ResolverDns; + _resolveOrder[3] = ResolverBcast; + } + } + else + { + int[] tmp = new int[4]; + StringTokenizer st = new StringTokenizer(ro, ","); + int i = 0; + while (st.HasMoreTokens()) + { + string s = st.NextToken().Trim(); + if (Runtime.EqualsIgnoreCase(s, "LMHOSTS")) + { + tmp[i++] = ResolverLmhosts; + } + else + { + if (Runtime.EqualsIgnoreCase(s, "WINS")) + { + if (nbns == null) + { + if (_log.Level > 1) + { + _log.WriteLine("UniAddress resolveOrder specifies WINS however the " + "jcifs.netbios.wins property has not been set" + ); + } + continue; + } + tmp[i++] = ResolverWins; + } + else + { + if (Runtime.EqualsIgnoreCase(s, "BCAST")) + { + tmp[i++] = ResolverBcast; + } + else + { + if (Runtime.EqualsIgnoreCase(s, "DNS")) + { + tmp[i++] = ResolverDns; + } + else + { + if (_log.Level > 1) + { + _log.WriteLine("unknown resolver method: " + s); + } + } + } + } + } + } + _resolveOrder = new int[i]; + Array.Copy(tmp, 0, _resolveOrder, 0, i); + } + } + + internal class Sem + { + internal Sem(int count) + { + this.Count = count; + } + + internal int Count; + } + + internal class QueryThread : Thread + { + internal Sem Sem; + + internal string Host; + + internal string Scope; + + internal int Type; + + internal NbtAddress[] Ans; + + internal IPAddress Svr; + + internal UnknownHostException Uhe; + + internal QueryThread(Sem sem, string host, int type, string scope, IPAddress + svr) : base("JCIFS-QueryThread: " + host) + { + this.Sem = sem; + this.Host = host; + this.Type = type; + this.Scope = scope; + this.Svr = svr; + } + + public override void Run() + { + try + { + //Ans = new [] { NbtAddress.GetByName(Host, Type, Scope, Svr) }; + Ans = NbtAddress.GetAllByName(Host, Type, Scope, Svr); + } + catch (UnknownHostException uhe) + { + this.Uhe = uhe; + } + catch (Exception ex) + { + Uhe = new UnknownHostException(ex.Message); + } + finally + { + lock (Sem) + { + Sem.Count--; + Runtime.Notify(Sem); + } + } + } + } + + /// + internal static NbtAddress[] LookupServerOrWorkgroup(string name, IPAddress svr) + { + Sem sem = new Sem(2); + int type = NbtAddress.IsWins(svr) ? unchecked(0x1b) : unchecked(0x1d); + QueryThread q1X = new QueryThread(sem, name, type, null, svr + ); + QueryThread q20 = new QueryThread(sem, name, unchecked(0x20), null, svr); + q1X.SetDaemon(true); + q20.SetDaemon(true); + try + { + lock (sem) + { + q1X.Start(); + q20.Start(); + while (sem.Count > 0 && q1X.Ans == null && q20.Ans == null) + { + Runtime.Wait(sem); + } + } + } + catch (Exception) + { + throw new UnknownHostException(name); + } + if (q1X.Ans != null) + { + return q1X.Ans; + } + if (q20.Ans != null) + { + return q20.Ans; + } + throw q1X.Uhe; + } + + ///

Determines the address of a host given it's host name. + /// + /// Determines the address of a host given it's host name. The name can be a + /// machine name like "jcifs.samba.org", or an IP address like "192.168.1.15". + /// + /// NetBIOS or DNS hostname to resolve + /// if there is an error resolving the name + /// + public static UniAddress GetByName(string hostname) + { + return GetByName(hostname, false); + } + + internal static bool IsDotQuadIp(string hostname) + { + if (char.IsDigit(hostname[0])) + { + int i; + int len; + int dots; + char[] data; + i = dots = 0; + len = hostname.Length; + data = hostname.ToCharArray(); + while (i < len && char.IsDigit(data[i++])) + { + if (i == len && dots == 3) + { + // probably an IP address + return true; + } + if (i < len && data[i] == '.') + { + dots++; + i++; + } + } + } + return false; + } + + internal static bool IsAllDigits(string hostname) + { + for (int i = 0; i < hostname.Length; i++) + { + if (char.IsDigit(hostname[i]) == false) + { + return false; + } + } + return true; + } + + /// Lookup hostname and return it's UniAddress. + /// + /// Lookup hostname and return it's UniAddress. If the + /// possibleNTDomainOrWorkgroup parameter is true an + /// addtional name query will be performed to locate a master browser. + /// + /// + public static UniAddress GetByName(string hostname, bool possibleNtDomainOrWorkgroup + ) + { + UniAddress[] addrs = GetAllByName(hostname, possibleNtDomainOrWorkgroup + ); + return addrs[0]; + } + + /// + public static UniAddress[] GetAllByName(string hostname, bool possibleNtDomainOrWorkgroup + ) + { + object addr; + int i; + if (string.IsNullOrEmpty(hostname)) + { + throw new UnknownHostException(); + } + if (IsDotQuadIp(hostname)) + { + UniAddress[] addrs = new UniAddress[1]; + addrs[0] = new UniAddress(NbtAddress.GetByName(hostname)); + return addrs; + } + for (i = 0; i < _resolveOrder.Length; i++) + { + try + { + switch (_resolveOrder[i]) + { + case ResolverLmhosts: + { + if ((addr = Lmhosts.GetByName(hostname)) == null) + { + continue; + } + break; + } + + case ResolverWins: + { + if (hostname == NbtAddress.MasterBrowserName || hostname.Length > 15) + { + // invalid netbios name + continue; + } + if (possibleNtDomainOrWorkgroup) + { + addr = LookupServerOrWorkgroup(hostname, NbtAddress.GetWinsAddress()); + } + else + { + addr = NbtAddress.GetByName(hostname, unchecked(0x20), null, NbtAddress.GetWinsAddress + ()); + } + break; + } + + case ResolverBcast: + { + if (hostname.Length > 15) + { + // invalid netbios name + continue; + } + + try + { + if (possibleNtDomainOrWorkgroup) + { + NbtAddress[] iaddrs = LookupServerOrWorkgroup(hostname, _baddr); + + UniAddress[] addrs = new UniAddress[iaddrs.Length]; + for (int ii = 0; ii < iaddrs.Length; ii++) + { + addrs[ii] = new UniAddress(iaddrs[ii]); + } + return addrs; + + } + else + { + addr = NbtAddress.GetByName(hostname, unchecked(0x20), null, _baddr); + } + + } + catch (Exception ex) + { + if (i == _resolveOrder.Length - 1) + { + throw ex; + } + else + { + continue; + } + } + break; + } + + case ResolverDns: + { + if (IsAllDigits(hostname)) + { + throw new UnknownHostException(hostname); + } + + IPAddress[] iaddrs = Extensions.GetAddressesByName(hostname); + + if (iaddrs == null || iaddrs.Length == 0) + { + continue; + } + + return iaddrs.Select(iaddr => new UniAddress(iaddr)).ToArray(); + } + + default: + { + // Success + throw new UnknownHostException(hostname); + } + } + UniAddress[] addrs1 = new UniAddress[1]; + addrs1[0] = new UniAddress(addr); + return addrs1; + } + catch (IOException) + { + } + } + // Success + // Failure + throw new UnknownHostException(hostname); + } + + internal object Addr; + + internal string CalledName; + + /// + /// Create a UniAddress by wrapping an InetAddress or + /// NbtAddress. + /// + /// + /// Create a UniAddress by wrapping an InetAddress or + /// NbtAddress. + /// + public UniAddress(object addr) + { + if (addr == null) + { + throw new ArgumentException(); + } + this.Addr = addr; + } + + /// Return the IP address of this address as a 32 bit integer. + /// Return the IP address of this address as a 32 bit integer. + public override int GetHashCode() + { + return Addr.GetHashCode(); + } + + /// Compare two addresses for equality. + /// + /// Compare two addresses for equality. Two UniAddresss are equal + /// if they are both UniAddress' and refer to the same IP address. + /// + public override bool Equals(object obj) + { + return obj is UniAddress && Addr.Equals(((UniAddress)obj).Addr); + } + + /// Guess first called name to try for session establishment. + /// + /// Guess first called name to try for session establishment. This + /// method is used exclusively by the jcifs.smb package. + /// + public virtual string FirstCalledName() + { + if (Addr is NbtAddress) + { + return ((NbtAddress)Addr).FirstCalledName(); + } + CalledName = ((IPAddress) Addr).GetHostAddress(); + if (IsDotQuadIp(CalledName)) + { + CalledName = NbtAddress.SmbserverName; + } + else + { + int i = CalledName.IndexOf('.'); + if (i > 1 && i < 15) + { + CalledName = Runtime.Substring(CalledName, 0, i).ToUpper(); + } + else + { + if (CalledName.Length > 15) + { + CalledName = NbtAddress.SmbserverName; + } + else + { + CalledName = CalledName.ToUpper(); + } + } + } + return CalledName; + } + + /// Guess next called name to try for session establishment. + /// + /// Guess next called name to try for session establishment. This + /// method is used exclusively by the jcifs.smb package. + /// + public virtual string NextCalledName() + { + if (Addr is NbtAddress) + { + return ((NbtAddress)Addr).NextCalledName(); + } + if (CalledName != NbtAddress.SmbserverName) + { + CalledName = NbtAddress.SmbserverName; + return CalledName; + } + return null; + } + + /// Return the underlying NbtAddress or InetAddress. + /// Return the underlying NbtAddress or InetAddress. + public virtual object GetAddress() + { + return Addr; + } + + /// Return the hostname of this address such as "MYCOMPUTER". + /// Return the hostname of this address such as "MYCOMPUTER". + public virtual string GetHostName() + { + if (Addr is NbtAddress) + { + return ((NbtAddress)Addr).GetHostName(); + } + return ((IPAddress) Addr).GetHostAddress(); + } + + /// Return the IP address as text such as "192.168.1.15". + /// Return the IP address as text such as "192.168.1.15". + public virtual string GetHostAddress() + { + if (Addr is NbtAddress) + { + return ((NbtAddress)Addr).GetHostAddress(); + } + return ((IPAddress)Addr).GetHostAddress(); + } + + public virtual IPAddress GetHostIpAddress() + { + return (IPAddress) Addr; + } + + /// + /// Return the a text representation of this address such as + /// MYCOMPUTER/192.168.1.15. + /// + /// + /// Return the a text representation of this address such as + /// MYCOMPUTER/192.168.1.15. + /// + public override string ToString() + { + return Addr.ToString(); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Base64.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Base64.cs new file mode 100644 index 0000000000..4770f13548 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Base64.cs @@ -0,0 +1,110 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.Text; + +namespace SharpCifs.Util +{ + public class Base64 + { + private static readonly string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + /// Base-64 encodes the supplied block of data. + /// + /// Base-64 encodes the supplied block of data. Line wrapping is not + /// applied on output. + /// + /// The block of data that is to be Base-64 encoded. + /// A String containing the encoded data. + public static string Encode(byte[] bytes) + { + int length = bytes.Length; + if (length == 0) + { + return string.Empty; + } + StringBuilder buffer = new StringBuilder((int)Math.Ceiling(length / 3d) * 4); + int remainder = length % 3; + length -= remainder; + int block; + int i = 0; + while (i < length) + { + block = ((bytes[i++] & unchecked(0xff)) << 16) | ((bytes[i++] & unchecked( + 0xff)) << 8) | (bytes[i++] & unchecked(0xff)); + buffer.Append(Alphabet[(int)(((uint)block) >> 18)]); + buffer.Append(Alphabet[((int)(((uint)block) >> 12)) & unchecked(0x3f)]); + buffer.Append(Alphabet[((int)(((uint)block) >> 6)) & unchecked(0x3f)]); + buffer.Append(Alphabet[block & unchecked(0x3f)]); + } + if (remainder == 0) + { + return buffer.ToString(); + } + if (remainder == 1) + { + block = (bytes[i] & unchecked(0xff)) << 4; + buffer.Append(Alphabet[(int)(((uint)block) >> 6)]); + buffer.Append(Alphabet[block & unchecked(0x3f)]); + buffer.Append("=="); + return buffer.ToString(); + } + block = (((bytes[i++] & unchecked(0xff)) << 8) | ((bytes[i]) & unchecked(0xff))) << 2; + buffer.Append(Alphabet[(int)(((uint)block) >> 12)]); + buffer.Append(Alphabet[((int)(((uint)block) >> 6)) & unchecked(0x3f)]); + buffer.Append(Alphabet[block & unchecked(0x3f)]); + buffer.Append("="); + return buffer.ToString(); + } + + /// Decodes the supplied Base-64 encoded string. + /// Decodes the supplied Base-64 encoded string. + /// The Base-64 encoded string that is to be decoded. + /// A byte[] containing the decoded data block. + public static byte[] Decode(string @string) + { + int length = @string.Length; + if (length == 0) + { + return new byte[0]; + } + int pad = (@string[length - 2] == '=') ? 2 : (@string[length - 1] == '=') ? 1 : 0; + int size = length * 3 / 4 - pad; + byte[] buffer = new byte[size]; + int block; + int i = 0; + int index = 0; + while (i < length) + { + block = (Alphabet.IndexOf(@string[i++]) & unchecked(0xff)) << 18 | (Alphabet + .IndexOf(@string[i++]) & unchecked(0xff)) << 12 | (Alphabet.IndexOf(@string + [i++]) & unchecked(0xff)) << 6 | (Alphabet.IndexOf(@string[i++]) & unchecked( + 0xff)); + buffer[index++] = unchecked((byte)((int)(((uint)block) >> 16))); + if (index < size) + { + buffer[index++] = unchecked((byte)(((int)(((uint)block) >> 8)) & unchecked(0xff))); + } + if (index < size) + { + buffer[index++] = unchecked((byte)(block & unchecked(0xff))); + } + } + return buffer; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/DES.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/DES.cs new file mode 100644 index 0000000000..c23b14cf88 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/DES.cs @@ -0,0 +1,568 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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; + +namespace SharpCifs.Util +{ + /// + /// This code is derived from the above source + /// JCIFS API + /// Norbert Hranitzky + ///

and modified again by Michael B. + ///

+ /// + /// This code is derived from the above source + /// JCIFS API + /// Norbert Hranitzky + ///

and modified again by Michael B. Allen + /// + public class DES + { + private int[] _encryptKeys = new int[32]; + + private int[] _decryptKeys = new int[32]; + + private int[] _tempInts = new int[2]; + + public DES() + { + } + + public DES(byte[] key) + { + // DesCipher - the DES encryption method + // + // The meat of this code is by Dave Zimmerman , and is: + // + // Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved. + // + // Permission to use, copy, modify, and distribute this software + // and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and + // without fee is hereby granted, provided that this copyright notice is kept + // intact. + // + // WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY + // OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + // TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + // PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE + // FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + // DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. + // + // THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE + // CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE + // PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT + // NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE + // SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE + // SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE + // PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET WORKSHOP + // SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR + // HIGH RISK ACTIVITIES. + // + // + // The rest is: + // + // Copyright (C) 1996 by Jef Poskanzer . All rights reserved. + // + // Copyright (C) 1996 by Wolfgang Platzer + // email: wplatzer@iaik.tu-graz.ac.at + // + // All rights reserved. + // + // Redistribution and use in source and binary forms, with or without + // modification, are permitted provided that the following conditions + // are met: + // 1. Redistributions of source code must retain the above copyright + // notice, this list of conditions and the following disclaimer. + // 2. Redistributions in binary form must reproduce the above copyright + // notice, this list of conditions and the following disclaimer in the + // documentation and/or other materials provided with the distribution. + // + // THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + // ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + // SUCH DAMAGE. + // + // Constructor, byte-array key. + if (key.Length == 7) + { + byte[] key8 = new byte[8]; + MakeSmbKey(key, key8); + SetKey(key8); + } + else + { + SetKey(key); + } + } + + public static void MakeSmbKey(byte[] key7, byte[] key8) + { + int i; + key8[0] = unchecked((byte)((key7[0] >> 1) & unchecked(0xff))); + key8[1] = unchecked((byte)((((key7[0] & unchecked(0x01)) << 6) | (((key7[1 + ] & unchecked(0xff)) >> 2) & unchecked(0xff))) & unchecked(0xff))); + key8[2] = unchecked((byte)((((key7[1] & unchecked(0x03)) << 5) | (((key7[2 + ] & unchecked(0xff)) >> 3) & unchecked(0xff))) & unchecked(0xff))); + key8[3] = unchecked((byte)((((key7[2] & unchecked(0x07)) << 4) | (((key7[3 + ] & unchecked(0xff)) >> 4) & unchecked(0xff))) & unchecked(0xff))); + key8[4] = unchecked((byte)((((key7[3] & unchecked(0x0F)) << 3) | (((key7[4 + ] & unchecked(0xff)) >> 5) & unchecked(0xff))) & unchecked(0xff))); + key8[5] = unchecked((byte)((((key7[4] & unchecked(0x1F)) << 2) | (((key7[5 + ] & unchecked(0xff)) >> 6) & unchecked(0xff))) & unchecked(0xff))); + key8[6] = unchecked((byte)((((key7[5] & unchecked(0x3F)) << 1) | (((key7[6 + ] & unchecked(0xff)) >> 7) & unchecked(0xff))) & unchecked(0xff))); + key8[7] = unchecked((byte)(key7[6] & unchecked(0x7F))); + for (i = 0; i < 8; i++) + { + key8[i] = unchecked((byte)(key8[i] << 1)); + } + } + + /// Set the key. + public virtual void SetKey(byte[] key) + { + // CHECK PAROTY TBD + Deskey(key, true, _encryptKeys); + Deskey(key, false, _decryptKeys); + } + + // Turn an 8-byte key into internal keys. + private void Deskey(byte[] keyBlock, bool encrypting, int[] knL) + { + int i; + int j; + int l; + int m; + int n; + int[] pc1M = new int[56]; + int[] pcr = new int[56]; + int[] kn = new int[32]; + for (j = 0; j < 56; ++j) + { + l = _pc1[j]; + m = l & 0x7; + pc1M[j] = ((keyBlock[(int)(((uint)l) >> 3)] & _bytebit[m]) != 0) ? 1 : 0; + } + for (i = 0; i < 16; ++i) + { + if (encrypting) + { + m = i << 1; + } + else + { + m = (15 - i) << 1; + } + n = m + 1; + kn[m] = kn[n] = 0; + for (j = 0; j < 28; ++j) + { + l = j + _totrot[i]; + if (l < 28) + { + pcr[j] = pc1M[l]; + } + else + { + pcr[j] = pc1M[l - 28]; + } + } + for (j = 28; j < 56; ++j) + { + l = j + _totrot[i]; + if (l < 56) + { + pcr[j] = pc1M[l]; + } + else + { + pcr[j] = pc1M[l - 28]; + } + } + for (j = 0; j < 24; ++j) + { + if (pcr[_pc2[j]] != 0) + { + kn[m] |= _bigbyte[j]; + } + if (pcr[_pc2[j + 24]] != 0) + { + kn[n] |= _bigbyte[j]; + } + } + } + Cookey(kn, knL); + } + + private void Cookey(int[] raw, int[] knL) + { + int raw0; + int raw1; + int rawi; + int knLi; + int i; + for (i = 0, rawi = 0, knLi = 0; i < 16; ++i) + { + raw0 = raw[rawi++]; + raw1 = raw[rawi++]; + knL[knLi] = (raw0 & unchecked(0x00fc0000)) << 6; + knL[knLi] |= (raw0 & unchecked(0x00000fc0)) << 10; + knL[knLi] |= (int)(((uint)(raw1 & unchecked(0x00fc0000))) >> 10); + knL[knLi] |= (int)(((uint)(raw1 & unchecked(0x00000fc0))) >> 6); + ++knLi; + knL[knLi] = (raw0 & unchecked(0x0003f000)) << 12; + knL[knLi] |= (raw0 & unchecked(0x0000003f)) << 16; + knL[knLi] |= (int)(((uint)(raw1 & unchecked(0x0003f000))) >> 4); + knL[knLi] |= (raw1 & unchecked(0x0000003f)); + ++knLi; + } + } + + /// Encrypt a block of eight bytes. + private void Encrypt(byte[] clearText, int clearOff, byte[] cipherText, int cipherOff + ) + { + SquashBytesToInts(clearText, clearOff, _tempInts, 0, 2); + Des(_tempInts, _tempInts, _encryptKeys); + SpreadIntsToBytes(_tempInts, 0, cipherText, cipherOff, 2); + } + + /// Decrypt a block of eight bytes. + private void Decrypt(byte[] cipherText, int cipherOff, byte[] clearText, int clearOff + ) + { + SquashBytesToInts(cipherText, cipherOff, _tempInts, 0, 2); + Des(_tempInts, _tempInts, _decryptKeys); + SpreadIntsToBytes(_tempInts, 0, clearText, clearOff, 2); + } + + // The DES function. + private void Des(int[] inInts, int[] outInts, int[] keys) + { + int fval; + int work; + int right; + int leftt; + int round; + int keysi = 0; + leftt = inInts[0]; + right = inInts[1]; + work = (((int)(((uint)leftt) >> 4)) ^ right) & unchecked(0x0f0f0f0f); + right ^= work; + leftt ^= (work << 4); + work = (((int)(((uint)leftt) >> 16)) ^ right) & unchecked(0x0000ffff); + right ^= work; + leftt ^= (work << 16); + work = (((int)(((uint)right) >> 2)) ^ leftt) & unchecked(0x33333333); + leftt ^= work; + right ^= (work << 2); + work = (((int)(((uint)right) >> 8)) ^ leftt) & unchecked(0x00ff00ff); + leftt ^= work; + right ^= (work << 8); + right = (right << 1) | (((int)(((uint)right) >> 31)) & 1); + work = (leftt ^ right) & unchecked((int)(0xaaaaaaaa)); + leftt ^= work; + right ^= work; + leftt = (leftt << 1) | (((int)(((uint)leftt) >> 31)) & 1); + for (round = 0; round < 8; ++round) + { + work = (right << 28) | ((int)(((uint)right) >> 4)); + work ^= keys[keysi++]; + fval = _sp7[work & unchecked(0x0000003f)]; + fval |= _sp5[((int)(((uint)work) >> 8)) & unchecked(0x0000003f)]; + fval |= _sp3[((int)(((uint)work) >> 16)) & unchecked(0x0000003f)]; + fval |= _sp1[((int)(((uint)work) >> 24)) & unchecked(0x0000003f)]; + work = right ^ keys[keysi++]; + fval |= _sp8[work & unchecked(0x0000003f)]; + fval |= _sp6[((int)(((uint)work) >> 8)) & unchecked(0x0000003f)]; + fval |= _sp4[((int)(((uint)work) >> 16)) & unchecked(0x0000003f)]; + fval |= _sp2[((int)(((uint)work) >> 24)) & unchecked(0x0000003f)]; + leftt ^= fval; + work = (leftt << 28) | ((int)(((uint)leftt) >> 4)); + work ^= keys[keysi++]; + fval = _sp7[work & unchecked(0x0000003f)]; + fval |= _sp5[((int)(((uint)work) >> 8)) & unchecked(0x0000003f)]; + fval |= _sp3[((int)(((uint)work) >> 16)) & unchecked(0x0000003f)]; + fval |= _sp1[((int)(((uint)work) >> 24)) & unchecked(0x0000003f)]; + work = leftt ^ keys[keysi++]; + fval |= _sp8[work & unchecked(0x0000003f)]; + fval |= _sp6[((int)(((uint)work) >> 8)) & unchecked(0x0000003f)]; + fval |= _sp4[((int)(((uint)work) >> 16)) & unchecked(0x0000003f)]; + fval |= _sp2[((int)(((uint)work) >> 24)) & unchecked(0x0000003f)]; + right ^= fval; + } + right = (right << 31) | ((int)(((uint)right) >> 1)); + work = (leftt ^ right) & unchecked((int)(0xaaaaaaaa)); + leftt ^= work; + right ^= work; + leftt = (leftt << 31) | ((int)(((uint)leftt) >> 1)); + work = (((int)(((uint)leftt) >> 8)) ^ right) & unchecked(0x00ff00ff); + right ^= work; + leftt ^= (work << 8); + work = (((int)(((uint)leftt) >> 2)) ^ right) & unchecked(0x33333333); + right ^= work; + leftt ^= (work << 2); + work = (((int)(((uint)right) >> 16)) ^ leftt) & unchecked(0x0000ffff); + leftt ^= work; + right ^= (work << 16); + work = (((int)(((uint)right) >> 4)) ^ leftt) & unchecked(0x0f0f0f0f); + leftt ^= work; + right ^= (work << 4); + outInts[0] = right; + outInts[1] = leftt; + } + + /// Encrypt a block of bytes. + public virtual void Encrypt(byte[] clearText, byte[] cipherText) + { + Encrypt(clearText, 0, cipherText, 0); + } + + /// Decrypt a block of bytes. + public virtual void Decrypt(byte[] cipherText, byte[] clearText) + { + Decrypt(cipherText, 0, clearText, 0); + } + + ///

encrypts an array where the length must be a multiple of 8 + public virtual byte[] Encrypt(byte[] clearText) + { + int length = clearText.Length; + if (length % 8 != 0) + { + Console.Out.WriteLine("Array must be a multiple of 8"); + return null; + } + byte[] cipherText = new byte[length]; + int count = length / 8; + for (int i = 0; i < count; i++) + { + Encrypt(clearText, i * 8, cipherText, i * 8); + } + return cipherText; + } + + /// decrypts an array where the length must be a multiple of 8 + public virtual byte[] Decrypt(byte[] cipherText) + { + int length = cipherText.Length; + if (length % 8 != 0) + { + Console.Out.WriteLine("Array must be a multiple of 8"); + return null; + } + byte[] clearText = new byte[length]; + int count = length / 8; + for (int i = 0; i < count; i++) + { + Encrypt(cipherText, i * 8, clearText, i * 8); + } + return clearText; + } + + private static byte[] _bytebit = { unchecked(unchecked(0x80)), unchecked(unchecked(0x40)), unchecked(unchecked(0x20)), unchecked(unchecked(0x10)), unchecked(unchecked(0x08)), unchecked(unchecked(0x04)), unchecked(unchecked(0x02)), unchecked(unchecked(0x01)) }; + + private static int[] _bigbyte = { unchecked(0x800000), unchecked( + 0x400000), unchecked(0x200000), unchecked(0x100000), unchecked( + 0x080000), unchecked(0x040000), unchecked(0x020000), unchecked( + 0x010000), unchecked(0x008000), unchecked(0x004000), unchecked( + 0x002000), unchecked(0x001000), unchecked(0x000800), unchecked( + 0x000400), unchecked(0x000200), unchecked(0x000100), unchecked( + 0x000080), unchecked(0x000040), unchecked(0x000020), unchecked( + 0x000010), unchecked(0x000008), unchecked(0x000004), unchecked( + 0x000002), unchecked(0x000001) }; + + private static byte[] _pc1 = { unchecked(56), unchecked(48) + , unchecked(40), unchecked(32), unchecked(24), unchecked(16), unchecked(8), unchecked(0), unchecked(57), unchecked(49), unchecked(41), unchecked(33), unchecked(25), unchecked(17), unchecked(9), unchecked(1), unchecked(58), unchecked( + 50), unchecked(42), unchecked(34), unchecked(26), unchecked( + 18), unchecked(10), unchecked(2), unchecked(59), unchecked( + 51), unchecked(43), unchecked(35), unchecked(62), unchecked( + 54), unchecked(46), unchecked(38), unchecked(30), unchecked( + 22), unchecked(14), unchecked(6), unchecked(61), unchecked( + 53), unchecked(45), unchecked(37), unchecked(29), unchecked( + 21), unchecked(13), unchecked(5), unchecked(60), unchecked( + 52), unchecked(44), unchecked(36), unchecked(28), unchecked( + 20), unchecked(12), unchecked(4), unchecked(27), unchecked( + 19), unchecked(11), unchecked(3) }; + + private static int[] _totrot = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, + 21, 23, 25, 27, 28 }; + + private static byte[] _pc2 = { unchecked(13), unchecked(16) + , unchecked(10), unchecked(23), unchecked(0), unchecked(4), unchecked(2), unchecked(27), unchecked(14), unchecked(5), unchecked(20), unchecked(9), unchecked(22), unchecked(18), unchecked(11), unchecked(3), unchecked(25), unchecked(7), unchecked(15), unchecked(6), unchecked(26), unchecked(19), unchecked(12), unchecked(1), unchecked(40), unchecked(51), unchecked(30), unchecked(36), unchecked(46), unchecked(54), unchecked(29), unchecked(39), unchecked(50), unchecked( + 44), unchecked(32), unchecked(47), unchecked(43), unchecked( + 48), unchecked(38), unchecked(55), unchecked(33), unchecked( + 52), unchecked(45), unchecked(41), unchecked(49), unchecked( + 35), unchecked(28), unchecked(31) }; + + private static int[] _sp1 = { unchecked(0x01010400), unchecked(0x00000000), unchecked(0x00010000), unchecked(0x01010404), unchecked( + 0x01010004), unchecked(0x00010404), unchecked(0x00000004), + unchecked(0x00010000), unchecked(0x00000400), unchecked(0x01010400), unchecked(0x01010404), unchecked(0x00000400), unchecked(0x01000404), unchecked(0x01010004), unchecked(0x01000000), unchecked( + 0x00000004), unchecked(0x00000404), unchecked(0x01000400), + unchecked(0x01000400), unchecked(0x00010400), unchecked(0x00010400), unchecked(0x01010000), unchecked(0x01010000), unchecked(0x01000404), unchecked(0x00010004), unchecked(0x01000004), unchecked( + 0x01000004), unchecked(0x00010004), unchecked(0x00000000), + unchecked(0x00000404), unchecked(0x00010404), unchecked(0x01000000), unchecked(0x00010000), unchecked(0x01010404), unchecked(0x00000004), unchecked(0x01010000), unchecked(0x01010400), unchecked( + 0x01000000), unchecked(0x01000000), unchecked(0x00000400), + unchecked(0x01010004), unchecked(0x00010000), unchecked(0x00010400), unchecked(0x01000004), unchecked(0x00000400), unchecked(0x00000004), unchecked(0x01000404), unchecked(0x00010404), unchecked( + 0x01010404), unchecked(0x00010004), unchecked(0x01010000), + unchecked(0x01000404), unchecked(0x01000004), unchecked(0x00000404), unchecked(0x00010404), unchecked(0x01010400), unchecked(0x00000404), unchecked(0x01000400), unchecked(0x01000400), unchecked( + 0x00000000), unchecked(0x00010004), unchecked(0x00010400), + unchecked(0x00000000), unchecked(0x01010004) }; + + private static int[] _sp2 = { unchecked((int)(0x80108020)), unchecked((int + )(0x80008000)), unchecked(0x00008000), unchecked(0x00108020), unchecked( + 0x00100000), unchecked(0x00000020), unchecked((int)(0x80100020)), + unchecked((int)(0x80008020)), unchecked((int)(0x80000020)), unchecked((int)(0x80108020 + )), unchecked((int)(0x80108000)), unchecked((int)(0x80000000)), unchecked((int)( + 0x80008000)), unchecked(0x00100000), unchecked(0x00000020), unchecked( + (int)(0x80100020)), unchecked(0x00108000), unchecked(0x00100020), + unchecked((int)(0x80008020)), unchecked(0x00000000), unchecked((int)(0x80000000 + )), unchecked(0x00008000), unchecked(0x00108020), unchecked((int)( + 0x80100000)), unchecked(0x00100020), unchecked((int)(0x80000020)), unchecked( + 0x00000000), unchecked(0x00108000), unchecked(0x00008020), + unchecked((int)(0x80108000)), unchecked((int)(0x80100000)), unchecked(0x00008020), unchecked(0x00000000), unchecked(0x00108020), unchecked((int)( + 0x80100020)), unchecked(0x00100000), unchecked((int)(0x80008020)), unchecked( + (int)(0x80100000)), unchecked((int)(0x80108000)), unchecked(0x00008000), + unchecked((int)(0x80100000)), unchecked((int)(0x80008000)), unchecked(0x00000020), unchecked((int)(0x80108020)), unchecked(0x00108020), unchecked(0x00000020), unchecked(0x00008000), unchecked((int)(0x80000000)), unchecked( + 0x00008020), unchecked((int)(0x80108000)), unchecked(0x00100000), + unchecked((int)(0x80000020)), unchecked(0x00100020), unchecked((int)(0x80008020 + )), unchecked((int)(0x80000020)), unchecked(0x00100020), unchecked(0x00108000), unchecked(0x00000000), unchecked((int)(0x80008000)), unchecked( + 0x00008020), unchecked((int)(0x80000000)), unchecked((int)(0x80100020)), + unchecked((int)(0x80108020)), unchecked(0x00108000) }; + + private static int[] _sp3 = { unchecked(0x00000208), unchecked(0x08020200), unchecked(0x00000000), unchecked(0x08020008), unchecked( + 0x08000200), unchecked(0x00000000), unchecked(0x00020208), + unchecked(0x08000200), unchecked(0x00020008), unchecked(0x08000008), unchecked(0x08000008), unchecked(0x00020000), unchecked(0x08020208), unchecked(0x00020008), unchecked(0x08020000), unchecked( + 0x00000208), unchecked(0x08000000), unchecked(0x00000008), + unchecked(0x08020200), unchecked(0x00000200), unchecked(0x00020200), unchecked(0x08020000), unchecked(0x08020008), unchecked(0x00020208), unchecked(0x08000208), unchecked(0x00020200), unchecked( + 0x00020000), unchecked(0x08000208), unchecked(0x00000008), + unchecked(0x08020208), unchecked(0x00000200), unchecked(0x08000000), unchecked(0x08020200), unchecked(0x08000000), unchecked(0x00020008), unchecked(0x00000208), unchecked(0x00020000), unchecked( + 0x08020200), unchecked(0x08000200), unchecked(0x00000000), + unchecked(0x00000200), unchecked(0x00020008), unchecked(0x08020208), unchecked(0x08000200), unchecked(0x08000008), unchecked(0x00000200), unchecked(0x00000000), unchecked(0x08020008), unchecked( + 0x08000208), unchecked(0x00020000), unchecked(0x08000000), + unchecked(0x08020208), unchecked(0x00000008), unchecked(0x00020208), unchecked(0x00020200), unchecked(0x08000008), unchecked(0x08020000), unchecked(0x08000208), unchecked(0x00000208), unchecked( + 0x08020000), unchecked(0x00020208), unchecked(0x00000008), + unchecked(0x08020008), unchecked(0x00020200) }; + + private static int[] _sp4 = { unchecked(0x00802001), unchecked(0x00002081), unchecked(0x00002081), unchecked(0x00000080), unchecked( + 0x00802080), unchecked(0x00800081), unchecked(0x00800001), + unchecked(0x00002001), unchecked(0x00000000), unchecked(0x00802000), unchecked(0x00802000), unchecked(0x00802081), unchecked(0x00000081), unchecked(0x00000000), unchecked(0x00800080), unchecked( + 0x00800001), unchecked(0x00000001), unchecked(0x00002000), + unchecked(0x00800000), unchecked(0x00802001), unchecked(0x00000080), unchecked(0x00800000), unchecked(0x00002001), unchecked(0x00002080), unchecked(0x00800081), unchecked(0x00000001), unchecked( + 0x00002080), unchecked(0x00800080), unchecked(0x00002000), + unchecked(0x00802080), unchecked(0x00802081), unchecked(0x00000081), unchecked(0x00800080), unchecked(0x00800001), unchecked(0x00802000), unchecked(0x00802081), unchecked(0x00000081), unchecked( + 0x00000000), unchecked(0x00000000), unchecked(0x00802000), + unchecked(0x00002080), unchecked(0x00800080), unchecked(0x00800081), unchecked(0x00000001), unchecked(0x00802001), unchecked(0x00002081), unchecked(0x00002081), unchecked(0x00000080), unchecked( + 0x00802081), unchecked(0x00000081), unchecked(0x00000001), + unchecked(0x00002000), unchecked(0x00800001), unchecked(0x00002001), unchecked(0x00802080), unchecked(0x00800081), unchecked(0x00002001), unchecked(0x00002080), unchecked(0x00800000), unchecked( + 0x00802001), unchecked(0x00000080), unchecked(0x00800000), + unchecked(0x00002000), unchecked(0x00802080) }; + + private static int[] _sp5 = { unchecked(0x00000100), unchecked(0x02080100), unchecked(0x02080000), unchecked(0x42000100), unchecked( + 0x00080000), unchecked(0x00000100), unchecked(0x40000000), + unchecked(0x02080000), unchecked(0x40080100), unchecked(0x00080000), unchecked(0x02000100), unchecked(0x40080100), unchecked(0x42000100), unchecked(0x42080000), unchecked(0x00080100), unchecked( + 0x40000000), unchecked(0x02000000), unchecked(0x40080000), + unchecked(0x40080000), unchecked(0x00000000), unchecked(0x40000100), unchecked(0x42080100), unchecked(0x42080100), unchecked(0x02000100), unchecked(0x42080000), unchecked(0x40000100), unchecked( + 0x00000000), unchecked(0x42000000), unchecked(0x02080100), + unchecked(0x02000000), unchecked(0x42000000), unchecked(0x00080100), unchecked(0x00080000), unchecked(0x42000100), unchecked(0x00000100), unchecked(0x02000000), unchecked(0x40000000), unchecked( + 0x02080000), unchecked(0x42000100), unchecked(0x40080100), + unchecked(0x02000100), unchecked(0x40000000), unchecked(0x42080000), unchecked(0x02080100), unchecked(0x40080100), unchecked(0x00000100), unchecked(0x02000000), unchecked(0x42080000), unchecked( + 0x42080100), unchecked(0x00080100), unchecked(0x42000000), + unchecked(0x42080100), unchecked(0x02080000), unchecked(0x00000000), unchecked(0x40080000), unchecked(0x42000000), unchecked(0x00080100), unchecked(0x02000100), unchecked(0x40000100), unchecked( + 0x00080000), unchecked(0x00000000), unchecked(0x40080000), + unchecked(0x02080100), unchecked(0x40000100) }; + + private static int[] _sp6 = { unchecked(0x20000010), unchecked(0x20400000), unchecked(0x00004000), unchecked(0x20404010), unchecked( + 0x20400000), unchecked(0x00000010), unchecked(0x20404010), + unchecked(0x00400000), unchecked(0x20004000), unchecked(0x00404010), unchecked(0x00400000), unchecked(0x20000010), unchecked(0x00400010), unchecked(0x20004000), unchecked(0x20000000), unchecked( + 0x00004010), unchecked(0x00000000), unchecked(0x00400010), + unchecked(0x20004010), unchecked(0x00004000), unchecked(0x00404000), unchecked(0x20004010), unchecked(0x00000010), unchecked(0x20400010), unchecked(0x20400010), unchecked(0x00000000), unchecked( + 0x00404010), unchecked(0x20404000), unchecked(0x00004010), + unchecked(0x00404000), unchecked(0x20404000), unchecked(0x20000000), unchecked(0x20004000), unchecked(0x00000010), unchecked(0x20400010), unchecked(0x00404000), unchecked(0x20404010), unchecked( + 0x00400000), unchecked(0x00004010), unchecked(0x20000010), + unchecked(0x00400000), unchecked(0x20004000), unchecked(0x20000000), unchecked(0x00004010), unchecked(0x20000010), unchecked(0x20404010), unchecked(0x00404000), unchecked(0x20400000), unchecked( + 0x00404010), unchecked(0x20404000), unchecked(0x00000000), + unchecked(0x20400010), unchecked(0x00000010), unchecked(0x00004000), unchecked(0x20400000), unchecked(0x00404010), unchecked(0x00004000), unchecked(0x00400010), unchecked(0x20004010), unchecked( + 0x00000000), unchecked(0x20404000), unchecked(0x20000000), + unchecked(0x00400010), unchecked(0x20004010) }; + + private static int[] _sp7 = { unchecked(0x00200000), unchecked(0x04200002), unchecked(0x04000802), unchecked(0x00000000), unchecked( + 0x00000800), unchecked(0x04000802), unchecked(0x00200802), + unchecked(0x04200800), unchecked(0x04200802), unchecked(0x00200000), unchecked(0x00000000), unchecked(0x04000002), unchecked(0x00000002), unchecked(0x04000000), unchecked(0x04200002), unchecked( + 0x00000802), unchecked(0x04000800), unchecked(0x00200802), + unchecked(0x00200002), unchecked(0x04000800), unchecked(0x04000002), unchecked(0x04200000), unchecked(0x04200800), unchecked(0x00200002), unchecked(0x04200000), unchecked(0x00000800), unchecked( + 0x00000802), unchecked(0x04200802), unchecked(0x00200800), + unchecked(0x00000002), unchecked(0x04000000), unchecked(0x00200800), unchecked(0x04000000), unchecked(0x00200800), unchecked(0x00200000), unchecked(0x04000802), unchecked(0x04000802), unchecked( + 0x04200002), unchecked(0x04200002), unchecked(0x00000002), + unchecked(0x00200002), unchecked(0x04000000), unchecked(0x04000800), unchecked(0x00200000), unchecked(0x04200800), unchecked(0x00000802), unchecked(0x00200802), unchecked(0x04200800), unchecked( + 0x00000802), unchecked(0x04000002), unchecked(0x04200802), + unchecked(0x04200000), unchecked(0x00200800), unchecked(0x00000000), unchecked(0x00000002), unchecked(0x04200802), unchecked(0x00000000), unchecked(0x00200802), unchecked(0x04200000), unchecked( + 0x00000800), unchecked(0x04000002), unchecked(0x04000800), + unchecked(0x00000800), unchecked(0x00200002) }; + + private static int[] _sp8 = { unchecked(0x10001040), unchecked(0x00001000), unchecked(0x00040000), unchecked(0x10041040), unchecked( + 0x10000000), unchecked(0x10001040), unchecked(0x00000040), + unchecked(0x10000000), unchecked(0x00040040), unchecked(0x10040000), unchecked(0x10041040), unchecked(0x00041000), unchecked(0x10041000), unchecked(0x00041040), unchecked(0x00001000), unchecked( + 0x00000040), unchecked(0x10040000), unchecked(0x10000040), + unchecked(0x10001000), unchecked(0x00001040), unchecked(0x00041000), unchecked(0x00040040), unchecked(0x10040040), unchecked(0x10041000), unchecked(0x00001040), unchecked(0x00000000), unchecked( + 0x00000000), unchecked(0x10040040), unchecked(0x10000040), + unchecked(0x10001000), unchecked(0x00041040), unchecked(0x00040000), unchecked(0x00041040), unchecked(0x00040000), unchecked(0x10041000), unchecked(0x00001000), unchecked(0x00000040), unchecked( + 0x10040040), unchecked(0x00001000), unchecked(0x00041040), + unchecked(0x10001000), unchecked(0x00000040), unchecked(0x10000040), unchecked(0x10040000), unchecked(0x10040040), unchecked(0x10000000), unchecked(0x00040000), unchecked(0x10001040), unchecked( + 0x00000000), unchecked(0x10041040), unchecked(0x00040040), + unchecked(0x10000040), unchecked(0x10040000), unchecked(0x10001000), unchecked(0x10001040), unchecked(0x00000000), unchecked(0x10041040), unchecked(0x00041000), unchecked(0x00041000), unchecked( + 0x00001040), unchecked(0x00001040), unchecked(0x00040040), + unchecked(0x10000000), unchecked(0x10041000) }; + + // Tables, permutations, S-boxes, etc. + /// Squash bytes down to ints. + public static void SquashBytesToInts(byte[] inBytes, int inOff, int[] outInts, int + outOff, int intLen) + { + for (int i = 0; i < intLen; ++i) + { + outInts[outOff + i] = ((inBytes[inOff + i * 4] & unchecked(0xff)) << 24) | + ((inBytes[inOff + i * 4 + 1] & unchecked(0xff)) << 16) | ((inBytes[inOff + + i * 4 + 2] & unchecked(0xff)) << 8) | (inBytes[inOff + i * 4 + 3] & unchecked( + 0xff)); + } + } + + /// Spread ints into bytes. + public static void SpreadIntsToBytes(int[] inInts, int inOff, byte[] outBytes, int + outOff, int intLen) + { + for (int i = 0; i < intLen; ++i) + { + outBytes[outOff + i * 4] = unchecked((byte)((int)(((uint)inInts[inOff + i]) >> 24 + ))); + outBytes[outOff + i * 4 + 1] = unchecked((byte)((int)(((uint)inInts[inOff + i]) >> + 16))); + outBytes[outOff + i * 4 + 2] = unchecked((byte)((int)(((uint)inInts[inOff + i]) >> + 8))); + outBytes[outOff + i * 4 + 3] = unchecked((byte)inInts[inOff + i]); + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Encdec.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Encdec.cs new file mode 100644 index 0000000000..7e4d57705b --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Encdec.cs @@ -0,0 +1,401 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Util +{ + public class Encdec + { + public const long MillisecondsBetween1970And1601 = 11644473600000L; + + public const long SecBetweeen1904And1970 = 2082844800L; + + public const int Time1970Sec32Be = 1; + + public const int Time1970Sec32Le = 2; + + public const int Time1904Sec32Be = 3; + + public const int Time1904Sec32Le = 4; + + public const int Time1601Nanos64Le = 5; + + public const int Time1601Nanos64Be = 6; + + public const int Time1970Millis64Be = 7; + + public const int Time1970Millis64Le = 8; + + public static int Enc_uint16be(short s, byte[] dst, int di) + { + dst[di++] = unchecked((byte)((s >> 8) & unchecked(0xFF))); + dst[di] = unchecked((byte)(s & unchecked(0xFF))); + return 2; + } + + public static int Enc_uint32be(int i, byte[] dst, int di) + { + dst[di++] = unchecked((byte)((i >> 24) & unchecked(0xFF))); + dst[di++] = unchecked((byte)((i >> 16) & unchecked(0xFF))); + dst[di++] = unchecked((byte)((i >> 8) & unchecked(0xFF))); + dst[di] = unchecked((byte)(i & unchecked(0xFF))); + return 4; + } + + public static int Enc_uint16le(short s, byte[] dst, int di) + { + dst[di++] = unchecked((byte)(s & unchecked(0xFF))); + dst[di] = unchecked((byte)((s >> 8) & unchecked(0xFF))); + return 2; + } + + public static int Enc_uint32le(int i, byte[] dst, int di) + { + dst[di++] = unchecked((byte)(i & unchecked(0xFF))); + dst[di++] = unchecked((byte)((i >> 8) & unchecked(0xFF))); + dst[di++] = unchecked((byte)((i >> 16) & unchecked(0xFF))); + dst[di] = unchecked((byte)((i >> 24) & unchecked(0xFF))); + return 4; + } + + public static short Dec_uint16be(byte[] src, int si) + { + return (short)(((src[si] & unchecked(0xFF)) << 8) | (src[si + 1] & unchecked( + 0xFF))); + } + + public static int Dec_uint32be(byte[] src, int si) + { + return ((src[si] & unchecked(0xFF)) << 24) | ((src[si + 1] & unchecked(0xFF)) << 16) | ((src[si + 2] & unchecked(0xFF)) << 8) | (src[si + 3] + & unchecked(0xFF)); + } + + public static short Dec_uint16le(byte[] src, int si) + { + return (short)((src[si] & unchecked(0xFF)) | ((src[si + 1] & unchecked(0xFF)) << 8)); + } + + public static int Dec_uint32le(byte[] src, int si) + { + return (src[si] & unchecked(0xFF)) | ((src[si + 1] & unchecked(0xFF + )) << 8) | ((src[si + 2] & unchecked(0xFF)) << 16) | ((src[si + 3] & unchecked( + 0xFF)) << 24); + } + + public static int Enc_uint64be(long l, byte[] dst, int di) + { + Enc_uint32be((int)(l & unchecked(0xFFFFFFFFL)), dst, di + 4); + Enc_uint32be((int)((l >> 32) & unchecked(0xFFFFFFFFL)), dst, di); + return 8; + } + + public static int Enc_uint64le(long l, byte[] dst, int di) + { + Enc_uint32le((int)(l & unchecked(0xFFFFFFFFL)), dst, di); + Enc_uint32le((int)((l >> 32) & unchecked(0xFFFFFFFFL)), dst, di + 4); + return 8; + } + + public static long Dec_uint64be(byte[] src, int si) + { + long l; + l = Dec_uint32be(src, si) & unchecked(0xFFFFFFFFL); + l <<= 32; + l |= Dec_uint32be(src, si + 4) & unchecked(0xFFFFFFFFL); + return l; + } + + public static long Dec_uint64le(byte[] src, int si) + { + long l; + l = Dec_uint32le(src, si + 4) & unchecked(0xFFFFFFFFL); + l <<= 32; + l |= Dec_uint32le(src, si) & unchecked(0xFFFFFFFFL); + return l; + } + + public static int Enc_floatle(float f, byte[] dst, int di) + { + return Enc_uint32le((int)BitConverter.DoubleToInt64Bits(f), dst, di); + } + + public static int Enc_floatbe(float f, byte[] dst, int di) + { + return Enc_uint32be((int)BitConverter.DoubleToInt64Bits(f), dst, di); + } + + public static float Dec_floatle(byte[] src, int si) + { + return (float)BitConverter.Int64BitsToDouble(Dec_uint32le(src, si)); + } + + public static float Dec_floatbe(byte[] src, int si) + { + return (float)BitConverter.Int64BitsToDouble(Dec_uint32be(src, si)); + } + + public static int Enc_doublele(double d, byte[] dst, int di) + { + return Enc_uint64le(BitConverter.DoubleToInt64Bits(d), dst, di); + } + + public static int Enc_doublebe(double d, byte[] dst, int di) + { + return Enc_uint64be(BitConverter.DoubleToInt64Bits(d), dst, di); + } + + public static double Dec_doublele(byte[] src, int si) + { + return BitConverter.Int64BitsToDouble(Dec_uint64le(src, si)); + } + + public static double Dec_doublebe(byte[] src, int si) + { + return BitConverter.Int64BitsToDouble(Dec_uint64be(src, si)); + } + + public static int Enc_time(DateTime date, byte[] dst, int di, int enc) + { + long t; + switch (enc) + { + case Time1970Sec32Be: + { + return Enc_uint32be((int)(date.GetTime() / 1000L), dst, di); + } + + case Time1970Sec32Le: + { + return Enc_uint32le((int)(date.GetTime() / 1000L), dst, di); + } + + case Time1904Sec32Be: + { + return Enc_uint32be((int)((date.GetTime() / 1000L + SecBetweeen1904And1970) & + unchecked((int)(0xFFFFFFFF))), dst, di); + } + + case Time1904Sec32Le: + { + return Enc_uint32le((int)((date.GetTime() / 1000L + SecBetweeen1904And1970) & + unchecked((int)(0xFFFFFFFF))), dst, di); + } + + case Time1601Nanos64Be: + { + t = (date.GetTime() + MillisecondsBetween1970And1601) * 10000L; + return Enc_uint64be(t, dst, di); + } + + case Time1601Nanos64Le: + { + t = (date.GetTime() + MillisecondsBetween1970And1601) * 10000L; + return Enc_uint64le(t, dst, di); + } + + case Time1970Millis64Be: + { + return Enc_uint64be(date.GetTime(), dst, di); + } + + case Time1970Millis64Le: + { + return Enc_uint64le(date.GetTime(), dst, di); + } + + default: + { + throw new ArgumentException("Unsupported time encoding"); + } + } + } + + public static DateTime Dec_time(byte[] src, int si, int enc) + { + long t; + switch (enc) + { + case Time1970Sec32Be: + { + return Sharpen.Extensions.CreateDate(Dec_uint32be(src, si) * 1000L); + } + + case Time1970Sec32Le: + { + return Sharpen.Extensions.CreateDate(Dec_uint32le(src, si) * 1000L); + } + + case Time1904Sec32Be: + { + return Sharpen.Extensions.CreateDate(((Dec_uint32be(src, si) & unchecked(0xFFFFFFFFL)) - SecBetweeen1904And1970) * 1000L); + } + + case Time1904Sec32Le: + { + return Sharpen.Extensions.CreateDate(((Dec_uint32le(src, si) & unchecked(0xFFFFFFFFL)) - SecBetweeen1904And1970) * 1000L); + } + + case Time1601Nanos64Be: + { + t = Dec_uint64be(src, si); + return Sharpen.Extensions.CreateDate(t / 10000L - MillisecondsBetween1970And1601 + ); + } + + case Time1601Nanos64Le: + { + t = Dec_uint64le(src, si); + return Sharpen.Extensions.CreateDate(t / 10000L - MillisecondsBetween1970And1601 + ); + } + + case Time1970Millis64Be: + { + return Sharpen.Extensions.CreateDate(Dec_uint64be(src, si)); + } + + case Time1970Millis64Le: + { + return Sharpen.Extensions.CreateDate(Dec_uint64le(src, si)); + } + + default: + { + throw new ArgumentException("Unsupported time encoding"); + } + } + } + + /// + public static int Enc_utf8(string str, byte[] dst, int di, int dlim) + { + int start = di; + int ch; + int strlen = str.Length; + for (int i = 0; di < dlim && i < strlen; i++) + { + ch = str[i]; + if ((ch >= unchecked(0x0001)) && (ch <= unchecked(0x007F))) + { + dst[di++] = unchecked((byte)ch); + } + else + { + if (ch > unchecked(0x07FF)) + { + if ((dlim - di) < 3) + { + break; + } + dst[di++] = unchecked((byte)(unchecked(0xE0) | ((ch >> 12) & unchecked(0x0F)))); + dst[di++] = unchecked((byte)(unchecked(0x80) | ((ch >> 6) & unchecked(0x3F)))); + dst[di++] = unchecked((byte)(unchecked(0x80) | ((ch >> 0) & unchecked(0x3F)))); + } + else + { + if ((dlim - di) < 2) + { + break; + } + dst[di++] = unchecked((byte)(unchecked(0xC0) | ((ch >> 6) & unchecked(0x1F)))); + dst[di++] = unchecked((byte)(unchecked(0x80) | ((ch >> 0) & unchecked(0x3F)))); + } + } + } + return di - start; + } + + /// + public static string Dec_utf8(byte[] src, int si, int slim) + { + char[] uni = new char[slim - si]; + int ui; + int ch; + for (ui = 0; si < slim && (ch = src[si++] & unchecked(0xFF)) != 0; ui++) + { + if (ch < unchecked(0x80)) + { + uni[ui] = (char)ch; + } + else + { + if ((ch & unchecked(0xE0)) == unchecked(0xC0)) + { + if ((slim - si) < 2) + { + break; + } + uni[ui] = (char)((ch & unchecked(0x1F)) << 6); + ch = src[si++] & unchecked(0xFF); + uni[ui] |= (char)((char)ch & unchecked(0x3F)); + if ((ch & unchecked(0xC0)) != unchecked(0x80) || uni[ui] < unchecked( + 0x80)) + { + throw new IOException("Invalid UTF-8 sequence"); + } + } + else + { + if ((ch & unchecked(0xF0)) == unchecked(0xE0)) + { + if ((slim - si) < 3) + { + break; + } + uni[ui] = (char)((ch & unchecked(0x0F)) << 12); + ch = src[si++] & unchecked(0xFF); + if ((ch & unchecked(0xC0)) != unchecked(0x80)) + { + throw new IOException("Invalid UTF-8 sequence"); + } + uni[ui] |= (char)((char)(ch & unchecked(0x3F)) << 6); + ch = src[si++] & unchecked(0xFF); + uni[ui] |= (char)((char)ch & unchecked(0x3F)); + if ((ch & unchecked(0xC0)) != unchecked(0x80) || uni[ui] < unchecked( + 0x800)) + { + throw new IOException("Invalid UTF-8 sequence"); + } + } + else + { + throw new IOException("Unsupported UTF-8 sequence"); + } + } + } + } + return new string(uni, 0, ui); + } + + /// + public static string Dec_ucs2le(byte[] src, int si, int slim, char[] buf) + { + int bi; + for (bi = 0; (si + 1) < slim; bi++, si += 2) + { + buf[bi] = (char)Dec_uint16le(src, si); + if (buf[bi] == '\0') + { + break; + } + } + return new string(buf, 0, bi); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/HMACT64.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/HMACT64.cs new file mode 100644 index 0000000000..9ab31d61b8 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/HMACT64.cs @@ -0,0 +1,146 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Sharpen; + +namespace SharpCifs.Util +{ + /// This is an implementation of the HMACT64 keyed hashing algorithm. + /// + /// This is an implementation of the HMACT64 keyed hashing algorithm. + /// HMACT64 is defined by Luke Leighton as a modified HMAC-MD5 (RFC 2104) + /// in which the key is truncated at 64 bytes (rather than being hashed + /// via MD5). + /// + public class Hmact64 : MessageDigest + { + private const int BlockLength = 64; + + private const byte Ipad = unchecked(unchecked(0x36)); + + private const byte Opad = unchecked(unchecked(0x5c)); + + private MessageDigest _md5; + + private byte[] _ipad = new byte[BlockLength]; + + private byte[] _opad = new byte[BlockLength]; + + /// Creates an HMACT64 instance which uses the given secret key material. + /// Creates an HMACT64 instance which uses the given secret key material. + /// The key material to use in hashing. + public Hmact64(byte[] key) + { + int length = Math.Min(key.Length, BlockLength); + for (int i = 0; i < length; i++) + { + _ipad[i] = unchecked((byte)(key[i] ^ Ipad)); + _opad[i] = unchecked((byte)(key[i] ^ Opad)); + } + for (int i1 = length; i1 < BlockLength; i1++) + { + _ipad[i1] = Ipad; + _opad[i1] = Opad; + } + try + { + _md5 = GetInstance("MD5"); + } + catch (Exception ex) + { + throw new InvalidOperationException(ex.Message); + } + EngineReset(); + } + + + protected byte[] EngineDigest() + { + byte[] digest = _md5.Digest(); + _md5.Update(_opad); + return _md5.Digest(digest); + } + + protected int EngineDigest(byte[] buf, int offset, int len) + { + byte[] digest = _md5.Digest(); + _md5.Update(_opad); + _md5.Update(digest); + try + { + _md5.Digest(buf, offset, len); + + return len; + } + catch (Exception) + { + throw new InvalidOperationException(); + } + } + + protected int EngineGetDigestLength() + { + return _md5.GetDigestLength(); + } + + protected void EngineReset() + { + _md5.Reset(); + _md5.Update(_ipad); + } + + protected void EngineUpdate(byte b) + { + _md5.Update(b); + } + + protected void EngineUpdate(byte[] input, int offset, int len) + { + _md5.Update(input, offset, len); + } + + public override byte[] Digest() + { + return EngineDigest(); + } + + public override int GetDigestLength() + { + return EngineGetDigestLength(); + } + + public override void Reset() + { + EngineReset(); + } + + public override void Update(byte[] b) + { + EngineUpdate(b, 0, b.Length); + } + + public override void Update(byte b) + { + EngineUpdate(b); + } + + public override void Update(byte[] b, int offset, int len) + { + EngineUpdate(b, offset, len); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Hexdump.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Hexdump.cs new file mode 100644 index 0000000000..7e53f76e3e --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Hexdump.cs @@ -0,0 +1,191 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; + +namespace SharpCifs.Util +{ + public class Hexdump + { + private static readonly string Nl = @"\r\n"; //Runtime.GetProperty("line.separator"); + + private static readonly int NlLength = Nl.Length; + + private static readonly char[] SpaceChars = { ' ', ' ', ' ', ' ', ' ' + , ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' + , ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' + , ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }; + + public static readonly char[] HexDigits = { '0', '1', '2', '3', '4', + '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + + private static bool IsIsoControl(char c) + { + return (c >= '\u0000' && c <= '\u001F') || (c >= '\u007F' && c <= '\u009F'); + } + + /// + /// Generate "hexdump" output of the buffer at src like the following: + ///

+		/// 00000: 04 d2 29 00 00 01 00 00 00 00 00 01 20 45 47 46  |..).........
+		/// 
+ /// + /// Generate "hexdump" output of the buffer at src like the following: + ///

+		/// 00000: 04 d2 29 00 00 01 00 00 00 00 00 01 20 45 47 46  |..)......... EGF|
+		/// 00010: 43 45 46 45 45 43 41 43 41 43 41 43 41 43 41 43  |CEFEECACACACACAC|
+		/// 00020: 41 43 41 43 41 43 41 43 41 43 41 41 44 00 00 20  |ACACACACACAAD.. |
+		/// 00030: 00 01 c0 0c 00 20 00 01 00 00 00 00 00 06 20 00  |..... ........ .|
+		/// 00040: ac 22 22 e1                                      |."".            |
+		/// 
+ ///
+ public static void ToHexdump(TextWriter ps, byte[] src, int srcIndex, int length) + { + if (length == 0) + { + return; + } + int s = length % 16; + int r = (s == 0) ? length / 16 : length / 16 + 1; + char[] c = new char[r * (74 + NlLength)]; + char[] d = new char[16]; + int i; + int si = 0; + int ci = 0; + do + { + ToHexChars(si, c, ci, 5); + ci += 5; + c[ci++] = ':'; + do + { + if (si == length) + { + int n = 16 - s; + Array.Copy(SpaceChars, 0, c, ci, n * 3); + ci += n * 3; + Array.Copy(SpaceChars, 0, d, s, n); + break; + } + c[ci++] = ' '; + i = src[srcIndex + si] & 0xFF; + ToHexChars(i, c, ci, 2); + ci += 2; + if (i < 0 || IsIsoControl((char)i)) + { + d[si % 16] = '.'; + } + else + { + d[si % 16] = (char)i; + } + } + while ((++si % 16) != 0); + c[ci++] = ' '; + c[ci++] = ' '; + c[ci++] = '|'; + Array.Copy(d, 0, c, ci, 16); + ci += 16; + c[ci++] = '|'; + //Sharpen.Runtime.GetCharsForString(NL, 0, NL_LENGTH, c, ci); + c = Nl.ToCharArray(0, NlLength); + ci += NlLength; + } + while (si < length); + ps.WriteLine(c); + } + + /// + /// This is an alternative to the java.lang.Integer.toHexString + /// method. + /// + /// + /// This is an alternative to the java.lang.Integer.toHexString + /// method. It is an efficient relative that also will pad the left side so + /// that the result is size digits. + /// + public static string ToHexString(int val, int size) + { + char[] c = new char[size]; + ToHexChars(val, c, 0, size); + return new string(c); + } + + public static string ToHexString(long val, int size) + { + char[] c = new char[size]; + ToHexChars(val, c, 0, size); + return new string(c); + } + + public static string ToHexString(byte[] src, int srcIndex, int size) + { + char[] c = new char[size]; + size = (size % 2 == 0) ? size / 2 : size / 2 + 1; + for (int i = 0, j = 0; i < size; i++) + { + c[j++] = HexDigits[(src[i] >> 4) & 0x0F]; + if (j == c.Length) + { + break; + } + c[j++] = HexDigits[src[i] & 0x0F]; + } + return new string(c); + } + + /// + /// This is the same as + /// ToHexString(int, int) + /// but provides a more practical form when trying to avoid + /// string + /// concatenation and + /// System.Text.StringBuilder + /// . + /// + public static void ToHexChars(int val, char[] dst, int dstIndex, int size) + { + while (size > 0) + { + int i = dstIndex + size - 1; + if (i < dst.Length) + { + dst[i] = HexDigits[val & 0x000F]; + } + if (val != 0) + { + val = (int)(((uint)val) >> 4); + } + size--; + } + } + + public static void ToHexChars(long val, char[] dst, int dstIndex, int size) + { + while (size > 0) + { + dst[dstIndex + size - 1] = HexDigits[(int)(val & 0x000FL)]; + if (val != 0) + { + val = (long)(((ulong)val) >> 4); + } + size--; + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/LogStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/LogStream.cs new file mode 100644 index 0000000000..9dd130b500 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/LogStream.cs @@ -0,0 +1,78 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.Diagnostics; +using System.IO; +using System.Text; +//using Windows.Storage; +//using Windows.UI.Notifications; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Util +{ + /// + /// 0 - nothing + /// 1 - critical [default] + /// 2 - basic info can be logged under load + /// 3 - almost everything + /// N - debugging + /// + public class LogStream: PrintWriter +{ + private static LogStream _inst = null; + + public int Level = 1; + + public void SetLevel(int level) + { + this.Level = level; + } + + public LogStream(TextWriter other) : base(other) + { + + } + + /// + /// This must be called before getInstance is called or + /// it will have no effect. + /// + /// + /// This must be called before getInstance is called or + /// it will have no effect. + /// + public static void SetInstance(TextWriter other) + { + //inst = new Jcifs.Util.LogStream(); + _inst = new LogStream(other); + } + + public static LogStream GetInstance() + { + if (_inst == null) + { + SetInstance(Console.Error); + } + return _inst; + } + + public override Encoding Encoding + { + get { throw new NotImplementedException(); } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/MD4.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/MD4.cs new file mode 100644 index 0000000000..99eb6ade66 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/MD4.cs @@ -0,0 +1,347 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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.Sharpen; + +namespace SharpCifs.Util +{ + /// Implements the MD4 message digest algorithm in Java. + /// + /// Implements the MD4 message digest algorithm in Java. + ///

+ /// References: + ///

    + ///
  1. Ronald L. Rivest, + /// " + /// The MD4 Message-Digest Algorithm", + /// IETF RFC-1320 (informational). + ///
+ ///

$Revision: 1.2 $ + /// + /// Raif S. Naffah + public class Md4 : MessageDigest + { + ///

The size in bytes of the input block to the tranformation algorithm. + /// The size in bytes of the input block to the tranformation algorithm. + private const int BlockLength = 64; + + /// 4 32-bit words (interim result) + private int[] _context = new int[4]; + + /// Number of bytes processed so far mod. + /// Number of bytes processed so far mod. 2 power of 64. + private long _count; + + /// 512 bits input buffer = 16 x 32-bit words holds until reaches 512 bits. + /// 512 bits input buffer = 16 x 32-bit words holds until reaches 512 bits. + private byte[] _buffer = new byte[BlockLength]; + + /// 512 bits work buffer = 16 x 32-bit words + private int[] _x = new int[16]; + + public Md4() + { + // This file is currently unlocked (change this line if you lock the file) + // + // $Log: MD4.java,v $ + // Revision 1.2 1998/01/05 03:41:19 iang + // Added references only. + // + // Revision 1.1.1.1 1997/11/03 22:36:56 hopwood + // + Imported to CVS (tagged as 'start'). + // + // Revision 0.1.0.0 1997/07/14 R. Naffah + // + original version + // + // $Endlog$ + // MD4 specific object variables + //........................................................................... + // = 512 / 8; + // Constructors + //........................................................................... + EngineReset(); + } + + /// This constructor is here to implement cloneability of this class. + /// This constructor is here to implement cloneability of this class. + private Md4(Md4 md) : this() + { + _context = (int[])md._context.Clone(); + _buffer = (byte[])md._buffer.Clone(); + _count = md._count; + } + + // Cloneable method implementation + //........................................................................... + /// Returns a copy of this MD object. + /// Returns a copy of this MD object. + public object Clone() + { + return new Md4(this); + } + + // JCE methods + //........................................................................... + /// + /// Resets this object disregarding any temporary data present at the + /// time of the invocation of this call. + /// + /// + /// Resets this object disregarding any temporary data present at the + /// time of the invocation of this call. + /// + protected void EngineReset() + { + // initial values of MD4 i.e. A, B, C, D + // as per rfc-1320; they are low-order byte first + _context[0] = unchecked(0x67452301); + _context[1] = unchecked((int)(0xEFCDAB89)); + _context[2] = unchecked((int)(0x98BADCFE)); + _context[3] = unchecked(0x10325476); + _count = 0L; + for (int i = 0; i < BlockLength; i++) + { + _buffer[i] = 0; + } + } + + /// Continues an MD4 message digest using the input byte. + /// Continues an MD4 message digest using the input byte. + protected void EngineUpdate(byte b) + { + // compute number of bytes still unhashed; ie. present in buffer + int i = (int)(_count % BlockLength); + _count++; + // update number of bytes + _buffer[i] = b; + if (i == BlockLength - 1) + { + Transform(_buffer, 0); + } + } + + /// MD4 block update operation. + /// + /// MD4 block update operation. + ///

+ /// Continues an MD4 message digest operation, by filling the buffer, + /// transform(ing) data in 512-bit message block(s), updating the variables + /// context and count, and leaving (buffering) the remaining bytes in buffer + /// for the next update or finish. + /// + /// input block + /// start of meaningful bytes in input + /// count of bytes in input block to consider + protected void EngineUpdate(byte[] input, int offset, int len) + { + // make sure we don't exceed input's allocated size/length + if (offset < 0 || len < 0 || (long)offset + len > input.Length) + { + throw new IndexOutOfRangeException(); + } + // compute number of bytes still unhashed; ie. present in buffer + int bufferNdx = (int)(_count % BlockLength); + _count += len; + // update number of bytes + int partLen = BlockLength - bufferNdx; + int i = 0; + if (len >= partLen) + { + Array.Copy(input, offset, _buffer, bufferNdx, partLen); + Transform(_buffer, 0); + for (i = partLen; i + BlockLength - 1 < len; i += BlockLength) + { + Transform(input, offset + i); + } + bufferNdx = 0; + } + // buffer remaining input + if (i < len) + { + Array.Copy(input, offset + i, _buffer, bufferNdx, len - i); + } + } + + ///

+ /// Completes the hash computation by performing final operations such + /// as padding. + /// + /// + /// Completes the hash computation by performing final operations such + /// as padding. At the return of this engineDigest, the MD engine is + /// reset. + /// + /// the array of bytes for the resulting hash value. + protected byte[] EngineDigest() + { + // pad output to 56 mod 64; as RFC1320 puts it: congruent to 448 mod 512 + int bufferNdx = (int)(_count % BlockLength); + int padLen = (bufferNdx < 56) ? (56 - bufferNdx) : (120 - bufferNdx); + // padding is alwas binary 1 followed by binary 0s + byte[] tail = new byte[padLen + 8]; + tail[0] = unchecked(unchecked(0x80)); + // append length before final transform: + // save number of bits, casting the long to an array of 8 bytes + // save low-order byte first. + for (int i = 0; i < 8; i++) + { + tail[padLen + i] = unchecked((byte)((long)(((ulong)(_count * 8)) >> (8 * i)))); + } + EngineUpdate(tail, 0, tail.Length); + byte[] result = new byte[16]; + // cast this MD4's context (array of 4 ints) into an array of 16 bytes. + for (int i1 = 0; i1 < 4; i1++) + { + for (int j = 0; j < 4; j++) + { + result[i1 * 4 + j] = unchecked((byte)((int)(((uint)_context[i1]) >> (8 * j)))); + } + } + // reset the engine + EngineReset(); + return result; + } + + // own methods + //........................................................................... + /// MD4 basic transformation. + /// + /// MD4 basic transformation. + ///

+ /// Transforms context based on 512 bits from input block starting + /// from the offset'th byte. + /// + /// input sub-array. + /// starting position of sub-array. + private void Transform(byte[] block, int offset) + { + // encodes 64 bytes from input block into an array of 16 32-bit + // entities. Use A as a temp var. + for (int i = 0; i < 16; i++) + { + _x[i] = (block[offset++] & unchecked(0xFF)) | (block[offset++] & unchecked( + 0xFF)) << 8 | (block[offset++] & unchecked(0xFF)) << 16 | (block[offset + ++] & unchecked(0xFF)) << 24; + } + int a = _context[0]; + int b = _context[1]; + int c = _context[2]; + int d = _context[3]; + a = Ff(a, b, c, d, _x[0], 3); + d = Ff(d, a, b, c, _x[1], 7); + c = Ff(c, d, a, b, _x[2], 11); + b = Ff(b, c, d, a, _x[3], 19); + a = Ff(a, b, c, d, _x[4], 3); + d = Ff(d, a, b, c, _x[5], 7); + c = Ff(c, d, a, b, _x[6], 11); + b = Ff(b, c, d, a, _x[7], 19); + a = Ff(a, b, c, d, _x[8], 3); + d = Ff(d, a, b, c, _x[9], 7); + c = Ff(c, d, a, b, _x[10], 11); + b = Ff(b, c, d, a, _x[11], 19); + a = Ff(a, b, c, d, _x[12], 3); + d = Ff(d, a, b, c, _x[13], 7); + c = Ff(c, d, a, b, _x[14], 11); + b = Ff(b, c, d, a, _x[15], 19); + a = Gg(a, b, c, d, _x[0], 3); + d = Gg(d, a, b, c, _x[4], 5); + c = Gg(c, d, a, b, _x[8], 9); + b = Gg(b, c, d, a, _x[12], 13); + a = Gg(a, b, c, d, _x[1], 3); + d = Gg(d, a, b, c, _x[5], 5); + c = Gg(c, d, a, b, _x[9], 9); + b = Gg(b, c, d, a, _x[13], 13); + a = Gg(a, b, c, d, _x[2], 3); + d = Gg(d, a, b, c, _x[6], 5); + c = Gg(c, d, a, b, _x[10], 9); + b = Gg(b, c, d, a, _x[14], 13); + a = Gg(a, b, c, d, _x[3], 3); + d = Gg(d, a, b, c, _x[7], 5); + c = Gg(c, d, a, b, _x[11], 9); + b = Gg(b, c, d, a, _x[15], 13); + a = Hh(a, b, c, d, _x[0], 3); + d = Hh(d, a, b, c, _x[8], 9); + c = Hh(c, d, a, b, _x[4], 11); + b = Hh(b, c, d, a, _x[12], 15); + a = Hh(a, b, c, d, _x[2], 3); + d = Hh(d, a, b, c, _x[10], 9); + c = Hh(c, d, a, b, _x[6], 11); + b = Hh(b, c, d, a, _x[14], 15); + a = Hh(a, b, c, d, _x[1], 3); + d = Hh(d, a, b, c, _x[9], 9); + c = Hh(c, d, a, b, _x[5], 11); + b = Hh(b, c, d, a, _x[13], 15); + a = Hh(a, b, c, d, _x[3], 3); + d = Hh(d, a, b, c, _x[11], 9); + c = Hh(c, d, a, b, _x[7], 11); + b = Hh(b, c, d, a, _x[15], 15); + _context[0] += a; + _context[1] += b; + _context[2] += c; + _context[3] += d; + } + + // The basic MD4 atomic functions. + private int Ff(int a, int b, int c, int d, int x, int s) + { + int t = a + ((b & c) | (~b & d)) + x; + return t << s | (int)(((uint)t) >> (32 - s)); + } + + private int Gg(int a, int b, int c, int d, int x, int s) + { + int t = a + ((b & (c | d)) | (c & d)) + x + unchecked(0x5A827999); + return t << s | (int)(((uint)t) >> (32 - s)); + } + + private int Hh(int a, int b, int c, int d, int x, int s) + { + int t = a + (b ^ c ^ d) + x + unchecked(0x6ED9EBA1); + return t << s | (int)(((uint)t) >> (32 - s)); + } + + public override byte[] Digest() + { + return EngineDigest(); + } + + public override int GetDigestLength() + { + return EngineDigest().Length; + } + + public override void Reset() + { + EngineReset(); + } + + public override void Update(byte[] b) + { + EngineUpdate(b, 0, b.Length); + } + + public override void Update(byte b) + { + EngineUpdate(b); + } + + public override void Update(byte[] b, int offset, int len) + { + EngineUpdate(b, offset, len); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/RC4.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/RC4.cs new file mode 100644 index 0000000000..b17e076e72 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/RC4.cs @@ -0,0 +1,68 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Util +{ + public class Rc4 + { + internal byte[] S; + + internal int I; + + internal int J; + + public Rc4() + { + } + + public Rc4(byte[] key) + { + Init(key, 0, key.Length); + } + + public virtual void Init(byte[] key, int ki, int klen) + { + S = new byte[256]; + for (I = 0; I < 256; I++) + { + S[I] = unchecked((byte)I); + } + for (I = J = 0; I < 256; I++) + { + J = (J + key[ki + I % klen] + S[I]) & unchecked(0xff); + byte t = S[I]; + S[I] = S[J]; + S[J] = t; + } + I = J = 0; + } + + public virtual void Update(byte[] src, int soff, int slen, byte[] dst, int doff) + { + int slim; + slim = soff + slen; + while (soff < slim) + { + I = (I + 1) & unchecked(0xff); + J = (J + S[I]) & unchecked(0xff); + byte t = S[I]; + S[I] = S[J]; + S[J] = t; + dst[doff++] = unchecked((byte)(src[soff++] ^ S[(S[I] + S[J]) & unchecked(0xff)])); + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/AbstractMap.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/AbstractMap.cs new file mode 100644 index 0000000000..2868a840ad --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/AbstractMap.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace SharpCifs.Util.Sharpen +{ + public abstract class AbstractMap : IDictionary + { + public virtual void Clear () + { + EntrySet ().Clear (); + } + + public virtual bool ContainsKey (object name) + { + return EntrySet ().Any (p => p.Key.Equals ((T)name)); + } + + public abstract ICollection> EntrySet (); + + public virtual TU Get (object key) + { + return EntrySet ().Where (p => p.Key.Equals (key)).Select (p => p.Value).FirstOrDefault (); + } + + protected virtual IEnumerator> InternalGetEnumerator () + { + return EntrySet ().GetEnumerator (); + } + + public virtual bool IsEmpty () + { + return !EntrySet ().Any (); + } + + public virtual TU Put (T key, TU value) + { + throw new NotSupportedException (); + } + + public virtual TU Remove (object key) + { + Iterator iterator = EntrySet () as Iterator; + if (iterator == null) { + throw new NotSupportedException (); + } + while (iterator.HasNext ()) { + TU local = iterator.Next (); + if (local.Equals ((T)key)) { + iterator.Remove (); + return local; + } + } + return default(TU); + } + + void ICollection>.Add (KeyValuePair item) + { + Put (item.Key, item.Value); + } + + bool ICollection>.Contains (KeyValuePair item) + { + throw new NotImplementedException (); + } + + void ICollection>.CopyTo (KeyValuePair[] array, int arrayIndex) + { + EntrySet ().CopyTo (array, arrayIndex); + } + + bool ICollection>.Remove (KeyValuePair item) + { + Remove (item.Key); + return true; + } + + void IDictionary.Add (T key, TU value) + { + Put (key, value); + } + + bool IDictionary.ContainsKey (T key) + { + return ContainsKey (key); + } + + bool IDictionary.Remove (T key) + { + if (ContainsKey (key)) { + Remove (key); + return true; + } + return false; + } + + bool IDictionary.TryGetValue (T key, out TU value) + { + if (ContainsKey (key)) { + value = Get (key); + return true; + } + value = default(TU); + return false; + } + + IEnumerator> IEnumerable>.GetEnumerator () + { + return InternalGetEnumerator (); + } + + IEnumerator IEnumerable.GetEnumerator () + { + return InternalGetEnumerator (); + } + + public virtual int Count { + get { return EntrySet ().Count; } + } + + public TU this[T key] { + get { return Get (key); } + set { Put (key, value); } + } + + public virtual IEnumerable Keys { + get { return EntrySet ().Select (p => p.Key); } + } + + int ICollection>.Count { + get { return Count; } + } + + bool ICollection>.IsReadOnly { + get { return false; } + } + + ICollection IDictionary.Keys { + get { return Keys.ToList (); } + } + + ICollection IDictionary.Values { + get { return Values.ToList (); } + } + + public virtual IEnumerable Values { + get { return EntrySet ().Select (p => p.Value); } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Arrays.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Arrays.cs new file mode 100644 index 0000000000..b3a0a85fa8 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Arrays.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SharpCifs.Util.Sharpen +{ + public class Arrays + { + public static List AsList (params T[] array) + { + return array.ToList (); + } + + public static bool Equals (T[] a1, T[] a2) + { + if (a1.Length != a2.Length) { + return false; + } + return !a1.Where((t, i) => !t.Equals(a2[i])).Any(); + } + + public static void Fill (T[] array, T val) + { + Fill (array, 0, array.Length, val); + } + + public static void Fill (T[] array, int start, int end, T val) + { + for (int i = start; i < end; i++) { + array[i] = val; + } + } + + public static void Sort (string[] array) + { + Array.Sort (array, (s1,s2) => string.CompareOrdinal (s1,s2)); + } + + public static void Sort (T[] array) + { + Array.Sort (array); + } + + public static void Sort (T[] array, IComparer c) + { + Array.Sort (array, c); + } + + public static void Sort (T[] array, int start, int count) + { + Array.Sort (array, start, count); + } + + public static void Sort (T[] array, int start, int count, IComparer c) + { + Array.Sort (array, start, count, c); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/BufferedReader.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/BufferedReader.cs new file mode 100644 index 0000000000..b3824b0d2c --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/BufferedReader.cs @@ -0,0 +1,11 @@ +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + public class BufferedReader : StreamReader + { + public BufferedReader (InputStreamReader r) : base(r.BaseStream) + { + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/BufferedWriter.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/BufferedWriter.cs new file mode 100644 index 0000000000..64a45915ad --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/BufferedWriter.cs @@ -0,0 +1,58 @@ +// +// BufferedWriter.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + public class BufferedWriter + { + StreamWriter _writer; + + public BufferedWriter (StreamWriter w) + { + _writer = w; + } + + public void Write (string s) + { + _writer.Write (s); + } + + public void NewLine () + { + _writer.WriteLine (); + } + + public void Close () + { + //Stream.`Close` method deleted + //_writer.Close (); + _writer.Dispose(); + } + } +} + diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/CharBuffer.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/CharBuffer.cs new file mode 100644 index 0000000000..76ca2dc956 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/CharBuffer.cs @@ -0,0 +1,19 @@ +namespace SharpCifs.Util.Sharpen +{ + internal class CharBuffer : CharSequence + { + internal string Wrapped; + + public override string ToString () + { + return Wrapped; + } + + public static CharBuffer Wrap (string str) + { + CharBuffer buffer = new CharBuffer (); + buffer.Wrapped = str; + return buffer; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/CharSequence.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/CharSequence.cs new file mode 100644 index 0000000000..fa2acf7bdc --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/CharSequence.cs @@ -0,0 +1,32 @@ +using System.Text; + +namespace SharpCifs.Util.Sharpen +{ + public class CharSequence + { + public static implicit operator CharSequence (string str) + { + return new StringCharSequence (str); + } + + public static implicit operator CharSequence (StringBuilder str) + { + return new StringCharSequence (str.ToString ()); + } + } + + class StringCharSequence: CharSequence + { + string _str; + + public StringCharSequence (string str) + { + this._str = str; + } + + public override string ToString () + { + return _str; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Collections.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Collections.cs new file mode 100644 index 0000000000..4432e62fb0 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Collections.cs @@ -0,0 +1,146 @@ +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace SharpCifs.Util.Sharpen +{ + internal static class Collections + { + static readonly IList Empty = new T [0]; + public static IList EmptySet { + get { return Empty; } + } + + } + + public static class Collections + { + public static bool AddAll (ICollection list, IEnumerable toAdd) + { + foreach (T t in toAdd) + list.Add (t); + return true; + } + + public static TV Remove (IDictionary map, TK toRemove) where TK : class + { + TV local; + if (map.TryGetValue (toRemove, out local)) { + map.Remove (toRemove); + return local; + } + return default(TV); + } + + + public static T[] ToArray (ICollection list) + { + T[] array = new T[list.Count]; + list.CopyTo (array, 0); + return array; + } + + public static T[] ToArray(List list) + { + T[] array = new T[list.Count]; + for(int c = 0; c < list.Count; c++) + { + array[c] = (T)list[c]; + } + + return array; + } + + + public static TU[] ToArray (ICollection list, TU[] res) where T:TU + { + if (res.Length < list.Count) + res = new TU [list.Count]; + + int n = 0; + foreach (T t in list) + res [n++] = t; + + if (res.Length > list.Count) + res [list.Count] = default (T); + return res; + } + + public static IDictionary EmptyMap () + { + return new Dictionary (); + } + + public static IList EmptyList () + { + return Collections.EmptySet; + } + + public static ICollection EmptySet () + { + return Collections.EmptySet; + } + + public static IList NCopies (int n, T elem) + { + List list = new List (n); + while (n-- > 0) { + list.Add (elem); + } + return list; + } + + public static void Reverse (IList list) + { + int end = list.Count - 1; + int index = 0; + while (index < end) { + T tmp = list [index]; + list [index] = list [end]; + list [end] = tmp; + ++index; + --end; + } + } + + public static ICollection Singleton (T item) + { + List list = new List (1); + list.Add (item); + return list; + } + + public static IList SingletonList (T item) + { + List list = new List (1); + list.Add (item); + return list; + } + + public static IList SynchronizedList (IList list) + { + return new SynchronizedList (list); + } + + public static ICollection UnmodifiableCollection (ICollection list) + { + return list; + } + + public static IList UnmodifiableList (IList list) + { + return new ReadOnlyCollection (list); + } + + public static ICollection UnmodifiableSet (ICollection list) + { + return list; + } + + public static IDictionary UnmodifiableMap (IDictionary dict) + { + return dict; + } + + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ConcurrentHashMap.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ConcurrentHashMap.cs new file mode 100644 index 0000000000..7f464ad362 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ConcurrentHashMap.cs @@ -0,0 +1,122 @@ +using System.Collections.Generic; + +namespace SharpCifs.Util.Sharpen +{ + internal class ConcurrentHashMap : AbstractMap, IConcurrentMap + { + private Dictionary _table; + + public ConcurrentHashMap () + { + _table = new Dictionary (); + } + + public ConcurrentHashMap (int initialCapacity, float loadFactor, int concurrencyLevel) + { + _table = new Dictionary (initialCapacity); + } + + public override void Clear () + { + lock (_table) { + _table = new Dictionary (); + } + } + + public override bool ContainsKey (object name) + { + return _table.ContainsKey ((T)name); + } + + public override ICollection> EntrySet () + { + return this; + } + + public override TU Get (object key) + { + TU local; + _table.TryGetValue ((T)key, out local); + return local; + } + + protected override IEnumerator> InternalGetEnumerator () + { + return _table.GetEnumerator (); + } + + public override bool IsEmpty () + { + return _table.Count == 0; + } + + public override TU Put (T key, TU value) + { + lock (_table) { + TU old = Get (key); + Dictionary newTable = new Dictionary (_table); + newTable[key] = value; + _table = newTable; + return old; + } + } + + public TU PutIfAbsent (T key, TU value) + { + lock (_table) { + if (!ContainsKey (key)) { + Dictionary newTable = new Dictionary (_table); + newTable[key] = value; + _table = newTable; + return value; + } + return Get (key); + } + } + + public override TU Remove (object key) + { + lock (_table) { + TU old = Get ((T)key); + Dictionary newTable = new Dictionary (_table); + newTable.Remove ((T)key); + _table = newTable; + return old; + } + } + + public bool Remove (object key, object value) + { + lock (_table) { + if (ContainsKey (key) && value.Equals (Get (key))) { + Dictionary newTable = new Dictionary (_table); + newTable.Remove ((T)key); + _table = newTable; + return true; + } + return false; + } + } + + public bool Replace (T key, TU oldValue, TU newValue) + { + lock (_table) { + if (ContainsKey (key) && oldValue.Equals (Get (key))) { + Dictionary newTable = new Dictionary (_table); + newTable[key] = newValue; + _table = newTable; + return true; + } + return false; + } + } + + public override IEnumerable Keys { + get { return _table.Keys; } + } + + public override IEnumerable Values { + get { return _table.Values; } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/DateFormat.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/DateFormat.cs new file mode 100644 index 0000000000..9a3b7ec4a3 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/DateFormat.cs @@ -0,0 +1,37 @@ +using System; +using System.Globalization; + +namespace SharpCifs.Util.Sharpen +{ + public abstract class DateFormat + { + public const int Default = 2; + + public static DateFormat GetDateTimeInstance (int dateStyle, int timeStyle) + { + return GetDateTimeInstance (dateStyle, timeStyle, CultureInfo.CurrentCulture); + } + + public static DateFormat GetDateTimeInstance (int dateStyle, int timeStyle, CultureInfo aLocale) + { + return new SimpleDateFormat (aLocale.DateTimeFormat.FullDateTimePattern, aLocale); + } + + TimeZoneInfo _timeZone; + + public abstract DateTime Parse (string value); + + public TimeZoneInfo GetTimeZone () + { + return _timeZone; + } + + public void SetTimeZone (TimeZoneInfo timeZone) + { + this._timeZone = timeZone; + } + + public abstract string Format (DateTime time); + } +} + diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/EnumeratorWrapper.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/EnumeratorWrapper.cs new file mode 100644 index 0000000000..f8efdde2a7 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/EnumeratorWrapper.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; + +namespace SharpCifs.Util.Sharpen +{ + internal class EnumeratorWrapper : Iterator + { + object _collection; + IEnumerator _e; + T _lastVal; + bool _more; + bool _copied; + + public EnumeratorWrapper (object collection, IEnumerator e) + { + this._e = e; + this._collection = collection; + _more = e.MoveNext (); + } + + public override bool HasNext () + { + return _more; + } + + public override T Next () + { + if (!_more) + throw new NoSuchElementException (); + _lastVal = _e.Current; + _more = _e.MoveNext (); + return _lastVal; + } + + public override void Remove () + { + ICollection col = _collection as ICollection; + if (col == null) { + throw new NotSupportedException (); + } + if (_more && !_copied) { + // Read the remaining elements, since the current enumerator + // will be invalid after removing the element + List remaining = new List (); + do { + remaining.Add (_e.Current); + } while (_e.MoveNext ()); + _e = remaining.GetEnumerator (); + _e.MoveNext (); + _copied = true; + } + col.Remove (_lastVal); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Exceptions.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Exceptions.cs new file mode 100644 index 0000000000..ec88b28496 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Exceptions.cs @@ -0,0 +1,217 @@ +// +// Exceptions.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; + +namespace SharpCifs.Util.Sharpen +{ + public class VirtualMachineError : Error + { + } + + public class StackOverflowError : VirtualMachineError + { + } + + public class BrokenBarrierException : Exception + { + } + + internal class BufferUnderflowException : Exception + { + } + + public class CharacterCodingException : Exception + { + } + + public class DataFormatException : Exception + { + } + + public class EofException : Exception + { + public EofException () + { + } + + public EofException (string msg) : base(msg) + { + } + } + + public class Error : Exception + { + public Error () + { + } + + public Error (Exception ex) : base("Runtime Exception", ex) + { + } + + public Error (string msg) : base(msg) + { + } + + public Error (string msg, Exception ex) : base(msg, ex) + { + } + } + + public class ExecutionException : Exception + { + public ExecutionException (Exception inner): base ("Execution failed", inner) + { + } + } + + public class InstantiationException : Exception + { + } + + public class InterruptedIoException : Exception + { + public InterruptedIoException (string msg) : base(msg) + { + } + } + + public class MissingResourceException : Exception + { + } + + public class NoSuchAlgorithmException : Exception + { + } + + public class NoSuchElementException : Exception + { + } + + internal class NoSuchMethodException : Exception + { + } + + internal class OverlappingFileLockException : Exception + { + } + + public class ParseException : Exception + { + public ParseException () + { + } + + public ParseException (string msg, int errorOffset) : base(string.Format ("Msg: {0}. Error Offset: {1}", msg, errorOffset)) + { + } + } + + public class RuntimeException : Exception + { + public RuntimeException () + { + } + + public RuntimeException (Exception ex) : base("Runtime Exception", ex) + { + } + + public RuntimeException (string msg) : base(msg) + { + } + + public RuntimeException (string msg, Exception ex) : base(msg, ex) + { + } + } + + internal class StringIndexOutOfBoundsException : Exception + { + } + + public class UnknownHostException : Exception + { + public UnknownHostException () + { + } + + public UnknownHostException(string message) : base(message) + { + + } + + public UnknownHostException (Exception ex): base ("Host not found", ex) + { + } + } + + public class UnsupportedEncodingException : Exception + { + } + + internal class UriSyntaxException : Exception + { + public UriSyntaxException (string s, string msg) : base(s + " " + msg) + { + } + } + + internal class ZipException : Exception + { + } + + public class GitException : Exception + { + } + + public class ConnectException: Exception + { + public ConnectException (string msg): base (msg) + { + } + } + + class KeyManagementException: Exception + { + } + + class IllegalCharsetNameException: Exception + { + public IllegalCharsetNameException (string msg): base (msg) + { + } + } + + class UnsupportedCharsetException: Exception + { + public UnsupportedCharsetException (string msg): base (msg) + { + } + } +} + diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Extensions.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Extensions.cs new file mode 100644 index 0000000000..a578635efb --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Extensions.cs @@ -0,0 +1,714 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +//using Windows.Networking; +//using Windows.Networking.Sockets; + +namespace SharpCifs.Util.Sharpen +{ + + + public static class Extensions + { + private static readonly long EpochTicks; + + static Extensions() + { + DateTime time = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + EpochTicks = time.Ticks; + } + + public static void Add(this IList list, int index, T item) + { + list.Insert(index, item); + } + + public static void AddFirst(this IList list, T item) + { + list.Insert(0, item); + } + + public static void AddLast(this IList list, T item) + { + list.Add(item); + } + + public static void RemoveLast(this IList list) + { + if (list.Count > 0) + list.Remove(list.Count - 1); + } + + public static StringBuilder AppendRange(this StringBuilder sb, string str, int start, int end) + { + return sb.Append(str, start, end - start); + } + + public static StringBuilder Delete(this StringBuilder sb, int start, int end) + { + return sb.Remove(start, end - start); + } + + public static void SetCharAt(this StringBuilder sb, int index, char c) + { + sb[index] = c; + } + + public static int IndexOf(this StringBuilder sb, string str) + { + return sb.ToString().IndexOf(str); + } + + public static int BitCount(int val) + { + uint num = (uint)val; + int count = 0; + for (int i = 0; i < 32; i++) + { + if ((num & 1) != 0) + { + count++; + } + num >>= 1; + } + return count; + } + + public static IndexOutOfRangeException CreateIndexOutOfRangeException(int index) + { + return new IndexOutOfRangeException("Index: " + index); + } + + public static string Decode(this Encoding e, byte[] chars, int start, int len) + { + try + { + byte[] bom = e.GetPreamble(); + if (bom != null && bom.Length > 0) + { + if (len >= bom.Length) + { + int pos = start; + bool hasBom = true; + for (int n = 0; n < bom.Length && hasBom; n++) + { + if (bom[n] != chars[pos++]) + hasBom = false; + } + if (hasBom) + { + len -= pos - start; + start = pos; + } + } + } + return e.GetString(chars, start, len); + } + catch (DecoderFallbackException) + { + throw new CharacterCodingException(); + } + } + + + + public static Encoding GetEncoding(string name) + { + // Encoding e = Encoding.GetEncoding (name, EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback); + try + { + + Encoding e = Encoding.GetEncoding(name.Replace('_', '-')); + if (e is UTF8Encoding) + return new UTF8Encoding(false, true); + + return e; + } + catch (ArgumentException) + { + throw new UnsupportedCharsetException(name); + } + } + + public static ICollection> EntrySet(this IDictionary s) + { + return s; + } + + + public static bool AddItem(this IList list, T item) + { + list.Add(item); + return true; + } + + public static bool AddItem(this ICollection list, T item) + { + list.Add(item); + return true; + } + + public static TU Get(this IDictionary d, T key) + { + TU val; + d.TryGetValue(key, out val); + return val; + } + + + public static TU Put(this IDictionary d, T key, TU value) + { + TU old; + d.TryGetValue(key, out old); + d[key] = value; + return old; + } + + public static void PutAll(this IDictionary d, IDictionary values) + { + foreach (KeyValuePair val in values) + d[val.Key] = val.Value; + } + + + public static CultureInfo GetEnglishCulture() + { + return new CultureInfo("en-US"); + } + + public static T GetFirst(this IList list) + { + return ((list.Count == 0) ? default(T) : list[0]); + } + + public static CultureInfo GetGermanCulture() + { + CultureInfo r = new CultureInfo("de-DE"); + return r; + } + + public static T GetLast(this IList list) + { + return ((list.Count == 0) ? default(T) : list[list.Count - 1]); + } + + public static int GetOffset(this TimeZoneInfo tzone, long date) + { + return (int)tzone.GetUtcOffset(MillisToDateTimeOffset(date, 0).DateTime).TotalMilliseconds; + } + + public static InputStream GetResourceAsStream(this Type type, string name) + { + //Type.`Assembly` property deleted + //string str2 = type.Assembly.GetName().Name + ".resources"; + string str2 = type.GetTypeInfo().Assembly.GetName().Name + ".resources"; + string[] textArray1 = { str2, ".", type.Namespace, ".", name }; + string str = string.Concat(textArray1); + + //Type.`Assembly` property deleted + //Stream manifestResourceStream = type.Assembly.GetManifestResourceStream(str); + Stream manifestResourceStream = type.GetTypeInfo().Assembly.GetManifestResourceStream(str); + if (manifestResourceStream == null) + { + return null; + } + return InputStream.Wrap(manifestResourceStream); + } + + public static long GetTime(this DateTime dateTime) + { + return new DateTimeOffset(DateTime.SpecifyKind(dateTime, DateTimeKind.Utc), TimeSpan.Zero).ToMillisecondsSinceEpoch(); + } + + public static void InitCause(this Exception ex, Exception cause) + { + Console.WriteLine(cause); + } + + public static bool IsEmpty(this ICollection col) + { + return (col.Count == 0); + } + + public static bool IsEmpty(this Stack col) + { + return (col.Count == 0); + } + + public static bool IsLower(this char c) + { + return char.IsLower(c); + } + + public static bool IsUpper(this char c) + { + return char.IsUpper(c); + } + + public static Iterator Iterator(this ICollection col) + { + return new EnumeratorWrapper(col, col.GetEnumerator()); + } + + public static Iterator Iterator(this IEnumerable col) + { + return new EnumeratorWrapper(col, col.GetEnumerator()); + } + + public static T Last(this ICollection col) + { + IList list = col as IList; + if (list != null) + { + return list[list.Count - 1]; + } + return col.Last(); + } + + public static int LowestOneBit(int val) + { + return (1 << NumberOfTrailingZeros(val)); + } + + public static bool Matches(this string str, string regex) + { + Regex regex2 = new Regex(regex); + return regex2.IsMatch(str); + } + + public static DateTime CreateDate(long milliSecondsSinceEpoch) + { + long num = EpochTicks + (milliSecondsSinceEpoch * 10000); + return new DateTime(num); + } + + public static DateTime CreateDateFromUTC(long milliSecondsSinceEpoch) + { + long num = EpochTicks + (milliSecondsSinceEpoch * 10000); + return new DateTime(num, DateTimeKind.Utc); + } + + + public static DateTimeOffset MillisToDateTimeOffset(long milliSecondsSinceEpoch, long offsetMinutes) + { + TimeSpan offset = TimeSpan.FromMinutes(offsetMinutes); + long num = EpochTicks + (milliSecondsSinceEpoch * 10000); + return new DateTimeOffset(num + offset.Ticks, offset); + } + + public static int NumberOfLeadingZeros(int val) + { + uint num = (uint)val; + int count = 0; + while ((num & 0x80000000) == 0) + { + num = num << 1; + count++; + } + return count; + } + + public static int NumberOfTrailingZeros(int val) + { + uint num = (uint)val; + int count = 0; + while ((num & 1) == 0) + { + num = num >> 1; + count++; + } + return count; + } + + public static int Read(this StreamReader reader, char[] data) + { + return reader.Read(data, 0, data.Length); + } + + public static T Remove(this IList list, T item) + { + int index = list.IndexOf(item); + if (index == -1) + { + return default(T); + } + T local = list[index]; + list.RemoveAt(index); + return local; + } + + public static T Remove(this IList list, int i) + { + T old; + try + { + old = list[i]; + list.RemoveAt(i); + } + catch (IndexOutOfRangeException) + { + throw new NoSuchElementException(); + } + return old; + } + + public static T RemoveFirst(this IList list) + { + return list.Remove(0); + } + + public static string ReplaceAll(this string str, string regex, string replacement) + { + Regex rgx = new Regex(regex); + + if (replacement.IndexOfAny(new[] { '\\', '$' }) != -1) + { + // Back references not yet supported + StringBuilder sb = new StringBuilder(); + for (int n = 0; n < replacement.Length; n++) + { + char c = replacement[n]; + if (c == '$') + throw new NotSupportedException("Back references not supported"); + if (c == '\\') + c = replacement[++n]; + sb.Append(c); + } + replacement = sb.ToString(); + } + + return rgx.Replace(str, replacement); + } + + public static bool RegionMatches(this string str, bool ignoreCase, int toOffset, string other, int ooffset, int len) + { + if (toOffset < 0 || ooffset < 0 || toOffset + len > str.Length || ooffset + len > other.Length) + return false; + return string.Compare(str, toOffset, other, ooffset, len) == 0; + } + + public static T Set(this IList list, int index, T item) + { + T old = list[index]; + list[index] = item; + return old; + } + + public static int Signum(long val) + { + if (val < 0) + { + return -1; + } + if (val > 0) + { + return 1; + } + return 0; + } + + public static void RemoveAll(this ICollection col, ICollection items) where TU : T + { + foreach (var u in items) + col.Remove(u); + } + + public static bool ContainsAll(this ICollection col, ICollection items) where TU : T + { + foreach (var u in items) + if (!col.Any(n => (ReferenceEquals(n, u)) || n.Equals(u))) + return false; + return true; + } + + public static bool Contains(this ICollection col, object item) + { + if (!(item is T)) + return false; + return col.Any(n => (ReferenceEquals(n, item)) || n.Equals(item)); + } + + public static void Sort(this IList list) + { + List sorted = new List(list); + sorted.Sort(); + for (int i = 0; i < list.Count; i++) + { + list[i] = sorted[i]; + } + } + + public static void Sort(this IList list, IComparer comparer) + { + List sorted = new List(list); + sorted.Sort(comparer); + for (int i = 0; i < list.Count; i++) + { + list[i] = sorted[i]; + } + } + + public static string[] Split(this string str, string regex) + { + return str.Split(regex, 0); + } + + public static string[] Split(this string str, string regex, int limit) + { + Regex rgx = new Regex(regex); + List list = new List(); + int startIndex = 0; + if (limit != 1) + { + int nm = 1; + foreach (Match match in rgx.Matches(str)) + { + list.Add(str.Substring(startIndex, match.Index - startIndex)); + startIndex = match.Index + match.Length; + if (limit > 0 && ++nm == limit) + break; + } + } + if (startIndex < str.Length) + { + list.Add(str.Substring(startIndex)); + } + if (limit >= 0) + { + int count = list.Count - 1; + while ((count >= 0) && (list[count].Length == 0)) + { + count--; + } + list.RemoveRange(count + 1, (list.Count - count) - 1); + } + return list.ToArray(); + } + + public static IList SubList(this IList list, int start, int len) + { + List sublist = new List(len); + for (int i = start; i < (start + len); i++) + { + sublist.Add(list[i]); + } + return sublist; + } + + public static char[] ToCharArray(this string str) + { + char[] destination = new char[str.Length]; + str.CopyTo(0, destination, 0, str.Length); + return destination; + } + + public static long ToMillisecondsSinceEpoch(this DateTime dateTime) + { + if (dateTime.Kind != DateTimeKind.Utc) + { + throw new ArgumentException("dateTime is expected to be expressed as a UTC DateTime", "dateTime"); + } + return new DateTimeOffset(DateTime.SpecifyKind(dateTime, DateTimeKind.Utc), TimeSpan.Zero).ToMillisecondsSinceEpoch(); + } + + public static long ToMillisecondsSinceEpoch(this DateTimeOffset dateTimeOffset) + { + return (((dateTimeOffset.Ticks - dateTimeOffset.Offset.Ticks) - EpochTicks) / TimeSpan.TicksPerMillisecond); + } + + public static string ToOctalString(int val) + { + return Convert.ToString(val, 8); + } + + public static string ToHexString(int val) + { + return Convert.ToString(val, 16); + } + + public static string ToString(object val) + { + return val.ToString(); + } + + public static string ToString(int val, int bas) + { + return Convert.ToString(val, bas); + } + + public static IList UpcastTo(this IList s) where T : TU + { + List list = new List(s.Count); + for (int i = 0; i < s.Count; i++) + { + list.Add(s[i]); + } + return list; + } + + public static ICollection UpcastTo(this ICollection s) where T : TU + { + List list = new List(s.Count); + foreach (var v in s) + { + list.Add(v); + } + return list; + } + + public static T ValueOf(T val) + { + return val; + } + + + //use? for NUnit-testing? + //public static string GetTestName(object obj) + //{ + // return GetTestName(); + //} + + //public static string GetTestName() + //{ + // MethodBase met; + // int n = 0; + // do + // { + // met = new StackFrame(n).GetMethod(); + // if (met != null) + // { + // foreach (Attribute at in met.GetCustomAttributes(true)) + // { + // if (at.GetType().FullName == "NUnit.Framework.TestAttribute") + // { + // // Convert back to camel case + // string name = met.Name; + // if (char.IsUpper(name[0])) + // name = char.ToLower(name[0]) + name.Substring(1); + // return name; + // } + // } + // } + // n++; + // } while (met != null); + // return ""; + //} + + public static string GetHostAddress(this IPAddress addr) + { + return addr.ToString(); + } + + + public static IPAddress GetAddressByName(string host) + { + if (host == "0.0.0.0") + { + return IPAddress.Any; + } + + try + { + return IPAddress.Parse(host); + } + catch (Exception ex) + { + return null; + } + } + + public static IPAddress[] GetAddressesByName(string host) + { + //IReadOnlyList data = null; + + //try + //{ + // Task.Run(async () => + // { + // data = await DatagramSocket.GetEndpointPairsAsync(new HostName(host), "0"); + // }).Wait(); + //} + //catch (Exception ex) + //{ + // return null; + //} + + //return data != null + // ? data.Where(i => i.RemoteHostName.Type == HostNameType.Ipv4) + // .GroupBy(i => i.RemoteHostName.DisplayName) + // .Select(i => IPAddress.Parse(i.First().RemoteHostName.DisplayName)) + // .ToArray() + // : null; + + //get v4-address only + var entry = Task.Run(() => System.Net.Dns.GetHostEntryAsync(host)) + .GetAwaiter() + .GetResult(); + return entry.AddressList + .Where(addr => addr.AddressFamily == AddressFamily.InterNetwork) + .ToArray(); + + } + + public static string GetImplementationVersion(this Assembly asm) + { + return asm.GetName().Version.ToString(); + } + + public static string GetHost(this Uri uri) + { + return string.IsNullOrEmpty(uri.Host) ? "" : uri.Host; + } + + public static string GetUserInfo(this Uri uri) + { + return string.IsNullOrEmpty(uri.UserInfo) ? null : uri.UserInfo; + } + + public static string GetQuery(this Uri uri) + { + return string.IsNullOrEmpty(uri.Query) ? null : uri.Query; + } + + public static int GetLocalPort(this Socket socket) + { + return ((IPEndPoint)socket.LocalEndPoint).Port; + } + + public static int GetPort(this Socket socket) + { + return ((IPEndPoint)socket.RemoteEndPoint).Port; + } + + public static IPAddress GetInetAddress(this Socket socket) + { + return ((IPEndPoint)socket.RemoteEndPoint).Address; + } + + + /*public static bool RemoveElement(this ArrayList list, object elem) + { + int i = list.IndexOf(elem); + if (i == -1) + return false; + list.RemoveAt(i); + return true; + }*/ + + public static Semaphore CreateSemaphore(int count) + { + return new Semaphore(count, int.MaxValue); + } + + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FileInputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FileInputStream.cs new file mode 100644 index 0000000000..25c5e06e07 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FileInputStream.cs @@ -0,0 +1,20 @@ +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + public class FileInputStream : InputStream + { + public FileInputStream (FilePath file) : this(file.GetPath ()) + { + } + + public FileInputStream (string file) + { + if (!File.Exists (file)) { + throw new FileNotFoundException ("File not found", file); + } + Wrapped = new FileStream (file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + } + + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FileOutputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FileOutputStream.cs new file mode 100644 index 0000000000..bf80294886 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FileOutputStream.cs @@ -0,0 +1,33 @@ +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + internal class FileOutputStream : OutputStream + { + public FileOutputStream (FilePath file): this (file.GetPath (), false) + { + } + + public FileOutputStream (string file): this (file, false) + { + } + + public FileOutputStream (FilePath file, bool append) : this(file.GetPath (), append) + { + } + + public FileOutputStream (string file, bool append) + { + try { + if (append) { + Wrapped = File.Open (file, FileMode.Append, FileAccess.Write); + } else { + Wrapped = File.Open (file, FileMode.Create, FileAccess.Write); + } + } catch (DirectoryNotFoundException) { + throw new FileNotFoundException ("File not found: " + file); + } + } + + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FilePath.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FilePath.cs new file mode 100644 index 0000000000..1b2f5eddcd --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FilePath.cs @@ -0,0 +1,313 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; + +namespace SharpCifs.Util.Sharpen +{ + public class FilePath + { + private string _path; + private static long _tempCounter; + + public FilePath () + { + } + + public FilePath (string path) + : this ((string) null, path) + { + + } + + public FilePath (FilePath other, string child) + : this ((string) other, child) + { + + } + + public FilePath (string other, string child) + { + if (other == null) { + _path = child; + } else { + while (!string.IsNullOrEmpty(child) && (child[0] == Path.DirectorySeparatorChar || child[0] == Path.AltDirectorySeparatorChar)) + child = child.Substring (1); + + if (!string.IsNullOrEmpty(other) && other[other.Length - 1] == Path.VolumeSeparatorChar) + other += Path.DirectorySeparatorChar; + + _path = Path.Combine (other, child); + } + } + + public static implicit operator FilePath (string name) + { + return new FilePath (name); + } + + public static implicit operator string (FilePath filePath) + { + return filePath == null ? null : filePath._path; + } + + public override bool Equals (object obj) + { + FilePath other = obj as FilePath; + if (other == null) + return false; + return GetCanonicalPath () == other.GetCanonicalPath (); + } + + public override int GetHashCode () + { + return _path.GetHashCode (); + } + + public bool CreateNewFile () + { + try { + //Stream.`Close` method deleted + //File.Open (_path, FileMode.CreateNew).Close (); + File.Open(_path, FileMode.CreateNew).Dispose(); + return true; + } catch { + return false; + } + } + + public static FilePath CreateTempFile () + { + return new FilePath (Path.GetTempFileName ()); + } + + public static FilePath CreateTempFile (string prefix, string suffix) + { + return CreateTempFile (prefix, suffix, null); + } + + public static FilePath CreateTempFile (string prefix, string suffix, FilePath directory) + { + string file; + if (prefix == null) { + throw new ArgumentNullException ("prefix"); + } + if (prefix.Length < 3) { + throw new ArgumentException ("prefix must have at least 3 characters"); + } + string str = (directory == null) ? Path.GetTempPath () : directory.GetPath (); + do { + file = Path.Combine (str, prefix + Interlocked.Increment (ref _tempCounter) + suffix); + } while (File.Exists (file)); + + new FileOutputStream (file).Close (); + return new FilePath (file); + } + + + public void DeleteOnExit () + { + } + + + public FilePath GetAbsoluteFile () + { + return new FilePath (Path.GetFullPath (_path)); + } + + public string GetAbsolutePath () + { + return Path.GetFullPath (_path); + } + + public FilePath GetCanonicalFile () + { + return new FilePath (GetCanonicalPath ()); + } + + public string GetCanonicalPath () + { + string p = Path.GetFullPath (_path); + p.TrimEnd (Path.DirectorySeparatorChar); + return p; + } + + public string GetName () + { + return Path.GetFileName (_path); + } + + public FilePath GetParentFile () + { + return new FilePath (Path.GetDirectoryName (_path)); + } + + public string GetPath () + { + return _path; + } + + public bool IsAbsolute () + { + return Path.IsPathRooted (_path); + } + + public bool IsDirectory () + { + return false; // FileHelper.Instance.IsDirectory(this); + } + + public bool IsFile () + { + return false; //FileHelper.Instance.IsFile (this); + } + + public long LastModified () + { + return 0; // FileHelper.Instance.LastModified(this); + } + + public long Length () + { + return 0; // FileHelper.Instance.Length(this); + } + + public string[] List () + { + return List (null); + } + + public string[] List (IFilenameFilter filter) + { + try { + if (IsFile ()) + return null; + List list = new List (); + foreach (string filePth in Directory.GetFileSystemEntries (_path)) { + string fileName = Path.GetFileName (filePth); + if ((filter == null) || filter.Accept (this, fileName)) { + list.Add (fileName); + } + } + return list.ToArray (); + } catch { + return null; + } + } + + public FilePath[] ListFiles () + { + try { + if (IsFile ()) + return null; + List list = new List (); + foreach (string filePath in Directory.GetFileSystemEntries (_path)) { + list.Add (new FilePath (filePath)); + } + return list.ToArray (); + } catch { + return null; + } + } + + static void MakeDirWritable (string dir) + { + //FileHelper.Instance.MakeDirWritable (dir); + } + + static void MakeFileWritable (string file) + { + //FileHelper.Instance.MakeFileWritable (file); + } + + public bool Mkdir () + { + try { + if (Directory.Exists (_path)) + return false; + Directory.CreateDirectory (_path); + return true; + } catch (Exception) { + return false; + } + } + + public bool Mkdirs () + { + try { + if (Directory.Exists (_path)) + return false; + Directory.CreateDirectory (_path); + return true; + } catch { + return false; + } + } + + public bool RenameTo (FilePath file) + { + return RenameTo (file._path); + } + + public bool RenameTo (string name) + { + return false; // FileHelper.Instance.RenameTo(this, name); + } + + public bool SetLastModified (long milis) + { + return false; // FileHelper.Instance.SetLastModified(this, milis); + } + + public bool SetReadOnly () + { + return false; // FileHelper.Instance.SetReadOnly(this); + } + + public Uri ToUri () + { + return new Uri (_path); + } + + // Don't change the case of this method, since ngit does reflection on it + public bool CanExecute () + { + return false; // FileHelper.Instance.CanExecute(this); + } + + // Don't change the case of this method, since ngit does reflection on it + public bool SetExecutable (bool exec) + { + return false; // FileHelper.Instance.SetExecutable(this, exec); + } + + public string GetParent () + { + string p = Path.GetDirectoryName (_path); + if (string.IsNullOrEmpty(p) || p == _path) + return null; + return p; + } + + public override string ToString () + { + return _path; + } + + static internal string PathSeparator { + get { return Path.PathSeparator.ToString (); } + } + + static internal char PathSeparatorChar { + get { return Path.PathSeparator; } + } + + static internal char SeparatorChar { + get { return Path.DirectorySeparatorChar; } + } + + static internal string Separator { + get { return Path.DirectorySeparatorChar.ToString (); } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FileReader.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FileReader.cs new file mode 100644 index 0000000000..7a0c1f90e1 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FileReader.cs @@ -0,0 +1,13 @@ +namespace SharpCifs.Util.Sharpen +{ + public class FileReader : InputStreamReader + { + //public FileReader (FilePath f) : base(f.GetPath ()) + //{ + //} + //path -> fileStream + public FileReader(InputStream s) : base(s) + { + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FileWriter.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FileWriter.cs new file mode 100644 index 0000000000..0675c238bc --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FileWriter.cs @@ -0,0 +1,18 @@ +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + //resharper said, nobody using this. i believe it. + //internal class FileWriter : StreamWriter + //{ + // public FileWriter (FilePath path) : base(path.GetPath ()) + // { + // } + + // public FileWriter Append (string sequence) + // { + // Write (sequence); + // return this; + // } + //} +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FilterInputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FilterInputStream.cs new file mode 100644 index 0000000000..dfc0ba2641 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FilterInputStream.cs @@ -0,0 +1,57 @@ +namespace SharpCifs.Util.Sharpen +{ + public class FilterInputStream : InputStream + { + protected InputStream In; + + public FilterInputStream (InputStream s) + { + In = s; + } + + public override int Available () + { + return In.Available (); + } + + public override void Close () + { + In.Close (); + } + + public override void Mark (int readlimit) + { + In.Mark (readlimit); + } + + public override bool MarkSupported () + { + return In.MarkSupported (); + } + + public override int Read () + { + return In.Read (); + } + + public override int Read (byte[] buf) + { + return In.Read (buf); + } + + public override int Read (byte[] b, int off, int len) + { + return In.Read (b, off, len); + } + + public override void Reset () + { + In.Reset (); + } + + public override long Skip (long cnt) + { + return In.Skip (cnt); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FilterOutputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FilterOutputStream.cs new file mode 100644 index 0000000000..4863105ed6 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/FilterOutputStream.cs @@ -0,0 +1,37 @@ +namespace SharpCifs.Util.Sharpen +{ + public class FilterOutputStream : OutputStream + { + protected OutputStream Out; + + public FilterOutputStream (OutputStream os) + { + Out = os; + } + + public override void Close () + { + Out.Close (); + } + + public override void Flush () + { + Out.Flush (); + } + + public override void Write (byte[] b) + { + Out.Write (b); + } + + public override void Write (int b) + { + Out.Write (b); + } + + public override void Write (byte[] b, int offset, int len) + { + Out.Write (b, offset, len); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Hashtable.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Hashtable.cs new file mode 100644 index 0000000000..c2c53485dc --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Hashtable.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Linq; + +namespace SharpCifs.Util.Sharpen +{ + public class Hashtable : Dictionary + { + public void Put(object key, object value) + { + Add(key, value); + } + + public object Get(object key) + { + var m_key = Keys.SingleOrDefault(k => k.Equals(key)); + + return m_key != null ? this[m_key] : null; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/HttpURLConnection.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/HttpURLConnection.cs new file mode 100644 index 0000000000..ace314eee4 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/HttpURLConnection.cs @@ -0,0 +1,37 @@ +// +// HttpURLConnection.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; + +namespace SharpCifs.Util.Sharpen +{ + public class UrlConnection + { + protected Uri Url; + } + +} + diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ICallable.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ICallable.cs new file mode 100644 index 0000000000..d847cb497a --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ICallable.cs @@ -0,0 +1,7 @@ +namespace SharpCifs.Util.Sharpen +{ + internal interface ICallable + { + T Call (); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IConcurrentMap.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IConcurrentMap.cs new file mode 100644 index 0000000000..dead242443 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IConcurrentMap.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace SharpCifs.Util.Sharpen +{ + internal interface IConcurrentMap : IDictionary + { + TU PutIfAbsent (T key, TU value); + bool Remove (object key, object value); + bool Replace (T key, TU oldValue, TU newValue); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IExecutor.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IExecutor.cs new file mode 100644 index 0000000000..5f76c2ed57 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IExecutor.cs @@ -0,0 +1,7 @@ +namespace SharpCifs.Util.Sharpen +{ + public interface IExecutor + { + void Execute (IRunnable runnable); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IFilenameFilter.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IFilenameFilter.cs new file mode 100644 index 0000000000..fe2eb6a3d6 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IFilenameFilter.cs @@ -0,0 +1,7 @@ +namespace SharpCifs.Util.Sharpen +{ + public interface IFilenameFilter + { + bool Accept (FilePath dir, string name); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IFuture.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IFuture.cs new file mode 100644 index 0000000000..5215e45028 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IFuture.cs @@ -0,0 +1,8 @@ +namespace SharpCifs.Util.Sharpen +{ + internal interface IFuture + { + bool Cancel (bool mayInterruptIfRunning); + T Get (); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IPrivilegedAction.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IPrivilegedAction.cs new file mode 100644 index 0000000000..4a5e92f9b5 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IPrivilegedAction.cs @@ -0,0 +1,7 @@ +namespace SharpCifs.Util.Sharpen +{ + internal interface IPrivilegedAction + { + T Run (); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IRunnable.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IRunnable.cs new file mode 100644 index 0000000000..7f6ae5533d --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/IRunnable.cs @@ -0,0 +1,7 @@ +namespace SharpCifs.Util.Sharpen +{ + public interface IRunnable + { + void Run (); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/InputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/InputStream.cs new file mode 100644 index 0000000000..2f3f070b50 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/InputStream.cs @@ -0,0 +1,169 @@ +using System; +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + public class InputStream : IDisposable + { + private long _mark; + protected Stream Wrapped; + protected Stream BaseStream; + + public static implicit operator InputStream (Stream s) + { + return Wrap (s); + } + + public static implicit operator Stream (InputStream s) + { + return s.GetWrappedStream (); + } + + public virtual int Available () + { + if (Wrapped is WrappedSystemStream) + return ((WrappedSystemStream)Wrapped).InputStream.Available (); + return 0; + } + + public virtual void Close () + { + if (Wrapped != null) { + //Stream.`Close` method deleted + //Wrapped.Close (); + Wrapped.Dispose(); + } + } + + public void Dispose () + { + Close (); + } + + internal Stream GetWrappedStream () + { + // Always create a wrapper stream (not directly Wrapped) since the subclass + // may be overriding methods that need to be called when used through the Stream class + return new WrappedSystemStream (this); + } + + public virtual void Mark (int readlimit) + { + if (Wrapped is WrappedSystemStream) + ((WrappedSystemStream)Wrapped).InputStream.Mark (readlimit); + else { + if (BaseStream is WrappedSystemStream) + ((WrappedSystemStream)BaseStream).OnMark (readlimit); + if (Wrapped != null) + _mark = Wrapped.Position; + } + } + + public virtual bool MarkSupported () + { + if (Wrapped is WrappedSystemStream) + return ((WrappedSystemStream)Wrapped).InputStream.MarkSupported (); + return ((Wrapped != null) && Wrapped.CanSeek); + } + + public virtual int Read () + { + if (Wrapped == null) { + throw new NotImplementedException (); + } + return Wrapped.ReadByte (); + } + + public virtual int Read (byte[] buf) + { + return Read (buf, 0, buf.Length); + } + + public virtual int Read (byte[] b, int off, int len) + { + if (Wrapped is WrappedSystemStream) + return ((WrappedSystemStream)Wrapped).InputStream.Read (b, off, len); + + if (Wrapped != null) { + int num = Wrapped.Read (b, off, len); + return ((num <= 0) ? -1 : num); + } + int totalRead = 0; + while (totalRead < len) { + int nr = Read (); + if (nr == -1) + return -1; + b[off + totalRead] = (byte)nr; + totalRead++; + } + return totalRead; + } + + public virtual void Reset () + { + if (Wrapped is WrappedSystemStream) + ((WrappedSystemStream)Wrapped).InputStream.Reset (); + else { + if (Wrapped == null) + throw new IOException (); + Wrapped.Position = _mark; + } + } + + public virtual long Skip (long cnt) + { + if (Wrapped is WrappedSystemStream) + return ((WrappedSystemStream)Wrapped).InputStream.Skip (cnt); + + long n = cnt; + while (n > 0) { + if (Read () == -1) + return cnt - n; + n--; + } + return cnt - n; + } + + internal virtual bool CanSeek () + { + if (Wrapped != null) + return Wrapped.CanSeek; + return false; + } + + internal virtual long Position { + get + { + if (Wrapped != null) + return Wrapped.Position; + throw new NotSupportedException (); + } + set { + if (Wrapped != null) + Wrapped.Position = value; + else + throw new NotSupportedException (); + } + } + + public virtual long Length + { + get + { + if (Wrapped != null) + { + return Wrapped.Length; + } + + throw new NotSupportedException(); + } + } + + static internal InputStream Wrap (Stream s) + { + InputStream stream = new InputStream (); + stream.Wrapped = s; + return stream; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/InputStreamReader.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/InputStreamReader.cs new file mode 100644 index 0000000000..f9f1983b83 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/InputStreamReader.cs @@ -0,0 +1,25 @@ +using System.IO; +using System.Text; + +namespace SharpCifs.Util.Sharpen +{ + public class InputStreamReader : StreamReader + { + //Stream(string path) constructor deleted + //protected InputStreamReader (string file) : base(file) + //{ + //} + + public InputStreamReader (InputStream s) : base(s.GetWrappedStream ()) + { + } + + public InputStreamReader (InputStream s, string encoding) : base(s.GetWrappedStream (), Encoding.GetEncoding (encoding)) + { + } + + public InputStreamReader (InputStream s, Encoding e) : base(s.GetWrappedStream (), e) + { + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Iterator.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Iterator.cs new file mode 100644 index 0000000000..634c7b404e --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Iterator.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace SharpCifs.Util.Sharpen +{ + public interface ITerator + { + bool HasNext (); + object Next (); + void Remove (); + } + + public abstract class Iterator : IEnumerator, ITerator + { + private T _lastValue; + + object ITerator.Next () + { + return Next (); + } + + public abstract bool HasNext (); + public abstract T Next (); + public abstract void Remove (); + + bool IEnumerator.MoveNext () + { + if (HasNext ()) { + _lastValue = Next (); + return true; + } + return false; + } + + void IEnumerator.Reset () + { + throw new NotImplementedException (); + } + + void IDisposable.Dispose () + { + } + + T IEnumerator.Current { + get { return _lastValue; } + } + + object IEnumerator.Current { + get { return _lastValue; } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/LinkageError.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/LinkageError.cs new file mode 100644 index 0000000000..9f4970bddf --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/LinkageError.cs @@ -0,0 +1,11 @@ +using System; + +namespace SharpCifs.Util.Sharpen +{ + internal class LinkageError : Exception + { + public LinkageError (string msg) : base(msg) + { + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/MD5.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/MD5.cs new file mode 100644 index 0000000000..50f3fa43b2 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/MD5.cs @@ -0,0 +1,275 @@ +//Copyright (c) Microsoft Corporation. All rights reserved. + +using System; +using System.Text; + +namespace SharpCifs.Util.Sharpen +{ // ************************************************************** +// * Raw implementation of the MD5 hash algorithm +// * from RFC 1321. +// * +// * Written By: Reid Borsuk and Jenny Zheng +// * Copyright (c) Microsoft Corporation. All rights reserved. +// ************************************************************** + +// Simple struct for the (a,b,c,d) which is used to compute the mesage digest. + struct AbcdStruct + { + public uint A; + public uint B; + public uint C; + public uint D; + } + + public sealed class Md5Core + { + //Prevent CSC from adding a default public constructor + private Md5Core() { } + + public static byte[] GetHash(string input, Encoding encoding) + { + if (null == input) + throw new ArgumentNullException("input", "Unable to calculate hash over null input data"); + if (null == encoding) + throw new ArgumentNullException("encoding", "Unable to calculate hash over a string without a default encoding. Consider using the GetHash(string) overload to use UTF8 Encoding"); + + byte[] target = encoding.GetBytes(input); + + return GetHash(target); + } + + public static byte[] GetHash(string input) + { + return GetHash(input, new UTF8Encoding()); + } + + public static string GetHashString(byte[] input) + { + if (null == input) + throw new ArgumentNullException("input", "Unable to calculate hash over null input data"); + + string retval = BitConverter.ToString(GetHash(input)); + retval = retval.Replace("-", ""); + + return retval; + } + + public static string GetHashString(string input, Encoding encoding) + { + if (null == input) + throw new ArgumentNullException("input", "Unable to calculate hash over null input data"); + if (null == encoding) + throw new ArgumentNullException("encoding", "Unable to calculate hash over a string without a default encoding. Consider using the GetHashString(string) overload to use UTF8 Encoding"); + + byte[] target = encoding.GetBytes(input); + + return GetHashString(target); + } + + public static string GetHashString(string input) + { + return GetHashString(input, new UTF8Encoding()); + } + + public static byte[] GetHash(byte[] input) + { + if (null == input) + throw new ArgumentNullException("input", "Unable to calculate hash over null input data"); + + //Intitial values defined in RFC 1321 + AbcdStruct abcd = new AbcdStruct(); + abcd.A = 0x67452301; + abcd.B = 0xefcdab89; + abcd.C = 0x98badcfe; + abcd.D = 0x10325476; + + //We pass in the input array by block, the final block of data must be handled specialy for padding & length embeding + int startIndex = 0; + while (startIndex <= input.Length - 64) + { + GetHashBlock(input, ref abcd, startIndex); + startIndex += 64; + } + // The final data block. + return GetHashFinalBlock(input, startIndex, input.Length - startIndex, abcd, (Int64)input.Length * 8); + } + + internal static byte[] GetHashFinalBlock(byte[] input, int ibStart, int cbSize, AbcdStruct abcd, Int64 len) + { + byte[] working = new byte[64]; + byte[] length = BitConverter.GetBytes(len); + + //Padding is a single bit 1, followed by the number of 0s required to make size congruent to 448 modulo 512. Step 1 of RFC 1321 + //The CLR ensures that our buffer is 0-assigned, we don't need to explicitly set it. This is why it ends up being quicker to just + //use a temporary array rather then doing in-place assignment (5% for small inputs) + Array.Copy(input, ibStart, working, 0, cbSize); + working[cbSize] = 0x80; + + //We have enough room to store the length in this chunk + if (cbSize < 56) + { + Array.Copy(length, 0, working, 56, 8); + GetHashBlock(working, ref abcd, 0); + } + else //We need an aditional chunk to store the length + { + GetHashBlock(working, ref abcd, 0); + //Create an entirely new chunk due to the 0-assigned trick mentioned above, to avoid an extra function call clearing the array + working = new byte[64]; + Array.Copy(length, 0, working, 56, 8); + GetHashBlock(working, ref abcd, 0); + } + byte[] output = new byte[16]; + Array.Copy(BitConverter.GetBytes(abcd.A), 0, output, 0, 4); + Array.Copy(BitConverter.GetBytes(abcd.B), 0, output, 4, 4); + Array.Copy(BitConverter.GetBytes(abcd.C), 0, output, 8, 4); + Array.Copy(BitConverter.GetBytes(abcd.D), 0, output, 12, 4); + return output; + } + + // Performs a single block transform of MD5 for a given set of ABCD inputs + /* If implementing your own hashing framework, be sure to set the initial ABCD correctly according to RFC 1321: + // A = 0x67452301; + // B = 0xefcdab89; + // C = 0x98badcfe; + // D = 0x10325476; + */ + internal static void GetHashBlock(byte[] input, ref AbcdStruct abcdValue, int ibStart) + { + uint[] temp = Converter(input, ibStart); + uint a = abcdValue.A; + uint b = abcdValue.B; + uint c = abcdValue.C; + uint d = abcdValue.D; + + a = R1(a, b, c, d, temp[0], 7, 0xd76aa478); + d = R1(d, a, b, c, temp[1], 12, 0xe8c7b756); + c = R1(c, d, a, b, temp[2], 17, 0x242070db); + b = R1(b, c, d, a, temp[3], 22, 0xc1bdceee); + a = R1(a, b, c, d, temp[4], 7, 0xf57c0faf); + d = R1(d, a, b, c, temp[5], 12, 0x4787c62a); + c = R1(c, d, a, b, temp[6], 17, 0xa8304613); + b = R1(b, c, d, a, temp[7], 22, 0xfd469501); + a = R1(a, b, c, d, temp[8], 7, 0x698098d8); + d = R1(d, a, b, c, temp[9], 12, 0x8b44f7af); + c = R1(c, d, a, b, temp[10], 17, 0xffff5bb1); + b = R1(b, c, d, a, temp[11], 22, 0x895cd7be); + a = R1(a, b, c, d, temp[12], 7, 0x6b901122); + d = R1(d, a, b, c, temp[13], 12, 0xfd987193); + c = R1(c, d, a, b, temp[14], 17, 0xa679438e); + b = R1(b, c, d, a, temp[15], 22, 0x49b40821); + + a = R2(a, b, c, d, temp[1], 5, 0xf61e2562); + d = R2(d, a, b, c, temp[6], 9, 0xc040b340); + c = R2(c, d, a, b, temp[11], 14, 0x265e5a51); + b = R2(b, c, d, a, temp[0], 20, 0xe9b6c7aa); + a = R2(a, b, c, d, temp[5], 5, 0xd62f105d); + d = R2(d, a, b, c, temp[10], 9, 0x02441453); + c = R2(c, d, a, b, temp[15], 14, 0xd8a1e681); + b = R2(b, c, d, a, temp[4], 20, 0xe7d3fbc8); + a = R2(a, b, c, d, temp[9], 5, 0x21e1cde6); + d = R2(d, a, b, c, temp[14], 9, 0xc33707d6); + c = R2(c, d, a, b, temp[3], 14, 0xf4d50d87); + b = R2(b, c, d, a, temp[8], 20, 0x455a14ed); + a = R2(a, b, c, d, temp[13], 5, 0xa9e3e905); + d = R2(d, a, b, c, temp[2], 9, 0xfcefa3f8); + c = R2(c, d, a, b, temp[7], 14, 0x676f02d9); + b = R2(b, c, d, a, temp[12], 20, 0x8d2a4c8a); + + a = R3(a, b, c, d, temp[5], 4, 0xfffa3942); + d = R3(d, a, b, c, temp[8], 11, 0x8771f681); + c = R3(c, d, a, b, temp[11], 16, 0x6d9d6122); + b = R3(b, c, d, a, temp[14], 23, 0xfde5380c); + a = R3(a, b, c, d, temp[1], 4, 0xa4beea44); + d = R3(d, a, b, c, temp[4], 11, 0x4bdecfa9); + c = R3(c, d, a, b, temp[7], 16, 0xf6bb4b60); + b = R3(b, c, d, a, temp[10], 23, 0xbebfbc70); + a = R3(a, b, c, d, temp[13], 4, 0x289b7ec6); + d = R3(d, a, b, c, temp[0], 11, 0xeaa127fa); + c = R3(c, d, a, b, temp[3], 16, 0xd4ef3085); + b = R3(b, c, d, a, temp[6], 23, 0x04881d05); + a = R3(a, b, c, d, temp[9], 4, 0xd9d4d039); + d = R3(d, a, b, c, temp[12], 11, 0xe6db99e5); + c = R3(c, d, a, b, temp[15], 16, 0x1fa27cf8); + b = R3(b, c, d, a, temp[2], 23, 0xc4ac5665); + + a = R4(a, b, c, d, temp[0], 6, 0xf4292244); + d = R4(d, a, b, c, temp[7], 10, 0x432aff97); + c = R4(c, d, a, b, temp[14], 15, 0xab9423a7); + b = R4(b, c, d, a, temp[5], 21, 0xfc93a039); + a = R4(a, b, c, d, temp[12], 6, 0x655b59c3); + d = R4(d, a, b, c, temp[3], 10, 0x8f0ccc92); + c = R4(c, d, a, b, temp[10], 15, 0xffeff47d); + b = R4(b, c, d, a, temp[1], 21, 0x85845dd1); + a = R4(a, b, c, d, temp[8], 6, 0x6fa87e4f); + d = R4(d, a, b, c, temp[15], 10, 0xfe2ce6e0); + c = R4(c, d, a, b, temp[6], 15, 0xa3014314); + b = R4(b, c, d, a, temp[13], 21, 0x4e0811a1); + a = R4(a, b, c, d, temp[4], 6, 0xf7537e82); + d = R4(d, a, b, c, temp[11], 10, 0xbd3af235); + c = R4(c, d, a, b, temp[2], 15, 0x2ad7d2bb); + b = R4(b, c, d, a, temp[9], 21, 0xeb86d391); + + abcdValue.A = unchecked(a + abcdValue.A); + abcdValue.B = unchecked(b + abcdValue.B); + abcdValue.C = unchecked(c + abcdValue.C); + abcdValue.D = unchecked(d + abcdValue.D); + } + + //Manually unrolling these equations nets us a 20% performance improvement + private static uint R1(uint a, uint b, uint c, uint d, uint x, int s, uint t) + { + // (b + LSR((a + F(b, c, d) + x + t), s)) + //F(x, y, z) ((x & y) | ((x ^ 0xFFFFFFFF) & z)) + return unchecked(b + Lsr((a + ((b & c) | ((b ^ 0xFFFFFFFF) & d)) + x + t), s)); + } + + private static uint R2(uint a, uint b, uint c, uint d, uint x, int s, uint t) + { + // (b + LSR((a + G(b, c, d) + x + t), s)) + //G(x, y, z) ((x & z) | (y & (z ^ 0xFFFFFFFF))) + return unchecked(b + Lsr((a + ((b & d) | (c & (d ^ 0xFFFFFFFF))) + x + t), s)); + } + + private static uint R3(uint a, uint b, uint c, uint d, uint x, int s, uint t) + { + // (b + LSR((a + H(b, c, d) + k + i), s)) + //H(x, y, z) (x ^ y ^ z) + return unchecked(b + Lsr((a + (b ^ c ^ d) + x + t), s)); + } + + private static uint R4(uint a, uint b, uint c, uint d, uint x, int s, uint t) + { + // (b + LSR((a + I(b, c, d) + k + i), s)) + //I(x, y, z) (y ^ (x | (z ^ 0xFFFFFFFF))) + return unchecked(b + Lsr((a + (c ^ (b | (d ^ 0xFFFFFFFF))) + x + t), s)); + } + + // Implementation of left rotate + // s is an int instead of a uint becuase the CLR requires the argument passed to >>/<< is of + // type int. Doing the demoting inside this function would add overhead. + private static uint Lsr(uint i, int s) + { + return ((i << s) | (i >> (32 - s))); + } + + //Convert input array into array of UInts + private static uint[] Converter(byte[] input, int ibStart) + { + if (null == input) + throw new ArgumentNullException("input", "Unable convert null array to array of uInts"); + + uint[] result = new uint[16]; + + for (int i = 0; i < 16; i++) + { + result[i] = input[ibStart + i * 4]; + result[i] += (uint)input[ibStart + i * 4 + 1] << 8; + result[i] += (uint)input[ibStart + i * 4 + 2] << 16; + result[i] += (uint)input[ibStart + i * 4 + 3] << 24; + } + + return result; + } + } +} \ No newline at end of file diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/MD5Managed.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/MD5Managed.cs new file mode 100644 index 0000000000..e74a05abf3 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/MD5Managed.cs @@ -0,0 +1,91 @@ +//Copyright (c) Microsoft Corporation. All rights reserved. + +using System; +using System.Security.Cryptography; + +// ************************************************************** +// * Raw implementation of the MD5 hash algorithm +// * from RFC 1321. +// * +// * Written By: Reid Borsuk and Jenny Zheng +// * Copyright (c) Microsoft Corporation. All rights reserved. +// ************************************************************** + + +#if SILVERLIGHT +#else +//public class MD5Managed : MD5 +#endif +namespace SharpCifs.Util.Sharpen +{ + public class Md5Managed : HashAlgorithm + + { + public static Md5Managed Create() + { + return new Md5Managed(); + } + + private byte[] _data; + private AbcdStruct _abcd; + private Int64 _totalLength; + private int _dataSize; + + public Md5Managed() + { + //field cannot access + //HashSizeValue = 0x80; + Initialize(); + } + + public override void Initialize() + { + _data = new byte[64]; + _dataSize = 0; + _totalLength = 0; + _abcd = new AbcdStruct(); + //Intitial values as defined in RFC 1321 + _abcd.A = 0x67452301; + _abcd.B = 0xefcdab89; + _abcd.C = 0x98badcfe; + _abcd.D = 0x10325476; + } + + protected override void HashCore(byte[] array, int ibStart, int cbSize) + { + int startIndex = ibStart; + int totalArrayLength = _dataSize + cbSize; + if (totalArrayLength >= 64) + { + Array.Copy(array, startIndex, _data, _dataSize, 64 - _dataSize); + // Process message of 64 bytes (512 bits) + Md5Core.GetHashBlock(_data, ref _abcd, 0); + startIndex += 64 - _dataSize; + totalArrayLength -= 64; + while (totalArrayLength >= 64) + { + Array.Copy(array, startIndex, _data, 0, 64); + Md5Core.GetHashBlock(array, ref _abcd, startIndex); + totalArrayLength -= 64; + startIndex += 64; + } + _dataSize = totalArrayLength; + Array.Copy(array, startIndex, _data, 0, totalArrayLength); + } + else + { + Array.Copy(array, startIndex, _data, _dataSize, cbSize); + _dataSize = totalArrayLength; + } + _totalLength += cbSize; + } + + protected override byte[] HashFinal() + { + //field cannot access + //HashValue = Md5Core.GetHashFinalBlock(_data, 0, _dataSize, _abcd, _totalLength * 8); + //return HashValue; + return Md5Core.GetHashFinalBlock(_data, 0, _dataSize, _abcd, _totalLength * 8); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Matcher.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Matcher.cs new file mode 100644 index 0000000000..d0bd79aa28 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Matcher.cs @@ -0,0 +1,83 @@ +using System; +using System.Text.RegularExpressions; + +namespace SharpCifs.Util.Sharpen +{ + internal class Matcher + { + private int _current; + private MatchCollection _matches; + private Regex _regex; + private string _str; + + internal Matcher (Regex regex, string str) + { + this._regex = regex; + this._str = str; + } + + public int End () + { + if ((_matches == null) || (_current >= _matches.Count)) { + throw new InvalidOperationException (); + } + return (_matches[_current].Index + _matches[_current].Length); + } + + public bool Find () + { + if (_matches == null) { + _matches = _regex.Matches (_str); + _current = 0; + } + return (_current < _matches.Count); + } + + public bool Find (int index) + { + _matches = _regex.Matches (_str, index); + _current = 0; + return (_matches.Count > 0); + } + + public string Group (int n) + { + if ((_matches == null) || (_current >= _matches.Count)) { + throw new InvalidOperationException (); + } + Group grp = _matches[_current].Groups[n]; + return grp.Success ? grp.Value : null; + } + + public bool Matches () + { + _matches = null; + return Find (); + } + + public string ReplaceFirst (string txt) + { + return _regex.Replace (_str, txt, 1); + } + + public Matcher Reset (CharSequence str) + { + return Reset (str.ToString ()); + } + + public Matcher Reset (string str) + { + _matches = null; + this._str = str; + return this; + } + + public int Start () + { + if ((_matches == null) || (_current >= _matches.Count)) { + throw new InvalidOperationException (); + } + return _matches[_current].Index; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/MessageDigest.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/MessageDigest.cs new file mode 100644 index 0000000000..5562f9d366 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/MessageDigest.cs @@ -0,0 +1,118 @@ +using System; +using System.IO; +using System.Reflection; +using System.Security.Cryptography; + +namespace SharpCifs.Util.Sharpen +{ + public abstract class MessageDigest + { + public void Digest (byte[] buffer, int o, int len) + { + byte[] d = Digest (); + d.CopyTo (buffer, o); + } + + public byte[] Digest (byte[] buffer) + { + Update (buffer); + return Digest (); + } + + public abstract byte[] Digest (); + public abstract int GetDigestLength (); + public static MessageDigest GetInstance (string algorithm) + { + switch (algorithm.ToLower ()) { + case "sha-1": + //System.Security.CryptographySHA1Managed not found + //return new MessageDigest (); + return new MessageDigest(); + case "md5": + return new MessageDigest (); + } + throw new NotSupportedException (string.Format ("The requested algorithm \"{0}\" is not supported.", algorithm)); + } + + public abstract void Reset (); + public abstract void Update (byte[] b); + public abstract void Update (byte b); + public abstract void Update (byte[] b, int offset, int len); + } + + + public class MessageDigest : MessageDigest where TAlgorithm : HashAlgorithm //, new() //use static `Create` method + { + private TAlgorithm _hash; + //private CryptoStream _stream; //don't work .NET Core + private MemoryStream _stream; + + + public MessageDigest () + { + Init (); + } + + public override byte[] Digest () + { + //CryptoStream -> MemoryStream, needless method + //_stream.FlushFinalBlock (); + + //HashAlgorithm.`Hash` property deleted + //byte[] hash = _hash.Hash; + byte[] hash = _hash.ComputeHash(_stream.ToArray()); + + Reset (); + return hash; + } + + public void Dispose () + { + if (_stream != null) { + _stream.Dispose (); + } + _stream = null; + } + + public override int GetDigestLength () + { + return (_hash.HashSize / 8); + } + + private void Init () + { + //use static `Create` method + //_hash = Activator.CreateInstance (); + var createMethod = typeof(TAlgorithm).GetRuntimeMethod("Create", new Type[0]); + _hash = (TAlgorithm)createMethod.Invoke(null, new object[] {}); + + //HashAlgorithm cannot cast `ICryptoTransform` on .NET Core, gave up using CryptoStream. + //_stream = new CryptoStream(Stream.Null, _hash, CryptoStreamMode.Write); + //_stream = new CryptoStream(_tmpStream, (ICryptoTransform)_hash, CryptoStreamMode.Write); + _stream = new MemoryStream(); + } + + public override void Reset () + { + Dispose (); + Init (); + } + + public override void Update (byte[] input) + { + _stream.Write (input, 0, input.Length); + } + + public override void Update (byte input) + { + _stream.WriteByte (input); + } + + public override void Update (byte[] input, int index, int count) + { + if (count < 0) + Console.WriteLine ("Argh!"); + _stream.Write (input, index, count); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/NetworkStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/NetworkStream.cs new file mode 100644 index 0000000000..05599cea3b --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/NetworkStream.cs @@ -0,0 +1,72 @@ +using System; +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + public class NetworkStream : Stream + { + SocketEx _socket; + + public NetworkStream(SocketEx socket) + { + _socket = socket; + } + + public override bool CanRead + { + get { throw new NotImplementedException(); } + } + + public override bool CanSeek + { + get { throw new NotImplementedException(); } + } + + public override bool CanWrite + { + get { throw new NotImplementedException(); } + } + + public override void Flush() + { + // throw new NotImplementedException(); + } + + public override long Length + { + get { throw new NotImplementedException(); } + } + + public override long Position + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + public override int Read(byte[] buffer, int offset, int count) + { + return _socket.Receive(buffer, offset, count); + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotImplementedException(); + } + + public override void SetLength(long value) + { + throw new NotImplementedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + _socket.Send(buffer, offset, count); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ObjectInputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ObjectInputStream.cs new file mode 100644 index 0000000000..dc3d6ccc3e --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ObjectInputStream.cs @@ -0,0 +1,25 @@ +using System; +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + internal class ObjectInputStream : InputStream + { + private BinaryReader _reader; + + public ObjectInputStream (InputStream s) + { + _reader = new BinaryReader (s.GetWrappedStream ()); + } + + public int ReadInt () + { + return _reader.ReadInt32 (); + } + + public object ReadObject () + { + throw new NotImplementedException (); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ObjectOutputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ObjectOutputStream.cs new file mode 100644 index 0000000000..97f3a2cfd2 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ObjectOutputStream.cs @@ -0,0 +1,19 @@ +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + internal class ObjectOutputStream : OutputStream + { + private BinaryWriter _bw; + + public ObjectOutputStream (OutputStream os) + { + _bw = new BinaryWriter (os.GetWrappedStream ()); + } + + public virtual void WriteInt (int i) + { + _bw.Write (i); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/OutputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/OutputStream.cs new file mode 100644 index 0000000000..0e6189f0cb --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/OutputStream.cs @@ -0,0 +1,86 @@ +using System; +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + public class OutputStream : IDisposable + { + protected Stream Wrapped; + + public static implicit operator OutputStream (Stream s) + { + return Wrap (s); + } + + public static implicit operator Stream (OutputStream s) + { + return s.GetWrappedStream (); + } + + public virtual void Close () + { + if (Wrapped != null) { + //Stream.`Close` method deleted + //Wrapped.Close (); + Wrapped.Dispose(); + } + } + + public void Dispose () + { + Close (); + } + + public virtual void Flush () + { + if (Wrapped != null) { + Wrapped.Flush (); + } + } + + internal Stream GetWrappedStream () + { + // Always create a wrapper stream (not directly Wrapped) since the subclass + // may be overriding methods that need to be called when used through the Stream class + return new WrappedSystemStream (this); + } + + static internal OutputStream Wrap (Stream s) + { + OutputStream stream = new OutputStream (); + stream.Wrapped = s; + return stream; + } + + public virtual void Write (int b) + { + if (Wrapped is WrappedSystemStream) + ((WrappedSystemStream)Wrapped).OutputStream.Write (b); + else { + if (Wrapped == null) + throw new NotImplementedException (); + Wrapped.WriteByte ((byte)b); + } + } + + public virtual void Write (byte[] b) + { + Write (b, 0, b.Length); + } + + public virtual void Write (byte[] b, int offset, int len) + { + if (Wrapped is WrappedSystemStream) + ((WrappedSystemStream)Wrapped).OutputStream.Write (b, offset, len); + else { + if (Wrapped != null) { + Wrapped.Write (b, offset, len); + } else { + for (int i = 0; i < len; i++) { + Write (b[i + offset]); + } + } + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/OutputStreamWriter.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/OutputStreamWriter.cs new file mode 100644 index 0000000000..6313b7c798 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/OutputStreamWriter.cs @@ -0,0 +1,20 @@ +using System.IO; +using System.Text; + +namespace SharpCifs.Util.Sharpen +{ + internal class OutputStreamWriter : StreamWriter + { + public OutputStreamWriter (OutputStream stream) : base(stream.GetWrappedStream ()) + { + } + + public OutputStreamWriter (OutputStream stream, string encoding) : base(stream.GetWrappedStream (), Extensions.GetEncoding (encoding)) + { + } + + public OutputStreamWriter (OutputStream stream, Encoding encoding) : base(stream.GetWrappedStream (), encoding) + { + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/PipedInputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/PipedInputStream.cs new file mode 100644 index 0000000000..d5004c988f --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/PipedInputStream.cs @@ -0,0 +1,172 @@ +using System; +using System.Threading; + +namespace SharpCifs.Util.Sharpen +{ + internal class PipedInputStream : InputStream + { + private byte[] _oneBuffer; + public const int PipeSize = 1024; + + protected byte[] Buffer; + private bool _closed; + private ManualResetEvent _dataEvent; + private int _end; + private int _start; + private object _thisLock; + private bool _allowGrow = false; + + public int In { + get { return _start; } + set { _start = value; } + } + + public int Out { + get { return _end; } + set { _end = value; } + } + + public PipedInputStream () + { + _thisLock = new object (); + _dataEvent = new ManualResetEvent (false); + Buffer = new byte[PipeSize + 1]; + } + + public PipedInputStream (PipedOutputStream os): this () + { + os.Attach (this); + } + + public override void Close () + { + lock (_thisLock) { + _closed = true; + _dataEvent.Set (); + } + } + + public override int Available () + { + lock (_thisLock) { + if (_start <= _end) { + return (_end - _start); + } + return ((Buffer.Length - _start) + _end); + } + } + + public override int Read () + { + if (_oneBuffer == null) + _oneBuffer = new byte[1]; + if (Read (_oneBuffer, 0, 1) == -1) + return -1; + return _oneBuffer[0]; + } + + public override int Read (byte[] b, int offset, int len) + { + int length = 0; + do { + _dataEvent.WaitOne (); + lock (_thisLock) { + if (_closed && Available () == 0) { + return -1; + } + if (_start < _end) { + length = Math.Min (len, _end - _start); + Array.Copy (Buffer, _start, b, offset, length); + _start += length; + } else if (_start > _end) { + length = Math.Min (len, Buffer.Length - _start); + Array.Copy (Buffer, _start, b, offset, length); + len -= length; + _start = (_start + length) % Buffer.Length; + if (len > 0) { + int i = Math.Min (len, _end); + Array.Copy (Buffer, 0, b, offset + length, i); + _start += i; + length += i; + } + } + if (_start == _end && !_closed) { + _dataEvent.Reset (); + } + Monitor.PulseAll (_thisLock); + } + } while (length == 0); + return length; + } + + private int Allocate (int len) + { + int alen; + while ((alen = TryAllocate (len)) == 0) { + // Wait until somebody reads data + try { + Monitor.Wait (_thisLock); + } catch { + _closed = true; + _dataEvent.Set (); + throw; + } + } + return alen; + } + + int TryAllocate (int len) + { + int free; + if (_start <= _end) { + free = (Buffer.Length - _end) + _start; + } else { + free = _start - _end; + } + if (free <= len) { + if (!_allowGrow) + return free > 0 ? free - 1 : 0; + int sizeInc = (len - free) + 1; + byte[] destinationArray = new byte[Buffer.Length + sizeInc]; + if (_start <= _end) { + Array.Copy (Buffer, _start, destinationArray, _start, _end - _start); + } else { + Array.Copy (Buffer, 0, destinationArray, 0, _end); + Array.Copy (Buffer, _start, destinationArray, _start + sizeInc, Buffer.Length - _start); + _start += sizeInc; + } + Buffer = destinationArray; + } + return len; + } + + internal void Write (int b) + { + lock (_thisLock) { + Allocate (1); + Buffer[_end] = (byte)b; + _end = (_end + 1) % Buffer.Length; + _dataEvent.Set (); + } + } + + internal void Write (byte[] b, int offset, int len) + { + do { + lock (_thisLock) { + int alen = Allocate (len); + int length = Math.Min (Buffer.Length - _end, alen); + Array.Copy (b, offset, Buffer, _end, length); + _end = (_end + length) % Buffer.Length; + if (length < alen) { + Array.Copy (b, offset + length, Buffer, 0, alen - length); + _end += alen - length; + } + _dataEvent.Set (); + len -= alen; + offset += alen; + } + } while (len > 0); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/PipedOutputStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/PipedOutputStream.cs new file mode 100644 index 0000000000..4c46f1ec00 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/PipedOutputStream.cs @@ -0,0 +1,37 @@ +namespace SharpCifs.Util.Sharpen +{ + internal class PipedOutputStream : OutputStream + { + PipedInputStream _ips; + + public PipedOutputStream () + { + } + + public PipedOutputStream (PipedInputStream iss) : this() + { + Attach (iss); + } + + public override void Close () + { + _ips.Close (); + base.Close (); + } + + internal void Attach (PipedInputStream iss) + { + _ips = iss; + } + + public override void Write (int b) + { + _ips.Write (b); + } + + public override void Write (byte[] b, int offset, int len) + { + _ips.Write (b, offset, len); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/PrintWriter.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/PrintWriter.cs new file mode 100644 index 0000000000..c366aa6659 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/PrintWriter.cs @@ -0,0 +1,231 @@ +using System; +using System.IO; +using System.Text; + +namespace SharpCifs.Util.Sharpen +{ + public class PrintWriter : TextWriter + { + TextWriter _writer; + private FileStream _stream; + + public PrintWriter (FilePath path) + { + //Stream(string path) constructor deleted + _stream = new FileStream(path, FileMode.Create, FileAccess.ReadWrite); + _writer = new StreamWriter (_stream); + } + + public PrintWriter (TextWriter other) + { + _writer = other; + } + + public override Encoding Encoding { + get { return _writer.Encoding; } + } + + public void Close() // remove `override` + { + //Stream.`Close` method deleted + //_writer.Close (); + _writer.Dispose(); + _stream.Dispose(); + } + + public override void Flush () + { + _writer.Flush (); + } + + public override IFormatProvider FormatProvider { + get { + return _writer.FormatProvider; + } + } + + public override string NewLine { + get { + return _writer.NewLine; + } + set { + _writer.NewLine = value; + } + } + + public override void Write (char[] buffer, int index, int count) + { + _writer.Write (buffer, index, count); + } + + public override void Write (char[] buffer) + { + _writer.Write (buffer); + } + + public void Write (string format, object arg0, object arg1, object arg2) + { + _writer.Write (format, arg0, arg1, arg2); + } + + public override void Write (string format, object arg0, object arg1) + { + _writer.Write (format, arg0, arg1); + } + + public override void Write (string format, object arg0) + { + _writer.Write (format, arg0); + } + + public override void Write (string format, params object[] arg) + { + _writer.Write (format, arg); + } + + public override void WriteLine (char[] buffer, int index, int count) + { + _writer.WriteLine (buffer, index, count); + } + + public override void WriteLine (char[] buffer) + { + _writer.WriteLine (buffer); + } + + public void WriteLine (string format, object arg0, object arg1, object arg2) + { + _writer.WriteLine (format, arg0, arg1, arg2); + } + + public override void WriteLine (string format, object arg0, object arg1) + { + _writer.WriteLine (format, arg0, arg1); + } + + public override void WriteLine (string format, object arg0) + { + _writer.WriteLine (format, arg0); + } + + public override void WriteLine (string format, params object[] arg) + { + _writer.WriteLine (format, arg); + } + + public override void WriteLine (ulong value) + { + _writer.WriteLine (value); + } + + public override void WriteLine (uint value) + { + _writer.WriteLine (value); + } + + public override void WriteLine (string value) + { + _writer.WriteLine (value); + } + + public override void WriteLine (float value) + { + _writer.WriteLine (value); + } + + public override void WriteLine (object value) + { + _writer.WriteLine (value); + } + + public override void WriteLine (long value) + { + _writer.WriteLine (value); + } + + public override void WriteLine (int value) + { + _writer.WriteLine (value); + } + + public override void WriteLine (double value) + { + _writer.WriteLine (value); + } + + public override void WriteLine (decimal value) + { + _writer.WriteLine (value); + } + + public override void WriteLine (char value) + { + _writer.WriteLine (value); + } + + public override void WriteLine (bool value) + { + _writer.WriteLine (value); + } + + public override void WriteLine () + { + _writer.WriteLine (); + } + + public override void Write (bool value) + { + _writer.Write (value); + } + + public override void Write (char value) + { + _writer.Write (value); + } + + public override void Write (decimal value) + { + _writer.Write (value); + } + + public override void Write (double value) + { + _writer.Write (value); + } + + public override void Write (int value) + { + _writer.Write (value); + } + + public override void Write (long value) + { + _writer.Write (value); + } + + public override void Write (object value) + { + _writer.Write (value); + } + + public override void Write (float value) + { + _writer.Write (value); + } + + public override void Write (string value) + { + _writer.Write (value); + } + + public override void Write (uint value) + { + _writer.Write (value); + } + + public override void Write (ulong value) + { + _writer.Write (value); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Properties.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Properties.cs new file mode 100644 index 0000000000..3d886ea87a --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Properties.cs @@ -0,0 +1,86 @@ +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + public class Properties + { + protected Hashtable _properties; + + public Properties() + { + _properties = new Hashtable(); + } + + public Properties(Properties defaultProp): this() + { + PutAll(defaultProp._properties); + } + + public void PutAll(Hashtable properties) + { + foreach (var key in properties.Keys) + { + //_properties.Add(key, properties[key]); + _properties.Put(key, properties[key]); + } + } + + public void SetProperty(object key, object value) + { + //_properties.Add(key, value); + _properties.Put(key, value); + } + + public object GetProperty(object key) + { + return _properties.Keys.Contains(key) ? _properties[key] : null; + } + + public object GetProperty(object key, object def) + { + /*if (_properties.ContainsKey(key)) + { + return _properties[key]; + } + return def;*/ + object value = _properties.Get(key); + + return value ?? def; + } + + public void Load(InputStream input) + { + StreamReader sr = new StreamReader(input); + while (!sr.EndOfStream) + { + string line = sr.ReadLine(); + + if (!string.IsNullOrEmpty(line)) + { + string[] tokens = line.Split('='); + //_properties.Add(tokens[0], tokens[1]); + _properties.Put(tokens[0], tokens[1]); + } + } + } + + public void Store(OutputStream output) + { + StreamWriter sw = new StreamWriter(output); + foreach (var key in _properties.Keys) + { + string line = string.Format("{0}={1}", key, _properties[key]); + sw.WriteLine(line); + } + } + + public void Store(TextWriter output) + { + foreach (var key in _properties.Keys) + { + string line = string.Format("{0}={1}", key, _properties[key]); + output.WriteLine(line); + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/RandomAccessFile.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/RandomAccessFile.cs new file mode 100644 index 0000000000..bf3596212f --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/RandomAccessFile.cs @@ -0,0 +1,87 @@ +using System; +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + public class RandomAccessFile + { + private FileStream _stream; + + public RandomAccessFile (FilePath file, string mode) : this(file.GetPath (), mode) + { + } + + public RandomAccessFile (string file, string mode) + { + if (mode.IndexOf ('w') != -1) + _stream = new FileStream (file, FileMode.OpenOrCreate, FileAccess.ReadWrite); + else + _stream = new FileStream (file, FileMode.Open, FileAccess.Read); + } + + public void Close () + { + //Stream.`Close` method deleted + //_stream.Close (); + _stream.Dispose(); + } + + public long GetFilePointer () + { + return _stream.Position; + } + + public long Length () + { + return _stream.Length; + } + + public int Read (byte[] buffer) + { + int r = _stream.Read (buffer, 0, buffer.Length); + return r > 0 ? r : -1; + } + + public int Read (byte[] buffer, int start, int size) + { + return _stream.Read (buffer, start, size); + } + + public void ReadFully (byte[] buffer, int start, int size) + { + while (size > 0) { + int num = _stream.Read (buffer, start, size); + if (num == 0) { + throw new EofException (); + } + size -= num; + start += num; + } + } + + public void Seek (long pos) + { + _stream.Position = pos; + } + + public void SetLength (long len) + { + _stream.SetLength (len); + } + + public void Write (int value) + { + _stream.Write (BitConverter.GetBytes (value), 0, 4); + } + + public void Write (byte[] buffer) + { + _stream.Write (buffer, 0, buffer.Length); + } + + public void Write (byte[] buffer, int start, int size) + { + _stream.Write (buffer, start, size); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ReentrantLock.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ReentrantLock.cs new file mode 100644 index 0000000000..aa34db9d05 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ReentrantLock.cs @@ -0,0 +1,22 @@ +using System.Threading; + +namespace SharpCifs.Util.Sharpen +{ + internal class ReentrantLock + { + public void Lock () + { + Monitor.Enter (this); + } + + public bool TryLock () + { + return Monitor.TryEnter (this); + } + + public void Unlock () + { + Monitor.Exit (this); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Reference.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Reference.cs new file mode 100644 index 0000000000..c7fbe9a488 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Reference.cs @@ -0,0 +1,7 @@ +namespace SharpCifs.Util.Sharpen +{ + internal abstract class Reference + { + public abstract T Get (); + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Runtime.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Runtime.cs new file mode 100644 index 0000000000..74ff16b1bb --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Runtime.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading; + +namespace SharpCifs.Util.Sharpen +{ + public class Runtime + { + private static Runtime _instance; + private List _shutdownHooks = new List (); + + internal void AddShutdownHook (IRunnable r) + { + ShutdownHook item = new ShutdownHook (); + item.Runnable = r; + _shutdownHooks.Add (item); + } + + internal int AvailableProcessors () + { + return Environment.ProcessorCount; + } + + public static long CurrentTimeMillis () + { + return DateTime.UtcNow.ToMillisecondsSinceEpoch (); + } + + static Hashtable _properties; + + public static Hashtable GetProperties () + { + if (_properties == null) { + _properties = new Hashtable (); + _properties ["jgit.fs.debug"] = "false"; + _properties["file.encoding"] = "UTF-8"; + if (Path.DirectorySeparatorChar != '\\') + _properties ["os.name"] = "Unix"; + else + _properties ["os.name"] = "Windows"; + } + return _properties; + } + + public static string GetProperty (string key) + { + if (GetProperties().Keys.Contains(key)) + { + return ((string)GetProperties()[key]); + } + return null; + } + + public static void SetProperty (string key, string value) + { + GetProperties () [key] = value; + } + + public static Runtime GetRuntime () + { + if (_instance == null) { + _instance = new Runtime (); + } + return _instance; + } + + public static int IdentityHashCode (object ob) + { + return RuntimeHelpers.GetHashCode (ob); + } + + internal long MaxMemory () + { + return int.MaxValue; + } + + private class ShutdownHook + { + public IRunnable Runnable; + + ~ShutdownHook () + { + Runnable.Run (); + } + } + + public static void DeleteCharAt (StringBuilder sb, int index) + { + sb.Remove (index, 1); + } + + public static byte[] GetBytesForString (string str) + { + return Encoding.UTF8.GetBytes (str); + } + + public static byte[] GetBytesForString (string str, string encoding) + { + return Encoding.GetEncoding (encoding).GetBytes (str); + } + + public static FieldInfo[] GetDeclaredFields (Type t) + { + throw new NotImplementedException("Type.GetFields not found on .NetStandard"); + //return t.GetFields (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + } + + public static void NotifyAll (object ob) + { + Monitor.PulseAll (ob); + } + + public static void Notify(object obj) + { + Monitor.Pulse(obj); + } + + public static void PrintStackTrace (Exception ex) + { + Console.WriteLine (ex); + } + + public static void PrintStackTrace (Exception ex, TextWriter tw) + { + tw.WriteLine (ex); + } + + public static string Substring (string str, int index) + { + return str.Substring (index); + } + + public static string Substring (string str, int index, int endIndex) + { + return str.Substring (index, endIndex - index); + } + + public static void Wait (object ob) + { + Monitor.Wait (ob); + } + + public static bool Wait (object ob, long milis) + { + return Monitor.Wait (ob, (int)milis); + } + + public static Type GetType (string name) + { + throw new NotImplementedException("AppDomain.CurrentDomain.GetAssemblies not found on .NetStandard"); + //foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies ()) { + // Type t = a.GetType (name); + // if (t != null) + // return t; + //} + //never used + //throw new InvalidOperationException ("Type not found: " + name); + } + + public static void SetCharAt (StringBuilder sb, int index, char c) + { + sb [index] = c; + } + + public static bool EqualsIgnoreCase (string s1, string s2) + { + return s1.Equals (s2, StringComparison.CurrentCultureIgnoreCase); + } + + internal static long NanoTime () + { + return Environment.TickCount * 1000 * 1000; + } + + internal static int CompareOrdinal (string s1, string s2) + { + return string.CompareOrdinal (s1, s2); + } + + public static string GetStringForBytes (byte[] chars) + { + return Encoding.UTF8.GetString (chars, 0, chars.Length); + } + + public static string GetStringForBytes (byte[] chars, string encoding) + { + return GetEncoding (encoding).GetString (chars, 0, chars.Length); + } + + public static string GetStringForBytes (byte[] chars, int start, int len) + { + return Encoding.UTF8.GetString (chars, start, len); + } + + public static string GetStringForBytes (byte[] chars, int start, int len, string encoding) + { + return GetEncoding (encoding).Decode (chars, start, len); + } + + public static Encoding GetEncoding (string name) + { + Encoding e = Encoding.GetEncoding (name.Replace ('_','-')); + if (e is UTF8Encoding) + return new UTF8Encoding (false, true); + return e; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/SimpleDateFormat.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/SimpleDateFormat.cs new file mode 100644 index 0000000000..35334b4f2a --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/SimpleDateFormat.cs @@ -0,0 +1,62 @@ +using System; +using System.Globalization; + +namespace SharpCifs.Util.Sharpen +{ + public class SimpleDateFormat : DateFormat + { + string _format; + + CultureInfo Culture { + get; set; + } + + bool Lenient { + get; set; + } + + public SimpleDateFormat (): this ("g") + { + } + + public SimpleDateFormat (string format): this (format, CultureInfo.CurrentCulture) + { + } + + public SimpleDateFormat (string format, CultureInfo c) + { + Culture = c; + this._format = format.Replace ("EEE", "ddd"); + this._format = this._format.Replace ("Z", "zzz"); + SetTimeZone (TimeZoneInfo.Local); + } + + public bool IsLenient () + { + return Lenient; + } + + public void SetLenient (bool lenient) + { + Lenient = lenient; + } + + public override DateTime Parse (string value) + { + if (IsLenient ()) + return DateTime.Parse (value); + return DateTime.ParseExact (value, _format, Culture); + } + + public override string Format (DateTime date) + { + date += GetTimeZone().BaseUtcOffset; + return date.ToString (_format); + } + + public string Format (long date) + { + return Extensions.MillisToDateTimeOffset (date, (int)GetTimeZone ().BaseUtcOffset.TotalMinutes).DateTime.ToString (_format); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/SocketEx.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/SocketEx.cs new file mode 100644 index 0000000000..4d06519498 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/SocketEx.cs @@ -0,0 +1,161 @@ +// SocketEx.cs implementation by J. Arturo +// +// 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 System.Net; +using System.Net.Sockets; +using System.Threading; + +namespace SharpCifs.Util.Sharpen +{ + public class SocketEx : Socket + { + private int _soTimeOut = -1; + + public int SoTimeOut + { + get + { + return _soTimeOut; + } + + set + { + if (value > 0) + { + _soTimeOut = value; + } + else + { + _soTimeOut = -1; + } + + } + } + + public SocketEx(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) + : base(addressFamily, socketType, protocolType) + { + + } + + public void Connect(IPEndPoint endPoint, int timeOut) + { + using (var evt = new ManualResetEventSlim(false)) + { + using (var args = new SocketAsyncEventArgs + { + RemoteEndPoint = endPoint + }) + { + args.Completed += delegate + { + evt.Set(); + }; + + ConnectAsync(args); + + if (!evt.Wait(timeOut)) + { + CancelConnectAsync(args); + throw new ConnectException("Can't connect to end point."); + } + if (args.SocketError != SocketError.Success) + { + throw new ConnectException("Can't connect to end point."); + } + } + } + } + + public void Bind2(EndPoint ep) + { + if (ep == null) + Bind(new IPEndPoint(IPAddress.Any, 0)); + else + Bind(ep); + } + + + public int Receive(byte[] buffer, int offset, int count) + { + using (var evt = new ManualResetEventSlim(false)) + { + using (var args = new SocketAsyncEventArgs + { + UserToken = this + }) + { + args.SetBuffer(buffer, offset, count); + + args.Completed += delegate + { + evt.Set(); + }; + + if (ReceiveAsync(args)) + { + if (!evt.Wait(_soTimeOut)) + { + throw new TimeoutException("No data received."); + } + } + + return args.BytesTransferred; + } + } + } + + public void Send(byte[] buffer, int offset, int length, EndPoint destination = null) + { + using (var evt = new ManualResetEventSlim(false)) + { + using (SocketAsyncEventArgs args = new SocketAsyncEventArgs + { + UserToken = this + }) + { + args.SetBuffer(buffer, offset, length); + + args.Completed += delegate + { + evt.Set(); + }; + + args.RemoteEndPoint = destination ?? RemoteEndPoint; + + + SendToAsync(args); + if (!evt.Wait(_soTimeOut)) + { + throw new TimeoutException("No data sent."); + } + } + } + } + + public InputStream GetInputStream() + { + return new NetworkStream(this); + } + + public OutputStream GetOutputStream() + { + return new NetworkStream(this); + } + + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/StringTokenizer.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/StringTokenizer.cs new file mode 100644 index 0000000000..74c14cff6c --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/StringTokenizer.cs @@ -0,0 +1,32 @@ +namespace SharpCifs.Util.Sharpen +{ + public class StringTokenizer + { + private string[] _tokens; + private int _pos; + + public StringTokenizer(string text, string delim) + { + _tokens = text.Split(delim); + } + + public int CountTokens() + { + return _tokens.Length; + } + + public string NextToken() + { + string value = _tokens[_pos]; + + _pos++; + + return value; + } + + public bool HasMoreTokens() + { + return _pos < _tokens.Length; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/SynchronizedList.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/SynchronizedList.cs new file mode 100644 index 0000000000..c105a8bab6 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/SynchronizedList.cs @@ -0,0 +1,106 @@ +using System.Collections; +using System.Collections.Generic; + +namespace SharpCifs.Util.Sharpen +{ + internal class SynchronizedList : IList + { + private IList _list; + + public SynchronizedList (IList list) + { + this._list = list; + } + + public int IndexOf (T item) + { + lock (_list) { + return _list.IndexOf (item); + } + } + + public void Insert (int index, T item) + { + lock (_list) { + _list.Insert (index, item); + } + } + + public void RemoveAt (int index) + { + lock (_list) { + _list.RemoveAt (index); + } + } + + void ICollection.Add (T item) + { + lock (_list) { + _list.Add (item); + } + } + + void ICollection.Clear () + { + lock (_list) { + _list.Clear (); + } + } + + bool ICollection.Contains (T item) + { + lock (_list) { + return _list.Contains (item); + } + } + + void ICollection.CopyTo (T[] array, int arrayIndex) + { + lock (_list) { + _list.CopyTo (array, arrayIndex); + } + } + + bool ICollection.Remove (T item) + { + lock (_list) { + return _list.Remove (item); + } + } + + IEnumerator IEnumerable.GetEnumerator () + { + return _list.GetEnumerator (); + } + + IEnumerator IEnumerable.GetEnumerator () + { + return _list.GetEnumerator (); + } + + public T this[int index] { + get { + lock (_list) { + return _list[index]; + } + } + set { + lock (_list) { + _list[index] = value; + } + } + } + + int ICollection.Count { + get { + lock (_list) { + return _list.Count; + } + } + } + + bool ICollection.IsReadOnly { + get { return _list.IsReadOnly; } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Thread.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Thread.cs new file mode 100644 index 0000000000..59f3df4699 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/Thread.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; + +namespace SharpCifs.Util.Sharpen +{ + public class Thread : IRunnable + { + private static ThreadGroup _defaultGroup = new ThreadGroup (); + private bool _interrupted; + private IRunnable _runnable; + private ThreadGroup _tgroup; + private System.Threading.Thread _thread; + + [ThreadStatic] + private static Thread _wrapperThread; + + public Thread () : this(null, null, null) + { + } + + public Thread (string name) : this (null, null, name) + { + } + + public Thread (ThreadGroup grp, string name) : this (null, grp, name) + { + } + + public Thread (IRunnable runnable): this (runnable, null, null) + { + } + + Thread (IRunnable runnable, ThreadGroup grp, string name) + { + _thread = new System.Threading.Thread (InternalRun); + + this._runnable = runnable ?? this; + _tgroup = grp ?? _defaultGroup; + _tgroup.Add (this); + if (name != null) + _thread.Name = name; + } + + private Thread (System.Threading.Thread t) + { + _thread = t; + _tgroup = _defaultGroup; + _tgroup.Add (this); + } + + public static Thread CurrentThread () + { + if (_wrapperThread == null) { + _wrapperThread = new Thread (System.Threading.Thread.CurrentThread); + } + return _wrapperThread; + } + + public string GetName () + { + return _thread.Name; + } + + public ThreadGroup GetThreadGroup () + { + return _tgroup; + } + + private void InternalRun () + { + _wrapperThread = this; + try { + _runnable.Run (); + } catch (Exception exception) { + Console.WriteLine (exception); + } finally { + _tgroup.Remove (this); + } + } + + public static void Yield () + { + } + + public void Interrupt () + { + lock (_thread) { + _interrupted = true; + //thread.Interrupt (); + + //TODO: implement CancellationToken + //_thread.Abort(); + throw new NotImplementedException("implement CancellationToken for thread"); + } + } + + public static bool Interrupted () + { + if (Thread._wrapperThread == null) { + return false; + } + Thread wrapperThread = Thread._wrapperThread; + lock (wrapperThread) { + bool interrupted = Thread._wrapperThread._interrupted; + Thread._wrapperThread._interrupted = false; + return interrupted; + } + } + + public bool IsAlive () + { + return _thread.IsAlive; + } + + public void Join () + { + _thread.Join (); + } + + public void Join (long timeout) + { + _thread.Join ((int)timeout); + } + + public virtual void Run () + { + } + + public void SetDaemon (bool daemon) + { + _thread.IsBackground = daemon; + } + + public void SetName (string name) + { + _thread.Name = name; + } + + public static void Sleep (long milis) + { + System.Threading.Thread.Sleep ((int)milis); + } + + public void Start () + { + _thread.Start (); + } + + public void Abort () + { + //TODO: implement CancellationToken + //_thread.Abort (); + throw new NotImplementedException("implement CancellationToken for thread"); + } + + } + + public class ThreadGroup + { + private List _threads = new List (); + + public ThreadGroup() + { + } + + public ThreadGroup (string name) + { + } + + internal void Add (Thread t) + { + lock (_threads) { + _threads.Add (t); + } + } + + internal void Remove (Thread t) + { + lock (_threads) { + _threads.Remove (t); + } + } + + public int Enumerate (Thread[] array) + { + lock (_threads) { + int count = Math.Min (array.Length, _threads.Count); + _threads.CopyTo (0, array, 0, count); + return count; + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadFactory.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadFactory.cs new file mode 100644 index 0000000000..7276c06a2c --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadFactory.cs @@ -0,0 +1,13 @@ +namespace SharpCifs.Util.Sharpen +{ + internal class ThreadFactory + { + public Thread NewThread (IRunnable r) + { + Thread t = new Thread (r); + t.SetDaemon (true); + t.Start (); + return t; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadPoolExecutor.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadPoolExecutor.cs new file mode 100644 index 0000000000..ef19b8bff5 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/ThreadPoolExecutor.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using ST = System.Threading; + +namespace SharpCifs.Util.Sharpen +{ + class ThreadPoolExecutor + { + ThreadFactory _tf; + int _corePoolSize; + int _maxPoolSize; + List _pool = new List (); + int _runningThreads; + int _freeThreads; + bool _shutdown; + Queue _pendingTasks = new Queue (); + + public ThreadPoolExecutor (int corePoolSize, ThreadFactory factory) + { + this._corePoolSize = corePoolSize; + _maxPoolSize = corePoolSize; + _tf = factory; + } + + public void SetMaximumPoolSize (int size) + { + _maxPoolSize = size; + } + + public bool IsShutdown () + { + return _shutdown; + } + + public virtual bool IsTerminated () + { + lock (_pendingTasks) { + return _shutdown && _pendingTasks.Count == 0; + } + } + + public virtual bool IsTerminating () + { + lock (_pendingTasks) { + return _shutdown && !IsTerminated (); + } + } + + public int GetCorePoolSize () + { + return _corePoolSize; + } + + public void PrestartAllCoreThreads () + { + lock (_pendingTasks) { + while (_runningThreads < _corePoolSize) + StartPoolThread (); + } + } + + public void SetThreadFactory (ThreadFactory f) + { + _tf = f; + } + + public void Execute (IRunnable r) + { + InternalExecute (r, true); + } + + internal void InternalExecute (IRunnable r, bool checkShutdown) + { + lock (_pendingTasks) { + if (_shutdown && checkShutdown) + throw new InvalidOperationException (); + if (_runningThreads < _corePoolSize) { + StartPoolThread (); + } + else if (_freeThreads > 0) { + _freeThreads--; + } + else if (_runningThreads < _maxPoolSize) { + StartPoolThread (); + } + _pendingTasks.Enqueue (r); + ST.Monitor.PulseAll (_pendingTasks); + } + } + + void StartPoolThread () + { + _runningThreads++; + _pool.Add (_tf.NewThread (new RunnableAction (RunPoolThread))); + } + + public void RunPoolThread () + { + while (!IsTerminated ()) { + try { + IRunnable r = null; + lock (_pendingTasks) { + _freeThreads++; + while (!IsTerminated () && _pendingTasks.Count == 0) + ST.Monitor.Wait (_pendingTasks); + if (IsTerminated ()) + break; + r = _pendingTasks.Dequeue (); + } + if (r != null) + r.Run (); + } + //supress all errors, anyway + //catch (ST.ThreadAbortException) { + // // Do not catch a thread abort. If we've been aborted just let the thread die. + // // Currently reseting an abort which was issued because the appdomain is being + // // torn down results in the process living forever and consuming 100% cpu time. + // return; + //} + catch { + } + } + } + + public virtual void Shutdown () + { + lock (_pendingTasks) { + _shutdown = true; + ST.Monitor.PulseAll (_pendingTasks); + } + } + + public virtual List ShutdownNow () + { + lock (_pendingTasks) { + _shutdown = true; + foreach (var t in _pool) { + try { + t.Abort (); + } catch {} + } + _pool.Clear (); + _freeThreads = 0; + _runningThreads = 0; + var res = new List (_pendingTasks); + _pendingTasks.Clear (); + return res; + } + } + } + + class RunnableAction: IRunnable + { + Action _action; + + public RunnableAction (Action a) + { + _action = a; + } + + public void Run () + { + _action (); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/WrappedSystemStream.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/WrappedSystemStream.cs new file mode 100644 index 0000000000..ef2993fa61 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Sharpen/WrappedSystemStream.cs @@ -0,0 +1,139 @@ +using System; +using System.IO; + +namespace SharpCifs.Util.Sharpen +{ + internal class WrappedSystemStream : Stream + { + private InputStream _ist; + private OutputStream _ost; + int _position; + int _markedPosition; + + public WrappedSystemStream (InputStream ist) + { + this._ist = ist; + } + + public WrappedSystemStream (OutputStream ost) + { + this._ost = ost; + } + + public InputStream InputStream { + get { return _ist; } + } + + public OutputStream OutputStream { + get { return _ost; } + } + + public void Close() //remove `override` + { + if (_ist != null) { + //Stream.`Close` method deleted + //_ist.Close (); + _ist.Dispose(); + } + if (_ost != null) { + //Stream.`Close` method deleted + //_ost.Close (); + _ost.Dispose(); + } + } + + public override void Flush () + { + _ost.Flush (); + } + + public override int Read (byte[] buffer, int offset, int count) + { + int res = _ist.Read (buffer, offset, count); + if (res != -1) { + _position += res; + return res; + } + return 0; + } + + public override int ReadByte () + { + int res = _ist.Read (); + if (res != -1) + _position++; + return res; + } + + public override long Seek (long offset, SeekOrigin origin) + { + if (origin == SeekOrigin.Begin) + Position = offset; + else if (origin == SeekOrigin.Current) + Position = Position + offset; + else if (origin == SeekOrigin.End) + Position = Length + offset; + return Position; + } + + public override void SetLength (long value) + { + throw new NotSupportedException (); + } + + public override void Write (byte[] buffer, int offset, int count) + { + _ost.Write (buffer, offset, count); + _position += count; + } + + public override void WriteByte (byte value) + { + _ost.Write (value); + _position++; + } + + public override bool CanRead { + get { return (_ist != null); } + } + + public override bool CanSeek { + get { return true; } + } + + public override bool CanWrite { + get { return (_ost != null); } + } + + public override long Length { + get { return _ist.Length; } + } + + internal void OnMark (int nb) + { + _markedPosition = _position; + _ist.Mark (nb); + } + + public override long Position { + get + { + if (_ist != null && _ist.CanSeek ()) + return _ist.Position; + return _position; + } + set + { + if (value == _position) + return; + if (value == _markedPosition) + _ist.Reset (); + else if (_ist != null && _ist.CanSeek ()) { + _ist.Position = value; + } + else + throw new NotSupportedException (); + } + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Transport/Request.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Transport/Request.cs new file mode 100644 index 0000000000..6e0c3fc7ba --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Transport/Request.cs @@ -0,0 +1,22 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Util.Transport +{ + public interface IRequest + { + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Transport/Response.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Transport/Response.cs new file mode 100644 index 0000000000..702fea9187 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Transport/Response.cs @@ -0,0 +1,25 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 +namespace SharpCifs.Util.Transport +{ + public abstract class Response + { + public long Expiration; + + public bool IsReceived; + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Transport/Transport.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Transport/Transport.cs new file mode 100644 index 0000000000..b02936ca61 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Transport/Transport.cs @@ -0,0 +1,454 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using SharpCifs.Smb; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Util.Transport +{ + /// + /// This class simplifies communication for protocols that support + /// multiplexing requests. + /// + /// + /// This class simplifies communication for protocols that support + /// multiplexing requests. It encapsulates a stream and some protocol + /// knowledge (provided by a concrete subclass) so that connecting, + /// disconnecting, sending, and receiving can be syncronized + /// properly. Apparatus is provided to send and receive requests + /// concurrently. + /// + public abstract class Transport : IRunnable + { + internal static int Id; + + //internal static LogStream log = LogStream.GetInstance(); + + public LogStream Log + { + get + { + return LogStream.GetInstance(); + } + } + + /// + public static int Readn(InputStream @in, byte[] b, int off, int len) + { + int i = 0; + int n = -5; + while (i < len) + { + n = @in.Read(b, off + i, len - i); + if (n <= 0) + { + break; + } + i += n; + } + return i; + } + + internal int State; + + internal string Name = "Transport" + Id++; + + internal Thread Thread; + + internal TransportException Te; + + protected internal Hashtable ResponseMap = new Hashtable(); + + /// + protected internal abstract void MakeKey(ServerMessageBlock request); + + /// + protected internal abstract ServerMessageBlock PeekKey(); + + /// + protected internal abstract void DoSend(ServerMessageBlock request); + + /// + protected internal abstract void DoRecv(Response response); + + /// + protected internal abstract void DoSkip(); + + /// + public virtual void Sendrecv(ServerMessageBlock request, Response response, long timeout) + { + lock (this) + { + MakeKey(request); + response.IsReceived = false; + try + { + ResponseMap.Put(request, response); + DoSend(request); + response.Expiration = Runtime.CurrentTimeMillis() + timeout; + while (!response.IsReceived) + { + Runtime.Wait(this, timeout); + timeout = response.Expiration - Runtime.CurrentTimeMillis(); + if (timeout <= 0) + { + throw new TransportException(Name + " timedout waiting for response to " + request + ); + } + } + } + catch (IOException ioe) + { + if (Log.Level > 2) + { + Runtime.PrintStackTrace(ioe, Log); + } + try + { + Disconnect(true); + } + catch (IOException ioe2) + { + Runtime.PrintStackTrace(ioe2, Log); + } + throw; + } + catch (Exception ie) + { + throw new TransportException(ie); + } + finally + { + //Sharpen.Collections.Remove(response_map, request); + ResponseMap.Remove(request); + } + } + } + + private void Loop() + { + while (Thread == Thread.CurrentThread()) + { + try + { + ServerMessageBlock key = PeekKey(); + if (key == null) + { + throw new IOException("end of stream"); + } + + + lock (this) + { + Response response = (Response)ResponseMap.Get(key); + if (response == null) + { + if (Log.Level >= 4) + { + Log.WriteLine("Invalid key, skipping message"); + } + DoSkip(); + } + else + { + DoRecv(response); + response.IsReceived = true; + Runtime.NotifyAll(this); + } + } + } + catch (Exception ex) + { + string msg = ex.Message; + bool timeout = msg != null && msg.Equals("Read timed out"); + bool hard = timeout == false; + if (!timeout && Log.Level >= 3) + { + Runtime.PrintStackTrace(ex, Log); + } + try + { + Disconnect(hard); + } + catch (IOException ioe) + { + Runtime.PrintStackTrace(ioe, Log); + } + } + } + } + + /// + protected internal abstract void DoConnect(); + + /// + protected internal abstract void DoDisconnect(bool hard); + + /// + public virtual void Connect(long timeout) + { + lock (this) + { + try + { + switch (State) + { + case 0: + { + break; + } + + case 3: + { + return; + } + + case 4: + { + // already connected + State = 0; + throw new TransportException("Connection in error", Te); + } + + default: + { + //TransportException te = new TransportException("Invalid state: " + state); + State = 0; + throw new TransportException("Invalid state: " + State); + } + } + State = 1; + Te = null; + Thread = new Thread(this); + Thread.SetDaemon(true); + lock (Thread) + { + Thread.Start(); + Runtime.Wait(Thread, timeout); + switch (State) + { + case 1: + { + State = 0; + Thread = null; + throw new TransportException("Connection timeout"); + } + + case 2: + { + if (Te != null) + { + State = 4; + Thread = null; + throw Te; + } + State = 3; + return; + } + } + } + } + catch (Exception ie) + { + State = 0; + Thread = null; + throw new TransportException(ie); + } + finally + { + if (State != 0 && State != 3 && State != 4) + { + if (Log.Level >= 1) + { + Log.WriteLine("Invalid state: " + State); + } + State = 0; + Thread = null; + } + } + } + } + + /// + public virtual void Disconnect(bool hard) + { + + if (hard) + { + IOException ioe = null; + switch (State) + { + case 0: + { + return; + } + + case 2: + { + hard = true; + goto case 3; + } + + case 3: + { + if (ResponseMap.Count != 0 && !hard) + { + break; + } + try + { + DoDisconnect(hard); + } + catch (IOException ioe0) + { + ioe = ioe0; + } + goto case 4; + } + + case 4: + { + Thread = null; + State = 0; + break; + } + + default: + { + if (Log.Level >= 1) + { + Log.WriteLine("Invalid state: " + State); + } + Thread = null; + State = 0; + break; + } + } + if (ioe != null) + { + throw ioe; + } + + return; + } + + lock (this) + { + IOException ioe = null; + switch (State) + { + case 0: + { + return; + } + + case 2: + { + hard = true; + goto case 3; + } + + case 3: + { + if (ResponseMap.Count != 0 && !hard) + { + break; + } + try + { + DoDisconnect(hard); + } + catch (IOException ioe0) + { + ioe = ioe0; + } + goto case 4; + } + + case 4: + { + Thread = null; + State = 0; + break; + } + + default: + { + if (Log.Level >= 1) + { + Log.WriteLine("Invalid state: " + State); + } + Thread = null; + State = 0; + break; + } + } + if (ioe != null) + { + throw ioe; + } + } + } + + public virtual void Run() + { + Thread runThread = Thread.CurrentThread(); + Exception ex0 = null; + try + { + DoConnect(); + } + catch (Exception ex) + { + ex0 = ex; + // Defer to below where we're locked + return; + } + finally + { + lock (runThread) + { + if (runThread != Thread) + { + if (ex0 != null) + { + if (Log.Level >= 2) + { + Runtime.PrintStackTrace(ex0, Log); + } + } + //return; + } + if (ex0 != null) + { + Te = new TransportException(ex0); + } + State = 2; + // run connected + Runtime.Notify(runThread); + } + } + Loop(); + } + + public override string ToString() + { + return Name; + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifs/Util/Transport/TransportException.cs b/Emby.Common.Implementations/IO/SharpCifs/Util/Transport/TransportException.cs new file mode 100644 index 0000000000..bd04551976 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifs/Util/Transport/TransportException.cs @@ -0,0 +1,63 @@ +// This code is derived from jcifs smb client library +// Ported by J. Arturo +// +// 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 System.IO; +using SharpCifs.Util.Sharpen; + +namespace SharpCifs.Util.Transport +{ + + public class TransportException : IOException + { + private Exception _rootCause; + + public TransportException() + { + } + + public TransportException(string msg) : base(msg) + { + } + + public TransportException(Exception rootCause) + { + this._rootCause = rootCause; + } + + public TransportException(string msg, Exception rootCause) : base(msg) + { + this._rootCause = rootCause; + } + + public virtual Exception GetRootCause() + { + return _rootCause; + } + + public override string ToString() + { + if (_rootCause != null) + { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + Runtime.PrintStackTrace(_rootCause, pw); + return base.ToString() + "\n" + sw; + } + return base.ToString(); + } + } +} diff --git a/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs b/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs new file mode 100644 index 0000000000..fb32669f14 --- /dev/null +++ b/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs @@ -0,0 +1,542 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SharpCifs.Smb; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.System; + +namespace Emby.Common.Implementations.IO +{ + public class SharpCifsFileSystem + { + private readonly MediaBrowser.Model.System.OperatingSystem _operatingSystem; + + public SharpCifsFileSystem(MediaBrowser.Model.System.OperatingSystem operatingSystem) + { + _operatingSystem = operatingSystem; + } + + public bool IsEnabledForPath(string path) + { + if (_operatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows) + { + return false; + } + + return path.StartsWith("smb://", StringComparison.OrdinalIgnoreCase) || IsUncPath(path); + } + + public FileSystemMetadata GetFileSystemInfo(string path) + { + var file = CreateSmbFile(path); + return ToMetadata(file); + } + + public FileSystemMetadata GetFileInfo(string path) + { + var file = CreateSmbFile(path); + return ToMetadata(file, false); + } + + public FileSystemMetadata GetDirectoryInfo(string path) + { + var file = CreateSmbFile(path); + return ToMetadata(file, true); + } + + private bool IsUncPath(string path) + { + return path.StartsWith("\\\\", StringComparison.OrdinalIgnoreCase); + } + + private string GetReturnPath(SmbFile file) + { + return file.GetCanonicalPath(); + //return file.GetPath(); + } + + private string ConvertUncToSmb(string path) + { + if (IsUncPath(path)) + { + path = path.Replace('\\', '/'); + path = "smb:" + path; + } + return path; + } + + private string AddAuthentication(string path) + { + return path; + } + + private SmbFile CreateSmbFile(string path) + { + path = ConvertUncToSmb(path); + path = AddAuthentication(path); + + return new SmbFile(path); + } + + DateTime baseDate = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + private FileSystemMetadata ToMetadata(SmbFile info, bool? isDirectory = null) + { + var result = new FileSystemMetadata(); + + result.Exists = info.Exists(); + result.FullName = GetReturnPath(info); + result.Extension = Path.GetExtension(result.FullName); + result.Name = info.GetName(); + + if (result.Exists) + { + result.IsDirectory = info.IsDirectory(); + result.IsHidden = info.IsHidden(); + + result.IsReadOnly = !info.CanWrite(); + + if (info.IsFile()) + { + result.Length = info.Length(); + result.DirectoryName = info.GetParent(); + } + + result.CreationTimeUtc = baseDate.AddMilliseconds(info.CreateTime()); + result.LastWriteTimeUtc = baseDate.AddMilliseconds(info.GetLastModified()); + } + else + { + if (isDirectory.HasValue) + { + result.IsDirectory = isDirectory.Value; + } + } + + return result; + } + + public void SetHidden(string path, bool isHidden) + { + var file = CreateSmbFile(path); + + var isCurrentlyHidden = file.IsHidden(); + + if (isCurrentlyHidden && !isHidden) + { + file.SetAttributes(file.GetAttributes() & ~SmbFile.AttrReadonly); + } + else if (!isCurrentlyHidden && isHidden) + { + file.SetAttributes(file.GetAttributes() | SmbFile.AttrReadonly); + } + } + + public void SetReadOnly(string path, bool isReadOnly) + { + var file = CreateSmbFile(path); + + var isCurrentlyReadOnly = !file.CanWrite(); + + if (isCurrentlyReadOnly && !isReadOnly) + { + file.SetReadWrite(); + } + else if (!isCurrentlyReadOnly && isReadOnly) + { + file.SetReadOnly(); + } + } + + public void DeleteFile(string path) + { + var file = CreateSmbFile(path); + + AssertFileExists(file, path); + + file.Delete(); + } + + public void DeleteDirectory(string path, bool recursive) + { + var file = CreateSmbFile(path); + + AssertDirectoryExists(file, path); + + file.Delete(); + } + + public void CreateDirectory(string path) + { + } + + public string[] ReadAllLines(string path) + { + var lines = new List(); + + using (var stream = OpenRead(path)) + { + using (var reader = new StreamReader(stream)) + { + while (!reader.EndOfStream) + { + lines.Add(reader.ReadLine()); + } + } + } + + return lines.ToArray(); + } + + public void WriteAllLines(string path, IEnumerable lines) + { + using (var stream = GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None)) + { + using (var writer = new StreamWriter(stream)) + { + foreach (var line in lines) + { + writer.WriteLine(line); + } + } + } + } + + private void AssertFileExists(SmbFile file, string path) + { + if (!file.Exists()) + { + throw new FileNotFoundException("File not found.", path); + } + } + + private void AssertDirectoryExists(SmbFile file, string path) + { + if (!file.Exists()) + { + throw new FileNotFoundException("File not found.", path); + } + } + + public Stream OpenRead(string path) + { + var file = CreateSmbFile(path); + + AssertFileExists(file, path); + + return file.GetInputStream(); + } + + private Stream OpenWrite(string path) + { + var file = CreateSmbFile(path); + + AssertFileExists(file, path); + + return file.GetInputStream(); + } + + public void CopyFile(string source, string target, bool overwrite) + { + if (string.Equals(source, target, StringComparison.Ordinal)) + { + throw new ArgumentException("Cannot CopyFile when source and target are the same"); + } + + using (var input = OpenRead(source)) + { + using (var output = GetFileStream(target, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None)) + { + input.CopyTo(output); + } + } + } + + public void MoveFile(string source, string target) + { + if (string.Equals(source, target, StringComparison.Ordinal)) + { + throw new ArgumentException("Cannot MoveFile when source and target are the same"); + } + + using (var input = OpenRead(source)) + { + using (var output = GetFileStream(target, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None)) + { + input.CopyTo(output); + } + } + + DeleteFile(source); + } + + public void MoveDirectory(string source, string target) + { + throw new NotImplementedException(); + } + + public bool DirectoryExists(string path) + { + var dir = CreateSmbFile(path); + + return dir.Exists() && dir.IsDirectory(); + } + + public bool FileExists(string path) + { + var file = CreateSmbFile(path); + return file.Exists(); + } + + public string ReadAllText(string path, Encoding encoding) + { + using (var stream = OpenRead(path)) + { + using (var reader = new StreamReader(stream, encoding)) + { + return reader.ReadToEnd(); + } + } + } + + public Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share) + { + if (mode == FileOpenMode.OpenOrCreate) + { + var file = CreateSmbFile(path); + if (!file.Exists()) + { + file.CreateNewFile(); + } + + mode = FileOpenMode.Open; + } + + if (mode == FileOpenMode.CreateNew) + { + var file = CreateSmbFile(path); + if (file.Exists()) + { + throw new IOException("File already exists"); + } + + file.CreateNewFile(); + + mode = FileOpenMode.Open; + } + + if (mode == FileOpenMode.Create) + { + var file = CreateSmbFile(path); + if (file.Exists()) + { + if (file.IsHidden()) + { + throw new UnauthorizedAccessException(string.Format("File {0} already exists and is hidden", path)); + } + + file.Delete(); + file.CreateNewFile(); + } + else + { + file.CreateNewFile(); + } + + mode = FileOpenMode.Open; + } + + if (mode == FileOpenMode.Open) + { + if (access == FileAccessMode.Read) + { + return OpenRead(path); + } + if (access == FileAccessMode.Write) + { + return OpenWrite(path); + } + throw new NotImplementedException(); + } + throw new NotImplementedException(); + } + + public void WriteAllBytes(string path, byte[] bytes) + { + using (var stream = GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None)) + { + stream.Write(bytes, 0, bytes.Length); + } + } + + public void WriteAllText(string path, string text) + { + using (var stream = GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None)) + { + using (var writer = new StreamWriter(stream)) + { + writer.Write(text); + } + } + } + + public void WriteAllText(string path, string text, Encoding encoding) + { + using (var stream = GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None)) + { + using (var writer = new StreamWriter(stream, encoding)) + { + writer.Write(text); + } + } + } + + public string ReadAllText(string path) + { + using (var stream = OpenRead(path)) + { + using (var reader = new StreamReader(stream)) + { + return reader.ReadToEnd(); + } + } + } + + public byte[] ReadAllBytes(string path) + { + using (var stream = OpenRead(path)) + { + using (var ms = new MemoryStream()) + { + stream.CopyTo(ms); + ms.Position = 0; + return ms.ToArray(); + } + } + } + + public IEnumerable GetDirectories(string path, bool recursive = false) + { + var dir = CreateSmbFile(path); + AssertDirectoryExists(dir, path); + + var list = ListFiles(dir, recursive); + + foreach (var file in list) + { + if (file.IsDirectory()) + { + yield return ToMetadata(file); + } + } + } + + public IEnumerable GetFiles(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) + { + var dir = CreateSmbFile(path); + AssertDirectoryExists(dir, path); + + var list = ListFiles(dir, recursive); + + foreach (var file in list) + { + if (file.IsFile()) + { + var filePath = GetReturnPath(file); + var extension = Path.GetExtension(filePath); + + if (extensions == null || extensions.Length == 0 || extensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + { + yield return ToMetadata(file); + } + } + } + } + + public IEnumerable GetFileSystemEntries(string path, bool recursive = false) + { + var dir = CreateSmbFile(path); + AssertDirectoryExists(dir, path); + + var list = ListFiles(dir, recursive); + + foreach (var file in list) + { + yield return ToMetadata(file); + } + } + + public IEnumerable GetFileSystemEntryPaths(string path, bool recursive = false) + { + var dir = CreateSmbFile(path); + AssertDirectoryExists(dir, path); + + var list = ListFiles(dir, recursive); + + foreach (var file in list) + { + yield return GetReturnPath(file); + } + } + + public IEnumerable GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) + { + var dir = CreateSmbFile(path); + AssertDirectoryExists(dir, path); + + var list = ListFiles(dir, recursive); + + foreach (var file in list) + { + if (file.IsFile()) + { + var filePath = GetReturnPath(file); + var extension = Path.GetExtension(filePath); + + if (extensions == null || extensions.Length == 0 || extensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + { + yield return filePath; + } + } + } + } + + public IEnumerable GetDirectoryPaths(string path, bool recursive = false) + { + var dir = CreateSmbFile(path); + AssertDirectoryExists(dir, path); + + var list = ListFiles(dir, recursive); + + foreach (var file in list) + { + if (file.IsDirectory()) + { + yield return GetReturnPath(file); + } + } + } + + private IEnumerable ListFiles(SmbFile dir, bool recursive) + { + var list = dir.ListFiles(); + + foreach (var file in list) + { + yield return file; + + if (recursive && file.IsDirectory()) + { + foreach (var subFile in ListFiles(file, recursive)) + { + yield return subFile; + } + } + } + } + } +} diff --git a/Emby.Server.Core/IO/LibraryMonitor.cs b/Emby.Server.Core/IO/LibraryMonitor.cs index e1e3186c3b..ae7b66597c 100644 --- a/Emby.Server.Core/IO/LibraryMonitor.cs +++ b/Emby.Server.Core/IO/LibraryMonitor.cs @@ -166,7 +166,11 @@ namespace Emby.Server.Core.IO private void Restart() { Stop(); - Start(); + + if (!_disposed) + { + Start(); + } } private bool IsLibraryMonitorEnabaled(BaseItem item) @@ -589,11 +593,13 @@ namespace Emby.Server.Core.IO } } + private bool _disposed; /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { + _disposed = true; Dispose(true); GC.SuppressFinalize(this); } diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs index e791503ab0..59e31debdf 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -353,24 +353,7 @@ namespace MediaBrowser.Model.IO // permission is required. If the file is opened with FileAccess.ReadWrite, both // System.Security.Permissions.FileIOPermissionAccess.Read and System.Security.Permissions.FileIOPermissionAccess.Write // permissions are required. - OpenOrCreate = 4, - // - // Summary: - // Specifies that the operating system should open an existing file. When the file - // is opened, it should be truncated so that its size is zero bytes. This requires - // System.Security.Permissions.FileIOPermissionAccess.Write permission. Attempts - // to read from a file opened with FileMode.Truncate cause an System.ArgumentException - // exception. - Truncate = 5, - // - // Summary: - // Opens the file if it exists and seeks to the end of the file, or creates a new - // file. This requires System.Security.Permissions.FileIOPermissionAccess.Append - // permission. FileMode.Append can be used only in conjunction with FileAccess.Write. - // Trying to seek to a position before the end of the file throws an System.IO.IOException - // exception, and any attempt to read fails and throws a System.NotSupportedException - // exception. - Append = 6 + OpenOrCreate = 4 } public enum FileAccessMode @@ -384,11 +367,7 @@ namespace MediaBrowser.Model.IO // Summary: // Write access to the file. Data can be written to the file. Combine with Read // for read/write access. - Write = 2, - // - // Summary: - // Read and write access to the file. Data can be written to and read from the file. - ReadWrite = 3 + Write = 2 } public enum FileShareMode