forked from LittleChest/dns-packet
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)
|
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) {
|
const renc = exports.record = function (type) {
|
||||||
switch (type.toUpperCase()) {
|
switch (type.toUpperCase()) {
|
||||||
case 'A': return ra
|
case 'A': return ra
|
||||||
@ -1315,6 +1374,7 @@ const renc = exports.record = function (type) {
|
|||||||
case 'RP': return rrp
|
case 'RP': return rrp
|
||||||
case 'NSEC': return rnsec
|
case 'NSEC': return rnsec
|
||||||
case 'NSEC3': return rnsec3
|
case 'NSEC3': return rnsec3
|
||||||
|
case 'SSHFP': return rsshfp
|
||||||
case 'DS': return rds
|
case 'DS': return rds
|
||||||
}
|
}
|
||||||
return runknown
|
return runknown
|
||||||
|
|||||||
9
test.js
9
test.js
@ -107,6 +107,15 @@ tape('soa', function (t) {
|
|||||||
t.end()
|
t.end()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
tape('sshfp', function (t) {
|
||||||
|
testEncoder(t, packet.sshfp, {
|
||||||
|
algorithm: 1,
|
||||||
|
hash: 1,
|
||||||
|
fingerprint: 'A108C9F834354D5B37AF988141C9294822F5BC00'
|
||||||
|
})
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
tape('a', function (t) {
|
tape('a', function (t) {
|
||||||
testEncoder(t, packet.a, '127.0.0.1')
|
testEncoder(t, packet.a, '127.0.0.1')
|
||||||
t.end()
|
t.end()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user