Esempio n. 1
0
ldns_status
ldns_resolver_new_default(ldns_resolver **res) {
	ldns_resolver *r;
	ldns_rdf *tmp;
	HKEY hKey;
	DWORD data_sz;
	char* buf;
	char* addr;

	RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
		"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 
		0, KEY_QUERY_VALUE, &hKey);

	RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, NULL, &data_sz);
	buf = (char*)malloc(data_sz + 1);

	RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, (LPBYTE)buf, &data_sz);

	RegCloseKey(hKey);

	if(buf[data_sz - 1] != 0) {
		buf[data_sz] = 0;
	}

	r = ldns_resolver_new();
	if(!r) {
		free(buf);
		return LDNS_STATUS_MEM_ERR;
	}

	addr = strtok(buf, " ");

	while(addr != NULL) {
		tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, addr);
		if (!tmp) {
			// try ip4
			tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, addr);
		}
		// could not parse it, exit 
		if (!tmp) {
			ldns_resolver_deep_free(r);
			free(buf);
			return LDNS_STATUS_SYNTAX_ERR;
		}
		(void)ldns_resolver_push_nameserver(r, tmp);
		ldns_rdf_deep_free(tmp);
		addr = strtok(NULL, " ");
	}

	free(buf);

	if(res) {
		*res = r;
		return LDNS_STATUS_OK;
	} else {
		return LDNS_STATUS_NULL;
	}
}
DCPluginSyncFilterResult
dcplugin_sync_pre_filter(DCPlugin *dcplugin, DCPluginDNSPacket *dcp_packet)
{
    uint8_t  *new_packet;
    ldns_rdf *edns_data;
    ldns_pkt *packet;
    size_t    new_packet_size;

    ldns_wire2pkt(&packet, dcplugin_get_wire_data(dcp_packet),
                  dcplugin_get_wire_data_len(dcp_packet));

    edns_data = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_HEX,
                                     dcplugin_get_user_data(dcplugin));
    ldns_pkt_set_edns_data(packet, edns_data);

    ldns_pkt2wire(&new_packet, packet, &new_packet_size);
    if (dcplugin_get_wire_data_max_len(dcp_packet) >= new_packet_size) {
        dcplugin_set_wire_data(dcp_packet, new_packet, new_packet_size);
    }

    free(new_packet);
    ldns_pkt_free(packet);

    return DCP_SYNC_FILTER_RESULT_OK;
}
Esempio n. 3
0
File: clib.c Progetto: crnt/zkdns
/* this will probably be moved to a better place in the library itself */
ldns_rr_list *
get_rrset(const ldns_zone *zone, const ldns_rdf *owner_name, const ldns_rr_type qtype, const ldns_rr_class qclass)
{
	const char* result;
	switch(qtype)
	{
		case LDNS_RR_TYPE_A:
			result = rp_get_a_record(rp_handle, owner_name->_data);
			break;
		default:
			result = 0;
	}
	if(!result)
	{
		return 0;
	}
	uint16_t i;
	ldns_rr_list *rrlist = ldns_rr_list_new();
	if (!zone || !owner_name) {
		fprintf(stderr, "Warning: get_rrset called with NULL zone or owner name\n");
		return rrlist;
	}

	ldns_rr* rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_A);
	ldns_rr_set_owner(rr, ldns_rdf_clone(owner_name));
	ldns_rdf* rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, result);
	ldns_rr_push_rdf(rr, rdf);
	
	ldns_rr_list_push_rr(rrlist, ldns_rr_clone(rr));
	
	return rrlist;
}
Esempio n. 4
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);
}
Esempio n. 5
0
ldns_resolver* createResolver(const char *dnsserver) {
    ldns_resolver   *res = NULL;
    ldns_status     status;
    ldns_rdf        *ns_rdf;

    if (dnsserver) {
        // Use the given DNS server
        res = ldns_resolver_new();
        if (!res)
            return NULL;

        // Create rdf from dnsserver
        ns_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, dnsserver);
#ifdef USE_IPV6
        if (!ns_rdf)
            ns_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, dnsserver);
#endif
        if (!ns_rdf) {
            ldns_resolver_deep_free(res);
            return NULL;
        } else {
            status = ldns_resolver_push_nameserver(res, ns_rdf);
            ldns_rdf_deep_free(ns_rdf);
            if (status != LDNS_STATUS_OK) {
                ldns_resolver_free(res);
                return NULL;
            }
        }
    } else {
        // Use a DNS server from resolv.conf
        status = ldns_resolver_new_frm_file(&res, NULL);
        if (status != LDNS_STATUS_OK) {
            ldns_resolver_free(res);
            return NULL;
        }
    }

    //  Enable TCP if requested
    ldns_resolver_set_usevc(res, mp_ldns_usevc);

    return res;
}
Esempio n. 6
0
File: lua.c Progetto: benlaurie/ldns
/*
==========
 RDF
==========
 */
