[Opendnssec-commits] [keihatsu.kirei.se/svn/dnssec] r3776 - in trunk/OpenDNSSEC: . enforcer/enforcerd enforcer/ksm enforcer/ksm/include/ksm enforcer/test enforcer/utils

Sion Lloyd sion at nominet.org.uk
Tue Aug 24 16:55:39 CEST 2010


Author: sion
Date: 2010-08-24 16:55:39 +0200 (Tue, 24 Aug 2010)
New Revision: 3776

Added:
   trunk/OpenDNSSEC/enforcer/utils/migrate_keyshare_mysql.pl
   trunk/OpenDNSSEC/enforcer/utils/migrate_keyshare_sqlite3.pl
Modified:
   trunk/OpenDNSSEC/
   trunk/OpenDNSSEC/NEWS
   trunk/OpenDNSSEC/enforcer/enforcerd/enforcer.c
   trunk/OpenDNSSEC/enforcer/enforcerd/enforcer.h
   trunk/OpenDNSSEC/enforcer/ksm/database_connection_mysql.c
   trunk/OpenDNSSEC/enforcer/ksm/dq_string.c
   trunk/OpenDNSSEC/enforcer/ksm/include/ksm/database.h
   trunk/OpenDNSSEC/enforcer/ksm/include/ksm/database_statement.h
   trunk/OpenDNSSEC/enforcer/ksm/include/ksm/ksm.h
   trunk/OpenDNSSEC/enforcer/ksm/include/ksm/ksmutil.h
   trunk/OpenDNSSEC/enforcer/ksm/ksm_import.c
   trunk/OpenDNSSEC/enforcer/ksm/ksm_key.c
   trunk/OpenDNSSEC/enforcer/ksm/ksm_list.c
   trunk/OpenDNSSEC/enforcer/ksm/ksm_purge.c
   trunk/OpenDNSSEC/enforcer/ksm/ksm_request.c
   trunk/OpenDNSSEC/enforcer/ksm/ksm_update.c
   trunk/OpenDNSSEC/enforcer/test/database_setup_mysql.sh.in
   trunk/OpenDNSSEC/enforcer/test/database_setup_sqlite3.sh.in
   trunk/OpenDNSSEC/enforcer/test/test_ksm_key.c
   trunk/OpenDNSSEC/enforcer/test/test_ksm_purge.c
   trunk/OpenDNSSEC/enforcer/test/test_ksm_request.c
   trunk/OpenDNSSEC/enforcer/test/test_ksm_update.c
   trunk/OpenDNSSEC/enforcer/utils/database_create.mysql
   trunk/OpenDNSSEC/enforcer/utils/database_create.sqlite3
   trunk/OpenDNSSEC/enforcer/utils/ksmutil.c
   trunk/OpenDNSSEC/enforcer/utils/ods-ksmutil.1.in
Log:
merge keysharing branch code to trunk.



Property changes on: trunk/OpenDNSSEC
___________________________________________________________________
Added: svn:mergeinfo
   + /branches/OpenDNSSEC-sion:3411-3767

Modified: trunk/OpenDNSSEC/NEWS
===================================================================
--- trunk/OpenDNSSEC/NEWS	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/NEWS	2010-08-24 14:55:39 UTC (rev 3776)
@@ -12,6 +12,10 @@
 * ldns-1.6.6 now required
 * libhsm will skip processing (and not create) any public keys if the
   per repository option <SkipPublicKey/> is set.
+* Keysharing improved - keys can now exist in different states on each zone
+  that the key is in use for.
+* Backup prepare/commit/rollback added for 2-step backups without taking the
+  enforcer offline.
 
 OpenDNSSEC 1.1.0 branch
 

Modified: trunk/OpenDNSSEC/enforcer/enforcerd/enforcer.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/enforcerd/enforcer.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/enforcerd/enforcer.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -324,6 +324,9 @@
 
     int same_keys = 0;      /* Do ksks and zsks look the same ? */
     int ksks_created = 0;   /* Were any KSKs created? */
+    
+    DB_RESULT result; 
+    int zone_count = 0;     /* Number of zones on policy */
 
     if  (policy->shared_keys == 1 ) {
         log_msg(config, LOG_INFO, "Key sharing is On");
@@ -339,13 +342,33 @@
         exit(1);
     }
 
+    /* See if our ZSKs and KSKs look the same */
     if (policy->ksk->sm == policy->zsk->sm && policy->ksk->bits == policy->zsk->bits && policy->ksk->algorithm == policy->zsk->algorithm) {
         same_keys = 1;
     } else {
         same_keys = 0;
     }
+
+    /* How many zones on this policy */ 
+    status = KsmZoneCountInit(&result, policy->id); 
+    if (status == 0) { 
+        status = KsmZoneCount(result, &zone_count); 
+    } 
+    DbFreeResult(result); 
+
+    if (status == 0) { 
+        /* make sure that we have at least one zone */ 
+        if (zone_count == 0) { 
+            log_msg(config, LOG_INFO, "No zones on policy %s, skipping...", policy->name);
+            return status; 
+        } 
+    } else {
+        log_msg(NULL, LOG_ERR, "Could not count zones on policy %s", policy->name);
+        return status; 
+    }
+
     /* Find out how many ksk keys are needed for the POLICY */
-    status = KsmKeyPredict(policy->id, KSM_TYPE_KSK, policy->shared_keys, config->interval, &ksks_needed, policy->ksk->rollover_scheme);
+    status = KsmKeyPredict(policy->id, KSM_TYPE_KSK, policy->shared_keys, config->interval, &ksks_needed, policy->ksk->rollover_scheme, zone_count);
     if (status != 0) {
         log_msg(NULL, LOG_ERR, "Could not predict ksk requirement for next interval for %s", policy->name);
         /* TODO exit? continue with next policy? */
@@ -356,6 +379,10 @@
         log_msg(NULL, LOG_ERR, "Could not count current ksk numbers for policy %s", policy->name);
         /* TODO exit? continue with next policy? */
     }
+    /* Correct for shared keys */
+    if (policy->shared_keys == KSM_KEYS_SHARED) {
+        keys_in_queue /= zone_count;
+    }
 
     new_keys = ksks_needed - keys_in_queue;
     /* fprintf(stderr, "keygen(ksk): new_keys(%d) = keys_needed(%d) - keys_in_queue(%d)\n", new_keys, ksks_needed, keys_in_queue); */
@@ -420,7 +447,7 @@
     current_count = 0;
 
     /* Find out how many zsk keys are needed for the POLICY */
-    status = KsmKeyPredict(policy->id, KSM_TYPE_ZSK, policy->shared_keys, config->interval, &zsks_needed, 0);
+    status = KsmKeyPredict(policy->id, KSM_TYPE_ZSK, policy->shared_keys, config->interval, &zsks_needed, 0, zone_count);
     if (status != 0) {
         log_msg(NULL, LOG_ERR, "Could not predict zsk requirement for next intervalfor %s", policy->name);
         /* TODO exit? continue with next policy? */
@@ -431,6 +458,10 @@
         log_msg(NULL, LOG_ERR, "Could not count current zsk numbers for policy %s", policy->name);
         /* TODO exit? continue with next policy? */
     }
+    /* Correct for shared keys */
+    if (policy->shared_keys == KSM_KEYS_SHARED) {
+        keys_in_queue /= zone_count;
+    }
     /* Might have to account for ksks */
     if (same_keys) {
         keys_in_queue -= ksks_needed;
@@ -520,7 +551,6 @@
     char* zone_name;
     char* current_policy;
     char* current_filename;
-    char* key_string = NULL;
     char *tag_name;
     int zone_id = -1;
     int signer_flag = 1; /* Is the signer responding? (1 == yes) */
@@ -633,10 +663,6 @@
                 xmlXPathFreeObject(xpathObj);
 
                 if (strcmp(current_policy, policy->name) != 0) {
-                    if (key_string != NULL) {
-                        StrFree(key_string);
-                        key_string = NULL;
-                    }
 
                     /* Read new Policy */ 
                     kaspSetPolicyDefaults(policy, current_policy);
@@ -652,17 +678,9 @@
                     }
                     log_msg(config, LOG_INFO, "Policy %s found in DB.", policy->name);
 
-                } else {
-                    /* Policy is same as previous zone, do not re-read */
-                    if (policy->shared_keys == 0) {
-                        if (key_string != NULL) {
-                            StrFree(key_string);
-                            key_string = NULL;
-                        }
-                    }
+                } /* else */ 
+                  /* Policy is same as previous zone, do not re-read */
 
-                }
-
                 StrFree(current_policy);
 
                 /* Evaluate xpath expression for signer configuration filename */
@@ -707,7 +725,7 @@
                 }
 
                 /* turn this zone and policy into a file */
-                status2 = commGenSignConf(zone_name, zone_id, current_filename, policy, &signer_flag, config->interval, config->manualKeyGeneration, &key_string, config->DSSubmitCmd);
+                status2 = commGenSignConf(zone_name, zone_id, current_filename, policy, &signer_flag, config->interval, config->manualKeyGeneration, config->DSSubmitCmd);
                 if (status2 == -2) {
                     log_msg(config, LOG_ERR, "Signconf not written for %s", zone_name);
                     /* Don't return? try to parse the rest of the zones? */
@@ -777,7 +795,6 @@
 
     xmlFreeDoc(doc);
     StrFree(zonelist_filename);
-    StrFree(key_string);
 
     return status;
 }
@@ -788,7 +805,7 @@
  *  returns 0 on success and -1 if something went wrong
  *                           -2 if the RequestKeys call failed
  */
