Skip to content

Instantly share code, notes, and snippets.

@Cube707
Last active July 28, 2022 13:00
Show Gist options
  • Save Cube707/251949ed279238f04fbc029c99376ae7 to your computer and use it in GitHub Desktop.
Save Cube707/251949ed279238f04fbc029c99376ae7 to your computer and use it in GitHub Desktop.
a PHP endpoint to handle KeePass files over https
<?php
/**
* KeePass HTTP Handler
*
* Allows you to use KeePass https://keepass.info/ and
* derivations thereof (keepass2android, etc.)
* with databases on your remote server over HTTP(S).
*
* Theoretically optional, but I recomend you configure BasicAuth on your web server and add a user for yourself.
* Than configure your server to only grant acces to this file to logged in users.
*
* Create your kdbx database files and upload them to the vault_dir as "username.kdbx"
* Klick "open from URL" and set path to `https://your.domain/path/to/kepass.php`.
* Use your basicAuth username and password to authenticate.
* (Username is send to the server and used to find the correct databease file)
*
*
* Use with care and don't get hacked.
*/
/** -----Configuration----- */
/** The kdbx vault directory */
$vault_dir = './keepassVault/';
/** get username and create db name */
$name = $_SERVER['PHP_AUTH_USER'];
$db = $vault_dir . $name . ".kdbx";
/** Handle the VERBS */
switch ($_SERVER['REQUEST_METHOD']):
case 'GET':
/** Check if databases exists */
if (!file_exists($db)) {
http_response_code(404);
exit;
}
/** send file to user */
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . basename($db));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($db));
ob_clean();
flush();
readfile($db);
exit;
case 'PUT':
$dbf = fopen($db . ".tmp", 'wb');
/** Lock and load */
if (flock($dbf, LOCK_EX)) {
fwrite($dbf, file_get_contents('php://input'));
fflush($dbf);
flock($dbf, LOCK_UN);
fclose($dbf);
} else {
/** Could not acquire lock, conflict! */
http_response_code(409);
exit;
}
http_response_code(200);
exit;
case 'DELETE':
/** Check if databases exists */
if (!file_exists($db)) {
http_response_code(404);
exit;
}
/** dont delete, but create backup */
rename($db, substr($db, 0, -5) . '_' . date('Y-m-d_His') . ".kdbx.bak");
http_response_code(200);
exit;
case 'MOVE':
/** Check if temp databases exists */
if (!file_exists($db . ".tmp")) {
http_response_code(404);
exit;
}
rename($db . ".tmp", $db);
http_response_code(200);
exit;
default:
http_response_code(405);
exit;
endswitch;
@Cube707
Copy link
Author

Cube707 commented Jul 27, 2022

This endpoint works with the default KeePass aplication and should also wokr with other applications that offer HTTPS (WebDav) syncronisation.
(for example Keepass2Android)

how it works

KeePass uses a very simple communication protocol. It works like this:

GET -> filename.kdbx  # load the file from the server
# user does stuff...
# ON save:
PUT -> filename.kdbx.tmp  # upload the new version as a temporary file
DELTE -> filename.kdbx  # delete the old file
MOVE -> filename.kdbx.tmp to filename.kdbx  # rename

The php endpoint handles all this and takes the appropriate actions on the server.

How to use

  1. Choose a folder on you webserver and upload keepass.php to it. This will act as you endpoint URL (for example https://example.org/path/to/keepass.php)

  2. configure your werbserver. You need to at least redirect all requests to keepass* to the php file so it handles all requests. I addidtionally recomend you guard the endpoint with BasicAuth.
    If you alos have a apatche-webserver, you can copy my config next to the php file:

    #### Redirect routs:
    RewriteEngine on
    # redirect keepass-temporary files to the php-handler
    RewriteRule ^keepass(.php)?\.tmp$ keepass.php [L]
    # block all requests to the vault
    RewriteRule ^keepassVault(/.*)?$ - [L,R=404]       
    
    ##### KeePass Handler requires login:
    <FilesMatch "keepass(.php)?$">
      AuthType Basic
      AuthName "KeePass Files"
      AuthBasicProvider file
      AuthUserFile users.txt
      Require valid-user
    </FilesMatch>
  3. create a folder keepassVault/ in the same folder.

  4. Configure a username and password for BasicAuth on your server (see here for apache)

  5. upload your keepass-database to the vault-folder, either manually or via curl:

    curl -X PUT --user demo:1234 --data @file.kdbx https://example.com/path/to/keepass
    curl -X MOVE --user demo:1234 https://example.com/path/to/keepass
  6. Use your database in KeePass:

  7. Open KeePass and go to FILE⇾Open⇾Open URL... (CTRL+SHIFT+O)

  8. Input your endpoint URL and the username and password. I recommend setting Remember to Remember username and password, so you only have to input the masterkey each time.
    image

  9. after clicking OK your file will be downloaded and you will be asked for your masterkey as usual.

Gotchas

  • the handler doesn't delete/override existing versions on the server, instead it creates backups each time you save in KeePass and send a new version. You have to clean up yourself so. (I myself have a cron script for that)

  • You obviously need internet-connection for this to work. There for I recommend you use some form of autobackoup to create local copies that you can fall back to when your internet is broken. (I use this plugin)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment