OpenDNSSEC-enforcer  1.4.7
ksm_key.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  * KsmKey - Manipulation of Key Information
29  *
30  * Description:
31  * Holds the functions needed to manipulate the KEYDATA table.
32  *
33  * N.B. The table is the KEYDATA table - rather than the KEY table - as
34  * KEY is a reserved word in SQL.
35 -*/
36 
37 #include <assert.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <time.h>
42 
43 #include "ksm/database.h"
44 #include "ksm/database_statement.h"
45 #include "ksm/datetime.h"
46 #include "ksm/db_fields.h"
47 #include "ksm/debug.h"
48 #include "ksm/kmedef.h"
49 #include "ksm/ksm.h"
50 #include "ksm/ksmdef.h"
51 #include "ksm/ksm_internal.h"
52 #include "ksm/message.h"
53 #include "ksm/string_util.h"
54 #include "ksm/string_util2.h"
55 
56 /*+
57  * KsmKeyPairCreate - Create Entry in the KeyPairs table
58  * (i.e. key creation in the HSM)
59  *
60  * Description:
61  * Creates a key in the database.
62  *
63  * Arguments:
64  * policy_id
65  * policy that the key is created for
66  * HSMKeyID
67  * ID the key is refered to in the HSM
68  * smID
69  * security module ID
70  * size
71  * size of key
72  * alg
73  * algorithm used
74  * generate
75  * timestamp of generation
76  *
77  * DB_ID* id (returned)
78  * ID of the created entry. This will be undefined on error.
79  *
80  * Returns:
81  * int
82  * Status return. 0=> Success, non-zero => error.
83 -*/
84 int KsmKeyPairCreate(int policy_id, const char* HSMKeyID, int smID, int size, int alg, const char* generate, DB_ID* id)
85 {
86  unsigned long rowid; /* ID of last inserted row */
87  int status = 0; /* Status return */
88  char* sql = NULL; /* SQL Statement */
89 
90  /* Check arguments */
91  if (id == NULL) {
92  return MsgLog(KSM_INVARG, "NULL id");
93  }
94 
95  sql = DisSpecifyInit("keypairs", "policy_id, HSMkey_id, securitymodule_id, size, algorithm, generate");
96  DisAppendInt(&sql, policy_id);
97  DisAppendString(&sql, HSMKeyID);
98  DisAppendInt(&sql, smID);
99  DisAppendInt(&sql, size);
100  DisAppendInt(&sql, alg);
101  DisAppendString(&sql, generate);
102  DisEnd(&sql);
103 
104  /* Execute the statement */
105 
106  status = DbExecuteSqlNoResult(DbHandle(), sql);
107  DisFree(sql);
108 
109  if (status == 0) {
110 
111  /* Succcess, get the ID of the inserted record */
112 
113  status = DbLastRowId(DbHandle(), &rowid);
114  if (status == 0) {
115  *id = (DB_ID) rowid;
116  }
117  }
118 
119  return status;
120 }
121 
122 /*+
123  * KsmDnssecKeyCreate - Create Entry in Dnsseckeys table
124  * (i.e. when a key is assigned to a policy/zone)
125  *
126  * Description:
127  * Allocates a key in the database.
128  *
129  * Arguments:
130  * KSM_KEY* data
131  * Data to insert into the database. The ID argument is ignored.
132  *
133  * DB_ID* id (returned)
134  * ID of the created entry. This will be undefined on error.
135  *
136  * Returns:
137  * int
138  * Status return. 0=> Success, non-zero => error.
139 -*/
140 
141 int KsmDnssecKeyCreate(int zone_id, int keypair_id, int keytype, int state, const char* time, const char* retTime, DB_ID* id)
142 {
143  unsigned long rowid; /* ID of last inserted row */
144  int status = 0; /* Status return */
145  char* sql = NULL; /* SQL Statement */
146  char* columns = NULL; /* what columns are we setting */
147 
148  /* Check arguments */
149  if (id == NULL) {
150  return MsgLog(KSM_INVARG, "NULL id");
151  }
152 
153  StrAppend(&columns, "zone_id, keypair_id, keytype, state");
154  if (state != KSM_STATE_GENERATE) {
155  StrAppend(&columns, ", ");
156  StrAppend(&columns, KsmKeywordStateValueToName(state));
157  }
158  if (state == KSM_STATE_ACTIVE && (retTime != NULL && retTime[0] != '\0')) {
159  StrAppend(&columns, ", retire");
160  }
161 
162  sql = DisSpecifyInit("dnsseckeys", columns);
163  DisAppendInt(&sql, zone_id);
164  DisAppendInt(&sql, keypair_id);
165  DisAppendInt(&sql, keytype);
166  DisAppendInt(&sql, state);
167  if (state != KSM_STATE_GENERATE) {
168  DisAppendString(&sql, time);
169  }
170  if (state == KSM_STATE_ACTIVE && (retTime != NULL && retTime[0] != '\0')) {
171  DisAppendString(&sql, retTime);
172  }
173  DisEnd(&sql);
174 
175  /* Execute the statement */
176 
177  status = DbExecuteSqlNoResult(DbHandle(), sql);
178  DisFree(sql);
179  StrFree(columns);
180 
181  if (status == 0) {
182 
183  /* Succcess, get the ID of the inserted record */
184 
185  status = DbLastRowId(DbHandle(), &rowid);
186  if (status == 0) {
187  *id = (DB_ID) rowid;
188  }
189  }
190 
191  return status;
192 }
193 
194 /*+
195  * KsmKeyInitSql - Query for Key Information With Sql Query
196  *
197  * Description:
198  * Performs a query for keys in the keydata table that match the given
199  * conditions.
200  *
201  * Arguments:
202  * DB_RESULT* result
203  * Pointer to a result to be used for information retrieval. Will
204  * be NULL on error.
205  *
206  * const char* sql
207  * SQL statement to select keys.
208  *
209  * (Actually, the statement could be anything, but it is assumed
210  * that it is an SQL statement starting "SELECT xxx FROM KEYDATA".)
211  *
212  * Returns:
213  * int
214  * Status return. 0 on success.
215 -*/
216 
217 int KsmKeyInitSql(DB_RESULT* result, const char* sql)
218 {
219  return DbExecuteSql(DbHandle(), sql, result);
220 }
221 
222 
223 
224 
225 /*+
226  * KsmKeyInit - Query for Key Information
227  *
228  * Description:
229  * Performs a query for keys in the keydata table that match the given
230  * conditions.
231  *
232  * Arguments:
233  * DB_RESULT* result
234  * Pointer to a result to be used for information retrieval. Will
235  * be NULL on error.
236  *
237  * DQS_QUERY_CONDITION* condition
238  * Array of condition objects, each defining a condition. The
239  * conditions are ANDed together. The array should end with an object
240  * with a condition code of 0.
241  *
242  * If NULL, all objects are selected.
243  *
244  * Returns:
245  * int
246  * Status return. 0 on success.
247 -*/
248 
249 int KsmKeyInit(DB_RESULT* result, DQS_QUERY_CONDITION* condition)
250 {
251  int i; /* Condition index */
252  char* sql = NULL; /* SQL query */
253  int status = 0; /* Status return */
254 
255  /* Construct the query */
256 
257  sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
258  if (condition) {
259  for (i = 0; condition[i].compare != DQS_END_OF_LIST; ++i) {
260  switch (condition[i].code) {
262  DqsConditionInt(&sql, "ALGORITHM", condition[i].compare,
263  condition[i].data.number, i);
264  break;
265 
266  case DB_KEYDATA_ID:
267  DqsConditionInt(&sql, "ID", condition[i].compare,
268  condition[i].data.number, i);
269  break;
270 
271  case DB_KEYDATA_KEYTYPE:
272  DqsConditionInt(&sql, "KEYTYPE", condition[i].compare,
273  condition[i].data.number, i);
274  break;
275 
276  case DB_KEYDATA_STATE:
277  DqsConditionInt(&sql, "STATE", condition[i].compare,
278  condition[i].data.number, i);
279  break;
280 
281  case DB_KEYDATA_ZONE_ID:
282  DqsConditionInt(&sql, "ZONE_ID", condition[i].compare,
283  condition[i].data.number, i);
284  break;
285 
286  default:
287 
288  /* Warn about unrecognised condition code */
289 
290  MsgLog(KME_UNRCONCOD, condition[i].code);
291  }
292  }
293  }
294  DqsEnd(&sql);
295 
296  /* Execute query and free up the query string */
297 
298  status = KsmKeyInitSql(result, sql);
299  DqsFree(sql);
300 
301  return status;
302 }
303 
304 
305 
306 /*+
307  * KsmKeyInitId - Query for Key Information by ID
308  *
309  * Description:
310  * Performs a query for a key in the zone table that matches the
311  * given ID.
312  *
313  * Arguments:
314  * DB_RESULT* result
315  * Pointer to a result to be used for information retrieval. Will
316  * be NULL on error.
317  *
318  * DB_ID id
319  * ID of the object.
320  *
321  * Returns:
322  * int
323  * Status return. 0 on success.
324 -*/
325 
326 int KsmKeyInitId(DB_RESULT* result, DB_ID id)
327 {
328  DQS_QUERY_CONDITION condition[2]; /* Condition for query */
329 
330  /* Initialize */
331 
332  condition[0].code = DB_KEYDATA_ID;
333  condition[0].compare = DQS_COMPARE_EQ;
334  condition[0].data.number = (int) id;
335 
336  condition[1].compare = DQS_END_OF_LIST;
337 
338  return KsmKeyInit(result, condition);
339 }
340 
341 
342 
343 /*+
344  * KsmKey - Return Key Information
345  *
346  * Description:
347  * Returns information about the next key in the result set.
348  *
349  * Arguments:
350  * DB_RESULT result
351  * Handle from KsmKeyInit
352  *
353  * KSM_KEYDATA* data
354  * Data is returned in here.
355  *
356  * Returns:
357  * int
358  * Status return:
359  * 0 success
360  * -1 end of record set reached
361  * non-zero some error occurred and a message has been output.
362  *
363  * If the status is non-zero, the returned data is meaningless.
364 -*/
365 
366 int KsmKey(DB_RESULT result, KSM_KEYDATA* data)
367 {
368  DB_ROW row = NULL; /* Row data */
369  int status = 0; /* Return status */
370 
371  /* Check arguments */
372  if (data == NULL) {
373  return MsgLog(KSM_INVARG, "NULL data");
374  }
375 
376  /* Initialize */
377 
378  memset(data, 0, sizeof(KSM_KEYDATA));
379 
380  /* Get the next row from the data and copy data across */
381 
382  status = DbFetchRow(result, &row);
383 
384  if (status == 0) {
385  status = DbUnsignedLong(row, DB_KEYDATA_ID, &(data->keypair_id));
386  }
387 
388  if (status == 0) {
389  status = DbInt(row, DB_KEYDATA_STATE, &(data->state));
390  }
391 
392  if (status == 0) {
393  status = DbStringBuffer(row, DB_KEYDATA_GENERATE,
394  data->generate, sizeof(data->generate));
395  }
396 
397  if (status == 0) {
398  status = DbStringBuffer(row, DB_KEYDATA_PUBLISH,
399  data->publish, sizeof(data->publish));
400  }
401 
402  if (status == 0) {
403  status = DbStringBuffer(row, DB_KEYDATA_READY,
404  data->ready, sizeof(data->ready));
405  }
406 
407  if (status == 0) {
408  status = DbStringBuffer(row, DB_KEYDATA_ACTIVE,
409  data->active, sizeof(data->active));
410  }
411 
412  if (status == 0) {
413  status = DbStringBuffer(row, DB_KEYDATA_RETIRE,
414  data->retire, sizeof(data->retire));
415  }
416 
417  if (status == 0) {
418  status = DbStringBuffer(row, DB_KEYDATA_DEAD,
419  data->dead, sizeof(data->dead));
420  }
421 
422  if (status == 0) {
423  status = DbInt(row, DB_KEYDATA_KEYTYPE, &(data->keytype));
424  }
425 
426  if (status == 0) {
427  status = DbInt(row, DB_KEYDATA_ALGORITHM, &(data->algorithm));
428  }
429 
430 /* if (status == 0) {
431  status = DbInt(row, DB_KEYDATA_SIGLIFETIME, &(data->siglifetime));
432  }
433 */
434  if (status == 0) {
435  status = DbStringBuffer(row, DB_KEYDATA_LOCATION,
436  data->location, sizeof(data->location));
437  }
438 
439  if (status == 0) {
440  status = DbInt(row, DB_KEYDATA_ZONE_ID, &(data->zone_id));
441  }
442 
443  if (status == 0) {
444  status = DbInt(row, DB_KEYDATA_FIXED_DATE, &(data->fixedDate));
445  }
446 
447  DbFreeRow(row);
448 
449  return status;
450 }
451 
452 
453 /*+
454  * KsmKeyEnd - End Key Information
455  *
456  * Description:
457  * Called at the end of a ksm_key cycle, frees up the stored
458  * result set.
459  *
460  * N.B. This does not clear stored error information, so allowing it
461  * to be called after a failure return from KsmKey to free up database
462  * context whilst preserving the reason for the error.
463  *
464  * Arguments:
465  * DB_RESULT result
466  * Handle from KsmKeyInit
467 -*/
468 
469 void KsmKeyEnd(DB_RESULT result)
470 {
471  DbFreeResult(result);
472 }
473 
474 
475 
476 /*+
477  * KsmKeyData - Return Data for Key
478  *
479  * Description:
480  * Returns data for the named Key.
481  *
482  * Arguments:
483  * DB_ID id
484  * Name/ID of the Key.
485  *
486  * KSM_GROUP* data
487  * Data for the Key.
488  *
489  * Returns:
490  * int
491  * Status return. One of:
492  *
493  * 0 Success
494  * -1 Key not found
495  * Other Error
496 -*/
497 
499 {
500  DB_RESULT result; /* Handle to the data */
501  int status; /* Status return code */
502 
503  status = KsmKeyInitId(&result, id);
504  if (status == 0) {
505 
506  /* Retrieve the key data */
507 
508  status = KsmKey(result, data);
509  (void) KsmKeyEnd(result);
510  }
511  /*
512  * else {
513  * On error, a message will have been output
514  * }
515  */
516 
517  return status;
518 }
519 
520 /*+
521  * KsmKeyPredict - predict how many keys are needed
522  *
523  * Description:
524  * Given a policy and a keytype work out how many keys will be required
525  * during the timeinterval specified (in seconds).
526  *
527  * We assume no emergency rollover and that a key has just been published
528  *
529  * Dt = interval
530  * Sp = safety margin
531  * Lk = lifetime of the key (either KSK or ZSK)
532  * Ek = no of standby keys
533  *
534  * no of keys = ( (Dt + Sp)/Lk ) + Ek
535  *
536  * (rounded up)
537  *
538  * Arguments:
539  * int policy_id
540  * The policy in question
541  * KSM_TYPE key_type
542  * KSK or ZSK
543  * int shared_keys
544  * 0 if keys not shared between zones
545  * int interval
546  * timespan (in seconds)
547  * int *count
548  * (OUT) the number of keys (-1 on error)
549  * int rollover_scheme
550  * KSK rollover scheme in use
551  * int zone_count
552  * Number of zones on this policy
553  *
554  * Returns:
555  * int
556  * Status return. One of:
557  *
558  * 0 Success
559  * Other Error
560 -*/
561 
562 int KsmKeyPredict(int policy_id, int keytype, int shared_keys, int interval, int *count, int rollover_scheme, int zone_count)
563 {
564  int status = 0; /* Status return */
565  KSM_PARCOLL coll; /* Parameters collection */
566 
567  /* Check arguments */
568  if (count == NULL) {
569  return MsgLog(KSM_INVARG, "NULL count");
570  }
571 
572  /* make sure that we have at least one zone */
573  if (zone_count == 0) {
574  *count = 0;
575  return status;
576  }
577 
578  /* Check that we have a valid key type */
579  if ((keytype != KSM_TYPE_KSK) && (keytype != KSM_TYPE_ZSK)) {
580  status = MsgLog(KME_UNKEYTYPE, keytype);
581  return status;
582  }
583 
584  /* Get list of parameters */
585  status = KsmParameterCollection(&coll, policy_id);
586  if (status != 0) {
587  *count = -1;
588  return status;
589  }
590 
591  /* We should have the policy now */
592  if (keytype == KSM_TYPE_KSK)
593  {
594  if (coll.ksklife == 0) {
595  *count = coll.standbyksks + 1;
596  }
597  else if (rollover_scheme == KSM_ROLL_DNSKEY) {
598  *count = ((interval + coll.pub_safety + coll.propdelay + coll.kskttl)/coll.ksklife) + coll.standbyksks + 1;
599  }
600  else if (rollover_scheme == KSM_ROLL_DS) {
601  *count = ((interval + coll.pub_safety + coll.kskpropdelay + coll.dsttl)/coll.ksklife) + coll.standbyksks + 1;
602  }
603 /* else if (rollover_scheme == KSM_ROLL_RRSET) {
604  temp = MAX((propdelay + kskttl), (kskpropdelay + dsttl));
605  if (RFC5011) {
606  temp = max(temp, 30*24*60*60);
607  }
608  *count = ((interval + coll.pub_safety + temp)/coll.ksklife) + coll.standbyksks + 1;
609  } */
610 
611  }
612  else if (keytype == KSM_TYPE_ZSK)
613  {
614  if (coll.zsklife == 0) {
615  *count = coll.standbyzsks + 1;
616  } else {
617  *count = ((interval + coll.pub_safety)/coll.zsklife) + coll.standbyzsks + 1;
618  }
619  }
620 
621  if (shared_keys == KSM_KEYS_NOT_SHARED) {
622  *count *= zone_count;
623  }
624 
625  return status;
626 }
627 
628 /*+
629  * KsmKeyCountQueue - Return Number of Keys in the queue before active state
630  *
631  * Description:
632  * Returns the number of keys in the KSM_STATE_GENERATE, KSM_STATE_PUBLISH,
633  * KSM_STATE_READY and KSM_STATE_ACTIVE state.
634  * (plus KSM_STATE_DSSUB, KSM_STATE_DSPUBLISH, KSM_STATE_DSREADY
635  * for standby KSKs)
636  *
637  * Arguments:
638  * int keytype
639  * Key type, KSK or ZSK
640  *
641  * int* count (returned)
642  * Number of keys in the que.
643  *
644  * int zone_id
645  * ID of zone that we are looking at (-1 == all zones)
646  *
647  * Returns:
648  * int
649  * Status return. 0 => success, Other implies error, in which case a
650  * message will have been output.
651 -*/
652 
653 int KsmKeyCountQueue(int keytype, int* count, int zone_id)
654 {
655  int clause = 0; /* Clause count */
656  char* sql = NULL; /* SQL to interrogate database */
657  int status = 0; /* Status return */
658  char in[128]; /* Easily large enought for 7 keys */
659  size_t nchar; /* Number of output characters */
660 
661  /* Create the SQL command to interrogate the database */
662 
663  nchar = snprintf(in, sizeof(in), "(%d, %d, %d, %d, %d, %d, %d)",
665  if (nchar >= sizeof(in)) {
666  status = MsgLog(KME_BUFFEROVF, "KsmKeyCountQueue");
667  return status;
668  }
669 
670  sql = DqsCountInit("KEYDATA_VIEW");
671  DqsConditionInt(&sql, "KEYTYPE", DQS_COMPARE_EQ, keytype, clause++);
672  DqsConditionKeyword(&sql, "STATE", DQS_COMPARE_IN, in, clause++);
673  if (zone_id != -1) {
674  DqsConditionInt(&sql, "ZONE_ID", DQS_COMPARE_EQ, zone_id, clause++);
675  }
676  DqsEnd(&sql);
677 
678  /* Execute the query and free resources */
679 
680  status = DbIntQuery(DbHandle(), count, sql);
681  DqsFree(sql);
682 
683  /* Report any errors */
684 
685  if (status != 0) {
686  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
687  }
688 
689  return status;
690 }
691 
692 /*+
693  * KsmKeyCountStillGood - Return Number of Keys that will still be usable at a particular
694  * time given a number of parameters
695  *
696  * Description:
697  * Returns the number of keys in the KSM_STATE_GENERATE, KSM_STATE_PUBLISH,
698  * KSM_STATE_READY, KSM_STATE_ACTIVE (or KSM_STATE_DSSUB,
699  * KSM_STATE_DSPUBLISH, KSM_STATE_DSREADY for standby KSKs) state after
700  * the given interval.
701  *
702  * Arguments:
703  * int policy_id
704  * id of the policy for which they key must have been created
705  * (-1 == all policies)
706  * int sm
707  * id of security module
708  * (-1 == all modules)
709  * int bits
710  * size of key desired
711  * (-1 == all sizes)
712  * int algorithm
713  * algorithm of key desired
714  * (-1 == all algorithms`)
715  * int interval
716  * how many seconds in the future we are talking about
717  * const char* datetime
718  * string describing when this calculation is being run
719  *
720  * int* count (returned)
721  * Number of keys in the que.
722  *
723  * int keytype
724  * Key type, KSK or ZSK
725  *
726  * Returns:
727  * int
728  * Status return. 0 => success, Other implies error, in which case a
729  * message will have been output.
730 -*/
731 
732 int KsmKeyCountStillGood(int policy_id, int sm, int bits, int algorithm, int interval, const char* datetime, int *count, int keytype)
733 {
734  int where = 0; /* WHERE clause value */
735  char* sql = NULL; /* SQL to interrogate database */
736  int status = 0; /* Status return */
737  char in[128]; /* Easily large enought for three keys */
738  char buffer[512]; /* For constructing part of the command */
739  size_t nchar; /* Number of output characters */
740  int total_interval; /* interval plus retirement time */
741  KSM_PARCOLL collection; /* Parameters collection */
742 
743  /*
744  * Construct the "IN" statement listing the states of the keys that
745  * are included in the output.
746  */
747 
748  /* Get list of parameters */
749  status = KsmParameterCollection(&collection, policy_id);
750  if (status != 0) {
751  return status;
752  }
753 
754  if (keytype == KSM_TYPE_ZSK)
755  {
756  total_interval = KsmParameterZskTtl(&collection) +
757  KsmParameterPropagationDelay(&collection) +
758  KsmParameterPubSafety(&collection) +
759  interval;
760  } else {
761  total_interval = KsmParameterKskTtl(&collection) +
762  KsmParameterKskPropagationDelay(&collection) +
763  KsmParameterPubSafety(&collection) +
764  interval;
765  }
766 
767  nchar = snprintf(in, sizeof(in), "(%d, %d, %d, %d, %d, %d, %d)",
769  if (nchar >= sizeof(in)) {
770  status = MsgLog(KME_BUFFEROVF, "KsmKeyCountStillGood");
771  return status;
772  }
773 
774  /*
775  * TODO is there an alternative to DATE_ADD which is more generic?
776  */
777 #ifdef USE_MYSQL
778  nchar = snprintf(buffer, sizeof(buffer),
779  "DATE_ADD('%s', INTERVAL %d SECOND)", datetime, total_interval);
780 #else
781  nchar = snprintf(buffer, sizeof(buffer),
782  "DATETIME('%s', '+%d SECONDS')", datetime, total_interval);
783 #endif /* USE_MYSQL */
784  if (nchar >= sizeof(buffer)) {
785  status = MsgLog(KME_BUFFEROVF, "KsmKeyCountStillGood");
786  return status;
787  }
788 
789  /* Create the SQL command to interrogate the database */
790 
791  /* Use 'distinct location' here so we don't count multiple entries for zones which share keys*/
792  sql = StrStrdup("SELECT COUNT(DISTINCT location) FROM KEYDATA_VIEW");
793  if (policy_id != -1) {
794  DqsConditionInt(&sql, "policy_id", DQS_COMPARE_EQ, policy_id, where++);
795  }
796  if (sm != -1) {
797  DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, sm, where++);
798  }
799  if (bits != -1) {
800  DqsConditionInt(&sql, "size", DQS_COMPARE_EQ, bits, where++);
801  }
802  if (algorithm != -1) {
803  DqsConditionInt(&sql, "algorithm", DQS_COMPARE_EQ, algorithm, where++);
804  }
805 
806  DqsConditionKeyword(&sql, "(STATE", DQS_COMPARE_IN, in, where++);
807  StrAppend(&sql, " or STATE is NULL)");
808 
809  /* Can't use our generic functions for this aggregated clause */
810 #ifdef USE_MYSQL
811  StrAppend(&sql, " and (RETIRE > ");
812 #else
813  StrAppend(&sql, " and (DATETIME(RETIRE) > ");
814 #endif /* USE_MYSQL */
815  StrAppend(&sql, buffer);
816  StrAppend(&sql, " or RETIRE is NULL)");
817 
818  /*DqsConditionKeyword(&sql, "zone_id", DQS_COMPARE_IS, "NULL", where++);*/
819  DqsEnd(&sql);
820 
821  /* Execute the query and free resources */
822 
823  status = DbIntQuery(DbHandle(), count, sql);
824  DqsFree(sql);
825 
826  /* Report any errors */
827 
828  if (status != 0) {
829  status = MsgLog(KME_SQLFAIL, DbErrmsg(DbHandle()));
830  }
831 
832  return status;
833 }
834 
835 /*+
836  * KsmKeyGetUnallocated
837  *
838  * Description:
839  * Given a set of policy values get the next unallocated keypair
840  * Executes:
841  * select min(id) from keydata
842  * where policy_id = policy_id
843  * and securitymodule_id = sm
844  * and size = bits
845  * and algorithm = algorithm
846  * and state is KSM_STATE_GENERATE
847  *
848  * Arguments:
849  * int policy_id
850  * id of the policy for which they key must have been created
851  * int sm
852  * id of security module
853  * int bits
854  * size of key desired
855  * int algorithm
856  * algorithm of key desired
857  * int zone_id
858  * zone we are allocating to
859  * int share_keys
860  * 0 if keys are not shared; 1 if they are
861  * int *keypair_id (out)
862  * id of next keypair
863  *
864  * Returns:
865  * int
866  * Status return. 0=> Success, non-zero => error.
867  * -1 == no free keys on that policy
868  */
869 
870 int KsmKeyGetUnallocated(int policy_id, int sm, int bits, int algorithm, int zone_id, int share_keys, int *keypair_id)
871 {
872 
873  int where = 0; /* WHERE clause value */
874  char* sql = NULL; /* SQL query */
875  DB_RESULT result; /* Handle converted to a result object */
876  DB_ROW row = NULL; /* Row data */
877  int status = 0; /* Status return */
878  char in_sql[1024];
879  char in_sql2[1024];
880 
881  if (share_keys == KSM_KEYS_NOT_SHARED) {
882  /* Construct the query */
883  sql = DqsSpecifyInit("KEYDATA_VIEW","min(id)");
884  DqsConditionInt(&sql, "policy_id", DQS_COMPARE_EQ, policy_id, where++);
885  DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, sm, where++);
886  DqsConditionInt(&sql, "size", DQS_COMPARE_EQ, bits, where++);
887  DqsConditionInt(&sql, "algorithm", DQS_COMPARE_EQ, algorithm, where++);
888  DqsConditionKeyword(&sql, "zone_id", DQS_COMPARE_IS, "NULL", where++);
889  } else {
890  snprintf(in_sql, 1024, "(select id from KEYALLOC_VIEW where zone_id = %d)", zone_id);
891  snprintf(in_sql2, 1024, "(select distinct id from KEYDATA_VIEW where policy_id = %d and state in (%d, %d))", policy_id, KSM_STATE_RETIRE, KSM_STATE_DEAD);
892 
893  /* Construct the query */
894  sql = DqsSpecifyInit("KEYALLOC_VIEW","min(id)");
895  DqsConditionInt(&sql, "policy_id", DQS_COMPARE_EQ, policy_id, where++);
896  DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, sm, where++);
897  DqsConditionInt(&sql, "size", DQS_COMPARE_EQ, bits, where++);
898  DqsConditionInt(&sql, "algorithm", DQS_COMPARE_EQ, algorithm, where++);
899  DqsConditionKeyword(&sql, "zone_id", DQS_COMPARE_IS, "NULL", where++);
900  DqsConditionKeyword(&sql, "id", DQS_COMPARE_NOT_IN, in_sql, where++);
901  DqsConditionKeyword(&sql, "id", DQS_COMPARE_NOT_IN, in_sql2, where++);
902  }
903  /* Execute query and free up the query string */
904  status = DbExecuteSql(DbHandle(), sql, &result);
905  DqsFree(sql);
906 
907  if (status != 0)
908  {
909  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
910  DbFreeResult(result);
911  return status;
912  }
913 
914  /* Get the next row from the data */
915  status = DbFetchRow(result, &row);
916  if (status == 0) {
917  DbInt(row, DB_KEYDATA_ID, keypair_id);
918  }
919  else if (status == -1) {}
920  /* No rows to return (but no DB error) */
921  else {
922  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
923  }
924 
925  DbFreeRow(row);
926  DbFreeResult(result);
927  return status;
928 }
929 
930 /*+
931  * KsmMarkKeysAsDead - When deleting zones we may need to indicate that keys are now dead
932  * (i.e. when keysharing is turned off or if we removed is the last zone on a policy)
933  *
934  * Description:
935  * Marks selected keys as dead in the database.
936  *
937  * Arguments:
938  * int zone_id
939  * ID of the zone (-1 if all zones are being removed)
940  *
941  * Returns:
942  * int
943  * Status return. 0=> Success, non-zero => error.
944 -*/
945 
946 int KsmMarkKeysAsDead(int zone_id)
947 {
948  int status = 0;
949 
950  DB_RESULT result; /* Result of query */
951  KSM_KEYDATA data; /* key information */
952  char* sql = NULL; /* SQL query */
953  int clause = 0;
954 
955  /* Find all the keys which are on that zone but are not already dead */
956  sql = DqsSpecifyInit("KEYDATA_VIEW", DB_KEYDATA_FIELDS);
957  DqsConditionInt(&sql, "state", DQS_COMPARE_LT, KSM_STATE_DEAD, clause++);
958  DqsConditionInt(&sql, "state", DQS_COMPARE_GT, KSM_STATE_GENERATE, clause++);
959  if (zone_id != -1) {
960  DqsConditionInt(&sql, "zone_id", DQS_COMPARE_EQ, zone_id, clause++);
961  }
962  DqsEnd(&sql);
963 
964  /* Now iterate round the keys meeting the condition and print them */
965 
966  status = KsmKeyInitSql(&result, sql);
967  if (status == 0) {
968  status = KsmKey(result, &data);
969  while (status == 0) {
970 
971  /* Kill the Key */
972  status = KsmKillKey(data.keypair_id, zone_id);
973  if (status == 0) {
974  status = KsmKey(result, &data);
975  }
976  }
977 
978  /* Convert EOF status to success */
979 
980  if (status == -1) {
981  status = 0;
982  }
983 
984  KsmKeyEnd(result);
985  }
986 
987  DqsFree(sql);
988  return 0;
989 }
990 
991 /*+
992  * KsmKillKey - Update key status to "dead"
993  *
994  * Description:
995  * Changes a keys status to dead (from any state)
996  *
997  * Arguments:
998  * int keypair_id
999  * Which key to process
1000  * int zone_id
1001  * Which zone to process
1002  *
1003  * Returns:
1004  * int
1005  * Status return. 0=> Success, non-zero => error.
1006 -*/
1007 
1008 int KsmKillKey(int keypair_id, int zone_id)
1009 {
1010  int status = 0; /* Status return */
1011  char* sql = NULL; /* SQL Statement */
1012  int set = 0;
1013  char* now = DtParseDateTimeString("now");
1014 
1015  /* Check datetime in case it came back NULL */
1016  if (now == NULL) {
1017  printf("Couldn't turn \"now\" into a date, quitting...\n");
1018  exit(1);
1019  }
1020 
1021  sql = DusInit("dnsseckeys");
1022  DusSetInt(&sql, "STATE", KSM_STATE_DEAD, set++);
1023  DusSetString(&sql, "DEAD", now, set++);
1024  DusConditionInt(&sql, "KEYPAIR_ID", DQS_COMPARE_EQ, keypair_id, 0);
1025  if (zone_id != -1) {
1026  DqsConditionInt(&sql, "zone_id", DQS_COMPARE_EQ, zone_id, 1);
1027  }
1028  DusEnd(&sql);
1029 
1030  /* Execute the statement */
1031 
1032  status = DbExecuteSqlNoResult(DbHandle(), sql);
1033  DusFree(sql);
1034 
1035  StrFree(now);
1036 
1037  return status;
1038 }
1039 
void DbFreeResult(DB_RESULT result)
#define DB_KEYDATA_ACTIVE
Definition: db_fields.h:62
int zone_id
Definition: ksm.h:115
char ready[KSM_TIME_LENGTH]
Definition: ksm.h:107
char dead[KSM_TIME_LENGTH]
Definition: ksm.h:104
#define DB_KEYDATA_PUBLISH
Definition: db_fields.h:60
#define KSM_TYPE_ZSK
Definition: ksm.h:357
#define StrFree(x)
Definition: string_util.h:66
#define KSM_INVARG
Definition: ksmdef.h:66
int DbFetchRow(DB_RESULT result, DB_ROW *row)
#define KSM_SQLFAIL
Definition: ksmdef.h:67
#define KSM_STATE_DEAD
Definition: ksm.h:370
int KsmKeyCountStillGood(int policy_id, int sm, int bits, int algorithm, int interval, const char *datetime, int *count, int keytype)
Definition: ksm_key.c:732
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
int kskttl
Definition: ksm.h:479
char location[KSM_NAME_LENGTH]
Definition: ksm.h:109
int pub_safety
Definition: ksm.h:482
int KsmKillKey(int keypair_id, int zone_id)
Definition: ksm_key.c:1008
#define DB_KEYDATA_ID
Definition: db_fields.h:57
#define KSM_STATE_READY
Definition: ksm.h:364
int KsmParameterZskTtl(KSM_PARCOLL *collection)
#define KSM_ROLL_DS
Definition: ksm.h:397
int state
Definition: ksm.h:99
int KsmParameterCollection(KSM_PARCOLL *data, int policy_id)
#define KSM_KEYS_NOT_SHARED
Definition: ksm.h:390
void DusFree(char *sql)
Definition: du_string.c:223
DQS_COMPARISON compare
char retire[KSM_TIME_LENGTH]
Definition: ksm.h:108
void DqsConditionKeyword(char **query, const char *field, DQS_COMPARISON compare, const char *value, int index)
Definition: dq_string.c:251
int dsttl
Definition: ksm.h:486
char * DisSpecifyInit(const char *table, const char *cols)
Definition: di_string.c:99
#define DB_KEYDATA_ZONE_ID
Definition: db_fields.h:68
int MsgLog(int status,...)
Definition: message.c:335
int KsmKeyPairCreate(int policy_id, const char *HSMKeyID, int smID, int size, int alg, const char *generate, DB_ID *id)
Definition: ksm_key.c:84
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
int ksklife
Definition: ksm.h:469
int KsmParameterKskTtl(KSM_PARCOLL *collection)
void DusConditionInt(char **query, const char *field, DQS_COMPARISON compare, int value, int clause)
Definition: du_string.c:170
const char * KsmKeywordStateValueToName(int value)
Definition: ksm_keyword.c:242
char * DqsCountInit(const char *table)
Definition: dq_string.c:90
int KsmMarkKeysAsDead(int zone_id)
Definition: ksm_key.c:946
DB_HANDLE DbHandle(void)
int KsmParameterKskPropagationDelay(KSM_PARCOLL *collection)
char * StrStrdup(const char *string)
Definition: string_util.c:124
int KsmKeyPredict(int policy_id, int keytype, int shared_keys, int interval, int *count, int rollover_scheme, int zone_count)
Definition: ksm_key.c:562
void DqsConditionInt(char **query, const char *field, DQS_COMPARISON compare, int value, int index)
Definition: dq_string.c:224
#define DB_KEYDATA_READY
Definition: db_fields.h:61
char * DtParseDateTimeString(const char *string)
Definition: datetime.c:614
#define KSM_STATE_DSPUBLISH
Definition: ksm.h:374
#define DB_KEYDATA_STATE
Definition: db_fields.h:58
int DbLastRowId(DB_HANDLE handle, DB_ID *id)
int KsmKeyInitSql(DB_RESULT *result, const char *sql)
Definition: ksm_key.c:217
unsigned long DB_ID
Definition: database.h:78
#define DB_KEYDATA_FIELDS
Definition: db_fields.h:56
const char * DbErrmsg(DB_HANDLE handle)
void DisAppendString(char **sql, const char *what)
Definition: di_string.c:142
int propdelay
Definition: ksm.h:472
#define DB_KEYDATA_FIXED_DATE
Definition: db_fields.h:69
void DbFreeRow(DB_ROW row)
int KsmParameterPropagationDelay(KSM_PARCOLL *collection)
int KsmKeyCountQueue(int keytype, int *count, int zone_id)
Definition: ksm_key.c:653
#define DB_KEYDATA_GENERATE
Definition: db_fields.h:59
int DbExecuteSql(DB_HANDLE handle, const char *stmt_str, DB_RESULT *result)
int keytype
Definition: ksm.h:100
void DisEnd(char **sql)
Definition: di_string.c:170
int DbStringBuffer(DB_ROW row, int field_index, char *buffer, size_t buflen)
#define KME_SQLFAIL
Definition: kmedef.h:67
int KsmKeyInitId(DB_RESULT *result, DB_ID id)
Definition: ksm_key.c:326
void StrAppend(char **str1, const char *str2)
Definition: string_util2.c:76
int fixedDate
Definition: ksm.h:116
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 KsmKeyInit(DB_RESULT *result, DQS_QUERY_CONDITION *condition)
Definition: ksm_key.c:249
char generate[KSM_TIME_LENGTH]
Definition: ksm.h:105
#define KSM_STATE_RETIRE
Definition: ksm.h:368
#define KSM_STATE_PUBLISH
Definition: ksm.h:362
int DbUnsignedLong(DB_ROW row, int field_index, unsigned long *value)
char * DusInit(const char *table)
Definition: du_string.c:60
int KsmParameterPubSafety(KSM_PARCOLL *collection)
int standbyzsks
Definition: ksm.h:471
DB_ID keypair_id
Definition: ksm.h:98
void DisFree(char *sql)
Definition: di_string.c:191
int KsmDnssecKeyCreate(int zone_id, int keypair_id, int keytype, int state, const char *time, const char *retTime, DB_ID *id)
Definition: ksm_key.c:141
int KsmKeyGetUnallocated(int policy_id, int sm, int bits, int algorithm, int zone_id, int share_keys, int *keypair_id)
Definition: ksm_key.c:870
int kskpropdelay
Definition: ksm.h:480
#define KME_BUFFEROVF
Definition: kmedef.h:48
#define DB_KEYDATA_RETIRE
Definition: db_fields.h:63
#define DB_KEYDATA_KEYTYPE
Definition: db_fields.h:65
int KsmKeyData(DB_ID id, KSM_KEYDATA *data)
Definition: ksm_key.c:498
char publish[KSM_TIME_LENGTH]
Definition: ksm.h:106
int zsklife
Definition: ksm.h:477
#define KSM_STATE_DSSUB
Definition: ksm.h:372
#define KME_UNRCONCOD
Definition: kmedef.h:69
#define KSM_TYPE_KSK
Definition: ksm.h:355
int DbInt(DB_ROW row, int field_index, int *value)
#define DB_KEYDATA_DEAD
Definition: db_fields.h:64
void DisAppendInt(char **sql, int what)
Definition: di_string.c:131
#define DB_KEYDATA_ALGORITHM
Definition: db_fields.h:66
#define KSM_STATE_DSREADY
Definition: ksm.h:376
int standbyksks
Definition: ksm.h:470
#define KME_UNKEYTYPE
Definition: kmedef.h:68
int KsmKey(DB_RESULT result, KSM_KEYDATA *data)
Definition: ksm_key.c:366
#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
void DqsEnd(char **query)
Definition: dq_string.c:299
int DbExecuteSqlNoResult(DB_HANDLE handle, const char *stmt_str)
void KsmKeyEnd(DB_RESULT result)
Definition: ksm_key.c:469
#define DB_KEYDATA_LOCATION
Definition: db_fields.h:67
char active[KSM_TIME_LENGTH]
Definition: ksm.h:103