'Run As...' doesn't correctly create user environment - c#

My C# application crashes under some circumstances when run with a non-admin user.
I'm experiencing a problem with Windows Server 2003 and I'm trying to find more information about it. It may be a problem on other Windows OS's.
It seems that if I create a non-admin user, and then run my application under this user with the 'Run as...' command, the users environment doesn't get set up correctly, and the TEMP environment variable points at C:\Windows\Temp instead of the users having their own Temp folder in the Documents and Settings profile. The user doesn't have permissions to this folder, so the application crashes with the .Net JIT compiler tries to write/read to this folder.
If I log on as this user, the situation is still wrong. I don't get the Environment being prepared thingy you normally get when logging on a new user, and my app still won't run without crashing during startup. Infact I've realized the user can't run calc.exe or other programs in the Windows folder. It appears that their environment is permanently messed up and I guess the only way forward is to delete their profile.
If I create a non-admin user, and log on as them before doing a 'Run as..', they're environment gets set up ok, and my application works.
I can't find any information on this problem or notes on whether Microsoft acknowledge it. Have you experienced this, or do you know where I can look to find more about it?

Consider using runas with a profile for the user if you are not.
C:\temp>runas RUNAS USAGE:
RUNAS [ [/noprofile | /profile] [/env] [/netonly] ]
/user: program
RUNAS [ [/noprofile | /profile] [/env] [/netonly] ]
/smartcard [/user:] program
/noprofile specifies that
the user's profile should not be
loaded.
This causes the application to load more quickly, but
can cause some applications to malfunction.
/profile specifies that the
user's profile should be loaded.
This is the default. /env to use
current environment instead of user's.
/netonly use if the
credentials specified are for remote
access only. /savecred to use credentials
previously saved by the user.
This option is not available on Windows XP Home
Edition
and will be ignored. /smartcard use if
the credentials are to be supplied
from a
smartcard. /user should be
in form USER#DOMAIN or DOMAIN\USER
program command line for EXE.
See below for examples
Examples:
runas /noprofile /user:mymachine\administrator cmd
runas /profile /env /user:mydomain\admin "mmc %windir%\system32\dsa.msc"
runas /env /user:user#domain.microsoft.com "notepad \"my file.txt\""
NOTE: Enter user's password only when
prompted. NOTE: USER#DOMAIN is not
compatible with /netonly. NOTE:
/profile is not compatible with
/netonly.

Related

TF.exe and TfSecurity.exe authentication on AzureDevOps

I have a piece of legacy c# code (console application) that runs as a nightly batch and fires off TF.exe and TFSSecurity.exe commands at AzureDevOps.
The commands are built by the c# code and then executed by means of launching PowerShell and executing them.
All have worked fine until now, but lately, it started failing for tf30063 authentication errors.
TF30063: You are not authorized to access https://dev.azure.com/
As part of my troubleshooting I have picked a few of these commands that are being built and executed them in an interactive PowerShell session.
tf permission /recursive $/<tfs_project_name>/ /collection:https://dev.azure.com/<organization_name>/
TFSSecurity /imx adm: /collection:https://dev.azure.com/<organization_name>/
It produces the same result - TF30063: You are not authorized to access https://dev.azure.com/.
The logged-on user (where the commands are run) is able to access this AzureDevOps URL via a browser.
Digging a bit deeper I ran the command: tf settings connections help which returned the following output:
Server Url : https://<organization_name>.visualstudio.com/
User :
I was actually expecting the passed URL here: https://dev.azure.com/
Not sure how this URL got there, or how to get it out - but, be that as it may, the empty user field arouses some suspicion.
I am really trying to figure out what the authentication flow/procedure is when executing these commands (TF and TFSSecurity) in Powershell.
I have been prompted for authentication by an AzureDevOps dialog once, but where do these provided credentials stored? And for how long?
I have been snooping around the Windows credentials in the Credential Manager, here I found some bits and pieces - but nothing conclusive.
Question:
Does anybody perhaps know how these 2 applications (tf.exe and TfSecurity.exe) handles authentication and storing of credentials?
System specs:
OS: Windows Server 2016
Powershell Version: 5.1.14393.3053
Location (version) of the tf.exe and TfSecurity.exe
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\
Team Explorer>
The cached credentials that tf.exe referenced might get corrupted. We donot know what caused this issue, nor can we give a certain method to fix this. You have to try below possible solutions to narrow down the fix.
1,
Using the browser from within your Visual Studio, View->Other Windows->Web Browser and navigate to the https://dev.azure.com/. Then check if it is logged in the wrong account, log out and relog in if wrong account is logged in.
2,
Running the following command from the Developer Command Prompt for VS:
tf workspaces /collection:https://dev.azure.com/<organization_name>
3,
Go to Team Explorer > Manage Connections (Little Plug next to Home button) > Right Clicked on Project > Connect. Then reenter in your credentials.
4, To clear all the caches
Close all Visual Studio instances, delete %LOCALAPPDATA%.IdentityService as you did.
Clear TFS caches %LOCALAPPDATA%\Microsoft\Team Foundation\7.0\Cache
Clear all the browser caches especially for the stored password
5, Run Visual Studio as another user:
cd C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE
runas /netonly /user: devenv.exe
Enter the user possword, then Team Explorer > Manage Connections
If none of the obove method fixes this issue. Please check here and here for more possible solutions.
You can also report a problem to Micrsoft Develop community(Report a problem > Azure Devops) if above issue persist.
For Server Url : https://.visualstudio.com/. It is the old version dev.azure.com domain name. The official document says it can be used as usual.
Update:
TF30063 error for TFSSecurity
The cached credentials for TFSSecurity is stored in the registry. You can delete it.
HKEY_CURRENT_USER\Software\Microsoft\VSCommon\14.0\ClientServices\TokenStorage\VisualStudio\VssApp
After you deleted the cached credentials in above registry. It will prompt you to re-enter the credential when you run tfssecurity.exe command again.

