Skip to content

Commit df25f24

Browse files
committed
Merge remote-tracking branch 'github/master' into win1
# Conflicts: # Cargo.toml # fs_quota/src/lib.rs # src/main.rs # src/tls.rs
2 parents 9589a52 + 9f3ea0a commit df25f24

File tree

5 files changed

+151
-126
lines changed

5 files changed

+151
-126
lines changed

Cargo.toml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,12 @@ categories = ["filesystem"]
2727
#
2828
# cargo build --release --no-default-features --features=quota
2929
#
30-
default = [ "pam", "quota" ]
30+
default = [ "pam", "quota", "tls" ]
3131

3232
# dependencies for the feature.
3333
pam = [ "pam-sandboxed" ]
3434
quota = [ "fs-quota" ]
35+
tls = []
3536

3637
# Include debug info in release builds.
3738
[profile.release]
@@ -63,22 +64,23 @@ nix = "0.21.0"
6364
#pam-sandboxed = { path = "pam", version = "0.2.0", optional = true }
6465
percent-encoding = "2.1.0"
6566
regex = "1.5.4"
67+
rustls-pemfile = "1.0.0"
6668
serde = { version = "1.0.125", features = ["derive"] }
6769
serde_json = "1.0.64"
6870
socket2 = "0.4.0"
6971
time = "0.1.42"
70-
#tls-listener = { version = "0.2.1", features = [ "hyper-h1", "hyper-h2" ] }
72+
#tls-listener = { version = "0.5.1", features = [ "hyper-h1", "hyper-h2", "rustls" ] }
7173
tokio = { version = "1.5.0", features = ["full"] }
72-
#tokio-rustls = "0.22.0"
74+
#tokio-rustls = "0.23.4"
7375
toml = "0.5.8"
7476
url = "2.2.2"
7577
webdav-handler = { path = "webdav-handler-rs", version = "=0.2.0" }
7678
#webdav-handler = "0.2.0"
7779
pwhash = "1.0.0"
7880

79-
[target.'cfg(not(target_os = "windows"))'.dependencies]
81+
[target.'cfg(not(windows))'.dependencies]
8082
fs-quota = { path = "fs_quota", version = "0.1.0", optional = true }
8183
pam-sandboxed = { path = "pam", version = "0.2.0", optional = true }
82-
tls-listener = { version = "0.2.1", features = [ "hyper-h1", "hyper-h2" ] }
83-
tokio-rustls = "0.22.0"
84+
tls-listener = { version = "0.5.1", features = [ "hyper-h1", "hyper-h2", "rustls" ] }
85+
tokio-rustls = "0.23.4"
8486

fs_quota/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ impl FsQuota {
127127
return Err(FqError::IoError(io::Error::last_os_error()));
128128
}
129129
Ok(FsQuota {
130-
bytes_used: ((vfs.f_blocks - vfs.f_bfree) as u64 * vfs.f_bsize) as u64,
131-
bytes_limit: Some(((vfs.f_blocks - (vfs.f_bfree - vfs.f_bavail)) as u64 * vfs.f_bsize) as u64),
130+
bytes_used: ((vfs.f_blocks - vfs.f_bfree) * vfs.f_frsize) as u64,
131+
bytes_limit: Some(((vfs.f_blocks - (vfs.f_bfree - vfs.f_bavail)) * vfs.f_frsize) as u64),
132132
files_used: (vfs.f_files - vfs.f_ffree) as u64,
133133
files_limit: Some((vfs.f_files - (vfs.f_ffree - vfs.f_favail)) as u64),
134134
})

src/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ pub struct Server {
4545
pub gid: Option<u32>,
4646
#[serde(default)]
4747
pub identification: Option<String>,
48+
#[serde(default)]
49+
pub cors: bool,
4850
}
4951

5052
#[derive(Deserialize, Debug, Clone, Default)]

src/main.rs

