Add require_user_urlparam config option that makes the ?l=<user> query optional.
This commit is contained in:
parent
c535ae8f1a
commit
adc699aeed
6 changed files with 49 additions and 11 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -1,5 +1,19 @@
|
||||||
# EasyWKS Changelog
|
# EasyWKS Changelog
|
||||||
|
|
||||||
|
<!-- BEGIN RELEASE v0.1.4 -->
|
||||||
|
## Version 0.1.4
|
||||||
|
|
||||||
|
Fix HTTP server, compatibility with older HTTP clients
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
<!-- BEGIN CHANGES 0.1.4 -->
|
||||||
|
- Fix config loading bug in webserver.
|
||||||
|
- Add `require_user_urlparam` config option that makes the `?l=<user>` query optional.
|
||||||
|
<!-- END CHANGES 0.1.4 -->
|
||||||
|
|
||||||
|
<!-- END RELEASE v0.1.4 -->
|
||||||
|
|
||||||
<!-- BEGIN RELEASE v0.1.3 -->
|
<!-- BEGIN RELEASE v0.1.3 -->
|
||||||
## Version 0.1.3
|
## Version 0.1.3
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,9 @@ permit_unsigned_response: false
|
||||||
httpd:
|
httpd:
|
||||||
host: 127.0.0.1
|
host: 127.0.0.1
|
||||||
port: 8080
|
port: 8080
|
||||||
|
# Some older HTTP clients omit the ?l=<userid> query suffix. Set
|
||||||
|
# this to false in order to permit such clients to retrieve keys.
|
||||||
|
#require_user_urlparam: true
|
||||||
|
|
||||||
# Defaults to stdout, supported: stdout, smtp
|
# Defaults to stdout, supported: stdout, smtp
|
||||||
mailing_method: smtp
|
mailing_method: smtp
|
||||||
|
|
|
@ -39,10 +39,21 @@ def _validate_smtp_config(value):
|
||||||
def _validate_httpd_config(value):
|
def _validate_httpd_config(value):
|
||||||
if not isinstance(value, dict):
|
if not isinstance(value, dict):
|
||||||
return f'must be a map, got {type(value)}'
|
return f'must be a map, got {type(value)}'
|
||||||
|
if 'host' in value:
|
||||||
if not isinstance(value['host'], str):
|
if not isinstance(value['host'], str):
|
||||||
return f'host must be a str, got {type(value["host"])}'
|
return f'host must be a str, got {type(value["host"])}'
|
||||||
|
else:
|
||||||
|
value['host'] = 'localhost'
|
||||||
|
if 'port' in value:
|
||||||
if not isinstance(value['port'], int):
|
if not isinstance(value['port'], int):
|
||||||
return f'port must be a int, got {type(value["port"])}'
|
return f'port must be a int, got {type(value["port"])}'
|
||||||
|
else:
|
||||||
|
value['port'] = 8080
|
||||||
|
if 'require_user_urlparam' in value:
|
||||||
|
if not isinstance(value['require_user_urlparam'], bool):
|
||||||
|
return f'port must be a bool, got {type(value["require_user_urlparam"])}'
|
||||||
|
else:
|
||||||
|
value['require_user_urlparam'] = True
|
||||||
|
|
||||||
|
|
||||||
def _validate_lmtpd_config(value):
|
def _validate_lmtpd_config(value):
|
||||||
|
@ -141,7 +152,8 @@ Config = _GlobalConfig(
|
||||||
permit_unsigned_response=_ConfigOption('permit_unsigned_response', bool, False),
|
permit_unsigned_response=_ConfigOption('permit_unsigned_response', bool, False),
|
||||||
httpd=_ConfigOption('httpd', dict, {
|
httpd=_ConfigOption('httpd', dict, {
|
||||||
'host': 'localhost',
|
'host': 'localhost',
|
||||||
'port': 8080
|
'port': 8080,
|
||||||
|
'require_user_urlparam': True
|
||||||
}, validator=_validate_httpd_config),
|
}, validator=_validate_httpd_config),
|
||||||
smtp=_ConfigOption('smtp', dict, {
|
smtp=_ConfigOption('smtp', dict, {
|
||||||
'host': 'localhost',
|
'host': 'localhost',
|
||||||
|
|
|
@ -52,6 +52,12 @@ def read_public_key(domain, user):
|
||||||
return key
|
return key
|
||||||
|
|
||||||
|
|
||||||
|
def read_hashed_public_key(domain, hu):
|
||||||
|
keyfile = os.path.join(Config.working_directory, domain, 'hu', hu)
|
||||||
|
key, _ = PGPKey.from_file(keyfile)
|
||||||
|
return key
|
||||||
|
|
||||||
|
|
||||||
def write_public_key(domain, user, key):
|
def write_public_key(domain, user, key):
|
||||||
hu = hash_user_id(user)
|
hu = hash_user_id(user)
|
||||||
keyfile = os.path.join(Config.working_directory, domain, 'hu', hu)
|
keyfile = os.path.join(Config.working_directory, domain, 'hu', hu)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
from .config import Config
|
from .config import Config
|
||||||
from .files import read_public_key, make_submission_address_file, make_policy_file
|
from .files import read_hashed_public_key, make_submission_address_file, make_policy_file
|
||||||
from .util import hash_user_id
|
from .util import hash_user_id
|
||||||
|
|
||||||
from bottle import get, run, abort, response, request
|
from bottle import get, run, abort, response, request
|
||||||
|
@ -26,12 +26,12 @@ def policy(domain: str):
|
||||||
def hu(domain: str, userhash: str):
|
def hu(domain: str, userhash: str):
|
||||||
if domain not in Config.domains:
|
if domain not in Config.domains:
|
||||||
abort(404, 'Not Found')
|
abort(404, 'Not Found')
|
||||||
|
if Config.httpd['require_user_urlparam']:
|
||||||
userid = request.query.l
|
userid = request.query.l
|
||||||
print(userid, userhash, hash_user_id(userid))
|
|
||||||
if not userid or hash_user_id(userid) != userhash:
|
if not userid or hash_user_id(userid) != userhash:
|
||||||
abort(404, 'Not Found')
|
abort(404, 'Not Found')
|
||||||
try:
|
try:
|
||||||
pubkey = read_public_key(domain, userid)
|
pubkey = read_hashed_public_key(domain, userhash)
|
||||||
response.add_header('Content-Type', 'application/octet-stream')
|
response.add_header('Content-Type', 'application/octet-stream')
|
||||||
return bytes(pubkey)
|
return bytes(pubkey)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
httpd:
|
httpd:
|
||||||
host: "::1"
|
host: "::1"
|
||||||
port: 8080
|
port: 8080
|
||||||
|
# Some older HTTP clients omit the ?l=<userid> query suffix. Set
|
||||||
|
# this to false in order to permit such clients to retrieve keys.
|
||||||
|
#require_user_urlparam: true
|
||||||
|
|
||||||
# Defaults to stdout, supported: stdout, smtp
|
# Defaults to stdout, supported: stdout, smtp
|
||||||
mailing_method: smtp
|
mailing_method: smtp
|
||||||
|
|
Loading…
Reference in a new issue