dahall / TaskScheduler

Provides a .NET wrapper for the Windows Task Scheduler. It aggregates the multiple versions, provides an editor and allows for localization.
MIT License
1.22k stars 194 forks source link

Searching for a particular task causes large number of requests to domain controller #883

Closed malvica closed 3 years ago

malvica commented 3 years ago

Describe the bug Hello Team, We are using the library version - 2.3.2.0(tried the latest 2.9.1 as well) in our product and have noticed a huge number of LSAlookup requests going to the Domain controller. When our product is installed it creates a task in the TaskScheduler called "TitusHealthMonitor". Once installed our code looks for the presence of the task it created to see if it somehow got tempered with(e.g. if someone deleted it). To do that we use the code shown below: using (var ts = new TaskService()) { return ts.RootFolder.AllTasks.FirstOrDefault(t => t.Name == "TitusHealthMonitor"); } As soon as it tries to iterate over the tasks tries to run the lambda expression it starts performing the LSALookups which can be seen in the lsp.log file in C:\Windows\debug location I have attached a file which shows how to enable the lsp logging. To Reproduce In order to reproduce the issue please run the attached c# solution.

Expected behavior I would like to understand what is causing those LSAlookups as it is impacting our customers traffic to their Domain Controllers.

Screenshots: image TaskSchedulerIssue.zip EnableLSPLogs.txt

Thank you

dahall commented 3 years ago

I just checked to confirm, but my code does not call LsaLookupSids. My assumption then is that the native Microsoft COM library for Task Scheduler is making the calls.

That said, I think there is a more efficient way to do the task lookup you described:

return TaskService.Instance.GetTask("TitusHealthMonitor");

TaskService.Instance is the same as new TaskService() and GetTask looks in the root folder for a given task's name and returns the task or null if not found. This method does not iterate to find the task, it goes directly to the internal database.

malvica commented 3 years ago

Hi Dahall, Thank you so much for the prompt reply! I was too wondering that it might be the native msft call to TaskScheduler causing it. Did you get a chance to run my solution though? I will try your recommended solution and will let you know how it goes.

Thanks again.

malvica commented 3 years ago

Hi again, your recommendation did work and brought down the number of calls to only two: image

I'll need to open a ticket with MSFT now to understand the reason behind those LSAlookups. Thanks a lot for the help :)

dahall commented 3 years ago

Every task has an associated ACL assigned to SIDs. My guess is that before granting access to the task, MSFT does a lookup on the SID and verifies access. Two calls would make sense (Owner and DACL SIDS).

malvica commented 3 years ago

Hello @dahall I contacted MSFT in order to get some help on the lsalookup call that I see using your library. As you mentioned that this call is coming from MSFT native COM I used the sample code from MSFT docs on Task Scheduler mentioned here https://docs.microsoft.com/en-us/windows/win32/taskschd/displaying-task-names-and-state--c---

MSFT came back saying the following call to CoInitializeSecurity is making LSALookup call, is that something that is being used in your library? hr = CoCreateInstance( CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService );

Thank you

dahall commented 3 years ago

Yes, every call to the TaskService constructor creates an instance of IID_ITaskService. So it is as I suspected. CoInitializeSecurity is a very common call in COM objects that are secured.

malvica commented 3 years ago

ok, just wanted to confirm that, thanks a lot for all the help :)