Methods

Module methods.

Those starting with '_' are meant for internal use.

new

new handles the following parameters:

 { 
   use_cache           => <0|1>,
   debug               => <0..8>,
   service_url         => <0|service_url,
   norid_header_secret => <0|test_secret>,
   norid_header_proxy  => <0|1>,
   norid_referral_ip   => <0|1|ip-address>,
   bauth_username      => <0|bauth_username>,
   bauth_password      => <0|bauth_password>,
   fieldset            => <0|fieldset>
   access_layers       => { layer1=>1, layer2=>2, .. }
   page_size           => <0|page size>, default $RDAP_PAGE_SIZE
   cursor              => <0|cursor>
   nopages             => <0|nopages>, default $RDAP_ENTITY_QUOTA_PAGES
   insert_page_info    => <0|1>
   force_ipv           => <0|4|6>
 }

All parameters are optional:

* use_cache:
  - 1: activate Net::RDAP lookup cache, see Net::RDAP for use,
       Note: usage not needed or tested for this lib.

* debug:
  - 0  : debug off
  - 1  : debug output from this module
  - 2  : headers output from LWP UA callback
  - 3  : Debug output from Net::RDAP::UA (headers and contents)
  - 4-8: Debug output using LWP::ConsoleLogger::Easy,
         which then must be installed

* service_url: 
  - the full http(s)-address of the Norid RDAP-servie to
    be accessed. 
  - default is $SERVICE_URL above.

* norid_header_secret: 
  - access token for layered access, and
    the token is sent in the 'X-RDAP-Secret' header.

* norid_header_proxy : 
  - Norid internal use only. 
  - true if the calling client can act as a proxy,
    and the header 'X-RDAP-Web-Proxy' is then set to 1.

* norid_referral_ip : 
  - Norid internal use only.
  - set if the calling client ip address argument shall be sent. When set:
    - if the argument passed is a pure integer, use the local ip-address as value.
    - if the argument passed is a valid ip address, use that address
      as value. This is the normal variant to be used to pass a proper client 
      ip address.
    - the ip-address is passed to the server in the '?client_ip=<ip-address>'
      argument.

* bauth_username:
  - Basic authentication username
    For a Norid registrar RDAP user where
    - RDAP username is     : 'rdapuser',
    - Norid registrar id is: 'reg1234'
    the basic username must be set as follows: 'rdapuser@reg1234'.

* bauth_password:
  - Basic authentication password

* fieldset:
  - Undef or one of the valid fieldSets to determine how much data
    should be returned for search hits
    If rate limiting becomes a problem, fieldset='full' could be
    considered.

* access_layers:
  - Optional. Access_layers to be expected and handled. Replaces the
    preconfigered and default ones in %RDAP_REGISTERED_LAYERS.

Paging parameters:

* page_size:
  Page size for the the RDAP service.
  Recommended set by the caller, as the lib may have wrong default
  values.

* cursor:
  - Undef or a cursor string to be used in succeeding page lookups,
    undef for first page.

* nopages:
  - max number of pages from cursor (1..x, default 10).
    The pageSize in the RDAP service decides the number of hits per
    page.


* insert_page_info:
   - Text formatting option, insert page info in the text if set.

Paging parameters set by lib, read them only:

* total_no_pages:
  Total number of pages that can be fetched with a search combo.
  Calculated as total_size / page_size and set by lib as soon as
  we know the value.

* page_number:
  The page number signalled by the rdap service.

* first_page|cur_page|prev_page|next_page:
   - Page hrefs set by lib when a search is performed.

Various:

* force_ipv:
  - force use of ip protocl version, 0/undef is default, else set to
    4 or 6

lookup

Do an RDAP lookup.

- $query      : Specifies the query string.
- $check      : Specifies if http 'head' shall be done, default is 'get'.
- $nameservers: Must be set to 1 for nameserver_name search
                and 2 for a domains by nameserver name search
- $entity     : Must be set to true for entity lookup, in which case the query should 
                identify an entity, like:
                 - a domain name or a handle
                For a search, this is more complex:
                - For identities (orgno, N.XXX.YYY or registrant handles),
                  a search domains by identity/registrant is done as default.
                  To force the search to search for entities by
                  identity/registrant instead, this option must be
                  set.

_lookup_rdap

Do an RDAP HEAD or GET lookup.

- $http_type: 'head' or 'get'
- $uri      : full arguments to base URI, identifying the actual lookup
              method and args
- other args as passed in $self.

_fetch_get_pages

Handle RDAP GET operations.

If search, loop and fetch the requested number of pages from the offset set by the cursor parameter.

get_href_page_cursor

Find and return cursor value from a href page link

_ua_callback

UA callback function to collect relevant info from the HTTP response.

For now, we want the response headers.

_map_rdap_error

Some RDAP error is returned from Net::RDAP, ref. Net::RDAP::Error.

Those are normally HTTP response errors in the 400 and 500 range, which are mapped to one of the $RDAP_LOOKUP_ERR_XXX local errors.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Status - All 1xx, 2xx, 3xx are not errors, but OK, need not be handled. - All 4xx, 5xx indicate some problem, so map relevant ones. - Some are not mapped. A warning is given, which may indicate that some error case has occured, and that the situation may need to be handled and added to this lib.

get_my_ip_address

Find local ip-address.

(Note: Sys::HostAddr were also tried for this purpose, but could die at random, so Sys::HostIP is selected. Only ipv4 seems to be processed by Sys::HostIP, so the selection is limited to ipv4. TODO: Consider using another module, which also supports v6).