Remote monitor directory via FileSystemWatcher [duplicate]

Suppose some Windows service uses code that wants mapped network drives and no UNC paths. How can I make the drive mapping available to the service's session when the service is started? Logging in as the service user and creating a persistent mapping will not establish the mapping in the context of the actual service.
Use this at your own risk. (I have tested it on XP and Server 2008 x64 R2)
For this hack you will need SysinternalsSuite by Mark Russinovich:
Step one:
Open an elevated cmd.exe prompt (Run as administrator)
Step two:
Elevate again to root using PSExec.exe:
Navigate to the folder containing SysinternalsSuite and execute the following command
psexec -i -s cmd.exe
you are now inside of a prompt that is nt authority\system and you can prove this by typing whoami. The -i is needed because drive mappings need to interact with the user
Step Three:
Create the persistent mapped drive as the SYSTEM account with the following command
net use z: \\servername\sharedfolder /persistent:yes
It's that easy!
WARNING: You can only remove this mapping the same way you created it, from the SYSTEM account. If you need to remove it, follow steps 1 and 2 but change the command on step 3 to net use z: /delete.
NOTE: The newly created mapped drive will now appear for ALL users of this system but they will see it displayed as "Disconnected Network Drive (Z:)". Do not let the name fool you. It may claim to be disconnected but it will work for everyone. That's how you can tell this hack is not supported by M$.
I found a solution that is similar to the one with psexec but works without additional tools and survives a reboot.
Just add a sheduled task, insert "system" in the "run as" field and point the task to a batch file with the simple command
net use z: \servername\sharedfolder /persistent:yes
Then select "run at system startup" (or similar, I do not have an English version) and you are done.
You'll either need to modify the service, or wrap it inside a helper process: apart from session/drive access issues, persistent drive mappings are only restored on an interactive logon, which services typically don't perform.
The helper process approach can be pretty simple: just create a new service that maps the drive and starts the 'real' service. The only things that are not entirely trivial about this are:
The helper service will need to pass on all appropriate SCM commands (start/stop, etc.) to the real service. If the real service accepts custom SCM commands, remember to pass those on as well (I don't expect a service that considers UNC paths exotic to use such commands, though...)
Things may get a bit tricky credential-wise. If the real service runs under a normal user account, you can run the helper service under that account as well, and all should be OK as long as the account has appropriate access to the network share. If the real service will only work when run as LOCALSYSTEM or somesuch, things get more interesting, as it either won't be able to 'see' the network drive at all, or require some credential juggling to get things to work.
A better way would be to use a symbolic link using mklink.exe. You can just create a link in the file system that any app can use. See http://en.wikipedia.org/wiki/NTFS_symbolic_link.
There is a good answer here:
https://superuser.com/a/651015/299678
I.e. You can use a symbolic link, e.g.
mklink /D C:\myLink \\127.0.0.1\c$
You could us the 'net use' command:
var p = System.Diagnostics.Process.Start("net.exe", "use K: \\\\Server\\path");
var isCompleted = p.WaitForExit(5000);
If that does not work in a service, try the Winapi and PInvoke WNetAddConnection2
Edit: Obviously I misunderstood you - you can not change the sourcecode of the service, right? In that case I would follow the suggestion by mdb, but with a little twist: Create your own service (lets call it mapping service) that maps the drive and add this mapping service to the dependencies for the first (the actual working) service. That way the working service will not start before the mapping service has started (and mapped the drive).
ForcePush,
NOTE: The newly created mapped drive will now appear for ALL users of this system but they will see it displayed as "Disconnected Network Drive (Z:)". Do not let the name fool you. It may claim to be disconnected but it will work for everyone. That's how you can tell this hack is not supported by M$...
It all depends on the share permissions. If you have Everyone in the share permissions, this mapped drive will be accessible by other users. But if you have only some particular user whose credentials you used in your batch script and this batch script was added to the Startup scripts, only System account will have access to that share not even Administrator.
So if you use, for example, a scheduled ntbackuo job, System account must be used in 'Run as'.
If your service's 'Log on as: Local System account' it should work.
What I did, I didn't map any drive letter in my startup script, just used net use \\\server\share ... and used UNC path in my scheduled jobs. Added a logon script (or just add a batch file to the startup folder) with the mapping to the same share with some drive letter: net use Z: \\\... with the same credentials. Now the logged user can see and access that mapped drive. There are 2 connections to the same share. In this case the user doesn't see that annoying "Disconnected network drive ...". But if you really need access to that share by the drive letter not just UNC, map that share with the different drive letters, e.g. Y for System and Z for users.
Found a way to grant Windows Service access to Network Drive.
Take Windows Server 2012 with NFS Disk for example:
Step 1: Write a Batch File to Mount.
Write a batch file, ex: C:\mount_nfs.bat
echo %time% >> c:\mount_nfs_log.txt
net use Z: \\{your ip}\{netdisk folder}\ >> C:\mount_nfs_log.txt 2>&1
Step 2: Mount Disk as NT AUTHORITY/SYSTEM.
Open "Task Scheduler", create a new task:
Run as "SYSTEM", at "System Startup".
Create action: Run "C:\mount_nfs.bat".
After these two simple steps, my Windows ActiveMQ Service run under "Local System" priviledge, perform perfectly without login.
The reason why you are able to access the drive in when you normally run the executable from command prompt is that when u are executing it as normal exe you are running that application in the User account from which you have logged on . And that user has the privileges to access the network. But , when you install the executable as a service , by default if you see in the task manage it runs under 'SYSTEM' account . And you might be knowing that the 'SYSTEM' doesn't have rights to access network resources.
There can be two solutions to this problem.
To map the drive as persistent as already pointed above.
There is one more approach that can be followed. If you open the service manager by typing in the 'services.msc'you can go to your service and in the properties of your service there is a logOn tab where you can specify the account as any other account than 'System' you can either start service from your own logged on user account or through 'Network Service'. When you do this .. the service can access any network component and drive even if they are not persistent also.
To achieve this programmatically you can look into 'CreateService' function at
http://msdn.microsoft.com/en-us/library/ms682450(v=vs.85).aspx and can set the parameter 'lpServiceStartName ' to 'NT AUTHORITY\NetworkService'. This will start your service under 'Network Service' account and then you are done.
You can also try by making the service as interactive by specifying SERVICE_INTERACTIVE_PROCESS in the servicetype parameter flag of your CreateService() function but this will be limited only till XP as Vista and 7 donot support this feature.
Hope the solutions help you.. Let me know if this worked for you .
I find a very simple method: using command "New-SmbGlobalMapping" of powershell, which will mount drive globally:
$User = "usernmae"
$PWord = ConvertTo-SecureString -String "password" -AsPlainText -Force
$creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $PWord
New-SmbGlobalMapping -RemotePath \\192.168.88.11\shares -Credential $creds -LocalPath S:
You wan't to either change the user that the Service runs under from "System" or find a sneaky way to run your mapping as System.
The funny thing is that this is possible by using the "at" command, simply schedule your drive mapping one minute into the future and it will be run under the System account making the drive visible to your service.
I can't comment yet (working on reputation) but created an account just to answer #Tech Jerk #spankmaster79 (nice name lol) and #NMC issues they reported in reply to the "I found a solution that is similar to the one with psexec but works without additional tools and survives a reboot." post #Larry had made.
The solution to this is to just browse to that folder from within the logged in account, ie:
\\servername\share
and let it prompt to login, and enter the same credentials you used for the UNC in psexec. After that it starts working. In my case, I think this is because the server with the service isn't a member of the same domain as the server I'm mapping to. I'm thinking if the UNC and the scheduled task both refer to the IP instead of hostname
\\123.456.789.012\share
it may avoid the problem altogether.
If I ever get enough rep points on here i'll add this as a reply instead.
Instead of relying on a persistent drive, you could set the script to map/unmap the drive each time you use it:
net use Q: \\share.domain.com\share
forfiles /p Q:\myfolder /s /m *.txt /d -0 /c "cmd /c del #path"
net use Q: /delete
This works for me.

Does TFS API require Visual Studio?

I am trying to check in, check out, GetLatest, etc. with the TFS API using C#.
For the development PC and an Admin user this works flawlessly.
however, on a dedicated maschine without VS 2010 installed and the TFS user being a non-Admin this does nto work.
I get the following error:
*
Access to the registry key
'HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0' is denied.
2012-10-08 14:58:30 [...] error : at
Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str)
at Microsoft.Win32.RegistryKey.CreateSubKey(String subkey,
RegistryKeyPermissionCheck permissionCheck, RegistrySecurity
registrySecurity) at
Microsoft.TeamFoundation.Client.UIHost.get_UserRegistryRoot() at
Microsoft.TeamFoundation.VersionControl.Client.Workstation.get_GetLatestOnCheckout()
*
I wonder if this has to do with Administrator rights?
The TFS "user" is actually a website running under that under account, so it is and is not supposed to be an Admin.
I tried running a test console app with my own credentials on the same maschine, and it works. So this is a credentials.
Can anyone help?
Is it enough to make the website user account an Admin?
And: what does it want to access the registry when creating the local workspace?
We've seen this kind of error when you are running a website under the application pool identity but the application pool identity is set to not load the user profile (and therefore has no HKCU registry access).
In IIS, under the advanced settings, set "Load User Profile"=True
See http://geekswithblogs.net/ProjectLawson/archive/2009/05/05/iis-system.web.aspnethostingpermission-exception-on-windows-7-rc.aspx
.. for more info.

