Setting Access permissions on Semaphore? - windows

I am assuming that once a semaphore is created by a process, it will be accessible by any process/user.
Is it possible to put access restrictions on a particular semaphore so that it can be accessible by only certain processes/users or only certain processes can release the semaphore.
I see some problems if we make a semaphore accessible by all processes.Eg: a dummy process can read the semaphore and release the lock at wish making a false signal to the actual process that is really waiting for the semaphore lock.
All these questions are arising as I am getting very weird output with the following code snippet:
use Win32::Semaphore;
$sem = Win32::Semaphore->new(0, 1,"reliance2692")
or print "Can't create semaphore\n";
$sem = Win32::Semaphore->open("reliance2692")
or print "Can't open semaphore\n";
print "Semaphore:" . $sem . "\n";
By running the above program, I am getting the following output
Can't create semaphore
Can't open semaphore
The output shows that its failed to create a semaphore and even failed to open semaphore.
creating a semaphore might have failed if a semaphore already exists with the given name.
I don't understand why opening a semaphore failed.
Can some clarify the scenario where both creating semaphore & opening semaphore fails.

Win32::Semaphore->new calls the Windows API function CreateSemaphore and gets the process's default security descriptor, which usually means that processes running as the same user as your script can have full access whereas processes running as other accounts get no access. So, for starters, your assumption is false.
The name you choose in your Perl code is passed directly to the API function, so it's subject to the same namespace rules as all other Win32 kernel objects.
Win32::Semaphore provides no interface for specifying access restrictions. Even if it did, Windows does not provide per-process permissions. Permissions are attached to the user, not the process.
If you're getting "access denied" from new, then that suggests there's another program running that chose to use that same name for something else — maybe another semaphore, or maybe something else, like an event or a mutex — and that process is running as a different user.
If you're getting "access denied" from open, then, in addition to the possibilities for new, it could be that another process has already opened a semaphore with the same name but has not granted full permissions to other users. Win32::Semaphore->open requests SEMAPHORE_ALL_ACCESS permission.
If the semaphore has already been opened by a process running as the same user, then you should not get "access denied." Neither new nor open should fail in that case, although $^E might hold 183 (ERROR_ALREADY_EXISTS) anyway.

For the record, I'm the author of Win32::Semaphore. As mobrule and Rob have explained, Windows security is user/group based. It's not possible to have a semaphore that only certain processes can access. If any process belonging to a user can access a semaphore, then any process of that user can access that semaphore.
Normally, the default access allows only the current user to access the semaphore. Nobody's ever requested the ability to have Win32::Semaphore specify a non-default security descriptor, and the associated API is non-trivial. If somebody created a module to manage a SECURITY_ATTRIBUTES structure, I'd be happy to add support for that to Win32::Semaphore and the related IPC modules. Win32-Security does not appear to be that module, although it might be a start.
If you need a semaphore to work across multiple users, your only solution right now is to create the semaphore outside of Win32::Semaphore, passing an appropriate SECURITY_ATTRIBUTES pointer. You could do that with a small helper program written in C, or using Inline::C. (Remember that once created, a semaphore exists as long as any process has an open handle to it, so your helper program needs to keep the semaphore handle open until you've called Win32::Semaphore->open on it.)

From Win32::Semaphore pod
$semaphore = Win32::Semaphore->new($initial, $maximum, [$name])
Constructor for a new semaphore object. $initial is the initial count, and $maximum is
the maximum count for the semaphore. If $name is omitted or undef, creates an unnamed
semaphore object.
If $name signifies an existing semaphore object, then $initial and $maximum are ignored
and the object is opened. If this happens, $^E will be set to 183
(ERROR_ALREADY_EXISTS).
If I'm reading this correctly, if your call to Win32::Semaphore->new refers to an existing semaphore, then the new call will open the semaphore as well, and the subsequent open call will be redundant (it's not clear to me from the pod what should happen if you open a sempahore that is already open).
Perhaps you could step through the code, checking the value of $sem as well as $! and $^E at each step.
Additional reply: the Windows API does have methods for setting access control of semaphores, but
they don't appear to be exposed in the Perl Win32::Semaphore module
access control can't be set unless it was already allowed by the other process that created the semaphore
I don't know if you have any good options for this problem. Can you modify the process that creates the semaphore to relax access restrictions? Ask the Win32::Semaphore author to update his module? Try to fix Win32::Semaphore yourself?

Related

Is there a way to know if the current process holds a specific file lock?

We have a serie of applications running on windows that uses file locking for protecting concurrent access to their data (shared files on network drive).
Sometimes, it seems one of these process fails to release one of these locks and everything freezes until the process is killed. Finding out who holds that lock is not always trivial (needs an admin to go on the file server and check network open files, go one workstation, find process and kill it).
We have a message queue system between the applications that is serviced by a background thread so, in theory, it would be possible to send out a message to every process asking them if they hold a lock to a specific file and if they do, mybe take an action like kill the process if the lock is held longer than a few seconds)
So, the question is: is there a way for a thread to know if a different thread of the same process holds a lock (LockFile) against a given file?
I'm not sure if there is a API to query this but a process can query itself with the LockFileEx function:
A shared lock can overlap an exclusive lock if both locks were created using the same file handle. When a shared lock overlaps an exclusive lock, the only possible access is a read by the owner of the locks.
The other thread could query and see if it can get shared access.
If you control the file format you could write the computer name and process id to the start of the file every time you take the lock. File memory mappings can view the file contents even while it is locked.

How to identify/authorize the sender of a message in a named pipe? (CreateNamedPipe)

