Giter Club home page Giter Club logo

webdav-daemon's Introduction

webdavd(1) - WebDAV daemon

About

webdavd is a WebDAV server designed to be a replace for SAMBA providing access to a system's files without taking ownership of them. It aims to differ from most WebDAV servers on a number of points:

  • Users are authenticated through PAM and are always operating system users.
  • The webserver switches OS user to match the authenticated user before accessing any files.
  • The daemon operates without any prior knowledge of the files it's serving.
  • The daemon does NOT take ownership of the files it modifies and serves. It does not take ownership of any files in any way. Even locking operations are implemented using the native OS flock() function.

Licence

(c) Copyright Philip Couling 2013-2017

This code may be used under an MIT Licence. Please see LICENCE.md for details.

Starting the server

If properly installed the server can be started with:

service webdavd start

The server can be started manually by calling:

webdavd config-file [config-file ...]

See Configuration for details of the config file.

Known Issues

  • Locking file is limited and it is currently not possible to lock a directory
  • PAM sessions are of a fixed length and their length is not affected by user activity.

Building from source

Under Ubuntu

sudo apt-get install gcc libmicrohttpd-dev libpam0g-dev libxml2-dev libgnutls28-dev libgnutls30 uuid-dev
make

Under Raspbian

sudo apt-get install gcc libmicrohttpd-dev libpam0g-dev libxml2-dev libgnutls28-dev uuid-dev
make

Packaging into a dpkg

To assemble everything into a DPKG you can either read one of the manifest files package-control/manifest.ubuntu or package-control/manifest.rpi

Or you can use my package-project script. For example:

package-project package-control/manifest.ubuntu

Packaging into an rpm on RHEL8

Use the included SPEC file to build the rpm file. package-control/webdavd.spec. It is sufficient to only download the SPEC file and run the below commands.

sudo dnf builddep webdavd.spec
rpmbuild --undefine=_disable_source_fetch -ba webdavd.spec

webdav-daemon's People

Contributors

couling avatar sbluhm avatar xyzzy42 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

webdav-daemon's Issues

OPTIONS request requires authentication

When an OPTIONS request is received, the server requires authentication. This will cause CORS requests to fail.

See https://www.jujens.eu/posts/en/2015/Jun/27/webdav-options/

Test: curl -i -X OPTIONS https://www.example.com
Result:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="My Server"
Content-Type: text/html

Expectation:

HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Length: 0
Accept: OPTIONS, GET, HEAD, DELETE, PROPFIND, PUT, PROPPATCH, COPY, MOVE, LOCK, UNLOCK
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 19 Nov 1980 00:00:00 GMT
Server: couling-webdavd
Accept-Ranges: bytes
DAV: 1
Content-Type: text/html

Resumable upload

Hi, I'm looking for a WebDAV server which could handle a storage of several terabytes of data (mainly pics & videos). Therefore I need to be absolutely sure the server supports resumable uploads (e.g. after network connection interruption or after smartphone restart etc.). Is it supported by default by webdavd? If not, could this be implemented?

And btw. do I need to care myself about SSL certificates or does webdavd have something like (optional) Let's Encrypt support like caddy does?

Installation help please

Sorry I am a linux ubuntu noob. I was able to make the binary and config file. However when I go to run it I get a internal server error and it wants to load that error file from usr/share. There isn't a make install so I am not sure where to put everything. Wondering if you can help out with a little more specifics

thanks
Brad

Read only on macOS

How to set up to support write for macOS? because now it can read-only.

Include a "Last-Modified" header

I noticed, that a "Last-Modified" header is not provided. Applications can use it for caching or other performance reasons. Would be nice to add it. (I will see if I can have a look at it later)

Self signed SSL certificate not accepted by Windows 10

I have create certificate in my server with this command line :

openssl req -x509 -nodes -days 2730 -newkey rsa:2048 -keyout cert.key -out cert.crt -config req.cnf -sha256

I have put my certificate path in conf file

443
ssl

build/rap
package-with/share

/etc/ssl/private/cert.crt
/etc/ssl/private/cert.key

But in Windows 10 when i put my URL : https://192.168.100.188. It don't work with error "Impossible to open a session in the network".
Nothing logs server side.

It work nice in HTTP.

