internal static void Decode <T>(AsnReader reader, Asn1Tag expectedTag, out T decoded)
            where T : KrbFastReq, new()
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            decoded = new T();

            AsnReader sequenceReader = reader.ReadSequence(expectedTag);
            AsnReader explicitReader;
            AsnReader collectionReader;

            explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0));

            if (explicitReader.TryReadPrimitiveBitStringValue(out _, out ReadOnlyMemory <byte> tmpFastOptions))
            {
                decoded.FastOptions = (FastOptions)tmpFastOptions.AsLong();
            }
            else
            {
                decoded.FastOptions = (FastOptions)explicitReader.ReadBitString(out _).AsLong();
            }


            explicitReader.ThrowIfNotEmpty();

            explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1));
            // Decode SEQUENCE OF for PaData
            {
                collectionReader = explicitReader.ReadSequence();
                var       tmpList = new List <KrbPaData>();
                KrbPaData tmpItem;

                while (collectionReader.HasData)
                {
                    KrbPaData.Decode <KrbPaData>(collectionReader, out KrbPaData tmp);
                    tmpItem = tmp;
                    tmpList.Add(tmpItem);
                }

                decoded.PaData = tmpList.ToArray();
            }

            explicitReader.ThrowIfNotEmpty();

            explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 2));
            KrbKdcReqBody.Decode <KrbKdcReqBody>(explicitReader, out KrbKdcReqBody tmpReqBody);
            decoded.ReqBody = tmpReqBody;

            explicitReader.ThrowIfNotEmpty();

            sequenceReader.ThrowIfNotEmpty();
        }
Esempio n. 2
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);
        }
Esempio n. 3
0
        public static KrbTgsReq CreateTgsReq(
            RequestServiceTicket rst,
            KrbEncryptionKey tgtSessionKey,
            KrbKdcRep kdcRep,
            out KrbEncryptionKey sessionKey
            )
        {
            var sname = rst.ServicePrincipalName.Split('/', '@');
            var tgt   = kdcRep.Ticket;

            var additionalTickets = new List <KrbTicket>();

            if (rst.KdcOptions.HasFlag(KdcOptions.EncTktInSkey) && rst.UserToUserTicket != null)
            {
                additionalTickets.Add(rst.UserToUserTicket);
            }

            if (!string.IsNullOrWhiteSpace(rst.S4uTarget))
            {
                rst.KdcOptions |= KdcOptions.Forwardable;
            }

            if (rst.S4uTicket != null)
            {
                rst.KdcOptions |= KdcOptions.ConstrainedDelegation;

                additionalTickets.Add(rst.S4uTicket);
            }

            var body = new KrbKdcReqBody
            {
                EType      = KerberosConstants.ETypes.ToArray(),
                KdcOptions = rst.KdcOptions,
                Nonce      = KerberosConstants.GetNonce(),
                Realm      = rst.Realm,
                SName      = new KrbPrincipalName()
                {
                    Type = PrincipalNameType.NT_SRV_INST,
                    Name = sname
                },
                Till  = KerberosConstants.EndOfTime,
                CName = rst.CNameHint
            };

            if (additionalTickets.Count > 0)
            {
                body.AdditionalTickets = additionalTickets.ToArray();
            }

            var bodyChecksum = KrbChecksum.Create(
                body.Encode(),
                tgtSessionKey.AsKey(),
                KeyUsage.PaTgsReqChecksum
                );

            var tgtApReq = CreateApReq(kdcRep, tgtSessionKey, bodyChecksum, out sessionKey);

            var pacOptions = new KrbPaPacOptions
            {
                Flags = PacOptions.ResourceBasedConstrainedDelegation | PacOptions.Claims | PacOptions.BranchAware
            }.Encode();

            var paData = new List <KrbPaData>()
            {
                new KrbPaData {
                    Type  = PaDataType.PA_TGS_REQ,
                    Value = tgtApReq.EncodeApplication()
                },
                new KrbPaData {
                    Type  = PaDataType.PA_PAC_OPTIONS,
                    Value = pacOptions
                }
            };

            if (!string.IsNullOrWhiteSpace(rst.S4uTarget))
            {
                paData.Add(new KrbPaData
                {
                    Type  = PaDataType.PA_FOR_USER,
                    Value = EncodeS4URequest(rst.S4uTarget, tgt.Realm, tgtSessionKey)
                });
            }

            var tgs = new KrbTgsReq
            {
                PaData = paData.ToArray(),
                Body   = body
            };

            return(tgs);
        }
        internal static void Decode <T>(AsnReader reader, Asn1Tag expectedTag, out T decoded)
            where T : KrbKdcReq, new()
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            decoded = new T();
            AsnReader sequenceReader = reader.ReadSequence(expectedTag);
            AsnReader explicitReader;
            AsnReader collectionReader;


            explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1));

            if (!explicitReader.TryReadInt32(out decoded.ProtocolVersionNumber))
            {
                explicitReader.ThrowIfNotEmpty();
            }

            explicitReader.ThrowIfNotEmpty();


            explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 2));

            if (!explicitReader.TryReadInt32(out decoded.MessageType))
            {
                explicitReader.ThrowIfNotEmpty();
            }

            explicitReader.ThrowIfNotEmpty();


            explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 3));

            // Decode SEQUENCE OF for PaData
            {
                collectionReader = explicitReader.ReadSequence();
                var       tmpList = new List <KrbPaData>();
                KrbPaData tmpItem;

                while (collectionReader.HasData)
                {
                    KrbPaData.Decode <KrbPaData>(collectionReader, out tmpItem);
                    tmpList.Add(tmpItem);
                }

                decoded.PaData = tmpList.ToArray();
            }

            explicitReader.ThrowIfNotEmpty();


            explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 4));
            KrbKdcReqBody.Decode <KrbKdcReqBody>(explicitReader, out decoded.Body);
            explicitReader.ThrowIfNotEmpty();


            sequenceReader.ThrowIfNotEmpty();
        }
