/// <summary> /// Gets the message associated with the given <see cref="NTStatus"/>. /// </summary> /// <param name="status">The <see cref="NTStatus"/> for the error.</param> /// <returns>The description of the error.</returns> private static string GetMessage(NTStatus status) { string hexCode = $"0x{(int)status:X8}"; string namedCode = Enum.GetName(typeof(NTStatus.Code), status.AsUInt32); string statusAsString = namedCode != null ? $"{namedCode} ({hexCode})" : hexCode; string insert = $"NT_STATUS {GetSeverityString(status)}: {statusAsString}"; string message = null; #if DESKTOP message = status.GetMessage(); #endif return message != null ? $"{message} ({insert})" : insert; }
public static FileCreationInformation GetFileCreationInformation(string fileurl, string filename, SMBCredential SMBCredential, SMB2Client client, NTStatus nts, ISMBFileStore fileStore) { //SMBLibrary.NTStatus actionStatus; FileCreationInformation newFile = new FileCreationInformation(); NTStatus status = nts; object handle; FileStatus fileStatus; //string path = fileurl; //string path = "Dokument/ARKIV/RUNSAL/23_02_2011/sz001!.PDF"; string tmpfile = Path.GetTempFileName(); status = fileStore.CreateFile(out handle, out fileStatus, fileurl, AccessMask.GENERIC_READ, 0, ShareAccess.Read, CreateDisposition.FILE_OPEN, CreateOptions.FILE_NON_DIRECTORY_FILE, null); if (status != NTStatus.STATUS_SUCCESS) { Console.WriteLine(status); return(null); } else { byte[] buf; var fs = new FileStream(tmpfile, FileMode.OpenOrCreate); var bw = new BinaryWriter(fs); int bufsz = 64 * 1000; int i = 0; do { status = fileStore.ReadFile(out buf, handle, i * bufsz, bufsz); if (status == NTStatus.STATUS_SUCCESS) { int n = buf.GetLength(0); bw.Write(buf, 0, n); if (n < bufsz) { break; } i++; } }while (status != NTStatus.STATUS_END_OF_FILE && i < 1000); if (status == NTStatus.STATUS_SUCCESS) { fileStore.CloseFile(handle); bw.Flush(); fs.Close(); fs = System.IO.File.OpenRead(tmpfile); //byte[] fileBytes = new byte[fs.Length]; //fs.Read(fileBytes, 0, fileBytes.Length); newFile.Overwrite = true; newFile.ContentStream = fs; //newFile.Content = fileBytes; newFile.Url = filename; } else { System.IO.File.Delete(tmpfile); return(null); } System.IO.File.Delete(tmpfile); } return(newFile); }
private static string GetSeverityString(NTStatus status) { switch (status.Severity) { case NTStatus.SeverityCode.STATUS_SEVERITY_SUCCESS: return "success"; case NTStatus.SeverityCode.STATUS_SEVERITY_INFORMATIONAL: return "information"; case NTStatus.SeverityCode.STATUS_SEVERITY_WARNING: return "warning"; case NTStatus.SeverityCode.STATUS_SEVERITY_ERROR: return "error"; default: return string.Empty; } }
/// <summary> /// Initializes a new instance of the <see cref="NTStatusException"/> class. /// </summary> /// <param name="statusCode">The status code identifying the error.</param> /// <param name="message">The exception message (which may be null to use the default).</param> /// <param name="inner">The inner exception.</param> public NTStatusException(NTStatus statusCode, string message, Exception inner) : base(message ?? GetMessage(statusCode), inner) { this.NativeErrorCode = statusCode; }
/// <summary> /// Initializes a new instance of the <see cref="NTStatusException"/> class. /// </summary> /// <param name="statusCode">The status code identifying the error.</param> public NTStatusException(NTStatus statusCode) : this(statusCode, null, null) { }
public static SMB2Command ReadResponse(byte[] buffer, int offset) { SMB2CommandName commandName = (SMB2CommandName)LittleEndianConverter.ToUInt16(buffer, offset + 12); ushort structureSize = LittleEndianConverter.ToUInt16(buffer, offset + SMB2Header.Length + 0); switch (commandName) { case SMB2CommandName.Negotiate: { if (structureSize == NegotiateResponse.DeclaredSize) { return(new NegotiateResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.SessionSetup: { // SESSION_SETUP Response and ERROR Response have the same declared StructureSize of 9. if (structureSize == SessionSetupResponse.DeclaredSize) { NTStatus status = (NTStatus)LittleEndianConverter.ToUInt32(buffer, offset + 8); if (status == NTStatus.STATUS_SUCCESS || status == NTStatus.STATUS_MORE_PROCESSING_REQUIRED) { return(new SessionSetupResponse(buffer, offset)); } else { return(new ErrorResponse(buffer, offset)); } } else { throw new InvalidDataException(); } } case SMB2CommandName.Logoff: { if (structureSize == LogoffResponse.DeclaredSize) { return(new LogoffResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.TreeConnect: { if (structureSize == TreeConnectResponse.DeclaredSize) { return(new TreeConnectResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.TreeDisconnect: { if (structureSize == TreeDisconnectResponse.DeclaredSize) { return(new TreeDisconnectResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.Create: { if (structureSize == CreateResponse.DeclaredSize) { return(new CreateResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.Close: { if (structureSize == CloseResponse.DeclaredSize) { return(new CloseResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.Flush: { if (structureSize == FlushResponse.DeclaredSize) { return(new FlushResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.Read: { if (structureSize == SMB2.ReadResponse.DeclaredSize) { return(new ReadResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.Write: { if (structureSize == WriteResponse.DeclaredSize) { return(new WriteResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.Lock: { if (structureSize == LockResponse.DeclaredSize) { return(new LockResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.IOCtl: { if (structureSize == IOCtlResponse.DeclaredSize) { return(new IOCtlResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.Cancel: { if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.Echo: { if (structureSize == EchoResponse.DeclaredSize) { return(new EchoResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } case SMB2CommandName.QueryDirectory: { // QUERY_DIRECTORY Response and ERROR Response have the same declared StructureSize of 9. if (structureSize == QueryDirectoryResponse.DeclaredSize) { NTStatus status = (NTStatus)LittleEndianConverter.ToUInt32(buffer, offset + 8); if (status == NTStatus.STATUS_SUCCESS) { return(new QueryDirectoryResponse(buffer, offset)); } else { return(new ErrorResponse(buffer, offset)); } } else { throw new InvalidDataException(); } } case SMB2CommandName.ChangeNotify: { // CHANGE_NOTIFY Response and ERROR Response have the same declared StructureSize of 9. if (structureSize == ChangeNotifyResponse.DeclaredSize) { NTStatus status = (NTStatus)LittleEndianConverter.ToUInt32(buffer, offset + 8); if (status == NTStatus.STATUS_SUCCESS || status == NTStatus.STATUS_NOTIFY_CLEANUP || status == NTStatus.STATUS_NOTIFY_ENUM_DIR) { return(new ChangeNotifyResponse(buffer, offset)); } else { return(new ErrorResponse(buffer, offset)); } } else { throw new InvalidDataException(); } } case SMB2CommandName.QueryInfo: { // QUERY_INFO Response and ERROR Response have the same declared StructureSize of 9. if (structureSize == QueryInfoResponse.DeclaredSize) { NTStatus status = (NTStatus)LittleEndianConverter.ToUInt32(buffer, offset + 8); if (status == NTStatus.STATUS_SUCCESS) { return(new QueryInfoResponse(buffer, offset)); } else { return(new ErrorResponse(buffer, offset)); } } else { throw new InvalidDataException(); } } case SMB2CommandName.SetInfo: { if (structureSize == SetInfoResponse.DeclaredSize) { return(new SetInfoResponse(buffer, offset)); } else if (structureSize == ErrorResponse.DeclaredSize) { return(new ErrorResponse(buffer, offset)); } else { throw new InvalidDataException(); } } default: throw new InvalidDataException("Invalid SMB2 command 0x" + ((ushort)commandName).ToString("X4")); } }
private static void ThrowIfLsaError(NTStatus lsaRetVal) => LsaNtStatusToWinError(lsaRetVal).ThrowIfFailed();
internal static Transaction2SetFileInformationResponse GetSubcommandResponse(SMB1Header header, Transaction2SetFileInformationRequest subcommand, ISMBShare share, SMB1ConnectionState state) { SMB1Session session = state.GetSession(header.UID); OpenFileObject openFile = session.GetOpenFileObject(subcommand.FID); if (openFile == null) { state.LogToServer(Severity.Verbose, "SetFileInformation failed. Invalid FID. (UID: {0}, TID: {1}, FID: {2})", header.UID, header.TID, subcommand.FID); header.Status = NTStatus.STATUS_INVALID_HANDLE; return(null); } if (share is FileSystemShare) { if (!((FileSystemShare)share).HasWriteAccess(session.SecurityContext, openFile.Path)) { state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. User '{2}' was denied access.", share.Name, openFile.Path, session.UserName); header.Status = NTStatus.STATUS_ACCESS_DENIED; return(null); } } if (subcommand.IsPassthroughInformationLevel) { FileInformation fileInfo; try { fileInfo = FileInformation.GetFileInformation(subcommand.InformationBytes, 0, subcommand.FileInformationClass); } catch (UnsupportedInformationLevelException) { state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: STATUS_OS2_INVALID_LEVEL.", share.Name, openFile.Path, subcommand.FileInformationClass); header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL; return(null); } catch (Exception) { state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: STATUS_INVALID_PARAMETER.", share.Name, openFile.Path, subcommand.FileInformationClass); header.Status = NTStatus.STATUS_INVALID_PARAMETER; return(null); } NTStatus status = share.FileStore.SetFileInformation(openFile.Handle, fileInfo); if (status != NTStatus.STATUS_SUCCESS) { state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information class: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.FileInformationClass, status, subcommand.FID); header.Status = status; return(null); } state.LogToServer(Severity.Information, "SetFileInformation on '{0}{1}' succeeded. Information class: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.FileInformationClass, subcommand.FID); } else { SetInformation information; try { information = SetInformation.GetSetInformation(subcommand.InformationBytes, subcommand.SetInformationLevel); } catch (UnsupportedInformationLevelException) { state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_OS2_INVALID_LEVEL.", share.Name, openFile.Path, subcommand.SetInformationLevel); header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL; return(null); } catch (Exception) { state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: STATUS_INVALID_PARAMETER.", share.Name, openFile.Path, subcommand.SetInformationLevel); header.Status = NTStatus.STATUS_INVALID_PARAMETER; return(null); } NTStatus status = SMB1FileStoreHelper.SetFileInformation(share.FileStore, openFile.Handle, information); if (status != NTStatus.STATUS_SUCCESS) { state.LogToServer(Severity.Verbose, "SetFileInformation on '{0}{1}' failed. Information level: {2}, NTStatus: {3}. (FID: {4})", share.Name, openFile.Path, subcommand.SetInformationLevel, status, subcommand.FID); header.Status = status; return(null); } state.LogToServer(Severity.Information, "SetFileInformation on '{0}{1}' succeeded. Information level: {2}. (FID: {3})", share.Name, openFile.Path, subcommand.SetInformationLevel, subcommand.FID); } Transaction2SetFileInformationResponse response = new Transaction2SetFileInformationResponse(); return(response); }
public static NetrServerStatisticsGetResponse NetrServerStatisticsGet(ISMBClient client, string serverName, string service, uint level, uint options, out NTStatus status) { using (RPCCallHelper rpc = new RPCCallHelper(client, ServerService.ServicePipeName, ServerService.ServiceInterfaceGuid, ServerService.ServiceVersion)) { status = rpc.BindPipe(); if (status != NTStatus.STATUS_SUCCESS) { return(null); } NetrServerStatisticsGetRequest netrServerStatisticsGetRequest = new NetrServerStatisticsGetRequest(); netrServerStatisticsGetRequest.ServerName = serverName; netrServerStatisticsGetRequest.Service = service; netrServerStatisticsGetRequest.Level = level; netrServerStatisticsGetRequest.Options = options; NetrServerStatisticsGetResponse netrServerStatisticsGetResponse; status = rpc.ExecuteCall((ushort)ServerServiceOpName.NetrServerStatisticsGet, netrServerStatisticsGetRequest, out netrServerStatisticsGetResponse); if (status != NTStatus.STATUS_SUCCESS) { return(null); } return(netrServerStatisticsGetResponse); } }
public static extern Win32ErrorCode RtlNtStatusToDosError(NTStatus Status);
internal IFileInfo FromFileName(string path, ISMBCredential credential) { if (!path.IsSharePath()) { return(null); } if (!path.TryResolveHostnameFromPath(out var ipAddress)) { throw new SMBException($"Failed FromFileName for {path}", new ArgumentException($"Unable to resolve \"{path.Hostname()}\"")); } NTStatus status = NTStatus.STATUS_SUCCESS; if (credential == null) { credential = _credentialProvider.GetSMBCredential(path); } if (credential == null) { throw new SMBException($"Failed FromFileName for {path}", new InvalidCredentialException($"Unable to find credential for path: {path}")); } ISMBFileStore fileStore = null; object handle = null; try { var shareName = path.ShareName(); var relativePath = path.RelativeSharePath(); _logger?.LogTrace($"Trying FromFileName {{RelativePath: {relativePath}}} for {{ShareName: {shareName}}}"); using var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize); fileStore = connection.SMBClient.TreeConnect(shareName, out status); status.HandleStatus(); AccessMask accessMask = AccessMask.SYNCHRONIZE | AccessMask.GENERIC_READ; ShareAccess shareAccess = ShareAccess.Read; CreateDisposition disposition = CreateDisposition.FILE_OPEN; CreateOptions createOptions = CreateOptions.FILE_SYNCHRONOUS_IO_NONALERT | CreateOptions.FILE_NON_DIRECTORY_FILE; status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, accessMask, 0, shareAccess, disposition, createOptions, null); status.HandleStatus(); status = fileStore.GetFileInformation(out FileInformation fileBasicInfo, handle, FileInformationClass.FileBasicInformation); status.HandleStatus(); status = fileStore.GetFileInformation(out FileInformation fileStandardInfo, handle, FileInformationClass.FileStandardInformation); status.HandleStatus(); FileStoreUtilities.CloseFile(fileStore, ref handle); return(new SMBFileInfo(path, _fileSystem, (FileBasicInformation)fileBasicInfo, (FileStandardInformation)fileStandardInfo, credential)); } catch (Exception ex) { throw new SMBException($"Failed FromFileName for {path}", ex); } finally { FileStoreUtilities.CloseFile(fileStore, ref handle); } }
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); if (response.OutputBuffer.Length > request.OutputBufferLength) { response.Header.Status = NTStatus.STATUS_BUFFER_OVERFLOW; response.OutputBuffer = ByteReader.ReadBytes(response.OutputBuffer, 0, (int)request.OutputBufferLength); } 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); if (response.OutputBuffer.Length > request.OutputBufferLength) { response.Header.Status = NTStatus.STATUS_BUFFER_OVERFLOW; response.OutputBuffer = ByteReader.ReadBytes(response.OutputBuffer, 0, (int)request.OutputBufferLength); } 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)); }
public ISMBFileStore TreeConnect(string shareName, out NTStatus status) { return(TreeConnect(shareName, ServiceName.AnyType, out status)); }
public static void HandleStatus(this NTStatus status) { switch (status) { //ERRDOS Class 0x01 case (NTStatus.STATUS_NOT_IMPLEMENTED): throw new NotImplementedException($"{status.ToString()}: {ERRBadFunc}"); case (NTStatus.STATUS_INVALID_DEVICE_REQUEST): throw new InvalidOperationException($"{status.ToString()}: {ERRBadFunc}"); case (NTStatus.STATUS_NO_SUCH_FILE): case (NTStatus.STATUS_NO_SUCH_DEVICE): case (NTStatus.STATUS_OBJECT_NAME_NOT_FOUND): throw new FileNotFoundException($"{status.ToString()}: {ERRBadFile}"); case (NTStatus.STATUS_OBJECT_PATH_INVALID): case (NTStatus.STATUS_OBJECT_PATH_NOT_FOUND): case (NTStatus.STATUS_OBJECT_PATH_SYNTAX_BAD): throw new DirectoryNotFoundException($"{status.ToString()}: {ERRBadPath}"); case (NTStatus.STATUS_TOO_MANY_OPENED_FILES): throw new FileNotFoundException($"{status.ToString()}: {ERRNoFids}"); case (NTStatus.STATUS_ACCESS_DENIED): case (NTStatus.STATUS_DELETE_PENDING): case (NTStatus.STATUS_PRIVILEGE_NOT_HELD): case (NTStatus.STATUS_LOGON_FAILURE): case (NTStatus.STATUS_FILE_IS_A_DIRECTORY): case (NTStatus.STATUS_CANNOT_DELETE): throw new UnauthorizedAccessException($"{status.ToString()}: {ERRNoAccess}"); case (NTStatus.STATUS_SMB_BAD_FID): case (NTStatus.STATUS_INVALID_HANDLE): case (NTStatus.STATUS_FILE_CLOSED): throw new ArgumentException($"{status.ToString()}: {ERRBadFid}"); case (NTStatus.STATUS_INSUFF_SERVER_RESOURCES): throw new OutOfMemoryException($"{status.ToString()}:{ERRNoMem}"); case (NTStatus.STATUS_OS2_INVALID_ACCESS): throw new UnauthorizedAccessException($"{status.ToString()}: {ERRBadAccess}"); case (NTStatus.STATUS_DATA_ERROR): throw new InvalidDataException($"{status.ToString()}: {ERRBadData}"); case (NTStatus.STATUS_DIRECTORY_NOT_EMPTY): throw new IOException($"{status.ToString()}: {ERRRemCd}"); case (NTStatus.STATUS_NO_MORE_FILES): throw new IOException($"{status.ToString()}: {ERRNoFiles}"); case (NTStatus.STATUS_END_OF_FILE): throw new IOException($"{status.ToString()}: {ERREof}"); case (NTStatus.STATUS_NOT_SUPPORTED): throw new NotSupportedException($"{status.ToString()}: {ERRUnsup}"); case (NTStatus.STATUS_OBJECT_NAME_COLLISION): throw new IOException($"{status.ToString()}: {ERRFileExists}"); case (NTStatus.STATUS_INVALID_PARAMETER): throw new ArgumentException($"{status.ToString()}: {ERRInvalidParam}"); case (NTStatus.STATUS_OS2_INVALID_LEVEL): throw new UnsupportedInformationLevelException($"{status.ToString()}: {ERRUnknownLevel}"); case (NTStatus.STATUS_RANGE_NOT_LOCKED): throw new AccessViolationException($"{status.ToString()}: {ERROR_NOT_LOCKED}"); case (NTStatus.STATUS_OS2_NO_MORE_SIDS): throw new InvalidOperationException($"{status.ToString()}: {ERROR_NO_MORE_SEARCH_HANDLES}"); case (NTStatus.STATUS_INVALID_INFO_CLASS): throw new UnsupportedInformationLevelException($"{status.ToString()}: {ERRBadPipe}"); case (NTStatus.STATUS_BUFFER_OVERFLOW): case (NTStatus.STATUS_MORE_PROCESSING_REQUIRED): throw new InvalidOperationException($"{status.ToString()}: {ERRMoreData}"); case (NTStatus.STATUS_NOTIFY_ENUM_DIR): throw new AccessViolationException($"{status.ToString()}: {ERR_NOTIFY_ENUM_DIR}"); //ERRSRV Class 0x02 case (NTStatus.STATUS_INVALID_SMB): throw new ArgumentException($"{status.ToString()}: {ERRInvSmb}"); //Is there a better exception for this? case (NTStatus.STATUS_NETWORK_NAME_DELETED): case (NTStatus.STATUS_SMB_BAD_TID): throw new ArgumentException($"{status.ToString()}: {ERRInvTid}"); case (NTStatus.STATUS_BAD_NETWORK_NAME): throw new ArgumentException($"{status.ToString()}: {ERRInvNetName}"); case (NTStatus.STATUS_SMB_BAD_COMMAND): throw new NotImplementedException($"{status.ToString()}: {ERRBadCmd}"); case (NTStatus.STATUS_TOO_MANY_SESSIONS): throw new ApplicationException($"{status.ToString()}: {ERRTooManyUids}"); case (NTStatus.STATUS_ACCOUNT_DISABLED): case (NTStatus.STATUS_ACCOUNT_EXPIRED): throw new AuthenticationException($"{status.ToString()}: {ERRAccountExpired}"); case (NTStatus.STATUS_INVALID_WORKSTATION): throw new UnauthorizedAccessException($"{status.ToString()}: {ERRBadClient}"); case (NTStatus.STATUS_INVALID_LOGON_HOURS): throw new UnauthorizedAccessException($"{status.ToString()}: {ERRBadLogonTime}"); case (NTStatus.STATUS_PASSWORD_EXPIRED): case (NTStatus.STATUS_PASSWORD_MUST_CHANGE): throw new InvalidCredentialException($"{status.ToString()}: {ERRPasswordExpired}"); //ERRHRD Class 0x03 case (NTStatus.STATUS_MEDIA_WRITE_PROTECTED): throw new AccessViolationException($"{status.ToString()}: {ERRNoWrite}"); case (NTStatus.STATUS_SHARING_VIOLATION): throw new InvalidOperationException($"{status.ToString()}: {ERRBadShare}"); case (NTStatus.STATUS_FILE_LOCK_CONFLICT): throw new InvalidOperationException($"{status.ToString()}: {ERRLock}"); //Others case (NTStatus.STATUS_DISK_FULL): throw new IOException($"{ status.ToString() }: Disk is full."); case (NTStatus.STATUS_LOGON_TYPE_NOT_GRANTED): throw new UnauthorizedAccessException($"{status.ToString()}: {NTStatus_STATUS_LOGON_TYPE_NOT_GRANTED}"); case (NTStatus.STATUS_ACCOUNT_LOCKED_OUT): throw new UnauthorizedAccessException($"{status.ToString()}: {NTStatus_STATUS_ACCOUNT_LOCKED_OUT}"); case (NTStatus.STATUS_ACCOUNT_RESTRICTION): throw new UnauthorizedAccessException($"{status.ToString()}: {NTStatus_STATUS_ACCOUNT_RESTRICTION}"); case (NTStatus.SEC_E_INVALID_TOKEN): throw new UnauthorizedAccessException($"{status.ToString()}"); case (NTStatus.SEC_E_SECPKG_NOT_FOUND): throw new InvalidCredentialException($"{status.ToString()}"); case (NTStatus.STATUS_OBJECT_NAME_INVALID): throw new MemberAccessException($"{status.ToString()}: {NTStatus_STATUS_OBJECT_NAME_INVALID}"); case (NTStatus.STATUS_OBJECT_NAME_EXISTS): throw new InvalidOperationException($"{status.ToString()}: {NTStatus_STATUS_OBJECT_NAME_EXISTS}"); case (NTStatus.STATUS_LOCK_NOT_GRANTED): throw new IOException($"{status.ToString()}: {NTStatus_STATUS_LOCK_NOT_GRANTED}"); case (NTStatus.STATUS_BUFFER_TOO_SMALL): throw new ArgumentException($"{status.ToString()}: {NTStatus_STATUS_BUFFER_TOO_SMALL}"); case (NTStatus.STATUS_BAD_DEVICE_TYPE): throw new InvalidOperationException($"{status.ToString()}: {NTStatus_STATUS_BAD_DEVICE_TYPE}"); case (NTStatus.STATUS_FS_DRIVER_REQUIRED): throw new FileLoadException($"{status.ToString()}: {NTStatus_STATUS_FS_DRIVER_REQUIRED}"); case (NTStatus.STATUS_USER_SESSION_DELETED): throw new UnauthorizedAccessException($"{status.ToString()}: {NTStatus_STATUS_USER_SESSION_DELETED}"); case (NTStatus.SEC_I_CONTINUE_NEEDED): throw new InvalidOperationException($"{status.ToString()}"); case (NTStatus.STATUS_CANCELLED): throw new IOException($"{status.ToString()}: {NTStatus_STATUS_CANCELLED}"); case (NTStatus.STATUS_PENDING): throw new InvalidOperationException($"{status.ToString()}: {NTStatus_STATUS_PENDING}"); case (SMBLibrary.NTStatus) 3221225566: throw new UnauthorizedAccessException("No logon servers are currently available to service the logon request."); case (NTStatus.STATUS_NOTIFY_CLEANUP): //Indicates that a notify change request has been completed due to closing the handle that made the notify change request. case (NTStatus.STATUS_SUCCESS): break; default: break; } }
public NTStatus SetFileInformation(object handle, FileInformation information) { FileHandle fileHandle = (FileHandle)handle; if (information is FileBasicInformation) { FileBasicInformation basicInformation = (FileBasicInformation)information; bool isHidden = ((basicInformation.FileAttributes & FileAttributes.Hidden) > 0); bool isReadonly = (basicInformation.FileAttributes & FileAttributes.ReadOnly) > 0; bool isArchived = (basicInformation.FileAttributes & FileAttributes.Archive) > 0; try { m_fileSystem.SetAttributes(fileHandle.Path, isHidden, isReadonly, isArchived); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "SetFileInformation: Failed to set file attributes on '{0}'. {1}.", fileHandle.Path, status); return(status); } try { m_fileSystem.SetDates(fileHandle.Path, basicInformation.CreationTime, basicInformation.LastWriteTime, basicInformation.LastAccessTime); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "SetFileInformation: Failed to set file dates on '{0}'. {1}.", fileHandle.Path, status); return(status); } return(NTStatus.STATUS_SUCCESS); } else if (information is FileRenameInformationType2) { FileRenameInformationType2 renameInformation = (FileRenameInformationType2)information; string newFileName = renameInformation.FileName; if (!newFileName.StartsWith(@"\")) { newFileName = @"\" + newFileName; } if (fileHandle.Stream != null) { fileHandle.Stream.Close(); } // Note: it's possible that we just want to upcase / downcase a filename letter. try { if (renameInformation.ReplaceIfExists && (m_fileSystem.GetEntry(newFileName) != null)) { m_fileSystem.Delete(newFileName); } m_fileSystem.Move(fileHandle.Path, newFileName); Log(Severity.Information, "SetFileInformation: Renamed '{0}' to '{1}'", fileHandle.Path, newFileName); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "SetFileInformation: Cannot rename '{0}' to '{1}'. {2}.", fileHandle.Path, newFileName, status); return(status); } fileHandle.Path = newFileName; return(NTStatus.STATUS_SUCCESS); } else if (information is FileDispositionInformation) { if (((FileDispositionInformation)information).DeletePending) { // We're supposed to delete the file on close, but it's too late to report errors at this late stage if (fileHandle.Stream != null) { fileHandle.Stream.Close(); } try { m_fileSystem.Delete(fileHandle.Path); Log(Severity.Information, "SetFileInformation: Deleted '{0}'", fileHandle.Path); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Information, "SetFileInformation: Error deleting '{0}'. {1}.", fileHandle.Path, status); return(status); } } return(NTStatus.STATUS_SUCCESS); } else if (information is FileAllocationInformation) { long allocationSize = ((FileAllocationInformation)information).AllocationSize; try { fileHandle.Stream.SetLength(allocationSize); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "SetFileInformation: Cannot set allocation for '{0}'. {1}.", fileHandle.Path, status); return(status); } return(NTStatus.STATUS_SUCCESS); } else if (information is FileEndOfFileInformation) { long endOfFile = ((FileEndOfFileInformation)information).EndOfFile; try { fileHandle.Stream.SetLength(endOfFile); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "SetFileInformation: Cannot set end of file for '{0}'. {1}.", fileHandle.Path, status); return(status); } return(NTStatus.STATUS_SUCCESS); } else { return(NTStatus.STATUS_NOT_IMPLEMENTED); } }
/// <param name="fileName">Expression as described in [MS-FSA] 2.1.4.4</param> public NTStatus QueryDirectory(out List <QueryDirectoryFileInformation> result, object handle, string fileName, FileInformationClass informationClass) { result = null; FileHandle directoryHandle = (FileHandle)handle; if (!directoryHandle.IsDirectory) { return(NTStatus.STATUS_INVALID_PARAMETER); } if (fileName == String.Empty) { return(NTStatus.STATUS_INVALID_PARAMETER); } string path = directoryHandle.Path; bool findExactName = !ContainsWildcardCharacters(fileName); List <FileSystemEntry> entries; if (!findExactName) { try { entries = m_fileSystem.ListEntriesInDirectory(path); } catch (UnauthorizedAccessException) { return(NTStatus.STATUS_ACCESS_DENIED); } entries = GetFiltered(entries, fileName); // Windows will return "." and ".." when enumerating directory files. // The SMB1 / SMB2 specifications mandate that when zero entries are found, the server SHOULD / MUST return STATUS_NO_SUCH_FILE. // For this reason, we MUST include the current directory and/or parent directory when enumerating a directory // in order to diffrentiate between a directory that does not exist and a directory with no entries. FileSystemEntry currentDirectory = m_fileSystem.GetEntry(path); currentDirectory.Name = "."; FileSystemEntry parentDirectory = m_fileSystem.GetEntry(FileSystem.GetParentDirectory(path)); parentDirectory.Name = ".."; entries.Insert(0, parentDirectory); entries.Insert(0, currentDirectory); } else { path = FileSystem.GetDirectoryPath(path); FileSystemEntry entry; try { entry = m_fileSystem.GetEntry(path + fileName); } catch (Exception ex) { if (ex is IOException || ex is UnauthorizedAccessException) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "QueryDirectory: Error querying '{0}'. {1}.", path, status); return(status); } else { throw; } } entries = new List <FileSystemEntry>(); entries.Add(entry); } try { result = FromFileSystemEntries(entries, informationClass); } catch (UnsupportedInformationLevelException) { return(NTStatus.STATUS_INVALID_INFO_CLASS); } return(NTStatus.STATUS_SUCCESS); }
private void OnNotifyChangeCompleted(NTStatus status, byte[] buffer, object context) { m_notifyChangeStatus = status; }
internal Stream Open(string path, FileMode mode, FileAccess access, FileShare share, FileOptions fileOptions, ISMBCredential credential) { if (!path.TryResolveHostnameFromPath(out var ipAddress)) { throw new ArgumentException($"Unable to resolve \"{path.Hostname()}\""); } NTStatus status = NTStatus.STATUS_SUCCESS; AccessMask accessMask = AccessMask.MAXIMUM_ALLOWED; ShareAccess shareAccess = ShareAccess.None; CreateDisposition disposition = CreateDisposition.FILE_OPEN; CreateOptions createOptions; switch (fileOptions) { case FileOptions.DeleteOnClose: createOptions = CreateOptions.FILE_DELETE_ON_CLOSE; break; case FileOptions.RandomAccess: createOptions = CreateOptions.FILE_RANDOM_ACCESS; break; case FileOptions.SequentialScan: createOptions = CreateOptions.FILE_SEQUENTIAL_ONLY; break; case FileOptions.WriteThrough: createOptions = CreateOptions.FILE_WRITE_THROUGH; break; case FileOptions.None: case FileOptions.Encrypted: // These two are not suported unless I am missing something case FileOptions.Asynchronous: // default: createOptions = CreateOptions.FILE_NON_DIRECTORY_FILE; break; } switch (access) { case FileAccess.Read: accessMask = AccessMask.GENERIC_READ; shareAccess = ShareAccess.Read; break; case FileAccess.Write: accessMask = AccessMask.GENERIC_WRITE; shareAccess = ShareAccess.Write; break; case FileAccess.ReadWrite: accessMask = AccessMask.GENERIC_ALL; shareAccess = ShareAccess.Write; break; } if (credential == null) { credential = _credentialProvider.GetSMBCredential(path); } if (credential == null) { throw new Exception($"Unable to find credential for path: {path}"); } var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize); var shareName = path.ShareName(); var relativePath = path.RelativeSharePath(); ISMBFileStore fileStore = connection.SMBClient.TreeConnect(shareName, out status); status.HandleStatus(); switch (mode) { case FileMode.Create: disposition = CreateDisposition.FILE_CREATE; break; case FileMode.CreateNew: disposition = CreateDisposition.FILE_OVERWRITE; break; case FileMode.Open: disposition = CreateDisposition.FILE_OPEN; break; case FileMode.OpenOrCreate: disposition = Exists(path) ? CreateDisposition.FILE_OPEN : CreateDisposition.FILE_CREATE; break; } int getInfoAttempts = 0; int getInfoAllowedRetrys = 5; object handle; FileInformation fileInfo; do { getInfoAttempts++; int openAttempts = 0; int openAllowedRetrys = 5; do { openAttempts++; status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, accessMask, 0, shareAccess, disposition, createOptions, null); }while (status == NTStatus.STATUS_PENDING && openAttempts < openAllowedRetrys); status.HandleStatus(); status = fileStore.GetFileInformation(out fileInfo, handle, FileInformationClass.FileStandardInformation); }while (status == NTStatus.STATUS_NETWORK_NAME_DELETED && getInfoAttempts < getInfoAllowedRetrys); status.HandleStatus(); var fileStandardInfo = (FileStandardInformation)fileInfo; Stream s = new SMBStream(fileStore, handle, connection, fileStandardInfo.EndOfFile); if (mode == FileMode.Append) { s.Seek(0, SeekOrigin.End); } return(s); }
public static UInt32 EfsRpcOpenFileRaw(RPCCallHelper rpc, out EXImportContextHandle hContext, string FileName, Int32 Flags, out NTStatus status) { EfsRpcOpenFileRawRequest openFileRequest = new EfsRpcOpenFileRawRequest(); openFileRequest.FileName = FileName; openFileRequest.Flags = Flags; EfsRpcOpenFileRawResponse openFileResponse; status = rpc.ExecuteCall((ushort)EFSServiceOpName.EfsRpcOpenFileRaw, openFileRequest, out openFileResponse); if (status != NTStatus.STATUS_SUCCESS) { hContext = new EXImportContextHandle(); return(0); } hContext = openFileResponse.ContextHandle; return(openFileResponse.Return); }
public WInteropIOException(NTStatus status) : this(status.ToHResult()) { }
public static void EfsRpcCloseRaw(RPCCallHelper rpc, ref EXImportContextHandle handle, out NTStatus status) { EfsRpcCloseRawRequest closeRequest = new EfsRpcCloseRawRequest(); closeRequest.handle = handle; EfsRpcCloseRawResponse closeResponse; status = rpc.ExecuteCall((ushort)LsaRemoteServiceOpName.LsarClose, closeRequest, out closeResponse); if (status != NTStatus.STATUS_SUCCESS) { return; } handle = closeResponse.Handle; }
internal static SMB2Command GetQueryDirectoryResponse(QueryDirectoryRequest request, ISMBShare share, SMB2ConnectionState state) { SMB2Session session = state.GetSession(request.Header.SessionID); OpenFileObject openFile = session.GetOpenFileObject(request.FileId); if (openFile == null) { return(new ErrorResponse(request.CommandName, NTStatus.STATUS_FILE_CLOSED)); } if (!((FileSystemShare)share).HasReadAccess(session.SecurityContext, openFile.Path)) { state.LogToServer(Severity.Verbose, "Query Directory on '{0}{1}' failed. User '{2}' was denied access.", share.Name, openFile.Path, session.UserName); return(new ErrorResponse(request.CommandName, NTStatus.STATUS_ACCESS_DENIED)); } FileSystemShare fileSystemShare = (FileSystemShare)share; FileID fileID = request.FileId; OpenSearch openSearch = session.GetOpenSearch(fileID); if (openSearch == null || request.Reopen) { if (request.Reopen) { session.RemoveOpenSearch(fileID); } List <QueryDirectoryFileInformation> entries; NTStatus searchStatus = share.FileStore.QueryDirectory(out entries, openFile.Handle, request.FileName, request.FileInformationClass); if (searchStatus != NTStatus.STATUS_SUCCESS) { state.LogToServer(Severity.Verbose, "Query Directory on '{0}{1}', Searched for '{2}', NTStatus: {3}", share.Name, openFile.Path, request.FileName, searchStatus.ToString()); return(new ErrorResponse(request.CommandName, searchStatus)); } state.LogToServer(Severity.Information, "Query Directory on '{0}{1}', Searched for '{2}', found {3} matching entries", share.Name, openFile.Path, request.FileName, entries.Count); openSearch = session.AddOpenSearch(fileID, entries, 0); } if (request.Restart || request.Reopen) { openSearch.EnumerationLocation = 0; } if (openSearch.Entries.Count == 0) { // [MS-SMB2] If there are no entries to return [..] the server MUST fail the request with STATUS_NO_SUCH_FILE. session.RemoveOpenSearch(fileID); return(new ErrorResponse(request.CommandName, NTStatus.STATUS_NO_SUCH_FILE)); } if (openSearch.EnumerationLocation == openSearch.Entries.Count) { return(new ErrorResponse(request.CommandName, NTStatus.STATUS_NO_MORE_FILES)); } List <QueryDirectoryFileInformation> page = new List <QueryDirectoryFileInformation>(); int pageLength = 0; for (int index = openSearch.EnumerationLocation; index < openSearch.Entries.Count; index++) { QueryDirectoryFileInformation fileInformation = openSearch.Entries[index]; if (fileInformation.FileInformationClass != request.FileInformationClass) { // We do not support changing FileInformationClass during a search (unless SMB2_REOPEN is set). return(new ErrorResponse(request.CommandName, NTStatus.STATUS_INVALID_PARAMETER)); } if (pageLength + fileInformation.Length <= request.OutputBufferLength) { page.Add(fileInformation); pageLength += fileInformation.Length; openSearch.EnumerationLocation = index + 1; } else { break; } if (request.ReturnSingleEntry) { break; } } QueryDirectoryResponse response = new QueryDirectoryResponse(); response.SetFileInformationList(page); return(response); }
public static List <string> ListShares(INTFileStore namedPipeShare, ShareType?shareType, out NTStatus status) { object pipeHandle; status = RPCClientHelper.Bind(namedPipeShare, ServerService.ServicePipeName, ServerService.ServiceInterfaceGuid, ServerService.ServiceVersion, out pipeHandle); if (status != NTStatus.STATUS_SUCCESS) { return(null); } NetrShareEnumRequest shareEnumRequest = new NetrShareEnumRequest(); shareEnumRequest.InfoStruct = new ShareEnum(); shareEnumRequest.InfoStruct.Level = 1; shareEnumRequest.InfoStruct.Info = new ShareInfo1Container(); shareEnumRequest.PreferedMaximumLength = UInt32.MaxValue; shareEnumRequest.ServerName = "*"; NetrShareEnumResponse shareEnumResponse; status = RPCClientHelper.ExecuteCall(namedPipeShare, pipeHandle, (ushort)ServerServiceOpName.NetrShareEnum, shareEnumRequest, out shareEnumResponse); if (status != NTStatus.STATUS_SUCCESS) { namedPipeShare.CloseFile(pipeHandle); return(null); } namedPipeShare.CloseFile(pipeHandle); ShareInfo1Container shareInfo1 = shareEnumResponse.InfoStruct.Info as ShareInfo1Container; if (shareInfo1 == null || shareInfo1.Entries == null) { if (shareEnumResponse.Result == Win32Error.ERROR_ACCESS_DENIED) { status = NTStatus.STATUS_ACCESS_DENIED; } else { status = NTStatus.STATUS_NOT_SUPPORTED; } return(null); } List <string> result = new List <string>(); foreach (ShareInfo1Entry entry in shareInfo1.Entries) { if (!shareType.HasValue || shareType.Value == entry.ShareType.ShareType) { result.Add(entry.NetName.Value); } } return(result); }
/// <summary> /// Initializes a new instance of the <see cref="NTStatusException"/> class. /// </summary> /// <param name="statusCode">The status code identifying the error.</param> /// <param name="message">The exception message (which may be null to use the default).</param> public NTStatusException(NTStatus statusCode, string message) : this(statusCode, message, null) { }
public ErrorResponse(SMB2CommandName commandName, NTStatus status) : base(commandName) { Header.IsResponse = true; Header.Status = status; StructureSize = DeclaredSize; }
internal static SMB2Command GetSessionSetupResponse(SessionSetupRequest request, GSSProvider securityProvider, SMB2ConnectionState state) { // [MS-SMB2] Windows [..] will also accept raw Kerberos messages and implicit NTLM messages as part of GSS authentication. SessionSetupResponse response = new SessionSetupResponse(); byte[] outputToken; NTStatus status = securityProvider.AcceptSecurityContext(ref state.AuthenticationContext, request.SecurityBuffer, out outputToken); if (status != NTStatus.STATUS_SUCCESS && status != NTStatus.SEC_I_CONTINUE_NEEDED) { string userName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.UserName) as string; string domainName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.DomainName) as string; string machineName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.MachineName) as string; string osVersion = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.OSVersion) as string; state.LogToServer(Severity.Information, "Session Setup: User '{0}' failed authentication (Domain: '{1}', Workstation: '{2}', OS version: '{3}'), NTStatus: {4}", userName, domainName, machineName, osVersion, status); return(new ErrorResponse(request.CommandName, status)); } if (outputToken != null) { response.SecurityBuffer = outputToken; } // According to [MS-SMB2] 3.3.5.5.3, response.Header.SessionID must be allocated if the server returns STATUS_MORE_PROCESSING_REQUIRED if (request.Header.SessionID == 0) { ulong?sessionID = state.AllocateSessionID(); if (!sessionID.HasValue) { return(new ErrorResponse(request.CommandName, NTStatus.STATUS_TOO_MANY_SESSIONS)); } response.Header.SessionID = sessionID.Value; } if (status == NTStatus.SEC_I_CONTINUE_NEEDED) { response.Header.Status = NTStatus.STATUS_MORE_PROCESSING_REQUIRED; } else // status == STATUS_SUCCESS { string userName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.UserName) as string; string domainName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.DomainName) as string; string machineName = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.MachineName) as string; string osVersion = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.OSVersion) as string; byte[] sessionKey = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.SessionKey) as byte[]; object accessToken = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.AccessToken); bool? isGuest = securityProvider.GetContextAttribute(state.AuthenticationContext, GSSAttributeName.IsGuest) as bool?; if (!isGuest.HasValue || !isGuest.Value) { state.LogToServer(Severity.Information, "Session Setup: User '{0}' authenticated successfully (Domain: '{1}', Workstation: '{2}', OS version: '{3}').", userName, domainName, machineName, osVersion); bool signingRequired = (request.SecurityMode == SecurityMode.SigningRequired); state.CreateSession(request.Header.SessionID, userName, machineName, sessionKey, accessToken, signingRequired); } else { state.LogToServer(Severity.Information, "Session Setup: User '{0}' failed authentication (Domain: '{1}', Workstation: '{2}', OS version: '{3}'), logged in as guest.", userName, domainName, machineName, osVersion); state.CreateSession(request.Header.SessionID, "Guest", machineName, sessionKey, accessToken, false); response.SessionFlags = SessionFlags.IsGuest; } } return(response); }
public static List <string> ListShares(INTFileStore namedPipeShare, ShareType?shareType, out NTStatus status) { object pipeHandle; FileStatus fileStatus; status = namedPipeShare.CreateFile(out pipeHandle, out fileStatus, ServerService.ServicePipeName, (AccessMask)(FileAccessMask.FILE_READ_DATA | FileAccessMask.FILE_WRITE_DATA), 0, ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE, CreateDisposition.FILE_OPEN, 0, null); if (status != NTStatus.STATUS_SUCCESS) { return(null); } BindPDU bindPDU = new BindPDU(); bindPDU.Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment; bindPDU.DataRepresentation.CharacterFormat = CharacterFormat.ASCII; bindPDU.DataRepresentation.ByteOrder = ByteOrder.LittleEndian; bindPDU.DataRepresentation.FloatingPointRepresentation = FloatingPointRepresentation.IEEE; bindPDU.MaxTransmitFragmentSize = 5680; bindPDU.MaxReceiveFragmentSize = 5680; ContextElement serverServiceContext = new ContextElement(); serverServiceContext.AbstractSyntax = new SyntaxID(ServerService.ServiceInterfaceGuid, ServerService.ServiceVersion); serverServiceContext.TransferSyntaxList.Add(new SyntaxID(RemoteServiceHelper.NDRTransferSyntaxIdentifier, RemoteServiceHelper.NDRTransferSyntaxVersion)); bindPDU.ContextList.Add(serverServiceContext); byte[] input = bindPDU.GetBytes(); byte[] output; status = namedPipeShare.DeviceIOControl(pipeHandle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, input, out output, 4096); if (status != NTStatus.STATUS_SUCCESS) { return(null); } BindAckPDU bindAckPDU = RPCPDU.GetPDU(output, 0) as BindAckPDU; if (bindAckPDU == null) { status = NTStatus.STATUS_NOT_SUPPORTED; return(null); } NetrShareEnumRequest shareEnumRequest = new NetrShareEnumRequest(); shareEnumRequest.InfoStruct = new ShareEnum(); shareEnumRequest.InfoStruct.Level = 1; shareEnumRequest.InfoStruct.Info = new ShareInfo1Container(); shareEnumRequest.PreferedMaximumLength = UInt32.MaxValue; shareEnumRequest.ServerName = "*"; RequestPDU requestPDU = new RequestPDU(); requestPDU.Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment; requestPDU.DataRepresentation.CharacterFormat = CharacterFormat.ASCII; requestPDU.DataRepresentation.ByteOrder = ByteOrder.LittleEndian; requestPDU.DataRepresentation.FloatingPointRepresentation = FloatingPointRepresentation.IEEE; requestPDU.OpNum = (ushort)ServerServiceOpName.NetrShareEnum; requestPDU.Data = shareEnumRequest.GetBytes(); requestPDU.AllocationHint = (uint)requestPDU.Data.Length; input = requestPDU.GetBytes(); int maxOutputLength = bindAckPDU.MaxTransmitFragmentSize; status = namedPipeShare.DeviceIOControl(pipeHandle, (uint)IoControlCode.FSCTL_PIPE_TRANSCEIVE, input, out output, maxOutputLength); if (status != NTStatus.STATUS_SUCCESS) { return(null); } ResponsePDU responsePDU = RPCPDU.GetPDU(output, 0) as ResponsePDU; if (responsePDU == null) { status = NTStatus.STATUS_NOT_SUPPORTED; return(null); } byte[] responseData = responsePDU.Data; while ((responsePDU.Flags & PacketFlags.LastFragment) == 0) { status = namedPipeShare.ReadFile(out output, pipeHandle, 0, maxOutputLength); if (status != NTStatus.STATUS_SUCCESS) { return(null); } responsePDU = RPCPDU.GetPDU(output, 0) as ResponsePDU; if (responsePDU == null) { status = NTStatus.STATUS_NOT_SUPPORTED; return(null); } responseData = ByteUtils.Concatenate(responseData, responsePDU.Data); } NetrShareEnumResponse shareEnumResponse = new NetrShareEnumResponse(responseData); ShareInfo1Container shareInfo1 = shareEnumResponse.InfoStruct.Info as ShareInfo1Container; if (shareInfo1 == null || shareInfo1.Entries == null) { if (shareEnumResponse.Result == Win32Error.ERROR_ACCESS_DENIED) { status = NTStatus.STATUS_ACCESS_DENIED; } else { status = NTStatus.STATUS_NOT_SUPPORTED; } return(null); } List <string> result = new List <string>(); foreach (ShareInfo1Entry entry in shareInfo1.Entries) { if (!shareType.HasValue || shareType.Value == entry.ShareType.ShareType) { result.Add(entry.NetName.Value); } } return(result); }
public NTStatus CreateFile(out object handle, out FileStatus fileStatus, string path, AccessMask desiredAccess, ShareAccess shareAccess, CreateDisposition createDisposition, CreateOptions createOptions, SecurityContext securityContext) { handle = null; fileStatus = FileStatus.FILE_DOES_NOT_EXIST; FileAccess createAccess = NTFileStoreHelper.ToCreateFileAccess(desiredAccess, createDisposition); bool requestedWriteAccess = (createAccess & FileAccess.Write) > 0; bool forceDirectory = (createOptions & CreateOptions.FILE_DIRECTORY_FILE) > 0; bool forceFile = (createOptions & CreateOptions.FILE_NON_DIRECTORY_FILE) > 0; if (forceDirectory & (createDisposition != CreateDisposition.FILE_CREATE && createDisposition != CreateDisposition.FILE_OPEN && createDisposition != CreateDisposition.FILE_OPEN_IF && createDisposition != CreateDisposition.FILE_SUPERSEDE)) { return(NTStatus.STATUS_INVALID_PARAMETER); } // Windows will try to access named streams (alternate data streams) regardless of the FILE_NAMED_STREAMS flag, we need to prevent this behaviour. if (path.Contains(":")) { // Windows Server 2003 will return STATUS_OBJECT_NAME_NOT_FOUND return(NTStatus.STATUS_NO_SUCH_FILE); } FileSystemEntry entry; try { entry = m_fileSystem.GetEntry(path); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "CreateFile: Error retrieving '{0}'. {1}.", path, status); return(status); } if (createDisposition == CreateDisposition.FILE_OPEN) { if (entry == null) { return(NTStatus.STATUS_NO_SUCH_FILE); } fileStatus = FileStatus.FILE_EXISTS; if (entry.IsDirectory && forceFile) { return(NTStatus.STATUS_FILE_IS_A_DIRECTORY); } if (!entry.IsDirectory && forceDirectory) { return(NTStatus.STATUS_OBJECT_PATH_INVALID); } } else if (createDisposition == CreateDisposition.FILE_CREATE) { if (entry != null) { // File already exists, fail the request Log(Severity.Verbose, "CreateFile: File '{0}' already exist", path); fileStatus = FileStatus.FILE_EXISTS; return(NTStatus.STATUS_OBJECT_NAME_COLLISION); } if (!requestedWriteAccess) { return(NTStatus.STATUS_ACCESS_DENIED); } try { if (forceDirectory) { Log(Severity.Information, "CreateFile: Creating directory '{0}'", path); entry = m_fileSystem.CreateDirectory(path); } else { Log(Severity.Information, "CreateFile: Creating file '{0}'", path); entry = m_fileSystem.CreateFile(path); } } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "CreateFile: Error creating '{0}'. {1}.", path, status); return(status); } fileStatus = FileStatus.FILE_CREATED; } else if (createDisposition == CreateDisposition.FILE_OPEN_IF || createDisposition == CreateDisposition.FILE_OVERWRITE || createDisposition == CreateDisposition.FILE_OVERWRITE_IF || createDisposition == CreateDisposition.FILE_SUPERSEDE) { if (entry == null) { if (createDisposition == CreateDisposition.FILE_OVERWRITE) { return(NTStatus.STATUS_OBJECT_PATH_NOT_FOUND); } if (!requestedWriteAccess) { return(NTStatus.STATUS_ACCESS_DENIED); } try { if (forceDirectory) { Log(Severity.Information, "CreateFile: Creating directory '{0}'", path); entry = m_fileSystem.CreateDirectory(path); } else { Log(Severity.Information, "CreateFile: Creating file '{0}'", path); entry = m_fileSystem.CreateFile(path); } } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "CreateFile: Error creating '{0}'. {1}.", path, status); return(status); } fileStatus = FileStatus.FILE_CREATED; } else { fileStatus = FileStatus.FILE_EXISTS; if (!requestedWriteAccess) { return(NTStatus.STATUS_ACCESS_DENIED); } if (createDisposition == CreateDisposition.FILE_OVERWRITE || createDisposition == CreateDisposition.FILE_OVERWRITE_IF) { // Truncate the file try { Stream temp = m_fileSystem.OpenFile(path, FileMode.Truncate, FileAccess.ReadWrite, FileShare.ReadWrite); temp.Close(); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "CreateFile: Error truncating '{0}'. {1}.", path, status); return(status); } fileStatus = FileStatus.FILE_OVERWRITTEN; } else if (createDisposition == CreateDisposition.FILE_SUPERSEDE) { // Delete the old file try { m_fileSystem.Delete(path); } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "CreateFile: Error deleting '{0}'. {1}.", path, status); return(status); } try { if (forceDirectory) { Log(Severity.Information, "CreateFile: Creating directory '{0}'", path); entry = m_fileSystem.CreateDirectory(path); } else { Log(Severity.Information, "CreateFile: Creating file '{0}'", path); entry = m_fileSystem.CreateFile(path); } } catch (Exception ex) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "CreateFile: Error creating '{0}'. {1}.", path, status); return(status); } fileStatus = FileStatus.FILE_SUPERSEDED; } } } else { return(NTStatus.STATUS_INVALID_PARAMETER); } FileAccess fileAccess = NTFileStoreHelper.ToFileAccess(desiredAccess.File); Stream stream; bool deleteOnClose = false; if (fileAccess == (FileAccess)0 || entry.IsDirectory) { stream = null; } else { NTStatus openStatus = OpenFileStream(out stream, path, fileAccess, shareAccess, createOptions); if (openStatus != NTStatus.STATUS_SUCCESS) { return(openStatus); } } deleteOnClose = (createOptions & CreateOptions.FILE_DELETE_ON_CLOSE) > 0; handle = new FileHandle(path, entry.IsDirectory, stream, deleteOnClose); if (fileStatus != FileStatus.FILE_CREATED && fileStatus != FileStatus.FILE_OVERWRITTEN && fileStatus != FileStatus.FILE_SUPERSEDED) { fileStatus = FileStatus.FILE_OPENED; } return(NTStatus.STATUS_SUCCESS); }
/// <summary> /// Convert an NTSTATUS to a Windows error code (returns ERROR_MR_MID_NOT_FOUND if unable to find an error) /// </summary> public static WindowsError NtStatusToWinError(NTStatus status) { return(Imports.LsaNtStatusToWinError(status)); }
public static Microsoft.SharePoint.Client.File GetBigSharePointFile(string fileurl, string filename, SMBCredential SMBCredential, SMB2Client client, NTStatus nts, ISMBFileStore fileStore, List list, ClientContext cc, DocumentModel doc, List <Metadata> fields) { Microsoft.SharePoint.Client.File uploadFile = null; ClientResult <long> bytesUploaded = null; //SMBLibrary.NTStatus actionStatus; FileCreationInformation newFile = new FileCreationInformation(); NTStatus status = nts; object handle; FileStatus fileStatus; string tmpfile = Path.GetTempFileName(); status = fileStore.CreateFile(out handle, out fileStatus, fileurl, AccessMask.GENERIC_READ, 0, ShareAccess.Read, CreateDisposition.FILE_OPEN, CreateOptions.FILE_NON_DIRECTORY_FILE, null); if (status != NTStatus.STATUS_SUCCESS) { Console.WriteLine(status); return(null); } else { string uniqueFileName = String.Empty; int blockSize = 8000000; // 8 MB long fileSize; Guid uploadId = Guid.NewGuid(); byte[] buf; var fs = new FileStream(tmpfile, FileMode.OpenOrCreate); var bw = new BinaryWriter(fs); int bufsz = 64 * 1000; int i = 0; do { status = fileStore.ReadFile(out buf, handle, i * bufsz, bufsz); if (status == NTStatus.STATUS_SUCCESS) { int n = buf.GetLength(0); bw.Write(buf, 0, n); if (n < bufsz) { break; } i++; } }while (status != NTStatus.STATUS_END_OF_FILE && i < 1000); if (status == NTStatus.STATUS_SUCCESS) { fileStore.CloseFile(handle); bw.Flush(); fs.Close(); //fs = System.IO.File.OpenRead(tmpfile); //byte[] fileBytes = new byte[fs.Length]; //fs.Read(fileBytes, 0, fileBytes.Length); try { fs = System.IO.File.Open(tmpfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); fileSize = fs.Length; uniqueFileName = Path.GetFileName(fs.Name); using (BinaryReader br = new BinaryReader(fs)) { byte[] buffer = new byte[blockSize]; byte[] lastBuffer = null; long fileoffset = 0; long totalBytesRead = 0; int bytesRead; bool first = true; bool last = false; while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0) { totalBytesRead = totalBytesRead + bytesRead; if (totalBytesRead >= fileSize) { last = true; lastBuffer = new byte[bytesRead]; Array.Copy(buffer, 0, lastBuffer, 0, bytesRead); } if (first) { using (MemoryStream contentStream = new MemoryStream()) { newFile.ContentStream = contentStream; newFile.Url = uniqueFileName; newFile.Overwrite = true; if (doc.foldername == null) { uploadFile = list.RootFolder.Files.Add(newFile); } /*else * { * string foldername = doc.foldername; * string sitecontent = doc.sitecontent; * * //Folder folder = list.RootFolder.Folders.GetByUrl(foldername); * * Folder folder = GetFolder(cc, list, foldername); * if (folder == null){ * if(doc.taxFields != null){ * folder = CreateDocumentSetWithTaxonomy(cc, list, sitecontent, foldername, doc.fields, fields, doc.taxFields); * } * else * { * folder = CreateFolder(cc, list, sitecontent, foldername, doc.fields, fields); * } * * } * }*/ using (MemoryStream s = new MemoryStream(buffer)) { bytesUploaded = uploadFile.StartUpload(uploadId, s); cc.ExecuteQuery(); fileoffset = bytesUploaded.Value; } first = false; } } else { uploadFile = cc.Web.GetFileByServerRelativeUrl(list.RootFolder.ServerRelativeUrl + Path.AltDirectorySeparatorChar + uniqueFileName); if (last) { using (MemoryStream s = new MemoryStream(lastBuffer)) { uploadFile = uploadFile.FinishUpload(uploadId, fileoffset, s); cc.ExecuteQuery(); } } else { using (MemoryStream s = new MemoryStream(buffer)) { bytesUploaded = uploadFile.ContinueUpload(uploadId, fileoffset, s); cc.ExecuteQuery(); fileoffset = bytesUploaded.Value; } } } } } } finally { System.IO.File.Delete(tmpfile); if (fs != null) { fs.Dispose(); } } } else { System.IO.File.Delete(tmpfile); return(null); } return(uploadFile); } }
public virtual NTStatus AcceptSecurityContext(ref GSSContext context, byte[] inputToken, out byte[] outputToken) { outputToken = null; SimpleProtectedNegotiationToken spnegoToken = null; try { spnegoToken = SimpleProtectedNegotiationToken.ReadToken(inputToken, 0, false); } catch { } if (spnegoToken != null) { if (spnegoToken is SimpleProtectedNegotiationTokenInit) { SimpleProtectedNegotiationTokenInit tokenInit = (SimpleProtectedNegotiationTokenInit)spnegoToken; if (tokenInit.MechanismTypeList.Count == 0) { return(NTStatus.SEC_E_INVALID_TOKEN); } // RFC 4178: Note that in order to avoid an extra round trip, the first context establishment token // of the initiator's preferred mechanism SHOULD be embedded in the initial negotiation message. byte[] preferredMechanism = tokenInit.MechanismTypeList[0]; IGSSMechanism mechanism = FindMechanism(preferredMechanism); bool isPreferredMechanism = (mechanism != null); if (!isPreferredMechanism) { mechanism = FindMechanism(tokenInit.MechanismTypeList); } if (mechanism != null) { NTStatus status; context = new GSSContext(mechanism, null); if (isPreferredMechanism) { byte[] mechanismOutput; status = mechanism.AcceptSecurityContext(ref context.MechanismContext, tokenInit.MechanismToken, out mechanismOutput); outputToken = GetSPNEGOTokenResponseBytes(mechanismOutput, status, mechanism.Identifier); } else { status = NTStatus.SEC_I_CONTINUE_NEEDED; outputToken = GetSPNEGOTokenResponseBytes(null, status, mechanism.Identifier); } return(status); } return(NTStatus.SEC_E_SECPKG_NOT_FOUND); } else // SimpleProtectedNegotiationTokenResponse { if (context == null) { return(NTStatus.SEC_E_INVALID_TOKEN); } IGSSMechanism mechanism = context.Mechanism; SimpleProtectedNegotiationTokenResponse tokenResponse = (SimpleProtectedNegotiationTokenResponse)spnegoToken; byte[] mechanismOutput; NTStatus status = mechanism.AcceptSecurityContext(ref context.MechanismContext, tokenResponse.ResponseToken, out mechanismOutput); outputToken = GetSPNEGOTokenResponseBytes(mechanismOutput, status, null); return(status); } } else { // [MS-SMB] The Windows GSS implementation supports raw Kerberos / NTLM messages in the SecurityBlob. // [MS-SMB2] Windows [..] will also accept raw Kerberos messages and implicit NTLM messages as part of GSS authentication. if (AuthenticationMessageUtils.IsSignatureValid(inputToken)) { MessageTypeName messageType = AuthenticationMessageUtils.GetMessageType(inputToken); IGSSMechanism ntlmAuthenticationProvider = FindMechanism(NTLMSSPIdentifier); if (ntlmAuthenticationProvider != null) { if (messageType == MessageTypeName.Negotiate) { context = new GSSContext(ntlmAuthenticationProvider, null); } if (context == null) { return(NTStatus.SEC_E_INVALID_TOKEN); } NTStatus status = ntlmAuthenticationProvider.AcceptSecurityContext(ref context.MechanismContext, inputToken, out outputToken); return(status); } else { return(NTStatus.SEC_E_SECPKG_NOT_FOUND); } } } return(NTStatus.SEC_E_INVALID_TOKEN); }
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)); } state.LogToServer(Severity.Verbose, "Create: Opened '{0}{1}'. (UID: {2}, TID: {3}, FID: {4})", share.Name, path, 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); } } }
internal IDirectoryInfo FromDirectoryName(string path, ISMBCredential credential) { if (!path.IsSharePath() || !path.IsValidSharePath()) { return(null); } if (!path.TryResolveHostnameFromPath(out var ipAddress)) { throw new SMBException($"Failed FromDirectoryName for {path}", new ArgumentException($"Unable to resolve \"{path.Hostname()}\"")); } NTStatus status = NTStatus.STATUS_SUCCESS; if (credential == null) { credential = _credentialProvider.GetSMBCredential(path); } if (credential == null) { throw new SMBException($"Failed FromDirectoryName for {path}", new InvalidCredentialException($"Unable to find credential for path: {path}")); } ISMBFileStore fileStore = null; object handle = null; try { var shareName = path.ShareName(); var relativePath = path.RelativeSharePath(); _logger?.LogTrace($"Trying FromDirectoryName {{RelativePath: {relativePath}}} for {{ShareName: {shareName}}}"); using var connection = SMBConnection.CreateSMBConnection(_smbClientFactory, ipAddress, transport, credential, _maxBufferSize); fileStore = connection.SMBClient.TreeConnect(shareName, out status); status.HandleStatus(); status = fileStore.CreateFile(out handle, out FileStatus fileStatus, relativePath, AccessMask.GENERIC_READ, 0, ShareAccess.Read, CreateDisposition.FILE_OPEN, CreateOptions.FILE_DIRECTORY_FILE, null); status.HandleStatus(); status = fileStore.GetFileInformation(out FileInformation fileInfo, handle, FileInformationClass.FileBasicInformation); // If you call this with any other FileInformationClass value // it doesn't work for some reason if (status != NTStatus.STATUS_SUCCESS) { return(null); } return(new SMBDirectoryInfo(path, fileInfo, _fileSystem, _credentialProvider, credential)); } catch (Exception ex) { throw new SMBException($"Failed FromDirectoryName for {path}", ex); } finally { FileStoreUtilities.CloseFile(fileStore, ref handle); } }
internal static Transaction2FindFirst2Response GetSubcommandResponse(SMB1Header header, uint maxDataCount, Transaction2FindFirst2Request subcommand, ISMBShare share, SMB1ConnectionState state) { SMB1Session session = state.GetSession(header.UID); string fileNamePattern = subcommand.FileName; if (!fileNamePattern.StartsWith(@"\")) { fileNamePattern = @"\" + fileNamePattern; } List <QueryDirectoryFileInformation> entries; FileInformationClass informationClass; try { informationClass = FindInformationHelper.ToFileInformationClass(subcommand.InformationLevel); } catch (UnsupportedInformationLevelException) { state.LogToServer(Severity.Verbose, "FindFirst2: Unsupported information level: {0}.", subcommand.InformationLevel); header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL; return(null); } NTStatus searchStatus = SMB1FileStoreHelper.QueryDirectory(out entries, share.FileStore, fileNamePattern, informationClass, session.SecurityContext); if (searchStatus != NTStatus.STATUS_SUCCESS) { state.LogToServer(Severity.Verbose, "FindFirst2: Searched for '{0}{1}', NTStatus: {2}", share.Name, fileNamePattern, searchStatus.ToString()); header.Status = searchStatus; return(null); } // We ignore SearchAttributes state.LogToServer(Severity.Information, "FindFirst2: Searched for '{0}{1}', found {2} matching entries", share.Name, fileNamePattern, entries.Count); // [MS-CIFS] If no matching entries are found, the server SHOULD fail the request with STATUS_NO_SUCH_FILE. if (entries.Count == 0) { header.Status = NTStatus.STATUS_NO_SUCH_FILE; return(null); } bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0; int entriesToReturn = Math.Min(subcommand.SearchCount, entries.Count); List <QueryDirectoryFileInformation> segment = entries.GetRange(0, entriesToReturn); int maxLength = (int)maxDataCount; FindInformationList findInformationList; try { findInformationList = FindInformationHelper.ToFindInformationList(segment, header.UnicodeFlag, maxLength); } catch (UnsupportedInformationLevelException) { state.LogToServer(Severity.Verbose, "FindFirst2: Unsupported information level: {0}.", subcommand.InformationLevel); header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL; return(null); } int returnCount = findInformationList.Count; Transaction2FindFirst2Response response = new Transaction2FindFirst2Response(); response.SetFindInformationList(findInformationList, header.UnicodeFlag); response.EndOfSearch = (returnCount == entries.Count); // If [..] the search fit within a single response and SMB_FIND_CLOSE_AT_EOS is set in the Flags field, // or if SMB_FIND_CLOSE_AFTER_REQUEST is set in the request, // the server SHOULD return a SID field value of zero. // This indicates that the search has been closed and is no longer active on the server. if ((response.EndOfSearch && subcommand.CloseAtEndOfSearch) || subcommand.CloseAfterRequest) { response.SID = 0; } else { ushort?searchHandle = session.AddOpenSearch(entries, returnCount); if (!searchHandle.HasValue) { header.Status = NTStatus.STATUS_OS2_NO_MORE_SIDS; return(null); } response.SID = searchHandle.Value; } return(response); }
public NTStatus GetFileInformation(out FileInformation result, object handle, FileInformationClass informationClass) { FileHandle fileHandle = (FileHandle)handle; string path = fileHandle.Path; FileSystemEntry entry; try { entry = m_fileSystem.GetEntry(path); } catch (Exception ex) { if (ex is IOException || ex is UnauthorizedAccessException) { NTStatus status = ToNTStatus(ex); Log(Severity.Verbose, "GetFileInformation on '{0}' failed. {1}", path, status); result = null; return(status); } else { throw; } } switch (informationClass) { case FileInformationClass.FileBasicInformation: { FileBasicInformation information = new FileBasicInformation(); information.CreationTime = entry.CreationTime; information.LastAccessTime = entry.LastAccessTime; information.LastWriteTime = entry.LastWriteTime; information.ChangeTime = entry.LastWriteTime; information.FileAttributes = GetFileAttributes(entry); result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FileStandardInformation: { FileStandardInformation information = new FileStandardInformation(); information.AllocationSize = (long)GetAllocationSize(entry.Size); information.EndOfFile = (long)entry.Size; information.Directory = entry.IsDirectory; information.DeletePending = fileHandle.DeleteOnClose; result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FileInternalInformation: { FileInternalInformation information = new FileInternalInformation(); result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FileEaInformation: { FileEaInformation information = new FileEaInformation(); information.EaSize = 0; result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FileAccessInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileNameInformation: { FileNameInformation information = new FileNameInformation(); information.FileName = entry.Name; result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FilePositionInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileFullEaInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileModeInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileAlignmentInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileAllInformation: { FileAllInformation information = new FileAllInformation(); information.BasicInformation.CreationTime = entry.CreationTime; information.BasicInformation.LastAccessTime = entry.LastAccessTime; information.BasicInformation.LastWriteTime = entry.LastWriteTime; information.BasicInformation.ChangeTime = entry.LastWriteTime; information.BasicInformation.FileAttributes = GetFileAttributes(entry); information.StandardInformation.AllocationSize = (long)GetAllocationSize(entry.Size); information.StandardInformation.EndOfFile = (long)entry.Size; information.StandardInformation.Directory = entry.IsDirectory; information.StandardInformation.DeletePending = fileHandle.DeleteOnClose; information.NameInformation.FileName = entry.Name; result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FileAlternateNameInformation: { // If there is no alternate name Windows will return STATUS_OBJECT_NAME_NOT_FOUND result = null; return(NTStatus.STATUS_OBJECT_NAME_NOT_FOUND); } case FileInformationClass.FileStreamInformation: { // This information class is used to enumerate the data streams of a file or a directory. // A buffer of FileStreamInformation data elements is returned by the server. FileStreamInformation information = new FileStreamInformation(); List <KeyValuePair <string, ulong> > dataStreams = m_fileSystem.ListDataStreams(fileHandle.Path); foreach (KeyValuePair <string, ulong> dataStream in dataStreams) { FileStreamEntry streamEntry = new FileStreamEntry(); ulong streamSize = dataStream.Value; streamEntry.StreamSize = (long)streamSize; streamEntry.StreamAllocationSize = (long)GetAllocationSize(streamSize); streamEntry.StreamName = dataStream.Key; information.Entries.Add(streamEntry); } result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FilePipeInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FilePipeLocalInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FilePipeRemoteInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileCompressionInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } case FileInformationClass.FileNetworkOpenInformation: { FileNetworkOpenInformation information = new FileNetworkOpenInformation(); information.CreationTime = entry.CreationTime; information.LastAccessTime = entry.LastAccessTime; information.LastWriteTime = entry.LastWriteTime; information.ChangeTime = entry.LastWriteTime; information.AllocationSize = (long)GetAllocationSize(entry.Size); information.EndOfFile = (long)entry.Size; information.FileAttributes = GetFileAttributes(entry); result = information; return(NTStatus.STATUS_SUCCESS); } case FileInformationClass.FileAttributeTagInformation: { result = null; return(NTStatus.STATUS_NOT_IMPLEMENTED); } default: result = null; return(NTStatus.STATUS_INVALID_INFO_CLASS); } }
public static extern Win32ErrorCode LsaNtStatusToWinError(NTStatus Status);
public void ConvertNtStatus(NTStatus status, WindowsError expected) { Error.NtStatusToWinError(status).Should().Be(expected); }