2 // SpnegoSecurityTokenProvider.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2007 Novell, Inc. http://www.novell.com
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
29 using System
.Security
.Principal
;
30 using System
.IdentityModel
.Selectors
;
31 using System
.IdentityModel
.Tokens
;
32 using System
.ServiceModel
.Channels
;
33 using System
.ServiceModel
.Description
;
34 using System
.ServiceModel
.Security
.Tokens
;
38 // mhm, why is this class not in S.SM.S.Tokens??
39 namespace System
.ServiceModel
.Security
41 // Anyways we won't support SSPI until it becomes open.
42 internal class SpnegoSecurityTokenProvider
: CommunicationSecurityTokenProvider
44 ClientCredentialsSecurityTokenManager manager
;
45 SecurityTokenRequirement requirement
;
46 SpnegoCommunicationObject comm
;
48 public SpnegoSecurityTokenProvider (ClientCredentialsSecurityTokenManager manager
, SecurityTokenRequirement requirement
)
50 this.manager
= manager
;
51 comm
= new SpnegoCommunicationObject (this);
54 public ClientCredentialsSecurityTokenManager Manager
{
55 get { return manager; }
58 public override ProviderCommunicationObject Communication
{
62 public override SecurityToken
GetOnlineToken (TimeSpan timeout
)
64 return comm
.GetToken (timeout
);
68 class SpnegoCommunicationObject
: ProviderCommunicationObject
70 SpnegoSecurityTokenProvider owner
;
72 public SpnegoCommunicationObject (SpnegoSecurityTokenProvider owner
)
77 WSTrustSecurityTokenServiceProxy proxy
;
79 protected internal override TimeSpan DefaultCloseTimeout
{
80 get { throw new NotImplementedException (); }
83 protected internal override TimeSpan DefaultOpenTimeout
{
84 get { throw new NotImplementedException (); }
87 protected override void OnAbort ()
89 throw new NotImplementedException ();
92 protected override void OnOpen (TimeSpan timeout
)
94 if (State
== CommunicationState
.Opened
)
95 throw new InvalidOperationException ("Already opened.");
99 proxy
= new WSTrustSecurityTokenServiceProxy (
100 IssuerBinding
, IssuerAddress
);
103 protected override IAsyncResult
OnBeginOpen (TimeSpan timeout
, AsyncCallback callback
, object state
)
105 throw new NotImplementedException ();
108 protected override void OnEndOpen (IAsyncResult result
)
110 throw new NotImplementedException ();
113 protected override void OnClose (TimeSpan timeout
)
119 protected override IAsyncResult
OnBeginClose (TimeSpan timeout
, AsyncCallback callback
, object state
)
121 throw new NotImplementedException ();
124 protected override void OnEndClose (IAsyncResult result
)
126 throw new NotImplementedException ();
129 public SecurityToken
GetToken (TimeSpan timeout
)
131 bool gss
= (TargetAddress
.Identity
== null);
132 SspiClientSession sspi
= new SspiClientSession ();
134 WstRequestSecurityToken rst
=
135 new WstRequestSecurityToken ();
138 rst
.BinaryExchange
= new WstBinaryExchange (Constants
.WstBinaryExchangeValueGss
);
139 // When the TargetAddress does not contain the endpoint
140 // identity, then .net seems to use Kerberos instead of
143 rst
.BinaryExchange
.Value
= sspi
.ProcessSpnegoInitialContextTokenRequest ();
145 rst
.BinaryExchange
.Value
= sspi
.ProcessMessageType1 ();
147 Message request
= Message
.CreateMessage (IssuerBinding
.MessageVersion
, Constants
.WstIssueAction
, rst
);
148 request
.Headers
.MessageId
= new UniqueId ();
149 request
.Headers
.ReplyTo
= new EndpointAddress (Constants
.WsaAnonymousUri
);
150 request
.Headers
.To
= TargetAddress
.Uri
;
151 MessageBuffer buffer
= request
.CreateBufferedCopy (0x10000);
152 // tlsctx.StoreMessage (buffer.CreateMessage ().GetReaderAtBodyContents ());
154 // receive MessageType2
155 Message response
= proxy
.Issue (buffer
.CreateMessage ());
156 buffer
= response
.CreateBufferedCopy (0x10000);
157 // tlsctx.StoreMessage (buffer.CreateMessage ().GetReaderAtBodyContents ());
159 WSTrustRequestSecurityTokenResponseReader reader
=
160 new WSTrustRequestSecurityTokenResponseReader (Constants
.WstSpnegoProofTokenType
, buffer
.CreateMessage ().GetReaderAtBodyContents (), SecurityTokenSerializer
, null);
163 byte [] raw
= reader
.Value
.BinaryExchange
.Value
;
165 sspi
.ProcessSpnegoInitialContextTokenResponse (raw
);
167 sspi
.ProcessMessageType2 (raw
);
170 WstRequestSecurityTokenResponse rstr
=
171 new WstRequestSecurityTokenResponse (SecurityTokenSerializer
);
172 rstr
.Context
= reader
.Value
.Context
;
173 rstr
.BinaryExchange
= new WstBinaryExchange (Constants
.WstBinaryExchangeValueGss
);
175 NetworkCredential cred
= owner
.Manager
.ClientCredentials
.Windows
.ClientCredential
;
176 string user
= string.IsNullOrEmpty (cred
.UserName
) ? Environment
.UserName
: cred
.UserName
;
177 string pass
= cred
.Password
?? String
.Empty
;
179 rstr
.BinaryExchange
.Value
= sspi
.ProcessSpnegoProcessContextToken (user
, pass
);
181 rstr
.BinaryExchange
.Value
= sspi
.ProcessMessageType3 (user
, pass
);
183 request
= Message
.CreateMessage (IssuerBinding
.MessageVersion
, Constants
.WstIssueReplyAction
, rstr
);
184 request
.Headers
.MessageId
= new UniqueId ();
185 request
.Headers
.ReplyTo
= new EndpointAddress (Constants
.WsaAnonymousUri
);
186 request
.Headers
.To
= TargetAddress
.Uri
;
188 buffer
= request
.CreateBufferedCopy (0x10000);
189 // tlsctx.StoreMessage (buffer.CreateMessage ().GetReaderAtBodyContents ());
191 proxy
= new WSTrustSecurityTokenServiceProxy (
192 IssuerBinding
, IssuerAddress
);
193 response
= proxy
.IssueReply (buffer
.CreateMessage ());
194 // FIXME: use correct limitation
195 buffer
= response
.CreateBufferedCopy (0x10000);
196 // don't store this message for ckhash (it's not part
198 Console
.WriteLine (buffer
.CreateMessage ());
200 throw new NotImplementedException ();