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 /** bits for the offset */ 29 #define RET_OFFSET_MASK (((unsigned)(~LDNS_WIREPARSE_MASK))>>LDNS_WIREPARSE_SHIFT) 30 /** return an error */ 31 #define RET_ERR(e, off) ((int)(((e)&LDNS_WIREPARSE_MASK)|(((off)&RET_OFFSET_MASK)<<LDNS_WIREPARSE_SHIFT))) 32 /** Move parse error but keep its ID */ 33 #define RET_ERR_SHIFT(e, move) RET_ERR(LDNS_WIREPARSE_ERROR(e), LDNS_WIREPARSE_OFFSET(e)+(move)); 34 35 /* 36 * No special care is taken, all dots are translated into 37 * label separators. 38 * @param rel: true if the domain is not absolute (not terminated in .). 39 * The output is then still terminated with a '0' rootlabel. 40 */ 41 static int sldns_str2wire_dname_buf_rel(const char* str, uint8_t* buf, 42 size_t* olen, int* rel) 43 { 44 size_t len; 45 46 const char *s; 47 uint8_t *q, *pq, label_len; 48 49 if(rel) *rel = 0; 50 len = strlen((char*)str); 51 /* octet representation can make strings a lot longer than actual length */ 52 if (len > LDNS_MAX_DOMAINLEN * 4) { 53 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, 0); 54 } 55 if (0 == len) { 56 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_UNDERFLOW, 0); 57 } 58 59 /* root label */ 60 if (1 == len && *str == '.') { 61 if(*olen < 1) 62 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 0); 63 buf[0] = 0; 64 *olen = 1; 65 return LDNS_WIREPARSE_ERR_OK; 66 } 67 68 /* get on with the rest */ 69 70 /* s is on the current character in the string 71 * pq points to where the labellength is going to go 72 * label_len keeps track of the current label's length 73 * q builds the dname inside the buf array 74 */ 75 len = 0; 76 if(*olen < 1) 77 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 0); 78 q = buf+1; 79 pq = buf; 80 label_len = 0; 81 for (s = str; *s; s++, q++) { 82 if (q >= buf + *olen) 83 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf); 84 if (q >= buf + LDNS_MAX_DOMAINLEN) 85 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf); 86 switch (*s) { 87 case '.': 88 if (label_len > LDNS_MAX_LABELLEN) { 89 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, q-buf); 90 } 91 if (label_len == 0) { 92 return RET_ERR(LDNS_WIREPARSE_ERR_EMPTY_LABEL, q-buf); 93 } 94 len += label_len + 1; 95 *q = 0; 96 *pq = label_len; 97 label_len = 0; 98 pq = q; 99 break; 100 case '\\': 101 /* octet value or literal char */ 102 s += 1; 103 if (!sldns_parse_escape(q, &s)) { 104 *q = 0; 105 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE, q-buf); 106 } 107 s -= 1; 108 label_len++; 109 break; 110 default: 111 *q = (uint8_t)*s; 112 label_len++; 113 } 114 } 115 116 /* add root label if last char was not '.' */ 117 if(label_len != 0) { 118 if(rel) *rel = 1; 119 if (q >= buf + *olen) 120 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf); 121 if (q >= buf + LDNS_MAX_DOMAINLEN) { 122 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf); 123 } 124 if (label_len > LDNS_MAX_LABELLEN) { 125 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, q-buf); 126 } 127 if (label_len == 0) { /* label_len 0 but not . at end? */ 128 return RET_ERR(LDNS_WIREPARSE_ERR_EMPTY_LABEL, q-buf); 129 } 130 len += label_len + 1; 131 *pq = label_len; 132 *q = 0; 133 } 134 len++; 135 *olen = len; 136 137 return LDNS_WIREPARSE_ERR_OK; 138 } 139 140 int sldns_str2wire_dname_buf(const char* str, uint8_t* buf, size_t* len) 141 { 142 return sldns_str2wire_dname_buf_rel(str, buf, len, NULL); 143 } 144 145 int sldns_str2wire_dname_buf_origin(const char* str, uint8_t* buf, size_t* len, 146 uint8_t* origin, size_t origin_len) 147 { 148 size_t dlen = *len; 149 int rel = 0; 150 int s = sldns_str2wire_dname_buf_rel(str, buf, &dlen, &rel); 151 if(s) return s; 152 153 if(rel && origin && dlen > 0) { 154 if((unsigned)dlen >= 0x00ffffffU || 155 (unsigned)origin_len >= 0x00ffffffU) 156 /* guard against integer overflow in addition */ 157 return RET_ERR(LDNS_WIREPARSE_ERR_GENERAL, *len); 158 if(dlen + origin_len - 1 > LDNS_MAX_DOMAINLEN) 159 return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, 160 LDNS_MAX_DOMAINLEN); 161 if(dlen + origin_len - 1 > *len) 162 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 163 *len); 164 memmove(buf+dlen-1, origin, origin_len); 165 *len = dlen + origin_len - 1; 166 } else 167 *len = dlen; 168 return LDNS_WIREPARSE_ERR_OK; 169 } 170 171 uint8_t* sldns_str2wire_dname(const char* str, size_t* len) 172 { 173 uint8_t dname[LDNS_MAX_DOMAINLEN+1]; 174 *len = sizeof(dname); 175 if(sldns_str2wire_dname_buf(str, dname, len) == 0) { 176 uint8_t* r; 177 if(*len > sizeof(dname)) return NULL; 178 r = (uint8_t*)malloc(*len); 179 if(r) return memcpy(r, dname, *len); 180 } 181 *len = 0; 182 return NULL; 183 } 184 185 /** read owner name */ 186 static int 187 rrinternal_get_owner(sldns_buffer* strbuf, uint8_t* rr, size_t* len, 188 size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, 189 size_t prev_len, char* token, size_t token_len) 190 { 191 /* split the rr in its parts -1 signals trouble */ 192 if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 193 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 194 sldns_buffer_position(strbuf)); 195 } 196 197 if(token_len < 2) /* make sure there is space to read "@" or "" */ 198 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 199 sldns_buffer_position(strbuf)); 200 if(token[0]=='@' && token[1]=='\0') { 201 uint8_t* tocopy; 202 if (origin) { 203 *dname_len = origin_len; 204 tocopy = origin; 205 } else if (prev) { 206 *dname_len = prev_len; 207 tocopy = prev; 208 } else { 209 /* default to root */ 210 *dname_len = 1; 211 tocopy = (uint8_t*)"\0"; 212 } 213 if(*len < *dname_len) 214 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 215 sldns_buffer_position(strbuf)); 216 memmove(rr, tocopy, *dname_len); 217 } else if(*token == '\0') { 218 /* no ownername was given, try prev, if that fails 219 * origin, else default to root */ 220 uint8_t* tocopy; 221 if(prev) { 222 *dname_len = prev_len; 223 tocopy = prev; 224 } else if(origin) { 225 *dname_len = origin_len; 226 tocopy = origin; 227 } else { 228 *dname_len = 1; 229 tocopy = (uint8_t*)"\0"; 230 } 231 if(*len < *dname_len) 232 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 233 sldns_buffer_position(strbuf)); 234 memmove(rr, tocopy, *dname_len); 235 } else { 236 size_t dlen = *len; 237 int s = sldns_str2wire_dname_buf_origin(token, rr, &dlen, 238 origin, origin_len); 239 if(s) return RET_ERR_SHIFT(s, 240 sldns_buffer_position(strbuf)-strlen(token)); 241 *dname_len = dlen; 242 } 243 return LDNS_WIREPARSE_ERR_OK; 244 } 245 246 /** read ttl */ 247 static int 248 rrinternal_get_ttl(sldns_buffer* strbuf, char* token, size_t token_len, 249 int* not_there, uint32_t* ttl, uint32_t default_ttl) 250 { 251 const char* endptr; 252 int overflow; 253 if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 254 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL, 255 sldns_buffer_position(strbuf)); 256 } 257 *ttl = (uint32_t) sldns_str2period(token, &endptr, &overflow); 258 if(overflow) { 259 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, 260 sldns_buffer_position(strbuf)); 261 } 262 263 if (strlen(token) > 0 && !isdigit((unsigned char)token[0])) { 264 *not_there = 1; 265 /* ah, it's not there or something */ 266 if (default_ttl == 0) { 267 *ttl = LDNS_DEFAULT_TTL; 268 } else { 269 *ttl = default_ttl; 270 } 271 } 272 return LDNS_WIREPARSE_ERR_OK; 273 } 274 275 /** read class */ 276 static int 277 rrinternal_get_class(sldns_buffer* strbuf, char* token, size_t token_len, 278 int* not_there, uint16_t* cl) 279 { 280 /* if 'not_there' then we got token from previous parse routine */ 281 if(!*not_there) { 282 /* parse new token for class */ 283 if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 284 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_CLASS, 285 sldns_buffer_position(strbuf)); 286 } 287 } else *not_there = 0; 288 *cl = sldns_get_rr_class_by_name(token); 289 /* class can be left out too, assume IN, current token must be type */ 290 if(*cl == 0 && strcmp(token, "CLASS0") != 0) { 291 *not_there = 1; 292 *cl = LDNS_RR_CLASS_IN; 293 } 294 return LDNS_WIREPARSE_ERR_OK; 295 } 296 297 /** read type */ 298 static int 299 rrinternal_get_type(sldns_buffer* strbuf, char* token, size_t token_len, 300 int* not_there, uint16_t* tp) 301 { 302 /* if 'not_there' then we got token from previous parse routine */ 303 if(!*not_there) { 304 /* parse new token for type */ 305 if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) { 306 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 307 sldns_buffer_position(strbuf)); 308 } 309 } 310 *tp = sldns_get_rr_type_by_name(token); 311 if(*tp == 0 && strcmp(token, "TYPE0") != 0) { 312 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 313 sldns_buffer_position(strbuf)); 314 } 315 return LDNS_WIREPARSE_ERR_OK; 316 } 317 318 /** put type, class, ttl into rr buffer */ 319 static int 320 rrinternal_write_typeclassttl(sldns_buffer* strbuf, uint8_t* rr, size_t len, 321 size_t dname_len, uint16_t tp, uint16_t cl, uint32_t ttl, int question) 322 { 323 if(question) { 324 /* question is : name, type, class */ 325 if(dname_len + 4 > len) 326 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 327 sldns_buffer_position(strbuf)); 328 sldns_write_uint16(rr+dname_len, tp); 329 sldns_write_uint16(rr+dname_len+2, cl); 330 return LDNS_WIREPARSE_ERR_OK; 331 } 332 333 /* type(2), class(2), ttl(4), rdatalen(2 (later)) = 10 */ 334 if(dname_len + 10 > len) 335 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 336 sldns_buffer_position(strbuf)); 337 sldns_write_uint16(rr+dname_len, tp); 338 sldns_write_uint16(rr+dname_len+2, cl); 339 sldns_write_uint32(rr+dname_len+4, ttl); 340 sldns_write_uint16(rr+dname_len+8, 0); /* rdatalen placeholder */ 341 return LDNS_WIREPARSE_ERR_OK; 342 } 343 344 /** find delimiters for type */ 345 static const char* 346 rrinternal_get_delims(sldns_rdf_type rdftype, size_t r_cnt, size_t r_max) 347 { 348 switch(rdftype) { 349 case LDNS_RDF_TYPE_B64 : 350 case LDNS_RDF_TYPE_HEX : /* These rdf types may con- */ 351 case LDNS_RDF_TYPE_LOC : /* tain whitespace, only if */ 352 case LDNS_RDF_TYPE_WKS : /* it is the last rd field. */ 353 case LDNS_RDF_TYPE_IPSECKEY : 354 case LDNS_RDF_TYPE_NSEC : if (r_cnt == r_max - 1) { 355 return "\n"; 356 } 357 break; 358 default : break; 359 } 360 return "\n\t "; 361 } 362 363 /* Syntactic sugar for sldns_rr_new_frm_str_internal */ 364 static int 365 sldns_rdf_type_maybe_quoted(sldns_rdf_type rdf_type) 366 { 367 return rdf_type == LDNS_RDF_TYPE_STR || 368 rdf_type == LDNS_RDF_TYPE_LONG_STR || 369 rdf_type == LDNS_RDF_TYPE_UNQUOTED; 370 } 371 372 /** see if rdata is quoted */ 373 static int 374 rrinternal_get_quoted(sldns_buffer* strbuf, const char** delimiters, 375 sldns_rdf_type rdftype) 376 { 377 if(sldns_rdf_type_maybe_quoted(rdftype) && 378 sldns_buffer_remaining(strbuf) > 0) { 379 380 /* skip spaces */ 381 while(sldns_buffer_remaining(strbuf) > 0 && 382 (*(sldns_buffer_current(strbuf)) == ' ' || 383 *(sldns_buffer_current(strbuf)) == '\t')) { 384 sldns_buffer_skip(strbuf, 1); 385 } 386 387 if(sldns_buffer_remaining(strbuf) > 0 && 388 *(sldns_buffer_current(strbuf)) == '\"') { 389 *delimiters = "\"\0"; 390 sldns_buffer_skip(strbuf, 1); 391 return 1; 392 } 393 } 394 return 0; 395 } 396 397 /** spool hex data into rdata */ 398 static int 399 rrinternal_spool_hex(char* token, uint8_t* rr, size_t rr_len, 400 size_t rr_cur_len, size_t* cur_hex_data_size, size_t hex_data_size) 401 { 402 char* p = token; 403 while(*p) { 404 if(isspace((unsigned char)*p)) { 405 p++; 406 continue; 407 } 408 if(!isxdigit((unsigned char)*p)) 409 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 410 p-token); 411 if(*cur_hex_data_size >= hex_data_size) 412 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 413 p-token); 414 /* extra robust check */ 415 if(rr_cur_len+(*cur_hex_data_size)/2 >= rr_len) 416 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 417 p-token); 418 /* see if 16s or 1s */ 419 if( ((*cur_hex_data_size)&1) == 0) { 420 rr[rr_cur_len+(*cur_hex_data_size)/2] = 421 (uint8_t)sldns_hexdigit_to_int(*p)*16; 422 } else { 423 rr[rr_cur_len+(*cur_hex_data_size)/2] += 424 (uint8_t)sldns_hexdigit_to_int(*p); 425 } 426 p++; 427 (*cur_hex_data_size)++; 428 } 429 return LDNS_WIREPARSE_ERR_OK; 430 } 431 432 /** read unknown rr type format */ 433 static int 434 rrinternal_parse_unknown(sldns_buffer* strbuf, char* token, size_t token_len, 435 uint8_t* rr, size_t* rr_len, size_t* rr_cur_len, size_t pre_data_pos) 436 { 437 const char* delim = "\n\t "; 438 size_t hex_data_size, cur_hex_data_size; 439 /* go back to before \# 440 * and skip it while setting delimiters better 441 */ 442 sldns_buffer_set_position(strbuf, pre_data_pos); 443 if(sldns_bget_token(strbuf, token, delim, token_len) == -1) 444 return LDNS_WIREPARSE_ERR_GENERAL; /* should not fail */ 445 /* read rdata octet length */ 446 if(sldns_bget_token(strbuf, token, delim, token_len) == -1) { 447 /* something goes very wrong here */ 448 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 449 sldns_buffer_position(strbuf)); 450 } 451 hex_data_size = (size_t)atoi(token); 452 if(hex_data_size > LDNS_MAX_RDFLEN || 453 *rr_cur_len + hex_data_size > *rr_len) { 454 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 455 sldns_buffer_position(strbuf)); 456 } 457 /* copy hex chars into hex str (2 chars per byte) */ 458 hex_data_size *= 2; 459 cur_hex_data_size = 0; 460 while(cur_hex_data_size < hex_data_size) { 461 int status; 462 ssize_t c = sldns_bget_token(strbuf, token, delim, token_len); 463 if((status = rrinternal_spool_hex(token, rr, *rr_len, 464 *rr_cur_len, &cur_hex_data_size, hex_data_size)) != 0) 465 return RET_ERR_SHIFT(status, 466 sldns_buffer_position(strbuf)-strlen(token)); 467 if(c == -1) { 468 if(cur_hex_data_size != hex_data_size) 469 return RET_ERR( 470 LDNS_WIREPARSE_ERR_SYNTAX_RDATA, 471 sldns_buffer_position(strbuf)); 472 break; 473 } 474 } 475 *rr_cur_len += hex_data_size/2; 476 return LDNS_WIREPARSE_ERR_OK; 477 } 478 479 /** parse normal RR rdata element */ 480 static int 481 rrinternal_parse_rdf(sldns_buffer* strbuf, char* token, size_t token_len, 482 uint8_t* rr, size_t rr_len, size_t* rr_cur_len, sldns_rdf_type rdftype, 483 uint16_t rr_type, size_t r_cnt, size_t r_max, size_t dname_len, 484 uint8_t* origin, size_t origin_len) 485 { 486 size_t len; 487 int status; 488 489 switch(rdftype) { 490 case LDNS_RDF_TYPE_DNAME: 491 /* check if the origin should be used or concatenated */ 492 if(strcmp(token, "@") == 0) { 493 uint8_t* tocopy; 494 size_t copylen; 495 if(origin) { 496 copylen = origin_len; 497 tocopy = origin; 498 } else if(rr_type == LDNS_RR_TYPE_SOA) { 499 copylen = dname_len; 500 tocopy = rr; /* copy rr owner name */ 501 } else { 502 copylen = 1; 503 tocopy = (uint8_t*)"\0"; 504 } 505 if((*rr_cur_len) + copylen > rr_len) 506 return RET_ERR( 507 LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 508 sldns_buffer_position(strbuf)); 509 memmove(rr+*rr_cur_len, tocopy, copylen); 510 (*rr_cur_len) += copylen; 511 } else { 512 size_t dlen = rr_len - (*rr_cur_len); 513 int s = sldns_str2wire_dname_buf_origin(token, 514 rr+*rr_cur_len, &dlen, origin, origin_len); 515 if(s) return RET_ERR_SHIFT(s, 516 sldns_buffer_position(strbuf)-strlen(token)); 517 (*rr_cur_len) += dlen; 518 } 519 return LDNS_WIREPARSE_ERR_OK; 520 521 case LDNS_RDF_TYPE_HEX: 522 case LDNS_RDF_TYPE_B64: 523 /* When this is the last rdata field, then the 524 * rest should be read in (cause then these 525 * rdf types may contain spaces). */ 526 if(r_cnt == r_max - 1) { 527 size_t tlen = strlen(token); 528 (void)sldns_bget_token(strbuf, token+tlen, "\n", 529 token_len - tlen); 530 } 531 break; 532 default: 533 break; 534 } 535 536 len = rr_len - (*rr_cur_len); 537 if((status=sldns_str2wire_rdf_buf(token, rr+(*rr_cur_len), &len, 538 rdftype)) != 0) 539 return RET_ERR_SHIFT(status, 540 sldns_buffer_position(strbuf)-strlen(token)); 541 *rr_cur_len += len; 542 return LDNS_WIREPARSE_ERR_OK; 543 } 544 545 /** 546 * Parse one rdf token. Takes care of quotes and parenthesis. 547 */ 548 static int 549 sldns_parse_rdf_token(sldns_buffer* strbuf, char* token, size_t token_len, 550 int* quoted, int* parens, size_t* pre_data_pos, 551 const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen) 552 { 553 size_t slen; 554 555 /* skip spaces and tabs */ 556 while(sldns_buffer_remaining(strbuf) > 0 && !*quoted && 557 (*(sldns_buffer_current(strbuf)) == ' ' || 558 *(sldns_buffer_current(strbuf)) == '\t')) { 559 sldns_buffer_skip(strbuf, 1); 560 } 561 562 *pre_data_pos = sldns_buffer_position(strbuf); 563 if(sldns_bget_token_par(strbuf, token, (*quoted)?"\"":delimiters, 564 token_len, parens, (*quoted)?NULL:" \t") == -1) { 565 return 0; 566 } 567 slen = strlen(token); 568 /* check if not quoted yet, and we have encountered quotes */ 569 if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) && 570 slen >= 2 && 571 (token[0] == '"' || token[0] == '\'') && 572 (token[slen-1] == '"' || token[slen-1] == '\'')) { 573 /* move token two smaller (quotes) with endnull */ 574 memmove(token, token+1, slen-2); 575 token[slen-2] = 0; 576 slen -= 2; 577 *quoted = 1; 578 } else if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) && 579 slen >= 2 && 580 (token[0] == '"' || token[0] == '\'')) { 581 /* got the start quote (remove it) but read remainder 582 * of quoted string as well into remainder of token */ 583 memmove(token, token+1, slen-1); 584 token[slen-1] = 0; 585 slen -= 1; 586 *quoted = 1; 587 /* rewind buffer over skipped whitespace */ 588 while(sldns_buffer_position(strbuf) > 0 && 589 (sldns_buffer_current(strbuf)[-1] == ' ' || 590 sldns_buffer_current(strbuf)[-1] == '\t')) { 591 sldns_buffer_skip(strbuf, -1); 592 } 593 if(sldns_bget_token_par(strbuf, token+slen, 594 "\"", token_len-slen, 595 parens, NULL) == -1) { 596 return 0; 597 } 598 slen = strlen(token); 599 } 600 *token_strlen = slen; 601 return 1; 602 } 603 604 /** Add space and one more rdf token onto the existing token string. */ 605 static int 606 sldns_affix_token(sldns_buffer* strbuf, char* token, size_t* token_len, 607 int* quoted, int* parens, size_t* pre_data_pos, 608 const char* delimiters, sldns_rdf_type rdftype, size_t* token_strlen) 609 { 610 size_t addlen = *token_len - *token_strlen; 611 size_t addstrlen = 0; 612 613 /* add space */ 614 /* when addlen < 2, the token buffer is full considering the NULL byte 615 * from strlen and will lead to buffer overflow with the second 616 * assignment below. */ 617 if(addlen < 2) return 0; 618 token[*token_strlen] = ' '; 619 token[++(*token_strlen)] = 0; 620 621 /* read another token */ 622 addlen = *token_len - *token_strlen; 623 if(!sldns_parse_rdf_token(strbuf, token+*token_strlen, addlen, quoted, 624 parens, pre_data_pos, delimiters, rdftype, &addstrlen)) 625 return 0; 626 (*token_strlen) += addstrlen; 627 return 1; 628 } 629 630 static int sldns_str2wire_svcparam_key_cmp(const void *a, const void *b) 631 { 632 return sldns_read_uint16(*(uint8_t**) a) 633 - sldns_read_uint16(*(uint8_t**) b); 634 } 635 636 /** 637 * Add constraints to the SVCB RRs which involve the whole set 638 */ 639 static int sldns_str2wire_check_svcbparams(uint8_t* rdata, uint16_t rdata_len) 640 { 641 size_t nparams = 0, i; 642 uint8_t new_rdata[LDNS_MAX_RDFLEN]; 643 uint8_t* new_rdata_ptr = new_rdata; 644 uint8_t* svcparams[MAX_NUMBER_OF_SVCPARAMS]; 645 uint8_t* rdata_ptr = rdata; 646 uint16_t rdata_remaining = rdata_len; 647 648 /* find the SvcParams */ 649 while (rdata_remaining) { 650 uint16_t svcbparam_len; 651 652 svcparams[nparams] = rdata_ptr; 653 if (rdata_remaining < 4) 654 return LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA; 655 svcbparam_len = sldns_read_uint16(rdata_ptr + 2); 656 rdata_remaining -= 4; 657 rdata_ptr += 4; 658 659 if (rdata_remaining < svcbparam_len) 660 return LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA; 661 rdata_remaining -= svcbparam_len; 662 rdata_ptr += svcbparam_len; 663 664 nparams += 1; 665 if (nparams >= MAX_NUMBER_OF_SVCPARAMS) 666 return LDNS_WIREPARSE_ERR_SVCB_TOO_MANY_PARAMS; 667 } 668 669 /* In draft-ietf-dnsop-svcb-https-06 Section 7: 670 * 671 * In wire format, the keys are represented by their numeric 672 * values in network byte order, concatenated in ascending order. 673 */ 674 qsort((void *)svcparams 675 ,nparams 676 ,sizeof(uint8_t*) 677 ,sldns_str2wire_svcparam_key_cmp); 678 679 680 /* The code below revolves around semantic errors in the SVCParam set. 681 * So long as we do not distinguish between running Unbound as a primary 682 * or as a secondary, we default to secondary behavior and we ignore the 683 * semantic errors. */ 684 685 #ifdef SVCB_SEMANTIC_ERRORS 686 { 687 uint8_t* mandatory = NULL; 688 /* In draft-ietf-dnsop-svcb-https-06 Section 7: 689 * 690 * Keys (...) MUST NOT appear more than once. 691 * 692 * If they key has already been seen, we have a duplicate 693 */ 694 for(i=0; i < nparams; i++) { 695 uint16_t key = sldns_read_uint16(svcparams[i]); 696 if(i + 1 < nparams && key == sldns_read_uint16(svcparams[i+1])) 697 return LDNS_WIREPARSE_ERR_SVCB_DUPLICATE_KEYS; 698 if(key == SVCB_KEY_MANDATORY) 699 mandatory = svcparams[i]; 700 } 701 702 /* Verify that all the SvcParamKeys in mandatory are present */ 703 if(mandatory) { 704 /* Divide by sizeof(uint16_t)*/ 705 uint16_t mandatory_nkeys = sldns_read_uint16(mandatory + 2) / sizeof(uint16_t); 706 707 /* Guaranteed by sldns_str2wire_svcparam_key_value */ 708 assert(mandatory_nkeys > 0); 709 710 for(i=0; i < mandatory_nkeys; i++) { 711 uint16_t mandatory_key = sldns_read_uint16( 712 mandatory 713 + 2 * sizeof(uint16_t) 714 + i * sizeof(uint16_t)); 715 uint8_t found = 0; 716 size_t j; 717 718 for(j=0; j < nparams; j++) { 719 if(mandatory_key == sldns_read_uint16(svcparams[j])) { 720 found = 1; 721 break; 722 } 723 } 724 725 if(!found) 726 return LDNS_WIREPARSE_ERR_SVCB_MANDATORY_MISSING_PARAM; 727 } 728 } 729 } 730 #endif 731 /* Write rdata in correct order */ 732 for (i = 0; i < nparams; i++) { 733 uint16_t svcparam_len = sldns_read_uint16(svcparams[i] + 2) 734 + 2 * sizeof(uint16_t); 735 736 if ((unsigned)(new_rdata_ptr - new_rdata) + svcparam_len > sizeof(new_rdata)) 737 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 738 739 memcpy(new_rdata_ptr, svcparams[i], svcparam_len); 740 new_rdata_ptr += svcparam_len; 741 } 742 memcpy(rdata, new_rdata, rdata_len); 743 return LDNS_WIREPARSE_ERR_OK; 744 } 745 746 /** parse rdata from string into rr buffer(-remainder after dname). */ 747 static int 748 rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len, 749 uint8_t* rr, size_t* rr_len, size_t dname_len, uint16_t rr_type, 750 uint8_t* origin, size_t origin_len) 751 { 752 const sldns_rr_descriptor *desc = sldns_rr_descript((uint16_t)rr_type); 753 size_t r_cnt, r_min, r_max; 754 size_t rr_cur_len = dname_len + 10, pre_data_pos, token_strlen; 755 int was_unknown_rr_format = 0, parens = 0, status, quoted; 756 const char* delimiters; 757 sldns_rdf_type rdftype; 758 /* a desc is always returned */ 759 if(!desc) return LDNS_WIREPARSE_ERR_GENERAL; 760 r_max = sldns_rr_descriptor_maximum(desc); 761 r_min = sldns_rr_descriptor_minimum(desc); 762 /* robust check */ 763 if(rr_cur_len > *rr_len) 764 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 765 sldns_buffer_position(strbuf)); 766 767 /* because number of fields can be variable, we can't rely on 768 * _maximum() only */ 769 for(r_cnt=0; r_cnt < r_max; r_cnt++) { 770 rdftype = sldns_rr_descriptor_field_type(desc, r_cnt); 771 delimiters = rrinternal_get_delims(rdftype, r_cnt, r_max); 772 quoted = rrinternal_get_quoted(strbuf, &delimiters, rdftype); 773 774 if(!sldns_parse_rdf_token(strbuf, token, token_len, "ed, 775 &parens, &pre_data_pos, delimiters, rdftype, 776 &token_strlen)) 777 break; 778 779 /* rfc3597 specifies that any type can be represented 780 * with \# method, which can contain spaces... 781 * it does specify size though... */ 782 783 /* unknown RR data */ 784 if(token_strlen>=2 && strncmp(token, "\\#", 2) == 0 && 785 !quoted && (token_strlen == 2 || token[2]==' ' || 786 token[2]=='\t')) { 787 was_unknown_rr_format = 1; 788 if((status=rrinternal_parse_unknown(strbuf, token, 789 token_len, rr, rr_len, &rr_cur_len, 790 pre_data_pos)) != 0) 791 return status; 792 } else if(token_strlen > 0 || quoted) { 793 if(rdftype == LDNS_RDF_TYPE_HIP) { 794 /* affix the HIT and PK fields, with a space */ 795 if(!sldns_affix_token(strbuf, token, 796 &token_len, "ed, &parens, 797 &pre_data_pos, delimiters, 798 rdftype, &token_strlen)) 799 break; 800 if(!sldns_affix_token(strbuf, token, 801 &token_len, "ed, &parens, 802 &pre_data_pos, delimiters, 803 rdftype, &token_strlen)) 804 break; 805 } else if(rdftype == LDNS_RDF_TYPE_INT16_DATA && 806 strcmp(token, "0")!=0) { 807 /* affix len and b64 fields */ 808 if(!sldns_affix_token(strbuf, token, 809 &token_len, "ed, &parens, 810 &pre_data_pos, delimiters, 811 rdftype, &token_strlen)) 812 break; 813 } 814 815 /* normal RR */ 816 if((status=rrinternal_parse_rdf(strbuf, token, 817 token_len, rr, *rr_len, &rr_cur_len, rdftype, 818 rr_type, r_cnt, r_max, dname_len, origin, 819 origin_len)) != 0) { 820 return status; 821 } 822 } 823 } 824 if(!was_unknown_rr_format && r_cnt+1 < r_min) { 825 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_MISSING_VALUE, 826 sldns_buffer_position(strbuf)); 827 } 828 while(parens != 0) { 829 /* read remainder, must be "" */ 830 if(sldns_bget_token_par(strbuf, token, "\n", token_len, 831 &parens, " \t") == -1) { 832 if(parens != 0) 833 return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS, 834 sldns_buffer_position(strbuf)); 835 break; 836 } 837 if(strcmp(token, "") != 0) 838 return RET_ERR(LDNS_WIREPARSE_ERR_PARENTHESIS, 839 sldns_buffer_position(strbuf)); 840 } 841 /* write rdata length */ 842 sldns_write_uint16(rr+dname_len+8, (uint16_t)(rr_cur_len-dname_len-10)); 843 *rr_len = rr_cur_len; 844 /* SVCB/HTTPS handling */ 845 if ((rr_type == LDNS_RR_TYPE_SVCB || rr_type == LDNS_RR_TYPE_HTTPS) 846 && !was_unknown_rr_format) { 847 size_t rdata_len = rr_cur_len - dname_len - 10; 848 uint8_t *rdata = rr+dname_len + 10; 849 850 /* skip 1st rdata field SvcPriority (uint16_t) */ 851 if (rdata_len < sizeof(uint16_t)) 852 return LDNS_WIREPARSE_ERR_OK; 853 854 rdata_len -= sizeof(uint16_t); 855 rdata += sizeof(uint16_t); 856 857 /* skip 2nd rdata field dname */ 858 while (rdata_len && *rdata != 0) { 859 uint8_t label_len; 860 861 if ((*rdata & 0xC0)) 862 return LDNS_WIREPARSE_ERR_OK; 863 864 label_len = *rdata + 1; 865 if (rdata_len < label_len) 866 return LDNS_WIREPARSE_ERR_OK; 867 868 rdata_len -= label_len; 869 rdata += label_len; 870 } 871 /* The root label is one more character, so smaller 872 * than 1 + 1 means no Svcparam Keys */ 873 if (rdata_len < 2 || *rdata != 0) 874 return LDNS_WIREPARSE_ERR_OK; 875 876 rdata_len -= 1; 877 rdata += 1; 878 return sldns_str2wire_check_svcbparams(rdata, rdata_len); 879 880 } 881 return LDNS_WIREPARSE_ERR_OK; 882 } 883 884 /* 885 * trailing spaces are allowed 886 * leading spaces are not allowed 887 * allow ttl to be optional 888 * class is optional too 889 * if ttl is missing, and default_ttl is 0, use DEF_TTL 890 * allow ttl to be written as 1d3h 891 * So the RR should look like. e.g. 892 * miek.nl. 3600 IN MX 10 elektron.atoom.net 893 * or 894 * miek.nl. 1h IN MX 10 elektron.atoom.net 895 * or 896 * miek.nl. IN MX 10 elektron.atoom.net 897 */ 898 static int 899 sldns_str2wire_rr_buf_internal(const char* str, uint8_t* rr, size_t* len, 900 size_t* dname_len, uint32_t default_ttl, uint8_t* origin, 901 size_t origin_len, uint8_t* prev, size_t prev_len, int question) 902 { 903 int status; 904 int not_there = 0; 905 char token[LDNS_MAX_RDFLEN+1]; 906 uint32_t ttl = 0; 907 uint16_t tp = 0, cl = 0; 908 size_t ddlen = 0; 909 910 /* string in buffer */ 911 sldns_buffer strbuf; 912 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 913 if(!dname_len) dname_len = &ddlen; 914 915 /* parse the owner */ 916 if((status=rrinternal_get_owner(&strbuf, rr, len, dname_len, origin, 917 origin_len, prev, prev_len, token, sizeof(token))) != 0) 918 return status; 919 920 /* parse the [ttl] [class] <type> */ 921 if((status=rrinternal_get_ttl(&strbuf, token, sizeof(token), 922 ¬_there, &ttl, default_ttl)) != 0) 923 return status; 924 if((status=rrinternal_get_class(&strbuf, token, sizeof(token), 925 ¬_there, &cl)) != 0) 926 return status; 927 if((status=rrinternal_get_type(&strbuf, token, sizeof(token), 928 ¬_there, &tp)) != 0) 929 return status; 930 /* put ttl, class, type into the rr result */ 931 if((status=rrinternal_write_typeclassttl(&strbuf, rr, *len, *dname_len, tp, cl, 932 ttl, question)) != 0) 933 return status; 934 /* for a question-RR we are done, no rdata */ 935 if(question) { 936 *len = *dname_len + 4; 937 return LDNS_WIREPARSE_ERR_OK; 938 } 939 940 /* rdata */ 941 if((status=rrinternal_parse_rdata(&strbuf, token, sizeof(token), 942 rr, len, *dname_len, tp, origin, origin_len)) != 0) 943 return status; 944 945 return LDNS_WIREPARSE_ERR_OK; 946 } 947 948 int sldns_str2wire_rr_buf(const char* str, uint8_t* rr, size_t* len, 949 size_t* dname_len, uint32_t default_ttl, uint8_t* origin, 950 size_t origin_len, uint8_t* prev, size_t prev_len) 951 { 952 return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, 953 default_ttl, origin, origin_len, prev, prev_len, 0); 954 } 955 956 int sldns_str2wire_rr_question_buf(const char* str, uint8_t* rr, size_t* len, 957 size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, 958 size_t prev_len) 959 { 960 return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, 961 0, origin, origin_len, prev, prev_len, 1); 962 } 963 964 uint16_t sldns_wirerr_get_type(uint8_t* rr, size_t len, size_t dname_len) 965 { 966 if(len < dname_len+2) 967 return 0; 968 return sldns_read_uint16(rr+dname_len); 969 } 970 971 uint16_t sldns_wirerr_get_class(uint8_t* rr, size_t len, size_t dname_len) 972 { 973 if(len < dname_len+4) 974 return 0; 975 return sldns_read_uint16(rr+dname_len+2); 976 } 977 978 uint32_t sldns_wirerr_get_ttl(uint8_t* rr, size_t len, size_t dname_len) 979 { 980 if(len < dname_len+8) 981 return 0; 982 return sldns_read_uint32(rr+dname_len+4); 983 } 984 985 uint16_t sldns_wirerr_get_rdatalen(uint8_t* rr, size_t len, size_t dname_len) 986 { 987 if(len < dname_len+10) 988 return 0; 989 return sldns_read_uint16(rr+dname_len+8); 990 } 991 992 uint8_t* sldns_wirerr_get_rdata(uint8_t* rr, size_t len, size_t dname_len) 993 { 994 if(len < dname_len+10) 995 return NULL; 996 return rr+dname_len+10; 997 } 998 999 uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len) 1000 { 1001 if(len < dname_len+10) 1002 return NULL; 1003 return rr+dname_len+8; 1004 } 1005 1006 const char* sldns_get_errorstr_parse(int e) 1007 { 1008 sldns_lookup_table *lt; 1009 lt = sldns_lookup_by_id(sldns_wireparse_errors, LDNS_WIREPARSE_ERROR(e)); 1010 return lt?lt->name:"unknown error"; 1011 } 1012 1013 /* Strip whitespace from the start and the end of <line>. */ 1014 char * 1015 sldns_strip_ws(char *line) 1016 { 1017 char *s = line, *e; 1018 1019 for (s = line; *s && isspace((unsigned char)*s); s++) 1020 ; 1021 for (e = strchr(s, 0); e > s+2 && isspace((unsigned char)e[-1]) && e[-2] != '\\'; e--) 1022 ; 1023 *e = 0; 1024 return s; 1025 } 1026 1027 int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, 1028 struct sldns_file_parse_state* parse_state) 1029 { 1030 char line[LDNS_RR_BUF_SIZE+1]; 1031 ssize_t size; 1032 1033 /* read an entire line in from the file */ 1034 if((size = sldns_fget_token_l(in, line, LDNS_PARSE_SKIP_SPACE, 1035 LDNS_RR_BUF_SIZE, parse_state?&parse_state->lineno:NULL)) 1036 == -1) { 1037 /* if last line was empty, we are now at feof, which is not 1038 * always a parse error (happens when for instance last line 1039 * was a comment) 1040 */ 1041 return LDNS_WIREPARSE_ERR_SYNTAX; 1042 } 1043 1044 /* we can have the situation, where we've read ok, but still got 1045 * no bytes to play with, in this case size is 0 */ 1046 if(size == 0) { 1047 if(*len > 0) 1048 rr[0] = 0; 1049 *len = 0; 1050 *dname_len = 0; 1051 return LDNS_WIREPARSE_ERR_OK; 1052 } 1053 1054 if(strncmp(line, "$ORIGIN", 7) == 0 && isspace((unsigned char)line[7])) { 1055 int s; 1056 strlcpy((char*)rr, line, *len); 1057 *len = 0; 1058 *dname_len = 0; 1059 if(!parse_state) return LDNS_WIREPARSE_ERR_OK; 1060 parse_state->origin_len = sizeof(parse_state->origin); 1061 s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8), 1062 parse_state->origin, &parse_state->origin_len); 1063 if(s) parse_state->origin_len = 0; 1064 return s; 1065 } else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) { 1066 const char* end = NULL; 1067 int overflow = 0; 1068 strlcpy((char*)rr, line, *len); 1069 *len = 0; 1070 *dname_len = 0; 1071 if(!parse_state) return LDNS_WIREPARSE_ERR_OK; 1072 parse_state->default_ttl = sldns_str2period( 1073 sldns_strip_ws(line+5), &end, &overflow); 1074 if(overflow) 1075 return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW; 1076 } else if (strncmp(line, "$INCLUDE", 8) == 0) { 1077 strlcpy((char*)rr, line, *len); 1078 *len = 0; 1079 *dname_len = 0; 1080 return LDNS_WIREPARSE_ERR_INCLUDE; 1081 } else if (strncmp(line, "$", 1) == 0) { 1082 strlcpy((char*)rr, line, *len); 1083 *len = 0; 1084 *dname_len = 0; 1085 return LDNS_WIREPARSE_ERR_INCLUDE; 1086 } else { 1087 int r = sldns_str2wire_rr_buf(line, rr, len, dname_len, 1088 parse_state?parse_state->default_ttl:0, 1089 (parse_state&&parse_state->origin_len)? 1090 parse_state->origin:NULL, 1091 parse_state?parse_state->origin_len:0, 1092 (parse_state&&parse_state->prev_rr_len)? 1093 parse_state->prev_rr:NULL, 1094 parse_state?parse_state->prev_rr_len:0); 1095 if(r == LDNS_WIREPARSE_ERR_OK && (*dname_len) != 0 && 1096 parse_state && 1097 (*dname_len) <= sizeof(parse_state->prev_rr)) { 1098 memmove(parse_state->prev_rr, rr, *dname_len); 1099 parse_state->prev_rr_len = (*dname_len); 1100 } 1101 if(r == LDNS_WIREPARSE_ERR_OK && parse_state) { 1102 parse_state->default_ttl = sldns_wirerr_get_ttl( 1103 rr, *len, *dname_len); 1104 } 1105 return r; 1106 } 1107 return LDNS_WIREPARSE_ERR_OK; 1108 } 1109 1110 static int 1111 sldns_str2wire_svcparam_key_lookup(const char *key, size_t key_len) 1112 { 1113 char buf[64]; 1114 char *endptr; 1115 unsigned long int key_value; 1116 1117 if (key_len >= 4 && key_len <= 8 && !strncmp(key, "key", 3)) { 1118 memcpy(buf, key + 3, key_len - 3); 1119 buf[key_len - 3] = 0; 1120 key_value = strtoul(buf, &endptr, 10); 1121 1122 if (endptr > buf /* digits seen */ 1123 && *endptr == 0 /* no non-digit chars after digits */ 1124 && key_value <= 65535) /* no overflow */ 1125 return key_value; 1126 1127 } else switch (key_len) { 1128 case 3: 1129 if (!strncmp(key, "ech", key_len)) 1130 return SVCB_KEY_ECH; 1131 break; 1132 1133 case 4: 1134 if (!strncmp(key, "alpn", key_len)) 1135 return SVCB_KEY_ALPN; 1136 if (!strncmp(key, "port", key_len)) 1137 return SVCB_KEY_PORT; 1138 break; 1139 1140 case 7: 1141 if (!strncmp(key, "dohpath", key_len)) 1142 return SVCB_KEY_DOHPATH; 1143 break; 1144 1145 case 8: 1146 if (!strncmp(key, "ipv4hint", key_len)) 1147 return SVCB_KEY_IPV4HINT; 1148 if (!strncmp(key, "ipv6hint", key_len)) 1149 return SVCB_KEY_IPV6HINT; 1150 break; 1151 1152 case 9: 1153 if (!strncmp(key, "mandatory", key_len)) 1154 return SVCB_KEY_MANDATORY; 1155 if (!strncmp(key, "echconfig", key_len)) 1156 return SVCB_KEY_ECH; /* allow "echconfig" as well as "ech" */ 1157 break; 1158 1159 case 15: 1160 if (!strncmp(key, "no-default-alpn", key_len)) 1161 return SVCB_KEY_NO_DEFAULT_ALPN; 1162 break; 1163 1164 default: 1165 break; 1166 } 1167 1168 /* Although the returned value might be used by the caller, 1169 * the parser has erred, so the zone will not be loaded. 1170 */ 1171 return -1; 1172 } 1173 1174 static int 1175 sldns_str2wire_svcparam_port(const char* val, uint8_t* rd, size_t* rd_len) 1176 { 1177 unsigned long int port; 1178 char *endptr; 1179 1180 if (*rd_len < 6) 1181 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1182 1183 port = strtoul(val, &endptr, 10); 1184 1185 if (endptr > val /* digits seen */ 1186 && *endptr == 0 /* no non-digit chars after digits */ 1187 && port <= 65535) { /* no overflow */ 1188 1189 sldns_write_uint16(rd, SVCB_KEY_PORT); 1190 sldns_write_uint16(rd + 2, sizeof(uint16_t)); 1191 sldns_write_uint16(rd + 4, port); 1192 *rd_len = 6; 1193 1194 return LDNS_WIREPARSE_ERR_OK; 1195 } 1196 1197 return LDNS_WIREPARSE_ERR_SVCB_PORT_VALUE_SYNTAX; 1198 } 1199 1200 static int 1201 sldns_str2wire_svcbparam_ipv4hint(const char* val, uint8_t* rd, size_t* rd_len) 1202 { 1203 size_t count; 1204 char ip_str[INET_ADDRSTRLEN+1]; 1205 const char *next_ip_str; 1206 size_t i; 1207 1208 for (i = 0, count = 1; val[i]; i++) { 1209 if (val[i] == ',') 1210 count += 1; 1211 if (count > SVCB_MAX_COMMA_SEPARATED_VALUES) { 1212 return LDNS_WIREPARSE_ERR_SVCB_IPV4_TOO_MANY_ADDRESSES; 1213 } 1214 } 1215 1216 if (*rd_len < (LDNS_IP4ADDRLEN * count) + 4) 1217 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1218 1219 /* count is number of comma's in val + 1; so the actual number of IPv4 1220 * addresses in val 1221 */ 1222 sldns_write_uint16(rd, SVCB_KEY_IPV4HINT); 1223 sldns_write_uint16(rd + 2, LDNS_IP4ADDRLEN * count); 1224 *rd_len = 4; 1225 1226 while (count) { 1227 if (!(next_ip_str = strchr(val, ','))) { 1228 if (inet_pton(AF_INET, val, rd + *rd_len) != 1) 1229 break; 1230 *rd_len += LDNS_IP4ADDRLEN; 1231 1232 assert(count == 1); 1233 1234 } else if (next_ip_str - val >= (int)sizeof(ip_str)) 1235 break; 1236 1237 else { 1238 memcpy(ip_str, val, next_ip_str - val); 1239 ip_str[next_ip_str - val] = 0; 1240 if (inet_pton(AF_INET, ip_str, rd + *rd_len) != 1) { 1241 break; 1242 } 1243 *rd_len += LDNS_IP4ADDRLEN; 1244 1245 val = next_ip_str + 1; 1246 } 1247 count--; 1248 } 1249 if (count) /* verify that we parsed all values */ 1250 return LDNS_WIREPARSE_ERR_SYNTAX_IP4; 1251 1252 return LDNS_WIREPARSE_ERR_OK; 1253 } 1254 1255 static int 1256 sldns_str2wire_svcbparam_ipv6hint(const char* val, uint8_t* rd, size_t* rd_len) 1257 { 1258 size_t count; 1259 char ip_str[INET6_ADDRSTRLEN+1]; 1260 const char *next_ip_str; 1261 size_t i; 1262 1263 for (i = 0, count = 1; val[i]; i++) { 1264 if (val[i] == ',') 1265 count += 1; 1266 if (count > SVCB_MAX_COMMA_SEPARATED_VALUES) { 1267 return LDNS_WIREPARSE_ERR_SVCB_IPV6_TOO_MANY_ADDRESSES; 1268 } 1269 } 1270 1271 if (*rd_len < (LDNS_IP6ADDRLEN * count) + 4) 1272 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1273 1274 /* count is number of comma's in val + 1; so the actual number of IPv6 1275 * addresses in val 1276 */ 1277 sldns_write_uint16(rd, SVCB_KEY_IPV6HINT); 1278 sldns_write_uint16(rd + 2, LDNS_IP6ADDRLEN * count); 1279 *rd_len = 4; 1280 1281 while (count) { 1282 if (!(next_ip_str = strchr(val, ','))) { 1283 if (inet_pton(AF_INET6, val, rd + *rd_len) != 1) 1284 break; 1285 *rd_len += LDNS_IP6ADDRLEN; 1286 1287 assert(count == 1); 1288 1289 } else if (next_ip_str - val >= (int)sizeof(ip_str)) 1290 break; 1291 1292 else { 1293 memcpy(ip_str, val, next_ip_str - val); 1294 ip_str[next_ip_str - val] = 0; 1295 if (inet_pton(AF_INET6, ip_str, rd + *rd_len) != 1) { 1296 break; 1297 } 1298 *rd_len += LDNS_IP6ADDRLEN; 1299 1300 val = next_ip_str + 1; 1301 } 1302 count--; 1303 } 1304 if (count) /* verify that we parsed all values */ 1305 return LDNS_WIREPARSE_ERR_SYNTAX_IP6; 1306 1307 return LDNS_WIREPARSE_ERR_OK; 1308 } 1309 1310 /* compare function used for sorting uint16_t's */ 1311 static int 1312 sldns_network_uint16_cmp(const void *a, const void *b) 1313 { 1314 return ((int)sldns_read_uint16(a)) - ((int)sldns_read_uint16(b)); 1315 } 1316 1317 static int 1318 sldns_str2wire_svcbparam_mandatory(const char* val, uint8_t* rd, size_t* rd_len) 1319 { 1320 size_t i, count, val_len; 1321 const char* next_key; 1322 1323 val_len = strlen(val); 1324 1325 for (i = 0, count = 1; val[i]; i++) { 1326 if (val[i] == ',') 1327 count += 1; 1328 if (count > SVCB_MAX_COMMA_SEPARATED_VALUES) { 1329 return LDNS_WIREPARSE_ERR_SVCB_MANDATORY_TOO_MANY_KEYS; 1330 } 1331 } 1332 if (sizeof(uint16_t) * (count + 2) > *rd_len) 1333 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1334 1335 sldns_write_uint16(rd, SVCB_KEY_MANDATORY); 1336 sldns_write_uint16(rd + 2, sizeof(uint16_t) * count); 1337 *rd_len = 4; 1338 1339 while (1) { 1340 int svcparamkey; 1341 1342 if (!(next_key = strchr(val, ','))) { 1343 svcparamkey = sldns_str2wire_svcparam_key_lookup(val, val_len); 1344 1345 if (svcparamkey < 0) { 1346 return LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY; 1347 } 1348 1349 sldns_write_uint16(rd + *rd_len, svcparamkey); 1350 *rd_len += 2; 1351 break; 1352 } else { 1353 svcparamkey = sldns_str2wire_svcparam_key_lookup(val, next_key - val); 1354 1355 if (svcparamkey < 0) { 1356 return LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY; 1357 } 1358 1359 sldns_write_uint16(rd + *rd_len, 1360 svcparamkey); 1361 *rd_len += 2; 1362 } 1363 1364 val_len -= next_key - val + 1; 1365 val = next_key + 1; /* skip the comma */ 1366 } 1367 1368 /* In draft-ietf-dnsop-svcb-https-06 Section 7: 1369 * 1370 * "In wire format, the keys are represented by their numeric 1371 * values in network byte order, concatenated in ascending order." 1372 */ 1373 qsort((void *)(rd + 4), count, sizeof(uint16_t), sldns_network_uint16_cmp); 1374 1375 /* The code below revolves around semantic errors in the SVCParam set. 1376 * So long as we do not distinguish between running Unbound as a primary 1377 * or as a secondary, we default to secondary behavior and we ignore the 1378 * semantic errors. */ 1379 #ifdef SVCB_SEMANTIC_ERRORS 1380 /* In draft-ietf-dnsop-svcb-https-06 Section 8 1381 * automatically mandatory MUST NOT appear in its own value-list 1382 */ 1383 if (sldns_read_uint16(rd + 4) == SVCB_KEY_MANDATORY) 1384 return LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY; 1385 1386 /* Guarantee key uniqueness. After the sort we only need to 1387 * compare neighbouring keys */ 1388 if (count > 1) { 1389 for (i = 0; i < count - 1; i++) { 1390 uint8_t* current_pos = (rd + 4 + (sizeof(uint16_t) * i)); 1391 uint16_t key = sldns_read_uint16(current_pos); 1392 1393 if (key == sldns_read_uint16(current_pos + 2)) { 1394 return LDNS_WIREPARSE_ERR_SVCB_MANDATORY_DUPLICATE_KEY; 1395 } 1396 } 1397 } 1398 #endif 1399 return LDNS_WIREPARSE_ERR_OK; 1400 } 1401 1402 static int 1403 sldns_str2wire_svcbparam_ech_value(const char* val, uint8_t* rd, size_t* rd_len) 1404 { 1405 uint8_t buffer[LDNS_MAX_RDFLEN]; 1406 int wire_len; 1407 1408 /* single 0 represents empty buffer */ 1409 if(strcmp(val, "0") == 0) { 1410 if (*rd_len < 4) 1411 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1412 sldns_write_uint16(rd, SVCB_KEY_ECH); 1413 sldns_write_uint16(rd + 2, 0); 1414 *rd_len = 4; 1415 1416 return LDNS_WIREPARSE_ERR_OK; 1417 } 1418 1419 wire_len = sldns_b64_pton(val, buffer, LDNS_MAX_RDFLEN); 1420 1421 if (wire_len <= 0) { 1422 return LDNS_WIREPARSE_ERR_SYNTAX_B64; 1423 } else if ((unsigned)wire_len + 4 > *rd_len) { 1424 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1425 } else { 1426 sldns_write_uint16(rd, SVCB_KEY_ECH); 1427 sldns_write_uint16(rd + 2, wire_len); 1428 memcpy(rd + 4, buffer, wire_len); 1429 *rd_len = 4 + wire_len; 1430 1431 return LDNS_WIREPARSE_ERR_OK; 1432 } 1433 } 1434 1435 static const char* 1436 sldns_str2wire_svcbparam_parse_next_unescaped_comma(const char *val) 1437 { 1438 while (*val) { 1439 /* Only return when the comma is not escaped*/ 1440 if (*val == '\\'){ 1441 ++val; 1442 if (!*val) 1443 break; 1444 } else if (*val == ',') 1445 return val; 1446 1447 val++; 1448 } 1449 return NULL; 1450 } 1451 1452 /* The source is already properly unescaped, this double unescaping is purely to allow for 1453 * comma's in comma separated alpn lists. 1454 * 1455 * In draft-ietf-dnsop-svcb-https-06 Section 7: 1456 * To enable simpler parsing, this SvcParamValue MUST NOT contain escape sequences. 1457 */ 1458 static size_t 1459 sldns_str2wire_svcbparam_parse_copy_unescaped(uint8_t *dst, 1460 const char *src, size_t len) 1461 { 1462 uint8_t *orig_dst = dst; 1463 1464 while (len) { 1465 if (*src == '\\') { 1466 src++; 1467 len--; 1468 if (!len) 1469 break; 1470 } 1471 *dst++ = *src++; 1472 len--; 1473 } 1474 return (size_t)(dst - orig_dst); 1475 } 1476 1477 static int 1478 sldns_str2wire_svcbparam_alpn_value(const char* val, 1479 uint8_t* rd, size_t* rd_len) 1480 { 1481 uint8_t unescaped_dst[LDNS_MAX_RDFLEN]; 1482 uint8_t *dst = unescaped_dst; 1483 const char *next_str; 1484 size_t str_len; 1485 size_t dst_len; 1486 size_t val_len; 1487 1488 val_len = strlen(val); 1489 1490 if (val_len > sizeof(unescaped_dst)) { 1491 return LDNS_WIREPARSE_ERR_SVCB_ALPN_KEY_TOO_LARGE; 1492 } 1493 while (val_len) { 1494 size_t key_len; 1495 1496 str_len = (next_str = sldns_str2wire_svcbparam_parse_next_unescaped_comma(val)) 1497 ? (size_t)(next_str - val) : val_len; 1498 1499 if (str_len > 255) { 1500 return LDNS_WIREPARSE_ERR_SVCB_ALPN_KEY_TOO_LARGE; 1501 } 1502 1503 key_len = sldns_str2wire_svcbparam_parse_copy_unescaped(dst + 1, val, str_len); 1504 *dst++ = key_len; 1505 dst += key_len; 1506 1507 if (!next_str) 1508 break; 1509 1510 /* skip the comma in the next iteration */ 1511 val_len -= next_str - val + 1; 1512 val = next_str + 1; 1513 } 1514 dst_len = dst - unescaped_dst; 1515 if (*rd_len < 4 + dst_len) 1516 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1517 sldns_write_uint16(rd, SVCB_KEY_ALPN); 1518 sldns_write_uint16(rd + 2, dst_len); 1519 memcpy(rd + 4, unescaped_dst, dst_len); 1520 *rd_len = 4 + dst_len; 1521 1522 return LDNS_WIREPARSE_ERR_OK; 1523 } 1524 1525 static int 1526 sldns_str2wire_svcbparam_dohpath_value(const char* val, 1527 uint8_t* rd, size_t* rd_len) 1528 { 1529 size_t val_len; 1530 1531 /* RFC6570#section-2.1 1532 * "The characters outside of expressions in a URI Template string are 1533 * intended to be copied literally" 1534 * Practically this means we do not have to look for "double escapes" 1535 * like in the alpn value list. 1536 */ 1537 1538 val_len = strlen(val); 1539 1540 if (*rd_len < 4 + val_len) { 1541 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1542 } 1543 1544 sldns_write_uint16(rd, SVCB_KEY_DOHPATH); 1545 sldns_write_uint16(rd + 2, val_len); 1546 memcpy(rd + 4, val, val_len); 1547 *rd_len = 4 + val_len; 1548 1549 return LDNS_WIREPARSE_ERR_OK; 1550 } 1551 1552 static int 1553 sldns_str2wire_svcparam_value(const char *key, size_t key_len, 1554 const char *val, uint8_t* rd, size_t* rd_len) 1555 { 1556 size_t str_len; 1557 int svcparamkey = sldns_str2wire_svcparam_key_lookup(key, key_len); 1558 1559 if (svcparamkey < 0) { 1560 return LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY; 1561 } 1562 1563 /* key without value */ 1564 if (val == NULL) { 1565 switch (svcparamkey) { 1566 #ifdef SVCB_SEMANTIC_ERRORS 1567 case SVCB_KEY_MANDATORY: 1568 case SVCB_KEY_ALPN: 1569 case SVCB_KEY_PORT: 1570 case SVCB_KEY_IPV4HINT: 1571 case SVCB_KEY_IPV6HINT: 1572 case SVCB_KEY_DOHPATH: 1573 return LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM; 1574 #endif 1575 default: 1576 if (*rd_len < 4) 1577 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1578 sldns_write_uint16(rd, svcparamkey); 1579 sldns_write_uint16(rd + 2, 0); 1580 *rd_len = 4; 1581 1582 return LDNS_WIREPARSE_ERR_OK; 1583 } 1584 } 1585 1586 /* value is non-empty */ 1587 switch (svcparamkey) { 1588 case SVCB_KEY_PORT: 1589 return sldns_str2wire_svcparam_port(val, rd, rd_len); 1590 case SVCB_KEY_IPV4HINT: 1591 return sldns_str2wire_svcbparam_ipv4hint(val, rd, rd_len); 1592 case SVCB_KEY_IPV6HINT: 1593 return sldns_str2wire_svcbparam_ipv6hint(val, rd, rd_len); 1594 case SVCB_KEY_MANDATORY: 1595 return sldns_str2wire_svcbparam_mandatory(val, rd, rd_len); 1596 #ifdef SVCB_SEMANTIC_ERRORS 1597 case SVCB_KEY_NO_DEFAULT_ALPN: 1598 return LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE; 1599 #endif 1600 case SVCB_KEY_ECH: 1601 return sldns_str2wire_svcbparam_ech_value(val, rd, rd_len); 1602 case SVCB_KEY_ALPN: 1603 return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len); 1604 case SVCB_KEY_DOHPATH: 1605 return sldns_str2wire_svcbparam_dohpath_value(val, rd, rd_len); 1606 default: 1607 str_len = strlen(val); 1608 if (*rd_len < 4 + str_len) 1609 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1610 sldns_write_uint16(rd, svcparamkey); 1611 sldns_write_uint16(rd + 2, str_len); 1612 memcpy(rd + 4, val, str_len); 1613 *rd_len = 4 + str_len; 1614 1615 return LDNS_WIREPARSE_ERR_OK; 1616 } 1617 1618 return LDNS_WIREPARSE_ERR_GENERAL; 1619 } 1620 1621 static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_len) 1622 { 1623 const char* eq_pos; 1624 char unescaped_val[LDNS_MAX_RDFLEN]; 1625 char* val_out = unescaped_val; 1626 const char* val_in; 1627 1628 eq_pos = strchr(str, '='); 1629 1630 /* case: key=value */ 1631 if (eq_pos != NULL && eq_pos[1]) { 1632 val_in = eq_pos + 1; 1633 1634 /* unescape characters and "" blocks */ 1635 if (*val_in == '"') { 1636 val_in++; 1637 while (*val_in != '"' 1638 && (size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val) 1639 && sldns_parse_char( (uint8_t*) val_out, &val_in)) { 1640 val_out++; 1641 } 1642 } else { 1643 while ((size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val) 1644 && sldns_parse_char( (uint8_t*) val_out, &val_in)) { 1645 val_out++; 1646 } 1647 } 1648 *val_out = 0; 1649 1650 return sldns_str2wire_svcparam_value(str, eq_pos - str, 1651 unescaped_val[0] ? unescaped_val : NULL, rd, rd_len); 1652 } 1653 /* case: key= */ 1654 else if (eq_pos != NULL && !(eq_pos[1])) { 1655 return sldns_str2wire_svcparam_value(str, eq_pos - str, NULL, rd, rd_len); 1656 } 1657 /* case: key */ 1658 else { 1659 return sldns_str2wire_svcparam_value(str, strlen(str), NULL, rd, rd_len); 1660 } 1661 } 1662 1663 int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len, 1664 sldns_rdf_type rdftype) 1665 { 1666 switch (rdftype) { 1667 case LDNS_RDF_TYPE_DNAME: 1668 return sldns_str2wire_dname_buf(str, rd, len); 1669 case LDNS_RDF_TYPE_INT8: 1670 return sldns_str2wire_int8_buf(str, rd, len); 1671 case LDNS_RDF_TYPE_INT16: 1672 return sldns_str2wire_int16_buf(str, rd, len); 1673 case LDNS_RDF_TYPE_INT32: 1674 return sldns_str2wire_int32_buf(str, rd, len); 1675 case LDNS_RDF_TYPE_A: 1676 return sldns_str2wire_a_buf(str, rd, len); 1677 case LDNS_RDF_TYPE_AAAA: 1678 return sldns_str2wire_aaaa_buf(str, rd, len); 1679 case LDNS_RDF_TYPE_STR: 1680 return sldns_str2wire_str_buf(str, rd, len); 1681 case LDNS_RDF_TYPE_APL: 1682 return sldns_str2wire_apl_buf(str, rd, len); 1683 case LDNS_RDF_TYPE_B64: 1684 return sldns_str2wire_b64_buf(str, rd, len); 1685 case LDNS_RDF_TYPE_B32_EXT: 1686 return sldns_str2wire_b32_ext_buf(str, rd, len); 1687 case LDNS_RDF_TYPE_HEX: 1688 return sldns_str2wire_hex_buf(str, rd, len); 1689 case LDNS_RDF_TYPE_NSEC: 1690 return sldns_str2wire_nsec_buf(str, rd, len); 1691 case LDNS_RDF_TYPE_TYPE: 1692 return sldns_str2wire_type_buf(str, rd, len); 1693 case LDNS_RDF_TYPE_CLASS: 1694 return sldns_str2wire_class_buf(str, rd, len); 1695 case LDNS_RDF_TYPE_CERT_ALG: 1696 return sldns_str2wire_cert_alg_buf(str, rd, len); 1697 case LDNS_RDF_TYPE_ALG: 1698 return sldns_str2wire_alg_buf(str, rd, len); 1699 case LDNS_RDF_TYPE_TIME: 1700 return sldns_str2wire_time_buf(str, rd, len); 1701 case LDNS_RDF_TYPE_PERIOD: 1702 return sldns_str2wire_period_buf(str, rd, len); 1703 case LDNS_RDF_TYPE_TSIGTIME: 1704 return sldns_str2wire_tsigtime_buf(str, rd, len); 1705 case LDNS_RDF_TYPE_LOC: 1706 return sldns_str2wire_loc_buf(str, rd, len); 1707 case LDNS_RDF_TYPE_WKS: 1708 return sldns_str2wire_wks_buf(str, rd, len); 1709 case LDNS_RDF_TYPE_NSAP: 1710 return sldns_str2wire_nsap_buf(str, rd, len); 1711 case LDNS_RDF_TYPE_ATMA: 1712 return sldns_str2wire_atma_buf(str, rd, len); 1713 case LDNS_RDF_TYPE_IPSECKEY: 1714 return sldns_str2wire_ipseckey_buf(str, rd, len); 1715 case LDNS_RDF_TYPE_NSEC3_SALT: 1716 return sldns_str2wire_nsec3_salt_buf(str, rd, len); 1717 case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: 1718 return sldns_str2wire_b32_ext_buf(str, rd, len); 1719 case LDNS_RDF_TYPE_ILNP64: 1720 return sldns_str2wire_ilnp64_buf(str, rd, len); 1721 case LDNS_RDF_TYPE_EUI48: 1722 return sldns_str2wire_eui48_buf(str, rd, len); 1723 case LDNS_RDF_TYPE_EUI64: 1724 return sldns_str2wire_eui64_buf(str, rd, len); 1725 case LDNS_RDF_TYPE_UNQUOTED: 1726 return sldns_str2wire_unquoted_buf(str, rd, len); 1727 case LDNS_RDF_TYPE_TAG: 1728 return sldns_str2wire_tag_buf(str, rd, len); 1729 case LDNS_RDF_TYPE_LONG_STR: 1730 return sldns_str2wire_long_str_buf(str, rd, len); 1731 case LDNS_RDF_TYPE_TSIGERROR: 1732 return sldns_str2wire_tsigerror_buf(str, rd, len); 1733 case LDNS_RDF_TYPE_HIP: 1734 return sldns_str2wire_hip_buf(str, rd, len); 1735 case LDNS_RDF_TYPE_INT16_DATA: 1736 return sldns_str2wire_int16_data_buf(str, rd, len); 1737 case LDNS_RDF_TYPE_SVCPARAM: 1738 return sldns_str2wire_svcparam_buf(str, rd, len); 1739 case LDNS_RDF_TYPE_UNKNOWN: 1740 case LDNS_RDF_TYPE_SERVICE: 1741 return LDNS_WIREPARSE_ERR_NOT_IMPL; 1742 case LDNS_RDF_TYPE_NONE: 1743 default: 1744 break; 1745 } 1746 return LDNS_WIREPARSE_ERR_GENERAL; 1747 } 1748 1749 int sldns_str2wire_int8_buf(const char* str, uint8_t* rd, size_t* len) 1750 { 1751 char* end; 1752 uint8_t r = (uint8_t)strtol((char*)str, &end, 10); 1753 if(*end != 0) 1754 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1755 if(*len < 1) 1756 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1757 rd[0] = r; 1758 *len = 1; 1759 return LDNS_WIREPARSE_ERR_OK; 1760 } 1761 1762 int sldns_str2wire_int16_buf(const char* str, uint8_t* rd, size_t* len) 1763 { 1764 char* end; 1765 uint16_t r = (uint16_t)strtol((char*)str, &end, 10); 1766 if(*end != 0) 1767 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1768 if(*len < 2) 1769 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1770 sldns_write_uint16(rd, r); 1771 *len = 2; 1772 return LDNS_WIREPARSE_ERR_OK; 1773 } 1774 1775 int sldns_str2wire_int32_buf(const char* str, uint8_t* rd, size_t* len) 1776 { 1777 char* end; 1778 uint32_t r; 1779 errno = 0; /* must set to zero before call, 1780 note race condition on errno */ 1781 if(*str == '-') 1782 r = (uint32_t)strtol((char*)str, &end, 10); 1783 else r = (uint32_t)strtoul((char*)str, &end, 10); 1784 if(*end != 0) 1785 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1786 if(errno == ERANGE) 1787 return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW; 1788 if(*len < 4) 1789 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1790 sldns_write_uint32(rd, r); 1791 *len = 4; 1792 return LDNS_WIREPARSE_ERR_OK; 1793 } 1794 1795 int sldns_str2wire_a_buf(const char* str, uint8_t* rd, size_t* len) 1796 { 1797 struct in_addr address; 1798 if(inet_pton(AF_INET, (char*)str, &address) != 1) 1799 return LDNS_WIREPARSE_ERR_SYNTAX_IP4; 1800 if(*len < sizeof(address)) 1801 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1802 memmove(rd, &address, sizeof(address)); 1803 *len = sizeof(address); 1804 return LDNS_WIREPARSE_ERR_OK; 1805 } 1806 1807 int sldns_str2wire_aaaa_buf(const char* str, uint8_t* rd, size_t* len) 1808 { 1809 #ifdef AF_INET6 1810 uint8_t address[LDNS_IP6ADDRLEN + 1]; 1811 if(inet_pton(AF_INET6, (char*)str, address) != 1) 1812 return LDNS_WIREPARSE_ERR_SYNTAX_IP6; 1813 if(*len < LDNS_IP6ADDRLEN) 1814 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1815 memmove(rd, address, LDNS_IP6ADDRLEN); 1816 *len = LDNS_IP6ADDRLEN; 1817 return LDNS_WIREPARSE_ERR_OK; 1818 #else 1819 return LDNS_WIREPARSE_ERR_NOT_IMPL; 1820 #endif 1821 } 1822 1823 int sldns_str2wire_str_buf(const char* str, uint8_t* rd, size_t* len) 1824 { 1825 uint8_t ch = 0; 1826 size_t sl = 0; 1827 const char* s = str; 1828 /* skip length byte */ 1829 if(*len < 1) 1830 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1831 1832 /* read characters */ 1833 while(sldns_parse_char(&ch, &s)) { 1834 if(sl >= 255) 1835 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, s-str); 1836 if(*len < sl+2) 1837 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1838 s-str); 1839 rd[++sl] = ch; 1840 } 1841 if(!s) 1842 return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; 1843 rd[0] = (uint8_t)sl; 1844 *len = sl+1; 1845 return LDNS_WIREPARSE_ERR_OK; 1846 } 1847 1848 int sldns_str2wire_apl_buf(const char* str, uint8_t* rd, size_t* len) 1849 { 1850 const char *my_str = str; 1851 1852 char my_ip_str[64]; 1853 size_t ip_str_len; 1854 1855 uint16_t family; 1856 int negation; 1857 size_t adflength = 0; 1858 uint8_t data[16+4]; 1859 uint8_t prefix; 1860 size_t i; 1861 1862 if(*my_str == '\0') { 1863 /* empty APL element, no data, no string */ 1864 *len = 0; 1865 return LDNS_WIREPARSE_ERR_OK; 1866 } 1867 1868 /* [!]afi:address/prefix */ 1869 if (strlen(my_str) < 2 1870 || strchr(my_str, ':') == NULL 1871 || strchr(my_str, '/') == NULL 1872 || strchr(my_str, ':') > strchr(my_str, '/')) { 1873 return LDNS_WIREPARSE_ERR_INVALID_STR; 1874 } 1875 1876 if (my_str[0] == '!') { 1877 negation = 1; 1878 my_str += 1; 1879 } else { 1880 negation = 0; 1881 } 1882 1883 family = (uint16_t) atoi(my_str); 1884 1885 my_str = strchr(my_str, ':') + 1; 1886 1887 /* need ip addr and only ip addr for inet_pton */ 1888 ip_str_len = (size_t) (strchr(my_str, '/') - my_str); 1889 if(ip_str_len+1 > sizeof(my_ip_str)) 1890 return LDNS_WIREPARSE_ERR_INVALID_STR; 1891 (void)strlcpy(my_ip_str, my_str, sizeof(my_ip_str)); 1892 my_ip_str[ip_str_len] = 0; 1893 1894 if (family == 1) { 1895 /* ipv4 */ 1896 if(inet_pton(AF_INET, my_ip_str, data+4) == 0) 1897 return LDNS_WIREPARSE_ERR_INVALID_STR; 1898 for (i = 0; i < 4; i++) { 1899 if (data[i+4] != 0) { 1900 adflength = i + 1; 1901 } 1902 } 1903 } else if (family == 2) { 1904 /* ipv6 */ 1905 if (inet_pton(AF_INET6, my_ip_str, data+4) == 0) 1906 return LDNS_WIREPARSE_ERR_INVALID_STR; 1907 for (i = 0; i < 16; i++) { 1908 if (data[i+4] != 0) { 1909 adflength = i + 1; 1910 } 1911 } 1912 } else { 1913 /* unknown family */ 1914 return LDNS_WIREPARSE_ERR_INVALID_STR; 1915 } 1916 1917 my_str = strchr(my_str, '/') + 1; 1918 prefix = (uint8_t) atoi(my_str); 1919 1920 sldns_write_uint16(data, family); 1921 data[2] = prefix; 1922 data[3] = (uint8_t)adflength; 1923 if (negation) { 1924 /* set bit 1 of byte 3 */ 1925 data[3] = data[3] | 0x80; 1926 } 1927 1928 if(*len < 4+adflength) 1929 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1930 memmove(rd, data, 4+adflength); 1931 *len = 4+adflength; 1932 return LDNS_WIREPARSE_ERR_OK; 1933 } 1934 1935 int sldns_str2wire_b64_buf(const char* str, uint8_t* rd, size_t* len) 1936 { 1937 size_t sz = sldns_b64_pton_calculate_size(strlen(str)); 1938 int n; 1939 if(strcmp(str, "0") == 0) { 1940 *len = 0; 1941 return LDNS_WIREPARSE_ERR_OK; 1942 } 1943 if(*len < sz) 1944 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1945 n = sldns_b64_pton(str, rd, *len); 1946 if(n < 0) 1947 return LDNS_WIREPARSE_ERR_SYNTAX_B64; 1948 *len = (size_t)n; 1949 return LDNS_WIREPARSE_ERR_OK; 1950 } 1951 1952 int sldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len) 1953 { 1954 size_t slen = strlen(str); 1955 size_t sz = sldns_b32_pton_calculate_size(slen); 1956 int n; 1957 if(*len < 1+sz) 1958 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1959 rd[0] = (uint8_t)sz; 1960 n = sldns_b32_pton_extended_hex(str, slen, rd+1, *len-1); 1961 if(n < 0) 1962 return LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT; 1963 *len = (size_t)n+1; 1964 return LDNS_WIREPARSE_ERR_OK; 1965 } 1966 1967 /** see if the string ends, or ends in whitespace */ 1968 static int 1969 sldns_is_last_of_string(const char* str) 1970 { 1971 if(*str == 0) return 1; 1972 while(isspace((unsigned char)*str)) 1973 str++; 1974 if(*str == 0) return 1; 1975 return 0; 1976 } 1977 1978 int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len) 1979 { 1980 const char* s = str; 1981 size_t dlen = 0; /* number of hexdigits parsed */ 1982 while(*s) { 1983 if(isspace((unsigned char)*s)) { 1984 s++; 1985 continue; 1986 } 1987 if(dlen == 0 && *s == '0' && sldns_is_last_of_string(s+1)) { 1988 *len = 0; 1989 return LDNS_WIREPARSE_ERR_OK; 1990 } 1991 if(!isxdigit((unsigned char)*s)) 1992 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1993 if(*len < dlen/2 + 1) 1994 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1995 s-str); 1996 if((dlen&1)==0) 1997 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1998 else rd[dlen/2] += (uint8_t)sldns_hexdigit_to_int(*s++); 1999 dlen++; 2000 } 2001 if((dlen&1)!=0) 2002 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 2003 *len = dlen/2; 2004 return LDNS_WIREPARSE_ERR_OK; 2005 } 2006 2007 int sldns_str2wire_nsec_buf(const char* str, uint8_t* rd, size_t* len) 2008 { 2009 const char *delim = "\n\t "; 2010 char token[64]; /* for a type name */ 2011 size_t type_count = 0; 2012 int block; 2013 size_t used = 0; 2014 uint16_t maxtype = 0; 2015 uint8_t typebits[8192]; /* 65536 bits */ 2016 uint8_t window_in_use[256]; 2017 2018 /* string in buffer */ 2019 sldns_buffer strbuf; 2020 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 2021 2022 /* parse the types */ 2023 memset(typebits, 0, sizeof(typebits)); 2024 memset(window_in_use, 0, sizeof(window_in_use)); 2025 while(sldns_buffer_remaining(&strbuf) > 0 && 2026 sldns_bget_token(&strbuf, token, delim, sizeof(token)) != -1) { 2027 uint16_t t = sldns_get_rr_type_by_name(token); 2028 if(token[0] == 0) 2029 continue; 2030 if(t == 0 && strcmp(token, "TYPE0") != 0) 2031 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 2032 sldns_buffer_position(&strbuf)); 2033 typebits[t/8] |= (0x80>>(t%8)); 2034 window_in_use[t/256] = 1; 2035 type_count++; 2036 if(t > maxtype) maxtype = t; 2037 } 2038 2039 /* empty NSEC bitmap */ 2040 if(type_count == 0) { 2041 *len = 0; 2042 return LDNS_WIREPARSE_ERR_OK; 2043 } 2044 2045 /* encode windows {u8 windowblock, u8 bitmaplength, 0-32u8 bitmap}, 2046 * block is 0-255 upper octet of types, length if 0-32. */ 2047 for(block = 0; block <= (int)maxtype/256; block++) { 2048 int i, blocklen = 0; 2049 if(!window_in_use[block]) 2050 continue; 2051 for(i=0; i<32; i++) { 2052 if(typebits[block*32+i] != 0) 2053 blocklen = i+1; 2054 } 2055 if(blocklen == 0) 2056 continue; /* empty window should have been !in_use */ 2057 if(used+blocklen+2 > *len) 2058 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2059 rd[used+0] = (uint8_t)block; 2060 rd[used+1] = (uint8_t)blocklen; 2061 for(i=0; i<blocklen; i++) { 2062 rd[used+2+i] = typebits[block*32+i]; 2063 } 2064 used += blocklen+2; 2065 } 2066 *len = used; 2067 return LDNS_WIREPARSE_ERR_OK; 2068 } 2069 2070 int sldns_str2wire_type_buf(const char* str, uint8_t* rd, size_t* len) 2071 { 2072 uint16_t t = sldns_get_rr_type_by_name(str); 2073 if(t == 0 && strcmp(str, "TYPE0") != 0) 2074 return LDNS_WIREPARSE_ERR_SYNTAX_TYPE; 2075 if(*len < 2) 2076 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2077 sldns_write_uint16(rd, t); 2078 *len = 2; 2079 return LDNS_WIREPARSE_ERR_OK; 2080 } 2081 2082 int sldns_str2wire_class_buf(const char* str, uint8_t* rd, size_t* len) 2083 { 2084 uint16_t c = sldns_get_rr_class_by_name(str); 2085 if(c == 0 && strcmp(str, "CLASS0") != 0) 2086 return LDNS_WIREPARSE_ERR_SYNTAX_CLASS; 2087 if(*len < 2) 2088 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2089 sldns_write_uint16(rd, c); 2090 *len = 2; 2091 return LDNS_WIREPARSE_ERR_OK; 2092 } 2093 2094 /* An certificate alg field can either be specified as a 8 bits number 2095 * or by its symbolic name. Handle both */ 2096 int sldns_str2wire_cert_alg_buf(const char* str, uint8_t* rd, size_t* len) 2097 { 2098 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_cert_algorithms, 2099 str); 2100 if(*len < 2) 2101 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2102 if(lt) { 2103 sldns_write_uint16(rd, (uint16_t)lt->id); 2104 } else { 2105 int s = sldns_str2wire_int16_buf(str, rd, len); 2106 if(s) return s; 2107 if(sldns_read_uint16(rd) == 0) 2108 return LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM; 2109 } 2110 *len = 2; 2111 return LDNS_WIREPARSE_ERR_OK; 2112 } 2113 2114 /* An alg field can either be specified as a 8 bits number 2115 * or by its symbolic name. Handle both */ 2116 int sldns_str2wire_alg_buf(const char* str, uint8_t* rd, size_t* len) 2117 { 2118 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_algorithms, str); 2119 if(*len < 1) 2120 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2121 if(lt) { 2122 rd[0] = (uint8_t)lt->id; 2123 *len = 1; 2124 } else { 2125 /* try as-is (a number) */ 2126 return sldns_str2wire_int8_buf(str, rd, len); 2127 } 2128 return LDNS_WIREPARSE_ERR_OK; 2129 } 2130 2131 int sldns_str2wire_tsigerror_buf(const char* str, uint8_t* rd, size_t* len) 2132 { 2133 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_tsig_errors, str); 2134 if(*len < 2) 2135 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2136 if(lt) { 2137 sldns_write_uint16(rd, (uint16_t)lt->id); 2138 *len = 2; 2139 } else { 2140 /* try as-is (a number) */ 2141 return sldns_str2wire_int16_buf(str, rd, len); 2142 } 2143 return LDNS_WIREPARSE_ERR_OK; 2144 } 2145 2146 int sldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len) 2147 { 2148 /* convert a time YYYYDDMMHHMMSS to wireformat */ 2149 struct tm tm; 2150 if(*len < 4) 2151 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2152 2153 /* Try to scan the time... */ 2154 memset(&tm, 0, sizeof(tm)); 2155 if (strlen(str) == 14 && sscanf(str, "%4d%2d%2d%2d%2d%2d", 2156 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 2157 &tm.tm_min, &tm.tm_sec) == 6) { 2158 tm.tm_year -= 1900; 2159 tm.tm_mon--; 2160 /* Check values */ 2161 if (tm.tm_year < 70) 2162 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 2163 if (tm.tm_mon < 0 || tm.tm_mon > 11) 2164 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 2165 if (tm.tm_mday < 1 || tm.tm_mday > 31) 2166 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 2167 if (tm.tm_hour < 0 || tm.tm_hour > 23) 2168 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 2169 if (tm.tm_min < 0 || tm.tm_min > 59) 2170 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 2171 if (tm.tm_sec < 0 || tm.tm_sec > 59) 2172 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 2173 2174 sldns_write_uint32(rd, (uint32_t)sldns_mktime_from_utc(&tm)); 2175 } else { 2176 /* handle it as 32 bits timestamp */ 2177 char *end; 2178 uint32_t l = (uint32_t)strtol((char*)str, &end, 10); 2179 if(*end != 0) 2180 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TIME, 2181 end-(char*)str); 2182 sldns_write_uint32(rd, l); 2183 } 2184 *len = 4; 2185 return LDNS_WIREPARSE_ERR_OK; 2186 } 2187 2188 int sldns_str2wire_tsigtime_buf(const char* str, uint8_t* rd, size_t* len) 2189 { 2190 char* end; 2191 uint64_t t = (uint64_t)strtol((char*)str, &end, 10); 2192 uint16_t high; 2193 uint32_t low; 2194 if(*end != 0) 2195 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TIME, end-str); 2196 if(*len < 6) 2197 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2198 high = (uint16_t)(t>>32); 2199 low = (uint32_t)(t); 2200 sldns_write_uint16(rd, high); 2201 sldns_write_uint32(rd+2, low); 2202 *len = 6; 2203 return LDNS_WIREPARSE_ERR_OK; 2204 } 2205 2206 int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len) 2207 { 2208 const char* end; 2209 int overflow; 2210 uint32_t p = sldns_str2period(str, &end, &overflow); 2211 if(*end != 0) 2212 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str); 2213 if(overflow) 2214 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, 2215 end-str); 2216 if(*len < 4) 2217 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2218 sldns_write_uint32(rd, p); 2219 *len = 4; 2220 return LDNS_WIREPARSE_ERR_OK; 2221 } 2222 2223 /** read "<digits>[.<digits>][mM]" into mantissa exponent format for LOC type */ 2224 static int 2225 loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) 2226 { 2227 uint32_t meters = 0, cm = 0, val; 2228 char* cm_endstr; 2229 while (isblank((unsigned char)*my_str)) { 2230 my_str++; 2231 } 2232 meters = (uint32_t)strtol(my_str, &my_str, 10); 2233 if (*my_str == '.') { 2234 my_str++; 2235 cm = (uint32_t)strtol(my_str, &cm_endstr, 10); 2236 if(cm_endstr == my_str + 1) 2237 cm *= 10; 2238 my_str = cm_endstr; 2239 } 2240 if (meters >= 1) { 2241 *e = 2; 2242 val = meters; 2243 } else { 2244 *e = 0; 2245 val = cm; 2246 } 2247 while(val >= 10) { 2248 (*e)++; 2249 val /= 10; 2250 } 2251 *m = (uint8_t)val; 2252 2253 if (*e > 9) 2254 return 0; 2255 if (*my_str == 'm' || *my_str == 'M') { 2256 my_str++; 2257 } 2258 *endstr = my_str; 2259 return 1; 2260 } 2261 2262 int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len) 2263 { 2264 uint32_t latitude = 0; 2265 uint32_t longitude = 0; 2266 uint32_t altitude = 0; 2267 2268 uint32_t equator = (uint32_t)1<<31; /* 2**31 */ 2269 2270 /* only support version 0 */ 2271 uint32_t h = 0; 2272 uint32_t m = 0; 2273 uint8_t size_b = 1, size_e = 2; 2274 uint8_t horiz_pre_b = 1, horiz_pre_e = 6; 2275 uint8_t vert_pre_b = 1, vert_pre_e = 3; 2276 2277 double s = 0.0; 2278 int northerness; 2279 int easterness; 2280 2281 char *my_str = (char *) str; 2282 2283 if (isdigit((unsigned char) *my_str)) { 2284 h = (uint32_t) strtol(my_str, &my_str, 10); 2285 } else { 2286 return LDNS_WIREPARSE_ERR_INVALID_STR; 2287 } 2288 2289 while (isblank((unsigned char) *my_str)) { 2290 my_str++; 2291 } 2292 2293 if (isdigit((unsigned char) *my_str)) { 2294 m = (uint32_t) strtol(my_str, &my_str, 10); 2295 } else if (*my_str == 'N' || *my_str == 'S') { 2296 goto north; 2297 } else { 2298 return LDNS_WIREPARSE_ERR_INVALID_STR; 2299 } 2300 2301 while (isblank((unsigned char) *my_str)) { 2302 my_str++; 2303 } 2304 2305 if (isdigit((unsigned char) *my_str)) { 2306 s = strtod(my_str, &my_str); 2307 } 2308 2309 /* skip blanks before northerness */ 2310 while (isblank((unsigned char) *my_str)) { 2311 my_str++; 2312 } 2313 2314 north: 2315 if (*my_str == 'N') { 2316 northerness = 1; 2317 } else if (*my_str == 'S') { 2318 northerness = 0; 2319 } else { 2320 return LDNS_WIREPARSE_ERR_INVALID_STR; 2321 } 2322 2323 my_str++; 2324 2325 /* store number */ 2326 s = 1000.0 * s; 2327 /* add a little to make floor in conversion a round */ 2328 s += 0.0005; 2329 latitude = (uint32_t) s; 2330 latitude += 1000 * 60 * m; 2331 latitude += 1000 * 60 * 60 * h; 2332 if (northerness) { 2333 latitude = equator + latitude; 2334 } else { 2335 latitude = equator - latitude; 2336 } 2337 while (isblank((unsigned char)*my_str)) { 2338 my_str++; 2339 } 2340 2341 if (isdigit((unsigned char) *my_str)) { 2342 h = (uint32_t) strtol(my_str, &my_str, 10); 2343 } else { 2344 return LDNS_WIREPARSE_ERR_INVALID_STR; 2345 } 2346 2347 while (isblank((unsigned char) *my_str)) { 2348 my_str++; 2349 } 2350 2351 if (isdigit((unsigned char) *my_str)) { 2352 m = (uint32_t) strtol(my_str, &my_str, 10); 2353 } else if (*my_str == 'E' || *my_str == 'W') { 2354 goto east; 2355 } else { 2356 return LDNS_WIREPARSE_ERR_INVALID_STR; 2357 } 2358 2359 while (isblank((unsigned char)*my_str)) { 2360 my_str++; 2361 } 2362 2363 if (isdigit((unsigned char) *my_str)) { 2364 s = strtod(my_str, &my_str); 2365 } 2366 2367 /* skip blanks before easterness */ 2368 while (isblank((unsigned char)*my_str)) { 2369 my_str++; 2370 } 2371 2372 east: 2373 if (*my_str == 'E') { 2374 easterness = 1; 2375 } else if (*my_str == 'W') { 2376 easterness = 0; 2377 } else { 2378 return LDNS_WIREPARSE_ERR_INVALID_STR; 2379 } 2380 2381 my_str++; 2382 2383 /* store number */ 2384 s *= 1000.0; 2385 /* add a little to make floor in conversion a round */ 2386 s += 0.0005; 2387 longitude = (uint32_t) s; 2388 longitude += 1000 * 60 * m; 2389 longitude += 1000 * 60 * 60 * h; 2390 2391 if (easterness) { 2392 longitude += equator; 2393 } else { 2394 longitude = equator - longitude; 2395 } 2396 2397 altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + 2398 10000000.0 + 0.5); 2399 if (*my_str == 'm' || *my_str == 'M') { 2400 my_str++; 2401 } 2402 2403 if (strlen(my_str) > 0) { 2404 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) 2405 return LDNS_WIREPARSE_ERR_INVALID_STR; 2406 } 2407 2408 if (strlen(my_str) > 0) { 2409 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) 2410 return LDNS_WIREPARSE_ERR_INVALID_STR; 2411 } 2412 2413 if (strlen(my_str) > 0) { 2414 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) 2415 return LDNS_WIREPARSE_ERR_INVALID_STR; 2416 } 2417 2418 if(*len < 16) 2419 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2420 rd[0] = 0; 2421 rd[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); 2422 rd[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); 2423 rd[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); 2424 sldns_write_uint32(rd + 4, latitude); 2425 sldns_write_uint32(rd + 8, longitude); 2426 sldns_write_uint32(rd + 12, altitude); 2427 *len = 16; 2428 return LDNS_WIREPARSE_ERR_OK; 2429 } 2430 2431 static void 2432 ldns_tolower_str(char* s) 2433 { 2434 if(s) { 2435 while(*s) { 2436 *s = (char)tolower((unsigned char)*s); 2437 s++; 2438 } 2439 } 2440 } 2441 2442 int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) 2443 { 2444 int rd_len = 1; 2445 int have_proto = 0; 2446 char token[50], proto_str[50]; 2447 sldns_buffer strbuf; 2448 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 2449 proto_str[0]=0; 2450 2451 /* check we have one byte for proto */ 2452 if(*len < 1) 2453 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2454 2455 while(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) > 0) { 2456 ldns_tolower_str(token); 2457 if(!have_proto) { 2458 struct protoent *p = getprotobyname(token); 2459 have_proto = 1; 2460 if(p) rd[0] = (uint8_t)p->p_proto; 2461 else if(strcasecmp(token, "tcp")==0) rd[0]=6; 2462 else if(strcasecmp(token, "udp")==0) rd[0]=17; 2463 else rd[0] = (uint8_t)atoi(token); 2464 (void)strlcpy(proto_str, token, sizeof(proto_str)); 2465 } else { 2466 int serv_port; 2467 if(atoi(token) != 0) serv_port=atoi(token); 2468 else if(strcmp(token, "0") == 0) serv_port=0; 2469 else if(strcasecmp(token, "domain")==0) serv_port=53; 2470 else { 2471 struct servent *serv = getservbyname(token, proto_str); 2472 if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port); 2473 else { 2474 #ifdef HAVE_ENDSERVENT 2475 endservent(); 2476 #endif 2477 #ifdef HAVE_ENDPROTOENT 2478 endprotoent(); 2479 #endif 2480 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 2481 sldns_buffer_position(&strbuf)); 2482 } 2483 } 2484 if(serv_port < 0 || serv_port > 65535) { 2485 #ifdef HAVE_ENDSERVENT 2486 endservent(); 2487 #endif 2488 #ifdef HAVE_ENDPROTOENT 2489 endprotoent(); 2490 #endif 2491 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 2492 sldns_buffer_position(&strbuf)); 2493 } 2494 if(rd_len < 1+serv_port/8+1) { 2495 /* bitmap is larger, init new bytes at 0 */ 2496 if(*len < 1+(size_t)serv_port/8+1) { 2497 #ifdef HAVE_ENDSERVENT 2498 endservent(); 2499 #endif 2500 #ifdef HAVE_ENDPROTOENT 2501 endprotoent(); 2502 #endif 2503 return RET_ERR( 2504 LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 2505 sldns_buffer_position(&strbuf)); 2506 } 2507 memset(rd+rd_len, 0, 1+(size_t)serv_port/8+1-rd_len); 2508 rd_len = 1+serv_port/8+1; 2509 } 2510 rd[1+ serv_port/8] |= (1 << (7 - serv_port % 8)); 2511 } 2512 } 2513 *len = (size_t)rd_len; 2514 2515 #ifdef HAVE_ENDSERVENT 2516 endservent(); 2517 #endif 2518 #ifdef HAVE_ENDPROTOENT 2519 endprotoent(); 2520 #endif 2521 return LDNS_WIREPARSE_ERR_OK; 2522 } 2523 2524 int sldns_str2wire_nsap_buf(const char* str, uint8_t* rd, size_t* len) 2525 { 2526 const char* s = str; 2527 size_t slen; 2528 size_t dlen = 0; /* number of hexdigits parsed */ 2529 2530 /* just a hex string with optional dots? */ 2531 if (s[0] != '0' || s[1] != 'x') 2532 return LDNS_WIREPARSE_ERR_INVALID_STR; 2533 s += 2; 2534 slen = strlen(s); 2535 if(slen > LDNS_MAX_RDFLEN*2) 2536 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 2537 while(*s) { 2538 if(isspace((unsigned char)*s) || *s == '.') { 2539 s++; 2540 continue; 2541 } 2542 if(!isxdigit((unsigned char)*s)) 2543 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 2544 if(*len < dlen/2 + 1) 2545 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 2546 s-str); 2547 if((dlen&1)==0) 2548 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 2549 else rd[dlen/2] += sldns_hexdigit_to_int(*s++); 2550 dlen++; 2551 } 2552 if((dlen&1)!=0) 2553 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 2554 *len = dlen/2; 2555 return LDNS_WIREPARSE_ERR_OK; 2556 } 2557 2558 int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len) 2559 { 2560 const char* s = str; 2561 size_t slen = strlen(str); 2562 size_t dlen = 0; /* number of hexdigits parsed for hex, 2563 digits for E.164 */ 2564 2565 if(slen > LDNS_MAX_RDFLEN*2) 2566 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 2567 if(*len < 1) 2568 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2569 if(*s == 0) { 2570 /* empty string */ 2571 rd[0] = 0; 2572 *len = 1; 2573 return LDNS_WIREPARSE_ERR_OK; 2574 } 2575 if(s[0] == '+') { 2576 rd[0] = 1; /* E.164 format */ 2577 /* digits '0'..'9', with skipped dots. */ 2578 s++; 2579 while(*s) { 2580 if(isspace((unsigned char)*s) || *s == '.') { 2581 s++; 2582 continue; 2583 } 2584 if(*s < '0' || *s > '9') 2585 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-str); 2586 if(*len < dlen + 2) 2587 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 2588 s-str); 2589 rd[dlen+1] = *s++; 2590 dlen++; 2591 } 2592 *len = dlen+1; 2593 return LDNS_WIREPARSE_ERR_OK; 2594 } 2595 2596 rd[0] = 0; /* AESA format */ 2597 /* hex, with skipped dots. */ 2598 while(*s) { 2599 if(isspace((unsigned char)*s) || *s == '.') { 2600 s++; 2601 continue; 2602 } 2603 if(!isxdigit((unsigned char)*s)) 2604 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 2605 if(*len < dlen/2 + 2) 2606 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 2607 s-str); 2608 if((dlen&1)==0) 2609 rd[dlen/2 + 1] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 2610 else rd[dlen/2 + 1] += sldns_hexdigit_to_int(*s++); 2611 dlen++; 2612 } 2613 if((dlen&1)!=0) 2614 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 2615 *len = dlen/2 + 1; 2616 return LDNS_WIREPARSE_ERR_OK; 2617 } 2618 2619 int sldns_str2wire_ipseckey_buf(const char* str, uint8_t* rd, size_t* len) 2620 { 2621 size_t gwlen = 0, keylen = 0; 2622 int s; 2623 uint8_t gwtype; 2624 char token[512]; 2625 sldns_buffer strbuf; 2626 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 2627 2628 if(*len < 3) 2629 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2630 /* precedence */ 2631 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 2632 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 2633 sldns_buffer_position(&strbuf)); 2634 rd[0] = (uint8_t)atoi(token); 2635 /* gateway_type */ 2636 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 2637 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 2638 sldns_buffer_position(&strbuf)); 2639 rd[1] = (uint8_t)atoi(token); 2640 gwtype = rd[1]; 2641 /* algorithm */ 2642 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 2643 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 2644 sldns_buffer_position(&strbuf)); 2645 rd[2] = (uint8_t)atoi(token); 2646 2647 /* gateway */ 2648 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 2649 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 2650 sldns_buffer_position(&strbuf)); 2651 if(gwtype == 0) { 2652 /* NOGATEWAY */ 2653 if(strcmp(token, ".") != 0) 2654 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 2655 sldns_buffer_position(&strbuf)); 2656 gwlen = 0; 2657 } else if(gwtype == 1) { 2658 /* IP4 */ 2659 gwlen = *len - 3; 2660 s = sldns_str2wire_a_buf(token, rd+3, &gwlen); 2661 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 2662 } else if(gwtype == 2) { 2663 /* IP6 */ 2664 gwlen = *len - 3; 2665 s = sldns_str2wire_aaaa_buf(token, rd+3, &gwlen); 2666 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 2667 } else if(gwtype == 3) { 2668 /* DNAME */ 2669 gwlen = *len - 3; 2670 s = sldns_str2wire_dname_buf(token, rd+3, &gwlen); 2671 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 2672 } else { 2673 /* unknown gateway type */ 2674 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 2675 sldns_buffer_position(&strbuf)); 2676 } 2677 /* double check for size */ 2678 if(*len < 3 + gwlen) 2679 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 2680 sldns_buffer_position(&strbuf)); 2681 2682 /* publickey in remainder of strbuf */ 2683 keylen = *len - 3 - gwlen; 2684 s = sldns_str2wire_b64_buf((const char*)sldns_buffer_current(&strbuf), 2685 rd+3+gwlen, &keylen); 2686 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 2687 2688 *len = 3 + gwlen + keylen; 2689 return LDNS_WIREPARSE_ERR_OK; 2690 } 2691 2692 int sldns_str2wire_nsec3_salt_buf(const char* str, uint8_t* rd, size_t* len) 2693 { 2694 int i, salt_length_str = (int)strlen(str); 2695 if (salt_length_str == 1 && str[0] == '-') { 2696 salt_length_str = 0; 2697 } else if (salt_length_str % 2 != 0) { 2698 return LDNS_WIREPARSE_ERR_SYNTAX_HEX; 2699 } 2700 if (salt_length_str > 512) 2701 return LDNS_WIREPARSE_ERR_SYNTAX_HEX; 2702 if(*len < 1+(size_t)salt_length_str / 2) 2703 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2704 rd[0] = (uint8_t) (salt_length_str / 2); 2705 for (i = 0; i < salt_length_str; i += 2) { 2706 if (isxdigit((unsigned char)str[i]) && 2707 isxdigit((unsigned char)str[i+1])) { 2708 rd[1+i/2] = (uint8_t)(sldns_hexdigit_to_int(str[i])*16 2709 + sldns_hexdigit_to_int(str[i+1])); 2710 } else { 2711 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, i); 2712 } 2713 } 2714 *len = 1 + (size_t)rd[0]; 2715 return LDNS_WIREPARSE_ERR_OK; 2716 } 2717 2718 int sldns_str2wire_ilnp64_buf(const char* str, uint8_t* rd, size_t* len) 2719 { 2720 unsigned int a, b, c, d; 2721 uint16_t shorts[4]; 2722 int l; 2723 if(*len < sizeof(shorts)) 2724 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2725 2726 if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 || 2727 l != (int)strlen(str) || /* more data to read */ 2728 strpbrk(str, "+-") /* signed hexes */ 2729 ) 2730 return LDNS_WIREPARSE_ERR_SYNTAX_ILNP64; 2731 shorts[0] = htons(a); 2732 shorts[1] = htons(b); 2733 shorts[2] = htons(c); 2734 shorts[3] = htons(d); 2735 memmove(rd, &shorts, sizeof(shorts)); 2736 *len = sizeof(shorts); 2737 return LDNS_WIREPARSE_ERR_OK; 2738 } 2739 2740 int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len) 2741 { 2742 unsigned int a, b, c, d, e, f; 2743 int l; 2744 2745 if(*len < 6) 2746 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2747 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n", 2748 &a, &b, &c, &d, &e, &f, &l) != 6 || 2749 l != (int)strlen(str)) 2750 return LDNS_WIREPARSE_ERR_SYNTAX_EUI48; 2751 rd[0] = a; 2752 rd[1] = b; 2753 rd[2] = c; 2754 rd[3] = d; 2755 rd[4] = e; 2756 rd[5] = f; 2757 *len = 6; 2758 return LDNS_WIREPARSE_ERR_OK; 2759 } 2760 2761 int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len) 2762 { 2763 unsigned int a, b, c, d, e, f, g, h; 2764 int l; 2765 2766 if(*len < 8) 2767 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2768 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n", 2769 &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 || 2770 l != (int)strlen(str)) 2771 return LDNS_WIREPARSE_ERR_SYNTAX_EUI64; 2772 rd[0] = a; 2773 rd[1] = b; 2774 rd[2] = c; 2775 rd[3] = d; 2776 rd[4] = e; 2777 rd[5] = f; 2778 rd[6] = g; 2779 rd[7] = h; 2780 *len = 8; 2781 return LDNS_WIREPARSE_ERR_OK; 2782 } 2783 2784 int sldns_str2wire_unquoted_buf(const char* str, uint8_t* rd, size_t* len) 2785 { 2786 return sldns_str2wire_str_buf(str, rd, len); 2787 } 2788 2789 int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len) 2790 { 2791 size_t slen = strlen(str); 2792 const char* ptr; 2793 2794 if (slen > 255) 2795 return LDNS_WIREPARSE_ERR_SYNTAX_TAG; 2796 if(*len < slen+1) 2797 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2798 for (ptr = str; *ptr; ptr++) { 2799 if(!isalnum((unsigned char)*ptr)) 2800 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TAG, ptr-str); 2801 } 2802 rd[0] = (uint8_t)slen; 2803 memmove(rd+1, str, slen); 2804 *len = slen+1; 2805 return LDNS_WIREPARSE_ERR_OK; 2806 } 2807 2808 int sldns_str2wire_long_str_buf(const char* str, uint8_t* rd, size_t* len) 2809 { 2810 uint8_t ch = 0; 2811 const char* pstr = str; 2812 size_t length = 0; 2813 2814 /* Fill data with parsed bytes */ 2815 while (sldns_parse_char(&ch, &pstr)) { 2816 if(*len < length+1) 2817 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2818 rd[length++] = ch; 2819 } 2820 if(!pstr) 2821 return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; 2822 *len = length; 2823 return LDNS_WIREPARSE_ERR_OK; 2824 } 2825 2826 int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len) 2827 { 2828 char* s, *end; 2829 int e; 2830 size_t hitlen, pklen = 0; 2831 /* presentation format: 2832 * pk-algo HIThex pubkeybase64 2833 * wireformat: 2834 * hitlen[1byte] pkalgo[1byte] pubkeylen[2byte] [hit] [pubkey] */ 2835 if(*len < 4) 2836 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2837 2838 /* read PK algorithm */ 2839 rd[1] = (uint8_t)strtol((char*)str, &s, 10); 2840 if(*s != ' ') 2841 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str); 2842 s++; 2843 while(*s == ' ') 2844 s++; 2845 2846 /* read HIT hex tag */ 2847 /* zero terminate the tag (replace later) */ 2848 end = strchr(s, ' '); 2849 if(!end) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-(char*)str); 2850 *end = 0; 2851 hitlen = *len - 4; 2852 if((e = sldns_str2wire_hex_buf(s, rd+4, &hitlen)) != 0) { 2853 *end = ' '; 2854 return RET_ERR_SHIFT(e, s-(char*)str); 2855 } 2856 if(hitlen > 255) { 2857 *end = ' '; 2858 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+255*2); 2859 } 2860 rd[0] = (uint8_t)hitlen; 2861 *end = ' '; 2862 s = end+1; 2863 2864 /* read pubkey base64 sequence */ 2865 pklen = *len - 4 - hitlen; 2866 if((e = sldns_str2wire_b64_buf(s, rd+4+hitlen, &pklen)) != 0) 2867 return RET_ERR_SHIFT(e, s-(char*)str); 2868 if(pklen > 65535) 2869 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+65535); 2870 sldns_write_uint16(rd+2, (uint16_t)pklen); 2871 2872 *len = 4 + hitlen + pklen; 2873 return LDNS_WIREPARSE_ERR_OK; 2874 } 2875 2876 int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len) 2877 { 2878 char* s; 2879 int n; 2880 n = strtol(str, &s, 10); 2881 if(n < 0) /* negative number not allowed */ 2882 return LDNS_WIREPARSE_ERR_SYNTAX; 2883 if(*len < ((size_t)n)+2) 2884 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2885 if(n > 65535) 2886 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 2887 2888 if(n == 0) { 2889 sldns_write_uint16(rd, 0); 2890 *len = 2; 2891 return LDNS_WIREPARSE_ERR_OK; 2892 } 2893 if(*s != ' ') 2894 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str); 2895 s++; 2896 while(*s == ' ') 2897 s++; 2898 2899 n = sldns_b64_pton(s, rd+2, (*len)-2); 2900 if(n < 0) 2901 return LDNS_WIREPARSE_ERR_SYNTAX_B64; 2902 sldns_write_uint16(rd, (uint16_t)n); 2903 *len = ((size_t)n)+2; 2904 return LDNS_WIREPARSE_ERR_OK; 2905 } 2906