Tuesday, July 24, 2012

Adding domain user as local admin immediatly after domain join

Here's a way to add a domain user as a local admin immediatly after joining the domain, without rebooting first:
  1. using System;  
  2. using System.Runtime.InteropServices;  
  3. using System.Security.Principal;  
  4. using System.Text;  
  5.   
  6. class NativeMethods  
  7. {  
  8.     public const int LOGON32_LOGON_INTERACTIVE = 2;  
  9.     public const int LOGON32_LOGON_NETWORK = 3;  
  10.     public const int LOGON32_LOGON_BATCH = 4;  
  11.     public const int LOGON32_LOGON_SERVICE = 5;  
  12.     public const int LOGON32_LOGON_UNLOCK = 7;  
  13.     public const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;  
  14.     public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;  
  15.   
  16.     public enum SID_NAME_USE  
  17.     {  
  18.         SidTypeUser = 1,  
  19.         SidTypeGroup,  
  20.         SidTypeDomain,  
  21.         SidTypeAlias,  
  22.         SidTypeWellKnownGroup,  
  23.         SidTypeDeletedAccount,  
  24.         SidTypeInvalid,  
  25.         SidTypeUnknown,  
  26.         SidTypeComputer,  
  27.     }  
  28.   
  29.     public struct LOCALGROUP_MEMBERS_INFO_0  
  30.     {  
  31.         public IntPtr PSID;  
  32.     }  
  33.   
  34.     [DllImport("kernel32.dll")]  
  35.     public extern static bool CloseHandle(IntPtr hToken);  
  36.   
  37.     [DllImport("advapi32.DLL", SetLastError = true)]  
  38.     public static extern int LogonUser(  
  39.         string lpszUsername,  
  40.         string lpszDomain,  
  41.         string lpszPassword,  
  42.         int dwLogonType,  
  43.         int dwLogonProvider,  
  44.         out IntPtr phToken);  
  45.   
  46.     [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]  
  47.     public static extern bool LookupAccountName(  
  48.         string lpSystemName,  
  49.         string lpAccountName,  
  50.         [MarshalAs(UnmanagedType.LPArray)] byte[] Sid,  
  51.         ref uint cbSid,  
  52.         StringBuilder ReferencedDomainName,  
  53.         ref uint cchReferencedDomainName,  
  54.         out SID_NAME_USE peUse);  
  55.   
  56.     [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]  
  57.     public static extern bool LookupAccountSid(  
  58.         string lpSystemName,  
  59.         [MarshalAs(UnmanagedType.LPArray)] byte[] lpSid,  
  60.         StringBuilder lpName,  
  61.         ref uint cchName,  
  62.         StringBuilder lpReferencedDomainName,  
  63.         ref uint cchReferencedDomainName,  
  64.         out SID_NAME_USE peUse);  
  65.   
  66.     [DllImport("netapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]  
  67.     public static extern int NetLocalGroupAddMembers(  
  68.         string servername,  
  69.         string groupname,  
  70.         uint level,  
  71.         ref LOCALGROUP_MEMBERS_INFO_0 buf,  
  72.         uint totalentries);  
  73. }  
  74.   
  75. public class AddAdminUserHelper  
  76. {  
  77.     public static void AddAdminUser(string domain, string username, string password)  
  78.     {  
  79.         // Get built in administrators account name  
  80.         StringBuilder adminGroupName = new StringBuilder();  
  81.         uint adminGroupNameCapacity = (uint)adminGroupName.Capacity;  
  82.         StringBuilder referencedDomainName = new StringBuilder();  
  83.         uint referencedDomainNameCapacity = (uint)referencedDomainName.Capacity;  
  84.         NativeMethods.SID_NAME_USE eUse;  
  85.         byte[] adminGroupSid = new byte[] { 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2 };  
  86.         if (!NativeMethods.LookupAccountSid(  
  87.             null,  
  88.             adminGroupSid,  
  89.             adminGroupName,  
  90.             ref adminGroupNameCapacity,  
  91.             referencedDomainName,  
  92.             ref referencedDomainNameCapacity,  
  93.             out eUse))  
  94.         {  
  95.             Console.WriteLine("LookupAccountSid failed with error " + Marshal.GetLastWin32Error());  
  96.             return;  
  97.         }  
  98.   
  99.         // Get a security token needed to be able to afterwards query for the user's SID  
  100.         IntPtr token = IntPtr.Zero;  
  101.         if (NativeMethods.LogonUser(  
  102.             username,  
  103.             domain,  
  104.             password,  
  105.             NativeMethods.LOGON32_LOGON_NEW_CREDENTIALS,  
  106.             0,  
  107.             out token) == 0)  
  108.         {  
  109.             Console.WriteLine("LogonUser failed with error " + Marshal.GetLastWin32Error());  
  110.             return;  
  111.         }  
  112.   
  113.         // Get user's SID  
  114.         byte[] userSid = new byte[1024];  
  115.         uint userSidLength = (uint)userSid.Length;  
  116.         referencedDomainName = new StringBuilder();  
  117.         referencedDomainNameCapacity = (uint)referencedDomainName.Capacity;  
  118.         NativeMethods.SID_NAME_USE peUse;  
  119.         using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(token))  
  120.         {  
  121.             if (!NativeMethods.LookupAccountName(  
  122.                 domain,  
  123.                 username,  
  124.                 userSid,  
  125.                 ref userSidLength,  
  126.                 referencedDomainName,  
  127.                 ref referencedDomainNameCapacity,  
  128.                 out peUse))  
  129.             {  
  130.                 Console.WriteLine("LookupAccountName failed with error " + Marshal.GetLastWin32Error());  
  131.                 return;  
  132.             }  
  133.         }  
  134.         NativeMethods.CloseHandle(token);  
  135.   
  136.         // Add user's SID to local admins group  
  137.         IntPtr userSidNative = Marshal.AllocHGlobal(userSid.Length);  
  138.         Marshal.Copy(userSid, 0, userSidNative, (int)userSid.Length);  
  139.         NativeMethods.LOCALGROUP_MEMBERS_INFO_0 info0;  
  140.         info0.PSID = userSidNative;  
  141.         int r = NativeMethods.NetLocalGroupAddMembers(  
  142.             null,  
  143.             adminGroupName.ToString(),  
  144.             0,  
  145.             ref info0,  
  146.             1);  
  147.         Marshal.FreeHGlobal(userSidNative);  
  148.         if (r != 0)  
  149.         {  
  150.             Console.WriteLine("NetLocalGroupAddMembers failed by returning " + r);  
  151.             return;  
  152.         }  
  153.     }  
  154. }  

No comments:

Post a Comment