How to grant Access on Files on a share drive?
From: Jörgen Ahrens (jahrens_at_community.nospam)
Date: 11/08/05
- Previous message: Rhett Gong [MSFT]: "RE: Getting/Setting Local Group Policy data via API ?"
- Next in thread: Jeffrey Tan[MSFT]: "RE: How to grant Access on Files on a share drive?"
- Reply: Jeffrey Tan[MSFT]: "RE: How to grant Access on Files on a share drive?"
- Reply: Jeffrey Tan[MSFT]: "RE: How to grant Access on Files on a share drive?"
- Reply: Jeffrey Tan[MSFT]: "RE: How to grant Access on Files on a share drive?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Date: Tue, 8 Nov 2005 09:55:54 +0100
Hi All
We are trying to grant access on files on a share drive.
We have a client application running on a client machine where we
impersonate a technical user that has access to the server.
The actual user doesn't have access to the files located on the server. At
runtime we would like to grant access to the client user (on a specific file
on the server).
We managed to grant access by :
- mapping the shared folder from the server to the client machine
- we did not impersonate the technical user, but we ran the client
application under the profile of the technical user (what is not what we
need).
It seems as if the impersonated would not recongnize the mapped drives.(we
tried to implement the mapping on the client machine under the normal user
account and under the technical user account as well as on the server
machine)
Is it true, that we need to have a mapped shared drive to actually succeed?
or is it possible to access the shared folder directly without mapping the
networkdrive?
If we need to map the network drive, how can we assure that the impersonated
user can see the mapped network drives?
We attached our testprogram (Impersonation seemed to worked well and is not
included in the testprogram).
thanks for your help
j.ahrens
---------------------------------------------------------------------------------------------
Test scenario:
Server: S01
Client: W07
Shared Folder on the Server: \\S01\_KnowledgeBase (D:\Daten\_KnowledgeBase)
Mapped network drive: \\S01\_KnowledgeBase is mapped onto K:\ on the client
(would be nice if we could drop that and just use \\S01\_KnowledgeBase
directly)
---------------------------------------------------------------------------------------------
CODE
---------------------------------------------------------------------------------------------
using System;
using System.Management;
using System.Collections;
namespace Ascami.LogExcellence.WinApp
{
// Access mask (see AccessMask property)
[Flags]
enum Mask : uint
{
FileReadData = 0x00000001,
FileWriteData = 0x00000002,
FileAppendData = 0x00000004,
FileReadEA = 0x00000008,
FileWriteEA = 0x00000010,
FileExecute = 0x00000020,
FileDeleteChild = 0x00000040,
FileReadAttributes = 0x00000080,
FileWriteAttributes= 0x00000100,
Delete = 0x00010000,
ReadControl = 0x00020000,
WriteDac = 0x00040000,
WriteOwner = 0x00080000,
Synchronize = 0x00100000,
AccessSystemSecurity = 0x01000000,
MaximumAllowed = 0x02000000,
GenericAll = 0x10000000,
GenericExecute= 0x20000000,
GenericWrite = 0x40000000,
GenericRead = 0x80000000
}
[Flags]
enum AceFlags : uint
{
NonInheritAce = 0,
ObjectInheritAce = 1,
ContainerInheritAce = 2,
NoPropagateInheritAce = 4,
InheritOnlyAce = 8,
InheritedAce = 16
}
[Flags]
enum AceType : uint
{
AccessAllowed = 0,
AccessDenied = 1,
Audit = 2
}
/// <summary>
/// The class offers two static functions used to allow or deny access to
files.
/// </summary>
class ManageFilePermissions
{
/// <summary>
/// This main is used to test this class.
/// </summary>
public static void Main()
{
//Start Impersonation
// Impersonation imp = new Impersonation();
// imp.LoadProfile("Ascami", "logexcellence", "pwd");
// imp.StartImpersonation();
//
//
System.Windows.Forms.MessageBox.Show(System.IO.Directory.Exists("K:\\1\\2").ToString());
bool success;
//Allow access for samrein to file K:\1\2\3.xls on server S01
success = ManageFilePermissions.AllowFileAccess("Ascami", "samrein",
"K:\\1\\2\\3.xls", "S01");
//Deny samrein
success = ManageFilePermissions.DenyFileAccess("Ascami", "samrein",
"K:\\1\\2\\3.xls", "S01");
//Allow wiederkehr
success = ManageFilePermissions.AllowFileAccess("Ascami", "swiederkehr",
"K:\\1\\2\\3.xls", "S01");
//Allow samrein
success = ManageFilePermissions.AllowFileAccess("Ascami", "samrein",
"K:\\1\\2\\3.xls", "S01");
//Deny mahrenes
success = ManageFilePermissions.DenyFileAccess("Ascami", "mahrens",
"K:\\1\\2\\3.xls", "S01");
//Deny wiederkehr
success = ManageFilePermissions.DenyFileAccess("Ascami", "swiederkehr",
"K:\\1\\2\\3.xls", "S01");
//Deny samrein
success = ManageFilePermissions.DenyFileAccess("Ascami", "samrein",
"K:\\1\\2\\3.xls", "S01");
}
/// <summary>
/// Allows the specified user to read and write the specified file.
/// </summary>
/// <param name="domain">The domain of the user</param>
/// <param name="username">The username of the user</param>
/// <param name="file">The file</param>
/// <param name="server">The server of the file. If it is placed on the
local machine use '.'</param>
/// <returns>true if the user is now allowed to read and write</returns>
public static bool AllowFileAccess(string domain, string username, string
file, string server)
{
ManagementObject lfs;
ManagementBaseObject descriptor; //The security descriptor
ManagementBaseObject[] dacl = FetchDACL(server, file, out lfs, out
descriptor);
if (dacl == null)
{
System.Windows.Forms.MessageBox.Show("Failed to fetch DACL.", "Error");
return false;
}
int aceIndex = GetACE(dacl, domain, username);
if (aceIndex == -1)
{
//ace does not exist -> create it, add it
ManagementBaseObject ace = CreateACE(domain, username, Mask.GenericRead
| Mask.GenericWrite);
if (ace == null)
{
System.Windows.Forms.MessageBox.Show("Could not create ACE for
domain\\username.", "Error");
return false;
}
dacl = AddACE(dacl, ace);
if (!WriteDACL(dacl, lfs, descriptor))
{
System.Windows.Forms.MessageBox.Show("Could not write DACL.", "Error");
return false;
}
return true;
}
else
{
//ace exists, modify it
ManagementBaseObject ace = dacl[aceIndex];
ModifyACE(ace, Mask.GenericRead | Mask.GenericWrite);
if (!WriteDACL(dacl, lfs, descriptor))
{
System.Windows.Forms.MessageBox.Show("Could not write DACL.", "Error");
return false;
}
return true;
}
}
/// <summary>
/// Denies the specified user to read and write the specified file.
/// </summary>
/// <param name="domain">The domain of the user</param>
/// <param name="username">The username of the user</param>
/// <param name="file">The file</param>
/// <param name="server">The server of the file. If it is placed on the
local machine use '.'</param>
/// <returns>true if the user is now denied to read and write</returns>
public static bool DenyFileAccess(string domain, string username, string
file, string server)
{
ManagementObject lfs;
ManagementBaseObject descriptor;
ManagementBaseObject[] dacl = FetchDACL(server, file, out lfs, out
descriptor);
if (dacl == null)
{
System.Windows.Forms.MessageBox.Show("Failed to fetch DACL.", "Error");
return false;
}
int aceIndex = GetACE(dacl, domain, username);
if (aceIndex == -1)
{
//No entry exists, return
return true;
}
else
{
dacl = RemoveACE(dacl, aceIndex);
if (!WriteDACL(dacl, lfs, descriptor))
{
System.Windows.Forms.MessageBox.Show("Could not write DACL.", "Error");
return false;
}
return true;
}
}
/// <summary>
/// Returns the index of the ACE from the DACL-list if it exists
/// </summary>
/// <param name="dacl">the discretionary access control list</param>
/// <param name="domain">The domain of the user</param>
/// <param name="username">The username of the user</param>
/// <returns>the index of the ace or -1 if none exists</returns>
private static int GetACE(ManagementBaseObject[] dacl, string domain,
string username)
{
ManagementBaseObject ace;
for (int i=0;i<dacl.Length;i++)
{
ace = dacl[i];
//Find out if it is an ace of the specified user
ManagementBaseObject trustee = (ManagementBaseObject)(ace["Trustee"]);
string trusteeDomain = trustee.Properties["Domain"].Value.ToString();
string trusteeUsername = trustee.Properties["Name"].Value.ToString();
if (string.Compare(domain, trusteeDomain, true)!= 0) continue;
if (string.Compare(username, trusteeUsername, true) != 0) continue;
//return the ace
return i;
}
return -1;
}
/// <summary>
/// Sets the ACE access mask.
/// </summary>
/// <param name="ace">The access control entry you would liko to
modify</param>
/// <param name="accessMask">The access mask</param>
private static void ModifyACE(ManagementBaseObject ace, Enum accessMask)
{
ace.Properties["AccessMask"].Value = accessMask;
}
/// <summary>
/// Creates a new Access Control Entry
/// </summary>
/// <param name="domain">The domain of the user</param>
/// <param name="username">The username of the user</param>
/// <param name="accessMask">The access mask</param>
/// <returns>The new Access Control Entry or null if the command
failed</returns>
private static ManagementBaseObject CreateACE(string domain, string
username, Enum accessMask)
{
ManagementBaseObject trustee = null;
ManagementBaseObject ace = null;
// Initialize new Trustee
try
{
trustee = new ManagementClass("Win32_Trustee");
trustee.Properties["Domain"].Value = domain;
trustee.Properties["Name"].Value = username;
}
catch (Exception)
{
//Happens if trustee does not exist
return null;
}
try
{
ace = new ManagementClass("Win32_ACE");
ace.Properties["AccessMask"].Value = accessMask;
ace.Properties["AceFlags"].Value = AceFlags.NoPropagateInheritAce;
ace.Properties["AceType"].Value = AceType.AccessAllowed;
ace.Properties["Trustee"].Value = trustee;
}
catch (Exception)
{
//No idea when this happens...
return null;
}
return ace;
}
/// <summary>
/// Writes the passed Discretionary Access Control List.
/// </summary>
/// <param name="dacl">The Discretionary Access Control List</param>
/// <param name="lfs">the object on which the dacl is written</param>
/// <param name="descriptor">the security descriptor</param>
/// <returns>true if successful, false if it failed</returns>
private static bool WriteDACL(ManagementBaseObject[] dacl,
ManagementObject lfs, ManagementBaseObject descriptor)
{
ManagementBaseObject inParams =
lfs.GetMethodParameters("SetSecurityDescriptor");
descriptor.Properties["Dacl"].Value = dacl;
inParams["Descriptor"] = descriptor;
ManagementBaseObject ret = lfs.InvokeMethod("SetSecurityDescriptor",
inParams, null);
if ((Convert.ToUInt32(ret.Properties["ReturnValue"].Value) == 0))
return true;
else
return false;
}
/// <summary>
/// Adds an ACE to a DACL
/// </summary>
/// <param name="dacl">The discretionary access control list</param>
/// <param name="ace">The access control entry</param>
/// <returns>the new discretionary access control list</returns>
private static ManagementBaseObject[] AddACE(ManagementBaseObject[] dacl,
ManagementBaseObject ace)
{
ManagementBaseObject[] newDacl = new ManagementBaseObject[dacl.Length+1];
dacl.CopyTo(newDacl, 0);
newDacl[newDacl.Length-1] = ace;
return newDacl;
}
/// <summary>
/// Removes an ACE of a DACL
/// </summary>
/// <param name="dacl">The discretionary access control list</param>
/// <param name="index">The index of the ACE you would like to
remove</param>
/// <returns>the new discretionary access control list</returns>
private static ManagementBaseObject[] RemoveACE(ManagementBaseObject[]
dacl, int index)
{
ManagementBaseObject[] newDacl = new ManagementBaseObject[dacl.Length-1];
int count = 0;
for (int i=0;i<dacl.Length;i++)
{
if (i==index) continue;
newDacl[count] = dacl[i];
count++;
}
return newDacl;
}
/// <summary>
/// Fetches the DACL for the specified file (non-inherited only!)
/// </summary>
/// <param name="server">The server the file is placed</param>
/// <param name="file">The path of the file</param>
/// <param name="lfs">out parameter: identifies the object(file)</param>
/// <param name="descriptor">out parameter: identifies the security
descriptor</param>
/// <returns>The discretionary access control list</returns>
private static ManagementBaseObject[] FetchDACL(string server, string
file, out ManagementObject lfs, out ManagementBaseObject descriptor)
{
lfs = null;
descriptor = null;
//The WMI Path of the file
try
{
ManagementPath path = new ManagementPath();
path.Server = server;
path.NamespacePath = @""; //for local machine @"root\cimv2" works, for
server not
//Replace backslashes by double blackslashes
file = file.Replace("\\", "\\\\");
path.RelativePath =
@"Win32_LogicalFileSecuritySetting.Path='"+file+"'";
//Fetch object
lfs = new ManagementObject(path);
// Get the security descriptor for this object
// bool EnablePrivileges = lfs.Scope.Options.EnablePrivileges;
lfs.Scope.Options.EnablePrivileges = true;
ManagementBaseObject outParams =
lfs.InvokeMethod("GetSecurityDescriptor", null, null);
if (((uint)(outParams.Properties["ReturnValue"].Value)) != 0)
{
System.Windows.Forms.MessageBox.Show("Failed to fetch object.",
"Error");
return null;
}
descriptor =
(ManagementBaseObject)(outParams.Properties["Descriptor"].Value);
//The DACL is an array of Win32_ACE objects.
ManagementBaseObject[] dacl =
(ManagementBaseObject[])(descriptor.Properties["Dacl"].Value);
//Remove all inherited aces
ArrayList nonInheritedAces = new ArrayList();
foreach(ManagementBaseObject ace in dacl)
{
if ((uint)ace["AceFlags"] == (uint)AceFlags.NonInheritAce)
{
nonInheritedAces.Add(ace);
}
}
dacl = new ManagementBaseObject[nonInheritedAces.Count];
nonInheritedAces.CopyTo(dacl);
return dacl;
}
catch (Exception e)
{
e.ToString();
return null;
}
}
}
}
- Previous message: Rhett Gong [MSFT]: "RE: Getting/Setting Local Group Policy data via API ?"
- Next in thread: Jeffrey Tan[MSFT]: "RE: How to grant Access on Files on a share drive?"
- Reply: Jeffrey Tan[MSFT]: "RE: How to grant Access on Files on a share drive?"
- Reply: Jeffrey Tan[MSFT]: "RE: How to grant Access on Files on a share drive?"
- Reply: Jeffrey Tan[MSFT]: "RE: How to grant Access on Files on a share drive?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
|