1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 namespace System.ServiceModel.Dispatcher
5 {
6     using System.ServiceModel.Channels;
7     using System.ServiceModel;
8     using System.ServiceModel.Description;
9     using System.Collections.ObjectModel;
10     using System.Collections.Generic;
11     using System.Xml;
12     using System.Security;
13     using System.Security.Permissions;
14     using System.ServiceModel.MsmqIntegration;
15     using System.Runtime;
16 
17     class PartialTrustValidationBehavior : IServiceBehavior, IEndpointBehavior
18     {
19         static PartialTrustValidationBehavior instance = null;
20 
21         internal static PartialTrustValidationBehavior Instance
22         {
23             get
24             {
25                 // no need to synchronize -- it's ok if two are created
26                 if (instance == null)
27                 {
28                     instance = new PartialTrustValidationBehavior();
29                 }
30                 return instance;
31             }
32         }
33 
ValidateEndpoint(ServiceEndpoint endpoint)34         void ValidateEndpoint(ServiceEndpoint endpoint)
35         {
36             Binding binding = endpoint.Binding;
37             if (binding != null)
38             {
39                 new BindingValidator(endpoint.Binding).Validate();
40             }
41         }
42 
43         #region IEndpointBehavior Members
44 
IEndpointBehavior.Validate(ServiceEndpoint endpoint)45         void IEndpointBehavior.Validate(ServiceEndpoint endpoint)
46         {
47             if (endpoint == null)
48                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoint");
49 
50             ValidateEndpoint(endpoint);
51         }
52 
IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)53         void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)54         void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)55         void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { }
56 
57         #endregion
58 
59         #region IServiceBehavior Members
60 
Validate(ServiceDescription description, ServiceHostBase serviceHostBase)61         public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
62         {
63             if (description == null)
64                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("description");
65             for (int i = 0; i < description.Endpoints.Count; i++)
66             {
67                 ServiceEndpoint endpoint = description.Endpoints[i];
68                 if (endpoint != null)
69                 {
70                     ValidateEndpoint(endpoint);
71                 }
72             }
73         }
74 
AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)75         public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)76         public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
77 
78         #endregion
79 
80         struct BindingValidator
81         {
82             static Type[] unsupportedBindings = new Type[]
83             {
84                 typeof(NetNamedPipeBinding),
85                 typeof(WSDualHttpBinding),
86                 typeof(WS2007FederationHttpBinding),
87                 typeof(WSFederationHttpBinding),
88                 typeof(NetMsmqBinding),
89 #pragma warning disable 0618
90                 typeof(NetPeerTcpBinding),
91 #pragma warning restore 0618
92                 typeof(MsmqIntegrationBinding),
93             };
94 
95             static Type[] unsupportedBindingElements = new Type[]
96             {
97                 typeof(AsymmetricSecurityBindingElement),
98                 typeof(CompositeDuplexBindingElement),
99                 typeof(MsmqTransportBindingElement),
100                 typeof(NamedPipeTransportBindingElement),
101                 typeof(OneWayBindingElement),
102 #pragma warning disable 0618
103                 typeof(PeerCustomResolverBindingElement),
104                 typeof(PeerTransportBindingElement),
105                 typeof(PnrpPeerResolverBindingElement),
106 #pragma warning restore 0618
107                 typeof(ReliableSessionBindingElement),
108                 typeof(SymmetricSecurityBindingElement),
109                 typeof(TransportSecurityBindingElement),
110                 typeof(MtomMessageEncodingBindingElement),
111             };
112 
113             Binding binding;
BindingValidatorSystem.ServiceModel.Dispatcher.PartialTrustValidationBehavior.BindingValidator114             internal BindingValidator(Binding binding)
115             {
116                 this.binding = binding;
117             }
118 
ValidateSystem.ServiceModel.Dispatcher.PartialTrustValidationBehavior.BindingValidator119             internal void Validate()
120             {
121                 Fx.Assert(binding != null, "BindingValidator was not constructed with a valid Binding instance");
122 
123                 Type bindingType = binding.GetType();
124                 if (IsUnsupportedBindingType(bindingType))
125                 {
126                     UnsupportedSecurityCheck(SR.FullTrustOnlyBindingSecurityCheck1, bindingType);
127                 }
128 
129                 // special-case error message for WSHttpBindings
130                 bool isWSHttpBinding = typeof(WSHttpBinding).IsAssignableFrom(bindingType);
131                 string sr = isWSHttpBinding ? SR.FullTrustOnlyBindingElementSecurityCheckWSHttpBinding1 : SR.FullTrustOnlyBindingElementSecurityCheck1;
132 
133                 BindingElementCollection elements = binding.CreateBindingElements();
134                 foreach (BindingElement element in elements)
135                 {
136                     Type bindingElementType = element.GetType();
137                     if (element != null && IsUnsupportedBindingElementType(bindingElementType))
138                     {
139                         UnsupportedSecurityCheck(sr, bindingElementType);
140                     }
141                 }
142             }
143 
IsUnsupportedBindingTypeSystem.ServiceModel.Dispatcher.PartialTrustValidationBehavior.BindingValidator144             bool IsUnsupportedBindingType(Type bindingType)
145             {
146                 for (int i = 0; i < unsupportedBindings.Length; i++)
147                 {
148                     if (unsupportedBindings[i] == bindingType)
149                         return true;
150                 }
151                 return false;
152             }
153 
IsUnsupportedBindingElementTypeSystem.ServiceModel.Dispatcher.PartialTrustValidationBehavior.BindingValidator154             bool IsUnsupportedBindingElementType(Type bindingElementType)
155             {
156                 for (int i = 0; i < unsupportedBindingElements.Length; i++)
157                 {
158                     if (unsupportedBindingElements[i] == bindingElementType)
159                         return true;
160                 }
161                 return false;
162             }
163 
164             static readonly PermissionSet fullTrust = new PermissionSet(PermissionState.Unrestricted);
UnsupportedSecurityCheckSystem.ServiceModel.Dispatcher.PartialTrustValidationBehavior.BindingValidator165             void UnsupportedSecurityCheck(string resource, Type type)
166             {
167                 try
168                 {
169                     fullTrust.Demand();
170                 }
171                 catch (SecurityException)
172                 {
173                     throw new InvalidOperationException(SR.GetString(resource, binding.Name, type));
174                 }
175             }
176 
177         }
178     }
179 
180 }
181