using System.Diagnostics; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; namespace Bit.Setup; public static class Helpers { public static string SecureRandomString(int length, bool alpha = true, bool upper = true, bool lower = true, bool numeric = true, bool special = false) { return SecureRandomString(length, RandomStringCharacters(alpha, upper, lower, numeric, special)); } // ref https://stackoverflow.com/a/8996788/1090359 with modifications public static string SecureRandomString(int length, string characters) { if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length), "length cannot be less than zero."); } if ((characters?.Length ?? 0) == 0) { throw new ArgumentOutOfRangeException(nameof(characters), "characters invalid."); } const int byteSize = 0x100; if (byteSize < characters.Length) { throw new ArgumentException( string.Format("{0} may contain no more than {1} characters.", nameof(characters), byteSize), nameof(characters)); } var outOfRangeStart = byteSize - (byteSize % characters.Length); using (var rng = RandomNumberGenerator.Create()) { var sb = new StringBuilder(); var buffer = new byte[128]; while (sb.Length < length) { rng.GetBytes(buffer); for (var i = 0; i < buffer.Length && sb.Length < length; ++i) { // Divide the byte into charSet-sized groups. If the random value falls into the last group and the // last group is too small to choose from the entire allowedCharSet, ignore the value in order to // avoid biasing the result. if (outOfRangeStart <= buffer[i]) { continue; } sb.Append(characters[buffer[i] % characters.Length]); } } return sb.ToString(); } } private static string RandomStringCharacters(bool alpha, bool upper, bool lower, bool numeric, bool special) { var characters = string.Empty; if (alpha) { if (upper) { characters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } if (lower) { characters += "abcdefghijklmnopqrstuvwxyz"; } } if (numeric) { characters += "0123456789"; } if (special) { characters += "!@#$%^*&"; } return characters; } public static string GetValueFromEnvFile(string envFile, string key) { if (!File.Exists($"/bitwarden/env/{envFile}.override.env")) { return null; } var lines = File.ReadAllLines($"/bitwarden/env/{envFile}.override.env"); foreach (var line in lines) { if (line.StartsWith($"{key}=")) { return line.Split(new char[] { '=' }, 2)[1].Trim('"').Replace("\\\"", "\""); } } return null; } public static string Exec(string cmd, bool returnStdout = false) { var process = new Process { StartInfo = new ProcessStartInfo { RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden } }; if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var escapedArgs = cmd.Replace("\"", "\\\""); process.StartInfo.FileName = "/bin/bash"; process.StartInfo.Arguments = $"-c \"{escapedArgs}\""; } else { process.StartInfo.FileName = "powershell"; process.StartInfo.Arguments = cmd; } process.Start(); var result = returnStdout ? process.StandardOutput.ReadToEnd() : null; process.WaitForExit(); return result; } public static string ReadInput(string prompt) { Console.ForegroundColor = ConsoleColor.Cyan; Console.Write("(!) "); Console.ResetColor(); Console.Write(prompt); if (prompt.EndsWith("?")) { Console.Write(" (y/N)"); } Console.Write(": "); var input = Console.ReadLine(); Console.WriteLine(); return input; } public static bool ReadQuestion(string prompt) { var input = ReadInput(prompt).ToLowerInvariant().Trim(); return input == "y" || input == "yes"; } public static void ShowBanner(Context context, string title, string message, ConsoleColor? color = null) { if (!context.PrintToScreen()) { return; } if (color != null) { Console.ForegroundColor = color.Value; } Console.WriteLine($"!!!!!!!!!! {title} !!!!!!!!!!"); Console.WriteLine(message); Console.WriteLine(); Console.ResetColor(); } public static HandlebarsDotNet.HandlebarsTemplate ReadTemplate(string templateName) { var assembly = typeof(Helpers).GetTypeInfo().Assembly; var fullTemplateName = $"Bit.Setup.Templates.{templateName}.hbs"; if (!assembly.GetManifestResourceNames().Any(f => f == fullTemplateName)) { return null; } using (var s = assembly.GetManifestResourceStream(fullTemplateName)) using (var sr = new StreamReader(s)) { var templateText = sr.ReadToEnd(); return HandlebarsDotNet.Handlebars.Compile(templateText); } } public static void WriteLine(Context context, string format = null, object arg0 = null, object arg1 = null, object arg2 = null) { if (!context.PrintToScreen()) { return; } if (format != null && arg0 != null && arg1 != null && arg2 != null) { Console.WriteLine(format, arg0, arg1, arg2); } else if (format != null && arg0 != null && arg1 != null) { Console.WriteLine(format, arg0, arg1); } else if (format != null && arg0 != null) { Console.WriteLine(format, arg0); } else if (format != null) { Console.WriteLine(format); } else { Console.WriteLine(); } } public static void WriteError(string errorMessage) { Console.ForegroundColor = ConsoleColor.Red; Console.Write("(!) "); Console.ResetColor(); Console.Write(errorMessage); Console.WriteLine(); } }