Splitted the SecureMessage method for a better readability.
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels.Security / SecurityReplyChannel.cs
1 //
2 // SecurityReplyChannel.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2006,2010 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.Collections.Generic;
29 using System.Collections.ObjectModel;
30 using System.Net.Security;
31 using System.IdentityModel.Selectors;
32 using System.IdentityModel.Tokens;
33 using System.Security.Cryptography.X509Certificates;
34 using System.ServiceModel;
35 using System.ServiceModel.Channels;
36 using System.ServiceModel.Description;
37 using System.ServiceModel.Security;
38 using System.ServiceModel.Security.Tokens;
39
40 namespace System.ServiceModel.Channels.Security
41 {
42         internal class SecurityReplyChannel : InternalReplyChannelBase
43         {
44                 IReplyChannel inner;
45
46                 public SecurityReplyChannel (
47                         SecurityChannelListener<IReplyChannel> source,
48                         IReplyChannel innerChannel)
49                         : base (source)
50                 {
51                         this.inner = innerChannel;
52                 }
53
54                 public SecurityChannelListener<IReplyChannel> Source {
55                         get { return (SecurityChannelListener<IReplyChannel>) Listener; }
56                 }
57
58                 // IReplyChannel
59
60                 protected override void OnOpen (TimeSpan timeout)
61                 {
62                         inner.Open (timeout);
63                 }
64
65                 protected override void OnClose (TimeSpan timeout)
66                 {
67                         inner.Close (timeout);
68                 }
69
70                 public override RequestContext ReceiveRequest (TimeSpan timeout)
71                 {
72                         RequestContext ctx;
73                         if (TryReceiveRequest (timeout, out ctx))
74                                 return ctx;
75                         throw new TimeoutException ("Failed to receive request context");
76                 }
77
78                 public override bool TryReceiveRequest (TimeSpan timeout, out RequestContext context)
79                 {
80                         DateTime start = DateTime.Now;
81
82                         if (!inner.TryReceiveRequest (timeout, out context))
83                                 return false;
84                         if (context == null)
85                                 return true;
86
87                         Message req, res;
88                         req = context.RequestMessage;
89                         switch (req.Headers.Action) {
90                         case Constants.WstIssueAction:
91                         case Constants.WstIssueReplyAction:
92                         case Constants.WstRenewAction:
93                         case Constants.WstCancelAction:
94                         case Constants.WstValidateAction:
95                                 var support = Source.SecuritySupport;
96                                 var commAuth = support.TokenAuthenticator as CommunicationSecurityTokenAuthenticator;
97                                 if (commAuth != null)
98                                         res = commAuth.Communication.ProcessNegotiation (req, timeout - (DateTime.Now - start));
99                                 else
100                                         throw new MessageSecurityException ("This reply channel does not expect incoming WS-Trust requests");
101
102                                 context.Reply (res, timeout - (DateTime.Now - start));
103                                 context.Close (timeout - (DateTime.Now - start));
104                                 // wait for another incoming message
105                                 return TryReceiveRequest (timeout - (DateTime.Now - start), out context);
106
107                                 break;
108                         }
109
110                         context = new SecurityRequestContext (this, context);
111                         return true;
112                 }
113
114                 [MonoTODO]
115                 public override bool WaitForRequest (TimeSpan timeout)
116                 {
117                         throw new NotImplementedException ();
118                 }
119
120                 // IChannel
121
122                 public override T GetProperty<T> ()
123                 {
124                         // FIXME: implement
125                         return inner.GetProperty<T> ();
126                 }
127         }
128 }