Exemple #1
0
/**
 * Read the next RR from zone file.
 *
 */
ldns_rr*
addns_read_rr(FILE* fd, char* line, ldns_rdf** orig, ldns_rdf** prev,
              uint32_t* ttl, ldns_status* status, unsigned int* l)
{
    ldns_rr* rr = NULL;
    int len = 0;
    uint32_t new_ttl = 0;

addns_read_line:
    if (ttl) {
        new_ttl = *ttl;
    }
    len = adutil_readline_frm_file(fd, line, l, 0);
    adutil_rtrim_line(line, &len);
    if (len >= 0) {
        switch (line[0]) {
        /* no directives */

        /* comments, empty lines */
        case ';':
        case '\n':
            goto addns_read_line; /* perhaps next line is rr */
            break;
        /* let's hope its a RR */
        default:
            if (adutil_whitespace_line(line, len)) {
                goto addns_read_line; /* perhaps next line is rr */
                break;
            }
            *status = ldns_rr_new_frm_str(&rr, line, new_ttl, *orig, prev);
            if (*status == LDNS_STATUS_OK) {
                return rr;
            } else if (*status == LDNS_STATUS_SYNTAX_EMPTY) {
                if (rr) {
                    ldns_rr_free(rr);
                    rr = NULL;
                }
                *status = LDNS_STATUS_OK;
                goto addns_read_line; /* perhaps next line is rr */
                break;
            } else {
                ods_log_error("[%s] error parsing RR at line %i (%s): %s",
                              adapter_str, l&&*l?*l:0,
                              ldns_get_errorstr_by_id(*status), line);
                while (len >= 0) {
                    len = adutil_readline_frm_file(fd, line, l, 0);
                }
                if (rr) {
                    ldns_rr_free(rr);
                    rr = NULL;
                }
                return NULL;
            }
            break;
        }
    }
    /* -1, EOF */
    *status = LDNS_STATUS_OK;
    return NULL;
}
/**
 * Update serial.
 *
 */
ods_status
zone_update_serial(zone_type* zone)
{
    ods_status status = ODS_STATUS_OK;
    rrset_type* rrset = NULL;
    rr_type* soa = NULL;
    ldns_rr* rr = NULL;
    ldns_rdf* soa_rdata = NULL;

    ods_log_assert(zone);
    ods_log_assert(zone->apex);
    ods_log_assert(zone->name);
    ods_log_assert(zone->db);
    ods_log_assert(zone->signconf);

    if (zone->db->serial_updated) {
        /* already done, unmark and return ok */
        ods_log_debug("[%s] zone %s soa serial already up to date",
            zone_str, zone->name);
        zone->db->serial_updated = 0;
        return ODS_STATUS_OK;
    }
    rrset = zone_lookup_rrset(zone, zone->apex, LDNS_RR_TYPE_SOA);
    ods_log_assert(rrset);
    ods_log_assert(rrset->rrs);
    ods_log_assert(rrset->rrs[0].rr);
    rr = ldns_rr_clone(rrset->rrs[0].rr);
    if (!rr) {
        ods_log_error("[%s] unable to update zone %s soa serial: failed to "
            "clone soa rr", zone_str, zone->name);
        return ODS_STATUS_ERR;
    }
    status = namedb_update_serial(zone->db, zone->signconf->soa_serial,
        zone->db->inbserial);
    if (status != ODS_STATUS_OK) {
        ods_log_error("[%s] unable to update zone %s soa serial: %s",
            zone_str, zone->name, ods_status2str(status));
        ldns_rr_free(rr);
        return status;
    }
    ods_log_verbose("[%s] zone %s set soa serial to %u", zone_str,
        zone->name, zone->db->intserial);
    soa_rdata = ldns_rr_set_rdf(rr,
        ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
        zone->db->intserial), SE_SOA_RDATA_SERIAL);
    if (soa_rdata) {
        ldns_rdf_deep_free(soa_rdata);
        soa_rdata = NULL;
    } else {
        ods_log_error("[%s] unable to update zone %s soa serial: failed to "
            "replace soa serial rdata", zone_str, zone->name);
        ldns_rr_free(rr);
        return ODS_STATUS_ERR;
    }
    soa = rrset_add_rr(rrset, rr);
    ods_log_assert(soa);
    rrset_diff(rrset, 0, 0);
    zone->db->serial_updated = 0;
    return ODS_STATUS_OK;
}
Exemple #3
0
/** convert to ldns rr */
static ldns_rr*
to_rr(struct ub_packed_rrset_key* k, struct packed_rrset_data* d, 
	uint32_t now, size_t i, uint16_t type)
{
	ldns_rr* rr = ldns_rr_new();
	ldns_rdf* rdf;
	ldns_status status;
	size_t pos;
	log_assert(i < d->count + d->rrsig_count);
	if(!rr) {
		return NULL;
	}
	ldns_rr_set_type(rr, type);
	ldns_rr_set_class(rr, ntohs(k->rk.rrset_class));
	if(d->rr_ttl[i] < now)
		ldns_rr_set_ttl(rr, 0);
	else	ldns_rr_set_ttl(rr, d->rr_ttl[i] - now);
	pos = 0;
	status = ldns_wire2dname(&rdf, k->rk.dname, k->rk.dname_len, &pos);
	if(status != LDNS_STATUS_OK) {
		/* we drop detailed error in status */
		ldns_rr_free(rr);
		return NULL;
	}
	ldns_rr_set_owner(rr, rdf);
	pos = 0;
	status = ldns_wire2rdf(rr, d->rr_data[i], d->rr_len[i], &pos);
	if(status != LDNS_STATUS_OK) {
		/* we drop detailed error in status */
		ldns_rr_free(rr);
		return NULL;
	}
	return rr;
}
Exemple #4
0
/** convert and print rdata */
static void
print_rd(int t, char* data, size_t len)
{
	size_t i, pos = 0;
	uint8_t* rd = (uint8_t*)malloc(len+2);
	ldns_rr* rr = ldns_rr_new();
	ldns_status status;
	if(!rd || !rr) {
		fprintf(stderr, "out of memory");
		exit(1);
	}
	ldns_rr_set_type(rr, t);
	ldns_write_uint16(rd, len);
	memmove(rd+2, data, len);
	ldns_rr_set_owner(rr, NULL);
	status = ldns_wire2rdf(rr, rd, len+2, &pos);
	if(status != LDNS_STATUS_OK) {
		free(rd);
		ldns_rr_free(rr);
		printf("error_printing_data");
		return;
	}
	for(i=0; i<ldns_rr_rd_count(rr); i++) {
		printf(" ");
		ldns_rdf_print(stdout, ldns_rr_rdf(rr, i));
	}
	ldns_rr_free(rr);
	free(rd);
}
Exemple #5
0
void *
sign (void *arg)
{
    hsm_ctx_t *ctx = NULL;
    hsm_key_t *key = NULL;

    size_t i;
    unsigned int iterations = 0;

    ldns_rr_list *rrset;
    ldns_rr *rr, *sig, *dnskey_rr;
    ldns_status status;
    hsm_sign_params_t *sign_params;

    sign_arg_t *sign_arg = arg;

    ctx = sign_arg->ctx;
    key = sign_arg->key;
    iterations = sign_arg->iterations;

    fprintf(stderr, "Signer thread #%d started...\n", sign_arg->id);

    /* Prepare dummy RRset for signing */
    rrset = ldns_rr_list_new();
    status = ldns_rr_new_frm_str(&rr, "regress.opendnssec.se. IN A 123.123.123.123", 0, NULL, NULL);
    if (status == LDNS_STATUS_OK) ldns_rr_list_push_rr(rrset, rr);
    status = ldns_rr_new_frm_str(&rr, "regress.opendnssec.se. IN A 124.124.124.124", 0, NULL, NULL);
    if (status == LDNS_STATUS_OK) ldns_rr_list_push_rr(rrset, rr);
    sign_params = hsm_sign_params_new();
    sign_params->algorithm = algorithm;
    sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "opendnssec.se.");
    dnskey_rr = hsm_get_dnskey(ctx, key, sign_params);
    sign_params->keytag = ldns_calc_keytag(dnskey_rr);

    /* Do some signing */
    for (i=0; i<iterations; i++) {
        sig = hsm_sign_rrset(ctx, rrset, key, sign_params);
        if (! sig) {
            fprintf(stderr,
                    "hsm_sign_rrset() returned error: %s in %s\n",
                    ctx->error_message,
                    ctx->error_action
            );
            break;
        }
        ldns_rr_free(sig);
    }

    /* Clean up */
    ldns_rr_list_deep_free(rrset);
    hsm_sign_params_free(sign_params);
    ldns_rr_free(dnskey_rr);
    hsm_destroy_context(ctx);

    fprintf(stderr, "Signer thread #%d done.\n", sign_arg->id);

    pthread_exit(NULL);
}
/**
 * Read the next RR from the backup file.
 *
 */
