mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Validate proxy urls better.
Use the url crate to handle proxies to make sure they conform to a proper format.
This commit is contained in:
parent
1a04e3b899
commit
3a14e9a6be
8 changed files with 35 additions and 24 deletions
|
@ -50,7 +50,7 @@ serde_json = "0.9.5"
|
||||||
tokio-core = "0.1.2"
|
tokio-core = "0.1.2"
|
||||||
tokio-io = "0.1"
|
tokio-io = "0.1"
|
||||||
tokio-signal = "0.1.2"
|
tokio-signal = "0.1.2"
|
||||||
url = "1.3"
|
url = "1.7.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
rand = "0.3.13"
|
rand = "0.3.13"
|
||||||
|
|
|
@ -32,6 +32,7 @@ serde_json = "0.9.5"
|
||||||
shannon = "0.2.0"
|
shannon = "0.2.0"
|
||||||
tokio-core = "0.1.2"
|
tokio-core = "0.1.2"
|
||||||
tokio-io = "0.1"
|
tokio-io = "0.1"
|
||||||
|
url = "1.7.0"
|
||||||
uuid = { version = "0.4", features = ["v4"] }
|
uuid = { version = "0.4", features = ["v4"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
|
|
@ -8,6 +8,7 @@ use hyper_proxy::{Intercept, Proxy, ProxyConnector};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use tokio_core::reactor::Handle;
|
use tokio_core::reactor::Handle;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
error_chain!{}
|
error_chain!{}
|
||||||
|
|
||||||
|
@ -16,14 +17,14 @@ pub struct APResolveData {
|
||||||
ap_list: Vec<String>,
|
ap_list: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apresolve(handle: &Handle, proxy: &Option<String>) -> Box<Future<Item = String, Error = Error>> {
|
fn apresolve(handle: &Handle, proxy: &Option<Url>) -> Box<Future<Item = String, Error = Error>> {
|
||||||
let url = Uri::from_str(APRESOLVE_ENDPOINT).expect("invalid AP resolve URL");
|
let url = Uri::from_str(APRESOLVE_ENDPOINT).expect("invalid AP resolve URL");
|
||||||
let use_proxy = proxy.is_some();
|
let use_proxy = proxy.is_some();
|
||||||
|
|
||||||
let mut req = Request::new(Method::Get, url.clone());
|
let mut req = Request::new(Method::Get, url.clone());
|
||||||
let response = match proxy {
|
let response = match *proxy {
|
||||||
&Some(ref val) => {
|
Some(ref val) => {
|
||||||
let proxy_url = Uri::from_str(&val).expect("invalid http proxy");
|
let proxy_url = Uri::from_str(val.as_str()).expect("invalid http proxy");
|
||||||
let proxy = Proxy::new(Intercept::All, proxy_url);
|
let proxy = Proxy::new(Intercept::All, proxy_url);
|
||||||
let connector = HttpConnector::new(4, handle);
|
let connector = HttpConnector::new(4, handle);
|
||||||
let proxy_connector = ProxyConnector::from_proxy_unsecured(connector, proxy);
|
let proxy_connector = ProxyConnector::from_proxy_unsecured(connector, proxy);
|
||||||
|
@ -73,7 +74,7 @@ fn apresolve(handle: &Handle, proxy: &Option<String>) -> Box<Future<Item = Strin
|
||||||
|
|
||||||
pub(crate) fn apresolve_or_fallback<E>(
|
pub(crate) fn apresolve_or_fallback<E>(
|
||||||
handle: &Handle,
|
handle: &Handle,
|
||||||
proxy: &Option<String>,
|
proxy: &Option<Url>,
|
||||||
) -> Box<Future<Item = String, Error = E>>
|
) -> Box<Future<Item = String, Error = E>>
|
||||||
where
|
where
|
||||||
E: 'static,
|
E: 'static,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use url::Url;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use version;
|
use version;
|
||||||
|
@ -8,7 +9,7 @@ use version;
|
||||||
pub struct SessionConfig {
|
pub struct SessionConfig {
|
||||||
pub user_agent: String,
|
pub user_agent: String,
|
||||||
pub device_id: String,
|
pub device_id: String,
|
||||||
pub proxy: Option<String>,
|
pub proxy: Option<Url>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SessionConfig {
|
impl Default for SessionConfig {
|
||||||
|
|
|
@ -5,14 +5,13 @@ pub use self::codec::APCodec;
|
||||||
pub use self::handshake::handshake;
|
pub use self::handshake::handshake;
|
||||||
|
|
||||||
use futures::{Future, Sink, Stream};
|
use futures::{Future, Sink, Stream};
|
||||||
use hyper::Uri;
|
|
||||||
use protobuf::{self, Message};
|
use protobuf::{self, Message};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
use std::str::FromStr;
|
|
||||||
use tokio_core::net::TcpStream;
|
use tokio_core::net::TcpStream;
|
||||||
use tokio_core::reactor::Handle;
|
use tokio_core::reactor::Handle;
|
||||||
use tokio_io::codec::Framed;
|
use tokio_io::codec::Framed;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
use authentication::Credentials;
|
use authentication::Credentials;
|
||||||
use version;
|
use version;
|
||||||
|
@ -24,22 +23,12 @@ pub type Transport = Framed<TcpStream, APCodec>;
|
||||||
pub fn connect(
|
pub fn connect(
|
||||||
addr: String,
|
addr: String,
|
||||||
handle: &Handle,
|
handle: &Handle,
|
||||||
proxy: &Option<String>,
|
proxy: &Option<Url>,
|
||||||
) -> Box<Future<Item = Transport, Error = io::Error>> {
|
) -> Box<Future<Item = Transport, Error = io::Error>> {
|
||||||
let (addr, connect_url) = match *proxy {
|
let (addr, connect_url) = match *proxy {
|
||||||
Some(ref url) => {
|
Some(ref url) => {
|
||||||
let url = Uri::from_str(url).expect("Malformed proxy address");
|
info!("Using proxy \"{}\"", url);
|
||||||
let host = url.host().expect("Malformed proxy address: no host");
|
(url.to_socket_addrs().unwrap().next().unwrap(), Some(addr))
|
||||||
let port = url.port().unwrap_or(3128);
|
|
||||||
|
|
||||||
(
|
|
||||||
format!("{}:{}", host, port)
|
|
||||||
.to_socket_addrs()
|
|
||||||
.unwrap()
|
|
||||||
.next()
|
|
||||||
.unwrap(),
|
|
||||||
Some(addr.clone()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
None => (addr.to_socket_addrs().unwrap().next().unwrap(), None),
|
None => (addr.to_socket_addrs().unwrap().next().unwrap(), None),
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,6 +30,7 @@ extern crate serde_json;
|
||||||
extern crate shannon;
|
extern crate shannon;
|
||||||
extern crate tokio_core;
|
extern crate tokio_core;
|
||||||
extern crate tokio_io;
|
extern crate tokio_io;
|
||||||
|
extern crate url;
|
||||||
extern crate uuid;
|
extern crate uuid;
|
||||||
|
|
||||||
extern crate librespot_protocol as protocol;
|
extern crate librespot_protocol as protocol;
|
||||||
|
|
|
@ -96,7 +96,7 @@ impl<T: AsyncRead + AsyncWrite> Future for ProxyTunnel<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn proxy_connect<T: AsyncWrite>(connection: T, connect_url: &str) -> WriteAll<T, Vec<u8>> {
|
fn proxy_connect<T: AsyncWrite>(connection: T, connect_url: &str) -> WriteAll<T, Vec<u8>> {
|
||||||
let uri = Uri::from_str(&connect_url).unwrap();
|
let uri = Uri::from_str(connect_url).unwrap();
|
||||||
let buffer = format!(
|
let buffer = format!(
|
||||||
"CONNECT {0}:{1} HTTP/1.1\r\n\
|
"CONNECT {0}:{1} HTTP/1.1\r\n\
|
||||||
\r\n",
|
\r\n",
|
||||||
|
|
20
src/main.rs
20
src/main.rs
|
@ -9,6 +9,7 @@ extern crate rpassword;
|
||||||
extern crate tokio_core;
|
extern crate tokio_core;
|
||||||
extern crate tokio_io;
|
extern crate tokio_io;
|
||||||
extern crate tokio_signal;
|
extern crate tokio_signal;
|
||||||
|
extern crate url;
|
||||||
|
|
||||||
use crypto::digest::Digest;
|
use crypto::digest::Digest;
|
||||||
use crypto::sha1::Sha1;
|
use crypto::sha1::Sha1;
|
||||||
|
@ -23,6 +24,7 @@ use std::process::exit;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use tokio_core::reactor::{Core, Handle};
|
use tokio_core::reactor::{Core, Handle};
|
||||||
use tokio_io::IoStream;
|
use tokio_io::IoStream;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
use librespot::core::authentication::{get_credentials, Credentials};
|
use librespot::core::authentication::{get_credentials, Credentials};
|
||||||
use librespot::core::cache::Cache;
|
use librespot::core::cache::Cache;
|
||||||
|
@ -248,7 +250,23 @@ fn setup(args: &[String]) -> Setup {
|
||||||
SessionConfig {
|
SessionConfig {
|
||||||
user_agent: version::version_string(),
|
user_agent: version::version_string(),
|
||||||
device_id: device_id,
|
device_id: device_id,
|
||||||
proxy: matches.opt_str("proxy").or(std::env::var("http_proxy").ok()),
|
proxy: matches.opt_str("proxy").or(std::env::var("http_proxy").ok()).map(
|
||||||
|
|s| {
|
||||||
|
match Url::parse(&s) {
|
||||||
|
Ok(url) => {
|
||||||
|
if url.host().is_none() || url.port().is_none() {
|
||||||
|
panic!("Invalid proxy url, only urls on the format \"http://host:port\" are allowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if url.scheme() != "http" {
|
||||||
|
panic!("Only unsecure http:// proxies are supported");
|
||||||
|
}
|
||||||
|
url
|
||||||
|
},
|
||||||
|
Err(err) => panic!("Invalid proxy url: {}, only urls on the format \"http://host:port\" are allowed", err)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue