@nictool/dns-resource-record 1.6.1 → 1.8.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 +47 -0
- package/README.md +356 -199
- package/dist/dns-rr.cjs +7050 -0
- 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 +96 -0
- package/lib/dns-query.js +67 -0
- package/lib/tinydns.js +128 -44
- package/lib/wire.js +629 -0
- package/package.json +28 -8
- 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 +60 -81
- package/rr/cname.js +8 -59
- package/rr/dhcid.js +20 -30
- package/rr/dname.js +10 -32
- package/rr/dnskey.js +38 -32
- package/rr/ds.js +59 -54
- 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 +17 -48
- 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 +108 -75
- package/rr/sig.js +70 -45
- package/rr/smimea.js +33 -33
- package/rr/soa.js +31 -49
- package/rr/spf.js +15 -18
- package/rr/srv.js +28 -51
- package/rr/sshfp.js +35 -48
- package/rr/svcb.js +27 -40
- package/rr/tlsa.js +34 -34
- package/rr/tsig.js +87 -24
- package/rr/txt.js +77 -68
- 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
|
|
|
@@ -22,88 +49,60 @@ export default class RRSIG extends RR {
|
|
|
22
49
|
this.set('algorithm', val)
|
|
23
50
|
}
|
|
24
51
|
|
|
25
|
-
getAlgorithmOptions() {
|
|
26
|
-
return new Map([
|
|
27
|
-
[1, 'RSA/MD5'],
|
|
28
|
-
[2, 'DH'],
|
|
29
|
-
[3, 'RRSIGA/SHA-1'],
|
|
30
|
-
[4, 'EC'],
|
|
31
|
-
[5, 'RSA/SHA-1'],
|
|
32
|
-
[253],
|
|
33
|
-
[254],
|
|
34
|
-
])
|
|
35
|
-
}
|
|
36
|
-
|
|
37
52
|
setLabels(val) {
|
|
38
|
-
|
|
39
|
-
this.is8bitInt('RRSIG', 'labels', val)
|
|
40
|
-
|
|
41
|
-
this.set('labels', val)
|
|
53
|
+
this.setTypedValue('u8', 'labels', val)
|
|
42
54
|
}
|
|
43
55
|
|
|
44
56
|
setOriginalTtl(val) {
|
|
45
|
-
|
|
46
|
-
this.is32bitInt('RRSIG', 'original ttl', val)
|
|
47
|
-
|
|
48
|
-
this.set('original ttl', val)
|
|
57
|
+
this.setTypedValue('u32', 'original ttl', val)
|
|
49
58
|
}
|
|
50
59
|
|
|
51
60
|
setSignatureExpiration(val) {
|
|
52
|
-
|
|
53
|
-
this.set('signature expiration', val)
|
|
61
|
+
this.setTypedValue('u32', 'signature expiration', val)
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
setSignatureInception(val) {
|
|
57
|
-
|
|
58
|
-
this.set('signature inception', val)
|
|
65
|
+
this.setTypedValue('u32', 'signature inception', val)
|
|
59
66
|
}
|
|
60
67
|
|
|
61
68
|
setKeyTag(val) {
|
|
62
|
-
|
|
63
|
-
this.set('key tag', val)
|
|
69
|
+
this.setTypedValue('u16', 'key tag', val)
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
setSignersName(val) {
|
|
67
|
-
|
|
68
|
-
this.set('signers name', val)
|
|
73
|
+
this.setTypedValue('fqdn', 'signers name', val)
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
setSignature(val) {
|
|
72
|
-
|
|
77
|
+
this.setTypedValue('str', 'signature', val)
|
|
78
|
+
}
|
|
73
79
|
|
|
74
|
-
|
|
80
|
+
getAlgorithmOptions() {
|
|
81
|
+
// IANA DNSSEC Algorithm Numbers
|
|
82
|
+
// https://www.iana.org/assignments/dns-sec-alg-numbers/
|
|
83
|
+
return new Map([
|
|
84
|
+
[1, 'RSA/MD5'],
|
|
85
|
+
[2, 'DH'],
|
|
86
|
+
[3, 'DSA/SHA-1'],
|
|
87
|
+
[4, 'EC'],
|
|
88
|
+
[5, 'RSA/SHA-1'],
|
|
89
|
+
[6, 'DSA-NSEC3-SHA1'],
|
|
90
|
+
[7, 'RSASHA1-NSEC3-SHA1'],
|
|
91
|
+
[8, 'RSA/SHA-256'],
|
|
92
|
+
[10, 'RSA/SHA-512'],
|
|
93
|
+
[13, 'ECDSA P-256/SHA-256'],
|
|
94
|
+
[14, 'ECDSA P-384/SHA-384'],
|
|
95
|
+
[15, 'Ed25519'],
|
|
96
|
+
[16, 'Ed448'],
|
|
97
|
+
[253],
|
|
98
|
+
[254],
|
|
99
|
+
])
|
|
75
100
|
}
|
|
76
101
|
|
|
77
102
|
getDescription() {
|
|
78
103
|
return 'Resource Record Signature'
|
|
79
104
|
}
|
|
80
105
|
|
|
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
106
|
getCanonical() {
|
|
108
107
|
return {
|
|
109
108
|
owner: 'example.com.',
|
|
@@ -127,12 +126,20 @@ export default class RRSIG extends RR {
|
|
|
127
126
|
fromBind({ bindline }) {
|
|
128
127
|
// example.com. 3600 IN RRSIG typecovered algorithm labels origttl sigexp siginc keytag signersname ( signature )
|
|
129
128
|
const parts = bindline.trim().split(/\s+/)
|
|
129
|
+
const typeCoveredStr = parts[4]
|
|
130
|
+
// type covered may be a type name ('A', 'MX'), TYPEnn (RFC 3597), or a numeric ID
|
|
131
|
+
const typeNN = typeCoveredStr.match(/^TYPE(\d+)$/i)
|
|
132
|
+
const typeCovered = /^\d+$/.test(typeCoveredStr)
|
|
133
|
+
? parseInt(typeCoveredStr, 10)
|
|
134
|
+
: typeNN
|
|
135
|
+
? parseInt(typeNN[1], 10)
|
|
136
|
+
: (WIRE.DNS_TYPE_IDS[typeCoveredStr.toUpperCase()] ?? parseInt(typeCoveredStr, 10))
|
|
130
137
|
return new RRSIG({
|
|
131
138
|
owner: parts[0],
|
|
132
139
|
ttl: parseInt(parts[1], 10),
|
|
133
140
|
class: parts[2],
|
|
134
141
|
type: 'RRSIG',
|
|
135
|
-
'type covered':
|
|
142
|
+
'type covered': typeCovered,
|
|
136
143
|
algorithm: parseInt(parts[5], 10),
|
|
137
144
|
labels: parseInt(parts[6], 10),
|
|
138
145
|
'original ttl': parseInt(parts[7], 10),
|
|
@@ -152,25 +159,26 @@ export default class RRSIG extends RR {
|
|
|
152
159
|
const [fqdn, n, rdata, ttl, ts, loc] = tinyline.slice(1).split(':')
|
|
153
160
|
if (parseInt(n, 10) !== this.getTypeId()) this.throwHelp('RRSIG fromTinydns, invalid n')
|
|
154
161
|
|
|
155
|
-
const bytes =
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
const
|
|
162
|
+
const bytes = Uint8Array.from(TINYDNS.octalToChar(rdata), (c) => c.charCodeAt(0))
|
|
163
|
+
const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
|
|
164
|
+
const typeCovered = dv.getUint16(0)
|
|
165
|
+
const algorithm = bytes[2]
|
|
166
|
+
const labels = bytes[3]
|
|
167
|
+
const originalTtl = dv.getUint32(4)
|
|
168
|
+
const signatureExpiration = dv.getUint32(8)
|
|
169
|
+
const signatureInception = dv.getUint32(12)
|
|
170
|
+
const keyTag = dv.getUint16(16)
|
|
163
171
|
|
|
164
172
|
let pos = 18
|
|
165
173
|
const labelArr = []
|
|
166
174
|
while (pos < bytes.length) {
|
|
167
|
-
const len = bytes
|
|
175
|
+
const len = bytes[pos++]
|
|
168
176
|
if (len === 0) break
|
|
169
|
-
labelArr.push(bytes.
|
|
177
|
+
labelArr.push(new TextDecoder().decode(bytes.subarray(pos, pos + len)))
|
|
170
178
|
pos += len
|
|
171
179
|
}
|
|
172
180
|
const signersName = `${labelArr.join('.')}.`
|
|
173
|
-
const signature = bytes.
|
|
181
|
+
const signature = new TextDecoder().decode(bytes.subarray(pos))
|
|
174
182
|
|
|
175
183
|
return new RRSIG({
|
|
176
184
|
owner: this.fullyQualify(fqdn),
|
|
@@ -191,9 +199,6 @@ export default class RRSIG extends RR {
|
|
|
191
199
|
}
|
|
192
200
|
|
|
193
201
|
/****** 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
202
|
|
|
198
203
|
toTinydns() {
|
|
199
204
|
const dataRe = new RegExp(/[\r\n\t:]/, 'g')
|
|
@@ -209,4 +214,32 @@ export default class RRSIG extends RR {
|
|
|
209
214
|
TINYDNS.escapeOctal(dataRe, this.get('signature')),
|
|
210
215
|
)
|
|
211
216
|
}
|
|
217
|
+
|
|
218
|
+
getWireRdata() {
|
|
219
|
+
const signerBytes = WIRELIB.wirePackDomain(this.get('signers name'))
|
|
220
|
+
const sigBytes = new TextEncoder().encode(this.get('signature'))
|
|
221
|
+
|
|
222
|
+
const totalLen = 2 + 1 + 1 + 4 + 4 + 4 + 2 + signerBytes.length + sigBytes.length
|
|
223
|
+
const bytes = new Uint8Array(totalLen)
|
|
224
|
+
const dv = new DataView(bytes.buffer, bytes.byteOffset)
|
|
225
|
+
|
|
226
|
+
let pos = 0
|
|
227
|
+
dv.setUint16(pos, this.get('type covered'))
|
|
228
|
+
pos += 2
|
|
229
|
+
bytes[pos++] = this.get('algorithm')
|
|
230
|
+
bytes[pos++] = this.get('labels')
|
|
231
|
+
dv.setUint32(pos, this.get('original ttl'))
|
|
232
|
+
pos += 4
|
|
233
|
+
dv.setUint32(pos, this.get('signature expiration'))
|
|
234
|
+
pos += 4
|
|
235
|
+
dv.setUint32(pos, this.get('signature inception'))
|
|
236
|
+
pos += 4
|
|
237
|
+
dv.setUint16(pos, this.get('key tag'))
|
|
238
|
+
pos += 2
|
|
239
|
+
bytes.set(signerBytes, pos)
|
|
240
|
+
pos += signerBytes.length
|
|
241
|
+
bytes.set(sigBytes, pos)
|
|
242
|
+
|
|
243
|
+
return bytes
|
|
244
|
+
}
|
|
212
245
|
}
|
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
|
}
|