mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-09 09:42:35 -05:00
Credentials store API (#38)
* CredentialService initial impl with Win32 support - Basic CredentialService APIs for Save, Read, Delete - E2E unit tests for Credential Service - Win32 implementation with unit tests * Save Password support on Mac v1 - Basic keychain support on Mac using Interop with the KeyChain APIs - All but 1 unit test passing. This will pass once API is changed, but checking this in with the existing API so that if we decide to alter behavior, we have a reference point. * Remove Username from Credentials API - Removed Username option from Credentials as this caused conflicting behavior on Mac vs Windows * Cleanup Using Statements and add Copyright * Linux CredentialStore Prototype * Linux credential store support - Full support for Linux credential store with tests * Plumbed CredentialService into Program init * Addressing Pull Request comments
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Code originally from http://credentialmanagement.codeplex.com/,
|
||||
// Licensed under the Apache License 2.0
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.SqlTools.EditorServices.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Credentials.Win32
|
||||
{
|
||||
public class CredentialSet: List<Win32Credential>, IDisposable
|
||||
{
|
||||
bool _disposed;
|
||||
|
||||
public CredentialSet()
|
||||
{
|
||||
}
|
||||
|
||||
public CredentialSet(string target)
|
||||
: this()
|
||||
{
|
||||
if (string.IsNullOrEmpty(target))
|
||||
{
|
||||
throw new ArgumentNullException("target");
|
||||
}
|
||||
Target = target;
|
||||
}
|
||||
|
||||
public string Target { get; set; }
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
// Prevent GC Collection since we have already disposed of this object
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~CredentialSet()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
ForEach(cred => cred.Dispose());
|
||||
}
|
||||
}
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public CredentialSet Load()
|
||||
{
|
||||
LoadInternal();
|
||||
return this;
|
||||
}
|
||||
|
||||
private void LoadInternal()
|
||||
{
|
||||
uint count;
|
||||
|
||||
IntPtr pCredentials = IntPtr.Zero;
|
||||
bool result = NativeMethods.CredEnumerateW(Target, 0, out count, out pCredentials);
|
||||
if (!result)
|
||||
{
|
||||
Logger.Write(LogLevel.Error, string.Format("Win32Exception: {0}", new Win32Exception(Marshal.GetLastWin32Error()).ToString()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Read in all of the pointers first
|
||||
IntPtr[] ptrCredList = new IntPtr[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
ptrCredList[i] = Marshal.ReadIntPtr(pCredentials, IntPtr.Size*i);
|
||||
}
|
||||
|
||||
// Now let's go through all of the pointers in the list
|
||||
// and create our Credential object(s)
|
||||
List<NativeMethods.CriticalCredentialHandle> credentialHandles =
|
||||
ptrCredList.Select(ptrCred => new NativeMethods.CriticalCredentialHandle(ptrCred)).ToList();
|
||||
|
||||
IEnumerable<Win32Credential> existingCredentials = credentialHandles
|
||||
.Select(handle => handle.GetCredential())
|
||||
.Select(nativeCredential =>
|
||||
{
|
||||
Win32Credential credential = new Win32Credential();
|
||||
credential.LoadInternal(nativeCredential);
|
||||
return credential;
|
||||
});
|
||||
AddRange(existingCredentials);
|
||||
|
||||
// The individual credentials should not be free'd
|
||||
credentialHandles.ForEach(handle => handle.SetHandleAsInvalid());
|
||||
|
||||
// Clean up memory to the Enumeration pointer
|
||||
NativeMethods.CredFree(pCredentials);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user