validate incoming cid's
This commit is contained in:
@@ -5,7 +5,7 @@ namespace LightlessSyncServer.Configuration;
|
|||||||
|
|
||||||
public class BroadcastConfiguration : IBroadcastConfiguration
|
public class BroadcastConfiguration : IBroadcastConfiguration
|
||||||
{
|
{
|
||||||
private static readonly TimeSpan DefaultEntryTtl = TimeSpan.FromMinutes(5);
|
private static readonly TimeSpan DefaultEntryTtl = TimeSpan.FromMinutes(180);
|
||||||
private const int DefaultMaxStatusBatchSize = 30;
|
private const int DefaultMaxStatusBatchSize = 30;
|
||||||
private const string DefaultNotificationTemplate = "{DisplayName} sent you a pair request. To accept, right-click them, open the context menu, and send a request back.";
|
private const string DefaultNotificationTemplate = "{DisplayName} sent you a pair request. To accept, right-click them, open the context menu, and send a request back.";
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ public class BroadcastOptions
|
|||||||
public string RedisKeyPrefix { get; set; } = "broadcast:";
|
public string RedisKeyPrefix { get; set; } = "broadcast:";
|
||||||
|
|
||||||
[Range(1, int.MaxValue)]
|
[Range(1, int.MaxValue)]
|
||||||
public int EntryTtlSeconds { get; set; } = 300;
|
public int EntryTtlSeconds { get; set; } = 10800;
|
||||||
|
|
||||||
[Range(1, int.MaxValue)]
|
[Range(1, int.MaxValue)]
|
||||||
public int MaxStatusBatchSize { get; set; } = 30;
|
public int MaxStatusBatchSize { get; set; } = 30;
|
||||||
|
|||||||
@@ -371,11 +371,6 @@ public partial class LightlessHub
|
|||||||
return new GroupJoinInfoDto(group.ToGroupData(), group.Owner.ToUserData(), group.ToEnum(), true);
|
return new GroupJoinInfoDto(group.ToGroupData(), group.Owner.ToUserData(), group.ToEnum(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsHex(char c) =>
|
|
||||||
(c >= '0' && c <= '9') ||
|
|
||||||
(c >= 'a' && c <= 'f') ||
|
|
||||||
(c >= 'A' && c <= 'F');
|
|
||||||
|
|
||||||
[Authorize(Policy = "Identified")]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task<bool> GroupJoinFinalize(GroupJoinDto dto)
|
public async Task<bool> GroupJoinFinalize(GroupJoinDto dto)
|
||||||
{
|
{
|
||||||
@@ -386,7 +381,7 @@ public partial class LightlessHub
|
|||||||
var group = await DbContext.Groups.Include(g => g.Owner).AsNoTracking().SingleOrDefaultAsync(g => g.GID == aliasOrGid || g.Alias == aliasOrGid, cancellationToken: _contextAccessor.HttpContext.RequestAborted).ConfigureAwait(false);
|
var group = await DbContext.Groups.Include(g => g.Owner).AsNoTracking().SingleOrDefaultAsync(g => g.GID == aliasOrGid || g.Alias == aliasOrGid, cancellationToken: _contextAccessor.HttpContext.RequestAborted).ConfigureAwait(false);
|
||||||
var groupGid = group?.GID ?? string.Empty;
|
var groupGid = group?.GID ?? string.Empty;
|
||||||
var existingPair = await DbContext.GroupPairs.AsNoTracking().SingleOrDefaultAsync(g => g.GroupGID == groupGid && g.GroupUserUID == UserUID).ConfigureAwait(false);
|
var existingPair = await DbContext.GroupPairs.AsNoTracking().SingleOrDefaultAsync(g => g.GroupGID == groupGid && g.GroupUserUID == UserUID).ConfigureAwait(false);
|
||||||
var isHashedPassword = dto.Password.Length == 64 && dto.Password.All(IsHex);
|
var isHashedPassword = dto.Password.Length == 64 && dto.Password.All(Uri.IsHexDigit);
|
||||||
var hashedPw = isHashedPassword
|
var hashedPw = isHashedPassword
|
||||||
? dto.Password
|
? dto.Password
|
||||||
: StringUtils.Sha256String(dto.Password);
|
: StringUtils.Sha256String(dto.Password);
|
||||||
|
|||||||
@@ -148,6 +148,13 @@ public partial class LightlessHub
|
|||||||
if (string.IsNullOrWhiteSpace(otherCid) || string.IsNullOrWhiteSpace(myCid))
|
if (string.IsNullOrWhiteSpace(otherCid) || string.IsNullOrWhiteSpace(myCid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
bool IsValidCid(string cid) => cid.Length == 64 && cid.All(Uri.IsHexDigit) && !cid.All(c => c == '0');
|
||||||
|
|
||||||
|
if (!IsValidCid(myCid) || !IsValidCid(otherCid))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (string.Equals(otherCid, myCid, StringComparison.Ordinal))
|
if (string.Equals(otherCid, myCid, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Warning, "You can't pair with yourself.").ConfigureAwait(false);
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Warning, "You can't pair with yourself.").ConfigureAwait(false);
|
||||||
@@ -338,6 +345,18 @@ public partial class LightlessHub
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(hashedCid) || hashedCid.Length != 64 || !hashedCid.All(c => Uri.IsHexDigit(c)))
|
||||||
|
{
|
||||||
|
_logger.LogCallWarning(LightlessHubLogger.Args("invalid cid format", UserUID, "CID", hashedCid));
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "Invalid CID format.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hashedCid.All(c => c == '0'))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var db = _redis.Database;
|
var db = _redis.Database;
|
||||||
var broadcastKey = _broadcastConfiguration.BuildRedisKey(hashedCid);
|
var broadcastKey = _broadcastConfiguration.BuildRedisKey(hashedCid);
|
||||||
|
|
||||||
@@ -438,6 +457,18 @@ public partial class LightlessHub
|
|||||||
if (!_broadcastConfiguration.EnableBroadcasting)
|
if (!_broadcastConfiguration.EnableBroadcasting)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(hashedCid) || hashedCid.Length != 64 || !hashedCid.All(c => Uri.IsHexDigit(c)))
|
||||||
|
{
|
||||||
|
_logger.LogCallWarning(LightlessHubLogger.Args("invalid cid format", UserUID, "CID", hashedCid));
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "Invalid CID format.").ConfigureAwait(false);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hashedCid.All(c => c == '0'))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var db = _redis.Database;
|
var db = _redis.Database;
|
||||||
var key = _broadcastConfiguration.BuildRedisKey(hashedCid);
|
var key = _broadcastConfiguration.BuildRedisKey(hashedCid);
|
||||||
|
|
||||||
@@ -479,6 +510,18 @@ public partial class LightlessHub
|
|||||||
if (!_broadcastConfiguration.EnableBroadcasting)
|
if (!_broadcastConfiguration.EnableBroadcasting)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(hashedCid) || hashedCid.Length != 64 || !hashedCid.All(c => Uri.IsHexDigit(c)))
|
||||||
|
{
|
||||||
|
_logger.LogCallWarning(LightlessHubLogger.Args("invalid cid format", UserUID, "CID", hashedCid));
|
||||||
|
await Clients.Caller.Client_ReceiveServerMessage(MessageSeverity.Error, "Invalid CID format.").ConfigureAwait(false);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hashedCid.All(c => c == '0'))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var db = _redis.Database;
|
var db = _redis.Database;
|
||||||
var key = _broadcastConfiguration.BuildRedisKey(hashedCid);
|
var key = _broadcastConfiguration.BuildRedisKey(hashedCid);
|
||||||
|
|
||||||
@@ -542,6 +585,14 @@ public partial class LightlessHub
|
|||||||
var tasks = new Dictionary<string, Task<RedisValueWithExpiry>>(hashedCids.Count);
|
var tasks = new Dictionary<string, Task<RedisValueWithExpiry>>(hashedCids.Count);
|
||||||
foreach (var cid in hashedCids)
|
foreach (var cid in hashedCids)
|
||||||
{
|
{
|
||||||
|
bool validHash = !string.IsNullOrWhiteSpace(cid) && cid.Length == 64 && cid.All(Uri.IsHexDigit) && !cid.All(c => c == '0');
|
||||||
|
|
||||||
|
if (!validHash)
|
||||||
|
{
|
||||||
|
tasks[cid] = Task.FromResult(new RedisValueWithExpiry(RedisValue.Null, null));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var key = _broadcastConfiguration.BuildRedisKey(cid);
|
var key = _broadcastConfiguration.BuildRedisKey(cid);
|
||||||
tasks[cid] = db.StringGetWithExpiryAsync(key);
|
tasks[cid] = db.StringGetWithExpiryAsync(key);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user