public async Task <ApplicationSessionContext> GetServiceTicket(RequestServiceTicket rst, CancellationToken cancellation) { rst.S4uTarget = null; rst.S4uTicket = this.krbApReq.EncryptedTicket; rst.KdcOptions |= KdcOptions.CNameInAdditionalTicket; bool retried = false; while (true) { try { return(await client.GetServiceTicket(rst, cancellation)); } catch (InvalidOperationException) { if (retried) { break; } await client.Authenticate(this.credential); retried = true; } } return(null); }
private static async Task RequestTickets(string user, string password, string overrideKdc) { var kerbCred = new KerberosPasswordCredential(user, password); KerberosClient client = new KerberosClient(overrideKdc); await client.Authenticate(kerbCred); var ticket = await client.GetServiceTicket( "host/appservice.corp.identityintervention.com", ApOptions.MutualRequired ); var encoded = ticket.EncodeApplication().ToArray(); var authenticator = new KerberosAuthenticator( new KeyTable( new KerberosKey( "P@ssw0rd!", principalName: new PrincipalName( PrincipalNameType.NT_PRINCIPAL, "CORP.IDENTITYINTERVENTION.com", new[] { "host/appservice.corp.identityintervention.com" } ), saltType: SaltType.ActiveDirectoryUser ) ) ); var validated = (KerberosIdentity)await authenticator.Authenticate(encoded); DumpClaims(validated); }
private static async Task RequestAndValidateTickets( string user, string password, string overrideKdc, string s4u = null, bool encodeNego = false, bool caching = false, bool includePac = true ) { var kerbCred = new KerberosPasswordCredential(user, password); using (var client = new KerberosClient(overrideKdc) { CacheServiceTickets = caching }) { if (!includePac) { client.AuthenticationOptions &= ~AuthenticationOptions.IncludePacRequest; } await client.Authenticate(kerbCred); var spn = FakeAppServiceSpn; var ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = spn, ApOptions = ApOptions.MutualRequired } ); await ValidateTicket(ticket, includePac : includePac); await client.RenewTicket(); ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = FakeAppServiceSpn, ApOptions = ApOptions.MutualRequired } ); await ValidateTicket(ticket, encodeNego, includePac : includePac); ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = FakeAppServiceSpn, ApOptions = ApOptions.MutualRequired, S4uTarget = s4u } ); await ValidateTicket(ticket, includePac : includePac); } }
public async Task RequestTgt(string algo) { var cred = new KerberosPasswordCredential(algo + user, password); var client = new KerberosClient($"{overrideKdc}:{port}"); for (var i = 0; i < AuthenticationAttempts; i++) { await client.Authenticate(cred); } }
public async Task ClientConnectsToServer_Withtimeout() { var port = NextPort(); var client = new KerberosClient($"127.0.0.1:{port}") { ConnectTimeout = TimeSpan.FromMilliseconds(1) }; await client.Authenticate(new KerberosPasswordCredential("test", "test", "test")); }
private static async Task RequestAndValidateTickets( string user, string password, string overrideKdc, string s4u = null, bool encodeNego = false, bool caching = false ) { var kerbCred = new KerberosPasswordCredential(user, password); KerberosClient client = new KerberosClient(overrideKdc) { CacheServiceTickets = caching }; await client.Authenticate(kerbCred); var spn = "host/appservice.corp.identityintervention.com"; var ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = spn, ApOptions = ApOptions.MutualRequired } ); await ValidateTicket(ticket); await client.RenewTicket(); ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = "host/appservice.corp.identityintervention.com", ApOptions = ApOptions.MutualRequired } ); await ValidateTicket(ticket, encodeNego); ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = "host/appservice.corp.identityintervention.com", ApOptions = ApOptions.MutualRequired, S4uTarget = s4u } ); await ValidateTicket(ticket); }
private static async Task RequestTickets(string user, string password, string overrideKdc, string s4u, string spn) { var kerbCred = new KerberosPasswordCredential(user, password); using (KerberosClient client = new KerberosClient(overrideKdc)) { await client.Authenticate(kerbCred); spn = spn ?? "host/appservice.corp.identityintervention.com"; KrbTicket s4uTicket = null; if (!string.IsNullOrWhiteSpace(s4u)) { var s4uSelf = await client.GetServiceTicket( kerbCred.UserName, ApOptions.MutualRequired, s4u : s4u ); s4uTicket = s4uSelf.Ticket; } var ticket = await client.GetServiceTicket( spn, ApOptions.MutualRequired, s4uTicket : s4uTicket ); var encoded = ticket.EncodeApplication().ToArray(); var authenticator = new KerberosAuthenticator( new KeyTable( new KerberosKey( "P@ssw0rd!", principalName: new PrincipalName( PrincipalNameType.NT_PRINCIPAL, "CORP.IDENTITYINTERVENTION.com", new[] { spn } ), saltType: SaltType.ActiveDirectoryUser ) ) ); var validated = (KerberosIdentity)await authenticator.Authenticate(encoded); DumpClaims(validated); } }
public async Task U2U() { var port = new Random().Next(20000, 40000); var options = new ListenerOptions { ListeningOn = new IPEndPoint(IPAddress.Loopback, port), DefaultRealm = "corp2.identityintervention.com".ToUpper(), IsDebug = true, RealmLocator = realm => LocateRealm(realm), ReceiveTimeout = TimeSpan.FromHours(1) }; KdcServiceListener listener = new KdcServiceListener(options); _ = listener.Start(); var kerbClientCred = new KerberosPasswordCredential("*****@*****.**", "P@ssw0rd!"); var client = new KerberosClient($"127.0.0.1:{port}"); await client.Authenticate(kerbClientCred); var kerbServerCred = new KerberosPasswordCredential("*****@*****.**", "P@ssw0rd!"); var server = new KerberosClient($"127.0.0.1:{port}"); await server.Authenticate(kerbClientCred); var serverEntry = await server.Cache.Get <KerberosClientCacheEntry>($"krbtgt/{server.DefaultDomain}"); var serverTgt = serverEntry.Ticket.Ticket; var apReq = await client.GetServiceTicket("host/u2u", ApOptions.MutualRequired | ApOptions.UseSessionKey, u2uServerTicket : serverTgt); Assert.IsNotNull(apReq); var decrypted = new DecryptedKrbApReq(apReq); Assert.IsNull(decrypted.Ticket); decrypted.Decrypt(serverEntry.SessionKey.AsKey()); decrypted.Validate(ValidationActions.All); Assert.IsNotNull(decrypted.Ticket); Assert.AreEqual("host/u2u/CORP.IDENTITYINTERVENTION.COM", decrypted.SName.FullyQualifiedName); listener.Stop(); }
public async Task RequestServiceTicket() { var kerbCred = new KerberosPasswordCredential(user, password); var client = new KerberosClient($"{overrideKdc}:{port}"); await client.Authenticate(kerbCred); for (var i = 0; i < AuthenticationAttempts; i++) { await client.GetServiceTicket( "host/appservice.corp.identityintervention.com", ApOptions.MutualRequired ); } }
static async Task <int> Main(string[] args) { var getTicketCommand = new Command("get-ticket") { new Option <string>( "--kdc", description: "Key Destribution Center (KDC). Try AD domain name if you don't know this value - will usually work") { Required = true }, new Option <string>( "--user", description: "Kerberos client principal. Ex. [email protected]") { Required = true }, new Option <string>( "--password", "Password for the client principal") { Required = true }, new Option <string>( "--spn", "Destination service account or SPN. Ex http/myservice.domain.com") { Required = true } }; getTicketCommand.Handler = CommandHandler.Create <string, string, string, string>(async(kdc, user, password, spn) => { var client = new KerberosClient(kdc); var kerbCred = new KerberosPasswordCredential(user, password); await client.Authenticate(kerbCred); var ticket = await client.GetServiceTicket(spn); var ticket64 = Convert.ToBase64String(ticket.EncodeApplication().ToArray()); Console.WriteLine(ticket64); }); var rootCommand = new RootCommand(); rootCommand.AddCommand(getTicketCommand); return(await rootCommand.InvokeAsync(args)); }
public void RequestTgt() { TcpKerberosTransport.MaxPoolSize = this.ConcurrentRequests * 2; if (this.credential == null) { this.credential = Creds.GetOrAdd(this.AlgorithmType, a => new KerberosPasswordCredential(a + this.user, this.password)); } var requestCounter = 0; try { Task.WaitAll(Enumerable.Range(0, this.ConcurrentRequests).Select(taskNum => Task.Run(async() => { var client = new KerberosClient(); client.Transports.OfType <UdpKerberosTransport>().FirstOrDefault().Enabled = false; client.Transports.OfType <HttpsKerberosTransport>().FirstOrDefault().Enabled = false; client.PinKdc(this.credential.Domain, $"{this.overrideKdc}:{this.Port}"); for (var i = 0; i < this.AuthenticationAttempts; i++) { try { await client.Authenticate(this.credential); Interlocked.Increment(ref Successes); if (this.DisplayProgress) { CountItOut(ref requestCounter); } } catch (Exception) { } } })).ToArray()); } catch { } }
public async Task RequestServiceTicket(string algo) { var kerbCred = new KerberosPasswordCredential(algo + this.user, this.password); using (var client = new KerberosClient()) { client.PinKdc(kerbCred.Domain, $"{this.overrideKdc}:{this.port}"); await client.Authenticate(kerbCred); for (var i = 0; i < this.AuthenticationAttempts; i++) { await client.GetServiceTicket( "host/appservice.corp.identityintervention.com", ApOptions.MutualRequired ); } } }
public void RequestTgt() { var requestCounter = 0; Task.WaitAll(Enumerable.Range(0, ConcurrentRequests).Select(taskNum => Task.Run(async() => { var client = new KerberosClient($"{overrideKdc}:{Port}"); for (var i = 0; i < AuthenticationAttempts; i++) { await client.Authenticate(credential); if (DisplayProgress) { CountItOut(ref requestCounter); } } })).ToArray()); }
public async Task E2E_U2U() { var port = NextPort(); using (var listener = StartListener(port)) { var kerbClientCred = new KerberosPasswordCredential(AdminAtCorpUserName, FakeAdminAtCorpPassword); var kerbServerCred = new KerberosPasswordCredential("*****@*****.**", FakeAdminAtCorpPassword); using (var client = new KerberosClient($"127.0.0.1:{port}")) using (var server = new KerberosClient($"127.0.0.1:{port}")) { await client.Authenticate(kerbClientCred); await server.Authenticate(kerbClientCred); var serverEntry = await server.Cache.Get <KerberosClientCacheEntry>($"krbtgt/{server.DefaultDomain}"); var serverTgt = serverEntry.Ticket.Ticket; var apReq = await client.GetServiceTicket("host/u2u", ApOptions.MutualRequired | ApOptions.UseSessionKey, u2uServerTicket : serverTgt); Assert.IsNotNull(apReq); var decrypted = new DecryptedKrbApReq(apReq); Assert.IsNull(decrypted.Ticket); decrypted.Decrypt(serverEntry.SessionKey.AsKey()); decrypted.Validate(ValidationActions.All); Assert.IsNotNull(decrypted.Ticket); Assert.AreEqual("host/[email protected]", decrypted.SName.FullyQualifiedName); } listener.Stop(); } }
public async Task ClientConnectsToServer_WithTimeout() { var port = NextPort(); using (var client = new KerberosClient() { ConnectTimeout = TimeSpan.FromMilliseconds(1) }) { client.Configuration.Defaults.DnsLookupKdc = false; client.PinKdc("test", $"127.0.0.1:{port}"); try { await client.Authenticate(new KerberosPasswordCredential("test", "test", "test")); } catch (AggregateException agg) { throw agg.InnerExceptions.First(); } } }
public void RequestTgt() { var requestCounter = 0; Task.WaitAll(Enumerable.Range(0, ConcurrentRequests).Select(taskNum => Task.Run(async() => { var algo = Algorithms[random.Next(0, Algorithms.Length - 1)]; var cred = Creds.GetOrAdd(algo, a => new KerberosPasswordCredential(a + user, password)); var client = new KerberosClient($"{overrideKdc}:{Port}"); for (var i = 0; i < AuthenticationAttempts; i++) { await client.Authenticate(cred); if (DisplayProgress) { CountItOut(ref requestCounter); } } })).ToArray()); }
private static async Task RequestAndValidateTickets(string user, string password, string overrideKdc) { var kerbCred = new KerberosPasswordCredential(user, password); KerberosClient client = new KerberosClient(overrideKdc); await client.Authenticate(kerbCred); var ticket = await client.GetServiceTicket( "host/appservice.corp.identityintervention.com", ApOptions.MutualRequired ); await ValidateTicket(ticket); await client.RenewTicket(); ticket = await client.GetServiceTicket( "host/appservice.corp.identityintervention.com", ApOptions.MutualRequired ); await ValidateTicket(ticket); }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app) { var whitelist = app.ApplicationServices.GetRequiredService <IWhitelist>(); var features = app.ServerFeatures.ToArray(); app.MapWhen(context => context.Request.HttpContext.Connection.LocalPort > 10000 , map => { map.Use(async(ctx, next) => { var proxyMap = ctx.RequestServices.GetService <ProxyMap>(); if (!proxyMap.Entries.TryGetValue(ctx.Connection.LocalPort, out var proxySettings)) { await ctx.Response.WriteAsync("No proxy settings found for this port mapping"); return; } var config = ctx.RequestServices.GetRequiredService <IConfiguration>(); var client = new KerberosClient(config.GetValue <string>("Kerberos:Kdc")); var kerbCred = new KerberosPasswordCredential(proxySettings.ClientLogin, proxySettings.ClientPassword); await client.Authenticate(kerbCred); var kerberosTicket = await client.GetServiceTicket(proxySettings.TargetSpn); ctx.Items["KerberosTicket"] = Convert.ToBase64String(kerberosTicket.EncodeApplication().ToArray()); ctx.Items["ProxySettings"] = proxySettings; await next(); }); map.RunProxy(async context => { var kerberosTicket = (string)context.Items["KerberosTicket"]; var proxySettings = (ProxyMapEntry)context.Items["ProxySettings"]; var proxyRequest = context.ForwardTo(proxySettings.TargetUrl); proxyRequest.HttpContext.Request.Headers.Add("Authorization", $"Negotiate {kerberosTicket}"); return(await proxyRequest.Send()); }); }); app.MapWhen(context => context.Request.HttpContext.Connection.LocalPort < 10000 , reverseProxy => { reverseProxy.UseAuthentication(); reverseProxy.Use(async(context, next) => { if (!context.User.Identity.IsAuthenticated) { if (whitelist.IsWhitelisted(context.Request)) { _logger.LogDebug($"Allowing passthrough for whitelisted request {context.Request.Path}"); } else { var authResult = await context.AuthenticateAsync(SpnegoAuthenticationDefaults.AuthenticationScheme); if (authResult.Succeeded) { _logger.LogDebug($"User {authResult.Principal.Identity.Name} successfully logged in"); await context.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, authResult.Principal); context.User = authResult.Principal; } else { _logger.LogDebug("User authentication failed, issuing WWW-Authenticate challenge"); await context.ChallengeAsync(SpnegoAuthenticationDefaults.AuthenticationScheme , new AuthenticationProperties()); return; } } } await next(); }); reverseProxy.RunProxy(async context => { HttpResponseMessage response; if (!context.Request.Headers.TryGetForwardAddress(out var forwardTo)) { response = new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent($"Required header {Constants.X_CF_Forwarded_Url} not present in the request") }; _logger.LogDebug($"Received request without {Constants.X_CF_Forwarded_Url} header"); return(response); } var forwardContext = context.ForwardTo(forwardTo); forwardContext.UpstreamRequest.RequestUri = new Uri(forwardTo); if (whitelist.IsWhitelisted(context.Request)) { _logger.LogInformation($"Allowing passthrough for whitelisted request {forwardTo}"); } else { if (context.User.Identity.IsAuthenticated) { forwardContext.UpstreamRequest.Headers.Add(Constants.X_CF_Identity, context.User.Identity.Name); var roles = string.Join(",", context.User.Claims.Where(x => x.Type == ClaimTypes.Role).Select(x => x.Value)); if (!string.IsNullOrEmpty(roles)) { forwardContext.UpstreamRequest.Headers.Add(Constants.X_CF_Roles, roles); } } forwardContext.UpstreamRequest.Headers.Remove("Authorization"); } _logger.LogTrace("Headers sent downstream"); _logger.LogTrace("-----------------------"); foreach (var header in forwardContext.UpstreamRequest.Headers) { _logger.LogTrace($" {header.Key}: {header.Value.FirstOrDefault()}"); } response = await forwardContext.Send(); _logger.LogDebug($"Downstream responded with: {response.StatusCode}"); // merge cookie header set at the proxy level with headers from downstream request foreach (var cookie in context.Response.Headers["Set-Cookie"]) { response.Headers.TryAddWithoutValidation("Set-Cookie", cookie); } return(response); }); });
public async Task E2EMultithreadedClient() { var port = new Random().Next(20000, 40000); var options = new ListenerOptions { ListeningOn = new IPEndPoint(IPAddress.Loopback, port), DefaultRealm = "corp2.identityintervention.com".ToUpper(), IsDebug = true, RealmLocator = realm => LocateRealm(realm), ReceiveTimeout = TimeSpan.FromHours(1) }; using (KdcServiceListener listener = new KdcServiceListener(options)) { _ = listener.Start(); var exceptions = new List <Exception>(); var kerbCred = new KerberosPasswordCredential("*****@*****.**", "P@ssw0rd!"); string kdc = $"127.0.0.1:{port}"; //string kdc = "10.0.0.21:88"; using (KerberosClient client = new KerberosClient(kdc)) { client.CacheServiceTickets = false; await client.Authenticate(kerbCred); Task.WaitAll(Enumerable.Range(0, 2).Select(taskNum => Task.Run(async() => { for (var i = 0; i < 100; i++) { try { if (i % 2 == 0) { await client.Authenticate(kerbCred); } var ticket = await client.GetServiceTicket(new RequestServiceTicket { ServicePrincipalName = "host/appservice.corp.identityintervention.com", ApOptions = ApOptions.MutualRequired }); Assert.IsNotNull(ticket.ApReq); await ValidateTicket(ticket); } catch (Exception ex) { exceptions.Add(ex); } } })).ToArray()); } listener.Stop(); if (exceptions.Count > 0) { throw new AggregateException($"Failed {exceptions.Count}", exceptions.GroupBy(e => e.GetType()).Select(e => e.First())); } } }
private static async Task MultithreadedRequests( int port, int threads, int requests, bool cacheTickets, bool encodeNego, bool includePac, string kdc ) { using (var listener = StartListener(port)) { var exceptions = new List <Exception>(); var kerbCred = new KerberosPasswordCredential(AdminAtCorpUserName, FakeAdminAtCorpPassword); using (KerberosClient client = new KerberosClient(kdc)) { client.CacheServiceTickets = cacheTickets; if (!includePac) { client.AuthenticationOptions &= ~AuthenticationOptions.IncludePacRequest; } await client.Authenticate(kerbCred); Task.WaitAll(Enumerable.Range(0, threads).Select(taskNum => Task.Run(async() => { for (var i = 0; i < requests; i++) { try { if (i % 2 == 0) { await client.Authenticate(kerbCred); } var ticket = await client.GetServiceTicket(new RequestServiceTicket { ServicePrincipalName = FakeAppServiceSpn, ApOptions = ApOptions.MutualRequired }); Assert.IsNotNull(ticket.ApReq); await ValidateTicket(ticket, encodeNego: encodeNego, includePac: includePac); } catch (Exception ex) { exceptions.Add(ex); } } })).ToArray()); } listener.Stop(); if (exceptions.Count > 0) { throw new AggregateException($"Failed {exceptions.Count}", exceptions.GroupBy(e => e.GetType()).Select(e => e.First())); } } }
internal static async Task RequestAndValidateTicketsWithCaches( KdcListener listener, string user, string password = null, string overrideKdc = null, KeyTable keytab = null, string s4u = null, bool encodeNego = false, bool caching = false, bool includePac = true, X509Certificate2 cert = null, string spn = FakeAppServiceSpn, KeyAgreementAlgorithm keyAgreement = KeyAgreementAlgorithm.DiffieHellmanModp14, bool allowWeakCrypto = false, bool useWeakCrypto = false, bool mutualAuth = true, KrbTicket s4uTicket = null, bool useKrb5TicketCache = false ) { KerberosCredential kerbCred; if (cert != null) { kerbCred = new TrustedAsymmetricCredential(cert, user) { KeyAgreement = keyAgreement }; } else if (keytab != null) { kerbCred = new KeytabCredential(user, keytab); } else { kerbCred = new KerberosPasswordCredential(user, password); } KerberosClient client = CreateClient( listener, overrideKdc, caching: caching, allowWeakCrypto: allowWeakCrypto, useWeakCrypto: useWeakCrypto, useKrb5TicketCache: useKrb5TicketCache ); using (kerbCred as IDisposable) using (client) { if (!includePac) { client.AuthenticationOptions &= ~AuthenticationOptions.IncludePacRequest; } await client.Authenticate(kerbCred); var ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = spn, ApOptions = mutualAuth ? ApOptions.MutualRequired : 0 } ); await ValidateTicket(ticket, includePac : includePac, spn : spn, mutualAuth : mutualAuth); await client.RenewTicket(); ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = spn, ApOptions = mutualAuth ? ApOptions.MutualRequired : 0 } ); await ValidateTicket(ticket, encodeNego, includePac : includePac, spn : spn, mutualAuth : mutualAuth); ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = spn, ApOptions = mutualAuth ? ApOptions.MutualRequired : 0, S4uTarget = s4u, S4uTicket = s4uTicket } ); await ValidateTicket(ticket, includePac : includePac, spn : spn, mutualAuth : mutualAuth); } if (user.Contains("-fallback")) { Assert.AreEqual(PrincipalNameType.NT_PRINCIPAL, kerbCred.PrincipalNameType); } else { Assert.AreEqual(PrincipalNameType.NT_ENTERPRISE, kerbCred.PrincipalNameType); } }
private static async Task RequestAndValidateTickets( string user, string password = null, string overrideKdc = null, KeyTable keytab = null, string s4u = null, bool encodeNego = false, bool caching = false, bool includePac = true, X509Certificate2 cert = null ) { KerberosCredential kerbCred; if (cert != null) { kerbCred = new TrustedAsymmetricCredential(cert, user); } else if (keytab != null) { kerbCred = new KeytabCredential(user, keytab); } else { kerbCred = new KerberosPasswordCredential(user, password); } using (var client = new KerberosClient(overrideKdc) { CacheServiceTickets = caching }) { if (!includePac) { client.AuthenticationOptions &= ~AuthenticationOptions.IncludePacRequest; } await client.Authenticate(kerbCred); var spn = FakeAppServiceSpn; var ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = spn, ApOptions = ApOptions.MutualRequired } ); await ValidateTicket(ticket, includePac : includePac); await client.RenewTicket(); ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = FakeAppServiceSpn, ApOptions = ApOptions.MutualRequired } ); await ValidateTicket(ticket, encodeNego, includePac : includePac); ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = FakeAppServiceSpn, ApOptions = ApOptions.MutualRequired, S4uTarget = s4u } ); await ValidateTicket(ticket, includePac : includePac); } }
private static async Task RequestTickets( X509Certificate2 cert, string user, string password, string overrideKdc, string s4u, string spn, bool retryDH, bool includeCNameHint, string servicePassword, string serviceSalt, bool cacheToFile ) { KerberosCredential kerbCred; if (cert == null) { kerbCred = new KerberosPasswordCredential(user, password); } else { var chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.Build(cert); var kdcCerts = new List <X509Certificate2>(); for (var i = 0; i < chain.ChainElements.Count; i++) { var c = chain.ChainElements[i].Certificate; if (c.Thumbprint != cert.Thumbprint) { kdcCerts.Add(c); } } if (retryDH) { kerbCred = new RandomDHAsymmetricCredential(cert, user); } else { kerbCred = new TrustedKdcAsymmetricCredential(cert, user); } } var factory = LoggerFactory.Create(builder => { builder.AddConsole(opt => opt.IncludeScopes = true); builder.AddFilter <ConsoleLoggerProvider>(level => level >= LogLevel.Trace); }); var client = new KerberosClient(logger: factory); if (Uri.TryCreate(overrideKdc, UriKind.Absolute, out Uri kdcProxy)) { client.Configuration.Realms[kdcProxy.DnsSafeHost].Kdc.Add(kdcProxy.OriginalString); client.Configuration.Realms[kerbCred.Domain].Kdc.Add(kdcProxy.OriginalString); client.Configuration.Defaults.DnsLookupKdc = false; } else if (!string.IsNullOrWhiteSpace(overrideKdc)) { client.Configuration.Defaults.DnsLookupKdc = false; client.PinKdc(kerbCred.Domain, overrideKdc); } if (cacheToFile) { client.Configuration.Defaults.DefaultCCacheName = "krb5cc"; } KrbPrincipalName cnameHint = null; if (includeCNameHint) { cnameHint = KrbPrincipalName.FromString(kerbCred.UserName, PrincipalNameType.NT_PRINCIPAL, kerbCred.Domain); } client.RenewTickets = true; using (client) using (kerbCred as IDisposable) { await client.Authenticate(kerbCred); spn = spn ?? "host/appservice.corp.identityintervention.com"; KrbTicket s4uTicket = null; if (!string.IsNullOrWhiteSpace(s4u)) { var s4uSelf = await client.GetServiceTicket( kerbCred.UserName, ApOptions.MutualRequired, s4u : s4u ); s4uTicket = s4uSelf.Ticket; } var session = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = spn, ApOptions = ApOptions.MutualRequired, S4uTicket = s4uTicket, CNameHint = cnameHint } ); DumpTicket(session.ApReq); ResetColor(); if (!retryDH) { try { await TryValidate(spn, session.ApReq, servicePassword, serviceSalt, factory); } catch (Exception ex) { W(ex.Message, ConsoleColor.Yellow); ResetColor(); } } } }
static async Task Main(string[] args) { loggerFactory = LoggerFactory.Create(builder => { builder .AddFilter("Microsoft", LogLevel.Warning) .AddFilter("System", LogLevel.Warning) .AddFilter("RestNegotiateClient.Program", LogLevel.Debug) .AddFilter("Kerberos.Net", LogLevel.Trace) .AddConsole(delegate(ConsoleLoggerOptions d) { }); }); logger = loggerFactory.CreateLogger <Program>(); /*CommandLineArguments parsedArgs = new CommandLineArguments(args); * String url = (String) parsedArgs.GetValueOrDefault(""); * if (!parsedArgs.ContainsKey("keytab")) { * await Console.Error.WriteLineAsync("Syntax: RestNegotiateClient --keytab <keytab> --principal <principal> <url>"); * return; * } * String keytab = (String) parsedArgs.GetValueOrDefault("keytab", "krb5.keytab"); * String principal = (String) parsedArgs.GetValueOrDefault("principal", "cud/[email protected]");*/ String keytab = args[0]; String principal = args[1]; String url = args[2]; String outfile = args[3]; Console.Error.WriteLine("keytab={0}, principal={1}, url={2}", keytab, principal, url, outfile); // Check URL is syntactically valid Uri uri = null; if (!Uri.TryCreate(url, UriKind.Absolute, out uri)) { throw new ArgumentException(String.Format("Invalid URL: {0}", url)); } var client = new KerberosClient("kdc0.ox.ac.uk", loggerFactory); client.AuthenticationOptions ^= AuthenticationOptions.Canonicalize; var udp = client.Transports.OfType <UdpKerberosTransport>().FirstOrDefault(); udp.Enabled = true; var keyTable = new KeyTable(File.ReadAllBytes(keytab)); var kerbCred = new KeytabCredential(principal, keyTable, "OX.AC.UK"); logger.LogDebug("User name: {0}", kerbCred.UserName); await client.Authenticate(kerbCred); logger.LogDebug("Authenticated!"); // Now get a service ticket for the HTTP server and perform the request String serverPrincipal = String.Format("HTTP/{0}", uri.DnsSafeHost); var ticket = await client.GetServiceTicket(serverPrincipal); String spnego = Convert.ToBase64String(ticket.EncodeGssApi().ToArray()); var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Negotiate", spnego); using (var outStream = File.Open(outfile, FileMode.Create)) { var httpStream = await httpClient.GetStreamAsync(uri); await httpStream.CopyToAsync(outStream); } }
static async Task TestKerberosAuthAndClaims(string[] args) { var cred = new KerberosPasswordCredential("test-user", "p@$$W0RD", "domain.local"); var spn = "nats/localhost.domain.local"; using var client = new KerberosClient(); await client.Authenticate(cred); var sess = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = spn, ApOptions = ApOptions.MutualRequired, //S4uTicket = stik.Ticket, //CNameHint = null, //cnameHint } ); var stik = sess.ApReq; // var stik = await client.GetServiceTicket(spn); var stok = stik.EncodeApplication().ToArray(); var kkey = new KerberosKey("p@$$W0RD", principalName: new PrincipalName( PrincipalNameType.NT_PRINCIPAL, stik.Ticket.Realm, new[] { spn } ), saltType: SaltType.ActiveDirectoryUser ); // var kkey = new KerberosKey("p@$$W0RD", // salt: "SampleSalt", // etype: stik.Ticket.EncryptedPart.EType, // saltType: SaltType.ActiveDirectoryService // ); var kval = new KerberosValidator(kkey); var auth = new KerberosAuthenticator(kval); var claims = await auth.Authenticate(stok); //var claims = await auth.Authenticate(session.ApReq.Ticket.EncodeApplication().ToArray()); Console.WriteLine($@" AuthType............: {claims.AuthenticationType} BootstrapContext....: {claims.BootstrapContext} IsAuthenticated.....: {claims.IsAuthenticated} Label...............: {claims.Label} Name................: {claims.Name} NameClaimType.......: {claims.NameClaimType} RoleClaimType.......: {claims.RoleClaimType} RoleClaimType.......: {claims.RoleClaimType} Claims..............: {string.Join("", claims.Claims.Select(c => " * " + c + "\r\n"))} Actor.AuthType............: {claims.Actor?.AuthenticationType} Actor.BootstrapContext....: {claims.Actor?.BootstrapContext} Actor.IsAuthenticated.....: {claims.Actor?.IsAuthenticated} Actor.Label...............: {claims.Actor?.Label} Actor.Name................: {claims.Actor?.Name} Actor.NameClaimType.......: {claims.Actor?.NameClaimType} Actor.RoleClaimType.......: {claims.Actor?.RoleClaimType} "); }
internal static async Task RequestAndValidateTickets( KdcListener listener, string user, string password = null, string overrideKdc = null, KeyTable keytab = null, string s4u = null, bool encodeNego = false, bool caching = false, bool includePac = true, X509Certificate2 cert = null, string spn = FakeAppServiceSpn, KeyAgreementAlgorithm keyAgreement = KeyAgreementAlgorithm.DiffieHellmanModp14 ) { KerberosCredential kerbCred; if (cert != null) { kerbCred = new TrustedAsymmetricCredential(cert, user) { KeyAgreement = keyAgreement }; } else if (keytab != null) { kerbCred = new KeytabCredential(user, keytab); } else { kerbCred = new KerberosPasswordCredential(user, password); } KerberosClient client = CreateClient(listener, overrideKdc, caching: caching); using (client) { if (!includePac) { client.AuthenticationOptions &= ~AuthenticationOptions.IncludePacRequest; } await client.Authenticate(kerbCred); var ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = spn, ApOptions = ApOptions.MutualRequired } ); await ValidateTicket(ticket, includePac : includePac, spn : spn); await client.RenewTicket(); ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = spn, ApOptions = ApOptions.MutualRequired } ); await ValidateTicket(ticket, encodeNego, includePac : includePac, spn : spn); ticket = await client.GetServiceTicket( new RequestServiceTicket { ServicePrincipalName = spn, ApOptions = ApOptions.MutualRequired, S4uTarget = s4u } ); await ValidateTicket(ticket, includePac : includePac, spn : spn); } }
internal static async Task <List <Exception> > MultithreadedRequests( int threads, int requests, bool cacheTickets, bool encodeNego, bool includePac, string kdc, X509Certificate2 cert, KdcListener listener ) { var exceptions = new List <Exception>(); KerberosCredential kerbCred; if (cert != null) { kerbCred = new TrustedAsymmetricCredential(cert, TestAtCorpUserName); } else { kerbCred = new KerberosPasswordCredential(AdminAtCorpUserName, FakeAdminAtCorpPassword); } KerberosClient client = CreateClient(listener, kdc); using (client) { client.CacheServiceTickets = cacheTickets; if (!includePac) { client.AuthenticationOptions &= ~AuthenticationOptions.IncludePacRequest; } await client.Authenticate(kerbCred); Task.WaitAll(Enumerable.Range(0, threads).Select(taskNum => Task.Run(async() => { for (var i = 0; i < requests; i++) { try { if (i % 2 == 0) { await client.Authenticate(kerbCred); } var ticket = await client.GetServiceTicket(new RequestServiceTicket { ServicePrincipalName = FakeAppServiceSpn, ApOptions = ApOptions.MutualRequired }); Assert.IsNotNull(ticket.ApReq); await ValidateTicket(ticket, encodeNego: encodeNego, includePac: includePac); } catch (Exception ex) { exceptions.Add(ex); } } })).ToArray()); } return(exceptions); }