Exemplo n.º 1
0
        public static KrbApReq CreateApReq(
            KrbKdcRep tgsRep,
            KerberosKey authenticatorKey,
            ApOptions options,
            out KrbAuthenticator authenticator
            )
        {
            var ticket = tgsRep.Ticket;

            authenticator = new KrbAuthenticator
            {
                CName          = tgsRep.CName,
                Realm          = ticket.Realm,
                SequenceNumber = KerberosConstants.GetNonce(),
                Subkey         = KrbEncryptionKey.Generate(authenticatorKey.EncryptionType),
                Checksum       = KrbChecksum.EncodeDelegationChecksum(new DelegationInfo())
            };

            KerberosConstants.Now(out authenticator.CTime, out authenticator.CuSec);

            var apReq = new KrbApReq
            {
                Ticket        = ticket,
                ApOptions     = options,
                Authenticator = KrbEncryptedData.Encrypt(
                    authenticator.EncodeApplication(),
                    authenticatorKey,
                    KeyUsage.ApReqAuthenticator
                    )
            };

            return(apReq);
        }
Exemplo n.º 2
0
        private static KrbApReq CreateApReq(KrbKdcRep kdcRep, KrbEncryptionKey tgtSessionKey, KrbChecksum checksum, out KrbEncryptionKey sessionKey)
        {
            var tgt = kdcRep.Ticket;

            var authenticator = new KrbAuthenticator
            {
                CName          = kdcRep.CName,
                Realm          = kdcRep.CRealm,
                SequenceNumber = KerberosConstants.GetNonce(),
                Checksum       = checksum
            };

            sessionKey           = KrbEncryptionKey.Generate(tgtSessionKey.EType);
            sessionKey.Usage     = KeyUsage.EncTgsRepPartSubSessionKey;
            authenticator.Subkey = sessionKey;

            KerberosConstants.Now(out authenticator.CTime, out authenticator.CuSec);

            var encryptedAuthenticator = KrbEncryptedData.Encrypt(
                authenticator.EncodeApplication(),
                tgtSessionKey.AsKey(),
                KeyUsage.PaTgsReqAuthenticator
                );

            var apReq = new KrbApReq
            {
                Ticket        = tgt,
                Authenticator = encryptedAuthenticator
            };

            return(apReq);
        }
Exemplo n.º 3
0
        private static KrbApReq CreateApReq(KrbKdcRep kdcRep, KrbEncryptionKey tgtSessionKey)
        {
            var tgt = kdcRep.Ticket;

            KerberosConstants.Now(out DateTimeOffset time, out int usec);

            var authenticator = new KrbAuthenticator
            {
                CName                      = kdcRep.CName,
                CTime                      = time,
                Cusec                      = usec,
                Realm                      = tgt.Realm,
                SequenceNumber             = KerberosConstants.GetNonce(),
                Subkey                     = tgtSessionKey,
                AuthenticatorVersionNumber = 5
            };

            var encryptedAuthenticator = KrbEncryptedData.Encrypt(
                authenticator.EncodeApplication(),
                tgtSessionKey.AsKey(),
                KeyUsage.PaTgsReqAuthenticator
                );

            var apReq = new KrbApReq
            {
                Ticket        = tgt,
                Authenticator = encryptedAuthenticator
            };

            return(apReq);
        }
Exemplo n.º 4
0
        public static KrbApReq CreateApReq(KrbKdcRep tgsRep, KerberosKey authenticatorKey, ApOptions options)
        {
            var ticket = tgsRep.Ticket;

            KerberosConstants.Now(out DateTimeOffset time, out int usec);

            var authenticator = new KrbAuthenticator
            {
                CName                      = tgsRep.CName,
                CTime                      = time,
                Cusec                      = usec,
                Realm                      = ticket.Realm,
                SequenceNumber             = KerberosConstants.GetNonce(),
                Subkey                     = null,
                AuthenticatorVersionNumber = 5
            };

            var apReq = new KrbApReq
            {
                Ticket        = ticket,
                ApOptions     = options,
                Authenticator = KrbEncryptedData.Encrypt(
                    authenticator.EncodeApplication(),
                    authenticatorKey,
                    KeyUsage.ApReqAuthenticator
                    )
            };

            return(apReq);
        }
