1
0
mirror of https://github.com/bitwarden/server synced 2026-01-03 09:03:44 +00:00

Turn on file scoped namespaces (#2225)

This commit is contained in:
Justin Baur
2022-08-29 14:53:16 -04:00
committed by GitHub
parent 7c4521e0b4
commit 34fb4cca2a
1206 changed files with 73816 additions and 75022 deletions

View File

@@ -36,206 +36,205 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System.Security.Cryptography;
using System.Text;
namespace Bit.Core.Utilities.Duo
namespace Bit.Core.Utilities.Duo;
public static class DuoWeb
{
public static class DuoWeb
private const string DuoProfix = "TX";
private const string AppPrefix = "APP";
private const string AuthPrefix = "AUTH";
private const int DuoExpire = 300;
private const int AppExpire = 3600;
private const int IKeyLength = 20;
private const int SKeyLength = 40;
private const int AKeyLength = 40;
public static string ErrorUser = "ERR|The username passed to sign_request() is invalid.";
public static string ErrorIKey = "ERR|The Duo integration key passed to sign_request() is invalid.";
public static string ErrorSKey = "ERR|The Duo secret key passed to sign_request() is invalid.";
public static string ErrorAKey = "ERR|The application secret key passed to sign_request() must be at least " +
"40 characters.";
public static string ErrorUnknown = "ERR|An unknown error has occurred.";
// throw on invalid bytes
private static Encoding _encoding = new UTF8Encoding(false, true);
private static DateTime _epoc = new DateTime(1970, 1, 1);
/// <summary>
/// Generate a signed request for Duo authentication.
/// The returned value should be passed into the Duo.init() call
/// in the rendered web page used for Duo authentication.
/// </summary>
/// <param name="ikey">Duo integration key</param>
/// <param name="skey">Duo secret key</param>
/// <param name="akey">Application secret key</param>
/// <param name="username">Primary-authenticated username</param>
/// <param name="currentTime">(optional) The current UTC time</param>
/// <returns>signed request</returns>
public static string SignRequest(string ikey, string skey, string akey, string username,
DateTime? currentTime = null)
{
private const string DuoProfix = "TX";
private const string AppPrefix = "APP";
private const string AuthPrefix = "AUTH";
private const int DuoExpire = 300;
private const int AppExpire = 3600;
private const int IKeyLength = 20;
private const int SKeyLength = 40;
private const int AKeyLength = 40;
string duoSig;
string appSig;
public static string ErrorUser = "ERR|The username passed to sign_request() is invalid.";
public static string ErrorIKey = "ERR|The Duo integration key passed to sign_request() is invalid.";
public static string ErrorSKey = "ERR|The Duo secret key passed to sign_request() is invalid.";
public static string ErrorAKey = "ERR|The application secret key passed to sign_request() must be at least " +
"40 characters.";
public static string ErrorUnknown = "ERR|An unknown error has occurred.";
var currentTimeValue = currentTime ?? DateTime.UtcNow;
// throw on invalid bytes
private static Encoding _encoding = new UTF8Encoding(false, true);
private static DateTime _epoc = new DateTime(1970, 1, 1);
/// <summary>
/// Generate a signed request for Duo authentication.
/// The returned value should be passed into the Duo.init() call
/// in the rendered web page used for Duo authentication.
/// </summary>
/// <param name="ikey">Duo integration key</param>
/// <param name="skey">Duo secret key</param>
/// <param name="akey">Application secret key</param>
/// <param name="username">Primary-authenticated username</param>
/// <param name="currentTime">(optional) The current UTC time</param>
/// <returns>signed request</returns>
public static string SignRequest(string ikey, string skey, string akey, string username,
DateTime? currentTime = null)
if (username == string.Empty)
{
string duoSig;
string appSig;
var currentTimeValue = currentTime ?? DateTime.UtcNow;
if (username == string.Empty)
{
return ErrorUser;
}
if (username.Contains("|"))
{
return ErrorUser;
}
if (ikey.Length != IKeyLength)
{
return ErrorIKey;
}
if (skey.Length != SKeyLength)
{
return ErrorSKey;
}
if (akey.Length < AKeyLength)
{
return ErrorAKey;
}
try
{
duoSig = SignVals(skey, username, ikey, DuoProfix, DuoExpire, currentTimeValue);
appSig = SignVals(akey, username, ikey, AppPrefix, AppExpire, currentTimeValue);
}
catch
{
return ErrorUnknown;
}
return $"{duoSig}:{appSig}";
return ErrorUser;
}
if (username.Contains("|"))
{
return ErrorUser;
}
if (ikey.Length != IKeyLength)
{
return ErrorIKey;
}
if (skey.Length != SKeyLength)
{
return ErrorSKey;
}
if (akey.Length < AKeyLength)
{
return ErrorAKey;
}
/// <summary>
/// Validate the signed response returned from Duo.
/// Returns the username of the authenticated user, or null.
/// </summary>
/// <param name="ikey">Duo integration key</param>
/// <param name="skey">Duo secret key</param>
/// <param name="akey">Application secret key</param>
/// <param name="sigResponse">The signed response POST'ed to the server</param>
/// <param name="currentTime">(optional) The current UTC time</param>
/// <returns>authenticated username, or null</returns>
public static string VerifyResponse(string ikey, string skey, string akey, string sigResponse,
DateTime? currentTime = null)
try
{
string authUser = null;
string appUser = null;
var currentTimeValue = currentTime ?? DateTime.UtcNow;
try
{
var sigs = sigResponse.Split(':');
var authSig = sigs[0];
var appSig = sigs[1];
authUser = ParseVals(skey, authSig, AuthPrefix, ikey, currentTimeValue);
appUser = ParseVals(akey, appSig, AppPrefix, ikey, currentTimeValue);
}
catch
{
return null;
}
if (authUser != appUser)
{
return null;
}
return authUser;
duoSig = SignVals(skey, username, ikey, DuoProfix, DuoExpire, currentTimeValue);
appSig = SignVals(akey, username, ikey, AppPrefix, AppExpire, currentTimeValue);
}
catch
{
return ErrorUnknown;
}
private static string SignVals(string key, string username, string ikey, string prefix, long expire,
DateTime currentTime)
return $"{duoSig}:{appSig}";
}
/// <summary>
/// Validate the signed response returned from Duo.
/// Returns the username of the authenticated user, or null.
/// </summary>
/// <param name="ikey">Duo integration key</param>
/// <param name="skey">Duo secret key</param>
/// <param name="akey">Application secret key</param>
/// <param name="sigResponse">The signed response POST'ed to the server</param>
/// <param name="currentTime">(optional) The current UTC time</param>
/// <returns>authenticated username, or null</returns>
public static string VerifyResponse(string ikey, string skey, string akey, string sigResponse,
DateTime? currentTime = null)
{
string authUser = null;
string appUser = null;
var currentTimeValue = currentTime ?? DateTime.UtcNow;
try
{
var ts = (long)(currentTime - _epoc).TotalSeconds;
expire = ts + expire;
var val = $"{username}|{ikey}|{expire.ToString()}";
var cookie = $"{prefix}|{Encode64(val)}";
var sig = Sign(key, cookie);
return $"{cookie}|{sig}";
var sigs = sigResponse.Split(':');
var authSig = sigs[0];
var appSig = sigs[1];
authUser = ParseVals(skey, authSig, AuthPrefix, ikey, currentTimeValue);
appUser = ParseVals(akey, appSig, AppPrefix, ikey, currentTimeValue);
}
catch
{
return null;
}
private static string ParseVals(string key, string val, string prefix, string ikey, DateTime currentTime)
if (authUser != appUser)
{
var ts = (long)(currentTime - _epoc).TotalSeconds;
var parts = val.Split('|');
if (parts.Length != 3)
{
return null;
}
var uPrefix = parts[0];
var uB64 = parts[1];
var uSig = parts[2];
var sig = Sign(key, $"{uPrefix}|{uB64}");
if (Sign(key, sig) != Sign(key, uSig))
{
return null;
}
if (uPrefix != prefix)
{
return null;
}
var cookie = Decode64(uB64);
var cookieParts = cookie.Split('|');
if (cookieParts.Length != 3)
{
return null;
}
var username = cookieParts[0];
var uIKey = cookieParts[1];
var expire = cookieParts[2];
if (uIKey != ikey)
{
return null;
}
var expireTs = Convert.ToInt32(expire);
if (ts >= expireTs)
{
return null;
}
return username;
return null;
}
private static string Sign(string skey, string data)
{
var keyBytes = Encoding.ASCII.GetBytes(skey);
var dataBytes = Encoding.ASCII.GetBytes(data);
return authUser;
}
using (var hmac = new HMACSHA1(keyBytes))
{
var hash = hmac.ComputeHash(dataBytes);
var hex = BitConverter.ToString(hash);
return hex.Replace("-", "").ToLower();
}
private static string SignVals(string key, string username, string ikey, string prefix, long expire,
DateTime currentTime)
{
var ts = (long)(currentTime - _epoc).TotalSeconds;
expire = ts + expire;
var val = $"{username}|{ikey}|{expire.ToString()}";
var cookie = $"{prefix}|{Encode64(val)}";
var sig = Sign(key, cookie);
return $"{cookie}|{sig}";
}
private static string ParseVals(string key, string val, string prefix, string ikey, DateTime currentTime)
{
var ts = (long)(currentTime - _epoc).TotalSeconds;
var parts = val.Split('|');
if (parts.Length != 3)
{
return null;
}
private static string Encode64(string plaintext)
var uPrefix = parts[0];
var uB64 = parts[1];
var uSig = parts[2];
var sig = Sign(key, $"{uPrefix}|{uB64}");
if (Sign(key, sig) != Sign(key, uSig))
{
var plaintextBytes = _encoding.GetBytes(plaintext);
return Convert.ToBase64String(plaintextBytes);
return null;
}
private static string Decode64(string encoded)
if (uPrefix != prefix)
{
var plaintextBytes = Convert.FromBase64String(encoded);
return _encoding.GetString(plaintextBytes);
return null;
}
var cookie = Decode64(uB64);
var cookieParts = cookie.Split('|');
if (cookieParts.Length != 3)
{
return null;
}
var username = cookieParts[0];
var uIKey = cookieParts[1];
var expire = cookieParts[2];
if (uIKey != ikey)
{
return null;
}
var expireTs = Convert.ToInt32(expire);
if (ts >= expireTs)
{
return null;
}
return username;
}
private static string Sign(string skey, string data)
{
var keyBytes = Encoding.ASCII.GetBytes(skey);
var dataBytes = Encoding.ASCII.GetBytes(data);
using (var hmac = new HMACSHA1(keyBytes))
{
var hash = hmac.ComputeHash(dataBytes);
var hex = BitConverter.ToString(hash);
return hex.Replace("-", "").ToLower();
}
}
private static string Encode64(string plaintext)
{
var plaintextBytes = _encoding.GetBytes(plaintext);
return Convert.ToBase64String(plaintextBytes);
}
private static string Decode64(string encoded)
{
var plaintextBytes = Convert.FromBase64String(encoded);
return _encoding.GetString(plaintextBytes);
}
}