27c21175d7
Migrate much of BI to Services. Added Wireless Profile Provider plugin feature. Added Certificate Authority Provider plugin feature. Modified Certificate Provider plugin feature. Database migration v17, for Device Profiles. Enrolment Client Updated to support CA Certificates, Wireless Profiles and Hardware Info. New Client Enrolment Protocol to support new features. Plugin Manifest Generator added to main solution. Improved AD search performance.
169 lines
7.4 KiB
C#
169 lines
7.4 KiB
C#
using Disco.Client.Interop;
|
|
using Disco.Models.ClientServices;
|
|
using Microsoft.Win32;
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
|
|
namespace Disco.Client.Extensions
|
|
{
|
|
public static class EnrolExtensions
|
|
{
|
|
|
|
public static void Build(this Enrol enrol)
|
|
{
|
|
enrol.ComputerName = Environment.MachineName;
|
|
enrol.RunningUserDomain = Environment.UserDomainName;
|
|
enrol.RunningUserName = Environment.UserName;
|
|
enrol.RunningInteractively = Environment.UserInteractive;
|
|
|
|
// Hardware Audit
|
|
enrol.Hardware = Hardware.Information;
|
|
enrol.SerialNumber = enrol.Hardware.SerialNumber;
|
|
|
|
// Apply System Information
|
|
enrol.ApplySystemInformation();
|
|
|
|
// Certificates
|
|
enrol.Certificates = Certificates.GetAllCertificates();
|
|
|
|
// Wireless Profiles
|
|
enrol.WirelessProfiles = WirelessNetwork.GetWirelessProfiles();
|
|
}
|
|
|
|
public static void Process(this EnrolResponse enrolResponse)
|
|
{
|
|
if (enrolResponse == null)
|
|
throw new ClientServiceException("Enrolment", "Server denied enrolment (Empty Response)");
|
|
|
|
ErrorReporting.EnrolmentSessionId = enrolResponse.SessionId;
|
|
|
|
if (!string.IsNullOrEmpty(enrolResponse.ErrorMessage))
|
|
throw new ClientServiceException("Enrolment", enrolResponse.ErrorMessage);
|
|
|
|
// Offline Domain Join
|
|
bool requireReboot = enrolResponse.ApplyOfflineDomainJoin();
|
|
|
|
// Device Owner
|
|
enrolResponse.ApplyDeviceAssignedUser();
|
|
|
|
// Certificates
|
|
enrolResponse.ApplyDeviceCertificates();
|
|
|
|
// Wireless Profiles
|
|
enrolResponse.ApplyWirelessProfiles();
|
|
|
|
Presentation.UpdateStatus("Enrolling Device", "Device Enrolment Successfully Completed", false, 0, 1500);
|
|
|
|
Program.RebootRequired = requireReboot;
|
|
Program.AllowUninstall = enrolResponse.AllowBootstrapperUninstall;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processes a Client Service Enrol Response for Offline Domain Join Actions
|
|
/// </summary>
|
|
/// <param name="enrolResponse"></param>
|
|
/// <returns>Boolean indicating whether a reboot is required.</returns>
|
|
private static bool ApplyOfflineDomainJoin(this EnrolResponse enrolResponse)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(enrolResponse.OfflineDomainJoinManifest))
|
|
{
|
|
Presentation.UpdateStatus("Enrolling Device", $"Performing Offline Domain Join:\r\nRenaming Computer: {Environment.MachineName} -> {enrolResponse.ComputerName}", true, -1, 1500);
|
|
|
|
string odjFile = Path.GetTempFileName();
|
|
File.WriteAllBytes(odjFile, Convert.FromBase64String(enrolResponse.OfflineDomainJoinManifest));
|
|
|
|
string odjWindowsPath = Environment.GetEnvironmentVariable("SystemRoot");
|
|
string odjProcessArguments = $"/REQUESTODJ /LOADFILE \"{odjFile}\" /WINDOWSPATH \"{odjWindowsPath}\" /LOCALOS";
|
|
|
|
ProcessStartInfo odjProcessStartInfo = new ProcessStartInfo("DJOIN.EXE", odjProcessArguments)
|
|
{
|
|
CreateNoWindow = true,
|
|
ErrorDialog = false,
|
|
LoadUserProfile = true,
|
|
RedirectStandardOutput = true,
|
|
UseShellExecute = false
|
|
};
|
|
string odjResult;
|
|
using (Process odjProcess = System.Diagnostics.Process.Start(odjProcessStartInfo))
|
|
{
|
|
odjResult = odjProcess.StandardOutput.ReadToEnd();
|
|
odjProcess.WaitForExit(20000); // 20 Seconds
|
|
}
|
|
Presentation.UpdateStatus("Enrolling Device", $"Offline Domain Join Result:\r\n{odjResult}", true, -1, 3000);
|
|
|
|
if (File.Exists(odjFile))
|
|
File.Delete(odjFile);
|
|
|
|
// Flush Logged-On History
|
|
if (!string.IsNullOrEmpty(enrolResponse.DomainName))
|
|
{
|
|
using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true))
|
|
{
|
|
regWinlogon.SetValue("DefaultDomainName", enrolResponse.DomainName, RegistryValueKind.String);
|
|
regWinlogon.SetValue("DefaultUserName", String.Empty, RegistryValueKind.String);
|
|
}
|
|
using (RegistryKey regLogonUI = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI", true))
|
|
{
|
|
regLogonUI.DeleteValue("LastLoggedOnUser", false);
|
|
}
|
|
}
|
|
|
|
return true; // Reboot required
|
|
}
|
|
else
|
|
{
|
|
// No Domain Join
|
|
return false; // Reboot not required
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processes a Client Service Enrol Response for Device Assigned User Actions
|
|
/// </summary>
|
|
/// <param name="enrolResponse"></param>
|
|
private static void ApplyDeviceAssignedUser(this EnrolResponse enrolResponse)
|
|
{
|
|
// Only run task if Assigned User was specified
|
|
if (!string.IsNullOrWhiteSpace(enrolResponse.AssignedUserSID))
|
|
{
|
|
Presentation.UpdateStatus("Enrolling Device", $"Configuring the device owner:\r\n{enrolResponse.AssignedUserDescription} ({enrolResponse.AssignedUserDomain}\\{enrolResponse.AssignedUserUsername})", true, -1, 3000);
|
|
|
|
if (enrolResponse.AssignedUserIsLocalAdmin)
|
|
Interop.LocalAuthentication.AddLocalGroupMembership("Administrators", enrolResponse.AssignedUserSID, enrolResponse.AssignedUserUsername, enrolResponse.AssignedUserDomain);
|
|
|
|
// Make Windows think this user was the last to logon
|
|
using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true))
|
|
{
|
|
regWinlogon.SetValue("DefaultDomainName", enrolResponse.AssignedUserDomain, RegistryValueKind.String);
|
|
regWinlogon.SetValue("DefaultUserName", enrolResponse.AssignedUserUsername, RegistryValueKind.String);
|
|
}
|
|
using (RegistryKey regLogonUI = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI", true))
|
|
{
|
|
regLogonUI.SetValue("LastLoggedOnUser", $@"{enrolResponse.AssignedUserDomain}\{enrolResponse.AssignedUserUsername}", RegistryValueKind.String);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void ApplyDeviceCertificates(this EnrolResponse enrolResponse)
|
|
{
|
|
if (enrolResponse.Certificates != null)
|
|
{
|
|
Presentation.UpdateStatus("Enrolling Device", "Configuring Certificates", true, -1, 1000);
|
|
|
|
enrolResponse.Certificates.Apply();
|
|
}
|
|
}
|
|
|
|
private static void ApplyWirelessProfiles(this EnrolResponse enrolResponse)
|
|
{
|
|
if (enrolResponse.WirelessProfiles != null)
|
|
{
|
|
Presentation.UpdateStatus("Enrolling Device", "Configuring Wireless Profiles", true, -1, 1000);
|
|
|
|
enrolResponse.WirelessProfiles.Apply();
|
|
}
|
|
}
|
|
}
|
|
}
|