123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- using System;
- using System.Net;
- using System.Security.Principal;
- using MediaBrowser.Model.Cryptography;
- using MediaBrowser.Model.IO;
- using MediaBrowser.Model.Logging;
- using MediaBrowser.Model.Text;
- using SocketHttpListener.Net.WebSockets;
- using SocketHttpListener.Primitives;
- namespace SocketHttpListener.Net
- {
- public sealed class HttpListenerContext
- {
- HttpListenerRequest request;
- HttpListenerResponse response;
- IPrincipal user;
- HttpConnection cnc;
- string error;
- int err_status = 400;
- private readonly ICryptoProvider _cryptoProvider;
- private readonly IMemoryStreamFactory _memoryStreamFactory;
- private readonly ITextEncoding _textEncoding;
- internal HttpListenerContext(HttpConnection cnc, ILogger logger, ICryptoProvider cryptoProvider, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem)
- {
- this.cnc = cnc;
- _cryptoProvider = cryptoProvider;
- _memoryStreamFactory = memoryStreamFactory;
- _textEncoding = textEncoding;
- request = new HttpListenerRequest(this, _textEncoding);
- response = new HttpListenerResponse(this, logger, _textEncoding, fileSystem);
- }
- internal int ErrorStatus
- {
- get { return err_status; }
- set { err_status = value; }
- }
- internal string ErrorMessage
- {
- get { return error; }
- set { error = value; }
- }
- internal bool HaveError
- {
- get { return (error != null); }
- }
- internal HttpConnection Connection
- {
- get { return cnc; }
- }
- public HttpListenerRequest Request
- {
- get { return request; }
- }
- public HttpListenerResponse Response
- {
- get { return response; }
- }
- public IPrincipal User
- {
- get { return user; }
- }
- internal void ParseAuthentication(AuthenticationSchemes expectedSchemes)
- {
- if (expectedSchemes == AuthenticationSchemes.Anonymous)
- return;
- // TODO: Handle NTLM/Digest modes
- string header = request.Headers["Authorization"];
- if (header == null || header.Length < 2)
- return;
- string[] authenticationData = header.Split(new char[] { ' ' }, 2);
- if (string.Equals(authenticationData[0], "basic", StringComparison.OrdinalIgnoreCase))
- {
- user = ParseBasicAuthentication(authenticationData[1]);
- }
- // TODO: throw if malformed -> 400 bad request
- }
- internal IPrincipal ParseBasicAuthentication(string authData)
- {
- try
- {
- // Basic AUTH Data is a formatted Base64 String
- //string domain = null;
- string user = null;
- string password = null;
- int pos = -1;
- var authDataBytes = Convert.FromBase64String(authData);
- string authString = _textEncoding.GetDefaultEncoding().GetString(authDataBytes, 0, authDataBytes.Length);
- // The format is DOMAIN\username:password
- // Domain is optional
- pos = authString.IndexOf(':');
- // parse the password off the end
- password = authString.Substring(pos + 1);
- // discard the password
- authString = authString.Substring(0, pos);
- // check if there is a domain
- pos = authString.IndexOf('\\');
- if (pos > 0)
- {
- //domain = authString.Substring (0, pos);
- user = authString.Substring(pos);
- }
- else
- {
- user = authString;
- }
- HttpListenerBasicIdentity identity = new HttpListenerBasicIdentity(user, password);
- // TODO: What are the roles MS sets
- return new GenericPrincipal(identity, new string[0]);
- }
- catch (Exception)
- {
- // Invalid auth data is swallowed silently
- return null;
- }
- }
- public HttpListenerWebSocketContext AcceptWebSocket(string protocol)
- {
- if (protocol != null)
- {
- if (protocol.Length == 0)
- throw new ArgumentException("An empty string.", "protocol");
- if (!protocol.IsToken())
- throw new ArgumentException("Contains an invalid character.", "protocol");
- }
- return new HttpListenerWebSocketContext(this, protocol, _cryptoProvider, _memoryStreamFactory);
- }
- }
- public class GenericPrincipal : IPrincipal
- {
- private IIdentity m_identity;
- private string[] m_roles;
- public GenericPrincipal(IIdentity identity, string[] roles)
- {
- if (identity == null)
- throw new ArgumentNullException("identity");
- m_identity = identity;
- if (roles != null)
- {
- m_roles = new string[roles.Length];
- for (int i = 0; i < roles.Length; ++i)
- {
- m_roles[i] = roles[i];
- }
- }
- else
- {
- m_roles = null;
- }
- }
- public virtual IIdentity Identity
- {
- get
- {
- return m_identity;
- }
- }
- public virtual bool IsInRole(string role)
- {
- if (role == null || m_roles == null)
- return false;
- for (int i = 0; i < m_roles.Length; ++i)
- {
- if (m_roles[i] != null && String.Compare(m_roles[i], role, StringComparison.OrdinalIgnoreCase) == 0)
- return true;
- }
- return false;
- }
- }
- }
|