Exemplo n.º 5
0
        public static KrbAsReq CreateAsReq(KerberosCredential credential, AuthenticationOptions options)
        {
            var kdcOptions = (KdcOptions)(options & ~AuthenticationOptions.AllAuthentication);

            var hostAddress = Environment.MachineName;

            var pacRequest = new KrbPaPacRequest
            {
                IncludePac = options.HasFlag(AuthenticationOptions.IncludePacRequest)
            };

            var padata = new List <KrbPaData>()
            {
                new KrbPaData
                {
                    Type  = PaDataType.PA_PAC_REQUEST,
                    Value = pacRequest.Encode()
                }
            };

            var asreq = new KrbAsReq()
            {
                MessageType = MessageType.KRB_AS_REQ,
                Body        = new KrbKdcReqBody
                {
                    Addresses = new[] {
                        new KrbHostAddress {
                            AddressType = AddressType.NetBios,
                            Address     = Encoding.ASCII.GetBytes(hostAddress.PadRight(16, ' '))
                        }
                    },
                    CName = KrbPrincipalName.FromString(
                        credential.UserName,
                        PrincipalNameType.NT_ENTERPRISE,
                        credential.Domain
                        ),
                    EType      = KerberosConstants.ETypes.ToArray(),
                    KdcOptions = kdcOptions,
                    Nonce      = KerberosConstants.GetNonce(),
                    RTime      = KerberosConstants.EndOfTime,
                    Realm      = credential.Domain,
                    SName      = new KrbPrincipalName
                    {
                        Type = PrincipalNameType.NT_SRV_INST,
                        Name = new[] { "krbtgt", credential.Domain }
                    },
                    Till = KerberosConstants.EndOfTime
                },
                PaData = padata.ToArray()
            };

            if (options.HasFlag(AuthenticationOptions.PreAuthenticate))
            {
                credential.TransformKdcReq(asreq);
            }

            return(asreq);
        }
Exemplo n.º 6
0
        public static KrbTgsReq CreateTgsReq(
            string spn,
            KrbEncryptionKey tgtSessionKey,
            KrbKdcRep kdcRep,
            KdcOptions options,
            KrbTicket user2UserTicket = null
            )
        {
            var tgtApReq = CreateApReq(kdcRep, tgtSessionKey);

            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.AsMemory()
                }
            };

            var tgt = kdcRep.Ticket;

            var sname = spn.Split('/', '@');

            var tgs = new KrbTgsReq
            {
                PaData = paData.ToArray(),
                Body   = new KrbKdcReqBody
                {
                    EType      = KerberosConstants.ETypes.ToArray(),
                    KdcOptions = options,
                    Nonce      = KerberosConstants.GetNonce(),
                    Realm      = tgt.Realm,
                    SName      = new KrbPrincipalName()
                    {
                        Type = PrincipalNameType.NT_SRV_HST,
                        Name = sname
                    },
                    Till = KerberosConstants.EndOfTime
                },
            };

            if (options.HasFlag(KdcOptions.EncTktInSkey) && user2UserTicket != null)
            {
                tgs.Body.AdditionalTickets = new[] {
                    user2UserTicket
                };
            }

            return(tgs);
        }
Exemplo n.º 7
0
        public static KrbAsReq CreateAsReq(KerberosCredential credential, AuthenticationOptions options)
        {
            if (credential == null)
            {
                throw new ArgumentNullException(nameof(credential));
            }

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

            var kdcOptions = (KdcOptions)(options & ~AuthenticationOptions.AllAuthentication);

            var pacRequest = new KrbPaPacRequest
            {
                IncludePac = options.HasFlag(AuthenticationOptions.IncludePacRequest)
            };

            var padata = new List <KrbPaData>()
            {
                new KrbPaData
                {
                    Type  = PaDataType.PA_PAC_REQUEST,
                    Value = pacRequest.Encode()
                }
            };

            var asreq = new KrbAsReq()
            {
                Body = new KrbKdcReqBody
                {
                    Addresses  = IncludeAddresses(config),
                    CName      = ExtractCName(credential),
                    EType      = KerberosConstants.GetPreferredETypes(config.Defaults.DefaultTicketEncTypes).ToArray(),
                    KdcOptions = kdcOptions,
                    Nonce      = KerberosConstants.GetNonce(),
                    RTime      = CalculateRenewTime(kdcOptions, config),
                    Realm      = credential.Domain,
                    SName      = new KrbPrincipalName
                    {
                        Type = PrincipalNameType.NT_SRV_INST,
                        Name = new[] { "krbtgt", credential.Domain }
                    },
                    Till = CalculateExpirationTime(config)
                },
                PaData = padata.ToArray()
            };

            if (options.HasFlag(AuthenticationOptions.PreAuthenticate))
            {
                credential.TransformKdcReq(asreq);
            }

            return(asreq);
        }
