/// <summary> /// Parses a specific HTTP header field. /// </summary> /// <param name="KeyLower">Lower-case version of field name.</param> /// <param name="Key">Field name, as it appears in the header.</param> /// <param name="Value">Unparsed header field value</param> /// <returns>HTTP header field object, corresponding to the particular field.</returns> protected override HttpField ParseField(string KeyLower, string Key, string Value) { switch (KeyLower) { case "accept": return(this.accept = new HttpFieldAccept(Key, Value)); case "accept-charset": return(this.acceptCharset = new HttpFieldAcceptCharset(Key, Value)); case "accept-encoding": return(this.acceptEncoding = new HttpFieldAcceptEncoding(Key, Value)); case "accept-language": return(this.acceptLanguage = new HttpFieldAcceptLanguage(Key, Value)); case "authorization": return(this.authorization = new HttpFieldAuthorization(Key, Value)); case "cookie": return(this.cookie = new HttpFieldCookie(Key, Value)); case "expect": return(this.expect = new HttpFieldExpect(Key, Value)); case "from": return(this.from = new HttpFieldFrom(Key, Value)); case "host": return(this.host = new HttpFieldHost(Key, Value)); case "if-match": return(this.ifMatch = new HttpFieldIfMatch(Key, Value)); case "if-modified-since": return(this.ifModifiedSince = new HttpFieldIfModifiedSince(Key, Value)); case "if-none-match": return(this.ifNoneMatch = new HttpFieldIfNoneMatch(Key, Value)); case "if-range": return(this.ifRange = new HttpFieldIfRange(Key, Value)); case "if-unmodified-since": return(this.ifUnmodifiedSince = new HttpFieldIfUnmodifiedSince(Key, Value)); case "referer": return(this.referer = new HttpFieldReferer(Key, Value)); case "range": return(this.range = new HttpFieldRange(Key, Value)); case "user-agent": return(this.userAgent = new HttpFieldUserAgent(Key, Value)); case "upgrade-insecure-requests": return(this.upgradeInsequreRequests = new HttpFieldUpgradeInsecureRequests(Key, Value)); default: return(base.ParseField(KeyLower, Key, Value)); } }
/// <summary> /// Executes the POST method on the resource. /// </summary> /// <param name="Request">HTTP Request</param> /// <param name="Response">HTTP Response</param> /// <exception cref="HttpException">If an error occurred when processing the method.</exception> public void POST(HttpRequest Request, HttpResponse Response) { if (!Request.HasData || Request.Session == null) { throw new BadRequestException(); } // TODO: Check User authenticated object Obj = Request.DecodeData(); string TabID = Request.Header["X-TabID"]; if (!(Obj is string Location) || string.IsNullOrEmpty(TabID)) { throw new BadRequestException(); } Uri Uri = new Uri(Location); string Resource = Uri.LocalPath; List <KeyValuePair <string, string> > Query = null; string s; if (!string.IsNullOrEmpty(Uri.Query)) { Query = new List <KeyValuePair <string, string> >(); int i; s = Uri.Query; if (s.StartsWith("?")) { s = s.Substring(1); } foreach (string Part in s.Split('&')) { i = Part.IndexOf('='); if (i < 0) { Query.Add(new KeyValuePair <string, string>(Part, string.Empty)); } else { Query.Add(new KeyValuePair <string, string>(Part.Substring(0, i), Part.Substring(i + 1))); } } } Response.ContentType = "application/json"; if (!eventsByTabID.TryGetValue(TabID, out TabQueue Queue)) { HttpFieldCookie Cookie = Request.Header.Cookie; string HttpSessionID = Cookie == null ? string.Empty : Cookie["HttpSessionID"]; Queue = new TabQueue(TabID, HttpSessionID, Request.Session); eventsByTabID[TabID] = Queue; } lock (locationByTabID) { if (!locationByTabID.TryGetValue(TabID, out s) || s != Resource) { locationByTabID[TabID] = Resource; } } lock (tabIdsByLocation) { if (!tabIdsByLocation.TryGetValue(Resource, out Dictionary <string, List <KeyValuePair <string, string> > > TabIds)) { TabIds = new Dictionary <string, List <KeyValuePair <string, string> > >(); tabIdsByLocation[Resource] = TabIds; } TabIds[TabID] = Query; } StringBuilder Json = null; lock (Queue) { if (Queue.Queue.First != null) { foreach (string Event in Queue.Queue) { if (Json == null) { Json = new StringBuilder("["); } else { Json.Append(','); } Json.Append(Event); } Queue.Queue.Clear(); Queue.Response = null; } else { Queue.Response = Response; } } if (Json != null) { timeoutByTabID.Remove(TabID); Json.Append(']'); Response.Write(Json.ToString()); Response.SendResponse(); Response.Dispose(); } else { timeoutByTabID[TabID] = Queue; } }
internal static void RegisterWebSocket(WebSocket Socket, string Location, string TabID) { Uri Uri = new Uri(Location); string Resource = Uri.LocalPath; List <KeyValuePair <string, string> > Query = null; string s; if (!string.IsNullOrEmpty(Uri.Query)) { Query = new List <KeyValuePair <string, string> >(); int i; s = Uri.Query; if (s.StartsWith("?")) { s = s.Substring(1); } foreach (string Part in s.Split('&')) { i = Part.IndexOf('='); if (i < 0) { Query.Add(new KeyValuePair <string, string>(Part, string.Empty)); } else { Query.Add(new KeyValuePair <string, string>(Part.Substring(0, i), Part.Substring(i + 1))); } } } if (eventsByTabID.TryGetValue(TabID, out TabQueue Queue)) { Queue.WebSocket = Socket; } else { HttpFieldCookie Cookie = Socket.HttpRequest.Header.Cookie; string HttpSessionID = Cookie == null ? string.Empty : Cookie["HttpSessionID"]; Queue = new TabQueue(TabID, HttpSessionID, Socket.HttpRequest.Session) { WebSocket = Socket }; eventsByTabID[TabID] = Queue; } lock (locationByTabID) { if (!locationByTabID.TryGetValue(TabID, out s) || s != Resource) { locationByTabID[TabID] = Resource; } } lock (tabIdsByLocation) { if (!tabIdsByLocation.TryGetValue(Resource, out Dictionary <string, List <KeyValuePair <string, string> > > TabIds)) { TabIds = new Dictionary <string, List <KeyValuePair <string, string> > >(); tabIdsByLocation[Resource] = TabIds; } TabIds[TabID] = Query; } LinkedList <string> ToSend = null; lock (Queue) { if (Queue.Queue.First != null) { ToSend = new LinkedList <string>(); foreach (string s2 in Queue.Queue) { ToSend.AddLast(s2); } Queue.Queue.Clear(); } } if (ToSend != null) { foreach (string s2 in ToSend) { Socket.Send(s2, 4096); } } }
internal async Task Process(string Id, string From, string To, HttpRequest Request, IEndToEndEncryption E2e, string EndpointReference, int MaxChunkSize, string PostResource, bool Ibb, bool Socks5) { HttpAuthenticationScheme[] AuthenticationSchemes; bool Result; try { if (this.server.TryGetResource(Request.Header.Resource, out HttpResource Resource, out string SubPath)) { Request.Resource = Resource; this.server.RequestReceived(Request, From, Resource, SubPath); AuthenticationSchemes = Resource.GetAuthenticationSchemes(Request); if (AuthenticationSchemes != null && AuthenticationSchemes.Length > 0) { foreach (HttpAuthenticationScheme Scheme in AuthenticationSchemes) { if (Scheme.UserSessions && Request.Session is null) { HttpFieldCookie Cookie = Request.Header.Cookie; if (!(Cookie is null)) { string HttpSessionID = Cookie["HttpSessionID"]; if (!string.IsNullOrEmpty(HttpSessionID)) { Request.Session = this.server.GetSession(HttpSessionID); } } } IUser User = await Scheme.IsAuthenticated(Request); if (!(User is null)) { Request.User = User; break; } } if (Request.User is null) { List <KeyValuePair <string, string> > Challenges = new List <KeyValuePair <string, string> >(); foreach (HttpAuthenticationScheme Scheme in AuthenticationSchemes) { string Challenge = Scheme.GetChallenge(); if (!string.IsNullOrEmpty(Challenge)) { Challenges.Add(new KeyValuePair <string, string>("WWW-Authenticate", Challenge)); } } await this.SendQuickResponse(Request, E2e, EndpointReference, Id, From, To, 401, "Unauthorized", false, MaxChunkSize, Challenges.ToArray()); Request.Dispose(); return; } } Request.SubPath = SubPath; Resource.Validate(Request); if (Request.Header.Expect != null) { if (Request.Header.Expect.Continue100) { if (!Request.HasData) { await this.SendQuickResponse(Request, E2e, EndpointReference, Id, From, To, 100, "Continue", false, MaxChunkSize); return; } } else { await this.SendQuickResponse(Request, E2e, EndpointReference, Id, From, To, 417, "Expectation Failed", true, MaxChunkSize); Request.Dispose(); return; } } await this.ExecuteRequest(E2e, EndpointReference, Id, From, To, MaxChunkSize, PostResource, Ibb, Socks5, Request, Resource); return; } else { this.server.RequestReceived(Request, From, null, null); await this.SendQuickResponse(Request, E2e, EndpointReference, Id, From, To, 404, "Not Found", false, MaxChunkSize); Result = true; } }
private async Task <bool?> QueueRequest(HttpRequest Request) { HttpAuthenticationScheme[] AuthenticationSchemes; bool Result; try { if (this.server.TryGetResource(Request.Header.Resource, out HttpResource Resource, out string SubPath)) { Request.Resource = Resource; Request.SubPath = SubPath; #if WINDOWS_UWP this.server.RequestReceived(Request, this.client.Client.Information.RemoteAddress.ToString() + ":" + this.client.Client.Information.RemotePort, Resource, SubPath); #else this.server.RequestReceived(Request, this.client.Client.Client.RemoteEndPoint.ToString(), Resource, SubPath); #endif AuthenticationSchemes = Resource.GetAuthenticationSchemes(Request); if (AuthenticationSchemes != null && AuthenticationSchemes.Length > 0) { ILoginAuditor Auditor = this.server.LoginAuditor; if (!(Auditor is null)) { DateTime?Next = await Auditor.GetEarliestLoginOpportunity(Request.RemoteEndPoint, "HTTP"); if (Next.HasValue) { StringBuilder sb = new StringBuilder(); DateTime TP = Next.Value; DateTime Today = DateTime.Today; HttpException Error; if (Next.Value == DateTime.MaxValue) { sb.Append("This endpoint ("); sb.Append(Request.RemoteEndPoint); sb.Append(") has been blocked from the system."); Error = new ForbiddenException(sb.ToString()); } else { sb.Append("Too many failed login attempts in a row registered. Try again in "); TimeSpan Span = TP - DateTime.Now; double d; if ((d = Span.TotalDays) >= 1) { d = Math.Ceiling(d); sb.Append(d.ToString()); sb.Append(" day"); } else if ((d = Span.TotalHours) >= 1) { d = Math.Ceiling(d); sb.Append(d.ToString()); sb.Append(" hour"); } else { d = Math.Ceiling(Span.TotalMinutes); sb.Append(d.ToString()); sb.Append(" minute"); } if (d > 1) { sb.Append('s'); } sb.Append('.'); Error = new TooManyRequestsException(sb.ToString()); } await this.SendResponse(Request, null, Error, true); Request.Dispose(); return(true); } } foreach (HttpAuthenticationScheme Scheme in AuthenticationSchemes) { if (Scheme.UserSessions && Request.Session is null) { HttpFieldCookie Cookie = Request.Header.Cookie; if (!(Cookie is null)) { string HttpSessionID = Cookie["HttpSessionID"]; if (!string.IsNullOrEmpty(HttpSessionID)) { Request.Session = this.server.GetSession(HttpSessionID); } } } IUser User = await Scheme.IsAuthenticated(Request); if (!(User is null)) { Request.User = User; break; } } if (Request.User is null) { List <KeyValuePair <string, string> > Challenges = new List <KeyValuePair <string, string> >(); foreach (HttpAuthenticationScheme Scheme in AuthenticationSchemes) { string Challenge = Scheme.GetChallenge(); if (!string.IsNullOrEmpty(Challenge)) { Challenges.Add(new KeyValuePair <string, string>("WWW-Authenticate", Challenge)); } } await this.SendResponse(Request, null, new HttpException(401, "Unauthorized", "Unauthorized access prohibited."), false, Challenges.ToArray()); Request.Dispose(); return(true); } } Resource.Validate(Request); if (Request.Header.Expect != null) { if (Request.Header.Expect.Continue100) { if (!Request.HasData) { await this.SendResponse(Request, null, new HttpException(100, "Continue", null), false); return(null); } } else { await this.SendResponse(Request, null, new HttpException(417, "Expectation Failed", "Unable to parse Expect header."), true); Request.Dispose(); return(false); } } Task _ = Task.Run(() => this.ProcessRequest(Request, Resource)); return(true); } else { await this.SendResponse(Request, null, new NotFoundException("Resource not found: " + this.server.CheckResourceOverride(Request.Header.Resource)), false); Result = true; } }