Thank you for your come back

Default config broken.

Partial work towards locking down the server has broken the default config.

<!-- Not yet supported until multiple servers is implemeted (see <server>
above). Planned to setup a lockdown on the main session -->
<restricted>nobody</restricted>

Because of this, the server cannot even create it's own log file to say whats wrong and a default install simply won't start.

Also, the default SSL settings leave port 443 unable to open and port 80 configured as a simple redirect to port 443.

<listen>
<port>80</port>
<!-- A host tag will bind the server to listen on that IP. Domains will
be convertied to an IP before binding. -->
<!-- <host>myHost.domain.tld</host> -->
<encryption>none</encryption>
<!-- It is NOT recomended to host content on unencrypted chanels. So this
port will just forward to an encrypted one -->
<forward-to>
<port>443</port>
<!-- Forwarding by default forwards to the same domain as the request.
If you want to specify a static domain then set it here -->
<!-- <host>another-domain.tld</host> -->
<!-- Is the client being forwarded to http ("none") or https ("ssl").
The following defaults to "ssl" if fowarding to port 443 and "none" for all
other ports -->
<!-- <encryption>ssl</encryption> -->
</forward-to>
</listen>
<!-- The following will listen on all ips and be encrypted -->
<listen>
<port>443</port>
<!-- Only "none" and "ssl" are currently supported. Encrypting with SSL
requires one or more <ssl-cert> certificates (see below) -->
<encryption>ssl</encryption>
</listen>

<ssl-cert>
<!-- The PEM encoded certificate file -->
<certificate>/etc/ssl/certs/local/server.crt</certificate>
<!-- If the certificate requires intermediary ca certificates then add
as many <chain> nodes as required. These must be added in order starting
with the closest to the <certificate> and finishing with the closest to the
root ca -->
<!-- <chain>/etc/ssl/certs/local/chain_server.crt</chain> -->
<!-- The key for <certificate> -->
<key>/etc/ssl/private/server.key</key>
</ssl-cert>

webdavd crashed

Hello @couling ,

for completeness, I would like to report a webdavd crash. I believe it happened after Microsoft Excel opened a file (from a Win10 machine). Error log:

Aug 16 2021 08:49:22 [2189108] Error: Rejecting request without auth
Aug 16 2021 08:49:22 [2189108] Error: Rejecting request without auth
Aug 16 2021 09:00:25 [2189108] Error: Rejecting request without auth
Aug 16 2021 09:00:25 [2189108] Error: Rejecting request without auth
Aug 16 2021 09:13:50 [2189108] Error: Rejecting request without auth
Aug 16 2021 09:13:51 [2189108] Error: Rejecting request without auth
Aug 16 2021 09:13:51 [2189108] Error: Rejecting request without auth
Aug 16 2021 09:13:51 [2189108] Error: Rejecting request without auth
Aug 16 2021 09:13:59 [2189108] Error: Rejecting request without auth
Aug 16 2021 07:14:00 [2193003] Error: PROPFIND not found stefan /shared/desktop.ini - No such file or directory
Aug 16 2021 07:14:03 [2193017] Error: PROPFIND not found stefan /shared/newfolder/desktop.ini - No such file or directory
Aug 16 2021 07:14:05 [2193019] Error: PROPFIND not found stefan /shared/newfolder/example/desktop.ini - No such file or directory
Aug 16 2021 09:14:11 [2189108] Error: Rejecting request without auth
Aug 16 2021 09:14:11 [2189108] Error: Rejecting request without auth
Aug 16 2021 09:14:11 [2189108] Error: Rejecting request without auth
Aug 16 2021 09:14:12 [2189108] Error: Rejecting request without auth
Aug 16 2021 09:14:20 [2189108] Error: stefan 1778
Aug 16 2021 07:14:20 [2193023] Error: PROPFIND not found stefan /shared/newfolder/example/~$File.ods - No such file or directory
Aug 16 2021 09:15:22 [2189108] Error: stefan 1778
Aug 16 2021 09:16:21 [2189108] Error: Could not receive socket message 16 -1 - Resource temporarily unavailable
Aug 16 2021 07:16:52 [2193017] Error: Could not send socket message - Broken pipe
Aug 16 2021 07:16:52 [2193023] Error: Could not send socket message - Broken pipe