static ldns_rr*
backup_read_rr(FILE* in, zone_type* zone, char* line, ldns_rdf** orig,
               ldns_rdf** prev, ldns_status* status, unsigned int* l)
{
    ldns_rr* rr = NULL;
    int len = 0;
backup_read_line:
    len = adutil_readline_frm_file(in, line, l, 1);
    if (len >= 0) {
        switch (line[0]) {
        case ';':
            /* done */
            *status = LDNS_STATUS_OK;
            return NULL;
            break;
        case '\n':
        case '\0':
            goto backup_read_line; /* perhaps next line is rr */
            break;
        /* let's hope its a RR */
        default:
            *status = ldns_rr_new_frm_str(&rr, line, zone->default_ttl,
                                          *orig, prev);
            if (*status == LDNS_STATUS_OK) {
                return rr;
            } else if (*status == LDNS_STATUS_SYNTAX_EMPTY) {
                if (rr) {
                    ldns_rr_free(rr);
                    rr = NULL;
                }
                *status = LDNS_STATUS_OK;
                goto backup_read_line; /* perhaps next line is rr */
                break;
            } else {
                ods_log_error("[%s] error parsing RR #%i (%s): %s",
                              backup_str, l&&*l?*l:0,
                              ldns_get_errorstr_by_id(*status), line);
                if (rr) {
                    ldns_rr_free(rr);
                    rr = NULL;
                }
                return NULL;
            }
            break;
        }
    }
    /* -1, EOF */
    *status = LDNS_STATUS_OK;
    return NULL;
}
Exemple #7
0
void
ldns_zone_deep_free(ldns_zone *zone) 
{
	ldns_rr_free(zone->_soa);
	ldns_rr_list_deep_free(zone->_rrs);
	LDNS_FREE(zone);
}
Exemple #8
0
/**
 * Lookup SOA RR.
 *
 */
ldns_rr*
adutil_lookup_soa_rr(FILE* fd)
{
    ldns_rr *cur_rr = NULL;
    char line[SE_ADFILE_MAXLINE];
    ldns_status status = LDNS_STATUS_OK;
    int line_len = 0;
    unsigned int l = 0;

    while (line_len >= 0) {
        line_len = adutil_readline_frm_file(fd, (char*) line, &l, 0);
        adutil_rtrim_line(line, &line_len);

        if (line_len > 0) {
            if (line[0] != ';') {
                status = ldns_rr_new_frm_str(&cur_rr, line, 0, NULL, NULL);
                if (status == LDNS_STATUS_OK) {
                    if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SOA) {
                        return cur_rr;
                    } else {
                        ldns_rr_free(cur_rr);
                        cur_rr = NULL;
                    }
                }
            }
        }
    }
    return NULL;
}
Exemple #9
0
INLINE void
ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
                               int deep)
{
	if (name) {
		if (name->name_alloced) {
			ldns_rdf_deep_free(name->name);
		}
		if (name->rrsets) {
			ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
		}
		if (name->nsec && deep) {
			ldns_rr_free(name->nsec);
		}
		if (name->nsec_signatures) {
			ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
		}
		if (name->hashed_name) {
			if (deep) {
				ldns_rdf_deep_free(name->hashed_name);
			}
		}
		LDNS_FREE(name);
	}
}
/**
 * Publish the NSEC3 parameters as indicated by the signer configuration.
 *
 */
ods_status
zone_publish_nsec3param(zone_type* zone)
{
    rrset_type* rrset = NULL;
    rr_type* n3prr = NULL;
    ldns_rr* rr = NULL;
    ods_status status = ODS_STATUS_OK;

    if (!zone || !zone->name || !zone->db || !zone->signconf) {
        return ODS_STATUS_ASSERT_ERR;
    }
    if (!zone->signconf->nsec3params) {
        /* NSEC */
        ods_log_assert(zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC);
        return ODS_STATUS_OK;
    }

    if (!zone->signconf->nsec3params->rr) {
        rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS);
        if (!rr) {
            ods_log_error("[%s] unable to publish nsec3params for zone %s: "
                "error creating rr (%s)", zone_str, zone->name,
                ods_status2str(status));
            return ODS_STATUS_MALLOC_ERR;
        }
        ldns_rr_set_class(rr, zone->klass);
        ldns_rr_set_ttl(rr, 0);
        ldns_rr_set_owner(rr, ldns_rdf_clone(zone->apex));
        ldns_nsec3_add_param_rdfs(rr,
            zone->signconf->nsec3params->algorithm, 0,
            zone->signconf->nsec3params->iterations,
            zone->signconf->nsec3params->salt_len,
            zone->signconf->nsec3params->salt_data);
        /**
         * Always set bit 7 of the flags to zero,
         * according to rfc5155 section 11
         */
        ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(rr, 1)), 7, 0);
        zone->signconf->nsec3params->rr = rr;
    }
    ods_log_assert(zone->signconf->nsec3params->rr);
    status = zone_add_rr(zone, zone->signconf->nsec3params->rr, 0);
    if (status == ODS_STATUS_UNCHANGED) {
        /* rr already exists, adjust pointer */
        rrset = zone_lookup_rrset(zone, zone->apex, LDNS_RR_TYPE_NSEC3PARAMS);
        ods_log_assert(rrset);
        n3prr = rrset_lookup_rr(rrset, zone->signconf->nsec3params->rr);
        ods_log_assert(n3prr);
        if (n3prr->rr != zone->signconf->nsec3params->rr) {
            ldns_rr_free(zone->signconf->nsec3params->rr);
        }
        zone->signconf->nsec3params->rr = n3prr->rr;
        status = ODS_STATUS_OK;
    } else if (status != ODS_STATUS_OK) {
        ods_log_error("[%s] unable to publish nsec3params for zone %s: "
            "error adding nsec3params (%s)", zone_str,
            zone->name, ods_status2str(status));
    }
    return status;
}
Exemple #11
0
static int
l_rr_free(lua_State *L)
{
	ldns_rr *tofree = (ldns_rr*)lua_touserdata(L, 1); /* pop from the stack */
	if (!tofree) {
		return 0;
	}
	ldns_rr_free(tofree);
	return 0;
}
/**
 * Update current SOA.
 *
 */
