Authentication from shared items federation token list

main
Bob Mottram 2021-07-25 22:18:38 +01:00
parent f142d9f001
commit 5ce777eb1b
4 changed files with 94 additions and 10 deletions

57
auth.py
View File

@ -89,7 +89,7 @@ def authorizeBasic(baseDir: str, path: str, authHeader: str,
""" """
if ' ' not in authHeader: if ' ' not in authHeader:
if debug: if debug:
print('DEBUG: basic auth - Authorixation header does not ' + print('DEBUG: basic auth - Authorisation header does not ' +
'contain a space character') 'contain a space character')
return False return False
if not hasUsersPath(path): if not hasUsersPath(path):
@ -147,6 +147,61 @@ def authorizeBasic(baseDir: str, path: str, authHeader: str,
return False return False
def authorizeDFC(sharedItemsFederatedDomains: [],
baseDir: str,
callingDomain: str,
authHeader: str,
debug: bool) -> bool:
"""HTTP basic auth for shared item federation
"""
if callingDomain not in sharedItemsFederatedDomains:
if debug:
print(callingDomain +
' is not in the shared items federation list')
return False
if 'Basic ' not in authHeader:
if debug:
print('DEBUG: DFC basic auth - Authorisation header does not ' +
'contain a space character')
return False
base64Str = \
authHeader.split(' ')[1].replace('\n', '').replace('\r', '')
plain = base64.b64decode(base64Str).decode('utf-8')
if ':' not in plain:
if debug:
print('DEBUG: DFC basic auth header does not contain a ":" ' +
'separator for username:password')
return False
basicAuthDomain = plain.split(':')[0]
if basicAuthDomain != callingDomain:
if debug:
print('DEBUG: DFC calling domain does not match ' +
'the one in the Authorization header (' +
basicAuthDomain + ')')
return False
passwordFile = baseDir + '/accounts/sharedItemsFederationTokens'
if not os.path.isfile(passwordFile):
if debug:
print('DEBUG: shared item federation tokens file missing ' +
passwordFile)
return False
providedPassword = plain.split(':')[1]
passfile = open(passwordFile, 'r')
for line in passfile:
if line.startswith(basicAuthDomain + ':'):
storedPassword = \
line.split(':')[1].replace('\n', '').replace('\r', '')
success = _verifyPassword(storedPassword, providedPassword)
if not success:
if debug:
print('DEBUG: DFC password check failed for ' +
basicAuthDomain)
return success
print('DEBUG: DFC did not find credentials for ' + basicAuthDomain +
' in ' + passwordFile)
return False
def storeBasicCredentials(baseDir: str, nickname: str, password: str) -> bool: def storeBasicCredentials(baseDir: str, nickname: str, password: str) -> bool:
"""Stores login credentials to a file """Stores login credentials to a file
""" """

View File

@ -105,6 +105,7 @@ from skills import actorSkillValue
from skills import setActorSkillLevel from skills import setActorSkillLevel
from auth import recordLoginFailure from auth import recordLoginFailure
from auth import authorize from auth import authorize
from auth import authorizeDFC
from auth import createPassword from auth import createPassword
from auth import createBasicAuthHeader from auth import createBasicAuthHeader
from auth import authorizeBasic from auth import authorizeBasic
@ -10671,11 +10672,13 @@ class PubServer(BaseHTTPRequestHandler):
if authorized: if authorized:
catalogAuthorized = True catalogAuthorized = True
else: else:
# basic auth access to catalog # basic auth access to shared items catalog
if self.headers.get('Authorization'): if self.headers.get('Authorization'):
if authorize(self.server.baseDir, self.path, if authorizeDFC(self.server.sharedItemsFederatedDomains,
self.headers['Authorization'], self.server.baseDir,
self.server.debug): callingDomain,
self.headers['Authorization'],
self.server.debug):
catalogAuthorized = True catalogAuthorized = True
# show shared items DFC catalog # show shared items DFC catalog
if self._hasAccept(callingDomain) and catalogAuthorized: if self._hasAccept(callingDomain) and catalogAuthorized:
@ -14808,7 +14811,8 @@ def loadTokens(baseDir: str, tokensDict: {}, tokensLookup: {}) -> None:
break break
def runDaemon(userAgentsBlocked: [], def runDaemon(sharedItemsFederatedDomains: [],
userAgentsBlocked: [],
logLoginFailures: bool, logLoginFailures: bool,
city: str, city: str,
showNodeInfoAccounts: bool, showNodeInfoAccounts: bool,
@ -15067,6 +15071,7 @@ def runDaemon(userAgentsBlocked: [],
httpd.httpPrefix = httpPrefix httpd.httpPrefix = httpPrefix
httpd.debug = debug httpd.debug = debug
httpd.federationList = fedList.copy() httpd.federationList = fedList.copy()
httpd.sharedItemsFederatedDomains = sharedItemsFederatedDomains.copy()
httpd.baseDir = baseDir httpd.baseDir = baseDir
httpd.instanceId = instanceId httpd.instanceId = instanceId
httpd.personCache = {} httpd.personCache = {}

View File

@ -264,6 +264,10 @@ parser.add_argument('--rss', dest='rss', type=str, default=None,
help='Show an rss feed for a given url') help='Show an rss feed for a given url')
parser.add_argument('-f', '--federate', nargs='+', dest='federationList', parser.add_argument('-f', '--federate', nargs='+', dest='federationList',
help='Specify federation list separated by spaces') help='Specify federation list separated by spaces')
parser.add_argument('--federateshares', nargs='+',
dest='sharedItemsFederatedDomains',
help='Specify federation list for shared items, ' +
'separated by spaces')
parser.add_argument("--following", "--followingList", parser.add_argument("--following", "--followingList",
dest='followingList', dest='followingList',
type=str2bool, nargs='?', type=str2bool, nargs='?',
@ -1024,6 +1028,16 @@ else:
if configFederationList: if configFederationList:
federationList = configFederationList federationList = configFederationList
sharedItemsFederatedDomains = []
if args.sharedItemsFederatedDomains:
setConfigParam(baseDir, 'sharedItemsFederatedDomains',
sharedItemsFederatedDomains)
else:
configSharedItemsFederatedDomains = \
getConfigParam(baseDir, 'sharedItemsFederatedDomains')
if configSharedItemsFederatedDomains:
sharedItemsFederatedDomains = configSharedItemsFederatedDomains
proxyType = None proxyType = None
if args.tor or domain.endswith('.onion'): if args.tor or domain.endswith('.onion'):
proxyType = 'tor' proxyType = 'tor'
@ -2142,6 +2156,9 @@ if args.desktop:
if federationList: if federationList:
print('Federating with: ' + str(federationList)) print('Federating with: ' + str(federationList))
if sharedItemsFederatedDomains:
print('Federating shared items with: ' +
str(sharedItemsFederatedDomains))
if args.block: if args.block:
if not nickname: if not nickname:
@ -2657,7 +2674,8 @@ if args.registration:
print('New registrations closed') print('New registrations closed')
if __name__ == "__main__": if __name__ == "__main__":
runDaemon(userAgentsBlocked, runDaemon(sharedItemsFederatedDomains,
userAgentsBlocked,
args.logLoginFailures, args.logLoginFailures,
args.city, args.city,
args.showNodeInfoAccounts, args.showNodeInfoAccounts,

View File

@ -457,6 +457,7 @@ def createServerAlice(path: str, domain: str, port: int,
shutil.rmtree(path) shutil.rmtree(path)
os.mkdir(path) os.mkdir(path)
os.chdir(path) os.chdir(path)
sharedItemsFederatedDomains = []
systemLanguage = 'en' systemLanguage = 'en'
nickname = 'alice' nickname = 'alice'
httpPrefix = 'http' httpPrefix = 'http'
@ -554,7 +555,8 @@ def createServerAlice(path: str, domain: str, port: int,
logLoginFailures = False logLoginFailures = False
userAgentsBlocked = [] userAgentsBlocked = []
print('Server running: Alice') print('Server running: Alice')
runDaemon(userAgentsBlocked, runDaemon(sharedItemsFederatedDomains,
userAgentsBlocked,
logLoginFailures, city, logLoginFailures, city,
showNodeInfoAccounts, showNodeInfoAccounts,
showNodeInfoVersion, showNodeInfoVersion,
@ -585,6 +587,7 @@ def createServerBob(path: str, domain: str, port: int,
shutil.rmtree(path) shutil.rmtree(path)
os.mkdir(path) os.mkdir(path)
os.chdir(path) os.chdir(path)
sharedItemsFederatedDomains = []
systemLanguage = 'en' systemLanguage = 'en'
nickname = 'bob' nickname = 'bob'
httpPrefix = 'http' httpPrefix = 'http'
@ -680,7 +683,8 @@ def createServerBob(path: str, domain: str, port: int,
logLoginFailures = False logLoginFailures = False
userAgentsBlocked = [] userAgentsBlocked = []
print('Server running: Bob') print('Server running: Bob')
runDaemon(userAgentsBlocked, runDaemon(sharedItemsFederatedDomains,
userAgentsBlocked,
logLoginFailures, city, logLoginFailures, city,
showNodeInfoAccounts, showNodeInfoAccounts,
showNodeInfoVersion, showNodeInfoVersion,
@ -710,6 +714,7 @@ def createServerEve(path: str, domain: str, port: int, federationList: [],
shutil.rmtree(path) shutil.rmtree(path)
os.mkdir(path) os.mkdir(path)
os.chdir(path) os.chdir(path)
sharedItemsFederatedDomains = []
nickname = 'eve' nickname = 'eve'
httpPrefix = 'http' httpPrefix = 'http'
proxyType = None proxyType = None
@ -740,7 +745,8 @@ def createServerEve(path: str, domain: str, port: int, federationList: [],
logLoginFailures = False logLoginFailures = False
userAgentsBlocked = [] userAgentsBlocked = []
print('Server running: Eve') print('Server running: Eve')
runDaemon(userAgentsBlocked, runDaemon(sharedItemsFederatedDomains,
userAgentsBlocked,
logLoginFailures, city, logLoginFailures, city,
showNodeInfoAccounts, showNodeInfoAccounts,
showNodeInfoVersion, showNodeInfoVersion,