Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ bld/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*.testlog
testlog.manifest

#NUNIT
*.VisualState.xml
Expand Down
18 changes: 12 additions & 6 deletions PSCredentialManager.Api/CredentialManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public void WriteCred(NativeCredential credential)
}
}

public Credential ReadCred(string target, CredType type)
public Credential ReadCred(string target, CredType type, bool includeClearPassword, bool includeSecurePassword)
{
IntPtr nativeCredentialPointer;

Expand All @@ -31,7 +31,7 @@ public Credential ReadCred(string target, CredType type)
{
using (CriticalCredentialHandle critCred = new CriticalCredentialHandle(nativeCredentialPointer))
{
return critCred.GetCredential();
return critCred.GetCredential(includeClearPassword, includeSecurePassword);
}
}
else
Expand All @@ -57,12 +57,18 @@ public void DeleteCred(string target, CredType type)

if (!delete)
{
string message = $"DeleteCred failed with the error code {lastError}.";
throw new Exception(message);
if(lastError == 1168)
{
throw new CredentialNotFoundException($"DeleteCred failed with the error code {lastError} (credential not found).");
}
else
{
throw new Exception($"DeleteCred failed with the error code {lastError}.");
}
}
}

public IEnumerable<Credential> ReadCred()
public IEnumerable<Credential> ReadCred(bool includeClearPassword, bool includeSecurePassword)
{
int count;
int flags;
Expand All @@ -84,7 +90,7 @@ public IEnumerable<Credential> ReadCred()
if (read)
{
CriticalCredentialHandle credHandle = new CriticalCredentialHandle(pCredentials);
return credHandle.GetCredentials(count);
return credHandle.GetCredentials(count, includeClearPassword, includeSecurePassword);
}
else
{
Expand Down
16 changes: 12 additions & 4 deletions PSCredentialManager.Api/CriticalCredentialHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,20 @@ internal CriticalCredentialHandle(IntPtr preexistingHandle)
SetHandle(preexistingHandle);
}

internal Credential GetCredential()
internal Credential GetCredential(bool includeClearPassword, bool includeSecurePassword)
{
if (!IsInvalid)
{
// Get the Credential from the mem location
NativeCredential nativeCredential = (NativeCredential)Marshal.PtrToStructure(handle, typeof(NativeCredential));

// Create a managed Credential type and fill it with data from the native counterpart.
Credential credential = nativeCredential.ToCredential();
Credential credential = nativeCredential.ToCredential(includeClearPassword, includeSecurePassword);

nativeCredential = new NativeCredential();

GC.Collect();

return credential;
}
else
Expand All @@ -46,7 +51,7 @@ protected override bool ReleaseHandle()
return false;
}

public Credential[] GetCredentials(int count)
public Credential[] GetCredentials(int count, bool includeClearPassword, bool includeSecurePassword)
{
if (IsInvalid)
{
Expand All @@ -58,9 +63,12 @@ public Credential[] GetCredentials(int count)
{
IntPtr pCred = Marshal.ReadIntPtr(handle, inx * IntPtr.Size);
NativeCredential nativeCredential = (NativeCredential)Marshal.PtrToStructure(pCred, typeof(NativeCredential));
Credential credential = nativeCredential.ToCredential();
Credential credential = nativeCredential.ToCredential(includeClearPassword, includeSecurePassword);
credentials[inx] = credential;
nativeCredential = new NativeCredential();
GC.Collect();
}
GC.Collect();
return credentials;
}

Expand Down
4 changes: 2 additions & 2 deletions PSCredentialManager.Api/Extensions/CredentialExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public static NativeCredential ToNativeCredential(this Credential credential)
TargetAlias = IntPtr.Zero,
Type = credential.Type,
Persist = (uint)credential.Persist,
CredentialBlobSize = credential.PaswordSize,
CredentialBlobSize = credential.SecurePassword != null ? (uint)credential.SecurePassword.Length * 2 : credential.PaswordSize,
TargetName = Marshal.StringToCoTaskMemUni(credential.TargetName),
CredentialBlob = Marshal.StringToCoTaskMemUni(credential.Password),
CredentialBlob = credential.SecurePassword != null ? Marshal.SecureStringToCoTaskMemUnicode(credential.SecurePassword) : Marshal.StringToCoTaskMemUni(credential.Password),
UserName = Marshal.StringToCoTaskMemUni(credential.UserName),
LastWritten = credential.LastWritten.ToComFileTime()
};
Expand Down
45 changes: 41 additions & 4 deletions PSCredentialManager.Api/Extensions/NativeCredentialExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace PSCredentialManager.Api.Extensions
{
public static class NativeCredentialExtensions
{
public static Credential ToCredential(this NativeCredential nativeCredential)
public static Credential ToCredential(this NativeCredential nativeCredential, bool includeClearPassword, bool includeSecurePassword)
{
Credential credential;

Expand All @@ -22,13 +22,50 @@ public static Credential ToCredential(this NativeCredential nativeCredential)
TargetName = Marshal.PtrToStringUni(nativeCredential.TargetName),
TargetAlias = Marshal.PtrToStringUni(nativeCredential.TargetAlias),
Comment = Marshal.PtrToStringUni(nativeCredential.Comment),
PaswordSize = nativeCredential.CredentialBlobSize,
LastWritten = nativeCredential.LastWritten.ToDateTime()
LastWritten = nativeCredential.LastWritten.ToDateTime(),
SecurePassword = null,
PaswordSize = uint.MinValue,
Password = null,
};

if (0 < nativeCredential.CredentialBlobSize)
{
credential.Password = Marshal.PtrToStringUni(nativeCredential.CredentialBlob, (int)nativeCredential.CredentialBlobSize / 2);
if(includeClearPassword)
{
credential.PaswordSize = nativeCredential.CredentialBlobSize;
credential.Password = Marshal.PtrToStringUni(nativeCredential.CredentialBlob, (int)nativeCredential.CredentialBlobSize / 2);
}

if(includeSecurePassword)
{
credential.SecurePassword = new System.Security.SecureString();

for(int i=0, size = (int)nativeCredential.CredentialBlobSize / 2; i< size; i++)
{
string singlesign = Marshal.PtrToStringUni(nativeCredential.CredentialBlob + (i*2), 1);
if(singlesign.Length > 0)
{
credential.SecurePassword.AppendChar(singlesign[0]);
}
singlesign = null;
GC.Collect();
}

GC.Collect();
}
}
else
{
if(includeClearPassword)
{
credential.PaswordSize = nativeCredential.CredentialBlobSize;
credential.Password = "";
}

if(includeSecurePassword)
{
credential.SecurePassword = new System.Security.SecureString();
}
}
}
catch (Exception ex)
Expand Down
12 changes: 6 additions & 6 deletions PSCredentialManager.ApiTests/CredentialManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ public void ReadCredTest()

};

ShimCriticalCredentialHandle.AllInstances.GetCredential =
(CriticalCredentialHandle criticalCredentialHandle) =>
ShimCriticalCredentialHandle.AllInstances.GetCredentialBooleanBoolean =
(CriticalCredentialHandle criticalCredentialHandle, bool includeClearPassword, bool includeSecurePassword) =>
{
return new Credential();
};

manager.ReadCred("server01", CredType.Generic);
manager.ReadCred("server01", CredType.Generic, true, true);
}
}