Exemplo n.º 8
0
        public static KrbApReq CreateApReq(
            KrbKdcRep tgsRep,
            KerberosKey authenticatorKey,
            RequestServiceTicket rst,
            out KrbAuthenticator authenticator
            )
        {
            if (tgsRep == null)
            {
                throw new ArgumentNullException(nameof(tgsRep));
            }

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

            var ticket = tgsRep.Ticket;

            authenticator = new KrbAuthenticator
            {
                CName          = tgsRep.CName,
                Realm          = ticket.Realm,
                SequenceNumber = KerberosConstants.GetNonce(),
                Subkey         = KrbEncryptionKey.Generate(authenticatorKey.EncryptionType),
                Checksum       = KrbChecksum.EncodeDelegationChecksum(new DelegationInfo(rst))
            };

            KerberosConstants.Now(out DateTimeOffset ctime, out int usec);

            authenticator.CTime = ctime;
            authenticator.CuSec = usec;

            var apReq = new KrbApReq
            {
                Ticket        = ticket,
                ApOptions     = rst.ApOptions,
                Authenticator = KrbEncryptedData.Encrypt(
                    authenticator.EncodeApplication(),
                    authenticatorKey,
                    KeyUsage.ApReqAuthenticator
                    )
            };

            return(apReq);
        }
Exemplo n.º 9
0
        public static KrbAsReq CreateAsReq(KerberosCredential credential, AuthenticationOptions options)
        {
            var kdcOptions = (KdcOptions)(options & ~AuthenticationOptions.AllAuthentication);

            var hostAddress = Environment.MachineName;

            var padata = new List <KrbPaData>()
            {
                new KrbPaData
                {
                    Type  = PaDataType.PA_PAC_REQUEST,
                    Value = new KrbPaPacRequest
                    {
                        IncludePac = options.HasFlag(AuthenticationOptions.IncludePacRequest)
                    }.Encode().AsMemory()
                }
            };

            if (options.HasFlag(AuthenticationOptions.PreAuthenticate))
            {
                KerberosConstants.Now(out DateTimeOffset timestamp, out int usec);

                var ts = new KrbPaEncTsEnc
                {
                    PaTimestamp = timestamp,
                    PaUSec      = usec
                };

                var tsEncoded = ts.Encode().AsMemory();

                KrbEncryptedData encData = KrbEncryptedData.Encrypt(
                    tsEncoded,
                    credential.CreateKey(),
                    KeyUsage.PaEncTs
                    );

                padata.Add(new KrbPaData
                {
                    Type  = PaDataType.PA_ENC_TIMESTAMP,
                    Value = encData.Encode().AsMemory()
                });
            }

            var asreq = new KrbAsReq()
            {
                MessageType = MessageType.KRB_AS_REQ,
                Body        = new KrbKdcReqBody
                {
                    Addresses = new[] {
                        new KrbHostAddress {
                            AddressType = AddressType.NetBios,
                            Address     = Encoding.ASCII.GetBytes(hostAddress.PadRight(16, ' '))
                        }
                    },
                    CName = new KrbPrincipalName
                    {
                        Name = new[] { $"{credential.UserName}@{credential.Domain}" },
                        Type = PrincipalNameType.NT_ENTERPRISE
                    },
                    EType      = KerberosConstants.ETypes.ToArray(),
                    KdcOptions = kdcOptions,
                    Nonce      = KerberosConstants.GetNonce(),
                    RTime      = KerberosConstants.EndOfTime,
                    Realm      = credential.Domain,
                    SName      = new KrbPrincipalName
                    {
                        Type = PrincipalNameType.NT_SRV_INST,
                        Name = new[] { "krbtgt", credential.Domain }
                    },
                    Till = KerberosConstants.EndOfTime
                },
                PaData = padata.ToArray()
            };

            return(asreq);
        }