I've created a communication between two applications using named pipes.
The first application creates a named pipe with CreateNamedPipe and reads the received messages with ReadFile sent by the second application. Both applications are able to communicate that way as intended.
Is it somehow possible to identify the sender of a received message?
Without some sort of identification (like getting the sender exe path) or authorization every other application could use that pipe to send messages to my application.
(Edit) Further details, because it seems it's important in this case:
The application that creates the pipe is running as a Windows service.
Both applications run locally on the same system.
The GetNamedPipeClientProcessId() will give you the process ID of the client process. You can then open a handle to the process with OpenProcess() and call GetModuleFileNameEx() to determine what application is running in that process. You can then vet the application in whatever way you think best, e.g., you might want to check the identity of the digital certificate or you might prefer to just check that the pathname is as you expect it to be.
Note that attempting to restrict access to a particular application rather than a particular user is never going to be robust; an attacker could always take control of the approved application and replace its code with their own. Basically it isn't going to be more than a speed bump, but if you feel it is worth doing, it can be done.
If what you really want to know is what user has connected, you should instead be using ImpersonateNamedPipeClient() as already suggested in the comments, followed by OpenThreadToken() and so on. Or better still, set the permissions when creating the named pipe so that only the authorized users are able to connect in the first place.
Now that you've clarified that the client runs with elevated privileges, I can make a more concrete recommendation: do both of the above. Configure the permissions on the named pipe so that only members of the Administrators group can access it; that will ensure that only applications running with elevated privilege can access it. Checking the executable as well won't hurt, but it isn't sufficient by itself, because an attacker could launch a copy of your application, suppress the requested elevatation, and inject their own code into the process. (Or, as conio points out, modify their own process to make it look as if they are running your executable; GetModuleFileNameEx() is not intended to be used as a security measure, so it makes no effort to avoid spoofing.)

Access denied error when using VirtualQueryEx

So, I wrote a program which is able to successfully read memory from most of processes using VirtualQueryEx. However, I've come across a process for which this function fails. It's not a system process, just a game process. Without Debug privileges I couldn't even open the process's handle. With them I am able to get the process's handle but still get access denied for VirtualQueryEx.
I'm not sure but maybe the process is private? If that's the case, what should I do to successfully use VirtualQueryEx function?
I've also read somewhere that I might have to suspend whole process's threads before running VirtualQueryEx, but so far I didn't need that... And when I used function Thread32First to get the first thread it gave me an error: ERROR_BAD_LENGTH...
I would be very grateful for any help in this matter!
How are you opening the process handle? From the doc:
The handle must have been opened with the PROCESS_QUERY_INFORMATION
access right, which enables using the handle to read information from
the process object.
Another possibility is that the target process and your process are different bitness (32 vs 64). In that case you either need to use MEMORY_BASIC_INFORMATION32 or something like VirtualQueryEx64 from wow64ext library.

how to prevent multiple program loading in windows?

I am developing an windows application.
what I want is to prevent this application running multiple in single OS.
(e.g. we can run multiple instance of notepad.exe, calc.exe at the same time... but I don't want this)
what is the most effective way to implement this?(preventing multiple instance of process running at same time)
I'd rather not use methods like checking process names or sharing some global file as a signal... since it is too easy to circumvent
thank you in advance
This is typically done with mutexs. When your process launches you call CreateMutex and check the return value. If it succeeded then this is the first launch, otherwise there is another instance of your process alive. Your mutex should be in the Global\ namespace. Also make sure to ReleaseMutex when your program finishes running.
What framework are you using? I'm assuming it's .Net? Here's a post from an msdn foum on the same thing.
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/3e139912-45ea-432e-b9e0-e03640c07c9f/
You mentioned you don't want to check current process names or use a global file.
Lock the current executable
.NET example code:
System.IO.File.Open(
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName,
System.IO.FileMode.Open,
System.IO.FileAccess.Read,
System.IO.FileShare.None);
The FileShare.None keeps any other process (like Windows Explorer) from executing the file until the app closes or the file handle (returned object) is explicitly closed.
Global Mutex
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682411%28v=vs.85%29.aspx
If the mutex is a named mutex and the object existed before this
function call, the return value is a handle to the existing object,
GetLastError returns ERROR_ALREADY_EXISTS, bInitialOwner is ignored,
and the calling thread is not granted ownership. However, if the
caller has limited access rights, the function will fail with
ERROR_ACCESS_DENIED and the caller should use the OpenMutex function.
Global mutex is the easiest way. To clarify another answer you don't just check the return value you check the GetLastError value as well.

Mutual exclusion across user session in Citrix environment

I have an application that runs in Citrix environment. The application can be run simultaneously by several users in different user sessions. In my application I am writing to a file which should be mutually exclusive across all the user sessions. I tried Mutex to avoid writing to a file from different user sessions but using Mutex failed as in some scenarios different user sessions could not detect whether the Mutex object was already created.
Could any one tell me which of the below approach is better to achieve mutual exclusion across all the user sessions:
Using Named pipes :
If named pipe already exists then application will wait till the pipe gets closed by the application instance which had opened it. Otherwise create the named pipe to indicate the acquiring of lock.
Using a lock file:
Create a normal file on disk to indicate the acquiring of lock and delete when unlock needs to be done.
You don't need to use a lock file. You can use the built in file system sharing mechanism.
When you open the file by calling CreateFile() you determine the sharing access for subsequent attempts to open the file with the dwShareMode parameter. For example, set this to 0 and no other process will be able to open the file.

Resources