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 * 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, * the GNU Lesser Public License as published by the Free Software Foundation,
@ -55,21 +55,23 @@ namespace SMBLibrary.Services
m_maxTransmitFragmentSize = bindAckPDU.MaxTransmitFragmentSize; m_maxTransmitFragmentSize = bindAckPDU.MaxTransmitFragmentSize;
Append(bindAckPDU.GetBytes()); 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 List<RPCPDU> responsePDUs = RemoteServiceHelper.GetRPCResponse((RequestPDU)rpcRequest, m_service, m_maxTransmitFragmentSize.Value);
if (m_maxTransmitFragmentSize.HasValue) foreach (RPCPDU responsePDU in responsePDUs)
{ {
List<ResponsePDU> responsePDUs = RemoteServiceHelper.GetRPCResponse((RequestPDU)rpcRequest, m_service, m_maxTransmitFragmentSize.Value); Append(responsePDU.GetBytes());
foreach (ResponsePDU responsePDU in responsePDUs)
{
Append(responsePDU.GetBytes());
}
} }
} }
else 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 * 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, * the GNU Lesser Public License as published by the Free Software Foundation,
@ -107,11 +107,28 @@ namespace SMBLibrary.Services
return -1; 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; int offset = 0;
List<ResponsePDU> result = new List<ResponsePDU>();
int maxPDUDataLength = maxTransmitFragmentSize - RPCPDU.CommonFieldsLength - ResponsePDU.ResponseFieldsLength; int maxPDUDataLength = maxTransmitFragmentSize - RPCPDU.CommonFieldsLength - ResponsePDU.ResponseFieldsLength;
do 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 * 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, * the GNU Lesser Public License as published by the Free Software Foundation,
@ -64,41 +64,57 @@ namespace SMBLibrary.Services
return response.GetBytes(); return response.GetBytes();
} }
default: default:
throw new NotImplementedException(); throw new UnsupportedOpNumException();
} }
} }
public NetrShareEnumResponse GetNetrShareEnumResponse(NetrShareEnumRequest request) public NetrShareEnumResponse GetNetrShareEnumResponse(NetrShareEnumRequest request)
{ {
NetrShareEnumResponse response = new NetrShareEnumResponse(); NetrShareEnumResponse response = new NetrShareEnumResponse();
if (request.InfoStruct.Level == 0) switch (request.InfoStruct.Level)
{ {
// We ignore request.PreferedMaximumLength case 0:
ShareInfo0Container info = new ShareInfo0Container(); {
foreach (string shareName in m_shares) // We ignore request.PreferedMaximumLength
{ ShareInfo0Container info = new ShareInfo0Container();
info.Add(new ShareInfo0Entry(shareName)); foreach (string shareName in m_shares)
} {
response.InfoStruct = new ShareEnum(info); info.Add(new ShareInfo0Entry(shareName));
response.TotalEntries = (uint)m_shares.Count; }
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) public NetrShareGetInfoResponse GetNetrShareGetInfoResponse(NetrShareGetInfoRequest request)
@ -113,56 +129,90 @@ namespace SMBLibrary.Services
return response; return response;
} }
if (request.Level == 0) switch (request.Level)
{ {
ShareInfo0Entry info = new ShareInfo0Entry(m_shares[shareIndex]); case 0:
response.InfoStruct = new ShareInfo(info); {
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) public NetrServerGetInfoResponse GetNetrWkstaGetInfoResponse(NetrServerGetInfoRequest request)
{ {
NetrServerGetInfoResponse response = new NetrServerGetInfoResponse(); NetrServerGetInfoResponse response = new NetrServerGetInfoResponse();
if (request.Level == 100) switch (request.Level)
{ {
ServerInfo100 info = new ServerInfo100(); case 100:
info.PlatformID = m_platformID; {
info.ServerName.Value = m_serverName; ServerInfo100 info = new ServerInfo100();
response.InfoStruct = new ServerInfo(info); 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) 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 * 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, * the GNU Lesser Public License as published by the Free Software Foundation,
@ -43,40 +43,54 @@ namespace SMBLibrary.Services
NetrWkstaGetInfoResponse response = GetNetrWkstaGetInfoResponse(request); NetrWkstaGetInfoResponse response = GetNetrWkstaGetInfoResponse(request);
return response.GetBytes(); return response.GetBytes();
default: default:
throw new NotImplementedException(); throw new UnsupportedOpNumException();
} }
} }
public NetrWkstaGetInfoResponse GetNetrWkstaGetInfoResponse(NetrWkstaGetInfoRequest request) public NetrWkstaGetInfoResponse GetNetrWkstaGetInfoResponse(NetrWkstaGetInfoRequest request)
{ {
NetrWkstaGetInfoResponse response = new NetrWkstaGetInfoResponse(); NetrWkstaGetInfoResponse response = new NetrWkstaGetInfoResponse();
if (request.Level == 100) switch (request.Level)
{ {
WorkstationInfo100 info = new WorkstationInfo100(); case 100:
info.PlatformID = m_platformID; {
info.ComputerName.Value = m_computerName; WorkstationInfo100 info = new WorkstationInfo100();
info.LanGroup.Value = m_lanGroup; info.PlatformID = m_platformID;
info.VerMajor = m_verMajor; info.ComputerName.Value = m_computerName;
info.VerMinor = m_verMinor; info.LanGroup.Value = m_lanGroup;
response.WkstaInfo = new WorkstationInfo(info); 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 public override Guid InterfaceGuid