OpenDNSSEC-enforcer 2.1.13
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
56
57static const char *module_str = "policy_resalt_task";
58
65static void
66generate_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
85static void
86to_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
102static time_t
103performresalt(task_type* task, char const *policyname, void *userdata,
104 void *context, int do_now)
105{
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 }
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
165static time_t
166perform_policy_resalt(task_type* task, char const *policyname, void *userdata, void *context)
167{
168 return performresalt(task, policyname, userdata, context, 0);
169}
170
171static time_t
172perform_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 */
180int
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
205int
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}
unsigned int policy_denial_salt_length(const policy_t *policy)
Definition policy.c:941
void policy_list_free(policy_list_t *policy_list)
Definition policy.c:2664
const policy_t * policy_list_next(policy_list_t *policy_list)
Definition policy.c:3214
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
policy_t * policy_new_get_by_name(const db_connection_t *connection, const char *name)
Definition policy.c:2090
const char * policy_name(const policy_t *policy)
Definition policy.c:813
int policy_set_denial_salt_last_change(policy_t *policy, unsigned int denial_salt_last_change)
Definition policy.c:1373
policy_list_t * policy_list_new(const db_connection_t *connection)
Definition policy.c:2621
int policy_set_denial_salt(policy_t *policy, const char *denial_salt_text)
Definition policy.c:1351
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
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)
schedule_type * taskq
Definition engine.h:60