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);
        }
        /// <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)));
        }
        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);
        }
        /// <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);
        }