C# EFS, Windows Encrypt Or Dycrypt Fails when Impersonated - c#

I need to write a file while impersonated as another user John (Member of administrator).
What happens:
File is written and created, then all Access Control is removed and added (Full Control).
No matter where in this process i try to Encrypt file access is denied
using FileOptions
Using File.Encrypt.
my worked around to at least encrypt was with opening another impersonation later on.
But No matter what i do, i can't Decrypt or even read the encrypted Text file.
If file is encrypted reading or decrypting fails, even though i can read or write just fine while impersonated.
In some scenarios Everything works fine, But after a system restart or logout, again fails with access denied.
For impersonation i used this answers Impersonation
using (impersonate = new ImpersonateUser(ImpersonationType.WinIdentity, Domain, User, SecurePassword))
{
System.Diagnostics.Debug.WriteLine($"Before Impersonation: {Environment.UserName}");
done = impersonate.RunImpersonated(() =>
{
System.Diagnostics.Debug.WriteLine($"After Impersonation: {Environment.UserName}");
//if (Util.IsWindowsEncrypted(ConfigFullPath)) File.Decrypt(ConfigFullPath);
var json = File.ReadAllText(ConfigFullPath);
var configFile_data = SerializationUtil.Deserialize<Config>(json);
//if (!Util.IsWindowsEncrypted(ConfigFullPath)) File.Encrypt(ConfigFullPath);
});
}
A working repository to reproduce is available here Repository containing full sample,
See CreateConfig or ReadConfig method in Config.cs
(if you were able to create and read a encrypted file, check if after
restart it is the same)
A Workaround i just found was to create a Process before doing any impersonation.
using (Process cmd = new Process())
{
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/c",
UseShellExecute = false,
UserName = user,
Password = pass,
LoadUserProfile = true
};
cmd.StartInfo = startInfo;
cmd.Start();
}

Related

Getting the output of .exe program in IIS under windows server 2012

We have our own C++ compiled OCR as .exe file that takes the image location as a parameter and return a string, and we place it in folder within our web-API 2 application folder, now we start the OCR as a process from the web-api, get the output and return it back.
everything works good in a local machine, when we deploy the API in the server, the output cannot be retrieved unless we replace the Application pool identity with the Admin in the application pool. At this stage we need to use the Application pool identity (or any other user but the admin) and still be able to retrieve the output from the process here is our code:
ProcessStartInfo info = new ProcessStartInfo
{
WorkingDirectory = enginepath,
CreateNoWindow = true,
UseShellExecute = false,
FileName = enginepath+"//"+"OCR.exe",
RedirectStandardOutput = true,
Arguments = " "+imageFilepath
};
using (Process process = Process.Start(info))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
return result;
}
}
we tried all the popular ways from giving the right permissions,loading the user profile=true, and still can't be able to retrieve the output.
*we need to be able to get the output within the web server application.

