1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 
5 namespace System.ServiceModel.Channels
6 {
7     using System.Net;
8     using System.Net.Security;
9     using System.Net.WebSockets;
10     using System.Runtime;
11     using System.Security.Authentication;
12     using System.Security.Principal;
13     using System.ServiceModel;
14     using System.ServiceModel.Dispatcher;
15     using System.ServiceModel.Security;
16     using System.Text;
17     using System.Xml;
18 
19     internal static class TransactionFlowDefaults
20     {
21         internal const TransactionFlowOption IssuedTokens = TransactionFlowOption.NotAllowed;
22         internal const bool Transactions = false;
23         internal static TransactionProtocol TransactionProtocol = System.ServiceModel.TransactionProtocol.OleTransactions;
24         internal const string TransactionProtocolString = System.ServiceModel.Configuration.ConfigurationStrings.OleTransactions;
25     }
26 
27     static class EncoderDefaults
28     {
29         internal const int MaxReadPoolSize = 64;
30         internal const int MaxWritePoolSize = 16;
31 
32         internal const int MaxDepth = 32;
33         internal const int MaxStringContentLength = 8192;
34         internal const int MaxArrayLength = 16384;
35         internal const int MaxBytesPerRead = 4096;
36         internal const int MaxNameTableCharCount = 16384;
37 
38         internal const int BufferedReadDefaultMaxDepth = 128;
39         internal const int BufferedReadDefaultMaxStringContentLength = Int32.MaxValue;
40         internal const int BufferedReadDefaultMaxArrayLength = Int32.MaxValue;
41         internal const int BufferedReadDefaultMaxBytesPerRead = Int32.MaxValue;
42         internal const int BufferedReadDefaultMaxNameTableCharCount = Int32.MaxValue;
43 
44         internal const CompressionFormat DefaultCompressionFormat = CompressionFormat.None;
45 
46         internal static readonly XmlDictionaryReaderQuotas ReaderQuotas = new XmlDictionaryReaderQuotas();
47 
IsDefaultReaderQuotas(XmlDictionaryReaderQuotas quotas)48         internal static bool IsDefaultReaderQuotas(XmlDictionaryReaderQuotas quotas)
49         {
50             return quotas.ModifiedQuotas == 0x00;
51         }
52     }
53 
54     static class TextEncoderDefaults
55     {
56         internal static readonly Encoding Encoding = Encoding.GetEncoding(TextEncoderDefaults.EncodingString, new EncoderExceptionFallback(), new DecoderExceptionFallback());
57         internal const string EncodingString = "utf-8";
58         internal static readonly Encoding[] SupportedEncodings = new Encoding[] { Encoding.UTF8, Encoding.Unicode, Encoding.BigEndianUnicode };
59         internal const string MessageVersionString = System.ServiceModel.Configuration.ConfigurationStrings.Soap12WSAddressing10;
60         internal static readonly CharSetEncoding[] CharSetEncodings = new CharSetEncoding[]
61         {
62             new CharSetEncoding("utf-8", Encoding.UTF8),
63             new CharSetEncoding("utf-16LE", Encoding.Unicode),
64             new CharSetEncoding("utf-16BE", Encoding.BigEndianUnicode),
65             new CharSetEncoding("utf-16", null),   // Ignore.  Ambiguous charSet, so autodetect.
66             new CharSetEncoding(null, null),       // CharSet omitted, so autodetect.
67         };
68 
ValidateEncoding(Encoding encoding)69         internal static void ValidateEncoding(Encoding encoding)
70         {
71             string charSet = encoding.WebName;
72             Encoding[] supportedEncodings = SupportedEncodings;
73             for (int i = 0; i < supportedEncodings.Length; i++)
74             {
75                 if (charSet == supportedEncodings[i].WebName)
76                     return;
77             }
78             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MessageTextEncodingNotSupported, charSet), "encoding"));
79         }
80 
EncodingToCharSet(Encoding encoding)81         internal static string EncodingToCharSet(Encoding encoding)
82         {
83             string webName = encoding.WebName;
84             CharSetEncoding[] charSetEncodings = CharSetEncodings;
85             for (int i = 0; i < charSetEncodings.Length; i++)
86             {
87                 Encoding enc = charSetEncodings[i].Encoding;
88                 if (enc == null)
89                     continue;
90 
91                 if (enc.WebName == webName)
92                     return charSetEncodings[i].CharSet;
93             }
94             return null;
95         }
96 
TryGetEncoding(string charSet, out Encoding encoding)97         internal static bool TryGetEncoding(string charSet, out Encoding encoding)
98         {
99             CharSetEncoding[] charSetEncodings = CharSetEncodings;
100 
101             // Quick check for exact equality
102             for (int i = 0; i < charSetEncodings.Length; i++)
103             {
104                 if (charSetEncodings[i].CharSet == charSet)
105                 {
106                     encoding = charSetEncodings[i].Encoding;
107                     return true;
108                 }
109             }
110 
111             // Check for case insensative match
112             for (int i = 0; i < charSetEncodings.Length; i++)
113             {
114                 string compare = charSetEncodings[i].CharSet;
115                 if (compare == null)
116                     continue;
117 
118                 if (compare.Equals(charSet, StringComparison.OrdinalIgnoreCase))
119                 {
120                     encoding = charSetEncodings[i].Encoding;
121                     return true;
122                 }
123             }
124 
125             encoding = null;
126             return false;
127         }
128 
129         internal class CharSetEncoding
130         {
131             internal string CharSet;
132             internal Encoding Encoding;
133 
CharSetEncoding(string charSet, Encoding enc)134             internal CharSetEncoding(string charSet, Encoding enc)
135             {
136                 CharSet = charSet;
137                 Encoding = enc;
138             }
139         }
140     }
141 
142     static class MtomEncoderDefaults
143     {
144         internal const int MaxBufferSize = 65536;
145     }
146 
147     static class BinaryEncoderDefaults
148     {
149         internal static EnvelopeVersion EnvelopeVersion { get { return EnvelopeVersion.Soap12; } }
150         internal static BinaryVersion BinaryVersion { get { return BinaryVersion.Version1; } }
151         internal const int MaxSessionSize = 2048;
152     }
153 
154     static class MsmqDefaults
155     {
156         internal const MessageCredentialType DefaultClientCredentialType = MessageCredentialType.Windows;
157         internal const Uri CustomDeadLetterQueue = null;
158         internal const DeadLetterQueue DeadLetterQueue = System.ServiceModel.DeadLetterQueue.System;
159         internal const bool Durable = true;
160         internal const bool ExactlyOnce = true;
161         internal const bool ReceiveContextEnabled = true;
162         internal const int MaxRetryCycles = 2;
163         internal const int MaxPoolSize = 8;
164         internal const MsmqAuthenticationMode MsmqAuthenticationMode = System.ServiceModel.MsmqAuthenticationMode.WindowsDomain;
165         internal const MsmqEncryptionAlgorithm MsmqEncryptionAlgorithm = System.ServiceModel.MsmqEncryptionAlgorithm.RC4Stream;
166         internal const MsmqSecureHashAlgorithm DefaultMsmqSecureHashAlgorithm = System.ServiceModel.MsmqSecureHashAlgorithm.Sha256;
167         internal static MsmqSecureHashAlgorithm MsmqSecureHashAlgorithm { get { return LocalAppContextSwitches.UseSha1InMsmqEncryptionAlgorithm ? MsmqSecureHashAlgorithm.Sha1 : DefaultMsmqSecureHashAlgorithm; } }
168         internal const ProtectionLevel MsmqProtectionLevel = ProtectionLevel.Sign;
169         internal const ReceiveErrorHandling ReceiveErrorHandling = System.ServiceModel.ReceiveErrorHandling.Fault;
170         internal const int ReceiveRetryCount = 5;
171         internal const QueueTransferProtocol QueueTransferProtocol = System.ServiceModel.QueueTransferProtocol.Native;
172         internal static TimeSpan RetryCycleDelay { get { return TimeSpanHelper.FromMinutes(30, MsmqDefaults.RetryCycleDelayString); } }
173         internal const string RetryCycleDelayString = "00:30:00";
174         internal static TimeSpan TimeToLive { get { return TimeSpanHelper.FromDays(1, MsmqDefaults.TimeToLiveString); } }
175         internal const string TimeToLiveString = "1.00:00:00";
176         internal const bool UseActiveDirectory = false;
177         internal const bool UseSourceJournal = false;
178         internal const bool UseMsmqTracing = false;
179         internal static TimeSpan ValidityDuration { get { return TimeSpanHelper.FromMinutes(5, MsmqDefaults.ValidityDurationString); } }
180         internal const string ValidityDurationString = "00:05:00";
181         internal static SecurityAlgorithmSuite MessageSecurityAlgorithmSuite
182         {
183             get { return SecurityAlgorithmSuite.Default; }
184         }
185     }
186 
187     static class MsmqIntegrationDefaults
188     {
189         internal const System.ServiceModel.MsmqIntegration.MsmqMessageSerializationFormat SerializationFormat =
190             System.ServiceModel.MsmqIntegration.MsmqMessageSerializationFormat.Xml;
191     }
192 
193     static class TransportDefaults
194     {
195         internal const bool ExtractGroupsForWindowsAccounts = SspiSecurityTokenProvider.DefaultExtractWindowsGroupClaims;
196         internal const HostNameComparisonMode HostNameComparisonMode = System.ServiceModel.HostNameComparisonMode.Exact;
197         internal const TokenImpersonationLevel ImpersonationLevel = TokenImpersonationLevel.Identification;
198         internal const bool ManualAddressing = false;
199         internal const long MaxReceivedMessageSize = 65536;
200         internal const int MaxDrainSize = (int)MaxReceivedMessageSize;
201         internal const long MaxBufferPoolSize = 512 * 1024;
202         internal const int MaxBufferSize = (int)MaxReceivedMessageSize;
203         internal const bool RequireClientCertificate = false;
204         internal const int MaxFaultSize = MaxBufferSize;
205         internal const int MaxSecurityFaultSize = 16384;
206 
207         internal const SslProtocols OldDefaultSslProtocols = System.Security.Authentication.SslProtocols.Tls |
208                         System.Security.Authentication.SslProtocols.Tls11 |
209                         System.Security.Authentication.SslProtocols.Tls12;
210 
211         internal static SslProtocols SslProtocols
212         {
213             get
214             {
215                 if (LocalAppContextSwitches.DontEnableSystemDefaultTlsVersions)
216                 {
217                     return OldDefaultSslProtocols;
218                 }
219                 else
220                 {
221                     // SslProtocols.None uses the default SSL protocol from the OS.
222                     return System.Security.Authentication.SslProtocols.None;
223                 }
224             }
225         }
226 
227         // Calling CreateFault on an incoming message can expose some DoS-related security
228         // vulnerabilities when a service is in streaming mode.  See MB 47592 for more details.
229         // The RM protocol service does not use streaming mode on any of its bindings, so the
230         // message we have in hand has already passed the binding�s MaxReceivedMessageSize check.
231         // Custom transports can use RM so int.MaxValue is dangerous.
232         internal const int MaxRMFaultSize = (int)MaxReceivedMessageSize;
233 
GetDefaultMessageEncoderFactory()234         internal static MessageEncoderFactory GetDefaultMessageEncoderFactory()
235         {
236             return new BinaryMessageEncodingBindingElement().CreateMessageEncoderFactory();
237         }
238     }
239 
240     static class ConnectionOrientedTransportDefaults
241     {
242         internal const bool AllowNtlm = SspiSecurityTokenProvider.DefaultAllowNtlm;
243         internal const int ConnectionBufferSize = 8192;
244         internal const string ConnectionPoolGroupName = "default";
245         internal const HostNameComparisonMode HostNameComparisonMode = System.ServiceModel.HostNameComparisonMode.StrongWildcard;
246         internal static TimeSpan IdleTimeout { get { return TimeSpanHelper.FromMinutes(2, IdleTimeoutString); } }
247         internal const string IdleTimeoutString = "00:02:00";
248         internal static TimeSpan ChannelInitializationTimeout { get { return TimeSpanHelper.FromSeconds(30, ChannelInitializationTimeoutString); } }
249         internal const string ChannelInitializationTimeoutString = "00:00:30";
250         internal const int MaxContentTypeSize = 256;
251         internal const int MaxOutboundConnectionsPerEndpoint = 10;
252         internal const int MaxPendingConnectionsConst = 0;
253         internal static TimeSpan MaxOutputDelay { get { return TimeSpanHelper.FromMilliseconds(200, MaxOutputDelayString); } }
254         internal const string MaxOutputDelayString = "00:00:00.2";
255         internal const int MaxPendingAcceptsConst = 0;
256         internal const int MaxViaSize = 2048;
257         internal const ProtectionLevel ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
258         internal const TransferMode TransferMode = System.ServiceModel.TransferMode.Buffered;
259 
260         private const int MaxPendingConnectionsPre45 = 10;
261         private const int MaxPendingAcceptsPre45 = 1;
262 
GetMaxConnections()263         internal static int GetMaxConnections()
264         {
265             return GetMaxPendingConnections();
266         }
267 
GetMaxPendingConnections()268         internal static int GetMaxPendingConnections()
269         {
270             // OSEnvironmentHelper.IsApplicationTargeting45 checks for whether target Fx version is >= 4.5 despite its name
271             if (OSEnvironmentHelper.IsApplicationTargeting45)
272             {
273                 return 12 * OSEnvironmentHelper.ProcessorCount;
274             }
275 
276             return MaxPendingConnectionsPre45;
277         }
278 
GetMaxPendingAccepts()279         internal static int GetMaxPendingAccepts()
280         {
281             // OSEnvironmentHelper.IsApplicationTargeting45 checks for whether target Fx version is >= 4.5 despite its name
282             if (OSEnvironmentHelper.IsApplicationTargeting45)
283             {
284                 return 2 * OSEnvironmentHelper.ProcessorCount;
285             }
286 
287             return MaxPendingAcceptsPre45;
288         }
289     }
290 
291     static class TcpTransportDefaults
292     {
293         internal const int ListenBacklogConst = 0;
294         internal static TimeSpan ConnectionLeaseTimeout { get { return TimeSpanHelper.FromMinutes(5, TcpTransportDefaults.ConnectionLeaseTimeoutString); } }
295         internal const string ConnectionLeaseTimeoutString = "00:05:00";
296         internal const bool PortSharingEnabled = false;
297         internal const bool TeredoEnabled = false;
298 
299         private const int ListenBacklogPre45 = 10;
300 
GetListenBacklog()301         internal static int GetListenBacklog()
302         {
303             // OSEnvironmentHelper.IsApplicationTargeting45 checks for whether target Fx version is >= 4.5 despite its name
304             if (OSEnvironmentHelper.IsApplicationTargeting45)
305             {
306                 return 12 * OSEnvironmentHelper.ProcessorCount;
307             }
308 
309             return ListenBacklogPre45;
310         }
311     }
312 
313     static class ApplicationContainerSettingsDefaults
314     {
315         internal const string CurrentUserSessionDefaultString = "CurrentSession";
316         internal const string Session0ServiceSessionString = "ServiceSession";
317         internal const string PackageFullNameDefaultString = null;
318 
319         /// <summary>
320         /// The current session will be used for resource lookup.
321         /// </summary>
322         internal const int CurrentSession = -1;
323 
324         /// <summary>
325         /// Session 0 is the NT Service session
326         /// </summary>
327         internal const int ServiceSession = 0;
328     }
329 
330     static class HttpTransportDefaults
331     {
332         internal const bool AllowCookies = false;
333         internal const AuthenticationSchemes AuthenticationScheme = AuthenticationSchemes.Anonymous;
334         internal const bool BypassProxyOnLocal = false;
335         internal const bool DecompressionEnabled = true;
336         internal const HostNameComparisonMode HostNameComparisonMode = System.ServiceModel.HostNameComparisonMode.StrongWildcard;
337         internal const bool KeepAliveEnabled = true;
338         internal const Uri ProxyAddress = null;
339         internal const AuthenticationSchemes ProxyAuthenticationScheme = AuthenticationSchemes.Anonymous;
340         internal const string Realm = "";
341         internal const TransferMode TransferMode = System.ServiceModel.TransferMode.Buffered;
342         internal const bool UnsafeConnectionNtlmAuthentication = false;
343         internal const bool UseDefaultWebProxy = true;
344         internal const string UpgradeHeader = "Upgrade";
345         internal const string ConnectionHeader = "Connection";
346         internal const HttpMessageHandlerFactory MessageHandlerFactory = null;
347 
348         internal static TimeSpan RequestInitializationTimeout { get { return TimeSpanHelper.FromMilliseconds(0, RequestInitializationTimeoutString); } }
349         internal const string RequestInitializationTimeoutString = "00:00:00";
350 
351         // We use 0 as the default value of the MaxPendingAccepts property on HttpTransportBindingElement. In 4.5 we always
352         // use 10 under the hood if the default value is picked. In future releases, we could adjust the underlying default
353         // value when we have the dynamic expending pattern of BeginGetContext call implemented and the heap fragmentation issue
354         // from NCL layer solved.
355         const int PendingAcceptsConstant = 10;
356         internal const int DefaultMaxPendingAccepts = 0;
357         internal const int MaxPendingAcceptsUpperLimit = 100000;
GetEffectiveMaxPendingAccepts(int maxPendingAccepts)358         internal static int GetEffectiveMaxPendingAccepts(int maxPendingAccepts)
359         {
360             return maxPendingAccepts == HttpTransportDefaults.DefaultMaxPendingAccepts ?
361                                         PendingAcceptsConstant :
362                                         maxPendingAccepts;
363         }
364 
365 
GetDefaultWebSocketTransportSettings()366         internal static WebSocketTransportSettings GetDefaultWebSocketTransportSettings()
367         {
368             return new WebSocketTransportSettings();
369         }
370 
GetDefaultMessageEncoderFactory()371         internal static MessageEncoderFactory GetDefaultMessageEncoderFactory()
372         {
373             return new TextMessageEncoderFactory(MessageVersion.Default, TextEncoderDefaults.Encoding, EncoderDefaults.MaxReadPoolSize, EncoderDefaults.MaxWritePoolSize, EncoderDefaults.ReaderQuotas);
374         }
375 
376         internal static SecurityAlgorithmSuite MessageSecurityAlgorithmSuite
377         {
378             get { return SecurityAlgorithmSuite.Default; }
379         }
380     }
381 
382     static class NetTcpDefaults
383     {
384         internal const MessageCredentialType MessageSecurityClientCredentialType = MessageCredentialType.Windows;
385         internal const bool TransactionsEnabled = false;
386 
387         internal static TransactionProtocol TransactionProtocol
388         {
389             get { return TransactionProtocol.Default; }
390         }
391 
392         internal static SecurityAlgorithmSuite MessageSecurityAlgorithmSuite
393         {
394             get { return SecurityAlgorithmSuite.Default; }
395         }
396     }
397 
398     static class NetHttpDefaults
399     {
400         internal static TransactionProtocol TransactionProtocol
401         {
402             get { return TransactionProtocol.Default; }
403         }
404     }
405 
406     static class PeerTransportDefaults
407     {
408         internal const IPAddress ListenIPAddress = null;
409         internal const int Port = 0;
410         internal const string ResolverTypeString = null;
411         internal const PeerAuthenticationMode PeerNodeAuthenticationMode = PeerAuthenticationMode.Password;
412         internal const bool MessageAuthentication = false;
413 
414         internal static bool ResolverAvailable
415         {
416             get { return PnrpPeerResolver.IsPnrpAvailable; }
417         }
418 
419         internal static bool ResolverInstalled
420         {
421             get { return PnrpPeerResolver.IsPnrpInstalled; }
422         }
423 
424         internal static Type ResolverType
425         {
426             get { return typeof(PnrpPeerResolver); }
427         }
428 
429         internal static Type ResolverBindingElementType
430         {
431             get { return typeof(PnrpPeerResolverBindingElement); }
432         }
433 
CreateResolver()434         internal static PeerResolver CreateResolver()
435         {
436             return new PnrpPeerResolver();
437         }
438 
439     }
440 
441     static class OneWayDefaults
442     {
443         internal static TimeSpan IdleTimeout { get { return TimeSpanHelper.FromMinutes(2, IdleTimeoutString); } }
444         internal const string IdleTimeoutString = "00:02:00";
445         internal const int MaxOutboundChannelsPerEndpoint = 10;
446         internal static TimeSpan LeaseTimeout { get { return TimeSpanHelper.FromMinutes(10, LeaseTimeoutString); } }
447         internal const string LeaseTimeoutString = "00:10:00";
448         internal const int MaxAcceptedChannels = 10;
449         internal const bool PacketRoutable = false;
450     }
451 
452     static class ReliableSessionDefaults
453     {
454         internal const string AcknowledgementIntervalString = "00:00:00.2";
455         internal static TimeSpan AcknowledgementInterval { get { return TimeSpanHelper.FromMilliseconds(200, AcknowledgementIntervalString); } }
456         internal const bool Enabled = false;
457         internal const bool FlowControlEnabled = true;
458         internal const string InactivityTimeoutString = "00:10:00";
459         internal static TimeSpan InactivityTimeout { get { return TimeSpanHelper.FromMinutes(10, InactivityTimeoutString); } }
460         internal const int MaxPendingChannels = 4;
461         internal const int MaxRetryCount = 8;
462         internal const int MaxTransferWindowSize = 8;
463         internal const bool Ordered = true;
464         internal static ReliableMessagingVersion ReliableMessagingVersion { get { return System.ServiceModel.ReliableMessagingVersion.WSReliableMessagingFebruary2005; } }
465         internal const string ReliableMessagingVersionString = System.ServiceModel.Configuration.ConfigurationStrings.WSReliableMessagingFebruary2005;
466     }
467 
468     static class BasicHttpBindingDefaults
469     {
470         internal const BasicHttpMessageCredentialType MessageSecurityClientCredentialType = BasicHttpMessageCredentialType.UserName;
471         internal const WSMessageEncoding MessageEncoding = WSMessageEncoding.Text;
472         internal const TransferMode TransferMode = System.ServiceModel.TransferMode.Buffered;
473         internal static Encoding TextEncoding
474         {
475             get { return TextEncoderDefaults.Encoding; }
476         }
477     }
478 
479     static class WSHttpBindingDefaults
480     {
481         internal const WSMessageEncoding MessageEncoding = WSMessageEncoding.Text;
482     }
483 
484     static class WSDualHttpBindingDefaults
485     {
486         internal const WSMessageEncoding MessageEncoding = WSMessageEncoding.Text;
487     }
488 
489     static class WebSocketDefaults
490     {
491         internal const WebSocketTransportUsage TransportUsage = WebSocketTransportUsage.Never;
492         internal const bool CreateNotificationOnConnection = false;
493         internal const string DefaultKeepAliveIntervalString = "00:00:00";
494         internal static readonly TimeSpan DefaultKeepAliveInterval = TimeSpanHelper.FromSeconds(0, DefaultKeepAliveIntervalString);
495 
496         internal const int BufferSize = 16 * 1024;
497         internal const int MinReceiveBufferSize = 256;
498         internal const int MinSendBufferSize = 16;
499         internal const bool DisablePayloadMasking = false;
500         internal const WebSocketMessageType DefaultWebSocketMessageType = WebSocketMessageType.Binary;
501         internal const string SubProtocol = null;
502 
503         internal const int DefaultMaxPendingConnections = 0;
504         // We set this number larger than that in TCP transport because in WebSocket cases, the connection is already authenticated
505         // after we create the half-open channel. The default value is set as the default one as MaxConcurrentSessions to make it work
506         // well in burst scenarios.
507         internal static readonly int MaxPendingConnectionsCpuCount = ServiceThrottle.DefaultMaxConcurrentSessionsCpuCount;
508 
509         internal const string WebSocketConnectionHeaderValue = "Upgrade";
510         internal const string WebSocketUpgradeHeaderValue = "websocket";
511 
512         [System.Diagnostics.CodeAnalysis.SuppressMessage(FxCop.Category.Globalization, "CA1303",
513                             Justification = "These strings don't need to be localized.")]
WebSocketDefaults()514         static WebSocketDefaults()
515         {
516         }
517     }
518 
519     static class NetHttpBindingDefaults
520     {
521         internal const NetHttpMessageEncoding MessageEncoding = NetHttpMessageEncoding.Binary;
522         internal const WebSocketTransportUsage TransportUsage = WebSocketTransportUsage.WhenDuplex;
523     }
524 }
525