summaryrefslogtreecommitdiff
path: root/SecurityIdentifier.cs
diff options
context:
space:
mode:
authorJake Mannens <jake@asger.xyz>2023-10-04 15:59:52 +1100
committerJake Mannens <jake@asger.xyz>2023-10-04 15:59:52 +1100
commitaa0b68f7648bd5a7c14b64737a4f8d3e402bfce5 (patch)
treef058842f77cfbd6e2a21abd3e4f8ad4f8ad1ed9a /SecurityIdentifier.cs
parent33438ac951430fa370965b42a3d98a54e704ab01 (diff)
Fix SID equality and WellKnownSid mappings
Diffstat (limited to 'SecurityIdentifier.cs')
-rw-r--r--SecurityIdentifier.cs79
1 files changed, 62 insertions, 17 deletions
diff --git a/SecurityIdentifier.cs b/SecurityIdentifier.cs
index c3f11ef..075788d 100644
--- a/SecurityIdentifier.cs
+++ b/SecurityIdentifier.cs
@@ -1,16 +1,43 @@
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Runtime.InteropServices;
+using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
namespace HyperBooru;
-public enum WellKnownSidType {
- NullSid,
- WorldSid,
- LocalSid,
- CreatorOwnerSid,
- CreatorGroupSid
+public static class WellKnownSid {
+ public static readonly SecurityIdentifier NullSid = new("S-1-0-0");
+ public static readonly SecurityIdentifier WorldSid = new("S-1-1-0");
+ public static readonly SecurityIdentifier LocalSid = new("S-1-2-0");
+ public static readonly SecurityIdentifier CreatorOwnerSid = new("S-1-3-0");
+ public static readonly SecurityIdentifier CreatorGroupSid = new("S-1-3-1");
+
+ private static readonly (string name, SecurityIdentifier sid)[] nameMap = new[] {
+ ( "Everyone", WorldSid ),
+ ( "LOCAL", LocalSid ),
+ ( "CREATOR OWNER", CreatorGroupSid ),
+ ( "CREATOR GROUP", CreatorGroupSid )
+ };
+
+ public static SecurityIdentifier? TranslateName(string name) {
+ try {
+ return nameMap
+ .First(x => x.name.ToLower() == name.ToLower().Trim())
+ .sid;
+ } catch(InvalidOperationException) {
+ return null;
+ }
+ }
+
+ public static string? TranslateSid(SecurityIdentifier sid) {
+ try {
+ return nameMap.First(x => x.sid == sid).name;
+ } catch(InvalidOperationException) {
+ return null;
+ }
+ }
}
public class SecurityIdentifier {
@@ -19,17 +46,6 @@ public class SecurityIdentifier {
private static readonly Regex SddlRegex =
new(@"^S(-[0-9]+){2,}$", RegexOptions.Compiled);
- private static readonly Dictionary<WellKnownSidType, string> wellKnownSidTypes = new() {
- { HyperBooru.WellKnownSidType.NullSid, "S-1-0-0" },
- { HyperBooru.WellKnownSidType.WorldSid, "S-1-1-0" },
- { HyperBooru.WellKnownSidType.LocalSid, "S-1-2-0" },
- { HyperBooru.WellKnownSidType.CreatorOwnerSid, "S-1-3-0" },
- { HyperBooru.WellKnownSidType.CreatorGroupSid, "S-1-3-1" }
- };
-
- public SecurityIdentifier(WellKnownSidType wellKnownSidType)
- : this(wellKnownSidTypes[wellKnownSidType]) {}
-
public SecurityIdentifier(string sddlForm) {
var match = SddlRegex.Match(sddlForm);
if(!match.Success)
@@ -119,6 +135,35 @@ public struct SidStruct {
public byte[] IdentifierAuthority;
[MarshalAs(UnmanagedType.ByValArray)]
public uint[] SubAuthorities;
+
+ public static bool operator ==(SidStruct? x, SidStruct? y) =>
+ x?.Equals(y) ?? false;
+
+ public static bool operator !=(SidStruct? x, SidStruct? y) =>
+ !(x == y);
+
+ public override bool Equals([NotNullWhen(true)] object? obj) {
+ if(obj is null || obj is not SidStruct)
+ return false;
+
+ var sid = (SidStruct) obj;
+
+ return
+ Revision == sid.Revision &&
+ SubAuthorityCount == sid.SubAuthorityCount &&
+ Enumerable.SequenceEqual(IdentifierAuthority, sid.IdentifierAuthority) &&
+ Enumerable.SequenceEqual(SubAuthorities, sid.SubAuthorities);
+ }
+
+ public override int GetHashCode() => (
+ Revision,
+ SubAuthorityCount,
+ IdentifierAuthority
+ .Select(v => (uint) v)
+ .Aggregate(0, (a, v) => HashCode.Combine(a, v)),
+ SubAuthorities
+ .Aggregate(0, (a, v) => HashCode.Combine(a, v)))
+ .GetHashCode();
}
public class SecurityIdentifierConverter : ValueConverter<SecurityIdentifier, byte[]> {