-int commGenSignConf(char* zone_name, int zone_id, char* current_filename, KSM_POLICY *policy, int* signer_flag, int run_interval, int man_key_gen, char** key_string, const char* DSSubmitCmd)
+int commGenSignConf(char* zone_name, int zone_id, char* current_filename, KSM_POLICY *policy, int* signer_flag, int run_interval, int man_key_gen, const char* DSSubmitCmd)
 {
     int status = 0;
     int status2 = 0;
@@ -886,55 +903,49 @@
     fprintf(file, "\t\t\t<TTL>PT%dS</TTL>\n", policy->ksk->ttl);
 
     /* get new keys _only_ if we don't have them from before */
-    if (*key_string == NULL) {
-        status = KsmRequestKeys(0, 0, datetime, commKeyConfig, key_string, policy->id, zone_id, run_interval, &NewDS);
-        if (status != 0) {
-            /* 
-             * Something went wrong (it should have been logged) stop this zone.
-             * Clean up the files, don't call the signer and move on to the next zone.
-             */
-            log_msg(NULL, LOG_ERR, "KsmRequestKeys returned: %d", status);
+    status = KsmRequestKeys(0, 0, datetime, commKeyConfig, file, policy->id, zone_id, run_interval, &NewDS);
+    if (status != 0) {
+        /* 
+         * Something went wrong (it should have been logged) stop this zone.
+         * Clean up the files, don't call the signer and move on to the next zone.
+         */
+        log_msg(NULL, LOG_ERR, "KsmRequestKeys returned: %d", status);
 
-            /* check for the specific case of not having any keys 
-               TODO check that this code can ever be executed after the restructure */
-            if (status == -1) {
-                status2 = KsmRequestGenerateCount(KSM_TYPE_KSK, &gencnt, zone_id);
+        /* check for the specific case of not having any keys 
+           TODO check that this code can ever be executed after the restructure */
+        if (status == -1) {
+            status2 = KsmRequestGenerateCount(KSM_TYPE_KSK, &gencnt, zone_id);
+            if (status2 == 0 && gencnt == 0) {
+                if(man_key_gen == 1) {
+                    log_msg(NULL, LOG_ERR, "There are no KSKs in the generate state; please use \"ods-ksmutil key generate\" to create some.");
+                } else {
+                    log_msg(NULL, LOG_WARNING, "There are no KSKs in the generate state; ods-enforcerd will create some on its next run.");
+                }
+            }
+            else if (status2 == 0) {
+                status2 = KsmRequestGenerateCount(KSM_TYPE_ZSK, &gencnt, zone_id);
                 if (status2 == 0 && gencnt == 0) {
                     if(man_key_gen == 1) {
-                        log_msg(NULL, LOG_ERR, "There are no KSKs in the generate state; please use \"ods-ksmutil key generate\" to create some.");
+                        log_msg(NULL, LOG_ERR, "There are no ZSKs in the generate state; please use \"ods-ksmutil key generate\" to create some.");
                     } else {
-                        log_msg(NULL, LOG_WARNING, "There are no KSKs in the generate state; ods-enforcerd will create some on its next run.");
+                        log_msg(NULL, LOG_WARNING, "There are no ZSKs in the generate state; ods-enforcerd will create some on its next run.");
                     }
                 }
-                else if (status2 == 0) {
-                    status2 = KsmRequestGenerateCount(KSM_TYPE_ZSK, &gencnt, zone_id);
-                    if (status2 == 0 && gencnt == 0) {
-                        if(man_key_gen == 1) {
-                            log_msg(NULL, LOG_ERR, "There are no ZSKs in the generate state; please use \"ods-ksmutil key generate\" to create some.");
-                        } else {
-                            log_msg(NULL, LOG_WARNING, "There are no ZSKs in the generate state; ods-enforcerd will create some on its next run.");
-                        }
-                    }
-                }
-                else {
-                    log_msg(NULL, LOG_ERR, "KsmRequestGenerateCount returned: %d", status2);
-                }
             }
+            else {
+                log_msg(NULL, LOG_ERR, "KsmRequestGenerateCount returned: %d", status2);
+            }
+        }
 
-            status = fclose(file);
-            unlink(temp_filename);
-            MemFree(datetime);
-            StrFree(temp_filename);
-            StrFree(old_filename);
-            StrFree(*key_string);
-            *key_string = NULL;
+        status = fclose(file);
+        unlink(temp_filename);
+        MemFree(datetime);
+        StrFree(temp_filename);
+        StrFree(old_filename);
 
-            return -2;
-        }
+        return -2;
     }
 
-    fprintf(file, "%s", *key_string);
-
     fprintf(file, "\t\t</Keys>\n");
 
     fprintf(file, "\n");
@@ -1118,34 +1129,27 @@
 
 int commKeyConfig(void* context, KSM_KEYDATA* key_data)
 {
-    char temp[32];
-    char **file = (char **)context;
+    FILE *file = (FILE *)context;
 
-    StrAppend(file, "\t\t\t<Key>\n");
-    StrAppend(file, "\t\t\t\t<Flags>");
-    snprintf(temp, 32, "%d", key_data->keytype);
-    StrAppend(file, temp);
-    StrAppend(file, "</Flags>\n\t\t\t\t<Algorithm>");
-    snprintf(temp, 32, "%d", key_data->algorithm);
-    StrAppend(file, temp);
-    StrAppend(file, "</Algorithm>\n\t\t\t\t<Locator>");
-    StrAppend(file, key_data->location);
-    StrAppend(file, "</Locator>\n");
+    fprintf(file, "\t\t\t<Key>\n");
+    fprintf(file, "\t\t\t\t<Flags>%d</Flags>\n", key_data->keytype); 
+    fprintf(file, "\t\t\t\t<Algorithm>%d</Algorithm>\n", key_data->algorithm); 
+    fprintf(file, "\t\t\t\t<Locator>%s</Locator>\n", key_data->location);
 
     if (key_data->keytype == KSM_TYPE_KSK)
     {
-        StrAppend(file, "\t\t\t\t<KSK />\n");
+        fprintf(file, "\t\t\t\t<KSK />\n");
     }
     if (key_data->keytype == KSM_TYPE_ZSK && key_data->state == KSM_STATE_ACTIVE)
     {
-        StrAppend(file, "\t\t\t\t<ZSK />\n");
+        fprintf(file, "\t\t\t\t<ZSK />\n");
     }
     if ((key_data->state > KSM_STATE_GENERATE && key_data->state < KSM_STATE_DEAD) || key_data->state == KSM_STATE_KEYPUBLISH)
     {
-        StrAppend(file, "\t\t\t\t<Publish />\n");
+        fprintf(file, "\t\t\t\t<Publish />\n");
     }
-    StrAppend(file, "\t\t\t</Key>\n");
-    StrAppend(file, "\n");
+    fprintf(file, "\t\t\t</Key>\n");
+    fprintf(file, "\n");
 
     return 0;
 }
@@ -1220,7 +1224,7 @@
 
     /* Make sure that enough keys are allocated to this zone */
     /* How many do we need ? (set sharing to 1 so that we get the number needed for a single zone on this policy */
-    status = KsmKeyPredict(policy->id, key_type, 1, interval, &keys_needed, rollover_scheme);
+    status = KsmKeyPredict(policy->id, key_type, 1, interval, &keys_needed, rollover_scheme, 1);
     if (status != 0) {
         log_msg(NULL, LOG_ERR, "Could not predict key requirement for next interval for %s", zone_name);
         StrFree(datetime);
@@ -1252,7 +1256,7 @@
     for (i=0 ; i < new_keys ; i++){
         key_pair_id = 0;
         if (key_type == KSM_TYPE_KSK) {
-            status = KsmKeyGetUnallocated(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, &key_pair_id);
+            status = KsmKeyGetUnallocated(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, zone_id, &key_pair_id);
             if (status == -1 || key_pair_id == 0) {
                 if (man_key_gen == 0) {
                     log_msg(NULL, LOG_WARNING, "Not enough keys to satisfy ksk policy for zone: %s", zone_name);
@@ -1269,7 +1273,7 @@
                 return 3;
             }
         } else {
-            status = KsmKeyGetUnallocated(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, &key_pair_id);
+            status = KsmKeyGetUnallocated(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, zone_id, &key_pair_id);
             if (status == -1 || key_pair_id == 0) {
                 if (man_key_gen == 0) {
                     log_msg(NULL, LOG_WARNING, "Not enough keys to satisfy zsk policy for zone: %s", zone_name);
@@ -1287,12 +1291,7 @@
             }
         }
         if(key_pair_id > 0) {
-            /* This will do all zones if keys are shared */ 
-            if (policy->keys->share_keys == 1) {
-                status = KsmDnssecKeyCreateOnPolicy(policy->id, key_pair_id, key_type);
-            } else {
-                status = KsmDnssecKeyCreate(zone_id, key_pair_id, key_type, &ignore);
-            }
+            status = KsmDnssecKeyCreate(zone_id, key_pair_id, key_type, KSM_STATE_GENERATE, datetime, &ignore);
             /* fprintf(stderr, "comm(%d) %s: allocated keypair id %d\n", key_type, zone_name, key_pair_id); */
         } else {
             /* This shouldn't happen */
@@ -1407,6 +1406,7 @@
 int do_purge(int interval, int policy_id)
 {
     char*       sql = NULL;     /* SQL query */
+    char*       sql1 = NULL;     /* SQL query */
     char*       sql2 = NULL;    /* SQL query */
     char*       sql3 = NULL;    /* SQL query */
     int         status = 0;     /* Status return */
@@ -1418,8 +1418,8 @@
     unsigned int    nchar;          /* Number of characters converted */
 
     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         count = 0;          /* How many keys don't match the purge */
 
     char *rightnow;
 
@@ -1437,93 +1437,106 @@
     }
 
     /* Select rows */
-    StrAppend(&sql, "select id, dead, location from KEYDATA_VIEW where state = 6 ");
+    StrAppend(&sql, "select distinct id, location from KEYDATA_VIEW where state = 6 ");
 
-#ifdef USE_MYSQL
-    nchar = snprintf(buffer, sizeof(buffer),
-        "and DEAD < DATE_ADD('%s', INTERVAL -%d SECOND) ", rightnow, interval);
-#else
-    nchar = snprintf(buffer, sizeof(buffer),
-        "and DEAD < DATETIME('%s', '-%d SECONDS') ", rightnow, interval);
-#endif /* USE_MYSQL */
-
-    StrAppend(&sql, buffer);
     if (policy_id != -1) {
         StrAppend(&sql, "and policy_id = ");
         snprintf(stringval, KSM_INT_STR_SIZE, "%d", policy_id);
         StrAppend(&sql, stringval);
     }
-    /* stop us doing the same key twice */
-    StrAppend(&sql, " group by location");
 
     DusEnd(&sql);
-    StrFree(rightnow);
 
     status = DbExecuteSql(DbHandle(), sql, &result);
 
     if (status == 0) {
         status = DbFetchRow(result, &row);
         while (status == 0) {
-            /* Got a row, purge it */
+            /* Got a row, check it */
             DbInt(row, 0, &temp_id);
-            DbString(row, 1, &temp_dead);
-            DbString(row, 2, &temp_loc);
+            DbString(row, 1, &temp_loc);
 
-            /* Delete from dnsseckeys */
-            sql2 = DdsInit("dnsseckeys");
-            DdsConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
-            DdsEnd(&sql);
+            sql1 = DqsCountInit("dnsseckeys");
+            DdsConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
+            DdsConditionInt(&sql1, "(state", DQS_COMPARE_NE, KSM_STATE_DEAD, 1);
 
-            status = DbExecuteSqlNoResult(DbHandle(), sql2);
-            DdsFree(sql2);
-            if (status != 0)
-            {
-                log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
-                DbStringFree(temp_dead);
-                DbStringFree(temp_loc);
-                DbFreeRow(row);
-                return status;
-            }
+#ifdef USE_MYSQL
+            nchar = snprintf(buffer, sizeof(buffer),
+                    " or state = %d and DEAD > DATE_ADD('%s', INTERVAL -%d SECOND)) ", KSM_STATE_DEAD, rightnow, interval);
+#else
+            nchar = snprintf(buffer, sizeof(buffer),
+                    " or state = %d and DEAD > DATETIME('%s', '-%d SECONDS')) ", KSM_STATE_DEAD, rightnow, interval);
+#endif /* USE_MYSQL */
+            StrFree(rightnow);
 
-            /* Delete from keypairs */
-            sql3 = DdsInit("keypairs");
-            DdsConditionInt(&sql3, "id", DQS_COMPARE_EQ, temp_id, 0);
-            DdsEnd(&sql);
+            StrAppend(&sql1, buffer);
+            DqsEnd(&sql1);
 
-            status = DbExecuteSqlNoResult(DbHandle(), sql3);
-            DdsFree(sql3);
-            if (status != 0)
-            {
+            status = DbIntQuery(DbHandle(), &count, sql1);
+            DqsFree(sql1);
+
+            if (status != 0) {
                 log_msg(NULL, LOG_ERR, "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 the count is zero then there is no reason not to purge this key */
+            if (count == 0) {
 
-            if (!key) {
-                log_msg(NULL, LOG_ERR, "Key not found: %s\n", temp_loc);
-                DbStringFree(temp_dead);
-                DbStringFree(temp_loc);
-                DbFreeRow(row);
-                return -1;
-            }
+                /* Delete from dnsseckeys */
+                sql2 = DdsInit("dnsseckeys");
+                DdsConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
+                DdsEnd(&sql);
 
-            status = hsm_remove_key(NULL, key);
+                status = DbExecuteSqlNoResult(DbHandle(), sql2);
+                DdsFree(sql2);
+                if (status != 0)
+                {
+                    log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
+                    DbStringFree(temp_loc);
+                    DbFreeRow(row);
+                    return status;
+                }
 
-            hsm_key_free(key);
+                /* Delete from keypairs */
+                sql3 = DdsInit("keypairs");
+                DdsConditionInt(&sql3, "id", DQS_COMPARE_EQ, temp_id, 0);
+                DdsEnd(&sql);
 
-            if (!status) {
-                log_msg(NULL, LOG_INFO, "Key remove successful.\n");
-            } else {
-                log_msg(NULL, LOG_ERR, "Key remove failed.\n");
-                DbStringFree(temp_dead);
-                DbStringFree(temp_loc);
-                DbFreeRow(row);
-                return -1;
+                status = DbExecuteSqlNoResult(DbHandle(), sql3);
+                DdsFree(sql3);
+                if (status != 0)
+                {
+                    log_msg(NULL, LOG_ERR, "SQL failed: %s\n", DbErrmsg(DbHandle()));
+                    DbStringFree(temp_loc);
+                    DbFreeRow(row);
+                    return status;
+                }
+
+                /* Delete from the HSM */
+                key = hsm_find_key_by_id(NULL, temp_loc);
+
+                if (!key) {
+                    log_msg(NULL, LOG_ERR, "Key not found: %s\n", temp_loc);
+                    DbStringFree(temp_loc);
+                    DbFreeRow(row);
+                    return -1;
+                }
+
+                status = hsm_remove_key(NULL, key);
+
+                hsm_key_free(key);
+
+                if (!status) {
+                    log_msg(NULL, LOG_INFO, "Key remove successful.\n");
+                } else {
+                    log_msg(NULL, LOG_ERR, "Key remove failed.\n");
+                    DbStringFree(temp_loc);
+                    DbFreeRow(row);
+                    return -1;
+                }
             }
 
             /* NEXT! */ 
@@ -1542,7 +1555,6 @@
     DusFree(sql);
     DbFreeRow(row);
 
-    DbStringFree(temp_dead);
     DbStringFree(temp_loc);
 
     return status;

Modified: trunk/OpenDNSSEC/enforcer/enforcerd/enforcer.h
===================================================================
--- trunk/OpenDNSSEC/enforcer/enforcerd/enforcer.h	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/enforcerd/enforcer.h	2010-08-24 14:55:39 UTC (rev 3776)
@@ -45,7 +45,7 @@
 int do_keygen(DAEMONCONFIG *config, KSM_POLICY* policy, hsm_ctx_t *ctx);
 int do_communication(DAEMONCONFIG *config, KSM_POLICY* policy);
 
-int commGenSignConf(char* zone_name, int zone_id, char* current_filename, KSM_POLICY *policy, int* signer_flag, int run_interval, int man_key_gen, char** key_string, const char* DSSubmitCmd);
+int commGenSignConf(char* zone_name, int zone_id, char* current_filename, KSM_POLICY *policy, int* signer_flag, int run_interval, int man_key_gen, const char* DSSubmitCmd);
 int commKeyConfig(void* context, KSM_KEYDATA* key_data);
 int allocateKeysToZone(KSM_POLICY *policy, int key_type, int zone_id, uint16_t interval, const char* zone_name, int man_key_gen, int rollover_scheme);
 int read_zonelist_filename(const char* filename, char** zone_list_filename);

Modified: trunk/OpenDNSSEC/enforcer/ksm/database_connection_mysql.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/ksm/database_connection_mysql.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/ksm/database_connection_mysql.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -157,6 +157,11 @@
 		*dbhandle = (DB_HANDLE) connection;
 	}
 
+    /* Check the version against what we have in database.h */
+    if (status == 0) {
+        status = db_version_check();
+    }
+
     return status;
 }
 

Modified: trunk/OpenDNSSEC/enforcer/ksm/dq_string.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/ksm/dq_string.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/ksm/dq_string.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -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;

Modified: trunk/OpenDNSSEC/enforcer/ksm/include/ksm/database.h
===================================================================
--- trunk/OpenDNSSEC/enforcer/ksm/include/ksm/database.h	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/ksm/include/ksm/database.h	2010-08-24 14:55:39 UTC (rev 3776)
@@ -42,7 +42,7 @@
 
 #include <stdlib.h>
 
-#define KSM_DB_VERSION 1    /* This needs to match that given in the dbadmin table */
+#define KSM_DB_VERSION 2    /* This needs to match that given in the dbadmin table */
 
 #define MYSQL_DB 1
 #define SQLITE_DB 2

Modified: trunk/OpenDNSSEC/enforcer/ksm/include/ksm/database_statement.h
===================================================================
--- trunk/OpenDNSSEC/enforcer/ksm/include/ksm/database_statement.h	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/ksm/include/ksm/database_statement.h	2010-08-24 14:55:39 UTC (rev 3776)
@@ -52,6 +52,7 @@
     DQS_COMPARE_GT,
     DQS_COMPARE_GE,
     DQS_COMPARE_IN,
+    DQS_COMPARE_NOT_IN,
     DQS_COMPARE_IS
 } DQS_COMPARISON;
 

Modified: trunk/OpenDNSSEC/enforcer/ksm/include/ksm/ksm.h
===================================================================
--- trunk/OpenDNSSEC/enforcer/ksm/include/ksm/ksm.h	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/ksm/include/ksm/ksm.h	2010-08-24 14:55:39 UTC (rev 3776)
@@ -126,8 +126,8 @@
 } KSM_KEYDATA;
 
 int KsmKeyPairCreate(int policy_id, const char* HSMKeyID, int smID, int size, int alg, const char* generate, DB_ID* id);
-int KsmDnssecKeyCreate(int zone_id, int keypair_id, int keytype, DB_ID* id);
-int KsmDnssecKeyCreateOnPolicy(int policy_id, int keypair_id, int keytype);
+int KsmDnssecKeyCreate(int zone_id, int keypair_id, int keytype, int state, const char* time, DB_ID* id);
+/*int KsmDnssecKeyCreateOnPolicy(int policy_id, int keypair_id, int keytype);*/
 int KsmKeyInitSql(DB_RESULT* result, const char* sql);
 int KsmKeyInit(DB_RESULT* result, DQS_QUERY_CONDITION* condition);
 int KsmKeyInitId(DB_RESULT* result, DB_ID id);
@@ -135,11 +135,10 @@
 void KsmKeyEnd(DB_RESULT result);
 int KsmKeyQuery(const char* sql, DB_RESULT* result);
 int KsmKeyData(DB_ID id, KSM_KEYDATA* data);
-int KsmKeyPredict(int policy_id, int keytype, int shared_keys, int interval, int *count, int rollover_scheme);
+int KsmKeyPredict(int policy_id, int keytype, int shared_keys, int interval, int *count, int rollover_scheme, int zone_count);
 int KsmKeyCountQueue(int keytype, int* count, int zone_id);
 int KsmKeyCountStillGood(int policy_id, int sm, int bits, int algorithm, int interval, const char* datetime, int *count, int keytype);
-int KsmKeyGetUnallocated(int policy_id, int sm, int bits, int algorithm, int *keypair_id);
-int KsmLinkKeys(const char* zone_name, int policy_id);
+int KsmKeyGetUnallocated(int policy_id, int sm, int bits, int algorithm, int zone_id, int *keypair_id);
 int KsmMarkKeysAsDead(int zone_id);
 int KsmKillKey(int keypair_id);
 
@@ -148,10 +147,6 @@
 int KsmDeleteKeyRange(int minid, int maxid);
 int KsmDeleteKeyRanges(int limit[], int size);
 
-/* modify */
-
-int KsmKeyModify(KSM_KEYDATA* data, int low, int high);
-
 /* KsmParameter */
 
 typedef struct {
@@ -530,17 +525,17 @@
 /* ksm_update */
 
 int KsmUpdate(int policy_id, int zone_id);
-void KsmUpdateKey(KSM_KEYDATA* data, KSM_PARCOLL* collection);
+void KsmUpdateKey(KSM_KEYDATA* data, KSM_PARCOLL* collection, int zone_id);
 void KsmUpdateGenerateKeyTime(KSM_KEYDATA* data);
-void KsmUpdatePublishKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection);
+void KsmUpdatePublishKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection, int zone_id);
 void KsmUpdateReadyKeyTime(KSM_KEYDATA* data);
-void KsmUpdateActiveKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection);
-void KsmUpdateRetireKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection);
+void KsmUpdateActiveKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection, int zone_id);
+void KsmUpdateRetireKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection, int zone_id);
 void KsmUpdateDeadKeyTime(KSM_KEYDATA* data);
-void KsmUpdateDSPublishKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection);
-void KsmUpdateKEYPublishKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection);
+void KsmUpdateDSPublishKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection, int zone_id);
+void KsmUpdateKEYPublishKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection, int zone_id);
 int KsmUpdateKeyTime(const KSM_KEYDATA* data, const char* source,
-    const char* destination, int interval);
+    const char* destination, int interval, int zone_id);
 
 /* ksm_request */
 
@@ -612,10 +607,12 @@
 int KsmImportPolicy(const char* policy_name, const char* policy_description);
 int KsmImportZone(const char* zone_name, int policy_id, int fail_if_exists, int *new_zone);
 int KsmImportAudit(int policy_id, const char* audit_contents);
-int KsmImportKeyPair(int policy_id, const char* HSMKeyID, int smID, int size, int alg, int state, const char* time, const char* opt_time, DB_ID* id);
+int KsmImportKeyPair(int policy_id, const char* HSMKeyID, int smID, int size, int alg, int state, const char* time, DB_ID* id);
 int KsmSmIdFromName(const char* name, int *id);
 int KsmSerialIdFromName(const char* name, int *id);
 int KsmPolicyIdFromName(const char* name, int *id);
+int KsmMarkPreBackup(int repo_id, const char* datetime);
+int KsmRollbackMarkPreBackup(int repo_id);
 int KsmMarkBackup(int repo_id, const char* datetime);
 int KsmCheckHSMkeyID(int repo_id, const char* cka_id, int *exists);
 

Modified: trunk/OpenDNSSEC/enforcer/ksm/include/ksm/ksmutil.h
===================================================================
--- trunk/OpenDNSSEC/enforcer/ksm/include/ksm/ksmutil.h	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/ksm/include/ksm/ksmutil.h	2010-08-24 14:55:39 UTC (rev 3776)
@@ -39,6 +39,7 @@
 #include <ksm/ksm.h>
 #include <ksm/database.h>
 #include <libxml/xpath.h>
+#include <inttypes.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -84,11 +85,15 @@
 int cmd_genkeys();
 void SetPolicyDefaults(KSM_POLICY *policy, char *name);
 int fix_file_perms(const char *dbschema);
-int CountKeys(int *zone_id, int keytag, const char *cka_id, int *key_count, char **temp_cka_id, int *temp_key_state);
-int MarkDSSeen(const char *cka_id, int zone_id, int policy_id, const char *datetime, int key_state);
+int CountKeys(int *zone_id, int keytag, const char *cka_id, int *key_count, char **temp_cka_id, int *temp_key_state, int *temp_keypair_id);
+int MarkDSSeen(int keypair_id, int zone_id, int policy_id, const char *datetime, int key_state);
 int RetireOldKey(int zone_id, int policy_id, const char *datetime);
 int CountKeysInState(int keytype, int keystate, int* count, int zone_id);
 int ChangeKeyState(int keytype, const char *cka_id, int zone_id, int policy_id, const char *datetime, int key_state);
+int get_conf_key_info(int* interval, int* man_key_gen);
+int LinkKeys(const char* zone_name, int policy_id);
+int allocateKeysToZone(KSM_POLICY *policy, int key_type, int zone_id, uint16_t interval, const char* zone_name, int man_key_gen, int rollover_scheme);
+int keyRoll(int zone_id, int policy_id, int key_type);
 
 #ifdef __cplusplus
 }

Modified: trunk/OpenDNSSEC/enforcer/ksm/ksm_import.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/ksm/ksm_import.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/ksm/ksm_import.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -314,8 +314,6 @@
  *          state to set key to
  *      time
  *          timestamp of entry into state given
- *      opt_time
- *          timestamp for key to retire (if active)
  *
  *      DB_ID* id (returned)
  *          ID of the created entry.  This will be undefined on error.
@@ -324,7 +322,7 @@
  *      int
  *          Status return.  0=> Success, non-zero => error.
 -*/
-int KsmImportKeyPair(int policy_id, const char* HSMKeyID, int smID, int size, int alg, int state, const char* time, const char* opt_time, DB_ID* id)
+int KsmImportKeyPair(int policy_id, const char* HSMKeyID, int smID, int size, int alg, int state, const char* time, DB_ID* id)
 {
     unsigned long rowid;			/* ID of last inserted row */
     int         status = 0;         /* Status return */
@@ -336,10 +334,10 @@
         return MsgLog(KSM_INVARG, "NULL id");
     }
 
