From f96ef74e9bb0db9421d35677241ce3a7f06f9899 Mon Sep 17 00:00:00 2001 From: antiduh Date: Thu, 19 Jun 2014 02:26:30 +0000 Subject: [PATCH] Implemented Credential acquisition and release. --- Credential.cs | 89 +++++++++++++++++++++++++++++++++++++++++------ CredentialUse.cs | 2 +- NSspi.csproj | 7 +++- NativeMethods.cs | 29 +++++++++++++-- PackageNames.cs | 2 +- Program.cs | 18 ++++++++++ SSPIException.cs | 8 ++--- SecurityStatus.cs | 34 ++++++++++++++++++ 8 files changed, 168 insertions(+), 21 deletions(-) create mode 100644 Program.cs create mode 100644 SecurityStatus.cs diff --git a/Credential.cs b/Credential.cs index 6d6a443..8b478a8 100644 --- a/Credential.cs +++ b/Credential.cs @@ -13,13 +13,74 @@ namespace NSspi private SecurityPackage securityPackage; + private long credHandle; + private long expiry; + public Credential(SecurityPackage package, CredentialType credentialType) { this.disposed = false; - this.securityPackage = package; - - Init(); + + this.credHandle = 0; + 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 == NSspi.SecurityPackage.Negotiate ) + { + packageName = PackageNames.Negotiate; + } + else if ( package == NSspi.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 = NativeMethods.AcquireCredentialsHandle( + null, + packageName, + use, + IntPtr.Zero, + IntPtr.Zero, + IntPtr.Zero, + IntPtr.Zero, + ref this.credHandle, + ref this.expiry + ); + + if ( status != SecurityStatus.Success ) + { + throw new SSPIException( "Failed to call AcquireCredentialHandle", status ); + } } ~Credential() @@ -45,12 +106,11 @@ namespace NSspi return null; } - // TODO use safe handle ... - public IntPtr CredentialHandle + public long CredentialHandle { get { - return IntPtr.Zero; + return this.credHandle; } } @@ -62,12 +122,19 @@ namespace NSspi protected virtual void Dispose( bool disposing ) { - this.disposed = true; - } + if ( this.disposed == false ) + { + SecurityStatus result; - private void Init() - { - } + result = NativeMethods.FreeCredentialsHandle( ref this.credHandle ); + this.disposed = true; + + if ( disposing && result != SecurityStatus.Success ) + { + throw new SSPIException( "Failed to release credentials handle", result ); + } + } + } } } diff --git a/CredentialUse.cs b/CredentialUse.cs index 65623b1..103ae2e 100644 --- a/CredentialUse.cs +++ b/CredentialUse.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace NSspi { - public enum CredentialUse : int + public enum CredentialUse : uint { Inbound = 1, Outbound = 2, diff --git a/NSspi.csproj b/NSspi.csproj index 62b739e..f319640 100644 --- a/NSspi.csproj +++ b/NSspi.csproj @@ -5,7 +5,7 @@ Debug AnyCPU {4B4CD933-BF62-4F92-B8FA-6771758C5197} - Library + WinExe Properties NSspi NSspi @@ -29,6 +29,9 @@ prompt 4 + + NSspi.Program + @@ -47,7 +50,9 @@ + + diff --git a/NativeMethods.cs b/NativeMethods.cs index 33275fe..030ed81 100644 --- a/NativeMethods.cs +++ b/NativeMethods.cs @@ -38,8 +38,14 @@ namespace NSspi ); */ - [DllImport( "Secur32.dll", CallingConvention = CallingConvention.Winapi, SetLastError=true)] - public extern int AcquireCredentialHandle( + [DllImport( + "Secur32.dll", + EntryPoint = "AcquireCredentialsHandle", + CallingConvention = CallingConvention.Winapi, + CharSet = CharSet.Unicode, + SetLastError = true + )] + public static extern SecurityStatus AcquireCredentialsHandle( string principleName, string packageName, CredentialUse credentialUse, @@ -47,8 +53,25 @@ namespace NSspi IntPtr packageData, IntPtr getKeyFunc, IntPtr getKeyData, - IntPtr credentialHandle, + ref long credentialHandle, ref long expiry ); + + /* + SECURITY_STATUS SEC_Entry FreeCredentialsHandle( + _In_ PCredHandle phCredential + ); + */ + [DllImport( + "Secur32.dll", + EntryPoint = "FreeCredentialsHandle", + CallingConvention = CallingConvention.Winapi, + CharSet = CharSet.Unicode, + SetLastError = true + )] + public static extern SecurityStatus FreeCredentialsHandle( + ref long credentialHandle + ); + } } diff --git a/PackageNames.cs b/PackageNames.cs index 1b0eee9..a6b971f 100644 --- a/PackageNames.cs +++ b/PackageNames.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; namespace NSspi { - public static sealed class PackageNames + public static class PackageNames { public const string Negotiate = "Negotiate"; diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..2fac4d1 --- /dev/null +++ b/Program.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NSspi +{ + public class Program + { + public static void Main( string[] args ) + { + Credential cred = new Credential( SecurityPackage.Negotiate, CredentialType.Client ); + cred.Dispose(); + + } + } +} diff --git a/SSPIException.cs b/SSPIException.cs index 21bbd9e..e440d8a 100644 --- a/SSPIException.cs +++ b/SSPIException.cs @@ -10,17 +10,17 @@ namespace NSspi [Serializable] public class SSPIException : Exception { - private int errorCode; + private SecurityStatus errorCode; private string message; public SSPIException( SerializationInfo info, StreamingContext context ) : base( info, context ) { this.message = info.GetString( "messsage" ); - this.errorCode = info.GetInt32( "errorCode" ); + this.errorCode = (SecurityStatus)info.GetUInt32( "errorCode" ); } - public SSPIException( string message, int errorCode ) + public SSPIException( string message, SecurityStatus errorCode ) { this.message = message; this.errorCode = errorCode; @@ -34,7 +34,7 @@ namespace NSspi info.AddValue( "errorCode", this.errorCode ); } - public int ErrorCode + public SecurityStatus ErrorCode { get { diff --git a/SecurityStatus.cs b/SecurityStatus.cs new file mode 100644 index 0000000..62ed767 --- /dev/null +++ b/SecurityStatus.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NSspi +{ + /* + // From winerror.h + #define SEC_E_OK ((HRESULT)0x00000000L) + #define SEC_E_INSUFFICIENT_MEMORY _HRESULT_TYPEDEF_(0x80090300L) + #define SEC_E_INVALID_HANDLE _HRESULT_TYPEDEF_(0x80090301L) + #define SEC_E_UNSUPPORTED_FUNCTION _HRESULT_TYPEDEF_(0x80090302L) + #define SEC_E_TARGET_UNKNOWN _HRESULT_TYPEDEF_(0x80090303L) + #define SEC_E_INTERNAL_ERROR _HRESULT_TYPEDEF_(0x80090304L) + #define SEC_E_SECPKG_NOT_FOUND _HRESULT_TYPEDEF_(0x80090305L) + #define SEC_E_NOT_OWNER _HRESULT_TYPEDEF_(0x80090306L) + #define SEC_E_UNKNOWN_CREDENTIALS _HRESULT_TYPEDEF_(0x8009030DL) + #define SEC_E_NO_CREDENTIALS _HRESULT_TYPEDEF_(0x8009030EL) + */ + + public enum SecurityStatus : uint + { + Success = 0, + InsufficientMemory = 0x80090300, + InvalidHandle = 0x80090301, + InternalError = 0x80090304, + SecPkgNotFound = 0x80090305, + NotOwner = 0x80090306, + NoCredentials = 0x8009030E, + UnknownCredentials = 0x8009030D + } +}