Expand Down Expand Up @@ -95,13 +95,13 @@ public void ReadCredTest1()

};

ShimCriticalCredentialHandle.AllInstances.GetCredentialsInt32 =
(CriticalCredentialHandle credentialHandle, int count) =>
ShimCriticalCredentialHandle.AllInstances.GetCredentialsInt32BooleanBoolean =
(CriticalCredentialHandle credentialHandle, int count, bool includeClearPassword, bool includeSecurePassword) =>
{
return new Credential[count];
};

manager.ReadCred();
manager.ReadCred(true, true);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ public void ToNativeCredentialTest()

Assert.IsNotNull(nativeCredential);
Assert.IsInstanceOfType(nativeCredential, typeof(NativeCredential));
string ncUserName = System.Runtime.InteropServices.Marshal.PtrToStringUni(nativeCredential.UserName);
Assert.IsNotNull(ncUserName);
Assert.AreEqual(credential.UserName, ncUserName);

Credential convertedOnlyClear = nativeCredential.ToCredential(true, false);
Assert.IsNotNull(convertedOnlyClear);
Assert.IsInstanceOfType(convertedOnlyClear, typeof(Credential));
Assert.AreEqual(credential.Password, convertedOnlyClear.Password);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,70 @@ public void ToCredentialTest()
UserName = new IntPtr(0)
};

Credential credential = nativeCredential.ToCredential();
Credential credential = nativeCredential.ToCredential(true, true);

