@nictool/dns-resource-record 1.4.0 → 1.5.0
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/CHANGELOG.md +18 -2
- package/README.md +20 -19
- package/lib/tinydns.js +10 -10
- package/package.json +2 -2
- package/rr/a.js +5 -5
- package/rr/aaaa.js +9 -9
- package/rr/apl.js +49 -2
- package/rr/caa.js +26 -23
- package/rr/cert.js +31 -7
- package/rr/cname.js +5 -5
- package/rr/dhcid.js +17 -2
- package/rr/dname.js +5 -5
- package/rr/dnskey.js +14 -8
- package/rr/ds.js +6 -6
- package/rr/hinfo.js +13 -10
- package/rr/hip.js +43 -2
- package/rr/https.js +22 -9
- package/rr/ipseckey.js +16 -16
- package/rr/key.js +13 -17
- package/rr/kx.js +18 -2
- package/rr/loc.js +14 -14
- package/rr/mx.js +5 -5
- package/rr/naptr.js +23 -19
- package/rr/ns.js +5 -5
- package/rr/nsec.js +6 -6
- package/rr/nsec3.js +52 -7
- package/rr/nsec3param.js +35 -22
- package/rr/nxt.js +7 -7
- package/rr/openpgpkey.js +14 -8
- package/rr/ptr.js +5 -5
- package/rr/rp.js +19 -2
- package/rr/rrsig.js +84 -10
- package/rr/sig.js +88 -12
- package/rr/smimea.js +6 -6
- package/rr/soa.js +6 -6
- package/rr/spf.js +3 -3
- package/rr/srv.js +11 -11
- package/rr/sshfp.js +8 -8
- package/rr/svcb.js +25 -10
- package/rr/tlsa.js +8 -8
- package/rr/tsig.js +139 -13
- package/rr/txt.js +10 -11
- package/rr/uri.js +8 -8
- package/rr/wks.js +26 -2
- package/rr.js +52 -7
package/rr/nsec3param.js
CHANGED
|
@@ -11,7 +11,7 @@ export default class NSEC3PARAM extends RR {
|
|
|
11
11
|
setHashAlgorithm(val) {
|
|
12
12
|
// Hash Algorithm is a single octet.
|
|
13
13
|
// The Hash Algorithm field is represented as an unsigned decimal integer.
|
|
14
|
-
if (
|
|
14
|
+
if (val === undefined || val === null) this.throwHelp(`NSEC3PARAM: 'hash algorithm' is required`)
|
|
15
15
|
|
|
16
16
|
this.is8bitInt('NSEC3PARAM', 'hash algorithm', val)
|
|
17
17
|
|
|
@@ -20,7 +20,7 @@ export default class NSEC3PARAM extends RR {
|
|
|
20
20
|
|
|
21
21
|
setFlags(val) {
|
|
22
22
|
// The Flags field is represented as an unsigned decimal integer.
|
|
23
|
-
if (
|
|
23
|
+
if (val === undefined || val === null) this.throwHelp(`NSEC3PARAM: 'flags' is required`)
|
|
24
24
|
|
|
25
25
|
this.is8bitInt('NSEC3PARAM', 'flags', val)
|
|
26
26
|
|
|
@@ -29,7 +29,7 @@ export default class NSEC3PARAM extends RR {
|
|
|
29
29
|
|
|
30
30
|
setIterations(val) {
|
|
31
31
|
// The Iterations field is represented as an unsigned decimal integer. 0-65535
|
|
32
|
-
if (
|
|
32
|
+
if (val === undefined || val === null) this.throwHelp(`NSEC3PARAM: 'iterations' is required`)
|
|
33
33
|
|
|
34
34
|
this.is16bitInt('NSEC3PARAM', 'iterations', val)
|
|
35
35
|
|
|
@@ -41,6 +41,15 @@ export default class NSEC3PARAM extends RR {
|
|
|
41
41
|
// hexadecimal digits. Whitespace is not allowed within the
|
|
42
42
|
// sequence. The Salt field is represented as "-" (without the
|
|
43
43
|
// quotes) when the Salt Length field has a value of 0
|
|
44
|
+
if (val === '-') {
|
|
45
|
+
this.set('salt', val)
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (val !== undefined && val !== null && !/^[0-9A-Fa-f]*$/.test(val)) {
|
|
50
|
+
this.throwHelp(`NSEC3PARAM: 'salt' must be hex or '-'`)
|
|
51
|
+
}
|
|
52
|
+
|
|
44
53
|
this.set('salt', val)
|
|
45
54
|
}
|
|
46
55
|
|
|
@@ -62,10 +71,10 @@ export default class NSEC3PARAM extends RR {
|
|
|
62
71
|
|
|
63
72
|
/****** IMPORTERS *******/
|
|
64
73
|
|
|
65
|
-
fromBind(
|
|
74
|
+
fromBind({ bindline }) {
|
|
66
75
|
// test.example.com 3600 IN NSEC3PARAM <hash> <flags> <iterations> <salt>
|
|
67
76
|
// Example: test.example.com. 3600 IN NSEC3PARAM 1 1 12 aabbccdd
|
|
68
|
-
const [owner, ttl, c, type, ha, flags, iterations, salt] =
|
|
77
|
+
const [owner, ttl, c, type, ha, flags, iterations, salt] = bindline.split(/\s+/)
|
|
69
78
|
return new NSEC3PARAM({
|
|
70
79
|
owner,
|
|
71
80
|
ttl: parseInt(ttl, 10),
|
|
@@ -78,22 +87,27 @@ export default class NSEC3PARAM extends RR {
|
|
|
78
87
|
})
|
|
79
88
|
}
|
|
80
89
|
|
|
81
|
-
fromTinydns(
|
|
82
|
-
const rd = opts.rd
|
|
83
|
-
|
|
90
|
+
fromTinydns({ tinyline }) {
|
|
84
91
|
// RDATA format: Hash Algorithm (3 octal chars) + Flags (3 octal chars) + Iterations (6 octal chars) + Salt (escaped hex string)
|
|
85
|
-
|
|
92
|
+
const [owner, _typeId, rd, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
93
|
+
if (rd.length < 4) {
|
|
86
94
|
this.throwHelp(`NSEC3PARAM: RDATA too short: ${rd}`)
|
|
87
95
|
}
|
|
88
96
|
|
|
97
|
+
// rd may contain actual binary characters (from JS string '\\001' -> char 0x01),
|
|
98
|
+
// so convert via octalToChar and read bytes from a Buffer for robust parsing.
|
|
99
|
+
const bytes = Buffer.from(TINYDNS.octalToChar(rd), 'binary')
|
|
100
|
+
|
|
89
101
|
return new NSEC3PARAM({
|
|
90
|
-
owner: this.fullyQualify(
|
|
91
|
-
ttl: parseInt(
|
|
102
|
+
owner: this.fullyQualify(owner),
|
|
103
|
+
ttl: parseInt(ttl, 10),
|
|
92
104
|
type: 'NSEC3PARAM',
|
|
93
|
-
'hash algorithm':
|
|
94
|
-
flags:
|
|
95
|
-
iterations:
|
|
96
|
-
salt:
|
|
105
|
+
'hash algorithm': bytes.readUInt8(0),
|
|
106
|
+
flags: bytes.readUInt8(1),
|
|
107
|
+
iterations: bytes.readUInt16BE(2),
|
|
108
|
+
salt: bytes.slice(4).toString('utf8'),
|
|
109
|
+
timestamp: ts,
|
|
110
|
+
location: loc?.trim() ?? '',
|
|
97
111
|
})
|
|
98
112
|
}
|
|
99
113
|
|
|
@@ -108,12 +122,11 @@ export default class NSEC3PARAM extends RR {
|
|
|
108
122
|
toTinydns() {
|
|
109
123
|
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
110
124
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return this.getTinydnsGeneric(rdata)
|
|
125
|
+
return this.getTinydnsGeneric(
|
|
126
|
+
TINYDNS.UInt8toOctal(this.get('hash algorithm')) +
|
|
127
|
+
TINYDNS.UInt8toOctal(this.get('flags')) +
|
|
128
|
+
TINYDNS.UInt16toOctal(this.get('iterations')) +
|
|
129
|
+
TINYDNS.escapeOctal(dataRe, this.get('salt')),
|
|
130
|
+
)
|
|
118
131
|
}
|
|
119
132
|
}
|
package/rr/nxt.js
CHANGED
|
@@ -43,9 +43,9 @@ export default class NXT extends RR {
|
|
|
43
43
|
|
|
44
44
|
/****** IMPORTERS *******/
|
|
45
45
|
|
|
46
|
-
fromTinydns(
|
|
47
|
-
const [owner, n, rdata, ttl, ts, loc] =
|
|
48
|
-
if (n
|
|
46
|
+
fromTinydns({ tinyline }) {
|
|
47
|
+
const [owner, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
48
|
+
if (parseInt(n, 10) !== this.getTypeId()) this.throwHelp('NXT fromTinydns, invalid n')
|
|
49
49
|
|
|
50
50
|
const binaryRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
51
51
|
const [nextDomain, _escapedLen, binaryLen] = TINYDNS.unpackDomainName(rdata)
|
|
@@ -57,20 +57,20 @@ export default class NXT extends RR {
|
|
|
57
57
|
'next domain': nextDomain,
|
|
58
58
|
'type bit map': binaryRdata.slice(binaryLen).toString(),
|
|
59
59
|
timestamp: ts,
|
|
60
|
-
location: loc
|
|
60
|
+
location: loc?.trim() ?? '',
|
|
61
61
|
})
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
fromBind(
|
|
64
|
+
fromBind({ bindline }) {
|
|
65
65
|
// test.example.com 3600 IN NXT NextDomain TypeBitMap
|
|
66
|
-
const [owner, ttl, c, type, next] =
|
|
66
|
+
const [owner, ttl, c, type, next] = bindline.split(/\s+/)
|
|
67
67
|
return new NXT({
|
|
68
68
|
owner,
|
|
69
69
|
ttl: parseInt(ttl, 10),
|
|
70
70
|
class: c,
|
|
71
71
|
type: type,
|
|
72
72
|
'next domain': next,
|
|
73
|
-
'type bit map':
|
|
73
|
+
'type bit map': bindline.split(/\s+/).slice(5).filter(removeParens).join(' ').trim(),
|
|
74
74
|
})
|
|
75
75
|
}
|
|
76
76
|
|
package/rr/openpgpkey.js
CHANGED
|
@@ -28,11 +28,14 @@ export default class OPENPGPKEY extends RR {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/****** IMPORTERS *******/
|
|
31
|
-
fromBind(
|
|
31
|
+
fromBind({ bindline: bindline }) {
|
|
32
32
|
// test.example.com 3600 IN OPENPGPKEY <base64 public key>
|
|
33
|
-
const regex =
|
|
34
|
-
|
|
35
|
-
const
|
|
33
|
+
const regex =
|
|
34
|
+
/^(?<owner>\S+)\s+(?<ttl>\d{1,10})\s+(?<class>IN)\s+(?<type>OPENPGPKEY)\s+(?<publickey>\S[\s\S]*)$/i
|
|
35
|
+
const match = bindline.trim().match(regex)
|
|
36
|
+
if (!match) this.throwHelp(`unable to parse OPENPGPKEY: ${bindline}`)
|
|
37
|
+
|
|
38
|
+
const { owner, ttl, class: c, type, publickey } = match.groups
|
|
36
39
|
|
|
37
40
|
return new OPENPGPKEY({
|
|
38
41
|
owner,
|
|
@@ -43,12 +46,15 @@ export default class OPENPGPKEY extends RR {
|
|
|
43
46
|
})
|
|
44
47
|
}
|
|
45
48
|
|
|
46
|
-
fromTinydns(
|
|
49
|
+
fromTinydns({ tinyline }) {
|
|
50
|
+
const [owner, _typeId, rd, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
47
51
|
return new OPENPGPKEY({
|
|
48
|
-
owner: this.fullyQualify(
|
|
49
|
-
ttl: parseInt(
|
|
52
|
+
owner: this.fullyQualify(owner),
|
|
53
|
+
ttl: parseInt(ttl, 10),
|
|
50
54
|
type: 'OPENPGPKEY',
|
|
51
|
-
'public key': Buffer.from(TINYDNS.unescapeOctal(
|
|
55
|
+
'public key': Buffer.from(TINYDNS.unescapeOctal(rd), 'base64').toString('utf-8'),
|
|
56
|
+
timestamp: ts,
|
|
57
|
+
location: loc?.trim() ?? '',
|
|
52
58
|
})
|
|
53
59
|
}
|
|
54
60
|
|
package/rr/ptr.js
CHANGED
|
@@ -31,9 +31,9 @@ export default class PTR extends RR {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/****** IMPORTERS *******/
|
|
34
|
-
fromTinydns(
|
|
34
|
+
fromTinydns({ tinyline }) {
|
|
35
35
|
// ^fqdn:p:ttl:timestamp:lo
|
|
36
|
-
const [fqdn, p, ttl, ts, loc] =
|
|
36
|
+
const [fqdn, p, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
37
37
|
|
|
38
38
|
return new PTR({
|
|
39
39
|
owner: this.fullyQualify(fqdn),
|
|
@@ -41,13 +41,13 @@ export default class PTR extends RR {
|
|
|
41
41
|
type: 'PTR',
|
|
42
42
|
dname: this.fullyQualify(p),
|
|
43
43
|
timestamp: ts,
|
|
44
|
-
location: loc
|
|
44
|
+
location: loc?.trim() ?? '',
|
|
45
45
|
})
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
fromBind(
|
|
48
|
+
fromBind({ bindline }) {
|
|
49
49
|
// test.example.com 3600 IN PTR dname
|
|
50
|
-
const [owner, ttl, c, type, dname] =
|
|
50
|
+
const [owner, ttl, c, type, dname] = bindline.split(/\s+/)
|
|
51
51
|
return new PTR({
|
|
52
52
|
owner,
|
|
53
53
|
ttl: parseInt(ttl, 10),
|
package/rr/rp.js
CHANGED
|
@@ -52,9 +52,9 @@ export default class RP extends RR {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/****** IMPORTERS *******/
|
|
55
|
-
fromBind(
|
|
55
|
+
fromBind({ bindline }) {
|
|
56
56
|
// test.example.com 3600 IN RP mbox txt
|
|
57
|
-
const [owner, ttl, c, type, mbox, txt] =
|
|
57
|
+
const [owner, ttl, c, type, mbox, txt] = bindline.split(/\s+/)
|
|
58
58
|
return new RP({
|
|
59
59
|
owner,
|
|
60
60
|
ttl: parseInt(ttl, 10),
|
|
@@ -65,6 +65,23 @@ export default class RP extends RR {
|
|
|
65
65
|
})
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
fromTinydns({ tinyline }) {
|
|
69
|
+
const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
70
|
+
|
|
71
|
+
const [mbox, consumed] = TINYDNS.unpackDomainName(rdata)
|
|
72
|
+
const txt = TINYDNS.unpackDomainName(rdata.slice(consumed))[0]
|
|
73
|
+
|
|
74
|
+
return new RP({
|
|
75
|
+
owner: this.fullyQualify(owner),
|
|
76
|
+
ttl: parseInt(ttl, 10),
|
|
77
|
+
type: 'RP',
|
|
78
|
+
mbox,
|
|
79
|
+
txt,
|
|
80
|
+
timestamp: ts,
|
|
81
|
+
location: loc?.trim() ?? '',
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
68
85
|
/****** EXPORTERS *******/
|
|
69
86
|
toBind(zone_opts) {
|
|
70
87
|
return `${this.getPrefix(zone_opts)}\t${this.getFQDN('mbox', zone_opts)}\t${this.getFQDN('txt', zone_opts)}\n`
|
package/rr/rrsig.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import RR from '../rr.js'
|
|
2
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
2
3
|
|
|
3
4
|
export default class RRSIG extends RR {
|
|
4
5
|
constructor(opts) {
|
|
@@ -101,16 +102,89 @@ export default class RRSIG extends RR {
|
|
|
101
102
|
|
|
102
103
|
/****** IMPORTERS *******/
|
|
103
104
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
fromBind({ bindline }) {
|
|
106
|
+
// example.com. 3600 IN RRSIG typecovered algorithm labels origttl sigexp siginc keytag signersname ( signature )
|
|
107
|
+
const parts = bindline.trim().split(/\s+/)
|
|
108
|
+
return new RRSIG({
|
|
109
|
+
owner: parts[0],
|
|
110
|
+
ttl: parseInt(parts[1], 10),
|
|
111
|
+
class: parts[2],
|
|
112
|
+
type: 'RRSIG',
|
|
113
|
+
'type covered': parseInt(parts[4], 10),
|
|
114
|
+
algorithm: parseInt(parts[5], 10),
|
|
115
|
+
labels: parseInt(parts[6], 10),
|
|
116
|
+
'original ttl': parseInt(parts[7], 10),
|
|
117
|
+
'signature expiration': parseInt(parts[8], 10),
|
|
118
|
+
'signature inception': parseInt(parts[9], 10),
|
|
119
|
+
'key tag': parseInt(parts[10], 10),
|
|
120
|
+
'signers name': parts[11],
|
|
121
|
+
signature: parts
|
|
122
|
+
.slice(12)
|
|
123
|
+
.filter((a) => a !== '(' && a !== ')')
|
|
124
|
+
.join(' ')
|
|
125
|
+
.trim(),
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
fromTinydns({ tinyline }) {
|
|
130
|
+
const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
131
|
+
if (parseInt(n, 10) !== this.getTypeId()) this.throwHelp('RRSIG fromTinydns, invalid n')
|
|
132
|
+
|
|
133
|
+
const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
134
|
+
const typeCovered = bytes.readUInt16BE(0)
|
|
135
|
+
const algorithm = bytes.readUInt8(2)
|
|
136
|
+
const labels = bytes.readUInt8(3)
|
|
137
|
+
const originalTtl = bytes.readUInt32BE(4)
|
|
138
|
+
const signatureExpiration = bytes.readUInt32BE(8)
|
|
139
|
+
const signatureInception = bytes.readUInt32BE(12)
|
|
140
|
+
const keyTag = bytes.readUInt16BE(16)
|
|
141
|
+
|
|
142
|
+
let pos = 18
|
|
143
|
+
const labelArr = []
|
|
144
|
+
while (pos < bytes.length) {
|
|
145
|
+
const len = bytes.readUInt8(pos++)
|
|
146
|
+
if (len === 0) break
|
|
147
|
+
labelArr.push(bytes.slice(pos, pos + len).toString())
|
|
148
|
+
pos += len
|
|
149
|
+
}
|
|
150
|
+
const signersName = `${labelArr.join('.')}.`
|
|
151
|
+
const signature = bytes.slice(pos).toString()
|
|
152
|
+
|
|
153
|
+
return new RRSIG({
|
|
154
|
+
owner: this.fullyQualify(fqdn),
|
|
155
|
+
ttl: parseInt(ttl, 10),
|
|
156
|
+
type: 'RRSIG',
|
|
157
|
+
'type covered': typeCovered,
|
|
158
|
+
algorithm,
|
|
159
|
+
labels,
|
|
160
|
+
'original ttl': originalTtl,
|
|
161
|
+
'signature expiration': signatureExpiration,
|
|
162
|
+
'signature inception': signatureInception,
|
|
163
|
+
'key tag': keyTag,
|
|
164
|
+
'signers name': signersName,
|
|
165
|
+
signature,
|
|
166
|
+
timestamp: ts,
|
|
167
|
+
location: loc?.trim() ?? '',
|
|
168
|
+
})
|
|
169
|
+
}
|
|
114
170
|
|
|
115
171
|
/****** EXPORTERS *******/
|
|
172
|
+
toBind(zone_opts) {
|
|
173
|
+
return `${this.getPrefix(zone_opts)}\t${this.get('type covered')}\t${this.get('algorithm')}\t${this.get('labels')}\t${this.get('original ttl')}\t${this.get('signature expiration')}\t${this.get('signature inception')}\t${this.get('key tag')}\t${this.getFQDN('signers name', zone_opts)}\t${this.get('signature')}\n`
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
toTinydns() {
|
|
177
|
+
const dataRe = new RegExp(/[\r\n\t:]/, 'g')
|
|
178
|
+
return this.getTinydnsGeneric(
|
|
179
|
+
TINYDNS.UInt16toOctal(this.get('type covered')) +
|
|
180
|
+
TINYDNS.UInt8toOctal(this.get('algorithm')) +
|
|
181
|
+
TINYDNS.UInt8toOctal(this.get('labels')) +
|
|
182
|
+
TINYDNS.UInt32toOctal(this.get('original ttl')) +
|
|
183
|
+
TINYDNS.UInt32toOctal(this.get('signature expiration')) +
|
|
184
|
+
TINYDNS.UInt32toOctal(this.get('signature inception')) +
|
|
185
|
+
TINYDNS.UInt16toOctal(this.get('key tag')) +
|
|
186
|
+
TINYDNS.packDomainName(this.get('signers name')) +
|
|
187
|
+
TINYDNS.escapeOctal(dataRe, this.get('signature')),
|
|
188
|
+
)
|
|
189
|
+
}
|
|
116
190
|
}
|
package/rr/sig.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import RR from '../rr.js'
|
|
2
2
|
|
|
3
|
+
import * as TINYDNS from '../lib/tinydns.js'
|
|
4
|
+
|
|
3
5
|
export default class SIG extends RR {
|
|
4
6
|
constructor(opts) {
|
|
5
7
|
super(opts)
|
|
@@ -15,8 +17,7 @@ export default class SIG extends RR {
|
|
|
15
17
|
|
|
16
18
|
setAlgorithm(val) {
|
|
17
19
|
// a 1 octet Algorithm field
|
|
18
|
-
|
|
19
|
-
this.is8bitInt('SIG', 'labels', val)
|
|
20
|
+
this.is8bitInt('SIG', 'algorithm', val)
|
|
20
21
|
|
|
21
22
|
this.set('algorithm', val)
|
|
22
23
|
}
|
|
@@ -90,18 +91,93 @@ export default class SIG extends RR {
|
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
/****** IMPORTERS *******/
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
94
|
+
|
|
95
|
+
fromBind({ bindline }) {
|
|
96
|
+
// example.com. 3600 IN SIG TypeCovered Algorithm Labels OrigTTL SigExpiration SigInception KeyTag SignersName ( Signature )
|
|
97
|
+
const parts = bindline.trim().split(/\s+/)
|
|
98
|
+
|
|
99
|
+
return new SIG({
|
|
100
|
+
owner: parts[0],
|
|
101
|
+
ttl: parseInt(parts[1], 10),
|
|
102
|
+
class: parts[2],
|
|
103
|
+
type: 'SIG',
|
|
104
|
+
'type covered': parseInt(parts[4], 10),
|
|
105
|
+
algorithm: parseInt(parts[5], 10),
|
|
106
|
+
labels: parseInt(parts[6], 10),
|
|
107
|
+
'original ttl': parseInt(parts[7], 10),
|
|
108
|
+
'signature expiration': parseInt(parts[8], 10),
|
|
109
|
+
'signature inception': parseInt(parts[9], 10),
|
|
110
|
+
'key tag': parseInt(parts[10], 10),
|
|
111
|
+
'signers name': parts[11],
|
|
112
|
+
signature: parts
|
|
113
|
+
.slice(12)
|
|
114
|
+
.filter((a) => a !== '(' && a !== ')')
|
|
115
|
+
.join(' ')
|
|
116
|
+
.trim(),
|
|
117
|
+
})
|
|
118
|
+
}
|
|
103
119
|
|
|
104
120
|
/****** EXPORTERS *******/
|
|
121
|
+
toTinydns() {
|
|
122
|
+
const dataRe = new RegExp(/[\r\n\t:]/, 'g')
|
|
123
|
+
|
|
124
|
+
return this.getTinydnsGeneric(
|
|
125
|
+
TINYDNS.UInt16toOctal(this.get('type covered')) +
|
|
126
|
+
TINYDNS.UInt8toOctal(this.get('algorithm')) +
|
|
127
|
+
TINYDNS.UInt8toOctal(this.get('labels')) +
|
|
128
|
+
TINYDNS.UInt32toOctal(this.get('original ttl')) +
|
|
129
|
+
TINYDNS.UInt32toOctal(this.get('signature expiration')) +
|
|
130
|
+
TINYDNS.UInt32toOctal(this.get('signature inception')) +
|
|
131
|
+
TINYDNS.UInt16toOctal(this.get('key tag')) +
|
|
132
|
+
TINYDNS.packDomainName(this.get('signers name')) +
|
|
133
|
+
TINYDNS.escapeOctal(dataRe, this.get('signature')),
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
fromTinydns({ tinyline }) {
|
|
138
|
+
const [fqdn, n, rdata, ttl, ts, loc] = tinyline.substring(1).split(':')
|
|
139
|
+
if (parseInt(n, 10) !== this.getTypeId()) this.throwHelp('SIG fromTinydns, invalid n')
|
|
140
|
+
|
|
141
|
+
const bytes = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
142
|
+
|
|
143
|
+
const typeCovered = bytes.readUInt16BE(0)
|
|
144
|
+
const algorithm = bytes.readUInt8(2)
|
|
145
|
+
const labels = bytes.readUInt8(3)
|
|
146
|
+
const originalTtl = bytes.readUInt32BE(4)
|
|
147
|
+
const signatureExpiration = bytes.readUInt32BE(8)
|
|
148
|
+
const signatureInception = bytes.readUInt32BE(12)
|
|
149
|
+
const keyTag = bytes.readUInt16BE(16)
|
|
150
|
+
|
|
151
|
+
// parse signers name from binary buffer starting at offset 18
|
|
152
|
+
let pos = 18
|
|
153
|
+
const labelsArr = []
|
|
154
|
+
while (pos < bytes.length) {
|
|
155
|
+
const len = bytes.readUInt8(pos++)
|
|
156
|
+
if (len === 0) break
|
|
157
|
+
labelsArr.push(bytes.slice(pos, pos + len).toString())
|
|
158
|
+
pos += len
|
|
159
|
+
}
|
|
160
|
+
const signersName = `${labelsArr.join('.')}.`
|
|
161
|
+
|
|
162
|
+
const signature = bytes.slice(pos).toString()
|
|
163
|
+
|
|
164
|
+
return new SIG({
|
|
165
|
+
owner: this.fullyQualify(fqdn),
|
|
166
|
+
ttl: parseInt(ttl, 10),
|
|
167
|
+
type: 'SIG',
|
|
168
|
+
'type covered': typeCovered,
|
|
169
|
+
algorithm,
|
|
170
|
+
labels,
|
|
171
|
+
'original ttl': originalTtl,
|
|
172
|
+
'signature expiration': signatureExpiration,
|
|
173
|
+
'signature inception': signatureInception,
|
|
174
|
+
'key tag': keyTag,
|
|
175
|
+
'signers name': signersName,
|
|
176
|
+
signature,
|
|
177
|
+
timestamp: ts,
|
|
178
|
+
location: loc?.trim() ?? '',
|
|
179
|
+
})
|
|
180
|
+
}
|
|
105
181
|
|
|
106
182
|
toBind(zone_opts) {
|
|
107
183
|
return `${this.getFQDN('owner', zone_opts)} ${this.get('ttl')} ${this.get('class')} SIG${this.getRdataFields()
|
package/rr/smimea.js
CHANGED
|
@@ -76,9 +76,9 @@ export default class SMIMEA extends RR {
|
|
|
76
76
|
|
|
77
77
|
/****** IMPORTERS *******/
|
|
78
78
|
|
|
79
|
-
fromBind(
|
|
79
|
+
fromBind({ bindline }) {
|
|
80
80
|
// test.example.com 3600 IN SMIMEA, usage, selector, match, data
|
|
81
|
-
const [owner, ttl, c, type, usage, selector, match] =
|
|
81
|
+
const [owner, ttl, c, type, usage, selector, match] = bindline.split(/\s+/)
|
|
82
82
|
return new SMIMEA({
|
|
83
83
|
owner,
|
|
84
84
|
ttl: parseInt(ttl, 10),
|
|
@@ -87,12 +87,12 @@ export default class SMIMEA extends RR {
|
|
|
87
87
|
'certificate usage': parseInt(usage, 10),
|
|
88
88
|
selector: parseInt(selector, 10),
|
|
89
89
|
'matching type': parseInt(match, 10),
|
|
90
|
-
'certificate association data':
|
|
90
|
+
'certificate association data': bindline.split(/\s+/).slice(7).join(' ').trim(),
|
|
91
91
|
})
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
fromTinydns(
|
|
95
|
-
const [owner, _typeId, rdata, ttl, ts, loc] =
|
|
94
|
+
fromTinydns({ tinyline }) {
|
|
95
|
+
const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
96
96
|
const binaryRdata = Buffer.from(TINYDNS.octalToChar(rdata), 'binary')
|
|
97
97
|
|
|
98
98
|
return new SMIMEA({
|
|
@@ -104,7 +104,7 @@ export default class SMIMEA extends RR {
|
|
|
104
104
|
'matching type': binaryRdata.readUInt8(2),
|
|
105
105
|
'certificate association data': binaryRdata.slice(3).toString(),
|
|
106
106
|
timestamp: ts,
|
|
107
|
-
location: loc
|
|
107
|
+
location: loc?.trim() ?? '',
|
|
108
108
|
})
|
|
109
109
|
}
|
|
110
110
|
|
package/rr/soa.js
CHANGED
|
@@ -84,10 +84,10 @@ export default class SOA extends RR {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/****** IMPORTERS *******/
|
|
87
|
-
fromBind(
|
|
87
|
+
fromBind({ bindline }) {
|
|
88
88
|
// example.com TTL IN SOA mname rname serial refresh retry expire minimum
|
|
89
89
|
const [owner, ttl, c, type, mname, rname, serial, refresh, retry, expire, minimum] =
|
|
90
|
-
|
|
90
|
+
bindline.split(/[\s+]/)
|
|
91
91
|
|
|
92
92
|
return new SOA({
|
|
93
93
|
owner,
|
|
@@ -104,9 +104,9 @@ export default class SOA extends RR {
|
|
|
104
104
|
})
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
fromTinydns(
|
|
107
|
+
fromTinydns({ tinyline }) {
|
|
108
108
|
// Zfqdn:mname:rname:ser:ref:ret:exp:min:ttl:time:lo
|
|
109
|
-
const [fqdn, mname, rname, ser, ref, ret, exp, min, ttl, ts, loc] =
|
|
109
|
+
const [fqdn, mname, rname, ser, ref, ret, exp, min, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
110
110
|
|
|
111
111
|
return new SOA({
|
|
112
112
|
owner: this.fullyQualify(fqdn),
|
|
@@ -114,13 +114,13 @@ export default class SOA extends RR {
|
|
|
114
114
|
type: 'SOA',
|
|
115
115
|
mname: this.fullyQualify(mname),
|
|
116
116
|
rname: this.fullyQualify(rname),
|
|
117
|
-
serial: parseInt(ser
|
|
117
|
+
serial: parseInt(ser ?? this.default?.serial, 10),
|
|
118
118
|
refresh: parseInt(ref, 10) || 16384,
|
|
119
119
|
retry: parseInt(ret, 10) || 2048,
|
|
120
120
|
expire: parseInt(exp, 10) || 1048576,
|
|
121
121
|
minimum: parseInt(min, 10) || 2560,
|
|
122
122
|
timestamp: parseInt(ts) || '',
|
|
123
|
-
location: loc
|
|
123
|
+
location: loc?.trim() ?? '',
|
|
124
124
|
})
|
|
125
125
|
}
|
|
126
126
|
|
package/rr/spf.js
CHANGED
|
@@ -31,9 +31,9 @@ export default class SPF extends TXT {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/****** IMPORTERS *******/
|
|
34
|
-
fromTinydns(
|
|
34
|
+
fromTinydns({ tinyline }) {
|
|
35
35
|
// SPF via generic, :fqdn:n:rdata:ttl:timestamp:lo
|
|
36
|
-
const [fqdn, n, rdata, ttl, ts, loc] =
|
|
36
|
+
const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
37
37
|
if (n != 99) this.throwHelp('SPF fromTinydns, invalid n')
|
|
38
38
|
|
|
39
39
|
return new SPF({
|
|
@@ -42,7 +42,7 @@ export default class SPF extends TXT {
|
|
|
42
42
|
data: TINYDNS.octalToChar(rdata),
|
|
43
43
|
ttl: parseInt(ttl, 10),
|
|
44
44
|
timestamp: ts,
|
|
45
|
-
location: loc
|
|
45
|
+
location: loc?.trim() ?? '',
|
|
46
46
|
})
|
|
47
47
|
}
|
|
48
48
|
|
package/rr/srv.js
CHANGED
|
@@ -54,22 +54,22 @@ export default class SRV extends RR {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/****** IMPORTERS *******/
|
|
57
|
-
fromTinydns(
|
|
58
|
-
const str =
|
|
57
|
+
fromTinydns({ tinyline }) {
|
|
58
|
+
const str = tinyline
|
|
59
59
|
let fqdn, addr, port, pri, weight, ttl, ts, loc, n, rdata
|
|
60
60
|
|
|
61
61
|
if (str[0] === 'S') {
|
|
62
62
|
// patched tinydns with S records
|
|
63
|
-
;[fqdn, addr, port, pri, weight, ttl, ts, loc] = str.
|
|
63
|
+
;[fqdn, addr, port, pri, weight, ttl, ts, loc] = str.slice(1).split(':')
|
|
64
64
|
} else {
|
|
65
65
|
// tinydns generic record format
|
|
66
|
-
;[fqdn, n, rdata, ttl, ts, loc] = str.
|
|
66
|
+
;[fqdn, n, rdata, ttl, ts, loc] = str.slice(1).split(':')
|
|
67
67
|
if (n != 33) this.throwHelp('SRV fromTinydns: invalid n')
|
|
68
68
|
|
|
69
|
-
pri = TINYDNS.octalToUInt16(rdata.
|
|
70
|
-
weight = TINYDNS.octalToUInt16(rdata.
|
|
71
|
-
port = TINYDNS.octalToUInt16(rdata.
|
|
72
|
-
addr = TINYDNS.unpackDomainName(rdata.
|
|
69
|
+
pri = TINYDNS.octalToUInt16(rdata.slice(0, 8))
|
|
70
|
+
weight = TINYDNS.octalToUInt16(rdata.slice(8, 16))
|
|
71
|
+
port = TINYDNS.octalToUInt16(rdata.slice(16, 24))
|
|
72
|
+
addr = TINYDNS.unpackDomainName(rdata.slice(24))[0]
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
return new SRV({
|
|
@@ -81,13 +81,13 @@ export default class SRV extends RR {
|
|
|
81
81
|
port: parseInt(port, 10),
|
|
82
82
|
target: this.fullyQualify(addr),
|
|
83
83
|
timestamp: ts,
|
|
84
|
-
location: loc
|
|
84
|
+
location: loc?.trim() ?? '',
|
|
85
85
|
})
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
fromBind(
|
|
88
|
+
fromBind({ bindline }) {
|
|
89
89
|
// test.example.com 3600 IN SRV Priority Weight Port Target
|
|
90
|
-
const [owner, ttl, c, type, pri, weight, port, target] =
|
|
90
|
+
const [owner, ttl, c, type, pri, weight, port, target] = bindline.split(/\s+/)
|
|
91
91
|
return new SRV({
|
|
92
92
|
owner: owner,
|
|
93
93
|
ttl: parseInt(ttl, 10),
|
package/rr/sshfp.js
CHANGED
|
@@ -59,26 +59,26 @@ export default class SSHFP extends RR {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/****** IMPORTERS *******/
|
|
62
|
-
fromTinydns(
|
|
62
|
+
fromTinydns({ tinyline }) {
|
|
63
63
|
// SSHFP via generic, :fqdn:n:rdata:ttl:timestamp:lo
|
|
64
|
-
const [fqdn, n, rdata, ttl, ts, loc] =
|
|
64
|
+
const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
65
65
|
if (n != 44) this.throwHelp('SSHFP fromTinydns, invalid n')
|
|
66
66
|
|
|
67
67
|
return new SSHFP({
|
|
68
68
|
owner: this.fullyQualify(fqdn),
|
|
69
69
|
ttl: parseInt(ttl, 10),
|
|
70
70
|
type: 'SSHFP',
|
|
71
|
-
algorithm: TINYDNS.octalToUInt8(rdata.
|
|
72
|
-
fptype: TINYDNS.octalToUInt8(rdata.
|
|
73
|
-
fingerprint: TINYDNS.octalToHex(rdata.
|
|
71
|
+
algorithm: TINYDNS.octalToUInt8(rdata.slice(0, 4)),
|
|
72
|
+
fptype: TINYDNS.octalToUInt8(rdata.slice(4, 8)),
|
|
73
|
+
fingerprint: TINYDNS.octalToHex(rdata.slice(8)),
|
|
74
74
|
timestamp: ts,
|
|
75
|
-
location: loc
|
|
75
|
+
location: loc?.trim() ?? '',
|
|
76
76
|
})
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
fromBind(
|
|
79
|
+
fromBind({ bindline }) {
|
|
80
80
|
// test.example.com 3600 IN SSHFP algo fptype fp
|
|
81
|
-
const [owner, ttl, c, type, algo, fptype, fp] =
|
|
81
|
+
const [owner, ttl, c, type, algo, fptype, fp] = bindline.split(/\s+/)
|
|
82
82
|
return new SSHFP({
|
|
83
83
|
owner,
|
|
84
84
|
ttl: parseInt(ttl, 10),
|