/// <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); } this.expectedPduType = null; }
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 void UpdateContext(KerberosTgsRequest request) { Context.Nonce = request.Request.req_body.nonce; if (Context.Subkey == null) { Context.ReplyKey = Context.SessionKey; } else { Context.ReplyKey = Context.Subkey; } }
//Get the expected Kerberos PDU from byte array private KerberosPdu getExpectedPduFromBytes( byte[] receivedBytes, out int consumedLength, out int expectedLength) { // initialize lengths consumedLength = 0; expectedLength = 0; if (null == receivedBytes || 0 == receivedBytes.Length) { return(null); } // TCP has a 4 bytes length header, while UDP has not byte[] pduBytes = receivedBytes; if ((this.Context.TransportType == TransportType.TCP)) { // insufficient data, needs to receive more if (receivedBytes.Length < sizeof(int)) { return(null); } // get pdu data length byte[] lengthBytes = ArrayUtility.SubArray(receivedBytes, 0, sizeof(int)); Array.Reverse(lengthBytes); int pduLength = BitConverter.ToInt32(lengthBytes, 0); // insufficient data, needs to receive more expectedLength = sizeof(int) + pduLength; if (receivedBytes.Length < expectedLength) { return(null); } // remove length header from pdu bytes pduBytes = ArrayUtility.SubArray <byte>(receivedBytes, sizeof(int), pduLength); } else { // UDP has no length header expectedLength = pduBytes.Length; } // decode according to message type consumedLength = expectedLength; // get message type // (the lower 5 bits indicates its kile message type) MsgType kileMessageType = (MsgType)(pduBytes[0] & 0x1f); KerberosPdu pdu = null; switch (kileMessageType) { case MsgType.KRB_AS_REQ: pdu = new KerberosAsRequest(); break; case MsgType.KRB_AS_RESP: pdu = new KerberosAsResponse(); break; case MsgType.KRB_TGS_REQ: pdu = new KerberosTgsRequest(); break; case MsgType.KRB_TGS_RESP: pdu = new KerberosTgsResponse(); break; case MsgType.KRB_ERROR: pdu = new KerberosKrbError(); break; default: throw new FormatException( "Unsupported Message Type: " + kileMessageType.ToString()); } pdu.FromBytes(pduBytes); // update context if (this.expectedPduType == null || this.expectedPduType == pdu.GetType()) { this.UpdateContext(pdu); } return(pdu); }
/// <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."); }
//Get the expected Kerberos PDU from byte array private KerberosPdu getExpectedPduFromBytes( byte[] receivedBytes, out int consumedLength, out int expectedLength) { // initialize lengths consumedLength = 0; expectedLength = 0; if (null == receivedBytes || 0 == receivedBytes.Length) { return null; } // TCP has a 4 bytes length header, while UDP has not byte[] pduBytes = receivedBytes; if ((this.Context.TransportType == TransportType.TCP)) { // insufficient data, needs to receive more if (receivedBytes.Length < sizeof(int)) { return null; } // get pdu data length byte[] lengthBytes = ArrayUtility.SubArray(receivedBytes, 0, sizeof(int)); Array.Reverse(lengthBytes); int pduLength = BitConverter.ToInt32(lengthBytes, 0); // insufficient data, needs to receive more expectedLength = sizeof(int) + pduLength; if (receivedBytes.Length < expectedLength) { return null; } // remove length header from pdu bytes pduBytes = ArrayUtility.SubArray<byte>(receivedBytes, sizeof(int), pduLength); } else { // UDP has no length header expectedLength = pduBytes.Length; } // decode according to message type consumedLength = expectedLength; // get message type // (the lower 5 bits indicates its kile message type) MsgType kileMessageType = (MsgType)(pduBytes[0] & 0x1f); KerberosPdu pdu = null; switch (kileMessageType) { case MsgType.KRB_AS_REQ: pdu = new KerberosAsRequest(); break; case MsgType.KRB_AS_RESP: pdu = new KerberosAsResponse(); break; case MsgType.KRB_TGS_REQ: pdu = new KerberosTgsRequest(); break; case MsgType.KRB_TGS_RESP: pdu = new KerberosTgsResponse(); break; case MsgType.KRB_ERROR: pdu = new KerberosKrbError(); break; default: throw new FormatException( "Unsupported Message Type: " + kileMessageType.ToString()); } pdu.FromBytes(pduBytes); // update context if (this.expectedPduType == null || this.expectedPduType == pdu.GetType()) this.UpdateContext(pdu); return pdu; }