From 241da896b1a099d7bc24c31bb531029b60a34773 Mon Sep 17 00:00:00 2001 From: antiduh Date: Fri, 27 Jun 2014 22:00:18 +0000 Subject: [PATCH] Implemented the ability to query the EnumerateSecurityPackages native API safely. --- NSspi/NativeMethods.cs | 5 ++++ NSspi/PackageSupport.cs | 65 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/NSspi/NativeMethods.cs b/NSspi/NativeMethods.cs index 17c9eba..3853098 100644 --- a/NSspi/NativeMethods.cs +++ b/NSspi/NativeMethods.cs @@ -33,5 +33,10 @@ namespace NSspi [ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )] [DllImport( "Secur32.dll", EntryPoint = "QuerySecurityPackageInfo", CharSet = CharSet.Unicode )] internal static extern SecurityStatus QuerySecurityPackageInfo( string packageName, ref IntPtr pkgInfo ); + + [ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )] + [DllImport( "Secur32.dll", EntryPoint = "EnumerateSecurityPackages", CharSet = CharSet.Unicode )] + internal static extern SecurityStatus EnumerateSecurityPackages( ref int numPackages, ref IntPtr pkgInfoArry ); + } } diff --git a/NSspi/PackageSupport.cs b/NSspi/PackageSupport.cs index f7d4ccd..c2bdf5e 100644 --- a/NSspi/PackageSupport.cs +++ b/NSspi/PackageSupport.cs @@ -13,7 +13,7 @@ namespace NSspi internal static SecPkgInfo GetPackageCapabilities( string packageName ) { SecPkgInfo info; - SecurityStatus status; + SecurityStatus status = SecurityStatus.InternalError; SecurityStatus freeStatus; IntPtr rawInfoPtr; @@ -45,8 +45,71 @@ namespace NSspi } } + if( status != SecurityStatus.OK ) + { + throw new SSPIException( "Failed to query security package provider details", status ); + } + return info; } + public static SecPkgInfo[] EnumeratePackages() + { + SecurityStatus status = SecurityStatus.InternalError; + SecPkgInfo[] packages = null; + IntPtr pkgArrayPtr; + IntPtr pkgPtr; + int numPackages = 0; + int pkgSize = Marshal.SizeOf( typeof(SecPkgInfo) ); + + pkgArrayPtr = new IntPtr(); + + RuntimeHelpers.PrepareConstrainedRegions(); + try { } + finally + { + status = NativeMethods.EnumerateSecurityPackages( ref numPackages, ref pkgArrayPtr ); + + if( pkgArrayPtr != IntPtr.Zero ) + { + try + { + if( status == SecurityStatus.OK ) + { + // Bwooop Bwooop Alocation Alert + // 1) We allocate the array + // 2) We allocate the individual elements in the array (they're class objects). + // 3) We allocate the strings in the individual elements in the array when we + // call Marshal.PtrToStructure() + + packages = new SecPkgInfo[numPackages]; + + for( int i = 0; i < numPackages; i++ ) + { + packages[i] = new SecPkgInfo(); + } + + for( int i = 0; i < numPackages; i++ ) + { + pkgPtr = IntPtr.Add( pkgArrayPtr, i * pkgSize ); + + Marshal.PtrToStructure( pkgPtr, packages[i] ); + } + } + } + finally + { + NativeMethods.FreeContextBuffer( pkgArrayPtr ); + } + } + } + + if( status != SecurityStatus.OK ) + { + throw new SSPIException( "Failed to enumerate security package providers", status ); + } + + return packages; + } } }