Automatically accessing Truecrypt/Keepass etc. using Windows 7 password

I basically want to automatically mount a (non-system) Truecrypt volume or start Keypass just protected with a single (secure) password, the one windows 7 use for default authentification.
I'm using C#.
Is there anyway to get this password when already being logged in?
Or anyway to get this password while I'm actually typing it during the login process.
For 1. I couldn't find anything (the password is not stored anywhere, just a hash of the password is stored)
For 2. I already tryed some things. I got a program to execute before a user logs on using
GPEDIT.MSC Computer Configuration -> Windows Settings -> Scripts -> StartUp.
Then I tryed to get the password using global key hooks (tryed GetAsyncKeyState and SetWindowsHookEx). Both work well when I try to capture keys when I'm already logged in, but not during the login process.
But I found a keylogging software (Elite Keylogger) which is actually able to get the password that way (when logging in). (I tryed the trial version in VMWare). The other things if tryed in VM Ware and also on a real machine.
Thank you for any help or tips.
I'm doing something similar with batch scripting in order to automatically mount a Truecrypt (or Veracrypt if you prefer) volume upon Windows login with Windows 10. I use a KeePass file setup to use Windows Authentication to securely house the encrypted volume password.
Here's the process:
1) Create your truecrypt or veracrypt non-system volume
2) Create a KeyPass file to hold an entry containing the password to the encrypted volume. Setup the KeyPass file to use windows authentication under the login you will use when you want the drive to automatically mount.
3) Use a batch script like the one below to open the encrypted volume. By housing the password in the KeyPass file with windows authentication you prevent exposing the password in plain-text in the batch file. You'll need to modify this script to your specific system.
#ECHO Mounting Secure Drive (S:)
#ECHO OFF
SETLOCAL EnableDelayedExpansion
SET x=0
FOR /F "usebackq" %%F IN (`"C:\Program Files (x86)\KeePass Password Safe 2\KPScript.exe" -c:GetEntryString C:\<LocationOfYourKeePassFile>\<keepassfilename>.kdbx -useraccount -ref-Title:<entrytitle> -Field:Password`) DO (
SET Pass!x!=%%F
set /a x+=1
)
"C:\Program Files\TrueCrypt\truecrypt" /v \Device\Harddisk0\Partition4 /ls /s /q /p %Pass0% /b /h n /w
4) Lastly, set up a windows Task Scheduler to run the batch upon windows login. Trigger should be "at log on" for the target user account. Action should be "Start a Program" with the target the full path to the batch script
Another feature I like about this approach is that I can save the encrypted file volume password elsewhere incase the windows account is corrupted or deleted. I.e. I may lose access to the KeyPass file that is setup to use windows authentication but if I've saved the actual encrypted disk password somewhere else, I can still restore access to the encrypted volume.
There is a way of unlocking a KeePass database with its master password automatically after the Windows log on. You can use the same database on other computer, because it will not be bound to your Windows user account. See this Super User answer for details.
You change your KeePass database to use your Windows account as the master key, then install the TrueCrypt plugin for KeePass. You then have an entry in KeePass that contain the password for the TrueCrypt mount also registered with the TrueCrypt plugin.
With that in place, after you've logged in, open KeePass and select the entry and click Ctrl + T and you have the volume mounted in TrueCrypt.

