diff options
author | vnugent <public@vaughnnugent.com> | 2023-01-14 16:24:28 -0500 |
---|---|---|
committer | vnugent <public@vaughnnugent.com> | 2023-01-14 16:24:28 -0500 |
commit | 52b8e30437e235817ed534dec860e781bb0468c0 (patch) | |
tree | b279418c23daec838fab6bf8a0b29c3091d2e300 /lib/Plugins.Essentials/src | |
parent | 0dcecff0f51bdb51b070c05255fbcd9338ab11f2 (diff) |
MemoryUtil native integer size update + tests
Diffstat (limited to 'lib/Plugins.Essentials/src')
-rw-r--r-- | lib/Plugins.Essentials/src/Accounts/AccountUtils.cs (renamed from lib/Plugins.Essentials/src/Accounts/AccountManager.cs) | 74 | ||||
-rw-r--r-- | lib/Plugins.Essentials/src/Accounts/INonce.cs | 42 | ||||
-rw-r--r-- | lib/Plugins.Essentials/src/Accounts/ISecretProvider.cs | 49 | ||||
-rw-r--r-- | lib/Plugins.Essentials/src/Accounts/NonceExtensions.cs | 75 | ||||
-rw-r--r-- | lib/Plugins.Essentials/src/Accounts/PasswordHashing.cs | 50 | ||||
-rw-r--r-- | lib/Plugins.Essentials/src/Extensions/JsonResponse.cs | 9 | ||||
-rw-r--r-- | lib/Plugins.Essentials/src/HttpEntity.cs | 8 | ||||
-rw-r--r-- | lib/Plugins.Essentials/src/Sessions/SessionInfo.cs | 2 |
8 files changed, 222 insertions, 87 deletions
diff --git a/lib/Plugins.Essentials/src/Accounts/AccountManager.cs b/lib/Plugins.Essentials/src/Accounts/AccountUtils.cs index f148fdb..610d646 100644 --- a/lib/Plugins.Essentials/src/Accounts/AccountManager.cs +++ b/lib/Plugins.Essentials/src/Accounts/AccountUtils.cs @@ -39,7 +39,6 @@ using VNLib.Plugins.Essentials.Users; using VNLib.Plugins.Essentials.Sessions; using VNLib.Plugins.Essentials.Extensions; - #nullable enable namespace VNLib.Plugins.Essentials.Accounts @@ -50,7 +49,7 @@ namespace VNLib.Plugins.Essentials.Accounts /// to facilitate unified user-controls, athentication, and security /// application-wide /// </summary> - public static partial class AccountManager + public static partial class AccountUtil { public const int MAX_EMAIL_CHARS = 50; public const int ID_FIELD_CHARS = 65; @@ -104,6 +103,7 @@ namespace VNLib.Plugins.Essentials.Accounts private const string FAILED_LOGIN_ENTRY = "acnt.flc"; private const string LOCAL_ACCOUNT_ENTRY = "acnt.ila"; private const string ACC_ORIGIN_ENTRY = "__.org"; + private const string TOKEN_UPDATE_TIME_ENTRY = "acnt.tut"; //private const string CHALLENGE_HASH_ENTRY = "acnt.chl"; //Privlage masks @@ -164,7 +164,7 @@ namespace VNLib.Plugins.Essentials.Accounts throw new ObjectDisposedException("The specifed user object has been released"); } //Alloc a buffer - using IMemoryHandle<byte> buffer = Memory.SafeAlloc<byte>(size); + using IMemoryHandle<byte> buffer = MemoryUtil.SafeAlloc<byte>(size); //Use the CGN to get a random set RandomHash.GetRandomBytes(buffer.Span); //Hash the new random password @@ -189,6 +189,7 @@ namespace VNLib.Plugins.Essentials.Accounts /// This field is not required /// </summary> /// <returns>The origin of the account</returns> + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string GetAccountOrigin(this IUser ud) => ud[ACC_ORIGIN_ENTRY]; /// <summary> /// If this account was created by any means other than a local account creation. @@ -196,6 +197,7 @@ namespace VNLib.Plugins.Essentials.Accounts /// </summary> /// <param name="ud"></param> /// <param name="origin">Value of the account origin</param> + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SetAccountOrigin(this IUser ud, string origin) => ud[ACC_ORIGIN_ENTRY] = origin; /// <summary> @@ -241,6 +243,8 @@ namespace VNLib.Plugins.Essentials.Accounts { throw new InvalidOperationException("The session is not set or the session is not a web-based session type"); } + //Update session-id for "upgrade" + ev.Session.RegenID(); //derrive token from login data TryGenerateToken(base64PubKey, out string base64ServerToken, out string base64ClientData); //Clear flags @@ -260,6 +264,8 @@ namespace VNLib.Plugins.Essentials.Accounts ev.Session.HasLocalAccount(localAccount); //Store the base64 server key to compute the hmac later ev.Session.Token = base64ServerToken; + //Update the last token upgrade time + ev.Session.LastTokenUpgrade(ev.RequestedTimeUtc); //Return the client encrypted data return base64ClientData; } @@ -325,7 +331,7 @@ namespace VNLib.Plugins.Essentials.Accounts private static void TryGenerateToken(string base64clientPublicKey, out string base64Digest, out string base64ClientData) { //Temporary work buffer - using IMemoryHandle<byte> buffer = Memory.SafeAlloc<byte>(4096, true); + using IMemoryHandle<byte> buffer = MemoryUtil.SafeAlloc<byte>(4096, true); /* * Create a new token buffer for bin buffers. * This buffer struct is used to break up @@ -396,7 +402,7 @@ namespace VNLib.Plugins.Essentials.Accounts * are equal it should mean that the client must have the private * key that generated the public key that was sent */ - using UnsafeMemoryHandle<byte> buffer = Memory.UnsafeAlloc<byte>(TokenHashSize * 2, true); + using UnsafeMemoryHandle<byte> buffer = MemoryUtil.UnsafeAlloc<byte>(TokenHashSize * 2, true); //Slice up buffers Span<byte> headerBuffer = buffer.Span[..TokenHashSize]; Span<byte> sessionBuffer = buffer.Span[TokenHashSize..]; @@ -405,8 +411,31 @@ namespace VNLib.Plugins.Essentials.Accounts && Convert.TryFromBase64String(ev.Session.Token, sessionBuffer, out int sessionTokenLen)) { //Do a fixed time equal (probably overkill, but should not matter too much) - return CryptographicOperations.FixedTimeEquals(headerBuffer[..headerTokenLen], sessionBuffer[..sessionTokenLen]); + if(CryptographicOperations.FixedTimeEquals(headerBuffer[..headerTokenLen], sessionBuffer[..sessionTokenLen])) + { + return true; + } + } + + /* + * If the token does not match, or cannot be found, check if the client + * has login cookies set, if not remove them. + * + * This does not affect the session, but allows for a web client to update + * its login state if its no-longer logged in + */ + + //Expire login cookie if set + if (ev.Server.RequestCookies.ContainsKey(LOGIN_COOKIE_NAME)) + { + ev.Server.ExpireCookie(LOGIN_COOKIE_NAME, sameSite: CookieSameSite.SameSite); } + //Expire the LI cookie if set + if (ev.Server.RequestCookies.ContainsKey(LOGIN_COOKIE_IDENTIFIER)) + { + ev.Server.ExpireCookie(LOGIN_COOKIE_IDENTIFIER, sameSite: CookieSameSite.SameSite); + } + return false; } @@ -432,6 +461,8 @@ namespace VNLib.Plugins.Essentials.Accounts TryGenerateToken(clientPublicKey, out string base64Digest, out string base64ClientData); //store the token to the user's session ev.Session.Token = base64Digest; + //Update the last token upgrade time + ev.Session.LastTokenUpgrade(ev.RequestedTimeUtc); //return the clients encrypted secret return base64ClientData; } @@ -478,7 +509,7 @@ namespace VNLib.Plugins.Essentials.Accounts return false; } //Alloc a buffer for decoding the public key - using UnsafeMemoryHandle<byte> pubKeyBuffer = Memory.UnsafeAlloc<byte>(PUBLIC_KEY_BUFFER_SIZE, true); + using UnsafeMemoryHandle<byte> pubKeyBuffer = MemoryUtil.UnsafeAlloc<byte>(PUBLIC_KEY_BUFFER_SIZE, true); //Decode the public key ERRNO pbkBytesWritten = VnEncoding.TryFromBase64Chars(base64PubKey, pubKeyBuffer); //Try to encrypt the data @@ -590,7 +621,7 @@ namespace VNLib.Plugins.Essentials.Accounts * be 2 * LOGIN_COOKIE_SIZE, and it can be split in half and shared * for both conversions */ - using UnsafeMemoryHandle<byte> buffer = Memory.UnsafeAlloc<byte>(2 * LOGIN_COOKIE_SIZE, true); + using UnsafeMemoryHandle<byte> buffer = MemoryUtil.UnsafeAlloc<byte>(2 * LOGIN_COOKIE_SIZE, true); //Slice up buffers Span<byte> cookieBuffer = buffer.Span[..LOGIN_COOKIE_SIZE]; Span<byte> sessionBuffer = buffer.Span.Slice(LOGIN_COOKIE_SIZE, LOGIN_COOKIE_SIZE); @@ -602,7 +633,7 @@ namespace VNLib.Plugins.Essentials.Accounts if(CryptographicOperations.FixedTimeEquals(cookieBuffer, sessionBuffer)) { //If the user is "logged in" and the request is using the POST method, then we can update the cookie - if(ev.Server.Method == HttpMethod.POST && ev.Session.Created.Add(RegenIdPeriod) < DateTimeOffset.UtcNow) + if(ev.Server.Method == HttpMethod.POST && ev.Session.Created.Add(RegenIdPeriod) < ev.RequestedTimeUtc) { //Regen login token ev.SetLogin(); @@ -655,7 +686,26 @@ namespace VNLib.Plugins.Essentials.Accounts } } } - + + /// <summary> + /// Gets the last time the session token was set + /// </summary> + /// <param name="session"></param> + /// <returns>The last time the token was updated/generated, or <see cref="DateTimeOffset.MinValue"/> if not set</returns> + public static DateTimeOffset LastTokenUpgrade(this in SessionInfo session) + { + //Get the serialized time value + string timeString = session[TOKEN_UPDATE_TIME_ENTRY]; + return long.TryParse(timeString, out long time) ? DateTimeOffset.FromUnixTimeSeconds(time) : DateTimeOffset.MinValue; + } + + /// <summary> + /// Updates the last time the session token was set + /// </summary> + /// <param name="session"></param> + /// <param name="updated">The UTC time the last token was set</param> + private static void LastTokenUpgrade(this in SessionInfo session, DateTimeOffset updated) + => session[TOKEN_UPDATE_TIME_ENTRY] = updated.ToUnixTimeSeconds().ToString(); /// <summary> /// Stores the browser's id during a login process @@ -711,7 +761,7 @@ namespace VNLib.Plugins.Essentials.Accounts //Calculate the password buffer size required int passByteCount = Encoding.UTF8.GetByteCount(rawPass); //Allocate the buffer - using UnsafeMemoryHandle<byte> bufferHandle = Memory.UnsafeAlloc<byte>(passByteCount + 64, true); + using UnsafeMemoryHandle<byte> bufferHandle = MemoryUtil.UnsafeAlloc<byte>(passByteCount + 64, true); //Slice buffers Span<byte> utf8PassBytes = bufferHandle.Span[..passByteCount]; Span<byte> hashBuffer = bufferHandle.Span[passByteCount..]; @@ -750,7 +800,7 @@ namespace VNLib.Plugins.Essentials.Accounts } int bufSize = base32Digest.Length + base64PasswordDigest.Length; //Alloc buffer - using UnsafeMemoryHandle<byte> buffer = Memory.UnsafeAlloc<byte>(bufSize); + using UnsafeMemoryHandle<byte> buffer = MemoryUtil.UnsafeAlloc<byte>(bufSize); //Split buffers Span<byte> localBuf = buffer.Span[..base32Digest.Length]; Span<byte> passBuf = buffer.Span[base32Digest.Length..]; diff --git a/lib/Plugins.Essentials/src/Accounts/INonce.cs b/lib/Plugins.Essentials/src/Accounts/INonce.cs index 7d53183..3a1b779 100644 --- a/lib/Plugins.Essentials/src/Accounts/INonce.cs +++ b/lib/Plugins.Essentials/src/Accounts/INonce.cs @@ -24,9 +24,6 @@ using System; -using VNLib.Utils; -using VNLib.Utils.Memory; - namespace VNLib.Plugins.Essentials.Accounts { /// <summary> @@ -48,43 +45,4 @@ namespace VNLib.Plugins.Essentials.Accounts /// <returns>True if the nonce values are equal, flase otherwise</returns> bool VerifyNonce(ReadOnlySpan<byte> nonceBytes); } - - /// <summary> - /// Provides INonce extensions for computing/verifying nonce values - /// </summary> - public static class NonceExtensions - { - /// <summary> - /// Computes a base32 nonce of the specified size and returns a string - /// representation - /// </summary> - /// <param name="nonce"></param> - /// <param name="size">The size (in bytes) of the nonce</param> - /// <returns>The base32 string of the computed nonce</returns> - public static string ComputeNonce<T>(this T nonce, int size) where T: INonce - { - //Alloc bin buffer - using UnsafeMemoryHandle<byte> buffer = Memory.UnsafeAlloc<byte>(size); - //Compute nonce - nonce.ComputeNonce(buffer.Span); - //Return base32 string - return VnEncoding.ToBase32String(buffer.Span, false); - } - /// <summary> - /// Compares the base32 encoded nonce value against the previously - /// generated nonce - /// </summary> - /// <param name="nonce"></param> - /// <param name="base32Nonce">The base32 encoded nonce string</param> - /// <returns>True if the nonce values are equal, flase otherwise</returns> - public static bool VerifyNonce<T>(this T nonce, ReadOnlySpan<char> base32Nonce) where T : INonce - { - //Alloc bin buffer - using UnsafeMemoryHandle<byte> buffer = Memory.UnsafeAlloc<byte>(base32Nonce.Length); - //Decode base32 nonce - ERRNO count = VnEncoding.TryFromBase32Chars(base32Nonce, buffer.Span); - //Verify nonce - return nonce.VerifyNonce(buffer.Span[..(int)count]); - } - } } diff --git a/lib/Plugins.Essentials/src/Accounts/ISecretProvider.cs b/lib/Plugins.Essentials/src/Accounts/ISecretProvider.cs new file mode 100644 index 0000000..41fb44d --- /dev/null +++ b/lib/Plugins.Essentials/src/Accounts/ISecretProvider.cs @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2022 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Plugins.Essentials +* File: ISecretProvider.cs +* +* ISecretProvider.cs is part of VNLib.Plugins.Essentials which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Plugins.Essentials is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Plugins.Essentials is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +using System; + +using VNLib.Utils; + +namespace VNLib.Plugins.Essentials.Accounts +{ + /// <summary> + /// Provides a password hashing secret aka pepper. + /// </summary> + public interface ISecretProvider + { + /// <summary> + /// The size of the buffer to use when retrieving the secret + /// </summary> + int BufferSize { get; } + + /// <summary> + /// Writes the secret to the buffer and returns the number of bytes + /// written to the buffer + /// </summary> + /// <param name="buffer">The buffer to write the secret data to</param> + /// <returns>The number of secret bytes written to the buffer</returns> + ERRNO GetSecret(Span<byte> buffer); + } +}
\ No newline at end of file diff --git a/lib/Plugins.Essentials/src/Accounts/NonceExtensions.cs b/lib/Plugins.Essentials/src/Accounts/NonceExtensions.cs new file mode 100644 index 0000000..5a40d29 --- /dev/null +++ b/lib/Plugins.Essentials/src/Accounts/NonceExtensions.cs @@ -0,0 +1,75 @@ +/* +* Copyright (c) 2022 Vaughn Nugent +* +* Library: VNLib +* Package: VNLib.Plugins.Essentials +* File: NonceExtensions.cs +* +* NonceExtensions.cs is part of VNLib.Plugins.Essentials which is part of the larger +* VNLib collection of libraries and utilities. +* +* VNLib.Plugins.Essentials is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License as +* published by the Free Software Foundation, either version 3 of the +* License, or (at your option) any later version. +* +* VNLib.Plugins.Essentials is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ + +using System; + +using VNLib.Utils; +using VNLib.Utils.Memory; + +namespace VNLib.Plugins.Essentials.Accounts +{ + /// <summary> + /// Provides INonce extensions for computing/verifying nonce values + /// </summary> + public static class NonceExtensions + { + /// <summary> + /// Computes a base32 nonce of the specified size and returns a string + /// representation + /// </summary> + /// <param name="nonce"></param> + /// <param name="size">The size (in bytes) of the nonce</param> + /// <returns>The base32 string of the computed nonce</returns> + public static string ComputeNonce<T>(this T nonce, int size) where T: INonce + { + //Alloc bin buffer + using UnsafeMemoryHandle<byte> buffer = MemoryUtil.UnsafeAlloc<byte>(size); + + //Compute nonce + nonce.ComputeNonce(buffer.Span); + + //Return base32 string + return VnEncoding.ToBase32String(buffer.Span, false); + } + + /// <summary> + /// Compares the base32 encoded nonce value against the previously + /// generated nonce + /// </summary> + /// <param name="nonce"></param> + /// <param name="base32Nonce">The base32 encoded nonce string</param> + /// <returns>True if the nonce values are equal, flase otherwise</returns> + public static bool VerifyNonce<T>(this T nonce, ReadOnlySpan<char> base32Nonce) where T : INonce + { + //Alloc bin buffer + using UnsafeMemoryHandle<byte> buffer = MemoryUtil.UnsafeAlloc<byte>(base32Nonce.Length); + + //Decode base32 nonce + ERRNO count = VnEncoding.TryFromBase32Chars(base32Nonce, buffer.Span); + + //Verify nonce + return nonce.VerifyNonce(buffer.Span[..(int)count]); + } + } +} diff --git a/lib/Plugins.Essentials/src/Accounts/PasswordHashing.cs b/lib/Plugins.Essentials/src/Accounts/PasswordHashing.cs index 1c3770b..9dc3ea1 100644 --- a/lib/Plugins.Essentials/src/Accounts/PasswordHashing.cs +++ b/lib/Plugins.Essentials/src/Accounts/PasswordHashing.cs @@ -32,21 +32,12 @@ using VNLib.Utils.Memory; namespace VNLib.Plugins.Essentials.Accounts { /// <summary> - /// A delegate method to recover a temporary copy of the secret/pepper - /// for a request - /// </summary> - /// <param name="buffer">The buffer to write the pepper to</param> - /// <returns>The number of bytes written to the buffer</returns> - public delegate ERRNO SecretAction(Span<byte> buffer); - - /// <summary> - /// Provides a structrued password hashing system implementing the <seealso cref="VnArgon2"/> library + /// Provides a structured password hashing system implementing the <seealso cref="VnArgon2"/> library /// with fixed time comparison /// </summary> public sealed class PasswordHashing { - private readonly SecretAction _getter; - private readonly int _secretSize; + private readonly ISecretProvider _secret; private readonly uint TimeCost; private readonly uint MemoryCost; @@ -57,23 +48,20 @@ namespace VNLib.Plugins.Essentials.Accounts /// <summary> /// Initalizes the <see cref="PasswordHashing"/> class /// </summary> - /// <param name="getter"></param> - /// <param name="secreteSize">The expected size of the secret (the size of the buffer to alloc for a copy)</param> + /// <param name="secret">The password secret provider</param> /// <param name="saltLen">A positive integer for the size of the random salt used during the hashing proccess</param> /// <param name="timeCost">The Argon2 time cost parameter</param> /// <param name="memoryCost">The Argon2 memory cost parameter</param> /// <param name="hashLen">The size of the hash to produce during hashing operations</param> /// <param name="parallism"> /// The Argon2 parallelism parameter (the number of threads to use for hasing) - /// (default = 0 - the number of processors) + /// (default = 0 - defaults to the number of logical processors) /// </param> /// <exception cref="ArgumentNullException"></exception> - /// <exception cref="ArgumentOutOfRangeException"></exception> - public PasswordHashing(SecretAction getter, int secreteSize, int saltLen = 32, uint timeCost = 4, uint memoryCost = UInt16.MaxValue, uint parallism = 0, uint hashLen = 128) + public PasswordHashing(ISecretProvider secret, int saltLen = 32, uint timeCost = 4, uint memoryCost = UInt16.MaxValue, uint parallism = 0, uint hashLen = 128) { //Store getter - _getter = getter ?? throw new ArgumentNullException(nameof(getter)); - _secretSize = secreteSize; + _secret = secret ?? throw new ArgumentNullException(nameof(secret)); //Store parameters HashLen = hashLen; @@ -114,18 +102,18 @@ namespace VNLib.Plugins.Essentials.Accounts return false; } //alloc secret buffer - using UnsafeMemoryHandle<byte> secretBuffer = Memory.UnsafeAlloc<byte>(_secretSize, true); + using UnsafeMemoryHandle<byte> secretBuffer = MemoryUtil.UnsafeAlloc<byte>(_secret.BufferSize, true); try { //Get the secret from the callback - ERRNO count = _getter(secretBuffer.Span); + ERRNO count = _secret.GetSecret(secretBuffer.Span); //Verify return VnArgon2.Verify2id(password, passHash, secretBuffer.Span[..(int)count]); } finally { //Erase secret buffer - Memory.InitializeBlock(secretBuffer.Span); + MemoryUtil.InitializeBlock(secretBuffer.Span); } } /// <summary> @@ -140,7 +128,7 @@ namespace VNLib.Plugins.Essentials.Accounts public bool Verify(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> salt, ReadOnlySpan<byte> password) { //Alloc a buffer with the same size as the hash - using UnsafeMemoryHandle<byte> hashBuf = Memory.UnsafeAlloc<byte>(hash.Length, true); + using UnsafeMemoryHandle<byte> hashBuf = MemoryUtil.UnsafeAlloc<byte>(hash.Length, true); //Hash the password with the current config Hash(password, salt, hashBuf.Span); //Compare the hashed password to the specified hash and return results @@ -164,7 +152,7 @@ namespace VNLib.Plugins.Essentials.Accounts public PrivateString Hash(ReadOnlySpan<char> password) { //Alloc shared buffer for the salt and secret buffer - using UnsafeMemoryHandle<byte> buffer = Memory.UnsafeAlloc<byte>(SaltLen + _secretSize, true); + using UnsafeMemoryHandle<byte> buffer = MemoryUtil.UnsafeAlloc<byte>(SaltLen + _secret.BufferSize, true); try { //Split buffers @@ -175,14 +163,14 @@ namespace VNLib.Plugins.Essentials.Accounts RandomHash.GetRandomBytes(saltBuf); //recover the secret - ERRNO count = _getter(secretBuf); + ERRNO count = _secret.GetSecret(secretBuf); //Hashes a password, with the current parameters return (PrivateString)VnArgon2.Hash2id(password, saltBuf, secretBuf[..(int)count], TimeCost, MemoryCost, Parallelism, HashLen); } finally { - Memory.InitializeBlock(buffer.Span); + MemoryUtil.InitializeBlock(buffer.Span); } } @@ -194,7 +182,7 @@ namespace VNLib.Plugins.Essentials.Accounts /// <returns>A <see cref="PrivateString"/> of the hashed and encoded password</returns> public PrivateString Hash(ReadOnlySpan<byte> password) { - using UnsafeMemoryHandle<byte> buffer = Memory.UnsafeAlloc<byte>(SaltLen + _secretSize, true); + using UnsafeMemoryHandle<byte> buffer = MemoryUtil.UnsafeAlloc<byte>(SaltLen + _secret.BufferSize, true); try { //Split buffers @@ -205,14 +193,14 @@ namespace VNLib.Plugins.Essentials.Accounts RandomHash.GetRandomBytes(saltBuf); //recover the secret - ERRNO count = _getter(secretBuf); + ERRNO count = _secret.GetSecret(secretBuf); //Hashes a password, with the current parameters return (PrivateString)VnArgon2.Hash2id(password, saltBuf, secretBuf[..(int)count], TimeCost, MemoryCost, Parallelism, HashLen); } finally { - Memory.InitializeBlock(buffer.Span); + MemoryUtil.InitializeBlock(buffer.Span); } } /// <summary> @@ -226,18 +214,18 @@ namespace VNLib.Plugins.Essentials.Accounts public void Hash(ReadOnlySpan<byte> password, ReadOnlySpan<byte> salt, Span<byte> hashOutput) { //alloc secret buffer - using UnsafeMemoryHandle<byte> secretBuffer = Memory.UnsafeAlloc<byte>(_secretSize, true); + using UnsafeMemoryHandle<byte> secretBuffer = MemoryUtil.UnsafeAlloc<byte>(_secret.BufferSize, true); try { //Get the secret from the callback - ERRNO count = _getter(secretBuffer.Span); + ERRNO count = _secret.GetSecret(secretBuffer.Span); //Hashes a password, with the current parameters VnArgon2.Hash2id(password, salt, secretBuffer.Span[..(int)count], hashOutput, TimeCost, MemoryCost, Parallelism); } finally { //Erase secret buffer - Memory.InitializeBlock(secretBuffer.Span); + MemoryUtil.InitializeBlock(secretBuffer.Span); } } } diff --git a/lib/Plugins.Essentials/src/Extensions/JsonResponse.cs b/lib/Plugins.Essentials/src/Extensions/JsonResponse.cs index 22cccd9..d087c06 100644 --- a/lib/Plugins.Essentials/src/Extensions/JsonResponse.cs +++ b/lib/Plugins.Essentials/src/Extensions/JsonResponse.cs @@ -49,12 +49,19 @@ namespace VNLib.Plugins.Essentials.Extensions internal JsonResponse(IObjectRental<JsonResponse> pool) { + /* + * I am breaking the memoryhandle rules by referrencing the same + * memory handle in two different wrappers. + */ + _pool = pool; //Alloc buffer - _handle = Memory.Shared.Alloc<byte>(4096, false); + _handle = MemoryUtil.Shared.Alloc<byte>(4096, false); + //Consume handle for stream, but make sure not to dispose the stream _asStream = VnMemoryStream.ConsumeHandle(_handle, 0, false); + //Get memory owner from handle _memoryOwner = _handle.ToMemoryManager(false); } diff --git a/lib/Plugins.Essentials/src/HttpEntity.cs b/lib/Plugins.Essentials/src/HttpEntity.cs index ffad607..416b004 100644 --- a/lib/Plugins.Essentials/src/HttpEntity.cs +++ b/lib/Plugins.Essentials/src/HttpEntity.cs @@ -77,6 +77,9 @@ namespace VNLib.Plugins.Essentials IsLocalConnection = entity.Server.LocalEndpoint.Address.IsLocalSubnet(TrustedRemoteIp); //Cache value IsSecure = entity.Server.IsSecure(IsBehindDownStreamServer); + + //Cache current time + RequestedTimeUtc = DateTimeOffset.UtcNow; } /// <summary> @@ -100,6 +103,11 @@ namespace VNLib.Plugins.Essentials /// or behind a trusted downstream server that is using tls. /// </summary> public readonly bool IsSecure; + /// <summary> + /// Caches a <see cref="DateTimeOffset"/> that was created when the connection was created. + /// The approximate current UTC time + /// </summary> + public readonly DateTimeOffset RequestedTimeUtc; /// <summary> /// The connection info object assocated with the entity diff --git a/lib/Plugins.Essentials/src/Sessions/SessionInfo.cs b/lib/Plugins.Essentials/src/Sessions/SessionInfo.cs index 13e2a84..6a974e0 100644 --- a/lib/Plugins.Essentials/src/Sessions/SessionInfo.cs +++ b/lib/Plugins.Essentials/src/Sessions/SessionInfo.cs @@ -106,7 +106,7 @@ namespace VNLib.Plugins.Essentials.Sessions /// </summary> public readonly Uri SpecifiedOrigin; /// <summary> - /// Privilages associated with user specified during login + /// The time the session was created /// </summary> public readonly DateTimeOffset Created; /// <summary> |