static int
l_rdf_new_frm_str(lua_State *L)
{
	uint16_t t = (uint16_t)lua_tonumber(L, 1);
	char *str = strdup((char*)luaL_checkstring(L, 2));
	if (!str) {
		return 0;
	}
	
	ldns_rdf *new_rdf = ldns_rdf_new_frm_str((ldns_rdf_type)t, str);
	if (new_rdf) {
		lua_pushlightuserdata(L, new_rdf);
		return 1;
	} else {
		return 0;
	}
}
Esempio n. 7
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;
}
Esempio n. 8
0
ldns_status
ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
{
    ldns_resolver *r;
    const char *keyword[LDNS_RESOLV_KEYWORDS];
    char word[LDNS_MAX_LINELEN + 1];
    int8_t expect;
    uint8_t i;
    ldns_rdf *tmp;
#ifdef HAVE_SSL
    ldns_rr *tmp_rr;
#endif
    ssize_t gtr, bgtr;
    ldns_buffer *b;
    int lnr = 0, oldline;
    if(!line_nr) line_nr = &lnr;

    /* do this better
     * expect =
     * 0: keyword
     * 1: default domain dname
     * 2: NS aaaa or a record
     */

    /* recognized keywords */
    keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
    keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
    keyword[LDNS_RESOLV_SEARCH] = "search";
    /* these two are read but not used atm TODO */
    keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
    keyword[LDNS_RESOLV_OPTIONS] = "options";
    keyword[LDNS_RESOLV_ANCHOR] = "anchor";
    expect = LDNS_RESOLV_KEYWORD;

    r = ldns_resolver_new();
    if (!r) {
        return LDNS_STATUS_MEM_ERR;
    }

    gtr = 1;
    word[0] = 0;
    oldline = *line_nr;
    expect = LDNS_RESOLV_KEYWORD;
    while (gtr > 0) {
        /* check comments */
        if (word[0] == '#') {
            word[0]='x';
            if(oldline == *line_nr) {
                /* skip until end of line */
                int c;
                do {
                    c = fgetc(fp);
                } while(c != EOF && c != '\n');
                if(c=='\n' && line_nr) (*line_nr)++;
            }
            /* and read next to prepare for further parsing */
            oldline = *line_nr;
            continue;
        }
        oldline = *line_nr;
        switch(expect) {
        case LDNS_RESOLV_KEYWORD:
            /* keyword */
            gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
            if (gtr != 0) {
                if(word[0] == '#') continue;
                for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
                    if (strcasecmp(keyword[i], word) == 0) {
                        /* chosen the keyword and
                         * expect values carefully
                        	 */
                        expect = i;
                        break;
                    }
                }
                /* no keyword recognized */
                if (expect == LDNS_RESOLV_KEYWORD) {
                    /* skip line */
                    /*
                    ldns_resolver_deep_free(r);
                    return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
                    */
                }
            }
            break;
        case LDNS_RESOLV_DEFDOMAIN:
            /* default domain dname */
            gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
            if (gtr == 0) {
                return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
            }
            if(word[0] == '#') {
                expect = LDNS_RESOLV_KEYWORD;
                continue;
            }
            tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
            if (!tmp) {
                ldns_resolver_deep_free(r);
                return LDNS_STATUS_SYNTAX_DNAME_ERR;
            }

            /* DOn't free, because we copy the pointer */
            ldns_resolver_set_domain(r, tmp);
            expect = LDNS_RESOLV_KEYWORD;
            break;
        case LDNS_RESOLV_NAMESERVER:
            /* NS aaaa or a record */
            gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
            if (gtr == 0) {
                return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
            }
            if(word[0] == '#') {
                expect = LDNS_RESOLV_KEYWORD;
                continue;
            }
            if(strchr(word, '%')) {
                /* snip off interface labels,
                 * fe80::222:19ff:fe31:4222%eth0 */
                strchr(word, '%')[0]=0;
            }
            tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
            if (!tmp) {
                /* try ip4 */
                tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
            }
            /* could not parse it, exit */
            if (!tmp) {
                ldns_resolver_deep_free(r);
                return LDNS_STATUS_SYNTAX_ERR;
            }
            (void)ldns_resolver_push_nameserver(r, tmp);
            ldns_rdf_deep_free(tmp);
            expect = LDNS_RESOLV_KEYWORD;
            break;
        case LDNS_RESOLV_SEARCH:
            /* search list domain dname */
            gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
            b = LDNS_MALLOC(ldns_buffer);
            if(!b) {
                ldns_resolver_deep_free(r);
                return LDNS_STATUS_MEM_ERR;
            }

            ldns_buffer_new_frm_data(b, word, (size_t) gtr);
            if(ldns_buffer_status(b) != LDNS_STATUS_OK) {
                LDNS_FREE(b);
                ldns_resolver_deep_free(r);
                return LDNS_STATUS_MEM_ERR;
            }
            bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1);
            while (bgtr > 0) {
                gtr -= bgtr;
                if(word[0] == '#') {
                    expect = LDNS_RESOLV_KEYWORD;
                    ldns_buffer_free(b);
                    continue;
                }
                tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
                if (!tmp) {
                    ldns_resolver_deep_free(r);
                    ldns_buffer_free(b);
                    return LDNS_STATUS_SYNTAX_DNAME_ERR;
                }

                ldns_resolver_push_searchlist(r, tmp);

                ldns_rdf_deep_free(tmp);
                bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL,
                                       (size_t) gtr + 1);
            }
            ldns_buffer_free(b);
            gtr = 1;
            expect = LDNS_RESOLV_KEYWORD;
            break;
        case LDNS_RESOLV_SORTLIST:
            gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
            /* sortlist not implemented atm */
            expect = LDNS_RESOLV_KEYWORD;
            break;
        case LDNS_RESOLV_OPTIONS:
            gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
            /* options not implemented atm */
            expect = LDNS_RESOLV_KEYWORD;
            break;
        case LDNS_RESOLV_ANCHOR:
            /* a file containing a DNSSEC trust anchor */
            gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
            if (gtr == 0) {
                ldns_resolver_deep_free(r);
                return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
            }
            if(word[0] == '#') {
                expect = LDNS_RESOLV_KEYWORD;
                continue;
            }

