OpenDNSSEC-enforcer  1.4.5
ksm_policy.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_policy.c - Manipulation of Policy Information
29  */
30 
31 #include <assert.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <time.h>
36 
37 #include "ksm/database.h"
38 #include "ksm/database_statement.h"
39 #include "ksm/datetime.h"
40 #include "ksm/db_fields.h"
41 #include "ksm/debug.h"
42 #include "ksm/ksmdef.h"
43 #include "ksm/kmedef.h"
44 #include "ksm/ksm.h"
45 #include "ksm/ksm_internal.h"
46 #include "ksm/message.h"
47 #include "ksm/string_util.h"
48 
49 /*+
50  * KsmPolicyInit - Query for Policy Information
51  *
52  *
53  * Arguments:
54  * DB_RESULT* result
55  * Pointer to a handle to be used for information retrieval. Will
56  * be NULL on error.
57  *
58  * const char* name
59  * Name of the parameter to retrieve information on. If NULL, information
60  * on all parameters is retrieved.
61  *
62  * Returns:
63  * int
64  * Status return. 0 on success.
65 -*/
66 
67 int KsmPolicyInit(DB_RESULT* result, const char* name)
68 {
69  int where = 0; /* WHERE clause value */
70  char* sql = NULL; /* SQL query */
71  int status = 0; /* Status return */
72 
73  /* Construct the query */
74 
75  sql = DqsSpecifyInit("policies","id, name, description, salt");
76  if (name) {
77  DqsConditionString(&sql, "NAME", DQS_COMPARE_EQ, name, where++);
78  }
79  DqsOrderBy(&sql, "id");
80 
81  /* Execute query and free up the query string */
82 
83  status = DbExecuteSql(DbHandle(), sql, result);
84 
85  DqsFree(sql);
86 
87  return status;
88 }
89 
90 /*+
91  * KsmPolicyParametersInit - Query for Policy Information
92  *
93  *
94  * Arguments:
95  * DB_RESULT* result
96  * Pointer to a handle to be used for information retrieval. Will
97  * be NULL on error.
98  *
99  * const char* name
100  * Name of the parameter to retrieve information on. If NULL, information
101  * on all parameters is retrieved.
102  *
103  * Returns:
104  * int
105  * Status return. 0 on success.
106 -*/
107 
108 int KsmPolicyParametersInit(DB_RESULT* result, const char* name)
109 {
110  int where = 0; /* WHERE clause value */
111  char* sql = NULL; /* SQL query */
112  int status = 0; /* Status return */
113 
114  /* Construct the query */
115 
116  sql = DqsSpecifyInit("policies p, parameters_policies x, parameters y, categories c ","y.name, c.name, x.value");
117  DqsConditionKeyword(&sql, "p.id", DQS_COMPARE_EQ, "x.policy_id", where++);
118  DqsConditionKeyword(&sql, "y.id", DQS_COMPARE_EQ, "x.parameter_id", where++);
119  DqsConditionKeyword(&sql, "c.id", DQS_COMPARE_EQ, "y.category_id", where++);
120  if (name) {
121  DqsConditionString(&sql, "p.NAME", DQS_COMPARE_EQ, name, where++);
122  }
123  DqsOrderBy(&sql, "p.NAME");
124 
125  /* Execute query and free up the query string */
126 
127  status = DbExecuteSql(DbHandle(), sql, result);
128 
129  DqsFree(sql);
130 
131  return status;
132 }
133 
134 /*+
135  * KsmPolicyExists - Check Policy Exists
136  *
137  *
138  * Arguments:
139  * const char* name
140  * Name of the parameter.
141  *
142  *
143  * Returns:
144  * int
145  * 0 Success, value found
146  * Other Error, message has been output
147 -*/
148 
149 int KsmPolicyExists(const char* name)
150 {
151  int status; /* Status return */
152  DB_RESULT result; /* Handle converted to a result object */
153  DB_ROW row = NULL; /* Row data */
154 
155  status = KsmPolicyInit(&result, name);
156  if (status == 0) {
157  /* Get the next row from the data */
158  status = DbFetchRow(result, &row);
159  if (status > 0) {
160  /* Error */
161  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
162  }
163  }
164  DbFreeRow(row);
165  DbFreeResult(result);
166  return status;
167 }
168 
169 /*+
170  * KsmPolicy - Return Policy Information
171  *
172  * Arguments:
173  * DB_RESULT result
174  * Handle from KsmParameterInit
175  *
176  * KSM_PARAMETER* data
177  * Data is returned in here.
178  *
179  * Returns:
180  * int
181  * Status return:
182  * 0 success
183  * -1 end of record set reached
184  * non-zero some error occurred and a message has been output.
185  *
186  * If the status is non-zero, the returned data is meaningless.
187 -*/
188 
189 int KsmPolicy(DB_RESULT result, KSM_POLICY* data)
190 {
191  int status = 0; /* Return status */
192  DB_ROW row = NULL; /* Row data */
193 
194  /* check the argument */
195  if (data == NULL) {
196  return MsgLog(KSM_INVARG, "NULL data");
197  }
198 
199  /* Get the next row from the data */
200  status = DbFetchRow(result, &row);
201  if (status == 0) {
202 
203  status = DbInt(row, DB_POLICY_ID, &(data->id));
204  DbStringBuffer(row, DB_POLICY_NAME, data->name, KSM_NAME_LENGTH*sizeof(char));
205  }
206  else if (status == -1) {}
207  /* No rows to return (but no error) */
208  else {
209  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
210  }
211 
212  if (row != NULL) {
213  DbFreeRow(row);
214  }
215 
216  return status;
217 }
218 
219 /*+
220  * KsmPolicyRead - Read Policy
221  *
222  * Description:
223  * Read policy from database in to a struct.
224  *
225  * Arguments:
226  * struct policy_t policy
227  * struct to hold policy information, it needs to have the policy name set
228 -*/
229 
231 {
232  KSM_POLICY_PARAMETER data; /* Parameter information */
233  DB_RESULT result; /* Handle to parameter */
234  int status = 0; /* Status return */
235 
236  /* check the argument */
237  if (policy == NULL) {
238  return MsgLog(KSM_INVARG, "NULL policy");
239  }
240 
241  /* status = KsmPolicyExists(policy->name); */
242  status = KsmPolicySetIdFromName(policy);
243 
244  /* NSEC3PARAM TTL might be null in the database if the policy was imported before the fix
245  * so default to zero */
246  policy->denial->ttl=0;
247 
248  if (status == 0) {
249 
250  status = KsmPolicyParametersInit(&result, policy->name);
251  if (status == 0) {
252  status = KsmPolicyParameter(result, &data);
253  while (status == 0) {
254  if (strncmp(data.category, "enforcer", 8) == 0) {
255 /* if (strncmp(data.name, "keycreate", 9) == 0) policy->enforcer->keycreate=data.value;
256  if (strncmp(data.name, "backup_interval", 15) == 0) policy->enforcer->backup_interval=data.value; */
257  if (strncmp(data.name, "keygeninterval", 14) == 0) policy->enforcer->keygeninterval=data.value;
258  }
259  if (strncmp(data.category, "zone", 4) == 0) {
260  if (strncmp(data.name, "propagationdelay", 16) == 0) policy->signer->propdelay=data.value;
261  if (strncmp(data.name, "min", 3) == 0) policy->signer->soamin=data.value;
262  if (strncmp(data.name, "ttl", 2) == 0) policy->signer->soattl=data.value;
263  if (strncmp(data.name, "serial", 6) == 0) policy->signer->serial=data.value;
264  if (strncmp(data.name, "propagationdelay", 16) == 0) policy->zone->propdelay=data.value;
265  if (strncmp(data.name, "min", 3) == 0) policy->zone->soa_min=data.value;
266  if (strncmp(data.name, "ttl", 3) == 0) policy->zone->soa_ttl=data.value;
267  if (strncmp(data.name, "serial", 6) == 0) policy->zone->serial=data.value;
268  }
269  if (strncmp(data.category, "parent", 6) == 0) {
270  if (strncmp(data.name, "propagationdelay", 16) == 0) policy->parent->propdelay=data.value;
271  if (strncmp(data.name, "min", 3) == 0) policy->parent->soa_min=data.value;
272  /* Resolve ambiguity in comparing names for these two parameters. With the old code if
273  ttlds came out the DB second, it would overwrite the value for ttl! */
274  if (strncmp(data.name, "ttlds", 5) == 0) {
275  policy->parent->ds_ttl=data.value;
276  }
277  else if (strncmp(data.name, "ttl", 3) == 0) {
278  policy->parent->soa_ttl=data.value;
279  }
280  }
281  if (strncmp(data.category, "signature", 9) == 0) {
282  if (strncmp(data.name, "jitter", 6) == 0) policy->signer->jitter=data.value;
283  if (strncmp(data.name, "refresh", 7) == 0) policy->signer->refresh=data.value;
284  if (strncmp(data.name, "clockskew", 9) == 0) policy->signature->clockskew=data.value;
285  if (strncmp(data.name, "resign", 6) == 0) policy->signature->resign=data.value;
286  if (strncmp(data.name, "valdefault", 10) == 0) policy->signature->valdefault=data.value;
287  if (strncmp(data.name, "valdenial", 9) == 0) policy->signature->valdenial=data.value;
288  }
289  if (strncmp(data.category, "denial", 6) == 0) {
290  if (strncmp(data.name, "version", 7) == 0) policy->denial->version=data.value;
291  if (strncmp(data.name, "resalt", 6) == 0) policy->denial->resalt=data.value;
292  if (strncmp(data.name, "alg", 3) == 0) policy->denial->algorithm=data.value;
293  if (strncmp(data.name, "iteration", 9) == 0) policy->denial->iteration=data.value;
294  if (strncmp(data.name, "optout", 6) == 0) policy->denial->optout=data.value;
295  if (strncmp(data.name, "ttl",3) == 0) policy->denial->ttl=data.value;
296  if (strncmp(data.name, "saltlength",10) == 0) policy->denial->saltlength=data.value;
297  }
298  if (strncmp(data.category, "zsk", 3) == 0) {
299  if (strncmp(data.name, "alg",3) == 0) policy->zsk->algorithm=data.value;
300  if (strncmp(data.name, "lifetime",8) == 0) policy->zsk->lifetime=data.value;
301  if (strncmp(data.name, "repository",10) == 0) policy->zsk->sm=data.value;
302  if (strncmp(data.name, "overlap",7) == 0) policy->zsk->overlap=data.value;
303  if (strncmp(data.name, "bits",4) == 0) policy->zsk->bits=data.value;
304  if (strncmp(data.name, "standby",7) == 0) policy->zsk->standby_keys=data.value;
305  if (strncmp(data.name, "manual_rollover",15) == 0) policy->zsk->manual_rollover=data.value;
306  }
307  if (strncmp(data.category, "ksk", 3) == 0) {
308  if (strncmp(data.name, "alg",3) == 0) policy->ksk->algorithm=data.value;
309  if (strncmp(data.name, "lifetime",8) == 0) policy->ksk->lifetime=data.value;
310  if (strncmp(data.name, "repository",10) == 0) policy->ksk->sm=data.value;
311  if (strncmp(data.name, "overlap",7) == 0) policy->ksk->overlap=data.value;
312  if (strncmp(data.name, "rfc5011",7) == 0) policy->ksk->rfc5011=data.value;
313  if (strncmp(data.name, "bits",4) == 0) policy->ksk->bits=data.value;
314  if (strncmp(data.name, "standby",7) == 0) policy->ksk->standby_keys=data.value;
315  if (strncmp(data.name, "manual_rollover",15) == 0) policy->ksk->manual_rollover=data.value;
316  if (strncmp(data.name, "rollover_scheme",15) == 0) policy->ksk->rollover_scheme=data.value;
317  }
318  if (strncmp(data.category, "keys", 4) == 0) {
319  if (strncmp(data.name, "ttl",3) == 0) policy->ksk->ttl=data.value;
320  if (strncmp(data.name, "ttl",3) == 0) policy->zsk->ttl=data.value;
321  if (strncmp(data.name, "zones_share_keys",16) == 0) policy->shared_keys=data.value;
322  if (strncmp(data.name, "ttl",3) == 0) policy->keys->ttl=data.value;
323  if (strncmp(data.name, "zones_share_keys",16) == 0) policy->keys->share_keys=data.value;
324  if (strncmp(data.name, "retiresafety",12) == 0) policy->keys->retire_safety=data.value;
325  if (strncmp(data.name, "publishsafety",13) == 0) policy->keys->publish_safety=data.value;
326  if (strncmp(data.name, "purge",5) == 0) policy->keys->purge=data.value;
327  }
328  /* Ignore any unknown parameters */
329 
330  status = KsmPolicyParameter(result, &data);
331  }
332 
333  /* All done, so tidy up */
334 
335  KsmParameterEnd(result);
336  }
337  } else {
338  return status;
339  }
340 
341  /* convert security module ids into names, capacities and requirebackup flags */
342  status = KsmPolicyPopulateSMFromIds(policy);
343 
344  return status;
345 }
346 
347 /*+
348  * KsmPolicyParameter - Return PolicyParameter Information
349  *
350  * Description:
351  * Returns information about the next key in the result set.
352  *
353  * Arguments:
354  * DB_RESULT result
355  * Handle from KsmParameterInit
356  *
357  * KSM_PARAMETER* data
358  * Data is returned in here.
359  *
360  * Returns:
361  * int
362  * Status return:
363  * 0 success
364  * -1 end of record set reached
365  * non-zero some error occurred and a message has been output.
366  *
367  * If the status is non-zero, the returned data is meaningless.
368 -*/
369 
371 {
372  int status = 0; /* Return status */
373  DB_ROW row = NULL; /* Row data */
374 
375  /* check the argument */
376  if (data == NULL) {
377  return MsgLog(KSM_INVARG, "NULL data");
378  }
379 
380  /* Get the next row from the data */
381  status = DbFetchRow(result, &row);
382 
383  if (status == 0) {
384 
385  /* Now copy the results into the output data */
386 
387  memset(data, 0, sizeof(KSM_POLICY_PARAMETER));
389  sizeof(data->name));
391  sizeof(data->category));
392  status = DbInt(row, DB_POLICY_PARAMETER_VALUE, &(data->value));
393  }
394  else if (status == -1) {}
395  /* No rows to return (but no error) */
396  else {
397  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
398  }
399 
400  if (row != NULL) {
401  DbFreeRow(row);
402  }
403 
404  return status;
405 }
406 
407 /*+
408  * KsmPolicyReadFromId - Read Policy given just the id
409  *
410  * Description:
411  * Read policy from database in to a struct.
412  *
413  * Arguments:
414  * struct policy_t policy
415  * struct to hold policy information should have id populated
416 -*/
417 
419 {
420  int status = KsmPolicyNameFromId(policy);
421 
422  if (status != 0)
423  {
424  return status;
425  }
426 
427  return KsmPolicyRead(policy);
428 
429 }
430 
432 {
433  int where = 0; /* WHERE clause value */
434  char* sql = NULL; /* SQL query */
435  DB_RESULT result; /* Handle converted to a result object */
436  DB_ROW row = NULL; /* Row data */
437  int status = 0; /* Status return */
438 
439  /* check the argument */
440  if (policy == NULL) {
441  return MsgLog(KSM_INVARG, "NULL policy");
442  }
443 
444  /* Construct the query */
445 
446  sql = DqsSpecifyInit("policies","id, name");
447  DqsConditionInt(&sql, "ID", DQS_COMPARE_EQ, policy->id, where++);
448  DqsOrderBy(&sql, "id");
449 
450  /* Execute query and free up the query string */
451  status = DbExecuteSql(DbHandle(), sql, &result);
452  DqsFree(sql);
453 
454  if (status != 0)
455  {
456  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
457  DbFreeResult(result);
458  return status;
459  }
460 
461  /* Get the next row from the data */
462  status = DbFetchRow(result, &row);
463  if (status == 0) {
464  DbStringBuffer(row, DB_POLICY_NAME, policy->name, KSM_NAME_LENGTH*sizeof(char));
465  }
466  else if (status == -1) {}
467  /* No rows to return (but no error) */
468  else {
469  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
470  }
471 
472  DbFreeRow(row);
473  DbFreeResult(result);
474  return status;
475 }
476 
477 /*+
478  * KsmPolicyUpdateSalt
479  *
480  * Description:
481  * Given a policy see if the salt needs updating (based on denial->resalt).
482  * If it is out of date then generate a new salt and write it to the struct.
483  * Also update the database with the new value and timestamp.
484  *
485  * Arguments:
486  * struct policy_t policy
487  * struct which holds the current policy information should have been populated
488  *
489  * Returns:
490  * int
491  * Status return:
492  * 0 success
493  * non-zero some error occurred and a message has been output.
494  * -1 no policy found
495  * -2 an error working out time difference between stamp and now
496  *
497 -*/
498 
500 {
501  /* First work out what the current salt is and when it was created */
502  int where = 0; /* WHERE clause value */
503  char* sql = NULL; /* SQL query */
504  DB_RESULT result; /* Handle converted to a result object */
505  DB_ROW row = NULL; /* Row data */
506  int status = 0; /* Status return */
507  char* datetime_now = DtParseDateTimeString("now"); /* where are we in time */
508  int time_diff; /* how many second have elapsed */
509  char* salt; /* This will be the salt that we create */
510  char buffer[KSM_SQL_SIZE]; /* update statement for salt_stamp */
511  unsigned int nchar; /* Number of characters converted */
512  int i = 0; /* a counter */
513  char* hex_chars = "0123456789abcdef"; /* for "manual" random string */
514 
515  /* check the argument */
516  if (policy == NULL) {
517  MsgLog(KSM_INVARG, "NULL policy");
518  StrFree(datetime_now);
519  return -1;
520  }
521 
522  /* Check datetime in case it came back NULL */
523  if (datetime_now == NULL) {
524  printf("Couldn't turn \"now\" into a date, quitting...\n");
525  exit(1);
526  }
527 
528  /* Construct the query */
529 
530  sql = DqsSpecifyInit("policies","id, salt, salt_stamp");
531  DqsConditionInt(&sql, "ID", DQS_COMPARE_EQ, policy->id, where++);
532  DqsOrderBy(&sql, "id");
533 
534  /* Execute query and free up the query string */
535  status = DbExecuteSql(DbHandle(), sql, &result);
536  DqsFree(sql);
537 
538  if (status != 0)
539  {
540  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
541  StrFree(datetime_now);
542  return status;
543  }
544 
545  /* Get the next row from the data */
546  status = DbFetchRow(result, &row);
547  if (status == 0) {
548  status = DbStringBuffer(row, DB_POLICY_SALT, policy->denial->salt, KSM_SALT_LENGTH*sizeof(char));
549  if (status == 0) {
550  status = DbStringBuffer(row, DB_POLICY_SALT_STAMP, policy->denial->salt_stamp, KSM_TIME_LENGTH*sizeof(char));
551  }
552 
553  if (status != 0) {
554  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
555  DbFreeResult(result);
556  DbFreeRow(row);
557  StrFree(datetime_now);
558  return status;
559  }
560  }
561  else if (status == -1) {
562  /* No rows to return (but no error), policy_id doesn't exist? */
563  DbFreeResult(result);
564  DbFreeRow(row);
565  StrFree(datetime_now);
566  return -1;
567  }
568  else {
569  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
570 
571  DbFreeResult(result);
572  DbFreeRow(row);
573  StrFree(datetime_now);
574  return status;
575  }
576 
577  DbFreeResult(result);
578  DbFreeRow(row);
579 
580  /* Now see if this needs to be updated; if the stamp is null then assume it does */
581  if (policy->denial->salt_stamp[0] == '\0') {
582  time_diff = -1;
583  } else {
584  status = DtDateDiff(datetime_now, policy->denial->salt_stamp, &time_diff);
585  }
586 
587  if (status == 0) {
588  if (policy->denial->resalt > time_diff && time_diff != -1 && policy->denial->salt[0] != '\0') {
589  /* current salt is fine */
590  StrFree(datetime_now);
591  return status;
592  } else {
593  /* salt needs updating, or is null */
594  salt = (char *)calloc(KSM_SALT_LENGTH, sizeof(char));
595  if (salt == NULL) {
596  MsgLog(KSM_INVARG, "Could not allocate memory for salt");
597  StrFree(datetime_now);
598  exit(1);
599  }
600 
601 #ifdef HAVE_ARC4RANDOM
602  for (i = 0; i < 2*(policy->denial->saltlength); i++) {
603  salt[i] = hex_chars[arc4random()%strlen(hex_chars)];
604  }
605 #else
606  srand( time(NULL) );
607  for (i = 0; i < 2*(policy->denial->saltlength); i++) {
608  salt[i] = hex_chars[rand()%strlen(hex_chars)];
609  }
610 #endif
611 
612  if (status != 0) {
613  StrFree(datetime_now);
614  StrFree(salt);
615  return status;
616  }
617  StrStrncpy(policy->denial->salt, salt, KSM_SALT_LENGTH);
618  StrStrncpy(policy->denial->salt_stamp, datetime_now, KSM_TIME_LENGTH);
619 
620  StrFree(salt);
621 
622  /* write these back to the database */
623 #ifdef USE_MYSQL
624  nchar = snprintf(buffer, sizeof(buffer),
625  "UPDATE policies SET salt = '%s', salt_stamp = '%s' WHERE ID = %lu",
626  policy->denial->salt, policy->denial->salt_stamp, (unsigned long) policy->id);
627 #else
628  nchar = snprintf(buffer, sizeof(buffer),
629  "UPDATE policies SET salt = '%s', salt_stamp = DATETIME('%s') WHERE ID = %lu",
630  policy->denial->salt, policy->denial->salt_stamp, (unsigned long) policy->id);
631 #endif /* USE_MYSQL */
632  if (nchar < sizeof(buffer)) {
633  /* All OK, execute the statement */
634 
635  status = DbExecuteSqlNoResult(DbHandle(), buffer);
636  }
637  else {
638  /* Unable to create update statement */
639 
640  status = MsgLog(KME_BUFFEROVF, "KsmPolicy");
641  }
642 
643  StrFree(datetime_now);
644  return status;
645  }
646  } else {
647  MsgLog(KSM_INVARG, "Could not calculate DateDiff");
648  StrFree(datetime_now);
649  return -2;
650  }
651 
652  StrFree(datetime_now);
653  return status;
654 }
655 
656 /*+
657  * KsmPolicyNullSaltStamp
658  *
659  * Description:
660  * Given a policy id set its saltstamp to NULL, this will force a resalt on
661  * the next enforcer run, suitable for when salt length has changed for
662  * instance.
663  *
664  * Arguments:
665  * int policy_id
666  * policy to work on
667  *
668  * Returns:
669  * int
670  * Status return:
671  * 0 success
672  * non-zero some error occurred and a message has been output.
673  * -1 no policy found
674  *
675 -*/
676 
677 int KsmPolicyNullSaltStamp(int policy_id)
678 {
679  char buffer[KSM_SQL_SIZE]; /* update statement for salt_stamp */
680  unsigned int nchar; /* Number of characters converted */
681  int status = 0;
682 
683  /* check the argument */
684  if (policy_id < 1) {
685  MsgLog(KSM_INVARG, "Negative or zero policy_id");
686  return -1;
687  }
688 
689  nchar = snprintf(buffer, sizeof(buffer),
690  "UPDATE policies SET salt_stamp = NULL WHERE ID = %lu",
691  (unsigned long) policy_id);
692 
693  if (nchar < sizeof(buffer)) {
694  /* All OK, execute the statement */
695 
696  status = DbExecuteSqlNoResult(DbHandle(), buffer);
697  }
698  else {
699  /* Unable to create update statement */
700 
701  status = MsgLog(KME_BUFFEROVF, "KsmPolicy");
702  }
703 
704  return status;
705 }
706 
707 
708 /* Populate security module information for a structure that has the sm_id fields filled in */
709 
711 {
712  int where = 0; /* WHERE clause value */
713  char* sql = NULL; /* SQL query */
714  DB_RESULT result; /* Handle converted to a result object */
715  DB_ROW row = NULL; /* Row data */
716  DB_RESULT result2; /* Handle converted to a result object */
717  DB_ROW row2 = NULL; /* Row data */
718  int status = 0; /* Status return */
719 
720  /* check the argument */
721  if (policy == NULL) {
722  return MsgLog(KSM_INVARG, "NULL policy");
723  }
724 
725  /* Construct the query for ksk */
726 
728  DqsConditionInt(&sql, "id", DQS_COMPARE_EQ, policy->ksk->sm, where++);
729 
730  /* Execute query and free up the query string */
731  status = DbExecuteSql(DbHandle(), sql, &result);
732  DqsFree(sql);
733 
734  if (status != 0)
735  {
736  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
737  DbFreeResult(result);
738  return status;
739  }
740 
741  /* Get the next row from the data */
742  status = DbFetchRow(result, &row);
743  if (status == 0) {
744  DbStringBuffer(row, DB_SECURITY_MODULE_NAME, policy->ksk->sm_name, KSM_NAME_LENGTH*sizeof(char));
747  }
748  else if (status == -1) {}
749  /* No rows to return (but no error) */
750  else {
751  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
752  DbFreeResult(result);
753  DbFreeRow(row);
754  return status;
755  }
756 
757  DbFreeResult(result);
758  DbFreeRow(row);
759 
760 
761  /* Construct the query for zsk */
762  where = 0;
763 
765  DqsConditionInt(&sql, "id", DQS_COMPARE_EQ, policy->zsk->sm, where++);
766 
767  /* Execute query and free up the query string */
768  status = DbExecuteSql(DbHandle(), sql, &result2);
769  DqsFree(sql);
770 
771  if (status != 0)
772  {
773  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
774  DbFreeResult(result2);
775  return status;
776  }
777 
778  /* Get the next row from the data */
779  status = DbFetchRow(result2, &row2);
780  if (status == 0) {
781  DbStringBuffer(row2, DB_SECURITY_MODULE_NAME, policy->zsk->sm_name, KSM_NAME_LENGTH*sizeof(char));
784  }
785  else if (status == -1) {}
786  /* No rows to return (but no error) */
787  else {
788  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
789  }
790 
791  DbFreeRow(row2);
792  DbFreeResult(result2);
793  return status;
794 }
795 
796 /*+
797  * KsmPolicySetIdFromName - Given a policy with the name set, fill in the ID
798  *
799  *
800  * Arguments:
801  *
802  * Name of the parameter.
803  *
804  *
805  * Returns:
806  * int
807  * 0 Success, value found
808  * Other Error
809 -*/
810 
812 {
813  int status; /* Status return */
814  DB_RESULT result; /* Handle converted to a result object */
815  DB_ROW row = NULL; /* Row data */
816 
817  if (policy == NULL || policy->name[0] == '\0') {
818  return MsgLog(KSM_INVARG, "NULL policy or name");
819  }
820 
821  status = KsmPolicyInit(&result, policy->name);
822  if (status == 0) {
823  /* Get the next row from the data */
824  status = DbFetchRow(result, &row);
825  if (status == 0) {
826  DbInt(row, DB_POLICY_ID, &policy->id);
828  DbStringBuffer(row, 3, policy->denial->salt, KSM_SALT_LENGTH*sizeof(char));
829  }
830  else if (status == -1) {
831  /* No rows to return (but no error) */
832  }
833  else {
834  /* Error */
835  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
836  }
837 
838  }
839  DbFreeRow(row);
840  DbFreeResult(result);
841  return status;
842 }
843 
844 /*+
845  * KsmPolicyIdFromZoneId
846  *
847  * Arguments:
848  * int zone_id zone id
849  * int* policy_id returned id
850  *
851  * Returns:
852  * int
853  * Status return:
854  * 0 success
855  * -1 no record found
856  * non-zero some error occurred and a message has been output.
857  *
858  * If the status is non-zero, the returned data is meaningless.
859 -*/
860 int KsmPolicyIdFromZoneId(int zone_id, int* policy_id)
861 {
862  int where = 0; /* WHERE clause value */
863  char* sql = NULL; /* SQL query */
864  DB_RESULT result; /* Handle converted to a result object */
865  DB_ROW row = NULL; /* Row data */
866  int status = 0; /* Status return */
867 
868  /* check the argument */
869  if (zone_id == -1) {
870  return MsgLog(KSM_INVARG, "NULL zone name");
871  }
872 
873  /* Construct the query */
874 
875  sql = DqsSpecifyInit("zones","id, policy_id");
876  DqsConditionInt(&sql, "ID", DQS_COMPARE_EQ, zone_id, where++);
877  DqsOrderBy(&sql, "id");
878 
879  /* Execute query and free up the query string */
880  status = DbExecuteSql(DbHandle(), sql, &result);
881  DqsFree(sql);
882 
883  if (status != 0)
884  {
885  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
886  DbFreeResult(result);
887  return status;
888  }
889 
890  /* Get the next row from the data */
891  status = DbFetchRow(result, &row);
892  if (status == 0) {
893  DbInt(row, 1, policy_id);
894  }
895  else if (status == -1) {}
896  /* No rows to return (but no DB error) */
897  else {
898  status = MsgLog(KSM_SQLFAIL, DbErrmsg(DbHandle()));
899  }
900 
901  DbFreeRow(row);
902  DbFreeResult(result);
903  return status;
904 }
905 
906 /*+
907  * KsmPolicyUpdateDesc - Update a policy description
908  *
909  * Arguments:
910  *
911  * int policy_id
912  * id of the policy
913  *
914  * const char* policy_description
915  * Description for that policy
916  *
917  * Returns:
918  * int
919  * Status return. 0 on success.
920  * -1 if an unexpected count value was returned
921 -*/
922 
923 int KsmPolicyUpdateDesc(int policy_id, const char* policy_description)
924 {
925  char* sql = NULL; /* SQL query */
926  int status = 0; /* Status return */
927 
928  char quoted_desc[KSM_POLICY_DESC_LENGTH]; /* with bad chars quoted */
929  /* check the main argument (description may be NULL) */
930  if (policy_id <= 0) {
931  return MsgLog(KSM_INVARG, "NULL policy id");
932  }
933 
934  /* Quote description */
935  status = DbQuoteString(DbHandle(), policy_description, quoted_desc, KSM_POLICY_DESC_LENGTH);
936 
937  if (status != 0) {
938  return status;
939  }
940 
941  /* Update policy */
942  sql = DusInit("policies");
943  DusSetString(&sql, "description", quoted_desc, 0);
944  DusConditionInt(&sql, "id", DQS_COMPARE_EQ, policy_id, 0);
945  DusEnd(&sql);
946 
947  status = DbExecuteSqlNoResult(DbHandle(), sql);
948  DisFree(sql);
949 
950  return status;
951 }
952 
954 {
955  KSM_POLICY *policy;
956 
957  policy = (KSM_POLICY *)malloc(sizeof(KSM_POLICY));
958  if (policy == NULL) {
959  return NULL;
960  }
961 
962  policy->description = (char *)calloc(KSM_POLICY_DESC_LENGTH, sizeof(char));
963  policy->signer = (KSM_SIGNER_POLICY *)malloc(sizeof(KSM_SIGNER_POLICY));
964  policy->signature = (KSM_SIGNATURE_POLICY *)malloc(sizeof(KSM_SIGNATURE_POLICY));
965  policy->denial = (KSM_DENIAL_POLICY *)malloc(sizeof(KSM_DENIAL_POLICY));
966  policy->keys = (KSM_COMMON_KEY_POLICY *)malloc(sizeof(KSM_COMMON_KEY_POLICY));
967  policy->ksk = (KSM_KEY_POLICY *)malloc(sizeof(KSM_KEY_POLICY));
968  policy->zsk = (KSM_KEY_POLICY *)malloc(sizeof(KSM_KEY_POLICY));
969  policy->enforcer = (KSM_ENFORCER_POLICY *)malloc(sizeof(KSM_ENFORCER_POLICY));
970  policy->zone = (KSM_ZONE_POLICY *)malloc(sizeof(KSM_ZONE_POLICY));
971  policy->parent = (KSM_PARENT_POLICY *)malloc(sizeof(KSM_PARENT_POLICY));
972 
973  /* if allocation fails, return NULL*/
974  if (policy->description == NULL ||
975  policy->signer == NULL ||
976  policy->signature == NULL ||
977  policy->denial == NULL ||
978  policy->keys == NULL ||
979  policy->ksk == NULL ||
980  policy->zsk == NULL ||
981  policy->enforcer == NULL ||
982  policy->zone == NULL ||
983  policy->parent == NULL) {
984  KsmPolicyFree(policy);
985  return NULL;
986  }
987 
988  return policy;
989 }
990 
992 {
993  free(policy->description);
994  free(policy->signer);
995  free(policy->signature);
996  free(policy->denial);
997  free(policy->keys);
998  free(policy->ksk);
999  free(policy->zsk);
1000  free(policy->enforcer);
1001  free(policy->zone);
1002  free(policy->parent);
1003  free(policy);
1004 }