private KerberosApRequest CreateApRequest(APOptions option, KerberosTicket ticket, EncryptionKey subKey, AuthorizationData data, KeyUsageNumber keyUsageNumber, ChecksumType checksumType, byte[] checksumBody) { Authenticator authenticator = CreateAuthenticator(ticket, data, subKey, checksumType, checksumBody); KerberosApRequest apRequest = new KerberosApRequest(Context.Pvno, option, ticket, authenticator, keyUsageNumber); return(apRequest); }
/// <summary> /// Create AP request and encode to GSSAPI token /// </summary> /// <param name="apOptions">AP options</param> /// <param name="data">Authorization data</param> /// <param name="subkey">Sub-session key in authenticator</param> /// <param name="checksumFlags">Checksum flags</param> /// <returns></returns> private byte[] CreateGssApiToken(ApOptions apOptions, AuthorizationData data, EncryptionKey subkey, ChecksumFlags checksumFlags, KerberosConstValue.GSSToken gssToken = KerberosConstValue.GSSToken.GSSSPNG) { APOptions options = new APOptions(KerberosUtility.ConvertInt2Flags((int)apOptions)); Authenticator authenticator = CreateAuthenticator(Context.Ticket, data, subkey, checksumFlags); this.ApRequestAuthenticator = authenticator; KerberosApRequest request = new KerberosApRequest( Context.Pvno, options, Context.Ticket, authenticator, KeyUsageNumber.AP_REQ_Authenticator ); this.client.UpdateContext(request); if ((this.Context.ChecksumFlag & ChecksumFlags.GSS_C_DCE_STYLE) == ChecksumFlags.GSS_C_DCE_STYLE) { return(request.ToBytes()); } else { return(KerberosUtility.AddGssApiTokenHeader(request, this.client.OidPkt, gssToken)); } }
private PA_DATA CreatePaTgsReqest(ChecksumType checksumType, byte[] checksumBody, AuthorizationData data) { APOptions option = new APOptions(KerberosUtility.ConvertInt2Flags((int)ApOptions.None)); EncryptionKey key = Context.SessionKey; KerberosApRequest apRequest = CreateApRequest(option, Context.Ticket, null, data, KeyUsageNumber.TG_REQ_PA_TGS_REQ_padataOR_AP_REQ_Authenticator, checksumType, checksumBody); PaTgsReq paTgsReq = new PaTgsReq(apRequest.Request); return(paTgsReq.Data); }
public static byte[] AddGssApiTokenHeader(KerberosApRequest request, KerberosConstValue.OidPkt oidPkt = KerberosConstValue.OidPkt.KerberosToken, KerberosConstValue.GSSToken gssToken = KerberosConstValue.GSSToken.GSSSPNG) { byte[] encoded = request.ToBytes(); byte[] token = KerberosUtility.AddGssApiTokenHeader(ArrayUtility.ConcatenateArrays( BitConverter.GetBytes(KerberosUtility.ConvertEndian((ushort)TOK_ID.KRB_AP_REQ)), encoded), oidPkt, gssToken); return(token); }
/// <summary> /// Create an instance. /// </summary> public KpasswordRequest(KerberosTicket ticket, Authenticator authenticator, string newPwd, bool isAuthErrorRequired = false) { //Create KerberosApRequest long pvno = KerberosConstValue.KERBEROSV5; APOptions option = new APOptions(KerberosUtility.ConvertInt2Flags((int)ApOptions.None)); KerberosApRequest ap_req = new KerberosApRequest(pvno, option, ticket, authenticator, KeyUsageNumber.AP_REQ_Authenticator); //Create KRB_PRIV ChangePasswdData pwd_data = new ChangePasswdData(new Asn1OctetString(newPwd), null, null); priv_enc_part = new EncKrbPrivPart(); priv_enc_part.user_data = pwd_data.newpasswd; priv_enc_part.usec = authenticator.cusec; priv_enc_part.seq_number = authenticator.seq_number; priv_enc_part.s_address = new HostAddress(new KerbInt32((int)AddressType.NetBios), new Asn1OctetString(Encoding.ASCII.GetBytes(System.Net.Dns.GetHostName()))); Asn1BerEncodingBuffer asnBuffPriv = new Asn1BerEncodingBuffer(); priv_enc_part.BerEncode(asnBuffPriv, true); byte[] encAsnEncodedPriv = null; if (!isAuthErrorRequired) { encAsnEncodedPriv = KerberosUtility.Encrypt((EncryptionType)authenticator.subkey.keytype.Value, authenticator.subkey.keyvalue.ByteArrayValue, asnBuffPriv.Data, (int)KeyUsageNumber.KRB_PRIV_EncPart); } else { encAsnEncodedPriv = KerberosUtility.Encrypt((EncryptionType)authenticator.subkey.keytype.Value, authenticator.subkey.keyvalue.ByteArrayValue, asnBuffPriv.Data, (int)KeyUsageNumber.None); } var encrypted = new EncryptedData(); encrypted.etype = new KerbInt32(authenticator.subkey.keytype.Value); encrypted.cipher = new Asn1OctetString(encAsnEncodedPriv); KRB_PRIV krb_priv = new KRB_PRIV(new Asn1Integer(pvno), new Asn1Integer((long)MsgType.KRB_PRIV), encrypted); //Calculate the msg_length and ap_req_length krb_priv.BerEncode(privBuffer, true); ap_req.Request.BerEncode(apBuffer, true); version = 0x0001; ap_req_length = (ushort)apBuffer.Data.Length; msg_length = (ushort)(ap_req_length + privBuffer.Data.Length + 3 * sizeof(ushort)); //Convert Endian version = KerberosUtility.ConvertEndian(version); ap_req_length = KerberosUtility.ConvertEndian(ap_req_length); msg_length = KerberosUtility.ConvertEndian(msg_length); }
/// <summary> /// Updated context based on Kerberos pdu /// </summary> /// <param name="pdu">Kerberos pdu</param> public override void UpdateContext(KerberosPdu pdu) { if (pdu is KerberosAsRequest) { KerberosAsRequest request = (KerberosAsRequest)pdu; UpdateContext(request); } if (pdu is KerberosKrbError) { KerberosKrbError error = (KerberosKrbError)pdu; UpdateContext(error); } if (pdu is KerberosAsResponse) { KerberosAsResponse response = (KerberosAsResponse)pdu; UpdateContext(response); } if (pdu is KerberosTgsRequest) { KerberosTgsRequest request = pdu as KerberosTgsRequest; UpdateContext(request); } if (pdu is KerberosTgsResponse) { KerberosTgsResponse response = pdu as KerberosTgsResponse; UpdateContext(response); } if (pdu is KerberosApRequest) { KerberosApRequest request = pdu as KerberosApRequest; UpdateContext(request); } if (pdu is KerberosApResponse) { KerberosApResponse response = pdu as KerberosApResponse; UpdateContext(response); } this.expectedPduType = null; }
private void UpdateContext(KerberosApRequest request) { this.Context.Time = request.Authenticator.ctime; this.Context.Cusec = request.Authenticator.cusec; if (request.Authenticator.cksum != null) { int flag = BitConverter.ToInt32(request.Authenticator.cksum.checksum.ByteArrayValue, KerberosConstValue.AUTHENTICATOR_CHECKSUM_LENGTH + sizeof(ChecksumFlags)); this.Context.ChecksumFlag = (ChecksumFlags)flag; } this.Context.ApSubKey = request.Authenticator.subkey; if (request.Authenticator.seq_number != null) { this.Context.currentLocalSequenceNumber = (uint)request.Authenticator.seq_number.Value; this.Context.CurrentRemoteSequenceNumber = this.Context.currentLocalSequenceNumber; } }
public KpasswordRequest() : base() { ap_req = new KerberosApRequest(); krb_priv = new KRB_PRIV(); }
private KerberosApRequest CreateApRequest(APOptions option, KerberosTicket ticket, EncryptionKey subkey, AuthorizationData data, KeyUsageNumber keyUsageNumber, ChecksumType checksumType, byte[] checksumBody) { Authenticator authenticator = CreateAuthenticator(ticket, data, subkey, checksumType, checksumBody); KerberosApRequest apReq = new KerberosApRequest(Context.Pvno, option, ticket, authenticator, keyUsageNumber); return apReq; }
/// <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 AP request and encode to GSSAPI token /// </summary> /// <param name="apOptions">AP options</param> /// <param name="data">Authorization data</param> /// <param name="subkey">Sub-session key in authenticator</param> /// <param name="checksumFlags">Checksum flags</param> /// <returns></returns> public byte[] CreateGssApiToken(ApOptions apOptions, AuthorizationData data, EncryptionKey subkey, ChecksumFlags checksumFlags, Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.KerberosConstValue.GSSToken gssToken = KerberosConstValue.GSSToken.GSSSPNG) { APOptions options = new APOptions(KerberosUtility.ConvertInt2Flags((int)apOptions)); Authenticator authenticator = CreateAuthenticator(Context.Ticket, data, subkey, checksumFlags); KerberosApRequest request = new KerberosApRequest( Context.Pvno, options, Context.Ticket, authenticator, KeyUsageNumber.AP_REQ_Authenticator ); return KerberosUtility.AddGssApiTokenHeader(request, this.oidPkt, gssToken); }
public PaFxFastReq CreateAsPaFxFast( EncryptionKey subKey, FastOptions fastOptions, ApOptions apOptions, Asn1SequenceOf<PA_DATA> seqPaData, string sName, KDC_REQ_BODY kdcReqBody, KrbFastArmorType armorType ) { string domain = this.Context.Realm.Value; PrincipalName sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST), KerberosUtility.String2SeqKerbString(sName, domain)); var armorKey = KerberosUtility.MakeArmorKey( Context.SelectedEType, subKey.keyvalue.ByteArrayValue, Context.ArmorSessionKey.keyvalue.ByteArrayValue); Context.FastArmorkey = new EncryptionKey(new KerbInt32((long)Context.SelectedEType), new Asn1OctetString(armorKey)); Asn1BerEncodingBuffer encodebuf = new Asn1BerEncodingBuffer(); kdcReqBody.BerEncode(encodebuf); var checksumType = KerberosUtility.GetChecksumType(Context.SelectedEType); var chksum = KerberosUtility.GetChecksum( armorKey, encodebuf.Data, (int)KeyUsageNumber.FAST_REQ_CHECKSUM, checksumType); Checksum checkSum = new Checksum(new KerbInt32((int)checksumType), new Asn1OctetString(chksum)); Authenticator plaintextAuthenticator = CreateAuthenticator(Context.ArmorTicket, null, subKey); KerberosApRequest apReq = new KerberosApRequest(Context.Pvno, new APOptions(KerberosUtility.ConvertInt2Flags((int)apOptions)), Context.ArmorTicket, plaintextAuthenticator, KeyUsageNumber.AP_REQ_Authenticator); KDC_REQ_BODY innerKdcReqBody = CreateKdcRequestBody(KdcOptions.CANONICALIZE | KdcOptions.FORWARDABLE | KdcOptions.RENEWABLE, sname); KerberosFastRequest fastReq = new KerberosFastRequest(fastOptions, seqPaData, innerKdcReqBody); FastArmorApRequest fastArmor = new FastArmorApRequest(apReq.Request); fastArmor.armorType = armorType; KerberosArmoredRequest armoredReq = new KerberosArmoredRequest(fastArmor, checkSum, (long)Context.SelectedEType, armorKey, fastReq); PA_FX_FAST_REQUEST paFxFastReq = new PA_FX_FAST_REQUEST(); paFxFastReq.SetData(PA_FX_FAST_REQUEST.armored_data, armoredReq.FastArmoredReq); PaFxFastReq paFxfast = new PaFxFastReq(paFxFastReq); return paFxfast; }
private void Smb2KerberosAuthentication(CaseVariant variant) { 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); #region Service Ticket EncryptionKey serviceKey; EncTicketPart encTicketPart = RetrieveAndDecryptServiceTicket(kerberosClient, out serviceKey); Ticket serviceTicket = kerberosClient.Context.Ticket.Ticket; Realm crealm = serviceTicket.realm; BaseTestSite.Assert.AreEqual(TestConfig.DomainName.ToLower(), encTicketPart.crealm.Value.ToLower(), "Realm name in service ticket encrypted part should match as expected, case insensitive"); BaseTestSite.Assert.AreEqual(TestConfig.UserName.ToLower(), KerberosUtility.PrincipalName2String(encTicketPart.cname).ToLower(), "User name in service ticket encrypted part should match as expected, case insensitive."); if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_TKT)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Add a type-unknown AuthorizationData to the ticket"); AuthorizationDataElement unknownElement = GenerateUnKnownAuthorizationDataElement(); AppendNewAuthDataElement(encTicketPart.authorization_data, unknownElement); } if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_TKT_OPTIONAL)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Add a type-unknown AuthorizationData which is inside AD_IF_RELEVANT to the ticket"); AuthorizationDataElement unknownElement = GenerateUnKnownAuthorizationDataElement(); AD_IF_RELEVANT ifRelavantElement = new AD_IF_RELEVANT(new[] { unknownElement }); var dataBuffer = new Asn1BerEncodingBuffer(); ifRelavantElement.BerEncode(dataBuffer); AuthorizationDataElement unknownElementOptional = new AuthorizationDataElement(new KerbInt32((long)AuthorizationData_elementType.AD_IF_RELEVANT), new Asn1OctetString(dataBuffer.Data)); AppendNewAuthDataElement(encTicketPart.authorization_data, unknownElementOptional); } if (variant.HasFlag(CaseVariant.TICKET_NOT_VALID)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the Ticket start time to tomorrow"); DateTime tomorrow = DateTime.Now.AddDays(1); string kerbTimeString = tomorrow.ToUniversalTime().ToString("yyyyMMddhhmmssZ"); encTicketPart.starttime = new KerberosTime(kerbTimeString, true); } if (variant.HasFlag(CaseVariant.TICKET_EXPIRED)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the Ticket end time to yesterday"); DateTime yesterday = DateTime.Now.AddDays(-1); string kerbTimeString = yesterday.ToUniversalTime().ToString("yyyyMMddhhmmssZ"); encTicketPart.endtime = new KerberosTime(kerbTimeString, true); } if (variant.HasFlag(CaseVariant.TICKET_WRONG_ENC_KEY)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Modify the Ticket, making it encrypted with wrong key"); serviceKey = KerberosUtility.GenerateKey(serviceKey); } EncryptedData data = EncryptTicket(encTicketPart, serviceKey); serviceTicket.enc_part = data; if (variant.HasFlag(CaseVariant.TICKET_WRONG_REALM)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the Realm in the Ticket to an unknown realm"); serviceTicket.realm = new Realm("kerb.com"); } if (variant.HasFlag(CaseVariant.TICKET_WRONG_SNAME)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the SNAME in the Ticket to an unknown service name"); serviceTicket.sname = new PrincipalName(new KerbInt32((long)PrincipalType.NT_SRV_INST), KerberosUtility.String2SeqKerbString("UnknownService", TestConfig.DomainName)); } if (variant.HasFlag(CaseVariant.TICKET_WRONG_KVNO)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the KVNO in the Ticket to an invalid Key Version Number (Int32.MaxValue)"); const int invalidKvno = System.Int32.MaxValue; serviceTicket.enc_part.kvno = new KerbInt32(invalidKvno); } #endregion #region Authenticator BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create Authenticator"); EncryptionKey subkey = KerberosUtility.GenerateKey(kerberosClient.Context.SessionKey); PrincipalName cname; if (variant.HasFlag(CaseVariant.AUTHENTICATOR_CNAME_NOT_MATCH)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Use wrong cname in the Authenticator"); cname = new PrincipalName(new KerbInt32((long)PrincipalType.NT_PRINCIPAL), KerberosUtility.String2SeqKerbString(TestConfig.NonAdminUserName, TestConfig.DomainName)); } else { cname = kerberosClient.Context.CName.Name; } Authenticator authenticator = CreateAuthenticator(cname, crealm, subkey); if (variant.HasFlag(CaseVariant.AUTHENTICATOR_CREALM_NOT_MATCH)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Use wrong crealm in the Authenticator"); authenticator.crealm = new Realm("kerb.com"); } if (variant.HasFlag(CaseVariant.AUTHENTICATOR_EXCEED_TIME_SKEW)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the ctime in the Authenticator to one hour later"); DateTime oneHourLater = DateTime.Now.AddHours(1); string kerbTimeString = oneHourLater.ToUniversalTime().ToString("yyyyMMddhhmmssZ"); authenticator.ctime = new KerberosTime(kerbTimeString, true); } if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_AUTHENTICATOR)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Add a type-unknown AuthorizationData to the Authenticator"); AuthorizationDataElement unknownElement = GenerateUnKnownAuthorizationDataElement(); authenticator.authorization_data = new AuthorizationData(new[] { unknownElement }); } if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_AUTHENTICATOR_OPTIONAL)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Add a type-unknown AuthorizationData which is inside AD_IF_RELEVANT to the Authenticator"); AuthorizationDataElement unknownElement = GenerateUnKnownAuthorizationDataElement(); AD_IF_RELEVANT ifRelavantElement = new AD_IF_RELEVANT(new[] { unknownElement }); var dataBuffer = new Asn1BerEncodingBuffer(); ifRelavantElement.BerEncode(dataBuffer); AuthorizationDataElement unknownElementOptional = new AuthorizationDataElement(new KerbInt32((long)AuthorizationData_elementType.AD_IF_RELEVANT), new Asn1OctetString(dataBuffer.Data)); authenticator.authorization_data = new AuthorizationData(new[] { unknownElementOptional }); } #endregion #region AP Request BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create AP Request"); if (variant.HasFlag(CaseVariant.AUTHENTICATOR_WRONG_ENC_KEY)) { BaseTestSite.Log.Add(LogEntryKind.TestStep, "Use wrong key to encrypt the Authenticator"); kerberosClient.Context.Ticket.SessionKey = KerberosUtility.GenerateKey(kerberosClient.Context.Ticket.SessionKey); } KerberosApRequest request = new KerberosApRequest( kerberosClient.Context.Pvno, new APOptions(KerberosUtility.ConvertInt2Flags((int)ApOptions.MutualRequired)), kerberosClient.Context.Ticket, authenticator, KeyUsageNumber.AP_REQ_Authenticator ); #endregion 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); #region Check the result byte[] repToken; uint status = DoSessionSetupWithGssToken(smb2Client, token, out repToken); if (variant.HasFlag(CaseVariant.AUTHENTICATOR_CNAME_NOT_MATCH) || variant.HasFlag(CaseVariant.AUTHENTICATOR_CREALM_NOT_MATCH)) { BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status, "Session Setup should fail because the cname or crealm in the authenticator does not match the same field in the Ticket"); if (TestConfig.IsWindowsPlatform) { KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken); BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_BADMATCH, krbError.ErrorCode, "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_BADMATCH); } smb2Client.Disconnect(); return; } if (variant.HasFlag(CaseVariant.AUTHENTICATOR_WRONG_ENC_KEY) || variant.HasFlag(CaseVariant.TICKET_WRONG_ENC_KEY)) { BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status, "Session Setup should fail because Ticket or Authenticator cannot be correctly decrypted"); if (TestConfig.IsWindowsPlatform) { KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken); BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_MODIFIED, krbError.ErrorCode, "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_MODIFIED); } smb2Client.Disconnect(); return; } if (variant.HasFlag(CaseVariant.AUTHENTICATOR_EXCEED_TIME_SKEW)) { BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status, "Session Setup should fail because the server time and the client time " + "in the Authenticator differ by (1 hour) more than the allowable clock skew"); if (TestConfig.IsWindowsPlatform) { KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken); BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_SKEW, krbError.ErrorCode, "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_SKEW); } smb2Client.Disconnect(); return; } if (variant.HasFlag(CaseVariant.TICKET_WRONG_KVNO) || variant.HasFlag(CaseVariant.TICKET_WRONG_REALM) || variant.HasFlag(CaseVariant.TICKET_WRONG_SNAME)) { BaseTestSite.Log.Add(LogEntryKind.Comment, "If decryption fails, server would try other keys"); } if (variant.HasFlag(CaseVariant.TICKET_NOT_VALID)) { BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status, "Session Setup should fail because the starttime (tomorrow) in the Ticket " + "is later than the current time by more than the allowable clock skew"); if (TestConfig.IsWindowsPlatform) { KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken); BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_TKT_NYV, krbError.ErrorCode, "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_TKT_NYV); } smb2Client.Disconnect(); return; } if (variant.HasFlag(CaseVariant.TICKET_EXPIRED)) { BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status, "Session Setup should fail because the current time is later than the endtime (yesterday)" + " in the Ticket by more than the allowable clock skew"); if (TestConfig.IsWindowsPlatform) { KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken); BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_TKT_EXPIRED, krbError.ErrorCode, "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_TKT_EXPIRED); } smb2Client.Disconnect(); return; } if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_TKT)) { BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status, "Session Setup should fail because of the unknown AutherizationData in the ticket"); smb2Client.Disconnect(); return; } if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_AUTHENTICATOR)) { BaseTestSite.Log.Add(LogEntryKind.Comment, "Unknown AuthorizationData in the Authenticator should not fail the request"); } if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_TKT_OPTIONAL) || variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_AUTHENTICATOR_OPTIONAL)) { BaseTestSite.Log.Add(LogEntryKind.Comment, "Unknown AuthorizationData in AD_IF_RELEVANT is optional. " + "Server should not fail the request."); } 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); string path = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare); AccessFile(smb2Client, path); #endregion smb2Client.LogOff(); smb2Client.Disconnect(); }
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(); }