OpenDNSSEC-enforcer  2.1.12
policy_resalt_task.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 Surfnet
3  * Copyright (c) 2011 .SE (The Internet Infrastructure Foundation).
4  * Copyright (c) 2011 OpenDNSSEC AB (svb)
5  * Copyright (c) 2014 NLnet Labs
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  */
30 
31 #include "config.h"
32 
33 /* On MacOSX arc4random is only available when we
34  undef _ANSI_SOURCE and define _DARWIN_C_SOURCE. */
35 #ifdef __APPLE__
36  #undef _ANSI_SOURCE
37  #define _DARWIN_C_SOURCE 1
38 #endif
39 /* Make arc4random visible on FreeBSD */
40 #ifndef __BSD_VISIBLE
41  #define __BSD_VISIBLE 1
42 #endif
43 
44 #include "duration.h"
45 #include "file.h"
46 #include "log.h"
47 #include "str.h"
48 #include "scheduler/task.h"
49 #include "daemon/engine.h"
50 #include "db/policy.h"
51 
52 #include <stdlib.h>
53 
55 #include "signconf/signconf_task.h"
56 
57 static const char *module_str = "policy_resalt_task";
58 
65 static void
66 generate_salt(char *buf, int len)
67 {
68 #ifdef HAVE_ARC4RANDOM
69  arc4random_buf(buf, len);
70 #else
71  int i;
72  /* Not really sure how many bits we get, but pseudo randomness
73  * is cheap. */
74  for (i = 0; i < len; i++)
75  buf[i] = rand() & 0xFF;
76 #endif
77 }
78 
85 static void
86 to_hex(const char *buf, int len, char *out)
87 {
88  const char *h = "0123456789abcdef";
89  int i;
90 
91  for (i = 0; i < len; i++) {
92  out[2*i] = h[(buf[i]>>4) & 0x0F];
93  out[2*i+1] = h[buf[i] & 0x0F];
94  }
95  out[2*len] = 0;
96 }
97 
102 static time_t
103 performresalt(task_type* task, char const *policyname, void *userdata,
104  void *context, int do_now)
105 {
106  policy_t *policy;
107  db_connection_t *dbconn = (db_connection_t *) context;
108  time_t resalt_time, now = time_now();
109  char salt[255], salthex[511];
110  int saltlength;
111  engine_type *engine = (engine_type *)userdata;
112 
113  policy = policy_new_get_by_name(dbconn, policyname);
114  if (!policy) {
115  ods_log_error("[%s] could not fetch policy %s from database,"
116  " rescheduling", module_str, policyname);
117  /* TODO: figure out if it was a database error. if it is truly
118  * not in database we should just return schedule_SUCCESS */
119  return schedule_DEFER;
120  }
121 
124  {
126  return schedule_SUCCESS;
127  }
128  resalt_time = policy_denial_salt_last_change(policy) +
130 
131  if (now >= resalt_time || do_now) {
132  saltlength = policy_denial_salt_length(policy);
133  if (saltlength < 0 || saltlength > 255) {
134  ods_log_error("[%s] policy %s has an invalid salt length. "
135  "Must be in range [0..255]", module_str, policy_name(policy));
137  return schedule_SUCCESS; /* no point in rescheduling */
138  }
139 
140 #ifndef HAVE_ARC4RANDOM
141  srand(now);
142 #endif
143 
144  /* Yes, we need to resalt this policy */
145  generate_salt(salt, saltlength);
146  to_hex(salt, saltlength, salthex);
147 
148  if(policy_set_denial_salt(policy, salthex) ||
151  {
152  ods_log_error("[%s] db error", module_str);
154  return schedule_DEFER;
155  }
156  resalt_time = now + policy_denial_resalt(policy);
157  ods_log_debug("[%s] policy %s resalted successfully", module_str, policy_name(policy));
158  signconf_task_flush_policy(engine, dbconn, policy);
159  }
160  if (policy_denial_resalt(policy) <= 0) resalt_time = -1;
162  return resalt_time;
163 }
164 
165 static time_t
166 perform_policy_resalt(task_type* task, char const *policyname, void *userdata, void *context)
167 {
168  return performresalt(task, policyname, userdata, context, 0);
169 }
170 
171 static time_t
172 perform_policy_forceresalt(task_type* task, char const *policyname, void *userdata, void *context)
173 {
174  return performresalt(task, policyname, userdata, context, 1);
175 }
176 
177 /*
178  * Schedule resalt tasks for all policies.
179  */
180 int
182 {
183 
184  policy_list_t *policylist;
185  const policy_t *policy;
186  task_type *task;
187  int status = ODS_STATUS_OK;
188 
189  policylist = policy_list_new(dbconn);
190  if (policy_list_get(policylist)) {
191  ods_log_error("[%s] Unable to get list of policies from database",
192  module_str);
193  policy_list_free(policylist);
194  return ODS_STATUS_ERR;
195  }
196 
197  while ((policy = policy_list_next(policylist))) {
198  task = task_create(strdup(policy_name(policy)), TASK_CLASS_ENFORCER, TASK_TYPE_RESALT, perform_policy_resalt, engine, NULL, time_now());
199  status |= schedule_task(engine->taskq, task, 1, 0);
200  }
201  policy_list_free(policylist);
202  return status;
203 }
204 
205 int
207 {
208 
209  policy_list_t *policylist;
210  const policy_t *policy;
211  task_type *task;
212  int status = ODS_STATUS_OK;
213 
214  policylist = policy_list_new(dbconn);
215  if (policy_list_get(policylist)) {
216  ods_log_error("[%s] Unable to get list of policies from database",
217  module_str);
218  policy_list_free(policylist);
219  return ODS_STATUS_ERR;
220  }
221 
222  while ((policy = policy_list_next(policylist))) {
223  task = task_create(strdup(policy_name(policy)), TASK_CLASS_ENFORCER, TASK_TYPE_RESALT, perform_policy_forceresalt, engine, NULL, time_now());
224  status |= schedule_task(engine->taskq, task, 1, 0);
225  }
226  policy_list_free(policylist);
227  return status;
228 }
const char * policy_name(const policy_t *policy)
Definition: policy.c:813
unsigned int policy_denial_salt_length(const policy_t *policy)
Definition: policy.c:941
const policy_t * policy_list_next(policy_list_t *policy_list)
Definition: policy.c:3214
void policy_list_free(policy_list_t *policy_list)
Definition: policy.c:2664
unsigned int policy_denial_salt_last_change(const policy_t *policy)
Definition: policy.c:957
unsigned int policy_passthrough(const policy_t *policy)
Definition: policy.c:1085
int policy_set_denial_salt_last_change(policy_t *policy, unsigned int denial_salt_last_change)
Definition: policy.c:1373
int policy_set_denial_salt(policy_t *policy, const char *denial_salt_text)
Definition: policy.c:1351
policy_list_t * policy_list_new(const db_connection_t *connection)
Definition: policy.c:2621
int policy_list_get(policy_list_t *policy_list)
Definition: policy.c:3040
void policy_free(policy_t *policy)
Definition: policy.c:518
unsigned int policy_denial_resalt(const policy_t *policy)
Definition: policy.c:917
policy_t * policy_new_get_by_name(const db_connection_t *connection, const char *name)
Definition: policy.c:2090
int policy_update(policy_t *policy)
Definition: policy.c:2110
policy_denial_type
Definition: policy.h:40
@ POLICY_DENIAL_TYPE_NSEC3
Definition: policy.h:43
int flush_resalt_task_all(engine_type *engine, db_connection_t *dbconn)
int flush_resalt_task_now(engine_type *engine, db_connection_t *dbconn)
void signconf_task_flush_policy(engine_type *engine, db_connection_t *dbconn, policy_t const *policy)
Definition: signconf_task.c:85
schedule_type * taskq
Definition: engine.h:60
Definition: policy.h:60