Printing a PDF from ASP .Net (c#) using Acrobat Reader

I am trying to print a PDF using ASP (C#) through Adobe Reader -the problem is it does work on my local machine but not on server. On my local it starts Adob eReader in minimized state and I can see the file present inside Printer's "See what's printing" window. But on the server I can see the process has started from Task Manager but there's no UI visible as well no file in printer's list.
I though it may be a permission issue but after trying the following steps - it still does not work.
What I have tried.
As by default it runs under DefaultAppPool user - so I created a new App pool under the admin user, it now starts the process under admin but still I can't see the UI and no output on printer.
I added permission "Allow service to interact with desktop" to IIS Admin Service following this article https://support.microsoft.com/en-us/help/555134 - but no difference.
My current code
string args = string.Format("/s /o /h /t \"{0}\" \"{1}\"", filepath, printerName);
var startInfo = new ProcessStartInfo {
FileName = Properties.Settings.Default.AdobeReaderPath,
Arguments = args,
CreateNoWindow = true,
ErrorDialog = false,
UseShellExecute = false,
Verb = "print",
WindowStyle = ProcessWindowStyle.Minimized,
RedirectStandardInput = true,
RedirectStandardOutput = true
};
var process = Process.Start(startInfo);
In the Application Pool Advanced settings, make sure you set the option
"Load User Profile" to True on the server.

Application not running from production web server

I have to run a tool from our internal website. There are few inputs that user will provide from UI and then I want to run the tool with user credential. My code works fine when I run it from my local machine, but when I deploy it to production server and try to execute it from there it does not start anything.
Here is my code, any advice will be greatly appreciated.
System.Diagnostics.ProcessStartInfo PSI = new System.Diagnostics.ProcessStartInfo(#"D:\run.bat");
PSI.UserName = "username";
PSI.Domain = "domain";
System.Security.SecureString securePwd = new System.Security.SecureString();
string password = "password";
foreach (char c in password)
{
// Append the character to the password.
securePwd.AppendChar(c);
}
PSI.Password = securePwd;
PSI.UseShellExecute = false;
process.StartInfo = PSI;
PSI.Arguments = SiteId.Text + " " + WebServiceUrl.Text + " " +LogFile.Text;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
First:
Check the identity of your application pool (advanced settings).
Switch the identity to "system" and see if the batch file runs from the web app.
If it does:
Change the identity back to network service,
Make sure your batch file has execute permissions applied for user Network Service (or whichever identity you chose)
If it doesn't:
Try opening the file with your code and appending some harmless text to the end.
If that works, you can at least rule out permissions and web-app view-ability concerns.
I want to close this thread as my problem of running an application from production server solved. But I'm facing issue to run that application using specific user name & password. It always run with whatever identity is set in apppool. So for now if I only use this line it works on app pool default identity
Process.Start("notepad");
But if I use this line of code it don't even start a notepad in that server
string password = "XXXXX";
System.Security.SecureString securePwd = new System.Security.SecureString();
foreach (char c in password)
{
// Append the character to the password.
securePwd.AppendChar(c);
}
Process.Start("notepad", "username", securePwd, "domain");
I'm going to ask a separate question on this. Thanks for all who replied.

How to write path that requires username and password?

I want to perform file copying from local HDD to a server
- to access the server it require to insert username and password,
at manual when I write the server name: \neoserver a window popup and after inserting username and password all the server's file appeared.
to perform the copying I use the command: File.copy(source path, destination path)
how can I write the server's path in a way it won't require user#pass???
You can use Process.Start to call the copy command line executable with the right credentials and parameters.
For best control, use ProcessStartInfo to supply all the information needed:
ProcessStartInfo startInfo = new ProcessStartInfo("copy");
startInfo.Arguments = "source dest";
startInfo.UserName = myUser;
startInfo.Password = myPassword;
Process.Start(startInfo);

Start Process with administrator right in C#

I have to start a command line program with System.Diagnostics.Process.Start() and run it as Administrator.
This action will also be run by a Scheduled Task every day.
I've just try to use :
Process p = new Process();
p.StartInfo.Verb = "runas";
this works fine if I'm running my program as Administrator, but when the Scheduled Task runs it, it doesn't take the 'runas' in consideration I think.
A better secure option to run a process with login and password is use the SecureString class to encrypt the password. Here a sample of code:
string pass = "yourpass";
string name ="login";
SecureString str;
ProcessStartInfo startInfo = new ProcessStartInfo();
char[] chArray = pass.ToCharArray();
fixed (char* chRef = chArray)
{
str = new SecureString(chRef, chArray.Length);
}
startInfo.Password = str;
startInfo.UserName = name;
Process.Start(startInfo);
You must allow unsafe code in your project properties.
Hope this help.
If you are using scheduled tasks, you can set the user and password for the task to run under.
Use the administrator credentials on the task and you will be fine.
With Process.Start, you need to supply the UserName and Password for the ProcessStartInfo:
Process p = new Process("pathto.exe");
p.StartInfo.UserName = "Administrator";
p.StartInfo.Password = "password";
p.Start();
Be aware that storing a password in clear text in a program is never secure as long as someone can peruse the application and see what is in it. Using SecureString to convert a stored password into a SecureString password does not make it more secure, because the clear text password would still be present.
The best way to use SecureString is to pass a single character for conversion at a time in someway that does not require having the complete unencrypted password anywhere in memory or on the hard drive. After that character is converted, the program should forget it, and then go on to the next.
This could be done I think only by passing characters through for translation as they are being typed into the console by the user.
I found it, I need to set the Scheduled Task to run the application with highest privileges in General settings.

Categories

Resources