1 /** 2 * str2wire.c - read txt presentation of RRs 3 * 4 * (c) NLnet Labs, 2005-2006 5 * 6 * See the file LICENSE for the license 7 */ 8 9 /** 10 * \file 11 * 12 * Parses text to wireformat. 13 */ 14 #include "config.h" 15 #include "sldns/str2wire.h" 16 #include "sldns/wire2str.h" 17 #include "sldns/sbuffer.h" 18 #include "sldns/parse.h" 19 #include "sldns/parseutil.h" 20 #include <ctype.h> 21 #ifdef HAVE_TIME_H 22 #include <time.h> 23 #endif 24 #ifdef HAVE_NETDB_H 25 #include <netdb.h> 26 #endif 27 28 /** return an error */ 29 #define RET_ERR(e, off) ((int)((e)|((off)<<LDNS_WIREPARSE_SHIFT))) 30 /** Move parse error but keep its ID */ 31 #define RET_ERR_SHIFT(e, move) RET_ERR(LDNS_WIREPARSE_ERROR(e), LDNS_WIREPARSE_OFFSET(e)+(move)); 32 #define LDNS_IP6ADDRLEN (128/8) 33 34 /* 35 * No special care is taken, all dots are translated into 36 * label separators. 37 * @param rel: true if the domain is not absolute (not terminated in .). 38 * The output is then still terminated with a '0' rootlabel. 39 */ 40 static int sldns_str2wire_dname_buf_rel(const char* str, uint8_t* buf, 41 size_t* olen, int* rel) 42 { 43 size_t len; 44 45 const char *s; 46 uint8_t *q, *pq, label_len; 47 48 if(rel) *rel = 0; 49 len = strlen((char*)str); 50 /* octet representation can make strings a lot longer than actual length */ 51 if (len > LDNS_MAX_DOMAINLEN * 4) { 52 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, 0); 53 } 54 if (0 == len) { 55 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, 0); 56 } 57 58 /* root label */ 59 if (1 == len && *str == '.') { 60 if(*olen < 1) 61 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 0); 62 buf[0] = 0; 63 *olen = 1; 64 return LDNS_WIREPARSE_ERR_OK; 65 } 66 67 /* get on with the rest */ 68 69 /* s is on the current character in the string 70 * pq points to where the labellength is going to go 71 * label_len keeps track of the current label's length 72 * q builds the dname inside the buf array 73 */ 74 len = 0; 75 if(*olen < 1) 76 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 0); 77 q = buf+1; 78 pq = buf; 79 label_len = 0; 80 for (s = str; *s; s++, q++) { 81 if (q >= buf + *olen) 82 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf); 83 if (q > buf + LDNS_MAX_DOMAINLEN) 84 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf); 85 switch (*s) { 86 case '.': 87 if (label_len > LDNS_MAX_LABELLEN) { 88 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, q-buf); 89 } 90 if (label_len == 0) { 91 return RET_ERR(LDNS_WIREPARSE_ERR_EMPTY_LABEL, q-buf); 92 } 93 len += label_len + 1; 94 *q = 0; 95 *pq = label_len; 96 label_len = 0; 97 pq = q; 98 break; 99 case '\\': 100 /* octet value or literal char */ 101 s += 1; 102 if (!sldns_parse_escape(q, &s)) { 103 *q = 0; 104 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, q-buf); 105 } 106 s -= 1; 107 label_len++; 108 break; 109 default: 110 *q = (uint8_t)*s; 111 label_len++; 112 } 113 } 114 115 /* add root label if last char was not '.' */ 116 if(label_len != 0) { 117 if(rel) *rel = 1; 118 if (q >= buf + *olen) 119 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf); 120 if (q > buf + LDNS_MAX_DOMAINLEN) { 121 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf); 122 } 123 if (label_len > LDNS_MAX_LABELLEN) { 124 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, q-buf); 125 } 126 if (label_len == 0) { /* label_len 0 but not . at end? */ 127 return RET_ERR(LDNS_WIREPARSE_ERR_EMPTY_LABEL, q-buf); 128 } 129 len += label_len + 1; 130 *pq = label_len; 131 *q = 0; 132 } 133 len++; 134 *olen = len; 135 136 return LDNS_WIREPARSE_ERR_OK; 137 } 138 139 int sldns_str2wire_dname_buf(const char* str, uint8_t* buf, size_t* len) 140 { 141 return sldns_str2wire_dname_buf_rel(str, buf, len, NULL); 142 } 143 144 int sldns_str2wire_dname_buf_origin(const char* str, uint8_t* buf, size_t* len, 145 uint8_t* origin, size_t origin_len) 146 { 147 size_t dlen = *len; 148 int rel = 0; 149 int s = sldns_str2wire_dname_buf_rel(str, buf, &dlen, &rel); 150 if(s) return s; 151 152 if(rel && origin && dlen > 0) { 153 if(dlen + origin_len - 1 > LDNS_MAX_DOMAINLEN) 154 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, 155 LDNS_MAX_DOMAINLEN); 156 if(dlen + origin_len - 1 > *len) 157 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 158 *len); 159 memmove(buf+dlen-1, origin, origin_len); 160 *len = dlen + origin_len - 1; 161 } else 162 *len = dlen; 163 return LDNS_WIREPARSE_ERR_OK; 164 } 165 166 uint8_t* sldns_str2wire_dname(const char* str, size_t* len) 167 { 168 uint8_t dname[LDNS_MAX_DOMAINLEN+1]; 169 *len = sizeof(dname); 170 if(sldns_str2wire_dname_buf(str, dname, len) == 0) { 171 uint8_t* r = (uint8_t*)malloc(*len); 172 if(r) return memcpy(r, dname, *len); 173 } 174 *len = 0; 175 return NULL; 176 } 177 178 /** read owner name */ 179 static int 180 rrinternal_get_owner(sldns_buffer* strbuf, uint8_t* rr, size_t* len, 181 size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, 182 size_t prev_len, char* token, size_t token_len) 183 { 184 /* split the rr in its parts -1 signals trouble */ 185 if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 186 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 187 sldns_buffer_position(strbuf)); 188 } 189 190 if(strcmp(token, "@") == 0) { 191 uint8_t* tocopy; 192 if (origin) { 193 *dname_len = origin_len; 194 tocopy = origin; 195 } else if (prev) { 196 *dname_len = prev_len; 197 tocopy = prev; 198 } else { 199 /* default to root */ 200 *dname_len = 1; 201 tocopy = (uint8_t*)"\0"; 202 } 203 if(*len < *dname_len) 204 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 205 sldns_buffer_position(strbuf)); 206 memmove(rr, tocopy, *dname_len); 207 } else if(*token == '\0') { 208 /* no ownername was given, try prev, if that fails 209 * origin, else default to root */ 210 uint8_t* tocopy; 211 if(prev) { 212 *dname_len = prev_len; 213 tocopy = prev; 214 } else if(origin) { 215 *dname_len = origin_len; 216 tocopy = origin; 217 } else { 218 *dname_len = 1; 219 tocopy = (uint8_t*)"\0"; 220 } 221 if(*len < *dname_len) 222 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 223 sldns_buffer_position(strbuf)); 224 memmove(rr, tocopy, *dname_len); 225 } else { 226 size_t dlen = *len; 227 int s = sldns_str2wire_dname_buf_origin(token, rr, &dlen, 228 origin, origin_len); 229 if(s) return RET_ERR_SHIFT(s, 230 sldns_buffer_position(strbuf)-strlen(token)); 231 *dname_len = dlen; 232 } 233 return LDNS_WIREPARSE_ERR_OK; 234 } 235 236 /** read ttl */ 237 static int 238 rrinternal_get_ttl(sldns_buffer* strbuf, char* token, size_t token_len, 239 int* not_there, uint32_t* ttl, uint32_t default_ttl) 240 { 241 const char* endptr; 242 if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 243 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL, 244 sldns_buffer_position(strbuf)); 245 } 246 *ttl = (uint32_t) sldns_str2period(token, &endptr); 247 248 if (strlen(token) > 0 && !isdigit((unsigned char)token[0])) { 249 *not_there = 1; 250 /* ah, it's not there or something */ 251 if (default_ttl == 0) { 252 *ttl = LDNS_DEFAULT_TTL; 253 } else { 254 *ttl = default_ttl; 255 } 256 } 257 return LDNS_WIREPARSE_ERR_OK; 258 } 259 260 /** read class */ 261 static int 262 rrinternal_get_class(sldns_buffer* strbuf, char* token, size_t token_len, 263 int* not_there, uint16_t* cl) 264 { 265 /* if 'not_there' then we got token from previous parse routine */ 266 if(!*not_there) { 267 /* parse new token for class */ 268 if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 269 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_CLASS, 270 sldns_buffer_position(strbuf)); 271 } 272 } else *not_there = 0; 273 *cl = sldns_get_rr_class_by_name(token); 274 /* class can be left out too, assume IN, current token must be type */ 275 if(*cl == 0 && strcmp(token, "CLASS0") != 0) { 276 *not_there = 1; 277 *cl = LDNS_RR_CLASS_IN; 278 } 279 return LDNS_WIREPARSE_ERR_OK; 280 } 281 282 /** read type */ 283 static int 284 rrinternal_get_type(sldns_buffer* strbuf, char* token, size_t token_len, 285 int* not_there, uint16_t* tp) 286 { 287 /* if 'not_there' then we got token from previous parse routine */ 288 if(!*not_there) { 289 /* parse new token for type */ 290 if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 291 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 292 sldns_buffer_position(strbuf)); 293 } 294 } 295 *tp = sldns_get_rr_type_by_name(token); 296 if(*tp == 0 && strcmp(token, "TYPE0") != 0) { 297 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 298 sldns_buffer_position(strbuf)); 299 } 300 return LDNS_WIREPARSE_ERR_OK; 301 } 302 303 /** put type, class, ttl into rr buffer */ 304 static int 305 rrinternal_write_typeclassttl(sldns_buffer* strbuf, uint8_t* rr, size_t len, 306 size_t dname_len, uint16_t tp, uint16_t cl, uint32_t ttl, int question) 307 { 308 if(question) { 309 /* question is : name, type, class */ 310 if(dname_len + 4 > len) 311 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 312 sldns_buffer_position(strbuf)); 313 sldns_write_uint16(rr+dname_len, tp); 314 sldns_write_uint16(rr+dname_len+2, cl); 315 return LDNS_WIREPARSE_ERR_OK; 316 } 317 318 /* type(2), class(2), ttl(4), rdatalen(2 (later)) = 10 */ 319 if(dname_len + 10 > len) 320 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 321 sldns_buffer_position(strbuf)); 322 sldns_write_uint16(rr+dname_len, tp); 323 sldns_write_uint16(rr+dname_len+2, cl); 324 sldns_write_uint32(rr+dname_len+4, ttl); 325 sldns_write_uint16(rr+dname_len+8, 0); /* rdatalen placeholder */ 326 return LDNS_WIREPARSE_ERR_OK; 327 } 328 329 /** find delimiters for type */ 330 static const char* 331 rrinternal_get_delims(sldns_rdf_type rdftype, uint16_t r_cnt, uint16_t r_max) 332 { 333 switch(rdftype) { 334 case LDNS_RDF_TYPE_B64 : 335 case LDNS_RDF_TYPE_HEX : /* These rdf types may con- */ 336 case LDNS_RDF_TYPE_LOC : /* tain whitespace, only if */ 337 case LDNS_RDF_TYPE_WKS : /* it is the last rd field. */ 338 case LDNS_RDF_TYPE_IPSECKEY : 339 case LDNS_RDF_TYPE_NSEC : if (r_cnt == r_max - 1) { 340 return "\n"; 341 } 342 break; 343 default : break; 344 } 345 return "\n\t "; 346 } 347 348 /* Syntactic sugar for sldns_rr_new_frm_str_internal */ 349 static int 350 sldns_rdf_type_maybe_quoted(sldns_rdf_type rdf_type) 351 { 352 return rdf_type == LDNS_RDF_TYPE_STR || 353 rdf_type == LDNS_RDF_TYPE_LONG_STR; 354 } 355 356 /** see if rdata is quoted */ 357 static int 358 rrinternal_get_quoted(sldns_buffer* strbuf, const char** delimiters, 359 sldns_rdf_type rdftype) 360 { 361 if(sldns_rdf_type_maybe_quoted(rdftype) && 362 sldns_buffer_remaining(strbuf) > 0) { 363 364 /* skip spaces */ 365 while(sldns_buffer_remaining(strbuf) > 0 && 366 *(sldns_buffer_current(strbuf)) == ' ') { 367 sldns_buffer_skip(strbuf, 1); 368 } 369 370 if(sldns_buffer_remaining(strbuf) > 0 && 371 *(sldns_buffer_current(strbuf)) == '\"') { 372 *delimiters = "\"\0"; 373 sldns_buffer_skip(strbuf, 1); 374 return 1; 375 } 376 } 377 return 0; 378 } 379 380 /** spool hex data into rdata */ 381 static int 382 rrinternal_spool_hex(char* token, uint8_t* rr, size_t rr_len, 383 size_t rr_cur_len, size_t* cur_hex_data_size, size_t hex_data_size) 384 { 385 char* p = token; 386 while(*p) { 387 if(isspace((unsigned char)*p)) { 388 p++; 389 continue; 390 } 391 if(!isxdigit((unsigned char)*p)) 392 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 393 p-token); 394 if(*cur_hex_data_size >= hex_data_size) 395 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 396 p-token); 397 /* extra robust check */ 398 if(rr_cur_len+(*cur_hex_data_size)/2 >= rr_len) 399 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 400 p-token); 401 /* see if 16s or 1s */ 402 if( ((*cur_hex_data_size)&1) == 0) { 403 rr[rr_cur_len+(*cur_hex_data_size)/2] = 404 (uint8_t)sldns_hexdigit_to_int(*p)*16; 405 } else { 406 rr[rr_cur_len+(*cur_hex_data_size)/2] += 407 (uint8_t)sldns_hexdigit_to_int(*p); 408 } 409 p++; 410 (*cur_hex_data_size)++; 411 } 412 return LDNS_WIREPARSE_ERR_OK; 413 } 414 415 /** read unknown rr type format */ 416 static int 417 rrinternal_parse_unknown(sldns_buffer* strbuf, char* token, size_t token_len, 418 uint8_t* rr, size_t* rr_len, size_t* rr_cur_len, size_t pre_data_pos) 419 { 420 const char* delim = "\n\t "; 421 size_t hex_data_size, cur_hex_data_size; 422 /* go back to before \# 423 * and skip it while setting delimiters better 424 */ 425 sldns_buffer_set_position(strbuf, pre_data_pos); 426 if(sldns_bget_token(strbuf, token, delim, token_len) == -1) 427 return LDNS_WIREPARSE_ERR_GENERAL; /* should not fail */ 428 /* read rdata octet length */ 429 if(sldns_bget_token(strbuf, token, delim, token_len) == -1) { 430 /* something goes very wrong here */ 431 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 432 sldns_buffer_position(strbuf)); 433 } 434 hex_data_size = (size_t)atoi(token); 435 if(hex_data_size > LDNS_MAX_RDFLEN || 436 *rr_cur_len + hex_data_size > *rr_len) { 437 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 438 sldns_buffer_position(strbuf)); 439 } 440 /* copy hex chars into hex str (2 chars per byte) */ 441 hex_data_size *= 2; 442 cur_hex_data_size = 0; 443 while(cur_hex_data_size < hex_data_size) { 444 int status; 445 ssize_t c = sldns_bget_token(strbuf, token, delim, token_len); 446 if((status = rrinternal_spool_hex(token, rr, *rr_len, 447 *rr_cur_len, &cur_hex_data_size, hex_data_size)) != 0) 448 return RET_ERR_SHIFT(status, 449 sldns_buffer_position(strbuf)-strlen(token)); 450 if(c == -1) { 451 if(cur_hex_data_size != hex_data_size) 452 return RET_ERR( 453 LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 454 sldns_buffer_position(strbuf)); 455 break; 456 } 457 } 458 *rr_cur_len += hex_data_size/2; 459 return LDNS_WIREPARSE_ERR_OK; 460 } 461 462 /** parse normal RR rdata element */ 463 static int 464 rrinternal_parse_rdf(sldns_buffer* strbuf, char* token, size_t token_len, 465 uint8_t* rr, size_t rr_len, size_t* rr_cur_len, sldns_rdf_type rdftype, 466 uint16_t rr_type, uint16_t r_cnt, uint16_t r_max, size_t dname_len, 467 uint8_t* origin, size_t origin_len) 468 { 469 size_t len; 470 int status; 471 472 switch(rdftype) { 473 case LDNS_RDF_TYPE_DNAME: 474 /* check if the origin should be used or concatenated */ 475 if(strcmp(token, "@") == 0) { 476 uint8_t* tocopy; 477 size_t copylen; 478 if(origin) { 479 copylen = origin_len; 480 tocopy = origin; 481 } else if(rr_type == LDNS_RR_TYPE_SOA) { 482 copylen = dname_len; 483 tocopy = rr; /* copy rr owner name */ 484 } else { 485 copylen = 1; 486 tocopy = (uint8_t*)"\0"; 487 } 488 if((*rr_cur_len) + copylen > rr_len) 489 return RET_ERR( 490 LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 491 sldns_buffer_position(strbuf)); 492 memmove(rr+*rr_cur_len, tocopy, copylen); 493 (*rr_cur_len) += copylen; 494 } else { 495 size_t dlen = rr_len - (*rr_cur_len); 496 int s = sldns_str2wire_dname_buf_origin(token, 497 rr+*rr_cur_len, &dlen, origin, origin_len); 498 if(s) return RET_ERR_SHIFT(s, 499 sldns_buffer_position(strbuf)-strlen(token)); 500 (*rr_cur_len) += dlen; 501 } 502 return LDNS_WIREPARSE_ERR_OK; 503 504 case LDNS_RDF_TYPE_HEX: 505 case LDNS_RDF_TYPE_B64: 506 /* When this is the last rdata field, then the 507 * rest should be read in (cause then these 508 * rdf types may contain spaces). */ 509 if(r_cnt == r_max - 1) { 510 size_t tlen = strlen(token); 511 (void)sldns_bget_token(strbuf, token+tlen, "\n", 512 token_len - tlen); 513 } 514 break; 515 default: 516 break; 517 } 518 519 len = rr_len - (*rr_cur_len); 520 if((status=sldns_str2wire_rdf_buf(token, rr+(*rr_cur_len), &len, 521 rdftype)) != 0) 522 return RET_ERR_SHIFT(status, 523 sldns_buffer_position(strbuf)-strlen(token)); 524 *rr_cur_len += len; 525 return LDNS_WIREPARSE_ERR_OK; 526 } 527 528 /** 529 * Parse one rdf token. Takes care of quotes and parenthesis. 530 */ 531 static int 532 sldns_parse_rdf_token(sldns_buffer* strbuf, char* token, size_t token_len, 533 int* quoted, int* parens, size_t* pre_data_pos, 534 const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen) 535 { 536 size_t slen; 537 538 /* skip spaces */ 539 while(sldns_buffer_remaining(strbuf) > 0 && !*quoted && 540 *(sldns_buffer_current(strbuf)) == ' ') { 541 sldns_buffer_skip(strbuf, 1); 542 } 543 544 *pre_data_pos = sldns_buffer_position(strbuf); 545 if(sldns_bget_token_par(strbuf, token, (*quoted)?"\"":delimiters, 546 token_len, parens, (*quoted)?NULL:" \t") == -1) { 547 return 0; 548 } 549 slen = strlen(token); 550 /* check if not quoted yet, and we have encountered quotes */ 551 if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) && 552 slen >= 2 && 553 (token[0] == '"' || token[0] == '\'') && 554 (token[slen-1] == '"' || token[slen-1] == '\'')) { 555 /* move token two smaller (quotes) with endnull */ 556 memmove(token, token+1, slen-2); 557 token[slen-2] = 0; 558 slen -= 2; 559 *quoted = 1; 560 } else if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) && 561 slen >= 2 && 562 (token[0] == '"' || token[0] == '\'')) { 563 /* got the start quote (remove it) but read remainder 564 * of quoted string as well into remainder of token */ 565 memmove(token, token+1, slen-1); 566 token[slen-1] = 0; 567 slen -= 1; 568 *quoted = 1; 569 /* rewind buffer over skipped whitespace */ 570 while(sldns_buffer_position(strbuf) > 0 && 571 (sldns_buffer_current(strbuf)[-1] == ' ' || 572 sldns_buffer_current(strbuf)[-1] == '\t')) { 573 sldns_buffer_skip(strbuf, -1); 574 } 575 if(sldns_bget_token_par(strbuf, token+slen, 576 "\"", token_len-slen, 577 parens, NULL) == -1) { 578 return 0; 579 } 580 slen = strlen(token); 581 } 582 *token_strlen = slen; 583 return 1; 584 } 585 586 /** Add space and one more rdf token onto the existing token string. */ 587 static int 588 sldns_affix_token(sldns_buffer* strbuf, char* token, size_t* token_len, 589 int* quoted, int* parens, size_t* pre_data_pos, 590 const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen) 591 { 592 size_t addlen = *token_len - *token_strlen; 593 size_t addstrlen = 0; 594 595 /* add space */ 596 if(addlen < 1) return 0; 597 token[*token_strlen] = ' '; 598 token[++(*token_strlen)] = 0; 599 600 /* read another token */ 601 addlen = *token_len - *token_strlen; 602 if(!sldns_parse_rdf_token(strbuf, token+*token_strlen, addlen, quoted, 603 parens, pre_data_pos, delimiters, rdftype, &addstrlen)) 604 return 0; 605 (*token_strlen) += addstrlen; 606 return 1; 607 } 608 609 /** parse rdata from string into rr buffer(-remainder after dname). */ 610 static int 611 rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len, 612 uint8_t* rr, size_t* rr_len, size_t dname_len, uint16_t rr_type, 613 uint8_t* origin, size_t origin_len) 614 { 615 const sldns_rr_descriptor *desc = sldns_rr_descript((uint16_t)rr_type); 616 uint16_t r_cnt, r_min, r_max; 617 size_t rr_cur_len = dname_len + 10, pre_data_pos, token_strlen; 618 int was_unknown_rr_format = 0, parens = 0, status, quoted; 619 const char* delimiters; 620 sldns_rdf_type rdftype; 621 /* a desc is always returned */ 622 if(!desc) return LDNS_WIREPARSE_ERR_GENERAL; 623 r_max = sldns_rr_descriptor_maximum(desc); 624 r_min = sldns_rr_descriptor_minimum(desc); 625 /* robust check */ 626 if(rr_cur_len > *rr_len) 627 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 628 sldns_buffer_position(strbuf)); 629 630 /* because number of fields can be variable, we can't rely on 631 * _maximum() only */ 632 for(r_cnt=0; r_cnt < r_max; r_cnt++) { 633 rdftype = sldns_rr_descriptor_field_type(desc, r_cnt); 634 delimiters = rrinternal_get_delims(rdftype, r_cnt, r_max); 635 quoted = rrinternal_get_quoted(strbuf, &delimiters, rdftype); 636 637 if(!sldns_parse_rdf_token(strbuf, token, token_len, "ed, 638 &parens, &pre_data_pos, delimiters, rdftype, 639 &token_strlen)) 640 break; 641 642 /* rfc3597 specifies that any type can be represented 643 * with \# method, which can contain spaces... 644 * it does specify size though... */ 645 646 /* unknown RR data */ 647 if(token_strlen>=2 && strncmp(token, "\\#", 2) == 0 && 648 !quoted && (token_strlen == 2 || token[2]==' ')) { 649 was_unknown_rr_format = 1; 650 if((status=rrinternal_parse_unknown(strbuf, token, 651 token_len, rr, rr_len, &rr_cur_len, 652 pre_data_pos)) != 0) 653 return status; 654 } else if(token_strlen > 0 || quoted) { 655 if(rdftype == LDNS_RDF_TYPE_HIP) { 656 /* affix the HIT and PK fields, with a space */ 657 if(!sldns_affix_token(strbuf, token, 658 &token_len, "ed, &parens, 659 &pre_data_pos, delimiters, 660 rdftype, &token_strlen)) 661 break; 662 if(!sldns_affix_token(strbuf, token, 663 &token_len, "ed, &parens, 664 &pre_data_pos, delimiters, 665 rdftype, &token_strlen)) 666 break; 667 } 668 669 /* normal RR */ 670 if((status=rrinternal_parse_rdf(strbuf, token, 671 token_len, rr, *rr_len, &rr_cur_len, rdftype, 672 rr_type, r_cnt, r_max, dname_len, origin, 673 origin_len)) != 0) { 674 return status; 675 } 676 } 677 } 678 if(!was_unknown_rr_format && r_cnt+1 < r_min) { 679 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, 680 sldns_buffer_position(strbuf)); 681 } 682 while(parens != 0) { 683 /* read remainder, must be "" */ 684 if(sldns_bget_token_par(strbuf, token, "\n", token_len, 685 &parens, " \t") == -1) { 686 if(parens != 0) 687 return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS, 688 sldns_buffer_position(strbuf)); 689 break; 690 } 691 if(strcmp(token, "") != 0) 692 return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS, 693 sldns_buffer_position(strbuf)); 694 } 695 /* write rdata length */ 696 sldns_write_uint16(rr+dname_len+8, rr_cur_len-dname_len-10); 697 *rr_len = rr_cur_len; 698 return LDNS_WIREPARSE_ERR_OK; 699 } 700 701 /* 702 * trailing spaces are allowed 703 * leading spaces are not allowed 704 * allow ttl to be optional 705 * class is optional too 706 * if ttl is missing, and default_ttl is 0, use DEF_TTL 707 * allow ttl to be written as 1d3h 708 * So the RR should look like. e.g. 709 * miek.nl. 3600 IN MX 10 elektron.atoom.net 710 * or 711 * miek.nl. 1h IN MX 10 elektron.atoom.net 712 * or 713 * miek.nl. IN MX 10 elektron.atoom.net 714 */ 715 static int 716 sldns_str2wire_rr_buf_internal(const char* str, uint8_t* rr, size_t* len, 717 size_t* dname_len, uint32_t default_ttl, uint8_t* origin, 718 size_t origin_len, uint8_t* prev, size_t prev_len, int question) 719 { 720 int status; 721 int not_there = 0; 722 char token[LDNS_MAX_RDFLEN+1]; 723 uint32_t ttl = 0; 724 uint16_t tp = 0, cl = 0; 725 size_t ddlen = 0; 726 727 /* string in buffer */ 728 sldns_buffer strbuf; 729 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 730 if(!dname_len) dname_len = &ddlen; 731 732 /* parse the owner */ 733 if((status=rrinternal_get_owner(&strbuf, rr, len, dname_len, origin, 734 origin_len, prev, prev_len, token, sizeof(token))) != 0) 735 return status; 736 737 /* parse the [ttl] [class] <type> */ 738 if((status=rrinternal_get_ttl(&strbuf, token, sizeof(token), 739 ¬_there, &ttl, default_ttl)) != 0) 740 return status; 741 if((status=rrinternal_get_class(&strbuf, token, sizeof(token), 742 ¬_there, &cl)) != 0) 743 return status; 744 if((status=rrinternal_get_type(&strbuf, token, sizeof(token), 745 ¬_there, &tp)) != 0) 746 return status; 747 /* put ttl, class, type into the rr result */ 748 if((status=rrinternal_write_typeclassttl(&strbuf, rr, *len, *dname_len, tp, cl, 749 ttl, question)) != 0) 750 return status; 751 /* for a question-RR we are done, no rdata */ 752 if(question) { 753 *len = *dname_len + 4; 754 return LDNS_WIREPARSE_ERR_OK; 755 } 756 757 /* rdata */ 758 if((status=rrinternal_parse_rdata(&strbuf, token, sizeof(token), 759 rr, len, *dname_len, tp, origin, origin_len)) != 0) 760 return status; 761 762 return LDNS_WIREPARSE_ERR_OK; 763 } 764 765 int sldns_str2wire_rr_buf(const char* str, uint8_t* rr, size_t* len, 766 size_t* dname_len, uint32_t default_ttl, uint8_t* origin, 767 size_t origin_len, uint8_t* prev, size_t prev_len) 768 { 769 return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, 770 default_ttl, origin, origin_len, prev, prev_len, 0); 771 } 772 773 int sldns_str2wire_rr_question_buf(const char* str, uint8_t* rr, size_t* len, 774 size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, 775 size_t prev_len) 776 { 777 return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, 778 0, origin, origin_len, prev, prev_len, 1); 779 } 780 781 uint16_t sldns_wirerr_get_type(uint8_t* rr, size_t len, size_t dname_len) 782 { 783 if(len < dname_len+2) 784 return 0; 785 return sldns_read_uint16(rr+dname_len); 786 } 787 788 uint16_t sldns_wirerr_get_class(uint8_t* rr, size_t len, size_t dname_len) 789 { 790 if(len < dname_len+4) 791 return 0; 792 return sldns_read_uint16(rr+dname_len+2); 793 } 794 795 uint32_t sldns_wirerr_get_ttl(uint8_t* rr, size_t len, size_t dname_len) 796 { 797 if(len < dname_len+8) 798 return 0; 799 return sldns_read_uint32(rr+dname_len+4); 800 } 801 802 uint16_t sldns_wirerr_get_rdatalen(uint8_t* rr, size_t len, size_t dname_len) 803 { 804 if(len < dname_len+10) 805 return 0; 806 return sldns_read_uint16(rr+dname_len+8); 807 } 808 809 uint8_t* sldns_wirerr_get_rdata(uint8_t* rr, size_t len, size_t dname_len) 810 { 811 if(len < dname_len+10) 812 return NULL; 813 return rr+dname_len+10; 814 } 815 816 uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len) 817 { 818 if(len < dname_len+10) 819 return NULL; 820 return rr+dname_len+8; 821 } 822 823 const char* sldns_get_errorstr_parse(int e) 824 { 825 sldns_lookup_table *lt; 826 lt = sldns_lookup_by_id(sldns_wireparse_errors, LDNS_WIREPARSE_ERROR(e)); 827 return lt?lt->name:"unknown error"; 828 } 829 830 /* Strip whitespace from the start and the end of <line>. */ 831 static char * 832 sldns_strip_ws(char *line) 833 { 834 char *s = line, *e; 835 836 for (s = line; *s && isspace((unsigned char)*s); s++) 837 ; 838 for (e = strchr(s, 0); e > s+2 && isspace((unsigned char)e[-1]) && e[-2] != '\\'; e--) 839 ; 840 *e = 0; 841 return s; 842 } 843 844 int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, 845 struct sldns_file_parse_state* parse_state) 846 { 847 char line[LDNS_RR_BUF_SIZE+1]; 848 ssize_t size; 849 850 /* read an entire line in from the file */ 851 if((size = sldns_fget_token_l(in, line, LDNS_PARSE_SKIP_SPACE, 852 LDNS_RR_BUF_SIZE, parse_state?&parse_state->lineno:NULL)) 853 == -1) { 854 /* if last line was empty, we are now at feof, which is not 855 * always a parse error (happens when for instance last line 856 * was a comment) 857 */ 858 return LDNS_WIREPARSE_ERR_SYNTAX; 859 } 860 861 /* we can have the situation, where we've read ok, but still got 862 * no bytes to play with, in this case size is 0 */ 863 if(size == 0) { 864 *len = 0; 865 *dname_len = 0; 866 return LDNS_WIREPARSE_ERR_OK; 867 } 868 869 if(strncmp(line, "$ORIGIN", 7) == 0 && isspace((unsigned char)line[7])) { 870 int s; 871 *len = 0; 872 *dname_len = 0; 873 if(!parse_state) return LDNS_WIREPARSE_ERR_OK; 874 parse_state->origin_len = sizeof(parse_state->origin); 875 s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8), 876 parse_state->origin, &parse_state->origin_len); 877 if(s) parse_state->origin_len = 0; 878 return s; 879 } else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) { 880 const char* end = NULL; 881 *len = 0; 882 *dname_len = 0; 883 if(!parse_state) return LDNS_WIREPARSE_ERR_OK; 884 parse_state->default_ttl = sldns_str2period( 885 sldns_strip_ws(line+5), &end); 886 } else if (strncmp(line, "$INCLUDE", 8) == 0) { 887 *len = 0; 888 *dname_len = 0; 889 return LDNS_WIREPARSE_ERR_INCLUDE; 890 } else { 891 return sldns_str2wire_rr_buf(line, rr, len, dname_len, 892 parse_state?parse_state->default_ttl:0, 893 (parse_state&&parse_state->origin_len)? 894 parse_state->origin:NULL, 895 parse_state->origin_len, 896 (parse_state&&parse_state->prev_rr_len)? 897 parse_state->prev_rr:NULL, 898 parse_state->prev_rr_len); 899 } 900 return LDNS_WIREPARSE_ERR_OK; 901 } 902 903 int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len, 904 sldns_rdf_type rdftype) 905 { 906 switch (rdftype) { 907 case LDNS_RDF_TYPE_DNAME: 908 return sldns_str2wire_dname_buf(str, rd, len); 909 case LDNS_RDF_TYPE_INT8: 910 return sldns_str2wire_int8_buf(str, rd, len); 911 case LDNS_RDF_TYPE_INT16: 912 return sldns_str2wire_int16_buf(str, rd, len); 913 case LDNS_RDF_TYPE_INT32: 914 return sldns_str2wire_int32_buf(str, rd, len); 915 case LDNS_RDF_TYPE_A: 916 return sldns_str2wire_a_buf(str, rd, len); 917 case LDNS_RDF_TYPE_AAAA: 918 return sldns_str2wire_aaaa_buf(str, rd, len); 919 case LDNS_RDF_TYPE_STR: 920 return sldns_str2wire_str_buf(str, rd, len); 921 case LDNS_RDF_TYPE_APL: 922 return sldns_str2wire_apl_buf(str, rd, len); 923 case LDNS_RDF_TYPE_B64: 924 return sldns_str2wire_b64_buf(str, rd, len); 925 case LDNS_RDF_TYPE_B32_EXT: 926 return sldns_str2wire_b32_ext_buf(str, rd, len); 927 case LDNS_RDF_TYPE_HEX: 928 return sldns_str2wire_hex_buf(str, rd, len); 929 case LDNS_RDF_TYPE_NSEC: 930 return sldns_str2wire_nsec_buf(str, rd, len); 931 case LDNS_RDF_TYPE_TYPE: 932 return sldns_str2wire_type_buf(str, rd, len); 933 case LDNS_RDF_TYPE_CLASS: 934 return sldns_str2wire_class_buf(str, rd, len); 935 case LDNS_RDF_TYPE_CERT_ALG: 936 return sldns_str2wire_cert_alg_buf(str, rd, len); 937 case LDNS_RDF_TYPE_ALG: 938 return sldns_str2wire_alg_buf(str, rd, len); 939 case LDNS_RDF_TYPE_TIME: 940 return sldns_str2wire_time_buf(str, rd, len); 941 case LDNS_RDF_TYPE_PERIOD: 942 return sldns_str2wire_period_buf(str, rd, len); 943 case LDNS_RDF_TYPE_LOC: 944 return sldns_str2wire_loc_buf(str, rd, len); 945 case LDNS_RDF_TYPE_WKS: 946 return sldns_str2wire_wks_buf(str, rd, len); 947 case LDNS_RDF_TYPE_NSAP: 948 return sldns_str2wire_nsap_buf(str, rd, len); 949 case LDNS_RDF_TYPE_ATMA: 950 return sldns_str2wire_atma_buf(str, rd, len); 951 case LDNS_RDF_TYPE_IPSECKEY: 952 return sldns_str2wire_ipseckey_buf(str, rd, len); 953 case LDNS_RDF_TYPE_NSEC3_SALT: 954 return sldns_str2wire_nsec3_salt_buf(str, rd, len); 955 case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: 956 return sldns_str2wire_b32_ext_buf(str, rd, len); 957 case LDNS_RDF_TYPE_ILNP64: 958 return sldns_str2wire_ilnp64_buf(str, rd, len); 959 case LDNS_RDF_TYPE_EUI48: 960 return sldns_str2wire_eui48_buf(str, rd, len); 961 case LDNS_RDF_TYPE_EUI64: 962 return sldns_str2wire_eui64_buf(str, rd, len); 963 case LDNS_RDF_TYPE_TAG: 964 return sldns_str2wire_tag_buf(str, rd, len); 965 case LDNS_RDF_TYPE_LONG_STR: 966 return sldns_str2wire_long_str_buf(str, rd, len); 967 case LDNS_RDF_TYPE_HIP: 968 return sldns_str2wire_hip_buf(str, rd, len); 969 case LDNS_RDF_TYPE_INT16_DATA: 970 return sldns_str2wire_int16_data_buf(str, rd, len); 971 case LDNS_RDF_TYPE_UNKNOWN: 972 case LDNS_RDF_TYPE_SERVICE: 973 return LDNS_WIREPARSE_ERR_NOT_IMPL; 974 case LDNS_RDF_TYPE_NONE: 975 default: 976 break; 977 } 978 return LDNS_WIREPARSE_ERR_GENERAL; 979 } 980 981 int sldns_str2wire_int8_buf(const char* str, uint8_t* rd, size_t* len) 982 { 983 char* end; 984 uint8_t r = (uint8_t)strtol((char*)str, &end, 10); 985 if(*end != 0) 986 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 987 if(*len < 1) 988 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 989 rd[0] = r; 990 *len = 1; 991 return LDNS_WIREPARSE_ERR_OK; 992 } 993 994 int sldns_str2wire_int16_buf(const char* str, uint8_t* rd, size_t* len) 995 { 996 char* end; 997 uint16_t r = (uint16_t)strtol((char*)str, &end, 10); 998 if(*end != 0) 999 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1000 if(*len < 2) 1001 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1002 sldns_write_uint16(rd, r); 1003 *len = 2; 1004 return LDNS_WIREPARSE_ERR_OK; 1005 } 1006 1007 int sldns_str2wire_int32_buf(const char* str, uint8_t* rd, size_t* len) 1008 { 1009 char* end; 1010 uint32_t r; 1011 errno = 0; /* must set to zero before call, 1012 note race condition on errno */ 1013 if(*str == '-') 1014 r = (uint32_t)strtol((char*)str, &end, 10); 1015 else r = (uint32_t)strtoul((char*)str, &end, 10); 1016 if(*end != 0) 1017 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1018 if(errno == ERANGE) 1019 return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW; 1020 if(*len < 4) 1021 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1022 sldns_write_uint32(rd, r); 1023 *len = 4; 1024 return LDNS_WIREPARSE_ERR_OK; 1025 } 1026 1027 int sldns_str2wire_a_buf(const char* str, uint8_t* rd, size_t* len) 1028 { 1029 struct in_addr address; 1030 if(inet_pton(AF_INET, (char*)str, &address) != 1) 1031 return LDNS_WIREPARSE_ERR_SYNTAX_IP4; 1032 if(*len < sizeof(address)) 1033 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1034 memmove(rd, &address, sizeof(address)); 1035 *len = sizeof(address); 1036 return LDNS_WIREPARSE_ERR_OK; 1037 } 1038 1039 int sldns_str2wire_aaaa_buf(const char* str, uint8_t* rd, size_t* len) 1040 { 1041 #ifdef AF_INET6 1042 uint8_t address[LDNS_IP6ADDRLEN + 1]; 1043 if(inet_pton(AF_INET6, (char*)str, address) != 1) 1044 return LDNS_WIREPARSE_ERR_SYNTAX_IP6; 1045 if(*len < LDNS_IP6ADDRLEN) 1046 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1047 memmove(rd, address, LDNS_IP6ADDRLEN); 1048 *len = LDNS_IP6ADDRLEN; 1049 return LDNS_WIREPARSE_ERR_OK; 1050 #else 1051 return LDNS_WIREPARSE_ERR_NOT_IMPL; 1052 #endif 1053 } 1054 1055 int sldns_str2wire_str_buf(const char* str, uint8_t* rd, size_t* len) 1056 { 1057 uint8_t ch = 0; 1058 size_t sl = 0; 1059 const char* s = str; 1060 /* skip length byte */ 1061 if(*len < 1) 1062 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1063 1064 /* read characters */ 1065 while(sldns_parse_char(&ch, &s)) { 1066 if(sl >= 255) 1067 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, s-str); 1068 if(*len < sl+1) 1069 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1070 s-str); 1071 rd[++sl] = ch; 1072 } 1073 if(!s) 1074 return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; 1075 rd[0] = (uint8_t)sl; 1076 *len = sl+1; 1077 return LDNS_WIREPARSE_ERR_OK; 1078 } 1079 1080 int sldns_str2wire_apl_buf(const char* str, uint8_t* rd, size_t* len) 1081 { 1082 const char *my_str = str; 1083 1084 char my_ip_str[64]; 1085 size_t ip_str_len; 1086 1087 uint16_t family; 1088 int negation; 1089 size_t adflength = 0; 1090 uint8_t data[16+4]; 1091 uint8_t prefix; 1092 size_t i; 1093 1094 if(*my_str == '\0') { 1095 /* empty APL element, no data, no string */ 1096 *len = 0; 1097 return LDNS_WIREPARSE_ERR_OK; 1098 } 1099 1100 /* [!]afi:address/prefix */ 1101 if (strlen(my_str) < 2 1102 || strchr(my_str, ':') == NULL 1103 || strchr(my_str, '/') == NULL 1104 || strchr(my_str, ':') > strchr(my_str, '/')) { 1105 return LDNS_WIREPARSE_ERR_INVALID_STR; 1106 } 1107 1108 if (my_str[0] == '!') { 1109 negation = 1; 1110 my_str += 1; 1111 } else { 1112 negation = 0; 1113 } 1114 1115 family = (uint16_t) atoi(my_str); 1116 1117 my_str = strchr(my_str, ':') + 1; 1118 1119 /* need ip addr and only ip addr for inet_pton */ 1120 ip_str_len = (size_t) (strchr(my_str, '/') - my_str); 1121 if(ip_str_len+1 > sizeof(my_ip_str)) 1122 return LDNS_WIREPARSE_ERR_INVALID_STR; 1123 (void)strlcpy(my_ip_str, my_str, sizeof(my_ip_str)); 1124 my_ip_str[ip_str_len] = 0; 1125 1126 if (family == 1) { 1127 /* ipv4 */ 1128 if(inet_pton(AF_INET, my_ip_str, data+4) == 0) 1129 return LDNS_WIREPARSE_ERR_INVALID_STR; 1130 for (i = 0; i < 4; i++) { 1131 if (data[i+4] != 0) { 1132 adflength = i + 1; 1133 } 1134 } 1135 } else if (family == 2) { 1136 /* ipv6 */ 1137 if (inet_pton(AF_INET6, my_ip_str, data+4) == 0) 1138 return LDNS_WIREPARSE_ERR_INVALID_STR; 1139 for (i = 0; i < 16; i++) { 1140 if (data[i+4] != 0) { 1141 adflength = i + 1; 1142 } 1143 } 1144 } else { 1145 /* unknown family */ 1146 return LDNS_WIREPARSE_ERR_INVALID_STR; 1147 } 1148 1149 my_str = strchr(my_str, '/') + 1; 1150 prefix = (uint8_t) atoi(my_str); 1151 1152 sldns_write_uint16(data, family); 1153 data[2] = prefix; 1154 data[3] = (uint8_t)adflength; 1155 if (negation) { 1156 /* set bit 1 of byte 3 */ 1157 data[3] = data[3] | 0x80; 1158 } 1159 1160 if(*len < 4+adflength) 1161 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1162 memmove(rd, data, 4+adflength); 1163 *len = 4+adflength; 1164 return LDNS_WIREPARSE_ERR_OK; 1165 } 1166 1167 int sldns_str2wire_b64_buf(const char* str, uint8_t* rd, size_t* len) 1168 { 1169 size_t sz = sldns_b64_pton_calculate_size(strlen(str)); 1170 int n; 1171 if(*len < sz) 1172 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1173 n = sldns_b64_pton(str, rd, *len); 1174 if(n < 0) 1175 return LDNS_WIREPARSE_ERR_SYNTAX_B64; 1176 *len = (size_t)n; 1177 return LDNS_WIREPARSE_ERR_OK; 1178 } 1179 1180 int sldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len) 1181 { 1182 size_t slen = strlen(str); 1183 size_t sz = sldns_b32_pton_calculate_size(slen); 1184 int n; 1185 if(*len < 1+sz) 1186 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1187 rd[0] = (uint8_t)sz; 1188 n = sldns_b32_pton_extended_hex(str, slen, rd+1, *len-1); 1189 if(n < 0) 1190 return LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT; 1191 *len = (size_t)n+1; 1192 return LDNS_WIREPARSE_ERR_OK; 1193 } 1194 1195 int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len) 1196 { 1197 const char* s = str; 1198 size_t dlen = 0; /* number of hexdigits parsed */ 1199 while(*s) { 1200 if(isspace((unsigned char)*s)) { 1201 s++; 1202 continue; 1203 } 1204 if(!isxdigit((unsigned char)*s)) 1205 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1206 if(*len < dlen/2 + 1) 1207 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1208 s-str); 1209 if((dlen&1)==0) 1210 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1211 else rd[dlen/2] += (uint8_t)sldns_hexdigit_to_int(*s++); 1212 dlen++; 1213 } 1214 if((dlen&1)!=0) 1215 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1216 *len = dlen/2; 1217 return LDNS_WIREPARSE_ERR_OK; 1218 } 1219 1220 int sldns_str2wire_nsec_buf(const char* str, uint8_t* rd, size_t* len) 1221 { 1222 const char *delim = "\n\t "; 1223 char token[64]; /* for a type name */ 1224 size_t type_count = 0; 1225 int block; 1226 size_t used = 0; 1227 uint16_t maxtype = 0; 1228 uint8_t typebits[8192]; /* 65536 bits */ 1229 uint8_t window_in_use[256]; 1230 1231 /* string in buffer */ 1232 sldns_buffer strbuf; 1233 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 1234 1235 /* parse the types */ 1236 memset(typebits, 0, sizeof(typebits)); 1237 memset(window_in_use, 0, sizeof(window_in_use)); 1238 while(sldns_buffer_remaining(&strbuf) > 0 && 1239 sldns_bget_token(&strbuf, token, delim, sizeof(token)) != -1) { 1240 uint16_t t = sldns_get_rr_type_by_name(token); 1241 if(token[0] == 0) 1242 continue; 1243 if(t == 0 && strcmp(token, "TYPE0") != 0) 1244 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 1245 sldns_buffer_position(&strbuf)); 1246 typebits[t/8] |= (0x80>>(t%8)); 1247 window_in_use[t/256] = 1; 1248 type_count++; 1249 if(t > maxtype) maxtype = t; 1250 } 1251 1252 /* empty NSEC bitmap */ 1253 if(type_count == 0) { 1254 *len = 0; 1255 return LDNS_WIREPARSE_ERR_OK; 1256 } 1257 1258 /* encode windows {u8 windowblock, u8 bitmaplength, 0-32u8 bitmap}, 1259 * block is 0-255 upper octet of types, length if 0-32. */ 1260 for(block = 0; block <= (int)maxtype/256; block++) { 1261 int i, blocklen = 0; 1262 if(!window_in_use[block]) 1263 continue; 1264 for(i=0; i<32; i++) { 1265 if(typebits[block*32+i] != 0) 1266 blocklen = i+1; 1267 } 1268 if(blocklen == 0) 1269 continue; /* empty window should have been !in_use */ 1270 if(used+blocklen+2 > *len) 1271 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1272 rd[used+0] = (uint8_t)block; 1273 rd[used+1] = (uint8_t)blocklen; 1274 for(i=0; i<blocklen; i++) { 1275 rd[used+2+i] = typebits[block*32+i]; 1276 } 1277 used += blocklen+2; 1278 } 1279 *len = used; 1280 return LDNS_WIREPARSE_ERR_OK; 1281 } 1282 1283 int sldns_str2wire_type_buf(const char* str, uint8_t* rd, size_t* len) 1284 { 1285 uint16_t t = sldns_get_rr_type_by_name(str); 1286 if(t == 0 && strcmp(str, "TYPE0") != 0) 1287 return LDNS_WIREPARSE_ERR_SYNTAX_TYPE; 1288 if(*len < 2) 1289 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1290 sldns_write_uint16(rd, t); 1291 *len = 2; 1292 return LDNS_WIREPARSE_ERR_OK; 1293 } 1294 1295 int sldns_str2wire_class_buf(const char* str, uint8_t* rd, size_t* len) 1296 { 1297 uint16_t c = sldns_get_rr_class_by_name(str); 1298 if(c == 0 && strcmp(str, "CLASS0") != 0) 1299 return LDNS_WIREPARSE_ERR_SYNTAX_CLASS; 1300 if(*len < 2) 1301 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1302 sldns_write_uint16(rd, c); 1303 *len = 2; 1304 return LDNS_WIREPARSE_ERR_OK; 1305 } 1306 1307 /* An certificate alg field can either be specified as a 8 bits number 1308 * or by its symbolic name. Handle both */ 1309 int sldns_str2wire_cert_alg_buf(const char* str, uint8_t* rd, size_t* len) 1310 { 1311 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_cert_algorithms, 1312 str); 1313 if(*len < 2) 1314 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1315 if(lt) { 1316 sldns_write_uint16(rd, (uint16_t)lt->id); 1317 } else { 1318 int s = sldns_str2wire_int16_buf(str, rd, len); 1319 if(s) return s; 1320 if(sldns_read_uint16(rd) == 0) 1321 return LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM; 1322 } 1323 *len = 2; 1324 return LDNS_WIREPARSE_ERR_OK; 1325 } 1326 1327 /* An alg field can either be specified as a 8 bits number 1328 * or by its symbolic name. Handle both */ 1329 int sldns_str2wire_alg_buf(const char* str, uint8_t* rd, size_t* len) 1330 { 1331 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_algorithms, str); 1332 if(*len < 1) 1333 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1334 if(lt) { 1335 rd[0] = (uint8_t)lt->id; 1336 *len = 1; 1337 } else { 1338 /* try as-is (a number) */ 1339 return sldns_str2wire_int8_buf(str, rd, len); 1340 } 1341 return LDNS_WIREPARSE_ERR_OK; 1342 } 1343 1344 int sldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len) 1345 { 1346 /* convert a time YYYYDDMMHHMMSS to wireformat */ 1347 struct tm tm; 1348 if(*len < 4) 1349 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1350 1351 /* Try to scan the time... */ 1352 memset(&tm, 0, sizeof(tm)); 1353 if (strlen(str) == 14 && sscanf(str, "%4d%2d%2d%2d%2d%2d", 1354 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 1355 &tm.tm_min, &tm.tm_sec) == 6) { 1356 tm.tm_year -= 1900; 1357 tm.tm_mon--; 1358 /* Check values */ 1359 if (tm.tm_year < 70) 1360 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1361 if (tm.tm_mon < 0 || tm.tm_mon > 11) 1362 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1363 if (tm.tm_mday < 1 || tm.tm_mday > 31) 1364 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1365 if (tm.tm_hour < 0 || tm.tm_hour > 23) 1366 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1367 if (tm.tm_min < 0 || tm.tm_min > 59) 1368 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1369 if (tm.tm_sec < 0 || tm.tm_sec > 59) 1370 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 1371 1372 sldns_write_uint32(rd, sldns_mktime_from_utc(&tm)); 1373 } else { 1374 /* handle it as 32 bits timestamp */ 1375 char *end; 1376 uint32_t l = (uint32_t)strtol((char*)str, &end, 10); 1377 if(*end != 0) 1378 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TIME, 1379 end-(char*)str); 1380 sldns_write_uint32(rd, l); 1381 } 1382 *len = 4; 1383 return LDNS_WIREPARSE_ERR_OK; 1384 } 1385 1386 int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len) 1387 { 1388 const char* end; 1389 uint32_t p = sldns_str2period(str, &end); 1390 if(*end != 0) 1391 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str); 1392 if(*len < 4) 1393 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1394 sldns_write_uint32(rd, p); 1395 *len = 4; 1396 return LDNS_WIREPARSE_ERR_OK; 1397 } 1398 1399 /** read "<digits>[.<digits>][mM]" into mantissa exponent format for LOC type */ 1400 static int 1401 loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) 1402 { 1403 uint32_t meters = 0, cm = 0, val; 1404 while (isblank((unsigned char)*my_str)) { 1405 my_str++; 1406 } 1407 meters = (uint32_t)strtol(my_str, &my_str, 10); 1408 if (*my_str == '.') { 1409 my_str++; 1410 cm = (uint32_t)strtol(my_str, &my_str, 10); 1411 } 1412 if (meters >= 1) { 1413 *e = 2; 1414 val = meters; 1415 } else { 1416 *e = 0; 1417 val = cm; 1418 } 1419 while(val >= 10) { 1420 (*e)++; 1421 val /= 10; 1422 } 1423 *m = (uint8_t)val; 1424 1425 if (*e > 9) 1426 return 0; 1427 if (*my_str == 'm' || *my_str == 'M') { 1428 my_str++; 1429 } 1430 *endstr = my_str; 1431 return 1; 1432 } 1433 1434 int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len) 1435 { 1436 uint32_t latitude = 0; 1437 uint32_t longitude = 0; 1438 uint32_t altitude = 0; 1439 1440 uint32_t equator = (uint32_t)1<<31; /* 2**31 */ 1441 1442 /* only support version 0 */ 1443 uint32_t h = 0; 1444 uint32_t m = 0; 1445 uint8_t size_b = 1, size_e = 2; 1446 uint8_t horiz_pre_b = 1, horiz_pre_e = 6; 1447 uint8_t vert_pre_b = 1, vert_pre_e = 3; 1448 1449 double s = 0.0; 1450 int northerness; 1451 int easterness; 1452 1453 char *my_str = (char *) str; 1454 1455 if (isdigit((unsigned char) *my_str)) { 1456 h = (uint32_t) strtol(my_str, &my_str, 10); 1457 } else { 1458 return LDNS_WIREPARSE_ERR_INVALID_STR; 1459 } 1460 1461 while (isblank((unsigned char) *my_str)) { 1462 my_str++; 1463 } 1464 1465 if (isdigit((unsigned char) *my_str)) { 1466 m = (uint32_t) strtol(my_str, &my_str, 10); 1467 } else if (*my_str == 'N' || *my_str == 'S') { 1468 goto north; 1469 } else { 1470 return LDNS_WIREPARSE_ERR_INVALID_STR; 1471 } 1472 1473 while (isblank((unsigned char) *my_str)) { 1474 my_str++; 1475 } 1476 1477 if (isdigit((unsigned char) *my_str)) { 1478 s = strtod(my_str, &my_str); 1479 } 1480 1481 /* skip blanks before norterness */ 1482 while (isblank((unsigned char) *my_str)) { 1483 my_str++; 1484 } 1485 1486 north: 1487 if (*my_str == 'N') { 1488 northerness = 1; 1489 } else if (*my_str == 'S') { 1490 northerness = 0; 1491 } else { 1492 return LDNS_WIREPARSE_ERR_INVALID_STR; 1493 } 1494 1495 my_str++; 1496 1497 /* store number */ 1498 s = 1000.0 * s; 1499 /* add a little to make floor in conversion a round */ 1500 s += 0.0005; 1501 latitude = (uint32_t) s; 1502 latitude += 1000 * 60 * m; 1503 latitude += 1000 * 60 * 60 * h; 1504 if (northerness) { 1505 latitude = equator + latitude; 1506 } else { 1507 latitude = equator - latitude; 1508 } 1509 while (isblank((unsigned char)*my_str)) { 1510 my_str++; 1511 } 1512 1513 if (isdigit((unsigned char) *my_str)) { 1514 h = (uint32_t) strtol(my_str, &my_str, 10); 1515 } else { 1516 return LDNS_WIREPARSE_ERR_INVALID_STR; 1517 } 1518 1519 while (isblank((unsigned char) *my_str)) { 1520 my_str++; 1521 } 1522 1523 if (isdigit((unsigned char) *my_str)) { 1524 m = (uint32_t) strtol(my_str, &my_str, 10); 1525 } else if (*my_str == 'E' || *my_str == 'W') { 1526 goto east; 1527 } else { 1528 return LDNS_WIREPARSE_ERR_INVALID_STR; 1529 } 1530 1531 while (isblank((unsigned char)*my_str)) { 1532 my_str++; 1533 } 1534 1535 if (isdigit((unsigned char) *my_str)) { 1536 s = strtod(my_str, &my_str); 1537 } 1538 1539 /* skip blanks before easterness */ 1540 while (isblank((unsigned char)*my_str)) { 1541 my_str++; 1542 } 1543 1544 east: 1545 if (*my_str == 'E') { 1546 easterness = 1; 1547 } else if (*my_str == 'W') { 1548 easterness = 0; 1549 } else { 1550 return LDNS_WIREPARSE_ERR_INVALID_STR; 1551 } 1552 1553 my_str++; 1554 1555 /* store number */ 1556 s *= 1000.0; 1557 /* add a little to make floor in conversion a round */ 1558 s += 0.0005; 1559 longitude = (uint32_t) s; 1560 longitude += 1000 * 60 * m; 1561 longitude += 1000 * 60 * 60 * h; 1562 1563 if (easterness) { 1564 longitude += equator; 1565 } else { 1566 longitude = equator - longitude; 1567 } 1568 1569 altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + 1570 10000000.0 + 0.5); 1571 if (*my_str == 'm' || *my_str == 'M') { 1572 my_str++; 1573 } 1574 1575 if (strlen(my_str) > 0) { 1576 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) 1577 return LDNS_WIREPARSE_ERR_INVALID_STR; 1578 } 1579 1580 if (strlen(my_str) > 0) { 1581 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) 1582 return LDNS_WIREPARSE_ERR_INVALID_STR; 1583 } 1584 1585 if (strlen(my_str) > 0) { 1586 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) 1587 return LDNS_WIREPARSE_ERR_INVALID_STR; 1588 } 1589 1590 if(*len < 16) 1591 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1592 rd[0] = 0; 1593 rd[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); 1594 rd[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); 1595 rd[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); 1596 sldns_write_uint32(rd + 4, latitude); 1597 sldns_write_uint32(rd + 8, longitude); 1598 sldns_write_uint32(rd + 12, altitude); 1599 *len = 16; 1600 return LDNS_WIREPARSE_ERR_OK; 1601 } 1602 1603 static void 1604 ldns_tolower_str(char* s) 1605 { 1606 if(s) { 1607 while(*s) { 1608 *s = (char)tolower((unsigned char)*s); 1609 s++; 1610 } 1611 } 1612 } 1613 1614 int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) 1615 { 1616 int rd_len = 1; 1617 int have_proto = 0; 1618 char token[50], proto_str[50]; 1619 sldns_buffer strbuf; 1620 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 1621 proto_str[0]=0; 1622 1623 /* check we have one byte for proto */ 1624 if(*len < 1) 1625 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1626 1627 while(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) > 0) { 1628 ldns_tolower_str(token); 1629 if(!have_proto) { 1630 struct protoent *p = getprotobyname(token); 1631 have_proto = 1; 1632 if(p) rd[0] = (uint8_t)p->p_proto; 1633 else rd[0] = (uint8_t)atoi(token); 1634 (void)strlcpy(proto_str, token, sizeof(proto_str)); 1635 } else { 1636 int serv_port; 1637 struct servent *serv = getservbyname(token, proto_str); 1638 if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port); 1639 else { 1640 serv_port = atoi(token); 1641 if(serv_port == 0 && strcmp(token, "0") != 0) { 1642 #ifdef HAVE_ENDSERVENT 1643 endservent(); 1644 #endif 1645 #ifdef HAVE_ENDPROTOENT 1646 endprotoent(); 1647 #endif 1648 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 1649 sldns_buffer_position(&strbuf)); 1650 } 1651 if(serv_port < 0 || serv_port > 65535) { 1652 #ifdef HAVE_ENDSERVENT 1653 endservent(); 1654 #endif 1655 #ifdef HAVE_ENDPROTOENT 1656 endprotoent(); 1657 #endif 1658 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 1659 sldns_buffer_position(&strbuf)); 1660 } 1661 } 1662 if(rd_len < 1+serv_port/8+1) { 1663 /* bitmap is larger, init new bytes at 0 */ 1664 if(*len < 1+(size_t)serv_port/8+1) { 1665 #ifdef HAVE_ENDSERVENT 1666 endservent(); 1667 #endif 1668 #ifdef HAVE_ENDPROTOENT 1669 endprotoent(); 1670 #endif 1671 return RET_ERR( 1672 LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1673 sldns_buffer_position(&strbuf)); 1674 } 1675 memset(rd+rd_len, 0, 1+(size_t)serv_port/8+1-rd_len); 1676 rd_len = 1+serv_port/8+1; 1677 } 1678 rd[1+ serv_port/8] |= (1 << (7 - serv_port % 8)); 1679 } 1680 } 1681 *len = (size_t)rd_len; 1682 1683 #ifdef HAVE_ENDSERVENT 1684 endservent(); 1685 #endif 1686 #ifdef HAVE_ENDPROTOENT 1687 endprotoent(); 1688 #endif 1689 return LDNS_WIREPARSE_ERR_OK; 1690 } 1691 1692 int sldns_str2wire_nsap_buf(const char* str, uint8_t* rd, size_t* len) 1693 { 1694 const char* s = str; 1695 size_t slen; 1696 size_t dlen = 0; /* number of hexdigits parsed */ 1697 1698 /* just a hex string with optional dots? */ 1699 if (s[0] != '0' || s[1] != 'x') 1700 return LDNS_WIREPARSE_ERR_INVALID_STR; 1701 s += 2; 1702 slen = strlen(s); 1703 if(slen > LDNS_MAX_RDFLEN*2) 1704 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 1705 while(*s) { 1706 if(isspace((unsigned char)*s) || *s == '.') { 1707 s++; 1708 continue; 1709 } 1710 if(!isxdigit((unsigned char)*s)) 1711 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1712 if(*len < dlen/2 + 1) 1713 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1714 s-str); 1715 if((dlen&1)==0) 1716 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1717 else rd[dlen/2] += sldns_hexdigit_to_int(*s++); 1718 dlen++; 1719 } 1720 if((dlen&1)!=0) 1721 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1722 *len = dlen/2; 1723 return LDNS_WIREPARSE_ERR_OK; 1724 } 1725 1726 int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len) 1727 { 1728 const char* s = str; 1729 size_t slen = strlen(str); 1730 size_t dlen = 0; /* number of hexdigits parsed */ 1731 1732 /* just a hex string with optional dots? */ 1733 /* notimpl e.164 format */ 1734 if(slen > LDNS_MAX_RDFLEN*2) 1735 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 1736 while(*s) { 1737 if(isspace((unsigned char)*s) || *s == '.') { 1738 s++; 1739 continue; 1740 } 1741 if(!isxdigit((unsigned char)*s)) 1742 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1743 if(*len < dlen/2 + 1) 1744 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1745 s-str); 1746 if((dlen&1)==0) 1747 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1748 else rd[dlen/2] += sldns_hexdigit_to_int(*s++); 1749 dlen++; 1750 } 1751 if((dlen&1)!=0) 1752 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1753 *len = dlen/2; 1754 return LDNS_WIREPARSE_ERR_OK; 1755 } 1756 1757 int sldns_str2wire_ipseckey_buf(const char* str, uint8_t* rd, size_t* len) 1758 { 1759 size_t gwlen = 0, keylen = 0; 1760 int s; 1761 uint8_t gwtype; 1762 char token[512]; 1763 sldns_buffer strbuf; 1764 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 1765 1766 if(*len < 3) 1767 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1768 /* precedence */ 1769 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1770 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1771 sldns_buffer_position(&strbuf)); 1772 rd[0] = (uint8_t)atoi(token); 1773 /* gateway_type */ 1774 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1775 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1776 sldns_buffer_position(&strbuf)); 1777 rd[1] = (uint8_t)atoi(token); 1778 gwtype = rd[1]; 1779 /* algorithm */ 1780 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1781 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1782 sldns_buffer_position(&strbuf)); 1783 rd[2] = (uint8_t)atoi(token); 1784 1785 /* gateway */ 1786 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 1787 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1788 sldns_buffer_position(&strbuf)); 1789 if(gwtype == 0) { 1790 /* NOGATEWAY */ 1791 if(strcmp(token, ".") != 0) 1792 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1793 sldns_buffer_position(&strbuf)); 1794 gwlen = 0; 1795 } else if(gwtype == 1) { 1796 /* IP4 */ 1797 gwlen = *len - 3; 1798 s = sldns_str2wire_a_buf(token, rd+3, &gwlen); 1799 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1800 } else if(gwtype == 2) { 1801 /* IP6 */ 1802 gwlen = *len - 3; 1803 s = sldns_str2wire_aaaa_buf(token, rd+3, &gwlen); 1804 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1805 } else if(gwtype == 3) { 1806 /* DNAME */ 1807 gwlen = *len - 3; 1808 s = sldns_str2wire_dname_buf(token, rd+3, &gwlen); 1809 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1810 } else { 1811 /* unknown gateway type */ 1812 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 1813 sldns_buffer_position(&strbuf)); 1814 } 1815 /* double check for size */ 1816 if(*len < 3 + gwlen) 1817 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1818 sldns_buffer_position(&strbuf)); 1819 1820 /* publickey in remainder of strbuf */ 1821 keylen = *len - 3 - gwlen; 1822 s = sldns_str2wire_b64_buf((const char*)sldns_buffer_current(&strbuf), 1823 rd+3+gwlen, &keylen); 1824 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 1825 1826 *len = 3 + gwlen + keylen; 1827 return LDNS_WIREPARSE_ERR_OK; 1828 } 1829 1830 int sldns_str2wire_nsec3_salt_buf(const char* str, uint8_t* rd, size_t* len) 1831 { 1832 int i, salt_length_str = (int)strlen(str); 1833 if (salt_length_str == 1 && str[0] == '-') { 1834 salt_length_str = 0; 1835 } else if (salt_length_str % 2 != 0) { 1836 return LDNS_WIREPARSE_ERR_SYNTAX_HEX; 1837 } 1838 if (salt_length_str > 512) 1839 return LDNS_WIREPARSE_ERR_SYNTAX_HEX; 1840 if(*len < 1+(size_t)salt_length_str / 2) 1841 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1842 rd[0] = (uint8_t) (salt_length_str / 2); 1843 for (i = 0; i < salt_length_str; i += 2) { 1844 if (isxdigit((unsigned char)str[i]) && 1845 isxdigit((unsigned char)str[i+1])) { 1846 rd[1+i/2] = (uint8_t)(sldns_hexdigit_to_int(str[i])*16 1847 + sldns_hexdigit_to_int(str[i+1])); 1848 } else { 1849 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, i); 1850 } 1851 } 1852 *len = 1 + (size_t)rd[0]; 1853 return LDNS_WIREPARSE_ERR_OK; 1854 } 1855 1856 int sldns_str2wire_ilnp64_buf(const char* str, uint8_t* rd, size_t* len) 1857 { 1858 unsigned int a, b, c, d; 1859 uint16_t shorts[4]; 1860 int l; 1861 if(*len < sizeof(shorts)) 1862 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1863 1864 if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 || 1865 l != (int)strlen(str) || /* more data to read */ 1866 strpbrk(str, "+-") /* signed hexes */ 1867 ) 1868 return LDNS_WIREPARSE_ERR_SYNTAX_ILNP64; 1869 shorts[0] = htons(a); 1870 shorts[1] = htons(b); 1871 shorts[2] = htons(c); 1872 shorts[3] = htons(d); 1873 memmove(rd, &shorts, sizeof(shorts)); 1874 *len = sizeof(shorts); 1875 return LDNS_WIREPARSE_ERR_OK; 1876 } 1877 1878 int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len) 1879 { 1880 unsigned int a, b, c, d, e, f; 1881 int l; 1882 1883 if(*len < 6) 1884 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1885 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n", 1886 &a, &b, &c, &d, &e, &f, &l) != 6 || 1887 l != (int)strlen(str)) 1888 return LDNS_WIREPARSE_ERR_SYNTAX_EUI48; 1889 rd[0] = a; 1890 rd[1] = b; 1891 rd[2] = c; 1892 rd[3] = d; 1893 rd[4] = e; 1894 rd[5] = f; 1895 *len = 6; 1896 return LDNS_WIREPARSE_ERR_OK; 1897 } 1898 1899 int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len) 1900 { 1901 unsigned int a, b, c, d, e, f, g, h; 1902 int l; 1903 1904 if(*len < 8) 1905 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1906 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n", 1907 &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 || 1908 l != (int)strlen(str)) 1909 return LDNS_WIREPARSE_ERR_SYNTAX_EUI64; 1910 rd[0] = a; 1911 rd[1] = b; 1912 rd[2] = c; 1913 rd[3] = d; 1914 rd[4] = e; 1915 rd[5] = f; 1916 rd[6] = g; 1917 rd[7] = h; 1918 *len = 8; 1919 return LDNS_WIREPARSE_ERR_OK; 1920 } 1921 1922 int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len) 1923 { 1924 size_t slen = strlen(str); 1925 const char* ptr; 1926 1927 if (slen > 255) 1928 return LDNS_WIREPARSE_ERR_SYNTAX_TAG; 1929 if(*len < slen+1) 1930 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1931 for (ptr = str; *ptr; ptr++) { 1932 if(!isalnum((unsigned char)*ptr)) 1933 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TAG, ptr-str); 1934 } 1935 rd[0] = slen; 1936 memmove(rd+1, str, slen); 1937 *len = slen+1; 1938 return LDNS_WIREPARSE_ERR_OK; 1939 } 1940 1941 int sldns_str2wire_long_str_buf(const char* str, uint8_t* rd, size_t* len) 1942 { 1943 uint8_t ch = 0; 1944 const char* pstr = str; 1945 size_t length = 0; 1946 1947 /* Fill data with parsed bytes */ 1948 while (sldns_parse_char(&ch, &pstr)) { 1949 if(*len < length+1) 1950 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1951 rd[length++] = ch; 1952 } 1953 if(!pstr) 1954 return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; 1955 *len = length; 1956 return LDNS_WIREPARSE_ERR_OK; 1957 } 1958 1959 int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len) 1960 { 1961 char* s, *end; 1962 int e; 1963 size_t hitlen, pklen = 0; 1964 /* presentation format: 1965 * pk-algo HIThex pubkeybase64 1966 * wireformat: 1967 * hitlen[1byte] pkalgo[1byte] pubkeylen[2byte] [hit] [pubkey] */ 1968 if(*len < 4) 1969 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1970 1971 /* read PK algorithm */ 1972 rd[1] = (uint8_t)strtol((char*)str, &s, 10); 1973 if(*s != ' ') 1974 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str); 1975 s++; 1976 while(*s == ' ') 1977 s++; 1978 1979 /* read HIT hex tag */ 1980 /* zero terminate the tag (replace later) */ 1981 end = strchr(s, ' '); 1982 if(!end) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-(char*)str); 1983 *end = 0; 1984 hitlen = *len - 4; 1985 if((e = sldns_str2wire_hex_buf(s, rd+4, &hitlen)) != 0) { 1986 *end = ' '; 1987 return RET_ERR_SHIFT(e, s-(char*)str); 1988 } 1989 if(hitlen > 255) { 1990 *end = ' '; 1991 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+255*2); 1992 } 1993 rd[0] = (uint8_t)hitlen; 1994 *end = ' '; 1995 s = end+1; 1996 1997 /* read pubkey base64 sequence */ 1998 pklen = *len - 4 - hitlen; 1999 if((e = sldns_str2wire_b64_buf(s, rd+4+hitlen, &pklen)) != 0) 2000 return RET_ERR_SHIFT(e, s-(char*)str); 2001 if(pklen > 65535) 2002 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+65535); 2003 sldns_write_uint16(rd+2, pklen); 2004 2005 *len = 4 + hitlen + pklen; 2006 return LDNS_WIREPARSE_ERR_OK; 2007 } 2008 2009 int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len) 2010 { 2011 size_t sz = sldns_b64_pton_calculate_size(strlen(str)); 2012 int n; 2013 if(*len < sz+2) 2014 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2015 if(sz > 65535) 2016 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 2017 n = sldns_b64_pton(str, rd+2, (*len)-2); 2018 if(n < 0) 2019 return LDNS_WIREPARSE_ERR_SYNTAX_B64; 2020 sldns_write_uint16(rd, (uint16_t)n); 2021 *len = (size_t)n; 2022 return LDNS_WIREPARSE_ERR_OK; 2023 } 2024