Skip to content

Commit a6fc7fd

Browse files
committed
Send AuthData if needed for multiple security context.
1 parent e5ab4d5 commit a6fc7fd

2 files changed

Lines changed: 55 additions & 21 deletions

File tree

NtApiDotNet/Win32/Rpc/Transport/RpcConnectedClientTransport.cs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
// limitations under the License.
1414

1515
using NtApiDotNet.Ndr.Marshal;
16-
using NtApiDotNet.Utilities.Misc;
1716
using NtApiDotNet.Win32.Rpc.Transport.PDU;
1817
using NtApiDotNet.Win32.Security.Authentication;
1918
using System;
@@ -47,6 +46,13 @@ protected RpcConnectedClientTransport(ushort max_recv_fragment, ushort max_send_
4746
_security_context = new Dictionary<int, RpcTransportSecurityContext>();
4847
_current_security_context = new RpcTransportSecurityContext(this, transport_security, _current_context_id++);
4948
_security_context[_current_security_context.ContextId] = _current_security_context;
49+
switch (transport_security.AuthenticationLevel)
50+
{
51+
case RpcAuthenticationLevel.PacketIntegrity:
52+
case RpcAuthenticationLevel.PacketPrivacy:
53+
_auth_data_required = true;
54+
break;
55+
}
5056

5157
if (DisableBindTimeFeatureNegotiation)
5258
_bind_time_features = BindTimeFeatureNegotiation.None;
@@ -75,13 +81,14 @@ protected RpcConnectedClientTransport(ushort max_recv_fragment, ushort max_send_
7581
private ushort _max_recv_fragment;
7682
private ushort _max_send_fragment;
7783
private int _recv_sequence_no;
78-
private int _send_senqunce_no;
84+
private int _send_sequence_no;
7985
private BindTimeFeatureNegotiation? _bind_time_features;
8086
private bool _transport_bound;
8187
private Guid _interface_id;
8288
private Version _interface_version;
8389
private Guid _transfer_syntax_id;
8490
private Version _transfer_syntax_version;
91+
private bool _auth_data_required;
8592

8693
private PDUBase CheckFault(PDUBase pdu)
8794
{
@@ -149,7 +156,7 @@ private Tuple<PDUBase, AuthData> SendReceivePDU(int call_id, PDUBase send_pdu, b
149156
RpcUtils.DumpBuffer(true, $"{GetType().Name} Send Buffer", fragment);
150157
if (!WriteFragment(fragment))
151158
throw new RpcTransportException("Failed to write out PDU buffer.");
152-
_send_senqunce_no++;
159+
_send_sequence_no++;
153160
if (!receive_pdu)
154161
return null;
155162

@@ -213,13 +220,11 @@ private byte[] SendReceiveRequestPDU(int proc_num, Guid objuuid, byte[] stub_dat
213220
int max_fragment = _max_send_fragment - request_pdu.HeaderLength;
214221
int auth_data_length = 0;
215222

216-
bool auth_required = false;
217-
if (security_context.NeedAuthData)
223+
if (_auth_data_required)
218224
{
219225
auth_data_length = security_context.AuthDataLength;
220226
max_fragment -= (auth_data_length + AuthData.PDU_AUTH_DATA_HEADER_SIZE);
221227
max_fragment &= ~0xF;
222-
auth_required = true;
223228
}
224229

225230
List<byte[]> fragments = PDURequest.DoFragment(stub_data, max_fragment);
@@ -246,7 +251,7 @@ private byte[] SendReceiveRequestPDU(int proc_num, Guid objuuid, byte[] stub_dat
246251
byte[] stub_fragment = fragments[i];
247252
byte[] auth_data = new byte[0];
248253
byte[] header = request_pdu.ToArray(pdu_header, stub_fragment.Length, 0);
249-
if (auth_required)
254+
if (_auth_data_required)
250255
{
251256
int auth_data_padding = 0;
252257
int auth_trailing_size = (header.Length + stub_fragment.Length + AuthData.PDU_AUTH_DATA_HEADER_SIZE) & 0xF;
@@ -257,7 +262,7 @@ private byte[] SendReceiveRequestPDU(int proc_num, Guid objuuid, byte[] stub_dat
257262
}
258263

259264
header = request_pdu.ToArray(pdu_header, stub_fragment.Length + AuthData.PDU_AUTH_DATA_HEADER_SIZE, auth_data_length);
260-
auth_data = security_context.ProtectPDU(header, ref stub_fragment, auth_data_padding, _send_senqunce_no);
265+
auth_data = security_context.ProtectPDU(header, ref stub_fragment, auth_data_padding, _send_sequence_no);
261266
}
262267

263268
MemoryStream send_stm = new MemoryStream();
@@ -270,7 +275,7 @@ private byte[] SendReceiveRequestPDU(int proc_num, Guid objuuid, byte[] stub_dat
270275
RpcUtils.DumpBuffer(true, name, fragment);
271276
if (!WriteFragment(fragment))
272277
throw new RpcTransportException("Failed to write out PDU buffer.");
273-
_send_senqunce_no++;
278+
_send_sequence_no++;
274279
}
275280

276281
MemoryStream recv_stm = new MemoryStream();
@@ -294,7 +299,7 @@ private byte[] SendReceiveRequestPDU(int proc_num, Guid objuuid, byte[] stub_dat
294299
var recv_pdu = CheckFault(curr_header.ToPDU(pdu.Item2));
295300
if (recv_pdu is PDUResponse resp_pdu)
296301
{
297-
byte[] resp_stub_data = auth_required ? security_context.UnprotectPDU(resp_pdu.ToArray(curr_header),
302+
byte[] resp_stub_data = _auth_data_required ? security_context.UnprotectPDU(resp_pdu.ToArray(curr_header),
298303
resp_pdu.StubData, auth_data, _recv_sequence_no) : resp_pdu.StubData;
299304
_recv_sequence_no++;
300305
recv_stm.Write(resp_stub_data, 0, resp_stub_data.Length);
@@ -528,15 +533,24 @@ public RpcTransportSecurityContext AddSecurityContext(RpcTransportSecurity trans
528533
{
529534
if (!SupportsMultipleSecurityContexts)
530535
throw new InvalidOperationException("Transport doesn't support multiple security context.");
531-
if (transport_security.AuthenticationLevel < RpcAuthenticationLevel.PacketIntegrity)
532-
throw new ArgumentException("Can only create a new context with higher authentication level.");
536+
switch (transport_security.AuthenticationLevel)
537+
{
538+
case RpcAuthenticationLevel.Connect:
539+
case RpcAuthenticationLevel.PacketIntegrity:
540+
case RpcAuthenticationLevel.PacketPrivacy:
541+
break;
542+
default:
543+
throw new ArgumentException("Can only create a new context with specific authentication levels.");
544+
}
545+
533546
if (!_transport_bound)
534547
throw new InvalidOperationException("Transport hasn't been bound yet.");
535548
var context = new RpcTransportSecurityContext(this,
536549
transport_security, _current_context_id++);
537550
try
538551
{
539552
BindAuth(true, context);
553+
_auth_data_required = true;
540554
return _security_context[context.ContextId] = context;
541555
}
542556
catch
@@ -577,7 +591,6 @@ public RpcClientResponse SendReceive(int proc_num, Guid objuuid, NdrDataRepresen
577591
/// </summary>
578592
/// <remarks>Should be set before connecting an RPC client.</remarks>
579593
public static bool DisableBindTimeFeatureNegotiation { get; set; }
580-
581594
#endregion
582595

583596
#region IDisposable implementation.

NtApiDotNet/Win32/Rpc/Transport/RpcTransportSecurityContext.cs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,23 @@ public sealed class RpcTransportSecurityContext
5050
public RpcAuthenticationLevel AuthenticationLevel => TransportSecurity.AuthenticationLevel;
5151

5252
internal bool Authenticated => AuthContext?.Done ?? false;
53-
internal bool NeedAuthData => TransportSecurity.AuthenticationLevel == RpcAuthenticationLevel.PacketIntegrity ||
54-
TransportSecurity.AuthenticationLevel == RpcAuthenticationLevel.PacketPrivacy;
55-
internal int AuthDataLength => TransportSecurity.AuthenticationLevel == RpcAuthenticationLevel.PacketIntegrity ?
56-
AuthContext.MaxSignatureSize : AuthContext.SecurityTrailerSize;
53+
54+
internal int AuthDataLength
55+
{
56+
get
57+
{
58+
switch (TransportSecurity.AuthenticationLevel)
59+
{
60+
case RpcAuthenticationLevel.PacketIntegrity:
61+
return AuthContext.MaxSignatureSize;
62+
case RpcAuthenticationLevel.PacketPrivacy:
63+
return AuthContext.SecurityTrailerSize;
64+
default:
65+
return 0;
66+
}
67+
}
68+
}
69+
5770
internal int MaxAuthLegs => TransportSecurity.AuthenticationType == RpcAuthenticationType.WinNT ? 3 : 8;
5871

5972
internal void SetNegotiatedAuthType()
@@ -97,19 +110,23 @@ internal byte[] ProtectPDU(byte[] header, ref byte[] stub_data, int auth_padding
97110
buffers.Add(new SecurityBufferInOut(SecurityBufferType.Data | SecurityBufferType.ReadOnly,
98111
AuthData.ToArray(TransportSecurity, auth_padding_length, ContextId, new byte[0])));
99112

100-
byte[] signature;
113+
byte[] signature = new byte[0];
101114
if (TransportSecurity.AuthenticationLevel == RpcAuthenticationLevel.PacketIntegrity)
102115
{
103116
signature = AuthContext.MakeSignature(buffers, send_sequence_no);
104117
}
105-
else
118+
else if (TransportSecurity.AuthenticationLevel == RpcAuthenticationLevel.PacketPrivacy)
106119
{
107120
signature = AuthContext.EncryptMessage(buffers, SecurityQualityOfProtectionFlags.None, send_sequence_no);
108121
stub_data = stub_data_buffer.ToArray();
109122
RpcUtils.DumpBuffer(true, "Send Encrypted Data", stub_data);
110123
}
111124

112-
RpcUtils.DumpBuffer(true, "Send Signature Data", signature);
125+
if (signature.Length > 0)
126+
{
127+
RpcUtils.DumpBuffer(true, "Send Signature Data", signature);
128+
}
129+
113130
return AuthData.ToArray(TransportSecurity, auth_padding_length, ContextId, signature);
114131
}
115132

@@ -134,11 +151,15 @@ internal byte[] UnprotectPDU(byte[] header, byte[] stub_data, AuthData auth_data
134151
throw new RpcTransportException("Invalid response PDU signature.");
135152
}
136153
}
137-
else
154+
else if (TransportSecurity.AuthenticationLevel == RpcAuthenticationLevel.PacketPrivacy)
138155
{
139156
AuthContext.DecryptMessage(buffers, signature, recv_sequence_no);
140157
stub_data = stub_data_buffer.ToArray();
141158
}
159+
else
160+
{
161+
// Do nothing.
162+
}
142163

143164
Array.Resize(ref stub_data, stub_data.Length - auth_data.Padding);
144165

0 commit comments

Comments
 (0)