/// <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 KerberosAsRequest CreateAsRequest(KDC_REQ_BODY kdcReqBody, Asn1SequenceOf <PA_DATA> paDatas, long pvno = KerberosConstValue.KERBEROSV5) { KerberosAsRequest request = new KerberosAsRequest( pvno, kdcReqBody, paDatas, Context.TransportType); return(request); }
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); }
private void UpdateContext(KerberosAsRequest request) { if (request.Request != null && request.Request.req_body != null) { Context.Addresses = request.Request.req_body.addresses; Context.Nonce = request.Request.req_body.nonce; } if (request.Request.padata != null) { var padataList = request.Request.padata.Elements; foreach (var padata in padataList) { var parsed = PaDataParser.ParseReqPaData(padata); if (parsed is PaFxFastReq) { Context.ReplyKey = Context.FastArmorkey; } } } }
/// <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; } }
//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); }
private KerberosAsRequest CreateAsRequest(KDC_REQ_BODY kdcReqBody, Asn1SequenceOf<PA_DATA> paDatas, long pvno = KerberosConstValue.KERBEROSV5) { KerberosAsRequest request = new KerberosAsRequest( pvno, kdcReqBody, paDatas, Context.TransportType); return 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; }