internal static SMB1Command GetNTCreateResponse(SMB1Header header, NTCreateAndXRequest request, ISMBShare share, SMB1ConnectionState state)
        {
            SMB1Session session      = state.GetSession(header.UID);
            bool        isExtended   = (request.Flags & NTCreateFlags.NT_CREATE_REQUEST_EXTENDED_RESPONSE) > 0;
            string      path         = request.FileName;
            FileAccess  createAccess = NTFileStoreHelper.ToCreateFileAccess(request.DesiredAccess, request.CreateDisposition);

            if (share is FileSystemShare)
            {
                if (!((FileSystemShare)share).HasAccess(session.SecurityContext, path, createAccess))
                {
                    state.LogToServer(Severity.Verbose, "Create: Opening '{0}{1}' failed. User '{2}' was denied access.", share.Name, request.FileName, session.UserName);
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(new ErrorResponse(request.CommandName));
                }
            }

            object     handle;
            FileStatus fileStatus;
            NTStatus   createStatus = share.FileStore.CreateFile(out handle, out fileStatus, path, request.DesiredAccess, request.ShareAccess, request.CreateDisposition, request.CreateOptions, session.SecurityContext);

            if (createStatus != NTStatus.STATUS_SUCCESS)
            {
                state.LogToServer(Severity.Verbose, "Create: Opening '{0}{1}' failed. NTStatus: '{2}'.", share.Name, path, createStatus);
                header.Status = createStatus;
                return(new ErrorResponse(request.CommandName));
            }

            state.LogToServer(Severity.Verbose, "Create: Opened '{0}{1}'.", share.Name, path);
            ushort?fileID = session.AddOpenFile(header.TID, path, handle);

            if (!fileID.HasValue)
            {
                share.FileStore.CloseFile(handle);
                header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES;
                return(new ErrorResponse(request.CommandName));
            }

            if (share is NamedPipeShare)
            {
                if (isExtended)
                {
                    return(CreateResponseExtendedForNamedPipe(fileID.Value, FileStatus.FILE_OPENED));
                }
                else
                {
                    return(CreateResponseForNamedPipe(fileID.Value, FileStatus.FILE_OPENED));
                }
            }
            else // FileSystemShare
            {
                FileNetworkOpenInformation fileInfo = NTFileStoreHelper.GetNetworkOpenInformation(share.FileStore, handle);
                if (isExtended)
                {
                    NTCreateAndXResponseExtended response = CreateResponseExtendedFromFileInformation(fileInfo, fileID.Value, fileStatus);
                    if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0)
                    {
                        response.OpLockLevel = OpLockLevel.BatchOpLockGranted;
                    }
                    return(response);
                }
                else
                {
                    NTCreateAndXResponse response = CreateResponseFromFileInformation(fileInfo, fileID.Value, fileStatus);
                    if ((request.Flags & NTCreateFlags.NT_CREATE_REQUEST_OPBATCH) > 0)
                    {
                        response.OpLockLevel = OpLockLevel.BatchOpLockGranted;
                    }
                    return(response);
                }
            }
        }
