コード例 #1
0
        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));
        }
コード例 #2
0
        /// <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);
        }
コード例 #3
0
        /// <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);
        }
コード例 #4
0
        /// <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);
        }
コード例 #5
0
        /// <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);
        }
コード例 #6
0
        /// <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);
        }
コード例 #7
0
        /// <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);
        }
コード例 #8
0
        /// <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);
        }
コード例 #9
0
        /// <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);
        }
コード例 #10
0
        /// <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;
        }
コード例 #11
0
        /// <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;
        }
コード例 #12
0
        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);
        }
コード例 #13
0
        /// <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);
        }
コード例 #14
0
        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);
        }
コード例 #15
0
        /// <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);
                }
            }
        }