Skip to content

Commit

Permalink
Merge pull request #17 from dwd/nato-clearances
Browse files Browse the repository at this point in the history
Nato clearances
  • Loading branch information
dwd authored Jan 31, 2017
2 parents 2a6f2a0 + 88f1d01 commit 3f1e1a9
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 56 deletions.
2 changes: 1 addition & 1 deletion deps/rapidxml
Submodule rapidxml updated 1 files
+20 −4 rapidxml.hpp
5 changes: 4 additions & 1 deletion include/spiffing/clearance.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,12 @@ namespace Spiffing {
void addCategory(std::shared_ptr<Category> const & cat);
private:
void parse_xml(std::string const &);
void parse_xml_debug(std::string const &);
void parse_xml_nato(std::string const &);
void parse_ber(std::string const &);
void parse_any(std::string const &);
void write_xml(std::string &) const;
void write_xml_debug(std::string &) const;
void write_xml_nato(std::string &) const;
void write_ber(std::string &) const;

std::shared_ptr<Spif> m_policy;
Expand Down
251 changes: 198 additions & 53 deletions src/clearance.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@ void Spiffing::Clearance::write(Spiffing::Format fmt, std::string & output) cons
write_ber(output);
break;
case Spiffing::Format::XML:
write_xml(output);
write_xml_debug(output);
break;
case Spiffing::Format::NATO:
write_xml_nato(output);
break;
case Spiffing::Format::ANY:
throw std::runtime_error("Unknown format");
}
Expand Down Expand Up @@ -131,61 +134,141 @@ bool Spiffing::Clearance::hasCategory(std::set<CategoryRef> const & cats) const
return false;
}

