private ReadOnlyMemory <byte> PreAuthFailed(KerberosValidationException kex, IKerberosPrincipal principal)
        {
            var err = new KrbError
            {
                ErrorCode = KerberosErrorCode.KDC_ERR_PREAUTH_FAILED,
                EText     = kex.Message,
                Realm     = RealmService.Name,
                SName     = KrbPrincipalName.FromPrincipal(principal)
            };

            return(err.EncodeApplication());
        }
Example #2
0
        private ReadOnlyMemory <byte> PreAuthFailed(PreAuthenticationContext context)
        {
            var err = new KrbError
            {
                ErrorCode = KerberosErrorCode.KDC_ERR_PREAUTH_FAILED,
                EText     = context.Failure.Message,
                Realm     = this.RealmService.Name,
                SName     = KrbPrincipalName.FromPrincipal(context.Principal)
            };

            return(err.EncodeApplication());
        }
        private ReadOnlyMemory <byte> RequirePreAuth(IEnumerable <KrbPaData> preAuthRequests, IKerberosPrincipal principal)
        {
            var err = new KrbError
            {
                ErrorCode = KerberosErrorCode.KDC_ERR_PREAUTH_REQUIRED,
                EText     = "",
                Realm     = RealmService.Name,
                SName     = KrbPrincipalName.FromPrincipal(principal),
                EData     = new KrbMethodData
                {
                    MethodData = preAuthRequests.ToArray()
                }.Encode().AsMemory()
            };

            return(err.EncodeApplication());
        }
Example #4
0
        private ReadOnlyMemory <byte> RequirePreAuth(PreAuthenticationContext context)
        {
            this.logger.LogTrace("AS-REQ requires pre-auth for user {User}", context.Principal.PrincipalName);

            var err = new KrbError
            {
                ErrorCode = KerberosErrorCode.KDC_ERR_PREAUTH_REQUIRED,
                EText     = string.Empty,
                Realm     = this.RealmService.Name,
                SName     = KrbPrincipalName.FromPrincipal(context.Principal),
                EData     = new KrbMethodData
                {
                    MethodData = context.PaData.ToArray()
                }.Encode()
            };

            return(err.EncodeApplication());
        }
        /// <summary>
        /// Executes the primary validation process for the pre-auth data.
        /// </summary>
        /// <param name="asReq">The message to validate</param>
        /// <param name="context">The current context of the request</param>
        /// <returns>Optionally returns PA-Data that needs to be sent to the client otherwise returns null.</returns>
        public override KrbPaData Validate(KrbKdcReq asReq, PreAuthenticationContext context)
        {
            // First we authenticate the incoming request
            //
            // 1. Get the ApReq (TGT) from the PA-Data of the request
            // 2. Decrypt the TGT and extract the client calling identity

            if (context.EvidenceTicketIdentity == null)
            {
                // we wouldn't ever hit this in the normal case, but we could hit it
                // if a referral came in from a realm we don't recognize or don't trust

                throw new KerberosProtocolException(KerberosErrorCode.KDC_ERR_S_PRINCIPAL_UNKNOWN);
            }

            var evidenceSName = KrbPrincipalName.FromPrincipal(context.EvidenceTicketIdentity, PrincipalNameType.NT_SRV_INST);

            if (!evidenceSName.IsKrbtgt())
            {
                // spec-wise this isn't exactly correct as the authz ticket might be for renewal
                // we will deviate from the spec because that's how other KDCs operate today
                // KDC_ERR_PADATA_TYPE_NOSUPP is the closest error to indicate the way you
                // authenticated the request is not something we're willing to accept

                throw new KerberosProtocolException(KerberosErrorCode.KDC_ERR_PADATA_TYPE_NOSUPP);
            }

            // we need to validate that the evidence ticket is the KDC service (krbtgt)
            // it might either be our KDC that issued it, or a KDC from another realm (referral)
            // if it's ours it'll match our service name (krbtgt), and it'll decrypt with our key
            // if it's a referral it'll match a trusted realm's name and decrypt with their key
            // if it's a referral then the incoming identity will also need to be transposed

            // no matter what we only ever want the TGS service ticket
            // it might belong to another realm, but that's ok because it could be a referral

            // it is a krbtgt service identity we recognize
            // it could be ours, or a referral from a trusted realm
            // in either case we can and will validate the ticket and
            // extract the user principal from within the krbtgt ticket

            var krbtgtKey = context.EvidenceTicketIdentity.RetrieveLongTermCredential();

            if (krbtgtKey == null)
            {
                // since the key comes from caller-implemented code we
                // should check to make sure they gave us a usable key

                throw new KerberosProtocolException(KerberosErrorCode.KDC_ERR_ETYPE_NOSUPP);
            }

            if (context.EvidenceTicketKey == null)
            {
                context.EvidenceTicketKey = krbtgtKey;
            }

            var state = context.GetState <TgsState>(PaDataType.PA_TGS_REQ);

            if (state.DecryptedApReq == null)
            {
                state.DecryptedApReq = DecryptApReq(state.ApReq, context.EvidenceTicketKey);
            }

            context.EncryptedPartKey = state.DecryptedApReq.SessionKey;
            context.Ticket           = state.DecryptedApReq.Ticket;

            return(null);
        }