public override async Task <KrbPaData> Validate(KrbKdcReq asReq, IKerberosPrincipal principal)
        {
            var timestamp = asReq.DecryptTimestamp(await principal.RetrieveLongTermCredential());

            if (timestamp == DateTimeOffset.MinValue)
            {
                return(new KrbPaData
                {
                    Type = PaDataType.PA_ENC_TIMESTAMP
                });
            }

            var skew = Service.Settings.MaximumSkew;

            DateTimeOffset now = Service.Now();

            if ((now - timestamp) > skew)
            {
                throw new KerberosValidationException(
                          $"Timestamp window is greater than allowed skew. Start: {timestamp}; End: {now}; Skew: {skew}"
                          );
            }

            return(null);
        }
Exemplo n.º 2
0
        public override async Task PostValidate(IKerberosPrincipal principal, List <KrbPaData> preAuthRequirements)
        {
            if (preAuthRequirements.Count <= 0)
            {
                // we don't want to include this if nothing is required otherwise we could
                // trigger a pre-auth check later in the flow or by the client in response

                return;
            }

            var cred = await principal.RetrieveLongTermCredential();

            var etypeInfo = new KrbETypeInfo2
            {
                ETypeInfo = new[] {
                    new  KrbETypeInfo2Entry {
                        EType = cred.EncryptionType,
                        Salt  = cred.Salt
                    }
                }
            };

            var infoPaData = new KrbPaData
            {
                Type  = PaDataType.PA_ETYPE_INFO2,
                Value = etypeInfo.Encode().AsMemory()
            };

            preAuthRequirements.Add(infoPaData);
        }
        public override void PostValidate(IKerberosPrincipal principal, List <KrbPaData> preAuthRequirements)
        {
            if (principal == null)
            {
                throw new ArgumentNullException(nameof(principal));
            }

            if (preAuthRequirements == null)
            {
                throw new ArgumentNullException(nameof(preAuthRequirements));
            }

            if (preAuthRequirements.Count <= 0)
            {
                // we don't want to include this if nothing is required otherwise we could
                // trigger a pre-auth check later in the flow or by the client in response

                return;
            }

            var entries = new List <KrbETypeInfo2Entry>();

            foreach (EncryptionType type in Enum.GetValues(typeof(EncryptionType)))
            {
                if (!CryptoService.SupportsEType(type, this.Service.Configuration.Defaults.AllowWeakCrypto))
                {
                    continue;
                }

                var cred = principal.RetrieveLongTermCredential(type);

                if (cred != null)
                {
                    entries.Add(new KrbETypeInfo2Entry
                    {
                        EType = cred.EncryptionType,
                        Salt  = cred.Salt
                    });
                }
            }

            var etypeInfo = new KrbETypeInfo2
            {
                ETypeInfo = entries.ToArray()
            };

            var infoPaData = new KrbPaData
            {
                Type  = PaDataType.PA_ETYPE_INFO2,
                Value = etypeInfo.Encode()
            };

            preAuthRequirements.Add(infoPaData);
        }
        private async Task <ReadOnlyMemory <byte> > GenerateAsRep(KrbAsReq asReq, IKerberosPrincipal principal)
        {
            // 1. detect if specific PAC contents are requested (claims)
            // 2. if requested generate PAC for user
            // 3. stuff PAC into ad-if-relevant pa-data of krbtgt ticket
            // 4. look up krbtgt account
            // 5. encrypt against krbtgt
            // 6. done

            var requirements = new List <KrbPaData>();

            foreach (var handler in postProcessAuthHandlers)
            {
                await InvokePreAuthHandler(null, principal, requirements, handler.Value);
            }

            var rst = new ServiceTicketRequest
            {
                Principal  = principal,
                Addresses  = asReq.Body.Addresses,
                Nonce      = asReq.Body.Nonce,
                IncludePac = true,
                Flags      = TicketFlags.Initial | KrbKdcRep.DefaultFlags
            };

            rst.EncryptedPartKey = await principal.RetrieveLongTermCredential();

            var pacRequest = asReq.PaData.FirstOrDefault(pa => pa.Type == PaDataType.PA_PAC_REQUEST);

            if (pacRequest != null)
            {
                var paPacRequest = KrbPaPacRequest.Decode(pacRequest.Value);

                rst.IncludePac = paPacRequest.IncludePac;
            }

            var asRep = await KrbAsRep.GenerateTgt(rst, RealmService);

            asRep.PaData = requirements.ToArray();

            return(asRep.EncodeApplication());
        }
Exemplo n.º 5
0
        public static async Task <KrbAsRep> GenerateTgt(
            IKerberosPrincipal principal,
            IEnumerable <KrbPaData> requirements,
            IRealmService realmService,
            KrbKdcReqBody asReq
            )
        {
            // This is approximately correct such that a client doesn't barf on it
            // The krbtgt Ticket structure is probably correct as far as AD thinks
            // Modulo the PAC, at least.

            var longTermKey = await principal.RetrieveLongTermCredential();

            var servicePrincipal = await realmService.Principals.RetrieveKrbtgt();

            var servicePrincipalKey = await servicePrincipal.RetrieveLongTermCredential();

            var now = realmService.Now();

            KrbAsRep asRep = await GenerateServiceTicket <KrbAsRep>(
                new ServiceTicketRequest
            {
                Principal           = principal,
                EncryptedPartKey    = longTermKey,
                ServicePrincipal    = servicePrincipal,
                ServicePrincipalKey = servicePrincipalKey,
                Now       = now,
                Addresses = asReq.Addresses,
                RenewTill = now + realmService.Settings.MaximumRenewalWindow,
                StartTime = now - realmService.Settings.MaximumSkew,
                EndTime   = now + realmService.Settings.SessionLifetime,
                Flags     = DefaultFlags,
                RealmName = realmService.Name,
                Nonce     = asReq.Nonce
            }
                );

            asRep.PaData = requirements.ToArray();

            return(asRep);
        }