def test_refer_to_temp(): lvs = r''' #_r1: "a"/b/"c" #_r2: #_r1/d/"e"/f ''' with pytest.raises(SemanticError): Checker(compile_lvs(lvs), {}) lvs = r''' #_: _a/b/c/d/e & { b: _a } ''' with pytest.raises(SemanticError): Checker(compile_lvs(lvs), {})
def test_cyclic_reference(): lvs = r''' #rule1: a/#rule2 #rule2: b/#rule1 ''' with pytest.raises(SemanticError): Checker(compile_lvs(lvs), {}) lvs = r''' #rule1: a <= #rule2 #rule2: b <= #rule1 ''' with pytest.raises(SemanticError): Checker(compile_lvs(lvs), {})
def test_redefinition(): lvs = r''' #rule: "a"/b/"c" #rule: d/"e"/f ''' with pytest.raises(SemanticError): Checker(compile_lvs(lvs), {})
def test_missing_definition(): lvs = r''' #rule1: #rule2/a ''' with pytest.raises(SemanticError): Checker(compile_lvs(lvs), {}) lvs = r''' #rule: a/b & { c: b } ''' with pytest.raises(SemanticError): Checker(compile_lvs(lvs), {}) lvs = r''' #rule: a/b & { b: c } ''' with pytest.raises(SemanticError): Checker(compile_lvs(lvs), {}) lvs = r''' #rule1: a <= #rule2 ''' with pytest.raises(SemanticError): Checker(compile_lvs(lvs), {}) lvs = r''' #_: a & { a: $fn() } ''' checker = Checker(compile_lvs(lvs), {}) assert not checker.validate_user_fns()
def test_temp_identifiers(): lvs = r''' #_: "a"/b/"c" #_: d/"e"/f ''' checker = Checker(compile_lvs(lvs), {}) assert checker.validate_user_fns() assert len(list(checker.match('/a/b/c'))) >= 1 assert len(list(checker.match('/e/e/e'))) >= 1 assert len(list(checker.match('/a/e/c'))) >= 2 lvs = r''' #_: a/_/_/b/c & { b: a } ''' checker = Checker(compile_lvs(lvs), {}) assert checker.validate_user_fns() assert len(list(checker.match('/a/a/a/a/a'))) >= 1 assert len(list(checker.match('/x/a/b/x/c'))) >= 1 assert len(list(checker.match('/x/a/b/y/c'))) == 0
def test_complicated_rule(): lvs = r''' #r1: a/b/c & { c: b, c: a, a: "a"|"x" } | { b: "b"|"y" } <= #r2 | #r3 #r2: x/y/z & { x: "xxx" } #r3: x/y/z & { y: "yyy" } ''' checker = Checker(compile_lvs(lvs), {}) assert len(list(checker.match('/a/b/c'))) >= 1 assert len(list(checker.match('/x/y/z'))) >= 1 assert len(list(checker.match('/x/x/x'))) >= 1 assert len(list(checker.match('/a/a/a'))) >= 1 assert len(list(checker.match('/a/c/a'))) == 0 assert len(list(checker.match('/a/x/x'))) == 0 assert checker.check('/a/b/c', '/xxx/yyy/zzz') assert checker.check('/x/y/z', '/xxx/xxx/xxx') assert checker.check('/x/x/x', '/xxx/yyy/zzz') assert checker.check('/a/a/a', '/xxx/xxx/xxx')
def main(): basedir = os.path.dirname(os.path.abspath(sys.argv[0])) tpm_path = os.path.join(basedir, 'privKeys') pib_path = os.path.join(basedir, 'pib.db') keychain = KeychainSqlite3(pib_path, TpmFile(tpm_path)) trust_anchor = keychain['/lvs-test'].default_key().default_cert() print(f'Trust anchor name: {Name.to_str(trust_anchor.name)}') lvs_model = compile_lvs(lvs_text) checker = Checker(lvs_model, DEFAULT_USER_FNS) app = NDNApp(keychain=keychain) validator = lvs_validator(checker, app, trust_anchor.data) async def fetch_interest(article: str): try: name = Name.from_str(f'/lvs-test/article/xinyu/{article}') print(f'Sending Interest {Name.to_str(name)}') data_name, meta_info, content = await app.express_interest( name, must_be_fresh=True, can_be_prefix=True, lifetime=6000, validator=validator) print(f'Received Data Name: {Name.to_str(data_name)}') print(meta_info) print(bytes(content).decode() if content else None) except InterestNack as e: print(f'Nacked with reason={e.reason}') except InterestTimeout: print(f'Timeout') except InterestCanceled: print(f'Canceled') except ValidationFailure: print(f'Data failed to validate') async def ndn_main(): await fetch_interest('hello') await fetch_interest('world') app.shutdown() app.run_forever(ndn_main())
def main(): basedir = os.path.dirname(os.path.abspath(sys.argv[0])) tpm_path = os.path.join(basedir, 'privKeys') pib_path = os.path.join(basedir, 'pib.db') keychain = KeychainSqlite3(pib_path, TpmFile(tpm_path)) trust_anchor = keychain['/lvs-test'].default_key().default_cert() admin_cert = keychain['/lvs-test/admin/ndn'].default_key().default_cert() author_cert = keychain['/lvs-test/author/xinyu'].default_key( ).default_cert() print(f'Trust anchor name: {Name.to_str(trust_anchor.name)}') print(f'Admin name: {Name.to_str(admin_cert.name)}') print(f'Author name: {Name.to_str(author_cert.name)}') lvs_model = compile_lvs(lvs_text) checker = Checker(lvs_model, DEFAULT_USER_FNS) # The following manual checks are listed for demonstration only. # In real implementation they are automatically done root_of_trust = checker.root_of_trust() print(f'LVS model root of trust: {root_of_trust}') print(f'LVS model user functions provided: {checker.validate_user_fns()}') ta_matches = sum((m[0] for m in checker.match(trust_anchor.name)), start=[]) assert len(ta_matches) > 0 assert root_of_trust.issubset(ta_matches) print(f'Trust anchor matches the root of trust: OK') app = NDNApp(keychain=keychain) # Note: This producer example does not use LVS validator at all # Also, the content of keychain is as follows: # /lvs-test # +->* /lvs-test/KEY/%5Cs%F8%B5%D9k%D2%D2 # +->* /lvs-test/KEY/%5Cs%F8%B5%D9k%D2%D2/self/v=1647829075409 # -- # /lvs-test/admin/ndn # +->* /lvs-test/admin/ndn/KEY/z%C7%D2%B0%22%FB%D0%F3 # +-> /lvs-test/admin/ndn/KEY/z%C7%D2%B0%22%FB%D0%F3/self/v=1647828984149 # +->* /lvs-test/admin/ndn/KEY/z%C7%D2%B0%22%FB%D0%F3/lvs-test/v=1647829580626 # -- # * /lvs-test/author/xinyu # +->* /lvs-test/author/xinyu/KEY/%18%F9%A7CP%F6%BD%1B # +-> /lvs-test/author/xinyu/KEY/%18%F9%A7CP%F6%BD%1B/self/v=1647828975217 # +->* /lvs-test/author/xinyu/KEY/%18%F9%A7CP%F6%BD%1B/ndn/v=1647829957196 @app.route('/lvs-test/article/xinyu/hello') def on_interest(name, param, _app_param): print(f'>> I: {Name.to_str(name)}, {param}') content = "Hello,".encode() data_name = name + [Component.from_version(timestamp())] app.put_data(data_name, content=content, freshness_period=10000) print(f'<< D: {Name.to_str(data_name)}') print(f'Content: {content.decode()}') print('') @app.route('/lvs-test/article/xinyu/world') def on_interest(name, param, _app_param): print(f'>> I: {Name.to_str(name)}, {param}') content = "world!".encode() data_name = name + [Component.from_version(timestamp())] app.put_data(data_name, content=content, freshness_period=10000) print(f'<< D: {Name.to_str(data_name)}') print(f'Content: {content.decode()}') print('') @app.route(trust_anchor.name) def on_interest(name, param, _app_param): print(f'>> I: {Name.to_str(name)}, {param}') app.put_raw_packet(trust_anchor.data) print(f'<< D: {Name.to_str(trust_anchor.name)}') print('') @app.route(admin_cert.name) def on_interest(name, param, _app_param): print(f'>> I: {Name.to_str(name)}, {param}') app.put_raw_packet(admin_cert.data) print(f'<< D: {Name.to_str(admin_cert.name)}') print('') @app.route(author_cert.name) def on_interest(name, param, _app_param): print(f'>> I: {Name.to_str(name)}, {param}') app.put_raw_packet(author_cert.data) print(f'<< D: {Name.to_str(author_cert.name)}') print('') print('Start serving ...') app.run_forever()
def test_user_fns(): lvs = r''' #r1: /a/b/c & { b: $eq(a), c: $eq_type("v=0") } ''' checker = Checker(compile_lvs(lvs), DEFAULT_USER_FNS) assert checker.validate_user_fns() assert len(list(checker.match('/a/b/v=1'))) == 0 assert len(list(checker.match('/e/e/v=1'))) == 1 assert len(list(checker.match('/e/e/c'))) == 0 lvs = r''' #r1: /a/b/c & { c: $eq(a, b), c: $eq_type("8=") } ''' checker = Checker(compile_lvs(lvs), DEFAULT_USER_FNS) assert checker.validate_user_fns() assert len(list(checker.match('/a/b/c'))) == 0 assert len(list(checker.match('/v=0/v=0/v=0'))) == 0 assert len(list(checker.match('/e/e/e'))) == 1
def test_signing_suggest(): with TemporaryDirectory() as tmpdirname: pib_file = os.path.join(tmpdirname, 'pib.db') tpm_dir = os.path.join(tmpdirname, 'privKeys') KeychainSqlite3.initialize(pib_file, 'tpm-file', tpm_dir) keychain = KeychainSqlite3(pib_file, TpmFile(tpm_dir)) assert len(keychain) == 0 la_id = keychain.touch_identity('/la') la_cert = la_id.default_key().default_cert().data la_cert_data = parse_certificate(la_cert) la_cert_name = la_cert_data.name la_signer = keychain.get_signer({'cert': la_cert_name}) la_author_id = keychain.touch_identity('/la/author/1') la_author_cert_name, la_author_cert = derive_cert(la_author_id.default_key().name, Component.from_str('la-signer'), la_cert_data.content, la_signer, datetime.utcnow(), 100) keychain.import_cert(la_id.default_key().name, la_author_cert_name, la_author_cert) ny_id = keychain.touch_identity('/ny') ny_cert = ny_id.default_key().default_cert().data ny_cert_data = parse_certificate(ny_cert) ny_cert_name = ny_cert_data.name ny_signer = keychain.get_signer({'cert': ny_cert_name}) ny_author_id = keychain.touch_identity('/ny/author/2') ny_author_cert_name, ny_author_cert = derive_cert(ny_author_id.default_key().name, Component.from_str('ny-signer'), ny_cert_data.content, ny_signer, datetime.utcnow(), 100) keychain.import_cert(ny_id.default_key().name, ny_author_cert_name, ny_author_cert) lvs = r''' #KEY: "KEY"/_/_/_ #article: /"article"/_topic/_ & { _topic: "eco" | "spo" } <= #author #author: /site/"author"/_/#KEY <= #anchor #anchor: /site/#KEY & {site: "la" | "ny" } ''' checker = Checker(compile_lvs(lvs), {}) assert checker.suggest("/article/eco/day1", keychain) == la_author_cert_name assert checker.suggest("/article/life/day1", keychain) is None lvs = r''' #KEY: "KEY"/_/_/_ #LAKEY: "KEY"/_/_signer/_ & { _signer: "la-signer" } #article: /"article"/_topic/_ & { _topic: "eco" | "spo" } <= #author #author: /site/"author"/_/#LAKEY <= #anchor #anchor: /site/#KEY & {site: "la"} ''' checker = Checker(compile_lvs(lvs), {}) assert checker.suggest("/article/eco/day1", keychain) == la_author_cert_name lvs = r''' #KEY: "KEY"/_/_/_version & { _version: $eq_type("v=0") } #article: /"article"/_topic/_ & { _topic: "life" | "fin" } <= #author #author: /site/"author"/_/#KEY & { site: "ny" } <= #anchor #anchor: /site/#KEY & { site: "ny" } ''' checker = Checker(compile_lvs(lvs), DEFAULT_USER_FNS) assert checker.suggest("/article/fin/day1", keychain) == ny_author_cert_name lvs = r''' #KEY: "KEY"/_/_/_version & { _version: $eq_type("v=0") } #NYKEY: "KEY"/_/_signer/_version& { _signer: "ny-signer", _version: $eq_type("v=0")} #article: /"article"/_topic/_ <= #author #author: /site/"author"/_/#NYKEY <= #anchor #anchor: /site/#KEY & {site: "ny"} #site: "ny" ''' checker = Checker(compile_lvs(lvs), DEFAULT_USER_FNS) assert checker.suggest("/article/eco/day1", keychain) == ny_author_cert_name
def test_compile(): lvs = r''' #rule: "a"/b/"c" ''' checker = Checker(compile_lvs(lvs), {}) assert checker.validate_user_fns()
def test_rule_expansion(): lvs = r''' #r1: a/_ #r2: #r1/"c" & { a: "xyz" } ''' checker = Checker(compile_lvs(lvs), {}) assert len(list(checker.match('/xyz/abc/c'))) == 1 assert len(list(checker.match('/a/abc/c'))) == 0 lvs = r''' #r1: a/_ #r2: /"c"/#r1 & { a: "xyz" } ''' checker = Checker(compile_lvs(lvs), {}) assert len(list(checker.match('/c/xyz/abc'))) == 1 assert len(list(checker.match('/c/a/abc'))) == 0 lvs = r''' #r1: a/_ & { a: "a"|"b" } #r2: #r1/_ & { a: "a"|"c" } ''' checker = Checker(compile_lvs(lvs), {}) assert len(list(checker.match('/a/b/c'))) >= 1 assert len(list(checker.match('/b/c/a'))) == 0 assert len(list(checker.match('/c/a/b'))) == 0 assert len(list(checker.match('/a/b'))) >= 1 assert len(list(checker.match('/b/c'))) >= 1 assert len(list(checker.match('/c/a'))) == 0 lvs = r''' #r1: a/_ & { a: "a" } | { a: "b" } #r2: #r1/_ & { a: "a" } | { a: "c" } ''' checker = Checker(compile_lvs(lvs), {}) assert len(list(checker.match('/a/b/c'))) >= 1 assert len(list(checker.match('/b/c/a'))) == 0 assert len(list(checker.match('/c/a/b'))) == 0 assert len(list(checker.match('/a/b'))) >= 1 assert len(list(checker.match('/b/c'))) >= 1 assert len(list(checker.match('/c/a'))) == 0 lvs = r''' #r1: a/_ & { a: "a" } | { a: "b" } #r2: #r1/c & { c: "c" } ''' checker = Checker(compile_lvs(lvs), {}) assert len(list(checker.match('/a/b/c'))) >= 1 assert len(list(checker.match('/b/c/c'))) >= 1 assert len(list(checker.match('/c/a/c'))) == 0 lvs = r''' #r1: a/b & { a: "a" } | { b: "b" } #r2: #r1/c & { c: "c" } ''' checker = Checker(compile_lvs(lvs), {}) assert len(list(checker.match('/a/b/c'))) >= 1 assert len(list(checker.match('/b/b/c'))) >= 1 assert len(list(checker.match('/a/a/c'))) >= 1
def test_named_pattern(): lvs = r''' #r1: a/b/a #r2: #r1/a & { a: "xyz" } ''' checker = Checker(compile_lvs(lvs), {}) assert len(list(checker.match('/xyz/b/xyz/xyz'))) == 1 assert len(list(checker.match('/a/b/a/xyz'))) == 0 assert len(list(checker.match('/a/b/a'))) == 1 assert len(list(checker.match('/a/b/c'))) == 0 lvs = r''' #r1: a/b/a & { a: "abc"|"def" } #r2: #r1/a & { a: "abc" } ''' checker = Checker(compile_lvs(lvs), {}) assert len(list(checker.match('/abc/b/abc/abc'))) == 1 assert len(list(checker.match('/def/b/def/abc'))) == 0 assert len(list(checker.match('/def/b/def/def'))) == 0 assert len(list(checker.match('/abc/b/def'))) == 0 assert len(list(checker.match('/def/b/def'))) == 1 lvs = r''' #r1: a/b/a #r2: /a <= #r1 ''' checker = Checker(compile_lvs(lvs), {}) assert not checker.check('/xyz', '/a/b/a') assert checker.check('/a', '/a/b/a')
def test_temp_pattern(): lvs = r''' #r1: _a/b/_a #r2: #r1/_a & { _a: "xyz" } ''' checker = Checker(compile_lvs(lvs), {}) assert len(list(checker.match('/a/b/c/xyz'))) == 1 assert len(list(checker.match('/a/b/c/d'))) == 0 lvs = r''' #r1: _a/b/_a & { _a: "abc"|"def" } #r2: #r1/_a & { _a: "xyz" } ''' checker = Checker(compile_lvs(lvs), {}) assert len(list(checker.match('/abc/b/abc/xyz'))) == 1 assert len(list(checker.match('/abc/b/xyz/xyz'))) == 0 assert len(list(checker.match('/abc/b/def/xyz'))) == 1 lvs = r''' #r1: _a/b/_a #r2: /_a <= #r1 ''' checker = Checker(compile_lvs(lvs), {}) assert checker.check('/xyz', '/a/b/c')
def test_future_reference(): lvs = r''' #_r1: a/b/c & { a: b } ''' checker = Checker(compile_lvs(lvs), {}) assert not list(checker.match('/a/b/c'))