-    StrAppend(&columns, "policy_id, HSMkey_id, securitymodule_id, size, algorithm, state, ");
-    StrAppend(&columns, KsmKeywordStateValueToName(state));
-    if (opt_time[0] != '\0') {
-        StrAppend(&columns, ", retire, fixedDate");
+    StrAppend(&columns, "policy_id, HSMkey_id, securitymodule_id, size, algorithm");
+    if (state == KSM_STATE_GENERATE) {
+        StrAppend(&columns, ", ");
+        StrAppend(&columns, KsmKeywordStateValueToName(state));
     }
 
     sql = DisSpecifyInit("keypairs", columns);
@@ -348,11 +346,8 @@
     DisAppendInt(&sql, smID);
     DisAppendInt(&sql, size);
     DisAppendInt(&sql, alg);
-    DisAppendInt(&sql, state);
-    DisAppendString(&sql, time);
-    if (opt_time[0] != '\0') {
-        DisAppendString(&sql, opt_time);
-        DisAppendInt(&sql, 1);
+    if (state == KSM_STATE_GENERATE) {
+        DisAppendString(&sql, time);
     }
     DisEnd(&sql);
 
@@ -478,6 +473,139 @@
 }
 
 /*+
+ * KsmMarkPreBackup - Mark a backup as having been prepared
+ *
+ *
+ * Arguments:
+ *
+ *      int repo_id
+ *          ID of the repository (-1 for all)
+ *
+ *      const char* datetime
+ *          When the pre backup was done
+ *
+ * Returns:
+ *      int
+ *          Status return.  0 on success.
+ *                          other on fail
+ */
+
+int KsmMarkPreBackup(int repo_id, const char* datetime)
+{
+    char*       sql = NULL;     /* SQL query */
+    int         status = 0;     /* Status return */
+    int         count = -1;     /* How many keys get marked */
+
+    /* Count how many we will mark */
+    sql = DqsCountInit("keypairs");
+    if (repo_id != -1) {
+        DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 0);
+        StrAppend(&sql, " and pre_backup is null");
+    } else {
+        StrAppend(&sql, " where pre_backup is null");
+    }
+    DqsEnd(&sql);
+
+    /* Execute query and free up the query string */
+    status = DbIntQuery(DbHandle(), &count, sql);
+    DqsFree(sql);
+    
+    if (status != 0)
+    {
+        status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
+        return status;
+	}
+
+    if (count == 0) {
+        /* No work to do */
+        return -1;
+    }
+
+    /* Update rows */
+    sql = DusInit("keypairs");
+    DusSetString(&sql, "PRE_BACKUP", datetime, 0);
+    if (repo_id != -1) {
+        DusConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 0);
+        StrAppend(&sql, " and pre_backup is null");
+    } else {
+        StrAppend(&sql, " where pre_backup is null");
+    }
+    DusEnd(&sql);
+
+    status = DbExecuteSqlNoResult(DbHandle(), sql);
+    DusFree(sql);
+
+    return status;
+}
+
+/*+
+ * KsmRollbackPreBackup - Rollback a backup prepare step
+ *
+ *
+ * Arguments:
+ *
+ *      int repo_id
+ *          ID of the repository (-1 for all)
+ *
+ * Returns:
+ *      int
+ *          Status return.  0 on success.
+ *                          other on fail
+ */
+
+int KsmRollbackMarkPreBackup(int repo_id)
+{
+    char*       sql = NULL;     /* SQL query */
+    int         status = 0;     /* Status return */
+    int         count = -1;     /* How many keys get marked */
+
+    /* Count how many we will mark */
+    sql = DqsCountInit("keypairs");
+    if (repo_id != -1) {
+        DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 0);
+        StrAppend(&sql, " and pre_backup is not null");
+        StrAppend(&sql, " and backup is null");
+    } else {
+        StrAppend(&sql, " where pre_backup is not null");
+        StrAppend(&sql, " and backup is null");
+    }
+    DqsEnd(&sql);
+
+    /* Execute query and free up the query string */
+    status = DbIntQuery(DbHandle(), &count, sql);
+    DqsFree(sql);
+    
+    if (status != 0)
+    {
+        status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
+        return status;
+	}
+
+    if (count == 0) {
+        /* No work to do */
+        return -1;
+    }
+
+    /* Update rows */
+    sql = DusInit("keypairs");
+    DusSetString(&sql, "PRE_BACKUP", NULL, 0);
+    if (repo_id != -1) {
+        DusConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 0);
+        StrAppend(&sql, " and pre_backup is not null");
+        StrAppend(&sql, " and backup is null");
+    } else {
+        StrAppend(&sql, " where pre_backup is null");
+        StrAppend(&sql, " and backup is null");
+    }
+    DusEnd(&sql);
+
+    status = DbExecuteSqlNoResult(DbHandle(), sql);
+    DusFree(sql);
+
+    return status;
+}
+
+/*+
  * KsmMarkBackup - Mark a backup as having been done
  *
  *
@@ -499,15 +627,45 @@
 {
     char*       sql = NULL;     /* SQL query */
     int         status = 0;     /* Status return */
+    int         count = -1;     /* How many keys get marked */
 
+    /* Count how many we will mark */
+    sql = DqsCountInit("keypairs");
+    if (repo_id != -1) {
+        DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 0);
+        StrAppend(&sql, " and pre_backup is not null");
+        StrAppend(&sql, " and backup is null");
+    } else {
+        StrAppend(&sql, " where pre_backup is not null");
+        StrAppend(&sql, " and backup is null");
+    }
+    DqsEnd(&sql);
+
+    /* Execute query and free up the query string */
+    status = DbIntQuery(DbHandle(), &count, sql);
+    DqsFree(sql);
+    
+    if (status != 0)
+    {
+        status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
+        return status;
+	}
+
+    if (count == 0) {
+        /* No work to do */
+        return -1;
+    }
+
     /* Update rows */
     sql = DusInit("keypairs");
     DusSetString(&sql, "BACKUP", datetime, 0);
     if (repo_id != -1) {
         DusConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 0);
         StrAppend(&sql, " and backup is null");
+        StrAppend(&sql, " and pre_backup is not null");
     } else {
         StrAppend(&sql, " where backup is null");
+        StrAppend(&sql, " and pre_backup is not null");
     }
     DusEnd(&sql);
 

Modified: trunk/OpenDNSSEC/enforcer/ksm/ksm_key.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/ksm/ksm_key.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/ksm/ksm_key.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -94,13 +94,12 @@
         return MsgLog(KSM_INVARG, "NULL id");
     }
 
-    sql = DisSpecifyInit("keypairs", "policy_id, HSMkey_id, securitymodule_id, size, algorithm, state, generate");
+    sql = DisSpecifyInit("keypairs", "policy_id, HSMkey_id, securitymodule_id, size, algorithm, generate");
     DisAppendInt(&sql, policy_id);
     DisAppendString(&sql, HSMKeyID);
     DisAppendInt(&sql, smID);
     DisAppendInt(&sql, size);
     DisAppendInt(&sql, alg);
-    DisAppendInt(&sql, KSM_STATE_GENERATE);
     DisAppendString(&sql, generate);
     DisEnd(&sql);
 
@@ -141,21 +140,32 @@
  *          Status return.  0=> Success, non-zero => error.
 -*/
 
-int KsmDnssecKeyCreate(int zone_id, int keypair_id, int keytype, DB_ID* id)
+int KsmDnssecKeyCreate(int zone_id, int keypair_id, int keytype, int state, const char* time, DB_ID* id)
 {
 	unsigned long rowid;			/* ID of last inserted row */
     int         status = 0;         /* Status return */
     char*       sql = NULL;         /* SQL Statement */
+    char*       columns = NULL;     /* what columns are we setting */
 
     /* Check arguments */
     if (id == NULL) {
         return MsgLog(KSM_INVARG, "NULL id");
     }
 
-    sql = DisSpecifyInit("dnsseckeys", "zone_id, keypair_id, keytype");
+    StrAppend(&columns, "zone_id, keypair_id, keytype, state");
+    if (state != KSM_STATE_GENERATE) {
+        StrAppend(&columns, ", ");
+        StrAppend(&columns, KsmKeywordStateValueToName(state));
+    }
+
+    sql = DisSpecifyInit("dnsseckeys", columns);
     DisAppendInt(&sql, zone_id);
     DisAppendInt(&sql, keypair_id);
     DisAppendInt(&sql, keytype);
+    DisAppendInt(&sql, state);
+    if (state != KSM_STATE_GENERATE) {
+        DisAppendString(&sql, time);
+    }
     DisEnd(&sql);
 
     /* Execute the statement */
@@ -177,180 +187,6 @@
 }
 
 /*+
- * KsmDnssecKeyCreateOnPolicy - Create Entries in Dnsseckeys table 
- *                              (i.e. when a key is assigned to a policy that shares 
- *                              keys between zones)
- *
- * Description:
- *      Allocates a key in the database.
- *
- * Arguments:
- *      int policy_id
- *          policy that the keys will be allocated to
- *
- *      int keypair_id
- *          key that will be allocated
- *
- *      int keytype
- *          type of key that will be allocated
- *
- * Returns:
- *      int
- *          Status return.  0=> Success, non-zero => error.
--*/
-
-int KsmDnssecKeyCreateOnPolicy(int policy_id, int keypair_id, int keytype)
-{
-    DB_ID       ignore = 0;
-    int         status = 0;         /* Status return */
-    DB_RESULT   result;             /* List result set */
-    KSM_ZONE*   zone;               /* Zone information */
-    
-	zone = (KSM_ZONE *)malloc(sizeof(KSM_ZONE));
-    zone->name = (char *)calloc(KSM_NAME_LENGTH, sizeof(char));
-    
-    status = KsmZoneInit(&result, policy_id);
-    if (status == 0) {
-        while (status == 0) {
-            status = KsmZone(result, zone);
-            if (status == 0) {
-                status = KsmDnssecKeyCreate(zone->id, keypair_id, keytype, &ignore);
-            }
-        }
-    }
-
-    /* Convert EOF status to success */
-    if (status == -1) {
-        status = 0;
-    }
-
-    DbFreeResult(result);
-
-	free(zone->name);
-	free(zone);
-
-    return status;
-}
-
-/*+
- * KsmKeyModify - Modify KEYDATA Entry
- *
- * Description:
- *      Modifies a key in the database.
- *
- * Arguments:
- *      KSM_KEY* data
- *          Data to update.  Only fields where the flagss bit is set are
- *          updated.
- *
- *      int low
- *          Lower bound of range to modify.
- *
- *      int high
- *          Higher bound of range to modify.
- *
- * Returns:
- *      int
- *          Status return.  0=> Success, non-zero => error.
--*/
-/*  everything except size, HSMkey_id and policy_id in keypairs */
-int KsmKeyModify(KSM_KEYDATA* data, int low, int high)
-{
-    int         set = 0;            /* For the SET clause */
-    int         status = 0;         /* Status return */
-    char*       sql = NULL;         /* SQL Statement */
-    int         temp;               /* For ensuring low < high */
-    int         where = 0;          /* for the WHERE clause */
-
-    /* Check arguments */
-    if (data == NULL) {
-        return MsgLog(KSM_INVARG, "NULL data");
-    }
-
-    /* Ensure range ordering is correct */
-
-    if (low > high) {
-        temp = low;
-        low = high;
-        high = temp;
-    }
-
-    /* Create the update command */
-
-    sql = DusInit("keypairs");
-
-    if (data->flags & KEYDATA_M_STATE) {
-        DusSetInt(&sql, "STATE", data->state, set++);
-    }
-
-    if (data->flags & KEYDATA_M_ALGORITHM) {
-        DusSetInt(&sql, "ALGORITHM", data->algorithm, set++);
-    }
-
- /*   if (data->flags & KEYDATA_M_SIGLIFETIME) {
-        DusSetInt(&sql, "SIGLIFETIME", data->siglifetime, set++);
-    }*/
-
-    /* ... the times */
-
-    if (data->flags & KEYDATA_M_ACTIVE) {
-        DusSetString(&sql, "ACTIVE", data->active, set++);
-    }
-
-    if (data->flags & KEYDATA_M_DEAD) {
-        DusSetString(&sql, "DEAD", data->dead, set++);
-    }
-
-    if (data->flags & KEYDATA_M_GENERATE) {
-        DusSetString(&sql, "GENERATE", data->generate, set++);
-    }
-
-    if (data->flags & KEYDATA_M_PUBLISH) {
-        DusSetString(&sql, "PUBLISH", data->publish, set++);
-    }
-
-    if (data->flags & KEYDATA_M_READY) {
-        DusSetString(&sql, "READY", data->ready, set++);
-    }
-
-    if (data->flags & KEYDATA_M_RETIRE) {
-        DusSetString(&sql, "RETIRE", data->retire, set++);
-    }
-
-    /* ... and location */
-
-    if (data->flags & KEYDATA_M_SMID) {
-        DusSetInt(&sql, "SECURITYMODULE_ID", data->securitymodule_id, set++);
-    }
-
-
-    /* For what keys? */
-
-    if (low == high) {
-        DusConditionInt(&sql, "ID", DQS_COMPARE_EQ, low, where++);
-    }
-    else {
-        DusConditionInt(&sql, "ID", DQS_COMPARE_GE, low, where++);
-        DusConditionInt(&sql, "ID", DQS_COMPARE_LE, high, where++);
-    }
-
-    /* All done, close the statement */
-
-    DusEnd(&sql);
-
-    /* Execute the statement */
-
-    status = DbExecuteSqlNoResult(DbHandle(), sql);
-
-    DusFree(sql);
-
-    return status;
-}
-
-
-
-
-/*+
  * KsmKeyInitSql - Query for Key Information With Sql Query
  *
  * Description:
@@ -434,7 +270,7 @@
 
             case DB_KEYDATA_STATE:
                 DqsConditionInt(&sql, "STATE", condition[i].compare,
-                    condition[i].data.number, i);
+                        condition[i].data.number, i);
                 break;
 
             case DB_KEYDATA_ZONE_ID:
@@ -707,6 +543,8 @@
  *          (OUT) the number of keys (-1 on error)
  *      int rollover_scheme
  *          KSK rollover scheme in use
+ *      int zone_count
+ *          Number of zones on this policy
  *
  * Returns:
  *      int
@@ -716,37 +554,22 @@
  *              Other   Error
 -*/
 
-int KsmKeyPredict(int policy_id, int keytype, int shared_keys, int interval, int *count, int rollover_scheme) 
+int KsmKeyPredict(int policy_id, int keytype, int shared_keys, int interval, int *count, int rollover_scheme, int zone_count) 
 { 
     int status = 0;   /* Status return */ 
     KSM_PARCOLL coll; /* Parameters collection */ 
 
-    DB_RESULT result; 
-    int zone_count = 0;
-
     /* Check arguments */
     if (count == NULL) {
         return MsgLog(KSM_INVARG, "NULL count");
     }
 
-    /* how many zones on this policy */ 
-    status = KsmZoneCountInit(&result, policy_id); 
-    if (status == 0) { 
-        status = KsmZoneCount(result, &zone_count); 
+    /* make sure that we have at least one zone */ 
+    if (zone_count == 0) { 
+        *count = 0; 
+        return status; 
     } 
-    DbFreeResult(result); 
 
-    if (status == 0) { 
-        /* make sure that we have at least one zone */ 
-        if (zone_count == 0) { 
-            *count = 0; 
-            return status; 
-        } 
-    } else { 
-        *count = -1; 
-        return status; 
-    }
-
     /* Check that we have a valid key type */
     if ((keytype != KSM_TYPE_KSK) && (keytype != KSM_TYPE_ZSK)) {
         status = MsgLog(KME_UNKEYTYPE, keytype);
@@ -960,7 +783,7 @@
 
     /* Create the SQL command to interrogate the database */ 
  
-    sql = DqsCountInit("keypairs");
+    sql = DqsCountInit("KEYDATA_VIEW");
     if (policy_id != -1) {
         DqsConditionInt(&sql, "policy_id", DQS_COMPARE_EQ, policy_id, where++);
     }
@@ -1024,6 +847,8 @@
  *          size of key desired
  *      int algorithm
  *          algorithm of key desired
+ *      int zone_id
+ *          zone we are allocating to
  *      int *keypair_id (out)
  *          id of next keypair
  *
@@ -1033,7 +858,7 @@
  *          -1 == no free keys on that policy
  */
 
-int KsmKeyGetUnallocated(int policy_id, int sm, int bits, int algorithm, int *keypair_id) 
+int KsmKeyGetUnallocated(int policy_id, int sm, int bits, int algorithm, int zone_id, int *keypair_id) 
 {
 
     int     where = 0;          /* WHERE clause value */
@@ -1041,20 +866,22 @@
     DB_RESULT       result;     /* Handle converted to a result object */
     DB_ROW      row = NULL;     /* Row data */
     int     status = 0;         /* Status return */
+    char    in_sql[64];
 
     /* check the arguments? */
     /*if (zone_name == NULL) {
         return MsgLog(KSM_INVARG, "NULL zone name");
     }*/
+    snprintf(in_sql, 64, "(select id from KEYALLOC_VIEW where zone_id = %d)", zone_id);
 
     /* Construct the query */
-    sql = DqsSpecifyInit("KEYDATA_VIEW","min(id)");
+    sql = DqsSpecifyInit("KEYALLOC_VIEW","min(id)");
     DqsConditionInt(&sql, "policy_id", DQS_COMPARE_EQ, policy_id, where++);
     DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, sm, where++);
     DqsConditionInt(&sql, "size", DQS_COMPARE_EQ, bits, where++);
     DqsConditionInt(&sql, "algorithm", DQS_COMPARE_EQ, algorithm, where++);
-    DqsConditionInt(&sql, "state", DQS_COMPARE_EQ, KSM_STATE_GENERATE, where++);
     DqsConditionKeyword(&sql, "zone_id", DQS_COMPARE_IS, "NULL", where++);
+    DqsConditionKeyword(&sql, "id", DQS_COMPARE_NOT_IN, in_sql, where++);
 
     /* Execute query and free up the query string */
     status = DbExecuteSql(DbHandle(), sql, &result);
@@ -1084,92 +911,6 @@
 }
 
 /*+
- * KsmLinkKeys - Create required entries in Dnsseckeys table for zones added to policies
- *                      (i.e. when keysharing is turned on)
- *
- * Description:
- *      Allocates a key in the database.
- *
- * Arguments:
- *      const char* zone_name
- *          name of zone
- *
- *      int policy_id
- *          ID of policy which the zone is on
- *
- * Returns:
- *      int
- *          Status return.  0=> Success, non-zero => error.
--*/
-
-int KsmLinkKeys(const char* zone_name, int policy_id)
-{
-    int status = 0;
-
-    DB_RESULT	    result;         /* Result of parameter query */
-    DB_RESULT	    result2;        /* Result of key query */
-    KSM_PARAMETER   data;           /* Parameter information */
-    KSM_KEYDATA     data2;          /* Key information */
-    char*           sql = NULL;     /* SQL query */
-    int             zone_id = 0;    /* id of zone supplied */ 
-    int             clause = 0;
-    DB_ID           ignore = 0;
-
-    /* First work out if the keys are shared on this policy */
-    status = KsmParameterInit(&result, "zones_share_keys", "keys", policy_id);
-    if (status != 0) {
-        return(status);
-    }
-    status = KsmParameter(result, &data);
-    if (status != 0) {
-        return(status);
-    }
-    KsmParameterEnd(result);
-    
-    /* If the policy does not share keys then return */
-    if (data.value != 1) {
-        return 0;
-    }
-
-    status = KsmZoneIdFromName(zone_name, &zone_id);
-    if (status != 0) {
-        return(status);
-    }
-
-    /* Otherwise, find all the keys which are on that policy but are not retired or dead */
-    sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
-    DqsConditionInt(&sql, "policy_id", DQS_COMPARE_EQ, policy_id, clause++);
-    DqsConditionInt(&sql, "state", DQS_COMPARE_LT, KSM_STATE_RETIRE, clause++);
-    StrAppend(&sql, " group by id");
-    DqsEnd(&sql);
-
-    /* Now iterate round the keys meeting the condition and print them */
-
-    status = KsmKeyInitSql(&result2, sql);
-    if (status == 0) {
-        status = KsmKey(result2, &data2);
-        while (status == 0) {
-
-            /* create a dnsseckeys entry for this key */
-			status = KsmDnssecKeyCreate(zone_id, data2.keypair_id, data2.keytype, &ignore);
-			if (status == 0) {
-				status = KsmKey(result2, &data2);
-			}
-        }
-
-        /* Convert EOF status to success */
-
-        if (status == -1) {
-            status = 0;
-        }
-
-        KsmKeyEnd(result2);
-    }
-
-    return 0;
-}
-
-/*+
  * KsmMarkKeysAsDead - When deleting zones we may need to indicate that keys are now dead
  *                     (i.e. when keysharing is turned off or if we removed is the last zone on a policy)
  *

Modified: trunk/OpenDNSSEC/enforcer/ksm/ksm_list.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/ksm/ksm_list.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/ksm/ksm_list.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -75,6 +75,7 @@
     DB_ROW      row2 = NULL;     /* Row data */
 
     char*       temp_date = NULL; /* place to store date returned */
+    char*       temp_pre_date = NULL; /* place to store pre-backup date returned */
     char*       temp_repo = NULL; /* place to store repository returned */
     int         temp_backup_req = 0; /* place to store backuprequired returned */
 
@@ -164,6 +165,47 @@
     DbFreeRow(row2);
     DbStringFree(temp_repo);
 
+    /* List repos which need a backup commit */
+    sql2 = NULL;
+    StrAppend(&sql2, "select s.name from keypairs k, securitymodules s ");
+    StrAppend(&sql2, "where s.id = k.securitymodule_id ");
+    if (repo_id != -1) {
+        StrAppend(&sql2, "and s.id = ");
+        snprintf(stringval, KSM_INT_STR_SIZE, "%d", repo_id);
+        StrAppend(&sql2, stringval);
+    }
+    StrAppend(&sql2, " and k.backup is null");
+    StrAppend(&sql2, " and k.pre_backup is not null");
+    StrAppend(&sql2, " group by s.name order by s.name");
+
+    DusEnd(&sql2);
+
+    status = DbExecuteSql(DbHandle(), sql2, &result2);
+
+    if (status == 0) {
+        status = DbFetchRow(result2, &row2);
+        while (status == 0) {
+            /* Got a row, print it */
+            DbString(row2, 0, &temp_repo);
+
+            printf("Repository %s has keys prepared for back up which have not been committed\n", temp_repo);
+            
+            status = DbFetchRow(result2, &row2);
+        }
+
+        /* Convert EOF status to success */
+
+        if (status == -1) {
+            status = 0;
+        }
+
+        DbFreeResult(result2);
+    }
+
+    DusFree(sql2);
+    DbFreeRow(row2);
+    DbStringFree(temp_repo);
+
     return status;
 }
 

Modified: trunk/OpenDNSSEC/enforcer/ksm/ksm_purge.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/ksm/ksm_purge.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/ksm/ksm_purge.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -55,6 +55,7 @@
 {
     char*   sql = NULL;
     char*   sql2 = NULL;
+    char*   sql3 = NULL;
     DB_RESULT	result;         /* Result of parameter query */
     int     where = 0;
     int     keypair_id;
@@ -81,6 +82,13 @@
                 DdsEnd(&sql2);
                 (void) DbExecuteSqlNoResult(DbHandle(), sql2);
                 DdsFree(sql2);
+
+                /* Delete the row from keypairs */
+                sql3 = DdsInit("keypairs");
+                DdsConditionInt(&sql3, "ID", DQS_COMPARE_EQ, keypair_id, 0);
+                DdsEnd(&sql3);
+                (void) DbExecuteSqlNoResult(DbHandle(), sql3);
+                DdsFree(sql3);
             }
 
             status = DbFetchRow(result, &row);
@@ -88,21 +96,7 @@
     }
     DdsFree(sql);
 
