getting effective folder permissions for user - c#

Is there api in .net for getting effective folder permissions for user?
I know how get permissions by using `DirectorySecurity.GetAccessRules().
But in this case I should manually analyze all permissions for user: permissions for groups, that include the user, inherited permissions and user permission for folder.
Is there a function in the Windows API that can return these permissions via platform invoke?

class Program
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
public struct LUID
{
public uint LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct AUTHZ_ACCESS_REQUEST
{
public int DesiredAccess;
public byte[] PrincipalSelfSid;
public OBJECT_TYPE_LIST[] ObjectTypeList;
public int ObjectTypeListLength;
public IntPtr OptionalArguments;
};
[StructLayout(LayoutKind.Sequential)]
public struct OBJECT_TYPE_LIST
{
OBJECT_TYPE_LEVEL Level;
int Sbz;
IntPtr ObjectType;
};
[StructLayout(LayoutKind.Sequential)]
public struct AUTHZ_ACCESS_REPLY
{
public int ResultListLength;
public IntPtr GrantedAccessMask;
public IntPtr SaclEvaluationResults;
public IntPtr Error;
};
public enum OBJECT_TYPE_LEVEL : int
{
ACCESS_OBJECT_GUID = 0,
ACCESS_PROPERTY_SET_GUID = 1,
ACCESS_PROPERTY_GUID = 2,
ACCESS_MAX_LEVEL = 4
};
enum AUTHZ_RM_FLAG : uint
{
AUTHZ_RM_FLAG_NO_AUDIT = 1,
AUTHZ_RM_FLAG_INITIALIZE_UNDER_IMPERSONATION = 2,
AUTHZ_RM_FLAG_NO_CENTRAL_ACCESS_POLICIES = 4,
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
static extern uint GetNamedSecurityInfo(
string pObjectName,
SE_OBJECT_TYPE ObjectType,
SECURITY_INFORMATION SecurityInfo,
out IntPtr pSidOwner,
out IntPtr pSidGroup,
out IntPtr pDacl,
out IntPtr pSacl,
out IntPtr pSecurityDescriptor);
[DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzInitializeContextFromSid", CharSet = CharSet.Unicode)]
static extern public bool AuthzInitializeContextFromSid(
int Flags,
IntPtr UserSid ,
IntPtr AuthzResourceManager,
IntPtr pExpirationTime,
LUID Identitifier,
IntPtr DynamicGroupArgs,
out IntPtr pAuthzClientContext
);
[DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzInitializeResourceManager", CharSet = CharSet.Unicode)]
static extern public bool AuthzInitializeResourceManager(
int flags,
IntPtr pfnAccessCheck,
IntPtr pfnComputeDynamicGroups,
IntPtr pfnFreeDynamicGroups,
string name,
out IntPtr rm
);
[DllImport("authz.dll", EntryPoint = "AuthzAccessCheck", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
private static extern bool AuthzAccessCheck(int flags,
IntPtr hAuthzClientContext,
ref AUTHZ_ACCESS_REQUEST pRequest,
IntPtr AuditEvent,
IntPtr pSecurityDescriptor,
byte[] OptionalSecurityDescriptorArray,
int OptionalSecurityDescriptorCount,
ref AUTHZ_ACCESS_REPLY pReply,
out IntPtr phAccessCheckResults);
enum ACCESS_MASK : uint
{
FILE_TRAVERSE = 0x20,FILE_LIST_DIRECTORY = 0x1,FILE_READ_DATA = 0x1,FILE_READ_ATTRIBUTES = 0x80,FILE_READ_EA = 0x8,FILE_ADD_FILE = 0x2,FILE_WRITE_DATA = 0x2,FILE_ADD_SUBDIRECTORY = 0x4,FILE_APPEND_DATA = 0x4,FILE_WRITE_ATTRIBUTES = 0x100,FILE_WRITE_EA = 0x10,FILE_DELETE_CHILD = 0x40,DELETE = 0x10000,READ_CONTROL = 0x20000,WRITE_DAC = 0x40000,
WRITE_OWNER = 0x80000,
}
[Flags]
enum SECURITY_INFORMATION : uint
{
OWNER_SECURITY_INFORMATION = 0x00000001,
GROUP_SECURITY_INFORMATION = 0x00000002,
DACL_SECURITY_INFORMATION = 0x00000004,
SACL_SECURITY_INFORMATION = 0x00000008,
UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000,
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000,
PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000,
PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
}
enum SE_OBJECT_TYPE
{
SE_UNKNOWN_OBJECT_TYPE = 0,
SE_FILE_OBJECT,
}
static void Main(string[] args)
{
//String UserName = "NT Authority\\Authenticated Users";
do {
Console.WriteLine("UserName:");
String UserName = Console.ReadLine();
SecurityIdentifier sid = null;
NTAccount ac = new NTAccount(UserName);
try
{
sid = (SecurityIdentifier)ac.Translate(typeof(SecurityIdentifier));
}
catch (Exception e)
{
Console.WriteLine("Not a group or user");
continue;
}
Console.WriteLine("Path:");
String Path = Console.ReadLine();
if (!(File.Exists(Path) || Directory.Exists(Path)))
{
Console.WriteLine("Invalid Path");
continue;
}
IntPtr pSidOwner, pSidGroup, pDacl, pSacl, pSecurityDescriptor;
ACCESS_MASK mask = new ACCESS_MASK();
uint ret = GetNamedSecurityInfo(Path,
SE_OBJECT_TYPE.SE_FILE_OBJECT,
SECURITY_INFORMATION.DACL_SECURITY_INFORMATION | SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION | SECURITY_INFORMATION.GROUP_SECURITY_INFORMATION,
out pSidOwner,
out pSidGroup,
out pDacl,
out pSacl,
out pSecurityDescriptor);
IntPtr hManager = IntPtr.Zero;
bool f = AuthzInitializeResourceManager(1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, null, out hManager);
byte[] bytes = new byte[sid.BinaryLength];
sid.GetBinaryForm(bytes, 0);
String _psUserSid = "";
foreach (byte si in bytes)
{
_psUserSid += si;
}
LUID unusedSid = new LUID();
IntPtr UserSid = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, UserSid, bytes.Length);
IntPtr pClientContext = IntPtr.Zero;
if (f)
{
f = AuthzInitializeContextFromSid(0, UserSid, hManager, IntPtr.Zero, unusedSid, IntPtr.Zero, out pClientContext);
AUTHZ_ACCESS_REQUEST request = new AUTHZ_ACCESS_REQUEST();
request.DesiredAccess = 0x02000000;
request.PrincipalSelfSid = null;
request.ObjectTypeList = null;
request.ObjectTypeListLength = 0;
request.OptionalArguments = IntPtr.Zero;
AUTHZ_ACCESS_REPLY reply = new AUTHZ_ACCESS_REPLY();
reply.GrantedAccessMask = IntPtr.Zero;
reply.ResultListLength = 0;
reply.SaclEvaluationResults = IntPtr.Zero;
IntPtr AccessReply = IntPtr.Zero;
reply.Error = Marshal.AllocHGlobal(1020);
reply.GrantedAccessMask = Marshal.AllocHGlobal(sizeof(uint));
reply.ResultListLength = 1;
int i = 0;
Dictionary<String, String> rightsmap = new Dictionary<String, String>();
List<string> effectivePermissionList = new List<string>();
string[] rights = new string[14] { "Full Control", "Traverse Folder / execute file", "List folder / read data", "Read attributes", "Read extended attributes", "Create files / write files", "Create folders / append data", "Write attributes", "Write extended attributes", "Delete subfolders and files", "Delete", "Read permission", "Change permission", "Take ownership" };
rightsmap.Add("FILE_TRAVERSE", "Traverse Folder / execute file");
rightsmap.Add("FILE_LIST_DIRECTORY", "List folder / read data");
rightsmap.Add("FILE_READ_DATA", "List folder / read data");
rightsmap.Add("FILE_READ_ATTRIBUTES", "Read attributes");
rightsmap.Add("FILE_READ_EA", "Read extended attributes");
rightsmap.Add("FILE_ADD_FILE", "Create files / write files");
rightsmap.Add("FILE_WRITE_DATA", "Create files / write files");
rightsmap.Add("FILE_ADD_SUBDIRECTORY", "Create folders / append data");
rightsmap.Add("FILE_APPEND_DATA", "Create folders / append data");
rightsmap.Add("FILE_WRITE_ATTRIBUTES", "Write attributes");
rightsmap.Add("FILE_WRITE_EA", "Write extended attributes");
rightsmap.Add("FILE_DELETE_CHILD", "Delete subfolders and files");
rightsmap.Add("DELETE", "Delete");
rightsmap.Add("READ_CONTROL", "Read permission");
rightsmap.Add("WRITE_DAC", "Change permission");
rightsmap.Add("WRITE_OWNER", "Take ownership");
f = AuthzAccessCheck(0, pClientContext, ref request, IntPtr.Zero, pSecurityDescriptor, null, 0, ref reply, out AccessReply);
if (f)
{
int granted_access = Marshal.ReadInt32(reply.GrantedAccessMask);
mask = (ACCESS_MASK)granted_access;
foreach (ACCESS_MASK item in Enum.GetValues(typeof(ACCESS_MASK)))
{
if ((mask & item) == item)
{
effectivePermissionList.Add(rightsmap[item.ToString()]);
i++;
}
}
}
Marshal.FreeHGlobal(reply.GrantedAccessMask);
if (i == 16)
{
effectivePermissionList.Insert(0, "Full Control");
}
Console.WriteLine(".......................");
foreach (string r in rights)
{
if (effectivePermissionList.Contains(r))
{
Console.WriteLine(r);
}
}
}
Console.WriteLine("_________________________________________________\n");
} while (true);
// Console.ReadLine();
}
}

Related

Changing user name of a Windows service in C# [duplicate]

This question already has an answer here:
When calling Windows API functions from C#, which source for signatures to trust: .NET Framework source code or PInvoke?
(1 answer)
Closed 6 months ago.
I'm trying to change user name and password of a Windows service in C# via WinAPI calls. I have created the service myself using WinAPI's CreateService(), based off of the code in this Stack Overflow answer.
If I use the same credentials in a call to ChangeServiceConfigA(), I'm told that user name and password are incorrect. I can change everything else with ChangeServiceConfigA(), even the password, but once I try to set user name and password, I get said error.
My code looks like this:
private const uint SERVICE_NO_CHANGE = 0xffffffff;
[Flags]
private enum ServiceAccessRights
{
QueryConfig = 0x1,
ChangeConfig = 0x2,
QueryStatus = 0x4,
EnumerateDependants = 0x8,
Start = 0x10,
Stop = 0x20,
PauseContinue = 0x40,
Interrogate = 0x80,
UserDefinedControl = 0x100,
Delete = 0x00010000,
StandardRightsRequired = 0xF0000,
AllAccess = StandardRightsRequired | QueryConfig | ChangeConfig |
QueryStatus | EnumerateDependants | Start | Stop | PauseContinue |
Interrogate | UserDefinedControl
}
private enum ServiceBootFlag : UInt32
{
Start = 0x00000000,
SystemStart = 0x00000001,
AutoStart = 0x00000002,
DemandStart = 0x00000003,
Disabled = 0x00000004,
ServiceNoChange = SERVICE_NO_CHANGE
}
private enum ServiceError : UInt32
{
Ignore = 0x00000000,
Normal = 0x00000001,
Severe = 0x00000002,
Critical = 0x00000003,
ServiceNoChange = SERVICE_NO_CHANGE
}
private enum ServiceType : UInt32
{
ServiceFileSystemDriver = 0x00000002,
ServiceKernelDrvier = 0x00000001,
ServiceWin32OwnProcess = 0x00000010,
ServiveWin32ShareProcess = 0x00000020,
ServiceNoChange = SERVICE_NO_CHANGE
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, ServiceAccessRights dwDesiredAccess, int dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string lpBinaryPathName, string? lpLoadOrderGroup, IntPtr lpdwTagId, string? lpDependencies, string? lpServiceStartName, string? lpPassword);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool ChangeServiceConfigA(IntPtr hService, ServiceType dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string? lpBinaryPathName, string? lpLoadOrderGroup, IntPtr lpdwTagId, string? lpDependencies, string? lpServiceStartName, string? lpPassword, string? lpDisplayName);
public static bool ChangeService(string serviceName, string? userName, string? password)
{
IntPtr scm = OpenSCManager(ScmAccessRights.Connect);
try
{
IntPtr service = OpenService(scm, serviceName, ServiceAccessRights.ChangeConfig);
if (service == IntPtr.Zero)
return false;
if (!ChangeServiceConfigA(service,
ServiceType.ServiceNoChange,
ServiceBootFlag.ServiceNoChange,
ServiceError.ServiceNoChange,
null, null, IntPtr.Zero, null,
userName, password, null))
throw new ApplicationException(":( sadface");
CloseServiceHandle(service);
return true;
}
finally
{
CloseServiceHandle(scm);
}
}
Argh, I found the answer by accident when doing the other WinAPI thing I meant to do:
QueryServiceConfigA() uses ANSI strings (while QueryServiceConfigW() uses Unicode), but most importanly, QueryServiceConfig() is an alias that automatically chooses the right one.
Declared like this, it works like a charm:
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool ChangeServiceConfig(IntPtr hService, ServiceType dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl, string? lpBinaryPathName, string? lpLoadOrderGroup, IntPtr lpdwTagId, string? lpDependencies, string? lpServiceStartName, string? lpPassword, string? lpDisplayName);

How to get effective permission for the file or folder in C# or C++? Any APIs for that?

My code is working but I need the simplified code and it's not working for the Authenticated Users group. Any other ways to calculate effective permissions?
Is there an API in .NET for getting effective folder permissions for a specific user? I know how get permissions by using DirectorySecurity.GetAccessRules(). But in this case I should manually analyze all permissions for user, permissions for groups, that include the user, inherited permissions and user permission for folder.
Is there a function in the Windows API that can return these permissions via platform invoke?
namespace DemoProject1
{
class Program
{
static Dictionary<String, String> rightsmap = new Dictionary<String, String>();
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint GetEffectiveRightsFromAcl(IntPtr pDacl, ref TRUSTEE pTrustee, ref ACCESS_MASK pAccessRights);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
struct TRUSTEE
{
IntPtr pMultipleTrustee; // must be null
public int MultipleTrusteeOperation;
public TRUSTEE_FORM TrusteeForm;
public TRUSTEE_TYPE TrusteeType;
[MarshalAs(UnmanagedType.LPStr)]
public string ptstrName;
}
enum TRUSTEE_FORM
{
TRUSTEE_IS_SID,
TRUSTEE_IS_NAME,
TRUSTEE_BAD_FORM,
TRUSTEE_IS_OBJECTS_AND_SID,
TRUSTEE_IS_OBJECTS_AND_NAME
}
enum TRUSTEE_TYPE
{
TRUSTEE_IS_UNKNOWN,
TRUSTEE_IS_USER,
TRUSTEE_IS_GROUP,
TRUSTEE_IS_DOMAIN,
TRUSTEE_IS_ALIAS,
TRUSTEE_IS_WELL_KNOWN_GROUP,
TRUSTEE_IS_DELETED,
TRUSTEE_IS_INVALID,
TRUSTEE_IS_COMPUTER
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
static extern uint GetNamedSecurityInfo(
string pObjectName,
SE_OBJECT_TYPE ObjectType,
SECURITY_INFORMATION SecurityInfo,
out IntPtr pSidOwner,
out IntPtr pSidGroup,
out IntPtr pDacl,
out IntPtr pSacl,
out IntPtr pSecurityDescriptor);
enum ACCESS_MASK : uint
{
FILE_TRAVERSE = 0x20,
FILE_LIST_DIRECTORY = 0x1,
FILE_READ_DATA = 0x1,
FILE_READ_ATTRIBUTES = 0x80,
FILE_READ_EA = 0x8,
FILE_ADD_FILE = 0x2,
FILE_WRITE_DATA = 0x2,
FILE_ADD_SUBDIRECTORY = 0x4,
FILE_APPEND_DATA = 0x4,
FILE_WRITE_ATTRIBUTES = 0x100,
FILE_WRITE_EA=0x10,
FILE_DELETE_CHILD = 0x40,
DELETE = 0x10000,
READ_CONTROL = 0x20000,
WRITE_DAC = 0x40000,
WRITE_OWNER = 0x80000,
////////FILE_EXECUTE =0x20,
}
[Flags]
enum SECURITY_INFORMATION : uint
{
OWNER_SECURITY_INFORMATION = 0x00000001,
GROUP_SECURITY_INFORMATION = 0x00000002,
DACL_SECURITY_INFORMATION = 0x00000004,
SACL_SECURITY_INFORMATION = 0x00000008,
UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000,
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000,
PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000,
PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
}
enum SE_OBJECT_TYPE
{
SE_UNKNOWN_OBJECT_TYPE = 0,
SE_FILE_OBJECT,
SE_SERVICE,
SE_PRINTER,
SE_REGISTRY_KEY,
SE_LMSHARE,
SE_KERNEL_OBJECT,
SE_WINDOW_OBJECT,
SE_DS_OBJECT,
SE_DS_OBJECT_ALL,
SE_PROVIDER_DEFINED_OBJECT,
SE_WMIGUID_OBJECT,
SE_REGISTRY_WOW64_32KEY
}
static void Main(string[] args)
{
//String UserName = "NT Authority\\Authenticated Users";
String UserName = "TEST-INC-34\\Test1";
String Path = "E:\\f1";
IntPtr pSidOwner, pSidGroup, pDacl, pSacl, pSecurityDescriptor;
ACCESS_MASK mask = new ACCESS_MASK();
uint ret = GetNamedSecurityInfo(Path,
SE_OBJECT_TYPE.SE_FILE_OBJECT,
SECURITY_INFORMATION.DACL_SECURITY_INFORMATION,
out pSidOwner, out pSidGroup, out pDacl, out pSacl, out pSecurityDescriptor);
TRUSTEE t = new TRUSTEE();
t.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_NAME;
t.TrusteeType = TRUSTEE_TYPE.TRUSTEE_IS_USER;
t.ptstrName = UserName;
//Console.WriteLine(t.ptstrName+" "+ t.TrusteeType);
ret = GetEffectiveRightsFromAcl(pDacl, ref t, ref mask);
int i = 0;
List<string> effectivePermissionList = new List<string>();
string[] rights = new string[14] {"Full Control" ,"Traverse Folder / execute file", "List folder / read data", "Read attributes", "Read extended attributes", "Create files / write files", "Create folders / append data", "Write attributes", "Write extended attributes", "Delete subfolders and files", "Delete", "Read permission", "Change permission", "Take ownership" };
rightsmap.Add("FILE_TRAVERSE", "Traverse Folder / execute file");
rightsmap.Add("FILE_LIST_DIRECTORY", "List folder / read data");
rightsmap.Add("FILE_READ_DATA", "List folder / read data");
rightsmap.Add("FILE_READ_ATTRIBUTES", "Read attributes");
rightsmap.Add("FILE_READ_EA", "Read extended attributes");
rightsmap.Add("FILE_ADD_FILE", "Create files / write files");
rightsmap.Add("FILE_WRITE_DATA", "Create files / write files");
rightsmap.Add("FILE_ADD_SUBDIRECTORY", "Create folders / append data");
rightsmap.Add("FILE_APPEND_DATA", "Create folders / append data");
rightsmap.Add("FILE_WRITE_ATTRIBUTES", "Write attributes");
rightsmap.Add("FILE_WRITE_EA", "Write extended attributes");
rightsmap.Add("FILE_DELETE_CHILD", "Delete subfolders and files");
rightsmap.Add("DELETE", "Delete");
rightsmap.Add("READ_CONTROL", "Read permission");
rightsmap.Add("WRITE_DAC", "Change permission");
rightsmap.Add("WRITE_OWNER", "Take ownership");
foreach (ACCESS_MASK item in Enum.GetValues(typeof(ACCESS_MASK)))
{
if ((mask & item) == item)
{
effectivePermissionList.Add(rightsmap[item.ToString()]);
i++;
}
}
//Console.WriteLine(i);
if (i == 16)
{
effectivePermissionList.Insert(0,"Full Control");
}
string user = System.IO.File.GetAccessControl(Path).GetOwner(typeof(System.Security.Principal.NTAccount)).ToString();
if (user.Equals(UserName))
{
if (!effectivePermissionList.Contains("Read permission"))
{
effectivePermissionList.Add("Read permission");
}
if (!effectivePermissionList.Contains("Change permission"))
{
effectivePermissionList.Add("Change permission");
}
}
foreach (string r in rights)
{
if (effectivePermissionList.Contains(r))
{
Console.WriteLine(r);
}
}
Console.ReadLine();
}
}
}
This is the exact answer for my question:
namespace EffectiveRightsUsingAuthzAPI
{
class Program
{
[DllImport("advapi32.dll", SetLastError = true)]
static extern uint GetEffectiveRightsFromAcl(IntPtr pDacl, ref TRUSTEE pTrustee, ref ACCESS_MASK pAccessRights);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
struct TRUSTEE
{
IntPtr pMultipleTrustee; // must be null
public int MultipleTrusteeOperation;
public TRUSTEE_FORM TrusteeForm;
public TRUSTEE_TYPE TrusteeType;
[MarshalAs(UnmanagedType.LPStr)]
public string ptstrName;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
public struct LUID
{
public uint LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct AUTHZ_ACCESS_REQUEST
{
public int DesiredAccess;
public byte[] PrincipalSelfSid;
public OBJECT_TYPE_LIST[] ObjectTypeList;
public int ObjectTypeListLength;
public IntPtr OptionalArguments;
};
[StructLayout(LayoutKind.Sequential)]
public struct OBJECT_TYPE_LIST
{
OBJECT_TYPE_LEVEL Level;
int Sbz;
IntPtr ObjectType;
};
[StructLayout(LayoutKind.Sequential)]
public struct AUTHZ_ACCESS_REPLY
{
public int ResultListLength;
public IntPtr GrantedAccessMask;
public IntPtr SaclEvaluationResults;
public IntPtr Error;
};
public enum OBJECT_TYPE_LEVEL : int
{
ACCESS_OBJECT_GUID = 0,
ACCESS_PROPERTY_SET_GUID = 1,
ACCESS_PROPERTY_GUID = 2,
ACCESS_MAX_LEVEL = 4
};
enum TRUSTEE_FORM
{
TRUSTEE_IS_SID,
TRUSTEE_IS_NAME,
TRUSTEE_BAD_FORM,
TRUSTEE_IS_OBJECTS_AND_SID,
TRUSTEE_IS_OBJECTS_AND_NAME
}
enum AUTHZ_RM_FLAG : uint
{
AUTHZ_RM_FLAG_NO_AUDIT = 1,
AUTHZ_RM_FLAG_INITIALIZE_UNDER_IMPERSONATION = 2,
AUTHZ_RM_FLAG_NO_CENTRAL_ACCESS_POLICIES = 4,
}
enum TRUSTEE_TYPE
{
TRUSTEE_IS_UNKNOWN,
TRUSTEE_IS_USER,
TRUSTEE_IS_GROUP,
TRUSTEE_IS_DOMAIN,
TRUSTEE_IS_ALIAS,
TRUSTEE_IS_WELL_KNOWN_GROUP,
TRUSTEE_IS_DELETED,
TRUSTEE_IS_INVALID,
TRUSTEE_IS_COMPUTER
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
static extern uint GetNamedSecurityInfo(
string pObjectName,
SE_OBJECT_TYPE ObjectType,
SECURITY_INFORMATION SecurityInfo,
out IntPtr pSidOwner,
out IntPtr pSidGroup,
out IntPtr pDacl,
out IntPtr pSacl,
out IntPtr pSecurityDescriptor);
[DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzInitializeContextFromSid", CharSet = CharSet.Unicode)]
static extern public bool AuthzInitializeContextFromSid(
int Flags,
IntPtr UserSid ,
IntPtr AuthzResourceManager,
IntPtr pExpirationTime,
LUID Identitifier,
IntPtr DynamicGroupArgs,
out IntPtr pAuthzClientContext
);
[DllImport("authz.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, EntryPoint = "AuthzInitializeResourceManager", CharSet = CharSet.Unicode)]
static extern public bool AuthzInitializeResourceManager(
int flags,
IntPtr pfnAccessCheck,
IntPtr pfnComputeDynamicGroups,
IntPtr pfnFreeDynamicGroups,
string name,
out IntPtr rm
);
[DllImport("authz.dll", EntryPoint = "AuthzAccessCheck", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
private static extern bool AuthzAccessCheck(int flags,
IntPtr hAuthzClientContext,
ref AUTHZ_ACCESS_REQUEST pRequest,
IntPtr AuditEvent,
IntPtr pSecurityDescriptor,
byte[] OptionalSecurityDescriptorArray,
int OptionalSecurityDescriptorCount,
ref AUTHZ_ACCESS_REPLY pReply,
out IntPtr phAccessCheckResults);
enum ACCESS_MASK : uint
{
FILE_TRAVERSE = 0x20,
FILE_LIST_DIRECTORY = 0x1,
FILE_READ_DATA = 0x1,
FILE_READ_ATTRIBUTES = 0x80,
FILE_READ_EA = 0x8,
FILE_ADD_FILE = 0x2,
FILE_WRITE_DATA = 0x2,
FILE_ADD_SUBDIRECTORY = 0x4,
FILE_APPEND_DATA = 0x4,
FILE_WRITE_ATTRIBUTES = 0x100,
FILE_WRITE_EA = 0x10,
FILE_DELETE_CHILD = 0x40,
DELETE = 0x10000,
READ_CONTROL = 0x20000,
WRITE_DAC = 0x40000,
WRITE_OWNER = 0x80000,
////////FILE_EXECUTE =0x20,
}
[Flags]
enum SECURITY_INFORMATION : uint
{
OWNER_SECURITY_INFORMATION = 0x00000001,
GROUP_SECURITY_INFORMATION = 0x00000002,
DACL_SECURITY_INFORMATION = 0x00000004,
SACL_SECURITY_INFORMATION = 0x00000008,
UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000,
UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000,
PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000,
PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
}
enum SE_OBJECT_TYPE
{
SE_UNKNOWN_OBJECT_TYPE = 0,
SE_FILE_OBJECT,
SE_SERVICE,
SE_PRINTER,
SE_REGISTRY_KEY,
SE_LMSHARE,
SE_KERNEL_OBJECT,
SE_WINDOW_OBJECT,
SE_DS_OBJECT,
SE_DS_OBJECT_ALL,
SE_PROVIDER_DEFINED_OBJECT,
SE_WMIGUID_OBJECT,
SE_REGISTRY_WOW64_32KEY
}
static void Main(string[] args)
{
//String UserName = "NT Authority\\Authenticated Users";
do {
Console.WriteLine("UserName:");
String UserName = Console.ReadLine();
Console.WriteLine("Path:");
String Path = Console.ReadLine();
IntPtr pSidOwner, pSidGroup, pDacl, pSacl, pSecurityDescriptor;
ACCESS_MASK mask = new ACCESS_MASK();
uint ret = GetNamedSecurityInfo(Path,
SE_OBJECT_TYPE.SE_FILE_OBJECT,
SECURITY_INFORMATION.DACL_SECURITY_INFORMATION | SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION | SECURITY_INFORMATION.GROUP_SECURITY_INFORMATION,
out pSidOwner, out pSidGroup, out pDacl, out pSacl, out pSecurityDescriptor);
IntPtr hManager = IntPtr.Zero;
bool f = AuthzInitializeResourceManager(1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, null, out hManager);
NTAccount ac = new NTAccount(UserName);
SecurityIdentifier sid = (SecurityIdentifier)ac.Translate(typeof(SecurityIdentifier));
byte[] bytes = new byte[sid.BinaryLength];
sid.GetBinaryForm(bytes, 0);
String _psUserSid = "";
foreach (byte si in bytes)
{
_psUserSid += si;
}
LUID unusedSid = new LUID();
IntPtr UserSid = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes, 0, UserSid, bytes.Length);
IntPtr pClientContext = IntPtr.Zero;
if (f)
{
f = AuthzInitializeContextFromSid(0, UserSid, hManager, IntPtr.Zero, unusedSid, IntPtr.Zero, out pClientContext);
AUTHZ_ACCESS_REQUEST request = new AUTHZ_ACCESS_REQUEST();
request.DesiredAccess = 0x02000000;
request.PrincipalSelfSid = null;
request.ObjectTypeList = null;
request.ObjectTypeListLength = 0;
request.OptionalArguments = IntPtr.Zero;
AUTHZ_ACCESS_REPLY reply = new AUTHZ_ACCESS_REPLY();
reply.GrantedAccessMask = IntPtr.Zero;
reply.ResultListLength = 0;
reply.SaclEvaluationResults = IntPtr.Zero;
IntPtr AccessReply = IntPtr.Zero;
reply.Error = Marshal.AllocHGlobal(1020);
reply.GrantedAccessMask = Marshal.AllocHGlobal(sizeof(uint));
reply.ResultListLength = 1;
int i = 0;
Dictionary<String, String> rightsmap = new Dictionary<String, String>();
List<string> effectivePermissionList = new List<string>();
string[] rights = new string[14] { "Full Control", "Traverse Folder / execute file", "List folder / read data", "Read attributes", "Read extended attributes", "Create files / write files", "Create folders / append data", "Write attributes", "Write extended attributes", "Delete subfolders and files", "Delete", "Read permission", "Change permission", "Take ownership" };
rightsmap.Add("FILE_TRAVERSE", "Traverse Folder / execute file");
rightsmap.Add("FILE_LIST_DIRECTORY", "List folder / read data");
rightsmap.Add("FILE_READ_DATA", "List folder / read data");
rightsmap.Add("FILE_READ_ATTRIBUTES", "Read attributes");
rightsmap.Add("FILE_READ_EA", "Read extended attributes");
rightsmap.Add("FILE_ADD_FILE", "Create files / write files");
rightsmap.Add("FILE_WRITE_DATA", "Create files / write files");
rightsmap.Add("FILE_ADD_SUBDIRECTORY", "Create folders / append data");
rightsmap.Add("FILE_APPEND_DATA", "Create folders / append data");
rightsmap.Add("FILE_WRITE_ATTRIBUTES", "Write attributes");
rightsmap.Add("FILE_WRITE_EA", "Write extended attributes");
rightsmap.Add("FILE_DELETE_CHILD", "Delete subfolders and files");
rightsmap.Add("DELETE", "Delete");
rightsmap.Add("READ_CONTROL", "Read permission");
rightsmap.Add("WRITE_DAC", "Change permission");
rightsmap.Add("WRITE_OWNER", "Take ownership");
f = AuthzAccessCheck(0, pClientContext, ref request, IntPtr.Zero, pSecurityDescriptor, null, 0, ref reply, out AccessReply);
if (f)
{
int granted_access = Marshal.ReadInt32(reply.GrantedAccessMask);
mask = (ACCESS_MASK)granted_access;
foreach (ACCESS_MASK item in Enum.GetValues(typeof(ACCESS_MASK)))
{
if ((mask & item) == item)
{
effectivePermissionList.Add(rightsmap[item.ToString()]);
i++;
}
}
}
Marshal.FreeHGlobal(reply.GrantedAccessMask);
if (i == 16)
{
effectivePermissionList.Insert(0, "Full Control");
}
Console.WriteLine(".......................");
foreach (string r in rights)
{
if (effectivePermissionList.Contains(r))
{
Console.WriteLine(r);
}
}
}
Console.WriteLine("_________________________________________________\n");
} while (true);
Console.ReadLine();
}
}
}

.NET Start Process with higher rights

I am trying to execute a program with admin rights through a C# application, which gets invoked with user rights only.
Code
ProcessStartInfo psi;
try
{
psi = new ProcessStartInfo(#"WINZIP32.EXE");
psi.UseShellExecute = false;
SecureString pw = new SecureString();
pw.AppendChar('p');
pw.AppendChar('a');
pw.AppendChar('s');
pw.AppendChar('s');
pw.AppendChar('w');
pw.AppendChar('o');
pw.AppendChar('r');
pw.AppendChar('d');
psi.Password = pw;
psi.UserName = "administrator";
Process.Start(psi);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
It does start winzip, but only with user rights. Is there something I am doing wrong or is it even possible to start a process with higher rights?
thank you!
Edit:
Here is the reason behind the question, maybe it helps to understand what i actually need.
I used winzip for example to get a general idea what's incorrect with my code. The actual problem is, our company uses 2 versions of a program. But before you start any of the versions you need to import a dll file with regsvr32 (with admin rights). Now I would like to write a program that let the user select the version, import the dll and starts the correct application.
You need to set ProcessStartInfo.UseShellExecute to true and ProcessStartInfo.Verb to runas:
Process process = null;
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = "WINZIP32.EXE";
processStartInfo.Verb = "runas";
processStartInfo.WindowStyle = ProcessWindowStyle.Normal;
processStartInfo.UseShellExecute = true;
process = Process.Start(processStartInfo);
This will cause the application to run as the administrator. UAC will however prompt the user to confirm. If this is not desirable then you'll need to add a manifest to permanently elevate the host process privilages.
You can run a process as another user(even an administrator) using the CreateProcessAsUser function (Win32 API).
CreateProcessAsUser accepts a user token as the first parameter, that is an impersonation token.
You have to use DLLImport to load the function from the Windows DLL.
Take a look at this example implementation that i have used in one of my projects :
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
internal struct SECURITY_ATTRIBUTES
{
public uint nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
internal enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
internal enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
public class ProcessAsUser
{
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx", SetLastError = true)]
private static extern bool DuplicateTokenEx(
IntPtr hExistingToken,
uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
Int32 ImpersonationLevel,
Int32 dwTokenType,
ref IntPtr phNewToken);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(
IntPtr ProcessHandle,
UInt32 DesiredAccess,
ref IntPtr TokenHandle);
[DllImport("userenv.dll", SetLastError = true)]
private static extern bool CreateEnvironmentBlock(
ref IntPtr lpEnvironment,
IntPtr hToken,
bool bInherit);
[DllImport("userenv.dll", SetLastError = true)]
private static extern bool DestroyEnvironmentBlock(
IntPtr lpEnvironment);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(
IntPtr hObject);
private const short SW_SHOW = 5;
private const uint TOKEN_QUERY = 0x0008;
private const uint TOKEN_DUPLICATE = 0x0002;
private const uint TOKEN_ASSIGN_PRIMARY = 0x0001;
private const int GENERIC_ALL_ACCESS = 0x10000000;
private const int STARTF_USESHOWWINDOW = 0x00000001;
private const int STARTF_FORCEONFEEDBACK = 0x00000040;
private const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400;
private const int STARTF_RUNFULLSCREEN = 0x00000020;
private static bool LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock)
{
bool result = false;
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
saThread.nLength = (uint)Marshal.SizeOf(saThread);
STARTUPINFO si = new STARTUPINFO();
si.cb = (uint)Marshal.SizeOf(si);
//if this member is NULL, the new process inherits the desktop
//and window station of its parent process. If this member is
//an empty string, the process does not inherit the desktop and
//window station of its parent process; instead, the system
//determines if a new desktop and window station need to be created.
//If the impersonated user already has a desktop, the system uses the
//existing desktop.
si.lpDesktop = #"WinSta0\Default"; //Modify as needed
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
si.wShowWindow = SW_SHOW;
//Set other si properties as required.
result = CreateProcessAsUser(
token,
null,
cmdLine,
ref saProcess,
ref saThread,
false,
CREATE_UNICODE_ENVIRONMENT,
envBlock,
null,
ref si,
out pi);
if (result == false)
{
int error = Marshal.GetLastWin32Error();
string message = String.Format("CreateProcessAsUser Error: {0}", error);
Debug.WriteLine(message);
}
return result;
}
/// <summary>
/// LaunchProcess As User Overloaded for Window Mode
/// </summary>
/// <param name="cmdLine"></param>
/// <param name="token"></param>
/// <param name="envBlock"></param>
/// <param name="WindowMode"></param>
/// <returns></returns>
private static bool LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock,uint WindowMode)
{
bool result = false;
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
SECURITY_ATTRIBUTES saProcess = new SECURITY_ATTRIBUTES();
SECURITY_ATTRIBUTES saThread = new SECURITY_ATTRIBUTES();
saProcess.nLength = (uint)Marshal.SizeOf(saProcess);
saThread.nLength = (uint)Marshal.SizeOf(saThread);
STARTUPINFO si = new STARTUPINFO();
si.cb = (uint)Marshal.SizeOf(si);
//if this member is NULL, the new process inherits the desktop
//and window station of its parent process. If this member is
//an empty string, the process does not inherit the desktop and
//window station of its parent process; instead, the system
//determines if a new desktop and window station need to be created.
//If the impersonated user already has a desktop, the system uses the
//existing desktop.
si.lpDesktop = #"WinSta0\Default"; //Default Vista/7 Desktop Session
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK;
//Check the Startup Mode of the Process
if (WindowMode == 1)
si.wShowWindow = SW_SHOW;
else if (WindowMode == 2)
{ //Do Nothing
}
else if (WindowMode == 3)
si.wShowWindow = 0; //Hide Window
else if (WindowMode == 4)
si.wShowWindow = 3; //Maximize Window
else if (WindowMode == 5)
si.wShowWindow = 6; //Minimize Window
else
si.wShowWindow = SW_SHOW;
//Set other si properties as required.
result = CreateProcessAsUser(
token,
null,
cmdLine,
ref saProcess,
ref saThread,
false,
CREATE_UNICODE_ENVIRONMENT,
envBlock,
null,
ref si,
out pi);
if (result == false)
{
int error = Marshal.GetLastWin32Error();
string message = String.Format("CreateProcessAsUser Error: {0}", error);
Debug.WriteLine(message);
}
return result;
}
private static IntPtr GetPrimaryToken(int processId)
{
IntPtr token = IntPtr.Zero;
IntPtr primaryToken = IntPtr.Zero;
bool retVal = false;
Process p = null;
try
{
p = Process.GetProcessById(processId);
}
catch (ArgumentException)
{
string details = String.Format("ProcessID {0} Not Available", processId);
Debug.WriteLine(details);
throw;
}
//Gets impersonation token
retVal = OpenProcessToken(p.Handle, TOKEN_DUPLICATE, ref token);
if (retVal == true)
{
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.nLength = (uint)Marshal.SizeOf(sa);
//Convert the impersonation token into Primary token
retVal = DuplicateTokenEx(
token,
TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY,
ref sa,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(int)TOKEN_TYPE.TokenPrimary,
ref primaryToken);
//Close the Token that was previously opened.
CloseHandle(token);
if (retVal == false)
{
string message = String.Format("DuplicateTokenEx Error: {0}", Marshal.GetLastWin32Error());
Debug.WriteLine(message);
}
}
else
{
string message = String.Format("OpenProcessToken Error: {0}", Marshal.GetLastWin32Error());
Debug.WriteLine(message);
}
//We'll Close this token after it is used.
return primaryToken;
}
private static IntPtr GetEnvironmentBlock(IntPtr token)
{
IntPtr envBlock = IntPtr.Zero;
bool retVal = CreateEnvironmentBlock(ref envBlock, token, false);
if (retVal == false)
{
//Environment Block, things like common paths to My Documents etc.
//Will not be created if "false"
//It should not adversley affect CreateProcessAsUser.
string message = String.Format("CreateEnvironmentBlock Error: {0}", Marshal.GetLastWin32Error());
Debug.WriteLine(message);
}
return envBlock;
}
public static bool Launch(string appCmdLine /*,int processId*/)
{
bool ret = false;
//Either specify the processID explicitly
//Or try to get it from a process owned by the user.
//In this case assuming there is only one explorer.exe
Process[] ps = Process.GetProcessesByName("explorer");
int processId = -1;//=processId
if (ps.Length > 0)
{
processId = ps[0].Id;
}
if (processId > 1)
{
IntPtr token = GetPrimaryToken(processId);
if (token != IntPtr.Zero)
{
IntPtr envBlock = GetEnvironmentBlock(token);
ret = LaunchProcessAsUser(appCmdLine, token, envBlock);
if (envBlock != IntPtr.Zero)
DestroyEnvironmentBlock(envBlock);
CloseHandle(token);
}
}
return ret;
}
Ref:
How to start a Process as administrator mode in C#
Elevating process privilege programmatically?
var psi = new ProcessStartInfo
{
FileName = "notepad",
UserName = "admin",
Domain = "",
Password = pass,
UseShellExecute = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
Verb = "runas";
};
Process.Start(psi);
//
var pass = new SecureString();
pass.AppendChar('s');
pass.AppendChar('e');
pass.AppendChar('c');
pass.AppendChar('r');
pass.AppendChar('e');
pass.AppendChar('t');
Process.Start("notepad", "admin", pass, "");
//Vista or higher check
if (System.Environment.OSVersion.Version.Major >= 6)
{
p.StartInfo.Verb = "runas";
}
Ref: How to run/start a new process with admin rights? ASP.net Forum
Another way is to impersonate the admin user. You can do this by
calling the Logon function and impersonate the user whose token you
will get then. For impersonating a user in code, look at:
WindowsImpersonationContext
Class
. Use the check
http://www.csharpfriends.com/Forums/ShowPost.aspx?PostID=31611 for
GetCurrentUser to see whether impersonation succeeded.
Code Snippet:
System.Diagnostics.Process process = null;
System.Diagnostics.ProcessStartInfo processStartInfo;
processStartInfo = new System.Diagnostics.ProcessStartInfo();
processStartInfo.FileName = "regedit.exe";
if (System.Environment.OSVersion.Version.Major >= 6) // Windows Vista or higher
{
processStartInfo.Verb = "runas";
}
else
{
// No need to prompt to run as admin
}
processStartInfo.Arguments = "";
processStartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
processStartInfo.UseShellExecute = true;
try
{
process = System.Diagnostics.Process.Start(processStartInfo);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
if (process != null)
{
process.Dispose();
}
}
//Try this with administrator login, i have not tested yet..
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
// Test harness.
// If you incorporate this code into a DLL, be sure to demand FullTrust.
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
private void button1_Click(object sender, EventArgs e)
{
SafeTokenHandle safeTokenHandle;
const int LOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_INTERACTIVE = 2;
bool returnValue = LogonUser("administrator", "", "password",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
out safeTokenHandle);
Console.WriteLine("LogonUser called.");
if (false == returnValue)
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("LogonUser failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}
using (safeTokenHandle)
{
Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
Console.WriteLine("Value of Windows NT token: " + safeTokenHandle);
// Check the identity.
Console.WriteLine("Before impersonation: "
+ WindowsIdentity.GetCurrent().Name);
// Use the token handle returned by LogonUser.
WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
{
System.Diagnostics.Process process = null;
System.Diagnostics.ProcessStartInfo processStartInfo;
processStartInfo = new System.Diagnostics.ProcessStartInfo();
processStartInfo.FileName = "regedit.exe";
//if (System.Environment.OSVersion.Version.Major >= 6) // Windows Vista or higher
//{
// processStartInfo.Verb = "runas";
//}
//else
//{
// // No need to prompt to run as admin
//}
processStartInfo.Arguments = "";
processStartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
processStartInfo.UseShellExecute = true;
try
{
process = System.Diagnostics.Process.Start(processStartInfo);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
if (process != null)
{
process.Dispose();
}
}
// Check the identity.
Console.WriteLine("After impersonation: "
+ WindowsIdentity.GetCurrent().Name);
}
// Releasing the context object stops the impersonation
// Check the identity.
Console.WriteLine("After closing the context: " + WindowsIdentity.GetCurrent().Name);
}
}

Impersonate admin account to edit registry key not working (C#)

I am using the following code to edit a registry key in the local machine hive ('SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\%SID%'). Everything seems to be fine until I actually try to open the registry key (with write permissions); a SecurityException is thrown with the message 'Requested registry access is not allowed.' I've checked and rechecked the permissions for the registry key and the user I'm impersonating and it all checks out. The code runs fine when logged into the impersonated user's account, but when logged in as a restricted user, it fails. It's as if the impersonation works all except for giving the thread administrative privileges. Any ideas about how to fix this would be greatly appreciated!
string KEY_STR = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\" + WindowsIdentity.GetCurrent().User.Value;
WindowsImpersonationContext adminContext = null;
IntPtr tokenHandle = new IntPtr(0);
try
{
LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle);
if (tokenHandle.Equals(new IntPtr(0))) LogonUser(userName, computerName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle);
WindowsIdentity adminIdentity = new WindowsIdentity(tokenHandle);
adminContext = adminIdentity.Impersonate();
RegistryKey key = Registry.LocalMachine.OpenSubKey(KEY_STR, true);
key.SetValue("State", 0x60001);
Console.Out.WriteLine("User profile changed to Mandatory.");
}
catch (Exception ex)
{
Console.Out.WriteLine("\nUnable to set profile to Mandatory:\n\t" + ex.Message);
}
finally
{
adminContext.Undo();
if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle);
}
I know this thread is pretty old, and maybe you solved this already, but I did it like this with no issues on a Win7 box:
string userName = "domain\\user"; // there's really just one slash,
//but you have to escape it if hard-coding..
//if brought in by a text box, it would be just domain\user
string password = "whatever";
string KEY_STR = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\" + WindowsIdentity.GetCurrent().User.Value;
WindowsImpersonationContext adminContext = Impersonation.getWic(userName, password);
if (adminContext != null)
{
try
{
RegistryKey key = Registry.LocalMachine.OpenSubKey(KEY_STR, true);
//NOTE: If this was on a remote machine, that line would just be:
// RegistryKey key = RegistryKey.OpenRemoteSubKey(RegistryHive.LocalMachine, computerName).OpenSubKey(KEY_STR, true);
key.SetValue("State", 0x60001);
Console.Out.WriteLine("User profile changed to Mandatory.");
}
catch (Exception ex)
{
Console.Out.WriteLine("\nUnable to set profile to Mandatory:\n\t" + ex.Message);
Impersonation.endImpersonation();
adminContext.Undo();
}
finally
{
Impersonation.endImpersonation();
// The above line does what you had, here --
//if (tokenHandle != IntPtr.Zero) CloseHandle(tokenHandle);
adminContext.Undo();
}
}
This is my separate Impersonation class. It has 2 main entry points, getWic() and doImpersonation() -- getWic() will take a username that looks like domain\user or machinename\user and split them up into their component parts before handing it off to doImpersonation(), while doImpersonation() accepts the parts already split, if you have it like that and don't need the code in getWic(). Both return a WindowsImpersonationContext.
using System;
using System.Data;
using System.Configuration;
using System.Security.Permissions;
using System.Security.Principal;
using System.Runtime.InteropServices;
[assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode = true)]
[assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "FullTrust")]
public class Impersonation
{
[DllImport("advapi32.dll", EntryPoint = "LogonUser")]
public static extern bool LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
// Declare the Logon Types as constants
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_LOGON_BATCH = 4;
const int LOGON32_LOGON_SERVICE = 5;
const int LOGON32_LOGON_UNLOCK = 7;
const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8; // Win2K or higher
const int LOGON32_LOGON_NEW_CREDENTIALS = 9; // Win2K or higher
// Declare the Logon Providers as constants
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_PROVIDER_WINNT50 = 3;
const int LOGON32_PROVIDER_WINNT40 = 2;
const int LOGON32_PROVIDER_WINNT35 = 1;
// Declare the Impersonation Levels as constants
const int SecurityAnonymous = 0;
const int SecurityIdentification = 1;
const int SecurityImpersonation = 2;
const int SecurityDelegation = 3;
private static WindowsIdentity newId;
private static IntPtr tokenHandle = new IntPtr(0);
private static IntPtr dupeTokenHandle = new IntPtr(0);
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public static WindowsImpersonationContext doImpersonation(string svcUserName, string domainName, string password)
{
// Initialize tokens
tokenHandle = IntPtr.Zero;
dupeTokenHandle = IntPtr.Zero;
// Call LogonUser to obtain a handle to an access token
bool returnValue = LogonUser(svcUserName, domainName, password,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_WINNT50, ref tokenHandle);
if (returnValue == false)
{
int ret = Marshal.GetLastWin32Error();
//Check for errors
if (ret != NO_ERROR)
throw new Exception("LogonUser failed with error code : " + GetError(ret));
}
bool retVal = DuplicateToken(tokenHandle, SecurityImpersonation, ref dupeTokenHandle);
if (retVal == false)
{
CloseHandle(tokenHandle);
throw new Exception("Exception thrown in trying to duplicate token.");
}
else
{
// Begin Impersonation
bool bRetVal = DuplicateToken(tokenHandle,
(int)SecurityImpersonation, ref dupeTokenHandle);
newId = new WindowsIdentity(dupeTokenHandle);
WindowsImpersonationContext impersonatedUser = newId.Impersonate();
return impersonatedUser;
}
}
public static void endImpersonation()
{
if (dupeTokenHandle != IntPtr.Zero)
CloseHandle(dupeTokenHandle);
if (tokenHandle != IntPtr.Zero)
CloseHandle(tokenHandle);
}
public static WindowsImpersonationContext getWic(string userNameStringFromTextbox, string password)
{
try
{
// Establish impersonation
string svcUser = userNameStringFromTextbox;
string[] arrUser = new string[2];
arrUser = svcUser.Split('\\');
string domain = arrUser[0];
string svcUserName = arrUser[1];
// Get Password: Convert from Base-64 String to decrypted string
//string keyLength = ConfigurationManager.AppSettings["keyLength"].ToString();
//string keyLocation = ConfigurationManager.AppSettings["keyLocation"].ToString();
//password = RSAEncrypt.DecryptData(password, keyLength, keyLocation);
WindowsImpersonationContext wic = doImpersonation(svcUserName, domain, password);
return wic;
}
catch (Exception ex)
{
ErrorLog.ErrorRoutine(new Exception("getWic() Error: " + ex.ToString()), ErrorMessage.NOTIFY_APP_ERROR);
return null;
}
}
#region Errors
const int NO_ERROR = 0;
const int ERROR_ACCESS_DENIED = 5;
const int ERROR_ALREADY_ASSIGNED = 85;
const int ERROR_BAD_DEVICE = 1200;
const int ERROR_BAD_NET_NAME = 67;
const int ERROR_BAD_PROVIDER = 1204;
const int ERROR_CANCELLED = 1223;
const int ERROR_EXTENDED_ERROR = 1208;
const int ERROR_INVALID_ADDRESS = 487;
const int ERROR_INVALID_PARAMETER = 87;
const int ERROR_INVALID_PASSWORD = 1216;
const int ERROR_MORE_DATA = 234;
const int ERROR_NO_MORE_ITEMS = 259;
const int ERROR_NO_NET_OR_BAD_PATH = 1203;
const int ERROR_NO_NETWORK = 1222;
const int ERROR_SESSION_CREDENTIAL_CONFLICT = 1219;
const int ERROR_BAD_PROFILE = 1206;
const int ERROR_CANNOT_OPEN_PROFILE = 1205;
const int ERROR_DEVICE_IN_USE = 2404;
const int ERROR_NOT_CONNECTED = 2250;
const int ERROR_OPEN_FILES = 2401;
private struct ErrorClass
{
public int num;
public string message;
public ErrorClass(int num, string message)
{
this.num = num;
this.message = message;
}
}
private static ErrorClass[] ERROR_LIST = new ErrorClass[] {
new ErrorClass(ERROR_ACCESS_DENIED, "Error: Access Denied"),
new ErrorClass(ERROR_ALREADY_ASSIGNED, "Error: Already Assigned"),
new ErrorClass(ERROR_BAD_DEVICE, "Error: Bad Device"),
new ErrorClass(ERROR_BAD_NET_NAME, "Error: Bad Net Name"),
new ErrorClass(ERROR_BAD_PROVIDER, "Error: Bad Provider"),
new ErrorClass(ERROR_CANCELLED, "Error: Cancelled"),
new ErrorClass(ERROR_EXTENDED_ERROR, "Error: Extended Error"),
new ErrorClass(ERROR_INVALID_ADDRESS, "Error: Invalid Address"),
new ErrorClass(ERROR_INVALID_PARAMETER, "Error: Invalid Parameter"),
new ErrorClass(ERROR_INVALID_PASSWORD, "Error: Invalid Password"),
new ErrorClass(ERROR_MORE_DATA, "Error: More Data"),
new ErrorClass(ERROR_NO_MORE_ITEMS, "Error: No More Items"),
new ErrorClass(ERROR_NO_NET_OR_BAD_PATH, "Error: No Net Or Bad Path"),
new ErrorClass(ERROR_NO_NETWORK, "Error: No Network"),
new ErrorClass(ERROR_SESSION_CREDENTIAL_CONFLICT, "Error: Credential Conflict"),
new ErrorClass(ERROR_BAD_PROFILE, "Error: Bad Profile"),
new ErrorClass(ERROR_CANNOT_OPEN_PROFILE, "Error: Cannot Open Profile"),
new ErrorClass(ERROR_DEVICE_IN_USE, "Error: Device In Use"),
new ErrorClass(ERROR_NOT_CONNECTED, "Error: Not Connected"),
new ErrorClass(ERROR_OPEN_FILES, "Error: Open Files"),
};
private static string GetError(int errNum)
{
foreach (ErrorClass er in ERROR_LIST)
{
if (er.num == errNum) return er.message;
}
return "Error: Unknown, " + errNum;
}
#endregion
}
Just taking a guess here, but do you happen to be on a Vista or Win7 box with UAC turned on? I'm willing to be you have to have user confirmation to elevate permissions to do this.
The token I had was insufficient to get write access to the registry. I'm going to use a windows service running as system to accomplish this instead.

change windows service password

I am having problems getting the code to change the password of a service of windows provided.
Is there an easy way to do this.
i got this link but it seems to be incomplete link text
here they have not declared SC_MANAGER_ALL_ACCESS, m_pServiceHandle
any suggestions?? thanks
Use WMI in managed code, per this site
using System.Management;
string objPath = string.Format("Win32_Service.Name='{0}'", serviceName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
object[] wmiParams = new object[11];
wmiParams[6] = username;
wmiParams[7] = password;
service.InvokeMethod("Change", wmiParams);
}
This works perfect...
private const int SC_MANAGER_ALL_ACCESS = 0x000F003F;
string serviceName;
private const uint SERVICE_NO_CHANGE = 0xffffffff; //this value is found in winsvc.h
private const uint SERVICE_QUERY_CONFIG = 0x00000001;
private const uint SERVICE_CHANGE_CONFIG = 0x00000002;
private const uint SERVICE_QUERY_STATUS = 0x00000004;
private const uint SERVICE_ENUMERATE_DEPENDENTS = 0x00000008;
private const uint SERVICE_START = 0x00000010;
private const uint SERVICE_STOP = 0x00000020;
private const uint SERVICE_PAUSE_CONTINUE = 0x00000040;
private const uint SERVICE_INTERROGATE = 0x00000080;
private const uint SERVICE_USER_DEFINED_CONTROL = 0x00000100;
private const uint STANDARD_RIGHTS_REQUIRED = 0x000F0000;
private const uint SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
SERVICE_CHANGE_CONFIG |
SERVICE_QUERY_STATUS |
SERVICE_ENUMERATE_DEPENDENTS |
SERVICE_START |
SERVICE_STOP |
SERVICE_PAUSE_CONTINUE |
SERVICE_INTERROGATE |
SERVICE_USER_DEFINED_CONTROL);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean ChangeServiceConfig(IntPtr hService, UInt32 nServiceType, UInt32 nStartType, UInt32 nErrorControl, String lpBinaryPathName, String lpLoadOrderGroup, IntPtr lpdwTagId, [In] char[] lpDependencies, String lpServiceStartName, String lpPassword, String lpDisplayName);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);
private bool ServicePasswordChange(string changePassword, string strServiceName)
{
try
{
IntPtr databaseHandle = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS);
if (databaseHandle == IntPtr.Zero)
throw new System.Runtime.InteropServices.ExternalException("Open Service Manager Error");
IntPtr pServiceHandle = OpenService(databaseHandle, strServiceName, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);
if (pServiceHandle == IntPtr.Zero)
throw new System.Runtime.InteropServices.ExternalException("Open Service Error");
//This code is changing the password for the service.
if (!ChangeServiceConfig(pServiceHandle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, null, null,
IntPtr.Zero, null, null, changePassword, null))
{
int nError = Marshal.GetLastWin32Error();
Win32Exception win32Exception = new Win32Exception(nError);
throw new System.Runtime.InteropServices.ExternalException("Could not change password : " + win32Exception.Message);
}
return true;
}
catch (Exception ex)
{
ErrFromApi_Label.Text = ex.ToString();
return false;
}
}

Categories

Resources