OpenDNSSEC-enforcer  1.4.5
ksm_request.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008-2009 Nominet UK. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 /*+
28  * ksm_request.c - Handle Request Keys Processing
29  *
30  * Description:
31  * The REQUEST command asks KSM to list the keys to be included in the
32  * zone when it is next signed. It can optionally force a rollover by
33  * marking the active key as retired.
34 -*/
35 
36 #include <assert.h>
37 #include <stdio.h>
38 #include <string.h>
39 
40 #include "ksm/database.h"
41 #include "ksm/database_statement.h"
42 #include "ksm/db_fields.h"
43 #include "ksm/debug.h"
44 #include "ksm/ksm.h"
45 #include "ksm/kmedef.h"
46 #include "ksm/ksmdef.h"
47 #include "ksm/message.h"
48 #include "ksm/memory.h"
49 #include "ksm/string_util.h"
50 #include "ksm/string_util2.h"
51 
52 /* TODO The nomenclature needs to be updated to agree with that in the timing draft */
53 
54 /*+
55  * KsmRequestKeys - Request Keys for Output
56  *
57  * Description:
58  * Updates the key times and then calls KsmRequestKeysByType to process
59  * keys of the type chosen by the keytype argument.
60  *
61  * Arguments:
62  * int keytype
63  * Key type for which the request should happen.
64  *
65  * KSM_TYPE_KSK KSKs
66  * KSM_TYPE_ZSK ZSKs
67  * Other Both KSK and ZSK
68  *
69  * int rollover
70  * 1 to force a rollover, 0 to ignore
71  *
72  * const char* datetime
73  * Time at which the request is issued. Comparisons for key
74  * expirations etc. will be against this time.
75  *
76  * KSM_REQUEST_CALLBACK callback
77  * Callback function called for every key that will be issued.
78  *
79  * void* context
80  * Context argument passed uninterpreted to the callback function.
81  *
82  * int policy_id
83  * ID of policy that we are looking at
84  *
85  * int zone_id
86  * ID of zone that we are looking at (-1 == all zones)
87  *
88  * int run_interval
89  * how frequently do we run?
90  *
91  * int* NewDS
92  * were new DS records needed?
93 -*/
94 
95 int KsmRequestKeys(int keytype, int rollover, const char* datetime,
96  KSM_REQUEST_CALLBACK callback, void* context, int policy_id, int zone_id,
97  int run_interval, int* NewDS)
98 {
99  int status; /* Status return */
100 
101  /* Start the transaction */
102  status = DbBeginTransaction();
103  if (status != 0) {
104  /* Something went wrong */
105 
107  return status;
108  }
109 
110  /* Update the estimated times of state change */
111  status = KsmUpdate(policy_id, zone_id);
112  if (status == 0) {
113 
114  /* Process all key types */
115 
116  if ((keytype == KSM_TYPE_KSK) || (keytype == KSM_TYPE_ZSK)) {
117  status = KsmRequestKeysByType(keytype, rollover, datetime,
118  callback, context, policy_id, zone_id, run_interval, NewDS);
119 
120  if (status != 0) {
121  DbRollback();
122  return status;
123  }
124  }
125  else {
126  status = KsmRequestKeysByType(KSM_TYPE_KSK, rollover, datetime,
127  callback, context, policy_id, zone_id, run_interval, NewDS);
128  if (status != 0) {
129  DbRollback();
130  return status;
131  }
132 
133  status = KsmRequestKeysByType(KSM_TYPE_ZSK, rollover, datetime,
134  callback, context, policy_id, zone_id, run_interval, NewDS);
135  if (status != 0) {
136  DbRollback();
137  return status;
138  }
139  }
140 
141  /*
142  * Finally, update the key times again, in case any keys were
143  * moved between states.
144  */
145 
146  status = KsmUpdate(policy_id, zone_id);
147  if (status != 0) {
148  DbRollback();
149  return status;
150  }
151  else
152  {
153  /* Everything worked by the looks of it */
154  DbCommit();
155  }
156  }
157  else
158  {
159  /* Whatever happened, it was not good */
160  DbRollback();
161  }
162 
163  return status;
164 }
165 
166 
167 /*+
168  * KsmRequestKeysByType - Request Keys for Output
169  *
170  * Description:
171  * Does REQUEST KEYS processing for keys of a given type.
172  *
173  * Arguments:
174  * int keytype
175  * Key type for which the request should happen.
176  *
177  * KSM_TYPE_KSK KSKs
178  * KSM_TYPE_ZSK ZSKs
179  *
180  * int rollover
181  * 1 to force a rollover, 0 to ignore
182  *
183  * const char* datetime
184  * Time to insert into database.
185  *
186  * KSM_REQUEST_CALLBACK callback
187  * Callback function called for every key that will be issued.
188  *
189  * void* context
190  * Context argument passed uninterpreted to the callback function.
191  *
192  * int policy_id
193  * ID of policy that we are looking at
194  *
195  * int zone_id
196  * ID of zone that we are looking at
197  *
198  * int run_interval
199  * how frequently do we run?
200  *
201  * int* NewDS
202  * were new DS records needed?
203  *
204  * Returns:
205  * int
206  * Status return. 0 = Success, other = error (in which case a message
207  * will have been output).
208 -*/
209 
210 int KsmRequestKeysByType(int keytype, int rollover, const char* datetime,
211  KSM_REQUEST_CALLBACK callback, void* context, int policy_id, int zone_id,
212  int run_interval, int* NewDS)
213 {
214  int active; /* Number of active keys to be retired */
215  KSM_PARCOLL collection; /* Parameters collection */
216  int ready; /* Number of keys in the "ready" state */
217  int first_pass = 0; /* Indicates if this zone has been published before */
218  int status; /* Status return */
219  char* zone_name = NULL; /* For rollover message, if needed */
220  int manual_rollover = 0; /* Flag specific to keytype */
221 
222  /* Check that we have a valid key type */
223 
224  if ((keytype != KSM_TYPE_KSK) && (keytype != KSM_TYPE_ZSK)) {
225  status = MsgLog(KME_UNKEYTYPE, keytype);
226  return status;
227  }
228 
230  (keytype == KSM_TYPE_KSK) ? "key" : "zone");
231 
232  /* Get list of parameters */
233 
234  status = KsmParameterCollection(&collection, policy_id);
235  if (status != 0) {
236  return status;
237  }
238 
239  if (keytype == KSM_TYPE_KSK) {
240  manual_rollover = collection.kskmanroll;
241  }
242  else if (keytype == KSM_TYPE_ZSK) {
243  manual_rollover = collection.zskmanroll;
244  }
245 
246  /* Check to see if this zone has been published before */
247  status = KsmRequestCheckFirstPass(keytype, &first_pass, zone_id);
248  if (status != 0) {
249  return status;
250  }
251 
252  /*
253  * Step 0: If rolling over the key, set the expected retirement date of
254  * active keys to the given date/time.
255  */
256 
257  if (rollover) {
258  status = KsmRequestSetActiveExpectedRetire(keytype, datetime, zone_id);
259  if (status != 0) {
260  return status;
261  }
262  } else {
263  /* Check for the compromised flag on the currently active key;
264  if set then force rollover to 1 (could set manual_rollover to 0)
265  NOTE: because of where this is called from we can not overwrite
266  the incoming rollover flag if set */
267  status = KsmRequestCheckCompromisedFlag(keytype, zone_id, &rollover);
268  if (status != 0) {
269  return status;
270  }
271  }
272  /*
273  * Step 0a: Complete Key rollover of standbykeys in KEYPUBLISH state
274  * if we are after their active time, move them into the active state
275  */
276  if (keytype == KSM_TYPE_KSK) {
277  status = KsmRequestChangeStateKeyPublishActive(datetime, zone_id, policy_id, NewDS);
278  if (status != 0) {
279  return status;
280  }
281 
282  if (*NewDS == 1) {
283  /* Standby Key has become active, retire the old key */
284  status = KsmRequestChangeStateActiveRetire(keytype, datetime, zone_id, policy_id);
285  if (status != 0) {
286  StrFree(zone_name);
287  return status;
288  }
289  *NewDS = 0; /* We were naughty when we used this flag, clean up */
290  /* DS set won't change until the old active key moves to dead */
291  }
292  }
293 
294 
295  /*
296  * Step 1. For each retired key, mark it as dead if it past the given
297  * time.
298  */
299 
300  status = KsmRequestChangeStateRetireDead(keytype, datetime, zone_id, policy_id, collection.kskroll, NewDS);
301  if (status != 0) {
302  return status;
303  }
304 
305  /*
306  * Step 2. For each key in the published state, set it ready if it has
307  * been in the zone long enough.
308  */
309 
310  if (keytype == KSM_TYPE_ZSK ||
311  collection.kskroll == KSM_ROLL_DNSKEY ||
312  first_pass == 1) {
313  status = KsmRequestChangeStatePublishReady(keytype, datetime, zone_id, policy_id, NewDS);
314  if (status != 0) {
315  return status;
316  }
317  }
318 
319  /*
320  * Step 2a. For each key in the dspublished state, set it dsready if it has
321  * been in the zone long enough.
322  */
323 
324  if (keytype == KSM_TYPE_KSK) {
325  status = KsmRequestChangeStateDSPublishDSReady(keytype, datetime, zone_id, policy_id);
326  if (status != 0) {
327  return status;
328  }
329  }
330 
331  /*
332  * Step 3a. make sure that we have enough standby KSKs
333  * Doing this before 3.
334  */
335 
336  if (keytype == KSM_TYPE_KSK) {
337  status = KsmRequestChangeStateGenerateDSSubConditional(keytype, datetime, &collection, zone_id, NewDS);
338 
339  /* Reset this flag; TODO is this correct? */
340  if (first_pass == 1) {
341  *NewDS = 0;
342  }
343  if (status != 0) {
344  return status;
345  }
346  }
347 
348  /*
349  * Step 3. We are within the appropriate interval of the retirement
350  * of the active key, move keys from the generate state into the
351  * publish state.
352  */
353 
354  status = KsmRequestChangeStateGeneratePublishConditional(keytype, datetime, &collection, zone_id, run_interval);
355  if (status != 0) {
356  return status;
357  }
358 
359  /*
360  * Step 4. If there is an active key and the date on which this procedure
361  * is run is earlier than the retire time of that key, exit the procedure.
362  */
363 
364  status = KsmRequestCheckActiveKey(keytype, datetime, &active, zone_id);
365  if (status != 0) {
366  return status;
367  }
368 
369  /*
370  * Step 5: Unless we are forcing a rollover, if there are some keys that
371  * will be active after the cut-off, end the modification of key states and
372  * times now. Otherwise continue.
373  *
374  * Note that we don't return if keys are active - we still need to issue
375  * the keys.
376  */
377 
378  if ((active <= 0) || (rollover)) {
379 
380  /* Get some info that we need for logging later */
381  status = KsmZoneNameFromId(zone_id, &zone_name);
382  if (status != 0) {
383  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
384  if (zone_name != NULL) {
385  StrFree(zone_name);
386  }
387  return(status);
388  }
389 
390  /*
391  * Step 6. If there are keys to be made active, count the number of keys
392  * in the "READY" state.
393  */
394 
395  status = KsmRequestCountReadyKey(keytype, datetime, &ready, zone_id);
396  if (status != 0) {
397  StrFree(zone_name);
398  return status;
399  }
400 
401  /*
402  * Step 7. We can only promote a key if there is at least one key in the
403  * READY state. Otherwise, just issue what we have.
404  */
405 
406  if (ready <= 0) {
407 
408  /*
409  * If this is the first pass for this zone. Then we can promote a key
410  * to active from published
411  * NB: A consequence of this is that these keys will have no "ready"
412  * time as they are never in the "ready" state.
413  */
414 
415  if (first_pass == 1) {
416  /* We have to wait until the KSK is ready before we can
417  * publish the DS record */
418  if (keytype == KSM_TYPE_KSK) {
419  /* status = KsmRequestChangeStateN(keytype, datetime, 1,
420  KSM_STATE_READY, KSM_STATE_ACTIVE, zone_id);*/
421  } else {
422  (void) MsgLog(KME_PROM_PUB, "ZSK");
423  status = KsmRequestChangeStateN(keytype, datetime, 1,
425  }
426 
427  if (status != 0) {
428  StrFree(zone_name);
429  return status;
430  }
431  }
432  else {
433  /* Move standby key from DSready to KEYPUBLISH if we can */
434  if (keytype == KSM_TYPE_KSK) {
435  status = KsmRequestChangeStateDSReadyKeyPublish(datetime, zone_id, policy_id);
436  if (status != 0) {
437  return status;
438  }
439  }
440 
441  (void) MsgLog(KME_NOREADYKEY, (keytype == KSM_TYPE_KSK ? "KSK" : "ZSK"), zone_name);
442  /* TODO return here? */
443  }
444  }
445  else if (manual_rollover == 1 && rollover == 0) {
446  (void) MsgLog(KME_MAN_ROLL_REQUIRED, (keytype == KSM_TYPE_KSK ? "KSK" : "ZSK"), zone_name);
447  }
448  /* TODO I think that this is no longer true... */
449  /* Check where we need this to happen */
450  else if (keytype == KSM_TYPE_KSK) {
451  /* A rollover should be occuring... For KSKs we just prompt for
452  * the user to submit their DS record
453  * TODO Include the keytag or cka-id in the message
454  * TODO Do we still need this? */
455  (void) MsgLog(KME_DS_SUBMISSION, zone_name);
456  }
457  else {
458 
459  /* Step 8. Make a key active. */
460  status = KsmRequestChangeStateReadyActive(keytype, datetime, 1, zone_id);
461  /*
462  * If we didn't complete due to non-backed up keys then skip the
463  * retire step; otherwise carry on.
464  */
465  if (status != KME_BACK_FATAL) {
466  if (status != 0) {
467  StrFree(zone_name);
468  return status;
469  }
470 
471  /* Step 9. ... and retire old active keys */
472  status = KsmRequestChangeStateActiveRetire(keytype, datetime, zone_id, policy_id);
473  if (status != 0) {
474  StrFree(zone_name);
475  return status;
476  }
477 
478  /* Log that a rollover has happened */
479  (void) MsgLog(KME_ROLL_ZONE, (keytype == KSM_TYPE_KSK ? "KSK" : "ZSK"), zone_name);
480  }
481  }
482  StrFree(zone_name);
483  }
484 
485  /* Step 10. Issue the keys */
486 
487  status = KsmRequestIssueKeys(keytype, callback, context, zone_id);
488 
489  return status;
490 }
491 
492 
493 
494 /*+
495  * KsmRequestSetActiveExpectedRetire - Set Expected Retire Date
496  *
497  * Description:
498  * Sets the expected retire date for active keys to the date specified.
499  * Note that this does change not the state from active - it only changes
500  * the expected retire date.
501  *
502  * Arguments:
503  * int keytype
504  * Type of keys being changed.
505  *
506  * const char* datetime
507  * Date/time for which the calculation is being done. This can be
508  * the string "NOW()".
509  *
510  * int zone_id
511  * Zone we are looking at (-1 == all zones)
512  *
513  * Returns:
514  * int
515  * Status return. 0 => success, Other => failure, in which case an
516  * error message will have been output.
517 -*/
518 
519 int KsmRequestSetActiveExpectedRetire(int keytype, const char* datetime, int zone_id)
520 {
521  int count = 0; /* Count of keys whose date will be set */
522  char* sql = NULL; /* For creating the SQL command */
523  int status = 0; /* Status return */
524  int where = 0; /* For the SQL selection */
525  int i = 0; /* A counter */
526  int j = 0; /* Another counter */
527  char* insql = NULL; /* SQL "IN" clause */
528  int* keyids; /* List of IDs of keys to promote */
529  DB_RESULT result; /* List result set */
530  KSM_KEYDATA data; /* Data for this key */
531  char buffer[32]; /* For integer conversion */
532 
533  /* Count how many keys will have the retire date set */
534 
535  sql = DqsCountInit("KEYDATA_VIEW");
536  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, where++);
537  DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, where++);
538  if (zone_id != -1) {
539  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
540  }
541  DqsEnd(&sql);
542 
543  status = DbIntQuery(DbHandle(), &count, sql);
544  DqsFree(sql);
545 
546  if (status != 0) {
547  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
548  return status;
549  }
550 
551  if (count == 0) {
552  /* Nothing to do NO ACTIVE KEYS! */
553  return status;
554  }
555 
556  /* Allocate space for the list of key IDs */
557  keyids = MemMalloc(count * sizeof(int));
558 
559  /* Get the list of IDs */
560 
561  where = 0;
562  sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
563  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, where++);
564  DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, where++);
565  if (zone_id != -1) {
566  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
567  }
568  DqsEnd(&sql);
569 
570  status = KsmKeyInitSql(&result, sql);
571  DqsFree(sql);
572 
573  if (status == 0) {
574  while (status == 0) {
575  status = KsmKey(result, &data);
576  if (status == 0) {
577  keyids[i] = data.keypair_id;
578  i++;
579  }
580  }
581 
582  /* Convert EOF status to success */
583 
584  if (status == -1) {
585  status = 0;
586  } else {
587  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
588  StrFree(keyids);
589  return status;
590  }
591 
592  KsmKeyEnd(result);
593 
594  } else {
595  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
596  StrFree(keyids);
597  return status;
598  }
599 
600  /*
601  * Now construct the "IN" statement listing the IDs of the keys we
602  * are planning to change the state of.
603  */
604 
605  StrAppend(&insql, "(");
606  for (j = 0; j < i; ++j) {
607  if (j != 0) {
608  StrAppend(&insql, ",");
609  }
610  snprintf(buffer, sizeof(buffer), "%d", keyids[j]);
611  StrAppend(&insql, buffer);
612  }
613  StrAppend(&insql, ")");
614 
615  /*
616  * Update the keys. This is done after a status check, as the debug
617  * code may have hit a database error, in which case we won't query the
618  * database again. ("status" is initialized to success in case the debug
619  * code is not executed.)
620  */
621 
622  sql = DusInit("keypairs");
623  DusSetInt(&sql, "fixedDate", 1, 0);
624  DusSetInt(&sql, "compromisedflag", 1, 1);
625 
626  DusConditionKeyword(&sql, "ID", DQS_COMPARE_IN, insql, 0);
627  DusEnd(&sql);
628 
629  status = DbExecuteSqlNoResult(DbHandle(), sql);
630  DusFree(sql);
631 
632  /* Report any errors */
633  if (status != 0) {
634  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
635  }
636 
637  sql = DusInit("dnsseckeys");
638  DusSetString(&sql, "RETIRE", datetime, 0);
639 
640  DusConditionKeyword(&sql, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0);
641  /* NO ZONE_ID !!! We want to retire ALL instances of this key */
642  StrFree(insql);
643  DusEnd(&sql);
644 
645  status = DbExecuteSqlNoResult(DbHandle(), sql);
646  DusFree(sql);
647 
648  /* Report any errors */
649  if (status != 0) {
650  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
651  }
652 
653  StrFree(keyids);
654 
655  return status;
656 }
657 
658 
659 
660 /*+
661  * KsmRequestChangeStatePublishReady - Change State from PUBLISH to READY
662  * KsmRequestChangeStateActiveRetire - Change State from ACTIVE to RETIRE
663  * KsmRequestChangeStateRetireDead - Change State from RETIRE to DEAD
664  *
665  * Description:
666  * Changes the state of keys of a particular type in the given zone
667  * between two states.
668  *
669  * Arguments:
670  * int keytype
671  * Type of keys being changed.
672  *
673  * const char* datetime
674  * Date/time for which the calculation is being done. This ancan be
675  * the string "NOW()".
676  *
677  * int zone_id
678  * ID of zone that we are looking at (-1 == all zones)
679  *
680  * Returns:
681  * int
682  * Status return. 0 => success, Other => failure, in which case an
683  * error message will have been output.
684 -*/
685 
686 int KsmRequestChangeStatePublishReady(int keytype, const char* datetime, int zone_id, int policy_id, int* NewDS)
687 {
688  return KsmRequestChangeState(keytype, datetime,
689  KSM_STATE_PUBLISH, KSM_STATE_READY, zone_id, policy_id, -1, NewDS);
690 }
691 
692 int KsmRequestChangeStateDSPublishDSReady(int keytype, const char* datetime, int zone_id, int policy_id)
693 {
694  int* dummy = NULL;
695  return KsmRequestChangeState(keytype, datetime,
696  KSM_STATE_DSPUBLISH, KSM_STATE_DSREADY, zone_id, policy_id, -1, dummy);
697 }
698 
699 int KsmRequestChangeStateDSReadyKeyPublish(const char* datetime, int zone_id, int policy_id)
700 {
701  int* dummy = NULL;
702  return KsmRequestChangeState(KSM_TYPE_KSK, datetime,
703  KSM_STATE_DSREADY, KSM_STATE_KEYPUBLISH, zone_id, policy_id, -1, dummy);
704 }
705 
706 int KsmRequestChangeStateKeyPublishActive(const char* datetime, int zone_id, int policy_id, int* NewDS)
707 {
708  return KsmRequestChangeState(KSM_TYPE_KSK, datetime,
709  KSM_STATE_KEYPUBLISH, KSM_STATE_ACTIVE, zone_id, policy_id, -1, NewDS);
710 }
711 
712 int KsmRequestChangeStateActiveRetire(int keytype, const char* datetime, int zone_id, int policy_id)
713 {
714  int* dummy = NULL;
715  return KsmRequestChangeState(keytype, datetime,
716  KSM_STATE_ACTIVE, KSM_STATE_RETIRE, zone_id, policy_id, -1, dummy);
717 }
718 
719 int KsmRequestChangeStateRetireDead(int keytype, const char* datetime, int zone_id, int policy_id, int rollover_scheme, int* NewDS)
720 {
721  return KsmRequestChangeState(keytype, datetime,
722  KSM_STATE_RETIRE, KSM_STATE_DEAD, zone_id, policy_id, rollover_scheme, NewDS);
723 }
724 
725 
726 
727 /*+
728  * KsmRequestChangeState - Change State of a Key
729  *
730  * Description:
731  * Changes the state of a key between two states if the estimated time of
732  * entering the target state is equal to or earlier than the given time.
733  * The time of entering the state is updated to the given time as well.
734  *
735  * Arguments:
736  * int keytype
737  * Type of keys being changed.
738  *
739  * const char* datetime
740  * Date/time for which the calculation is being done. This can be
741  * the string "NOW()".
742  *
743  * int src_state
744  * ID of the state that the key is moving from.
745  *
746  * int dst_state
747  * ID of the state that the key is moving to.
748  *
749  * int zone_id
750  * ID of zone that we are looking at (-1 == all zones)
751  *
752  * int policy_id
753  * ID of the policy that we are looking at
754  *
755  * int rollover_scheme
756  * what KSK rollover scheme are we using
757  *
758  * Returns:
759  * int
760  * Status return. 0 => success, Other => failure, in which case an
761  * error message will have been output.
762 -*/
763 
764 int KsmRequestChangeState(int keytype, const char* datetime,
765  int src_state, int dst_state, int zone_id, int policy_id,
766  int rollover_scheme, int* NewDS)
767 {
768  int where = 0; /* for the SELECT statement */
769  char* dst_col = NULL; /* Destination column */
770  int set = 0; /* For UPDATE */
771  char* sql = NULL; /* SQL statement (when verifying) */
772  int status = 0; /* Status return */
773  int count = 0; /* How many keys fit our select? */
774  int i = 0; /* A counter */
775  int j = 0; /* Another counter */
776  char* insql = NULL; /* SQL "IN" clause */
777  int* keyids; /* List of IDs of keys to promote */
778  DB_RESULT result; /* List result set */
779  KSM_KEYDATA data; /* Data for this key */
780  char buffer[32]; /* For integer conversion */
781  char* zone_name = NULL; /* For DS removal message, if needed */
782 
783  /* Unused parameter */
784  (void)policy_id;
785 
786  /* Create the destination column name */
787  if (dst_state == KSM_STATE_DSREADY) {
789  } else if (dst_state == KSM_STATE_KEYPUBLISH) {
791  } else {
792  dst_col = StrStrdup(KsmKeywordStateValueToName(dst_state));
793  }
794  (void) StrToUpper(dst_col);
795 
796  /* First up we need to count how many keys will move */
797  sql = DqsCountInit("KEYDATA_VIEW");
798  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, where++);
799  DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, src_state, where++);
800  if (zone_id != -1) {
801  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
802  }
803  DqsConditionString(&sql, dst_col, DQS_COMPARE_LE, datetime, where++);
804  DqsEnd(&sql);
805 
806  status = DbIntQuery(DbHandle(), &count, sql);
807  DqsFree(sql);
808 
809  if (status != 0) {
810  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
811  StrFree(dst_col);
812  return status;
813  }
814 
815  if (count == 0) {
816  /* Nothing to do */
817  StrFree(dst_col);
818  return status;
819  }
820 
821  /* Allocate space for the list of key IDs */
822  keyids = MemMalloc(count * sizeof(int));
823 
824  /* Get the list of IDs */
825 
826  where = 0;
827  sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
828  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, where++);
829  DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, src_state, where++);
830  if (zone_id != -1) {
831  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, where++);
832  }
833  DqsConditionString(&sql, dst_col, DQS_COMPARE_LE, datetime, where++);
834  DqsEnd(&sql);
835 
836  status = KsmKeyInitSql(&result, sql);
837  DqsFree(sql);
838 
839  if (status == 0) {
840  while (status == 0) {
841  status = KsmKey(result, &data);
842  if (status == 0) {
843  keyids[i] = data.keypair_id;
844  i++;
845  }
846  }
847 
848  /* Convert EOF status to success */
849 
850  if (status == -1) {
851  status = 0;
852  } else {
853  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
854  StrFree(dst_col);
855  StrFree(keyids);
856  return status;
857  }
858 
859  KsmKeyEnd(result);
860 
861  } else {
862  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
863  StrFree(dst_col);
864  StrFree(keyids);
865  return status;
866  }
867 
868  /* Notify progress if debugging */
869 
871  KsmKeywordStateValueToName(src_state),
872  KsmKeywordStateValueToName(dst_state));
873 
874  /*
875  * Now construct the "IN" statement listing the IDs of the keys we
876  * are planning to change the state of.
877  */
878 
879  StrAppend(&insql, "(");
880  for (j = 0; j < i; ++j) {
881  if (j != 0) {
882  StrAppend(&insql, ",");
883  }
884  snprintf(buffer, sizeof(buffer), "%d", keyids[j]);
885  StrAppend(&insql, buffer);
886  }
887  StrAppend(&insql, ")");
888 
889  StrFree(keyids);
890 
891  /*
892  * Update the keys. This is done after a status check, as the debug
893  * code may have hit a database error, in which case we won't query the
894  * database again. ("status" is initialized to success in case the debug
895  * code is not executed.)
896  */
897 
898  sql = DusInit("dnsseckeys");
899  DusSetInt(&sql, "STATE", dst_state, set++);
900  DusSetString(&sql, dst_col, datetime, set++);
901 
902  DusConditionKeyword(&sql, "KEYPAIR_ID", DQS_COMPARE_IN, insql, 0);
903  DusConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, 1);
904  DusEnd(&sql);
905  StrFree(dst_col);
906 
907  status = DbExecuteSqlNoResult(DbHandle(), sql);
908  DusFree(sql);
909 
910  /* Report any errors */
911  if (status != 0) {
912  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
913  }
914 
915  /* See if we need to log a message about the DS records */
916  if (keytype == KSM_TYPE_KSK && ((dst_state == KSM_STATE_DEAD && rollover_scheme == KSM_ROLL_DS) || dst_state == KSM_STATE_READY))
917  {
918  /* Set our flag */
919  *NewDS = 1;
920 
921  /* Get common info we need for either message */
922  status = KsmZoneNameFromId(zone_id, &zone_name);
923  if (status != 0) {
924  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
925  if (zone_name != NULL) {
926  StrFree(insql);
927  StrFree(zone_name);
928  }
929  return(status);
930  }
931 
932  /* If we moved a KSK from retire to dead then the DS can be removed */
933  if (dst_state == KSM_STATE_DEAD && rollover_scheme == KSM_ROLL_DS) {
934  (void) MsgLog(KME_DS_REM_ZONE, zone_name);
935  }
936  else if (dst_state == KSM_STATE_READY) {
937  (void) MsgLog(KME_NEW_DS, zone_name);
938 
939  }
940  }
941  else if (keytype == KSM_TYPE_KSK && src_state == KSM_STATE_KEYPUBLISH) {
942  /* Set our flag, we are completing an emergency rollover */
943  *NewDS = 1;
944  }
945 
946  StrFree(insql);
947  StrFree(zone_name);
948 
949  return status;
950 }
951 
952 
953 
954 /*+
955  * KsmRequestChangeStateGeneratePublish - Change State from GENERATE to PUBLISH
956  * KsmRequestChangeStateGenerateDSPublish - Change State from GENERATE to DSPUBLISH
957  * KsmRequestChangeStateReadyActive - Change State from READY to ACTIVE
958  *
959  * Description:
960  * Changes the state of a number of keys from one state to another.
961  *
962  * Arguments:
963  * int keytype
964  * Type of keys being changed.
965  *
966  * const char* datetime
967  * Date/time for which this request is being made.
968  *
969  * int count
970  * Number of keys to be promoted to the publish state. There is no
971  * check as to whether that number of keys are available in the
972  * GENERATE state - it is assumed that that check has already been
973  * carried out.
974  *
975  * int zone_id
976  * ID of zone that we are looking at (-1 == all zones)
977  *
978  * Returns:
979  * int
980  * Status return. 0 => success, Other => failure, in which case an
981  * error message will have been output.
982 -*/
983 
984 int KsmRequestChangeStateGeneratePublish(int keytype, const char* datetime,
985  int count, int zone_id)
986 {
987  return KsmRequestChangeStateN(keytype, datetime, count,
989 }
990 
991 int KsmRequestChangeStateGenerateDSSub(int keytype, const char* datetime,
992  int count, int zone_id)
993 {
994  return KsmRequestChangeStateN(keytype, datetime, count,
996 }
997 
998 int KsmRequestChangeStateReadyActive(int keytype, const char* datetime,
999  int count, int zone_id)
1000 {
1001  return KsmRequestChangeStateN(keytype, datetime, count,
1002  KSM_STATE_READY, KSM_STATE_ACTIVE, zone_id);
1003 }
1004 
1005 
1006 /*+
1007  * KsmRequestChangeStateN - Change State of N Keys
1008  *
1009  * Description:
1010  * Changes the state of a given number of keys from one state to another.
1011  *
1012  * Arguments:
1013  * int keytype
1014  * Type of keys being changed.
1015  *
1016  * const char* datetime
1017  * Date/time for which this request is being made.
1018  *
1019  * int count
1020  * Number of keys to be promoted to the destination state. There is no
1021  * check as to whether that number of keys are available in the
1022  * state - it is assumed that that check has already been carried out.
1023  *
1024  * int src_state
1025  * State from which keys are being prompted.
1026  *
1027  * int dst_state
1028  * State to which keys are being promoted.
1029  *
1030  * int zone_id
1031  * ID of zone that we are looking at (-1 == all zones)
1032  *
1033  * Returns:
1034  * int
1035  * Status return. 0 => success, Other => failure, in which case an
1036  * error message will have been output.
1037 -*/
1038 
1039 int KsmRequestChangeStateN(int keytype, const char* datetime, int count,
1040  int src_state, int dst_state, int zone_id)
1041 {
1042  char buffer[32]; /* For integer conversion */
1043  DQS_QUERY_CONDITION condition[4]; /* Condition codes */
1044  KSM_KEYDATA data; /* Data for this key */
1045  char* dst_name = NULL; /* Dest state name uppercase */
1046  DB_RESULT result; /* List result set */
1047  int i; /* Loop counter */
1048  char* insql = NULL; /* SQL "IN" clause */
1049  int* keyids; /* List of IDs of keys to promote */
1050  int setclause = 0; /* For the "SET" clauses */
1051  char* sql1 = NULL; /* SQL statement */
1052  char* sql2 = NULL; /* SQL statement */
1053  char* sql3 = NULL; /* SQL statement */
1054  int status; /* Status return */
1055  int whereclause = 0; /* For the "WHERE" clauses */
1056  int count1 = 0; /* No. of non-backed up keys */
1057  int count2 = 0; /* No. of non-backed up keys which should be */
1058 
1059  /* Just checking */
1060  if (count <= 0) {
1061  status = MsgLog(KSM_INVARG, "Asked to move 0 keys");
1062  return status;
1063  }
1064 
1065  /* Notify progress if debugging */
1066 
1068  KsmKeywordStateValueToName(src_state),
1069  KsmKeywordStateValueToName(dst_state));
1070 
1071  /* Allocate space for the list of key IDs */
1072  keyids = MemMalloc(count * sizeof(int));
1073 
1074  /* Get the list of IDs */
1075 
1076  condition[0].code = DB_KEYDATA_KEYTYPE;
1077  condition[0].data.number = keytype;
1078  condition[0].compare = DQS_COMPARE_EQ;
1079 
1080  condition[1].code = DB_KEYDATA_STATE;
1081  condition[1].data.number = src_state;
1082  condition[1].compare = DQS_COMPARE_EQ;
1083 
1084  condition[2].compare = DQS_END_OF_LIST;
1085 
1086  if (zone_id != -1) {
1087  condition[2].code = DB_KEYDATA_ZONE_ID;
1088  condition[2].data.number = zone_id;
1089  condition[2].compare = DQS_COMPARE_EQ;
1090 
1091  condition[3].compare = DQS_END_OF_LIST;
1092  }
1093 
1094 
1095  status = KsmKeyInit(&result, condition);
1096  for (i = 0; ((i < count) && (status == 0)); ++i) {
1097  status = KsmKey(result, &data);
1098  if (status == 0) {
1099  keyids[i] = data.keypair_id;
1100  }
1101  }
1102  KsmKeyEnd(result);
1103 
1104  /* Did we get everything? */
1105 
1106  if (status == 0) {
1107 
1108  /*
1109  * Yes: construct the "IN" statement listing the IDs of the keys we
1110  * are planning to change the state of.
1111  */
1112 
1113  StrAppend(&insql, "(");
1114  for (i = 0; i < count; ++i) {
1115  if (i != 0) {
1116  StrAppend(&insql, ",");
1117  }
1118  snprintf(buffer, sizeof(buffer), "%d", keyids[i]);
1119  StrAppend(&insql, buffer);
1120  }
1121  StrAppend(&insql, ")");
1122 
1123  /* Get upper case names of the states (= names of date columns) */
1124 
1125  if (dst_state == KSM_STATE_DSSUB) {
1126  StrAppend(&dst_name, KSM_STATE_PUBLISH_STRING);
1127  } else {
1128  dst_name = StrStrdup(KsmKeywordStateValueToName(dst_state));
1129  }
1130  (void) StrToUpper(dst_name);
1131 
1132  if (dst_state == KSM_STATE_ACTIVE) {
1133  /*
1134  * We are making the key(s) active so check the backedupness of these keys,
1135  * and compare with the requirebackup flag on their repository
1136  */
1137  /*
1138  * First see if we have any which are not backed up
1139  */
1140  StrAppend(&sql1, "select count(*) from keypairs where id in ");
1141  StrAppend(&sql1, insql);
1142  StrAppend(&sql1, " and backup is null");
1143 
1144  status = DbIntQuery(DbHandle(), &count1, sql1);
1145  DqsFree(sql1);
1146 
1147  if (status != 0)
1148  {
1149  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
1150  StrFree(insql);
1151  MemFree(keyids);
1152  StrFree(dst_name);
1153  return status;
1154  }
1155 
1156  if (count1 != 0) {
1157  /*
1158  * See if any of these are supposed to be backed up
1159  */
1160 
1161  StrAppend(&sql2, "select count(*) from keypairs k, securitymodules s where s.id = k.securitymodule_id and k.id in ");
1162  StrAppend(&sql2, insql);
1163  StrAppend(&sql2, " and k.backup is null and s.requirebackup = 1");
1164 
1165  status = DbIntQuery(DbHandle(), &count2, sql2);
1166  DqsFree(sql2);
1167 
1168  if (status != 0)
1169  {
1170  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
1171  StrFree(insql);
1172  MemFree(keyids);
1173  StrFree(dst_name);
1174  return status;
1175  }
1176 
1177  if (count2 != 0) {
1178  /*
1179  * This is bad; log an error and return
1180  */
1181  status = MsgLog(KME_BACK_FATAL, (keytype == KSM_TYPE_KSK) ? "KSK" : "ZSK");
1182  StrFree(insql);
1183  MemFree(keyids);
1184  StrFree(dst_name);
1185  return status;
1186  }
1187 
1188  /*
1189  * We allow this, but with a strong warning
1190  */
1191  (void) MsgLog(KME_BACK_NON_FATAL, (keytype == KSM_TYPE_KSK) ? "KSK" : "ZSK");
1192  }
1193  }
1194 
1195  /*
1196  * Now construct the "UPDATE" statement and execute it. This relies on
1197  * the fact that the name of the state is the same as the name of
1198  * the column in KEYDATA holding the date at which the key moved to
1199  * that state.
1200  */
1201 
1202  sql3 = DusInit("dnsseckeys");
1203  DusSetInt(&sql3, "STATE", dst_state, setclause++);
1204  DusSetString(&sql3, dst_name, datetime, setclause++);
1205  StrFree(dst_name);
1206 
1207  DusConditionKeyword(&sql3, "KEYPAIR_ID", DQS_COMPARE_IN, insql, whereclause++);
1208  DusConditionInt(&sql3, "ZONE_ID", DQS_COMPARE_EQ, zone_id, whereclause++);
1209  StrFree(insql);
1210  DusEnd(&sql3);
1211 
1212  status = DbExecuteSqlNoResult(DbHandle(), sql3);
1213  DusFree(sql3);
1214 
1215  /* Report any errors */
1216 
1217  if (status != 0) {
1218  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
1219  }
1220  }
1221 
1222  /* Free up resources */
1223 
1224  MemFree(keyids);
1225 
1226  return status;
1227 }
1228 
1229 /*+
1230  * KsmRequestChangeStateGenerateDSSubConditional -
1231  * Change State from Generate to DSSub
1232  *
1233  * Description:
1234  * Make sure that the zone has the correct number of standby keys.
1235  *
1236  * Arguments:
1237  * int keytype
1238  * Key type for which the request should happen.
1239  *
1240  * KSM_TYPE_KSK KSKs
1241  * KSM_TYPE_ZSK ZSKs
1242  *
1243  * const char* datetime
1244  * Date/time for which this request is taking place.
1245  *
1246  * KSM_PARCOLL* collection
1247  * Pointer to parameter collection for this zone.
1248  *
1249  * int zone_id
1250  * ID of zone that we are looking at (-1 == all zones)
1251  *
1252  * Returns:
1253  * int
1254  * Status return. 0 => success, Other => failure, in which case an
1255  * error message will have been output.
1256 -*/
1257 
1259  const char* datetime, KSM_PARCOLL* collection, int zone_id, int* NewDS)
1260 {
1261  int gencnt; /* Number of keys in generate state */
1262  int newkeys; /* New keys required */
1263  int standby; /* Number of standby keys */
1264  int reqkeys; /* Number of keys required */
1265  int status; /* Status return */
1266 
1267  /* How many standby keys we have */
1268  status = KsmRequestStandbyKSKCount(&standby, zone_id);
1269  if (status != 0) {
1270  return status;
1271  }
1272 
1273  reqkeys = KsmParameterStandbyKSKeys(collection);
1274 
1275  /*
1276  * So, if we remove "pendret" keys from the number of "available"
1277  * keys, how many are we short of the required number? This is how many
1278  * we need to promote from "generate" to "publish"
1279  */
1280 
1281  newkeys = reqkeys - standby;
1282 
1283  if (newkeys > 0) {
1284 
1285  /* Are there enough generated keys available */
1286 
1287  status = KsmRequestGenerateCount(keytype, &gencnt, zone_id);
1288  if (status == 0) {
1289  if (gencnt < newkeys) {
1290  status = MsgLog(KME_INSFGENKEY, gencnt,
1291  KsmKeywordTypeValueToName(keytype), newkeys);
1292  }
1294  KsmKeywordTypeValueToName(keytype));
1295 
1296  if (status == 0) {
1297 
1298  /* There are enough keys, so move them to "dssub" state */
1299 
1300  status = KsmRequestChangeStateGenerateDSSub(keytype,
1301  datetime, newkeys, zone_id);
1302 
1303  /* Set our flag */
1304  *NewDS = 1;
1305  }
1306  }
1307  }
1308 
1309  return 0;
1310 }
1311 
1312 /*+
1313  * KsmRequestChangeStateGeneratePublishConditional -
1314  * Change State from Generate to Pubish
1315  *
1316  * Description:
1317  * Unlike the other "Change State" functions, this is conditional. It
1318  * promotes keys in the "Generate" state to the "Publish" state to maintain
1319  * the required number of keys active/standby keys when the active keys
1320  * are retired.
1321  *
1322  * a) For the given time, work out how many "active" keys have a retire
1323  * date within this time + "publication interval". Call this number
1324  * Npr (Number pending retirement).
1325  *
1326  * This should be 1 or 0, as there is an assumption that there is only
1327  * ever one active key.
1328  *
1329  * b) Work out how many keys are in the active, publish and ready states.
1330  * Call this Nt (Number total).
1331  *
1332  * c) Now look at the difference (Nt - Npr). This is the number of keys
1333  * that will be (potentially) usable after the active key retires.
1334  * If this number is less than (1 + Ne) (where Ne is the number of
1335  * standby keys), move the difference from the generated state into
1336  * the published state.
1337  *
1338  * Arguments:
1339  * int keytype
1340  * Key type for which the request should happen.
1341  *
1342  * KSM_TYPE_KSK KSKs
1343  * KSM_TYPE_ZSK ZSKs
1344  *
1345  * const char* datetime
1346  * Date/time for which this request is taking place.
1347  *
1348  * KSM_PARCOLL* collection
1349  * Pointer to parameter collection for this zone.
1350  *
1351  * int zone_id
1352  * ID of zone that we are looking at (-1 == all zones)
1353  *
1354  * int run_interval
1355  * how frequently do we run?
1356  *
1357  * Returns:
1358  * int
1359  * Status return. 0 => success, Other => failure, in which case an
1360  * error message will have been output.
1361 -*/
1362 
1364  const char* datetime, KSM_PARCOLL* collection, int zone_id, int run_interval)
1365 {
1366  int availkeys; /* Number of availkeys keys */
1367  int gencnt; /* Number of keys in generate state */
1368  int newkeys; /* New keys required */
1369  int pendret; /* Number of keys that will be retired */
1370  int reqkeys; /* Number of keys required */
1371  int status; /* Status return */
1372 
1373  /* How many active keys will be retired in the immediate future */
1374  status = KsmRequestPendingRetireCount(keytype, datetime, collection,
1375  &pendret, zone_id, run_interval);
1376  if (status != 0) {
1377  return status;
1378  }
1379  DbgLog(DBG_M_REQUEST, KME_RETIRECNT, pendret);
1380 
1381  /* How many available keys are there */
1382 
1383  status = KsmRequestAvailableCount(keytype, datetime, collection,
1384  &availkeys, zone_id);
1385  if (status != 0) {
1386  return status;
1387  }
1388  DbgLog(DBG_M_REQUEST, KME_AVAILCNT, availkeys);
1389 
1390  /*
1391  * We need at least one active key and "number of standby keys" ready
1392  * keys at any one time.
1393  */
1394 
1395  if (keytype == KSM_TYPE_KSK) {
1396  /* For KSKs we sort out standby keys separately */
1397  reqkeys = 1; /*+ KsmParameterStandbyKSKeys(collection);*/
1398  }
1399  else if (keytype == KSM_TYPE_ZSK) {
1400  reqkeys = 1 + KsmParameterStandbyZSKeys(collection);
1401  }
1402  else {
1403  /* should not get here */
1404  return -1;
1405  }
1406 
1407  /*
1408  * So, if we remove "pendret" keys from the number of "available"
1409  * keys, how many are we short of the required number? This is how many
1410  * we need to promote from "generate" to "publish"
1411  */
1412 
1413  newkeys = reqkeys - (availkeys - pendret);
1414  /* fprintf(stderr, "%s: keytype(%d): newkeys(%d) = reqkeys(%d) - (availkeys(%d) - pendret(%d))\n", datetime, keytype, newkeys, reqkeys, availkeys, pendret); */
1415  DbgLog(DBG_M_REQUEST, KME_KEYCNTSUMM, reqkeys, newkeys);
1416 
1417  if (newkeys > 0) {
1418 
1419  /* Are there enough generated keys available */
1420 
1421  status = KsmRequestGenerateCount(keytype, &gencnt, zone_id);
1422  if (status == 0) {
1423  if (gencnt < newkeys) {
1424  status = MsgLog(KME_INSFGENKEY, gencnt,
1425  KsmKeywordTypeValueToName(keytype), newkeys);
1426  }
1428  KsmKeywordTypeValueToName(keytype));
1429 
1430  if (status == 0) {
1431 
1432  /* There are enough keys, so move them to "publish" state */
1433 
1434  status = KsmRequestChangeStateGeneratePublish(keytype,
1435  datetime, newkeys, zone_id);
1436  }
1437  }
1438  }
1439 
1440  return 0;
1441 }
1442 
1443 
1444 
1445 /*+
1446  * KsmRequestPendingRetireCount - Get Count of Keys Pending Retirement
1447  *
1448  * Description:
1449  * For the given time, works out how many "active" keys have a retire
1450  * date within this time + "publication interval".
1451  *
1452  * This should be 1 or 0, as there is an assumption that there is only
1453  * ever one active key.
1454  *
1455  * Arguments:
1456  * int keytype
1457  * Key type for which the request should happen.
1458  *
1459  * KSM_TYPE_KSK KSKs
1460  * KSM_TYPE_ZSK ZSKs
1461  *
1462  * const char* datetime
1463  * Date/time for which this request is taking place.
1464  *
1465  * KSM_PARCOLL* parameters
1466  * Parameters associated with this zone.
1467  *
1468  * int* count (returned)
1469  * Number of active keys that will retire within that period.
1470  *
1471  * int zone_id
1472  * ID of zone that we are looking at (-1 == all zones)
1473  *
1474  * Returns:
1475  * int
1476  * Status return. 0 => success, <>0 => error, in which case a message
1477  * will have been output.
1478 -*/
1479 
1480 int KsmRequestPendingRetireCount(int keytype, const char* datetime,
1481  KSM_PARCOLL* parameters, int* count, int zone_id, int interval)
1482 {
1483  char buffer[256]; /* For constructing part of the command */
1484  int clause = 0; /* Used in constructing SQL statement */
1485  size_t nchar; /* Number of characters written */
1486  char* sql; /* SQL command to be isssued */
1487  int status; /* Status return */
1488  int total_interval; /* The PublicationInterval + interval (when we will run again) */
1489 
1490  if (keytype == KSM_TYPE_ZSK)
1491  {
1492  total_interval = KsmParameterZskTtl(parameters) +
1493  KsmParameterPropagationDelay(parameters) +
1494  KsmParameterPubSafety(parameters) +
1495  interval;
1496  } else {
1497  total_interval = KsmParameterKskTtl(parameters) +
1498  KsmParameterKskPropagationDelay(parameters) +
1499  KsmParameterPubSafety(parameters) +
1500  interval;
1501  /*
1502  if (DOUBLEDNSKEY) {
1503  total_interval = KsmParameterKskTtl(parameters) +
1504  KsmParameterPropagationDelay(parameters) +
1505  KsmParameterDSTtl(parameters) +
1506  KsmParameterKskPropagationDelay(parameters) +
1507  KsmParameterPubSafety(parameters) +
1508  interval;
1509  }
1510  if (DOUBLEDS) {
1511  total_interval = KsmParameterDSTtl(parameters) +
1512  KsmParameterKskPropagationDelay(parameters) +
1513  KsmParameterPubSafety(parameters) +
1514  interval;
1515  }
1516  if (DOUBLERRSET) {
1517  temp = MAX(
1518  (KsmParameterKskTtl(parameters) + KsmParameterPropagationDelay(parameters)),
1519  (KsmParameterDSTtl(parameters) + KsmParameterKskPropagationDelay(parameters)));
1520  if (RFC5011) {
1521  temp = max(temp, 30*24*60*60);
1522  }
1523  total_interval = temp + KsmParameterPubSafety(parameters) +
1524  interval;
1525  }
1526  */
1527  }
1528  /* Create the SQL command to interrogate the database */
1529 
1530  sql = DqsCountInit("KEYDATA_VIEW");
1531  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, clause++);
1532  DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, clause++);
1533  if (zone_id != -1) {
1534  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++);
1535  }
1536 
1537  /* Calculate the initial publication interval & add to query */
1538 
1539  /*
1540  * TODO is there an alternative to DATE_ADD which is more generic?
1541  */
1542 #ifdef USE_MYSQL
1543  nchar = snprintf(buffer, sizeof(buffer),
1544  "DATE_ADD('%s', INTERVAL %d SECOND)",
1545  datetime, total_interval);
1546 #else
1547  nchar = snprintf(buffer, sizeof(buffer),
1548  "DATETIME('%s', '+%d SECONDS')",
1549  datetime, total_interval);
1550 #endif /* USE_MYSQL */
1551  if (nchar >= sizeof(buffer)) {
1552  status = MsgLog(KME_BUFFEROVF, "KsmRequestKeys");
1553  DqsFree(sql);
1554  return status;
1555  }
1556 
1557 #ifdef USE_MYSQL
1558  DqsConditionKeyword(&sql, "RETIRE", DQS_COMPARE_LE, buffer, clause++);
1559 #else
1560  DqsConditionKeyword(&sql, "DATETIME(RETIRE)", DQS_COMPARE_LE, buffer, clause++);
1561 #endif /* USE_MYSQL */
1562 
1563  DqsEnd(&sql);
1564 
1565  /* Execute the query and free resources */
1566 
1567  status = DbIntQuery(DbHandle(), count, sql);
1568  DqsFree(sql);
1569 
1570  /* Report any errors */
1571 
1572  if (status != 0) {
1573  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
1574  }
1575 
1576  return status;
1577 }
1578 
1579 
1580 
1581 /*+
1582  * KsmRequestAvailableCount - Get Count of Available Keys
1583  *
1584  * Description:
1585  * By "available", is the number of keys in the "published", "ready"
1586  * and "active" state.
1587  *
1588  * Arguments:
1589  * int keytype
1590  * Key type for which the request should happen.
1591  *
1592  * KSM_TYPE_KSK KSKs
1593  * KSM_TYPE_ZSK ZSKs
1594  *
1595  * const char* datetime
1596  * Date/time for which this request is taking place.
1597  *
1598  * KSM_PARCOLL* parameters
1599  * Parameters associated with this zone.
1600  *
1601  * int* count (returned)
1602  * Number of available keys.
1603  *
1604  * int zone_id
1605  * ID of zone that we are looking at (-1 == all zones)
1606  *
1607  * Returns:
1608  * int
1609  * Status return. 0 => success, <>0 => error, in which case a message
1610  * will have been output.
1611 -*/
1612 
1613 int KsmRequestAvailableCount(int keytype, const char* datetime, KSM_PARCOLL* parameters, int* count, int zone_id)
1614 {
1615  char buffer[256]; /* For constructing part of the command */
1616  int clause = 0; /* Used in constructing SQL statement */
1617  size_t nchar; /* Number of characters written */
1618  char* sql; /* SQL command to be isssued */
1619  int status; /* Status return */
1620 
1621  /* Unused parameters */
1622  (void)datetime;
1623  (void)parameters;
1624 
1625  /* Create the SQL command to interrogate the database */
1626 
1627  sql = DqsCountInit("KEYDATA_VIEW");
1628  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, clause++);
1629 
1630  /* Calculate the initial publication interval & add to query */
1631 
1632  nchar = snprintf(buffer, sizeof(buffer), "(%d, %d, %d, %d)",
1634  if (nchar >= sizeof(buffer)) {
1635  status = MsgLog(KME_BUFFEROVF, "KsmRequestKeys");
1636  DqsFree(sql);
1637  return status;
1638  }
1639  DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, buffer, clause++);
1640  if (zone_id != -1) {
1641  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++);
1642  }
1643  DqsEnd(&sql);
1644 
1645  /* Execute the query and free resources */
1646 
1647  status = DbIntQuery(DbHandle(), count, sql);
1648  DqsFree(sql);
1649 
1650  /* Report any errors */
1651 
1652  if (status != 0) {
1653  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
1654  }
1655 
1656  return status;
1657 }
1658 
1659 
1660 /*+
1661  * KsmRequestGenerateCount - Return Number of Keys in Generate State
1662  *
1663  * Description:
1664  * Returns the retire time of the currently active key. If there are
1665  * multiple active keys, returns the earliest time.
1666  *
1667  * Arguments:
1668  * int keytype
1669  * Time of key to search for.
1670  *
1671  * int* count (returned)
1672  * Number of available keys.
1673  *
1674  * int zone_id
1675  * ID of zone that we are looking at (-1 == all zones)
1676  *
1677  * Returns:
1678  * int
1679  * Status return. 0 => success, Other implies error, in which case a
1680  * message will have been output.
1681 -*/
1682 
1683 int KsmRequestGenerateCount(int keytype, int* count, int zone_id)
1684 {
1685  int clause = 0; /* Clause count */
1686  char* sql = NULL; /* SQL to interrogate database */
1687  int status = 0; /* Status return */
1688 
1689  /* Create the SQL */
1690 
1691  sql = DqsCountInit("KEYDATA_VIEW");
1692  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, clause++);
1693  DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, KSM_STATE_GENERATE, clause++);
1694  if (zone_id != -1) {
1695  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++);
1696  }
1697  DqsEnd(&sql);
1698 
1699  /* Execute the query and free resources */
1700 
1701  status = DbIntQuery(DbHandle(), count, sql);
1702  DqsFree(sql);
1703 
1704  /* Report any errors */
1705 
1706  if (status != 0) {
1707  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
1708  }
1709 
1710  return status;
1711 }
1712 
1713 /*+
1714  * KsmRequestStandbyKSKCount - Get Count of Standby Keys
1715  *
1716  * Description:
1717  * The number of keys in the "dspublished" and "dsready" states.
1718  *
1719  * Arguments:
1720  *
1721  * int* count (returned)
1722  * Number of standby keys.
1723  *
1724  * int zone_id
1725  * ID of zone that we are looking at (-1 == all zones)
1726  *
1727  * Returns:
1728  * int
1729  * Status return. 0 => success, <>0 => error, in which case a message
1730  * will have been output.
1731 -*/
1732 
1733 int KsmRequestStandbyKSKCount(int* count, int zone_id)
1734 {
1735  char buffer[256]; /* For constructing part of the command */
1736  int clause = 0; /* Used in constructing SQL statement */
1737  size_t nchar; /* Number of characters written */
1738  char* sql; /* SQL command to be isssued */
1739  int status; /* Status return */
1740 
1741  /* Create the SQL command to interrogate the database */
1742 
1743  sql = DqsCountInit("KEYDATA_VIEW");
1744  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, KSM_TYPE_KSK, clause++);
1745 
1746  /* Calculate the initial publication interval & add to query */
1747 
1748  nchar = snprintf(buffer, sizeof(buffer), "(%d, %d, %d)",
1750  if (nchar >= sizeof(buffer)) {
1751  status = MsgLog(KME_BUFFEROVF, "KsmRequestKeys");
1752  DqsFree(sql);
1753  return status;
1754  }
1755  DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, buffer, clause++);
1756  if (zone_id != -1) {
1757  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++);
1758  }
1759  DqsEnd(&sql);
1760 
1761  /* Execute the query and free resources */
1762 
1763  status = DbIntQuery(DbHandle(), count, sql);
1764  DqsFree(sql);
1765 
1766  /* Report any errors */
1767 
1768  if (status != 0) {
1769  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
1770  }
1771 
1772  return status;
1773 }
1774 
1775 /*
1776  * KsmRequestCheckActiveKey - Check Active Key
1777  *
1778  * Description:
1779  * Checks:
1780  *
1781  * a) If there is an active key.
1782  * b) If a key is present, what the retire time of it is. This is compared
1783  * against the specified date/time.
1784  *
1785  * A flag is returned indicating whether the key (if active) should be
1786  * replaced.
1787  *
1788  * Arguments:
1789  * int keytype
1790  * Either KSK or ZSK, depending on the key type
1791  *
1792  * const char* datetime
1793  * Date/time at which the check is being carried out.
1794  *
1795  * int* count
1796  * Number of active keys of the appropriate type and in the zone
1797  * that will be active AFTER the given date and time.
1798  *
1799  * int zone_id
1800  * ID of zone that we are looking at (-1 == all zones)
1801  *
1802  * This negative form (i.e. keys not meeting the specified condition)
1803  * is used to ensure that if there are no active keys, this fact is
1804  * reported.
1805  *
1806  * Returns:
1807  * int
1808  * Status return. 0 => success, Other => error, in which case a message
1809  * will have been output.
1810 -*/
1811 
1812 int KsmRequestCheckActiveKey(int keytype, const char* datetime, int* count, int zone_id)
1813 {
1814  int clause = 0; /* Clause counter */
1815  char* sql = NULL; /* SQL command */
1816  int status; /* Status return */
1817 #ifdef USE_MYSQL
1818 #else
1819  char buf[256]; /* For constructing part of the command */
1820 #endif /* USE_MYSQL */
1821  sql = DqsCountInit("KEYDATA_VIEW");
1822  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, clause++);
1823  DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, clause++);
1824  if (zone_id != -1) {
1825  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++);
1826  }
1827 
1828 #ifdef USE_MYSQL
1829  DqsConditionString(&sql, "RETIRE", DQS_COMPARE_GT, datetime, clause++);
1830 #else
1831  snprintf(buf, sizeof(buf), "DATETIME('%s')", datetime);
1832  DqsConditionKeyword(&sql, "DATETIME(RETIRE)", DQS_COMPARE_GT, buf, clause++);
1833 #endif /* USE_MYSQL */
1834 
1835  DqsEnd(&sql);
1836 
1837  status = DbIntQuery(DbHandle(), count, sql);
1838  DqsFree(sql);
1839 
1840  if (status != 0) {
1841  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
1842  }
1844  KsmKeywordTypeValueToName(keytype));
1845 
1846  return status;
1847 }
1848 
1849 
1850 
1851 /*
1852  * KsmRequestCountReadyKey - Count Keys in READY state
1853  *
1854  * Description:
1855  * Counts the number of keys in the "READY" state.
1856  *
1857  * Arguments:
1858  * int keytype
1859  * Either KSK or ZSK, depending on the key type
1860  *
1861  * const char* datetime
1862  * Date/time at which the check is being carried out.
1863  *
1864  * int* count
1865  * Number of keys meeting the condition.
1866  *
1867  * int zone_id
1868  * ID of zone that we are looking at (-1 == all zones)
1869  *
1870  * Returns:
1871  * int
1872  * Status return. 0 => success, Other => error, in which case a message
1873  * will have been output.
1874 -*/
1875 
1876 int KsmRequestCountReadyKey(int keytype, const char* datetime, int* count, int zone_id)
1877 {
1878  int clause = 0; /* Clause counter */
1879  char* sql = NULL; /* SQL command */
1880  int status; /* Status return */
1881 
1882  /* Unused parameter */
1883  (void)datetime;
1884 
1885  sql = DqsCountInit("KEYDATA_VIEW");
1886  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, clause++);
1887  DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, KSM_STATE_READY, clause++);
1888  if (zone_id != -1) {
1889  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++);
1890  }
1891  DqsEnd(&sql);
1892 
1893  status = DbIntQuery(DbHandle(), count, sql);
1894  DqsFree(sql);
1895 
1896  if (status != 0) {
1897  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
1898  }
1900  KsmKeywordTypeValueToName(keytype));
1901 
1902  return status;
1903 }
1904 
1905 /*
1906  * KsmRequestCheckFirstPass - Work out if this zone has been processed before
1907  *
1908  * Description:
1909  * Counts the number of keys above the PUBLISH state; if this is 0 then this is
1910  * a new zone.
1911  *
1912  * Arguments:
1913  * int keytype
1914  * Either KSK or ZSK, depending on the key type
1915  *
1916  * int* first_pass_flag
1917  * Indicator as to the result
1918  *
1919  * int zone_id
1920  * ID of zone that we are looking at (-1 == all zones)
1921  *
1922  * Returns:
1923  * int
1924  * Status return. 0 => success, Other => error, in which case a message
1925  * will have been output.
1926 -*/
1927 
1928 int KsmRequestCheckFirstPass(int keytype, int* first_pass_flag, int zone_id)
1929 {
1930  int clause = 0; /* Clause counter */
1931  char* sql = NULL; /* SQL command */
1932  int status; /* Status return */
1933  int count = 0; /* Number of matching keys */
1934 
1935  sql = DqsCountInit("KEYDATA_VIEW");
1936  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, clause++);
1937  DqsConditionInt(&sql, "STATE", DQS_COMPARE_GE, KSM_STATE_PUBLISH, clause++);
1938  if (zone_id != -1) {
1939  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++);
1940  }
1941  DqsEnd(&sql);
1942 
1943  status = DbIntQuery(DbHandle(), &count, sql);
1944  DqsFree(sql);
1945 
1946  if (status != 0) {
1947  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
1948  }
1949 
1950  if (count == 0) {
1951  /* No "ready, active, retired or dead" keys */
1952  *first_pass_flag = 1;
1953  }
1954  else {
1955  *first_pass_flag = 0;
1956  }
1957 
1958  return status;
1959 }
1960 
1961 /*
1962  * KsmRequestCheckCompromisedFlag - Work out if this zone is rolling
1963  *
1964  * Description:
1965  * Counts the number of "compromised" active keys, if > 0 then force
1966  * the zone to roll if we can.
1967  *
1968  * Arguments:
1969  * int keytype
1970  * Either KSK or ZSK, depending on the key type
1971  *
1972  * int zone_id
1973  * ID of zone that we are looking at (-1 == all zones)
1974  *
1975  * int* comp_flag
1976  * Force rollover behaviour if the active key is marked as compromised
1977  *
1978  * Returns:
1979  * int
1980  * Status return. 0 => success, Other => error, in which case a message
1981  * will have been output.
1982 -*/
1983 
1984 int KsmRequestCheckCompromisedFlag(int keytype, int zone_id, int* comp_flag)
1985 {
1986  int clause = 0; /* Clause counter */
1987  char* sql = NULL; /* SQL command */
1988  int status; /* Status return */
1989  int count = 0; /* Number of matching keys */
1990 
1991  sql = DqsCountInit("KEYDATA_VIEW");
1992  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, clause++);
1993  DqsConditionInt(&sql, "STATE", DQS_COMPARE_EQ, KSM_STATE_ACTIVE, clause++);
1994  if (zone_id != -1) {
1995  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++);
1996  }
1997  DqsConditionInt(&sql, "compromisedflag", DQS_COMPARE_EQ, 1, clause++);
1998  DqsEnd(&sql);
1999 
2000  status = DbIntQuery(DbHandle(), &count, sql);
2001  DqsFree(sql);
2002 
2003  if (status != 0) {
2004  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
2005  }
2006 
2007  if (count == 0) {
2008  /* No "compromised" keys; i.e. keys waiting to roll */
2009  /* We actually don't need to do this as it can only be 0 already */
2010  *comp_flag = 0;
2011  }
2012  else {
2013  *comp_flag = 1;
2014  }
2015 
2016  return status;
2017 }
2018 
2019 /*+
2020  * KsmRequestIssueKeys - Issue Keys
2021  *
2022  * Description:
2023  * Done as the last step in the "REQUEST KEYS" operation, this actually
2024  * issues the keys that should be in the current zone file. All keys in
2025  * the "publish", "ready", "active" and "retire" states are included.
2026  *
2027  * Arguments:
2028  * int keytype
2029  * Type of keys required.
2030  *
2031  * KSM_REQUEST_CALLBACK callback
2032  * Callback function called for every key that will be issued.
2033  *
2034  * void* context
2035  * Context argument passed uninterpreted to the callback function.
2036  *
2037  * int zone_id
2038  * ID of zone that we are looking at (-1 == all zones)
2039  *
2040  * Returns:
2041  * int
2042  * Status return. 0 => success, <>0 => error (in which case a message
2043  * will have been output).
2044 -*/
2045 
2046 int KsmRequestIssueKeys(int keytype, KSM_REQUEST_CALLBACK callback,
2047  void* context, int zone_id)
2048 {
2049  int clause = 0; /* For the WHERE clause */
2050  KSM_KEYDATA data; /* Data for this key */
2051  DB_RESULT result; /* Result set from query */
2052  char in[128]; /* Easily large enought for four keys */
2053  size_t nchar; /* Number of output characters */
2054  char* sql = NULL; /* SQL statement to get listing */
2055  int status; /* Status return */
2056 
2057  /*
2058  * Construct the "IN" statement listing the states of the keys that
2059  * are included in the output.
2060  */
2061 
2062  nchar = snprintf(in, sizeof(in), "(%d, %d, %d, %d, %d)",
2064  if (nchar >= sizeof(in)) {
2065  status = MsgLog(KME_BUFFEROVF, "KsmRequestIssueKeys");
2066  return status;
2067  }
2068 
2069  /* Create the SQL command to interrogate the database */
2070 
2071  sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
2072  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, clause++);
2073  DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, in, clause++);
2074  if (zone_id != -1) {
2075  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++);
2076  }
2077  DqsEnd(&sql);
2078 
2079  /* Now iterate round the keys meeting the condition and print them */
2080 
2081  status = KsmKeyInitSql(&result, sql);
2082  if (status == 0) {
2083  status = KsmKey(result, &data);
2084  while (status == 0) {
2085  status = (*callback)(context, &data);
2086  if (status == 0) {
2087  status = KsmKey(result, &data);
2088  }
2089  }
2090 
2091  /* Convert EOF status to success */
2092 
2093  if (status == -1) {
2094  status = 0;
2095  }
2096 
2097  KsmKeyEnd(result);
2098  }
2099 
2100  DqsFree(sql);
2101  return status;
2102 }
2103 
2104 
2105 
2106 /*+
2107  * KsmRequestPrintKey - Print Key Data
2108  *
2109  * Description:
2110  * Suitable callback function for KsmRequest, this prints a summary of the
2111  * key information to stdout.
2112  *
2113  * Arguments:
2114  * void* context
2115  * Context passed to KsmUpdate. This is unused.
2116  *
2117  * KSM_KEYDATA* data
2118  * Data about the key to be isssued.
2119  *
2120  * Returns:
2121  * int
2122  * Always 0.
2123 -*/
2124 
2125 int KsmRequestPrintKey(void* context, KSM_KEYDATA* data)
2126 {
2127  /* Unused parameter */
2128  (void)context;
2129 
2130  printf("%s %lu %d %d %s\n", KsmKeywordStateValueToName(data->state),
2131  data->keypair_id, data->keytype, data->algorithm, data->location);
2132 
2133  return 0;
2134 }
int KsmRequestChangeStateKeyPublishActive(const char *datetime, int zone_id, int policy_id, int *NewDS)
Definition: ksm_request.c:706
int KsmRequestKeys(int keytype, int rollover, const char *datetime, KSM_REQUEST_CALLBACK callback, void *context, int policy_id, int zone_id, int run_interval, int *NewDS)
Definition: ksm_request.c:95
#define KME_READYCNT
Definition: kmedef.h:63
int KsmRequestCountReadyKey(int keytype, const char *datetime, int *count, int zone_id)
Definition: ksm_request.c:1876
#define KSM_TYPE_ZSK
Definition: ksm.h:357
#define StrFree(x)
Definition: string_util.h:66
void DusConditionKeyword(char **query, const char *field, DQS_COMPARISON compare, const char *value, int clause)
Definition: du_string.c:182
int DbRollback(void)
#define KSM_INVARG
Definition: ksmdef.h:66
int KsmRequestCheckActiveKey(int keytype, const char *datetime, int *count, int zone_id)
Definition: ksm_request.c:1812
#define KSM_SQLFAIL
Definition: ksmdef.h:67
int KsmRequestPendingRetireCount(int keytype, const char *datetime, KSM_PARCOLL *parameters, int *count, int zone_id, int interval)
Definition: ksm_request.c:1480
#define KSM_STATE_DEAD
Definition: ksm.h:370
int KsmRequestCheckFirstPass(int keytype, int *first_pass_flag, int zone_id)
Definition: ksm_request.c:1928
union DQS_QUERY_CONDITION::@0 data
char * DqsSpecifyInit(const char *table, const char *fields)
Definition: dq_string.c:117
#define KSM_STATE_ACTIVE
Definition: ksm.h:366
char location[KSM_NAME_LENGTH]
Definition: ksm.h:109
int KsmUpdate(int policy_id, int zone_id)
Definition: ksm_update.c:70
int(* KSM_REQUEST_CALLBACK)(void *context, KSM_KEYDATA *key)
Definition: ksm.h:545
int KsmRequestChangeStateGeneratePublishConditional(int keytype, const char *datetime, KSM_PARCOLL *collection, int zone_id, int run_interval)
Definition: ksm_request.c:1363
#define KSM_STATE_READY
Definition: ksm.h:364
int KsmParameterZskTtl(KSM_PARCOLL *collection)
#define KME_AVAILCNT
Definition: kmedef.h:47
int KsmRequestGenerateCount(int keytype, int *count, int zone_id)
Definition: ksm_request.c:1683
#define KSM_ROLL_DS
Definition: ksm.h:397
int state
Definition: ksm.h:99
int KsmParameterCollection(KSM_PARCOLL *data, int policy_id)
void DusFree(char *sql)
Definition: du_string.c:223
int KsmRequestChangeState(int keytype, const char *datetime, int src_state, int dst_state, int zone_id, int policy_id, int rollover_scheme, int *NewDS)
Definition: ksm_request.c:764
DQS_COMPARISON compare
#define KME_GENERATECNT
Definition: kmedef.h:53
#define KME_PROM_PUB
Definition: kmedef.h:71
void DqsConditionKeyword(char **query, const char *field, DQS_COMPARISON compare, const char *value, int index)
Definition: dq_string.c:251
int KsmRequestCheckCompromisedFlag(int keytype, int zone_id, int *comp_flag)
Definition: ksm_request.c:1984
#define KSM_STATE_READY_STRING
Definition: ksm.h:365
int KsmRequestPrintKey(void *context, KSM_KEYDATA *data)
Definition: ksm_request.c:2125
int KsmRequestChangeStateDSPublishDSReady(int keytype, const char *datetime, int zone_id, int policy_id)
Definition: ksm_request.c:692
#define DB_KEYDATA_ZONE_ID
Definition: db_fields.h:68
#define KME_DS_SUBMISSION
Definition: kmedef.h:82
int MsgLog(int status,...)
Definition: message.c:335
void DbgLog(unsigned int mask, int status,...)
Definition: debug.c:170
void DusSetInt(char **sql, const char *field, int data, int clause)
Definition: du_string.c:97
void DqsFree(char *query)
Definition: dq_string.c:320
#define KSM_ROLL_DNSKEY
Definition: ksm.h:395
#define KME_DS_REM_ZONE
Definition: kmedef.h:74
#define KSM_STATE_KEYPUBLISH
Definition: ksm.h:378
#define KME_INSFGENKEY
Definition: kmedef.h:54
int KsmParameterKskTtl(KSM_PARCOLL *collection)
void DusConditionInt(char **query, const char *field, DQS_COMPARISON compare, int value, int clause)
Definition: du_string.c:170
#define MemFree(ptr)
Definition: memory.h:48
const char * KsmKeywordStateValueToName(int value)
Definition: ksm_keyword.c:242
char * DqsCountInit(const char *table)
Definition: dq_string.c:90
DB_HANDLE DbHandle(void)
int KsmParameterKskPropagationDelay(KSM_PARCOLL *collection)
char * StrStrdup(const char *string)
Definition: string_util.c:124
void DqsConditionInt(char **query, const char *field, DQS_COMPARISON compare, int value, int index)
Definition: dq_string.c:224
int KsmRequestChangeStateReadyActive(int keytype, const char *datetime, int count, int zone_id)
Definition: ksm_request.c:998
#define KME_KEYCHSTATE
Definition: kmedef.h:55
int DbCommit(void)
int kskmanroll
Definition: ksm.h:484
int KsmRequestStandbyKSKCount(int *count, int zone_id)
Definition: ksm_request.c:1733
int KsmRequestChangeStateGenerateDSSub(int keytype, const char *datetime, int count, int zone_id)
Definition: ksm_request.c:991
#define KSM_STATE_DSPUBLISH
Definition: ksm.h:374
#define DB_KEYDATA_STATE
Definition: db_fields.h:58
int KsmParameterStandbyZSKeys(KSM_PARCOLL *collection)
int KsmRequestChangeStatePublishReady(int keytype, const char *datetime, int zone_id, int policy_id, int *NewDS)
Definition: ksm_request.c:686
int KsmKeyInitSql(DB_RESULT *result, const char *sql)
Definition: ksm_key.c:217
#define DB_KEYDATA_FIELDS
Definition: db_fields.h:56
const char * DbErrmsg(DB_HANDLE handle)
int KsmKey(DB_RESULT result, KSM_KEYDATA *data)
Definition: ksm_key.c:366
#define KME_NOREADYKEY
Definition: kmedef.h:57
int KsmParameterPropagationDelay(KSM_PARCOLL *collection)
int KsmRequestAvailableCount(int keytype, const char *datetime, KSM_PARCOLL *parameters, int *count, int zone_id)
Definition: ksm_request.c:1613
int KsmRequestChangeStateGeneratePublish(int keytype, const char *datetime, int count, int zone_id)
Definition: ksm_request.c:984
int keytype
Definition: ksm.h:100
int KsmKeyInit(DB_RESULT *result, DQS_QUERY_CONDITION *condition)
Definition: ksm_key.c:249
#define KME_SQLFAIL
Definition: kmedef.h:67
void StrAppend(char **str1, const char *str2)
Definition: string_util2.c:76
#define KSM_STATE_PUBLISH_STRING
Definition: ksm.h:363
int KsmRequestChangeStateRetireDead(int keytype, const char *datetime, int zone_id, int policy_id, int rollover_scheme, int *NewDS)
Definition: ksm_request.c:719
int algorithm
Definition: ksm.h:101
void DusEnd(char **sql)
Definition: du_string.c:202
int DbIntQuery(DB_HANDLE handle, int *value, const char *query)
int KsmRequestChangeStateN(int keytype, const char *datetime, int count, int src_state, int dst_state, int zone_id)
Definition: ksm_request.c:1039
#define KSM_STATE_RETIRE
Definition: ksm.h:368
#define KSM_STATE_PUBLISH
Definition: ksm.h:362
int KsmZoneNameFromId(int zone_id, char **zone_name)
Definition: ksm_zone.c:412
char * DusInit(const char *table)
Definition: du_string.c:60
#define KME_NEW_DS
Definition: kmedef.h:84
int KsmParameterPubSafety(KSM_PARCOLL *collection)
int KsmRequestKeysByType(int keytype, int rollover, const char *datetime, KSM_REQUEST_CALLBACK callback, void *context, int policy_id, int zone_id, int run_interval, int *NewDS)
Definition: ksm_request.c:210
DB_ID keypair_id
Definition: ksm.h:98
#define KME_ROLL_ZONE
Definition: kmedef.h:76
const char * KsmKeywordTypeValueToName(int value)
Definition: ksm_keyword.c:247
#define KME_MAN_ROLL_REQUIRED
Definition: kmedef.h:79
#define KME_BACK_NON_FATAL
Definition: kmedef.h:73
#define KME_BUFFEROVF
Definition: kmedef.h:48
#define KME_BACK_FATAL
Definition: kmedef.h:72
#define DB_KEYDATA_KEYTYPE
Definition: db_fields.h:65
int KsmRequestChangeStateDSReadyKeyPublish(const char *datetime, int zone_id, int policy_id)
Definition: ksm_request.c:699
#define KSM_STATE_DSSUB
Definition: ksm.h:372
#define KSM_TYPE_KSK
Definition: ksm.h:355
int KsmParameterStandbyKSKeys(KSM_PARCOLL *collection)
#define DBG_M_REQUEST
Definition: debug.h:45
#define KME_KEYCNTSUMM
Definition: kmedef.h:56
void * MemMalloc(size_t size)
Definition: memory.c:57
int KsmRequestChangeStateGenerateDSSubConditional(int keytype, const char *datetime, KSM_PARCOLL *collection, int zone_id, int *NewDS)
Definition: ksm_request.c:1258
#define KSM_STATE_DSREADY
Definition: ksm.h:376
size_t StrToUpper(char *text)
Definition: string_util.c:353
void KsmKeyEnd(DB_RESULT result)
Definition: ksm_key.c:469
#define KME_UNKEYTYPE
Definition: kmedef.h:68
#define KSM_STATE_GENERATE
Definition: ksm.h:360
void DusSetString(char **sql, const char *field, const char *data, int clause)
Definition: du_string.c:113
int KsmRequestIssueKeys(int keytype, KSM_REQUEST_CALLBACK callback, void *context, int zone_id)
Definition: ksm_request.c:2046
void DqsEnd(char **query)
Definition: dq_string.c:299
#define KME_REQKEYTYPE
Definition: kmedef.h:65
int DbBeginTransaction(void)
int DbExecuteSqlNoResult(DB_HANDLE handle, const char *stmt_str)
int KsmRequestSetActiveExpectedRetire(int keytype, const char *datetime, int zone_id)
Definition: ksm_request.c:519
int zskmanroll
Definition: ksm.h:485
void DqsConditionString(char **query, const char *field, DQS_COMPARISON compare, const char *value, int index)
Definition: dq_string.c:238
#define KME_RETIRECNT
Definition: kmedef.h:66
int KsmRequestChangeStateActiveRetire(int keytype, const char *datetime, int zone_id, int policy_id)
Definition: ksm_request.c:712
int kskroll
Definition: ksm.h:487
#define KME_REMAINACT
Definition: kmedef.h:64