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