Best guess IP seems to be the one on the en0-interface, but when a VPN is in use, you might want that address to be selected. So, try to do the best ip selection by ourselves by a reverse sort instead of a sort, thus selecting the 'highest' numbered and public ip-address).

Return localhost if no other ip is found.

Return empty if localhost iface not found.

_is_a_valid_parameter

Check whether a parameter contains something fishy

Ref. CSS: https://www.owasp.org/index.php/Testing_for_Cross_site_scripting#Description_of_Cross-site_scripting_Vulnerabilities

Returns 0 if not ok, 1 if OK.

The below code can be used if special chars should also be generally blocked, but not in use for now:

my $ILLCHARS = q/`';_|<>${}[]^]/;
my $ILLCHARSqr = qr/[\|<>\$\{\}\[\]\^';_\|]/mx;
if ($v =~ $ILLCHARSqr) {
   print STDERR "Parameter value contains illegal character(s), one or more of: '$ILLCHARS': '$v'";
   return;
}

validate_and_analyze

1) Validate ip address, if set

2) Validate query, return if query not among the expexted ones.
   - domain name or name server name
   - some object handle (D, P, R, H)
   - some registrar handle (regXXX-NORID)
   - some identity (9 digits orgno, N.XXX.yyyyyyyy)

2) Analyze query and args and find what http method and uri arguments
   to use for the lookup and set them in '_method' and '_uri'

is_a_valid_domainname

Check whether a domainname or nameserver is valid.

Returns undef if not ok. Returns 1 if OK.

rdap_get_obj_name

Fetch the name from an object.

If we have a Net::DNS::Domain object (domain/ns), also get the xname.

norid_handle_type

Determine type of Norid handle.

result_as_rdap_string

Return sensible rdap formatted text string. Uses internal helper formatting functions.

Shows how to access data returned by Net::RDAP.

rdap_obj_as_string

Return sensible rdap formatted text string for an rdap object.

Code stolen from rdapper and adapted.

rdap_notice_or_remark_as_string

Format RDAP notice or remark as text string.

rdap_vcard_as_string

Format vcard object(s) as a text string.

rdap_page_info_as_string

Format and insert page info, if requested.

rdap_get_entities_by_entity_handle

Based on a subscriber handle (O or P), fetch domain list for it.

rdap_get_domains_by_entity_handle

Based on a subscriber handle (O or P), fetch domain list for it.

For domain list on entity, we will try fetch all domains possible on a single quota as default via $RDAP_ENTITY_QUOTA_PAGES since it is set to a high enough value. User may try fewer or more pages bt specifying nopages.

rdap_get_entities_by_domain_name

Domain lookup entities for a domain name.

NAME

NOLookup::RDAP::RDAPLookup - Lookup RDAP data from the Norid (.no) RDAP service.

SYNOPSIS

    use Encode;
    use NOLookup::RDAP::RDAPLookup;
 
    # Default API service URL
    my $SERVICE_URL = "https://rdap.norid.no";

    # Example 1: Domain name lookup
    # Decode the query when needed, like for IDNs
    # or names with national characters.

    my $q = 'norid.no';
    #$q = decode('ISO8859-1', 'øl.no');

    # Authenticate with secret and be a proxy (Norid only) 
    my $bo = NOLookup::RDAP::RDAPLookup->new(
     {
	service_url         => 'https://rdap.norid.no',
	debug               => 0,
	use_cache  	    => 0,
	norid_header_secret => '<secret>',
	norid_header_proxy  => 1,
     });

    # Authenticate with basic authentication 
    my $bo = NOLookup::RDAP::RDAPLookup->new(
     {
	service_url         => 'https://rdap.norid.no',
	debug               => 0,
	use_cache  	    => 0,
	bauth_username      => 'rdapuser@reg1234',
	bauth_password      => '<password>',
     });

    # test HEAD operation for existence
    $bo->lookup($q, 1, 0, 0);
    if ($bo->error) {
       print "HEAD: Error, error / status: ",
          $bo->error . "/" . $bo->status) . "\n";
    }

    # test GET operations
    $bo->lookup($q, 0, 0, 0);
    if ($bo->error) {
       print "GET: Error, error / status: ",
          $bo->error . "/" . $bo->status) . "\n";
    }
	
    # result of lookup is in $bo->result
    # This result contains response objects built by Net::RDAP

    # if a lookup has arguments which results in a search type, the
    # is_a_search method returns true. This is a hint to the caller to
    # process paging information in the result, and maybe perform several
    # next-lookups to get more data.

    my $res = $bo->result;
    print "handle: ", $bo->handle, "\n";

 * See bin/no_rdap.pl for more information on usage.

 * See various formatting/helper functions in this file for how to
   access the various objects returned by Net::RDAP.

DESCRIPTION

This module provides an object oriented API for use with the Norid RDAP service. It uses the Net::RDAP module from Cpan internally to fetch information from the Norid RDAP.

SUPPORT

For now, support questions should be sent to:

<(nospam)info(at)norid.no>

SEE ALSO

https://www.norid.no/en https://teknisk.norid.no/en/integrere-mot-norid/rdap-tjenesten

CAVEATS

AUTHOR

Trond Haugen, <(nospam)info(at)norid.no>

COPYRIGHT

Copyright (c) 2020- Trond Haugen <(nospam)info(at)norid.no>. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

LICENSE

This library is free software. You can redistribute it and/or modify it under the same terms as Perl itself.

About the Norid RDAP API

See https://teknisk.norid.no/en/integrere-mot-norid/rdap-tjenesten