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