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