Esempio n. 5
0
        public static KrbTgsReq CreateTgsReq(
            RequestServiceTicket rst,
            KrbEncryptionKey tgtSessionKey,
            KrbKdcRep kdcRep,
            out KrbEncryptionKey sessionKey
            )
        {
            if (kdcRep == null)
            {
                throw new ArgumentNullException(nameof(kdcRep));
            }

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

            if (string.IsNullOrWhiteSpace(rst.ServicePrincipalName))
            {
                throw new ArgumentNullException(nameof(rst.ServicePrincipalName));
            }

            var sname = rst.ServicePrincipalName.Split('/', '@');
            var tgt   = kdcRep.Ticket;

            var additionalTickets = new List <KrbTicket>();

            if (rst.KdcOptions.HasFlag(KdcOptions.EncTktInSkey) && rst.UserToUserTicket != null)
            {
                additionalTickets.Add(rst.UserToUserTicket);
            }

            if (!string.IsNullOrWhiteSpace(rst.S4uTarget) && rst.S4uTicket != null)
            {
                throw new InvalidOperationException(SR.Resource("S4uTargetTicketBothPresent"));
            }

            if (!string.IsNullOrWhiteSpace(rst.S4uTarget))
            {
                rst.KdcOptions |= KdcOptions.Forwardable;
            }

            if (rst.S4uTicket != null)
            {
                rst.KdcOptions |= KdcOptions.ConstrainedDelegation;

                additionalTickets.Add(rst.S4uTicket);
            }

            var config = rst.Configuration ?? Krb5Config.Default();

            var body = new KrbKdcReqBody
            {
                EType      = GetPreferredETypes(config.Defaults.DefaultTgsEncTypes, config.Defaults.AllowWeakCrypto).ToArray(),
                KdcOptions = rst.KdcOptions,
                Nonce      = GetNonce(),
                Realm      = rst.Realm,
                SName      = new KrbPrincipalName()
                {
                    Type = PrincipalNameType.NT_SRV_INST,
                    Name = sname
                },
                Till  = EndOfTime,
                CName = rst.CNameHint
            };

            if (additionalTickets.Count > 0)
            {
                body.AdditionalTickets = additionalTickets.ToArray();
            }

            var bodyChecksum = KrbChecksum.Create(
                body.Encode(),
                tgtSessionKey.AsKey(),
                KeyUsage.PaTgsReqChecksum
                );

            var tgtApReq = CreateApReq(kdcRep, tgtSessionKey, bodyChecksum, out sessionKey);

            var pacOptions = new KrbPaPacOptions
            {
                Flags = PacOptions.ResourceBasedConstrainedDelegation | PacOptions.Claims | PacOptions.BranchAware
            }.Encode();

            var paData = new List <KrbPaData>()
            {
                new KrbPaData
                {
                    Type  = PaDataType.PA_TGS_REQ,
                    Value = tgtApReq.EncodeApplication()
                },
                new KrbPaData
                {
                    Type  = PaDataType.PA_PAC_OPTIONS,
                    Value = pacOptions
                }
            };

            if (!string.IsNullOrWhiteSpace(rst.S4uTarget))
            {
                if (tgtSessionKey.EType == EncryptionType.RC4_HMAC_NT)
                {
                    paData.Add(new KrbPaData
                    {
                        Type  = PaDataType.PA_FOR_USER,
                        Value = EncodeS4ULegacyRequest(rst.S4uTarget, tgt.Realm, tgtSessionKey)
                    });
                }
                else
                {
                    paData.Add(new KrbPaData
                    {
                        Type  = PaDataType.PA_FOR_X509_USER,
                        Value = EncodeS4URequest(rst.S4uTarget, rst.S4uTargetCertificate, body.Nonce, tgt.Realm, sessionKey)
                    });
                }
            }

            var tgs = new KrbTgsReq
            {
                PaData = paData.ToArray(),
                Body   = body
            };

            return(tgs);
        }