blob: 6f44996396f8961506b0f648b5ce818167f2f9c1 [file] [log] [blame]
/*
* Copyright (c) 2022 Apple Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DNS_OBJ_DOMAIN_NAME_H
#define DNS_OBJ_DOMAIN_NAME_H
//======================================================================================================================
// MARK: - Headers
#include "dns_obj.h"
#include "dns_common.h"
#include <stdint.h>
#include <stdbool.h>
#include "nullability.h"
//======================================================================================================================
// MARK: - Object Reference Definition
DNS_OBJECT_TYPEDEF_OPAQUE_POINTER(domain_name);
#include "dns_obj_rr_nsec3.h"
//======================================================================================================================
// MARK: - Object Methods
/*!
* @brief
* Create a domain name object from the domain name labels.
*
* @param labels
* The domain name labels.
*
* @param allocate_memory
* The boolean value to indicate whether to copy the domain name labels to a newly allocated memory. If the it is false, the caller is responsible to ensure
* that the domain name labels is always valid during the life time of this domain name object.
*
* @param out_error
* The error value indicates the success of the function call or the error encountered.
*
* @result
* The domain name object created, or NULL if error happens during creation. <code>out_error</code> will be set to the error encountered if it is not NULL.
*/
dns_obj_domain_name_t NULLABLE
dns_obj_domain_name_create_with_labels(const uint8_t * NONNULL labels, const bool allocate_memory,
dns_obj_error_t * NULLABLE out_error);
/*!
* @brief
* Concatenate two domain name object together to form a new domain name object, where <code>front_domain</code> is the left part, and
* <code>end_domain</code> is the right part.
*
* @param front_domain
* The left part of the concatenation result, or the subdomain part.
*
* @param end_domain
* The right part of the concatenation result, or the parent domain part.
*
* @param out_error
* The pointer to the error value indicates the success of the function call or the error encountered.
*
* @result
* The output domain object after the concatenation, or NULL if error happens.
*/
dns_obj_domain_name_t NULLABLE
dns_obj_domain_name_create_concatenation(dns_obj_domain_name_t NONNULL front_domain,
dns_obj_domain_name_t NONNULL end_domain, dns_obj_error_t * NULLABLE out_error);
/*!
* @brief
* Append the subdomain name label(s) to a domain name object to form a new one.
*
* @param subdomain_in_labels
* The left part of the concatenation result, or the subdomain part.
*
* @param end_domain
* The right part of the concatenation result, or the parent domain part.
*
* @param out_error
* The pointer to the error value indicates the success of the function call or the error encountered.
*
* @result
* The output domain object after the concatenation, or NULL if error happens.
*/
dns_obj_domain_name_t NULLABLE
dns_obj_domain_name_create_concatenation_with_subdomain(const uint8_t * NONNULL subdomain_in_labels,
dns_obj_domain_name_t NONNULL end_domain, dns_obj_error_t * NULLABLE out_error);
/*!
* @brief
* Create the domain name in canonical form based on the labels value of RRSIG record.
*
* @param name
* The domain name object.
*
* @param rrsig_labels
* The "labels" field of RRSIG rdata.
*
* @param out_error
* The pointer to the error value indicates the success of the function call or the error encountered.
*
* @result
* The domain name in canonical form. See <https://datatracker.ietf.org/doc/html/rfc4034#section-6.1> for Canonical DNS Name Order.
*/
dns_obj_domain_name_t NULLABLE
dns_obj_domain_name_create_canonical(dns_obj_domain_name_t NONNULL name, uint8_t rrsig_labels,
dns_obj_error_t * NULLABLE out_error);
/*!
* @brief
* Create the domain name object from NULL-terminated C string.
*
* @param name_cstring
* The domain name in C string format.
*
* @param our_error
* The pointer to the error value indicates the success of the function call or the error encountered.
*
* @result
* The domain name object created, or NULL if error happens (such as malformed C string domain name) during creation. <code>out_error</code> will be
* set to the error encountered if it is not NULL.
*
*/
dns_obj_domain_name_t NULLABLE
dns_obj_domain_name_create_with_cstring(const char * NONNULL name_cstring, dns_obj_error_t * NULLABLE our_error);
/*!
* @brief
* Create a new domain name object from the existing one with newly allocated memory.
*
* @param name
* The domain name object to be copied.
*
* @param out_error
* The pointer to the error value indicates the success of the function call or the error encountered.
*
* @result
* The domain name object copy, or NULL if error happens. <code>out_error</code> will be set to the error encountered if it is not NULL.
*/
dns_obj_domain_name_t NULLABLE
dns_obj_domain_name_create_copy(dns_obj_domain_name_t NONNULL name, dns_obj_error_t * NULLABLE out_error);
/*!
* @brief
* Get the domain name labels from the domain name object.
*
* @param domain_name
* The domain name object.
*
* @result
* The domain name labels passed in when the domain name object is created. If <code>allocate_memory</code> is false, the exact same pointer passed in
* when calling <code>dns_obj_domain_name_create_with_labels()</code> will be returned.
*/
const uint8_t * NONNULL
dns_obj_domain_name_get_labels(dns_obj_domain_name_t NONNULL domain_name);
/*!
* @brief
* Get the number of labels in the domain name from the domain name object.
*
* @param domain_name
* The domain name object.
*
* @result
* The number of labels.
*
* @discussion
* The root label is not counted as a label count. Therefore, this function will return <code>0</code> for the root label.
*/
size_t
dns_obj_domain_name_get_label_count(dns_obj_domain_name_t NONNULL domain_name);
/*!
* @brief
* Get the length of the domain name labels for the domain name object.
*
* @param domain_name
* The domain name object.
*
* @result
* The length of the domain name labels of the domain name object.
*/
size_t
dns_obj_domain_name_get_length(dns_obj_domain_name_t NONNULL domain_name);
/*!
* @brief
* Convert the domain name object to C string name.
*
* @param domain_name
* The domain name object.
*
* @param out_name_cstring
* The output buffer that will be used to store the converted domain name C string. It has to be no less than <code>MAX_ESCAPED_DOMAIN_NAME</code>,
* or the result will be undefined.
*
* @result
* The error value indicates the success of the function call or the error encountered. If the value is <code>DNSSEC_ERROR_NO_ERROR</code>,
* <code>out_name_cstring</code> will be filled with the converted domain name C string.
*
*/
dns_obj_error_t
dns_obj_domain_name_to_cstring(dns_obj_domain_name_t NONNULL domain_name, char out_name_cstring[static MAX_ESCAPED_DOMAIN_NAME]);
/*!
* @brief
* Check if the domain name object is a root domain.
*
* @param domain_name
* The domain name object to check.
*
* @result
* True, if it is root domain, otherwise, false.
*/
bool
dns_obj_domain_name_is_root(dns_obj_domain_name_t NONNULL domain_name);
bool
dns_obj_domain_name_is_single_label(dns_obj_domain_name_t NONNULL domain_name);
/*!
* @brief
* Check if <code>domain_name</code> is a subdomain of <code>parent</code>.
*
* @param domain_name
* The subdomain domain name object to be checked.
*
* @param parent
* The parent domain name object to be checked.
*
* @result
* True if <code>domain_name</code> is a subdomain of <code>parent</code>, false otherwise.
*
* @discussion
* Note that if two domain name object are the same, this function will return <code>false</code>. Since www.apple.com .is not a real subdomain of
* www.apple.com.
*/
bool
dns_obj_domain_name_is_sub_domain_of(dns_obj_domain_name_t NONNULL domain_name, dns_obj_domain_name_t NONNULL parent);
/*!
* @brief
* Copy the parent domain of the domain name object, the level of the parent is specified by <code>index</code>.
*
* @param domain_name
* The domain name object.
*
* @param index
* The level of the parent domain, for example, for domain name labels: www.apple.com.
* index 0 means www.apple.com.
* index 1 means apple.com.
* index 2 means com.
* index 3 means <root>.
* index 4 or more means nothing.
*
* @param out_error
* The pointer to the error value indicates the success of the function call or the error encountered.
*
* @result
* The parent domain name object if index is less than or equal to <code>dns_obj_domain_name_get_label_count(labels)</code>, otherwise, NULL.
*/
dns_obj_domain_name_t NULLABLE
dns_obj_domain_name_copy_parent_domain(dns_obj_domain_name_t NONNULL domain_name, size_t index, dns_obj_error_t * NULLABLE out_error);
/*!
* @brief
* Compute and create a new domain name object that is the closest common ancestor of <code>domain_name</code> and <code>other</code>.
*
* @param domain_name
* The domain name object.
*
* @param other
* The domain name object.
*
* @param out_error
* The pointer to the error value indicates the success of the function call or the error encountered.
*
* @result
* A new domain name object that is the closest common ancestor of the two domain names passed in.
*
* @discussion
* The closest common ancestor of two domain names is the longest name matching of them starting from the root.
*/
dns_obj_domain_name_t NULLABLE
dns_obj_domain_name_copy_closest_common_ancestor(dns_obj_domain_name_t NONNULL domain_name,
dns_obj_domain_name_t NONNULL other, dns_obj_error_t * NONNULL out_error);
/*!
* @brief
* Check if the domain name is a "wildcard domain name".
*
* @param domain_name
* The domain name object to check.
*
* @result
* True, if the domain name is a wildcard domain name, otherwise, false.
*
* @discussion
* For the definition of the "wildcard domain name", see [RFC 4592 2.1.1. Wildcard Domain Name and Asterisk Label](https://datatracker.ietf.org/doc/html/rfc4592#section-2.1.1)
*/
bool
dns_obj_domain_name_is_wildcard_domain_name(dns_obj_domain_name_t NONNULL domain_name);
/*!
* @brief
* Check if the <code>domain_name</code> is a wildcard expansion of wildcard domain name <code>wildcard</code>.
*
* @param domain_name
* The domain name object to be checked.
*
* @param wildcard
* The wildcard domain name to match.
*
* @result
* True, if the <code>domain_name</code> is a wildcard expansion of wildcard domain name <code>wildcard</code>, otherwise, false.
*/
bool
dns_obj_domain_name_is_a_wildcard_expansion(dns_obj_domain_name_t NONNULL domain_name,
dns_obj_domain_name_t NONNULL wildcard);
/*!
* @brief
* Calculate and set the base32 hex encoded hashed domain name, as specified by the parameters provided.
*
* @param domain_name
* The domain name object to calculate the hash.
*
* @param algorithm
* The algorithm that will be used to calculate the hash value.
*
* @param iterations
* The number of additional hash iterations performed when generating the hash.
*
* @param salt
* The salt added to the data to be hashed to make hash output more difficult to guess.
*
* @param salt_length
* The length of the salt.
*
* @param zone_domain
* The zone that generates the hash value. This is required because all NSEC3 record name has the zone domain appended. To be able to compare the
* hashed name with the NSEC3 name, the zone domain has to be specified.
*
* @result
* The error value indicates the success of the function call or the error encountered.
*
* @discussion
* After calling <code>dns_obj_domain_name_set_nsec3_hashed_name_with_params()</code>, if no error occurs, the hashed name can be get by calling
* <code>dns_obj_domain_name_get_nsec3_hashed_name()</code>.
*/
dns_obj_error_t
dns_obj_domain_name_set_nsec3_hashed_name_with_params(dns_obj_domain_name_t NONNULL domain_name, uint8_t algorithm,
uint16_t iterations, const uint8_t * NULLABLE salt, uint8_t salt_length, const uint8_t * NONNULL zone_domain);
/*!
* @brief
* Get the base32 hex encoded hashed domain name object.
*
* @param domain_name
* The domain name object.
*
* @param nsec3
* The NSEC3 resource record that provides the parameters required to calculate the hash.
*
* @result
* The base32 hex encoded hashed domain name object if NONNULL <code>nsec3</code> has been provided when calling this function previously,
* or NULL if <code>dns_obj_domain_name_get_nsec3_hashed_name()</code> has never been called with NONNULL <code>nsec3</code>.
*
* @discussion
* If <code>dns_obj_domain_name_get_nsec3_hashed_name()</code> is called with NONNULL <code>nsec3</code> for the first time, the hash value
* will be computed and the result base32 hex encoded hashed domain name object will be returned.
* Note that the final hashed name is encoded as base32 hex (without padding) to be abled to be compared with other domain name object.
*/
dns_obj_domain_name_t NULLABLE
dns_obj_domain_name_get_nsec3_hashed_name(dns_obj_domain_name_t NONNULL domain_name, dns_obj_rr_nsec3_t NULLABLE nsec3);
/*!
* @brief
* Clear previously calculated hashed domain name that is specified by the NSEC3 resource record object or the parameters, so a new hash value can be
* calculated based on the new NSEC3 record.
*
* @param domain_name
* The domain name object.
*/
void
dns_obj_domain_name_clear_nsec3_hashed_name(dns_obj_domain_name_t NONNULL domain_name);
#endif // DNS_OBJ_DOMAIN_NAME_H