forked from UniStuttgart-VISUS/Visus.LdapAuthentication
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SidConverter.cs
88 lines (75 loc) · 3.38 KB
/
SidConverter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// <copyright file="SidConverter.cs" company="Visualisierungsinstitut der Universität Stuttgart">
// Copyright © 2021 - 2024 Visualisierungsinstitut der Universität Stuttgart.
// Licensed under the MIT licence. See LICENCE file for details.
// </copyright>
// <author>Christoph Müller</author>
using System;
using System.DirectoryServices.Protocols;
using System.Linq;
using System.Text;
using Visus.DirectoryAuthentication.Properties;
namespace Visus.DirectoryAuthentication {
/// <summary>
/// Provides a platform-independent implementation for converting Windows
/// security identifiers.
/// </summary>
public sealed class SidConverter : ILdapAttributeConverter {
#region Public class methods
/// <summary>
/// Converts the raw bytes of a SID into the well-known string
/// representation.
/// </summary>
/// <remarks>
/// This method manually converts a SID into a string. We cannot use
/// the built-in features of C# here, because we are running on Linux.
/// See also https://devblogs.microsoft.com/oldnewthing/20040315-00/?p=40253
/// and https://docs.microsoft.com/en-us/windows/desktop/secauthz/sid-components.
/// </remarks>
/// <param name="sid">The byte representation of the SID. It is safe to
/// pass <c>null</c>, in which case the result will be <c>null</c> as
/// well.</param>
/// <returns>The string representation of the SID.</returns>
/// <exception cref="ArgumentException">In case <paramref name="sid"/>
/// is not <c>null</c> and shorter than two bytes.</exception>
public static string Convert(byte[] sid) {
if (sid == null) {
return null;
}
if (sid.Length < 2) {
var msg = Resources.ErrorInvalidSid;
msg = string.Format(msg, BitConverter.ToString(sid));
throw new ArgumentException(msg, nameof(sid));
}
// Start with the mandatory "S-".
var sb = new StringBuilder("S-");
// Continue by adding the revision level.
sb.AppendFormat("{0}-", sid[0]);
// Determine the number of sub-authorities.
var subAuthorities = (int) sid[1];
if (sid.Length != 2 + 6 + subAuthorities * 4) {
var msg = Resources.ErrorInvalidSid;
msg = string.Format(msg, BitConverter.ToString(sid));
throw new ArgumentException(msg, nameof(sid));
}
// Retrieve the authority, which is a 48-bit big-endian number.
var authority = BitConverter.ToUInt32(
sid.Skip(2).Take(6).Reverse().ToArray());
sb.AppendFormat("{0}", authority);
// Retrieve the sub-authorities, which are 32-bit little-endian
// numbers.
for (int i = 0; i < subAuthorities; ++i) {
sb.AppendFormat("-{0}", BitConverter.ToUInt32(
sid, 2 + 6 + i * 4));
}
return sb.ToString();
}
#endregion
#region Public methods
/// <inheritdoc />
public object Convert(DirectoryAttribute attribute, object parameter) {
_ = attribute ?? throw new ArgumentNullException(nameof(attribute));
return Convert((byte[]) attribute[0]);
}
#endregion
}
}