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 size_t rdata_len = rr_cur_len - dname_len - 10; 847 uint8_t *rdata = rr+dname_len + 10; 848 849 /* skip 1st rdata field SvcPriority (uint16_t) */ 850 if (rdata_len < sizeof(uint16_t)) 851 return LDNS_WIREPARSE_ERR_OK; 852 853 rdata_len -= sizeof(uint16_t); 854 rdata += sizeof(uint16_t); 855 856 /* skip 2nd rdata field dname */ 857 while (rdata_len && *rdata != 0) { 858 uint8_t label_len; 859 860 if (*rdata & 0xC0) 861 return LDNS_WIREPARSE_ERR_OK; 862 863 label_len = *rdata + 1; 864 if (rdata_len < label_len) 865 return LDNS_WIREPARSE_ERR_OK; 866 867 rdata_len -= label_len; 868 rdata += label_len; 869 } 870 /* The root label is one more character, so smaller 871 * than 1 + 1 means no Svcparam Keys */ 872 if (rdata_len < 2 || *rdata != 0) 873 return LDNS_WIREPARSE_ERR_OK; 874 875 rdata_len -= 1; 876 rdata += 1; 877 return sldns_str2wire_check_svcbparams(rdata, rdata_len); 878 879 } 880 return LDNS_WIREPARSE_ERR_OK; 881 } 882 883 /* 884 * trailing spaces are allowed 885 * leading spaces are not allowed 886 * allow ttl to be optional 887 * class is optional too 888 * if ttl is missing, and default_ttl is 0, use DEF_TTL 889 * allow ttl to be written as 1d3h 890 * So the RR should look like. e.g. 891 * miek.nl. 3600 IN MX 10 elektron.atoom.net 892 * or 893 * miek.nl. 1h IN MX 10 elektron.atoom.net 894 * or 895 * miek.nl. IN MX 10 elektron.atoom.net 896 */ 897 static int 898 sldns_str2wire_rr_buf_internal(const char* str, uint8_t* rr, size_t* len, 899 size_t* dname_len, uint32_t default_ttl, uint8_t* origin, 900 size_t origin_len, uint8_t* prev, size_t prev_len, int question) 901 { 902 int status; 903 int not_there = 0; 904 char token[LDNS_MAX_RDFLEN+1]; 905 uint32_t ttl = 0; 906 uint16_t tp = 0, cl = 0; 907 size_t ddlen = 0; 908 909 /* string in buffer */ 910 sldns_buffer strbuf; 911 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 912 if(!dname_len) dname_len = &ddlen; 913 914 /* parse the owner */ 915 if((status=rrinternal_get_owner(&strbuf, rr, len, dname_len, origin, 916 origin_len, prev, prev_len, token, sizeof(token))) != 0) 917 return status; 918 919 /* parse the [ttl] [class] <type> */ 920 if((status=rrinternal_get_ttl(&strbuf, token, sizeof(token), 921 ¬_there, &ttl, default_ttl)) != 0) 922 return status; 923 if((status=rrinternal_get_class(&strbuf, token, sizeof(token), 924 ¬_there, &cl)) != 0) 925 return status; 926 if((status=rrinternal_get_type(&strbuf, token, sizeof(token), 927 ¬_there, &tp)) != 0) 928 return status; 929 /* put ttl, class, type into the rr result */ 930 if((status=rrinternal_write_typeclassttl(&strbuf, rr, *len, *dname_len, tp, cl, 931 ttl, question)) != 0) 932 return status; 933 /* for a question-RR we are done, no rdata */ 934 if(question) { 935 *len = *dname_len + 4; 936 return LDNS_WIREPARSE_ERR_OK; 937 } 938 939 /* rdata */ 940 if((status=rrinternal_parse_rdata(&strbuf, token, sizeof(token), 941 rr, len, *dname_len, tp, origin, origin_len)) != 0) 942 return status; 943 944 return LDNS_WIREPARSE_ERR_OK; 945 } 946 947 int sldns_str2wire_rr_buf(const char* str, uint8_t* rr, size_t* len, 948 size_t* dname_len, uint32_t default_ttl, uint8_t* origin, 949 size_t origin_len, uint8_t* prev, size_t prev_len) 950 { 951 return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, 952 default_ttl, origin, origin_len, prev, prev_len, 0); 953 } 954 955 int sldns_str2wire_rr_question_buf(const char* str, uint8_t* rr, size_t* len, 956 size_t* dname_len, uint8_t* origin, size_t origin_len, uint8_t* prev, 957 size_t prev_len) 958 { 959 return sldns_str2wire_rr_buf_internal(str, rr, len, dname_len, 960 0, origin, origin_len, prev, prev_len, 1); 961 } 962 963 uint16_t sldns_wirerr_get_type(uint8_t* rr, size_t len, size_t dname_len) 964 { 965 if(len < dname_len+2) 966 return 0; 967 return sldns_read_uint16(rr+dname_len); 968 } 969 970 uint16_t sldns_wirerr_get_class(uint8_t* rr, size_t len, size_t dname_len) 971 { 972 if(len < dname_len+4) 973 return 0; 974 return sldns_read_uint16(rr+dname_len+2); 975 } 976 977 uint32_t sldns_wirerr_get_ttl(uint8_t* rr, size_t len, size_t dname_len) 978 { 979 if(len < dname_len+8) 980 return 0; 981 return sldns_read_uint32(rr+dname_len+4); 982 } 983 984 uint16_t sldns_wirerr_get_rdatalen(uint8_t* rr, size_t len, size_t dname_len) 985 { 986 if(len < dname_len+10) 987 return 0; 988 return sldns_read_uint16(rr+dname_len+8); 989 } 990 991 uint8_t* sldns_wirerr_get_rdata(uint8_t* rr, size_t len, size_t dname_len) 992 { 993 if(len < dname_len+10) 994 return NULL; 995 return rr+dname_len+10; 996 } 997 998 uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len) 999 { 1000 if(len < dname_len+10) 1001 return NULL; 1002 return rr+dname_len+8; 1003 } 1004 1005 const char* sldns_get_errorstr_parse(int e) 1006 { 1007 sldns_lookup_table *lt; 1008 lt = sldns_lookup_by_id(sldns_wireparse_errors, LDNS_WIREPARSE_ERROR(e)); 1009 return lt?lt->name:"unknown error"; 1010 } 1011 1012 /* Strip whitespace from the start and the end of <line>. */ 1013 char * 1014 sldns_strip_ws(char *line) 1015 { 1016 char *s = line, *e; 1017 1018 for (s = line; *s && isspace((unsigned char)*s); s++) 1019 ; 1020 for (e = strchr(s, 0); e > s+2 && isspace((unsigned char)e[-1]) && e[-2] != '\\'; e--) 1021 ; 1022 *e = 0; 1023 return s; 1024 } 1025 1026 int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, 1027 struct sldns_file_parse_state* parse_state) 1028 { 1029 char line[LDNS_RR_BUF_SIZE+1]; 1030 ssize_t size; 1031 1032 /* read an entire line in from the file */ 1033 if((size = sldns_fget_token_l(in, line, LDNS_PARSE_SKIP_SPACE, 1034 LDNS_RR_BUF_SIZE, parse_state?&parse_state->lineno:NULL)) 1035 == -1) { 1036 /* if last line was empty, we are now at feof, which is not 1037 * always a parse error (happens when for instance last line 1038 * was a comment) 1039 */ 1040 return LDNS_WIREPARSE_ERR_SYNTAX; 1041 } 1042 1043 /* we can have the situation, where we've read ok, but still got 1044 * no bytes to play with, in this case size is 0 */ 1045 if(size == 0) { 1046 if(*len > 0) 1047 rr[0] = 0; 1048 *len = 0; 1049 *dname_len = 0; 1050 return LDNS_WIREPARSE_ERR_OK; 1051 } 1052 1053 if(strncmp(line, "$ORIGIN", 7) == 0 && isspace((unsigned char)line[7])) { 1054 int s; 1055 strlcpy((char*)rr, line, *len); 1056 *len = 0; 1057 *dname_len = 0; 1058 if(!parse_state) return LDNS_WIREPARSE_ERR_OK; 1059 parse_state->origin_len = sizeof(parse_state->origin); 1060 s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8), 1061 parse_state->origin, &parse_state->origin_len); 1062 if(s) parse_state->origin_len = 0; 1063 return s; 1064 } else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) { 1065 const char* end = NULL; 1066 int overflow = 0; 1067 strlcpy((char*)rr, line, *len); 1068 *len = 0; 1069 *dname_len = 0; 1070 if(!parse_state) return LDNS_WIREPARSE_ERR_OK; 1071 parse_state->default_ttl = sldns_str2period( 1072 sldns_strip_ws(line+5), &end, &overflow); 1073 if(overflow) 1074 return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW; 1075 } else if (strncmp(line, "$INCLUDE", 8) == 0) { 1076 strlcpy((char*)rr, line, *len); 1077 *len = 0; 1078 *dname_len = 0; 1079 return LDNS_WIREPARSE_ERR_INCLUDE; 1080 } else if (strncmp(line, "$", 1) == 0) { 1081 strlcpy((char*)rr, line, *len); 1082 *len = 0; 1083 *dname_len = 0; 1084 return LDNS_WIREPARSE_ERR_INCLUDE; 1085 } else { 1086 int r = sldns_str2wire_rr_buf(line, rr, len, dname_len, 1087 parse_state?parse_state->default_ttl:0, 1088 (parse_state&&parse_state->origin_len)? 1089 parse_state->origin:NULL, 1090 parse_state?parse_state->origin_len:0, 1091 (parse_state&&parse_state->prev_rr_len)? 1092 parse_state->prev_rr:NULL, 1093 parse_state?parse_state->prev_rr_len:0); 1094 if(r == LDNS_WIREPARSE_ERR_OK && (*dname_len) != 0 && 1095 parse_state && 1096 (*dname_len) <= sizeof(parse_state->prev_rr)) { 1097 memmove(parse_state->prev_rr, rr, *dname_len); 1098 parse_state->prev_rr_len = (*dname_len); 1099 } 1100 if(r == LDNS_WIREPARSE_ERR_OK && parse_state) { 1101 parse_state->default_ttl = sldns_wirerr_get_ttl( 1102 rr, *len, *dname_len); 1103 } 1104 return r; 1105 } 1106 return LDNS_WIREPARSE_ERR_OK; 1107 } 1108 1109 static int 1110 sldns_str2wire_svcparam_key_lookup(const char *key, size_t key_len) 1111 { 1112 char buf[64]; 1113 char *endptr; 1114 unsigned long int key_value; 1115 1116 if (key_len >= 4 && key_len <= 8 && !strncmp(key, "key", 3)) { 1117 memcpy(buf, key + 3, key_len - 3); 1118 buf[key_len - 3] = 0; 1119 key_value = strtoul(buf, &endptr, 10); 1120 1121 if (endptr > buf /* digits seen */ 1122 && *endptr == 0 /* no non-digit chars after digits */ 1123 && key_value <= 65535) /* no overflow */ 1124 return key_value; 1125 1126 } else switch (key_len) { 1127 case 3: 1128 if (!strncmp(key, "ech", key_len)) 1129 return SVCB_KEY_ECH; 1130 break; 1131 1132 case 4: 1133 if (!strncmp(key, "alpn", key_len)) 1134 return SVCB_KEY_ALPN; 1135 if (!strncmp(key, "port", key_len)) 1136 return SVCB_KEY_PORT; 1137 break; 1138 1139 case 7: 1140 if (!strncmp(key, "dohpath", key_len)) 1141 return SVCB_KEY_DOHPATH; 1142 break; 1143 1144 case 8: 1145 if (!strncmp(key, "ipv4hint", key_len)) 1146 return SVCB_KEY_IPV4HINT; 1147 if (!strncmp(key, "ipv6hint", key_len)) 1148 return SVCB_KEY_IPV6HINT; 1149 break; 1150 1151 case 9: 1152 if (!strncmp(key, "mandatory", key_len)) 1153 return SVCB_KEY_MANDATORY; 1154 if (!strncmp(key, "echconfig", key_len)) 1155 return SVCB_KEY_ECH; /* allow "echconfig" as well as "ech" */ 1156 break; 1157 1158 case 15: 1159 if (!strncmp(key, "no-default-alpn", key_len)) 1160 return SVCB_KEY_NO_DEFAULT_ALPN; 1161 break; 1162 1163 default: 1164 break; 1165 } 1166 1167 /* Although the returned value might be used by the caller, 1168 * the parser has erred, so the zone will not be loaded. 1169 */ 1170 return -1; 1171 } 1172 1173 static int 1174 sldns_str2wire_svcparam_port(const char* val, uint8_t* rd, size_t* rd_len) 1175 { 1176 unsigned long int port; 1177 char *endptr; 1178 1179 if (*rd_len < 6) 1180 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1181 1182 port = strtoul(val, &endptr, 10); 1183 1184 if (endptr > val /* digits seen */ 1185 && *endptr == 0 /* no non-digit chars after digits */ 1186 && port <= 65535) { /* no overflow */ 1187 1188 sldns_write_uint16(rd, SVCB_KEY_PORT); 1189 sldns_write_uint16(rd + 2, sizeof(uint16_t)); 1190 sldns_write_uint16(rd + 4, port); 1191 *rd_len = 6; 1192 1193 return LDNS_WIREPARSE_ERR_OK; 1194 } 1195 1196 return LDNS_WIREPARSE_ERR_SVCB_PORT_VALUE_SYNTAX; 1197 } 1198 1199 static int 1200 sldns_str2wire_svcbparam_ipv4hint(const char* val, uint8_t* rd, size_t* rd_len) 1201 { 1202 size_t count; 1203 char ip_str[INET_ADDRSTRLEN+1]; 1204 char *next_ip_str; 1205 size_t i; 1206 1207 for (i = 0, count = 1; val[i]; i++) { 1208 if (val[i] == ',') 1209 count += 1; 1210 if (count > SVCB_MAX_COMMA_SEPARATED_VALUES) { 1211 return LDNS_WIREPARSE_ERR_SVCB_IPV4_TOO_MANY_ADDRESSES; 1212 } 1213 } 1214 1215 if (*rd_len < (LDNS_IP4ADDRLEN * count) + 4) 1216 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1217 1218 /* count is number of comma's in val + 1; so the actual number of IPv4 1219 * addresses in val 1220 */ 1221 sldns_write_uint16(rd, SVCB_KEY_IPV4HINT); 1222 sldns_write_uint16(rd + 2, LDNS_IP4ADDRLEN * count); 1223 *rd_len = 4; 1224 1225 while (count) { 1226 if (!(next_ip_str = strchr(val, ','))) { 1227 if (inet_pton(AF_INET, val, rd + *rd_len) != 1) 1228 break; 1229 *rd_len += LDNS_IP4ADDRLEN; 1230 1231 assert(count == 1); 1232 1233 } else if (next_ip_str - val >= (int)sizeof(ip_str)) 1234 break; 1235 1236 else { 1237 memcpy(ip_str, val, next_ip_str - val); 1238 ip_str[next_ip_str - val] = 0; 1239 if (inet_pton(AF_INET, ip_str, rd + *rd_len) != 1) { 1240 break; 1241 } 1242 *rd_len += LDNS_IP4ADDRLEN; 1243 1244 val = next_ip_str + 1; 1245 } 1246 count--; 1247 } 1248 if (count) /* verify that we parsed all values */ 1249 return LDNS_WIREPARSE_ERR_SYNTAX_IP4; 1250 1251 return LDNS_WIREPARSE_ERR_OK; 1252 } 1253 1254 static int 1255 sldns_str2wire_svcbparam_ipv6hint(const char* val, uint8_t* rd, size_t* rd_len) 1256 { 1257 size_t count; 1258 char ip_str[INET6_ADDRSTRLEN+1]; 1259 char *next_ip_str; 1260 size_t i; 1261 1262 for (i = 0, count = 1; val[i]; i++) { 1263 if (val[i] == ',') 1264 count += 1; 1265 if (count > SVCB_MAX_COMMA_SEPARATED_VALUES) { 1266 return LDNS_WIREPARSE_ERR_SVCB_IPV6_TOO_MANY_ADDRESSES; 1267 } 1268 } 1269 1270 if (*rd_len < (LDNS_IP6ADDRLEN * count) + 4) 1271 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1272 1273 /* count is number of comma's in val + 1; so the actual number of IPv6 1274 * addresses in val 1275 */ 1276 sldns_write_uint16(rd, SVCB_KEY_IPV6HINT); 1277 sldns_write_uint16(rd + 2, LDNS_IP6ADDRLEN * count); 1278 *rd_len = 4; 1279 1280 while (count) { 1281 if (!(next_ip_str = strchr(val, ','))) { 1282 if (inet_pton(AF_INET6, val, rd + *rd_len) != 1) 1283 break; 1284 *rd_len += LDNS_IP6ADDRLEN; 1285 1286 assert(count == 1); 1287 1288 } else if (next_ip_str - val >= (int)sizeof(ip_str)) 1289 break; 1290 1291 else { 1292 memcpy(ip_str, val, next_ip_str - val); 1293 ip_str[next_ip_str - val] = 0; 1294 if (inet_pton(AF_INET6, ip_str, rd + *rd_len) != 1) { 1295 break; 1296 } 1297 *rd_len += LDNS_IP6ADDRLEN; 1298 1299 val = next_ip_str + 1; 1300 } 1301 count--; 1302 } 1303 if (count) /* verify that we parsed all values */ 1304 return LDNS_WIREPARSE_ERR_SYNTAX_IP6; 1305 1306 return LDNS_WIREPARSE_ERR_OK; 1307 } 1308 1309 /* compare function used for sorting uint16_t's */ 1310 static int 1311 sldns_network_uint16_cmp(const void *a, const void *b) 1312 { 1313 return ((int)sldns_read_uint16(a)) - ((int)sldns_read_uint16(b)); 1314 } 1315 1316 static int 1317 sldns_str2wire_svcbparam_mandatory(const char* val, uint8_t* rd, size_t* rd_len) 1318 { 1319 size_t i, count, val_len; 1320 char* next_key; 1321 1322 val_len = strlen(val); 1323 1324 for (i = 0, count = 1; val[i]; i++) { 1325 if (val[i] == ',') 1326 count += 1; 1327 if (count > SVCB_MAX_COMMA_SEPARATED_VALUES) { 1328 return LDNS_WIREPARSE_ERR_SVCB_MANDATORY_TOO_MANY_KEYS; 1329 } 1330 } 1331 if (sizeof(uint16_t) * (count + 2) > *rd_len) 1332 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1333 1334 sldns_write_uint16(rd, SVCB_KEY_MANDATORY); 1335 sldns_write_uint16(rd + 2, sizeof(uint16_t) * count); 1336 *rd_len = 4; 1337 1338 while (1) { 1339 int svcparamkey; 1340 1341 if (!(next_key = strchr(val, ','))) { 1342 svcparamkey = sldns_str2wire_svcparam_key_lookup(val, val_len); 1343 1344 if (svcparamkey < 0) { 1345 return LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY; 1346 } 1347 1348 sldns_write_uint16(rd + *rd_len, svcparamkey); 1349 *rd_len += 2; 1350 break; 1351 } else { 1352 svcparamkey = sldns_str2wire_svcparam_key_lookup(val, next_key - val); 1353 1354 if (svcparamkey < 0) { 1355 return LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY; 1356 } 1357 1358 sldns_write_uint16(rd + *rd_len, 1359 svcparamkey); 1360 *rd_len += 2; 1361 } 1362 1363 val_len -= next_key - val + 1; 1364 val = next_key + 1; /* skip the comma */ 1365 } 1366 1367 /* In draft-ietf-dnsop-svcb-https-06 Section 7: 1368 * 1369 * "In wire format, the keys are represented by their numeric 1370 * values in network byte order, concatenated in ascending order." 1371 */ 1372 qsort((void *)(rd + 4), count, sizeof(uint16_t), sldns_network_uint16_cmp); 1373 1374 /* The code below revolves around semantic errors in the SVCParam set. 1375 * So long as we do not distinguish between running Unbound as a primary 1376 * or as a secondary, we default to secondary behavior and we ignore the 1377 * semantic errors. */ 1378 #ifdef SVCB_SEMANTIC_ERRORS 1379 /* In draft-ietf-dnsop-svcb-https-06 Section 8 1380 * automatically mandatory MUST NOT appear in its own value-list 1381 */ 1382 if (sldns_read_uint16(rd + 4) == SVCB_KEY_MANDATORY) 1383 return LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY; 1384 1385 /* Guarantee key uniqueness. After the sort we only need to 1386 * compare neighbouring keys */ 1387 if (count > 1) { 1388 for (i = 0; i < count - 1; i++) { 1389 uint8_t* current_pos = (rd + 4 + (sizeof(uint16_t) * i)); 1390 uint16_t key = sldns_read_uint16(current_pos); 1391 1392 if (key == sldns_read_uint16(current_pos + 2)) { 1393 return LDNS_WIREPARSE_ERR_SVCB_MANDATORY_DUPLICATE_KEY; 1394 } 1395 } 1396 } 1397 #endif 1398 return LDNS_WIREPARSE_ERR_OK; 1399 } 1400 1401 static int 1402 sldns_str2wire_svcbparam_ech_value(const char* val, uint8_t* rd, size_t* rd_len) 1403 { 1404 uint8_t buffer[LDNS_MAX_RDFLEN]; 1405 int wire_len; 1406 1407 /* single 0 represents empty buffer */ 1408 if(strcmp(val, "0") == 0) { 1409 if (*rd_len < 4) 1410 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1411 sldns_write_uint16(rd, SVCB_KEY_ECH); 1412 sldns_write_uint16(rd + 2, 0); 1413 1414 return LDNS_WIREPARSE_ERR_OK; 1415 } 1416 1417 wire_len = sldns_b64_pton(val, buffer, LDNS_MAX_RDFLEN); 1418 1419 if (wire_len <= 0) { 1420 return LDNS_WIREPARSE_ERR_SYNTAX_B64; 1421 } else if ((unsigned)wire_len + 4 > *rd_len) { 1422 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1423 } else { 1424 sldns_write_uint16(rd, SVCB_KEY_ECH); 1425 sldns_write_uint16(rd + 2, wire_len); 1426 memcpy(rd + 4, buffer, wire_len); 1427 *rd_len = 4 + wire_len; 1428 1429 return LDNS_WIREPARSE_ERR_OK; 1430 } 1431 } 1432 1433 static const char* 1434 sldns_str2wire_svcbparam_parse_next_unescaped_comma(const char *val) 1435 { 1436 while (*val) { 1437 /* Only return when the comma is not escaped*/ 1438 if (*val == '\\'){ 1439 ++val; 1440 if (!*val) 1441 break; 1442 } else if (*val == ',') 1443 return val; 1444 1445 val++; 1446 } 1447 return NULL; 1448 } 1449 1450 /* The source is already properly unescaped, this double unescaping is purely to allow for 1451 * comma's in comma separated alpn lists. 1452 * 1453 * In draft-ietf-dnsop-svcb-https-06 Section 7: 1454 * To enable simpler parsing, this SvcParamValue MUST NOT contain escape sequences. 1455 */ 1456 static size_t 1457 sldns_str2wire_svcbparam_parse_copy_unescaped(uint8_t *dst, 1458 const char *src, size_t len) 1459 { 1460 uint8_t *orig_dst = dst; 1461 1462 while (len) { 1463 if (*src == '\\') { 1464 src++; 1465 len--; 1466 if (!len) 1467 break; 1468 } 1469 *dst++ = *src++; 1470 len--; 1471 } 1472 return (size_t)(dst - orig_dst); 1473 } 1474 1475 static int 1476 sldns_str2wire_svcbparam_alpn_value(const char* val, 1477 uint8_t* rd, size_t* rd_len) 1478 { 1479 uint8_t unescaped_dst[LDNS_MAX_RDFLEN]; 1480 uint8_t *dst = unescaped_dst; 1481 const char *next_str; 1482 size_t str_len; 1483 size_t dst_len; 1484 size_t val_len; 1485 1486 val_len = strlen(val); 1487 1488 if (val_len > sizeof(unescaped_dst)) { 1489 return LDNS_WIREPARSE_ERR_SVCB_ALPN_KEY_TOO_LARGE; 1490 } 1491 while (val_len) { 1492 size_t key_len; 1493 1494 str_len = (next_str = sldns_str2wire_svcbparam_parse_next_unescaped_comma(val)) 1495 ? (size_t)(next_str - val) : val_len; 1496 1497 if (str_len > 255) { 1498 return LDNS_WIREPARSE_ERR_SVCB_ALPN_KEY_TOO_LARGE; 1499 } 1500 1501 key_len = sldns_str2wire_svcbparam_parse_copy_unescaped(dst + 1, val, str_len); 1502 *dst++ = key_len; 1503 dst += key_len; 1504 1505 if (!next_str) 1506 break; 1507 1508 /* skip the comma in the next iteration */ 1509 val_len -= next_str - val + 1; 1510 val = next_str + 1; 1511 } 1512 dst_len = dst - unescaped_dst; 1513 if (*rd_len < 4 + dst_len) 1514 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1515 sldns_write_uint16(rd, SVCB_KEY_ALPN); 1516 sldns_write_uint16(rd + 2, dst_len); 1517 memcpy(rd + 4, unescaped_dst, dst_len); 1518 *rd_len = 4 + dst_len; 1519 1520 return LDNS_WIREPARSE_ERR_OK; 1521 } 1522 1523 static int 1524 sldns_str2wire_svcbparam_dohpath_value(const char* val, 1525 uint8_t* rd, size_t* rd_len) 1526 { 1527 size_t val_len; 1528 1529 /* RFC6570#section-2.1 1530 * "The characters outside of expressions in a URI Template string are 1531 * intended to be copied literally" 1532 * Practically this means we do not have to look for "double escapes" 1533 * like in the alpn value list. 1534 */ 1535 1536 val_len = strlen(val); 1537 1538 if (*rd_len < 4 + val_len) { 1539 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1540 } 1541 1542 sldns_write_uint16(rd, SVCB_KEY_DOHPATH); 1543 sldns_write_uint16(rd + 2, val_len); 1544 memcpy(rd + 4, val, val_len); 1545 *rd_len = 4 + val_len; 1546 1547 return LDNS_WIREPARSE_ERR_OK; 1548 } 1549 1550 static int 1551 sldns_str2wire_svcparam_value(const char *key, size_t key_len, 1552 const char *val, uint8_t* rd, size_t* rd_len) 1553 { 1554 size_t str_len; 1555 int svcparamkey = sldns_str2wire_svcparam_key_lookup(key, key_len); 1556 1557 if (svcparamkey < 0) { 1558 return LDNS_WIREPARSE_ERR_SVCB_UNKNOWN_KEY; 1559 } 1560 1561 /* key without value */ 1562 if (val == NULL) { 1563 switch (svcparamkey) { 1564 #ifdef SVCB_SEMANTIC_ERRORS 1565 case SVCB_KEY_MANDATORY: 1566 case SVCB_KEY_ALPN: 1567 case SVCB_KEY_PORT: 1568 case SVCB_KEY_IPV4HINT: 1569 case SVCB_KEY_IPV6HINT: 1570 case SVCB_KEY_DOHPATH: 1571 return LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM; 1572 #endif 1573 default: 1574 if (*rd_len < 4) 1575 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1576 sldns_write_uint16(rd, svcparamkey); 1577 sldns_write_uint16(rd + 2, 0); 1578 *rd_len = 4; 1579 1580 return LDNS_WIREPARSE_ERR_OK; 1581 } 1582 } 1583 1584 /* value is non-empty */ 1585 switch (svcparamkey) { 1586 case SVCB_KEY_PORT: 1587 return sldns_str2wire_svcparam_port(val, rd, rd_len); 1588 case SVCB_KEY_IPV4HINT: 1589 return sldns_str2wire_svcbparam_ipv4hint(val, rd, rd_len); 1590 case SVCB_KEY_IPV6HINT: 1591 return sldns_str2wire_svcbparam_ipv6hint(val, rd, rd_len); 1592 case SVCB_KEY_MANDATORY: 1593 return sldns_str2wire_svcbparam_mandatory(val, rd, rd_len); 1594 #ifdef SVCB_SEMANTIC_ERRORS 1595 case SVCB_KEY_NO_DEFAULT_ALPN: 1596 return LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE; 1597 #endif 1598 case SVCB_KEY_ECH: 1599 return sldns_str2wire_svcbparam_ech_value(val, rd, rd_len); 1600 case SVCB_KEY_ALPN: 1601 return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len); 1602 case SVCB_KEY_DOHPATH: 1603 return sldns_str2wire_svcbparam_dohpath_value(val, rd, rd_len); 1604 default: 1605 str_len = strlen(val); 1606 if (*rd_len < 4 + str_len) 1607 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1608 sldns_write_uint16(rd, svcparamkey); 1609 sldns_write_uint16(rd + 2, str_len); 1610 memcpy(rd + 4, val, str_len); 1611 *rd_len = 4 + str_len; 1612 1613 return LDNS_WIREPARSE_ERR_OK; 1614 } 1615 1616 return LDNS_WIREPARSE_ERR_GENERAL; 1617 } 1618 1619 static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_len) 1620 { 1621 const char* eq_pos; 1622 char unescaped_val[LDNS_MAX_RDFLEN]; 1623 char* val_out = unescaped_val; 1624 const char* val_in; 1625 1626 eq_pos = strchr(str, '='); 1627 1628 /* case: key=value */ 1629 if (eq_pos != NULL && eq_pos[1]) { 1630 val_in = eq_pos + 1; 1631 1632 /* unescape characters and "" blocks */ 1633 if (*val_in == '"') { 1634 val_in++; 1635 while (*val_in != '"' 1636 && (size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val) 1637 && sldns_parse_char( (uint8_t*) val_out, &val_in)) { 1638 val_out++; 1639 } 1640 } else { 1641 while ((size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val) 1642 && sldns_parse_char( (uint8_t*) val_out, &val_in)) { 1643 val_out++; 1644 } 1645 } 1646 *val_out = 0; 1647 1648 return sldns_str2wire_svcparam_value(str, eq_pos - str, 1649 unescaped_val[0] ? unescaped_val : NULL, rd, rd_len); 1650 } 1651 /* case: key= */ 1652 else if (eq_pos != NULL && !(eq_pos[1])) { 1653 return sldns_str2wire_svcparam_value(str, eq_pos - str, NULL, rd, rd_len); 1654 } 1655 /* case: key */ 1656 else { 1657 return sldns_str2wire_svcparam_value(str, strlen(str), NULL, rd, rd_len); 1658 } 1659 } 1660 1661 int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len, 1662 sldns_rdf_type rdftype) 1663 { 1664 switch (rdftype) { 1665 case LDNS_RDF_TYPE_DNAME: 1666 return sldns_str2wire_dname_buf(str, rd, len); 1667 case LDNS_RDF_TYPE_INT8: 1668 return sldns_str2wire_int8_buf(str, rd, len); 1669 case LDNS_RDF_TYPE_INT16: 1670 return sldns_str2wire_int16_buf(str, rd, len); 1671 case LDNS_RDF_TYPE_INT32: 1672 return sldns_str2wire_int32_buf(str, rd, len); 1673 case LDNS_RDF_TYPE_A: 1674 return sldns_str2wire_a_buf(str, rd, len); 1675 case LDNS_RDF_TYPE_AAAA: 1676 return sldns_str2wire_aaaa_buf(str, rd, len); 1677 case LDNS_RDF_TYPE_STR: 1678 return sldns_str2wire_str_buf(str, rd, len); 1679 case LDNS_RDF_TYPE_APL: 1680 return sldns_str2wire_apl_buf(str, rd, len); 1681 case LDNS_RDF_TYPE_B64: 1682 return sldns_str2wire_b64_buf(str, rd, len); 1683 case LDNS_RDF_TYPE_B32_EXT: 1684 return sldns_str2wire_b32_ext_buf(str, rd, len); 1685 case LDNS_RDF_TYPE_HEX: 1686 return sldns_str2wire_hex_buf(str, rd, len); 1687 case LDNS_RDF_TYPE_NSEC: 1688 return sldns_str2wire_nsec_buf(str, rd, len); 1689 case LDNS_RDF_TYPE_TYPE: 1690 return sldns_str2wire_type_buf(str, rd, len); 1691 case LDNS_RDF_TYPE_CLASS: 1692 return sldns_str2wire_class_buf(str, rd, len); 1693 case LDNS_RDF_TYPE_CERT_ALG: 1694 return sldns_str2wire_cert_alg_buf(str, rd, len); 1695 case LDNS_RDF_TYPE_ALG: 1696 return sldns_str2wire_alg_buf(str, rd, len); 1697 case LDNS_RDF_TYPE_TIME: 1698 return sldns_str2wire_time_buf(str, rd, len); 1699 case LDNS_RDF_TYPE_PERIOD: 1700 return sldns_str2wire_period_buf(str, rd, len); 1701 case LDNS_RDF_TYPE_TSIGTIME: 1702 return sldns_str2wire_tsigtime_buf(str, rd, len); 1703 case LDNS_RDF_TYPE_LOC: 1704 return sldns_str2wire_loc_buf(str, rd, len); 1705 case LDNS_RDF_TYPE_WKS: 1706 return sldns_str2wire_wks_buf(str, rd, len); 1707 case LDNS_RDF_TYPE_NSAP: 1708 return sldns_str2wire_nsap_buf(str, rd, len); 1709 case LDNS_RDF_TYPE_ATMA: 1710 return sldns_str2wire_atma_buf(str, rd, len); 1711 case LDNS_RDF_TYPE_IPSECKEY: 1712 return sldns_str2wire_ipseckey_buf(str, rd, len); 1713 case LDNS_RDF_TYPE_NSEC3_SALT: 1714 return sldns_str2wire_nsec3_salt_buf(str, rd, len); 1715 case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER: 1716 return sldns_str2wire_b32_ext_buf(str, rd, len); 1717 case LDNS_RDF_TYPE_ILNP64: 1718 return sldns_str2wire_ilnp64_buf(str, rd, len); 1719 case LDNS_RDF_TYPE_EUI48: 1720 return sldns_str2wire_eui48_buf(str, rd, len); 1721 case LDNS_RDF_TYPE_EUI64: 1722 return sldns_str2wire_eui64_buf(str, rd, len); 1723 case LDNS_RDF_TYPE_UNQUOTED: 1724 return sldns_str2wire_unquoted_buf(str, rd, len); 1725 case LDNS_RDF_TYPE_TAG: 1726 return sldns_str2wire_tag_buf(str, rd, len); 1727 case LDNS_RDF_TYPE_LONG_STR: 1728 return sldns_str2wire_long_str_buf(str, rd, len); 1729 case LDNS_RDF_TYPE_TSIGERROR: 1730 return sldns_str2wire_tsigerror_buf(str, rd, len); 1731 case LDNS_RDF_TYPE_HIP: 1732 return sldns_str2wire_hip_buf(str, rd, len); 1733 case LDNS_RDF_TYPE_INT16_DATA: 1734 return sldns_str2wire_int16_data_buf(str, rd, len); 1735 case LDNS_RDF_TYPE_SVCPARAM: 1736 return sldns_str2wire_svcparam_buf(str, rd, len); 1737 case LDNS_RDF_TYPE_UNKNOWN: 1738 case LDNS_RDF_TYPE_SERVICE: 1739 return LDNS_WIREPARSE_ERR_NOT_IMPL; 1740 case LDNS_RDF_TYPE_NONE: 1741 default: 1742 break; 1743 } 1744 return LDNS_WIREPARSE_ERR_GENERAL; 1745 } 1746 1747 int sldns_str2wire_int8_buf(const char* str, uint8_t* rd, size_t* len) 1748 { 1749 char* end; 1750 uint8_t r = (uint8_t)strtol((char*)str, &end, 10); 1751 if(*end != 0) 1752 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1753 if(*len < 1) 1754 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1755 rd[0] = r; 1756 *len = 1; 1757 return LDNS_WIREPARSE_ERR_OK; 1758 } 1759 1760 int sldns_str2wire_int16_buf(const char* str, uint8_t* rd, size_t* len) 1761 { 1762 char* end; 1763 uint16_t r = (uint16_t)strtol((char*)str, &end, 10); 1764 if(*end != 0) 1765 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1766 if(*len < 2) 1767 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1768 sldns_write_uint16(rd, r); 1769 *len = 2; 1770 return LDNS_WIREPARSE_ERR_OK; 1771 } 1772 1773 int sldns_str2wire_int32_buf(const char* str, uint8_t* rd, size_t* len) 1774 { 1775 char* end; 1776 uint32_t r; 1777 errno = 0; /* must set to zero before call, 1778 note race condition on errno */ 1779 if(*str == '-') 1780 r = (uint32_t)strtol((char*)str, &end, 10); 1781 else r = (uint32_t)strtoul((char*)str, &end, 10); 1782 if(*end != 0) 1783 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, end-(char*)str); 1784 if(errno == ERANGE) 1785 return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW; 1786 if(*len < 4) 1787 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1788 sldns_write_uint32(rd, r); 1789 *len = 4; 1790 return LDNS_WIREPARSE_ERR_OK; 1791 } 1792 1793 int sldns_str2wire_a_buf(const char* str, uint8_t* rd, size_t* len) 1794 { 1795 struct in_addr address; 1796 if(inet_pton(AF_INET, (char*)str, &address) != 1) 1797 return LDNS_WIREPARSE_ERR_SYNTAX_IP4; 1798 if(*len < sizeof(address)) 1799 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1800 memmove(rd, &address, sizeof(address)); 1801 *len = sizeof(address); 1802 return LDNS_WIREPARSE_ERR_OK; 1803 } 1804 1805 int sldns_str2wire_aaaa_buf(const char* str, uint8_t* rd, size_t* len) 1806 { 1807 #ifdef AF_INET6 1808 uint8_t address[LDNS_IP6ADDRLEN + 1]; 1809 if(inet_pton(AF_INET6, (char*)str, address) != 1) 1810 return LDNS_WIREPARSE_ERR_SYNTAX_IP6; 1811 if(*len < LDNS_IP6ADDRLEN) 1812 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1813 memmove(rd, address, LDNS_IP6ADDRLEN); 1814 *len = LDNS_IP6ADDRLEN; 1815 return LDNS_WIREPARSE_ERR_OK; 1816 #else 1817 return LDNS_WIREPARSE_ERR_NOT_IMPL; 1818 #endif 1819 } 1820 1821 int sldns_str2wire_str_buf(const char* str, uint8_t* rd, size_t* len) 1822 { 1823 uint8_t ch = 0; 1824 size_t sl = 0; 1825 const char* s = str; 1826 /* skip length byte */ 1827 if(*len < 1) 1828 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1829 1830 /* read characters */ 1831 while(sldns_parse_char(&ch, &s)) { 1832 if(sl >= 255) 1833 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, s-str); 1834 if(*len < sl+2) 1835 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1836 s-str); 1837 rd[++sl] = ch; 1838 } 1839 if(!s) 1840 return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; 1841 rd[0] = (uint8_t)sl; 1842 *len = sl+1; 1843 return LDNS_WIREPARSE_ERR_OK; 1844 } 1845 1846 int sldns_str2wire_apl_buf(const char* str, uint8_t* rd, size_t* len) 1847 { 1848 const char *my_str = str; 1849 1850 char my_ip_str[64]; 1851 size_t ip_str_len; 1852 1853 uint16_t family; 1854 int negation; 1855 size_t adflength = 0; 1856 uint8_t data[16+4]; 1857 uint8_t prefix; 1858 size_t i; 1859 1860 if(*my_str == '\0') { 1861 /* empty APL element, no data, no string */ 1862 *len = 0; 1863 return LDNS_WIREPARSE_ERR_OK; 1864 } 1865 1866 /* [!]afi:address/prefix */ 1867 if (strlen(my_str) < 2 1868 || strchr(my_str, ':') == NULL 1869 || strchr(my_str, '/') == NULL 1870 || strchr(my_str, ':') > strchr(my_str, '/')) { 1871 return LDNS_WIREPARSE_ERR_INVALID_STR; 1872 } 1873 1874 if (my_str[0] == '!') { 1875 negation = 1; 1876 my_str += 1; 1877 } else { 1878 negation = 0; 1879 } 1880 1881 family = (uint16_t) atoi(my_str); 1882 1883 my_str = strchr(my_str, ':') + 1; 1884 1885 /* need ip addr and only ip addr for inet_pton */ 1886 ip_str_len = (size_t) (strchr(my_str, '/') - my_str); 1887 if(ip_str_len+1 > sizeof(my_ip_str)) 1888 return LDNS_WIREPARSE_ERR_INVALID_STR; 1889 (void)strlcpy(my_ip_str, my_str, sizeof(my_ip_str)); 1890 my_ip_str[ip_str_len] = 0; 1891 1892 if (family == 1) { 1893 /* ipv4 */ 1894 if(inet_pton(AF_INET, my_ip_str, data+4) == 0) 1895 return LDNS_WIREPARSE_ERR_INVALID_STR; 1896 for (i = 0; i < 4; i++) { 1897 if (data[i+4] != 0) { 1898 adflength = i + 1; 1899 } 1900 } 1901 } else if (family == 2) { 1902 /* ipv6 */ 1903 if (inet_pton(AF_INET6, my_ip_str, data+4) == 0) 1904 return LDNS_WIREPARSE_ERR_INVALID_STR; 1905 for (i = 0; i < 16; i++) { 1906 if (data[i+4] != 0) { 1907 adflength = i + 1; 1908 } 1909 } 1910 } else { 1911 /* unknown family */ 1912 return LDNS_WIREPARSE_ERR_INVALID_STR; 1913 } 1914 1915 my_str = strchr(my_str, '/') + 1; 1916 prefix = (uint8_t) atoi(my_str); 1917 1918 sldns_write_uint16(data, family); 1919 data[2] = prefix; 1920 data[3] = (uint8_t)adflength; 1921 if (negation) { 1922 /* set bit 1 of byte 3 */ 1923 data[3] = data[3] | 0x80; 1924 } 1925 1926 if(*len < 4+adflength) 1927 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1928 memmove(rd, data, 4+adflength); 1929 *len = 4+adflength; 1930 return LDNS_WIREPARSE_ERR_OK; 1931 } 1932 1933 int sldns_str2wire_b64_buf(const char* str, uint8_t* rd, size_t* len) 1934 { 1935 size_t sz = sldns_b64_pton_calculate_size(strlen(str)); 1936 int n; 1937 if(strcmp(str, "0") == 0) { 1938 *len = 0; 1939 return LDNS_WIREPARSE_ERR_OK; 1940 } 1941 if(*len < sz) 1942 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1943 n = sldns_b64_pton(str, rd, *len); 1944 if(n < 0) 1945 return LDNS_WIREPARSE_ERR_SYNTAX_B64; 1946 *len = (size_t)n; 1947 return LDNS_WIREPARSE_ERR_OK; 1948 } 1949 1950 int sldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len) 1951 { 1952 size_t slen = strlen(str); 1953 size_t sz = sldns_b32_pton_calculate_size(slen); 1954 int n; 1955 if(*len < 1+sz) 1956 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 1957 rd[0] = (uint8_t)sz; 1958 n = sldns_b32_pton_extended_hex(str, slen, rd+1, *len-1); 1959 if(n < 0) 1960 return LDNS_WIREPARSE_ERR_SYNTAX_B32_EXT; 1961 *len = (size_t)n+1; 1962 return LDNS_WIREPARSE_ERR_OK; 1963 } 1964 1965 /** see if the string ends, or ends in whitespace */ 1966 static int 1967 sldns_is_last_of_string(const char* str) 1968 { 1969 if(*str == 0) return 1; 1970 while(isspace((unsigned char)*str)) 1971 str++; 1972 if(*str == 0) return 1; 1973 return 0; 1974 } 1975 1976 int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len) 1977 { 1978 const char* s = str; 1979 size_t dlen = 0; /* number of hexdigits parsed */ 1980 while(*s) { 1981 if(isspace((unsigned char)*s)) { 1982 s++; 1983 continue; 1984 } 1985 if(dlen == 0 && *s == '0' && sldns_is_last_of_string(s+1)) { 1986 *len = 0; 1987 return LDNS_WIREPARSE_ERR_OK; 1988 } 1989 if(!isxdigit((unsigned char)*s)) 1990 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 1991 if(*len < dlen/2 + 1) 1992 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 1993 s-str); 1994 if((dlen&1)==0) 1995 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 1996 else rd[dlen/2] += (uint8_t)sldns_hexdigit_to_int(*s++); 1997 dlen++; 1998 } 1999 if((dlen&1)!=0) 2000 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 2001 *len = dlen/2; 2002 return LDNS_WIREPARSE_ERR_OK; 2003 } 2004 2005 int sldns_str2wire_nsec_buf(const char* str, uint8_t* rd, size_t* len) 2006 { 2007 const char *delim = "\n\t "; 2008 char token[64]; /* for a type name */ 2009 size_t type_count = 0; 2010 int block; 2011 size_t used = 0; 2012 uint16_t maxtype = 0; 2013 uint8_t typebits[8192]; /* 65536 bits */ 2014 uint8_t window_in_use[256]; 2015 2016 /* string in buffer */ 2017 sldns_buffer strbuf; 2018 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 2019 2020 /* parse the types */ 2021 memset(typebits, 0, sizeof(typebits)); 2022 memset(window_in_use, 0, sizeof(window_in_use)); 2023 while(sldns_buffer_remaining(&strbuf) > 0 && 2024 sldns_bget_token(&strbuf, token, delim, sizeof(token)) != -1) { 2025 uint16_t t = sldns_get_rr_type_by_name(token); 2026 if(token[0] == 0) 2027 continue; 2028 if(t == 0 && strcmp(token, "TYPE0") != 0) 2029 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TYPE, 2030 sldns_buffer_position(&strbuf)); 2031 typebits[t/8] |= (0x80>>(t%8)); 2032 window_in_use[t/256] = 1; 2033 type_count++; 2034 if(t > maxtype) maxtype = t; 2035 } 2036 2037 /* empty NSEC bitmap */ 2038 if(type_count == 0) { 2039 *len = 0; 2040 return LDNS_WIREPARSE_ERR_OK; 2041 } 2042 2043 /* encode windows {u8 windowblock, u8 bitmaplength, 0-32u8 bitmap}, 2044 * block is 0-255 upper octet of types, length if 0-32. */ 2045 for(block = 0; block <= (int)maxtype/256; block++) { 2046 int i, blocklen = 0; 2047 if(!window_in_use[block]) 2048 continue; 2049 for(i=0; i<32; i++) { 2050 if(typebits[block*32+i] != 0) 2051 blocklen = i+1; 2052 } 2053 if(blocklen == 0) 2054 continue; /* empty window should have been !in_use */ 2055 if(used+blocklen+2 > *len) 2056 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2057 rd[used+0] = (uint8_t)block; 2058 rd[used+1] = (uint8_t)blocklen; 2059 for(i=0; i<blocklen; i++) { 2060 rd[used+2+i] = typebits[block*32+i]; 2061 } 2062 used += blocklen+2; 2063 } 2064 *len = used; 2065 return LDNS_WIREPARSE_ERR_OK; 2066 } 2067 2068 int sldns_str2wire_type_buf(const char* str, uint8_t* rd, size_t* len) 2069 { 2070 uint16_t t = sldns_get_rr_type_by_name(str); 2071 if(t == 0 && strcmp(str, "TYPE0") != 0) 2072 return LDNS_WIREPARSE_ERR_SYNTAX_TYPE; 2073 if(*len < 2) 2074 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2075 sldns_write_uint16(rd, t); 2076 *len = 2; 2077 return LDNS_WIREPARSE_ERR_OK; 2078 } 2079 2080 int sldns_str2wire_class_buf(const char* str, uint8_t* rd, size_t* len) 2081 { 2082 uint16_t c = sldns_get_rr_class_by_name(str); 2083 if(c == 0 && strcmp(str, "CLASS0") != 0) 2084 return LDNS_WIREPARSE_ERR_SYNTAX_CLASS; 2085 if(*len < 2) 2086 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2087 sldns_write_uint16(rd, c); 2088 *len = 2; 2089 return LDNS_WIREPARSE_ERR_OK; 2090 } 2091 2092 /* An certificate alg field can either be specified as a 8 bits number 2093 * or by its symbolic name. Handle both */ 2094 int sldns_str2wire_cert_alg_buf(const char* str, uint8_t* rd, size_t* len) 2095 { 2096 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_cert_algorithms, 2097 str); 2098 if(*len < 2) 2099 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2100 if(lt) { 2101 sldns_write_uint16(rd, (uint16_t)lt->id); 2102 } else { 2103 int s = sldns_str2wire_int16_buf(str, rd, len); 2104 if(s) return s; 2105 if(sldns_read_uint16(rd) == 0) 2106 return LDNS_WIREPARSE_ERR_CERT_BAD_ALGORITHM; 2107 } 2108 *len = 2; 2109 return LDNS_WIREPARSE_ERR_OK; 2110 } 2111 2112 /* An alg field can either be specified as a 8 bits number 2113 * or by its symbolic name. Handle both */ 2114 int sldns_str2wire_alg_buf(const char* str, uint8_t* rd, size_t* len) 2115 { 2116 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_algorithms, str); 2117 if(*len < 1) 2118 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2119 if(lt) { 2120 rd[0] = (uint8_t)lt->id; 2121 *len = 1; 2122 } else { 2123 /* try as-is (a number) */ 2124 return sldns_str2wire_int8_buf(str, rd, len); 2125 } 2126 return LDNS_WIREPARSE_ERR_OK; 2127 } 2128 2129 int sldns_str2wire_tsigerror_buf(const char* str, uint8_t* rd, size_t* len) 2130 { 2131 sldns_lookup_table *lt = sldns_lookup_by_name(sldns_tsig_errors, str); 2132 if(*len < 2) 2133 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2134 if(lt) { 2135 sldns_write_uint16(rd, (uint16_t)lt->id); 2136 *len = 2; 2137 } else { 2138 /* try as-is (a number) */ 2139 return sldns_str2wire_int16_buf(str, rd, len); 2140 } 2141 return LDNS_WIREPARSE_ERR_OK; 2142 } 2143 2144 int sldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len) 2145 { 2146 /* convert a time YYYYDDMMHHMMSS to wireformat */ 2147 struct tm tm; 2148 if(*len < 4) 2149 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2150 2151 /* Try to scan the time... */ 2152 memset(&tm, 0, sizeof(tm)); 2153 if (strlen(str) == 14 && sscanf(str, "%4d%2d%2d%2d%2d%2d", 2154 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, 2155 &tm.tm_min, &tm.tm_sec) == 6) { 2156 tm.tm_year -= 1900; 2157 tm.tm_mon--; 2158 /* Check values */ 2159 if (tm.tm_year < 70) 2160 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 2161 if (tm.tm_mon < 0 || tm.tm_mon > 11) 2162 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 2163 if (tm.tm_mday < 1 || tm.tm_mday > 31) 2164 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 2165 if (tm.tm_hour < 0 || tm.tm_hour > 23) 2166 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 2167 if (tm.tm_min < 0 || tm.tm_min > 59) 2168 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 2169 if (tm.tm_sec < 0 || tm.tm_sec > 59) 2170 return LDNS_WIREPARSE_ERR_SYNTAX_TIME; 2171 2172 sldns_write_uint32(rd, (uint32_t)sldns_mktime_from_utc(&tm)); 2173 } else { 2174 /* handle it as 32 bits timestamp */ 2175 char *end; 2176 uint32_t l = (uint32_t)strtol((char*)str, &end, 10); 2177 if(*end != 0) 2178 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TIME, 2179 end-(char*)str); 2180 sldns_write_uint32(rd, l); 2181 } 2182 *len = 4; 2183 return LDNS_WIREPARSE_ERR_OK; 2184 } 2185 2186 int sldns_str2wire_tsigtime_buf(const char* str, uint8_t* rd, size_t* len) 2187 { 2188 char* end; 2189 uint64_t t = (uint64_t)strtol((char*)str, &end, 10); 2190 uint16_t high; 2191 uint32_t low; 2192 if(*end != 0) 2193 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TIME, end-str); 2194 if(*len < 6) 2195 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2196 high = (uint16_t)(t>>32); 2197 low = (uint32_t)(t); 2198 sldns_write_uint16(rd, high); 2199 sldns_write_uint32(rd+2, low); 2200 *len = 6; 2201 return LDNS_WIREPARSE_ERR_OK; 2202 } 2203 2204 int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len) 2205 { 2206 const char* end; 2207 int overflow; 2208 uint32_t p = sldns_str2period(str, &end, &overflow); 2209 if(*end != 0) 2210 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str); 2211 if(overflow) 2212 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW, 2213 end-str); 2214 if(*len < 4) 2215 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2216 sldns_write_uint32(rd, p); 2217 *len = 4; 2218 return LDNS_WIREPARSE_ERR_OK; 2219 } 2220 2221 /** read "<digits>[.<digits>][mM]" into mantissa exponent format for LOC type */ 2222 static int 2223 loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) 2224 { 2225 uint32_t meters = 0, cm = 0, val; 2226 char* cm_endstr; 2227 while (isblank((unsigned char)*my_str)) { 2228 my_str++; 2229 } 2230 meters = (uint32_t)strtol(my_str, &my_str, 10); 2231 if (*my_str == '.') { 2232 my_str++; 2233 cm = (uint32_t)strtol(my_str, &cm_endstr, 10); 2234 if(cm_endstr == my_str + 1) 2235 cm *= 10; 2236 my_str = cm_endstr; 2237 } 2238 if (meters >= 1) { 2239 *e = 2; 2240 val = meters; 2241 } else { 2242 *e = 0; 2243 val = cm; 2244 } 2245 while(val >= 10) { 2246 (*e)++; 2247 val /= 10; 2248 } 2249 *m = (uint8_t)val; 2250 2251 if (*e > 9) 2252 return 0; 2253 if (*my_str == 'm' || *my_str == 'M') { 2254 my_str++; 2255 } 2256 *endstr = my_str; 2257 return 1; 2258 } 2259 2260 int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len) 2261 { 2262 uint32_t latitude = 0; 2263 uint32_t longitude = 0; 2264 uint32_t altitude = 0; 2265 2266 uint32_t equator = (uint32_t)1<<31; /* 2**31 */ 2267 2268 /* only support version 0 */ 2269 uint32_t h = 0; 2270 uint32_t m = 0; 2271 uint8_t size_b = 1, size_e = 2; 2272 uint8_t horiz_pre_b = 1, horiz_pre_e = 6; 2273 uint8_t vert_pre_b = 1, vert_pre_e = 3; 2274 2275 double s = 0.0; 2276 int northerness; 2277 int easterness; 2278 2279 char *my_str = (char *) str; 2280 2281 if (isdigit((unsigned char) *my_str)) { 2282 h = (uint32_t) strtol(my_str, &my_str, 10); 2283 } else { 2284 return LDNS_WIREPARSE_ERR_INVALID_STR; 2285 } 2286 2287 while (isblank((unsigned char) *my_str)) { 2288 my_str++; 2289 } 2290 2291 if (isdigit((unsigned char) *my_str)) { 2292 m = (uint32_t) strtol(my_str, &my_str, 10); 2293 } else if (*my_str == 'N' || *my_str == 'S') { 2294 goto north; 2295 } else { 2296 return LDNS_WIREPARSE_ERR_INVALID_STR; 2297 } 2298 2299 while (isblank((unsigned char) *my_str)) { 2300 my_str++; 2301 } 2302 2303 if (isdigit((unsigned char) *my_str)) { 2304 s = strtod(my_str, &my_str); 2305 } 2306 2307 /* skip blanks before northerness */ 2308 while (isblank((unsigned char) *my_str)) { 2309 my_str++; 2310 } 2311 2312 north: 2313 if (*my_str == 'N') { 2314 northerness = 1; 2315 } else if (*my_str == 'S') { 2316 northerness = 0; 2317 } else { 2318 return LDNS_WIREPARSE_ERR_INVALID_STR; 2319 } 2320 2321 my_str++; 2322 2323 /* store number */ 2324 s = 1000.0 * s; 2325 /* add a little to make floor in conversion a round */ 2326 s += 0.0005; 2327 latitude = (uint32_t) s; 2328 latitude += 1000 * 60 * m; 2329 latitude += 1000 * 60 * 60 * h; 2330 if (northerness) { 2331 latitude = equator + latitude; 2332 } else { 2333 latitude = equator - latitude; 2334 } 2335 while (isblank((unsigned char)*my_str)) { 2336 my_str++; 2337 } 2338 2339 if (isdigit((unsigned char) *my_str)) { 2340 h = (uint32_t) strtol(my_str, &my_str, 10); 2341 } else { 2342 return LDNS_WIREPARSE_ERR_INVALID_STR; 2343 } 2344 2345 while (isblank((unsigned char) *my_str)) { 2346 my_str++; 2347 } 2348 2349 if (isdigit((unsigned char) *my_str)) { 2350 m = (uint32_t) strtol(my_str, &my_str, 10); 2351 } else if (*my_str == 'E' || *my_str == 'W') { 2352 goto east; 2353 } else { 2354 return LDNS_WIREPARSE_ERR_INVALID_STR; 2355 } 2356 2357 while (isblank((unsigned char)*my_str)) { 2358 my_str++; 2359 } 2360 2361 if (isdigit((unsigned char) *my_str)) { 2362 s = strtod(my_str, &my_str); 2363 } 2364 2365 /* skip blanks before easterness */ 2366 while (isblank((unsigned char)*my_str)) { 2367 my_str++; 2368 } 2369 2370 east: 2371 if (*my_str == 'E') { 2372 easterness = 1; 2373 } else if (*my_str == 'W') { 2374 easterness = 0; 2375 } else { 2376 return LDNS_WIREPARSE_ERR_INVALID_STR; 2377 } 2378 2379 my_str++; 2380 2381 /* store number */ 2382 s *= 1000.0; 2383 /* add a little to make floor in conversion a round */ 2384 s += 0.0005; 2385 longitude = (uint32_t) s; 2386 longitude += 1000 * 60 * m; 2387 longitude += 1000 * 60 * 60 * h; 2388 2389 if (easterness) { 2390 longitude += equator; 2391 } else { 2392 longitude = equator - longitude; 2393 } 2394 2395 altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + 2396 10000000.0 + 0.5); 2397 if (*my_str == 'm' || *my_str == 'M') { 2398 my_str++; 2399 } 2400 2401 if (strlen(my_str) > 0) { 2402 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) 2403 return LDNS_WIREPARSE_ERR_INVALID_STR; 2404 } 2405 2406 if (strlen(my_str) > 0) { 2407 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) 2408 return LDNS_WIREPARSE_ERR_INVALID_STR; 2409 } 2410 2411 if (strlen(my_str) > 0) { 2412 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) 2413 return LDNS_WIREPARSE_ERR_INVALID_STR; 2414 } 2415 2416 if(*len < 16) 2417 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2418 rd[0] = 0; 2419 rd[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); 2420 rd[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); 2421 rd[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); 2422 sldns_write_uint32(rd + 4, latitude); 2423 sldns_write_uint32(rd + 8, longitude); 2424 sldns_write_uint32(rd + 12, altitude); 2425 *len = 16; 2426 return LDNS_WIREPARSE_ERR_OK; 2427 } 2428 2429 static void 2430 ldns_tolower_str(char* s) 2431 { 2432 if(s) { 2433 while(*s) { 2434 *s = (char)tolower((unsigned char)*s); 2435 s++; 2436 } 2437 } 2438 } 2439 2440 int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) 2441 { 2442 int rd_len = 1; 2443 int have_proto = 0; 2444 char token[50], proto_str[50]; 2445 sldns_buffer strbuf; 2446 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 2447 proto_str[0]=0; 2448 2449 /* check we have one byte for proto */ 2450 if(*len < 1) 2451 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2452 2453 while(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) > 0) { 2454 ldns_tolower_str(token); 2455 if(!have_proto) { 2456 struct protoent *p = getprotobyname(token); 2457 have_proto = 1; 2458 if(p) rd[0] = (uint8_t)p->p_proto; 2459 else if(strcasecmp(token, "tcp")==0) rd[0]=6; 2460 else if(strcasecmp(token, "udp")==0) rd[0]=17; 2461 else rd[0] = (uint8_t)atoi(token); 2462 (void)strlcpy(proto_str, token, sizeof(proto_str)); 2463 } else { 2464 int serv_port; 2465 if(atoi(token) != 0) serv_port=atoi(token); 2466 else if(strcmp(token, "0") == 0) serv_port=0; 2467 else if(strcasecmp(token, "domain")==0) serv_port=53; 2468 else { 2469 struct servent *serv = getservbyname(token, proto_str); 2470 if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port); 2471 else { 2472 #ifdef HAVE_ENDSERVENT 2473 endservent(); 2474 #endif 2475 #ifdef HAVE_ENDPROTOENT 2476 endprotoent(); 2477 #endif 2478 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 2479 sldns_buffer_position(&strbuf)); 2480 } 2481 } 2482 if(serv_port < 0 || serv_port > 65535) { 2483 #ifdef HAVE_ENDSERVENT 2484 endservent(); 2485 #endif 2486 #ifdef HAVE_ENDPROTOENT 2487 endprotoent(); 2488 #endif 2489 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, 2490 sldns_buffer_position(&strbuf)); 2491 } 2492 if(rd_len < 1+serv_port/8+1) { 2493 /* bitmap is larger, init new bytes at 0 */ 2494 if(*len < 1+(size_t)serv_port/8+1) { 2495 #ifdef HAVE_ENDSERVENT 2496 endservent(); 2497 #endif 2498 #ifdef HAVE_ENDPROTOENT 2499 endprotoent(); 2500 #endif 2501 return RET_ERR( 2502 LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 2503 sldns_buffer_position(&strbuf)); 2504 } 2505 memset(rd+rd_len, 0, 1+(size_t)serv_port/8+1-rd_len); 2506 rd_len = 1+serv_port/8+1; 2507 } 2508 rd[1+ serv_port/8] |= (1 << (7 - serv_port % 8)); 2509 } 2510 } 2511 *len = (size_t)rd_len; 2512 2513 #ifdef HAVE_ENDSERVENT 2514 endservent(); 2515 #endif 2516 #ifdef HAVE_ENDPROTOENT 2517 endprotoent(); 2518 #endif 2519 return LDNS_WIREPARSE_ERR_OK; 2520 } 2521 2522 int sldns_str2wire_nsap_buf(const char* str, uint8_t* rd, size_t* len) 2523 { 2524 const char* s = str; 2525 size_t slen; 2526 size_t dlen = 0; /* number of hexdigits parsed */ 2527 2528 /* just a hex string with optional dots? */ 2529 if (s[0] != '0' || s[1] != 'x') 2530 return LDNS_WIREPARSE_ERR_INVALID_STR; 2531 s += 2; 2532 slen = strlen(s); 2533 if(slen > LDNS_MAX_RDFLEN*2) 2534 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 2535 while(*s) { 2536 if(isspace((unsigned char)*s) || *s == '.') { 2537 s++; 2538 continue; 2539 } 2540 if(!isxdigit((unsigned char)*s)) 2541 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 2542 if(*len < dlen/2 + 1) 2543 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 2544 s-str); 2545 if((dlen&1)==0) 2546 rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 2547 else rd[dlen/2] += sldns_hexdigit_to_int(*s++); 2548 dlen++; 2549 } 2550 if((dlen&1)!=0) 2551 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 2552 *len = dlen/2; 2553 return LDNS_WIREPARSE_ERR_OK; 2554 } 2555 2556 int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len) 2557 { 2558 const char* s = str; 2559 size_t slen = strlen(str); 2560 size_t dlen = 0; /* number of hexdigits parsed for hex, 2561 digits for E.164 */ 2562 2563 if(slen > LDNS_MAX_RDFLEN*2) 2564 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 2565 if(*len < 1) 2566 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2567 if(*s == 0) { 2568 /* empty string */ 2569 rd[0] = 0; 2570 *len = 1; 2571 return LDNS_WIREPARSE_ERR_OK; 2572 } 2573 if(s[0] == '+') { 2574 rd[0] = 1; /* E.164 format */ 2575 /* digits '0'..'9', with skipped dots. */ 2576 s++; 2577 while(*s) { 2578 if(isspace((unsigned char)*s) || *s == '.') { 2579 s++; 2580 continue; 2581 } 2582 if(*s < '0' || *s > '9') 2583 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-str); 2584 if(*len < dlen + 2) 2585 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 2586 s-str); 2587 rd[dlen+1] = *s++; 2588 dlen++; 2589 } 2590 *len = dlen+1; 2591 return LDNS_WIREPARSE_ERR_OK; 2592 } 2593 2594 rd[0] = 0; /* AESA format */ 2595 /* hex, with skipped dots. */ 2596 while(*s) { 2597 if(isspace((unsigned char)*s) || *s == '.') { 2598 s++; 2599 continue; 2600 } 2601 if(!isxdigit((unsigned char)*s)) 2602 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 2603 if(*len < dlen/2 + 2) 2604 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 2605 s-str); 2606 if((dlen&1)==0) 2607 rd[dlen/2 + 1] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16; 2608 else rd[dlen/2 + 1] += sldns_hexdigit_to_int(*s++); 2609 dlen++; 2610 } 2611 if((dlen&1)!=0) 2612 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); 2613 *len = dlen/2 + 1; 2614 return LDNS_WIREPARSE_ERR_OK; 2615 } 2616 2617 int sldns_str2wire_ipseckey_buf(const char* str, uint8_t* rd, size_t* len) 2618 { 2619 size_t gwlen = 0, keylen = 0; 2620 int s; 2621 uint8_t gwtype; 2622 char token[512]; 2623 sldns_buffer strbuf; 2624 sldns_buffer_init_frm_data(&strbuf, (uint8_t*)str, strlen(str)); 2625 2626 if(*len < 3) 2627 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2628 /* precedence */ 2629 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 2630 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 2631 sldns_buffer_position(&strbuf)); 2632 rd[0] = (uint8_t)atoi(token); 2633 /* gateway_type */ 2634 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 2635 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 2636 sldns_buffer_position(&strbuf)); 2637 rd[1] = (uint8_t)atoi(token); 2638 gwtype = rd[1]; 2639 /* algorithm */ 2640 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 2641 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 2642 sldns_buffer_position(&strbuf)); 2643 rd[2] = (uint8_t)atoi(token); 2644 2645 /* gateway */ 2646 if(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) <= 0) 2647 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 2648 sldns_buffer_position(&strbuf)); 2649 if(gwtype == 0) { 2650 /* NOGATEWAY */ 2651 if(strcmp(token, ".") != 0) 2652 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 2653 sldns_buffer_position(&strbuf)); 2654 gwlen = 0; 2655 } else if(gwtype == 1) { 2656 /* IP4 */ 2657 gwlen = *len - 3; 2658 s = sldns_str2wire_a_buf(token, rd+3, &gwlen); 2659 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 2660 } else if(gwtype == 2) { 2661 /* IP6 */ 2662 gwlen = *len - 3; 2663 s = sldns_str2wire_aaaa_buf(token, rd+3, &gwlen); 2664 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 2665 } else if(gwtype == 3) { 2666 /* DNAME */ 2667 gwlen = *len - 3; 2668 s = sldns_str2wire_dname_buf(token, rd+3, &gwlen); 2669 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 2670 } else { 2671 /* unknown gateway type */ 2672 return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, 2673 sldns_buffer_position(&strbuf)); 2674 } 2675 /* double check for size */ 2676 if(*len < 3 + gwlen) 2677 return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, 2678 sldns_buffer_position(&strbuf)); 2679 2680 /* publickey in remainder of strbuf */ 2681 keylen = *len - 3 - gwlen; 2682 s = sldns_str2wire_b64_buf((const char*)sldns_buffer_current(&strbuf), 2683 rd+3+gwlen, &keylen); 2684 if(s) return RET_ERR_SHIFT(s, sldns_buffer_position(&strbuf)); 2685 2686 *len = 3 + gwlen + keylen; 2687 return LDNS_WIREPARSE_ERR_OK; 2688 } 2689 2690 int sldns_str2wire_nsec3_salt_buf(const char* str, uint8_t* rd, size_t* len) 2691 { 2692 int i, salt_length_str = (int)strlen(str); 2693 if (salt_length_str == 1 && str[0] == '-') { 2694 salt_length_str = 0; 2695 } else if (salt_length_str % 2 != 0) { 2696 return LDNS_WIREPARSE_ERR_SYNTAX_HEX; 2697 } 2698 if (salt_length_str > 512) 2699 return LDNS_WIREPARSE_ERR_SYNTAX_HEX; 2700 if(*len < 1+(size_t)salt_length_str / 2) 2701 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2702 rd[0] = (uint8_t) (salt_length_str / 2); 2703 for (i = 0; i < salt_length_str; i += 2) { 2704 if (isxdigit((unsigned char)str[i]) && 2705 isxdigit((unsigned char)str[i+1])) { 2706 rd[1+i/2] = (uint8_t)(sldns_hexdigit_to_int(str[i])*16 2707 + sldns_hexdigit_to_int(str[i+1])); 2708 } else { 2709 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, i); 2710 } 2711 } 2712 *len = 1 + (size_t)rd[0]; 2713 return LDNS_WIREPARSE_ERR_OK; 2714 } 2715 2716 int sldns_str2wire_ilnp64_buf(const char* str, uint8_t* rd, size_t* len) 2717 { 2718 unsigned int a, b, c, d; 2719 uint16_t shorts[4]; 2720 int l; 2721 if(*len < sizeof(shorts)) 2722 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2723 2724 if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 || 2725 l != (int)strlen(str) || /* more data to read */ 2726 strpbrk(str, "+-") /* signed hexes */ 2727 ) 2728 return LDNS_WIREPARSE_ERR_SYNTAX_ILNP64; 2729 shorts[0] = htons(a); 2730 shorts[1] = htons(b); 2731 shorts[2] = htons(c); 2732 shorts[3] = htons(d); 2733 memmove(rd, &shorts, sizeof(shorts)); 2734 *len = sizeof(shorts); 2735 return LDNS_WIREPARSE_ERR_OK; 2736 } 2737 2738 int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len) 2739 { 2740 unsigned int a, b, c, d, e, f; 2741 int l; 2742 2743 if(*len < 6) 2744 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2745 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n", 2746 &a, &b, &c, &d, &e, &f, &l) != 6 || 2747 l != (int)strlen(str)) 2748 return LDNS_WIREPARSE_ERR_SYNTAX_EUI48; 2749 rd[0] = a; 2750 rd[1] = b; 2751 rd[2] = c; 2752 rd[3] = d; 2753 rd[4] = e; 2754 rd[5] = f; 2755 *len = 6; 2756 return LDNS_WIREPARSE_ERR_OK; 2757 } 2758 2759 int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len) 2760 { 2761 unsigned int a, b, c, d, e, f, g, h; 2762 int l; 2763 2764 if(*len < 8) 2765 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2766 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n", 2767 &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 || 2768 l != (int)strlen(str)) 2769 return LDNS_WIREPARSE_ERR_SYNTAX_EUI64; 2770 rd[0] = a; 2771 rd[1] = b; 2772 rd[2] = c; 2773 rd[3] = d; 2774 rd[4] = e; 2775 rd[5] = f; 2776 rd[6] = g; 2777 rd[7] = h; 2778 *len = 8; 2779 return LDNS_WIREPARSE_ERR_OK; 2780 } 2781 2782 int sldns_str2wire_unquoted_buf(const char* str, uint8_t* rd, size_t* len) 2783 { 2784 return sldns_str2wire_str_buf(str, rd, len); 2785 } 2786 2787 int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len) 2788 { 2789 size_t slen = strlen(str); 2790 const char* ptr; 2791 2792 if (slen > 255) 2793 return LDNS_WIREPARSE_ERR_SYNTAX_TAG; 2794 if(*len < slen+1) 2795 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2796 for (ptr = str; *ptr; ptr++) { 2797 if(!isalnum((unsigned char)*ptr)) 2798 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TAG, ptr-str); 2799 } 2800 rd[0] = (uint8_t)slen; 2801 memmove(rd+1, str, slen); 2802 *len = slen+1; 2803 return LDNS_WIREPARSE_ERR_OK; 2804 } 2805 2806 int sldns_str2wire_long_str_buf(const char* str, uint8_t* rd, size_t* len) 2807 { 2808 uint8_t ch = 0; 2809 const char* pstr = str; 2810 size_t length = 0; 2811 2812 /* Fill data with parsed bytes */ 2813 while (sldns_parse_char(&ch, &pstr)) { 2814 if(*len < length+1) 2815 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2816 rd[length++] = ch; 2817 } 2818 if(!pstr) 2819 return LDNS_WIREPARSE_ERR_SYNTAX_BAD_ESCAPE; 2820 *len = length; 2821 return LDNS_WIREPARSE_ERR_OK; 2822 } 2823 2824 int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len) 2825 { 2826 char* s, *end; 2827 int e; 2828 size_t hitlen, pklen = 0; 2829 /* presentation format: 2830 * pk-algo HIThex pubkeybase64 2831 * wireformat: 2832 * hitlen[1byte] pkalgo[1byte] pubkeylen[2byte] [hit] [pubkey] */ 2833 if(*len < 4) 2834 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2835 2836 /* read PK algorithm */ 2837 rd[1] = (uint8_t)strtol((char*)str, &s, 10); 2838 if(*s != ' ') 2839 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str); 2840 s++; 2841 while(*s == ' ') 2842 s++; 2843 2844 /* read HIT hex tag */ 2845 /* zero terminate the tag (replace later) */ 2846 end = strchr(s, ' '); 2847 if(!end) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-(char*)str); 2848 *end = 0; 2849 hitlen = *len - 4; 2850 if((e = sldns_str2wire_hex_buf(s, rd+4, &hitlen)) != 0) { 2851 *end = ' '; 2852 return RET_ERR_SHIFT(e, s-(char*)str); 2853 } 2854 if(hitlen > 255) { 2855 *end = ' '; 2856 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+255*2); 2857 } 2858 rd[0] = (uint8_t)hitlen; 2859 *end = ' '; 2860 s = end+1; 2861 2862 /* read pubkey base64 sequence */ 2863 pklen = *len - 4 - hitlen; 2864 if((e = sldns_str2wire_b64_buf(s, rd+4+hitlen, &pklen)) != 0) 2865 return RET_ERR_SHIFT(e, s-(char*)str); 2866 if(pklen > 65535) 2867 return RET_ERR(LDNS_WIREPARSE_ERR_LABEL_OVERFLOW, s-(char*)str+65535); 2868 sldns_write_uint16(rd+2, (uint16_t)pklen); 2869 2870 *len = 4 + hitlen + pklen; 2871 return LDNS_WIREPARSE_ERR_OK; 2872 } 2873 2874 int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len) 2875 { 2876 char* s; 2877 int n; 2878 n = strtol(str, &s, 10); 2879 if(n < 0) /* negative number not allowed */ 2880 return LDNS_WIREPARSE_ERR_SYNTAX; 2881 if(*len < ((size_t)n)+2) 2882 return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; 2883 if(n > 65535) 2884 return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; 2885 2886 if(n == 0) { 2887 sldns_write_uint16(rd, 0); 2888 *len = 2; 2889 return LDNS_WIREPARSE_ERR_OK; 2890 } 2891 if(*s != ' ') 2892 return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str); 2893 s++; 2894 while(*s == ' ') 2895 s++; 2896 2897 n = sldns_b64_pton(s, rd+2, (*len)-2); 2898 if(n < 0) 2899 return LDNS_WIREPARSE_ERR_SYNTAX_B64; 2900 sldns_write_uint16(rd, (uint16_t)n); 2901 *len = ((size_t)n)+2; 2902 return LDNS_WIREPARSE_ERR_OK; 2903 } 2904