How do I access a Linux Samba share from a Windows Service? - windows-services

I'm writing a Windows Service in C#. I have a samba share on a linux server that I can browse/read/write from the windows machine, and I have it mapped to a drive letter. The Windows service is running as the SYSTEM user and cannot write to the share.
What should I change?

I used an entry like this in my samba configuration file (smb.conf) to make it writable by any user.
[myshare]
comment = My Share
path = /home/myusername/myshare
public = yes
writable = yes
#maps all users to the nobody user?
only guest = yes

You need to either make the share visible to the System User. or install the service as a User other than the Local System Account that actually has permission to browse the share.
You can change the installation account in the Project Installer by setting the following 2 properties. (it's in the ProjectInstaller.Designer File
this.serviceProcessInstaller1.Username = "DOMAIN\\UserName";
this.serviceProcessInstaller1.Password = "Password";

Related

Network Service account does not accept local paths

I am creating a program that runs as a service and creates database backups (using pg_dump.exe) at certain points during the day. This program needs to be able to write the backup files to local drives AND mapped network drives.
At first, I was unable to write to network drives, but solved the problem by having the service log on as an administrator account. However, my boss wants the program to run without users having to key in a username and password for the account.
I tried to get around this by using the Network Service account (which does not need a password and always has the same name). Now my program will write to network drives, but not local drives! I tried using the regular C:\<directory name>\ path syntax as well as \\<computer name>\C$\<directory name>\ syntax and also \\<ip address>\C$\<directory name>\, none of which work.
Is there any way to get the Network Service account to access local drives?
Just give the account permission to access those files/directories, it should work. For accessing local files, you need to tweak ACLs on the files and directories. For accessing via network share, you have to make changes to file ACLs, as well as permissions on network share.
File ACLs can be modified in Exploler UI, or from command line, using standard icacls.exe. E.g. this command line will give directory and all files underneath Read, Write and Delete permissions for Network Service.
icacls c:\MyDirectory /T /grant "NT AUTHORITY\Network Service":(R,W,D)
File share permissions are easier to modify from UI, using fsmgmt.msc tool.
You will need to figure out what minimal set of permissions necessary to be applied. If you don't worry about security at all, you can give full permissions, but it is almost always an overkill, and opens you up more if for any reason the service is compromised.
I worked around this problem by creating a new user at install time which I add to the Administrators group. This allows the service to write to local and network drives, without ever needing password/username info during the setup.

Access file from shared folder from Windows Service

I have a windows service on XP OS in .Net Framework 2.0 which access folder and reads file from it to load it in database.
Shared folder has permission for "Everyone" with full control with all subfolder. and service runs on "Local System Account". and currently system running with Administrator account.
The stack trace is :
Message : Error while searching for files in : \\nw1\data\nov2012
Access to the path '\\nw1\data\nov2012' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.Directory.InternalGetFileDirectoryNames(String path, String userPathOriginal, String searchPattern, Boolean includeFiles, Boolean includeDirs, SearchOption searchOption)
at System.IO.DirectoryInfo.GetFiles(String searchPattern, SearchOption searchOption)
at System.IO.DirectoryInfo.GetFiles()
at MyWinApp.Winservice1.SearchFiles(String imp, FileFolder objFile)
Edit: I found on MSDN that "LocalSystem Account has extensive privileges on the local computer" but not sure why it is not able to access network shared folder
can anyone suggest sollution for this problem?
Thanks,
I searched on internet but everywhere i found that anyhow i have to provide username/password to provide proper permission to windows service to access network shared folder(directly to windows service property or in windows service code like given here, code in that thread is here). so to make it working it for now i set username/password manually to service property.
If you are running the service with a local account (I believe is windows what we are talking about) and that local account does not belong to the domain or a domain.
You can always create the local account on the computer that is running the services AND create the local account on the computer that is sharing the folder.
Same account name, same password. It will work

ASP.NET MVC NESTED Virtual Directory for Content Files

I'm trying to map a virtual directory in my ASP.NET MVC 3 website. The virtual directory contains image files only, and the physical directory is located on another server. When I try to access an image from this directory via a web browser, I get an HTTP 500 error:
Parser Error Message: An error occurred loading a configuration file: Failed to start monitoring changes to '<virtual directory path>' because access is denied.
[EDIT]: After restarting IIS, I see that it's added "access is denied" to the end of the error message. However, the directory has the "Everyone" permission on it with read-access and it's still not working. I've seen posts that detail this same error, but the permission-setting solution isn't working for me.
Why is it looking for a configuration file? I've updated my Global.asax to ignore the route in question, and from within IIS 6, I can browse the files located in the virtual directory without issue. I've verified that the virtual directory is NOT set up as an application. Also, the permissions on the directory have read access for Everyone set. What am I doing wrong?
[EDIT #2]: The virtual directory being pointed to is a network shared folder... Does that make any difference?
[EDIT #3]: The IIS 6 hierarchy for what I'm trying to do is this: Default Website -> OurSite (MVC website which is ITSELF a virtual directory) -> Images (virtual directory that I'm struggling with). There definitely is a problem with the fact that this is a nested virtual directory; if I create the directory as a direct child of Default Website instead of Default Website -> OurSite, it works fine.
Thanks,
Andy
Make sure the identity running the App Pool also has execute and list permissions on that virtual folder as it's trying to monitor it for changes for caching.
http://support.microsoft.com/kb/316721/
[EDIT] This link indicates it may be the second case where it's not having permissions to a subfolder in the shared directory.
http://support.microsoft.com/kb/317955
Does the ASPNET account have access all the way down that tree?
Reading Turnkey's answer and your comments, I just wanted to point out that if your AppPool is using NETWORK SERVICE identity then your remote server needs to add the web server's machine/computer account to the shared folder and NTFS permissions NOT the NETWORK SERVICE account.
If you add NETWORK SERVICE to the shared folder and NTFS permissions, you are just adding the local machine's NETWORK SERVICE account not the web server's NETWORK SERVICE account. I hope I am making sense.
Whenever you use a computer's NETWORK SERVICE account to connect remotely you are in effect using the computer's machine account so that's what you need to add.
Say your web server is called PRODSERVER, you need to add the machine/computer account PRODSERVER$ to the remote shared folder's permissions.
Hope that helps.

Start / Stop a Windows Service from a non-Administrator user account

I have a WindowsService named, say, BST. And I need to give a non-Administrator user, UserA, the permissions to Start/Stop this particular service. My service runs on a variety of Windows OS, starting from Windows Server 2003 to Windows 7.
How can I do this?
I Googled and found some stuff about giving permissions using the command [sc sdset], but I am not exactly sure about the parameters. I do not want to set the permissions for a group, but ONLY to a particular user, UserA in this case.
Below I have put together everything I learned about Starting/Stopping a Windows Service from a non-Admin user account, if anyone needs to know.
Primarily, there are two ways in which to Start / Stop a Windows Service.
1. Directly accessing the service through logon Windows user account.
2. Accessing the service through IIS using Network Service account.
Command line command to start / stop services:
C:/> net start <SERVICE_NAME>
C:/> net stop <SERVICE_NAME>
C# Code to start / stop services:
ServiceController service = new ServiceController(SERVICE_NAME);
//Start the service
if (service.Status == ServiceControllerStatus.Stopped)
{
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(10.0));
}
//Stop the service
if (service.Status == ServiceControllerStatus.Running)
{
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10.0));
}
Note 1:
When accessing the service through IIS, create a Visual Studio C# ASP.NET Web Application and put the code in there. Deploy the WebService to IIS Root Folder (C:\inetpub\wwwroot\) and you're good to go.
Access it by the url http:///.
1. Direct Access Method
If the Windows User Account from which either you give the command or run the code is a non-Admin account, then you need to set the privileges to that particular user account so it has the ability to start and stop Windows Services. This is how you do it.
Login to an Administrator account on the computer which has the non-Admin account from which you want to Start/Stop the service. Open up the command prompt and give the following command:
C:/>sc sdshow <SERVICE_NAME>
Output of this will be something like this:
D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
It lists all the permissions each User / Group on this computer has with regards to .
A description of one part of above command is as follows:
D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)
It has the default owner, default group, and it has the Security descriptor control flags (A;;CCLCSWRPWPDTLOCRRC;;;SY):
ace_type - "A": ACCESS_ALLOWED_ACE_TYPE,
ace_flags - n/a,
rights - CCLCSWRPWPDTLOCRRC, please refer to the Access Rights and Access Masks and Directory Services Access Rights
CC: ADS_RIGHT_DS_CREATE_CHILD - Create a child DS object.
LC: ADS_RIGHT_ACTRL_DS_LIST - Enumerate a DS object.
SW: ADS_RIGHT_DS_SELF - Access allowed only after validated rights checks supported by the object are performed. This flag can be used alone to perform all validated rights checks of the object or it can be combined with an identifier of a specific validated right to perform only that check.
RP: ADS_RIGHT_DS_READ_PROP - Read the properties of a DS object.
WP: ADS_RIGHT_DS_WRITE_PROP - Write properties for a DS object.
DT: ADS_RIGHT_DS_DELETE_TREE - Delete a tree of DS objects.
LO: ADS_RIGHT_DS_LIST_OBJECT - List a tree of DS objects.
CR: ADS_RIGHT_DS_CONTROL_ACCESS - Access allowed only after extended rights checks supported by the object are performed. This flag can be used alone to perform all extended rights checks on the object or it can be combined with an identifier of a specific extended right to perform only that check.
RC: READ_CONTROL - The right to read the information in the object's security descriptor, not including the information in the system access control list (SACL). (This is a Standard Access Right, please read more http://msdn.microsoft.com/en-us/library/aa379607(VS.85).aspx)
object_guid - n/a,
inherit_object_guid - n/a,
account_sid - "SY": Local system. The corresponding RID is SECURITY_LOCAL_SYSTEM_RID.
Now what we need to do is to set the appropriate permissions to Start/Stop Windows Services to the groups or users we want. In this case we need the current non-Admin user be able to Start/Stop the service so we are going to set the permissions to that user. To do that, we need the SID of that particular Windows User Account. To obtain it, open up the Registry (Start > regedit) and locate the following registry key.
LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
Under that there is a seperate Key for each an every user account in this computer, and the key name is the SID of each account. SID are usually of the format S-1-5-21-2103278432-2794320136-1883075150-1000. Click on each Key, and you will see on the pane to the right a list of values for each Key. Locate "ProfileImagePath", and by it's value you can find the User Name that SID belongs to. For instance, if the user name of the account is SACH, then the value of "ProfileImagePath" will be something like "C:\Users\Sach". So note down the SID of the user account you want to set the permissions to.
Note2:
Here a simple C# code sample which can be used to obtain a list of said Keys and it's values.
//LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList RegistryKey
RegistryKey profileList = Registry.LocalMachine.OpenSubKey(keyName);
//Get a list of SID corresponding to each account on the computer
string[] sidList = profileList.GetSubKeyNames();
foreach (string sid in sidList)
{
//Based on above names, get 'Registry Keys' corresponding to each SID
RegistryKey profile = Registry.LocalMachine.OpenSubKey(Path.Combine(keyName, sid));
//SID
string strSID = sid;
//UserName which is represented by above SID
string strUserName = (string)profile.GetValue("ProfileImagePath");
}
Now that we have the SID of the user account we want to set the permissions to, let's get down to it. Let's assume the SID of the user account is S-1-5-21-2103278432-2794320136-1883075150-1000.
Copy the output of the [sc sdshow ] command to a text editor. It will look like this:
D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
Now, copy the (A;;CCLCSWRPWPDTLOCRRC;;;SY) part of the above text, and paste it just before the S:(AU;... part of the text. Then change that part to look like this:
(A;;RPWPCR;;;S-1-5-21-2103278432-2794320136-1883075150-1000)
Then add sc sdset at the front, and enclose the above part with quotes. Your final command should look something like the following:
sc sdset <SERVICE_NAME> "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;RPWPCR;;;S-1-5-21-2103278432-2794320136-1883075150-1000)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)"
Now execute this in your command prompt, and it should give the output as follows if successful:
[SC] SetServiceObjectSecurity SUCCESS
Now we're good to go! Your non-Admin user account has been granted permissions to Start/Stop your service! Try loggin in to the user account and Start/Stop the service and it should let you do that.
2. Access through IIS Method
In this case, we need to grant the permission to the IIS user "Network Services" instead of the logon Windows user account. The procedure is the same, only the parameters of the command will be changed. Since we set the permission to "Network Services", replace SID with the string "NS" in the final sdset command we used previously. The final command should look something like this:
sc sdset <SERVICE_NAME> "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;RPWPCR;;;NS)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)"
Execute it in the command prompt from an Admin user account, and voila! You have the permission to Start / Stop the service from any user account (irrespective of whether it ia an Admin account or not) using a WebMethod. Refer to Note1 to find out how to do so.
I use the SubInACL utility for this. For example, if I wanted to give the user job on the computer VMX001 the ability to start and stop the World Wide Web Publishing Service (also know as w3svc), I would issue the following command as an Administrator:
subinacl.exe /service w3svc /grant=VMX001\job=PTO
The permissions you can grant are defined as follows (list taken from here):
F : Full Control
R : Generic Read
W : Generic Write
X : Generic eXecute
L : Read controL
Q : Query Service Configuration
S : Query Service Status
E : Enumerate Dependent Services
C : Service Change Configuration
T : Start Service
O : Stop Service
P : Pause/Continue Service
I : Interrogate Service
U : Service User-Defined Control Commands
So, by specifying PTO, I am entitling the job user to Pause/Continue, Start, and Stop the w3svc service.
Edit: updated links to web.archive.org since the original MS links are dead.
Login as an administrator.
Download subinacl.exe from Microsoft:
http://www.microsoft.com/en-us/download/details.aspx?id=23510
Grant permissions to the regular user account to manage the BST
services.
(subinacl.exe is in C:\Program Files (x86)\Windows Resource Kits\Tools\).
cd C:\Program Files (x86)\Windows Resource Kits\Tools\
subinacl /SERVICE \\MachineName\bst /GRANT=domainname.com\username=F or
subinacl /SERVICE \\MachineName\bst /GRANT=username=F
Logout and log back in as the user. They should now be able to
launch the BST service.
There is a free GUI Tool ServiceSecurityEditor
Which allows you to edit Windows Service permissions. I have successfully used it to give a non-Administrator user the rights to start and stop a service.
I had used "sc sdset" before I knew about this tool.
ServiceSecurityEditor feels like cheating, it's that easy :)
It's significantly easier to grant management permissions to a service using one of these tools:
Group Policy
Security Template
subinacl.exe command-line tool.
Here's the MSKB article with instructions for Windows Server 2008 / Windows 7, but the instructions are the same for 2000 and 2003.
subinacl.exe command-line tool is probably the only viable and very easy to use from anything in this post. You cant use a GPO with non-system services and the other option is just way way way too complicated.
Windows Service runs using a local system account.It can start automatically as the user logs into the system or it can be started manually.However, a windows service say BST can be run using a particular user account on the machine.This can be done as follows:start services.msc and go to the properties of your windows service,BST.From there you can give the login parameters of the required user.Service then runs with that user account and no other user can run that service.

Creating service on windows xp

I'm creating services on Windows XP.
I have to use a utility that we are using . The utility is making registration in the registry.
My question is that when I'm creating the service a folder name Enum is not created, which I saw was created for all other services.
Is it important ? For what I need it ?
Thanks
You should use the service APIs (CreateService) to create your service instead of manipulating the registry manually (or via your utility).
The format of the services registry has changed over the years and if you don't use the defined APIs, you may risk malfunctions (you're also going to require a reboot after the registry changes are made because the service controller has now way of knowing about your new service).
A common windows service doesn't need anything such as "Enum" Directory. It must be something specific in your applications. So if the directory wasn't created automatically, you need to write an installer for your service which creates this directory automatically, or create it manually.
You can use the command "instsrv" if you want to register a new service running under Windows XP.
Cheers
Tomas

Resources