source: branches/eraser6/CodeReview/Eraser.Util/Security.cs @ 1552

Revision 1552, 8.1 KB checked in by lowjoel, 4 years ago (diff)

Combined the functions in AdvApi?, MsCorEEApi and WintrustApi? to Security.cs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2009 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
24using System.Text;
25using System.ComponentModel;
26using System.Security.Principal;
27using System.Runtime.InteropServices;
28
29namespace Eraser.Util
30{
31    public static class Security
32    {
33        /// <summary>
34        /// Checks whether the current process is running with administrative
35        /// privileges.
36        /// </summary>
37        /// <returns>True if the user is an administrator. This only returns
38        /// true under Vista when UAC is enabled and the process is elevated.</returns>
39        public static bool IsAdministrator()
40        {
41            WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
42            return principal.IsInRole(WindowsBuiltInRole.Administrator);
43        }
44
45        /// <summary>
46        /// Checks whether the current process is running with administrative privileges.
47        /// </summary>
48        /// <returns>Returns true if UAC is enabled under Vista. Will return false
49        /// under pre-Vista OSes</returns>
50        public static bool UacEnabled()
51        {
52            //Check whether we're on Vista
53            if (Environment.OSVersion.Platform != PlatformID.Win32NT ||
54                Environment.OSVersion.Version < new Version(6, 0))
55            {
56                //UAC doesn't exist on these platforms.
57                return false;
58            }
59
60            //Get the process token.
61            SafeTokenHandle hToken = new SafeTokenHandle();
62            bool result = NativeMethods.OpenProcessToken(NativeMethods.GetCurrentProcess(),
63                NativeMethods.TOKEN_QUERY, out hToken);
64            if (!result || hToken.IsInvalid)
65                throw KernelApi.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
66
67            IntPtr pElevationType = Marshal.AllocHGlobal(Marshal.SizeOf(
68                typeof(NativeMethods.TOKEN_ELEVATION_TYPE)));
69            try
70            {
71                //Get the token information for our current process.
72                uint returnSize = 0;
73                result = NativeMethods.GetTokenInformation(hToken,
74                    NativeMethods.TOKEN_INFORMATION_CLASS.TokenElevationType,
75                    pElevationType, sizeof(NativeMethods.TOKEN_ELEVATION_TYPE),
76                    out returnSize);
77
78                //Check the return code
79                if (!result)
80                    throw KernelApi.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
81
82                NativeMethods.TOKEN_ELEVATION_TYPE elevationType =
83                    (NativeMethods.TOKEN_ELEVATION_TYPE)Marshal.PtrToStructure(
84                        pElevationType, typeof(NativeMethods.TOKEN_ELEVATION_TYPE));
85                return elevationType != NativeMethods.TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault;
86            }
87            finally
88            {
89                Marshal.FreeHGlobal(pElevationType);
90            }
91        }
92
93        /// <summary>
94        /// Verifies the Authenticode signature in a file.
95        /// </summary>
96        /// <param name="pathToFile">The file to verify.</param>
97        /// <returns>True if the file contains a valid Authenticode certificate.</returns>
98        public static bool VerifyAuthenticode(string pathToFile)
99        {
100            IntPtr unionPointer = IntPtr.Zero;
101
102            try
103            {
104                NativeMethods.WINTRUST_FILE_INFO fileinfo = new NativeMethods.WINTRUST_FILE_INFO();
105                fileinfo.cbStruct = (uint)Marshal.SizeOf(typeof(NativeMethods.WINTRUST_FILE_INFO));
106                fileinfo.pcwszFilePath = pathToFile;
107
108                NativeMethods.WINTRUST_DATA data = new NativeMethods.WINTRUST_DATA();
109                data.cbStruct = (uint)Marshal.SizeOf(typeof(NativeMethods.WINTRUST_DATA));
110                data.dwUIChoice = NativeMethods.WINTRUST_DATA.UIChoices.WTD_UI_NONE;
111                data.fdwRevocationChecks = NativeMethods.WINTRUST_DATA.RevocationChecks.WTD_REVOKE_NONE;
112                data.dwUnionChoice = NativeMethods.WINTRUST_DATA.UnionChoices.WTD_CHOICE_FILE;
113                unionPointer = data.pUnion = Marshal.AllocHGlobal((int)fileinfo.cbStruct);
114                Marshal.StructureToPtr(fileinfo, data.pUnion, false);
115
116                Guid guid = NativeMethods.WINTRUST_ACTION_GENERIC_VERIFY_V2;
117                return NativeMethods.WinVerifyTrust(IntPtr.Zero, ref guid, ref data) == 0;
118            }
119            finally
120            {
121                if (unionPointer != IntPtr.Zero)
122                    Marshal.FreeHGlobal(unionPointer);
123            }
124        }
125
126        /// <summary>
127        /// Gets a value indicating whether the assembly manifest at the supplied
128        /// path contains a strong name signature.
129        /// </summary>
130        /// <param name="assemblyPath">The path to the portable executable (.exe or
131        /// .dll) file for the assembly to be verified.</param>
132        /// <returns>True if the verification was successful; otherwise, false.</returns>
133        /// <remarks>VerifyStrongName is a utility function to check the validity
134        /// of an assembly, taking into account registry settings.</remarks>
135        public static bool VerifyStrongName(string assemblyPath)
136        {
137            bool wasVerified = false;
138            return NativeMethods.StrongNameSignatureVerificationEx(assemblyPath, false,
139                out wasVerified) && wasVerified;
140        }
141
142        /// <summary>
143        /// Randomises the provided buffer using CryptGenRandom.
144        /// </summary>
145        /// <param name="cryptGenRandom">The buffer which receives the random
146        /// data. The contents of this buffer can also be used as a random
147        /// seed.</param>
148        /// <returns>True if the operation suceeded.</returns>
149        public static bool Randomise(byte[] buffer)
150        {
151            return CryptApi.CryptGenRandom(buffer);
152        }
153    }
154
155    internal sealed class CryptApi : IDisposable
156    {
157        /// <summary>
158        /// Constructor.
159        /// </summary>
160        private CryptApi()
161        {
162            /* Intel i8xx (82802 Firmware Hub Device) hardware random number generator */
163            const string IntelDefaultProvider = "Intel Hardware Cryptographic Service Provider";
164
165            handle = new SafeCryptHandle();
166            if (NativeMethods.CryptAcquireContext(out handle, string.Empty,
167                IntelDefaultProvider, NativeMethods.PROV_INTEL_SEC, 0))
168            {
169                return;
170            }
171            else if (NativeMethods.CryptAcquireContext(out handle, string.Empty,
172                string.Empty, NativeMethods.PROV_RSA_FULL, 0))
173            {
174                return;
175            }
176            else if (Marshal.GetLastWin32Error() == NativeMethods.NTE_BAD_KEYSET)
177            {
178                //Default keyset doesn't exist, attempt to create a new one
179                if (NativeMethods.CryptAcquireContext(out handle, string.Empty, string.Empty,
180                    NativeMethods.PROV_RSA_FULL, NativeMethods.CRYPT_NEWKEYSET))
181                {
182                    return;
183                }
184            }
185
186            throw new NotSupportedException("Unable to acquire a cryptographic service provider.");
187        }
188
189        #region IDisposable Members
190        ~CryptApi()
191        {
192            Dispose(false);
193        }
194
195        public void Dispose(bool disposing)
196        {
197            if (disposing)
198                handle.Close();
199        }
200
201        public void Dispose()
202        {
203            Dispose(true);
204            GC.SuppressFinalize(this);
205        }
206        #endregion
207
208        /// <summary>
209        /// The GenRandom function fills a buffer with cryptographically random bytes.
210        /// </summary>
211        /// <param name="buffer">Buffer to receive the returned data. This buffer
212        /// must be at least dwLen bytes in length.
213        ///
214        /// Optionally, the application can fill this buffer with data to use as
215        /// an auxiliary random seed.</param>
216        public static bool CryptGenRandom(byte[] buffer)
217        {
218            return NativeMethods.CryptGenRandom(instance.handle, (uint)buffer.Length, buffer);
219        }
220
221        /// <summary>
222        /// The HCRYPTPROV handle.
223        /// </summary>
224        private SafeCryptHandle handle;
225
226        /// <summary>
227        /// The global CryptAPI instance.
228        /// </summary>
229        private static CryptApi instance = new CryptApi();
230    }
231
232    internal class SafeCryptHandle : SafeHandle
233    {
234        public SafeCryptHandle()
235            : base(IntPtr.Zero, true)
236        {
237        }
238
239        public override bool IsInvalid
240        {
241            get { return handle == IntPtr.Zero; }
242        }
243
244        protected override bool ReleaseHandle()
245        {
246            NativeMethods.CryptReleaseContext(handle, 0u);
247            handle = IntPtr.Zero;
248            return true;
249        }
250    }
251
252    internal class SafeTokenHandle : SafeHandle
253    {
254        public SafeTokenHandle()
255            : base(IntPtr.Zero, true)
256        {
257        }
258
259        public override bool IsInvalid
260        {
261            get { return handle == IntPtr.Zero; }
262        }
263
264        protected override bool ReleaseHandle()
265        {
266            NativeMethods.CloseHandle(handle);
267            handle = IntPtr.Zero;
268            return true;
269        }
270    }
271}
Note: See TracBrowser for help on using the repository browser.