#ifdef HAVE_SSL
            tmp_rr = ldns_read_anchor_file(word);
            (void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
            ldns_rr_free(tmp_rr);
#endif
            expect = LDNS_RESOLV_KEYWORD;
            break;
        }
    }

    /* finally, add the root domain to the search list */
    ldns_resolver_push_searchlist(r, ldns_dname_new_frm_str("."));

    if (res) {
        *res = r;
        return LDNS_STATUS_OK;
    } else {
        ldns_resolver_deep_free(r);
        return LDNS_STATUS_NULL;
    }
}
Esempio n. 9
0
ldns_status
ldns_pkt_tsig_sign_next(ldns_pkt *pkt, const char *key_name, const char *key_data,
	uint16_t fudge, const char *algorithm_name, ldns_rdf *query_mac, int tsig_timers_only)
{
	ldns_rr *tsig_rr;
	ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name);
	ldns_rdf *fudge_rdf = NULL;
	ldns_rdf *orig_id_rdf = NULL;
	ldns_rdf *algorithm_rdf;
	ldns_rdf *error_rdf = NULL;
	ldns_rdf *mac_rdf = NULL;
	ldns_rdf *other_data_rdf = NULL;

	ldns_status status = LDNS_STATUS_OK;

	uint8_t *pkt_wire = NULL;
	size_t pkt_wire_len;

	struct timeval tv_time_signed;
	uint8_t *time_signed = NULL;
	ldns_rdf *time_signed_rdf = NULL;

	algorithm_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, algorithm_name);
	if(!key_name_rdf || !algorithm_rdf) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}

	/* eww don't have create tsigtime rdf yet :( */
	/* bleh :p */
	if (gettimeofday(&tv_time_signed, NULL) == 0) {
		time_signed = LDNS_XMALLOC(uint8_t, 6);
		if(!time_signed) {
			status = LDNS_STATUS_MEM_ERR;
			goto clean;
		}
		ldns_write_uint64_as_uint48(time_signed,
				(uint64_t)tv_time_signed.tv_sec);
	} else {
		status = LDNS_STATUS_INTERNAL_ERR;
		goto clean;
	}

	time_signed_rdf = ldns_rdf_new(LDNS_RDF_TYPE_TSIGTIME, 6, time_signed);
	if(!time_signed_rdf) {
		LDNS_FREE(time_signed);
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}

	fudge_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, fudge);

	orig_id_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, ldns_pkt_id(pkt));

	error_rdf = ldns_native2rdf_int16(LDNS_RDF_TYPE_INT16, 0);

	other_data_rdf = ldns_native2rdf_int16_data(0, NULL);

	if(!fudge_rdf || !orig_id_rdf || !error_rdf || !other_data_rdf) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}

	if (ldns_pkt2wire(&pkt_wire, pkt, &pkt_wire_len) != LDNS_STATUS_OK) {
		status = LDNS_STATUS_ERR;
		goto clean;
	}

	status = ldns_tsig_mac_new(&mac_rdf, pkt_wire, pkt_wire_len,
			key_data, key_name_rdf, fudge_rdf, algorithm_rdf,
			time_signed_rdf, error_rdf, other_data_rdf, query_mac, tsig_timers_only);

	if (!mac_rdf) {
		goto clean;
	}

	LDNS_FREE(pkt_wire);

	/* Create the TSIG RR */
	tsig_rr = ldns_rr_new();
	if(!tsig_rr) {
		status = LDNS_STATUS_MEM_ERR;
		goto clean;
	}
	ldns_rr_set_owner(tsig_rr, key_name_rdf);
	ldns_rr_set_class(tsig_rr, LDNS_RR_CLASS_ANY);
	ldns_rr_set_type(tsig_rr, LDNS_RR_TYPE_TSIG);
	ldns_rr_set_ttl(tsig_rr, 0);

	ldns_rr_push_rdf(tsig_rr, algorithm_rdf);
	ldns_rr_push_rdf(tsig_rr, time_signed_rdf);
	ldns_rr_push_rdf(tsig_rr, fudge_rdf);
	ldns_rr_push_rdf(tsig_rr, mac_rdf);
	ldns_rr_push_rdf(tsig_rr, orig_id_rdf);
	ldns_rr_push_rdf(tsig_rr, error_rdf);
	ldns_rr_push_rdf(tsig_rr, other_data_rdf);

	ldns_pkt_set_tsig(pkt, tsig_rr);

	return status;

  clean:
	LDNS_FREE(pkt_wire);
	ldns_rdf_free(key_name_rdf);
	ldns_rdf_free(algorithm_rdf);
	ldns_rdf_free(time_signed_rdf);
	ldns_rdf_free(fudge_rdf);
	ldns_rdf_free(orig_id_rdf);
	ldns_rdf_free(error_rdf);
	ldns_rdf_free(other_data_rdf);
	return status;
}
Esempio n. 10
0
bool
ldns_pkt_tsig_verify_next(ldns_pkt *pkt, uint8_t *wire, size_t wirelen, const char* key_name,
	const char *key_data, ldns_rdf *orig_mac_rdf, int tsig_timers_only)
{
	ldns_rdf *fudge_rdf;
	ldns_rdf *algorithm_rdf;
	ldns_rdf *time_signed_rdf;
	ldns_rdf *orig_id_rdf;
	ldns_rdf *error_rdf;
	ldns_rdf *other_data_rdf;
	ldns_rdf *pkt_mac_rdf;
	ldns_rdf *my_mac_rdf;
	ldns_rdf *key_name_rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, key_name);
	uint16_t pkt_id, orig_pkt_id;
	ldns_status status;

	uint8_t *prepared_wire = NULL;
	size_t prepared_wire_size = 0;

	ldns_rr *orig_tsig = ldns_pkt_tsig(pkt);

	if (!orig_tsig || ldns_rr_rd_count(orig_tsig) <= 6) {
		ldns_rdf_deep_free(key_name_rdf);
		return false;
	}
	algorithm_rdf = ldns_rr_rdf(orig_tsig, 0);
	time_signed_rdf = ldns_rr_rdf(orig_tsig, 1);
	fudge_rdf = ldns_rr_rdf(orig_tsig, 2);
	pkt_mac_rdf = ldns_rr_rdf(orig_tsig, 3);
	orig_id_rdf = ldns_rr_rdf(orig_tsig, 4);
	error_rdf = ldns_rr_rdf(orig_tsig, 5);
	other_data_rdf = ldns_rr_rdf(orig_tsig, 6);

	/* remove temporarily */
	ldns_pkt_set_tsig(pkt, NULL);
	/* temporarily change the id to the original id */
	pkt_id = ldns_pkt_id(pkt);
	orig_pkt_id = ldns_rdf2native_int16(orig_id_rdf);
	ldns_pkt_set_id(pkt, orig_pkt_id);

	prepared_wire = ldns_tsig_prepare_pkt_wire(wire, wirelen, &prepared_wire_size);

	status = ldns_tsig_mac_new(&my_mac_rdf, prepared_wire, prepared_wire_size,
			key_data, key_name_rdf, fudge_rdf, algorithm_rdf,
			time_signed_rdf, error_rdf, other_data_rdf, orig_mac_rdf, tsig_timers_only);

	LDNS_FREE(prepared_wire);

	if (status != LDNS_STATUS_OK) {
		ldns_rdf_deep_free(key_name_rdf);
		return false;
	}
	/* Put back the values */
	ldns_pkt_set_tsig(pkt, orig_tsig);
	ldns_pkt_set_id(pkt, pkt_id);

	ldns_rdf_deep_free(key_name_rdf);

	if (ldns_rdf_compare(pkt_mac_rdf, my_mac_rdf) == 0) {
		ldns_rdf_deep_free(my_mac_rdf);
		return true;
	} else {
		ldns_rdf_deep_free(my_mac_rdf);
		return false;
	}
}
Esempio n. 11
0
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;
}
Esempio n. 13
0
ldns_status
ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr)
{
	ldns_resolver *r;
	const char *keyword[LDNS_RESOLV_KEYWORDS];
	char word[LDNS_MAX_LINELEN + 1];
	int8_t expect;
	uint8_t i;
	ldns_rdf *tmp;
#ifdef HAVE_SSL
	ldns_rr *tmp_rr;
#endif
	ssize_t gtr;
	ldns_buffer *b;

	/* do this better 
	 * expect = 
	 * 0: keyword
	 * 1: default domain dname
	 * 2: NS aaaa or a record
	 */

	/* recognized keywords */
	keyword[LDNS_RESOLV_NAMESERVER] = "nameserver";
	keyword[LDNS_RESOLV_DEFDOMAIN] = "domain";
	keyword[LDNS_RESOLV_SEARCH] = "search";
	/* these two are read but not used atm TODO */
	keyword[LDNS_RESOLV_SORTLIST] = "sortlist";
	keyword[LDNS_RESOLV_OPTIONS] = "options";
	keyword[LDNS_RESOLV_ANCHOR] = "anchor";
	expect = LDNS_RESOLV_KEYWORD;

	r = ldns_resolver_new();
	if (!r) {
		return LDNS_STATUS_MEM_ERR;
	}

	gtr = 1;
	word[0] = 0;
	while (gtr > 0) {
		/* check comments */
		if (word[0] == '#') {
			/* read the rest of the line, should be 1 word */
			gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
			/* prepare the next string for further parsing */
			gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
			continue;
		}
		switch(expect) {
			case LDNS_RESOLV_KEYWORD:
				/* keyword */
				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
				if (gtr != 0) {
					for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) {
						if (strcasecmp(keyword[i], word) == 0) {
							/* chosen the keyword and
							 * expect values carefully
							 */
							expect = i;
							break;
						}
					}
					/* no keyword recognized */
					if (expect == LDNS_RESOLV_KEYWORD) {
						/* skip line */
						/*
						ldns_resolver_deep_free(r);
						return LDNS_STATUS_SYNTAX_KEYWORD_ERR;
						*/
					}
				}
				break;
			case LDNS_RESOLV_DEFDOMAIN:
				/* default domain dname */
				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
				if (gtr == 0) {
					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
				}
				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
				if (!tmp) {
					ldns_resolver_deep_free(r);
					return LDNS_STATUS_SYNTAX_DNAME_ERR;
				}

				/* DOn't free, because we copy the pointer */
				ldns_resolver_set_domain(r, tmp);
				expect = LDNS_RESOLV_KEYWORD;
				break;
			case LDNS_RESOLV_NAMESERVER:
				/* NS aaaa or a record */
				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
				if (gtr == 0) {
					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
				}
				tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, word);
				if (!tmp) {
					/* try ip4 */
					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, word);
				}
				/* could not parse it, exit */
				if (!tmp) {
					ldns_resolver_deep_free(r);
					return LDNS_STATUS_SYNTAX_ERR;
				}
				(void)ldns_resolver_push_nameserver(r, tmp);
				ldns_rdf_deep_free(tmp);
				expect = LDNS_RESOLV_KEYWORD;
				break;
			case LDNS_RESOLV_SEARCH:
				/* search list domain dname */
				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
				b = LDNS_MALLOC(ldns_buffer);
				ldns_buffer_new_frm_data(b, word, (size_t) gtr);

				gtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr);
				while (gtr > 0) {
					tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word);
					if (!tmp) {
						ldns_resolver_deep_free(r);
						return LDNS_STATUS_SYNTAX_DNAME_ERR;
					}

					ldns_resolver_push_searchlist(r, tmp); 

					ldns_rdf_deep_free(tmp);
					gtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr);
				}
				ldns_buffer_free(b);
				gtr = 1;
				expect = LDNS_RESOLV_KEYWORD;
				break;
			case LDNS_RESOLV_SORTLIST:
				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
				/* sortlist not implemented atm */
				expect = LDNS_RESOLV_KEYWORD;
				break;
			case LDNS_RESOLV_OPTIONS:
				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr);
				/* options not implemented atm */
				expect = LDNS_RESOLV_KEYWORD;
				break;
			case LDNS_RESOLV_ANCHOR:
				/* a file containing a DNSSEC trust anchor */
				gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr);
				if (gtr == 0) {
					return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR;
				}

