diff --git a/Credential.cs b/Credential.cs index 8b478a8..724759a 100644 --- a/Credential.cs +++ b/Credential.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.DirectoryServices.AccountManagement; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -101,9 +102,33 @@ namespace NSspi } } - public string GetName() + public string Name { - return null; + get + { + NativeMethods.QueryNameAttribCarrier carrier = new NativeMethods.QueryNameAttribCarrier(); + + SecurityStatus status; + string name = null; + + status = NativeMethods.QueryCredentialsAttribute_Name( + ref this.credHandle, + CredentialQueryAttrib.Names, + ref carrier + ); + + if ( status == SecurityStatus.Success ) + { + name = Marshal.PtrToStringUni( carrier.Name ); + NativeMethods.FreeContextBuffer( carrier.Name ); + } + else + { + throw new SSPIException( "Failed to query credential name", status ); + } + + return name; + } } public long CredentialHandle diff --git a/CredentialQueryAttrib.cs b/CredentialQueryAttrib.cs new file mode 100644 index 0000000..7f5bd86 --- /dev/null +++ b/CredentialQueryAttrib.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NSspi +{ + /* + #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 + } +} diff --git a/NSspi.csproj b/NSspi.csproj index f319640..fca18d9 100644 --- a/NSspi.csproj +++ b/NSspi.csproj @@ -46,6 +46,7 @@ + diff --git a/NativeMethods.cs b/NativeMethods.cs index 030ed81..7f1b2fa 100644 --- a/NativeMethods.cs +++ b/NativeMethods.cs @@ -73,5 +73,55 @@ namespace NSspi ref long credentialHandle ); + /* + SECURITY_STATUS SEC_Entry FreeContextBuffer( + _In_ PVOID pvContextBuffer + ); + */ + [DllImport( + "Secur32.dll", + EntryPoint = "FreeContextBuffer", + CallingConvention = CallingConvention.Winapi, + CharSet = CharSet.Unicode, + SetLastError = true + )] + public static extern SecurityStatus FreeContextBuffer( IntPtr buffer ); + + + + /* + SECURITY_STATUS SEC_Entry QueryCredentialsAttributes( + _In_ PCredHandle phCredential, + _In_ ULONG ulAttribute, + _Out_ PVOID pBuffer + ); + */ + + /// + /// 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. + /// + /// + /// + /// + /// + [DllImport( + "Secur32.dll", + EntryPoint = "QueryCredentialsAttributes", + CallingConvention = CallingConvention.Winapi, + CharSet = CharSet.Unicode, + SetLastError = true + )] + public static extern SecurityStatus QueryCredentialsAttribute_Name( + ref long credentialHandle, + CredentialQueryAttrib attributeName, + ref QueryNameAttribCarrier name + ); + + [StructLayout( LayoutKind.Sequential )] + public struct QueryNameAttribCarrier + { + public IntPtr Name; + } } } diff --git a/Program.cs b/Program.cs index 2fac4d1..ce677df 100644 --- a/Program.cs +++ b/Program.cs @@ -10,9 +10,22 @@ namespace NSspi { public static void Main( string[] args ) { - Credential cred = new Credential( SecurityPackage.Negotiate, CredentialType.Client ); - cred.Dispose(); + Credential cred = null; + try + { + cred = new Credential( SecurityPackage.Negotiate, CredentialType.Client ); + string name = cred.GetName(); + Console.Out.WriteLine( name ); + Console.Out.Flush(); + } + finally + { + if ( cred != null ) + { + cred.Dispose(); + } + } } } }