ServerService, WorkstationService: Unsupported OpNums and Levels are now reported back to the client instead of NotImplementedException

This commit is contained in:
Tal Aloni 2018-05-17 14:36:55 +03:00
parent 3289c0e333
commit fc048b1232
4 changed files with 193 additions and 110 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
/* Copyright (C) 2017-2018 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
*
* You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation,
@ -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<RPCPDU> responsePDUs = RemoteServiceHelper.GetRPCResponse((RequestPDU)rpcRequest, m_service, m_maxTransmitFragmentSize.Value);
foreach (RPCPDU responsePDU in responsePDUs)
{
List<ResponsePDU> 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());
}
}

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
/* Copyright (C) 2014-2018 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
*
* You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation,
@ -107,11 +107,28 @@ namespace SMBLibrary.Services
return -1;
}
public static List<ResponsePDU> GetRPCResponse(RequestPDU requestPDU, RemoteService service, int maxTransmitFragmentSize)
public static List<RPCPDU> GetRPCResponse(RequestPDU requestPDU, RemoteService service, int maxTransmitFragmentSize)
{
byte[] responseBytes = service.GetResponseBytes(requestPDU.OpNum, requestPDU.Data);
List<RPCPDU> result = new List<RPCPDU>();
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<ResponsePDU> result = new List<ResponsePDU>();
int maxPDUDataLength = maxTransmitFragmentSize - RPCPDU.CommonFieldsLength - ResponsePDU.ResponseFieldsLength;
do
{

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
/* Copyright (C) 2014-2018 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
*
* You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation,
@ -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)

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2014-2017 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
/* Copyright (C) 2014-2018 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
*
* You can redistribute this program and/or modify it under the terms of
* the GNU Lesser Public License as published by the Free Software Foundation,
@ -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