#ifdef HAVE_SSL
				tmp_rr = ldns_read_anchor_file(word);
				(void) ldns_resolver_push_dnssec_anchor(r, tmp_rr);
				ldns_rr_free(tmp_rr);
#endif
				expect = LDNS_RESOLV_KEYWORD;
				break;
		}
	}
	
	if (res) {
		*res = r;
		return LDNS_STATUS_OK;
	} else {
		return LDNS_STATUS_NULL;
	}
}
Esempio n. 14
0
ldns_rr_list* getaddr_rdf(ldns_resolver *res, ldns_rdf *hostrdf) {
    ldns_rdf        *rdf;
    ldns_resolver   *r = NULL;
    ldns_rr_list    *rrl;
    ldns_rr_list    *ret = NULL;
    ldns_pkt        *pkt;
    ldns_status     status;

    if (ldns_rdf_get_type(hostrdf) == LDNS_RDF_TYPE_A
#ifdef USE_IPV6
        || ldns_rdf_get_type(hostrdf) == LDNS_RDF_TYPE_AAAA
#endif
       ) {
        rdf = ldns_rdf_address_reverse(hostrdf);

        r = res;
        if (res == NULL) {
            status = ldns_resolver_new_frm_file(&r, NULL);
            if (status != LDNS_STATUS_OK)
                return NULL;
        }

        // Fetch PTR
        pkt = ldns_resolver_query(r, rdf, LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN,
                                          LDNS_RD);

        if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR)
            return NULL;

        rrl = ldns_pkt_rr_list_by_name_and_type(pkt, rdf, LDNS_RR_TYPE_PTR,
                                                          LDNS_SECTION_ANSWER);

        if (ldns_rr_list_rr_count(rrl) != 1)
            return NULL;

        ldns_rdf_deep_free(rdf);
        rdf = ldns_rdf_clone(ldns_rr_rdf(ldns_rr_list_rr(rrl,0),0));
        ldns_pkt_free(pkt);
        ldns_rr_list_deep_free(rrl);
    } else if (ldns_rdf_get_type(hostrdf) == LDNS_RDF_TYPE_DNAME) {
        rdf = hostrdf;
    } else {
        return NULL;
    }

    if (r == NULL) {
        r = res;
        if (res == NULL) {
            status = ldns_resolver_new_frm_file(&r, NULL);
            if (status != LDNS_STATUS_OK)
                return NULL;
        }
    }

#ifdef USE_IPV6
    if (ldns_rdf_get_type(hostrdf) != LDNS_RDF_TYPE_A) {
        // Fetch AAAA
        pkt = ldns_resolver_query(r, rdf, LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN,
                                          LDNS_RD);

        if (pkt != NULL && ldns_pkt_get_rcode(pkt) == LDNS_RCODE_NOERROR) {
            rrl = ldns_pkt_rr_list_by_name_and_type(pkt, rdf, LDNS_RR_TYPE_AAAA,
                                                    LDNS_SECTION_ANSWER);
            ldns_pkt_free(pkt);

            if (ldns_rr_list_rr_count(rrl) > 0) {
                ret = rrl;
                rrl = NULL;
            } else {
                ldns_rr_list_free(rrl);
            }
        }
    }

    if (ldns_rdf_get_type(hostrdf) != LDNS_RDF_TYPE_AAAA) {
#else
    if (1) {
#endif /* USE_IPV6 */

        // Fetch AA
        pkt = ldns_resolver_query(r, rdf, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN,
                                          LDNS_RD);

        if (pkt != NULL && ldns_pkt_get_rcode(pkt) == LDNS_RCODE_NOERROR) {

            rrl = ldns_pkt_rr_list_by_name_and_type(pkt, rdf, LDNS_RR_TYPE_A,
                                                    LDNS_SECTION_ANSWER);

            ldns_pkt_free(pkt);

            if (ldns_rr_list_rr_count(rrl) > 0) {
                if (ret == NULL) {
                    ret = rrl;
                } else {
                    ldns_rr_list_cat(ret, rrl);
                    ldns_rr_list_free(rrl);
                }
            } else {
                ldns_rr_list_free(rrl);
            }
        } // if (pkt != NULL && ldns_pkt_ge...
    }

    if (res == NULL)
        ldns_resolver_deep_free(r);

    return ret;
}

ldns_rr_list* getaddr(ldns_resolver *res, const char *hostname) {

    ldns_rdf    *rdf;

    /* Check if hostname is a ip */
    rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, hostname);
#ifdef USE_IPV6
    if (!rdf) {
        rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, hostname);
    }
