private static void ValidateExpiration(string source, X509Certificate2 loadedCertificate, ServerStore serverStore) { if (loadedCertificate.NotAfter < DateTime.UtcNow) { if (Logger.IsOperationsEnabled) { Logger.Operations($"The provided certificate {loadedCertificate.FriendlyName} from {source} is expired! Thubprint: {loadedCertificate.Thumbprint}, Expired on: {loadedCertificate.NotAfter}"); } } if (serverStore.LicenseManager.GetLicenseStatus().Type == LicenseType.Developer) { // Do not allow long range certificates in developer mode. if (loadedCertificate.NotAfter > DateTime.UtcNow.AddMonths(4)) { const string msg = "The server certificate expiration date is more than 4 months from now. " + "This is not allowed when using the developer license. " + "The developer license is not allowed for production use. " + "Either switch the license or use a short term certificate."; if (Logger.IsOperationsEnabled) { Logger.Operations(msg); } throw new InvalidOperationException(msg); } } }
public static RavenServer.CertificateHolder ValidateCertificateAndCreateCertificateHolder(string source, X509Certificate2 loadedCertificate, byte[] rawBytes, string password, ServerStore serverStore) { ValidateExpiration(source, loadedCertificate, serverStore); ValidatePrivateKey(source, password, rawBytes, out var privateKey); ValidateKeyUsages(source, loadedCertificate); AddCertificateChainToTheUserCertificateAuthority(loadedCertificate, rawBytes, password); return(new RavenServer.CertificateHolder { Certificate = loadedCertificate, CertificateForClients = Convert.ToBase64String(loadedCertificate.Export(X509ContentType.Cert)), PrivateKey = privateKey }); }
public RavenServer.CertificateHolder LoadCertificateFromPath(string path, string password, ServerStore serverStore) { try { path = Path.Combine(AppContext.BaseDirectory, path); var rawData = File.ReadAllBytes(path); // we need to load it as exportable because we might need to send it over the cluster var loadedCertificate = new X509Certificate2(rawData, password, X509KeyStorageFlags.Exportable); ValidateExpiration(path, loadedCertificate, serverStore); ValidatePrivateKey(path, password, rawData, out var privateKey); ValidateKeyUsages(path, loadedCertificate); return(new RavenServer.CertificateHolder { Certificate = loadedCertificate, CertificateForClients = Convert.ToBase64String(loadedCertificate.Export(X509ContentType.Cert)), PrivateKey = privateKey }); } catch (Exception e) { throw new InvalidOperationException($"Could not load certificate file {path}", e); } }
public RavenServer.CertificateHolder LoadCertificateWithExecutable(string executable, string args, ServerStore serverStore) { var process = new Process { StartInfo = new ProcessStartInfo { FileName = executable, Arguments = args, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true } }; var sw = Stopwatch.StartNew(); try { process.Start(); } catch (Exception e) { throw new InvalidOperationException($"Unable to get certificate by executing {executable} {args}. Failed to start process.", e); } var ms = new MemoryStream(); var readErrors = process.StandardError.ReadToEndAsync(); var readStdOut = process.StandardOutput.BaseStream.CopyToAsync(ms); string GetStdError() { try { return(readErrors.Result); } catch { return("Unable to get stderr"); } } if (process.WaitForExit((int)_config.CertificateExecTimeout.AsTimeSpan.TotalMilliseconds) == false) { process.Kill(); throw new InvalidOperationException($"Unable to get certificate by executing {executable} {args}, waited for {_config.CertificateExecTimeout} ms but the process didn't exit. Stderr: {GetStdError()}"); } try { readStdOut.Wait(_config.CertificateExecTimeout.AsTimeSpan); readErrors.Wait(_config.CertificateExecTimeout.AsTimeSpan); } catch (Exception e) { throw new InvalidOperationException( $"Unable to get certificate by executing {executable} {args}, waited for {_config.CertificateExecTimeout} ms but the process didn't exit. Stderr: {GetStdError()}", e); } if (Logger.IsOperationsEnabled) { var errors = GetStdError(); Logger.Operations(string.Format($"Executing {executable} {args} took {sw.ElapsedMilliseconds:#,#;;0} ms")); if (!string.IsNullOrWhiteSpace(errors)) { Logger.Operations(string.Format($"Executing {executable} {args} finished with exit code: {process.ExitCode}. Errors: {errors}")); } } if (process.ExitCode != 0) { throw new InvalidOperationException( $"Unable to get certificate by executing {executable} {args}, the exit code was {process.ExitCode}. Stderr: {GetStdError()}"); } var rawData = ms.ToArray(); X509Certificate2 loadedCertificate; AsymmetricKeyEntry privateKey; try { // may need to send this over the cluster, so use exportable here loadedCertificate = new X509Certificate2(rawData, (string)null, X509KeyStorageFlags.Exportable); ValidateExpiration(executable, loadedCertificate, serverStore); ValidatePrivateKey(executable, null, rawData, out privateKey); ValidateKeyUsages(executable, loadedCertificate); } catch (Exception e) { throw new InvalidOperationException($"Got invalid certificate via {executable} {args}", e); } return(new RavenServer.CertificateHolder { Certificate = loadedCertificate, CertificateForClients = Convert.ToBase64String(loadedCertificate.Export(X509ContentType.Cert)), PrivateKey = privateKey }); }