├── waf ├── tests ├── unit-tests │ ├── config-files │ │ ├── config-ca-2 │ │ ├── config-ca-3 │ │ ├── config-client-2 │ │ ├── config-ca-4 │ │ ├── config-ca-1 │ │ ├── config-ca-6 │ │ ├── config-challenge-possession │ │ ├── config-client-3 │ │ ├── config-client-1 │ │ └── config-ca-5 │ ├── test-send-email.sh │ ├── main.cpp │ ├── redirection-policy.t.cpp │ ├── ca-memory.t.cpp │ ├── name-assignment.t.cpp │ ├── challenge-pin.t.cpp │ ├── challenge-possession.t.cpp │ └── requester.t.cpp ├── wscript ├── io-key-chain-fixture.hpp ├── key-chain-fixture.hpp ├── io-fixture.hpp ├── boost-test.hpp ├── clock-fixture.cpp ├── global-configuration.cpp └── clock-fixture.hpp ├── libndn-cert.pc.in ├── .jenkins.d ├── 09-cleanup.sh ├── 20-tests.sh ├── 10-build.sh ├── 30-coverage.sh ├── 01-ndn-cxx.sh ├── README.md └── 00-deps.sh ├── .mailmap ├── .dockerignore ├── .gitignore ├── client.conf.sample ├── .editorconfig ├── .github └── workflows │ ├── ci.yml │ └── docker.yml ├── tools ├── wscript └── ndncert-ca-status.cpp ├── .waf-tools ├── coverage.py ├── sanitizers.py ├── sqlite3.py └── openssl.py ├── AUTHORS.md ├── systemd └── ndncert-ca.service.in ├── ndncert-mail.conf.sample ├── src ├── detail │ ├── ca-storage.cpp │ ├── challenge-encoder.hpp │ ├── error-encoder.hpp │ ├── info-encoder.hpp │ ├── probe-encoder.hpp │ ├── ca-memory.hpp │ ├── ca-sqlite.hpp │ ├── request-encoder.hpp │ ├── profile-storage.hpp │ ├── ca-configuration.hpp │ ├── ndncert-common.cpp │ ├── ca-memory.cpp │ ├── info-encoder.cpp │ ├── profile-storage.cpp │ ├── error-encoder.cpp │ ├── ca-storage.hpp │ ├── ca-request-state.cpp │ ├── ca-configuration.cpp │ ├── ca-profile.hpp │ ├── ca-request-state.hpp │ ├── ndncert-common.hpp │ ├── probe-encoder.cpp │ ├── ca-profile.cpp │ └── challenge-encoder.cpp ├── redirection │ ├── redirection-email.hpp │ ├── redirection-policy.cpp │ ├── redirection-param.hpp │ ├── redirection-email.cpp │ ├── redirection-param.cpp │ └── redirection-policy.hpp ├── name-assignment │ ├── assignment-hash.hpp │ ├── assignment-random.cpp │ ├── assignment-param.hpp │ ├── assignment-random.hpp │ ├── assignment-email.hpp │ ├── assignment-hash.cpp │ ├── assignment-param.cpp │ ├── assignment-func.cpp │ ├── assignment-email.cpp │ └── assignment-func.hpp ├── challenge │ ├── challenge-pin.hpp │ ├── challenge-email.hpp │ ├── challenge-possession.hpp │ ├── challenge-module.cpp │ └── challenge-module.hpp └── ca-module.hpp ├── ca.conf.sample ├── Dockerfile ├── .jenkins ├── README.md ├── ndncert-send-email-challenge.py └── wscript /waf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/named-data/ndncert/HEAD/waf -------------------------------------------------------------------------------- /tests/unit-tests/config-files/config-ca-2: -------------------------------------------------------------------------------- 1 | { 2 | "ca-prefix": "/ndn", 3 | "ca-info": "missing max validity period, max suffix length, and probe", 4 | "supported-challenges": 5 | [ 6 | { "challenge": "pin" } 7 | ] 8 | } -------------------------------------------------------------------------------- /tests/unit-tests/test-send-email.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | RECEIVER=$1 4 | SECRET=$2 5 | CANAME=$3 6 | CERTNAME=$4 7 | 8 | MESSAGE=$RECEIVER" "$SECRET" "$CANAME" "$CERTNAME 9 | 10 | echo $MESSAGE > tmp.txt 11 | echo $MESSAGE 12 | -------------------------------------------------------------------------------- /libndn-cert.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@PREFIX@ 2 | libdir=@LIBDIR@ 3 | includedir=@INCLUDEDIR@ 4 | 5 | Name: libndn-cert 6 | Description: ndncert library 7 | Version: @VERSION@ 8 | Libs: -L${libdir} -lndn-cert 9 | Cflags: -I${includedir} 10 | Requires: libndn-cxx >= 0.8.1 11 | -------------------------------------------------------------------------------- /tests/unit-tests/config-files/config-ca-3: -------------------------------------------------------------------------------- 1 | { 2 | "ca-prefix": "/ndn", 3 | "ca-info": "missing challenge", 4 | "max-validity-period": "86400", 5 | "max-suffix-length": 3, 6 | "probe-parameters": 7 | [ 8 | { "probe-parameter-key": "full name" } 9 | ] 10 | } -------------------------------------------------------------------------------- /.jenkins.d/09-cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | PROJ=ndncert 5 | 6 | sudo rm -f /usr/local/bin/"$PROJ"* 7 | sudo rm -fr /usr/local/include/"$PROJ" 8 | sudo rm -f /usr/local/lib{,64}/lib"$PROJ"* 9 | sudo rm -f /usr/local/lib{,64}/pkgconfig/{,lib}"$PROJ".pc 10 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Zhiyi Zhang 2 | 3 | Alexander Afanasyev 4 | Alexander Afanasyev 5 | Md Ashiqur Rahman 6 | -------------------------------------------------------------------------------- /tests/unit-tests/config-files/config-client-2: -------------------------------------------------------------------------------- 1 | { 2 | "ca-list": 3 | [ 4 | { 5 | "ca-prefix": "/ndn/edu/ucla", 6 | "ca-info": "missing certificate", 7 | "probe-parameters": 8 | [ 9 | { "probe-parameter-key": "email" } 10 | ] 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/unit-tests/config-files/config-ca-4: -------------------------------------------------------------------------------- 1 | { 2 | "ca-prefix": "/ndn", 3 | "ca-info": "unsupported challenge", 4 | "max-validity-period": "86400", 5 | "max-suffix-length": 3, 6 | "probe-parameters": 7 | [ 8 | { "probe-parameter-key": "full name" } 9 | ], 10 | "supported-challenges": 11 | [ 12 | { "challenge": "something" } 13 | ] 14 | } -------------------------------------------------------------------------------- /tests/unit-tests/config-files/config-ca-1: -------------------------------------------------------------------------------- 1 | { 2 | "ca-prefix": "/ndn", 3 | "forwarding-hint": "/repo", 4 | "ca-info": "ndn testbed ca", 5 | "max-validity-period": "864000", 6 | "max-suffix-length": 3, 7 | "probe-parameters": 8 | [ 9 | { "probe-parameter-key": "full name" } 10 | ], 11 | "supported-challenges": 12 | [ 13 | { "challenge": "PIN" } 14 | ] 15 | } -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Waf build system 2 | build/ 3 | .waf-*-*/ 4 | .waf3-*-*/ 5 | .lock-waf* 6 | 7 | # Compiled python code 8 | **/__pycache__/ 9 | **/*.py[cod] 10 | 11 | # Qt Creator 12 | *.creator 13 | *.creator.user 14 | .qtc_clangd/ 15 | 16 | # Visual Studio Code 17 | .vscode/ 18 | 19 | # macOS 20 | **/.DS_Store 21 | **/.AppleDouble 22 | **/.LSOverride 23 | **/._* 24 | 25 | # Other 26 | Dockerfile 27 | VERSION.info 28 | -------------------------------------------------------------------------------- /tests/unit-tests/config-files/config-ca-6: -------------------------------------------------------------------------------- 1 | { 2 | "ca-prefix": "/ndn", 3 | "ca-info": "ndn testbed ca", 4 | "max-validity-period": "864000", 5 | "max-suffix-length": 3, 6 | "probe-parameters": 7 | [ 8 | { "probe-parameter-key": "full name" } 9 | ], 10 | "supported-challenges": 11 | [ 12 | { "challenge": "PIN" } 13 | ], 14 | "name-assignment": 15 | { 16 | "nonexistent": "" 17 | } 18 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Backup files 2 | *~ 3 | *.bak 4 | *.orig 5 | *.rej 6 | 7 | # Waf build system 8 | /build/ 9 | .waf-*-*/ 10 | .waf3-*-*/ 11 | .lock-waf* 12 | 13 | # Compiled python code 14 | __pycache__/ 15 | *.py[cod] 16 | 17 | # Emacs 18 | \#*\# 19 | /.emacs.desktop 20 | /.emacs.desktop.lock 21 | *.elc 22 | .\#* 23 | 24 | # Visual Studio Code 25 | .vscode/ 26 | 27 | # macOS 28 | .DS_Store 29 | .AppleDouble 30 | .LSOverride 31 | ._* 32 | 33 | # Other 34 | /VERSION.info 35 | -------------------------------------------------------------------------------- /tests/wscript: -------------------------------------------------------------------------------- 1 | # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- 2 | 3 | top = '..' 4 | 5 | def build(bld): 6 | tmpdir = 'UNIT_TESTS_TMPDIR="%s"' % bld.bldnode.make_node('tests-tmp') 7 | bld.program( 8 | target=f'{top}/unit-tests', 9 | name='unit-tests', 10 | source=bld.path.ant_glob(['*.cpp', 'unit-tests/**/*.cpp']), 11 | use='BOOST_TESTS libndn-cert', 12 | defines=[tmpdir], 13 | includes=top, 14 | install_path=None) 15 | -------------------------------------------------------------------------------- /client.conf.sample: -------------------------------------------------------------------------------- 1 | { 2 | "ca-list": [ 3 | { 4 | "ca-prefix": "/ndn", 5 | "certificate": "Bv0BSwcjCANuZG4IA0tFWQgIJ8SyKp97gScIA25kbjYIAAABgHX6c7QUCRgBAhkEADbugBVbMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPuDnW4oq0mULLT8PDXh0zuBg+0SJ1yPC85jylUU+hgxX9fDNyjlykLrvb1D6IQRJWJHMKWe6TJKPUhGgOT658hZyGwEDHBYHFAgDbmRuCANLRVkICCfEsiqfe4En/QD9Jv0A/g8yMDIyMDQyOVQxNTM5NTD9AP8PMjAyNjEyMzFUMjM1OTU5/QECKf0CACX9AgEIZnVsbG5hbWX9AgIVTkROIFRlc3RiZWQgUm9vdCAyMjA0F0gwRgIhAPYUOjNakdfDGh5j9dcCGOz+Ie1MqoAEsjM9PEUEWbnqAiEApu0rg9GAK1LNExjLYAF6qVgpWQgU+atPn63Gtuubqyg=" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | 8 | [*.{cpp,hpp}] 9 | indent_style = space 10 | indent_size = 2 11 | trim_trailing_whitespace = true 12 | 13 | [{*.{py,sh},.jenkins,wscript}] 14 | indent_style = space 15 | indent_size = 4 16 | trim_trailing_whitespace = true 17 | 18 | [*.md] 19 | indent_style = space 20 | trim_trailing_whitespace = false 21 | 22 | [*.rst] 23 | indent_style = space 24 | trim_trailing_whitespace = true 25 | 26 | [*.{yaml,yml}] 27 | indent_style = space 28 | indent_size = 2 29 | trim_trailing_whitespace = true 30 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - '**' 6 | paths-ignore: 7 | - 'Dockerfile' 8 | - '.dockerignore' 9 | - '.editorconfig' 10 | - '.gitignore' 11 | - '.mailmap' 12 | - '*.md' 13 | workflow_dispatch: 14 | 15 | permissions: {} 16 | 17 | jobs: 18 | Ubuntu: 19 | uses: named-data/actions/.github/workflows/jenkins-script-ubuntu.yml@v1 20 | macOS: 21 | uses: named-data/actions/.github/workflows/jenkins-script-macos.yml@v1 22 | PPA: 23 | uses: named-data/actions/.github/workflows/ppa.yml@v1 24 | with: 25 | extra-deps: libboost-program-options-dev 26 | -------------------------------------------------------------------------------- /tools/wscript: -------------------------------------------------------------------------------- 1 | # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- 2 | 3 | top = '..' 4 | 5 | def build(bld): 6 | bld.program( 7 | name='ndncert-client', 8 | target=f'{top}/bin/ndncert-client', 9 | source='ndncert-client.cpp', 10 | use='BOOST_TOOLS libndn-cert') 11 | 12 | bld.program( 13 | name='ndncert-ca-server', 14 | target=f'{top}/bin/ndncert-ca-server', 15 | source='ndncert-ca-server.cpp', 16 | use='BOOST_TOOLS libndn-cert') 17 | 18 | bld.program( 19 | name='ndncert-ca-status', 20 | target=f'{top}/bin/ndncert-ca-status', 21 | source='ndncert-ca-status.cpp', 22 | use='BOOST_TOOLS libndn-cert') 23 | -------------------------------------------------------------------------------- /.waf-tools/coverage.py: -------------------------------------------------------------------------------- 1 | from waflib import TaskGen 2 | 3 | def options(opt): 4 | opt.add_option('--with-coverage', action='store_true', default=False, 5 | help='Add compiler flags to enable code coverage information') 6 | 7 | def configure(conf): 8 | if conf.options.with_coverage: 9 | if not conf.options.debug: 10 | conf.fatal('Code coverage flags require debug mode compilation (add --debug)') 11 | conf.check_cxx(cxxflags=['-fprofile-arcs', '-ftest-coverage', '-fPIC'], 12 | linkflags=['-fprofile-arcs'], uselib_store='GCOV', mandatory=True) 13 | 14 | @TaskGen.feature('cxx','cc') 15 | @TaskGen.after('process_source') 16 | def add_coverage(self): 17 | if getattr(self, 'use', ''): 18 | self.use += ' GCOV' 19 | else: 20 | self.use = 'GCOV' 21 | -------------------------------------------------------------------------------- /tests/unit-tests/config-files/config-challenge-possession: -------------------------------------------------------------------------------- 1 | { 2 | "anchor-list": 3 | [ 4 | { 5 | "certificate": "Bv0CJAcsCANuZG4IBXNpdGUxCANLRVkICBG8IvRjFf8XCARzZWxmCAn9AAABWcgU2aUUCRgBAhkEADbugBX9AU8wggFLMIIBAwYHKoZIzj0CATCB9wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEQQRrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQEDQgAES9Cb9iANUNYmwt5bjwNW1mZgjzIkDJb6FTCdiYWnkMMIVxh2YDllphoWDEAPS6kqJczzCuhnGYpZCp9tTaYKGxZMGwEDHB0HGwgDbmRuCAVzaXRlMQgDS0VZCAgRvCL0YxX/F/0A/Sb9AP4PMTk3MDAxMDFUMDAwMDAw/QD/DzIwMzcwMTE3VDIxMjg0NhdIMEYCIQDXkR1hF3GiP7yLXq+0JBJfi9QC+hhAu/1Bykx+MWz6RAIhANwelBTxxZr2C5bD15mjfhWudK4I1tOb4b/9xWCHyM7F" 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /.jenkins.d/20-tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eo pipefail 3 | 4 | # https://github.com/google/sanitizers/wiki/SanitizerCommonFlags 5 | # https://github.com/google/sanitizers/wiki/AddressSanitizerFlags 6 | ASAN_OPTIONS="color=always" 7 | ASAN_OPTIONS+=":strip_path_prefix=${PWD}/" 8 | ASAN_OPTIONS+=":check_initialization_order=1" 9 | ASAN_OPTIONS+=":detect_stack_use_after_return=1" 10 | ASAN_OPTIONS+=":strict_init_order=1" 11 | ASAN_OPTIONS+=":strict_string_checks=1" 12 | ASAN_OPTIONS+=":detect_invalid_pointer_pairs=2" 13 | export ASAN_OPTIONS 14 | 15 | # https://www.boost.org/doc/libs/release/libs/test/doc/html/boost_test/runtime_config/summary.html 16 | export BOOST_TEST_BUILD_INFO=1 17 | export BOOST_TEST_COLOR_OUTPUT=1 18 | export BOOST_TEST_DETECT_MEMORY_LEAK=0 19 | export BOOST_TEST_LOGGER=HRF,test_suite,stdout:XML,all,build/xunit-log.xml 20 | 21 | set -x 22 | 23 | # Prepare environment 24 | rm -rf ~/.ndn 25 | 26 | # Run unit tests 27 | ./build/unit-tests 28 | -------------------------------------------------------------------------------- /tests/unit-tests/config-files/config-client-3: -------------------------------------------------------------------------------- 1 | { 2 | "ca-list": 3 | [ 4 | { 5 | "ca-info": "missing ca prefix", 6 | "probe-parameters": 7 | [ 8 | { "probe-parameter-key": "email" } 9 | ], 10 | "certificate": "ANuZG4IBXNpdGUxCANLRVkICBG8IvRjFf8XCARzZWxmCAn9AAABWcgU2aUUCRgBAhkEADbugBX9AU8wggFLMIIBAwYHKoZIzj0CATCB9wIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wWwQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLAxUAxJ02CIbnBJNqZnjhE50mt4GffpAEQQRrF9Hy4SxCR/i85uVjpEDydwN9gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQEDQgAES9Cb9iANUNYmwt5bjwNW1mZgjzIkDJb6FTCdiYWnkMMIVxh2YDllphoWDEAPS6kqJczzCuhnGYpZCp9tTaYKGxZMGwEDHB0HGwgDbmRuCAVzaXRlMQgDS0VZCAgRvCL0YxX/F/0A/Sb9AP4PMTk3MDAxMDFUMDAwMDAw/QD/DzIwMzcwMTE3VDIxMjg0NhdIMEYCIQDXkR1hF3GiP7yLXq+0JBJfi9QC+hhAu/1Bykx+MWz6RAIhANwelBTxxZr2C5bD15mjfhWudK4I1tOb4b/9xWCHyM7F" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /.github/workflows/docker.yml: -------------------------------------------------------------------------------- 1 | name: Docker 2 | on: 3 | push: 4 | tags: 5 | - 'v?[0-9]+.[0-9]+*' 6 | schedule: 7 | # twice a month 8 | - cron: '20 11 5,20 * *' 9 | workflow_dispatch: 10 | 11 | permissions: 12 | attestations: write 13 | id-token: write 14 | packages: write 15 | 16 | jobs: 17 | ndncert-build: 18 | uses: named-data/actions/.github/workflows/docker-image.yml@v1 19 | with: 20 | name: ndncert-build 21 | target: build 22 | ndncert-ca: 23 | needs: ndncert-build 24 | uses: named-data/actions/.github/workflows/docker-image.yml@v1 25 | with: 26 | name: ndncert-ca 27 | target: ca 28 | contexts: build=docker-image://${{ needs.ndncert-build.outputs.image }} 29 | ndncert-client: 30 | needs: ndncert-build 31 | uses: named-data/actions/.github/workflows/docker-image.yml@v1 32 | with: 33 | name: ndncert-client 34 | target: client 35 | contexts: build=docker-image://${{ needs.ndncert-build.outputs.image }} 36 | -------------------------------------------------------------------------------- /.waf-tools/sanitizers.py: -------------------------------------------------------------------------------- 1 | # Davide Pesavento (LIP6), 2016 2 | 3 | def options(opt): 4 | opt.add_option('--with-sanitizer', action='store', default='', dest='sanitizers', 5 | help='Comma-separated list of compiler sanitizers to enable [default=none]') 6 | 7 | def configure(conf): 8 | for san in conf.options.sanitizers.split(','): 9 | if not san: 10 | continue 11 | 12 | sanflag = '-fsanitize=%s' % san 13 | conf.start_msg('Checking if compiler supports %s' % sanflag) 14 | 15 | if conf.check_cxx(cxxflags=['-Werror', sanflag, '-fno-omit-frame-pointer'], 16 | linkflags=[sanflag], mandatory=False): 17 | conf.end_msg('yes') 18 | conf.env.append_unique('CXXFLAGS', [sanflag, '-fno-omit-frame-pointer']) 19 | conf.env.append_unique('LINKFLAGS', [sanflag]) 20 | else: 21 | conf.end_msg('no', color='RED') 22 | conf.fatal('%s sanitizer is not supported by the current compiler' % san) 23 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | # NDNCERT Authors 2 | 3 | The following lists maintainers, primary developers, and all much-appreciated contributors to NDNCERT in alphabetical order. 4 | The specific contributions of individual authors can be obtained from the git history of the [official NDNCERT repository](https://github.com/named-data/ndncert). 5 | If you would like to become a contributor to the official repository, please follow the recommendations in . 6 | 7 | * Alexander Afanasyev 8 | * Ashlesh Gawande 9 | * Siqi Liu 10 | * Eric Newberry 11 | * Davide Pesavento 12 | * Md Ashiqur Rahman 13 | * Junxiao Shi 14 | * Tianyuan Yu 15 | * Yufeng Zhang 16 | * Zhiyi Zhang 17 | 18 | ## Technical Advisors 19 | 20 | * Lixia Zhang 21 | -------------------------------------------------------------------------------- /.jenkins.d/10-build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eo pipefail 3 | 4 | if [[ -z $DISABLE_ASAN ]]; then 5 | ASAN="--with-sanitizer=address" 6 | fi 7 | if [[ $JOB_NAME == *code-coverage ]]; then 8 | COVERAGE="--with-coverage" 9 | fi 10 | 11 | set -x 12 | 13 | if [[ $JOB_NAME != *code-coverage && $JOB_NAME != *limited-build ]]; then 14 | # Build in release mode with tests 15 | ./waf --color=yes configure --with-tests 16 | ./waf --color=yes build 17 | 18 | # Cleanup 19 | ./waf --color=yes distclean 20 | 21 | # Build in release mode without tests 22 | ./waf --color=yes configure 23 | ./waf --color=yes build 24 | 25 | # Cleanup 26 | ./waf --color=yes distclean 27 | fi 28 | 29 | # Build in debug mode with tests 30 | ./waf --color=yes configure --debug --with-tests $ASAN $COVERAGE 31 | ./waf --color=yes build 32 | 33 | # Install 34 | sudo ./waf --color=yes install 35 | 36 | if [[ $ID_LIKE == *linux* ]]; then 37 | if [[ $(uname -m) == x86_64 && -d /usr/lib64 ]]; then 38 | sudo tee /etc/ld.so.conf.d/ndn.conf >/dev/null <<< /usr/local/lib64 39 | fi 40 | sudo ldconfig 41 | fi 42 | -------------------------------------------------------------------------------- /tests/unit-tests/config-files/config-client-1: -------------------------------------------------------------------------------- 1 | { 2 | "ca-list": 3 | [ 4 | { 5 | "ca-prefix": "/ndn/edu/ucla", 6 | "ca-info": "ndn testbed ca", 7 | "max-validity-period": "864000", 8 | "max-suffix-length": 3, 9 | "probe-parameters": 10 | [ 11 | { "probe-parameter-key": "email" } 12 | ], 13 | "certificate": "Bv0BKwcrCANuZG4IBXNpdGUxCANLRVkICEKyYEYHiBwyCARzZWxmNggAAAF/V5V9QhQJGAECGQQANu6AFVswWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARRaZbFLRSnL1fmj8X3hInCCPy4qe17QujMMYq8qe+CKqV+OjexhrUvpwRDImRZOgXLCjOTyYnW3wxlxskTz8Y3FkwbAQMcHQcbCANuZG4IBXNpdGUxCANLRVkICEKyYEYHiBwy/QD9Jv0A/g8xOTcwMDEwMVQwMDAwMDD9AP8PMjA0MjAyMjhUMDA1ODA5F0YwRAIgFtFP0WocLQCtbwMTnqNtnCDmu62EJyC4uuCZ4Q/Wb8UCIGHb3e4St78378py81GjEZd/2L/aGbE3vbYQIiNxIYPN" 14 | }, 15 | { 16 | "ca-prefix": "/ndn/edu/ucla/zhiyi", 17 | "certificate": "Bv0BKwcrCANuZG4IBXNpdGUxCANLRVkICEKyYEYHiBwyCARzZWxmNggAAAF/V5V9QhQJGAECGQQANu6AFVswWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARRaZbFLRSnL1fmj8X3hInCCPy4qe17QujMMYq8qe+CKqV+OjexhrUvpwRDImRZOgXLCjOTyYnW3wxlxskTz8Y3FkwbAQMcHQcbCANuZG4IBXNpdGUxCANLRVkICEKyYEYHiBwy/QD9Jv0A/g8xOTcwMDEwMVQwMDAwMDD9AP8PMjA0MjAyMjhUMDA1ODA5F0YwRAIgFtFP0WocLQCtbwMTnqNtnCDmu62EJyC4uuCZ4Q/Wb8UCIGHb3e4St78378py81GjEZd/2L/aGbE3vbYQIiNxIYPN" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /.jenkins.d/30-coverage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eo pipefail 3 | 4 | [[ $JOB_NAME == *code-coverage ]] || exit 0 5 | 6 | export FORCE_COLOR=1 7 | export UV_NO_MANAGED_PYTHON=1 8 | 9 | set -x 10 | 11 | # Generate a detailed HTML report and an XML report in Cobertura format using gcovr 12 | # Note: trailing slashes are important in the paths below. Do not remove them! 13 | uvx --from 'git+https://github.com/gcovr/gcovr@99b82e7' gcovr \ 14 | --decisions \ 15 | --filter src/ \ 16 | --exclude-throw-branches \ 17 | --exclude-unreachable-branches \ 18 | --cobertura build/coverage.xml \ 19 | --html-details build/gcovr/ \ 20 | --txt-summary \ 21 | build 22 | 23 | # Generate a detailed HTML report using lcov 24 | lcov \ 25 | --quiet \ 26 | --capture \ 27 | --directory . \ 28 | --include "$PWD/src/*" \ 29 | --branch-coverage \ 30 | --rc no_exception_branch=1 \ 31 | --ignore-errors inconsistent,mismatch,mismatch \ 32 | --output-file build/coverage.info 33 | 34 | genhtml \ 35 | --quiet \ 36 | --branch-coverage \ 37 | --demangle-cpp \ 38 | --legend \ 39 | --missed \ 40 | --show-proportion \ 41 | --title "ndncert unit tests" \ 42 | --ignore-errors inconsistent,inconsistent \ 43 | --output-directory build/lcov \ 44 | build/coverage.info 45 | -------------------------------------------------------------------------------- /systemd/ndncert-ca.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Certificate Management Identity Management Service for NDN 3 | BindsTo=nfd.service 4 | After=nfd.service 5 | 6 | [Service] 7 | Environment=HOME=%S/ndncert-ca 8 | ExecStart=@BINDIR@/ndncert-ca-server 9 | Restart=on-failure 10 | RestartPreventExitStatus=2 11 | User=ndn 12 | 13 | CapabilityBoundingSet= 14 | LockPersonality=yes 15 | MemoryDenyWriteExecute=yes 16 | NoNewPrivileges=yes 17 | PrivateDevices=yes 18 | PrivateTmp=yes 19 | PrivateUsers=yes 20 | ProtectControlGroups=yes 21 | ProtectHome=yes 22 | ProtectKernelModules=yes 23 | ProtectKernelTunables=yes 24 | # systemd older than v232 doesn't support a value of "strict" for ProtectSystem, 25 | # so it will ignore that line and use ProtectSystem=full; with newer systemd, 26 | # the latter assignment is recognized and takes precedence, resulting in an 27 | # effective setting of ProtectSystem=strict 28 | ProtectSystem=full 29 | ProtectSystem=strict 30 | RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 AF_PACKET 31 | RestrictNamespaces=yes 32 | RestrictRealtime=yes 33 | StateDirectory=ndncert-ca 34 | SystemCallArchitectures=native 35 | SystemCallErrorNumber=EPERM 36 | SystemCallFilter=~@aio @chown @clock @cpu-emulation @debug @keyring @module @mount @obsolete @privileged @raw-io @reboot @resources @setuid @swap 37 | 38 | # Dependency 39 | [Install] 40 | WantedBy=multi-user.target 41 | WantedBy=nfd.service -------------------------------------------------------------------------------- /ndncert-mail.conf.sample: -------------------------------------------------------------------------------- 1 | [ndncert.smtp] 2 | # Address or hostname of SMTP server 3 | smtp_server = 4 | # SMTP server port number; usually 25, 465, or 587 5 | smtp_port = 6 | # One of ssl/starttls/none 7 | encrypt_mode = 8 | # Optional username and password for SMTP authentication 9 | #smtp_user = 10 | #smtp_password = 11 | 12 | [ndncert.email] 13 | from = NDN Certificate Robot 14 | subject = Your NDNCERT verification code 15 | text_template = Your email was recently used to apply for a digital certificate from NDNCERT. 16 | Here is the verification code to enter into your application and complete the certificate issuance process. Do not share this code with anyone else. 17 | 18 | Your verification code is: ${secret} 19 | CA name: ${ca_name} 20 | Certificate name: ${cert_name} 21 | 22 | If you do not know what is going on, please ignore this message. 23 | html_template = 24 |

Your email was recently used to apply for a digital certificate from NDNCERT.
25 | Here is the verification code to enter into your application and complete the certificate issuance process. Do not share this code with anyone else.

26 |

Your verification code is: ${secret}
27 | CA name: ${ca_name}
28 | Certificate name: ${cert_name}

29 |

If you do not know what is going on, please ignore this message.

30 | -------------------------------------------------------------------------------- /.waf-tools/sqlite3.py: -------------------------------------------------------------------------------- 1 | from waflib.Configure import conf 2 | 3 | def options(opt): 4 | opt.add_option('--with-sqlite3', type='string', default=None, dest='sqlite3_dir', 5 | help='directory where SQLite3 is installed, e.g., /usr/local') 6 | 7 | @conf 8 | def check_sqlite3(self, *k, **kw): 9 | root = k and k[0] or kw.get('path', self.options.sqlite3_dir) 10 | mandatory = kw.get('mandatory', True) 11 | var = kw.get('uselib_store', 'SQLITE3') 12 | 13 | if root: 14 | self.check_cxx(lib='sqlite3', 15 | msg='Checking for SQLite3 library', 16 | define_name='HAVE_%s' % var, 17 | uselib_store=var, 18 | mandatory=mandatory, 19 | includes='%s/include' % root, 20 | libpath='%s/lib' % root) 21 | else: 22 | try: 23 | self.check_cfg(package='sqlite3', 24 | args=['--cflags', '--libs'], 25 | global_define=True, 26 | define_name='HAVE_%s' % var, 27 | uselib_store='SQLITE3', 28 | mandatory=True) 29 | except: 30 | self.check_cxx(lib='sqlite3', 31 | msg='Checking for SQLite3 library', 32 | define_name='HAVE_%s' % var, 33 | uselib_store=var, 34 | mandatory=mandatory) 35 | -------------------------------------------------------------------------------- /.jenkins.d/01-ndn-cxx.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -exo pipefail 3 | 4 | pushd "$CACHE_DIR" >/dev/null 5 | 6 | INSTALLED_VERSION= 7 | if [[ $ID == macos ]]; then 8 | BOOST=$(brew list --formula --versions boost) 9 | OLD_BOOST=$(cat boost.txt || :) 10 | if [[ $OLD_BOOST != $BOOST ]]; then 11 | echo "$BOOST" > boost.txt 12 | INSTALLED_VERSION=NONE 13 | fi 14 | fi 15 | 16 | if [[ -z $INSTALLED_VERSION ]]; then 17 | INSTALLED_VERSION=$(git -C ndn-cxx rev-parse HEAD 2>/dev/null || echo NONE) 18 | fi 19 | 20 | sudo rm -rf ndn-cxx-latest 21 | git clone --depth 1 https://github.com/named-data/ndn-cxx.git ndn-cxx-latest 22 | LATEST_VERSION=$(git -C ndn-cxx-latest rev-parse HEAD 2>/dev/null || echo UNKNOWN) 23 | 24 | if [[ $INSTALLED_VERSION != $LATEST_VERSION ]]; then 25 | sudo rm -rf ndn-cxx 26 | mv ndn-cxx-latest ndn-cxx 27 | else 28 | sudo rm -rf ndn-cxx-latest 29 | fi 30 | 31 | sudo rm -f /usr/local/bin/ndnsec* 32 | sudo rm -fr /usr/local/include/ndn-cxx 33 | sudo rm -f /usr/local/lib{,64}/libndn-cxx* 34 | sudo rm -f /usr/local/lib{,64}/pkgconfig/libndn-cxx.pc 35 | 36 | pushd ndn-cxx >/dev/null 37 | 38 | ./waf --color=yes configure 39 | ./waf --color=yes build 40 | sudo ./waf --color=yes install 41 | 42 | popd >/dev/null 43 | popd >/dev/null 44 | 45 | if [[ $ID_LIKE == *linux* ]]; then 46 | if [[ $(uname -m) == x86_64 && -d /usr/lib64 ]]; then 47 | sudo tee /etc/ld.so.conf.d/ndn.conf >/dev/null <<< /usr/local/lib64 48 | fi 49 | sudo ldconfig 50 | fi 51 | -------------------------------------------------------------------------------- /tests/io-key-chain-fixture.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2013-2022 Regents of the University of California. 4 | * 5 | * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). 6 | * 7 | * ndn-cxx library is free software: you can redistribute it and/or modify it under the 8 | * terms of the GNU Lesser General Public License as published by the Free Software 9 | * Foundation, either version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License and GNU Lesser 16 | * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see 17 | * . 18 | * 19 | * See AUTHORS.md for complete list of ndn-cxx authors and contributors. 20 | */ 21 | 22 | #ifndef NDNCERT_TESTS_IO_KEY_CHAIN_FIXTURE_HPP 23 | #define NDNCERT_TESTS_IO_KEY_CHAIN_FIXTURE_HPP 24 | 25 | #include "tests/io-fixture.hpp" 26 | #include "tests/key-chain-fixture.hpp" 27 | 28 | namespace ndncert::tests { 29 | 30 | class IoKeyChainFixture : public IoFixture, public KeyChainFixture 31 | { 32 | }; 33 | 34 | } // namespace ndncert::tests 35 | 36 | #endif // NDNCERT_TESTS_IO_KEY_CHAIN_FIXTURE_HPP 37 | -------------------------------------------------------------------------------- /tests/unit-tests/main.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2014-2022, Regents of the University of California, 4 | * Arizona Board of Regents, 5 | * Colorado State University, 6 | * University Pierre & Marie Curie, Sorbonne University, 7 | * Washington University in St. Louis, 8 | * Beijing Institute of Technology, 9 | * The University of Memphis. 10 | * 11 | * This file, originally written as part of NFD (Named Data Networking Forwarding Daemon), 12 | * is a part of ndncert, a certificate management system based on NDN. 13 | * 14 | * ndncert is free software: you can redistribute it and/or modify it under the terms 15 | * of the GNU General Public License as published by the Free Software Foundation, either 16 | * version 3 of the License, or (at your option) any later version. 17 | * 18 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 19 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 20 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 21 | * 22 | * You should have received copies of the GNU General Public License along with 23 | * ndncert, e.g., in COPYING.md file. If not, see . 24 | * 25 | * See AUTHORS.md for complete list of ndncert authors and contributors. 26 | */ 27 | 28 | #define BOOST_TEST_MODULE ndncert 29 | #include "tests/boost-test.hpp" 30 | -------------------------------------------------------------------------------- /src/detail/ca-storage.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "detail/ca-storage.hpp" 22 | 23 | namespace ndncert::ca { 24 | 25 | std::unique_ptr 26 | CaStorage::createCaStorage(const std::string& caStorageType, const Name& caName, const std::string& path) 27 | { 28 | auto& factory = getFactory(); 29 | auto i = factory.find(caStorageType); 30 | return i == factory.end() ? nullptr : i->second(caName, path); 31 | } 32 | 33 | CaStorage::CaStorageFactory& 34 | CaStorage::getFactory() 35 | { 36 | static CaStorageFactory factory; 37 | return factory; 38 | } 39 | 40 | } // namespace ndncert::ca 41 | -------------------------------------------------------------------------------- /ca.conf.sample: -------------------------------------------------------------------------------- 1 | { 2 | "ca-prefix": "/example", 3 | "ca-info": "An example NDNCERT CA", 4 | "max-validity-period": "1296000", 5 | "max-suffix-length": "2", 6 | "probe-parameters": [ 7 | { 8 | "probe-parameter-key": "email" 9 | } 10 | ], 11 | "supported-challenges": [ 12 | { 13 | "challenge": "pin" 14 | }, 15 | { 16 | "challenge": "email" 17 | } 18 | ], 19 | "redirect-to": [ 20 | { 21 | "ca-prefix": "/ndn/edu/ucla", 22 | "certificate": "Bv0BNQcwCANuZG4IA2VkdQgEdWNsYQgDS0VZCAgAdGt6D7S2VAgEc2VsZggJ/QAAAX5lZMOiFAkYAQIZBAA27oAVWzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOKmvwHmK5t+MhMPgft4qmKC7YF9I6UM/o7GFa4BjZQknsqLvxdW2zIAF+iPPHJV0eVAijX6bYrQobuomiWZAY0WUBsBAxwhBx8IA25kbggDZWR1CAR1Y2xhCANLRVkICAB0a3oPtLZU/QD9Jv0A/g8xOTcwMDEwMVQwMDAwMDD9AP8PMjA0MjAxMTJUMDAxNjQ5F0cwRQIgBF/HS0j1DMo/dIILv/6IMUmMAhVtS3m97YgS8tsBhC0CIQCgEm0e6KoBCyV6PiueN9YW9zSSkdg8MLCxsyduP8tRsQ==", 23 | "policy-type": "email", 24 | "policy-param": "g.ucla.edu" 25 | }, 26 | { 27 | "ca-prefix": "/ndn/edu/ucla/cs", 28 | "certificate": "Bv0BPgc0CANuZG4IA2VkdQgEdWNsYQgCY3MIA0tFWQgI27kFrpVyxUAIBHNlbGYICf0AAAF+ZZ/79xQJGAECGQQANu6AFVswWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASOLtEWMpMk8tPqPe0VY9SAYA0e969NNy5t0QeseNvr6AbYWQHBR4oa6Ymv3TRlQnyy+IzvKPte5suX/Qhtnjn2FlQbAQMcJQcjCANuZG4IA2VkdQgEdWNsYQgCY3MIA0tFWQgI27kFrpVyxUD9AP0m/QD+DzE5NzAwMTAxVDAwMDAwMP0A/w8yMDQyMDExMlQwMTIxMzAXSDBGAiEAm+aJbcmI0n37Qhear5fo//S02ZlDkmao8a7olSsElx8CIQDD8dZkYfD8xcvYl3vXm7G/NSXFrnrRqxC7NR/4r4swbw==", 29 | "policy-type": "email", 30 | "policy-param": "cs.ucla.edu" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /src/redirection/redirection-email.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_REDIRECTION_EMAIL_HPP 22 | #define NDNCERT_REDIRECTION_EMAIL_HPP 23 | 24 | #include "redirection-policy.hpp" 25 | 26 | namespace ndncert { 27 | 28 | class RedirectionEmail : public RedirectionPolicy 29 | { 30 | public: 31 | explicit 32 | RedirectionEmail(const std::string& format = ""); 33 | 34 | bool 35 | isRedirecting(const std::multimap& params) override; 36 | 37 | private: 38 | std::string m_domain; 39 | }; 40 | 41 | } // namespace ndncert 42 | 43 | #endif // NDNCERT_REDIRECTION_EMAIL_HPP 44 | -------------------------------------------------------------------------------- /src/redirection/redirection-policy.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "redirection-policy.hpp" 22 | 23 | namespace ndncert { 24 | 25 | std::unique_ptr 26 | RedirectionPolicy::createPolicyFunc(const std::string& policyType, const std::string& format) 27 | { 28 | auto& factory = getFactory(); 29 | auto i = factory.find(policyType); 30 | return i == factory.end() ? nullptr : i->second(format); 31 | } 32 | 33 | RedirectionPolicy::PolicyFactory& 34 | RedirectionPolicy::getFactory() 35 | { 36 | static PolicyFactory factory; 37 | return factory; 38 | } 39 | 40 | } // namespace ndncert 41 | -------------------------------------------------------------------------------- /tests/key-chain-fixture.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2013-2024 Regents of the University of California. 4 | * 5 | * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). 6 | * 7 | * ndn-cxx library is free software: you can redistribute it and/or modify it under the 8 | * terms of the GNU Lesser General Public License as published by the Free Software 9 | * Foundation, either version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License and GNU Lesser 16 | * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see 17 | * . 18 | * 19 | * See AUTHORS.md for complete list of ndn-cxx authors and contributors. 20 | */ 21 | 22 | #ifndef NDNCERT_TESTS_KEY_CHAIN_FIXTURE_HPP 23 | #define NDNCERT_TESTS_KEY_CHAIN_FIXTURE_HPP 24 | 25 | #include 26 | 27 | namespace ndncert::tests { 28 | 29 | /** 30 | * @brief A fixture providing an in-memory KeyChain. 31 | */ 32 | class KeyChainFixture 33 | { 34 | protected: 35 | ndn::KeyChain m_keyChain{"pib-memory:", "tpm-memory:"}; 36 | }; 37 | 38 | } // namespace ndncert::tests 39 | 40 | #endif // NDNCERT_TESTS_KEY_CHAIN_FIXTURE_HPP 41 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | ARG NDN_CXX_VERSION=latest 4 | FROM ghcr.io/named-data/ndn-cxx-build:${NDN_CXX_VERSION} AS build 5 | 6 | ARG JOBS 7 | ARG SOURCE_DATE_EPOCH 8 | RUN --mount=rw,target=/src <. 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_ASSIGNMENT_HASH_HPP 22 | #define NDNCERT_ASSIGNMENT_HASH_HPP 23 | 24 | #include "assignment-func.hpp" 25 | 26 | namespace ndncert { 27 | 28 | /** 29 | * assign names base on client probe parameter 30 | */ 31 | class AssignmentHash : public NameAssignmentFunc 32 | { 33 | public: 34 | AssignmentHash(const std::string& format = ""); 35 | 36 | std::vector 37 | assignName(const std::multimap& params) override; 38 | }; 39 | 40 | } // namespace ndncert 41 | 42 | #endif // NDNCERT_ASSIGNMENT_HASH_HPP 43 | -------------------------------------------------------------------------------- /src/name-assignment/assignment-random.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "assignment-random.hpp" 22 | 23 | #include 24 | 25 | namespace ndncert { 26 | 27 | NDNCERT_REGISTER_NAME_ASSIGNMENT_FUNC(AssignmentRandom, "random"); 28 | 29 | AssignmentRandom::AssignmentRandom(const std::string& format) 30 | : NameAssignmentFunc(format) 31 | { 32 | } 33 | 34 | std::vector 35 | AssignmentRandom::assignName(const std::multimap&) 36 | { 37 | return {ndn::PartialName(std::to_string(ndn::random::generateSecureWord64()))}; 38 | } 39 | 40 | } // namespace ndncert 41 | -------------------------------------------------------------------------------- /src/name-assignment/assignment-param.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2021, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_ASSIGNMENT_PARAM_HPP 22 | #define NDNCERT_ASSIGNMENT_PARAM_HPP 23 | 24 | #include "assignment-func.hpp" 25 | 26 | namespace ndncert { 27 | 28 | /** 29 | * assign names base on client probe parameter 30 | */ 31 | class AssignmentParam : public NameAssignmentFunc 32 | { 33 | public: 34 | AssignmentParam(const std::string& format = ""); 35 | 36 | std::vector 37 | assignName(const std::multimap& params) override; 38 | }; 39 | 40 | } // namespace ndncert 41 | 42 | #endif // NDNCERT_ASSIGNMENT_PARAM_HPP 43 | -------------------------------------------------------------------------------- /src/redirection/redirection-param.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_REDIRECTION_PARAM_HPP 22 | #define NDNCERT_REDIRECTION_PARAM_HPP 23 | 24 | #include "redirection-policy.hpp" 25 | 26 | namespace ndncert { 27 | 28 | class RedirectionParam : public RedirectionPolicy 29 | { 30 | public: 31 | explicit 32 | RedirectionParam(const std::string& format = ""); 33 | 34 | bool 35 | isRedirecting(const std::multimap& params) override; 36 | 37 | private: 38 | std::map m_format; 39 | }; 40 | 41 | } // namespace ndncert 42 | 43 | #endif // NDNCERT_REDIRECTION_PARAM_HPP 44 | -------------------------------------------------------------------------------- /src/detail/challenge-encoder.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_CHALLENGE_ENCODER_HPP 22 | #define NDNCERT_DETAIL_CHALLENGE_ENCODER_HPP 23 | 24 | #include "detail/ca-request-state.hpp" 25 | #include "requester-request.hpp" 26 | 27 | namespace ndncert::challengetlv { 28 | 29 | Block 30 | encodeDataContent(ca::RequestState& request, const Name& issuedCertName = Name(), 31 | const Name& forwardingHint = Name()); 32 | 33 | void 34 | decodeDataContent(const Block& contentBlock, requester::Request& state); 35 | 36 | } // namespace ndncert::challengetlv 37 | 38 | #endif // NDNCERT_DETAIL_CHALLENGE_ENCODER_HPP 39 | -------------------------------------------------------------------------------- /src/name-assignment/assignment-random.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2021, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_ASSIGNMENT_RANDOM_HPP 22 | #define NDNCERT_ASSIGNMENT_RANDOM_HPP 23 | 24 | #include "assignment-func.hpp" 25 | 26 | namespace ndncert { 27 | 28 | /** 29 | * assign names base on client probe parameter 30 | */ 31 | class AssignmentRandom : public NameAssignmentFunc 32 | { 33 | public: 34 | AssignmentRandom(const std::string& format = ""); 35 | 36 | std::vector 37 | assignName(const std::multimap& params) override; 38 | }; 39 | 40 | } // namespace ndncert 41 | 42 | #endif // NDNCERT_ASSIGNMENT_RANDOM_HPP 43 | -------------------------------------------------------------------------------- /src/name-assignment/assignment-email.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_ASSIGNMENT_EMAIL_HPP 22 | #define NDNCERT_ASSIGNMENT_EMAIL_HPP 23 | 24 | #include "assignment-func.hpp" 25 | 26 | namespace ndncert { 27 | 28 | /** 29 | * @brief Assign names based on requester's email address 30 | */ 31 | class AssignmentEmail : public NameAssignmentFunc 32 | { 33 | public: 34 | explicit 35 | AssignmentEmail(const std::string& format = ""); 36 | 37 | std::vector 38 | assignName(const std::multimap& params) override; 39 | }; 40 | 41 | } // namespace ndncert 42 | 43 | #endif // NDNCERT_ASSIGNMENT_EMAIL_HPP 44 | -------------------------------------------------------------------------------- /.jenkins.d/README.md: -------------------------------------------------------------------------------- 1 | # Continuous Integration Scripts 2 | 3 | ## Environment Variables 4 | 5 | - `ID`: lower-case string that identifies the operating system, for example: `ID=ubuntu`, 6 | `ID=centos`. See [os-release(5)] for more information. On macOS, where `os-release` is 7 | not available, we emulate it by setting `ID=macos`. 8 | 9 | - `ID_LIKE`: space-separated list of operating system identifiers that are closely related 10 | to the running OS. See [os-release(5)] for more information. The listed values are used 11 | by the CI scripts to select the proper behavior for different platforms and OS flavors. 12 | 13 | Examples: 14 | 15 | - On CentOS, `ID_LIKE="centos rhel fedora linux"` 16 | - On Ubuntu, `ID_LIKE="ubuntu debian linux"` 17 | 18 | - `VERSION_ID`: identifies the operating system version, excluding any release code names. 19 | See [os-release(5)] for more information. Examples: `VERSION_ID=42`, `VERSION_ID=22.04`. 20 | 21 | - `JOB_NAME`: defines the type of the current CI job. Depending on the job type, the CI 22 | scripts can perform different tasks. 23 | 24 | Supported values: 25 | 26 | - empty: default build task 27 | - `code-coverage`: debug build with tests and code coverage analysis 28 | - `limited-build`: only a single debug build with tests 29 | 30 | - `CACHE_DIR`: directory containing cached files from previous builds, e.g., a compiled 31 | version of ndn-cxx. If not set, `/tmp` is used. 32 | 33 | - `DISABLE_ASAN`: disable building with AddressSanitizer. This is automatically set for 34 | the `code-coverage` job type. 35 | 36 | [os-release(5)]: https://www.freedesktop.org/software/systemd/man/os-release.html 37 | -------------------------------------------------------------------------------- /src/detail/error-encoder.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_ERROR_ENCODER_HPP 22 | #define NDNCERT_DETAIL_ERROR_ENCODER_HPP 23 | 24 | #include "detail/ndncert-common.hpp" 25 | 26 | #include 27 | 28 | namespace ndncert::errortlv { 29 | 30 | /** 31 | * Encode error information into a Data content TLV 32 | */ 33 | Block 34 | encodeDataContent(ErrorCode errorCode, std::string_view description); 35 | 36 | /** 37 | * Decode error information from Data content TLV 38 | */ 39 | std::tuple 40 | decodefromDataContent(const Block& block); 41 | 42 | } // namespace ndncert::errortlv 43 | 44 | #endif // NDNCERT_DETAIL_ERROR_ENCODER_HPP 45 | -------------------------------------------------------------------------------- /src/detail/info-encoder.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_INFO_ENCODER_HPP 22 | #define NDNCERT_DETAIL_INFO_ENCODER_HPP 23 | 24 | #include "detail/ca-profile.hpp" 25 | 26 | namespace ndncert::infotlv { 27 | 28 | /** 29 | * Encode CA configuration and its certificate into a TLV block as INFO Data packet content. 30 | */ 31 | Block 32 | encodeDataContent(const CaProfile& caConfig, const Certificate& certificate); 33 | 34 | /** 35 | * Decode CA configuration from the TLV block of INFO Data packet content. 36 | */ 37 | CaProfile 38 | decodeDataContent(const Block& block); 39 | 40 | } // namespace ndncert::infotlv 41 | 42 | #endif // NDNCERT_DETAIL_INFO_ENCODER_HPP 43 | -------------------------------------------------------------------------------- /tests/io-fixture.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2013-2023 Regents of the University of California. 4 | * 5 | * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). 6 | * 7 | * ndn-cxx library is free software: you can redistribute it and/or modify it under the 8 | * terms of the GNU Lesser General Public License as published by the Free Software 9 | * Foundation, either version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License and GNU Lesser 16 | * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see 17 | * . 18 | * 19 | * See AUTHORS.md for complete list of ndn-cxx authors and contributors. 20 | */ 21 | 22 | #ifndef NDNCERT_TESTS_IO_FIXTURE_HPP 23 | #define NDNCERT_TESTS_IO_FIXTURE_HPP 24 | 25 | #include "tests/clock-fixture.hpp" 26 | 27 | #include 28 | 29 | namespace ndncert::tests { 30 | 31 | class IoFixture : public ClockFixture 32 | { 33 | private: 34 | void 35 | afterTick() final 36 | { 37 | if (m_io.stopped()) { 38 | m_io.restart(); 39 | } 40 | m_io.poll(); 41 | } 42 | 43 | protected: 44 | boost::asio::io_context m_io; 45 | }; 46 | 47 | } // namespace ndncert::tests 48 | 49 | #endif // NDNCERT_TESTS_IO_FIXTURE_HPP 50 | -------------------------------------------------------------------------------- /tests/unit-tests/config-files/config-ca-5: -------------------------------------------------------------------------------- 1 | { 2 | "ca-prefix": "/ndn", 3 | "ca-info": "unsupported challenge", 4 | "max-validity-period": "86400", 5 | "max-suffix-length": 3, 6 | "probe-parameters": 7 | [ 8 | { "probe-parameter-key": "full name" } 9 | ], 10 | "supported-challenges": 11 | [ 12 | { "challenge": "pin" } 13 | ], 14 | "redirect-to": 15 | [ 16 | { 17 | "ca-prefix": "/ndn/edu/ucla", 18 | "certificate": "Bv0BNQcvCANuZG4IA2VkdQgEdWNsYQgDS0VZCAhtCJjCeE5aEwgEc2VsZjYIAAABf1ePw8kUCRgBAhkEADbugBVbMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwrhu4gD0eba7jbVqg1qfwuRj2JSqOfnwdiOlholvhCGpdXHpqg5o68ajADQPL9S555uvfabbFnPhv86X/Diy5hZQGwEDHCEHHwgDbmRuCANlZHUIBHVjbGEIA0tFWQgIbQiYwnhOWhP9AP0m/QD+DzE5NzAwMTAxVDAwMDAwMP0A/w8yMDQyMDIyOFQwMDUxNTMXSDBGAiEA11i8sGwf83hd+IQ2vve+Ax1O7zZeV8cG6FAXvXFQ0kACIQDAvqq0CRAYYJ/RFLW21wNGJf1Rf3OgFyGEKpLjnRkxaw==", 19 | "policy-type": "param", 20 | "policy-param": "" 21 | }, 22 | { 23 | "ca-prefix": "/ndn/edu/ucla/cs/irl", 24 | "certificate": "Bv0BRQc4CANuZG4IA2VkdQgEdWNsYQgCY3MIA2lybAgDS0VZCAgWVGa5Tzd9WggEc2VsZjYIAAABf1eQ1LoUCRgBAhkEADbugBVbMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7hBKT9GapKRII3LT9q0kY5RXEE9Cu9B2Pg/E4Mndbqr3nbnMmm+SUAeIcrnTQa4c9ri8oCLkTesXsW0Tr8oTuhZZGwEDHCoHKAgDbmRuCANlZHUIBHVjbGEIAmNzCANpcmwIA0tFWQgIFlRmuU83fVr9AP0m/QD+DzE5NzAwMTAxVDAwMDAwMP0A/w8yMDQyMDIyOFQwMDUzMDMXRjBEAiA9Q/FjffFLasMfr7MIQY/KBBQScNKYyrEyphz4wOcQjAIgLf14XL8LaqqUyfBkwQXeCv3pipsnZw5BFhv8c5UCLVE=", 25 | "policy-type": "param", 26 | "policy-param": "" 27 | } 28 | ], 29 | "name-assignment": 30 | { 31 | "param": "/group/email", 32 | "param": "/group/name", 33 | "random": "" 34 | } 35 | } -------------------------------------------------------------------------------- /.jenkins: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eo pipefail 3 | 4 | case $(uname) in 5 | Linux) 6 | if [[ -e /etc/os-release ]]; then 7 | source /etc/os-release 8 | else 9 | source /usr/lib/os-release 10 | fi 11 | export ID VERSION_ID 12 | export ID_LIKE="${ID} ${ID_LIKE} linux" 13 | if [[ -z $GITHUB_ACTIONS ]]; then 14 | export PATH="${HOME}/.local/bin${PATH:+:}${PATH}" 15 | fi 16 | ;; 17 | Darwin) 18 | # Emulate a subset of os-release(5) 19 | export ID=macos 20 | export VERSION_ID=$(sw_vers -productVersion) 21 | if [[ -z $GITHUB_ACTIONS ]]; then 22 | export PATH="/usr/local/bin${PATH:+:}${PATH}" 23 | fi 24 | if [[ -x /opt/homebrew/bin/brew ]]; then 25 | eval "$(/opt/homebrew/bin/brew shellenv)" 26 | elif [[ -x /usr/local/bin/brew ]]; then 27 | eval "$(/usr/local/bin/brew shellenv)" 28 | fi 29 | ;; 30 | esac 31 | 32 | export CACHE_DIR=${CACHE_DIR:-/tmp} 33 | 34 | if [[ $JOB_NAME == *code-coverage ]]; then 35 | export DISABLE_ASAN=1 36 | export DISABLE_HEADERS_CHECK=1 37 | fi 38 | 39 | # https://reproducible-builds.org/docs/source-date-epoch/ 40 | export SOURCE_DATE_EPOCH=$(git log -1 --format=%ct) 41 | 42 | for file in .jenkins.d/*; do 43 | [[ -f $file && -x $file ]] || continue 44 | 45 | if [[ -n $GITHUB_ACTIONS ]]; then 46 | label=$(basename "$file" | sed -E 's/[[:digit:]]+-(.*)\..*/\1/') 47 | echo "::group::${label}" 48 | fi 49 | 50 | echo "\$ $file" 51 | "$file" 52 | 53 | if [[ -n $GITHUB_ACTIONS ]]; then 54 | echo "::endgroup::" 55 | fi 56 | done 57 | -------------------------------------------------------------------------------- /src/redirection/redirection-email.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "redirection-email.hpp" 22 | 23 | namespace ndncert { 24 | 25 | NDNCERT_REGISTER_REDIRECTION_POLICY(RedirectionEmail, "email"); 26 | 27 | RedirectionEmail::RedirectionEmail(const std::string& format) 28 | : m_domain(format) 29 | { 30 | } 31 | 32 | bool 33 | RedirectionEmail::isRedirecting(const std::multimap& params) 34 | { 35 | for (auto it = params.find("email"); it != params.end() && it->first == "email"; it++) { 36 | auto i = it->second.rfind('@'); 37 | if (i != std::string::npos && it->second.substr(i + 1) == m_domain) { 38 | return true; 39 | } 40 | } 41 | return false; 42 | } 43 | 44 | } // namespace ndncert 45 | -------------------------------------------------------------------------------- /tests/boost-test.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2014-2020, Regents of the University of California, 4 | * Arizona Board of Regents, 5 | * Colorado State University, 6 | * University Pierre & Marie Curie, Sorbonne University, 7 | * Washington University in St. Louis, 8 | * Beijing Institute of Technology, 9 | * The University of Memphis. 10 | * 11 | * This file, originally written as part of NFD (Named Data Networking Forwarding Daemon), 12 | * is a part of ndncert, a certificate management system based on NDN. 13 | * 14 | * ndncert is free software: you can redistribute it and/or modify it under the terms 15 | * of the GNU General Public License as published by the Free Software Foundation, either 16 | * version 3 of the License, or (at your option) any later version. 17 | * 18 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 19 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 20 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 21 | * 22 | * You should have received copies of the GNU General Public License along with 23 | * ndncert, e.g., in COPYING.md file. If not, see . 24 | * 25 | * See AUTHORS.md for complete list of ndncert authors and contributors. 26 | */ 27 | 28 | #ifndef NDNCERT_TESTS_BOOST_TEST_HPP 29 | #define NDNCERT_TESTS_BOOST_TEST_HPP 30 | 31 | // suppress warnings from Boost.Test 32 | #pragma GCC system_header 33 | #pragma clang system_header 34 | 35 | #define BOOST_TEST_DYN_LINK 36 | #include 37 | 38 | #endif // NDNCERT_TESTS_BOOST_TEST_HPP 39 | -------------------------------------------------------------------------------- /.jenkins.d/00-deps.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eo pipefail 3 | 4 | APT_PKGS=( 5 | dpkg-dev 6 | g++ 7 | libboost-chrono-dev 8 | libboost-date-time-dev 9 | libboost-dev 10 | libboost-log-dev 11 | libboost-program-options-dev 12 | libboost-stacktrace-dev 13 | libboost-test-dev 14 | libboost-thread-dev 15 | libsqlite3-dev 16 | libssl-dev 17 | pkgconf 18 | python3 19 | ) 20 | DNF_PKGS=( 21 | boost-devel 22 | gcc-c++ 23 | libasan 24 | lld 25 | openssl-devel 26 | pkgconf 27 | python3 28 | sqlite-devel 29 | ) 30 | FORMULAE=(boost openssl pkgconf) 31 | case $JOB_NAME in 32 | *code-coverage) 33 | APT_PKGS+=(lcov libjson-xs-perl) 34 | ;; 35 | *Docs) 36 | APT_PKGS+=(doxygen graphviz) 37 | FORMULAE+=(doxygen graphviz) 38 | ;; 39 | esac 40 | 41 | install_uv() { 42 | if [[ -z $GITHUB_ACTIONS && $ID_LIKE == *debian* ]]; then 43 | sudo apt-get install -qy --no-install-recommends pipx 44 | pipx upgrade uv || pipx install uv 45 | fi 46 | } 47 | 48 | set -x 49 | 50 | if [[ $ID == macos ]]; then 51 | export HOMEBREW_COLOR=1 52 | export HOMEBREW_NO_ENV_HINTS=1 53 | if [[ -n $GITHUB_ACTIONS ]]; then 54 | export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 55 | fi 56 | brew update 57 | brew install --formula "${FORMULAE[@]}" 58 | elif [[ $ID_LIKE == *debian* ]]; then 59 | sudo apt-get update -qq 60 | sudo apt-get install -qy --no-install-recommends "${APT_PKGS[@]}" 61 | elif [[ $ID_LIKE == *fedora* ]]; then 62 | sudo dnf install -y "${DNF_PKGS[@]}" 63 | fi 64 | 65 | case $JOB_NAME in 66 | *code-coverage) 67 | install_uv 68 | ;; 69 | *Docs) 70 | install_uv 71 | export FORCE_COLOR=1 72 | export UV_NO_MANAGED_PYTHON=1 73 | uv tool install sphinx --upgrade --with-requirements docs/requirements.txt 74 | ;; 75 | esac 76 | -------------------------------------------------------------------------------- /src/name-assignment/assignment-hash.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "assignment-hash.hpp" 22 | 23 | #include 24 | 25 | namespace ndncert { 26 | 27 | NDNCERT_REGISTER_NAME_ASSIGNMENT_FUNC(AssignmentHash, "hash"); 28 | 29 | AssignmentHash::AssignmentHash(const std::string& format) 30 | : NameAssignmentFunc(format) 31 | { 32 | } 33 | 34 | std::vector 35 | AssignmentHash::assignName(const std::multimap& params) 36 | { 37 | std::vector resultList; 38 | Name result; 39 | for (const auto& item : m_nameFormat) { 40 | auto it = params.find(item); 41 | if (it != params.end()) { 42 | ndn::util::Sha256 digest; 43 | digest << it->second; 44 | result.append(digest.toString()); 45 | } 46 | else { 47 | return resultList; 48 | } 49 | } 50 | resultList.push_back(std::move(result)); 51 | return resultList; 52 | } 53 | 54 | } // namespace ndncert 55 | -------------------------------------------------------------------------------- /src/detail/probe-encoder.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_PROBE_ENCODER_HPP 22 | #define NDNCERT_DETAIL_PROBE_ENCODER_HPP 23 | 24 | #include "detail/ndncert-common.hpp" 25 | 26 | #include 27 | 28 | namespace ndncert::probetlv { 29 | 30 | // For Client use 31 | Block 32 | encodeApplicationParameters(const std::multimap& parameters); 33 | 34 | void 35 | decodeDataContent(const Block& block, 36 | std::vector>& availableNames, 37 | std::vector& availableRedirection); 38 | 39 | // For CA use 40 | Block 41 | encodeDataContent(const std::vector& identifiers, 42 | std::optional maxSuffixLength = std::nullopt, 43 | const std::vector& redirectionItems = {}); 44 | 45 | std::multimap 46 | decodeApplicationParameters(const Block& block); 47 | 48 | } // namespace ndncert::probetlv 49 | 50 | #endif // NDNCERT_DETAIL_PROBE_ENCODER_HPP 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NDNCERT: NDN Certificate Management Protocol 2 | 3 | ![Language](https://img.shields.io/badge/C%2B%2B-17-blue) 4 | [![CI](https://github.com/named-data/ndncert/actions/workflows/ci.yml/badge.svg)](https://github.com/named-data/ndncert/actions/workflows/ci.yml) 5 | [![Docker](https://github.com/named-data/ndncert/actions/workflows/docker.yml/badge.svg)](https://github.com/named-data/ndncert/actions/workflows/docker.yml) 6 | 7 | The NDN certificate management protocol (**NDNCERT**) enables automatic certificate management 8 | in NDN. In Named Data Networking (NDN), every entity should have a corresponding identity 9 | (namespace) and the corresponding certificate for this namespace. Moreover, entities need simple 10 | mechanisms to manage sub-identities and their certificates. NDNCERT provides flexible mechanisms 11 | to request certificates from a certificate authority (CA) and, as soon as the certificate is 12 | obtained, mechanisms to issue and manage certificates in the designated namespace. Note that 13 | NDNCERT does not impose any specific trust model or trust anchors. While the primary use case of 14 | this protocol is to manage NDN testbed certificates, it can be used with any other set of global 15 | and local trust anchors. 16 | 17 | See [our GitHub wiki](https://github.com/named-data/ndncert/wiki) for more details. 18 | 19 | ## Reporting bugs 20 | 21 | Please submit any bug reports or feature requests to the 22 | [NDNCERT issue tracker](https://redmine.named-data.net/projects/ndncert/issues). 23 | 24 | ## Contributing 25 | 26 | We greatly appreciate contributions to the NDNCERT code base, provided that they are 27 | licensed under the GNU GPL version 3 or a compatible license. 28 | If you are new to the NDN software community, please read our [Contributor's Guide]( 29 | https://github.com/named-data/.github/blob/main/CONTRIBUTING.md) to get started. 30 | 31 | ## License 32 | 33 | NDNCERT is free software distributed under the GNU General Public License version 3. 34 | See [`COPYING.md`](COPYING.md) for details. 35 | -------------------------------------------------------------------------------- /tests/clock-fixture.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2013-2022 Regents of the University of California. 4 | * 5 | * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). 6 | * 7 | * ndn-cxx library is free software: you can redistribute it and/or modify it under the 8 | * terms of the GNU Lesser General Public License as published by the Free Software 9 | * Foundation, either version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License and GNU Lesser 16 | * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see 17 | * . 18 | * 19 | * See AUTHORS.md for complete list of ndn-cxx authors and contributors. 20 | */ 21 | 22 | #include "tests/clock-fixture.hpp" 23 | 24 | namespace ndncert::tests { 25 | 26 | ClockFixture::ClockFixture() 27 | : m_steadyClock(std::make_shared()) 28 | , m_systemClock(std::make_shared()) 29 | { 30 | time::setCustomClocks(m_steadyClock, m_systemClock); 31 | } 32 | 33 | ClockFixture::~ClockFixture() 34 | { 35 | time::setCustomClocks(nullptr, nullptr); 36 | } 37 | 38 | void 39 | ClockFixture::advanceClocks(time::nanoseconds tick, time::nanoseconds total) 40 | { 41 | BOOST_ASSERT(tick > time::nanoseconds::zero()); 42 | BOOST_ASSERT(total >= time::nanoseconds::zero()); 43 | 44 | while (total > time::nanoseconds::zero()) { 45 | auto t = std::min(tick, total); 46 | m_steadyClock->advance(t); 47 | m_systemClock->advance(t); 48 | total -= t; 49 | 50 | afterTick(); 51 | } 52 | } 53 | 54 | } // namespace ndncert::tests 55 | -------------------------------------------------------------------------------- /src/detail/ca-memory.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_CA_MEMORY_HPP 22 | #define NDNCERT_DETAIL_CA_MEMORY_HPP 23 | 24 | #include "detail/ca-storage.hpp" 25 | 26 | namespace ndncert::ca { 27 | 28 | class CaMemory : public CaStorage 29 | { 30 | public: 31 | static const std::string STORAGE_TYPE; 32 | 33 | explicit 34 | CaMemory(const Name& caName = "", const std::string& path = ""); 35 | 36 | public: 37 | RequestState 38 | getRequest(const RequestId& requestId) override; 39 | 40 | void 41 | addRequest(const RequestState& request) override; 42 | 43 | void 44 | updateRequest(const RequestState& request) override; 45 | 46 | void 47 | deleteRequest(const RequestId& requestId) override; 48 | 49 | std::list 50 | listAllRequests() override; 51 | 52 | std::list 53 | listAllRequests(const Name& caName) override; 54 | 55 | private: 56 | std::map m_requests; 57 | }; 58 | 59 | } // namespace ndncert::ca 60 | 61 | #endif // NDNCERT_DETAIL_CA_MEMORY_HPP 62 | -------------------------------------------------------------------------------- /src/detail/ca-sqlite.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_CA_SQLITE_HPP 22 | #define NDNCERT_DETAIL_CA_SQLITE_HPP 23 | 24 | #include "detail/ca-storage.hpp" 25 | 26 | struct sqlite3; 27 | 28 | namespace ndncert::ca { 29 | 30 | class CaSqlite : public CaStorage 31 | { 32 | public: 33 | static const std::string STORAGE_TYPE; 34 | 35 | explicit 36 | CaSqlite(const Name& caName, const std::string& path = ""); 37 | 38 | ~CaSqlite() override; 39 | 40 | public: 41 | RequestState 42 | getRequest(const RequestId& requestId) override; 43 | 44 | void 45 | addRequest(const RequestState& request) override; 46 | 47 | void 48 | updateRequest(const RequestState& request) override; 49 | 50 | void 51 | deleteRequest(const RequestId& requestId) override; 52 | 53 | std::list 54 | listAllRequests() override; 55 | 56 | std::list 57 | listAllRequests(const Name& caName) override; 58 | 59 | private: 60 | sqlite3* m_database; 61 | }; 62 | 63 | } // namespace ndncert::ca 64 | 65 | #endif // NDNCERT_DETAIL_CA_SQLITE_HPP 66 | -------------------------------------------------------------------------------- /src/name-assignment/assignment-param.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "assignment-param.hpp" 22 | 23 | namespace ndncert { 24 | 25 | NDNCERT_REGISTER_NAME_ASSIGNMENT_FUNC(AssignmentParam, "param"); 26 | 27 | AssignmentParam::AssignmentParam(const std::string& format) 28 | : NameAssignmentFunc(format) 29 | { 30 | } 31 | 32 | std::vector 33 | AssignmentParam::assignName(const std::multimap& params) 34 | { 35 | std::vector resultList; 36 | Name result; 37 | for (const auto& item : m_nameFormat) { 38 | if (item.size() >= 2 && item[0] == '"' && item[item.size() - 1] == '"') { 39 | result.append(item.substr(1, item.size() - 2)); 40 | } 41 | else { 42 | auto it = params.find(item); 43 | if (it != params.end() && !it->second.empty()) { 44 | result.append(it->second); 45 | } 46 | else { 47 | return resultList; // empty 48 | } 49 | } 50 | } 51 | resultList.push_back(std::move(result)); 52 | return resultList; 53 | } 54 | 55 | } // namespace ndncert 56 | -------------------------------------------------------------------------------- /src/detail/request-encoder.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_REQUEST_ENCODER_HPP 22 | #define NDNCERT_DETAIL_REQUEST_ENCODER_HPP 23 | 24 | #include "detail/ca-request-state.hpp" 25 | 26 | namespace ndncert::requesttlv { 27 | 28 | Block 29 | encodeApplicationParameters(RequestType requestType, const std::vector& ecdhPub, 30 | const Certificate& certRequest); 31 | 32 | void 33 | decodeApplicationParameters(const Block& block, RequestType requestType, std::vector& ecdhPub, 34 | std::shared_ptr& certRequest); 35 | 36 | Block 37 | encodeDataContent(const std::vector& ecdhKey, const std::array& salt, 38 | const RequestId& requestId, const std::vector& challenges); 39 | 40 | std::list 41 | decodeDataContent(const Block& content, std::vector& ecdhKey, 42 | std::array& salt, RequestId& requestId); 43 | 44 | } // namespace ndncert::requesttlv 45 | 46 | #endif // NDNCERT_DETAIL_REQUEST_ENCODER_HPP 47 | -------------------------------------------------------------------------------- /src/name-assignment/assignment-func.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "assignment-func.hpp" 22 | 23 | namespace ndncert { 24 | 25 | NameAssignmentFunc::NameAssignmentFunc(const std::string& format) 26 | { 27 | size_t index = 0, startIndex = 0; 28 | while ((index = format.find("/", startIndex)) != std::string::npos) { 29 | auto component = format.substr(startIndex, index - startIndex); 30 | if (!component.empty()) { 31 | m_nameFormat.push_back(component); 32 | } 33 | startIndex = index + 1; 34 | } 35 | if (startIndex != format.size()) { 36 | m_nameFormat.push_back(format.substr(startIndex)); 37 | } 38 | } 39 | 40 | std::unique_ptr 41 | NameAssignmentFunc::createNameAssignmentFunc(const std::string& challengeType, const std::string& format) 42 | { 43 | auto& factory = getFactory(); 44 | auto i = factory.find(challengeType); 45 | return i == factory.end() ? nullptr : i->second(format); 46 | } 47 | 48 | NameAssignmentFunc::FuncFactory& 49 | NameAssignmentFunc::getFactory() 50 | { 51 | static FuncFactory factory; 52 | return factory; 53 | } 54 | 55 | } // namespace ndncert 56 | -------------------------------------------------------------------------------- /src/detail/profile-storage.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_PROFILE_STORAGE_HPP 22 | #define NDNCERT_DETAIL_PROFILE_STORAGE_HPP 23 | 24 | #include "detail/ca-profile.hpp" 25 | 26 | namespace ndncert::requester { 27 | 28 | /** 29 | * @brief CA profiles kept by a requester. 30 | * @sa https://github.com/named-data/ndncert/wiki/Client-Configuration-Sample 31 | */ 32 | class ProfileStorage 33 | { 34 | public: 35 | /** 36 | * @throw std::runtime_error when config file cannot be correctly parsed. 37 | */ 38 | void 39 | load(const std::string& fileName); 40 | 41 | /** 42 | * @throw std::runtime_error when config file cannot be correctly parsed. 43 | */ 44 | void 45 | load(const JsonSection& json); 46 | 47 | void 48 | save(const std::string& fileName) const; 49 | 50 | void 51 | removeCaProfile(const Name& caName); 52 | 53 | /** 54 | * @brief Add a new CA profile 55 | * @warning This will add a new trust anchor for requesters. 56 | */ 57 | void 58 | addCaProfile(const CaProfile& profile); 59 | 60 | const std::list& 61 | getKnownProfiles() const; 62 | 63 | private: 64 | std::list m_caProfiles; 65 | }; 66 | 67 | } // namespace ndncert::requester 68 | 69 | #endif // NDNCERT_DETAIL_PROFILE_STORAGE_HPP 70 | -------------------------------------------------------------------------------- /src/redirection/redirection-param.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "redirection-param.hpp" 22 | 23 | #include 24 | #include 25 | 26 | namespace ndncert { 27 | 28 | NDNCERT_REGISTER_REDIRECTION_POLICY(RedirectionParam, "param"); 29 | 30 | RedirectionParam::RedirectionParam(const std::string& format) 31 | { 32 | if (format.empty()) { 33 | return; 34 | } 35 | 36 | std::vector strs; 37 | boost::split(strs, format, boost::is_any_of("&")); 38 | for (const auto& s : strs) { 39 | auto i = s.find('='); 40 | if (i == std::string::npos) { 41 | NDN_THROW(std::runtime_error("Redirection param format: no '=' in format piece")); 42 | } 43 | m_format.emplace(s.substr(0, i), s.substr(i + 1)); 44 | } 45 | } 46 | 47 | bool 48 | RedirectionParam::isRedirecting(const std::multimap& params) 49 | { 50 | for (const auto& p : m_format) { 51 | bool found = false; 52 | for (auto it = params.find(p.first); it != params.end() && it->first == p.first; ++it) { 53 | if (it->second == p.second) { 54 | found = true; 55 | break; 56 | } 57 | } 58 | if (!found) { 59 | return false; 60 | } 61 | } 62 | return true; 63 | } 64 | 65 | } // namespace ndncert 66 | -------------------------------------------------------------------------------- /tests/global-configuration.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "tests/boost-test.hpp" 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace ndncert::tests { 31 | 32 | class GlobalConfiguration 33 | { 34 | public: 35 | GlobalConfiguration() 36 | { 37 | const char* envHome = ::getenv("HOME"); 38 | if (envHome) 39 | m_home.assign(envHome); 40 | 41 | // in case an earlier test run crashed without a chance to run the destructor 42 | std::filesystem::remove_all(TESTDIR); 43 | 44 | auto testHome = TESTDIR / "test-home"; 45 | std::filesystem::create_directories(testHome); 46 | 47 | if (::setenv("HOME", testHome.c_str(), 1) != 0) 48 | NDN_THROW(std::runtime_error("setenv() failed")); 49 | } 50 | 51 | ~GlobalConfiguration() noexcept 52 | { 53 | if (m_home.empty()) 54 | ::unsetenv("HOME"); 55 | else 56 | ::setenv("HOME", m_home.data(), 1); 57 | 58 | std::error_code ec; 59 | std::filesystem::remove_all(TESTDIR, ec); // ignore error 60 | } 61 | 62 | private: 63 | static inline const std::filesystem::path TESTDIR{UNIT_TESTS_TMPDIR}; 64 | std::string m_home; 65 | }; 66 | 67 | BOOST_TEST_GLOBAL_CONFIGURATION(GlobalConfiguration); 68 | 69 | } // namespace ndncert::tests 70 | -------------------------------------------------------------------------------- /ndncert-send-email-challenge.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import argparse 3 | import configparser 4 | import smtplib 5 | from email.message import EmailMessage 6 | 7 | # init arg parser and parse 8 | parser = argparse.ArgumentParser(description='Email challenge sender for NDNCERT CA') 9 | parser.add_argument('recipient', help='email address of the recipient') 10 | parser.add_argument('secret', help='secret code for the challenge') 11 | parser.add_argument('ca_name', help='name of the certificate authority') 12 | parser.add_argument('cert_name', help='name of the certificate being requested') 13 | args = parser.parse_args() 14 | 15 | vars = { 16 | 'ca_name': args.ca_name, 17 | 'cert_name': args.cert_name, 18 | 'recipient': args.recipient, 19 | 'secret': args.secret, 20 | } 21 | 22 | # open config file 23 | cfg = configparser.ConfigParser(empty_lines_in_values=True, 24 | interpolation=configparser.ExtendedInterpolation()) 25 | cfg.read('@SYSCONFDIR@/ndncert/ndncert-mail.conf') 26 | 27 | # read smtp settings 28 | server = cfg.get('ndncert.smtp', 'smtp_server') 29 | port = cfg.get('ndncert.smtp', 'smtp_port') 30 | encrypt_mode = cfg.get('ndncert.smtp', 'encrypt_mode') 31 | username = cfg.get('ndncert.smtp', 'smtp_user', fallback=None) 32 | password = cfg.get('ndncert.smtp', 'smtp_password', fallback=None) 33 | 34 | # read email settings 35 | from_addr = cfg.get('ndncert.email', 'from', vars=vars) 36 | subject = cfg.get('ndncert.email', 'subject', vars=vars) 37 | text = cfg.get('ndncert.email', 'text_template', vars=vars) 38 | html = cfg.get('ndncert.email', 'html_template', vars=vars) 39 | 40 | # create email message 41 | msg = EmailMessage() 42 | msg['From'] = from_addr 43 | msg['To'] = args.recipient 44 | msg['Subject'] = subject 45 | msg.set_content(text) 46 | msg.add_alternative(html, subtype='html') 47 | 48 | # connect to SMTP server 49 | if encrypt_mode == 'ssl': 50 | context = smtplib.SMTP_SSL(server, port, timeout=10) 51 | elif encrypt_mode == 'starttls': 52 | context = smtplib.SMTP(server, port, timeout=10) 53 | context.starttls() 54 | elif encrypt_mode == 'none': 55 | context = smtplib.SMTP(server, port, timeout=10) 56 | else: 57 | raise ValueError(f'Invalid encrypt_mode: {encrypt_mode}') 58 | 59 | with context as smtp: 60 | if username and password: 61 | smtp.login(username, password) 62 | # send email 63 | smtp.send_message(msg) 64 | -------------------------------------------------------------------------------- /src/name-assignment/assignment-email.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "assignment-email.hpp" 22 | 23 | namespace ndncert { 24 | 25 | NDNCERT_REGISTER_NAME_ASSIGNMENT_FUNC(AssignmentEmail, "email"); 26 | 27 | AssignmentEmail::AssignmentEmail(const std::string& format) 28 | : NameAssignmentFunc(format) 29 | { 30 | } 31 | 32 | std::vector 33 | AssignmentEmail::assignName(const std::multimap& params) 34 | { 35 | std::vector resultList; 36 | Name result; 37 | if (!m_nameFormat.empty() && params.count("email") > 0) { 38 | const std::string& email = params.begin()->second; 39 | auto formatIter = m_nameFormat.begin(); 40 | size_t emailSplit = email.rfind("@"); 41 | std::string domain = "." + email.substr(emailSplit + 1); 42 | 43 | if (emailSplit != std::string::npos && emailSplit > 0) { 44 | size_t domainSplit = domain.rfind("."); 45 | while (domainSplit != std::string::npos) { 46 | if (formatIter != m_nameFormat.end() && domain.substr(domainSplit + 1) == *formatIter) { 47 | formatIter++; 48 | } 49 | else { 50 | result.append(domain.substr(domainSplit + 1).data()); 51 | } 52 | domain = domain.substr(0, domainSplit); 53 | domainSplit = domain.rfind("."); 54 | } 55 | result.append(email.substr(0, emailSplit).data()); 56 | resultList.push_back(std::move(result)); 57 | } 58 | } 59 | return resultList; 60 | } 61 | 62 | } // namespace ndncert 63 | -------------------------------------------------------------------------------- /src/detail/ca-configuration.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_CA_CONFIGURATION_HPP 22 | #define NDNCERT_DETAIL_CA_CONFIGURATION_HPP 23 | 24 | #include "ca-profile.hpp" 25 | #include "name-assignment/assignment-func.hpp" 26 | #include "redirection/redirection-policy.hpp" 27 | 28 | namespace ndncert::ca { 29 | 30 | /** 31 | * @brief CA's configuration on NDNCERT. 32 | * 33 | * The format of CA configuration in JSON 34 | * { 35 | * "ca-prefix": "", 36 | * "ca-info": "", 37 | * "max-validity-period": "", 38 | * "max-suffix-length": "", 39 | * "probe-parameters": 40 | * [ 41 | * {"probe-parameter-key": ""}, 42 | * {"probe-parameter-key": ""} 43 | * ] 44 | * "supported-challenges": 45 | * [ 46 | * {"challenge": ""}, 47 | * {"challenge": ""} 48 | * ] 49 | * } 50 | */ 51 | class CaConfig 52 | { 53 | public: 54 | /** 55 | * @brief Load CA configuration from the file. 56 | * @throw std::runtime_error when config file cannot be correctly parsed. 57 | */ 58 | void 59 | load(const std::string& fileName); 60 | 61 | public: 62 | /** 63 | * @brief the CA's profile 64 | */ 65 | CaProfile caProfile; 66 | /** 67 | * @brief Used for CA redirection 68 | */ 69 | std::vector, std::unique_ptr>> redirection; 70 | /** 71 | * @brief Name Assignment Functions 72 | */ 73 | std::vector> nameAssignmentFuncs; 74 | }; 75 | 76 | } // namespace ndncert::ca 77 | 78 | #endif // NDNCERT_DETAIL_CA_CONFIGURATION_HPP 79 | -------------------------------------------------------------------------------- /src/detail/ndncert-common.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "detail/ndncert-common.hpp" 22 | 23 | #include 24 | 25 | namespace ndncert { 26 | 27 | std::ostream& 28 | operator<<(std::ostream& out, ErrorCode code) 29 | { 30 | switch (code) { 31 | case ErrorCode::NO_ERROR: return out << "NO_ERROR"; 32 | case ErrorCode::BAD_INTEREST_FORMAT: return out << "BAD_INTEREST_FORMAT"; 33 | case ErrorCode::BAD_PARAMETER_FORMAT: return out << "BAD_PARAMETER_FORMAT"; 34 | case ErrorCode::BAD_SIGNATURE: return out << "BAD_SIGNATURE"; 35 | case ErrorCode::INVALID_PARAMETER: return out << "INVALID_PARAMETER"; 36 | case ErrorCode::NAME_NOT_ALLOWED: return out << "NAME_NOT_ALLOWED"; 37 | case ErrorCode::BAD_VALIDITY_PERIOD: return out << "BAD_VALIDITY_PERIOD"; 38 | case ErrorCode::OUT_OF_TRIES: return out << "OUT_OF_TRIES"; 39 | case ErrorCode::OUT_OF_TIME: return out << "OUT_OF_TIME"; 40 | case ErrorCode::NO_AVAILABLE_NAMES: return out << "NO_AVAILABLE_NAMES"; 41 | } 42 | return out << ""; 43 | } 44 | 45 | std::ostream& 46 | operator<<(std::ostream& out, RequestType type) 47 | { 48 | switch (type) { 49 | case RequestType::NOTINITIALIZED: return out << "Not Initialized"; 50 | case RequestType::NEW: return out << "New"; 51 | case RequestType::RENEW: return out << "Renew"; 52 | case RequestType::REVOKE: return out << "Revoke"; 53 | } 54 | return out << ""; 55 | } 56 | 57 | } // namespace ndncert 58 | -------------------------------------------------------------------------------- /src/detail/ca-memory.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "detail/ca-memory.hpp" 22 | 23 | namespace ndncert::ca { 24 | 25 | const std::string CaMemory::STORAGE_TYPE = "ca-storage-memory"; 26 | NDNCERT_REGISTER_CA_STORAGE(CaMemory); 27 | 28 | CaMemory::CaMemory(const Name&, const std::string&) 29 | : CaStorage() 30 | { 31 | } 32 | 33 | RequestState 34 | CaMemory::getRequest(const RequestId& requestId) 35 | { 36 | auto it = m_requests.find(requestId); 37 | if (it == m_requests.end()) { 38 | NDN_THROW(std::runtime_error("Request " + ndn::toHex(requestId) + " does not exist")); 39 | } 40 | return it->second; 41 | } 42 | 43 | void 44 | CaMemory::addRequest(const RequestState& request) 45 | { 46 | auto result = m_requests.insert({request.requestId, request}); 47 | if (!result.second) { 48 | NDN_THROW(std::runtime_error("Request " + ndn::toHex(request.requestId) + " already exists")); 49 | } 50 | } 51 | 52 | void 53 | CaMemory::updateRequest(const RequestState& request) 54 | { 55 | m_requests.insert_or_assign(request.requestId, request); 56 | } 57 | 58 | void 59 | CaMemory::deleteRequest(const RequestId& requestId) 60 | { 61 | m_requests.erase(requestId); 62 | } 63 | 64 | std::list 65 | CaMemory::listAllRequests() 66 | { 67 | std::list result; 68 | for (const auto& entry : m_requests) { 69 | result.push_back(entry.second); 70 | } 71 | return result; 72 | } 73 | 74 | std::list 75 | CaMemory::listAllRequests(const Name& caName) 76 | { 77 | std::list result; 78 | for (const auto& entry : m_requests) { 79 | if (entry.second.caPrefix == caName) { 80 | result.push_back(entry.second); 81 | } 82 | } 83 | return result; 84 | } 85 | 86 | } // namespace ndncert::ca 87 | -------------------------------------------------------------------------------- /tools/ndncert-ca-status.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "ca-module.hpp" 22 | #include "detail/ca-sqlite.hpp" 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | namespace ndncert::ca { 31 | 32 | static int 33 | main(int argc, char* argv[]) 34 | { 35 | namespace po = boost::program_options; 36 | std::string caNameString = ""; 37 | po::options_description description( 38 | "Usage: ndncert-ca-status [-h] caName\n" 39 | "\n" 40 | "Options"); 41 | description.add_options() 42 | ("help,h", "produce help message") 43 | ("caName", po::value(&caNameString), "CA Identity Name, e.g., /example"); 44 | po::positional_options_description p; 45 | p.add("caName", 1); 46 | po::variables_map vm; 47 | try { 48 | po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm); 49 | po::notify(vm); 50 | } 51 | catch (const std::exception& e) { 52 | std::cerr << "ERROR: " << e.what() << std::endl; 53 | return 1; 54 | } 55 | if (vm.count("help") != 0) { 56 | std::cerr << description << std::endl; 57 | return 0; 58 | } 59 | if (vm.count("caName") == 0) { 60 | std::cerr << "ERROR: you must specify a CA identity." << std::endl; 61 | return 2; 62 | } 63 | 64 | CaSqlite storage(Name(caNameString), ""); 65 | std::list requestList; 66 | requestList = storage.listAllRequests(); 67 | std::cerr << "The pending requests are :" << std::endl; 68 | for (const auto& entry : requestList) { 69 | std::cerr << "***************************************\n" 70 | << entry 71 | << "***************************************\n"; 72 | } 73 | return 0; 74 | } 75 | 76 | } // namespace ndncert::ca 77 | 78 | int 79 | main(int argc, char* argv[]) 80 | { 81 | return ndncert::ca::main(argc, argv); 82 | } 83 | -------------------------------------------------------------------------------- /tests/clock-fixture.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2013-2022 Regents of the University of California. 4 | * 5 | * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). 6 | * 7 | * ndn-cxx library is free software: you can redistribute it and/or modify it under the 8 | * terms of the GNU Lesser General Public License as published by the Free Software 9 | * Foundation, either version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License and GNU Lesser 16 | * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see 17 | * . 18 | * 19 | * See AUTHORS.md for complete list of ndn-cxx authors and contributors. 20 | */ 21 | 22 | #ifndef NDNCERT_TESTS_CLOCK_FIXTURE_HPP 23 | #define NDNCERT_TESTS_CLOCK_FIXTURE_HPP 24 | 25 | #include 26 | 27 | namespace ndncert::tests { 28 | 29 | namespace time = ndn::time; 30 | 31 | /** \brief A test fixture that overrides steady clock and system clock. 32 | */ 33 | class ClockFixture 34 | { 35 | public: 36 | virtual 37 | ~ClockFixture(); 38 | 39 | /** \brief Advance steady and system clocks. 40 | * 41 | * Clocks are advanced in increments of \p tick for \p nTicks ticks. 42 | * afterTick() is called after each tick. 43 | * 44 | * Exceptions thrown during I/O events are propagated to the caller. 45 | * Clock advancement will stop in the event of an exception. 46 | */ 47 | void 48 | advanceClocks(time::nanoseconds tick, size_t nTicks = 1) 49 | { 50 | advanceClocks(tick, tick * nTicks); 51 | } 52 | 53 | /** \brief Advance steady and system clocks. 54 | * 55 | * Clocks are advanced in increments of \p tick for \p total time. 56 | * The last increment might be shorter than \p tick. 57 | * afterTick() is called after each tick. 58 | * 59 | * Exceptions thrown during I/O events are propagated to the caller. 60 | * Clock advancement will stop in the event of an exception. 61 | */ 62 | void 63 | advanceClocks(time::nanoseconds tick, time::nanoseconds total); 64 | 65 | protected: 66 | ClockFixture(); 67 | 68 | private: 69 | /** \brief Called by advanceClocks() after each clock advancement (tick). 70 | * 71 | * The base class implementation is a no-op. 72 | */ 73 | virtual void 74 | afterTick() 75 | { 76 | } 77 | 78 | protected: 79 | std::shared_ptr m_steadyClock; 80 | std::shared_ptr m_systemClock; 81 | }; 82 | 83 | } // namespace ndncert::tests 84 | 85 | #endif // NDNCERT_TESTS_CLOCK_FIXTURE_HPP 86 | -------------------------------------------------------------------------------- /src/challenge/challenge-pin.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_CHALLENGE_PIN_HPP 22 | #define NDNCERT_CHALLENGE_PIN_HPP 23 | 24 | #include "challenge-module.hpp" 25 | 26 | namespace ndncert { 27 | 28 | /** 29 | * @brief Provide PIN code based challenge. 30 | * 31 | * The main process of this challenge module is: 32 | * 1. End entity provides empty string. The first POLL is only for selection. 33 | * 2. The challenge module will generate a PIN code in ChallengeDefinedField. 34 | * 3. End entity provides the verification code from some way to challenge module. 35 | * 36 | * There are four specific status defined in this challenge: 37 | * NEED_CODE: When selection is made. 38 | * WRONG_CODE: Get wrong verification code but still with secret lifetime and max retry times. 39 | * 40 | * Failure info when application fails: 41 | * FAILURE_TIMEOUT: When secret is out-dated. 42 | * FAILURE_MAXRETRY: When requester tries too many times. 43 | * 44 | * @sa https://github.com/named-data/ndncert/wiki/NDNCERT-Protocol-0.3-Challenges 45 | */ 46 | class ChallengePin : public ChallengeModule 47 | { 48 | public: 49 | ChallengePin(const size_t& maxAttemptTimes = 3, 50 | const time::seconds& secretLifetime = time::seconds(3600)); 51 | 52 | // For CA 53 | std::tuple 54 | handleChallengeRequest(const Block& params, ca::RequestState& request) override; 55 | 56 | // For Client 57 | std::multimap 58 | getRequestedParameterList(Status status, const std::string& challengeStatus) override; 59 | 60 | Block 61 | genChallengeRequestTLV(Status status, const std::string& challengeStatus, 62 | const std::multimap& params) override; 63 | 64 | // challenge status 65 | static const std::string NEED_CODE; 66 | static const std::string WRONG_CODE; 67 | // parameters 68 | static const std::string PARAMETER_KEY_CODE; 69 | }; 70 | 71 | } // namespace ndncert 72 | 73 | #endif // NDNCERT_CHALLENGE_PIN_HPP 74 | -------------------------------------------------------------------------------- /tests/unit-tests/redirection-policy.t.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "redirection/redirection-policy.hpp" 22 | #include "redirection/redirection-param.hpp" 23 | #include "redirection/redirection-email.hpp" 24 | 25 | #include "tests/boost-test.hpp" 26 | 27 | namespace ndncert::tests { 28 | 29 | BOOST_AUTO_TEST_SUITE(TestRedirectionPolicy) 30 | 31 | BOOST_AUTO_TEST_CASE(RedirectionPolicyParam) 32 | { 33 | RedirectionParam assignment(""); 34 | std::multimap params; 35 | BOOST_CHECK(assignment.isRedirecting(params)); 36 | params.emplace("abc", "123"); 37 | BOOST_CHECK(assignment.isRedirecting(params)); 38 | 39 | RedirectionParam assignment1("abc=123"); 40 | params.clear(); 41 | BOOST_CHECK(!assignment1.isRedirecting(params)); 42 | params.emplace("abc", "124"); 43 | BOOST_CHECK(!assignment1.isRedirecting(params)); 44 | params.emplace("abc", "123"); 45 | BOOST_CHECK(assignment1.isRedirecting(params)); 46 | 47 | RedirectionParam assignment2("abc=123&xyz=789"); 48 | params.clear(); 49 | BOOST_CHECK(!assignment2.isRedirecting(params)); 50 | params.emplace("abc", "123"); 51 | BOOST_CHECK(!assignment2.isRedirecting(params)); 52 | params.emplace("xyz", "788"); 53 | BOOST_CHECK(!assignment2.isRedirecting(params)); 54 | params.emplace("xyz", "789"); 55 | BOOST_CHECK(assignment2.isRedirecting(params)); 56 | params.emplace("abz", "789"); 57 | BOOST_CHECK(assignment2.isRedirecting(params)); 58 | } 59 | 60 | BOOST_AUTO_TEST_CASE(RedirectionPolicyEmail) 61 | { 62 | RedirectionEmail assignment("cs.ucla.edu"); 63 | std::multimap params; 64 | BOOST_CHECK(!assignment.isRedirecting(params)); 65 | params.emplace("email", "das@math.ucla.edu"); 66 | BOOST_CHECK(!assignment.isRedirecting(params)); 67 | 68 | params.clear(); 69 | params.emplace("email", "das@cs.ucla.edu"); 70 | BOOST_CHECK(assignment.isRedirecting(params)); 71 | 72 | params.clear(); 73 | params.emplace("email", "das@ucla.edu"); 74 | BOOST_CHECK(!assignment.isRedirecting(params)); 75 | } 76 | 77 | BOOST_AUTO_TEST_SUITE_END() // TestNameAssignment 78 | 79 | } // namespace ndncert::tests 80 | -------------------------------------------------------------------------------- /src/detail/info-encoder.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "detail/info-encoder.hpp" 22 | 23 | namespace ndncert::infotlv { 24 | 25 | Block 26 | encodeDataContent(const CaProfile& caConfig, const Certificate& certificate) 27 | { 28 | Block content(ndn::tlv::Content); 29 | content.push_back(makeNestedBlock(tlv::CaPrefix, caConfig.caPrefix)); 30 | std::string caInfo; 31 | if (caConfig.caInfo.empty()) { 32 | caInfo = "Issued by " + certificate.getSignatureInfo().getKeyLocator().getName().toUri(); 33 | } 34 | else { 35 | caInfo = caConfig.caInfo; 36 | } 37 | content.push_back(ndn::makeStringBlock(tlv::CaInfo, caInfo)); 38 | for (const auto& key : caConfig.probeParameterKeys) { 39 | content.push_back(ndn::makeStringBlock(tlv::ParameterKey, key)); 40 | } 41 | content.push_back(ndn::makeNonNegativeIntegerBlock(tlv::MaxValidityPeriod, caConfig.maxValidityPeriod.count())); 42 | content.push_back(makeNestedBlock(tlv::CaCertificate, certificate)); 43 | content.encode(); 44 | return content; 45 | } 46 | 47 | CaProfile 48 | decodeDataContent(const Block& block) 49 | { 50 | CaProfile result; 51 | block.parse(); 52 | for (auto const &item : block.elements()) { 53 | switch (item.type()) { 54 | case tlv::CaPrefix: 55 | item.parse(); 56 | result.caPrefix.wireDecode(item.get(ndn::tlv::Name)); 57 | break; 58 | case tlv::CaInfo: 59 | result.caInfo = readString(item); 60 | break; 61 | case tlv::ParameterKey: 62 | result.probeParameterKeys.push_back(readString(item)); 63 | break; 64 | case tlv::MaxValidityPeriod: 65 | result.maxValidityPeriod = time::seconds(readNonNegativeInteger(item)); 66 | break; 67 | case tlv::CaCertificate: 68 | item.parse(); 69 | result.cert = std::make_shared(item.get(ndn::tlv::Data)); 70 | break; 71 | default: 72 | if (ndn::tlv::isCriticalType(item.type())) { 73 | NDN_THROW(std::runtime_error("Unrecognized TLV Type: " + std::to_string(item.type()))); 74 | } 75 | break; 76 | } 77 | } 78 | return result; 79 | } 80 | 81 | } // namespace ndncert::infotlv 82 | -------------------------------------------------------------------------------- /src/detail/profile-storage.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "detail/profile-storage.hpp" 22 | 23 | #include 24 | 25 | namespace ndncert::requester { 26 | 27 | void 28 | ProfileStorage::load(const std::string& fileName) 29 | { 30 | JsonSection configJson; 31 | try { 32 | boost::property_tree::read_json(fileName, configJson); 33 | } 34 | catch (const std::exception& error) { 35 | NDN_THROW(std::runtime_error("Failed to parse configuration file " + fileName + ", " + error.what())); 36 | } 37 | if (configJson.begin() == configJson.end()) { 38 | NDN_THROW(std::runtime_error("No JSON configuration found in file: " + fileName)); 39 | } 40 | load(configJson); 41 | } 42 | 43 | void 44 | ProfileStorage::load(const JsonSection& json) 45 | { 46 | m_caProfiles.clear(); 47 | auto caList = json.get_child("ca-list"); 48 | for (const auto& item : caList) { 49 | auto profile = CaProfile::fromJson(item.second); 50 | if (profile.cert == nullptr) { 51 | NDN_THROW(std::runtime_error("No CA certificate is loaded from JSON configuration.")); 52 | } 53 | m_caProfiles.push_back(std::move(profile)); 54 | } 55 | } 56 | 57 | void 58 | ProfileStorage::save(const std::string& fileName) const 59 | { 60 | JsonSection configJson; 61 | for (const auto& caItem : m_caProfiles) { 62 | configJson.push_back({"", caItem.toJson()}); 63 | } 64 | std::stringstream ss; 65 | boost::property_tree::write_json(ss, configJson); 66 | std::ofstream configFile(fileName); 67 | configFile << ss.str(); 68 | } 69 | 70 | void 71 | ProfileStorage::removeCaProfile(const Name& caName) 72 | { 73 | m_caProfiles.remove_if([&](const CaProfile& item) { return item.caPrefix == caName; }); 74 | } 75 | 76 | void 77 | ProfileStorage::addCaProfile(const CaProfile& profile) 78 | { 79 | for (auto& item : m_caProfiles) { 80 | if (item.caPrefix == profile.caPrefix) { 81 | item = profile; 82 | return; 83 | } 84 | } 85 | m_caProfiles.push_back(profile); 86 | } 87 | 88 | const std::list& 89 | ProfileStorage::getKnownProfiles() const 90 | { 91 | return m_caProfiles; 92 | } 93 | 94 | } // namespace ndncert::requester 95 | -------------------------------------------------------------------------------- /src/detail/error-encoder.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "detail/error-encoder.hpp" 22 | 23 | #include 24 | 25 | namespace ndncert::errortlv { 26 | 27 | NDN_LOG_INIT(ndncert.encode.error); 28 | 29 | Block 30 | encodeDataContent(ErrorCode errorCode, std::string_view description) 31 | { 32 | Block response(ndn::tlv::Content); 33 | response.push_back(ndn::makeNonNegativeIntegerBlock(tlv::ErrorCode, static_cast(errorCode))); 34 | response.push_back(ndn::makeStringBlock(tlv::ErrorInfo, description)); 35 | response.encode(); 36 | return response; 37 | } 38 | 39 | std::tuple 40 | decodefromDataContent(const Block& block) 41 | { 42 | try { 43 | block.parse(); 44 | 45 | int codeCount = 0; 46 | int infoCount = 0; 47 | int otherCriticalCount = 0; 48 | ErrorCode error = ErrorCode::NO_ERROR; 49 | std::string errorInfo; 50 | for (const auto& item : block.elements()) { 51 | if (item.type() == tlv::ErrorCode) { 52 | error = ndn::readNonNegativeIntegerAs(block.get(tlv::ErrorCode)); 53 | codeCount++; 54 | } 55 | else if (item.type() == tlv::ErrorInfo) { 56 | errorInfo = readString(block.get(tlv::ErrorInfo)); 57 | infoCount++; 58 | } 59 | else if (ndn::tlv::isCriticalType(item.type())) { 60 | otherCriticalCount++; 61 | } 62 | else { 63 | // ignore 64 | } 65 | } 66 | 67 | if (codeCount == 0 && infoCount == 0) { 68 | return {ErrorCode::NO_ERROR, ""}; 69 | } 70 | if (codeCount != 1 || infoCount != 1) { 71 | NDN_THROW(std::runtime_error("Error TLV contains " + std::to_string(codeCount) + 72 | " error code(s) and " + std::to_string(infoCount) + 73 | " error info(s), instead of expected 1 time each.")); 74 | } 75 | if (otherCriticalCount > 0) { 76 | NDN_THROW(std::runtime_error("Unknown critical TLV type in error packet")); 77 | } 78 | return {error, errorInfo}; 79 | } 80 | catch (const std::exception& e) { 81 | NDN_LOG_ERROR("Exception in error message decoding: " << e.what()); 82 | return {ErrorCode::NO_ERROR, ""}; 83 | } 84 | } 85 | 86 | } // namespace ndncert::errortlv 87 | -------------------------------------------------------------------------------- /src/redirection/redirection-policy.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_REDIRECTION_POLICY_HPP 22 | #define NDNCERT_REDIRECTION_POLICY_HPP 23 | 24 | #include "detail/ndncert-common.hpp" 25 | 26 | #include 27 | 28 | namespace ndncert { 29 | 30 | class RedirectionPolicy : boost::noncopyable 31 | { 32 | public: 33 | virtual 34 | ~RedirectionPolicy() = default; 35 | 36 | /** 37 | * @brief The Redirection Policy provided by the CA operator to decide if redirection is suitable. 38 | * @param params A list of parameter key-value pairs from the probe. 39 | * @return true if the provided @p params conform to the configured redirection policy. 40 | */ 41 | virtual bool 42 | isRedirecting(const std::multimap& params) = 0; 43 | 44 | public: // factory 45 | template 46 | static void 47 | registerRedirectionPolicy(const std::string& type) 48 | { 49 | PolicyFactory& factory = getFactory(); 50 | BOOST_ASSERT(factory.count(type) == 0); 51 | factory[type] = [] (const std::string& format) { return std::make_unique(format); }; 52 | } 53 | 54 | static std::unique_ptr 55 | createPolicyFunc(const std::string& policyType, const std::string& format = ""); 56 | 57 | private: 58 | using CreateFunc = std::function(const std::string &)>; 59 | using PolicyFactory = std::map; 60 | 61 | static PolicyFactory& 62 | getFactory(); 63 | }; 64 | 65 | } // namespace ndncert 66 | 67 | #define NDNCERT_REGISTER_REDIRECTION_POLICY(C, T) \ 68 | static class NdnCert##C##RedirectionPolicyRegistrationClass \ 69 | { \ 70 | public: \ 71 | NdnCert##C##RedirectionPolicyRegistrationClass() \ 72 | { \ 73 | ::ndncert::RedirectionPolicy::registerRedirectionPolicy(T); \ 74 | } \ 75 | } g_NdnCert##C##RedirectionPolicyRegistrationVariable 76 | 77 | #endif // NDNCERT_REDIRECTION_POLICY_HPP 78 | -------------------------------------------------------------------------------- /src/challenge/challenge-email.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_CHALLENGE_EMAIL_HPP 22 | #define NDNCERT_CHALLENGE_EMAIL_HPP 23 | 24 | #include "challenge-module.hpp" 25 | 26 | namespace ndncert { 27 | 28 | /** 29 | * @brief Provide email-based challenge. 30 | * 31 | * The main process of this challenge module is: 32 | * 1. Requester provides its email address. 33 | * 2. The challenge module will send a verification code to this email address. 34 | * 3. Requester provides the verification code to challenge module. 35 | * 36 | * There are several challenge status in EMAIL challenge: 37 | * NEED_CODE: When email address is provided and the verification code has been sent out. 38 | * WRONG_CODE: Wrong code but still within secret lifetime and within max try times. 39 | * 40 | * Failure info when application fails: 41 | * FAILURE_MAXRETRY: When run out retry times. 42 | * FAILURE_TIMEOUT: When the secret lifetime expires. 43 | * 44 | * @sa https://github.com/named-data/ndncert/wiki/NDNCERT-Protocol-0.3-Challenges 45 | */ 46 | class ChallengeEmail : public ChallengeModule 47 | { 48 | public: 49 | ChallengeEmail(const std::string& scriptPath = "ndncert-send-email-challenge", 50 | const size_t& maxAttemptTimes = 3, 51 | const time::seconds secretLifetime = time::seconds(300)); 52 | 53 | // For CA 54 | std::tuple 55 | handleChallengeRequest(const Block& params, ca::RequestState& request) override; 56 | 57 | // For Client 58 | std::multimap 59 | getRequestedParameterList(Status status, const std::string& challengeStatus) override; 60 | 61 | Block 62 | genChallengeRequestTLV(Status status, const std::string& challengeStatus, 63 | const std::multimap& params) override; 64 | 65 | // challenge status 66 | static const std::string NEED_CODE; 67 | static const std::string WRONG_CODE; 68 | // challenge parameters 69 | static const std::string PARAMETER_KEY_EMAIL; 70 | static const std::string PARAMETER_KEY_CODE; 71 | 72 | NDNCERT_PUBLIC_WITH_TESTS_ELSE_PRIVATE: 73 | static bool 74 | isValidEmailAddress(const std::string& emailAddress); 75 | 76 | void 77 | sendEmail(const std::string& emailAddress, const std::string& secret, 78 | const ca::RequestState& request) const; 79 | 80 | private: 81 | std::string m_sendEmailScript; 82 | }; 83 | 84 | } // namespace ndncert 85 | 86 | #endif // NDNCERT_CHALLENGE_EMAIL_HPP 87 | -------------------------------------------------------------------------------- /src/detail/ca-storage.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_CA_STORAGE_HPP 22 | #define NDNCERT_DETAIL_CA_STORAGE_HPP 23 | 24 | #include "detail/ca-request-state.hpp" 25 | 26 | #include 27 | 28 | namespace ndncert::ca { 29 | 30 | class CaStorage : boost::noncopyable 31 | { 32 | public: 33 | virtual 34 | ~CaStorage() = default; 35 | 36 | /** 37 | * @throw std::runtime_error The request cannot be fetched from underlying data storage 38 | */ 39 | virtual RequestState 40 | getRequest(const RequestId& requestId) = 0; 41 | 42 | /** 43 | * @throw std::runtime_error There is an existing request with the same request ID 44 | */ 45 | virtual void 46 | addRequest(const RequestState& request) = 0; 47 | 48 | virtual void 49 | updateRequest(const RequestState& request) = 0; 50 | 51 | virtual void 52 | deleteRequest(const RequestId& requestId) = 0; 53 | 54 | virtual std::list 55 | listAllRequests() = 0; 56 | 57 | virtual std::list 58 | listAllRequests(const Name& caName) = 0; 59 | 60 | public: // factory 61 | template 62 | static void 63 | registerCaStorage(const std::string& type = CaStorageType::STORAGE_TYPE) 64 | { 65 | auto& factory = getFactory(); 66 | BOOST_ASSERT(factory.count(type) == 0); 67 | factory[type] = [] (const Name& caName, const std::string& path) { 68 | return std::make_unique(caName, path); 69 | }; 70 | } 71 | 72 | static std::unique_ptr 73 | createCaStorage(const std::string& caStorageType, const Name& caName, const std::string& path); 74 | 75 | private: 76 | using CreateFunc = std::function(const Name&, const std::string&)>; 77 | using CaStorageFactory = std::map; 78 | 79 | static CaStorageFactory& 80 | getFactory(); 81 | }; 82 | 83 | } // namespace ndncert::ca 84 | 85 | #define NDNCERT_REGISTER_CA_STORAGE(C) \ 86 | static class NdnCert##C##CaStorageRegistrationClass \ 87 | { \ 88 | public: \ 89 | NdnCert##C##CaStorageRegistrationClass() \ 90 | { \ 91 | ::ndncert::ca::CaStorage::registerCaStorage(); \ 92 | } \ 93 | } g_NdnCert##C##CaStorageRegistrationVariable 94 | 95 | #endif // NDNCERT_DETAIL_CA_STORAGE_HPP 96 | -------------------------------------------------------------------------------- /src/detail/ca-request-state.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2023, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "detail/ca-request-state.hpp" 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace ndncert { 28 | 29 | std::string statusToString(Status status) 30 | { 31 | switch (status) { 32 | case Status::BEFORE_CHALLENGE: 33 | return "Before challenge"; 34 | case Status::CHALLENGE: 35 | return "In challenge"; 36 | case Status::PENDING: 37 | return "Pending after challenge"; 38 | case Status::SUCCESS: 39 | return "Success"; 40 | case Status::FAILURE: 41 | return "Failure"; 42 | default: 43 | return "Unrecognized status"; 44 | } 45 | } 46 | 47 | Status 48 | statusFromBlock(const Block& block) 49 | { 50 | auto status_int = readNonNegativeInteger(block); 51 | if (status_int > 6) 52 | NDN_THROW(std::runtime_error("Unrecognized Status")); 53 | return static_cast(status_int); 54 | } 55 | 56 | namespace ca { 57 | 58 | ChallengeState::ChallengeState(const std::string& challengeStatus, 59 | const time::system_clock::time_point& challengeTp, 60 | size_t remainingTries, time::seconds remainingTime, 61 | JsonSection&& challengeSecrets) 62 | : challengeStatus(challengeStatus) 63 | , timestamp(challengeTp) 64 | , remainingTries(remainingTries) 65 | , remainingTime(remainingTime) 66 | , secrets(std::move(challengeSecrets)) 67 | { 68 | } 69 | 70 | std::ostream& 71 | operator<<(std::ostream& os, const RequestState& request) 72 | { 73 | os << "Request's CA name: " << request.caPrefix << "\n"; 74 | os << "Request's request ID: " << ndn::toHex(request.requestId) << "\n"; 75 | os << "Request's status: " << statusToString(request.status) << "\n"; 76 | os << "Request's challenge type: " << request.challengeType << "\n"; 77 | if (request.challengeState) { 78 | os << "Challenge Status: " << request.challengeState->challengeStatus << "\n"; 79 | os << "Challenge remaining tries:" << request.challengeState->remainingTries << " times\n"; 80 | os << "Challenge remaining time: " << request.challengeState->remainingTime.count() << " seconds\n"; 81 | os << "Challenge last update: " << time::toIsoString(request.challengeState->timestamp) << "\n"; 82 | std::stringstream ss; 83 | boost::property_tree::write_json(ss, request.challengeState->secrets); 84 | os << "Challenge secret: " << ss.str() << "\n"; 85 | } 86 | os << "Certificate:\n"; 87 | ndn::util::IndentedStream os2(os, " "); 88 | os2 << request.cert; 89 | return os; 90 | } 91 | 92 | } // namespace ca 93 | } // namespace ndncert 94 | -------------------------------------------------------------------------------- /src/ca-module.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_CA_MODULE_HPP 22 | #define NDNCERT_CA_MODULE_HPP 23 | 24 | #include "detail/ca-configuration.hpp" 25 | #include "detail/ca-storage.hpp" 26 | 27 | #include 28 | #include 29 | 30 | namespace ndncert::ca { 31 | 32 | /** 33 | * @brief The function would be invoked whenever the certificate request status is updated. 34 | * The callback is used to notice the CA application or CA command line tool. The callback is 35 | * fired whenever a request instance is created, challenge status is updated, and when certificate 36 | * is issued. 37 | * 38 | * @param RequestState The state of the certificate request whose status is updated. 39 | */ 40 | using StatusUpdateCallback = std::function; 41 | 42 | class CaModule : boost::noncopyable 43 | { 44 | public: 45 | CaModule(ndn::Face& face, ndn::KeyChain& keyChain, const std::string& configPath, 46 | const std::string& storageType = "ca-storage-sqlite3"); 47 | 48 | CaConfig& 49 | getCaConf() 50 | { 51 | return m_config; 52 | } 53 | 54 | const std::unique_ptr& 55 | getCaStorage() const 56 | { 57 | return m_storage; 58 | } 59 | 60 | void 61 | setStatusUpdateCallback(StatusUpdateCallback cb) 62 | { 63 | m_statusUpdateCallback = std::move(cb); 64 | } 65 | 66 | const Data& 67 | getCaProfileData(); 68 | 69 | NDNCERT_PUBLIC_WITH_TESTS_ELSE_PRIVATE: 70 | void 71 | registerPrefix(); 72 | 73 | void 74 | onCaProfileDiscovery(const Interest& request); 75 | 76 | void 77 | onProbe(const Interest& request); 78 | 79 | void 80 | onNewRenewRevoke(const Interest& request, RequestType requestType); 81 | 82 | void 83 | onChallenge(const Interest& request); 84 | 85 | std::unique_ptr 86 | getCertificateRequest(const Interest& request); 87 | 88 | Certificate 89 | issueCertificate(const RequestState& requestState); 90 | 91 | Data 92 | makeErrorPacket(const Name& name, ErrorCode errorCode, std::string_view errorInfo); 93 | 94 | NDNCERT_PUBLIC_WITH_TESTS_ELSE_PRIVATE: 95 | ndn::Face& m_face; 96 | ndn::KeyChain& m_keyChain; 97 | CaConfig m_config; 98 | std::unique_ptr m_storage; 99 | 100 | uint8_t m_requestIdGenKey[32]; 101 | std::unique_ptr m_profileData; 102 | StatusUpdateCallback m_statusUpdateCallback; 103 | 104 | std::vector m_registeredPrefixes; 105 | std::vector m_interestFilters; 106 | }; 107 | 108 | } // namespace ndncert::ca 109 | 110 | #endif // NDNCERT_CA_MODULE_HPP 111 | -------------------------------------------------------------------------------- /src/name-assignment/assignment-func.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_ASSIGNMENT_FUNC_HPP 22 | #define NDNCERT_ASSIGNMENT_FUNC_HPP 23 | 24 | #include "detail/ca-request-state.hpp" 25 | 26 | #include 27 | 28 | namespace ndncert { 29 | 30 | class NameAssignmentFunc : boost::noncopyable 31 | { 32 | protected: 33 | explicit 34 | NameAssignmentFunc(const std::string& format = ""); 35 | 36 | public: 37 | virtual 38 | ~NameAssignmentFunc() = default; 39 | 40 | /** 41 | * @brief The name assignment function provided by the CA operator to generate available 42 | * namecomponents. 43 | * 44 | * The function does not guarantee that all the returned names are available. Therefore the 45 | * CA should further check the availability of each returned name and remove unavailable results. 46 | * 47 | * @param vector A list of parameter key-value pair used for name assignment. 48 | * @return a vector containing the possible namespaces derived from the parameters. 49 | */ 50 | virtual std::vector 51 | assignName(const std::multimap& params) = 0; 52 | 53 | public: // factory 54 | template 55 | static void 56 | registerNameAssignmentFunc(const std::string& type) 57 | { 58 | auto& factory = getFactory(); 59 | BOOST_ASSERT(factory.count(type) == 0); 60 | factory[type] = [] (const std::string& format) { return std::make_unique(format); }; 61 | } 62 | 63 | static std::unique_ptr 64 | createNameAssignmentFunc(const std::string& type, const std::string& format = ""); 65 | 66 | NDNCERT_PUBLIC_WITH_TESTS_ELSE_PROTECTED: 67 | std::vector m_nameFormat; 68 | 69 | private: 70 | using CreateFunc = std::function(const std::string &)>; 71 | using FuncFactory = std::map; 72 | 73 | static FuncFactory& 74 | getFactory(); 75 | }; 76 | 77 | } // namespace ndncert 78 | 79 | #define NDNCERT_REGISTER_NAME_ASSIGNMENT_FUNC(C, T) \ 80 | static class NdnCert##C##NameAssignmentRegistrationClass \ 81 | { \ 82 | public: \ 83 | NdnCert##C##NameAssignmentRegistrationClass() \ 84 | { \ 85 | ::ndncert::NameAssignmentFunc::registerNameAssignmentFunc(T); \ 86 | } \ 87 | } g_NdnCert##C##NameAssignmentRegistrationVariable 88 | 89 | #endif // NDNCERT_ASSIGNMENT_FUNC_HPP 90 | -------------------------------------------------------------------------------- /tests/unit-tests/ca-memory.t.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "detail/ca-memory.hpp" 22 | 23 | #include "tests/boost-test.hpp" 24 | #include "tests/key-chain-fixture.hpp" 25 | 26 | namespace ndncert::tests { 27 | 28 | using namespace ca; 29 | 30 | BOOST_FIXTURE_TEST_SUITE(TestCaMemory, KeyChainFixture) 31 | 32 | BOOST_AUTO_TEST_CASE(RequestOperations) 33 | { 34 | CaMemory storage; 35 | 36 | auto identity1 = m_keyChain.createIdentity(Name("/ndn/site1")); 37 | auto key1 = identity1.getDefaultKey(); 38 | auto cert1 = key1.getDefaultCertificate(); 39 | 40 | // add operation 41 | RequestId requestId = {{101}}; 42 | RequestState request1; 43 | request1.caPrefix = Name("/ndn/site1"); 44 | request1.requestId = requestId; 45 | request1.requestType = RequestType::NEW; 46 | request1.cert = cert1; 47 | BOOST_CHECK_NO_THROW(storage.addRequest(request1)); 48 | 49 | // get operation 50 | auto result = storage.getRequest(requestId); 51 | BOOST_CHECK_EQUAL(request1.cert, result.cert); 52 | BOOST_CHECK(request1.status == result.status); 53 | BOOST_CHECK_EQUAL(request1.caPrefix, result.caPrefix); 54 | BOOST_CHECK_EQUAL_COLLECTIONS(request1.encryptionKey.begin(), request1.encryptionKey.end(), 55 | result.encryptionKey.begin(), result.encryptionKey.end()); 56 | 57 | // update operation 58 | RequestState request2; 59 | request2.caPrefix = Name("/ndn/site1"); 60 | request2.requestId = requestId; 61 | request2.requestType = RequestType::NEW; 62 | request2.cert = cert1; 63 | request2.challengeType = "email"; 64 | JsonSection secret; 65 | secret.add("code", "1234"); 66 | request2.challengeState = ChallengeState("test", time::system_clock::now(), 3, 67 | time::seconds(3600), std::move(secret)); 68 | storage.updateRequest(request2); 69 | result = storage.getRequest(requestId); 70 | BOOST_CHECK_EQUAL(request2.cert, result.cert); 71 | BOOST_CHECK(request2.status == result.status); 72 | BOOST_CHECK_EQUAL(request2.caPrefix, result.caPrefix); 73 | 74 | // another add operation 75 | auto identity2 = m_keyChain.createIdentity(Name("/ndn/site2")); 76 | auto key2 = identity2.getDefaultKey(); 77 | auto cert2 = key2.getDefaultCertificate(); 78 | RequestId requestId2 = {{102}}; 79 | RequestState request3; 80 | request3.caPrefix = Name("/ndn/site2"); 81 | request3.requestId = requestId2; 82 | request3.requestType = RequestType::NEW; 83 | request3.cert = cert2; 84 | storage.addRequest(request3); 85 | 86 | // list operation 87 | auto allRequests = storage.listAllRequests(); 88 | BOOST_CHECK_EQUAL(allRequests.size(), 2); 89 | 90 | storage.deleteRequest(requestId2); 91 | allRequests = storage.listAllRequests(); 92 | BOOST_CHECK_EQUAL(allRequests.size(), 1); 93 | } 94 | 95 | BOOST_AUTO_TEST_SUITE_END() // TestCaMemory 96 | 97 | } // namespace ndncert::tests 98 | -------------------------------------------------------------------------------- /src/challenge/challenge-possession.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2022, Regents of the University of California. 3 | * 4 | * This file is part of ndncert, a certificate management system based on NDN. 5 | * 6 | * ndncert is free software: you can redistribute it and/or modify it under the terms 7 | * of the GNU General Public License as published by the Free Software Foundation, either 8 | * version 3 of the License, or (at your option) any later version. 9 | * 10 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 12 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 | * 14 | * You should have received copies of the GNU General Public License along with 15 | * ndncert, e.g., in COPYING.md file. If not, see . 16 | * 17 | * See AUTHORS.md for complete list of ndncert authors and contributors. 18 | */ 19 | 20 | #ifndef NDNCERT_CHALLENGE_POSSESSION_HPP 21 | #define NDNCERT_CHALLENGE_POSSESSION_HPP 22 | 23 | #include "challenge-module.hpp" 24 | 25 | #include 26 | 27 | namespace ndncert { 28 | 29 | /** 30 | * @brief Provide Possession based challenge 31 | * 32 | * Possession here means possession of the certificate issued by a trust anchor. Once the requester 33 | * could proof his/her possession of an existing certificate from this or other certificate issuer, 34 | * the requester could finish the challenge. 35 | * 36 | * The requester needs to provide the proof of the possession of a certificate issued by 37 | * a trust anchor. The challenge require the requester to pass the BASE64 certificate and 38 | * a BASE64 Data packet signed by the credential pub key and whose content is the request id. 39 | * 40 | * The main process of this challenge module is: 41 | * 1. Requester provides a certificate signed by that trusted certificate as credential. 42 | * 2. The challenge module will verify the signature of the credential. 43 | * 3. The challenge module will Provide a 16 octet random number data. 44 | * 3. The Requester signs the signed Data to prove it possess the private key 45 | * 46 | * Failure info when application fails: 47 | * INVALID_PARAMETER: When the cert issued from trust anchor or self-signed cert 48 | * cannot be validated. 49 | * FAILURE_INVALID_FORMAT: When the credential format is wrong. 50 | */ 51 | class ChallengePossession : public ChallengeModule 52 | { 53 | public: 54 | explicit 55 | ChallengePossession(const std::string& configPath = ""); 56 | 57 | // For CA 58 | std::tuple 59 | handleChallengeRequest(const Block& params, ca::RequestState& request) override; 60 | 61 | // For Client 62 | std::multimap 63 | getRequestedParameterList(Status status, const std::string& challengeStatus) override; 64 | 65 | Block 66 | genChallengeRequestTLV(Status status, const std::string& challengeStatus, 67 | const std::multimap& params) override; 68 | 69 | static void 70 | fulfillParameters(std::multimap& params, 71 | ndn::KeyChain& keyChain, const Name& issuedCertName, 72 | ndn::span nonce); 73 | 74 | // challenge parameters 75 | static const std::string PARAMETER_KEY_CREDENTIAL_CERT; 76 | static const std::string PARAMETER_KEY_NONCE; 77 | static const std::string PARAMETER_KEY_PROOF; 78 | static const std::string NEED_PROOF; 79 | 80 | NDNCERT_PUBLIC_WITH_TESTS_ELSE_PRIVATE: 81 | void 82 | parseConfigFile(); 83 | 84 | NDNCERT_PUBLIC_WITH_TESTS_ELSE_PRIVATE: 85 | std::list m_trustAnchors; 86 | std::string m_configFile; 87 | }; 88 | 89 | } // namespace ndncert 90 | 91 | #endif // NDNCERT_CHALLENGE_POSSESSION_HPP 92 | -------------------------------------------------------------------------------- /src/detail/ca-configuration.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "detail/ca-configuration.hpp" 22 | 23 | #include 24 | 25 | #include 26 | 27 | namespace ndncert::ca { 28 | 29 | void 30 | CaConfig::load(const std::string& fileName) 31 | { 32 | JsonSection configJson; 33 | try { 34 | boost::property_tree::read_json(fileName, configJson); 35 | } 36 | catch (const std::exception& error) { 37 | NDN_THROW(std::runtime_error("Failed to parse configuration file " + fileName + ", " + error.what())); 38 | } 39 | 40 | if (configJson.begin() == configJson.end()) { 41 | NDN_THROW(std::runtime_error("No JSON configuration found in file: " + fileName)); 42 | } 43 | caProfile = CaProfile::fromJson(configJson); 44 | if (caProfile.supportedChallenges.empty()) { 45 | NDN_THROW(std::runtime_error("At least one challenge should be specified.")); 46 | } 47 | 48 | // parse redirection section if present 49 | redirection.clear(); 50 | auto redirectionItems = configJson.get_child_optional(CONFIG_REDIRECTION); 51 | if (redirectionItems) { 52 | for (const auto& item : *redirectionItems) { 53 | auto caPrefixStr = item.second.get(CONFIG_CA_PREFIX, ""); 54 | auto caCertStr = item.second.get(CONFIG_CERTIFICATE, ""); 55 | if (caCertStr.empty()) { 56 | NDN_THROW(std::runtime_error("Redirect-to item's certificate cannot be empty.")); 57 | } 58 | std::istringstream ss(caCertStr); 59 | auto caCert = ndn::io::load(ss); 60 | if (!caPrefixStr.empty() && Name(caPrefixStr) != caCert->getIdentity()) { 61 | NDN_THROW(std::runtime_error("Redirect-to item's prefix and certificate does not match.")); 62 | } 63 | 64 | auto policyType = item.second.get(CONFIG_REDIRECTION_POLICY_TYPE, ""); 65 | auto policyParam = item.second.get(CONFIG_REDIRECTION_POLICY_PARAM, ""); 66 | if (policyType.empty()) { 67 | NDN_THROW(std::runtime_error("Redirect-to policy type expected but not provided.")); 68 | } 69 | auto policy = RedirectionPolicy::createPolicyFunc(policyType, policyParam); 70 | if (policy == nullptr) { 71 | NDN_THROW(std::runtime_error("Error on creating redirection policy")); 72 | } 73 | redirection.emplace_back(caCert, std::move(policy)); 74 | } 75 | } 76 | 77 | // parse name assignment if present 78 | nameAssignmentFuncs.clear(); 79 | auto nameAssignmentItems = configJson.get_child_optional(CONFIG_NAME_ASSIGNMENT); 80 | if (nameAssignmentItems) { 81 | for (const auto& [key, val] : *nameAssignmentItems) { 82 | auto func = NameAssignmentFunc::createNameAssignmentFunc(key, val.data()); 83 | if (func == nullptr) { 84 | NDN_THROW(std::runtime_error("Error on creating name assignment function")); 85 | } 86 | nameAssignmentFuncs.push_back(std::move(func)); 87 | } 88 | } 89 | } 90 | 91 | } // namespace ndncert::ca 92 | -------------------------------------------------------------------------------- /src/challenge/challenge-module.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "challenge/challenge-module.hpp" 22 | 23 | #include 24 | 25 | namespace ndncert { 26 | 27 | ChallengeModule::ChallengeModule(const std::string& challengeType, 28 | size_t maxAttemptTimes, 29 | time::seconds secretLifetime) 30 | : CHALLENGE_TYPE(challengeType) 31 | , m_maxAttemptTimes(maxAttemptTimes) 32 | , m_secretLifetime(secretLifetime) 33 | { 34 | } 35 | 36 | bool 37 | ChallengeModule::isChallengeSupported(const std::string& challengeType) 38 | { 39 | auto& factory = getFactory(); 40 | auto i = factory.find(challengeType); 41 | return i != factory.end(); 42 | } 43 | 44 | std::unique_ptr 45 | ChallengeModule::createChallengeModule(const std::string& challengeType) 46 | { 47 | auto& factory = getFactory(); 48 | auto i = factory.find(challengeType); 49 | return i == factory.end() ? nullptr : i->second(); 50 | } 51 | 52 | ChallengeModule::ChallengeFactory& 53 | ChallengeModule::getFactory() 54 | { 55 | static ChallengeFactory factory; 56 | return factory; 57 | } 58 | 59 | std::string 60 | ChallengeModule::generateSecretCode() 61 | { 62 | uint32_t securityCode = 0; 63 | do { 64 | securityCode = ndn::random::generateSecureWord32(); 65 | } while (securityCode >= 4294000000); 66 | securityCode /= 4294; 67 | std::string result = std::to_string(securityCode); 68 | while (result.length() < 6) { 69 | result = "0" + result; 70 | } 71 | return result; 72 | } 73 | 74 | std::tuple 75 | ChallengeModule::returnWithError(ca::RequestState& request, ErrorCode errorCode, std::string errorInfo) 76 | { 77 | request.status = Status::FAILURE; 78 | request.challengeType = ""; 79 | request.challengeState = std::nullopt; 80 | return {errorCode, std::move(errorInfo)}; 81 | } 82 | 83 | std::tuple 84 | ChallengeModule::returnWithNewChallengeStatus(ca::RequestState& request, const std::string& challengeStatus, 85 | JsonSection challengeSecret, size_t remainingTries, 86 | time::seconds remainingTime) 87 | { 88 | request.status = Status::CHALLENGE; 89 | request.challengeType = CHALLENGE_TYPE; 90 | request.challengeState = ca::ChallengeState(challengeStatus, time::system_clock::now(), remainingTries, 91 | remainingTime, std::move(challengeSecret)); 92 | return {ErrorCode::NO_ERROR, ""}; 93 | } 94 | 95 | std::tuple 96 | ChallengeModule::returnWithSuccess(ca::RequestState& request) 97 | { 98 | request.status = Status::PENDING; 99 | request.challengeType = CHALLENGE_TYPE; 100 | request.challengeState = std::nullopt; 101 | return {ErrorCode::NO_ERROR, ""}; 102 | } 103 | 104 | } // namespace ndncert 105 | -------------------------------------------------------------------------------- /src/detail/ca-profile.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_CA_PROFILE_HPP 22 | #define NDNCERT_DETAIL_CA_PROFILE_HPP 23 | 24 | #include "detail/ndncert-common.hpp" 25 | 26 | #include 27 | 28 | namespace ndncert { 29 | 30 | // used in parsing CA configuration file and Client CA profile storage file 31 | const std::string CONFIG_CA_PREFIX = "ca-prefix"; 32 | const std::string CONFIG_CA_INFO = "ca-info"; 33 | const std::string CONFIG_MAX_VALIDITY_PERIOD = "max-validity-period"; 34 | const std::string CONFIG_MAX_SUFFIX_LENGTH = "max-suffix-length"; 35 | const std::string CONFIG_PROBE_PARAMETERS = "probe-parameters"; 36 | const std::string CONFIG_PROBE_PARAMETER = "probe-parameter-key"; 37 | const std::string CONFIG_SUPPORTED_CHALLENGES = "supported-challenges"; 38 | const std::string CONFIG_CHALLENGE = "challenge"; 39 | const std::string CONFIG_CERTIFICATE = "certificate"; 40 | const std::string CONFIG_FORWARDING_HINT = "forwarding-hint"; 41 | const std::string CONFIG_REDIRECTION = "redirect-to"; 42 | const std::string CONFIG_NAME_ASSIGNMENT = "name-assignment"; 43 | const std::string CONFIG_REDIRECTION_POLICY_TYPE = "policy-type"; 44 | const std::string CONFIG_REDIRECTION_POLICY_PARAM = "policy-param"; 45 | 46 | class CaProfile 47 | { 48 | public: 49 | /** 50 | * Parse the configuration JSON. 51 | * @param json the configuration json to parse 52 | * @return the CaProfile according to this json 53 | */ 54 | static CaProfile 55 | fromJson(const JsonSection& json); 56 | 57 | /** 58 | * @return the JSON representation of this profile. 59 | */ 60 | JsonSection 61 | toJson() const; 62 | 63 | public: 64 | /** 65 | * @brief CA Name prefix (without /CA suffix). 66 | */ 67 | Name caPrefix; 68 | /** 69 | * @brief Forwarding hint for requesters to retrieve issued certificates. 70 | */ 71 | Name forwardingHint; 72 | /** 73 | * @brief CA Information. 74 | */ 75 | std::string caInfo; 76 | /** 77 | * @brief A list of parameter-keys for PROBE. 78 | */ 79 | std::vector probeParameterKeys; 80 | /** 81 | * @brief Maximum allowed validity period of the certificate being requested. 82 | * 83 | * The value is in the unit of second. 84 | * Default: one day (86400 seconds). 85 | */ 86 | time::seconds maxValidityPeriod; 87 | /** 88 | * @brief Maximum allowed suffix length of requested name. 89 | * 90 | * E.g., When its value is 2, at most 2 name components can be assigned after m_caPrefix. 91 | * Default: none. 92 | */ 93 | std::optional maxSuffixLength; 94 | /** 95 | * @brief A list of supported challenges. Only CA side will have m_supportedChallenges. 96 | */ 97 | std::vector supportedChallenges; 98 | /** 99 | * @brief CA's certificate. Only Client side will have m_cert. 100 | */ 101 | std::shared_ptr cert; 102 | }; 103 | 104 | } // namespace ndncert 105 | 106 | #endif // NDNCERT_DETAIL_CA_PROFILE_HPP 107 | -------------------------------------------------------------------------------- /tests/unit-tests/name-assignment.t.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "name-assignment/assignment-email.hpp" 22 | #include "name-assignment/assignment-random.hpp" 23 | #include "name-assignment/assignment-param.hpp" 24 | #include "name-assignment/assignment-hash.hpp" 25 | 26 | #include "tests/boost-test.hpp" 27 | 28 | namespace ndncert::tests { 29 | 30 | BOOST_AUTO_TEST_SUITE(TestNameAssignment) 31 | 32 | BOOST_AUTO_TEST_CASE(NameAssignmentRandom) 33 | { 34 | AssignmentRandom assignment; 35 | BOOST_CHECK_EQUAL(assignment.assignName(std::multimap()).size(), 1); 36 | BOOST_CHECK_EQUAL(assignment.assignName(std::multimap()).begin()->size(), 1); 37 | } 38 | 39 | BOOST_AUTO_TEST_CASE(NameAssignmentParam) 40 | { 41 | AssignmentParam assignment("/abc/xyz"); 42 | std::multimap params; 43 | params.emplace("abc", "123"); 44 | BOOST_CHECK_EQUAL(assignment.assignName(params).size(), 0); 45 | params.emplace("xyz", "789"); 46 | BOOST_CHECK_EQUAL(assignment.assignName(params).size(), 1); 47 | BOOST_CHECK_EQUAL(*assignment.assignName(params).begin(), Name("/123/789")); 48 | params.emplace("fake", "456"); 49 | BOOST_CHECK_EQUAL(assignment.assignName(params).size(), 1); 50 | BOOST_CHECK_EQUAL(*assignment.assignName(params).begin(), Name("/123/789")); 51 | params.find("xyz")->second = ""; 52 | BOOST_CHECK_EQUAL(assignment.assignName(params).size(), 0); 53 | 54 | AssignmentParam assignment2("/\"guest\"/email"); 55 | params.emplace("email", "1@1.com"); 56 | BOOST_CHECK_EQUAL(assignment2.assignName(params).size(), 1); 57 | BOOST_CHECK_EQUAL(assignment2.assignName(params).begin()->toUri(), Name("/guest/1@1.com").toUri()); 58 | 59 | AssignmentParam assignment3("/\"/email"); 60 | BOOST_CHECK_EQUAL(assignment3.assignName(params).size(), 0); 61 | } 62 | 63 | BOOST_AUTO_TEST_CASE(NameAssignmentHash) 64 | { 65 | AssignmentHash assignment("/abc/xyz"); 66 | std::multimap params; 67 | params.emplace("abc", "123"); 68 | BOOST_CHECK_EQUAL(assignment.assignName(params).size(), 0); 69 | params.emplace("xyz", "789"); 70 | BOOST_CHECK_EQUAL(assignment.assignName(params).size(), 1); 71 | BOOST_CHECK_EQUAL(assignment.assignName(params).begin()->size(), 2); 72 | params.emplace("fake", "456"); 73 | BOOST_CHECK_EQUAL(assignment.assignName(params).size(), 1); 74 | BOOST_CHECK_EQUAL(assignment.assignName(params).begin()->size(), 2); 75 | params.find("xyz")->second = ""; 76 | BOOST_CHECK_EQUAL(assignment.assignName(params).size(), 1); 77 | BOOST_CHECK_EQUAL(assignment.assignName(params).begin()->size(), 2); 78 | } 79 | 80 | BOOST_AUTO_TEST_CASE(NameAssignmentEmail) 81 | { 82 | AssignmentEmail assignment("/edu/ucla"); 83 | std::multimap params; 84 | BOOST_CHECK_EQUAL(assignment.assignName(params).size(), 0); 85 | params.emplace("email", "das@math.ucla.edu"); 86 | BOOST_CHECK_EQUAL(*assignment.assignName(params).begin(), Name("/math/das")); 87 | 88 | params.clear(); 89 | params.emplace("email", "d/~.^as@6666=.9!"); 90 | BOOST_CHECK_EQUAL(assignment.assignName(params).size(), 1); 91 | BOOST_CHECK_EQUAL(*assignment.assignName(params).begin(), Name("/9!/6666%3D/d%2F~.%5Eas")); 92 | } 93 | 94 | BOOST_AUTO_TEST_SUITE_END() // TestNameAssignment 95 | 96 | } // namespace ndncert::tests 97 | -------------------------------------------------------------------------------- /src/challenge/challenge-module.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_CHALLENGE_MODULE_HPP 22 | #define NDNCERT_CHALLENGE_MODULE_HPP 23 | 24 | #include "detail/ca-request-state.hpp" 25 | 26 | #include 27 | #include 28 | 29 | namespace ndncert { 30 | 31 | class ChallengeModule : boost::noncopyable 32 | { 33 | public: 34 | ChallengeModule(const std::string& challengeType, size_t maxAttemptTimes, time::seconds secretLifetime); 35 | 36 | virtual 37 | ~ChallengeModule() = default; 38 | 39 | // For CA 40 | virtual std::tuple 41 | handleChallengeRequest(const Block& params, ca::RequestState& request) = 0; 42 | 43 | // For Client 44 | virtual std::multimap 45 | getRequestedParameterList(Status status, const std::string& challengeStatus) = 0; 46 | 47 | virtual Block 48 | genChallengeRequestTLV(Status status, const std::string& challengeStatus, 49 | const std::multimap& params) = 0; 50 | 51 | public: // factory 52 | template 53 | static void 54 | registerChallengeModule(const std::string& type) 55 | { 56 | auto& factory = getFactory(); 57 | BOOST_ASSERT(factory.count(type) == 0); 58 | factory[type] = [] { return std::make_unique(); }; 59 | } 60 | 61 | static bool 62 | isChallengeSupported(const std::string& challengeType); 63 | 64 | static std::unique_ptr 65 | createChallengeModule(const std::string& challengeType); 66 | 67 | protected: // helpers used by concrete challenge modules 68 | static std::string 69 | generateSecretCode(); 70 | 71 | static std::tuple 72 | returnWithError(ca::RequestState& request, ErrorCode errorCode, std::string errorInfo); 73 | 74 | std::tuple 75 | returnWithNewChallengeStatus(ca::RequestState& request, const std::string& challengeStatus, 76 | JsonSection challengeSecret, size_t remainingTries, time::seconds remainingTime); 77 | 78 | std::tuple 79 | returnWithSuccess(ca::RequestState& request); 80 | 81 | public: 82 | const std::string CHALLENGE_TYPE; 83 | 84 | protected: 85 | const size_t m_maxAttemptTimes; 86 | const time::seconds m_secretLifetime; 87 | 88 | private: 89 | using CreateFunc = std::function()>; 90 | using ChallengeFactory = std::map; 91 | 92 | static ChallengeFactory& 93 | getFactory(); 94 | }; 95 | 96 | } // namespace ndncert 97 | 98 | #define NDNCERT_REGISTER_CHALLENGE(C, T) \ 99 | static class NdnCert##C##ChallengeRegistrationClass \ 100 | { \ 101 | public: \ 102 | NdnCert##C##ChallengeRegistrationClass() \ 103 | { \ 104 | ::ndncert::ChallengeModule::registerChallengeModule(T); \ 105 | } \ 106 | } g_NdnCert##C##ChallengeRegistrationVariable 107 | 108 | #endif // NDNCERT_CHALLENGE_MODULE_HPP 109 | -------------------------------------------------------------------------------- /src/detail/ca-request-state.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_CA_REQUEST_STATE_HPP 22 | #define NDNCERT_DETAIL_CA_REQUEST_STATE_HPP 23 | 24 | #include "detail/ndncert-common.hpp" 25 | 26 | #include 27 | #include 28 | 29 | namespace ndncert { 30 | 31 | using RequestId = std::array; 32 | 33 | enum class Status : uint16_t { 34 | BEFORE_CHALLENGE = 0, 35 | CHALLENGE = 1, 36 | PENDING = 2, 37 | SUCCESS = 3, 38 | FAILURE = 4, 39 | }; 40 | 41 | /** 42 | * @brief Convert request status to string. 43 | */ 44 | std::string 45 | statusToString(Status status); 46 | 47 | /** 48 | * @brief Convert request status to string. 49 | */ 50 | Status 51 | statusFromBlock(const Block& block); 52 | 53 | namespace ca { 54 | 55 | /** 56 | * @brief The state maintained by the Challenge module. 57 | */ 58 | struct ChallengeState 59 | { 60 | ChallengeState(const std::string& challengeStatus, const time::system_clock::time_point& challengeTp, 61 | size_t remainingTries, time::seconds remainingTime, 62 | JsonSection&& challengeSecrets); 63 | 64 | /** 65 | * @brief The status of the challenge. 66 | */ 67 | std::string challengeStatus; 68 | /** 69 | * @brief The timestamp of the last update of the challenge state. 70 | */ 71 | time::system_clock::time_point timestamp; 72 | /** 73 | * @brief Remaining tries of the challenge. 74 | */ 75 | size_t remainingTries; 76 | /** 77 | * @brief Remaining time of the challenge. 78 | */ 79 | time::seconds remainingTime; 80 | /** 81 | * @brief The secret for the challenge. 82 | */ 83 | JsonSection secrets; 84 | }; 85 | 86 | /** 87 | * @brief Represents a certificate request instance kept by the CA. 88 | * 89 | * ChallengeModule should take use of RequestState.ChallengeState to keep the challenge state. 90 | */ 91 | struct RequestState 92 | { 93 | /** 94 | * @brief The CA that the request is under. 95 | */ 96 | Name caPrefix; 97 | /** 98 | * @brief The ID of the request. 99 | */ 100 | RequestId requestId; 101 | /** 102 | * @brief The type of the request. 103 | */ 104 | RequestType requestType = RequestType::NOTINITIALIZED; 105 | /** 106 | * @brief The status of the request. 107 | */ 108 | Status status = Status::BEFORE_CHALLENGE; 109 | /** 110 | * @brief The self-signed certificate in the request. 111 | */ 112 | Certificate cert; 113 | /** 114 | * @brief The encryption key for the requester. 115 | */ 116 | std::array encryptionKey = {}; 117 | /** 118 | * @brief The last Initialization Vector used by the AES encryption. 119 | */ 120 | std::vector encryptionIv; 121 | /** 122 | * @brief The last Initialization Vector used by the other side's AES encryption. 123 | */ 124 | std::vector decryptionIv; 125 | /** 126 | * @brief The challenge type. 127 | */ 128 | std::string challengeType; 129 | /** 130 | * @brief The challenge state. 131 | */ 132 | std::optional challengeState; 133 | }; 134 | 135 | std::ostream& 136 | operator<<(std::ostream& os, const RequestState& request); 137 | 138 | } // namespace ca 139 | } // namespace ndncert 140 | 141 | #endif // NDNCERT_DETAIL_CA_REQUEST_STATE_HPP 142 | -------------------------------------------------------------------------------- /src/detail/ndncert-common.hpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #ifndef NDNCERT_DETAIL_NDNCERT_COMMON_HPP 22 | #define NDNCERT_DETAIL_NDNCERT_COMMON_HPP 23 | 24 | #include "detail/ndncert-config.hpp" 25 | 26 | #ifdef NDNCERT_WITH_TESTS 27 | #define NDNCERT_VIRTUAL_WITH_TESTS virtual 28 | #define NDNCERT_PUBLIC_WITH_TESTS_ELSE_PROTECTED public 29 | #define NDNCERT_PUBLIC_WITH_TESTS_ELSE_PRIVATE public 30 | #define NDNCERT_PROTECTED_WITH_TESTS_ELSE_PRIVATE protected 31 | #else 32 | #define NDNCERT_VIRTUAL_WITH_TESTS 33 | #define NDNCERT_PUBLIC_WITH_TESTS_ELSE_PROTECTED protected 34 | #define NDNCERT_PUBLIC_WITH_TESTS_ELSE_PRIVATE private 35 | #define NDNCERT_PROTECTED_WITH_TESTS_ELSE_PRIVATE private 36 | #endif 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | #include 55 | #include 56 | #include 57 | 58 | namespace ndncert { 59 | 60 | using ndn::Block; 61 | using ndn::Data; 62 | using ndn::Interest; 63 | using ndn::Name; 64 | using ndn::SignatureInfo; 65 | using ndn::security::Certificate; 66 | 67 | namespace time = ndn::time; 68 | using namespace ndn::time_literals; 69 | using namespace std::string_literals; 70 | 71 | namespace tlv { 72 | 73 | enum : uint32_t { 74 | CaPrefix = 129, 75 | CaInfo = 131, 76 | ParameterKey = 133, 77 | ParameterValue = 135, 78 | CaCertificate = 137, 79 | MaxValidityPeriod = 139, 80 | ProbeResponse = 141, 81 | MaxSuffixLength = 143, 82 | EcdhPub = 145, 83 | CertRequest = 147, 84 | Salt = 149, 85 | RequestId = 151, 86 | Challenge = 153, 87 | Status = 155, 88 | InitializationVector = 157, 89 | EncryptedPayload = 159, 90 | SelectedChallenge = 161, 91 | ChallengeStatus = 163, 92 | RemainingTries = 165, 93 | RemainingTime = 167, 94 | IssuedCertName = 169, 95 | ErrorCode = 171, 96 | ErrorInfo = 173, 97 | AuthenticationTag = 175, 98 | CertToRevoke = 177, 99 | ProbeRedirect = 179, 100 | }; 101 | 102 | } // namespace tlv 103 | 104 | using JsonSection = boost::property_tree::ptree; 105 | 106 | // NDNCERT error code 107 | enum class ErrorCode : uint64_t { 108 | NO_ERROR = 0, 109 | BAD_INTEREST_FORMAT = 1, 110 | BAD_PARAMETER_FORMAT = 2, 111 | BAD_SIGNATURE = 3, 112 | INVALID_PARAMETER = 4, 113 | NAME_NOT_ALLOWED = 5, 114 | BAD_VALIDITY_PERIOD = 6, 115 | OUT_OF_TRIES = 7, 116 | OUT_OF_TIME = 8, 117 | NO_AVAILABLE_NAMES = 9, 118 | }; 119 | 120 | // Convert error code to string 121 | std::ostream& 122 | operator<<(std::ostream& os, ErrorCode code); 123 | 124 | // NDNCERT request type 125 | enum class RequestType : uint64_t { 126 | NOTINITIALIZED = 0, 127 | NEW = 1, 128 | RENEW = 2, 129 | REVOKE = 3, 130 | }; 131 | 132 | // Convert request type to string 133 | std::ostream& 134 | operator<<(std::ostream& out, RequestType type); 135 | 136 | } // namespace ndncert 137 | 138 | #endif // NDNCERT_DETAIL_NDNCERT_COMMON_HPP 139 | -------------------------------------------------------------------------------- /.waf-tools/openssl.py: -------------------------------------------------------------------------------- 1 | """ 2 | When using this tool, the wscript should look like: 3 | 4 | def options(opt): 5 | opt.load('openssl') 6 | 7 | def configure(conf): 8 | conf.load('compiler_cxx openssl') 9 | conf.check_openssl() 10 | 11 | def build(bld): 12 | bld(source='main.cpp', target='app', use='OPENSSL') 13 | """ 14 | 15 | import re 16 | from waflib import Utils 17 | from waflib.Configure import conf 18 | 19 | OPENSSL_DIR = ['/usr', '/usr/local', '/opt/local', '/sw'] 20 | OPENSSL_DIR_MACOS = ['/usr/local', 21 | '/opt/homebrew/opt/openssl', # Homebrew on arm64 22 | '/usr/local/opt/openssl', # Homebrew on x86_64 23 | '/opt/local'] # MacPorts 24 | 25 | def options(opt): 26 | opt.add_option('--with-openssl', type='string', default=None, dest='openssl_dir', 27 | help='directory where OpenSSL is installed, e.g., /usr/local') 28 | 29 | @conf 30 | def __openssl_get_version_file(self, dir): 31 | try: 32 | return self.root.find_dir(dir).find_node('include/openssl/opensslv.h') 33 | except: 34 | return None 35 | 36 | @conf 37 | def __openssl_find_root_and_version_file(self, root): 38 | if root: 39 | file = self.__openssl_get_version_file(root) 40 | if not file: 41 | self.fatal(f'OpenSSL not found in {root}') 42 | return (root, file) 43 | 44 | openssl_dirs = OPENSSL_DIR 45 | if Utils.unversioned_sys_platform() == 'darwin': 46 | openssl_dirs = OPENSSL_DIR_MACOS 47 | 48 | for dir in openssl_dirs: 49 | file = self.__openssl_get_version_file(dir) 50 | if file: 51 | return (dir, file) 52 | 53 | self.fatal('OpenSSL not found, please provide a --with-openssl=PATH argument (see --help)') 54 | 55 | @conf 56 | def __openssl_check_version(self, version_file, atleast_version): 57 | min_version = tuple(int(i) for i in atleast_version.split('.')) 58 | txt = version_file.read() 59 | 60 | # OpenSSL 3.0.0 and later 61 | ver_tuple = (re.search(r'^#\s*define\s+OPENSSL_VERSION_MAJOR\s+(\d+)', txt, re.MULTILINE), 62 | re.search(r'^#\s*define\s+OPENSSL_VERSION_MINOR\s+(\d+)', txt, re.MULTILINE), 63 | re.search(r'^#\s*define\s+OPENSSL_VERSION_PATCH\s+(\d+)', txt, re.MULTILINE)) 64 | ver_string = re.search(r'^#\s*define\s+OPENSSL_FULL_VERSION_STR\s+"(.+)"', txt, re.MULTILINE) 65 | if all(ver_tuple): 66 | version = tuple(int(i[1]) for i in ver_tuple) 67 | ver_string = ver_string[1] if ver_string else '.'.join(version) 68 | return (version >= min_version, ver_string) 69 | 70 | # OpenSSL 1.1.1 and earlier 71 | ver_number = re.search(r'^#\s*define\s+OPENSSL_VERSION_NUMBER\s+(.+)L', txt, re.MULTILINE) 72 | ver_string = re.search(r'^#\s*define\s+OPENSSL_VERSION_TEXT\s+"(.+)"', txt, re.MULTILINE) 73 | if ver_number and ver_string: 74 | version = int(ver_number[1], 16) 75 | min_version = (min_version[0] << 28) | (min_version[1] << 20) | (min_version[2] << 12) | 0xf 76 | return (version >= min_version, ver_string[1]) 77 | 78 | self.fatal(f'Cannot extract version information from {version_file}') 79 | 80 | @conf 81 | def check_openssl(self, *k, **kw): 82 | self.start_msg('Checking for OpenSSL version') 83 | 84 | path = k and k[0] or kw.get('path', self.options.openssl_dir) 85 | root, version_file = self.__openssl_find_root_and_version_file(path) 86 | atleast_version = kw.get('atleast_version', 0) 87 | ok, version_str = self.__openssl_check_version(version_file, atleast_version) 88 | 89 | self.end_msg(version_str) 90 | if not ok: 91 | self.fatal(f'The version of OpenSSL is too old; {atleast_version} or later is required.\n' 92 | 'Please upgrade your distribution or manually install a newer version of OpenSSL.') 93 | 94 | if 'msg' not in kw: 95 | kw['msg'] = 'Checking if OpenSSL library works' 96 | if 'lib' not in kw: 97 | kw['lib'] = ['ssl', 'crypto'] 98 | if 'uselib_store' not in kw: 99 | kw['uselib_store'] = 'OPENSSL' 100 | if 'define_name' not in kw: 101 | kw['define_name'] = f"HAVE_{kw['uselib_store']}" 102 | kw['includes'] = f'{root}/include' 103 | kw['libpath'] = f'{root}/lib' 104 | 105 | self.check_cxx(**kw) 106 | -------------------------------------------------------------------------------- /src/detail/probe-encoder.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "detail/probe-encoder.hpp" 22 | 23 | namespace ndncert::probetlv { 24 | 25 | Block 26 | encodeApplicationParameters(const std::multimap& parameters) 27 | { 28 | Block content(ndn::tlv::ApplicationParameters); 29 | for (const auto& items : parameters) { 30 | content.push_back(ndn::makeStringBlock(tlv::ParameterKey, items.first)); 31 | content.push_back(ndn::makeStringBlock(tlv::ParameterValue, items.second)); 32 | } 33 | content.encode(); 34 | return content; 35 | } 36 | 37 | std::multimap 38 | decodeApplicationParameters(const Block& block) 39 | { 40 | std::multimap result; 41 | block.parse(); 42 | const auto& elements = block.elements(); 43 | for (size_t i = 0; i < elements.size(); i++) { 44 | if (i + 1 < elements.size() && elements[i].type() == tlv::ParameterKey && 45 | elements[i + 1].type() == tlv::ParameterValue) { 46 | result.emplace(readString(elements.at(i)), readString(elements.at(i + 1))); 47 | i++; 48 | } 49 | else if (ndn::tlv::isCriticalType(elements[i].type())) { 50 | NDN_THROW(std::runtime_error("Unrecognized TLV Type: " + std::to_string(elements[i].type()))); 51 | } 52 | else { 53 | //ignore 54 | } 55 | } 56 | return result; 57 | } 58 | 59 | Block 60 | encodeDataContent(const std::vector& identifiers, std::optional maxSuffixLength, 61 | const std::vector& redirectionItems) 62 | { 63 | Block content(ndn::tlv::Content); 64 | for (const auto& name : identifiers) { 65 | Block item(tlv::ProbeResponse); 66 | item.push_back(name.wireEncode()); 67 | if (maxSuffixLength) { 68 | item.push_back(ndn::makeNonNegativeIntegerBlock(tlv::MaxSuffixLength, *maxSuffixLength)); 69 | } 70 | content.push_back(item); 71 | } 72 | 73 | for (const auto& item : redirectionItems) { 74 | content.push_back(makeNestedBlock(tlv::ProbeRedirect, item)); 75 | } 76 | 77 | content.encode(); 78 | return content; 79 | } 80 | 81 | void 82 | decodeDataContent(const Block& block, std::vector>& availableNames, 83 | std::vector& availableRedirection) 84 | { 85 | block.parse(); 86 | for (const auto& item : block.elements()) { 87 | if (item.type() == tlv::ProbeResponse) { 88 | item.parse(); 89 | Name elementName; 90 | int maxSuffixLength = 0; 91 | for (const auto& subBlock : item.elements()) { 92 | if (subBlock.type() == ndn::tlv::Name) { 93 | if (!elementName.empty()) { 94 | NDN_THROW(std::runtime_error("Invalid probe format")); 95 | } 96 | elementName.wireDecode(subBlock); 97 | } 98 | else if (subBlock.type() == tlv::MaxSuffixLength) { 99 | maxSuffixLength = readNonNegativeInteger(subBlock); 100 | } 101 | else if (ndn::tlv::isCriticalType(subBlock.type())) { 102 | NDN_THROW(std::runtime_error("Unrecognized TLV Type in probe name item: " + std::to_string(subBlock.type()))); 103 | } 104 | else { 105 | //ignore 106 | } 107 | } 108 | if (elementName.empty()) { 109 | NDN_THROW(std::runtime_error("Invalid probe format")); 110 | } 111 | availableNames.emplace_back(elementName, maxSuffixLength); 112 | } 113 | else if (item.type() == tlv::ProbeRedirect) { 114 | availableRedirection.emplace_back(Name(item.blockFromValue())); 115 | } 116 | else if (ndn::tlv::isCriticalType(item.type())) { 117 | NDN_THROW(std::runtime_error("Unrecognized TLV Type: " + std::to_string(item.type()))); 118 | } 119 | else { 120 | //ignore 121 | } 122 | } 123 | } 124 | 125 | } // namespace ndncert::probetlv 126 | -------------------------------------------------------------------------------- /tests/unit-tests/challenge-pin.t.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2022, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "challenge/challenge-pin.hpp" 22 | 23 | #include "tests/boost-test.hpp" 24 | #include "tests/key-chain-fixture.hpp" 25 | 26 | namespace ndncert::tests { 27 | 28 | BOOST_FIXTURE_TEST_SUITE(TestChallengePin, KeyChainFixture) 29 | 30 | BOOST_AUTO_TEST_CASE(ChallengeType) 31 | { 32 | ChallengePin challenge; 33 | BOOST_CHECK_EQUAL(challenge.CHALLENGE_TYPE, "pin"); 34 | } 35 | 36 | BOOST_AUTO_TEST_CASE(OnChallengeRequestWithEmptyInfo) 37 | { 38 | auto identity = m_keyChain.createIdentity(Name("/ndn/site1")); 39 | auto key = identity.getDefaultKey(); 40 | auto cert = key.getDefaultCertificate(); 41 | RequestId requestId = {{101}}; 42 | ca::RequestState request; 43 | request.caPrefix = Name("/ndn/site1"); 44 | request.requestId = requestId; 45 | request.requestType = RequestType::NEW; 46 | request.cert = cert; 47 | 48 | ChallengePin challenge; 49 | challenge.handleChallengeRequest(ndn::makeEmptyBlock(tlv::EncryptedPayload), request); 50 | 51 | BOOST_CHECK(request.status == Status::CHALLENGE); 52 | BOOST_CHECK_EQUAL(request.challengeState->challengeStatus, ChallengePin::NEED_CODE); 53 | BOOST_CHECK_EQUAL(request.challengeType, "pin"); 54 | } 55 | 56 | BOOST_AUTO_TEST_CASE(OnChallengeRequestWithCode) 57 | { 58 | auto identity = m_keyChain.createIdentity(Name("/ndn/site1")); 59 | auto key = identity.getDefaultKey(); 60 | auto cert = key.getDefaultCertificate(); 61 | JsonSection secret; 62 | secret.add(ChallengePin::PARAMETER_KEY_CODE, "12345"); 63 | RequestId requestId = {{101}}; 64 | ca::RequestState request; 65 | request.caPrefix = Name("/ndn/site1"); 66 | request.requestId = requestId; 67 | request.requestType = RequestType::NEW; 68 | request.status = Status::CHALLENGE; 69 | request.cert = cert; 70 | request.challengeType = "pin"; 71 | request.challengeState = ca::ChallengeState(ChallengePin::NEED_CODE, time::system_clock::now(), 72 | 3, time::seconds(3600), std::move(secret)); 73 | 74 | Block paramTLV = ndn::makeEmptyBlock(tlv::EncryptedPayload); 75 | paramTLV.push_back(ndn::makeStringBlock(tlv::ParameterKey, ChallengePin::PARAMETER_KEY_CODE)); 76 | paramTLV.push_back(ndn::makeStringBlock(tlv::ParameterValue, "12345")); 77 | 78 | ChallengePin challenge; 79 | challenge.handleChallengeRequest(paramTLV, request); 80 | 81 | BOOST_CHECK(request.status == Status::PENDING); 82 | BOOST_CHECK(!request.challengeState); 83 | } 84 | 85 | BOOST_AUTO_TEST_CASE(OnChallengeRequestWithWrongCode) 86 | { 87 | auto identity = m_keyChain.createIdentity(Name("/ndn/site1")); 88 | auto key = identity.getDefaultKey(); 89 | auto cert = key.getDefaultCertificate(); 90 | JsonSection secret; 91 | secret.add(ChallengePin::PARAMETER_KEY_CODE, "12345"); 92 | RequestId requestId = {{101}}; 93 | ca::RequestState request; 94 | request.caPrefix = Name("/ndn/site1"); 95 | request.requestId = requestId; 96 | request.requestType = RequestType::NEW; 97 | request.status = Status::CHALLENGE; 98 | request.cert = cert; 99 | request.challengeType = "pin"; 100 | request.challengeState = ca::ChallengeState(ChallengePin::NEED_CODE, time::system_clock::now(), 101 | 3, time::seconds(3600), std::move(secret)); 102 | 103 | Block paramTLV = ndn::makeEmptyBlock(tlv::EncryptedPayload); 104 | paramTLV.push_back(ndn::makeStringBlock(tlv::ParameterKey, ChallengePin::PARAMETER_KEY_CODE)); 105 | paramTLV.push_back(ndn::makeStringBlock(tlv::ParameterValue, "45678")); 106 | 107 | ChallengePin challenge; 108 | challenge.handleChallengeRequest(paramTLV, request); 109 | 110 | BOOST_CHECK(request.status == Status::CHALLENGE); 111 | BOOST_CHECK_EQUAL(request.challengeState->challengeStatus, ChallengePin::WRONG_CODE); 112 | BOOST_CHECK_EQUAL(request.challengeState->secrets.empty(), false); 113 | } 114 | 115 | BOOST_AUTO_TEST_SUITE_END() // TestChallengePin 116 | 117 | } // namespace ndncert::tests 118 | -------------------------------------------------------------------------------- /src/detail/ca-profile.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "detail/ca-profile.hpp" 22 | #include "challenge/challenge-module.hpp" 23 | 24 | #include 25 | #include 26 | 27 | namespace ndncert { 28 | 29 | CaProfile 30 | CaProfile::fromJson(const JsonSection& json) 31 | { 32 | CaProfile profile; 33 | // CA prefix 34 | profile.caPrefix = Name(json.get(CONFIG_CA_PREFIX, "")); 35 | if (profile.caPrefix.empty()) { 36 | NDN_THROW(std::runtime_error("Cannot parse ca-prefix from the config file")); 37 | } 38 | // Forwarding hint 39 | profile.forwardingHint = Name(json.get(CONFIG_FORWARDING_HINT, "")); 40 | if (profile.forwardingHint.empty()) { 41 | profile.forwardingHint = Name(profile.caPrefix).append("CA"); 42 | } 43 | // CA info 44 | profile.caInfo = json.get(CONFIG_CA_INFO, ""); 45 | // CA max validity period 46 | profile.maxValidityPeriod = time::seconds(json.get(CONFIG_MAX_VALIDITY_PERIOD, 86400)); 47 | // CA max suffix length 48 | profile.maxSuffixLength = std::nullopt; 49 | auto maxSuffixLength = json.get_optional(CONFIG_MAX_SUFFIX_LENGTH); 50 | if (maxSuffixLength) { 51 | profile.maxSuffixLength = *maxSuffixLength; 52 | } 53 | // probe parameter keys 54 | profile.probeParameterKeys.clear(); 55 | auto probeParametersJson = json.get_child_optional(CONFIG_PROBE_PARAMETERS); 56 | if (probeParametersJson) { 57 | for (const auto& item : *probeParametersJson) { 58 | auto probeParameter = item.second.get(CONFIG_PROBE_PARAMETER, ""); 59 | probeParameter = boost::algorithm::to_lower_copy(probeParameter); 60 | if (probeParameter == "") { 61 | NDN_THROW(std::runtime_error("Probe parameter key cannot be empty.")); 62 | } 63 | profile.probeParameterKeys.push_back(probeParameter); 64 | } 65 | } 66 | // supported challenges 67 | profile.supportedChallenges.clear(); 68 | auto challengeListJson = json.get_child_optional(CONFIG_SUPPORTED_CHALLENGES); 69 | if (challengeListJson) { 70 | for (const auto& item : *challengeListJson) { 71 | auto challengeType = item.second.get(CONFIG_CHALLENGE, ""); 72 | challengeType = boost::algorithm::to_lower_copy(challengeType); 73 | if (challengeType == "") { 74 | NDN_THROW(std::runtime_error("Challenge type cannot be empty.")); 75 | } 76 | if (!ChallengeModule::isChallengeSupported(challengeType)) { 77 | NDN_THROW(std::runtime_error("Challenge " + challengeType + " is not supported.")); 78 | } 79 | profile.supportedChallenges.push_back(challengeType); 80 | } 81 | } 82 | // anchor certificate 83 | profile.cert = nullptr; 84 | auto certificateStr = json.get(CONFIG_CERTIFICATE, ""); 85 | if (!certificateStr.empty()) { 86 | std::istringstream ss(certificateStr); 87 | profile.cert = ndn::io::load(ss); 88 | } 89 | return profile; 90 | } 91 | 92 | JsonSection 93 | CaProfile::toJson() const 94 | { 95 | JsonSection caItem; 96 | caItem.put(CONFIG_CA_PREFIX, caPrefix.toUri()); 97 | caItem.put(CONFIG_CA_INFO, caInfo); 98 | caItem.put(CONFIG_MAX_VALIDITY_PERIOD, maxValidityPeriod.count()); 99 | if (maxSuffixLength) { 100 | caItem.put(CONFIG_MAX_SUFFIX_LENGTH, *maxSuffixLength); 101 | } 102 | if (!probeParameterKeys.empty()) { 103 | JsonSection probeParametersJson; 104 | for (const auto& key : probeParameterKeys) { 105 | JsonSection keyJson; 106 | keyJson.put(CONFIG_PROBE_PARAMETER, key); 107 | probeParametersJson.push_back({"", keyJson}); 108 | } 109 | caItem.add_child("", probeParametersJson); 110 | } 111 | if (!supportedChallenges.empty()) { 112 | JsonSection challengeListJson; 113 | for (const auto& challenge : supportedChallenges) { 114 | JsonSection challengeJson; 115 | challengeJson.put(CONFIG_CHALLENGE, challenge); 116 | challengeListJson.push_back({"", challengeJson}); 117 | } 118 | caItem.add_child("", challengeListJson); 119 | } 120 | if (cert != nullptr) { 121 | std::stringstream ss; 122 | ndn::io::save(*cert, ss); 123 | caItem.put("certificate", ss.str()); 124 | } 125 | return caItem; 126 | } 127 | 128 | } // namespace ndncert 129 | -------------------------------------------------------------------------------- /tests/unit-tests/challenge-possession.t.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "challenge/challenge-possession.hpp" 22 | 23 | #include "tests/boost-test.hpp" 24 | #include "tests/key-chain-fixture.hpp" 25 | 26 | #include 27 | 28 | namespace ndncert::tests { 29 | 30 | class ChallengePossessionFixture : public KeyChainFixture 31 | { 32 | public: 33 | void 34 | createTrustAnchor() 35 | { 36 | trustAnchor = m_keyChain.createIdentity("/trust").getDefaultKey().getDefaultCertificate(); 37 | challenge.parseConfigFile(); 38 | challenge.m_trustAnchors.front() = trustAnchor; 39 | } 40 | 41 | void 42 | createCertificateRequest() 43 | { 44 | state.caPrefix = "/example"; 45 | state.requestId = RequestId{{101}}; 46 | state.requestType = RequestType::NEW; 47 | state.cert = m_keyChain.createIdentity("/example").getDefaultKey().getDefaultCertificate(); 48 | } 49 | 50 | void 51 | createRequesterCredential() 52 | { 53 | auto keyB = m_keyChain.createIdentity("/trust/cert").getDefaultKey(); 54 | ndn::security::MakeCertificateOptions opts; 55 | opts.issuerId = ndn::name::Component("Credential"); 56 | opts.validity.emplace(ndn::security::ValidityPeriod::makeRelative(-1_s, 1_min)); 57 | credential = m_keyChain.makeCertificate(keyB, signingByCertificate(trustAnchor), opts); 58 | m_keyChain.addCertificate(keyB, credential); 59 | } 60 | 61 | void 62 | signCertRequest() 63 | { 64 | auto params = challenge.getRequestedParameterList(state.status, ""); 65 | ChallengePossession::fulfillParameters(params, m_keyChain, credential.getName(), std::array{}); 66 | Block paramsTlv = challenge.genChallengeRequestTLV(state.status, "", params); 67 | challenge.handleChallengeRequest(paramsTlv, state); 68 | BOOST_CHECK_EQUAL(statusToString(state.status), statusToString(Status::CHALLENGE)); 69 | BOOST_REQUIRE(state.challengeState.has_value()); 70 | BOOST_CHECK_EQUAL(state.challengeState->challengeStatus, "need-proof"); 71 | } 72 | 73 | void 74 | replyFromServer(ndn::span nonce) 75 | { 76 | auto params2 = challenge.getRequestedParameterList(state.status, state.challengeState->challengeStatus); 77 | ChallengePossession::fulfillParameters(params2, m_keyChain, credential.getName(), nonce); 78 | Block paramsTlv2 = challenge.genChallengeRequestTLV(state.status, state.challengeState->challengeStatus, params2); 79 | challenge.handleChallengeRequest(paramsTlv2, state); 80 | } 81 | 82 | public: 83 | ChallengePossession challenge{"tests/unit-tests/config-files/config-challenge-possession"}; 84 | Certificate trustAnchor; 85 | ca::RequestState state; 86 | Certificate credential; 87 | }; 88 | 89 | BOOST_FIXTURE_TEST_SUITE(TestChallengePossession, ChallengePossessionFixture) 90 | 91 | BOOST_AUTO_TEST_CASE(LoadConfig) 92 | { 93 | BOOST_CHECK_EQUAL(challenge.CHALLENGE_TYPE, "Possession"); 94 | 95 | challenge.parseConfigFile(); 96 | BOOST_CHECK_EQUAL(challenge.m_trustAnchors.size(), 1); 97 | auto cert = challenge.m_trustAnchors.front(); 98 | BOOST_CHECK_EQUAL(cert.getName(), 99 | "/ndn/site1/KEY/%11%BC%22%F4c%15%FF%17/self/%FD%00%00%01Y%C8%14%D9%A5"); 100 | } 101 | 102 | BOOST_AUTO_TEST_CASE(HandleChallengeRequest) 103 | { 104 | createTrustAnchor(); 105 | createCertificateRequest(); 106 | createRequesterCredential(); 107 | signCertRequest(); 108 | 109 | auto nonceBuf = ndn::fromHex(state.challengeState->secrets.get("nonce", "")); 110 | std::array nonce{}; 111 | memcpy(nonce.data(), nonceBuf->data(), 16); 112 | replyFromServer(nonce); 113 | BOOST_CHECK_EQUAL(statusToString(state.status), statusToString(Status::PENDING)); 114 | } 115 | 116 | BOOST_AUTO_TEST_CASE(HandleChallengeRequestProofFail) 117 | { 118 | createTrustAnchor(); 119 | createCertificateRequest(); 120 | createRequesterCredential(); 121 | signCertRequest(); 122 | 123 | std::array nonce{}; 124 | replyFromServer(nonce); 125 | BOOST_CHECK_EQUAL(statusToString(state.status), statusToString(Status::FAILURE)); 126 | } 127 | 128 | BOOST_AUTO_TEST_SUITE_END() // TestChallengePossession 129 | 130 | } // namespace ndncert::tests 131 | -------------------------------------------------------------------------------- /wscript: -------------------------------------------------------------------------------- 1 | # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- 2 | 3 | import os 4 | from waflib import Utils 5 | 6 | VERSION = '0.1.0' 7 | APPNAME = 'ndncert' 8 | 9 | def options(opt): 10 | opt.load(['compiler_cxx', 'gnu_dirs']) 11 | opt.load(['default-compiler-flags', 12 | 'coverage', 'sanitizers', 13 | 'boost', 'openssl', 'sqlite3'], 14 | tooldir=['.waf-tools']) 15 | 16 | optgrp = opt.add_option_group('ndncert Options') 17 | optgrp.add_option('--with-tests', action='store_true', default=False, 18 | help='Build unit tests') 19 | optgrp.add_option('--without-tools', action='store_false', default=True, dest='with_tools', 20 | help='Do not build tools') 21 | 22 | def configure(conf): 23 | conf.load(['compiler_cxx', 'gnu_dirs', 24 | 'default-compiler-flags', 25 | 'boost', 'openssl', 'sqlite3']) 26 | 27 | conf.env.WITH_TESTS = conf.options.with_tests 28 | conf.env.WITH_TOOLS = conf.options.with_tools 29 | 30 | # Prefer pkgconf if it's installed, because it gives more correct results 31 | # on Fedora/CentOS/RHEL/etc. See https://bugzilla.redhat.com/show_bug.cgi?id=1953348 32 | # Store the result in env.PKGCONFIG, which is the variable used inside check_cfg() 33 | conf.find_program(['pkgconf', 'pkg-config'], var='PKGCONFIG') 34 | 35 | pkg_config_path = os.environ.get('PKG_CONFIG_PATH', f'{conf.env.LIBDIR}/pkgconfig') 36 | conf.check_cfg(package='libndn-cxx', args=['libndn-cxx >= 0.8.1', '--cflags', '--libs'], 37 | uselib_store='NDN_CXX', pkg_config_path=pkg_config_path) 38 | 39 | conf.check_sqlite3() 40 | conf.check_openssl(lib='crypto', atleast_version='1.1.1') 41 | 42 | conf.check_boost() 43 | if conf.env.BOOST_VERSION_NUMBER < 107100: 44 | conf.fatal('The minimum supported version of Boost is 1.71.0.\n' 45 | 'Please upgrade your distribution or manually install a newer version of Boost.\n' 46 | 'For more information, see https://redmine.named-data.net/projects/nfd/wiki/Boost') 47 | 48 | if conf.env.WITH_TESTS: 49 | conf.check_boost(lib='unit_test_framework', mt=True, uselib_store='BOOST_TESTS') 50 | 51 | if conf.env.WITH_TOOLS: 52 | conf.check_boost(lib='program_options', mt=True, uselib_store='BOOST_TOOLS') 53 | 54 | conf.check_compiler_flags() 55 | 56 | # Loading "late" to prevent tests from being compiled with profiling flags 57 | conf.load('coverage') 58 | conf.load('sanitizers') 59 | 60 | # If there happens to be a static library, waf will put the corresponding -L flags 61 | # before dynamic library flags. This can result in compilation failure when the 62 | # system has a different version of the ndncert library installed. 63 | conf.env.prepend_value('STLIBPATH', ['.']) 64 | 65 | conf.define_cond('WITH_TESTS', conf.env.WITH_TESTS) 66 | conf.define('SYSCONFDIR', conf.env.SYSCONFDIR) 67 | # The config header will contain all defines that were added using conf.define() 68 | # or conf.define_cond(). Everything that was added directly to conf.env.DEFINES 69 | # will not appear in the config header, but will instead be passed directly to the 70 | # compiler on the command line. 71 | conf.write_config_header('src/detail/ndncert-config.hpp', define_prefix='NDNCERT_') 72 | 73 | def build(bld): 74 | bld.shlib( 75 | target='ndn-cert', 76 | name='libndn-cert', 77 | vnum=VERSION, 78 | cnum=VERSION, 79 | source=bld.path.ant_glob('src/**/*.cpp'), 80 | use='BOOST NDN_CXX OPENSSL SQLITE3', 81 | includes='src', 82 | export_includes='src') 83 | 84 | if bld.env.WITH_TESTS: 85 | bld.recurse('tests') 86 | 87 | if bld.env.WITH_TOOLS: 88 | bld.recurse('tools') 89 | 90 | # Install header files 91 | srcdir = bld.path.find_dir('src') 92 | bld.install_files('${INCLUDEDIR}/ndncert', 93 | srcdir.ant_glob('**/*.hpp'), 94 | cwd=srcdir, 95 | relative_trick=True) 96 | bld.install_files('${INCLUDEDIR}/ndncert/detail', 'src/detail/ndncert-config.hpp') 97 | 98 | # Install sample configs 99 | bld.install_files('${SYSCONFDIR}/ndncert', 100 | ['ca.conf.sample', 101 | 'client.conf.sample', 102 | 'ndncert-mail.conf.sample']) 103 | 104 | bld(features='subst', 105 | source='libndn-cert.pc.in', 106 | target='libndn-cert.pc', 107 | install_path='${LIBDIR}/pkgconfig', 108 | VERSION=VERSION) 109 | 110 | bld(features='subst', 111 | name='ndncert-send-email-challenge', 112 | source='ndncert-send-email-challenge.py', 113 | target='bin/ndncert-send-email-challenge', 114 | install_path='${BINDIR}', 115 | chmod=Utils.O755) 116 | 117 | if Utils.unversioned_sys_platform() == 'linux': 118 | bld(features='subst', 119 | name='systemd-units', 120 | source='systemd/ndncert-ca.service.in', 121 | target='systemd/ndncert-ca.service') 122 | 123 | def dist(ctx): 124 | ctx.algo = 'tar.xz' 125 | 126 | def distcheck(ctx): 127 | ctx.algo = 'tar.xz' 128 | -------------------------------------------------------------------------------- /src/detail/challenge-encoder.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "detail/challenge-encoder.hpp" 22 | 23 | namespace ndncert::challengetlv { 24 | 25 | Block 26 | encodeDataContent(ca::RequestState& request, const Name& issuedCertName, const Name& forwardingHint) 27 | { 28 | Block response(tlv::EncryptedPayload); 29 | response.push_back(ndn::makeNonNegativeIntegerBlock(tlv::Status, static_cast(request.status))); 30 | if (request.challengeState) { 31 | response.push_back(ndn::makeStringBlock(tlv::ChallengeStatus, request.challengeState->challengeStatus)); 32 | response.push_back(ndn::makeNonNegativeIntegerBlock(tlv::RemainingTries, 33 | request.challengeState->remainingTries)); 34 | response.push_back(ndn::makeNonNegativeIntegerBlock(tlv::RemainingTime, 35 | request.challengeState->remainingTime.count())); 36 | if (request.challengeState->challengeStatus == "need-proof") { 37 | response.push_back(ndn::makeStringBlock(tlv::ParameterKey, "nonce")); 38 | auto nonce = ndn::fromHex(request.challengeState->secrets.get("nonce", "")); 39 | response.push_back(ndn::makeBinaryBlock(tlv::ParameterValue, *nonce)); 40 | } 41 | } 42 | if (!issuedCertName.empty()) { 43 | response.push_back(makeNestedBlock(tlv::IssuedCertName, issuedCertName)); 44 | response.push_back(makeNestedBlock(ndn::tlv::ForwardingHint, forwardingHint)); 45 | } 46 | response.encode(); 47 | 48 | return encodeBlockWithAesGcm128(ndn::tlv::Content, request.encryptionKey.data(), 49 | response.value(), response.value_size(), 50 | request.requestId.data(), request.requestId.size(), 51 | request.encryptionIv); 52 | } 53 | 54 | void 55 | decodeDataContent(const Block& contentBlock, requester::Request& state) 56 | { 57 | auto result = decodeBlockWithAesGcm128(contentBlock, state.m_aesKey.data(), 58 | state.m_requestId.data(), state.m_requestId.size(), 59 | state.m_decryptionIv, state.m_encryptionIv); 60 | auto data = ndn::makeBinaryBlock(tlv::EncryptedPayload, result); 61 | data.parse(); 62 | 63 | int numStatus = 0; 64 | bool lookingForNonce = false; 65 | for (const auto &item : data.elements()) { 66 | if (!lookingForNonce) { 67 | switch (item.type()) { 68 | case tlv::Status: 69 | state.m_status = statusFromBlock(data.get(tlv::Status)); 70 | numStatus++; 71 | break; 72 | case tlv::ChallengeStatus: 73 | state.m_challengeStatus = readString(item); 74 | break; 75 | case tlv::RemainingTries: 76 | state.m_remainingTries = readNonNegativeInteger(item); 77 | break; 78 | case tlv::RemainingTime: 79 | state.m_freshBefore = time::system_clock::now() + 80 | time::seconds(readNonNegativeInteger(item)); 81 | break; 82 | case tlv::IssuedCertName: 83 | state.m_issuedCertName = Name(item.blockFromValue()); 84 | break; 85 | case ndn::tlv::ForwardingHint: 86 | state.m_forwardingHint = Name(item.blockFromValue()); 87 | break; 88 | case tlv::ParameterKey: 89 | if (readString(item) == "nonce") { 90 | lookingForNonce = true; 91 | } 92 | else { 93 | NDN_THROW(std::runtime_error("Unknown Parameter: " + readString(item))); 94 | } 95 | break; 96 | default: 97 | if (ndn::tlv::isCriticalType(item.type())) { 98 | NDN_THROW(std::runtime_error("Unrecognized TLV Type: " + std::to_string(item.type()))); 99 | } 100 | else { 101 | //ignore 102 | } 103 | break; 104 | } 105 | } 106 | else { 107 | if (item.type() == tlv::ParameterValue) { 108 | lookingForNonce = false; 109 | if (item.value_size() != 16) { 110 | NDN_THROW(std::runtime_error("Wrong nonce length")); 111 | } 112 | memcpy(state.m_nonce.data(), item.value(), 16); 113 | } 114 | else { 115 | NDN_THROW(std::runtime_error("Parameter Key found, but no value found")); 116 | } 117 | } 118 | } 119 | if (numStatus != 1) { 120 | NDN_THROW(std::runtime_error("number of status block is not equal to 1; there are " + 121 | std::to_string(numStatus) + " status blocks")); 122 | } 123 | } 124 | 125 | } // namespace ndncert::challengetlv 126 | -------------------------------------------------------------------------------- /tests/unit-tests/requester.t.cpp: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2017-2024, Regents of the University of California. 4 | * 5 | * This file is part of ndncert, a certificate management system based on NDN. 6 | * 7 | * ndncert is free software: you can redistribute it and/or modify it under the terms 8 | * of the GNU General Public License as published by the Free Software Foundation, either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * ndncert is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | * 15 | * You should have received copies of the GNU General Public License along with 16 | * ndncert, e.g., in COPYING.md file. If not, see . 17 | * 18 | * See AUTHORS.md for complete list of ndncert authors and contributors. 19 | */ 20 | 21 | #include "requester-request.hpp" 22 | #include "ca-module.hpp" 23 | #include "detail/error-encoder.hpp" 24 | #include "detail/probe-encoder.hpp" 25 | 26 | #include "tests/boost-test.hpp" 27 | #include "tests/io-key-chain-fixture.hpp" 28 | 29 | #include 30 | #include 31 | 32 | namespace ndncert::tests { 33 | 34 | using namespace requester; 35 | 36 | BOOST_FIXTURE_TEST_SUITE(TestRequester, IoKeyChainFixture) 37 | 38 | BOOST_AUTO_TEST_CASE(GenProbeInterest) 39 | { 40 | auto identity = m_keyChain.createIdentity(Name("/site")); 41 | auto key = identity.getDefaultKey(); 42 | auto cert = key.getDefaultCertificate(); 43 | 44 | CaProfile ca_profile; 45 | ca_profile.probeParameterKeys.push_back("email"); 46 | ca_profile.probeParameterKeys.push_back("uid"); 47 | ca_profile.probeParameterKeys.push_back("name"); 48 | ca_profile.caPrefix = Name("/site"); 49 | ca_profile.cert = std::make_shared(cert); 50 | 51 | std::multimap probeParams; 52 | probeParams.emplace("email", "zhiyi@cs.ucla.edu"); 53 | probeParams.emplace("uid", "987654321"); 54 | probeParams.emplace("name", "Zhiyi Zhang"); 55 | auto firstInterest = Request::genProbeInterest(ca_profile, std::move(probeParams)); 56 | 57 | BOOST_CHECK(firstInterest->getName().at(-1).isParametersSha256Digest()); 58 | // ignore the last name component (ParametersSha256Digest) 59 | BOOST_CHECK_EQUAL(firstInterest->getName().getPrefix(-1), "/site/CA/PROBE"); 60 | BOOST_CHECK_EQUAL(readString(firstInterest->getApplicationParameters().get(tlv::ParameterValue)), "zhiyi@cs.ucla.edu"); 61 | } 62 | 63 | BOOST_AUTO_TEST_CASE(OnProbeResponse) 64 | { 65 | auto identity = m_keyChain.createIdentity(Name("/site")); 66 | auto key = identity.getDefaultKey(); 67 | auto cert = key.getDefaultCertificate(); 68 | 69 | CaProfile ca_profile; 70 | ca_profile.probeParameterKeys.push_back("email"); 71 | ca_profile.probeParameterKeys.push_back("uid"); 72 | ca_profile.probeParameterKeys.push_back("name"); 73 | ca_profile.caPrefix = Name("/site"); 74 | ca_profile.cert = std::make_shared(cert); 75 | 76 | std::vector availableNames; 77 | availableNames.emplace_back("/site1"); 78 | availableNames.emplace_back("/site2"); 79 | 80 | m_keyChain.createIdentity(Name("/ndn")); 81 | ndn::DummyClientFace face(m_io, m_keyChain, {true, true}); 82 | ca::CaModule ca(face, m_keyChain, "tests/unit-tests/config-files/config-ca-5", "ca-storage-memory"); 83 | 84 | Data reply; 85 | reply.setName(Name("/site/CA/PROBE")); 86 | reply.setFreshnessPeriod(time::seconds(100)); 87 | { 88 | std::vector redirectionNames; 89 | for (const auto &i : ca.m_config.redirection) redirectionNames.push_back(i.first->getFullName()); 90 | reply.setContent(probetlv::encodeDataContent(availableNames, 3, redirectionNames)); 91 | } 92 | m_keyChain.sign(reply, ndn::signingByIdentity(identity)); 93 | 94 | std::vector> names; 95 | std::vector redirects; 96 | Request::onProbeResponse(reply, ca_profile, names, redirects); 97 | 98 | // Test names and redirects are properly stored 99 | BOOST_CHECK_EQUAL(names.size(), 2); 100 | BOOST_CHECK_EQUAL(names[0].first.toUri(), "/site1"); 101 | BOOST_CHECK_EQUAL(names[0].second, 3); 102 | BOOST_CHECK_EQUAL(names[1].first.toUri(), "/site2"); 103 | BOOST_CHECK_EQUAL(names[1].second, 3); 104 | 105 | BOOST_CHECK_EQUAL(redirects.size(), 2); 106 | BOOST_CHECK_EQUAL(ndn::security::extractIdentityFromCertName(redirects[0].getPrefix(-1)), "/ndn/edu/ucla"); 107 | BOOST_CHECK_EQUAL(ndn::security::extractIdentityFromCertName(redirects[1].getPrefix(-1)), "/ndn/edu/ucla/cs/irl"); 108 | } 109 | 110 | BOOST_AUTO_TEST_CASE(ErrorHandling) 111 | { 112 | auto identity = m_keyChain.createIdentity(Name("/site")); 113 | auto key = identity.getDefaultKey(); 114 | auto cert = key.getDefaultCertificate(); 115 | 116 | CaProfile item; 117 | item.caPrefix = Name("/site"); 118 | item.cert = std::make_shared(cert); 119 | Request state(m_keyChain, item, RequestType::NEW); 120 | 121 | Data errorPacket; 122 | errorPacket.setName(Name("/site/pretend/this/is/error/packet")); 123 | errorPacket.setFreshnessPeriod(time::seconds(100)); 124 | errorPacket.setContent(errortlv::encodeDataContent(ErrorCode::INVALID_PARAMETER, "This is a test.")); 125 | m_keyChain.sign(errorPacket, ndn::signingByIdentity(identity)); 126 | 127 | std::vector> ids; 128 | std::vector cas; 129 | BOOST_CHECK_THROW(Request::onProbeResponse(errorPacket, item, ids, cas), std::runtime_error); 130 | BOOST_CHECK_THROW(state.onNewRenewRevokeResponse(errorPacket), std::runtime_error); 131 | BOOST_CHECK_THROW(state.onChallengeResponse(errorPacket), std::runtime_error); 132 | } 133 | 134 | BOOST_AUTO_TEST_SUITE_END() // TestRequester 135 | 136 | } // namespace ndncert::tests 137 | --------------------------------------------------------------------------------