-    /* Finally, delete the rows from keypairs */
-    where = 0;
-    sql = DdsInit("keypairs");
-    DdsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, KSM_STATE_DEAD, where++);
-    DdsEnd(&sql);
-    
-    /*
-     * Just execute the appropriate SQL.  Ignore the status return as we don't
-     * need to pass anything back to the caller, and if there is an error, any
-     * message will have been output.
-     */
-
-    (void) DbExecuteSqlNoResult(DbHandle(), sql);
-    DdsFree(sql);
     DbFreeRow(row);
-
+    
     return;
 }

Modified: trunk/OpenDNSSEC/enforcer/ksm/ksm_request.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/ksm/ksm_request.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/ksm/ksm_request.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -325,18 +325,8 @@
     }
 
     /*
-     * Step 3.  We are within the appropriate interval of the retirement
-     * of the active key, move keys from the generate state into the
-     * publish state.
-     */
-
-    status = KsmRequestChangeStateGeneratePublishConditional(keytype, datetime, &collection, zone_id, run_interval);
-    if (status != 0) {
-        return status;
-    }
-
-    /*
      * Step 3a.  make sure that we have enough standby KSKs
+     * Doing this before 3.
      */
 
     if (keytype == KSM_TYPE_KSK) {
@@ -352,6 +342,17 @@
     }
 
     /*
+     * Step 3.  We are within the appropriate interval of the retirement
+     * of the active key, move keys from the generate state into the
+     * publish state.
+     */
+
+    status = KsmRequestChangeStateGeneratePublishConditional(keytype, datetime, &collection, zone_id, run_interval);
+    if (status != 0) {
+        return status;
+    }
+
+    /*
      * Step 4. If there is an active key and the date on which this procedure
      * is run is earlier than the retire time of that key, exit the procedure.
      */
@@ -381,20 +382,6 @@
             }
             return(status);
         }
-        /* Get the shared_keys parameter */
-        status = KsmParameterInit(&result, "zones_share_keys", "keys", policy_id);
-        if (status != 0) {
-            status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
-            StrFree(zone_name);
-            return(status);
-        }
-        status = KsmParameter(result, &shared);
-        if (status != 0) {
-            status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
-            StrFree(zone_name);
-            return(status);
-        }
-        KsmParameterEnd(result);
 
         /*
          * Step 6. If there are keys to be made active, count the number of keys
@@ -485,12 +472,7 @@
                 }
 
                 /* Log that a rollover has happened */
-                if (shared.value == 0) {
-                    (void) MsgLog(KME_ROLL_ZONE, (keytype == KSM_TYPE_KSK ? "KSK" : "ZSK"), zone_name);
-                }
-                else {
-                    (void) MsgLog(KME_ROLL_POLICY, (keytype == KSM_TYPE_KSK ? "KSK" : "ZSK"), zone_name, zone_name);
-                }
+                (void) MsgLog(KME_ROLL_ZONE, (keytype == KSM_TYPE_KSK ? "KSK" : "ZSK"), zone_name);
             }
         }
         StrFree(zone_name);
@@ -634,11 +616,25 @@
      */
 
     sql = DusInit("keypairs");
-    DusSetString(&sql, "RETIRE", datetime, 0);
-    DusSetInt(&sql, "fixedDate", 1, 1);
-    DusSetInt(&sql, "compromisedflag", 1, 2);
+    DusSetInt(&sql, "fixedDate", 1, 0);
+    DusSetInt(&sql, "compromisedflag", 1, 1);
 
     DusConditionKeyword(&sql, "ID", DQS_COMPARE_IN, insql, 0);
+    DusEnd(&sql);
+
+    status = DbExecuteSqlNoResult(DbHandle(), sql);
+    DusFree(sql);
+
+    /* Report any errors */
+    if (status != 0) {
+        status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
+    }
+
+    sql = DusInit("dnsseckeys");
+    DusSetString(&sql, "RETIRE", datetime, 0);
+
+    DusConditionKeyword(&sql, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0);
+    /* NO ZONE_ID !!! We want to retire ALL instances of this key */
     StrFree(insql);
     DusEnd(&sql);
 
@@ -895,11 +891,12 @@
      * code is not executed.)
      */
 
-    sql = DusInit("keypairs");
+    sql = DusInit("dnsseckeys");
     DusSetInt(&sql, "STATE", dst_state, set++);
     DusSetString(&sql, dst_col, datetime, set++);
 
-    DusConditionKeyword(&sql, "ID", DQS_COMPARE_IN, insql, 0);
+    DusConditionKeyword(&sql, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0);
+    DusConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
     DusEnd(&sql);
     StrFree(dst_col);
 
@@ -927,31 +924,10 @@
             }
             return(status);
         }
-        /* Get the shared_keys parameter */
-        status = KsmParameterInit(&result2, "zones_share_keys", "keys", policy_id);
-        if (status != 0) {
-            status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
-            StrFree(insql);
-            StrFree(zone_name);
-            return(status);
-        }
-        status = KsmParameter(result2, &data2);
-        if (status != 0) {
-            status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
-            StrFree(insql);
-            StrFree(zone_name);
-            return(status);
-        }
-        KsmParameterEnd(result2);
 
         /* If we moved a KSK from retire to dead then the DS can be removed */
         if (dst_state == KSM_STATE_DEAD && rollover_scheme == KSM_ROLL_DS) {
-            if (data2.value == 0) {
-                (void) MsgLog(KME_DS_REM_ZONE, zone_name);
-            }
-            else {
-                (void) MsgLog(KME_DS_REM_POLICY, zone_name);
-            }
+            (void) MsgLog(KME_DS_REM_ZONE, zone_name);
         }
         else if (dst_state == KSM_STATE_READY) {
             (void) MsgLog(KME_NEW_DS, zone_name);
@@ -1219,12 +1195,13 @@
          * that state.
          */
 
-        sql3 = DusInit("keypairs");
+        sql3 = DusInit("dnsseckeys");
         DusSetInt(&sql3, "STATE", dst_state, setclause++);
         DusSetString(&sql3, dst_name, datetime, setclause++);
         StrFree(dst_name);
 
-        DusConditionKeyword(&sql3, "ID", DQS_COMPARE_IN, insql, whereclause++);
+        DusConditionKeyword(&sql3, "KEYPAIR_ID", DQS_COMPARE_IN, insql, whereclause++);
+        DusConditionInt(&sql3, "ZONE_ID", DQS_COMPARE_EQ, zone_id, whereclause++);
         StrFree(insql);
         DusEnd(&sql3);
 

Modified: trunk/OpenDNSSEC/enforcer/ksm/ksm_update.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/ksm/ksm_update.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/ksm/ksm_update.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -108,7 +108,7 @@
             /* Transaction handling is one level up (in KsmRequestKeys) */
             status = KsmKey(result, &data);
             while (status == 0) {
-                (void) KsmUpdateKey(&data, &collection);
+                (void) KsmUpdateKey(&data, &collection, zone_id);
                 status = KsmKey(result, &data);
             }
             (void) KsmKeyEnd(result);
@@ -144,9 +144,12 @@
  *
  *      KSM_PARCOLL* collection
  *          Parameter collection.
+ *
+ *      int zone_id
+ *          zone we are looking at
 -*/
 
-void KsmUpdateKey(KSM_KEYDATA* data, KSM_PARCOLL* collection)
+void KsmUpdateKey(KSM_KEYDATA* data, KSM_PARCOLL* collection, int zone_id)
 {
     /* check the argument */
     if (data == NULL) {
@@ -160,7 +163,7 @@
         break;
 
     case KSM_STATE_PUBLISH:
-        KsmUpdatePublishKeyTime(data, collection);
+        KsmUpdatePublishKeyTime(data, collection, zone_id);
         break;
 
     case KSM_STATE_READY:
@@ -168,11 +171,11 @@
         break;
 
     case KSM_STATE_ACTIVE:
-        KsmUpdateActiveKeyTime(data, collection);
+        KsmUpdateActiveKeyTime(data, collection, zone_id);
         break;
 
     case KSM_STATE_RETIRE:
-        KsmUpdateRetireKeyTime(data, collection);
+        KsmUpdateRetireKeyTime(data, collection, zone_id);
         break;
 
     case KSM_STATE_DEAD:
@@ -184,7 +187,7 @@
         break;
 
     case KSM_STATE_DSPUBLISH:
-        KsmUpdateDSPublishKeyTime(data, collection);
+        KsmUpdateDSPublishKeyTime(data, collection, zone_id);
         break;
 
     case KSM_STATE_DSREADY:
@@ -192,7 +195,7 @@
         break;
 
     case KSM_STATE_KEYPUBLISH:
-        KsmUpdateKEYPublishKeyTime(data, collection);
+        KsmUpdateKEYPublishKeyTime(data, collection, zone_id);
         break;
     default:
 
@@ -235,7 +238,7 @@
     return;
 }
 
-void KsmUpdatePublishKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection)
+void KsmUpdatePublishKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection, int zone_id)
 {
     int deltat = 0;  /* Time interval */
     int Ipc;     /* Child zone publication interval */
@@ -296,7 +299,7 @@
         return;
     }
 
-    (void) KsmUpdateKeyTime(data, "PUBLISH", "READY", deltat);
+    (void) KsmUpdateKeyTime(data, "PUBLISH", "READY", deltat, zone_id);
 
     return;
 }
@@ -319,7 +322,7 @@
     return;
 }
 
-void KsmUpdateActiveKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection)
+void KsmUpdateActiveKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection, int zone_id)
 {
     int deltat;     /* Time interval */
 
@@ -363,13 +366,13 @@
      * may still be active.
      */
     if (!data->fixedDate) {
-        (void) KsmUpdateKeyTime(data, "ACTIVE", "RETIRE", deltat);
+        (void) KsmUpdateKeyTime(data, "ACTIVE", "RETIRE", deltat, zone_id);
     }
 
     return;
 }
 
-void KsmUpdateRetireKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection)
+void KsmUpdateRetireKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection, int zone_id)
 {
     int deltat = 0;     /* Time interval */
 
@@ -417,7 +420,7 @@
         return;
     }
 
-    (void) KsmUpdateKeyTime(data, "RETIRE", "DEAD", deltat);
+    (void) KsmUpdateKeyTime(data, "RETIRE", "DEAD", deltat, zone_id);
 
     return;
 }
@@ -441,7 +444,7 @@
     return;
 }
 
-void KsmUpdateDSPublishKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection)
+void KsmUpdateDSPublishKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection, int zone_id)
 {
     int deltat = 0;  /* Time interval */
 
@@ -482,12 +485,12 @@
         return;
     }
 
-    (void) KsmUpdateKeyTime(data, "PUBLISH", "READY", deltat);
+    (void) KsmUpdateKeyTime(data, "PUBLISH", "READY", deltat, zone_id);
 
     return;
 }
 
-void KsmUpdateKEYPublishKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection)
+void KsmUpdateKEYPublishKeyTime(KSM_KEYDATA* data, KSM_PARCOLL* collection, int zone_id)
 {
     int deltat = 0;  /* Time interval */
 
@@ -515,7 +518,7 @@
     deltat = collection->zskttl +
             collection->propdelay + collection->pub_safety;
 
-    (void) KsmUpdateKeyTime(data, "PUBLISH", "ACTIVE", deltat);
+    (void) KsmUpdateKeyTime(data, "PUBLISH", "ACTIVE", deltat, zone_id);
 
     return;
 }
@@ -542,6 +545,9 @@
  *      int interval
  *          Interval (seconds) to update the source field with.
  *
+ *      int zone_id
+ *          zone we are looking at
+ *
  * Returns:
  *      int
  *          0       Update successful
@@ -549,7 +555,7 @@
 -*/
 
 int KsmUpdateKeyTime(const KSM_KEYDATA* data, const char* source,
-    const char* destination, int interval)
+    const char* destination, int interval, int zone_id)
 {
     char            buffer[KSM_SQL_SIZE];    /* Long enough for any statement */
     unsigned int    nchar;          /* Number of characters converted */
@@ -562,12 +568,12 @@
 
 #ifdef USE_MYSQL
     nchar = snprintf(buffer, sizeof(buffer),
-        "UPDATE keypairs SET %s = DATE_ADD(%s, INTERVAL %d SECOND) WHERE ID = %lu",
-        destination, source, interval, (unsigned long) data->keypair_id);
+        "UPDATE dnsseckeys SET %s = DATE_ADD(%s, INTERVAL %d SECOND) WHERE KEYPAIR_ID = %lu and zone_id = %d",
+        destination, source, interval, (unsigned long) data->keypair_id, zone_id);
 #else
     nchar = snprintf(buffer, sizeof(buffer),
-        "UPDATE keypairs SET %s = DATETIME(%s, '+%d SECONDS') WHERE ID = %lu",
-        destination, source, interval, (unsigned long) data->keypair_id);
+        "UPDATE dnsseckeys SET %s = DATETIME(%s, '+%d SECONDS') WHERE KEYPAIR_ID = %lu and zone_id = %d",
+        destination, source, interval, (unsigned long) data->keypair_id, zone_id);
 #endif /* USE_MYSQL */
 
     if (nchar < sizeof(buffer)) {

Modified: trunk/OpenDNSSEC/enforcer/test/database_setup_mysql.sh.in
===================================================================
--- trunk/OpenDNSSEC/enforcer/test/database_setup_mysql.sh.in	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/test/database_setup_mysql.sh.in	2010-08-24 14:55:39 UTC (rev 3776)
@@ -115,10 +115,10 @@
 insert into securitymodules (id, name, capacity) values (NULL, "softHSM-01-1", 1000);
 
 -- Create a dead key which we can purge out of the database
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 6, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
 -- With 2 zones using it:
-INSERT INTO dnsseckeys VALUES (NULL, 1, 1, 257);
-INSERT INTO dnsseckeys VALUES (NULL, 1, 2, 257);
+INSERT INTO dnsseckeys VALUES (NULL, 1, 1, 257, 6, NULL, NULL, NULL, NULL, "2002-01-01 01:00:00");
+INSERT INTO dnsseckeys VALUES (NULL, 1, 2, 257, 6, NULL, NULL, NULL, NULL, "2002-01-01 01:00:00");
 
 -- parameters for KsmParameter tests
 INSERT INTO categories VALUES (NULL,		"Test");
@@ -128,23 +128,23 @@
 INSERT INTO parameters_policies VALUES (NULL, (select id from parameters where name = "Blah2"), 2, 1	);
 
 -- Create a key which we can request from the database
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO dnsseckeys VALUES (NULL, 2, 1, 257);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO dnsseckeys VALUES (NULL, 2, 1, 257, 1, NULL, NULL, NULL, NULL, "2002-01-01 01:00:00");
 
 -- Create a set of keys which we can delete from the database
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
 EOF
 		;;
 

Modified: trunk/OpenDNSSEC/enforcer/test/database_setup_sqlite3.sh.in
===================================================================
--- trunk/OpenDNSSEC/enforcer/test/database_setup_sqlite3.sh.in	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/test/database_setup_sqlite3.sh.in	2010-08-24 14:55:39 UTC (rev 3776)
@@ -96,10 +96,10 @@
 insert into securitymodules (id, name, capacity) values (NULL, "softHSM-01-1", 1000);
 
 -- Create a dead key which we can purge out of the database
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 6, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
 -- With 2 zones using it:
-INSERT INTO dnsseckeys VALUES (NULL, 1, 1, 257);
-INSERT INTO dnsseckeys VALUES (NULL, 1, 2, 257);
+INSERT INTO dnsseckeys VALUES (NULL, 1, 1, 257, 6, NULL, NULL, NULL, NULL, "2002-01-01 01:00:00");
+INSERT INTO dnsseckeys VALUES (NULL, 1, 2, 257, 6, NULL, NULL, NULL, NULL, "2002-01-01 01:00:00");
 
 -- parameters for KsmParameter tests
 INSERT INTO categories VALUES (NULL,		"Test");
@@ -109,23 +109,23 @@
 INSERT INTO parameters_policies VALUES (NULL, (select id from parameters where name = "Blah2"), 2, 1	);
 
 -- Create a key which we can request from the database
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO dnsseckeys VALUES (NULL, 2, 1, 257);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO dnsseckeys VALUES (NULL, 2, 1, 257, 1, NULL, NULL, NULL, NULL, "2002-01-01 01:00:00");
 
 -- Create a set of keys which we can delete from the database
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
-INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, 1, "2001-01-01 01:00:00", NULL, NULL, NULL, NULL, "2002-01-01 01:00:00", 2, NULL, "", NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
+INSERT INTO keypairs VALUES(NULL, "0x1", 5, 1024, 1, "2001-01-01 01:00:00", 2, NULL, "", NULL, NULL, 0);
 EOF
 		;;
 

Modified: trunk/OpenDNSSEC/enforcer/test/test_ksm_key.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/test/test_ksm_key.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/test/test_ksm_key.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -170,7 +170,7 @@
 
     /* Now create a row in dnsseckeys for the above */
 
-    status = KsmDnssecKeyCreate(zone_id, keypair_id, KSM_TYPE_ZSK, &dnsseckey_id);
+    status = KsmDnssecKeyCreate(zone_id, keypair_id, KSM_TYPE_ZSK, KSM_STATE_GENERATE, generate, &dnsseckey_id);
 
 	CU_ASSERT_EQUAL(status, 0);
 
@@ -189,67 +189,6 @@
 }
 
 /*+
- * TestKsmKeyModify - Test Key Modify code
- *
- * Description:
- *      Tests that keys are created when requested
--*/
-
-static void TestKsmKeyModify(void)
-{
-
-    KSM_KEYDATA     data;           /* Holds information for insertion */
-	char		buffer[8]; /* User buffer */
-	DB_RESULT	result;		/* Result object */
-	DB_ROW		row;		/* Row object */
-    DB_ID           key_id;         /* Created key ID */
-    int             status = 0;     /* Status return */
-	char*		sql;		/* Constructed query */
-	int			where = 0;	/* WHERE clause count */
-
-    /* Create a new keypair entry */
-    int     policy_id = 2;
-    char*   HSMKeyID = "0x1";
-    int     smID = 1;
-    int     size = 1024;
-    int     alg = KSM_ALGORITHM_DSASHA1;
-    char*   generate = "2009-01-01";
-
-    status = KsmKeyPairCreate(policy_id, HSMKeyID, smID, size, alg, generate, &key_id);
-
-	CU_ASSERT_EQUAL(status, 0);
-
-	/* Assume that a key has been added (tested above) */
-
-    /* Change the algorithm and save to database */
-    TestKeyClear(&data);
-    data.algorithm = KSM_ALGORITHM_RSAMD5;
-    data.flags |= KEYDATA_M_ALGORITHM;
-
-    status = KsmKeyModify(&data, key_id, key_id);
-
-	CU_ASSERT_EQUAL(status, 0);
-
-    /* check on the key */
-    sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
-	DqsConditionInt(&sql, "ID", DQS_COMPARE_EQ, key_id, where++);
-	DqsEnd(&sql);
-	status = DbExecuteSql(DbHandle(), sql, &result);
-	CU_ASSERT_EQUAL(status, 0);
-	DqsFree(sql);
-
-	status = DbFetchRow(result, &row);
-	CU_ASSERT_EQUAL(status, 0);
-	status = DbStringBuffer(row, DB_KEYDATA_ALGORITHM, buffer, sizeof(buffer));
-	CU_ASSERT_EQUAL(status, 0);
-	CU_ASSERT_STRING_EQUAL(buffer, "1");
-
-	DbFreeRow(row);
-	DbFreeResult(result);
-
-}
-
-/*+
  * TestKsmKeyPredict - Test Key Predict code
  *
  * Description:
@@ -265,13 +204,13 @@
     int count;
     int status;
 
-    status =  KsmKeyPredict(policy_id, keytype, keys_shared, interval, &count, KSM_ROLL_DEFAULT);
+    status =  KsmKeyPredict(policy_id, keytype, keys_shared, interval, &count, KSM_ROLL_DEFAULT, 1);
 
     CU_ASSERT_EQUAL(status, 0);
     CU_ASSERT_EQUAL(count, 7); /* 4 rollovers, 2 standby plus one to get ready */
 
     keytype = KSM_TYPE_ZSK;