void Spiffing::Clearance::parse_xml(std::string const & clearance) {
using namespace rapidxml;
std::string tmp{clearance};
xml_document<> doc;
doc.parse<0>(const_cast<char *>(tmp.c_str()));
auto root = doc.first_node();
if (std::string("clearance") != root->name()) {
throw std::runtime_error("Not a clearance");
void Spiffing::Clearance::parse_xml_debug(std::string const & clearance) {
using namespace rapidxml;
std::string tmp{clearance};
xml_document<> doc;
doc.parse<0>(const_cast<char *>(tmp.c_str()));
auto root = doc.first_node();
if (std::string("clearance") != root->name()) {
throw std::runtime_error("Not a clearance");
}
if (root->xmlns() == nullptr ||
std::string("http://surevine.com/xmlns/spiffy") != root->xmlns()) {
throw std::runtime_error("XML Namespace of clearance is unknown");
}
// Get security policy.
auto securityPolicy = root->first_node("policy");
if (securityPolicy) {
auto idattr = securityPolicy->first_attribute("id");
if (idattr) m_policy_id = idattr->value();
m_policy = Site::site().spif(m_policy_id);
if (m_policy->policy_id() != m_policy_id) {
throw std::runtime_error("Policy mismatch: " + m_policy_id);
}
if (root->xmlns() == nullptr ||
std::string("http://surevine.com/xmlns/spiffy") != root->xmlns()) {
throw std::runtime_error("XML Namespace of clearance is unknown");
} else throw std::runtime_error("No policy in clearance");
// Get classification.
for (auto securityClassification = root->first_node("classification"); securityClassification; securityClassification = securityClassification->next_sibling("classification")) {
auto lacvattr = securityClassification->first_attribute("lacv");
if (lacvattr) {
lacv_t lacv = std::stoull(lacvattr->value());
m_classList.insert(lacv);
}
// Get security policy.
auto securityPolicy = root->first_node("policy");
if (securityPolicy) {
auto idattr = securityPolicy->first_attribute("id");
if (idattr) m_policy_id = idattr->value();
m_policy = Site::site().spif(m_policy_id);
if (m_policy->policy_id() != m_policy_id) {
throw std::runtime_error("Policy mismatch: " + m_policy_id);
}
} else throw std::runtime_error("No policy in clearance");
// Get classification.
for(auto securityClassification = root->first_node("classification"); securityClassification; securityClassification = securityClassification->next_sibling("classification")) {
auto lacvattr = securityClassification->first_attribute("lacv");
if (lacvattr) {
lacv_t lacv = std::stoull(lacvattr->value());
m_classList.insert(lacv);
}
}
// Find tagsets.
for (auto tag = root->first_node("tag"); tag; tag = tag->next_sibling("tag")) {
auto typeattr = tag->first_attribute("type");
if (!typeattr) throw std::runtime_error("tag without type");
std::string tag_type = typeattr->value();
Spiffing::TagType type;
if (tag_type == "restrictive") {
type = Spiffing::TagType::restrictive;
} else if (tag_type == "permissive") {
type = Spiffing::TagType::permissive;
} else if (tag_type == "enumeratedPermissive") {
type = Spiffing::TagType::enumeratedPermissive;
} else if (tag_type == "enumeratedRestrictive") {
type = Spiffing::TagType::enumeratedRestrictive;
} else throw std::runtime_error("unsupported tag type " + tag_type);
auto idattr = tag->first_attribute("id");
if (!idattr) throw std::runtime_error("tag without id");
std::string id = idattr->value();
auto lacvattr = tag->first_attribute("lacv");
if (!lacvattr) throw std::runtime_error("tag without lacv");
Spiffing::Lacv lacv = Spiffing::Lacv::parse(std::string(lacvattr->value(), lacvattr->value_size()));
auto cat = m_policy->tagSetLookup(id)->categoryLookup(type, lacv);
addCategory(cat);
}
}


void Spiffing::Clearance::parse_xml(std::string const & label) {
using namespace rapidxml;
std::string tmp{label};
xml_document<> doc;
doc.parse<parse_fastest>(const_cast<char *>(tmp.c_str()));
auto root = doc.first_node();
if (root->xmlns() == nullptr) {
throw std::runtime_error("XML Namespace of label is unknown");
}
std::string xmlns{root->xmlns(), root->xmlns_size()};
if (xmlns == "http://surevine.com/xmlns/spiffy") {
parse_xml_debug(label);
} else if (xmlns == "urn:nato:stanag:4774:confidentialityclearance:1:0") {
parse_xml_nato(label);
} else {
throw std::runtime_error("Namespace not found");
}
}

void Spiffing::Clearance::parse_xml_nato(std::string const & clearance) {
using namespace rapidxml;
std::string tmp{clearance};
char const * slab{"urn:nato:stanag:4774:confidentialitymetadatalabel:1:0"};
xml_document<> doc;
doc.parse<0>(const_cast<char *>(tmp.c_str()));
auto root = doc.first_node();
if (std::string("ConfidentialityClearance") != root->name()) {
throw std::runtime_error("Not a clearance");
}
if (root->xmlns() == nullptr ||
std::string("urn:nato:stanag:4774:confidentialityclearance:1:0") != root->xmlns()) {
throw std::runtime_error("XML Namespace of clearance is unknown");
}
// Get security policy.
auto securityPolicy = root->first_node("PolicyIdentifier", slab);
if (securityPolicy) {
auto idattr = securityPolicy->first_attribute("URI");
if (idattr) m_policy_id = idattr->value();
if (m_policy_id.find("urn:oid:") == 0) {
m_policy_id = m_policy_id.substr(8);
} else {
m_policy_id = "";
}
m_policy = Site::site().spif_by_name(securityPolicy->value());
if (m_policy_id.empty()) m_policy_id = m_policy->policy_id();
if (m_policy->policy_id() != m_policy_id) {
throw std::runtime_error("Policy mismatch: " + m_policy_id);
}
// Find tagsets.
for (auto tag = root->first_node("tag"); tag; tag = tag->next_sibling("tag")) {
auto typeattr = tag->first_attribute("type");
if (!typeattr) throw std::runtime_error("tag without type");
std::string tag_type = typeattr->value();
Spiffing::TagType type;
if (tag_type == "restrictive") {
type = Spiffing::TagType::restrictive;
} else if (tag_type == "permissive") {
type = Spiffing::TagType::permissive;
} else if (tag_type == "enumeratedPermissive") {
type = Spiffing::TagType::enumeratedPermissive;
} else if (tag_type == "enumeratedRestrictive") {
type = Spiffing::TagType::enumeratedRestrictive;
} else throw std::runtime_error("unsupported tag type " + tag_type);
auto idattr = tag->first_attribute("id");
if (!idattr) throw std::runtime_error("tag without id");
std::string id = idattr->value();
auto lacvattr = tag->first_attribute("lacv");
if (!lacvattr) throw std::runtime_error("tag without lacv");
Spiffing::Lacv lacv = Spiffing::Lacv::parse(std::string(lacvattr->value(), lacvattr->value_size()));
auto cat = m_policy->tagSetLookup(id)->categoryLookup(type, lacv);
addCategory(cat);
} else throw std::runtime_error("No policy in clearance");
// Get classification list.
auto classList = root->first_node("ClassificationList");
for(auto securityClassification = classList->first_node("Classification", slab); securityClassification; securityClassification = securityClassification->next_sibling("Classification", slab)) {
auto classn = m_policy->classificationLookup(securityClassification->value());
if (classn) {
m_classList.insert(classn->lacv());
}
}
// Find tagsets.
for (auto tag = root->first_node("Category", slab); tag; tag = tag->next_sibling("Category", slab)) {
auto typeattr = tag->first_attribute("Type");
if (!typeattr) throw std::runtime_error("tag without Type");
std::string tag_type = typeattr->value();
TagType type;
if (tag_type == "RESTRICTIVE") {
type = TagType::restrictive;
} else if (tag_type == "PERMISSIVE") {
type = TagType::permissive;
} else throw std::runtime_error("unsupported tag type " + tag_type);
auto tagname_a = tag->first_attribute("TagName");
if (!tagname_a) throw std::runtime_error("Category without TagName");
std::string tagname = tagname_a->value();
auto tagSet = m_policy->tagSetLookupByName(tagname);
for (auto valtag = tag->first_node("GenericValue"); valtag; valtag = valtag->next_sibling("GenericValue")) {
auto cat = tagSet->categoryLookup(type, valtag->value());
addCategory(cat);
}
}
}

void Spiffing::Clearance::parse_any(std::string const & clearance) {
Expand All @@ -199,7 +282,7 @@ void Spiffing::Clearance::parse_any(std::string const & clearance) {
parse_xml(clearance);
}

void Spiffing::Clearance::write_xml(std::string & output) const {
void Spiffing::Clearance::write_xml_debug(std::string & output) const {
using namespace rapidxml;
// Do something sensible.
xml_document<> doc;
Expand Down Expand Up @@ -247,6 +330,68 @@ void Spiffing::Clearance::write_xml(std::string & output) const {
}


void Spiffing::Clearance::write_xml_nato(std::string & output) const {
using namespace rapidxml;
const char * slab = "urn:nato:stanag:4774:confidentialitymetadatalabel:1:0";
// Do something sensible.
xml_document<> doc;
auto root = doc.allocate_node(node_element, "ConfidentialityClearance");
root->append_attribute(doc.allocate_attribute("xmlns", "urn:nato:stanag:4774:confidentialityclearance:1:0"));
auto policy = doc.allocate_node(node_element, "PolicyIdentifier");
policy->append_attribute(doc.allocate_attribute("xmlns", slab));
std::string policy_uri{"urn:oid:" + m_policy_id};
policy->append_attribute(doc.allocate_attribute("URI", policy_uri.c_str()));
policy->value(m_policy->name().c_str());
root->append_node(policy);
auto classList = doc.allocate_node(node_element, "ClassificationList");
for (auto lacv : m_classList) {
auto classn = doc.allocate_node(node_element, "Classification");
auto cls = m_policy->classificationLookup(lacv);
classn->append_attribute(doc.allocate_attribute("xmlns", slab));
classn->value(cls->name().c_str());
classList->append_node(classn);
}
root->append_node(classList);
// Category Encoding
std::string tagset_id;
TagType tagType = TagType::informative; // Dummy
xml_node<> * tag = nullptr;
for (auto const & cat : m_cats) {
if (cat->tag().tagSet().id() != tagset_id
|| cat->tag().tagType() != tagType) {
tagset_id = cat->tag().tagSet().id();
tagType = cat->tag().tagType();
tag = doc.allocate_node(node_element, "Category");
tag->append_attribute(doc.allocate_attribute("xmlns", slab));
const char *p = nullptr;
switch (cat->tag().tagType()) {
case TagType::enumeratedRestrictive:
case TagType::restrictive:
p = "RESTRICTIVE";
break;
case TagType::enumeratedPermissive:
case TagType::permissive:
p = "PERMISSIVE";
break;
default:
throw std::runtime_error("Tagtype unimplemented!");
}
tag->append_attribute(doc.allocate_attribute("Type", p));
// Note: needs a temp string.
// tag->append_attribute(doc.allocate_attribute("URI", "urn:oid:" + cat->tag().tagSet().id().c_str()));
tag->append_attribute(doc.allocate_attribute("TagName", cat->tag().tagSet().name().c_str()));
root->append_node(tag);
}
auto catval = doc.allocate_node(node_element, "GenericValue");
catval->value(cat->name().c_str());
assert(tag);
tag->append_node(catval);
}
doc.append_node(root);
rapidxml::print(std::back_inserter(output), doc, rapidxml::print_no_indenting);
}


void Spiffing::Clearance::write_ber(std::string & output) const {
Asn<Clearance_t> asn_clearance(&asn_DEF_Clearance);
asn_clearance.alloc();
Expand Down
26 changes: 25 additions & 1 deletion test-data/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
EXECUTOR?=

INPUTS=$(wildcard food-label*.xml) $(wildcard food-clearance*.xml)
OUTPUTS=$(INPUTS:%.xml=%-nato-out2.ber) $(INPUTS:%.xml=%-missi-out2.ber)
NATO_INPUTS=$(wildcard nato-clearance*.nato)
OUTPUTS=$(INPUTS:%.xml=%-nato-out2.ber) $(INPUTS:%.xml=%-nato-out2.nato) $(INPUTS:%.xml=%-missi-out2.ber)
OUTPUTS+= $(NATO_INPUTS:%.nato=%-nato-out2.ber)

all:
$(EXECUTOR) ../test tests.xml
Expand All @@ -15,6 +17,13 @@ food-label-%-nato-out2.ber: food-label-%.xml
diff $@ $*-nato-out.ber
rm $*-nato-out.ber $*-nato-out.xml

food-label-%-nato-out2.nato: food-label-%.xml
$(EXECUTOR) ../transpifferizer -p food-policy.xml $< $*-nato-out.nato
$(EXECUTOR) ../transpifferizer -p food-policy.xml $*-nato-out.nato $*-nato-out.xml
$(EXECUTOR) ../transpifferizer -p food-policy.xml $*-nato-out.xml $@
diff $@ $*-nato-out.nato
rm $*-nato-out.nato $*-nato-out.xml

food-label-%-missi-out2.ber: food-label-%.xml
$(EXECUTOR) ../transpifferizer -p food-policy-missi.xml $< $*-missi-out.ber
$(EXECUTOR) ../transpifferizer -p food-policy-missi.xml $*-missi-out.ber $*-missi-out.xml
Expand All @@ -29,6 +38,21 @@ food-clearance-%-nato-out2.ber: food-clearance-%.xml
diff $@ $*-nato-out.ber
rm $*-nato-out.ber $*-nato-out.xml

food-clearance-%-nato-out2.nato: food-clearance-%.xml
$(EXECUTOR) ../transpifferizer -p food-policy.xml -c $< $*-nato-out.nato
$(EXECUTOR) ../transpifferizer -p food-policy.xml -c $*-nato-out.nato $*-nato-out.xml
$(EXECUTOR) ../transpifferizer -p food-policy.xml -c $*-nato-out.xml $@
diff $@ $*-nato-out.nato
rm $*-nato-out.nato $*-nato-out.xml

nato-clearance-%-nato-out2.ber: nato-clearance-%.nato
$(EXECUTOR) ../transpifferizer -p nato-4774-policy.xml -c $< $*-nato-out.ber
$(EXECUTOR) ../transpifferizer -p nato-4774-policy.xml -c $*-nato-out.ber $*-nato-out.xml
$(EXECUTOR) ../transpifferizer -p nato-4774-policy.xml -c $*-nato-out.xml $*-nato-out.nato
$(EXECUTOR) ../transpifferizer -p nato-4774-policy.xml -c $*-nato-out.nato $@
diff $@ $*-nato-out.ber
rm $*-nato-out.nato $*-nato-out.ber $*-nato-out.xml

food-clearance-%-missi-out2.ber: food-clearance-%.xml
$(EXECUTOR) ../transpifferizer -p food-policy-missi.xml -c $< $*-missi-out.ber
$(EXECUTOR) ../transpifferizer -p food-policy-missi.xml -c $*-missi-out.ber $*-missi-out.xml
Expand Down

0 comments on commit 3f1e1a9

Please sign in to comment.