Reorganized the project to put the library one folder down.
This commit is contained in:
13
NSspi/Credentials/ClientCredential.cs
Normal file
13
NSspi/Credentials/ClientCredential.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
public class ClientCredential : Credential
|
||||
{
|
||||
public ClientCredential( SecurityPackage package ) : base( package, CredentialType.Client ) { }
|
||||
}
|
||||
}
|
||||
202
NSspi/Credentials/Credential.cs
Normal file
202
NSspi/Credentials/Credential.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.DirectoryServices.AccountManagement;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NSspi.Credentials;
|
||||
using NSspi.Credentials.Credentials;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
public class Credential : IDisposable
|
||||
{
|
||||
private bool disposed;
|
||||
|
||||
private SecurityPackage securityPackage;
|
||||
|
||||
private SafeCredentialHandle safeCredHandle;
|
||||
private long expiry;
|
||||
|
||||
public Credential(SecurityPackage package, CredentialType credentialType)
|
||||
{
|
||||
this.disposed = false;
|
||||
this.securityPackage = package;
|
||||
|
||||
this.expiry = 0;
|
||||
|
||||
Init( package, credentialType );
|
||||
}
|
||||
|
||||
private void Init( SecurityPackage package, CredentialType credentialType )
|
||||
{
|
||||
string packageName;
|
||||
CredentialUse use;
|
||||
|
||||
// -- Package --
|
||||
if ( package == SecurityPackage.Kerberos )
|
||||
{
|
||||
packageName = PackageNames.Kerberos;
|
||||
}
|
||||
else if ( package == SecurityPackage.Negotiate )
|
||||
{
|
||||
packageName = PackageNames.Negotiate;
|
||||
}
|
||||
else if ( package == SecurityPackage.NTLM )
|
||||
{
|
||||
packageName = PackageNames.Ntlm;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException( "Invalid value provided for the 'package' parameter." );
|
||||
}
|
||||
|
||||
// -- Credential --
|
||||
if ( credentialType == CredentialType.Client )
|
||||
{
|
||||
use = CredentialUse.Outbound;
|
||||
}
|
||||
else if ( credentialType == CredentialType.Server )
|
||||
{
|
||||
use = CredentialUse.Inbound;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException( "Invalid value provided for the 'credentialType' parameter." );
|
||||
}
|
||||
|
||||
// -- Invoke --
|
||||
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
|
||||
this.safeCredHandle = new SafeCredentialHandle();
|
||||
|
||||
// The finally clause is the actual constrained region. The VM pre-allocates any stack space,
|
||||
// performs any allocations it needs to prepare methods for execution, and postpones any
|
||||
// instances of the 'uncatchable' exceptions (ThreadAbort, StackOverflow, OutOfMemory).
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try { }
|
||||
finally
|
||||
{
|
||||
status = CredentialNativeMethods.AcquireCredentialsHandle(
|
||||
null,
|
||||
packageName,
|
||||
use,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
ref this.safeCredHandle.rawHandle,
|
||||
ref this.expiry
|
||||
);
|
||||
}
|
||||
|
||||
if ( status != SecurityStatus.OK )
|
||||
{
|
||||
throw new SSPIException( "Failed to call AcquireCredentialHandle", status );
|
||||
}
|
||||
}
|
||||
|
||||
~Credential()
|
||||
{
|
||||
Dispose( false );
|
||||
}
|
||||
|
||||
public SecurityPackage SecurityPackage
|
||||
{
|
||||
get
|
||||
{
|
||||
if( this.disposed )
|
||||
{
|
||||
throw new ObjectDisposedException( base.GetType().Name );
|
||||
}
|
||||
|
||||
return this.securityPackage;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
QueryNameAttribCarrier carrier = new QueryNameAttribCarrier();
|
||||
|
||||
SecurityStatus status = SecurityStatus.InternalError;
|
||||
string name = null;
|
||||
bool gotRef = false;
|
||||
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
this.safeCredHandle.DangerousAddRef( ref gotRef );
|
||||
}
|
||||
catch( Exception )
|
||||
{
|
||||
if( gotRef == true )
|
||||
{
|
||||
this.safeCredHandle.DangerousRelease();
|
||||
gotRef = false;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if( gotRef )
|
||||
{
|
||||
status = CredentialNativeMethods.QueryCredentialsAttribute_Name(
|
||||
ref this.safeCredHandle.rawHandle,
|
||||
CredentialQueryAttrib.Names,
|
||||
ref carrier
|
||||
);
|
||||
|
||||
this.safeCredHandle.DangerousRelease();
|
||||
|
||||
if( status == SecurityStatus.OK && carrier.Name != IntPtr.Zero )
|
||||
{
|
||||
name = Marshal.PtrToStringUni( carrier.Name );
|
||||
NativeMethods.FreeContextBuffer( carrier.Name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( status.IsError() )
|
||||
{
|
||||
throw new SSPIException( "Failed to query credential name", status );
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public SafeCredentialHandle Handle
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.safeCredHandle;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose( true );
|
||||
GC.SuppressFinalize( this );
|
||||
}
|
||||
|
||||
protected virtual void Dispose( bool disposing )
|
||||
{
|
||||
if ( this.disposed == false )
|
||||
{
|
||||
if ( disposing )
|
||||
{
|
||||
this.safeCredHandle.Dispose();
|
||||
}
|
||||
|
||||
this.disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
77
NSspi/Credentials/CredentialNativeMethods.cs
Normal file
77
NSspi/Credentials/CredentialNativeMethods.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NSspi.Credentials;
|
||||
using NSspi.Credentials.Credentials;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
internal static class CredentialNativeMethods
|
||||
{
|
||||
/*
|
||||
SECURITY_STATUS SEC_Entry AcquireCredentialsHandle(
|
||||
_In_ SEC_CHAR *pszPrincipal, // [in] name of principal. NULL = principal of current security context
|
||||
_In_ SEC_CHAR *pszPackage, // [in] name of security package - "Kerberos", "Negotiate", "NTLM", etc
|
||||
_In_ ULONG fCredentialUse, // [in] flags indicating use.
|
||||
_In_ PLUID pvLogonID, // [in] pointer to logon identifier. NULL = we're not specifying the id of another logon session
|
||||
_In_ PVOID pAuthData, // [in] package-specific data. NULL = default credentials for security package
|
||||
_In_ SEC_GET_KEY_FN pGetKeyFn, // [in] pointer to GetKey function. NULL = we're not using a callback to retrieve the credentials
|
||||
_In_ PVOID pvGetKeyArgument, // [in] value to pass to GetKey
|
||||
_Out_ PCredHandle phCredential, // [out] credential handle (this must be already allocated)
|
||||
_Out_ PTimeStamp ptsExpiry // [out] lifetime of the returned credentials
|
||||
);
|
||||
|
||||
SECURITY_STATUS SEC_Entry FreeCredentialsHandle(
|
||||
_In_ PCredHandle phCredential
|
||||
);
|
||||
|
||||
SECURITY_STATUS SEC_Entry QueryCredentialsAttributes(
|
||||
_In_ PCredHandle phCredential,
|
||||
_In_ ULONG ulAttribute,
|
||||
_Out_ PVOID pBuffer
|
||||
);
|
||||
*/
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail)]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "AcquireCredentialsHandle", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus AcquireCredentialsHandle(
|
||||
string principleName,
|
||||
string packageName,
|
||||
CredentialUse credentialUse,
|
||||
IntPtr loginId,
|
||||
IntPtr packageData,
|
||||
IntPtr getKeyFunc,
|
||||
IntPtr getKeyData,
|
||||
ref RawSspiHandle credentialHandle,
|
||||
ref long expiry
|
||||
);
|
||||
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "FreeCredentialsHandle", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus FreeCredentialsHandle(
|
||||
ref RawSspiHandle credentialHandle
|
||||
);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The overload of the QueryCredentialsAttribute method that is used for querying the name attribute.
|
||||
/// In this call, it takes a void* to a structure that contains a wide char pointer. The wide character
|
||||
/// pointer is allocated by the SSPI api, and thus needs to be released by a call to FreeContextBuffer().
|
||||
/// </summary>
|
||||
/// <param name="credentialHandle"></param>
|
||||
/// <param name="attributeName"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
|
||||
[DllImport( "Secur32.dll", EntryPoint = "QueryCredentialsAttributes", CharSet = CharSet.Unicode )]
|
||||
internal static extern SecurityStatus QueryCredentialsAttribute_Name(
|
||||
ref RawSspiHandle credentialHandle,
|
||||
CredentialQueryAttrib attributeName,
|
||||
ref QueryNameAttribCarrier name
|
||||
);
|
||||
}
|
||||
}
|
||||
15
NSspi/Credentials/CredentialPackage.cs
Normal file
15
NSspi/Credentials/CredentialPackage.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
public enum SecurityPackage
|
||||
{
|
||||
Negotiate = 0,
|
||||
Kerberos = 1,
|
||||
NTLM = 2
|
||||
}
|
||||
}
|
||||
23
NSspi/Credentials/CredentialQueryAttrib.cs
Normal file
23
NSspi/Credentials/CredentialQueryAttrib.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
/*
|
||||
#define SECPKG_CRED_ATTR_NAMES 1
|
||||
#define SECPKG_CRED_ATTR_SSI_PROVIDER 2
|
||||
#define SECPKG_CRED_ATTR_KDC_PROXY_SETTINGS 3
|
||||
#define SECPKG_CRED_ATTR_CERT 4
|
||||
*/
|
||||
|
||||
public enum CredentialQueryAttrib : uint
|
||||
{
|
||||
Names = 1,
|
||||
SsiProvider = 2,
|
||||
KdcProxySettings = 3,
|
||||
Cert = 4
|
||||
}
|
||||
}
|
||||
14
NSspi/Credentials/CredentialType.cs
Normal file
14
NSspi/Credentials/CredentialType.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
public enum CredentialType
|
||||
{
|
||||
Client = 0,
|
||||
Server = 1
|
||||
}
|
||||
}
|
||||
15
NSspi/Credentials/CredentialUse.cs
Normal file
15
NSspi/Credentials/CredentialUse.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
public enum CredentialUse : uint
|
||||
{
|
||||
Inbound = 1,
|
||||
Outbound = 2,
|
||||
Both = 3,
|
||||
}
|
||||
}
|
||||
15
NSspi/Credentials/QueryNameSupport.cs
Normal file
15
NSspi/Credentials/QueryNameSupport.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials.Credentials
|
||||
{
|
||||
[StructLayout( LayoutKind.Sequential )]
|
||||
public struct QueryNameAttribCarrier
|
||||
{
|
||||
public IntPtr Name;
|
||||
}
|
||||
}
|
||||
28
NSspi/Credentials/SafeCredentialHandle.cs
Normal file
28
NSspi/Credentials/SafeCredentialHandle.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
|
||||
public class SafeCredentialHandle : SafeSspiHandle
|
||||
{
|
||||
public SafeCredentialHandle()
|
||||
: base()
|
||||
{ }
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
SecurityStatus status = CredentialNativeMethods.FreeCredentialsHandle(
|
||||
ref base.rawHandle
|
||||
);
|
||||
|
||||
base.ReleaseHandle();
|
||||
|
||||
return status == SecurityStatus.OK;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
13
NSspi/Credentials/ServerCredential.cs
Normal file
13
NSspi/Credentials/ServerCredential.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NSspi.Credentials
|
||||
{
|
||||
public class ServerCredential : Credential
|
||||
{
|
||||
public ServerCredential( SecurityPackage package ) : base( package, CredentialType.Server ) { }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user