static void list_keys_retract(OrmConn conn, int sockfd, const char *datastore) { #define LOG_AND_RETURN(errmsg)\ do{ods_log_error_and_printf(sockfd,module_str,errmsg);return;}while(0) // List the keys with retract flags. ods_printf(sockfd, "Database set to: %s\n" "Retract Keys:\n" "Zone: " "Key role: " "Id: " "\n" ,datastore ); OrmTransaction transaction(conn); if (!transaction.started()) LOG_AND_RETURN("transaction not started"); { OrmResultRef rows; ::ods::keystate::EnforcerZone enfzone; if (!OrmMessageEnum(conn,enfzone.descriptor(),rows)) LOG_AND_RETURN("zone enumeration failed"); for (bool next=OrmFirst(rows); next; next=OrmNext(rows)) { if (!OrmGetMessage(rows, enfzone, /*zones + keys*/true)) LOG_AND_RETURN("retrieving zone from database failed"); for (int k=0; k<enfzone.keys_size(); ++k) { const ::ods::keystate::KeyData &key = enfzone.keys(k); // Don't suggest ZSKs can be retracted, don't show them if (key.role() == ::ods::keystate::ZSK) continue; // Only show keys that have the retract flag set. if (key.ds_at_parent()!=::ods::keystate::retract) continue; std::string keyrole = keyrole_Name(key.role()); ods_printf(sockfd, "%-31s %-13s %-40s\n", enfzone.name().c_str(), keyrole.c_str(), key.locator().c_str() ); } } } #undef LOG_AND_RETURN }
int handled_policy_import_cmd(int sockfd, engine_type* engine, const char *cmd, ssize_t n) { const char *scmd = "policy import"; cmd = ods_check_command(cmd,n,scmd); if (!cmd) return 0; // not handled ods_log_debug("[%s] %s command", module_str, scmd); time_t tstart = time(NULL); /* perform_policy_import(sockfd, engine->config); */ perform_update_kasp(sockfd, engine->config); //TODO: Need error checking so we only do this if the update succeeds perform_hsmkey_gen(sockfd, engine->config, 0 /* automatic */, engine->config->automatic_keygen_duration); flush_all_tasks(sockfd, engine); ods_printf(sockfd,"%s completed in %ld seconds.\n",scmd,time(NULL)-tstart); return 1; }
void help_keystate_list_cmd(int sockfd) { ods_printf(sockfd, "key list list all the keys used by a zone\n" // " --verbose (aka -v) also show the id for every key.\n" ); }
int handled_zone_del_cmd(int sockfd, engine_type* engine, const char *cmd, ssize_t n) { const char *scmd = "zone delete"; cmd = ods_check_command(cmd,n,scmd); if (!cmd) return 0; // not handled ods_log_debug("[%s] %s command", module_str, scmd); std::string zone; int need_write_xml = 0; if (!get_arguments(sockfd,cmd,zone, need_write_xml)) { help_zone_del_cmd(sockfd); return 1; } time_t tstart = time(NULL); perform_zone_del(sockfd,engine->config, zone.c_str(), need_write_xml, false); ods_printf(sockfd,"%s completed in %ld seconds.\n",scmd,time(NULL)-tstart); return 1; }
int handled_keystate_list_cmd(int sockfd, engine_type* engine, const char *cmd, ssize_t n) { char buf[ODS_SE_MAXLINE]; const char *argv[8]; const int NARGV = sizeof(argv)/sizeof(char*); int argc; const char *scmd = "key list"; cmd = ods_check_command(cmd,n,scmd); if (!cmd) return 0; // not handled ods_log_debug("[%s] %s command", module_str, scmd); // Use buf as an intermediate buffer for the command. strncpy(buf,cmd,sizeof(buf)); buf[sizeof(buf)-1] = '\0'; // separate the arguments argc = ods_str_explode(buf,NARGV,argv); if (argc > NARGV) { ods_log_warning("[%s] too many arguments for %s command", module_str,scmd); ods_printf(sockfd,"too many arguments\n"); help_keystate_list_cmd(sockfd); return 1; // errors, but handled } bool bVerbose = ods_find_arg(&argc,argv,"verbose","v") != -1; bool bDebug = ods_find_arg(&argc,argv,"debug","d") != -1; if (argc) { ods_log_warning("[%s] unknown arguments for %s command", module_str,scmd); ods_printf(sockfd,"unknown arguments\n"); help_keystate_list_cmd(sockfd); return 1; // errors, but handled } time_t tstart = time(NULL); perform_keystate_list(sockfd, engine->config, bVerbose, bDebug); ods_printf(sockfd,"%s completed in %ld seconds.\n",scmd,time(NULL)-tstart); return 1; }
int handled_update_all_cmd(int sockfd, engine_type* engine, const char *cmd, ssize_t n) { const char *scmd = "update all"; cmd = ods_check_command(cmd,n,scmd); if (!cmd) return 0; // not handled ods_log_debug("[%s] %s command", module_str, scmd); // check that we are using a compatible protobuf version. GOOGLE_PROTOBUF_VERIFY_VERSION; time_t tstart = time(NULL); autostart(engine); /* Check all files for errors. The perform_update_*() * functions check as well but this gives us all or nothing. * Plus we get a complete check of the files mentioned in the * conf which need not be the same as the files in use by the * running enforcer!*/ char *kasp = NULL; char *zonelist = NULL; char **replist = NULL; int repcount, i; int error = 1; if (check_conf(engine->config->cfg_filename, &kasp, &zonelist, &replist, &repcount, 0)) ods_log_error_and_printf(sockfd, module_str, "Unable to validate '%s' consistency.", engine->config->cfg_filename); else if (check_kasp(kasp, replist, repcount, 0)) ods_log_error_and_printf(sockfd, module_str, "Unable to validate '%s' consistency.", kasp); else if (check_zonelist(zonelist, 0)) ods_log_error_and_printf(sockfd, module_str, "Unable to validate '%s' consistency.", zonelist); else error = 0; free(kasp); free(zonelist); if (replist) { for (i = 0; i < repcount; i++) free(replist[i]); } if (!error) error |= perform_update_repositorylist(sockfd, engine); if (!error) error |= perform_update_kasp(sockfd, engine->config); if (!error) error |= perform_update_keyzones(sockfd, engine->config); if (!error) { perform_update_hsmkeys(sockfd, engine->config, 0 /* automatic */); perform_hsmkey_gen(sockfd, engine->config, 0 /* automatic */, engine->config->automatic_keygen_duration); flush_all_tasks(sockfd, engine); } ods_printf(sockfd, "%s completed in %ld seconds.\n",scmd,time(NULL)-tstart); return 1; }
void help_policy_resalt_cmd(int sockfd) { ods_printf(sockfd, "policy resalt Generate new NSEC3 salts for policies that have salts\n" " older than the resalt duration.\n" ); }
void help_keystate_list_cmd(int sockfd) { ods_printf(sockfd, "key list List the keys in the enforcer database.\n" " [--verbose] (aka -v) also show additional key parameters.\n" " [--debug] (aka -d) print information about the keystate.\n" ); }
void help_zone_del_cmd(int sockfd) { ods_printf(sockfd, "zone delete Delete zones from the enforcer database.\n" " --zone <zone> | --all (aka -z | -a) zone, or delete all zones.\n" " [--xml] (aka -u) update zonelist.xml.\n" ); }
void help_zone_del_cmd(int sockfd) { ods_printf(sockfd, "zone del delete zones\n" " --zone <zone> (aka -z) the zone to delete\n" " --force (aka -f) additional flag to " "indicate you really mean it\n" ); }
void help_keystate_ds_seen_cmd(int sockfd) { ods_printf(sockfd, "key ds-seen Issue a ds-seen to the enforcer for a KSK.\n" " (This command with no parameters lists eligible keys.)\n" " --zone <zone> (aka -z) zone.\n" " --cka_id <CKA_ID> (aka -k) cka_id <CKA_ID> of the key.\n" " --keytag <keytag> (aka -x) keytag <keytag> of the key.\n" ); }
int handled_zone_list_cmd(int sockfd, engine_type* engine, const char *cmd, ssize_t n) { const char *scmd = "zone list"; cmd = ods_check_command(cmd,n,scmd); if (!cmd) return 0; // not handled ods_log_debug("[%s] %s command", module_str, scmd); time_t tstart = time(NULL); perform_zone_list(sockfd,engine->config); ods_printf(sockfd,"%s completed in %ld seconds.\n",scmd,time(NULL)-tstart); return 1; }
void perform_update_hsmkeys(int sockfd, engineconfig_type *config, int bManual) { // check that we are using a compatible protobuf version. GOOGLE_PROTOBUF_VERIFY_VERSION; OrmConnRef conn; if (!ods_orm_connect(sockfd, config, conn)) return; // errors have already been reported. // Go through all the keys in HSMs and import them if they are // not already present if (bManual) { ods_printf(sockfd, "Database set to: %s\n", config->datastore); // DEPRECATED, key state import should selectively import keys. import_all_keys_from_all_hsms(sockfd,conn); } }
/* Delete any policies with no zones */ int handled_policy_purge_cmd(int sockfd, engine_type* engine, const char *cmd, ssize_t n){ const char *scmd = "policy purge"; cmd = ods_check_command(cmd,n,scmd); if (!cmd) return 0; // not handled // TODO: Should we require a confirmation here? ods_log_debug("[%s] %s command", module_str, scmd); time_t tstart = time(NULL); perform_policy_purge(sockfd, engine->config); ods_printf(sockfd, "%s completed in %ld seconds.\n",scmd,time(NULL)-tstart); return 1; }
void help_policy_purge_cmd(int sockfd){ ods_printf(sockfd, "policy purge Delete any policies with no zones and update kasp.xml. \n"); }
void help_zone_list_cmd(int sockfd) { ods_printf(sockfd,"zone list list zones\n"); }
void perform_keystate_export(int sockfd, engineconfig_type *config, const char *zone, int bds) { #define LOG_AND_RETURN(errmsg) do { ods_log_error_and_printf(\ sockfd,module_str,errmsg); return; } while (0) #define LOG_AND_RETURN_1(errmsg,param) do { ods_log_error_and_printf(\ sockfd,module_str,errmsg,param); return; } while (0) GOOGLE_PROTOBUF_VERIFY_VERSION; OrmConnRef conn; if (!ods_orm_connect(sockfd, config, conn)) return; // error already reported. { OrmTransactionRW transaction(conn); if (!transaction.started()) LOG_AND_RETURN("transaction not started"); std::string qzone; if (!OrmQuoteStringValue(conn, std::string(zone), qzone)) LOG_AND_RETURN("quoting string value failed"); { OrmResultRef rows; ::ods::keystate::EnforcerZone enfzone; if (!OrmMessageEnumWhere(conn,enfzone.descriptor(), rows,"name = %s",qzone.c_str())) LOG_AND_RETURN("zone enumeration failed"); if (!OrmFirst(rows)) { ods_printf(sockfd,"zone %s not found\n",zone); return; } OrmContextRef context; if (!OrmGetMessage(rows, enfzone, /*zones + keys*/true, context)) LOG_AND_RETURN("retrieving zone from database failed"); // we no longer need the query result, so release it. rows.release(); // Retrieve the dnskey ttl from the policy associated with the zone. ::ods::kasp::Policy policy; if (!load_kasp_policy(conn, enfzone.policy(), policy)) LOG_AND_RETURN_1("policy %s not found",enfzone.policy().c_str()); uint32_t dnskey_ttl = policy.keys().ttl(); bool bSubmitChanged = false; bool bRetractChanged = false; bool bKeytagChanged = false; for (int k=0; k<enfzone.keys_size(); ++k) { const ::ods::keystate::KeyData &key = enfzone.keys(k); if (key.role()==::ods::keystate::ZSK) continue; if (key.ds_at_parent()!=::ods::keystate::submit && key.ds_at_parent()!=::ods::keystate::submitted && key.ds_at_parent()!=::ods::keystate::retract && key.ds_at_parent()!=::ods::keystate::retracted ) continue; std::string dnskey; uint16_t keytag = dnskey_from_id(dnskey,key.locator().c_str(), key.role(), enfzone.name().c_str(), key.algorithm(),bds, dnskey_ttl); if (keytag) { ods_writen(sockfd, dnskey.c_str(), dnskey.size()); bSubmitChanged = key.ds_at_parent()==::ods::keystate::submit; bRetractChanged = key.ds_at_parent()==::ods::keystate::retract; bKeytagChanged = key.keytag()!=keytag; if (bSubmitChanged) { ::ods::keystate::KeyData *kd = enfzone.mutable_keys(k); kd->set_ds_at_parent(::ods::keystate::submitted); } if (bRetractChanged) { ::ods::keystate::KeyData *kd = enfzone.mutable_keys(k); kd->set_ds_at_parent(::ods::keystate::retracted); } if (bKeytagChanged) { ::ods::keystate::KeyData *kd = enfzone.mutable_keys(k); kd->set_keytag(keytag); } } else LOG_AND_RETURN_1("unable to find key with id %s", key.locator().c_str()); } if (bSubmitChanged || bRetractChanged || bKeytagChanged) { // Update the zone recursively in the database as keystates // have been changed because of the export if (!OrmMessageUpdate(context)) LOG_AND_RETURN("updating zone in the database failed"); if (!transaction.commit()) LOG_AND_RETURN("committing zone to the database failed"); } } } }
static void import_all_keys_from_all_hsms(int sockfd, OrmConn conn) { hsm_ctx_t * hsm_ctx = hsm_create_context(); if (!hsm_ctx) { ods_log_error_and_printf(sockfd, module_str, "could not connect to HSM"); return; } size_t nkeys; hsm_key_t **kl = hsm_list_keys(hsm_ctx, &nkeys); if (!kl) { ods_log_error_and_printf(sockfd, module_str, "could not list hsm keys"); return; } ods_printf(sockfd, "HSM keys:\n" " " "Algorithm: " "Bits: " "Id: " "\n" ); OrmTransactionRW transaction(conn); if (!transaction.started()) { ods_log_error_and_printf(sockfd, module_str, "could not start database transaction"); hsm_key_list_free(kl,nkeys); hsm_destroy_context(hsm_ctx); return; } for (int i=0; i<nkeys; ++i) { hsm_key_t *k = kl[i]; hsm_key_info_t *kinf = hsm_get_key_info(hsm_ctx,k); OrmResultRef result; if (!OrmMessageEnumWhere(conn, ::ods::hsmkey::HsmKey::descriptor(), result, "locator='%s'",kinf->id)) { // free allocated resources hsm_key_info_free(kinf); ods_log_error_and_printf(sockfd, module_str, "database query failed"); break; } if (OrmFirst(result)) { // Key already exists ::ods::hsmkey::HsmKey key; OrmContextRef context; if (!OrmGetMessage(result,key,true,context)) { // free allocated resources hsm_key_info_free(kinf); // release query result, we don't need it anymore. result.release(); // This is an unexpected error ! ods_log_error_and_printf(sockfd, module_str, "database record retrieval failed"); break; } else { // release query result, we don't need it anymore. result.release(); // retrieved the key from the database // Change key settings based on information from HSM key info if (key.key_type() == std::string(kinf->algorithm_name) || key.repository() == std::string(k->module->name)) { // key in the table does NOT need updating. } else { // key in the table needs updating. key.set_key_type( kinf->algorithm_name ); key.set_repository( k->module->name ); if (!OrmMessageUpdate(context)) { // This is an unexpected error ! ods_log_error_and_printf(sockfd, module_str, "database record retrieval failed"); } else { ods_printf(sockfd, "%-7s %-10s %-7ld %-40s\n", "update", kinf->algorithm_name, kinf->keysize, kinf->id ); } } // release the context, we don't need it anymore. context.release(); } } else { // release query result, we don't need it anymore. result.release(); // key does not exist ::ods::hsmkey::HsmKey key; key.set_locator(kinf->id); key.set_bits(kinf->keysize); key.set_key_type( kinf->algorithm_name ); key.set_repository( k->module->name ); // verify that according to the proto file definition the key is // fully initialized. if(!key.IsInitialized()) { // free allocated resources hsm_key_info_free(kinf); ods_log_error_and_printf(sockfd, module_str, "new HsmKey missing required fields"); break; } pb::uint64 keyid; if (!OrmMessageInsert(conn, key, keyid)) { // free allocated resources hsm_key_info_free(kinf); // This is an unexpected error ! ods_log_error_and_printf(sockfd, module_str, "database record insertion failed"); break; } else { // Key was inserted successfully ods_printf(sockfd, "%-7s %-10s %-7ld %-40s\n", "import", kinf->algorithm_name, kinf->keysize, kinf->id ); } } hsm_key_info_free(kinf); } hsm_key_list_free(kl,nkeys); hsm_destroy_context(hsm_ctx); }
static bool retract_dnskey_by_id(int sockfd, const char *ds_retract_command, const char *id, ::ods::keystate::keyrole role, const char *zone, int algorithm) { /* Code to output the DNSKEY record (stolen from hsmutil) */ hsm_ctx_t *hsm_ctx = hsm_create_context(); if (!hsm_ctx) { ods_log_error_and_printf(sockfd, module_str, "could not connect to HSM"); return false; } hsm_key_t *key = hsm_find_key_by_id(hsm_ctx, id); if (!key) { ods_log_error_and_printf(sockfd, module_str, "key %s not found in any HSM", id); hsm_destroy_context(hsm_ctx); return false; } bool bOK = false; char *dnskey_rr_str; hsm_sign_params_t *sign_params = hsm_sign_params_new(); sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone); sign_params->algorithm = (ldns_algorithm)algorithm; sign_params->flags = LDNS_KEY_ZONE_KEY; sign_params->flags += LDNS_KEY_SEP_KEY; /*KSK=>SEP*/ ldns_rr *dnskey_rr = hsm_get_dnskey(hsm_ctx, key, sign_params); #if 0 ldns_rr_print(stdout, dnskey_rr); #endif dnskey_rr_str = ldns_rr2str(dnskey_rr); hsm_sign_params_free(sign_params); ldns_rr_free(dnskey_rr); hsm_key_free(key); /* Replace tab with white-space */ for (int i = 0; dnskey_rr_str[i]; ++i) { if (dnskey_rr_str[i] == '\t') { dnskey_rr_str[i] = ' '; } } /* We need to strip off trailing comments before we send to any clients that might be listening */ for (int i = 0; dnskey_rr_str[i]; ++i) { if (dnskey_rr_str[i] == ';') { dnskey_rr_str[i] = '\n'; dnskey_rr_str[i+1] = '\0'; break; } } // pass the dnskey rr string to a configured // delegation signer retract program. if (ds_retract_command && ds_retract_command[0] != '\0') { /* send records to the configured command */ FILE *fp = popen(ds_retract_command, "w"); if (fp == NULL) { ods_log_error_and_printf(sockfd, module_str, "failed to run command: %s: %s", ds_retract_command, strerror(errno)); } else { int bytes_written = fprintf(fp, "%s", dnskey_rr_str); if (bytes_written < 0) { ods_log_error_and_printf(sockfd, module_str, "[%s] Failed to write to %s: %s", ds_retract_command, strerror(errno)); } else { if (pclose(fp) == -1) { ods_log_error_and_printf(sockfd, module_str, "failed to close %s: %s", ds_retract_command, strerror(errno)); } else { bOK = true; ods_printf(sockfd, "key %s retracted by %s\n", id, ds_retract_command); } } } } else { ods_log_error_and_printf(sockfd, module_str, "no \"DelegationSignerRetractCommand\" binary " "configured in conf.xml."); } LDNS_FREE(dnskey_rr_str); hsm_destroy_context(hsm_ctx); return bOK; }
int handled_keystate_ds_seen_cmd(int sockfd, engine_type* engine, const char *cmd, ssize_t n) { char buf[ODS_SE_MAXLINE]; const char *argv[8]; const int NARGV = sizeof(argv)/sizeof(char*); int argc; const char *scmd = "key ds-seen"; cmd = ods_check_command(cmd,n,scmd); if (!cmd) return 0; // not handled ods_log_debug("[%s] %s command", module_str, scmd); // Use buf as an intermediate buffer for the command. strncpy(buf,cmd,sizeof(buf)); buf[sizeof(buf)-1] = '\0'; // separate the arguments argc = ods_str_explode(buf,NARGV,argv); if (argc > NARGV) { ods_log_warning("[%s] too many arguments for %s command", module_str,scmd); ods_printf(sockfd,"too many arguments\n"); return 1; // errors, but handled } const char *zone = NULL; const char *cka_id = NULL; const char *keytag = NULL; (void)ods_find_arg_and_param(&argc,argv,"zone","z",&zone); (void)ods_find_arg_and_param(&argc,argv,"cka_id","k",&cka_id); (void)ods_find_arg_and_param(&argc,argv,"keytag","x",&keytag); // Check for unknown parameters on the command line if (argc) { ods_log_warning("[%s] unknown arguments for %s command", module_str,scmd); ods_printf(sockfd,"unknown arguments\n"); help_keystate_ds_seen_cmd(sockfd); return 1; // errors, but handled } // Check for too many parameters on the command line if (argc > NARGV) { ods_log_warning("[%s] too many arguments for %s command", module_str,scmd); ods_printf(sockfd,"too many arguments\n"); help_keystate_ds_seen_cmd(sockfd); return 1; // errors, but handled } // Either no option or combi of zone & cka_id or zone & keytag needs to be // present. But not both cka_id and keytag uint16_t nkeytag = 0; if (zone || cka_id || keytag) { if (!zone) { ods_log_warning("[%s] expected option --zone <zone> for %s command", module_str,scmd); ods_printf(sockfd,"expected --zone <zone> option\n"); help_keystate_ds_seen_cmd(sockfd); return 1; // errors, but handled } if (!cka_id && !keytag) { ods_log_warning("[%s] expected option --cka_id <cka_id> or " "--keytag <keytag> for %s command", module_str,scmd); ods_printf(sockfd,"expected --cka_id <cka_id> or " "--keytag <keytag> option\n"); help_keystate_ds_seen_cmd(sockfd); return 1; // errors, but handled } else { if (cka_id && keytag) { ods_log_warning("[%s] both --cka_id <cka_id> and --keytag <keytag> given, " "please only specify one for %s command", module_str,scmd); ods_printf(sockfd, "both --cka_id <cka_id> and --keytag <keytag> given, " "please only specify one\n"); help_keystate_ds_seen_cmd(sockfd); return 1; // errors, but handled } } if (keytag) { int kt = atoi(keytag); if (kt<=0 || kt>=65536) { ods_log_warning("[%s] value \"%s\" for --keytag is invalid", module_str,keytag); ods_printf(sockfd, "value \"%s\" for --keytag is invalid\n", keytag); return 1; // errors, but handled } nkeytag = (uint16_t )kt; } } time_t tstart = time(NULL); perform_keystate_ds_seen(sockfd,engine->config,zone,cka_id,nkeytag); ods_printf(sockfd,"%s completed in %ld seconds.\n",scmd,time(NULL)-tstart); flush_enforce_task(engine); return 1; }
static void retract_keys(OrmConn conn, int sockfd, const char *zone, const char *id, const char *datastore, const char *ds_retract_command) { #define LOG_AND_RETURN(errmsg)\ do{ods_log_error_and_printf(sockfd,module_str,errmsg);return;}while(0) #define LOG_AND_RETURN_1(errmsg,p)\ do{ods_log_error_and_printf(sockfd,module_str,errmsg,p);return;}while(0) OrmTransactionRW transaction(conn); if (!transaction.started()) LOG_AND_RETURN("transaction not started"); { OrmResultRef rows; ::ods::keystate::EnforcerZone enfzone; if (zone) { std::string qzone; if (!OrmQuoteStringValue(conn, std::string(zone), qzone)) LOG_AND_RETURN("quoting string value failed"); if (!OrmMessageEnumWhere(conn,enfzone.descriptor(), rows,"name = %s",qzone.c_str())) LOG_AND_RETURN("zone enumeration failed"); } else { if (!OrmMessageEnum(conn,enfzone.descriptor(),rows)) LOG_AND_RETURN("zone enumeration failed"); } bool bZonesModified = false; if (!OrmFirst(rows)) { if (zone) LOG_AND_RETURN_1("zone %s not found",zone); } else { for (bool next=true; next; next=OrmNext(rows)) { OrmContextRef context; if (!OrmGetMessage(rows, enfzone, /*zones + keys*/true, context)) LOG_AND_RETURN("retrieving zone from database failed"); // Try to change the state of a specific 'retract' key to 'retracted'. bool bKeyModified = false; for (int k=0; k<enfzone.keys_size(); ++k) { const ::ods::keystate::KeyData &key = enfzone.keys(k); // Don't retract ZSKs from the parent. if (key.role()==::ods::keystate::ZSK) continue; // Only retract KSKs that have the retract flag set. if (key.ds_at_parent()!=::ods::keystate::retract) continue; if (id) { // --id <id> // Force retract key to the parent for specific key id. if (key.locator()==id) { // retract key with this id from the parent if (retract_dnskey_by_id(sockfd,ds_retract_command, key.locator().c_str(), key.role(), enfzone.name().c_str(), key.algorithm())) { ::ods::keystate::KeyData *kd = enfzone.mutable_keys(k); kd->set_ds_at_parent(::ods::keystate::retracted); bKeyModified = true; } } } else { if (zone) { // --zone <zone> // Force retract key from the parent for specific zone. if (enfzone.name()==zone) { // retract key for this zone from the parent if (retract_dnskey_by_id(sockfd,ds_retract_command, key.locator().c_str(), key.role(), enfzone.name().c_str(), key.algorithm())) { ::ods::keystate::KeyData *kd = enfzone.mutable_keys(k); kd->set_ds_at_parent(::ods::keystate::retracted); bKeyModified = true; } } } else { // --auto // Retract all keys from the parent that have // the retract flag set. if (retract_dnskey_by_id(sockfd,ds_retract_command, key.locator().c_str(), key.role(), enfzone.name().c_str(), key.algorithm())) { ::ods::keystate::KeyData *kd = enfzone.mutable_keys(k); kd->set_ds_at_parent(::ods::keystate::retracted); bKeyModified = true; } } } } if (bKeyModified) { if (!OrmMessageUpdate(context)) LOG_AND_RETURN_1("failed to update zone %s in the database", enfzone.name().c_str()); bZonesModified = true; } } // we no longer need the query result, so release it. rows.release(); } // Report back the status of the operation. if (bZonesModified) { // Commit updated records to the database. if (!transaction.commit()) LOG_AND_RETURN_1("unable to commit updated zone %s to the database",zone); ods_log_debug("[%s] key states have been updated",module_str); ods_printf(sockfd,"update of key states completed.\n"); } else { ods_log_debug("[%s] key states are unchanged",module_str); if (id) ods_printf(sockfd, "No key state changes for id \"%s\"\n", id); else if (zone) ods_printf(sockfd, "No key state changes for zone \"%s\"\n", zone); else ods_printf(sockfd,"key states are unchanged\n"); } } #undef LOG_AND_RETURN #undef LOG_AND_RETURN_1 }
void perform_keystate_list(int sockfd, engineconfig_type *config, int bverbose) { GOOGLE_PROTOBUF_VERIFY_VERSION; OrmConnRef conn; if (!ods_orm_connect(sockfd, config, conn)) return; // error already reported. { OrmTransaction transaction(conn); if (!transaction.started()) { ods_log_error("[%s] Could not start database transaction", module_str); ods_printf(sockfd, "error: Could not start database transaction\n"); return; } ::ods::keystate::EnforcerZone zone; { OrmResultRef rows; if (!OrmMessageEnum(conn, zone.descriptor(),rows)) { ods_log_error("[%s] error enumerating zones", module_str); ods_printf(sockfd, "error enumerating zones\n"); return; } ods_printf(sockfd, "Database set to: %s\n" "Keys:\n" "Zone: " "Key role: " "DS: " "DNSKEY: " "RRSIGDNSKEY: " "RRSIG: " "Pub: " "Act: " "Id:" "\n" ,config->datastore ); for (bool next=OrmFirst(rows); next; next=OrmNext(rows)) { if (!OrmGetMessage(rows, zone, true)) { ods_log_error("[%s] error reading zone", module_str); ods_printf(sockfd, "error reading zone\n"); return; } for (int k=0; k<zone.keys_size(); ++k) { const ::ods::keystate::KeyData &key = zone.keys(k); std::string keyrole = keyrole_Name(key.role()); std::string ds_rrstate = rrstate_Name(key.ds().state()); std::string dnskey_rrstate = rrstate_Name(key.dnskey().state()); std::string rrsigdnskey_rrstate = rrstate_Name(key.rrsigdnskey().state()); std::string rrsig_rrstate = rrstate_Name(key.rrsig().state()); ods_printf(sockfd, "%-31s %-13s %-12s %-12s %-12s %-12s %d %4d %s\n", zone.name().c_str(), keyrole.c_str(), ds_rrstate.c_str(), dnskey_rrstate.c_str(), rrsigdnskey_rrstate.c_str(), rrsig_rrstate.c_str(), key.publish(), key.active_ksk()||key.active_zsk(), key.locator().c_str() ); } } } } }
void help_policy_import_cmd(int sockfd) { ods_printf(sockfd, "policy import Import policies from kasp.xml into the enforcer database.\n"); }
static bool retract_dnskey_by_id(int sockfd, const char *ds_retract_command, const char *id, ::ods::keystate::keyrole role, const char *zone, int algorithm, bool force) { struct stat stat_ret; /* Code to output the DNSKEY record (stolen from hsmutil) */ hsm_ctx_t *hsm_ctx = hsm_create_context(); if (!hsm_ctx) { ods_log_error_and_printf(sockfd, module_str, "could not connect to HSM"); return false; } hsm_key_t *key = hsm_find_key_by_id(hsm_ctx, id); if (!key) { ods_log_error_and_printf(sockfd, module_str, "key %s not found in any HSM", id); hsm_destroy_context(hsm_ctx); return false; } bool bOK = false; char *dnskey_rr_str; hsm_sign_params_t *sign_params = hsm_sign_params_new(); sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone); sign_params->algorithm = (ldns_algorithm)algorithm; sign_params->flags = LDNS_KEY_ZONE_KEY; sign_params->flags += LDNS_KEY_SEP_KEY; /*KSK=>SEP*/ ldns_rr *dnskey_rr = hsm_get_dnskey(hsm_ctx, key, sign_params); #if 0 ldns_rr_print(stdout, dnskey_rr); #endif dnskey_rr_str = ldns_rr2str(dnskey_rr); hsm_sign_params_free(sign_params); ldns_rr_free(dnskey_rr); hsm_key_free(key); /* Replace tab with white-space */ for (int i = 0; dnskey_rr_str[i]; ++i) { if (dnskey_rr_str[i] == '\t') { dnskey_rr_str[i] = ' '; } } /* We need to strip off trailing comments before we send to any clients that might be listening */ for (int i = 0; dnskey_rr_str[i]; ++i) { if (dnskey_rr_str[i] == ';') { dnskey_rr_str[i] = '\n'; dnskey_rr_str[i+1] = '\0'; break; } } // pass the dnskey rr string to a configured // delegation signer retract program. if (!ds_retract_command || ds_retract_command[0] == '\0') { if (!force) { ods_log_error_and_printf(sockfd, module_str, "No \"DelegationSignerRetractCommand\" " "configured. No state changes made. " "Use --force to override."); bOK = false; } /* else: Do nothing, return keytag. */ } else if (stat(ds_retract_command, &stat_ret) != 0) { /* First check that the command exists */ ods_log_error_and_printf(sockfd, module_str, "Cannot stat file %s: %s", ds_retract_command, strerror(errno)); } else if (S_ISREG(stat_ret.st_mode) && !(stat_ret.st_mode & S_IXUSR || stat_ret.st_mode & S_IXGRP || stat_ret.st_mode & S_IXOTH)) { /* Then see if it is a regular file, then if usr, grp or * all have execute set */ ods_log_error_and_printf(sockfd, module_str, "File %s is not executable", ds_retract_command); } else { /* send records to the configured command */ FILE *fp = popen(ds_retract_command, "w"); if (fp == NULL) { ods_log_error_and_printf(sockfd, module_str, "failed to run command: %s: %s", ds_retract_command, strerror(errno)); } else { int bytes_written = fprintf(fp, "%s", dnskey_rr_str); if (bytes_written < 0) { ods_log_error_and_printf(sockfd, module_str, "[%s] Failed to write to %s: %s", ds_retract_command, strerror(errno)); } else if (pclose(fp) == -1) { ods_log_error_and_printf(sockfd, module_str, "failed to close %s: %s", ds_retract_command, strerror(errno)); } else { bOK = true; ods_printf(sockfd, "key %s retracted by %s\n", id, ds_retract_command); } } } LDNS_FREE(dnskey_rr_str); hsm_destroy_context(hsm_ctx); return bOK; }
void help_policy_list_cmd(int sockfd) { ods_printf(sockfd,"policy list list policies\n"); }
void perform_zone_del(int sockfd, engineconfig_type *config, const char *zone, int need_write_xml, bool quiet) { GOOGLE_PROTOBUF_VERIFY_VERSION; OrmConnRef conn; if (!ods_orm_connect(sockfd, config, conn)) return; // error already reported. std::string qzone; bool is_del_succeed = false; if (strlen(zone) > 0) { if (!OrmQuoteStringValue(conn, std::string(zone), qzone)) { const char *emsg = "quoting zone value failed"; ods_log_error_and_printf(sockfd,module_str,emsg); return; } } { OrmTransactionRW transaction(conn); if (!transaction.started()) { const char *emsg = "could not start database transaction"; ods_log_error_and_printf(sockfd,module_str,emsg); return; } if (qzone.empty()) { OrmResultRef rows; ::ods::keystate::EnforcerZone enfzone; std::vector<std::string> del_zones; bool ok = OrmMessageEnum(conn, enfzone.descriptor(), rows); if (!ok) { transaction.rollback(); ods_log_error("[%s] enum enforcer zone failed", module_str); return; } for (bool next=OrmFirst(rows); next; next = OrmNext(rows)) { OrmContextRef context; if (!OrmGetMessage(rows, enfzone, true, context)) { rows.release(); transaction.rollback(); ods_log_error("[%s] retrieving zone from database failed"); return; } del_zones.push_back(enfzone.name()); } rows.release(); for (std::vector<std::string>::iterator it = del_zones.begin(); it != del_zones.end(); ++it) { std::string del_zone; if (!OrmQuoteStringValue(conn, std::string(*it), del_zone)) { transaction.rollback(); const char *emsg = "quoting zone value failed"; ods_log_error_and_printf(sockfd,module_str,emsg); return; } if (!OrmMessageDeleteWhere(conn, ::ods::keystate::EnforcerZone::descriptor(), "name = %s", del_zone.c_str())) { transaction.rollback(); const char *emsg = "unable to delete zone %s"; ods_log_error_and_printf(sockfd,module_str,emsg, it->c_str()); return; } is_del_succeed = true; } } else { //find the zone OrmResultRef rows; if (!OrmMessageEnumWhere(conn, ::ods::keystate::EnforcerZone::descriptor(), rows, "name = %s", qzone.c_str())) { transaction.rollback(); ods_log_error_and_printf(sockfd, module_str, "unable to find zone %s", qzone.c_str()); return; } if (!OrmFirst(rows)) { rows.release(); transaction.rollback(); ods_log_error_and_printf(sockfd, module_str, "Couldn't find zone %s", qzone.c_str()); return; } rows.release(); if (!OrmMessageDeleteWhere(conn, ::ods::keystate::EnforcerZone::descriptor(), "name = %s", qzone.c_str())) { transaction.rollback(); const char *emsg = "unable to delete zone %s"; ods_log_error_and_printf(sockfd,module_str,emsg,qzone.c_str()); return; } is_del_succeed = true; } if (!transaction.commit()) { const char *emsg = "committing delete of zone %s to database failed"; ods_log_error_and_printf(sockfd,module_str,emsg,qzone.c_str()); return; } } // Now lets write out the required files - the internal list and optionally the zonelist.xml // Note at the moment we re-export the whole file in zonelist.xml format here but this should be optimised.... if (is_del_succeed) { if (!perform_write_signzone_file(sockfd, config)) { ods_log_error_and_printf(sockfd, module_str, "failed to write internal zonelist"); } if (need_write_xml) { if (!perform_zonelist_export_to_file(config->zonelist_filename,config)) { ods_log_error_and_printf(sockfd, module_str, "failed to write zonelist.xml"); } if (!quiet) { if (qzone.empty()) { ods_printf(sockfd, "Deleted all zones in database and zonelist.xml updated.\n"); } else { ods_printf(sockfd, "Deleted zone: %s in database and zonelist.xml updated.\n", zone); } } } else if (!quiet) { if (qzone.empty()) { ods_printf(sockfd, "Deleted all zones in database only. Use the --xml flag or run \"ods-enforcer zonelist export\" if an update of zonelist.xml is required.\n", zone); } else { ods_printf(sockfd, "Deleted zone: %s in database only. Use the --xml flag or run \"ods-enforcer zonelist export\" if an update of zonelist.xml is required.\n", zone); } } } }
void help_update_all_cmd(int sockfd) { ods_printf(sockfd, "update all Perform update kasp, zonelist and repositorylist.\n" ); }