// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_2_0
+
+#if NET_2_0 && SECURITY_DEP
+
using System.IO;
using System.Net.Sockets;
-using System.Collections.Generic;
+using System.Collections;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using Mono.Security.Authenticode;
+
namespace System.Net {
sealed class EndPointListener
{
IPEndPoint endpoint;
Socket sock;
- Dictionary<ListenerPrefix, HttpListener> prefixes;
- List<ListenerPrefix> unhandled; // host = '*'
- List<ListenerPrefix> all; // host = '+'
- bool secure; // Can a port have listeners for secure and not secure at the same time? No!
+ Hashtable prefixes; // Dictionary <ListenerPrefix, HttpListener>
+ ArrayList unhandled; // List<ListenerPrefix> unhandled; host = '*'
+ ArrayList all; // List<ListenerPrefix> all; host = '+'
+ X509Certificate2 cert;
+ AsymmetricAlgorithm key;
+ bool secure;
public EndPointListener (IPAddress addr, int port, bool secure)
{
+ if (secure) {
+ this.secure = secure;
+ LoadCertificateAndKey (addr, port);
+ }
+
endpoint = new IPEndPoint (addr, port);
sock = new Socket (addr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
sock.Bind (endpoint);
sock.Listen (500);
sock.BeginAccept (OnAccept, this);
- prefixes = new Dictionary<ListenerPrefix, HttpListener> ();
- this.secure = secure;
+ prefixes = new Hashtable ();
+ }
+
+ void LoadCertificateAndKey (IPAddress addr, int port)
+ {
+ // Actually load the certificate
+ try {
+ string dirname = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
+ string path = Path.Combine (dirname, ".mono");
+ path = Path.Combine (path, "httplistener");
+ string cert_file = Path.Combine (path, String.Format ("{0}.cer", port));
+ string pvk_file = Path.Combine (path, String.Format ("{0}.pvk", port));
+ cert = new X509Certificate2 (cert_file);
+ key = PrivateKey.CreateFromFile (pvk_file).RSA;
+ } catch {
+ // ignore errors
+ }
}
static void OnAccept (IAsyncResult ares)
if (accepted == null)
return;
- HttpConnection conn = new HttpConnection (accepted, epl, epl.secure);
+
+ if (epl.secure && (epl.cert == null || epl.key == null)) {
+ accepted.Close ();
+ return;
+ }
+ HttpConnection conn = new HttpConnection (accepted, epl, epl.secure, epl.cert, epl.key);
conn.BeginReadRequest ();
}
host = host.Substring (0, colon);
}
- string path = HttpUtility.UrlDecode (raw_url);
+ string path;
+ Uri raw_uri;
+ if (Uri.MaybeUri (raw_url) && Uri.TryCreate (raw_url, UriKind.Absolute, out raw_uri))
+ path = raw_uri.PathAndQuery;
+ else
+ path = HttpUtility.UrlDecode (raw_url);
+
+ string path_slash = path [path.Length - 1] == '/' ? path : path + "/";
+
HttpListener best_match = null;
int best_length = -1;
if (ppath.Length < best_length)
continue;
- if (p.Host == host && path.StartsWith (ppath)) {
+ if (p.Host == host && (path.StartsWith (ppath) || path_slash.StartsWith (ppath))) {
best_length = ppath.Length;
- best_match = prefixes [p];
+ best_match = (HttpListener) prefixes [p];
prefix = p;
}
}
return null;
}
- HttpListener MatchFromList (string host, string path, List<ListenerPrefix> list, out ListenerPrefix prefix)
+ HttpListener MatchFromList (string host, string path, ArrayList list, out ListenerPrefix prefix)
{
prefix = null;
if (list == null)
return best_match;
}
- void AddSpecial (List<ListenerPrefix> coll, ListenerPrefix prefix)
+ void AddSpecial (ArrayList coll, ListenerPrefix prefix)
{
if (coll == null)
return;
coll.Add (prefix);
}
- void RemoveSpecial (List<ListenerPrefix> coll, ListenerPrefix prefix)
+ void RemoveSpecial (ArrayList coll, ListenerPrefix prefix)
{
if (coll == null)
return;
int c = coll.Count;
for (int i = 0; i < c; i++) {
- ListenerPrefix p = coll [i];
+ ListenerPrefix p = (ListenerPrefix) coll [i];
if (p.Path == prefix.Path) {
coll.RemoveAt (i);
CheckIfRemove ();
lock (prefixes) {
if (prefix.Host == "*") {
if (unhandled == null)
- unhandled = new List<ListenerPrefix> ();
+ unhandled = new ArrayList ();
prefix.Listener = listener;
AddSpecial (unhandled, prefix);
if (prefix.Host == "+") {
if (all == null)
- all = new List<ListenerPrefix> ();
+ all = new ArrayList ();
prefix.Listener = listener;
AddSpecial (all, prefix);
return;
}
if (prefixes.ContainsKey (prefix)) {
- HttpListener other = prefixes [prefix];
+ HttpListener other = (HttpListener) prefixes [prefix];
if (other != listener) // TODO: code.
throw new HttpListenerException (400, "There's another listener for " + prefix);
return;