Skip to content

Instantly share code, notes, and snippets.

@aurorabbit
Last active May 26, 2018 19:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aurorabbit/36c509ddeeba2b97c3019534f8dbcce9 to your computer and use it in GitHub Desktop.
Save aurorabbit/36c509ddeeba2b97c3019534f8dbcce9 to your computer and use it in GitHub Desktop.
Example Apache WebDAV Configuration

Example Apache2 WebDAV config

This is an example SQLite schema and httpd.conf for per-share user authentication, using htpasswd for bcrypt.

schema.sql creates the tables for the database.

httpd.conf has an example Apache2 configuration.

add-user.lua is a small script for creating a user and granting them access to the Share with ID 1.

The script breaks when given a password with a single quote ('), however io.popen doesn't allow multiple commands, so the impact is limited to an invalid htpasswd invocation.

CREATE TABLE IF NOT EXISTS Share (
id INTEGER PRIMARY KEY ASC,
name TEXT,
UNIQUE (name)
);
CREATE TABLE IF NOT EXISTS ShareAuth (
Share INTEGER,
User INTEGER,
FOREIGN KEY (Share) REFERENCES Share(id),
FOREIGN KEY (User) REFERENCES User(id),
UNIQUE (Share, User)
);
CREATE TABLE User (
id INTEGER PRIMARY KEY ASC,
username TEXT NOT NULL,
password TEXT NOT NULL,
UNIQUE (username)
);
DBDriver sqlite3
DBDParams /srv/database/auth.db
Alias /share1
<Directory /md0/dav/share1/>
Require dbd-group share1
Options +Indexes
AddDefaultCharset UTF-8
DAV On
AuthType Basic
AuthName "share1 network storage"
AuthBasicProvider dbd
PWQuery "SELECT password FROM User WHERE username = %s"
AuthzDBDQuery "SELECT Share.name FROM ShareAuth JOIN Share ON Share.id = ShareMembership.Share JOIN User ON User.id = ShareMembership.User WHERE username = %s"
</Directory>
sqlite = require('lsqlite3')
db = sqlite.open('db.sqlite')
-- prepare queries
user_query = db:prepare("SELECT COUNT(*) FROM User WHERE username = ?")
user_insert = db:prepare("INSERT INTO User (username, password) VALUES (?, ?)")
-- adds to first share
-- TODO: have an input for this
auth_insert = db:prepare("INSERT INTO ShareAuth (User, Share) VALUES (?, 1)")
-- username input
io.write("Username: ")
local username = io.input():read()
-- check for duplicate username
user_query:bind_values(username)
user_query:step()
if user_query:get_value(0) > 0 then
print(string.format("User exists: %s", username))
os.exit()
end
if user_query:finalize() ~= sqlite.OK then
print("Error checking duplicate username")
os.exit()
end
-- password hashing command
-- WARNING: passwords with a "'" will break the command
local bcrypt = "htpasswd -nbBC 6 '' '%s'"
-- password input
local hash = ""
while string.len(hash) < 60 do
os.execute("stty -echo")
io.write("Password: ")
local password = io.input():read()
print()
io.write("Confirm: ")
local confirm_password = io.input():read()
print()
os.execute("stty echo")
-- length check
if string.len(password) < 8 then
print("Password must be at least 8 characters")
elseif password ~= confirm_password then
print("Password didn't match")
else
-- password hash
local handle = io.popen(string.format(bcrypt, password))
hash = handle:read():sub(2)
end
end
-- insert into User
user_insert:bind_values(username, hash)
user_insert:step()
local user_id = user_insert:last_insert_rowid()
if user_insert:finalize() ~= sqlite.OK then
print("Error creating user")
os.exit()
else
print(string.format("Created user: %s id %u", username, user_id))
end
-- grant share authorization
auth_insert:bind_values(user_id)
auth_insert:step()
if auth_insert:finalize() ~= sqlite.OK then
print("Error giving access to QDrive")
os.exit()
else
print("Granted access to QDrive")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment