Example #1
0
        public KileAsRequest CreateAsRequest(string sName,
                                             KDCOptions kdcOptions,
                                             Asn1SequenceOf <PA_DATA> paData,
                                             params EncryptionType[] encryptionTypes)
        {
            var 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 = 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), KerberosUtility.String2SeqKerbString(sName, domain));
            }

            if (encryptionTypes != null)
            {
                var 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);
        }
Example #2
0
        public KileTgsRequest CreateTgsRequest(string sName,
                                               KDCOptions kdcOptions,
                                               Asn1SequenceOf <PA_DATA> paData,
                                               ChecksumType checksumType,
                                               Ticket additionalTicket,
                                               AuthorizationData authorizationData)
        {
            if (sName == null)
            {
                throw new ArgumentNullException(nameof(sName));
            }
            var sname = new PrincipalName(new KerbInt32((int)PrincipalType.NT_SRV_INST),
                                          KerberosUtility.String2SeqKerbString(sName.Split('/')));

            return(CreateTgsRequest(sname, kdcOptions, new KerbUInt32((uint)Math.Abs((uint)DateTime.Now.Ticks)), context.UserRealm, paData,
                                    checksumType, additionalTicket, authorizationData));
        }
Example #3
0
        private void Smb2KerberosAuthentication(CaseVariant variant)
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Initialize Kerberos Functional Client");
            KerberosFunctionalClient kerberosClient = new KerberosFunctionalClient(
                TestConfig.DomainName,
                TestConfig.UserName,
                TestConfig.UserPassword,
                KerberosAccountType.User,
                KDCIP,
                KDCPort,
                TransportType.TCP,
                OidPkt,
                BaseTestSite);

            #region Service Ticket
            EncryptionKey serviceKey;
            EncTicketPart encTicketPart = RetrieveAndDecryptServiceTicket(kerberosClient, out serviceKey);

            Ticket serviceTicket = kerberosClient.Context.Ticket.Ticket;

            Realm crealm = serviceTicket.realm;
            BaseTestSite.Assert.AreEqual(TestConfig.DomainName.ToLower(),
                                         encTicketPart.crealm.Value.ToLower(),
                                         "Realm name in service ticket encrypted part should match as expected, case insensitive");
            BaseTestSite.Assert.AreEqual(TestConfig.UserName.ToLower(),
                                         KerberosUtility.PrincipalName2String(encTicketPart.cname).ToLower(),
                                         "User name in service ticket encrypted part should match as expected, case insensitive.");

            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_TKT))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Add a type-unknown AuthorizationData to the ticket");
                AuthorizationDataElement unknownElement = GenerateUnKnownAuthorizationDataElement();
                AppendNewAuthDataElement(encTicketPart.authorization_data, unknownElement);
            }

            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_TKT_OPTIONAL))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Add a type-unknown AuthorizationData which is inside AD_IF_RELEVANT to the ticket");
                AuthorizationDataElement unknownElement    = GenerateUnKnownAuthorizationDataElement();
                AD_IF_RELEVANT           ifRelavantElement =
                    new AD_IF_RELEVANT(new[] { unknownElement });
                var dataBuffer = new Asn1BerEncodingBuffer();
                ifRelavantElement.BerEncode(dataBuffer);
                AuthorizationDataElement unknownElementOptional =
                    new AuthorizationDataElement(new KerbInt32((long)AuthorizationData_elementType.AD_IF_RELEVANT), new Asn1OctetString(dataBuffer.Data));
                AppendNewAuthDataElement(encTicketPart.authorization_data, unknownElementOptional);
            }

            if (variant.HasFlag(CaseVariant.TICKET_NOT_VALID))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the Ticket start time to tomorrow");
                DateTime tomorrow       = DateTime.Now.AddDays(1);
                string   kerbTimeString = tomorrow.ToUniversalTime().ToString("yyyyMMddhhmmssZ");
                encTicketPart.starttime = new KerberosTime(kerbTimeString, true);
            }
            if (variant.HasFlag(CaseVariant.TICKET_EXPIRED))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the Ticket end time to yesterday");
                DateTime yesterday      = DateTime.Now.AddDays(-1);
                string   kerbTimeString = yesterday.ToUniversalTime().ToString("yyyyMMddhhmmssZ");
                encTicketPart.endtime = new KerberosTime(kerbTimeString, true);
            }

            if (variant.HasFlag(CaseVariant.TICKET_WRONG_ENC_KEY))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Modify the Ticket, making it encrypted with wrong key");
                serviceKey = KerberosUtility.GenerateKey(serviceKey);
            }

            EncryptedData data = EncryptTicket(encTicketPart, serviceKey);
            serviceTicket.enc_part = data;

            if (variant.HasFlag(CaseVariant.TICKET_WRONG_REALM))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the Realm in the Ticket to an unknown realm");
                serviceTicket.realm = new Realm("kerb.com");
            }
            if (variant.HasFlag(CaseVariant.TICKET_WRONG_SNAME))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the SNAME in the Ticket to an unknown service name");
                serviceTicket.sname = new PrincipalName(new KerbInt32((long)PrincipalType.NT_SRV_INST),
                                                        KerberosUtility.String2SeqKerbString("UnknownService", TestConfig.DomainName));
            }
            if (variant.HasFlag(CaseVariant.TICKET_WRONG_KVNO))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep,
                                     "Change the KVNO in the Ticket to an invalid Key Version Number (Int32.MaxValue)");
                const int invalidKvno = System.Int32.MaxValue;
                serviceTicket.enc_part.kvno = new KerbInt32(invalidKvno);
            }
            #endregion

            #region Authenticator
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create Authenticator");
            EncryptionKey subkey = KerberosUtility.GenerateKey(kerberosClient.Context.SessionKey);
            PrincipalName cname;
            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_CNAME_NOT_MATCH))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Use wrong cname in the Authenticator");
                cname = new PrincipalName(new KerbInt32((long)PrincipalType.NT_PRINCIPAL),
                                          KerberosUtility.String2SeqKerbString(TestConfig.NonAdminUserName, TestConfig.DomainName));
            }
            else
            {
                cname = kerberosClient.Context.CName.Name;
            }

            Authenticator authenticator = CreateAuthenticator(cname, crealm, subkey);
            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_CREALM_NOT_MATCH))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Use wrong crealm in the Authenticator");
                authenticator.crealm = new Realm("kerb.com");
            }

            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_EXCEED_TIME_SKEW))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Change the ctime in the Authenticator to one hour later");
                DateTime oneHourLater   = DateTime.Now.AddHours(1);
                string   kerbTimeString = oneHourLater.ToUniversalTime().ToString("yyyyMMddhhmmssZ");
                authenticator.ctime = new KerberosTime(kerbTimeString, true);
            }

            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_AUTHENTICATOR))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Add a type-unknown AuthorizationData to the Authenticator");
                AuthorizationDataElement unknownElement = GenerateUnKnownAuthorizationDataElement();
                authenticator.authorization_data = new AuthorizationData(new[] { unknownElement });
            }

            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_AUTHENTICATOR_OPTIONAL))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep,
                                     "Add a type-unknown AuthorizationData which is inside AD_IF_RELEVANT to the Authenticator");
                AuthorizationDataElement unknownElement    = GenerateUnKnownAuthorizationDataElement();
                AD_IF_RELEVANT           ifRelavantElement =
                    new AD_IF_RELEVANT(new[] { unknownElement });
                var dataBuffer = new Asn1BerEncodingBuffer();
                ifRelavantElement.BerEncode(dataBuffer);
                AuthorizationDataElement unknownElementOptional =
                    new AuthorizationDataElement(new KerbInt32((long)AuthorizationData_elementType.AD_IF_RELEVANT), new Asn1OctetString(dataBuffer.Data));
                authenticator.authorization_data = new AuthorizationData(new[] { unknownElementOptional });
            }

            #endregion

            #region AP Request
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create AP Request");
            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_WRONG_ENC_KEY))
            {
                BaseTestSite.Log.Add(LogEntryKind.TestStep, "Use wrong key to encrypt the Authenticator");
                kerberosClient.Context.Ticket.SessionKey = KerberosUtility.GenerateKey(kerberosClient.Context.Ticket.SessionKey);
            }
            KerberosApRequest request = new KerberosApRequest(
                kerberosClient.Context.Pvno,
                new APOptions(KerberosUtility.ConvertInt2Flags((int)ApOptions.MutualRequired)),
                kerberosClient.Context.Ticket,
                authenticator,
                KeyUsageNumber.AP_REQ_Authenticator
                );
            #endregion

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Create GSS Token");
            byte[] token = KerberosUtility.AddGssApiTokenHeader(request, OidPkt, GssToken);

            Smb2FunctionalClientForKerbAuth smb2Client = new Smb2FunctionalClientForKerbAuth(TestConfig.Timeout, TestConfig, BaseTestSite);
            smb2Client.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);

            #region Check the result

            byte[] repToken;
            uint   status = DoSessionSetupWithGssToken(smb2Client, token, out repToken);

            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_CNAME_NOT_MATCH) || variant.HasFlag(CaseVariant.AUTHENTICATOR_CREALM_NOT_MATCH))
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                                                "Session Setup should fail because the cname or crealm in the authenticator does not match the same field in the Ticket");
                if (TestConfig.IsWindowsPlatform)
                {
                    KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken);
                    BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_BADMATCH, krbError.ErrorCode,
                                                 "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_BADMATCH);
                }
                smb2Client.Disconnect();
                return;
            }
            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_WRONG_ENC_KEY) || variant.HasFlag(CaseVariant.TICKET_WRONG_ENC_KEY))
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                                                "Session Setup should fail because Ticket or Authenticator cannot be correctly decrypted");
                if (TestConfig.IsWindowsPlatform)
                {
                    KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken);
                    BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_MODIFIED, krbError.ErrorCode,
                                                 "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_MODIFIED);
                }
                smb2Client.Disconnect();
                return;
            }
            if (variant.HasFlag(CaseVariant.AUTHENTICATOR_EXCEED_TIME_SKEW))
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                                                "Session Setup should fail because the server time and the client time " +
                                                "in the Authenticator differ by (1 hour) more than the allowable clock skew");
                if (TestConfig.IsWindowsPlatform)
                {
                    KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken);
                    BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_SKEW, krbError.ErrorCode,
                                                 "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_SKEW);
                }
                smb2Client.Disconnect();
                return;
            }
            if (variant.HasFlag(CaseVariant.TICKET_WRONG_KVNO) ||
                variant.HasFlag(CaseVariant.TICKET_WRONG_REALM) ||
                variant.HasFlag(CaseVariant.TICKET_WRONG_SNAME))
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment, "If decryption fails, server would try other keys");
            }
            if (variant.HasFlag(CaseVariant.TICKET_NOT_VALID))
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                                                "Session Setup should fail because the starttime (tomorrow) in the Ticket " +
                                                "is later than the current time by more than the allowable clock skew");
                if (TestConfig.IsWindowsPlatform)
                {
                    KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken);
                    BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_TKT_NYV, krbError.ErrorCode,
                                                 "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_TKT_NYV);
                }
                smb2Client.Disconnect();
                return;
            }
            if (variant.HasFlag(CaseVariant.TICKET_EXPIRED))
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                                                "Session Setup should fail because the current time is later than the endtime (yesterday)" +
                                                " in the Ticket by more than the allowable clock skew");
                if (TestConfig.IsWindowsPlatform)
                {
                    KerberosKrbError krbError = kerberosClient.GetKrbErrorFromToken(repToken);
                    BaseTestSite.Assert.AreEqual(KRB_ERROR_CODE.KRB_AP_ERR_TKT_EXPIRED, krbError.ErrorCode,
                                                 "SMB Server should return {0}", KRB_ERROR_CODE.KRB_AP_ERR_TKT_EXPIRED);
                }
                smb2Client.Disconnect();
                return;
            }
            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_TKT))
            {
                BaseTestSite.Assert.AreNotEqual(Smb2Status.STATUS_SUCCESS, status,
                                                "Session Setup should fail because of the unknown AutherizationData in the ticket");
                smb2Client.Disconnect();
                return;
            }
            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_AUTHENTICATOR))
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment,
                                     "Unknown AuthorizationData in the Authenticator should not fail the request");
            }
            if (variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_TKT_OPTIONAL) ||
                variant.HasFlag(CaseVariant.AUTHDATA_UNKNOWN_TYPE_IN_AUTHENTICATOR_OPTIONAL))
            {
                BaseTestSite.Log.Add(LogEntryKind.Comment, "Unknown AuthorizationData in AD_IF_RELEVANT is optional. " +
                                     "Server should not fail the request.");
            }

            KerberosApResponse apRep = kerberosClient.GetApResponseFromToken(repToken, GssToken);
            // Get subkey from AP response, which used for signing in smb2
            apRep.Decrypt(kerberosClient.Context.Ticket.SessionKey.keyvalue.ByteArrayValue);
            smb2Client.SetSessionSigningAndEncryption(true, false, apRep.ApEncPart.subkey.keyvalue.ByteArrayValue);

            string path = Smb2Utility.GetUncPath(TestConfig.SutComputerName, TestConfig.BasicFileShare);
            AccessFile(smb2Client, path);
            #endregion

            smb2Client.LogOff();
            smb2Client.Disconnect();
        }