2024-02-29 11:03:23 +00:00
|
|
|
__filename__ = "securemode.py"
|
|
|
|
__author__ = "Bob Mottram"
|
|
|
|
__license__ = "AGPL3+"
|
|
|
|
__version__ = "1.5.0"
|
|
|
|
__maintainer__ = "Bob Mottram"
|
|
|
|
__email__ = "bob@libreserver.org"
|
|
|
|
__status__ = "Production"
|
2024-02-29 11:04:05 +00:00
|
|
|
__module_group__ = "Security"
|
2024-02-29 11:03:23 +00:00
|
|
|
|
|
|
|
from httpsig import verify_post_headers
|
|
|
|
from session import establish_session
|
2024-09-13 13:58:14 +00:00
|
|
|
from flags import url_permitted
|
2024-02-29 11:03:23 +00:00
|
|
|
from httpsig import signed_get_key_id
|
|
|
|
from cache import get_person_pub_key
|
|
|
|
|
|
|
|
|
|
|
|
def secure_mode(curr_session, proxy_type: str,
|
|
|
|
force: bool, server, headers: {}, path: str) -> bool:
|
2024-02-29 11:05:11 +00:00
|
|
|
"""http authentication (aka 'authorized fetch') of GET requests for json
|
2024-02-29 11:03:23 +00:00
|
|
|
See AUTHORIZED_FETCH in https://docs.joinmastodon.org/admin/config
|
|
|
|
"""
|
|
|
|
if not server.secure_mode and not force:
|
|
|
|
return True
|
|
|
|
|
|
|
|
key_id = signed_get_key_id(headers, server.debug)
|
|
|
|
if not key_id:
|
|
|
|
if server.debug:
|
|
|
|
print('AUTH: secure mode, ' +
|
|
|
|
'failed to obtain key_id from signature')
|
|
|
|
return False
|
|
|
|
|
|
|
|
# is the key_id (actor) valid?
|
|
|
|
if not url_permitted(key_id, server.federation_list):
|
|
|
|
if server.debug:
|
|
|
|
print('AUTH: Secure mode GET request not permitted: ' + key_id)
|
|
|
|
return False
|
|
|
|
|
|
|
|
if server.onion_domain:
|
|
|
|
if '.onion/' in key_id:
|
|
|
|
curr_session = server.session_onion
|
|
|
|
proxy_type = 'tor'
|
|
|
|
if server.i2p_domain:
|
|
|
|
if '.i2p/' in key_id:
|
|
|
|
curr_session = server.session_i2p
|
|
|
|
proxy_type = 'i2p'
|
|
|
|
|
|
|
|
curr_session = \
|
|
|
|
establish_session("secure mode",
|
|
|
|
curr_session, proxy_type,
|
|
|
|
server)
|
|
|
|
if not curr_session:
|
|
|
|
return False
|
|
|
|
|
|
|
|
# obtain the public key. key_id is the actor
|
|
|
|
pub_key = \
|
|
|
|
get_person_pub_key(server.base_dir,
|
|
|
|
curr_session, key_id,
|
|
|
|
server.person_cache, server.debug,
|
|
|
|
server.project_version,
|
|
|
|
server.http_prefix,
|
|
|
|
server.domain,
|
|
|
|
server.onion_domain,
|
|
|
|
server.i2p_domain,
|
|
|
|
server.signing_priv_key_pem)
|
|
|
|
if not pub_key:
|
|
|
|
if server.debug:
|
|
|
|
print('AUTH: secure mode failed to ' +
|
|
|
|
'obtain public key for ' + key_id)
|
|
|
|
return False
|
|
|
|
|
|
|
|
# was an error http code returned?
|
|
|
|
if isinstance(pub_key, dict):
|
|
|
|
if server.debug:
|
|
|
|
print('AUTH: failed to ' +
|
|
|
|
'obtain public key for ' + key_id +
|
|
|
|
' ' + str(pub_key))
|
|
|
|
return False
|
|
|
|
|
|
|
|
# verify the GET request without any digest
|
|
|
|
if verify_post_headers(server.http_prefix,
|
|
|
|
server.domain_full,
|
|
|
|
pub_key, headers,
|
|
|
|
path, True, None, '', server.debug):
|
|
|
|
return True
|
|
|
|
|
|
|
|
if server.debug:
|
|
|
|
print('AUTH: secure mode authorization failed for ' + key_id)
|
|
|
|
return False
|