static void
notify_update_soa(notify_type* notify, ldns_rr* soa)
{
    if (!notify) {
        return;
    }
    if (notify->soa) {
        ldns_rr_free(notify->soa);
    }
    notify->soa = soa;
    return;
}
Exemple #13
0
struct trust_anchor*
anchor_store_str(struct val_anchors* anchors, ldns_buffer* buffer,
	const char* str)
{
	struct trust_anchor* ta;
	ldns_rr* rr = NULL;
	ldns_status status = ldns_rr_new_frm_str(&rr, str, 0, NULL, NULL);
	if(status != LDNS_STATUS_OK) {
		log_err("error parsing trust anchor: %s", 
			ldns_get_errorstr_by_id(status));
		ldns_rr_free(rr);
		return NULL;
	}
	if(!(ta=anchor_store_new_rr(anchors, buffer, rr))) {
		log_err("out of memory");
		ldns_rr_free(rr);
		return NULL;
	}
	ldns_rr_free(rr);
	return ta;
}
Exemple #14
0
INLINE void
ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
{
	ldns_dnssec_rrs *next;
	while (rrs) {
		next = rrs->next;
		if (deep) {
			ldns_rr_free(rrs->rr);
		}
		LDNS_FREE(rrs);
		rrs = next;
	}
}
Exemple #15
0
ldns_status
zonefile_read(struct zonefile *z, ldns_rr **out)
{
	ldns_rr *rr;
	ldns_status status = LDNS_STATUS_OK;

	if (!z->valid)
		return (LDNS_STATUS_ERR);

	if (z->count == 1 && z->rr_soa != NULL) {
		*out = z->rr_soa;
		z->rr_soa = NULL;
		return (LDNS_STATUS_OK);
	}
	for (;;) {
		if (feof(z->fp)) {
			*out = NULL;
			if (z->is_pipe)
				pclose(z->fp);
			else
				fclose(z->fp);
			z->fp = NULL;
			return (LDNS_STATUS_OK);
		}
		status = ldns_rr_new_frm_fp_l(&rr, z->fp, &z->ttl, &z->origin, &z->prev, NULL);
		switch (status) {
		case LDNS_STATUS_OK:
			if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
				ldns_rr_free(rr);
                		rr = 0;
				z->valid = false;
				status = LDNS_STATUS_OK;
				goto out;
			}
			z->count++;
			goto out;
		case LDNS_STATUS_SYNTAX_EMPTY:
		case LDNS_STATUS_SYNTAX_TTL:
		case LDNS_STATUS_SYNTAX_ORIGIN:
			status = LDNS_STATUS_OK;
			break;
		default:
			goto out;
		}
	}
out:
	if (status != LDNS_STATUS_OK)
		return (status);
	*out = rr;
	return (status);
}
Exemple #16
0
static int
hsm_test_sign (hsm_ctx_t *ctx, hsm_key_t *key, ldns_algorithm alg)
{
    int result;
    ldns_rr_list *rrset;
    ldns_rr *rr, *sig, *dnskey_rr;
    ldns_status status;
    hsm_sign_params_t *sign_params;

    rrset = ldns_rr_list_new();

    status = ldns_rr_new_frm_str(&rr, "example.com. IN A 192.168.0.1", 0, NULL, NULL);
    if (status == LDNS_STATUS_OK) ldns_rr_list_push_rr(rrset, rr);

    status = ldns_rr_new_frm_str(&rr, "example.com. IN A 192.168.0.2", 0, NULL, NULL);
    if (status == LDNS_STATUS_OK) ldns_rr_list_push_rr(rrset, rr);

    sign_params = hsm_sign_params_new();
    sign_params->algorithm = alg;
    sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "example.com.");
    dnskey_rr = hsm_get_dnskey(ctx, key, sign_params);
    sign_params->keytag = ldns_calc_keytag(dnskey_rr);

    sig = hsm_sign_rrset(ctx, rrset, key, sign_params);
    if (sig) {
        result = 0;
        ldns_rr_free(sig);
    } else {
        result = 1;
    }

    ldns_rr_list_deep_free(rrset);
    hsm_sign_params_free(sign_params);
    ldns_rr_free(dnskey_rr);

    return result;
}
Exemple #17
0
/** read qinfo from next three words */
static char*
load_qinfo(char* str, struct query_info* qinfo, ldns_buffer* buf, 
	struct regional* region)
{
	/* s is part of the buf */
	char* s = str;
	ldns_rr* rr;
	ldns_status status;

	/* skip three words */
	s = strchr(str, ' ');
	if(s) s = strchr(s+1, ' ');
	if(s) s = strchr(s+1, ' ');
	if(!s) {
		log_warn("error line too short, %s", str);
		return NULL;
	}
	s[0] = 0;
	s++;

	/* parse them */
	status = ldns_rr_new_question_frm_str(&rr, str, NULL, NULL);
	if(status != LDNS_STATUS_OK) {
		log_warn("error cannot parse: %s %s",
			ldns_get_errorstr_by_id(status), str);
		return NULL;
	}
	qinfo->qtype = ldns_rr_get_type(rr);
	qinfo->qclass = ldns_rr_get_class(rr);
	ldns_buffer_clear(buf);
	status = ldns_dname2buffer_wire(buf, ldns_rr_owner(rr));
	ldns_rr_free(rr);
	if(status != LDNS_STATUS_OK) {
		log_warn("error cannot dname2wire: %s", 
			ldns_get_errorstr_by_id(status));
		return NULL;
	}
	ldns_buffer_flip(buf);
	qinfo->qname_len = ldns_buffer_limit(buf);
	qinfo->qname = (uint8_t*)regional_alloc_init(region, 
		ldns_buffer_begin(buf), ldns_buffer_limit(buf));
	if(!qinfo->qname) {
		log_warn("error out of memory");
		return NULL;
	}

	return s;
}
Exemple #18
0
/* key_list must be initialized with ldns_rr_list_new() */
ldns_status
read_key_file(const char *filename, ldns_rr_list *key_list)
{       
        int line_len = 0;
        int line_nr = 0;
        int key_count = 0;
        char line[LDNS_MAX_PACKETLEN];
        ldns_status status;
        FILE *input_file;
        ldns_rr *rr;

        input_file = fopen(filename, "r");
        if (!input_file) {
                fprintf(stderr, "Error opening %s: %s\n",
                        filename, strerror(errno));
                return LDNS_STATUS_ERR;
        }
        while (line_len >= 0) {
                line_len = read_line(input_file, line);
                line_nr++;
                if (line_len > 0 && line[0] != ';') {
                        status = ldns_rr_new_frm_str(&rr, line, 0, NULL, NULL);
                        if (status != LDNS_STATUS_OK) {
                                fprintf(stderr,
                                                "Error parsing DNSKEY RR in line %d: %s\n",
                                                line_nr,
                                                ldns_get_errorstr_by_id(status));
                        } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY ||
                                           ldns_rr_get_type(rr) == LDNS_RR_TYPE_DS) {
                                ldns_rr_list_push_rr(key_list, rr);
                                key_count++;
                        } else {
                                ldns_rr_free(rr);
                        }
                }
        }
//        printf(";; Number of trusted keys: %d\n", key_count);
        if (key_count > 0) {
                return LDNS_STATUS_OK;
        } else {
                /*fprintf(stderr, "No keys read\n");*/
                return LDNS_STATUS_ERR;
        }
}
/**
 * Cleanup notify structure.
 *
 */
