File: UnsafePeerToPeerMethods.cs

package info (click to toggle)
mono 6.12.0.199%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,296,836 kB
  • sloc: cs: 11,181,803; xml: 2,850,076; ansic: 699,709; cpp: 123,344; perl: 59,361; javascript: 30,841; asm: 21,853; makefile: 20,405; sh: 15,009; python: 4,839; pascal: 925; sql: 859; sed: 16; php: 1
file content (351 lines) | stat: -rw-r--r-- 15,280 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
//------------------------------------------------------------------------------
// <copyright file="Logging.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//------------------------------------------------------------------------------

using System.Security.Permissions;

namespace System.Net.PeerToPeer
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Win32.SafeHandles;
    using System.Security;
    using System.Runtime.InteropServices;
    using System.Runtime.ConstrainedExecution;
    using System.Threading;
    using System.Net.Sockets;
    using Microsoft.Win32;
    using System.Diagnostics;
    using System.IO;

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    internal struct PEER_PNRP_CLOUD_INFO
    {
        internal IntPtr pwzCloudName;
        internal UInt32 dwScope;
        internal UInt32 dwScopeId;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    internal struct PEER_PNRP_REGISTRATION_INFO
    {
        internal string pwszCloudName;
        internal string pwszPublishingIdentity;
        internal UInt32 cAddresses;
        internal IntPtr ArrayOfSOCKADDRIN6Pointers;
        internal ushort wport;
        internal string pwszComment;
        internal PEER_DATA payLoad;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    internal struct PEER_PNRP_ENDPOINT_INFO
    {
        internal IntPtr pwszPeerName;
        internal UInt32 cAddresses;
        internal IntPtr ArrayOfSOCKADDRIN6Pointers;
        internal IntPtr pwszComment;
        internal PEER_DATA payLoad;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    internal struct PEER_DATA
    {
        internal UInt32 cbPayload;
        internal IntPtr pbPayload;
    }

    [System.Security.SuppressUnmanagedCodeSecurityAttribute()]
    internal static class UnsafeP2PNativeMethods
    {
        internal const string P2P = "p2p.dll";

        [DllImport(P2P, CharSet = CharSet.Unicode)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        internal extern static void PeerFreeData(IntPtr dataToFree);

        [SecurityCritical]
        [DllImport(P2P, CharSet = CharSet.Unicode)]
        internal extern static Int32 PeerPnrpGetCloudInfo(out UInt32 pNumClouds, out SafePeerData pArrayOfClouds);

        [DllImport(P2P, CharSet = CharSet.Unicode)]
        internal extern static Int32 PeerPnrpStartup(ushort versionRequired);

        [SecurityCritical]
        [DllImport(P2P, CharSet = CharSet.Unicode)]
        internal extern static Int32
            PeerCreatePeerName(string identity, string classfier, out SafePeerData peerName);

        //[DllImport(P2P, CharSet = CharSet.Unicode)]
        //internal extern static Int32 PeerCreatePeerName(string identity, string classfier, out SafePeerData peerName);

        [SecurityCritical]
        [DllImport(P2P, CharSet = CharSet.Unicode)]
        internal extern static Int32 PeerIdentityGetDefault(out SafePeerData defaultIdentity);

        /*
        [DllImport(P2P, CharSet = CharSet.Unicode)]
        internal extern static Int32 PeerIdentityCreate(string classifier, string friendlyName, IntPtr hCryptoProv, out SafePeerData defaultIdentity);
        */
        [SecurityCritical]
        [DllImport(P2P, CharSet = CharSet.Unicode)]
        internal extern static Int32 PeerNameToPeerHostName(string peerName, out SafePeerData peerHostName);

        [SecurityCritical]
        [DllImport(P2P, CharSet = CharSet.Unicode)]
        internal extern static Int32 PeerHostNameToPeerName(string peerHostName, out SafePeerData peerName);

        [SecurityCritical]
        [DllImport(P2P, CharSet = CharSet.Unicode)]
        public extern static Int32 PeerPnrpRegister(string pcwzPeerName,
                                                    ref PEER_PNRP_REGISTRATION_INFO registrationInfo,
                                                    out SafePeerNameUnregister handle);

        [DllImport(P2P, CharSet = CharSet.Unicode)]
        public extern static Int32 PeerPnrpUnregister(IntPtr handle);

        [SecurityCritical]
        [DllImport(P2P, CharSet = CharSet.Unicode)]
        public extern static Int32 PeerPnrpUpdateRegistration(SafePeerNameUnregister hRegistration,
                                                    ref PEER_PNRP_REGISTRATION_INFO registrationInfo);


        [SecurityCritical]
        [DllImport(P2P, CharSet = CharSet.Unicode)]
        public extern static Int32 PeerPnrpResolve(string pcwzPeerNAme,
                                                   string pcwzCloudName,
                                                   ref UInt32 pcEndPoints,
                                                   out SafePeerData pEndPoints);

        [SecurityCritical]
        [DllImport(P2P, CharSet = CharSet.Unicode)]
        public extern static Int32 PeerPnrpStartResolve(string pcwzPeerNAme,
                                                   string pcwzCloudName,
                                                   UInt32 cEndPoints,
                                                   SafeWaitHandle hEvent,
                                                   out SafePeerNameEndResolve safePeerNameEndResolve);

        [SecurityCritical]
        [DllImport(P2P, CharSet = CharSet.Unicode)]
        public extern static Int32 PeerPnrpGetEndpoint(IntPtr Handle,
                                                       out SafePeerData pEndPoint);

        [DllImport(P2P, CharSet = CharSet.Unicode)]
        public extern static Int32 PeerPnrpEndResolve(IntPtr Handle);

        private static object s_InternalSyncObject;
        private static volatile bool s_Initialized;
        private const int PNRP_VERSION = 2;
        private static object InternalSyncObject {
            get {
                if (s_InternalSyncObject == null) {
                    object o = new object();
                    Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
                }
                return s_InternalSyncObject;
            }
        }
        // <SecurityKernel Critical="True" Ring="0">
        // <CallsSuppressUnmanagedCode Name="PeerPnrpStartup(UInt16):Int32" />
        // <SatisfiesLinkDemand Name="Marshal.GetExceptionForHR(System.Int32):System.Exception" />
        // </SecurityKernel>
        [System.Security.SecurityCritical]
        internal static void PnrpStartup()
        {
            if (!s_Initialized) {
                lock (InternalSyncObject) {
                    if (!s_Initialized) {
                        Int32 result = PeerPnrpStartup(PNRP_VERSION);
                        if (result != 0) {
                            throw new PeerToPeerException(SR.GetString(SR.Pnrp_StartupFailed), Marshal.GetExceptionForHR(result));
                        }
                        s_Initialized = true;
                    }
                }
            }
        } //end of method PnrpStartup

    }


    // <SecurityKernel Critical="True" Ring="0">
    // <SatisfiesLinkDemand Name="SafeHandleZeroOrMinusOneIsInvalid" />
    // </SecurityKernel>
#pragma warning disable 618    // Have not migrated to v4 transparency yet
    [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
#pragma warning restore 618
    [System.Security.SuppressUnmanagedCodeSecurityAttribute()]
    internal sealed class SafePeerData : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafePeerData() : base(true) { }
        //private SafePeerData(bool ownsHandle) : base(ownsHandle) { }
        internal string UnicodeString
        {
            get
            {
                return Marshal.PtrToStringUni(handle);
            }
        }
        protected override bool ReleaseHandle()
        {
            UnsafeP2PNativeMethods.PeerFreeData(handle);
            SetHandleAsInvalid();   //Mark it closed - This does not change the value of the handle it self
            SetHandle(IntPtr.Zero); //Mark it invalid - Change the value to Zero
            return true;
        }
    }


    // <SecurityKernel Critical="True" Ring="0">
    // <SatisfiesLinkDemand Name="SafeHandleZeroOrMinusOneIsInvalid" />
    // </SecurityKernel>
#pragma warning disable 618    // Have not migrated to v4 transparency yet
    [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
#pragma warning restore 618
    [System.Security.SuppressUnmanagedCodeSecurityAttribute()]
    internal sealed class SafePeerNameUnregister : SafeHandleZeroOrMinusOneIsInvalid
    {
        internal SafePeerNameUnregister() : base(true) { }
        //internal SafePeerNameUnregister(bool ownsHandle) : base(ownsHandle) { }
        protected override bool ReleaseHandle()
        {
            UnsafeP2PNativeMethods.PeerPnrpUnregister(handle);
            SetHandleAsInvalid(); //Mark it closed - This does not change the value of the handle it self
            SetHandle(IntPtr.Zero); //Mark it invalid - Change the value to Zero
            return true;
        }
    }

    // <SecurityKernel Critical="True" Ring="0">
    // <SatisfiesLinkDemand Name="SafeHandleZeroOrMinusOneIsInvalid" />
    // </SecurityKernel>
#pragma warning disable 618    // Have not migrated to v4 transparency yet
    [System.Security.SecurityCritical(System.Security.SecurityCriticalScope.Everything)]
#pragma warning restore 618
    [System.Security.SuppressUnmanagedCodeSecurityAttribute()]
    internal sealed class SafePeerNameEndResolve : SafeHandleZeroOrMinusOneIsInvalid
    {
        internal SafePeerNameEndResolve() : base(true) { }
        //internal SafePeerNameEndResolve(bool ownsHandle) : base(ownsHandle) { }
        protected override bool ReleaseHandle()
        {
            UnsafeP2PNativeMethods.PeerPnrpEndResolve(handle);
            SetHandleAsInvalid(); //Mark it closed - This does not change the value of the handle it self
            SetHandle(IntPtr.Zero); //Mark it invalid - Change the value to Zero
            return true;
        }
    }

    /// <remarks>
    /// Determines whether P2P is installed
    /// Note static constructors are guaranteed to be
    /// run in a thread safe manner. so no locks are necessary
    /// </remarks>
    internal static class PeerToPeerOSHelper
    {
        private const string OSInstallTypeRegKey = @"Software\Microsoft\Windows NT\CurrentVersion";
        private const string OSInstallTypeRegKeyPath = @"HKEY_LOCAL_MACHINE\" + OSInstallTypeRegKey;
        private const string OSInstallTypeRegName = "InstallationType";
        private const string InstallTypeStringServerCore = "Server Core";

        private static bool s_supportsP2P = false;
        private static SafeLoadLibrary s_P2PLibrary = null;
        // <SecurityKernel Critical="True" Ring="0">
        // <CallsSuppressUnmanagedCode Name="UnsafeSystemNativeMethods.GetProcAddress(System.Net.SafeLoadLibrary,System.String):System.IntPtr" />
        // <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
        // <ReferencesCritical Name="Field: s_P2PLibrary" Ring="1" />
        // <ReferencesCritical Name="Method: SafeLoadLibrary.LoadLibraryEx(System.String):System.Net.SafeLoadLibrary" Ring="1" />
        // </SecurityKernel>
        [System.Security.SecurityCritical]
        static PeerToPeerOSHelper() {

            if (IsSupportedOS()) {

                // if OS is supported, but p2p.dll is not available, P2P is not supported (original behavior)
                string dllFileName = Path.Combine(Environment.SystemDirectory, UnsafeP2PNativeMethods.P2P);
                s_P2PLibrary = SafeLoadLibrary.LoadLibraryEx(dllFileName);
                if (!s_P2PLibrary.IsInvalid) {
                    IntPtr Address = UnsafeSystemNativeMethods.GetProcAddress(s_P2PLibrary, "PeerCreatePeerName");
                    if (Address != IntPtr.Zero) {
                        s_supportsP2P = true;
                    }
                }
            }
            //else --> the SafeLoadLibrary would have already been marked
            //          closed by the LoadLibraryEx call above.
        }

        [SecurityCritical]
        private static bool IsSupportedOS()
        {
            // extend this method when adding further OS/install type restrictions

            // P2P is not supported on Server Core installation type
            if (IsServerCore()) {
                return false;
            }

            return true;
        }

        [SecurityCritical]
        [RegistryPermission(SecurityAction.Assert, Read = OSInstallTypeRegKeyPath)]
        private static bool IsServerCore()
        {
            // This code does the same as System.Net.ComNetOS.GetWindowsInstallType(). Since ComNetOS is internal and
            // we don't want to add InternalsVisibleToAttribute to System.dll, we have to duplicate the code.
            try {
                using (RegistryKey installTypeKey = Registry.LocalMachine.OpenSubKey(OSInstallTypeRegKey)) {
                    string installType = installTypeKey.GetValue(OSInstallTypeRegName) as string;

                    if (string.IsNullOrEmpty(installType)) {
                        Logging.P2PTraceSource.TraceEvent(TraceEventType.Warning, 0,
                            SR.GetString(SR.P2P_empty_osinstalltype, OSInstallTypeRegKey + "\\" + OSInstallTypeRegName));
                    }
                    else {
                        if (String.Compare(installType, InstallTypeStringServerCore, StringComparison.OrdinalIgnoreCase) == 0) {
                            return true;
                        }
                    }
                }
            }
            catch (UnauthorizedAccessException e) {
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Warning, 0,
                    SR.GetString(SR.P2P_cant_determine_osinstalltype, OSInstallTypeRegKey, e.Message));
            }
            catch (SecurityException e) {
                Logging.P2PTraceSource.TraceEvent(TraceEventType.Warning, 0,
                    SR.GetString(SR.P2P_cant_determine_osinstalltype, OSInstallTypeRegKey, e.Message));
            }

            return false;
        }

        internal static bool SupportsP2P {
            get {
                return s_supportsP2P;
            }
        }
        internal static IntPtr P2PModuleHandle
        {
            // <SecurityKernel Critical="True" Ring="0">
            // <SatisfiesLinkDemand Name="SafeHandle.get_IsClosed():System.Boolean" />
            // <SatisfiesLinkDemand Name="SafeHandle.get_IsInvalid():System.Boolean" />
            // <SatisfiesLinkDemand Name="SafeHandle.DangerousGetHandle():System.IntPtr" />
            // <ReferencesCritical Name="Field: s_P2PLibrary" Ring="1" />
            // </SecurityKernel>
            [System.Security.SecurityCritical]
            [SecurityPermissionAttribute(SecurityAction.LinkDemand, UnmanagedCode=true)]
            get
            {
                if (!s_P2PLibrary.IsClosed && !s_P2PLibrary.IsInvalid)
                    return s_P2PLibrary.DangerousGetHandle();
                return IntPtr.Zero;
            }
        }
    }

}