Beispiel #1
0
        public async Task <(NTStatus status, SecurityDescriptor result)> GetSecurityInformation(object handle, SecurityInformation securityInformation, CancellationToken cancellationToken)
        {
            SecurityDescriptor result  = null;
            QueryInfoRequest   request = new QueryInfoRequest();

            request.InfoType            = InfoType.Security;
            request.SecurityInformation = securityInformation;
            request.OutputBufferLength  = 4096;
            request.FileId = (FileID)handle;

            await TrySendCommandAsync(request, cancellationToken);

            SMB2Command response = m_client.WaitForCommand(SMB2CommandName.QueryInfo);

            if (response != null)
            {
                if (response.Header.Status == NTStatus.STATUS_SUCCESS && response is QueryInfoResponse)
                {
                    result = ((QueryInfoResponse)response).GetSecurityInformation();
                }
                return(response.Header.Status, result);
            }

            return(NTStatus.STATUS_INVALID_SMB, result);
        }
Beispiel #2
0
        public async Task <(NTStatus status, FileSystemInformation result)> GetFileSystemInformationAsync(object handle, FileSystemInformationClass informationClass, CancellationToken cancellationToken)
        {
            QueryInfoRequest request = new QueryInfoRequest();

            request.InfoType = InfoType.FileSystem;
            request.FileSystemInformationClass = informationClass;
            request.OutputBufferLength         = 4096;
            request.FileId = (FileID)handle;

            await TrySendCommandAsync(request, cancellationToken);

            SMB2Command response = m_client.WaitForCommand(SMB2CommandName.QueryInfo);

            if (response != null)
            {
                FileSystemInformation result = null;
                if (response.Header.Status == NTStatus.STATUS_SUCCESS && response is QueryInfoResponse)
                {
                    result = ((QueryInfoResponse)response).GetFileSystemInformation(informationClass);
                }
                return(response.Header.Status, result);
            }

            return(NTStatus.STATUS_INVALID_SMB, null);
        }
        internal static SMB2Command GetQueryInfoResponse(QueryInfoRequest request, ISMBShare share, SMB2ConnectionState state)
        {
            SMB2Session session = state.GetSession(request.Header.SessionID);

            if (request.InfoType == InfoType.File)
            {
                OpenFileObject openFile = session.GetOpenFileObject(request.FileId);
                if (openFile == null)
                {
                    return(new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED));
                }

                if (share is FileSystemShare)
                {
                    if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path))
                    {
                        state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. User '{2}' was denied access.", share.Name, openFile.Path, session.UserName);
                        return(new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED));
                    }
                }

                FileInformation fileInformation;
                NTStatus        queryStatus = share.FileStore.GetFileInformation(out fileInformation, openFile.Handle, request.FileInformationClass);
                if (queryStatus != NTStatus.STATUS_SUCCESS)
                {
                    state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: {3}", share.Name, openFile.Path, request.FileInformationClass, queryStatus);
                    return(new ErrorResponse(request.CommandName, queryStatus));
                }

                state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information class: {2}", share.Name, openFile.Path, request.FileInformationClass);
                QueryInfoResponse response = new QueryInfoResponse();
                response.SetFileInformation(fileInformation);
                return(response);
            }
            else if (request.InfoType == InfoType.FileSystem)
            {
                if (share is FileSystemShare)
                {
                    if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, @"\"))
                    {
                        state.LogToServer(Severity.Verbose, "GetFileSystemInformation on '{0}' failed. User '{1}' was denied access.", share.Name, session.UserName);
                        return(new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED));
                    }

                    FileSystemInformation fileSystemInformation;
                    NTStatus queryStatus = share.FileStore.GetFileSystemInformation(out fileSystemInformation, request.FileSystemInformationClass);
                    if (queryStatus != NTStatus.STATUS_SUCCESS)
                    {
                        state.LogToServer(Severity.Verbose, "GetFileSystemInformation on '{0}' failed. Information class: {1}, NTStatus: {2}", share.Name, request.FileSystemInformationClass, queryStatus);
                        return(new ErrorResponse(request.CommandName, queryStatus));
                    }

                    state.LogToServer(Severity.Information, "GetFileSystemInformation on '{0} succeeded. Information class: {1}", share.Name, request.FileSystemInformationClass);
                    QueryInfoResponse response = new QueryInfoResponse();
                    response.SetFileSystemInformation(fileSystemInformation);
                    return(response);
                }
            }
            return(new ErrorResponse(request.CommandName, NTStatus.STATUS_NOT_SUPPORTED));
        }
