aboutsummaryrefslogtreecommitdiff
path: root/lib/Plugins.Essentials/src
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-01-14 16:24:28 -0500
committerLibravatar vnugent <public@vaughnnugent.com>2023-01-14 16:24:28 -0500
commit52b8e30437e235817ed534dec860e781bb0468c0 (patch)
treeb279418c23daec838fab6bf8a0b29c3091d2e300 /lib/Plugins.Essentials/src
parent0dcecff0f51bdb51b070c05255fbcd9338ab11f2 (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.cs42
-rw-r--r--lib/Plugins.Essentials/src/Accounts/ISecretProvider.cs49
-rw-r--r--lib/Plugins.Essentials/src/Accounts/NonceExtensions.cs75
-rw-r--r--lib/Plugins.Essentials/src/Accounts/PasswordHashing.cs50
-rw-r--r--lib/Plugins.Essentials/src/Extensions/JsonResponse.cs9
-rw-r--r--lib/Plugins.Essentials/src/HttpEntity.cs8
-rw-r--r--lib/Plugins.Essentials/src/Sessions/SessionInfo.cs2
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>