@nictool/dns-resource-record 1.6.1 → 1.7.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 +33 -0
- package/README.md +323 -199
- package/dist/dns-rr.min.js +26 -0
- package/dist/dns-rr.min.js.map +7 -0
- package/index.js +12 -11
- package/lib/binary.js +108 -0
- package/lib/bind.js +94 -0
- package/lib/dns-query.js +67 -0
- package/lib/tinydns.js +128 -44
- package/lib/wire.js +519 -0
- package/package.json +23 -6
- package/rr/TEMPLATE.js +124 -0
- package/rr/a.js +8 -48
- package/rr/aaaa.js +13 -80
- package/rr/apl.js +123 -27
- package/rr/caa.js +27 -50
- package/rr/cert.js +58 -87
- package/rr/cname.js +7 -63
- package/rr/dhcid.js +20 -30
- package/rr/dname.js +9 -36
- package/rr/dnskey.js +38 -32
- package/rr/ds.js +43 -57
- package/rr/hinfo.js +21 -40
- package/rr/hip.js +88 -26
- package/rr/https.js +28 -40
- package/rr/ipseckey.js +97 -18
- package/rr/key.js +39 -29
- package/rr/kx.js +16 -27
- package/rr/loc.js +42 -12
- package/rr/mx.js +16 -51
- package/rr/naptr.js +58 -33
- package/rr/ns.js +8 -36
- package/rr/nsec.js +89 -18
- package/rr/nsec3.js +62 -26
- package/rr/nsec3param.js +56 -53
- package/rr/nxt.js +57 -18
- package/rr/openpgpkey.js +24 -30
- package/rr/ptr.js +7 -47
- package/rr/rp.js +17 -32
- package/rr/rrsig.js +80 -85
- package/rr/sig.js +70 -45
- package/rr/smimea.js +33 -33
- package/rr/soa.js +31 -49
- package/rr/spf.js +10 -17
- package/rr/srv.js +22 -62
- package/rr/sshfp.js +25 -53
- package/rr/svcb.js +27 -40
- package/rr/tlsa.js +34 -34
- package/rr/tsig.js +87 -24
- package/rr/txt.js +40 -59
- package/rr/uri.js +19 -29
- package/rr/wks.js +154 -22
- package/rr.js +290 -109
- package/lib/readme.js +0 -84
package/rr/ptr.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import RR from '../rr.js'
|
|
2
2
|
|
|
3
3
|
export default class PTR extends RR {
|
|
4
|
+
static typeName = 'PTR'
|
|
5
|
+
static typeId = 12
|
|
6
|
+
static RFCs = [1035]
|
|
7
|
+
static tinydnsType = '^'
|
|
8
|
+
static rdataFields = [['dname', 'fqdn']]
|
|
9
|
+
static tags = ['common']
|
|
10
|
+
|
|
4
11
|
constructor(opts) {
|
|
5
12
|
super(opts)
|
|
6
13
|
}
|
|
@@ -18,22 +25,6 @@ export default class PTR extends RR {
|
|
|
18
25
|
return 'Pointer'
|
|
19
26
|
}
|
|
20
27
|
|
|
21
|
-
getTags() {
|
|
22
|
-
return ['common']
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
getRdataFields(arg) {
|
|
26
|
-
return ['dname']
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
getRFCs() {
|
|
30
|
-
return [1035]
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
getTypeId() {
|
|
34
|
-
return 12
|
|
35
|
-
}
|
|
36
|
-
|
|
37
28
|
getCanonical() {
|
|
38
29
|
return {
|
|
39
30
|
owner: '2.2.0.192.in-addr.arpa.',
|
|
@@ -44,39 +35,8 @@ export default class PTR extends RR {
|
|
|
44
35
|
}
|
|
45
36
|
}
|
|
46
37
|
|
|
47
|
-
/****** IMPORTERS *******/
|
|
48
|
-
fromTinydns({ tinyline }) {
|
|
49
|
-
// ^fqdn:p:ttl:timestamp:lo
|
|
50
|
-
const [fqdn, p, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
51
|
-
|
|
52
|
-
return new PTR({
|
|
53
|
-
owner: this.fullyQualify(fqdn),
|
|
54
|
-
ttl: parseInt(ttl, 10),
|
|
55
|
-
type: 'PTR',
|
|
56
|
-
dname: this.fullyQualify(p),
|
|
57
|
-
timestamp: ts,
|
|
58
|
-
location: loc?.trim() ?? '',
|
|
59
|
-
})
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
fromBind({ bindline }) {
|
|
63
|
-
// test.example.com 3600 IN PTR dname
|
|
64
|
-
const [owner, ttl, c, type, dname] = bindline.split(/\s+/)
|
|
65
|
-
return new PTR({
|
|
66
|
-
owner,
|
|
67
|
-
ttl: parseInt(ttl, 10),
|
|
68
|
-
class: c,
|
|
69
|
-
type: type,
|
|
70
|
-
dname: dname,
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
|
|
74
38
|
/****** EXPORTERS *******/
|
|
75
39
|
getWireRdata() {
|
|
76
40
|
return this.wirePackDomain(this.get('dname'))
|
|
77
41
|
}
|
|
78
|
-
|
|
79
|
-
toTinydns() {
|
|
80
|
-
return `^${this.getTinyFQDN('owner')}:${this.getTinyFQDN('dname')}:${this.getTinydnsPostamble()}\n`
|
|
81
|
-
}
|
|
82
42
|
}
|
package/rr/rp.js
CHANGED
|
@@ -3,6 +3,12 @@ import RR from '../rr.js'
|
|
|
3
3
|
import * as TINYDNS from '../lib/tinydns.js'
|
|
4
4
|
|
|
5
5
|
export default class RP extends RR {
|
|
6
|
+
static typeName = 'RP'
|
|
7
|
+
static rdataFields = [
|
|
8
|
+
['mbox', 'fqdn'],
|
|
9
|
+
['txt', 'fqdn'],
|
|
10
|
+
]
|
|
11
|
+
|
|
6
12
|
constructor(opts) {
|
|
7
13
|
super(opts)
|
|
8
14
|
}
|
|
@@ -27,23 +33,9 @@ export default class RP extends RR {
|
|
|
27
33
|
getDescription() {
|
|
28
34
|
return 'Responsible Person'
|
|
29
35
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
getRdataFields(arg) {
|
|
36
|
-
return ['mbox', 'txt']
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
getRFCs() {
|
|
40
|
-
return [1183]
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
getTypeId() {
|
|
44
|
-
return 17
|
|
45
|
-
}
|
|
46
|
-
|
|
36
|
+
static tags = ['obsolete']
|
|
37
|
+
static RFCs = [1183]
|
|
38
|
+
static typeId = 17
|
|
47
39
|
getCanonical() {
|
|
48
40
|
return {
|
|
49
41
|
owner: 'example.com.',
|
|
@@ -56,19 +48,6 @@ export default class RP extends RR {
|
|
|
56
48
|
}
|
|
57
49
|
|
|
58
50
|
/****** IMPORTERS *******/
|
|
59
|
-
fromBind({ bindline }) {
|
|
60
|
-
// test.example.com 3600 IN RP mbox txt
|
|
61
|
-
const [owner, ttl, c, type, mbox, txt] = bindline.split(/\s+/)
|
|
62
|
-
return new RP({
|
|
63
|
-
owner,
|
|
64
|
-
ttl: parseInt(ttl, 10),
|
|
65
|
-
class: c,
|
|
66
|
-
type,
|
|
67
|
-
mbox,
|
|
68
|
-
txt,
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
-
|
|
72
51
|
fromTinydns({ tinyline }) {
|
|
73
52
|
const [owner, _typeId, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
74
53
|
|
|
@@ -87,8 +66,14 @@ export default class RP extends RR {
|
|
|
87
66
|
}
|
|
88
67
|
|
|
89
68
|
/****** EXPORTERS *******/
|
|
90
|
-
|
|
91
|
-
|
|
69
|
+
|
|
70
|
+
getWireRdata() {
|
|
71
|
+
const mbox = this.wirePackDomain(this.get('mbox'))
|
|
72
|
+
const txt = this.wirePackDomain(this.get('txt'))
|
|
73
|
+
const result = new Uint8Array(mbox.length + txt.length)
|
|
74
|
+
result.set(mbox, 0)
|
|
75
|
+
result.set(txt, mbox.length)
|
|
76
|
+
return result
|
|
92
77
|
}
|
|
93
78
|
|
|
94
79
|
toTinydns() {
|
package/rr/rrsig.js
CHANGED
|
@@ -1,17 +1,44 @@
|
|
|
1
1
|
import RR from '../rr.js'
|
|
2
2
|
import * as TINYDNS from '../lib/tinydns.js'
|
|
3
|
+
import * as WIRE from '../lib/binary.js'
|
|
4
|
+
import * as WIRELIB from '../lib/wire.js'
|
|
3
5
|
|
|
4
6
|
export default class RRSIG extends RR {
|
|
7
|
+
static typeName = 'RRSIG'
|
|
8
|
+
static typeId = 46
|
|
9
|
+
static RFCs = [4034]
|
|
10
|
+
static rdataFields = [
|
|
11
|
+
['type covered', 'u16'],
|
|
12
|
+
['algorithm', 'u8'],
|
|
13
|
+
['labels', 'u8'],
|
|
14
|
+
['original ttl', 'u32'],
|
|
15
|
+
['signature expiration', 'u32'],
|
|
16
|
+
['signature inception', 'u32'],
|
|
17
|
+
['key tag', 'u16'],
|
|
18
|
+
['signers name', 'fqdn'],
|
|
19
|
+
['signature', 'str'],
|
|
20
|
+
]
|
|
21
|
+
static tags = ['dnssec']
|
|
22
|
+
|
|
5
23
|
constructor(opts) {
|
|
6
24
|
super(opts)
|
|
7
25
|
}
|
|
8
26
|
|
|
9
27
|
/****** Resource record specific setters *******/
|
|
10
28
|
setTypeCovered(val) {
|
|
11
|
-
// a
|
|
12
|
-
if (!val) this.throwHelp(`RRSIG: 'type covered' is required`)
|
|
13
|
-
if (val
|
|
14
|
-
|
|
29
|
+
// a 16-bit Type Covered field (RFC 4034 §3.1.1)
|
|
30
|
+
if (!val && val !== 0) this.throwHelp(`RRSIG: 'type covered' is required`)
|
|
31
|
+
if (typeof val === 'string') {
|
|
32
|
+
const typeNN = val.match(/^TYPE(\d+)$/i)
|
|
33
|
+
if (typeNN) {
|
|
34
|
+
val = parseInt(typeNN[1], 10)
|
|
35
|
+
} else {
|
|
36
|
+
const id = WIRE.DNS_TYPE_IDS[val.toUpperCase()]
|
|
37
|
+
if (id === undefined) this.throwHelp(`RRSIG: 'type covered' is not a recognized type name`)
|
|
38
|
+
val = id
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
this.is16bitInt('RRSIG', 'type covered', val)
|
|
15
42
|
this.set('type covered', val)
|
|
16
43
|
}
|
|
17
44
|
|
|
@@ -34,76 +61,10 @@ export default class RRSIG extends RR {
|
|
|
34
61
|
])
|
|
35
62
|
}
|
|
36
63
|
|
|
37
|
-
setLabels(val) {
|
|
38
|
-
// a 1 octet Labels field
|
|
39
|
-
this.is8bitInt('RRSIG', 'labels', val)
|
|
40
|
-
|
|
41
|
-
this.set('labels', val)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
setOriginalTtl(val) {
|
|
45
|
-
// a 4 octet Original TTL field
|
|
46
|
-
this.is32bitInt('RRSIG', 'original ttl', val)
|
|
47
|
-
|
|
48
|
-
this.set('original ttl', val)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
setSignatureExpiration(val) {
|
|
52
|
-
// a 4 octet Signature Expiration field
|
|
53
|
-
this.set('signature expiration', val)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
setSignatureInception(val) {
|
|
57
|
-
// a 4 octet Signature Inception field
|
|
58
|
-
this.set('signature inception', val)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
setKeyTag(val) {
|
|
62
|
-
// a 2 octet Key tag
|
|
63
|
-
this.set('key tag', val)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
setSignersName(val) {
|
|
67
|
-
// the Signer's Name field
|
|
68
|
-
this.set('signers name', val)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
setSignature(val) {
|
|
72
|
-
// the Signature field.
|
|
73
|
-
|
|
74
|
-
this.set('signature', val)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
64
|
getDescription() {
|
|
78
65
|
return 'Resource Record Signature'
|
|
79
66
|
}
|
|
80
67
|
|
|
81
|
-
getTags() {
|
|
82
|
-
return ['dnssec']
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
getRdataFields(arg) {
|
|
86
|
-
return [
|
|
87
|
-
'type covered',
|
|
88
|
-
'algorithm',
|
|
89
|
-
'labels',
|
|
90
|
-
'original ttl',
|
|
91
|
-
'signature expiration',
|
|
92
|
-
'signature inception',
|
|
93
|
-
'key tag',
|
|
94
|
-
'signers name',
|
|
95
|
-
'signature',
|
|
96
|
-
]
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
getRFCs() {
|
|
100
|
-
return [4034]
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
getTypeId() {
|
|
104
|
-
return 46
|
|
105
|
-
}
|
|
106
|
-
|
|
107
68
|
getCanonical() {
|
|
108
69
|
return {
|
|
109
70
|
owner: 'example.com.',
|
|
@@ -127,12 +88,20 @@ export default class RRSIG extends RR {
|
|
|
127
88
|
fromBind({ bindline }) {
|
|
128
89
|
// example.com. 3600 IN RRSIG typecovered algorithm labels origttl sigexp siginc keytag signersname ( signature )
|
|
129
90
|
const parts = bindline.trim().split(/\s+/)
|
|
91
|
+
const typeCoveredStr = parts[4]
|
|
92
|
+
// type covered may be a type name ('A', 'MX'), TYPEnn (RFC 3597), or a numeric ID
|
|
93
|
+
const typeNN = typeCoveredStr.match(/^TYPE(\d+)$/i)
|
|
94
|
+
const typeCovered = /^\d+$/.test(typeCoveredStr)
|
|
95
|
+
? parseInt(typeCoveredStr, 10)
|
|
96
|
+
: typeNN
|
|
97
|
+
? parseInt(typeNN[1], 10)
|
|
98
|
+
: (WIRE.DNS_TYPE_IDS[typeCoveredStr.toUpperCase()] ?? parseInt(typeCoveredStr, 10))
|
|
130
99
|
return new RRSIG({
|
|
131
100
|
owner: parts[0],
|
|
132
101
|
ttl: parseInt(parts[1], 10),
|
|
133
102
|
class: parts[2],
|
|
134
103
|
type: 'RRSIG',
|
|
135
|
-
'type covered':
|
|
104
|
+
'type covered': typeCovered,
|
|
136
105
|
algorithm: parseInt(parts[5], 10),
|
|
137
106
|
labels: parseInt(parts[6], 10),
|
|
138
107
|
'original ttl': parseInt(parts[7], 10),
|
|
@@ -152,25 +121,26 @@ export default class RRSIG extends RR {
|
|
|
152
121
|
const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
153
122
|
if (parseInt(n, 10) !== this.getTypeId()) this.throwHelp('RRSIG fromTinydns, invalid n')
|
|
154
123
|
|
|
155
|
-
const bytes =
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
const
|
|
124
|
+
const bytes = Uint8Array.from(TINYDNS.octalToChar(rdata), (c) => c.charCodeAt(0))
|
|
125
|
+
const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
|
|
126
|
+
const typeCovered = dv.getUint16(0)
|
|
127
|
+
const algorithm = bytes[2]
|
|
128
|
+
const labels = bytes[3]
|
|
129
|
+
const originalTtl = dv.getUint32(4)
|
|
130
|
+
const signatureExpiration = dv.getUint32(8)
|
|
131
|
+
const signatureInception = dv.getUint32(12)
|
|
132
|
+
const keyTag = dv.getUint16(16)
|
|
163
133
|
|
|
164
134
|
let pos = 18
|
|
165
135
|
const labelArr = []
|
|
166
136
|
while (pos < bytes.length) {
|
|
167
|
-
const len = bytes
|
|
137
|
+
const len = bytes[pos++]
|
|
168
138
|
if (len === 0) break
|
|
169
|
-
labelArr.push(bytes.
|
|
139
|
+
labelArr.push(new TextDecoder().decode(bytes.subarray(pos, pos + len)))
|
|
170
140
|
pos += len
|
|
171
141
|
}
|
|
172
142
|
const signersName = `${labelArr.join('.')}.`
|
|
173
|
-
const signature = bytes.
|
|
143
|
+
const signature = new TextDecoder().decode(bytes.subarray(pos))
|
|
174
144
|
|
|
175
145
|
return new RRSIG({
|
|
176
146
|
owner: this.fullyQualify(fqdn),
|
|
@@ -191,9 +161,6 @@ export default class RRSIG extends RR {
|
|
|
191
161
|
}
|
|
192
162
|
|
|
193
163
|
/****** EXPORTERS *******/
|
|
194
|
-
toBind(zone_opts) {
|
|
195
|
-
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`
|
|
196
|
-
}
|
|
197
164
|
|
|
198
165
|
toTinydns() {
|
|
199
166
|
const dataRe = new RegExp(/[\r\n\t:]/, 'g')
|
|
@@ -209,4 +176,32 @@ export default class RRSIG extends RR {
|
|
|
209
176
|
TINYDNS.escapeOctal(dataRe, this.get('signature')),
|
|
210
177
|
)
|
|
211
178
|
}
|
|
179
|
+
|
|
180
|
+
getWireRdata() {
|
|
181
|
+
const signerBytes = WIRELIB.wirePackDomain(this.get('signers name'))
|
|
182
|
+
const sigBytes = new TextEncoder().encode(this.get('signature'))
|
|
183
|
+
|
|
184
|
+
const totalLen = 2 + 1 + 1 + 4 + 4 + 4 + 2 + signerBytes.length + sigBytes.length
|
|
185
|
+
const bytes = new Uint8Array(totalLen)
|
|
186
|
+
const dv = new DataView(bytes.buffer, bytes.byteOffset)
|
|
187
|
+
|
|
188
|
+
let pos = 0
|
|
189
|
+
dv.setUint16(pos, this.get('type covered'))
|
|
190
|
+
pos += 2
|
|
191
|
+
bytes[pos++] = this.get('algorithm')
|
|
192
|
+
bytes[pos++] = this.get('labels')
|
|
193
|
+
dv.setUint32(pos, this.get('original ttl'))
|
|
194
|
+
pos += 4
|
|
195
|
+
dv.setUint32(pos, this.get('signature expiration'))
|
|
196
|
+
pos += 4
|
|
197
|
+
dv.setUint32(pos, this.get('signature inception'))
|
|
198
|
+
pos += 4
|
|
199
|
+
dv.setUint16(pos, this.get('key tag'))
|
|
200
|
+
pos += 2
|
|
201
|
+
bytes.set(signerBytes, pos)
|
|
202
|
+
pos += signerBytes.length
|
|
203
|
+
bytes.set(sigBytes, pos)
|
|
204
|
+
|
|
205
|
+
return bytes
|
|
206
|
+
}
|
|
212
207
|
}
|
package/rr/sig.js
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import RR from '../rr.js'
|
|
2
2
|
|
|
3
3
|
import * as TINYDNS from '../lib/tinydns.js'
|
|
4
|
+
import * as WIRE from '../lib/binary.js'
|
|
5
|
+
import * as WIRELIB from '../lib/wire.js'
|
|
4
6
|
|
|
5
7
|
export default class SIG extends RR {
|
|
8
|
+
static typeName = 'SIG'
|
|
9
|
+
static typeId = 24
|
|
10
|
+
static RFCs = [2535, 3755]
|
|
11
|
+
static rdataFields = [
|
|
12
|
+
['type covered', 'u16'],
|
|
13
|
+
['algorithm', 'u8'],
|
|
14
|
+
['labels', 'u8'],
|
|
15
|
+
['original ttl', 'u32'],
|
|
16
|
+
['signature expiration', 'u32'],
|
|
17
|
+
['signature inception', 'u32'],
|
|
18
|
+
['key tag', 'u16'],
|
|
19
|
+
['signers name', 'fqdn'],
|
|
20
|
+
['signature', 'str'],
|
|
21
|
+
]
|
|
22
|
+
static tags = ['obsolete']
|
|
23
|
+
|
|
6
24
|
constructor(opts) {
|
|
7
25
|
super(opts)
|
|
8
26
|
}
|
|
@@ -68,32 +86,6 @@ export default class SIG extends RR {
|
|
|
68
86
|
return 'Signature'
|
|
69
87
|
}
|
|
70
88
|
|
|
71
|
-
getTags() {
|
|
72
|
-
return ['obsolete']
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
getRdataFields(arg) {
|
|
76
|
-
return [
|
|
77
|
-
'type covered',
|
|
78
|
-
'algorithm',
|
|
79
|
-
'labels',
|
|
80
|
-
'original ttl',
|
|
81
|
-
'signature expiration',
|
|
82
|
-
'signature inception',
|
|
83
|
-
'key tag',
|
|
84
|
-
'signers name',
|
|
85
|
-
'signature',
|
|
86
|
-
]
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
getRFCs() {
|
|
90
|
-
return [2535, 3755]
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
getTypeId() {
|
|
94
|
-
return 24
|
|
95
|
-
}
|
|
96
|
-
|
|
97
89
|
getCanonical() {
|
|
98
90
|
return {
|
|
99
91
|
owner: 'example.com.',
|
|
@@ -117,13 +109,17 @@ export default class SIG extends RR {
|
|
|
117
109
|
fromBind({ bindline }) {
|
|
118
110
|
// example.com. 3600 IN SIG TypeCovered Algorithm Labels OrigTTL SigExpiration SigInception KeyTag SignersName ( Signature )
|
|
119
111
|
const parts = bindline.trim().split(/\s+/)
|
|
112
|
+
const typeCoveredStr = parts[4]
|
|
113
|
+
const typeCovered = /^\d+$/.test(typeCoveredStr)
|
|
114
|
+
? parseInt(typeCoveredStr, 10)
|
|
115
|
+
: (WIRE.DNS_TYPE_IDS[typeCoveredStr.toUpperCase()] ?? parseInt(typeCoveredStr, 10))
|
|
120
116
|
|
|
121
117
|
return new SIG({
|
|
122
118
|
owner: parts[0],
|
|
123
119
|
ttl: parseInt(parts[1], 10),
|
|
124
120
|
class: parts[2],
|
|
125
121
|
type: 'SIG',
|
|
126
|
-
'type covered':
|
|
122
|
+
'type covered': typeCovered,
|
|
127
123
|
algorithm: parseInt(parts[5], 10),
|
|
128
124
|
labels: parseInt(parts[6], 10),
|
|
129
125
|
'original ttl': parseInt(parts[7], 10),
|
|
@@ -156,36 +152,65 @@ export default class SIG extends RR {
|
|
|
156
152
|
)
|
|
157
153
|
}
|
|
158
154
|
|
|
155
|
+
getWireRdata() {
|
|
156
|
+
const signerBytes = WIRELIB.wirePackDomain(this.get('signers name'))
|
|
157
|
+
const sigBytes = new TextEncoder().encode(this.get('signature'))
|
|
158
|
+
|
|
159
|
+
const totalLen = 2 + 1 + 1 + 4 + 4 + 4 + 2 + signerBytes.length + sigBytes.length
|
|
160
|
+
const bytes = new Uint8Array(totalLen)
|
|
161
|
+
const dv = new DataView(bytes.buffer, bytes.byteOffset)
|
|
162
|
+
|
|
163
|
+
let pos = 0
|
|
164
|
+
dv.setUint16(pos, this.get('type covered'))
|
|
165
|
+
pos += 2
|
|
166
|
+
bytes[pos++] = this.get('algorithm')
|
|
167
|
+
bytes[pos++] = this.get('labels')
|
|
168
|
+
dv.setUint32(pos, this.get('original ttl'))
|
|
169
|
+
pos += 4
|
|
170
|
+
dv.setUint32(pos, this.get('signature expiration'))
|
|
171
|
+
pos += 4
|
|
172
|
+
dv.setUint32(pos, this.get('signature inception'))
|
|
173
|
+
pos += 4
|
|
174
|
+
dv.setUint16(pos, this.get('key tag'))
|
|
175
|
+
pos += 2
|
|
176
|
+
bytes.set(signerBytes, pos)
|
|
177
|
+
pos += signerBytes.length
|
|
178
|
+
bytes.set(sigBytes, pos)
|
|
179
|
+
|
|
180
|
+
return bytes
|
|
181
|
+
}
|
|
182
|
+
|
|
159
183
|
fromTinydns({ tinyline }) {
|
|
160
|
-
const
|
|
161
|
-
if (parseInt(
|
|
184
|
+
const { owner, typeId, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline)
|
|
185
|
+
if (parseInt(typeId, 10) !== this.getTypeId()) this.throwHelp('SIG fromTinydns, invalid n')
|
|
162
186
|
|
|
163
|
-
const bytes =
|
|
187
|
+
const bytes = TINYDNS.octalRdataToBytes(rdata)
|
|
188
|
+
const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
|
|
164
189
|
|
|
165
|
-
const typeCovered =
|
|
166
|
-
const algorithm = bytes
|
|
167
|
-
const labels = bytes
|
|
168
|
-
const originalTtl =
|
|
169
|
-
const signatureExpiration =
|
|
170
|
-
const signatureInception =
|
|
171
|
-
const keyTag =
|
|
190
|
+
const typeCovered = dv.getUint16(0)
|
|
191
|
+
const algorithm = bytes[2]
|
|
192
|
+
const labels = bytes[3]
|
|
193
|
+
const originalTtl = dv.getUint32(4)
|
|
194
|
+
const signatureExpiration = dv.getUint32(8)
|
|
195
|
+
const signatureInception = dv.getUint32(12)
|
|
196
|
+
const keyTag = dv.getUint16(16)
|
|
172
197
|
|
|
173
|
-
// parse signers name from binary
|
|
198
|
+
// parse signers name from binary starting at offset 18
|
|
174
199
|
let pos = 18
|
|
175
200
|
const labelsArr = []
|
|
176
201
|
while (pos < bytes.length) {
|
|
177
|
-
const len = bytes
|
|
202
|
+
const len = bytes[pos++]
|
|
178
203
|
if (len === 0) break
|
|
179
|
-
labelsArr.push(bytes.
|
|
204
|
+
labelsArr.push(new TextDecoder().decode(bytes.subarray(pos, pos + len)))
|
|
180
205
|
pos += len
|
|
181
206
|
}
|
|
182
207
|
const signersName = `${labelsArr.join('.')}.`
|
|
183
208
|
|
|
184
|
-
const signature = bytes.
|
|
209
|
+
const signature = new TextDecoder().decode(bytes.subarray(pos))
|
|
185
210
|
|
|
186
211
|
return new SIG({
|
|
187
|
-
owner
|
|
188
|
-
ttl
|
|
212
|
+
owner,
|
|
213
|
+
ttl,
|
|
189
214
|
type: 'SIG',
|
|
190
215
|
'type covered': typeCovered,
|
|
191
216
|
algorithm,
|
|
@@ -196,8 +221,8 @@ export default class SIG extends RR {
|
|
|
196
221
|
'key tag': keyTag,
|
|
197
222
|
'signers name': signersName,
|
|
198
223
|
signature,
|
|
199
|
-
timestamp
|
|
200
|
-
location
|
|
224
|
+
timestamp,
|
|
225
|
+
location,
|
|
201
226
|
})
|
|
202
227
|
}
|
|
203
228
|
|
package/rr/smimea.js
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import RR from '../rr.js'
|
|
2
2
|
|
|
3
3
|
import * as TINYDNS from '../lib/tinydns.js'
|
|
4
|
+
import * as BINARY from '../lib/binary.js'
|
|
4
5
|
|
|
5
6
|
export default class SMIMEA extends RR {
|
|
7
|
+
static typeName = 'SMIMEA'
|
|
8
|
+
static typeId = 53
|
|
9
|
+
static RFCs = [8162]
|
|
10
|
+
static rdataFields = [
|
|
11
|
+
['certificate usage', 'u8'],
|
|
12
|
+
['selector', 'u8'],
|
|
13
|
+
['matching type', 'u8'],
|
|
14
|
+
['certificate association data', 'hex'],
|
|
15
|
+
]
|
|
16
|
+
static tags = ['security']
|
|
17
|
+
|
|
6
18
|
constructor(opts) {
|
|
7
19
|
super(opts)
|
|
8
20
|
}
|
|
@@ -58,22 +70,6 @@ export default class SMIMEA extends RR {
|
|
|
58
70
|
return 'S/MIME cert association'
|
|
59
71
|
}
|
|
60
72
|
|
|
61
|
-
getTags() {
|
|
62
|
-
return ['security']
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
getRdataFields(arg) {
|
|
66
|
-
return ['certificate usage', 'selector', 'matching type', 'certificate association data']
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
getRFCs() {
|
|
70
|
-
return [8162]
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
getTypeId() {
|
|
74
|
-
return 53
|
|
75
|
-
}
|
|
76
|
-
|
|
77
73
|
getCanonical() {
|
|
78
74
|
return {
|
|
79
75
|
owner: '_443._tcp.www.example.com.',
|
|
@@ -87,10 +83,6 @@ export default class SMIMEA extends RR {
|
|
|
87
83
|
}
|
|
88
84
|
}
|
|
89
85
|
|
|
90
|
-
getQuotedFields() {
|
|
91
|
-
return []
|
|
92
|
-
}
|
|
93
|
-
|
|
94
86
|
/****** IMPORTERS *******/
|
|
95
87
|
|
|
96
88
|
fromBind({ bindline }) {
|
|
@@ -109,31 +101,39 @@ export default class SMIMEA extends RR {
|
|
|
109
101
|
}
|
|
110
102
|
|
|
111
103
|
fromTinydns({ tinyline }) {
|
|
112
|
-
const
|
|
113
|
-
const binaryRdata =
|
|
104
|
+
const { owner, rdata, ttl, timestamp, location } = this.parseTinydnsLine(tinyline)
|
|
105
|
+
const binaryRdata = TINYDNS.octalRdataToBytes(rdata)
|
|
114
106
|
|
|
115
107
|
return new SMIMEA({
|
|
116
|
-
owner
|
|
117
|
-
ttl
|
|
108
|
+
owner,
|
|
109
|
+
ttl,
|
|
118
110
|
type: 'SMIMEA',
|
|
119
|
-
'certificate usage': binaryRdata
|
|
120
|
-
selector: binaryRdata
|
|
121
|
-
'matching type': binaryRdata
|
|
122
|
-
'certificate association data': binaryRdata.
|
|
123
|
-
timestamp
|
|
124
|
-
location
|
|
111
|
+
'certificate usage': binaryRdata[0],
|
|
112
|
+
selector: binaryRdata[1],
|
|
113
|
+
'matching type': binaryRdata[2],
|
|
114
|
+
'certificate association data': BINARY.bytesToHex(binaryRdata.subarray(3)),
|
|
115
|
+
timestamp,
|
|
116
|
+
location,
|
|
125
117
|
})
|
|
126
118
|
}
|
|
127
119
|
|
|
128
120
|
/****** EXPORTERS *******/
|
|
129
121
|
toTinydns() {
|
|
130
|
-
const dataRe = new RegExp(/[\r\n\t:\\/]/, 'g')
|
|
131
|
-
|
|
132
122
|
return this.getTinydnsGeneric(
|
|
133
123
|
TINYDNS.UInt8toOctal(this.get('certificate usage')) +
|
|
134
124
|
TINYDNS.UInt8toOctal(this.get('selector')) +
|
|
135
125
|
TINYDNS.UInt8toOctal(this.get('matching type')) +
|
|
136
|
-
TINYDNS.
|
|
126
|
+
TINYDNS.packHex(this.get('certificate association data').replace(/[\s()]/g, '')),
|
|
137
127
|
)
|
|
138
128
|
}
|
|
129
|
+
|
|
130
|
+
getWireRdata() {
|
|
131
|
+
const cadBytes = BINARY.hexToBytes(this.get('certificate association data').replace(/[\s()]/g, ''))
|
|
132
|
+
const bytes = new Uint8Array(3 + cadBytes.length)
|
|
133
|
+
bytes[0] = this.get('certificate usage')
|
|
134
|
+
bytes[1] = this.get('selector')
|
|
135
|
+
bytes[2] = this.get('matching type')
|
|
136
|
+
bytes.set(cadBytes, 3)
|
|
137
|
+
return bytes
|
|
138
|
+
}
|
|
139
139
|
}
|