/// <summary>
        /// Decode the KRB_ERROR token got from application.
        /// </summary>
        /// <param name="errorToken">The token got from an application message. This argument cannot be null.</param>
        /// <returns>The decoded AP response.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input parameter is null.</exception>
        /// <exception cref="System.FormatException">Thrown when the errorToken is not valid.</exception>
        public KileKrbError ParseKrbError(byte[] errorToken)
        {
            if (errorToken == null)
            {
                throw new ArgumentNullException("errorToken");
            }

            byte[] errorBody = KileUtility.VerifyGssApiTokenHeader(errorToken);

            // Check if it has a two-byte tok_id
            if (errorBody == null || errorBody.Length <= sizeof(TOK_ID))
            {
                throw new FormatException("Not a valid KRB_ERROR token!");
            }

            TOK_ID id = (TOK_ID)KileUtility.ConvertEndian(BitConverter.ToUInt16(errorBody, 0));

            if (id != TOK_ID.KRB_ERROR)
            {
                throw new FormatException("Not a valid KRB_ERROR token!");
            }

            errorBody = ArrayUtility.SubArray(errorBody, sizeof(TOK_ID));
            KileKrbError error = new KileKrbError();

            error.FromBytes(errorBody);
            return(error);
        }
        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>
 /// Wrap a length before the buffer.
 /// </summary>
 /// <param name="buffer">The buffer to be wrapped.</param>
 /// <param name="isBigEndian">Specify if the length is Big-Endian.</param>
 /// <returns>The buffer added length.</returns>
 internal static byte[] WrapLength(byte[] buffer, bool isBigEndian)
 {
     if (isBigEndian)
     {
         return(ArrayUtility.ConcatenateArrays(
                    BitConverter.GetBytes(KileUtility.ConvertEndian((uint)buffer.Length)), buffer));
     }
     else
     {
         return(ArrayUtility.ConcatenateArrays(BitConverter.GetBytes(buffer.Length), buffer));
     }
 }
        public KileAsRequest CreateAsRequest(string sName,
                                             KRBFlags kdcOptions,
                                             Asn1SequenceOf <PA_DATA> paData,
                                             params EncryptionType[] encryptionTypes)
        {
            KileAsRequest request = new KileAsRequest(context);

            request.Request.msg_type = new Asn1Integer((int)MsgType.KRB_AS_REQ);
            request.Request.pvno     = new Asn1Integer(ConstValue.KERBEROSV5);
            request.Request.padata   = paData;

            request.Request.req_body             = new KDC_REQ_BODY();
            request.Request.req_body.kdc_options = new KDCOptions(KileUtility.ConvertInt2Flags((int)kdcOptions));
            request.Request.req_body.nonce       = new KerbUInt32((uint)Math.Abs((int)DateTime.Now.Ticks));
            request.Request.req_body.till        = new KerberosTime(ConstValue.TGT_TILL_TIME);
            request.Request.req_body.rtime       = new KerberosTime(ConstValue.TGT_RTIME);
            request.Request.req_body.addresses   =
                new HostAddresses(new HostAddress[1] {
                new HostAddress(new KerbInt32((int)AddressType.NetBios),
                                new Asn1OctetString(Encoding.ASCII.GetBytes(System.Net.Dns.GetHostName())))
            });

            if (userName != null)
            {
                request.Request.req_body.cname =
                    new PrincipalName(new KerbInt32((int)PrincipalType.NT_PRINCIPAL), KerberosUtility.String2SeqKerbString(userName));
            }

            if (domain != null)
            {
                request.Request.req_body.realm = new Realm(domain);
            }

            if (sName != null)
            {
                request.Request.req_body.sname =
                    new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST), KileUtility.String2SeqKerbString(sName, domain));
            }

            if (encryptionTypes != null)
            {
                KerbInt32[] etypes = new KerbInt32[encryptionTypes.Length];
                for (int i = 0; i < encryptionTypes.Length; i++)
                {
                    etypes[i] = new KerbInt32((int)encryptionTypes[i]);
                }

                request.Request.req_body.etype = new Asn1SequenceOf <KerbInt32>(etypes);
            }

            return(request);
        }
        public EncryptionKey GenerateKey(EncryptionKey baseKey)
        {
            if (baseKey == null || baseKey.keytype == null ||
                baseKey.keyvalue == null || baseKey.keyvalue.Value == null)
            {
                return(null);
            }

            byte[]        keyBuffer = KileUtility.GenerateRandomBytes((uint)baseKey.keyvalue.ByteArrayValue.Length);
            EncryptionKey newKey    = new EncryptionKey(new KerbInt32(baseKey.keytype.Value), new Asn1OctetString(keyBuffer));

            return(newKey);
        }
        /// <summary>
        /// Create authenticator for AP request or part of PA-DATA for TGS request.
        /// </summary>
        /// <param name="cRealm">This field contains the name of the realm in which the client is registered and in
        /// which initial authentication took place.</param>
        /// <param name="cName">This field contains the name part of the client's principal identifier.</param>
        /// <param name="checksumType">The checksum type selected.</param>
        /// <param name="seqNumber">The current local sequence number.</param>
        /// <param name="flag">The flag set in checksum field of Authenticator.</param>
        /// <param name="subkey">Specify the new subkey used in the following exchange. This field is optional.
        /// This argument can be got with method GenerateKey(ApSessionKey).
        /// This argument can be null. If this argument is null, no subkey will be sent.</param>
        /// <param name="authorizationData">The authentication data of authenticator. This field is optional.
        /// This argument can be generated by method ConstructAuthorizationData. This argument can be null.
        /// If this argument is null, no Authorization Data will be sent.</param>
        /// <param name="key">The key to do checksum.</param>
        /// <param name="checksumBody">The data to compute checksum.</param>
        /// <returns>The created authenticator.</returns>
        private Authenticator CreateAuthenticator(Realm cRealm,
                                                  PrincipalName cName,
                                                  ChecksumType checksumType,
                                                  int seqNumber,
                                                  ChecksumFlags flag,
                                                  EncryptionKey subkey,
                                                  AuthorizationData authorizationData,
                                                  EncryptionKey key,
                                                  byte[] checksumBody)
        {
            Authenticator plaintextAuthenticator = new Authenticator();

            plaintextAuthenticator.authenticator_vno  = new Asn1Integer(ConstValue.KERBEROSV5);
            plaintextAuthenticator.crealm             = cRealm;
            plaintextAuthenticator.cname              = cName;
            plaintextAuthenticator.cusec              = new Microseconds(0);
            plaintextAuthenticator.ctime              = KileUtility.CurrentKerberosTime;
            plaintextAuthenticator.seq_number         = new KerbUInt32(seqNumber);
            plaintextAuthenticator.subkey             = subkey;
            plaintextAuthenticator.authorization_data = authorizationData;

            if (checksumType == ChecksumType.ap_authenticator_8003)
            {
                // compute the checksum
                AuthCheckSum checksum = new AuthCheckSum();
                checksum.Lgth  = ConstValue.AUTHENTICATOR_CHECKSUM_LENGTH;
                checksum.Bnd   = new byte[checksum.Lgth];
                checksum.Flags = (int)flag;
                byte[] checkData = ArrayUtility.ConcatenateArrays(BitConverter.GetBytes(checksum.Lgth),
                                                                  checksum.Bnd,
                                                                  BitConverter.GetBytes(checksum.Flags));
                // in AP request
                plaintextAuthenticator.cksum = new Checksum(new KerbInt32((int)checksumType), new Asn1OctetString(checkData));
            }
            else
            {
                // in TGS PA data
                byte[] checkData = KileUtility.GetChecksum(
                    key.keyvalue.ByteArrayValue,
                    checksumBody,
                    (int)KeyUsageNumber.TGS_REQ_PA_TGS_REQ_adataOR_AP_REQ_Authenticator_cksum,
                    checksumType);

                plaintextAuthenticator.cksum = new Checksum(new KerbInt32((int)checksumType), new Asn1OctetString(checkData));
            }

            return(plaintextAuthenticator);
        }
        /// <summary>
        /// Construct an kerbcred EncryptedData.
        /// </summary>
        /// <param name="key">The key to do encryption.</param>
        /// <returns>The EncKrbCredPart.</returns>
        private EncKrbCredPart ConstrutCredEncryptedData(EncryptionKey key)
        {
            EncKrbCredPart encKrbCred = new EncKrbCredPart();

            encKrbCred.nonce     = new KerbUInt32((uint)Math.Abs((int)DateTime.Now.Ticks));
            encKrbCred.timestamp = new KerberosTime(KileUtility.GetCurrentUTCTime());
            encKrbCred.usec      = new Microseconds(0);
            encKrbCred.s_address = new HostAddress(new KerbInt32((int)AddressType.NetBios),
                                                   new Asn1OctetString(Dns.GetHostName()));

            KrbCredInfo[] krbCredInfo = new KrbCredInfo[1];
            krbCredInfo[0]         = new KrbCredInfo();
            krbCredInfo[0].key     = key;
            encKrbCred.ticket_info = new Asn1SequenceOf <KrbCredInfo>(krbCredInfo);

            return(encKrbCred);
        }
        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);
        }
        public KileTgsRequest CreateTgsRequest(string sName,
                                               KRBFlags kdcOptions,
                                               KerbUInt32 nonce,
                                               Asn1SequenceOf <PA_DATA> paData,
                                               ChecksumType checksumType,
                                               Ticket additionalTicket,
                                               AuthorizationData authorizationData)
        {
            if (sName == null)
            {
                throw new ArgumentNullException("sName");
            }
            PrincipalName sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST),
                                                    KileUtility.String2SeqKerbString(sName.Split('/')));

            return(CreateTgsRequest(context.UserRealm, context.UserName, sname, kdcOptions, nonce, context.UserRealm, paData,
                                    checksumType, additionalTicket, authorizationData));
        }
        /// <summary>
        /// Construct PA_TGS_REQ for TGS request.
        /// </summary>
        /// <param name="cRealm">This field contains the name of the realm in which the client is registered and in
        /// which initial authentication took place.</param>
        /// <param name="cName">This field contains the name part of the client's principal identifier.</param>
        /// <param name="checksumType">The checksum type in Authenticator.</param>
        /// <param name="checksumBody">The data to compute checksum.</param>
        /// <returns>The constructed PaData.</returns>
        private PA_DATA ConstructTgsPaData(Realm cRealm, PrincipalName cName, ChecksumType checksumType, byte[] checksumBody)
        {
            AP_REQ request = new AP_REQ();

            KerbAuthDataTokenRestrictions adRestriction =
                ConstructKerbAuthDataTokenRestrictions(0,
                                                       (uint)LSAP_TOKEN_INFO_INTEGRITY_Flags.FULL_TOKEN,
                                                       (uint)LSAP_TOKEN_INFO_INTEGRITY_TokenIL.Medium,
                                                       new Guid().ToString());
            AuthorizationData authData = ConstructAuthorizationData(adRestriction);

            // create and encrypt authenticator
            Authenticator authenticator = CreateAuthenticator(cRealm,
                                                              cName,
                                                              checksumType,
                                                              0,
                                                              0,
                                                              null,
                                                              authData,
                                                              context.TgsSessionKey,
                                                              checksumBody);
            Asn1BerEncodingBuffer asnBuffPlainAuthenticator = new Asn1BerEncodingBuffer();

            authenticator.BerEncode(asnBuffPlainAuthenticator, true);
            byte[] encAsnEncodedAuth =
                KileUtility.Encrypt((EncryptionType)context.TgsSessionKey.keytype.Value,
                                    context.TgsSessionKey.keyvalue.ByteArrayValue,
                                    asnBuffPlainAuthenticator.Data,
                                    (int)KeyUsageNumber.TG_REQ_PA_TGS_REQ_padataOR_AP_REQ_Authenticator);
            request.authenticator        = new EncryptedData();
            request.authenticator.etype  = new Microsoft.Protocols.TestTools.StackSdk.Security.KerberosLib.KerbInt32(context.TgsSessionKey.keytype.Value);
            request.authenticator.cipher = new Asn1OctetString(encAsnEncodedAuth);

            // create AP request
            request.ap_options = new APOptions(KileUtility.ConvertInt2Flags((int)ApOptions.None));
            request.msg_type   = new Asn1Integer((int)MsgType.KRB_AP_REQ);
            request.pvno       = new Asn1Integer(ConstValue.KERBEROSV5);
            request.ticket     = context.TgsTicket;
            Asn1BerEncodingBuffer apBerBuffer = new Asn1BerEncodingBuffer();

            request.BerEncode(apBerBuffer, true);

            return(new PA_DATA(new KerbInt32((int)PaDataType.PA_TGS_REQ), new Asn1OctetString(apBerBuffer.Data)));
        }
 /// <summary>
 /// Compute RC4HMAC.
 /// </summary>
 /// <param name="key">The key to do RC4HMAC.</param>
 /// <param name="macContent">The content to do HMAC.</param>
 /// <param name="data">The data to be computed.</param>
 /// <param name="isExport">True for EncryptionType.RC4_HMAC_EXP, false for EncryptionType.RC4_HMAC.</param>
 /// <returns>The computed result.</returns>
 internal static byte[] RC4HMAC(byte[] key, byte[] macContent, byte[] data, bool isExport)
 {
     byte[] Kseq = null;
     if (isExport)   // EncryptionType.RC4_HMAC_EXP
     {
         // Kseq = HMAC(Kss, "fortybits", (int32)0);
         Kseq = KileUtility.HMAC(key, ConstValue.FORTY_BITS, 0);
         // memset(Kseq+7, 0xab, 9)
         for (int i = 0; i < 9; ++i)
         {
             Kseq[i + 7] = 0xab;
         }
     }
     else            // EncryptionType.RC4_HMAC
     {
         Kseq = KileUtility.HMAC(key, 0);
     }
     Kseq = HMAC(Kseq, macContent);
     return(KileUtility.RC4(Kseq, data));
 }
        /// <summary>
        /// Construct EncKrbPrivPartof of KrbPrivRequest
        /// </summary>
        /// <param name="krbPrivRequest">to decide whether an seq_number in EncKrbPrivPart or not</param>
        /// <param name="userData">The user data want to send.</param>
        /// <returns>The EncKrbPrivPart.</returns>
        private EncKrbPrivPart ConstructEncKrbPrivPart(KRB_PRIV_REQUEST krbPrivRequest, byte[] userData)
        {
            EncKrbPrivPart encKrbPriv = new EncKrbPrivPart();

            encKrbPriv.s_address = new HostAddress(new KerbInt32((int)AddressType.NetBios),
                                                   new Asn1OctetString(Dns.GetHostName()));
            encKrbPriv.usec      = new Microseconds(0);
            encKrbPriv.user_data = new Asn1OctetString(userData);

            if (krbPrivRequest == KRB_PRIV_REQUEST.KrbPrivWithSequenceNumber)
            {
                encKrbPriv.seq_number = new KerbUInt32((long)context.CurrentLocalSequenceNumber);
                encKrbPriv.timestamp  = null;
            }
            else
            {
                encKrbPriv.seq_number = null;
                encKrbPriv.timestamp  = new KerberosTime(KileUtility.GetCurrentUTCTime());
            }

            return(encKrbPriv);
        }
        public KileApRequest CreateApRequest(
            Realm cRealm,
            PrincipalName cName,
            ApOptions apOptions,
            ChecksumType checksumType,
            int seqNumber,
            ChecksumFlags flag,
            EncryptionKey subkey,
            AuthorizationData authorizationData)
        {
            if (cRealm == null)
            {
                throw new ArgumentNullException("cRealm");
            }
            if (cName == null)
            {
                throw new ArgumentNullException("cName");
            }
            KileApRequest request = new KileApRequest(context);

            request.Authenticator = CreateAuthenticator(cRealm,
                                                        cName,
                                                        checksumType,
                                                        seqNumber,
                                                        flag,
                                                        subkey,
                                                        authorizationData,
                                                        context.ApSessionKey,
                                                        null);

            request.Request.ap_options = new APOptions(KileUtility.ConvertInt2Flags((int)apOptions));
            request.Request.msg_type   = new Asn1Integer((int)MsgType.KRB_AP_REQ);
            request.Request.pvno       = new Asn1Integer(ConstValue.KERBEROSV5);
            request.Request.ticket     = context.ApTicket;

            return(request);
        }
