private void SendTgsRequest(string sName, KdcOptions kdcOptions, Asn1SequenceOf <PA_DATA> seqPadata = null, AuthorizationData dataInAuthentiator = null, AuthorizationData dataInEncAuthData = null, MsgType msgType = MsgType.KRB_TGS_REQ) { if (string.IsNullOrEmpty(sName)) { throw new ArgumentNullException("sName"); } PrincipalName sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST), KerberosUtility.String2SeqKerbString(sName.Split('/'))); KDC_REQ_BODY kdcReqBody = this.CreateKdcRequestBody(kdcOptions, sname, dataInEncAuthData); // almost same as AS request Asn1BerEncodingBuffer bodyBuffer = new Asn1BerEncodingBuffer(); kdcReqBody.BerEncode(bodyBuffer); ChecksumType checksumType = KerberosUtility.GetChecksumType(this.Context.SelectedEType); PA_DATA paTgsReq = CreatePaTgsReqest(checksumType, bodyBuffer.Data, dataInAuthentiator); // use AS session key encrypt authenticator. Asn1SequenceOf <PA_DATA> tempPaData = null; if (seqPadata == null || seqPadata.Elements == null || seqPadata.Elements.Length == 0) { tempPaData = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paTgsReq }); } else { PA_DATA[] paDatas = new PA_DATA[seqPadata.Elements.Length + 1]; Array.Copy(seqPadata.Elements, paDatas, seqPadata.Elements.Length); paDatas[seqPadata.Elements.Length] = paTgsReq; tempPaData = new Asn1SequenceOf <PA_DATA>(paDatas); } KerberosTgsRequest tgsRequest = new KerberosTgsRequest(KerberosConstValue.KERBEROSV5, kdcReqBody, tempPaData, Context.TransportType); tgsRequest.Request.msg_type.Value = (long)msgType; this.client.SendPdu(tgsRequest); }
private KDC_REQ_BODY CreateKdcRequestBody(KdcOptions kdcOptions, PrincipalName sName, AuthorizationData authData = null) { KDC_REQ_BODY kdcReqBody = this.CreateKdcRequestBody(kdcOptions, sName); if (authData == null) { return(kdcReqBody); } Asn1BerEncodingBuffer asnEncBuffer = new Asn1BerEncodingBuffer(); authData.BerEncode(asnEncBuffer, true); EncryptedData encryptData = new EncryptedData(); encryptData.etype = new KerbInt32(0); byte[] encryptAsnEncoded = asnEncBuffer.Data; if (this.Context.SessionKey != null && this.Context.SessionKey.keytype != null && this.Context.SessionKey.keyvalue != null && this.Context.SessionKey.keyvalue.Value != null) { encryptAsnEncoded = KerberosUtility.Encrypt( (EncryptionType)this.Context.SessionKey.keytype.Value, this.Context.SessionKey.keyvalue.ByteArrayValue, encryptAsnEncoded, (int)KeyUsageNumber.TGS_REQ_KDC_REQ_BODY_AuthorizationData ); encryptData.etype = new KerbInt32(this.Context.SessionKey.keytype.Value); } encryptData.cipher = new Asn1OctetString(encryptAsnEncoded); kdcReqBody.enc_authorization_data = encryptData; return(kdcReqBody); }
protected void TypicalASExchange(KerberosTestClient client, KdcOptions options) { //Create and send AS request PaPacRequest paPacRequest = new PaPacRequest(true); PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims); Asn1SequenceOf <PA_DATA> paData = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paPacRequest.Data, paPacOptions.Data }); client.SendAsRequest(options, paData); //Recieve preauthentication required error METHOD_DATA methodData; KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData); //Create pa-enc-timestamp string timeStamp = KerberosUtility.CurrentKerberosTime.Value; PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, this.client.Context.SelectedEType, this.client.Context.CName.Password, this.client.Context.CName.Salt); paData = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.Data }); //Create and send AS request client.SendAsRequest(options, paData); KerberosAsResponse asResponse = client.ExpectAsResponse(); }
public void KPSInvalidTargetDomain() { base.Logging(); if (!this.testConfig.UseProxy) { BaseTestSite.Assert.Inconclusive("This case is only applicable when Kerberos Proxy Service is in use."); } //Create kerberos test client and connect client = new KerberosTestClient(this.testConfig.LocalRealm.RealmName, this.testConfig.LocalRealm.User[1].Username, this.testConfig.LocalRealm.User[1].Password, KerberosAccountType.User, testConfig.LocalRealm.KDC[0].IPAddress, testConfig.LocalRealm.KDC[0].Port, testConfig.TransportType, testConfig.SupportedOid); KKDCPClient proxyClient = new KKDCPClient(proxyClientConfig); //Set the TargetDomain to an invalid value; proxyClient.TargetDomain = "InvalidDomain"; client.UseProxy = true; client.ProxyClient = proxyClient; KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends Proxy Message with invalid Target Domain."); client.SendAsRequest(options, null); BaseTestSite.Assert.AreEqual(KKDCPError.STATUS_NO_LOGON_SERVERS, client.ProxyClient.Error, "Server should drop the connection."); }
private CLAIMS_SET?GetADUserClaims_SingleRealm(string realm, string user, string userPwd, string server, string servicePwd, string serviceSpn) { base.Logging(); client = new KerberosTestClient(this.testConfig.LocalRealm.RealmName, this.testConfig.LocalRealm.User[2].Username, this.testConfig.LocalRealm.User[2].Password, KerberosAccountType.User, testConfig.LocalRealm.KDC[0].IPAddress, testConfig.LocalRealm.KDC[0].Port, testConfig.TransportType, testConfig.SupportedOid); KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE; client.SendAsRequest(options, null); METHOD_DATA methodData; KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData); BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with PaEncTimeStamp, PaPacRequest and paPacOptions."); string timeStamp = KerberosUtility.CurrentKerberosTime.Value; PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, client.Context.SelectedEType, client.Context.CName.Password, this.client.Context.CName.Salt); PaPacRequest paPacRequest = new PaPacRequest(true); PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc); Asn1SequenceOf <PA_DATA> seqOfPaData = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.Data }); client.SendAsRequest(options, seqOfPaData); KerberosAsResponse asResponse = client.ExpectAsResponse(); BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send FAST armored TGS request: {0}.", this.testConfig.LocalRealm.FileServer[0].Smb2ServiceName); Asn1SequenceOf <PA_DATA> seqOfPaData2 = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paPacRequest.Data, paPacOptions.Data }); client.SendTgsRequest(this.testConfig.LocalRealm.FileServer[0].Smb2ServiceName, options, seqOfPaData2); KerberosTgsResponse tgsResponse = client.ExpectTgsResponse(); EncryptionKey key = testConfig.QueryKey(this.testConfig.LocalRealm.FileServer[0].Smb2ServiceName, client.Context.Realm.ToString(), client.Context.SelectedEType); tgsResponse.DecryptTicket(key); BaseTestSite.Assert.IsNotNull(tgsResponse.EncPart, "The encrypted part of TGS-REP is decrypted."); if (this.testConfig.IsKileImplemented) { BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data."); AdWin2KPac adWin2kPac = FindOneInAuthData <AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements); BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac."); foreach (PacInfoBuffer buf in adWin2kPac.Pac.PacInfoBuffers) { if (buf.GetType() == typeof(ClientClaimsInfo)) { return(((ClientClaimsInfo)buf).NativeClaimSet); } } } return(null); }
public static KrbTgsReq CreateTgsReq( string spn, KrbEncryptionKey tgtSessionKey, KrbKdcRep kdcRep, KdcOptions options, KrbTicket user2UserTicket = null ) { var tgtApReq = CreateApReq(kdcRep, tgtSessionKey); var pacOptions = new KrbPaPacOptions { Flags = PacOptions.ResourceBasedConstrainedDelegation | PacOptions.Claims | PacOptions.BranchAware }.Encode(); var paData = new List <KrbPaData>() { new KrbPaData { Type = PaDataType.PA_TGS_REQ, Value = tgtApReq.EncodeApplication() }, new KrbPaData { Type = PaDataType.PA_PAC_OPTIONS, Value = pacOptions.AsMemory() } }; var tgt = kdcRep.Ticket; var sname = spn.Split('/', '@'); var tgs = new KrbTgsReq { PaData = paData.ToArray(), Body = new KrbKdcReqBody { EType = KerberosConstants.ETypes.ToArray(), KdcOptions = options, Nonce = KerberosConstants.GetNonce(), Realm = tgt.Realm, SName = new KrbPrincipalName() { Type = PrincipalNameType.NT_SRV_HST, Name = sname }, Till = KerberosConstants.EndOfTime }, }; if (options.HasFlag(KdcOptions.EncTktInSkey) && user2UserTicket != null) { tgs.Body.AdditionalTickets = new[] { user2UserTicket }; } return(tgs); }
private KerberosAsRequest SendAsRequest(KdcOptions kdcOptions, Asn1SequenceOf <PA_DATA> seqPaData) { string sName = KerberosConstValue.KERBEROS_SNAME; string domain = this.Context.Realm.Value; PrincipalName sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST), KerberosUtility.String2SeqKerbString(sName, domain)); KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sname); KerberosAsRequest asRequest = this.CreateAsRequest(kdcReqBody, seqPaData); this.client.SendPdu(asRequest); return(asRequest); }
/// <summary> /// Generate a GCC AP token for the given account and SPN. /// </summary> /// <param name="kdcIpAddr">KDC IP address</param> /// <param name="account">Account Name.</param> /// <param name="pwd">Password of the account.</param> /// <param name="domain">Domain name.</param> /// <param name="spn">SPN</param> /// <param name="aType">Account type</param> /// <returns>Token</returns> public static byte[] GenerateGssApToken(string kdcIpAddr, string account, string pwd, string domain, string spn, KerberosAccountType aType) { KerberosTestClient client = new KerberosTestClient( domain, account, pwd, KerberosAccountType.User, kdcIpAddr, 88, Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.TransportType.TCP, (KerberosConstValue.OidPkt)Enum.Parse(typeof(KerberosConstValue.OidPkt), "MSKerberosToken")); //Create and send AS request KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE | KdcOptions.OK_AS_DELEGATE; client.SendAsRequest(options, null); //Recieve preauthentication required error Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.METHOD_DATA methodData; KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData); //Create sequence of PA data string timeStamp = KerberosUtility.CurrentKerberosTime.Value; Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.PaEncTimeStamp paEncTimeStamp = new Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.PaEncTimeStamp(timeStamp, 0, client.Context.SelectedEType, client.Context.CName.Password, client.Context.CName.Salt); Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.PaPacRequest paPacRequest = new Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.PaPacRequest(true); Microsoft.Protocols.TestTools.StackSdk.Asn1.Asn1SequenceOf <PA_DATA> seqOfPaData = new Microsoft.Protocols.TestTools.StackSdk.Asn1.Asn1SequenceOf <PA_DATA>(new Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data }); //Create and send AS request client.SendAsRequest(options, seqOfPaData); KerberosAsResponse asResponse = client.ExpectAsResponse(); //Create and send TGS request client.SendTgsRequest(spn, options); KerberosTgsResponse refTgsResponse = client.ExpectTgsResponse(); // client.ChangeRealm(childDomain, childDcIp, 88, Microsoft.Protocols.TestTools.StackSdk.Security.Kerberos.TransportType.TCP); // client.SendTgsRequest(spn, options); // KerberosTgsResponse tgsResponse = client.ExpectTgsResponse(); Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.AuthorizationData data = null; Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.EncryptionKey subkey = Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.KerberosUtility.GenerateKey(client.Context.SessionKey); byte[] token = client.CreateGssApiToken(Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.ApOptions.None, data, subkey, Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.ChecksumFlags.None, KerberosConstValue.GSSToken.GSSAPI ); return(token); }
private EncTicketPart RetrieveAndDecryptServiceTicket(KerberosFunctionalClient kerberosClient, out EncryptionKey serviceKey) { //Create and send AS request const KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE; kerberosClient.SendAsRequest(options, null); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client expects Kerberos Error from KDC"); //Receive preauthentication required error METHOD_DATA methodData; KerberosKrbError krbError = kerberosClient.ExpectPreauthRequiredError(out methodData); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client sends AS request with PA-DATA set"); //Create sequence of PA data string timeStamp = KerberosUtility.CurrentKerberosTime.Value; PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, kerberosClient.Context.SelectedEType, kerberosClient.Context.CName.Password, kerberosClient.Context.CName.Salt); PaPacRequest paPacRequest = new PaPacRequest(true); Asn1SequenceOf <PA_DATA> seqOfPaData = new Asn1SequenceOf <PA_DATA>(new[] { paEncTimeStamp.Data, paPacRequest.Data }); //Create and send AS request kerberosClient.SendAsRequest(options, seqOfPaData); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client expects AS response from KDC"); KerberosAsResponse asResponse = kerberosClient.ExpectAsResponse(); BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT."); //Create and send TGS request BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client sends TGS request to KDC"); kerberosClient.SendTgsRequest(servicePrincipalName, options); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client expects TGS response from KDC"); KerberosTgsResponse tgsResponse = kerberosClient.ExpectTgsResponse(); BaseTestSite.Assert.AreEqual(servicePrincipalName, KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname), "Service principal name in service ticket should match expected."); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Decrypt SMB2 Service Ticket"); serviceKey = keyManager.QueryKey(servicePrincipalName, TestConfig.DomainName, kerberosClient.Context.SelectedEType); tgsResponse.DecryptTicket(serviceKey); return(tgsResponse.TicketEncPart); }
private static DateTimeOffset?CalculateRenewTime(KdcOptions kdcOptions, Krb5Config config) { if (!kdcOptions.HasFlag(KdcOptions.Renewable)) { return(null); } if (config.Defaults.RenewLifetime > TimeSpan.Zero) { return(DateTimeOffset.UtcNow.Add(config.Defaults.RenewLifetime)); } else { return(EndOfTime); } }
private KDC_REQ_BODY CreateKdcRequestBody(KdcOptions kdcOptions, PrincipalName sName) { KerbUInt32 nonce = new KerbUInt32((uint)Math.Abs((int)DateTime.Now.Ticks)); KerberosTime till = new KerberosTime(KerberosConstValue.TGT_TILL_TIME); KerberosTime rtime = new KerberosTime(KerberosConstValue.TGT_RTIME); HostAddresses addresses = new HostAddresses(new HostAddress[1] { new HostAddress(new KerbInt32((int)AddressType.NetBios), new Asn1OctetString(Encoding.ASCII.GetBytes(System.Net.Dns.GetHostName()))) }); KDCOptions options = new KDCOptions(KerberosUtility.ConvertInt2Flags((int)kdcOptions)); KDC_REQ_BODY kdcReqBody = new KDC_REQ_BODY(options, Context.CName.Name, Context.Realm, sName, null, till, rtime, nonce, Context.SupportedEType, addresses, null, null); return(kdcReqBody); }
private void DAC_Smb2_AccessFile(string RealmName, User user, Computer kdc, TransportType transportType, FileServer fileserver, string filePath, string fileName, bool expectAccessDeny) { base.Logging(); client = new KerberosTestClient(RealmName, user.Username, user.Password, KerberosAccountType.User, kdc.IPAddress, kdc.Port, transportType, testConfig.SupportedOid); //Create and send AS request KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE; client.SendAsRequest(options, null); //Recieve preauthentication required error METHOD_DATA methodData; KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData); //Create sequence of PA data string timeStamp = KerberosUtility.CurrentKerberosTime.Value; PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, client.Context.SelectedEType, this.client.Context.CName.Password, this.client.Context.CName.Salt); PaPacRequest paPacRequest = new PaPacRequest(true); Asn1SequenceOf <PA_DATA> seqOfPaData = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data }); //Create and send AS request client.SendAsRequest(options, seqOfPaData); KerberosAsResponse asResponse = client.ExpectAsResponse(); BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT."); //Create and send TGS request client.SendTgsRequest(fileserver.Smb2ServiceName, options); KerberosTgsResponse tgsResponse = client.ExpectTgsResponse(); BaseTestSite.Assert.AreEqual(fileserver.Smb2ServiceName, KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname), "Service principal name in service ticket should match expected."); EncryptionKey key = testConfig.QueryKey(fileserver.Smb2ServiceName, client.Context.Realm.ToString(), client.Context.SelectedEType); tgsResponse.DecryptTicket(key); BaseTestSite.Assert.AreEqual(RealmName.ToLower(), tgsResponse.TicketEncPart.crealm.Value.ToLower(), "Realm name in service ticket encrypted part should match expected."); BaseTestSite.Assert.AreEqual(user.Username.ToLower(), KerberosUtility.PrincipalName2String(tgsResponse.TicketEncPart.cname).ToLower(), "User name in service ticket encrypted part should match expected."); //Assert authorization data if (this.testConfig.IsKileImplemented) { BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data."); AdWin2KPac adWin2kPac = FindOneInAuthData <AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements); BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac."); } AuthorizationData data = null; EncryptionKey subkey = KerberosUtility.GenerateKey(client.Context.SessionKey); byte[] token = client.CreateGssApiToken(ApOptions.MutualRequired, data, subkey, ChecksumFlags.GSS_C_MUTUAL_FLAG | ChecksumFlags.GSS_C_INTEG_FLAG); BaseTestSite.Log.Add(LogEntryKind.Comment, "Logon to fileserver and Access File."); AccessFile(filePath, fileName, fileserver, token, tgsResponse.EncPart.key, expectAccessDeny); }
private void claimsTest_Kerberos_CrossRealm_ADSource_User_Only(bool ctaFromConfig) { client = new KerberosTestClient(this.testConfig.LocalRealm.RealmName, this.testConfig.LocalRealm.User[2].Username, this.testConfig.LocalRealm.User[2].Password, KerberosAccountType.User, testConfig.LocalRealm.KDC[0].IPAddress, testConfig.LocalRealm.KDC[0].Port, testConfig.TransportType, testConfig.SupportedOid); //Create and send AS request KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE; client.SendAsRequest(options, null); //Recieve preauthentication required error METHOD_DATA methodData; KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData); //Create sequence of PA data string timeStamp = KerberosUtility.CurrentKerberosTime.Value; PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, this.client.Context.SelectedEType, this.client.Context.CName.Password, this.client.Context.CName.Salt); PaPacRequest paPacRequest = new PaPacRequest(true); PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc); Asn1SequenceOf <PA_DATA> seqOfPaData = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.Data }); //Create and send AS request client.SendAsRequest(options, seqOfPaData); KerberosAsResponse asResponse = client.ExpectAsResponse(); Asn1SequenceOf <PA_DATA> seqOfPaData2 = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data }); //Create and send TGS request client.SendTgsRequest(this.testConfig.TrustedRealm.KDC[0].DefaultServiceName, options, seqOfPaData2); BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send TGS request"); KerberosTgsResponse tgsResponse = client.ExpectTgsResponse(); BaseTestSite.Log.Add(LogEntryKind.Comment, "Receive a referral TGS response."); BaseTestSite.Assert.AreEqual(this.testConfig.TrustedRealm.KDC[0].DefaultServiceName, KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname), "The service principal name in referral ticket should match expected."); BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(), tgsResponse.Response.ticket.realm.Value.ToLower(), "The realm name in referral ticket should match expected."); EncryptionKey key = testConfig.QueryKey(this.testConfig.TrustedRealm.KDC[0].DefaultServiceName + "@" + this.testConfig.LocalRealm.RealmName, client.Context.Realm.ToString(), client.Context.SelectedEType); tgsResponse.DecryptTicket(key); CLAIMS_SET claims = new CLAIMS_SET(); AdWin2KPac adWin2kPac = FindOneInAuthData <AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements); bool foundClaims = false; foreach (PacInfoBuffer buf in adWin2kPac.Pac.PacInfoBuffers) { if (buf.GetType() == typeof(ClientClaimsInfo)) { claims = ((ClientClaimsInfo)buf).NativeClaimSet; foundClaims = true; } } BaseTestSite.Assert.IsTrue(foundClaims, "Found claims in referral TGS Ticket"); foundClaims = false; #region genertaed transformed claims Dictionary <string, string> expectedClaims = new Dictionary <string, string>(); if (!ctaFromConfig) { ClaimTransformer transformer = new ClaimTransformer(this.testConfig.TrustedRealm.KDC[0].IPAddress, this.testConfig.TrustedRealm.RealmName, this.testConfig.TrustedRealm.Admin.Username, this.testConfig.TrustedRealm.Admin.Password); List <CLAIMS_ARRAY> transformed = null; BaseTestSite.Assert.AreEqual <Win32ErrorCode_32>(Win32ErrorCode_32.ERROR_SUCCESS, transformer.TransformClaimsOnTrustTraversal(claims.ClaimsArrays, this.testConfig.LocalRealm.RealmName, true, out transformed), "should successfully transform claims"); foreach (CLAIMS_ARRAY array in transformed) { foreach (CLAIM_ENTRY entry in array.ClaimEntries) { string id = entry.Id; string value = null; switch (entry.Type) { case CLAIM_TYPE.CLAIM_TYPE_BOOLEAN: value = entry.Values.Struct4.BooleanValues[0].ToString(); break; case CLAIM_TYPE.CLAIM_TYPE_INT64: value = entry.Values.Struct1.Int64Values[0].ToString(); break; case CLAIM_TYPE.CLAIM_TYPE_STRING: value = entry.Values.Struct3.StringValues[0].ToString(); break; case CLAIM_TYPE.CLAIM_TYPE_UINT64: value = entry.Values.Struct2.Uint64Values[0].ToString(); break; default: BaseTestSite.Assert.Fail("Found invalid claim type during transform, value:" + (int)entry.Type); break; } expectedClaims.Add(id.ToLower(), value.ToLower()); } } } else { string[] tmp = this.testConfig.LocalRealm.User[2].TransformedClaims.ToLower().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries); BaseTestSite.Assert.IsTrue(tmp != null && tmp.Length % 2 == 0, "Claim.Crossforest.TransformedClaims in PTFConfig should be valid and not empty"); for (int i = 0; i < tmp.Length; i += 2) { expectedClaims.Add(tmp[i], tmp[i + 1]); } } #endregion //Change realm client.ChangeRealm(this.testConfig.TrustedRealm.RealmName, this.testConfig.TrustedRealm.KDC[0].IPAddress, this.testConfig.TrustedRealm.KDC[0].Port, this.testConfig.TransportType); //Create and send referal TGS request client.SendTgsRequest(this.testConfig.TrustedRealm.FileServer[0].Smb2ServiceName, options); KerberosTgsResponse refTgsResponse = client.ExpectTgsResponse(); BaseTestSite.Assert.AreEqual(this.testConfig.TrustedRealm.FileServer[0].Smb2ServiceName, KerberosUtility.PrincipalName2String(refTgsResponse.Response.ticket.sname), "The service principal name in service ticket should match expected."); BaseTestSite.Assert.AreEqual(this.testConfig.TrustedRealm.RealmName.ToLower(), refTgsResponse.Response.ticket.realm.Value.ToLower(), "The realm name in service ticket should match expected."); key = testConfig.QueryKey(this.testConfig.TrustedRealm.FileServer[0].Smb2ServiceName, client.Context.Realm.ToString(), client.Context.SelectedEType); refTgsResponse.DecryptTicket(key); BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.RealmName.ToLower(), refTgsResponse.TicketEncPart.crealm.Value.ToLower(), "Realm name in service ticket encrypted part should match expected."); BaseTestSite.Assert.AreEqual(this.testConfig.LocalRealm.User[2].Username, KerberosUtility.PrincipalName2String(refTgsResponse.TicketEncPart.cname).ToLower(), "User name in service ticket encrypted part should match expected."); adWin2kPac = FindOneInAuthData <AdWin2KPac>(refTgsResponse.TicketEncPart.authorization_data.Elements); foreach (PacInfoBuffer buf in adWin2kPac.Pac.PacInfoBuffers) { if (buf.GetType() == typeof(ClientClaimsInfo)) { foundClaims = true; claims = ((ClientClaimsInfo)buf).NativeClaimSet; } } int errors = 0; BaseTestSite.Assert.IsTrue(foundClaims, "Found claims in reference TGS Ticket"); for (int i = 0; i < claims.ClaimsArrays[0].ClaimEntries.Length; i++) { string claimvalue = null; if (!expectedClaims.TryGetValue(claims.ClaimsArrays[0].ClaimEntries[i].Id.ToLower(), out claimvalue)) { errors++; BaseTestSite.Log.Add(LogEntryKind.CheckFailed, "Found unexpected claim with id: " + claims.ClaimsArrays[0].ClaimEntries[i].Id + " after transform"); } else { if (claimvalue != claims.ClaimsArrays[0].ClaimEntries[i].Values.Struct3.StringValues[0].ToLower()) { errors++; BaseTestSite.Log.Add( LogEntryKind.CheckFailed, "Value of claim \"" + claims.ClaimsArrays[0].ClaimEntries[i].Id + "\" is not expected, expected: " + claimvalue + " ,actual: " + claims.ClaimsArrays[0].ClaimEntries[i].Values.Struct3.StringValues[0]); } expectedClaims.Remove(claims.ClaimsArrays[0].ClaimEntries[i].Id); } } BaseTestSite.Assert.AreEqual(expectedClaims.Count, claims.ClaimsArrays[0].ClaimEntries.Count(), "Claims count should be equal."); BaseTestSite.Assert.AreEqual <int>(0, errors, "Expect no error should be found when compare claims from reference TGS ticket"); }
private KDC_REQ_BODY CreateKdcRequestBody( KdcOptions kdcOptions, PrincipalName sName, KerberosTime from, KerberosTime till ) { KerbUInt32 nonce = new KerbUInt32((uint)Math.Abs((int)DateTime.Now.Ticks)); KerberosTime rtime = new KerberosTime(KerberosConstValue.TGT_RTIME); HostAddresses addresses = new HostAddresses(new HostAddress[1] { new HostAddress(new KerbInt32((int)AddressType.NetBios), new Asn1OctetString(Encoding.ASCII.GetBytes(System.Net.Dns.GetHostName()))) }); KDCOptions options = new KDCOptions(KerberosUtility.ConvertInt2Flags((int)kdcOptions)); KDC_REQ_BODY kdcReqBody = new KDC_REQ_BODY(options, Context.CName.Name, Context.Realm, sName, from, till, rtime, nonce, Context.SupportedEType, addresses, null, null); return kdcReqBody; }
/// <summary> /// Create and send AS request /// </summary> /// <param name="kdcOptions">KDC options</param> /// <param name="seqPaData">A sequence of preauthentication data</param> public void SendAsRequest(KdcOptions kdcOptions, Asn1SequenceOf<PA_DATA> seqPaData, KerberosTime from, KerberosTime till) { string sName = KerberosConstValue.KERBEROS_SNAME; string domain = this.Context.Realm.Value; PrincipalName sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST), KerberosUtility.String2SeqKerbString(sName, domain)); KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sname, from, till); KerberosAsRequest asRequest = this.CreateAsRequest(kdcReqBody, seqPaData); this.SendPdu(asRequest); this.testSite.Log.Add(LogEntryKind.Debug, "Send AS Request."); }
/// <summary> /// Initialize the context from a token. /// </summary> /// <param name="inToken">The token used to initialize.</param> /// <exception cref="System.NotSupportedException">Thrown when the ContextAttribute contains a flag that not be /// supported.</exception> /// <exception cref="System.InvalidOperationException">Thrown when an error is returned.</exception> public override void Initialize(byte[] inToken) { if (inToken == null || inToken.Length == 0) { KilePdu response = null; string sname = ConstValue.KERBEROS_SNAME; KileAsRequest asRequest; EncryptionKey subkey = null; // Create and send AS request for pre-authentication KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.RENEWABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLEOK; KDCOptions flags = new KDCOptions(KerberosUtility.ConvertInt2Flags((int)options)); // Create and send AS request for pre-authentication asRequest = client.CreateAsRequest(sname, flags, null, this.GetClientSupportedEtype()); client.SendPdu(asRequest); response = client.ExpectPdu(ConstValue.TIMEOUT_DEFAULT); KileKrbError preAuthError = response as KileKrbError; if ((preAuthError == null) || (!preAuthError.ErrorCode.Equals(KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED))) { throw new InvalidOperationException("The Error code should be KDC_ERR_PREAUTH_REQUIRED"); } // Create and send AS request for TGT var defualtEncryptType = (client.ClientContext.TgsSessionKey == null) ? EncryptionType.RC4_HMAC : (EncryptionType)client.ClientContext.TgsSessionKey.keytype.Value; PaEncTimeStamp timestamp = client.ConstructPaEncTimeStamp(defualtEncryptType); PaPacRequest pacRequest = client.ConstructPaPacRequest(true); Asn1SequenceOf <PA_DATA> paData = client.ConstructPaData(timestamp, pacRequest); if ((contextAttribute & ClientSecurityContextAttribute.DceStyle) == ClientSecurityContextAttribute.DceStyle) { asRequest = client.CreateAsRequest(sname, flags, paData, this.GetClientSupportedEtype()); //subkey = new EncryptionKey((int)EncryptionType.AES256_CTS_HMAC_SHA1_96, // KileUtility.GenerateRandomBytes(ConstValue.AES_KEY_LENGTH)); var key = KeyGenerator.MakeKey(EncryptionType.AES256_CTS_HMAC_SHA1_96, client.ClientContext.Password, client.ClientContext.Salt); subkey = new EncryptionKey(new KerbInt32((long)EncryptionType.AES256_CTS_HMAC_SHA1_96), new Asn1OctetString(key)); } else { asRequest = client.CreateAsRequest(sname, flags, paData, this.GetClientSupportedEtype()); } client.SendPdu(asRequest); response = client.ExpectPdu(ConstValue.TIMEOUT_DEFAULT); if (response.GetType() == typeof(KileKrbError)) { throw new InvalidOperationException("Received Kerberos Error response: " + ((KileKrbError)response).ErrorCode); } KileAsResponse asResponse = (KileAsResponse)response; // Create and send TGS request // for example: "KERB.COMldapsut02.kerb.com" client.ClientContext.Salt = domain.ToUpper(); string[] nameList = userLogonName.Split('/'); foreach (string name in nameList) { client.ClientContext.Salt += name; } KileTgsRequest tgsRequest = client.CreateTgsRequest(this.serverName, flags, null, ChecksumType.hmac_md5_string, null, null); client.SendPdu(tgsRequest); response = client.ExpectPdu(ConstValue.TIMEOUT_DEFAULT); if (response.GetType() == typeof(KileKrbError)) { throw new InvalidOperationException("Received Kerberos Error response: " + ((KileKrbError)response).ErrorCode); } KileTgsResponse tgsResponse = (KileTgsResponse)response; ApOptions apOption; ChecksumFlags checksumFlag; GetFlagsByContextAttribute(out apOption, out checksumFlag); KerbAuthDataTokenRestrictions adRestriction = client.ConstructKerbAuthDataTokenRestrictions(0, (uint)LSAP_TOKEN_INFO_INTEGRITY_Flags.FULL_TOKEN, (uint)LSAP_TOKEN_INFO_INTEGRITY_TokenIL.Medium, new Guid().ToString()); AdAuthDataApOptions adApOptions = client.ConstructAdAuthDataApOptions(ConstValue.KERB_AP_OPTIONS_CBT); AuthorizationData authData = client.ConstructAuthorizationData(adRestriction, adApOptions); KileApRequest apRequest = client.CreateApRequest(apOption, ChecksumType.ap_authenticator_8003, ConstValue.SEQUENCE_NUMBER_DEFAULT, checksumFlag, subkey, authData); token = apRequest.ToBytes(); bool isMutualAuth = (contextAttribute & ClientSecurityContextAttribute.MutualAuth) == ClientSecurityContextAttribute.MutualAuth; bool isDceStyle = (contextAttribute & ClientSecurityContextAttribute.DceStyle) == ClientSecurityContextAttribute.DceStyle; if (isMutualAuth || isDceStyle) { continueProcess = true; // SEC_I_CONTINUE_NEEDED; } else { continueProcess = false; // SEC_E_OK; } } else // mutual authentication { KileApResponse apResponse = client.ParseApResponse(inToken); token = null; if ((contextAttribute & ClientSecurityContextAttribute.DceStyle) == ClientSecurityContextAttribute.DceStyle) { KileApResponse apResponseSend = client.CreateApResponse(null); token = apResponseSend.ToBytes(); } this.continueProcess = false; // SEC_E_OK; } }
//S4U2Proxy //[MS-SFU] 3.2.5.2.1.2 Using ServicesAllowedToSendForwardedTicketsTo //The KDC checks if the security principal name(SPN) for Service 2, //identified in the sname and srealm fields of the KRB_TGS_REQ message, //is in the Service 1 account's ServicesAllowedToSendForwardedTicketsTo parameter. //If it is, then the KDC replies with a service ticket for Service 2. //Otherwise the KDC MUST return `KRB-ERR-BADOPTION`. public static async System.Threading.Tasks.Task S4U2Proxy(string kdc, ILoggerFactory logger, TcpKerberosTransport transport, KrbAsRep asRep, KrbTgsRep s4u2self, string username, string password, string domainName, string impersonateuser, string spn, bool outKirbi = false, bool verbose = false, bool ptt = false, string hash = null, EncryptionType etype = EncryptionType.RC4_HMAC_NT) { var now = DateTime.UtcNow; credKey = password != null ? new KerberosPasswordCredential(username, password, domainName).CreateKey() : new Utils.KerberosHashCreds(username, hash, etype, domainName).CreateKey(); KrbEncAsRepPart asDecrypted = password != null ? new KerberosPasswordCredential(username, password, domainName).DecryptKdcRep( asRep, KeyUsage.EncAsRepPart, d => KrbEncAsRepPart.DecodeApplication(d)) : new Utils.KerberosHashCreds(username, hash, etype, domainName).DecryptKdcRep( asRep, KeyUsage.EncAsRepPart, d => KrbEncAsRepPart.DecodeApplication(d)); var sessionKey = asDecrypted.Key; //Request Service Ticket parameters ApOptions apOptions = ApOptions.Reserved; KdcOptions kdcOptions = KdcOptions.Forwardable | KdcOptions.Renewable | KdcOptions.RenewableOk; string s4u = null; KrbTicket s4uTicket = s4u2self.Ticket; KrbTicket u2uServerTicket = null; var rst = new RequestServiceTicket() { ServicePrincipalName = spn, ApOptions = apOptions, S4uTarget = s4u, S4uTicket = s4uTicket, UserToUserTicket = u2uServerTicket, KdcOptions = kdcOptions, Realm = domainName }; var sname = rst.ServicePrincipalName.Split('/', '@'); var tgt = asRep.Ticket; var additionalTickets = new List <KrbTicket>(); if (rst.KdcOptions.HasFlag(KdcOptions.EncTktInSkey) && rst.UserToUserTicket != null) { additionalTickets.Add(rst.UserToUserTicket); } if (!string.IsNullOrWhiteSpace(rst.S4uTarget)) { rst.KdcOptions |= KdcOptions.Forwardable; } if (rst.S4uTicket != null) { rst.KdcOptions = rst.KdcOptions | KdcOptions.ConstrainedDelegation | KdcOptions.CNameInAdditionalTicket; additionalTickets.Add(rst.S4uTicket); } //EncryptionType[] kdcReqEtype = { EncryptionType.RC4_HMAC_NT }; string[] name = { }; var body = new KrbKdcReqBody { EType = KrbConstants.KerberosConstants.ETypes.ToArray(), KdcOptions = rst.KdcOptions, Nonce = KrbConstants.KerberosConstants.GetNonce(), Realm = rst.Realm, SName = new KrbPrincipalName() { Type = PrincipalNameType.NT_SRV_INST, Name = sname }, Till = KrbConstants.KerberosConstants.EndOfTime, CName = new KrbPrincipalName() { Type = PrincipalNameType.NT_SRV_INST, Name = name }, }; if (additionalTickets.Count > 0) { body.AdditionalTickets = additionalTickets.ToArray(); } var bodyChecksum = KrbChecksum.Create( body.Encode(), sessionKey.AsKey(), KeyUsage.PaTgsReqChecksum ); //ApReq //Authenticator var authenticator = new KrbAuthenticator { CName = asRep.CName, Realm = asRep.Ticket.Realm, SequenceNumber = KrbConstants.KerberosConstants.GetNonce(), Checksum = bodyChecksum, CTime = now, CuSec = now.Millisecond //new Random().Next(0, 999999) }; var subSessionKey = KrbEncryptionKey.Generate(sessionKey.EType); subSessionKey.Usage = KeyUsage.EncTgsRepPartSubSessionKey; authenticator.Subkey = subSessionKey; var encryptedAuthenticator = KrbEncryptedData.Encrypt( authenticator.EncodeApplication(), sessionKey.AsKey(), KeyUsage.PaTgsReqAuthenticator ); var apReq = new KrbApReq { Ticket = tgt, ApOptions = apOptions, Authenticator = encryptedAuthenticator }; var pacOptions = new KrbPaPacOptions { Flags = PacOptions.ResourceBasedConstrainedDelegation }.Encode(); var paData = new List <KrbPaData>() { new KrbPaData { Type = PaDataType.PA_TGS_REQ, Value = apReq.EncodeApplication() }, new KrbPaData { Type = PaDataType.PA_PAC_OPTIONS, Value = pacOptions } }; if (!string.IsNullOrWhiteSpace(rst.S4uTarget)) { var paS4u = new KrbPaForUser { AuthPackage = "Kerberos", UserName = new KrbPrincipalName { Type = PrincipalNameType.NT_ENTERPRISE, Name = new[] { s4u } }, UserRealm = tgt.Realm }; paS4u.GenerateChecksum(subSessionKey.AsKey()); paData.Add(new KrbPaData { Type = PaDataType.PA_FOR_USER, Value = paS4u.Encode() }); } var tgs = new KrbTgsReq { PaData = paData.ToArray(), Body = body }; ReadOnlyMemory <byte> encodedTgs = tgs.EncodeApplication(); Console.WriteLine("[*] Sending TGS-REQ [S4U2Proxy] ..."); if (verbose) { PrintFunc.PrintReq(tgs, credKey, sessionKey.AsKey()); } CancellationToken cancellation = default; cancellation.ThrowIfCancellationRequested(); KrbTgsRep tgsRep = null; try { tgsRep = await transport.SendMessage <KrbTgsRep>( rst.Realm, encodedTgs, cancellation ); } catch (KerberosProtocolException pex) { Console.WriteLine("[x] Kerberos Error: {0}", pex.Message); Environment.Exit(0); } Console.WriteLine("[*] Receiving TGS-REP [S4U2Proxy] ..."); try { KrbEncTgsRepPart tgsDecryptedRepPart = tgsRep.EncPart.Decrypt <KrbEncTgsRepPart>( subSessionKey.AsKey(), KeyUsage.EncTgsRepPartSubSessionKey, (ReadOnlyMemory <byte> t) => KrbEncTgsRepPart.DecodeApplication(t)); if (verbose) { PrintFunc.PrintRep(tgsRep, credKey); Console.WriteLine(" * [Decrypted Enc-Part]:"); PrintFunc.PrintRepEnc(tgsDecryptedRepPart, credKey); } if (outKirbi) { var kirbiTGS = Kirbi.toKirbi(tgsRep, tgsDecryptedRepPart, ptt); Console.WriteLine("[+] TGS Kirbi:"); Console.WriteLine(" - {0}", Convert.ToBase64String(kirbiTGS)); } }catch (Exception e) { Console.WriteLine("[x] {0}", e.Message); } }
/// <summary> /// Create and send FAST TGS request /// </summary> /// <param name="sName">Service principal name</param> /// <param name="kdcOptions">KDC options</param> /// <param name="innerSeqPaData">A sequence of preauthentication data in FAST request</param> /// <param name="outerSeqPaData">A sequence of preauthentication data</param> /// <param name="subKey">Sub-session key for authenticator in FAST armor field</param> /// <param name="fastOptions">FAST options</param> /// <param name="apOptions">AP options in FAST armor field</param> /// <param name="data">Authorization data</param> public void SendTgsRequestWithFastHideCName( string sName, PrincipalName cName, KdcOptions kdcOptions, Asn1SequenceOf<PA_DATA> innerSeqPaData, Asn1SequenceOf<PA_DATA> outerSeqPaData, EncryptionKey subKey, ApOptions apOptions, AuthorizationData data = null) { var fastOptions = new Protocols.TestTools.StackSdk.Security.KerberosV5.Preauth.FastOptions( KerberosUtility.ConvertInt2Flags((int)FastOptionFlags.Hide_Client_Names)); Context.Subkey = subKey; Context.ReplyKey = subKey; string domain = this.Context.Realm.Value; PrincipalName sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST), KerberosUtility.String2SeqKerbString(sName.Split('/'))); KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sname, data); kdcReqBody.cname = cName; Asn1BerEncodingBuffer bodyBuffer = new Asn1BerEncodingBuffer(); kdcReqBody.BerEncode(bodyBuffer); APOptions option = new APOptions(KerberosUtility.ConvertInt2Flags((int)ApOptions.None)); ChecksumType checksumType = KerberosUtility.GetChecksumType(Context.SelectedEType); KerberosApRequest apRequest = CreateApRequest( option, Context.Ticket, subKey, data, KeyUsageNumber.TG_REQ_PA_TGS_REQ_padataOR_AP_REQ_Authenticator, checksumType, bodyBuffer.Data); PaTgsReq paTgsReq = new PaTgsReq(apRequest.Request); Asn1SequenceOf<PA_DATA> tempPaData = null; if (outerSeqPaData == null || outerSeqPaData.Elements == null || outerSeqPaData.Elements.Length == 0) { tempPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paTgsReq.Data }); } else { tempPaData.Elements = new PA_DATA[outerSeqPaData.Elements.Length + 1]; Array.Copy(outerSeqPaData.Elements, tempPaData.Elements, outerSeqPaData.Elements.Length); tempPaData.Elements[outerSeqPaData.Elements.Length] = paTgsReq.Data; } var armorKey = GetArmorKey(Context.SessionKey, subKey); var pafxfast = CreateTgsPaFxFast(armorKey, Context.Ticket, fastOptions, apOptions, tempPaData, sName, paTgsReq.Data.padata_value.ByteArrayValue); Context.FastArmorkey = armorKey; PA_DATA[] elements; if (outerSeqPaData != null && outerSeqPaData.Elements.Length > 0) { elements = new PA_DATA[outerSeqPaData.Elements.Length + 1]; Array.Copy(outerSeqPaData.Elements, elements, outerSeqPaData.Elements.Length); elements[outerSeqPaData.Elements.Length] = pafxfast.Data; elements[outerSeqPaData.Elements.Length + 1] = paTgsReq.Data; } else { elements = new PA_DATA[] { pafxfast.Data, paTgsReq.Data }; } Asn1SequenceOf<PA_DATA> seqPaData = new Asn1SequenceOf<PA_DATA>(); KerberosTgsRequest tgsRequest = new KerberosTgsRequest(KerberosConstValue.KERBEROSV5, kdcReqBody, new Asn1SequenceOf<PA_DATA>(elements), Context.TransportType); this.SendPdu(tgsRequest); this.testSite.Log.Add(LogEntryKind.Debug, "Send FAST TGS request."); }
/// <summary> /// Create and send FAST TGS request /// </summary> /// <param name="sName">Service principal name</param> /// <param name="kdcOptions">KDC options</param> /// <param name="innerSeqPaData">A sequence of preauthentication data in FAST request</param> /// <param name="outerSeqPaData">A sequence of preauthentication data</param> /// <param name="subKey">Sub-session key for authenticator in FAST armor field</param> /// <param name="fastOptions">FAST options</param> /// <param name="apOptions">AP options in FAST armor field</param> /// <param name="data">Authorization data</param> public void SendTgsRequestWithExplicitFast( string sName, KdcOptions kdcOptions, Asn1SequenceOf<PA_DATA> innerSeqPaData, Asn1SequenceOf<PA_DATA> outerSeqPaData, EncryptionKey subKey, FastOptions fastOptions, ApOptions apOptions, AuthorizationData data = null) { Context.Subkey = subKey; Context.ReplyKey = subKey; string domain = this.Context.Realm.Value; PrincipalName sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST), KerberosUtility.String2SeqKerbString(sName.Split('/'))); KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sname, data); Asn1BerEncodingBuffer bodyBuffer = new Asn1BerEncodingBuffer(); kdcReqBody.BerEncode(bodyBuffer); //Create PA-TGS-REQ APOptions option = new APOptions(KerberosUtility.ConvertInt2Flags((int)ApOptions.None)); ChecksumType checksumType = KerberosUtility.GetChecksumType(Context.SelectedEType); KerberosApRequest apRequest = CreateApRequest( option, Context.Ticket, subKey, data, KeyUsageNumber.TG_REQ_PA_TGS_REQ_padataOR_AP_REQ_Authenticator, checksumType, bodyBuffer.Data); PaTgsReq paTgsReq = new PaTgsReq(apRequest.Request); Asn1SequenceOf<PA_DATA> tempPaData = null; if (outerSeqPaData == null || outerSeqPaData.Elements == null || outerSeqPaData.Elements.Length == 0) { tempPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paTgsReq.Data }); } else { tempPaData.Elements = new PA_DATA[outerSeqPaData.Elements.Length + 1]; Array.Copy(outerSeqPaData.Elements, tempPaData.Elements, outerSeqPaData.Elements.Length); tempPaData.Elements[outerSeqPaData.Elements.Length] = paTgsReq.Data; } //Create explicit FAST armor EncryptionKey explicitSubkey = KerberosUtility.MakeKey( Context.SelectedEType, "Password04!", "This is a salt"); Authenticator plaintextAuthenticator = CreateAuthenticator(Context.ArmorTicket, null, explicitSubkey); KerberosApRequest apReq = new KerberosApRequest(Context.Pvno, new APOptions(KerberosUtility.ConvertInt2Flags((int)apOptions)), Context.ArmorTicket, plaintextAuthenticator, KeyUsageNumber.AP_REQ_Authenticator); FastArmorApRequest explicitArmor = new FastArmorApRequest(apReq.Request); //Create armor key var armorKey = GetArmorKey(Context.ArmorSessionKey, subKey, explicitSubkey); Context.FastArmorkey = armorKey; //Create PA-FX-FAST var pafxfast = CreateTgsPaFxFast(armorKey, Context.ArmorTicket, fastOptions, apOptions, tempPaData, sName, paTgsReq.Data.padata_value.ByteArrayValue, explicitArmor); PA_DATA[] elements; if (outerSeqPaData != null && outerSeqPaData.Elements.Length > 0) { elements = new PA_DATA[outerSeqPaData.Elements.Length + 1]; Array.Copy(outerSeqPaData.Elements, elements, outerSeqPaData.Elements.Length); elements[outerSeqPaData.Elements.Length] = pafxfast.Data; elements[outerSeqPaData.Elements.Length + 1] = paTgsReq.Data; } else { elements = new PA_DATA[] { pafxfast.Data, paTgsReq.Data }; } Asn1SequenceOf<PA_DATA> seqPaData = new Asn1SequenceOf<PA_DATA>(); KerberosTgsRequest tgsRequest = new KerberosTgsRequest(KerberosConstValue.KERBEROSV5, kdcReqBody, new Asn1SequenceOf<PA_DATA>(elements), Context.TransportType); this.SendPdu(tgsRequest); this.testSite.Log.Add(LogEntryKind.Debug, "Send FAST TGS request."); }
/// <summary> /// Create and send TGS request /// </summary> /// <param name="sName">Service principal name</param> /// <param name="kdcOptions">KDC options</param> /// <param name="seqPadata">A sequence of preauthentication data</param> /// <param name="checksumType">Checksum type of PA-TGS-REQ</param> /// <param name="additionalTicket">Additional ticket</param> /// <param name="data">Authorization data</param> public void SendTgsRequest(string sName, KdcOptions kdcOptions, Asn1SequenceOf<PA_DATA> seqPadata = null, Ticket additionalTicket = null, AuthorizationData dataInAuthenticator = null, AuthorizationData dataInEncAuthData = null) { if (sName == null) { throw new ArgumentNullException("sName"); } PrincipalName sname = new PrincipalName( new KerbInt32((int)PrincipalType.NT_SRV_INST), KerberosUtility.String2SeqKerbString(sName.Split('/'))); KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sname, dataInEncAuthData); Asn1BerEncodingBuffer bodyBuffer = new Asn1BerEncodingBuffer(); kdcReqBody.BerEncode(bodyBuffer); ChecksumType checksumType = KerberosUtility.GetChecksumType(Context.SelectedEType); PA_DATA paTgsReq = CreatePaTgsReq(checksumType, bodyBuffer.Data, dataInAuthenticator); Asn1SequenceOf<PA_DATA> tempPaData = null; if (seqPadata == null || seqPadata.Elements == null || seqPadata.Elements.Length == 0) { tempPaData = new Asn1SequenceOf<PA_DATA>(new PA_DATA[] { paTgsReq }); } else { PA_DATA[] paDatas = new PA_DATA[seqPadata.Elements.Length + 1]; Array.Copy(seqPadata.Elements, paDatas, seqPadata.Elements.Length); paDatas[seqPadata.Elements.Length] = paTgsReq; tempPaData = new Asn1SequenceOf<PA_DATA>(paDatas); } KerberosTgsRequest tgsRequest = new KerberosTgsRequest(KerberosConstValue.KERBEROSV5, kdcReqBody, tempPaData, Context.TransportType); this.SendPdu(tgsRequest); this.testSite.Log.Add(LogEntryKind.Debug, "Send TGS request."); }
/// <summary> /// Create and send FAST AS request /// </summary> /// <param name="kdcOptions">KDC options</param> /// <param name="innerSeqPaData">A sequence of preauthentication data in FAST request</param> /// <param name="outerSeqPaData">A sequence of preauthentication data</param> /// <param name="subKey">Sub-session key for authenticator in FAST armor field</param> /// <param name="fastOptions">FAST options</param> /// <param name="apOptions">AP options in FAST armor field</param> public void SendAsRequestWithFastHideCName( KdcOptions kdcOptions, string cName, Asn1SequenceOf<PA_DATA> innerSeqPaData, Asn1SequenceOf<PA_DATA> outerSeqPaData, EncryptionKey subKey, ApOptions apOptions) { var fastOptions = new Protocols.TestTools.StackSdk.Security.KerberosV5.Preauth.FastOptions( KerberosUtility.ConvertInt2Flags((int)FastOptionFlags.Hide_Client_Names)); Context.Subkey = subKey; string sName = KerberosConstValue.KERBEROS_SNAME; string domain = this.Context.Realm.Value; PrincipalName sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST), KerberosUtility.String2SeqKerbString(sName, domain)); KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sname); kdcReqBody.cname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_PRINCIPAL), KerberosUtility.String2SeqKerbString(cName)); var pafxfast = CreateAsPaFxFast(subKey, fastOptions, apOptions, innerSeqPaData, sName, kdcReqBody); PA_DATA[] elements; if (outerSeqPaData != null && outerSeqPaData.Elements.Length > 0) { elements = new PA_DATA[outerSeqPaData.Elements.Length + 1]; Array.Copy(outerSeqPaData.Elements, elements, outerSeqPaData.Elements.Length); elements[outerSeqPaData.Elements.Length] = pafxfast.Data; } else { elements = new PA_DATA[] { pafxfast.Data }; } Asn1SequenceOf<PA_DATA> seqPaData = new Asn1SequenceOf<PA_DATA>(); KerberosAsRequest asRequest = this.CreateAsRequest(kdcReqBody, new Asn1SequenceOf<PA_DATA>(elements)); this.SendPdu(asRequest); this.testSite.Log.Add(LogEntryKind.Debug, "Send AS Request with FAST PA-DATA."); }
/// <summary> /// Create and send FAST AS request with an unknown armor type /// </summary> /// <param name="kdcOptions">KDC options</param> /// <param name="innerSeqPaData">A sequence of preauthentication data in FAST request</param> /// <param name="outerSeqPaData">A sequence of preauthentication data</param> /// <param name="subKey">Sub-session key for authenticator in FAST armor field</param> /// <param name="fastOptions">FAST options</param> /// <param name="apOptions">AP options in FAST armor field</param> /// <param name="armorType">armorType</param> public void SendAsRequestWithFast( KdcOptions kdcOptions, Asn1SequenceOf<PA_DATA> innerSeqPaData, Asn1SequenceOf<PA_DATA> outerSeqPaData, EncryptionKey subKey, FastOptions fastOptions, ApOptions apOptions, KrbFastArmorType armorType ) { Context.Subkey = subKey; string sName = KerberosConstValue.KERBEROS_SNAME; string domain = this.Context.Realm.Value; PrincipalName sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST), KerberosUtility.String2SeqKerbString(sName, domain)); KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sname); var pafxfast = CreateAsPaFxFast(subKey, fastOptions, apOptions, innerSeqPaData, sName, kdcReqBody, armorType); PA_DATA[] elements; if (outerSeqPaData != null && outerSeqPaData.Elements.Length > 0) { elements = new PA_DATA[outerSeqPaData.Elements.Length + 1]; Array.Copy(outerSeqPaData.Elements, elements, outerSeqPaData.Elements.Length); elements[outerSeqPaData.Elements.Length] = pafxfast.Data; } else { elements = new PA_DATA[] { pafxfast.Data }; } Asn1SequenceOf<PA_DATA> seqPaData = new Asn1SequenceOf<PA_DATA>(); KerberosAsRequest asRequest = this.CreateAsRequest(kdcReqBody, new Asn1SequenceOf<PA_DATA>(elements)); this.SendPdu(asRequest); this.testSite.Log.Add(LogEntryKind.Debug, "Send AS Request with FAST PA-DATA."); }
private void CBAC_Smb2_AccessFile(string RealmName, User user, Computer kdc, TransportType transportType, FileServer fileserver, string filePath, string fileName, bool expectAccessDeny) { base.Logging(); client = new KerberosTestClient(RealmName, user.Username, user.Password, KerberosAccountType.User, kdc.IPAddress, kdc.Port, transportType, testConfig.SupportedOid); KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE; client.SendAsRequest(options, null); METHOD_DATA methodData; KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData); BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send AS request with PaEncTimeStamp, PaPacRequest and paPacOptions."); string timeStamp = KerberosUtility.CurrentKerberosTime.Value; PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, client.Context.SelectedEType, client.Context.CName.Password, this.client.Context.CName.Salt); PaPacRequest paPacRequest = new PaPacRequest(true); PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc); Asn1SequenceOf <PA_DATA> seqOfPaData = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.Data }); client.SendAsRequest(options, seqOfPaData); KerberosAsResponse asResponse = client.ExpectAsResponse(); //Verify encrypted padata PaSupportedEncTypes paSupportedEncTypes = null; BaseTestSite.Assert.IsNotNull(asResponse.EncPart, "The encrypted part of AS-REP is decrypted."); BaseTestSite.Assert.IsNotNull(asResponse.EncPart.pa_datas, "The encrypted padata is not null."); if (this.testConfig.IsKileImplemented) { foreach (var padata in asResponse.EncPart.pa_datas.Elements) { var parsedPadata = PaDataParser.ParseRepPaData(padata); if (parsedPadata is PaSupportedEncTypes) { paSupportedEncTypes = parsedPadata as PaSupportedEncTypes; } } BaseTestSite.Assert.IsNotNull(paSupportedEncTypes, "The encrypted padata of AS-REP contains PA_SUPPORTED_ENCTYPES."); if (this.testConfig.IsClaimSupported) { BaseTestSite.Assert.IsTrue( paSupportedEncTypes.SupportedEncTypes.HasFlag(SupportedEncryptionTypes.Claims_Supported), "Claims is supported."); } } //TGS exchange BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send FAST armored TGS request: {0}.", fileserver.Smb2ServiceName); Asn1SequenceOf <PA_DATA> seqOfPaData2 = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paPacRequest.Data, paPacOptions.Data }); client.SendTgsRequest(fileserver.Smb2ServiceName, options, seqOfPaData2); KerberosTgsResponse tgsResponse = client.ExpectTgsResponse(); EncryptionKey key = testConfig.QueryKey(fileserver.Smb2ServiceName, client.Context.Realm.ToString(), client.Context.SelectedEType); tgsResponse.DecryptTicket(key); BaseTestSite.Assert.IsNotNull(tgsResponse.EncPart, "The encrypted part of TGS-REP is decrypted."); //Verify TGS encryped padata paSupportedEncTypes = null; BaseTestSite.Assert.IsNotNull(tgsResponse.EncPart, "The encrypted part of TGS-REP is decrypted."); BaseTestSite.Assert.IsNotNull(tgsResponse.EncPart.pa_datas, "The encrypted padata of TGS-REP is not null."); if (this.testConfig.IsKileImplemented) { foreach (var padata in tgsResponse.EncPart.pa_datas.Elements) { var parsedPadata = PaDataParser.ParseRepPaData(padata); if (parsedPadata is PaSupportedEncTypes) { paSupportedEncTypes = parsedPadata as PaSupportedEncTypes; } } BaseTestSite.Assert.IsNotNull(paSupportedEncTypes, "The encrypted padata of TGS-REP contains PA_SUPPORTED_ENCTYPES."); } if (this.testConfig.IsKileImplemented) { BaseTestSite.Assert.IsNotNull(tgsResponse.TicketEncPart.authorization_data, "The ticket contains Authorization data."); AdWin2KPac adWin2kPac = FindOneInAuthData <AdWin2KPac>(tgsResponse.TicketEncPart.authorization_data.Elements); BaseTestSite.Assert.IsNotNull(adWin2kPac, "The Authorization data contains AdWin2KPac."); } AuthorizationData data = null; EncryptionKey subkey = KerberosUtility.GenerateKey(client.Context.SessionKey); byte[] token = client.CreateGssApiToken(ApOptions.MutualRequired, data, subkey, ChecksumFlags.GSS_C_MUTUAL_FLAG | ChecksumFlags.GSS_C_INTEG_FLAG); BaseTestSite.Log.Add(LogEntryKind.Comment, "Logon to fileserver and Access File."); AccessFile(filePath, fileName, fileserver, token, tgsResponse.EncPart.key, expectAccessDeny); }
private void CrossRealm_Smb2_AccessFile(string localRealmName, string trustuedRealmName, User localUser, Computer localKDC, Computer trustedKDC, TransportType transportType, FileServer fileserverInTrustedRealm, string filePath, string fileName, bool expectAccessDeny) { base.Logging(); client = new KerberosTestClient(localRealmName, localUser.Username, localUser.Password, KerberosAccountType.User, localKDC.IPAddress, localKDC.Port, transportType, testConfig.SupportedOid); //Create and send AS request KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE; client.SendAsRequest(options, null); //Recieve preauthentication required error METHOD_DATA methodData; KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData); //Create sequence of PA data string timeStamp = KerberosUtility.CurrentKerberosTime.Value; PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, this.client.Context.SelectedEType, this.client.Context.CName.Password, this.client.Context.CName.Salt); PaPacRequest paPacRequest = new PaPacRequest(true); Asn1SequenceOf <PA_DATA> seqOfPaData = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data }); //Create and send AS request client.SendAsRequest(options, seqOfPaData); KerberosAsResponse asResponse = client.ExpectAsResponse(); //Create and send TGS request if (this.testConfig.TrustType == Adapter.TrustType.Forest) { client.SendTgsRequest(fileserverInTrustedRealm.Smb2ServiceName, options); } else if (this.testConfig.TrustType == Adapter.TrustType.Realm) { client.SendTgsRequest(trustedKDC.DefaultServiceName, options); } BaseTestSite.Log.Add(LogEntryKind.Comment, "Create and send TGS request"); KerberosTgsResponse tgsResponse = client.ExpectTgsResponse(); BaseTestSite.Log.Add(LogEntryKind.Comment, "Receive a referral TGS response."); BaseTestSite.Assert.AreEqual(trustedKDC.DefaultServiceName, KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname), "The service principal name in referral ticket should match expected."); BaseTestSite.Assert.AreEqual(localRealmName.ToLower(), tgsResponse.Response.ticket.realm.Value.ToLower(), "The realm name in referral ticket should match expected."); //Change realm client.ChangeRealm(trustuedRealmName, trustedKDC.IPAddress, trustedKDC.Port, this.testConfig.TransportType); //Create and send referral TGS request client.SendTgsRequest(fileserverInTrustedRealm.Smb2ServiceName, options); KerberosTgsResponse refTgsResponse = client.ExpectTgsResponse(); BaseTestSite.Assert.AreEqual(fileserverInTrustedRealm.Smb2ServiceName, KerberosUtility.PrincipalName2String(refTgsResponse.Response.ticket.sname), "The service principal name in service ticket should match expected."); BaseTestSite.Assert.AreEqual(trustuedRealmName.ToLower(), refTgsResponse.Response.ticket.realm.Value.ToLower(), "The realm name in service ticket should match expected."); EncryptionKey key = testConfig.QueryKey(fileserverInTrustedRealm.Smb2ServiceName, client.Context.Realm.ToString(), client.Context.SelectedEType); refTgsResponse.DecryptTicket(key); BaseTestSite.Assert.AreEqual(localRealmName.ToLower(), refTgsResponse.TicketEncPart.crealm.Value.ToLower(), "Realm name in service ticket encrypted part should match expected."); BaseTestSite.Assert.AreEqual(localUser.Username.ToLower(), KerberosUtility.PrincipalName2String(refTgsResponse.TicketEncPart.cname).ToLower(), "User name in service ticket encrypted part should match expected."); AuthorizationData data = null; EncryptionKey subkey = KerberosUtility.GenerateKey(client.Context.SessionKey); byte[] token = client.CreateGssApiToken(ApOptions.MutualRequired, data, subkey, ChecksumFlags.GSS_C_MUTUAL_FLAG | ChecksumFlags.GSS_C_INTEG_FLAG); BaseTestSite.Log.Add(LogEntryKind.Comment, "Logon to fileserver and Access File."); AccessFile(filePath, fileName, fileserverInTrustedRealm, token, refTgsResponse.EncPart.key, expectAccessDeny); }
/// <summary> /// Create and send TGS request /// </summary> /// <param name="sName">Service principal name</param> /// <param name="kdcOptions">KDC options</param> /// <param name="msgType">Message Type</param> public void SendTgsRequest(string sName, KdcOptions kdcOptions, MsgType msgType) { SendTgsRequest(sName, kdcOptions, null, null, null, null, msgType); }
//TODO... //askTGS with TGT kirbi public static async System.Threading.Tasks.Task <TicketFlags> askTGS2(string kdc, ILoggerFactory logger, TcpKerberosTransport transport, KrbAsRep asRep, string username, string password, string domainName, string spn, bool isUnconstrained = false, bool outKirbi = false, bool verbose = false, bool kerberoast = false, bool ptt = false, string hash = null, EncryptionType etype = EncryptionType.RC4_HMAC_NT, bool outfile = false, string srvName = null, string tgsHash = null, EncryptionType tgsEtype = EncryptionType.AES256_CTS_HMAC_SHA1_96 ) { var now = DateTime.Now; credKey = password != null ? new KerberosPasswordCredential(username, password, domainName).CreateKey() : new Utils.KerberosHashCreds(username, hash, etype, domainName).CreateKey(); KrbEncAsRepPart asDecrypted = cred.DecryptKdcRep( asRep, KeyUsage.EncAsRepPart, d => KrbEncAsRepPart.DecodeApplication(d)); var sessionKey = asDecrypted.Key; //Request Service Ticket parameters ApOptions apOptions = ApOptions.Reserved; KdcOptions kdcOptions = KdcOptions.Forwardable | KdcOptions.Renewable | KdcOptions.RenewableOk | KdcOptions.Canonicalize; string s4u = null; KrbTicket s4uTicket = null; KrbTicket u2uServerTicket = null; if (isUnconstrained) { spn = $"krbtgt/{domainName}"; kdcOptions |= KdcOptions.Forwarded; } var rst = new RequestServiceTicket() { ServicePrincipalName = spn, ApOptions = apOptions, S4uTarget = s4u, S4uTicket = s4uTicket, UserToUserTicket = u2uServerTicket, KdcOptions = kdcOptions, Realm = domainName }; var sname = rst.ServicePrincipalName.Split('/', '@'); var tgt = asRep.Ticket; var additionalTickets = new List <KrbTicket>(); if (rst.KdcOptions.HasFlag(KdcOptions.EncTktInSkey) && rst.UserToUserTicket != null) { additionalTickets.Add(rst.UserToUserTicket); } if (!string.IsNullOrWhiteSpace(rst.S4uTarget)) { rst.KdcOptions |= KdcOptions.Forwardable; } if (rst.S4uTicket != null) { rst.KdcOptions |= KdcOptions.ConstrainedDelegation; additionalTickets.Add(rst.S4uTicket); } var body = new KrbKdcReqBody { //Specify RC4 as the only supported EType EType = new[] { EncryptionType.RC4_HMAC_NT },//KrbConstants.KerberosConstants.ETypes.ToArray(), KdcOptions = rst.KdcOptions, Nonce = KrbConstants.KerberosConstants.GetNonce(), Realm = rst.Realm, SName = new KrbPrincipalName() { Type = PrincipalNameType.NT_SRV_INST, Name = sname }, Till = KrbConstants.KerberosConstants.EndOfTime, CName = rst.CNameHint }; if (additionalTickets.Count > 0) { body.AdditionalTickets = additionalTickets.ToArray(); } var bodyChecksum = KrbChecksum.Create( body.Encode(), sessionKey.AsKey(), KeyUsage.PaTgsReqChecksum ); //ApReq //Authenticator var authenticator = new KrbAuthenticator { CName = asRep.CName, Realm = asRep.Ticket.Realm, SequenceNumber = KrbConstants.KerberosConstants.GetNonce(), Checksum = bodyChecksum, CTime = now, CuSec = now.Millisecond //new Random().Next(0, 999999) }; var subSessionKey = KrbEncryptionKey.Generate(sessionKey.EType); subSessionKey.Usage = KeyUsage.EncTgsRepPartSubSessionKey; authenticator.Subkey = subSessionKey; var encryptedAuthenticator = KrbEncryptedData.Encrypt( authenticator.EncodeApplication(), sessionKey.AsKey(), KeyUsage.PaTgsReqAuthenticator ); var apReq = new KrbApReq { Ticket = tgt, ApOptions = apOptions, Authenticator = encryptedAuthenticator }; var pacOptions = new KrbPaPacOptions { Flags = PacOptions.BranchAware }.Encode(); var paData = new List <KrbPaData>() { new KrbPaData { Type = PaDataType.PA_TGS_REQ, Value = apReq.EncodeApplication() }, new KrbPaData { Type = PaDataType.PA_PAC_OPTIONS, Value = pacOptions } }; if (!string.IsNullOrWhiteSpace(rst.S4uTarget)) { var paS4u = new KrbPaForUser { AuthPackage = "Kerberos", UserName = new KrbPrincipalName { Type = PrincipalNameType.NT_ENTERPRISE, Name = new[] { s4u } }, UserRealm = tgt.Realm }; paS4u.GenerateChecksum(subSessionKey.AsKey()); paData.Add(new KrbPaData { Type = PaDataType.PA_FOR_USER, Value = paS4u.Encode() }); } var tgs = new KrbTgsReq { PaData = paData.ToArray(), Body = body }; ReadOnlyMemory <byte> encodedTgs = tgs.EncodeApplication(); Console.WriteLine("[*] Sending TGS-REQ ..."); if (verbose) { PrintFunc.PrintReq(tgs, credKey, sessionKey.AsKey()); } CancellationToken cancellation = default; cancellation.ThrowIfCancellationRequested(); KrbTgsRep tgsRep = null; try { tgsRep = await transport.SendMessage <KrbTgsRep>( rst.Realm, encodedTgs, cancellation ); } catch (KerberosProtocolException pex) { Console.WriteLine("[x] Kerberos Error: {0}\n", pex.Message); Environment.Exit(0); } Console.WriteLine("[*] Receiving TGS-REP ..."); if (verbose) { PrintFunc.PrintRep(tgsRep, credKey); } var returnFlag = TicketFlags.Anonymous; try { //TGS-REP Enc-Part //https://github.com/dotnet/Kerberos.NET/blob/develop/Kerberos.NET/Entities/Krb/KrbTgsReq.cs#L144 KrbEncTgsRepPart tgsDecryptedRepPart = tgsRep.EncPart.Decrypt <KrbEncTgsRepPart>( subSessionKey.AsKey(), KeyUsage.EncTgsRepPartSubSessionKey, (ReadOnlyMemory <byte> t) => KrbEncTgsRepPart.DecodeApplication(t)); if (verbose) { Console.WriteLine(" * [Decrypted Enc-Part]:"); PrintFunc.PrintRepEnc(tgsDecryptedRepPart, credKey); returnFlag = tgsDecryptedRepPart.Flags; if (!string.IsNullOrEmpty(tgsHash)) { //========================================= //TGS Tiket Enc-Part //Service account Cred var kerbCred2 = new Utils.KerberosHashCreds(srvName, tgsHash, tgsEtype); //TGS-REQ Ticket Enc-Part KrbEncTicketPart ticketDecrypted = tgsRep.Ticket.EncryptedPart.Decrypt <KrbEncTicketPart> (kerbCred2.CreateKey(), KeyUsage.Ticket, (ReadOnlyMemory <byte> t) => KrbEncTicketPart.DecodeApplication(t)); Console.WriteLine(" * [Decrypted Ticket Enc-Part]:"); PrintFunc.PrintTicketEnc(ticketDecrypted); //========================================= } } if (outKirbi || outfile) { var kirbiTGS = Kirbi.toKirbi(tgsRep, tgsDecryptedRepPart, ptt); if (outKirbi) { Console.WriteLine("[+] TGS Kirbi:"); Console.WriteLine(" - {0}", Convert.ToBase64String(kirbiTGS)); } if (outfile) { Utils.Utils.WriteBytesToFile(Utils.Utils.MakeTicketFileName(username, sname), kirbiTGS); } } } catch (Exception e) { Console.WriteLine("[x] {0}", e.Message); } if (kerberoast) { //Kerberoasting var encType = (int)Enum.Parse(typeof(EncryptionType), tgsRep.Ticket.EncryptedPart.EType.ToString()); var myCipher = (BitConverter.ToString(tgsRep.Ticket.EncryptedPart.Cipher.ToArray())).Replace("-", ""); var kroasthash = String.Format("$krb5tgs${0}$*{1}${2}${3}*${4}${5}", encType, username, domainName, spn, myCipher.Substring(0, 32), myCipher.Substring(32)); Console.WriteLine("[+] Kerberoasting Hash: {0}", kroasthash); } return(returnFlag); }
internal void Encode(AsnWriter writer, Asn1Tag tag) { writer.PushSequence(tag); writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 0)); writer.WriteBitString(KdcOptions.AsReadOnlySpan()); writer.PopSequence(new Asn1Tag(TagClass.ContextSpecific, 0)); if (Asn1Extension.HasValue(CName)) { writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 1)); CName?.Encode(writer); writer.PopSequence(new Asn1Tag(TagClass.ContextSpecific, 1)); } writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 2)); writer.WriteCharacterString(UniversalTagNumber.GeneralString, Realm); writer.PopSequence(new Asn1Tag(TagClass.ContextSpecific, 2)); if (Asn1Extension.HasValue(SName)) { writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 3)); SName?.Encode(writer); writer.PopSequence(new Asn1Tag(TagClass.ContextSpecific, 3)); } if (Asn1Extension.HasValue(From)) { writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 4)); writer.WriteGeneralizedTime(From.Value); writer.PopSequence(new Asn1Tag(TagClass.ContextSpecific, 4)); } writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 5)); writer.WriteGeneralizedTime(Till); writer.PopSequence(new Asn1Tag(TagClass.ContextSpecific, 5)); if (Asn1Extension.HasValue(RTime)) { writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 6)); writer.WriteGeneralizedTime(RTime.Value); writer.PopSequence(new Asn1Tag(TagClass.ContextSpecific, 6)); } writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 7)); writer.WriteInteger(Nonce); writer.PopSequence(new Asn1Tag(TagClass.ContextSpecific, 7)); writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 8)); writer.PushSequence(); for (int i = 0; i < EType.Length; i++) { writer.WriteInteger((long)EType[i]); } writer.PopSequence(); writer.PopSequence(new Asn1Tag(TagClass.ContextSpecific, 8)); if (Asn1Extension.HasValue(Addresses)) { writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 9)); writer.PushSequence(); for (int i = 0; i < Addresses.Length; i++) { Addresses[i]?.Encode(writer); } writer.PopSequence(); writer.PopSequence(new Asn1Tag(TagClass.ContextSpecific, 9)); } if (Asn1Extension.HasValue(EncAuthorizationData)) { writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 10)); EncAuthorizationData?.Encode(writer); writer.PopSequence(new Asn1Tag(TagClass.ContextSpecific, 10)); } if (Asn1Extension.HasValue(AdditionalTickets)) { writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 11)); writer.PushSequence(); for (int i = 0; i < AdditionalTickets.Length; i++) { AdditionalTickets[i]?.Encode(writer); } writer.PopSequence(); writer.PopSequence(new Asn1Tag(TagClass.ContextSpecific, 11)); } writer.PopSequence(tag); }
/// <summary> /// Kerberos Client Initialize without server token /// </summary> private void ClientInitialize() { this.ApRequestAuthenticator = null; // Create and send AS request for pre-authentication KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE; KerberosTicket ticket = this.GetTGTCachedToken(this.credential, this.serverName); if (ticket == null) { this.SendAsRequest(options, null); // Expect recieve preauthentication required error METHOD_DATA methodData; this.ExpectPreauthRequiredError(out methodData); // Create sequence of PA data string timeStamp = KerberosUtility.CurrentKerberosTime.Value; PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, this.Context.SelectedEType, this.Context.CName.Password, this.Context.CName.Salt); PaPacRequest paPacRequest = new PaPacRequest(true); PaPacOptions paPacOptions = new PaPacOptions(PacOptions.Claims | PacOptions.ForwardToFullDc); Asn1SequenceOf <PA_DATA> seqOfPaData_AS = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data, paPacOptions.Data }); // Create and send AS request for TGT KerberosAsRequest asRequest = this.SendAsRequest(options, seqOfPaData_AS); // Expect TGT(AS) Response from KDC KerberosAsResponse asResponse = this.ExpectAsResponse(); // Create and send TGS request Asn1SequenceOf <PA_DATA> seqOfPaData_TGS = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paPacRequest.Data, paPacOptions.Data }); this.SendTgsRequest(this.serverName, options, seqOfPaData_TGS); // Expect TGS Response from KDC KerberosTgsResponse tgsResponse = this.ExpectTgsResponse(); this.UpdateTGTCachedToken(this.Context.Ticket); } else { // Restore SessionKey and Ticket from cache this.Context.SessionKey = ticket.SessionKey; this.Context.ApSessionKey = ticket.SessionKey; this.Context.Ticket = ticket; this.Context.SelectedEType = (EncryptionType)Context.Ticket.Ticket.enc_part.etype.Value; } // cache this.Context.Ticket; ApOptions apOption; GetFlagsByContextAttribute(out apOption); AuthorizationData data = null; EncryptionKey subkey = KerberosUtility.GenerateKey(this.client.Context.ContextKey); this.token = this.CreateGssApiToken(apOption, data, subkey, this.Context.ChecksumFlag, KerberosConstValue.GSSToken.GSSAPI); bool isMutualAuth = (contextAttribute & ClientSecurityContextAttribute.MutualAuth) == ClientSecurityContextAttribute.MutualAuth; bool isDceStyle = (contextAttribute & ClientSecurityContextAttribute.DceStyle) == ClientSecurityContextAttribute.DceStyle; if (isMutualAuth || isDceStyle) { this.needContinueProcessing = true; } else { this.needContinueProcessing = false; } }
public void KerbAuth_Replay() { #region Get Service Ticket BaseTestSite.Log.Add(LogEntryKind.TestStep, "Initialize Kerberos Functional Client"); KerberosFunctionalClient kerberosClient = new KerberosFunctionalClient( TestConfig.DomainName, TestConfig.UserName, TestConfig.UserPassword, KerberosAccountType.User, KDCIP, KDCPort, TransportType.TCP, OidPkt, BaseTestSite); //Create and send AS request const KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE; kerberosClient.SendAsRequest(options, null); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client expects Kerberos Error from KDC"); //Receive preauthentication required error METHOD_DATA methodData; KerberosKrbError krbError = kerberosClient.ExpectPreauthRequiredError(out methodData); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client sends AS request with PA-DATA set"); //Create sequence of PA data string timeStamp = KerberosUtility.CurrentKerberosTime.Value; PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, kerberosClient.Context.SelectedEType, kerberosClient.Context.CName.Password, kerberosClient.Context.CName.Salt); PaPacRequest paPacRequest = new PaPacRequest(true); Asn1SequenceOf <PA_DATA> seqOfPaData = new Asn1SequenceOf <PA_DATA>(new[] { paEncTimeStamp.Data, paPacRequest.Data }); //Create and send AS request kerberosClient.SendAsRequest(options, seqOfPaData); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client expects AS response from KDC"); KerberosAsResponse asResponse = kerberosClient.ExpectAsResponse(); BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT."); //Create and send TGS request BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client sends TGS request to KDC"); kerberosClient.SendTgsRequest(servicePrincipalName, options); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Kerberos Functional Client expects TGS response from KDC"); KerberosTgsResponse tgsResponse = kerberosClient.ExpectTgsResponse(); BaseTestSite.Assert.AreEqual(servicePrincipalName, KerberosUtility.PrincipalName2String(tgsResponse.Response.ticket.sname), "Service principal name in service ticket should match expected."); #endregion #region Create AP request Ticket serviceTicket = kerberosClient.Context.Ticket.Ticket; Realm crealm = serviceTicket.realm; EncryptionKey subkey = KerberosUtility.GenerateKey(kerberosClient.Context.SessionKey); PrincipalName cname = kerberosClient.Context.CName.Name; Authenticator authenticator = CreateAuthenticator(cname, crealm, subkey); BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create AP Request"); KerberosApRequest request = new KerberosApRequest( kerberosClient.Context.Pvno, new APOptions(KerberosUtility.ConvertInt2Flags((int)ApOptions.MutualRequired)), kerberosClient.Context.Ticket, authenticator, KeyUsageNumber.AP_REQ_Authenticator ); #endregion #region Create GSS token and send session setup request BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create GSS Token"); byte[] token = KerberosUtility.AddGssApiTokenHeader(request, OidPkt, GssToken); Smb2FunctionalClientForKerbAuth smb2Client = new Smb2FunctionalClientForKerbAuth(TestConfig.Timeout, TestConfig, BaseTestSite); smb2Client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress); byte[] repToken; uint status = DoSessionSetupWithGssToken(smb2Client, token, out repToken); KerberosApResponse apRep = kerberosClient.GetApResponseFromToken(repToken, GssToken); // Get subkey from AP response, which used for signing in smb2 apRep.Decrypt(kerberosClient.Context.Ticket.SessionKey.keyvalue.ByteArrayValue); smb2Client.SetSessionSigningAndEncryption(true, false, apRep.ApEncPart.subkey.keyvalue.ByteArrayValue); #endregion #region Second client BaseTestSite.Log.Add(LogEntryKind.TestStep, "Replay the request from another client"); Smb2FunctionalClientForKerbAuth smb2Client2 = new Smb2FunctionalClientForKerbAuth(TestConfig.Timeout, TestConfig, BaseTestSite); smb2Client2.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress); status = DoSessionSetupWithGssToken(smb2Client2, token, out repToken); BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status, "Session Setup should fail because it uses a Replay of KRB_AP_REQ"); if (TestConfig.IsWindowsPlatform) { krbError = kerberosClient.GetKrbErrorFromToken(repToken); BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_REPEAT, krbError.ErrorCode, "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_REPEAT); } smb2Client2.Disconnect(); #endregion string path = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare); AccessFile(smb2Client, path); smb2Client.LogOff(); smb2Client.Disconnect(); }
/// <summary> /// Create and send AS request for Password change /// </summary> /// <param name="kdcOptions">KDC options</param> /// <param name="seqPaData">A sequence of preauthentication data</param> public void SendAsRequestForPwdChange(KdcOptions kdcOptions, Asn1SequenceOf<PA_DATA> seqPaData) { PrincipalName sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST), KerberosUtility.String2SeqKerbString(KerberosConstValue.KERBEROS_KADMIN_SNAME.Split('/'))); KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sname); KerberosAsRequest asRequest = this.CreateAsRequest(kdcReqBody, seqPaData); this.SendPdu(asRequest); this.testSite.Log.Add(LogEntryKind.Debug, "Send AS Request for password change."); }
private KDC_REQ_BODY CreateKdcRequestBody( KdcOptions kdcOptions, PrincipalName sName, AuthorizationData data = null ) { KDC_REQ_BODY kdcReqBody = CreateKdcRequestBody(kdcOptions, sName); if (data == null) return kdcReqBody; Asn1BerEncodingBuffer asnBuffer = new Asn1BerEncodingBuffer(); // Fix me: NullReferenceException if data is null. if (data != null) data.BerEncode(asnBuffer, true); EncryptedData eData = new EncryptedData(); eData.etype = new KerbInt32(0); byte[] encAsnEncoded = asnBuffer.Data; if (Context.SessionKey != null && Context.SessionKey.keytype != null && Context.SessionKey.keyvalue != null && Context.SessionKey.keyvalue.Value != null) { encAsnEncoded = KerberosUtility.Encrypt((EncryptionType)Context.SessionKey.keytype.Value, Context.SessionKey.keyvalue.ByteArrayValue, asnBuffer.Data, (int)KeyUsageNumber.TGS_REQ_KDC_REQ_BODY_AuthorizationData); eData.etype = new KerbInt32(Context.SessionKey.keytype.Value); } eData.cipher = new Asn1OctetString(encAsnEncoded); kdcReqBody.enc_authorization_data = eData; return kdcReqBody; }
public void ChangePasswordSuccess() { base.Logging(); if (!this.testConfig.UseProxy) { BaseTestSite.Assert.Inconclusive("This case is only applicable when Kerberos Proxy Service is in use."); } //Create kerberos test client and connect client = new KerberosTestClient(this.testConfig.LocalRealm.RealmName, this.testConfig.LocalRealm.User[22].Username, this.testConfig.LocalRealm.User[22].Password, KerberosAccountType.User, testConfig.LocalRealm.KDC[0].IPAddress, testConfig.LocalRealm.KDC[0].Port, testConfig.TransportType, testConfig.SupportedOid); // Kerberos Proxy Service is used if (this.testConfig.UseProxy) { BaseTestSite.Log.Add(LogEntryKind.Comment, "Initialize KKDCP Client ."); KKDCPClient proxyClient = new KKDCPClient(proxyClientConfig); proxyClient.TargetDomain = this.testConfig.LocalRealm.RealmName; client.UseProxy = true; client.ProxyClient = proxyClient; } KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends AS_REQ without Pre-Authentication data"); client.SendAsRequestForPwdChange(options, null); //Recieve preauthentication required error METHOD_DATA methodData; BaseTestSite.Log.Add(LogEntryKind.TestStep, "KDC returns KRB_ERROR: KDC_ERR_PREAUTH_REQUIRED"); KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData); //Create sequence of PA data BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends AS_REQ with PA-ENC-TIMESTAMP and PA-PAC-REQUEST"); string timeStamp = KerberosUtility.CurrentKerberosTime.Value; PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, this.client.Context.SelectedEType, this.client.Context.CName.Password, this.client.Context.CName.Salt); PaPacRequest paPacRequest = new PaPacRequest(true); Asn1SequenceOf <PA_DATA> seqOfPaData = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data }); //Create and send AS request client.SendAsRequestForPwdChange(options, seqOfPaData); BaseTestSite.Log.Add(LogEntryKind.TestStep, "KDC returns AS_REP"); KerberosAsResponse asResponse = client.ExpectAsResponse(); BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT."); //Create kpassword test client and connect KpasswdTestClient kpassClient = new KpasswdTestClient( testConfig.LocalRealm.KDC[0].IPAddress, KerberosConstValue.KPASSWORD_PORT, testConfig.TransportType, client.Context.Ticket); // Kerberos Proxy Service is used if (this.testConfig.UseProxy) { BaseTestSite.Log.Add(LogEntryKind.Comment, "Initialize KKDCP Client ."); KKDCPClient proxyClient = new KKDCPClient(proxyClientConfig); proxyClient.TargetDomain = this.testConfig.LocalRealm.RealmName; kpassClient.UseProxy = true; kpassClient.ProxyClient = proxyClient; } //Create and send Kpassword request string newPwd = this.testConfig.LocalRealm.User[22].Password; BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client sends KpasswordRequest"); kpassClient.SendKpasswordRequest(newPwd); BaseTestSite.Log.Add(LogEntryKind.TestStep, "KDC returns KpasswordResponse"); KpasswordResponse kpassResponse = kpassClient.ExpectKpasswordResponse(); //Verify the result code BaseTestSite.Assert.AreEqual(KpasswdError.KRB5_KPASSWD_SUCCESS, (KpasswdError)kpassClient.GetResultCode(kpassResponse), "The result code should be KRB5_KPASSWD_SUCCESS."); }
public void NetworkLogonLdapWithoutPac_Ldap() { base.Logging(); client = new KerberosTestClient(this.testConfig.LocalRealm.RealmName, this.testConfig.LocalRealm.User[1].Username, this.testConfig.LocalRealm.User[1].Password, KerberosAccountType.User, testConfig.LocalRealm.KDC[0].IPAddress, testConfig.LocalRealm.KDC[0].Port, testConfig.TransportType, testConfig.SupportedOid); // Kerberos Proxy Service is used if (this.testConfig.UseProxy) { BaseTestSite.Log.Add(LogEntryKind.Comment, "Initialize KKDCP Client ."); KKDCPClient proxyClient = new KKDCPClient(proxyClientConfig); proxyClient.TargetDomain = this.testConfig.LocalRealm.RealmName; client.UseProxy = true; client.ProxyClient = proxyClient; } //Create and send AS request KdcOptions options = KdcOptions.FORWARDABLE | KdcOptions.CANONICALIZE | KdcOptions.RENEWABLE; client.SendAsRequest(options, null); //Recieve preauthentication required error METHOD_DATA methodData; KerberosKrbError krbError = client.ExpectPreauthRequiredError(out methodData); //Create sequence of PA data string timeStamp = KerberosUtility.CurrentKerberosTime.Value; PaEncTimeStamp paEncTimeStamp = new PaEncTimeStamp(timeStamp, 0, this.client.Context.SelectedEType, this.client.Context.CName.Password, this.client.Context.CName.Salt); PaPacRequest paPacRequest = new PaPacRequest(false); Asn1SequenceOf <PA_DATA> seqOfPaData = new Asn1SequenceOf <PA_DATA>(new PA_DATA[] { paEncTimeStamp.Data, paPacRequest.Data }); //Create and send AS request client.SendAsRequest(options, seqOfPaData); KerberosAsResponse asResponse = client.ExpectAsResponse(); BaseTestSite.Assert.IsNotNull(asResponse.Response.ticket, "AS response should contain a TGT."); //Create and send TGS request client.SendTgsRequest(this.testConfig.LocalRealm.LdapServer[0].LdapServiceName, options); KerberosTgsResponse tgsResponse = client.ExpectTgsResponse(); AuthorizationData data = null; EncryptionKey subkey = KerberosUtility.GenerateKey(client.Context.SessionKey); byte[] token = client.CreateGssApiToken(ApOptions.MutualRequired, data, subkey, ChecksumFlags.GSS_C_MUTUAL_FLAG | ChecksumFlags.GSS_C_INTEG_FLAG, this.testConfig.LocalRealm.LdapServer[0].GssToken); //AP exchange part byte[] repToken = this.SendAndRecieveLdapAp(this.testConfig.LocalRealm.LdapServer[0], token, this.testConfig.TrustedRealm.LdapServer[0].GssToken); KerberosApResponse apResponse = client.GetApResponseFromToken(repToken, this.testConfig.LocalRealm.LdapServer[0].GssToken); }