propagate forced TLSA onto subdomains
[pdns-pipe-nmc.git] / SPEC.md
1 % JSON Domain Format as Implemented by Pdns-Pipe-Nmc
2
3 This document is based on
4 [Namecoin Domain Name Specification](https://wiki.namecoin.info/index.php?title=Domain_Name_Specification).
5 It tries to follow it closely, and clarify parts that are not
6 specified, or specified ambiguously, in the original document.
7
8 One notable deviation is the specification of `"delegate"` and `"import"`
9 attributes: domain objects to which their value point are
10 replacing/merging to the domain object in which they are defined.
11 This seems to be in line with at least one existing "real world"
12 implementation.
13
14 This specification is implemented by the `pdns-pipe-nmc` program.
15
16 ## Data Format
17
18 ### `DomObj` Object
19
20 `DomObj` is a data structure that is associated with an FQDN. It is
21 either a `String` containing a dotted quad (see Note below), or a
22 JSON `Map`, with the following attributes, all optional:
23
24 | Key         | Type                                  | Comment                                    |
25 |-------------|---------------------------------------|--------------------------------------------|
26 | service     | Array(SrvObj)                         | Located two levels above position          |
27 | ip          | Array(String)                         | Dotted quad format "1.2.3.4"               |
28 | ip6         | Array(String)                         | Semicolon format "DEAD::BEEF"              |
29 | tor         | String                                | Onion name                                 |
30 | i2p         | I2pObj                                |                                            |
31 | freenet     | String                                |                                            |
32 | alias       | String                                | Nullifies other attributes                 |
33 | translate   | String                                | Nullifies the "map" attribute              |
34 | email       | String                                | Used in `SOA`                              |
35 | loc         | String                                | Format suitable for `LOC`                  |
36 | info        | JsonObj                               | Currently unspecified                      |
37 | ns          | Array(String)                         | Domain names as in `NS`                    |
38 | delegate    | String                                | Replaces current object                    |
39 | import      | Array(String)                         | "Deep" merges into current object          |
40 | map         | Map(String:DomObj)                    | Tree of subdomain objects                  |
41 | fingerprint | Array(String)                         |                                            |
42 | tls         | Map(String:Map(String:Array(TlsObj))) | Outer `Map` by `Protocol`, inner by `Port` |
43 | ds          | Array(DsObj)                          |                                            |
44
45 #### Notes:
46
47 * Any attribute specified as `Array(String)` may be present in the
48   JSON document as a plain `String`, which is interpreted the same way
49   as an `Array` containing a single `String` element. In other words,
50   `"ip":"1.2.3.4"` is equivalent to `"ip":["1.2.3.4"]`. (This does not
51   apply to non-string-array attributes, like "service" or "ds".)
52 * If `DomObj` is a `String`, it is interpreted as an IPv4 address.
53   In other words, string `"1.2.3.4"` is the same as the Map
54   `"{\"ip\":\"1.2.3.4\"}"`. Such "shorthand" DomObj can be present at
55   the top level or as a value in the `"map"` attribute.
56
57 ### `SrvObj` Object
58
59 `SrvObj` is a heterogenous Array of fixed size containing 6 elements:
60
61 | N | Type   | Meaning  |
62 |---|--------|----------|
63 | 0 | String | Service  |
64 | 1 | String | Protocol |
65 | 2 | Int    | Priority |
66 | 3 | Int    | Weight   |
67 | 4 | Int    | Port     |
68 | 5 | String | FQDN     |
69
70 #### Notes
71
72 * `Service` and `Protocol` are two elements of the domain name, without
73   the undescore '_'.
74 * `SrvObj` with Service `"smtp"`, Protocol `"tcp"` and Port `25` is also
75   interpteted as an `MX` DNS resource at the domain level containing the
76   `"service"` object.
77 * When lookup is performed for `SRV` records at fqdn
78   `"_serv._proto.sub.dom.bit"`, domain object for `"sub.dom.bit"` must be
79   fetched, and in this object, `SrvObj`s for the Service `"serv"` and
80   Protocol `"proto"` selected from its `"service"` attribute.
81
82 ### `TlsObj` Object
83
84 `TlsObj` is a heterogenous Array of fixed size containing 3 elements:
85
86 | N | Type   | Meaning                                               |
87 |---|--------|-------------------------------------------------------|
88 | 0 | Int    | Match type - 0:Exact, 1:SHA-256, 2:SHA-512            |
89 | 1 | String | Match value - certificate or hash of it as hex string |
90 | 2 | Int    | Include subdomains - 0:No, 1:Yes                      |
91
92 #### Notes
93
94 * The fields of the object correspond to the attributes defined by
95   [RFC-6698](http://tools.ietf.org/html/rfc6698) ("DANE").
96
97 ### `DsObj` Object
98
99 `DsObj` is a heterogenous Array of fixed size containing 4 elements:
100
101 | N | Type   | Meaning                  |
102 |---|--------|--------------------------|
103 | 0 | Int    | Key Tag                  |
104 | 1 | Int    | Key Algorithm            |
105 | 2 | Int    | Hash Type                |
106 | 3 | String | Hash Value as hex string |
107
108 #### Notes
109
110 * The fields of the object correspond to the attributes defined by
111   [RFC-3658](http://tools.ietf.org/html/rfc3658).
112
113 ## Data Interpretation
114
115 ### Semantics of the Attributes
116
117 #### service attribute
118
119 Translates to DNS `SRV` RR, only it is located in the subdomain tree
120 two levels higher than the `SRV` record would. For example, a
121 `"service"` attribute in the `"map"` hieararchy at the point
122 corresponding to the FQDN "sub.dom.bit" with the value
123
124 ```
125 "service": [ ["imap", "tcp", 0, 0, 143, "mail.host.com" ],
126              ["smtp", "tcp", 0, 0,  25, "relay.host.com"] ]
127 ```
128
129 corresponds to two `SRV` RRs at two different points in the
130 subdomain tree:
131
132 ```
133 _imap._tcp.sub.dom.bit. IN SRV 0 0 143 mail.host.com.
134 _smtp._tcp.sub.dom.bit. IN SRV 0 0  25 relay.host.com.
135 ```
136
137 In addition to these, an `MX` RR is syntesized at the "sub.dom.bit"
138 level:
139
140 ```
141 sub.dom.bit. IN MX 0 relay.host.com.
142 ```
143
144 Note: Hostname element **must** be specified as fully qualified domain
145 name of the host, and **must not** terminate with a dot. 
146 This requirement seems to be in line with many existing definitions in
147 the blockchain; however it deviates from the BIND zone file format, in
148 which names that have not terminating dot are automatically expanded
149 by attaching the current origin zone to the end of the name.
150
151 #### ip attribute
152
153 Contains a list of strings representing IPv4 addresses in dotted
154 quad notation. For example,
155
156 ```
157 "ip": ["1.2.3.4", "5.6.7.8"]
158 ```
159
160 translates into a series of `A` RRs:
161
162 ```
163         IN A 1.2.3.4
164         IN A 5.6.7.8
165 ```
166
167 #### ip6 attribute
168
169 Contains a list of strings representing IPv6 addresses in semicolon
170 quads notation. For example,
171
172 ```
173 "ip6": ["2001:4860:0:1001::68"]
174 ```
175
176 translates into one AAAA RR:
177
178 ```
179         IN AAAA 2001:4860:0:1001::68
180 ```
181
182 #### tor attribute
183
184 Does not translate into any DNS RR. Contains Tor hidden service address.
185
186 ```
187 "tor": "eqt5g4fuenphqinx.onion"
188 ```
189
190 #### i2p attribute
191
192 Does not translate into any DNS RR. It is a JSON Map with three
193 optional String attributes: `"destination"`, `"name"` and `"b32"`.
194
195 ```
196 "i2p": { "destination": "XaZscx...0jGAAAA"
197        , "name": "example.i2p"
198        , "b32" : "ukeu...nkdq.b32.i2p"
199        }
200 ```
201
202 #### freenet attribute
203
204 Does not translate into any DNS RR. Contains Freesite key.
205
206 ```
207 "freenet": "USK@0I8g...xbZ4,AQACAAE/Example/42/"
208 ```
209
210 #### alias attribute
211
212 Translates into `CNAME` RR. Invalidates all other attributes.
213
214 ```
215 "alias": "realhost.example.bit"
216 ```
217
218 Notes:
219 * Hostname **must** be specified as fully qualified domain
220   name of the host, and **must not** terminate with a dot. 
221 * Element of the `"map"` with empty key, `"delegate"` and `"import"`
222   are processed before this invalidation takes place.
223
224 #### translate attribute
225
226 Translates into `DNAME` RR. Invalidates the contents of the `"map"`
227 attribute.
228
229 ```
230 "translate": "otherhost.bit"
231 ```
232
233 Notes:
234 * Hostname **must** be specified as fully qualified domain
235   name of the host, and **must not** terminate with a dot. 
236 * Element of the `"map"` with empty key, `"delegate"` and `"import"`
237   are processed before this invalidation takes place.
238
239 #### email attribute
240
241 Translates into the `email` element of the SOA and RP RRs. The
242 value `"email":"user@domain.tld"` becomes `user.domain.tld.`
243 in the DNS record.
244
245 ```
246 "email": "hostmaster@example.bit"
247 ```
248
249 #### loc attribute
250
251 Translates into `LOC` RR. Value must conform to the format defined
252 by [RFC-1876](http://tools.ietf.org/html/rfc1876).
253
254 ```
255 "loc": "46 31 18.000 N 6 34 26.000 E 401.00m 1m 10000m 10m"
256 ```
257
258 #### info attribute
259
260 Does not translate into any DNS RR. Contains a JSON object with
261 format unspecified at the time of this writing. Intented for
262 the registrant information.
263
264 #### ns attribute
265
266 Translates into `NS` RR. Because it effectively delegates all
267 control over the domain to external nameservers, it also invalidates
268 all other attributes.
269
270 ```
271 "ns": ["ns.myserver.net", "192.168.3.4"]
272 ```
273
274 Notes:
275 * Hostname **must** be specified as fully qualified domain
276   name of the host, and **must not** terminate with a dot. 
277 * Element of the `"map"` with empty key, `"delegate"` and `"import"`
278   are processed before this invalidation takes place.
279
280 #### delegate attribute
281
282 Does not translate into any DNS RR. Instead, the value is used as
283 a key for namecoin lookup (i.e. the value must be specified with
284 the namespace prefix), and the result of the lookup replaces all
285 other attributes
286
287 ```
288 "delegate": "s/example74845"
289 ```
290
291 Notes:
292 * Element of the `"map"` with empty key, `"delegate"` and
293   `"import"` are processed before this invalidation takes place.
294 * Unlike many other attributes, this can only contain a single
295   string as the value, rather than a list.
296
297 #### import attribute
298
299 Does not translate into any DNS RR. Instead, the value is used as
300 the key for namecoin lookup (i.e. the value must be specified with
301 the namespace prefix), and the result of the lookup is merged with
302 the current domain object.
303
304 ```
305 "import": ["dd/example", "s/example6473"]
306 ```
307
308 #### map attribute
309
310 JSON Map object containing subdomain names as its keys and domain
311 objects as values. Element of the map with empty key "" has special
312 meaning: the value of this map element is merged into the current
313 domain object. This operaton happens first when a new domain object
314 is analyzed, and is performed recursively. In the result of the
315 merge, the `"map"` does not contain the element with empty key.
316 Further operatons that can potentially modify the contents of the
317 current domain object (`import` and `delegate` lookups) start when
318 the empty element of the `"map"` has been recursively merged into
319 the current object.
320
321 ```
322 "map": { "www": { "alias" : "www.example.com" }
323        , "www2": { "delegate": "d/example" }
324        }
325 ```
326
327 Note: When a key contains dots ".", it is converted to a nested
328 map. Empty elements in the result of split, such as when a dot is
329 at the beginning or at the end of the key, or there are
330 consequitive dots, are diagnosed as erroneous data.
331
332 ```
333 "map": { "www.uk": { "alias" : "www.example.co.uk" }
334        , "www..us": { "alias" : "www.example.com" }
335        , "smtp.us.": { "alias" : "smtp.example.com" }
336 ```
337
338 is equivalent to
339
340 ```
341 "map": { "uk": { "map": { "www": { "alias" : "www.example.co.uk" }}}
342        , "us": { "map": { "www": { "alias" : "www.example.com" }
343                         , "smtp": { "alias" : "smtp.example.com" }}
344                }
345        }
346 ```
347
348 #### fingerprint attribute
349
350 Does not translate into any DNS RR. Contains a list of TLS
351 certificate fingerprints. Deprecated.
352
353 #### tls attribute
354
355 Intended to carry attributes as per
356 [RFC-6698](http://tools.ietf.org/html/rfc6698) ("DANE").
357
358 ```
359 "tls": {
360   "tcp": {
361            { "443": [ [1, "660008F9...7621B787", 1] ]
362            , "25": [ [1, "660008F9...7621B787", 1] ]
363            }
364          }
365        }
366 ```
367
368 translates into:
369
370 ```
371 _443._tcp      TLSA  (3 0 1 660008F9...7621B787)
372 _25._tcp       TLSA  (3 0 1 660008F9...7621B787)
373 ```
374
375 The third element of the `TlsObj` heterogenous array is an extention
376 to the DANE definition. Value `0` means that this rule is not enforced
377 upon subdomains, value `1` means that it is enforced on subdomains.
378 Rule defined inside a subdomain `DomObj` that specifies `0` on a rule
379 existing in upper domain, that specifies `1` should be ignored. I.e.
380 subdomain rule cannot revoke enforcement imposed by an upper domain rule.
381
382 #### ds attribute
383
384 Translates into `DS` RR. Carries attributes defined by
385 [RFC-4034](http://tools.ietf.org/html/rfc4034).
386
387 ```
388 "ds": [ [31381,8,1,"pA1W...ceTI="]
389       , [31381,8,2,"toHB...ndexitQ6j8E="]
390       ]
391 ```
392
393 ### Lookup Sequence
394
395 Assuming a query is performed for
396 `sdN`++"."++{...}++"."++`sd2`++"."++`sd1`++"."++`dom`++".bit"
397 (`sdX` list possibly being empty), the lookup process starts by
398 querying the database for the object corresponding to `dom`.
399 Technically, it is easiest to populate a "seed" DomObj with a
400 single attribute `"import"` the value of which corresponds to the
401 `dom` name in the Namecoin namespace, which is `"d/" ++ dom`.
402 This domain object is then transformed by the following
403 recursive sequece:
404
405 1. Value of the element of the `"map"` attribute with the key `""`
406    (empty string) is recursively merged into the base domain. The
407    `""` element of the `"map"` is removed from the result.
408 2. If attribute `"delegate"` does not exist in the resulting object,
409    step 3 is is performed. If attribute `"delegate"` exists, in
410    the resulting object, lookup is performed for the values of this
411    attribute, and fetched object replaces the base domain completely.
412    The result is passed as base domain to step 1.
413 3. If attribute `"import"` does not exist in the resulting object,
414    recursion stops, and step 4 is performed on the result
415    If attribute `"import"` exists in the resulting object, lookup is
416    performed for the values of this attribute, and fetched objects
417    are recursively merged into the base domain. The `"import"`
418    attribute is removed from the result. Then the result is passed
419    as base domain to step 1.
420 4. If subdomain chain is empty, recursion stops, and step 5 is
421    performed on the result. If subdomain chain is not empty, next
422    element is taken out of the chain, and the `"map"` is looked
423    up for the element with the name matching the subdomain element.
424    The value of this element of the `"map"` is passed as base domain
425    to step 1. If matching element does not exist, lookup is considered
426    failed.
427 5. Domain object in which all `""` map elements and all `"delegate"`
428    and `"import"` elements are acted upon and removed, is then
429    "normalized" by removal of attributes that are nullified by the
430    presence of other attributes.
431
432 Note that the process involves recursion nested levels deep.
433
434 ### Merging Procedure
435
436 When a domain object `extra` needs merging into a domain object `base`,
437 the following rules are applied:
438
439 * Of `String` and other "scalar" attributes, one is chosen, the value
440   from the `base` taking precedence.
441 * On `Array` attribtes, `union` operation is performed. (Of equal
442   elements, only one copy is left.)
443 * On `Map` attributes, recursive merge is performed. On the top level,
444   elemens with keys that are only present in either `base` or `extra`
445   object are all put into result. The values of the elements that are
446   present in both `base` and `extra` objects are merged according to
447   the rules applicable to their type.
448