Lines changed: 98 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ mod userfs;
2828
use std::convert::TryFrom;
2929
use std::io;
3030
use std::net::{SocketAddr, ToSocketAddrs};
31-
#[cfg(feature = "tls")]
31+
#[cfg(all(not(windows), feature = "tls"))]
3232
use std::os::unix::io::{FromRawFd, AsRawFd};
3333
use std::process::exit;
3434
use std::sync::Arc;
@@ -41,9 +41,9 @@ use hyper::{
4141
server::conn::{AddrIncoming, AddrStream},
4242
service::{make_service_fn, service_fn},
4343
};
44-
#[cfg(feature = "tls")]
44+
#[cfg(all(not(windows), feature = "tls"))]
4545
use tls_listener::TlsListener;
46-
#[cfg(feature = "tls")]
46+
#[cfg(all(not(windows), feature = "tls"))]
4747
use tokio_rustls::server::TlsStream;
4848
use webdav_handler::{davpath::DavPath, DavConfig, DavHandler, DavMethod, DavMethodSet};
4949
use webdav_handler::{fakels::FakeLs, fs::DavFileSystem, ls::DavLockSystem};
@@ -52,8 +52,8 @@ use crate::config::{AcctType, Auth, CaseInsensitive, Handler, Location, OnNotfou
5252
use crate::rootfs::RootFs;
5353
use crate::router::MatchedRoute;
5454
use crate::suid::proc_switch_ugid;
55-
#[cfg(feature = "tls")]
56-
use crate::tls::tls_config;
55+
#[cfg(all(not(windows), feature = "tls"))]
56+
use crate::tls::tls_acceptor;
5757
use crate::userfs::UserFs;
5858

5959
static PROGNAME: &'static str = "webdav-server";
@@ -105,48 +105,41 @@ impl Server {
105105
None => return Ok(None),
106106
};
107107

108-
#[cfg(target_os = "windows")]
108+
#[cfg(target_os = "windows")]
109109
panic!();
110-
#[cfg(not(target_os = "windows"))]
110+
#[cfg(not(target_os = "windows"))]
111111
{
112-
// check if user exists.
113-
let pwd = match cache::cached::unixuser(user, self.config.unix.aux_groups).await {
114-
Ok(pwd) => pwd,
115-
Err(_) => {
116-
debug!("acct: unix: user {} not found", user);
117-
return Err(StatusCode::UNAUTHORIZED);
118-
},
119-
};
112+
113+
// check if user exists.
114+
let pwd = match cache::cached::unixuser(user, self.config.unix.aux_groups).await {
115+
Ok(pwd) => pwd,
116+
Err(_) => {
117+
debug!("acct: unix: user {} not found", user);
118+
return Err(StatusCode::UNAUTHORIZED);
119+
},
120+
};
120121

121-
// check minimum uid
122-
if let Some(min_uid) = self.config.unix.min_uid {
123-
if pwd.uid < min_uid {
124-
debug!("acct: {}: uid {} too low (<{})", pwd.name, pwd.uid, min_uid);
125-
return Err(StatusCode::FORBIDDEN);
126-
}
122+
// check minimum uid
123+
if let Some(min_uid) = self.config.unix.min_uid {
124+
if pwd.uid < min_uid {
125+
debug!("acct: {}: uid {} too low (<{})", pwd.name, pwd.uid, min_uid);
126+
return Err(StatusCode::FORBIDDEN);
127127
}
128-
Ok(Some(pwd))
128+
}
129+
Ok(Some(pwd))
130+
129131
}
130132
}
131133

132-
// return a new response::Builder with the Server: header set.
134+
// return a new response::Builder with the Server and CORS header set.
133135
fn response_builder(&self) -> http::response::Builder {
134136
let mut builder = hyper::Response::builder();
135-
let id = self
136-
.config
137-
.server
138-
.identification
139-
.as_ref()
140-
.map(|s| s.as_str())
141-
.unwrap_or("webdav-server-rs");
142-
if id != "" {
143-
builder = builder.header("Server", id);
144-
}
137+
self.set_headers(builder.headers_mut().unwrap());
145138
builder
146139
}
147140

148-
// Set Server: webdav-server-rs header.
149-
fn set_server_header(&self, headers: &mut http::HeaderMap<http::header::HeaderValue>) {
141+
// Set Server: webdav-server-rs header, and CORS.
142+
fn set_headers(&self, headers: &mut http::HeaderMap<http::header::HeaderValue>) {
150143
let id = self
151144
.config
152145
.server
@@ -157,6 +150,11 @@ impl Server {
157150
if id != "" {
158151
headers.insert("server", id.parse().unwrap());
159152
}
153+
if self.config.server.cors {
154+
headers.insert("Access-Control-Allow-Origin", "*".parse().unwrap());
155+
headers.insert("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,PROPFIND".parse().unwrap());
156+
headers.insert("Access-Control-Allow-Headers", "DNT,Depth,Range".parse().unwrap());
157+
}
160158
}
161159

162160
// handle a request.
@@ -382,12 +380,11 @@ impl Server {
382380
async fn run_davhandler(&self, config: DavConfig, req: HttpRequest) -> HttpResult {
383381
let resp = self.dh.handle_with(config, req).await;
384382
let (mut parts, body) = resp.into_parts();
385-
self.set_server_header(&mut parts.headers);
383+
self.set_headers(&mut parts.headers);
386384
Ok(http::Response::from_parts(parts, body))
387385
}
388386
}
389387

390-
391388
fn main() -> Result<(), Box<dyn std::error::Error>> {
392389
// command line option processing.
393390
let matches = clap_app!(webdav_server =>
@@ -466,7 +463,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
466463
// build servers (one for each listen address).
467464
let dav_server = Server::new(config.clone(), auth);
468465
let mut servers = Vec::new();
469-
#[cfg(feature="tls")]
466+
#[cfg(all(not(windows), feature = "tls"))]
470467
let mut tls_servers = Vec::new();
471468

472469
// Plaintext servers.
@@ -502,68 +499,72 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
502499
});
503500
}
504501

505-
#[cfg(feature="tls")]
502+
#[cfg(all(not(windows), feature = "tls"))]
506503
// TLS servers.
507-
for sockaddr in tls_addrs {
508-
let listener = make_listener(sockaddr).unwrap_or_else(|e| {
509-
eprintln!("{}: listener on {:?}: {}", PROGNAME, &sockaddr, e);
510-
exit(1);
511-
});
512-
let dav_server = dav_server.clone();
513-
let tls_config = tls_config(&config.server)?;
514-
let make_service = make_service_fn(move |stream: &TlsStream<AddrStream>| {
515-
let dav_server = dav_server.clone();
516-
let remote_addr = stream.get_ref().0.remote_addr();
517-
async move {
518-
let func = move |req| {
519-
let dav_server = dav_server.clone();
520-
async move { dav_server.route(req, remote_addr).await }
521-
};
522-
Ok::<_, hyper::Error>(service_fn(func))
523-
}
524-
});
525-
526-
// Since the server can exit when there's an error on the TlsStream,
527-
// we run it in a loop. Every time the loop is entered we dup() the
528-
// listening fd and create a new TcpListener. This way, we should
529-
// not lose any pending connections during a restart.
530-
let master_listen_fd = listener.as_raw_fd();
531-
std::mem::forget(listener);
504+
if tls_addrs.len() > 0 {
505+
let tls_acceptor = tls_acceptor(&config.server)?;
532506

533-
println!("Listening on http://{:?}", sockaddr);
534-
tls_servers.push(async move {
535-
loop {
536-
// reuse the incoming socket after the server exits.
537-
let listen_fd = match nix::unistd::dup(master_listen_fd) {
538-
Ok(fd) => fd,
539-
Err(e) => {
540-
eprintln!("{}: server error: dup: {}", PROGNAME, e);
541-
break;
542-
}
543-
};
544-
// SAFETY: listen_fd is unique (we just dup'ed it).
545-
let std_listen = unsafe { std::net::TcpListener::from_raw_fd(listen_fd) };
546-
let listener = match tokio::net::TcpListener::from_std(std_listen) {
547-
Ok(l) => l,
548-
Err(e) => {
549-
eprintln!("{}: server error: new TcpListener: {}", PROGNAME, e);
550-
break;
551-
}
552-
};
553-
let a_incoming = match AddrIncoming::from_listener(listener) {
554-
Ok(a) => a,
555-
Err(e) => {
556-
eprintln!("{}: server error: new AddrIncoming: {}", PROGNAME, e);
557-
break;
507+
for sockaddr in tls_addrs {
508+
let tls_acceptor = tls_acceptor.clone();
509+
let listener = make_listener(sockaddr).unwrap_or_else(|e| {
510+
eprintln!("{}: listener on {:?}: {}", PROGNAME, &sockaddr, e);
511+
exit(1);
512+
});
513+
let dav_server = dav_server.clone();
514+
let make_service = make_service_fn(move |stream: &TlsStream<AddrStream>| {
515+
let dav_server = dav_server.clone();
516+
let remote_addr = stream.get_ref().0.remote_addr();
517+
async move {
518+
let func = move |req| {
519+
let dav_server = dav_server.clone();
520+
async move { dav_server.route(req, remote_addr).await }
521+
};
522+
Ok::<_, hyper::Error>(service_fn(func))
523+
}
524+
});
525+
526+
// Since the server can exit when there's an error on the TlsStream,
527+
// we run it in a loop. Every time the loop is entered we dup() the
528+
// listening fd and create a new TcpListener. This way, we should
529+
// not lose any pending connections during a restart.
530+
let master_listen_fd = listener.as_raw_fd();
531+
std::mem::forget(listener);
532+
533+
println!("Listening on https://{:?}", sockaddr);
534+
tls_servers.push(async move {
535+
loop {
536+
// reuse the incoming socket after the server exits.
537+
let listen_fd = match nix::unistd::dup(master_listen_fd) {
538+
Ok(fd) => fd,
539+
Err(e) => {
540+
eprintln!("{}: server error: dup: {}", PROGNAME, e);
541+
break;
542+
}
543+
};
544+
// SAFETY: listen_fd is unique (we just dup'ed it).
545+
let std_listen = unsafe { std::net::TcpListener::from_raw_fd(listen_fd) };
546+
let listener = match tokio::net::TcpListener::from_std(std_listen) {
547+
Ok(l) => l,
548+
Err(e) => {
549+
eprintln!("{}: server error: new TcpListener: {}", PROGNAME, e);
550+
break;
551+
}
552+
};
553+
let a_incoming = match AddrIncoming::from_listener(listener) {
554+
Ok(a) => a,
555+
Err(e) => {
556+
eprintln!("{}: server error: new AddrIncoming: {}", PROGNAME, e);
557+
break;
558+
}
559+
};
560+
let incoming = TlsListener::new(tls_acceptor.clone(), a_incoming);
561+
let server = hyper::Server::builder(incoming);
562+
if let Err(e) = server.serve(make_service.clone()).await {
563+
eprintln!("{}: server error: {} (retrying)", PROGNAME, e);
558564
}
559-
};
560-
let incoming = TlsListener::new(tls_config.clone(), a_incoming);
561-
let server = hyper::Server::builder(incoming);
562-
if let Err(e) = server.serve(make_service.clone()).await {
563-
eprintln!("{}: server error: {} (retrying)", PROGNAME, e);
564565
}
565-
}
566-
});
566+
});
567+
}
567568
}
568569

569570
// drop privs.
@@ -587,7 +588,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
587588
for server in servers.drain(..) {
588589
tasks.push(tokio::spawn(server));
589590
}
590-
#[cfg(feature="tls")]
591+
#[cfg(all(not(windows), feature = "tls"))]
591592
for server in tls_servers.drain(..) {
592593
tasks.push(tokio::spawn(server));
593594
}

0 commit comments

Comments
 (0)