Преглед изворни кода

SMB1Client: Additional client functions implemented

Tal Aloni пре 7 година
родитељ
комит
928bb59c90
3 измењених фајлова са 227 додато и 2 уклоњено
  1. 25 2
      SMBLibrary/Client/SMB1Client.cs
  2. 201 0
      SMBLibrary/Client/SMB1FileStore.cs
  3. 1 0
      SMBLibrary/SMBLibrary.csproj

+ 25 - 2
SMBLibrary/Client/SMB1Client.cs

@@ -195,7 +195,7 @@ namespace SMBLibrary.Client
                 SessionSetupAndXRequestExtended request = new SessionSetupAndXRequestExtended();
                 request.MaxBufferSize = MaxBufferSize;
                 request.MaxMpxCount = MaxMpxCount;
-                request.Capabilities = Capabilities.Unicode | Capabilities.NTStatusCode;
+                request.Capabilities = Capabilities.Unicode | Capabilities.NTStatusCode | Capabilities.LargeRead | Capabilities.LargeWrite;
                 request.SecurityBlob = NTLMAuthenticationHelper.GetNegotiateMessage(m_securityBlob, domainName, authenticationMethod);
                 TrySendMessage(request);
                 
@@ -209,7 +209,7 @@ namespace SMBLibrary.Client
                         request = new SessionSetupAndXRequestExtended();
                         request.MaxBufferSize = MaxBufferSize;
                         request.MaxMpxCount = MaxMpxCount;
-                        request.Capabilities = Capabilities.Unicode | Capabilities.NTStatusCode | Capabilities.ExtendedSecurity;
+                        request.Capabilities = Capabilities.Unicode | Capabilities.NTStatusCode | Capabilities.LargeRead | Capabilities.LargeWrite | Capabilities.ExtendedSecurity;
 
                         request.SecurityBlob = NTLMAuthenticationHelper.GetAuthenticateMessage(response.SecurityBlob, domainName, userName, password, authenticationMethod, out m_sessionKey);
                         TrySendMessage(request);
@@ -229,6 +229,29 @@ namespace SMBLibrary.Client
             }
         }
 
