Merge pull request #3199 from lambdageek/dev/proxy-setter
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel / NetTcpBinding.cs
1 //
2 // NetTcpBinding.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2005 Novell, Inc.  http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Collections.Generic;
30 using System.Net.Security;
31 using System.ServiceModel.Channels;
32 using System.ServiceModel.Description;
33 using System.ServiceModel.Security;
34 using System.ServiceModel.Security.Tokens;
35 using System.ServiceModel.Configuration;
36 using System.Text;
37 using System.Xml;
38
39 namespace System.ServiceModel
40 {
41         public class NetTcpBinding : Binding, IBindingRuntimePreferences
42         {
43                 int max_conn;
44                 OptionalReliableSession reliable_session;
45                 NetTcpSecurity security;
46                 XmlDictionaryReaderQuotas reader_quotas
47                         = new XmlDictionaryReaderQuotas ();
48                 bool transaction_flow;
49 #if !MOBILE && !XAMMAC_4_5
50                 TransactionProtocol transaction_protocol;
51 #endif
52                 TcpTransportBindingElement transport;
53
54                 public NetTcpBinding ()
55                         : this (SecurityMode.Transport)
56                 {
57                 }
58
59                 public NetTcpBinding (SecurityMode securityMode)
60                         : this (securityMode, false)
61                 {
62                 }
63
64                 public NetTcpBinding (SecurityMode securityMode,
65                         bool reliableSessionEnabled)
66                 {
67                         security = new NetTcpSecurity (securityMode);
68                         transport = new TcpTransportBindingElement ();
69                 }
70
71                 public NetTcpBinding (string configurationName)
72                         : this ()
73                 {
74 #if !MOBILE && !XAMMAC_4_5
75                         var bindingsSection = ConfigUtil.BindingsSection;
76                         var el = bindingsSection.NetTcpBinding.Bindings [configurationName];
77                         el.ApplyConfiguration (this);
78 #else
79                         throw new NotImplementedException ();
80 #endif
81                 }
82
83                 internal NetTcpBinding (TcpTransportBindingElement transport,
84                                         NetTcpSecurity security,
85                                         bool reliableSessionEnabled)
86                 {
87                         this.transport = transport;
88                         this.security = security;
89                 }
90
91                 public HostNameComparisonMode HostNameComparisonMode {
92                         get { return transport.HostNameComparisonMode; }
93                         set { transport.HostNameComparisonMode = value; }
94                 }
95
96                 public int ListenBacklog {
97                         get { return transport.ListenBacklog; }
98                         set { transport.ListenBacklog = value; }
99                 }
100
101                 public long MaxBufferPoolSize {
102                         get { return transport.MaxBufferPoolSize; }
103                         set { transport.MaxBufferPoolSize = value; }
104                 }
105
106                 public int MaxBufferSize {
107                         get { return transport.MaxBufferSize; }
108                         set { transport.MaxBufferSize = value; }
109                 }
110
111                 [MonoTODO]
112                 public int MaxConnections {
113                         get { return max_conn; }
114                         set { max_conn = value; }
115                 }
116
117                 public long MaxReceivedMessageSize {
118                         get { return transport.MaxReceivedMessageSize; }
119                         set { transport.MaxReceivedMessageSize = value; }
120                 }
121
122                 public bool PortSharingEnabled {
123                         get { return transport.PortSharingEnabled; }
124                         set { transport.PortSharingEnabled = value; }
125                 }
126
127                 [MonoTODO]
128                 public OptionalReliableSession ReliableSession {
129                         get { return reliable_session; }
130                 }
131
132                 public XmlDictionaryReaderQuotas ReaderQuotas {
133                         get { return reader_quotas; }
134                         set { reader_quotas = value; }
135                 }
136
137                 public NetTcpSecurity Security {
138                         get { return security; }
139                         set { security = value; }
140                 }
141
142                 public EnvelopeVersion EnvelopeVersion {
143                         get { return EnvelopeVersion.Soap12; }
144                 }
145
146                 public TransferMode TransferMode {
147                         get { return transport.TransferMode; }
148                         set { transport.TransferMode = value; }
149                 }
150
151                 public bool TransactionFlow {
152                         get { return transaction_flow; }
153                         set { transaction_flow = value; }
154                 }
155
156 #if !MOBILE && !XAMMAC_4_5
157                 public TransactionProtocol TransactionProtocol {
158                         get { return transaction_protocol; }
159                         set { transaction_protocol = value; }
160                 }
161 #endif
162
163                 // overrides
164
165                 public override string Scheme {
166                         get { return "net.tcp"; }
167                 }
168
169                 public override BindingElementCollection CreateBindingElements ()
170                 {
171 #if !MOBILE && !XAMMAC_4_5
172                         BindingElement tx = new TransactionFlowBindingElement (TransactionProtocol.WSAtomicTransactionOctober2004);
173                         SecurityBindingElement sec = CreateMessageSecurity ();
174 #endif
175                         var msg = new BinaryMessageEncodingBindingElement ();
176                         if (ReaderQuotas != null)
177                                 ReaderQuotas.CopyTo (msg.ReaderQuotas);
178                         var trsec = CreateTransportSecurity ();
179                         BindingElement tr = GetTransport ();
180                         List<BindingElement> list = new List<BindingElement> ();
181 #if !MOBILE && !XAMMAC_4_5
182                         if (tx != null)
183                                 list.Add (tx);
184                         if (sec != null)
185                                 list.Add (sec);
186 #endif
187                         list.Add (msg);
188                         if (trsec != null)
189                                 list.Add (trsec);
190                         list.Add (tr);
191                         return new BindingElementCollection (list.ToArray ());
192                 }
193
194                 BindingElement GetTransport ()
195                 {
196                         return transport.Clone ();
197                 }
198
199 #if !MOBILE && !XAMMAC_4_5
200                 // It is problematic, but there is no option to disable establishing security context in this binding unlike WSHttpBinding...
201                 SecurityBindingElement CreateMessageSecurity ()
202                 {
203                         if (Security.Mode == SecurityMode.Transport ||
204                             Security.Mode == SecurityMode.None)
205                                 return null;
206
207                         // FIXME: this is wrong. Could be Asymmetric, depends on Security.Message.AlgorithmSuite value.
208                         SymmetricSecurityBindingElement element =
209                                 new SymmetricSecurityBindingElement ();
210
211                         element.MessageSecurityVersion = MessageSecurityVersion.Default;
212
213                         element.SetKeyDerivation (false);
214
215                         switch (Security.Message.ClientCredentialType) {
216                         case MessageCredentialType.Certificate:
217                                 element.EndpointSupportingTokenParameters.Endorsing.Add (
218                                         new X509SecurityTokenParameters ());
219                                 goto default;
220                         case MessageCredentialType.IssuedToken:
221                                 IssuedSecurityTokenParameters istp =
222                                         new IssuedSecurityTokenParameters ();
223                                 // FIXME: issuer binding must be secure.
224                                 istp.IssuerBinding = new CustomBinding (
225                                         new TextMessageEncodingBindingElement (),
226                                         GetTransport ());
227                                 element.EndpointSupportingTokenParameters.Endorsing.Add (istp);
228                                 goto default;
229                         case MessageCredentialType.UserName:
230                                 element.EndpointSupportingTokenParameters.SignedEncrypted.Add (
231                                         new UserNameSecurityTokenParameters ());
232                                 goto default;
233                         case MessageCredentialType.Windows:
234                                 element.ProtectionTokenParameters =
235                                         new KerberosSecurityTokenParameters ();
236                                 break;
237                         default: // including .None
238                                 X509SecurityTokenParameters p =
239                                         new X509SecurityTokenParameters ();
240                                 p.X509ReferenceStyle = X509KeyIdentifierClauseType.Thumbprint;
241                                 element.ProtectionTokenParameters = p;
242                                 break;
243                         }
244
245                         // SecureConversation enabled
246
247                         ChannelProtectionRequirements reqs =
248                                 new ChannelProtectionRequirements ();
249                         // FIXME: fill the reqs
250
251                         return SecurityBindingElement.CreateSecureConversationBindingElement (
252                                 // FIXME: requireCancellation
253                                 element, true, reqs);
254                 }
255 #endif
256
257                 BindingElement CreateTransportSecurity ()
258                 {
259                         switch (Security.Mode) {
260                         case SecurityMode.Transport:
261                                 return new WindowsStreamSecurityBindingElement () {
262                                         ProtectionLevel = Security.Transport.ProtectionLevel };
263
264                         case SecurityMode.TransportWithMessageCredential:
265                                 return new SslStreamSecurityBindingElement ();
266
267                         default:
268                                 return null;
269                         }
270
271                         // FIXME: consider Security.Transport.ExtendedProtectionPolicy.
272
273                         switch (Security.Transport.ClientCredentialType) {
274                         case TcpClientCredentialType.Windows:
275                                 return new WindowsStreamSecurityBindingElement () { ProtectionLevel = Security.Transport.ProtectionLevel };
276                         case TcpClientCredentialType.Certificate:
277                                 // FIXME: set RequireClientCertificate and IdentityVerifier depending on other properties, if applicable.
278                                 return new SslStreamSecurityBindingElement ();
279                         default: // includes None
280                                 return null;
281                         }
282                 }
283
284                 bool IBindingRuntimePreferences.ReceiveSynchronously {
285                         get { throw new NotImplementedException (); }
286                 }
287         }
288 }