1/*
2 * winrc/anchor-update.c - windows trust anchor update util
3 *
4 * Copyright (c) 2009, NLnet Labs. All rights reserved.
5 *
6 * This software is open source.
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 *
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36/**
37 * \file
38 *
39 * This file is made because contrib/update-anchor.sh does not work on
40 * windows (no shell).
41 */
42#include "config.h"
43#include "libunbound/unbound.h"
44#include "sldns/rrdef.h"
45#include "sldns/pkthdr.h"
46#include "sldns/wire2str.h"
47
48/** usage */
49static void
50usage(void)
51{
52	printf("usage: { name-of-domain filename }+ \n");
53	printf("exit codes: 0 anchors updated, 1 no changes, 2 errors.\n");
54	exit(1);
55}
56
57/** fatal exit */
58static void fatal(const char* str)
59{
60	printf("fatal error: %s\n", str);
61	exit(2);
62}
63
64/** lookup data */
65static struct ub_result*
66do_lookup(struct ub_ctx* ctx, char* domain)
67{
68	struct ub_result* result = NULL;
69	int r;
70	r = ub_resolve(ctx, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN,
71		&result);
72	if(r) {
73		printf("failed to lookup %s\n", ub_strerror(r));
74		fatal("ub_resolve failed");
75	}
76	if(!result->havedata && (result->rcode == LDNS_RCODE_SERVFAIL ||
77		result->rcode == LDNS_RCODE_REFUSED))
78		return NULL; /* probably no internet connection */
79	if(!result->havedata) fatal("result has no data");
80	if(!result->secure) fatal("result is not secure");
81	return result;
82}
83
84/** print result to file */
85static void
86do_print(struct ub_result* result, char* file)
87{
88	FILE* out = fopen(file, "w");
89	char s[65535], t[32];
90	int i;
91	if(!out) {
92		perror(file);
93		fatal("fopen failed");
94	}
95	i = 0;
96	if(result->havedata)
97	  while(result->data[i]) {
98		sldns_wire2str_rdata_buf((uint8_t*)result->data[i],
99			(size_t)result->len[i], s, sizeof(s),
100			(uint16_t)result->qtype);
101		sldns_wire2str_type_buf((uint16_t)result->qtype, t, sizeof(t));
102		fprintf(out, "%s\t%s\t%s\n", result->qname, t, s);
103		i++;
104	}
105	fclose(out);
106}
107
108/** update domain to file */
109static int
110do_update(char* domain, char* file)
111{
112	struct ub_ctx* ctx;
113	struct ub_result* result;
114	int r;
115	printf("updating %s to %s\n", domain, file);
116	ctx = ub_ctx_create();
117	if(!ctx) fatal("ub_ctx_create failed");
118
119	if((r=ub_ctx_add_ta_file(ctx, file))) {
120		printf("%s\n", ub_strerror(r));
121		fatal("ub_ctx_add_ta_file failed");
122	}
123
124	if(!(result=do_lookup(ctx, domain))) {
125		ub_ctx_delete(ctx);
126		return 1;
127	}
128	ub_ctx_delete(ctx);
129	do_print(result, file);
130	ub_resolve_free(result);
131	return 0;
132}
133
134/** anchor update main */
135int main(int argc, char** argv)
136{
137	int retcode = 1;
138	if(argc == 1) {
139		usage();
140	}
141	argc--;
142	argv++;
143	while(argc > 0) {
144		int r = do_update(argv[0], argv[1]);
145		if(r == 0) retcode = 0;
146
147		/* next */
148		argc-=2;
149		argv+=2;
150	}
151	return retcode;
152}
153