From 07b1e2748c7079df60309debc314f0343a892268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 8 May 2017 11:43:25 +0200 Subject: [PATCH] Proper check for Origins in WS server. --- server-utils/src/cors.rs | 13 +++++++------ server-utils/src/hosts.rs | 13 +++++++------ server-utils/src/lib.rs | 2 ++ server-utils/src/matcher.rs | 10 +++++++++- ws/src/session.rs | 6 +++--- 5 files changed, 28 insertions(+), 16 deletions(-) diff --git a/server-utils/src/cors.rs b/server-utils/src/cors.rs index 50c6703cf..c2ae8f408 100644 --- a/server-utils/src/cors.rs +++ b/server-utils/src/cors.rs @@ -2,7 +2,7 @@ use std::{fmt, ops}; use hosts::{Host, Port}; -use matcher::Matcher; +use matcher::{Matcher, Pattern}; /// Origin Protocol #[derive(Clone, Hash, Debug, PartialEq, Eq)] @@ -74,11 +74,6 @@ impl Origin { Origin::with_host(protocol, hostname) } - /// Checks if given string matches the pattern. - pub fn matches>(&self, other: T) -> bool { - self.matcher.matches(other) - } - fn to_string(protocol: &OriginProtocol, host: &Host) -> String { format!( "{}://{}", @@ -92,6 +87,12 @@ impl Origin { } } +impl Pattern for Origin { + fn matches>(&self, other: T) -> bool { + self.matcher.matches(other) + } +} + impl ops::Deref for Origin { type Target = str; fn deref(&self) -> &Self::Target { diff --git a/server-utils/src/hosts.rs b/server-utils/src/hosts.rs index 2ae5d3478..50196fccc 100644 --- a/server-utils/src/hosts.rs +++ b/server-utils/src/hosts.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::net::SocketAddr; -use matcher::Matcher; +use matcher::{Matcher, Pattern}; const SPLIT_PROOF: &'static str = "split always returns non-empty iterator."; @@ -80,11 +80,6 @@ impl Host { Host::new(host, port) } - /// Checks if given string matches the pattern. - pub fn matches>(&self, other: T) -> bool { - self.matcher.matches(other) - } - fn pre_process(host: &str) -> String { // Remove possible protocol definition let mut it = host.split("://"); @@ -111,6 +106,12 @@ impl Host { } } +impl Pattern for Host { + fn matches>(&self, other: T) -> bool { + self.matcher.matches(other) + } +} + impl ::std::ops::Deref for Host { type Target = str; fn deref(&self) -> &Self::Target { diff --git a/server-utils/src/lib.rs b/server-utils/src/lib.rs index 94cad1593..6d911a6db 100644 --- a/server-utils/src/lib.rs +++ b/server-utils/src/lib.rs @@ -14,3 +14,5 @@ pub mod cors; pub mod hosts; pub mod reactor; mod matcher; + +pub use matcher::Pattern; diff --git a/server-utils/src/matcher.rs b/server-utils/src/matcher.rs index 004d7d7db..37d2c4c5e 100644 --- a/server-utils/src/matcher.rs +++ b/server-utils/src/matcher.rs @@ -2,6 +2,12 @@ use globset::{GlobMatcher, GlobBuilder}; use std::ascii::AsciiExt; use std::{fmt, hash}; +/// Pattern that can be matched to string. +pub trait Pattern { + /// Returns true if given string matches the pattern. + fn matches>(&self, other: T) -> bool; +} + #[derive(Clone)] pub struct Matcher(Option, String); impl Matcher { @@ -16,8 +22,10 @@ impl Matcher { string.into() ) } +} - pub fn matches>(&self, other: T) -> bool { +impl Pattern for Matcher { + fn matches>(&self, other: T) -> bool { let s = other.as_ref(); match self.0 { Some(ref matcher) => matcher.is_match(s), diff --git a/ws/src/session.rs b/ws/src/session.rs index 3d220b43a..ae509a952 100644 --- a/ws/src/session.rs +++ b/ws/src/session.rs @@ -1,9 +1,9 @@ use std; -use std::ascii::AsciiExt; use std::sync::{atomic, Arc}; use core; use core::futures::Future; +use server_utils::Pattern; use server_utils::cors::Origin; use server_utils::hosts::Host; use server_utils::tokio_core::reactor::Remote; @@ -258,7 +258,7 @@ impl> ws::Factory for Factory { } fn header_is_allowed(allowed: &Option>, header: Option<&[u8]>) -> bool where - T: ::std::ops::Deref, + T: Pattern, { let header = header.map(std::str::from_utf8); @@ -270,7 +270,7 @@ fn header_is_allowed(allowed: &Option>, header: Option<&[u8]>) -> bool // Validate Origin (Some(Ok(val)), Some(values)) => { for v in values { - if val.eq_ignore_ascii_case(&v) { + if v.matches(val) { return true } }