void
notify_cleanup(notify_type* notify)
{
    allocator_type* allocator = NULL;
    if (!notify) {
        return;
    }
    allocator = notify->allocator;
    if (notify->handler.fd != -1) {
        close(notify->handler.fd);
        notify->handler.fd = -1;
    }
    if (notify->soa) {
        ldns_rr_free(notify->soa);
    }
    tsig_rr_cleanup(notify->tsig_rr);
    allocator_deallocate(allocator, (void*) notify);
    allocator_cleanup(allocator);
    return;
}
Exemple #20
0
/** dump one rrset zonefile line */
static int
dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k,
        struct packed_rrset_data* d, uint32_t now, size_t i, uint16_t type)
{
	char* s;
	ldns_rr* rr = to_rr(k, d, now, i, type);
	if(!rr) {
		return ssl_printf(ssl, "BADRR\n");
	}
	s = ldns_rr2str(rr);
	ldns_rr_free(rr);
	if(!s) {
		return ssl_printf(ssl, "BADRR\n");
	}
	if(!ssl_printf(ssl, "%s", s)) {
		free(s);
		return 0;
	}
	free(s);
	return 1;
}
Exemple #21
0
void
zonefile_destroy(struct zonefile **z)
{
	if (*z) {
		if ((*z)->fp) {
			if ((*z)->is_pipe)
				pclose((*z)->fp);
			else
				fclose((*z)->fp);
		}
		if ((*z)->origin)
			ldns_rdf_deep_free((*z)->origin);
		if ((*z)->prev)
			ldns_rdf_deep_free((*z)->prev);
		if ((*z)->domain)
			ldns_rdf_deep_free((*z)->domain);
		if ((*z)->rr_soa)
			ldns_rr_free((*z)->rr_soa);
		free(*z);
		*z = NULL;
	}
}
Exemple #22
0
static ldns_status
read_soa(struct zonefile *z)
{
	ldns_rr *rr;
	ldns_status status;

	for (;;) {
		status = ldns_rr_new_frm_fp_l(&rr, z->fp, &z->ttl, &z->origin, &z->prev, NULL);
		switch (status) {
		case LDNS_STATUS_OK:
			goto out;
		case LDNS_STATUS_SYNTAX_EMPTY:
		case LDNS_STATUS_SYNTAX_TTL:
		case LDNS_STATUS_SYNTAX_ORIGIN:
			status = LDNS_STATUS_OK;
			break;
		default:
			goto out;
		}
	}
out:
	if (status != LDNS_STATUS_OK) {
		z->valid = false;
		return (LDNS_STATUS_ERR);
	}

	if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_SOA) {
		ldns_rr_free(rr);
		z->valid = false;
		return (LDNS_STATUS_ERR);
	}

	z->count = 1;
	z->domain = ldns_rdf_clone(ldns_rr_owner(rr));
	z->origin = ldns_rdf_clone(ldns_rr_owner(rr));
	z->rr_soa = rr;
	return (LDNS_STATUS_OK);
}
int
main(int argc, char **argv)
{
	char *filename;
	FILE *fp;
	ldns_zone *z;
	int line_nr = 0;
	int c;
	bool canonicalize = false;
	bool sort = false;
	bool strip = false;
	bool only_dnssec = false;
	bool print_soa = true;
	ldns_status s;
	size_t i;
	ldns_rr_list *stripped_list;
	ldns_rr *cur_rr;
	ldns_rr_type cur_rr_type;

        while ((c = getopt(argc, argv, "cdhnsvz")) != -1) {
                switch(c) {
                	case 'c':
                		canonicalize = true;
                		break;
                	case 'd':
                		only_dnssec = true;
                		if (strip) {
                			fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n");
				}
				break;
			case 'h':
				printf("Usage: %s [-c] [-v] [-z] <zonefile>\n", argv[0]);
				printf("\tReads the zonefile and prints it.\n");
				printf("\tThe RR count of the zone is printed to stderr.\n");
				printf("\t-c canonicalize all rrs in the zone.\n");
				printf("\t-d only show DNSSEC data from the zone\n");
				printf("\t-h show this text\n");
				printf("\t-n do not print the SOA record\n");
				printf("\t-s strip DNSSEC data from the zone\n");
				printf("\t-v shows the version and exits\n");
				printf("\t-z sort the zone (implies -c).\n");
				printf("\nif no file is given standard input is read\n");
				exit(EXIT_SUCCESS);
				break;
			case 'n':
				print_soa = false;
				break;
                        case 's':
                        	strip = true;
                		if (only_dnssec) {
                			fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n");
				}
                        	break;
			case 'v':
				printf("read zone version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
				exit(EXIT_SUCCESS);
				break;
                        case 'z':
                		canonicalize = true;
                                sort = true;
                                break;
		}
	}

	argc -= optind;
	argv += optind;

	if (argc == 0) {
		fp = stdin;
	} else {
		filename = argv[0];

		fp = fopen(filename, "r");
		if (!fp) {
			fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
			exit(EXIT_FAILURE);
		}
	}
	
	s = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, LDNS_RR_CLASS_IN, &line_nr);

	if (strip) {
		stripped_list = ldns_rr_list_new();
		while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) {
			cur_rr_type = ldns_rr_get_type(cur_rr);
			if (cur_rr_type == LDNS_RR_TYPE_RRSIG ||
			    cur_rr_type == LDNS_RR_TYPE_NSEC ||
			    cur_rr_type == LDNS_RR_TYPE_NSEC3 ||
			    cur_rr_type == LDNS_RR_TYPE_NSEC3PARAMS
			   ) {
				ldns_rr_free(cur_rr);
			} else {
				ldns_rr_list_push_rr(stripped_list, cur_rr);
			}
		}
		ldns_rr_list_free(ldns_zone_rrs(z));
		ldns_zone_set_rrs(z, stripped_list);
	}
	if (only_dnssec) {
		stripped_list = ldns_rr_list_new();
		while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) {
			cur_rr_type = ldns_rr_get_type(cur_rr);
			if (cur_rr_type == LDNS_RR_TYPE_RRSIG ||
			    cur_rr_type == LDNS_RR_TYPE_NSEC ||
			    cur_rr_type == LDNS_RR_TYPE_NSEC3 ||
			    cur_rr_type == LDNS_RR_TYPE_NSEC3PARAMS
			   ) {
				ldns_rr_list_push_rr(stripped_list, cur_rr);
			} else {
				ldns_rr_free(cur_rr);
			}
		}
		ldns_rr_list_free(ldns_zone_rrs(z));
		ldns_zone_set_rrs(z, stripped_list);
	}

	if (s == LDNS_STATUS_OK) {
		if (canonicalize) {
			ldns_rr2canonical(ldns_zone_soa(z));
			for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) {
				ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z), i));
			}
		}
		if (sort) {
			ldns_zone_sort(z);
		}

		if (print_soa && ldns_zone_soa(z)) {
			ldns_rr_print(stdout, ldns_zone_soa(z));
		}
		ldns_rr_list_print(stdout, ldns_zone_rrs(z));

		ldns_zone_deep_free(z);
	} else {
		fprintf(stderr, "%s at %d\n", 
				ldns_get_errorstr_by_id(s),
				line_nr);
                exit(EXIT_FAILURE);
	}
	fclose(fp);

        exit(EXIT_SUCCESS);
}
Exemple #24
0
/**
 * Read a file with trust anchors
 * @param anchors: anchor storage.
 * @param buffer: parsing buffer.
 * @param fname: string.
 * @param onlyone: only one trust anchor allowed in file.
 * @return NULL on error. Else last trust-anchor point.
 */
