Webinterface for password safe "pass" (http://www.passwordstore.org/)
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
7 years ago | |
---|---|---|
apigen | 7 years ago | |
backend | 7 years ago | |
doc | 7 years ago | |
frontend | 7 years ago | |
.gitignore | 7 years ago | |
README.md | 7 years ago | |
apigen.backend.config | 7 years ago | |
apigen.webapi.config | 7 years ago | |
gendocu.sh | 7 years ago | |
webpass-uml.dia | 7 years ago | |
webpass-uml.jpeg | 7 years ago |
README.md
webpass
webpass is a web based frontend for the shell password safe program "pass". It contains a backend implementing an web API and a frontend for browsers.
installation
- checkout code from https://www.seiichiro0185.org/gitlab/andrwe/webpass.git
- configure webserver
- for nginx configuration example using default php-fpm settings see below
- change permissions of data path that webserver-user may write into it
sudo chown http:http data && sudo chmod 770 data
user http;
worker_processes 1;
error_log /tmp/nginx-error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
access_log /tmp/nginx-access.log;
sendfile on;
keepalive_timeout 65;
gzip on;
root /data/git/webpass/backend;
server {
listen 80;
server_name localhost;
location /webpass {
index index.php;
rewrite ^(.*)$ /webpass/index.php last;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
}
API
All API calls have to POST the variable "json" containing the JSON encoded parameters. Every JSON has to contain the login data in format:
{ "login": {"username": "<username>", "password": "<password>"} }
category | method | description | call | params added to URL | POST-params in JSON | Return |
---|---|---|---|---|---|---|
user | add | add a user to password storage | /user/add/ | username | "newlogin": { "password": "password", "admin": false-OR-true} | { "success": true-OR-false, "error": error-code, "error_msg": "error message"} |
user | exists | check if users exist | /user/exists/ | { "success": true-OR-false, "error": error-code, "error_msg": "error message"} | ||
user | ready | check if addition of given user has finished | /user/ready/ | username | { "success": true-OR-false, "error": error-code, "error_msg": "error message"} | |
user | remove | remove given user | /user/remove/ | username | { "success": true-OR-false, "error": error-code, "error_msg": "error message"} | |
user | credCheck | check user credentials | /user/credCheck | { "success": true-OR-false, "error": error-code, "error_msg": "error message"} | ||
user | isAdmin | check whether user is admin or not | /user/isAdmin | { "success": true-OR-false, "error": error-code, "error_msg": "error message"} | ||
user | list | list existing users | /user/list | { "success": true-OR-false, "error": error-code, "error_msg": "error message", "data": { 2: "user1", 3: "user2", ... } } | ||
store | add | add identifier to password store | /store/add | "store": { "category": "category", "identifier": "identifier", "password": "password", [ "force": true-OR-false (default = false) ] } | { "success": true-OR-false, "error": error-code, "error_msg": "error message"} | |
store | add | add category to password store | /store/add | "store": { "category": "category" } | { "success": true-OR-false, "error": error-code, "error_msg": "error message"} | |
store | show | show password of identifier | /store/show | "store": { "category": "category", "identifier": "identifier" } | { "success": true-OR-false, "error": error-code, "error_msg": "error message", "data": {"password"} } | |
store | list | list identifiers in store (category may be omitted to list first level) | /store/list | "store": { "category": "category" } | { "success": true-OR-false, "error": error-code, "error_msg": "error message", "data": [ { "name": "name1", "type": "category", { "name": "name3", "type": "identifier" } ] } | |
store | list | list all identifiers in store (category may be omitted to list first level) | /store/list | "store": { "category": "category", "listall": true } | { "success": true-OR-false, "error": error-code, "error_msg": "error message", "data": [ { "name": "name1", "type": "category", "data": [ { "name": "name2", "type": "identifier" } ] }, { "name": "name3", "type": "identifier" } ] } | |
store | remove | remove category/identifier from password store (either category or identifier have to be given) | /store/remove | "store": { "category": "category", "identifier": "identifier", [ "force": true-OR-false (default = false) ] } | { "success": true-OR-false, "error": error-code, "error_msg": "error message"} | |
store | copy | copy category/identifier within password store | /store/copy | "store": { "category": "category", "identifier": "identifier", "newcategory": "newcategory", "newidentifier": "newidentifier", "force": true-OR-false (default = false) } | { "success": true-OR-false, "error": error-code, "error_msg": "error message"} | |
store | move | move category/identifier within password store | /store/copy | "store": { "category": "category", "identifier": "identifier", "newcategory": "newcategory", "newidentifier": "newidentifier", "force": true-OR-false (default = false) } | { "success": true-OR-false, "error": error-code, "error_msg": "error message"} | |
store | find | find categories/identifiers matching a search string | /store/find | "store": { "search": "searchstring" } | { "success": true-OR-false, "error": error-code, "error_msg": "error message", "data": {"array same as list method"} } |
Error codes
code | message | call |
---|---|---|
0 | (used if "data" is set) | all |
1 | (internal use only if no error occured) | API::processApi(), user/add |
2 | method not found | API::processApi(), WebpassBackend::user(), WebpassBackend::store() |
3 | only admins may do | WebpassBackend::user() |
4 | method not yet implemented | all |
5 | not enough paramters for given method | WebpassBackend::user() |
6 | username or password missing | all |
10 | user does not exist | user/ready, user/credCheck, user/modify, user/remove |
11 | user is ready | user/ready |
12 | initializing user | user/ready |
13 | users found | user/exists |
14 | no users found | user/exists |
15 | user removed | user/remove |
16 | user could not be removed | user/remove |
17 | user initialization started | user/add |
18 | credentials valid | user/credCheck |
19 | credentials invalid | user/credCheck |
20 | user renamed successfully | user/modify->name |
21 | user could not be renamed | user/modify->name |
30 | login data stored successfully | store/add |
31 | login data could not be stored | store/add |
32 | given identifier already exists, "force" needed | store/add |
33 | could not load stored password | store/show |
34 | given category/identifier does not exist | store/list, store/remove, store/copy |
35 | given category is emtpy | store/list |
36 | category is not empty and "force" is not given, skipped | store/remove |
37 | category removed successfully | store/remove |
38 | category could not be removed | store/remove |
39 | identifier removed successfully | store/remove |
40 | identifier could not be removed | store/remove |
41 | either category or identifier has to be given | store/remove, store/copy |
42 | either new category or new identifier has to be given | store/copy |
43 | one or more categories/identifiers already exists in target, "force" needed | store/copy |
44 | login data could not be stored, password missing | store/add |
45 | category/identifier copied successfully | store/copy |
46 | category/identifier could not be copied | store/copy |
47 | category/identifier moved successfully | store/move |
48 | category/identifier could not be moved | store/move |
49 | search string missing | store/find |
50 | path removed successfully | WebpassBackend::_removePath() |
51 | path could not be removed | WebpassBackend::_removePath() |
52 | path moved successfully | WebpassBackend::_movePath() |
53 (unused) | path could not be moved | WebpassBackend::_movePath() |
54 (unused) | path copied successfully | WebpassBackend::_copyPath() |
55 | path could not be copied | WebpassBackend::_copyPath() |
56 (unused) | destination path alredy exists | WebpassBackend::_copyPath(), WebpassBackend::_movePath() |
57 (unused) | source path does not exist | WebpassBackend::_copyPath(), WebpassBackend::_movePath() |
58 | Path does exist | WebpassBackend::_existsPath() |
59 | Path does not exist | WebpassBackend::_existsPath() |
Decisions
- frontend does session handling
- in backend the session data (GPG password) would be cached on the system storing the GPG keys => all persons and systems with access to server may use keys by just reading the cache
- don't implement Git support of "pass"
- if Git is enabled "pass" creates a new commit for every change
- if GPG key is compromised changing the key would not be sufficient as the attacker just has to revert some commits => all passwords have to be changed too
- without Git support the probability of comprised passwords is lower and GPG key change might be enough
- category and identifier are give via POST
- it kind of breaks RESTful but there are to much restrictions if given via URL (e.g. character-set)
TODO
- validation of username based on allowed characters
- validation of store path given by store/*
- general error handling checks
- validation of category and identifier names
Credits
- RESTful API class http://sidelang.blogspot.de/2013/05/create-restful-services-api-in-php.html
- documentation generator apigen http://apigen.org/