public static void UnlikelyFailAuthorization(HttpContext context, string database, RavenServer.AuthenticateConnection feature, AuthorizationStatus authorizationStatus) { string message; if (feature == null || feature.Status == RavenServer.AuthenticationStatus.None || feature.Status == RavenServer.AuthenticationStatus.NoCertificateProvided) { message = "This server requires client certificate for authentication, but none was provided by the client."; } else { var name = feature.Certificate.FriendlyName; if (string.IsNullOrWhiteSpace(name)) { name = feature.Certificate.Subject; } if (string.IsNullOrWhiteSpace(name)) { name = feature.Certificate.ToString(false); } name += $"(Thumbprint: {feature.Certificate.Thumbprint})"; if (feature.Status == RavenServer.AuthenticationStatus.UnfamiliarCertificate) { message = $"The supplied client certificate '{name}' is unknown to the server. In order to register your certificate please contact your system administrator."; } else if (feature.Status == RavenServer.AuthenticationStatus.UnfamiliarIssuer) { message = $"The supplied client certificate '{name}' is unknown to the server but has a known Public Key Pinning Hash. Will not use it to authenticate because the issuer is unknown. To fix this, the admin can register the pinning hash of the *issuer* certificate: '{feature.IssuerHash}' in the '{RavenConfiguration.GetKey(x => x.Security.WellKnownIssuerHashes)}' configuration entry."; } else if (feature.Status == RavenServer.AuthenticationStatus.Allowed) { message = $"Could not authorize access to {(database ?? "the server")} using provided client certificate '{name}'."; } else if (feature.Status == RavenServer.AuthenticationStatus.Operator) { message = $"Insufficient security clearance to access {(database ?? "the server")} using provided client certificate '{name}'."; } else if (feature.Status == RavenServer.AuthenticationStatus.Expired) { message = $"The supplied client certificate '{name}' has expired on {feature.Certificate.NotAfter:D}. Please contact your system administrator in order to obtain a new one."; } else if (feature.Status == RavenServer.AuthenticationStatus.NotYetValid) { message = $"The supplied client certificate '{name}'cannot be used before {feature.Certificate.NotBefore:D}"; } else { message = "Access to the server was denied."; } } switch (authorizationStatus) { case AuthorizationStatus.ClusterAdmin: message += " ClusterAdmin access is required but not given to this certificate"; break; case AuthorizationStatus.Operator: message += " Operator/ClusterAdmin access is required but not given to this certificate"; break; case AuthorizationStatus.DatabaseAdmin: message += " DatabaseAdmin access is required but not given to this certificate"; break; } context.Response.StatusCode = (int)HttpStatusCode.Forbidden; using (var ctx = JsonOperationContext.ShortTermSingleUse()) using (var writer = new BlittableJsonTextWriter(ctx, context.Response.Body)) { DrainRequest(ctx, context); if (RavenServerStartup.IsHtmlAcceptable(context)) { context.Response.StatusCode = (int)HttpStatusCode.Redirect; context.Response.Headers["Location"] = "/auth-error.html?err=" + Uri.EscapeDataString(message); return; } ctx.Write(writer, new DynamicJsonValue { ["Type"] = "InvalidAuth", ["Message"] = message }); } }
public void UnlikelyFailAuthorization(HttpContext context, string database, RavenServer.AuthenticateConnection feature, AuthorizationStatus authorizationStatus) { string message; if (feature == null || feature.Status == RavenServer.AuthenticationStatus.None || feature.Status == RavenServer.AuthenticationStatus.NoCertificateProvided) { message = "This server requires client certificate for authentication, but none was provided by the client."; } else { var name = feature.Certificate.FriendlyName; if (string.IsNullOrWhiteSpace(name)) { name = feature.Certificate.Subject; } if (string.IsNullOrWhiteSpace(name)) { name = feature.Certificate.ToString(false); } name += "(Thumbprint: " + feature.Certificate.Thumbprint + ")"; if (feature.Status == RavenServer.AuthenticationStatus.UnfamiliarCertificate) { message = "The supplied client certificate '" + name + "' is unknown to the server. In order to register your certificate please contact your system administrator."; } else if (feature.Status == RavenServer.AuthenticationStatus.Allowed) { message = "Could not authorize access to " + (database ?? "the server") + " using provided client certificate '" + name + "'."; } else if (feature.Status == RavenServer.AuthenticationStatus.Operator) { message = "Insufficient security clearance to access " + (database ?? "the server") + " using provided client certificate '" + name + "'."; } else if (feature.Status == RavenServer.AuthenticationStatus.Expired) { message = "The supplied client certificate '" + name + "' has expired on " + feature.Certificate.NotAfter.ToString("D") + ". Please contact your system administrator in order to obtain a new one."; } else if (feature.Status == RavenServer.AuthenticationStatus.NotYetValid) { message = "The supplied client certificate '" + name + "'cannot be used before " + feature.Certificate.NotBefore.ToString("D"); } else { message = "Access to the server was denied."; } } switch (authorizationStatus) { case AuthorizationStatus.ClusterAdmin: message += " ClusterAdmin access is required but not given to this certificate"; break; case AuthorizationStatus.Operator: message += " Operator/ClusterAdmin access is required but not given to this certificate"; break; case AuthorizationStatus.DatabaseAdmin: message += " DatabaseAdmin access is required but not given to this certificate"; break; } context.Response.StatusCode = (int)HttpStatusCode.Forbidden; using (var ctx = JsonOperationContext.ShortTermSingleUse()) using (var writer = new BlittableJsonTextWriter(ctx, context.Response.Body)) { DrainRequest(ctx, context); if (RavenServerStartup.IsHtmlAcceptable(context)) { context.Response.StatusCode = (int)HttpStatusCode.Redirect; context.Response.Headers["Location"] = "/auth-error.html?err=" + Uri.EscapeDataString(message); return; } ctx.Write(writer, new DynamicJsonValue { ["Type"] = "InvalidAuth", ["Message"] = message }); } }
public void UnlikelyFailAuthorization(HttpContext context, string database, RavenServer.AuthenticateConnection feature) { string message; if (feature == null || feature.Status == RavenServer.AuthenticationStatus.None || feature.Status == RavenServer.AuthenticationStatus.NoCertificateProvided) { message = "This server requires client certificate for authentication, but none was provided by the client"; } else { var name = feature.Certificate.FriendlyName; if (string.IsNullOrWhiteSpace(name)) { name = feature.Certificate.Subject; } if (string.IsNullOrWhiteSpace(name)) { name = feature.Certificate.ToString(false); } if (feature.Status == RavenServer.AuthenticationStatus.UnfamiliarCertificate) { message = "The provided client certificate '" + name + "' is not on the allowed list of certificates that can access this server"; } else if (feature.Status == RavenServer.AuthenticationStatus.Allowed) { message = "The provided client certificate '" + name + "' is not authorized to access " + (database ?? "the server"); } else if (feature.Status == RavenServer.AuthenticationStatus.Operator) { message = "The provided client certificate '" + name + "' does not have sufficient level to access " + (database ?? "the server"); } else if (feature.Status == RavenServer.AuthenticationStatus.Expired) { message = "The provided client certificate '" + name + "' is expired on " + feature.Certificate.NotAfter; } else if (feature.Status == RavenServer.AuthenticationStatus.NotYetValid) { message = "The provided client certificate '" + name + "' is not yet valid because it starts on " + feature.Certificate.NotBefore; } else { message = "Access to this server was denied, but the reason why is confidential, you did not see this message and your memory will self destruct in 5 seconds."; } } context.Response.StatusCode = (int)HttpStatusCode.Forbidden; using (var ctx = JsonOperationContext.ShortTermSingleUse()) using (var writer = new BlittableJsonTextWriter(ctx, context.Response.Body)) { DrainRequest(ctx, context); if (RavenServerStartup.IsHtmlAcceptable(context)) { context.Response.StatusCode = (int)HttpStatusCode.Redirect; context.Response.Headers["Location"] = "/studio/auth-error.html?err=" + Uri.EscapeDataString(message); return; } ctx.Write(writer, new DynamicJsonValue { ["Type"] = "InvalidAuth", ["Message"] = message }); } }