TSIG and TKEY parsing by gldns

This commit is contained in:
Willem Toorop 2017-05-02 16:28:55 +02:00
parent 1e44ea7bd8
commit dab93cd197
8 changed files with 204 additions and 11 deletions

View File

@ -469,6 +469,30 @@ gldns_buffer_write_at(gldns_buffer *buffer, size_t at, const void *data, size_t
memcpy(buffer->_data + at, data, count); memcpy(buffer->_data + at, data, count);
} }
/**
* set the given byte to the buffer at the specified position
* \param[in] buffer the buffer
* \param[in] at the position (in number of bytes) to write the data at
* \param[in] c the byte to set to the buffer
* \param[in] count the number of bytes of bytes to write
*/
INLINE void
gldns_buffer_set_at(gldns_buffer *buffer, size_t at, int c, size_t count)
{
if (!buffer->_vfixed)
assert(gldns_buffer_available_at(buffer, at, count));
else if (gldns_buffer_remaining_at(buffer, at) == 0)
return;
else if (count > gldns_buffer_remaining_at(buffer, at)) {
memset(buffer->_data + at, c,
gldns_buffer_remaining_at(buffer, at));
return;
}
memset(buffer->_data + at, c, count);
}
/** /**
* writes count bytes of data to the current position of the buffer * writes count bytes of data to the current position of the buffer
* \param[in] buffer the buffer * \param[in] buffer the buffer

View File

@ -120,6 +120,10 @@ gldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
if (line_nr) { if (line_nr) {
*line_nr = *line_nr + 1; *line_nr = *line_nr + 1;
} }
if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
*t = '\0';
return -1;
}
*t++ = ' '; *t++ = ' ';
prev_c = c; prev_c = c;
continue; continue;

View File

@ -175,7 +175,7 @@ static const gldns_rdf_type type_tkey_wireformat[] = {
GLDNS_RDF_TYPE_TIME, GLDNS_RDF_TYPE_TIME,
GLDNS_RDF_TYPE_TIME, GLDNS_RDF_TYPE_TIME,
GLDNS_RDF_TYPE_INT16, GLDNS_RDF_TYPE_INT16,
GLDNS_RDF_TYPE_INT16, GLDNS_RDF_TYPE_TSIGERROR,
GLDNS_RDF_TYPE_INT16_DATA, GLDNS_RDF_TYPE_INT16_DATA,
GLDNS_RDF_TYPE_INT16_DATA, GLDNS_RDF_TYPE_INT16_DATA,
}; };
@ -185,7 +185,7 @@ static const gldns_rdf_type type_tsig_wireformat[] = {
GLDNS_RDF_TYPE_INT16, GLDNS_RDF_TYPE_INT16,
GLDNS_RDF_TYPE_INT16_DATA, GLDNS_RDF_TYPE_INT16_DATA,
GLDNS_RDF_TYPE_INT16, GLDNS_RDF_TYPE_INT16,
GLDNS_RDF_TYPE_INT16, GLDNS_RDF_TYPE_TSIGERROR,
GLDNS_RDF_TYPE_INT16_DATA GLDNS_RDF_TYPE_INT16_DATA
}; };
static const gldns_rdf_type type_tlsa_wireformat[] = { static const gldns_rdf_type type_tlsa_wireformat[] = {
@ -606,7 +606,7 @@ static gldns_rr_descriptor rdata_field_descriptors[] = {
{GLDNS_RR_TYPE_CAA, "CAA", 3, 3, type_caa_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_CAA, "CAA", 3, 3, type_caa_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
#ifdef DRAFT_RRTYPES #ifdef DRAFT_RRTYPES
/* 258 */ /* 258 */
{GLDNS_RR_TYPE_AVC, "AVC", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_TXT, "AVC", 1, 0, NULL, GLDNS_RDF_TYPE_STR, GLDNS_RR_NO_COMPRESS, 0 },
#else #else
{GLDNS_RR_TYPE_NULL, "TYPE258", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 }, {GLDNS_RR_TYPE_NULL, "TYPE258", 1, 1, type_0_wireformat, GLDNS_RDF_TYPE_NONE, GLDNS_RR_NO_COMPRESS, 0 },
#endif #endif

View File