Beispiel #4
0
        public void GetFileSystemInformation(out FileSystemInformation result, NtHandle handle, FileSystemInformationClass informationClass)
        {
            QueryInfoRequest request = new QueryInfoRequest
            {
                InfoType = InfoType.FileSystem,
                FileSystemInformationClass = informationClass,
                OutputBufferLength         = 4096,
                FileId = (FileID)handle
            };

            SendCommand(request);
            QueryInfoResponse queryInfoResponse = (QueryInfoResponse)WaitForCommand(request.MessageID);

            queryInfoResponse.IsSuccessElseThrow();
            result = queryInfoResponse.GetFileSystemInformation(informationClass);
        }
Beispiel #5
0
        public void GetSecurityInformation(out SecurityDescriptor?result, NtHandle handle, SecurityInformation securityInformation)
        {
            result = null;

            QueryInfoRequest request = new QueryInfoRequest
            {
                InfoType            = InfoType.Security,
                SecurityInformation = securityInformation,
                OutputBufferLength  = 4096,
                FileId = (FileID)handle
            };

            SendCommand(request);
            SMB2Command response = WaitForCommand(request.MessageID);

            response.IsSuccessElseThrow();

            if (response is QueryInfoResponse queryInfoResponse)
            {
                result = queryInfoResponse.GetSecurityInformation();
            }
        }
Beispiel #6
0
        public NTStatus GetSecurityInformation(out SecurityDescriptor result, object handle, SecurityInformation securityInformation)
        {
            result = null;
            QueryInfoRequest request = new QueryInfoRequest();

            request.InfoType            = InfoType.Security;
            request.SecurityInformation = securityInformation;
            request.OutputBufferLength  = 4096;
            request.FileId = (FileID)handle;

            ulong       messageId = TrySendCommand(request);
            SMB2Command response  = m_client.WaitForCommand(SMB2CommandName.QueryInfo, messageId);

            if (response != null)
            {
                if (response.Header.Status == NTStatus.STATUS_SUCCESS && response is QueryInfoResponse)
                {
                    result = ((QueryInfoResponse)response).GetSecurityInformation();
                }
                return(response.Header.Status);
            }

            return(NTStatus.STATUS_INVALID_SMB);
        }
Beispiel #7
0
        public NTStatus GetFileSystemInformation(out FileSystemInformation result, object handle, FileSystemInformationClass informationClass)
        {
            result = null;
            QueryInfoRequest request = new QueryInfoRequest();

            request.InfoType = InfoType.FileSystem;
            request.FileSystemInformationClass = informationClass;
            request.OutputBufferLength         = 4096;
            request.FileId = (FileID)handle;

            TrySendCommand(request);
            SMB2Command response = m_client.WaitForCommand(SMB2CommandName.QueryInfo);

            if (response != null)
            {
                if (response.Header.Status == NTStatus.STATUS_SUCCESS && response is QueryInfoResponse)
                {
                    result = ((QueryInfoResponse)response).GetFileSystemInformation(informationClass);
                }
                return(response.Header.Status);
            }

            return(NTStatus.STATUS_INVALID_SMB);
        }
