Local Service User Logged into Windows - windows-vista

I created a Windows Service that Tracks which App Server a user is actually connected to through a load balancer.
It retrieves the user that is logged into windows on that machine, then cross references the Active Directory (AD) account to return the first name, last name and E-mail (for notification through the website created for this project)
There is one system on the Network where users only remote into the system, the Vista System, for some reason it is returning with Values that say "LOCAL SERVICE" is Logged into that machine, it's weird and the Security Guys say that it is impossible for the "LOCAL SERVICE" account to be logged into Windows.
Here is how I get the user that is logged into Windows
ManagementScope ms = new ManagementScope("\\\\.\\root\\cimv2");
ObjectQuery query = new ObjectQuery("select * from win32_computersystem");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(ms, query);
foreach (ManagementObject mo in searcher.Get())
{
_username = mo["username"].ToString();
}
// remove the domain part from the username
string[] usernameParts = _username.Split('\\');
_username = usernameParts[usernameParts.Length - 1];
is this an Edge Case that I can fix, or is the user actually "logged in" to this machine
Is there multiple users logged into this machine and Vista lists "LOCAL SERVICE" as one of them?
Cross Post on CodeReview

Related

Get AzureAD email address from username using Windows API?

I am using
WTSEnumerateSessionsEx(WTS_CURRENT_SERVER_HANDLE, &level, 0, &pSessionInfo, &count);
to get session information. It will tell me all logged in users. If I use it on Windows 11 with another user logged in,
WTS User: DESKTOP-VVVVVVV\joew, session id: 1, state: 0, session name: Console
WTS User: AzureAD\JoeWillcoxso_garbage, session id: 17, state: 4
From the state, joew is the active user and JoeWillcoxso_garbage. It's not exactly that, but I'm protecting it...you get the idea.
The session info will give me the domain and username. When I login to Windows for an AzureAD with a non-standard credential provider, I use my AzureAD email address and the CP is smart enough to use AzureAD as the domain name. But, when the machine was joined to AzureAD, it created a local account for the email address as JoeWillcoxso_garbage. ( I write "created a local account", but in PowerShell if I do get-localuser *, that user does not show up in the list.)
I can use LsaEnumerateLogonSessions() and LsaGetLogonSessionData() to get session data from the local security authority. I can match things between the two calls (LsaGetLogonSessionData and WTSEnumerateSessionsEx) using session id and username. However, there is no way to get an email address. I can get a PSID in the session data, not sure if there is a way to turn that into an email address. On my local machine, I'm not attached to an AD. Just running as WORKGROUP.
For an AzureAD user, calling NetUserGetInfo() always fails for the AAD user even when running elevated. I haven't yet tried as NT_AUTHORITY account...
I'm looking for an API or maybe some way to query WMI to turn the AzureAD\JoeWillcoxso_garbage user name into joe#someaad.onmicrosoft.com email address. Or, maybe need a web API to hit login.windows.net. There are places in the registry where I can find the email address, but I don't think they are guaranteed to always be there.
Since a user may be logged in already (and on Windows 10/11 with fast switching), sometimes an unlock is not CPUS_UNLOCK_WORKSTATION but CPUS_LOGON. With fast switching, if I lock, come back 10 minutes later, and do an unlock, it's not an unlock but a logon (CPUS_LOGON) although it acts just like an unlock used to do.
For instance, at HKEY_USERS\THE_SID_OF_THE USER\Software\Microsoft\Office\Teams, HomeUserUpn has the email address. I can get the SID of the logged on users...so I could possible get the email to match up... but, that's assuming that key is there. I want something more bullet proof.
• You can surely get the email address from the UPN for the signed in user through the below powershell commands very easily as you must have remote script execution rights over the systems in your network.
a) Whoami /upn --> Displays the full email address of the logged in user
b) "$env:USERNAME#$env:USERDNSDOMAIN" --> Displays the full email address along with the DNS zone in which its entry is mapped to
c) $msAccountName = ([adsisearcher]"(samaccountname=$env:USERNAME)").FindOne().Properties.mail
$msAccountName --> Displays the email address from the online O365/Azure AD account
Thus, accordingly as per the above powershell commands, you can get the email address of the logged in session user for Azure AD. Also, if you want to use the WTS query function for this purpose, kindly refer to the below link for more details as it aptly describes the usage of WTS query commands for the said purpose: -
https://www.idrix.fr/Root/Samples/upn.cpp
I wanted something to use from Win32, hence the tag. What I did find is that from a process running as NT_System account, I could iterate all the LSA sessions.
I could use LSAEnumerateLogonSessions() to get a list of all the sessions.
Once I had the sessions, for each session I could call LsaGetLogonSessionData() which would return a PSECURITY_LOGON_SESSION_DATA which importantly returns session ID, logon domain, logon name, and SID of the user. Looking at the logon domain, I could know if it was AzureAD because it would literally be AzureAD. Knowing it was AzureAD, I could then use the SID and do a registry lookup at key (not entire function):
CString s;
s.Format(L"SOFTWARE\\Microsoft\\IdentityStore\\Cache\\%s\\IdentityCache\\%s", lpwzSid, lpwzSid);
ATL::CRegKey regKey;
if (ERROR_SUCCESS == regKey.Open(HKEY_LOCAL_MACHINE, s, KEY_READ))
{
WCHAR szUserName[MAX_PATH] = { 0 };
ULONG ulChars = MAX_PATH;
if (ERROR_SUCCESS == regKey.QueryStringValue(L"UserName", szUserName, &ulChars) && ulChars > 0)
{
return CString(szUserName);
}
}
That almost works except for one little nit... sometimes the AzureAD user has logged out but still has an open LSA session. I have no idea how this happens, but I have observed it on Windows 11. IDK if this is for all AzureAD users, but I have noticed it can be the case for the account used to join the AzureAD domain. So, in that case, it is necessary to backcheck and use WTSEnumerateSessionsEx() and verify that there really is an open session.

