/* * Parse rdata portion of an RRSIG Resource Record. * Returns the number of bytes in the RRSIG rdata portion that were parsed. * Caller assumes responsiblity for allocated dnskey_rdata memory. */ int val_parse_rrsig_rdata(const u_char *buf, size_t buflen, val_rrsig_rdata_t * rdata) { size_t index = 0; const u_char *cp; size_t namelen; int retval; if (!rdata || !buf) return VAL_BAD_ARGUMENT; if (index + 18 > buflen) return VAL_BAD_ARGUMENT; cp = buf; VAL_GET16(rdata->type_covered, cp); index += 2; rdata->algorithm = (u_char) (buf[index]); index += 1; rdata->labels = (u_char) (buf[index]); index += 1; cp = (buf + index); VAL_GET32(rdata->orig_ttl, cp); index += 4; VAL_GET32(rdata->sig_expr, cp); index += 4; VAL_GET32(rdata->sig_incp, cp); index += 4; VAL_GET16(rdata->key_tag, cp); index += 2; if (VAL_NO_ERROR != (retval = val_parse_dname(buf, buflen, index, (char *) rdata->signer_name, &namelen))) { return retval; } index += namelen; rdata->signature_len = (buflen > index) ? (buflen - index) : 0; if (rdata->signature_len > 0) { rdata->signature = (u_char *) MALLOC(rdata->signature_len * sizeof(u_char)); if (rdata->signature == NULL) return VAL_OUT_OF_MEMORY; memcpy(rdata->signature, buf + index, rdata->signature_len); index += rdata->signature_len; } else rdata->signature = NULL; return VAL_NO_ERROR; }
/* * Returns VAL_NO_ERROR on success, other values on failure */ static int rsamd5_parse_public_key(const u_char *buf, size_t buflen, RSA * rsa) { int index = 0; const u_char *cp; u_int16_t exp_len = 0x0000; BIGNUM *bn_exp; BIGNUM *bn_mod; if (!rsa || buflen == 0) return VAL_BAD_ARGUMENT; cp = buf; if (buf[index] == 0) { if (buflen < 3) return VAL_BAD_ARGUMENT; index += 1; cp = (buf + index); VAL_GET16(exp_len, cp); index += 2; } else { exp_len += buf[index]; index += 1; } if (exp_len > buflen - index) { return VAL_BAD_ARGUMENT; } /* * Extract the exponent */ bn_exp = BN_bin2bn(buf + index, exp_len, NULL); index += exp_len; if (buflen <= index) { return VAL_BAD_ARGUMENT; } /* * Extract the modulus */ bn_mod = BN_bin2bn(buf + index, buflen - index, NULL); rsa->e = bn_exp; rsa->n = bn_mod; return VAL_NO_ERROR; /* success */ }
/* * Parse rdata portion of a DS Resource Record. */ int val_parse_ds_rdata(const u_char *buf, size_t buflen, val_ds_rdata_t * rdata) { size_t index = 0; const u_char *cp = buf; if (!rdata || !buf) return VAL_BAD_ARGUMENT; if (index + 2 + 1 + 1 > buflen) return VAL_BAD_ARGUMENT; VAL_GET16(rdata->d_keytag, cp); index += 2; rdata->d_algo = (u_char) (buf[index]); index += 1; rdata->d_type = (u_char) (buf[index]); index += 1; /* * Only SHA-1 is understood */ if (rdata->d_type == ALG_DS_HASH_SHA1) rdata->d_hash_len = SHA_DIGEST_LENGTH; else if (rdata->d_type == ALG_DS_HASH_SHA256) rdata->d_hash_len = SHA256_DIGEST_LENGTH; else return VAL_NOT_IMPLEMENTED; if (index + rdata->d_hash_len > buflen) return VAL_BAD_ARGUMENT; rdata->d_hash = (u_char *) MALLOC(rdata->d_hash_len * sizeof(u_char)); if (rdata->d_hash == NULL) return VAL_OUT_OF_MEMORY; memcpy(rdata->d_hash, buf + index, rdata->d_hash_len); index += rdata->d_hash_len; return VAL_NO_ERROR; }
/* * Parse rdata portion of a DNSKEY Resource Record. * Returns the number of bytes in the DNSKEY rdata portion that were parsed on success. * Returns 0 on failure. */ int val_parse_dnskey_rdata(const u_char *buf, size_t buflen, val_dnskey_rdata_t * rdata) { size_t index = 0; const u_char *cp; if (!rdata || !buf) return VAL_BAD_ARGUMENT; if (index + 4 > buflen) return VAL_BAD_ARGUMENT; cp = buf; VAL_GET16(rdata->flags, cp); index += 2; rdata->protocol = (u_char) (buf[index]); index += 1; rdata->algorithm = (u_char) (buf[index]); index += 1; rdata->public_key_len = (buflen > index) ? (buflen - index) : 0; if (rdata->public_key_len > 0) { rdata->public_key = (u_char *) MALLOC(rdata->public_key_len * sizeof(u_char)); if (rdata->public_key == NULL) return VAL_OUT_OF_MEMORY; memcpy(rdata->public_key, buf + index, rdata->public_key_len); index += rdata->public_key_len; } else rdata->public_key = NULL; if (rdata->algorithm == ALG_RSAMD5) { rdata->key_tag = rsamd5_keytag(buf, buflen); } else { rdata->key_tag = keytag(buf, buflen); } return VAL_NO_ERROR; }
static int process_packet(val_context_t *context) { HEADER *query_header, *response_header; u_char *pos; int q_name_len, rc; u_int16_t type_h, class_h; struct sockaddr from; socklen_t from_len; u_char query[4096], response[4096]; int query_size, response_size; /* * get a packet */ from_len = sizeof(from); memset(&from, 0x0, sizeof(from)); do { rc = recvfrom(listen_fd, query, sizeof(query), 0, &from, &from_len); if (rc < 0 && errno != EINTR) { // xxx-rks: log err msg break; } } while (rc < 0); if (rc < 0) return rc; query_size = rc; if (query_size < (sizeof(HEADER) + 1)) return -1; query_header = (HEADER *) query; /* * get query name */ pos = &query[sizeof(HEADER)]; q_name_len = wire_name_length(pos); pos += q_name_len; /* * get class and type */ VAL_GET16(type_h, pos); VAL_GET16(class_h, pos); response_size = sizeof(response); get_results(context, "test", (char *)&query[sizeof(HEADER)], (int)class_h, (int)type_h, response, &response_size, 0); /* * check to see if we need a dummy response */ val_log(NULL, LOG_DEBUG, "XXX-RKS: handle no response"); if (0 == response_size) { // no response; generate dummy/nxdomain response? return 1; } response_header = (HEADER*)response; response_header->id = query_header->id; /* * send response */ do { rc = sendto(listen_fd, response, response_size, 0, &from, sizeof(from)); if (rc < 0 && errno != EINTR) { // xxx-rks: log err msg break; } } while (rc < 0); if (rc > 0) { val_log(NULL, LOG_DEBUG, "sent %d bytes", rc); } return 0; /* no error */ }
val_nsec3_rdata_t * val_parse_nsec3_rdata(u_char * rr_rdata, size_t rdatalen, val_nsec3_rdata_t * nd) { u_char *cp; size_t nexthashlen, retlen; u_char *nexthash; if (nd == NULL) return NULL; cp = rr_rdata; if (rdatalen < 5) { /* * somethings wrong */ return NULL; } nd->alg = *cp; cp += 1; nd->flags = *cp; cp += 1; VAL_GET16(nd->iterations, cp); nd->saltlen = *cp; cp += 1; if ((cp - rr_rdata) >= rdatalen) return NULL; nd->salt = cp; cp += nd->saltlen; if ((cp - rr_rdata) >= rdatalen) return NULL; nexthashlen = *cp; cp += 1; if ((cp - rr_rdata) >= rdatalen) return NULL; nexthash = cp; cp += nexthashlen; /* note that the next check does not check >= */ /* this is because the bit field can be empty */ if ((cp - rr_rdata) > rdatalen) return NULL; base32hex_encode(nexthash, nexthashlen, &(nd->nexthash), &retlen); nd->nexthashlen = (u_char)retlen; if (retlen > nd->nexthashlen) return NULL; /* bit field can be empty */ if (cp - rr_rdata == rdatalen) { nd->bit_field = 0; } else { nd->bit_field = cp - rr_rdata; } return nd; }