Files
domain_utility/Program.cs
2025-03-06 21:27:59 +07:00

583 lines
26 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Newtonsoft.Json;
using Renci.SshNet;
using Spectre.Console;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.DirectoryServices;
using System.IO;
using System.Linq;
using System.Management;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Reflection;
using System.Security.Principal;
using System.Text.RegularExpressions;
using System.Threading;
namespace domain_utility
{
internal class Program
{
static readonly string regularDateTime = @"(\d+[.]\d+[.]\d+[ ]\d+[:]\d+[:]\d+)";
static readonly string[,] stringsToFind = new string[,] {
{ "Учетная запись активна", @"(Yes|No)", "Учетная запись работает: " },
{ "Последний пароль задан", regularDateTime, "Когда был сменен пароль: " },
{ "Действие пароля завершается", regularDateTime, "Когда нужно менять пароль (крайний срок): "},
{ "Членство в глобальных группах", @"([*].+)", "Член групп:\t" }
};
static readonly string[,] computerNameRegex = new string[,] {
{ "^[a-zA-Z]+\\d+$", "R54-630300" }, // THE01
{ "^\\d{6,}[a-zA-Z]+\\d+$", "R54-" }, // 630300THE01
{ "^[rR]\\d{2,}[-]\\d{6,}[a-zA-Z]+\\d+$", "" } // R54-630300THE01
};
static string domain_user = string.Empty;
static string domain_password = string.Empty;
static bool _click_cancel = false;
static bool IsStringContainIp(string ip)
{
return Regex.IsMatch(ip, @"^(\d+[.]\d+[.]\d+[.]\d+)$");
}
static string CheckComputerName(string pcName)
{
for (int i = 0; i < computerNameRegex.GetLength(0); i++)
if (Regex.IsMatch(pcName, computerNameRegex[i, 0]))
return $"{computerNameRegex[i, 1]}{pcName}".ToUpper();
return string.Empty;
}
static string InputData(string message, Action callback, bool withClear = true, bool withChecks = true)
{
if (withClear)
AnsiConsole.Clear();
string data = AnsiConsole.Prompt(
new TextPrompt<string>(message + "\n> ")
);
if (string.IsNullOrWhiteSpace(data))
return InputData(message, callback, withClear, withChecks);
data = data.Trim();
AnsiConsole.WriteLine();
if (withChecks)
if (!IsStringContainIp(data))
{
data = CheckComputerName(data);
if (data == string.Empty)
{
AnsiConsole.WriteLine("Имя компьютера или IP-адрес не распознаны! Попробуйте еще раз.");
BackToMenu(callback);
}
}
return data;
}
static void BackToMenu(Action callback, bool withMessage = true)
{
if (withMessage)
AnsiConsole.WriteLine("\nНажмите Enter чтобы продолжить, ESC чтобы вернуться на главную.");
ConsoleKey key = Console.ReadKey(true).Key;
if (key == ConsoleKey.Enter)
callback.Invoke();
else if (key == ConsoleKey.Escape)
Menu();
else
{
AnsiConsole.WriteLine("Нажмите Enter или ESC!");
BackToMenu(callback, false);
}
}
static void InputDomainCredentials()
{
if (domain_user == string.Empty)
{
string machineNameAndUser = WindowsIdentity.GetCurrent().Name.ToString();
int indexOfUserName = machineNameAndUser.IndexOf('\\') + 1;
domain_user = machineNameAndUser.Substring(indexOfUserName, machineNameAndUser.Length - indexOfUserName).ToLower();
}
if (domain_password != string.Empty)
return;
domain_password = AnsiConsole.Prompt(
new TextPrompt<string>("\nВведите пароль от ТЕКУЩЕЙ учетной записи:\n> ")
.Secret()
);
}
static void ExecuteCommandViaSSH(string remote, string commandToExecute)
{
InputDomainCredentials();
try
{
using (SshClient client = new SshClient(remote, domain_user, domain_password))
{
client.Connect();
SshCommand command = client.RunCommand(commandToExecute);
AnsiConsole.WriteLine(command.Result);
client.Disconnect();
}
}
catch (Exception ex)
{
AnsiConsole.WriteLine("Произошла ошибка: " + ex.Message);
}
}
static void ResetAdminPassword()
{
string machineNameAndUser = WindowsIdentity.GetCurrent().Name.ToString();
string machineName = machineNameAndUser.Substring(0, machineNameAndUser.IndexOf('\\'));
using (DirectoryEntry directoryEntry = new DirectoryEntry(string.Format("WinNT://{0}/{1}", machineName, "Администратор")))
{
//directoryEntry.Properties["LockOutTime"].Value = 0;
directoryEntry.Invoke("SetPassword", "Qwe12345");
directoryEntry.CommitChanges();
directoryEntry.Close();
}
AnsiConsole.WriteLine("Пароль сброшен.");
BackToMenu(Menu);
}
static string PingHost(string host)
{
string returnMessage = string.Empty;
PingOptions pingOptions = new PingOptions() { DontFragment = true }; // TTL = 128
using (Ping ping = new Ping())
{
byte[] buffer = new byte[32];
for (int i = 0; i < 4; i++)
{
try
{
PingReply pingReply = ping.Send(host, 1000, buffer, pingOptions);
if (pingReply == null)
{
returnMessage = "Ошибка подключения по неизвестной причине.";
throw new Exception(message: string.Empty);
}
switch (pingReply.Status)
{
case IPStatus.Success:
{
if (pingReply.RoundtripTime < 1)
returnMessage = string.Format("Ответ от {0}: число байт={1} время<1мс TTL={2}", pingReply.Address, pingReply.Buffer.Length, pingReply.Options.Ttl);
else
returnMessage = string.Format("Ответ от {0}: число байт={1} время={2}мс TTL={3}", pingReply.Address, pingReply.Buffer.Length, pingReply.RoundtripTime, pingReply.Options.Ttl);
break;
}
case IPStatus.TimedOut:
returnMessage = "Время подключения истекло.";
break;
case IPStatus.DestinationHostUnreachable:
returnMessage = "Заданный узел недоступен.";
break;
default:
returnMessage = string.Format("Ошибка пинга: {0}", pingReply.Status.ToString());
break;
}
}
catch (Exception ex)
{
if (ex.Message != string.Empty)
returnMessage = string.Format("Ошибка подключения: {0}", ex.Message);
}
}
}
return returnMessage;
}
static void PingClickCancel(object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
_click_cancel = true;
}
static void StartPing()
{
string remote = InputData("ping компьютера\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):",
StartPing);
AnsiConsole.WriteLine("Нажмите Ctrl + C чтобы остановить\n");
string correctName = CheckComputerName(remote);
if (correctName != string.Empty)
{
try
{
IPAddress ip = Dns.GetHostEntry(correctName).AddressList.First(addr => addr.AddressFamily == AddressFamily.InterNetwork);
remote = ip.ToString();
AnsiConsole.WriteLine("Обмен пакетами с {0}.main.russianpost.ru [{1}] с 32 байтами данных:", correctName, remote);
}
catch (Exception)
{
AnsiConsole.WriteLine("Компьютер не найден.");
BackToMenu(StartPing);
return;
}
}
else
AnsiConsole.WriteLine("Обмен пакетами с {0} по с 32 байтами данных:", remote);
Console.CancelKeyPress += PingClickCancel;
for (int i = 0; i < 4; i++)
{
if (_click_cancel) break;
AnsiConsole.WriteLine(PingHost(remote));
Thread.Sleep(1000);
}
Console.CancelKeyPress -= PingClickCancel;
_click_cancel = false;
BackToMenu(StartPing);
}
static void StartRDPConnection()
{
string remote = InputData("удаленный доступ к компьютеру\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):",
StartRDPConnection);
remote = $"/v:{remote} /f";
Process proc = new Process();
proc.StartInfo = new ProcessStartInfo("mstsc", remote);
proc.Start();
AnsiConsole.WriteLine("Подключение открыто.");
BackToMenu(StartRDPConnection);
}
static void ShowDomainUserInfo()
{
string username = InputData("посмотреть информацию о пользователе\n\nВведите имя пользователя (пр. 'lev.rusanov'): ", ShowDomainUserInfo, withChecks: false);
username = $"user {username} /domain";
ProcessStartInfo procStartInfo = new ProcessStartInfo("net", username)
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
};
List<string> strArr = new List<string> { };
Process proc = new Process();
proc.StartInfo = procStartInfo;
proc.Start();
while (!proc.StandardOutput.EndOfStream)
strArr.Add(proc.StandardOutput.ReadLine());
Match regex;
bool groupsFlag = false;
for (int i = 0; i < strArr.Count; i++)
{
for (int j = 0; j < stringsToFind.GetLength(0); j++)
{
if (strArr[i].Contains(stringsToFind[j, 0]))
{
regex = Regex.Match(strArr[i], stringsToFind[j, 1]);
if (regex.Success)
{
AnsiConsole.WriteLine(stringsToFind[j, 2] + regex.Value);
if (j == 3)
{
groupsFlag = true;
continue;
}
}
}
if (j == 3 && groupsFlag)
{
regex = Regex.Match(strArr[i], stringsToFind[j, 1]);
if (regex.Success)
AnsiConsole.WriteLine("\t\t" + regex.Value);
}
}
}
strArr.Clear();
BackToMenu(ShowDomainUserInfo);
}
static void ShowComputerBootupTime()
{
string remote = InputData("посмотреть дату последней загрузки компьютера\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):",
ShowComputerBootupTime);
ManagementScope scope = new ManagementScope(string.Format(@"\\{0}\root\cimv2", remote));
try
{
scope.Connect();
ObjectQuery query = new ObjectQuery("SELECT LastBootUpTime FROM Win32_OperatingSystem");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
var firstResult = searcher.Get().OfType<ManagementObject>().First()["LastBootUpTime"];
DateTime lastBootUp = ManagementDateTimeConverter.ToDateTime(firstResult.ToString());
AnsiConsole.WriteLine("Дата последней загрузки: " + lastBootUp);
AnsiConsole.WriteLine("Время работы (д:ч:м:с): " + (DateTime.Now.ToUniversalTime() - lastBootUp.ToUniversalTime()).ToString(@"d\:hh\:mm\:ss"));
}
catch (Exception)
{
AnsiConsole.WriteLine("Произошла ошибка. Попробуйте еще раз.");
}
BackToMenu(ShowComputerBootupTime);
}
static void RemoteRebootWindows()
{
string remote = InputData("удаленная перезагрузка компьютера\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):",
RemoteRebootWindows);
remote = $"/m \\\\{remote} /r /f /t 180 /c \"Через 3 минуты будет произведена перезагрузка ПК!\"";
Process proc = new Process();
proc.StartInfo = new ProcessStartInfo("shutdown", remote);
proc.Start();
AnsiConsole.WriteLine("Команда перезагрузки отправлена.");
BackToMenu(RemoteRebootWindows);
}
static void OpenComputerCups()
{
string remote = InputData("открыть CUPS выбранного компьютера (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):",
OpenComputerCups);
Process.Start($"https://{remote}:631/printers");
AnsiConsole.WriteLine($"CUPS {remote} открыт.");
BackToMenu(OpenComputerCups);
}
static void ExecuteCustomCommandViaSSH()
{
string remote = InputData("выполнить команду через SSH (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):",
ExecuteCustomCommandViaSSH);
string commandToExecute = InputData("Введите команду для выполнения:", ExecuteCustomCommandViaSSH, withClear: false, withChecks: false);
ExecuteCommandViaSSH(remote, commandToExecute);
AnsiConsole.WriteLine("Команда выполнена.");
BackToMenu(ExecuteCustomCommandViaSSH);
}
static void FixConky()
{
string remote = InputData("изменить время обновления conky с 0.5 на 300 (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):",
FixConky);
ExecuteCommandViaSSH(remote, "sudo sed -i 's/update_interval = 0.5,/update_interval = 300,/' /etc/conky/conky.conf");
AnsiConsole.WriteLine("Команда исправления Conky отправлена.");
BackToMenu(FixConky);
}
static void RemoteRebootLinux()
{
string remote = InputData("удаленная перезагрузка компьютера (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):",
RemoteRebootLinux);
ExecuteCommandViaSSH(remote, "sudo shutdown -r +3 \"Через 3 минуты будет произведена перезагрузка ПК!\"");
AnsiConsole.WriteLine("Команда перезагрузки отправлена.");
BackToMenu(RemoteRebootLinux);
}
static void ShowLinuxComputerBootupTime()
{
string remote = InputData("посмотреть время работы компьютера (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):",
ShowLinuxComputerBootupTime);
ExecuteCommandViaSSH(remote, "uptime");
BackToMenu(ShowLinuxComputerBootupTime);
}
static void ChangeRemote802Password()
{
string remote = InputData("сменить пароль для 802.1x (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04')\nall - для массового изменения",
ChangeRemote802Password, withChecks: false);
remote = remote.Trim().ToLower();
if (remote != "all")
{
if (!IsStringContainIp(remote))
{
remote = CheckComputerName(remote);
if (remote == string.Empty)
ChangeRemote802Password();
}
}
string new802password = AnsiConsole.Prompt(
new TextPrompt<string>("\nВведите новый пароль от УЗ:\n> ")
.Secret()
);
if (remote == "all")
{
InputDomainCredentials();
string path = Path.Combine(Environment.CurrentDirectory, "settings.json");
if (!File.Exists(path))
{
AnsiConsole.WriteLine("Файл с настройками не найден!");
BackToMenu(ChangeRemote802Password);
}
JsonFile data = JsonConvert.DeserializeObject<JsonFile>(File.ReadAllText(path));
string unitKey;
int sleep_time = data.sleep_time;
foreach (KeyValuePair<string, List<int>> unit in data.arm_list)
{
unitKey = unit.Key;
foreach (int position in unit.Value)
{
remote = CheckComputerName($"{unitKey}{(position < 10 ? $"0{position}" : position.ToString())}");
if (remote == string.Empty)
{
AnsiConsole.WriteLine($"{unitKey}{(position < 10 ? $"0{position}" : position.ToString())}: имя ПК не распознано.");
continue;
}
try
{
using (SshClient client = new SshClient(remote, domain_user, domain_password))
{
client.Connect();
SshCommand command = client.RunCommand($"sudo sed -i 's/password=.\\+/password={new802password}/' /etc/NetworkManager/system-connections/Проводное\\ подключение\\ 1.nmconnection");
//AnsiConsole.WriteLine(command.Result);
command = client.RunCommand("sudo nmcli connection reload");
//AnsiConsole.WriteLine(command.Result);
command.Dispose();
client.Disconnect();
}
AnsiConsole.WriteLine(remote + ": ");
}
catch (Exception ex)
{
AnsiConsole.WriteLine(remote + ": " + ex.Message);
}
}
}
}
else
{
ExecuteCommandViaSSH(remote, $"sudo sed -i 's/^password=.\\+/password={new802password}/' /etc/NetworkManager/system-connections/Проводное\\ подключение\\ 1.nmconnection && sudo nmcli connection reload");
AnsiConsole.WriteLine("Команда отправлена.");
}
BackToMenu(ChangeRemote802Password);
}
static void DisableKdeWallet()
{
string remote = InputData("отключить KDE кошелек (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):",
DisableKdeWallet);
ExecuteCommandViaSSH(remote, "sudo sed -i 's/^Exec=/#Exec=/' /usr/share/dbus-1/services/org.kde.kwalletd5.service");
AnsiConsole.WriteLine("Команда отключения кошелька отправлена.");
BackToMenu(DisableKdeWallet);
}
private class MenuItem
{
public string Name { get; }
public Action Executor { get; }
public MenuItem(string _name, Action _executor)
{
Name = _name;
Executor = _executor;
}
}
static readonly MenuItem[] availableOptions = new[]
{
new MenuItem("ping компьютера", () => StartPing()),
new MenuItem("удаленный доступ к компьютеру", () => StartRDPConnection()),
new MenuItem("посмотреть информацию о пользователе", () => ShowDomainUserInfo()),
new MenuItem("посмотреть дату последней загрузки компьютера", () => ShowComputerBootupTime()),
new MenuItem("удаленная перезагрузка компьютера", () => RemoteRebootWindows()),
new MenuItem("открыть CUPS выбранного компьютера (Linux)", () => OpenComputerCups()),
new MenuItem("выполнить команду через SSH (Linux)", () => ExecuteCustomCommandViaSSH()),
new MenuItem("изменить время обновления conky с 0.5 на 300 (Linux)", () => FixConky()),
new MenuItem("удаленная перезагрузка компьютера (Linux)", () => RemoteRebootLinux()),
new MenuItem("посмотреть время работы компьютера (Linux)", () => ShowLinuxComputerBootupTime()),
new MenuItem("сменить пароль для 802.1x (Linux)", () => ChangeRemote802Password()),
new MenuItem("отключить KDE кошелек (Linux)", () => DisableKdeWallet()),
};
static void Menu()
{
AnsiConsole.Clear();
MenuItem choice = AnsiConsole.Prompt(
new SelectionPrompt<MenuItem>()
.Title("Выберите действие:")
.PageSize(15)
//.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
.UseConverter(i => i.Name)
.AddChoices(availableOptions)
);
choice.Executor();
}
class JsonFile
{
public int sleep_time = 0;
public int restart_time = 0;
public string message = "";
public Dictionary<string, List<int>> arm_list = null;
}
static void StartRestartComputers()
{
string path = Path.Combine(Environment.CurrentDirectory, "settings.json");
if (!File.Exists(path))
{
AnsiConsole.WriteLine("Файл с настройками не найден!");
Console.ReadKey();
return;
}
JsonFile data = JsonConvert.DeserializeObject<JsonFile>(File.ReadAllText(path));
string remote, unitKey;
int sleep_time = data.sleep_time;
foreach (KeyValuePair<string, List<int>> unit in data.arm_list)
{
unitKey = unit.Key;
foreach (int position in unit.Value)
{
remote = CheckComputerName($"{unitKey}{(position < 10 ? $"0{position}" : position.ToString())}");
if (remote == string.Empty)
{
AnsiConsole.WriteLine($"{unitKey}{(position < 10 ? $"0{position}" : position.ToString())}: имя ПК не распознано.");
continue;
}
//AnsiConsole.WriteLine($"{remote}: shutdown -r +{data.restart_time} \"{data.message}\"");
ExecuteCommandViaSSH(remote, $"sudo shutdown -r +{data.restart_time} \"{data.message}\"");
Thread.Sleep(sleep_time);
}
}
Console.ReadKey();
}
static void Main(string[] args)
{
Console.Title = Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyTitleAttribute>().Title;
if (args.Length > 0 && args[0] == "reboot")
{
StartRestartComputers();
return;
}
Menu();
}
}
}