Skip to content

Commit 614765a

Browse files
committed
Fixing few claims encoder issues and enabling a couple of tests
1 parent 89a6c16 commit 614765a

6 files changed

Lines changed: 171 additions & 45 deletions

File tree

Kerberos.NET/Entities/Krb/KrbKdcRep.cs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,16 @@ public KrbKdcRep()
2222
internal const TicketFlags DefaultFlags = TicketFlags.Renewable |
2323
TicketFlags.Forwardable;
2424

25-
public static KrbCred GenerateWrappedServiceTicket(ServiceTicketRequest request, KrbEncryptionKey encryptionKey = null)
25+
public static KrbCred GenerateWrappedServiceTicket(
26+
ServiceTicketRequest request,
27+
KrbEncryptionKey sessionKey = null,
28+
IEnumerable<KrbAuthorizationData> authz = null
29+
)
2630
{
2731
GenerateServiceTicket<KrbTgsRep>(
2832
request,
29-
encryptionKey,
33+
sessionKey,
34+
authz,
3035
out KrbEncTicketPart encTicketPart,
3136
out KrbTicket ticket,
3237
out _,
@@ -37,7 +42,11 @@ out _
3742
return KrbCred.WrapTicket(ticket, encTicketPart);
3843
}
3944

40-
public static T GenerateServiceTicket<T>(ServiceTicketRequest request, KrbEncryptionKey encryptionKey = null)
45+
public static T GenerateServiceTicket<T>(
46+
ServiceTicketRequest request,
47+
KrbEncryptionKey encryptionKey = null,
48+
IEnumerable<KrbAuthorizationData> authz = null
49+
)
4150
where T : KrbKdcRep, new()
4251
{
4352
if (request.EncryptedPartKey == null)
@@ -48,6 +57,7 @@ public static T GenerateServiceTicket<T>(ServiceTicketRequest request, KrbEncryp
4857
request = GenerateServiceTicket<T>(
4958
request,
5059
encryptionKey,
60+
authz,
5161
out KrbEncTicketPart encTicketPart,
5262
out KrbTicket ticket,
5363
out KrbEncKdcRepPart encKdcRepPart,
@@ -74,7 +84,8 @@ out MessageType messageType
7484

7585
private static ServiceTicketRequest GenerateServiceTicket<T>(
7686
ServiceTicketRequest request,
77-
KrbEncryptionKey encryptionKey,
87+
KrbEncryptionKey sessionKey,
88+
IEnumerable<KrbAuthorizationData> authz,
7889
out KrbEncTicketPart encTicketPart,
7990
out KrbTicket ticket,
8091
out KrbEncKdcRepPart encKdcRepPart,
@@ -103,9 +114,10 @@ out MessageType messageType
103114
request.RealmName = request.RealmName?.ToUpperInvariant();
104115
}
105116

106-
var authz = GenerateAuthorizationData(request);
107-
108-
var sessionKey = encryptionKey;
117+
if (authz == null)
118+
{
119+
authz = GenerateAuthorizationData(request);
120+
}
109121

110122
if (sessionKey == null)
111123
{

Kerberos.NET/Entities/Pac/ClaimEntry.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// -----------------------------------------------------------------------
1+
// -----------------------------------------------------------------------
22
// Licensed to The .NET Foundation under one or more agreements.
33
// The .NET Foundation licenses this file to you under the MIT license.
44
// -----------------------------------------------------------------------
@@ -30,8 +30,11 @@ public void Marshal(NdrBuffer buffer)
3030
throw new ArgumentNullException(nameof(buffer));
3131
}
3232

33-
buffer.WriteDeferredConformantVaryingArray(this.Id.AsMemory());
33+
buffer.WriteDeferredString(this.Id.AsMemory());
34+
35+
buffer.WriteInt16LittleEndian((short)this.Type);
3436

37+
// We have to repeat the type again
3538
buffer.WriteInt16LittleEndian((short)this.Type);
3639
buffer.WriteInt32LittleEndian(this.Count);
3740

@@ -45,7 +48,7 @@ public void Marshal(NdrBuffer buffer)
4548
[KerberosIgnore]
4649
public int Count { get; set; }
4750

48-
public IList<object> Values { get; private set; } = new List<object>();
51+
public IList<object> Values { get; set; } = new List<object>();
4952

5053
public IEnumerable<T> GetValuesOfType<T>()
5154
{
@@ -103,12 +106,12 @@ public void MarshalUnion(NdrBuffer buffer)
103106
case ClaimType.CLAIM_TYPE_STRING:
104107
var arr = this.GetValuesOfType<string>().Select(v => v.AsMemory());
105108

106-
buffer.WriteDeferredArray(arr, val => buffer.WriteConformantVaryingArray(val.Span));
109+
buffer.WriteDeferredArray(arr, val => buffer.WriteString(val.Span));
107110
break;
108111
default:
109112
buffer.WriteFixedPrimitiveArray<long>(this.GetValuesOfType<long>().ToArray());
110113
break;
111114
}
112115
}
113116
}
114-
}
117+
}

