diff options
author | nectar <nectar@FreeBSD.org> | 2002-11-24 20:59:25 +0000 |
---|---|---|
committer | nectar <nectar@FreeBSD.org> | 2002-11-24 20:59:25 +0000 |
commit | d13cd487f69aa39c9486c32e8c28e08dc9a63c76 (patch) | |
tree | 2708753996e89e20cd6831ff0f1965ac9952a791 /crypto/heimdal/lib/roken/resolve.c | |
parent | 923bcb0860f02fab9cc26fecdbcffc17a9d9a7ec (diff) | |
parent | 1abd325d288bd51f6ca702d7fbf296a6f47f7e74 (diff) | |
download | FreeBSD-src-d13cd487f69aa39c9486c32e8c28e08dc9a63c76.zip FreeBSD-src-d13cd487f69aa39c9486c32e8c28e08dc9a63c76.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r107207,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'crypto/heimdal/lib/roken/resolve.c')
-rw-r--r-- | crypto/heimdal/lib/roken/resolve.c | 430 |
1 files changed, 234 insertions, 196 deletions
diff --git a/crypto/heimdal/lib/roken/resolve.c b/crypto/heimdal/lib/roken/resolve.c index ac380d7..ddecb98 100644 --- a/crypto/heimdal/lib/roken/resolve.c +++ b/crypto/heimdal/lib/roken/resolve.c @@ -45,7 +45,7 @@ #include <assert.h> -RCSID("$Id: resolve.c,v 1.36 2002/09/09 21:39:19 joda Exp $"); +RCSID("$Id: resolve.c,v 1.36.4.1 2002/10/21 14:48:15 joda Exp $"); #undef HAVE_RES_NSEARCH #if (defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND) @@ -111,6 +111,221 @@ dns_free_data(struct dns_reply *r) free (r); } +static int +parse_record(const unsigned char *data, const unsigned char *end_data, + const unsigned char **pp, struct resource_record **rr) +{ + int type, class, ttl, size; + int status; + char host[MAXDNAME]; + const unsigned char *p = *pp; + status = dn_expand(data, end_data, p, host, sizeof(host)); + if(status < 0) + return -1; + if (p + status + 10 > end_data) + return -1; + p += status; + type = (p[0] << 8) | p[1]; + p += 2; + class = (p[0] << 8) | p[1]; + p += 2; + ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + p += 4; + size = (p[0] << 8) | p[1]; + p += 2; + + if (p + size > end_data) + return -1; + + *rr = calloc(1, sizeof(**rr)); + if(*rr == NULL) + return -1; + (*rr)->domain = strdup(host); + if((*rr)->domain == NULL) { + free(*rr); + return -1; + } + (*rr)->type = type; + (*rr)->class = class; + (*rr)->ttl = ttl; + (*rr)->size = size; + switch(type){ + case T_NS: + case T_CNAME: + case T_PTR: + status = dn_expand(data, end_data, p, host, sizeof(host)); + if(status < 0) { + free(*rr); + return -1; + } + (*rr)->u.txt = strdup(host); + if((*rr)->u.txt == NULL) { + free(*rr); + return -1; + } + break; + case T_MX: + case T_AFSDB:{ + status = dn_expand(data, end_data, p + 2, host, sizeof(host)); + if(status < 0){ + free(*rr); + return -1; + } + if (status + 2 > size) { + free(*rr); + return -1; + } + + (*rr)->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) + + strlen(host)); + if((*rr)->u.mx == NULL) { + free(*rr); + return -1; + } + (*rr)->u.mx->preference = (p[0] << 8) | p[1]; + strcpy((*rr)->u.mx->domain, host); + break; + } + case T_SRV:{ + status = dn_expand(data, end_data, p + 6, host, sizeof(host)); + if(status < 0){ + free(*rr); + return -1; + } + if (status + 6 > size) { + free(*rr); + return -1; + } + + (*rr)->u.srv = + (struct srv_record*)malloc(sizeof(struct srv_record) + + strlen(host)); + if((*rr)->u.srv == NULL) { + free(*rr); + return -1; + } + (*rr)->u.srv->priority = (p[0] << 8) | p[1]; + (*rr)->u.srv->weight = (p[2] << 8) | p[3]; + (*rr)->u.srv->port = (p[4] << 8) | p[5]; + strcpy((*rr)->u.srv->target, host); + break; + } + case T_TXT:{ + if(size == 0 || size < *p + 1) { + free(*rr); + return -1; + } + (*rr)->u.txt = (char*)malloc(*p + 1); + if((*rr)->u.txt == NULL) { + free(*rr); + return -1; + } + strncpy((*rr)->u.txt, (char*)p + 1, *p); + (*rr)->u.txt[*p] = '\0'; + break; + } + case T_KEY : { + size_t key_len; + + if (size < 4) { + free(*rr); + return -1; + } + + key_len = size - 4; + (*rr)->u.key = malloc (sizeof(*(*rr)->u.key) + key_len - 1); + if ((*rr)->u.key == NULL) { + free(*rr); + return -1; + } + + (*rr)->u.key->flags = (p[0] << 8) | p[1]; + (*rr)->u.key->protocol = p[2]; + (*rr)->u.key->algorithm = p[3]; + (*rr)->u.key->key_len = key_len; + memcpy ((*rr)->u.key->key_data, p + 4, key_len); + break; + } + case T_SIG : { + size_t sig_len; + + if(size <= 18) { + free(*rr); + return -1; + } + status = dn_expand (data, end_data, p + 18, host, sizeof(host)); + if (status < 0) { + free(*rr); + return -1; + } + if (status + 18 > size) { + free(*rr); + return -1; + } + + /* the signer name is placed after the sig_data, to make it + easy to free this struture; the size calculation below + includes the zero-termination if the structure itself. + don't you just love C? + */ + sig_len = size - 18 - status; + (*rr)->u.sig = malloc(sizeof(*(*rr)->u.sig) + + strlen(host) + sig_len); + if ((*rr)->u.sig == NULL) { + free(*rr); + return -1; + } + (*rr)->u.sig->type = (p[0] << 8) | p[1]; + (*rr)->u.sig->algorithm = p[2]; + (*rr)->u.sig->labels = p[3]; + (*rr)->u.sig->orig_ttl = (p[4] << 24) | (p[5] << 16) + | (p[6] << 8) | p[7]; + (*rr)->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16) + | (p[10] << 8) | p[11]; + (*rr)->u.sig->sig_inception = (p[12] << 24) | (p[13] << 16) + | (p[14] << 8) | p[15]; + (*rr)->u.sig->key_tag = (p[16] << 8) | p[17]; + (*rr)->u.sig->sig_len = sig_len; + memcpy ((*rr)->u.sig->sig_data, p + 18 + status, sig_len); + (*rr)->u.sig->signer = &(*rr)->u.sig->sig_data[sig_len]; + strcpy((*rr)->u.sig->signer, host); + break; + } + + case T_CERT : { + size_t cert_len; + + if (size < 5) { + free(*rr); + return -1; + } + + cert_len = size - 5; + (*rr)->u.cert = malloc (sizeof(*(*rr)->u.cert) + cert_len - 1); + if ((*rr)->u.cert == NULL) { + free(*rr); + return -1; + } + + (*rr)->u.cert->type = (p[0] << 8) | p[1]; + (*rr)->u.cert->tag = (p[2] << 8) | p[3]; + (*rr)->u.cert->algorithm = p[4]; + (*rr)->u.cert->cert_len = cert_len; + memcpy ((*rr)->u.cert->cert_data, p + 5, cert_len); + break; + } + default: + (*rr)->u.data = (unsigned char*)malloc(size); + if(size != 0 && (*rr)->u.data == NULL) { + free(*rr); + return -1; + } + memcpy((*rr)->u.data, p, size); + } + *pp = p + size; + return 0; +} + #ifndef TEST_RESOLVE static #endif @@ -118,8 +333,9 @@ struct dns_reply* parse_reply(const unsigned char *data, size_t len) { const unsigned char *p; - char host[128]; int status; + int i; + char host[MAXDNAME]; const unsigned char *end_data = data + len; struct dns_reply *r; struct resource_record **rr; @@ -137,6 +353,10 @@ parse_reply(const unsigned char *data, size_t len) memcpy(&r->h, p, 12); /* XXX this will probably be mostly garbage */ p += 12; #endif + if(ntohs(r->h.qdcount) != 1) { + free(r); + return NULL; + } status = dn_expand(data, end_data, p, host, sizeof(host)); if(status < 0){ dns_free_data(r); @@ -156,209 +376,27 @@ parse_reply(const unsigned char *data, size_t len) p += 2; r->q.class = (p[0] << 8 | p[1]); p += 2; + rr = &r->head; - while(p < end_data){ - int type, class, ttl, size; - status = dn_expand(data, end_data, p, host, sizeof(host)); - if(status < 0){ + for(i = 0; i < ntohs(r->h.ancount); i++) { + if(parse_record(data, end_data, &p, rr) != 0) { dns_free_data(r); return NULL; } - if (p + status + 10 > end_data) { - dns_free_data(r); - return NULL; - } - p += status; - type = (p[0] << 8) | p[1]; - p += 2; - class = (p[0] << 8) | p[1]; - p += 2; - ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; - p += 4; - size = (p[0] << 8) | p[1]; - p += 2; - - if (p + size > end_data) { - dns_free_data(r); - return NULL; - } - - *rr = (struct resource_record*)calloc(1, - sizeof(struct resource_record)); - if(*rr == NULL) { + rr = &(*rr)->next; + } + for(i = 0; i < ntohs(r->h.nscount); i++) { + if(parse_record(data, end_data, &p, rr) != 0) { dns_free_data(r); return NULL; } - (*rr)->domain = strdup(host); - if((*rr)->domain == NULL) { + rr = &(*rr)->next; + } + for(i = 0; i < ntohs(r->h.arcount); i++) { + if(parse_record(data, end_data, &p, rr) != 0) { dns_free_data(r); return NULL; } - (*rr)->type = type; - (*rr)->class = class; - (*rr)->ttl = ttl; - (*rr)->size = size; - switch(type){ - case T_NS: - case T_CNAME: - case T_PTR: - status = dn_expand(data, end_data, p, host, sizeof(host)); - if(status < 0){ - dns_free_data(r); - return NULL; - } - (*rr)->u.txt = strdup(host); - if((*rr)->u.txt == NULL) { - dns_free_data(r); - return NULL; - } - break; - case T_MX: - case T_AFSDB:{ - status = dn_expand(data, end_data, p + 2, host, sizeof(host)); - if(status < 0){ - dns_free_data(r); - return NULL; - } - if (status + 2 > size) { - dns_free_data(r); - return NULL; - } - - (*rr)->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) + - strlen(host)); - if((*rr)->u.mx == NULL) { - dns_free_data(r); - return NULL; - } - (*rr)->u.mx->preference = (p[0] << 8) | p[1]; - strcpy((*rr)->u.mx->domain, host); - break; - } - case T_SRV:{ - status = dn_expand(data, end_data, p + 6, host, sizeof(host)); - if(status < 0){ - dns_free_data(r); - return NULL; - } - if (status + 6 > size) { - dns_free_data(r); - return NULL; - } - - (*rr)->u.srv = - (struct srv_record*)malloc(sizeof(struct srv_record) + - strlen(host)); - if((*rr)->u.srv == NULL) { - dns_free_data(r); - return NULL; - } - (*rr)->u.srv->priority = (p[0] << 8) | p[1]; - (*rr)->u.srv->weight = (p[2] << 8) | p[3]; - (*rr)->u.srv->port = (p[4] << 8) | p[5]; - strcpy((*rr)->u.srv->target, host); - break; - } - case T_TXT:{ - (*rr)->u.txt = (char*)malloc(size + 1); - if((*rr)->u.txt == NULL) { - dns_free_data(r); - return NULL; - } - strncpy((*rr)->u.txt, (char*)p + 1, *p); - (*rr)->u.txt[*p] = 0; - break; - } - case T_KEY : { - size_t key_len; - - if (size < 4) { - dns_free_data (r); - return NULL; - } - - key_len = size - 4; - (*rr)->u.key = malloc (sizeof(*(*rr)->u.key) + key_len - 1); - if ((*rr)->u.key == NULL) { - dns_free_data (r); - return NULL; - } - - (*rr)->u.key->flags = (p[0] << 8) | p[1]; - (*rr)->u.key->protocol = p[2]; - (*rr)->u.key->algorithm = p[3]; - (*rr)->u.key->key_len = key_len; - memcpy ((*rr)->u.key->key_data, p + 4, key_len); - break; - } - case T_SIG : { - size_t sig_len; - - status = dn_expand (data, end_data, p + 18, host, sizeof(host)); - if (status < 0) { - dns_free_data (r); - return NULL; - } - if (status + 18 > size) { - dns_free_data(r); - return NULL; - } - - sig_len = len - 18 - status; - (*rr)->u.sig = malloc(sizeof(*(*rr)->u.sig) - + strlen(host) + sig_len); - if ((*rr)->u.sig == NULL) { - dns_free_data (r); - return NULL; - } - (*rr)->u.sig->type = (p[0] << 8) | p[1]; - (*rr)->u.sig->algorithm = p[2]; - (*rr)->u.sig->labels = p[3]; - (*rr)->u.sig->orig_ttl = (p[4] << 24) | (p[5] << 16) - | (p[6] << 8) | p[7]; - (*rr)->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16) - | (p[10] << 8) | p[11]; - (*rr)->u.sig->sig_inception = (p[12] << 24) | (p[13] << 16) - | (p[14] << 8) | p[15]; - (*rr)->u.sig->key_tag = (p[16] << 8) | p[17]; - (*rr)->u.sig->sig_len = sig_len; - memcpy ((*rr)->u.sig->sig_data, p + 18 + status, sig_len); - (*rr)->u.sig->signer = &(*rr)->u.sig->sig_data[sig_len]; - strcpy((*rr)->u.sig->signer, host); - break; - } - - case T_CERT : { - size_t cert_len; - - if (size < 5) { - dns_free_data(r); - return NULL; - } - - cert_len = size - 5; - (*rr)->u.cert = malloc (sizeof(*(*rr)->u.cert) + cert_len - 1); - if ((*rr)->u.cert == NULL) { - dns_free_data (r); - return NULL; - } - - (*rr)->u.cert->type = (p[0] << 8) | p[1]; - (*rr)->u.cert->tag = (p[2] << 8) | p[3]; - (*rr)->u.cert->algorithm = p[4]; - (*rr)->u.cert->cert_len = cert_len; - memcpy ((*rr)->u.cert->cert_data, p + 5, cert_len); - break; - } - default: - (*rr)->u.data = (unsigned char*)malloc(size); - if(size != 0 && (*rr)->u.data == NULL) { - dns_free_data(r); - return NULL; - } - memcpy((*rr)->u.data, p, size); - } - p += size; rr = &(*rr)->next; } *rr = NULL; @@ -566,7 +604,7 @@ main(int argc, char **argv) dns_srv_order(r); for(rr = r->head; rr;rr=rr->next){ - printf("%s %s %d ", rr->domain, dns_type_to_string(rr->type), rr->ttl); + printf("%-30s %-5s %-6d ", rr->domain, dns_type_to_string(rr->type), rr->ttl); switch(rr->type){ case T_NS: case T_CNAME: |