Ejemplo n.º 1
0
        public static KrbCred WrapTicket(KrbTicket ticket, KrbEncTicketPart encTicketPart)
        {
            if (ticket is null)
            {
                throw new ArgumentNullException(nameof(ticket));
            }

            if (encTicketPart is null)
            {
                throw new ArgumentNullException(nameof(encTicketPart));
            }

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

            var encPart = new KrbEncKrbCredPart
            {
                Timestamp  = timestamp,
                USec       = usec,
                TicketInfo = new[]
                {
                    new KrbCredInfo
                    {
                        Key       = encTicketPart.Key,
                        AuthTime  = encTicketPart.AuthTime,
                        EndTime   = encTicketPart.EndTime,
                        Flags     = encTicketPart.Flags,
                        PName     = encTicketPart.CName,
                        Realm     = encTicketPart.CRealm,
                        RenewTill = encTicketPart.RenewTill,
                        SName     = ticket.SName,
                        SRealm    = ticket.Realm,
                        StartTime = encTicketPart.StartTime,
                    }
                }
            };

            var cred = new KrbCred
            {
                EncryptedPart = new KrbEncryptedData {
                    Cipher = encPart.EncodeApplication()
                },
                Tickets = new[] { ticket },
            };

            return(cred);
        }
Ejemplo n.º 2
0
        private static KrbEncTicketPart CreateEncTicketPart(
            ServiceTicketRequest request,
            KrbAuthorizationData[] authorizationDatas,
            KrbEncryptionKey sessionKey)
        {
            var cname = CreateCNameForTicket(request);

            var flags = request.Flags;

            if (request.PreAuthenticationData?.Any(r => r.Type == PaDataType.PA_REQ_ENC_PA_REP) ?? false)
            {
                flags |= TicketFlags.EncryptedPreAuthentication;
            }

            var addresses = request.Addresses;

            if (addresses == null)
            {
                addresses = Array.Empty <KrbHostAddress>();
            }

            var encTicketPart = new KrbEncTicketPart()
            {
                CName             = cname,
                Key               = sessionKey,
                AuthTime          = request.Now,
                StartTime         = request.StartTime,
                EndTime           = request.EndTime,
                CRealm            = request.RealmName,
                Flags             = flags,
                AuthorizationData = authorizationDatas,
                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;
            }

            return(encTicketPart);
        }
Ejemplo n.º 3
0
 public static KrbCred WrapTicket(KrbTicket ticket, KrbEncTicketPart encTicketPart)
 {
     return(WrapTicket(
                ticket,
                new KrbCredInfo
     {
         Key = encTicketPart.Key,
         AuthTime = encTicketPart.AuthTime,
         EndTime = encTicketPart.EndTime,
         Flags = encTicketPart.Flags,
         PName = encTicketPart.CName,
         Realm = encTicketPart.CRealm,
         RenewTill = encTicketPart.RenewTill,
         SName = ticket.SName,
         SRealm = ticket.Realm,
         StartTime = encTicketPart.StartTime,
     }
                ));
 }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        private static ServiceTicketRequest GenerateServiceTicket <T>(
            ServiceTicketRequest request,
            out KrbEncTicketPart encTicketPart,
            out KrbTicket ticket,
            out KrbEncKdcRepPart encKdcRepPart,
            out KeyUsage keyUsage,
            out MessageType messageType
            )
            where T : KrbKdcRep, new()
        {
            if (request.Principal == null)
            {
                throw new InvalidOperationException("A Principal identity must be provided");
            }

            if (request.ServicePrincipal == null)
            {
                throw new InvalidOperationException("A service principal must be provided");
            }

            if (request.ServicePrincipalKey == null)
            {
                throw new InvalidOperationException("A service principal key must be provided");
            }

            var authz = GenerateAuthorizationData(request);

            var sessionKey = KrbEncryptionKey.Generate(request.PreferredClientEType ?? request.ServicePrincipalKey.EncryptionType);

            encTicketPart = CreateEncTicketPart(request, authz.ToArray(), sessionKey);
            bool appendRealm = false;

            if (request.ServicePrincipal.PrincipalName.Contains("/"))
            {
                appendRealm = true;
            }

            ticket = new KrbTicket()
            {
                Realm = request.RealmName,
                SName = KrbPrincipalName.FromPrincipal(
                    request.ServicePrincipal,
                    PrincipalNameType.NT_SRV_INST,
                    appendRealm ? null : request.RealmName
                    ),
                EncryptedPart = KrbEncryptedData.Encrypt(
                    encTicketPart.EncodeApplication(),
                    request.ServicePrincipalKey,
                    KeyUsage.Ticket
                    )
            };
            if (typeof(T) == typeof(KrbAsRep))
            {
                encKdcRepPart = new KrbEncAsRepPart();
                keyUsage      = KeyUsage.EncAsRepPart;
                messageType   = MessageType.KRB_AS_REP;
            }
            else if (typeof(T) == typeof(KrbTgsRep))
            {
                encKdcRepPart = new KrbEncTgsRepPart();
                keyUsage      = request.EncryptedPartKey?.Usage ?? KeyUsage.EncTgsRepPartSessionKey;
                messageType   = MessageType.KRB_TGS_REP;
            }
            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         = request.Nonce;
            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()
                    }
                }
            };
            return(request);
        }
Ejemplo n.º 6
0
        public static async Task <T> GenerateServiceTicket <T>(ServiceTicketRequest request)
            where T : KrbKdcRep, new()
        {
            if (request.EncryptedPartKey == null)
            {
                throw new ArgumentException("A session key must be provided to encrypt the response", nameof(request.EncryptedPartKey));
            }

            if (request.Principal == null)
            {
                throw new ArgumentException("A Principal identity must be provided", nameof(request.Principal));
            }

            if (request.ServicePrincipal == null)
            {
                throw new ArgumentException("A service principal must be provided", nameof(request.ServicePrincipal));
            }

            if (request.ServicePrincipalKey == null)
            {
                throw new ArgumentException("A service principal key must be provided", nameof(request.ServicePrincipalKey));
            }

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

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

            var sessionKey = KrbEncryptionKey.Generate(request.ServicePrincipalKey.EncryptionType);

            var flags = request.Flags;

            if (request.PreAuthenticationData?.Any(r => r.Type == PaDataType.PA_REQ_ENC_PA_REP) ?? false)
            {
                flags |= TicketFlags.EncryptedPreAuthentication;
            }

            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         = request.Nonce;
            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()
                    }
                }
            };

            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);
        }