| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Channels
- {
- using System.Collections.ObjectModel;
- using System.Diagnostics;
- using System.IdentityModel.Policy;
- using System.IdentityModel.Selectors;
- using System.IdentityModel.Tokens;
- using System.IO;
- using System.Net;
- using System.Net.Cache;
- using System.Net.Security;
- using System.Runtime;
- using System.Runtime.CompilerServices;
- using System.Runtime.Diagnostics;
- using System.Security;
- using System.Security.Authentication.ExtendedProtection;
- using System.Security.Cryptography;
- using System.Security.Permissions;
- using System.Security.Principal;
- using System.ServiceModel;
- using System.ServiceModel.Description;
- using System.ServiceModel.Diagnostics;
- using System.ServiceModel.Diagnostics.Application;
- using System.ServiceModel.Security;
- using System.ServiceModel.Security.Tokens;
- using System.Text;
- using System.Threading;
- class HttpChannelFactory<TChannel>
- : TransportChannelFactory<TChannel>,
- IHttpTransportFactorySettings
- {
- static bool httpWebRequestWebPermissionDenied = false;
- static RequestCachePolicy requestCachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
- readonly ClientWebSocketFactory clientWebSocketFactory;
- bool allowCookies;
- AuthenticationSchemes authenticationScheme;
- HttpCookieContainerManager httpCookieContainerManager;
- // Double-checked locking pattern requires volatile for read/write synchronization
- volatile MruCache<Uri, Uri> credentialCacheUriPrefixCache;
- bool decompressionEnabled;
- // Double-checked locking pattern requires volatile for read/write synchronization
- [Fx.Tag.SecurityNote(Critical = "This cache stores strings that contain domain/user name/password. Must not be settable from PT code.")]
- [SecurityCritical]
- volatile MruCache<string, string> credentialHashCache;
- [Fx.Tag.SecurityNote(Critical = "This hash algorithm takes strings that contain domain/user name/password. Must not be settable from PT code.")]
- [SecurityCritical]
- HashAlgorithm hashAlgorithm;
- bool keepAliveEnabled;
- int maxBufferSize;
- IWebProxy proxy;
- WebProxyFactory proxyFactory;
- SecurityCredentialsManager channelCredentials;
- SecurityTokenManager securityTokenManager;
- TransferMode transferMode;
- ISecurityCapabilities securityCapabilities;
- WebSocketTransportSettings webSocketSettings;
- ConnectionBufferPool bufferPool;
- Lazy<string> webSocketSoapContentType;
- internal HttpChannelFactory(HttpTransportBindingElement bindingElement, BindingContext context)
- : base(bindingElement, context, HttpTransportDefaults.GetDefaultMessageEncoderFactory())
- {
- // validate setting interactions
- if (bindingElement.TransferMode == TransferMode.Buffered)
- {
- if (bindingElement.MaxReceivedMessageSize > int.MaxValue)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ArgumentOutOfRangeException("bindingElement.MaxReceivedMessageSize",
- SR.GetString(SR.MaxReceivedMessageSizeMustBeInIntegerRange)));
- }
- if (bindingElement.MaxBufferSize != bindingElement.MaxReceivedMessageSize)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("bindingElement",
- SR.GetString(SR.MaxBufferSizeMustMatchMaxReceivedMessageSize));
- }
- }
- else
- {
- if (bindingElement.MaxBufferSize > bindingElement.MaxReceivedMessageSize)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("bindingElement",
- SR.GetString(SR.MaxBufferSizeMustNotExceedMaxReceivedMessageSize));
- }
- }
- if (TransferModeHelper.IsRequestStreamed(bindingElement.TransferMode) &&
- bindingElement.AuthenticationScheme != AuthenticationSchemes.Anonymous)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("bindingElement", SR.GetString(
- SR.HttpAuthDoesNotSupportRequestStreaming));
- }
- this.allowCookies = bindingElement.AllowCookies;
- #pragma warning disable 618
- if (!this.allowCookies)
- {
- Collection<HttpCookieContainerBindingElement> httpCookieContainerBindingElements = context.BindingParameters.FindAll<HttpCookieContainerBindingElement>();
- if (httpCookieContainerBindingElements.Count > 1)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MultipleCCbesInParameters, typeof(HttpCookieContainerBindingElement))));
- }
- if (httpCookieContainerBindingElements.Count == 1)
- {
- this.allowCookies = true;
- context.BindingParameters.Remove<HttpCookieContainerBindingElement>();
- }
- }
- #pragma warning restore 618
- if (this.allowCookies)
- {
- this.httpCookieContainerManager = new HttpCookieContainerManager();
- }
- if (!bindingElement.AuthenticationScheme.IsSingleton())
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("value", SR.GetString(SR.HttpRequiresSingleAuthScheme,
- bindingElement.AuthenticationScheme));
- }
- this.authenticationScheme = bindingElement.AuthenticationScheme;
- this.decompressionEnabled = bindingElement.DecompressionEnabled;
- this.keepAliveEnabled = bindingElement.KeepAliveEnabled;
- this.maxBufferSize = bindingElement.MaxBufferSize;
- this.transferMode = bindingElement.TransferMode;
- if (bindingElement.Proxy != null)
- {
- this.proxy = bindingElement.Proxy;
- }
- else if (bindingElement.ProxyAddress != null)
- {
- if (bindingElement.UseDefaultWebProxy)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UseDefaultWebProxyCantBeUsedWithExplicitProxyAddress)));
- }
- if (bindingElement.ProxyAuthenticationScheme == AuthenticationSchemes.Anonymous)
- {
- this.proxy = new WebProxy(bindingElement.ProxyAddress, bindingElement.BypassProxyOnLocal);
- }
- else
- {
- this.proxy = null;
- this.proxyFactory =
- new WebProxyFactory(bindingElement.ProxyAddress, bindingElement.BypassProxyOnLocal,
- bindingElement.ProxyAuthenticationScheme);
- }
- }
- else if (!bindingElement.UseDefaultWebProxy)
- {
- this.proxy = new WebProxy();
- }
- this.channelCredentials = context.BindingParameters.Find<SecurityCredentialsManager>();
- this.securityCapabilities = bindingElement.GetProperty<ISecurityCapabilities>(context);
- this.webSocketSettings = WebSocketHelper.GetRuntimeWebSocketSettings(bindingElement.WebSocketSettings);
- int webSocketBufferSize = WebSocketHelper.ComputeClientBufferSize(this.MaxReceivedMessageSize);
- this.bufferPool = new ConnectionBufferPool(webSocketBufferSize);
- Collection<ClientWebSocketFactory> clientWebSocketFactories = context.BindingParameters.FindAll<ClientWebSocketFactory>();
- if (clientWebSocketFactories.Count > 1)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
- "context",
- SR.GetString(SR.MultipleClientWebSocketFactoriesSpecified, typeof(BindingContext).Name, typeof(ClientWebSocketFactory).Name));
- }
- else
- {
- this.clientWebSocketFactory = clientWebSocketFactories.Count == 0 ? null : clientWebSocketFactories[0];
- }
- this.webSocketSoapContentType = new Lazy<string>(() => { return this.MessageEncoderFactory.CreateSessionEncoder().ContentType; }, LazyThreadSafetyMode.ExecutionAndPublication);
- }
- public bool AllowCookies
- {
- get
- {
- return this.allowCookies;
- }
- }
- public AuthenticationSchemes AuthenticationScheme
- {
- get
- {
- return this.authenticationScheme;
- }
- }
- public bool DecompressionEnabled
- {
- get
- {
- return this.decompressionEnabled;
- }
- }
- public virtual bool IsChannelBindingSupportEnabled
- {
- get
- {
- return false;
- }
- }
- public bool KeepAliveEnabled
- {
- get
- {
- return this.keepAliveEnabled;
- }
- }
- public SecurityTokenManager SecurityTokenManager
- {
- get
- {
- return this.securityTokenManager;
- }
- }
- public int MaxBufferSize
- {
- get
- {
- return maxBufferSize;
- }
- }
- public IWebProxy Proxy
- {
- get
- {
- return this.proxy;
- }
- }
- public TransferMode TransferMode
- {
- get
- {
- return transferMode;
- }
- }
- public override string Scheme
- {
- get
- {
- return Uri.UriSchemeHttp;
- }
- }
- public WebSocketTransportSettings WebSocketSettings
- {
- get { return this.webSocketSettings; }
- }
- internal string WebSocketSoapContentType
- {
- get
- {
- return this.webSocketSoapContentType.Value;
- }
- }
- protected ConnectionBufferPool WebSocketBufferPool
- {
- get { return this.bufferPool; }
- }
- // must be called under lock (this.credentialHashCache)
- HashAlgorithm HashAlgorithm
- {
- [SecurityCritical]
- get
- {
- if (this.hashAlgorithm == null)
- {
- this.hashAlgorithm = CryptoHelper.CreateHashAlgorithm(SecurityAlgorithms.Sha1Digest);
- }
- else
- {
- this.hashAlgorithm.Initialize();
- }
- return this.hashAlgorithm;
- }
- }
- int IHttpTransportFactorySettings.MaxBufferSize
- {
- get { return MaxBufferSize; }
- }
- TransferMode IHttpTransportFactorySettings.TransferMode
- {
- get { return TransferMode; }
- }
- protected ClientWebSocketFactory ClientWebSocketFactory
- {
- get
- {
- return this.clientWebSocketFactory;
- }
- }
- public override T GetProperty<T>()
- {
- if (typeof(T) == typeof(ISecurityCapabilities))
- {
- return (T)(object)this.securityCapabilities;
- }
- if (typeof(T) == typeof(IHttpCookieContainerManager))
- {
- return (T)(object)this.GetHttpCookieContainerManager();
- }
- return base.GetProperty<T>();
- }
- [PermissionSet(SecurityAction.Demand, Unrestricted = true), SecuritySafeCritical]
- [MethodImpl(MethodImplOptions.NoInlining)]
- private HttpCookieContainerManager GetHttpCookieContainerManager()
- {
- return this.httpCookieContainerManager;
- }
- internal virtual SecurityMessageProperty CreateReplySecurityProperty(HttpWebRequest request,
- HttpWebResponse response)
- {
- // Don't pull in System.Authorization if we don't need to!
- if (!response.IsMutuallyAuthenticated)
- {
- return null;
- }
- return CreateMutuallyAuthenticatedReplySecurityProperty(response);
- }
- internal Exception CreateToMustEqualViaException(Uri to, Uri via)
- {
- return new ArgumentException(SR.GetString(SR.HttpToMustEqualVia, to, via));
- }
- [MethodImpl(MethodImplOptions.NoInlining)]
- SecurityMessageProperty CreateMutuallyAuthenticatedReplySecurityProperty(HttpWebResponse response)
- {
- string spn = AuthenticationManager.CustomTargetNameDictionary[response.ResponseUri.AbsoluteUri];
- if (spn == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.HttpSpnNotFound,
- response.ResponseUri)));
- }
- ReadOnlyCollection<IAuthorizationPolicy> spnPolicies = SecurityUtils.CreatePrincipalNameAuthorizationPolicies(spn);
- SecurityMessageProperty remoteSecurity = new SecurityMessageProperty();
- remoteSecurity.TransportToken = new SecurityTokenSpecification(null, spnPolicies);
- remoteSecurity.ServiceSecurityContext = new ServiceSecurityContext(spnPolicies);
- return remoteSecurity;
- }
- internal override int GetMaxBufferSize()
- {
- return MaxBufferSize;
- }
- SecurityTokenProviderContainer CreateAndOpenTokenProvider(TimeSpan timeout, AuthenticationSchemes authenticationScheme,
- EndpointAddress target, Uri via, ChannelParameterCollection channelParameters)
- {
- SecurityTokenProvider tokenProvider = null;
- switch (authenticationScheme)
- {
- case AuthenticationSchemes.Anonymous:
- break;
- case AuthenticationSchemes.Basic:
- tokenProvider = TransportSecurityHelpers.GetUserNameTokenProvider(this.SecurityTokenManager, target, via, this.Scheme, authenticationScheme, channelParameters);
- break;
- case AuthenticationSchemes.Negotiate:
- case AuthenticationSchemes.Ntlm:
- tokenProvider = TransportSecurityHelpers.GetSspiTokenProvider(this.SecurityTokenManager, target, via, this.Scheme, authenticationScheme, channelParameters);
- break;
- case AuthenticationSchemes.Digest:
- tokenProvider = TransportSecurityHelpers.GetDigestTokenProvider(this.SecurityTokenManager, target, via, this.Scheme, authenticationScheme, channelParameters);
- break;
- default:
- // The setter for this property should prevent this.
- throw Fx.AssertAndThrow("CreateAndOpenTokenProvider: Invalid authentication scheme");
- }
- SecurityTokenProviderContainer result;
- if (tokenProvider != null)
- {
- result = new SecurityTokenProviderContainer(tokenProvider);
- result.Open(timeout);
- }
- else
- {
- result = null;
- }
- return result;
- }
- protected virtual void ValidateCreateChannelParameters(EndpointAddress remoteAddress, Uri via)
- {
- base.ValidateScheme(via);
- if (this.MessageVersion.Addressing == AddressingVersion.None && remoteAddress.Uri != via)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateToMustEqualViaException(remoteAddress.Uri, via));
- }
- }
- protected override TChannel OnCreateChannel(EndpointAddress remoteAddress, Uri via)
- {
- EndpointAddress httpRemoteAddress = remoteAddress != null && WebSocketHelper.IsWebSocketUri(remoteAddress.Uri) ?
- new EndpointAddress(WebSocketHelper.NormalizeWsSchemeWithHttpScheme(remoteAddress.Uri), remoteAddress) :
- remoteAddress;
- Uri httpVia = WebSocketHelper.IsWebSocketUri(via) ? WebSocketHelper.NormalizeWsSchemeWithHttpScheme(via) : via;
- return this.OnCreateChannelCore(httpRemoteAddress, httpVia);
- }
- protected virtual TChannel OnCreateChannelCore(EndpointAddress remoteAddress, Uri via)
- {
- ValidateCreateChannelParameters(remoteAddress, via);
- this.ValidateWebSocketTransportUsage();
- if (typeof(TChannel) == typeof(IRequestChannel))
- {
- return (TChannel)(object)new HttpRequestChannel((HttpChannelFactory<IRequestChannel>)(object)this, remoteAddress, via, ManualAddressing);
- }
- else
- {
- return (TChannel)(object)new ClientWebSocketTransportDuplexSessionChannel((HttpChannelFactory<IDuplexSessionChannel>)(object)this, this.clientWebSocketFactory, remoteAddress, via, this.WebSocketBufferPool);
- }
- }
- protected void ValidateWebSocketTransportUsage()
- {
- Type channelType = typeof(TChannel);
- if (channelType == typeof(IRequestChannel) && this.WebSocketSettings.TransportUsage == WebSocketTransportUsage.Always)
- {
- throw FxTrace.Exception.AsError(new InvalidOperationException(SR.GetString(
- SR.WebSocketCannotCreateRequestClientChannelWithCertainWebSocketTransportUsage,
- typeof(TChannel),
- WebSocketTransportSettings.TransportUsageMethodName,
- typeof(WebSocketTransportSettings).Name,
- this.WebSocketSettings.TransportUsage)));
- }
- else if (channelType == typeof(IDuplexSessionChannel))
- {
- if (this.WebSocketSettings.TransportUsage == WebSocketTransportUsage.Never)
- {
- throw FxTrace.Exception.AsError(new InvalidOperationException(SR.GetString(
- SR.WebSocketCannotCreateRequestClientChannelWithCertainWebSocketTransportUsage,
- typeof(TChannel),
- WebSocketTransportSettings.TransportUsageMethodName,
- typeof(WebSocketTransportSettings).Name,
- this.WebSocketSettings.TransportUsage)));
- }
- else if (!WebSocketHelper.OSSupportsWebSockets() && this.ClientWebSocketFactory == null)
- {
- throw FxTrace.Exception.AsError(new PlatformNotSupportedException(SR.GetString(SR.WebSocketsClientSideNotSupported, typeof(ClientWebSocketFactory).FullName)));
- }
- }
- }
- [MethodImpl(MethodImplOptions.NoInlining)]
- void InitializeSecurityTokenManager()
- {
- if (this.channelCredentials == null)
- {
- this.channelCredentials = ClientCredentials.CreateDefaultCredentials();
- }
- this.securityTokenManager = this.channelCredentials.CreateSecurityTokenManager();
- }
- protected virtual bool IsSecurityTokenManagerRequired()
- {
- if (this.AuthenticationScheme != AuthenticationSchemes.Anonymous)
- {
- return true;
- }
- if (this.proxyFactory != null && this.proxyFactory.AuthenticationScheme != AuthenticationSchemes.Anonymous)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
- {
- this.OnOpen(timeout);
- return new CompletedAsyncResult(callback, state);
- }
- protected override void OnEndOpen(IAsyncResult result)
- {
- CompletedAsyncResult.End(result);
- }
- protected override void OnOpen(TimeSpan timeout)
- {
- if (IsSecurityTokenManagerRequired())
- {
- this.InitializeSecurityTokenManager();
- }
- if (this.AllowCookies &&
- !this.httpCookieContainerManager.IsInitialized) // We don't want to overwrite the CookieContainer if someone has set it already.
- {
- this.httpCookieContainerManager.CookieContainer = new CookieContainer();
- }
- // we need to make sure System.Net will buffer faults (sent as 500 requests) up to our allowed size
- // Their value is in Kbytes and ours is in bytes. We round up so that the KB value is large enough to
- // encompass our MaxReceivedMessageSize. See MB#20860 and related for details
- if (!httpWebRequestWebPermissionDenied && HttpWebRequest.DefaultMaximumErrorResponseLength != -1)
- {
- int MaxReceivedMessageSizeKbytes;
- if (MaxBufferSize >= (int.MaxValue - 1024)) // make sure NCL doesn't overflow
- {
- MaxReceivedMessageSizeKbytes = -1;
- }
- else
- {
- MaxReceivedMessageSizeKbytes = (int)(MaxBufferSize / 1024);
- if (MaxReceivedMessageSizeKbytes * 1024 < MaxBufferSize)
- {
- MaxReceivedMessageSizeKbytes++;
- }
- }
- if (MaxReceivedMessageSizeKbytes == -1
- || MaxReceivedMessageSizeKbytes > HttpWebRequest.DefaultMaximumErrorResponseLength)
- {
- try
- {
- HttpWebRequest.DefaultMaximumErrorResponseLength = MaxReceivedMessageSizeKbytes;
- }
- catch (SecurityException exception)
- {
- // CSDMain\33725 - setting DefaultMaximumErrorResponseLength should not fail HttpChannelFactory.OnOpen
- // if the user does not have the permission to do so.
- httpWebRequestWebPermissionDenied = true;
- DiagnosticUtility.TraceHandledException(exception, TraceEventType.Warning);
- }
- }
- }
- }
- protected override void OnClosed()
- {
- base.OnClosed();
- if (this.bufferPool != null)
- {
- this.bufferPool.Close();
- }
- }
- static internal void TraceResponseReceived(HttpWebResponse response, Message message, object receiver)
- {
- if (DiagnosticUtility.ShouldTraceVerbose)
- {
- if (response != null && response.ResponseUri != null)
- {
- TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.HttpResponseReceived, SR.GetString(SR.TraceCodeHttpResponseReceived), new StringTraceRecord("ResponseUri", response.ResponseUri.ToString()), receiver, null, message);
- }
- else
- {
- TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.HttpResponseReceived, SR.GetString(SR.TraceCodeHttpResponseReceived), receiver, message);
- }
- }
- }
- [Fx.Tag.SecurityNote(Critical = "Uses unsafe critical method AppendWindowsAuthenticationInfo to access the credential domain/user name/password.")]
- [SecurityCritical]
- [MethodImpl(MethodImplOptions.NoInlining)]
- string AppendWindowsAuthenticationInfo(string inputString, NetworkCredential credential,
- AuthenticationLevel authenticationLevel, TokenImpersonationLevel impersonationLevel)
- {
- return SecurityUtils.AppendWindowsAuthenticationInfo(inputString, credential, authenticationLevel, impersonationLevel);
- }
- protected virtual string OnGetConnectionGroupPrefix(HttpWebRequest httpWebRequest, SecurityTokenContainer clientCertificateToken)
- {
- return string.Empty;
- }
- internal static bool IsWindowsAuth(AuthenticationSchemes authScheme)
- {
- Fx.Assert(authScheme.IsSingleton(), "authenticationScheme used in an Http(s)ChannelFactory must be a singleton value.");
- return authScheme == AuthenticationSchemes.Negotiate ||
- authScheme == AuthenticationSchemes.Ntlm;
- }
- [Fx.Tag.SecurityNote(Critical = "Uses unsafe critical method AppendWindowsAuthenticationInfo to access the credential domain/user name/password.",
- Safe = "Uses the domain/user name/password to store and compute a hash. The store is SecurityCritical. The hash leaks but" +
- "the hash cannot be reversed to the domain/user name/password.")]
- [SecuritySafeCritical]
- string GetConnectionGroupName(HttpWebRequest httpWebRequest, NetworkCredential credential, AuthenticationLevel authenticationLevel,
- TokenImpersonationLevel impersonationLevel, SecurityTokenContainer clientCertificateToken)
- {
- if (this.credentialHashCache == null)
- {
- lock (ThisLock)
- {
- if (this.credentialHashCache == null)
- {
- this.credentialHashCache = new MruCache<string, string>(5);
- }
- }
- }
- // The following line is a work-around for VSWhidbey 558605. In particular, we need to isolate our
- // connection groups based on whether we are streaming the request.
- string inputString = TransferModeHelper.IsRequestStreamed(this.TransferMode) ? "streamed" : string.Empty;
- if (IsWindowsAuth(this.AuthenticationScheme))
- {
- // for NTLM & Negotiate, System.Net doesn't pool connections by default. This is because
- // IIS doesn't re-authenticate NTLM connections (made for a perf reason), and HttpWebRequest
- // shared connections among multiple callers.
- // This causes Indigo a performance problem in turn. We mitigate this by (1) enabling
- // connection sharing for NTLM connections on our pool, and (2) scoping the pool we use
- // to be based on the NetworkCredential that is being used to authenticate the connection.
- // Therefore we're only sharing connections among the same Credential.
- // Setting this will fail in partial trust, and that's ok since this is an optimization.
- if (!httpWebRequestWebPermissionDenied)
- {
- try
- {
- httpWebRequest.UnsafeAuthenticatedConnectionSharing = true;
- }
- catch (SecurityException e)
- {
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- httpWebRequestWebPermissionDenied = true;
- }
- }
- inputString = AppendWindowsAuthenticationInfo(inputString, credential, authenticationLevel, impersonationLevel);
- }
- string prefix = this.OnGetConnectionGroupPrefix(httpWebRequest, clientCertificateToken);
- inputString = string.Concat(prefix, inputString);
- string credentialHash = null;
- // we have to lock around each call to TryGetValue since the MruCache modifies the
- // contents of it's mruList in a single-threaded manner underneath TryGetValue
- if (!string.IsNullOrEmpty(inputString))
- {
- lock (this.credentialHashCache)
- {
- if (!this.credentialHashCache.TryGetValue(inputString, out credentialHash))
- {
- byte[] inputBytes = new UTF8Encoding().GetBytes(inputString);
- byte[] digestBytes = this.HashAlgorithm.ComputeHash(inputBytes);
- credentialHash = Convert.ToBase64String(digestBytes);
- this.credentialHashCache.Add(inputString, credentialHash);
- }
- }
- }
- return credentialHash;
- }
- Uri GetCredentialCacheUriPrefix(Uri via)
- {
- Uri result;
- if (this.credentialCacheUriPrefixCache == null)
- {
- lock (ThisLock)
- {
- if (this.credentialCacheUriPrefixCache == null)
- {
- this.credentialCacheUriPrefixCache = new MruCache<Uri, Uri>(10);
- }
- }
- }
- lock (this.credentialCacheUriPrefixCache)
- {
- if (!this.credentialCacheUriPrefixCache.TryGetValue(via, out result))
- {
- result = new UriBuilder(via.Scheme, via.Host, via.Port).Uri;
- this.credentialCacheUriPrefixCache.Add(via, result);
- }
- }
- return result;
- }
- // core code for creating an HttpWebRequest
- HttpWebRequest GetWebRequest(EndpointAddress to, Uri via, NetworkCredential credential,
- TokenImpersonationLevel impersonationLevel, AuthenticationLevel authenticationLevel,
- SecurityTokenProviderContainer proxyTokenProvider, SecurityTokenContainer clientCertificateToken, TimeSpan timeout, bool isWebSocketRequest)
- {
- Uri httpWebRequestUri = isWebSocketRequest ? WebSocketHelper.GetWebSocketUri(via) : via;
- HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(httpWebRequestUri);
- Fx.Assert(httpWebRequest.Method.Equals("GET", StringComparison.OrdinalIgnoreCase), "the default HTTP method of HttpWebRequest should be 'Get'.");
- if (!isWebSocketRequest)
- {
- httpWebRequest.Method = "POST";
- if (TransferModeHelper.IsRequestStreamed(TransferMode))
- {
- httpWebRequest.SendChunked = true;
- httpWebRequest.AllowWriteStreamBuffering = false;
- }
- else
- {
- httpWebRequest.AllowWriteStreamBuffering = true;
- }
- }
- httpWebRequest.CachePolicy = requestCachePolicy;
- httpWebRequest.KeepAlive = this.keepAliveEnabled;
- if (this.decompressionEnabled)
- {
- httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
- }
- else
- {
- httpWebRequest.AutomaticDecompression = DecompressionMethods.None;
- }
- if (credential != null)
- {
- CredentialCache credentials = new CredentialCache();
- credentials.Add(this.GetCredentialCacheUriPrefix(via),
- AuthenticationSchemesHelper.ToString(this.authenticationScheme), credential);
- httpWebRequest.Credentials = credentials;
- }
- httpWebRequest.AuthenticationLevel = authenticationLevel;
- httpWebRequest.ImpersonationLevel = impersonationLevel;
- string connectionGroupName = GetConnectionGroupName(httpWebRequest, credential, authenticationLevel, impersonationLevel, clientCertificateToken);
- X509CertificateEndpointIdentity remoteCertificateIdentity = to.Identity as X509CertificateEndpointIdentity;
- if (remoteCertificateIdentity != null)
- {
- connectionGroupName = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}[{1}]", connectionGroupName, remoteCertificateIdentity.Certificates[0].Thumbprint);
- }
- if (!string.IsNullOrEmpty(connectionGroupName))
- {
- httpWebRequest.ConnectionGroupName = connectionGroupName;
- }
- if (AuthenticationScheme == AuthenticationSchemes.Basic)
- {
- httpWebRequest.PreAuthenticate = true;
- }
- if (this.proxy != null)
- {
- httpWebRequest.Proxy = this.proxy;
- }
- else if (this.proxyFactory != null)
- {
- httpWebRequest.Proxy = this.proxyFactory.CreateWebProxy(httpWebRequest, proxyTokenProvider, timeout);
- }
- if (this.AllowCookies)
- {
- httpWebRequest.CookieContainer = this.httpCookieContainerManager.CookieContainer;
- }
- // we do this at the end so that we access the correct ServicePoint
- httpWebRequest.ServicePoint.UseNagleAlgorithm = false;
- return httpWebRequest;
- }
- void ApplyManualAddressing(ref EndpointAddress to, ref Uri via, Message message)
- {
- if (ManualAddressing)
- {
- Uri toHeader = message.Headers.To;
- if (toHeader == null)
- {
- throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ManualAddressingRequiresAddressedMessages)), message);
- }
- to = new EndpointAddress(toHeader);
- if (this.MessageVersion.Addressing == AddressingVersion.None)
- {
- via = toHeader;
- }
- }
- // now apply query string property
- object property;
- if (message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out property))
- {
- HttpRequestMessageProperty requestProperty = (HttpRequestMessageProperty)property;
- if (!string.IsNullOrEmpty(requestProperty.QueryString))
- {
- UriBuilder uriBuilder = new UriBuilder(via);
- if (requestProperty.QueryString.StartsWith("?", StringComparison.Ordinal))
- {
- uriBuilder.Query = requestProperty.QueryString.Substring(1);
- }
- else
- {
- uriBuilder.Query = requestProperty.QueryString;
- }
- via = uriBuilder.Uri;
- }
- }
- }
- [MethodImpl(MethodImplOptions.NoInlining)]
- void CreateAndOpenTokenProvidersCore(EndpointAddress to, Uri via, ChannelParameterCollection channelParameters, TimeSpan timeout, out SecurityTokenProviderContainer tokenProvider, out SecurityTokenProviderContainer proxyTokenProvider)
- {
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- tokenProvider = CreateAndOpenTokenProvider(timeoutHelper.RemainingTime(), this.AuthenticationScheme, to, via, channelParameters);
- if (this.proxyFactory != null)
- {
- proxyTokenProvider = CreateAndOpenTokenProvider(timeoutHelper.RemainingTime(), this.proxyFactory.AuthenticationScheme, to, via, channelParameters);
- }
- else
- {
- proxyTokenProvider = null;
- }
- }
- internal void CreateAndOpenTokenProviders(EndpointAddress to, Uri via, ChannelParameterCollection channelParameters, TimeSpan timeout, out SecurityTokenProviderContainer tokenProvider, out SecurityTokenProviderContainer proxyTokenProvider)
- {
- if (!IsSecurityTokenManagerRequired())
- {
- tokenProvider = null;
- proxyTokenProvider = null;
- }
- else
- {
- CreateAndOpenTokenProvidersCore(to, via, channelParameters, timeout, out tokenProvider, out proxyTokenProvider);
- }
- }
- internal HttpWebRequest GetWebRequest(EndpointAddress to, Uri via, SecurityTokenProviderContainer tokenProvider,
- SecurityTokenProviderContainer proxyTokenProvider, SecurityTokenContainer clientCertificateToken, TimeSpan timeout, bool isWebSocketRequest)
- {
- TokenImpersonationLevel impersonationLevel;
- AuthenticationLevel authenticationLevel;
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- NetworkCredential credential = HttpChannelUtilities.GetCredential(this.authenticationScheme,
- tokenProvider, timeoutHelper.RemainingTime(), out impersonationLevel, out authenticationLevel);
- return GetWebRequest(to, via, credential, impersonationLevel, authenticationLevel, proxyTokenProvider, clientCertificateToken, timeoutHelper.RemainingTime(), isWebSocketRequest);
- }
- internal static bool MapIdentity(EndpointAddress target, AuthenticationSchemes authenticationScheme)
- {
- if ((target.Identity == null) || (target.Identity is X509CertificateEndpointIdentity))
- {
- return false;
- }
- return IsWindowsAuth(authenticationScheme);
- }
- bool MapIdentity(EndpointAddress target)
- {
- return MapIdentity(target, this.AuthenticationScheme);
- }
- protected class HttpRequestChannel : RequestChannel
- {
- // Double-checked locking pattern requires volatile for read/write synchronization
- volatile bool cleanupIdentity;
- HttpChannelFactory<IRequestChannel> factory;
- SecurityTokenProviderContainer tokenProvider;
- SecurityTokenProviderContainer proxyTokenProvider;
- ServiceModelActivity activity = null;
- ChannelParameterCollection channelParameters;
- public HttpRequestChannel(HttpChannelFactory<IRequestChannel> factory, EndpointAddress to, Uri via, bool manualAddressing)
- : base(factory, to, via, manualAddressing)
- {
- this.factory = factory;
- }
- public HttpChannelFactory<IRequestChannel> Factory
- {
- get { return this.factory; }
- }
- internal ServiceModelActivity Activity
- {
- get { return this.activity; }
- }
- protected ChannelParameterCollection ChannelParameters
- {
- get
- {
- return this.channelParameters;
- }
- }
- public override T GetProperty<T>()
- {
- if (typeof(T) == typeof(ChannelParameterCollection))
- {
- if (this.State == CommunicationState.Created)
- {
- lock (ThisLock)
- {
- if (this.channelParameters == null)
- {
- this.channelParameters = new ChannelParameterCollection();
- }
- }
- }
- return (T)(object)this.channelParameters;
- }
- else
- {
- return base.GetProperty<T>();
- }
- }
- void PrepareOpen()
- {
- if (Factory.MapIdentity(RemoteAddress))
- {
- lock (ThisLock)
- {
- cleanupIdentity = HttpTransportSecurityHelpers.AddIdentityMapping(Via, RemoteAddress);
- }
- }
- }
- void CreateAndOpenTokenProviders(TimeSpan timeout)
- {
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- if (!ManualAddressing)
- {
- Factory.CreateAndOpenTokenProviders(this.RemoteAddress, this.Via, this.channelParameters, timeoutHelper.RemainingTime(), out this.tokenProvider, out this.proxyTokenProvider);
- }
- }
- void CloseTokenProviders(TimeSpan timeout)
- {
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- if (this.tokenProvider != null)
- {
- tokenProvider.Close(timeoutHelper.RemainingTime());
- }
- if (this.proxyTokenProvider != null)
- {
- proxyTokenProvider.Close(timeoutHelper.RemainingTime());
- }
- }
- void AbortTokenProviders()
- {
- if (this.tokenProvider != null)
- {
- tokenProvider.Abort();
- }
- if (this.proxyTokenProvider != null)
- {
- proxyTokenProvider.Abort();
- }
- }
- protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
- {
- PrepareOpen();
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- CreateAndOpenTokenProviders(timeoutHelper.RemainingTime());
- return new CompletedAsyncResult(callback, state);
- }
- protected override void OnOpen(TimeSpan timeout)
- {
- PrepareOpen();
- CreateAndOpenTokenProviders(timeout);
- }
- protected override void OnEndOpen(IAsyncResult result)
- {
- CompletedAsyncResult.End(result);
- }
- void PrepareClose(bool aborting)
- {
- if (cleanupIdentity)
- {
- lock (ThisLock)
- {
- if (cleanupIdentity)
- {
- cleanupIdentity = false;
- HttpTransportSecurityHelpers.RemoveIdentityMapping(Via, RemoteAddress, !aborting);
- }
- }
- }
- }
- protected override void OnAbort()
- {
- PrepareClose(true);
- AbortTokenProviders();
- base.OnAbort();
- }
- protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
- {
- IAsyncResult retval = null;
- using (ServiceModelActivity.BoundOperation(this.activity))
- {
- PrepareClose(false);
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- CloseTokenProviders(timeoutHelper.RemainingTime());
- retval = base.BeginWaitForPendingRequests(timeoutHelper.RemainingTime(), callback, state);
- }
- ServiceModelActivity.Stop(this.activity);
- return retval;
- }
- protected override void OnEndClose(IAsyncResult result)
- {
- using (ServiceModelActivity.BoundOperation(this.activity))
- {
- base.EndWaitForPendingRequests(result);
- }
- ServiceModelActivity.Stop(this.activity);
- }
- protected override void OnClose(TimeSpan timeout)
- {
- using (ServiceModelActivity.BoundOperation(this.activity))
- {
- PrepareClose(false);
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- CloseTokenProviders(timeoutHelper.RemainingTime());
- base.WaitForPendingRequests(timeoutHelper.RemainingTime());
- }
- ServiceModelActivity.Stop(this.activity);
- }
- protected override IAsyncRequest CreateAsyncRequest(Message message, AsyncCallback callback, object state)
- {
- if (DiagnosticUtility.ShouldUseActivity && this.activity == null)
- {
- this.activity = ServiceModelActivity.CreateActivity();
- if (null != FxTrace.Trace)
- {
- FxTrace.Trace.TraceTransfer(this.activity.Id);
- }
- ServiceModelActivity.Start(this.activity, SR.GetString(SR.ActivityReceiveBytes, this.RemoteAddress.Uri.ToString()), ActivityType.ReceiveBytes);
- }
- return new HttpChannelAsyncRequest(this, callback, state);
- }
- protected override IRequest CreateRequest(Message message)
- {
- return new HttpChannelRequest(this, Factory);
- }
- public virtual HttpWebRequest GetWebRequest(EndpointAddress to, Uri via, ref TimeoutHelper timeoutHelper)
- {
- return GetWebRequest(to, via, null, ref timeoutHelper);
- }
- protected HttpWebRequest GetWebRequest(EndpointAddress to, Uri via, SecurityTokenContainer clientCertificateToken, ref TimeoutHelper timeoutHelper)
- {
- SecurityTokenProviderContainer webRequestTokenProvider;
- SecurityTokenProviderContainer webRequestProxyTokenProvider;
- if (this.ManualAddressing)
- {
- this.Factory.CreateAndOpenTokenProviders(to, via, this.channelParameters, timeoutHelper.RemainingTime(),
- out webRequestTokenProvider, out webRequestProxyTokenProvider);
- }
- else
- {
- webRequestTokenProvider = this.tokenProvider;
- webRequestProxyTokenProvider = this.proxyTokenProvider;
- }
- try
- {
- return this.Factory.GetWebRequest(to, via, webRequestTokenProvider, webRequestProxyTokenProvider, clientCertificateToken, timeoutHelper.RemainingTime(), false);
- }
- finally
- {
- if (this.ManualAddressing)
- {
- if (webRequestTokenProvider != null)
- {
- webRequestTokenProvider.Abort();
- }
- if (webRequestProxyTokenProvider != null)
- {
- webRequestProxyTokenProvider.Abort();
- }
- }
- }
- }
- protected IAsyncResult BeginGetWebRequest(
- EndpointAddress to, Uri via, SecurityTokenContainer clientCertificateToken, ref TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
- {
- return new GetWebRequestAsyncResult(this, to, via, clientCertificateToken, ref timeoutHelper, callback, state);
- }
- public virtual IAsyncResult BeginGetWebRequest(
- EndpointAddress to, Uri via, ref TimeoutHelper timeoutHelper, AsyncCallback callback, object state)
- {
- return BeginGetWebRequest(to, via, null, ref timeoutHelper, callback, state);
- }
- public virtual HttpWebRequest EndGetWebRequest(IAsyncResult result)
- {
- return GetWebRequestAsyncResult.End(result);
- }
- public virtual bool WillGetWebRequestCompleteSynchronously()
- {
- return ((this.tokenProvider == null) && !Factory.ManualAddressing);
- }
- internal virtual void OnWebRequestCompleted(HttpWebRequest request)
- {
- // empty
- }
- class HttpChannelRequest : IRequest
- {
- HttpRequestChannel channel;
- HttpChannelFactory<IRequestChannel> factory;
- EndpointAddress to;
- Uri via;
- HttpWebRequest webRequest;
- HttpAbortReason abortReason;
- ChannelBinding channelBinding;
- int webRequestCompleted;
- EventTraceActivity eventTraceActivity;
- public HttpChannelRequest(HttpRequestChannel channel, HttpChannelFactory<IRequestChannel> factory)
- {
- this.channel = channel;
- this.to = channel.RemoteAddress;
- this.via = channel.Via;
- this.factory = factory;
- }
- public void SendRequest(Message message, TimeSpan timeout)
- {
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- factory.ApplyManualAddressing(ref this.to, ref this.via, message);
- this.webRequest = channel.GetWebRequest(this.to, this.via, ref timeoutHelper);
- Message request = message;
- try
- {
- if (channel.State != CommunicationState.Opened)
- {
- // if we were aborted while getting our request or doing correlation,
- // we need to abort the web request and bail
- Cleanup();
- channel.ThrowIfDisposedOrNotOpen();
- }
- HttpChannelUtilities.SetRequestTimeout(this.webRequest, timeoutHelper.RemainingTime());
- HttpOutput httpOutput = HttpOutput.CreateHttpOutput(this.webRequest, this.factory, request, this.factory.IsChannelBindingSupportEnabled);
- bool success = false;
- try
- {
- httpOutput.Send(timeoutHelper.RemainingTime());
- this.channelBinding = httpOutput.TakeChannelBinding();
- httpOutput.Close();
- success = true;
- if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled)
- {
- this.eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message);
- if (TD.MessageSentByTransportIsEnabled())
- {
- TD.MessageSentByTransport(eventTraceActivity, this.to.Uri.AbsoluteUri);
- }
- }
- }
- finally
- {
- if (!success)
- {
- httpOutput.Abort(HttpAbortReason.Aborted);
- }
- }
- }
- finally
- {
- if (!object.ReferenceEquals(request, message))
- {
- request.Close();
- }
- }
- }
- void Cleanup()
- {
- if (this.webRequest != null)
- {
- HttpChannelUtilities.AbortRequest(this.webRequest);
- this.TryCompleteWebRequest(this.webRequest);
- }
- ChannelBindingUtility.Dispose(ref this.channelBinding);
- }
- public void Abort(RequestChannel channel)
- {
- Cleanup();
- abortReason = HttpAbortReason.Aborted;
- }
- public void Fault(RequestChannel channel)
- {
- Cleanup();
- }
- [System.Diagnostics.CodeAnalysis.SuppressMessage(FxCop.Category.ReliabilityBasic, "Reliability104",
- Justification = "This is an old method from previous release.")]
- public Message WaitForReply(TimeSpan timeout)
- {
- if (TD.HttpResponseReceiveStartIsEnabled())
- {
- TD.HttpResponseReceiveStart(this.eventTraceActivity);
- }
- HttpWebResponse response = null;
- WebException responseException = null;
- try
- {
- try
- {
- response = (HttpWebResponse)webRequest.GetResponse();
- }
- catch (NullReferenceException nullReferenceException)
- {
- // workaround for Whidbey bug #558605 - only happens in streamed case.
- if (TransferModeHelper.IsRequestStreamed(this.factory.transferMode))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- HttpChannelUtilities.CreateNullReferenceResponseException(nullReferenceException));
- }
- throw;
- }
- if (TD.MessageReceivedByTransportIsEnabled())
- {
- TD.MessageReceivedByTransport(this.eventTraceActivity ?? EventTraceActivity.Empty,
- response.ResponseUri != null ? response.ResponseUri.AbsoluteUri : string.Empty,
- EventTraceActivity.GetActivityIdFromThread());
- }
- if (DiagnosticUtility.ShouldTraceVerbose)
- {
- HttpChannelFactory<TChannel>.TraceResponseReceived(response, null, this);
- }
- }
- catch (WebException webException)
- {
- responseException = webException;
- response = HttpChannelUtilities.ProcessGetResponseWebException(webException, this.webRequest,
- abortReason);
- }
- HttpInput httpInput = HttpChannelUtilities.ValidateRequestReplyResponse(this.webRequest, response,
- this.factory, responseException, this.channelBinding);
- this.channelBinding = null;
- Message replyMessage = null;
- if (httpInput != null)
- {
- Exception exception = null;
- replyMessage = httpInput.ParseIncomingMessage(out exception);
- Fx.Assert(exception == null, "ParseIncomingMessage should not set an exception after parsing a response message.");
- if (replyMessage != null)
- {
- HttpChannelUtilities.AddReplySecurityProperty(this.factory, this.webRequest, response,
- replyMessage);
- if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled && (eventTraceActivity != null))
- {
- EventTraceActivityHelper.TryAttachActivity(replyMessage, eventTraceActivity);
- }
- }
- }
- this.TryCompleteWebRequest(this.webRequest);
- return replyMessage;
- }
- public void OnReleaseRequest()
- {
- this.TryCompleteWebRequest(this.webRequest);
- }
- void TryCompleteWebRequest(HttpWebRequest request)
- {
- if (request == null)
- {
- return;
- }
- if (Interlocked.CompareExchange(ref this.webRequestCompleted, 1, 0) == 0)
- {
- this.channel.OnWebRequestCompleted(request);
- }
- }
- }
- class HttpChannelAsyncRequest : TraceAsyncResult, IAsyncRequest
- {
- static AsyncCallback onProcessIncomingMessage = Fx.ThunkCallback(new AsyncCallback(OnParseIncomingMessage));
- static AsyncCallback onGetResponse = Fx.ThunkCallback(new AsyncCallback(OnGetResponse));
- static AsyncCallback onGetWebRequestCompleted;
- static AsyncCallback onSend = Fx.ThunkCallback(new AsyncCallback(OnSend));
- static Action<object> onSendTimeout;
- ChannelBinding channelBinding;
- HttpChannelFactory<IRequestChannel> factory;
- HttpRequestChannel channel;
- HttpOutput httpOutput;
- HttpInput httpInput;
- Message message;
- Message requestMessage;
- Message replyMessage;
- HttpWebResponse response;
- HttpWebRequest request;
- object sendLock = new object();
- IOThreadTimer sendTimer;
- TimeoutHelper timeoutHelper;
- EndpointAddress to;
- Uri via;
- HttpAbortReason abortReason;
- int webRequestCompleted;
- EventTraceActivity eventTraceActivity;
- public HttpChannelAsyncRequest(HttpRequestChannel channel, AsyncCallback callback, object state)
- : base(callback, state)
- {
- this.channel = channel;
- this.to = channel.RemoteAddress;
- this.via = channel.Via;
- this.factory = channel.Factory;
- }
- IOThreadTimer SendTimer
- {
- get
- {
- if (this.sendTimer == null)
- {
- if (onSendTimeout == null)
- {
- onSendTimeout = new Action<object>(OnSendTimeout);
- }
- this.sendTimer = new IOThreadTimer(onSendTimeout, this, false);
- }
- return this.sendTimer;
- }
- }
- public static void End(IAsyncResult result)
- {
- AsyncResult.End<HttpChannelAsyncRequest>(result);
- }
- public void BeginSendRequest(Message message, TimeSpan timeout)
- {
- this.message = this.requestMessage = message;
- this.timeoutHelper = new TimeoutHelper(timeout);
- if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled)
- {
- this.eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message);
- }
- factory.ApplyManualAddressing(ref this.to, ref this.via, this.requestMessage);
- if (this.channel.WillGetWebRequestCompleteSynchronously())
- {
- SetWebRequest(channel.GetWebRequest(this.to, this.via, ref this.timeoutHelper));
- if (this.SendWebRequest())
- {
- base.Complete(true);
- }
- }
- else
- {
- if (onGetWebRequestCompleted == null)
- {
- onGetWebRequestCompleted = Fx.ThunkCallback(
- new AsyncCallback(OnGetWebRequestCompletedCallback));
- }
- IAsyncResult result = channel.BeginGetWebRequest(
- to, via, ref this.timeoutHelper, onGetWebRequestCompleted, this);
- if (result.CompletedSynchronously)
- {
- if (TD.MessageSentByTransportIsEnabled())
- {
- TD.MessageSentByTransport(this.eventTraceActivity, this.to.Uri.AbsoluteUri);
- }
- if (this.OnGetWebRequestCompleted(result))
- {
- base.Complete(true);
- }
- }
- }
- }
- static void OnGetWebRequestCompletedCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- HttpChannelAsyncRequest thisPtr = (HttpChannelAsyncRequest)result.AsyncState;
- Exception completionException = null;
- bool completeSelf;
- try
- {
- completeSelf = thisPtr.OnGetWebRequestCompleted(result);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- thisPtr.Complete(false, completionException);
- }
- }
- void AbortSend()
- {
- CancelSendTimer();
- if (this.request != null)
- {
- this.TryCompleteWebRequest(this.request);
- this.abortReason = HttpAbortReason.TimedOut;
- httpOutput.Abort(this.abortReason);
- }
- }
- void CancelSendTimer()
- {
- lock (sendLock)
- {
- if (this.sendTimer != null)
- {
- this.sendTimer.Cancel();
- this.sendTimer = null;
- }
- }
- }
- bool OnGetWebRequestCompleted(IAsyncResult result)
- {
- SetWebRequest(this.channel.EndGetWebRequest(result));
- return this.SendWebRequest();
- }
- bool SendWebRequest()
- {
- this.httpOutput = HttpOutput.CreateHttpOutput(this.request, this.factory, this.requestMessage, this.factory.IsChannelBindingSupportEnabled);
- bool success = false;
- try
- {
- bool result = false;
- SetSendTimeout(timeoutHelper.RemainingTime());
- IAsyncResult asyncResult = httpOutput.BeginSend(timeoutHelper.RemainingTime(), onSend, this);
- success = true;
- if (asyncResult.CompletedSynchronously)
- {
- result = CompleteSend(asyncResult);
- }
- return result;
- }
- finally
- {
- if (!success)
- {
- this.httpOutput.Abort(HttpAbortReason.Aborted);
- if (!object.ReferenceEquals(this.message, this.requestMessage))
- {
- this.requestMessage.Close();
- }
- }
- }
- }
- bool CompleteSend(IAsyncResult result)
- {
- bool success = false;
- try
- {
- httpOutput.EndSend(result);
- this.channelBinding = httpOutput.TakeChannelBinding();
- httpOutput.Close();
- success = true;
- if (TD.MessageSentByTransportIsEnabled())
- {
- TD.MessageSentByTransport(this.eventTraceActivity, this.to.Uri.AbsoluteUri);
- }
- }
- finally
- {
- if (!success)
- {
- httpOutput.Abort(HttpAbortReason.Aborted);
- }
- if (!object.ReferenceEquals(this.message, this.requestMessage))
- {
- this.requestMessage.Close();
- }
- }
- try
- {
- IAsyncResult getResponseResult;
- try
- {
- getResponseResult = request.BeginGetResponse(onGetResponse, this);
- }
- catch (NullReferenceException nullReferenceException)
- {
- // workaround for Whidbey bug #558605 - only happens in streamed case.
- if (TransferModeHelper.IsRequestStreamed(this.factory.transferMode))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- HttpChannelUtilities.CreateNullReferenceResponseException(nullReferenceException));
- }
- throw;
- }
- if (getResponseResult.CompletedSynchronously)
- {
- return CompleteGetResponse(getResponseResult);
- }
- return false;
- }
- catch (IOException ioException)
- {
- throw TraceUtility.ThrowHelperError(new CommunicationException(ioException.Message,
- ioException), this.requestMessage);
- }
- catch (WebException webException)
- {
- throw TraceUtility.ThrowHelperError(new CommunicationException(webException.Message,
- webException), this.requestMessage);
- }
- catch (ObjectDisposedException objectDisposedException)
- {
- if (abortReason == HttpAbortReason.Aborted)
- {
- throw TraceUtility.ThrowHelperError(new CommunicationObjectAbortedException(SR.GetString(SR.HttpRequestAborted, to.Uri),
- objectDisposedException), this.requestMessage);
- }
- throw TraceUtility.ThrowHelperError(new TimeoutException(SR.GetString(SR.HttpRequestTimedOut,
- to.Uri, this.timeoutHelper.OriginalTimeout), objectDisposedException), this.requestMessage);
- }
- }
- [System.Diagnostics.CodeAnalysis.SuppressMessage(FxCop.Category.ReliabilityBasic, "Reliability104",
- Justification = "This is an old method from previous release.")]
- bool CompleteGetResponse(IAsyncResult result)
- {
- using (ServiceModelActivity.BoundOperation(this.channel.Activity))
- {
- HttpWebResponse response = null;
- WebException responseException = null;
- try
- {
- try
- {
- CancelSendTimer();
- response = (HttpWebResponse)request.EndGetResponse(result);
- }
- catch (NullReferenceException nullReferenceException)
- {
- // workaround for Whidbey bug #558605 - only happens in streamed case.
- if (TransferModeHelper.IsRequestStreamed(this.factory.transferMode))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- HttpChannelUtilities.CreateNullReferenceResponseException(nullReferenceException));
- }
- throw;
- }
- if (TD.MessageReceivedByTransportIsEnabled())
- {
- TD.MessageReceivedByTransport(
- this.eventTraceActivity ?? EventTraceActivity.Empty,
- this.to.Uri.AbsoluteUri,
- EventTraceActivity.GetActivityIdFromThread());
- }
- if (DiagnosticUtility.ShouldTraceVerbose)
- {
- HttpChannelFactory<TChannel>.TraceResponseReceived(response, this.message, this);
- }
- }
- catch (WebException webException)
- {
- responseException = webException;
- response = HttpChannelUtilities.ProcessGetResponseWebException(webException, request,
- abortReason);
- }
- return ProcessResponse(response, responseException);
- }
- }
- void Cleanup()
- {
- if (this.request != null)
- {
- HttpChannelUtilities.AbortRequest(this.request);
- this.TryCompleteWebRequest(this.request);
- }
- ChannelBindingUtility.Dispose(ref this.channelBinding);
- }
- void SetSendTimeout(TimeSpan timeout)
- {
- // We also set the timeout on the HttpWebRequest so that we can subsequently use it in the
- // exception message in the event of a timeout.
- HttpChannelUtilities.SetRequestTimeout(this.request, timeout);
- if (timeout == TimeSpan.MaxValue)
- {
- CancelSendTimer();
- }
- else
- {
- SendTimer.Set(timeout);
- }
- }
- public void Abort(RequestChannel channel)
- {
- Cleanup();
- abortReason = HttpAbortReason.Aborted;
- }
- public void Fault(RequestChannel channel)
- {
- Cleanup();
- }
- void SetWebRequest(HttpWebRequest webRequest)
- {
- this.request = webRequest;
- if (channel.State != CommunicationState.Opened)
- {
- // if we were aborted while getting our request, we need to abort the web request and bail
- Cleanup();
- channel.ThrowIfDisposedOrNotOpen();
- }
- }
- public Message End()
- {
- HttpChannelAsyncRequest.End(this);
- return replyMessage;
- }
- bool ProcessResponse(HttpWebResponse response, WebException responseException)
- {
- this.httpInput = HttpChannelUtilities.ValidateRequestReplyResponse(this.request, response,
- this.factory, responseException, this.channelBinding);
- this.channelBinding = null;
- if (httpInput != null)
- {
- this.response = response;
- IAsyncResult result =
- httpInput.BeginParseIncomingMessage(onProcessIncomingMessage, this);
- if (!result.CompletedSynchronously)
- {
- return false;
- }
- CompleteParseIncomingMessage(result);
- }
- else
- {
- this.replyMessage = null;
- }
- this.TryCompleteWebRequest(this.request);
- return true;
- }
- void CompleteParseIncomingMessage(IAsyncResult result)
- {
- Exception exception = null;
- this.replyMessage = this.httpInput.EndParseIncomingMessage(result, out exception);
- Fx.Assert(exception == null, "ParseIncomingMessage should not set an exception after parsing a response message.");
- if (this.replyMessage != null)
- {
- HttpChannelUtilities.AddReplySecurityProperty(this.factory, this.request, this.response,
- this.replyMessage);
- }
- }
- static void OnParseIncomingMessage(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- HttpChannelAsyncRequest thisPtr = (HttpChannelAsyncRequest)result.AsyncState;
- Exception completionException = null;
- try
- {
- thisPtr.CompleteParseIncomingMessage(result);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completionException = e;
- }
- thisPtr.Complete(false, completionException);
- }
- static void OnSend(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- HttpChannelAsyncRequest thisPtr = (HttpChannelAsyncRequest)result.AsyncState;
- Exception completionException = null;
- bool completeSelf;
- try
- {
- completeSelf = thisPtr.CompleteSend(result);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- thisPtr.Complete(false, completionException);
- }
- }
- static void OnSendTimeout(object state)
- {
- HttpChannelAsyncRequest thisPtr = (HttpChannelAsyncRequest)state;
- thisPtr.AbortSend();
- }
- [System.Diagnostics.CodeAnalysis.SuppressMessage(FxCop.Category.ReliabilityBasic, "Reliability104",
- Justification = "This is an old method from previous release.")]
- static void OnGetResponse(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- HttpChannelAsyncRequest thisPtr = (HttpChannelAsyncRequest)result.AsyncState;
- Exception completionException = null;
- bool completeSelf;
- try
- {
- completeSelf = thisPtr.CompleteGetResponse(result);
- }
- catch (WebException webException)
- {
- completeSelf = true;
- completionException = new CommunicationException(webException.Message, webException);
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completeSelf = true;
- completionException = e;
- }
- if (completeSelf)
- {
- thisPtr.Complete(false, completionException);
- }
- }
- public void OnReleaseRequest()
- {
- this.TryCompleteWebRequest(this.request);
- }
- void TryCompleteWebRequest(HttpWebRequest request)
- {
- if (request == null)
- {
- return;
- }
- if (Interlocked.CompareExchange(ref this.webRequestCompleted, 1, 0) == 0)
- {
- this.channel.OnWebRequestCompleted(request);
- }
- }
- }
- class GetWebRequestAsyncResult : AsyncResult
- {
- static AsyncCallback onGetSspiCredential;
- static AsyncCallback onGetUserNameCredential;
- SecurityTokenContainer clientCertificateToken;
- HttpChannelFactory<IRequestChannel> factory;
- SecurityTokenProviderContainer proxyTokenProvider;
- HttpWebRequest request;
- EndpointAddress to;
- TimeoutHelper timeoutHelper;
- SecurityTokenProviderContainer tokenProvider;
- Uri via;
- public GetWebRequestAsyncResult(HttpRequestChannel channel,
- EndpointAddress to, Uri via, SecurityTokenContainer clientCertificateToken, ref TimeoutHelper timeoutHelper,
- AsyncCallback callback, object state)
- : base(callback, state)
- {
- this.to = to;
- this.via = via;
- this.clientCertificateToken = clientCertificateToken;
- this.timeoutHelper = timeoutHelper;
- this.factory = channel.Factory;
- this.tokenProvider = channel.tokenProvider;
- this.proxyTokenProvider = channel.proxyTokenProvider;
- if (factory.ManualAddressing)
- {
- this.factory.CreateAndOpenTokenProviders(to, via, channel.channelParameters, timeoutHelper.RemainingTime(),
- out this.tokenProvider, out this.proxyTokenProvider);
- }
- bool completeSelf = false;
- IAsyncResult result = null;
- if (factory.AuthenticationScheme == AuthenticationSchemes.Anonymous)
- {
- SetupWebRequest(AuthenticationLevel.None, TokenImpersonationLevel.None, null);
- completeSelf = true;
- }
- else if (factory.AuthenticationScheme == AuthenticationSchemes.Basic)
- {
- if (onGetUserNameCredential == null)
- {
- onGetUserNameCredential = Fx.ThunkCallback(new AsyncCallback(OnGetUserNameCredential));
- }
- result = TransportSecurityHelpers.BeginGetUserNameCredential(
- tokenProvider, timeoutHelper.RemainingTime(), onGetUserNameCredential, this);
- if (result.CompletedSynchronously)
- {
- CompleteGetUserNameCredential(result);
- completeSelf = true;
- }
- }
- else
- {
- if (onGetSspiCredential == null)
- {
- onGetSspiCredential = Fx.ThunkCallback(new AsyncCallback(OnGetSspiCredential));
- }
- result = TransportSecurityHelpers.BeginGetSspiCredential(
- tokenProvider, timeoutHelper.RemainingTime(), onGetSspiCredential, this);
- if (result.CompletedSynchronously)
- {
- CompleteGetSspiCredential(result);
- completeSelf = true;
- }
- }
- if (completeSelf)
- {
- CloseTokenProvidersIfRequired();
- base.Complete(true);
- }
- }
- public static HttpWebRequest End(IAsyncResult result)
- {
- GetWebRequestAsyncResult thisPtr = AsyncResult.End<GetWebRequestAsyncResult>(result);
- return thisPtr.request;
- }
- void CompleteGetUserNameCredential(IAsyncResult result)
- {
- NetworkCredential credential =
- TransportSecurityHelpers.EndGetUserNameCredential(result);
- SetupWebRequest(AuthenticationLevel.None, TokenImpersonationLevel.None, credential);
- }
- void CompleteGetSspiCredential(IAsyncResult result)
- {
- AuthenticationLevel authenticationLevel;
- TokenImpersonationLevel impersonationLevel;
- NetworkCredential credential =
- TransportSecurityHelpers.EndGetSspiCredential(result, out impersonationLevel, out authenticationLevel);
- if (factory.AuthenticationScheme == AuthenticationSchemes.Digest)
- {
- HttpChannelUtilities.ValidateDigestCredential(ref credential, impersonationLevel);
- }
- else if (factory.AuthenticationScheme == AuthenticationSchemes.Ntlm)
- {
- if (authenticationLevel == AuthenticationLevel.MutualAuthRequired)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
- SR.GetString(SR.CredentialDisallowsNtlm)));
- }
- }
- SetupWebRequest(authenticationLevel, impersonationLevel, credential);
- }
- void SetupWebRequest(AuthenticationLevel authenticationLevel, TokenImpersonationLevel impersonationLevel, NetworkCredential credential)
- {
- this.request = factory.GetWebRequest(to, via, credential, impersonationLevel,
- authenticationLevel, this.proxyTokenProvider, this.clientCertificateToken, timeoutHelper.RemainingTime(), false);
- }
- void CloseTokenProvidersIfRequired()
- {
- if (this.factory.ManualAddressing)
- {
- if (this.tokenProvider != null)
- {
- tokenProvider.Abort();
- }
- if (this.proxyTokenProvider != null)
- {
- proxyTokenProvider.Abort();
- }
- }
- }
- static void OnGetSspiCredential(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- GetWebRequestAsyncResult thisPtr = (GetWebRequestAsyncResult)result.AsyncState;
- Exception completionException = null;
- try
- {
- thisPtr.CompleteGetSspiCredential(result);
- thisPtr.CloseTokenProvidersIfRequired();
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completionException = e;
- }
- thisPtr.Complete(false, completionException);
- }
- static void OnGetUserNameCredential(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- GetWebRequestAsyncResult thisPtr = (GetWebRequestAsyncResult)result.AsyncState;
- Exception completionException = null;
- try
- {
- thisPtr.CompleteGetUserNameCredential(result);
- thisPtr.CloseTokenProvidersIfRequired();
- }
- #pragma warning suppress 56500 // [....], transferring exception to another thread
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completionException = e;
- }
- thisPtr.Complete(false, completionException);
- }
- }
- }
- class WebProxyFactory
- {
- Uri address;
- bool bypassOnLocal;
- AuthenticationSchemes authenticationScheme;
- public WebProxyFactory(Uri address, bool bypassOnLocal, AuthenticationSchemes authenticationScheme)
- {
- this.address = address;
- this.bypassOnLocal = bypassOnLocal;
- if (!authenticationScheme.IsSingleton())
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("value", SR.GetString(SR.HttpRequiresSingleAuthScheme,
- authenticationScheme));
- }
- this.authenticationScheme = authenticationScheme;
- }
- internal AuthenticationSchemes AuthenticationScheme
- {
- get
- {
- return authenticationScheme;
- }
- }
- public IWebProxy CreateWebProxy(HttpWebRequest request, SecurityTokenProviderContainer tokenProvider, TimeSpan timeout)
- {
- WebProxy result = new WebProxy(this.address, this.bypassOnLocal);
- if (this.authenticationScheme != AuthenticationSchemes.Anonymous)
- {
- TokenImpersonationLevel impersonationLevel;
- AuthenticationLevel authenticationLevel;
- NetworkCredential credential = HttpChannelUtilities.GetCredential(this.authenticationScheme,
- tokenProvider, timeout, out impersonationLevel, out authenticationLevel);
- // The impersonation level for target auth is also used for proxy auth (by System.Net). Therefore,
- // fail if the level stipulated for proxy auth is more restrictive than that for target auth.
- if (!TokenImpersonationLevelHelper.IsGreaterOrEqual(impersonationLevel, request.ImpersonationLevel))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(
- SR.ProxyImpersonationLevelMismatch, impersonationLevel, request.ImpersonationLevel)));
- }
- // The authentication level for target auth is also used for proxy auth (by System.Net).
- // Therefore, fail if proxy auth requires mutual authentication but target auth does not.
- if ((authenticationLevel == AuthenticationLevel.MutualAuthRequired) &&
- (request.AuthenticationLevel != AuthenticationLevel.MutualAuthRequired))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(
- SR.ProxyAuthenticationLevelMismatch, authenticationLevel, request.AuthenticationLevel)));
- }
- CredentialCache credentials = new CredentialCache();
- credentials.Add(this.address, AuthenticationSchemesHelper.ToString(this.authenticationScheme),
- credential);
- result.Credentials = credentials;
- }
- return result;
- }
- }
- }
- }
|