async def dagCidSign(self, ipfsop, request): async with self.throttler: try: js = await request.json() if not js or not isinstance(js, dict): return await self.msgError() if not jsonSchemaValidate(js, dagCidSignSchema): raise Exception('Invalid req schema') elixir = js.get('elixir') token = js.get('sessiontoken') if token != self.service._token: raise Exception('Invalid token') cid = None for msg in self.service.elixirs: try: head = msg['snakeoil'][0:64] tail = msg['snakeoil'][64:128] if elixir == head: cid = msg['cids'][0] log.debug(f'Head: {head}: {cid}') break elif elixir == tail: cid = msg['cids'][1] log.debug(f'Tail: {tail}: {cid}') break else: continue except Exception as err: log.debug(f'Error searching elixirs: {err}') continue if not cid: raise Exception('CID not found') if not self.service.cidRequestable(cid): log.debug(f'Asked to sign CID {cid} but not requestable') raise Exception('CID not requestable') except Exception as err: self.message(f'Unauthorized request: {err}') return await self.msgError(status=401) self.message('Received CID sign request for CID: {}'.format(cid)) try: signed = await ipfsop.rsaAgent.pssSign64(cid.encode()) if signed: return web.json_response({cid: {'pss64': signed}}) else: raise Exception('Cannot sign CID') except Exception: return await self.msgError()
async def analyze(self, ipfsop, peerId, dagCid, pubKeyPem): try: log.debug(f'Analyzing DAG: {dagCid} for {peerId}') async with SeedsPortal(dagCid=dagCid) as pdag: if not jsonSchemaValidate(SeedsEDag.schema, pdag.root): log.debug(f'Analyzing DAG: {dagCid}: Schema INVALID') return False else: log.debug(f'Analyzing DAG: {dagCid}: Schema VALID !') await ipfsop.sleep() if not pdag.iterationSig: # Not signed yet return False if not await ipfsop.ctx.rsaExec.pssVerif64( pdag.iterationUid.encode(), pdag.iterationSig.encode(), pubKeyPem): log.debug(f'Analyzing DAG: {dagCid}: SIG WRONG') return False else: log.debug(f'Analyzing DAG: {dagCid}: SIG OK !') # Pin seeds descriptors for sname, section in pdag.root['c']['seeds'].items(): lkeys = [ key for key in section.keys() if not key.startswith('_') ] for key in lkeys: seeds = section[key] for idx, entry in enumerate(seeds): path = f'c/seeds/{sname}/{key}/{idx}/seedlink' resolved = await pdag.resolve(path) if resolved: ensure( ipfsop.pin(resolved, recursive=False, timeout=20)) await ipfsop.sleep() await ipfsop.sleep() except DAGError as dage: log.debug(f'Analyzing DAG: {dagCid}: DAG error {dage}') return False except Exception as err: log.debug(f'Analyzing DAG: {dagCid}: unknown error {err}') return False else: return True
def nsCacheLoad(self): try: assert len(self.cache) == 0 with open(str(self.nsCachePath), 'r') as fd: cache = json.load(fd) if not jsonSchemaValidate(cache, nsCacheSchema): raise Exception('Invalid NS cache schema') except Exception as err: log.debug(f'Error loading NS cache: {err}') else: log.warning(f'IPNS cache: loaded from {self.nsCachePath}') self.cache = cache
async def importYamlHashmarks(self, yamlpath, source): count = 0 try: with open(yamlpath, 'rt') as fd: data = load(fd, Loader=Loader) except Exception as e: log.debug('Error importing {}: {}'.format(yamlpath, str(e))) return False if not jsonSchemaValidate(data, schema): return False for mark in data['hashmarks']: if await importHashmark(mark, source): count += 1 return count
async def updateSourceInfo(self, yamlpath, source): try: with open(yamlpath, 'rt') as fd: data = load(fd, Loader=Loader) except Exception as e: log.debug('Error importing {}: {}'.format(yamlpath, str(e))) else: if not jsonSchemaValidate(data, sourceInfoSchema): return False name = data.get('source_name') author = data.get('source_author') source.name = name source.author = author await source.save() return True
async def authPss(self, ipfsop, request): curProfile = ipfsop.ctx.currentProfile if not curProfile: return await self.msgError() try: js = await request.json() if not js or not isinstance(js, dict): return await self.msgError() if not jsonSchemaValidate(js, authReqSchema): raise Exception('Invalid req schema') except Exception: return await self.msgError() did = js.get('did') if not didIdentRe.match(did): return await self.msgError() self.message( 'Received DID auth challenge request for DID: {}'.format(did)) currentIpid = await curProfile.userInfo.ipIdentifier() if not currentIpid or did != currentIpid.did: # We don't answer to requests for DIDs other than the # one we currently use return await self.msgError(error='Invalid DID') privKey = curProfile._didKeyStore._privateKeyForDid(did) if not privKey: return await self.msgError() try: signed = await self.rsaExecutor.pssSign(js['challenge'].encode(), privKey.exportKey()) if signed: return await self.vcResponse(did, base64.b64encode(signed).decode(), js['nonce']) except Exception: return await self.msgError(error='PSS error')
async def didPing(self, ipfsop, request): async with self.throttler: curProfile = ipfsop.ctx.currentProfile if not curProfile: return await self.msgError() try: js = await request.json() if not js or not isinstance(js, dict): return await self.msgError() if not jsonSchemaValidate(js, pingReqSchema): raise Exception('Invalid req schema') token = js.get('ident_token') if token != self.service._token: self.message(f'didPing: Invalid token {token}') raise Exception('Invalid token') except Exception: return await self.msgError() did = js.get('did') self.message('Received didPing request for DID: {}'.format( did)) currentIpid = await curProfile.userInfo.ipIdentifier() if not currentIpid or did != currentIpid.did: return await self.msgError(error='Invalid DID') return web.json_response({ 'didpong': { 'version': 0, did: { 'userstatus': curProfile.status, 'userstatusmessage': curProfile.statusMessage, 'date': utcDatetimeIso() } } })
def validSchema(self, schema=None): sch = schema if schema else self.__class__.schema return jsonSchemaValidate(self.data, sch)
async def authPss(self, ipfsop, request): async with self.throttler: curProfile = ipfsop.ctx.currentProfile if not curProfile: return await self.msgError() try: js = await request.json() if not js or not isinstance(js, dict): return await self.msgError() if not jsonSchemaValidate(js, authReqSchema): raise Exception('Invalid req schema') # Token not mandatory but soon if 0: token = js.get('ident_token') if token != self.service._token: raise Exception(f'Invalid DIDAuth token {token}') except Exception as err: self.message(f'authPss error: {err}') return await self.msgError(error='Invalid token or schema') did = js.get('did') if not didIdentRe.match(did): return await self.msgError(error=f'Invalid DID: {did}') self.message( f'Received DID auth challenge request for DID: {did}') currentIpid = await curProfile.userInfo.ipIdentifier() if not currentIpid or did != currentIpid.did: # We don't answer to requests for DIDs other than the # one we currently use return await self.msgError(error='Invalid DID') rsaAgent = await currentIpid.rsaAgentGet(ipfsop) if not rsaAgent: return await self.msgError() privKey = await rsaAgent._privateKey() if not privKey: return await self.msgError( error=f'Invalid key for DID: {did}') try: signed = await self.rsaExecutor.pssSign( js['challenge'].encode(), privKey.exportKey() ) if signed: return await self.vcResponse( did, base64.b64encode(signed).decode(), js['nonce'] ) except Exception as err: self.message( f'Error while making VC response for {did}: {err}') return await self.msgError(error='PSS error')