Example #14
0
 public override bool Decrypt(params SecurityBuffer[] securityBuffers)
 {
     return(KileUtility.Decrypt(server, securityBuffers));
 }
Example #15
0
 public override void Encrypt(params SecurityBuffer[] securityBuffers)
 {
     KileUtility.Encrypt(server, securityBuffers);
 }
Example #16
0
 public override bool Verify(params SecurityBuffer[] securityBuffers)
 {
     return(KileUtility.Verify(server, securityBuffers));
 }
Example #17
0
 public override void Sign(params SecurityBuffer[] securityBuffers)
 {
     KileUtility.Sign(server, securityBuffers);
 }
        /// <summary>
        /// Create TGS response.
        /// </summary>
        /// <param name="kileConnection">Maintain a connection with a target client. This argument cannot be null.</param>
        /// <param name="seqOfPaData">The pre-authentication data.
        /// This argument can be generated by method ConstructPaData. This argument could be null.</param>
        /// <param name="encTicketFlags">Ticket Flags</param>
        /// <param name="ticketEncryptKey">Encryption key used to encrypt ticket. This parameter cannot be null
        /// In User-User Authentication mode, use session key in additional ticket in KileTgsRequest.
        /// Otherwise use service's secret key.</param>
        /// <param name="ticketAuthorizationData">The authorization-data field is used to pass authorization data from
        /// the principal on whose behalf a ticket was issued to the application service. This parameter could be null.
        /// </param>
        /// <returns>The created TGS response.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input parameter is null.</exception>
        /// <exception cref="System.InvalidOperationException">Thrown when no kileConnection related server context
        /// is found </exception>
        public KileTgsResponse CreateTgsResponse(
            KileConnection kileConnection,
            _SeqOfPA_DATA seqOfPaData,
            EncTicketFlags encTicketFlags,
            EncryptionKey ticketEncryptKey,
            AuthorizationData ticketAuthorizationData)
        {
            KileServerContext serverContext = GetServerContextByKileConnection(kileConnection);

            if (ticketEncryptKey == null)
            {
                throw new ArgumentNullException("ticketEncryptKey");
            }
            else
            {
                serverContext.TicketEncryptKey = ticketEncryptKey;
            }
            KileTgsResponse response = new KileTgsResponse(serverContext);

            // Construct a Ticket
            Ticket ticket = new Ticket();

            ticket.tkt_vno = new Asn1Integer(ConstValue.KERBEROSV5);
            ticket.realm   = new Realm(domain);
            ticket.sname   = serverContext.SName;

            // Set EncTicketPart
            EncTicketPart  encTicketPart  = new EncTicketPart();
            EncryptionType encryptionType = (EncryptionType)serverContext.EncryptType.elements[0].mValue;

            encTicketPart.key                = new EncryptionKey((int)encryptionType, GetEncryptionKeyByType(encryptionType));
            encTicketPart.flags              = new TicketFlags(KileUtility.ConvertInt2Flags((int)encTicketFlags));
            encTicketPart.crealm             = serverContext.TgsTicket.crealm;
            encTicketPart.cname              = serverContext.TgsTicket.cname;
            encTicketPart.transited          = serverContext.TgsTicket.transited;
            encTicketPart.authtime           = KileUtility.CurrentKerberosTime;
            encTicketPart.starttime          = KileUtility.CurrentKerberosTime;
            encTicketPart.endtime            = serverContext.TgsTicket.endtime;
            encTicketPart.renew_till         = serverContext.TgsTicket.renew_till;
            encTicketPart.caddr              = serverContext.Addresses;
            encTicketPart.authorization_data = ticketAuthorizationData;
            response.TicketEncPart           = encTicketPart;

            // Set AS_REP
            response.Response.pvno     = new Asn1Integer(ConstValue.KERBEROSV5);
            response.Response.msg_type = new Asn1Integer((int)MsgType.KRB_TGS_RESP);
            response.Response.padata   = seqOfPaData;
            response.Response.crealm   = serverContext.UserRealm;
            response.Response.cname    = serverContext.UserName;
            response.Response.ticket   = ticket;

            // Set EncASRepPart
            EncTGSRepPart encTGSRepPart = new EncTGSRepPart();

            encTGSRepPart.key = encTicketPart.key;
            LastReq_element element = new LastReq_element(new Int32(0), KileUtility.CurrentKerberosTime);

            encTGSRepPart.last_req   = new LastReq(new LastReq_element[] { element });
            encTGSRepPart.nonce      = serverContext.Nonce;
            encTGSRepPart.flags      = encTicketPart.flags;
            encTGSRepPart.authtime   = encTicketPart.authtime;
            encTGSRepPart.starttime  = encTicketPart.starttime;
            encTGSRepPart.endtime    = encTicketPart.endtime;
            encTGSRepPart.renew_till = encTicketPart.renew_till;
            encTGSRepPart.srealm     = ticket.realm;
            encTGSRepPart.sname      = ticket.sname;
            encTGSRepPart.caddr      = encTicketPart.caddr;
            response.EncPart         = encTGSRepPart;

            return(response);
        }
        /// <summary>
        /// Create AS response.
        /// </summary>
        /// <param name="kileConnection">Maintain a connection with a target client. This argument cannot be null.</param>
        /// <param name="accountType">The type of the logoned account. User or Computer</param>
        /// <param name="password">Password of the user who logon the system. This argument cannot be null.</param>
        /// <param name="SeqofPaData">The pre-authentication data in AS request.
        /// This argument can be generated by method ConstructPaData. This argument could be null.</param>
        /// <param name="encTicketFlags">Ticket Flags</param>
        /// <param name="ticketAuthorizationData">The authorization-data field is used to pass authorization data from
        /// the principal on whose behalf a ticket was issued to the application service. This parameter could be null.
        /// </param>
        /// <returns>The created AS response.</returns>
        /// <exception cref="System.ArgumentNullException">Thrown when the input parameter is null.</exception>
        /// <exception cref="System.InvalidOperationException">Thrown when no kileConnection related server context
        /// is found </exception>
        public KileAsResponse CreateAsResponse(
            KileConnection kileConnection,
            KerberosAccountType accountType,
            string password,
            _SeqOfPA_DATA SeqofPaData,
            EncTicketFlags encTicketFlags,
            AuthorizationData ticketAuthorizationData)
        {
            KileServerContext serverContext = GetServerContextByKileConnection(kileConnection);
            string            cName         = serverContext.UserName.name_string.elements[0].mValue;
            string            cRealm        = serverContext.UserRealm.mValue;

            serverContext.Salt             = GenerateSalt(cRealm, cName, accountType);
            serverContext.TicketEncryptKey = new EncryptionKey((int)EncryptionType.RC4_HMAC,
                                                               GetEncryptionKeyByType(EncryptionType.RC4_HMAC));

            if (password == null)
            {
                throw new ArgumentNullException("password");
            }
            else
            {
                serverContext.Password = password;
            }
            KileAsResponse response = new KileAsResponse(serverContext);

            // Construct a Ticket
            Ticket ticket = new Ticket();

            ticket.tkt_vno = new Asn1Integer(ConstValue.KERBEROSV5);
            ticket.realm   = new Realm(domain);
            ticket.sname   = serverContext.SName;

            // Set EncTicketPart
            EncTicketPart  encTicketPart  = new EncTicketPart();
            EncryptionType encryptionType = (EncryptionType)serverContext.EncryptType.elements[0].mValue;

            encTicketPart.key                = new EncryptionKey((int)encryptionType, GetEncryptionKeyByType(encryptionType));
            encTicketPart.flags              = new TicketFlags(KileUtility.ConvertInt2Flags((int)encTicketFlags));
            encTicketPart.crealm             = serverContext.UserRealm;
            encTicketPart.cname              = serverContext.UserName;
            encTicketPart.transited          = new TransitedEncoding(4, null);
            encTicketPart.authtime           = KileUtility.CurrentKerberosTime;
            encTicketPart.starttime          = KileUtility.CurrentKerberosTime;
            encTicketPart.endtime            = serverContext.endTime;
            encTicketPart.renew_till         = serverContext.rtime ?? encTicketPart.endtime;
            encTicketPart.caddr              = serverContext.Addresses;
            encTicketPart.authorization_data = ticketAuthorizationData;
            response.TicketEncPart           = encTicketPart;

            // Set AS_REP
            response.Response.pvno     = new Asn1Integer(ConstValue.KERBEROSV5);
            response.Response.msg_type = new Asn1Integer((int)MsgType.KRB_AS_RESP);
            response.Response.padata   = SeqofPaData;
            response.Response.crealm   = serverContext.UserRealm;
            response.Response.cname    = serverContext.UserName;
            response.Response.ticket   = ticket;

            // Set EncASRepPart
            EncASRepPart encASRepPart = new EncASRepPart();

            encASRepPart.key = encTicketPart.key;
            LastReq_element element = new LastReq_element(new Int32(0), KileUtility.CurrentKerberosTime);

            encASRepPart.last_req   = new LastReq(new LastReq_element[] { element });
            encASRepPart.nonce      = serverContext.Nonce;
            encASRepPart.flags      = encTicketPart.flags;
            encASRepPart.authtime   = encTicketPart.authtime;
            encASRepPart.starttime  = encTicketPart.starttime;
            encASRepPart.endtime    = encTicketPart.endtime;
            encASRepPart.renew_till = encTicketPart.renew_till;
            encASRepPart.srealm     = ticket.realm;
            encASRepPart.sname      = ticket.sname;
            encASRepPart.caddr      = encTicketPart.caddr;
            response.EncPart        = encASRepPart;

            return(response);
        }
        public KileTgsRequest CreateTgsRequest(
            Realm cRealm,
            PrincipalName cName,
            PrincipalName sName,
            KRBFlags kdcOptions,
            KerbUInt32 nonce,
            Realm realm,
            Asn1SequenceOf <PA_DATA> paData,
            ChecksumType checksumType,
            Ticket additionalTicket,
            AuthorizationData authorizationData)
        {
            if (cRealm == null)
            {
                throw new ArgumentNullException("cRealm");
            }
            if (cName == null)
            {
                throw new ArgumentNullException("cName");
            }
            if (sName == null)
            {
                throw new ArgumentNullException("sName");
            }
            if (realm == null)
            {
                throw new ArgumentNullException("realm");
            }

            KileTgsRequest request = new KileTgsRequest(context);

            request.Request.msg_type = new Asn1Integer((int)MsgType.KRB_TGS_REQ);
            request.Request.pvno     = new Asn1Integer(ConstValue.KERBEROSV5);

            #region construct req_body
            request.Request.req_body             = new KDC_REQ_BODY();
            request.Request.req_body.kdc_options = new KDCOptions(KileUtility.ConvertInt2Flags((int)kdcOptions));
            request.Request.req_body.nonce       = nonce;
            request.Request.req_body.till        = new KerberosTime(ConstValue.TGT_TILL_TIME);
            request.Request.req_body.etype       = context.ClientEncryptionTypes;
            request.Request.req_body.realm       = realm;

            if (additionalTicket != null)
            {
                request.Request.req_body.additional_tickets = new Asn1SequenceOf <Ticket>(new Ticket[] { additionalTicket });
            }
            request.Request.req_body.sname = sName;
            request.EncAuthorizationData   = authorizationData;

            if (authorizationData != null)
            {
                Asn1BerEncodingBuffer asnBuffer = new Asn1BerEncodingBuffer();
                authorizationData.BerEncode(asnBuffer, true);

                request.Request.req_body.enc_authorization_data       = new EncryptedData();
                request.Request.req_body.enc_authorization_data.etype = new KerbInt32(0);
                byte[] encAsnEncoded = asnBuffer.Data;
                if (context.TgsSessionKey != null && context.TgsSessionKey.keytype != null &&
                    context.TgsSessionKey.keyvalue != null && context.TgsSessionKey.keyvalue.Value != null)
                {
                    encAsnEncoded = KileUtility.Encrypt((EncryptionType)context.TgsSessionKey.keytype.Value,
                                                        context.TgsSessionKey.keyvalue.ByteArrayValue,
                                                        asnBuffer.Data,
                                                        (int)KeyUsageNumber.TGS_REQ_KDC_REQ_BODY_AuthorizationData);
                    request.Request.req_body.enc_authorization_data.etype =
                        new KerbInt32(context.TgsSessionKey.keytype.Value);
                }

                request.Request.req_body.enc_authorization_data.cipher = new Asn1OctetString(encAsnEncoded);
            }
            #endregion construct req_body

            #region construct PA_DATA
            Asn1BerEncodingBuffer bodyBuffer = new Asn1BerEncodingBuffer();
            request.Request.req_body.BerEncode(bodyBuffer);
            PA_DATA tgsPaData = ConstructTgsPaData(cRealm, cName, checksumType, bodyBuffer.Data);

            request.Request.padata = new Asn1SequenceOf <PA_DATA>();
            if (paData == null || paData.Elements == null || paData.Elements.Length == 0)
            {
                request.Request.padata.Elements = new PA_DATA[] { tgsPaData };
            }
            else
            {
                request.Request.padata.Elements = new PA_DATA[paData.Elements.Length + 1];
                Array.Copy(paData.Elements, request.Request.padata.Elements, paData.Elements.Length);
                request.Request.padata.Elements[paData.Elements.Length] = tgsPaData;
            }
            #endregion construct PA_DATA

            return(request);
        }