From ef4e675372fcb300eb47598c0f632ad4b0315571 Mon Sep 17 00:00:00 2001 From: Matt Connew Date: Wed, 4 Dec 2024 10:46:18 -0800 Subject: [PATCH 1/2] Add netstandard support back to Federation --- .../MessageInterceptor/AsyncResult.cs | 90 ++-- .../MessageInterceptor/TimeoutHelper.cs | 19 +- .../src/Resources/Strings.resx | 6 + .../src/Resources/xlf/Strings.cs.xlf | 10 + .../src/Resources/xlf/Strings.de.xlf | 10 + .../src/Resources/xlf/Strings.es.xlf | 10 + .../src/Resources/xlf/Strings.fr.xlf | 10 + .../src/Resources/xlf/Strings.it.xlf | 10 + .../src/Resources/xlf/Strings.ja.xlf | 10 + .../src/Resources/xlf/Strings.ko.xlf | 10 + .../src/Resources/xlf/Strings.pl.xlf | 10 + .../src/Resources/xlf/Strings.pt-BR.xlf | 10 + .../src/Resources/xlf/Strings.ru.xlf | 10 + .../src/Resources/xlf/Strings.tr.xlf | 10 + .../src/Resources/xlf/Strings.zh-Hans.xlf | 10 + .../src/Resources/xlf/Strings.zh-Hant.xlf | 10 + .../src/System.ServiceModel.Federation.csproj | 2 +- .../src/System/Runtime/Fx.cs | 54 ++ .../src/System/Runtime/InternalSR.cs | 22 + .../OperationWithTimeoutAsyncResult.cs | 401 ++++++++++++++ .../src/System/Runtime/TaskHelpers.cs | 184 +++++++ .../src/System/Runtime/TimeoutHelper.cs | 206 ++++++++ .../ServiceModel/Federation/LogHelper.cs | 31 -- .../ServiceModel/Federation/WSTrustChannel.cs | 44 +- .../Federation/WSTrustChannelFactory.cs | 10 +- .../WSTrustChannelSecurityTokenProvider.cs | 33 +- .../Federation/WSTrustRequestBodyWriter.cs | 4 +- .../Federation/WSTrustUtilities.cs | 20 +- .../WsTrustChannelSecurityTokenManager.cs | 4 +- .../Federation/WsTrustTokenParameters.cs | 6 +- .../Security/ISecurityCommunicationObject.cs | 23 + .../ServiceModel/Security/SecurityUtils.cs | 48 ++ .../ServiceModel/Security/ServiceDefaults.cs | 15 + .../WrapperSecurityCommunicationObject.cs | 494 ++++++++++++++++++ ...tem.ServiceModel.Primitives.netstandard.cs | 3 + .../ref/System.ServiceModel.Security.cs | 2 + .../src/Internals/InternalSR.cs | 2 + .../src/netstandard.cs | 2 + 38 files changed, 1699 insertions(+), 156 deletions(-) create mode 100644 src/System.ServiceModel.Federation/src/System/Runtime/Fx.cs create mode 100644 src/System.ServiceModel.Federation/src/System/Runtime/InternalSR.cs create mode 100644 src/System.ServiceModel.Federation/src/System/Runtime/OperationWithTimeoutAsyncResult.cs create mode 100644 src/System.ServiceModel.Federation/src/System/Runtime/TaskHelpers.cs create mode 100644 src/System.ServiceModel.Federation/src/System/Runtime/TimeoutHelper.cs delete mode 100644 src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/LogHelper.cs create mode 100644 src/System.ServiceModel.Federation/src/System/ServiceModel/Security/ISecurityCommunicationObject.cs create mode 100644 src/System.ServiceModel.Federation/src/System/ServiceModel/Security/SecurityUtils.cs create mode 100644 src/System.ServiceModel.Federation/src/System/ServiceModel/Security/ServiceDefaults.cs create mode 100644 src/System.ServiceModel.Federation/src/System/ServiceModel/Security/WrapperSecurityCommunicationObject.cs diff --git a/src/System.Private.ServiceModel/tests/Scenarios/Extensibility/MessageInterceptor/AsyncResult.cs b/src/System.Private.ServiceModel/tests/Scenarios/Extensibility/MessageInterceptor/AsyncResult.cs index f6838dfbbfc..d3ce0b4fee5 100644 --- a/src/System.Private.ServiceModel/tests/Scenarios/Extensibility/MessageInterceptor/AsyncResult.cs +++ b/src/System.Private.ServiceModel/tests/Scenarios/Extensibility/MessageInterceptor/AsyncResult.cs @@ -11,29 +11,29 @@ /// A generic base class for IAsyncResult implementations /// that wraps a ManualResetEvent. /// -abstract class AsyncResult : IAsyncResult +internal abstract class AsyncResult : IAsyncResult { - AsyncCallback callback; - object state; - bool completedSynchronously; - bool endCalled; - Exception exception; - bool isCompleted; - ManualResetEvent manualResetEvent; - object thisLock; + private AsyncCallback _callback; + private object _state; + private bool _completedSynchronously; + private bool _endCalled; + private Exception _exception; + private bool _isCompleted; + private ManualResetEvent _manualResetEvent; + private object _thisLock; protected AsyncResult(AsyncCallback callback, object state) { - this.callback = callback; - this.state = state; - this.thisLock = new object(); + this._callback = callback; + this._state = state; + this._thisLock = new object(); } public object AsyncState { get { - return state; + return _state; } } @@ -41,20 +41,20 @@ public WaitHandle AsyncWaitHandle { get { - if (manualResetEvent != null) + if (_manualResetEvent != null) { - return manualResetEvent; + return _manualResetEvent; } lock (ThisLock) { - if (manualResetEvent == null) + if (_manualResetEvent == null) { - manualResetEvent = new ManualResetEvent(isCompleted); + _manualResetEvent = new ManualResetEvent(_isCompleted); } } - return manualResetEvent; + return _manualResetEvent; } } @@ -62,7 +62,7 @@ public bool CompletedSynchronously { get { - return completedSynchronously; + return _completedSynchronously; } } @@ -70,15 +70,15 @@ public bool IsCompleted { get { - return isCompleted; + return _isCompleted; } } - object ThisLock + private object ThisLock { get { - return this.thisLock; + return this._thisLock; } } @@ -86,37 +86,37 @@ object ThisLock // of the operation and notify the callback. protected void Complete(bool completedSynchronously) { - if (isCompleted) + if (_isCompleted) { // It is a bug to call Complete twice. throw new InvalidOperationException("Cannot call Complete twice"); } - this.completedSynchronously = completedSynchronously; + this._completedSynchronously = completedSynchronously; if (completedSynchronously) { // If we completedSynchronously, then there is no chance that the manualResetEvent was created so // we do not need to worry about a race condition. - Debug.Assert(this.manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult."); - this.isCompleted = true; + Debug.Assert(this._manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult."); + this._isCompleted = true; } else { lock (ThisLock) { - this.isCompleted = true; - if (this.manualResetEvent != null) + this._isCompleted = true; + if (this._manualResetEvent != null) { - this.manualResetEvent.Set(); + this._manualResetEvent.Set(); } } } // If the callback throws, there is a bug in the callback implementation - if (callback != null) + if (_callback != null) { - callback(this); + _callback(this); } } @@ -124,7 +124,7 @@ protected void Complete(bool completedSynchronously) // the callback, it will capture the exception and store it to be thrown during AsyncResult.End. protected void Complete(bool completedSynchronously, Exception exception) { - this.exception = exception; + this._exception = exception; Complete(completedSynchronously); } @@ -145,26 +145,26 @@ protected static TAsyncResult End(IAsyncResult result) throw new ArgumentException("Invalid async result.", "result"); } - if (asyncResult.endCalled) + if (asyncResult._endCalled) { throw new InvalidOperationException("Async object already ended."); } - asyncResult.endCalled = true; + asyncResult._endCalled = true; - if (!asyncResult.isCompleted) + if (!asyncResult._isCompleted) { asyncResult.AsyncWaitHandle.WaitOne(); } - if (asyncResult.manualResetEvent != null) + if (asyncResult._manualResetEvent != null) { - asyncResult.manualResetEvent.Dispose(); + asyncResult._manualResetEvent.Dispose(); } - if (asyncResult.exception != null) + if (asyncResult._exception != null) { - throw asyncResult.exception; + throw asyncResult._exception; } return asyncResult; @@ -172,7 +172,7 @@ protected static TAsyncResult End(IAsyncResult result) } //An AsyncResult that completes as soon as it is instantiated. -class CompletedAsyncResult : AsyncResult +internal class CompletedAsyncResult : AsyncResult { public CompletedAsyncResult(AsyncCallback callback, object state) : base(callback, state) @@ -187,9 +187,9 @@ public static void End(IAsyncResult result) } //A strongly typed AsyncResult -abstract class TypedAsyncResult : AsyncResult +internal abstract class TypedAsyncResult : AsyncResult { - T data; + private T _data; protected TypedAsyncResult(AsyncCallback callback, object state) : base(callback, state) @@ -198,12 +198,12 @@ protected TypedAsyncResult(AsyncCallback callback, object state) public T Data { - get { return data; } + get { return _data; } } protected void Complete(T data, bool completedSynchronously) { - this.data = data; + this._data = data; Complete(completedSynchronously); } @@ -215,7 +215,7 @@ public static T End(IAsyncResult result) } //A strongly typed AsyncResult that completes as soon as it is instantiated. -class TypedCompletedAsyncResult : TypedAsyncResult +internal class TypedCompletedAsyncResult : TypedAsyncResult { public TypedCompletedAsyncResult(T data, AsyncCallback callback, object state) : base(callback, state) diff --git a/src/System.Private.ServiceModel/tests/Scenarios/Extensibility/MessageInterceptor/TimeoutHelper.cs b/src/System.Private.ServiceModel/tests/Scenarios/Extensibility/MessageInterceptor/TimeoutHelper.cs index ce1051e67a7..9868e6e1f98 100644 --- a/src/System.Private.ServiceModel/tests/Scenarios/Extensibility/MessageInterceptor/TimeoutHelper.cs +++ b/src/System.Private.ServiceModel/tests/Scenarios/Extensibility/MessageInterceptor/TimeoutHelper.cs @@ -11,8 +11,9 @@ public struct TimeoutHelper public static TimeSpan DefaultTimeout { get { return TimeSpan.FromMinutes(2); } } public static TimeSpan DefaultShortTimeout { get { return TimeSpan.FromSeconds(4); } } public static TimeSpan Infinite { get { return TimeSpan.MaxValue; } } - DateTime deadline; - TimeSpan originalTimeout; + + private DateTime _deadline; + private TimeSpan _originalTimeout; public TimeoutHelper(TimeSpan timeout) { @@ -21,31 +22,31 @@ public TimeoutHelper(TimeSpan timeout) throw new ArgumentOutOfRangeException("timeout"); } - this.originalTimeout = timeout; + this._originalTimeout = timeout; if (timeout == TimeSpan.MaxValue) { - this.deadline = DateTime.MaxValue; + this._deadline = DateTime.MaxValue; } else { - this.deadline = DateTime.UtcNow + timeout; + this._deadline = DateTime.UtcNow + timeout; } } public TimeSpan OriginalTimeout { - get { return this.originalTimeout; } + get { return this._originalTimeout; } } public TimeSpan RemainingTime() { - if (this.deadline == DateTime.MaxValue) + if (this._deadline == DateTime.MaxValue) { return TimeSpan.MaxValue; } else { - TimeSpan remaining = this.deadline - DateTime.UtcNow; + TimeSpan remaining = this._deadline - DateTime.UtcNow; if (remaining <= TimeSpan.Zero) { return TimeSpan.Zero; @@ -150,7 +151,7 @@ public static bool WaitOne(WaitHandle waitHandle, TimeSpan timeout, bool exitSyn } } - static class Ticks + private static class Ticks { public static long FromMilliseconds(int milliseconds) { diff --git a/src/System.ServiceModel.Federation/src/Resources/Strings.resx b/src/System.ServiceModel.Federation/src/Resources/Strings.resx index d32f2f6ea68..8b81ec329a3 100644 --- a/src/System.ServiceModel.Federation/src/Resources/Strings.resx +++ b/src/System.ServiceModel.Federation/src/Resources/Strings.resx @@ -198,4 +198,10 @@ Client cannot determine the Service Principal Name based on the identity in the target address '{0}' for the purpose of SspiNegotiation/Kerberos. The target address identity must be a UPN identity (like acmedomain\alice) or SPN identity (like host/bobs-machine). + + AsyncResult completed twice. + + + KeyType is not supported: {0} + diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.cs.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.cs.xlf index 5694f1193ea..a06e75f9836 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.cs.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.cs.xlf @@ -7,6 +7,11 @@ Zpracujte akci {0}. + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. Scénáře nosných klíčů by v odpovědi neměly obsahovat ověřovací token nebo entropii vystavitele. @@ -72,6 +77,11 @@ IssuedTokenRenewalThresholdPercentage musí být větší nebo rovno 1 a menší nebo rovno 100. Bylo: '{0}'. + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. MaxIssuedTokenCachingTime musí být větší než TimeSpan.Zero. Bylo: '{0}'. diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.de.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.de.xlf index 507aba14deb..9d3222a7787 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.de.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.de.xlf @@ -7,6 +7,11 @@ Aktion "{0}" verarbeiten. + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. Bearerschlüsselszenarien sollten kein Nachweistoken oder eine Ausstellerentropie in der Antwort enthalten. @@ -72,6 +77,11 @@ "IssuedTokenRenewalThresholdPercentage" muss größer oder gleich 1 und kleiner oder gleich 100 sein. War: '{0}'. + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. MaxIssuedTokenCachingTime muss größer als TimeSpan.Zero sein. War: '{0}'. diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.es.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.es.xlf index d6517baffb4..9731b4466ce 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.es.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.es.xlf @@ -7,6 +7,11 @@ Procese la acción "{0}". + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. Los escenarios de clave del portador no deben incluir un token de prueba o una entropía de emisor en la respuesta. @@ -72,6 +77,11 @@ IssuedTokenRenewalThresholdPercentage debe ser mayor o igual que 1 y menor o igual que 100. Era: "{0}". + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. MaxIssuedTokenCachingTime debe ser mayor que TimeSpan.Zero. Era: "{0}". diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.fr.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.fr.xlf index 64152600572..8f69c55f8a7 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.fr.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.fr.xlf @@ -7,6 +7,11 @@ Traiter l'action '{0}'. + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. Les scénarios de clé de porteur ne doivent pas inclure de jeton de preuve ou d’entropie d’émetteur dans la réponse. @@ -72,6 +77,11 @@ IssuedTokenRenewalThresholdPercentage doit être supérieur ou égal à 1 et inférieur ou égal à 100. Was: '{0}'. + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. MaxIssuedTokenCachingTime doit être supérieur à TimeSpan.Zero. Was: '{0}'. diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.it.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.it.xlf index 2bd5b1e9392..f7305061fa7 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.it.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.it.xlf @@ -7,6 +7,11 @@ Elaborazione dell'azione '{0}'. + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. Gli scenari chiave di connessione non devono includere un token di prova o un'entropia dell'autorità di certificazione nella risposta. @@ -72,6 +77,11 @@ IssuedTokenRenewalThresholdPercentage deve essere maggiore o uguale a 1 e minore o uguale a 100. Era: '{0}'. + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. MaxIssuedTokenCachingTime deve essere maggiore di TimeSpan.Zero. Era: '{0}'. diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.ja.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.ja.xlf index a7aadda0e3c..7adb39446a0 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.ja.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.ja.xlf @@ -7,6 +7,11 @@ アクション '{0}' を処理します。 + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. ベアラーの主要なシナリオでは、応答に証明トークンまたは発行者エントロピを含めない必要があります。 @@ -72,6 +77,11 @@ IssuedTokenRenewalThresholdPercentage は 1 以上 100 以下である必要があります。 '{0}' でした。 + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. MaxIssuedTokenCachingTime は TimeSpan.Zero より大きくする必要があります。 '{0}' でした。 diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.ko.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.ko.xlf index 49cfc75f7f6..fc8a1d9cdda 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.ko.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.ko.xlf @@ -7,6 +7,11 @@ 동작 '{0}'을(를) 처리하세요. + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. 전달자 키 시나리오는 응답에 증명 토큰 또는 발급자 엔트로피를 포함하지 않아야 합니다. @@ -72,6 +77,11 @@ IssuedTokenRenewalThresholdPercentage는 1보다 크거나 같고 100보다 작거나 같아야 합니다. 이전: '{0}'. + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. MaxIssuedTokenCachingTime은 TimeSpan.Zero보다 커야 합니다. 이전: '{0}'. diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.pl.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.pl.xlf index 677a415e741..1bf9904ed35 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.pl.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.pl.xlf @@ -7,6 +7,11 @@ Przetwarzaj akcję „{0}”. + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. Scenariusze klucza elementu nośnego nie powinny zawierać tokenu potwierdzającego ani entropii wystawcy w odpowiedzi. @@ -72,6 +77,11 @@ Wartość IssuedTokenRenewalThresholdPercentage musi być większa lub równa 1 i mniejsza lub równa 100. Była: „{0}”. + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. Wartość MaxIssuedTokenCachingTime musi być większa niż wartość TimeSpan.Zero. Była: „{0}”. diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.pt-BR.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.pt-BR.xlf index 67780835dc2..9bb6ab500d0 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.pt-BR.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.pt-BR.xlf @@ -7,6 +7,11 @@ Processar a ação '{0}'. + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. Os cenários principais do portador não devem incluir um token de prova ou entropia do emissor na resposta. @@ -72,6 +77,11 @@ IssuedTokenRenewalThresholdPercentage deve ser maior ou igual a 1 e menor ou igual a 100. Era: '{0}'. + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. MaxIssuedTokenCachingTime deve ser maior que TimeSpan.Zero. Era: '{0}'. diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.ru.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.ru.xlf index af7917ae222..a58c65d54a4 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.ru.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.ru.xlf @@ -7,6 +7,11 @@ Обработка действия "{0}". + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. Сценарии с ключом носителем не должны включать в ответ маркер проверки или энтропию издателя. @@ -72,6 +77,11 @@ Значение IssuedTokenRenewalThresholdPercentage должно быть больше или равно 1 и меньше или равно 100. Было: "{0}". + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. Значение MaxIssuedTokenCachingTime должно быть больше TimeSpan.Zero. Было: "{0}". diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.tr.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.tr.xlf index c46bb369e48..a8442fb5417 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.tr.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.tr.xlf @@ -7,6 +7,11 @@ '{0}' eylemini işleyin. + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. Taşıyıcı anahtar senaryoları yanıtta bir kanıt belirteci veya veren entropi içermemelidir. @@ -72,6 +77,11 @@ IssuedTokenRenewalThresholdPercentage değeri en az 1 ve en fazla 100 olmalıdır. Değer şuydu: '{0}'. + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. MaxIssuedTokenCachingTime değeri TimeSpan.Zero değerinden büyük olmalıdır. Değer şuydu: '{0}'. diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.zh-Hans.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.zh-Hans.xlf index 4851cea3efc..9c4ba94ee0a 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.zh-Hans.xlf @@ -7,6 +7,11 @@ 处理操作“{0}”。 + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. 持有者关键方案不应在响应中包含证明令牌或证书颁发者熵。 @@ -72,6 +77,11 @@ IssuedTokenRenewalThresholdPercentage 必须大于或等于 1,且小于或等于 100。之前的值为:“{0}”。 + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. MaxIssuedTokenCachingTime 必须大于 TimeSpan.Zero。之前的值为:“{0}”。 diff --git a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.zh-Hant.xlf b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.zh-Hant.xlf index 160ee5ea5df..c030942e76c 100644 --- a/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/System.ServiceModel.Federation/src/Resources/xlf/Strings.zh-Hant.xlf @@ -7,6 +7,11 @@ 處理動作 '{0}'。 + + AsyncResult completed twice. + AsyncResult completed twice. + + Bearer key scenarios should not include a proof token or issuer entropy in the response. Bearer 金鑰案例不應在回應中包含證明權杖或簽發者 Entropy。 @@ -72,6 +77,11 @@ IssuedTokenRenewalThresholdPercentage 必須大於或等於 1 且小於或等於 100,但卻是 '{0}'。 + + KeyType is not supported: {0} + KeyType is not supported: {0} + + MaxIssuedTokenCachingTime must be greater than TimeSpan.Zero. Was: '{0}'. MaxIssuedTokenCachingTime 必須大於 TimeSpan.Zero,但卻是 '{0}'。 diff --git a/src/System.ServiceModel.Federation/src/System.ServiceModel.Federation.csproj b/src/System.ServiceModel.Federation/src/System.ServiceModel.Federation.csproj index 7615f2bb4b0..e6355c0071a 100644 --- a/src/System.ServiceModel.Federation/src/System.ServiceModel.Federation.csproj +++ b/src/System.ServiceModel.Federation/src/System.ServiceModel.Federation.csproj @@ -6,7 +6,7 @@ true true $(Ship_WcfPackages) - $(DotNetVersion) + netstandard2.0 true diff --git a/src/System.ServiceModel.Federation/src/System/Runtime/Fx.cs b/src/System.ServiceModel.Federation/src/System/Runtime/Fx.cs new file mode 100644 index 00000000000..363456c119a --- /dev/null +++ b/src/System.ServiceModel.Federation/src/System/Runtime/Fx.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.ObjectModel; +using System.Reflection; + +namespace System.Runtime +{ + internal static class Fx + { + public static bool IsFatal(Exception exception) + { + while (exception != null) + { + if (exception is OutOfMemoryException && !(exception is InsufficientMemoryException)) + { + return true; + } + + // These exceptions aren't themselves fatal, but since the CLR uses them to wrap other exceptions, + // we want to check to see whether they've been used to wrap a fatal exception. If so, then they + // count as fatal. + if (exception is TypeInitializationException || + exception is TargetInvocationException) + { + exception = exception.InnerException; + } + else if (exception is AggregateException aggException) + { + // AggregateExceptions have a collection of inner exceptions, which may themselves be other + // wrapping exceptions (including nested AggregateExceptions). Recursively walk this + // hierarchy. The (singular) InnerException is included in the collection. + ReadOnlyCollection innerExceptions = aggException.InnerExceptions; + foreach (Exception innerException in innerExceptions) + { + if (IsFatal(innerException)) + { + return true; + } + } + + break; + } + else + { + break; + } + } + + return false; + } + + } +} diff --git a/src/System.ServiceModel.Federation/src/System/Runtime/InternalSR.cs b/src/System.ServiceModel.Federation/src/System/Runtime/InternalSR.cs new file mode 100644 index 00000000000..71601a65de9 --- /dev/null +++ b/src/System.ServiceModel.Federation/src/System/Runtime/InternalSR.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Runtime +{ + internal static class InternalSR + { +#pragma warning disable IDE1006 // Naming Styles + internal static readonly string AsyncCallbackThrewException = "Async Callback threw an exception."; + internal static readonly string AsyncResultAlreadyEnded = "End cannot be called twice on an AsyncResult."; + internal static readonly string InvalidAsyncResult = "An incorrect IAsyncResult was provided to an 'End' method. The IAsyncResult object passed to 'End' must be the one returned from the matching 'Begin' or passed to the callback provided to 'Begin'."; + internal static readonly string InvalidNullAsyncResult = "A null value was returned from an async 'Begin' method or passed to an AsyncCallback. Async 'Begin' implementations must return a non-null IAsyncResult and pass the same IAsyncResult object as the parameter to the AsyncCallback."; + internal static readonly string InvalidAsyncResultImplementationGeneric = "An incorrect implementation of the IAsyncResult interface may be returning incorrect values from the CompletedSynchronously property or calling the AsyncCallback more than once."; + + internal static string InvalidAsyncResultImplementation(object param0) => $"An incorrect implementation of the IAsyncResult interface may be returning incorrect values from the CompletedSynchronously property or calling the AsyncCallback more than once. The type {param0} could be the incorrect implementation."; +#pragma warning restore IDE1006 // Naming Styles + } +} diff --git a/src/System.ServiceModel.Federation/src/System/Runtime/OperationWithTimeoutAsyncResult.cs b/src/System.ServiceModel.Federation/src/System/Runtime/OperationWithTimeoutAsyncResult.cs new file mode 100644 index 00000000000..ca1e5808835 --- /dev/null +++ b/src/System.ServiceModel.Federation/src/System/Runtime/OperationWithTimeoutAsyncResult.cs @@ -0,0 +1,401 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.ServiceModel; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Runtime +{ + internal class OperationWithTimeoutAsyncResult : AsyncResult + { + private static readonly Action s_scheduledCallback = new Action(OnScheduled); + private TimeoutHelper _timeoutHelper; + private Action _operationWithTimeout; + + public OperationWithTimeoutAsyncResult(Action operationWithTimeout, TimeSpan timeout, AsyncCallback callback, object state) + : base(callback, state) + { + _operationWithTimeout = operationWithTimeout; + _timeoutHelper = new TimeoutHelper(timeout); + _ = Task.Factory.StartNew(s_scheduledCallback, this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + } + + private static void OnScheduled(object state) + { + OperationWithTimeoutAsyncResult thisResult = (OperationWithTimeoutAsyncResult)state; + Exception completionException = null; + try + { + thisResult._operationWithTimeout(thisResult._timeoutHelper.RemainingTime()); + } + catch (Exception e) + { + if (Fx.IsFatal(e)) + { + throw; + } + + completionException = e; + } + + thisResult.Complete(false, completionException); + } + + public static void End(IAsyncResult result) + { + End(result); + } + } + + internal abstract class AsyncResult : IAsyncResult + { + private static AsyncCallback s_asyncCompletionWrapperCallback; + private AsyncCallback _callback; + private bool _endCalled; + private Exception _exception; + private AsyncCompletion _nextAsyncCompletion; + private Action _beforePrepareAsyncCompletionAction; + private Func _checkSyncValidationFunc; + private ManualResetEvent _manualResetEvent; + private object _thisLock; + + + protected AsyncResult(AsyncCallback callback, object state) + { + _callback = callback; + AsyncState = state; + _thisLock = new object(); + } + + public object AsyncState { get; } + + public WaitHandle AsyncWaitHandle + { + get + { + if (_manualResetEvent != null) + { + return _manualResetEvent; + } + + lock (ThisLock) + { + if (_manualResetEvent == null) + { + _manualResetEvent = new ManualResetEvent(IsCompleted); + } + } + + return _manualResetEvent; + } + } + + public bool CompletedSynchronously { get; private set; } + + public bool HasCallback + { + get + { + return _callback != null; + } + } + + public bool IsCompleted { get; private set; } + + // used in conjunction with PrepareAsyncCompletion to allow for finally blocks + protected Action OnCompleting { get; set; } + + private object ThisLock + { + get + { + return _thisLock; + } + } + + // subclasses like TraceAsyncResult can use this to wrap the callback functionality in a scope + protected Action VirtualCallback + { + get; + set; + } + + protected void Complete(bool completedSynchronously) + { + if (IsCompleted) + { + throw new InvalidOperationException(SR.Format(SR.AsyncResultCompletedTwice, GetType())); + } + + + + CompletedSynchronously = completedSynchronously; + if (OnCompleting != null) + { + // Allow exception replacement, like a catch/throw pattern. + try + { + OnCompleting(this, _exception); + } + catch (Exception exception) + { + if (Fx.IsFatal(exception)) + { + throw; + } + _exception = exception; + } + } + + if (completedSynchronously) + { + // If we completedSynchronously, then there's no chance that the manualResetEvent was created so + // we don't need to worry about a race condition. + Debug.Assert(_manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult."); + IsCompleted = true; + } + else + { + lock (ThisLock) + { + IsCompleted = true; + if (_manualResetEvent != null) + { + _manualResetEvent.Set(); + } + } + } + + if (_callback != null) + { + try + { + if (VirtualCallback != null) + { + VirtualCallback(_callback, this); + } + else + { + _callback(this); + } + } + catch (Exception e) + { + if (Fx.IsFatal(e)) + { + throw; + } + + throw new CommunicationException(InternalSR.AsyncCallbackThrewException, e); + } + } + } + + protected void Complete(bool completedSynchronously, Exception exception) + { + _exception = exception; + Complete(completedSynchronously); + } + + private static void AsyncCompletionWrapperCallback(IAsyncResult result) + { + if (result == null) + { + throw new InvalidOperationException(InternalSR.InvalidNullAsyncResult); + } + if (result.CompletedSynchronously) + { + return; + } + + AsyncResult thisPtr = (AsyncResult)result.AsyncState; + if (!thisPtr.OnContinueAsyncCompletion(result)) + { + return; + } + + AsyncCompletion callback = thisPtr.GetNextCompletion(); + if (callback == null) + { + ThrowInvalidAsyncResult(result); + } + + bool completeSelf = false; + Exception completionException = null; + try + { + completeSelf = callback(result); + } + catch (Exception e) + { + if (Fx.IsFatal(e)) + { + throw; + } + completeSelf = true; + completionException = e; + } + + if (completeSelf) + { + thisPtr.Complete(false, completionException); + } + } + + // Note: this should be only derived by the TransactedAsyncResult + protected virtual bool OnContinueAsyncCompletion(IAsyncResult result) + { + return true; + } + + // Note: this should be used only by the TransactedAsyncResult + protected void SetBeforePrepareAsyncCompletionAction(Action beforePrepareAsyncCompletionAction) + { + _beforePrepareAsyncCompletionAction = beforePrepareAsyncCompletionAction; + } + + // Note: this should be used only by the TransactedAsyncResult + protected void SetCheckSyncValidationFunc(Func checkSyncValidationFunc) + { + _checkSyncValidationFunc = checkSyncValidationFunc; + } + + protected AsyncCallback PrepareAsyncCompletion(AsyncCompletion callback) + { + if (_beforePrepareAsyncCompletionAction != null) + { + _beforePrepareAsyncCompletionAction(); + } + + _nextAsyncCompletion = callback; + if (AsyncResult.s_asyncCompletionWrapperCallback == null) + { + AsyncResult.s_asyncCompletionWrapperCallback = new AsyncCallback(AsyncCompletionWrapperCallback); + } + return AsyncResult.s_asyncCompletionWrapperCallback; + } + + protected bool CheckSyncContinue(IAsyncResult result) + { + AsyncCompletion dummy; + return TryContinueHelper(result, out dummy); + } + + protected bool SyncContinue(IAsyncResult result) + { + AsyncCompletion callback; + if (TryContinueHelper(result, out callback)) + { + return callback(result); + } + else + { + return false; + } + } + + private bool TryContinueHelper(IAsyncResult result, out AsyncCompletion callback) + { + if (result == null) + { + throw new InvalidOperationException(InternalSR.InvalidNullAsyncResult); + } + + callback = null; + if (_checkSyncValidationFunc != null) + { + if (!_checkSyncValidationFunc(result)) + { + return false; + } + } + else if (!result.CompletedSynchronously) + { + return false; + } + + callback = GetNextCompletion(); + if (callback == null) + { + ThrowInvalidAsyncResult("Only call Check/SyncContinue once per async operation (once per PrepareAsyncCompletion)."); + } + return true; + } + + private AsyncCompletion GetNextCompletion() + { + AsyncCompletion result = _nextAsyncCompletion; + _nextAsyncCompletion = null; + return result; + } + + protected static void ThrowInvalidAsyncResult(IAsyncResult result) + { + throw new InvalidOperationException(InternalSR.InvalidAsyncResultImplementation(result.GetType())); + } + + protected static void ThrowInvalidAsyncResult(string debugText) + { + string message = InternalSR.InvalidAsyncResultImplementationGeneric; + if (debugText != null) + { +#if DEBUG + message += " " + debugText; +#endif + } + throw new InvalidOperationException(message); + } + + protected static TAsyncResult End(IAsyncResult result) + where TAsyncResult : AsyncResult + { + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + + TAsyncResult asyncResult = result as TAsyncResult; + + if (asyncResult == null) + { + throw new ArgumentException(InternalSR.InvalidAsyncResult, nameof(result)); + } + + if (asyncResult._endCalled) + { + throw new InvalidOperationException(InternalSR.AsyncResultAlreadyEnded); + } + + + asyncResult._endCalled = true; + + if (!asyncResult.IsCompleted) + { + asyncResult.AsyncWaitHandle.WaitOne(); + } + + if (asyncResult._manualResetEvent != null) + { + asyncResult._manualResetEvent.Dispose(); + } + + if (asyncResult._exception != null) + { + throw asyncResult._exception; + } + + return asyncResult; + } + + // can be utilized by subclasses to write core completion code for both the sync and async paths + // in one location, signalling chainable synchronous completion with the boolean result, + // and leveraging PrepareAsyncCompletion for conversion to an AsyncCallback. + // NOTE: requires that "this" is passed in as the state object to the asynchronous sub-call being used with a completion routine. + protected delegate bool AsyncCompletion(IAsyncResult result); + } +} diff --git a/src/System.ServiceModel.Federation/src/System/Runtime/TaskHelpers.cs b/src/System.ServiceModel.Federation/src/System/Runtime/TaskHelpers.cs new file mode 100644 index 00000000000..a39ef81059d --- /dev/null +++ b/src/System.ServiceModel.Federation/src/System/Runtime/TaskHelpers.cs @@ -0,0 +1,184 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics.Contracts; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Runtime +{ + internal static class TaskHelpers + { + // Helper method when implementing an APM wrapper around a Task based async method which returns a result. + // In the BeginMethod method, you would call use ToApm to wrap a call to MethodAsync: + // return MethodAsync(params).ToApm(callback, state); + // In the EndMethod, you would use ToApmEnd to ensure the correct exception handling + // This will handle throwing exceptions in the correct place and ensure the IAsyncResult contains the provided + // state object + public static Task ToApm(this Task task, AsyncCallback callback, object state) + { + // When using APM, the returned IAsyncResult must have the passed in state object stored in AsyncState. This + // is so the callback can regain state. If the incoming task already holds the state object, there's no need + // to create a TaskCompletionSource to ensure the returned (IAsyncResult)Task has the right state object. + // This is a performance optimization for this special case. + if (task.AsyncState == state) + { + if (callback != null) + { + task.ContinueWith((antecedent, obj) => + { + var callbackObj = obj as AsyncCallback; + callbackObj(antecedent); + }, callback, CancellationToken.None, TaskContinuationOptions.HideScheduler, TaskScheduler.Default); + } + return task; + } + + // Need to create a TaskCompletionSource so that the returned Task object has the correct AsyncState value. + var tcs = new TaskCompletionSource(state); + var continuationState = Tuple.Create(tcs, callback); + task.ContinueWith((antecedent, obj) => + { + var tuple = obj as Tuple, AsyncCallback>; + var tcsObj = tuple.Item1; + var callbackObj = tuple.Item2; + if (antecedent.IsFaulted) + { + tcsObj.TrySetException(antecedent.Exception.InnerException); + } + else if (antecedent.IsCanceled) + { + tcsObj.TrySetCanceled(); + } + else + { + tcsObj.TrySetResult(antecedent.Result); + } + + if (callbackObj != null) + { + callbackObj(tcsObj.Task); + } + }, continuationState, CancellationToken.None, TaskContinuationOptions.HideScheduler, TaskScheduler.Default); + return tcs.Task; + } + + // Helper method when implementing an APM wrapper around a Task based async method which returns a result. + // In the BeginMethod method, you would call use ToApm to wrap a call to MethodAsync: + // return MethodAsync(params).ToApm(callback, state); + // In the EndMethod, you would use ToApmEnd to ensure the correct exception handling + // This will handle throwing exceptions in the correct place and ensure the IAsyncResult contains the provided + // state object + public static Task ToApm(this Task task, AsyncCallback callback, object state) + { + // When using APM, the returned IAsyncResult must have the passed in state object stored in AsyncState. This + // is so the callback can regain state. If the incoming task already holds the state object, there's no need + // to create a TaskCompletionSource to ensure the returned (IAsyncResult)Task has the right state object. + // This is a performance optimization for this special case. + if (task.AsyncState == state) + { + if (callback != null) + { + task.ContinueWith((antecedent, obj) => + { + var callbackObj = obj as AsyncCallback; + callbackObj(antecedent); + }, callback, CancellationToken.None, TaskContinuationOptions.HideScheduler, TaskScheduler.Default); + } + return task; + } + + // Need to create a TaskCompletionSource so that the returned Task object has the correct AsyncState value. + // As we intend to create a task with no Result value, we don't care what result type the TCS holds as we + // won't be using it. As Task derives from Task, the returned Task is compatible. + var tcs = new TaskCompletionSource(state); + var continuationState = Tuple.Create(tcs, callback); + task.ContinueWith((antecedent, obj) => + { + var tuple = obj as Tuple, AsyncCallback>; + var tcsObj = tuple.Item1; + var callbackObj = tuple.Item2; + if (antecedent.IsFaulted) + { + tcsObj.TrySetException(antecedent.Exception.InnerException); + } + else if (antecedent.IsCanceled) + { + tcsObj.TrySetCanceled(); + } + else + { + tcsObj.TrySetResult(null); + } + + if (callbackObj != null) + { + callbackObj(tcsObj.Task); + } + }, continuationState, CancellationToken.None, TaskContinuationOptions.HideScheduler, TaskScheduler.Default); + return tcs.Task; + } + + // Helper method to implement the End method of an APM method pair which is wrapping a Task based + // async method when the Task returns a result. By using task.GetAwaiter.GetResult(), the exception + // handling conventions are the same as when await'ing a task, i.e. this throws the first exception + // and doesn't wrap it in an AggregateException. It also throws the right exception if the task was + // cancelled. + public static TResult ToApmEnd(this IAsyncResult iar) + { + Task task = iar as Task; + Contract.Assert(task != null, "IAsyncResult must be an instance of Task"); + return task.GetAwaiter().GetResult(); + } + + // Helper method to implement the End method of an APM method pair which is wrapping a Task based + // async method when the Task does not return result. + public static void ToApmEnd(this IAsyncResult iar) + { + Task task = iar as Task; + Contract.Assert(task != null, "IAsyncResult must be an instance of Task"); + task.GetAwaiter().GetResult(); + } + + // If the task is about to complete, this method will be more expensive than the regular method as it + // always causes a WaitHandle to be allocated. If it is expected that the task will take longer than + // the time of a spin wait, then a WaitHandle will be allocated anyway and this method avoids the CPU + // cost of the spin wait. + public static void WaitForCompletionNoSpin(this Task task) + { + if (!task.IsCompleted) + { + ((IAsyncResult)task).AsyncWaitHandle.WaitOne(); + } + + // Call GetResult() to get any exceptions that were thrown + task.GetAwaiter().GetResult(); + } + + private static readonly TimeSpan s_maxWait = TimeSpan.FromMilliseconds(int.MaxValue); + + public static bool WaitForCompletionNoSpin(this Task task, TimeSpan timeout) + { + if (timeout >= s_maxWait) + { + task.WaitForCompletionNoSpin(); + return true; + } + + bool completed = true; + if (!task.IsCompleted) + { + completed = ((IAsyncResult)task).AsyncWaitHandle.WaitOne(timeout); + } + + if (completed) + { + // Throw any exceptions if there are any + task.GetAwaiter().GetResult(); + } + + return completed; + } + } +} diff --git a/src/System.ServiceModel.Federation/src/System/Runtime/TimeoutHelper.cs b/src/System.ServiceModel.Federation/src/System/Runtime/TimeoutHelper.cs new file mode 100644 index 00000000000..87d07e6f671 --- /dev/null +++ b/src/System.ServiceModel.Federation/src/System/Runtime/TimeoutHelper.cs @@ -0,0 +1,206 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.Contracts; +using System.Threading; + +namespace System.Runtime +{ + internal struct TimeoutHelper + { + public static readonly TimeSpan MaxWait = TimeSpan.FromMilliseconds(int.MaxValue); + private static readonly CancellationToken s_precancelledToken = new CancellationToken(true); + + private bool _deadlineSet; + private DateTime _deadline; + + public TimeoutHelper(TimeSpan timeout) + { + Contract.Assert(timeout >= TimeSpan.Zero, "timeout must be non-negative"); + + OriginalTimeout = timeout; + _deadline = DateTime.MaxValue; + _deadlineSet = (timeout == TimeSpan.MaxValue); + } + + public TimeSpan OriginalTimeout { get; } + + public static bool IsTooLarge(TimeSpan timeout) + { + return (timeout > MaxWait) && (timeout != TimeSpan.MaxValue); + } + + //public static TimeSpan FromMilliseconds(int milliseconds) + //{ + // if (milliseconds == Timeout.Infinite) + // { + // return TimeSpan.MaxValue; + // } + // else + // { + // return TimeSpan.FromMilliseconds(milliseconds); + // } + //} + + //public static int ToMilliseconds(TimeSpan timeout) + //{ + // if (timeout == TimeSpan.MaxValue) + // { + // return Timeout.Infinite; + // } + // else + // { + // long ticks = Ticks.FromTimeSpan(timeout); + // if (ticks / TimeSpan.TicksPerMillisecond > int.MaxValue) + // { + // return int.MaxValue; + // } + // return Ticks.ToMilliseconds(ticks); + // } + //} + + //public static TimeSpan Min(TimeSpan val1, TimeSpan val2) + //{ + // if (val1 > val2) + // { + // return val2; + // } + // else + // { + // return val1; + // } + //} + + //public static TimeSpan Add(TimeSpan timeout1, TimeSpan timeout2) + //{ + // return Ticks.ToTimeSpan(Ticks.Add(Ticks.FromTimeSpan(timeout1), Ticks.FromTimeSpan(timeout2))); + //} + + //public static DateTime Add(DateTime time, TimeSpan timeout) + //{ + // if (timeout >= TimeSpan.Zero && DateTime.MaxValue - time <= timeout) + // { + // return DateTime.MaxValue; + // } + // if (timeout <= TimeSpan.Zero && DateTime.MinValue - time >= timeout) + // { + // return DateTime.MinValue; + // } + // return time + timeout; + //} + + //public static DateTime Subtract(DateTime time, TimeSpan timeout) + //{ + // return Add(time, TimeSpan.Zero - timeout); + //} + + //public static TimeSpan Divide(TimeSpan timeout, int factor) + //{ + // if (timeout == TimeSpan.MaxValue) + // { + // return TimeSpan.MaxValue; + // } + + // return Ticks.ToTimeSpan((Ticks.FromTimeSpan(timeout) / factor) + 1); + //} + + public TimeSpan RemainingTime() + { + if (!_deadlineSet) + { + SetDeadline(); + return OriginalTimeout; + } + else if (_deadline == DateTime.MaxValue) + { + return TimeSpan.MaxValue; + } + else + { + TimeSpan remaining = _deadline - DateTime.UtcNow; + if (remaining <= TimeSpan.Zero) + { + return TimeSpan.Zero; + } + else + { + return remaining; + } + } + } + + //public TimeSpan ElapsedTime() + //{ + // return OriginalTimeout - RemainingTime(); + //} + + private void SetDeadline() + { + Contract.Assert(!_deadlineSet, "TimeoutHelper deadline set twice."); + _deadline = DateTime.UtcNow + OriginalTimeout; + _deadlineSet = true; + } + + //public static void ThrowIfNegativeArgument(TimeSpan timeout) + //{ + // ThrowIfNegativeArgument(timeout, "timeout"); + //} + + //public static void ThrowIfNegativeArgument(TimeSpan timeout, string argumentName) + //{ + // if (timeout < TimeSpan.Zero) + // { + // throw Fx.Exception.ArgumentOutOfRange(argumentName, timeout, InternalSR.TimeoutMustBeNonNegative(argumentName, timeout)); + // } + //} + + //public static void ThrowIfNonPositiveArgument(TimeSpan timeout) + //{ + // ThrowIfNonPositiveArgument(timeout, "timeout"); + //} + + //public static void ThrowIfNonPositiveArgument(TimeSpan timeout, string argumentName) + //{ + // if (timeout <= TimeSpan.Zero) + // { + // throw Fx.Exception.ArgumentOutOfRange(argumentName, timeout, InternalSR.TimeoutMustBePositive(argumentName, timeout)); + // } + //} + + //public static bool WaitOne(WaitHandle waitHandle, TimeSpan timeout) + //{ + // ThrowIfNegativeArgument(timeout); + // if (timeout == TimeSpan.MaxValue) + // { + // waitHandle.WaitOne(); + // return true; + // } + // else + // { + // // http://msdn.microsoft.com/en-us/library/85bbbxt9(v=vs.110).aspx + // // with exitContext was used in Desktop which is not supported in Net Native or CoreClr + // return waitHandle.WaitOne(timeout); + // } + //} + + //public static bool Wait(ManualResetEventSlim mres, TimeSpan timeout) + //{ + // ThrowIfNegativeArgument(timeout); + // if (timeout == TimeSpan.MaxValue) + // { + // mres.Wait(); + // return true; + // } + // else + // { + // return mres.Wait(timeout); + // } + //} + + //internal static TimeoutException CreateEnterTimedOutException(TimeSpan timeout) + //{ + // return new TimeoutException(SRP.Format(SRP.LockTimeoutExceptionMessage, timeout)); + //} + } + +} diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/LogHelper.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/LogHelper.cs deleted file mode 100644 index ba23fdb121e..00000000000 --- a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/LogHelper.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Globalization; - -namespace System.ServiceModel.Federation -{ - /// - /// Helper class for logging. - /// - internal class LogHelper - { - /// - /// Formats the string using InvariantCulture - /// - /// Format string. - /// Format arguments. - /// Formatted string. - internal static string FormatInvariant(string format, params object[] args) - { - if (format == null) - return string.Empty; - - if (args == null) - return format; - - return string.Format(CultureInfo.InvariantCulture, format, args); - } - } -} diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannel.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannel.cs index e334ef1d4a7..06978a3571e 100644 --- a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannel.cs +++ b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannel.cs @@ -27,9 +27,9 @@ public class WSTrustChannel : IWSTrustChannelContract, IChannel, ICommunicationO /// The this channel will be used to send a to the STS. public WSTrustChannel(IRequestChannel requestChannel) { - RequestChannel = requestChannel ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(requestChannel)); + RequestChannel = requestChannel ?? throw new ArgumentNullException(nameof(requestChannel)); if (requestChannel.State != CommunicationState.Created) - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(LogHelper.FormatInvariant(SR.GetResourceString(SR.IRequestChannelMustBeCreated), requestChannel.State))); + throw new InvalidOperationException(SR.Format(SR.IRequestChannelMustBeCreated, requestChannel.State)); MessageVersion = RequestChannel.GetProperty(); if (MessageVersion == null || MessageVersion == MessageVersion.None) @@ -72,7 +72,7 @@ public WSTrustChannel(IRequestChannel requestChannel) /// The that represents the . protected virtual Message CreateRequest(WsTrustRequest trustRequest) { - _ = trustRequest ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(trustRequest)); + _ = trustRequest ?? throw new ArgumentNullException(nameof(trustRequest)); return Message.CreateMessage(MessageVersion, GetRequestAction(trustRequest), new WSTrustRequestBodyWriter(trustRequest, TrustSerializer)); @@ -85,7 +85,7 @@ protected virtual Message CreateRequest(WsTrustRequest trustRequest) /// The WS-Addressing action to use. public static string GetRequestAction(WsTrustRequest trustRequest) { - _ = trustRequest ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(trustRequest)); + _ = trustRequest ?? throw new ArgumentNullException(nameof(trustRequest)); WsTrustActions wsTrustActions; if (trustRequest.WsTrustVersion == WsTrustVersion.Trust13) @@ -95,7 +95,7 @@ public static string GetRequestAction(WsTrustRequest trustRequest) else if (trustRequest.WsTrustVersion == WsTrustVersion.Trust14) wsTrustActions = WsTrustActions.Trust14; else - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetResourceString(SR.WsTrustVersionNotSupported, trustRequest.WsTrustVersion.ToString()))); + throw new NotSupportedException(SR.Format(SR.WsTrustVersionNotSupported, trustRequest.WsTrustVersion.ToString())); if (trustRequest.RequestType.Equals(wsTrustActions.Issue)) return wsTrustActions.IssueRequest; @@ -106,7 +106,7 @@ public static string GetRequestAction(WsTrustRequest trustRequest) else if (trustRequest.RequestType.Equals(wsTrustActions.Validate)) return wsTrustActions.ValidateRequest; else - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetResourceString(SR.RequestTypeNotSupported, trustRequest.RequestType))); + throw new NotSupportedException(SR.Format(SR.RequestTypeNotSupported, trustRequest.RequestType)); } /// @@ -116,7 +116,7 @@ public static string GetRequestAction(WsTrustRequest trustRequest) /// The for the . private WsSerializationContext GetSerializationContext(WsTrustRequest trustRequest) { - _ = trustRequest ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(trustRequest)); + _ = trustRequest ?? throw new ArgumentNullException(nameof(trustRequest)); if (trustRequest.WsTrustVersion == WsTrustVersion.TrustFeb2005) { if (_wsSerializationContextTrustFeb2005 == null) @@ -139,7 +139,7 @@ private WsSerializationContext GetSerializationContext(WsTrustRequest trustReque return _wsSerializationContextTrust1_4; } - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetResourceString(SR.WsTrustVersionNotSupported, trustRequest.WsTrustVersion.ToString()))); + throw new NotSupportedException(SR.Format(SR.WsTrustVersionNotSupported, trustRequest.WsTrustVersion.ToString())); } #region IChannel Members @@ -201,7 +201,7 @@ event EventHandler ICommunicationObject.Opening } /// - /// Causes a communication object to transition immediately from its current state into the closed state. + /// Causes a communication object to transition immediately from its current state into the closed state. /// void ICommunicationObject.Abort() { @@ -215,11 +215,11 @@ void ICommunicationObject.Abort() /// The that specifies how long the close operation has to complete before timing out. /// /// - /// The delegate that receives notification of the completion of the asynchronous + /// The delegate that receives notification of the completion of the asynchronous /// close operation. /// /// - /// An object, specified by the application, that contains state information associated with the asynchronous + /// An object, specified by the application, that contains state information associated with the asynchronous /// close operation. /// /// The that references the asynchronous close operation. @@ -232,11 +232,11 @@ IAsyncResult ICommunicationObject.BeginClose(TimeSpan timeout, AsyncCallback cal /// Begins an asynchronous operation to close a communication object. /// /// - /// The delegate that receives notification of the completion of the asynchronous + /// The delegate that receives notification of the completion of the asynchronous /// close operation. /// /// - /// An object, specified by the application, that contains state information associated with the asynchronous + /// An object, specified by the application, that contains state information associated with the asynchronous /// close operation. /// /// The that references the asynchronous close operation. @@ -252,11 +252,11 @@ IAsyncResult ICommunicationObject.BeginClose(AsyncCallback callback, object stat /// The that specifies how long the open operation has to complete before timing out. /// /// - /// The delegate that receives notification of the completion of the asynchronous + /// The delegate that receives notification of the completion of the asynchronous /// close operation. /// /// - /// An object, specified by the application, that contains state information associated with the asynchronous + /// An object, specified by the application, that contains state information associated with the asynchronous /// close operation. /// /// The that references the asynchronous open operation. @@ -269,11 +269,11 @@ IAsyncResult ICommunicationObject.BeginOpen(TimeSpan timeout, AsyncCallback call /// Begins an asynchronous operation to open a communication object. /// /// - /// The delegate that receives notification of the completion of the asynchronous + /// The delegate that receives notification of the completion of the asynchronous /// close operation. /// /// - /// An object, specified by the application, that contains state information associated with the asynchronous + /// An object, specified by the application, that contains state information associated with the asynchronous /// close operation. /// /// The that references the asynchronous open operation. @@ -331,7 +331,7 @@ void ICommunicationObject.Open(TimeSpan timeout) } /// - /// Causes a communication object to transition from the created state into the opened state. + /// Causes a communication object to transition from the created state into the opened state. /// void ICommunicationObject.Open() { @@ -355,21 +355,21 @@ CommunicationState ICommunicationObject.State /// A issued by the STS. public async virtual Task IssueAsync(WsTrustRequest trustRequest) { - _ = trustRequest ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(trustRequest)); + _ = trustRequest ?? throw new ArgumentNullException(nameof(trustRequest)); Message requestMessage = CreateRequest(trustRequest); Message response = await Task.Factory.FromAsync(RequestChannel.BeginRequest, RequestChannel.EndRequest, requestMessage, null, TaskCreationOptions.None).ConfigureAwait(false); if (response.IsFault) { MessageFault fault = MessageFault.CreateFault(response, FaultMaxBufferSize); - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(FaultException.CreateFault(fault, response.Headers?.Action)); + throw FaultException.CreateFault(fault, response.Headers?.Action); } WsTrustResponse trustResponse = TrustSerializer.ReadResponse(response.GetReaderAtBodyContents()); WCFSecurityToken token = WSTrustUtilities.CreateGenericXmlSecurityToken(trustRequest, trustResponse, GetSerializationContext(trustRequest), null); if (token == null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.Format(SR.TokenProviderUnableToGetToken, string.IsNullOrEmpty(Address) ? ToString() : Address))); - + throw new SecurityTokenException(SR.Format(SR.TokenProviderUnableToGetToken, string.IsNullOrEmpty(Address) ? ToString() : Address)); + return token; } #endregion diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannelFactory.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannelFactory.cs index 6ad16cb4bc1..e3b13e5ae07 100644 --- a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannelFactory.cs +++ b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannelFactory.cs @@ -20,7 +20,7 @@ public class WSTrustChannelFactory : ChannelFactory public WSTrustChannelFactory(ServiceEndpoint serviceEndpoint) : base(serviceEndpoint) { - _ = serviceEndpoint ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serviceEndpoint)); + _ = serviceEndpoint ?? throw new ArgumentNullException(nameof(serviceEndpoint)); EndpointAddress = serviceEndpoint.Address; } @@ -32,9 +32,9 @@ public WSTrustChannelFactory(ServiceEndpoint serviceEndpoint) public WSTrustChannelFactory(Binding binding, EndpointAddress endpointAddress) : base(binding, endpointAddress) { - _ = binding ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(binding)); + _ = binding ?? throw new ArgumentNullException(nameof(binding)); - EndpointAddress = endpointAddress ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(endpointAddress)); + EndpointAddress = endpointAddress ?? throw new ArgumentNullException(nameof(endpointAddress)); } /// @@ -45,8 +45,8 @@ public WSTrustChannelFactory(Binding binding, EndpointAddress endpointAddress) /// A that can be used to send an Issue request to a STS. public override IWSTrustChannelContract CreateChannel(EndpointAddress endpointAddress, Uri via) { - _ = endpointAddress ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(endpointAddress)); - _ = via ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(via)); + _ = endpointAddress ?? throw new ArgumentNullException(nameof(endpointAddress)); + _ = via ?? throw new ArgumentNullException(nameof(via)); return new WSTrustChannel(base.CreateChannel(endpointAddress, via) as IRequestChannel); } diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannelSecurityTokenProvider.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannelSecurityTokenProvider.cs index 1f96d5d650c..ffe3e70050f 100644 --- a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannelSecurityTokenProvider.cs +++ b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannelSecurityTokenProvider.cs @@ -8,10 +8,8 @@ using System.IdentityModel.Selectors; using System.IdentityModel.Tokens; using System.IO; -using System.Runtime.Diagnostics; using System.ServiceModel.Channels; using System.ServiceModel.Description; -using System.ServiceModel.Diagnostics; using System.Runtime; using System.ServiceModel.Security; using System.ServiceModel.Security.Tokens; @@ -44,7 +42,6 @@ public class WSTrustChannelSecurityTokenProvider : SecurityTokenProvider, ICommu private readonly SecurityAlgorithmSuite _securityAlgorithmSuite; private WsSerializationContext _requestSerializationContext; private WrapperSecurityCommunicationObject _communicationObject; - private EventTraceActivity _eventTraceActivity; /// /// Instantiates a that describe the parameters for a WSTrust request. @@ -54,14 +51,14 @@ public class WSTrustChannelSecurityTokenProvider : SecurityTokenProvider, ICommu /// thrown if (IssuedSecurityTokenParameters) is not a . public WSTrustChannelSecurityTokenProvider(SecurityTokenRequirement tokenRequirement) { - SecurityTokenRequirement = tokenRequirement ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new ArgumentNullException(nameof(tokenRequirement)), EventLevel.Error); + SecurityTokenRequirement = tokenRequirement ?? throw new ArgumentNullException(nameof(tokenRequirement)); SecurityTokenRequirement.TryGetProperty(SecurityAlgorithmSuiteProperty, out _securityAlgorithmSuite); IssuedSecurityTokenParameters issuedSecurityTokenParameters = SecurityTokenRequirement.GetProperty(IssuedSecurityTokenParametersProperty); WSTrustTokenParameters = issuedSecurityTokenParameters as WSTrustTokenParameters; if (WSTrustTokenParameters == null) { - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new ArgumentException(LogHelper.FormatInvariant(SR.GetResourceString(SR.IssuedSecurityTokenParametersIncorrectType), issuedSecurityTokenParameters), nameof(tokenRequirement)), EventLevel.Error); + throw new ArgumentException(SR.Format(SR.IssuedSecurityTokenParametersIncorrectType, issuedSecurityTokenParameters), nameof(tokenRequirement)); } _communicationObject = new WrapperSecurityCommunicationObject(this); @@ -139,7 +136,7 @@ protected virtual WsTrustRequest CreateWsTrustRequest() keyType = _requestSerializationContext.TrustKeyTypes.Bearer; break; default: - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new NotSupportedException(LogHelper.FormatInvariant("KeyType is not supported: {0}", WSTrustTokenParameters.KeyType)), EventLevel.Error); + throw new NotSupportedException(SR.Format(SR.KeyTypeNotSupported, WSTrustTokenParameters.KeyType)); } Entropy entropy = null; @@ -186,7 +183,7 @@ protected virtual WsTrustRequest CreateWsTrustRequest() trustRequest.Claims = new Claims(WSTrustTokenParameters.Claims.Dialect, claimTypes); } - + foreach (XmlElement parameter in WSTrustTokenParameters.AdditionalRequestParameters) { trustRequest.AdditionalXmlElements.Add((XmlElement)parameter.CloneNode(true)); @@ -195,18 +192,6 @@ protected virtual WsTrustRequest CreateWsTrustRequest() return trustRequest; } - private EventTraceActivity EventTraceActivity - { - get - { - if (_eventTraceActivity == null) - { - _eventTraceActivity = EventTraceActivity.GetFromThreadOrCreate(); - } - return _eventTraceActivity; - } - } - private WsTrustResponse GetCachedResponse(WsTrustRequest request) { if (WSTrustTokenParameters.CacheIssuedTokens && CachedResponse != null) @@ -319,7 +304,7 @@ private WsTrustVersion GetWsTrustVersion(MessageSecurityVersion messageSecurityV if (messageSecurityVersion.TrustVersion == TrustVersion.WSTrustFeb2005) return WsTrustVersion.TrustFeb2005; - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new NotSupportedException(LogHelper.FormatInvariant(SR.GetResourceString(SR.WsTrustVersionNotSupported), MessageSecurityVersion.TrustVersion)), EventLevel.Error); + throw new NotSupportedException(SR.Format(SR.WsTrustVersionNotSupported, MessageSecurityVersion.TrustVersion)); } private void InitializeKeyEntropyMode() @@ -381,8 +366,7 @@ internal SecurityKeyEntropyMode KeyEntropyMode set { if (!Enum.IsDefined(typeof(SecurityKeyEntropyMode), value)) - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidEnumArgumentException(nameof(value), (int)value, typeof(SecurityKeyEntropyMode)), EventLevel.Error); - + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(SecurityKeyEntropyMode)); _keyEntropyMode = value; } } @@ -491,10 +475,7 @@ void ISecurityCommunicationObject.OnClosing() { } void ISecurityCommunicationObject.OnFaulted() { } - void ISecurityCommunicationObject.OnOpened() - { - SecurityTraceRecordHelper.TraceTokenProviderOpened(EventTraceActivity, this); - } + void ISecurityCommunicationObject.OnOpened() { } void ISecurityCommunicationObject.OnOpening() { } diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustRequestBodyWriter.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustRequestBodyWriter.cs index d1823b4cae5..cc34ea834e2 100644 --- a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustRequestBodyWriter.cs +++ b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustRequestBodyWriter.cs @@ -20,8 +20,8 @@ internal class WSTrustRequestBodyWriter : BodyWriter /// The used to write the into a . public WSTrustRequestBodyWriter(WsTrustRequest trustRequest, WsTrustSerializer trustSerializer) : base(true) { - TrustRequest = trustRequest ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(trustRequest)); - TrustSerializer = trustSerializer ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(trustSerializer)); + TrustRequest = trustRequest ?? throw new ArgumentNullException(nameof(trustRequest)); + TrustSerializer = trustSerializer ?? throw new ArgumentNullException(nameof(trustSerializer)); } /// diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustUtilities.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustUtilities.cs index 25226a9e2c8..eed10ddf151 100644 --- a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustUtilities.cs +++ b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustUtilities.cs @@ -44,13 +44,13 @@ internal static BinarySecretSecurityToken GetProofToken(WsTrustRequest request, // Encrypted keys and encrypted entropy are not supported, currently, as they should // only be needed by unsupported message security scenarios. if (response.RequestedProofToken?.EncryptedKey != null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new NotSupportedException(SR.GetResourceString(SR.EncryptedKeysForProofTokensNotSupported)), EventLevel.Error); + throw new NotSupportedException(SR.EncryptedKeysForProofTokensNotSupported); // Bearer scenarios have no proof token if (string.Equals(keyType, serializationContext.TrustKeyTypes.Bearer, StringComparison.Ordinal)) { if (response.RequestedProofToken != null || response.Entropy != null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidOperationException(SR.GetResourceString(SR.BearerKeyShouldNotIincludeAProofToken)), EventLevel.Error); + throw new InvalidOperationException(SR.BearerKeyShouldNotIincludeAProofToken); return null; } @@ -61,7 +61,7 @@ internal static BinarySecretSecurityToken GetProofToken(WsTrustRequest request, { // Confirm that a computed key algorithm isn't also specified if (!string.IsNullOrEmpty(response.RequestedProofToken.ComputedKeyAlgorithm) || response.Entropy != null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidOperationException(SR.GetResourceString(SR.RSTRProofTokenShouldNotHaveAComputedKeyAlgorithmOrIssuerEntropy)), EventLevel.Error); + throw new InvalidOperationException(SR.RSTRProofTokenShouldNotHaveAComputedKeyAlgorithmOrIssuerEntropy); return new BinarySecretSecurityToken(response.RequestedProofToken.BinarySecret.Data); } @@ -70,7 +70,7 @@ internal static BinarySecretSecurityToken GetProofToken(WsTrustRequest request, else if (response.RequestedProofToken?.ComputedKeyAlgorithm != null) { if (!string.Equals(keyType, serializationContext.TrustKeyTypes.Symmetric, StringComparison.Ordinal)) - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidOperationException(SR.GetResourceString(SR.ComputedKeyProofTokensAreOnlySupportedWithSymmetricKeyTypes)), EventLevel.Error); + throw new InvalidOperationException(SR.ComputedKeyProofTokensAreOnlySupportedWithSymmetricKeyTypes); if (string.Equals(response.RequestedProofToken.ComputedKeyAlgorithm, serializationContext.TrustKeyTypes.PSHA1, StringComparison.Ordinal)) { @@ -78,16 +78,16 @@ internal static BinarySecretSecurityToken GetProofToken(WsTrustRequest request, // If we wish to support it in the future, most of the work will be in the WSTrust serializer; // this code would just have to use protected key's .Secret property to get the key material. if (response.Entropy?.ProtectedKey != null || request.Entropy?.ProtectedKey != null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelper( new NotSupportedException(SR.GetResourceString(SR.ProtectedKeyEntropyIsNotSupported)), EventLevel.Error); + throw new NotSupportedException(SR.ProtectedKeyEntropyIsNotSupported); // Get issuer and requester entropy byte[] issuerEntropy = response.Entropy?.BinarySecret?.Data; if (issuerEntropy == null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidOperationException(SR.GetResourceString(SR.ComputedKeyProofTokensRequireIssuerToSupplyKeyMaterialViaEntropy)), EventLevel.Error); + throw new InvalidOperationException(SR.ComputedKeyProofTokensRequireIssuerToSupplyKeyMaterialViaEntropy); byte[] requestorEntropy = request.Entropy?.BinarySecret?.Data; if (requestorEntropy == null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidOperationException(SR.GetResourceString(SR.ComputedKeyProofTokensRequireRequesterToSupplyKeyMaterialViaEntropy)), EventLevel.Error); + throw new InvalidOperationException(SR.ComputedKeyProofTokensRequireRequesterToSupplyKeyMaterialViaEntropy); // Get key size int keySizeInBits = response.KeySizeInBits ?? 0; // RSTR key size has precedence @@ -98,13 +98,13 @@ internal static BinarySecretSecurityToken GetProofToken(WsTrustRequest request, keySizeInBits = algorithmSuite?.DefaultSymmetricKeyLength ?? 0; // Symmetric keys should default to a length corresponding to the algorithm in use if (keySizeInBits == 0) - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new InvalidOperationException(SR.GetResourceString(SR.NoKeySizeProvided)), EventLevel.Error); + throw new InvalidOperationException(SR.NoKeySizeProvided); return new BinarySecretSecurityToken(Psha1KeyGenerator.ComputeCombinedKey(issuerEntropy, requestorEntropy, keySizeInBits)); } else { - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new NotSupportedException(SR.GetResourceString(SR.OnlyPSHA1ComputedKeysAreSupported)), EventLevel.Error); + throw new NotSupportedException(SR.OnlyPSHA1ComputedKeysAreSupported); } } // If the response does not have a proof token or computed key value, but the request proposed entropy, @@ -112,7 +112,7 @@ internal static BinarySecretSecurityToken GetProofToken(WsTrustRequest request, else if (request.Entropy != null) { if (request.Entropy.ProtectedKey != null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new NotSupportedException(SR.GetResourceString(SR.ProtectedKeyEntropyIsNotSupported)), EventLevel.Error); + throw new NotSupportedException(SR.ProtectedKeyEntropyIsNotSupported); if (request.Entropy.BinarySecret != null) return new BinarySecretSecurityToken(request.Entropy.BinarySecret.Data); diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WsTrustChannelSecurityTokenManager.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WsTrustChannelSecurityTokenManager.cs index c35a37080df..d0b0e600929 100644 --- a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WsTrustChannelSecurityTokenManager.cs +++ b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WsTrustChannelSecurityTokenManager.cs @@ -25,7 +25,7 @@ public class WSTrustChannelSecurityTokenManager : ClientCredentialsSecurityToken public WSTrustChannelSecurityTokenManager(WSTrustChannelClientCredentials wsTrustChannelClientCredentials) : base(wsTrustChannelClientCredentials) { - _wsTrustChannelClientCredentials = wsTrustChannelClientCredentials ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new ArgumentNullException(nameof(wsTrustChannelClientCredentials)), EventLevel.Error); + _wsTrustChannelClientCredentials = wsTrustChannelClientCredentials ?? throw new ArgumentNullException(nameof(wsTrustChannelClientCredentials)); } /// @@ -36,7 +36,7 @@ public WSTrustChannelSecurityTokenManager(WSTrustChannelClientCredentials wsTrus public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement) { if (tokenRequirement == null) - throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new ArgumentNullException(nameof(tokenRequirement)), EventLevel.Error); + throw new ArgumentNullException(nameof(tokenRequirement)); // If the token requirement includes an issued security token parameter of type // WSTrustTokenParameters, then tokens should be provided by a WSTrustChannelSecurityTokenProvider. diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WsTrustTokenParameters.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WsTrustTokenParameters.cs index 11a11e21b9f..5b04b7fa9c8 100644 --- a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WsTrustTokenParameters.cs +++ b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WsTrustTokenParameters.cs @@ -125,7 +125,7 @@ public int IssuedTokenRenewalThresholdPercentage { get => _issuedTokenRenewalThresholdPercentage; set => _issuedTokenRenewalThresholdPercentage = (value <= 0 || value > 100) - ? throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new ArgumentOutOfRangeException(nameof(value), LogHelper.FormatInvariant(SR.GetResourceString(SR.IssuedTokenRenewalThresholdPercentageIncorrect), value)), EventLevel.Error) + ? throw new ArgumentOutOfRangeException(nameof(value), SR.Format(SR.IssuedTokenRenewalThresholdPercentageIncorrect, value)) : value; } @@ -153,7 +153,7 @@ public TimeSpan MaxIssuedTokenCachingTime { get => _maxIssuedTokenCachingTime; set => _maxIssuedTokenCachingTime = value <= TimeSpan.Zero - ? throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new ArgumentOutOfRangeException(nameof(value), LogHelper.FormatInvariant(SR.GetResourceString(SR.MaxIssuedTokenCachingTimeMustBeGreaterThanTimeSpanZero), value)), EventLevel.Error) + ? throw new ArgumentOutOfRangeException(nameof(value), SR.Format(SR.MaxIssuedTokenCachingTimeMustBeGreaterThanTimeSpanZero, value)) : value; } @@ -163,7 +163,7 @@ public TimeSpan MaxIssuedTokenCachingTime public MessageSecurityVersion MessageSecurityVersion { get => _messageSecurityVersion; - set => _messageSecurityVersion = value ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelper(new ArgumentNullException(nameof(value)), EventLevel.Error); + set => _messageSecurityVersion = value ?? throw new ArgumentNullException(nameof(value)); } /// diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/ISecurityCommunicationObject.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/ISecurityCommunicationObject.cs new file mode 100644 index 00000000000..e590fa85901 --- /dev/null +++ b/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/ISecurityCommunicationObject.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System.Threading.Tasks; + +namespace System.ServiceModel.Security +{ + internal interface ISecurityCommunicationObject + { + TimeSpan DefaultOpenTimeout { get; } + TimeSpan DefaultCloseTimeout { get; } + void OnAbort(); + Task OnCloseAsync(TimeSpan timeout); + void OnClosed(); + void OnClosing(); + void OnFaulted(); + Task OnOpenAsync(TimeSpan timeout); + void OnOpened(); + void OnOpening(); + } +} diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/SecurityUtils.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/SecurityUtils.cs new file mode 100644 index 00000000000..c1334864381 --- /dev/null +++ b/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/SecurityUtils.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ServiceModel.Channels; + +namespace System.ServiceModel.Security +{ + internal static class SecurityUtils + { + // Copied from TransportDefaults + public const int MaxSecurityFaultSize = 16384; + + internal static void ThrowIfNegotiationFault(Message message, EndpointAddress target) + { + if (message.IsFault) + { + MessageFault fault = MessageFault.CreateFault(message, MaxSecurityFaultSize); + Exception faultException = new FaultException(fault, message.Headers.Action); + if (fault.Code != null && fault.Code.IsReceiverFault && fault.Code.SubCode != null) + { + FaultCode subCode = fault.Code.SubCode; + if (subCode.Name == "ServerTooBusy" && subCode.Namespace == "http://schemas.microsoft.com/ws/2006/05/security") + { + throw new ServerTooBusyException(SR.Format(SR.SecurityServerTooBusy, target), faultException); + } + else if (subCode.Name == "EndpointUnavailable" && subCode.Namespace == message.Version.Addressing.Namespace()) + { + throw new EndpointNotFoundException(SR.Format(SR.SecurityEndpointNotFound, target), faultException); + } + } + + throw faultException; + } + } + } + + internal static class AddressingVersionExtensions + { + public static string Namespace(this AddressingVersion addressingVersion) + { + // AddressingVersion.ToString() returns the string "{addressing name} ({addressing namespace})" so we can + // extract the namespace out easily. + var addressingVersionString = addressingVersion.ToString(); + int pos = addressingVersionString.IndexOf('('); + return addressingVersionString.Substring(pos + 1, addressingVersionString.Length - pos - 2); + } + } +} diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/ServiceDefaults.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/ServiceDefaults.cs new file mode 100644 index 00000000000..6d2e53182f4 --- /dev/null +++ b/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/ServiceDefaults.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +namespace System.ServiceModel +{ + internal static class ServiceDefaults + { + public static TimeSpan CloseTimeout { get { return TimeSpan.FromMinutes(1); } } + public static TimeSpan OpenTimeout { get { return TimeSpan.FromMinutes(1); } } + public static TimeSpan ReceiveTimeout { get { return TimeSpan.FromMinutes(10); } } + public static TimeSpan SendTimeout { get { return TimeSpan.FromMinutes(1); } } + } +} diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/WrapperSecurityCommunicationObject.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/WrapperSecurityCommunicationObject.cs new file mode 100644 index 00000000000..8c0096eac12 --- /dev/null +++ b/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/WrapperSecurityCommunicationObject.cs @@ -0,0 +1,494 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +using System.ServiceModel.Channels; +using System.IdentityModel.Selectors; +using System.Threading.Tasks; +using System.Runtime; + +namespace System.ServiceModel.Security +{ + internal class WrapperSecurityCommunicationObject : CommunicationObject + { + private ISecurityCommunicationObject _innerCommunicationObject; + + public WrapperSecurityCommunicationObject(ISecurityCommunicationObject innerCommunicationObject) + : base() + { + _innerCommunicationObject = innerCommunicationObject ?? throw new ArgumentNullException(nameof(innerCommunicationObject)); + } + + internal Type GetCommunicationObjectInnerType() + { + return _innerCommunicationObject.GetType(); + } + + protected override Type GetCommunicationObjectType() + { + return _innerCommunicationObject.GetType(); + } + + protected override TimeSpan DefaultCloseTimeout + { + get { return _innerCommunicationObject.DefaultCloseTimeout; } + } + + protected override TimeSpan DefaultOpenTimeout + { + get { return _innerCommunicationObject.DefaultOpenTimeout; } + } + + protected override void OnAbort() + { + _innerCommunicationObject.OnAbort(); + } + + protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) + { + return OnCloseAsync(timeout).ToApm(callback, state); + } + + protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) + { + return OnOpenAsync(timeout).ToApm(callback, state); + } + + protected override void OnClose(TimeSpan timeout) + { + _innerCommunicationObject.OnCloseAsync(timeout).GetAwaiter().GetResult(); + } + + protected override void OnClosed() + { + _innerCommunicationObject.OnClosed(); + base.OnClosed(); + } + + protected override void OnClosing() + { + _innerCommunicationObject.OnClosing(); + base.OnClosing(); + } + + protected override void OnEndClose(IAsyncResult result) + { + result.ToApmEnd(); + } + + protected override void OnEndOpen(IAsyncResult result) + { + result.ToApmEnd(); + } + + protected override void OnFaulted() + { + _innerCommunicationObject.OnFaulted(); + base.OnFaulted(); + } + + protected override void OnOpen(TimeSpan timeout) + { + _innerCommunicationObject.OnOpenAsync(timeout).GetAwaiter().GetResult(); + } + + protected override void OnOpened() + { + _innerCommunicationObject.OnOpened(); + base.OnOpened(); + } + + protected override void OnOpening() + { + _innerCommunicationObject.OnOpening(); + base.OnOpening(); + } + + internal Task OnCloseAsync(TimeSpan timeout) + { + return _innerCommunicationObject.OnCloseAsync(timeout); + } + + internal Task OnOpenAsync(TimeSpan timeout) + { + return _innerCommunicationObject.OnOpenAsync(timeout); + } + + internal void ThrowIfClosedOrNotOpen() + { + switch (State) + { + case CommunicationState.Created: + throw CreateNotOpenException(); + + case CommunicationState.Opening: + throw CreateNotOpenException(); + + case CommunicationState.Opened: + break; + + case CommunicationState.Closing: + break; + + case CommunicationState.Closed: + throw CreateClosedException(); + + case CommunicationState.Faulted: + throw CreateFaultedException(); + + default: + throw new Exception("ThrowIfClosedOrNotOpen: Unknown CommunicationObject.state"); + } + } + + private Exception CreateNotOpenException() + { + return new InvalidOperationException(SR.Format(SR.CommunicationObjectCannotBeUsed, GetCommunicationObjectType().ToString(), State.ToString())); + } + + private Exception CreateClosedException() + { + return new ObjectDisposedException(GetCommunicationObjectType().ToString()); + } + + internal Exception CreateFaultedException() + { + string message = SR.Format(SR.CommunicationObjectFaulted1, GetCommunicationObjectType().ToString()); + return new CommunicationObjectFaultedException(message); + } + + internal abstract class CommunicationObjectSecurityTokenProvider : SecurityTokenProvider, ISecurityCommunicationObject + { + + protected CommunicationObjectSecurityTokenProvider() + { + CommunicationObject = new WrapperSecurityCommunicationObject(this); + } + + protected WrapperSecurityCommunicationObject CommunicationObject { get; } + + public event EventHandler Closed + { + add { CommunicationObject.Closed += value; } + remove { CommunicationObject.Closed -= value; } + } + + public event EventHandler Closing + { + add { CommunicationObject.Closing += value; } + remove { CommunicationObject.Closing -= value; } + } + + public event EventHandler Faulted + { + add { CommunicationObject.Faulted += value; } + remove { CommunicationObject.Faulted -= value; } + } + + public event EventHandler Opened + { + add { CommunicationObject.Opened += value; } + remove { CommunicationObject.Opened -= value; } + } + + public event EventHandler Opening + { + add { CommunicationObject.Opening += value; } + remove { CommunicationObject.Opening -= value; } + } + + public CommunicationState State + { + get { return CommunicationObject.State; } + } + + public virtual TimeSpan DefaultOpenTimeout + { + get { return ServiceDefaults.OpenTimeout; } + } + + public virtual TimeSpan DefaultCloseTimeout + { + get { return ServiceDefaults.CloseTimeout; } + } + + // communication object + public void Abort() + { + CommunicationObject.Abort(); + } + + public void Close() + { + CommunicationObject.Close(); + } + + public void Close(TimeSpan timeout) + { + CommunicationObject.Close(timeout); + } + + public IAsyncResult BeginClose(AsyncCallback callback, object state) + { + return CommunicationObject.BeginClose(callback, state); + } + + public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state) + { + return CommunicationObject.BeginClose(timeout, callback, state); + } + + public void EndClose(IAsyncResult result) + { + CommunicationObject.EndClose(result); + } + + public void Open() + { + CommunicationObject.Open(); + } + + public void Open(TimeSpan timeout) + { + CommunicationObject.Open(timeout); + } + + public IAsyncResult BeginOpen(AsyncCallback callback, object state) + { + return CommunicationObject.BeginOpen(callback, state); + } + + public IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state) + { + return CommunicationObject.BeginOpen(timeout, callback, state); + } + + public void EndOpen(IAsyncResult result) + { + CommunicationObject.EndOpen(result); + } + + public void Dispose() + { + Close(); + } + + // ISecurityCommunicationObject methods + public virtual void OnAbort() + { + } + + public virtual Task OnCloseAsync(TimeSpan timeout) + { + return Task.CompletedTask; + } + + public virtual void OnClosed() + { + } + + public virtual void OnClosing() + { + } + + public virtual void OnFaulted() + { + OnAbort(); + } + + public virtual Task OnOpenAsync(TimeSpan timeout) + { + return Task.CompletedTask; + } + + public virtual void OnOpened() + { + } + + public virtual void OnOpening() + { + } + } + + internal abstract class CommunicationObjectSecurityTokenAuthenticator : SecurityTokenAuthenticator, ICommunicationObject, ISecurityCommunicationObject + { + protected CommunicationObjectSecurityTokenAuthenticator() + { + CommunicationObject = new WrapperSecurityCommunicationObject(this); + } + + protected WrapperSecurityCommunicationObject CommunicationObject { get; } + + public event EventHandler Closed + { + add { CommunicationObject.Closed += value; } + remove { CommunicationObject.Closed -= value; } + } + + public event EventHandler Closing + { + add { CommunicationObject.Closing += value; } + remove { CommunicationObject.Closing -= value; } + } + + public event EventHandler Faulted + { + add { CommunicationObject.Faulted += value; } + remove { CommunicationObject.Faulted -= value; } + } + + public event EventHandler Opened + { + add { CommunicationObject.Opened += value; } + remove { CommunicationObject.Opened -= value; } + } + + public event EventHandler Opening + { + add { CommunicationObject.Opening += value; } + remove { CommunicationObject.Opening -= value; } + } + + public CommunicationState State + { + get { return CommunicationObject.State; } + } + + public virtual TimeSpan DefaultOpenTimeout + { + get { return ServiceDefaults.OpenTimeout; } + } + + public virtual TimeSpan DefaultCloseTimeout + { + get { return ServiceDefaults.CloseTimeout; } + } + + // communication object + public void Abort() + { + CommunicationObject.Abort(); + } + + public void Close() + { + CommunicationObject.Close(); + } + + public void Close(TimeSpan timeout) + { + CommunicationObject.Close(timeout); + } + + public IAsyncResult BeginClose(AsyncCallback callback, object state) + { + return CommunicationObject.BeginClose(callback, state); + } + + public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state) + { + return CommunicationObject.BeginClose(timeout, callback, state); + } + + public void EndClose(IAsyncResult result) + { + CommunicationObject.EndClose(result); + } + + public void Open() + { + CommunicationObject.Open(); + } + + public void Open(TimeSpan timeout) + { + CommunicationObject.Open(timeout); + } + + public IAsyncResult BeginOpen(AsyncCallback callback, object state) + { + return CommunicationObject.BeginOpen(callback, state); + } + + public IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state) + { + return CommunicationObject.BeginOpen(timeout, callback, state); + } + + public void EndOpen(IAsyncResult result) + { + CommunicationObject.EndOpen(result); + } + + public void Dispose() + { + Close(); + } + + // ISecurityCommunicationObject methods + public virtual void OnAbort() + { + } + + public IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) + { + return new OperationWithTimeoutAsyncResult(OnClose, timeout, callback, state); + } + + public IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) + { + return new OperationWithTimeoutAsyncResult(OnOpen, timeout, callback, state); + } + + public virtual void OnClose(TimeSpan timeout) + { + } + + public Task OnCloseAsync(TimeSpan timeout) + { + return Task.CompletedTask; + } + + public virtual void OnClosed() + { + } + + public virtual void OnClosing() + { + } + + public void OnEndClose(IAsyncResult result) + { + OperationWithTimeoutAsyncResult.End(result); + } + + public void OnEndOpen(IAsyncResult result) + { + OperationWithTimeoutAsyncResult.End(result); + } + + public virtual void OnFaulted() + { + OnAbort(); + } + + public virtual void OnOpen(TimeSpan timeout) + { + } + + public Task OnOpenAsync(TimeSpan timeout) + { + return Task.CompletedTask; + } + + public virtual void OnOpened() + { + } + + public virtual void OnOpening() + { + } + } + } +} diff --git a/src/System.ServiceModel.Primitives/ref/System.ServiceModel.Primitives.netstandard.cs b/src/System.ServiceModel.Primitives/ref/System.ServiceModel.Primitives.netstandard.cs index f074735230a..6bb4ea028a8 100644 --- a/src/System.ServiceModel.Primitives/ref/System.ServiceModel.Primitives.netstandard.cs +++ b/src/System.ServiceModel.Primitives/ref/System.ServiceModel.Primitives.netstandard.cs @@ -1125,6 +1125,9 @@ protected virtual void OnOpened() { } protected virtual void OnOpening() { } public void Open() { } public void Open(System.TimeSpan timeout) { } + protected internal void ThrowIfDisposed() { } + protected internal void ThrowIfDisposedOrImmutable() { } + protected internal void ThrowIfDisposedOrNotOpen() { } } public enum CompressionFormat { diff --git a/src/System.ServiceModel.Primitives/ref/System.ServiceModel.Security.cs b/src/System.ServiceModel.Primitives/ref/System.ServiceModel.Security.cs index 81ad720ecd0..ad75e76352b 100644 --- a/src/System.ServiceModel.Primitives/ref/System.ServiceModel.Security.cs +++ b/src/System.ServiceModel.Primitives/ref/System.ServiceModel.Security.cs @@ -241,10 +241,12 @@ public class IssuedSecurityTokenParameters : System.ServiceModel.Security.Tokens protected IssuedSecurityTokenParameters(IssuedSecurityTokenParameters other) { } public IssuedSecurityTokenParameters() { } protected override SecurityTokenParameters CloneCore() { return default; } + public Collections.ObjectModel.Collection AdditionalRequestParameters { get { return default; } } public MessageSecurityVersion DefaultMessageSecurityVersion { get { return default; } set { } } public EndpointAddress IssuerAddress { get { return default; } set { } } public Channels.Binding IssuerBinding { get { return default; } set { } } public System.IdentityModel.Tokens.SecurityKeyType KeyType { get { return default; } set { } } + public int KeySize { get { return default; } set { } } public string TokenType { get { return default; } set { } } } public partial class SecureConversationSecurityTokenParameters : System.ServiceModel.Security.Tokens.SecurityTokenParameters diff --git a/src/System.ServiceModel.Primitives/src/Internals/InternalSR.cs b/src/System.ServiceModel.Primitives/src/Internals/InternalSR.cs index 4f8ae62bf07..66d8eb615b1 100644 --- a/src/System.ServiceModel.Primitives/src/Internals/InternalSR.cs +++ b/src/System.ServiceModel.Primitives/src/Internals/InternalSR.cs @@ -9,6 +9,7 @@ namespace System.Runtime { internal class InternalSR { +#pragma warning disable IDE1006 // Naming Styles internal static readonly string ActionItemIsAlreadyScheduled = "The ActionItem was already scheduled for execution that hasn't been completed yet."; internal static readonly string AsyncCallbackThrewException = "Async Callback threw an exception."; internal static readonly string AsyncResultAlreadyEnded = "End cannot be called twice on an AsyncResult."; @@ -20,6 +21,7 @@ internal class InternalSR internal static readonly string ReadNotSupported = "Read not supported on this stream."; internal static readonly string SeekNotSupported = "Seek not supported on this stream."; internal static readonly string ValueMustBeNonNegative = "Value must be non-negative."; +#pragma warning restore IDE1006 // Naming Styles internal static string ArgumentNullOrEmpty(object param0) => $"The argument {param0} is null or empty."; internal static string AsyncResultCompletedTwice(object param0) => $"The IAsyncResult implementation '{param0}' tried to complete a single operation multiple times. This could be caused by an incorrect application IAsyncResult implementation or other extensibility code, such as an IAsyncResult that returns incorrect CompletedSynchronously values or invokes the AsyncCallback multiple times."; diff --git a/src/System.ServiceModel.Primitives/src/netstandard.cs b/src/System.ServiceModel.Primitives/src/netstandard.cs index 4eb6dd3e357..ebe6417ab3e 100644 --- a/src/System.ServiceModel.Primitives/src/netstandard.cs +++ b/src/System.ServiceModel.Primitives/src/netstandard.cs @@ -2468,10 +2468,12 @@ public class IssuedSecurityTokenParameters : System.ServiceModel.Security.Tokens protected IssuedSecurityTokenParameters(IssuedSecurityTokenParameters other) { } public IssuedSecurityTokenParameters() { } protected override SecurityTokenParameters CloneCore() { return default; } + public Collections.ObjectModel.Collection AdditionalRequestParameters { get { return default; } } public MessageSecurityVersion DefaultMessageSecurityVersion { get { return default; } set { } } public EndpointAddress IssuerAddress { get { return default; } set { } } public Channels.Binding IssuerBinding { get { return default; } set { } } public System.IdentityModel.Tokens.SecurityKeyType KeyType { get { return default; } set { } } + public int KeySize { get { return default; } set { } } public string TokenType { get { return default; } set { } } } public partial class SecureConversationSecurityTokenParameters : System.ServiceModel.Security.Tokens.SecurityTokenParameters From f2f9d81347351a440b1aa71c4558dda56f4ae19d Mon Sep 17 00:00:00 2001 From: Matt Connew Date: Wed, 4 Dec 2024 14:35:06 -0800 Subject: [PATCH 2/2] Moved WrapperSecurityCommunicationObject to S.IM.Security namespace to avoid check that WCF implementations implement async methods --- .../Security/WrapperSecurityCommunicationObject.cs | 8 +++++--- .../Federation/WSTrustChannelSecurityTokenProvider.cs | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) rename src/System.ServiceModel.Federation/src/System/{ServiceModel => IdentityModel}/Security/WrapperSecurityCommunicationObject.cs (99%) diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/WrapperSecurityCommunicationObject.cs b/src/System.ServiceModel.Federation/src/System/IdentityModel/Security/WrapperSecurityCommunicationObject.cs similarity index 99% rename from src/System.ServiceModel.Federation/src/System/ServiceModel/Security/WrapperSecurityCommunicationObject.cs rename to src/System.ServiceModel.Federation/src/System/IdentityModel/Security/WrapperSecurityCommunicationObject.cs index 8c0096eac12..c1d7c9b4104 100644 --- a/src/System.ServiceModel.Federation/src/System/ServiceModel/Security/WrapperSecurityCommunicationObject.cs +++ b/src/System.ServiceModel.Federation/src/System/IdentityModel/Security/WrapperSecurityCommunicationObject.cs @@ -3,12 +3,14 @@ // See the LICENSE file in the project root for more information. -using System.ServiceModel.Channels; using System.IdentityModel.Selectors; -using System.Threading.Tasks; using System.Runtime; +using System.ServiceModel; +using System.ServiceModel.Channels; +using System.ServiceModel.Security; +using System.Threading.Tasks; -namespace System.ServiceModel.Security +namespace System.IdentityModel.Security { internal class WrapperSecurityCommunicationObject : CommunicationObject { diff --git a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannelSecurityTokenProvider.cs b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannelSecurityTokenProvider.cs index ffe3e70050f..037cd2fb545 100644 --- a/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannelSecurityTokenProvider.cs +++ b/src/System.ServiceModel.Federation/src/System/ServiceModel/Federation/WSTrustChannelSecurityTokenProvider.cs @@ -22,6 +22,7 @@ using Microsoft.IdentityModel.Protocols.WsPolicy; using Microsoft.IdentityModel.Protocols.WsTrust; using SecurityToken = System.IdentityModel.Tokens.SecurityToken; +using System.IdentityModel.Security; namespace System.ServiceModel.Federation {