access.log

Aug 16 2021 09:13:50 192.168.0.23 <auth failed> 401 OPTIONS /shared
Aug 16 2021 09:13:51 192.168.0.23 <auth failed> 401 PROPFIND /shared
Aug 16 2021 09:13:51 192.168.0.23 <auth failed> 401 OPTIONS /
Aug 16 2021 09:13:51 192.168.0.23 <auth failed> 401 PROPFIND /
Aug 16 2021 09:13:59 192.168.0.23 <auth failed> 401 PROPFIND /
Aug 16 2021 09:14:00 192.168.0.23 stefan 207 PROPFIND /
Aug 16 2021 09:14:00 192.168.0.23 stefan 207 PROPFIND /
Aug 16 2021 09:14:00 192.168.0.23 stefan 207 PROPFIND /shared
Aug 16 2021 09:14:00 192.168.0.23 stefan 207 PROPFIND /shared
Aug 16 2021 09:14:00 192.168.0.23 stefan 404 PROPFIND /shared/desktop.ini
Aug 16 2021 09:14:03 192.168.0.23 stefan 207 PROPFIND /shared/newfolder
Aug 16 2021 09:14:03 192.168.0.23 stefan 404 PROPFIND /shared/newfolder/desktop.ini
Aug 16 2021 09:14:05 192.168.0.23 stefan 207 PROPFIND /shared/newfolder/example
Aug 16 2021 09:14:05 192.168.0.23 stefan 404 PROPFIND /shared/newfolder/example/desktop.ini
Aug 16 2021 09:14:11 192.168.0.23 <auth failed> 401 OPTIONS /shared/newfolder/
Aug 16 2021 09:14:11 192.168.0.23 <auth failed> 401 OPTIONS /shared/newfolder/
Aug 16 2021 09:14:11 192.168.0.23 <auth failed> 401 OPTIONS /shared/newfolder/
Aug 16 2021 09:14:12 192.168.0.23 <auth failed> 401 OPTIONS /shared/newfolder/
Aug 16 2021 09:14:20 192.168.0.23 stefan 500 OPTIONS /shared/newfolder/
Aug 16 2021 09:14:20 192.168.0.23 stefan 200 GET /shared/newfolder/example/file.ods
Aug 16 2021 09:14:20 192.168.0.23 stefan 207 PROPFIND /shared/newfolder/example/file.ods
Aug 16 2021 09:14:20 192.168.0.23 stefan 200 LOCK /shared/newfolder/example/file.ods
Aug 16 2021 09:14:20 192.168.0.23 stefan 404 PROPFIND /shared/newfolder/example/~$file.ods
Aug 16 2021 09:14:21 192.168.0.23 stefan 201 PUT /shared/newfolder/example/~$file.ods
Aug 16 2021 09:14:21 192.168.0.23 stefan 200 LOCK /shared/newfolder/example/~$file.ods
Aug 16 2021 09:14:21 192.168.0.23 stefan 207 PROPPATCH /shared/newfolder/example/~$file.ods
Aug 16 2021 09:15:22 192.168.0.23 stefan 204 DELETE /shared/newfolder/example/~$file.ods
Aug 16 2021 09:15:23 192.168.0.23 stefan 207 PROPFIND /shared/newfolder/example
Aug 16 2021 09:15:30 192.168.0.23 stefan 200 LOCK /shared/newfolder/example/file.ods
Aug 16 2021 09:16:21 192.168.0.23 stefan 500 PROPFIND /shared/newfolder/example/file.ods

Add support for custom headers

Users might need custom headers. Especially, if you want to allow CORS. For example:
Access-Control-Allow-Origin: 'https://www.example.com'
Access-Control-Allow-Headers: 'cache-control'

This could be included in the server section of the config.xml

Alternatives to this project

I ran across this after trying to solve the same issue in nginx - actually I think I responded to your initial question in the unix stack exchange, which probably spurred this development.

