1 //
2 // SecurityRequestChannel.cs
3 //
4 // Author:
5 //	Atsushi Enomoto  <atsushi@ximian.com>
6 //
7 // Copyright (C) 2006 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 
29 using System;
30 using System.Collections.Generic;
31 using System.Collections.ObjectModel;
32 using System.IdentityModel.Selectors;
33 using System.IdentityModel.Tokens;
34 using System.Runtime.Serialization;
35 using System.Security.Cryptography;
36 using System.Security.Cryptography.X509Certificates;
37 using System.Security.Cryptography.Xml;
38 using System.ServiceModel;
39 using System.ServiceModel.Channels;
40 using System.ServiceModel.Description;
41 using System.ServiceModel.Security;
42 using System.ServiceModel.Security.Tokens;
43 using System.Xml;
44 using System.Xml.XPath;
45 
46 using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
47 
48 namespace System.ServiceModel.Channels.Security
49 {
50 	class SecurityDuplexSession : DuplexSessionBase
51 	{
52 		SecurityDuplexSessionChannel channel;
53 
SecurityDuplexSession(SecurityDuplexSessionChannel channel)54 		public SecurityDuplexSession (SecurityDuplexSessionChannel channel)
55 		{
56 			this.channel = channel;
57 		}
58 
59 		public override TimeSpan DefaultCloseTimeout {
60 			get { return channel.DefaultCloseTimeout; }
61 		}
62 
Close(TimeSpan timeout)63 		public override void Close (TimeSpan timeout)
64 		{
65 			// valid only if the inner channel is ISessionChannel
66 			var d = channel.Channel as IDuplexSessionChannel;
67 			if (d != null)
68 				d.Session.CloseOutputSession (timeout);
69 		}
70 	}
71 
72 	class SecurityDuplexSessionChannel : DuplexChannelBase, IDuplexSessionChannel
73 	{
74 		IChannel channel;
75 		InitiatorMessageSecurityBindingSupport security_initiator;
76 		RecipientMessageSecurityBindingSupport security_recipient;
77 		SecurityDuplexSession session;
78 
SecurityDuplexSessionChannel(ChannelFactoryBase factory, IChannel innerChannel, EndpointAddress remoteAddress, Uri via, InitiatorMessageSecurityBindingSupport security)79 		public SecurityDuplexSessionChannel (ChannelFactoryBase factory, IChannel innerChannel, EndpointAddress remoteAddress, Uri via, InitiatorMessageSecurityBindingSupport security)
80 			: base (factory, remoteAddress, via)
81 		{
82 			this.channel = innerChannel;
83 			session = new SecurityDuplexSession (this);
84 			InitializeSecurityFunctionality (security);
85 		}
86 
SecurityDuplexSessionChannel(ChannelListenerBase listener, IChannel innerChannel, RecipientMessageSecurityBindingSupport security)87 		public SecurityDuplexSessionChannel (ChannelListenerBase listener, IChannel innerChannel, RecipientMessageSecurityBindingSupport security)
88 			: base (listener)
89 		{
90 			this.channel = innerChannel;
91 			session = new SecurityDuplexSession (this);
92 			InitializeSecurityFunctionality (security);
93 		}
94 
95 		public IChannel Channel {
96 			get { return channel; }
97 		}
98 
99 		public IDuplexSession Session {
100 			get { return session; }
101 		}
102 
InitializeSecurityFunctionality(InitiatorMessageSecurityBindingSupport security)103 		void InitializeSecurityFunctionality (InitiatorMessageSecurityBindingSupport security)
104 		{
105 			security_initiator = security;
106 		}
107 
InitializeSecurityFunctionality(RecipientMessageSecurityBindingSupport security)108 		void InitializeSecurityFunctionality (RecipientMessageSecurityBindingSupport security)
109 		{
110 			security_recipient = security;
111 		}
112 
OnOpen(TimeSpan timeout)113 		protected override void OnOpen (TimeSpan timeout)
114 		{
115 			channel.Open (timeout);
116 			if (security_initiator != null)
117 				security_initiator.Prepare ((ChannelFactoryBase) Manager, RemoteAddress);
118 			else
119 				security_recipient.Prepare ((ChannelListenerBase) Manager, LocalAddress.Uri);
120 		}
121 
OnClose(TimeSpan timeout)122 		protected override void OnClose (TimeSpan timeout)
123 		{
124 			if (security_initiator != null)
125 				security_initiator.Release ();
126 			else
127 				security_recipient.Release ();
128 			channel.Close (timeout);
129 		}
130 
OnAbort()131 		protected override void OnAbort ()
132 		{
133 			if (security_initiator != null)
134 				security_initiator.Release ();
135 			else
136 				security_recipient.Release ();
137 			channel.Abort ();
138 		}
139 
TryReceive(TimeSpan timeout, out Message message)140 		public override bool TryReceive (TimeSpan timeout, out Message message)
141 		{
142 			ThrowIfDisposedOrNotOpen ();
143 			var input = (IInputChannel) channel;
144 			if (!input.TryReceive (timeout, out message))
145 				return false;
146 			message = DecryptMessage (message);
147 			return true;
148 		}
149 
WaitForMessage(TimeSpan timeout)150 		public override bool WaitForMessage (TimeSpan timeout)
151 		{
152 			var input = (IInputChannel) channel;
153 			return input.WaitForMessage (timeout);
154 		}
155 
Send(Message message)156 		public override void Send (Message message)
157 		{
158 			Send (message, DefaultSendTimeout);
159 		}
160 
Send(Message message, TimeSpan timeout)161 		public override void Send (Message message, TimeSpan timeout)
162 		{
163 			Message secure = SecureMessage (message);
164 			var output = (IOutputChannel) channel;
165 			output.Send (secure, timeout);
166 		}
167 
SecureMessage(Message msg)168 		Message SecureMessage (Message msg)
169 		{
170 			if (security_initiator != null)
171 				return new InitiatorMessageSecurityGenerator (msg, security_initiator, RemoteAddress).SecureMessage ();
172 			else
173 				return new RecipientMessageSecurityGenerator (msg, null, security_recipient).SecureMessage (); // FIXME: supply SecurityMessageProperty (if any)
174 		}
175 
DecryptMessage(Message msg)176 		Message DecryptMessage (Message msg)
177 		{
178 			if (security_initiator != null)
179 				return new InitiatorSecureMessageDecryptor (msg, null, security_initiator).DecryptMessage (); // FIXME: supply SecurityMessageProperty (if any)
180 			else
181 				return new RecipientSecureMessageDecryptor (msg, security_recipient).DecryptMessage ();
182 		}
183 	}
184 }
185 
186