Assert.IsNotNull(credential);
Assert.IsInstanceOfType(credential, typeof(Credential));
}

[TestMethod()]
public void ToCredentialTestFilledValues()
{
Credential credential = new Credential()
{
AttributeCount = 0,
Attributes = new IntPtr(0),
Comment = "This is a comment",
Password = "April123!!",
PaswordSize = 20,
Flags = 0,
LastWritten = DateTime.Now,
Persist = CredPersist.LocalMachine,
TargetName = "server01",
Type = CredType.Generic,
UserName = "test-user"
};

NativeCredential nativeCredential = credential.ToNativeCredential();

Assert.IsNotNull(nativeCredential);
Assert.IsInstanceOfType(nativeCredential, typeof(NativeCredential));
string ncUserName = System.Runtime.InteropServices.Marshal.PtrToStringUni(nativeCredential.UserName);
Assert.IsNotNull(ncUserName);
Assert.AreEqual(credential.UserName, ncUserName);

Credential convertedOnlyClear = nativeCredential.ToCredential(true, false);
Assert.IsNotNull(convertedOnlyClear);
Assert.IsInstanceOfType(convertedOnlyClear, typeof(Credential));
Assert.IsNotNull(convertedOnlyClear.UserName);
Assert.AreEqual(credential.UserName, convertedOnlyClear.UserName);
Assert.IsNotNull(convertedOnlyClear.Password);
Assert.AreEqual(credential.Password, convertedOnlyClear.Password);
Assert.AreEqual(credential.PaswordSize, convertedOnlyClear.PaswordSize);
Assert.IsNull(convertedOnlyClear.SecurePassword);

Credential convertedOnlySecure = nativeCredential.ToCredential(false, true);
Assert.IsNotNull(convertedOnlySecure);
Assert.IsInstanceOfType(convertedOnlySecure, typeof(Credential));
Assert.IsNotNull(convertedOnlySecure.UserName);
Assert.AreEqual(credential.UserName, convertedOnlySecure.UserName);
Assert.IsNotNull(convertedOnlySecure.SecurePassword);
Assert.AreEqual(credential.Password, convertedOnlySecure.SecurePassword.ToInsecureString());
Assert.AreEqual(uint.MinValue, convertedOnlySecure.PaswordSize);
Assert.IsNull(convertedOnlySecure.Password);

Credential convertedClearAndSecure = nativeCredential.ToCredential(true, true);
Assert.IsNotNull(convertedClearAndSecure);
Assert.IsInstanceOfType(convertedClearAndSecure, typeof(Credential));
Assert.IsNotNull(convertedClearAndSecure.UserName);
Assert.AreEqual(credential.UserName, convertedClearAndSecure.UserName);
Assert.IsNotNull(convertedClearAndSecure.Password);
Assert.IsNotNull(convertedClearAndSecure.SecurePassword);
Assert.AreEqual(credential.Password, convertedClearAndSecure.Password);
Assert.AreEqual(credential.PaswordSize, convertedClearAndSecure.PaswordSize);
Assert.AreEqual(credential.Password, convertedClearAndSecure.SecurePassword.ToInsecureString());
Assert.AreEqual(credential.PaswordSize, (uint)convertedClearAndSecure.SecurePassword.Length * 2);

}
}
}
25 changes: 25 additions & 0 deletions PSCredentialManager.ApiTests/Extensions/SecureStringExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Runtime.InteropServices;
using System.Security;

namespace PSCredentialManager.ApiTests.Extensions
{
public static class SecureStringExtensions
{
public static string ToInsecureString(this SecureString secureString)
{
IntPtr secureStringPtr = IntPtr.Zero;

try
{
secureStringPtr = Marshal.SecureStringToGlobalAllocUnicode(secureString);
return Marshal.PtrToStringUni(secureStringPtr);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(secureStringPtr);
}

}
}
}
19 changes: 19 additions & 0 deletions PSCredentialManager.ApiTests/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Security;

namespace PSCredentialManager.ApiTests.Extensions
{
public static class StringExtensions
{
public static SecureString ToSecureString(this string insecureString)
{
SecureString secureString = new SecureString();

foreach (char character in insecureString)
{
secureString.AppendChar(character);
}

return secureString;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
<Compile Include="CredentialManagerTests.cs" />
<Compile Include="Extensions\CredentialExtensionsTests.cs" />
<Compile Include="Extensions\NativeCredentialExtensionsTests.cs" />
<Compile Include="Extensions\SecureStringExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
Loading