@nictool/dns-resource-record 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codeclimate.yml +25 -0
- package/CHANGELOG.md +253 -0
- package/DEVELOP.md +23 -0
- package/LICENSE +29 -0
- package/README.md +267 -0
- package/index.js +67 -0
- package/lib/tinydns.js +186 -0
- package/package.json +40 -0
- package/rr/a.js +65 -0
- package/rr/aaaa.js +137 -0
- package/rr/caa.js +129 -0
- package/rr/cert.js +75 -0
- package/rr/cname.js +76 -0
- package/rr/dname.js +74 -0
- package/rr/dnskey.js +117 -0
- package/rr/ds.js +104 -0
- package/rr/hinfo.js +84 -0
- package/rr/ipseckey.js +159 -0
- package/rr/key.js +73 -0
- package/rr/loc.js +216 -0
- package/rr/mx.js +86 -0
- package/rr/naptr.js +146 -0
- package/rr/ns.js +74 -0
- package/rr/nsec.js +61 -0
- package/rr/nsec3.js +99 -0
- package/rr/nsec3param.js +84 -0
- package/rr/openpgpkey.js +44 -0
- package/rr/ptr.js +65 -0
- package/rr/rrsig.js +101 -0
- package/rr/sig.js +100 -0
- package/rr/smimea.js +73 -0
- package/rr/soa.js +140 -0
- package/rr/spf.js +54 -0
- package/rr/srv.js +122 -0
- package/rr/sshfp.js +86 -0
- package/rr/tlsa.js +106 -0
- package/rr/txt.js +122 -0
- package/rr/uri.js +95 -0
- package/rr.js +291 -0
- package/test/a.js +76 -0
- package/test/aaaa.js +79 -0
- package/test/base.js +138 -0
- package/test/caa.js +104 -0
- package/test/cert.js +48 -0
- package/test/cname.js +41 -0
- package/test/dname.js +53 -0
- package/test/dnskey.js +44 -0
- package/test/ds.js +44 -0
- package/test/fake.js +26 -0
- package/test/hinfo.js +75 -0
- package/test/ipseckey.js +115 -0
- package/test/key.js +37 -0
- package/test/loc.js +71 -0
- package/test/mx.js +75 -0
- package/test/naptr.js +40 -0
- package/test/ns.js +53 -0
- package/test/nsec.js +38 -0
- package/test/nsec3.js +26 -0
- package/test/nsec3param.js +26 -0
- package/test/openpgpkey.js +35 -0
- package/test/ptr.js +54 -0
- package/test/rr.js +196 -0
- package/test/smimea.js +45 -0
- package/test/soa.js +77 -0
- package/test/spf.js +48 -0
- package/test/srv.js +81 -0
- package/test/sshfp.js +62 -0
- package/test/tinydns.js +140 -0
- package/test/tlsa.js +54 -0
- package/test/txt.js +70 -0
- package/test/uri.js +61 -0
package/rr/dname.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import net from 'net'
|
|
2
|
+
|
|
3
|
+
import RR from '../rr.js'
|
|
4
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
5
|
+
|
|
6
|
+
export default class DNAME extends RR {
|
|
7
|
+
constructor (opts) {
|
|
8
|
+
super(opts)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/****** Resource record specific setters *******/
|
|
12
|
+
setTarget (val) {
|
|
13
|
+
if (!val) throw new Error('DNAME: target is required')
|
|
14
|
+
|
|
15
|
+
if (net.isIPv4(val) || net.isIPv6(val))
|
|
16
|
+
throw new Error(`DNAME: target must be a domain name, ${this.citeRFC()}`)
|
|
17
|
+
|
|
18
|
+
this.isFullyQualified('DNAME', 'target', val)
|
|
19
|
+
this.isValidHostname('DNAME', 'target', val)
|
|
20
|
+
|
|
21
|
+
// RFC 4034: letters in the DNS names are lower cased
|
|
22
|
+
this.set('target', val.toLowerCase())
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
getDescription () {
|
|
26
|
+
return 'Delegation Name'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getRdataFields (arg) {
|
|
30
|
+
return [ 'target' ]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getRFCs () {
|
|
34
|
+
return [ 2672, 6672 ]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getTypeId () {
|
|
38
|
+
return 39
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/****** IMPORTERS *******/
|
|
42
|
+
fromTinydns (opts) {
|
|
43
|
+
// DNAME via generic, :fqdn:n:rdata:ttl:timestamp:lo
|
|
44
|
+
const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':')
|
|
45
|
+
if (n != 39) throw new Error('DNAME fromTinydns, invalid n')
|
|
46
|
+
|
|
47
|
+
return new DNAME({
|
|
48
|
+
type : 'DNAME',
|
|
49
|
+
owner : this.fullyQualify(fqdn),
|
|
50
|
+
target : (TINYDNS.unpackDomainName(rdata))[0],
|
|
51
|
+
ttl : parseInt(ttl, 10),
|
|
52
|
+
timestamp: ts,
|
|
53
|
+
location : loc !== '' && loc !== '\n' ? loc : '',
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
fromBind (opts) {
|
|
58
|
+
// test.example.com 3600 IN DNAME ...
|
|
59
|
+
const [ owner, ttl, c, type, target ] = opts.bindline.split(/\s+/)
|
|
60
|
+
return new DNAME({
|
|
61
|
+
owner,
|
|
62
|
+
ttl : parseInt(ttl, 10),
|
|
63
|
+
class: c,
|
|
64
|
+
type,
|
|
65
|
+
target,
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/****** EXPORTERS *******/
|
|
70
|
+
toTinydns () {
|
|
71
|
+
const rdata = TINYDNS.packDomainName(this.get('target'))
|
|
72
|
+
return this.getTinydnsGeneric(rdata)
|
|
73
|
+
}
|
|
74
|
+
}
|
package/rr/dnskey.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
|
|
2
|
+
import RR from '../rr.js'
|
|
3
|
+
|
|
4
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
5
|
+
|
|
6
|
+
export default class DNSKEY extends RR {
|
|
7
|
+
constructor (opts) {
|
|
8
|
+
super(opts)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/****** Resource record specific setters *******/
|
|
12
|
+
setFlags (val) {
|
|
13
|
+
// a 2 octet Flags Field
|
|
14
|
+
this.is16bitInt('DNSKEY', 'flags', val)
|
|
15
|
+
|
|
16
|
+
// the possible values are: 0, 256, and 257; RFC 4034
|
|
17
|
+
if (![ 0, 256, 257 ].includes(val)) throw new Error(`DNSKEY: flags invalid, ${this.citeRFC()}`)
|
|
18
|
+
|
|
19
|
+
this.set('flags', val)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
setProtocol (val) {
|
|
23
|
+
// 1 octet
|
|
24
|
+
this.is8bitInt('DNSKEY', 'protocol', val)
|
|
25
|
+
|
|
26
|
+
// The Protocol Field MUST be represented as an unsigned decimal integer with a value of 3.
|
|
27
|
+
if (![ 3 ].includes(val)) throw new Error(`DNSKEY: protocol invalid, ${this.citeRFC()}`)
|
|
28
|
+
|
|
29
|
+
this.set('protocol', val)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
setAlgorithm (val) {
|
|
33
|
+
// 1 octet
|
|
34
|
+
this.is8bitInt('DNSKEY', 'algorithm', val)
|
|
35
|
+
|
|
36
|
+
// https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
|
|
37
|
+
// 1=RSA/MD5, 2=DH, 3=DSA/SHA-1, 4=EC, 5=RSA/SHA-1
|
|
38
|
+
if (![ ...Array(16).keys(),253,254 ].includes(val))
|
|
39
|
+
console.error(`DNSKEY: algorithm (${val}) not recognized, ${this.citeRFC()}`)
|
|
40
|
+
|
|
41
|
+
this.set('algorithm', val)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
setPublickey (val) {
|
|
45
|
+
if (!val) throw new Error(`DNSKEY: publickey is required, ${this.citeRFC()}`)
|
|
46
|
+
|
|
47
|
+
this.set('publickey', val)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
getDescription () {
|
|
51
|
+
return 'DNS Public Key'
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
getRdataFields (arg) {
|
|
55
|
+
return [ 'flags', 'protocol', 'algorithm', 'publickey' ]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
getRFCs () {
|
|
59
|
+
return [ 4034, 6014, 8624 ]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
getTypeId () {
|
|
63
|
+
return 48
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/****** IMPORTERS *******/
|
|
67
|
+
|
|
68
|
+
fromBind (opts) {
|
|
69
|
+
// test.example.com 3600 IN DNSKEY Flags Protocol Algorithm PublicKey
|
|
70
|
+
const match = opts.bindline.match(/^([^\s]+)\s+([0-9]+)\s+(\w+)\s+(\w+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+\s*(.*?)\s*$/)
|
|
71
|
+
if (!match) throw new Error(`unable to parse DNSKEY: ${opts.bindline}`)
|
|
72
|
+
const [ owner, ttl, c, type, flags, protocol, algorithm, publickey ] = match.slice(1)
|
|
73
|
+
|
|
74
|
+
return new DNSKEY({
|
|
75
|
+
owner,
|
|
76
|
+
ttl : parseInt(ttl, 10),
|
|
77
|
+
class : c,
|
|
78
|
+
type : type,
|
|
79
|
+
flags : parseInt(flags, 10),
|
|
80
|
+
protocol : parseInt(protocol, 10),
|
|
81
|
+
algorithm: parseInt(algorithm, 10),
|
|
82
|
+
publickey: publickey,
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fromTinydns (opts) {
|
|
87
|
+
const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':')
|
|
88
|
+
if (n != 48) throw new Error('DNSKEY fromTinydns, invalid n')
|
|
89
|
+
|
|
90
|
+
const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
91
|
+
|
|
92
|
+
return new DNSKEY({
|
|
93
|
+
owner : this.fullyQualify(fqdn),
|
|
94
|
+
ttl : parseInt(ttl, 10),
|
|
95
|
+
type : 'DNSKEY',
|
|
96
|
+
flags : bytes.readUInt16BE(0),
|
|
97
|
+
protocol : bytes.readUInt8(2),
|
|
98
|
+
'algorithm': bytes.readUInt8(3),
|
|
99
|
+
'publickey': bytes.slice(4).toString(),
|
|
100
|
+
timestamp : ts,
|
|
101
|
+
location : loc !== '' && loc !== '\n' ? loc : '',
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/****** EXPORTERS *******/
|
|
106
|
+
|
|
107
|
+
toTinydns () {
|
|
108
|
+
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
109
|
+
|
|
110
|
+
return this.getTinydnsGeneric(
|
|
111
|
+
TINYDNS.UInt16toOctal(this.get('flags')) +
|
|
112
|
+
TINYDNS.UInt8toOctal(this.get('protocol')) +
|
|
113
|
+
TINYDNS.UInt8toOctal(this.get('algorithm')) +
|
|
114
|
+
TINYDNS.escapeOctal(dataRe, this.get('publickey'))
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
}
|
package/rr/ds.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
|
|
2
|
+
import RR from '../rr.js'
|
|
3
|
+
|
|
4
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
5
|
+
|
|
6
|
+
export default class DS extends RR {
|
|
7
|
+
constructor (opts) {
|
|
8
|
+
super(opts)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/****** Resource record specific setters *******/
|
|
12
|
+
setKeyTag (val) {
|
|
13
|
+
// a 2 octet Key Tag field...in network byte order
|
|
14
|
+
if (!val) throw new Error(`DS: key tag is required`)
|
|
15
|
+
if (val.length > 2) throw new Error(`DS: key tag is too long, ${this.citeRFC()}`)
|
|
16
|
+
|
|
17
|
+
this.set('key tag', val)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
setAlgorithm (val) {
|
|
21
|
+
// 1=RSA/MD5, 2=DH, 3=DSA/SHA-1, 4=EC, 5=RSA/SHA-1
|
|
22
|
+
if (![ 1,2,3,4,5,253,254 ].includes(val))
|
|
23
|
+
throw new Error(`DS: algorithm invalid, ${this.citeRFC()}`)
|
|
24
|
+
|
|
25
|
+
this.set('algorithm', val)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
setDigestType (val) {
|
|
29
|
+
if (![ 1,2 ].includes(val)) throw new Error(`DS: digest type invalid, ${this.citeRFC()}`)
|
|
30
|
+
|
|
31
|
+
this.set('digest type', val)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setDigest (val) {
|
|
35
|
+
if (!val) throw new Error(`DS: digest is required, ${this.citeRFC()}`)
|
|
36
|
+
|
|
37
|
+
this.set('digest', val)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
getDescription () {
|
|
41
|
+
return 'Delegation Signer'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getRdataFields (arg) {
|
|
45
|
+
return [ 'key tag', 'algorithm', 'digest type', 'digest' ]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
getRFCs () {
|
|
49
|
+
return [ 4034, 4509 ]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getTypeId () {
|
|
53
|
+
return 43
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/****** IMPORTERS *******/
|
|
57
|
+
|
|
58
|
+
fromBind (opts) {
|
|
59
|
+
// test.example.com 3600 IN DS Key Tag Algorithm, Digest Type, Digest
|
|
60
|
+
const [ owner, ttl, c, type, keytag, algorithm, digesttype ] = opts.bindline.split(/\s+/)
|
|
61
|
+
return new DS({
|
|
62
|
+
owner,
|
|
63
|
+
ttl : parseInt(ttl, 10),
|
|
64
|
+
class : c,
|
|
65
|
+
type,
|
|
66
|
+
'key tag' : parseInt(keytag, 10),
|
|
67
|
+
algorithm : parseInt(algorithm, 10),
|
|
68
|
+
'digest type': parseInt(digesttype, 10),
|
|
69
|
+
digest : opts.bindline.split(/\s+/).slice(7).join(' ').trim(),
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
fromTinydns (opts) {
|
|
74
|
+
const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':')
|
|
75
|
+
if (n != 43) throw new Error('DS fromTinydns, invalid n')
|
|
76
|
+
|
|
77
|
+
const binRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
78
|
+
|
|
79
|
+
return new DS({
|
|
80
|
+
owner : this.fullyQualify(fqdn),
|
|
81
|
+
ttl : parseInt(ttl, 10),
|
|
82
|
+
type : 'DS',
|
|
83
|
+
'key tag' : binRdata.readUInt16BE(0),
|
|
84
|
+
algorithm : binRdata.readUInt8(2),
|
|
85
|
+
'digest type': binRdata.readUInt8(3),
|
|
86
|
+
digest : binRdata.slice(4).toString(),
|
|
87
|
+
timestamp : ts,
|
|
88
|
+
location : loc !== '' && loc !== '\n' ? loc : '',
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/****** EXPORTERS *******/
|
|
93
|
+
|
|
94
|
+
toTinydns () {
|
|
95
|
+
const rdataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
96
|
+
|
|
97
|
+
return this.getTinydnsGeneric(
|
|
98
|
+
TINYDNS.UInt16toOctal(this.get('key tag')) +
|
|
99
|
+
TINYDNS.UInt8toOctal(this.get('algorithm')) +
|
|
100
|
+
TINYDNS.UInt8toOctal(this.get('digest type')) +
|
|
101
|
+
TINYDNS.escapeOctal(rdataRe, this.get('digest'))
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
}
|
package/rr/hinfo.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
|
|
2
|
+
import RR from '../rr.js'
|
|
3
|
+
|
|
4
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
5
|
+
|
|
6
|
+
export default class HINFO extends RR {
|
|
7
|
+
constructor (opts) {
|
|
8
|
+
super(opts)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/****** Resource record specific setters *******/
|
|
12
|
+
setCpu (val) {
|
|
13
|
+
if (val.length > 255) throw new Error('HINFO cpu cannot exceed 255 chars')
|
|
14
|
+
this.set('cpu', val.replace(/^["']|["']$/g, ''))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
setOs (val) {
|
|
18
|
+
if (val.length > 255) throw new Error('HINFO os cannot exceed 255 chars')
|
|
19
|
+
this.set('os', val.replace(/^["']|["']$/g, ''))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getDescription () {
|
|
23
|
+
return 'Host Info'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getRdataFields (arg) {
|
|
27
|
+
return [ 'cpu', 'os' ]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getRFCs () {
|
|
31
|
+
return [ 1034, 1035, 8482 ]
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getTypeId () {
|
|
35
|
+
return 13
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getQuotedFields () {
|
|
39
|
+
return [ 'cpu', 'os' ]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/****** IMPORTERS *******/
|
|
43
|
+
fromBind (opts) {
|
|
44
|
+
// test.example.com 3600 IN HINFO DEC-2060 TOPS20
|
|
45
|
+
const match = opts.bindline.match(/([^\s]+)\s+([0-9]+)\s+(IN)\s+(HINFO)\s+("[^"]+"|[^\s]+)\s+("[^"]+"|[^\s]+)/i)
|
|
46
|
+
if (!match) throw new Error(`unable to parse HINFO: ${opts.bindline}`)
|
|
47
|
+
const [ owner, ttl, c, type, cpu, os ] = match.slice(1)
|
|
48
|
+
|
|
49
|
+
return new HINFO({
|
|
50
|
+
owner,
|
|
51
|
+
ttl : parseInt(ttl, 10),
|
|
52
|
+
class: c,
|
|
53
|
+
type,
|
|
54
|
+
cpu,
|
|
55
|
+
os,
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fromTinydns (opts) {
|
|
60
|
+
// HINFO via generic, :fqdn:n:rdata:ttl:timestamp:lo
|
|
61
|
+
const [ fqdn, , rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':')
|
|
62
|
+
const [ cpu, os ] = [ ...TINYDNS.unpackString(rdata) ]
|
|
63
|
+
|
|
64
|
+
return new this.constructor({
|
|
65
|
+
owner : this.fullyQualify(fqdn),
|
|
66
|
+
ttl : parseInt(ttl, 10),
|
|
67
|
+
type : 'HINFO',
|
|
68
|
+
cpu,
|
|
69
|
+
os,
|
|
70
|
+
timestamp: ts,
|
|
71
|
+
location : loc !== '' && loc !== '\n' ? loc : '',
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/****** EXPORTERS *******/
|
|
76
|
+
toTinydns () {
|
|
77
|
+
return this.getTinydnsGeneric(
|
|
78
|
+
[
|
|
79
|
+
TINYDNS.packString(this.get('cpu')),
|
|
80
|
+
TINYDNS.packString(this.get('os')),
|
|
81
|
+
].join('')
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
}
|
package/rr/ipseckey.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
|
|
2
|
+
import net from 'net'
|
|
3
|
+
|
|
4
|
+
import RR from '../rr.js'
|
|
5
|
+
|
|
6
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
7
|
+
|
|
8
|
+
export default class IPSECKEY extends RR {
|
|
9
|
+
constructor (opts) {
|
|
10
|
+
super(opts)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/****** Resource record specific setters *******/
|
|
14
|
+
setPrecedence (val) {
|
|
15
|
+
// an 8-bit precedence for this record.
|
|
16
|
+
this.is8bitInt('IPSECKEY', 'precedence', val)
|
|
17
|
+
|
|
18
|
+
this.set('precedence', val)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
setGatewayType (val) {
|
|
22
|
+
// 0 (none), 1 (4-byte IPv4), 2 (16-byte IPv6), 3 (wire encoded domain name)
|
|
23
|
+
if (![ 0,1,2,3 ].includes(val))
|
|
24
|
+
throw new Error(`IPSECKEY: Gateway Type is invalid, ${this.citeRFC()}`)
|
|
25
|
+
|
|
26
|
+
this.set('gateway type', val)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setAlgorithm (val) {
|
|
30
|
+
// unsigned int, 1 octet, values: 1=DSA, 2=RSA
|
|
31
|
+
if (![ 1,2 ].includes(val))
|
|
32
|
+
throw new Error(`IPSECKEY: Algorithm invalid, ${this.citeRFC()}`)
|
|
33
|
+
|
|
34
|
+
this.set('algorithm', val)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setGateway (val) {
|
|
38
|
+
const gwErr = new Error(`IPSECKEY: gateway invalid (${val}), ${this.citeRFC()}`)
|
|
39
|
+
switch (this.get('gateway type')) {
|
|
40
|
+
case 0: if (val !== '.') throw gwErr; break
|
|
41
|
+
case 1: if (!net.isIPv4(val)) throw gwErr; break
|
|
42
|
+
case 2: if (!net.isIPv6(val)) throw gwErr; break
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.set('gateway', val)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
setPublickey (val) {
|
|
49
|
+
// if (val) throw new Error(`IPSECKEY: publickey is optional, ${this.citeRFC()}`)
|
|
50
|
+
|
|
51
|
+
this.set('publickey', val)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
getDescription () {
|
|
55
|
+
return 'IPsec Keying'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
getRdataFields (arg) {
|
|
59
|
+
return [ 'precedence', 'gateway type', 'algorithm', 'gateway', 'publickey' ]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
getRFCs () {
|
|
63
|
+
return [ 4025 ]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
getTypeId () {
|
|
67
|
+
return 45
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/****** IMPORTERS *******/
|
|
71
|
+
fromBind (opts) {
|
|
72
|
+
// FQDN TTL CLASS IPSECKEY Precedence GatewayType Algorithm Gateway PublicKey
|
|
73
|
+
const [ owner, ttl, c, type, prec, gwt, algo, gateway, publickey ] = opts.bindline.split(/\s+/)
|
|
74
|
+
return new IPSECKEY({
|
|
75
|
+
owner,
|
|
76
|
+
ttl : parseInt(ttl, 10),
|
|
77
|
+
class : c,
|
|
78
|
+
type,
|
|
79
|
+
precedence : parseInt(prec, 10),
|
|
80
|
+
'gateway type': parseInt(gwt, 10),
|
|
81
|
+
algorithm : parseInt(algo, 10),
|
|
82
|
+
gateway,
|
|
83
|
+
publickey,
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
fromTinydns (opts) {
|
|
88
|
+
const [ fqdn, n, rdata, ttl, ts, loc ] = opts.tinyline.substring(1).split(':')
|
|
89
|
+
if (n != 45) throw new Error('IPSECKEY fromTinydns, invalid n')
|
|
90
|
+
|
|
91
|
+
const precedence = TINYDNS.octalToUInt8(rdata.substring(0, 4))
|
|
92
|
+
const gwType = TINYDNS.octalToUInt8(rdata.substring(4, 8))
|
|
93
|
+
const algorithm = TINYDNS.octalToUInt8(rdata.substring(8, 12))
|
|
94
|
+
|
|
95
|
+
let len, gateway, octalKey
|
|
96
|
+
|
|
97
|
+
switch (gwType) {
|
|
98
|
+
case 0: // no gateway
|
|
99
|
+
gateway = rdata.substring(12, 13) // should always be: '.'
|
|
100
|
+
octalKey = rdata.substring(13)
|
|
101
|
+
break
|
|
102
|
+
case 1: // 4-byte IPv4 address
|
|
103
|
+
gateway = TINYDNS.octalToIPv4(rdata.substring(12, 28))
|
|
104
|
+
octalKey = rdata.substring(28)
|
|
105
|
+
break
|
|
106
|
+
case 2: // 16-byte IPv6
|
|
107
|
+
gateway = TINYDNS.octalToHex(rdata.substring(12, 76))
|
|
108
|
+
octalKey = rdata.substring(76)
|
|
109
|
+
break
|
|
110
|
+
case 3: // wire encoded domain name
|
|
111
|
+
[ gateway, len ] = TINYDNS.unpackDomainName(rdata.substring(12))
|
|
112
|
+
octalKey = rdata.substring(12 + len)
|
|
113
|
+
break
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return new IPSECKEY({
|
|
117
|
+
owner : this.fullyQualify(fqdn),
|
|
118
|
+
ttl : parseInt(ttl, 10),
|
|
119
|
+
type : 'IPSECKEY',
|
|
120
|
+
precedence,
|
|
121
|
+
'gateway type': gwType,
|
|
122
|
+
algorithm,
|
|
123
|
+
gateway,
|
|
124
|
+
publickey : TINYDNS.octalToBase64(octalKey),
|
|
125
|
+
timestamp : ts,
|
|
126
|
+
location : loc !== '' && loc !== '\n' ? loc : '',
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/****** EXPORTERS *******/
|
|
131
|
+
|
|
132
|
+
toTinydns () {
|
|
133
|
+
const rdataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
134
|
+
|
|
135
|
+
let rdata = ''
|
|
136
|
+
rdata += TINYDNS.UInt8toOctal(this.get('precedence'))
|
|
137
|
+
rdata += TINYDNS.UInt8toOctal(this.get('gateway type'))
|
|
138
|
+
rdata += TINYDNS.UInt8toOctal(this.get('algorithm'))
|
|
139
|
+
|
|
140
|
+
switch (this.get('gateway type')) {
|
|
141
|
+
case 0:
|
|
142
|
+
rdata += TINYDNS.escapeOctal(rdataRe, '.')
|
|
143
|
+
break
|
|
144
|
+
case 1:
|
|
145
|
+
rdata += TINYDNS.ipv4toOctal(this.get('gateway'))
|
|
146
|
+
break
|
|
147
|
+
case 2:
|
|
148
|
+
rdata += TINYDNS.ipv6toOctal(this.get('gateway'))
|
|
149
|
+
break
|
|
150
|
+
case 3:
|
|
151
|
+
rdata += TINYDNS.packDomainName(this.get('gateway'))
|
|
152
|
+
break
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
rdata += TINYDNS.base64toOctal(this.get('publickey'))
|
|
156
|
+
|
|
157
|
+
return this.getTinydnsGeneric(rdata)
|
|
158
|
+
}
|
|
159
|
+
}
|
package/rr/key.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
|
|
2
|
+
import RR from '../rr.js'
|
|
3
|
+
|
|
4
|
+
export default class KEY extends RR {
|
|
5
|
+
constructor (opts) {
|
|
6
|
+
super(opts)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/****** Resource record specific setters *******/
|
|
10
|
+
setFlags (val) {
|
|
11
|
+
// a 2 octet Flags Field
|
|
12
|
+
this.is16bitInt('KEY', 'flags', val)
|
|
13
|
+
|
|
14
|
+
this.set('flags', val)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
setProtocol (val) {
|
|
18
|
+
// 1 octet
|
|
19
|
+
this.is8bitInt('KEY', 'protocol', val)
|
|
20
|
+
|
|
21
|
+
this.set('protocol', val)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
setAlgorithm (val) {
|
|
25
|
+
// 1 octet
|
|
26
|
+
// 1=RSA/MD5, 2=DH, 3=DSA/SHA-1, 4=EC, 5=RSA/SHA-1
|
|
27
|
+
if (![ 1,2,3,4,5,253,254 ].includes(val))
|
|
28
|
+
throw new Error(`KEY: algorithm invalid, ${this.citeRFC()}`)
|
|
29
|
+
|
|
30
|
+
this.set('algorithm', val)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
setPublickey (val) {
|
|
34
|
+
if (!val) throw new Error(`KEY: publickey is required, ${this.citeRFC()}`)
|
|
35
|
+
|
|
36
|
+
this.set('publickey', val)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getDescription () {
|
|
40
|
+
return 'DNS Public Key'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getRdataFields (arg) {
|
|
44
|
+
return [ 'flags', 'protocol', 'algorithm', 'publickey' ]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getRFCs () {
|
|
48
|
+
return [ 2535, 3445 ]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getTypeId () {
|
|
52
|
+
return 25
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/****** IMPORTERS *******/
|
|
56
|
+
|
|
57
|
+
fromBind (opts) {
|
|
58
|
+
// test.example.com 3600 IN KEY Flags Protocol Algorithm PublicKey
|
|
59
|
+
const [ owner, ttl, c, type, flags, protocol, algorithm ] = opts.bindline.split(/\s+/)
|
|
60
|
+
return new KEY({
|
|
61
|
+
owner,
|
|
62
|
+
ttl : parseInt(ttl, 10),
|
|
63
|
+
class : c,
|
|
64
|
+
type : type,
|
|
65
|
+
flags : parseInt(flags, 10),
|
|
66
|
+
protocol : parseInt(protocol, 10),
|
|
67
|
+
algorithm: parseInt(algorithm, 10),
|
|
68
|
+
publickey: opts.bindline.split(/\s+/).slice(7).join(' ').trim(),
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/****** EXPORTERS *******/
|
|
73
|
+
}
|