Skip to content

Commit

Permalink
fix: wrap session api calls with a timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
rvazarkar committed Aug 7, 2024
1 parent 44fa792 commit a9e3128
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 32 deletions.
3 changes: 2 additions & 1 deletion src/CommonLib/LdapConnectionPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ public async IAsyncEnumerable<LdapResult<IDirectoryObject>> Query(LdapQueryParam
queryParameters);
}

//All of our catch blocks fall through to this, so even when handling errors, we will always release the semaphore no matter what
_semaphore.Release();

//If we have a tempResult set it means we hit an error we couldn't recover from, so yield that result and then break out of the function
Expand Down Expand Up @@ -194,7 +195,7 @@ public async IAsyncEnumerable<LdapResult<IDirectoryObject>> PagedQuery(LdapQuery
LdapResult<IDirectoryObject> tempResult = null;

while (!cancellationToken.IsCancellationRequested) {
_semaphore.WaitAsync(cancellationToken);
await _semaphore.WaitAsync(cancellationToken);
SearchResponse response = null;
try {
_log.LogTrace("Sending paged ldap request - {Info}", queryParameters.GetQueryInfo());
Expand Down
105 changes: 74 additions & 31 deletions src/CommonLib/Processors/ComputerSessionProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,32 +44,54 @@ public ComputerSessionProcessor(ILdapUtils utils, string currentUserName = null,
/// <param name="computerName"></param>
/// <param name="computerSid"></param>
/// <param name="computerDomain"></param>
/// <param name="timeout"></param>
/// <returns></returns>
public async Task<SessionAPIResult> ReadUserSessions(string computerName, string computerSid,
string computerDomain) {
string computerDomain, TimeSpan timeout = default) {

if (timeout == default) {
timeout = TimeSpan.FromMinutes(2);
}
var ret = new SessionAPIResult();
NetAPIResult<IEnumerable<NetSessionEnumResults>> result;

_log.LogDebug("Running NetSessionEnum for {ObjectName}", computerName);

if (_doLocalAdminSessionEnum) {
// If we are authenticating using a local admin, we need to impersonate for this
using (new Impersonator(_localAdminUsername, ".", _localAdminPassword,
LogonType.LOGON32_LOGON_NEW_CREDENTIALS, LogonProvider.LOGON32_PROVIDER_WINNT50)) {
result = _nativeMethods.NetSessionEnum(computerName);
}
var apiTask = Task.Run(() => {
NetAPIResult<IEnumerable<NetSessionEnumResults>> result;
if (_doLocalAdminSessionEnum) {
// If we are authenticating using a local admin, we need to impersonate for this
using (new Impersonator(_localAdminUsername, ".", _localAdminPassword,
LogonType.LOGON32_LOGON_NEW_CREDENTIALS, LogonProvider.LOGON32_PROVIDER_WINNT50)) {
result = _nativeMethods.NetSessionEnum(computerName);
}

if (result.IsFailed) {
// Fall back to default User
_log.LogDebug(
"NetSessionEnum failed on {ComputerName} with local admin credentials: {Status}. Fallback to default user.",
computerName, result.Status);
if (result.IsFailed) {
// Fall back to default User
_log.LogDebug(
"NetSessionEnum failed on {ComputerName} with local admin credentials: {Status}. Fallback to default user.",
computerName, result.Status);
result = _nativeMethods.NetSessionEnum(computerName);
}
} else {
result = _nativeMethods.NetSessionEnum(computerName);
}
} else {
result = _nativeMethods.NetSessionEnum(computerName);

return result;
});

if (await Task.WhenAny(Task.Delay(timeout), apiTask) != apiTask) {
await SendComputerStatus(new CSVComputerStatus {
Status = "Timeout",
Task = "NetSessionEnum",
ComputerName = computerName
});
ret.Collected = false;
ret.FailureReason = "Timeout";
return ret;
}

var result = apiTask.Result;

if (result.IsFailed) {
await SendComputerStatus(new CSVComputerStatus {
Status = result.Status.ToString(),
Expand Down Expand Up @@ -153,33 +175,54 @@ await SendComputerStatus(new CSVComputerStatus {
/// <param name="computerName"></param>
/// <param name="computerSamAccountName"></param>
/// <param name="computerSid"></param>
/// <param name="timeout"></param>
/// <returns></returns>
public async Task<SessionAPIResult> ReadUserSessionsPrivileged(string computerName,
string computerSamAccountName, string computerSid) {
string computerSamAccountName, string computerSid, TimeSpan timeout = default) {
var ret = new SessionAPIResult();
NetAPIResult<IEnumerable<NetWkstaUserEnumResults>>
result;
if (timeout == default) {
timeout = TimeSpan.FromMinutes(2);
}

_log.LogDebug("Running NetWkstaUserEnum for {ObjectName}", computerName);

if (_doLocalAdminSessionEnum) {
// If we are authenticating using a local admin, we need to impersonate for this
using (new Impersonator(_localAdminUsername, ".", _localAdminPassword,
LogonType.LOGON32_LOGON_NEW_CREDENTIALS, LogonProvider.LOGON32_PROVIDER_WINNT50)) {
result = _nativeMethods.NetWkstaUserEnum(computerName);
}
var apiTask = Task.Run(() => {
NetAPIResult<IEnumerable<NetWkstaUserEnumResults>>
result;
if (_doLocalAdminSessionEnum) {
// If we are authenticating using a local admin, we need to impersonate for this
using (new Impersonator(_localAdminUsername, ".", _localAdminPassword,
LogonType.LOGON32_LOGON_NEW_CREDENTIALS, LogonProvider.LOGON32_PROVIDER_WINNT50)) {
result = _nativeMethods.NetWkstaUserEnum(computerName);
}

if (result.IsFailed) {
// Fall back to default User
_log.LogDebug(
"NetWkstaUserEnum failed on {ComputerName} with local admin credentials: {Status}. Fallback to default user.",
computerName, result.Status);
if (result.IsFailed) {
// Fall back to default User
_log.LogDebug(
"NetWkstaUserEnum failed on {ComputerName} with local admin credentials: {Status}. Fallback to default user.",
computerName, result.Status);
result = _nativeMethods.NetWkstaUserEnum(computerName);
}
} else {
result = _nativeMethods.NetWkstaUserEnum(computerName);
}
} else {
result = _nativeMethods.NetWkstaUserEnum(computerName);

return result;
});

if (await Task.WhenAny(Task.Delay(timeout), apiTask) != apiTask) {
await SendComputerStatus(new CSVComputerStatus {
Status = "Timeout",
Task = "NetWkstaUserEnum",
ComputerName = computerName
});
ret.Collected = false;
ret.FailureReason = "Timeout";
return ret;
}

var result = apiTask.Result;

if (result.IsFailed) {
await SendComputerStatus(new CSVComputerStatus {
Status = result.Status.ToString(),
Expand Down

0 comments on commit a9e3128

Please sign in to comment.