Exemplo n.º 10
0
        public static async Task <T> GenerateServiceTicket <T>(ServiceTicketRequest request)
            where T : KrbKdcRep, new()
        {
            var sessionKey = KrbEncryptionKey.Generate(request.ServicePrincipalKey.EncryptionType);

            var authz = await GenerateAuthorizationData(request.Principal, request.ServicePrincipalKey);

            var cname = KrbPrincipalName.FromPrincipal(request.Principal, realm: request.RealmName);

            var flags = request.Flags;

            if (request.Principal.SupportedPreAuthenticationTypes.Any())
            {
                // This is not strictly an accurate way of detecting if the user was pre-authenticated.
                // If pre-auth handlers are registered and the principal has PA-Types available, a request
                // will never make it to this point without getting authenticated.
                //
                // However if no pre-auth handlers are registered, then the PA check is skipped
                // and this isn't technically accurate anymore.
                //
                // TODO: this should tie into the make-believe policy check being used in the
                // auth handler section

                flags |= TicketFlags.EncryptedPreAuthentication | TicketFlags.PreAuthenticated;
            }

            var addresses = request.Addresses;

            if (addresses == null)
            {
                addresses = new KrbHostAddress[0];
            }

            var encTicketPart = new KrbEncTicketPart()
            {
                CName             = cname,
                Key               = sessionKey,
                AuthTime          = request.Now,
                StartTime         = request.StartTime,
                EndTime           = request.EndTime,
                CRealm            = request.RealmName,
                Flags             = flags,
                AuthorizationData = authz.ToArray(),
                CAddr             = addresses.ToArray(),
                Transited         = new KrbTransitedEncoding()
            };

            if (flags.HasFlag(TicketFlags.Renewable))
            {
                // RenewTill should never increase if it was set previously even if this is a renewal pass

                encTicketPart.RenewTill = request.RenewTill;
            }

            var ticket = new KrbTicket()
            {
                Realm = request.RealmName,
                SName = KrbPrincipalName.FromPrincipal(
                    request.ServicePrincipal,
                    PrincipalNameType.NT_SRV_INST,
                    request.RealmName
                    ),
                EncryptedPart = KrbEncryptedData.Encrypt(
                    encTicketPart.EncodeApplication(),
                    request.ServicePrincipalKey,
                    KeyUsage.Ticket
                    )
            };

            KrbEncKdcRepPart encKdcRepPart;

            if (typeof(T) == typeof(KrbAsRep))
            {
                encKdcRepPart = new KrbEncAsRepPart();
            }
            else if (typeof(T) == typeof(KrbTgsRep))
            {
                encKdcRepPart = new KrbEncTgsRepPart();
            }
            else
            {
                throw new InvalidOperationException($"Requested Service Ticket type is neither KrbAsRep nor KrbTgsRep. Type: {typeof(T)}");
            }

            encKdcRepPart.AuthTime      = encTicketPart.AuthTime;
            encKdcRepPart.StartTime     = encTicketPart.StartTime;
            encKdcRepPart.EndTime       = encTicketPart.EndTime;
            encKdcRepPart.RenewTill     = encTicketPart.RenewTill;
            encKdcRepPart.KeyExpiration = request.Principal.Expires;
            encKdcRepPart.Realm         = request.RealmName;
            encKdcRepPart.SName         = ticket.SName;
            encKdcRepPart.Flags         = encTicketPart.Flags;
            encKdcRepPart.CAddr         = encTicketPart.CAddr;
            encKdcRepPart.Key           = sessionKey;
            encKdcRepPart.Nonce         = KerberosConstants.GetNonce();
            encKdcRepPart.LastReq       = new[] { new KrbLastReq {
                                                      Type = 0, Value = request.Now
                                                  } };
            encKdcRepPart.EncryptedPaData = new KrbMethodData
            {
                MethodData = new[]
                {
                    new KrbPaData
                    {
                        Type  = PaDataType.PA_SUPPORTED_ETYPES,
                        Value = request.Principal.SupportedEncryptionTypes.AsReadOnly(littleEndian: true).AsMemory()
                    }
                }
            };

            encKdcRepPart.EncodeApplication();

            var rep = new T
            {
                CName       = cname,
                CRealm      = request.RealmName,
                MessageType = MessageType.KRB_AS_REP,
                Ticket      = ticket,
                EncPart     = KrbEncryptedData.Encrypt(
                    encKdcRepPart.EncodeApplication(),
                    request.EncryptedPartKey,
                    encKdcRepPart.KeyUsage
                    )
            };

            return(rep);
        }
Exemplo n.º 11
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);
        }
Exemplo n.º 12
0
        private static void Concat(Memory <byte> checksumData, ref int position, ref string value)
        {
            KerberosConstants.UnicodeStringToUtf8(value).CopyTo(checksumData.Span.Slice(position, value.Length));

            position += value.Length;
        }
Exemplo n.º 13
0
 public void StampServerTime()
 {
     KerberosConstants.Now(out this.STime, out this.Susc);
 }