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
+ }
+}