forked from indymedia/epicyon
Authentication debug
parent
6602d0b78e
commit
c4797d3de2
33
auth.py
33
auth.py
|
@ -49,25 +49,50 @@ def nicknameFromBasicAuth(authHeader: str) -> str:
|
||||||
return None
|
return None
|
||||||
return plain.split(':')[0]
|
return plain.split(':')[0]
|
||||||
|
|
||||||
def authorizeBasic(baseDir: str,authHeader: str) -> bool:
|
def authorizeBasic(baseDir: str,path: str,authHeader: str,debug: bool) -> bool:
|
||||||
"""HTTP basic auth
|
"""HTTP basic auth
|
||||||
"""
|
"""
|
||||||
if ' ' not in authHeader:
|
if ' ' not in authHeader:
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: Authorixation header does not contain a space character')
|
||||||
return False
|
return False
|
||||||
|
if '/users/' not in path:
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: Path for Authorization does not contain a user')
|
||||||
|
return False
|
||||||
|
pathUsersSection=path.split('/users/')[1]
|
||||||
|
if '/' not in pathUsersSection:
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: This is not a users endpoint')
|
||||||
|
return False
|
||||||
|
nicknameFromPath=pathUsersSection.split('/')[0]
|
||||||
base64Str = authHeader.split(' ')[1].replace('\n','')
|
base64Str = authHeader.split(' ')[1].replace('\n','')
|
||||||
plain = base64.b64decode(base64Str).decode('utf-8')
|
plain = base64.b64decode(base64Str).decode('utf-8')
|
||||||
if ':' not in plain:
|
if ':' not in plain:
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: Basic Auth header does not contain a ":" separator for username:password')
|
||||||
return False
|
return False
|
||||||
nickname = plain.split(':')[0]
|
nickname = plain.split(':')[0]
|
||||||
|
if nickname!=nicknameFromPath:
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: Nickname given in the path ('+nicknameFromPath+') does not match the one in the Authorization header ('+nickname+')')
|
||||||
|
return False
|
||||||
passwordFile=baseDir+'/accounts/passwords'
|
passwordFile=baseDir+'/accounts/passwords'
|
||||||
if not os.path.isfile(passwordFile):
|
if not os.path.isfile(passwordFile):
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: passwords file missing')
|
||||||
return False
|
return False
|
||||||
providedPassword = plain.split(':')[1]
|
providedPassword = plain.split(':')[1]
|
||||||
passfile = open(passwordFile, "r")
|
passfile = open(passwordFile, "r")
|
||||||
for line in passfile:
|
for line in passfile:
|
||||||
if line.startswith(nickname+':'):
|
if line.startswith(nickname+':'):
|
||||||
storedPassword=line.split(':')[1].replace('\n','')
|
storedPassword=line.split(':')[1].replace('\n','')
|
||||||
return verifyPassword(storedPassword,providedPassword)
|
success = verifyPassword(storedPassword,providedPassword)
|
||||||
|
if not success:
|
||||||
|
if debug:
|
||||||
|
print('DEBUG: Password check failed for '+nickname)
|
||||||
|
return success
|
||||||
|
print('DEBUG: Did not find credentials for '+nickname+' in '+passwordFile)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def storeBasicCredentials(baseDir: str,nickname: str,password: str) -> bool:
|
def storeBasicCredentials(baseDir: str,nickname: str,password: str) -> bool:
|
||||||
|
@ -100,7 +125,7 @@ def storeBasicCredentials(baseDir: str,nickname: str,password: str) -> bool:
|
||||||
passfile.write(storeStr+'\n')
|
passfile.write(storeStr+'\n')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def authorize(baseDir: str,authHeader: str) -> bool:
|
def authorize(baseDir: str,path: str,authHeader: str,debug: bool) -> bool:
|
||||||
if authHeader.lower().startswith('basic '):
|
if authHeader.lower().startswith('basic '):
|
||||||
return authorizeBasic(baseDir,authHeader)
|
return authorizeBasic(baseDir,path,authHeader,debug)
|
||||||
return False
|
return False
|
||||||
|
|
21
daemon.py
21
daemon.py
|
@ -172,15 +172,18 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
if self.path.endswith('/inbox'):
|
if self.path.endswith('/inbox'):
|
||||||
if '/users/' in self.path:
|
if '/users/' in self.path:
|
||||||
if self.headers.get('Authorization'):
|
if self.headers.get('Authorization'):
|
||||||
nickname=self.path.split('/users/')[1].replace('/inbox','')
|
if authorize(self.server.baseDir,self.path,self.headers['Authorization'],self.server.debug):
|
||||||
if nickname==nicknameFromBasicAuth(self.headers['Authorization']):
|
# TODO
|
||||||
if authorize(self.server.baseDir,self.headers['Authorization']):
|
print('inbox access not supported yet')
|
||||||
# TODO
|
self.send_response(405)
|
||||||
print('inbox access not supported yet')
|
self.end_headers()
|
||||||
self.send_response(405)
|
self.server.POSTbusy=False
|
||||||
self.end_headers()
|
return
|
||||||
self.server.POSTbusy=False
|
else:
|
||||||
return
|
if self.server.debug:
|
||||||
|
print('DEBUG: '+nickname+' was not authorized to access '+self.path)
|
||||||
|
if self.server.debug:
|
||||||
|
print('DEBUG: GET access to inbox is unauthorized')
|
||||||
self.send_response(405)
|
self.send_response(405)
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.server.POSTbusy=False
|
self.server.POSTbusy=False
|
||||||
|
|
|
@ -52,7 +52,7 @@ def createPerson(baseDir: str,nickname: str,domain: str,port: int, \
|
||||||
'value': 'schema:value'}],
|
'value': 'schema:value'}],
|
||||||
'attachment': [],
|
'attachment': [],
|
||||||
'endpoints': {
|
'endpoints': {
|
||||||
'id': httpPrefix+'://'+domain+'/users/'+nickname+'/endpoints'
|
'id': httpPrefix+'://'+domain+'/users/'+nickname+'/endpoints',
|
||||||
'sharedInbox': httpPrefix+'://'+domain+'/inbox',
|
'sharedInbox': httpPrefix+'://'+domain+'/inbox',
|
||||||
'uploadMedia': httpPrefix+'://'+domain+'/users/'+nickname+'/endpoints/uploadMedia'
|
'uploadMedia': httpPrefix+'://'+domain+'/users/'+nickname+'/endpoints/uploadMedia'
|
||||||
},
|
},
|
||||||
|
|
2
posts.py
2
posts.py
|
@ -360,7 +360,7 @@ def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \
|
||||||
savePostToOutbox(baseDir,httpPrefix,newPostId,nickname,domain,newPost)
|
savePostToOutbox(baseDir,httpPrefix,newPostId,nickname,domain,newPost)
|
||||||
return newPost
|
return newPost
|
||||||
|
|
||||||
def outboxMessageCreateWrap(httpPrefix str,nickname: str,domain: str,messageJson: {}) -> {}:
|
def outboxMessageCreateWrap(httpPrefix: str,nickname: str,domain: str,messageJson: {}) -> {}:
|
||||||
"""Wraps a received message in a Create
|
"""Wraps a received message in a Create
|
||||||
https://www.w3.org/TR/activitypub/#object-without-create
|
https://www.w3.org/TR/activitypub/#object-without-create
|
||||||
"""
|
"""
|
||||||
|
|
8
tests.py
8
tests.py
|
@ -318,16 +318,18 @@ def testAuthentication():
|
||||||
|
|
||||||
authHeader=createBasicAuthHeader(nickname,password)
|
authHeader=createBasicAuthHeader(nickname,password)
|
||||||
assert nickname==nicknameFromBasicAuth(authHeader)
|
assert nickname==nicknameFromBasicAuth(authHeader)
|
||||||
assert authorizeBasic(baseDir,authHeader)
|
assert authorizeBasic(baseDir,'/users/'+nickname+'/inbox',authHeader,False)
|
||||||
|
assert authorizeBasic(baseDir,'/users/'+nickname,authHeader,False)==False
|
||||||
|
assert authorizeBasic(baseDir,'/users/othernick/inbox',authHeader,False)==False
|
||||||
|
|
||||||
authHeader=createBasicAuthHeader(nickname,password+'1')
|
authHeader=createBasicAuthHeader(nickname,password+'1')
|
||||||
assert authorizeBasic(baseDir,authHeader)==False
|
assert authorizeBasic(baseDir,'/users/'+nickname+'/inbox',authHeader,False)==False
|
||||||
|
|
||||||
password='someOtherPassword'
|
password='someOtherPassword'
|
||||||
assert storeBasicCredentials(baseDir,nickname,password)
|
assert storeBasicCredentials(baseDir,nickname,password)
|
||||||
|
|
||||||
authHeader=createBasicAuthHeader(nickname,password)
|
authHeader=createBasicAuthHeader(nickname,password)
|
||||||
assert authorizeBasic(baseDir,authHeader)
|
assert authorizeBasic(baseDir,'/users/'+nickname+'/inbox',authHeader,False)
|
||||||
|
|
||||||
os.chdir(currDir)
|
os.chdir(currDir)
|
||||||
shutil.rmtree(baseDir)
|
shutil.rmtree(baseDir)
|
||||||
|
|
Loading…
Reference in New Issue