hashing and pkey signing working
This commit is contained in:
parent
889f7993bc
commit
f0792d77a0
1
.coveralls.yml
Normal file
1
.coveralls.yml
Normal file
@ -0,0 +1 @@
|
||||
repo_token: 0fXi81cx3Khi8g0Q0mGqsABePoEdJfMcf
|
@ -6,3 +6,9 @@ rust:
|
||||
matrix:
|
||||
allow_failure:
|
||||
- rust: nightly
|
||||
after_success: |
|
||||
sudo apt-get install libcurl4-openssl-dev libelf-dev libdw-dev &&
|
||||
wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz &&
|
||||
tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build && cmake .. && make &&
|
||||
sudo make install && cd ../.. &&
|
||||
kcov --coveralls-id=$TRAVIS_JOB_ID --exclude-pattern=/.cargo target/kcov target/debug/trust-dns-*
|
||||
|
73
Cargo.lock
generated
73
Cargo.lock
generated
@ -1,11 +1,12 @@
|
||||
[root]
|
||||
name = "trust-dns"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"chrono 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"docopt 0.6.73 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -32,6 +33,11 @@ name = "bitflags"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "0.2.11"
|
||||
@ -64,6 +70,15 @@ dependencies = [
|
||||
"strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.1.4"
|
||||
@ -73,11 +88,24 @@ dependencies = [
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libressl-pnacl-sys"
|
||||
version = "2.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"pnacl-build-helper 1.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.3.2"
|
||||
@ -126,6 +154,41 @@ dependencies = [
|
||||
"rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"openssl-sys 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pkg-config 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "pnacl-build-helper"
|
||||
version = "1.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.3.11"
|
||||
@ -166,6 +229,14 @@ name = "strsim"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "tempdir"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.32"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "trust-dns"
|
||||
version = "0.4.0"
|
||||
version = "0.4.1"
|
||||
authors = ["Benjamin Fry <benjaminfry@me.com>"]
|
||||
|
||||
# A short blurb about the package. This is not rendered in any format when
|
||||
@ -68,3 +68,4 @@ docopt = "^0.6.72"
|
||||
mio = "^0.4.3"
|
||||
toml = "^0.1.22"
|
||||
chrono = "^0.2.16"
|
||||
openssl = "^0.6.7"
|
||||
|
41
README.md
41
README.md
@ -1,4 +1,7 @@
|
||||
# trust-dns [![Build Status](https://travis-ci.org/bluejekyll/trust-dns.svg?branch=master)](https://travis-ci.org/bluejekyll/trust-dns)
|
||||
# trust-dns
|
||||
[![Build Status](https://travis-ci.org/bluejekyll/trust-dns.svg?branch=master)](https://travis-ci.org/bluejekyll/trust-dns)
|
||||
[![Coverage Status](https://coveralls.io/repos/bluejekyll/trust-dns/badge.svg?branch=master&service=github)](https://coveralls.io/github/bluejekyll/trust-dns?branch=master)
|
||||
[![](http://meritbadge.herokuapp.com/trust-dns)](https://crates.io/crates/trust-dns)
|
||||
A Rust based DNS client and server, built to be safe and secure from the
|
||||
ground up.
|
||||
|
||||
@ -19,28 +22,46 @@ WARNING!!! Under active development!
|
||||
The client now supports timeouts (thanks mio!). Currently hardcoded to 5 seconds,
|
||||
I'll make this configurable if people ask for that, but this allows me to move on.
|
||||
|
||||
The server code is complete, the daemon currently only supports IPv4. Master file
|
||||
parsing is complete and supported. There is currently no forking option, and
|
||||
the server is not yet threaded.
|
||||
The server code is complete, the daemon supports IPv4 and IPv6, UDP and TCP.
|
||||
There currently is no way to limit TCP and AXFR operations, so it is still not
|
||||
recommended to put into production as TCP can be used to DOS the service.
|
||||
Master file parsing is complete and supported. There is currently no forking
|
||||
option, and the server is not yet threaded.
|
||||
|
||||
## RFC's implemented
|
||||
|
||||
### Basic operations
|
||||
- [RFC 1035](https://tools.ietf.org/html/rfc1035): Base DNS spec (partial, caching not yet supported)
|
||||
- [RFC 3596](https://tools.ietf.org/html/rfc3596): IPv6
|
||||
- [RFC 2782](https://tools.ietf.org/html/rfc2782): Service location
|
||||
|
||||
### Update operations
|
||||
- [RFC 2136](https://tools.ietf.org/html/rfc2136): Dynamic Update
|
||||
|
||||
## RFC's in progress or not yet implemented
|
||||
|
||||
### Basic operations
|
||||
- [RFC 2308](https://tools.ietf.org/html/rfc2308): Negative Caching of DNS Queries
|
||||
- [RFC 2317](https://tools.ietf.org/html/rfc2317): Classless IN-ADDR.ARPA delegation
|
||||
- [RFC 6891](https://tools.ietf.org/html/rfc6891): Extension Mechanisms for DNS
|
||||
|
||||
### Update operations
|
||||
- [RFC 1995](https://tools.ietf.org/html/rfc1995): Incremental Zone Transfer
|
||||
- [RFC 1996](https://tools.ietf.org/html/rfc1996): Notify slaves of update
|
||||
- [RFC 2782](https://tools.ietf.org/html/rfc2782): Service location
|
||||
- [RFC 3007](https://tools.ietf.org/html/rfc3007): Secure Dynamic Update
|
||||
- [RFC 6891](https://tools.ietf.org/html/rfc6891): Extension Mechanisms for DNS
|
||||
- [RFC 4034](https://tools.ietf.org/html/rfc4034): DNSSEC Resource Records
|
||||
- [DNSCrypt](https://dnscrypt.org): Trusted DNS queries
|
||||
- [Update Leases](https://tools.ietf.org/html/draft-sekar-dns-ul-01): Dynamic DNS Update Leases
|
||||
- [Long-Lived Queries](http://tools.ietf.org/html/draft-sekar-dns-llq-01): Notify with bells
|
||||
|
||||
### Secure DNS operations
|
||||
- [RFC 3007](https://tools.ietf.org/html/rfc3007): Secure Dynamic Update
|
||||
- [RFC 4034](https://tools.ietf.org/html/rfc4034): DNSSEC Resource Records
|
||||
- [RFC 4035](https://tools.ietf.org/html/rfc4035): Protocol Modifications for DNSSEC
|
||||
- [RFC 4509](https://tools.ietf.org/html/rfc4509): SHA-256 in DNSSEC Delegation Signer
|
||||
- [RFC 5155](https://tools.ietf.org/html/rfc5155): DNSSEC Hashed Authenticated Denial of Existence
|
||||
- [RFC 5702](https://tools.ietf.org/html/rfc5702): SHA-2 Algorithms with RSA in DNSKEY and RRSIG for DNSSEC
|
||||
- [RFC 6840](https://tools.ietf.org/html/rfc6840): Clarifications and Implementation Notes for DNSSEC
|
||||
- [RFC 6944](https://tools.ietf.org/html/rfc6944): DNSKEY Algorithm Implementation Status
|
||||
- [DNSCrypt](https://dnscrypt.org): Trusted DNS queries
|
||||
|
||||
# Usage
|
||||
|
||||
This assumes that you have [Rust](https://www.rust-lang.org) stable installed. These
|
||||
@ -94,6 +115,6 @@ so this should allow it to work with most internal loads.
|
||||
|
||||
- Why are you building another DNS server?
|
||||
|
||||
Because I've gotten tired of seeing the security advisories out there for BIND.
|
||||
Because of all the security advisories out there for BIND.
|
||||
Using Rust semantics it should be possible to develop a high performance and
|
||||
safe DNS Server that is more resilient to attacks.
|
||||
|
@ -248,7 +248,9 @@ impl Authority {
|
||||
* if (local option)
|
||||
* return (REFUSED)
|
||||
*/
|
||||
fn authorize(&self) -> UpdateResult<()> {
|
||||
fn authorize(&self/*, update_message: &UpdateMessage*/) -> UpdateResult<()> {
|
||||
//
|
||||
|
||||
if !self.allow_update {
|
||||
warn!("update attempted on non-updatable Authority: {}", self.origin);
|
||||
Err(ResponseCode::Refused)
|
||||
|
@ -25,6 +25,7 @@ pub enum DecodeError {
|
||||
UnknownDnsClassStr(String),
|
||||
UnknownRecordTypeValue(u16),
|
||||
UnknownRecordTypeStr(String),
|
||||
UnknownAlgorithmTypeValue(u8),
|
||||
NoRecordDataType,
|
||||
NoRecordDataLength,
|
||||
EOF,
|
||||
@ -38,6 +39,7 @@ impl fmt::Display for DecodeError {
|
||||
DecodeError::UnknownDnsClassStr(ref val) => write!(f, "DnsClass string unknown: {}", val),
|
||||
DecodeError::UnknownRecordTypeValue(ref val) => write!(f, "RecordType value unknown: {}", val),
|
||||
DecodeError::UnknownRecordTypeStr(ref val) => write!(f, "RecordType string unknown: {}", val),
|
||||
DecodeError::UnknownAlgorithmTypeValue(ref val) => write!(f, "AlgorithmType value unknown: {}", val),
|
||||
DecodeError::NoRecordDataType => write!(f, "There was no record data type specified"),
|
||||
DecodeError::NoRecordDataLength => write!(f, "There was no record data length specified"),
|
||||
DecodeError::EOF => write!(f, "End of input reached before next read could complete"),
|
||||
@ -53,6 +55,7 @@ impl Error for DecodeError {
|
||||
DecodeError::UnknownDnsClassStr(..) => "DnsClass string unknown",
|
||||
DecodeError::UnknownRecordTypeValue(..) => "RecordType value unknown",
|
||||
DecodeError::UnknownRecordTypeStr(..) => "RecordType string unknown",
|
||||
DecodeError::UnknownAlgorithmTypeValue(..) => "AlgorithmType value unknown",
|
||||
DecodeError::NoRecordDataType => "RecordType unspecified",
|
||||
DecodeError::NoRecordDataLength => "RecordData length unspecified",
|
||||
DecodeError::EOF => "End of input",
|
||||
|
@ -18,6 +18,7 @@ extern crate mio;
|
||||
extern crate toml;
|
||||
extern crate rustc_serialize;
|
||||
extern crate chrono;
|
||||
extern crate openssl;
|
||||
|
||||
pub mod logger;
|
||||
pub mod rr;
|
||||
|
229
src/rr/dnssec/algorithm.rs
Normal file
229
src/rr/dnssec/algorithm.rs
Normal file
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
use std::convert::Into;
|
||||
|
||||
use openssl::crypto::pkey;
|
||||
use openssl::crypto::hash;
|
||||
|
||||
use ::serialize::binary::*;
|
||||
use ::error::*;
|
||||
|
||||
// RFC 6944 DNSSEC DNSKEY Algorithm Status April 2013
|
||||
//
|
||||
// 2.2. Algorithm Implementation Status Assignment Rationale
|
||||
//
|
||||
// RSASHA1 has an implementation status of Must Implement, consistent
|
||||
// with [RFC4034]. RSAMD5 has an implementation status of Must Not
|
||||
// Implement because of known weaknesses in MD5.
|
||||
//
|
||||
// The status of RSASHA1-NSEC3-SHA1 is set to Recommended to Implement
|
||||
// as many deployments use NSEC3. The status of RSA/SHA-256 and RSA/
|
||||
// SHA-512 are also set to Recommended to Implement as major deployments
|
||||
// (such as the root zone) use these algorithms [ROOTDPS]. It is
|
||||
// believed that RSA/SHA-256 or RSA/SHA-512 algorithms will replace
|
||||
// older algorithms (e.g., RSA/SHA-1) that have a perceived weakness.
|
||||
//
|
||||
// Likewise, ECDSA with the two identified curves (ECDSAP256SHA256 and
|
||||
// ECDSAP384SHA384) is an algorithm that may see widespread use due to
|
||||
// the perceived similar level of security offered with smaller key size
|
||||
// compared to the key sizes of algorithms such as RSA. Therefore,
|
||||
// ECDSAP256SHA256 and ECDSAP384SHA384 are Recommended to Implement.
|
||||
//
|
||||
// All other algorithms used in DNSSEC specified without an
|
||||
// implementation status are currently set to Optional.
|
||||
//
|
||||
// 2.3. DNSSEC Implementation Status Table
|
||||
//
|
||||
// The DNSSEC algorithm implementation status table is listed below.
|
||||
// Only the algorithms already specified for use with DNSSEC at the time
|
||||
// of writing are listed.
|
||||
//
|
||||
// +------------+------------+-------------------+-------------------+
|
||||
// | Must | Must Not | Recommended | Optional |
|
||||
// | Implement | Implement | to Implement | |
|
||||
// +------------+------------+-------------------+-------------------+
|
||||
// | | | | |
|
||||
// | RSASHA1 | RSAMD5 | RSASHA256 | Any |
|
||||
// | | | RSASHA1-NSEC3 | registered |
|
||||
// | | | -SHA1 | algorithm |
|
||||
// | | | RSASHA512 | not listed in |
|
||||
// | | | ECDSAP256SHA256 | this table |
|
||||
// | | | ECDSAP384SHA384 | |
|
||||
// +------------+------------+-------------------+-------------------+
|
||||
//
|
||||
// This table does not list the Reserved values in the IANA registry
|
||||
// table or the values for INDIRECT (252), PRIVATE (253), and PRIVATEOID
|
||||
// (254). These values may relate to more than one algorithm and are
|
||||
// therefore up to the implementer's discretion. As noted, any
|
||||
// algorithm not listed in the table is Optional. As of this writing,
|
||||
// the Optional algorithms are DSASHA1, DH, DSA-NSEC3-SHA1, and GOST-
|
||||
// ECC, but in general, anything not explicitly listed is Optional.
|
||||
//
|
||||
// 2.4. Specifying New Algorithms and Updating the Status of Existing
|
||||
// Entries
|
||||
//
|
||||
// [RFC6014] establishes a parallel procedure for adding a registry
|
||||
// entry for a new algorithm other than a standards track document.
|
||||
// Because any algorithm not listed in the foregoing table is Optional,
|
||||
// algorithms entered into the registry using the [RFC6014] procedure
|
||||
// are automatically Optional.
|
||||
//
|
||||
// It has turned out to be useful for implementations to refer to a
|
||||
// single document that specifies the implementation status of every
|
||||
// algorithm. Accordingly, when a new algorithm is to be registered
|
||||
// with a status other than Optional, this document shall be made
|
||||
// obsolete by a new document that adds the new algorithm to the table
|
||||
// in Section 2.3. Similarly, if the status of any algorithm in the
|
||||
// table in Section 2.3 changes, a new document shall make this document
|
||||
// obsolete; that document shall include a replacement of the table in
|
||||
// Section 2.3. This way, the goal of having one authoritative document
|
||||
// to specify all the status values is achieved.
|
||||
//
|
||||
// This document cannot be updated, only made obsolete and replaced by a
|
||||
// successor document.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||
pub enum Algorithm {
|
||||
/// DO NOT USE, SHA1 is a compromised hashing function, it is here for backward compatability
|
||||
RSASHA1,
|
||||
RSASHA256,
|
||||
/// DO NOT USE, SHA1 is a compromised hashing function, it is here for backward compatability
|
||||
RSASHA1_NSEC3_SHA1,
|
||||
RSASHA512,
|
||||
// ECDSAP256SHA256, // not yet supported
|
||||
// ECDSAP384SHA384,
|
||||
}
|
||||
|
||||
impl Algorithm {
|
||||
pub fn get_hash_type(self) -> hash::Type {
|
||||
match self {
|
||||
Algorithm::RSASHA1 | Algorithm::RSASHA1_NSEC3_SHA1 => hash::Type::SHA1,
|
||||
Algorithm::RSASHA256 => hash::Type::SHA256,
|
||||
Algorithm::RSASHA512 => hash::Type::SHA512,
|
||||
// Algorithm::ECDSAP256SHA256 => hash::Type::SHA256,
|
||||
// Algorithm::ECDSAP384SHA384 => hash::Type::SHA384,
|
||||
}
|
||||
}
|
||||
|
||||
fn hash(&self, data: &[u8]) -> Vec<u8> {
|
||||
hash::hash(self.get_hash_type(), data)
|
||||
}
|
||||
|
||||
pub fn sign(&self, private_key: &pkey::PKey, data: &[u8]) -> Vec<u8> {
|
||||
if !private_key.can(pkey::Role::Sign) { panic!("This key cannot be used for signing") }
|
||||
|
||||
// calculate the hash...
|
||||
let hash = self.hash(data);
|
||||
|
||||
// then sign and return
|
||||
private_key.sign(&hash)
|
||||
}
|
||||
|
||||
pub fn verify(&self, public_key: &pkey::PKey, data: &[u8], signature: &[u8]) -> bool {
|
||||
if !public_key.can(pkey::Role::Verify) { panic!("This key cannot be used to verify signature") }
|
||||
|
||||
// calculate the hash on the local data
|
||||
let hash = self.hash(data);
|
||||
|
||||
// verify the remotely sent signature
|
||||
public_key.verify(&hash, signature)
|
||||
}
|
||||
|
||||
/// http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
|
||||
pub fn from_u8(value: u8) -> DecodeResult<Self> {
|
||||
match value {
|
||||
5 => Ok(Algorithm::RSASHA1),
|
||||
7 => Ok(Algorithm::RSASHA1_NSEC3_SHA1),
|
||||
8 => Ok(Algorithm::RSASHA256),
|
||||
10 => Ok(Algorithm::RSASHA512),
|
||||
// 13 => Algorithm::ECDSAP256SHA256,
|
||||
// 14 => Algorithm::ECDSAP384SHA384,
|
||||
_ => Err(DecodeError::UnknownAlgorithmTypeValue(value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BinSerializable<Algorithm> for Algorithm {
|
||||
// http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
|
||||
fn read(decoder: &mut BinDecoder) -> DecodeResult<Algorithm> {
|
||||
let algorithm_id = try!(decoder.read_u8());
|
||||
Algorithm::from_u8(algorithm_id)
|
||||
}
|
||||
|
||||
fn emit(&self, encoder: &mut BinEncoder) -> EncodeResult {
|
||||
encoder.emit(u8::from(*self))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&'static str> for Algorithm {
|
||||
fn from(s: &'static str) -> Algorithm {
|
||||
match s {
|
||||
"RSASHA1" => Algorithm::RSASHA1,
|
||||
"RSASHA256" => Algorithm::RSASHA256,
|
||||
"RSASHA1-NSEC3-SHA1" => Algorithm::RSASHA1_NSEC3_SHA1,
|
||||
"RSASHA512" => Algorithm::RSASHA512,
|
||||
// "ECDSAP256SHA256" => Algorithm::ECDSAP256SHA256,
|
||||
// "ECDSAP384SHA384" => Algorithm::ECDSAP384SHA384,
|
||||
_ => panic!("unrecognized string {}", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Algorithm> for &'static str {
|
||||
fn from(a: Algorithm) -> &'static str {
|
||||
match a {
|
||||
Algorithm::RSASHA1 => "RSASHA1",
|
||||
Algorithm::RSASHA256 => "RSASHA256",
|
||||
Algorithm::RSASHA1_NSEC3_SHA1 => "RSASHA1-NSEC3-SHA1",
|
||||
Algorithm::RSASHA512 => "RSASHA512",
|
||||
// ECDSAP256SHA256 => "ECDSAP256SHA256",
|
||||
// ECDSAP384SHA384 => "ECDSAP384SHA384",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Algorithm> for u8 {
|
||||
fn from(a: Algorithm) -> u8 {
|
||||
match a {
|
||||
Algorithm::RSASHA1 => 5,
|
||||
Algorithm::RSASHA256 => 7,
|
||||
Algorithm::RSASHA1_NSEC3_SHA1 => 8,
|
||||
Algorithm::RSASHA512 => 10,
|
||||
// ECDSAP256SHA256 => 13,
|
||||
// ECDSAP384SHA384 => 14,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::Algorithm;
|
||||
use openssl::crypto::pkey;
|
||||
|
||||
#[test]
|
||||
fn test_hashing() {
|
||||
let bytes = b"www.example.com";
|
||||
let mut pkey = pkey::PKey::new();
|
||||
pkey.gen(2048);
|
||||
|
||||
for algorithm in &[Algorithm::RSASHA1,
|
||||
Algorithm::RSASHA256,
|
||||
Algorithm::RSASHA1_NSEC3_SHA1,
|
||||
Algorithm::RSASHA512] {
|
||||
let sig = algorithm.sign(&pkey, bytes);
|
||||
assert!(algorithm.verify(&pkey, bytes, &sig));
|
||||
}
|
||||
}
|
||||
}
|
18
src/rr/dnssec/mod.rs
Normal file
18
src/rr/dnssec/mod.rs
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
mod algorithm;
|
||||
|
||||
pub use self::algorithm::Algorithm;
|
@ -19,6 +19,7 @@ pub mod resource;
|
||||
pub mod record_data;
|
||||
pub mod domain;
|
||||
mod rdata;
|
||||
mod dnssec;
|
||||
|
||||
pub use self::record_type::RecordType;
|
||||
pub use self::resource::Record;
|
||||
|
@ -17,13 +17,14 @@
|
||||
// TODO: these should each be it's own struct, it would make parsing and decoding a little cleaner
|
||||
// and also a little more ergonomic when accessing.
|
||||
// each of these module's has the parser for that rdata embedded, to keep the file sizes down...
|
||||
pub mod a;
|
||||
pub mod aaaa;
|
||||
pub mod cname;
|
||||
pub mod mx;
|
||||
pub mod null;
|
||||
pub mod ns;
|
||||
pub mod ptr;
|
||||
pub mod sig;
|
||||
pub mod soa;
|
||||
pub mod srv;
|
||||
pub mod txt;
|
||||
pub mod a;
|
||||
pub mod aaaa;
|
||||
|
259
src/rr/rdata/sig.rs
Normal file
259
src/rr/rdata/sig.rs
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
use ::serialize::txt::*;
|
||||
use ::serialize::binary::*;
|
||||
use ::error::*;
|
||||
use ::rr::record_data::RData;
|
||||
use ::rr::domain::Name;
|
||||
use ::rr::dnssec::Algorithm;
|
||||
|
||||
// RFC 2535 & 2931 DNS Security Extensions March 1999
|
||||
//
|
||||
// NOTE: RFC 2535 was obsoleted with 4034+, with the exception of the
|
||||
// usage for UPDATE, which is what this implementation is for.
|
||||
//
|
||||
// 4.1 SIG RDATA Format
|
||||
//
|
||||
// The RDATA portion of a SIG RR is as shown below. The integrity of
|
||||
// the RDATA information is protected by the signature field.
|
||||
//
|
||||
// 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | type covered | algorithm | labels |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | original TTL |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | signature expiration |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | signature inception |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | key tag | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ signer's name +
|
||||
// | /
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-/
|
||||
// / /
|
||||
// / signature /
|
||||
// / /
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// 4.1.1 Type Covered Field
|
||||
//
|
||||
// The "type covered" is the type of the other RRs covered by this SIG.
|
||||
//
|
||||
// 4.1.2 Algorithm Number Field
|
||||
//
|
||||
// This octet is as described in section 3.2.
|
||||
//
|
||||
// 4.1.3 Labels Field
|
||||
//
|
||||
// The "labels" octet is an unsigned count of how many labels there are
|
||||
// in the original SIG RR owner name not counting the null label for
|
||||
// root and not counting any initial "*" for a wildcard. If a secured
|
||||
// retrieval is the result of wild card substitution, it is necessary
|
||||
// for the resolver to use the original form of the name in verifying
|
||||
// the digital signature. This field makes it easy to determine the
|
||||
// original form.
|
||||
//
|
||||
// If, on retrieval, the RR appears to have a longer name than indicated
|
||||
// by "labels", the resolver can tell it is the result of wildcard
|
||||
// substitution. If the RR owner name appears to be shorter than the
|
||||
// labels count, the SIG RR must be considered corrupt and ignored. The
|
||||
// maximum number of labels allowed in the current DNS is 127 but the
|
||||
// entire octet is reserved and would be required should DNS names ever
|
||||
// be expanded to 255 labels. The following table gives some examples.
|
||||
// The value of "labels" is at the top, the retrieved owner name on the
|
||||
// left, and the table entry is the name to use in signature
|
||||
// verification except that "bad" means the RR is corrupt.
|
||||
//
|
||||
// labels= | 0 | 1 | 2 | 3 | 4 |
|
||||
// --------+-----+------+--------+----------+----------+
|
||||
// .| . | bad | bad | bad | bad |
|
||||
// d.| *. | d. | bad | bad | bad |
|
||||
// c.d.| *. | *.d. | c.d. | bad | bad |
|
||||
// b.c.d.| *. | *.d. | *.c.d. | b.c.d. | bad |
|
||||
// a.b.c.d.| *. | *.d. | *.c.d. | *.b.c.d. | a.b.c.d. |
|
||||
//
|
||||
// 4.1.4 Original TTL Field
|
||||
//
|
||||
// The "original TTL" field is included in the RDATA portion to avoid
|
||||
// (1) authentication problems that caching servers would otherwise
|
||||
// cause by decrementing the real TTL field and (2) security problems
|
||||
// that unscrupulous servers could otherwise cause by manipulating the
|
||||
// real TTL field. This original TTL is protected by the signature
|
||||
// while the current TTL field is not.
|
||||
//
|
||||
// NOTE: The "original TTL" must be restored into the covered RRs when
|
||||
// the signature is verified (see Section 8). This generaly implies
|
||||
// that all RRs for a particular type, name, and class, that is, all the
|
||||
// RRs in any particular RRset, must have the same TTL to start with.
|
||||
//
|
||||
// 4.1.5 Signature Expiration and Inception Fields
|
||||
//
|
||||
// The SIG is valid from the "signature inception" time until the
|
||||
// "signature expiration" time. Both are unsigned numbers of seconds
|
||||
// since the start of 1 January 1970, GMT, ignoring leap seconds. (See
|
||||
// also Section 4.4.) Ring arithmetic is used as for DNS SOA serial
|
||||
// numbers [RFC 1982] which means that these times can never be more
|
||||
// than about 68 years in the past or the future. This means that these
|
||||
// times are ambiguous modulo ~136.09 years. However there is no
|
||||
// security flaw because keys are required to be changed to new random
|
||||
// keys by [RFC 2541] at least every five years. This means that the
|
||||
// probability that the same key is in use N*136.09 years later should
|
||||
// be the same as the probability that a random guess will work.
|
||||
//
|
||||
// A SIG RR may have an expiration time numerically less than the
|
||||
// inception time if the expiration time is near the 32 bit wrap around
|
||||
// point and/or the signature is long lived.
|
||||
//
|
||||
// (To prevent misordering of network requests to update a zone
|
||||
// dynamically, monotonically increasing "signature inception" times may
|
||||
// be necessary.)
|
||||
//
|
||||
// A secure zone must be considered changed for SOA serial number
|
||||
// purposes not only when its data is updated but also when new SIG RRs
|
||||
// are inserted (ie, the zone or any part of it is re-signed).
|
||||
//
|
||||
// 4.1.6 Key Tag Field
|
||||
//
|
||||
// The "key Tag" is a two octet quantity that is used to efficiently
|
||||
// select between multiple keys which may be applicable and thus check
|
||||
// that a public key about to be used for the computationally expensive
|
||||
// effort to check the signature is possibly valid. For algorithm 1
|
||||
// (MD5/RSA) as defined in [RFC 2537], it is the next to the bottom two
|
||||
// octets of the public key modulus needed to decode the signature
|
||||
// field. That is to say, the most significant 16 of the least
|
||||
// significant 24 bits of the modulus in network (big endian) order. For
|
||||
// all other algorithms, including private algorithms, it is calculated
|
||||
// as a simple checksum of the KEY RR as described in Appendix C.
|
||||
//
|
||||
// 4.1.7 Signer's Name Field
|
||||
//
|
||||
// The "signer's name" field is the domain name of the signer generating
|
||||
// the SIG RR. This is the owner name of the public KEY RR that can be
|
||||
// used to verify the signature. It is frequently the zone which
|
||||
// contained the RRset being authenticated. Which signers should be
|
||||
// authorized to sign what is a significant resolver policy question as
|
||||
// discussed in Section 6. The signer's name may be compressed with
|
||||
// standard DNS name compression when being transmitted over the
|
||||
// network.
|
||||
//
|
||||
// 4.1.8 Signature Field
|
||||
//
|
||||
// The actual signature portion of the SIG RR binds the other RDATA
|
||||
// fields to the RRset of the "type covered" RRs with that owner name
|
||||
// and class. This covered RRset is thereby authenticated. To
|
||||
// accomplish this, a data sequence is constructed as follows:
|
||||
//
|
||||
// data = RDATA | RR(s)...
|
||||
//
|
||||
// where "|" is concatenation,
|
||||
//
|
||||
// RDATA is the wire format of all the RDATA fields in the SIG RR itself
|
||||
// (including the canonical form of the signer's name) before but not
|
||||
// including the signature, and
|
||||
//
|
||||
// RR(s) is the RRset of the RR(s) of the type covered with the same
|
||||
// owner name and class as the SIG RR in canonical form and order as
|
||||
// defined in Section 8.
|
||||
//
|
||||
// How this data sequence is processed into the signature is algorithm
|
||||
// dependent. These algorithm dependent formats and procedures are
|
||||
// described in separate documents (Section 3.2).
|
||||
//
|
||||
// SIGs SHOULD NOT be included in a zone for any "meta-type" such as
|
||||
// ANY, AXFR, etc. (but see section 5.6.2 with regard to IXFR).
|
||||
//
|
||||
// SIG { type_covered: u16, algorithm: SecAlgorithm, num_labels: u8, original_ttl: u32,
|
||||
// sig_expiration: u32, sig_inception: u32, key_tag: u16, signer_name: Name, sig: Vec<u8> }
|
||||
pub fn read(decoder: &mut BinDecoder) -> DecodeResult<RData> {
|
||||
// TODO should we verify here? or elsewhere...
|
||||
let type_covered = try!(decoder.read_u16());
|
||||
let algorithm = try!(Algorithm::read(decoder));
|
||||
let num_labels = try!(decoder.read_u8());
|
||||
let original_ttl = try!(decoder.read_u32());
|
||||
let sig_expiration = try!(decoder.read_u32());
|
||||
let sig_inception = try!(decoder.read_u32());
|
||||
let key_tag = try!(decoder.read_u16());
|
||||
let signer_name = try!(Name::read(decoder));
|
||||
let sig = try!(decoder.read_vec(algorithm.get_hash_type().md_len()));
|
||||
|
||||
Ok(RData::SIG {
|
||||
type_covered: type_covered,
|
||||
algorithm: algorithm,
|
||||
num_labels: num_labels,
|
||||
original_ttl: original_ttl,
|
||||
sig_expiration: sig_expiration,
|
||||
sig_inception: sig_expiration,
|
||||
key_tag: key_tag,
|
||||
signer_name: signer_name,
|
||||
sig: sig,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn emit(encoder: &mut BinEncoder, sig: &RData) -> EncodeResult {
|
||||
if let RData::SIG { type_covered, algorithm, num_labels, original_ttl, sig_expiration, sig_inception, key_tag, ref signer_name, ref sig } = *sig {
|
||||
try!(encoder.emit_u16(type_covered));
|
||||
try!(algorithm.emit(encoder));
|
||||
try!(encoder.emit(num_labels));
|
||||
try!(encoder.emit_u32(original_ttl));
|
||||
try!(encoder.emit_u32(sig_expiration));
|
||||
try!(encoder.emit_u32(sig_inception));
|
||||
try!(encoder.emit_u16(key_tag));
|
||||
try!(signer_name.emit(encoder));
|
||||
try!(encoder.emit_vec(sig));
|
||||
Ok(())
|
||||
} else {
|
||||
panic!("wrong type here {:?}", sig);
|
||||
}
|
||||
}
|
||||
|
||||
// VENERA Action\.domains (
|
||||
// 20 ; SERIAL
|
||||
// 7200 ; REFRESH
|
||||
// 600 ; RETRY
|
||||
// 3600000; EXPIRE
|
||||
// 60) ; MINIMUM
|
||||
// pub fn parse(tokens: &Vec<Token>, origin: Option<&Name>) -> ParseResult<RData> {
|
||||
// let mut token = tokens.iter();
|
||||
//
|
||||
// let mname: Name = try!(token.next().ok_or(ParseError::MissingToken("mname".to_string())).and_then(|t| if let &Token::CharData(ref s) = t {Name::parse(s, origin)} else {Err(ParseError::UnexpectedToken(t.clone()))} ));
|
||||
// let rname: Name = try!(token.next().ok_or(ParseError::MissingToken("rname".to_string())).and_then(|t| if let &Token::CharData(ref s) = t {Name::parse(s, origin)} else {Err(ParseError::UnexpectedToken(t.clone()))} ));
|
||||
// let mut list = try!(token.next().ok_or(ParseError::MissingToken("List".to_string())).and_then(|t| if let &Token::List(ref v) = t {Ok(v)} else {Err(ParseError::UnexpectedToken(t.clone()))} )).iter();
|
||||
//
|
||||
// let serial: u32 = try!(list.next().ok_or(ParseError::MissingToken("serial".to_string())).and_then(|s| Ok(try!(s.parse()))));
|
||||
// let refresh: i32 = try!(list.next().ok_or(ParseError::MissingToken("refresh".to_string())).and_then(|s| Ok(try!(s.parse()))));
|
||||
// let retry: i32 = try!(list.next().ok_or(ParseError::MissingToken("retry".to_string())).and_then(|s| Ok(try!(s.parse()))));
|
||||
// let expire: i32 = try!(list.next().ok_or(ParseError::MissingToken("expire".to_string())).and_then(|s| Ok(try!(s.parse()))));
|
||||
// let minimum: u32 = try!(list.next().ok_or(ParseError::MissingToken("minimum".to_string())).and_then(|s| Ok(try!(s.parse()))));
|
||||
//
|
||||
//
|
||||
// // let serial: u32 = try!(token.next().ok_or(ParseError::MissingToken("serial".to_string())).and_then(|t| if let &Token::CharData(ref s) = t {Ok(try!(s.parse()))} else {Err(ParseError::UnexpectedToken(t.clone()))} ));
|
||||
// // let refresh: i32 = try!(token.next().ok_or(ParseError::MissingToken("refresh".to_string())).and_then(|t| if let &Token::CharData(ref s) = t {Ok(try!(s.parse()))} else {Err(ParseError::UnexpectedToken(t.clone()))} ));
|
||||
// // let retry: i32 = try!(token.next().ok_or(ParseError::MissingToken("retry".to_string())).and_then(|t| if let &Token::CharData(ref s) = t {Ok(try!(s.parse()))} else {Err(ParseError::UnexpectedToken(t.clone()))} ));
|
||||
// // let expire: i32 = try!(token.next().ok_or(ParseError::MissingToken("expire".to_string())).and_then(|t| if let &Token::CharData(ref s) = t {Ok(try!(s.parse()))} else {Err(ParseError::UnexpectedToken(t.clone()))} ));
|
||||
// // let minimum: u32 = try!(token.next().ok_or(ParseError::MissingToken("minimum".to_string())).and_then(|t| if let &Token::CharData(ref s) = t {Ok(try!(s.parse()))} else {Err(ParseError::UnexpectedToken(t.clone()))} ));
|
||||
//
|
||||
// Ok(RData::SOA{
|
||||
// mname: mname,
|
||||
// rname: rname,
|
||||
// serial: serial,
|
||||
// refresh: refresh,
|
||||
// retry: retry,
|
||||
// expire: expire,
|
||||
// minimum: minimum,
|
||||
// })
|
||||
// }
|
@ -19,6 +19,7 @@ use std::convert::From;
|
||||
use ::error::*;
|
||||
use ::serialize::binary::*;
|
||||
use ::serialize::txt::*;
|
||||
use ::rr::dnssec::Algorithm;
|
||||
use super::domain::Name;
|
||||
use super::record_type::RecordType;
|
||||
use super::rdata;
|
||||
@ -174,6 +175,30 @@ pub enum RData {
|
||||
// description of the IN-ADDR.ARPA domain for an example.
|
||||
PTR { ptrdname: Name },
|
||||
|
||||
// RFC 2535 & 2931 DNS Security Extensions March 1999
|
||||
//
|
||||
// 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | type covered | algorithm | labels |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | original TTL |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | signature expiration |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | signature inception |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | key tag | |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ signer's name +
|
||||
// | /
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-/
|
||||
// / /
|
||||
// / signature /
|
||||
// / /
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
SIG { type_covered: u16, algorithm: Algorithm, num_labels: u8, original_ttl: u32,
|
||||
sig_expiration: u32, sig_inception: u32, key_tag: u16, signer_name: Name, sig: Vec<u8> },
|
||||
|
||||
// 3.3.13. SOA RDATA format
|
||||
//
|
||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
|
@ -35,8 +35,8 @@ pub enum RecordType {
|
||||
// DHCID, // 49 RFC 4701 DHCP identifier
|
||||
// DLV, // 32769 RFC 4431 DNSSEC Lookaside Validation record
|
||||
// DNAME, // 39 RFC 2672 Delegation Name
|
||||
// DNSKEY, // 48 RFC 4034 DNS Key record
|
||||
// DS, // 43 RFC 4034 Delegation signer
|
||||
DNSKEY, // 48 RFC 4034 DNS Key record: RSASHA256 and RSASHA512, RFC5702
|
||||
DS, // 43 RFC 4034 Delegation signer: RSASHA256 and RSASHA512, RFC5702
|
||||
// HIP, // 55 RFC 5205 Host Identity Protocol
|
||||
// IPSECKEY, // 45 RFC 4025 IPsec Key
|
||||
// KEY, // 25 RFC 2535[3] and RFC 2930[4] Key record
|
||||
@ -47,12 +47,12 @@ pub enum RecordType {
|
||||
NS, // 2 RFC 1035[1] Name server record
|
||||
NULL, // 0 RFC 1035[1] Null server record, for testing
|
||||
// NSEC, // 47 RFC 4034 Next-Secure record
|
||||
// NSEC3, // 50 RFC 5155 NSEC record version 3
|
||||
NSEC3, // 50 RFC 5155 NSEC record version 3
|
||||
// NSEC3PARAM, // 51 RFC 5155 NSEC3 parameters
|
||||
PTR, // 12 RFC 1035[1] Pointer record
|
||||
// RRSIG, // 46 RFC 4034 DNSSEC signature
|
||||
RRSIG, // 46 RFC 4034 DNSSEC signature: RSASHA256 and RSASHA512, RFC5702
|
||||
// RP, // 17 RFC 1183 Responsible person
|
||||
// SIG, // 24 RFC 2535 Signature
|
||||
SIG, // 24 RFC 2535 (2931) Signature, to support 2137 Update
|
||||
SOA, // 6 RFC 1035[1] and RFC 2308[9] Start of [a zone of] authority record
|
||||
SRV, // 33 RFC 2782 Service locator
|
||||
// SSHFP, // 44 RFC 4255 SSH Public Key Fingerprint
|
||||
|
@ -84,15 +84,26 @@ impl<'a> BinDecoder<'a> {
|
||||
let length: u8 = try!(self.pop());
|
||||
|
||||
// TODO once Drain stabalizes on Vec, this should be replaced...
|
||||
let mut label_vec: Vec<u8> = Vec::with_capacity(length as usize);
|
||||
for _ in 0..length as usize {
|
||||
label_vec.push(try!(self.pop()))
|
||||
}
|
||||
let mut label_vec: Vec<u8> = try!(self.read_vec(length as usize));
|
||||
|
||||
// translate bytes to string, then lowercase...
|
||||
Ok(try!(String::from_utf8(label_vec)).to_lowercase())
|
||||
}
|
||||
|
||||
pub fn read_vec(&mut self, len: usize) -> DecodeResult<Vec<u8>> {
|
||||
// TODO once Drain stabalizes on Vec, this should be replaced...
|
||||
let mut vec: Vec<u8> = Vec::with_capacity(len);
|
||||
for _ in 0..len as usize {
|
||||
vec.push(try!(self.pop()))
|
||||
}
|
||||
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
pub fn read_u8(&mut self) -> DecodeResult<u8> {
|
||||
self.pop()
|
||||
}
|
||||
|
||||
/// parses the next 2 bytes into u16. This performs a byte-by-byte manipulation, there
|
||||
/// which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
|
||||
///
|
||||
|
@ -147,4 +147,14 @@ impl<'a> BinEncoder<'a> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn emit_vec(&mut self, data: &[u8]) -> EncodeResult {
|
||||
self.buffer.reserve(data.len());
|
||||
|
||||
for i in data {
|
||||
try!(self.emit(*i));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user