//
// Author:
// Vladimir Krasnov <vladimirk@mainsoft.com>
+// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2005-2006 Mainsoft, Inc. http://www.mainsoft.com
+// Copyright (C) 2009-2010 Novell, Inc. http://www.novell.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
+using System.IdentityModel.Selectors;
+using System.IdentityModel.Tokens;
using System.ServiceModel.Description;
+using System.ServiceModel.Security;
+using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Net;
public abstract Uri RequestUrl { get; }
public abstract string HttpMethod { get; }
public abstract void Abort ();
+
+ public abstract string User { get; }
+ public abstract string Password { get; }
+ public abstract void ReturnUnauthorized ();
}
class HttpListenerContextInfo : HttpContextInfo
{
ctx.Response.Abort ();
}
+
+ public override string User {
+ get { return ctx.User != null ? ((HttpListenerBasicIdentity) ctx.User.Identity).Name : null; }
+ }
+
+ public override string Password {
+ get { return ctx.User != null ? ((HttpListenerBasicIdentity) ctx.User.Identity).Password : null; }
+ }
+
+ public override void ReturnUnauthorized ()
+ {
+ ctx.Response.StatusCode = 401;
+ }
}
class AspNetHttpContextInfo : HttpContextInfo
{
ctx.Response.Close ();
}
+
+ public override string User {
+ get { return ctx.User != null ? ((GenericIdentity) ctx.User.Identity).Name : null; }
+ }
+
+ // FIXME: how to acquire this?
+ public override string Password {
+ get { return null; }
+ }
+
+ public override void ReturnUnauthorized ()
+ {
+ ctx.Response.StatusCode = 401;
+ }
}
internal class HttpSimpleListenerManager : HttpListenerManager
opened_listeners = new Dictionary<Uri, HttpListener> ();
}
- public HttpSimpleListenerManager (IChannelListener channelListener)
- : base (channelListener)
+ public HttpSimpleListenerManager (IChannelListener channelListener, HttpTransportBindingElement source, ServiceCredentialsSecurityTokenManager securityTokenManager)
+ : base (channelListener, source, securityTokenManager)
{
}
lock (opened_listeners) {
if (!opened_listeners.ContainsKey (channelListener.Uri)) {
HttpListener listener = new HttpListener ();
+ listener.AuthenticationSchemeSelectorDelegate = delegate (HttpListenerRequest req) {
+ return Source.AuthenticationScheme;
+ };
+ listener.Realm = Source.Realm;
+ listener.UnsafeConnectionNtlmAuthentication = Source.UnsafeConnectionNtlmAuthentication;
string uriString = channelListener.Uri.ToString ();
if (!uriString.EndsWith ("/", StringComparison.Ordinal))
http_listener = null;
}
- public override void KickContextReceiver (IChannelListener listener, Action<HttpContextInfo> contextReceivedCallback)
+ protected override void KickContextReceiver (IChannelListener listener, Action<HttpContextInfo> contextReceivedCallback)
{
http_listener.BeginGetContext (delegate (IAsyncResult result) {
var hctx = http_listener.EndGetContext (result);
{
SvcHttpHandler http_handler;
- public AspNetListenerManager (IChannelListener channelListener)
- : base (channelListener)
+ public AspNetListenerManager (IChannelListener channelListener, HttpTransportBindingElement source, ServiceCredentialsSecurityTokenManager securityTokenManager)
+ : base (channelListener, source, securityTokenManager)
{
- http_handler = SvcHttpHandlerFactory.GetHandlerForListener (channelListener);
+ http_handler = SvcHttpHandler.Current;
}
- public SvcHttpHandler Source {
- get { return http_handler; }
- }
+ internal SvcHttpHandler HttpHandler { get { return http_handler; } }
protected override void OnRegister (IChannelListener channelListener, TimeSpan timeout)
{
Func<IChannelListener,HttpContext> wait_delegate;
- public override void KickContextReceiver (IChannelListener listener, Action<HttpContextInfo> contextReceivedCallback)
+ protected override void KickContextReceiver (IChannelListener listener, Action<HttpContextInfo> contextReceivedCallback)
{
if (wait_delegate == null)
wait_delegate = new Func<IChannelListener,HttpContext> (http_handler.WaitForRequest);
AutoResetEvent wait_http_ctx = new AutoResetEvent (false);
List<HttpContextInfo> pending = new List<HttpContextInfo> ();
-public MetadataPublishingInfo MexInfo { get { return mex_info; } }
+ public MetadataPublishingInfo MexInfo { get { return mex_info; } }
+ public HttpTransportBindingElement Source { get; private set; }
+
+ SecurityTokenAuthenticator security_token_authenticator;
+ SecurityTokenResolver security_token_resolver;
static HttpListenerManager ()
{
registered_channels = new Dictionary<Uri, List<IChannelListener>> ();
}
- protected HttpListenerManager (IChannelListener channelListener)
+ protected HttpListenerManager (IChannelListener channelListener, HttpTransportBindingElement source, ServiceCredentialsSecurityTokenManager securityTokenManager)
{
this.channel_listener = channelListener;
// FIXME: this cast should not be required, but current JIT somehow causes an internal error.
mex_info = ((IChannelListener) channelListener).GetProperty<MetadataPublishingInfo> ();
wsdl_instance = mex_info != null ? mex_info.Instance : null;
+ Source = source;
+
+ if (securityTokenManager != null) {
+ var str = new SecurityTokenRequirement () { TokenType = SecurityTokenTypes.UserName };
+ security_token_authenticator = securityTokenManager.CreateSecurityTokenAuthenticator (str, out security_token_resolver);
+ }
}
public void Open (TimeSpan timeout)
protected abstract void OnRegister (IChannelListener listener, TimeSpan timeout);
protected abstract void OnUnregister (IChannelListener listener, bool abort);
+ public void CancelGetHttpContextAsync ()
+ {
+ wait_http_ctx.Set ();
+ }
+
// Do not directly handle retrieved HttpListenerContexts when
// the listener received ones.
// Instead, iterate every listeners to find the most-likely-
}
}
- public abstract void KickContextReceiver (IChannelListener listener, Action<HttpContextInfo> contextReceiverCallback);
+ protected abstract void KickContextReceiver (IChannelListener listener, Action<HttpContextInfo> contextReceiverCallback);
void DispatchHttpListenerContext (HttpContextInfo ctx)
{
if (wsdl_instance == null) {
- pending.Add (ctx);
- wait_http_ctx.Set ();
+ AddListenerContext (ctx);
return;
}
foreach (var l in registered_channels [channel_listener.Uri]) {
var lm = l.GetProperty<HttpListenerManager> ();
if (lm.FilterHttpContext (ctx)) {
- lm.pending.Add (ctx);
- lm.wait_http_ctx.Set ();
+ lm.AddListenerContext (ctx);
return;
}
}
- pending.Add (ctx);
- wait_http_ctx.Set ();
+ AddListenerContext (ctx);
+ }
+
+ void AddListenerContext (HttpContextInfo ctx)
+ {
+ if (Source.AuthenticationScheme != AuthenticationSchemes.Anonymous) {
+ if (security_token_authenticator != null)
+ // FIXME: use return value?
+ try {
+ security_token_authenticator.ValidateToken (new UserNameSecurityToken (ctx.User, ctx.Password));
+ } catch (Exception) {
+ ctx.ReturnUnauthorized ();
+ }
+ else {
+ ctx.ReturnUnauthorized ();
+ }
+ }
+
+ lock (registered_channels) {
+ pending.Add (ctx);
+ // FIXME: this should not be required, but it somehow saves some failures wrt concurrent calls.
+ Thread.Sleep (100);
+ wait_http_ctx.Set ();
+ }
}
const UriComponents cmpflag = UriComponents.HttpRequestUrl ^ UriComponents.Query;