mirror of
https://github.com/MichaelGrafnetter/DSInternals
synced 2025-02-16 10:56:49 +00:00
Implemented a slightly more secure handling of GMSA passwords.
This commit is contained in:
parent
8e2a188632
commit
ca52581151
@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace DSInternals.Common.Data
|
||||
namespace DSInternals.Common.Data
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a group-managed service account's password information.
|
||||
/// </summary>
|
||||
@ -25,6 +25,17 @@ namespace DSInternals.Common.Data
|
||||
/// Gets the current password.
|
||||
/// </summary>
|
||||
public string CurrentPassword
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.SecureCurrentPassword.ToUnicodeString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current password.
|
||||
/// </summary>
|
||||
public SecureString SecureCurrentPassword
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
@ -34,6 +45,17 @@ namespace DSInternals.Common.Data
|
||||
/// Gets the previous password.
|
||||
/// </summary>
|
||||
public string PreviousPassword
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.SecurePreviousPassword.ToUnicodeString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the previous password.
|
||||
/// </summary>
|
||||
public SecureString SecurePreviousPassword
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
@ -86,13 +108,13 @@ namespace DSInternals.Common.Data
|
||||
|
||||
// A 16-bit offset, in bytes, from the beginning of this structure to the CurrentPassword field. The CurrentPasswordOffset field MUST NOT be set to 0x0000.
|
||||
short currentPasswordOffset = reader.ReadInt16();
|
||||
this.CurrentPassword = blob.ReadWString(currentPasswordOffset);
|
||||
this.SecureCurrentPassword = blob.ReadSecureWString(currentPasswordOffset);
|
||||
|
||||
// A 16-bit offset, in bytes, from the beginning of this structure to the PreviousPassword field. If this field is set to 0x0000, then the account has no previous password.
|
||||
short previousPasswordOffset = reader.ReadInt16();
|
||||
if(previousPasswordOffset > 0)
|
||||
{
|
||||
this.PreviousPassword = blob.ReadWString(previousPasswordOffset);
|
||||
this.SecurePreviousPassword = blob.ReadSecureWString(previousPasswordOffset);
|
||||
}
|
||||
|
||||
// A 16-bit offset, in bytes, from the beginning of this structure to the QueryPasswordInterval field.
|
||||
|
@ -2,6 +2,7 @@
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
|
||||
@ -62,22 +63,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
public static string ReadWString(this byte[] buffer, int startIndex)
|
||||
public static SecureString ReadSecureWString(this byte[] buffer, int startIndex)
|
||||
{
|
||||
Validator.AssertNotNull(buffer, "buffer");
|
||||
Validator.AssertNotNull(buffer, nameof(buffer));
|
||||
// TODO: Assert startIndex > 0
|
||||
int maxLength = buffer.Length - startIndex;
|
||||
var sb = new StringBuilder(maxLength);
|
||||
|
||||
// Prepare an empty SecureString that will eventually be returned
|
||||
var result = new SecureString();
|
||||
|
||||
for (int i = startIndex; i < buffer.Length; i += UnicodeEncoding.CharSize)
|
||||
{
|
||||
// Convert the next 2 bytes from the byte array into a unicode character
|
||||
char c = BitConverter.ToChar(buffer, i);
|
||||
|
||||
if (c == Char.MinValue)
|
||||
{
|
||||
// End of string reached
|
||||
return sb.ToString();
|
||||
// End of string has been reached
|
||||
return result;
|
||||
}
|
||||
sb.Append(c);
|
||||
|
||||
result.AppendChar(c);
|
||||
}
|
||||
|
||||
// If we reached this point, the \0 char has not been found, so throw an exception.
|
||||
// TODO: Add a reasonable exception message
|
||||
throw new ArgumentException();
|
||||
|
Loading…
Reference in New Issue
Block a user