#endif
    if (!rdf) {
        rdf = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, hostname);
    }
    if (!rdf)
        return NULL;

    return getaddr_rdf(res, rdf);
}
static bool 
retract_dnskey_by_id(int sockfd,
					const char *ds_retract_command,
					const char *id,
					::ods::keystate::keyrole role,
					const char *zone,
					int algorithm)
{
    /* Code to output the DNSKEY record  (stolen from hsmutil) */
    hsm_ctx_t *hsm_ctx = hsm_create_context();
    if (!hsm_ctx) {
		ods_log_error_and_printf(sockfd,
								 module_str,
								 "could not connect to HSM");
        return false;
    }
    hsm_key_t *key = hsm_find_key_by_id(hsm_ctx, id);
    
    if (!key) {
        ods_log_error_and_printf(sockfd,
								 module_str,
								 "key %s not found in any HSM",
								 id);
        hsm_destroy_context(hsm_ctx);
        return false;
    }
    
    bool bOK = false;
    char *dnskey_rr_str;
	
    hsm_sign_params_t *sign_params = hsm_sign_params_new();
    sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone);
    sign_params->algorithm = (ldns_algorithm)algorithm;
    sign_params->flags = LDNS_KEY_ZONE_KEY;
    sign_params->flags += LDNS_KEY_SEP_KEY; /*KSK=>SEP*/
    
    ldns_rr *dnskey_rr = hsm_get_dnskey(hsm_ctx, key, sign_params);
#if 0
    ldns_rr_print(stdout, dnskey_rr);
#endif        
    dnskey_rr_str = ldns_rr2str(dnskey_rr);
    
    hsm_sign_params_free(sign_params);
    ldns_rr_free(dnskey_rr);
    hsm_key_free(key);
	
    /* Replace tab with white-space */
    for (int i = 0; dnskey_rr_str[i]; ++i) {
        if (dnskey_rr_str[i] == '\t') {
            dnskey_rr_str[i] = ' ';
        }
    }
    
    /* We need to strip off trailing comments before we send
     to any clients that might be listening */
    for (int i = 0; dnskey_rr_str[i]; ++i) {
        if (dnskey_rr_str[i] == ';') {
            dnskey_rr_str[i] = '\n';
            dnskey_rr_str[i+1] = '\0';
            break;
        }
    }

    // pass the dnskey rr string to a configured
    // delegation signer retract program.
    if (ds_retract_command && ds_retract_command[0] != '\0') {
        /* send records to the configured command */
        FILE *fp = popen(ds_retract_command, "w");
        if (fp == NULL) {
            ods_log_error_and_printf(sockfd,
									 module_str,
									 "failed to run command: %s: %s",
									 ds_retract_command,
									 strerror(errno));
        } else {
            int bytes_written = fprintf(fp, "%s", dnskey_rr_str);
            if (bytes_written < 0) {
                ods_log_error_and_printf(sockfd,
										 module_str,
										 "[%s] Failed to write to %s: %s",
										 ds_retract_command,
										 strerror(errno));
            } else {
				
                if (pclose(fp) == -1) {
                    ods_log_error_and_printf(sockfd,
											 module_str,
											 "failed to close %s: %s",
											 ds_retract_command,
											 strerror(errno));
                } else {
                    bOK = true;
                    ods_printf(sockfd,
							   "key %s retracted by %s\n",
							   id,
							   ds_retract_command);
                }
            }
        }
    } else {
        ods_log_error_and_printf(sockfd,
								 module_str,
								 "no \"DelegationSignerRetractCommand\" binary "
								 "configured in conf.xml.");
    }
	
    LDNS_FREE(dnskey_rr_str);
    hsm_destroy_context(hsm_ctx);
    return bOK;
}
static bool 
retract_dnskey_by_id(int sockfd,
					const char *ds_retract_command,
					const char *id,
					::ods::keystate::keyrole role,
					const char *zone,
					int algorithm,
					bool force)
{
	struct stat stat_ret;
	/* Code to output the DNSKEY record  (stolen from hsmutil) */
	hsm_ctx_t *hsm_ctx = hsm_create_context();
	if (!hsm_ctx) {
		ods_log_error_and_printf(sockfd,
								 module_str,
								 "could not connect to HSM");
		return false;
	}
	hsm_key_t *key = hsm_find_key_by_id(hsm_ctx, id);
	
	if (!key) {
		ods_log_error_and_printf(sockfd,
								 module_str,
								 "key %s not found in any HSM",
								 id);
		hsm_destroy_context(hsm_ctx);
		return false;
	}
	
	bool bOK = false;
	char *dnskey_rr_str;
	
	hsm_sign_params_t *sign_params = hsm_sign_params_new();
	sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone);
	sign_params->algorithm = (ldns_algorithm)algorithm;
	sign_params->flags = LDNS_KEY_ZONE_KEY;
	sign_params->flags += LDNS_KEY_SEP_KEY; /*KSK=>SEP*/
	
	ldns_rr *dnskey_rr = hsm_get_dnskey(hsm_ctx, key, sign_params);
#if 0
	ldns_rr_print(stdout, dnskey_rr);
