Recently I was trying to find answer to question "How to determine if current logged in user is part of domain or not"
On Stackoverflow I found pretty decent answers for the above which involved usage of
using System.Security.Principal;
using System.DirectoryServices.AccountManagement;
But I also see a simple solution saying
System.Environment.UserDomainName; - gives name of the current user's domain name.
System.Environment.MachineName; - gives name of the machine.
If above two are not the same means the user is part of domain returned by UserDomainName
Fair enough, also confirmed by this link from MSDN
Now the question is what if the "Domain name" and "Machine name" are identical?
or
Is it possible that a machine with the exact same name as domain name can join the domain?
If this is true, is there any possibilities to counter check this by adding something to this simple solution
I bet you the current logged on user does not have a distingished name if he or she isn't logged on to a domain. Use GetUserNameEx with the EXTENDED_NAME_FORMAT type NameFullyQualifiedDN (1).
If you get a value back then you know the current user is logged on to a domain. Though, Calling this function might block your program unexpectedly for a period of time. You probably want to call this function in a asynchronous fashion as it might atempt to connect to some Active Directory service and just eventually fail or timeout.
An yet more resilient way to accomplish this would be to look up the account SID and check whether the EqualPrefixSid can compare it with the machine. If this is the case, then you know the current account is local to the machine (i.e. not in a domain). This does not involve crossing the network and waiting for a timeout, so it's a more direct approach. Interestingly, it also implies that if the machine name is the same as the user domain, Windows would have to assume that the domain you want to logon on to is the local machine and it should therefore be almost impossible to logon to the actual domain if the machine name really is the same as the domain.
Related
I am trying to run a file watcher over some server path using windows service.
I am using my windows login credential to run the service, and am able to access this "someServerPath" from my login.
But when I do that from the FileSystemWatcher it throws:
The directory name \someServerPath is invalid" exception.
var fileWatcher = new FileSystemWatcher(GetServerPath())
{
NotifyFilter=(NotifyFilters.LastWrite|NotifyFilters.FileName),
EnableRaisingEvents=true,
IncludeSubdirectories=true
};
public static string GetServerPath()
{
return string.Format(#"\\{0}", FileServer1);
}
Can anyone please help me with this?
I have projects using the FileSystemWatcher object monitoring UNC paths without any issues.
My guess from looking at your code example may be that you are pointing the watcher at the root share of the server (//servername/) which may not be a valid file system share? I know it returns things like printers, scheduled tasks, etc. in windows explorer.
Try pointing the watcher to a share beneath the root - something like //servername/c$/ would be a good test example if you have remote administrative rights on the server.
With regards to the updated question, I agree that you probably need to specify a valid share, rather than just the remote server name.
[Update] Fixed previous question about the exception with this:
specify the name as #"\\someServerPath"
The \ is being escaped as a single \
When you prefix the string with an # symbol, it doesn't process the escape sequences.
I was just asked this question in regards to FileSystemWatcher code running as a service and the issue is permissions. I searched and found this question and answer but unfortunately none of the answers here solved the problem. Anyway, I just solved it, so I thought I would throw in the solution here for next guy who searches and find this question.
The drive was mapped as a logged in user but the service was running as LocalSystem. LocalSystem is a different account and does not have access to drives mapped by a user.
The fix is to either:
Authenticate first (I use a C# Class to establish a network connection with credentials)
Run your service as a user that has access to the share.
You can test LocalSystem authentication by using a LocalSystem command prompt, see How to open a command prompt running as Local System?
Even though this is already answered I thought I would put in my two cents worth becaus eyou can see this same error even if you supply valid paths.
You will get the same error when the process running the watcher does not have access to the remote share. This will happen if the watcher is in a service running under the System account and the share is created by a user. System does not have access to that share and wont recognize it, you will need to impersonate the user to get access to it.
although you can use a FileWatcher over the network, you will have to account for other factors, like disconnection of the network share. If your connection to the share is terminated (maintenance, lag, equipment reset, etc) you will no longer have a valid handle on the share in your filewatcher
You can't use directory watches over network shares, this is a limitation of the OS, not of .NET.
I need to know how to get the name and domain of the primary user of a computer, remotely. I define the primary user preferably as the user logged on most times, or longest time over a period. Alternatively, if this is impossible, as the user currently/last logged on.
Currently, i scan an Active Directoy for all computer objects in an OU. I then loop though them, and try to get the name of the user using WMI.
I look in Win32_ComputerSystem to see if UserName returns a value. If this is not the case, i look in Win32_LogonSession and get the username for all LogonTypes that equal 2 or 10. If this returns none, or multiple values, i discard the result and look in Win32_Process for all non-system processes and define the primary user as the user with most processes running.
There are several problems with my approach:
Win32_ComputerSystem - UserName is often null.
Win32_LogonSession often return multiple or no values. There can be only 1 primary user.
Looking in Win32_Process is kinda ridiculous, since this will only return me the user with most processes, most likely not the primary user.
If no user is currently logged on, looking in Win32_Process returns no value and none of the 3 steps might return a value.
My 3 approaches might get me the current user. Does anyone know of a way to get the primary user? Or at least a better way to get the current. Not necessarily using WMI.
Thanks
If you have administrator privileges on the remote computer and sharing access
you can use Computer Management and select to
connect to other computer and see what users and groups are on that computer.
Or you can use TS Remote Administration or Remote Desktop if the remote computer has that capability.
Use psexec.exe (www.sysinternals.com) to run commands on a remote pc:
psexec \\pc1 net user | find /i "Steve"
psexec \\pc1 c:\tool\psloggedon | find /i "Steve"
1) Find if John Black has an account on PC1.
2) Find if he is currently logged on.
Use psloggedon.exe that uis is another SysInternals tool.
Check this also: http://www.wisesoft.co.uk/scripts/vbscript_display_username_of_user_on_a_remote_computer.aspx
Also if you want to find the User Name of the currently logged user on a remote computer using the remote computer IP then Go to the command line an type nbtstat -A <IP of remote computer> This will return all of the NetBIOS names registered on the computer, one of which is the username.
I am attempting to Impersonate an administrator account from a LocalSystem Service in order to get data from administrators HKEY CURRENT USER registry - in order to impersonate I am using the codeproject code found at the following site written by Uwe Keim: Impersonator
My source code is as follows:
using (new Impersonator("user", ".", "pass"))
{
RegistryKey rk = Registry.CurrentUser.OpenSubKey("Software\\CompanyName");
string sValue = rk.GetValue("Value", "").ToString();
rk2.Close();
}
My expectation was that sValue would be from the user/pass account (as I am impersonating it) but oddly enough it is still the sValue from the LocalSystem account where my service is runnning ...
Any clues on what I am doing wrong? Any help would be much appreciated.
Thanks,
I know this is an old thread but I recently came across the same issue (albeit from a C++ Windows service) and thought I'd share my findings, because many forums have asked the same question and none have left a satisfactory answer.
Basically, I've found two ways to approach this, though this is an answer more for C applications rather than .NET (I haven't tested with pinvoke but it may work).
Solution 1:
Instead of using RegOpenKey, use RegOpenCurrentUser() to get the key handle. Apparently, the reason RegOpenKey doesn't get the impersonated user's key is because HKEY_CURRENT_USER is cached in the running thread.
Solution 2:
RegDisablePredefinedCache(). This disables the cache mentioned above and lets subsequent calls to HKEY_CURRENT_USER be of the actual impersonated user. This is the solution I went with.
Hope this helps.
Everything I've read on the subject seems to indicate that impersonation should get you access to the HKEY_CurrentUser for the impersonated account. However, it could be a quirk in the .NET Registry implementation.
This is just a hunch, and an untested one at that, but have you considered using Registry.Users instead of Registry.CurrentUser?
You'll need to find the SID for the Administrator account, but you should be able to deduce that using Regedit
By default the HKEY_CURRENT_USER handle is cached on a process wide basis. So when you impersonate a user and then access the current user hive you will be accessing the hive of the user that started the process not the user being impersonated. This is true for all Win32 processes not just .Net. If you wish to disable this caching so that all current user calls go to the correct user hive under HKEY_USERS then you must call RegDisablePredefinedCache via pInvoke.
Be warned that if the user being impersonated has not had their profile loaded then any CurrentUser requests will be forwarded to the .DEFAULT user. So you may also need to call LoadUserProfile.
Disabling the handle caching will also cause a slight slowdown in all CurrentUser requests.
I'm guessing you're going to find that you're out of luck. It can't be done.
If applications were able to impersonate an Administrator account and write values to the Registry in Windows, it would present a huge security hole. My guess is that the Registry.CurrentUser property will ALWAYS reference the user running your application...whether or not you try impersonation or not.
EDIT
Turns out that I didn't read the implementation details of the Impersonator code you were using. Your problem could be something completely different.
Does your code refer to the Registry static class prior to your impersonation code being run? If so, that would be the problem. If you look at the Registry.CurrentUser property in Reflector, you'll see that it is set by the static constructor of the Registry object. Static constructors get called when the static object is first referenced.
In your case, if you're referencing the Registry object (whether it involves CurrentUser or not) the static constructor is being called which is setting CurrentUser to your original user...not the Impersonated account.
Apologies in advance as I haven't had much experience with directories before.
I have an ASP.net application, and I have to validate its users against an Active Directory Application Mode instance running on Server 2k3. I was previously attempting a connection with DirectoryEntry and catching the COMException if the user's credentials (userPrincipalName & password) were wrong, but I had a number of problems when trying to bind as users who weren't a member of any ADAM groups (which is a requirement).
I recently found the System.DirectoryServices.AccountManagement library, which seems a lot more promising, but although it works on my local machine, I'm having some troubles when testing this in our testbed environment. Chances are I'm simply misunderstanding how to use these objects correctly, as I wasn't able to find any great documentation on the matter. Currently I am creating a PrincipalContext with a Windows username and password, then calling the AuthenticateCredentials with the user's userPrincipalName and password. Here's a very short exert of what I'm doing:
using (var serviceContext = new PrincipalContext(
ContextType.ApplicationDirectory,
serverAddress,
rootContainer,
ContextOptions.Negotiate | ContextOptions.SecureSocketLayer,
serviceAccountUsername,
serviceAccountPassword)) {
bool credentialsValid = serviceContext.ValidateCredentials(userID, password, ContextOptions.SecureSocketLayer | ContextOptions.SimpleBind)
}
If the user's credentials are valid, I then go on to perform other operations with that principal context. As I said, this works for both users with and without roles in my own environment, but not in our testbed environment. My old DirectoryEntry way of checking the user's credentials still works with the same configuration.
After a very long morning, I was able to figure out the problem!
The exception message I was receiving when calling ValidateCredentials was extremely vague. After installing Visual Studio 2008 in the test environment (which is on the other side of the country, mind you!), I was able to debug and retrieve the HRESULT of the error. After some very deep searching in to Google, I found some very vague comments about "SSL Warnings" being picked up as other exceptions, and that enabling "SCHANNEL logging" (which I'm very unfamiliar with!) might reveal some more insight. So, after switching that on in the registry and retrying the connection, I was presented with this:
The certificate received from the remote server does not contain the expected name. It is therefore not possible to determine whether we are connecting to the correct server. The server name we were expecting is ADAMServer. The SSL connection request has failed. The attached data contains the server certificate.
I found this rather strange, as the old method of connecting via SSL worked fine. In any case, my co-worker was able to spot the problem - the name on the SSL certificate that had been issued on the server was that of the DNS name ("adam2.net") and not the host name ("adamserver"). Although I'm told that's the norm, it just wasn't resolving the correct name when using PrincipalContext.
Long story short; re-issuing a certificate with the computer name and not the DNS name fixed the problem!
I am trying to run a file watcher over some server path using windows service.
I am using my windows login credential to run the service, and am able to access this "someServerPath" from my login.
But when I do that from the FileSystemWatcher it throws:
The directory name \someServerPath is invalid" exception.
var fileWatcher = new FileSystemWatcher(GetServerPath())
{
NotifyFilter=(NotifyFilters.LastWrite|NotifyFilters.FileName),
EnableRaisingEvents=true,
IncludeSubdirectories=true
};
public static string GetServerPath()
{
return string.Format(#"\\{0}", FileServer1);
}
Can anyone please help me with this?
I have projects using the FileSystemWatcher object monitoring UNC paths without any issues.
My guess from looking at your code example may be that you are pointing the watcher at the root share of the server (//servername/) which may not be a valid file system share? I know it returns things like printers, scheduled tasks, etc. in windows explorer.
Try pointing the watcher to a share beneath the root - something like //servername/c$/ would be a good test example if you have remote administrative rights on the server.
With regards to the updated question, I agree that you probably need to specify a valid share, rather than just the remote server name.
[Update] Fixed previous question about the exception with this:
specify the name as #"\\someServerPath"
The \ is being escaped as a single \
When you prefix the string with an # symbol, it doesn't process the escape sequences.
I was just asked this question in regards to FileSystemWatcher code running as a service and the issue is permissions. I searched and found this question and answer but unfortunately none of the answers here solved the problem. Anyway, I just solved it, so I thought I would throw in the solution here for next guy who searches and find this question.
The drive was mapped as a logged in user but the service was running as LocalSystem. LocalSystem is a different account and does not have access to drives mapped by a user.
The fix is to either:
Authenticate first (I use a C# Class to establish a network connection with credentials)
Run your service as a user that has access to the share.
You can test LocalSystem authentication by using a LocalSystem command prompt, see How to open a command prompt running as Local System?
Even though this is already answered I thought I would put in my two cents worth becaus eyou can see this same error even if you supply valid paths.
You will get the same error when the process running the watcher does not have access to the remote share. This will happen if the watcher is in a service running under the System account and the share is created by a user. System does not have access to that share and wont recognize it, you will need to impersonate the user to get access to it.
although you can use a FileWatcher over the network, you will have to account for other factors, like disconnection of the network share. If your connection to the share is terminated (maintenance, lag, equipment reset, etc) you will no longer have a valid handle on the share in your filewatcher
You can't use directory watches over network shares, this is a limitation of the OS, not of .NET.