├── .circleci └── config.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── cmd ├── keyManager │ └── keyManager.go ├── rainsd │ ├── config │ │ ├── server-scion.conf │ │ └── server-tcp.conf │ ├── data │ │ ├── cert │ │ │ ├── server.crt │ │ │ └── server.key │ │ ├── config │ │ │ ├── server-scion.conf │ │ │ └── server-tcp.conf │ │ └── keys │ │ │ └── rootDelegationAssertion.gob │ └── rainsd.go ├── rdig │ └── rdig.go └── zonepub │ └── zonepub.go ├── docs ├── DESIGN-NOTES.md ├── cache-design │ ├── DESIGN-ASSERTION-CACHE.md │ ├── DESIGN-CONNECTION-CAPABILITY.md │ ├── DESIGN-KEY-CACHES.md │ ├── DESIGN-NEG-CACHE.md │ ├── DESIGN-PENDING-KEY-CACHE.md │ └── DESIGN-PENDING-QUERY-CACHE.md ├── components-overview.md ├── man │ ├── keyManager.md │ ├── rainsd.md │ ├── rdig.md │ └── zpub.md ├── rains-server-design.md └── zonefile-format.md ├── go.mod ├── go.sum ├── internal └── pkg │ ├── algorithmTypes │ ├── algorithmTypes.go │ ├── hash_jsonenums.go │ ├── hash_string.go │ ├── signature_jsonenums.go │ └── signature_string.go │ ├── cache │ ├── assertionCache.go │ ├── assertionCache_test.go │ ├── cache_test.go │ ├── capabilityCache.go │ ├── capabilityCache_test.go │ ├── connectionCache.go │ ├── connectionCache_test.go │ ├── interfaces.go │ ├── negAssertionCache.go │ ├── negAssertionCache_test.go │ ├── pendingKeyCache.go │ ├── pendingKeyCache_test.go │ ├── pendingQueryCache.go │ ├── pendingQueryCache_test.go │ ├── zoneKeyCache.go │ └── zoneKeyCache_test.go │ ├── cbor │ └── cbor.go │ ├── connection │ ├── connection.go │ ├── scion │ │ ├── appnet.go │ │ └── path_selection.go │ ├── type_jsonenums.go │ └── type_string.go │ ├── datastructures │ ├── bitarray │ │ ├── bitarray.go │ │ └── bitarray_test.go │ ├── safeCounter │ │ ├── safeCounter.go │ │ └── safeCounter_test.go │ └── safeHashMap │ │ ├── safeHashMap.go │ │ └── safeHashMap_test.go │ ├── keyManager │ ├── keyManager.go │ ├── keyManager_test.go │ └── testdata │ │ ├── privateKeyTest │ │ ├── test2_sec.pem │ │ └── test_sec.pem │ │ └── publicKeyTest │ │ ├── test2_pub.pem │ │ └── test_pub.pem │ ├── keys │ ├── keys.go │ ├── keyspaceid_jsonenums.go │ └── keyspaceid_string.go │ ├── libresolve │ ├── resolver.go │ └── resolver_test.go │ ├── lruCache │ ├── lruCache.go │ └── lruCache_test.go │ ├── message │ ├── message.go │ ├── message_test.go │ └── testData.go │ ├── object │ ├── certificateusage_string.go │ ├── object.go │ ├── object_test.go │ ├── protocoltype_string.go │ ├── testData.go │ └── type_string.go │ ├── publisher │ ├── README.md │ ├── publisher.go │ ├── publisherConfig.go │ ├── publisherConn.go │ ├── publisherUtil.go │ └── test │ │ ├── malformed.conf │ │ ├── zonePrivate.key │ │ └── zonePrivateWrongSize.key │ ├── query │ ├── option_string.go │ ├── query.go │ └── query_test.go │ ├── rainsd │ ├── assertionEngine.go │ ├── cache.go │ ├── inbox.go │ ├── notification.go │ ├── queryEngine.go │ ├── server.go │ ├── serverConfig.go │ ├── serverUtil.go │ ├── switchboard.go │ └── verify.go │ ├── section │ ├── assertion.go │ ├── assertion_test.go │ ├── bloomfilter.go │ ├── bloomfilter_test.go │ ├── bloomfilteralgo_jsonenums.go │ ├── bloomfilteralgo_string.go │ ├── interfaces.go │ ├── interval.go │ ├── interval_test.go │ ├── notification.go │ ├── notification_test.go │ ├── notificationtype_string.go │ ├── pshard.go │ ├── pshard_test.go │ ├── sections_test.go │ ├── shard.go │ ├── shard_test.go │ ├── testData.go │ ├── util.go │ ├── zone.go │ └── zone_test.go │ ├── siglib │ ├── rainsSiglib.go │ └── rainsSiglib_test.go │ ├── signature │ ├── signature.go │ └── signature_test.go │ ├── token │ ├── token.go │ └── token_test.go │ ├── util │ ├── rainslibUtil.go │ ├── rainslibUtil_test.go │ └── test │ │ └── .keepme │ └── zonefile │ ├── decoder.go │ ├── encoder.go │ ├── encoder_test.go │ ├── test │ ├── newzonefile.txt │ └── zonefile.txt │ ├── zoneFileEncoder.go │ ├── zoneFileEncoder_test.go │ ├── zoneFileIO.go │ ├── zoneFileIOTestData.go │ ├── zoneFileIO_test.go │ ├── zoneFileParser.go │ ├── zoneFileParser.y │ ├── zoneFileWordScanner.go │ └── zoneFileWordScanner_test.go ├── pkg └── rains │ ├── option_string.go │ ├── options.go │ ├── query.go │ ├── type_string.go │ └── types.go ├── rains.graffle └── test └── integration ├── README.md ├── fullCoverageSCION.go ├── fullCoverageSCION_test.go ├── fullCoverageTCP.go ├── fullCoverageTCP_test.go └── testdata ├── cert ├── server.crt └── server.key ├── conf ├── SCIONnamingServerRoot.conf ├── SCIONnamingServerch.conf ├── SCIONnamingServerethz.ch.conf ├── SCIONpublisherRoot.conf ├── SCIONpublisherch.conf ├── SCIONpublisherethz.ch.conf ├── SCIONresolver.conf ├── SCIONresolver2.conf ├── namingServerRoot.conf ├── namingServerch.conf ├── namingServerethz.ch.conf ├── publisherRoot.conf ├── publisherch.conf ├── publisherethz.ch.conf ├── resolver.conf └── resolver2.conf ├── keys ├── ch │ ├── ch_pub.pem │ └── ch_sec.pem └── ethz.ch │ ├── ethz.ch_pub.pem │ └── ethz.ch_sec.pem ├── messages ├── SCIONmessages.txt ├── messages.txt └── messagesAllObjects.txt └── zonefiles ├── SCIONch.txt ├── SCIONethz.ch.txt ├── SCIONroot.txt ├── ch.txt ├── ethz.ch.txt ├── ethz.chAllObjects.txt └── root.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | #IDE 7 | .idea/ 8 | 9 | # Folders 10 | _obj 11 | _test 12 | vendor/*/ 13 | 14 | #Large benchmarking files 15 | *zonefileDeleg1000000 16 | *zonefile1000000 17 | *zonefileDeleg100000 18 | *zonefile100000 19 | 20 | # Architecture specific extensions/prefixes 21 | *.[568vq] 22 | [568vq].out 23 | 24 | *.cgo1.go 25 | *.cgo2.c 26 | _cgo_defun.c 27 | _cgo_gotypes.go 28 | _cgo_export.* 29 | 30 | _testmain.go 31 | 32 | *.exe 33 | *.test 34 | *.prof 35 | *.out 36 | 37 | 38 | #binary of executables 39 | /cmd/keyManager/keyManager 40 | /cmd/rainsd/rainsd 41 | /cmd/rdig/rdig 42 | /cmd/resolve/resolve 43 | /cmd/test/* 44 | /cmd/zoneManager/zoneManager 45 | /cmd/zonepub/zonepub 46 | /build/* 47 | 48 | #test file 49 | /cmd/zonepub/data/newZonefile.txt 50 | internal/pkg/keyManager/testdata/test_pub.pem 51 | internal/pkg/keyManager/testdata/test_sec.pem 52 | internal/pkg/util/test/test.gob 53 | 54 | #test coverage files 55 | *coverage.out 56 | *coverage.html 57 | 58 | #integration test files 59 | *assertionCheckPoint.gob 60 | *negAssertionCheckPoint.gob 61 | *zoneKeyCheckPoint.gob 62 | test/integration/testdata/keys/root/root_pub.pem 63 | test/integration/testdata/keys/root/root_sec.pem 64 | test/integration/testdata/keys/selfSignedRootDelegationAssertion.gob 65 | 66 | #Yacc 67 | /tools/yacc/y.go 68 | /tools/yacc/zoneFileDecoderGenerated.go 69 | /tools/yacc/y.output 70 | /tools/yacc/zonefileParser 71 | 72 | #example 73 | examples/rainsdServer/rainsdServer 74 | examples/test 75 | examples/rainsdServer/data/newZonefile.txt 76 | examples/rainsdServer/keys/rootPrivateKey.txt 77 | examples/rainsdServer/keys/selfSignedRootDelegationAssertion.gob 78 | 79 | 80 | #simulation generated files 81 | cmd/simulation/conf/* 82 | !cmd/simulation/conf/namingServer.conf 83 | !cmd/simulation/conf/publisher.conf 84 | !cmd/simulation/conf/resolver.conf 85 | cmd/simulation/keys/* 86 | cmd/simulation/zonefiles/* 87 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | COMMIT=$(shell git rev-parse HEAD) 2 | BRANCH=$(shell git rev-parse --abbrev-ref HEAD) 3 | HOSTNAME=$(shell hostname -f) 4 | 5 | BUILD_PATH=${PWD}/build/ 6 | 7 | LDFLAGS = -ldflags "-X main.buildinfo_hostname=${HOSTNAME} -X main.buildinfo_commit=${COMMIT} -X main.buildinfo_branch=${BRANCH}" 8 | 9 | all: clean rainsd zonepub rdig keymanager 10 | 11 | clean: 12 | @rm -rf ${BUILD_PATH} 13 | @mkdir ${BUILD_PATH} 14 | 15 | rainsd: vet 16 | @go build ${LDFLAGS} -o ${BUILD_PATH}/rainsd github.com/netsec-ethz/rains/cmd/rainsd 17 | 18 | zonepub: vet 19 | @go build ${LDFLAGS} -o ${BUILD_PATH}/publisher github.com/netsec-ethz/rains/cmd/zonepub 20 | 21 | rdig: vet 22 | @go build ${LDFLAGS} -o ${BUILD_PATH}/rdig github.com/netsec-ethz/rains/cmd/rdig 23 | 24 | keymanager: vet 25 | @go build ${LDFLAGS} -o ${BUILD_PATH}/keymanager github.com/netsec-ethz/rains/cmd/keyManager 26 | 27 | vet: 28 | @go fmt ./... 29 | @go vet ./internal/... 30 | @go vet ./cmd/... 31 | @go vet ./test/... 32 | 33 | generate: internal/pkg/zonefile/zoneFileParser.go go_generate 34 | 35 | internal/pkg/zonefile/zoneFileParser.go: internal/pkg/zonefile/zoneFileParser.y 36 | $(if $(which goyacc), go install golang.org/x/tools/cmd/goyacc) 37 | @goyacc -p "ZFP" -o $@ $< 38 | 39 | go_generate: 40 | $(if $(which stringer), go install golang.org/x/tools/cmd/stringer) 41 | # XXX: not running github.com/campoy/jsonenums as its currently broken with modules! 42 | @go generate -run stringer ./... 43 | 44 | test: vet unit integration 45 | 46 | unit: 47 | @go test ./internal/pkg/... 48 | 49 | integration: rainsd rdig zonepub 50 | @go test -tags=integration ./test/integration/ 51 | 52 | cover: 53 | @go test -coverprofile=coverage.out -coverpkg=./internal/pkg/... ./internal/pkg/... ./test/... 54 | @go tool cover -html=coverage.out -o coverage.html 55 | firefox coverage.html 56 | 57 | .PHONY: all clean rainsd zonepub rdig zoneman keymanager vet generate go_generate test unit integration 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RAINS, Another Internet Naming Service 2 | 3 | This repository contains a reference implementation of a RAINS server, 4 | supporting authority, intermediary, and query service, as well as associated 5 | tools for managing the server. It has the following executables: 6 | 7 | - `rainsd`: A configurable RAINS server 8 | - `rdig`: A command-line tool for querying RAINS servers 9 | - `zonepub`: A command-line tool for a naming authority to publish information 10 | about its zone(s) to its authoritative RAINS servers 11 | - `keyManager`: A command-line tool for a naming authority to manage its 12 | key pairs 13 | 14 | In addition to this there is a resolver in `libresolve` which either forwards 15 | a query to a RAINS server to resolve it or performs a recursive lookup itself 16 | on the callers behalf before sending the received answer back to the caller. 17 | 18 | 19 | ## Understanding RAINS 20 | 21 | The RAINS implementation is based on the RAINS protocol specified in the 22 | [Internet draft](https://tools.ietf.org/html/draft-trammell-rains-protocol-05). 23 | The different components necessary to run 24 | a RAINS infrastructure are described [here](docs/components-overview.md). 25 | The design of this RAINS server is explained [here](docs/rains-server-design.md) and 26 | the [cache folder](docs/cache-design) contains design decisions for all caches. The 27 | zonefile format, designed to be conveniently readable by a human, is defined in 28 | backus normal form [here](docs/zonefile-format.md). Each command line tool has a help 29 | page which explains all commands and flags that are supported. 30 | 31 | ## Installing and using RAINS 32 | 33 | ### On your machine 34 | 35 | 1. Make sure that you are using a clean and recently updated Ubuntu 16.04. 36 | 1. Download the repo e.g. `git clone https://github.com/netsec-ethz/rains` 37 | 1. Create the necessary binaries by calling [make](Makefile) 38 | 1. Use the binaries created in the cmd [folder](cmd/) 39 | 40 | ### In SCION lab 41 | 42 | TODO 43 | 44 | ## Issues and Test coverage 45 | 46 | The RAINS server and tools are under active development. An up to date 47 | list of issues and bugs can be found [here](https://github.com/netsec-ethz/rains/issues/). 48 | 49 | The server and all tools are tested using unit and integration tests. 50 | A description of the integration test can be found in this [readme](test/integration/README.md) 51 | To inspect the test coverage of all unit tests together with the integration test, 52 | perform the following steps: 53 | 1. go test -coverprofile=coverage.out -coverpkg=./internal/pkg/... ./... 54 | 2. go tool cover -html=coverage.out -o coverage.html 55 | 3. firefox coverage.html 56 | -------------------------------------------------------------------------------- /cmd/rainsd/config/server-scion.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "keys/selfSignedRootDelegationAssertion.gob", 3 | "ServerAddress": { 4 | "Type": "SCION", 5 | "Local": "1-ff00:0:110,[127.0.0.1]:0" 6 | }, 7 | "MaxConnections": 1000, 8 | "KeepAlivePeriod": 60, 9 | "TCPTimeout": 300, 10 | "TLSCertificateFile": "config/server.crt", 11 | "TLSPrivateKeyFile": "config/server.key", 12 | "MaxMsgByteLength": 65536, 13 | "PrioBufferSize": 1000, 14 | "NormalBufferSize": 100000, 15 | "PrioWorkerCount": 2, 16 | "NormalWorkerCount": 10, 17 | "ActiveTokenCacheSize": 1000, 18 | "ZoneKeyCacheSize": 1000, 19 | "ZoneKeyCacheWarnSize": 750, 20 | "MaxPublicKeysPerZone": 5, 21 | "PendingKeyCacheSize": 1000, 22 | "AssertionCacheSize": 10000, 23 | "PendingQueryCacheSize": 100, 24 | "RedirectionCacheSize": 1000, 25 | "RedirectionCacheWarnSize": 750, 26 | "CapabilitiesCacheSize": 50, 27 | "NotificationBufferSize": 20, 28 | "NotificationWorkerCount": 2, 29 | "PeerToCapCacheSize": 1000, 30 | "Capabilities": ["urn:x-rains:tlssrv"], 31 | "InfrastructureKeyCacheSize": 10, 32 | "ExternalKeyCacheSize": 5, 33 | "DelegationQueryValidity": 5, 34 | "NegativeAssertionCacheSize": 500, 35 | "AddressQueryValidity": 5, 36 | "QueryValidity": 5, 37 | "MaxCacheValidity": { 38 | "AssertionValidity": 720, 39 | "ShardValidity": 720, 40 | "ZoneValidity": 720, 41 | "AddressAssertionValidity": 720 42 | }, 43 | "ReapVerifyTimeout": 1800, 44 | "ReapEngineTimeout": 1800, 45 | "ContextAuthority": ["."], 46 | "ZoneAuthority": ["ch."] 47 | } 48 | -------------------------------------------------------------------------------- /cmd/rainsd/config/server-tcp.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "keys/selfSignedRootDelegationAssertion.gob", 3 | "ServerAddress": { 4 | "Type": "TCP", 5 | "TCPAddr": { 6 | "IP": "127.0.0.1", 7 | "Port": 5022, 8 | "Zone": "" 9 | } 10 | }, 11 | "MaxConnections": 1000, 12 | "KeepAlivePeriod": 60, 13 | "TCPTimeout": 300, 14 | "TLSCertificateFile": "config/server.crt", 15 | "TLSPrivateKeyFile": "config/server.key", 16 | "MaxMsgByteLength": 65536, 17 | "PrioBufferSize": 1000, 18 | "NormalBufferSize": 100000, 19 | "PrioWorkerCount": 2, 20 | "NormalWorkerCount": 10, 21 | "ActiveTokenCacheSize": 1000, 22 | "ZoneKeyCacheSize": 1000, 23 | "ZoneKeyCacheWarnSize": 750, 24 | "MaxPublicKeysPerZone": 5, 25 | "PendingKeyCacheSize": 1000, 26 | "AssertionCacheSize": 10000, 27 | "PendingQueryCacheSize": 100, 28 | "RedirectionCacheSize": 1000, 29 | "RedirectionCacheWarnSize": 750, 30 | "CapabilitiesCacheSize": 50, 31 | "NotificationBufferSize": 20, 32 | "NotificationWorkerCount": 2, 33 | "PeerToCapCacheSize": 1000, 34 | "Capabilities": ["urn:x-rains:tlssrv"], 35 | "InfrastructureKeyCacheSize": 10, 36 | "ExternalKeyCacheSize": 5, 37 | "DelegationQueryValidity": 5, 38 | "NegativeAssertionCacheSize": 500, 39 | "AddressQueryValidity": 5, 40 | "QueryValidity": 5, 41 | "MaxCacheValidity": { 42 | "AssertionValidity": 720, 43 | "ShardValidity": 720, 44 | "ZoneValidity": 720, 45 | "AddressAssertionValidity": 720 46 | }, 47 | "ReapVerifyTimeout": 1800, 48 | "ReapEngineTimeout": 1800, 49 | "ContextAuthority": ["."], 50 | "ZoneAuthority": ["ch."] 51 | } 52 | -------------------------------------------------------------------------------- /cmd/rainsd/data/cert/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID5TCCAs2gAwIBAgIJAJGmPmx+xCpcMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYD 3 | VQQGEwJDSDEPMA0GA1UECAwGWnVyaWNoMQ8wDQYDVQQHDAZadXJpY2gxDDAKBgNV 4 | BAoMA0VUSDEPMA0GA1UECwwGTmV0U2VjMQ8wDQYDVQQDDAZzZXJ2ZXIxJzAlBgkq 5 | hkiG9w0BCQEWGGZlaGxtYWNoQHN0dWRlbnQuZXRoei5jaDAeFw0xNzAzMTMxMDE3 6 | MTlaFw0yNzAzMTExMDE3MTlaMIGIMQswCQYDVQQGEwJDSDEPMA0GA1UECAwGWnVy 7 | aWNoMQ8wDQYDVQQHDAZadXJpY2gxDDAKBgNVBAoMA0VUSDEPMA0GA1UECwwGTmV0 8 | U2VjMQ8wDQYDVQQDDAZzZXJ2ZXIxJzAlBgkqhkiG9w0BCQEWGGZlaGxtYWNoQHN0 9 | dWRlbnQuZXRoei5jaDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANaI 10 | rGRyjAKsj7Ma1xwXT7vlB1Bstr60GRQr/QKCr3EadhgXfX4u4SlCnoswVV8X8t9v 11 | Ik8lxozfO/jYrJd/J2YG+cRHlm5dVR2t3cAe+AhhOyMi9tpBcGY9uizeD5sPyGqh 12 | 3ZF4XjqMQyN5N8OANNNCEs87zYfwVDzifR2tYpZdUMKjI0G7WpydSmywKjZq11VE 13 | 8rgd6vOGimLOLZaxS3yA+N2d8L9YAohBAKrhCUaDnqt5Yj092e3QP5hBuyjR+NSd 14 | vCVX/fAMVMkUSD+QpLR8RYEK8ykHCZzWJaNO6vH41KAyZiE34H4rg05booADnF0B 15 | gbDY2ClVV/iwYs0KgIkCAwEAAaNQME4wHQYDVR0OBBYEFAkWeBV9SFceJAxe6J/g 16 | ZeC2fJeZMB8GA1UdIwQYMBaAFAkWeBV9SFceJAxe6J/gZeC2fJeZMAwGA1UdEwQF 17 | MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAGSKwxsOau6GcQEF7La3aoVba3bRanQh 18 | /EJVzSc4GECTgonMFnn3PfzOTTG4iL5FPyLZ9Hu3pJXwP7eyHwR9sGYvvepDhwXA 19 | 0syIuR282H06ByXwl8nIQRjRi1agISEZAyp1Y3iEkEjmCE1PUKAK4qzFvSTSdJJv 20 | tBk5pNPDR/UJwH1kK375cpeFjSH4sw4yIz13fAfrOV2y5n7yN8/dj1pNse7V5vKo 21 | thj2gY5vhK5JpSdRP5Tiwb6nju/zj8AxxVpWlX3I6PeQ+yCTPPVvIBCd1EiJwYyI 22 | y+QQwhgbAkl8kkGwLh5q8TcgFeHzkHcc/nQQdoMRBBnGpjKZ44Egrpg= 23 | -----END CERTIFICATE----- 24 | -------------------------------------------------------------------------------- /cmd/rainsd/data/cert/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA1oisZHKMAqyPsxrXHBdPu+UHUGy2vrQZFCv9AoKvcRp2GBd9 3 | fi7hKUKeizBVXxfy328iTyXGjN87+Nisl38nZgb5xEeWbl1VHa3dwB74CGE7IyL2 4 | 2kFwZj26LN4Pmw/IaqHdkXheOoxDI3k3w4A000ISzzvNh/BUPOJ9Ha1ill1QwqMj 5 | QbtanJ1KbLAqNmrXVUTyuB3q84aKYs4tlrFLfID43Z3wv1gCiEEAquEJRoOeq3li 6 | PT3Z7dA/mEG7KNH41J28JVf98AxUyRRIP5CktHxFgQrzKQcJnNYlo07q8fjUoDJm 7 | ITfgfiuDTluigAOcXQGBsNjYKVVX+LBizQqAiQIDAQABAoIBABCny7qAqh4LB50A 8 | GHM13BraTRcRWZ60nL3ULHBldPly9HgqWrPRL+nkIirsNbSMR27RUfiTFjcZna5U 9 | JBIe7RAeuoViiWtIE7OaK/0eamM8KTsxG7kWG4PUhv+0vcFsGEMvDeSdU7N38D5w 10 | ysOC0JcWKh+spOhI4EFZ1BzZuS2zLIevFqwd4xScW5pbW3cTiuNWEhqPfyu9C06w 11 | g9XEEtmwZWdjLGK0zp8jVdcDQgW5GvlwpXJJGmzvB2DHZTOTPqiUnSg8rnYc9o6M 12 | gETY0YAFn0QYUbPpWX21n9YRNks9xLFRum91JlcFlPQbA7+yv6eLqYC3/Hnbcgfk 13 | E6Le4AECgYEA83Z/S8BGUc0Np93TrhtH+TtJbSHTzzZxtTfZPGY0lhxBjrW/1Mk3 14 | ubIlC9prlDSs3iD19melQC4gLkJqCowihLQgBpyeEElf7KvI65/J5mI1+nUwRhio 15 | 9mm6fhN8Y0pV6ekvlBhHetk9abisyoA5MgE9j70NHt+3SHUBTkE7eqECgYEA4ZTQ 16 | M4VAv21gIJwyVIl5tk8Q++UaHzLOcMDnISzefSLm6CdvoU0Cbnlun8Ps89ASShLI 17 | tb/u54h4TbjsUd8T+Fy0KZ33lCbnV29A9LUOEmem7sinqtandqsaKv+rRDXsLZQS 18 | VGPtsLRuTWygw1WaJWmvxD9k0iaaPgnRHdthZOkCgYEA8X2CerL3jUAl4XJo+3PY 19 | CmFCTduV6x2H4EbLVdvTIWpZpKKm6vvEKI+Jq541w0YUiiiLkKPyCB04kmoSIPAr 20 | dRHuCmDjcCg329vxabaPX9Pe0tXW0lC3l+P7tf7CDQK5AVHpfa4viK1e+zTRP/O7 21 | x9vvIlpVX2BsvpRAfUy7IMECgYA21dDipUK/Bdx3MOD/Mcf3bDLpuKBn8xbBy/Kj 22 | Wt/etWxCBMwa/rhXmIcuqRbhkbPQc858d+KgP8lWw1wW7s5Q8mANOcwkJGzaET5N 23 | /fEkwjOPGhG/8pwUubULvMiqNR1rWvI1t3DhIospoP1XXmixLYa/gtWETEP0TriZ 24 | tGlxeQKBgEJ9m4lyJMbnZr6+dMhd1DTPwXspHbb8HMgSOwoVc5OVPFK4lEHWgu1Y 25 | cXT6frGOT8Ndp2ehiZehQSkwQSfYpSWZ9iyzcTxXPj2/tTF37rUSZv0ZmxM3Vapr 26 | G89AZsRJXcr43Nn9JdL060Scw3n/HiTiGT0Tm1nu6ntkXUlkpFt5 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /cmd/rainsd/data/config/server-scion.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "data/keys/rootDelegationAssertion.gob", 3 | "AssertionCheckPointInterval": 3600, 4 | "NegAssertionCheckPointInterval":3600, 5 | "ZoneKeyCheckPointInterval":3600, 6 | "CheckPointPath": "data/checkpoint/resolver/", 7 | "PreLoadCaches": false, 8 | "ServerAddress": { 9 | "Type": "SCION", 10 | "SCIONAddr": "1-ff00:0:110,[127.0.0.1]:0" 11 | }, 12 | "MaxConnections": 1000, 13 | "KeepAlivePeriod": 60, 14 | "TCPTimeout": 300, 15 | "TLSCertificateFile": "data/cert/server.crt", 16 | "TLSPrivateKeyFile": "data/cert/server.key", 17 | "PrioBufferSize": 1000, 18 | "NormalBufferSize": 100000, 19 | "PrioWorkerCount": 2, 20 | "NormalWorkerCount": 10, 21 | "ZoneKeyCacheSize": 1000, 22 | "ZoneKeyCacheWarnSize": 750, 23 | "MaxPublicKeysPerZone": 5, 24 | "PendingKeyCacheSize": 1000, 25 | "AssertionCacheSize": 10000, 26 | "PendingQueryCacheSize": 100, 27 | "CapabilitiesCacheSize": 50, 28 | "NotificationBufferSize": 20, 29 | "NotificationWorkerCount": 2, 30 | "Capabilities": ["urn:x-rains:tlssrv"], 31 | "DelegationQueryValidity": 5, 32 | "NegativeAssertionCacheSize": 500, 33 | "QueryValidity": 5, 34 | "MaxCacheValidity": { 35 | "AssertionValidity": 720, 36 | "ShardValidity": 720, 37 | "PshardValidity": 720, 38 | "ZoneValidity": 720 39 | }, 40 | "ContextAuthority": ["."], 41 | "ZoneAuthority": ["ch."] 42 | } 43 | -------------------------------------------------------------------------------- /cmd/rainsd/data/config/server-tcp.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "data/keys/rootDelegationAssertion.gob", 3 | "AssertionCheckPointInterval": 3600, 4 | "NegAssertionCheckPointInterval":3600, 5 | "ZoneKeyCheckPointInterval":3600, 6 | "CheckPointPath": "data/checkpoint/resolver/", 7 | "PreLoadCaches": false, 8 | "ServerAddress": { 9 | "Type": "TCP", 10 | "TCPAddr": { 11 | "IP": "127.0.0.1", 12 | "Port": 5022, 13 | "Zone": "" 14 | } 15 | }, 16 | "MaxConnections": 1000, 17 | "KeepAlivePeriod": 60, 18 | "TCPTimeout": 300, 19 | "TLSCertificateFile": "data/cert/server.crt", 20 | "TLSPrivateKeyFile": "data/cert/server.key", 21 | "PrioBufferSize": 1000, 22 | "NormalBufferSize": 100000, 23 | "PrioWorkerCount": 2, 24 | "NormalWorkerCount": 10, 25 | "ZoneKeyCacheSize": 1000, 26 | "ZoneKeyCacheWarnSize": 750, 27 | "MaxPublicKeysPerZone": 5, 28 | "PendingKeyCacheSize": 1000, 29 | "AssertionCacheSize": 10000, 30 | "PendingQueryCacheSize": 100, 31 | "CapabilitiesCacheSize": 50, 32 | "NotificationBufferSize": 20, 33 | "NotificationWorkerCount": 2, 34 | "Capabilities": ["urn:x-rains:tlssrv"], 35 | "DelegationQueryValidity": 5, 36 | "NegativeAssertionCacheSize": 500, 37 | "QueryValidity": 5, 38 | "MaxCacheValidity": { 39 | "AssertionValidity": 720, 40 | "ShardValidity": 720, 41 | "PshardValidity": 720, 42 | "ZoneValidity": 720 43 | }, 44 | "ContextAuthority": ["."], 45 | "ZoneAuthority": ["ch."] 46 | } 47 | -------------------------------------------------------------------------------- /cmd/rainsd/data/keys/rootDelegationAssertion.gob: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netsec-ethz/rains/8e9ef27f2403c644ef93a07af1d4ae7c8378811d/cmd/rainsd/data/keys/rootDelegationAssertion.gob -------------------------------------------------------------------------------- /docs/cache-design/DESIGN-ASSERTION-CACHE.md: -------------------------------------------------------------------------------- 1 | # Assertion cache 2 | 3 | ## Cache design decisions 4 | - Assertions over which the server has authority and all delegation assertions are only removed when 5 | they expire. All other assertions are subject to a least recently used policy. 6 | 7 | ## Assertion requirements 8 | - cache has a maximum size which is configurable (to avoid memory exhaustion of the server in case 9 | of an attack). It is not fix size to reduce the number of comparisons needed for checking that the 10 | new assertion is consistent with all already cached entries. 11 | - In case the cache is full the least recently used assertion over which the server has no authority 12 | is removed from the cache. In case the authoritative assertions fill up the cache an error msg 13 | must be logged such that an operator can change the configuration. 14 | - it must provide an insertion function which stores an assertion together with an expiration time 15 | to the cache (expiration time is necessary as we might want to store them for a shorter amount of 16 | time as they are valid. It is not possible to change the value directly as it is protected by the 17 | signature). It must also add this entry to the consistency cache. 18 | - it must provide fast lookup of a set of assertions based on name, type, and zone (if any context 19 | is allowed) or a name, type, zone, and context. A set is returned such that the calling function 20 | can decide which entry it wants to send back according to a policy. Be aware that also expired, 21 | but not yet reaped values are returned in the set. 22 | - it must provide a reap function that removes expired assertions. This function must also remove 23 | the corresponding element in the consistency cache. 24 | - it must provide a removal function which removes all assertions of a specific zone in case this 25 | zone misbehaved or sent inconsistent messages. 26 | - all cache operations must be safe for concurrent access 27 | 28 | ## Assertion implementation 29 | - lru strategy is implemented as a linked list where pointers to the head and tail of the list are 30 | accessible. 31 | - on insertion or lookup of an assertion it is moved to the head of the list 32 | - in case the cache is full the assertion at the tail of the list is removed. 33 | - to allow fast lookups of assertions, two hash maps are used. The first hashmap is keyed by zone, 34 | name, and type. The value is a pointer to the second hashmap which is keyed by the context. The 35 | value points to a lru list node. 36 | - a list node contains a set (safe for concurrent accesses) of objects containing an assertion and 37 | expiration time. Each object in the set must have the same zone, name, type, and context. 38 | - sections over which this server has authority are not subject to lru removal. 39 | -------------------------------------------------------------------------------- /docs/cache-design/DESIGN-NEG-CACHE.md: -------------------------------------------------------------------------------- 1 | # Negative assertion cache 2 | 3 | ## Cache design decisions 4 | - Shards and Zones over which the server has authority are only removed when they expire. All other 5 | shards and zones are subject to a least recently used policy. 6 | - Expired but not yet reaped shards and zones are also returned such that the caller can decide how 7 | he wants to handle them. e.g. when a query has option 5 (expired assertions are acceptable) set. 8 | 9 | ## Negative assertion requirements 10 | - cache has a maximum size which is configurable (to avoid memory exhaustion of the server in case 11 | of an attack). It is not fix size to reduce the number of comparisons needed for checking that a 12 | new shard or zone is consistent with all already cached entries. 13 | - In case the cache is full the least recently used shard or zone over which the server has no 14 | authority is removed from the cache. In case the authoritative shards and zones fill up the cache 15 | an error msg must be logged such that an operator can change the configuration. 16 | - it must provide an insertion function which stores a shard or zone together with an expiration 17 | time to the cache (expiration time is necessary as we might want to store them for a shorter 18 | amount of time as they are valid. It is not possible to change the value directly as it is 19 | protected by the signature). The shard or zone must also be added to the consistency cache. 20 | - it must provide fast lookup of a set of shards and zones based on a subjectZone (if any context is 21 | allowed) or a subjectZone and context. A set of all intervals containing the subjectZone is 22 | returned such that the calling function can decide which entry it wants to send back according to 23 | a policy. 24 | - it must provide a reap function that removes expired entries. This function must also remove the 25 | corresponding element in the consistency cache. 26 | - it must provide a removal function which removes all assertions of a specific zone in case this 27 | zone misbehaved or sent inconsistent messages. 28 | - all cache operations must be safe for concurrent access 29 | 30 | ## Negative assertion implementation 31 | - lru strategy is implemented as a linked list where pointers to the head and tail of the list are 32 | accessible. 33 | - on insertion or lookup of an entry it is moved to the head of the list 34 | - in case the cache is full the shard or zone at the tail of the list is removed. 35 | - to allow fast lookup two hash maps and segment trees are used. Segment trees can efficiently 36 | return all intervals stored in the tree which contain a query point. The first hashmap is keyed by 37 | a zone. The value is a pointer to the second hashmap which is keyed by the context. The value 38 | points to a segment tree data structure. A stored interval in the tree is a lru list node where 39 | the interval of the list node is inherited from the contained shard or zone. 40 | - a list node contains a set (safe for concurrent accesses) of objects containing a shard or zone 41 | with an expiration time. Each object in the set must have the same subjectZone, context and 42 | interval. 43 | - sections over which this server has authority are not subject to lru removal. 44 | -------------------------------------------------------------------------------- /docs/man/keyManager.md: -------------------------------------------------------------------------------- 1 | keyManager(1) -- A RAINS key manager 2 | ================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `keyManager` [command] [path] [options] 7 | 8 | ## DESCRIPTION 9 | 10 | keyManager is a tool for managing public private key pairs for the RAINS infrastructure from the 11 | command line. It offers key generation for all algorithms supported by RAINS and stores the keys pem 12 | encoded. The private key is encrypted using aes before being pem encoded. The aes key is generated 13 | from a user provided password. Given the name of the key and the correct password, the keyManager 14 | decrypts the private key and prints it pem encoded. 15 | 16 | ## OPTIONS 17 | 18 | * path: 19 | Path where the keys are or will be stored. The current location is the default path. 20 | 21 | * `-n`, `--name`: 22 | The prefix of the file name where the key is loaded from or will be stored to. 23 | 24 | * `-a`, `--algo`: 25 | Defines the algorithm which is used in key generation. The default is ed25519. Supported 26 | algorithms are: ed25519 27 | 28 | * `--phase`: 29 | Defines the key phase for which a key is generated. The default is 0 30 | 31 | * `-d`, `--description`: 32 | Description allows to store an arbitrary string value with the key. It can e.g. be used to store 33 | the information in which zone and context the key pair is used. The default is the empty string. 34 | 35 | * `--pwd`: 36 | Pwd states the password to encrypt or decrypt a private key. The default is the empty string. 37 | 38 | ## COMMANDS 39 | * `load`, `l`: 40 | Prints all public keys stored at the provided path. 41 | * `generate`, `gen`, `g`: 42 | Generate first creates a new public-private key pair according to the provided algorithm. It 43 | then encrypts the private key with the provided password. Lastly, it pem encodes the private and 44 | public key separately and stores them at the provided path. The file prefix corresponds to the 45 | provided name followed by _sec.pem or _pub.pem (for private or public key). 46 | * `decrypt`, `d`: 47 | Decrypt loads the pem encoded private key at path corresponding to the provided name. It then 48 | encrypts the private key with the user provided password and prints to decrypted key pem encoded 49 | to the stdout. 50 | 51 | ## EXAMPLES 52 | 53 | TODO 54 | -------------------------------------------------------------------------------- /docs/man/rdig.md: -------------------------------------------------------------------------------- 1 | rdig(1) -- A RAINS query tool 2 | ================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `rdig` [@server] [options] [name] [type] [queryoptions...] 7 | 8 | ## DESCRIPTION 9 | 10 | rdig (short for RAINS dig) is a tool for querying RAINS servers from the command line. It performs 11 | lookups of the provided domain names and prints the results on the command line in zone file format. 12 | 13 | ## Simple Usage 14 | 15 | A typical usage of rdig looks like: 16 | 17 | rdig @server name type... 18 | 19 | where: 20 | * server: is the IP address or a name of the RAINS server to which the query will be sent. The 21 | address can be an IPv4 address in dotted-decimal notation or an IPv6 address in colon-delimited 22 | notation. If the provided argument is a host name, rdig first resolves the IP address of that 23 | host before sending the actual query to this RAINS server. If no server argument is provided, 24 | rdig consults /etc/resolv.conf and queries the name servers listed there. 25 | 26 | * name: "is the fully qualified domain name of the Assertion that will be looked up" 27 | 28 | * type: specifies the type(s) for which rdig issues a query. Allowed types are: name, ip6, ip4, redir, 29 | deleg, nameset, cert, srv, regr, regt, infra, extra, next. If no type argument is provided, the 30 | type is set to ip6. 31 | 32 | ## OPTIONS 33 | 34 | * `-p`, `--port`: is the port number that rdig will send its queries to. (default 55553) 35 | * `-k`, `--keyphase`: is the key phase for which a delegation is requested. (default 0) 36 | * `-c`, `--context`: specifies the context for which rdig issues a query. (default ".") 37 | * `-e`, `--expires`: expires sets the valid until timestamp of the query in unix seconds since 1970. 38 | (default current timestamp + 1 second) 39 | * `-i`, `--insecureTLS`: when set it does not check the validity of the server's TLS certificate. 40 | (default false) 41 | * `-t`, `--token`: specifies a token to be used in the query instead of using a randomly generated 42 | one. 43 | 44 | ## QUERY OPTIONS 45 | 46 | RAINS supports a set of query options to allow a querier to express preferences on how the query 47 | should be handled. RAINS servers are not bound to these preferences. Query options are to be set in 48 | priority order, i.e. to specify query options minEE and minIL with higher priority on minEE, write: 49 | -minEE -minIL. Each query option is identified by a keyword. 50 | 51 | * `-1`, `--minEE`: Query option: Minimize end-to-end latency 52 | * `-2`, `--minAS`: Query option: Minimize last-hop answer size (bandwidth) 53 | * `-3`, `--minIL`: Query option: Minimize information leakage beyond first hop 54 | * `-4`, `--noIL`: Query option: No information leakage beyond first hop: cached answers only 55 | * `-5`, `--exp`: Query option: Expired assertions are acceptable 56 | * `-6`, `--tracing`: Query option: Enable query token tracing 57 | * `-7`, `--noVD`: Query option: Disable verification delegation (client protocol only) 58 | * `-8`, `--noCaching`: Query option: Suppress proactive caching of future assertions 59 | * `-9`, `--maxAF`: Query option: Maximize answer freshness 60 | 61 | ## EXAMPLES 62 | 63 | Simple query for the address associated to the name of www.inf.ethz.ch: 64 | 65 | rdig www.inf.ethz.ch 66 | 67 | Querying the certificates which are used to authenticate connections to www.inf.ethz.ch: 68 | 69 | rdig www.inf.ethz.ch cert 70 | 71 | Finding the name `simplon` within the context of inf.ethz.ch: 72 | 73 | rdig -c inf.ethz.ch simplon 74 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/netsec-ethz/rains 2 | 3 | go 1.21.10 4 | 5 | toolchain go1.21.11 6 | 7 | require ( 8 | github.com/britram/borat v0.0.0-20181011130314-f891bcfcfb9b 9 | github.com/inconshreveable/log15 v0.0.0-20180818164646-67afb5ed74ec 10 | github.com/scionproto/scion v0.11.1-0.20240610170620-50b971ca2d4b 11 | github.com/spf13/cobra v1.8.0 12 | github.com/spf13/pflag v1.0.5 13 | github.com/stretchr/testify v1.9.0 14 | golang.org/x/crypto v0.23.0 15 | ) 16 | 17 | require ( 18 | github.com/beorn7/perks v1.0.1 // indirect 19 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 20 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 21 | github.com/dchest/cmac v1.0.0 // indirect 22 | github.com/dustin/go-humanize v1.0.1 // indirect 23 | github.com/go-stack/stack v1.8.0 // indirect 24 | github.com/golang/protobuf v1.5.4 // indirect 25 | github.com/google/gopacket v1.1.19 // indirect 26 | github.com/google/uuid v1.6.0 // indirect 27 | github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect 28 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect 29 | github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect 30 | github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect 31 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 32 | github.com/mattn/go-colorable v0.1.13 // indirect 33 | github.com/mattn/go-isatty v0.0.20 // indirect 34 | github.com/mattn/go-sqlite3 v1.14.22 // indirect 35 | github.com/ncruces/go-strftime v0.1.9 // indirect 36 | github.com/opentracing/opentracing-go v1.2.0 // indirect 37 | github.com/pelletier/go-toml/v2 v2.2.2 // indirect 38 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect 39 | github.com/prometheus/client_golang v1.19.1 // indirect 40 | github.com/prometheus/client_model v0.6.1 // indirect 41 | github.com/prometheus/common v0.53.0 // indirect 42 | github.com/prometheus/procfs v0.14.0 // indirect 43 | github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect 44 | github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect 45 | github.com/uber/jaeger-lib v2.4.1+incompatible // indirect 46 | go.uber.org/atomic v1.11.0 // indirect 47 | go.uber.org/multierr v1.11.0 // indirect 48 | go.uber.org/zap v1.27.0 // indirect 49 | golang.org/x/net v0.25.0 // indirect 50 | golang.org/x/sync v0.7.0 // indirect 51 | golang.org/x/sys v0.20.0 // indirect 52 | golang.org/x/text v0.15.0 // indirect 53 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 // indirect 54 | google.golang.org/grpc v1.63.2 // indirect 55 | google.golang.org/protobuf v1.34.1 // indirect 56 | gopkg.in/d4l3k/messagediff.v1 v1.2.1 // indirect 57 | gopkg.in/yaml.v3 v3.0.1 // indirect 58 | modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect 59 | modernc.org/libc v1.50.5 // indirect 60 | modernc.org/mathutil v1.6.0 // indirect 61 | modernc.org/memory v1.8.0 // indirect 62 | modernc.org/sqlite v1.29.9 // indirect 63 | modernc.org/strutil v1.2.0 // indirect 64 | modernc.org/token v1.1.0 // indirect 65 | ) 66 | -------------------------------------------------------------------------------- /internal/pkg/algorithmTypes/algorithmTypes.go: -------------------------------------------------------------------------------- 1 | package algorithmTypes 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | ) 7 | 8 | // Signature specifies a signature algorithm type 9 | type Signature int 10 | 11 | //go:generate stringer -type=Signature 12 | //go:generate jsonenums -type=Signature 13 | const ( 14 | Ed25519 Signature = iota + 1 15 | Ed448 16 | ) 17 | 18 | // AtoSig returns a signature algorithm type based on common string representation thereof. 19 | func AtoSig(str string) (Signature, error) { 20 | switch str { 21 | case Ed25519.String(), "ed25519", "ED25519", strconv.Itoa(int(Ed25519)): 22 | return Ed25519, nil 23 | case Ed448.String(), "ed448", "ED448", strconv.Itoa(int(Ed448)): 24 | return Ed448, nil 25 | } 26 | return Signature(-1), fmt.Errorf("%s is not a signature algorithm type", str) 27 | } 28 | 29 | // Hash specifies a hash algorithm type 30 | type Hash int 31 | 32 | //go:generate stringer -type=Hash 33 | //go:generate jsonenums -type=Hash 34 | const ( 35 | NoHashAlgo Hash = iota 36 | Sha256 37 | Sha384 38 | Sha512 39 | Shake256 40 | Fnv64 41 | Fnv128 42 | ) 43 | -------------------------------------------------------------------------------- /internal/pkg/algorithmTypes/hash_jsonenums.go: -------------------------------------------------------------------------------- 1 | // generated by jsonenums -type=Hash; DO NOT EDIT 2 | 3 | package algorithmTypes 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | ) 9 | 10 | var ( 11 | _HashNameToValue = map[string]Hash{ 12 | "NoHashAlgo": NoHashAlgo, 13 | "Sha256": Sha256, 14 | "Sha384": Sha384, 15 | "Sha512": Sha512, 16 | "Shake256": Shake256, 17 | "Fnv64": Fnv64, 18 | "Fnv128": Fnv128, 19 | } 20 | 21 | _HashValueToName = map[Hash]string{ 22 | NoHashAlgo: "NoHashAlgo", 23 | Sha256: "Sha256", 24 | Sha384: "Sha384", 25 | Sha512: "Sha512", 26 | Shake256: "Shake256", 27 | Fnv64: "Fnv64", 28 | Fnv128: "Fnv128", 29 | } 30 | ) 31 | 32 | func init() { 33 | var v Hash 34 | if _, ok := interface{}(v).(fmt.Stringer); ok { 35 | _HashNameToValue = map[string]Hash{ 36 | interface{}(NoHashAlgo).(fmt.Stringer).String(): NoHashAlgo, 37 | interface{}(Sha256).(fmt.Stringer).String(): Sha256, 38 | interface{}(Sha384).(fmt.Stringer).String(): Sha384, 39 | interface{}(Sha512).(fmt.Stringer).String(): Sha512, 40 | interface{}(Shake256).(fmt.Stringer).String(): Shake256, 41 | interface{}(Fnv64).(fmt.Stringer).String(): Fnv64, 42 | interface{}(Fnv128).(fmt.Stringer).String(): Fnv128, 43 | } 44 | } 45 | } 46 | 47 | // MarshalJSON is generated so Hash satisfies json.Marshaler. 48 | func (r Hash) MarshalJSON() ([]byte, error) { 49 | if s, ok := interface{}(r).(fmt.Stringer); ok { 50 | return json.Marshal(s.String()) 51 | } 52 | s, ok := _HashValueToName[r] 53 | if !ok { 54 | return nil, fmt.Errorf("invalid Hash: %d", r) 55 | } 56 | return json.Marshal(s) 57 | } 58 | 59 | // UnmarshalJSON is generated so Hash satisfies json.Unmarshaler. 60 | func (r *Hash) UnmarshalJSON(data []byte) error { 61 | var s string 62 | if err := json.Unmarshal(data, &s); err != nil { 63 | return fmt.Errorf("Hash should be a string, got %s", data) 64 | } 65 | v, ok := _HashNameToValue[s] 66 | if !ok { 67 | return fmt.Errorf("invalid Hash %q", s) 68 | } 69 | *r = v 70 | return nil 71 | } 72 | -------------------------------------------------------------------------------- /internal/pkg/algorithmTypes/hash_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=Hash"; DO NOT EDIT. 2 | 3 | package algorithmTypes 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[NoHashAlgo-0] 12 | _ = x[Sha256-1] 13 | _ = x[Sha384-2] 14 | _ = x[Sha512-3] 15 | _ = x[Shake256-4] 16 | _ = x[Fnv64-5] 17 | _ = x[Fnv128-6] 18 | } 19 | 20 | const _Hash_name = "NoHashAlgoSha256Sha384Sha512Shake256Fnv64Fnv128" 21 | 22 | var _Hash_index = [...]uint8{0, 10, 16, 22, 28, 36, 41, 47} 23 | 24 | func (i Hash) String() string { 25 | if i < 0 || i >= Hash(len(_Hash_index)-1) { 26 | return "Hash(" + strconv.FormatInt(int64(i), 10) + ")" 27 | } 28 | return _Hash_name[_Hash_index[i]:_Hash_index[i+1]] 29 | } 30 | -------------------------------------------------------------------------------- /internal/pkg/algorithmTypes/signature_jsonenums.go: -------------------------------------------------------------------------------- 1 | // generated by jsonenums -type=Signature; DO NOT EDIT 2 | 3 | package algorithmTypes 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | ) 9 | 10 | var ( 11 | _SignatureNameToValue = map[string]Signature{ 12 | "Ed25519": Ed25519, 13 | "Ed448": Ed448, 14 | } 15 | 16 | _SignatureValueToName = map[Signature]string{ 17 | Ed25519: "Ed25519", 18 | Ed448: "Ed448", 19 | } 20 | ) 21 | 22 | func init() { 23 | var v Signature 24 | if _, ok := interface{}(v).(fmt.Stringer); ok { 25 | _SignatureNameToValue = map[string]Signature{ 26 | interface{}(Ed25519).(fmt.Stringer).String(): Ed25519, 27 | interface{}(Ed448).(fmt.Stringer).String(): Ed448, 28 | } 29 | } 30 | } 31 | 32 | // MarshalJSON is generated so Signature satisfies json.Marshaler. 33 | func (r Signature) MarshalJSON() ([]byte, error) { 34 | if s, ok := interface{}(r).(fmt.Stringer); ok { 35 | return json.Marshal(s.String()) 36 | } 37 | s, ok := _SignatureValueToName[r] 38 | if !ok { 39 | return nil, fmt.Errorf("invalid Signature: %d", r) 40 | } 41 | return json.Marshal(s) 42 | } 43 | 44 | // UnmarshalJSON is generated so Signature satisfies json.Unmarshaler. 45 | func (r *Signature) UnmarshalJSON(data []byte) error { 46 | var s string 47 | if err := json.Unmarshal(data, &s); err != nil { 48 | return fmt.Errorf("Signature should be a string, got %s", data) 49 | } 50 | v, ok := _SignatureNameToValue[s] 51 | if !ok { 52 | return fmt.Errorf("invalid Signature %q", s) 53 | } 54 | *r = v 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /internal/pkg/algorithmTypes/signature_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=Signature"; DO NOT EDIT. 2 | 3 | package algorithmTypes 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[Ed25519-1] 12 | _ = x[Ed448-2] 13 | } 14 | 15 | const _Signature_name = "Ed25519Ed448" 16 | 17 | var _Signature_index = [...]uint8{0, 7, 12} 18 | 19 | func (i Signature) String() string { 20 | i -= 1 21 | if i < 0 || i >= Signature(len(_Signature_index)-1) { 22 | return "Signature(" + strconv.FormatInt(int64(i+1), 10) + ")" 23 | } 24 | return _Signature_name[_Signature_index[i]:_Signature_index[i+1]] 25 | } 26 | -------------------------------------------------------------------------------- /internal/pkg/cache/capabilityCache.go: -------------------------------------------------------------------------------- 1 | package cache 2 | 3 | import ( 4 | "crypto/sha256" 5 | "fmt" 6 | "sort" 7 | 8 | log "github.com/inconshreveable/log15" 9 | "github.com/netsec-ethz/rains/internal/pkg/datastructures/safeCounter" 10 | "github.com/netsec-ethz/rains/internal/pkg/lruCache" 11 | "github.com/netsec-ethz/rains/internal/pkg/message" 12 | ) 13 | 14 | /* 15 | * Capability cache implementation 16 | */ 17 | type CapabilityImpl struct { 18 | capabilityMap *lruCache.Cache 19 | counter *safeCounter.Counter 20 | } 21 | 22 | func NewCapability(maxSize int) *CapabilityImpl { 23 | cache := &CapabilityImpl{ 24 | capabilityMap: lruCache.New(), 25 | counter: safeCounter.New(maxSize), 26 | } 27 | cache.capabilityMap.GetOrAdd("e5365a09be554ae55b855f15264dbc837b04f5831daeb321359e18cdabab5745", 28 | []message.Capability{message.TLSOverTCP}, true) 29 | cache.capabilityMap.GetOrAdd("76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71", 30 | []message.Capability{message.NoCapability}, false) 31 | cache.counter.Add(2) 32 | return cache 33 | } 34 | 35 | func (c *CapabilityImpl) Add(capabilities []message.Capability) { 36 | //FIXME CFE take a SHA-256 hash of the CBOR byte stream derived from normalizing such an array by sorting it in lexicographically increasing order, 37 | //then serializing it and add it to the cache 38 | sort.Slice(capabilities, func(i, j int) bool { return capabilities[i] < capabilities[j] }) 39 | cs := []byte{} 40 | for _, c := range capabilities { 41 | cs = append(cs, []byte(c)...) 42 | } 43 | hash := sha256.Sum256(cs) 44 | _, ok := c.capabilityMap.GetOrAdd(string(hash[:]), capabilities, false) 45 | //handle full cache 46 | if ok && c.counter.Inc() { 47 | for { 48 | k, _ := c.capabilityMap.GetLeastRecentlyUsed() 49 | if _, ok := c.capabilityMap.Remove(k); ok { 50 | c.counter.Dec() 51 | break 52 | } 53 | } 54 | } 55 | } 56 | 57 | func (c *CapabilityImpl) Get(hash []byte) ([]message.Capability, bool) { 58 | if v, ok := c.capabilityMap.Get(string(hash)); ok { 59 | if val, ok := v.([]message.Capability); ok { 60 | return val, true 61 | } 62 | log.Warn("Cache entry is not of type []message.Capability", 63 | "actualType", fmt.Sprintf("%T", v)) 64 | } 65 | return nil, false 66 | } 67 | 68 | func (c *CapabilityImpl) Len() int { 69 | return c.counter.Value() 70 | } 71 | -------------------------------------------------------------------------------- /internal/pkg/cache/capabilityCache_test.go: -------------------------------------------------------------------------------- 1 | package cache 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | "github.com/netsec-ethz/rains/internal/pkg/datastructures/safeCounter" 8 | "github.com/netsec-ethz/rains/internal/pkg/lruCache" 9 | "github.com/netsec-ethz/rains/internal/pkg/message" 10 | ) 11 | 12 | func TestCapabilityCache(t *testing.T) { 13 | //TODO CFE remove these manually added entries once there is a working add implementation 14 | cache := lruCache.New() 15 | cache.GetOrAdd("e5365a09be554ae55b855f15264dbc837b04f5831daeb321359e18cdabab5745", 16 | []message.Capability{message.TLSOverTCP}, true) 17 | cache.GetOrAdd("76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71", 18 | []message.Capability{message.NoCapability}, false) 19 | counter := safeCounter.New(10) 20 | counter.Add(2) 21 | var tests = []struct { 22 | input Capability 23 | }{ 24 | {&CapabilityImpl{capabilityMap: cache, counter: counter}}, 25 | } 26 | for i, test := range tests { 27 | c := test.input 28 | if c.Len() != 2 { 29 | t.Error("init size is incorrect", "size", c.Len()) 30 | } 31 | //TODO CFE test add when it is correctly implemented. 32 | caps, ok := c.Get([]byte("e5365a09be554ae55b855f15264dbc837b04f5831daeb321359e18cdabab5745")) 33 | if !ok { 34 | t.Errorf("%d: Get did not returned contained element.", i) 35 | } 36 | if !reflect.DeepEqual(caps, []message.Capability{message.TLSOverTCP}) { 37 | t.Errorf("%d: Returned element is wrong", i) 38 | } 39 | caps, ok = c.Get([]byte("76be8b528d0075f7aae98d6fa57a6d3c83ae480a8469e668d7b0af968995ac71")) 40 | if !ok { 41 | t.Errorf("%d: Get did not returned contained element.", i) 42 | } 43 | if !reflect.DeepEqual(caps, []message.Capability{message.NoCapability}) { 44 | t.Errorf("%d: Returned element is wrong", i) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /internal/pkg/cache/connectionCache_test.go: -------------------------------------------------------------------------------- 1 | package cache 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "net" 7 | "reflect" 8 | "testing" 9 | "time" 10 | 11 | "github.com/netsec-ethz/rains/internal/pkg/datastructures/safeCounter" 12 | "github.com/netsec-ethz/rains/internal/pkg/lruCache" 13 | "github.com/netsec-ethz/rains/internal/pkg/message" 14 | ) 15 | 16 | func TestConnectionCache(t *testing.T) { 17 | var tests = []struct { 18 | input Connection 19 | }{ 20 | {&ConnectionImpl{cache: lruCache.New(), counter: safeCounter.New(3)}}, 21 | } 22 | for i, test := range tests { 23 | tcpAddr := "localhost:8100" 24 | tcpAddr2 := "localhost:8101" 25 | tcpAddr3 := "localhost:8102" 26 | go mockServer(tcpAddr, t) 27 | go mockServer(tcpAddr2, t) 28 | go mockServer(tcpAddr3, t) 29 | time.Sleep(time.Millisecond * 50) 30 | c := test.input 31 | if c.Len() != 0 { 32 | t.Errorf("%d:init size is incorrect actual=%d", i, c.Len()) 33 | } 34 | conn1, _ := net.Dial("tcp", tcpAddr) 35 | conn2, _ := net.Dial("tcp", tcpAddr2) 36 | conn3, _ := net.Dial("tcp", tcpAddr3) 37 | connInfo1 := conn1.RemoteAddr().(*net.TCPAddr) 38 | connInfo2 := conn2.RemoteAddr().(*net.TCPAddr) 39 | connInfo3 := conn3.RemoteAddr().(*net.TCPAddr) 40 | c.AddConnection(conn1) 41 | c.AddConnection(conn2) 42 | if c.Len() != 2 { 43 | t.Errorf("%d: size is incorrect after 2 inserts. actual=%d", i, c.Len()) 44 | } 45 | c.AddConnection(conn3) 46 | //Check that lru is working 47 | if c.Len() != 2 { 48 | t.Errorf("%d: size is incorrect after lru removal expected=2 actual=%d", i, c.Len()) 49 | } 50 | _, ok := c.GetConnection(connInfo1) 51 | if ok { 52 | t.Errorf("%d: Wrong connection removed", i) 53 | } 54 | outConn2, ok := c.GetConnection(connInfo2) 55 | if !ok { 56 | t.Errorf("%d: Wrong connection removed", i) 57 | } 58 | _, ok = c.GetConnection(connInfo3) 59 | if !ok { 60 | t.Errorf("%d: Wrong connection removed", i) 61 | } 62 | //test that connection can still be used. 63 | outConn2[0].Write([]byte("testMsg\n")) 64 | buffer := make([]byte, 7) 65 | _, err := outConn2[0].Read(buffer) 66 | if err != nil || !reflect.DeepEqual(buffer, []byte("testMsg")) { 67 | t.Errorf("%d: Connection is not active or msg received is wrong", i) 68 | } 69 | //test adding capability 70 | capabilityList := []message.Capability{message.TLSOverTCP} 71 | ok = c.AddCapabilityList(connInfo2, capabilityList) 72 | if !ok { 73 | t.Errorf("%d: Was not able to add capability list to connection2", i) 74 | } 75 | ok = c.AddCapabilityList(connInfo1, capabilityList) 76 | if ok { 77 | t.Errorf("%d: Was able to add capability list to connection1 although it is not in the cache", i) 78 | } 79 | //test retrieving capability 80 | returnList, ok := c.GetCapabilityList(connInfo2) 81 | if !ok || !reflect.DeepEqual(returnList, capabilityList) { 82 | t.Errorf("%d: Obtained capability list does not matched added one or was not found", i) 83 | } 84 | returnList, ok = c.GetCapabilityList(connInfo1) 85 | if ok || returnList != nil { 86 | t.Errorf("%d: Nothing should have been returned", i) 87 | } 88 | //test closeAndRemoveConnection 89 | c.CloseAndRemoveConnection(conn2) 90 | _, ok = c.GetConnection(connInfo2) 91 | if ok || c.Len() != 1 { 92 | t.Errorf("%d: Wrong connection removed or count is off", i) 93 | } 94 | } 95 | } 96 | 97 | func mockServer(tcpAddr string, t *testing.T) { 98 | ln, err := net.Listen("tcp", tcpAddr) 99 | if err != nil { 100 | panic(fmt.Sprintf("Could not mock the server: %v", err)) 101 | } 102 | for { 103 | conn, _ := ln.Accept() 104 | go handleConn(conn) 105 | } 106 | } 107 | 108 | // handleConn responds with the same message as received 109 | func handleConn(c net.Conn) { 110 | input := bufio.NewScanner(c) 111 | for input.Scan() { 112 | c.Write([]byte(input.Text())) 113 | } 114 | c.Close() 115 | } 116 | -------------------------------------------------------------------------------- /internal/pkg/cache/pendingKeyCache.go: -------------------------------------------------------------------------------- 1 | package cache 2 | 3 | import ( 4 | "time" 5 | 6 | log "github.com/inconshreveable/log15" 7 | "github.com/netsec-ethz/rains/internal/pkg/datastructures/safeCounter" 8 | "github.com/netsec-ethz/rains/internal/pkg/datastructures/safeHashMap" 9 | "github.com/netsec-ethz/rains/internal/pkg/token" 10 | "github.com/netsec-ethz/rains/internal/pkg/util" 11 | ) 12 | 13 | type pkcValue struct { 14 | //mss contains all the message and the sender for which some keys are missing 15 | mss util.MsgSectionSender 16 | //expiration contains the expiration value of the forwarded query 17 | expiration int64 18 | } 19 | 20 | type PendingKeyImpl struct { 21 | //tokenMap is a map from token to *pendingQueryCacheValue safe for concurrent use 22 | tokenMap *safeHashMap.Map 23 | //counter holds the number of sectionSender objects stored in the cache 24 | counter *safeCounter.Counter 25 | } 26 | 27 | func NewPendingKey(maxSize int) *PendingKeyImpl { 28 | return &PendingKeyImpl{ 29 | tokenMap: safeHashMap.New(), 30 | counter: safeCounter.New(maxSize), 31 | } 32 | } 33 | 34 | // Add adds ss to the cache together with the token and expiration time of the query sent to the 35 | // host with the addr defined in ss. 36 | func (c *PendingKeyImpl) Add(ss util.MsgSectionSender, t token.Token, expiration int64) { 37 | if c.counter.IsFull() { 38 | log.Error("Pending key cache is full") 39 | return 40 | } 41 | if ok := c.tokenMap.Add(t.String(), pkcValue{mss: ss, expiration: expiration}); !ok { 42 | log.Warn("Token already in key cache. Random source of Token generator no random enough?") 43 | return 44 | } 45 | c.counter.Inc() 46 | } 47 | 48 | // GetAndRemove returns util.MsgSectionSender which corresponds to token and true, and deletes it from 49 | // the cache. False is returned if no util.MsgSectionSender matched token. 50 | func (c *PendingKeyImpl) GetAndRemove(t token.Token) (util.MsgSectionSender, bool) { 51 | if val, present := c.tokenMap.Get(t.String()); present { 52 | c.tokenMap.Remove(t.String()) 53 | c.counter.Dec() 54 | return val.(pkcValue).mss, true 55 | } 56 | return util.MsgSectionSender{}, false 57 | } 58 | 59 | // ContainsToken returns true if t is cached 60 | func (c *PendingKeyImpl) ContainsToken(t token.Token) bool { 61 | _, present := c.tokenMap.Get(t.String()) 62 | return present 63 | } 64 | 65 | // RemoveExpiredValues deletes all expired entries. It logs the host's addr which was not able to 66 | // respond in time. 67 | func (c *PendingKeyImpl) RemoveExpiredValues() { 68 | keys := c.tokenMap.GetAllKeys() 69 | for _, key := range keys { 70 | if val, present := c.tokenMap.Get(key); present { 71 | if val := val.(pkcValue); val.expiration < time.Now().Unix() { 72 | c.tokenMap.Remove(key) 73 | c.counter.Dec() 74 | log.Warn("No response to delegation query received before expiration", 75 | "sectionSender", val.mss) 76 | } 77 | } 78 | } 79 | } 80 | 81 | // Len returns the number of sections in the cache 82 | func (c *PendingKeyImpl) Len() int { 83 | return c.tokenMap.Len() 84 | } 85 | -------------------------------------------------------------------------------- /internal/pkg/cache/pendingKeyCache_test.go: -------------------------------------------------------------------------------- 1 | package cache 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | "time" 7 | 8 | "github.com/netsec-ethz/rains/internal/pkg/datastructures/safeCounter" 9 | "github.com/netsec-ethz/rains/internal/pkg/datastructures/safeHashMap" 10 | "github.com/netsec-ethz/rains/internal/pkg/token" 11 | ) 12 | 13 | func TestPendingKeyCache(t *testing.T) { 14 | mss, _ := getQueries() 15 | var tests = []struct { 16 | input PendingKey 17 | }{ 18 | {&PendingKeyImpl{counter: safeCounter.New(4), tokenMap: safeHashMap.New()}}, 19 | } 20 | for i, test := range tests { 21 | c := test.input 22 | if c.Len() != 0 { 23 | t.Errorf("%d:init size is incorrect actual=%d", i, c.Len()) 24 | } 25 | //Test c.Add() 26 | c.Add(mss[0], mss[0].Token, time.Now().Add(time.Hour).Unix()) 27 | if c.Len() != 1 { 28 | t.Error("mss[0] was not added to the cache") 29 | } 30 | c.Add(mss[1], mss[1].Token, time.Now().Add(time.Hour).Unix()) 31 | if c.Len() != 2 { 32 | t.Error("mss[1] was not added to the cache") 33 | } 34 | c.Add(mss[2], mss[2].Token, time.Now().Add(time.Hour).Unix()) 35 | if c.Len() != 3 { 36 | t.Error("mss[2] was not added to the cache") 37 | } 38 | //Test c.ContainsToken() 39 | if !c.ContainsToken(mss[0].Token) || !c.ContainsToken(mss[0].Token) || 40 | !c.ContainsToken(mss[0].Token) || c.ContainsToken(token.New()) { 41 | t.Error("unexpected token was in the cache") 42 | } 43 | //Test c.GetAndRemove() 44 | if v, ok := c.GetAndRemove(mss[0].Token); !ok || c.Len() != 2 || 45 | !reflect.DeepEqual(v, mss[0]) { 46 | t.Error("mss[0] should be returned for this token") 47 | } 48 | if v, ok := c.GetAndRemove(mss[1].Token); !ok || c.Len() != 1 || 49 | !reflect.DeepEqual(v, mss[1]) { 50 | t.Error("mss[1] should be returned for this token") 51 | } 52 | if v, ok := c.GetAndRemove(mss[2].Token); !ok || c.Len() != 0 || 53 | !reflect.DeepEqual(v, mss[2]) { 54 | t.Error("mss[2] should be returned for this token") 55 | } 56 | //Test c.RemoveExpiredValues() 57 | c.Add(mss[0], mss[0].Token, time.Now().Add(time.Hour).Unix()) 58 | c.Add(mss[2], mss[2].Token, time.Now().Add(-time.Hour).Unix()) 59 | c.RemoveExpiredValues() 60 | if v, ok := c.GetAndRemove(mss[0].Token); !ok || c.Len() != 0 || 61 | !reflect.DeepEqual(v, mss[0]) { 62 | t.Error("expired value was not removed") 63 | } 64 | } 65 | } 66 | 67 | func TestPendingKeyCacheCounter(t *testing.T) { 68 | mss, _ := getQueries() 69 | var tests = []struct { 70 | maxSize int 71 | }{ 72 | {2}, 73 | } 74 | for _, test := range tests { 75 | c := &PendingKeyImpl{counter: safeCounter.New(test.maxSize), tokenMap: safeHashMap.New()} 76 | c.Add(mss[0], mss[0].Token, time.Now().Add(time.Hour).Unix()) 77 | //Test same token 78 | c.Add(mss[1], mss[0].Token, time.Now().Add(time.Hour).Unix()) 79 | if c.Len() != 1 { 80 | t.Error("entry added with same token did not overwrite old value") 81 | } 82 | c.Add(mss[1], mss[1].Token, time.Now().Add(time.Hour).Unix()) 83 | //Test MaxSize 84 | c.Add(mss[2], mss[2].Token, time.Now().Add(time.Hour).Unix()) 85 | if c.Len() != 2 { 86 | t.Error("was able to add more entries than maxSize") 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /internal/pkg/cache/pendingQueryCache_test.go: -------------------------------------------------------------------------------- 1 | package cache 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | "time" 7 | 8 | "github.com/netsec-ethz/rains/internal/pkg/datastructures/safeCounter" 9 | "github.com/netsec-ethz/rains/internal/pkg/section" 10 | "github.com/netsec-ethz/rains/internal/pkg/token" 11 | ) 12 | 13 | // TODO make compatible with new pendingQueryCache 14 | func TestPendingQueryCache(t *testing.T) { 15 | mss, _ := getQueries() 16 | var tests = []struct { 17 | maxSize int 18 | }{ 19 | {3}, 20 | } 21 | for i, test := range tests { 22 | c := &PendingQueryImpl{counter: safeCounter.New(test.maxSize), 23 | tokenMap: make(map[token.Token]*pqcValue), queryMap: make(map[string]token.Token)} 24 | if c.Len() != 0 { 25 | t.Errorf("%d:init size is incorrect actual=%d", i, c.Len()) 26 | } 27 | //Test c.Add() 28 | if ok := c.Add(mss[0], mss[0].Token, time.Now().Add(time.Hour).Unix()); !ok || c.Len() != 1 { 29 | t.Error("mss[0] was not added to the cache") 30 | } 31 | if ok := c.Add(mss[1], mss[1].Token, time.Now().Add(time.Hour).Unix()); ok || c.Len() != 2 { 32 | t.Error("mss[1] was not added to the cache") 33 | } 34 | if ok := c.Add(mss[2], mss[2].Token, time.Now().Add(time.Hour).Unix()); !ok || c.Len() != 3 { 35 | t.Error("mss[2] was not added to the cache") 36 | } 37 | //Test c.GetAndRemove() 38 | if v := c.GetAndRemove(mss[1].Token); len(v) != 0 || c.Len() != 3 { 39 | t.Error("token should not be part of the cache") 40 | } 41 | if v := c.GetAndRemove(mss[2].Token); len(v) != 1 || !reflect.DeepEqual(v[0], mss[2]) || 42 | c.Len() != 2 { 43 | t.Error("mss[2] should be returned for this token") 44 | } 45 | if v := c.GetAndRemove(mss[0].Token); len(v) != 2 || !reflect.DeepEqual(v[0], mss[0]) || 46 | !reflect.DeepEqual(v[1], mss[1]) || c.Len() != 0 { 47 | t.Error("mss[0] and mss[1] should be returned for this token") 48 | } 49 | //Test c.RemoveExpiredValues() 50 | c.Add(mss[0], mss[0].Token, time.Now().Add(time.Hour).Unix()) 51 | c.Add(mss[2], mss[2].Token, time.Now().Add(-time.Hour).Unix()) 52 | c.RemoveExpiredValues() 53 | if v := c.GetAndRemove(mss[0].Token); c.Len() != 0 || !reflect.DeepEqual(v[0], mss[0]) { 54 | t.Error("expired value was not removed") 55 | } 56 | 57 | //Add and retrieve delegation query 58 | if ok := c.Add(mss[3], mss[3].Token, time.Now().Add(time.Hour).Unix()); !ok || c.Len() != 1 { 59 | t.Error("mss[0] was not added to the cache") 60 | } 61 | if v := c.GetAndRemove(mss[3].Token); len(v) != 1 || !reflect.DeepEqual(v[0], mss[3]) || 62 | c.Len() != 0 { 63 | t.Error("mss[3] was not added to the cache") 64 | } 65 | 66 | //Add invalid input 67 | invalidMss := mss[0] 68 | invalidMss.Sections = []section.Section{§ion.Assertion{}} 69 | if ok := c.Add(invalidMss, invalidMss.Token, time.Now().Add(time.Hour).Unix()); ok || c.Len() != 0 { 70 | t.Error("mss with non query section was added to the cache") 71 | } 72 | 73 | //Test test maxSize 74 | for j := 0; j < test.maxSize; j++ { 75 | c.Add(mss[0], token.New(), time.Now().Add(time.Hour).Unix()) 76 | } 77 | c.Add(mss[0], token.New(), time.Now().Add(time.Hour).Unix()) 78 | if c.Len() != test.maxSize { 79 | t.Error("was able to add more entries than maxSize") 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /internal/pkg/cbor/cbor.go: -------------------------------------------------------------------------------- 1 | package cbor 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/britram/borat" 7 | ) 8 | 9 | // Writer defines all functions necessary to encode a message or section in cbor 10 | type Writer interface { 11 | Marshal(x interface{}) error 12 | WriteIntMap(m map[int]interface{}) error 13 | WriteTag(t borat.CBORTag) error 14 | WriteArray(a []interface{}) error 15 | } 16 | 17 | // Reader defines all functions necessary to decode a message or section encoded in cbor 18 | type Reader interface { 19 | Unmarshal(x interface{}) error 20 | ReadTag() (borat.CBORTag, error) 21 | ReadIntMapUntagged() (map[int]interface{}, error) 22 | } 23 | 24 | // NewWriter returns a new cbor writer which writes to out. 25 | func NewWriter(out io.Writer) Writer { 26 | return borat.NewCBORWriter(out) 27 | } 28 | 29 | // NewWriter returns a new cbor writer which writes to out. 30 | func NewReader(in io.Reader) Reader { 31 | return borat.NewCBORReader(in) 32 | } 33 | -------------------------------------------------------------------------------- /internal/pkg/connection/scion/path_selection.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 ETH Zurich 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License.package main 14 | 15 | package scion 16 | 17 | import ( 18 | "context" 19 | 20 | "github.com/scionproto/scion/pkg/addr" 21 | "github.com/scionproto/scion/pkg/snet" 22 | "github.com/scionproto/scion/pkg/snet/path" 23 | ) 24 | 25 | // SetDefaultPath sets the first path returned by a query to sciond. 26 | // This is a no-op if if remote is in the local AS. 27 | func SetDefaultPath(addr *snet.UDPAddr) error { 28 | paths, err := QueryPaths(addr.IA) 29 | if err != nil { 30 | return err 31 | } else if len(paths) > 0 { 32 | addr.Path = paths[0].Dataplane() 33 | addr.NextHop = paths[0].UnderlayNextHop() 34 | } else { 35 | addr.Path = path.Empty{} 36 | addr.NextHop = nil 37 | } 38 | return nil 39 | } 40 | 41 | // QueryPaths queries the DefNetwork's sciond PathQuerier connection for paths to addr 42 | // If addr is in the local IA, an empty slice and no error is returned. 43 | func QueryPaths(ia addr.IA) ([]snet.Path, error) { 44 | if ia == Host().IA { 45 | return nil, nil 46 | } else { 47 | paths, err := queryPaths(context.TODO(), ia) 48 | if err != nil || len(paths) == 0 { 49 | return nil, err 50 | } 51 | return paths, nil 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /internal/pkg/connection/type_jsonenums.go: -------------------------------------------------------------------------------- 1 | // generated by jsonenums -type=Type; DO NOT EDIT 2 | 3 | package connection 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | ) 9 | 10 | var ( 11 | _TypeNameToValue = map[string]Type{ 12 | "TCP": TCP, 13 | "SCION": SCION, 14 | } 15 | 16 | _TypeValueToName = map[Type]string{ 17 | TCP: "TCP", 18 | SCION: "SCION", 19 | } 20 | ) 21 | 22 | func init() { 23 | var v Type 24 | if _, ok := interface{}(v).(fmt.Stringer); ok { 25 | _TypeNameToValue = map[string]Type{ 26 | interface{}(TCP).(fmt.Stringer).String(): TCP, 27 | interface{}(SCION).(fmt.Stringer).String(): SCION, 28 | } 29 | } 30 | } 31 | 32 | // MarshalJSON is generated so Type satisfies json.Marshaler. 33 | func (r Type) MarshalJSON() ([]byte, error) { 34 | if s, ok := interface{}(r).(fmt.Stringer); ok { 35 | return json.Marshal(s.String()) 36 | } 37 | s, ok := _TypeValueToName[r] 38 | if !ok { 39 | return nil, fmt.Errorf("invalid Type: %d", r) 40 | } 41 | return json.Marshal(s) 42 | } 43 | 44 | // UnmarshalJSON is generated so Type satisfies json.Unmarshaler. 45 | func (r *Type) UnmarshalJSON(data []byte) error { 46 | var s string 47 | if err := json.Unmarshal(data, &s); err != nil { 48 | return fmt.Errorf("Type should be a string, got %s", data) 49 | } 50 | v, ok := _TypeNameToValue[s] 51 | if !ok { 52 | return fmt.Errorf("invalid Type %q", s) 53 | } 54 | *r = v 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /internal/pkg/connection/type_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=Type"; DO NOT EDIT. 2 | 3 | package connection 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[TCP-1] 12 | _ = x[SCION-2] 13 | } 14 | 15 | const _Type_name = "TCPSCION" 16 | 17 | var _Type_index = [...]uint8{0, 3, 8} 18 | 19 | func (i Type) String() string { 20 | i -= 1 21 | if i < 0 || i >= Type(len(_Type_index)-1) { 22 | return "Type(" + strconv.FormatInt(int64(i+1), 10) + ")" 23 | } 24 | return _Type_name[_Type_index[i]:_Type_index[i+1]] 25 | } 26 | -------------------------------------------------------------------------------- /internal/pkg/datastructures/bitarray/bitarray.go: -------------------------------------------------------------------------------- 1 | package bitarray 2 | 3 | import "errors" 4 | 5 | // Bitarray datastructure 6 | type BitArray []byte 7 | 8 | // SetBit sets the ith bit. Returns an error if i is out of bound 9 | func (b BitArray) SetBit(i int) error { 10 | block := i / 8 11 | if block >= len(b) { 12 | return errors.New("i out of bound") 13 | } 14 | b[block] |= getOffset(i % 8) 15 | return nil 16 | } 17 | 18 | // GetBit gets the ith bit. Returns true if bit is set; or an error if i is out of bound 19 | func (b BitArray) GetBit(i int) (bool, error) { 20 | block := i / 8 21 | if block >= len(b) { 22 | return false, errors.New("i out of bound") 23 | } 24 | return (b[block] & getOffset(i%8)) != 0, nil 25 | } 26 | 27 | // getOffset returns an uint8 bit mask where pos is set to 1. 0 is returned when pos is larger than 7 28 | // or negative. 29 | func getOffset(pos int) uint8 { 30 | if pos == 0 { 31 | return 1 32 | } else if pos == 1 { 33 | return 2 34 | } else if pos == 2 { 35 | return 4 36 | } else if pos == 3 { 37 | return 8 38 | } else if pos == 4 { 39 | return 16 40 | } else if pos == 5 { 41 | return 32 42 | } else if pos == 6 { 43 | return 64 44 | } else if pos == 7 { 45 | return 128 46 | } 47 | return 0 48 | } 49 | -------------------------------------------------------------------------------- /internal/pkg/datastructures/bitarray/bitarray_test.go: -------------------------------------------------------------------------------- 1 | package bitarray 2 | 3 | import "testing" 4 | 5 | func TestSetBit(t *testing.T) { 6 | b := make(BitArray, 2) 7 | if b.SetBit(16) == nil { 8 | t.Errorf("SetBit did not return an error") 9 | } 10 | b.SetBit(0) 11 | if b[0] != 1 { 12 | t.Errorf("SetBit did not set bit at position 0 in first block, value=%d", b[0]) 13 | } 14 | b.SetBit(0) 15 | if b[0] != 1 { 16 | t.Errorf("Setting same bit twice reverted the outcome, value=%d", b[0]) 17 | } 18 | b.SetBit(1) 19 | if b[0] != 3 { 20 | t.Errorf("SetBit did not set bit at position 1 in first block, value=%d", b[0]) 21 | } 22 | b.SetBit(8) 23 | if b[1] != 1 { 24 | t.Errorf("SetBit did not set bit at position 0 in second block, value=%d", b[1]) 25 | } 26 | 27 | } 28 | 29 | func TestGetBit(t *testing.T) { 30 | b := make(BitArray, 2) 31 | b[0] = 3 32 | if _, err := b.GetBit(16); err == nil { 33 | t.Errorf("GetBit did not return an error") 34 | } 35 | if val, err := b.GetBit(0); err != nil || !val { 36 | t.Errorf("GetBit returned wrong value, value=%v", val) 37 | } 38 | if val, err := b.GetBit(1); err != nil || !val { 39 | t.Errorf("GetBit returned wrong value, value=%v", val) 40 | } 41 | if val, err := b.GetBit(2); err != nil || val { 42 | t.Errorf("GetBit returned wrong value, value=%v", val) 43 | } 44 | if val, err := b.GetBit(3); err != nil || val { 45 | t.Errorf("GetBit returned wrong value, value=%v", val) 46 | } 47 | if val, err := b.GetBit(4); err != nil || val { 48 | t.Errorf("GetBit returned wrong value, value=%v", val) 49 | } 50 | if val, err := b.GetBit(5); err != nil || val { 51 | t.Errorf("GetBit returned wrong value, value=%v", val) 52 | } 53 | if val, err := b.GetBit(6); err != nil || val { 54 | t.Errorf("GetBit returned wrong value, value=%v", val) 55 | } 56 | if val, err := b.GetBit(7); err != nil || val { 57 | t.Errorf("GetBit returned wrong value, value=%v", val) 58 | } 59 | b[1] = 1 60 | if val, err := b.GetBit(8); err != nil || !val { 61 | t.Errorf("GetBit returned wrong value, value=%v", val) 62 | } 63 | if val, err := b.GetBit(9); err != nil || val { 64 | t.Errorf("GetBit returned wrong value, value=%v", val) 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /internal/pkg/datastructures/safeCounter/safeCounter.go: -------------------------------------------------------------------------------- 1 | package safeCounter 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | 7 | log "github.com/inconshreveable/log15" 8 | ) 9 | 10 | // Counter is a concurrency safe counter 11 | type Counter struct { 12 | maxCount int 13 | count int 14 | mux sync.Mutex 15 | } 16 | 17 | // New returns a new concurrency safe hash map 18 | func New(maxcount int) *Counter { 19 | return &Counter{maxCount: maxcount, count: 0} 20 | } 21 | 22 | // Inc increases the count by one. it returns false if count < maxCount 23 | func (m *Counter) Inc() bool { 24 | m.mux.Lock() 25 | defer m.mux.Unlock() 26 | m.count++ 27 | return m.count >= m.maxCount 28 | } 29 | 30 | // Add increases the count by i. it returns false if count < maxCount 31 | func (m *Counter) Add(i int) bool { 32 | m.mux.Lock() 33 | defer m.mux.Unlock() 34 | m.count += i 35 | if m.count < 0 { 36 | log.Error("counter should never be negative", "counter", m.count) 37 | } 38 | return m.count >= m.maxCount 39 | } 40 | 41 | // Dec decrements the count by one. 42 | func (m *Counter) Dec() { 43 | m.mux.Lock() 44 | defer m.mux.Unlock() 45 | m.count-- 46 | if m.count < 0 { 47 | log.Error("counter should never be negative", "counter", m.count) 48 | } 49 | } 50 | 51 | // Sub decreases the count by i. 52 | func (m *Counter) Sub(i int) { 53 | m.Add(-i) 54 | } 55 | 56 | // Value returns the current value of the counter 57 | func (m *Counter) Value() int { 58 | m.mux.Lock() 59 | defer m.mux.Unlock() 60 | return m.count 61 | } 62 | 63 | // Info returns the current value of the counter and the maxCount 64 | func (m *Counter) Info() (int, int) { 65 | m.mux.Lock() 66 | defer m.mux.Unlock() 67 | return m.count, m.maxCount 68 | } 69 | 70 | // IsFull returns true if count is larger or equal to maxCount. 71 | func (m *Counter) IsFull() bool { 72 | return m.count >= m.maxCount 73 | } 74 | 75 | func (m *Counter) String() string { 76 | return fmt.Sprintf("%d/%d", m.count, m.maxCount) 77 | } 78 | -------------------------------------------------------------------------------- /internal/pkg/datastructures/safeHashMap/safeHashMap.go: -------------------------------------------------------------------------------- 1 | package safeHashMap 2 | 3 | import "sync" 4 | 5 | // Map is a concurrency safe hash map 6 | type Map struct { 7 | hashMap map[string]interface{} 8 | mux sync.RWMutex 9 | } 10 | 11 | // New returns a new concurrency safe hash map 12 | func New() *Map { 13 | return &Map{hashMap: make(map[string]interface{})} 14 | } 15 | 16 | // Add inserts the key value pair to the map. If there is already a mapping it will be overwritten by 17 | // the new value. It returns true if there was not yet a mapping. 18 | func (m *Map) Add(key string, value interface{}) bool { 19 | m.mux.Lock() 20 | defer m.mux.Unlock() 21 | size := len(m.hashMap) 22 | m.hashMap[key] = value 23 | return len(m.hashMap) > size 24 | } 25 | 26 | // GetOrAdd only inserts the key value pair to Map if there has not yet been a mapping for key. It 27 | // first returns the already existing value associated with the key or otherwise the new value. The 28 | // second return value is a boolean value which is true if the mapping has not yet been present. 29 | func (m *Map) GetOrAdd(key string, value interface{}) (interface{}, bool) { 30 | m.mux.Lock() 31 | defer m.mux.Unlock() 32 | v, ok := m.hashMap[key] 33 | if ok { 34 | return v, false 35 | } 36 | m.hashMap[key] = value 37 | return value, true 38 | } 39 | 40 | // Get returns if the key is present the value associated with it from the map and true. Otherwise 41 | // the value type's zero value and false is returned 42 | func (m *Map) Get(key string) (interface{}, bool) { 43 | m.mux.RLock() 44 | defer m.mux.RUnlock() 45 | v, ok := m.hashMap[key] 46 | return v, ok 47 | } 48 | 49 | // GetAll returns all contained values 50 | func (m *Map) GetAll() []interface{} { 51 | m.mux.RLock() 52 | defer m.mux.RUnlock() 53 | values := []interface{}{} 54 | for _, v := range m.hashMap { 55 | values = append(values, v) 56 | } 57 | return values 58 | } 59 | 60 | // GetAllKeys returns all keys 61 | func (m *Map) GetAllKeys() []string { 62 | m.mux.RLock() 63 | defer m.mux.RUnlock() 64 | keys := []string{} 65 | for k := range m.hashMap { 66 | keys = append(keys, k) 67 | } 68 | return keys 69 | } 70 | 71 | // Remove deletes the key value pair from the map. 72 | // It returns the value and true if an element was deleted. Otherwise nil and false 73 | func (m *Map) Remove(key string) (interface{}, bool) { 74 | m.mux.Lock() 75 | defer m.mux.Unlock() 76 | size := len(m.hashMap) 77 | value := m.hashMap[key] 78 | delete(m.hashMap, key) 79 | return value, len(m.hashMap) < size 80 | } 81 | 82 | // Len returns the number of elements in the map 83 | func (m *Map) Len() int { 84 | m.mux.RLock() 85 | defer m.mux.RUnlock() 86 | return len(m.hashMap) 87 | } 88 | -------------------------------------------------------------------------------- /internal/pkg/keyManager/keyManager_test.go: -------------------------------------------------------------------------------- 1 | package keyManager 2 | 3 | import ( 4 | "encoding/pem" 5 | "fmt" 6 | "strings" 7 | "testing" 8 | ) 9 | 10 | func TestGenerateKey(t *testing.T) { 11 | if err := GenerateKey("testdata", "test", "description3", "ed25519", "testPwd", 1); err != nil { 12 | t.Fatal("was not able to generate public keys") 13 | } 14 | if _, err := LoadPublicKeys("testdata"); err != nil { 15 | t.Fatalf("was not able to load public keys: %v", err) 16 | } 17 | if _, err := DecryptKey("testdata", "test_sec.pem", "testPwd"); err != nil { 18 | t.Fatalf("was not able to decrypt private keys: %v", err) 19 | } 20 | } 21 | 22 | func TestLoadPublicKeys(t *testing.T) { 23 | var tests = []struct { 24 | path string 25 | result string 26 | }{ 27 | {"testdata/publicKeyTest", `-----BEGIN RAINS PUBLIC KEY----- 28 | description: description2 29 | keyAlgo: ed25519 30 | keyPhase: 1 31 | 32 | FX4mSFylma5gJKxyipQomDfcG35cykCmF/TVDldpTDo= 33 | -----END RAINS PUBLIC KEY----- 34 | 35 | -----BEGIN RAINS PUBLIC KEY----- 36 | description: description 37 | keyAlgo: ed25519 38 | keyPhase: 1 39 | 40 | 8GjPXoeiLjI8IXtvNQhUJM59FFpZKPF3l+2YorfRWCU= 41 | -----END RAINS PUBLIC KEY----- 42 | `}, 43 | } 44 | 45 | for i, test := range tests { 46 | keys, err := LoadPublicKeys(test.path) 47 | if err != nil { 48 | t.Fatal("was not able to load public keys") 49 | } 50 | val := []string{} 51 | for _, key := range keys { 52 | val = append(val, fmt.Sprintf("%s", pem.EncodeToMemory(key))) 53 | } 54 | if strings.Join(val, "\n") != test.result { 55 | t.Fatalf("%d: Public content is different, expected=%s actual=%s", i, 56 | test.result, strings.Join(val, "\n")) 57 | } 58 | } 59 | } 60 | 61 | func TestDecryptKey(t *testing.T) { 62 | var tests = []struct { 63 | path string 64 | name string 65 | pwd string 66 | result string 67 | }{ 68 | {"testdata/privateKeyTest", "test_sec.pem", "testPwd", `-----BEGIN RAINS ENCRYPTED PRIVATE KEY----- 69 | description: description 70 | iv: 59540bd9d74515e2f33be1ee9cc80dea 71 | keyAlgo: ed25519 72 | keyPhase: 1 73 | salt: d720625555f7b4ad 74 | 75 | ROEfF6uzOsPP20+mADJFpvU6SmHrmUlrdvf62PprS7nwaM9eh6IuMjwhe281CFQk 76 | zn0UWlko8XeX7Ziit9FYJQ== 77 | -----END RAINS ENCRYPTED PRIVATE KEY----- 78 | `}, 79 | {"testdata/privateKeyTest", "test2_sec.pem", "testPwd", `-----BEGIN RAINS ENCRYPTED PRIVATE KEY----- 80 | description: description2 81 | iv: a8bcc983643b3cfbe3781694a43ad90a 82 | keyAlgo: ed25519 83 | keyPhase: 1 84 | salt: 0f6d4d32946fe782 85 | 86 | /i6JnB6qUwgcB+sYs/8cCbIMwCqvq+wBzXxLrZPi+gUVfiZIXKWZrmAkrHKKlCiY 87 | N9wbflzKQKYX9NUOV2lMOg== 88 | -----END RAINS ENCRYPTED PRIVATE KEY----- 89 | `}, 90 | } 91 | for i, test := range tests { 92 | key, err := DecryptKey(test.path, test.name, test.pwd) 93 | if err != nil { 94 | t.Fatalf("%d: was not able to load private keys", i) 95 | } 96 | if fmt.Sprintf("%s", pem.EncodeToMemory(key)) != test.result { 97 | t.Fatalf("%d: Was not able to load public keys, expected=%s actual=%s", i, 98 | test.result, 99 | fmt.Sprintf("%s", pem.EncodeToMemory(key))) 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /internal/pkg/keyManager/testdata/privateKeyTest/test2_sec.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RAINS ENCRYPTED PRIVATE KEY----- 2 | description: description2 3 | iv: a8bcc983643b3cfbe3781694a43ad90a 4 | keyAlgo: ed25519 5 | keyPhase: 1 6 | salt: 0f6d4d32946fe782 7 | 8 | UZ6Rp4mZiJYgtyq/mO2/GppJotEp+CqAx1NsGe9Vz4BQnkeZkL2Nw7Gq9JuR0r6L 9 | xrnwzYHsdS0sI7SO9EY28w== 10 | -----END RAINS ENCRYPTED PRIVATE KEY----- 11 | -------------------------------------------------------------------------------- /internal/pkg/keyManager/testdata/privateKeyTest/test_sec.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RAINS ENCRYPTED PRIVATE KEY----- 2 | description: description 3 | iv: 59540bd9d74515e2f33be1ee9cc80dea 4 | keyAlgo: ed25519 5 | keyPhase: 1 6 | salt: d720625555f7b4ad 7 | 8 | P7881It7WHNlr1RtCAI3FmCqz65JsrYtxSlzbS0+gOUTCUe8moo/cBEx0TKMIyZw 9 | KHM25xISP24iIM6oR1lcEQ== 10 | -----END RAINS ENCRYPTED PRIVATE KEY----- 11 | -------------------------------------------------------------------------------- /internal/pkg/keyManager/testdata/publicKeyTest/test2_pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RAINS PUBLIC KEY----- 2 | description: description2 3 | keyAlgo: ed25519 4 | keyPhase: 1 5 | 6 | FX4mSFylma5gJKxyipQomDfcG35cykCmF/TVDldpTDo= 7 | -----END RAINS PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /internal/pkg/keyManager/testdata/publicKeyTest/test_pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RAINS PUBLIC KEY----- 2 | description: description 3 | keyAlgo: ed25519 4 | keyPhase: 1 5 | 6 | 8GjPXoeiLjI8IXtvNQhUJM59FFpZKPF3l+2YorfRWCU= 7 | -----END RAINS PUBLIC KEY----- 8 | -------------------------------------------------------------------------------- /internal/pkg/keys/keys.go: -------------------------------------------------------------------------------- 1 | package keys 2 | 3 | import ( 4 | "bytes" 5 | "encoding/hex" 6 | "fmt" 7 | 8 | log "github.com/inconshreveable/log15" 9 | 10 | "github.com/netsec-ethz/rains/internal/pkg/algorithmTypes" 11 | "golang.org/x/crypto/ed25519" 12 | ) 13 | 14 | // PublicKeyID contains all necessary information to distinguish different public keys from the same 15 | // authority 16 | type PublicKeyID struct { 17 | //Algorithm determines the signature algorithm to be used for signing and verification 18 | Algorithm algorithmTypes.Signature 19 | //KeySpace is an identifier of a key space 20 | KeySpace KeySpaceID 21 | //KeyPhase defines the keyPhase in which this public key is valid 22 | KeyPhase int 23 | } 24 | 25 | func (p PublicKeyID) String() string { 26 | return fmt.Sprintf("AT=%s KS=%s KP=%d", p.Algorithm, p.KeySpace, p.KeyPhase) 27 | } 28 | 29 | // Hash returns a string containing all information uniquely identifying a public key ID. 30 | func (p PublicKeyID) Hash() string { 31 | return fmt.Sprintf("%d,%d,%d", p.Algorithm, p.KeySpace, p.KeyPhase) 32 | } 33 | 34 | // PublicKey contains information about a public key 35 | type PublicKey struct { 36 | PublicKeyID 37 | ValidSince int64 38 | ValidUntil int64 39 | Key interface{} 40 | } 41 | 42 | // CompareTo compares two publicKey objects and returns 0 if they are equal, 1 if p is greater than 43 | // pkey and -1 if p is smaller than pkey 44 | func (p PublicKey) CompareTo(pkey PublicKey) int { 45 | if p.Algorithm < pkey.Algorithm { 46 | return -1 47 | } else if p.Algorithm > pkey.Algorithm { 48 | return 1 49 | } else if p.KeySpace < pkey.KeySpace { 50 | return -1 51 | } else if p.KeySpace > pkey.KeySpace { 52 | return 1 53 | } else if p.ValidSince < pkey.ValidSince { 54 | return -1 55 | } else if p.ValidSince > pkey.ValidSince { 56 | return 1 57 | } else if p.ValidUntil < pkey.ValidUntil { 58 | return -1 59 | } else if p.ValidUntil > pkey.ValidUntil { 60 | return 1 61 | } else if p.KeyPhase < pkey.KeyPhase { 62 | return -1 63 | } else if p.KeyPhase > pkey.KeyPhase { 64 | return 1 65 | } 66 | switch k1 := p.Key.(type) { 67 | case ed25519.PublicKey: 68 | if k2, ok := pkey.Key.(ed25519.PublicKey); ok { 69 | return bytes.Compare(k1, k2) 70 | } 71 | log.Error("PublicKey.Key Type does not match algorithmIdType", "algoType", pkey.Algorithm, "KeyType", fmt.Sprintf("%T", pkey.Key)) 72 | default: 73 | log.Warn("Unsupported public key type", "type", fmt.Sprintf("%T", p.Key)) 74 | } 75 | return 0 76 | } 77 | 78 | // String implements Stringer interface 79 | func (p PublicKey) String() string { 80 | keyString := "" 81 | switch k1 := p.Key.(type) { 82 | case ed25519.PublicKey: 83 | keyString = hex.EncodeToString(k1) 84 | default: 85 | log.Warn("Unsupported public key type", "type", fmt.Sprintf("%T", p.Key)) 86 | } 87 | return fmt.Sprintf("{%s VS=%d VU=%d data=%s}", p.PublicKeyID, p.ValidSince, p.ValidUntil, keyString) 88 | } 89 | 90 | // Hash returns a string containing all information uniquely identifying a public key. 91 | func (p PublicKey) Hash() string { 92 | keyString := "" 93 | switch k1 := p.Key.(type) { 94 | case ed25519.PublicKey: 95 | keyString = hex.EncodeToString(k1) 96 | default: 97 | log.Warn("Unsupported public key type", "type", fmt.Sprintf("%T", p.Key)) 98 | } 99 | return fmt.Sprintf("%s,%d,%d,%s", p.PublicKeyID.Hash(), p.ValidSince, p.ValidUntil, keyString) 100 | } 101 | 102 | // KeySpaceID identifies a key space 103 | type KeySpaceID int 104 | 105 | //go:generate stringer -type=KeySpaceID 106 | //go:generate jsonenums -type=KeySpaceID 107 | const ( 108 | RainsKeySpace KeySpaceID = 0 109 | ) 110 | -------------------------------------------------------------------------------- /internal/pkg/keys/keyspaceid_jsonenums.go: -------------------------------------------------------------------------------- 1 | // generated by jsonenums -type=KeySpaceID; DO NOT EDIT 2 | 3 | package keys 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | ) 9 | 10 | var ( 11 | _KeySpaceIDNameToValue = map[string]KeySpaceID{ 12 | "RainsKeySpace": RainsKeySpace, 13 | } 14 | 15 | _KeySpaceIDValueToName = map[KeySpaceID]string{ 16 | RainsKeySpace: "RainsKeySpace", 17 | } 18 | ) 19 | 20 | func init() { 21 | var v KeySpaceID 22 | if _, ok := interface{}(v).(fmt.Stringer); ok { 23 | _KeySpaceIDNameToValue = map[string]KeySpaceID{ 24 | interface{}(RainsKeySpace).(fmt.Stringer).String(): RainsKeySpace, 25 | } 26 | } 27 | } 28 | 29 | // MarshalJSON is generated so KeySpaceID satisfies json.Marshaler. 30 | func (r KeySpaceID) MarshalJSON() ([]byte, error) { 31 | if s, ok := interface{}(r).(fmt.Stringer); ok { 32 | return json.Marshal(s.String()) 33 | } 34 | s, ok := _KeySpaceIDValueToName[r] 35 | if !ok { 36 | return nil, fmt.Errorf("invalid KeySpaceID: %d", r) 37 | } 38 | return json.Marshal(s) 39 | } 40 | 41 | // UnmarshalJSON is generated so KeySpaceID satisfies json.Unmarshaler. 42 | func (r *KeySpaceID) UnmarshalJSON(data []byte) error { 43 | var s string 44 | if err := json.Unmarshal(data, &s); err != nil { 45 | return fmt.Errorf("KeySpaceID should be a string, got %s", data) 46 | } 47 | v, ok := _KeySpaceIDNameToValue[s] 48 | if !ok { 49 | return fmt.Errorf("invalid KeySpaceID %q", s) 50 | } 51 | *r = v 52 | return nil 53 | } 54 | -------------------------------------------------------------------------------- /internal/pkg/keys/keyspaceid_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=KeySpaceID"; DO NOT EDIT. 2 | 3 | package keys 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[RainsKeySpace-0] 12 | } 13 | 14 | const _KeySpaceID_name = "RainsKeySpace" 15 | 16 | var _KeySpaceID_index = [...]uint8{0, 13} 17 | 18 | func (i KeySpaceID) String() string { 19 | if i < 0 || i >= KeySpaceID(len(_KeySpaceID_index)-1) { 20 | return "KeySpaceID(" + strconv.FormatInt(int64(i), 10) + ")" 21 | } 22 | return _KeySpaceID_name[_KeySpaceID_index[i]:_KeySpaceID_index[i+1]] 23 | } 24 | -------------------------------------------------------------------------------- /internal/pkg/libresolve/resolver_test.go: -------------------------------------------------------------------------------- 1 | package libresolve 2 | 3 | import ( 4 | "net" 5 | "strings" 6 | "testing" 7 | "time" 8 | 9 | "github.com/netsec-ethz/rains/internal/pkg/message" 10 | "github.com/netsec-ethz/rains/internal/pkg/section" 11 | 12 | "github.com/netsec-ethz/rains/internal/pkg/object" 13 | "github.com/netsec-ethz/rains/internal/pkg/query" 14 | 15 | "github.com/netsec-ethz/rains/internal/pkg/cache" 16 | "github.com/netsec-ethz/rains/internal/pkg/datastructures/safeHashMap" 17 | "github.com/netsec-ethz/rains/internal/pkg/util" 18 | ) 19 | 20 | func newResolver() *Resolver { 21 | return &Resolver{ 22 | RootNameServers: []net.Addr{}, 23 | Forwarders: []net.Addr{}, 24 | Mode: Recursive, 25 | InsecureTLS: defaultInsecureTLS, 26 | DialTimeout: defaultTimeout, 27 | FailFast: defaultFailFast, 28 | Delegations: safeHashMap.New(), 29 | Connections: cache.NewConnection(1), 30 | MaxCacheValidity: util.MaxCacheValidity{ 31 | AssertionValidity: 100, 32 | ShardValidity: 100, 33 | PshardValidity: 100, 34 | ZoneValidity: 100, 35 | }, 36 | MaxRecursiveCount: 1, 37 | } 38 | } 39 | 40 | func newQuery() *query.Name { 41 | return &query.Name{ 42 | Context: "", 43 | Name: "", 44 | Types: []object.Type{object.OTName}, 45 | Expiration: 100, 46 | Options: []query.Option{}, 47 | KeyPhase: 1, 48 | CurrentTime: 10, 49 | } 50 | } 51 | 52 | func TestRecursiveResolveMaxDepth(t *testing.T) { 53 | resolver := newResolver() 54 | q := newQuery() 55 | _, err := resolver.recursiveResolve(q, 1) 56 | if err == nil { 57 | t.Error("Should fail because max recursion depth is 1") 58 | } else if !strings.HasPrefix(err.Error(), "Maximum number of recursive calls") { 59 | t.Errorf("Unexpected error not about max. recursive calls. This is the error: %v", err) 60 | } 61 | _, err = resolver.recursiveResolve(q, 0) 62 | if err == nil || strings.HasPrefix(err.Error(), "Maximum number of recursive calls") { 63 | t.Errorf("Unexpected error about max. recursive calls. This is the error: %v", err) 64 | } 65 | } 66 | 67 | func TestRecursiveResolveQueriesRoot(t *testing.T) { 68 | assertion := section.Assertion{SubjectZone: ".", SubjectName: "ch"} 69 | resolver := newResolver() 70 | resolver.RootNameServers = []net.Addr{&net.IPAddr{IP: net.IPv4(127, 0, 0, 11), Zone: "test-zone"}} 71 | numberOfMessagesSent := 0 72 | resolver.sendQuery = func(msg message.Message, addr net.Addr, timeout time.Duration) (message.Message, error) { 73 | if ipAddr, ok := addr.(*net.IPAddr); !ok || !ipAddr.IP.Equal(net.IPv4(127, 0, 0, 11)) || ipAddr.Zone != "test-zone" { 74 | t.Fatalf("Resolver contacted some other server at %v", ipAddr) 75 | } 76 | numberOfMessagesSent++ 77 | return message.Message{Content: []section.Section{&assertion}}, nil 78 | } 79 | resolver.handleAnswer = func(r *Resolver, msg message.Message, q *query.Name, recurseCount int) ( 80 | isFinal bool, isRedir bool, redirMap map[string]string, srvMap map[string]object.ServiceInfo, 81 | ipMap map[string]string, nameMap map[string]object.Name) { 82 | isFinal = true 83 | return 84 | } 85 | q := newQuery() 86 | ans, err := resolver.recursiveResolve(q, 0) 87 | if err != nil { 88 | t.Fatalf("The call to recursiveResolve finished with an error: %v", err) 89 | } 90 | if len(ans.Content) != 1 || ans.Content[0].(*section.Assertion) == nil || ans.Content[0].(*section.Assertion).FQDN() != assertion.FQDN() { 91 | t.Fatalf("Wrong answer received, FQDN: %q", assertion.FQDN()) 92 | } 93 | if numberOfMessagesSent != 1 { 94 | t.Fatalf("Should have contacted 1 root server, but did it %d times", numberOfMessagesSent) 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /internal/pkg/lruCache/lruCache.go: -------------------------------------------------------------------------------- 1 | package lruCache 2 | 3 | import ( 4 | "container/list" 5 | "sync" 6 | 7 | log "github.com/inconshreveable/log15" 8 | ) 9 | 10 | // Cache is a LRU cache where some elements are not subject to the LRU removal strategy. This cache is safe for concurrent use. 11 | type Cache struct { 12 | mux sync.RWMutex 13 | 14 | internalList *list.List //values in the internalList are only explicitly removed 15 | lruList *list.List 16 | hashMap map[string]*list.Element 17 | } 18 | 19 | type entry struct { 20 | internal bool 21 | key string 22 | value interface{} 23 | } 24 | 25 | // New returns a freshly created cache with all its internal structures initialized 26 | func New() *Cache { 27 | cache := Cache{ 28 | internalList: list.New(), 29 | lruList: list.New(), 30 | hashMap: make(map[string]*list.Element), 31 | } 32 | return &cache 33 | } 34 | 35 | // GetOrAdd only inserts the key value pair to Cache if there has not yet been a mapping for key. It 36 | // first returns the already existing value associated with the key or otherwise the new value. The 37 | // second return value is a boolean value which is true if the mapping has not yet been present. 38 | func (c *Cache) GetOrAdd(key string, value interface{}, isInternal bool) (interface{}, bool) { 39 | c.mux.Lock() 40 | defer c.mux.Unlock() 41 | e, ok := c.hashMap[key] 42 | if ok { 43 | if e == nil { 44 | log.Error("A list element returned by the hash map is nil. This should never occur!") 45 | } 46 | v := e.Value.(*entry) 47 | if v.internal { 48 | c.internalList.MoveToFront(e) 49 | } else { 50 | c.lruList.MoveToFront(e) 51 | } 52 | return v.value, false 53 | } 54 | if isInternal { 55 | e = c.internalList.PushFront(&entry{internal: true, key: key, value: value}) 56 | } else { 57 | e = c.lruList.PushFront(&entry{internal: false, key: key, value: value}) 58 | } 59 | c.hashMap[key] = e 60 | return value, true 61 | } 62 | 63 | // Get returns if the key is present the value associated with it from the map and true. Otherwise 64 | // the value type's zero value and false is returned 65 | func (c *Cache) Get(key string) (interface{}, bool) { 66 | c.mux.RLock() 67 | defer c.mux.RUnlock() 68 | v, ok := c.hashMap[key] 69 | if ok { 70 | e := v.Value.(*entry) 71 | if e.internal { 72 | c.internalList.MoveToFront(v) 73 | } else { 74 | c.lruList.MoveToFront(v) 75 | } 76 | return e.value, true 77 | } 78 | return nil, false 79 | } 80 | 81 | // GetAll returns all contained values. It does not affect lru list order. 82 | func (c *Cache) GetAll() []interface{} { 83 | c.mux.RLock() 84 | defer c.mux.RUnlock() 85 | values := []interface{}{} 86 | for _, v := range c.hashMap { 87 | values = append(values, v.Value.(*entry).value) 88 | } 89 | return values 90 | } 91 | 92 | // Remove deletes the key value pair from the map. 93 | // It returns the value and true if an element was deleted. Otherwise the value and false. 94 | func (c *Cache) Remove(key string) (interface{}, bool) { 95 | c.mux.Lock() 96 | defer c.mux.Unlock() 97 | e, ok := c.hashMap[key] 98 | if !ok { 99 | return nil, false 100 | } 101 | delete(c.hashMap, key) 102 | v := e.Value.(*entry) 103 | if v.internal { 104 | c.internalList.Remove(e) 105 | } else { 106 | c.lruList.Remove(e) 107 | } 108 | return v.value, true 109 | } 110 | 111 | // GetLeastRecentlyUsed returns the least recently used key value pair. It does not update the 112 | // recentness of the element 113 | func (c *Cache) GetLeastRecentlyUsed() (string, interface{}) { 114 | c.mux.RLock() 115 | defer c.mux.RUnlock() 116 | e := c.lruList.Back() 117 | if e != nil { 118 | v := e.Value.(*entry) 119 | return v.key, v.value 120 | } 121 | return "", nil 122 | } 123 | 124 | // Len returns the number of elements in the cache 125 | func (c *Cache) Len() int { 126 | c.mux.RLock() 127 | defer c.mux.RUnlock() 128 | return len(c.hashMap) 129 | } 130 | -------------------------------------------------------------------------------- /internal/pkg/message/testData.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | import ( 4 | "github.com/netsec-ethz/rains/internal/pkg/algorithmTypes" 5 | "github.com/netsec-ethz/rains/internal/pkg/keys" 6 | "github.com/netsec-ethz/rains/internal/pkg/object" 7 | "github.com/netsec-ethz/rains/internal/pkg/query" 8 | "github.com/netsec-ethz/rains/internal/pkg/section" 9 | "github.com/netsec-ethz/rains/internal/pkg/signature" 10 | "github.com/netsec-ethz/rains/internal/pkg/token" 11 | ) 12 | 13 | const ( 14 | testDomain = "example.com" 15 | testZone = "com" 16 | testSubjectName = "example" 17 | globalContext = "." 18 | ) 19 | 20 | // GetMessage returns a messages containing all The assertion contains an instance of every object.Types 21 | func GetMessage() Message { 22 | sig := signature.Sig{ 23 | PublicKeyID: keys.PublicKeyID{ 24 | KeySpace: keys.RainsKeySpace, 25 | Algorithm: algorithmTypes.Ed25519, 26 | }, 27 | ValidSince: 1000, 28 | ValidUntil: 2000, 29 | Data: []byte("SignatureData")} 30 | 31 | assertion := §ion.Assertion{ 32 | Content: object.AllObjects(), 33 | Context: globalContext, 34 | SubjectName: testSubjectName, 35 | SubjectZone: testSubjectName, 36 | Signatures: []signature.Sig{sig}, 37 | } 38 | 39 | aWithoutSig := §ion.Assertion{ 40 | Content: object.AllObjects(), 41 | Context: globalContext, 42 | SubjectName: testSubjectName, 43 | SubjectZone: testSubjectName, 44 | } 45 | 46 | shard := §ion.Shard{ 47 | Content: []*section.Assertion{assertion, aWithoutSig}, 48 | Context: globalContext, 49 | SubjectZone: testSubjectName, 50 | RangeFrom: "aaa", 51 | RangeTo: "zzz", 52 | Signatures: []signature.Sig{sig}, 53 | } 54 | 55 | pshard := §ion.Pshard{ 56 | Context: globalContext, 57 | SubjectZone: testSubjectName, 58 | RangeFrom: "aaa", 59 | RangeTo: "zzz", 60 | Signatures: []signature.Sig{sig}, 61 | } 62 | 63 | zone := §ion.Zone{ 64 | Content: []*section.Assertion{assertion, aWithoutSig}, 65 | Context: globalContext, 66 | SubjectZone: testSubjectName, 67 | Signatures: []signature.Sig{sig}, 68 | } 69 | 70 | q := &query.Name{ 71 | Context: globalContext, 72 | Expiration: 159159, 73 | Name: testDomain, 74 | Options: []query.Option{query.QOMinE2ELatency, query.QOMinInfoLeakage}, 75 | Types: []object.Type{object.OTIP4Addr}, 76 | } 77 | 78 | notification := §ion.Notification{ 79 | Token: token.New(), 80 | Type: section.NTNoAssertionsExist, 81 | Data: "Notification information", 82 | } 83 | 84 | message := Message{ 85 | Content: []section.Section{ 86 | assertion, 87 | shard, 88 | zone, 89 | q, 90 | notification, 91 | pshard, 92 | }, 93 | Token: token.New(), 94 | Capabilities: []Capability{Capability("Test"), Capability("Yes!")}, 95 | Signatures: []signature.Sig{sig}, 96 | } 97 | return message 98 | } 99 | -------------------------------------------------------------------------------- /internal/pkg/object/certificateusage_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=CertificateUsage"; DO NOT EDIT. 2 | 3 | package object 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[CUTrustAnchor-2] 12 | _ = x[CUEndEntity-3] 13 | } 14 | 15 | const _CertificateUsage_name = "CUTrustAnchorCUEndEntity" 16 | 17 | var _CertificateUsage_index = [...]uint8{0, 13, 24} 18 | 19 | func (i CertificateUsage) String() string { 20 | i -= 2 21 | if i < 0 || i >= CertificateUsage(len(_CertificateUsage_index)-1) { 22 | return "CertificateUsage(" + strconv.FormatInt(int64(i+2), 10) + ")" 23 | } 24 | return _CertificateUsage_name[_CertificateUsage_index[i]:_CertificateUsage_index[i+1]] 25 | } 26 | -------------------------------------------------------------------------------- /internal/pkg/object/protocoltype_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=ProtocolType"; DO NOT EDIT. 2 | 3 | package object 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[PTUnspecified-0] 12 | _ = x[PTTLS-1] 13 | } 14 | 15 | const _ProtocolType_name = "PTUnspecifiedPTTLS" 16 | 17 | var _ProtocolType_index = [...]uint8{0, 13, 18} 18 | 19 | func (i ProtocolType) String() string { 20 | if i < 0 || i >= ProtocolType(len(_ProtocolType_index)-1) { 21 | return "ProtocolType(" + strconv.FormatInt(int64(i), 10) + ")" 22 | } 23 | return _ProtocolType_name[_ProtocolType_index[i]:_ProtocolType_index[i+1]] 24 | } 25 | -------------------------------------------------------------------------------- /internal/pkg/object/type_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=Type"; DO NOT EDIT. 2 | 3 | package object 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[OTName-1] 12 | _ = x[OTIP6Addr-2] 13 | _ = x[OTIP4Addr-3] 14 | _ = x[OTRedirection-4] 15 | _ = x[OTDelegation-5] 16 | _ = x[OTNameset-6] 17 | _ = x[OTCertInfo-7] 18 | _ = x[OTServiceInfo-8] 19 | _ = x[OTRegistrar-9] 20 | _ = x[OTRegistrant-10] 21 | _ = x[OTInfraKey-11] 22 | _ = x[OTExtraKey-12] 23 | _ = x[OTNextKey-13] 24 | _ = x[OTScionAddr-14] 25 | } 26 | 27 | const _Type_name = "OTNameOTIP6AddrOTIP4AddrOTRedirectionOTDelegationOTNamesetOTCertInfoOTServiceInfoOTRegistrarOTRegistrantOTInfraKeyOTExtraKeyOTNextKeyOTScionAddr" 28 | 29 | var _Type_index = [...]uint8{0, 6, 15, 24, 37, 49, 58, 68, 81, 92, 104, 114, 124, 133, 144} 30 | 31 | func (i Type) String() string { 32 | i -= 1 33 | if i < 0 || i >= Type(len(_Type_index)-1) { 34 | return "Type(" + strconv.FormatInt(int64(i+1), 10) + ")" 35 | } 36 | return _Type_name[_Type_index[i]:_Type_index[i+1]] 37 | } 38 | -------------------------------------------------------------------------------- /internal/pkg/publisher/README.md: -------------------------------------------------------------------------------- 1 | # Zone publisher 2 | 3 | ## Input 4 | 5 | Config and a zonefile. The zonefile MUST contain a zone. It MAY contain shards and pshards. Either 6 | the present shards and pshards are used or they are discarded and new shards and pshards are created 7 | based on the zone's content. -------------------------------------------------------------------------------- /internal/pkg/publisher/publisherConfig.go: -------------------------------------------------------------------------------- 1 | package publisher 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/netsec-ethz/rains/internal/pkg/algorithmTypes" 7 | "github.com/netsec-ethz/rains/internal/pkg/connection" 8 | "github.com/netsec-ethz/rains/internal/pkg/section" 9 | ) 10 | 11 | // Config lists configurations for publishing zone information, see zonepub flag description for 12 | // detail. 13 | type Config struct { 14 | ZonefilePath string 15 | AuthServers []connection.Info 16 | PrivateKeyPath string 17 | ShardingConf ShardingConfig 18 | PShardingConf PShardingConfig 19 | MetaDataConf MetaDataConfig 20 | ConsistencyConf ConsistencyConfig 21 | DoSigning bool 22 | MaxZoneSize int 23 | OutputPath string 24 | DoPublish bool 25 | } 26 | 27 | // ShardingConfig contains configuration options on how to split a zone into shards. 28 | type ShardingConfig struct { 29 | KeepShards bool 30 | DoSharding bool 31 | NofAssertionsPerShard int 32 | MaxShardSize int 33 | } 34 | 35 | // PShardingConfig contains configuration options on how to split a zone into probabilistic shards. 36 | type PShardingConfig struct { 37 | KeepPshards bool 38 | DoPsharding bool 39 | NofAssertionsPerPshard int 40 | BloomFilterConf BloomFilterConfig 41 | } 42 | 43 | // BloomFilterConfig specifies the bloom filter's meta data 44 | type BloomFilterConfig struct { 45 | BFAlgo section.BloomFilterAlgo 46 | BFHash algorithmTypes.Hash 47 | BloomFilterSize int 48 | } 49 | 50 | // MetaDataConfig determines how the signature meta data is generated and to which section(s) it is 51 | // added. 52 | type MetaDataConfig struct { 53 | AddSignatureMetaData bool 54 | AddSigMetaDataToAssertions bool 55 | AddSigMetaDataToShards bool 56 | AddSigMetaDataToPshards bool 57 | SignatureAlgorithm algorithmTypes.Signature 58 | KeyPhase int 59 | SigValidSince int64 60 | SigValidUntil int64 61 | SigSigningInterval time.Duration 62 | } 63 | 64 | // ConsistencyConfig determines which consistency checks are performed prior to signing. 65 | type ConsistencyConfig struct { 66 | DoConsistencyCheck bool 67 | SortShards bool 68 | SortZone bool 69 | SigNotExpired bool 70 | CheckStringFields bool 71 | } 72 | 73 | // DefaultConfig return the default configuration for the zone publisher. 74 | func DefaultConfig() Config { 75 | return Config{ 76 | ZonefilePath: "data/zonefiles/zf.txt", 77 | AuthServers: []connection.Info{}, 78 | PrivateKeyPath: "data/keys/key_sec.pem", 79 | ShardingConf: ShardingConfig{ 80 | DoSharding: true, 81 | KeepShards: false, 82 | MaxShardSize: 1000, 83 | NofAssertionsPerShard: -1, 84 | }, 85 | PShardingConf: PShardingConfig{ 86 | DoPsharding: true, 87 | KeepPshards: false, 88 | NofAssertionsPerPshard: 50, 89 | BloomFilterConf: BloomFilterConfig{ 90 | BFAlgo: section.BloomKM12, 91 | BFHash: algorithmTypes.Shake256, 92 | BloomFilterSize: 200, 93 | }, 94 | }, 95 | MetaDataConf: MetaDataConfig{ 96 | AddSignatureMetaData: true, 97 | AddSigMetaDataToAssertions: true, 98 | AddSigMetaDataToShards: true, 99 | AddSigMetaDataToPshards: true, 100 | SignatureAlgorithm: algorithmTypes.Ed25519, 101 | KeyPhase: 0, 102 | SigValidSince: time.Now().Unix(), 103 | SigValidUntil: time.Now().Add(24 * time.Hour).Unix(), 104 | SigSigningInterval: time.Minute, 105 | }, 106 | ConsistencyConf: ConsistencyConfig{ 107 | DoConsistencyCheck: true, 108 | SortShards: false, 109 | SortZone: false, 110 | SigNotExpired: false, 111 | CheckStringFields: false, 112 | }, 113 | DoSigning: true, 114 | MaxZoneSize: 60000, 115 | OutputPath: "", 116 | DoPublish: true, 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /internal/pkg/publisher/publisherConn.go: -------------------------------------------------------------------------------- 1 | package publisher 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "time" 7 | 8 | log "github.com/inconshreveable/log15" 9 | "github.com/netsec-ethz/rains/internal/pkg/connection" 10 | "github.com/netsec-ethz/rains/internal/pkg/message" 11 | "github.com/netsec-ethz/rains/internal/pkg/section" 12 | ) 13 | 14 | // connectAndSendMsg establishes a connection to server and sends msg. It returns the server info on 15 | // the result channel if it was not able to send the whole msg to it, else nil. 16 | func connectAndSendMsg(msg message.Message, server net.Addr) error { 17 | 18 | conn, err := connection.CreateConnection(server) 19 | if err != nil { 20 | return fmt.Errorf("unable to establish a connection: %s", err) 21 | } 22 | defer conn.Close() 23 | err = connection.WriteMessage(conn, &msg) 24 | if err != nil { 25 | return fmt.Errorf("unable send message: %s", err) 26 | } 27 | 28 | // Wait 1 second for reply 29 | deadline := time.Now().Add(1 * time.Second) 30 | conn.SetReadDeadline(deadline) 31 | for deadline.After(time.Now()) { 32 | replyMsg, err := connection.ReceiveMessage(conn) 33 | if err != nil { 34 | return fmt.Errorf("error receiving message: %s", err) 35 | } 36 | //only accept notification messages in response to published information. 37 | if n, ok := replyMsg.Content[0].(*section.Notification); ok && n.Token == msg.Token { 38 | if handleResponse(msg.Content[0].(*section.Notification)) { 39 | return nil 40 | } 41 | } 42 | } 43 | return fmt.Errorf("timeout while waiting for response") 44 | } 45 | 46 | // handleResponse handles the received notification message and returns true if the connection can 47 | // be closed. 48 | func handleResponse(n *section.Notification) bool { 49 | switch n.Type { 50 | case section.NTHeartbeat, section.NTNoAssertionsExist, section.NTNoAssertionAvail: 51 | //nop 52 | case section.NTCapHashNotKnown: 53 | //TODO CFE send back the whole capability list in an empty message 54 | case section.NTBadMessage: 55 | log.Error("Sent msg was malformed", "data", n.Data) 56 | case section.NTRcvInconsistentMsg: 57 | log.Error("Sent msg was inconsistent", "data", n.Data) 58 | case section.NTMsgTooLarge: 59 | log.Error("Sent msg was too large", "data", n.Data) 60 | //What should we do in this case. apparently it is not possible to send a zone because 61 | //it is too large. send shards instead? 62 | case section.NTUnspecServerErr: 63 | log.Error("Unspecified error of other server", "data", n.Data) 64 | //TODO CFE resend? 65 | case section.NTServerNotCapable: 66 | log.Error("Other server was not capable", "data", n.Data) 67 | //TODO CFE when can this occur? 68 | default: 69 | log.Error("Received non existing notification type") 70 | } 71 | return false 72 | } 73 | -------------------------------------------------------------------------------- /internal/pkg/publisher/publisherUtil.go: -------------------------------------------------------------------------------- 1 | package publisher 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | "io/ioutil" 8 | "strings" 9 | "time" 10 | 11 | log "github.com/inconshreveable/log15" 12 | "github.com/netsec-ethz/rains/internal/pkg/keyManager" 13 | "github.com/netsec-ethz/rains/internal/pkg/keys" 14 | ) 15 | 16 | // LoadConfig loads configuration information from configPath 17 | func LoadConfig(configPath string) (Config, error) { 18 | var config Config 19 | file, err := ioutil.ReadFile(configPath) 20 | if err != nil { 21 | log.Error("Could not open config file...", "path", configPath, "error", err) 22 | return Config{}, err 23 | } 24 | if err = json.Unmarshal(file, &config); err != nil { 25 | log.Error("Could not unmarshal json format of config", "error", err) 26 | return Config{}, err 27 | } 28 | config.MetaDataConf.SigSigningInterval *= time.Second 29 | return config, nil 30 | } 31 | 32 | // LoadPrivateKeys reads private keys from the path provided in the config and returns a map from 33 | // PublicKeyID to the corresponding private key data. 34 | func LoadPrivateKeys(path string) (map[keys.PublicKeyID]interface{}, error) { 35 | output := make(map[keys.PublicKeyID]interface{}) 36 | files, err := ioutil.ReadDir(path) 37 | if err != nil { 38 | return nil, fmt.Errorf("Was not able to read directory: %v", err) 39 | } 40 | for _, f := range files { 41 | if strings.HasSuffix(f.Name(), keyManager.SecSuffix) { 42 | keyPem, err := keyManager.DecryptKey(path, f.Name(), "") 43 | if err != nil { 44 | return nil, fmt.Errorf("Was not able to decrypt key: %v", err) 45 | } 46 | keyID, pkey, err := keyManager.PemToKeyID(keyPem) 47 | if err != nil { 48 | return nil, fmt.Errorf("Was not able to decode pem encoded private key: %v", err) 49 | } 50 | if _, ok := output[keyID]; ok { 51 | return nil, errors.New("Two keys for the same key meta data are not allowed") 52 | } 53 | output[keyID] = pkey 54 | } 55 | } 56 | return output, nil 57 | } 58 | -------------------------------------------------------------------------------- /internal/pkg/publisher/test/malformed.conf: -------------------------------------------------------------------------------- 1 | { 2 | "AssertionValidit": 86400 3 | -------------------------------------------------------------------------------- /internal/pkg/publisher/test/zonePrivate.key: -------------------------------------------------------------------------------- 1 | 80e1a328b908c2d6c2f10659355b15618ead2e42acf1dfcf39488fc7006c444e2245137bcb058f799843bb8c6df31927b547e4951142b99ae97c668b076e9d84 -------------------------------------------------------------------------------- /internal/pkg/publisher/test/zonePrivateWrongSize.key: -------------------------------------------------------------------------------- 1 | 80e1a328b908c2d6c2f10659355b15618ead2e42acf1dfcf39488fc7006c444e2245137bcb058f799843bb8c6df31927b547e4951142b99ae97c668b076e9d8480 -------------------------------------------------------------------------------- /internal/pkg/query/option_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=Option"; DO NOT EDIT. 2 | 3 | package query 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[QOMinE2ELatency-1] 12 | _ = x[QOMinLastHopAnswerSize-2] 13 | _ = x[QOMinInfoLeakage-3] 14 | _ = x[QOCachedAnswersOnly-4] 15 | _ = x[QOExpiredAssertionsOk-5] 16 | _ = x[QOTokenTracing-6] 17 | _ = x[QONoVerificationDelegation-7] 18 | _ = x[QONoProactiveCaching-8] 19 | _ = x[QOMaxFreshness-9] 20 | } 21 | 22 | const _Option_name = "QOMinE2ELatencyQOMinLastHopAnswerSizeQOMinInfoLeakageQOCachedAnswersOnlyQOExpiredAssertionsOkQOTokenTracingQONoVerificationDelegationQONoProactiveCachingQOMaxFreshness" 23 | 24 | var _Option_index = [...]uint8{0, 15, 37, 53, 72, 93, 107, 133, 153, 167} 25 | 26 | func (i Option) String() string { 27 | i -= 1 28 | if i < 0 || i >= Option(len(_Option_index)-1) { 29 | return "Option(" + strconv.FormatInt(int64(i+1), 10) + ")" 30 | } 31 | return _Option_name[_Option_index[i]:_Option_index[i+1]] 32 | } 33 | -------------------------------------------------------------------------------- /internal/pkg/query/query_test.go: -------------------------------------------------------------------------------- 1 | package query 2 | 3 | import ( 4 | "math/rand" 5 | "reflect" 6 | "sort" 7 | "strconv" 8 | "testing" 9 | 10 | "github.com/netsec-ethz/rains/internal/pkg/object" 11 | ) 12 | 13 | func TestContainsOptions(t *testing.T) { 14 | var tests = []struct { 15 | input []Option 16 | param Option 17 | want bool 18 | }{ 19 | {[]Option{QOCachedAnswersOnly, QOExpiredAssertionsOk}, QOCachedAnswersOnly, true}, 20 | {[]Option{QOCachedAnswersOnly, QOExpiredAssertionsOk}, QOExpiredAssertionsOk, true}, 21 | {[]Option{}, QOCachedAnswersOnly, false}, 22 | {[]Option{QOExpiredAssertionsOk}, QOCachedAnswersOnly, false}, 23 | } 24 | for i, test := range tests { 25 | if containsOption(test.param, test.input) != test.want { 26 | t.Errorf("%d: containsOptions response incorrect. expected=%v, actual=%v", i, test.want, containsOption(test.param, test.input)) 27 | } 28 | query := &Name{Options: test.input} 29 | if query.ContainsOption(test.param) != test.want { 30 | t.Errorf("%d: ContainsOptions response incorrect. expected=%v, actual=%v", i, test.want, containsOption(test.param, test.input)) 31 | } 32 | } 33 | } 34 | 35 | func TestQuerySort(t *testing.T) { 36 | var tests = []struct { 37 | input []Option 38 | sorted []Option 39 | }{ 40 | {[]Option{Option(5), Option(3)}, []Option{Option(3), Option(5)}}, 41 | } 42 | for i, test := range tests { 43 | q := &Name{Options: test.input} 44 | q.Sort() 45 | if !reflect.DeepEqual(q.Options, test.sorted) { 46 | t.Errorf("%d: Sort() does not sort correctly expected=%v actual=%v", i, test.sorted, q.Options) 47 | } 48 | } 49 | } 50 | 51 | func TestQueryCompareTo(t *testing.T) { 52 | queries := sortedQueries(5) 53 | shuffled := append([]*Name{}, queries...) 54 | for i := len(shuffled) - 1; i > 0; i-- { 55 | j := rand.Intn(i + 1) 56 | shuffled[i], shuffled[j] = shuffled[j], shuffled[i] 57 | } 58 | sort.Slice(shuffled, func(i, j int) bool { 59 | return shuffled[i].CompareTo(shuffled[j]) < 0 60 | }) 61 | for i, q := range queries { 62 | checkQuery(q, shuffled[i], t) 63 | } 64 | } 65 | 66 | func sortedQueries(nof int) []*Name { 67 | queries := []*Name{} 68 | for i := 0; i < nof; i++ { 69 | for j := 0; j < nof; j++ { 70 | for k := 0; k < 13; k++ { 71 | for l := 0; l < nof; l++ { 72 | for m := 0; m < 8; m++ { 73 | //TODO CFE extend this test when we support multiple connection per assertion 74 | queries = append(queries, &Name{ 75 | Context: strconv.Itoa(i), 76 | Name: strconv.Itoa(j), 77 | Types: []object.Type{object.Type(k)}, 78 | Expiration: int64(l), 79 | Options: []Option{Option(m)}, 80 | }) 81 | } 82 | for m := 0; m < 7; m++ { 83 | for n := m + 1; n < 8; n++ { 84 | //TODO CFE extend this test when we support multiple connection per assertion 85 | queries = append(queries, &Name{ 86 | Context: strconv.Itoa(i), 87 | Name: strconv.Itoa(j), 88 | Types: []object.Type{object.Type(k)}, 89 | Expiration: int64(l), 90 | Options: []Option{Option(m), Option(n)}, 91 | }) 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | queries = append(queries, queries[len(queries)-1]) 99 | return queries 100 | } 101 | 102 | func checkQuery(q1, q2 *Name, t *testing.T) { 103 | if q1.Context != q2.Context { 104 | t.Error("Query context mismatch") 105 | } 106 | if q1.Expiration != q2.Expiration { 107 | t.Error("Query Expires mismatch") 108 | } 109 | if q1.Name != q2.Name { 110 | t.Error("Query Name mismatch") 111 | } 112 | if len(q1.Types) != len(q2.Types) { 113 | t.Error("Query Type length mismatch") 114 | } 115 | for i, o1 := range q1.Types { 116 | if o1 != q2.Types[i] { 117 | t.Errorf("Query Type at position %d mismatch", i) 118 | } 119 | } 120 | if len(q1.Options) != len(q2.Options) { 121 | t.Error("Query Option length mismatch") 122 | } 123 | for i, o1 := range q1.Options { 124 | if o1 != q2.Options[i] { 125 | t.Errorf("Query Option at position %d mismatch", i) 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /internal/pkg/rainsd/cache.go: -------------------------------------------------------------------------------- 1 | package rainsd 2 | 3 | import ( 4 | "github.com/netsec-ethz/rains/internal/pkg/cache" 5 | ) 6 | 7 | type Caches struct { 8 | //connCache stores connections of this server. It is not guaranteed that a returned connection is still active. 9 | ConnCache cache.Connection 10 | 11 | //capabilities stores known hashes of capabilities and for each connInfo what capability the communication partner has. 12 | Capabilities cache.Capability 13 | 14 | //zoneKeyCache is used to store public keys of zones and a pointer to assertions containing them. 15 | ZoneKeyCache cache.ZonePublicKey 16 | 17 | //pendingSignatures contains all sections that are waiting for a delegation query to arrive such that their signatures can be verified. 18 | PendingKeys cache.PendingKey 19 | 20 | //pendingQueries contains a mapping from all self issued pending queries to the set of message bodies waiting for it. 21 | PendingQueries cache.PendingQuery 22 | 23 | //assertionCache contains a set of valid assertions where some of them might be expired. 24 | //An entry is marked as extrenal if it might be evicted by a LRU caching strategy. 25 | AssertionsCache cache.Assertion 26 | 27 | //negAssertionCache contains for each zone and context an interval tree to find all shards and zones containing a specific assertion 28 | //for a zone the range is infinit: range "","" 29 | //for a shard the range is given as declared in the section. 30 | //An entry is marked as extrenal if it might be evicted by a LRU caching strategy. 31 | NegAssertionCache cache.NegativeAssertion 32 | } 33 | 34 | func initCaches(config Config) *Caches { 35 | caches := new(Caches) 36 | caches.ConnCache = cache.NewConnection(config.MaxConnections) 37 | caches.Capabilities = cache.NewCapability(config.CapabilitiesCacheSize) 38 | caches.ZoneKeyCache = cache.NewZoneKey(config.ZoneKeyCacheSize, config.ZoneKeyCacheWarnSize, 39 | config.MaxPublicKeysPerZone) 40 | caches.PendingKeys = cache.NewPendingKey(config.PendingKeyCacheSize) 41 | caches.PendingQueries = cache.NewPendingQuery(config.PendingQueryCacheSize) 42 | caches.AssertionsCache = cache.NewAssertion(config.AssertionCacheSize) 43 | caches.NegAssertionCache = cache.NewNegAssertion(config.NegativeAssertionCacheSize) 44 | return caches 45 | } 46 | 47 | func initReapers(config Config, caches *Caches, stop chan bool) { 48 | go repeatFuncCaller(caches.ZoneKeyCache.RemoveExpiredKeys, config.ReapZoneKeyCacheInterval, stop) 49 | go repeatFuncCaller(caches.PendingKeys.RemoveExpiredValues, config.ReapPendingKeyCacheInterval, stop) 50 | go repeatFuncCaller(caches.AssertionsCache.RemoveExpiredValues, config.ReapAssertionCacheInterval, stop) 51 | go repeatFuncCaller(caches.NegAssertionCache.RemoveExpiredValues, config.ReapNegAssertionCacheInterval, stop) 52 | go repeatFuncCaller(caches.PendingQueries.RemoveExpiredValues, config.ReapPendingQCacheInterval, stop) 53 | } 54 | -------------------------------------------------------------------------------- /internal/pkg/section/bloomfilter_test.go: -------------------------------------------------------------------------------- 1 | package section 2 | 3 | import ( 4 | "math/rand" 5 | "sort" 6 | "testing" 7 | 8 | "github.com/netsec-ethz/rains/internal/pkg/algorithmTypes" 9 | "github.com/netsec-ethz/rains/internal/pkg/datastructures/bitarray" 10 | "github.com/netsec-ethz/rains/internal/pkg/object" 11 | ) 12 | 13 | func TestBloomFilter(t *testing.T) { 14 | var tests = []struct { 15 | input BloomFilter 16 | }{ 17 | {BloomFilter{BloomKM12, algorithmTypes.Shake256, make(bitarray.BitArray, 16)}}, 18 | {BloomFilter{BloomKM12, algorithmTypes.Fnv64, make(bitarray.BitArray, 16)}}, 19 | {BloomFilter{BloomKM12, algorithmTypes.Fnv128, make(bitarray.BitArray, 16)}}, 20 | {BloomFilter{BloomKM16, algorithmTypes.Fnv128, make(bitarray.BitArray, 16)}}, 21 | {BloomFilter{BloomKM16, algorithmTypes.Shake256, make(bitarray.BitArray, 16)}}, 22 | {BloomFilter{BloomKM16, algorithmTypes.Fnv64, make(bitarray.BitArray, 16)}}, 23 | {BloomFilter{BloomKM20, algorithmTypes.Fnv128, make(bitarray.BitArray, 16)}}, 24 | {BloomFilter{BloomKM20, algorithmTypes.Shake256, make(bitarray.BitArray, 16)}}, 25 | {BloomFilter{BloomKM20, algorithmTypes.Fnv64, make(bitarray.BitArray, 16)}}, 26 | {BloomFilter{BloomKM24, algorithmTypes.Fnv128, make(bitarray.BitArray, 16)}}, 27 | {BloomFilter{BloomKM24, algorithmTypes.Shake256, make(bitarray.BitArray, 16)}}, 28 | {BloomFilter{BloomKM24, algorithmTypes.Fnv64, make(bitarray.BitArray, 16)}}, 29 | } 30 | for _, test := range tests { 31 | test.input.Add("testName", "testZone", "testContext", object.OTIP4Addr) 32 | if ok, err := test.input.Contains("testName", "testZone", "testContext", object.OTIP4Addr); err != nil || !ok { 33 | t.Fatal("Filter should contain this element") 34 | } 35 | if ok, err := test.input.Contains("testName", "testZone", "testContext", object.OTIP6Addr); err != nil || ok { 36 | t.Fatal("Filter should not contain this element") 37 | } 38 | } 39 | } 40 | 41 | func TestBloomFilterCompareTo(t *testing.T) { 42 | bfs := sortedBloomFilters(10) 43 | shuffled := append([]BloomFilter{}, bfs...) 44 | for i := len(shuffled) - 1; i > 0; i-- { 45 | j := rand.Intn(i + 1) 46 | shuffled[i], shuffled[j] = shuffled[j], shuffled[i] 47 | } 48 | sort.Slice(shuffled, func(i, j int) bool { 49 | return shuffled[i].CompareTo(shuffled[j]) < 0 50 | }) 51 | for i, a := range bfs { 52 | if a.CompareTo(shuffled[i]) != 0 { 53 | t.Fatal("Not sorted correctly") 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /internal/pkg/section/bloomfilteralgo_jsonenums.go: -------------------------------------------------------------------------------- 1 | // generated by jsonenums -type=BloomFilterAlgo; DO NOT EDIT 2 | 3 | package section 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | ) 9 | 10 | var ( 11 | _BloomFilterAlgoNameToValue = map[string]BloomFilterAlgo{ 12 | "BloomKM12": BloomKM12, 13 | "BloomKM16": BloomKM16, 14 | "BloomKM20": BloomKM20, 15 | "BloomKM24": BloomKM24, 16 | } 17 | 18 | _BloomFilterAlgoValueToName = map[BloomFilterAlgo]string{ 19 | BloomKM12: "BloomKM12", 20 | BloomKM16: "BloomKM16", 21 | BloomKM20: "BloomKM20", 22 | BloomKM24: "BloomKM24", 23 | } 24 | ) 25 | 26 | func init() { 27 | var v BloomFilterAlgo 28 | if _, ok := interface{}(v).(fmt.Stringer); ok { 29 | _BloomFilterAlgoNameToValue = map[string]BloomFilterAlgo{ 30 | interface{}(BloomKM12).(fmt.Stringer).String(): BloomKM12, 31 | interface{}(BloomKM16).(fmt.Stringer).String(): BloomKM16, 32 | interface{}(BloomKM20).(fmt.Stringer).String(): BloomKM20, 33 | interface{}(BloomKM24).(fmt.Stringer).String(): BloomKM24, 34 | } 35 | } 36 | } 37 | 38 | // MarshalJSON is generated so BloomFilterAlgo satisfies json.Marshaler. 39 | func (r BloomFilterAlgo) MarshalJSON() ([]byte, error) { 40 | if s, ok := interface{}(r).(fmt.Stringer); ok { 41 | return json.Marshal(s.String()) 42 | } 43 | s, ok := _BloomFilterAlgoValueToName[r] 44 | if !ok { 45 | return nil, fmt.Errorf("invalid BloomFilterAlgo: %d", r) 46 | } 47 | return json.Marshal(s) 48 | } 49 | 50 | // UnmarshalJSON is generated so BloomFilterAlgo satisfies json.Unmarshaler. 51 | func (r *BloomFilterAlgo) UnmarshalJSON(data []byte) error { 52 | var s string 53 | if err := json.Unmarshal(data, &s); err != nil { 54 | return fmt.Errorf("BloomFilterAlgo should be a string, got %s", data) 55 | } 56 | v, ok := _BloomFilterAlgoNameToValue[s] 57 | if !ok { 58 | return fmt.Errorf("invalid BloomFilterAlgo %q", s) 59 | } 60 | *r = v 61 | return nil 62 | } 63 | -------------------------------------------------------------------------------- /internal/pkg/section/bloomfilteralgo_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=BloomFilterAlgo"; DO NOT EDIT. 2 | 3 | package section 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[BloomKM12-1] 12 | _ = x[BloomKM16-2] 13 | _ = x[BloomKM20-3] 14 | _ = x[BloomKM24-4] 15 | } 16 | 17 | const _BloomFilterAlgo_name = "BloomKM12BloomKM16BloomKM20BloomKM24" 18 | 19 | var _BloomFilterAlgo_index = [...]uint8{0, 9, 18, 27, 36} 20 | 21 | func (i BloomFilterAlgo) String() string { 22 | i -= 1 23 | if i < 0 || i >= BloomFilterAlgo(len(_BloomFilterAlgo_index)-1) { 24 | return "BloomFilterAlgo(" + strconv.FormatInt(int64(i+1), 10) + ")" 25 | } 26 | return _BloomFilterAlgo_name[_BloomFilterAlgo_index[i]:_BloomFilterAlgo_index[i+1]] 27 | } 28 | -------------------------------------------------------------------------------- /internal/pkg/section/interfaces.go: -------------------------------------------------------------------------------- 1 | package section 2 | 3 | import ( 4 | "time" 5 | 6 | cbor "github.com/britram/borat" 7 | 8 | "github.com/netsec-ethz/rains/internal/pkg/keys" 9 | "github.com/netsec-ethz/rains/internal/pkg/signature" 10 | ) 11 | 12 | // Section can be either an Assertion, Shard, Zone, Query, Notification, AddressAssertion, AddressZone, AddressQuery section 13 | type Section interface { 14 | Sort() 15 | String() string 16 | MarshalCBOR(w *cbor.CBORWriter) error 17 | UnmarshalMap(m map[int]interface{}) error 18 | } 19 | 20 | // WithSig is an interface for a section protected by a signature. In the current 21 | // implementation it can be an Assertion, Shard, Zone, AddressAssertion, AddressZone 22 | type WithSig interface { 23 | Section 24 | AllSigs() []signature.Sig 25 | Sigs(keyspace keys.KeySpaceID) []signature.Sig 26 | AddSig(sig signature.Sig) 27 | DeleteSig(index int) 28 | DeleteAllSigs() 29 | GetContext() string 30 | GetSubjectZone() string 31 | UpdateValidity(validSince, validUntil int64, maxValidity time.Duration) 32 | ValidSince() int64 33 | SetValidSince(int64) 34 | ValidUntil() int64 35 | SetValidUntil(int64) 36 | Hash() string 37 | IsConsistent() bool 38 | NeededKeys(map[signature.MetaData]bool) 39 | AddSigInMarshaller() 40 | DontAddSigInMarshaller() 41 | } 42 | 43 | // WithSigForward can be either an Assertion, Shard or Zone 44 | type WithSigForward interface { 45 | WithSig 46 | Interval 47 | } 48 | 49 | // Query is the interface for a query section. In the current implementation it can be 50 | // a query or an addressQuery 51 | type Query interface { 52 | GetContext() string 53 | GetExpiration() int64 54 | } 55 | 56 | // Interval defines an interval over strings 57 | type Interval interface { 58 | //Begin of the interval 59 | Begin() string 60 | //End of the interval 61 | End() string 62 | } 63 | 64 | // Hasher can be implemented by objects that are not natively hashable. 65 | // For an object to be a map key (or a part thereof), it must be hashable. 66 | type Hasher interface { 67 | //Hash must return a string uniquely identifying the object 68 | //It must hold for all objects that o1 == o2 iff o1.Hash() == o2.Hash() 69 | Hash() string 70 | } 71 | -------------------------------------------------------------------------------- /internal/pkg/section/interval.go: -------------------------------------------------------------------------------- 1 | package section 2 | 3 | // Intersect returns true if a and b are overlapping 4 | func Intersect(a, b Interval) bool { 5 | //case1: both intervals are points => compare with equality 6 | if a.Begin() == a.End() && b.Begin() == b.End() && a.Begin() != "" && b.Begin() != "" { 7 | return a.Begin() == b.Begin() 8 | } 9 | //case2: at least one of them is an interval 10 | if a.Begin() == "" { 11 | return b.Begin() == "" || a.End() == "" || a.End() > b.Begin() 12 | } 13 | if a.End() == "" { 14 | return b.End() == "" || a.Begin() < b.End() 15 | } 16 | if b.Begin() == "" { 17 | return b.End() == "" || b.End() > a.Begin() 18 | } 19 | if b.End() == "" { 20 | return b.Begin() < a.End() 21 | } 22 | return a.Begin() < b.End() && a.End() > b.Begin() 23 | } 24 | 25 | // TotalInterval is an interval over the whole namespace 26 | type TotalInterval struct{} 27 | 28 | // Begin defines the start of the total namespace 29 | func (t TotalInterval) Begin() string { 30 | return "" 31 | } 32 | 33 | // End defines the end of the total namespace 34 | func (t TotalInterval) End() string { 35 | return "" 36 | } 37 | 38 | // StringInterval implements Interval for a single string value 39 | type StringInterval struct { 40 | Name string 41 | } 42 | 43 | // Begin defines the start of a StringInterval namespace 44 | func (s StringInterval) Begin() string { 45 | return s.Name 46 | } 47 | 48 | // End defines the end of a StringInterval namespace 49 | func (s StringInterval) End() string { 50 | return s.Name 51 | } 52 | -------------------------------------------------------------------------------- /internal/pkg/section/interval_test.go: -------------------------------------------------------------------------------- 1 | package section 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestIntersect(t *testing.T) { 8 | var tests = []struct { 9 | i1 Interval 10 | i2 Interval 11 | intersect bool 12 | }{ 13 | //Points 14 | {StringInterval{"a"}, StringInterval{"a"}, true}, 15 | {StringInterval{"a"}, StringInterval{"b"}, false}, 16 | //"" represents the start and end of the name space. A point cannot be there. Undefined 17 | //behavior where our code returns true. 18 | {StringInterval{""}, StringInterval{""}, true}, 19 | {StringInterval{""}, StringInterval{"b"}, true}, 20 | {StringInterval{"b"}, StringInterval{""}, true}, 21 | //Intervals and Point 22 | {&Shard{RangeFrom: "a", RangeTo: "b"}, StringInterval{"a"}, false}, 23 | {&Shard{RangeFrom: "a", RangeTo: "b"}, StringInterval{"b"}, false}, 24 | {&Shard{RangeFrom: "a", RangeTo: "b"}, StringInterval{"c"}, false}, 25 | {&Shard{RangeFrom: "a", RangeTo: "b"}, StringInterval{"aa"}, true}, 26 | {&Shard{RangeFrom: "", RangeTo: "b"}, StringInterval{"c"}, false}, 27 | {&Shard{RangeFrom: "b", RangeTo: ""}, StringInterval{"a"}, false}, 28 | {&Shard{RangeFrom: "", RangeTo: "b"}, StringInterval{"a"}, true}, 29 | {&Shard{RangeFrom: "b", RangeTo: ""}, StringInterval{"z"}, true}, 30 | //Intervals 31 | {&Shard{RangeFrom: "a", RangeTo: "b"}, &Shard{RangeFrom: "a", RangeTo: "b"}, true}, 32 | {&Shard{RangeFrom: "a", RangeTo: "b"}, &Shard{RangeFrom: "b", RangeTo: "c"}, false}, 33 | {&Shard{RangeFrom: "b", RangeTo: "c"}, &Shard{RangeFrom: "a", RangeTo: "b"}, false}, 34 | {&Shard{RangeFrom: "a", RangeTo: "c"}, &Shard{RangeFrom: "b", RangeTo: "d"}, true}, 35 | {&Shard{RangeFrom: "b", RangeTo: "d"}, &Shard{RangeFrom: "a", RangeTo: "c"}, true}, 36 | {&Shard{RangeFrom: "a", RangeTo: "d"}, &Shard{RangeFrom: "b", RangeTo: "c"}, true}, 37 | {&Shard{RangeFrom: "b", RangeTo: "c"}, &Shard{RangeFrom: "a", RangeTo: "d"}, true}, 38 | } 39 | for i, test := range tests { 40 | if Intersect(test.i1, test.i2) != test.intersect { 41 | t.Errorf("%d: Unexpected intersection. expected=%v, actual=%v", i, test.intersect, 42 | Intersect(test.i1, test.i2)) 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /internal/pkg/section/notification.go: -------------------------------------------------------------------------------- 1 | package section 2 | 3 | import ( 4 | "encoding/hex" 5 | "errors" 6 | "fmt" 7 | 8 | cbor "github.com/britram/borat" 9 | 10 | "github.com/netsec-ethz/rains/internal/pkg/keys" 11 | "github.com/netsec-ethz/rains/internal/pkg/signature" 12 | "github.com/netsec-ethz/rains/internal/pkg/token" 13 | ) 14 | 15 | // Notification contains information about the notification 16 | type Notification struct { 17 | Token token.Token 18 | Type NotificationType 19 | Data string 20 | } 21 | 22 | // UnmarshalMap unpacks a CBOR unmarshaled map to this object. 23 | func (n *Notification) UnmarshalMap(m map[int]interface{}) error { 24 | tok, ok := m[2].([]byte) 25 | if !ok || len(tok) != 16 { 26 | return errors.New("cbor notification encoding of the token should be a byte array of length 16") 27 | } 28 | for i, val := range tok { 29 | n.Token[i] = val 30 | } 31 | if not, ok := m[21].(int); ok { 32 | n.Type = NotificationType(not) 33 | } else { 34 | return errors.New("cbor notification map does not contain type") 35 | } 36 | if data, ok := m[22].(string); ok { 37 | n.Data = string(data) 38 | } else { 39 | return errors.New("cbor notification map does not contain data") 40 | } 41 | return nil 42 | } 43 | 44 | // MarshalCBOR implements the CBORMarshaler interface. 45 | func (n *Notification) MarshalCBOR(w *cbor.CBORWriter) error { 46 | m := make(map[int]interface{}) 47 | m[2] = n.Token[:] 48 | m[21] = int(n.Type) 49 | m[22] = n.Data 50 | return w.WriteIntMap(m) 51 | } 52 | 53 | // Sort sorts the content of the notification lexicographically. 54 | func (n *Notification) Sort() { 55 | //notification is already sorted (it does not contain a list of elements). 56 | } 57 | 58 | // CompareTo compares two notifications and returns 0 if they are equal, 1 if n is greater than 59 | // notification and -1 if n is smaller than notification 60 | func (n *Notification) CompareTo(notification *Notification) int { 61 | if comp := token.Compare(n.Token, notification.Token); comp != 0 { 62 | return comp 63 | } else if n.Type < notification.Type { 64 | return -1 65 | } else if n.Type > notification.Type { 66 | return 1 67 | } else if n.Data < notification.Data { 68 | return -1 69 | } else if n.Data > notification.Data { 70 | return 1 71 | } 72 | return 0 73 | } 74 | 75 | // String implements Stringer interface 76 | func (n *Notification) String() string { 77 | if n == nil { 78 | return "Notification:nil" 79 | } 80 | return fmt.Sprintf("Notification:[TOK=%s TYPE=%d DATA=%s]", 81 | hex.EncodeToString(n.Token[:]), n.Type, n.Data) 82 | } 83 | 84 | // filterSigs returns only those signatures which are in the given keySpace 85 | func filterSigs(signatures []signature.Sig, keySpace keys.KeySpaceID) []signature.Sig { 86 | sigs := []signature.Sig{} 87 | for _, sig := range signatures { 88 | if sig.KeySpace == keySpace { 89 | sigs = append(sigs, sig) 90 | } 91 | } 92 | return sigs 93 | } 94 | 95 | // NotificationType defines the type of a notification section 96 | type NotificationType int 97 | 98 | //go:generate stringer -type=NotificationType 99 | const ( 100 | NTHeartbeat NotificationType = 100 101 | NTCapHashNotKnown NotificationType = 399 102 | NTBadMessage NotificationType = 400 103 | NTRcvInconsistentMsg NotificationType = 403 104 | NTNoAssertionsExist NotificationType = 404 105 | NTMsgTooLarge NotificationType = 413 106 | NTUnspecServerErr NotificationType = 500 107 | NTServerNotCapable NotificationType = 501 108 | NTNoAssertionAvail NotificationType = 504 109 | ) 110 | -------------------------------------------------------------------------------- /internal/pkg/section/notification_test.go: -------------------------------------------------------------------------------- 1 | package section 2 | 3 | import ( 4 | "math/rand" 5 | "sort" 6 | "testing" 7 | ) 8 | 9 | func TestNotificationCompareTo(t *testing.T) { 10 | ns := sortedNotifications(5) 11 | shuffled := append([]*Notification{}, ns...) 12 | for i := len(shuffled) - 1; i > 0; i-- { 13 | j := rand.Intn(i + 1) 14 | shuffled[i], shuffled[j] = shuffled[j], shuffled[i] 15 | } 16 | sort.Slice(shuffled, func(i, j int) bool { 17 | return shuffled[i].CompareTo(shuffled[j]) < 0 18 | }) 19 | for i, n := range ns { 20 | checkNotification(n, shuffled[i], t) 21 | } 22 | } 23 | 24 | func checkNotification(n1, n2 *Notification, t *testing.T) { 25 | if n1.Type != n2.Type { 26 | t.Error("Notification Type mismatch") 27 | } 28 | if n1.Token != n2.Token { 29 | t.Error("Notification Token mismatch") 30 | } 31 | if n1.Data != n2.Data { 32 | t.Error("Notification Data mismatch") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /internal/pkg/section/notificationtype_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=NotificationType"; DO NOT EDIT. 2 | 3 | package section 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[NTHeartbeat-100] 12 | _ = x[NTCapHashNotKnown-399] 13 | _ = x[NTBadMessage-400] 14 | _ = x[NTRcvInconsistentMsg-403] 15 | _ = x[NTNoAssertionsExist-404] 16 | _ = x[NTMsgTooLarge-413] 17 | _ = x[NTUnspecServerErr-500] 18 | _ = x[NTServerNotCapable-501] 19 | _ = x[NTNoAssertionAvail-504] 20 | } 21 | 22 | const ( 23 | _NotificationType_name_0 = "NTHeartbeat" 24 | _NotificationType_name_1 = "NTCapHashNotKnownNTBadMessage" 25 | _NotificationType_name_2 = "NTRcvInconsistentMsgNTNoAssertionsExist" 26 | _NotificationType_name_3 = "NTMsgTooLarge" 27 | _NotificationType_name_4 = "NTUnspecServerErrNTServerNotCapable" 28 | _NotificationType_name_5 = "NTNoAssertionAvail" 29 | ) 30 | 31 | var ( 32 | _NotificationType_index_1 = [...]uint8{0, 17, 29} 33 | _NotificationType_index_2 = [...]uint8{0, 20, 39} 34 | _NotificationType_index_4 = [...]uint8{0, 17, 35} 35 | ) 36 | 37 | func (i NotificationType) String() string { 38 | switch { 39 | case i == 100: 40 | return _NotificationType_name_0 41 | case 399 <= i && i <= 400: 42 | i -= 399 43 | return _NotificationType_name_1[_NotificationType_index_1[i]:_NotificationType_index_1[i+1]] 44 | case 403 <= i && i <= 404: 45 | i -= 403 46 | return _NotificationType_name_2[_NotificationType_index_2[i]:_NotificationType_index_2[i+1]] 47 | case i == 413: 48 | return _NotificationType_name_3 49 | case 500 <= i && i <= 501: 50 | i -= 500 51 | return _NotificationType_name_4[_NotificationType_index_4[i]:_NotificationType_index_4[i+1]] 52 | case i == 504: 53 | return _NotificationType_name_5 54 | default: 55 | return "NotificationType(" + strconv.FormatInt(int64(i), 10) + ")" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /internal/pkg/section/pshard_test.go: -------------------------------------------------------------------------------- 1 | package section 2 | 3 | import ( 4 | "math/rand" 5 | "sort" 6 | "testing" 7 | ) 8 | 9 | func TestPshardCopy(t *testing.T) { 10 | pshard := GetPshard() 11 | pCopy := pshard.Copy(pshard.Context, pshard.SubjectZone) 12 | checkPshard(pshard, pCopy, t) 13 | if pshard == pCopy { 14 | t.Error("Pshard was not copied. Pointer is still the same.") 15 | } 16 | } 17 | 18 | func TestPshardInterval(t *testing.T) { 19 | var tests = []struct { 20 | input *Pshard 21 | wantBegin string 22 | wantEnd string 23 | }{ 24 | {&Pshard{RangeFrom: "a", RangeTo: "z"}, "a", "z"}, 25 | {new(Pshard), "", ""}, 26 | } 27 | for i, test := range tests { 28 | if test.input.Begin() != test.wantBegin || test.input.End() != test.wantEnd { 29 | t.Errorf("%d: Pshard Begin and End are not as expectedBegin=%s expectedEnd=%s actualBegin=%s actualEnd=%s", i, 30 | test.wantBegin, test.wantEnd, test.input.Begin(), test.input.End()) 31 | } 32 | } 33 | } 34 | 35 | func TestPshardCompareTo(t *testing.T) { 36 | pshards := sortedPshards(4) 37 | shuffled := append([]*Pshard{}, pshards...) 38 | for i := len(shuffled) - 1; i > 0; i-- { 39 | j := rand.Intn(i + 1) 40 | shuffled[i], shuffled[j] = shuffled[j], shuffled[i] 41 | } 42 | sort.Slice(shuffled, func(i, j int) bool { 43 | return shuffled[i].CompareTo(shuffled[j]) < 0 44 | }) 45 | for i, s := range pshards { 46 | checkPshard(s, shuffled[i], t) 47 | } 48 | } 49 | 50 | func TestPshardInRange(t *testing.T) { 51 | ss := Pshard{ 52 | RangeFrom: "abc", 53 | RangeTo: "xyz", 54 | } 55 | testMatrix := []struct { 56 | Input string 57 | Output bool 58 | }{ 59 | { 60 | Input: "aaa", 61 | Output: false, 62 | }, 63 | { 64 | Input: "abc", 65 | Output: false, 66 | }, 67 | { 68 | Input: "abcdef", 69 | Output: true, 70 | }, 71 | { 72 | Input: "zzz", 73 | Output: false, 74 | }, 75 | } 76 | for i, testCase := range testMatrix { 77 | if out := ss.InRange(testCase.Input); out != testCase.Output { 78 | t.Errorf("case %d: expected response of %t from InRange, but got %t with input %s", 79 | i, out, testCase.Output, testCase.Input) 80 | } 81 | } 82 | } 83 | 84 | func checkPshard(s1, s2 *Pshard, t *testing.T) { 85 | if s1.Context != s2.Context { 86 | t.Error("Pshard context mismatch") 87 | } 88 | if s1.SubjectZone != s2.SubjectZone { 89 | t.Error("Pshard subjectZone mismatch") 90 | } 91 | if s1.RangeFrom != s2.RangeFrom { 92 | t.Error("Pshard RangeFrom mismatch") 93 | } 94 | if s1.RangeTo != s2.RangeTo { 95 | t.Error("Pshard RangeTo mismatch") 96 | } 97 | checkSignatures(s1.Signatures, s2.Signatures, t) 98 | if s1.BloomFilter.CompareTo(s2.BloomFilter) != 0 { 99 | t.Error("Pshard Bloomfilter mismatch") 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /internal/pkg/section/sections_test.go: -------------------------------------------------------------------------------- 1 | package section 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | "github.com/netsec-ethz/rains/internal/pkg/keys" 8 | "github.com/netsec-ethz/rains/internal/pkg/signature" 9 | ) 10 | 11 | func TestSigs(t *testing.T) { 12 | var tests = []struct { 13 | input []signature.Sig 14 | param keys.KeySpaceID 15 | output []signature.Sig 16 | }{ 17 | {[]signature.Sig{signature.Sig{PublicKeyID: keys.PublicKeyID{KeySpace: keys.KeySpaceID(-1)}}, signature.Sig{}}, keys.RainsKeySpace, []signature.Sig{signature.Sig{}}}, 18 | } 19 | for i, test := range tests { 20 | var s WithSig 21 | s = &Assertion{Signatures: test.input} 22 | sigs := s.Sigs(test.param) 23 | if !reflect.DeepEqual(sigs, test.output) { 24 | t.Errorf("%d: assertion.Sigs() does not return the expected signatures expected=%v actual=%v", i, test.output, sigs) 25 | } 26 | s = &Shard{Signatures: test.input} 27 | sigs = s.Sigs(test.param) 28 | if !reflect.DeepEqual(sigs, test.output) { 29 | t.Errorf("%d: shard.Sigs() does not return the expected signatures expected=%v actual=%v", i, test.output, sigs) 30 | } 31 | s = &Zone{Signatures: test.input} 32 | sigs = s.Sigs(test.param) 33 | if !reflect.DeepEqual(sigs, test.output) { 34 | t.Errorf("%d: zone.Sigs() does not return the expected signatures expected=%v actual=%v", i, test.output, sigs) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /internal/pkg/section/util.go: -------------------------------------------------------------------------------- 1 | package section 2 | 3 | import ( 4 | "math" 5 | "time" 6 | 7 | log "github.com/inconshreveable/log15" 8 | ) 9 | 10 | func UpdateValidity(validSince, validUntil, oldValidSince, oldValidUntil int64, 11 | maxValidity time.Duration) (int64, int64) { 12 | if oldValidSince == 0 { 13 | oldValidSince = math.MaxInt64 14 | } 15 | if validSince < oldValidSince { 16 | if validSince > time.Now().Add(maxValidity).Unix() { 17 | oldValidSince = time.Now().Add(maxValidity).Unix() 18 | log.Warn("newValidSince exceeded maxValidity", "oldValidSince", oldValidSince, 19 | "newValidSince", validSince, "maxValidity", maxValidity) 20 | } else { 21 | oldValidSince = validSince 22 | } 23 | } 24 | if validUntil > oldValidUntil { 25 | if validUntil > time.Now().Add(maxValidity).Unix() { 26 | oldValidUntil = time.Now().Add(maxValidity).Unix() 27 | log.Warn("newValidUntil exceeded maxValidity", "oldValidSince", oldValidSince, 28 | "newValidSince", validSince, "maxValidity", maxValidity) 29 | } else { 30 | oldValidUntil = validUntil 31 | } 32 | } 33 | return oldValidSince, oldValidUntil 34 | } 35 | -------------------------------------------------------------------------------- /internal/pkg/section/zone_test.go: -------------------------------------------------------------------------------- 1 | package section 2 | 3 | import ( 4 | "math/rand" 5 | "reflect" 6 | "sort" 7 | "testing" 8 | ) 9 | 10 | func TestZoneInterval(t *testing.T) { 11 | var tests = []struct { 12 | input *Zone 13 | want string 14 | }{ 15 | {new(Zone), ""}, 16 | } 17 | for i, test := range tests { 18 | if test.input.Begin() != test.want || test.input.End() != test.want { 19 | t.Errorf("%d: Assertion Begin and End are not as expected=%s actualBegin=%s actualEnd=%s", i, test.want, test.input.Begin(), test.input.End()) 20 | } 21 | } 22 | } 23 | 24 | func TestZoneIsConsistent(t *testing.T) { 25 | var tests = []struct { 26 | input *Zone 27 | want bool 28 | }{ 29 | {new(Zone), true}, 30 | {&Zone{Content: []*Assertion{&Assertion{SubjectZone: "zone"}}}, false}, 31 | {&Zone{Content: []*Assertion{&Assertion{Context: "ctx"}}}, false}, 32 | } 33 | for i, test := range tests { 34 | if test.input.IsConsistent() != test.want { 35 | t.Errorf("%d: unexpected zone (in)consistency expected=%v actual=%v", i, test.want, 36 | test.input.IsConsistent()) 37 | } 38 | } 39 | } 40 | 41 | func TestZoneCompareTo(t *testing.T) { 42 | zones := sortedZones(5) 43 | shuffled := append([]*Zone{}, zones...) 44 | for i := len(shuffled) - 1; i > 0; i-- { 45 | j := rand.Intn(i + 1) 46 | shuffled[i], shuffled[j] = shuffled[j], shuffled[i] 47 | } 48 | sort.Slice(shuffled, func(i, j int) bool { 49 | return shuffled[i].CompareTo(shuffled[j]) < 0 50 | }) 51 | for i, z := range zones { 52 | checkZone(z, shuffled[i], t) 53 | } 54 | z1 := &Zone{} 55 | z2 := &Zone{Content: []*Assertion{&Assertion{}}} 56 | if z1.CompareTo(z2) != -1 { 57 | t.Error("Different content length are not sorted correctly") 58 | } 59 | if z2.CompareTo(z1) != 1 { 60 | t.Error("Different content length are not sorted correctly") 61 | } 62 | } 63 | 64 | func TestZoneSort(t *testing.T) { 65 | //FIXME 66 | var tests = []struct { 67 | input []*Assertion 68 | sorted []*Assertion 69 | }{ 70 | {}, 71 | } 72 | for i, test := range tests { 73 | z := &Zone{Content: test.input} 74 | z.Sort() 75 | if !reflect.DeepEqual(z.Content, test.sorted) { 76 | t.Errorf("%d: Zone.Sort() does not sort correctly expected=%v actual=%v", i, test.sorted, z.Content) 77 | } 78 | } 79 | } 80 | 81 | func checkZone(z1, z2 *Zone, t *testing.T) { 82 | if z1.Context != z2.Context { 83 | t.Error("Zone context mismatch") 84 | } 85 | if z1.SubjectZone != z2.SubjectZone { 86 | t.Error("Zone subjectZone mismatch") 87 | } 88 | checkSignatures(z1.Signatures, z2.Signatures, t) 89 | if len(z1.Content) != len(z2.Content) { 90 | t.Error("Zone Content length mismatch") 91 | } 92 | for i, s1 := range z1.Content { 93 | checkAssertion(s1, z2.Content[i], t) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /internal/pkg/signature/signature_test.go: -------------------------------------------------------------------------------- 1 | package signature 2 | 3 | import ( 4 | "math/rand" 5 | "reflect" 6 | "sort" 7 | "testing" 8 | 9 | "github.com/netsec-ethz/rains/internal/pkg/algorithmTypes" 10 | "github.com/netsec-ethz/rains/internal/pkg/keys" 11 | "golang.org/x/crypto/ed25519" 12 | ) 13 | 14 | func TestSignDataErrors(t *testing.T) { 15 | _, key, _ := ed25519.GenerateKey(nil) 16 | var tests = []struct { 17 | sig *Sig 18 | key interface{} 19 | expected string 20 | }{ 21 | {&Sig{}, nil, "privateKey is nil"}, 22 | {&Sig{}, key, "signature algorithm type not supported: Signature(0)"}, 23 | {&Sig{PublicKeyID: keys.PublicKeyID{Algorithm: algorithmTypes.Ed25519}}, 24 | Sig{}, "could not assert type ed25519.PrivateKey"}, 25 | } 26 | for i, test := range tests { 27 | err := test.sig.SignData(test.key, []byte("Wrong encoding")) 28 | if err == nil || err.Error() != test.expected { 29 | t.Fatalf("%d: Unexpected error result, expected=%s actual=%s", i, test.expected, err.Error()) 30 | } 31 | } 32 | } 33 | 34 | func TestVerifySignatureErrors(t *testing.T) { 35 | key, _, _ := ed25519.GenerateKey(nil) 36 | var tests = []struct { 37 | sig *Sig 38 | key interface{} 39 | }{ 40 | {&Sig{}, nil}, 41 | {&Sig{Data: []byte("some data")}, nil}, 42 | {&Sig{Data: []byte("some data")}, key}, 43 | {&Sig{Data: "sd", PublicKeyID: keys.PublicKeyID{Algorithm: algorithmTypes.Ed25519}}, Sig{}}, 44 | } 45 | for i, test := range tests { 46 | ok := test.sig.VerifySignature(test.key, []byte("Wrong encoding")) 47 | if ok { 48 | t.Fatalf("%d: Signature should not verify", i) 49 | } 50 | } 51 | } 52 | 53 | func TestSigCompareTo(t *testing.T) { 54 | sigs := sortedSigs() 55 | shuffled := append([]Sig{}, sigs...) 56 | for i := len(shuffled) - 1; i > 0; i-- { 57 | j := rand.Intn(i + 1) 58 | shuffled[i], shuffled[j] = shuffled[j], shuffled[i] 59 | } 60 | sort.Slice(shuffled, func(i, j int) bool { 61 | return shuffled[i].CompareTo(shuffled[j]) < 0 62 | }) 63 | for i, s := range sigs { 64 | if !reflect.DeepEqual(s, shuffled[i]) { 65 | t.Fatalf("compareTo did not work correctly: sorted=%v result=%v", sigs, shuffled) 66 | } 67 | } 68 | } 69 | 70 | func sortedSigs() []Sig { 71 | sigs := []Sig{} 72 | for i := 0; i < 1; i++ { 73 | for j := 0; j < 2; j++ { 74 | for k := 0; k < 2; k++ { 75 | for l := 0; l < 2; l++ { 76 | for m := 0; m < 2; m++ { 77 | for n := 0; n < 2; n++ { 78 | sigs = append(sigs, Sig{ 79 | PublicKeyID: keys.PublicKeyID{ 80 | Algorithm: algorithmTypes.Signature(i + 1), 81 | KeySpace: keys.KeySpaceID(j), 82 | KeyPhase: k, 83 | }, 84 | ValidSince: int64(l), 85 | ValidUntil: int64(m), 86 | Data: make([]byte, 1+n), 87 | }) 88 | } 89 | } 90 | } 91 | } 92 | } 93 | } 94 | sigs = append(sigs, sigs[len(sigs)-1]) //equals 95 | return sigs 96 | } 97 | -------------------------------------------------------------------------------- /internal/pkg/token/token.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import ( 4 | "bytes" 5 | "crypto/rand" 6 | "encoding/hex" 7 | 8 | log "github.com/inconshreveable/log15" 9 | ) 10 | 11 | // Token identifies a message 12 | type Token [16]byte 13 | 14 | // String implements Stringer interface 15 | func (t Token) String() string { 16 | return hex.EncodeToString(t[:]) 17 | } 18 | 19 | // Compare returns an integer comparing two Tokens lexicographically. The result will be 0 if 20 | // a==b, -1 if a < b, and +1 if a > b. A nil argument is equivalent to an empty slice 21 | func Compare(a, b Token) int { 22 | return bytes.Compare(a[:], b[:]) 23 | } 24 | 25 | // New generates a new unique Token 26 | func New() Token { 27 | token := [16]byte{} 28 | _, err := rand.Read(token[:]) 29 | if err != nil { 30 | log.Warn("Error during random token generation", "error", err) 31 | } 32 | return Token(token) 33 | } 34 | -------------------------------------------------------------------------------- /internal/pkg/token/token_test.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGenerateToken(t *testing.T) { 8 | t1 := New() 9 | t2 := New() 10 | if t1 == t2 { 11 | t.Errorf("Subsequent generated tokens should not have the same value t1=%s t2=%s", t1, t2) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /internal/pkg/util/test/.keepme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netsec-ethz/rains/8e9ef27f2403c644ef93a07af1d4ae7c8378811d/internal/pkg/util/test/.keepme -------------------------------------------------------------------------------- /internal/pkg/zonefile/decoder.go: -------------------------------------------------------------------------------- 1 | package zonefile 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/netsec-ethz/rains/internal/pkg/object" 7 | "github.com/netsec-ethz/rains/internal/pkg/query" 8 | ) 9 | 10 | // decodeNameQueryUnsafe returns a name query. It assumes the encoding is in the correct format and 11 | // does not perform input validation 12 | func decodeNameQueryUnsafe(scanner *WordScanner) *query.Name { 13 | scanner.Scan() 14 | q := &query.Name{} 15 | q.Context = scanner.Text() 16 | scanner.Scan() 17 | q.Name = scanner.Text() 18 | scanner.Scan() 19 | q.Types = decodeObjectTypesUnsafe(scanner) 20 | scanner.Scan() 21 | q.Expiration, _ = strconv.ParseInt(scanner.Text(), 10, 64) 22 | scanner.Scan() 23 | q.Options = decodeQueryOptionsUnsafe(scanner) 24 | return q 25 | } 26 | 27 | // decodeObjectTypesUnsafe returns query connection. It assumes the encoding is in the correct format 28 | // and does not perform input validation 29 | func decodeObjectTypesUnsafe(scanner *WordScanner) []object.Type { 30 | types := []object.Type{} 31 | scanner.Scan() 32 | for scanner.Text() != "]" { 33 | val, _ := strconv.Atoi(scanner.Text()) 34 | types = append(types, object.Type(val)) 35 | scanner.Scan() 36 | } 37 | return types 38 | } 39 | 40 | // decodeQueryOptionsUnsafe returns query options. It assumes the encoding is in the correct format 41 | // and does not perform input validation 42 | func decodeQueryOptionsUnsafe(scanner *WordScanner) []query.Option { 43 | options := []query.Option{} 44 | scanner.Scan() 45 | for scanner.Text() != "]" { 46 | val, _ := strconv.Atoi(scanner.Text()) 47 | options = append(options, query.Option(val)) 48 | scanner.Scan() 49 | } 50 | return options 51 | } 52 | -------------------------------------------------------------------------------- /internal/pkg/zonefile/encoder.go: -------------------------------------------------------------------------------- 1 | package zonefile 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | 8 | "github.com/netsec-ethz/rains/internal/pkg/message" 9 | "github.com/netsec-ethz/rains/internal/pkg/object" 10 | "github.com/netsec-ethz/rains/internal/pkg/query" 11 | "github.com/netsec-ethz/rains/internal/pkg/section" 12 | ) 13 | 14 | // encodeMessage returns a rains message as a string in signable format (which resembles the zone file format) 15 | func encodeMessage(m *message.Message) string { 16 | return fmt.Sprintf(":M: %s %s [\n%s\n]", encodeCapabilities(m.Capabilities), m.Token.String(), IO{}.Encode(m.Content)) 17 | } 18 | 19 | // encodeQuery returns an encoding which resembles the zone file format 20 | func encodeQuery(q *query.Name) string { 21 | return fmt.Sprintf(":Q: %s %s %s %d %s", q.Context, q.Name, encodeObjectTypes(q.Types), 22 | q.Expiration, encodeQueryOptions(q.Options)) 23 | } 24 | 25 | // encodeNotification returns a notification in signable format (which resembles the zone file format) 26 | func encodeNotification(n *section.Notification) string { 27 | return fmt.Sprintf(":N: %s %s %s", n.Token.String(), strconv.Itoa(int(n.Type)), n.Data) 28 | } 29 | 30 | // encodeCapabilities returns capabilities separated by space in signable format (which resembles the zone file format) 31 | func encodeCapabilities(caps []message.Capability) string { 32 | encodedCaps := make([]string, len(caps)) 33 | for i, capa := range caps { 34 | encodedCaps[i] = string(capa) 35 | } 36 | return fmt.Sprintf("[ %s ]", strings.Join(encodedCaps, " ")) 37 | } 38 | 39 | // encodeQueryOptions returns query options separated by space in signable format (which resembles the zone file format) 40 | func encodeQueryOptions(qopts []query.Option) string { 41 | encodedQO := make([]string, len(qopts)) 42 | for i, qopt := range qopts { 43 | encodedQO[i] = strconv.Itoa(int(qopt)) 44 | } 45 | return fmt.Sprintf("[ %s ]", strings.Join(encodedQO, " ")) 46 | } 47 | 48 | // encodeObjectTypes returns query connection separated by space in signable format (which resembles the zone file format) 49 | func encodeObjectTypes(objs []object.Type) string { 50 | encodedOT := make([]string, len(objs)) 51 | for i, objType := range objs { 52 | encodedOT[i] = strconv.Itoa(int(objType)) 53 | } 54 | return fmt.Sprintf("[ %s ]", strings.Join(encodedOT, " ")) 55 | } 56 | -------------------------------------------------------------------------------- /internal/pkg/zonefile/encoder_test.go: -------------------------------------------------------------------------------- 1 | package zonefile 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/netsec-ethz/rains/internal/pkg/message" 7 | ) 8 | 9 | func TestEncodeQuery(t *testing.T) { 10 | queries, encodings := getQueriesAndEncodings() 11 | for i, query := range queries { 12 | encodedQ := encodeQuery(query) 13 | if encodedQ != encodings[i] { 14 | t.Errorf("Encoding wrong. expected=%s actual=%s", encodings[i], encodedQ) 15 | } 16 | } 17 | } 18 | 19 | func TestEncodeNotification(t *testing.T) { 20 | notifications, encodings := getNotificationsAndEncodings() 21 | for i, notification := range notifications { 22 | encodedN := encodeNotification(notification) 23 | if encodedN != encodings[i] { 24 | t.Errorf("Encoding wrong. expected=%s actual=%s", encodings[i], encodedN) 25 | } 26 | } 27 | } 28 | 29 | func TestMessageEncoding(t *testing.T) { 30 | messages, encodings := getMessagesAndEncodings() 31 | for i, message := range messages { 32 | encodedM := encodeMessage(message) 33 | if encodedM != encodings[i] { 34 | t.Errorf("Encoding wrong. expected=%s actual=%s", encodings[i], encodedM) 35 | } 36 | } 37 | } 38 | 39 | func TestEncodeCapabilities(t *testing.T) { 40 | var tests = []struct { 41 | input []message.Capability 42 | want string 43 | }{ 44 | {[]message.Capability{message.Capability("capa1")}, "[ capa1 ]"}, 45 | {[]message.Capability{message.Capability("capa1"), message.Capability("capa2")}, "[ capa1 capa2 ]"}, 46 | } 47 | for _, test := range tests { 48 | if encodeCapabilities(test.input) != test.want { 49 | t.Errorf("Encoding incorrect. expected=%s, actual=%s", test.want, encodeCapabilities(test.input)) 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /internal/pkg/zonefile/test/newzonefile.txt: -------------------------------------------------------------------------------- 1 | :Z: ch. . [ 2 | :A: ch [ :name: a [ :ip4: :ip6: ] ] 3 | :A: ch [ :ip4: 192.168.1.10 ] 4 | :A: ethz [ 5 | :ip6: 2001:db8:85a3::8a2e:370:7334 6 | :ip4: 129.132.128.139 7 | ] 8 | :A: ch [ :redir: ns.ch. ] 9 | :A: ch [ :deleg: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ] 10 | :A: ch [ :nameset: [:alpha:][:alnum:]* ] 11 | :A: ch [ :cert: :tls: :endEntity: :sha256: e28b1bd3a73882b198dfe4f0fa954c ] 12 | :A: ch [ :srv: dns 53 0 ] 13 | :A: ch [ :regr: registrar text ] 14 | :A: ch [ :regt: registrant info ] 15 | :A: ch [ :infra: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ] 16 | :A: ch [ :extra: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ] 17 | :A: ch [ :next: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 100000 20000000 ] 18 | :A: ch [ :ip4: 192.168.1.10 ] 19 | :A: ch [ :ip4: 192.168.1.10 ] ( :sig: :ed25519: :rains: 1 2000 5000 ) 20 | 21 | ] ( :sig: :ed25519: :rains: 1 2000 5000 ) 22 | 23 | :S: ch. . < > [ 24 | :A: ch [ :name: a [ :ip4: :ip6: ] ] 25 | :A: ch [ :ip4: 192.168.1.10 ] 26 | :A: ethz [ 27 | :ip6: 2001:db8:85a3::8a2e:370:7334 28 | :ip6: 129.132.128.139 29 | ] 30 | :A: ch [ :redir: ns.ch. ] 31 | :A: ch [ :deleg: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ] 32 | :A: ch [ :nameset: [:alpha:][:alnum:]* ] 33 | :A: ch [ :cert: :tls: :endEntity: :sha256: e28b1bd3a73882b198dfe4f0fa954c ] 34 | :A: ch [ :srv: dns 53 0 ] 35 | :A: ch [ :regr: registrar text ] 36 | :A: ch [ :regt: registrant info ] 37 | :A: ch [ :infra: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ] 38 | :A: ch [ :extra: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ] 39 | :A: ch [ :next: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 100000 20000000 ] 40 | :A: ch [ :ip4: 192.168.1.10 ] ( :sig: :ed25519: :rains: 1 2000 5000 ) 41 | 42 | :A: ch [ :ip4: 192.168.1.10 ] 43 | ] ( :sig: :ed25519: :rains: 1 2000 5000 ) 44 | 45 | :P: ch. . < > :bloomKM12: :shake256: e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 46 | 47 | :P: ch. . < > :bloomKM16: :fnv128: e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 48 | 49 | :P: ch. . < > :bloomKM20: :fnv64: e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 50 | 51 | :P: ch. . < > :bloomKM24: :shake256: e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ( :sig: :ed25519: :rains: 1 2000 5000 ) 52 | 53 | :A: www ch. . [ :ip4: 192.168.1.10 ] ( :sig: :ed25519: :rains: 1 2000 5000 ) 54 | 55 | :A: www ethz.ch. . [ :scion: 2-ff00:0:222,[2001:db8:85a3::8a2e:370:7334] ] -------------------------------------------------------------------------------- /internal/pkg/zonefile/test/zonefile.txt: -------------------------------------------------------------------------------- 1 | :Z: ch. . [ 2 | :A: ch [ :name: a [ :ip4: :ip6: ] ] 3 | :A: ch [ :ip4: 192.168.1.10 ] 4 | :A: ethz [ 5 | :ip6: 2001:db8:85a3::8a2e:370:7334 6 | :ip4: 129.132.128.139 7 | ] 8 | :A: ch [ :redir: ns.ch. ] 9 | :A: ch [ :deleg: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ] 10 | :A: ch [ :nameset: [:alpha:][:alnum:]* ] 11 | :A: ch [ :cert: :tls: :endEntity: :sha256: e28b1bd3a73882b198dfe4f0fa954c ] 12 | :A: ch [ :srv: dns 53 0 ] 13 | :A: ch [ :regr: registrar text ] 14 | :A: ch [ :regt: registrant info ] 15 | :A: ch [ :infra: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ] 16 | :A: ch [ :extra: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ] 17 | :A: ch [ :next: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 100000 20000000 ] 18 | :A: ch [ :ip4: 192.168.1.10 ] 19 | :A: ch [ :ip4: 192.168.1.10 ] ( :sig: :ed25519: :rains: 1 2000 5000 ) 20 | 21 | ] ( :sig: :ed25519: :rains: 1 2000 5000 ) 22 | 23 | :S: ch. . < > [ 24 | :A: ch [ :name: a [ :ip4: :ip6: ] ] 25 | :A: ch [ :ip4: 192.168.1.10 ] 26 | :A: ethz [ 27 | :ip6: 2001:db8:85a3::8a2e:370:7334 28 | :ip6: 129.132.128.139 29 | ] 30 | :A: ch [ :redir: ns.ch. ] 31 | :A: ch [ :deleg: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ] 32 | :A: ch [ :nameset: [:alpha:][:alnum:]* ] 33 | :A: ch [ :cert: :tls: :endEntity: :sha256: e28b1bd3a73882b198dfe4f0fa954c ] 34 | :A: ch [ :srv: dns 53 0 ] 35 | :A: ch [ :regr: registrar text ] 36 | :A: ch [ :regt: registrant info ] 37 | :A: ch [ :infra: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ] 38 | :A: ch [ :extra: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ] 39 | :A: ch [ :next: :ed25519: 5 e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 100000 20000000 ] 40 | :A: ch [ :ip4: 192.168.1.10 ] ( :sig: :ed25519: :rains: 1 2000 5000 ) 41 | 42 | :A: ch [ :ip4: 192.168.1.10 ] 43 | ] ( :sig: :ed25519: :rains: 1 2000 5000 ) 44 | 45 | :P: ch. . < > :bloomKM12: :shake256: e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 46 | 47 | :P: ch. . < > :bloomKM16: :fnv128: e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 48 | 49 | :P: ch. . < > :bloomKM20: :fnv64: e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 50 | 51 | :P: ch. . < > :bloomKM24: :shake256: e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 ( :sig: :ed25519: :rains: 1 2000 5000 ) 52 | 53 | :A: www ch. . [ :ip4: 192.168.1.10 ] ( :sig: :ed25519: :rains: 1 2000 5000 ) 54 | 55 | :A: www ethz.ch. . [ :scion: 2-ff00:0:222,[2001:db8:85a3::8a2e:370:7334] ] 56 | -------------------------------------------------------------------------------- /internal/pkg/zonefile/zoneFileIO_test.go: -------------------------------------------------------------------------------- 1 | package zonefile 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "fmt" 7 | "io/ioutil" 8 | "strings" 9 | "testing" 10 | 11 | "github.com/netsec-ethz/rains/internal/pkg/section" 12 | ) 13 | 14 | func TestEncodeDecodeZone(t *testing.T) { 15 | zone, err := IO{}.LoadZonefile("test/zonefile.txt") 16 | if err != nil { 17 | t.Error(err) 18 | } 19 | sections := []section.Section{} 20 | for _, e := range zone { 21 | sections = append(sections, e) 22 | } 23 | err = IO{}.EncodeAndStore("test/newzonefile.txt", sections) 24 | origData, _ := ioutil.ReadFile("test/zonefile.txt") 25 | newData, _ := ioutil.ReadFile("test/newzonefile.txt") 26 | scanner1 := bufio.NewScanner(bytes.NewReader(origData)) 27 | scanner2 := bufio.NewScanner(bytes.NewReader(newData)) 28 | scanner1.Split(bufio.ScanWords) 29 | scanner2.Split(bufio.ScanWords) 30 | go1 := scanner1.Scan() 31 | go2 := scanner2.Scan() 32 | if go1 != go2 { 33 | t.Error("One file has more content") 34 | } 35 | for go1 { 36 | if scanner1.Text() != scanner2.Text() { 37 | t.Error("Content is different at token level", "a=", scanner1.Text(), "b=", scanner2.Text()) 38 | } 39 | go1 = scanner1.Scan() 40 | go2 = scanner2.Scan() 41 | if go1 != go2 { 42 | t.Error("One file has more content") 43 | } 44 | } 45 | 46 | // Check reencoding single assertions works 47 | scanner3 := bufio.NewScanner(bytes.NewReader(origData)) 48 | scanner4 := bufio.NewScanner(bytes.NewReader(newData)) 49 | scanner3.Split(bufio.ScanLines) 50 | scanner4.Split(bufio.ScanLines) 51 | go3 := scanner3.Scan() 52 | go4 := scanner4.Scan() 53 | var next string 54 | if go3 != go4 { 55 | t.Error("One file has more lines") 56 | } 57 | for go3 { 58 | if scanner3.Text() != scanner4.Text() { 59 | t.Error("Content is different at line level", scanner3.Text(), scanner4.Text()) 60 | } 61 | next = scanner3.Text() 62 | go3 = scanner3.Scan() 63 | go4 = scanner4.Scan() 64 | if go3 != go4 { 65 | t.Error("One file has more lines") 66 | } 67 | } 68 | 69 | decodedSection := decode(t, []byte(next))[0] 70 | stringSection := strings.TrimSpace(IO{}.Encode([]section.Section{decodedSection})) 71 | if next != stringSection { 72 | t.Error(fmt.Sprintf("Content is different:\nExpected:\t'%v'\nGot:\t\t'%v'", next, stringSection)) 73 | } 74 | } 75 | 76 | func decode(t *testing.T, input []byte) []section.WithSigForward { 77 | zfParser := IO{} 78 | sections, err := zfParser.Decode(input) 79 | if err != nil { 80 | t.Error(fmt.Sprintf("Was not able to parse section: %v", err)) 81 | } 82 | return sections 83 | } 84 | -------------------------------------------------------------------------------- /internal/pkg/zonefile/zoneFileWordScanner.go: -------------------------------------------------------------------------------- 1 | package zonefile 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "fmt" 7 | "strings" 8 | ) 9 | 10 | // NewWordScanner returns a WordScanner 11 | func NewWordScanner(data []byte) *WordScanner { 12 | scanner := bufio.NewScanner(bytes.NewReader(data)) 13 | scanner.Split(bufio.ScanWords) 14 | return &WordScanner{data: data, scanner: scanner, wordsRead: 0} 15 | } 16 | 17 | // WordScanner uses bufio.Scanner to scan words of the input. Additionally it keeps track of the line (of the input) on which the scanner currently is 18 | type WordScanner struct { 19 | data []byte 20 | scanner *bufio.Scanner 21 | wordsRead int 22 | } 23 | 24 | // Scan moves the Scanner to the next Token, which will then be available through the Bytes or Text method. 25 | // False is returned when the scan stops, either by reaching the end of the input or an error. 26 | func (ws *WordScanner) Scan() bool { 27 | ws.wordsRead++ 28 | return ws.scanner.Scan() 29 | } 30 | 31 | // Text returns the value of the current Token generated by a call to Scan as a newly allocated string. 32 | func (ws *WordScanner) Text() string { 33 | return ws.scanner.Text() 34 | } 35 | 36 | func (ws *WordScanner) TextLine() string { 37 | return fmt.Sprintf("%s at line %d", ws.Text(), ws.LineNumber()) 38 | } 39 | 40 | // LineNumber returns the number of the line of the input data on which the current Token of the scanner is. 41 | func (ws *WordScanner) LineNumber() int { 42 | lineScanner := bufio.NewScanner(bytes.NewReader(ws.data)) 43 | i := 0 44 | lineNr := 1 45 | for lineScanner.Scan() && i < ws.wordsRead { 46 | scanner := bufio.NewScanner(strings.NewReader(lineScanner.Text())) 47 | scanner.Split(bufio.ScanWords) 48 | for scanner.Scan() { 49 | i++ 50 | if i == ws.wordsRead { 51 | return lineNr 52 | } 53 | } 54 | lineNr++ 55 | } 56 | return lineNr 57 | } 58 | -------------------------------------------------------------------------------- /internal/pkg/zonefile/zoneFileWordScanner_test.go: -------------------------------------------------------------------------------- 1 | package zonefile 2 | 3 | import "testing" 4 | 5 | func TestWordScanner(t *testing.T) { 6 | var tests = []struct { 7 | input string 8 | scansCalls int 9 | lineNumber int 10 | text string 11 | }{ 12 | {"Hello my name", 2, 1, "my"}, 13 | {"Hello\tmy\tname", 2, 1, "my"}, 14 | {"Hello\tmy\nname", 2, 1, "my"}, 15 | {"Hello my\nname", 3, 2, "name"}, 16 | {"Hello\tmy\n\nname", 3, 3, "name"}, 17 | {"Hello\tmy\n\nname \t\nis", 4, 4, "is"}, 18 | {"Hello\tmy\n\nname \t\nis", 5, 5, ""}, 19 | } 20 | for _, test := range tests { 21 | scanner := NewWordScanner([]byte(test.input)) 22 | for i := 0; i < test.scansCalls; i++ { 23 | scanner.Scan() 24 | } 25 | if scanner.Text() != test.text { 26 | t.Errorf("Wrong test. expected=%s, actual=%s", test.text, scanner.Text()) 27 | } 28 | if scanner.LineNumber() != test.lineNumber { 29 | t.Errorf("Line number incorrect. expected=%d, actual=%d", test.lineNumber, scanner.LineNumber()) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /pkg/rains/option_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=Option"; DO NOT EDIT. 2 | 3 | package rains 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[QOMinE2ELatency-1] 12 | _ = x[QOMinLastHopAnswerSize-2] 13 | _ = x[QOMinInfoLeakage-3] 14 | _ = x[QOCachedAnswersOnly-4] 15 | _ = x[QOExpiredAssertionsOk-5] 16 | _ = x[QOTokenTracing-6] 17 | _ = x[QONoVerificationDelegation-7] 18 | _ = x[QONoProactiveCaching-8] 19 | _ = x[QOMaxFreshness-9] 20 | } 21 | 22 | const _Option_name = "QOMinE2ELatencyQOMinLastHopAnswerSizeQOMinInfoLeakageQOCachedAnswersOnlyQOExpiredAssertionsOkQOTokenTracingQONoVerificationDelegationQONoProactiveCachingQOMaxFreshness" 23 | 24 | var _Option_index = [...]uint8{0, 15, 37, 53, 72, 93, 107, 133, 153, 167} 25 | 26 | func (i Option) String() string { 27 | i -= 1 28 | if i < 0 || i >= Option(len(_Option_index)-1) { 29 | return "Option(" + strconv.FormatInt(int64(i+1), 10) + ")" 30 | } 31 | return _Option_name[_Option_index[i]:_Option_index[i+1]] 32 | } 33 | -------------------------------------------------------------------------------- /pkg/rains/options.go: -------------------------------------------------------------------------------- 1 | package rains 2 | 3 | import ( 4 | "github.com/netsec-ethz/rains/internal/pkg/query" 5 | ) 6 | 7 | // Option enables a client or server to specify performance/privacy tradeoffs 8 | type Option int 9 | 10 | //go:generate stringer -type=Option 11 | const ( 12 | QOMinE2ELatency Option = iota + 1 13 | QOMinLastHopAnswerSize 14 | QOMinInfoLeakage 15 | QOCachedAnswersOnly 16 | QOExpiredAssertionsOk 17 | QOTokenTracing 18 | QONoVerificationDelegation 19 | QONoProactiveCaching 20 | QOMaxFreshness 21 | ) 22 | 23 | // AllOptions returns all query options 24 | func AllOptions() []Option { 25 | return []Option{QOMinE2ELatency, QOMinLastHopAnswerSize, 26 | QOMinInfoLeakage, QOCachedAnswersOnly, 27 | QOExpiredAssertionsOk, QOTokenTracing, 28 | QONoVerificationDelegation, 29 | QONoProactiveCaching, QOMaxFreshness} 30 | } 31 | 32 | func convertOpts(opts []Option) []query.Option { 33 | var qOpts []query.Option 34 | for _, o := range opts { 35 | qOpts = append(qOpts, query.Option(o)) 36 | } 37 | return qOpts 38 | } 39 | -------------------------------------------------------------------------------- /pkg/rains/query.go: -------------------------------------------------------------------------------- 1 | package rains 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "time" 7 | 8 | "github.com/netsec-ethz/rains/internal/pkg/message" 9 | "github.com/netsec-ethz/rains/internal/pkg/section" 10 | "github.com/netsec-ethz/rains/internal/pkg/token" 11 | "github.com/netsec-ethz/rains/internal/pkg/util" 12 | "github.com/netsec-ethz/rains/internal/pkg/zonefile" 13 | ) 14 | 15 | // Message carries the reply received from the a RAINS server 16 | type Message struct { 17 | 18 | // embedded message type 19 | msg message.Message 20 | } 21 | 22 | // ParseMessage parses the message and returns a map mapping all object types found in the assertion to their value 23 | func (m *Message) ParseMessage() (map[Type]string, error) { 24 | 25 | // we expect exactly one section, an assertion 26 | if len(m.msg.Content) != 1 { 27 | return nil, fmt.Errorf("message contains invalid number of sections") 28 | } 29 | 30 | assertion, ok := m.msg.Content[0].(*section.Assertion) 31 | if !ok { 32 | return nil, fmt.Errorf("message is not an assertion") 33 | } 34 | 35 | vals := make(map[Type]string) 36 | for _, cont := range assertion.Content { 37 | vals[Type(cont.Type)] = fmt.Sprintf("%v", cont.Value) 38 | } 39 | 40 | return vals, nil 41 | } 42 | 43 | func (m Message) String() string { 44 | return formatSections(m.msg.Content) 45 | } 46 | 47 | // Query queries the RAINS server at addr for name and returns a map of values 48 | // each corresponding to a type requested by types 49 | func Query(name, context string, types []Type, opts []Option, 50 | expire, timeout time.Duration, addr net.Addr) (map[Type]string, error) { 51 | 52 | raw, err := QueryRaw(name, context, types, opts, expire, timeout, addr) 53 | if err != nil { 54 | return nil, err 55 | } 56 | res, err := raw.ParseMessage() 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | // only return requested types 62 | var m = map[Type]string{} 63 | for _, t := range types { 64 | m[t] = res[t] 65 | } 66 | 67 | return m, nil 68 | } 69 | 70 | // QueryRaw queries the RAINS server at addr for name and returns the raw reply 71 | func QueryRaw(name, context string, types []Type, opts []Option, 72 | expire, timeout time.Duration, addr net.Addr) (Message, error) { 73 | 74 | token := token.New() 75 | qTypes := convertTyps(types) 76 | qOpts := convertOpts(opts) 77 | 78 | msg := util.NewQueryMessage(name, context, time.Now().Add(expire).Unix(), qTypes, qOpts, token) 79 | reply, err := util.SendQuery(msg, addr, timeout) 80 | if err != nil { 81 | return Message{}, err 82 | } 83 | 84 | return Message{reply}, nil 85 | } 86 | 87 | // formatSections formats sections according to the zone file format 88 | func formatSections(sections []section.Section) string { 89 | return zonefile.IO{}.Encode(sections) 90 | } 91 | -------------------------------------------------------------------------------- /pkg/rains/type_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=Type"; DO NOT EDIT. 2 | 3 | package rains 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[OTName-1] 12 | _ = x[OTIP6Addr-2] 13 | _ = x[OTIP4Addr-3] 14 | _ = x[OTRedirection-4] 15 | _ = x[OTDelegation-5] 16 | _ = x[OTNameset-6] 17 | _ = x[OTCertInfo-7] 18 | _ = x[OTServiceInfo-8] 19 | _ = x[OTRegistrar-9] 20 | _ = x[OTRegistrant-10] 21 | _ = x[OTInfraKey-11] 22 | _ = x[OTExtraKey-12] 23 | _ = x[OTNextKey-13] 24 | _ = x[OTScionAddr-14] 25 | } 26 | 27 | const _Type_name = "OTNameOTIP6AddrOTIP4AddrOTRedirectionOTDelegationOTNamesetOTCertInfoOTServiceInfoOTRegistrarOTRegistrantOTInfraKeyOTExtraKeyOTNextKeyOTScionAddr" 28 | 29 | var _Type_index = [...]uint8{0, 6, 15, 24, 37, 49, 58, 68, 81, 92, 104, 114, 124, 133, 144} 30 | 31 | func (i Type) String() string { 32 | i -= 1 33 | if i < 0 || i >= Type(len(_Type_index)-1) { 34 | return "Type(" + strconv.FormatInt(int64(i+1), 10) + ")" 35 | } 36 | return _Type_name[_Type_index[i]:_Type_index[i+1]] 37 | } 38 | -------------------------------------------------------------------------------- /pkg/rains/types.go: -------------------------------------------------------------------------------- 1 | package rains 2 | 3 | import ( 4 | "github.com/netsec-ethz/rains/internal/pkg/object" 5 | ) 6 | 7 | // Type identifier for object connection. ID chosen according to RAINS Protocol Specification 8 | type Type int 9 | 10 | //go:generate stringer -type=Type 11 | const ( 12 | OTName Type = iota + 1 13 | OTIP6Addr 14 | OTIP4Addr 15 | OTRedirection 16 | OTDelegation 17 | OTNameset 18 | OTCertInfo 19 | OTServiceInfo 20 | OTRegistrar 21 | OTRegistrant 22 | OTInfraKey 23 | OTExtraKey 24 | OTNextKey 25 | OTScionAddr 26 | ) 27 | 28 | // AllTypes returns all object types 29 | func AllTypes() []Type { 30 | return []Type{OTName, OTIP6Addr, OTIP4Addr, OTRedirection, 31 | OTDelegation, OTNameset, OTCertInfo, OTServiceInfo, 32 | OTRegistrar, OTRegistrant, OTInfraKey, OTExtraKey, 33 | OTNextKey, OTScionAddr} 34 | } 35 | 36 | func convertTyps(types []Type) []object.Type { 37 | var oTypes []object.Type 38 | for _, t := range types { 39 | oTypes = append(oTypes, object.Type(t)) 40 | } 41 | return oTypes 42 | } 43 | -------------------------------------------------------------------------------- /rains.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netsec-ethz/rains/8e9ef27f2403c644ef93a07af1d4ae7c8378811d/rains.graffle -------------------------------------------------------------------------------- /test/integration/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | This document describes the different components of the integration test and what we are testing. 4 | 5 | ## Topology 6 | 7 | The integration consists of three authoritative servers, 2 caching resolvers and a client sending 8 | queries to the two caching resolvers. There is one authoritative server for the root, a TLD and a 9 | SLD. The SLD is a subzone of the TLD. The caching resolvers start their recursive lookups at the 10 | root and get then referred to the other authoritative servers. 11 | 12 | ## Queries 13 | The queries the client is going to send and expected answers are stored in a file located at 14 | 'testdata/messages/messages.txt'. The query must be on a single line. The answer sections must be on 15 | the following line(s). An empty line marks the end of the answer. Queries are represented in a 16 | zonefile like format and answers are represented in zonefile format. 17 | 18 | ## Test 19 | 20 | The integration test covers the following parts: 21 | 22 | - Loading files such as config, zonefile, keys, checkpoints, certificates 23 | - tcp connection handling and sending messages over tcp between all components 24 | - SCION connection handling and sending messages over SCION between all components 25 | (To run the SCION part of the integration test, you need to have SCION installed and 26 | start a local topology like this, WARNING this overwrites the gen folder: 27 | ``` 28 | cd $SC; PYTHONPATH=$PYTHONPATH:$SC/topology:$SC/python python/topology/generator.py -c $SC/topology/Tiny.topo 29 | echo '1-ff00_0_110' > ./gen/ia 30 | ./supervisor/supervisor.sh reload 31 | ./supervisor/supervisor.sh start dispatcher 32 | ./supervisor/supervisor.sh start as1-ff00_0_110:* 33 | ``` 34 | - recursive lookup with and without alias 35 | - preprocessing and publishing zone information 36 | - preloading caches of a caching resolver from checkpoint files 37 | - a caching resolver answers with cached entries if present 38 | - marshal and unmarshal of messages and sections 39 | - signing sections and verifying signatures 40 | - queries are correctly answered 41 | - key generation, storing and loading 42 | 43 | ## Coverage 44 | The file fullCoverageTCP.go must be present and include all paths for which we want to do coverage 45 | measurements. Otherwise the coverage tool does not add instrumentation code to these packages. 46 | 47 | To create coverage measurements execute the following commands: 48 | - go test -coverprofile=coverage.out -coverpkg=../../internal/pkg/... 49 | - go tool cover -html=coverage.out -o coverage.html 50 | - firefox coverage.html -------------------------------------------------------------------------------- /test/integration/fullCoverageSCION.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | "net" 5 | 6 | "github.com/netsec-ethz/rains/internal/pkg/libresolve" 7 | "github.com/netsec-ethz/rains/internal/pkg/publisher" 8 | "github.com/netsec-ethz/rains/internal/pkg/rainsd" 9 | "github.com/netsec-ethz/rains/internal/pkg/util" 10 | ) 11 | 12 | /* 13 | * This file must be present and include all paths for which we want to do coverage measurements. 14 | * Otherwise the coverage tool does not add instrumentation code to these packages. 15 | */ 16 | 17 | func AddCoverageInstrumentationSCION() { 18 | rainsd.New(rainsd.Config{}, "") 19 | publisher.New(publisher.Config{}) 20 | libresolve.New(nil, nil, "", libresolve.Recursive, &net.TCPAddr{}, 1000, util.MaxCacheValidity{}, 50) 21 | } 22 | -------------------------------------------------------------------------------- /test/integration/fullCoverageTCP.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | "net" 5 | 6 | "github.com/netsec-ethz/rains/internal/pkg/libresolve" 7 | "github.com/netsec-ethz/rains/internal/pkg/publisher" 8 | "github.com/netsec-ethz/rains/internal/pkg/rainsd" 9 | "github.com/netsec-ethz/rains/internal/pkg/util" 10 | ) 11 | 12 | /* 13 | * This file must be present and include all paths for which we want to do coverage measurements. 14 | * Otherwise the coverage tool does not add instrumentation code to these packages. 15 | */ 16 | 17 | func AddCoverageInstrumentation() { 18 | rainsd.New(rainsd.Config{}, "") 19 | publisher.New(publisher.Config{}) 20 | libresolve.New(nil, nil, "", libresolve.Recursive, &net.TCPAddr{}, 1000, util.MaxCacheValidity{}, 50) 21 | } 22 | -------------------------------------------------------------------------------- /test/integration/testdata/cert/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID5TCCAs2gAwIBAgIJAJGmPmx+xCpcMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYD 3 | VQQGEwJDSDEPMA0GA1UECAwGWnVyaWNoMQ8wDQYDVQQHDAZadXJpY2gxDDAKBgNV 4 | BAoMA0VUSDEPMA0GA1UECwwGTmV0U2VjMQ8wDQYDVQQDDAZzZXJ2ZXIxJzAlBgkq 5 | hkiG9w0BCQEWGGZlaGxtYWNoQHN0dWRlbnQuZXRoei5jaDAeFw0xNzAzMTMxMDE3 6 | MTlaFw0yNzAzMTExMDE3MTlaMIGIMQswCQYDVQQGEwJDSDEPMA0GA1UECAwGWnVy 7 | aWNoMQ8wDQYDVQQHDAZadXJpY2gxDDAKBgNVBAoMA0VUSDEPMA0GA1UECwwGTmV0 8 | U2VjMQ8wDQYDVQQDDAZzZXJ2ZXIxJzAlBgkqhkiG9w0BCQEWGGZlaGxtYWNoQHN0 9 | dWRlbnQuZXRoei5jaDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANaI 10 | rGRyjAKsj7Ma1xwXT7vlB1Bstr60GRQr/QKCr3EadhgXfX4u4SlCnoswVV8X8t9v 11 | Ik8lxozfO/jYrJd/J2YG+cRHlm5dVR2t3cAe+AhhOyMi9tpBcGY9uizeD5sPyGqh 12 | 3ZF4XjqMQyN5N8OANNNCEs87zYfwVDzifR2tYpZdUMKjI0G7WpydSmywKjZq11VE 13 | 8rgd6vOGimLOLZaxS3yA+N2d8L9YAohBAKrhCUaDnqt5Yj092e3QP5hBuyjR+NSd 14 | vCVX/fAMVMkUSD+QpLR8RYEK8ykHCZzWJaNO6vH41KAyZiE34H4rg05booADnF0B 15 | gbDY2ClVV/iwYs0KgIkCAwEAAaNQME4wHQYDVR0OBBYEFAkWeBV9SFceJAxe6J/g 16 | ZeC2fJeZMB8GA1UdIwQYMBaAFAkWeBV9SFceJAxe6J/gZeC2fJeZMAwGA1UdEwQF 17 | MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAGSKwxsOau6GcQEF7La3aoVba3bRanQh 18 | /EJVzSc4GECTgonMFnn3PfzOTTG4iL5FPyLZ9Hu3pJXwP7eyHwR9sGYvvepDhwXA 19 | 0syIuR282H06ByXwl8nIQRjRi1agISEZAyp1Y3iEkEjmCE1PUKAK4qzFvSTSdJJv 20 | tBk5pNPDR/UJwH1kK375cpeFjSH4sw4yIz13fAfrOV2y5n7yN8/dj1pNse7V5vKo 21 | thj2gY5vhK5JpSdRP5Tiwb6nju/zj8AxxVpWlX3I6PeQ+yCTPPVvIBCd1EiJwYyI 22 | y+QQwhgbAkl8kkGwLh5q8TcgFeHzkHcc/nQQdoMRBBnGpjKZ44Egrpg= 23 | -----END CERTIFICATE----- 24 | -------------------------------------------------------------------------------- /test/integration/testdata/cert/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEA1oisZHKMAqyPsxrXHBdPu+UHUGy2vrQZFCv9AoKvcRp2GBd9 3 | fi7hKUKeizBVXxfy328iTyXGjN87+Nisl38nZgb5xEeWbl1VHa3dwB74CGE7IyL2 4 | 2kFwZj26LN4Pmw/IaqHdkXheOoxDI3k3w4A000ISzzvNh/BUPOJ9Ha1ill1QwqMj 5 | QbtanJ1KbLAqNmrXVUTyuB3q84aKYs4tlrFLfID43Z3wv1gCiEEAquEJRoOeq3li 6 | PT3Z7dA/mEG7KNH41J28JVf98AxUyRRIP5CktHxFgQrzKQcJnNYlo07q8fjUoDJm 7 | ITfgfiuDTluigAOcXQGBsNjYKVVX+LBizQqAiQIDAQABAoIBABCny7qAqh4LB50A 8 | GHM13BraTRcRWZ60nL3ULHBldPly9HgqWrPRL+nkIirsNbSMR27RUfiTFjcZna5U 9 | JBIe7RAeuoViiWtIE7OaK/0eamM8KTsxG7kWG4PUhv+0vcFsGEMvDeSdU7N38D5w 10 | ysOC0JcWKh+spOhI4EFZ1BzZuS2zLIevFqwd4xScW5pbW3cTiuNWEhqPfyu9C06w 11 | g9XEEtmwZWdjLGK0zp8jVdcDQgW5GvlwpXJJGmzvB2DHZTOTPqiUnSg8rnYc9o6M 12 | gETY0YAFn0QYUbPpWX21n9YRNks9xLFRum91JlcFlPQbA7+yv6eLqYC3/Hnbcgfk 13 | E6Le4AECgYEA83Z/S8BGUc0Np93TrhtH+TtJbSHTzzZxtTfZPGY0lhxBjrW/1Mk3 14 | ubIlC9prlDSs3iD19melQC4gLkJqCowihLQgBpyeEElf7KvI65/J5mI1+nUwRhio 15 | 9mm6fhN8Y0pV6ekvlBhHetk9abisyoA5MgE9j70NHt+3SHUBTkE7eqECgYEA4ZTQ 16 | M4VAv21gIJwyVIl5tk8Q++UaHzLOcMDnISzefSLm6CdvoU0Cbnlun8Ps89ASShLI 17 | tb/u54h4TbjsUd8T+Fy0KZ33lCbnV29A9LUOEmem7sinqtandqsaKv+rRDXsLZQS 18 | VGPtsLRuTWygw1WaJWmvxD9k0iaaPgnRHdthZOkCgYEA8X2CerL3jUAl4XJo+3PY 19 | CmFCTduV6x2H4EbLVdvTIWpZpKKm6vvEKI+Jq541w0YUiiiLkKPyCB04kmoSIPAr 20 | dRHuCmDjcCg329vxabaPX9Pe0tXW0lC3l+P7tf7CDQK5AVHpfa4viK1e+zTRP/O7 21 | x9vvIlpVX2BsvpRAfUy7IMECgYA21dDipUK/Bdx3MOD/Mcf3bDLpuKBn8xbBy/Kj 22 | Wt/etWxCBMwa/rhXmIcuqRbhkbPQc858d+KgP8lWw1wW7s5Q8mANOcwkJGzaET5N 23 | /fEkwjOPGhG/8pwUubULvMiqNR1rWvI1t3DhIospoP1XXmixLYa/gtWETEP0TriZ 24 | tGlxeQKBgEJ9m4lyJMbnZr6+dMhd1DTPwXspHbb8HMgSOwoVc5OVPFK4lEHWgu1Y 25 | cXT6frGOT8Ndp2ehiZehQSkwQSfYpSWZ9iyzcTxXPj2/tTF37rUSZv0ZmxM3Vapr 26 | G89AZsRJXcr43Nn9JdL060Scw3n/HiTiGT0Tm1nu6ntkXUlkpFt5 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/SCIONnamingServerRoot.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "testdata/keys/selfSignedRootDelegationAssertion.gob", 3 | "AssertionCheckPointInterval": 3600, 4 | "NegAssertionCheckPointInterval":3600, 5 | "ZoneKeyCheckPointInterval":3600, 6 | "CheckPointPath": "testdata/checkpoint/root/", 7 | "PreLoadCaches": false, 8 | "ServerAddress": { 9 | "Type": "SCION", 10 | "SCIONAddr": "1-ff00:0:110,[127.0.0.1]:5022" 11 | }, 12 | "PublisherAddress": { 13 | "Type": "SCION", 14 | "SCIONAddr": "1-ff00:0:110,[127.0.0.1]:5022" 15 | }, 16 | "MaxConnections": 1000, 17 | "KeepAlivePeriod": 60, 18 | "TCPTimeout": 300, 19 | "TLSCertificateFile": "testdata/cert/server.crt", 20 | "TLSPrivateKeyFile": "testdata/cert/server.key", 21 | 22 | "PrioBufferSize": 20, 23 | "NormalBufferSize": 100, 24 | "NotificationBufferSize": 10, 25 | "PrioWorkerCount": 2, 26 | "NormalWorkerCount": 10, 27 | "NotificationWorkerCount": 2, 28 | "CapabilitiesCacheSize": 50, 29 | "Capabilities": ["urn:x-rains:tlssrv"], 30 | 31 | "ZoneKeyCacheSize": 1000, 32 | "ZoneKeyCacheWarnSize": 750, 33 | "MaxPublicKeysPerZone": 5, 34 | "PendingKeyCacheSize": 1000, 35 | "DelegationQueryValidity": 5, 36 | "ReapZoneKeyCacheInterval": 1800, 37 | "ReapPendingKeyCacheInterval": 1800, 38 | 39 | "AssertionCacheSize": 10000, 40 | "NegativeAssertionCacheSize": 1000, 41 | "PendingQueryCacheSize": 100, 42 | "QueryValidity": 5, 43 | "Authorities": [ 44 | { 45 | "Zone": ".", 46 | "Context": "." 47 | } 48 | ], 49 | "MaxCacheValidity": { 50 | "AssertionValidity": 720, 51 | "ShardValidity": 720, 52 | "PshardValidity": 720, 53 | "ZoneValidity": 720 54 | }, 55 | "ReapAssertionCacheInterval": 1800, 56 | "ReapNegAssertionCacheInterval": 1800, 57 | "ReapPendingQCacheInterval": 1800 58 | } 59 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/SCIONnamingServerch.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "testdata/keys/selfSignedRootDelegationAssertion.gob", 3 | "AssertionCheckPointInterval": 3600, 4 | "NegAssertionCheckPointInterval":3600, 5 | "ZoneKeyCheckPointInterval":3600, 6 | "CheckPointPath": "testdata/checkpoint/ch/", 7 | "PreLoadCaches": false, 8 | "ServerAddress": { 9 | "Type": "SCION", 10 | "SCIONAddr": "1-ff00:0:110,[127.0.0.1]:5023" 11 | }, 12 | "PublisherAddress": { 13 | "Type": "SCION", 14 | "SCIONAddr": "1-ff00:0:110,[127.0.0.1]:5023" 15 | }, 16 | "MaxConnections": 1000, 17 | "KeepAlivePeriod": 60, 18 | "TCPTimeout": 300, 19 | "TLSCertificateFile": "testdata/cert/server.crt", 20 | "TLSPrivateKeyFile": "testdata/cert/server.key", 21 | 22 | "PrioBufferSize": 20, 23 | "NormalBufferSize": 100, 24 | "NotificationBufferSize": 10, 25 | "PrioWorkerCount": 2, 26 | "NormalWorkerCount": 10, 27 | "NotificationWorkerCount": 2, 28 | "CapabilitiesCacheSize": 50, 29 | "Capabilities": ["urn:x-rains:tlssrv"], 30 | 31 | "ZoneKeyCacheSize": 1000, 32 | "ZoneKeyCacheWarnSize": 750, 33 | "MaxPublicKeysPerZone": 5, 34 | "PendingKeyCacheSize": 1000, 35 | "DelegationQueryValidity": 5, 36 | "ReapZoneKeyCacheInterval": 1800, 37 | "ReapPendingKeyCacheInterval": 1800, 38 | 39 | "AssertionCacheSize": 10000, 40 | "NegativeAssertionCacheSize": 1000, 41 | "PendingQueryCacheSize": 100, 42 | "QueryValidity": 5, 43 | "Authorities": [ 44 | { 45 | "Zone": "ch.", 46 | "Context": "." 47 | } 48 | ], 49 | "MaxCacheValidity": { 50 | "AssertionValidity": 720, 51 | "ShardValidity": 720, 52 | "PshardValidity": 720, 53 | "ZoneValidity": 720 54 | }, 55 | "ReapAssertionCacheInterval": 1800, 56 | "ReapNegAssertionCacheInterval": 1800, 57 | "ReapPendingQCacheInterval": 1800 58 | } 59 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/SCIONnamingServerethz.ch.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "testdata/keys/selfSignedRootDelegationAssertion.gob", 3 | "AssertionCheckPointInterval": 3600, 4 | "NegAssertionCheckPointInterval":3600, 5 | "ZoneKeyCheckPointInterval":3600, 6 | "CheckPointPath": "testdata/checkpoint/ethz.ch/", 7 | "PreLoadCaches": false, 8 | "ServerAddress": { 9 | "Type": "SCION", 10 | "SCIONAddr": "1-ff00:0:110,[127.0.0.1]:5024" 11 | }, 12 | "PublisherAddress": { 13 | "Type": "SCION", 14 | "SCIONAddr": "1-ff00:0:110,[127.0.0.1]:5024" 15 | }, 16 | "MaxConnections": 1000, 17 | "KeepAlivePeriod": 60, 18 | "TCPTimeout": 300, 19 | "TLSCertificateFile": "testdata/cert/server.crt", 20 | "TLSPrivateKeyFile": "testdata/cert/server.key", 21 | 22 | "PrioBufferSize": 20, 23 | "NormalBufferSize": 100, 24 | "NotificationBufferSize": 10, 25 | "PrioWorkerCount": 2, 26 | "NormalWorkerCount": 10, 27 | "NotificationWorkerCount": 2, 28 | "CapabilitiesCacheSize": 50, 29 | "Capabilities": ["urn:x-rains:tlssrv"], 30 | 31 | "ZoneKeyCacheSize": 1000, 32 | "ZoneKeyCacheWarnSize": 750, 33 | "MaxPublicKeysPerZone": 5, 34 | "PendingKeyCacheSize": 1000, 35 | "DelegationQueryValidity": 5, 36 | "ReapZoneKeyCacheInterval": 1800, 37 | "ReapPendingKeyCacheInterval": 1800, 38 | 39 | "AssertionCacheSize": 10000, 40 | "NegativeAssertionCacheSize": 1000, 41 | "PendingQueryCacheSize": 100, 42 | "QueryValidity": 5, 43 | "Authorities": [ 44 | { 45 | "Zone": "ethz.ch.", 46 | "Context": "." 47 | } 48 | ], 49 | "MaxCacheValidity": { 50 | "AssertionValidity": 720, 51 | "ShardValidity": 720, 52 | "PshardValidity": 720, 53 | "ZoneValidity": 720 54 | }, 55 | "ReapAssertionCacheInterval": 1800, 56 | "ReapNegAssertionCacheInterval": 1800, 57 | "ReapPendingQCacheInterval": 1800 58 | } 59 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/SCIONpublisherRoot.conf: -------------------------------------------------------------------------------- 1 | { 2 | "ZonefilePath": "testdata/zonefiles/SCIONroot.txt", 3 | "AuthServers": [{ 4 | "Type": "SCION", 5 | "SCIONAddr": "1-ff00:0:110,[127.0.0.1]:5022" 6 | }], 7 | "PrivateKeyPath": "testdata/keys/root", 8 | "ShardingConf" : { 9 | "KeepShards": false, 10 | "DoSharding": true, 11 | "MaxShardSize": 1000, 12 | "NofAssertionsPerShard": -1 13 | }, 14 | "PShardingConf" : { 15 | "KeepPshards": false, 16 | "DoPsharding" : true, 17 | "NofAssertionsPerPshard" : 2, 18 | "BloomFilterConf" : { 19 | "BFAlgo" : "BloomKM12", 20 | "BFHash" : "Shake256", 21 | "BloomFilterSize" : 80 22 | } 23 | }, 24 | "MetaDataConf" : { 25 | "AddSignatureMetaData": true, 26 | "AddSigMetaDataToAssertions": true, 27 | "AddSigMetaDataToShards": true, 28 | "AddSigMetaDataToPshards": true, 29 | "SignatureAlgorithm": "Ed25519", 30 | "KeyPhase": 1, 31 | "SigValidSince": 1543840931, 32 | "SigValidUntil": 2301221742, 33 | "SigSigningInterval": 60 34 | }, 35 | "ConsistencyConf" : { 36 | "DoConsistencyCheck": true, 37 | "SortShards": true, 38 | "SortZone": true, 39 | "SigNotExpired": false, 40 | "CheckStringFields": false 41 | }, 42 | "DoSigning": true, 43 | "MaxZoneSize": 50000, 44 | "OutputPath": "", 45 | "DoPublish": true 46 | } 47 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/SCIONpublisherch.conf: -------------------------------------------------------------------------------- 1 | { 2 | "ZonefilePath": "testdata/zonefiles/SCIONch.txt", 3 | "AuthServers": [{ 4 | "Type": "SCION", 5 | "SCIONAddr": "1-ff00:0:110,[127.0.0.1]:5023" 6 | }], 7 | "PrivateKeyPath": "testdata/keys/ch", 8 | "ShardingConf" : { 9 | "KeepShards": false, 10 | "DoSharding": true, 11 | "MaxShardSize": 200, 12 | "NofAssertionsPerShard": -1 13 | }, 14 | "PShardingConf" : { 15 | "KeepPshards": false, 16 | "DoPsharding" : true, 17 | "NofAssertionsPerPshard" : 2, 18 | "BloomFilterConf" : { 19 | "BFAlgo" : "BloomKM12", 20 | "BFHash" : "Shake256", 21 | "BloomFilterSize" : 80 22 | } 23 | }, 24 | "MetaDataConf" : { 25 | "AddSignatureMetaData": true, 26 | "AddSigMetaDataToAssertions": true, 27 | "AddSigMetaDataToShards": true, 28 | "AddSigMetaDataToPshards": true, 29 | "SignatureAlgorithm": "Ed25519", 30 | "KeyPhase": 1, 31 | "SigValidSince": 1543840932, 32 | "SigValidUntil": 2301221742, 33 | "SigSigningInterval": 60 34 | }, 35 | "ConsistencyConf" : { 36 | "DoConsistencyCheck": false, 37 | "SortShards": true, 38 | "SortZone": true, 39 | "SigNotExpired": false, 40 | "CheckStringFields": false 41 | }, 42 | "DoSigning": true, 43 | "MaxZoneSize": 50000, 44 | "OutputPath": "", 45 | "DoPublish": true 46 | } 47 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/SCIONpublisherethz.ch.conf: -------------------------------------------------------------------------------- 1 | { 2 | "ZonefilePath": "testdata/zonefiles/SCIONethz.ch.txt", 3 | "AuthServers": [{ 4 | "Type": "SCION", 5 | "SCIONAddr": "1-ff00:0:110,[127.0.0.1]:5024" 6 | }], 7 | "PrivateKeyPath": "testdata/keys/ethz.ch", 8 | "ShardingConf" : { 9 | "KeepShards": false, 10 | "DoSharding": false, 11 | "MaxShardSize": -1, 12 | "NofAssertionsPerShard": 1 13 | }, 14 | "PShardingConf" : { 15 | "KeepPshards": false, 16 | "DoPsharding" : false, 17 | "NofAssertionsPerPshard" : 2, 18 | "BloomFilterConf" : { 19 | "BFAlgo" : "BloomKM12", 20 | "BFHash" : "Shake256", 21 | "BloomFilterSize" : 80 22 | } 23 | }, 24 | "MetaDataConf" : { 25 | "AddSignatureMetaData": true, 26 | "AddSigMetaDataToAssertions": true, 27 | "AddSigMetaDataToShards": true, 28 | "AddSigMetaDataToPshards": true, 29 | "SignatureAlgorithm": "Ed25519", 30 | "KeyPhase": 1, 31 | "SigValidSince": 1543840933, 32 | "SigValidUntil": 2301221742, 33 | "SigSigningInterval": 60 34 | }, 35 | "ConsistencyConf" : { 36 | "DoConsistencyCheck": false, 37 | "SortShards": true, 38 | "SortZone": true, 39 | "SigNotExpired": false, 40 | "CheckStringFields": false 41 | }, 42 | "DoSigning": true, 43 | "MaxZoneSize": 50000, 44 | "OutputPath": "", 45 | "DoPublish": true 46 | } 47 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/SCIONresolver.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "testdata/keys/selfSignedRootDelegationAssertion.gob", 3 | "AssertionCheckPointInterval": 1, 4 | "NegAssertionCheckPointInterval":1, 5 | "ZoneKeyCheckPointInterval":1, 6 | "CheckPointPath": "testdata/checkpoint/resolver/", 7 | "PreLoadCaches": false, 8 | 9 | "ServerAddress": { 10 | "Type": "SCION", 11 | "SCIONAddr": "1-ff00:0:110,[127.0.0.1]:5025" 12 | }, 13 | "MaxConnections": 1000, 14 | "KeepAlivePeriod": 60, 15 | "TCPTimeout": 300, 16 | "TLSCertificateFile": "testdata/cert/server.crt", 17 | "TLSPrivateKeyFile": "testdata/cert/server.key", 18 | 19 | "PrioBufferSize": 20, 20 | "NormalBufferSize": 100, 21 | "NotificationBufferSize": 10, 22 | "PrioWorkerCount": 2, 23 | "NormalWorkerCount": 10, 24 | "NotificationWorkerCount": 2, 25 | "CapabilitiesCacheSize": 50, 26 | "Capabilities": ["urn:x-rains:tlssrv"], 27 | 28 | "ZoneKeyCacheSize": 1000, 29 | "ZoneKeyCacheWarnSize": 750, 30 | "MaxPublicKeysPerZone": 5, 31 | "PendingKeyCacheSize": 1000, 32 | "DelegationQueryValidity": 5, 33 | "ReapZoneKeyCacheInterval": 1800, 34 | "ReapPendingKeyCacheInterval": 1800, 35 | 36 | "AssertionCacheSize": 10000, 37 | "NegativeAssertionCacheSize": 1000, 38 | "PendingQueryCacheSize": 100, 39 | "QueryValidity": 5, 40 | "Authorities": [], 41 | "MaxCacheValidity": { 42 | "AssertionValidity": 720, 43 | "ShardValidity": 720, 44 | "PshardValidity": 720, 45 | "ZoneValidity": 720 46 | }, 47 | "ReapAssertionCacheInterval": 1800, 48 | "ReapNegAssertionCacheInterval": 1800, 49 | "ReapPendingQCacheInterval": 1800 50 | } 51 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/SCIONresolver2.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "testdata/keys/selfSignedRootDelegationAssertion.gob", 3 | "AssertionCheckPointInterval": 3600, 4 | "NegAssertionCheckPointInterval":3600, 5 | "ZoneKeyCheckPointInterval":3600, 6 | "CheckPointPath": "testdata/checkpoint/resolver/", 7 | "PreLoadCaches": true, 8 | 9 | "ServerAddress": { 10 | "Type": "SCION", 11 | "SCIONAddr": "1-ff00:0:110,[127.0.0.1]:5026" 12 | }, 13 | "MaxConnections": 1000, 14 | "KeepAlivePeriod": 60, 15 | "TCPTimeout": 300, 16 | "TLSCertificateFile": "testdata/cert/server.crt", 17 | "TLSPrivateKeyFile": "testdata/cert/server.key", 18 | 19 | "PrioBufferSize": 20, 20 | "NormalBufferSize": 100, 21 | "NotificationBufferSize": 10, 22 | "PrioWorkerCount": 2, 23 | "NormalWorkerCount": 10, 24 | "NotificationWorkerCount": 2, 25 | "CapabilitiesCacheSize": 50, 26 | "Capabilities": ["urn:x-rains:tlssrv"], 27 | 28 | "ZoneKeyCacheSize": 1000, 29 | "ZoneKeyCacheWarnSize": 750, 30 | "MaxPublicKeysPerZone": 5, 31 | "PendingKeyCacheSize": 1000, 32 | "DelegationQueryValidity": 5, 33 | "ReapZoneKeyCacheInterval": 1800, 34 | "ReapPendingKeyCacheInterval": 1800, 35 | 36 | "AssertionCacheSize": 10000, 37 | "NegativeAssertionCacheSize": 1000, 38 | "PendingQueryCacheSize": 100, 39 | "QueryValidity": 5, 40 | "Authorities": [], 41 | "MaxCacheValidity": { 42 | "AssertionValidity": 720, 43 | "ShardValidity": 720, 44 | "PshardValidity": 720, 45 | "ZoneValidity": 720 46 | }, 47 | "ReapAssertionCacheInterval": 1800, 48 | "ReapNegAssertionCacheInterval": 1800, 49 | "ReapPendingQCacheInterval": 1800 50 | } 51 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/namingServerRoot.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "testdata/keys/selfSignedRootDelegationAssertion.gob", 3 | "AssertionCheckPointInterval": 3600, 4 | "NegAssertionCheckPointInterval":3600, 5 | "ZoneKeyCheckPointInterval":3600, 6 | "CheckPointPath": "testdata/checkpoint/root/", 7 | "PreLoadCaches": false, 8 | "ServerAddress": { 9 | "Type": "TCP", 10 | "TCPAddr": { 11 | "IP": "127.0.0.1", 12 | "Port": 5022, 13 | "Zone": "" 14 | } 15 | }, 16 | "PublisherAddress": { 17 | "Type": "TCP", 18 | "TCPAddr": { 19 | "IP": "127.0.0.1", 20 | "Zone": "", 21 | "Port": 5022 22 | } 23 | }, 24 | "MaxConnections": 1000, 25 | "KeepAlivePeriod": 60, 26 | "TCPTimeout": 300, 27 | "TLSCertificateFile": "testdata/cert/server.crt", 28 | "TLSPrivateKeyFile": "testdata/cert/server.key", 29 | 30 | "PrioBufferSize": 20, 31 | "NormalBufferSize": 100, 32 | "NotificationBufferSize": 10, 33 | "PrioWorkerCount": 2, 34 | "NormalWorkerCount": 10, 35 | "NotificationWorkerCount": 2, 36 | "CapabilitiesCacheSize": 50, 37 | "Capabilities": ["urn:x-rains:tlssrv"], 38 | 39 | "ZoneKeyCacheSize": 1000, 40 | "ZoneKeyCacheWarnSize": 750, 41 | "MaxPublicKeysPerZone": 5, 42 | "PendingKeyCacheSize": 1000, 43 | "DelegationQueryValidity": 5, 44 | "ReapZoneKeyCacheInterval": 1800, 45 | "ReapPendingKeyCacheInterval": 1800, 46 | 47 | "AssertionCacheSize": 10000, 48 | "NegativeAssertionCacheSize": 1000, 49 | "PendingQueryCacheSize": 100, 50 | "QueryValidity": 5, 51 | "Authorities": [ 52 | { 53 | "Zone": ".", 54 | "Context": "." 55 | } 56 | ], 57 | "MaxCacheValidity": { 58 | "AssertionValidity": 720, 59 | "ShardValidity": 720, 60 | "PshardValidity": 720, 61 | "ZoneValidity": 720 62 | }, 63 | "ReapAssertionCacheInterval": 1800, 64 | "ReapNegAssertionCacheInterval": 1800, 65 | "ReapPendingQCacheInterval": 1800 66 | } 67 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/namingServerch.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "testdata/keys/selfSignedRootDelegationAssertion.gob", 3 | "AssertionCheckPointInterval": 3600, 4 | "NegAssertionCheckPointInterval":3600, 5 | "ZoneKeyCheckPointInterval":3600, 6 | "CheckPointPath": "testdata/checkpoint/ch/", 7 | "PreLoadCaches": false, 8 | "ServerAddress": { 9 | "Type": "TCP", 10 | "TCPAddr": { 11 | "IP": "127.0.0.1", 12 | "Port": 5023 13 | } 14 | }, 15 | "PublisherAddress": { 16 | "Type": "TCP", 17 | "TCPAddr": { 18 | "IP": "127.0.0.1" 19 | } 20 | }, 21 | "MaxConnections": 1000, 22 | "KeepAlivePeriod": 60, 23 | "TCPTimeout": 300, 24 | "TLSCertificateFile": "testdata/cert/server.crt", 25 | "TLSPrivateKeyFile": "testdata/cert/server.key", 26 | 27 | "PrioBufferSize": 20, 28 | "NormalBufferSize": 100, 29 | "NotificationBufferSize": 10, 30 | "PrioWorkerCount": 2, 31 | "NormalWorkerCount": 10, 32 | "NotificationWorkerCount": 2, 33 | "CapabilitiesCacheSize": 50, 34 | "Capabilities": ["urn:x-rains:tlssrv"], 35 | 36 | "ZoneKeyCacheSize": 1000, 37 | "ZoneKeyCacheWarnSize": 750, 38 | "MaxPublicKeysPerZone": 5, 39 | "PendingKeyCacheSize": 1000, 40 | "DelegationQueryValidity": 5, 41 | "ReapZoneKeyCacheInterval": 1800, 42 | "ReapPendingKeyCacheInterval": 1800, 43 | 44 | "AssertionCacheSize": 10000, 45 | "NegativeAssertionCacheSize": 1000, 46 | "PendingQueryCacheSize": 100, 47 | "QueryValidity": 5, 48 | "Authorities": [ 49 | { 50 | "Zone": "ch.", 51 | "Context": "." 52 | } 53 | ], 54 | "MaxCacheValidity": { 55 | "AssertionValidity": 720, 56 | "ShardValidity": 720, 57 | "PshardValidity": 720, 58 | "ZoneValidity": 720 59 | }, 60 | "ReapAssertionCacheInterval": 1800, 61 | "ReapNegAssertionCacheInterval": 1800, 62 | "ReapPendingQCacheInterval": 1800 63 | } 64 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/namingServerethz.ch.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "testdata/keys/selfSignedRootDelegationAssertion.gob", 3 | "AssertionCheckPointInterval": 3600, 4 | "NegAssertionCheckPointInterval":3600, 5 | "ZoneKeyCheckPointInterval":3600, 6 | "CheckPointPath": "testdata/checkpoint/ethz.ch/", 7 | "PreLoadCaches": false, 8 | "ServerAddress": { 9 | "Type": "TCP", 10 | "TCPAddr": { 11 | "IP": "127.0.0.1", 12 | "Port": 5024, 13 | "Zone": "" 14 | } 15 | }, 16 | "PublisherAddress": { 17 | "Type": "TCP", 18 | "TCPAddr": { 19 | "IP": "127.0.0.1", 20 | "Zone": "", 21 | "Port": 5024 22 | } 23 | }, 24 | "MaxConnections": 1000, 25 | "KeepAlivePeriod": 60, 26 | "TCPTimeout": 300, 27 | "TLSCertificateFile": "testdata/cert/server.crt", 28 | "TLSPrivateKeyFile": "testdata/cert/server.key", 29 | 30 | "PrioBufferSize": 20, 31 | "NormalBufferSize": 100, 32 | "NotificationBufferSize": 10, 33 | "PrioWorkerCount": 2, 34 | "NormalWorkerCount": 10, 35 | "NotificationWorkerCount": 2, 36 | "CapabilitiesCacheSize": 50, 37 | "Capabilities": ["urn:x-rains:tlssrv"], 38 | 39 | "ZoneKeyCacheSize": 1000, 40 | "ZoneKeyCacheWarnSize": 750, 41 | "MaxPublicKeysPerZone": 5, 42 | "PendingKeyCacheSize": 1000, 43 | "DelegationQueryValidity": 5, 44 | "ReapZoneKeyCacheInterval": 1800, 45 | "ReapPendingKeyCacheInterval": 1800, 46 | 47 | "AssertionCacheSize": 10000, 48 | "NegativeAssertionCacheSize": 1000, 49 | "PendingQueryCacheSize": 100, 50 | "QueryValidity": 5, 51 | "Authorities": [ 52 | { 53 | "Zone": "ethz.ch.", 54 | "Context": "." 55 | } 56 | ], 57 | "MaxCacheValidity": { 58 | "AssertionValidity": 720, 59 | "ShardValidity": 720, 60 | "PshardValidity": 720, 61 | "ZoneValidity": 720 62 | }, 63 | "ReapAssertionCacheInterval": 1800, 64 | "ReapNegAssertionCacheInterval": 1800, 65 | "ReapPendingQCacheInterval": 1800 66 | } 67 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/publisherRoot.conf: -------------------------------------------------------------------------------- 1 | { 2 | "ZonefilePath": "testdata/zonefiles/root.txt", 3 | "AuthServers": [{ 4 | "Type": "TCP", 5 | "TCPAddr": { 6 | "IP": "127.0.0.1", 7 | "Port": 5022, 8 | "Zone": "" 9 | } 10 | }], 11 | "PrivateKeyPath": "testdata/keys/root", 12 | "ShardingConf" : { 13 | "KeepShards": false, 14 | "DoSharding": true, 15 | "MaxShardSize": 1000, 16 | "NofAssertionsPerShard": -1 17 | }, 18 | "PShardingConf" : { 19 | "KeepPshards": false, 20 | "DoPsharding" : true, 21 | "NofAssertionsPerPshard" : 2, 22 | "BloomFilterConf" : { 23 | "BFAlgo" : "BloomKM12", 24 | "BFHash" : "Shake256", 25 | "BloomFilterSize" : 80 26 | } 27 | }, 28 | "MetaDataConf" : { 29 | "AddSignatureMetaData": true, 30 | "AddSigMetaDataToAssertions": true, 31 | "AddSigMetaDataToShards": true, 32 | "AddSigMetaDataToPshards": true, 33 | "SignatureAlgorithm": "Ed25519", 34 | "KeyPhase": 1, 35 | "SigValidSince": 1543840931, 36 | "SigValidUntil": 2301221742, 37 | "SigSigningInterval": 60 38 | }, 39 | "ConsistencyConf" : { 40 | "DoConsistencyCheck": true, 41 | "SortShards": true, 42 | "SortZone": true, 43 | "SigNotExpired": false, 44 | "CheckStringFields": false 45 | }, 46 | "DoSigning": true, 47 | "MaxZoneSize": 50000, 48 | "OutputPath": "", 49 | "DoPublish": true 50 | } 51 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/publisherch.conf: -------------------------------------------------------------------------------- 1 | { 2 | "ZonefilePath": "testdata/zonefiles/ch.txt", 3 | "AuthServers": [{ 4 | "Type": "TCP", 5 | "TCPAddr": { 6 | "IP": "127.0.0.1", 7 | "Port": 5023, 8 | "Zone": "" 9 | } 10 | }], 11 | "PrivateKeyPath": "testdata/keys/ch", 12 | "ShardingConf" : { 13 | "KeepShards": false, 14 | "DoSharding": true, 15 | "MaxShardSize": 200, 16 | "NofAssertionsPerShard": -1 17 | }, 18 | "PShardingConf" : { 19 | "KeepPshards": false, 20 | "DoPsharding" : true, 21 | "NofAssertionsPerPshard" : 2, 22 | "BloomFilterConf" : { 23 | "BFAlgo" : "BloomKM12", 24 | "BFHash" : "Shake256", 25 | "BloomFilterSize" : 80 26 | } 27 | }, 28 | "MetaDataConf" : { 29 | "AddSignatureMetaData": true, 30 | "AddSigMetaDataToAssertions": true, 31 | "AddSigMetaDataToShards": true, 32 | "AddSigMetaDataToPshards": true, 33 | "SignatureAlgorithm": "Ed25519", 34 | "KeyPhase": 1, 35 | "SigValidSince": 1543840932, 36 | "SigValidUntil": 2301221742, 37 | "SigSigningInterval": 60 38 | }, 39 | "ConsistencyConf" : { 40 | "DoConsistencyCheck": false, 41 | "SortShards": true, 42 | "SortZone": true, 43 | "SigNotExpired": false, 44 | "CheckStringFields": false 45 | }, 46 | "DoSigning": true, 47 | "MaxZoneSize": 50000, 48 | "OutputPath": "", 49 | "DoPublish": true 50 | } 51 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/publisherethz.ch.conf: -------------------------------------------------------------------------------- 1 | { 2 | "ZonefilePath": "testdata/zonefiles/ethz.ch.txt", 3 | "AuthServers": [{ 4 | "Type": "TCP", 5 | "TCPAddr": { 6 | "IP": "127.0.0.1", 7 | "Port": 5024, 8 | "Zone": "" 9 | } 10 | }], 11 | "PrivateKeyPath": "testdata/keys/ethz.ch", 12 | "ShardingConf" : { 13 | "KeepShards": false, 14 | "DoSharding": false, 15 | "MaxShardSize": -1, 16 | "NofAssertionsPerShard": 1 17 | }, 18 | "PShardingConf" : { 19 | "KeepPshards": false, 20 | "DoPsharding" : false, 21 | "NofAssertionsPerPshard" : 2, 22 | "BloomFilterConf" : { 23 | "BFAlgo" : "BloomKM12", 24 | "BFHash" : "Shake256", 25 | "BloomFilterSize" : 80 26 | } 27 | }, 28 | "MetaDataConf" : { 29 | "AddSignatureMetaData": true, 30 | "AddSigMetaDataToAssertions": true, 31 | "AddSigMetaDataToShards": true, 32 | "AddSigMetaDataToPshards": true, 33 | "SignatureAlgorithm": "Ed25519", 34 | "KeyPhase": 1, 35 | "SigValidSince": 1543840933, 36 | "SigValidUntil": 2301221742, 37 | "SigSigningInterval": 60 38 | }, 39 | "ConsistencyConf" : { 40 | "DoConsistencyCheck": false, 41 | "SortShards": true, 42 | "SortZone": true, 43 | "SigNotExpired": false, 44 | "CheckStringFields": false 45 | }, 46 | "DoSigning": true, 47 | "MaxZoneSize": 50000, 48 | "OutputPath": "", 49 | "DoPublish": true 50 | } 51 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/resolver.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "testdata/keys/selfSignedRootDelegationAssertion.gob", 3 | "AssertionCheckPointInterval": 1, 4 | "NegAssertionCheckPointInterval":1, 5 | "ZoneKeyCheckPointInterval":1, 6 | "CheckPointPath": "testdata/checkpoint/resolver/", 7 | "PreLoadCaches": false, 8 | 9 | "ServerAddress": { 10 | "Type": "TCP", 11 | "TCPAddr": { 12 | "IP": "127.0.0.1", 13 | "Port": 5025 14 | } 15 | }, 16 | "MaxConnections": 1000, 17 | "KeepAlivePeriod": 60, 18 | "TCPTimeout": 300, 19 | "TLSCertificateFile": "testdata/cert/server.crt", 20 | "TLSPrivateKeyFile": "testdata/cert/server.key", 21 | 22 | "PrioBufferSize": 20, 23 | "NormalBufferSize": 100, 24 | "NotificationBufferSize": 10, 25 | "PrioWorkerCount": 2, 26 | "NormalWorkerCount": 10, 27 | "NotificationWorkerCount": 2, 28 | "CapabilitiesCacheSize": 50, 29 | "Capabilities": ["urn:x-rains:tlssrv"], 30 | 31 | "ZoneKeyCacheSize": 1000, 32 | "ZoneKeyCacheWarnSize": 750, 33 | "MaxPublicKeysPerZone": 5, 34 | "PendingKeyCacheSize": 1000, 35 | "DelegationQueryValidity": 5, 36 | "ReapZoneKeyCacheInterval": 1800, 37 | "ReapPendingKeyCacheInterval": 1800, 38 | 39 | "AssertionCacheSize": 10000, 40 | "NegativeAssertionCacheSize": 1000, 41 | "PendingQueryCacheSize": 100, 42 | "QueryValidity": 5, 43 | "Authorities": [], 44 | "MaxCacheValidity": { 45 | "AssertionValidity": 720, 46 | "ShardValidity": 720, 47 | "PshardValidity": 720, 48 | "ZoneValidity": 720 49 | }, 50 | "ReapAssertionCacheInterval": 1800, 51 | "ReapNegAssertionCacheInterval": 1800, 52 | "ReapPendingQCacheInterval": 1800 53 | } 54 | -------------------------------------------------------------------------------- /test/integration/testdata/conf/resolver2.conf: -------------------------------------------------------------------------------- 1 | { 2 | "RootZonePublicKeyPath": "testdata/keys/selfSignedRootDelegationAssertion.gob", 3 | "AssertionCheckPointInterval": 3600, 4 | "NegAssertionCheckPointInterval":3600, 5 | "ZoneKeyCheckPointInterval":3600, 6 | "CheckPointPath": "testdata/checkpoint/resolver/", 7 | "PreLoadCaches": true, 8 | 9 | "ServerAddress": { 10 | "Type": "TCP", 11 | "TCPAddr": { 12 | "IP": "127.0.0.1", 13 | "Port": 5026 14 | } 15 | }, 16 | "MaxConnections": 1000, 17 | "KeepAlivePeriod": 60, 18 | "TCPTimeout": 300, 19 | "TLSCertificateFile": "testdata/cert/server.crt", 20 | "TLSPrivateKeyFile": "testdata/cert/server.key", 21 | 22 | "PrioBufferSize": 20, 23 | "NormalBufferSize": 100, 24 | "NotificationBufferSize": 10, 25 | "PrioWorkerCount": 2, 26 | "NormalWorkerCount": 10, 27 | "NotificationWorkerCount": 2, 28 | "CapabilitiesCacheSize": 50, 29 | "Capabilities": ["urn:x-rains:tlssrv"], 30 | 31 | "ZoneKeyCacheSize": 1000, 32 | "ZoneKeyCacheWarnSize": 750, 33 | "MaxPublicKeysPerZone": 5, 34 | "PendingKeyCacheSize": 1000, 35 | "DelegationQueryValidity": 5, 36 | "ReapZoneKeyCacheInterval": 1800, 37 | "ReapPendingKeyCacheInterval": 1800, 38 | 39 | "AssertionCacheSize": 10000, 40 | "NegativeAssertionCacheSize": 1000, 41 | "PendingQueryCacheSize": 100, 42 | "QueryValidity": 5, 43 | "Authorities": [], 44 | "MaxCacheValidity": { 45 | "AssertionValidity": 720, 46 | "ShardValidity": 720, 47 | "PshardValidity": 720, 48 | "ZoneValidity": 720 49 | }, 50 | "ReapAssertionCacheInterval": 1800, 51 | "ReapNegAssertionCacheInterval": 1800, 52 | "ReapPendingQCacheInterval": 1800 53 | } 54 | -------------------------------------------------------------------------------- /test/integration/testdata/keys/ch/ch_pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RAINS PUBLIC KEY----- 2 | : 3 | hexEncoding: 06c6d21fa1f2047581e8dcf2b014a9a001cd00c58de592c57cc86b2be641a220 4 | keyAlgo: Ed25519 5 | keyPhase: 1 6 | 7 | BsbSH6HyBHWB6NzysBSpoAHNAMWN5ZLFfMhrK+ZBoiA= 8 | -----END RAINS PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /test/integration/testdata/keys/ch/ch_sec.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RAINS ENCRYPTED PRIVATE KEY----- 2 | : 3 | iv: a03d3b35873177fda69b3e916dbf33d8 4 | keyAlgo: Ed25519 5 | keyPhase: 1 6 | salt: 3950baabebec5c97 7 | 8 | USMaVZg3hXCjMXikZeEPHC6G0iwtzHTYC9q1oqSM/AD7Cs0uH9ZVRVtH4o4ZwxN2 9 | 9mk9uYIlzRnDVg2MpTY3Tw== 10 | -----END RAINS ENCRYPTED PRIVATE KEY----- 11 | -------------------------------------------------------------------------------- /test/integration/testdata/keys/ethz.ch/ethz.ch_pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RAINS PUBLIC KEY----- 2 | : 3 | hexEncoding: e399545d248fb3ece0cd822ee3b6222df06fd278308923d9bebef997c9a1afa9 4 | keyAlgo: Ed25519 5 | keyPhase: 1 6 | 7 | 45lUXSSPs+zgzYIu47YiLfBv0ngwiSPZvr75l8mhr6k= 8 | -----END RAINS PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /test/integration/testdata/keys/ethz.ch/ethz.ch_sec.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RAINS ENCRYPTED PRIVATE KEY----- 2 | : 3 | iv: b31bb199c22998d31286411411e95f12 4 | keyAlgo: Ed25519 5 | keyPhase: 1 6 | salt: 953c7bdd8caed2d5 7 | 8 | XWqsVHeOTDMmv7Fsq6/9dCuEb1mbKAP8laOEIi4/JElWUPqgpwOpoE5y5o/Cr4to 9 | 0snyciZQS8If87WEDON9hQ== 10 | -----END RAINS ENCRYPTED PRIVATE KEY----- 11 | -------------------------------------------------------------------------------- /test/integration/testdata/messages/SCIONmessages.txt: -------------------------------------------------------------------------------- 1 | :Q: . www.ethz.ch. [ 14 ] -1 [ ] 2 | :A: www ethz.ch. . [ :scion: 2-ff00:0:222,[198.175.162.241] ] 3 | 4 | :Q: . www.ethz.ch. [ 1 ] -1 [ ] 5 | :A: www ethz.ch. . [ :name: a [ :scion: ] ] 6 | 7 | :Q: . www.ethz.ch. [ 7 ] -1 [ ] 8 | :A: www ethz.ch. . [ :cert: :tls: :endEntity: :sha256: e28b1bd3a73882b198dfe4f0fa954c ] 9 | 10 | :Q: . _ftp._udpscion.ethz.ch. [ 8 ] -1 [ ] 11 | :A: _ftp._udpscion ethz.ch. . [ :srv: ftp.ethz.ch. 20 0 ] 12 | 13 | :Q: . www.ethz.ch. [ 9 ] -1 [ ] 14 | :Z: ethz.ch. . [ 15 | :A: _ftp._udpscion [ :srv: ftp.ethz.ch. 20 0 ] 16 | :A: www [ :name: a [ :scion: ] ] 17 | :A: www [ :cert: :tls: :endEntity: :sha256: e28b1bd3a73882b198dfe4f0fa954c ] 18 | :A: www [ :scion: 2-ff00:0:222,[198.175.162.241] ] 19 | ] 20 | -------------------------------------------------------------------------------- /test/integration/testdata/messages/messages.txt: -------------------------------------------------------------------------------- 1 | :Q: . www.ethz.ch. [ 3 ] -1 [ ] 2 | :A: www ethz.ch. . [ :ip4: 198.175.162.241 ] 3 | 4 | :Q: . www.ethz.ch. [ 2 ] -1 [ ] 5 | :A: www ethz.ch. . [ :ip6: 2001:db8:85a3::8a2e:370:7334 ] 6 | 7 | :Q: . www.ethz.ch. [ 1 ] -1 [ ] 8 | :A: www ethz.ch. . [ :name: a [ :ip6: :ip4: :scion: ] ] 9 | 10 | :Q: . www.ethz.ch. [ 7 ] -1 [ ] 11 | :A: www ethz.ch. . [ :cert: :tls: :endEntity: :sha256: e28b1bd3a73882b198dfe4f0fa954c ] 12 | 13 | :Q: . _ftp._tcp.ethz.ch. [ 8 ] -1 [ ] 14 | :A: _ftp._tcp ethz.ch. . [ :srv: ftp.ethz.ch. 20 0 ] 15 | 16 | :Q: . www.ethz.ch. [ 9 ] -1 [ ] 17 | :Z: ethz.ch. . [ 18 | :A: _ftp._tcp [ :srv: ftp.ethz.ch. 20 0 ] 19 | :A: www [ :name: a [ :ip6: :ip4: :scion: ] ] 20 | :A: www [ :ip6: 2001:db8:85a3::8a2e:370:7334 ] 21 | :A: www [ :ip4: 198.175.162.241 ] 22 | :A: www [ :cert: :tls: :endEntity: :sha256: e28b1bd3a73882b198dfe4f0fa954c ] 23 | :A: www [ :scion: 2-ff00:0:222,[127.0.0.1] ] 24 | ] 25 | -------------------------------------------------------------------------------- /test/integration/testdata/messages/messagesAllObjects.txt: -------------------------------------------------------------------------------- 1 | :Q: . www.ethz.ch. [ 3 ] -1 [ ] 2 | :A: www ethz.ch. . [ :ip4: 198.175.162.241 ] 3 | 4 | :Q: . www.ethz.ch. [ 2 ] -1 [ ] 5 | :A: www ethz.ch. . [ :ip6: 2001:db8:: ] 6 | 7 | :Q: . www.ethz.ch. [ 1 ] -1 [ ] 8 | :A: www ethz.ch. . [ :name: a [ :ip4: :ip6: ] ] 9 | 10 | :Q: . www.ethz.ch. [ 6 ] -1 [ ] 11 | :A: www ethz.ch. . [ :nameset: nameset expression ] 12 | 13 | :Q: . www.ethz.ch. [ 7 ] -1 [ ] 14 | :A: www ethz.ch. . [ :cert: :tls: :endEntity: :sha256: e28b1bd3a73882b198dfe4f0fa954c ] 15 | 16 | :Q: . _ftp._tcp.ethz.ch. [ 8 ] -1 [ ] 17 | :A: _ftp._tcp ethz.ch. . [ :srv: ftp.ethz.ch. 20 0 ] 18 | 19 | :Q: . www.ethz.ch. [ 9 ] -1 [ ] 20 | :A: www ethz.ch. . [ :regr: registrar info ] 21 | 22 | :Q: . www.ethz.ch. [ 10 ] -1 [ ] 23 | :A: www ethz.ch. . [ :regt: registrant info ] 24 | 25 | :Q: . www.ethz.ch. [ 11 ] -1 [ ] 26 | :A: www ethz.ch. . [ :infra: :ed25519: 5 27 | e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 28 | ] 29 | 30 | :Q: . www.ethz.ch. [ 12 ] -1 [ ] 31 | :A: www ethz.ch. . [ :extra: :ed25519: 5 32 | e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 33 | ] 34 | 35 | :Q: . www.ethz.ch. [ 13 ] -1 [ ] 36 | :A: www ethz.ch. . [ :next: :ed25519: 5 37 | e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 38 | 100000 20000000 39 | ] -------------------------------------------------------------------------------- /test/integration/testdata/zonefiles/SCIONch.txt: -------------------------------------------------------------------------------- 1 | :Z: ch. . [ 2 | :A: ethz [ :redir: _rains._udpscion.ns.ethz.ch. ] 3 | :A: ethz [ :deleg: :ed25519: 1 e399545d248fb3ece0cd822ee3b6222df06fd278308923d9bebef997c9a1afa9 ] 4 | :A: _rains._udpscion.ns.ethz [ :srv: ns1.ethz.ch. 5024 0 ] 5 | :A: ns1.ethz [ :scion: 1-ff00:0:110,[127.0.0.1] ] 6 | ] 7 | -------------------------------------------------------------------------------- /test/integration/testdata/zonefiles/SCIONethz.ch.txt: -------------------------------------------------------------------------------- 1 | :Z: ethz.ch. . [ 2 | :A: www [ :name: a [ :scion: ] ] 3 | :A: www [ :scion: 2-ff00:0:222,[198.175.162.241] ] 4 | :A: www [ :cert: :tls: :endEntity: :sha256: e28b1bd3a73882b198dfe4f0fa954c ] 5 | :A: _ftp._udpscion [ :srv: ftp.ethz.ch. 20 0 ] 6 | ] 7 | -------------------------------------------------------------------------------- /test/integration/testdata/zonefiles/SCIONroot.txt: -------------------------------------------------------------------------------- 1 | :Z: . . [ 2 | :A: ch [ :redir: _rains._udpscion.ns.ch. ] 3 | :A: ch [ :deleg: :ed25519: 1 06c6d21fa1f2047581e8dcf2b014a9a001cd00c58de592c57cc86b2be641a220 ] 4 | :A: _rains._udpscion.ns.ch [ :srv: ns1.ch. 5023 0 ] 5 | :A: ns1.ch [ :scion: 1-ff00:0:110,[127.0.0.1] ] 6 | ] 7 | -------------------------------------------------------------------------------- /test/integration/testdata/zonefiles/ch.txt: -------------------------------------------------------------------------------- 1 | :Z: ch. . [ 2 | :A: ethz [ :redir: _rains._tcp.ns.ethz.ch. ] 3 | :A: ethz [ :deleg: :ed25519: 1 e399545d248fb3ece0cd822ee3b6222df06fd278308923d9bebef997c9a1afa9 ] 4 | :A: _rains._tcp.ns.ethz [ :srv: ns1.ethz.ch. 5024 0 ] 5 | :A: ns1.ethz [ :ip4: 127.0.0.1 ] 6 | ] 7 | -------------------------------------------------------------------------------- /test/integration/testdata/zonefiles/ethz.ch.txt: -------------------------------------------------------------------------------- 1 | :Z: ethz.ch. . [ 2 | :A: www [ :name: a [ :ip6: :ip4: :scion: ] ] 3 | :A: www [ :ip6: 2001:0db8:85a3:0000:0000:8a2e:0370:7334 ] 4 | :A: www [ :ip4: 198.175.162.241 ] 5 | :A: www [ :scion: 2-ff00:0:222,[127.0.0.1] ] 6 | :A: www [ :cert: :tls: :endEntity: :sha256: e28b1bd3a73882b198dfe4f0fa954c ] 7 | :A: _ftp._tcp [ :srv: ftp.ethz.ch. 20 0 ] 8 | ] 9 | -------------------------------------------------------------------------------- /test/integration/testdata/zonefiles/ethz.chAllObjects.txt: -------------------------------------------------------------------------------- 1 | :Z: ethz.ch. . [ 2 | :A: www [ :ip4: 198.175.162.241 ] 3 | :A: www [ :ip6: 2001:db8:: ] 4 | :A: www [ :scion: 2-ff00:0:222,[127.0.0.1] ] 5 | :A: www [ :name: a [ :ip4: :ip6: ] ] 6 | :A: www [ :nameset: nameset expression ] 7 | :A: www [ :cert: :tls: :endEntity: :sha256: e28b1bd3a73882b198dfe4f0fa954c ] 8 | :A: _ftp._tcp [ :srv: ftp.ethz.ch. 20 0 ] 9 | :A: www [ :regr: registrar info ] 10 | :A: www [ :regt: registrant info ] 11 | :A: www [ :infra: :ed25519: 5 12 | e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 13 | ] 14 | :A: www [ :extra: :ed25519: 5 15 | e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 16 | ] 17 | :A: www [ :next: :ed25519: 5 18 | e28b1bd3a73882b198dfe4f0fa95403c5916ac7b97387bd20f49511de628b702 19 | 100000 20000000 ] 20 | ] 21 | -------------------------------------------------------------------------------- /test/integration/testdata/zonefiles/root.txt: -------------------------------------------------------------------------------- 1 | :Z: . . [ 2 | :A: ch [ :redir: _rains._tcp.ns.ch. ] 3 | :A: ch [ :deleg: :ed25519: 1 06c6d21fa1f2047581e8dcf2b014a9a001cd00c58de592c57cc86b2be641a220 ] 4 | :A: _rains._tcp.ns.ch [ :srv: ns1.ch. 5023 0 ] 5 | :A: ns1.ch [ :ip4: 127.0.0.1 ] 6 | ] 7 | --------------------------------------------------------------------------------