diff options
-rw-r--r-- | LibGit2Sharp.Tests/TestHelpers/Constants.cs | 19 | ||||
-rw-r--r-- | LibGit2Sharp/LibGit2Sharp.csproj | 1 | ||||
-rw-r--r-- | LibGit2Sharp/SecureUsernamePasswordCredentials.cs | 50 |
3 files changed, 70 insertions, 0 deletions
diff --git a/LibGit2Sharp.Tests/TestHelpers/Constants.cs b/LibGit2Sharp.Tests/TestHelpers/Constants.cs index 450746ff..5a389136 100644 --- a/LibGit2Sharp.Tests/TestHelpers/Constants.cs +++ b/LibGit2Sharp.Tests/TestHelpers/Constants.cs @@ -22,6 +22,9 @@ namespace LibGit2Sharp.Tests.TestHelpers // ... return new UsernamePasswordCredentials { Username = "username", Password = "swordfish" }; // // Or: + // ... return new SecureUsernamePasswordCredentials() { Username = "username", Password = StringToSecureString("swordfish") }; + // + // Or: // public const string PrivateRepoUrl = "https://tfs.contoso.com/tfs/DefaultCollection/project/_git/project"; // ... return new DefaultCredentials(); @@ -68,5 +71,21 @@ namespace LibGit2Sharp.Tests.TestHelpers Trace.TraceInformation("Test working directory set to '{0}'", testWorkingDirectory); return testWorkingDirectory; } + + // To help with creating secure strings to test with. + private static System.Security.SecureString StringToSecureString(string str) + { + var chars = str.ToCharArray(); + + var secure = new System.Security.SecureString(); + for (var i = 0; i < chars.Length; i++) + { + secure.AppendChar(chars[i]); + } + + secure.MakeReadOnly(); + + return secure; + } } } diff --git a/LibGit2Sharp/LibGit2Sharp.csproj b/LibGit2Sharp/LibGit2Sharp.csproj index 60b35252..856d2433 100644 --- a/LibGit2Sharp/LibGit2Sharp.csproj +++ b/LibGit2Sharp/LibGit2Sharp.csproj @@ -143,6 +143,7 @@ <Compile Include="RenameDetails.cs" /> <Compile Include="RevertResult.cs" /> <Compile Include="RevertOptions.cs" /> + <Compile Include="SecureUsernamePasswordCredentials.cs" /> <Compile Include="StageOptions.cs" /> <Compile Include="StatusOptions.cs" /> <Compile Include="SimilarityOptions.cs" /> diff --git a/LibGit2Sharp/SecureUsernamePasswordCredentials.cs b/LibGit2Sharp/SecureUsernamePasswordCredentials.cs new file mode 100644 index 00000000..5e1d4931 --- /dev/null +++ b/LibGit2Sharp/SecureUsernamePasswordCredentials.cs @@ -0,0 +1,50 @@ +using System; +using LibGit2Sharp.Core; +using System.Security; +using System.Runtime.InteropServices; + +namespace LibGit2Sharp +{ + /// <summary> + /// Class that uses <see cref="SecureString"/> to hold username and password credentials for remote repository access. + /// </summary> + public sealed class SecureUsernamePasswordCredentials : Credentials + { + /// <summary> + /// Callback to acquire a credential object. + /// </summary> + /// <param name="cred">The newly created credential object.</param> + /// <returns>0 for success, < 0 to indicate an error, > 0 to indicate no credential was acquired.</returns> + protected internal override int GitCredentialHandler(out IntPtr cred) + { + if (Username == null || Password == null) + { + throw new InvalidOperationException("UsernamePasswordCredentials contains a null Username or Password."); + } + + IntPtr passwordPtr = IntPtr.Zero; + + try + { + passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(Password); + + return NativeMethods.git_cred_userpass_plaintext_new(out cred, Username, Marshal.PtrToStringUni(passwordPtr)); + } + finally + { + Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr); + } + + } + + /// <summary> + /// Username for username/password authentication (as in HTTP basic auth). + /// </summary> + public string Username { get; set; } + + /// <summary> + /// Password for username/password authentication (as in HTTP basic auth). + /// </summary> + public SecureString Password { get; set; } + } +} |