#endif        
	dnskey_rr_str = ldns_rr2str(dnskey_rr);
	
	hsm_sign_params_free(sign_params);
	ldns_rr_free(dnskey_rr);
	hsm_key_free(key);
	
	/* Replace tab with white-space */
	for (int i = 0; dnskey_rr_str[i]; ++i) {
		if (dnskey_rr_str[i] == '\t') {
			dnskey_rr_str[i] = ' ';
		}
	}
	
	/* We need to strip off trailing comments before we send
	 to any clients that might be listening */
	for (int i = 0; dnskey_rr_str[i]; ++i) {
		if (dnskey_rr_str[i] == ';') {
			dnskey_rr_str[i] = '\n';
			dnskey_rr_str[i+1] = '\0';
			break;
		}
	}
	// pass the dnskey rr string to a configured
	// delegation signer retract program.
	if (!ds_retract_command || ds_retract_command[0] == '\0') {
		if (!force) {
			ods_log_error_and_printf(sockfd, module_str, 
				"No \"DelegationSignerRetractCommand\" "
				"configured. No state changes made. "
				"Use --force to override.");
			bOK = false;
		}
		/* else: Do nothing, return keytag. */
	} else if (stat(ds_retract_command, &stat_ret) != 0) {
		/* First check that the command exists */
		ods_log_error_and_printf(sockfd, module_str,
			"Cannot stat file %s: %s", ds_retract_command,
			strerror(errno));
	} else if (S_ISREG(stat_ret.st_mode) && 
			!(stat_ret.st_mode & S_IXUSR || 
			  stat_ret.st_mode & S_IXGRP || 
			  stat_ret.st_mode & S_IXOTH)) {
		/* Then see if it is a regular file, then if usr, grp or 
		 * all have execute set */
		ods_log_error_and_printf(sockfd, module_str,
			"File %s is not executable", ds_retract_command);
	} else {
		/* send records to the configured command */
		FILE *fp = popen(ds_retract_command, "w");
		if (fp == NULL) {
			ods_log_error_and_printf(sockfd, module_str,
				"failed to run command: %s: %s", ds_retract_command,
				strerror(errno));
		} else {
			int bytes_written = fprintf(fp, "%s", dnskey_rr_str);
			if (bytes_written < 0) {
				ods_log_error_and_printf(sockfd, module_str,
					"[%s] Failed to write to %s: %s", ds_retract_command,
					strerror(errno));
			} else if (pclose(fp) == -1) {
				ods_log_error_and_printf(sockfd, module_str,
					"failed to close %s: %s", ds_retract_command,
					strerror(errno));
			} else {
				bOK = true;
				ods_printf(sockfd, "key %s retracted by %s\n", id,
					ds_retract_command);
			}
		}
	}
	
	LDNS_FREE(dnskey_rr_str);
	hsm_destroy_context(hsm_ctx);
	return bOK;
}
Esempio n. 17
0
ldns_status
ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet)
{
	ldns_rr_list *rr_list;
	uint16_t i;
	
	/* edns tmp vars */
	ldns_rr *edns_rr;
	uint8_t edata[4];
	
	(void) ldns_hdr2buffer_wire(buffer, packet);

	rr_list = ldns_pkt_question(packet);
	if (rr_list) {
		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
			(void) ldns_rr2buffer_wire(buffer, 
			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION);
		}
	}
	rr_list = ldns_pkt_answer(packet);
	if (rr_list) {
		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
			(void) ldns_rr2buffer_wire(buffer, 
			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER);
		}
	}
	rr_list = ldns_pkt_authority(packet);
	if (rr_list) {
		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
			(void) ldns_rr2buffer_wire(buffer, 
			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY);
		}
	}
	rr_list = ldns_pkt_additional(packet);
	if (rr_list) {
		for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) {
			(void) ldns_rr2buffer_wire(buffer, 
			             ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL);
		}
	}
	
	/* add EDNS to additional if it is needed */
	if (ldns_pkt_edns(packet)) {
		edns_rr = ldns_rr_new();
		ldns_rr_set_owner(edns_rr,
				ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, "."));
		ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT);
		ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet));
		edata[0] = ldns_pkt_edns_extended_rcode(packet);
		edata[1] = ldns_pkt_edns_version(packet);
		ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet));
		ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata));
		(void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL);
		ldns_rr_free(edns_rr);
	}
	
	/* add TSIG to additional if it is there */
	if (ldns_pkt_tsig(packet)) {
		(void) ldns_rr2buffer_wire(buffer,
		                           ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL);
	}
	
	return LDNS_STATUS_OK;
}
Esempio n. 18
0
int
main(int argc, char *argv[])
{
	ldns_resolver *res;
	ldns_rdf *ns;
	ldns_rdf *domain;
	ldns_rr_list *l = NULL;

	ldns_rr_list *dns_root = NULL;
	const char *root_file = "/etc/named.root";

	ldns_status status;
	
	int i;

	char *domain_str;
	char *outputfile_str;
	ldns_buffer *outputfile_buffer;
	FILE *outputfile;
	ldns_rr *k;
	
	bool insecure = false;
	ldns_pkt *pkt;

	domain = NULL;
	res = NULL;

	if (argc < 2) {
		usage(stdout, argv[0]);
		exit(EXIT_FAILURE);
	} else {
		for (i = 1; i < argc; i++) {
			if (strncmp("-4", argv[i], 3) == 0) {
				if (address_family != 0) {
					fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n");
					exit(EXIT_FAILURE);
				}
				address_family = 1;
			} else if (strncmp("-6", argv[i], 3) == 0) {
				if (address_family != 0) {
					fprintf(stderr, "Options -4 and -6 cannot be specified at the same time\n");
					exit(EXIT_FAILURE);
				}
				address_family = 2;
			} else if (strncmp("-h", argv[i], 3) == 0) {
				usage(stdout, argv[0]);
				exit(EXIT_SUCCESS);
			} else if (strncmp("-i", argv[i], 2) == 0) {
				insecure = true;
			} else if (strncmp("-r", argv[i], 2) == 0) {
				if (strlen(argv[i]) > 2) {
					root_file = argv[i]+2;
				} else if (i+1 >= argc) {
					usage(stdout, argv[0]);
					exit(EXIT_FAILURE);
				} else {
					root_file = argv[i+1];
					i++;
				}
			} else if (strncmp("-s", argv[i], 3) == 0) {
				store_in_file = true;
			} else if (strncmp("-v", argv[i], 2) == 0) {
				if (strlen(argv[i]) > 2) {
					verbosity = atoi(argv[i]+2);
				} else if (i+1 > argc) {
					usage(stdout, argv[0]);
					exit(EXIT_FAILURE);
				} else {
					verbosity = atoi(argv[i+1]);
					i++;
				}
			} else {
				/* create a rdf from the command line arg */
				if (domain) {
					fprintf(stdout, "You can only specify one domain at a time\n");
					exit(EXIT_FAILURE);
				}

				domain = ldns_dname_new_frm_str(argv[i]);
			}

		}
		if (!domain) {
			usage(stdout, argv[0]);
			exit(EXIT_FAILURE);
		}
	}

	dns_root = read_root_hints(root_file);
	if (!dns_root) {
		fprintf(stderr, "cannot read the root hints file\n");
		exit(EXIT_FAILURE);
	}

	/* create a new resolver from /etc/resolv.conf */
	status = ldns_resolver_new_frm_file(&res, NULL);

	if (status != LDNS_STATUS_OK) {
		fprintf(stderr, "Warning: Unable to create stub resolver from /etc/resolv.conf:\n");
		fprintf(stderr, "%s\n", ldns_get_errorstr_by_id(status));
		fprintf(stderr, "defaulting to nameserver at 127.0.0.1 for separate nameserver name lookups\n");
		res = ldns_resolver_new();
		ns = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, "127.0.0.1");
		status = ldns_resolver_push_nameserver(res, ns);
		if (status != LDNS_STATUS_OK) {
			fprintf(stderr, "Unable to create stub resolver: %s\n", ldns_get_errorstr_by_id(status));
			exit(EXIT_FAILURE);
		}
		ldns_rdf_deep_free(ns);
	}

	ldns_resolver_set_ip6(res, address_family);

	if (insecure) {
		pkt = ldns_resolver_query(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, LDNS_RD);
		if (pkt) {
		l = ldns_pkt_rr_list_by_type(pkt, LDNS_RR_TYPE_DNSKEY, LDNS_SECTION_ANY_NOQUESTION);
		}
	} else {
		l = retrieve_dnskeys(res, domain, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, dns_root);
	}
	
	/* separator for result data and verbosity data */
	if (verbosity > 0) {
		fprintf(stdout, "; ---------------------------\n");
		fprintf(stdout, "; Got the following keys:\n");
	}
	if (l) {
		if (store_in_file) {
			/* create filename:
			 * K<domain>.+<alg>.+<id>.key
			 */
			for (i = 0; (size_t) i < ldns_rr_list_rr_count(l); i++) {
				k = ldns_rr_list_rr(l, (size_t) i);
				
				outputfile_buffer = ldns_buffer_new(300);
				domain_str = ldns_rdf2str(ldns_rr_owner(k));
				ldns_buffer_printf(outputfile_buffer, "K%s+%03u+%05u.key", domain_str, ldns_rdf2native_int8(ldns_rr_rdf(k, 2)),
					(unsigned int) ldns_calc_keytag(k));
				outputfile_str = ldns_buffer_export(outputfile_buffer);
				
				if (verbosity >= 1) {
					fprintf(stdout, "Writing key to file %s\n", outputfile_str);
				}
				
				outputfile = fopen(outputfile_str, "w");
				if (!outputfile) {
					fprintf(stderr, "Error writing key to file %s: %s\n", outputfile_str, strerror(errno));
				} else {
					ldns_rr_print(outputfile, k);
					fclose(outputfile);
				}
				
				LDNS_FREE(domain_str);
				LDNS_FREE(outputfile_str);
				LDNS_FREE(outputfile_buffer);
			}
		} else {
			ldns_rr_list_print(stdout, l);
		}
	} else {
		fprintf(stderr, "no answer packet received, stub resolver config:\n");
		ldns_resolver_print(stderr, res);
	}
	printf("\n");

	ldns_rdf_deep_free(domain);
	ldns_resolver_deep_free(res);
	ldns_rr_list_deep_free(l);
	ldns_rr_list_deep_free(dns_root);
	return EXIT_SUCCESS;
}
Esempio n. 19
0
/**
 * Read the next RR from zone file.
 *
 */