static struct trust_anchor*
anchor_read_file(struct val_anchors* anchors, ldns_buffer* buffer,
	const char* fname, int onlyone)
{
	struct trust_anchor* ta = NULL, *tanew;
	uint32_t default_ttl = 3600;
	ldns_rdf* origin = NULL, *prev = NULL;
	int line_nr = 1;
	ldns_status status;
	ldns_rr* rr;
	int ok = 1;
	FILE* in = fopen(fname, "r");
	if(!in) {
		log_err("error opening file %s: %s", fname, strerror(errno));
		return 0;
	}
	while(!feof(in)) {
		rr = NULL;
		status = ldns_rr_new_frm_fp_l(&rr, in, &default_ttl, &origin,
			&prev, &line_nr);
		if(status == LDNS_STATUS_SYNTAX_EMPTY /* empty line */
			|| status == LDNS_STATUS_SYNTAX_TTL /* $TTL */
			|| status == LDNS_STATUS_SYNTAX_ORIGIN /* $ORIGIN */)
			continue;
		if(status != LDNS_STATUS_OK) {
			log_err("parse error in %s:%d : %s", fname, line_nr,
				ldns_get_errorstr_by_id(status));
			ldns_rr_free(rr);
			ok = 0;
			break;
		}
		if(ldns_rr_get_type(rr) != LDNS_RR_TYPE_DS && 
			ldns_rr_get_type(rr) != LDNS_RR_TYPE_DNSKEY) {
			ldns_rr_free(rr);
			continue;
		}
		if(!(tanew=anchor_store_new_rr(anchors, buffer, rr))) {
			log_err("error at %s line %d", fname, line_nr);
			ldns_rr_free(rr);
			ok = 0;
			break;
		}
		if(onlyone && ta && ta != tanew) {
			log_err("error at %s line %d: no multiple anchor "
				"domains allowed (you can have multiple "
				"keys, but they must have the same name).", 
				fname, line_nr);
			ldns_rr_free(rr);
			ok = 0;
			break;
		}
		ta = tanew;
		ldns_rr_free(rr);
	}
	ldns_rdf_deep_free(origin);
	ldns_rdf_deep_free(prev);
	fclose(in);
	if(!ok) return NULL;
	/* empty file is OK when multiple anchors are allowed */
	if(!onlyone && !ta) return (struct trust_anchor*)1;
	return ta;
}
Exemple #25
0
int
main(int argc, char **argv)
{
	char *filename;
	FILE *fp;
	ldns_zone *z;
	int line_nr = 0;
	int c;
	bool canonicalize = false;
	bool sort = false;
	bool strip = false;
	bool only_dnssec = false;
	bool print_soa = true;
	ldns_status s;
	size_t i;
	ldns_rr_list *stripped_list;
	ldns_rr *cur_rr;
	ldns_rr_type cur_rr_type;
	ldns_output_format_storage fmt_storage;
	ldns_output_format* fmt = ldns_output_format_init(&fmt_storage);

	ldns_soa_serial_increment_func_t soa_serial_increment_func = NULL;
	int soa_serial_increment_func_data = 0;

        while ((c = getopt(argc, argv, "0bcdhnpsu:U:vzS:")) != -1) {
                switch(c) {
			case 'b':
				fmt->flags |= 
					( LDNS_COMMENT_BUBBLEBABBLE |
					  LDNS_COMMENT_FLAGS        );
				break;
			case '0':
				fmt->flags |= LDNS_FMT_ZEROIZE_RRSIGS;
				break;
                	case 'c':
                		canonicalize = true;
                		break;
                	case 'd':
                		only_dnssec = true;
                		if (strip) {
                			fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n");
				}
				break;
			case 'h':
				print_usage("ldns-read-zone");
				break;
			case 'n':
				print_soa = false;
				break;
			case 'p':
				fmt->flags |= LDNS_FMT_PAD_SOA_SERIAL;
				break;
                        case 's':
                        	strip = true;
                		if (only_dnssec) {
                			fprintf(stderr, "Warning: stripping both DNSSEC and non-DNSSEC records. Output will be sparse.\n");
				}
                        	break;
			case 'u':
				s = ldns_output_format_set_type(fmt,
					ldns_get_rr_type_by_name(optarg));
				if (s != LDNS_STATUS_OK) {
					fprintf( stderr
					       , "Cannot set rr type %s "
					         "in output format to "
						 "print as unknown type: %s\n"
					       , ldns_rr_descript(
					       ldns_get_rr_type_by_name(optarg)
						       )->_name
					       , ldns_get_errorstr_by_id(s)
					       );
					exit(EXIT_FAILURE);
				}
				break;
			case 'U':
				s = ldns_output_format_clear_type(fmt,
					ldns_get_rr_type_by_name(optarg));
				if (s != LDNS_STATUS_OK) {
					fprintf( stderr
					       , "Cannot set rr type %s "
					         "in output format to not "
						 "print as unknown type: %s\n"
					       , ldns_rr_descript(
					       ldns_get_rr_type_by_name(optarg)
						       )->_name
					       , ldns_get_errorstr_by_id(s)
					       );
					exit(EXIT_FAILURE);
				}
				break;
			case 'v':
				printf("read zone version %s (ldns version %s)\n", LDNS_VERSION, ldns_version());
				exit(EXIT_SUCCESS);
				break;
                        case 'z':
                		canonicalize = true;
                                sort = true;
                                break;
			case 'S':
				strip = true;
				if (*optarg == '+' || *optarg == '-') {
					soa_serial_increment_func_data =
						atoi(optarg);
					soa_serial_increment_func =
						ldns_soa_serial_increment_by;
				} else if (! strtok(optarg, "0123456789")) {
					soa_serial_increment_func_data =
						atoi(optarg);
					soa_serial_increment_func =
						ldns_soa_serial_identity;
				} else if (!strcasecmp(optarg, "YYYYMMDDxx")){
					soa_serial_increment_func =
						ldns_soa_serial_datecounter;
				} else if (!strcasecmp(optarg, "unixtime")){
					soa_serial_increment_func =
						ldns_soa_serial_unixtime;
				} else {
					fprintf(stderr, "-S expects a number "
						"optionally preceded by a "
						"+ or - sign to indicate an "
						"offset, or the text YYYYMM"
						"DDxx or unixtime\n");
					exit(EXIT_FAILURE);
				}
				break;
		}
	}

	argc -= optind;
	argv += optind;

	if (argc == 0) {
		fp = stdin;
	} else {
		filename = argv[0];

		fp = fopen(filename, "r");
		if (!fp) {
			fprintf(stderr, "Unable to open %s: %s\n", filename, strerror(errno));
			exit(EXIT_FAILURE);
		}
	}
	
	s = ldns_zone_new_frm_fp_l(&z, fp, NULL, 0, LDNS_RR_CLASS_IN, &line_nr);

	fclose(fp);
	if (s != LDNS_STATUS_OK) {
		fprintf(stderr, "%s at %d\n", 
				ldns_get_errorstr_by_id(s),
				line_nr);
                exit(EXIT_FAILURE);
	}


	if (strip) {
		stripped_list = ldns_rr_list_new();
		while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) {
			cur_rr_type = ldns_rr_get_type(cur_rr);
			if (cur_rr_type == LDNS_RR_TYPE_RRSIG ||
			    cur_rr_type == LDNS_RR_TYPE_NSEC ||
			    cur_rr_type == LDNS_RR_TYPE_NSEC3 ||
			    cur_rr_type == LDNS_RR_TYPE_NSEC3PARAM
			   ) {
				ldns_rr_free(cur_rr);
			} else {
				ldns_rr_list_push_rr(stripped_list, cur_rr);
			}
		}
		ldns_rr_list_free(ldns_zone_rrs(z));
		ldns_zone_set_rrs(z, stripped_list);
	}
	if (only_dnssec) {
		stripped_list = ldns_rr_list_new();
		while ((cur_rr = ldns_rr_list_pop_rr(ldns_zone_rrs(z)))) {
			cur_rr_type = ldns_rr_get_type(cur_rr);
			if (cur_rr_type == LDNS_RR_TYPE_RRSIG ||
			    cur_rr_type == LDNS_RR_TYPE_NSEC ||
			    cur_rr_type == LDNS_RR_TYPE_NSEC3 ||
			    cur_rr_type == LDNS_RR_TYPE_NSEC3PARAM
			   ) {
				ldns_rr_list_push_rr(stripped_list, cur_rr);
			} else {
				ldns_rr_free(cur_rr);
			}
		}
		ldns_rr_list_free(ldns_zone_rrs(z));
		ldns_zone_set_rrs(z, stripped_list);
	}

	if (canonicalize) {
		ldns_rr2canonical(ldns_zone_soa(z));
		for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(z)); i++) {
			ldns_rr2canonical(ldns_rr_list_rr(ldns_zone_rrs(z), i));
		}
	}
	if (sort) {
		ldns_zone_sort(z);
	}

	if (print_soa && ldns_zone_soa(z)) {
		if (soa_serial_increment_func) {
			ldns_rr_soa_increment_func_int(
					ldns_zone_soa(z)
				, soa_serial_increment_func
				, soa_serial_increment_func_data
				);
		}
		ldns_rr_print_fmt(stdout, fmt, ldns_zone_soa(z));
	}
	ldns_rr_list_print_fmt(stdout, fmt, ldns_zone_rrs(z));

	ldns_zone_deep_free(z);

        exit(EXIT_SUCCESS);
}
/**
 * Read namedb from backup file.
 *
 */
