idnits 2.17.1 draft-newton-rdap-jcr-05.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** The document seems to lack a Security Considerations section. ** The document seems to lack an IANA Considerations section. (See Section 2.2 of https://www.ietf.org/id-info/checklist for how to handle the case when there are no actions for IANA.) Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The document date (January 15, 2018) is 2292 days in the past. Is this intentional? -- Found something which looks like a code comment -- if you have code sections in the document, please surround them with '' and '' lines. Checking references for intended status: Informational ---------------------------------------------------------------------------- ** Obsolete normative reference: RFC 5988 (Obsoleted by RFC 8288) ** Obsolete normative reference: RFC 7159 (Obsoleted by RFC 8259) ** Obsolete normative reference: RFC 7483 (Obsoleted by RFC 9083) Summary: 5 errors (**), 0 flaws (~~), 1 warning (==), 2 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Network Working Group A. Newton 3 Internet-Draft ARIN 4 Intended status: Informational January 15, 2018 5 Expires: July 19, 2018 7 A Description of RDAP JSON Messages Using JSON Content Rules 8 draft-newton-rdap-jcr-05 10 Abstract 12 This document describes the JSON responses in the Registration Data 13 Access Protocol with the formal notation of JSON Content Rules. 15 Status of This Memo 17 This Internet-Draft is submitted in full conformance with the 18 provisions of BCP 78 and BCP 79. 20 Internet-Drafts are working documents of the Internet Engineering 21 Task Force (IETF). Note that other groups may also distribute 22 working documents as Internet-Drafts. The list of current Internet- 23 Drafts is at http://datatracker.ietf.org/drafts/current/. 25 Internet-Drafts are draft documents valid for a maximum of six months 26 and may be updated, replaced, or obsoleted by other documents at any 27 time. It is inappropriate to use Internet-Drafts as reference 28 material or to cite them other than as "work in progress." 30 This Internet-Draft will expire on July 19, 2018. 32 Copyright Notice 34 Copyright (c) 2018 IETF Trust and the persons identified as the 35 document authors. All rights reserved. 37 This document is subject to BCP 78 and the IETF Trust's Legal 38 Provisions Relating to IETF Documents 39 (http://trustee.ietf.org/license-info) in effect on the date of 40 publication of this document. Please review these documents 41 carefully, as they describe your rights and restrictions with respect 42 to this document. Code Components extracted from this document must 43 include Simplified BSD License text as described in Section 4.e of 44 the Trust Legal Provisions and are provided without warranty as 45 described in the Simplified BSD License. 47 Table of Contents 49 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 50 2. Response . . . . . . . . . . . . . . . . . . . . . . . . . . 3 51 3. Object Classes . . . . . . . . . . . . . . . . . . . . . . . 4 52 3.1. Entity Object Class . . . . . . . . . . . . . . . . . . . 4 53 3.2. Nameserver Object Class . . . . . . . . . . . . . . . . . 15 54 3.3. Domain Object Class . . . . . . . . . . . . . . . . . . . 15 55 3.4. IP Network Object Class . . . . . . . . . . . . . . . . . 16 56 3.5. Autnum Object Class . . . . . . . . . . . . . . . . . . . 17 57 4. Search Results . . . . . . . . . . . . . . . . . . . . . . . 17 58 5. Error Response . . . . . . . . . . . . . . . . . . . . . . . 18 59 6. Common Structures . . . . . . . . . . . . . . . . . . . . . . 18 60 6.1. RDAP Conformance . . . . . . . . . . . . . . . . . . . . 19 61 6.2. Links . . . . . . . . . . . . . . . . . . . . . . . . . . 19 62 6.3. Notices And Remarks . . . . . . . . . . . . . . . . . . . 19 63 6.4. Language Identifier . . . . . . . . . . . . . . . . . . . 20 64 6.5. Events . . . . . . . . . . . . . . . . . . . . . . . . . 20 65 6.6. Status . . . . . . . . . . . . . . . . . . . . . . . . . 21 66 6.7. Port 43 . . . . . . . . . . . . . . . . . . . . . . . . . 21 67 6.8. Public IDs . . . . . . . . . . . . . . . . . . . . . . . 22 68 7. Validating Responses . . . . . . . . . . . . . . . . . . . . 22 69 8. Stricter Validation . . . . . . . . . . . . . . . . . . . . . 22 70 9. Complete Rulesets for RDAP . . . . . . . . . . . . . . . . . 26 71 10. Normative References . . . . . . . . . . . . . . . . . . . . 45 72 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 45 74 1. Introduction 76 The JSON [RFC7159] responses of the Registration Data Access Protocol 77 [RFC7483] are officially defined with English prose. Those 78 definitions contain imprecise or ambiguous JSON structures and 79 require lengthy, tedious examples in the attempt to offer 80 clarification. The English prose can be difficult for non-native 81 English readers, and the examples create their own confusion. 83 This document describes the JSON found in RDAP with JSON Content 84 Rules [I-D.newton-json-content-rules] (JCR). 86 JCR overcomes some of the obstacles of describing JSON with English 87 prose, reducing the tediousness of the prose and accompanying lengthy 88 examples to understandable data structures. Additionally, JCR has 89 mechanisms which can be used by software developers to create test 90 harnesses and technology compatibility kits. 92 Though this document describes all of the JSON found in [RFC7483], it 93 presents the structures in a different order. The rules defined here 94 use the JCR mixin style of specification, where common structures are 95 defined in group rules instead of separately, distinct objects. 97 2. Response 99 [RFC7483] describes ten distinct JSON response: five entity class 100 response, an error response, a help response, and three search 101 responses. 103 @{root} $entity_response = { 104 $response_mixin, 105 $entity_mixin 106 } 108 @{root} $nameserver_response = { 109 $response_mixin, 110 $nameserver_mixin 111 } 113 @{root} $domain_response = { 114 $response_mixin, 115 $domain_mixin 116 } 118 @{root} $network_response = { 119 $response_mixin, 120 $network_mixin 121 } 123 @{root} $autnum_response = { 124 $response_mixin, 125 $autnum_mixin 126 } 128 @{root} $error_response = { 129 $response_mixin, 130 $error_mixin 131 } 133 @{root} $help_response = { 134 $response_mixin, 135 $lang ? 136 } 138 @{root} $domainSearch_response = { 139 $response_mixin, 140 $lang ?, 141 $domainSearchResult 143 } 145 @{root} $nameserverSearch_response = { 146 $response_mixin, 147 $lang ?, 148 $nameserverSearchResult 149 } 151 @{root} $entitySearch_response = { 152 $response_mixin, 153 $lang ?, 154 $entitySearchResult 155 } 157 Figure 1 159 All of the responses have a common set of object members described by 160 response_mixin. 162 $response_mixin = ( 163 $rdapConformance ?, 164 "notices" : $notices ? 165 ) 167 Figure 2 169 3. Object Classes 171 The primary data structures in RDAP are called object classes. These 172 are first order object instances with identifiers. They are JSON 173 objects which contain other JSON data types. 175 3.1. Entity Object Class 177 The Entity object class represents persons or organizations. 179 $entities = "entities" : [ $entity_oc * ] 181 $entity_oc = { 182 $entity_mixin 183 } 185 $entity_mixin = ( 186 "objectClassName" : "entity", 187 $common_mixin, 188 "vcardArray" : [ "vcard", $vcard * ] ?, 189 "asEventActor" : [ $noActorEvent * ] ?, 190 "roles" : [ string * ] ?, 191 $publicIds ?, 192 $entities ?, 193 "networks" : [ $network_oc * ] ?, 194 "autnums" : [ $autnum_oc * ] ? 195 ) 197 Figure 3 199 The Entity object class incorporates jCard [RFC7095] (vCard in JSON) 200 for contact information. 202 Each jCard is made up of vCard properties in an array. The very 203 first property must be "version", and the "fn" property must appear 204 once and only once. 206 $vcard = [ 207 [ "version", {}, "text", "4.0" ], 208 $vcard_not_fn_properties * , 209 [ "fn", { $vcard_type_param?, $vcard_language_param? , 210 $vcard_altid_param? , $vcard_pid_param? , 211 $vcard_pref_param?, $vcard_any_param? }, 212 "text", string ], 213 $vcard_not_fn_properties * 214 ] 216 $vcard_not_fn_properties = 217 ( 218 $vcard_source | 219 $vcard_kind | 220 $vcard_n | 221 $vcard_nicname | 222 $vcard_photo | 223 $vcard_bday | 224 $vcard_anniversary | 225 $vcard_gender | 226 $vcard_adr | 227 $vcard_tel | 228 $vcard_email | 229 $vcard_impp | 230 $vcard_lang | 231 $vcard_tz | 232 $vcard_geo | 233 $vcard_title | 234 $vcard_role | 235 $vcard_logo | 236 $vcard_org | 237 $vcard_member | 238 $vcard_related | 239 $vcard_categories | 240 $vcard_note | 241 $vcard_prodid | 242 $vcard_rev | 243 $vcard_sound | 244 $vcard_uid | 245 $vcard_clientpidmap | 246 $vcard_url | 247 $vcard_key | 248 $vcard_fburl | 249 $vcard_caladruri | 250 $vcard_caluri | 251 $vcard_x10 252 ) 253 Figure 4 255 Each vCard property is composed of a property name, a set of 256 parameters, and data values. 258 $vcard_source = [ "source", $vcard_source_prop ] 259 $vcard_source_prop = ( 260 { $vcard_pid_param? , $vcard_pref_param?, $vcard_altid_param? , 261 $vcard_mediatype_param?, $vcard_any_param? } , 262 "uri", uri 263 ) 265 $vcard_kind = [ "kind", $vcard_kind_prop ] 266 $vcard_kind_prop = ( 267 { $vcard_any_param? }, 268 "text", $vcard_kind_type 269 ) 271 $vcard_n = [ "n", $vcard_n_prop ] 272 $vcard_n_prop = ( 273 { $vcard_sort_as_param? , $vcard_language_param? , 274 $vcard_altid_param? , $vcard_any_param? }, 275 "text", $vcard_string_type_array 276 ) 278 $vcard_nicname = [ "nicname", $vcard_nicname_prop ] 279 $vcard_nicname_prop = ( 280 { $vcard_type_param? , $vcard_language_param? , 281 $vcard_altid_param? , $vcard_pid_param? , 282 $vcard_pref_param? , $vcard_any_param ? }, 283 "text", $vcard_string_type_array 284 ) 286 $vcard_photo = [ "photo", $vcard_photo_prop ] 287 $vcard_photo_prop = ( 288 { $vcard_altid_param? , $vcard_type_param? , 289 $vcard_mediatype_param? , $vcard_pref_param? , 290 $vcard_pid_param? , $vcard_any_param? }, 291 "uri", uri 292 ) 294 $vcard_bday = [ "bday", $vcard_bday_prop ] 295 $vcard_bday_prop = ( 296 ( { $vcard_language_param?, $vcard_altid_param?, 297 $vcard_calscale_param?, $vcard_any_param? }, 298 "text", string 299 ) | 300 ( { $vcard_altid_param?, $vcard_calscale_param?, 301 $vcard_any_param? }, 302 "date-and-or-time", $vcard_date_and_or_time_type 303 ) 304 ) 306 $vcard_anniversary = [ "anniversary", $vcard_anniversary_prop ] 307 $vcard_anniversary_prop = ( 308 { $vcard_altid_param?, $vcard_calscale_param?, $vcard_any_param? }, 309 "date-and-or-time", $vcard_date_and_or_time_type 310 ) 312 $vcard_gender = [ "gender", $vcard_gender_prop ] 313 $vcard_gender_prop = ( 314 { $vcard_any_param? }, 315 "text", 316 ( $vcard_gender_type | [ $vcard_gender_type, string + ] ) 317 ) 319 $vcard_adr = [ "adr", $vcard_adr_prop ] 320 $vcard_adr_prop = ( 321 { $vcard_label_param? , $vcard_language_param? , 322 $vcard_geo_param ? , $vcard_tz_param? , 323 $vcard_altid_param? , $vcard_pid_param? , 324 $vcard_pref_param? , $vcard_type_param? , 325 $vcard_any_param? }, 326 "text", $vcard_string_type_array 327 ) 329 $vcard_tel = [ "tel", $vcard_tel_prop ] 330 $vcard_tel_prop = ( 331 ( { $vcard_type_param? , $vcard_pid_param? , $vcard_pref_param? , 332 $vcard_altid_param?, $vcard_any_param? }, "text", string 333 ) | 334 ( { $vcard_type_param? , $vcard_pid_param? , $vcard_pref_param? , 335 $vcard_altid_param?, $vcard_mediatype_param?, 336 $vcard_any_param? }, 337 "uri", uri..tel 338 ) 339 ) 341 $vcard_email = [ "email", $vcard_email_prop ] 342 $vcard_email_prop = ( 343 { $vcard_pid_param? , $vcard_pref_param? , $vcard_type_param? , 344 $vcard_altid_param? , $vcard_any_param ? }, 345 "text", string 346 ) 348 $vcard_impp = [ "impp", $vcard_impp_prop ] 349 $vcard_impp_prop = ( 350 { $vcard_pid_param? , $vcard_pref_param? , $vcard_type_param? , 351 $vcard_mediatype_param? , $vcard_altid_param? , 352 $vcard_any_param }, 353 "uri", uri..impp 354 ) 356 $vcard_lang = [ "lang", $vcard_lang_prop ] 357 $vcard_lang_prop = ( 358 { $vcard_pid_param? , $vcard_pref_param? , $vcard_altid_param? , 359 $vcard_type_param? , $vcard_any_param? }, 360 "language-tag", $vcard_language_tag_type 361 ) 363 $vcard_tz = [ "tz", $vcard_tz_prop ] 364 $vcard_tz_prop = ( 365 { $vcard_altid_param?, $vcard_pid_param? , $vcard_pref_param? , 366 $vcard_type_param? , $vcard_mediatype_param?, 367 $vcard_any_param? }, 368 ( ( "text", string ) | 369 ( "uri" , uri ) | 370 ( "utc-offset" , $vcard_utc_offset_type ) ) 371 ) 373 $vcard_geo = [ "geo", $vcard_geo_prop ] 374 $vcard_geo_prop = ( 375 { $vcard_pid_param? , $vcard_pref_param? , $vcard_type_param? , 376 $vcard_mediatype_param? , $vcard_altid_param? , 377 $vcard_any_param? }, 378 "uri", uri..geo 379 ) 381 $vcard_title = [ "title", $vcard_title_prop ] 382 $vcard_title_prop = ( 383 { $vcard_language_param? , $vcard_pid_param? , $vcard_pref_param? , 384 $vcard_altid_param? , $vcard_type_param? , $vcard_any_param? }, 385 "text", string 386 ) 388 $vcard_role = [ "role", $vcard_role_prop ] 389 $vcard_role_prop = ( 390 { $vcard_language_param? , $vcard_pid_param? , $vcard_pref_param? , 391 $vcard_altid_param? , $vcard_type_param? , $vcard_any_param? }, 392 "text", string 393 ) 395 $vcard_logo = [ "logo", $vcard_logo_prop ] 396 $vcard_logo_prop = ( 397 { $vcard_altid_param? , $vcard_type_param? , 398 $vcard_mediatype_param? , $vcard_pref_param? , 399 $vcard_pid_param? , $vcard_language_param? , 400 $vcard_any_param? }, 401 "uri", uri 402 ) 404 $vcard_org = [ "org", $vcard_org_prop ] 405 $vcard_org_prop = ( 406 { $vcard_sort_as_param? , $vcard_language_param? , 407 $vcard_pid_param? , $vcard_pref_param? , $vcard_altid_param? , 408 $vcard_type_param? , $vcard_any_param? }, 409 "text", $vcard_string_type_array 410 ) 412 $vcard_member = [ "member", $vcard_member_prop ] 413 $vcard_member_prop = ( 414 { $vcard_altid_param? , $vcard_mediatype_param? , 415 $vcard_pref_param? , $vcard_pid_param? , $vcard_any_param? }, 416 "uri", uri 417 ) 419 $vcard_related = [ "related", $vcard_related_prop ] 420 $vcard_related_prop = ( 421 ( { $vcard_mediatype_param? , $vcard_pref_param? , 422 $vcard_altid_param? , $vcard_type_param? , 423 $vcard_any_param? }, 424 "uri", uri 425 ) | 426 ( { $vcard_language_param? , $vcard_pref_param? , 427 $vcard_altid_param? , $vcard_type_param? , 428 $vcard_any_param? }, 429 "text", $vcard_related_type_array 430 ) 431 ) 433 $vcard_categories = [ "categories", $vcard_categories_prop ] 434 $vcard_categories_prop = ( 435 { $vcard_pid_param? , $vcard_pref_param? , $vcard_type_param ?, 436 $vcard_altid_param? , $vcard_any_param? }, 437 "text", $vcard_string_type_array 438 ) 440 $vcard_note = [ "note", $vcard_note_prop ] 441 $vcard_note_prop = ( 442 { $vcard_language_param? , $vcard_pid_param? , 443 $vcard_pref_param? , $vcard_type_param? , 444 $vcard_altid_param? , $vcard_any_param ? }, 446 "text", string 447 ) 449 $vcard_prodid = [ "prodid", $vcard_prodid_prop ] 450 $vcard_prodid_prop = ( { $vcard_any_param ? }, "text", string ) 452 $vcard_rev = [ "rev", $vcard_rev_prop ] 453 $vcard_rev_prop = ( 454 { $vcard_any_param ? }, "timestamp", datetime 455 ) 457 $vcard_sound = [ "sound", $vcard_sound_prop ] 458 $vcard_sound_prop = ( 459 { $vcard_altid_param? , $vcard_mediatype_param? , 460 $vcard_language_param? , $vcard_pref_param? , 461 $vcard_pid_param? , $vcard_any_param? }, 462 "uri", uri 463 ) 465 $vcard_uid = [ "uid", $vcard_uid_prop ] 466 $vcard_uid_prop = ( 467 ( { $vcard_any_param? }, "uri", uri ) | 468 ( { $vcard_any_param? }, "text", string ) 469 ) 471 $vcard_clientpidmap = [ "clientpidmap", $vcard_clientpidmap_prop ] 472 $vcard_clientpidmap_prop = ( {}, "text", [ /^[0-9]+$/, uri ] ) 474 $vcard_url = [ "url", $vcard_url_prop ] 475 $vcard_url_prop = ( 476 { $vcard_altid_param? , $vcard_mediatype_param? , 477 $vcard_pref_param? , $vcard_pid_param? , $vcard_any_param? }, 478 "uri", uri 479 ) 481 $vcard_key = [ "key", $vcard_key_prop ] 482 $vcard_key_prop = ( 483 ( { $vcard_mediatype_param? , $vcard_pref_param? , 484 $vcard_altid_param? , $vcard_type_param? , 485 $vcard_any_param? }, 486 "uri", uri 487 ) | 488 ( { $vcard_pref_param? , $vcard_altid_param? , 489 $vcard_type_param? , $vcard_any_param? }, 490 "text", string 491 ) 492 ) 493 $vcard_fburl = [ "fburl", $vcard_fburl_prop ] 494 $vcard_fburl_prop = ( 495 { $vcard_altid_param? , $vcard_mediatype_param? , 496 $vcard_altid_param? , $vcard_pref_param? , 497 $vcard_pid_param? , $vcard_any_param? }, 498 "uri", uri 499 ) 501 $vcard_caladruri = [ "caladruri", $vcard_caladruri_prop ] 502 $vcard_caladruri_prop = ( 503 { $vcard_altid_param? , $vcard_mediatype_param? , 504 $vcard_altid_param? , $vcard_pref_param? , 505 $vcard_pid_param? , $vcard_any_param? }, 506 "uri", uri 507 ) 509 $vcard_caluri = [ "caluri", $vcard_caluri_prop ] 510 $vcard_caluri_prop = ( 511 { $vcard_altid_param? , $vcard_mediatype_param? , 512 $vcard_altid_param? , $vcard_pref_param? , 513 $vcard_pid_param? , $vcard_any_param? }, 514 "uri", uri 515 ) 517 $vcard_x10 = [ $vcard_x_name_type, $vcard_x10_prop ] 518 $vcard_x10_prop = ( 519 { $vcard_language_param? , $vcard_pref_param? , 520 $vcard_altid_param? , $vcard_pid_param? , 521 $vcard_type_param? , $vcard_mediatype_param? , 522 $vcard_calscale_param? , $vcard_sort_as_param? , 523 $vcard_geo_param? , $vcard_tz_param? , 524 $vcard_label_param? , $vcard_any_param? }, 525 $vcard_x_name_type, $vcard_string_type_array 526 ) 528 Figure 5 530 vCard parameters are grouped into a JSON object, where each member of 531 the object is a parameter. 533 $vcard_language_param = "language" : $vcard_language_tag_type 534 $vcard_pref_param = "pref" : $vcard_pref_type 535 $vcard_altid_param = "altid" : string 536 $vcard_pid_param = "pid" : $vcard_pid_type_array 537 $vcard_type_param = "type" : $vcard_type_type_array 538 $vcard_mediatype_param = "mediatype" : $vcard_mediatype_type 539 $vcard_calscale_param = "calscale" : $vcard_calscale_type 540 $vcard_sort_as_param = "sort-as" : $vcard_string_type_array 541 $vcard_geo_param = "geo" : uri..geo 542 $vcard_tz_param = "tz" : $vcard_utc_offset_type 543 $vcard_label_param = "label" : $vcard_string_type_array 544 $vcard_any_param = /^x\-[A-Za-z0-9\-]*$/ : $vcard_string_type_array 546 Figure 6 548 vCard values are determined by a string denoting the value type, 549 followed by the value or an array of those values. 551 $vcard_string_type_array = 552 ( string | [ ( string | [ string * ] ) * ] ) 553 $vcard_language_tag_type =: 554 /[a-z]{2}(-[A-Z][a-zA-Z]*(\-[A-Z]{2})?)?/ 555 $vcard_mediatype_type =: /^\w+\/[\-.\w]+(?:\+[\-.\w]+)?$/ 556 $vcard_utc_offset_type =: /^(([\-\+]\d{1,2}):?(\d{2})?)?$/ 557 $vcard_date_or_time =: ( 558 /^(\d{4})-?(\d{2})-?(\d{2})$/ | 559 /^(\d{4})$/ | 560 /^--(\d{2})-?(\d{2})$/ | 561 /^--(\d{2})$/ | 562 /^---(\d{2})$/ | 563 /^(\d{2})(([-+]\d{1,2}):?(\d{2})?)?$/ | 564 /^(\d{2}):?(\d{2})(([\-\+]\d{1,2}):?(\d{2})?)?$/ | 565 /^(\d{2}):?(\d{2}):?(\d{2})(Z|([\-\+]\d{1,2}):?(\d{2})?)?$/ | 566 /^-(\d{2}):?(\d{2})(Z|([\-\+]\d{1,2}):?(\d{2})?)?$/ | 567 /^-(\d{2})(([\-\+]\d{1,2}):?(\d{2})?)?$/ | 568 /^--(\d{2})(([\-\+]\d{1,2}):?(\d{2})?)?$/ 569 ) 570 $vcard_date_and_or_time_type =: ( 571 datetime | $vcard_date_or_time 572 ) 573 $vcard_group_type =: /^[a-zA-Z0-9\-]+$/ 574 $vcard_type_type =: ( 575 "home" | "work" | $vcard_tel_type | $vcard_related_type | 576 $vcard_x_name_type 578 ) 579 $vcard_type_type_array = ( 580 $vcard_type_type | [ $vcard_type_type * ] 581 ) 582 $vcard_tel_type =: ( 583 "text" | "voice" | "fax" | "cell" | "video" | 584 "pager" | "textphone" | "main-number" 585 ) 586 $vcard_tel_type_array = ( $vcard_tel_type | [ $vcard_tel_type * ] ) 587 $vcard_related_type =: ( 588 "contact" | "acquaintance" | "friend" | "met" | 589 "co-worker" | "colleague" | "co-resident" | 590 "neighbor" | "child" | "parent" | "sibling" | 591 "spouse" | "kin" | "muse" | "crush" | "date" | 592 "sweetheart" | "me" | "agent" | "emergency" 593 ) 594 $vcard_related_type_array = ( 595 $vcard_related_type | [ $vcard_related_type * ] 596 ) 597 $vcard_index_type =: /^[1-9]?[0-9]*$/ 598 $vcard_expertise_level_type =: ( 599 "beginner" | "average" | "expert" 600 ) 601 $vcard_hobby_type =: ( "high" | "medium" | "low" ) 602 $vcard_pref_type =: /^[1-9]?[0-9]{1}$|^100$/ 603 $vcard_pid_type =: /^[0-9]+(\.[0-9]+)?$/ 604 $vcard_pid_type_array = ( 605 $vcard_pid_type | [ $vcard_pid_type * ] 606 ) 607 $vcard_gender_type =: ( "M" | "F" | "O" | "N" | "U" ) 608 $vcard_gender_type_array = ( 609 $vcard_gender_type | [ $vcard_gender_type * ] 610 ) 611 $vcard_kind_type =: ( 612 "individual" | "group" | "org" | "location" | 613 "application" | "device" 614 ) 615 $vcard_iana_token_type =: /^[A-Za-z0-9\-]*$/ 616 $vcard_x_name_type =: /^x\-[A-Za-z0-9\-]*$/ 617 $vcard_calscale_type =: ( 618 "gregorian" | $vcard_iana_token_type | $vcard_x_name_type 619 ) 621 Figure 7 623 3.2. Nameserver Object Class 625 The nameserver object class represents DNS nameservers in registries. 627 $nameservers = "nameservers" : [ $nameserver_oc * ] 629 $nameserver_oc = { 630 $nameserver_mixin 631 } 633 $nameserver_mixin = ( 634 "objectClassName" : "nameserver", 635 $common_mixin, 636 "ldhName" : fqdn, 637 "unicodeName" : idn ?, 638 "ipAddresses" : { 639 "v4" : [ ipv4 + ] ?, 640 "v6" : [ ipv6 + ] ? 641 } ?, 642 $entities ? 643 ) 645 Figure 8 647 3.3. Domain Object Class 649 The Domain object class is the most complex of all the object classes 650 defined in RDAP. It represents both forward and reverse DNS 651 delegations. It's complexity is mostly due to the DNSSEC provisions 652 of the object class. 654 $domain_oc = { 655 $domain_mixin 656 } 658 $domain_mixin = ( 659 "objectClassName" : "domain", 660 $common_mixin, 661 "ldhName" : fqdn, 662 "unicodeName" : idn ?, 663 "variants" : [ $variant * ] ?, 664 $nameservers ?, 665 $secureDNS ?, 666 $entities ?, 667 $publicIds ?, 668 "network" : $network_oc ? 669 ) 670 $variant = { 671 "relation" : [ string * ] ?, 672 "idnTable" : string ?, 673 "variantNames" : [ 674 { "ldhName" : fqdn, "unicodeName" : idn } * 675 ] 676 } 678 $secureDNS = "secureDNS" : { 679 "zoneSigned" : boolean ?, 680 "delegationSigned" : boolean ?, 681 "maxSigLife" : integer ?, 682 "dsData" : [ $dsData_obj * ] ?, 683 "keyData" : [ $keyData_obj * ] ? 684 } 686 $dsData_obj = { 687 "keyTag" : integer, 688 "algorithm" : integer, 689 "digest" : string, 690 "digestType" : integer, 691 $events ?, 692 $links ? 693 } 695 $keyData_obj = { 696 "flags" : integer, 697 "protocol" : integer, 698 "publicKey" : string, 699 "algorithm" : integer, 700 $events ?, 701 $links ? 702 } 704 Figure 9 706 3.4. IP Network Object Class 708 The IP Network object class represents IP network registrations in 709 RIRs. 711 $network_oc = { 712 $network_mixin 713 } 715 $network_mixin = ( 716 "objectClassName" : "ip network", 717 $common_mixin, 718 "startAddress" : ( ipv4 | ipv6 ) ?, 719 "endAddres" : ( ipv4 | ipv6 ) ?, 720 "ipVersion" : ( "v4" | "v6" ) ?, 721 "name" : string ?, 722 "type" : string ?, 723 "country" : /[A-Z]{2}/ ?, 724 "parentHandle" : string ?, 725 $entities ? 726 ) 728 Figure 10 730 3.5. Autnum Object Class 732 The Autnum object class represents an autonomous system number or 733 blocks of autonomous system numbers in an RIR. 735 $autnum_oc = { 736 $autnum_mixin 737 } 739 $autnum_mixin = ( 740 "objectClassName" : "autnum", 741 $common_mixin, 742 "startAutnum" : int32 ?, 743 "endAutnum" : int32 ?, 744 "name" : string ?, 745 "type" : string ?, 746 "country" : string ?, 747 $entities ? 748 ) 750 Figure 11 752 4. Search Results 754 Search results in RDAP are merely arrays of object classes. 756 $domainSearchResult = 757 "domainSearchResult" : [ $domain_oc * ] 759 $nameserverSearchResult = 760 "nameserverSearchResult" : [ $nameserver_oc * ] 762 $entitySearchResult = 763 "entitySearchResult" : [ $entity_oc * ] 765 Figure 12 767 5. Error Response 769 Section 6 of [RFC7483] describes RDAP error responses. 771 $error_mixin = ( 772 "errorCode" : integer, 773 "title" : string ?, 774 "description" : [ string * ] ? 775 ) 777 Figure 13 779 6. Common Structures 781 Section 4 of [RFC7483] describes eight common structures used 782 throughout the JSON in RDAP. 784 Most of these common structures are grouped together in a rule called 785 common_mixin. 787 $common_mixin = ( 788 "handle" : string ?, 789 "remarks" : [ $notice * ] ?, 790 $links ?, 791 $events ?, 792 $status ?, 793 $port43 ?, 794 $lang ? 795 ) 797 Figure 14 799 6.1. RDAP Conformance 801 The rdapConformance array is the versioning and capabilities 802 negotiation mechanism of RDAP. 804 $rdapConformance = "rdapConformance" : [ string * ] 806 Figure 15 808 6.2. Links 810 Structures in RDAP may link to information in other data systems 811 using links. Additionally, RDAP uses "self" links to identify 812 instances of RDAP object classes. The data found in each link is 813 described by [RFC5988]. 815 RDAP links are an array of distinct objects, each representing a 816 separate link. 818 $links = ( "links" : [ $link * ] ) 820 ; see RFC 5988 821 $link = { 822 "value" : uri ?, 823 "rel" : string ?, 824 "href" : uri, 825 "hreflang" : [ $lang_value * ] ?, 826 "title" : string ?, 827 "media" : string ?, 828 "type" : 829 /[a-zA-Z][a-zA-Z0-9]*\/[a-zA-Z][a-zA-Z0-9]*/ ? 830 } 832 Figure 16 834 6.3. Notices And Remarks 836 In RDAP, notices and remarks share the same structure. The 837 difference is that notices are meta-data regarding the entirety of a 838 response whereas remarks are meta-data covering a specific instance 839 of an object class. 841 $notices = [ $notice * ] 843 $notice = { 844 "title" : string ?, 845 "description" : [ string * ], 846 "type" : string ?, 847 $links ?, 848 $lang ? 849 } 851 Figure 17 853 6.4. Language Identifier 855 The "lang" member occurs many RDAP data structures. And the same 856 construct is used in the links structures. 858 ; the language value as defined in RFC 5646 859 $lang_value =: /[a-z]{2}(\-[A-Z][a-zA-Z]*(\-[A-Z]{2})?)?/ 861 $lang = ( "lang" : $lang_value ) 863 Figure 18 865 6.5. Events 867 RDAP events note when a specific action has occured on an object 868 instance, and by whom. The same structure appears in all object 869 classes, as well as being re-used by entities embedded by other 870 objects. 872 $events = "events" : [ $event * ] 874 $noActorEvent_mixin = ( 875 "eventAction" : string, 876 "eventDate" : datetime, 877 $links ?, 878 $lang ? 879 ) 881 $noActorEvent = { 882 $noActorEvent_mixin 883 } 885 $event = { 886 $noActorEvent_mixin, 887 "eventActor" : string ? 888 } 890 Figure 19 892 6.6. Status 894 The status of RDAP object instances is indicated by an array of 895 strings, where the value of the strings are registered in an IANA 896 registry. 898 $status = "status" : [ string * ] 900 Figure 20 902 6.7. Port 43 904 RDAP object classes reference their corresponding Whois 905 representation using the "port43" object member. This is simply a 906 string holding the hostname of the Whois service. 908 $port43 = "port43" : string 910 Figure 21 912 6.8. Public IDs 914 Some RDAP services are required to identify entities and domains by 915 public identifiers, such as ICANN Registrar IDs. The publicIds 916 object member is an array of objects to represent these identifiers. 918 $publicIds = "publicIds" : [ $publicId * ] 920 $publicId = { 921 "type" : string, 922 "identifier" : string 923 } 925 Figure 22 927 7. Validating Responses 929 Many JSON roots for RDAP are defined in Figure 1. For applications 930 where an RDAP query must yield a specific response, the appropriate 931 root must be used for validating the response. 933 For example, if the RDAP query https://example.com/rdap/ 934 ip/2001:db8::0 is expected to yield an IP network response, then the 935 validation must only use the $network_response root. 937 8. Stricter Validation 939 RDAP has a very lenient JSON model where information and structures 940 not strictly forbidden are allowed. However, this lenient model 941 allows information from RDAP help and error responses to be found in 942 other responses, and responses for single objects to be found in 943 responses from searches. 945 For applications where these structures cannot be mixed and 946 validation is desired, override rules may be used. 948 For readability, two new rules are created to group the single 949 objects and the search results. 951 The responses with a single object returned represented by mixins. 952 This rule groups those mixins. 954 $object_class = ( 955 $entity_mixin | 956 $nameserver_mixin | 957 $domain_mixin | 958 $network_mixin | 959 $autnum_mixin 960 ) 962 Figure 23 964 The responses to searches are objects containing a single search 965 member which is an array containing the object class mixins. This 966 rule groups the search members. 968 $search_results = ( 969 $domainSearchResult | 970 $nameserverSearchResult | 971 $entitySearchResult 972 ) 974 Figure 24 976 Using the new rules in Figure 23 and Figure 24, override rules (rules 977 rewriting existing rules) can be written for greater strictness. 979 These rules for single object responses prevent search and error 980 response elements to be present. 982 @{root} $entity_response = { 983 $response_mixin, 984 $entity_mixin, 985 @{not} $error_mixin, 986 @{not} $search_results 987 } 989 @{root} $nameserver_response = { 990 $response_mixin, 991 $nameserver_mixin, 992 @{not} $error_mixin, 993 @{not} $search_results 994 } 996 @{root} $domain_response = { 997 $response_mixin, 998 $domain_mixin, 999 @{not} $error_mixin, 1000 @{not} $search_results 1001 } 1003 @{root} $network_response = { 1004 $response_mixin, 1005 $network_mixin, 1006 @{not} $error_mixin, 1007 @{not} $search_results 1008 } 1010 @{root} $autnum_response = { 1011 $response_mixin, 1012 $autnum_mixin, 1013 @{not} $error_mixin, 1014 @{not} $search_results 1015 } 1017 Figure 25 1019 These rules for help and error responses prevent single object and 1020 search arrays. 1022 @{root} $error_response = { 1023 $response_mixin, 1024 $error_mixin, 1025 @{not} $object_class, 1026 @{not} $search_results 1027 } 1029 @{root} $help_response = { 1030 $response_mixin, 1031 $lang ?, 1032 @{not} $error_mixin, 1033 @{not} $object_class, 1034 @{not} $search_results 1035 } 1037 Figure 26 1039 These rules for search responses prevent single object and error data 1040 structures. 1042 @{root} $domainSearch_response = { 1043 $response_mixin, 1044 $lang ?, 1045 $domainSearchResult, 1046 @{not} $error_mixin, 1047 @{not} $object_class 1048 } 1050 @{root} $nameserverSearch_response = { 1051 $response_mixin, 1052 $lang ?, 1053 $nameserverSearchResult, 1054 @{not} $error_mixin, 1055 @{not} $object_class 1056 } 1058 @{root} $entitySearch_response = { 1059 $response_mixin, 1060 $lang ?, 1061 $entitySearchResult, 1062 @{not} $error_mixin, 1063 @{not} $object_class 1064 } 1066 Figure 27 1068 9. Complete Rulesets for RDAP 1070 The following rulesets, along with a test framework and examples of 1071 good and bad RDAP JSON instances, may be found at 1072 . 1074 The following is the complete ruleset of JSON Content Rules for RDAP. 1076 ; 1077 ; JSON Content Rules (JCR) ruleset 1078 ; for the Registry Data Access Protocol (RDAP) 1079 ; 1080 ; Specified in RFC 7483 1081 ; 1083 # ruleset-id rdap_level_0 1085 ; 1086 ; The various types of responses 1087 ; 1089 @{root} $entity_response = { 1090 $response_mixin, 1091 $entity_mixin 1092 } 1094 @{root} $nameserver_response = { 1095 $response_mixin, 1096 $nameserver_mixin 1097 } 1099 @{root} $domain_response = { 1100 $response_mixin, 1101 $domain_mixin 1102 } 1104 @{root} $network_response = { 1105 $response_mixin, 1106 $network_mixin 1107 } 1109 @{root} $autnum_response = { 1110 $response_mixin, 1111 $autnum_mixin 1112 } 1114 @{root} $error_response = { 1115 $response_mixin, 1116 $error_mixin 1117 } 1119 @{root} $help_response = { 1120 $response_mixin, 1121 $lang ? 1122 } 1124 @{root} $domainSearch_response = { 1125 $response_mixin, 1126 $lang ?, 1127 $domainSearchResult 1128 } 1130 @{root} $nameserverSearch_response = { 1131 $response_mixin, 1132 $lang ?, 1133 $nameserverSearchResult 1135 } 1137 @{root} $entitySearch_response = { 1138 $response_mixin, 1139 $lang ?, 1140 $entitySearchResult 1141 } 1143 $response_mixin = ( 1144 $rdapConformance ?, 1145 "notices" : $notices ? 1146 ) 1148 ; 1149 ; RFC 7483 Section 4.1 - RDAP Conformance 1150 ; 1152 $rdapConformance = "rdapConformance" : [ string * ] 1154 ; 1155 ; RFC 7483 Section 4.2 - Links 1156 ; 1158 $links = ( "links" : [ $link * ] ) 1160 ; see RFC 5988 1161 $link = { 1162 "value" : uri ?, 1163 "rel" : string ?, 1164 "href" : uri, 1165 "hreflang" : [ $lang_value * ] ?, 1166 "title" : string ?, 1167 "media" : string ?, 1168 "type" : 1169 /[a-zA-Z][a-zA-Z0-9]*\/[a-zA-Z][a-zA-Z0-9]*/ ? 1170 } 1172 ; 1173 ; RFC 7483 Section 4.3 - Notices 1174 ; 1176 $notices = [ $notice * ] 1178 $notice = { 1179 "title" : string ?, 1180 "description" : [ string * ], 1181 "type" : string ?, 1182 $links ?, 1183 $lang ? 1184 } 1186 ; 1187 ; RFC 7483 Section 4.4 - Language Identifier 1188 ; 1190 ; the language value as defined in RFC 5646 1191 $lang_value =: /[a-z]{2}(\-[A-Z][a-zA-Z]*(\-[A-Z]{2})?)?/ 1193 $lang = ( "lang" : $lang_value ) 1195 ; 1196 ; RFC 7483 Section 4.5 - Events 1197 ; 1199 $events = "events" : [ $event * ] 1201 $noActorEvent_mixin = ( 1202 "eventAction" : string, 1203 "eventDate" : datetime, 1204 $links ?, 1205 $lang ? 1206 ) 1208 $noActorEvent = { 1209 $noActorEvent_mixin 1210 } 1212 $event = { 1213 $noActorEvent_mixin, 1214 "eventActor" : string ? 1215 } 1217 ; 1218 ; RFC 7483 Section 4.6 - Status 1219 ; 1221 $status = "status" : [ string * ] 1223 ; 1224 ; RFC 7483 Section 4.7 - Port43 1225 ; 1227 $port43 = "port43" : string 1229 ; 1230 ; RFC 7482 Section 4.8 - Public Ids 1231 ; 1233 $publicIds = "publicIds" : [ $publicId * ] 1235 $publicId = { 1236 "type" : string, 1237 "identifier" : string 1238 } 1240 ; 1241 ; Common Object Class Structures 1242 ; 1244 $common_mixin = ( 1245 "handle" : string ?, 1246 "remarks" : [ $notice * ] ?, 1247 $links ?, 1248 $events ?, 1249 $status ?, 1250 $port43 ?, 1251 $lang ? 1252 ) 1254 ; 1255 ; RFC 7483 Section 5.1 - Entity Object Class 1256 ; 1258 $entities = "entities" : [ $entity_oc * ] 1260 $entity_oc = { 1261 $entity_mixin 1262 } 1264 $entity_mixin = ( 1265 "objectClassName" : "entity", 1266 $common_mixin, 1267 "vcardArray" : [ "vcard", $vcard * ] ?, 1268 "asEventActor" : [ $noActorEvent * ] ?, 1269 "roles" : [ string * ] ?, 1270 $publicIds ?, 1271 $entities ?, 1272 "networks" : [ $network_oc * ] ?, 1273 "autnums" : [ $autnum_oc * ] ? 1274 ) 1276 ; jCard (see RFC 7095) is an algorithm for converting 1277 ; vCard to JSON. Each jCard is represented by an array of 1278 ; vCard properties. The "version" property must be the 1279 ; first property, and there must be one and only one "fn" 1280 ; property in some part of the array. 1281 ; 1282 ; Here we represent this by an ordered array, with "version" 1283 ; being the first property, then listing all the properties 1284 ; that match by property name, then matching 1285 ; the "fn" property, then matching any other property again. 1286 $vcard = [ 1287 [ "version", {}, "text", "4.0" ], 1288 $vcard_not_fn_properties * , 1289 [ "fn", { $vcard_type_param?, $vcard_language_param? , 1290 $vcard_altid_param? , $vcard_pid_param? , 1291 $vcard_pref_param?, $vcard_any_param? }, 1292 "text", string ], 1293 $vcard_not_fn_properties * 1294 ] 1296 $vcard_not_fn_properties = 1297 ( 1298 $vcard_source | 1299 $vcard_kind | 1300 $vcard_n | 1301 $vcard_nicname | 1302 $vcard_photo | 1303 $vcard_bday | 1304 $vcard_anniversary | 1305 $vcard_gender | 1306 $vcard_adr | 1307 $vcard_tel | 1308 $vcard_email | 1309 $vcard_impp | 1310 $vcard_lang | 1311 $vcard_tz | 1312 $vcard_geo | 1313 $vcard_title | 1314 $vcard_role | 1315 $vcard_logo | 1316 $vcard_org | 1317 $vcard_member | 1318 $vcard_related | 1319 $vcard_categories | 1320 $vcard_note | 1321 $vcard_prodid | 1322 $vcard_rev | 1323 $vcard_sound | 1324 $vcard_uid | 1325 $vcard_clientpidmap | 1326 $vcard_url | 1327 $vcard_key | 1328 $vcard_fburl | 1329 $vcard_caladruri | 1330 $vcard_caluri | 1331 $vcard_x10 1332 ) 1334 ; vCard properties. Each one is defined with a common 1335 ; definition, and then a group that matches the property name. 1336 $vcard_source = [ "source", $vcard_source_prop ] 1337 $vcard_source_prop = ( 1338 { $vcard_pid_param? , $vcard_pref_param?, $vcard_altid_param? , 1339 $vcard_mediatype_param?, $vcard_any_param? } , 1340 "uri", uri 1341 ) 1343 $vcard_kind = [ "kind", $vcard_kind_prop ] 1344 $vcard_kind_prop = ( 1345 { $vcard_any_param? }, 1346 "text", $vcard_kind_type 1347 ) 1349 $vcard_n = [ "n", $vcard_n_prop ] 1350 $vcard_n_prop = ( 1351 { $vcard_sort_as_param? , $vcard_language_param? , 1352 $vcard_altid_param? , $vcard_any_param? }, 1353 "text", $vcard_string_type_array 1354 ) 1356 $vcard_nicname = [ "nicname", $vcard_nicname_prop ] 1357 $vcard_nicname_prop = ( 1358 { $vcard_type_param? , $vcard_language_param? , 1359 $vcard_altid_param? , $vcard_pid_param? , 1360 $vcard_pref_param? , $vcard_any_param ? }, 1361 "text", $vcard_string_type_array 1362 ) 1364 $vcard_photo = [ "photo", $vcard_photo_prop ] 1365 $vcard_photo_prop = ( 1366 { $vcard_altid_param? , $vcard_type_param? , 1367 $vcard_mediatype_param? , $vcard_pref_param? , 1368 $vcard_pid_param? , $vcard_any_param? }, 1369 "uri", uri 1370 ) 1372 $vcard_bday = [ "bday", $vcard_bday_prop ] 1373 $vcard_bday_prop = ( 1374 ( { $vcard_language_param?, $vcard_altid_param?, 1375 $vcard_calscale_param?, $vcard_any_param? }, 1376 "text", string 1377 ) | 1378 ( { $vcard_altid_param?, $vcard_calscale_param?, 1379 $vcard_any_param? }, 1380 "date-and-or-time", $vcard_date_and_or_time_type 1381 ) 1382 ) 1384 $vcard_anniversary = [ "anniversary", $vcard_anniversary_prop ] 1385 $vcard_anniversary_prop = ( 1386 { $vcard_altid_param?, $vcard_calscale_param?, $vcard_any_param? }, 1387 "date-and-or-time", $vcard_date_and_or_time_type 1388 ) 1390 $vcard_gender = [ "gender", $vcard_gender_prop ] 1391 $vcard_gender_prop = ( 1392 { $vcard_any_param? }, 1393 "text", 1394 ( $vcard_gender_type | [ $vcard_gender_type, string + ] ) 1395 ) 1397 $vcard_adr = [ "adr", $vcard_adr_prop ] 1398 $vcard_adr_prop = ( 1399 { $vcard_label_param? , $vcard_language_param? , 1400 $vcard_geo_param ? , $vcard_tz_param? , 1401 $vcard_altid_param? , $vcard_pid_param? , 1402 $vcard_pref_param? , $vcard_type_param? , 1403 $vcard_any_param? }, 1404 "text", $vcard_string_type_array 1405 ) 1407 $vcard_tel = [ "tel", $vcard_tel_prop ] 1408 $vcard_tel_prop = ( 1409 ( { $vcard_type_param? , $vcard_pid_param? , $vcard_pref_param? , 1410 $vcard_altid_param?, $vcard_any_param? }, "text", string 1411 ) | 1412 ( { $vcard_type_param? , $vcard_pid_param? , $vcard_pref_param? , 1413 $vcard_altid_param?, $vcard_mediatype_param?, 1414 $vcard_any_param? }, 1415 "uri", uri..tel 1416 ) 1417 ) 1419 $vcard_email = [ "email", $vcard_email_prop ] 1420 $vcard_email_prop = ( 1421 { $vcard_pid_param? , $vcard_pref_param? , $vcard_type_param? , 1422 $vcard_altid_param? , $vcard_any_param ? }, 1423 "text", string 1424 ) 1426 $vcard_impp = [ "impp", $vcard_impp_prop ] 1427 $vcard_impp_prop = ( 1428 { $vcard_pid_param? , $vcard_pref_param? , $vcard_type_param? , 1429 $vcard_mediatype_param? , $vcard_altid_param? , 1430 $vcard_any_param }, 1431 "uri", uri..impp 1432 ) 1434 $vcard_lang = [ "lang", $vcard_lang_prop ] 1435 $vcard_lang_prop = ( 1436 { $vcard_pid_param? , $vcard_pref_param? , $vcard_altid_param? , 1437 $vcard_type_param? , $vcard_any_param? }, 1438 "language-tag", $vcard_language_tag_type 1439 ) 1441 $vcard_tz = [ "tz", $vcard_tz_prop ] 1442 $vcard_tz_prop = ( 1443 { $vcard_altid_param?, $vcard_pid_param? , $vcard_pref_param? , 1444 $vcard_type_param? , $vcard_mediatype_param?, 1445 $vcard_any_param? }, 1446 ( ( "text", string ) | 1447 ( "uri" , uri ) | 1448 ( "utc-offset" , $vcard_utc_offset_type ) ) 1449 ) 1451 $vcard_geo = [ "geo", $vcard_geo_prop ] 1452 $vcard_geo_prop = ( 1453 { $vcard_pid_param? , $vcard_pref_param? , $vcard_type_param? , 1454 $vcard_mediatype_param? , $vcard_altid_param? , 1455 $vcard_any_param? }, 1456 "uri", uri..geo 1457 ) 1459 $vcard_title = [ "title", $vcard_title_prop ] 1460 $vcard_title_prop = ( 1461 { $vcard_language_param? , $vcard_pid_param? , $vcard_pref_param? , 1462 $vcard_altid_param? , $vcard_type_param? , $vcard_any_param? }, 1463 "text", string 1464 ) 1466 $vcard_role = [ "role", $vcard_role_prop ] 1467 $vcard_role_prop = ( 1468 { $vcard_language_param? , $vcard_pid_param? , $vcard_pref_param? , 1469 $vcard_altid_param? , $vcard_type_param? , $vcard_any_param? }, 1471 "text", string 1472 ) 1474 $vcard_logo = [ "logo", $vcard_logo_prop ] 1475 $vcard_logo_prop = ( 1476 { $vcard_altid_param? , $vcard_type_param? , 1477 $vcard_mediatype_param? , $vcard_pref_param? , 1478 $vcard_pid_param? , $vcard_language_param? , 1479 $vcard_any_param? }, 1480 "uri", uri 1481 ) 1483 $vcard_org = [ "org", $vcard_org_prop ] 1484 $vcard_org_prop = ( 1485 { $vcard_sort_as_param? , $vcard_language_param? , 1486 $vcard_pid_param? , $vcard_pref_param? , $vcard_altid_param? , 1487 $vcard_type_param? , $vcard_any_param? }, 1488 "text", $vcard_string_type_array 1489 ) 1491 $vcard_member = [ "member", $vcard_member_prop ] 1492 $vcard_member_prop = ( 1493 { $vcard_altid_param? , $vcard_mediatype_param? , 1494 $vcard_pref_param? , $vcard_pid_param? , $vcard_any_param? }, 1495 "uri", uri 1496 ) 1498 $vcard_related = [ "related", $vcard_related_prop ] 1499 $vcard_related_prop = ( 1500 ( { $vcard_mediatype_param? , $vcard_pref_param? , 1501 $vcard_altid_param? , $vcard_type_param? , 1502 $vcard_any_param? }, 1503 "uri", uri 1504 ) | 1505 ( { $vcard_language_param? , $vcard_pref_param? , 1506 $vcard_altid_param? , $vcard_type_param? , 1507 $vcard_any_param? }, 1508 "text", $vcard_related_type_array 1509 ) 1510 ) 1512 $vcard_categories = [ "categories", $vcard_categories_prop ] 1513 $vcard_categories_prop = ( 1514 { $vcard_pid_param? , $vcard_pref_param? , $vcard_type_param ?, 1515 $vcard_altid_param? , $vcard_any_param? }, 1516 "text", $vcard_string_type_array 1517 ) 1518 $vcard_note = [ "note", $vcard_note_prop ] 1519 $vcard_note_prop = ( 1520 { $vcard_language_param? , $vcard_pid_param? , 1521 $vcard_pref_param? , $vcard_type_param? , 1522 $vcard_altid_param? , $vcard_any_param ? }, 1523 "text", string 1524 ) 1526 $vcard_prodid = [ "prodid", $vcard_prodid_prop ] 1527 $vcard_prodid_prop = ( { $vcard_any_param ? }, "text", string ) 1529 $vcard_rev = [ "rev", $vcard_rev_prop ] 1530 $vcard_rev_prop = ( 1531 { $vcard_any_param ? }, "timestamp", datetime 1532 ) 1534 $vcard_sound = [ "sound", $vcard_sound_prop ] 1535 $vcard_sound_prop = ( 1536 { $vcard_altid_param? , $vcard_mediatype_param? , 1537 $vcard_language_param? , $vcard_pref_param? , 1538 $vcard_pid_param? , $vcard_any_param? }, 1539 "uri", uri 1540 ) 1542 $vcard_uid = [ "uid", $vcard_uid_prop ] 1543 $vcard_uid_prop = ( 1544 ( { $vcard_any_param? }, "uri", uri ) | 1545 ( { $vcard_any_param? }, "text", string ) 1546 ) 1548 $vcard_clientpidmap = [ "clientpidmap", $vcard_clientpidmap_prop ] 1549 $vcard_clientpidmap_prop = ( {}, "text", [ /^[0-9]+$/, uri ] ) 1551 $vcard_url = [ "url", $vcard_url_prop ] 1552 $vcard_url_prop = ( 1553 { $vcard_altid_param? , $vcard_mediatype_param? , 1554 $vcard_pref_param? , $vcard_pid_param? , $vcard_any_param? }, 1555 "uri", uri 1556 ) 1558 $vcard_key = [ "key", $vcard_key_prop ] 1559 $vcard_key_prop = ( 1560 ( { $vcard_mediatype_param? , $vcard_pref_param? , 1561 $vcard_altid_param? , $vcard_type_param? , 1562 $vcard_any_param? }, 1563 "uri", uri 1564 ) | 1565 ( { $vcard_pref_param? , $vcard_altid_param? , 1566 $vcard_type_param? , $vcard_any_param? }, 1567 "text", string 1568 ) 1569 ) 1571 $vcard_fburl = [ "fburl", $vcard_fburl_prop ] 1572 $vcard_fburl_prop = ( 1573 { $vcard_altid_param? , $vcard_mediatype_param? , 1574 $vcard_altid_param? , $vcard_pref_param? , 1575 $vcard_pid_param? , $vcard_any_param? }, 1576 "uri", uri 1577 ) 1579 $vcard_caladruri = [ "caladruri", $vcard_caladruri_prop ] 1580 $vcard_caladruri_prop = ( 1581 { $vcard_altid_param? , $vcard_mediatype_param? , 1582 $vcard_altid_param? , $vcard_pref_param? , 1583 $vcard_pid_param? , $vcard_any_param? }, 1584 "uri", uri 1585 ) 1587 $vcard_caluri = [ "caluri", $vcard_caluri_prop ] 1588 $vcard_caluri_prop = ( 1589 { $vcard_altid_param? , $vcard_mediatype_param? , 1590 $vcard_altid_param? , $vcard_pref_param? , 1591 $vcard_pid_param? , $vcard_any_param? }, 1592 "uri", uri 1593 ) 1595 $vcard_x10 = [ $vcard_x_name_type, $vcard_x10_prop ] 1596 $vcard_x10_prop = ( 1597 { $vcard_language_param? , $vcard_pref_param? , 1598 $vcard_altid_param? , $vcard_pid_param? , 1599 $vcard_type_param? , $vcard_mediatype_param? , 1600 $vcard_calscale_param? , $vcard_sort_as_param? , 1601 $vcard_geo_param? , $vcard_tz_param? , 1602 $vcard_label_param? , $vcard_any_param? }, 1603 $vcard_x_name_type, $vcard_string_type_array 1604 ) 1606 ; Each vCard property can have parameters. 1607 $vcard_language_param = "language" : $vcard_language_tag_type 1608 $vcard_pref_param = "pref" : $vcard_pref_type 1609 $vcard_altid_param = "altid" : string 1610 $vcard_pid_param = "pid" : $vcard_pid_type_array 1611 $vcard_type_param = "type" : $vcard_type_type_array 1612 $vcard_mediatype_param = "mediatype" : $vcard_mediatype_type 1613 $vcard_calscale_param = "calscale" : $vcard_calscale_type 1614 $vcard_sort_as_param = "sort-as" : $vcard_string_type_array 1615 $vcard_geo_param = "geo" : uri..geo 1616 $vcard_tz_param = "tz" : $vcard_utc_offset_type 1617 $vcard_label_param = "label" : $vcard_string_type_array 1618 $vcard_any_param = /^x\-[A-Za-z0-9\-]*$/ : $vcard_string_type_array 1620 ; Each vCard property has a value type. 1621 $vcard_string_type_array = 1622 ( string | [ ( string | [ string * ] ) * ] ) 1623 $vcard_language_tag_type =: 1624 /[a-z]{2}(-[A-Z][a-zA-Z]*(\-[A-Z]{2})?)?/ 1625 $vcard_mediatype_type =: /^\w+\/[\-.\w]+(?:\+[\-.\w]+)?$/ 1626 $vcard_utc_offset_type =: /^(([\-\+]\d{1,2}):?(\d{2})?)?$/ 1627 $vcard_date_or_time =: ( 1628 /^(\d{4})-?(\d{2})-?(\d{2})$/ | 1629 /^(\d{4})$/ | 1630 /^--(\d{2})-?(\d{2})$/ | 1631 /^--(\d{2})$/ | 1632 /^---(\d{2})$/ | 1633 /^(\d{2})(([-+]\d{1,2}):?(\d{2})?)?$/ | 1634 /^(\d{2}):?(\d{2})(([\-\+]\d{1,2}):?(\d{2})?)?$/ | 1635 /^(\d{2}):?(\d{2}):?(\d{2})(Z|([\-\+]\d{1,2}):?(\d{2})?)?$/ | 1636 /^-(\d{2}):?(\d{2})(Z|([\-\+]\d{1,2}):?(\d{2})?)?$/ | 1637 /^-(\d{2})(([\-\+]\d{1,2}):?(\d{2})?)?$/ | 1638 /^--(\d{2})(([\-\+]\d{1,2}):?(\d{2})?)?$/ 1639 ) 1640 $vcard_date_and_or_time_type =: ( 1641 datetime | $vcard_date_or_time 1642 ) 1643 $vcard_group_type =: /^[a-zA-Z0-9\-]+$/ 1644 $vcard_type_type =: ( 1645 "home" | "work" | $vcard_tel_type | $vcard_related_type | 1646 $vcard_x_name_type 1647 ) 1648 $vcard_type_type_array = ( 1649 $vcard_type_type | [ $vcard_type_type * ] 1650 ) 1651 $vcard_tel_type =: ( 1652 "text" | "voice" | "fax" | "cell" | "video" | 1653 "pager" | "textphone" | "main-number" 1654 ) 1655 $vcard_tel_type_array = ( $vcard_tel_type | [ $vcard_tel_type * ] ) 1656 $vcard_related_type =: ( 1657 "contact" | "acquaintance" | "friend" | "met" | 1658 "co-worker" | "colleague" | "co-resident" | 1659 "neighbor" | "child" | "parent" | "sibling" | 1660 "spouse" | "kin" | "muse" | "crush" | "date" | 1661 "sweetheart" | "me" | "agent" | "emergency" 1663 ) 1664 $vcard_related_type_array = ( 1665 $vcard_related_type | [ $vcard_related_type * ] 1666 ) 1667 $vcard_index_type =: /^[1-9]?[0-9]*$/ 1668 $vcard_expertise_level_type =: ( 1669 "beginner" | "average" | "expert" 1670 ) 1671 $vcard_hobby_type =: ( "high" | "medium" | "low" ) 1672 $vcard_pref_type =: /^[1-9]?[0-9]{1}$|^100$/ 1673 $vcard_pid_type =: /^[0-9]+(\.[0-9]+)?$/ 1674 $vcard_pid_type_array = ( 1675 $vcard_pid_type | [ $vcard_pid_type * ] 1676 ) 1677 $vcard_gender_type =: ( "M" | "F" | "O" | "N" | "U" ) 1678 $vcard_gender_type_array = ( 1679 $vcard_gender_type | [ $vcard_gender_type * ] 1680 ) 1681 $vcard_kind_type =: ( 1682 "individual" | "group" | "org" | "location" | 1683 "application" | "device" 1684 ) 1685 $vcard_iana_token_type =: /^[A-Za-z0-9\-]*$/ 1686 $vcard_x_name_type =: /^x\-[A-Za-z0-9\-]*$/ 1687 $vcard_calscale_type =: ( 1688 "gregorian" | $vcard_iana_token_type | $vcard_x_name_type 1689 ) 1691 ; 1692 ; RFC 7483 Section 5.2 - Nameserver Object Class 1693 ; 1695 $nameservers = "nameservers" : [ $nameserver_oc * ] 1697 $nameserver_oc = { 1698 $nameserver_mixin 1699 } 1701 $nameserver_mixin = ( 1702 "objectClassName" : "nameserver", 1703 $common_mixin, 1704 "ldhName" : fqdn, 1705 "unicodeName" : idn ?, 1706 "ipAddresses" : { 1707 "v4" : [ ipv4 + ] ?, 1708 "v6" : [ ipv6 + ] ? 1709 } ?, 1710 $entities ? 1712 ) 1714 ; 1715 ; RFC 7483 Section 5.3 - Domain Object Class 1716 ; 1718 $domain_oc = { 1719 $domain_mixin 1720 } 1722 $domain_mixin = ( 1723 "objectClassName" : "domain", 1724 $common_mixin, 1725 "ldhName" : fqdn, 1726 "unicodeName" : idn ?, 1727 "variants" : [ $variant * ] ?, 1728 $nameservers ?, 1729 $secureDNS ?, 1730 $entities ?, 1731 $publicIds ?, 1732 "network" : $network_oc ? 1733 ) 1735 $variant = { 1736 "relation" : [ string * ] ?, 1737 "idnTable" : string ?, 1738 "variantNames" : [ 1739 { "ldhName" : fqdn, "unicodeName" : idn } * 1740 ] 1741 } 1743 $secureDNS = "secureDNS" : { 1744 "zoneSigned" : boolean ?, 1745 "delegationSigned" : boolean ?, 1746 "maxSigLife" : integer ?, 1747 "dsData" : [ $dsData_obj * ] ?, 1748 "keyData" : [ $keyData_obj * ] ? 1749 } 1751 $dsData_obj = { 1752 "keyTag" : integer, 1753 "algorithm" : integer, 1754 "digest" : string, 1755 "digestType" : integer, 1756 $events ?, 1757 $links ? 1758 } 1759 $keyData_obj = { 1760 "flags" : integer, 1761 "protocol" : integer, 1762 "publicKey" : string, 1763 "algorithm" : integer, 1764 $events ?, 1765 $links ? 1766 } 1768 ; 1769 ; RFC 7483 Section 5.4 - IP Network Object Class 1770 ; 1772 $network_oc = { 1773 $network_mixin 1774 } 1776 $network_mixin = ( 1777 "objectClassName" : "ip network", 1778 $common_mixin, 1779 "startAddress" : ( ipv4 | ipv6 ) ?, 1780 "endAddres" : ( ipv4 | ipv6 ) ?, 1781 "ipVersion" : ( "v4" | "v6" ) ?, 1782 "name" : string ?, 1783 "type" : string ?, 1784 "country" : /[A-Z]{2}/ ?, 1785 "parentHandle" : string ?, 1786 $entities ? 1787 ) 1789 ; 1790 ; RFC 7483 Section 5.5 - Autnum Object Class 1791 ; 1793 $autnum_oc = { 1794 $autnum_mixin 1795 } 1797 $autnum_mixin = ( 1798 "objectClassName" : "autnum", 1799 $common_mixin, 1800 "startAutnum" : int32 ?, 1801 "endAutnum" : int32 ?, 1802 "name" : string ?, 1803 "type" : string ?, 1804 "country" : string ?, 1805 $entities ? 1806 ) 1807 ; 1808 ; RFC 7483 Section 6 - Error 1809 ; 1811 $error_mixin = ( 1812 "errorCode" : integer, 1813 "title" : string ?, 1814 "description" : [ string * ] ? 1815 ) 1817 ; 1818 ; RFC 7483 Section 8 - Search Results 1819 ; 1821 $domainSearchResult = 1822 "domainSearchResult" : [ $domain_oc * ] 1824 $nameserverSearchResult = 1825 "nameserverSearchResult" : [ $nameserver_oc * ] 1827 $entitySearchResult = 1828 "entitySearchResult" : [ $entity_oc * ] 1830 Figure 28: Complete Ruleset for RDAP 1832 The following is the complete ruleset of override rules for stricter 1833 validation of RDAP. 1835 ; 1836 ; Override rules for strict RDAP checking. 1837 ; 1839 ; 1840 ; Object class response 1841 ; 1843 @{root} $entity_response = { 1844 $response_mixin, 1845 $entity_mixin, 1846 @{not} $error_mixin, 1847 @{not} $search_results 1848 } 1850 @{root} $nameserver_response = { 1851 $response_mixin, 1852 $nameserver_mixin, 1853 @{not} $error_mixin, 1854 @{not} $search_results 1855 } 1857 @{root} $domain_response = { 1858 $response_mixin, 1859 $domain_mixin, 1860 @{not} $error_mixin, 1861 @{not} $search_results 1862 } 1864 @{root} $network_response = { 1865 $response_mixin, 1866 $network_mixin, 1867 @{not} $error_mixin, 1868 @{not} $search_results 1869 } 1871 @{root} $autnum_response = { 1872 $response_mixin, 1873 $autnum_mixin, 1874 @{not} $error_mixin, 1875 @{not} $search_results 1876 } 1877 ; 1878 ; Help and error response 1879 ; 1881 @{root} $error_response = { 1882 $response_mixin, 1883 $error_mixin, 1884 @{not} $object_class, 1885 @{not} $search_results 1886 } 1888 @{root} $help_response = { 1889 $response_mixin, 1890 $lang ?, 1891 @{not} $error_mixin, 1892 @{not} $object_class, 1893 @{not} $search_results 1894 } 1895 ; 1896 ; Search responses 1897 ; 1899 @{root} $domainSearch_response = { 1900 $response_mixin, 1901 $lang ?, 1902 $domainSearchResult, 1903 @{not} $error_mixin, 1904 @{not} $object_class 1905 } 1907 @{root} $nameserverSearch_response = { 1908 $response_mixin, 1909 $lang ?, 1910 $nameserverSearchResult, 1911 @{not} $error_mixin, 1912 @{not} $object_class 1913 } 1915 @{root} $entitySearch_response = { 1916 $response_mixin, 1917 $lang ?, 1918 $entitySearchResult, 1919 @{not} $error_mixin, 1920 @{not} $object_class 1921 } 1922 ; 1923 ; Object class mixins 1924 ; 1926 $object_class = ( 1927 $entity_mixin | 1928 $nameserver_mixin | 1929 $domain_mixin | 1930 $network_mixin | 1931 $autnum_mixin 1932 ) 1933 ; 1934 ; All search results 1935 ; 1937 $search_results = ( 1938 $domainSearchResult | 1939 $nameserverSearchResult | 1940 $entitySearchResult 1941 ) 1943 Figure 29: Override Ruleset for RDAP 1945 10. Normative References 1947 [RFC5988] Nottingham, M., "Web Linking", RFC 5988, 1948 DOI 10.17487/RFC5988, October 2010, . 1951 [RFC7095] Kewisch, P., "jCard: The JSON Format for vCard", RFC 7095, 1952 DOI 10.17487/RFC7095, January 2014, . 1955 [RFC7159] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data 1956 Interchange Format", RFC 7159, DOI 10.17487/RFC7159, March 1957 2014, . 1959 [RFC7483] Newton, A. and S. Hollenbeck, "JSON Responses for the 1960 Registration Data Access Protocol (RDAP)", RFC 7483, 1961 DOI 10.17487/RFC7483, March 2015, . 1964 [I-D.newton-json-content-rules] 1965 Newton, A. and P. Cordell, "A Language for Rules 1966 Describing JSON Content", draft-newton-json-content- 1967 rules-09 (work in progress), September 2017. 1969 Author's Address 1971 Andrew Lee Newton 1972 American Registry for Internet Numbers 1973 3635 Concorde Parkway 1974 Chantilly, VA 20151 1975 US 1977 Email: andy@arin.net 1978 URI: http://www.arin.net