# # # patch "cmd_policy.cc" # from [589737cc2cd3c94bd860e20327894daa582113e9] # to [6a10d05b0c08df3b0e8220acba639e19013a0d04] # # patch "policy.cc" # from [aa2c60f1678ea1104aee12f61f8225162b3b0f6a] # to [eaabf785c3962e7eec66465ada891b8e5becdbb2] # # patch "policy.hh" # from [b089b8a6e7d898cc9ab6c7fc3bb37999ede3b456] # to [8b03d80bf7d715c67d13a387b7cd8a4982a1e81b] # # patch "project.cc" # from [4cf6ded39104d9cc951b6564c95c4a515a796c82] # to [13b39126ec8c39fc4ea9428b7092657b4f904420] # # patch "project.hh" # from [98c50e4c557f3a13563b6931e1b5c9c3bec27a3c] # to [cf47bf7a55c95d41af083cd7cb80085ed53dd987] # ============================================================ --- cmd_policy.cc 589737cc2cd3c94bd860e20327894daa582113e9 +++ cmd_policy.cc 6a10d05b0c08df3b0e8220acba639e19013a0d04 @@ -1,9 +1,11 @@ // Copyright 2008 Timothy Brownawell // // This file is made available under the GNU GPL v2 or later. #include "base.hh" +#include + #include "app_state.hh" #include "basic_io.hh" #include "botan/botan.h" @@ -19,8 +21,8 @@ CMD_GROUP(policy, "policy", "", CMD_REF( #include "transforms.hh" CMD_GROUP(policy, "policy", "", CMD_REF(__root__), - N_("Commands that deal with policy branches."), - ""); + N_("Commands that deal with policy branches."), + ""); namespace basic_io { @@ -44,8 +46,8 @@ namespace { void write_branch_policy(data & dat, - std::string const & branch_uid, - std::set const & committers) + std::string const & branch_uid, + std::set const & committers) { basic_io::printer printer; basic_io::stanza st; @@ -53,15 +55,15 @@ namespace { for (std::set::const_iterator i = committers.begin(); i != committers.end(); ++i) { - st.push_str_pair(basic_io::syms::committer, (*i)()); + st.push_str_pair(basic_io::syms::committer, (*i)()); } printer.print_stanza(st); dat = data(printer.buf); } void write_branch_policy(data & dat, - std::string const & branch_uid, - rsa_keypair_id const & committer) + std::string const & branch_uid, + rsa_keypair_id const & committer) { std::set committers; committers.insert(committer); @@ -72,10 +74,10 @@ namespace { // and put it in a new branch which is referenced by that file. void create_policy_branch(database & db, key_store & keys, - lua_hooks & lua, options & opts, - branch_prefix const & policy_name, - std::set const & administrators, - std::string & policy_uid, data & spec) + lua_hooks & lua, options & opts, + branch_prefix const & policy_name, + std::set const & administrators, + std::string & policy_uid, data & spec) { cache_user_key(opts, lua, db, keys); @@ -93,7 +95,7 @@ namespace { cs.dirs_added.insert(file_path_internal("")); cs.dirs_added.insert(file_path_internal("branches")); cs.files_added.insert(std::make_pair(file_path_internal("branches/__policy__"), - spec_id)); + spec_id)); roster_t old_roster; revision_t rev; make_revision(revision_id(), old_roster, cs, rev); @@ -106,7 +108,7 @@ namespace { // write to the db if (!db.file_version_exists(spec_id)) { - db.put_file(spec_id, spec_data); + db.put_file(spec_id, spec_data); } db.put_revision(rev_id, rdat); @@ -123,9 +125,9 @@ namespace { std::string author = opts.author(); if (author.empty()) { - if (!lua.hook_get_author(branch_name(policy_name() + ".__policy__"), - keys.signing_key, author)) - author = keys.signing_key(); + if (!lua.hook_get_author(branch_name(policy_name() + ".__policy__"), + keys.signing_key, author)) + author = keys.signing_key(); } utf8 changelog(N_("Create new policy branch.")); @@ -146,8 +148,8 @@ CMD(create_project, "create_project", "" N_(""), options::opts::none) { - N(args.size() == 1, - F("Wrong argument count.")); + if (args.size() != 1) + throw usage(execid); database db(app); key_store keys(app); @@ -157,10 +159,10 @@ CMD(create_project, "create_project", "" system_path project_file = project_dir / path_component(project_name); require_path_is_directory(app.opts.conf_dir, - F("Cannot find configuration directory."), - F("Configuration directory is a file.")); + F("Cannot find configuration directory."), + F("Configuration directory is a file.")); require_path_is_nonexistent(project_file, - F("You already have a project with that name.")); + F("You already have a project with that name.")); mkdir_p(project_dir); cache_user_key(app.opts, app.lua, db, keys); @@ -170,8 +172,8 @@ CMD(create_project, "create_project", "" std::string policy_uid; data policy_spec; create_policy_branch(db, keys, app.lua, app.opts, - branch_prefix(project_name), admin_keys, - policy_uid, policy_spec); + branch_prefix(project_name), admin_keys, + policy_uid, policy_spec); write_data(project_file, policy_spec, project_dir); P(F("Wrote project spec to %s") % project_file); @@ -183,8 +185,8 @@ CMD(create_subpolicy, "create_subpolicy" "", options::opts::none) { - N(args.size() == 1, - F("Wrong argument count.")); + if (args.size() != 1) + throw usage(execid); database db(app); key_store keys(app); @@ -236,20 +238,20 @@ CMD(create_subpolicy, "create_subpolicy" data child_spec; // Create the new policy branch. create_policy_branch(db, keys, app.lua, app.opts, - prefix, admin_keys, child_uid, child_spec); + prefix, admin_keys, child_uid, child_spec); file_id child_spec_id; file_data child_file_dat(child_spec); calculate_ident(child_file_dat, child_spec_id); // Delegate to it in the parent policy branch. policy_changes.files_added.insert(std::make_pair(delegation_file, - child_spec_id)); + child_spec_id)); revision_t policy_new_revision; make_revision(policy_old_rev_id, - policy_old_roster, - policy_changes, - policy_new_revision); + policy_old_roster, + policy_changes, + policy_new_revision); { revision_id rev_id; @@ -261,7 +263,7 @@ CMD(create_subpolicy, "create_subpolicy" // write to the db if (!db.file_version_exists(child_spec_id)) { - db.put_file(child_spec_id, child_file_dat); + db.put_file(child_spec_id, child_file_dat); } db.put_revision(rev_id, rdat); @@ -278,13 +280,14 @@ CMD(create_subpolicy, "create_subpolicy" std::string author = app.opts.author(); if (author.empty()) { - if (!app.lua.hook_get_author(branch_name(prefix() + ".__policy__"), - keys.signing_key, author)) - author = keys.signing_key(); + if (!app.lua.hook_get_author(branch_name(prefix() + ".__policy__"), + keys.signing_key, author)) + author = keys.signing_key(); } utf8 changelog(N_("Create new policy branch.")); - cert_revision_in_branch(db, keys, rev_id, branch_uid(policy_policy.branch_cert_value)); + cert_revision_in_branch(db, keys, rev_id, + branch_uid(policy_policy.branch_cert_value)); cert_revision_changelog(db, keys, rev_id, changelog); cert_revision_date_time(db, keys, rev_id, date); cert_revision_author(db, keys, rev_id, author); @@ -295,8 +298,170 @@ CMD(create_branch, "create_branch", "", CMD(create_branch, "create_branch", "", CMD_REF(policy), N_("NAME"), - N_("Create a new branch."), + N_("Create a new branch, attached to the nearest subpolicy."), "", options::opts::none) { + if (args.size() != 1) + throw usage(execid); + + database db(app); + key_store keys(app); + project_set projects(db, app.lua, app.opts); + branch_name branch(idx(args, 0)()); + + branch_policy parent_policy; + branch_prefix parent_prefix; + project_t * const project = projects.maybe_get_project_of_branch(branch); + N(project != NULL, F("Cannot find project for %s") % branch); + E(project->get_policy_branch_policy_of(branch, parent_policy, parent_prefix), + F("Cannot find a parent policy for %s") % branch); + P(F("Parent policy: %s") % parent_prefix); + + I(branch().find(parent_prefix()) == 0); + std::string relative_name = branch().substr(parent_prefix().size()); + if (relative_name.size() > 0 && relative_name[0] == '.') + relative_name.erase(0, 1); + if (relative_name.empty()) + relative_name = "__main__"; + + + std::set policy_heads; + get_branch_heads(parent_policy, false, db, policy_heads, NULL); + N(policy_heads.size() == 1, + F("Parent policy branch has %n heads, should have 1") % policy_heads.size()); + revision_id policy_old_rev_id(*policy_heads.begin()); + roster_t policy_old_roster; + db.get_roster(policy_old_rev_id, policy_old_roster); + file_path branch_dir = file_path_internal("branches"); + file_path branch_file = branch_dir / path_component(relative_name); + N(!policy_old_roster.has_node(branch_file), + F("A branch %s already exists under policy %s") + % relative_name % parent_prefix); + + cset policy_changes; + if (!policy_old_roster.has_node(branch_dir)) + { + policy_changes.dirs_added.insert(branch_dir); + } + + cache_user_key(app.opts, app.lua, db, keys); + std::set admin_keys; + admin_keys.insert(keys.signing_key); + + std::string branch_uid = generate_uid(); + data branch_spec; + write_branch_policy(branch_spec, branch_uid, admin_keys); + + + file_id branch_spec_id; + file_data branch_spec_dat(branch_spec); + calculate_ident(branch_spec_dat, branch_spec_id); + + policy_changes.files_added.insert(std::make_pair(branch_file, branch_spec_id)); + + revision_t policy_new_revision; + make_revision(policy_old_rev_id, + policy_old_roster, + policy_changes, + policy_new_revision); + + revision_id rev_id; + calculate_ident(policy_new_revision, rev_id); + revision_data rdat; + write_revision(policy_new_revision, rdat); + + + transaction_guard guard(db); + + if (!db.file_version_exists(branch_spec_id)) + db.put_file(branch_spec_id, branch_spec_dat); + db.put_revision(rev_id, rdat); + + // project_t::put_standard_certs would translate the branch name, + // which wouldn't work + date_t date; + if (app.opts.date_given) + date = app.opts.date; + else + date = date_t::now(); + + std::string author = app.opts.author(); + if (author.empty()) + { + if (!app.lua.hook_get_author(branch_name(parent_prefix() + ".__policy"), + keys.signing_key, author)) + author = keys.signing_key(); + } + utf8 changelog(N_("Declare new branch.")); + + cert_revision_in_branch(db, keys, rev_id, + parent_policy.branch_cert_value); + cert_revision_changelog(db, keys, rev_id, changelog); + cert_revision_date_time(db, keys, rev_id, date); + cert_revision_author(db, keys, rev_id, author); + + guard.commit(); } + +CMD_FWD_DECL(list); + +void list_policy(project_t const & proj, branch_prefix const & prefix, bool recursive) +{ + std::cout< subpolicies; + proj.get_subpolicies(prefix, subpolicies); + for (std::set::const_iterator i = subpolicies.begin(); + i != subpolicies.end(); ++i) + { + list_policy(proj, *i, recursive); + } + } +} + +CMD(policies, "policies", "", CMD_REF(list), + N_("PREFIX [...]"), + N_("List policies"), + N_("List subpolicies of the given policy prefixes, or toplevel projects\n" + "if no arguments are provided."), + options::opts::recursive) +{ + database db(app); + key_store keys(app); + project_set projects(db, app.lua, app.opts); + + if (args.empty()) + { + project_set::project_map const & project_list = projects.all_projects(); + for (project_set::project_map::const_iterator i = project_list.begin(); + i != project_list.end(); ++i) + { + list_policy(i->second, i->first, app.opts.recursive); + } + } + else + { + for (args_vector::const_iterator i = args.begin(); + i != args.end(); ++i) + { + branch_name const bn((*i)()); + branch_prefix const bp((*i)()); + project_t * const project = projects.maybe_get_project_of_branch(bn); + N(project != NULL, F("Cannot find a project for %s") % *i); + N(project->policy_exists(bp), + F("Policy %s does not exist.") % *i); + list_policy(*project, bp, app.opts.recursive); + } + } +} + + +// Local Variables: +// mode: C++ +// fill-column: 76 +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s: ============================================================ --- policy.cc aa2c60f1678ea1104aee12f61f8225162b3b0f6a +++ policy.cc eaabf785c3962e7eec66465ada891b8e5becdbb2 @@ -413,7 +413,7 @@ map policy_b } -bool +policy_revision const * policy_branch::get_nearest_policy(branch_name const & name, branch_policy & policy_policy, branch_prefix & policy_prefix, @@ -421,7 +421,7 @@ policy_branch::get_nearest_policy(branch { shared_ptr policy = get_policy(); if (!policy) - return false; + return NULL; policy_policy = branch_policy(branch_name(), my_branch_cert_value, @@ -430,7 +430,7 @@ policy_branch::get_nearest_policy(branch prefix()); } -bool +policy_revision const * policy_revision::get_nearest_policy(branch_name const & name, branch_policy & policy_policy, branch_prefix & policy_prefix, @@ -449,9 +449,20 @@ policy_revision::get_nearest_policy(bran } } policy_prefix = branch_prefix(accumulated_prefix); - return true; + return this; } +void +policy_revision::get_delegation_names(std::set & names) const +{ + names.clear(); + for (std::map::const_iterator i = delegations.begin(); + i != delegations.end(); ++i) + { + names.insert(i->first); + } +} + // Local Variables: // mode: C++ // fill-column: 76 ============================================================ --- policy.hh b089b8a6e7d898cc9ab6c7fc3bb37999ede3b456 +++ policy.hh 8b03d80bf7d715c67d13a387b7cd8a4982a1e81b @@ -96,7 +96,7 @@ public: boost::shared_ptr maybe_get_branch_policy(branch_name const & name); - bool + policy_revision const * get_nearest_policy(branch_name const & name, branch_policy & policy_policy, branch_prefix & policy_prefix, @@ -113,7 +113,9 @@ public: branch_prefix const & prefix); std::map all_branches(); - bool + void get_delegation_names(std::set & names) const; + + policy_revision const * get_nearest_policy(branch_name const & name, branch_policy & policy_policy, branch_prefix & policy_prefix, ============================================================ --- project.cc 4cf6ded39104d9cc951b6564c95c4a515a796c82 +++ project.cc 13b39126ec8c39fc4ea9428b7092657b4f904420 @@ -75,10 +75,43 @@ project_t::get_policy_branch_policy_of(b return project_policy->policy.get_nearest_policy(name, policy_branch_policy, policy_prefix, - acc); + acc) != NULL; } +bool +project_t::policy_exists(branch_prefix const & name) const +{ + if (project_policy->passthru) + return name().empty(); + + branch_policy pol; + branch_prefix prefix; + std::string tmp; + bool got = project_policy->policy.get_nearest_policy(branch_name(name()), + pol, prefix, tmp) != NULL; + return got && prefix() == name(); +} + void +project_t::get_subpolicies(branch_prefix const & name, + std::set & names) const +{ + if (project_policy->passthru) + return; + + branch_policy pol; + branch_prefix prefix; + std::string tmp; + policy_revision const * pr = + project_policy->policy.get_nearest_policy(branch_name(name()), + pol, prefix, tmp); + if (pr != NULL) + { + pr->get_delegation_names(names); + } +} + +void project_t::get_branch_list(std::set & names, bool check_heads) { @@ -597,6 +630,12 @@ project_set::project_set(database & db, } } +project_set::project_map const & +project_set::all_projects() const +{ + return projects; +} + project_t & project_set::get_project(branch_prefix const & name) { @@ -633,7 +672,7 @@ project_set::maybe_get_project_of_branch if (i->first() == "") return &i->second; std::string pre = i->first() + "."; - if (branch().substr(0, pre.size()) == pre) + if (branch().substr(0, pre.size()) == pre || branch() == i->first()) return &i->second; } return NULL; ============================================================ --- project.hh 98c50e4c557f3a13563b6931e1b5c9c3bec27a3c +++ project.hh cf47bf7a55c95d41af083cd7cb80085ed53dd987 @@ -66,6 +66,9 @@ public: bool get_policy_branch_policy_of(branch_name const & name, branch_policy & policy_branch_policy, branch_prefix & policy_prefix); + bool policy_exists(branch_prefix const & name) const; + void get_subpolicies(branch_prefix const & name, + std::set & names) const; void get_branch_list(std::set & names, bool check_heads = false); @@ -134,9 +137,9 @@ public: { public: database & db; + typedef std::map project_map; private: - typedef std::map project_map; project_map projects; public: @@ -144,6 +147,8 @@ public: lua_hooks & lua, options & opts); + project_map const & all_projects() const; + // Get a named project. project_t & get_project(branch_prefix const & name); project_t * maybe_get_project(branch_prefix const & name);