10a38af08b
Device Profile setting which specifies whether assigned users are set as Local Administrators. Default is true (which maintains compatibility).
191 lines
9.6 KiB
C#
191 lines
9.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Disco.Models.ClientServices;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.IO;
|
|
using System.Diagnostics;
|
|
using Microsoft.Win32;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace Disco.Client.Extensions
|
|
{
|
|
public static class EnrolExtensions
|
|
{
|
|
|
|
public static void Build(this Enrol enrol)
|
|
{
|
|
enrol.DeviceUUID = Interop.SystemAudit.DeviceUUID;
|
|
enrol.DeviceSerialNumber = Interop.SystemAudit.DeviceSerialNumber;
|
|
|
|
enrol.DeviceComputerName = Interop.LocalAuthentication.ComputerName;
|
|
|
|
enrol.DeviceManufacturer = Interop.SystemAudit.DeviceManufacturer;
|
|
enrol.DeviceModel = Interop.SystemAudit.DeviceModel;
|
|
enrol.DeviceModelType = Interop.SystemAudit.DeviceType;
|
|
|
|
enrol.DeviceIsPartOfDomain = Interop.SystemAudit.DeviceIsPartOfDomain;
|
|
|
|
// LAN
|
|
enrol.DeviceLanMacAddress = Interop.Network.PrimaryLanMacAddress;
|
|
|
|
// WAN
|
|
enrol.DeviceWlanMacAddress = Interop.Network.PrimaryWlanMacAddress;
|
|
|
|
// Certificates
|
|
enrol.DeviceCertificates = Interop.Certificates.GetCertificateSubjects(StoreName.My, StoreLocation.LocalMachine);
|
|
}
|
|
|
|
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();
|
|
|
|
// Certificates
|
|
enrolResponse.ApplyDeviceCertificates();
|
|
|
|
// Device Owner
|
|
enrolResponse.ApplyDeviceAssignedUser();
|
|
|
|
|
|
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.OfflineDomainJoin))
|
|
{
|
|
Presentation.UpdateStatus("Enrolling Device", string.Format("Performing Offline Domain Join:{0}Renaming Computer: {1} -> {2}", Environment.NewLine, Interop.LocalAuthentication.ComputerName, enrolResponse.DeviceComputerName), true, -1, 1500);
|
|
|
|
string odjFile = Path.GetTempFileName();
|
|
File.WriteAllBytes(odjFile, Convert.FromBase64String(enrolResponse.OfflineDomainJoin));
|
|
|
|
string odjWindowsPath = Environment.GetEnvironmentVariable("SystemRoot");
|
|
string odjProcessArguments = string.Format("/REQUESTODJ /LOADFILE \"{0}\" /WINDOWSPATH \"{1}\" /LOCALOS", odjFile, odjWindowsPath);
|
|
|
|
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", string.Format("Offline Domain Join Result:{0}{1}", Environment.NewLine, odjResult), true, -1, 3000);
|
|
|
|
if (File.Exists(odjFile))
|
|
File.Delete(odjFile);
|
|
|
|
// Flush Logged-On History
|
|
if (!string.IsNullOrEmpty(enrolResponse.DeviceDomainName))
|
|
{
|
|
using (RegistryKey regWinlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true))
|
|
{
|
|
regWinlogon.SetValue("DefaultDomainName", enrolResponse.DeviceDomainName, 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.DeviceAssignedUserSID))
|
|
{
|
|
Presentation.UpdateStatus("Enrolling Device", string.Format(@"Configuring the device owner:{0}{1} ({2}\{3})", Environment.NewLine, enrolResponse.DeviceAssignedUserName, enrolResponse.DeviceAssignedUserDomain, enrolResponse.DeviceAssignedUserUsername), true, -1, 3000);
|
|
|
|
if (enrolResponse.DeviceAssignedUserIsLocalAdmin)
|
|
Interop.LocalAuthentication.AddLocalGroupMembership("Administrators", enrolResponse.DeviceAssignedUserSID, enrolResponse.DeviceAssignedUserUsername, enrolResponse.DeviceAssignedUserDomain);
|
|
|
|
// 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.DeviceAssignedUserDomain, RegistryValueKind.String);
|
|
regWinlogon.SetValue("DefaultUserName", enrolResponse.DeviceAssignedUserUsername, RegistryValueKind.String);
|
|
}
|
|
using (RegistryKey regLogonUI = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI", true))
|
|
{
|
|
regLogonUI.SetValue("LastLoggedOnUser", string.Format(@"{0}\{1}", enrolResponse.DeviceAssignedUserDomain, enrolResponse.DeviceAssignedUserUsername), RegistryValueKind.String);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processes a Client Service Enrol Response for Device Certificate Actions
|
|
/// </summary>
|
|
/// <param name="enrolResponse"></param>
|
|
private static void ApplyDeviceCertificates(this EnrolResponse enrolResponse)
|
|
{
|
|
// Only run if a Certificate was supplied
|
|
if (!string.IsNullOrEmpty(enrolResponse.DeviceCertificate))
|
|
{
|
|
Presentation.UpdateStatus("Enrolling Device", "Configuring Wireless Certificates", true, -1, 1000);
|
|
|
|
var certPersonalBytes = Convert.FromBase64String(enrolResponse.DeviceCertificate);
|
|
var certPersonal = new X509Certificate2(certPersonalBytes, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
|
|
if (certPersonal == null)
|
|
throw new ClientServiceException("Enrolment > Device Certificate", "Unable to Import Device Certificate Provided, possibly check password.");
|
|
|
|
// Certificate Removal
|
|
if (enrolResponse.DeviceCertificateRemoveExisting != null && enrolResponse.DeviceCertificateRemoveExisting.Count > 0)
|
|
{
|
|
List<Regex> regExMatchesSubject = new List<Regex>();
|
|
foreach (var subjectRegEx in enrolResponse.DeviceCertificateRemoveExisting)
|
|
regExMatchesSubject.Add(new Regex(subjectRegEx, RegexOptions.IgnoreCase));
|
|
|
|
// Remove from 'My' Store
|
|
Interop.Certificates.RemoveCertificates(StoreName.My, StoreLocation.LocalMachine, regExMatchesSubject, certPersonal);
|
|
// Remove from 'Root' Store
|
|
Interop.Certificates.RemoveCertificates(StoreName.Root, StoreLocation.LocalMachine, regExMatchesSubject, certPersonal);
|
|
// Remove from 'CertificateAuthority' Store
|
|
Interop.Certificates.RemoveCertificates(StoreName.CertificateAuthority, StoreLocation.LocalMachine, regExMatchesSubject, certPersonal);
|
|
}
|
|
|
|
// Add Certificate
|
|
Presentation.UpdateStatus("Enrolling Device", string.Format("Configuring Wireless Certificates{0}Installing Certificate: {1}", Environment.NewLine, Interop.Certificates.GetCertificateFriendlyName(certPersonal)), true, -1);
|
|
Interop.Certificates.AddCertificate(StoreName.My, StoreLocation.LocalMachine, certPersonal);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|