b93a852a339847b29931c173766510d216908c45
[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.  If empty element appears as a result of split, such as when
329 a dot is at the beginning or at the end of the key, or there are
330 consequitive dots, such elemets are ignored. For example,
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 #### ds attribute
369
370 Translates into `DS` RR. Carries attributes defined by
371 [RFC-4034](http://tools.ietf.org/html/rfc4034).
372
373 ```
374 "ds": [ [31381,8,1,"pA1W...ceTI="]
375       , [31381,8,2,"toHB...ndexitQ6j8E="]
376       ]
377 ```
378
379 ### Lookup Sequence
380
381 Assuming a query is performed for
382 `sdN`++"."++{...}++"."++`sd2`++"."++`sd1`++"."++`dom`++".bit"
383 (`sdX` list possibly being empty), the lookup process starts by
384 querying the database for the object corresponding to `dom`.
385 Technically, it is easiest to populate a "seed" DomObj with a
386 single attribute `"import"` the value of which corresponds to the
387 `dom` name in the Namecoin namespace, which is `"d/" ++ dom`.
388 This domain object is then transformed by the following
389 recursive sequece:
390
391 1. Value of the element of the `"map"` attribute with the key `""`
392    (empty string) is recursively merged into the base domain. The
393    `""` element of the `"map"` is removed from the result.
394 2. If attribute `"delegate"` does not exist in the resulting object,
395    step 3 is is performed. If attribute `"delegate"` exists, in
396    the resulting object, lookup is performed for the values of this
397    attribute, and fetched object replaces the base domain completely.
398    The result is passed as base domain to step 1.
399 3. If attribute `"import"` does not exist in the resulting object,
400    recursion stops, and step 4 is performed on the result
401    If attribute `"import"` exists in the resulting object, lookup is
402    performed for the values of this attribute, and fetched objects
403    are recursively merged into the base domain. The `"import"`
404    attribute is removed from the result. Then the result is passed
405    as base domain to step 1.
406 4. If subdomain chain is empty, recursion stops, and step 5 is
407    performed on the result. If subdomain chain is not empty, next
408    element is taken out of the chain, and the `"map"` is looked
409    up for the element with the name matching the subdomain element.
410    The value of this element of the `"map"` is passed as base domain
411    to step 1. If matching element does not exist, lookup is considered
412    failed.
413 5. Domain object in which all `""` map elements and all `"delegate"`
414    and `"import"` elements are acted upon and removed, is then
415    "normalized" by removal of attributes that are nullified by the
416    presence of other attributes.
417
418 Note that the process involves recursion nested levels deep.
419
420 ### Merging Procedure
421
422 When a domain object `extra` needs merging into a domain object `base`,
423 the following rules are applied:
424
425 * Of `String` and other "scalar" attributes, one is chosen, the value
426   from the `base` taking precedence.
427 * On `Array` attribtes, `union` operation is performed. (Of equal
428   elements, only one copy is left.)
429 * On `Map` attributes, recursive merge is performed. On the top level,
430   elemens with keys that are only present in either `base` or `extra`
431   object are all put into result. The values of the elements that are
432   present in both `base` and `extra` objects are merged according to
433   the rules applicable to their type.
434