예제 #1
0
        public static async ValueTask <bool> AuthenticateAsync(HttpContext httpContext, ServerStore serverStore, string database, string remoteTask)
        {
            var feature = httpContext.Features.Get <IHttpAuthenticationFeature>() as RavenServer.AuthenticateConnection;

            if (feature == null) // we are not using HTTPS
            {
                return(true);
            }

            switch (feature.Status)
            {
            case RavenServer.AuthenticationStatus.Operator:
            case RavenServer.AuthenticationStatus.ClusterAdmin:
                // we can trust this certificate
                return(true);

            case RavenServer.AuthenticationStatus.Allowed:
                // check that the certificate is allowed for this database.
                if (feature.CanAccess(database, requireAdmin: false))
                {
                    return(true);
                }

                await RequestRouter.UnlikelyFailAuthorizationAsync(httpContext, database, feature, AuthorizationStatus.RestrictedAccess);

                return(false);

            case RavenServer.AuthenticationStatus.UnfamiliarIssuer:
                await RequestRouter.UnlikelyFailAuthorizationAsync(httpContext, database, feature, AuthorizationStatus.RestrictedAccess);

                return(false);

            case RavenServer.AuthenticationStatus.UnfamiliarCertificate:
                using (serverStore.ContextPool.AllocateOperationContext(out TransactionOperationContext context))
                    using (context.OpenReadTransaction())
                    {
                        if (serverStore.Cluster.TryReadPullReplicationDefinition(database, remoteTask, context, out var pullReplication))
                        {
                            var cert = httpContext.Connection.ClientCertificate;
#pragma warning disable CS0618 // Type or member is obsolete
                            if (pullReplication.Certificates != null && pullReplication.Certificates.Count > 0)
                            {
                                if (pullReplication.Certificates.ContainsKey(cert.Thumbprint))
                                {
                                    return(true);
                                }
                            }
#pragma warning restore CS0618 // Type or member is obsolete
                            else
                            {
                                if (serverStore.Cluster.IsReplicationCertificate(context, database, remoteTask, cert, out _))
                                {
                                    return(true);
                                }

                                if (serverStore.Cluster.IsReplicationCertificateByPublicKeyPinningHash(context, database, remoteTask, cert, serverStore.Configuration.Security, out _))
                                {
                                    return(true);
                                }
                            }
                        }

                        await RequestRouter.UnlikelyFailAuthorizationAsync(httpContext, database, feature, AuthorizationStatus.RestrictedAccess);

                        return(false);
                    }

            default:
                throw new ArgumentException($"This is a bug, we should deal with '{feature?.Status}' authentication status at RequestRoute.TryAuthorize function.");
            }
        }