--- opendnssec-1.1.1/enforcer/ksm/dq_string.c 2010-07-08 22:53:47.000000000 +0200 +++ opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/ksm/dq_string.c 2010-07-15 15:56:42.000000000 +0200 @@ -177,6 +177,10 @@ StrAppend(query, " IN "); break; + case DQS_COMPARE_NOT_IN: + StrAppend(query, " NOT IN "); + break; + case DQS_COMPARE_IS: StrAppend(query, " IS "); break; diff -Nur opendnssec-1.1.1/enforcer/ksm/du_string.c opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/ksm/du_string.c --- opendnssec-1.1.1/enforcer/ksm/du_string.c 2010-07-08 22:53:47.000000000 +0200 +++ opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/ksm/du_string.c 2010-07-15 15:56:42.000000000 +0200 @@ -74,6 +74,7 @@ /*+ * DusSetInt - Integer Set * DusSetString - String Set + * DusSetKeyword - Keyword set * * Description: * Appends an integer or string field to the sql of the form: @@ -133,6 +134,20 @@ return; } +void DusSetKeyword(char** sql, const char* field, const char* data, int clause) +{ + if (clause) { + StrAppend(sql, ", "); + } + + StrAppend(sql, field); + StrAppend(sql, " = "); + + StrAppend(sql, data); + + return; +} + /*+ * DusConditionInt - Append Integer Condition to Query diff -Nur opendnssec-1.1.1/enforcer/ksm/include/ksm/database_statement.h opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/ksm/include/ksm/database_statement.h --- opendnssec-1.1.1/enforcer/ksm/include/ksm/database_statement.h 2010-07-08 22:53:46.000000000 +0200 +++ opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/ksm/include/ksm/database_statement.h 2010-07-15 15:56:42.000000000 +0200 @@ -52,6 +52,7 @@ DQS_COMPARE_GT, DQS_COMPARE_GE, DQS_COMPARE_IN, + DQS_COMPARE_NOT_IN, DQS_COMPARE_IS } DQS_COMPARISON; diff -Nur opendnssec-1.1.1/enforcer/ksm/include/ksm/ksm.h opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/ksm/include/ksm/ksm.h --- opendnssec-1.1.1/enforcer/ksm/include/ksm/ksm.h 2010-07-08 22:53:46.000000000 +0200 +++ opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/ksm/include/ksm/ksm.h 2010-07-15 16:45:33.000000000 +0200 @@ -380,6 +380,8 @@ #define KSM_STATE_DSREADY_STRING "dsready" #define KSM_STATE_KEYPUBLISH 10 #define KSM_STATE_KEYPUBLISH_STRING "keypublish" +#define KSM_STATE_BACKUPPREP 11 +#define KSM_STATE_BACKUPPREP_STRING "backupprep" #define KSM_SERIAL_UNIX_STRING "unixtime" #define KSM_SERIAL_UNIX 1 @@ -617,6 +619,9 @@ int KsmSerialIdFromName(const char* name, int *id); int KsmPolicyIdFromName(const char* name, int *id); int KsmMarkBackup(int repo_id, const char* datetime); +int KsmPrepareBackup(int repo_id, const char* datetime); +int KsmCommitBackup(int repo_id, const char* datetime); +int KsmRollbackBackup(int repo_id, const char* datetime); int KsmCheckHSMkeyID(int repo_id, const char* cka_id, int *exists); /* KsmList */ diff -Nur opendnssec-1.1.1/enforcer/ksm/ksm_import.c opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/ksm/ksm_import.c --- opendnssec-1.1.1/enforcer/ksm/ksm_import.c 2010-07-08 22:53:47.000000000 +0200 +++ opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/ksm/ksm_import.c 2010-07-15 16:54:44.000000000 +0200 @@ -478,6 +478,124 @@ } /*+ + * KsmPrepareBackup - Prepare a backup for two-phase backup + * + * + * Arguments: + * + * int repo_id + * ID of the repository (-1 for all) + * + * const char* datetime + * When the backup was done + * + * Returns: + * int + * Status return. 0 on success. + * other on fail + */ + +int KsmPrepareBackup(int repo_id, const char* datetime) +{ + char* sql = NULL; /* SQL query */ + int status = 0; /* Status return */ + + /* Update rows */ + sql = DusInit("keypairs"); + DusSetInt(&sql, "STATE", KSM_STATE_BACKUPPREP, 0); + DusConditionInt(&sql, "state", DQS_COMPARE_EQ, KSM_STATE_GENERATE, 0); + if (repo_id != -1) { + DusConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 1); + } + StrAppend(&sql, " and backup is null"); + DusEnd(&sql); + + status = DbExecuteSqlNoResult(DbHandle(), sql); + DusFree(sql); + + return status; +} + +/*+ + * KsmCommitBackup - Finish a 2-phase backup successfuly + * + * + * Arguments: + * + * int repo_id + * ID of the repository (-1 for all) + * + * const char* datetime + * When the backup was done + * + * Returns: + * int + * Status return. 0 on success. + * other on fail + */ + +int KsmCommitBackup(int repo_id, const char* datetime) +{ + char* sql = NULL; /* SQL query */ + int status = 0; /* Status return */ + + /* Update rows */ + sql = DusInit("keypairs"); + DusSetInt(&sql, "STATE", KSM_STATE_GENERATE, 0); + DusSetString(&sql, "BACKUP", datetime, 1); + DusConditionInt(&sql, "state", DQS_COMPARE_EQ, KSM_STATE_BACKUPPREP, 0); + if (repo_id != -1) { + DusConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 1); + } + StrAppend(&sql, " and backup is null"); + DusEnd(&sql); + + status = DbExecuteSqlNoResult(DbHandle(), sql); + DusFree(sql); + + return status; +} + +/*+ + * KsmRollbackBackup - Terminate a 2-phase backup by undoing it + * + * + * Arguments: + * + * int repo_id + * ID of the repository (-1 for all) + * + * const char* datetime + * When the backup was done + * + * Returns: + * int + * Status return. 0 on success. + * other on fail + */ + +int KsmRollbackBackup(int repo_id, const char* datetime) +{ + char* sql = NULL; /* SQL query */ + int status = 0; /* Status return */ + + /* Update rows */ + sql = DusInit("keypairs"); + DusSetInt(&sql, "STATE", KSM_STATE_GENERATE, 0); + DusConditionInt(&sql, "state", DQS_COMPARE_EQ, KSM_STATE_BACKUPPREP, 0); + if (repo_id != -1) { + DusConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 1); + } + StrAppend(&sql, " and backup is null"); + DusEnd(&sql); + + status = DbExecuteSqlNoResult(DbHandle(), sql); + DusFree(sql); + + return status; +} + +/*+ * KsmMarkBackup - Mark a backup as having been done * * diff -Nur opendnssec-1.1.1/enforcer/ksm/ksm_policy.c opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/ksm/ksm_policy.c --- opendnssec-1.1.1/enforcer/ksm/ksm_policy.c 2010-07-08 22:53:47.000000000 +0200 +++ opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/ksm/ksm_policy.c 2010-07-15 15:56:42.000000000 +0200 @@ -48,6 +48,8 @@ #include "ksm/message.h" #include "ksm/string_util.h" +#include + /*+ * KsmPolicyInit - Query for Policy Information * @@ -847,6 +849,211 @@ return status; } +/*+ + * KsmPolicyPrune + * + * Arguments: + * none + * + * Returns: + * int + * Status return: + * 0 success + * -1 no record found + * non-zero some error occurred and a message has been output. + * Procedure: + * Assign DEAD status to all keys that belong to policies that have no + * zones attached. The absense of zones implies that keys need not + * remain in RETIRED state for a while. + * Then, prune all DEAD keys (including other ones in that state, so + * that is a side-effect of pruning policies, which seems fair). + * Then, remove parameter_policies for zone-less policies and finally, + * in light of referential integrity constraints, it is possible to + * remove the policies themselves that have no zones attached. +-*/ +int KsmPolicyPrune(char *config) +{ + int where = 0; /* WHERE clause value */ + char* sql = NULL; /* SQL query */ + char* sql2 = NULL; /* SQL query */ + char* sql3 = NULL; /* SQL query */ + DB_RESULT result; /* Handle converted to a result object */ + DB_ROW row = NULL; /* Row data */ + int status = 0; /* Status return */ + int PurgeKeys (int, int); + hsm_key_t *key = NULL; /* Key information */ + int temp_id = -1; /* place to store the key id returned */ + char* temp_dead = NULL; /* place to store dead date returned */ + char* temp_loc = NULL; /* place to store location returned */ + int done_something; + + + /* Beat keys to death if they are used by a non-existent policy */ + sql = DusInit("keypairs"); + DusSetInt(&sql, "STATE", KSM_STATE_DEAD, 0); +#ifdef USE_MYSQL + DusSetKeyword(&sql, KsmKeywordStateValueToName(KSM_STATE_DEAD), "NOW()", 1); +#else + DusSetKeyword(&sql, KsmKeywordStateValueToName(KSM_STATE_DEAD), "DATETIME()", 1); +#endif /* USE_MYSQL */ + DusConditionKeyword (&sql, "policy_id", DQS_COMPARE_NOT_IN, "(select policy_id from zones)", 0); + DusConditionKeyword (&sql, "dead", DQS_COMPARE_EQ, "NULL", 1); + status = DbExecuteSqlNoResult(DbHandle(), sql); + DusFree(sql); + + if (status != 0) + { + status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle())); + DbFreeResult(result); + return status; + } + + /* connect to the HSM */ + status = hsm_open(config, hsm_prompt_pin, NULL); + if (status) { + hsm_print_error(NULL); + DbFreeResult(result); + return(-1); + } + + /* Select rows */ + sql = StrStrdup("select id, dead, location from KEYDATA_VIEW where state = 6 and policy_id not in (select policy_id from zones)"); + /* stop us doing the same key twice */ + StrAppend(&sql, " group by location"); + + DusEnd(&sql); + + status = DbExecuteSql(DbHandle(), sql, &result); + + if (status == 0) { + status = DbFetchRow(result, &row); + while (status == 0) { + /* Got a row, purge it */ + DbInt(row, 0, &temp_id); + DbString(row, 1, &temp_dead); + DbString(row, 2, &temp_loc); + done_something = 1; + + /* Delete from dnsseckeys */ + sql2 = DdsInit("dnsseckeys"); + DdsConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, temp_id, 0); + DdsEnd(&sql); + + status = DbExecuteSqlNoResult(DbHandle(), sql2); + DdsFree(sql2); + if (status != 0) + { + printf("SQL failed: %s\n", DbErrmsg(DbHandle())); + DbStringFree(temp_dead); + DbStringFree(temp_loc); + DbFreeRow(row); + return status; + } + + /* Delete from keypairs */ + sql3 = DdsInit("keypairs"); + DdsConditionInt(&sql3, "id", DQS_COMPARE_EQ, temp_id, 0); + DdsEnd(&sql); + + status = DbExecuteSqlNoResult(DbHandle(), sql3); + DdsFree(sql3); + if (status != 0) + { + printf("SQL failed: %s\n", DbErrmsg(DbHandle())); + DbStringFree(temp_dead); + DbStringFree(temp_loc); + DbFreeRow(row); + return status; + } + + /* Delete from the HSM */ + key = hsm_find_key_by_id(NULL, temp_loc); + + if (!key) { + printf("Key not found: %s\n", temp_loc); + DbStringFree(temp_dead); + DbStringFree(temp_loc); + DbFreeRow(row); + return -1; + } + + status = hsm_remove_key(NULL, key); + + hsm_key_free(key); + + if (!status) { + printf("Key remove successful.\n"); + } else { + printf("Key remove failed.\n"); + DbStringFree(temp_dead); + DbStringFree(temp_loc); + DbFreeRow(row); + return -1; + } + + /* NEXT! */ + status = DbFetchRow(result, &row); + } + + /* Convert EOF status to success */ + + if (status == -1) { + status = 0; + } + + DbFreeResult(result); + } + + if (done_something == 0) { + printf("No keys to purge.\n"); + } + + DusFree(sql); + DbFreeRow(row); + + DbStringFree(temp_dead); + DbStringFree(temp_loc); + + if (status != 0) + { + status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle())); + DbFreeResult(result); + return status; + } + + /* Delete policy parameters that are not used for zone-related policies */ + where = 0; + sql = DdsInit ("parameters_policies"); + DdsConditionKeyword (&sql, "policy_id", DQS_COMPARE_NOT_IN, "(select policy_id from zones)", 0); + DdsEnd (&sql); + status = DbExecuteSqlNoResult(DbHandle(), sql); + DdsFree (sql); + + if (status != 0) + { + status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle())); + DbFreeResult(result); + return status; + } + + /* Delete policies that are not used in relation to any zones */ + where = 0; + sql = DdsInit ("policies"); + DdsConditionKeyword (&sql, "id", DQS_COMPARE_NOT_IN, "(select policy_id from zones)", 0); + DdsEnd (&sql); + status = DbExecuteSqlNoResult(DbHandle(), sql); + DdsFree (sql); + + if (status != 0) + { + status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle())); + DbFreeResult(result); + return status; + } + + return status; +} + KSM_POLICY *KsmPolicyAlloc() { KSM_POLICY *policy; diff -Nur opendnssec-1.1.1/enforcer/utils/ksmutil.c opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/utils/ksmutil.c --- opendnssec-1.1.1/enforcer/utils/ksmutil.c 2010-07-08 22:53:45.000000000 +0200 +++ opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/utils/ksmutil.c 2010-07-19 13:03:42.000000000 +0200 @@ -187,6 +187,13 @@ } void +usage_policyprune () +{ + fprintf(stderr, + " policy prune\n"); +} + + void usage_policy () { fprintf(stderr, @@ -194,6 +201,7 @@ progname); usage_policyexport (); usage_policylist (); + usage_policyprune (); } void @@ -256,7 +264,9 @@ " key purge\n" "\t--zone aka -z\n" " key purge\n" - "\t--policy aka -p\n"); + "\t--policy aka -p\n" + " key purge\n" + "\t--all aka -a\n"); } void @@ -307,9 +317,15 @@ usage_backup () { fprintf(stderr, - " backup done\n" + " backup prepare\n" + "\t--repository aka -r\n" + " backup commit\n" + "\t--repository aka -r\n" + " backup rollback\n" "\t--repository aka -r\n" " backup list\n" + "\t--repository aka -r\n" + " backup done\n" "\t--repository aka -r\n"); } @@ -344,6 +360,7 @@ usage_repo (); usage_policyexport (); usage_policylist (); + usage_policyprune (); usage_keylist (); usage_keyexport (); usage_keyimport (); @@ -1747,62 +1764,49 @@ } /* - * note that fact that a backup has been performed + * List rollovers */ int -cmd_backup () +cmd_listrolls () { int status = 0; - int repo_id = -1; + int qualifier_id = -1; /* ID of qualifer (if given) */ /* Database connection details */ DB_HANDLE dbhandle; FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ - char* datetime = DtParseDateTimeString("now"); - - /* Check datetime in case it came back NULL */ - if (datetime == NULL) { - printf("Couldn't turn \"now\" into a date, quitting...\n"); - exit(1); - } - /* try to connect to the database */ status = db_connect(&dbhandle, &lock_fd, 1); if (status != 0) { printf("Failed to connect to database\n"); db_disconnect(lock_fd); - StrFree(datetime); return(1); } - /* Turn repo name into an id (if provided) */ - if (o_repository != NULL) { - status = KsmSmIdFromName(o_repository, &repo_id); + /* Turn zone name into an id (if provided) */ + if (o_zone != NULL) { + status = KsmZoneIdFromName(o_zone, &qualifier_id); if (status != 0) { - printf("Error: unable to find a repository named \"%s\" in database\n", o_repository); + printf("Error: unable to find a zone named \"%s\" in database\n", o_zone); db_disconnect(lock_fd); - StrFree(datetime); return status; } } - status = KsmMarkBackup(repo_id, datetime); + printf("Rollovers:\n"); + + status = KsmListRollovers(qualifier_id); + if (status != 0) { - printf("Error: failed to mark backup as done\n"); + printf("Error: failed to list rollovers\n"); db_disconnect(lock_fd); - StrFree(datetime); return status; } - if (o_repository != NULL) { - printf("Marked repository %s as backed up at %s\n", o_repository, datetime); - } else { - printf("Marked all repositories as backed up at %s\n", datetime); - } + printf("\n"); - StrFree(datetime); /* Release sqlite lock file (if we have it) */ db_disconnect(lock_fd); @@ -1811,10 +1815,10 @@ } /* - * List rollovers + * List backups */ int -cmd_listrolls () +cmd_listbackups () { int status = 0; @@ -1825,33 +1829,31 @@ FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ /* try to connect to the database */ - status = db_connect(&dbhandle, &lock_fd, 1); + status = db_connect(&dbhandle, &lock_fd, 0); if (status != 0) { printf("Failed to connect to database\n"); db_disconnect(lock_fd); return(1); } - /* Turn zone name into an id (if provided) */ - if (o_zone != NULL) { - status = KsmZoneIdFromName(o_zone, &qualifier_id); + /* Turn repo name into an id (if provided) */ + if (o_repository != NULL) { + status = KsmSmIdFromName(o_repository, &qualifier_id); if (status != 0) { - printf("Error: unable to find a zone named \"%s\" in database\n", o_zone); + printf("Error: unable to find a repository named \"%s\" in database\n", o_repository); db_disconnect(lock_fd); return status; } } - printf("Rollovers:\n"); - - status = KsmListRollovers(qualifier_id); + printf("Backups:\n"); + status = KsmListBackups(qualifier_id); if (status != 0) { - printf("Error: failed to list rollovers\n"); + printf("Error: failed to list backups\n"); db_disconnect(lock_fd); return status; } - printf("\n"); /* Release sqlite lock file (if we have it) */ @@ -1862,47 +1864,91 @@ } /* - * List backups + * note that fact that a backup has been performed */ int -cmd_listbackups () +cmd_backup (char *case_verb) { int status = 0; - int qualifier_id = -1; /* ID of qualifer (if given) */ + int repo_id = -1; /* Database connection details */ DB_HANDLE dbhandle; FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ + char* datetime = DtParseDateTimeString("now"); + + /* Check datetime in case it came back NULL */ + if (datetime == NULL) { + printf("Couldn't turn \"now\" into a date, quitting...\n"); + exit(1); + } + /* try to connect to the database */ - status = db_connect(&dbhandle, &lock_fd, 0); + status = db_connect(&dbhandle, &lock_fd, 1); if (status != 0) { printf("Failed to connect to database\n"); db_disconnect(lock_fd); + StrFree(datetime); return(1); } /* Turn repo name into an id (if provided) */ if (o_repository != NULL) { - status = KsmSmIdFromName(o_repository, &qualifier_id); + status = KsmSmIdFromName(o_repository, &repo_id); if (status != 0) { printf("Error: unable to find a repository named \"%s\" in database\n", o_repository); db_disconnect(lock_fd); + StrFree(datetime); return status; } } - printf("Backups:\n"); - status = KsmListBackups(qualifier_id); + if (!strncmp(case_verb, "DONE", 4)) { + status = KsmMarkBackup(repo_id, datetime); + if (o_repository != NULL) { + printf("Marked repository %s as backed up at %s\n", o_repository, datetime); + } else { + printf("Marked all repositories as backed up at %s\n", datetime); + } + } else if (!strncmp(case_verb, "PREPARE", 7)) { + status = KsmPrepareBackup(repo_id, datetime); + if (o_repository != NULL) { + printf("Prepared new keys in repository %s for backup at %s\n", o_repository, datetime); + } else { + printf("Prepared new keys in all repositories for backup at %s\n", datetime); + } + } else if (!strncmp(case_verb, "COMMIT", 6)) { + status = KsmCommitBackup(repo_id, datetime); + if (o_repository != NULL) { + printf("Marked all prepared keys in repository %s as backed up at %s\n", o_repository, datetime); + } else { + printf("Marked all prepared keys in all repositories as backed up at %s\n", datetime); + } + } else if (!strncmp(case_verb, "ROLLBACK", 8)) { + status = KsmRollbackBackup(repo_id, datetime); + if (o_repository != NULL) { + printf("Rolled back preparation of keys for backup in repository %s at %s\n", o_repository, datetime); + } else { + printf("Rolled back preparation of keys for backup in all repositories at %s\n", datetime); + } + } else if (!strncmp(case_verb, "LIST", 4)) { + status = cmd_listbackups(); + } else { + printf("Unknown command: backup %s\n", case_verb); + usage_backup(); + status = -1; + } if (status != 0) { - printf("Error: failed to list backups\n"); + printf("Error: failed to execute backup subcommand\n"); db_disconnect(lock_fd); + StrFree(datetime); return status; } - printf("\n"); + StrFree(datetime); /* Release sqlite lock file (if we have it) */ db_disconnect(lock_fd); @@ -1991,6 +2037,44 @@ } /* + * Prune policy + */ + int +cmd_prunepolicy () +{ + int status = 0; + + /* Database connection details */ + DB_HANDLE dbhandle; + FILE* lock_fd = NULL; /* This is the lock file descriptor for a SQLite DB */ + int KsmPolicyPrune (char *config); + + /* try to connect to the database */ + status = db_connect(&dbhandle, &lock_fd, 0); + if (status != 0) { + printf("Failed to connect to database\n"); + db_disconnect(lock_fd); + return(1); + } + + status = KsmPolicyPrune(config); + + if (status != 0) { + printf("Error: failed to prune policies\n"); + db_disconnect(lock_fd); + return status; + } + + printf("\n"); + + /* Release sqlite lock file (if we have it) */ + db_disconnect(lock_fd); + + DbDisconnect(dbhandle); + return 0; +} + +/* * List keys */ int @@ -2972,6 +3056,8 @@ result = cmd_exportpolicy(); } else if (!strncmp(case_verb, "LIST", 4)) { result = cmd_listpolicy(); + } else if (!strncmp(case_verb, "PRUNE", 5)) { + result = cmd_prunepolicy(); } else { printf("Unknown command: policy %s\n", case_verb); usage_policy(); @@ -3005,7 +3091,7 @@ } } else if (!strncmp(case_verb, "PURGE", 5)) { - if ((o_zone != NULL && o_policy == NULL) || + if ((o_zone != NULL && o_policy == NULL) || (o_zone == NULL && o_policy != NULL)){ result = cmd_keypurge(); } @@ -3031,17 +3117,8 @@ } else if (!strncmp(case_command, "BACKUP", 6)) { argc --; argc --; argv ++; argv ++; - /* verb should be done or list */ - if (!strncmp(case_verb, "DONE", 4)) { - result = cmd_backup(); - } - else if (!strncmp(case_verb, "LIST", 4)) { - result = cmd_listbackups(); - } else { - printf("Unknown command: backup %s\n", case_verb); - usage_backup(); - result = -1; - } + /* verb is further split in cmd_backup() */ + result = cmd_backup(case_verb); } else if (!strncmp(case_command, "ROLLOVER", 8)) { argc --; argc --; argv ++; argv ++; @@ -5272,12 +5349,12 @@ * Arguments: * * int zone_id - * ID of the zone + * ID of the zone * * int policy_id * ID of the policy * - * N.B. Only one of the arguments should be set, the other should be -1 + * N.B. At most one of the arguments should be set, the other(s) should be -1 * * Returns: * int @@ -5304,9 +5381,9 @@ /* Key information */ hsm_key_t *key = NULL; - if ((zone_id == -1 && policy_id == -1) || - (zone_id != -1 && policy_id != -1)){ - printf("Please provide either a zone OR a policy to key purge\n"); + if ((zone_id == -1 && policy_id == -1) || + (zone_id != -1 && policy_id != -1)){ + printf("Please provide EITHER a zone OR a policy to key purge\n"); usage_keypurge(); return(1); } diff -Nur opendnssec-1.1.1/enforcer/utils/ods-ksmutil.1 opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/utils/ods-ksmutil.1 --- opendnssec-1.1.1/enforcer/utils/ods-ksmutil.1 2010-07-12 22:11:09.000000000 +0200 +++ opendnssec-1.1.1-policy_prune-keybackup_2phase/enforcer/utils/ods-ksmutil.1 2010-07-19 13:24:57.000000000 +0200 @@ -19,13 +19,13 @@ .B ods-ksmutil rollover list .RB ... .br -.B ods-ksmutil policy export +.B ods-ksmutil policy list|export|prune .RB ... .br .B ods-ksmutil repository list .RB ... .br -.B ods-ksmutil backup list|done +.B ods-ksmutil backup list|prepare|commit|rollback|done .br .B ods-ksmutil database backup .RB ... @@ -230,8 +230,19 @@ .SH "POLICY ADMINISTRATION SUBCOMMANDS" .LP .TP +.B policy list +Show a list of policies stored in the database. +.LP +.TP .B policy export [--policy|--all|-p|-a] Export a policy from the database in the same format as the kasp.xml file. +.LP +.TP +.B policy prune +When updating policies, the KASP will never remove policies. This command +explicitly requests to remove any policies that are not related to any +zone. Any keys related to that policy will also be removed, and it will +also cleanup the underlying HSM. .SH "REPOSITORY AND BACKUP SUBCOMMANDS" .LP .TP @@ -242,19 +253,42 @@ List the backups that have been made on the given repository. The \-\-repository option specifies what repository to list. .TP +.B backup prepare \-\-repository|\-r name +Start a two-phase key backup procedure. +Prepare the keys generated up to here for backup. Any keys generated +automatically by OpenDNSSEC after this command are not guaranteed to be +backed up, and will therefore not be taken into account when committing +the prepared keys for use by OpenDNSSEC. The next command is usually +either \fBbackup commit\fR or, in case of failure of the key backup +itself, \fBbackup rollback\fR. This sequence works reliably if the +KASP Enforcer is running. If it is not, the single-phase backup of +\fBbackup done\fR provides a one-phase backup alternative. +.TP +.B backup commit \-\-repository|\-r name +Successfully end a two-phase key backup procedure. +After a key backup has succeeded, release all previously prepared keys +for service by OpenDNSSEC. Any keys that were generated since the last +issued preparation will not be released as it is uncertain whether these +are actually backed up. +.TP +.B backup rollback \-\-repository|\-r name +Safely end a failed two-phase key backup procedure. +After a key backup has failed, rollback all previously prepapared keys +to the state where they are generated, but not yet available for service +by OpenDNSSEC. After fixing this problem, a new attempt to backup the +keys can be made. +.TP .B backup done \-\-repository|\-r name Indicate that a backup of the given repository has been done, all non-backed up keys will now be marked as backed up. The \-\-repository option specifies what repository to list. This is a necessary step for repositories that have the RequireBackup flag set. Note that the KASP Enforcer may take the initiative to generate keys after -the backup has started and before the backup is done. In the current version -of OpenDNSSEC, it is therefore needed to stop the KASP Enforcer to be assured -that all keys are backed up. The sequence would therefore be -.LI Issue \fBods-control ksm stop\fR -.LI Make a backup of the repository -.LI Issue \fBods-ksmutil backup done\fR -.LI Issue \fBods-control ksm start\fR +the backup has started and before the backup is done. This single-phase +backup command waives that, which is safe when the KASP Enforcer is not +running. If you intend to keep the Enforcer running, you will instead +want to use the two-phase \fBbackup prepare\fR followed by either +\fBbackup commit\fR or \fBbackup rollback\fR. .TP .B database backup [\-\-output|\-o output] Make a copy of the database of the KASP Enforcer (if using sqlite).