Skip to content

Commit

Permalink
Merge branch 'master' into pocs
Browse files Browse the repository at this point in the history
  • Loading branch information
Jim8y authored Oct 8, 2024
2 parents 6514458 + 331fa24 commit cbc6f6e
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 5 deletions.
24 changes: 19 additions & 5 deletions src/Plugins/RpcServer/RpcServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.AspNetCore.Server.Kestrel.Https;
using Microsoft.Extensions.DependencyInjection;
using Neo.Extensions;
using Neo.Json;
using Neo.Network.P2P;
using System;
Expand All @@ -26,6 +27,7 @@
using System.Linq.Expressions;
using System.Net.Security;
using System.Reflection;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
Expand All @@ -44,10 +46,18 @@ public partial class RpcServer : IDisposable
private readonly NeoSystem system;
private readonly LocalNode localNode;

// avoid GetBytes every time
private readonly byte[] _rpcUser;
private readonly byte[] _rpcPass;

public RpcServer(NeoSystem system, RpcServerSettings settings)
{
this.system = system;
this.settings = settings;

_rpcUser = settings.RpcUser is not null ? Encoding.UTF8.GetBytes(settings.RpcUser) : [];
_rpcPass = settings.RpcPass is not null ? Encoding.UTF8.GetBytes(settings.RpcPass) : [];

localNode = system.LocalNode.Ask<LocalNode>(new LocalNode.GetInstance()).Result;
RegisterMethods(this);
Initialize_SmartContract();
Expand All @@ -65,21 +75,25 @@ internal bool CheckAuth(HttpContext context)
return false;
}

string authstring;
byte[] auths;
try
{
authstring = Encoding.UTF8.GetString(Convert.FromBase64String(reqauth.Replace("Basic ", "").Trim()));
auths = Convert.FromBase64String(reqauth.Replace("Basic ", "").Trim());
}
catch
{
return false;
}

string[] authvalues = authstring.Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries);
if (authvalues.Length < 2)
int colonIndex = Array.IndexOf(auths, (byte)':');
if (colonIndex == -1)
return false;

return authvalues[0] == settings.RpcUser && authvalues[1] == settings.RpcPass;
byte[] user = auths[..colonIndex];
byte[] pass = auths[(colonIndex + 1)..];

// Always execute both checks, but both must evaluate to true
return CryptographicOperations.FixedTimeEquals(user, _rpcUser) & CryptographicOperations.FixedTimeEquals(pass, _rpcPass);
}

private static JObject CreateErrorResponse(JToken id, RpcError rpcError)
Expand Down
42 changes: 42 additions & 0 deletions tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,47 @@ public void TestCheckAuth_ValidCredentials_ReturnsTrue()
// Assert
Assert.IsTrue(result);
}

[TestMethod]
public void TestCheckAuth()
{
var memoryStoreProvider = new TestMemoryStoreProvider(new MemoryStore());
var neoSystem = new NeoSystem(TestProtocolSettings.SoleNode, memoryStoreProvider);
var rpcServerSettings = RpcServerSettings.Default with
{
SessionEnabled = true,
SessionExpirationTime = TimeSpan.FromSeconds(0.3),
MaxGasInvoke = 1500_0000_0000,
Network = TestProtocolSettings.SoleNode.Network,
RpcUser = "testuser",
RpcPass = "testpass",
};
var rpcServer = new RpcServer(neoSystem, rpcServerSettings);

var context = new DefaultHttpContext();
context.Request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes("testuser:testpass"));
var result = rpcServer.CheckAuth(context);
Assert.IsTrue(result);

context.Request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes("testuser:wrongpass"));
result = rpcServer.CheckAuth(context);
Assert.IsFalse(result);

context.Request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes("wronguser:testpass"));
result = rpcServer.CheckAuth(context);
Assert.IsFalse(result);

context.Request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes("testuser:"));
result = rpcServer.CheckAuth(context);
Assert.IsFalse(result);

context.Request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(":testpass"));
result = rpcServer.CheckAuth(context);
Assert.IsFalse(result);

context.Request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(""));
result = rpcServer.CheckAuth(context);
Assert.IsFalse(result);
}
}
}

0 comments on commit cbc6f6e

Please sign in to comment.