1 /* 2 * testcode/signit.c - debug tool to sign rrsets with given keys. 3 * 4 * Copyright (c) 2007, 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 program signs rrsets with the given keys. It can be used to 40 * construct input to test the validator with. 41 */ 42 #include "config.h" 43 #include <ldns/ldns.h> 44 #include <assert.h> 45 46 #define DNSKEY_BIT_ZSK 0x0100 47 48 /** 49 * Key settings 50 */ 51 struct keysets { 52 /** signature inception */ 53 uint32_t incep; 54 /** signature expiration */ 55 uint32_t expi; 56 /** owner name */ 57 char* owner; 58 /** keytag */ 59 uint16_t keytag; 60 /** DNSKEY flags */ 61 uint16_t flags; 62 }; 63 64 /** print usage and exit */ 65 static void 66 usage(void) 67 { 68 printf("usage: signit expi ince keytag owner keyfile\n"); 69 printf("present rrset data on stdin.\n"); 70 printf("signed data is printed to stdout.\n"); 71 printf("\n"); 72 printf("Or use: signit NSEC3PARAM hash flags iter salt\n"); 73 printf("present names on stdin, hashed names are printed to stdout.\n"); 74 exit(1); 75 } 76 77 static time_t 78 convert_timeval(const char* str) 79 { 80 time_t t; 81 struct tm tm; 82 memset(&tm, 0, sizeof(tm)); 83 if(strlen(str) < 14) 84 return 0; 85 if(sscanf(str, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, 86 &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) 87 return 0; 88 tm.tm_year -= 1900; 89 tm.tm_mon--; 90 /* Check values */ 91 if (tm.tm_year < 70) return 0; 92 if (tm.tm_mon < 0 || tm.tm_mon > 11) return 0; 93 if (tm.tm_mday < 1 || tm.tm_mday > 31) return 0; 94 if (tm.tm_hour < 0 || tm.tm_hour > 23) return 0; 95 if (tm.tm_min < 0 || tm.tm_min > 59) return 0; 96 if (tm.tm_sec < 0 || tm.tm_sec > 59) return 0; 97 /* call ldns conversion function */ 98 t = ldns_mktime_from_utc(&tm); 99 return t; 100 } 101 102 static void fatal_exit(const char* format, ...) 103 { 104 va_list args; 105 va_start(args, format); 106 printf("fatal exit: "); 107 vprintf(format, args); 108 va_end(args); 109 exit(1); 110 } 111 112 /** read expi ince keytag owner from cmdline */ 113 static void 114 parse_cmdline(char *argv[], struct keysets* s) 115 { 116 s->expi = convert_timeval(argv[1]); 117 s->incep = convert_timeval(argv[2]); 118 s->keytag = (uint16_t)atoi(argv[3]); 119 s->owner = argv[4]; 120 s->flags = DNSKEY_BIT_ZSK; /* to enforce signing */ 121 } 122 123 /** read all key files, exit on error */ 124 static ldns_key_list* 125 read_keys(int num, char* names[], struct keysets* set) 126 { 127 int i; 128 ldns_key_list* keys = ldns_key_list_new(); 129 ldns_key* k; 130 ldns_rdf* rdf; 131 ldns_status s; 132 int b; 133 FILE* in; 134 135 if(!keys) fatal_exit("alloc failure"); 136 for(i=0; i<num; i++) { 137 printf("read keyfile %s\n", names[i]); 138 in = fopen(names[i], "r"); 139 if(!in) fatal_exit("could not open %s: %s", names[i], 140 strerror(errno)); 141 s = ldns_key_new_frm_fp(&k, in); 142 fclose(in); 143 if(s != LDNS_STATUS_OK) 144 fatal_exit("bad keyfile %s: %s", names[i], 145 ldns_get_errorstr_by_id(s)); 146 ldns_key_set_expiration(k, set->expi); 147 ldns_key_set_inception(k, set->incep); 148 s = ldns_str2rdf_dname(&rdf, set->owner); 149 if(s != LDNS_STATUS_OK) 150 fatal_exit("bad owner name %s: %s", set->owner, 151 ldns_get_errorstr_by_id(s)); 152 ldns_key_set_pubkey_owner(k, rdf); 153 ldns_key_set_flags(k, set->flags); 154 ldns_key_set_keytag(k, set->keytag); 155 b = ldns_key_list_push_key(keys, k); 156 assert(b); 157 } 158 return keys; 159 } 160 161 /** read list of rrs from the file */ 162 static ldns_rr_list* 163 read_rrs(FILE* in) 164 { 165 uint32_t my_ttl = 3600; 166 ldns_rdf *my_origin = NULL; 167 ldns_rdf *my_prev = NULL; 168 ldns_status s; 169 int line_nr = 1; 170 int b; 171 172 ldns_rr_list* list; 173 ldns_rr *rr; 174 175 list = ldns_rr_list_new(); 176 if(!list) fatal_exit("alloc error"); 177 178 while(!feof(in)) { 179 s = ldns_rr_new_frm_fp_l(&rr, in, &my_ttl, &my_origin, 180 &my_prev, &line_nr); 181 if(s == LDNS_STATUS_SYNTAX_TTL || 182 s == LDNS_STATUS_SYNTAX_ORIGIN || 183 s == LDNS_STATUS_SYNTAX_EMPTY) 184 continue; 185 else if(s != LDNS_STATUS_OK) 186 fatal_exit("parse error in line %d: %s", line_nr, 187 ldns_get_errorstr_by_id(s)); 188 b = ldns_rr_list_push_rr(list, rr); 189 assert(b); 190 } 191 printf("read %d lines\n", line_nr); 192 193 return list; 194 } 195 196 /** sign the rrs with the keys */ 197 static void 198 signit(ldns_rr_list* rrs, ldns_key_list* keys) 199 { 200 ldns_rr_list* rrset; 201 ldns_rr_list* sigs; 202 203 while(ldns_rr_list_rr_count(rrs) > 0) { 204 rrset = ldns_rr_list_pop_rrset(rrs); 205 if(!rrset) fatal_exit("copy alloc failure"); 206 sigs = ldns_sign_public(rrset, keys); 207 if(!sigs) fatal_exit("failed to sign"); 208 ldns_rr_list_print(stdout, rrset); 209 ldns_rr_list_print(stdout, sigs); 210 printf("\n"); 211 ldns_rr_list_free(rrset); 212 ldns_rr_list_free(sigs); 213 } 214 } 215 216 /** process keys and signit */ 217 static void 218 process_keys(int argc, char* argv[]) 219 { 220 ldns_rr_list* rrs; 221 ldns_key_list* keys; 222 struct keysets settings; 223 assert(argc == 6); 224 225 parse_cmdline(argv, &settings); 226 keys = read_keys(1, argv+5, &settings); 227 rrs = read_rrs(stdin); 228 signit(rrs, keys); 229 230 ldns_rr_list_deep_free(rrs); 231 ldns_key_list_free(keys); 232 } 233 234 /** process nsec3 params and perform hashing */ 235 static void 236 process_nsec3(int argc, char* argv[]) 237 { 238 char line[10240]; 239 ldns_rdf* salt; 240 ldns_rdf* in, *out; 241 ldns_status status; 242 status = ldns_str2rdf_nsec3_salt(&salt, argv[5]); 243 if(status != LDNS_STATUS_OK) 244 fatal_exit("Could not parse salt %s: %s", argv[5], 245 ldns_get_errorstr_by_id(status)); 246 assert(argc == 6); 247 while(fgets(line, (int)sizeof(line), stdin)) { 248 if(strlen(line) > 0) 249 line[strlen(line)-1] = 0; /* remove trailing newline */ 250 if(line[0]==0) 251 continue; 252 status = ldns_str2rdf_dname(&in, line); 253 if(status != LDNS_STATUS_OK) 254 fatal_exit("Could not parse name %s: %s", line, 255 ldns_get_errorstr_by_id(status)); 256 ldns_rdf_print(stdout, in); 257 printf(" -> "); 258 /* arg 3 is flags, unused */ 259 out = ldns_nsec3_hash_name(in, (uint8_t)atoi(argv[2]), 260 (uint16_t)atoi(argv[4]), 261 ldns_rdf_data(salt)[0], ldns_rdf_data(salt)+1); 262 if(!out) 263 fatal_exit("Could not hash %s", line); 264 ldns_rdf_print(stdout, out); 265 printf("\n"); 266 ldns_rdf_deep_free(in); 267 ldns_rdf_deep_free(out); 268 } 269 ldns_rdf_deep_free(salt); 270 } 271 272 /** main program */ 273 int main(int argc, char* argv[]) 274 { 275 if(argc != 6) { 276 usage(); 277 } 278 if(strcmp(argv[1], "NSEC3PARAM") == 0) { 279 process_nsec3(argc, argv); 280 return 0; 281 } 282 process_keys(argc, argv); 283 return 0; 284 } 285