+        public SMB1FileStore TreeConnect(string shareName, ServiceName serviceName, out NTStatus status)
+        {
+            TreeConnectAndXRequest request = new TreeConnectAndXRequest();
+            request.Path = shareName;
+            request.Service = serviceName;
+            TrySendMessage(request);
+            SMB1Message reply = WaitForMessage(CommandName.SMB_COM_TREE_CONNECT_ANDX);
+            if (reply != null)
+            {
+                status = reply.Header.Status;
+                if (reply.Header.Status == NTStatus.STATUS_SUCCESS && reply.Commands[0] is TreeConnectAndXResponse)
+                {
+                    TreeConnectAndXResponse response = (TreeConnectAndXResponse)reply.Commands[0];
+                    return new SMB1FileStore(this, reply.Header.TID);
+                }
+            }
+            else
+            {
+                status = NTStatus.STATUS_INVALID_SMB;
+            }
+            return null;
+        }
+
         private void OnServerSocketReceive(IAsyncResult ar)
         {
             if (ar != m_currentAsyncResult)

+ 201 - 0
SMBLibrary/Client/SMB1FileStore.cs

@@ -0,0 +1,201 @@
+/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
+ * 
+ * You can redistribute this program and/or modify it under the terms of
+ * the GNU Lesser Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ */
+using System;
+using System.Collections.Generic;
+using SMBLibrary.SMB1;
+using Utilities;
+
+namespace SMBLibrary.Client
+{
+    public class SMB1FileStore : INTFileStore
+    {
+        private SMB1Client m_client;
+        private ushort m_treeID;
+
+        public SMB1FileStore(SMB1Client client, ushort treeID)
+        {
+            m_client = client;
+            m_treeID = treeID;
+        }
+
+        public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, FileAttributes fileAttributes, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext)
+        {
+            handle = null;
+            fileStatus = FileStatus.FILE_DOES_NOT_EXIST;
+            NTCreateAndXRequest request = new NTCreateAndXRequest();
+            request.FileName = path;
+            request.DesiredAccess = desiredAccess;
+            request.ExtFileAttributes = ToExtendedFileAttributes(fileAttributes);
+            request.ShareAccess = shareAccess;
+            request.CreateDisposition = createDisposition;
+            request.CreateOptions = createOptions;
+
+            TrySendMessage(request);
+            SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_NT_CREATE_ANDX);
+            if (reply != null)
+            {
+                if (reply.Commands[0] is NTCreateAndXResponse)
+                {
+                    NTCreateAndXResponse response = reply.Commands[0] as NTCreateAndXResponse;
+                    handle = response.FID;
+                    fileStatus = ToFileStatus(response.CreateDisposition);
+                    return reply.Header.Status;
+                }
+                else if (reply.Commands[0] is ErrorResponse)
+                {
+                    return reply.Header.Status;
+                }
+            }
+            return NTStatus.STATUS_INVALID_SMB;
+        }
+
+        public NTStatus CloseFile(object handle)
+        {
+            CloseRequest request = new CloseRequest();
+            request.FID = (ushort)handle;
+            TrySendMessage(request);
+            SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_CLOSE);
+            if (reply != null)
+            {
+                return reply.Header.Status;
+            }
+            return NTStatus.STATUS_INVALID_SMB;
+        }
+
+        public NTStatus ReadFile(out byte[] data, object handle, long offset, int maxCount)
+        {
+            data = null;
+            ReadAndXRequest request = new ReadAndXRequest();
+            request.FID = (ushort)handle;
+            request.Offset = (ulong)offset;
+            request.MaxCountLarge = (uint)maxCount;
+
+            TrySendMessage(request);
+            SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_READ_ANDX);
+            if (reply != null)
+            {
+                if (reply.Header.Status == NTStatus.STATUS_SUCCESS && reply.Commands[0] is ReadAndXResponse)
+                {
+                    data = ((ReadAndXResponse)reply.Commands[0]).Data;
+                }
+                return reply.Header.Status;
+            }
+            return NTStatus.STATUS_INVALID_SMB;
+        }
+
+        public NTStatus WriteFile(out int numberOfBytesWritten, object handle, long offset, byte[] data)
+        {
+            numberOfBytesWritten = 0;
+            WriteAndXRequest request = new WriteAndXRequest();
+            request.FID = (ushort)handle;
+            request.Offset = (ulong)offset;
+            request.Data = data;
+
+            TrySendMessage(request);
+            SMB1Message reply = m_client.WaitForMessage(CommandName.SMB_COM_WRITE_ANDX);
+            if (reply != null)
+            {
+                if (reply.Header.Status == NTStatus.STATUS_SUCCESS && reply.Commands[0] is WriteAndXResponse)
+                {
+                    numberOfBytesWritten = (int)((WriteAndXResponse)reply.Commands[0]).Count;
+                }
+                return reply.Header.Status;
+            }
+            return NTStatus.STATUS_INVALID_SMB;
+        }
+
+        public NTStatus FlushFileBuffers(object handle)
+        {
+            throw new NotImplementedException();
+        }
+
+        public NTStatus LockFile(object handle, long byteOffset, long length, bool exclusiveLock)
+        {
+            throw new NotImplementedException();
+        }
+
+        public NTStatus UnlockFile(object handle, long byteOffset, long length)
+        {
+            throw new NotImplementedException();
+        }
+
+        public NTStatus QueryDirectory(out List<QueryDirectoryFileInformation> result, object handle, string fileName, FileInformationClass informationClass)
+        {
+            throw new NotImplementedException();
+        }
+
+        public NTStatus GetFileInformation(out FileInformation result, object handle, FileInformationClass informationClass)
+        {
+            throw new NotImplementedException();
+        }
+
+        public NTStatus SetFileInformation(object handle, FileInformation information)
+        {
+            throw new NotImplementedException();
+        }
+
+        public NTStatus GetFileSystemInformation(out FileSystemInformation result, FileSystemInformationClass informationClass)
+        {
+            throw new NotImplementedException();
+        }
+
+        public NTStatus NotifyChange(out object ioRequest, object handle, NotifyChangeFilter completionFilter, bool watchTree, int outputBufferSize, OnNotifyChangeCompleted onNotifyChangeCompleted, object context)
+        {
+            throw new NotImplementedException();
+        }
+
+        public NTStatus Cancel(object ioRequest)
+        {
+            throw new NotImplementedException();
+        }
+
+        public NTStatus DeviceIOControl(object handle, uint ctlCode, byte[] input, out byte[] output, int maxOutputLength)
+        {
+            throw new NotImplementedException();
+        }
+
+        private static ExtendedFileAttributes ToExtendedFileAttributes(FileAttributes fileAttributes)
+        {
+            // We only return flags that can be used with NtCreateFile
+            ExtendedFileAttributes extendedFileAttributes = ExtendedFileAttributes.ReadOnly |
+                                                            ExtendedFileAttributes.Hidden |
+                                                            ExtendedFileAttributes.System |
+                                                            ExtendedFileAttributes.Archive |
+                                                            ExtendedFileAttributes.Normal |
+                                                            ExtendedFileAttributes.Temporary |
+                                                            ExtendedFileAttributes.Offline |
+                                                            ExtendedFileAttributes.Encrypted;
+            return (extendedFileAttributes & (ExtendedFileAttributes)fileAttributes);
+        }
+
+        private void TrySendMessage(SMB1Command request)
+        {
+            m_client.TrySendMessage(request, m_treeID);
+        }
+
+        private static FileStatus ToFileStatus(CreateDisposition createDisposition)
+        {
+            switch (createDisposition)
+            {
+                case CreateDisposition.FILE_SUPERSEDE:
+                    return FileStatus.FILE_SUPERSEDED;
+                case CreateDisposition.FILE_OPEN:
+                    return FileStatus.FILE_OPENED;
+                case CreateDisposition.FILE_CREATE:
+                    return FileStatus.FILE_CREATED;
+                case CreateDisposition.FILE_OPEN_IF:
+                    return FileStatus.FILE_OVERWRITTEN;
+                case CreateDisposition.FILE_OVERWRITE:
+                    return FileStatus.FILE_EXISTS;
+                case CreateDisposition.FILE_OVERWRITE_IF:
+                    return FileStatus.FILE_DOES_NOT_EXIST;
+                default:
+                    return FileStatus.FILE_OPENED;
+            }
+        }
+    }
+}

+ 1 - 0
SMBLibrary/SMBLibrary.csproj

@@ -58,6 +58,7 @@
     <Compile Include="Client\Enums\AuthenticationMethod.cs" />
     <Compile Include="Client\NTLMAuthenticationHelper.cs" />
     <Compile Include="Client\SMB1Client.cs" />
+    <Compile Include="Client\SMB1FileStore.cs" />
     <Compile Include="Enums\NTStatus.cs" />
     <Compile Include="Enums\SMBTransportType.cs" />
     <Compile Include="Enums\Win32Error.cs" />