public static IAuthDataElement ParseAuthDataElement(AuthorizationDataElement element)
        {
            IAuthDataElement authDataElement;

            switch ((AuthorizationData_elementType)element.ad_type.Value)
            {
            case AuthorizationData_elementType.AD_IF_RELEVANT:
                authDataElement = AdIfRelevent.Parse(element);
                break;

            case AuthorizationData_elementType.AD_WIN2K_PAC:
                authDataElement = AdWin2KPac.Parse(element);
                break;

            case AuthorizationData_elementType.AD_FX_FAST_USED:
                authDataElement = AdFxFastUsed.Parse(element);
                break;

            case AuthorizationData_elementType.KERB_AUTH_DATA_TOKEN_RESTRICTIONS:
                authDataElement = KerbAuthDataTokenRestrictions.Parse(element);
                break;

            default:
                return(null);
            }
            return(authDataElement);
        }
 public static AdAuthDataApOptions Parse(AuthorizationDataElement element)
 {
     if (element.ad_type.Value != (int)AuthorizationData_elementType.AD_AUTH_DATA_AP_OPTIONS)
         throw new Exception();
     var apOptions = new APOptions();
     apOptions.BerDecode(new Asn1DecodingBuffer(element.ad_data.ByteArrayValue));
     throw new NotImplementedException();
 }
 public static AdFxFastArmor Parse(AuthorizationDataElement element)
 {
     if (element.ad_type.Value != (int)AuthorizationData_elementType.AD_FX_FAST_ARMOR)
     {
         throw new Exception();
     }
     return(new AdFxFastArmor());
 }
        public static AdAuthDataApOptions Parse(AuthorizationDataElement element)
        {
            if (element.ad_type.Value != (int)AuthorizationData_elementType.AD_AUTH_DATA_AP_OPTIONS)
            {
                throw new Exception();
            }
            var apOptions = new APOptions();

            apOptions.BerDecode(new Asn1DecodingBuffer(element.ad_data.ByteArrayValue));
            throw new NotImplementedException();
        }
        public static AdIfRelevent Parse(AuthorizationDataElement element)
        {
            if (element.ad_type.Value != (int)AuthorizationData_elementType.AD_IF_RELEVANT)
            {
                throw new Exception();
            }
            var adIfRelevant = new AD_IF_RELEVANT();

            adIfRelevant.BerDecode(new Asn1DecodingBuffer(element.ad_data.ByteArrayValue));
            return(new AdIfRelevent(adIfRelevant));
        }
        public static AdWin2KPac Parse(AuthorizationDataElement element)
        {
            if (element.ad_type.Value != (int)AuthorizationData_elementType.AD_WIN2K_PAC)
            {
                throw new Exception();
            }
            var adWin2KPac = new AdWin2KPac();

            adWin2KPac.Pac = PacUtility.DecodePacType(element.ad_data.ByteArrayValue);
            return(adWin2KPac);
        }
        public static KerbAuthDataTokenRestrictions Parse(AuthorizationDataElement element)
        {
            if (element.ad_type.Value != (int)AuthorizationData_elementType.KERB_AUTH_DATA_TOKEN_RESTRICTIONS)
            {
                throw new Exception();
            }
            var entry = new KERB_AD_RESTRICTION_ENTRY();

            entry.BerDecode(new Asn1DecodingBuffer(element.ad_data.ByteArrayValue));

            LSAP_TOKEN_INFO_INTEGRITY ltii = new LSAP_TOKEN_INFO_INTEGRITY();

            ltii.GetElements(entry.restriction);

            return(new KerbAuthDataTokenRestrictions(
                       (int)entry.restriction_type.Value,
                       (uint)ltii.flags.Value,
                       (uint)ltii.tokenIL.Value,
                       Encoding.UTF8.GetString(ltii.machineID.ByteArrayValue)));
        }
        public static KerbAuthDataTokenRestrictions Parse(AuthorizationDataElement element)
        {
            if (element.ad_type.Value != (int)AuthorizationData_elementType.KERB_AUTH_DATA_TOKEN_RESTRICTIONS)
                throw new Exception();
            var entry = new KERB_AD_RESTRICTION_ENTRY();
            entry.BerDecode(new Asn1DecodingBuffer(element.ad_data.ByteArrayValue));

            LSAP_TOKEN_INFO_INTEGRITY ltii = new LSAP_TOKEN_INFO_INTEGRITY();
            ltii.GetElements(entry.restriction);

            return new KerbAuthDataTokenRestrictions(
                (int)entry.restriction_type.Value,
                (uint)ltii.flags.Value,
                (uint)ltii.tokenIL.Value,
                Encoding.UTF8.GetString(ltii.machineID.ByteArrayValue));
        }
 public static IAuthDataElement ParseAuthDataElement(AuthorizationDataElement element)
 {
     IAuthDataElement authDataElement;
     switch ((AuthorizationData_elementType)element.ad_type.Value)
     {
         case AuthorizationData_elementType.AD_IF_RELEVANT:
             authDataElement = AdIfRelevent.Parse(element);
             break;
         case AuthorizationData_elementType.AD_WIN2K_PAC:
             authDataElement = AdWin2KPac.Parse(element);
             break;
         case AuthorizationData_elementType.AD_FX_FAST_USED:
             authDataElement = AdFxFastUsed.Parse(element);
             break;
         case AuthorizationData_elementType.KERB_AUTH_DATA_TOKEN_RESTRICTIONS:
             authDataElement = KerbAuthDataTokenRestrictions.Parse(element);
             break;
         default:
             return null;
     }
     return authDataElement;
 }
 public static AdWin2KPac Parse(AuthorizationDataElement element)
 {
     if (element.ad_type.Value != (int)AuthorizationData_elementType.AD_WIN2K_PAC)
         throw new Exception();
     var adWin2KPac = new AdWin2KPac();
     adWin2KPac.Pac = PacUtility.DecodePacType(element.ad_data.ByteArrayValue);
     return adWin2KPac;
 }
 public static AdIfRelevent Parse(AuthorizationDataElement element)
 {
     if (element.ad_type.Value != (int)AuthorizationData_elementType.AD_IF_RELEVANT)
         throw new Exception();
     var adIfRelevant = new AD_IF_RELEVANT();
     adIfRelevant.BerDecode(new Asn1DecodingBuffer(element.ad_data.ByteArrayValue));
     return new AdIfRelevent(adIfRelevant);
 }
 public static AdFxFastUsed Parse(AuthorizationDataElement element)
 {
     if (element.ad_type.Value != (int)AuthorizationData_elementType.AD_FX_FAST_USED)
         throw new Exception();
     return new AdFxFastUsed();
 }
        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();
        }
 private AuthorizationDataElement GenerateUnKnownAuthorizationDataElement()
 {
     byte[] randomData = new byte[100];
     Random r = new Random();
     r.NextBytes(randomData);
     const int unknownType = Int16.MaxValue;
     AuthorizationDataElement unknowElement = new AuthorizationDataElement(new KerbInt32(unknownType), new Asn1OctetString(randomData));
     return unknowElement;
 }
 private void AppendNewAuthDataElement(AuthorizationData originalAuthData, AuthorizationDataElement newElement)
 {
     int elementNum = originalAuthData.Elements.Length;
     AuthorizationDataElement[] elements = new AuthorizationDataElement[elementNum + 1];
     originalAuthData.Elements.CopyTo(elements, 0);
     elements[elementNum] = newElement;
     originalAuthData.Elements = elements;
 }