Implement SSHFP records (#80)
* Add SSHFP record support Use offset since we may receive a full dns packet Account for maximum hash lengths for each hash type fix: don't use the output of `Buffer#copy()`, instead use `Buffer#byteLength` fix: normalize fingerprint string fix: the offset pointer starts out at RDLENGTH fix: account for the `RDLENGTH` field in `rsshfp.decode()` * tests: add test for the SSHFP record type
This commit is contained in:
parent
a5ee7897e2
commit
fab30b2588
60
index.js
60
index.js
@ -1294,6 +1294,65 @@ rds.encodingLength = function (digest) {
|
||||
return 6 + Buffer.byteLength(digest.digest)
|
||||
}
|
||||
|
||||
const rsshfp = exports.sshfp = {}
|
||||
|
||||
rsshfp.getFingerprintLengthForHashType = function getFingerprintLengthForHashType (hashType) {
|
||||
switch (hashType) {
|
||||
case 1: return 20
|
||||
case 2: return 32
|
||||
}
|
||||
}
|
||||
|
||||
rsshfp.encode = function encode (record, buf, offset) {
|
||||
if (!buf) buf = Buffer.alloc(rsshfp.encodingLength(record))
|
||||
if (!offset) offset = 0
|
||||
const oldOffset = offset
|
||||
|
||||
offset += 2 // The function call starts with the offset pointer at the RDLENGTH field, not the RDATA one
|
||||
buf[offset] = record.algorithm
|
||||
offset += 1
|
||||
buf[offset] = record.hash
|
||||
offset += 1
|
||||
|
||||
const fingerprintBuf = Buffer.from(record.fingerprint.toUpperCase(), 'hex')
|
||||
if (fingerprintBuf.length !== rsshfp.getFingerprintLengthForHashType(record.hash)) {
|
||||
throw new Error('Invalid fingerprint length')
|
||||
}
|
||||
fingerprintBuf.copy(buf, offset)
|
||||
offset += fingerprintBuf.byteLength
|
||||
|
||||
rsshfp.encode.bytes = offset - oldOffset
|
||||
buf.writeUInt16BE(rsshfp.encode.bytes - 2, oldOffset)
|
||||
|
||||
return buf
|
||||
}
|
||||
|
||||
rsshfp.encode.bytes = 0
|
||||
|
||||
rsshfp.decode = function decode (buf, offset) {
|
||||
if (!offset) offset = 0
|
||||
const oldOffset = offset
|
||||
|
||||
const record = {}
|
||||
offset += 2 // Account for the RDLENGTH field
|
||||
record.algorithm = buf[offset]
|
||||
offset += 1
|
||||
record.hash = buf[offset]
|
||||
offset += 1
|
||||
|
||||
const fingerprintLength = rsshfp.getFingerprintLengthForHashType(record.hash)
|
||||
record.fingerprint = buf.slice(offset, offset + fingerprintLength).toString('hex').toUpperCase()
|
||||
offset += fingerprintLength
|
||||
rsshfp.decode.bytes = offset - oldOffset
|
||||
return record
|
||||
}
|
||||
|
||||
rsshfp.decode.bytes = 0
|
||||
|
||||
rsshfp.encodingLength = function (record) {
|
||||
return 4 + Buffer.from(record.fingerprint, 'hex').byteLength
|
||||
}
|
||||
|
||||
const renc = exports.record = function (type) {
|
||||
switch (type.toUpperCase()) {
|
||||
case 'A': return ra
|
||||
@ -1315,6 +1374,7 @@ const renc = exports.record = function (type) {
|
||||
case 'RP': return rrp
|
||||
case 'NSEC': return rnsec
|
||||
case 'NSEC3': return rnsec3
|
||||
case 'SSHFP': return rsshfp
|
||||
case 'DS': return rds
|
||||
}
|
||||
return runknown
|
||||
|
||||
9
test.js
9
test.js
@ -107,6 +107,15 @@ tape('soa', function (t) {
|
||||
t.end()
|
||||
})
|
||||
|
||||
tape('sshfp', function (t) {
|
||||
testEncoder(t, packet.sshfp, {
|
||||
algorithm: 1,
|
||||
hash: 1,
|
||||
fingerprint: 'A108C9F834354D5B37AF988141C9294822F5BC00'
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
|
||||
tape('a', function (t) {
|
||||
testEncoder(t, packet.a, '127.0.0.1')
|
||||
t.end()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user