Local user account created with Powershell is NOT shown in settings "Family & Other people"

I am working on Windows 10 Assigned Access for Desktop for version 1607.
Mission: I need to get Assigned Access to work with Powershell.
Steps done:
I create a new LocalUser account with New-LocalUser and I enable the account with Enable-LocalUser. To check if the account is added, I run Get-LocalUser and see that the account is created (see attachment).
Issue:
To double check I go to the PC settings for Accounts-Family & other people, but I cannot see the new local user account "KioskTest".
I have restarted the computer but the account is not added to "Family & Other people".
I have spent some time on this and I would really appreciate your help, How can I make sure that the added Local user "KioskTest" is shown in the PC Accounts settings-Family & other people, when using Powershell?
I can Set-AssignedAccess, when I do Get-AssignedAccess I can see that it is there. Trouble is, I cannot login to the local user account because I cannot find the account in the settings for the PC.
It's like powershell has "hidden" the local user account from my client computer!!!
ADDED information + updated images:
After some trial and error I found out the following:
Using NET USER username password/ADD --works perfectly! I can find the user account and login as a customer would. The account is part of the LocalGroupMember
The local user account created with New-LocalUser with Powershell does NOT appear in the PC account settings BUT if you click on set assigned access in the Family & other people the system finds the local user account (see attachment). However you cannot login to the account as it seemingly does not have a group membership! Not great for testing :(
Thanks for taking the time,
Karina
See attachment:
Powershell Get-AssignedAccess
PC Account settings Family & other people
In my case it was a group membership issue. I have created some users with powershell new-localuser, but they did not show up in any GUI and I was unable to log on. The users were only visible in powershell with get-localuser and lusmgr. In settings, control panel 'user accounts' and login screen they did not show up.
I just had to add the new users to the local 'users' group. Once this was done, the new users were visible in all settings and available for login.
I was unaware of that local security policy (local policy/user rights assignment/allow log on locally) restricting login to 'Guest,Administrators,Users,Backup Operators'.
Either add the users to one of these groups or add them to the local security policy.
This isn't really a PowerShell issue and might be better suited for SuperUser. But I would guess that this is an issue with group membership. Unfortunately get-localuser doesn't give membership. So something like this would be the PowerShell way to check which user objects belong to which local groups.
Get-Localgroup | % { "`n$($_.name)`n"; get-localgroupmember $_}
Then check through which groups other user objects are a member of and add the KioskTest account to that group using this:
Add-LocalGroupMember -Group "ExampleGroup" -Member "KioskTest"
To validate user is created or not, the below simple command helps. You may try it.
In case user is created you will get below output
Command- net user TestUser2
Output-
User name TestUser2
When user is not present
Command- net user TestUser
output-
The user name could not be found.
I had the same issue. The problem was that when specifying the group I didn´t take into account that before the name of the group needs to go domain or in my case, name of the virtual machine. Therefore the command will look like this:
... -Group "DomainName\ExampleGroup" ...
You can check the existing groups on your machine by typing lusrmgr in Window´s run window.

How to check if user is a Domain User or Local User?

I want to be able to check if the user running the current thread is:
a Domain User
a Local User of the machine
There are some cavaets:
i do not know (or care) if the machine is domain joined
because the domain of the logged in user could be from a different from the machine domain
and because the domain of the user that the process is running as could from the logged in user or machine domains
and because the domain of the user that the thread is running as could be from the process, logged in or machine domains
In other words, i want:
public static Boolean IsLocalUser()
{
//code here
}
Research Effort
What follows is extraneous bonus information. It adds nothing to the question, but is here solely to make the question longer.
Check if machine is domain joined using NetGetJoinInformation
I can use NetGetJoinInformation to check if the local machine is joined to a domain:
NetGetJoinInformation(null, ref domain, ref joinStatus);
Returns:
NetSetupUnknownStatus: The status is unknown.
NetSetupUnjoined: The computer is not joined.
NetSetupWorkgroupName: The computer is joined to a workgroup.
domain contains name of workgroup (e.g. WORKGROUP)
NetSetupDomainName: The computer is joined to a domain.
domain contains the legacy NetBIOS name of the domain (e.g. STACKOVERFLOW)
Check if machine is domain joined using DsRoleGetPrimaryDomainInformation
I can use DsRoleGetPrimaryDomainInformation to check if the local machine is joined to a domain:
DsRoleGetPrimaryDomainInformation(null,
DsRolePrimaryDomainInfoBasic,
DSROLE_PRIMARY_DOMAIN_INFO_BASIC);
Returns a DSROLE_PRIMARY_DOMAIN_INFO_BASIC structure:
MachineRole
DsRole_RoleStandaloneWorkstation: the machine is not domain joined
DsRole_RoleStandaloneServer: the machine is not domain joined
DsRole_RoleMemberWorkstation: the machine is domain joined
DsRole_RoleMemberServer: the machine is domain joined
DsRole_RoleBackupDomainController: the machine is domain joined
DsRole_RolePrimaryDomainController: the machine is domain joined
DomainNameDns: returns the DNS Domain name (e.g. stackoverflow.com) (optional)
DomainNameFlat: returns the legacy NetBIOS domain name (e.g. STACKOVERFLOW)
But, again, telling me name name of the domain that the machine is joined to doesn't help when the user is not a domain user, or the user is from a different domain
Getting the name of the current user using GetUserName
Windows does provide a GetUserName function:
GetUserName(buffer, Length(buffer));
returns the name of the user, e.g. lsimpson
Getting the name of the current user using GetUserNameEx
Windows does provide a GetUserNameEx function, that allows you to return the username in different formats:
NameUnknown: (nothing)
NameFullyQualifiedDN: CN=John Smith,OU=Stackoverflow Users,DC=stackoverflow,DC=com
NameSamCompatible: STACKOVERFLOW\jsmith
NameDisplay: John
NameUniqueId: {C1AF1DE6-363D-42A7-BB0D-9D1EDDC44B81}
NameCanonical: stackoverflow.com/Stackoverfow Users/John Smith
NameUserPrincipal: jsmith#stackoverflow.com
NameCanonicalEx: stackoverflow.com/Stackoverflow Users/John Smith
NameServicePrincipal: (nothing)
NameDnsDomain: STACKOVERFLOW.COM\jsmith
also
NameUnknown:
NameFullyQualifiedDN:
NameSamCompatible: HYDROGEN\john
NameDisplay:
NameUniqueId:
NameCanonical:
NameUserPrincipal:
NameCanonicalEx:
NameServicePrincipal:
NameDnsDomain:
KB11154: How to retrieve current user and domain name
Microsoft has a knowledge base article:
How to retrieve current user and domain names on Windows NT, Windows 2000, or Windows XP
it involves:
OpenThreadToken
OpenProcessToken (if there is no thread token)
GetTokenInformation - to get a TOKEN_USER
LookupAccountSid - to get a username and domain name from a TOKEN_USER
In the end it returns:
username: e.g. jsmith
domain: e.g. HYDROGEN, STACKOVERFLOW
Good afternoon!
I looked into some of the other solutions posted for this problem, but most of them do not take into account the caveats that you listed. Most of the relevant solutions are from the following post:
Check if user is a Domain User or Local User
Of these solutions, the following seems to be the most in line with what you proposed:
bool IsLocalUser(string accountName)
{
var domainContext = new PrincipalContext(ContextType.Machine);
return Principal.FindByIdentity(domainContext, accountName) != null;
}

Listing Windows user accounts that are visible to user at login screen

I would like to list Windows user accounts but ONLY those that are visible at login screen, one that is displayed after windows boots.
I googled and all I found boils down to this method:
http://www.mydigitallife.info/how-to-create-hidden-user-account-hide-user-account-from-welcome-screen-in-windows/
However, on my computer there are no registry keys that are mentioned in the above article - I don't want to create them, I want to check something that already exists.
I use the following query:
List<string> list = new List<string>();
SelectQuery query = new SelectQuery("Win32_UserAccount");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject obj in searcher.Get())
{
if (isInteresting(obj))
{
list.Add(obj.GetPropertyValue("Name").ToString());
}
}
With properties of objects that are returned by the above query I managed to filter some accounts (full list of those properties: http://msdn.microsoft.com/en-us/library/windows/desktop/aa394507(v=vs.85).aspx#properties), but there is still some junk from the point of view of everyday user (like accounts used for updates by driver vendors).
That registry key isn't the only reason why an account might not be displayed on the logon screen. Here are a few others:
The account is disabled
The account does not have interactive logon privilege (SeInteractiveLogonRight)
The account is explicitly denied interactive logon privilege (SeDenyInteractiveLogonRight)
Usually SeInteractiveLogonRight is granted to the Guest user, plus members of the Administrators, Users, and Backup Operators groups. Any account (other than Guest) that isn't a member of one of these groups will probably not be shown on the logon screen. (I'm not sure what happens if SeInteractiveLogonRight has been removed from one of these groups, I wouldn't be surprised if the logon screen showed the accounts anyway.)
You can use LsaEnumerateAccountRights to check whether an account has SeDenyInteractiveLogonRight applied, or LsaEnumerateAccountsWithUserRight to get a list of affected accounts. Usually individual accounts, rather than groups, are granted this right, so it is likely that the logon screen checks accounts in this way.

Using Delegates with Exchange Web Services

Has anyone used delegates with exchnage web services? I would like one user to be able to control other users' calendars in Exchange. I'm finding this problem to be a little tricky, and I'd like to see how others have been able to get it to work properly.
I'm just getting started here, but i managed to get access to Resource calendars via a delegate account.
I used the recommendations from this article about delegate account and resource accounts. (Resource accounts are tricky because they are disabled in the AD, and you have to use a delegate account to get access to them)
After setting up the delegate account on the server, I set up the ExchangeServerBinding using the credentials of the delegate account:
ExchangeServiceBinding binding = new ExchangeServiceBinding();
binding.Url = #"https://dc1.litwareinc.com/ews/exchange.asmx";
// Setup binding with username and password of the delegate account
binding.Credentials =
new NetworkCredential(delegateuserName, delegatepassword, "litwareinc.com");
(I'm using Microsofts prepared virtual server image for testing)
Then when accessing the mailbox, I set up a FindItemType request and use the smtp address of the account i want to access:
// Prepare request
var findItemRequest = new FindItemType();
// Setup the mailbox using the smtp address of the account wanted
var mailbox = new EmailAddressType {EmailAddress = mailboxId};
findItemRequest.ParentFolderIds =
new[] {new DistinguishedFolderIdType {Mailbox = mailbox}};
((DistinguishedFolderIdType) findItemRequest.ParentFolderIds[0]).Id =
DistinguishedFolderIdNameType.calendar;
findItemRequest.Traversal = ItemQueryTraversalType.Shallow;
// Add ItemResponseShapeType and Calendarview to request here ...
// The create a FindItemResponseType using the binding and the request
var response = binding.FindItem(findItemRequest);
So in short:
Setup an account with delegate access on the Exchange server, this can be done via owa or with a Exchange Shell script
Use the account with delegate access on the ExchangeServiceBinding object
Access target account using a FindItemType with the target account smtp-addres as EmailAddressType
Regards
Jesper Hauge

Resources