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;
}
示例#3
0
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"
			   );
	
}
示例#10
0
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"
        );
}
示例#12
0
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;
}
示例#13
0
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");
}
示例#16
0
void help_zone_list_cmd(int sockfd)
{
    ods_printf(sockfd,"zone list       list zones\n");
}
示例#17
0
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");
			}
		}
	}
}
示例#18
0
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
}
示例#22
0
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;
}
示例#25
0
void help_policy_list_cmd(int sockfd)
{
    ods_printf(sockfd,"policy list     list policies\n");
}
示例#26
0
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"
	);
}