Exemple #2
0
        internal static SMB1Command GetOpenAndXResponse(SMB1Header header, OpenAndXRequest request, ISMBShare share, SMB1ConnectionState state)
        {
            SMB1Session session    = state.GetSession(header.UID);
            bool        isExtended = (request.Flags & OpenFlags.SMB_OPEN_EXTENDED_RESPONSE) > 0;
            string      path       = request.FileName;

            if (!path.StartsWith(@"\"))
            {
                path = @"\" + path;
            }

            AccessMask        desiredAccess;
            ShareAccess       shareAccess;
            CreateDisposition createDisposition;

            try
            {
                desiredAccess     = ToAccessMask(request.AccessMode.AccessMode);
                shareAccess       = ToShareAccess(request.AccessMode.SharingMode);
                createDisposition = ToCreateDisposition(request.OpenMode);
            }
            catch (ArgumentException)
            {
                // Invalid input according to MS-CIFS
                header.Status = NTStatus.STATUS_OS2_INVALID_ACCESS;
                return(new ErrorResponse(request.CommandName));
            }
            CreateOptions createOptions = ToCreateOptions(request.AccessMode);

            FileAccess createAccess = NTFileStoreHelper.ToCreateFileAccess(desiredAccess, createDisposition);

            if (share is FileSystemShare)
            {
                if (!((FileSystemShare)share).HasAccess(session.SecurityContext, path, createAccess))
                {
                    state.LogToServer(Severity.Verbose, "OpenAndX: Opening '{0}{1}' failed. User '{2}' was denied access.", share.Name, request.FileName, session.UserName);
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(new ErrorResponse(request.CommandName));
                }
            }

            object     handle;
            FileStatus fileStatus;

            header.Status = share.FileStore.CreateFile(out handle, out fileStatus, path, desiredAccess, 0, shareAccess, createDisposition, createOptions, session.SecurityContext);
            if (header.Status != NTStatus.STATUS_SUCCESS)
            {
                state.LogToServer(Severity.Verbose, "OpenAndX: Opening '{0}{1}' failed. NTStatus: {2}.", share.Name, path, header.Status);
                return(new ErrorResponse(request.CommandName));
            }

            FileAccess fileAccess = ToFileAccess(request.AccessMode.AccessMode);
            ushort?    fileID     = session.AddOpenFile(header.TID, share.Name, path, handle, fileAccess);

            if (!fileID.HasValue)
            {
                share.FileStore.CloseFile(handle);
                state.LogToServer(Severity.Verbose, "Create: Opening '{0}{1}' failed. Too many open files.", share.Name, path);
                header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES;
                return(new ErrorResponse(request.CommandName));
            }

            state.LogToServer(Severity.Verbose, "OpenAndX: Opened '{0}{1}'. (UID: {2}, TID: {3}, FID: {4})", share.Name, path, header.UID, header.TID, fileID.Value);
            OpenResult openResult = ToOpenResult(fileStatus);

            if (share is NamedPipeShare)
            {
                if (isExtended)
                {
                    return(CreateResponseExtendedForNamedPipe(fileID.Value, openResult));
                }
                else
                {
                    return(CreateResponseForNamedPipe(fileID.Value, openResult));
                }
            }
            else // FileSystemShare
            {
                FileNetworkOpenInformation fileInfo = NTFileStoreHelper.GetNetworkOpenInformation(share.FileStore, handle);
                if (isExtended)
                {
                    return(CreateResponseExtendedFromFileInfo(fileInfo, fileID.Value, openResult));
                }
                else
                {
                    return(CreateResponseFromFileInfo(fileInfo, fileID.Value, openResult));
                }
            }
        }
Exemple #3
0
        internal static SMB1Command GetNTCreateResponse(SMB1Header header, NTCreateAndXRequest request, ISMBShare share, SMB1ConnectionState state)
        {
            SMB1Session session    = state.GetSession(header.UID);
            bool        isExtended = (request.Flags & NTCreateFlags.NT_CREATE_REQUEST_EXTENDED_RESPONSE) > 0;
            string      path       = request.FileName;

            if (!path.StartsWith(@"\"))
            {
                path = @"\" + path;
            }

            FileAccess createAccess = NTFileStoreHelper.ToCreateFileAccess(request.DesiredAccess, request.CreateDisposition);

            if (share is FileSystemShare)
            {
                if (!((FileSystemShare)share).HasAccess(session.SecurityContext, path, createAccess))
                {
                    state.LogToServer(Severity.Verbose, "Create: Opening '{0}{1}' failed. User '{2}' was denied access.", share.Name, request.FileName, session.UserName);
                    header.Status = NTStatus.STATUS_ACCESS_DENIED;
                    return(new ErrorResponse(request.CommandName));
                }
            }

            object         handle;
            FileStatus     fileStatus;
            FileAttributes fileAttributes = ToFileAttributes(request.ExtFileAttributes);
            // GetFileInformation/FileNetworkOpenInformation requires FILE_READ_ATTRIBUTES
            AccessMask desiredAccess = request.DesiredAccess | (AccessMask)FileAccessMask.FILE_READ_ATTRIBUTES;
            NTStatus   createStatus  = share.FileStore.CreateFile(out handle, out fileStatus, path, desiredAccess, fileAttributes, request.ShareAccess, request.CreateDisposition, request.CreateOptions, session.SecurityContext);

            if (createStatus != NTStatus.STATUS_SUCCESS)
            {
                state.LogToServer(Severity.Verbose, "Create: Opening '{0}{1}' failed. NTStatus: {2}.", share.Name, path, createStatus);
                header.Status = createStatus;
                return(new ErrorResponse(request.CommandName));
            }

            FileAccess fileAccess = NTFileStoreHelper.ToFileAccess(desiredAccess);
            ushort?    fileID     = session.AddOpenFile(header.TID, share.Name, path, handle, fileAccess);

            if (!fileID.HasValue)
            {
                share.FileStore.CloseFile(handle);
                state.LogToServer(Severity.Verbose, "Create: Opening '{0}{1}' failed. Too many open files.", share.Name, path);
                header.Status = NTStatus.STATUS_TOO_MANY_OPENED_FILES;
                return(new ErrorResponse(request.CommandName));
            }

            string fileAccessString  = fileAccess.ToString().Replace(", ", "|");
            string shareAccessString = request.ShareAccess.ToString().Replace(", ", "|");

            state.LogToServer(Severity.Verbose, "Create: Opened '{0}{1}', FileAccess: {2}, ShareAccess: {3}. (UID: {4}, TID: {5}, FID: {6})", share.Name, path, fileAccessString, shareAccessString, header.UID, header.TID, fileID.Value);
            if (share is NamedPipeShare)
            {
                if (isExtended)
                {
                    return(CreateResponseExtendedForNamedPipe(fileID.Value, FileStatus.FILE_OPENED));
                }
                else
                {
                    return(CreateResponseForNamedPipe(fileID.Value, FileStatus.FILE_OPENED));
                }
            }
            else // FileSystemShare
            {
                FileNetworkOpenInformation fileInfo = NTFileStoreHelper.GetNetworkOpenInformation(share.FileStore, handle);
                if (isExtended)
                {
                    NTCreateAndXResponseExtended response = CreateResponseExtendedFromFileInformation(fileInfo, fileID.Value, fileStatus);
                    return(response);
                }
                else
                {
                    NTCreateAndXResponse response = CreateResponseFromFileInformation(fileInfo, fileID.Value, fileStatus);
                    return(response);
                }
            }
        }