/src/Security/Authentication/Negotiate/test/Negotiate.Test/NegotiateHandlerTests.cs

https://github.com/aspnet/AspNetCore · C# · 620 lines · 549 code · 65 blank · 6 comment · 26 complexity · 50e49aa5030307b5049502a6312a77d5 MD5 · raw file

  1. // Copyright (c) .NET Foundation. All rights reserved.
  2. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Security.Claims;
  6. using System.Security.Principal;
  7. using System.Threading.Tasks;
  8. using Microsoft.AspNetCore.Builder;
  9. using Microsoft.AspNetCore.Connections;
  10. using Microsoft.AspNetCore.Connections.Features;
  11. using Microsoft.AspNetCore.Hosting;
  12. using Microsoft.AspNetCore.Http;
  13. using Microsoft.AspNetCore.Routing;
  14. using Microsoft.AspNetCore.TestHost;
  15. using Microsoft.Extensions.Caching.Memory;
  16. using Microsoft.Extensions.DependencyInjection;
  17. using Microsoft.Extensions.Hosting;
  18. using Microsoft.Net.Http.Headers;
  19. using Xunit;
  20. using Xunit.Sdk;
  21. namespace Microsoft.AspNetCore.Authentication.Negotiate
  22. {
  23. public class NegotiateHandlerTests
  24. {
  25. [Fact]
  26. public async Task Anonymous_MissingConnectionFeatures_ThrowsNotSupported()
  27. {
  28. using var host = await CreateHostAsync();
  29. var server = host.GetTestServer();
  30. var ex = await Assert.ThrowsAsync<NotSupportedException>(() => SendAsync(server, "/Anonymous1", connection: null));
  31. Assert.Equal("Negotiate authentication requires a server that supports IConnectionItemsFeature like Kestrel.", ex.Message);
  32. }
  33. [Fact]
  34. public async Task Anonymous_NoChallenge_NoOps()
  35. {
  36. using var host = await CreateHostAsync();
  37. var server = host.GetTestServer();
  38. var result = await SendAsync(server, "/Anonymous1", new TestConnection());
  39. Assert.Equal(StatusCodes.Status200OK, result.Response.StatusCode);
  40. }
  41. [Fact]
  42. public async Task Anonymous_Http2_NoOps()
  43. {
  44. using var host = await CreateHostAsync();
  45. var server = host.GetTestServer();
  46. var result = await SendAsync(server, "/Anonymous2", connection: null, http2: true);
  47. Assert.Equal(StatusCodes.Status200OK, result.Response.StatusCode);
  48. }
  49. [Fact]
  50. public async Task Anonymous_Challenge_401Negotiate()
  51. {
  52. using var host = await CreateHostAsync();
  53. var server = host.GetTestServer();
  54. var result = await SendAsync(server, "/Authenticate", new TestConnection());
  55. Assert.Equal(StatusCodes.Status401Unauthorized, result.Response.StatusCode);
  56. Assert.Equal("Negotiate", result.Response.Headers[HeaderNames.WWWAuthenticate]);
  57. }
  58. [Fact]
  59. public async Task Anonymous_ChallengeHttp2_401Negotiate()
  60. {
  61. using var host = await CreateHostAsync();
  62. var server = host.GetTestServer();
  63. var result = await SendAsync(server, "/Authenticate", connection: null, http2: true);
  64. // Clients will downgrade to HTTP/1.1 and authenticate.
  65. Assert.Equal(StatusCodes.Status401Unauthorized, result.Response.StatusCode);
  66. Assert.Equal("Negotiate", result.Response.Headers[HeaderNames.WWWAuthenticate]);
  67. }
  68. [Fact]
  69. public async Task NtlmStage1Auth_401NegotiateServerBlob1()
  70. {
  71. using var host = await CreateHostAsync();
  72. var server = host.GetTestServer();
  73. var result = await SendAsync(server, "/404", new TestConnection(), "Negotiate ClientNtlmBlob1");
  74. Assert.Equal(StatusCodes.Status401Unauthorized, result.Response.StatusCode);
  75. Assert.Equal("Negotiate ServerNtlmBlob1", result.Response.Headers[HeaderNames.WWWAuthenticate]);
  76. }
  77. [Fact]
  78. public async Task AnonymousAfterNtlmStage1_Throws()
  79. {
  80. using var host = await CreateHostAsync();
  81. var server = host.GetTestServer();
  82. var testConnection = new TestConnection();
  83. await NtlmStage1Auth(server, testConnection);
  84. var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => SendAsync(server, "/404", testConnection));
  85. Assert.Equal("An anonymous request was received in between authentication handshake requests.", ex.Message);
  86. }
  87. [Fact]
  88. public async Task NtlmStage2Auth_WithoutStage1_Throws()
  89. {
  90. using var host = await CreateHostAsync();
  91. var server = host.GetTestServer();
  92. var ex = await Assert.ThrowsAsync<TrueException>(() => SendAsync(server, "/404", new TestConnection(), "Negotiate ClientNtlmBlob2"));
  93. Assert.Equal("Stage1Complete", ex.UserMessage);
  94. }
  95. [Theory]
  96. [InlineData(false)]
  97. [InlineData(true)]
  98. public async Task NtlmStage1And2Auth_Success(bool persistNtlm)
  99. {
  100. using var host = await CreateHostAsync(options => options.PersistNtlmCredentials = persistNtlm);
  101. var server = host.GetTestServer();
  102. var testConnection = new TestConnection();
  103. await NtlmStage1And2Auth(server, testConnection);
  104. }
  105. [Theory]
  106. [InlineData(false)]
  107. [InlineData(true)]
  108. public async Task KerberosAuth_Success(bool persistKerberos)
  109. {
  110. using var host = await CreateHostAsync(options => options.PersistKerberosCredentials = persistKerberos);
  111. var server = host.GetTestServer();
  112. var testConnection = new TestConnection();
  113. await KerberosAuth(server, testConnection);
  114. }
  115. [Theory]
  116. [InlineData(false)]
  117. [InlineData(true)]
  118. public async Task KerberosTwoStageAuth_Success(bool persistKerberos)
  119. {
  120. using var host = await CreateHostAsync(options => options.PersistKerberosCredentials = persistKerberos);
  121. var server = host.GetTestServer();
  122. var testConnection = new TestConnection();
  123. await KerberosStage1And2Auth(server, testConnection);
  124. }
  125. [Theory]
  126. [InlineData("NTLM")]
  127. [InlineData("Kerberos")]
  128. [InlineData("Kerberos2")]
  129. public async Task AnonymousAfterCompletedPersist_Cached(string protocol)
  130. {
  131. using var host = await CreateHostAsync(options => options.PersistNtlmCredentials = options.PersistKerberosCredentials = true);
  132. var server = host.GetTestServer();
  133. var testConnection = new TestConnection();
  134. if (protocol == "NTLM")
  135. {
  136. await NtlmStage1And2Auth(server, testConnection);
  137. }
  138. else if (protocol == "Kerberos2")
  139. {
  140. await KerberosStage1And2Auth(server, testConnection);
  141. }
  142. else
  143. {
  144. await KerberosAuth(server, testConnection);
  145. }
  146. var result = await SendAsync(server, "/Authenticate", testConnection);
  147. Assert.Equal(StatusCodes.Status200OK, result.Response.StatusCode);
  148. Assert.False(result.Response.Headers.ContainsKey(HeaderNames.WWWAuthenticate));
  149. }
  150. [Theory]
  151. [InlineData("NTLM")]
  152. [InlineData("Kerberos")]
  153. [InlineData("Kerberos2")]
  154. public async Task AnonymousAfterCompletedNoPersist_Denied(string protocol)
  155. {
  156. using var host = await CreateHostAsync(options => options.PersistNtlmCredentials = options.PersistKerberosCredentials = false);
  157. var server = host.GetTestServer();
  158. var testConnection = new TestConnection();
  159. if (protocol == "NTLM")
  160. {
  161. await NtlmStage1And2Auth(server, testConnection);
  162. }
  163. else if (protocol == "Kerberos2")
  164. {
  165. await KerberosStage1And2Auth(server, testConnection);
  166. }
  167. else
  168. {
  169. await KerberosAuth(server, testConnection);
  170. }
  171. var result = await SendAsync(server, "/Authenticate", testConnection);
  172. Assert.Equal(StatusCodes.Status401Unauthorized, result.Response.StatusCode);
  173. Assert.Equal("Negotiate", result.Response.Headers[HeaderNames.WWWAuthenticate]);
  174. }
  175. [Theory]
  176. [InlineData(false)]
  177. [InlineData(true)]
  178. public async Task AuthHeaderAfterNtlmCompleted_ReAuthenticates(bool persist)
  179. {
  180. using var host = await CreateHostAsync(options => options.PersistNtlmCredentials = persist);
  181. var server = host.GetTestServer();
  182. var testConnection = new TestConnection();
  183. await NtlmStage1And2Auth(server, testConnection);
  184. await NtlmStage1And2Auth(server, testConnection);
  185. }
  186. [Fact]
  187. public async Task RBACClaimsRetrievedFromCacheAfterKerberosCompleted()
  188. {
  189. var claimsCache = new MemoryCache(new MemoryCacheOptions());
  190. claimsCache.Set("name", new string[] { "CN=Domain Admins,CN=Users,DC=domain,DC=net" });
  191. NegotiateOptions negotiateOptions = null;
  192. using var host = await CreateHostAsync(options =>
  193. {
  194. options.EnableLdap(ldapSettings =>
  195. {
  196. ldapSettings.Domain = "domain.NET";
  197. ldapSettings.ClaimsCache = claimsCache;
  198. ldapSettings.EnableLdapClaimResolution = false; // This disables binding to the LDAP connection on startup
  199. });
  200. negotiateOptions = options;
  201. });
  202. var server = host.GetTestServer();
  203. var testConnection = new TestConnection();
  204. negotiateOptions.EnableLdap(_ => { }); // Forcefully re-enable ldap claims resolution to trigger RBAC claims retrieval from cache
  205. await AuthenticateAndRetrieveRBACClaims(server, testConnection);
  206. }
  207. [Theory]
  208. [InlineData(false)]
  209. [InlineData(true)]
  210. public async Task AuthHeaderAfterKerberosCompleted_ReAuthenticates(bool persist)
  211. {
  212. using var host = await CreateHostAsync(options => options.PersistNtlmCredentials = persist);
  213. var server = host.GetTestServer();
  214. var testConnection = new TestConnection();
  215. await KerberosAuth(server, testConnection);
  216. await KerberosAuth(server, testConnection);
  217. }
  218. [Theory]
  219. [InlineData(false)]
  220. [InlineData(true)]
  221. public async Task AuthHeaderAfterKerberos2StageCompleted_ReAuthenticates(bool persist)
  222. {
  223. using var host = await CreateHostAsync(options => options.PersistNtlmCredentials = persist);
  224. var server = host.GetTestServer();
  225. var testConnection = new TestConnection();
  226. await KerberosStage1And2Auth(server, testConnection);
  227. await KerberosStage1And2Auth(server, testConnection);
  228. }
  229. [Fact]
  230. public async Task ApplicationExceptionReExecute_AfterComplete_DoesntReRun()
  231. {
  232. var builder = new HostBuilder()
  233. .ConfigureServices(services => services
  234. .AddAuthentication(NegotiateDefaults.AuthenticationScheme)
  235. .AddNegotiate(options =>
  236. {
  237. options.StateFactory = new TestNegotiateStateFactory();
  238. }))
  239. .ConfigureWebHost(webHostBuilder =>
  240. {
  241. webHostBuilder.UseTestServer();
  242. webHostBuilder.Configure(app =>
  243. {
  244. app.UseExceptionHandler("/error");
  245. app.UseAuthentication();
  246. app.Run(context =>
  247. {
  248. Assert.True(context.User.Identity.IsAuthenticated);
  249. if (context.Request.Path.Equals("/error"))
  250. {
  251. return context.Response.WriteAsync("Error Handler");
  252. }
  253. throw new TimeZoneNotFoundException();
  254. });
  255. });
  256. });
  257. using var host = await builder.StartAsync();
  258. var server = host.GetTestServer();
  259. var testConnection = new TestConnection();
  260. await NtlmStage1Auth(server, testConnection);
  261. var result = await SendAsync(server, "/Authenticate", testConnection, "Negotiate ClientNtlmBlob2");
  262. Assert.Equal(StatusCodes.Status500InternalServerError, result.Response.StatusCode);
  263. Assert.False(result.Response.Headers.ContainsKey(HeaderNames.WWWAuthenticate));
  264. }
  265. [Fact]
  266. public async Task CredentialError_401()
  267. {
  268. using var host = await CreateHostAsync();
  269. var server = host.GetTestServer();
  270. var testConnection = new TestConnection();
  271. var result = await SendAsync(server, "/Authenticate", testConnection, "Negotiate CredentialError");
  272. Assert.Equal(StatusCodes.Status401Unauthorized, result.Response.StatusCode);
  273. Assert.Equal("Negotiate", result.Response.Headers[HeaderNames.WWWAuthenticate]);
  274. }
  275. [Fact]
  276. public async Task ClientError_400()
  277. {
  278. using var host = await CreateHostAsync();
  279. var server = host.GetTestServer();
  280. var testConnection = new TestConnection();
  281. var result = await SendAsync(server, "/404", testConnection, "Negotiate ClientError");
  282. Assert.Equal(StatusCodes.Status400BadRequest, result.Response.StatusCode);
  283. Assert.DoesNotContain(HeaderNames.WWWAuthenticate, result.Response.Headers);
  284. }
  285. [Fact]
  286. public async Task OtherError_Throws()
  287. {
  288. using var host = await CreateHostAsync();
  289. var server = host.GetTestServer();
  290. var testConnection = new TestConnection();
  291. var ex = await Assert.ThrowsAsync<Exception>(() => SendAsync(server, "/404", testConnection, "Negotiate OtherError"));
  292. Assert.Equal("A test other error occurred", ex.Message);
  293. }
  294. private static async Task AuthenticateAndRetrieveRBACClaims(TestServer server, TestConnection testConnection)
  295. {
  296. var result = await SendAsync(server, "/AuthenticateAndRetrieveRBACClaims", testConnection, "Negotiate ClientKerberosBlob");
  297. Assert.Equal(StatusCodes.Status200OK, result.Response.StatusCode);
  298. Assert.Equal("Negotiate ServerKerberosBlob", result.Response.Headers[HeaderNames.WWWAuthenticate]);
  299. }
  300. // Single Stage
  301. private static async Task KerberosAuth(TestServer server, TestConnection testConnection)
  302. {
  303. var result = await SendAsync(server, "/Authenticate", testConnection, "Negotiate ClientKerberosBlob");
  304. Assert.Equal(StatusCodes.Status200OK, result.Response.StatusCode);
  305. Assert.Equal("Negotiate ServerKerberosBlob", result.Response.Headers[HeaderNames.WWWAuthenticate]);
  306. }
  307. private static async Task KerberosStage1And2Auth(TestServer server, TestConnection testConnection)
  308. {
  309. await KerberosStage1Auth(server, testConnection);
  310. await KerberosStage2Auth(server, testConnection);
  311. }
  312. private static async Task KerberosStage1Auth(TestServer server, TestConnection testConnection)
  313. {
  314. var result = await SendAsync(server, "/Authenticate", testConnection, "Negotiate ClientKerberosBlob1");
  315. Assert.Equal(StatusCodes.Status401Unauthorized, result.Response.StatusCode);
  316. Assert.Equal("Negotiate ServerKerberosBlob1", result.Response.Headers[HeaderNames.WWWAuthenticate]);
  317. }
  318. private static async Task KerberosStage2Auth(TestServer server, TestConnection testConnection)
  319. {
  320. var result = await SendAsync(server, "/Authenticate", testConnection, "Negotiate ClientKerberosBlob2");
  321. Assert.Equal(StatusCodes.Status200OK, result.Response.StatusCode);
  322. Assert.Equal("Negotiate ServerKerberosBlob2", result.Response.Headers[HeaderNames.WWWAuthenticate]);
  323. }
  324. private static async Task NtlmStage1And2Auth(TestServer server, TestConnection testConnection)
  325. {
  326. await NtlmStage1Auth(server, testConnection);
  327. await NtlmStage2Auth(server, testConnection);
  328. }
  329. private static async Task NtlmStage1Auth(TestServer server, TestConnection testConnection)
  330. {
  331. var result = await SendAsync(server, "/404", testConnection, "Negotiate ClientNtlmBlob1");
  332. Assert.Equal(StatusCodes.Status401Unauthorized, result.Response.StatusCode);
  333. Assert.Equal("Negotiate ServerNtlmBlob1", result.Response.Headers[HeaderNames.WWWAuthenticate]);
  334. }
  335. private static async Task NtlmStage2Auth(TestServer server, TestConnection testConnection)
  336. {
  337. var result = await SendAsync(server, "/Authenticate", testConnection, "Negotiate ClientNtlmBlob2");
  338. Assert.Equal(StatusCodes.Status200OK, result.Response.StatusCode);
  339. Assert.Equal("Negotiate ServerNtlmBlob2", result.Response.Headers[HeaderNames.WWWAuthenticate]);
  340. }
  341. private static async Task<IHost> CreateHostAsync(Action<NegotiateOptions> configureOptions = null)
  342. {
  343. var builder = new HostBuilder()
  344. .ConfigureServices(services => services
  345. .AddRouting()
  346. .AddAuthentication(NegotiateDefaults.AuthenticationScheme)
  347. .AddNegotiate(options =>
  348. {
  349. options.StateFactory = new TestNegotiateStateFactory();
  350. configureOptions?.Invoke(options);
  351. }))
  352. .ConfigureWebHost(webHostBuilder =>
  353. {
  354. webHostBuilder.UseTestServer();
  355. webHostBuilder.Configure(app =>
  356. {
  357. app.UseRouting();
  358. app.UseAuthentication();
  359. app.UseEndpoints(ConfigureEndpoints);
  360. });
  361. });
  362. return await builder.StartAsync();
  363. }
  364. private static void ConfigureEndpoints(IEndpointRouteBuilder builder)
  365. {
  366. builder.Map("/Anonymous1", context =>
  367. {
  368. Assert.Equal("HTTP/1.1", context.Request.Protocol);
  369. Assert.False(context.User.Identity.IsAuthenticated, "Anonymous");
  370. return Task.CompletedTask;
  371. });
  372. builder.Map("/Anonymous2", context =>
  373. {
  374. Assert.Equal("HTTP/2", context.Request.Protocol);
  375. Assert.False(context.User.Identity.IsAuthenticated, "Anonymous");
  376. return Task.CompletedTask;
  377. });
  378. builder.Map("/Authenticate", async context =>
  379. {
  380. if (!context.User.Identity.IsAuthenticated)
  381. {
  382. await context.ChallengeAsync();
  383. return;
  384. }
  385. Assert.Equal("HTTP/1.1", context.Request.Protocol); // Not HTTP/2
  386. var name = context.User.Identity.Name;
  387. Assert.False(string.IsNullOrEmpty(name), "name");
  388. await context.Response.WriteAsync(name);
  389. });
  390. builder.Map("/AuthenticateAndRetrieveRBACClaims", async context =>
  391. {
  392. if (!context.User.Identity.IsAuthenticated)
  393. {
  394. await context.ChallengeAsync();
  395. return;
  396. }
  397. Assert.Equal("HTTP/1.1", context.Request.Protocol); // Not HTTP/2
  398. var name = context.User.Identity.Name;
  399. Assert.False(string.IsNullOrEmpty(name), "name");
  400. Assert.Contains(
  401. context.User.Claims,
  402. claim => claim.Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
  403. && claim.Value == "CN=Domain Admins,CN=Users,DC=domain,DC=net");
  404. await context.Response.WriteAsync(name);
  405. });
  406. builder.Map("/AlreadyAuthenticated", async context =>
  407. {
  408. Assert.Equal("HTTP/1.1", context.Request.Protocol); // Not HTTP/2
  409. Assert.True(context.User.Identity.IsAuthenticated, "Authenticated");
  410. var name = context.User.Identity.Name;
  411. Assert.False(string.IsNullOrEmpty(name), "name");
  412. await context.Response.WriteAsync(name);
  413. });
  414. builder.Map("/Unauthorized", async context =>
  415. {
  416. // Simulate Authorization failure
  417. var result = await context.AuthenticateAsync();
  418. await context.ChallengeAsync();
  419. });
  420. builder.Map("/SignIn", context =>
  421. {
  422. return Assert.ThrowsAsync<InvalidOperationException>(() => context.SignInAsync(new ClaimsPrincipal()));
  423. });
  424. builder.Map("/signOut", context =>
  425. {
  426. return Assert.ThrowsAsync<InvalidOperationException>(() => context.SignOutAsync());
  427. });
  428. }
  429. private static Task<HttpContext> SendAsync(TestServer server, string path, TestConnection connection, string authorizationHeader = null, bool http2 = false)
  430. {
  431. return server.SendAsync(context =>
  432. {
  433. context.Request.Protocol = http2 ? "HTTP/2" : "HTTP/1.1";
  434. context.Request.Path = path;
  435. if (!string.IsNullOrEmpty(authorizationHeader))
  436. {
  437. context.Request.Headers[HeaderNames.Authorization] = authorizationHeader;
  438. }
  439. if (connection != null)
  440. {
  441. context.Features.Set<IConnectionItemsFeature>(connection);
  442. context.Features.Set<IConnectionCompleteFeature>(connection);
  443. }
  444. });
  445. }
  446. private class TestConnection : IConnectionItemsFeature, IConnectionCompleteFeature
  447. {
  448. public IDictionary<object, object> Items { get; set; } = new ConnectionItems();
  449. public void OnCompleted(Func<object, Task> callback, object state)
  450. {
  451. }
  452. }
  453. private class TestNegotiateStateFactory : INegotiateStateFactory
  454. {
  455. public INegotiateState CreateInstance() => new TestNegotiateState();
  456. }
  457. private class TestNegotiateState : INegotiateState
  458. {
  459. private string _protocol;
  460. private bool Stage1Complete { get; set; }
  461. public bool IsCompleted { get; private set; }
  462. public bool IsDisposed { get; private set; }
  463. public string Protocol
  464. {
  465. get
  466. {
  467. if (IsDisposed)
  468. {
  469. throw new ObjectDisposedException(nameof(TestNegotiateState));
  470. }
  471. if (!Stage1Complete)
  472. {
  473. throw new InvalidOperationException("Authentication has not started yet.");
  474. }
  475. return _protocol;
  476. }
  477. }
  478. public void Dispose()
  479. {
  480. IsDisposed = true;
  481. }
  482. public IIdentity GetIdentity()
  483. {
  484. if (IsDisposed)
  485. {
  486. throw new ObjectDisposedException(nameof(TestNegotiateState));
  487. }
  488. if (!IsCompleted)
  489. {
  490. throw new InvalidOperationException("Authentication is not complete.");
  491. }
  492. return new GenericIdentity("name", _protocol);
  493. }
  494. public string GetOutgoingBlob(string incomingBlob, out BlobErrorType errorType, out Exception ex)
  495. {
  496. if (IsDisposed)
  497. {
  498. throw new ObjectDisposedException(nameof(TestNegotiateState));
  499. }
  500. if (IsCompleted)
  501. {
  502. throw new InvalidOperationException("Authentication is already complete.");
  503. }
  504. errorType = BlobErrorType.None;
  505. ex = null;
  506. switch (incomingBlob)
  507. {
  508. case "ClientNtlmBlob1":
  509. Assert.False(Stage1Complete, nameof(Stage1Complete));
  510. Stage1Complete = true;
  511. _protocol = "NTLM";
  512. return "ServerNtlmBlob1";
  513. case "ClientNtlmBlob2":
  514. Assert.True(Stage1Complete, nameof(Stage1Complete));
  515. Assert.Equal("NTLM", _protocol);
  516. IsCompleted = true;
  517. return "ServerNtlmBlob2";
  518. // Kerberos can require one or two stages
  519. case "ClientKerberosBlob":
  520. Assert.False(Stage1Complete, nameof(Stage1Complete));
  521. _protocol = "Kerberos";
  522. Stage1Complete = true;
  523. IsCompleted = true;
  524. return "ServerKerberosBlob";
  525. case "ClientKerberosBlob1":
  526. Assert.False(Stage1Complete, nameof(Stage1Complete));
  527. _protocol = "Kerberos";
  528. Stage1Complete = true;
  529. return "ServerKerberosBlob1";
  530. case "ClientKerberosBlob2":
  531. Assert.True(Stage1Complete, nameof(Stage1Complete));
  532. Assert.Equal("Kerberos", _protocol);
  533. IsCompleted = true;
  534. return "ServerKerberosBlob2";
  535. case "CredentialError":
  536. errorType = BlobErrorType.CredentialError;
  537. ex = new Exception("A test credential error occurred");
  538. return null;
  539. case "ClientError":
  540. errorType = BlobErrorType.ClientError;
  541. ex = new Exception("A test client error occurred");
  542. return null;
  543. case "OtherError":
  544. errorType = BlobErrorType.Other;
  545. ex = new Exception("A test other error occurred");
  546. return null;
  547. default:
  548. errorType = BlobErrorType.Other;
  549. ex = new InvalidOperationException(incomingBlob);
  550. return null;
  551. }
  552. }
  553. }
  554. }
  555. }