static ldns_rr*
adfile_read_rr(FILE* fd, zone_type* zone, char* line, ldns_rdf** orig,
    ldns_rdf** prev, uint32_t* ttl, ldns_status* status, unsigned int* l)
{
    ldns_rr* rr = NULL;
    ldns_rdf* tmp = NULL;
    FILE* fd_include = NULL;
    int len = 0;
    ods_status s = ODS_STATUS_OK;
    uint32_t new_ttl = 0;
    const char *endptr;  /* unused */
    int offset = 0;

adfile_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]) {
            /* directive */
            case '$':
                if (strncmp(line, "$ORIGIN", 7) == 0 && isspace((int)line[7])) {
                    /* copy from ldns */
                    if (*orig) {
                        ldns_rdf_deep_free(*orig);
                        *orig = NULL;
                    }
                    offset = 8;
                    while (isspace((int)line[offset])) {
                        offset++;
                    }
                    tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME,
                        line + offset);
                    if (!tmp) {
                        /* could not parse what next to $ORIGIN */
                        *status = LDNS_STATUS_SYNTAX_DNAME_ERR;
                        return NULL;
                    }
                    *orig = tmp;
                    /* end copy from ldns */
                    goto adfile_read_line; /* perhaps next line is rr */
                    break;
                } else if (strncmp(line, "$TTL", 4) == 0 &&
                    isspace((int)line[4])) {
                    /* override default ttl */
                    offset = 5;
                    while (isspace((int)line[offset])) {
                        offset++;
                    }
                    if (ttl) {
                        *ttl = ldns_str2period(line + offset, &endptr);
                        new_ttl = *ttl;
                    }
                    goto adfile_read_line; /* perhaps next line is rr */
                    break;
                } else if (strncmp(line, "$INCLUDE", 8) == 0 &&
                    isspace((int)line[8])) {
                    /* dive into this file */
                    offset = 9;
                    while (isspace((int)line[offset])) {
                        offset++;
                    }
                    fd_include = ods_fopen(line + offset, NULL, "r");
                    if (fd_include) {
                        s = adfile_read_file(fd_include, zone);
                        ods_fclose(fd_include);
                    } else {
                        ods_log_error("[%s] unable to open include file %s",
                            adapter_str, (line+offset));
                        *status = LDNS_STATUS_SYNTAX_ERR;
                        return NULL;
                    }
                    if (s != ODS_STATUS_OK) {
                        *status = LDNS_STATUS_SYNTAX_ERR;
                        ods_log_error("[%s] error in include file %s",
                            adapter_str, (line+offset));
                        return NULL;
                    }
                    /* restore current ttl */
                    if (ttl) {
                        *ttl = new_ttl;
                    }
                    goto adfile_read_line; /* perhaps next line is rr */
                    break;
                }
                goto adfile_read_rr; /* this can be an owner name */
                break;
            /* comments, empty lines */
            case ';':
            case '\n':
                goto adfile_read_line; /* perhaps next line is rr */
                break;
            /* let's hope its a RR */
            default:
adfile_read_rr:
                if (adutil_whitespace_line(line, len)) {
                    goto adfile_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 adfile_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;
}
Esempio n. 20
0
int
cmd_dnskey (int argc, char *argv[])
{
    char *id;
    char *name;
    int type;
    int algo;

    hsm_key_t *key = NULL;
    ldns_rr *dnskey_rr;
    hsm_sign_params_t *sign_params;

    if (argc != 4) {
        usage();
        return -1;
    }

    id = strdup(argv[0]);
    name = strdup(argv[1]);
    type = atoi(argv[2]);
    algo = atoi(argv[3]);

    key = hsm_find_key_by_id(NULL, id);

    if (!key) {
        printf("Key not found: %s\n", id);
        free(name);
        free(id);
        return -1;
    }

    if (type != LDNS_KEY_ZONE_KEY && type != LDNS_KEY_ZONE_KEY + LDNS_KEY_SEP_KEY) {
        printf("Invalid key type: %i\n", type);
        printf("Please use: %i or %i\n", LDNS_KEY_ZONE_KEY, LDNS_KEY_ZONE_KEY + LDNS_KEY_SEP_KEY);
        free(name);
        free(id);
        return -1;
    }

    hsm_key_info_t *key_info = hsm_get_key_info(NULL, key);
    switch (algo) {
        case LDNS_SIGN_RSAMD5:
        case LDNS_SIGN_RSASHA1:
        case LDNS_SIGN_RSASHA1_NSEC3:
        case LDNS_SIGN_RSASHA256:
        case LDNS_SIGN_RSASHA512:
            if (strcmp(key_info->algorithm_name, "RSA") != 0) {
                printf("Not an RSA key, the key is of algorithm %s.\n", key_info->algorithm_name);
                hsm_key_info_free(key_info);
                free(name);
                free(id);
                return -1;
            }
            break;
        case LDNS_SIGN_DSA:
        case LDNS_SIGN_DSA_NSEC3:
            if (strcmp(key_info->algorithm_name, "DSA") != 0) {
                printf("Not a DSA key, the key is of algorithm %s.\n", key_info->algorithm_name);
                hsm_key_info_free(key_info);
                free(name);
                free(id);
                return -1;
            }
            break;
        case LDNS_SIGN_ECC_GOST:
            if (strcmp(key_info->algorithm_name, "GOST") != 0) {
                printf("Not a GOST key, the key is of algorithm %s.\n", key_info->algorithm_name);
                hsm_key_info_free(key_info);
                free(name);
                free(id);
                return -1;
            }
            break;
/* TODO: We can remove the directive if we require LDNS >= 1.6.13 */
#if !defined LDNS_BUILD_CONFIG_USE_ECDSA || LDNS_BUILD_CONFIG_USE_ECDSA
        case LDNS_SIGN_ECDSAP256SHA256:
            if (strcmp(key_info->algorithm_name, "ECDSA") != 0) {
                printf("Not an ECDSA key, the key is of algorithm %s.\n", key_info->algorithm_name);
                hsm_key_info_free(key_info);
                free(name);
                free(id);
                return -1;
            }
            if (key_info->keysize != 256) {
                printf("The key is a ECDSA/%lu, expecting ECDSA/256 for this algorithm.\n", key_info->keysize);
                hsm_key_info_free(key_info);
                free(name);
                free(id);
                return -1;
            }
            break;
        case LDNS_SIGN_ECDSAP384SHA384:
            if (strcmp(key_info->algorithm_name, "ECDSA") != 0) {
                printf("Not an ECDSA key, the key is of algorithm %s.\n", key_info->algorithm_name);
                hsm_key_info_free(key_info);
                free(name);
                free(id);
                return -1;
            }
            if (key_info->keysize != 384) {
                printf("The key is a ECDSA/%lu, expecting ECDSA/384 for this algorithm.\n", key_info->keysize);
                hsm_key_info_free(key_info);
                free(name);
                free(id);
                return -1;
            }
            break;
#endif
        default:
            printf("Invalid algorithm: %i\n", algo);
            hsm_key_info_free(key_info);
            free(name);
            free(id);
            return -1;
    }
    hsm_key_info_free(key_info);

    sign_params = hsm_sign_params_new();
    sign_params->algorithm = algo;
    sign_params->flags = type;
    sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, name);
    dnskey_rr = hsm_get_dnskey(NULL, key, sign_params);
    sign_params->keytag = ldns_calc_keytag(dnskey_rr);

    ldns_rr_print(stdout, dnskey_rr);

    hsm_sign_params_free(sign_params);
    ldns_rr_free(dnskey_rr);
    hsm_key_free(key);
    free(name);
    free(id);

    return 0;
}
int main (int argc, char **argv) {
    /* Local Vars */
    char            *out = NULL;
    ldns_resolver   *res;
    ldns_rdf        *domain;
    ldns_rdf        *host;
    ldns_rdf        *example;
    ldns_pkt        *pkt;
    ldns_rr         *rr;
    ldns_status     status;

    /* Set signal handling and alarm */
    if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR)
        critical("Setup SIGALRM trap failed!");

    /* Process check arguments */
    if (process_arguments(argc, argv) != OK)
        unknown("Parsing arguments failed!");

    /* Start plugin timeout */
    alarm(mp_timeout);

    // Create DNAME from domainname
    domain = ldns_dname_new_frm_str(domainname);
    if (!domain)
        usage("Invalid domainname '%s'", domainname);

    // Create rdf from hostaddr
    host = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_A, hostname);
