mirror of
https://github.com/NLnetLabs/unbound.git
synced 2024-09-21 06:37:08 +00:00
- Fix #637: Integer Overflow in sldns_str2period function.
This commit is contained in:
parent
f81420d77f
commit
debe5c665f
@ -1,3 +1,6 @@
|
||||
3 March 2022: Wouter
|
||||
- Fix #637: Integer Overflow in sldns_str2period function.
|
||||
|
||||
2 March 2022: George
|
||||
- Merge PR #632 from scottrw93: Match cnames in ipset.
|
||||
- Various fixes for #632: variable initialisation, convert the qinfo
|
||||
|
@ -4456,7 +4456,7 @@ chunkline_get_line_collated(struct auth_chunk** chunk, size_t* chunk_pos,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** process $ORIGIN for http */
|
||||
/** process $ORIGIN for http, 0 nothing, 1 done, 2 error */
|
||||
static int
|
||||
http_parse_origin(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
|
||||
{
|
||||
@ -4467,13 +4467,16 @@ http_parse_origin(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
|
||||
pstate->origin_len = sizeof(pstate->origin);
|
||||
s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8),
|
||||
pstate->origin, &pstate->origin_len);
|
||||
if(s) pstate->origin_len = 0;
|
||||
if(s) {
|
||||
pstate->origin_len = 0;
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** process $TTL for http */
|
||||
/** process $TTL for http, 0 nothing, 1 done, 2 error */
|
||||
static int
|
||||
http_parse_ttl(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
|
||||
{
|
||||
@ -4481,8 +4484,12 @@ http_parse_ttl(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
|
||||
if(strncmp(line, "$TTL", 4) == 0 &&
|
||||
isspace((unsigned char)line[4])) {
|
||||
const char* end = NULL;
|
||||
int overflow = 0;
|
||||
pstate->default_ttl = sldns_str2period(
|
||||
sldns_strip_ws(line+5), &end);
|
||||
sldns_strip_ws(line+5), &end, &overflow);
|
||||
if(overflow) {
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -4493,15 +4500,20 @@ static int
|
||||
chunkline_non_comment_RR(struct auth_chunk** chunk, size_t* chunk_pos,
|
||||
sldns_buffer* buf, struct sldns_file_parse_state* pstate)
|
||||
{
|
||||
int ret;
|
||||
while(chunkline_get_line_collated(chunk, chunk_pos, buf)) {
|
||||
if(chunkline_is_comment_line_or_empty(buf)) {
|
||||
/* a comment, go to next line */
|
||||
continue;
|
||||
}
|
||||
if(http_parse_origin(buf, pstate)) {
|
||||
if((ret=http_parse_origin(buf, pstate))!=0) {
|
||||
if(ret == 2)
|
||||
return 0;
|
||||
continue; /* $ORIGIN has been handled */
|
||||
}
|
||||
if(http_parse_ttl(buf, pstate)) {
|
||||
if((ret=http_parse_ttl(buf, pstate))!=0) {
|
||||
if(ret == 2)
|
||||
return 0;
|
||||
continue; /* $TTL has been handled */
|
||||
}
|
||||
return 1;
|
||||
@ -5007,6 +5019,7 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
struct sldns_file_parse_state pstate;
|
||||
struct auth_chunk* chunk;
|
||||
size_t chunk_pos;
|
||||
int ret;
|
||||
memset(&pstate, 0, sizeof(pstate));
|
||||
pstate.default_ttl = 3600;
|
||||
if(xfr->namelen < sizeof(pstate.origin)) {
|
||||
@ -5063,10 +5076,24 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
continue;
|
||||
}
|
||||
/* parse line and add RR */
|
||||
if(http_parse_origin(scratch_buffer, &pstate)) {
|
||||
if((ret=http_parse_origin(scratch_buffer, &pstate))!=0) {
|
||||
if(ret == 2) {
|
||||
verbose(VERB_ALGO, "error parsing ORIGIN on line [%s:%d] %s",
|
||||
xfr->task_transfer->master->file,
|
||||
pstate.lineno,
|
||||
sldns_buffer_begin(scratch_buffer));
|
||||
return 0;
|
||||
}
|
||||
continue; /* $ORIGIN has been handled */
|
||||
}
|
||||
if(http_parse_ttl(scratch_buffer, &pstate)) {
|
||||
if((ret=http_parse_ttl(scratch_buffer, &pstate))!=0) {
|
||||
if(ret == 2) {
|
||||
verbose(VERB_ALGO, "error parsing TTL on line [%s:%d] %s",
|
||||
xfr->task_transfer->master->file,
|
||||
pstate.lineno,
|
||||
sldns_buffer_begin(scratch_buffer));
|
||||
return 0;
|
||||
}
|
||||
continue; /* $TTL has been handled */
|
||||
}
|
||||
if(!http_parse_add_rr(xfr, z, scratch_buffer, &pstate)) {
|
||||
|
@ -209,11 +209,13 @@ sldns_hexdigit_to_int(char ch)
|
||||
}
|
||||
|
||||
uint32_t
|
||||
sldns_str2period(const char *nptr, const char **endptr)
|
||||
sldns_str2period(const char *nptr, const char **endptr, int* overflow)
|
||||
{
|
||||
int sign = 0;
|
||||
uint32_t i = 0;
|
||||
uint32_t seconds = 0;
|
||||
const uint32_t maxint = 0xffffffff;
|
||||
*overflow = 0;
|
||||
|
||||
for(*endptr = nptr; **endptr; (*endptr)++) {
|
||||
switch (**endptr) {
|
||||
@ -236,26 +238,46 @@ sldns_str2period(const char *nptr, const char **endptr)
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
if(seconds > maxint-i) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i;
|
||||
i = 0;
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
if(i > maxint/60 || seconds > maxint-(i*60)) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i * 60;
|
||||
i = 0;
|
||||
break;
|
||||
case 'h':
|
||||
case 'H':
|
||||
if(i > maxint/(60*60) || seconds > maxint-(i*60*60)) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i * 60 * 60;
|
||||
i = 0;
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
if(i > maxint/(60*60*24) || seconds > maxint-(i*60*60*24)) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i * 60 * 60 * 24;
|
||||
i = 0;
|
||||
break;
|
||||
case 'w':
|
||||
case 'W':
|
||||
if(i > maxint/(60*60*24*7) || seconds > maxint-(i*60*60*24*7)) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i * 60 * 60 * 24 * 7;
|
||||
i = 0;
|
||||
break;
|
||||
@ -269,15 +291,27 @@ sldns_str2period(const char *nptr, const char **endptr)
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if(i > maxint/10 || i > maxint - (**endptr - '0')) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
i *= 10;
|
||||
i += (**endptr - '0');
|
||||
break;
|
||||
default:
|
||||
if(seconds > maxint-i) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i;
|
||||
/* disregard signedness */
|
||||
return seconds;
|
||||
}
|
||||
}
|
||||
if(seconds > maxint-i) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i;
|
||||
/* disregard signedness */
|
||||
return seconds;
|
||||
|
@ -74,9 +74,11 @@ struct tm * sldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct t
|
||||
* converts a ttl value (like 5d2h) to a long.
|
||||
* \param[in] nptr the start of the string
|
||||
* \param[out] endptr points to the last char in case of error
|
||||
* \param[out] overflow returns if the string causes integer overflow error,
|
||||
* the number is too big, string of digits too long.
|
||||
* \return the convert duration value
|
||||
*/
|
||||
uint32_t sldns_str2period(const char *nptr, const char **endptr);
|
||||
uint32_t sldns_str2period(const char *nptr, const char **endptr, int* overflow);
|
||||
|
||||
/**
|
||||
* Returns the int value of the given (hex) digit
|
||||
|
@ -249,11 +249,16 @@ rrinternal_get_ttl(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
int* not_there, uint32_t* ttl, uint32_t default_ttl)
|
||||
{
|
||||
const char* endptr;
|
||||
int overflow;
|
||||
if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) {
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL,
|
||||
sldns_buffer_position(strbuf));
|
||||
}
|
||||
*ttl = (uint32_t) sldns_str2period(token, &endptr);
|
||||
*ttl = (uint32_t) sldns_str2period(token, &endptr, &overflow);
|
||||
if(overflow) {
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW,
|
||||
sldns_buffer_position(strbuf));
|
||||
}
|
||||
|
||||
if (strlen(token) > 0 && !isdigit((unsigned char)token[0])) {
|
||||
*not_there = 1;
|
||||
@ -1055,12 +1060,15 @@ int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len,
|
||||
return s;
|
||||
} else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) {
|
||||
const char* end = NULL;
|
||||
int overflow = 0;
|
||||
strlcpy((char*)rr, line, *len);
|
||||
*len = 0;
|
||||
*dname_len = 0;
|
||||
if(!parse_state) return LDNS_WIREPARSE_ERR_OK;
|
||||
parse_state->default_ttl = sldns_str2period(
|
||||
sldns_strip_ws(line+5), &end);
|
||||
sldns_strip_ws(line+5), &end, &overflow);
|
||||
if(overflow)
|
||||
return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW;
|
||||
} else if (strncmp(line, "$INCLUDE", 8) == 0) {
|
||||
strlcpy((char*)rr, line, *len);
|
||||
*len = 0;
|
||||
@ -2157,9 +2165,13 @@ int sldns_str2wire_tsigtime_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
{
|
||||
const char* end;
|
||||
uint32_t p = sldns_str2period(str, &end);
|
||||
int overflow;
|
||||
uint32_t p = sldns_str2period(str, &end, &overflow);
|
||||
if(*end != 0)
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str);
|
||||
if(overflow)
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW,
|
||||
end-str);
|
||||
if(*len < 4)
|
||||
return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
|
||||
sldns_write_uint32(rd, p);
|
||||
|
Loading…
Reference in New Issue
Block a user