diff -Nru opendnssec-1.1.1/enforcer/ksm/.deps/ksm_policy.Po opendnssec-1.1.1-policy_prune/enforcer/ksm/.deps/ksm_policy.Po --- opendnssec-1.1.1/enforcer/ksm/.deps/ksm_policy.Po 2010-07-12 22:11:19.000000000 +0200 +++ opendnssec-1.1.1-policy_prune/enforcer/ksm/.deps/ksm_policy.Po 2010-07-15 14:42:00.000000000 +0200 @@ -34,7 +34,8 @@ /usr/include/bits/posix2_lim.h /usr/include/bits/sockaddr.h \ /usr/include/asm/socket.h /usr/include/asm-x86_64/socket.h \ /usr/include/asm/sockios.h /usr/include/asm-x86_64/sockios.h \ - /usr/include/stdint.h include/ksm/memory.h include/ksm/string_util.h + /usr/include/stdint.h include/ksm/memory.h include/ksm/string_util.h \ + /usr/include/libhsm.h /usr/include/assert.h: @@ -181,3 +182,5 @@ include/ksm/memory.h: include/ksm/string_util.h: + +/usr/include/libhsm.h: diff -Nru opendnssec-1.1.1/enforcer/ksm/dq_string.c opendnssec-1.1.1-policy_prune/enforcer/ksm/dq_string.c --- opendnssec-1.1.1/enforcer/ksm/dq_string.c 2010-07-08 22:53:47.000000000 +0200 +++ opendnssec-1.1.1-policy_prune/enforcer/ksm/dq_string.c 2010-07-14 16:19:33.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 -Nru opendnssec-1.1.1/enforcer/ksm/du_string.c opendnssec-1.1.1-policy_prune/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/enforcer/ksm/du_string.c 2010-07-15 13:54:22.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 -Nru opendnssec-1.1.1/enforcer/ksm/include/ksm/database_statement.h opendnssec-1.1.1-policy_prune/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/enforcer/ksm/include/ksm/database_statement.h 2010-07-14 17:14:52.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 -Nru opendnssec-1.1.1/enforcer/ksm/ksm_policy.c opendnssec-1.1.1-policy_prune/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/enforcer/ksm/ksm_policy.c 2010-07-15 14:41:56.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 -Nru opendnssec-1.1.1/enforcer/utils/ksmutil.c opendnssec-1.1.1-policy_prune/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/enforcer/utils/ksmutil.c 2010-07-15 13:34:31.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 @@ -344,6 +354,7 @@ usage_repo (); usage_policyexport (); usage_policylist (); + usage_policyprune (); usage_keylist (); usage_keyexport (); usage_keyimport (); @@ -1991,6 +2002,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 +3021,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 +3056,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(); } @@ -5272,12 +5323,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 +5355,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 -Nru opendnssec-1.1.1/enforcer/utils/ods-ksmutil.1 opendnssec-1.1.1-policy_prune/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/enforcer/utils/ods-ksmutil.1 2010-07-15 15:22:12.000000000 +0200 @@ -19,7 +19,7 @@ .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 @@ -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