Option to strictly enforce object capabilities

master
Bob Mottram 2019-07-07 18:47:37 +01:00
parent 8c8b48731a
commit b9ebf425b1
4 changed files with 44 additions and 12 deletions

View File

@ -498,7 +498,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.POSTbusy=False self.server.POSTbusy=False
def runDaemon(baseDir: str,domain: str,port=80,httpPrefix='https', \ 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: if len(domain)==0:
domain='localhost' domain='localhost'
if '.' not in domain: if '.' not in domain:
@ -528,6 +529,7 @@ def runDaemon(baseDir: str,domain: str,port=80,httpPrefix='https', \
httpd.inboxQueue=[] httpd.inboxQueue=[]
httpd.sendThreads=[] httpd.sendThreads=[]
httpd.postLog=[] httpd.postLog=[]
httpd.ocapAlways=ocapAlways
print('Running ActivityPub daemon on ' + domain + ' port ' + str(port)) print('Running ActivityPub daemon on ' + domain + ' port ' + str(port))
httpd.thrInboxQueue= \ httpd.thrInboxQueue= \
threadWithTrace(target=runInboxQueue, \ threadWithTrace(target=runInboxQueue, \
@ -535,6 +537,7 @@ def runDaemon(baseDir: str,domain: str,port=80,httpPrefix='https', \
httpd.postLog,httpd.cachedWebfingers, \ httpd.postLog,httpd.cachedWebfingers, \
httpd.personCache,httpd.inboxQueue, \ httpd.personCache,httpd.inboxQueue, \
domain,port,useTor,httpd.federationList, \ domain,port,useTor,httpd.federationList, \
httpd.ocapAlways, \
httpd.ocapGranted,debug),daemon=True) httpd.ocapGranted,debug),daemon=True)
httpd.thrInboxQueue.start() httpd.thrInboxQueue.start()
httpd.serve_forever() httpd.serve_forever()

View File

@ -108,6 +108,9 @@ parser.add_argument("--testsnetwork", type=str2bool, nargs='?', \
parser.add_argument("--testdata", type=str2bool, nargs='?', \ parser.add_argument("--testdata", type=str2bool, nargs='?', \
const=True, default=False, \ const=True, default=False, \
help="Generate some data for testing purposes") 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() args = parser.parse_args()
debug=False debug=False
@ -168,6 +171,9 @@ if args.domain:
if args.port: if args.port:
port=args.port port=args.port
setConfigParam(baseDir,'port',port) setConfigParam(baseDir,'port',port)
ocapAlways=False
if args.ocap:
ocapAlways=args.ocap
httpPrefix='https' httpPrefix='https'
if args.http: if args.http:
httpPrefix='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,"another mystery solved hey",False,True,False,ocapGranted)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"let's go bowling",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)

View File

@ -147,7 +147,7 @@ def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str
commentjson.dump(newQueueItem, fp, indent=4, sort_keys=False) commentjson.dump(newQueueItem, fp, indent=4, sort_keys=False)
return filename 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 """Processes received items and moves them to
the appropriate directories the appropriate directories
""" """
@ -178,6 +178,7 @@ def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cache
queueJson=commentjson.load(fp) queueJson=commentjson.load(fp)
# check that capabilities are accepted # check that capabilities are accepted
capabilitiesPassed=False
if queueJson['post'].get('capabilities'): if queueJson['post'].get('capabilities'):
if queueJson['post']['type']!='Accept': if queueJson['post']['type']!='Accept':
if isinstance(queueJson['post']['capabilities'], dict): if isinstance(queueJson['post']['capabilities'], dict):
@ -230,7 +231,25 @@ def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cache
queueJson['post']['actor']) queueJson['post']['actor'])
os.remove(queueFilename) os.remove(queueFilename)
queue.pop(0) 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 # Try a few times to obtain the public key
pubKey=None pubKey=None

View File

@ -108,7 +108,7 @@ def testThreads():
thr.join() thr.join()
assert thr.isAlive()==False 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)) print('Creating test server: Alice on port '+str(port))
if os.path.isdir(path): if os.path.isdir(path):
shutil.rmtree(path) shutil.rmtree(path)
@ -132,9 +132,9 @@ def createServerAlice(path: str,domain: str,port: int,federationList: [],ocapGra
global testServerAliceRunning global testServerAliceRunning
testServerAliceRunning = True testServerAliceRunning = True
print('Server running: Alice') 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)) print('Creating test server: Bob on port '+str(port))
if os.path.isdir(path): if os.path.isdir(path):
shutil.rmtree(path) shutil.rmtree(path)
@ -158,7 +158,7 @@ def createServerBob(path: str,domain: str,port: int,federationList: [],ocapGrant
global testServerBobRunning global testServerBobRunning
testServerBobRunning = True testServerBobRunning = True
print('Server running: Bob') 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(): def testPostMessageBetweenServers():
print('Testing sending message from one server to the inbox of another') print('Testing sending message from one server to the inbox of another')
@ -178,16 +178,18 @@ def testPostMessageBetweenServers():
shutil.rmtree(baseDir+'/.tests') shutil.rmtree(baseDir+'/.tests')
os.mkdir(baseDir+'/.tests') os.mkdir(baseDir+'/.tests')
ocapAlways=False
# create the servers # create the servers
aliceDir=baseDir+'/.tests/alice' aliceDir=baseDir+'/.tests/alice'
aliceDomain='127.0.0.50' aliceDomain='127.0.0.50'
alicePort=61935 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' bobDir=baseDir+'/.tests/bob'
bobDomain='127.0.0.100' bobDomain='127.0.0.100'
bobPort=61936 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() thrAlice.start()
thrBob.start() thrBob.start()
@ -261,16 +263,18 @@ def testFollowBetweenServers():
shutil.rmtree(baseDir+'/.tests') shutil.rmtree(baseDir+'/.tests')
os.mkdir(baseDir+'/.tests') os.mkdir(baseDir+'/.tests')
ocapAlways=True
# create the servers # create the servers
aliceDir=baseDir+'/.tests/alice' aliceDir=baseDir+'/.tests/alice'
aliceDomain='127.0.0.42' aliceDomain='127.0.0.42'
alicePort=61935 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' bobDir=baseDir+'/.tests/bob'
bobDomain='127.0.0.64' bobDomain='127.0.0.64'
bobPort=61936 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() thrAlice.start()
thrBob.start() thrBob.start()