BOOST_FIXTURE_TEST_CASE(Exemption, CommandInterestFixture) { KeyChain keyChain; Name identity("/TestCommandInterest/AnyKey"); Name certName; BOOST_REQUIRE_NO_THROW(certName = keyChain.createIdentity(identity)); CommandInterestGenerator generator; CommandInterestValidator validator; validator.addInterestBypassRule("^<TestCommandInterest><Exemption>"); //Test a legitimate command shared_ptr<Interest> commandInterest1 = make_shared<Interest>("/TestCommandInterest/Exemption/Command1"); generator.generateWithIdentity(*commandInterest1, identity); validator.validate(*commandInterest1, bind(&CommandInterestFixture::validated, this, _1), bind(&CommandInterestFixture::validationFailed, this, _1, _2)); BOOST_CHECK_EQUAL(m_validity, true); BOOST_CHECK_NO_THROW(keyChain.deleteIdentity(identity)); }
int ndnsec_cert_gen(int argc, char** argv) { using boost::tokenizer; using boost::escaped_list_separator; using namespace ndn; using namespace ndn::time; namespace po = boost::program_options; std::string notBeforeStr; std::string notAfterStr; std::string subjectName; std::string requestFile("-"); std::string signId; std::string subjectInfo; std::string certPrefix; bool hasSignId = false; po::options_description description( "General Usage\n" " ndnsec cert-gen [-h] [-S date] [-E date] [-N subject-name] [-I subject-info] " "[-s sign-id] [-p cert-prefix] request\n" "General options"); description.add_options() ("help,h", "produce help message") ("not-before,S", po::value<std::string>(¬BeforeStr), "certificate starting date, YYYYMMDDhhmmss") ("not-after,E", po::value<std::string>(¬AfterStr), "certificate ending date, YYYYMMDDhhmmss") ("subject-name,N", po::value<std::string>(&subjectName), "subject name") ("subject-info,I", po::value<std::string>(&subjectInfo), "subject info, pairs of OID and string description: " "\"2.5.4.10 'University of California, Los Angeles'\"") ("sign-id,s", po::value<std::string>(&signId), "signing Identity, system default identity if not specified") ("cert-prefix,p", po::value<std::string>(&certPrefix), "cert prefix, which is the part of certificate name before " "KEY component") ("request,r", po::value<std::string>(&requestFile), "request file name, - for stdin") ; po::positional_options_description p; p.add("request", 1); po::variables_map vm; try { po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm); po::notify(vm); } catch (const std::exception& e) { std::cerr << "ERROR: " << e.what() << std::endl; return 1; } if (vm.count("help") != 0) { std::cerr << description << std::endl; return 0; } if (vm.count("sign-id") != 0) { hasSignId = true; } if (vm.count("subject-name") == 0) { std::cerr << "subject_name must be specified" << std::endl; return 1; } std::vector<CertificateSubjectDescription> subjectDescription; subjectDescription.push_back(CertificateSubjectDescription(oid::ATTRIBUTE_NAME, subjectName)); tokenizer<escaped_list_separator<char> > subjectInfoItems (subjectInfo, escaped_list_separator<char>("\\", " \t", "'\"")); tokenizer<escaped_list_separator<char> >::iterator it = subjectInfoItems.begin(); while (it != subjectInfoItems.end()) { std::string oid = *it; it++; if (it == subjectInfoItems.end()) { std::cerr << "ERROR: unmatched info for oid [" << oid << "]" << std::endl; return 1; } std::string value = *it; subjectDescription.push_back(CertificateSubjectDescription(OID(oid), value)); it++; } system_clock::TimePoint notBefore; system_clock::TimePoint notAfter; if (vm.count("not-before") == 0) { notBefore = system_clock::now(); } else { notBefore = fromIsoString(notBeforeStr.substr(0, 8) + "T" + notBeforeStr.substr(8, 6)); } if (vm.count("not-after") == 0) { notAfter = notBefore + days(365); } else { notAfter = fromIsoString(notAfterStr.substr(0, 8) + "T" + notAfterStr.substr(8, 6)); if (notAfter < notBefore) { std::cerr << "not-before is later than not-after" << std::endl; return 1; } } if (vm.count("request") == 0) { std::cerr << "request file must be specified" << std::endl; return 1; } shared_ptr<IdentityCertificate> selfSignedCertificate = getIdentityCertificate(requestFile); if (!static_cast<bool>(selfSignedCertificate)) { std::cerr << "ERROR: input error" << std::endl; return 1; } KeyChain keyChain; Name keyName = selfSignedCertificate->getPublicKeyName(); Name signIdName; Name prefix(certPrefix); if (!hasSignId) signIdName = keyChain.getDefaultIdentity(); else signIdName = Name(signId); shared_ptr<IdentityCertificate> certificate = keyChain.prepareUnsignedIdentityCertificate(keyName, selfSignedCertificate->getPublicKeyInfo(), signIdName, notBefore, notAfter, subjectDescription, prefix); if (!static_cast<bool>(certificate)) { std::cerr << "ERROR: key name is not formated correctly or does not match certificate name." << std::endl; return 1; } keyChain.createIdentity(signIdName); Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(signIdName); keyChain.sign(*certificate, signingCertificateName); Block wire = certificate->wireEncode(); try { using namespace CryptoPP; StringSource ss(wire.wire(), wire.size(), true, new Base64Encoder(new FileSink(std::cout), true, 64)); } catch (const CryptoPP::Exception& e) { std::cerr << "ERROR: " << e.what() << std::endl; return 1; } return 0; }
int ndnsec_cert_gen(int argc, char** argv) { using boost::tokenizer; using boost::escaped_list_separator; using namespace ndn; using namespace ndn::time; namespace po = boost::program_options; std::string notBeforeStr; std::string notAfterStr; std::string subjectName; std::string requestFile("-"); std::string signId; std::string subjectInfo; bool hasSignId = false; bool isNack = false; po::options_description description("General Usage\n ndnsec cert-gen [-h] [-S date] [-E date] [-N subject-name] [-I subject-info] [-s sign-id] request\nGeneral options"); description.add_options() ("help,h", "produce help message") ("not-before,S", po::value<std::string>(¬BeforeStr), "certificate starting date, YYYYMMDDhhmmss") ("not-after,E", po::value<std::string>(¬AfterStr), "certificate ending date, YYYYMMDDhhmmss") ("subject-name,N", po::value<std::string>(&subjectName), "subject name") ("subject-info,I", po::value<std::string>(&subjectInfo), "subject info, pairs of OID and string description: \"2.5.4.10 'University of California, Los Angeles'\"") ("nack", "Generate revocation certificate (NACK)") ("sign-id,s", po::value<std::string>(&signId), "signing Identity, system default identity if not specified") ("request,r", po::value<std::string>(&requestFile), "request file name, - for stdin") ; po::positional_options_description p; p.add("request", 1); po::variables_map vm; try { po::store(po::command_line_parser(argc, argv).options(description).positional(p).run(), vm); po::notify(vm); } catch (const std::exception& e) { std::cerr << "ERROR: " << e.what() << std::endl; return 1; } if (vm.count("help") != 0) { std::cerr << description << std::endl; return 0; } if (vm.count("sign-id") != 0) { hasSignId = true; } if (vm.count("nack") != 0) { isNack = true; } std::vector<CertificateSubjectDescription> otherSubDescrypt; tokenizer<escaped_list_separator<char> > subjectInfoItems (subjectInfo, escaped_list_separator<char> ("\\", " \t", "'\"")); tokenizer<escaped_list_separator<char> >::iterator it = subjectInfoItems.begin(); while (it != subjectInfoItems.end()) { std::string oid = *it; it++; if (it == subjectInfoItems.end()) { std::cerr << "ERROR: unmatched info for oid [" << oid << "]" << std::endl; return 1; } std::string value = *it; otherSubDescrypt.push_back(CertificateSubjectDescription(oid, value)); it++; } system_clock::TimePoint notBefore; system_clock::TimePoint notAfter; if (vm.count("not-before") == 0) { notBefore = system_clock::now(); } else { notBefore = fromIsoString(notBeforeStr.substr(0, 8) + "T" + notBeforeStr.substr(8, 6)); } if (vm.count("not-after") == 0) { notAfter = notBefore + days(365); } else { notAfter = fromIsoString(notAfterStr.substr(0, 8) + "T" + notAfterStr.substr(8, 6)); if (notAfter < notBefore) { std::cerr << "not-before is later than not-after" << std::endl; return 1; } } if (vm.count("request") == 0) { std::cerr << "request file must be specified" << std::endl; return 1; } shared_ptr<IdentityCertificate> selfSignedCertificate = getIdentityCertificate(requestFile); if (!static_cast<bool>(selfSignedCertificate)) { std::cerr << "ERROR: input error" << std::endl; return 1; } KeyChain keyChain; Name keyName = selfSignedCertificate->getPublicKeyName(); Name signIdName; Name certName; if (!hasSignId) signIdName = keyChain.getDefaultIdentity(); else signIdName = Name(signId); if (signIdName.isPrefixOf(keyName)) { // if signee's namespace is a sub-namespace of signer, for example, signer's namespace is // /ndn/test, signee's namespace is /ndn/test/alice, the generated certificate name is // /ndn/test/KEY/alice/ksk-1234/ID-CERT/%01%02 certName.append(signIdName) .append("KEY") .append(keyName.getSubName(signIdName.size())) .append("ID-CERT") .appendVersion(); } else { // if signee's namespace is not a sub-namespace of signer, for example, signer's namespace is // /ndn/test, signee's namespace is /ndn/ucla/bob, the generated certificate name is // /ndn/ucla/bob/KEY/ksk-1234/ID-CERT/%01%02 certName.append(keyName.getPrefix(-1)) .append("KEY") .append(keyName.get(-1)) .append("ID-CERT") .appendVersion(); } Block wire; if (!isNack) { if (vm.count("subject-name") == 0) { std::cerr << "subject_name must be specified" << std::endl; return 1; } CertificateSubjectDescription subDescryptName("2.5.4.41", subjectName); IdentityCertificate certificate; certificate.setName(certName); certificate.setNotBefore(notBefore); certificate.setNotAfter(notAfter); certificate.setPublicKeyInfo(selfSignedCertificate->getPublicKeyInfo()); certificate.addSubjectDescription(subDescryptName); for (size_t i = 0; i < otherSubDescrypt.size(); i++) certificate.addSubjectDescription(otherSubDescrypt[i]); certificate.encode(); keyChain.createIdentity(signIdName); Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(signIdName); keyChain.sign(certificate, signingCertificateName); wire = certificate.wireEncode(); } else { Data revocationCert; // revocationCert.setContent(void*, 0); // empty content revocationCert.setName(certName); keyChain.createIdentity(signIdName); Name signingCertificateName = keyChain.getDefaultCertificateNameForIdentity(signIdName); keyChain.sign(revocationCert, signingCertificateName); wire = revocationCert.wireEncode(); } try { using namespace CryptoPP; StringSource ss(wire.wire(), wire.size(), true, new Base64Encoder(new FileSink(std::cout), true, 64)); } catch (const CryptoPP::Exception& e) { std::cerr << "ERROR: " << e.what() << std::endl; return 1; } return 0; }
BOOST_FIXTURE_TEST_CASE(CommandInterest, CommandInterestFixture) { KeyChain keyChain; Name identity("/TestCommandInterest/Validation"); identity.appendVersion(); Name certName; BOOST_REQUIRE_NO_THROW(certName = keyChain.createIdentity(identity)); CommandInterestGenerator generator; CommandInterestValidator validator; validator.addInterestRule("^<TestCommandInterest><Validation>", *keyChain.getCertificate(certName)); //Test a legitimate command shared_ptr<Interest> commandInterest1 = make_shared<Interest>("/TestCommandInterest/Validation/Command1"); generator.generateWithIdentity(*commandInterest1, identity); validator.validate(*commandInterest1, bind(&CommandInterestFixture::validated, this, _1), bind(&CommandInterestFixture::validationFailed, this, _1, _2)); BOOST_CHECK_EQUAL(m_validity, true); //Test an outdated command reset(); shared_ptr<Interest> commandInterest2 = make_shared<Interest>("/TestCommandInterest/Validation/Command2"); time::milliseconds timestamp = time::toUnixTimestamp(time::system_clock::now()); timestamp -= time::seconds(5); Name commandName = commandInterest2->getName(); commandName .appendNumber(timestamp.count()) .appendNumber(random::generateWord64()); commandInterest2->setName(commandName); keyChain.signByIdentity(*commandInterest2, identity); validator.validate(*commandInterest2, bind(&CommandInterestFixture::validated, this, _1), bind(&CommandInterestFixture::validationFailed, this, _1, _2)); BOOST_CHECK_EQUAL(m_validity, false); //Test an unauthorized command Name identity2("/TestCommandInterest/Validation2"); Name certName2; BOOST_REQUIRE_NO_THROW(certName2 = keyChain.createIdentity(identity2)); shared_ptr<Interest> commandInterest3 = make_shared<Interest>("/TestCommandInterest/Validation/Command3"); generator.generateWithIdentity(*commandInterest3, identity2); validator.validate(*commandInterest3, bind(&CommandInterestFixture::validated, this, _1), bind(&CommandInterestFixture::validationFailed, this, _1, _2)); BOOST_CHECK_EQUAL(m_validity, false); //Test another unauthorized command shared_ptr<Interest> commandInterest4 = make_shared<Interest>("/TestCommandInterest/Validation2/Command"); generator.generateWithIdentity(*commandInterest4, identity); validator.validate(*commandInterest4, bind(&CommandInterestFixture::validated, this, _1), bind(&CommandInterestFixture::validationFailed, this, _1, _2)); BOOST_CHECK_EQUAL(m_validity, false); BOOST_CHECK_NO_THROW(keyChain.deleteIdentity(identity)); BOOST_CHECK_NO_THROW(keyChain.deleteIdentity(identity2)); }