I started working on davt ( https://github.com/lsst-dm/davt, see this file specifically: https://github.com/lsst-dm/davt/blob/ded56645e47e8281dc74ffd36d3c12110dab36a8/davt.lua ) a lua module for use in nginx to aid in implementing impersonation per-request.

I had to make davt flexible enough to take UIDs, GIDs, and potentially a list of GIDs to impersonate a user. I haven't thoroughly tested it yet, but it works fine even with the the async/thread pool implementation of nginx (because file descriptors are done in a single process, where the impersonation happens). Probably a similar approach could be done with apache, I'm not sure.

Volume is read-only with MacOS Finder as client

The issues appears to be that MacOS's finder requires the DAV server to be level 2 with lock support in order to allow write access. Since webdavd reports DAV 1, it will only allow read-only access.

Write access works fine with another client, e.g. cadaver.

Chunked download & upload supported?

Is chunked download & upload supported?

Usually only chunked download is being supported (to e.g. "watch video only from the middle without downloading the first half of it"), but I'd need also chunked upload support (as a prerequisite to resumable uploads).

Could you clarify on both?

broken tls support on Arch Linux

http works well, but https:

$ cadaver https://10.0.1.140:443
....
Username: user
Password:
Could not open collection:
Could not read status line: connection was closed by server

The same with nautilus and dolphin webdav clients.

Distro: ArchLinux

Versions:
webdav-daemon v1.1.r1.bc88ec6-2
libmicrohttpd 0.9.70-3

Config:

<?xml version="1.0" encoding="utf-8" ?>
<server-config xmlns="http://couling.me/webdavd">
	<server>
		<rap-binary>/usr/bin/rap</rap-binary>
		<static-response-dir>/usr/share/webdavd</static-response-dir>
		<chroot-path>~</chroot-path>
		<listen>
			<port>80</port>
			<encryption>none</encryption>
		</listen>
		<listen>
			<port>443</port>
			<encryption>ssl</encryption>
		</listen>
		<ssl-cert>
			<certificate>/etc/letsencrypt/live/.../cert.pem</certificate>
			<key>/etc/letsencrypt/live/.../privkey.pem</key>
		</ssl-cert>
	</server>
</server-config>

Compliance class 2

As of PR #21 (later than version 1.1) WebDAV Daemon will report itself as compliance levels 1 and 2 instead of just 1. As far as I'm aware it is not compliant with class 2.

The move to report compliance without actually supporting it correctly was a pragmatic decision to get some clients to interact with the server (see #17 ).

Before the next release this must be fixed. According to RFC 4918 compliance class 2 requires the server MUST:

  • Support the LOCK method
  • The DAV:supportedlock property,
  • The DAV:lockdiscovery property
  • The Time-Out response header
  • The Lock-Token request header.

And SHOULD also support the

  • The Timeout request header
  • The 'owner' XML element.

compile issues with gcc-10 on Debian testing

Hi,

While attempting to compile with gcc-10 on Debian testing I get the following issues:

gcc -O3 -s -Werror -Wall -Wno-pointer-sign  -Wno-unused-result -std=gnu99 -pthread -MMD -o build/webdavd.o webdavd.c -I/usr/include/libxml2 -c
webdavd.c: In function ‘runServer’:
webdavd.c:1962:14: error: assignment to ‘MHD_AccessHandlerCallback’ {aka ‘enum MHD_Result (*)(void *, struct MHD_Connection *, const char *, const char *, const char *, const char *, unsigned int *, void **)’} from incompatible pointer type ‘int (*)(void *, Request *, const char *, const char *, const char *, const char *, size_t *, void **)’ {aka ‘int (*)(void *, struct MHD_Connection *, const char *, const char *, const char *, const char *, unsigned int *, void **)’} [-Werror=incompatible-pointer-types]
 1962 |     callback = &answerForwardToRequest;
      |              ^
webdavd.c:1964:14: error: assignment to ‘MHD_AccessHandlerCallback’ {aka ‘enum MHD_Result (*)(void *, struct MHD_Connection *, const char *, const char *, const char *, const char *, unsigned int *, void **)’} from incompatible pointer type ‘int (*)(void *, Request *, const char *, const char *, const char *, const char *, size_t *, void **)’ {aka ‘int (*)(void *, struct MHD_Connection *, const char *, const char *, const char *, const char *, unsigned int *, void **)’} [-Werror=incompatible-pointer-types]
 1964 |     callback = &answerToRequest;
      |              ^
webdavd.c: In function ‘createRap’:
webdavd.c:416:5: error: array subscript 1 is outside array bounds of ‘int[1]’ [-Werror=array-bounds]
  416 |     stdLogError(errno, "Could not assign new socket (%d) to %d", newSockFd[1],
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  417 |       (int) RAP_CONTROL_SOCKET);
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~
webdavd.c:470:6: note: while referencing ‘socketFd’
  470 |  int socketFd;
      |      ^~~~~~~~
cc1: all warnings being treated as errors
make: *** [makefile:14: build/webdavd.o] Error 1

Guessing gcc-10 is a bit more strict and errors.

Cheers,

Compilation error

webdavd.c:81:2: error: unknown type name ‘gnutls_pcert_st’
gnutls_pcert_st * certs;
^

Is it due to some version mismatch?

Locking problem with propfind and get

I've setup nginx to proxy a virtual host to webdavd on the same host but another port. This works fine with cadaver.
Creating files with macos as the client works, but hangs. I don't know if it's related to the nginx proxy or not, but I think not. As macos needs class 2 support for write access, and webdavd only supports class 1, obviously no one has tested it with macos without a proxy and found it to work.

It appears to work fine through the PUT command which creates the file ok. Then there is a PROPFIND on the newly created file and webdavd doesn't respond.

Here's the logs from nginx:

1.2.3.4 - tpiepho [04/Jun/2021:16:34:35 -0700] "LOCK /davtest/testfile HTTP/1.1" 200 457 "-" "WebDAVFS/3.0.0 (03008000) Darwin/19.6.0 (x86_64)" "-"
1.2.3.4 - tpiepho [04/Jun/2021:16:34:35 -0700] "PUT /davtest/testfile HTTP/1.1" 201 0 "-" "WebDAVFS/3.0.0 (03008000) Darwin/19.6.0 (x86_64)" "-"
2021/06/04 16:35:35 [error] 1776945#0: *443 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 1.2.3.4, server: vhost.server.name, request: "PROPFIND /davtest/testfile HTTP/1.1", upstream: "http://127.0.0.1:30001/davtest/testfile", host: "vhost.server.name"
1.2.3.4 - tpiepho [04/Jun/2021:16:35:35 -0700] "PROPFIND /davtest/testfile HTTP/1.1" 504 167 "-" "WebDAVFS/3.0.0 (03008000) Darwin/19.6.0 (x86_64)" "-"
1.2.3.4 - tpiepho [04/Jun/2021:16:35:35 -0700] "UNLOCK /davtest/testfile HTTP/1.1" 204 0 "-" "WebDAVFS/3.0.0 (03008000) Darwin/19.6.0 (x86_64)" "-"
1.2.3.4 - tpiepho [04/Jun/2021:16:35:35 -0700] "PROPFIND /davtest/testfile HTTP/1.1" 207 460 "-" "WebDAVFS/3.0.0 (03008000) Darwin/19.6.0 (x86_64)" "-"

The key thing to see is that exactly 1 minute after the PUT, which worked with 201 and created the file, the PROPFIND fails with 504, gateway timeout, because webdavd failed to respond. Then there is an UNLOCK, which works, and a PROPFIND of the same file, which works this time and macos, after the 1 minute timeout, is happy.

The log from webdavd:

Jun 04 2021 16:34:35 127.0.0.1 tpiepho 200 LOCK /davtest/testfile
Jun 04 2021 16:34:35 127.0.0.1 tpiepho 201 PUT /davtest/testfile
Jun 04 2021 16:35:35 127.0.0.1 tpiepho 500 UNLOCK /davtest/testfile
Jun 04 2021 16:35:35 127.0.0.1 tpiepho 207 PROPFIND /davtest/testfile
Jun 04 2021 16:35:35 127.0.0.1 tpiepho 207 PROPFIND /davtest/testfile

Notice here that webdavd responded to TWO PROPFINDs after the UNLOCK. The ordering is wrong here, one should be before, one after. Also notice 1st PROPFIND is one minute after the PUT.

I checked with wireshark while this was running, actual sequence was LOCK PUT PROPFIND (one minute delay) UNLOCK PROPFIND.

It seems like what is happening is the PROPFIND on a locked file is blocking until the file is unlocked.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.