forked from indymedia/epicyon
Fixing public key lookup
parent
08134954bc
commit
e12f0994cf
35
daemon.py
35
daemon.py
|
@ -16,7 +16,6 @@ from webfinger import webfingerMeta
|
|||
from webfinger import webfingerLookup
|
||||
from webfinger import webfingerHandle
|
||||
from person import personLookup
|
||||
from person import personKeyLookup
|
||||
from person import personOutboxJson
|
||||
from posts import getPersonPubKey
|
||||
from posts import outboxMessageCreateWrap
|
||||
|
@ -24,6 +23,7 @@ from posts import savePostToOutbox
|
|||
from inbox import inboxPermittedMessage
|
||||
from inbox import inboxMessageHasParams
|
||||
from inbox import runInboxQueue
|
||||
from inbox import savePostToInboxQueue
|
||||
from follow import getFollowingFeed
|
||||
from auth import authorize
|
||||
from threads import threadWithTrace
|
||||
|
@ -67,10 +67,10 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.wfile.write("<html><head></head><body><h1>404 Not Found</h1></body></html>".encode('utf-8'))
|
||||
|
||||
def _webfinger(self) -> bool:
|
||||
if self.server.debug:
|
||||
print('DEBUG: WEBFINGER well-known')
|
||||
if not self.path.startswith('/.well-known'):
|
||||
return False
|
||||
if self.server.debug:
|
||||
print('DEBUG: WEBFINGER well-known')
|
||||
|
||||
if self.server.debug:
|
||||
print('DEBUG: WEBFINGER host-meta')
|
||||
|
@ -216,7 +216,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self._set_headers('application/json')
|
||||
self.wfile.write(json.dumps(followers).encode('utf-8'))
|
||||
self.server.GETbusy=False
|
||||
return
|
||||
return
|
||||
# look up a person
|
||||
getPerson = personLookup(self.server.domain,self.path, \
|
||||
self.server.baseDir)
|
||||
|
@ -225,13 +225,6 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.wfile.write(json.dumps(getPerson).encode('utf-8'))
|
||||
self.server.GETbusy=False
|
||||
return
|
||||
personKey = personKeyLookup(self.server.domain,self.path, \
|
||||
self.server.baseDir)
|
||||
if personKey:
|
||||
self._set_headers('text/html; charset=utf-8')
|
||||
self.wfile.write(personKey.encode('utf-8'))
|
||||
self.server.GETbusy=False
|
||||
return
|
||||
# check that a json file was requested
|
||||
if not self.path.endswith('.json'):
|
||||
if self.server.debug:
|
||||
|
@ -366,13 +359,14 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
|
||||
pprint(messageJson)
|
||||
|
||||
if not headers.get('keyId'):
|
||||
if self.server.debug:
|
||||
print('DEBUG: POST to inbox has no keyId in header')
|
||||
self.send_response(403)
|
||||
self.end_headers()
|
||||
self.server.POSTbusy=False
|
||||
return
|
||||
if not self.headers.get('signature'):
|
||||
if 'keyId=' not in self.headers['signature']:
|
||||
if self.server.debug:
|
||||
print('DEBUG: POST to inbox has no keyId in header signature parameter')
|
||||
self.send_response(403)
|
||||
self.end_headers()
|
||||
self.server.POSTbusy=False
|
||||
return
|
||||
|
||||
if self.server.debug:
|
||||
print('DEBUG: POST saving to inbox cache')
|
||||
|
@ -387,11 +381,10 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
cacheFilename = \
|
||||
savePostToInboxQueue(self.server.baseDir, \
|
||||
self.server.httpPrefix, \
|
||||
headers['keyId'], \
|
||||
self.postToNickname, \
|
||||
self.server.domain, \
|
||||
messageJson,
|
||||
self.headers)
|
||||
self.headers['signature'])
|
||||
if cacheFilename:
|
||||
if cacheFilename not in self.server.inboxQueue:
|
||||
self.server.inboxQueue.append(cacheFilename)
|
||||
|
@ -410,7 +403,7 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.POSTbusy=False
|
||||
return
|
||||
|
||||
def runDaemon(domain: str,port=80,httpPrefix='https',fedList=[],useTor=False,debug=False) -> None:
|
||||
def runDaemon(baseDir: str,domain: str,port=80,httpPrefix='https',fedList=[],useTor=False,debug=False) -> None:
|
||||
if len(domain)==0:
|
||||
domain='localhost'
|
||||
if '.' not in domain:
|
||||
|
|
|
@ -133,4 +133,4 @@ if not os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain):
|
|||
print('Creating default admin account '+nickname+'@'+domain)
|
||||
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(baseDir,nickname,domain,port,httpPrefix,True)
|
||||
|
||||
runDaemon(domain,port,httpPrefix,federationList,useTor,debug)
|
||||
runDaemon(baseDir,domain,port,httpPrefix,federationList,useTor,debug)
|
||||
|
|
|
@ -24,7 +24,7 @@ def signPostHeaders(privateKeyPem: str, nickname: str, domain: str, \
|
|||
if port!=80 and port!=443:
|
||||
domain=domain+':'+str(port)
|
||||
|
||||
keyID = httpPrefix+'://'+domain+'/users/'+nickname+'/main-key'
|
||||
keyID = httpPrefix+'://'+domain+'/users/'+nickname+'#main-key'
|
||||
if not messageBodyJson:
|
||||
headers = {'host': domain}
|
||||
else:
|
||||
|
|
24
inbox.py
24
inbox.py
|
@ -18,6 +18,7 @@ from posts import getPersonPubKey
|
|||
from httpsig import verifyPostHeaders
|
||||
from session import createSession
|
||||
from follow import receiveFollowRequest
|
||||
from pprint import pprint
|
||||
|
||||
def inboxMessageHasParams(messageJson: {}) -> bool:
|
||||
"""Checks whether an incoming message contains expected parameters
|
||||
|
@ -58,14 +59,12 @@ def validPublishedDate(published) -> bool:
|
|||
return False
|
||||
return True
|
||||
|
||||
def savePostToInboxQueue(baseDir: str,httpPrefix: str,keyId: str,nickname: str, domain: str,postJson: {},headers: {}) -> str:
|
||||
def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str,postJson: {},headers: str) -> str:
|
||||
"""Saves the give json to the inbox queue for the person
|
||||
keyId specifies the actor sending the post
|
||||
"""
|
||||
if ':' in domain:
|
||||
domain=domain.split(':')[0]
|
||||
if not keyId:
|
||||
return None
|
||||
if not postJson.get('id'):
|
||||
return None
|
||||
postId=postJson['id'].replace('/activity','')
|
||||
|
@ -82,9 +81,8 @@ def savePostToInboxQueue(baseDir: str,httpPrefix: str,keyId: str,nickname: str,
|
|||
return None
|
||||
filename=inboxQueueDir+'/'+postId.replace('/','#')+'.json'
|
||||
|
||||
newBufferItem = {
|
||||
newQueueItem = {
|
||||
'published': published,
|
||||
'keyId': keyid,
|
||||
'headers': headers,
|
||||
'post': postJson,
|
||||
'filename': filename,
|
||||
|
@ -128,7 +126,21 @@ def runInboxQueue(baseDir: str,httpPrefix: str,personCache: {},queue: [],domain:
|
|||
# Try a few times to obtain teh public key
|
||||
pubKey=None
|
||||
for tries in range(5):
|
||||
pubKey=getPersonPubKey(session,queueJson['keyId'],personCache)
|
||||
keyId=None
|
||||
signatureParams=queueJson['headers'].split(',')
|
||||
for signatureItem in signatureParams:
|
||||
if signatureItem.startswith('keyId='):
|
||||
if '"' in signatureItem:
|
||||
keyId=signatureItem.split('"')[1]
|
||||
break
|
||||
if not keyId:
|
||||
if debug:
|
||||
print('DEBUG: No keyId in signature: '+queueJson['headers']['signature'])
|
||||
os.remove(queueFilename)
|
||||
queue.pop(0)
|
||||
continue
|
||||
|
||||
pubKey=getPersonPubKey(session,keyId,personCache,debug)
|
||||
if not pubKey:
|
||||
if debug:
|
||||
print('DEBUG: Retry '+str(tries+1)+' obtaining public key for '+queueJson['keyId'])
|
||||
|
|
29
person.py
29
person.py
|
@ -71,7 +71,7 @@ def createPerson(baseDir: str,nickname: str,domain: str,port: int, \
|
|||
'name': nickname,
|
||||
'outbox': httpPrefix+'://'+domain+'/users/'+nickname+'/outbox',
|
||||
'preferredUsername': ''+nickname,
|
||||
'publicKey': {'id': httpPrefix+'://'+domain+'/users/'+nickname+'/main-key',
|
||||
'publicKey': {'id': httpPrefix+'://'+domain+'/users/'+nickname+'#main-key',
|
||||
'owner': httpPrefix+'://'+domain+'/users/'+nickname,
|
||||
'publicKeyPem': publicKeyPem,
|
||||
'summary': '',
|
||||
|
@ -118,38 +118,13 @@ def validNickname(nickname: str) -> bool:
|
|||
if c in nickname:
|
||||
return False
|
||||
return True
|
||||
|
||||
def personKeyLookup(domain: str,path: str,baseDir: str) -> str:
|
||||
"""Lookup the public key of the person with a given nickname
|
||||
"""
|
||||
if not path.endswith('/main-key'):
|
||||
return None
|
||||
if not path.startswith('/users/'):
|
||||
return None
|
||||
nickname=path.replace('/users/','',1).replace('/main-key','')
|
||||
if not validNickname(nickname):
|
||||
return None
|
||||
if ':' in domain:
|
||||
domain=domain.split(':')[0]
|
||||
handle=nickname.lower()+'@'+domain.lower()
|
||||
filename=baseDir+'/accounts/'+handle.lower()+'.json'
|
||||
if not os.path.isfile(filename):
|
||||
return None
|
||||
personJson={"user": "unknown"}
|
||||
with open(filename, 'r') as fp:
|
||||
personJson=commentjson.load(fp)
|
||||
if personJson.get('publicKey'):
|
||||
if personJson['publicKey'].get('publicKeyPem'):
|
||||
return personJson['publicKey']['publicKeyPem']
|
||||
return None
|
||||
|
||||
def personLookup(domain: str,path: str,baseDir: str) -> {}:
|
||||
"""Lookup the person for an given nickname
|
||||
"""
|
||||
notPersonLookup=['/inbox','/outbox','/outboxarchive', \
|
||||
'/followers','/following','/featured', \
|
||||
'.png','.jpg','.gif','.mpv', \
|
||||
'#main-key','/main-key']
|
||||
'.png','.jpg','.gif','.mpv']
|
||||
for ending in notPersonLookup:
|
||||
if path.endswith(ending):
|
||||
return None
|
||||
|
|
13
posts.py
13
posts.py
|
@ -103,18 +103,27 @@ def getPersonBox(session,wfRequest: {},personCache: {},boxName='inbox') -> (str,
|
|||
|
||||
return personJson[boxName],pubKeyId,pubKey,personId
|
||||
|
||||
def getPersonPubKey(session,personUrl: str,personCache: {}) -> str:
|
||||
def getPersonPubKey(session,personUrl: str,personCache: {},debug: bool) -> str:
|
||||
asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'}
|
||||
if not personUrl:
|
||||
return None
|
||||
personUrl=personUrl.replace('#main-key','')
|
||||
personJson = getPersonFromCache(personUrl,personCache)
|
||||
if not personJson:
|
||||
print('************Obtaining public key for '+personUrl)
|
||||
if debug:
|
||||
print('DEBUG: Obtaining public key for '+personUrl)
|
||||
personJson = getJson(session,personUrl,asHeader,None)
|
||||
pubKey=None
|
||||
if personJson.get('publicKey'):
|
||||
if personJson['publicKey'].get('publicKeyPem'):
|
||||
pubKey=personJson['publicKey']['publicKeyPem']
|
||||
else:
|
||||
if personJson.get('publicKeyPem'):
|
||||
pubKey=personJson['publicKeyPem']
|
||||
|
||||
if not pubKey:
|
||||
if debug:
|
||||
print('DEBUG: Public key not found for '+personUrl)
|
||||
|
||||
storePersonInCache(personUrl,personJson,personCache)
|
||||
return pubKey
|
||||
|
|
6
tests.py
6
tests.py
|
@ -111,7 +111,7 @@ def createServerAlice(path: str,domain: str,port: int,federationList: []):
|
|||
os.mkdir(path)
|
||||
os.chdir(path)
|
||||
nickname='alice'
|
||||
httpPrefix=False
|
||||
httpPrefix='http'
|
||||
useTor=False
|
||||
clientToServer=False
|
||||
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,nickname,domain,port,httpPrefix,True)
|
||||
|
@ -124,7 +124,7 @@ def createServerAlice(path: str,domain: str,port: int,federationList: []):
|
|||
global testServerAliceRunning
|
||||
testServerAliceRunning = True
|
||||
print('Server running: Alice')
|
||||
runDaemon(domain,port,httpPrefix,federationList,useTor,True)
|
||||
runDaemon(path,domain,port,httpPrefix,federationList,useTor,True)
|
||||
|
||||
def createServerBob(path: str,domain: str,port: int,federationList: []):
|
||||
print('Creating test server: Bob on port '+str(port))
|
||||
|
@ -146,7 +146,7 @@ def createServerBob(path: str,domain: str,port: int,federationList: []):
|
|||
global testServerBobRunning
|
||||
testServerBobRunning = True
|
||||
print('Server running: Bob')
|
||||
runDaemon(domain,port,httpPrefix,federationList,useTor,True)
|
||||
runDaemon(path,domain,port,httpPrefix,federationList,useTor,True)
|
||||
|
||||
def testPostMessageBetweenServers():
|
||||
print('Testing sending message from one server to the inbox of another')
|
||||
|
|
Loading…
Reference in New Issue