Exemple #1
0
/*
 * Export the fingerprint of a key as a DNS resource record
 */
int
export_dns_rr(const char *hostname, const Key *key, FILE *f, int generic)
{
	u_int8_t rdata_pubkey_algorithm = 0;
	u_int8_t rdata_digest_type = SSHFP_HASH_SHA1;
	u_char *rdata_digest;
	u_int rdata_digest_len;

	int i;
	int success = 0;

	if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
			 &rdata_digest, &rdata_digest_len, key)) {

		if (generic)
			fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", hostname,
			    DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len,
			    rdata_pubkey_algorithm, rdata_digest_type);
		else
			fprintf(f, "%s IN SSHFP %d %d ", hostname,
			    rdata_pubkey_algorithm, rdata_digest_type);

		for (i = 0; i < rdata_digest_len; i++)
			fprintf(f, "%02x", rdata_digest[i]);
		fprintf(f, "\n");
		success = 1;
	} else {
		error("dns_export_rr: unsupported algorithm");
	}

	return success;
}
Exemple #2
0
/*
 * Export the fingerprint of a key as a DNS resource record
 */
int
export_dns_rr(const char *hostname, struct sshkey *key, FILE *f, int generic)
{
    u_int8_t rdata_pubkey_algorithm = 0;
    u_int8_t rdata_digest_type = SSHFP_HASH_RESERVED;
    u_int8_t dtype;
    u_char *rdata_digest;
    size_t i, rdata_digest_len;
    int success = 0;

    for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) {
        rdata_digest_type = dtype;
        if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
                         &rdata_digest, &rdata_digest_len, key)) {
            if (generic) {
                fprintf(f, "%s IN TYPE%d \\# %zu %02x %02x ",
                        hostname, DNS_RDATATYPE_SSHFP,
                        2 + rdata_digest_len,
                        rdata_pubkey_algorithm, rdata_digest_type);
            } else {
                fprintf(f, "%s IN SSHFP %d %d ", hostname,
                        rdata_pubkey_algorithm, rdata_digest_type);
            }
            for (i = 0; i < rdata_digest_len; i++)
                fprintf(f, "%02x", rdata_digest[i]);
            fprintf(f, "\n");
            free(rdata_digest); /* from sshkey_fingerprint_raw() */
            success = 1;
        }
    }

    /* No SSHFP record was generated at all */
    if (success == 0) {
        error("%s: unsupported algorithm and/or digest_type", __func__);
    }

    return success;
}
Exemple #3
0
/*
 * Verify the given hostname, address and host key using DNS.
 * Returns 0 if lookup succeeds, -1 otherwise
 */
int
verify_host_key_dns(const char *hostname, struct sockaddr *address,
    const Key *hostkey, int *flags)
{
	int counter;
	int result;
	struct rrsetinfo *fingerprints = NULL;

	u_int8_t hostkey_algorithm;
	u_int8_t hostkey_digest_type;
	u_char *hostkey_digest;
	u_int hostkey_digest_len;

	u_int8_t dnskey_algorithm;
	u_int8_t dnskey_digest_type;
	u_char *dnskey_digest;
	u_int dnskey_digest_len;

	*flags = 0;

	debug3("verify_hostkey_dns");
	if (hostkey == NULL)
		fatal("No key to look up!");

	result = getrrsetbyname(hostname, DNS_RDATACLASS_IN,
	    DNS_RDATATYPE_SSHFP, 0, &fingerprints);
	if (result) {
		verbose("DNS lookup error: %s", dns_result_totext(result));
		return -1;
	}

	if (fingerprints->rri_flags & RRSET_VALIDATED) {
		*flags |= DNS_VERIFY_SECURE;
		debug("found %d secure fingerprints in DNS",
		    fingerprints->rri_nrdatas);
	} else {
		debug("found %d insecure fingerprints in DNS",
		    fingerprints->rri_nrdatas);
	}

	/* Initialize host key parameters */
	if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type,
	    &hostkey_digest, &hostkey_digest_len, hostkey)) {
		error("Error calculating host key fingerprint.");
		freerrset(fingerprints);
		return -1;
	}

	if (fingerprints->rri_nrdatas)
		*flags |= DNS_VERIFY_FOUND;

	for (counter = 0 ; counter < fingerprints->rri_nrdatas ; counter++)  {
		/*
		 * Extract the key from the answer. Ignore any badly
		 * formatted fingerprints.
		 */
		if (!dns_read_rdata(&dnskey_algorithm, &dnskey_digest_type,
		    &dnskey_digest, &dnskey_digest_len,
		    fingerprints->rri_rdatas[counter].rdi_data,
		    fingerprints->rri_rdatas[counter].rdi_length)) {
			verbose("Error parsing fingerprint from DNS.");
			continue;
		}

		/* Check if the current key is the same as the given key */
		if (hostkey_algorithm == dnskey_algorithm &&
		    hostkey_digest_type == dnskey_digest_type) {

			if (hostkey_digest_len == dnskey_digest_len &&
			    memcmp(hostkey_digest, dnskey_digest,
			    hostkey_digest_len) == 0) {

				*flags |= DNS_VERIFY_MATCH;
			}
		}
	}

	freerrset(fingerprints);

	if (*flags & DNS_VERIFY_FOUND)
		if (*flags & DNS_VERIFY_MATCH)
			debug("matching host key fingerprint found in DNS");
		else
			debug("mismatching host key fingerprint found in DNS");
	else
		debug("no host key fingerprint found in DNS");

	return 0;
}
Exemple #4
0
/*
 * Verify the given hostname, address and host key using DNS.
 * Returns 0 if lookup succeeds, -1 otherwise
 */