Kerberos.NET/Entities/Pac/ClaimsSet.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// -----------------------------------------------------------------------
1+
// -----------------------------------------------------------------------
22
// Licensed to The .NET Foundation under one or more agreements.
33
// The .NET Foundation licenses this file to you under the MIT license.
44
// -----------------------------------------------------------------------
@@ -24,7 +24,11 @@ public void Marshal(NdrBuffer buffer)
2424

2525
buffer.WriteInt16LittleEndian(this.ReservedType);
2626
buffer.WriteInt32LittleEndian(this.ReservedFieldSize);
27-
buffer.WriteDeferredConformantArray<byte>(this.ReservedField.Span);
27+
28+
// This.is the ReservedField that should be written to buffer as:
29+
// WriteDeferredConformantArray<byte>(this.ReservedField.Span)
30+
// However, it's currently reserved and should be 0
31+
buffer.WriteInt32LittleEndian(0);
2832
}
2933

3034
public void Unmarshal(NdrBuffer buffer)
@@ -55,4 +59,4 @@ public void Unmarshal(NdrBuffer buffer)
5559

5660
public ReadOnlyMemory<byte> ReservedField { get; set; }
5761
}
58-
}
62+
}

Kerberos.NET/Entities/Pac/ClaimsSetMetadata.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// -----------------------------------------------------------------------
1+
// -----------------------------------------------------------------------
22
// Licensed to The .NET Foundation under one or more agreements.
33
// The .NET Foundation licenses this file to you under the MIT license.
44
// -----------------------------------------------------------------------
@@ -30,7 +30,10 @@ public override void Marshal(NdrBuffer buffer)
3030
buffer.WriteInt16LittleEndian(this.ReservedType);
3131
buffer.WriteInt32LittleEndian(this.ReservedFieldSize);
3232

33-
buffer.WriteDeferredConformantArray<byte>(this.ReservedField.Span);
33+
// This.is the ReservedField that should be written to buffer as:
34+
// buffer.WriteDeferredConformantArray<byte>(this.ReservedField.Span)
35+
// However, it's currently reserved and should be 0
36+
buffer.WriteInt32LittleEndian(0);
3437
}
3538

3639
private static ReadOnlySpan<byte> Compress(ClaimsSet claimsSet, CompressionFormat compressionFormat, out int originalSize)
@@ -107,4 +110,4 @@ private ClaimsSet UnmarshalClaimsSet(ReadOnlyMemory<byte> claimSet)
107110

108111
public override PacType PacType => PacType.CLIENT_CLAIMS;
109112
}
110-
}
113+
}

Kerberos.NET/Ndr/NdrBuffer.Write.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,24 @@ public void WriteConformantVaryingArray<T>(ReadOnlySpan<T> array)
304304
}
305305
}
306306

307+
public void WriteDeferredString<T>(ReadOnlyMemory<T> buffer)
308+
where T : struct
309+
{
310+
if (this.WriteDeferred())
311+
{
312+
this.deferrals.Defer(() => this.WriteString(buffer.Span));
313+
}
314+
}
315+
316+
public void WriteString<T>(ReadOnlySpan<T> array)
317+
where T : struct
318+
{
319+
if (typeof(T) == typeof(char))
320+
{
321+
this.WriteNullTerminatedString(MemoryMarshal.Cast<T, char>(array));
322+
}
323+
}
324+
307325
private void WriteConformantVaryingCharArray(ReadOnlySpan<char> chars)
308326
{
309327
var indexOfNull = chars.IndexOf('\0');
@@ -324,6 +342,29 @@ private void WriteConformantVaryingCharArray(ReadOnlySpan<char> chars)
324342
this.WriteSpan(bytes);
325343
}
326344