@ -351,6 +351,9 @@ enum gldns_enum_rdf_type
*/ */
GLDNS_RDF_TYPE_LONG_STR, GLDNS_RDF_TYPE_LONG_STR,
/** TSIG extended 16bit error value */
GLDNS_RDF_TYPE_TSIGERROR,
/* Aliases */ /* Aliases */
GLDNS_RDF_TYPE_BITMAP = GLDNS_RDF_TYPE_NSEC GLDNS_RDF_TYPE_BITMAP = GLDNS_RDF_TYPE_NSEC
}; };
@ -423,7 +426,7 @@ enum gldns_enum_edns_option
GLDNS_EDNS_DAU = 5, /* RFC6975 */ GLDNS_EDNS_DAU = 5, /* RFC6975 */
GLDNS_EDNS_DHU = 6, /* RFC6975 */ GLDNS_EDNS_DHU = 6, /* RFC6975 */
GLDNS_EDNS_N3U = 7, /* RFC6975 */ GLDNS_EDNS_N3U = 7, /* RFC6975 */
GLDNS_EDNS_CLIENT_SUBNET = 8, /* draft-vandergaast-edns-client-subnet */ GLDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */
GLDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/ GLDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/
GLDNS_EDNS_PADDING = 12 /* RFC7830 */ GLDNS_EDNS_PADDING = 12 /* RFC7830 */
}; };
@ -431,6 +434,15 @@ typedef enum gldns_enum_edns_option gldns_edns_option;
#define GLDNS_EDNS_MASK_DO_BIT 0x8000 #define GLDNS_EDNS_MASK_DO_BIT 0x8000
/** TSIG and TKEY extended rcodes (16bit), 0-15 are the normal rcodes. */
#define GLDNS_TSIG_ERROR_NOERROR 0
#define GLDNS_TSIG_ERROR_BADSIG 16
#define GLDNS_TSIG_ERROR_BADKEY 17
#define GLDNS_TSIG_ERROR_BADTIME 18
#define GLDNS_TSIG_ERROR_BADMODE 19
#define GLDNS_TSIG_ERROR_BADNAME 20
#define GLDNS_TSIG_ERROR_BADALG 21
/** /**
* Contains all information about resource record types. * Contains all information about resource record types.
* *

View File

@ -664,6 +664,14 @@ rrinternal_parse_rdata(gldns_buffer* strbuf, char* token, size_t token_len,
&pre_data_pos, delimiters, &pre_data_pos, delimiters,
rdftype, &token_strlen)) rdftype, &token_strlen))
break; break;
} else if(rdftype == GLDNS_RDF_TYPE_INT16_DATA &&
strcmp(token, "0")!=0) {
/* affix len and b64 fields */
if(!gldns_affix_token(strbuf, token,
&token_len, &quoted, &parens,
&pre_data_pos, delimiters,
rdftype, &token_strlen))
break;
} }
/* normal RR */ /* normal RR */
@ -940,6 +948,8 @@ int gldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len,
return gldns_str2wire_time_buf(str, rd, len); return gldns_str2wire_time_buf(str, rd, len);
case GLDNS_RDF_TYPE_PERIOD: case GLDNS_RDF_TYPE_PERIOD:
return gldns_str2wire_period_buf(str, rd, len); return gldns_str2wire_period_buf(str, rd, len);
case GLDNS_RDF_TYPE_TSIGTIME:
return gldns_str2wire_tsigtime_buf(str, rd, len);
case GLDNS_RDF_TYPE_LOC: case GLDNS_RDF_TYPE_LOC:
return gldns_str2wire_loc_buf(str, rd, len); return gldns_str2wire_loc_buf(str, rd, len);
case GLDNS_RDF_TYPE_WKS: case GLDNS_RDF_TYPE_WKS:
@ -964,6 +974,8 @@ int gldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len,
return gldns_str2wire_tag_buf(str, rd, len); return gldns_str2wire_tag_buf(str, rd, len);
case GLDNS_RDF_TYPE_LONG_STR: case GLDNS_RDF_TYPE_LONG_STR:
return gldns_str2wire_long_str_buf(str, rd, len); return gldns_str2wire_long_str_buf(str, rd, len);
case GLDNS_RDF_TYPE_TSIGERROR:
return gldns_str2wire_tsigerror_buf(str, rd, len);
case GLDNS_RDF_TYPE_HIP: case GLDNS_RDF_TYPE_HIP:
return gldns_str2wire_hip_buf(str, rd, len); return gldns_str2wire_hip_buf(str, rd, len);
case GLDNS_RDF_TYPE_INT16_DATA: case GLDNS_RDF_TYPE_INT16_DATA:
@ -1341,6 +1353,21 @@ int gldns_str2wire_alg_buf(const char* str, uint8_t* rd, size_t* len)
return GLDNS_WIREPARSE_ERR_OK; return GLDNS_WIREPARSE_ERR_OK;
} }
int gldns_str2wire_tsigerror_buf(const char* str, uint8_t* rd, size_t* len)
{
gldns_lookup_table *lt = gldns_lookup_by_name(gldns_tsig_errors, str);
if(*len < 2)
return GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
if(lt) {
gldns_write_uint16(rd, (uint16_t)lt->id);
*len = 2;
} else {
/* try as-is (a number) */
return gldns_str2wire_int16_buf(str, rd, len);
}
return GLDNS_WIREPARSE_ERR_OK;
}
int gldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len) int gldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len)
{ {
/* convert a time YYYYDDMMHHMMSS to wireformat */ /* convert a time YYYYDDMMHHMMSS to wireformat */
@ -1383,6 +1410,24 @@ int gldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len)
return GLDNS_WIREPARSE_ERR_OK; return GLDNS_WIREPARSE_ERR_OK;
} }
int gldns_str2wire_tsigtime_buf(const char* str, uint8_t* rd, size_t* len)
{
char* end;
uint64_t t = (uint64_t)strtol((char*)str, &end, 10);
uint16_t high;
uint32_t low;
if(*end != 0)
return RET_ERR(GLDNS_WIREPARSE_ERR_SYNTAX_TIME, end-str);
if(*len < 6)
return GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
high = (uint16_t)(t>>32);
low = (uint32_t)(t);
gldns_write_uint16(rd, high);
gldns_write_uint32(rd+2, low);
*len = 6;
return GLDNS_WIREPARSE_ERR_OK;
}
int gldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len) int gldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len)
{ {
const char* end; const char* end;
@ -2008,13 +2053,26 @@ int gldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len)
int gldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len) int gldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len)
{ {
size_t sz = gldns_b64_pton_calculate_size(strlen(str)); char* s;
int n; int n;
if(*len < sz+2) n = strtol(str, &s, 10);
if(*len < ((size_t)n)+2)
return GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; return GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
if(sz > 65535) if(n > 65535)
return GLDNS_WIREPARSE_ERR_LABEL_OVERFLOW; return GLDNS_WIREPARSE_ERR_LABEL_OVERFLOW;
n = gldns_b64_pton(str, rd+2, (*len)-2);
if(n == 0) {
gldns_write_uint16(rd, 0);
*len = 2;
return GLDNS_WIREPARSE_ERR_OK;
}
if(*s != ' ')
return RET_ERR(GLDNS_WIREPARSE_ERR_SYNTAX_INT, s-(char*)str);
s++;
while(*s == ' ')
s++;
n = gldns_b64_pton(s, rd+2, (*len)-2);
if(n < 0) if(n < 0)
return GLDNS_WIREPARSE_ERR_SYNTAX_B64; return GLDNS_WIREPARSE_ERR_SYNTAX_B64;
gldns_write_uint16(rd, (uint16_t)n); gldns_write_uint16(rd, (uint16_t)n);

View File

@ -417,6 +417,24 @@ int gldns_str2wire_time_buf(const char* str, uint8_t* rd, size_t* len);
*/ */
int gldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len); int gldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len);
/**
* Convert rdf of type GLDNS_RDF_TYPE_TSIGTIME from string to wireformat.
* @param str: the text to convert for this rdata element.
* @param rd: rdata buffer for the wireformat.
* @param len: length of rd buffer on input, used length on output.
* @return 0 on success, error on failure.
*/
int gldns_str2wire_tsigtime_buf(const char* str, uint8_t* rd, size_t* len);
/**
* Convert rdf of type GLDNS_RDF_TYPE_TSIGERROR from string to wireformat.
* @param str: the text to convert for this rdata element.
* @param rd: rdata buffer for the wireformat.
* @param len: length of rd buffer on input, used length on output.
* @return 0 on success, error on failure.
*/
int gldns_str2wire_tsigerror_buf(const char* str, uint8_t* rd, size_t* len);
/** /**
* Convert rdf of type GLDNS_RDF_TYPE_LOC from string to wireformat. * Convert rdf of type GLDNS_RDF_TYPE_LOC from string to wireformat.
* @param str: the text to convert for this rdata element. * @param str: the text to convert for this rdata element.

View File

@ -173,6 +173,28 @@ static gldns_lookup_table gldns_edns_options_data[] = {
}; };
gldns_lookup_table* gldns_edns_options = gldns_edns_options_data; gldns_lookup_table* gldns_edns_options = gldns_edns_options_data;
static gldns_lookup_table gldns_tsig_errors_data[] = {
{ GLDNS_TSIG_ERROR_NOERROR, "NOERROR" },
{ GLDNS_RCODE_FORMERR, "FORMERR" },
{ GLDNS_RCODE_SERVFAIL, "SERVFAIL" },
{ GLDNS_RCODE_NXDOMAIN, "NXDOMAIN" },
{ GLDNS_RCODE_NOTIMPL, "NOTIMPL" },
{ GLDNS_RCODE_REFUSED, "REFUSED" },
{ GLDNS_RCODE_YXDOMAIN, "YXDOMAIN" },
{ GLDNS_RCODE_YXRRSET, "YXRRSET" },
{ GLDNS_RCODE_NXRRSET, "NXRRSET" },
{ GLDNS_RCODE_NOTAUTH, "NOTAUTH" },
{ GLDNS_RCODE_NOTZONE, "NOTZONE" },
{ GLDNS_TSIG_ERROR_BADSIG, "BADSIG" },
{ GLDNS_TSIG_ERROR_BADKEY, "BADKEY" },
{ GLDNS_TSIG_ERROR_BADTIME, "BADTIME" },
{ GLDNS_TSIG_ERROR_BADMODE, "BADMODE" },
{ GLDNS_TSIG_ERROR_BADNAME, "BADNAME" },
{ GLDNS_TSIG_ERROR_BADALG, "BADALG" },
{ 0, NULL }
};
gldns_lookup_table* gldns_tsig_errors = gldns_tsig_errors_data;
char* gldns_wire2str_pkt(uint8_t* data, size_t len) char* gldns_wire2str_pkt(uint8_t* data, size_t len)
{ {
size_t slen = (size_t)gldns_wire2str_pkt_buf(data, len, NULL, 0); size_t slen = (size_t)gldns_wire2str_pkt_buf(data, len, NULL, 0);
@ -285,6 +307,12 @@ int gldns_wire2str_rcode_buf(int rcode, char* s, size_t slen)
return gldns_wire2str_rcode_print(&s, &slen, rcode); return gldns_wire2str_rcode_print(&s, &slen, rcode);
} }
int gldns_wire2str_opcode_buf(int opcode, char* s, size_t slen)
{
/* use arguments as temporary variables */
return gldns_wire2str_opcode_print(&s, &slen, opcode);
}
int gldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen) int gldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
{ {
/* use arguments as temporary variables */ /* use arguments as temporary variables */
@ -982,6 +1010,8 @@ int gldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
return gldns_wire2str_tag_scan(d, dlen, s, slen); return gldns_wire2str_tag_scan(d, dlen, s, slen);
case GLDNS_RDF_TYPE_LONG_STR: case GLDNS_RDF_TYPE_LONG_STR:
return gldns_wire2str_long_str_scan(d, dlen, s, slen); return gldns_wire2str_long_str_scan(d, dlen, s, slen);
case GLDNS_RDF_TYPE_TSIGERROR:
return gldns_wire2str_tsigerror_scan(d, dlen, s, slen);
} }
/* unknown rdf type */ /* unknown rdf type */
return -1; return -1;
@ -1580,6 +1610,7 @@ int gldns_wire2str_hip_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
int gldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) int gldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
{ {
int w;
uint16_t n; uint16_t n;
if(*dl < 2) if(*dl < 2)
return -1; return -1;
@ -1588,7 +1619,12 @@ int gldns_wire2str_int16_data_scan(uint8_t** d, size_t* dl, char** s, size_t* sl
return -1; return -1;
(*d)+=2; (*d)+=2;
(*dl)-=2; (*dl)-=2;
return gldns_wire2str_b64_scan_num(d, dl, s, sl, n); if(n == 0) {
return gldns_str_print(s, sl, "0");
}
w = gldns_str_print(s, sl, "%u ", (unsigned)n);
w += gldns_wire2str_b64_scan_num(d, dl, s, sl, n);
return w;
} }
int gldns_wire2str_nsec3_next_owner_scan(uint8_t** d, size_t* dl, char** s, int gldns_wire2str_nsec3_next_owner_scan(uint8_t** d, size_t* dl, char** s,
@ -1645,10 +1681,10 @@ int gldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
if(*dl < 1+n) if(*dl < 1+n)
return -1; return -1;
for(i=0; i<n; i++) for(i=0; i<n; i++)
if(!isalnum((unsigned char)(*d)[1+i])) if(!isalnum((unsigned char)(*d)[i+1]))
return -1; return -1;
for(i=0; i<n; i++) for(i=0; i<n; i++)
w += gldns_str_print(s, sl, "%c", (char)(*d)[1+i]); w += gldns_str_print(s, sl, "%c", (char)(*d)[i+1]);
(*d)+=n+1; (*d)+=n+1;
(*dl)-=(n+1); (*dl)-=(n+1);
return w; return w;
@ -1667,6 +1703,21 @@ int gldns_wire2str_long_str_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
return w; return w;
} }
int gldns_wire2str_tsigerror_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
{
gldns_lookup_table *lt;
int data, w;
if(*dl < 2) return -1;
data = (int)gldns_read_uint16(*d);
lt = gldns_lookup_by_id(gldns_tsig_errors, data);
if(lt && lt->name)
w = gldns_str_print(s, sl, "%s", lt->name);
else w = gldns_str_print(s, sl, "%d", data);
(*dl)-=2;
(*d)+=2;
return w;
}
int gldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data, int gldns_wire2str_edns_llq_print(char** s, size_t* sl, uint8_t* data,
size_t len) size_t len)
{ {

View File

@ -38,6 +38,8 @@ extern struct gldns_struct_lookup_table* gldns_edns_flags;
extern struct gldns_struct_lookup_table* gldns_edns_options; extern struct gldns_struct_lookup_table* gldns_edns_options;
/** error string from wireparse */ /** error string from wireparse */
extern struct gldns_struct_lookup_table* gldns_wireparse_errors; extern struct gldns_struct_lookup_table* gldns_wireparse_errors;
/** tsig errors are the rcodes with extra (higher) values */
extern struct gldns_struct_lookup_table* gldns_tsig_errors;
/** /**
* Convert wireformat packet to a string representation * Convert wireformat packet to a string representation
@ -441,6 +443,17 @@ int gldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len);
*/ */
int gldns_wire2str_rcode_buf(int rcode, char* str, size_t len); int gldns_wire2str_rcode_buf(int rcode, char* str, size_t len);
/**
* Convert host format opcode to a string. 'QUERY', 'NOTIFY', 'UPDATE'.
* With user buffer.
* @param opcode: opcode as integer in host order
* @param str: the string to write to.
* @param len: length of str.
* @return the number of characters for this element, excluding zerobyte.
* Is larger or equal than str_len if output was truncated.
*/
int gldns_wire2str_opcode_buf(int opcode, char* str, size_t len);
/** /**
* Convert wire dname to a string, "example.com.". With user buffer. * Convert wire dname to a string, "example.com.". With user buffer.
* @param dname: the dname in uncompressed wireformat. * @param dname: the dname in uncompressed wireformat.
@ -796,6 +809,19 @@ int gldns_wire2str_hip_scan(uint8_t** data, size_t* data_len, char** str,
int gldns_wire2str_int16_data_scan(uint8_t** data, size_t* data_len, char** str, int gldns_wire2str_int16_data_scan(uint8_t** data, size_t* data_len, char** str,
size_t* str_len); size_t* str_len);
/**
* Scan wireformat tsigerror field to string, with user buffers.
* It shifts the arguments to move along (see gldns_wire2str_pkt_scan).
* @param data: wireformat data.
* @param data_len: length of data buffer.
* @param str: string buffer.
* @param str_len: length of string buffer.
* @return number of characters (except null) needed to print.
* Can return -1 on failure.
*/
int gldns_wire2str_tsigerror_scan(uint8_t** data, size_t* data_len, char** str,
size_t* str_len);
/** /**
* Scan wireformat nsec3_next_owner field to string, with user buffers. * Scan wireformat nsec3_next_owner field to string, with user buffers.
* It shifts the arguments to move along (see gldns_wire2str_pkt_scan). * It shifts the arguments to move along (see gldns_wire2str_pkt_scan).