OpenDNSSEC-enforcer  1.3.15
ksm_import.c
Go to the documentation of this file.
1 /*
2  * $Id: ksm_import.c 5838 2011-11-08 14:28:05Z sion $
3  *
4  * Copyright (c) 2008-2009 Nominet UK. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
29 /*
30  * ksm_import.c - Import/update configuration data in kasp database
31  */
32 
33 #include <assert.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <time.h>
38 
39 #include "ksm/database.h"
40 #include "ksm/database_statement.h"
41 #include "ksm/datetime.h"
42 #include "ksm/db_fields.h"
43 #include "ksm/debug.h"
44 #include "ksm/ksmdef.h"
45 #include "ksm/ksm.h"
46 #include "ksm/ksm_internal.h"
47 #include "ksm/message.h"
48 #include "ksm/string_util.h"
49 #include "ksm/string_util2.h"
50 
51 /*+
52  * KsmImportRepository - Insert or update a repository
53  *
54  *
55  * Arguments:
56  *
57  * const char* repo_name
58  * Name of the repository
59  *
60  * const char* repo_capacity
61  * Capacity for that repository
62  *
63  * int require_backup
64  * flag to indicate if keys in this repo need to be backed up before they can be used
65  *
66  * Returns:
67  * int
68  * Status return. 0 on success.
69  * -1 if an unexpected count value was returned
70 -*/
71 
72 int KsmImportRepository(const char* repo_name, const char* repo_capacity, int require_backup)
73 {
74  char* sql = NULL; /* SQL query */
75  int status = 0; /* Status return */
76  int count = 0; /* Do we already have a repository with this name? */
77 
78  /* check the main argument (capacity may be NULL) */
79  if (repo_name == NULL) {
80  return MsgLog(KSM_INVARG, "NULL repository name");
81  }
82 
83  /*
84  * First see if this repository exists
85  */
87  DqsConditionString(&sql, "NAME", DQS_COMPARE_EQ, repo_name, 0);
88  DqsEnd(&sql);
89 
90  /* Execute query and free up the query string */
91  status = DbIntQuery(DbHandle(), &count, sql);
92  DqsFree(sql);
93 
94  if (status != 0)
95  {
96  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
97  return status;
98  }
99 
100  /* If the count was 0 then we do an insert, otherwise we do an update */
101  if (count == 0)
102  {
103  sql = DisSpecifyInit(DB_SECURITY_MODULE_TABLE, "name, capacity, requirebackup");
104  DisAppendString(&sql, repo_name);
105  DisAppendString(&sql, repo_capacity);
106  DisAppendInt(&sql, require_backup);
107  DisEnd(&sql);
108 
109  status = DbExecuteSqlNoResult(DbHandle(), sql);
110  DisFree(sql);
111  }
112  else if (count == 1)
113  {
115  DusSetString(&sql, "capacity", repo_capacity, 0);
116  DusSetInt(&sql, "requirebackup", require_backup, 1);
117  DusConditionString(&sql, "name", DQS_COMPARE_EQ, repo_name, 0);
118  DusEnd(&sql);
119 
120  status = DbExecuteSqlNoResult(DbHandle(), sql);
121  DusFree(sql);
122  }
123  else
124  {
125  return -1;
126  }
127 
128  return status;
129 }
130 
131 /*+
132  * KsmImportPolicy - Insert a policy (will not be called if policy exists, unlike above
133  *
134  *
135  * Arguments:
136  *
137  * const char* policy_name
138  * Name of the policy
139  *
140  * const char* policy_description
141  * Description for that policy
142  *
143  * Returns:
144  * int
145  * Status return. 0 on success.
146  * -1 if an unexpected count value was returned
147 -*/
148 
149 int KsmImportPolicy(const char* policy_name, const char* policy_description)
150 {
151  char* sql = NULL; /* SQL query */
152  int status = 0; /* Status return */
153 
154  /* check the main argument (description may be NULL) */
155  if (policy_name == NULL) {
156  return MsgLog(KSM_INVARG, "NULL policy name");
157  }
158 
159  /* Insert policy */
160  sql = DisSpecifyInit("policies", "name, description");
161  DisAppendString(&sql, policy_name);
162  DisAppendString(&sql, policy_description);
163  DisEnd(&sql);
164 
165  status = DbExecuteSqlNoResult(DbHandle(), sql);
166  DisFree(sql);
167 
168  return status;
169 }
170 
171 /*+
172  * KsmImportZone - Insert or update a zone
173  *
174  *
175  * Arguments:
176  *
177  * const char* zone_name
178  * Name of the repository
179  *
180  * int policy_id
181  * Policy for the zone
182  *
183  * int fail_if_exists
184  * Set to 1 if you don't want to update existing zones
185  *
186  * int *new_zone
187  * (returned) indicate if the zone was new to the database
188  *
189  * const char* signconf
190  * Where is the signconf saved
191  *
192  * const char* input
193  * Where is the input file
194  *
195  * const char* output
196  * Where is the output file
197  *
198  * Returns:
199  * int
200  * Status return. 0 on success.
201  * -1 if an unexpected count value was returned
202  * -2 if the zone exists and fail_if_exists == 1
203  * -3 if the zone exists with and without a trailing dot
204 -*/
205 int KsmImportZone(const char* zone_name, int policy_id, int fail_if_exists, int *new_zone, const char* signconf, const char* input, const char* output)
206 {
207  char* sql = NULL; /* SQL query */
208  int status = 0; /* Status return */
209  int count = 0; /* Do we already have a zone with this name? */
210  char* zone_name_td = NULL; /* zone name with td swapped */
211  char in_clause[KSM_SQL_SIZE]; /* in part of where clause */
212 
213  /* check the arguments */
214  if (zone_name == NULL || policy_id == 0) {
215  return MsgLog(KSM_INVARG, "NULL zone name or policy");
216  }
217 
218  /* make copy of zone_name with opposite td to original (unless original is
219  "."; in which case the copy is identical */
220  zone_name_td = StrStrdup(zone_name);
221  if (strlen(zone_name_td) > 1 && zone_name_td[strlen(zone_name_td)-1] == '.') {
222  zone_name_td[strlen(zone_name_td)-1] = '\0';
223  }
224  else if (strlen(zone_name_td) > 1) {
225  StrAppend(&zone_name_td, ".");
226  }
227 
228  snprintf(in_clause, KSM_SQL_SIZE, "(\"%s\",\"%s\")", zone_name, zone_name_td);
229 
230  /*
231  * First see if this zone exists
232  */
234  DqsConditionKeyword(&sql, "NAME", DQS_COMPARE_IN, in_clause, 0);
235  DqsEnd(&sql);
236 
237  /* Execute query and free up the query string */
238  status = DbIntQuery(DbHandle(), &count, sql);
239  DqsFree(sql);
240 
241  if (status != 0)
242  {
243  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
244  return status;
245  }
246 
247  /* If the count was 0 then we do an insert, otherwise we do an update */
248  if (count == 0)
249  {
250  sql = DisSpecifyInit(DB_ZONE_TABLE, "name, policy_id, signconf, input, output");
251  DisAppendString(&sql, zone_name);
252  DisAppendInt(&sql, policy_id);
253  DisAppendString(&sql, signconf);
254  DisAppendString(&sql, input);
255  DisAppendString(&sql, output);
256  DisEnd(&sql);
257 
258  status = DbExecuteSqlNoResult(DbHandle(), sql);
259  DisFree(sql);
260 
261  *new_zone = 1;
262  }
263  else if (count == 1)
264  {
265  if (fail_if_exists == 1) {
266  return -2;
267  }
268  sql = DusInit(DB_ZONE_TABLE);
269  DusSetInt(&sql, "policy_id", policy_id, 0);
270  DusSetString(&sql, "signconf", signconf, 1);
271  DusSetString(&sql, "input", input, 2);
272  DusSetString(&sql, "output", output, 3);
273  DusConditionString(&sql, "name", DQS_COMPARE_EQ, zone_name, 0);
274  DusEnd(&sql);
275 
276  status = DbExecuteSqlNoResult(DbHandle(), sql);
277  DusFree(sql);
278 
279  *new_zone = 0;
280  }
281  else if (count == 2)
282  {
283  return -3;
284  }
285  else
286  {
287  return -1;
288  }
289 
290  return status;
291 }
292 
293 /*+
294  * KsmImportAudit - Import contents of the Audit tag for a policy, which will already exist
295  *
296  *
297  * Arguments:
298  *
299  * int policy_id
300  * ID of the policy
301  *
302  * const char* audit_contents
303  * Audit information for that policy
304  *
305  * Returns:
306  * int
307  * Status return. 0 on success.
308  * -1 if an unexpected count value was returned
309 -*/
310 
311 int KsmImportAudit(int policy_id, const char* audit_contents)
312 {
313  char* sql = NULL; /* SQL query */
314  int status = 0; /* Status return */
315 
316  /* Insert policy */
317  sql = DusInit("policies");
318  DusSetString(&sql, "audit", audit_contents, 0);
319  DusConditionInt(&sql, "id", DQS_COMPARE_EQ, policy_id, 0);
320  DusEnd(&sql);
321 
322  status = DbExecuteSqlNoResult(DbHandle(), sql);
323  DusFree(sql);
324 
325  return status;
326 }
327 
328 /*+
329  * KsmImportKeyPair - Create Entry in the KeyPairs table for an existing key
330  *
331  * Description:
332  * Creates a key in the database. If the retire time is set then it is marked as
333  * fixed (I.e. it will not be changed to fit the policy timings.)
334  *
335  * Arguments:
336  * policy_id
337  * policy that the key is created for
338  * HSMKeyID
339  * ID the key is refered to in the HSM
340  * smID
341  * security module ID
342  * size
343  * size of key
344  * alg
345  * algorithm used
346  * state
347  * state to set key to
348  * time
349  * timestamp of entry into state given
350  * fixDate
351  * set to 1 if the retire date should be fixed
352  *
353  * DB_ID* id (returned)
354  * ID of the created entry. This will be undefined on error.
355  *
356  * Returns:
357  * int
358  * Status return. 0=> Success, non-zero => error.
359 -*/
360 int KsmImportKeyPair(int policy_id, const char* HSMKeyID, int smID, int size, int alg, int state, const char* time, int fixDate, DB_ID* id)
361 {
362  unsigned long rowid; /* ID of last inserted row */
363  int status = 0; /* Status return */
364  char* sql = NULL; /* SQL Statement */
365  char* columns = NULL; /* what columns are we setting */
366 
367  /* Check arguments */
368  if (id == NULL) {
369  return MsgLog(KSM_INVARG, "NULL id");
370  }
371 
372  StrAppend(&columns, "policy_id, HSMkey_id, securitymodule_id, size, algorithm");
373  if (state == KSM_STATE_GENERATE) {
374  StrAppend(&columns, ", ");
375  StrAppend(&columns, KsmKeywordStateValueToName(state));
376  }
377  if (state == KSM_STATE_ACTIVE && fixDate == 1) {
378  StrAppend(&columns, ", fixedDate");
379  }
380 
381  sql = DisSpecifyInit("keypairs", columns);
382  DisAppendInt(&sql, policy_id);
383  DisAppendString(&sql, HSMKeyID);
384  DisAppendInt(&sql, smID);
385  DisAppendInt(&sql, size);
386  DisAppendInt(&sql, alg);
387  if (state == KSM_STATE_GENERATE) {
388  DisAppendString(&sql, time);
389  }
390  if (state == KSM_STATE_ACTIVE && fixDate == 1) {
391  DisAppendInt(&sql, fixDate);
392  }
393  DisEnd(&sql);
394 
395  /* Execute the statement */
396 
397  status = DbExecuteSqlNoResult(DbHandle(), sql);
398  DisFree(sql);
399  StrFree(columns);
400 
401  if (status == 0) {
402 
403  /* Succcess, get the ID of the inserted record */
404 
405  status = DbLastRowId(DbHandle(), &rowid);
406  if (status == 0) {
407  *id = (DB_ID) rowid;
408  }
409  }
410 
411  return status;
412 }
413 
414 int KsmSmIdFromName(const char* name, int *id)
415 {
416  char* sql = NULL; /* SQL query */
417  int status = 0; /* Status return */
418 
419  /* check the argument */
420  if (name == NULL) {
421  return MsgLog(KSM_INVARG, "NULL name");
422  }
423 
424  /* Construct the query */
425 
427  DqsConditionString(&sql, "name", DQS_COMPARE_EQ, name, 0);
428  DqsEnd(&sql);
429 
430  /* Execute query and free up the query string */
431  status = DbIntQuery(DbHandle(), id, sql);
432  DqsFree(sql);
433 
434  if (status != 0)
435  {
436  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
437  return status;
438  }
439 
440  return status;
441 }
442 
443 int KsmSerialIdFromName(const char* name, int *id)
444 {
445  char* sql = NULL; /* SQL query */
446  int status = 0; /* Status return */
447 
448  /* check the argument */
449  if (name == NULL) {
450  return MsgLog(KSM_INVARG, "NULL name");
451  }
452 
453  /* Construct the query */
454 
455  sql = DqsSpecifyInit("serialmodes","id");
456  DqsConditionString(&sql, "name", DQS_COMPARE_EQ, name, 0);
457  DqsEnd(&sql);
458 
459  /* Execute query and free up the query string */
460  status = DbIntQuery(DbHandle(), id, sql);
461  DqsFree(sql);
462 
463  if (status != 0)
464  {
465  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
466  return status;
467  }
468 
469  return status;
470 }
471 
472 /*+
473  * KsmPolicyIdFromName - Given a policy name return the id
474  *
475  *
476  * Arguments:
477  *
478  * Name of the policy.
479  *
480  *
481  * Returns:
482  * int
483  * 0 Success, value found
484  * Other Error
485 -*/
486 int KsmPolicyIdFromName(const char* name, int *id)
487 {
488  char* sql = NULL; /* SQL query */
489  int status = 0; /* Status return */
490 
491  /* check the argument */
492  if (name == NULL) {
493  return MsgLog(KSM_INVARG, "NULL name");
494  }
495 
496  /* Construct the query */
497 
498  sql = DqsSpecifyInit("policies","id");
499  DqsConditionString(&sql, "name", DQS_COMPARE_EQ, name, 0);
500  DqsEnd(&sql);
501 
502  /* Execute query and free up the query string */
503  status = DbIntQuery(DbHandle(), id, sql);
504  DqsFree(sql);
505 
506  if (status != 0)
507  {
508  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
509  return status;
510  }
511 
512  return status;
513 }
514 
515 /*+
516  * KsmMarkPreBackup - Mark a backup as having been prepared
517  *
518  *
519  * Arguments:
520  *
521  * int repo_id
522  * ID of the repository (-1 for all)
523  *
524  * const char* datetime
525  * When the pre backup was done
526  *
527  * Returns:
528  * int
529  * Status return. 0 on success.
530  * other on fail
531  */
532 
533 int KsmMarkPreBackup(int repo_id, const char* datetime)
534 {
535  char* sql = NULL; /* SQL query */
536  int status = 0; /* Status return */
537  int count = -1; /* How many keys get marked */
538 
539  /* Count how many we will mark */
540  sql = DqsCountInit("keypairs");
541  if (repo_id != -1) {
542  DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 0);
543  StrAppend(&sql, " and pre_backup is null");
544  } else {
545  StrAppend(&sql, " where pre_backup is null");
546  }
547  DqsEnd(&sql);
548 
549  /* Execute query and free up the query string */
550  status = DbIntQuery(DbHandle(), &count, sql);
551  DqsFree(sql);
552 
553  if (status != 0)
554  {
555  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
556  return status;
557  }
558 
559  if (count == 0) {
560  /* No work to do */
561  return -1;
562  }
563 
564  /* Update rows */
565  sql = DusInit("keypairs");
566  DusSetString(&sql, "PRE_BACKUP", datetime, 0);
567  if (repo_id != -1) {
568  DusConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 0);
569  StrAppend(&sql, " and pre_backup is null");
570  } else {
571  StrAppend(&sql, " where pre_backup is null");
572  }
573  DusEnd(&sql);
574 
575  status = DbExecuteSqlNoResult(DbHandle(), sql);
576  DusFree(sql);
577 
578  return status;
579 }
580 
581 /*+
582  * KsmRollbackPreBackup - Rollback a backup prepare step
583  *
584  *
585  * Arguments:
586  *
587  * int repo_id
588  * ID of the repository (-1 for all)
589  *
590  * Returns:
591  * int
592  * Status return. 0 on success.
593  * other on fail
594  */
595 
596 int KsmRollbackMarkPreBackup(int repo_id)
597 {
598  char* sql = NULL; /* SQL query */
599  int status = 0; /* Status return */
600  int count = -1; /* How many keys get marked */
601 
602  /* Count how many we will mark */
603  sql = DqsCountInit("keypairs");
604  if (repo_id != -1) {
605  DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 0);
606  StrAppend(&sql, " and pre_backup is not null");
607  StrAppend(&sql, " and backup is null");
608  } else {
609  StrAppend(&sql, " where pre_backup is not null");
610  StrAppend(&sql, " and backup is null");
611  }
612  DqsEnd(&sql);
613 
614  /* Execute query and free up the query string */
615  status = DbIntQuery(DbHandle(), &count, sql);
616  DqsFree(sql);
617 
618  if (status != 0)
619  {
620  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
621  return status;
622  }
623 
624  if (count == 0) {
625  /* No work to do */
626  return -1;
627  }
628 
629  /* Update rows */
630  sql = DusInit("keypairs");
631  DusSetString(&sql, "PRE_BACKUP", NULL, 0);
632  if (repo_id != -1) {
633  DusConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 0);
634  StrAppend(&sql, " and pre_backup is not null");
635  StrAppend(&sql, " and backup is null");
636  } else {
637  StrAppend(&sql, " where pre_backup is null");
638  StrAppend(&sql, " and backup is null");
639  }
640  DusEnd(&sql);
641 
642  status = DbExecuteSqlNoResult(DbHandle(), sql);
643  DusFree(sql);
644 
645  return status;
646 }
647 
648 /*+
649  * KsmMarkBackup - Mark a backup as having been done
650  *
651  *
652  * Arguments:
653  *
654  * int repo_id
655  * ID of the repository (-1 for all)
656  *
657  * const char* datetime
658  * When the backup was done
659  *
660  * Returns:
661  * int
662  * Status return. 0 on success.
663  * other on fail
664  */
665 
666 int KsmMarkBackup(int repo_id, const char* datetime)
667 {
668  char* sql = NULL; /* SQL query */
669  int status = 0; /* Status return */
670  int count = -1; /* How many keys get marked */
671 
672  /* Count how many we will mark */
673  sql = DqsCountInit("keypairs");
674  if (repo_id != -1) {
675  DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 0);
676  StrAppend(&sql, " and pre_backup is not null");
677  StrAppend(&sql, " and backup is null");
678  } else {
679  StrAppend(&sql, " where pre_backup is not null");
680  StrAppend(&sql, " and backup is null");
681  }
682  DqsEnd(&sql);
683 
684  /* Execute query and free up the query string */
685  status = DbIntQuery(DbHandle(), &count, sql);
686  DqsFree(sql);
687 
688  if (status != 0)
689  {
690  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
691  return status;
692  }
693 
694  if (count == 0) {
695  /* No work to do */
696  return -1;
697  }
698 
699  /* Update rows */
700  sql = DusInit("keypairs");
701  DusSetString(&sql, "BACKUP", datetime, 0);
702  if (repo_id != -1) {
703  DusConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 0);
704  StrAppend(&sql, " and backup is null");
705  StrAppend(&sql, " and pre_backup is not null");
706  } else {
707  StrAppend(&sql, " where backup is null");
708  StrAppend(&sql, " and pre_backup is not null");
709  }
710  DusEnd(&sql);
711 
712  status = DbExecuteSqlNoResult(DbHandle(), sql);
713  DusFree(sql);
714 
715  return status;
716 }
717 
718 /*+
719  * KsmCheckHSMkeyID - Checks if the cka_id exists in the hsm specified
720  *
721  *
722  * Arguments:
723  *
724  * int repo_id
725  * ID of the repository (-1 for all)
726  *
727  * const char* cka_id
728  * ID to look for
729  *
730  * int *exists
731  * Flag to say if the ID exists
732  *
733  * Returns:
734  * int
735  * Status return. 0 on success.
736  * -1 if an unexpected count value was returned
737 -*/
738 
739 int KsmCheckHSMkeyID(int repo_id, const char* cka_id, int *exists)
740 {
741  char* sql = NULL; /* SQL query */
742  int status = 0; /* Status return */
743  int count = 0; /* Do we already have a key with this ID? */
744 
745  /* check the arguments */
746  if (cka_id == NULL) {
747  return MsgLog(KSM_INVARG, "NULL cka_id");
748  }
749 
750  /*
751  * Set up the count
752  */
753  sql = DqsCountInit("keypairs");
754  DqsConditionString(&sql, "HSMkey_id", DQS_COMPARE_EQ, cka_id, 0);
755  if (repo_id != -1) {
756  DqsConditionInt(&sql, "securitymodule_id", DQS_COMPARE_EQ, repo_id, 1);
757  }
758  DqsEnd(&sql);
759 
760  /* Execute query and free up the query string */
761  status = DbIntQuery(DbHandle(), &count, sql);
762  DqsFree(sql);
763 
764  if (status != 0)
765  {
766  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
767  return status;
768  }
769 
770  if (count > 0) {
771  *exists = 1;
772  }
773  else {
774  *exists = 0;
775  }
776 
777  return 0;
778 }
779