345+
private void WriteNullTerminatedString(ReadOnlySpan<char> chars)
346+
{
347+
var indexOfNull = chars.IndexOf('\0');
348+
349+
var charWrite = chars;
350+
351+
if (indexOfNull > 0)
352+
{
353+
charWrite = chars.Slice(0, indexOfNull);
354+
}
355+
356+
var bytes = MemoryMarshal.Cast<char, byte>(charWrite);
357+
358+
this.WriteInt32LittleEndian(charWrite.Length + 1);
359+
this.WriteInt32LittleEndian(0);
360+
this.WriteInt32LittleEndian(charWrite.Length + 1);
361+
362+
this.WriteSpan(bytes);
363+
364+
// Null termination char
365+
this.WriteInt16LittleEndian(0);
366+
}
367+
327368
public void WriteDeferredConformantArray<T>(ReadOnlySpan<T> span)
328369
where T : struct
329370
{

Tests/Tests.Kerberos.NET/Pac/NdrTests.cs

Lines changed: 90 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// -----------------------------------------------------------------------
1+
// -----------------------------------------------------------------------
22
// Licensed to The .NET Foundation under one or more agreements.
33
// The .NET Foundation licenses this file to you under the MIT license.
44
// -----------------------------------------------------------------------
@@ -33,6 +33,69 @@ public class NdrTests : BaseTest
3333
"QpXsMxbf8OTdTpPUjM+YO15nLKpyU1OkLkPG2OotRgIp0NoeKcyaSBsTCBrqADAgEXooGmBIGj24IhfgqoJAvOcADQ4hEiN9rrnB1iG43jBJqvsZlPtiy60LMNDKQEiQrW5yNca11V8ZJP0iPG" +
3434
"xEmequOqPQvcSAk4I3EpzYH7wcdvBN/Cie0xUC6nrLJAoO1sScn7iiR2xKwBwOLWSvJzUa5XZ7OlelLQjYCp2r3+I6TMPf8OUEvuhzSfKm5rBiHpR9owA83+RsGtXTAQsFZ8bghEsO8Q9QRq9A==";
3535

36+
37+
[TestMethod]
38+
public void NdrClientClaimsEncoding()
39+
{
40+
byte[] encodedClientClaims =
41+
{0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42+
0x00, 0x00, 0x02, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
43+
0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44+
0xe8, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xd8, 0x00, 0x00, 0x00,
45+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
46+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
47+
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
48+
0x0c, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00,
49+
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x31, 0x00, 0x32, 0x00,
50+
0x33, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x37, 0x00, 0x00, 0x00,
51+
0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x65, 0x00, 0x79, 0x00, 0x4a, 0x00, 0x30, 0x00,
52+
0x65, 0x00, 0x58, 0x00, 0x41, 0x00, 0x69, 0x00, 0x4f, 0x00, 0x69, 0x00, 0x4a, 0x00, 0x4b, 0x00,
53+
0x56, 0x00, 0x31, 0x00, 0x51, 0x00, 0x69, 0x00, 0x4c, 0x00, 0x43, 0x00, 0x4a, 0x00, 0x68, 0x00,
54+
0x62, 0x00, 0x47, 0x00, 0x63, 0x00, 0x69, 0x00, 0x4f, 0x00, 0x69, 0x00, 0x4a, 0x00, 0x53, 0x00,
55+
0x55, 0x00, 0x7a, 0x00, 0x49, 0x00, 0x31, 0x00, 0x4e, 0x00, 0x69, 0x00, 0x49, 0x00, 0x73, 0x00,
56+
0x49, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x31, 0x00, 0x64, 0x00, 0x43, 0x00, 0x49, 0x00, 0x36, 0x00,
57+
0x49, 0x00, 0x6b, 0x00, 0x31, 0x00, 0x48, 0x00, 0x54, 0x00, 0x48, 0x00, 0x46, 0x00, 0x71, 0x00,
58+
0x4f, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
59+
60+
ClaimEntry entry = new ClaimEntry
61+
{
62+
Id = "123",
63+
Type = ClaimType.CLAIM_TYPE_STRING,
64+
Values = new List<object> { "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1HTHFqOT" }
65+
};
66+
67+
entry.Count = entry.Values.Count;
68+
69+
ClaimsArray array = new ClaimsArray
70+
{
71+
ClaimSource = ClaimSourceType.CLAIMS_SOURCE_TYPE_AD,
72+
ClaimEntries = new List<ClaimEntry> { entry },
73+
Count = 1
74+
};
75+
76+
ClaimsSet claims = new ClaimsSet
77+
{
78+
ReservedType = 0,
79+
ClaimsArray = new List<ClaimsArray> { array },
80+
ReservedField = ReadOnlyMemory<byte>.Empty,
81+
Count = 1,
82+
ReservedFieldSize = 0
83+
};
84+
85+
ClaimsSetMetadata ClientClaims = new ClaimsSetMetadata
86+
{
87+
ClaimsSet = claims,
88+
CompressionFormat = CompressionFormat.COMPRESSION_FORMAT_NONE,
89+
ReservedType = 0,
90+
ReservedField = ReadOnlyMemory<byte>.Empty,
91+
ReservedFieldSize = 0
92+
};
93+
94+
var encoded = ClientClaims.Marshal();
95+
96+
Assert.IsTrue(encoded.Span.SequenceEqual(encodedClientClaims));
97+
}
98+
3699
private static async Task<PrivilegedAttributeCertificate> GeneratePac(bool includeClaims)
37100
{
38101
DecryptedKrbApReq result = null;
@@ -155,41 +218,41 @@ public async Task PacServerSignatureRoundtrip()
155218
Assert.IsTrue(signature.Signature.Span.SequenceEqual(signatureDecoded.Signature.Span));
156219
}
157220

158-
// [TestMethod]
159-
// public async Task NdrClaimsRoundtrip()
160-
// {
161-
// var pac = await GeneratePac(true);
221+
[TestMethod]
222+
public async Task NdrClaimsRoundtrip()
223+
{
224+
var pac = await GeneratePac(true);
162225

163-
// var claims = pac.ClientClaims;
226+
var claims = pac.ClientClaims;
164227

165-
// var claimsDecoded = TestPacEncoding(claims);
228+
var claimsDecoded = TestPacEncoding(claims);
166229

167-
// Assert.IsNotNull(claimsDecoded);
230+
Assert.IsNotNull(claimsDecoded);
168231

169-
// Assert.AreEqual(claims.ClaimsSet.ClaimsArray.Count(), claimsDecoded.ClaimsSet.ClaimsArray.Count());
232+
Assert.AreEqual(claims.ClaimsSet.ClaimsArray.Count(), claimsDecoded.ClaimsSet.ClaimsArray.Count());
170233

171-
// for (var i = 0; i < claims.ClaimsSet.ClaimsArray.Count(); i++)
172-
// {
173-
// var left = claims.ClaimsSet.ClaimsArray.ElementAt(i);
174-
// var right = claimsDecoded.ClaimsSet.ClaimsArray.ElementAt(i);
234+
for (var i = 0; i < claims.ClaimsSet.ClaimsArray.Count(); i++)
235+
{
236+
var left = claims.ClaimsSet.ClaimsArray.ElementAt(i);
237+
var right = claimsDecoded.ClaimsSet.ClaimsArray.ElementAt(i);
175238

176-
// Assert.AreEqual(left.ClaimSource, right.ClaimSource);
239+
Assert.AreEqual(left.ClaimSource, right.ClaimSource);
177240

178-
// Assert.AreEqual(left.ClaimEntries.Count(), right.ClaimEntries.Count());
241+
Assert.AreEqual(left.ClaimEntries.Count(), right.ClaimEntries.Count());
179242

180-
// for (var c = 0; c < left.ClaimEntries.Count(); c++)
181-
// {
182-
// var claimLeft = left.ClaimEntries.ElementAt(c);
183-
// var claimRight = right.ClaimEntries.ElementAt(c);
243+
for (var c = 0; c < left.ClaimEntries.Count(); c++)
244+
{
245+
var claimLeft = left.ClaimEntries.ElementAt(c);
246+
var claimRight = right.ClaimEntries.ElementAt(c);
184247

185-
// Assert.AreEqual(claimLeft.Type, claimRight.Type);
186-
// Assert.AreEqual(claimLeft.Id, claimRight.Id);
187-
// Assert.AreEqual(claimLeft.Values.Count(), claimRight.Values.Count());
248+
Assert.AreEqual(claimLeft.Type, claimRight.Type);
249+
Assert.AreEqual(claimLeft.Id, claimRight.Id);
250+
Assert.AreEqual(claimLeft.Values.Count(), claimRight.Values.Count());
188251

189-
// Assert.IsTrue(claimLeft.Values.SequenceEqual(claimRight.Values));
190-
// }
191-
// }
192-
// }
252+
Assert.IsTrue(claimLeft.Values.SequenceEqual(claimRight.Values));
253+
}
254+
}
255+
}
193256

194257
[TestMethod]
195258
public async Task NdrLogonInfoRoundtrip()
@@ -253,4 +316,4 @@ private static void AssertSidsAreEqual(SecurityIdentifier leftSid, SecurityIdent
253316
Assert.AreEqual(leftSid.Attributes, rightSid.Attributes);
254317
}
255318
}
256-
}
319+
}

0 commit comments

Comments
 (0)