#ifdef USE_IPV6
    if (!host)
        host = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_AAAA, hostname);
#endif
    if (!host) {
        ldns_rdf_deep_free(domain);
        usage("Invalid hostname '%s'", hostname);
    }

    // Create DNAME from example.com
    example = ldns_dname_new_frm_str("exmple.com");
    if (!example)
        usage("Invalid domainname 'example.com'");

    // Create resolver
    res = ldns_resolver_new();
    if (!res) {
        ldns_rdf_deep_free(domain);
        ldns_rdf_deep_free(host);
        unknown("Create resolver failed.");
    }
    // Add ns to resolver
    status = ldns_resolver_push_nameserver(res, host);
    if (status != LDNS_STATUS_OK) {
        ldns_rdf_deep_free(domain);
        ldns_rdf_deep_free(host);
        ldns_resolver_deep_free(res);
        unknown("Adding %s as NS fails.", domainname);
    }

    if (udp) {
        // Disable TCP
        ldns_resolver_set_usevc(res, 0);

        // Fetch SOA
        pkt = mp_ldns_resolver_query(res, domain, LDNS_RR_TYPE_SOA,
                                  LDNS_RR_CLASS_IN, 0);
        if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) {
            mp_strcat_comma(&out, "No UDP Answer");
        } else if (ldns_pkt_aa(pkt) == 0) {
            mp_strcat_comma(&out, "Non Authoritative UDP Answer");
        }
        if (mp_verbose > 2) {
            printf("[ SOA Answer ]----------\n");
            ldns_pkt_print(stdout,pkt);
        }
        ldns_pkt_free(pkt);

        if (recursion) {
            // Fetch example.com SOA
            ldns_resolver_set_recursive(res, TRUE);
            pkt = mp_ldns_resolver_query(res, example, LDNS_RR_TYPE_SOA,
                    LDNS_RR_CLASS_IN, LDNS_RD);
            ldns_resolver_set_recursive(res, FALSE);
            if (pkt && (ldns_pkt_get_rcode(pkt) != LDNS_RCODE_REFUSED &&
                    ldns_pkt_get_rcode(pkt) != LDNS_RCODE_SERVFAIL)) {
                mp_strcat_comma(&out, "Recursive UDP Answer");
            }
            if (mp_verbose > 2) {
                printf("[ SOA Answer ]----------\n");
                ldns_pkt_print(stdout,pkt);
            }
            ldns_pkt_free(pkt);
        }
    }

    if (tcp) {
        // Enable TCP
        ldns_resolver_set_usevc(res, 1);

        // Fetch SOA
        pkt = mp_ldns_resolver_query(res, domain, LDNS_RR_TYPE_SOA,
                                  LDNS_RR_CLASS_IN, 0);
        if (pkt == NULL || ldns_pkt_get_rcode(pkt) != LDNS_RCODE_NOERROR) {
            mp_strcat_comma(&out, "No TCP Answer");
        } else if (ldns_pkt_aa(pkt) == 0) {
            mp_strcat_comma(&out, "Non Authoritative TCP Answer");
        }
        if (mp_verbose > 2) {
            printf("[ SOA Answer ]----------\n");
            ldns_pkt_print(stdout,pkt);
        }
        ldns_pkt_free(pkt);

        if (recursion) {
            // Fetch example.com SOA
            ldns_resolver_set_recursive(res, TRUE);
            pkt = mp_ldns_resolver_query(res, example, LDNS_RR_TYPE_SOA,
                    LDNS_RR_CLASS_IN, LDNS_RD);
            ldns_resolver_set_recursive(res, FALSE);
            if (pkt && (ldns_pkt_get_rcode(pkt) != LDNS_RCODE_REFUSED &&
                    ldns_pkt_get_rcode(pkt) != LDNS_RCODE_SERVFAIL)) {
                mp_strcat_comma(&out, "Recursive TCP Answer");
            }
            if (mp_verbose > 2) {
                printf("[ SOA Answer ]----------\n");
                ldns_pkt_print(stdout,pkt);
            }
            ldns_pkt_free(pkt);
        }
    }

    if (axfr) {
        status = ldns_axfr_start(res, domain, LDNS_RR_CLASS_IN);
        if (status == LDNS_STATUS_OK) {
            rr = NULL;
            rr = ldns_axfr_next(res);
            if (rr) {
                mp_strcat_comma(&out, "AXFR allowed.");
            }
        }
    }

    if (out)
        critical("Authoritative DNS for %s: %s", domainname, out);

    ok("Authoritative DNS for %s", domainname);
}