mirror of
https://github.com/bitwarden/server.git
synced 2024-12-04 14:13:28 +01:00
122 lines
4.0 KiB
C#
122 lines
4.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Linq;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.Models;
|
|
using DbUp.Engine;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace Bit.Migrator.DbScripts
|
|
{
|
|
class ScriptMigrateU2FToWebAuthn : IScript
|
|
{
|
|
|
|
public string ProvideScript(Func<IDbCommand> commandFactory)
|
|
{
|
|
var cmd = commandFactory();
|
|
cmd.CommandText = "SELECT Id, TwoFactorProviders FROM [dbo].[User] WHERE TwoFactorProviders IS NOT NULL";
|
|
|
|
var users = new List<object>();
|
|
|
|
using (var reader = cmd.ExecuteReader())
|
|
{
|
|
while (reader.Read())
|
|
{
|
|
var id = reader.GetGuid(0);
|
|
var twoFactorProviders = reader.GetString(1);
|
|
|
|
if (string.IsNullOrWhiteSpace(twoFactorProviders))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var providers = JsonConvert.DeserializeObject<Dictionary<TwoFactorProviderType, TwoFactorProvider>>(twoFactorProviders);
|
|
|
|
if (!providers.ContainsKey(TwoFactorProviderType.U2f))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var u2fProvider = providers[TwoFactorProviderType.U2f];
|
|
|
|
if (!u2fProvider.Enabled || !HasProperMetaData(u2fProvider))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var u2fKeys = LoadKeys(u2fProvider);
|
|
var webAuthnKeys = u2fKeys.Select(key => (key.Item1, key.Item2.ToWebAuthnData()));
|
|
|
|
var webAuthnProvider = new TwoFactorProvider
|
|
{
|
|
Enabled = true,
|
|
MetaData = webAuthnKeys.ToDictionary(x => x.Item1, x => (object)x.Item2)
|
|
};
|
|
|
|
providers[TwoFactorProviderType.WebAuthn] = webAuthnProvider;
|
|
|
|
users.Add(new User
|
|
{
|
|
Id = id,
|
|
TwoFactorProviders = JsonConvert.SerializeObject(providers),
|
|
});
|
|
}
|
|
}
|
|
|
|
foreach (User user in users)
|
|
{
|
|
var command = commandFactory();
|
|
|
|
command.CommandText = "UPDATE [dbo].[User] SET TwoFactorProviders = @twoFactorProviders WHERE Id = @id";
|
|
var idParameter = command.CreateParameter();
|
|
idParameter.ParameterName = "@id";
|
|
idParameter.Value = user.Id;
|
|
|
|
var twoFactorParameter = command.CreateParameter();
|
|
twoFactorParameter.ParameterName = "@twoFactorProviders";
|
|
twoFactorParameter.Value = user.TwoFactorProviders;
|
|
|
|
command.Parameters.Add(idParameter);
|
|
command.Parameters.Add(twoFactorParameter);
|
|
|
|
command.ExecuteNonQuery();
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
private bool HasProperMetaData(TwoFactorProvider provider)
|
|
{
|
|
return (provider?.MetaData?.Count ?? 0) > 0;
|
|
}
|
|
|
|
private List<Tuple<string, TwoFactorProvider.U2fMetaData>> LoadKeys(TwoFactorProvider provider)
|
|
{
|
|
var keys = new List<Tuple<string, TwoFactorProvider.U2fMetaData>>();
|
|
|
|
// Support up to 5 keys
|
|
for (var i = 1; i <= 5; i++)
|
|
{
|
|
var keyName = $"Key{i}";
|
|
if (provider.MetaData.ContainsKey(keyName))
|
|
{
|
|
var key = new TwoFactorProvider.U2fMetaData((dynamic)provider.MetaData[keyName]);
|
|
if (!key?.Compromised ?? false)
|
|
{
|
|
keys.Add(new Tuple<string, TwoFactorProvider.U2fMetaData>(keyName, key));
|
|
}
|
|
}
|
|
}
|
|
|
|
return keys;
|
|
}
|
|
|
|
private class User
|
|
{
|
|
public Guid Id { get; set; }
|
|
public string TwoFactorProviders { get; set; }
|
|
}
|
|
}
|
|
}
|