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