Question

I know that you can run a process with a given username/password in the following way:

var processInfo = new ProcessStartInfo
{
    WorkingDirectory = workingDirectory,
    FileName = "a name",
    UserName = loggedUserName, 
    Password = "password",
    Domain = userNameDomain,
    UseShellExecute = false,
};
Process.Start(processInfo);

The problem I'm facing is that I don't want to write the actual password as a part of the code and the process won't start if I leave the Password attribute empty... How can I safely start the process without exposing the password as a hard coded string in the code?

Était-ce utile?

La solution

The ProcessStartInfo.Password is not a simple string that you can write down and assign to the property. What you need is a SecureString instance and a SecureString cannot be created passing a simple string to its constructor. Obviously the OS has no API or method that allows a non trusted program to retrieve the password of the current user (it would be the biggest security bug ever heard of).

So, in my thinking, you are left with only one option. Ask your user to type again the password and the resulting input should be transformed into a SecureString

This example is an extension method for the string class that I have seen here

using System.Security;

// ...

public static SecureString ConvertToSecureString(this string password)
{
    if (password == null)
        throw new ArgumentNullException("password");

    unsafe
    {
        fixed (char* passwordChars = password)
        {
            var securePassword = new SecureString(passwordChars, password.Length);
            securePassword.MakeReadOnly();
            return securePassword;
        }
    }
}

you could use it to transform the password typed by your user and start the process

using(frmGetPassword fgp = new frmGetPassword())
{
     if(DialogResult.OK == fgp.ShowDialog())
     {
         SecureString ss = fgp.Password.ConvertToSecureString();
         var processInfo = new ProcessStartInfo
         {
             WorkingDirectory = workingDirectory,
             FileName = "a name",
             UserName = loggedUserName, 
             Password = ss,
             Domain = userNameDomain,
             UseShellExecute = false,
         };
         Process.Start(processInfo);
     }
}

Autres conseils

I use the windows Password store to manage such passwords. Check out the http://credentialmanagement.codeplex.com/ library which wraps around the windows API. Either your Setup-Routine or Admin can add the password to the store, which can then be retrieved at runtime from the application. Only drawback is that the store is user-specific. You can't create a password which can be used across multiple users.

It's as simple as that:

        _credentials = new CredentialSet("myApp:*");
        if (_credentials.Count == 0)
        {
            //TODO: ask user for password, supply it here, or use windows UI to set password (rundll32.exe keymgr.dll, KRShowKeyMgr)
            var c = new Credential()
            {
                Target = "myApp:Production",
                Username = "SomeUser",
                Description = "Credentials for doing something...",
                PersistanceType = PersistanceType.LocalComputer,
                Type = CredentialType.DomainPassword
            };
            c.Save();
            _credentials.Add(c);
        }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top