OpenDNSSEC-enforcer  2.0.2
zone_add_cmd.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 .SE (The Internet Infrastructure Foundation).
3  * Copyright (c) 2014 OpenDNSSEC AB (svb)
4  * 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 #include "config.h"
30 
31 #include "daemon/engine.h"
32 #include "daemon/cmdhandler.h"
33 #include "file.h"
34 #include "str.h"
35 #include "log.h"
36 #include "clientpipe.h"
37 #include "db/policy.h"
38 #include "db/zone.h"
40 #include "enforcer/enforce_task.h"
41 #include "hsmkey/hsm_key_factory.h"
42 
43 #include "keystate/zone_add_cmd.h"
44 
45 #include <limits.h>
46 
47 static const char *module_str = "zone_add_cmd";
48 
49 static void
50 usage(int sockfd)
51 {
52  client_printf(sockfd,
53  "zone add\n"
54  " --zone <zone> aka -z\n"
55  " [--policy <policy>] aka -p\n"
56  " [--signerconf <path>] aka -s\n"
57  " [--in-type <type>] aka -j\n"
58  );
59  client_printf(sockfd,
60  " [--input <path>] aka -i\n"
61  " [--out-type <type>] aka -q\n"
62  " [--output <path>] aka -o\n"
63  " [--xml] aka -u\n"
64  " [--suspend] aka -n\n"
65  );
66 }
67 
68 static void
69 help(int sockfd)
70 {
71  client_printf(sockfd,
72  "Add a new zone to the enforcer database.\n"
73  "\nOptions:\n"
74  "zone name of the zone\n"
75  "policy name of the policy, if not set the default policy is used\n"
76  "signerconf specify a location for signer configuration file, default is /var/opendnssec/signconf/\n"
77  "in-type specify the type of input, should be DNS or File, default is File \n"
78  "input specify a location for the unsigned zone, this location is set in conf.xml, default for File Adapter is /var/opendnssec/unsigned/ and for DNS Adapter is /etc/opendnssec/addns.xml \n"
79  "out-type specify the type of output, should be DNS or File, default is File\n"
80  "output specify a location for the signed zone, this location is set in conf.xml, default path for File Adapter is /var/opendnssec/signed/ and for DNS Adapter is /etc/opendnssec/addns.xml \n"
81  "xml update the zonelist.xml file\n"
82  "suspend suspend this zone until running enforce command\n\n"
83  );
84 }
85 
86 static int
87 handles(const char *cmd, ssize_t n)
88 {
89  return ods_check_command(cmd, n, zone_add_funcblock()->cmdname)?1:0;
90 }
91 
92 static int
93 run(int sockfd, engine_type* engine, const char *cmd, ssize_t n,
94  db_connection_t *dbconn)
95 {
96  char* buf;
97  const char* argv[18];
98  int argc;
99  const char *zone_name = NULL;
100  const char *policy_name = NULL;
101  const char *signconf = NULL;
102  const char *input = NULL;
103  const char *output = NULL;
104  const char *input_type = NULL;
105  const char *output_type = NULL;
106  char path[PATH_MAX];
107  int write_xml;
108  policy_t* policy;
109  zone_t* zone;
110  int ret = 0;
111  int suspend;
112  (void)engine;
113 
114  ods_log_debug("[%s] %s command", module_str, zone_add_funcblock()->cmdname);
115  cmd = ods_check_command(cmd, n, zone_add_funcblock()->cmdname);
116 
117  if (!(buf = strdup(cmd))) {
118  client_printf_err(sockfd, "memory error\n");
119  return -1;
120  }
121 
122  argc = ods_str_explode(buf, 18, argv);
123  if (argc > 17) {
124  client_printf_err(sockfd, "too many arguments\n");
125  free(buf);
126  return -1;
127  }
128 
129  ods_find_arg_and_param(&argc, argv, "zone", "z", &zone_name);
130  ods_find_arg_and_param(&argc, argv, "policy", "p", &policy_name);
131  ods_find_arg_and_param(&argc, argv, "signerconf", "s", &signconf);
132  ods_find_arg_and_param(&argc, argv, "input", "i", &input);
133  ods_find_arg_and_param(&argc, argv, "output", "o", &output);
134  ods_find_arg_and_param(&argc, argv, "in-type", "j", &input_type);
135  ods_find_arg_and_param(&argc, argv, "out-type", "q", &output_type);
136  write_xml = ods_find_arg(&argc, argv, "xml", "u") > -1 ? 1 : 0;
137  suspend = ods_find_arg(&argc, argv, "suspend", "n") > -1 ? 1 : 0;
138 
139  if (argc) {
140  client_printf_err(sockfd, "unknown arguments\n");
141  free(buf);
142  return -1;
143  }
144  if (!zone_name) {
145  client_printf_err(sockfd, "expected option --zone <zone>\n");
146  free(buf);
147  return -1;
148  }
149 
150  if ((zone = zone_new_get_by_name(dbconn, zone_name))) {
151  client_printf_err(sockfd, "Unable to add zone, zone already exists!\n");
152  zone_free(zone);
153  free(buf);
154  return 1;
155  }
156 
157  if (!(policy = policy_new_get_by_name(dbconn, (policy_name ? policy_name : "default")))) {
158  client_printf_err(sockfd, "Unable to find policy %s needed for adding the zone!\n", (policy_name ? policy_name : "default"));
159  free(buf);
160  return 1;
161  }
162 
163  if (!(zone = zone_new(dbconn))) {
164  client_printf_err(sockfd, "Unable to add zone, memory allocation problem!\n");
165  }
166  if (zone_set_name(zone, zone_name)) {
167  client_printf_err(sockfd, "Unable to add zone, failed to set zone name!\n");
168  }
169  if (zone_set_policy_id(zone, policy_id(policy))) {
170  client_printf_err(sockfd, "Unable to add zone, failed to set policy!\n");
171  }
172  if (input_type) {
173  if (!strcasecmp(input_type, "DNS"))
174  input_type = "DNS";
175  else if (!strcasecmp(input_type, "File"))
176  input_type = "File";
177  else {
178  client_printf_err(sockfd, "Unable to add zone, %s is not a valid input type! in_type must be File or DNS.\n", input_type);
179  return 1;
180  }
181  if (zone_set_input_adapter_type(zone, input_type)) {
182  client_printf_err(sockfd, "Unable to add zone, failed to set input type!\n");
183  }
184  }
185  if (input) {
186  if (input[0] == '/') {
187  if (zone_set_input_adapter_uri(zone, input)) {
188  client_printf_err(sockfd, "Unable to add zone, failed to set input!\n");
189  }
190  }
191  else {
192  if (input_type && !strcasecmp(input_type, "DNS")) {
193  if (snprintf(path, sizeof(path), "%s/%s", OPENDNSSEC_CONFIG_DIR, input) >= (int)sizeof(path)
194  || zone_set_input_adapter_uri(zone, path))
195  {
196  client_printf_err(sockfd, "Unable to add zone, failed to set input!\n");
197  }
198  }
199  else {
200  if (snprintf(path, sizeof(path), "%s/unsigned/%s", OPENDNSSEC_STATE_DIR, input) >= (int)sizeof(path)
201  || zone_set_input_adapter_uri(zone, path))
202  {
203  client_printf_err(sockfd, "Unable to add zone, failed to set input!\n");
204  }
205  }
206  }
207  }
208  else {
209  if (input_type && !strcasecmp(input_type, "DNS")) {
210  if (snprintf(path, sizeof(path), "%s/addns.xml", OPENDNSSEC_CONFIG_DIR) >= (int)sizeof(path)
211  || zone_set_input_adapter_uri(zone, path))
212  {
213  client_printf_err(sockfd, "Unable to add zone, failed to set input!\n");
214  }
215  }
216  else {
217  if (snprintf(path, sizeof(path), "%s/unsigned/%s", OPENDNSSEC_STATE_DIR, zone_name) >= (int)sizeof(path)
218  || zone_set_input_adapter_uri(zone, path))
219  {
220  client_printf_err(sockfd, "Unable to add zone, failed to set input!\n");
221  }
222  }
223  }
224  client_printf(sockfd, "input is set to %s. \n", zone_input_adapter_uri(zone));
225  if (access(zone_input_adapter_uri(zone), F_OK) == -1) {
226  client_printf_err(sockfd, "WARNING: The input file %s for zone %s does not currently exist. The zone will be added to the database anyway. \n", zone_input_adapter_uri(zone), zone_name);
227  ods_log_warning("[%s] WARNING: The input file %s for zone %s does not currently exist. The zone will be added to the database anyway.", module_str, zone_input_adapter_uri(zone), zone_name);
228  }
229  else if (access(zone_input_adapter_uri(zone), R_OK)) {
230  client_printf_err(sockfd, "WARNING: Read access to input file %s for zone %s denied! \n ", zone_input_adapter_uri(zone), zone_name);
231  ods_log_warning("[%s] WARNING: Read access to input file %s for zone %s denied! ", module_str, zone_input_adapter_uri(zone), zone_name);
232  }
233 
234  if (output_type) {
235  if (!strcasecmp(output_type, "DNS"))
236  output_type = "DNS";
237  else if (!strcasecmp(output_type, "File"))
238  output_type = "File";
239  else {
240  client_printf_err(sockfd, "Unable to add zone, %s is not a valid output type! out_type must be File or DNS.\n", output_type);
241  return 1;
242  }
243  if (zone_set_output_adapter_type(zone, output_type)) {
244  client_printf_err(sockfd, "Unable to add zone, failed to set output type!\n");
245  }
246  }
247  if (output) {
248  if (output[0] == '/') {
249  if (zone_set_output_adapter_uri(zone, output)) {
250  client_printf_err(sockfd, "Unable to add zone, failed to set output!\n");
251  }
252  }
253  else {
254  if (output_type && !strcasecmp(output_type, "DNS")) {
255  if (snprintf(path, sizeof(path), "%s/%s", OPENDNSSEC_CONFIG_DIR, output) >= (int)sizeof(path)
256  || zone_set_output_adapter_uri(zone, path))
257  {
258  client_printf_err(sockfd, "Unable to add zone, failed to set output!\n");
259  }
260  }
261  else {
262  if (snprintf(path, sizeof(path), "%s/signed/%s", OPENDNSSEC_STATE_DIR, output) >= (int)sizeof(path)
263  || zone_set_output_adapter_uri(zone, path))
264  {
265  client_printf_err(sockfd, "Unable to add zone, failed to set output!\n");
266  }
267  }
268  }
269  }
270  else {
271  if(output_type && !strcasecmp(output_type, "DNS")) {
272  if (snprintf(path, sizeof(path), "%s/addns.xml", OPENDNSSEC_CONFIG_DIR) >= (int)sizeof(path)
273  || zone_set_output_adapter_uri(zone, path))
274  {
275  client_printf_err(sockfd, "Unable to add zone, failed to set output!\n");
276  }
277  }
278  else {
279  if (snprintf(path, sizeof(path), "%s/signed/%s", OPENDNSSEC_STATE_DIR, zone_name) >= (int)sizeof(path)
280  || zone_set_output_adapter_uri(zone, path))
281  {
282  client_printf_err(sockfd, "Unable to add zone, failed to set output!\n");
283  }
284  }
285  }
286 
287  client_printf(sockfd, "output is set to %s. \n", zone_output_adapter_uri(zone));
288  if (output_type && !strcasecmp(output_type, "DNS")) {
289  if (access(zone_output_adapter_uri(zone), F_OK) == -1) {
290  client_printf_err(sockfd, "WARNING: The output file %s for zone %s does not currently exist. The zone will be added to the database anyway. \n", zone_output_adapter_uri(zone), zone_name);
291  ods_log_warning("[%s] WARNING: The output file %s for zone %s does not currently exist. The zone will be added to the database anyway.", module_str, zone_output_adapter_uri(zone), zone_name);
292  }
293  else if (access(zone_output_adapter_uri(zone), R_OK)) {
294  client_printf_err(sockfd, "WARNING: Read access to output file %s for zone %s denied! \n ", zone_output_adapter_uri(zone), zone_name);
295  ods_log_warning("[%s] WARNING: Read access to output file %s for zone %s denied! ", module_str, zone_output_adapter_uri(zone), zone_name);
296  }
297  }
298 
299  if (signconf) {
300  if (signconf[0] == '/') {
301  if (zone_set_signconf_path(zone, signconf)) {
302  client_printf_err(sockfd, "Unable to add zone, failed to set signconf!\n");
303  }
304  }
305  else {
306  if (snprintf(path, sizeof(path), "%s/signconf/%s", OPENDNSSEC_STATE_DIR, signconf) >= (int)sizeof(path)
307  || zone_set_signconf_path(zone, path))
308  {
309  client_printf_err(sockfd, "Unable to add zone, failed to set signconf!\n");
310  }
311  }
312  }
313  else {
314  char signedfile[257] = "";
315  strncat (strncat (signedfile, zone_name, strlen (zone_name)), ".xml", 4);
316  if (snprintf(path, sizeof(path), "%s/signconf/%s", OPENDNSSEC_STATE_DIR, signedfile) >= (int)sizeof(path)
317  || zone_set_signconf_path(zone, path))
318  {
319  client_printf_err(sockfd, "Unable to add zone, failed to set signconf!\n");
320  }
321  }
322  if (suspend) {
323  if (zone_set_next_change(zone, -1)) {
324  ods_log_error("[%s] Cannot suspend zone %s, database error!", module_str, zone_name);
325  client_printf_err(sockfd, "Cannot suspend zone %s, database error!\n", zone_name);
326  }
327  }
328 
329  if (zone_create(zone)) {
330  client_printf_err(sockfd, "Unable to add zone, database error!\n");
331  zone_free(zone);
332  policy_free(policy);
333  free(buf);
334  return 1;
335  }
336  ods_log_info("[%s] zone %s added [policy: %s]", module_str, zone_name, (policy_name ? policy_name : "default"));
337  client_printf(sockfd, "Zone %s added successfully\n", zone_name);
338  free(buf);
339 
340  if (write_xml) {
341  if (zonelist_update_add(sockfd, engine->config->zonelist_filename, zone, 1) != ZONELIST_UPDATE_OK) {
342  ods_log_error("[%s] zonelist %s updated failed", module_str, engine->config->zonelist_filename);
343  client_printf_err(sockfd, "Zonelist %s update failed!\n", engine->config->zonelist_filename);
344  ret = 1;
345  }
346  else {
347  ods_log_info("[%s] zonelist %s updated successfully", module_str, engine->config->zonelist_filename);
348  client_printf(sockfd, "Zonelist %s updated successfully\n", engine->config->zonelist_filename);
349  }
350  }
351 
352  if (snprintf(path, sizeof(path), "%s/%s", engine->config->working_dir, OPENDNSSEC_ENFORCER_ZONELIST) >= (int)sizeof(path)
353  || zonelist_update_add(sockfd, path, zone, 0) != ZONELIST_UPDATE_OK)
354  {
355  ods_log_error("[%s] internal zonelist update failed", module_str);
356  client_printf_err(sockfd, "Unable to update the internal zonelist %s, updates will not reach the Signer!\n", path);
357  ret = 1;
358  }
359  else {
360  ods_log_info("[%s] internal zonelist updated successfully", module_str);
361  }
362 
363  /*
364  * On successful generate HSM keys and add/flush enforce task.
365  */
366  hsm_key_factory_generate_policy(engine, dbconn, policy, 0);
367  ods_log_debug("[%s] Flushing enforce task", module_str);
368  flush_enforce_task(engine, 0);
369 
370  policy_free(policy);
371 
372  zone_free(zone);
373 
374  return ret;
375 }
376 
377 static struct cmd_func_block funcblock = {
378  "zone add", &usage, &help, &handles, &run
379 };
380 
381 struct cmd_func_block*
383 {
384  return &funcblock;
385 }
const char * zone_output_adapter_uri(const zone_t *zone)
Definition: zone.c:886
void(* help)(int sockfd)
Definition: cmdhandler.h:64
void ods_log_debug(const char *format,...)
Definition: log.c:41
policy_t * policy_new_get_by_name(const db_connection_t *connection, const char *name)
Definition: policy.c:2090
#define ZONELIST_UPDATE_OK
const char * zonelist_filename
Definition: cfg.h:57
const char * policy_name(const policy_t *policy)
Definition: policy.c:813
int zone_set_signconf_path(zone_t *zone, const char *signconf_path_text)
Definition: zone.c:969
void hsm_key_factory_generate_policy(engine_type *engine, const db_connection_t *connection, const policy_t *policy, time_t duration)
void ods_log_info(const char *format,...)
Definition: log.c:55
int zone_set_output_adapter_uri(zone_t *zone, const char *output_adapter_uri_text)
Definition: zone.c:1127
int zone_set_policy_id(zone_t *zone, const db_value_t *policy_id)
Definition: zone.c:918
int(* run)(int sockfd, struct engine_struct *engine, const char *cmd, ssize_t n, db_connection_t *dbconn)
Definition: cmdhandler.h:79
int zone_set_input_adapter_uri(zone_t *zone, const char *input_adapter_uri_text)
Definition: zone.c:1083
const char * cmdname
Definition: cmdhandler.h:59
void ods_log_error(const char *format,...)
Definition: log.c:69
int zonelist_update_add(int sockfd, const char *filename, const zone_t *zone, int comment)
void zone_free(zone_t *zone)
Definition: zone.c:325
void(* usage)(int sockfd)
Definition: cmdhandler.h:61
engineconfig_type * config
Definition: engine.h:53
void policy_free(policy_t *policy)
Definition: policy.c:518
zone_t * zone_new(const db_connection_t *connection)
Definition: zone.c:287
int zone_set_name(zone_t *zone, const char *name_text)
Definition: zone.c:937
int zone_set_next_change(zone_t *zone, int next_change)
Definition: zone.c:991
struct cmd_func_block * zone_add_funcblock(void)
Definition: zone_add_cmd.c:382
zone_t * zone_new_get_by_name(const db_connection_t *connection, const char *name)
Definition: zone.c:1569
const char * zone_name(const zone_t *zone)
Definition: zone.c:782
int zone_set_output_adapter_type(zone_t *zone, const char *output_adapter_type_text)
Definition: zone.c:1105
const char * working_dir
Definition: cfg.h:64
Definition: policy.h:60
Definition: zone.h:46
int(* handles)(const char *cmd, ssize_t n)
Definition: cmdhandler.h:67
const char * zone_input_adapter_uri(const zone_t *zone)
Definition: zone.c:870
const db_value_t * policy_id(const policy_t *policy)
Definition: policy.c:805
int zone_create(zone_t *zone)
Definition: zone.c:1206
void ods_log_warning(const char *format,...)
Definition: log.c:62
int flush_enforce_task(engine_type *engine, bool enforce_all)
Definition: enforce_task.c:323
int zone_set_input_adapter_type(zone_t *zone, const char *input_adapter_type_text)
Definition: zone.c:1061