ods_status
backup_read_namedb(FILE* in, void* zone)
{
    zone_type* z = (zone_type*) zone;
    denial_type* denial = NULL;
    rrset_type* rrset = NULL;
    ods_status result = ODS_STATUS_OK;
    ldns_rr_type type_covered;
    ldns_rr* rr = NULL;
    ldns_rdf* prev = NULL;
    ldns_rdf* orig = NULL;
    ldns_rdf* dname = NULL;
    ldns_status status = LDNS_STATUS_OK;
    char line[SE_ADFILE_MAXLINE];
    char* str = NULL;
    char* locator = NULL;
    uint32_t flags = 0;
    unsigned int l = 0;

    ods_log_assert(in);
    ods_log_assert(z);

    /* $ORIGIN <zone name> */
    dname = adapi_get_origin(z);
    if (!dname) {
        ods_log_error("[%s] error getting default value for $ORIGIN",
                      backup_str);
        return ODS_STATUS_ERR;
    }
    orig = ldns_rdf_clone(dname);
    if (!orig) {
        ods_log_error("[%s] error setting default value for $ORIGIN",
                      backup_str);
        return ODS_STATUS_ERR;
    }
    /* read RRs */
    ods_log_debug("[%s] read RRs %s", backup_str, z->name);
    while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
            != NULL) {
        /* check status */
        if (status != LDNS_STATUS_OK) {
            ods_log_error("[%s] error reading RR #%i (%s): %s",
                          backup_str, l, ldns_get_errorstr_by_id(status), line);
            result = ODS_STATUS_ERR;
            goto backup_namedb_done;
        }
        /* add to the database */
        result = adapi_add_rr(z, rr, 1);
        if (result == ODS_STATUS_UNCHANGED) {
            ods_log_debug("[%s] skipping RR #%i (duplicate): %s",
                          backup_str, l, line);
            ldns_rr_free(rr);
            rr = NULL;
            result = ODS_STATUS_OK;
            continue;
        } else if (result != ODS_STATUS_OK) {
            ods_log_error("[%s] error adding RR #%i: %s",
                          backup_str, l, line);
            ldns_rr_free(rr);
            rr = NULL;
            goto backup_namedb_done;
        }
    }
    if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
        ods_log_error("[%s] error reading RR #%i (%s): %s",
                      backup_str, l, ldns_get_errorstr_by_id(status), line);
        result = ODS_STATUS_ERR;
        goto backup_namedb_done;
    }
    namedb_diff(z->db, 0, 0);

    /* read NSEC(3)s */
    ods_log_debug("[%s] read NSEC(3)s %s", backup_str, z->name);
    l = 0;
    while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
            != NULL) {
        /* check status */
        if (status != LDNS_STATUS_OK) {
            ods_log_error("[%s] error reading NSEC(3) #%i (%s): %s",
                          backup_str, l, ldns_get_errorstr_by_id(status), line);
            result = ODS_STATUS_ERR;
            goto backup_namedb_done;
        }
        if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_NSEC &&
                ldns_rr_get_type(rr) != LDNS_RR_TYPE_NSEC3) {
            ods_log_error("[%s] error NSEC(3) #%i is not NSEC(3): %s",
                          backup_str, l, line);
            ldns_rr_free(rr);
            rr = NULL;
            result = ODS_STATUS_ERR;
            goto backup_namedb_done;
        }
        /* add to the denial chain */
        denial = namedb_lookup_denial(z->db, ldns_rr_owner(rr));
        if (!denial) {
            ods_log_error("[%s] error adding NSEC(3) #%i: %s",
                          backup_str, l, line);
            ldns_rr_free(rr);
            rr = NULL;
            result = ODS_STATUS_ERR;
            goto backup_namedb_done;
        }
        denial_add_rr(denial, rr);
    }
    if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
        ods_log_error("[%s] error reading NSEC(3) #%i (%s): %s",
                      backup_str, l, ldns_get_errorstr_by_id(status), line);
        result = ODS_STATUS_ERR;
        goto backup_namedb_done;
    }

    /* read RRSIGs */
    ods_log_debug("[%s] read RRSIGs %s", backup_str, z->name);
    l = 0;
    while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
            != NULL) {
        /* check status */
        if (status != LDNS_STATUS_OK) {
            ods_log_error("[%s] error reading RRSIG #%i (%s): %s",
                          backup_str, l, ldns_get_errorstr_by_id(status), line);
            result = ODS_STATUS_ERR;
            goto backup_namedb_done;
        }
        if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) {
            ods_log_error("[%s] error RRSIG #%i is not RRSIG: %s",
                          backup_str, l, line);
            ldns_rr_free(rr);
            rr = NULL;
            result = ODS_STATUS_ERR;
            goto backup_namedb_done;
        }
        /* read locator and flags */
        str = strstr(line, "flags");
        if (str) {
            flags = (uint32_t) atoi(str+6);
        }
        str = strstr(line, "locator");
        if (str) {
            locator = replace_space_with_nul(str+8);
        }
        /* add signatures */
        type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
        if (type_covered == LDNS_RR_TYPE_NSEC ||
                type_covered == LDNS_RR_TYPE_NSEC3) {
            denial = namedb_lookup_denial(z->db, ldns_rr_owner(rr));
            if (!denial) {
                ods_log_error("[%s] error restoring RRSIG #%i (%s): %s",
                              backup_str, l, ldns_get_errorstr_by_id(status), line);
                ldns_rr_free(rr);
                rr = NULL;
                result = ODS_STATUS_ERR;
                goto backup_namedb_done;
            }
            rrset = denial->rrset;
        } else {
            rrset = zone_lookup_rrset(z, ldns_rr_owner(rr), type_covered);
        }
        if (!rrset || !rrset_add_rrsig(rrset, rr, locator, flags)) {
            ods_log_error("[%s] error restoring RRSIG #%i (%s): %s",
                          backup_str, l, ldns_get_errorstr_by_id(status), line);
            ldns_rr_free(rr);
            rr = NULL;
            result = ODS_STATUS_ERR;
            goto backup_namedb_done;
        } else {
            rrset->needs_signing = 0;
        }
    }
    if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
        ods_log_error("[%s] error reading RRSIG #%i (%s): %s",
                      backup_str, l, ldns_get_errorstr_by_id(status), line);
        result = ODS_STATUS_ERR;
    }

backup_namedb_done:
    if (orig) {
        ldns_rdf_deep_free(orig);
        orig = NULL;
    }
    if (prev) {
        ldns_rdf_deep_free(prev);
        prev = NULL;
    }
    return result;
}
Exemple #27
0
/*
 *  Makes an exact copy of the wire, but with the tsig rr removed
 */
