public static void UpdateAuthDataInTicket(Ticket ticket, byte[] key, AuthorizationData authorizationData) { EncryptionType encryptType = (EncryptionType)ticket.enc_part.etype.Value; byte[] clearText = KileUtility.Decrypt( encryptType, key, ticket.enc_part.cipher.ByteArrayValue, (int)KeyUsageNumber.AS_REP_TicketAndTGS_REP_Ticket); // Decode the ticket. Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(clearText); EncTicketPart encTicketPart = new EncTicketPart(); encTicketPart.BerDecode(decodeBuffer); // Set with new authorization data encTicketPart.authorization_data = authorizationData; Asn1BerEncodingBuffer ticketBerBuffer = new Asn1BerEncodingBuffer(); encTicketPart.BerEncode(ticketBerBuffer, true); byte[] cipherData = KileUtility.Encrypt( encryptType, key, ticketBerBuffer.Data, (int)KeyUsageNumber.AS_REP_TicketAndTGS_REP_Ticket); ticket.enc_part = new EncryptedData(new KerbInt32((int)encryptType), null, new Asn1OctetString(cipherData)); }
/// <summary> /// Decode Kpassword Response from bytes /// </summary> /// <param name="buffer">the byte array to be decoded</param> /// <exception cref="System.ArgumentNullException">thrown when input buffer is null</exception> public override void FromBytes(byte[] buffer) { if (null == buffer) { throw new ArgumentNullException("buffer"); } //Calculate the length of the message and the length of AP response data byte[] msgLengthBytes = ArrayUtility.SubArray <byte>(buffer, 0, sizeof(ushort)); Array.Reverse(msgLengthBytes); ushort msgLength = BitConverter.ToUInt16(msgLengthBytes, 0); byte[] apLengthBytes = ArrayUtility.SubArray <byte>(buffer, 2 * sizeof(ushort), sizeof(ushort)); Array.Reverse(apLengthBytes); ushort apLength = BitConverter.ToUInt16(apLengthBytes, 0); //Decode the ap response and the krb-priv message byte[] apBytes = ArrayUtility.SubArray <byte>(buffer, 3 * sizeof(ushort), apLength); Asn1DecodingBuffer apBuffer = new Asn1DecodingBuffer(apBytes); this.ap_rep.Response.BerDecode(apBuffer); byte[] privBytes = ArrayUtility.SubArray <byte>(buffer, 3 * sizeof(ushort) + apLength); Asn1DecodingBuffer privBuffer = new Asn1DecodingBuffer(privBytes); this.krb_priv.BerDecode(privBuffer); }
/// <summary> /// Decode a byte array to a designated Asn.1 type /// </summary> /// <typeparam name="T">designated Asn.1 type</typeparam> /// <param name="rawData">byte array to be decoded</param> /// <returns>the decoded Asn.1 type</returns> public static T DecodeAsn1 <T>(byte[] rawData) where T : Asn1Object, new() { T asn1Type = new T(); Asn1DecodingBuffer buffer = new Asn1DecodingBuffer(rawData); asn1Type.BerDecode(buffer); return(asn1Type); }
/// <summary> /// Decode AS Request from bytes /// </summary> /// <param name="buffer">the byte array to be decoded</param> /// <exception cref="System.ArgumentNullException">thrown when input buffer is null</exception> public override void FromBytes(byte[] buffer) { if (buffer == null) { throw new ArgumentNullException("buffer"); } Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(buffer); Request.BerDecode(decodeBuffer); }
/// <summary> /// Decode GSSAPI token to AP-REP /// </summary> /// <param name="token">GSSAPI token</param> /// <returns></returns> private KerberosApResponse GetApResponseFromToken(byte[] token, KerberosConstValue.GSSToken gssToken = KerberosConstValue.GSSToken.GSSSPNG) { if (gssToken == KerberosConstValue.GSSToken.GSSSPNG) { token = KerberosUtility.DecodeNegotiationToken(token); } if (token[0] == KerberosConstValue.KERBEROS_TAG) { byte[] apData = KerberosUtility.VerifyGssApiTokenHeader(token, this.client.OidPkt); // Check if it has a two-byte tok_id if (null == apData || apData.Length <= sizeof(TOK_ID)) { throw new FormatException( "Data length is shorter than a valid AP Response data length."); } // verify TOK_ID byte[] tokenID = ArrayUtility.SubArray <byte>(apData, 0, sizeof(TOK_ID)); Array.Reverse(tokenID); TOK_ID id = (TOK_ID)BitConverter.ToUInt16(tokenID, 0); if (!id.Equals(TOK_ID.KRB_AP_REP)) { throw new Exception("ApResponse Token ID should be KRB_AP_REP"); } // Get apBody token = ArrayUtility.SubArray(apData, sizeof(TOK_ID)); } KerberosApResponse apRep = new KerberosApResponse(); apRep.FromBytes(token); // Get the current encryption type, cipher data EncryptionType encryptType = (EncryptionType)apRep.Response.enc_part.etype.Value; byte[] cipherData = apRep.Response.enc_part.cipher.ByteArrayValue; byte[] sessionKey = this.Context.ApSessionKey.keyvalue.ByteArrayValue; // decrypt enc_part to clear text byte[] clearText = KerberosUtility.Decrypt(encryptType, sessionKey, cipherData, (int)KeyUsageNumber.AP_REP_EncAPRepPart); // decode enc_part Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(clearText); apRep.ApEncPart = new EncAPRepPart(); apRep.ApEncPart.BerDecode(decodeBuffer); this.client.UpdateContext(apRep); return(apRep); }
/// <summary> /// Decode KDCProxyMessage from bytes /// </summary> /// <param name="buffer">byte array to be decoded</param> /// <exception cref="System.ArgumentNullException">thrown when input buffer is null</exception> public void FromBytes(byte[] buffer) { if (null == buffer) { throw new ArgumentNullException("buffer"); } this.Message = new KDC_PROXY_MESSAGE(); Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(buffer); this.Message.BerDecode(decodeBuffer); }
/// <summary> /// Decrypt the KRB-PRIV /// </summary> /// <param name="subkey">the subkey used to decrypt</param> public void DecryptKrbPriv(EncryptionKey subkey) { byte[] priv = KerberosUtility.Decrypt( (EncryptionType)subkey.keytype.Value, subkey.keyvalue.ByteArrayValue, krb_priv.enc_part.cipher.ByteArrayValue, (int)KeyUsageNumber.KRB_PRIV_EncPart); Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(priv); priv_enc_part.BerDecode(decodeBuffer); }
/// <summary> /// Decode TGS Response from bytes /// </summary> /// <param name="buffer">byte array to be decoded</param> /// <exception cref="System.ArgumentNullException">thrown when input buffer is null</exception> public override void FromBytes(byte[] buffer) { if (null == buffer) { throw new ArgumentNullException("buffer"); } KerberosUtility.OnDumpMessage("KRB5:KrbMessage", "Kerberos Message", KerberosUtility.DumpLevel.WholeMessage, buffer); // Decode TGS Response Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(buffer); Response.BerDecode(decodeBuffer); }
/// <summary> /// Decodes an LDAP v3 packet. /// </summary> /// <param name="messageBytes">The message bytes that contains the packet data.</param> /// <param name="context">The context that contains decode-related information.</param> /// <returns>Decoded LDAP v3 packet.</returns> internal override AdtsLdapPacket ParseAdtsLdapPacket(byte[] messageBytes, AdtsLdapContext context) { LDAPMessage message = new LDAPMessage(); Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(messageBytes); message.BerDecode(decodeBuffer); Type innerMessageType = message.protocolOp.GetData().GetType(); AdtsLdapPacket packet = CreatePacketFromType(innerMessageType); context.MessageId = (long)message.messageID.Value; packet.messageId = (long)message.messageID.Value; packet.ldapMessagev3 = message; return(packet); }
/// <summary> /// Decode the Krb Error from bytes /// </summary> /// <param name="buffer">The byte array to be decoded.</param> /// <exception cref="System.ArgumentNullException">thrown when input buffer is null</exception> public override void FromBytes(byte[] buffer) { if (null == buffer) { throw new ArgumentNullException("buffer"); } KerberosUtility.OnDumpMessage("KRB5:KrbMessage", "Kerberos Message", KerberosUtility.DumpLevel.WholeMessage, buffer); // Decode Krb Error Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(buffer); this.KrbError.BerDecode(decodeBuffer); ErrorCode = (KRB_ERROR_CODE)KrbError.error_code.Value; }
/// <summary> /// Decode AS Response from bytes /// </summary> /// <param name="buffer">the byte array to be decoded</param> /// <exception cref="System.ArgumentNullException">thrown when input buffer is null</exception> public override void FromBytes(byte[] buffer) { if (null == buffer) { throw new ArgumentNullException("buffer"); } KerberosUtility.OnDumpMessage("KRB5:KrbMessage", "Kerberos Message", KerberosUtility.DumpLevel.WholeMessage, buffer); // Decode AS Response Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(buffer); this.Response.BerDecode(decodeBuffer); // Get the current encryption type, cipher data, session key EncryptionType encryptType = (EncryptionType)this.Response.enc_part.etype.Value; }
public static AuthorizationData GetAuthDataInTicket(Ticket ticket, byte[] key) { EncryptionType encryptType = (EncryptionType)ticket.enc_part.etype.Value; byte[] clearText = KileUtility.Decrypt( encryptType, key, ticket.enc_part.cipher.ByteArrayValue, (int)KeyUsageNumber.AS_REP_TicketAndTGS_REP_Ticket); // Decode the ticket. Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(clearText); EncTicketPart encTicketPart = new EncTicketPart(); encTicketPart.BerDecode(decodeBuffer); return(encTicketPart.authorization_data); }
/// <summary> /// Expected a KDC_ERR_PREAUTH_REQUIRED error /// </summary> /// <param name="eData">Error data of this error</param> /// <returns></returns> private KerberosKrbError ExpectPreauthRequiredError(out METHOD_DATA eData) { KerberosPdu responsePdu = this.client.ExpectPdu(KerberosConstValue.TIMEOUT_DEFAULT, typeof(KerberosKrbError)); if ((responsePdu == null) || (!(responsePdu is KerberosKrbError))) { throw new InvalidOperationException("Response type should be KerberosKrbError"); } KerberosKrbError krbError = responsePdu as KerberosKrbError; if (!krbError.ErrorCode.Equals(KRB_ERROR_CODE.KDC_ERR_PREAUTH_REQUIRED)) { throw new InvalidOperationException("The Error code should be KDC_ERR_PREAUTH_REQUIRED"); } eData = new METHOD_DATA(); Asn1DecodingBuffer buffer = new Asn1DecodingBuffer(krbError.KrbError.e_data.ByteArrayValue); eData.BerDecode(buffer); return(krbError); }
private void DecryptAsResponse(byte[] key) { var encryptType = (EncryptionType)Response.enc_part.etype.Value; int keyUsage = (int)KeyUsageNumber.AS_REP_ENCRYPTEDPART; if (encryptType == EncryptionType.RC4_HMAC) { keyUsage = (int)KeyUsageNumber.TGS_REP_encrypted_part; } var encPartRawData = KerberosUtility.Decrypt( encryptType, key, Response.enc_part.cipher.ByteArrayValue, keyUsage); Asn1DecodingBuffer buf = new Asn1DecodingBuffer(encPartRawData); Asn1Tag tag = null; Asn1StandardProcedure.TagBerDecode(buf, out tag); //Some implementations unconditionally send an encrypted EncTGSRepPart in the field //regardless of whether the reply is an AS-REP or a TGS-REP.([RFC4120] Section 5.4.2) if (tag.TagValue == 25) //EncAsRepPart { EncPart = new EncASRepPart(); } else if (tag.TagValue == 26) //EncTgsRepPart { EncPart = new EncTGSRepPart(); } else { throw new Exception("Unknown tag number"); } EncPart.BerDecode(new Asn1DecodingBuffer(encPartRawData)); KerberosUtility.OnDumpMessage("KRB5:AS-REP(enc-part)", "Encrypted part of AS-REP", KerberosUtility.DumpLevel.PartialMessage, encPartRawData); }
/// <summary> /// Update the context. /// </summary> /// <param name="pdu">The PDU to update the context.</param> internal override void UpdateContext(KilePdu pdu) { if (pdu == null) { return; } lock (contextLock) { Type pduType = pdu.GetType(); if (pduType == typeof(KileAsRequest)) { KileAsRequest request = (KileAsRequest)pdu; if (request.Request != null && request.Request.req_body != null) { cName = request.Request.req_body.cname; cRealm = request.Request.req_body.realm; eType = request.Request.req_body.etype; } } else if (pduType == typeof(KileAsResponse)) { KileAsResponse response = (KileAsResponse)pdu; if (response.EncPart != null) { tgsSessionKey = response.EncPart.key; } if (response.Response != null) { tgsTicket = response.Response.ticket; if (tgsTicket != null && tgsTicket.sname != null && tgsTicket.sname.name_string != null && tgsTicket.sname.name_string.Elements != null && tgsTicket.sname.name_string.Elements.Length > 1) { int count = tgsTicket.sname.name_string.Elements.Length; cRealm = new Realm(tgsTicket.sname.name_string.Elements[count - 1].Value); } if (response.Response.padata != null && response.Response.padata.Elements != null) { foreach (PA_DATA paData in response.Response.padata.Elements) { if (paData.padata_type != null && paData.padata_type.Value == (long)PaDataType.PA_ETYPE_INFO2) { Asn1DecodingBuffer buffer = new Asn1DecodingBuffer(paData.padata_value.ByteArrayValue); ETYPE_INFO2 eTypeInfo2 = new ETYPE_INFO2(); eTypeInfo2.BerDecode(buffer); if (eTypeInfo2.Elements != null && eTypeInfo2.Elements.Length > 0) { // the salt is received from KDC salt = eTypeInfo2.Elements[0].salt.Value; return; } } } } } } else if (pduType == typeof(KileTgsResponse)) { KileTgsResponse response = (KileTgsResponse)pdu; if (response.Response != null) { apTicket = response.Response.ticket; if (apTicket != null && apTicket.sname != null && apTicket.sname.name_string != null && apTicket.sname.name_string.Elements != null && apTicket.sname.name_string.Elements.Length > 1) { int count = apTicket.sname.name_string.Elements.Length; cRealm = new Realm(apTicket.sname.name_string.Elements[count - 1].Value); } } if (response.EncPart != null) { apSessionKey = response.EncPart.key; } } else if (pduType == typeof(KileApRequest)) { KileApRequest request = (KileApRequest)pdu; if (request.Authenticator != null) { apSubKey = request.Authenticator.subkey; apRequestCtime = request.Authenticator.ctime; apRequestCusec = request.Authenticator.cusec; if (request.Authenticator.cksum != null && request.Authenticator.cksum.cksumtype.Value == (int)ChecksumType.ap_authenticator_8003 && request.Authenticator.cksum.checksum != null && request.Authenticator.cksum.checksum.Value != null && request.Authenticator.cksum.checksum.Value.Length == ConstValue.AUTH_CHECKSUM_SIZE) { int flag = BitConverter.ToInt32(request.Authenticator.cksum.checksum.ByteArrayValue, ConstValue.AUTHENTICATOR_CHECKSUM_LENGTH + sizeof(int)); checksumFlag = (ChecksumFlags)flag; } if (request.Authenticator.seq_number != null) { currentLocalSequenceNumber = (ulong)request.Authenticator.seq_number.Value; currentRemoteSequenceNumber = currentLocalSequenceNumber; } } } else if (pduType == typeof(KileApResponse)) { KileApResponse response = (KileApResponse)pdu; if (response.ApEncPart != null) { if (response.ApEncPart.seq_number != null) { currentRemoteSequenceNumber = (ulong)response.ApEncPart.seq_number.Value; } if (response.ApEncPart.subkey != null) { acceptorSubKey = response.ApEncPart.subkey; } } } // else do nothing } }
private void UpdateContext(KerberosAsResponse response) { KerberosFastResponse kerbFastRep = null; if (response.Response.padata != null && response.Response.padata.Elements != null) { foreach (PA_DATA paData in response.Response.padata.Elements) { var parsedPaData = PaDataParser.ParseRepPaData(paData); if (parsedPaData is PaETypeInfo2) { Asn1DecodingBuffer buffer = new Asn1DecodingBuffer(paData.padata_value.ByteArrayValue); ETYPE_INFO2 eTypeInfo2 = new ETYPE_INFO2(); eTypeInfo2.BerDecode(buffer); if (eTypeInfo2.Elements != null && eTypeInfo2.Elements.Length > 0) { // the salt is received from KDC if (eTypeInfo2.Elements[0].salt != null) { Context.CName.Salt = eTypeInfo2.Elements[0].salt.Value; } continue; } } if (parsedPaData is PaFxFastRep) { var armoredRep = ((PaFxFastRep)parsedPaData).GetArmoredRep(); kerbFastRep = ((PaFxFastRep)parsedPaData).GetKerberosFastRep(Context.FastArmorkey); var strKey = kerbFastRep.FastResponse.strengthen_key; Context.ReplyKey = KerberosUtility.KrbFxCf2( strKey, //Fix me: should be Context.ReplyKey KerberosUtility.MakeKey(Context.SelectedEType, Context.CName.Password, Context.CName.Salt), "strengthenkey", "replykey"); } } } if (Context.ReplyKey != null) { response.Decrypt(Context.ReplyKey.keyvalue.ByteArrayValue); } else { var encryptType = (EncryptionType)response.Response.enc_part.etype.Value; var key = KeyGenerator.MakeKey(encryptType, Context.CName.Password, Context.CName.Salt); Context.ReplyKey = new EncryptionKey(new KerbInt32((long)encryptType), new Asn1OctetString(key)); response.Decrypt(key); } if (response.EncPart != null) { Context.SessionKey = response.EncPart.key; } if (response.Response != null) { //Response.Response.cname is not the real CName of the ticket when hide-client-names=1 if (kerbFastRep != null && kerbFastRep.FastResponse != null && kerbFastRep.FastResponse.finished != null) { // Windows DC is case insensitive. It may change the cname in the response, e.g. administrator -> Administrator Context.CName.Name = kerbFastRep.FastResponse.finished.cname; Context.Ticket = new KerberosTicket(response.Response.ticket, kerbFastRep.FastResponse.finished.cname, response.EncPart.key); } else { // Windows DC is case insensitive. It may change the cname in the response, e.g. administrator -> Administrator Context.CName.Name = response.Response.cname; Context.Ticket = new KerberosTicket(response.Response.ticket, response.Response.cname, response.EncPart.key); } Context.SelectedEType = (EncryptionType)Context.Ticket.SessionKey.keytype.Value; if (Context.Ticket != null && Context.Ticket.Ticket.sname != null && Context.Ticket.Ticket.sname.name_string != null && Context.Ticket.Ticket.sname.name_string.Elements != null && Context.Ticket.Ticket.sname.name_string.Elements.Length > 1) { int count = Context.Ticket.Ticket.sname.name_string.Elements.Length; Context.Realm = new Realm(Context.Ticket.Ticket.sname.name_string.Elements[count - 1].Value); } } }