6
\$\begingroup\$

I've got a project I've been working on that connect to a file server and writes some data to a text file. In order to do this I added a textbox for the user to type their username and a passwordbox well for the password. In my models I have an interface called IPassword that looks like the following:

public interface IPassword
{
    SecureString Password { get; }
}

Using MVVM Light I created a RelayCommand and tied it to a button. When the button is clicked it calls the function ExportList (I've removed any code relating to my file server location):

    public void ExportList(object parameter)
    {
        var passwordContainer = parameter as IPassword;
        NetworkCredential credentials;
        string folder = String.Empty;

        if (passwordContainer != null && IsEnabled == true)
        {
            var securePassword = passwordContainer.Password;
            var password = ConvertToUnsecureString(securePassword);

            credentials = new NetworkCredential();
            credentials.UserName = Username;
            credentials.Password = password;
            credentials.Domain = "domain name";

            folder = "folder location";
            WriteToNetworkFolder(folder, credentials);
        }

        else
        {
            folder = "local folder location";
            WriteToLocalFolder(folder);
        }
    }

    private string ConvertToUnsecureString(SecureString password)
    {
        if (password == null)
        {
            return String.Empty;
        }

        IntPtr unmanagedString = IntPtr.Zero;
        try
        {
            unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(password);
            return Marshal.PtrToStringUni(unmanagedString);
        }

        finally
        {
            Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
        }
    }

    private void WriteToNetworkFolder(string folder, NetworkCredential credentials)
    {
        // Open the connection to the server
        using (new NetworkConnection(folder, credentials))
        {
            foreach (string location in LocationsPicked)
            {
                string fileName = folder + "\\" + location + ".txt";

                // Write out the lines to each text file
                try
                {
                    using (StreamWriter writer = new StreamWriter(fileName, true))
                    {
                        for (int i = 0; i < address.PhysicalAddresses.Count; i++)
                        {
                            writer.WriteLine(address.PhysicalAddresses[i]);
                        }
                    }
                }

                catch (IOException ioe)
                {
                    Console.WriteLine("The file was not written.");
                    Console.WriteLine(ioe.Message);
                    Console.WriteLine(ioe.StackTrace);
                }
            }

            UpdateStatusBar("Success! Your MAC address(es) were successfully exported!");
        }
    }

The main reason I did it this way was because you cannot use databinding to get the password from a passwordbox due to security reasons. Is this the best way to handle this situation? If not, then how would you recommend getting the password?

\$\endgroup\$
9
  • 1
    \$\begingroup\$ how would you recommend getting the password? Don't get the password! If you can get an actual plain text password to validate against, you've done something wrong. \$\endgroup\$ – Mathieu Guindon Mar 30 '15 at 16:28
  • 1
    \$\begingroup\$ Unless you know of a way to login to a file server without a user's credentials I don't know what else to do. \$\endgroup\$ – pallasmedia Mar 30 '15 at 16:39
  • \$\begingroup\$ Is the file server on Active Directory? \$\endgroup\$ – Mathieu Guindon Mar 30 '15 at 16:42
  • 1
    \$\begingroup\$ Yes, it also happens to be a domain controller. \$\endgroup\$ – pallasmedia Mar 30 '15 at 16:43
  • 1
    \$\begingroup\$ Well we still have some computers on our network that have not yet been joined to the domain. If the program was run from one of these computer's wouldn't Windows authentication fail? \$\endgroup\$ – pallasmedia Mar 30 '15 at 18:08
6
\$\begingroup\$

Why don't you just use the overloaded constructor of the NetworkCredential class which takes the password as SecureString?

In this way you can remove the ConvertToUnsecureString() method at all and you don't have to read the decrypted value of the password.


It is always recommended to use System.IO.Path.Combine() instead of adding up the path by using string concatenation. In this way you will be safe regarding illegal characters in the path, missing \ etc.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.