From b9ebf425b11094325fa7c0985090078caf819590 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 7 Jul 2019 18:47:37 +0100 Subject: [PATCH] Option to strictly enforce object capabilities --- daemon.py | 5 ++++- epicyon.py | 8 +++++++- inbox.py | 23 +++++++++++++++++++++-- tests.py | 20 ++++++++++++-------- 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/daemon.py b/daemon.py index 77a5e0ac..15689a45 100644 --- a/daemon.py +++ b/daemon.py @@ -498,7 +498,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.POSTbusy=False def runDaemon(baseDir: str,domain: str,port=80,httpPrefix='https', \ - fedList=[],ocapGranted={},useTor=False,debug=False) -> None: + fedList=[],ocapAlways=False,ocapGranted={}, \ + useTor=False,debug=False) -> None: if len(domain)==0: domain='localhost' if '.' not in domain: @@ -528,6 +529,7 @@ def runDaemon(baseDir: str,domain: str,port=80,httpPrefix='https', \ httpd.inboxQueue=[] httpd.sendThreads=[] httpd.postLog=[] + httpd.ocapAlways=ocapAlways print('Running ActivityPub daemon on ' + domain + ' port ' + str(port)) httpd.thrInboxQueue= \ threadWithTrace(target=runInboxQueue, \ @@ -535,6 +537,7 @@ def runDaemon(baseDir: str,domain: str,port=80,httpPrefix='https', \ httpd.postLog,httpd.cachedWebfingers, \ httpd.personCache,httpd.inboxQueue, \ domain,port,useTor,httpd.federationList, \ + httpd.ocapAlways, \ httpd.ocapGranted,debug),daemon=True) httpd.thrInboxQueue.start() httpd.serve_forever() diff --git a/epicyon.py b/epicyon.py index 090e20e1..c930faa9 100644 --- a/epicyon.py +++ b/epicyon.py @@ -108,6 +108,9 @@ parser.add_argument("--testsnetwork", type=str2bool, nargs='?', \ parser.add_argument("--testdata", type=str2bool, nargs='?', \ const=True, default=False, \ help="Generate some data for testing purposes") +parser.add_argument("--ocap", type=str2bool, nargs='?', \ + const=True, default=False, \ + help="Always strictly enforce object capabilities") args = parser.parse_args() debug=False @@ -168,6 +171,9 @@ if args.domain: if args.port: port=args.port setConfigParam(baseDir,'port',port) +ocapAlways=False +if args.ocap: + ocapAlways=args.ocap httpPrefix='https' if args.http: httpPrefix='http' @@ -351,4 +357,4 @@ if args.testdata: createPublicPost(baseDir,nickname,domain,port,httpPrefix,"another mystery solved hey",False,True,False,ocapGranted) createPublicPost(baseDir,nickname,domain,port,httpPrefix,"let's go bowling",False,True,False,ocapGranted) -runDaemon(baseDir,domain,port,httpPrefix,federationList,ocapGranted,useTor,debug) +runDaemon(baseDir,domain,port,httpPrefix,federationList,ocapAlways,ocapGranted,useTor,debug) diff --git a/inbox.py b/inbox.py index 39563dec..25355acb 100644 --- a/inbox.py +++ b/inbox.py @@ -147,7 +147,7 @@ def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str commentjson.dump(newQueueItem, fp, indent=4, sort_keys=False) return filename -def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cachedWebfingers: {},personCache: {},queue: [],domain: str,port: int,useTor: bool,federationList: [],ocapGranted: {},debug: bool) -> None: +def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cachedWebfingers: {},personCache: {},queue: [],domain: str,port: int,useTor: bool,federationList: [],ocapAlways: bool,ocapGranted: {},debug: bool) -> None: """Processes received items and moves them to the appropriate directories """ @@ -178,6 +178,7 @@ def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cache queueJson=commentjson.load(fp) # check that capabilities are accepted + capabilitiesPassed=False if queueJson['post'].get('capabilities'): if queueJson['post']['type']!='Accept': if isinstance(queueJson['post']['capabilities'], dict): @@ -230,7 +231,25 @@ def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cache queueJson['post']['actor']) os.remove(queueFilename) queue.pop(0) - continue + continue + if debug: + print('DEBUG: object capabilities check success') + capabilitiesPassed=True + + if ocapAlways and not capabilitiesPassed: + # Allow follow types through + # i.e. anyone can make a follow request + if queueJson['post'].get('type'): + if queueJson['post']['type']=='Follow' or \ + queueJson['post']['type']=='Accept': + capabilitiesPassed=True + if not capabilitiesPassed: + if debug: + print('DEBUG: object capabilities check failed') + pprint(queueJson['post']) + os.remove(queueFilename) + queue.pop(0) + continue # Try a few times to obtain the public key pubKey=None diff --git a/tests.py b/tests.py index 79ff8a6e..432176a8 100644 --- a/tests.py +++ b/tests.py @@ -108,7 +108,7 @@ def testThreads(): thr.join() assert thr.isAlive()==False -def createServerAlice(path: str,domain: str,port: int,federationList: [],ocapGranted: {},hasFollows: bool,hasPosts :bool): +def createServerAlice(path: str,domain: str,port: int,federationList: [],ocapGranted: {},hasFollows: bool,hasPosts :bool,ocapAlways: bool): print('Creating test server: Alice on port '+str(port)) if os.path.isdir(path): shutil.rmtree(path) @@ -132,9 +132,9 @@ def createServerAlice(path: str,domain: str,port: int,federationList: [],ocapGra global testServerAliceRunning testServerAliceRunning = True print('Server running: Alice') - runDaemon(path,domain,port,httpPrefix,federationList,ocapGranted,useTor,True) + runDaemon(path,domain,port,httpPrefix,federationList,ocapAlways,ocapGranted,useTor,True) -def createServerBob(path: str,domain: str,port: int,federationList: [],ocapGranted: {},hasFollows: bool,hasPosts :bool): +def createServerBob(path: str,domain: str,port: int,federationList: [],ocapGranted: {},hasFollows: bool,hasPosts :bool,ocapAlways :bool): print('Creating test server: Bob on port '+str(port)) if os.path.isdir(path): shutil.rmtree(path) @@ -158,7 +158,7 @@ def createServerBob(path: str,domain: str,port: int,federationList: [],ocapGrant global testServerBobRunning testServerBobRunning = True print('Server running: Bob') - runDaemon(path,domain,port,httpPrefix,federationList,ocapGranted,useTor,True) + runDaemon(path,domain,port,httpPrefix,federationList,ocapAlways,ocapGranted,useTor,True) def testPostMessageBetweenServers(): print('Testing sending message from one server to the inbox of another') @@ -178,16 +178,18 @@ def testPostMessageBetweenServers(): shutil.rmtree(baseDir+'/.tests') os.mkdir(baseDir+'/.tests') + ocapAlways=False + # create the servers aliceDir=baseDir+'/.tests/alice' aliceDomain='127.0.0.50' alicePort=61935 - thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList,ocapGranted,True,True),daemon=True) + thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList,ocapGranted,True,True,ocapAlways),daemon=True) bobDir=baseDir+'/.tests/bob' bobDomain='127.0.0.100' bobPort=61936 - thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList,ocapGranted,True,True),daemon=True) + thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList,ocapGranted,True,True,ocapAlways),daemon=True) thrAlice.start() thrBob.start() @@ -261,16 +263,18 @@ def testFollowBetweenServers(): shutil.rmtree(baseDir+'/.tests') os.mkdir(baseDir+'/.tests') + ocapAlways=True + # create the servers aliceDir=baseDir+'/.tests/alice' aliceDomain='127.0.0.42' alicePort=61935 - thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList,ocapGranted,False,False),daemon=True) + thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList,ocapGranted,False,False,ocapAlways),daemon=True) bobDir=baseDir+'/.tests/bob' bobDomain='127.0.0.64' bobPort=61936 - thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList,ocapGranted,False,False),daemon=True) + thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList,ocapGranted,False,False,ocapAlways),daemon=True) thrAlice.start() thrBob.start()