-    status =  KsmKeyPredict(policy_id, keytype, keys_shared, interval, &count, KSM_ROLL_DEFAULT);
+    status =  KsmKeyPredict(policy_id, keytype, keys_shared, interval, &count, KSM_ROLL_DEFAULT, 1);
 
     CU_ASSERT_EQUAL(status, 0);
     CU_ASSERT_EQUAL(count, 7);
@@ -349,15 +288,15 @@
     int zone_id = 1;
     int status;
 
-    status = KsmKeyGetUnallocated(policy_id, sm, bits, algorithm, &keypair_id);
+    status = KsmKeyGetUnallocated(policy_id, sm, bits, algorithm, zone_id, &keypair_id);
 
     CU_ASSERT_EQUAL(status, 0);
     CU_ASSERT_EQUAL(keypair_id, 3); 
 
-    status = KsmDnssecKeyCreate(zone_id, keypair_id, KSM_TYPE_ZSK, &dnsseckey_id);
+    status = KsmDnssecKeyCreate(zone_id, keypair_id, KSM_TYPE_ZSK, KSM_STATE_GENERATE, "now", &dnsseckey_id);
     CU_ASSERT_EQUAL(status, 0);
 
-    status = KsmKeyGetUnallocated(policy_id, sm, bits, algorithm, &keypair_id);
+    status = KsmKeyGetUnallocated(policy_id, sm, bits, algorithm, zone_id, &keypair_id);
 
     CU_ASSERT_EQUAL(status, 0);
     CU_ASSERT_EQUAL(keypair_id, 4);
@@ -374,12 +313,10 @@
 {
 
     DB_ID           key_pair_id;     /* Created key ID */
-    DB_ID           dnsseckey_id;   /* Created key ID */
     int             status = 0;     /* Status return */
     int			    rowcount;	    /* Number of rows returned */
 	char*		    sql;		    /* Constructed query */
 	int			    where = 0;	    /* WHERE clause count */
-    int             zone_id = 1;
 
     /* Create a new keypair entry */
     int     policy_id = 2;
@@ -397,7 +334,7 @@
 	CU_ASSERT_EQUAL(status, 0);
 
     /* Now create rows in dnsseckeys for the above */
-    status = KsmDnssecKeyCreateOnPolicy(policy_id, key_pair_id, KSM_TYPE_ZSK);
+    /*status = KsmDnssecKeyCreateOnPolicy(policy_id, key_pair_id, KSM_TYPE_ZSK);*/
 	CU_ASSERT_EQUAL(status, 0);
 
 	/* Check that a key has been added */
@@ -436,12 +373,11 @@
     struct test_testdef tests[] = {
         {"KsmKeyPairCreate", TestKsmKeyPairCreate},
         {"KsmDnssecKeyCreate", TestKsmDnssecKeyCreate},
-        {"KsmKeyModify", TestKsmKeyModify},
         {"KsmKeyPredict", TestKsmKeyPredict},
         {"KsmKeyCountQueue", TestKsmKeyCountQueue},
 /*        {"KsmKeyCountUnallocated", TestKsmKeyCountUnallocated},*/
         {"KsmKeyGetUnallocated", TestKsmKeyGetUnallocated},
-        {"KsmDnssecKeyCreateOnPolicy", TestKsmDnssecKeyCreateOnPolicy},
+/*        {"KsmDnssecKeyCreateOnPolicy", TestKsmDnssecKeyCreateOnPolicy},*/
         {NULL,                      NULL}
     };
 

Modified: trunk/OpenDNSSEC/enforcer/test/test_ksm_purge.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/test/test_ksm_purge.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/test/test_ksm_purge.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -60,15 +60,18 @@
     int			rowcount;	/* Number of rows returned */
 	char*		sql;		/* Constructed query */
 	char*		sql2;		/* Constructed query */
+	char*		sql3;		/* Constructed query */
 	int			status;		/* Status return */
 	int			where = 0;	/* WHERE clause count */
 
 	/* Check that only one key is "dead" (STATE=6) */
 
-	sql = DqsCountInit("keypairs");
+	sql = DqsCountInit("dnsseckeys");
 	DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, 6, where++);
+    StrAppend(&sql, " group by id");
 	DqsEnd(&sql);
 	status = DbIntQuery(DbHandle(), &rowcount, sql);
+	DqsFree(sql);
 
 	CU_ASSERT_EQUAL(status, 0);
 	CU_ASSERT_EQUAL(rowcount, 1);
@@ -88,8 +91,10 @@
     KsmPurge();
 
     /* Now make sure that we have no dead keys */
-	status = DbIntQuery(DbHandle(), &rowcount, sql);
-	DqsFree(sql);
+    sql3 = DqsCountInit("dnsseckeys");
+	DqsConditionInt(&sql3, "STATE", DQS_COMPARE_EQ, 6, 0);
+	status = DbIntQuery(DbHandle(), &rowcount, sql3);
+	DqsFree(sql3);
 
 	CU_ASSERT_EQUAL(status, 0);
 

Modified: trunk/OpenDNSSEC/enforcer/test/test_ksm_request.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/test/test_ksm_request.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/test/test_ksm_request.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -96,15 +96,30 @@
 	int		status = 0;
     int     zone_id = 1; /* opendnssec.org */
     int     newDS = 0;
+    int policy_id = 2;
+    int sm = 1;        /* count over all security modules */
+    int bits = 1024;      /* count over all sizes */
+    int algorithm = KSM_ALGORITHM_RSASHA1; /* count over all algorithms */
+    int keypair_id;
+    DB_ID dnsseckey_id;
 
     char*   datetime = DtParseDateTimeString("now");
 
-    /* push a key into some state that update can operate on */
+    /* Allocate a key to the zone (routines previously tested) */
+    status = KsmKeyGetUnallocated(policy_id, sm, bits, algorithm, zone_id, &keypair_id);
+    CU_ASSERT_EQUAL(status, 0);
+
+    status = KsmDnssecKeyCreate(zone_id, keypair_id, KSM_TYPE_ZSK, KSM_STATE_GENERATE, datetime, &dnsseckey_id);
+    CU_ASSERT_EQUAL(status, 0);
+
+    /* push the key into some state that update can operate on */
     status = KsmRequestChangeStateN( KSM_TYPE_ZSK, datetime, 1,
         KSM_STATE_GENERATE, KSM_STATE_PUBLISH, zone_id);
 
+	CU_ASSERT_EQUAL(status, 0);
+
 	/* Check that keys of a particular type can be requested */
-    KsmRequestKeys(keytype, rollover, datetime, TestCallbackFn, NULL, 2, zone_id, 0, &newDS);
+    KsmRequestKeys(keytype, rollover, datetime, TestCallbackFn, NULL, policy_id, zone_id, 0, &newDS);
 
 	/*CU_ASSERT_EQUAL(status, 1);*/ /* just make sure that something flags this as needing more work */
 	CU_ASSERT_EQUAL(no_keys, 1);

Modified: trunk/OpenDNSSEC/enforcer/test/test_ksm_update.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/test/test_ksm_update.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/test/test_ksm_update.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -67,7 +67,7 @@
     /* Create a new dnsseckeys entry (use our previously tested routines) 
      * keys 3 - 15 are unallocated */
 
-    status = KsmDnssecKeyCreate(zone_id, 3, KSM_TYPE_ZSK, &dnsseckey_id);
+    status = KsmDnssecKeyCreate(zone_id, 3, KSM_TYPE_ZSK, KSM_STATE_GENERATE, datetime, &dnsseckey_id);
 	CU_ASSERT_EQUAL(status, 0);
 
 	/* push a key into some state that update can operate on */

Modified: trunk/OpenDNSSEC/enforcer/utils/database_create.mysql
===================================================================
--- trunk/OpenDNSSEC/enforcer/utils/database_create.mysql	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/utils/database_create.mysql	2010-08-24 14:55:39 UTC (rev 3776)
@@ -25,7 +25,7 @@
     description varchar(255)
 );
 
-insert into dbadmin values (1, "This needs to be in sync with the version defined in database.h");
+insert into dbadmin values (2, "This needs to be in sync with the version defined in database.h");
 
 # security modules - store information about all the sms used
 create table securitymodules (
@@ -90,22 +90,17 @@
 
 # stores the private key info
 create table keypairs(
-  id     smallint not null auto_increment,
-  HSMkey_id  varchar(255) not null,
+  id            smallint not null auto_increment,
+  HSMkey_id     varchar(255) not null,
   algorithm     tinyint not null,             # algorithm code
   size          smallint,
   securitymodule_id          tinyint,                      # where the key is stored
-  state         tinyint,                      # state of the key (defines valid fields)
   generate      timestamp null default null,  # time key inserted into database
-  publish       timestamp null default null,  # time when key published into the zone
-  ready         timestamp null default null,  # time when the key is ready for use
-  active        timestamp null default null,  # time when the key was made active
-  retire        timestamp null default null,  # time when the key retires
-  dead          timestamp null default null,  # time when key is slated for removal
-  policy_id        mediumint,
+  policy_id     mediumint,
   compromisedflag tinyint,
   publickey     varchar(1024),                # public key data
-  backup        timestamp null default null,  # time when backup was performed
+  pre_backup    timestamp null default null,  # time when backup was started
+  backup        timestamp null default null,  # time when backup was finished
   fixedDate     tinyint default 0,            # Set to 1 to stop dates from being set according to the policy timings        
   
   constraint primary key (id),
@@ -119,6 +114,12 @@
   keypair_id    smallint,
   zone_id        mediumint,
   keytype       smallint not null,             # zsk or ksk (use code in dnskey record)
+  state         tinyint,                      # state of the key (defines valid fields)
+  publish       timestamp null default null,  # time when key published into the zone
+  ready         timestamp null default null,  # time when the key is ready for use
+  active        timestamp null default null,  # time when the key was made active
+  retire        timestamp null default null,  # time when the key retires
+  dead          timestamp null default null,  # time when key is slated for removal
 
   constraint primary key (id),
   constraint foreign key (zone_id) references zones (id),
@@ -150,13 +151,24 @@
 where p.category_id = c.id;
 
 create or replace view KEYDATA_VIEW as
-select k.id, k.state,	k.generate, k.publish, k.ready,	k.active,	k.retire,
-       k.dead, d.keytype, k.algorithm,	k.HSMkey_id as location, d.zone_id,
+select k.id, d.state,	k.generate, d.publish, d.ready,	d.active,	d.retire,
+       d.dead, d.keytype, k.algorithm,	k.HSMkey_id as location, d.zone_id,
        k.policy_id, k.securitymodule_id, k.size, k.compromisedflag, k.fixedDate
 from keypairs k left outer join dnsseckeys d
 on k.id = d.keypair_id;
 
+create or replace view INT_KEYALLOC_VIEW_FOR_MYSQL as
+select k.id as id, k.HSMkey_id as location, z.id as zone_id, k.algorithm as algorithm, k.policy_id as policy_id, k.securitymodule_id as securitymodule_id, k.size as size,
+    k.compromisedflag as compromisedflag
+from keypairs k left join zones z 
+on k.policy_id = z.policy_id;
 
+create or replace view KEYALLOC_VIEW as
+select v.id as id, location, algorithm, policy_id, securitymodule_id, size, compromisedflag, d.zone_id as zone_id from
+INT_KEYALLOC_VIEW_FOR_MYSQL v left outer join dnsseckeys d
+on d.zone_id = v.zone_id
+and d.keypair_id = v.id;
+
 # insert default data
 
 # default categories

Modified: trunk/OpenDNSSEC/enforcer/utils/database_create.sqlite3
===================================================================
--- trunk/OpenDNSSEC/enforcer/utils/database_create.sqlite3	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/utils/database_create.sqlite3	2010-08-24 14:55:39 UTC (rev 3776)
@@ -25,7 +25,7 @@
     "description" TEXT
 );
 
-insert into dbadmin values (1, "This needs to be in sync with the version defined in database.h");
+insert into dbadmin values (2, "This needs to be in sync with the version defined in database.h");
 
 -- security modules - store information about all the sms used
 create table securitymodules (
@@ -86,17 +86,12 @@
   algorithm     tinyint not null,             -- algorithm code
   size          smallint,
   securitymodule_id          tinyint,                      -- where the key is stored
-  state         tinyint,                      -- state of the key (defines valid fields)
   generate      varchar(64) null default null,  -- time key inserted into database
-  publish       varchar(64) null default null,  -- time when key published into the zone
-  ready         varchar(64) null default null,  -- time when the key is ready for use
-  active        varchar(64) null default null,  -- time when the key was made active
-  retire        varchar(64) null default null,  -- time when the key retires
-  dead          varchar(64) null default null,  -- time when key is slated for removal
   policy_id        mediumint,
   compromisedflag tinyint,
   publickey     varchar(1024),                -- public key data
-  backup        varchar(64) null default null,  -- time when backup was performed
+  pre_backup    varchar(64) null default null,  -- time when backup was started
+  backup        varchar(64) null default null,  -- time when backup was finished
   fixedDate     tinyint default 0,            -- Set to 1 to stop dates from being set according to the policy timings        
   
   foreign key (securitymodule_id) references securitymodules (id),
@@ -109,7 +104,14 @@
   keypair_id    smallint,
   zone_id        mediumint,
   keytype       smallint not null,             -- zsk or ksk (use code in dnskey record)
+  state         tinyint,                      -- state of the key (defines valid fields)
+  publish       varchar(64) null default null,  -- time when key published into the zone
+  ready         varchar(64) null default null,  -- time when the key is ready for use
+  active        varchar(64) null default null,  -- time when the key was made active
+  retire        varchar(64) null default null,  -- time when the key retires
+  dead          varchar(64) null default null,  -- time when key is slated for removal
 
+
   foreign key (zone_id) references zones (id),
   foreign key (keypair_id) references keypairs (id)
 );
@@ -142,8 +144,8 @@
 
 drop view if exists KEYDATA_VIEW;
 create view KEYDATA_VIEW as
-select k.id as id, k.state as state, k.generate as generate, k.publish as publish,
-    k.ready as ready, k.active as active, k.retire as retire, k.dead as dead, 
+select k.id as id, d.state as state, k.generate as generate, d.publish as publish,
+    d.ready as ready, d.active as active, d.retire as retire, d.dead as dead, 
     d.keytype as keytype, k.algorithm as algorithm, k.HSMkey_id as location,
     d.zone_id as zone_id, k.policy_id as policy_id, 
     k.securitymodule_id as securitymodule_id, k.size as size,
@@ -152,6 +154,16 @@
 from  keypairs k left outer join dnsseckeys d
 on k.id = d.keypair_id;
 
+drop view if exists KEYALLOC_VIEW;
+create view KEYALLOC_VIEW as
+select v.id as id, location, algorithm, policy_id, securitymodule_id, size, compromisedflag, d.zone_id as zone_id from
+(select k.id as id, k.HSMkey_id as location, z.id as zone_id, k.algorithm as algorithm, k.policy_id as policy_id, k.securitymodule_id as securitymodule_id, k.size as size,
+    k.compromisedflag as compromisedflag
+from keypairs k left join zones z where k.policy_id = z.policy_id )  v 
+left outer join dnsseckeys d
+on d.zone_id = v.zone_id
+and d.keypair_id = v.id;
+
 -- insert default data
 
 -- default categories

Modified: trunk/OpenDNSSEC/enforcer/utils/ksmutil.c
===================================================================
--- trunk/OpenDNSSEC/enforcer/utils/ksmutil.c	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/utils/ksmutil.c	2010-08-24 14:55:39 UTC (rev 3776)
@@ -282,6 +282,7 @@
 {
     fprintf(stderr,
             "  key ds-seen\n"
+            /*"\t--zone <zone> (or --all)                 aka -z\n"*/
             "\t--zone <zone>                            aka -z\n"
             "\t--keytag <keytag> | --cka_id <CKA_ID>    aka -x / -k\n"
             "\t--no-retire\n");
@@ -307,9 +308,15 @@
 usage_backup ()
 {
     fprintf(stderr,
-            "  backup done\n"
+            "  backup prepare\n"
             "\t--repository <repository>                aka -r\n"
+            "  backup commit\n"
+            "\t--repository <repository>                aka -r\n"
+            "  backup rollback\n"
+            "\t--repository <repository>                aka -r\n"
             "  backup list\n"
+            "\t--repository <repository>                aka -r\n"
+            "  backup done\n"
             "\t--repository <repository>                aka -r\n");
 }
 
@@ -740,6 +747,9 @@
     int policy_id = 0;
     int new_zone;   /* ignored */
 
+    DB_RESULT      result;         /* Result of parameter query */
+    KSM_PARAMETER   data;           /* Parameter information */
+
     xmlDocPtr doc = NULL;
 
     int status = 0;
@@ -855,9 +865,10 @@
     }
 
     /* If need be (keys shared on policy) link existing keys to zone */
-    status = KsmLinkKeys(o_zone, policy_id);
+    /* First work out if the keys are shared on this policy */
+    status = KsmParameterInit(&result, "zones_share_keys", "keys", policy_id);
     if (status != 0) {
-        printf("Failed to Link Keys to zone\n");
+        printf("Can't retrieve shared-keys parameter for policy\n");
         db_disconnect(lock_fd);
         StrFree(zonelist_filename);
         StrFree(sig_conf_name);
@@ -865,6 +876,31 @@
         StrFree(output_name);
         return(1);
     }
+    status = KsmParameter(result, &data);
+    if (status != 0) {
+        printf("Can't retrieve shared-keys parameter for policy\n");
+        db_disconnect(lock_fd);
+        StrFree(zonelist_filename);
+        StrFree(sig_conf_name);
+        StrFree(input_name);
+        StrFree(output_name);
+        return(1);
+    }
+    KsmParameterEnd(result);
+    
+    /* If the policy does not share keys then skip this */
+    if (data.value == 1) {
+        status = LinkKeys(o_zone, policy_id);
+        if (status != 0) {
+            printf("Failed to Link Keys to zone\n");
+            db_disconnect(lock_fd);
+            StrFree(zonelist_filename);
+            StrFree(sig_conf_name);
+            StrFree(input_name);
+            StrFree(output_name);
+            return(1);
+        }
+    }
 
     /* Release sqlite lock file (if we have it) */
     db_disconnect(lock_fd);
@@ -905,6 +941,8 @@
         return(1);
     }
 
