diff --git a/SMBLibrary/Services/RPCPipeStream.cs b/SMBLibrary/Services/RPCPipeStream.cs index 8eda3f6..b8e26d9 100644 --- a/SMBLibrary/Services/RPCPipeStream.cs +++ b/SMBLibrary/Services/RPCPipeStream.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Tal Aloni . All rights reserved. +/* Copyright (C) 2017-2018 Tal Aloni . All rights reserved. * * You can redistribute this program and/or modify it under the terms of * the GNU Lesser Public License as published by the Free Software Foundation, @@ -55,21 +55,23 @@ namespace SMBLibrary.Services m_maxTransmitFragmentSize = bindAckPDU.MaxTransmitFragmentSize; Append(bindAckPDU.GetBytes()); } - else if (rpcRequest is RequestPDU) + else if (m_maxTransmitFragmentSize.HasValue && rpcRequest is RequestPDU) // if BindPDU was not received, we treat as protocol error { - // if BindPDU was not received, we ignore any subsequent RPC packets - if (m_maxTransmitFragmentSize.HasValue) + List responsePDUs = RemoteServiceHelper.GetRPCResponse((RequestPDU)rpcRequest, m_service, m_maxTransmitFragmentSize.Value); + foreach (RPCPDU responsePDU in responsePDUs) { - List responsePDUs = RemoteServiceHelper.GetRPCResponse((RequestPDU)rpcRequest, m_service, m_maxTransmitFragmentSize.Value); - foreach (ResponsePDU responsePDU in responsePDUs) - { - Append(responsePDU.GetBytes()); - } + Append(responsePDU.GetBytes()); } } else { - throw new NotImplementedException("Unsupported RPC Packet Type"); + FaultPDU faultPDU = new FaultPDU(); + faultPDU.Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment; + faultPDU.DataRepresentation = new DataRepresentationFormat(CharacterFormat.ASCII, ByteOrder.LittleEndian, FloatingPointRepresentation.IEEE); + faultPDU.CallID = 0; + faultPDU.AllocationHint = RPCPDU.CommonFieldsLength + FaultPDU.FaultFieldsLength; + faultPDU.Status = FaultStatus.ProtocolError; + Append(faultPDU.GetBytes()); } } diff --git a/SMBLibrary/Services/RemoteServiceHelper.cs b/SMBLibrary/Services/RemoteServiceHelper.cs index 77435b0..8ccde54 100644 --- a/SMBLibrary/Services/RemoteServiceHelper.cs +++ b/SMBLibrary/Services/RemoteServiceHelper.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2017 Tal Aloni . All rights reserved. +/* Copyright (C) 2014-2018 Tal Aloni . All rights reserved. * * You can redistribute this program and/or modify it under the terms of * the GNU Lesser Public License as published by the Free Software Foundation, @@ -107,11 +107,28 @@ namespace SMBLibrary.Services return -1; } - public static List GetRPCResponse(RequestPDU requestPDU, RemoteService service, int maxTransmitFragmentSize) + public static List GetRPCResponse(RequestPDU requestPDU, RemoteService service, int maxTransmitFragmentSize) { - byte[] responseBytes = service.GetResponseBytes(requestPDU.OpNum, requestPDU.Data); + List result = new List(); + byte[] responseBytes; + try + { + responseBytes = service.GetResponseBytes(requestPDU.OpNum, requestPDU.Data); + } + catch (UnsupportedOpNumException) + { + FaultPDU faultPDU = new FaultPDU(); + faultPDU.Flags = PacketFlags.FirstFragment | PacketFlags.LastFragment | PacketFlags.DidNotExecute; + faultPDU.DataRepresentation = requestPDU.DataRepresentation; + faultPDU.CallID = requestPDU.CallID; + faultPDU.AllocationHint = RPCPDU.CommonFieldsLength + FaultPDU.FaultFieldsLength; + // Windows will return either nca_s_fault_ndr or nca_op_rng_error. + faultPDU.Status = FaultStatus.OpRangeError; + result.Add(faultPDU); + return result; + } + int offset = 0; - List result = new List(); int maxPDUDataLength = maxTransmitFragmentSize - RPCPDU.CommonFieldsLength - ResponsePDU.ResponseFieldsLength; do { diff --git a/SMBLibrary/Services/ServerService/ServerService.cs b/SMBLibrary/Services/ServerService/ServerService.cs index 7d37b70..5b84318 100644 --- a/SMBLibrary/Services/ServerService/ServerService.cs +++ b/SMBLibrary/Services/ServerService/ServerService.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2017 Tal Aloni . All rights reserved. +/* Copyright (C) 2014-2018 Tal Aloni . All rights reserved. * * You can redistribute this program and/or modify it under the terms of * the GNU Lesser Public License as published by the Free Software Foundation, @@ -64,41 +64,57 @@ namespace SMBLibrary.Services return response.GetBytes(); } default: - throw new NotImplementedException(); + throw new UnsupportedOpNumException(); } } public NetrShareEnumResponse GetNetrShareEnumResponse(NetrShareEnumRequest request) { NetrShareEnumResponse response = new NetrShareEnumResponse(); - if (request.InfoStruct.Level == 0) + switch (request.InfoStruct.Level) { - // We ignore request.PreferedMaximumLength - ShareInfo0Container info = new ShareInfo0Container(); - foreach (string shareName in m_shares) - { - info.Add(new ShareInfo0Entry(shareName)); - } - response.InfoStruct = new ShareEnum(info); - response.TotalEntries = (uint)m_shares.Count; + case 0: + { + // We ignore request.PreferedMaximumLength + ShareInfo0Container info = new ShareInfo0Container(); + foreach (string shareName in m_shares) + { + info.Add(new ShareInfo0Entry(shareName)); + } + response.InfoStruct = new ShareEnum(info); + response.TotalEntries = (uint)m_shares.Count; + response.Result = Win32Error.ERROR_SUCCESS; + return response; + } + case 1: + { + // We ignore request.PreferedMaximumLength + ShareInfo1Container info = new ShareInfo1Container(); + foreach (string shareName in m_shares) + { + info.Add(new ShareInfo1Entry(shareName, new ShareTypeExtended(ShareType.DiskDrive))); + } + response.InfoStruct = new ShareEnum(info); + response.TotalEntries = (uint)m_shares.Count; + response.Result = Win32Error.ERROR_SUCCESS; + return response; + } + case 2: + case 501: + case 502: + case 503: + { + response.InfoStruct = new ShareEnum(request.InfoStruct.Level); + response.Result = Win32Error.ERROR_NOT_SUPPORTED; + return response; + } + default: + { + response.InfoStruct = new ShareEnum(request.InfoStruct.Level); + response.Result = Win32Error.ERROR_INVALID_LEVEL; + return response; + } } - else if (request.InfoStruct.Level == 1) - { - // We ignore request.PreferedMaximumLength - ShareInfo1Container info = new ShareInfo1Container(); - foreach (string shareName in m_shares) - { - info.Add(new ShareInfo1Entry(shareName, new ShareTypeExtended(ShareType.DiskDrive))); - } - response.InfoStruct = new ShareEnum(info); - response.TotalEntries = (uint)m_shares.Count; - } - else - { - throw new NotImplementedException(); - } - response.Result = Win32Error.ERROR_SUCCESS; - return response; } public NetrShareGetInfoResponse GetNetrShareGetInfoResponse(NetrShareGetInfoRequest request) @@ -113,56 +129,90 @@ namespace SMBLibrary.Services return response; } - if (request.Level == 0) + switch (request.Level) { - ShareInfo0Entry info = new ShareInfo0Entry(m_shares[shareIndex]); - response.InfoStruct = new ShareInfo(info); + case 0: + { + ShareInfo0Entry info = new ShareInfo0Entry(m_shares[shareIndex]); + response.InfoStruct = new ShareInfo(info); + response.Result = Win32Error.ERROR_SUCCESS; + return response; + } + case 1: + { + ShareInfo1Entry info = new ShareInfo1Entry(m_shares[shareIndex], new ShareTypeExtended(ShareType.DiskDrive)); + response.InfoStruct = new ShareInfo(info); + response.Result = Win32Error.ERROR_SUCCESS; + return response; + } + case 2: + { + ShareInfo2Entry info = new ShareInfo2Entry(m_shares[shareIndex], new ShareTypeExtended(ShareType.DiskDrive)); + response.InfoStruct = new ShareInfo(info); + response.Result = Win32Error.ERROR_SUCCESS; + return response; + } + case 501: + case 502: + case 503: + case 1005: + { + response.InfoStruct = new ShareInfo(request.Level); + response.Result = Win32Error.ERROR_NOT_SUPPORTED; + return response; + } + default: + { + response.InfoStruct = new ShareInfo(request.Level); + response.Result = Win32Error.ERROR_INVALID_LEVEL; + return response; + } } - else if (request.Level == 1) - { - ShareInfo1Entry info = new ShareInfo1Entry(m_shares[shareIndex], new ShareTypeExtended(ShareType.DiskDrive)); - response.InfoStruct = new ShareInfo(info); - } - else if (request.Level == 2) - { - ShareInfo2Entry info = new ShareInfo2Entry(m_shares[shareIndex], new ShareTypeExtended(ShareType.DiskDrive)); - response.InfoStruct = new ShareInfo(info); - } - else - { - throw new NotImplementedException(); - } - response.Result = Win32Error.ERROR_SUCCESS; - return response; } public NetrServerGetInfoResponse GetNetrWkstaGetInfoResponse(NetrServerGetInfoRequest request) { NetrServerGetInfoResponse response = new NetrServerGetInfoResponse(); - if (request.Level == 100) + switch (request.Level) { - ServerInfo100 info = new ServerInfo100(); - info.PlatformID = m_platformID; - info.ServerName.Value = m_serverName; - response.InfoStruct = new ServerInfo(info); + case 100: + { + ServerInfo100 info = new ServerInfo100(); + info.PlatformID = m_platformID; + info.ServerName.Value = m_serverName; + response.InfoStruct = new ServerInfo(info); + response.Result = Win32Error.ERROR_SUCCESS; + return response; + } + case 101: + { + ServerInfo101 info = new ServerInfo101(); + info.PlatformID = m_platformID; + info.ServerName.Value = m_serverName; + info.VerMajor = m_verMajor; + info.VerMinor = m_verMinor; + info.Type = m_serverType; + info.Comment.Value = String.Empty; + response.InfoStruct = new ServerInfo(info); + response.Result = Win32Error.ERROR_SUCCESS; + return response; + } + case 102: + case 103: + case 502: + case 503: + { + response.InfoStruct = new ServerInfo(request.Level); + response.Result = Win32Error.ERROR_NOT_SUPPORTED; + return response; + } + default: + { + response.InfoStruct = new ServerInfo(request.Level); + response.Result = Win32Error.ERROR_INVALID_LEVEL; + return response; + } } - else if (request.Level == 101) - { - ServerInfo101 info = new ServerInfo101(); - info.PlatformID = m_platformID; - info.ServerName.Value = m_serverName; - info.VerMajor = m_verMajor; - info.VerMinor = m_verMinor; - info.Type = m_serverType; - info.Comment.Value = String.Empty; - response.InfoStruct = new ServerInfo(info); - } - else - { - throw new NotImplementedException(); - } - response.Result = Win32Error.ERROR_SUCCESS; - return response; } private int IndexOfShare(string shareName) diff --git a/SMBLibrary/Services/WorkstationService/WorkstationService.cs b/SMBLibrary/Services/WorkstationService/WorkstationService.cs index 43168b2..224171a 100644 --- a/SMBLibrary/Services/WorkstationService/WorkstationService.cs +++ b/SMBLibrary/Services/WorkstationService/WorkstationService.cs @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2017 Tal Aloni . All rights reserved. +/* Copyright (C) 2014-2018 Tal Aloni . All rights reserved. * * You can redistribute this program and/or modify it under the terms of * the GNU Lesser Public License as published by the Free Software Foundation, @@ -43,40 +43,54 @@ namespace SMBLibrary.Services NetrWkstaGetInfoResponse response = GetNetrWkstaGetInfoResponse(request); return response.GetBytes(); default: - throw new NotImplementedException(); + throw new UnsupportedOpNumException(); } } public NetrWkstaGetInfoResponse GetNetrWkstaGetInfoResponse(NetrWkstaGetInfoRequest request) { NetrWkstaGetInfoResponse response = new NetrWkstaGetInfoResponse(); - if (request.Level == 100) + switch (request.Level) { - WorkstationInfo100 info = new WorkstationInfo100(); - info.PlatformID = m_platformID; - info.ComputerName.Value = m_computerName; - info.LanGroup.Value = m_lanGroup; - info.VerMajor = m_verMajor; - info.VerMinor = m_verMinor; - response.WkstaInfo = new WorkstationInfo(info); + case 100: + { + WorkstationInfo100 info = new WorkstationInfo100(); + info.PlatformID = m_platformID; + info.ComputerName.Value = m_computerName; + info.LanGroup.Value = m_lanGroup; + info.VerMajor = m_verMajor; + info.VerMinor = m_verMinor; + response.WkstaInfo = new WorkstationInfo(info); + response.Result = Win32Error.ERROR_SUCCESS; + return response; + } + case 101: + { + WorkstationInfo101 info = new WorkstationInfo101(); + info.PlatformID = m_platformID; + info.ComputerName.Value = m_computerName; + info.LanGroup.Value = m_lanGroup; + info.VerMajor = m_verMajor; + info.VerMinor = m_verMinor; + info.LanRoot.Value = m_lanGroup; + response.WkstaInfo = new WorkstationInfo(info); + response.Result = Win32Error.ERROR_SUCCESS; + return response; + } + case 102: + case 502: + { + response.WkstaInfo = new WorkstationInfo(request.Level); + response.Result = Win32Error.ERROR_NOT_SUPPORTED; + return response; + } + default: + { + response.WkstaInfo = new WorkstationInfo(request.Level); + response.Result = Win32Error.ERROR_INVALID_LEVEL; + return response; + } } - else if (request.Level == 101) - { - WorkstationInfo101 info = new WorkstationInfo101(); - info.PlatformID = m_platformID; - info.ComputerName.Value = m_computerName; - info.LanGroup.Value = m_lanGroup; - info.VerMajor = m_verMajor; - info.VerMinor = m_verMinor; - info.LanRoot.Value = m_lanGroup; - response.WkstaInfo = new WorkstationInfo(info); - } - else - { - throw new NotImplementedException(); - } - response.Result = Win32Error.ERROR_SUCCESS; - return response; } public override Guid InterfaceGuid