Beispiel #8
0
        internal static SMB2Command GetQueryInfoResponse(QueryInfoRequest request, ISMBShare share, SMB2ConnectionState state)
        {
            SMB2Session session = state.GetSession(request.Header.SessionID);

            if (request.InfoType == InfoType.File)
            {
                OpenFileObject openFile = session.GetOpenFileObject(request.FileId);
                if (openFile == null)
                {
                    state.LogToServer(Severity.Verbose, "GetFileInformation failed. Invalid FileId. (SessionID: {0}, TreeID: {1}, FileId: {2})", request.Header.SessionID, request.Header.TreeID, request.FileId.Volatile);
                    return(new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED));
                }

                if (share is FileSystemShare)
                {
                    if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path))
                    {
                        state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. User '{2}' was denied access.", share.Name, openFile.Path, session.UserName);
                        return(new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED));
                    }
                }

                FileInformation fileInformation;
                NTStatus        queryStatus = share.FileStore.GetFileInformation(out fileInformation, openFile.Handle, request.FileInformationClass);
                if (queryStatus != NTStatus.STATUS_SUCCESS)
                {
                    state.LogToServer(Severity.Verbose, "GetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: {3}. (FileId: {4})", share.Name, openFile.Path, request.FileInformationClass, queryStatus, request.FileId.Volatile);
                    return(new ErrorResponse(request.CommandName, queryStatus));
                }

                state.LogToServer(Severity.Information, "GetFileInformation on '{0}{1}' succeeded. Information class: {2}. (FileId: {3})", share.Name, openFile.Path, request.FileInformationClass, request.FileId.Volatile);
                QueryInfoResponse response = new QueryInfoResponse();
                response.SetFileInformation(fileInformation);
                return(response);
            }
            else if (request.InfoType == InfoType.FileSystem)
            {
                if (share is FileSystemShare)
                {
                    if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, @"\"))
                    {
                        state.LogToServer(Severity.Verbose, "GetFileSystemInformation on '{0}' failed. User '{1}' was denied access.", share.Name, session.UserName);
                        return(new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED));
                    }

                    FileSystemInformation fileSystemInformation;
                    NTStatus queryStatus = share.FileStore.GetFileSystemInformation(out fileSystemInformation, request.FileSystemInformationClass);
                    if (queryStatus != NTStatus.STATUS_SUCCESS)
                    {
                        state.LogToServer(Severity.Verbose, "GetFileSystemInformation on '{0}' failed. Information class: {1}, NTStatus: {2}", share.Name, request.FileSystemInformationClass, queryStatus);
                        return(new ErrorResponse(request.CommandName, queryStatus));
                    }

                    state.LogToServer(Severity.Information, "GetFileSystemInformation on '{0}' succeeded. Information class: {1}", share.Name, request.FileSystemInformationClass);
                    QueryInfoResponse response = new QueryInfoResponse();
                    response.SetFileSystemInformation(fileSystemInformation);
                    return(response);
                }
            }
            else if (request.InfoType == InfoType.Security)
            {
                OpenFileObject openFile = session.GetOpenFileObject(request.FileId);
                if (openFile == null)
                {
                    state.LogToServer(Severity.Verbose, "GetSecurityInformation failed. Invalid FileId. (SessionID: {0}, TreeID: {1}, FileId: {2})", request.Header.SessionID, request.Header.TreeID, request.FileId.Volatile);
                    return(new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED));
                }

                if (share is FileSystemShare)
                {
                    if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path))
                    {
                        state.LogToServer(Severity.Verbose, "GetSecurityInformation on '{0}{1}' failed. User '{2}' was denied access.", share.Name, openFile.Path, session.UserName);
                        return(new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED));
                    }
                }

                SecurityDescriptor securityDescriptor;
                NTStatus           queryStatus = share.FileStore.GetSecurityInformation(out securityDescriptor, openFile.Handle, request.SecurityInformation);
                if (queryStatus != NTStatus.STATUS_SUCCESS)
                {
                    state.LogToServer(Severity.Verbose, "GetSecurityInformation on '{0}{1}' failed. Security information: 0x{2}, NTStatus: {3}. (FileId: {4})", share.Name, openFile.Path, request.SecurityInformation.ToString("X"), queryStatus, request.FileId.Volatile);
                    return(new ErrorResponse(request.CommandName, queryStatus));
                }

                if (securityDescriptor.Length > request.OutputBufferLength)
                {
                    state.LogToServer(Severity.Information, "GetSecurityInformation on '{0}{1}' failed. Security information: 0x{2}, NTStatus: STATUS_BUFFER_TOO_SMALL. (FileId: {3})", share.Name, openFile.Path, request.SecurityInformation.ToString("X"), request.FileId.Volatile);
                    byte[] errorData = LittleEndianConverter.GetBytes((uint)securityDescriptor.Length);
                    return(new ErrorResponse(request.CommandName, NTStatus.STATUS_BUFFER_TOO_SMALL, errorData));
                }

                state.LogToServer(Severity.Information, "GetSecurityInformation on '{0}{1}' succeeded. Security information: 0x{2}. (FileId: {3})", share.Name, openFile.Path, request.SecurityInformation.ToString("X"), request.FileId.Volatile);
                QueryInfoResponse response = new QueryInfoResponse();
                response.SetSecurityInformation(securityDescriptor);
                return(response);
            }
            return(new ErrorResponse(request.CommandName, NTStatus.STATUS_NOT_SUPPORTED));
        }