Write Access to Program Files folder

my application include a self-updater executable that is used to update the application.
One of the first steps the updater is performing is to check that it does have write permission to the application folder
IPermission perm = new FileIOPermission(FileIOPermissionAccess.AllAccess, _localApplicationCodebase);
if (!SecurityManager.IsGranted(perm))
{
OnProgressChanged("Security Permission Not Granted \n The updater does not have read/write access to the application's files (" +
_localApplicationCodebase + ")",MessageTypes.Error);
return false;
}
OnProgressChanged("Updater have read/write access to local application files at " + _localApplicationCodebase);
return true;
When executing under Win7/Vista, this code pass (meaning that according to CAS, the code does have write access), however when I try to write files, I got an Access Denied (and I confirmed that the files are NOT in use)
I understand that Vista/Win7 UAC is preventing users from writing files in the program files folders. However, what I don't understand is why the permission is granted if in reality it is not
Regards,
Eric Girard
PS : If I run the same code using 'Run As Administrator', it works fine
The important thing to know about UAC is that by default, no code runs with Administrator privileges and thus cannot write to the Program Files directory. Even if you are logged in as an administrator, the apps are launched with standard user privliges.
There are two ways around this. You can have the user start the app with the Run As Administrator menu item. But this relies on the user to remember something. The better was is to embed a manifest into your executable that requests administrator privileges. In the manifest, set requestedExecutionLevel to requireAdministrator. This will cause UAC to prompt the user for admin credentials as soon as the app starts.
As Daniel said, the best solution is to put the updating functionality in a separate application. Your primary app will have an manifest that sets the requestedExecutionLevel to "asInvoker" and your updater app with request "requireAdministrator". Your primary app can run with standard privileges. But when the update needs to happen, use Process.Start to launch the updater application that requires the user to enter the admin credentials.
The best way to write an auto updater is to have a secondary application. The first program calls the second with elevated privileges, prompting UAC. Then the second application can install the patches.
I'm not sure if this is what you're trying to do, but I've found this post helpful. The included code let's you detect if you're app is running on Vista, if UAC is enabled and if user is elevated.
http://www.itwriting.com/blog/198-c-code-to-detect-uac-elevation-on-vista.html
then restart your app with runas to let user elevate permissions
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.Verb = "runas";
processInfo.FileName = Application.ExecutablePath;
Process.Start(processInfo);

Categories