static uint8_t *
ldns_tsig_prepare_pkt_wire(uint8_t *wire, size_t wire_len, size_t *result_len)
{
	uint8_t *wire2 = NULL;
	uint16_t qd_count;
	uint16_t an_count;
	uint16_t ns_count;
	uint16_t ar_count;
	ldns_rr *rr;

	size_t pos;
	uint16_t i;

	ldns_status status;

	if(wire_len < LDNS_HEADER_SIZE) {
		return NULL;
	}
	/* fake parse the wire */
	qd_count = LDNS_QDCOUNT(wire);
	an_count = LDNS_ANCOUNT(wire);
	ns_count = LDNS_NSCOUNT(wire);
	ar_count = LDNS_ARCOUNT(wire);

	if (ar_count > 0) {
		ar_count--;
	} else {
		return NULL;
	}

	pos = LDNS_HEADER_SIZE;

	for (i = 0; i < qd_count; i++) {
		status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_QUESTION);
		if (status != LDNS_STATUS_OK) {
			return NULL;
		}
		ldns_rr_free(rr);
	}

	for (i = 0; i < an_count; i++) {
		status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_ANSWER);
		if (status != LDNS_STATUS_OK) {
			return NULL;
		}
		ldns_rr_free(rr);
	}

	for (i = 0; i < ns_count; i++) {
		status = ldns_wire2rr(&rr, wire, wire_len, &pos, LDNS_SECTION_AUTHORITY);
		if (status != LDNS_STATUS_OK) {
			return NULL;
		}
		ldns_rr_free(rr);
	}

	for (i = 0; i < ar_count; i++) {
		status = ldns_wire2rr(&rr, wire, wire_len, &pos,
				LDNS_SECTION_ADDITIONAL);
		if (status != LDNS_STATUS_OK) {
			return NULL;
		}
		ldns_rr_free(rr);
	}

	*result_len = pos;
	wire2 = LDNS_XMALLOC(uint8_t, *result_len);
	if(!wire2) {
		return NULL;
	}
	memcpy(wire2, wire, *result_len);

	ldns_write_uint16(wire2 + LDNS_ARCOUNT_OFF, ar_count);

	return wire2;
}
static uint16_t 
dnskey_from_id(std::string &dnskey,
               const char *id,
               ::ods::keystate::keyrole role,
               const char *zone,
               int algorithm,
               int bDS,
               uint32_t ttl)
{
    hsm_key_t *key;
    hsm_sign_params_t *sign_params;
    ldns_rr *dnskey_rr;
    ldns_algorithm algo = (ldns_algorithm)algorithm;
    
    /* Code to output the DNSKEY record  (stolen from hsmutil) */
    hsm_ctx_t *hsm_ctx = hsm_create_context();
    if (!hsm_ctx) {
        ods_log_error("[%s] Could not connect to HSM", module_str);
        return false;
    }
    key = hsm_find_key_by_id(hsm_ctx, id);
    
    if (!key) {
        // printf("Key %s in DB but not repository\n", id);
        hsm_destroy_context(hsm_ctx);
        return 0;
    }
    
    /*
     * Sign params only need to be kept around 
     * for the hsm_get_dnskey() call.
     */
    sign_params = hsm_sign_params_new();
    sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone);
    sign_params->algorithm = algo;
    sign_params->flags = LDNS_KEY_ZONE_KEY;
    if (role == ::ods::keystate::KSK)
        sign_params->flags += LDNS_KEY_SEP_KEY; /*KSK=>SEP*/
    /* Get the DNSKEY record */
    dnskey_rr = hsm_get_dnskey(hsm_ctx, key, sign_params);
    hsm_sign_params_free(sign_params);
    /* Calculate the keytag for this key, we return it. */
    uint16_t keytag = ldns_calc_keytag(dnskey_rr);
    /* Override the TTL in the dnskey rr */
    if (ttl)
        ldns_rr_set_ttl(dnskey_rr, ttl);
    
    char *rrstr;
    if (!bDS) {
#if 0
        ldns_rr_print(stdout, dnskey_rr);
#endif
        rrstr = ldns_rr2str(dnskey_rr);
        dnskey = rrstr;
        LDNS_FREE(rrstr);
    } else {
    
        switch (algo) {
            case LDNS_RSASHA1: // 5
            {
                /* DS record (SHA1) */
                ldns_rr *ds_sha1_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA1);
#if 0
                ldns_rr_print(stdout, ds_sha1_rr);
#endif
                rrstr = ldns_rr2str(ds_sha1_rr);
                dnskey = rrstr;
                LDNS_FREE(rrstr);

                ldns_rr_free(ds_sha1_rr);
                break;
            }
            case LDNS_RSASHA256: // 8 - RFC 5702
            {
        
                /* DS record (SHA256) */
                ldns_rr *ds_sha256_rr = ldns_key_rr2ds(dnskey_rr, LDNS_SHA256);
#if 0
                ldns_rr_print(stdout, ds_sha256_rr);
#endif
                rrstr = ldns_rr2str(ds_sha256_rr);
                dnskey = rrstr;
                LDNS_FREE(rrstr);

                ldns_rr_free(ds_sha256_rr);
                break;
            }
            default:
                keytag = 0;
        }
    }
    ldns_rr_free(dnskey_rr);
    hsm_key_free(key);
    hsm_destroy_context(hsm_ctx);
    
    return keytag;
}
int
main (int argc, char *argv[])
{
    int result;
    hsm_ctx_t *ctx;
    hsm_key_t **keys;
    hsm_key_t *key = NULL;
    char *id;
    size_t key_count = 0;
    size_t i;
    ldns_rr_list *rrset;
    ldns_rr *rr, *sig, *dnskey_rr;
    ldns_status status;
    hsm_sign_params_t *sign_params;

    int do_generate = 0;
    int do_sign = 0;
    int do_delete = 0;
    int do_random = 0;

    int res;
    uint32_t r32;
    uint64_t r64;

    char *config = NULL;
    const char *repository = "default";

    int ch;

    progname = argv[0];

    while ((ch = getopt(argc, argv, "hgsdrc:")) != -1) {
        switch (ch) {
        case 'c':
            config = strdup(optarg);
            break;
        case 'g':
            do_generate = 1;
            break;
        case 'h':
            usage();
            exit(0);
            break;
        case 's':
            do_sign = 1;
            break;
        case 'd':
            do_delete = 1;
            break;
        case 'r':
            do_random = 1;
            break;
        default:
            usage();
            exit(1);
        }
    }

    if (!config) {
        usage();
        exit(1);
    }

    /*
     * Open HSM library
     */
    fprintf(stdout, "Starting HSM lib test\n");
    result = hsm_open(config, hsm_prompt_pin);
    fprintf(stdout, "hsm_open result: %d\n", result);

    /*
     * Create HSM context
     */
    ctx = hsm_create_context();
    printf("global: ");
    hsm_print_ctx(NULL);
    printf("my: ");
    hsm_print_ctx(ctx);

    /*
     * Generate a new key OR find any key with an ID
     */
    if (do_generate) {
        key = hsm_generate_rsa_key(ctx, repository, 1024);

        if (key) {
            printf("\nCreated key!\n");
            hsm_print_key(key);
            printf("\n");
        } else {
            printf("Error creating key, bad token name?\n");
            hsm_print_error(ctx);
            exit(1);
        }
    } else if (do_sign || do_delete) {
        keys = hsm_list_keys(ctx, &key_count);
        printf("I have found %u keys\n", (unsigned int) key_count);

        /* let's just use the very first key we find and throw away the rest */
        for (i = 0; i < key_count && !key; i++) {
            printf("\nFound key!\n");
            hsm_print_key(keys[i]);

            id = hsm_get_key_id(ctx, keys[i]);

            if (id) {
                printf("Using key ID: %s\n", id);
                if (key) hsm_key_free(key);
                key = hsm_find_key_by_id(ctx, id);
                printf("ptr: 0x%p\n", (void *) key);
                free(id);
            } else {
                printf("Got no key ID (broken key?), skipped...\n");
            }

            hsm_key_free(keys[i]);
        }
        free(keys);

        if (!key) {
            printf("Failed to find useful key\n");
            exit(1);
        }
    }

    /*
     * Do some signing
     */
    if (do_sign) {
        printf("\nSigning with:\n");
        hsm_print_key(key);
        printf("\n");

        rrset = ldns_rr_list_new();

        status = ldns_rr_new_frm_str(&rr, "regress.opendnssec.se. IN A 123.123.123.123", 0, NULL, NULL);
        if (status == LDNS_STATUS_OK) ldns_rr_list_push_rr(rrset, rr);
        status = ldns_rr_new_frm_str(&rr, "regress.opendnssec.se. IN A 124.124.124.124", 0, NULL, NULL);
        if (status == LDNS_STATUS_OK) ldns_rr_list_push_rr(rrset, rr);

        sign_params = hsm_sign_params_new();
        sign_params->algorithm = LDNS_RSASHA1;
        sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "opendnssec.se.");
        dnskey_rr = hsm_get_dnskey(ctx, key, sign_params);
        sign_params->keytag = ldns_calc_keytag(dnskey_rr);

        sig = hsm_sign_rrset(ctx, rrset, key, sign_params);
        if (sig) {
            ldns_rr_list_print(stdout, rrset);
            ldns_rr_print(stdout, sig);
            ldns_rr_print(stdout, dnskey_rr);
            ldns_rr_free(sig);
        } else {
            hsm_print_error(ctx);
            exit(-1);
        }

        /* cleanup */
        ldns_rr_list_deep_free(rrset);
        hsm_sign_params_free(sign_params);
        ldns_rr_free(dnskey_rr);
    }

    /*
     * Delete key
     */
    if (do_delete) {
        printf("\nDelete key:\n");
        hsm_print_key(key);
        /* res = hsm_remove_key(ctx, key); */
        res = hsm_remove_key(ctx, key);
        printf("Deleted key. Result: %d\n", res);
        printf("\n");
    }

    if (key) hsm_key_free(key);

    /*
     * Test random{32,64} functions
     */
    if (do_random) {
        r32 = hsm_random32(ctx);
        printf("random 32: %u\n", r32);
        r64 = hsm_random64(ctx);
        printf("random 64: %llu\n", (long long unsigned int)r64);
    }

    /*
     * Destroy HSM context
     */
    if (ctx) {
        hsm_destroy_context(ctx);
    }

    /*
     * Close HSM library
     */
    result = hsm_close();
    fprintf(stdout, "all done! hsm_close result: %d\n", result);

    if (config) free(config);
    
    return 0;
}
/**
 * Read ixfr journal from file.
 *
 *
 */
