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