+    /* TODO - KICK THE ENFORCER? */
+
     printf("Imported zone: %s\n", o_zone);
 
     return 0;
@@ -1413,24 +1451,13 @@
     DB_RESULT	result;         /* Result of parameter query */
     KSM_PARAMETER data;         /* Parameter information */
     
-    int key_type = 0;
-    int zone_id = 0;
-    int policy_id = 0;
+    int key_type = -1;
+    int zone_id = -1;
+    int policy_id = -1;
 
     int status = 0;
     int user_certain;
 
-    int NewDS = 0;      /* has the DS set changed */
-
-    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");
-        StrFree(datetime);
-        exit(1);
-    }
-
     /* If we were given a keytype, turn it into a number */
     if (o_keytype != NULL) {
         StrToLower(o_keytype);
@@ -1442,14 +1469,12 @@
     if (status != 0) {
         printf("Failed to connect to database\n");
         db_disconnect(lock_fd);
-        StrFree(datetime);
         return(1);
     }
 
     status = KsmZoneIdAndPolicyFromName(o_zone, &policy_id, &zone_id);
     if (status != 0) {
         db_disconnect(lock_fd);
-        StrFree(datetime);
         return(status);
     }
 
@@ -1457,40 +1482,33 @@
     status = KsmParameterInit(&result, "zones_share_keys", "keys", policy_id);
     if (status != 0) {
         db_disconnect(lock_fd);
-        StrFree(datetime);
         return(status);
     }
     status = KsmParameter(result, &data);
     if (status != 0) {
         db_disconnect(lock_fd);
-        StrFree(datetime);
         return(status);
     }
     KsmParameterEnd(result);
     
     /* Warn and confirm if this will roll more than one zone */
     if (data.value == 1) {
-        printf("*WARNING* This zone shares keys with others, they will all be rolled; are you sure? [y/N] ");
+        printf("*WARNING* This zone shares keys with others, all instances of the active key on this zone will be retired; are you sure? [y/N] ");
 
         user_certain = getchar();
         if (user_certain != 'y' && user_certain != 'Y') {
             printf("Okay, quitting...\n");
             db_disconnect(lock_fd);
-            StrFree(datetime);
             exit(0);
         }
     }
 
-    /* retire the active key(s) */
-    if (key_type == 0) {
-        KsmRequestKeys(KSM_TYPE_ZSK, 1, datetime, printKey, datetime, policy_id, zone_id, 0, &NewDS);
-        KsmRequestKeys(KSM_TYPE_KSK, 1, datetime, printKey, datetime, policy_id, zone_id, 0, &NewDS);
+    status = keyRoll(zone_id, policy_id, key_type);
+    if (status != 0) {
+        db_disconnect(lock_fd);
+        return(status);
     }
-    else {
-        KsmRequestKeys(key_type, 1, datetime, printKey, datetime, policy_id, zone_id, 0, &NewDS);
-    }
 
-    StrFree(datetime);
     /* Release sqlite lock file (if we have it) */
     db_disconnect(lock_fd);
 
@@ -1516,31 +1534,15 @@
     FILE* lock_fd = NULL;   /* This is the lock file descriptor for a SQLite DB */
 
     DB_RESULT   result;     /* To see if the policy shares keys or not */
-    KSM_PARAMETER data;     /* Parameter information */
-    DB_RESULT   result2;    /* For counting the zones on the policy */
-    DB_RESULT   result3;    /* For looping over the zones on the policy */
-	KSM_ZONE*   zone;
 
     int zone_count = -1;
-    int *zone_list = NULL;
-    int n = 0;
-    int i = 0;
     
     int key_type = 0;
     int policy_id = 0;
 
     int status = 0;
     int user_certain;
-    int NewDS = 0;      /* has the DS set changed */
 
-    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);
-    }
-
     /* If we were given a keytype, turn it into a number */
     if (o_keytype != NULL) {
         StrToLower(o_keytype);
@@ -1552,7 +1554,6 @@
     if (status != 0) {
         printf("Failed to connect to database\n");
         db_disconnect(lock_fd);
-        StrFree(datetime);
         return(1);
     }
 
@@ -1560,7 +1561,6 @@
     if (status != 0) {
         printf("Error, can't find policy : %s\n", o_policy);
         db_disconnect(lock_fd);
-        StrFree(datetime);
         return(status);
     }
 
@@ -1571,112 +1571,32 @@
     if (user_certain != 'y' && user_certain != 'Y') {
         printf("Okay, quitting...\n");
         db_disconnect(lock_fd);
-        StrFree(datetime);
         exit(0);
     }
 
-    /* Find out if this policy shares keys, (we only need to do one zone if this is the case) */
-    status = KsmParameterInit(&result, "zones_share_keys", "keys", policy_id);
-    if (status != 0) {
-        db_disconnect(lock_fd);
-        StrFree(datetime);
-        return(status);
-    }
-    status = KsmParameter(result, &data);
-    if (status != 0) {
-        db_disconnect(lock_fd);
-        StrFree(datetime);
-        return(status);
-    }
-    KsmParameterEnd(result);
-
     /* Find out how many zones we will need to do */
-    if (data.value == 0) {
-        /* how many zones on this policy */ 
-        status = KsmZoneCountInit(&result2, policy_id); 
-        if (status == 0) { 
-            status = KsmZoneCount(result2, &zone_count); 
-        } 
-        DbFreeResult(result2); 
+    /* how many zones on this policy */ 
+    status = KsmZoneCountInit(&result, policy_id); 
+    if (status == 0) { 
+        status = KsmZoneCount(result, &zone_count); 
+    } 
+    DbFreeResult(result); 
 
-        if (status == 0) { 
-            /* make sure that we have at least one zone */ 
-            if (zone_count == 0) {
-                printf("No zones on policy; nothing to roll\n");
-                db_disconnect(lock_fd);
-                StrFree(datetime);
-                return status; 
-            } 
-        } else { 
-            printf("Couldn't count zones on policy; quitting...\n");
+    if (status == 0) { 
+        /* make sure that we have at least one zone */ 
+        if (zone_count == 0) {
+            printf("No zones on policy; nothing to roll\n");
             db_disconnect(lock_fd);
-            StrFree(datetime);
-            exit(1); 
-        }
-    }
-    else {
-        /* Keys are shared, so we only need to do the first zone */
-        zone_count = 1;
-    }
-
-    /* Allocate space for our array */
-    zone_list = (int *)calloc(zone_count, sizeof(int));
-    if (zone_list == NULL) {
-        printf("Couldn't calloc zone list for policy; quitting...\n");
+            return status; 
+        } 
+    } else { 
+        printf("Couldn't count zones on policy; quitting...\n");
         db_disconnect(lock_fd);
-        StrFree(datetime);
         exit(1); 
     }
 
-    status = KsmZoneInit(&result3, policy_id);
-    if (status == 0) {
-        
-        zone = (KSM_ZONE *)malloc(sizeof(KSM_ZONE));
-        zone->name = (char *)calloc(KSM_ZONE_NAME_LENGTH, sizeof(char));
+    status = keyRoll(-1, policy_id, key_type);
 
-        status = KsmZone(result3, zone);
-
-        while (status == 0) {
-
-            /* Get the zone_id */
-            zone_list[n] = zone->id;
-            n++;
-
-            /* We can leave now if the policy shares keys */
-            if (data.value == 1) {
-                break;
-            }
-
-            status = KsmZone(result3, zone);
-        }
-
-        free(zone->name);
-        free(zone);
-
-    } 
-    else {
-        db_disconnect(lock_fd);
-        StrFree(datetime);
-        free(zone_list);
-        return(status);
-    }
-    DbFreeResult(result3);
-
-    /* Now we can do the work (outside of any other DB loops to satisfy sqlite < 3.6.5) */
-    for (i = zone_count-1; i >= 0; i--) { 
-
-        /* retire the active key(s) */
-        if (key_type == 0) {
-            KsmRequestKeys(KSM_TYPE_ZSK, 1, datetime, printKey, datetime, policy_id, zone_list[i], 0, &NewDS);
-            KsmRequestKeys(KSM_TYPE_KSK, 1, datetime, printKey, datetime, policy_id, zone_list[i], 0, &NewDS);
-        }
-        else {
-            KsmRequestKeys(key_type, 1, datetime, printKey, datetime, policy_id, zone_list[i], 0, &NewDS);
-        }
-    }
-    StrFree(datetime);
-    free(zone_list);
-
     /* Release sqlite lock file (if we have it) */
     db_disconnect(lock_fd);
 
@@ -1753,7 +1673,7 @@
  * note that fact that a backup has been performed
  */
     int
-cmd_backup ()
+cmd_backup (const char* qualifier)
 {
     int status = 0;
 
@@ -1791,20 +1711,70 @@
         }
     }
 
-    status = KsmMarkBackup(repo_id, datetime);
-    if (status != 0) {
-        printf("Error: failed to mark backup as done\n");
-        db_disconnect(lock_fd);
-        StrFree(datetime);
-        return status;
+    /* Do Pre first */
+    if (strncmp(qualifier, "PREPARE", 7) == 0 ||
+            strncmp(qualifier, "DONE", 4) == 0 ) {
+        status = KsmMarkPreBackup(repo_id, datetime);
+        if (status == -1) {
+            printf("There were no keys to mark\n");
+        }
+        else if (status != 0) {
+            printf("Error: failed to mark pre_backup as done\n");
+            db_disconnect(lock_fd);
+            StrFree(datetime);
+            return status;
+        } else {
+            if (strncmp(qualifier, "PREPARE", 7) == 0) {
+                if (o_repository != NULL) {
+                    printf("Marked repository %s as pre-backed up at %s\n", o_repository, datetime);
+                } else {
+                    printf("Marked all repositories as pre-backed up at %s\n", 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);
+    /* Then commit */
+    if (strncmp(qualifier, "COMMIT", 6) == 0 ||
+            strncmp(qualifier, "DONE", 4) == 0 ) {
+        status = KsmMarkBackup(repo_id, datetime);
+        if (status == -1) {
+            printf("There were no keys to mark\n");
+        }
+        else if (status != 0) {
+            printf("Error: failed to mark backup as done\n");
+            db_disconnect(lock_fd);
+            StrFree(datetime);
+            return status;
+        } else {
+            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);
+            }
+        }
     }
 
+    /* Finally rollback */
+    if (strncmp(qualifier, "ROLLBACK", 6) == 0 ) {
+        status = KsmRollbackMarkPreBackup(repo_id);
+        if (status == -1) {
+            printf("There were no keys to rollback\n");
+        }
+        else if (status != 0) {
+            printf("Error: failed to mark backup as done\n");
+            db_disconnect(lock_fd);
+            StrFree(datetime);
+            return status;
+        } else {
+            if (o_repository != NULL) {
+                printf("Rolled back pre-backup of repository %s\n", o_repository);
+            } else {
+                printf("Rolled back pre-backup of all repositories\n");
+            }
+        }
+    }
+
     StrFree(datetime);
     /* Release sqlite lock file (if we have it) */
     db_disconnect(lock_fd);
@@ -2058,6 +2028,7 @@
     int key_count = -1;
     int keytag_int = -1;
     int temp_key_state = -1;
+    int temp_keypair_id = -1;
     char* temp_cka_id = NULL; /* This will be set if we find a single matching key */
     int user_certain;           /* Continue ? */
 
@@ -2169,7 +2140,7 @@
          * Get a count of keys that match our specifiers, will also print out
          * matching keys; note that zone_id may be overwritten
          */
-        status = CountKeys(&zone_id, keytag_int, o_cka_id, &key_count, &temp_cka_id, &temp_key_state);
+        status = CountKeys(&zone_id, keytag_int, o_cka_id, &key_count, &temp_cka_id, &temp_key_state, &temp_keypair_id);
         if (status != 0) {
             printf("Error: failed to count keys\n");
             db_disconnect(lock_fd);
@@ -2252,6 +2223,7 @@
     int key_count = -1;
     int keytag_int = -1;
     int temp_key_state = -1;
+    int temp_keypair_id = -1;
     char* temp_cka_id = NULL; /* This will be set if we find a single matching key */
     int user_certain;           /* Continue ? */
 
@@ -2296,7 +2268,16 @@
     }
 
     /* Turn zone name into an id (if provided) */
-    if (o_zone != NULL) {
+    /* TODO sort out all flag */
+    /*if (o_zone == NULL && !all_flag) {
+        printf("Please specify a zone or use the --all flag to indicate all zones using this key\n");*/
+    if (o_zone == NULL) {
+        printf("Please specify a zone using the --zone flag\n");
+        usage_keydsseen();
+        StrFree(datetime);
+        return(-1);
+    } 
+    else if (o_zone != NULL) {
         status = KsmZoneIdFromName(o_zone, &zone_id);
         if (status != 0) {
             printf("Error: unable to find a zone named \"%s\" in database\n", o_zone);
@@ -2305,7 +2286,18 @@
             return status;
         }
     }
+    else if (all_flag) {
+        printf("*WARNING* This will act on every zone where this key is in use; are you sure? [y/N] ");
 
+        user_certain = getchar();
+        if (user_certain != 'y' && user_certain != 'Y') {
+            printf("Okay, quitting...\n");
+            exit(0);
+        }
+        
+        zone_id = -1;
+    }
+
     /* Check the keytag is numeric */
     if (o_keytag != NULL) {
         if (StrIsDigits(o_keytag)) {
@@ -2328,7 +2320,7 @@
      * Get a count of keys that match our specifiers, will also print out
      * matching keys; note that zone_id may be overwritten
      */
-    status = CountKeys(&zone_id, keytag_int, o_cka_id, &key_count, &temp_cka_id, &temp_key_state);
+    status = CountKeys(&zone_id, keytag_int, o_cka_id, &key_count, &temp_cka_id, &temp_key_state, &temp_keypair_id);
     if (status != 0) {
         printf("Error: failed to count keys\n");
         db_disconnect(lock_fd);
@@ -2370,7 +2362,7 @@
     }
 
     /* Do stuff */
-    status = MarkDSSeen(temp_cka_id, zone_id, policy_id, datetime, temp_key_state);
+    status = MarkDSSeen(temp_keypair_id, zone_id, policy_id, datetime, temp_key_state);
 
     /* Let them know that it seemed to work */
     if (status == 0) {
@@ -2674,7 +2666,7 @@
     }
 
     /* create basic keypair */
-    status = KsmImportKeyPair(policy_id, o_cka_id, repo_id, size_int, algo_id, state_id, form_time, form_opt_time, &keypair_id);
+    status = KsmImportKeyPair(policy_id, o_cka_id, repo_id, size_int, algo_id, state_id, form_time, &keypair_id);
     if (status != 0) {
         printf("Error: couldn't import key\n");
         db_disconnect(lock_fd);
@@ -2682,11 +2674,11 @@
     }
 
     /* allocate key to zone(s) */
-    if (data.value == 1) {
+    /* TODO might not need this any more */
+/*    if (data.value == 1) {
         status = KsmDnssecKeyCreateOnPolicy(policy_id, (int) keypair_id, keytype_id);
-    } else {
-        status = KsmDnssecKeyCreate(zone_id, (int) keypair_id, keytype_id, &ignore);
-    }
+    } else {*/
+    status = KsmDnssecKeyCreate(zone_id, (int) keypair_id, keytype_id, state_id, form_time, &ignore);
 
     if (status != 0) {
         printf("Error: couldn't allocate key to zone(s)\n");
@@ -3034,9 +3026,12 @@
     } 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();
+        /* verb should be done, prepare, commit, rollback or list */
+        if (!strncmp(case_verb, "DONE", 4) ||
+                !strncmp(case_verb, "PREPARE", 7) ||
+                !strncmp(case_verb, "COMMIT", 6) ||
+                !strncmp(case_verb, "ROLLBACK", 8)) {
+            result = cmd_backup(case_verb);
         }
         else if (!strncmp(case_verb, "LIST", 4)) {
             result = cmd_listbackups();
@@ -4074,13 +4069,14 @@
                 /* If need be link existing keys to zone */
                 if (new_zone == 1) {
                     printf("Added zone %s to database\n", zone_name);
+                /* WITH NEW KEYSHARING LEAVE THIS TO THE ENFORCER TODO - CHECK THIS IS RIGHT */
+                    /*
                     status = KsmLinkKeys(zone_name, policy_id);
                     if (status != 0) {
                         printf("Failed to Link Keys to zone\n");
-                        /* Don't return? try to parse the rest of the zones? */
                         ret = xmlTextReaderRead(reader);
                         continue;
-                    }
+                    }*/
                 }
 
                 /* make a note of the zone_id */
@@ -5291,6 +5287,7 @@
 int PurgeKeys(int zone_id, int policy_id)
 {
     char*       sql = NULL;     /* SQL query */
+    char*       sql1 = NULL;     /* SQL query */
     char*       sql2 = NULL;    /* SQL query */
     char*       sql3 = NULL;    /* SQL query */
     int         status = 0;     /* Status return */
@@ -5299,8 +5296,8 @@
     DB_ROW      row = NULL;     /* Row data */
 
     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         count = 0;          /* How many keys don't match the purge */
 
     int         done_something = 0; /* have we done anything? */
 
@@ -5322,7 +5319,7 @@
     }
 
     /* Select rows */
-    StrAppend(&sql, "select id, dead, location from KEYDATA_VIEW where state = 6 ");
+    StrAppend(&sql, "select distinct id, location from KEYDATA_VIEW where state = 6 ");
     if (zone_id != -1) {
         StrAppend(&sql, "and zone_id = ");
         snprintf(stringval, KSM_INT_STR_SIZE, "%d", zone_id);
@@ -5333,9 +5330,6 @@
         snprintf(stringval, KSM_INT_STR_SIZE, "%d", policy_id);
         StrAppend(&sql, stringval);
     }
-    /* stop us doing the same key twice */
-    StrAppend(&sql, " group by location");
-
     DusEnd(&sql);
 
     status = DbExecuteSql(DbHandle(), sql, &result);
@@ -5343,67 +5337,82 @@
     if (status == 0) {
         status = DbFetchRow(result, &row);
         while (status == 0) {
-            /* Got a row, purge it */
+            /* Got a row, check it */
             DbInt(row, 0, &temp_id);
-            DbString(row, 1, &temp_dead);
-            DbString(row, 2, &temp_loc);
-            done_something = 1;
+            DbString(row, 1, &temp_loc);
 
-            /* Delete from dnsseckeys */
-            sql2 = DdsInit("dnsseckeys");
-            DdsConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
-            DdsEnd(&sql);
+            sql1 = DqsCountInit("dnsseckeys");
+            DdsConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
+            DdsConditionInt(&sql1, "state", DQS_COMPARE_NE, KSM_STATE_DEAD, 1);
+            DqsEnd(&sql1);
 
-            status = DbExecuteSqlNoResult(DbHandle(), sql2);
-            DdsFree(sql2);
-            if (status != 0)
-            {
+            status = DbIntQuery(DbHandle(), &count, sql1);
+            DqsFree(sql1);
+
+            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);
+            /* If the count is zero then there is no reason not to purge this key */
+            if (count == 0) {
 
-            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;
-            }
+                done_something = 1;
 
-            /* Delete from the HSM */
-            key = hsm_find_key_by_id(NULL, temp_loc);
+                /* Delete from dnsseckeys */
+                sql2 = DdsInit("dnsseckeys");
+                DdsConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
+                DdsEnd(&sql);
 
-            if (!key) {
-                printf("Key not found: %s\n", temp_loc);
-                DbStringFree(temp_dead);
-                DbStringFree(temp_loc);
-                DbFreeRow(row);
-                return -1;
-            }
+                status = DbExecuteSqlNoResult(DbHandle(), sql2);
+                DdsFree(sql2);
+                if (status != 0)
+                {
+                    printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
+                    DbStringFree(temp_loc);
+                    DbFreeRow(row);
+                    return status;
+                }
 
-            status = hsm_remove_key(NULL, key);
+                /* Delete from keypairs */
+                sql3 = DdsInit("keypairs");
+                DdsConditionInt(&sql3, "id", DQS_COMPARE_EQ, temp_id, 0);
+                DdsEnd(&sql);
 
-            hsm_key_free(key);
+                status = DbExecuteSqlNoResult(DbHandle(), sql3);
+                DdsFree(sql3);
+                if (status != 0)
+                {
+                    printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
+                    DbStringFree(temp_loc);
+                    DbFreeRow(row);
+                    return status;
+                }
 
-            if (!status) {
-                printf("Key remove successful.\n");
-            } else {
-                printf("Key remove failed.\n");
-                DbStringFree(temp_dead);
-                DbStringFree(temp_loc);
-                DbFreeRow(row);
-                return -1;
+                /* 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_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_loc);
+                    DbFreeRow(row);
+                    return -1;
+                }
             }
 
             /* NEXT! */ 
@@ -5426,7 +5435,6 @@
     DusFree(sql);
     DbFreeRow(row);
 
-    DbStringFree(temp_dead);
     DbStringFree(temp_loc);
 
     return status;
@@ -5453,6 +5461,9 @@
     int new_keys = 0;       /* number of keys required */
     unsigned int current_count = 0;  /* number of keys already in HSM */
 
+    DB_RESULT result; 
+    int zone_count = 0;     /* Number of zones on policy */
+
     int same_keys = 0;      /* Do ksks and zsks look the same ? */
     int ksks_created = 0;   /* Were any KSKs created? */
 
@@ -5592,8 +5603,27 @@
     } else {
         same_keys = 0;
     }
+
+    /* How many zones on this policy */ 
+    status = KsmZoneCountInit(&result, policy->id); 
+    if (status == 0) { 
+        status = KsmZoneCount(result, &zone_count); 
+    } 
+    DbFreeResult(result); 
+
+    if (status == 0) { 
+        /* make sure that we have at least one zone */ 
+        if (zone_count == 0) { 
+            printf("No zones on policy %s, skipping...", policy->name);
+            return status; 
+        } 
+    } else {
+        printf("Could not count zones on policy %s", policy->name);
+        return status; 
+    }
+
     /* Find out how many ksk keys are needed for the POLICY */
-    status = KsmKeyPredict(policy->id, KSM_TYPE_KSK, policy->shared_keys, interval, &ksks_needed, policy->ksk->rollover_scheme);
+    status = KsmKeyPredict(policy->id, KSM_TYPE_KSK, policy->shared_keys, interval, &ksks_needed, policy->ksk->rollover_scheme, zone_count);
     if (status != 0) {
         printf("Could not predict ksk requirement for next interval for %s\n", policy->name);
         /* TODO exit? continue with next policy? */
@@ -5604,6 +5634,10 @@
         printf("Could not count current ksk numbers for policy %s\n", policy->name);
         /* TODO exit? continue with next policy? */
     }
+    /* Correct for shared keys */
+    if (policy->shared_keys == KSM_KEYS_SHARED) {
+        keys_in_queue /= zone_count;
+    }
 
     new_keys = ksks_needed - keys_in_queue;
     /* fprintf(stderr, "keygen(ksk): new_keys(%d) = keys_needed(%d) - keys_in_queue(%d)\n", new_keys, ksks_needed, keys_in_queue); */
@@ -5673,7 +5707,7 @@
     current_count = 0;
 
     /* Find out how many zsk keys are needed for the POLICY */
-    status = KsmKeyPredict(policy->id, KSM_TYPE_ZSK, policy->shared_keys, interval, &zsks_needed, 0);
+    status = KsmKeyPredict(policy->id, KSM_TYPE_ZSK, policy->shared_keys, interval, &zsks_needed, 0, zone_count);
     if (status != 0) {
         printf("Could not predict zsk requirement for next interval for %s\n", policy->name);
         /* TODO exit? continue with next policy? */
@@ -5684,6 +5718,10 @@
         printf("Could not count current zsk numbers for policy %s\n", policy->name);
         /* TODO exit? continue with next policy? */
     }
+    /* Correct for shared keys */
+    if (policy->shared_keys == KSM_KEYS_SHARED) {
+        keys_in_queue /= zone_count;
+    }
     /* Might have to account for ksks */
     if (same_keys) {
         keys_in_queue -= ksks_needed;
@@ -5982,13 +6020,15 @@
  *      int * temp_key_state (returned)
  *          What state is the key in (only used if _one_ key returned)
  *
+ *      int * temp_keypair_id (returned)
+ *          ID of the key found (only used if _one_ key returned)
  * Returns:
  *      int
  *          Status return.  0 on success.
  *                          other on fail
  */
 
-int CountKeys(int *zone_id, int keytag, const char *cka_id, int *key_count, char **temp_cka_id, int *temp_key_state)
+int CountKeys(int *zone_id, int keytag, const char *cka_id, int *key_count, char **temp_cka_id, int *temp_key_state, int *temp_keypair_id)
 {
     char*       sql = NULL;     /* SQL query */
     int         status = 0;     /* Status return */
@@ -6005,6 +6045,7 @@
     char*       temp_loc = NULL;    /* place to store location returned */
     int         temp_alg = 0;       /* place to store algorithm returned */
     int         temp_state = 0;     /* place to store state returned */
+    int         temp_keypair = 0;   /* place to store id returned */
 
     int         temp_count = 0;     /* Count of keys found */
 
@@ -6029,7 +6070,7 @@
     }
 
     /* TODO do I need to use the view */
-    StrAppend(&sql, "select k.zone_id, k.location, k.algorithm, k.state from KEYDATA_VIEW k where state in ");
+    StrAppend(&sql, "select k.zone_id, k.location, k.algorithm, k.state, k.id from KEYDATA_VIEW k where state in ");
     StrAppend(&sql, buffer);
     StrAppend(&sql, " and zone_id is not null and k.keytype = 257");
 
@@ -6062,6 +6103,7 @@
             DbString(row, 1, &temp_loc);
             DbInt(row, 2, &temp_alg);
             DbInt(row, 3, &temp_state);
+            DbInt(row, 4, &temp_keypair);
 
             done_row = 0;
 
@@ -6091,6 +6133,7 @@
                     StrAppend(temp_cka_id, temp_loc);
                     *zone_id = temp_zone_id;
                     *temp_key_state = temp_state;
+                    *temp_keypair_id = temp_keypair;
                     printf("Found key with CKA_ID %s\n", temp_loc);
                 }
 
@@ -6104,6 +6147,7 @@
                     StrAppend(temp_cka_id, temp_loc);
                     *zone_id = temp_zone_id;
                     *temp_key_state = temp_state;
+                    *temp_keypair_id = temp_keypair;
                     printf("Found key with CKA_ID %s\n", temp_loc);
                 }
             }
@@ -6165,7 +6209,7 @@
  *                          other on fail
  */
 
-int MarkDSSeen(const char *cka_id, int zone_id, int policy_id, const char *datetime, int key_state)
+int MarkDSSeen(int keypair_id, int zone_id, int policy_id, const char *datetime, int key_state)
 {
     char*       sql1 = NULL;    /* SQL query */
     int         status = 0;     /* Status return */
@@ -6212,13 +6256,14 @@
                 "DATETIME('%s', '+%d SECONDS') ", datetime, deltat);
 #endif /* USE_MYSQL */
 
-        sql1 = DusInit("keypairs");
+        sql1 = DusInit("dnsseckeys");
         DusSetInt(&sql1, "STATE", KSM_STATE_ACTIVE, 0);
         DusSetString(&sql1, KsmKeywordStateValueToName(KSM_STATE_ACTIVE), datetime, 1);
         StrAppend(&sql1, ", RETIRE = ");
         StrAppend(&sql1, buffer);
 
-        DusConditionString(&sql1, "HSMkey_id", DQS_COMPARE_EQ, cka_id, 0);
+        DusConditionInt(&sql1, "KEYPAIR_ID", DQS_COMPARE_EQ, keypair_id, 0);
+        DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
         DusEnd(&sql1);
     }
     else {
@@ -6236,13 +6281,14 @@
                 "DATETIME('%s', '+%d SECONDS') ", datetime, deltat);
 #endif /* USE_MYSQL */
 
-        sql1 = DusInit("keypairs");
+        sql1 = DusInit("dnsseckeys");
         DusSetInt(&sql1, "STATE", KSM_STATE_DSPUBLISH, 0);
         DusSetString(&sql1, KsmKeywordStateValueToName(KSM_STATE_PUBLISH), datetime, 1);
         StrAppend(&sql1, ", READY = ");
         StrAppend(&sql1, buffer);
 
-        DusConditionString(&sql1, "HSMkey_id", DQS_COMPARE_EQ, cka_id, 0);
+        DusConditionInt(&sql1, "KEYPAIR_ID", DQS_COMPARE_EQ, keypair_id, 0);
+        DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
         DusEnd(&sql1);
     }
 
@@ -6352,12 +6398,13 @@
         "DATETIME('%s', '+%d SECONDS') ", datetime, deltat);
 #endif /* USE_MYSQL */
 
-    sql2 = DusInit("keypairs");
+    sql2 = DusInit("dnsseckeys");
     DusSetInt(&sql2, "STATE", KSM_STATE_RETIRE, 0);
     DusSetString(&sql2, KsmKeywordStateValueToName(KSM_STATE_RETIRE), datetime, 1);
     StrAppend(&sql2, ", DEAD = ");
     StrAppend(&sql2, buffer);
-    DusConditionInt(&sql2, "ID", DQS_COMPARE_EQ, id, 0);
+    DusConditionInt(&sql2, "keypair_id", DQS_COMPARE_EQ, id, 0);
+    DusConditionInt(&sql2, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
 
     status = DbExecuteSqlNoResult(DbHandle(), sql2);
     DusFree(sql2);
@@ -6466,6 +6513,16 @@
     char*       sql1 = NULL;    /* SQL query */
     int         status = 0;     /* Status return */
 
+    int     count = 0;      /* Count of keys whose date will be set */
+    char*   sql = NULL;     /* For creating the SQL command */
+    int     where = 0;      /* For the SQL selection */
+    int     i = 0;          /* A counter */
+    int     j = 0;          /* Another counter */
+    char*   insql = NULL;   /* SQL "IN" clause */
+    int*    keyids;         /* List of IDs of keys to promote */
+    DB_RESULT    result;    /* List result set */
+    KSM_KEYDATA  data;      /* Data for this key */
+
     char            buffer[KSM_SQL_SIZE];    /* Long enough for any statement */
     unsigned int    nchar;          /* Number of characters converted */
     
@@ -6484,6 +6541,86 @@
         return status;
     }
 
+    /* Count how many keys will have their state changed */
+
+    sql = DqsCountInit("KEYDATA_VIEW");
+    DqsConditionString(&sql, "location", DQS_COMPARE_EQ, cka_id, where++);
+    if (zone_id != -1) {
+        DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
+    }
+    DqsEnd(&sql);
+
+    status = DbIntQuery(DbHandle(), &count, sql);
+    DqsFree(sql);
+
+    if (status != 0) {
+        status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
+        return status;
+    }
+
+    if (count == 0) {
+        /* Nothing to do, error? */
+        return status;
+    }
+
+    /* Allocate space for the list of key IDs */
+    keyids = MemMalloc(count * sizeof(int));
+
+    /* Get the list of IDs */
+
+    where = 0;
+    sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
+    DqsConditionString(&sql, "location", DQS_COMPARE_EQ, cka_id, where++);
+    if (zone_id != -1) {
+        DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
+    }
+    DqsEnd(&sql);
+
+    status = KsmKeyInitSql(&result, sql);
+    DqsFree(sql);
+
+    if (status == 0) {
+        while (status == 0) {
+            status = KsmKey(result, &data);
+            if (status == 0) {
+                keyids[i] = data.keypair_id;
+                i++;
+            }
+        }
+
+        /* Convert EOF status to success */
+
+        if (status == -1) {
+            status = 0;
+        } else {
+            status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
+            StrFree(keyids);
+            return status;
+        }
+
+        KsmKeyEnd(result);
+
+    } else {
+        status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
+        StrFree(keyids);
+		return status;
+	}
+    
+    /*
+     * Now construct the "IN" statement listing the IDs of the keys we
+     * are planning to change the state of.
+     */
+
+    StrAppend(&insql, "(");
+    for (j = 0; j < i; ++j) {
+        if (j != 0) {
+            StrAppend(&insql, ",");
+        }
+        snprintf(buffer, sizeof(buffer), "%d", keyids[j]);
+        StrAppend(&insql, buffer);
+    }
+    StrAppend(&insql, ")");
+
 /* 0) Start a transaction */
     status = DbBeginTransaction();
     if (status != 0) {
@@ -6508,13 +6645,16 @@
                 "DATETIME('%s', '+%d SECONDS') ", datetime, deltat);
 #endif /* USE_MYSQL */
 
-        sql1 = DusInit("keypairs");
+        sql1 = DusInit("dnsseckeys");
         DusSetInt(&sql1, "STATE", KSM_STATE_ACTIVE, 0);
         DusSetString(&sql1, KsmKeywordStateValueToName(KSM_STATE_ACTIVE), datetime, 1);
         StrAppend(&sql1, ", RETIRE = ");
         StrAppend(&sql1, buffer);
 
-        DusConditionString(&sql1, "HSMkey_id", DQS_COMPARE_EQ, cka_id, 0);
+        DusConditionKeyword(&sql1, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0);
+        if (zone_id != -1) {
+            DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
+        }
         DusEnd(&sql1);
     }
     else if (keystate == KSM_STATE_RETIRE) {
@@ -6537,13 +6677,16 @@
                 "DATETIME('%s', '+%d SECONDS') ", datetime, deltat);
 #endif /* USE_MYSQL */
 
-        sql1 = DusInit("keypairs");
+        sql1 = DusInit("dnsseckeys");
         DusSetInt(&sql1, "STATE", KSM_STATE_RETIRE, 0);
         DusSetString(&sql1, KsmKeywordStateValueToName(KSM_STATE_RETIRE), datetime, 1);
         StrAppend(&sql1, ", DEAD = ");
         StrAppend(&sql1, buffer);
 
-        DusConditionString(&sql1, "HSMkey_id", DQS_COMPARE_EQ, cka_id, 0);
+        DusConditionKeyword(&sql1, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0);
+        if (zone_id != -1) {
+            DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
+        }
         DusEnd(&sql1);
     }
     else if (keystate == KSM_STATE_DSPUBLISH) {
@@ -6559,13 +6702,16 @@
                 "DATETIME('%s', '+%d SECONDS') ", datetime, deltat);
 #endif /* USE_MYSQL */
 
-        sql1 = DusInit("keypairs");
+        sql1 = DusInit("dnsseckeys");
         DusSetInt(&sql1, "STATE", KSM_STATE_DSPUBLISH, 0);
         DusSetString(&sql1, KsmKeywordStateValueToName(KSM_STATE_PUBLISH), datetime, 1);
         StrAppend(&sql1, ", READY = ");
         StrAppend(&sql1, buffer);
 
-        DusConditionString(&sql1, "HSMkey_id", DQS_COMPARE_EQ, cka_id, 0);
+        DusConditionKeyword(&sql1, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0);
+        if (zone_id != -1) {
+            DusConditionInt(&sql1, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
+        }
         DusEnd(&sql1);
     }
     else {
@@ -6576,6 +6722,8 @@
     status = DbExecuteSqlNoResult(DbHandle(), sql1);
     DusFree(sql1);
 
+    StrFree(keyids);
+    
     /* Report any errors */
     if (status != 0) {
         status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
@@ -6601,3 +6749,479 @@
 	   OPENDNSSEC_ENFORCER_PIDFILE and send a SIGHUP itself */
 	return system(RESTART_ENFORCERD_CMD);
 }
+
+/* 
+ *  Read the conf.xml file, we will not validate as that was done as we read the database.
+ *  Instead we just extract the RepositoryList into the database and also learn the 
+ *  location of the zonelist.
+ */
+int get_conf_key_info(int* interval, int* man_key_gen)
+{
+    int status = 0;
+    int mysec = 0;
+    xmlDocPtr doc = NULL;
+    xmlXPathContextPtr xpathCtx = NULL;
+    xmlXPathObjectPtr xpathObj = NULL;
+    char* temp_char = NULL;
+
+    xmlChar *iv_expr = (unsigned char*) "//Configuration/Enforcer/Interval";
+    xmlChar *mk_expr = (unsigned char*) "//Configuration/Enforcer/ManualKeyGeneration";
+
+    /* Load XML document */
+    doc = xmlParseFile(config);
+    if (doc == NULL) {
+        printf("Error: unable to parse file \"%s\"\n", config);
+        return(-1);
+    }
+
+    /* Create xpath evaluation context */
+    xpathCtx = xmlXPathNewContext(doc);
+    if(xpathCtx == NULL) {
+        printf("Error: unable to create new XPath context\n");
+        xmlFreeDoc(doc);
+        return(-1);
+    }
+    
+    /* Evaluate xpath expression for interval */
+    xpathObj = xmlXPathEvalExpression(iv_expr, xpathCtx);
+    if(xpathObj == NULL) {
+        printf("Error: unable to evaluate xpath expression: %s", iv_expr);
+        xmlXPathFreeContext(xpathCtx);
+        xmlFreeDoc(doc);
+        return(-1);
+    }
+
+    temp_char = (char *)xmlXPathCastToString(xpathObj);
+    status = DtXMLIntervalSeconds(temp_char, &mysec);
+    if (status > 0) {
+        printf("Error: unable to convert Interval %s to seconds, error: %i\n", temp_char, status);
+        StrFree(temp_char);
+        return status;
+    }
+    else if (status == -1) {
+        printf("Warning: converting %s to seconds may not give what you expect\n", temp_char);
+    }
+    *interval = mysec;
+    StrFree(temp_char);
+    xmlXPathFreeObject(xpathObj);
+
+    /* Evaluate xpath expression for Manual key generation */
+    xpathObj = xmlXPathEvalExpression(mk_expr, xpathCtx);
+    if(xpathObj == NULL) {
+        printf("Error: unable to evaluate xpath expression: %s\n", mk_expr);
+        xmlXPathFreeContext(xpathCtx);
+        xmlFreeDoc(doc);
+        return(-1);
+    }
+
+    if (xpathObj->nodesetval != NULL && xpathObj->nodesetval->nodeNr > 0) {
+        /* Manual key generation tag is present */
+        *man_key_gen = 1;
+    }
+    else {
+        /* Tag absent */
+        *man_key_gen = 0;
+    }
+    xmlXPathFreeObject(xpathObj);
+
+    if (xpathCtx) {
+        xmlXPathFreeContext(xpathCtx);
+    }
+    if (doc) {
+        xmlFreeDoc(doc);
+    }
+
+    return 0;
+}
+
+/* TODO put this fn and the one below somewhere that we can call it from here and the enforcer */
+ /*+
+ * LinkKeys - Create required entries in Dnsseckeys table for zones added to policies
+ *                      (i.e. when keysharing is turned on)
+ *
+ * Description:
+ *      Allocates a key in the database.
+ *
+ * Arguments:
+ *      const char* zone_name
+ *          name of zone
+ *
+ *      int policy_id
+ *          ID of policy which the zone is on
+ *
+ *      int interval
+ *          Enforcer run interval
+ *
+ *      int man_key_gen
+ *          Manual Key Generation flag
+ *
+ * Returns:
+ *      int
+ *          Status return.  0=> Success, non-zero => error.
+-*/
+
+int LinkKeys(const char* zone_name, int policy_id)
+{
+    int status = 0;
+
+    int interval = -1;          /* Enforcer interval */
+    int man_key_gen = -1;       /* Manual key generation flag */
+
+    int             zone_id = 0;    /* id of zone supplied */ 
+    KSM_POLICY* policy;
+
+    /* Get some info from conf.xml */
+    status = get_conf_key_info(&interval, &man_key_gen);
+    if (status != 0) {
+        printf("Failed to Link Keys to zone\n");
+        return(1);
+    }
+
+    status = KsmZoneIdFromName(zone_name, &zone_id);
+    if (status != 0) {
+        return(status);
+    }
+
+    policy = KsmPolicyAlloc();
+    if (policy == NULL) {
+        printf("Malloc for policy struct failed\n");
+        exit(1);
+    }
+    SetPolicyDefaults(policy, o_policy);
+
+    status = KsmPolicyExists(o_policy);
+    if (status == 0) {
+        /* Policy exists */
+        status = KsmPolicyRead(policy);
+        if(status != 0) {
+            printf("Error: unable to read policy %s from database\n", o_policy);
+            KsmPolicyFree(policy);
+            return status;
+        }
+    } else {
+        printf("Error: policy %s doesn't exist in database\n", o_policy);
+        KsmPolicyFree(policy);
+        return status;
+    }
+
+    /* Make sure that enough keys are allocated to this zone */
+    status = allocateKeysToZone(policy, KSM_TYPE_ZSK, zone_id, interval, zone_name, man_key_gen, 0);
+    if (status != 0) {
+        printf("Error allocating zsks to zone %s", zone_name);
+        KsmPolicyFree(policy);
+        return(status);
+    }
+    status = allocateKeysToZone(policy, KSM_TYPE_KSK, zone_id, interval, zone_name, man_key_gen, policy->ksk->rollover_scheme);
+    if (status != 0) {
+        printf("Error allocating ksks to zone %s", zone_name);
+        KsmPolicyFree(policy);
+        return(status);
+    }
+
+    KsmPolicyFree(policy);
+    return 0;
+}
+
+/* allocateKeysToZone
+ *
+ * Description:
+ *      Allocates existing keys to zones
+ *
+ * Arguments:
+ *      policy
+ *          policy that the keys were created for
+ *      key_type
+ *          KSK or ZSK
+ *      zone_id
+ *          ID of zone in question
+ *      interval
+ *          time before next run
+ *      zone_name
+ *          just in case we need to log something
+ *      man_key_gen
+ *          lack of keys may be an issue for the user to fix
+ *      int rollover_scheme
+ *          KSK rollover scheme in use
+ *
+ * Returns:
+ *      int
+ *          Status return.  0=> Success, non-zero => error.
+ *          1 == error with input
+ *          2 == not enough keys to satisfy policy
+ *          3 == database error
+ -*/
+
+
+int allocateKeysToZone(KSM_POLICY *policy, int key_type, int zone_id, uint16_t interval, const char* zone_name, int man_key_gen, int rollover_scheme)
+{
+    int status = 0;
+    int keys_needed = 0;
+    int keys_in_queue = 0;
+    int keys_pending_retirement = 0;
+    int new_keys = 0;
+    int key_pair_id = 0;
+    int i = 0;
+    DB_ID ignore = 0;
+    KSM_PARCOLL collection; /* Parameters collection */
+    char*   datetime = DtParseDateTimeString("now");
+
+    /* Check datetime in case it came back NULL */
+    if (datetime == NULL) {
+        printf("Couldn't turn \"now\" into a date, quitting...");
+        exit(1);
+    }
+
+    if (policy == NULL) {
+        printf("NULL policy sent to allocateKeysToZone");
+        StrFree(datetime);
+        return 1;
+    }
+
+    if (key_type != KSM_TYPE_KSK && key_type != KSM_TYPE_ZSK) {
+        printf("Unknown keytype: %i in allocateKeysToZone", key_type);
+        StrFree(datetime);
+        return 1;
+    }
+
+    /* Get list of parameters */
+    status = KsmParameterCollection(&collection, policy->id);
+    if (status != 0) {
+        StrFree(datetime);
+        return status;
+    }
+
+    /* Make sure that enough keys are allocated to this zone */
+    /* How many do we need ? (set sharing to 1 so that we get the number needed for a single zone on this policy */
+    status = KsmKeyPredict(policy->id, key_type, 1, interval, &keys_needed, rollover_scheme, 1);
+    if (status != 0) {
+        printf("Could not predict key requirement for next interval for %s", zone_name);
+        StrFree(datetime);
+        return 3;
+    }
+
+    /* How many do we have ? TODO should this include the currently active key?*/
+    status = KsmKeyCountQueue(key_type, &keys_in_queue, zone_id);
+    if (status != 0) {
+        printf("Could not count current key numbers for zone %s", zone_name);
+        StrFree(datetime);
+        return 3;
+    }
+
+    /* or about to retire */
+    status = KsmRequestPendingRetireCount(key_type, datetime, &collection, &keys_pending_retirement, zone_id, interval);
+    if (status != 0) {
+        printf("Could not count keys which may retire before the next run (for zone %s)", zone_name);
+        StrFree(datetime);
+        return 3;
+    }
+
+    StrFree(datetime);
+    new_keys = keys_needed - (keys_in_queue - keys_pending_retirement);
+
+    /* fprintf(stderr, "comm(%d) %s: new_keys(%d) = keys_needed(%d) - (keys_in_queue(%d) - keys_pending_retirement(%d))\n", key_type, zone_name, new_keys, keys_needed, keys_in_queue, keys_pending_retirement); */
+
+    /* Allocate keys */
+    for (i=0 ; i < new_keys ; i++){
+        key_pair_id = 0;
+        if (key_type == KSM_TYPE_KSK) {
+            status = KsmKeyGetUnallocated(policy->id, policy->ksk->sm, policy->ksk->bits, policy->ksk->algorithm, zone_id, &key_pair_id);
+            if (status == -1 || key_pair_id == 0) {
+                if (man_key_gen == 0) {
+                    printf("Not enough keys to satisfy ksk policy for zone: %s", zone_name);
+                    printf("ods-enforcerd will create some more keys on its next run");
+                }
+                else {
+                    printf("Not enough keys to satisfy ksk policy for zone: %s", zone_name);
+                    printf("please use \"ods-ksmutil key generate\" to create some more keys.");
+                }
+                return 2;
+            }
+            else if (status != 0) {
+                printf("Could not get an unallocated ksk for zone: %s", zone_name);
+                return 3;
+            }
+        } else {
+            status = KsmKeyGetUnallocated(policy->id, policy->zsk->sm, policy->zsk->bits, policy->zsk->algorithm, zone_id, &key_pair_id);
+            if (status == -1 || key_pair_id == 0) {
+                if (man_key_gen == 0) {
+                    printf("Not enough keys to satisfy zsk policy for zone: %s", zone_name);
+                    printf("ods-enforcerd will create some more keys on its next run");
+                }
+                else {
+                    printf("Not enough keys to satisfy zsk policy for zone: %s", zone_name);
+                    printf("please use \"ods-ksmutil key generate\" to create some more keys.");
+                }
+                return 2;
+            }
+            else if (status != 0) {
+                printf("Could not get an unallocated zsk for zone: %s", zone_name);
+                return 3;
+            }
+        }
+        if(key_pair_id > 0) {
+            status = KsmDnssecKeyCreate(zone_id, key_pair_id, key_type, KSM_STATE_GENERATE, datetime, &ignore);
+            /* fprintf(stderr, "comm(%d) %s: allocated keypair id %d\n", key_type, zone_name, key_pair_id); */
+        } else {
+            /* This shouldn't happen */
+            printf("KsmKeyGetUnallocated returned bad key_id %d for zone: %s; exiting...", key_pair_id, zone_name);
+            exit(1);
+        }
+
+    }
+
+    return status;
+}
+
+
+/* keyRoll
+ *
+ * Description:
+ *      Rolls keys far enough for the enforcer to take over
+ *
+ * Arguments:
+ *      zone_id
+ *          ID of zone in question (-1 == all)
+ *      policy_id
+ *          policy that should be rolled (-1 == all)
+ *      key_type
+ *          KSK or ZSK (-1 == all)
+ *
+ * Returns:
+ *      int
+ *          Status return.  0=> Success, non-zero => error.
+ -*/
+
+int keyRoll(int zone_id, int policy_id, int key_type)
+{
+
+    int status = 0;
+    int size = -1;
+
+    char*       sql = NULL;     /* SQL query */
+    char*       sql1 = NULL;    /* SQL query */
+    char        sql2[KSM_SQL_SIZE];
+    DB_RESULT	result1;        /* Result of the query */
+    DB_ROW      row = NULL;     /* Row data */
+    int         temp_id = -1;   /* place to store the key id returned */
+    int         temp_type = -1; /* place to store the key type returned */
+    int         where = 0;
+    
+    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");
+        StrFree(datetime);
+        exit(1);
+    }
+
+    /* retire the active key(s) */
+    /* Find the key ID */
+    sql = DqsSpecifyInit("KEYDATA_VIEW","id, keytype");
+    if (zone_id != -1) {
+        DqsConditionInt(&sql, "zone_id", DQS_COMPARE_EQ, zone_id, where++);
+    }
+    if (policy_id != -1) {
+        DqsConditionInt(&sql, "policy_id", DQS_COMPARE_EQ, policy_id, where++);
+    }
+    DqsConditionInt(&sql, "state", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, where++);
+    if (key_type != -1) {
+        DqsConditionInt(&sql, "keytype", DQS_COMPARE_EQ, key_type, where++);
+    }
+    DqsEnd(&sql);
+
+    status = DbExecuteSql(DbHandle(), sql, &result1);
+
+    if (status == 0) {
+        status = DbFetchRow(result1, &row);
+        while (status == 0) {
+            /* Got a row, deal with it */
+            DbInt(row, 0, &temp_id);
+            DbInt(row, 1, &temp_type);
+
+            sql1 = DusInit("keypairs");
+            DusSetInt(&sql1, "fixedDate", 1, 0);
+            DusSetInt(&sql1, "compromisedflag", 1, 1);
+
+            DusConditionInt(&sql1, "id", DQS_COMPARE_EQ, temp_id, 0);
+            DusEnd(&sql1);
+            status = DbExecuteSqlNoResult(DbHandle(), sql1);
+            DusFree(sql1);
+
+            /* Report any errors */
+            if (status != 0) {
+                printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
+                return status;
+            }
+
+            /* Loop over instances of this key: */
+            /* active-> set retire time */
+            sql1 = DusInit("dnsseckeys");
+            DusSetString(&sql1, "RETIRE", datetime, 0);
+
+            DusConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
+            DusConditionInt(&sql1, "state", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, 1);
+            DusEnd(&sql1);
+            status = DbExecuteSqlNoResult(DbHandle(), sql1);
+            DusFree(sql1);
+
+            /* Report any errors */
+            if (status != 0) {
+                printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
+                return status;
+            }
+
+            /* other-> move to dead */
+            sql1 = DusInit("dnsseckeys");
+            DusSetString(&sql1, "DEAD", datetime, 0);
+            DusSetInt(&sql1, "state", KSM_STATE_DEAD, 1);
+
+            DusConditionInt(&sql1, "keypair_id", DQS_COMPARE_EQ, temp_id, 0);
+            DusConditionInt(&sql1, "state", DQS_COMPARE_NE, KSM_STATE_ACTIVE, 1);
+            DusEnd(&sql1);
+            status = DbExecuteSqlNoResult(DbHandle(), sql1);
+            DusFree(sql1);
+
+            /* Report any errors */
+            if (status != 0) {
+                printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
+                return status;
+            }
+           
+            /* Promote any standby keys if we need to, i.e. we retired a KSK 
+               and there is nothing able to take over from it */
+            if (temp_type == KSM_TYPE_KSK) {
+                /* find each zone in turn */
+                size = snprintf(sql2, KSM_SQL_SIZE, "update dnsseckeys set state = %d where state = %d and zone_id in (select zone_id from dnsseckeys where retire = \"%s\" and keypair_id = %d) and zone_id not in (select zone_id from KEYDATA_VIEW where policy_id = %d and keytype = %d and state in (%d,%d))", KSM_STATE_KEYPUBLISH, KSM_STATE_DSREADY, datetime, temp_id, policy_id, KSM_TYPE_KSK, KSM_STATE_PUBLISH, KSM_STATE_READY);
+
+                /* Quick check that we didn't run out of space */
+                if (size < 0 || size >= KSM_SQL_SIZE) {
+                    printf("Couldn't construct SQL to promote standby key\n");
+                    return -1;
+                }
+
+                status = DbExecuteSqlNoResult(DbHandle(), sql2);
+
+                /* Report any errors */
+                if (status != 0) {
+                    printf("SQL failed: %s\n", DbErrmsg(DbHandle()));
+                    return status;
+                }
+            }
+
+            /* NEXT KEY */ 
+            status = DbFetchRow(result1, &row);
+        }
+
+        /* Convert EOF status to success */
+        if (status == -1) {
+            status = 0;
+        }
+        DbFreeResult(result1);
+    }
+    DqsFree(sql);
+
+    StrFree(datetime);
+    
+    return status;
+}

Modified: trunk/OpenDNSSEC/enforcer/utils/ods-ksmutil.1.in
===================================================================
--- trunk/OpenDNSSEC/enforcer/utils/ods-ksmutil.1.in	2010-08-24 13:55:07 UTC (rev 3775)
+++ trunk/OpenDNSSEC/enforcer/utils/ods-ksmutil.1.in	2010-08-24 14:55:39 UTC (rev 3776)
@@ -25,7 +25,7 @@
 .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 ...
@@ -242,23 +242,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:
-.br
-1. Issue \fBods-control ksm stop\fR
-.br
-2. Make a backup of the repository
-.br
-3. Issue \fBods-ksmutil backup done\fR
-.br
-4. 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).




More information about the Opendnssec-commits mailing list