ods_status
backup_read_ixfr(FILE* in, void* zone)
{
    zone_type* z = (zone_type*) zone;
    ods_status result = ODS_STATUS_OK;
    ldns_rr* rr = NULL;
    ldns_rdf* prev = NULL;
    ldns_rdf* orig = NULL;
    ldns_rdf* dname = NULL;
    ldns_status status = LDNS_STATUS_OK;
    char line[SE_ADFILE_MAXLINE];
    uint32_t serial = 0;
    unsigned l = 0;
    unsigned first_soa = 1; /* expect soa first */
    unsigned del_mode = 0;

    ods_log_assert(in);
    ods_log_assert(z);

    /* $ORIGIN <zone name> */
    dname = adapi_get_origin(z);
    if (!dname) {
        ods_log_error("[%s] error getting default value for $ORIGIN",
                      backup_str);
        return ODS_STATUS_ERR;
    }
    orig = ldns_rdf_clone(dname);
    if (!orig) {
        ods_log_error("[%s] error setting default value for $ORIGIN",
                      backup_str);
        return ODS_STATUS_ERR;
    }
    /* read RRs */
    while ((rr = backup_read_rr(in, z, line, &orig, &prev, &status, &l))
            != NULL) {
        /* check status */
        if (status != LDNS_STATUS_OK) {
            ods_log_error("[%s] error reading RR #%i (%s): %s",
                          backup_str, l, ldns_get_errorstr_by_id(status), line);
            result = ODS_STATUS_ERR;
            goto backup_ixfr_done;
        }
        if (first_soa == 2) {
            ods_log_error("[%s] bad ixfr journal: trailing RRs after final "
                          "SOA", backup_str);
            ldns_rr_free(rr);
            rr = NULL;
            result = ODS_STATUS_ERR;
            goto backup_ixfr_done;
        }
        if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
            serial = ldns_rdf2native_int32(
                         ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
            if (first_soa) {
                ods_log_debug("[%s] ixfr first SOA: %s", backup_str,
                              ldns_rr2str(rr));
                /* first SOA */
                ldns_rr_free(rr);
                rr = NULL;
                if (z->db->outserial != serial) {
                    ods_log_error("[%s] bad ixfr journal: first SOA wrong "
                                  "serial (was %u, expected %u)", backup_str,
                                  serial, z->db->outserial);
                    result = ODS_STATUS_ERR;
                    goto backup_ixfr_done;
                }
                first_soa = 0;
                continue;
            }
            ods_log_assert(!first_soa);
            if (!del_mode) {
                if (z->db->outserial == serial) {
                    /* final SOA */
                    ods_log_debug("[%s] ixfr final SOA: %s", backup_str,
                                  ldns_rr2str(rr));
                    ldns_rr_free(rr);
                    rr = NULL;
                    result = ODS_STATUS_OK;
                    first_soa = 2;
                    continue;
                } else {
                    ods_log_debug("[%s] new part SOA: %s", backup_str,
                                  ldns_rr2str(rr));
                    lock_basic_lock(&z->ixfr->ixfr_lock);
                    ixfr_purge(z->ixfr);
                    lock_basic_unlock(&z->ixfr->ixfr_lock);
                }
            } else {
                ods_log_debug("[%s] second part SOA: %s", backup_str,
                              ldns_rr2str(rr));
            }
            del_mode = !del_mode;
        }
        /* ixfr add or del rr */
        if (first_soa) {
            ods_log_error("[%s] bad ixfr journal: first RR not SOA",
                          backup_str);
            ldns_rr_free(rr);
            rr = NULL;
            result = ODS_STATUS_ERR;
            goto backup_ixfr_done;
        }
        ods_log_assert(!first_soa);
        lock_basic_lock(&z->ixfr->ixfr_lock);
        if (del_mode) {
            ods_log_debug("[%s] -IXFR: %s", backup_str, ldns_rr2str(rr));
            ixfr_del_rr(z->ixfr, rr);
        } else {
            ods_log_debug("[%s] +IXFR: %s", backup_str, ldns_rr2str(rr));
            ixfr_add_rr(z->ixfr, rr);
        }
        lock_basic_unlock(&z->ixfr->ixfr_lock);
    }
    if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
        ods_log_error("[%s] error reading RR #%i (%s): %s",
                      backup_str, l, ldns_get_errorstr_by_id(status), line);
        result = ODS_STATUS_ERR;
    }

backup_ixfr_done:
    if (orig) {
        ldns_rdf_deep_free(orig);
        orig = NULL;
    }
    if (prev) {
        ldns_rdf_deep_free(prev);
        prev = NULL;
    }
    return result;
}