int
verify_host_key_dns(const char *hostname, struct sockaddr *address,
    struct sshkey *hostkey, int *flags)
{
	u_int counter;
	int result;
	unsigned int rrset_flags = 0;
	struct rrsetinfo *fingerprints = NULL;

	u_int8_t hostkey_algorithm;
	u_int8_t hostkey_digest_type = SSHFP_HASH_RESERVED;
	u_char *hostkey_digest;
	size_t hostkey_digest_len;

	u_int8_t dnskey_algorithm;
	u_int8_t dnskey_digest_type;
	u_char *dnskey_digest;
	size_t dnskey_digest_len;

	*flags = 0;

	debug3("verify_host_key_dns");
	if (hostkey == NULL)
		fatal("No key to look up!");

	if (is_numeric_hostname(hostname)) {
		debug("skipped DNS lookup for numerical hostname");
		return -1;
	}

	/*
	 * Original getrrsetbyname function, found on OpenBSD for example,
	 * doesn't accept any flag and prerequisite for obtaining AD bit in
	 * DNS response is set by "options edns0" in resolv.conf.
	 *
	 * Our version is more clever and use RRSET_FORCE_EDNS0 flag.
	 */
#ifndef HAVE_GETRRSETBYNAME
	rrset_flags |= RRSET_FORCE_EDNS0;
#endif
	result = getrrsetbyname(hostname, DNS_RDATACLASS_IN,
	    DNS_RDATATYPE_SSHFP, rrset_flags, &fingerprints);

	if (result) {
		verbose("DNS lookup error: %s", dns_result_totext(result));
		return -1;
	}

	if (fingerprints->rri_flags & RRSET_VALIDATED) {
		*flags |= DNS_VERIFY_SECURE;
		debug("found %d secure fingerprints in DNS",
		    fingerprints->rri_nrdatas);
	} else {
		debug("found %d insecure fingerprints in DNS",
		    fingerprints->rri_nrdatas);
	}

	/* Initialize default host key parameters */
	if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type,
	    &hostkey_digest, &hostkey_digest_len, hostkey)) {
		error("Error calculating host key fingerprint.");
		freerrset(fingerprints);
		return -1;
	}

	if (fingerprints->rri_nrdatas)
		*flags |= DNS_VERIFY_FOUND;

	for (counter = 0; counter < fingerprints->rri_nrdatas; counter++) {
		/*
		 * Extract the key from the answer. Ignore any badly
		 * formatted fingerprints.
		 */
		if (!dns_read_rdata(&dnskey_algorithm, &dnskey_digest_type,
		    &dnskey_digest, &dnskey_digest_len,
		    fingerprints->rri_rdatas[counter].rdi_data,
		    fingerprints->rri_rdatas[counter].rdi_length)) {
			verbose("Error parsing fingerprint from DNS.");
			continue;
		}

		if (hostkey_digest_type != dnskey_digest_type) {
			hostkey_digest_type = dnskey_digest_type;
			free(hostkey_digest);

			/* Initialize host key parameters */
			if (!dns_read_key(&hostkey_algorithm,
			    &hostkey_digest_type, &hostkey_digest,
			    &hostkey_digest_len, hostkey)) {
				error("Error calculating key fingerprint.");
				freerrset(fingerprints);
				return -1;
			}
		}

		/* Check if the current key is the same as the given key */
		if (hostkey_algorithm == dnskey_algorithm &&
		    hostkey_digest_type == dnskey_digest_type) {
			if (hostkey_digest_len == dnskey_digest_len &&
			    timingsafe_bcmp(hostkey_digest, dnskey_digest,
			    hostkey_digest_len) == 0)
				*flags |= DNS_VERIFY_MATCH;
		}
		free(dnskey_digest);
	}

	free(hostkey_digest); /* from sshkey_fingerprint_raw() */
	freerrset(fingerprints);

	if (*flags & DNS_VERIFY_FOUND)
		if (*flags & DNS_VERIFY_MATCH)
			debug("matching host key fingerprint found in DNS");
		else
			debug("mismatching host key fingerprint found in DNS");
	else
		debug("no host key fingerprint found in DNS");

	return 0;
}