From e79334a6f6fa4439ec70148a9051084db3cd30bf Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Mon, 25 Mar 2019 12:59:42 +0900 Subject: [PATCH] Fix: if anyone can create invoice and /invoices has storeId parameters, then it should be allowed --- BTCPayServer.Tests/BTCPayServerTester.cs | 6 +++- BTCPayServer.Tests/UnitTest1.cs | 43 ++++++++++++++++++++++++ BTCPayServer/Hosting/BTCpayMiddleware.cs | 5 ++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/BTCPayServer.Tests/BTCPayServerTester.cs b/BTCPayServer.Tests/BTCPayServerTester.cs index add697e31..5967e75c0 100644 --- a/BTCPayServer.Tests/BTCPayServerTester.cs +++ b/BTCPayServer.Tests/BTCPayServerTester.cs @@ -35,6 +35,7 @@ using System.Text; using System.Threading; using Xunit; using BTCPayServer.Services; +using System.Net.Http; namespace BTCPayServer.Tests { @@ -120,7 +121,8 @@ namespace BTCPayServer.Tests File.WriteAllText(confPath, config.ToString()); ServerUri = new Uri("http://" + HostName + ":" + Port + "/"); - + HttpClient = new HttpClient(); + HttpClient.BaseAddress = ServerUri; Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development"); var conf = new DefaultConfiguration() { Logger = Logs.LogProvider.CreateLogger("Console") }.CreateConfiguration(new[] { "--datadir", _Directory, "--conf", confPath, "--disable-registration", "false" }); _Host = new WebHostBuilder() @@ -209,6 +211,8 @@ namespace BTCPayServer.Tests } } + public HttpClient HttpClient { get; set; } + public string HostName { get; diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 543012a85..46c263829 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -1096,6 +1096,49 @@ namespace BTCPayServer.Tests return invoice2.CryptoInfo[0].Rate; } + [Fact] + [Trait("Integration", "Integration")] + public async Task CanUseAnyoneCanCreateInvoice() + { + using (var tester = ServerTester.Create()) + { + tester.Start(); + var user = tester.NewAccount(); + user.GrantAccess(); + user.RegisterDerivationScheme("BTC"); + + Logs.Tester.LogInformation("StoreId without anyone can create invoice = 401"); + var response = await tester.PayTester.HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Post, $"invoices?storeId={user.StoreId}") + { + Content = new StringContent("{\"Price\": 5000, \"currency\": \"USD\"}", Encoding.UTF8, "application/json"), + }); + Assert.Equal(401, (int)response.StatusCode); + + Logs.Tester.LogInformation("No store without anyone can create invoice = 404 because the bitpay API can't know the storeid"); + response = await tester.PayTester.HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Post, $"invoices") + { + Content = new StringContent("{\"Price\": 5000, \"currency\": \"USD\"}", Encoding.UTF8, "application/json"), + }); + Assert.Equal(404, (int)response.StatusCode); + + user.ModifyStore(s => s.AnyoneCanCreateInvoice = true); + + Logs.Tester.LogInformation("Bad store with anyone can create invoice = 401"); + response = await tester.PayTester.HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Post, $"invoices?storeId=badid") + { + Content = new StringContent("{\"Price\": 5000, \"currency\": \"USD\"}", Encoding.UTF8, "application/json"), + }); + Assert.Equal(401, (int)response.StatusCode); + + Logs.Tester.LogInformation("Good store with anyone can create invoice = 200"); + response = await tester.PayTester.HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Post, $"invoices?storeId={user.StoreId}") + { + Content = new StringContent("{\"Price\": 5000, \"currency\": \"USD\"}", Encoding.UTF8, "application/json"), + }); + Assert.Equal(200, (int)response.StatusCode); + } + } + [Fact] [Trait("Integration", "Integration")] public void CanTweakRate() diff --git a/BTCPayServer/Hosting/BTCpayMiddleware.cs b/BTCPayServer/Hosting/BTCpayMiddleware.cs index b3ff43b08..4ebf18531 100644 --- a/BTCPayServer/Hosting/BTCpayMiddleware.cs +++ b/BTCPayServer/Hosting/BTCpayMiddleware.cs @@ -88,6 +88,9 @@ namespace BTCPayServer.Hosting if (!httpContext.Request.Path.HasValue) return false; + // In case of anyone can create invoice, the storeId can be set explicitely + bitpayAuth |= httpContext.Request.Query.ContainsKey("storeid"); + var isJson = (httpContext.Request.ContentType ?? string.Empty).StartsWith("application/json", StringComparison.OrdinalIgnoreCase); var path = httpContext.Request.Path.Value; var method = httpContext.Request.Method; @@ -95,7 +98,7 @@ namespace BTCPayServer.Hosting if ( (isCors || bitpayAuth) && - (path == "/invoices" || path == "/invoices/") && + (path == "/invoices" || path == "/invoices/") && (isCors || (method == "POST" && isJson))) return true;