initial commit; version 22.5.12042

This commit is contained in:
2022-12-12 23:28:25 -05:00
commit af1b03d79f
17653 changed files with 22692970 additions and 0 deletions

View File

@ -0,0 +1,297 @@
<?php
/**
* Color.php
*
* PHP version 5
*
* Copyright (c) 2007 Stefan Walk
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* @category Console
* @package Console_Color2
* @author Stefan Walk <et@php.net>
* @license http://www.opensource.org/licenses/mit-license.php MIT License
* @link http://pear.php.net/package/Console_Color2
*/
/**
* A simple class to use ANSI Colorcodes.
*
* Of all the functions, you probably only want to use convert() and escape().
* They are easier to use. However, if you want to access colorcodes more
* directly, look into the other functions.
*
* @category Console
* @package Console_Color
* @author Stefan Walk <et@php.net>
* @license http://www.opensource.org/licenses/mit-license.php MIT License
* @link http://pear.php.net/package/Console_Color
*/
class Console_Color2
{
protected $color_codes;
public function __construct() {
$this->setColorCodes(array(
'color' => array(
'black' => 30,
'red' => 31,
'green' => 32,
'brown' => 33,
'blue' => 34,
'purple' => 35,
'cyan' => 36,
'grey' => 37,
'yellow' => 33
),
'style' => array(
'normal' => 0,
'bold' => 1,
'light' => 1,
'underscore' => 4,
'underline' => 4,
'blink' => 5,
'inverse' => 6,
'hidden' => 8,
'concealed' => 8
),
'background' => array(
'black' => 40,
'red' => 41,
'green' => 42,
'brown' => 43,
'yellow' => 43,
'blue' => 44,
'purple' => 45,
'cyan' => 46,
'grey' => 47
)
)
);
}
public function setColorCodes($color_codes)
{
$this->color_codes = $color_codes;
}
public function getColorCodes()
{
return $this->color_codes;
}
/**
* Returns an ANSI-Controlcode
*
* Takes 1 to 3 Arguments: either 1 to 3 strings containing the name of the
* FG Color, style and BG color, or one array with the indices color, style
* or background.
*
* @param mixed $color Optional.
* Either a string with the name of the foreground
* color, or an array with the indices 'color',
* 'style', 'background' and corresponding names as
* values.
* @param string $style Optional name of the style
* @param string $background Optional name of the background color
*
* @return string
*/
public function color($color = null, $style = null, $background = null) // {{{
{
$colors = $this->getColorCodes();
if (is_array($color)) {
$style = isset($color['style']) ? $color['style'] : null;
$background = isset($color['background']) ? $color['background'] : null;
$color = isset($color['color']) ? $color['color'] : null;
}
if ($color == 'reset') {
return "\033[0m";
}
$code = array();
if (isset($style)) {
$code[] = $colors['style'][$style];
}
if (isset($color)) {
$code[] = $colors['color'][$color];
}
if (isset($background)) {
$code[] = $colors['background'][$background];
}
if (empty($code)) {
$code[] = 0;
}
$code = implode(';', $code);
return "\033[{$code}m";
} // }}}
/**
* Returns a FG color controlcode
*
* @param string $name Name of controlcode
*
* @return string
*/
public function fgcolor($name)
{
$colors = $this->getColorCodes();
return "\033[".$colors['color'][$name].'m';
}
/**
* Returns a style controlcode
*
* @param string $name Name of controlcode
*
* @return string
*/
function bgcolor($name)
{
$colors = $this->getColorCodes();
return "\033[".$colors['background'][$name].'m';
}
/**
* Converts colorcodes in the format %y (for yellow) into ansi-control
* codes. The conversion table is: ('bold' meaning 'light' on some
* terminals). It's almost the same conversion table irssi uses.
* <pre>
* text text background
* ------------------------------------------------
* %k %K %0 black dark grey black
* %r %R %1 red bold red red
* %g %G %2 green bold green green
* %y %Y %3 yellow bold yellow yellow
* %b %B %4 blue bold blue blue
* %m %M %5 magenta bold magenta magenta
* %p %P magenta (think: purple)
* %c %C %6 cyan bold cyan cyan
* %w %W %7 white bold white white
*
* %F Blinking, Flashing
* %U Underline
* %8 Reverse
* %_,%9 Bold
*
* %n Resets the color
* %% A single %
* </pre>
* First param is the string to convert, second is an optional flag if
* colors should be used. It defaults to true, if set to false, the
* colorcodes will just be removed (And %% will be transformed into %)
*
* @param string $string String to convert
* @param bool $colored Should the string be colored?
*
* @return string
*/
public function convert($string, $colored = true)
{
static $conversions = array ( // static so the array doesn't get built
// everytime
// %y - yellow, and so on... {{{
'%y' => array('color' => 'yellow', 'style' => 'normal'),
'%g' => array('color' => 'green', 'style' => 'normal'),
'%b' => array('color' => 'blue', 'style' => 'normal'),
'%r' => array('color' => 'red', 'style' => 'normal'),
'%p' => array('color' => 'purple', 'style' => 'normal'),
'%m' => array('color' => 'purple', 'style' => 'normal'),
'%c' => array('color' => 'cyan', 'style' => 'normal'),
'%w' => array('color' => 'grey', 'style' => 'normal'),
'%k' => array('color' => 'black', 'style' => 'normal'),
'%n' => array('color' => 'reset' ),
'%Y' => array('color' => 'yellow', 'style' => 'light'),
'%G' => array('color' => 'green', 'style' => 'light'),
'%B' => array('color' => 'blue', 'style' => 'light'),
'%R' => array('color' => 'red', 'style' => 'light'),
'%P' => array('color' => 'purple', 'style' => 'light'),
'%M' => array('color' => 'purple', 'style' => 'light'),
'%C' => array('color' => 'cyan', 'style' => 'light'),
'%W' => array('color' => 'grey', 'style' => 'light'),
'%K' => array('color' => 'black', 'style' => 'light'),
'%N' => array('color' => 'reset', 'style' => 'light'),
'%3' => array('background' => 'yellow'),
'%2' => array('background' => 'green' ),
'%4' => array('background' => 'blue' ),
'%1' => array('background' => 'red' ),
'%5' => array('background' => 'purple'),
'%6' => array('background' => 'cyan' ),
'%7' => array('background' => 'grey' ),
'%0' => array('background' => 'black' ),
// Don't use this, I can't stand flashing text
'%F' => array('style' => 'blink'),
'%U' => array('style' => 'underline'),
'%8' => array('style' => 'inverse'),
'%9' => array('style' => 'bold'),
'%_' => array('style' => 'bold')
// }}}
);
if ($colored) {
$string = str_replace('%%', '% ', $string);
foreach ($conversions as $key => $value) {
$string = str_replace($key, $this->color($value),
$string);
}
$string = str_replace('% ', '%', $string);
} else {
$string = preg_replace('/%((%)|.)/', '$2', $string);
}
return $string;
}
/**
* Escapes % so they don't get interpreted as color codes
*
* @param string $string String to escape
*
* @return string
*/
public function escape($string)
{
return str_replace('%', '%%', $string);
}
/**
* Strips ANSI color codes from a string
*
* @param string $string String to strip
*
* @acess public
* @return string
*/
public function strip($string)
{
return preg_replace('/\033\[[\d;]+m/', '', $string);
}
}

481
libs/pear/Crypt/CHAP.php Normal file
View File

@ -0,0 +1,481 @@
<?php
/*
Copyright (c) 2002-2010, Michael Bretterklieber <michael@bretterklieber.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This code cannot simply be copied and put under the GNU Public License or
any other GPL-like (LGPL, GPL2) License.
$Id: CHAP.php 302857 2010-08-28 21:12:59Z mbretter $
*/
require_once 'PEAR.php';
/**
* Classes for generating packets for various CHAP Protocols:
* CHAP-MD5: RFC1994
* MS-CHAPv1: RFC2433
* MS-CHAPv2: RFC2759
*
* @package Crypt_CHAP
* @author Michael Bretterklieber <michael@bretterklieber.com>
* @access public
* @version $Revision: 302857 $
*/
/**
* class Crypt_CHAP
*
* Abstract base class for CHAP
*
* @package Crypt_CHAP
*/
class Crypt_CHAP extends PEAR
{
/**
* Random binary challenge
* @var string
*/
var $challenge = null;
/**
* Binary response
* @var string
*/
var $response = null;
/**
* User password
* @var string
*/
var $password = null;
/**
* Id of the authentication request. Should incremented after every request.
* @var integer
*/
var $chapid = 1;
/**
* Constructor
*
* Generates a random challenge
* @return void
*/
function __construct()
{
//$this->PEAR();
$this->generateChallenge();
}
/**
* Generates a random binary challenge
*
* @param string $varname Name of the property
* @param integer $size Size of the challenge in Bytes
* @return void
*/
function generateChallenge($varname = 'challenge', $size = 8)
{
$this->$varname = '';
for ($i = 0; $i < $size; $i++) {
$this->$varname .= pack('C', 1 + mt_rand() % 255);
}
return $this->$varname;
}
/**
* Generates the response. Overwrite this.
*
* @return void
*/
function challengeResponse()
{
}
}
/**
* class Crypt_CHAP_MD5
*
* Generate CHAP-MD5 Packets
*
* @package Crypt_CHAP
*/
class Crypt_CHAP_MD5 extends Crypt_CHAP
{
/**
* Generates the response.
*
* CHAP-MD5 uses MD5-Hash for generating the response. The Hash consists
* of the chapid, the plaintext password and the challenge.
*
* @return string
*/
function challengeResponse()
{
return pack('H*', md5(pack('C', $this->chapid) . $this->password . $this->challenge));
}
}
/**
* class Crypt_CHAP_MSv1
*
* Generate MS-CHAPv1 Packets. MS-CHAP doesen't use the plaintext password, it uses the
* NT-HASH wich is stored in the SAM-Database or in the smbpasswd, if you are using samba.
* The NT-HASH is MD4(str2unicode(plaintextpass)).
* You need the hash extension for this class.
*
* @package Crypt_CHAP
*/
class Crypt_CHAP_MSv1 extends Crypt_CHAP
{
/**
* Wether using deprecated LM-Responses or not.
* 0 = use LM-Response, 1 = use NT-Response
* @var bool
*/
var $flags = 1;
/**
* Constructor
*
* Loads the hash extension
* @return void
*/
function __construct()
{
//$this->Crypt_CHAP();
$this->loadExtension('hash');
}
/**
* Generates the NT-HASH from the given plaintext password.
*
* @access public
* @return string
*/
function ntPasswordHash($password = null)
{
//if (isset($password)) {
if (!is_null($password)) {
return pack('H*',hash('md4', $this->str2unicode($password)));
} else {
return pack('H*',hash('md4', $this->str2unicode($this->password)));
}
}
/**
* Converts ascii to unicode.
*
* @access public
* @return string
*/
function str2unicode($str)
{
$uni = '';
$str = (string) $str;
for ($i = 0; $i < strlen($str); $i++) {
$a = ord($str[$i]) << 8;
$uni .= sprintf("%X", $a);
}
return pack('H*', $uni);
}
/**
* Generates the NT-Response.
*
* @access public
* @return string
*/
function challengeResponse()
{
return $this->_challengeResponse();
}
/**
* Generates the NT-Response.
*
* @access public
* @return string
*/
function ntChallengeResponse()
{
return $this->_challengeResponse(false);
}
/**
* Generates the LAN-Manager-Response.
*
* @access public
* @return string
*/
function lmChallengeResponse()
{
return $this->_challengeResponse(true);
}
/**
* Generates the response.
*
* Generates the response using DES.
*
* @param bool $lm wether generating LAN-Manager-Response
* @access private
* @return string
*/
function _challengeResponse($lm = false)
{
if ($lm) {
$hash = $this->lmPasswordHash();
} else {
$hash = $this->ntPasswordHash();
}
$hash = str_pad($hash, 21, "\0");
if (!extension_loaded('mcrypt') && extension_loaded('openssl')) {
// added openssl routines for dapphp/radius
$key = $this->_desAddParity(substr($hash, 0, 7));
$resp1 = openssl_encrypt($this->challenge, 'des-ecb', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
$key = $this->_desAddParity(substr($hash, 7, 7));
$resp2 = openssl_encrypt($this->challenge, 'des-ecb', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
$key = $this->_desAddParity(substr($hash, 14, 7));
$resp3 = openssl_encrypt($this->challenge, 'des-ecb', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
} else {
$td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$key = $this->_desAddParity(substr($hash, 0, 7));
mcrypt_generic_init($td, $key, $iv);
$resp1 = mcrypt_generic($td, $this->challenge);
mcrypt_generic_deinit($td);
$key = $this->_desAddParity(substr($hash, 7, 7));
mcrypt_generic_init($td, $key, $iv);
$resp2 = mcrypt_generic($td, $this->challenge);
mcrypt_generic_deinit($td);
$key = $this->_desAddParity(substr($hash, 14, 7));
mcrypt_generic_init($td, $key, $iv);
$resp3 = mcrypt_generic($td, $this->challenge);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
}
return $resp1 . $resp2 . $resp3;
}
/**
* Generates the LAN-Manager-HASH from the given plaintext password.
*
* @access public
* @return string
*/
function lmPasswordHash($password = null)
{
$plain = isset($password) ? $password : $this->password;
$plain = substr(strtoupper($plain), 0, 14);
while (strlen($plain) < 14) {
$plain .= "\0";
}
return $this->_desHash(substr($plain, 0, 7)) . $this->_desHash(substr($plain, 7, 7));
}
/**
* Generates an irreversible HASH.
*
* @access private
* @return string
*/
function _desHash($plain)
{
if (!extension_loaded('mcrypt') && extension_loaded('openssl')) {
// added openssl routines for dapphp/radius
$key = $this->_desAddParity($plain);
$hash = openssl_encrypt('KGS!@#$%', 'des-ecb', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
return $hash;
} else {
$key = $this->_desAddParity($plain);
$td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_ECB, '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$hash = mcrypt_generic($td, 'KGS!@#$%');
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $hash;
}
}
/**
* Adds the parity bit to the given DES key.
*
* @access private
* @param string $key 7-Bytes Key without parity
* @return string
*/
function _desAddParity($key)
{
static $odd_parity = array(
1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254);
$bin = '';
for ($i = 0; $i < strlen($key); $i++) {
$bin .= sprintf('%08s', decbin(ord($key[$i])));
}
$str1 = explode('-', substr(chunk_split($bin, 7, '-'), 0, -1));
$x = '';
foreach($str1 as $s) {
$x .= sprintf('%02s', dechex($odd_parity[bindec($s . '0')]));
}
return pack('H*', $x);
}
/**
* Generates the response-packet.
*
* @param bool $lm wether including LAN-Manager-Response
* @access private
* @return string
*/
function response($lm = false)
{
$ntresp = $this->ntChallengeResponse();
if ($lm) {
$lmresp = $this->lmChallengeResponse();
} else {
$lmresp = str_repeat ("\0", 24);
}
// Response: LM Response, NT Response, flags (0 = use LM Response, 1 = use NT Response)
return $lmresp . $ntresp . pack('C', !$lm);
}
}
/**
* class Crypt_CHAP_MSv2
*
* Generate MS-CHAPv2 Packets. This version of MS-CHAP uses a 16 Bytes authenticator
* challenge and a 16 Bytes peer Challenge. LAN-Manager responses no longer exists
* in this version. The challenge is already a SHA1 challenge hash of both challenges
* and of the username.
*
* @package Crypt_CHAP
*/
class Crypt_CHAP_MSv2 extends Crypt_CHAP_MSv1
{
/**
* The username
* @var string
*/
var $username = null;
/**
* The 16 Bytes random binary peer challenge
* @var string
*/
var $peerChallenge = null;
/**
* The 16 Bytes random binary authenticator challenge
* @var string
*/
var $authChallenge = null;
/**
* Constructor
*
* Generates the 16 Bytes peer and authentication challenge
* @return void
*/
function __construct()
{
//$this->Crypt_CHAP_MSv1();
$this->generateChallenge('peerChallenge', 16);
$this->generateChallenge('authChallenge', 16);
}
/**
* Generates a hash from the NT-HASH.
*
* @access public
* @param string $nthash The NT-HASH
* @return string
*/
function ntPasswordHashHash($nthash)
{
return pack('H*',hash('md4', $nthash));
}
/**
* Generates the challenge hash from the peer and the authenticator challenge and
* the username. SHA1 is used for this, but only the first 8 Bytes are used.
*
* @access public
* @return string
*/
function challengeHash()
{
return substr(pack('H*',hash('sha1', $this->peerChallenge . $this->authChallenge . $this->username)), 0, 8);
}
/**
* Generates the response.
*
* @access public
* @return string
*/
function challengeResponse()
{
$this->challenge = $this->challengeHash();
return $this->_challengeResponse();
}
}

267
libs/pear/Mail/Mail.php Normal file
View File

@ -0,0 +1,267 @@
<?php
/**
* PEAR's Mail:: interface.
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 1997-2017, Chuck Hagenbuch & Richard Heyes
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Mail
* @package Mail
* @author Chuck Hagenbuch <chuck@horde.org>
* @copyright 1997-2017 Chuck Hagenbuch
* @license http://opensource.org/licenses/BSD-3-Clause New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/Mail/
*/
require_once 'PEAR.php';
/**
* PEAR's Mail:: interface. Defines the interface for implementing
* mailers under the PEAR hierarchy, and provides supporting functions
* useful in multiple mailer backends.
*
* @version $Revision$
* @package Mail
*/
class Mail
{
/**
* Line terminator used for separating header lines.
* @var string
*/
public $sep = "\r\n";
/**
* Provides an interface for generating Mail:: objects of various
* types
*
* @param string $driver The kind of Mail:: object to instantiate.
* @param array $params The parameters to pass to the Mail:: object.
*
* @return object Mail a instance of the driver class or if fails a PEAR Error
*/
public static function factory($driver, $params = array())
{
$driver = strtolower($driver);
@include_once 'Mail/' . $driver . '.php';
$class = 'Mail_' . $driver;
if (class_exists($class)) {
$mailer = new $class($params);
return $mailer;
} else {
return PEAR::raiseError('Unable to find class for driver ' . $driver);
}
}
/**
* Implements Mail::send() function using php's built-in mail()
* command.
*
* @param mixed $recipients Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param array $headers The array of headers to send with the mail, in an
* associative array, where the array key is the
* header name (ie, 'Subject'), and the array value
* is the header value (ie, 'test'). The header
* produced from those values would be 'Subject:
* test'.
*
* @param string $body The full text of the message body, including any
* Mime parts, etc.
*
* @return mixed Returns true on success, or a PEAR_Error
* containing a descriptive error message on
* failure.
*
* @deprecated use Mail_mail::send instead
*/
public function send($recipients, $headers, $body)
{
if (!is_array($headers)) {
return PEAR::raiseError('$headers must be an array');
}
$result = $this->_sanitizeHeaders($headers);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
// if we're passed an array of recipients, implode it.
if (is_array($recipients)) {
$recipients = implode(', ', $recipients);
}
// get the Subject out of the headers array so that we can
// pass it as a seperate argument to mail().
$subject = '';
if (isset($headers['Subject'])) {
$subject = $headers['Subject'];
unset($headers['Subject']);
}
// flatten the headers out.
list(, $text_headers) = Mail::prepareHeaders($headers);
return mail($recipients, $subject, $body, $text_headers);
}
/**
* Sanitize an array of mail headers by removing any additional header
* strings present in a legitimate header's value. The goal of this
* filter is to prevent mail injection attacks.
*
* @param array $headers The associative array of headers to sanitize.
*/
protected function _sanitizeHeaders(&$headers)
{
foreach ($headers as $key => $value) {
$headers[$key] =
preg_replace('=((<CR>|<LF>|0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i',
null, $value);
}
}
/**
* Take an array of mail headers and return a string containing
* text usable in sending a message.
*
* @param array $headers The array of headers to prepare, in an associative
* array, where the array key is the header name (ie,
* 'Subject'), and the array value is the header
* value (ie, 'test'). The header produced from those
* values would be 'Subject: test'.
*
* @return mixed Returns false if it encounters a bad address,
* otherwise returns an array containing two
* elements: Any From: address found in the headers,
* and the plain text version of the headers.
*/
protected function prepareHeaders($headers)
{
$lines = array();
$from = null;
foreach ($headers as $key => $value) {
if (strcasecmp($key, 'From') === 0) {
include_once 'Mail/RFC822.php';
$parser = new Mail_RFC822();
$addresses = $parser->parseAddressList($value, 'localhost', false);
if (is_a($addresses, 'PEAR_Error')) {
return $addresses;
}
$from = $addresses[0]->mailbox . '@' . $addresses[0]->host;
// Reject envelope From: addresses with spaces.
if (strstr($from, ' ')) {
return false;
}
$lines[] = $key . ': ' . $value;
} elseif (strcasecmp($key, 'Received') === 0) {
$received = array();
if (is_array($value)) {
foreach ($value as $line) {
$received[] = $key . ': ' . $line;
}
}
else {
$received[] = $key . ': ' . $value;
}
// Put Received: headers at the top. Spam detectors often
// flag messages with Received: headers after the Subject:
// as spam.
$lines = array_merge($received, $lines);
} else {
// If $value is an array (i.e., a list of addresses), convert
// it to a comma-delimited string of its elements (addresses).
if (is_array($value)) {
$value = implode(', ', $value);
}
$lines[] = $key . ': ' . $value;
}
}
return array($from, join($this->sep, $lines));
}
/**
* Take a set of recipients and parse them, returning an array of
* bare addresses (forward paths) that can be passed to sendmail
* or an smtp server with the rcpt to: command.
*
* @param mixed Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid.
*
* @return mixed An array of forward paths (bare addresses) or a PEAR_Error
* object if the address list could not be parsed.
*/
protected function parseRecipients($recipients)
{
include_once 'Mail/RFC822.php';
// if we're passed an array, assume addresses are valid and
// implode them before parsing.
if (is_array($recipients)) {
$recipients = implode(', ', $recipients);
}
// Parse recipients, leaving out all personal info. This is
// for smtp recipients, etc. All relevant personal information
// should already be in the headers.
$Mail_RFC822 = new Mail_RFC822();
$addresses = $Mail_RFC822->parseAddressList($recipients, 'localhost', false);
// If parseAddressList() returned a PEAR_Error object, just return it.
if (is_a($addresses, 'PEAR_Error')) {
return $addresses;
}
$recipients = array();
if (is_array($addresses)) {
foreach ($addresses as $ob) {
$recipients[] = $ob->mailbox . '@' . $ob->host;
}
}
return $recipients;
}
}

View File

@ -0,0 +1,929 @@
<?php
/**
* RFC 822 Email address list validation Utility
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2001-2017, Chuck Hagenbuch & Richard Heyes
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Mail
* @package Mail
* @author Richard Heyes <richard@phpguru.org>
* @author Chuck Hagenbuch <chuck@horde.org
* @copyright 2001-2017 Richard Heyes
* @license http://opensource.org/licenses/BSD-3-Clause New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/Mail/
*/
/**
* RFC 822 Email address list validation Utility
*
* What is it?
*
* This class will take an address string, and parse it into it's consituent
* parts, be that either addresses, groups, or combinations. Nested groups
* are not supported. The structure it returns is pretty straight forward,
* and is similar to that provided by the imap_rfc822_parse_adrlist(). Use
* print_r() to view the structure.
*
* How do I use it?
*
* $address_string = 'My Group: "Richard" <richard@localhost> (A comment), ted@example.com (Ted Bloggs), Barney;';
* $structure = Mail_RFC822::parseAddressList($address_string, 'example.com', true)
* print_r($structure);
*
* @author Richard Heyes <richard@phpguru.org>
* @author Chuck Hagenbuch <chuck@horde.org>
* @version $Revision$
* @license BSD
* @package Mail
*/
class Mail_RFC822 {
/**
* The address being parsed by the RFC822 object.
* @var string $address
*/
var $address = '';
/**
* The default domain to use for unqualified addresses.
* @var string $default_domain
*/
var $default_domain = 'localhost';
/**
* Should we return a nested array showing groups, or flatten everything?
* @var boolean $nestGroups
*/
var $nestGroups = true;
/**
* Whether or not to validate atoms for non-ascii characters.
* @var boolean $validate
*/
var $validate = true;
/**
* The array of raw addresses built up as we parse.
* @var array $addresses
*/
var $addresses = array();
/**
* The final array of parsed address information that we build up.
* @var array $structure
*/
var $structure = array();
/**
* The current error message, if any.
* @var string $error
*/
var $error = null;
/**
* An internal counter/pointer.
* @var integer $index
*/
var $index = null;
/**
* The number of groups that have been found in the address list.
* @var integer $num_groups
* @access public
*/
var $num_groups = 0;
/**
* A variable so that we can tell whether or not we're inside a
* Mail_RFC822 object.
* @var boolean $mailRFC822
*/
var $mailRFC822 = true;
/**
* A limit after which processing stops
* @var int $limit
*/
var $limit = null;
/**
* Sets up the object. The address must either be set here or when
* calling parseAddressList(). One or the other.
*
* @param string $address The address(es) to validate.
* @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost.
* @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
* @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
*
* @return object Mail_RFC822 A new Mail_RFC822 object.
*/
public function __construct($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
{
if (isset($address)) $this->address = $address;
if (isset($default_domain)) $this->default_domain = $default_domain;
if (isset($nest_groups)) $this->nestGroups = $nest_groups;
if (isset($validate)) $this->validate = $validate;
if (isset($limit)) $this->limit = $limit;
}
/**
* Starts the whole process. The address must either be set here
* or when creating the object. One or the other.
*
* @param string $address The address(es) to validate.
* @param string $default_domain Default domain/host etc.
* @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
* @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
*
* @return array A structured array of addresses.
*/
public function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
{
if (!isset($this) || !isset($this->mailRFC822)) {
$obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit);
return $obj->parseAddressList();
}
if (isset($address)) $this->address = $address;
if (isset($default_domain)) $this->default_domain = $default_domain;
if (isset($nest_groups)) $this->nestGroups = $nest_groups;
if (isset($validate)) $this->validate = $validate;
if (isset($limit)) $this->limit = $limit;
$this->structure = array();
$this->addresses = array();
$this->error = null;
$this->index = null;
// Unfold any long lines in $this->address.
$this->address = preg_replace('/\r?\n/', "\r\n", $this->address);
$this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address);
while ($this->address = $this->_splitAddresses($this->address));
if ($this->address === false || isset($this->error)) {
require_once 'PEAR.php';
return PEAR::raiseError($this->error);
}
// Validate each address individually. If we encounter an invalid
// address, stop iterating and return an error immediately.
foreach ($this->addresses as $address) {
$valid = $this->_validateAddress($address);
if ($valid === false || isset($this->error)) {
require_once 'PEAR.php';
return PEAR::raiseError($this->error);
}
if (!$this->nestGroups) {
$this->structure = array_merge($this->structure, $valid);
} else {
$this->structure[] = $valid;
}
}
return $this->structure;
}
/**
* Splits an address into separate addresses.
*
* @param string $address The addresses to split.
* @return boolean Success or failure.
*/
protected function _splitAddresses($address)
{
if (!empty($this->limit) && count($this->addresses) == $this->limit) {
return '';
}
if ($this->_isGroup($address) && !isset($this->error)) {
$split_char = ';';
$is_group = true;
} elseif (!isset($this->error)) {
$split_char = ',';
$is_group = false;
} elseif (isset($this->error)) {
return false;
}
// Split the string based on the above ten or so lines.
$parts = explode($split_char, $address);
$string = $this->_splitCheck($parts, $split_char);
// If a group...
if ($is_group) {
// If $string does not contain a colon outside of
// brackets/quotes etc then something's fubar.
// First check there's a colon at all:
if (strpos($string, ':') === false) {
$this->error = 'Invalid address: ' . $string;
return false;
}
// Now check it's outside of brackets/quotes:
if (!$this->_splitCheck(explode(':', $string), ':')) {
return false;
}
// We must have a group at this point, so increase the counter:
$this->num_groups++;
}
// $string now contains the first full address/group.
// Add to the addresses array.
$this->addresses[] = array(
'address' => trim($string),
'group' => $is_group
);
// Remove the now stored address from the initial line, the +1
// is to account for the explode character.
$address = trim(substr($address, strlen($string) + 1));
// If the next char is a comma and this was a group, then
// there are more addresses, otherwise, if there are any more
// chars, then there is another address.
if ($is_group && substr($address, 0, 1) == ','){
$address = trim(substr($address, 1));
return $address;
} elseif (strlen($address) > 0) {
return $address;
} else {
return '';
}
// If you got here then something's off
return false;
}
/**
* Checks for a group at the start of the string.
*
* @param string $address The address to check.
* @return boolean Whether or not there is a group at the start of the string.
*/
protected function _isGroup($address)
{
// First comma not in quotes, angles or escaped:
$parts = explode(',', $address);
$string = $this->_splitCheck($parts, ',');
// Now we have the first address, we can reliably check for a
// group by searching for a colon that's not escaped or in
// quotes or angle brackets.
if (count($parts = explode(':', $string)) > 1) {
$string2 = $this->_splitCheck($parts, ':');
return ($string2 !== $string);
} else {
return false;
}
}
/**
* A common function that will check an exploded string.
*
* @param array $parts The exloded string.
* @param string $char The char that was exploded on.
* @return mixed False if the string contains unclosed quotes/brackets, or the string on success.
*/
protected function _splitCheck($parts, $char)
{
$string = $parts[0];
for ($i = 0; $i < count($parts); $i++) {
if ($this->_hasUnclosedQuotes($string)
|| $this->_hasUnclosedBrackets($string, '<>')
|| $this->_hasUnclosedBrackets($string, '[]')
|| $this->_hasUnclosedBrackets($string, '()')
|| substr($string, -1) == '\\') {
if (isset($parts[$i + 1])) {
$string = $string . $char . $parts[$i + 1];
} else {
$this->error = 'Invalid address spec. Unclosed bracket or quotes';
return false;
}
} else {
$this->index = $i;
break;
}
}
return $string;
}
/**
* Checks if a string has unclosed quotes or not.
*
* @param string $string The string to check.
* @return boolean True if there are unclosed quotes inside the string,
* false otherwise.
*/
protected function _hasUnclosedQuotes($string)
{
$string = trim($string);
$iMax = strlen($string);
$in_quote = false;
$i = $slashes = 0;
for (; $i < $iMax; ++$i) {
switch ($string[$i]) {
case '\\':
++$slashes;
break;
case '"':
if ($slashes % 2 == 0) {
$in_quote = !$in_quote;
}
// Fall through to default action below.
default:
$slashes = 0;
break;
}
}
return $in_quote;
}
/**
* Checks if a string has an unclosed brackets or not. IMPORTANT:
* This function handles both angle brackets and square brackets;
*
* @param string $string The string to check.
* @param string $chars The characters to check for.
* @return boolean True if there are unclosed brackets inside the string, false otherwise.
*/
protected function _hasUnclosedBrackets($string, $chars)
{
$num_angle_start = substr_count($string, $chars[0]);
$num_angle_end = substr_count($string, $chars[1]);
$this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]);
$this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]);
if ($num_angle_start < $num_angle_end) {
$this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')';
return false;
} else {
return ($num_angle_start > $num_angle_end);
}
}
/**
* Sub function that is used only by hasUnclosedBrackets().
*
* @param string $string The string to check.
* @param integer &$num The number of occurences.
* @param string $char The character to count.
* @return integer The number of occurences of $char in $string, adjusted for backslashes.
*/
protected function _hasUnclosedBracketsSub($string, &$num, $char)
{
$parts = explode($char, $string);
for ($i = 0; $i < count($parts); $i++){
if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i]))
$num--;
if (isset($parts[$i + 1]))
$parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1];
}
return $num;
}
/**
* Function to begin checking the address.
*
* @param string $address The address to validate.
* @return mixed False on failure, or a structured array of address information on success.
*/
protected function _validateAddress($address)
{
$is_group = false;
$addresses = array();
if ($address['group']) {
$is_group = true;
// Get the group part of the name
$parts = explode(':', $address['address']);
$groupname = $this->_splitCheck($parts, ':');
$structure = array();
// And validate the group part of the name.
if (!$this->_validatePhrase($groupname)){
$this->error = 'Group name did not validate.';
return false;
} else {
// Don't include groups if we are not nesting
// them. This avoids returning invalid addresses.
if ($this->nestGroups) {
$structure = new stdClass;
$structure->groupname = $groupname;
}
}
$address['address'] = ltrim(substr($address['address'], strlen($groupname . ':')));
}
// If a group then split on comma and put into an array.
// Otherwise, Just put the whole address in an array.
if ($is_group) {
while (strlen($address['address']) > 0) {
$parts = explode(',', $address['address']);
$addresses[] = $this->_splitCheck($parts, ',');
$address['address'] = trim(substr($address['address'], strlen(end($addresses) . ',')));
}
} else {
$addresses[] = $address['address'];
}
// Trim the whitespace from all of the address strings.
array_map('trim', $addresses);
// Validate each mailbox.
// Format could be one of: name <geezer@domain.com>
// geezer@domain.com
// geezer
// ... or any other format valid by RFC 822.
for ($i = 0; $i < count($addresses); $i++) {
if (!$this->validateMailbox($addresses[$i])) {
if (empty($this->error)) {
$this->error = 'Validation failed for: ' . $addresses[$i];
}
return false;
}
}
// Nested format
if ($this->nestGroups) {
if ($is_group) {
$structure->addresses = $addresses;
} else {
$structure = $addresses[0];
}
// Flat format
} else {
if ($is_group) {
$structure = array_merge($structure, $addresses);
} else {
$structure = $addresses;
}
}
return $structure;
}
/**
* Function to validate a phrase.
*
* @param string $phrase The phrase to check.
* @return boolean Success or failure.
*/
protected function _validatePhrase($phrase)
{
// Splits on one or more Tab or space.
$parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY);
$phrase_parts = array();
while (count($parts) > 0){
$phrase_parts[] = $this->_splitCheck($parts, ' ');
for ($i = 0; $i < $this->index + 1; $i++)
array_shift($parts);
}
foreach ($phrase_parts as $part) {
// If quoted string:
if (substr($part, 0, 1) == '"') {
if (!$this->_validateQuotedString($part)) {
return false;
}
continue;
}
// Otherwise it's an atom:
if (!$this->_validateAtom($part)) return false;
}
return true;
}
/**
* Function to validate an atom which from rfc822 is:
* atom = 1*<any CHAR except specials, SPACE and CTLs>
*
* If validation ($this->validate) has been turned off, then
* validateAtom() doesn't actually check anything. This is so that you
* can split a list of addresses up before encoding personal names
* (umlauts, etc.), for example.
*
* @param string $atom The string to check.
* @return boolean Success or failure.
*/
protected function _validateAtom($atom)
{
if (!$this->validate) {
// Validation has been turned off; assume the atom is okay.
return true;
}
// Check for any char from ASCII 0 - ASCII 127
if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) {
return false;
}
// Check for specials:
if (preg_match('/[][()<>@,;\\:". ]/', $atom)) {
return false;
}
// Check for control characters (ASCII 0-31):
if (preg_match('/[\\x00-\\x1F]+/', $atom)) {
return false;
}
return true;
}
/**
* Function to validate quoted string, which is:
* quoted-string = <"> *(qtext/quoted-pair) <">
*
* @param string $qstring The string to check
* @return boolean Success or failure.
*/
protected function _validateQuotedString($qstring)
{
// Leading and trailing "
$qstring = substr($qstring, 1, -1);
// Perform check, removing quoted characters first.
return !preg_match('/[\x0D\\\\"]/', preg_replace('/\\\\./', '', $qstring));
}
/**
* Function to validate a mailbox, which is:
* mailbox = addr-spec ; simple address
* / phrase route-addr ; name and route-addr
*
* @param string &$mailbox The string to check.
* @return boolean Success or failure.
*/
public function validateMailbox(&$mailbox)
{
// A couple of defaults.
$phrase = '';
$comment = '';
$comments = array();
// Catch any RFC822 comments and store them separately.
$_mailbox = $mailbox;
while (strlen(trim($_mailbox)) > 0) {
$parts = explode('(', $_mailbox);
$before_comment = $this->_splitCheck($parts, '(');
if ($before_comment != $_mailbox) {
// First char should be a (.
$comment = substr(str_replace($before_comment, '', $_mailbox), 1);
$parts = explode(')', $comment);
$comment = $this->_splitCheck($parts, ')');
$comments[] = $comment;
// +2 is for the brackets
$_mailbox = substr($_mailbox, strpos($_mailbox, '('.$comment)+strlen($comment)+2);
} else {
break;
}
}
foreach ($comments as $comment) {
$mailbox = str_replace("($comment)", '', $mailbox);
}
$mailbox = trim($mailbox);
// Check for name + route-addr
if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') {
$parts = explode('<', $mailbox);
$name = $this->_splitCheck($parts, '<');
$phrase = trim($name);
$route_addr = trim(substr($mailbox, strlen($name.'<'), -1));
if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) {
return false;
}
// Only got addr-spec
} else {
// First snip angle brackets if present.
if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') {
$addr_spec = substr($mailbox, 1, -1);
} else {
$addr_spec = $mailbox;
}
if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
return false;
}
}
// Construct the object that will be returned.
$mbox = new stdClass();
// Add the phrase (even if empty) and comments
$mbox->personal = $phrase;
$mbox->comment = isset($comments) ? $comments : array();
if (isset($route_addr)) {
$mbox->mailbox = $route_addr['local_part'];
$mbox->host = $route_addr['domain'];
$route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : '';
} else {
$mbox->mailbox = $addr_spec['local_part'];
$mbox->host = $addr_spec['domain'];
}
$mailbox = $mbox;
return true;
}
/**
* This function validates a route-addr which is:
* route-addr = "<" [route] addr-spec ">"
*
* Angle brackets have already been removed at the point of
* getting to this function.
*
* @param string $route_addr The string to check.
* @return mixed False on failure, or an array containing validated address/route information on success.
*/
protected function _validateRouteAddr($route_addr)
{
// Check for colon.
if (strpos($route_addr, ':') !== false) {
$parts = explode(':', $route_addr);
$route = $this->_splitCheck($parts, ':');
} else {
$route = $route_addr;
}
// If $route is same as $route_addr then the colon was in
// quotes or brackets or, of course, non existent.
if ($route === $route_addr){
unset($route);
$addr_spec = $route_addr;
if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
return false;
}
} else {
// Validate route part.
if (($route = $this->_validateRoute($route)) === false) {
return false;
}
$addr_spec = substr($route_addr, strlen($route . ':'));
// Validate addr-spec part.
if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
return false;
}
}
if (isset($route)) {
$return['adl'] = $route;
} else {
$return['adl'] = '';
}
$return = array_merge($return, $addr_spec);
return $return;
}
/**
* Function to validate a route, which is:
* route = 1#("@" domain) ":"
*
* @param string $route The string to check.
* @return mixed False on failure, or the validated $route on success.
*/
protected function _validateRoute($route)
{
// Split on comma.
$domains = explode(',', trim($route));
foreach ($domains as $domain) {
$domain = str_replace('@', '', trim($domain));
if (!$this->_validateDomain($domain)) return false;
}
return $route;
}
/**
* Function to validate a domain, though this is not quite what
* you expect of a strict internet domain.
*
* domain = sub-domain *("." sub-domain)
*
* @param string $domain The string to check.
* @return mixed False on failure, or the validated domain on success.
*/
protected function _validateDomain($domain)
{
// Note the different use of $subdomains and $sub_domains
$subdomains = explode('.', $domain);
while (count($subdomains) > 0) {
$sub_domains[] = $this->_splitCheck($subdomains, '.');
for ($i = 0; $i < $this->index + 1; $i++)
array_shift($subdomains);
}
foreach ($sub_domains as $sub_domain) {
if (!$this->_validateSubdomain(trim($sub_domain)))
return false;
}
// Managed to get here, so return input.
return $domain;
}
/**
* Function to validate a subdomain:
* subdomain = domain-ref / domain-literal
*
* @param string $subdomain The string to check.
* @return boolean Success or failure.
*/
protected function _validateSubdomain($subdomain)
{
if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){
if (!$this->_validateDliteral($arr[1])) return false;
} else {
if (!$this->_validateAtom($subdomain)) return false;
}
// Got here, so return successful.
return true;
}
/**
* Function to validate a domain literal:
* domain-literal = "[" *(dtext / quoted-pair) "]"
*
* @param string $dliteral The string to check.
* @return boolean Success or failure.
*/
protected function _validateDliteral($dliteral)
{
return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && ((! isset($matches[1])) || $matches[1] != '\\');
}
/**
* Function to validate an addr-spec.
*
* addr-spec = local-part "@" domain
*
* @param string $addr_spec The string to check.
* @return mixed False on failure, or the validated addr-spec on success.
*/
protected function _validateAddrSpec($addr_spec)
{
$addr_spec = trim($addr_spec);
// Split on @ sign if there is one.
if (strpos($addr_spec, '@') !== false) {
$parts = explode('@', $addr_spec);
$local_part = $this->_splitCheck($parts, '@');
$domain = substr($addr_spec, strlen($local_part . '@'));
// No @ sign so assume the default domain.
} else {
$local_part = $addr_spec;
$domain = $this->default_domain;
}
if (($local_part = $this->_validateLocalPart($local_part)) === false) return false;
if (($domain = $this->_validateDomain($domain)) === false) return false;
// Got here so return successful.
return array('local_part' => $local_part, 'domain' => $domain);
}
/**
* Function to validate the local part of an address:
* local-part = word *("." word)
*
* @param string $local_part
* @return mixed False on failure, or the validated local part on success.
*/
protected function _validateLocalPart($local_part)
{
$parts = explode('.', $local_part);
$words = array();
// Split the local_part into words.
while (count($parts) > 0) {
$words[] = $this->_splitCheck($parts, '.');
for ($i = 0; $i < $this->index + 1; $i++) {
array_shift($parts);
}
}
// Validate each word.
foreach ($words as $word) {
// word cannot be empty (#17317)
if ($word === '') {
return false;
}
// If this word contains an unquoted space, it is invalid. (6.2.4)
if (strpos($word, ' ') && $word[0] !== '"')
{
return false;
}
if ($this->_validatePhrase(trim($word)) === false) return false;
}
// Managed to get here, so return the input.
return $local_part;
}
/**
* Returns an approximate count of how many addresses are in the
* given string. This is APPROXIMATE as it only splits based on a
* comma which has no preceding backslash. Could be useful as
* large amounts of addresses will end up producing *large*
* structures when used with parseAddressList().
*
* @param string $data Addresses to count
* @return int Approximate count
*/
public function approximateCount($data)
{
return count(preg_split('/(?<!\\\\),/', $data));
}
/**
* This is a email validating function separate to the rest of the
* class. It simply validates whether an email is of the common
* internet form: <user>@<domain>. This can be sufficient for most
* people. Optional stricter mode can be utilised which restricts
* mailbox characters allowed to alphanumeric, full stop, hyphen
* and underscore.
*
* @param string $data Address to check
* @param boolean $strict Optional stricter mode
* @return mixed False if it fails, an indexed array
* username/domain if it matches
*/
public function isValidInetAddress($data, $strict = false)
{
$regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i';
if (preg_match($regex, trim($data), $matches)) {
return array($matches[1], $matches[2]);
} else {
return false;
}
}
}

View File

@ -0,0 +1,168 @@
<?php
/**
* internal PHP-mail() implementation of the PEAR Mail:: interface.
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2010-2017, Chuck Hagenbuch
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Mail
* @package Mail
* @author Chuck Hagenbuch <chuck@horde.org>
* @copyright 2010-2017 Chuck Hagenbuch
* @license http://opensource.org/licenses/BSD-3-Clause New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/Mail/
*/
/**
* internal PHP-mail() implementation of the PEAR Mail:: interface.
* @package Mail
* @version $Revision$
*/
class Mail_mail extends Mail {
/**
* Any arguments to pass to the mail() function.
* @var string
*/
var $_params = '';
/**
* Constructor.
*
* Instantiates a new Mail_mail:: object based on the parameters
* passed in.
*
* @param array $params Extra arguments for the mail() function.
*/
public function __construct($params = null)
{
// The other mail implementations accept parameters as arrays.
// In the interest of being consistent, explode an array into
// a string of parameter arguments.
if (is_array($params)) {
$this->_params = join(' ', $params);
} else {
$this->_params = $params;
}
/* Because the mail() function may pass headers as command
* line arguments, we can't guarantee the use of the standard
* "\r\n" separator. Instead, we use the system's native line
* separator. */
if (defined('PHP_EOL')) {
$this->sep = PHP_EOL;
} else {
$this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n";
}
}
/**
* Implements Mail_mail::send() function using php's built-in mail()
* command.
*
* @param mixed $recipients Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param array $headers The array of headers to send with the mail, in an
* associative array, where the array key is the
* header name (ie, 'Subject'), and the array value
* is the header value (ie, 'test'). The header
* produced from those values would be 'Subject:
* test'.
*
* @param string $body The full text of the message body, including any
* Mime parts, etc.
*
* @return mixed Returns true on success, or a PEAR_Error
* containing a descriptive error message on
* failure.
*/
public function send($recipients, $headers, $body)
{
if (!is_array($headers)) {
return PEAR::raiseError('$headers must be an array');
}
$result = $this->_sanitizeHeaders($headers);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
// If we're passed an array of recipients, implode it.
if (is_array($recipients)) {
$recipients = implode(', ', $recipients);
}
// Get the Subject out of the headers array so that we can
// pass it as a seperate argument to mail().
$subject = '';
if (isset($headers['Subject'])) {
$subject = $headers['Subject'];
unset($headers['Subject']);
}
// Also remove the To: header. The mail() function will add its own
// To: header based on the contents of $recipients.
unset($headers['To']);
// Flatten the headers out.
$headerElements = $this->prepareHeaders($headers);
if (is_a($headerElements, 'PEAR_Error')) {
return $headerElements;
}
list(, $text_headers) = $headerElements;
// We only use mail()'s optional fifth parameter if the additional
// parameters have been provided and we're not running in safe mode.
if (empty($this->_params)) {
$result = mail($recipients, $subject, $body, $text_headers);
} else {
$result = mail($recipients, $subject, $body, $text_headers,
$this->_params);
}
// If the mail() function returned failure, we need to create a
// PEAR_Error object and return it instead of the boolean result.
if ($result === false) {
$result = PEAR::raiseError('mail() returned failure');
}
return $result;
}
}

View File

@ -0,0 +1,142 @@
<?php
/**
* Mock implementation
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2010-2017, Chuck Hagenbuch
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Mail
* @package Mail
* @author Chuck Hagenbuch <chuck@horde.org>
* @copyright 2010-2017 Chuck Hagenbuch
* @license http://opensource.org/licenses/BSD-3-Clause New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/Mail/
*/
/**
* Mock implementation of the PEAR Mail:: interface for testing.
* @access public
* @package Mail
* @version $Revision$
*/
class Mail_mock extends Mail {
/**
* Array of messages that have been sent with the mock.
*
* @var array
*/
public $sentMessages = array();
/**
* Callback before sending mail.
*
* @var callback
*/
protected $_preSendCallback;
/**
* Callback after sending mai.
*
* @var callback
*/
protected $_postSendCallback;
/**
* Constructor.
*
* Instantiates a new Mail_mock:: object based on the parameters
* passed in. It looks for the following parameters, both optional:
* preSendCallback Called before an email would be sent.
* postSendCallback Called after an email would have been sent.
*
* @param array Hash containing any parameters.
*/
public function __construct($params)
{
if (isset($params['preSendCallback']) &&
is_callable($params['preSendCallback'])) {
$this->_preSendCallback = $params['preSendCallback'];
}
if (isset($params['postSendCallback']) &&
is_callable($params['postSendCallback'])) {
$this->_postSendCallback = $params['postSendCallback'];
}
}
/**
* Implements Mail_mock::send() function. Silently discards all
* mail.
*
* @param mixed $recipients Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param array $headers The array of headers to send with the mail, in an
* associative array, where the array key is the
* header name (ie, 'Subject'), and the array value
* is the header value (ie, 'test'). The header
* produced from those values would be 'Subject:
* test'.
*
* @param string $body The full text of the message body, including any
* Mime parts, etc.
*
* @return mixed Returns true on success, or a PEAR_Error
* containing a descriptive error message on
* failure.
*/
public function send($recipients, $headers, $body)
{
if ($this->_preSendCallback) {
call_user_func_array($this->_preSendCallback,
array(&$this, $recipients, $headers, $body));
}
$entry = array('recipients' => $recipients, 'headers' => $headers, 'body' => $body);
$this->sentMessages[] = $entry;
if ($this->_postSendCallback) {
call_user_func_array($this->_postSendCallback,
array(&$this, $recipients, $headers, $body));
}
return true;
}
}

View File

@ -0,0 +1,85 @@
<?php
/**
* Null implementation of the PEAR Mail interface
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2010-2017, Phil Kernick
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Mail
* @package Mail
* @author Phil Kernick <philk@rotfl.com.au>
* @copyright 2010-2017 Phil Kernick
* @license http://opensource.org/licenses/BSD-3-Clause New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/Mail/
*/
/**
* Null implementation of the PEAR Mail:: interface.
* @access public
* @package Mail
* @version $Revision$
*/
class Mail_null extends Mail {
/**
* Implements Mail_null::send() function. Silently discards all
* mail.
*
* @param mixed $recipients Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param array $headers The array of headers to send with the mail, in an
* associative array, where the array key is the
* header name (ie, 'Subject'), and the array value
* is the header value (ie, 'test'). The header
* produced from those values would be 'Subject:
* test'.
*
* @param string $body The full text of the message body, including any
* Mime parts, etc.
*
* @return mixed Returns true on success, or a PEAR_Error
* containing a descriptive error message on
* failure.
*/
public function send($recipients, $headers, $body)
{
return true;
}
}

View File

@ -0,0 +1,199 @@
<?php
/**
* Sendmail implementation of the PEAR Mail interface.
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2010-2017, Chuck Hagenbuch & Jon Parise
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Mail
* @package Mail
* @author Jon Parise <jon@php.net>
* @author Chuck Hagenbuch <chuck@horde.org>
* @copyright 2010-2017 Chuck Hagenbuch
* @license http://opensource.org/licenses/BSD-3-Clause New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/Mail/
*/
/**
* Sendmail implementation of the PEAR Mail:: interface.
* @access public
* @package Mail
* @version $Revision$
*/
class Mail_sendmail extends Mail {
/**
* The location of the sendmail or sendmail wrapper binary on the
* filesystem.
* @var string
*/
var $sendmail_path = '/usr/sbin/sendmail';
/**
* Any extra command-line parameters to pass to the sendmail or
* sendmail wrapper binary.
* @var string
*/
var $sendmail_args = '-i';
/**
* Constructor.
*
* Instantiates a new Mail_sendmail:: object based on the parameters
* passed in. It looks for the following parameters:
* sendmail_path The location of the sendmail binary on the
* filesystem. Defaults to '/usr/sbin/sendmail'.
*
* sendmail_args Any extra parameters to pass to the sendmail
* or sendmail wrapper binary.
*
* If a parameter is present in the $params array, it replaces the
* default.
*
* @param array $params Hash containing any parameters different from the
* defaults.
*/
public function __construct($params)
{
if (isset($params['sendmail_path'])) {
$this->sendmail_path = $params['sendmail_path'];
}
if (isset($params['sendmail_args'])) {
$this->sendmail_args = $params['sendmail_args'];
}
/*
* Because we need to pass message headers to the sendmail program on
* the commandline, we can't guarantee the use of the standard "\r\n"
* separator. Instead, we use the system's native line separator.
*/
if (defined('PHP_EOL')) {
$this->sep = PHP_EOL;
} else {
$this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n";
}
}
/**
* Implements Mail::send() function using the sendmail
* command-line binary.
*
* @param mixed $recipients Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param array $headers The array of headers to send with the mail, in an
* associative array, where the array key is the
* header name (ie, 'Subject'), and the array value
* is the header value (ie, 'test'). The header
* produced from those values would be 'Subject:
* test'.
*
* @param string $body The full text of the message body, including any
* Mime parts, etc.
*
* @return mixed Returns true on success, or a PEAR_Error
* containing a descriptive error message on
* failure.
*/
public function send($recipients, $headers, $body)
{
if (!is_array($headers)) {
return PEAR::raiseError('$headers must be an array');
}
$result = $this->_sanitizeHeaders($headers);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
$recipients = $this->parseRecipients($recipients);
if (is_a($recipients, 'PEAR_Error')) {
return $recipients;
}
$recipients = implode(' ', array_map('escapeshellarg', $recipients));
$headerElements = $this->prepareHeaders($headers);
if (is_a($headerElements, 'PEAR_Error')) {
return $headerElements;
}
list($from, $text_headers) = $headerElements;
/* Since few MTAs are going to allow this header to be forged
* unless it's in the MAIL FROM: exchange, we'll use
* Return-Path instead of From: if it's set. */
if (!empty($headers['Return-Path'])) {
$from = $headers['Return-Path'];
}
if (!isset($from)) {
return PEAR::raiseError('No from address given.');
} elseif (strpos($from, ' ') !== false ||
strpos($from, ';') !== false ||
strpos($from, '&') !== false ||
strpos($from, '`') !== false) {
return PEAR::raiseError('From address specified with dangerous characters.');
}
$from = escapeshellarg($from); // Security bug #16200
$mail = @popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') . " -f$from -- $recipients", 'w');
if (!$mail) {
return PEAR::raiseError('Failed to open sendmail [' . $this->sendmail_path . '] for execution.');
}
// Write the headers following by two newlines: one to end the headers
// section and a second to separate the headers block from the body.
fputs($mail, $text_headers . $this->sep . $this->sep);
fputs($mail, $body);
$result = pclose($mail);
if (version_compare(phpversion(), '4.2.3') == -1) {
// With older php versions, we need to shift the pclose
// result to get the exit code.
$result = $result >> 8 & 0xFF;
}
if ($result != 0) {
return PEAR::raiseError('sendmail returned error code ' . $result,
$result);
}
return true;
}
}

View File

@ -0,0 +1,461 @@
<?php
/**
* SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class.
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2010-2017, Chuck Hagenbuch & Jon Parise
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category HTTP
* @package HTTP_Request
* @author Jon Parise <jon@php.net>
* @author Chuck Hagenbuch <chuck@horde.org>
* @copyright 2010-2017 Chuck Hagenbuch
* @license http://opensource.org/licenses/BSD-3-Clause New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/Mail/
*/
/** Error: Failed to create a Net_SMTP object */
define('PEAR_MAIL_SMTP_ERROR_CREATE', 10000);
/** Error: Failed to connect to SMTP server */
define('PEAR_MAIL_SMTP_ERROR_CONNECT', 10001);
/** Error: SMTP authentication failure */
define('PEAR_MAIL_SMTP_ERROR_AUTH', 10002);
/** Error: No From: address has been provided */
define('PEAR_MAIL_SMTP_ERROR_FROM', 10003);
/** Error: Failed to set sender */
define('PEAR_MAIL_SMTP_ERROR_SENDER', 10004);
/** Error: Failed to add recipient */
define('PEAR_MAIL_SMTP_ERROR_RECIPIENT', 10005);
/** Error: Failed to send data */
define('PEAR_MAIL_SMTP_ERROR_DATA', 10006);
/**
* SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class.
* @access public
* @package Mail
* @version $Revision$
*/
class Mail_smtp extends Mail {
/**
* SMTP connection object.
*
* @var object
* @access private
*/
var $_smtp = null;
/**
* The list of service extension parameters to pass to the Net_SMTP
* mailFrom() command.
*
* @var array
*/
var $_extparams = array();
/**
* The SMTP host to connect to.
*
* @var string
*/
var $host = 'localhost';
/**
* The port the SMTP server is on.
*
* @var integer
*/
var $port = 25;
/**
* Should SMTP authentication be used?
*
* This value may be set to true, false or the name of a specific
* authentication method.
*
* If the value is set to true, the Net_SMTP package will attempt to use
* the best authentication method advertised by the remote SMTP server.
*
* @var mixed
*/
var $auth = false;
/**
* The username to use if the SMTP server requires authentication.
*
* @var string
*/
var $username = '';
/**
* The password to use if the SMTP server requires authentication.
*
* @var string
*/
var $password = '';
/**
* Hostname or domain that will be sent to the remote SMTP server in the
* HELO / EHLO message.
*
* @var string
*/
var $localhost = 'localhost';
/**
* SMTP connection timeout value. NULL indicates no timeout.
*
* @var integer
*/
var $timeout = null;
/**
* Turn on Net_SMTP debugging?
*
* @var boolean $debug
*/
var $debug = false;
/**
* Indicates whether or not the SMTP connection should persist over
* multiple calls to the send() method.
*
* @var boolean
*/
var $persist = false;
/**
* Use SMTP command pipelining (specified in RFC 2920) if the SMTP server
* supports it. This speeds up delivery over high-latency connections. By
* default, use the default value supplied by Net_SMTP.
*
* @var boolean
*/
var $pipelining;
/**
* The list of socket options
*
* @var array
*/
var $socket_options = array();
/**
* Constructor.
*
* Instantiates a new Mail_smtp:: object based on the parameters
* passed in. It looks for the following parameters:
* host The server to connect to. Defaults to localhost.
* port The port to connect to. Defaults to 25.
* auth SMTP authentication. Defaults to none.
* username The username to use for SMTP auth. No default.
* password The password to use for SMTP auth. No default.
* localhost The local hostname / domain. Defaults to localhost.
* timeout The SMTP connection timeout. Defaults to none.
* verp Whether to use VERP or not. Defaults to false.
* DEPRECATED as of 1.2.0 (use setMailParams()).
* debug Activate SMTP debug mode? Defaults to false.
* persist Should the SMTP connection persist?
* pipelining Use SMTP command pipelining
*
* If a parameter is present in the $params array, it replaces the
* default.
*
* @param array Hash containing any parameters different from the
* defaults.
*/
public function __construct($params)
{
if (isset($params['host'])) $this->host = $params['host'];
if (isset($params['port'])) $this->port = $params['port'];
if (isset($params['auth'])) $this->auth = $params['auth'];
if (isset($params['username'])) $this->username = $params['username'];
if (isset($params['password'])) $this->password = $params['password'];
if (isset($params['localhost'])) $this->localhost = $params['localhost'];
if (isset($params['timeout'])) $this->timeout = $params['timeout'];
if (isset($params['debug'])) $this->debug = (bool)$params['debug'];
if (isset($params['persist'])) $this->persist = (bool)$params['persist'];
if (isset($params['pipelining'])) $this->pipelining = (bool)$params['pipelining'];
if (isset($params['socket_options'])) $this->socket_options = $params['socket_options'];
// Deprecated options
if (isset($params['verp'])) {
$this->addServiceExtensionParameter('XVERP', is_bool($params['verp']) ? null : $params['verp']);
}
}
/**
* Destructor implementation to ensure that we disconnect from any
* potentially-alive persistent SMTP connections.
*/
public function __destruct()
{
$this->disconnect();
}
/**
* Implements Mail::send() function using SMTP.
*
* @param mixed $recipients Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param array $headers The array of headers to send with the mail, in an
* associative array, where the array key is the
* header name (e.g., 'Subject'), and the array value
* is the header value (e.g., 'test'). The header
* produced from those values would be 'Subject:
* test'.
*
* @param string $body The full text of the message body, including any
* MIME parts, etc.
*
* @return mixed Returns true on success, or a PEAR_Error
* containing a descriptive error message on
* failure.
*/
public function send($recipients, $headers, $body)
{
$result = $this->send_or_fail($recipients, $headers, $body);
/* If persistent connections are disabled, destroy our SMTP object. */
if ($this->persist === false) {
$this->disconnect();
}
return $result;
}
protected function send_or_fail($recipients, $headers, $body)
{
/* If we don't already have an SMTP object, create one. */
$result = $this->getSMTPObject();
if (PEAR::isError($result)) {
return $result;
}
if (!is_array($headers)) {
return PEAR::raiseError('$headers must be an array');
}
$this->_sanitizeHeaders($headers);
$headerElements = $this->prepareHeaders($headers);
if (is_a($headerElements, 'PEAR_Error')) {
$this->_smtp->rset();
return $headerElements;
}
list($from, $textHeaders) = $headerElements;
/* Since few MTAs are going to allow this header to be forged
* unless it's in the MAIL FROM: exchange, we'll use
* Return-Path instead of From: if it's set. */
if (!empty($headers['Return-Path'])) {
$from = $headers['Return-Path'];
}
if (!isset($from)) {
$this->_smtp->rset();
return PEAR::raiseError('No From: address has been provided',
PEAR_MAIL_SMTP_ERROR_FROM);
}
$params = null;
if (!empty($this->_extparams)) {
foreach ($this->_extparams as $key => $val) {
$params .= ' ' . $key . (is_null($val) ? '' : '=' . $val);
}
}
if (PEAR::isError($res = $this->_smtp->mailFrom($from, ltrim($params)))) {
$error = $this->_error("Failed to set sender: $from", $res);
$this->_smtp->rset();
return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER);
}
$recipients = $this->parseRecipients($recipients);
if (is_a($recipients, 'PEAR_Error')) {
$this->_smtp->rset();
return $recipients;
}
foreach ($recipients as $recipient) {
$res = $this->_smtp->rcptTo($recipient);
if (is_a($res, 'PEAR_Error')) {
$error = $this->_error("Failed to add recipient: $recipient", $res);
$this->_smtp->rset();
return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT);
}
}
/* Send the message's headers and the body as SMTP data. */
$res = $this->_smtp->data($body, $textHeaders);
list(,$args) = $this->_smtp->getResponse();
if (preg_match("/ queued as (.*)/", $args, $queued)) {
$this->queued_as = $queued[1];
}
/* we need the greeting; from it we can extract the authorative name of the mail server we've really connected to.
* ideal if we're connecting to a round-robin of relay servers and need to track which exact one took the email */
$this->greeting = $this->_smtp->getGreeting();
if (is_a($res, 'PEAR_Error')) {
$error = $this->_error('Failed to send data', $res);
$this->_smtp->rset();
return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA);
}
return true;
}
/**
* Connect to the SMTP server by instantiating a Net_SMTP object.
*
* @return mixed Returns a reference to the Net_SMTP object on success, or
* a PEAR_Error containing a descriptive error message on
* failure.
*
* @since 1.2.0
*/
public function getSMTPObject()
{
if (is_object($this->_smtp) !== false) {
return $this->_smtp;
}
include_once 'Net/SMTP.php';
$this->_smtp = new Net_SMTP($this->host,
$this->port,
$this->localhost,
$this->pipelining,
0,
$this->socket_options);
/* If we still don't have an SMTP object at this point, fail. */
if (is_object($this->_smtp) === false) {
return PEAR::raiseError('Failed to create a Net_SMTP object',
PEAR_MAIL_SMTP_ERROR_CREATE);
}
/* Configure the SMTP connection. */
if ($this->debug) {
$this->_smtp->setDebug(true);
}
/* Attempt to connect to the configured SMTP server. */
if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) {
$error = $this->_error('Failed to connect to ' .
$this->host . ':' . $this->port,
$res);
return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT);
}
/* Attempt to authenticate if authentication has been enabled. */
if ($this->auth) {
$method = is_string($this->auth) ? $this->auth : '';
if (PEAR::isError($res = $this->_smtp->auth($this->username,
$this->password,
$method))) {
$error = $this->_error("$method authentication failure",
$res);
$this->_smtp->rset();
return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH);
}
}
return $this->_smtp;
}
/**
* Add parameter associated with a SMTP service extension.
*
* @param string Extension keyword.
* @param string Any value the keyword needs.
*
* @since 1.2.0
*/
public function addServiceExtensionParameter($keyword, $value = null)
{
$this->_extparams[$keyword] = $value;
}
/**
* Disconnect and destroy the current SMTP connection.
*
* @return boolean True if the SMTP connection no longer exists.
*
* @since 1.1.9
*/
public function disconnect()
{
/* If we have an SMTP object, disconnect and destroy it. */
if (is_object($this->_smtp) && $this->_smtp->disconnect()) {
$this->_smtp = null;
}
/* We are disconnected if we no longer have an SMTP object. */
return ($this->_smtp === null);
}
/**
* Build a standardized string describing the current SMTP error.
*
* @param string $text Custom string describing the error context.
* @param object $error Reference to the current PEAR_Error object.
*
* @return string A string describing the current SMTP error.
*
* @since 1.1.7
*/
protected function _error($text, $error)
{
/* Split the SMTP response into a code and a response string. */
list($code, $response) = $this->_smtp->getResponse();
/* Build our standardized error string. */
return $text
. ' [SMTP: ' . $error->getMessage()
. " (code: $code, response: $response)]";
}
}

View File

@ -0,0 +1,504 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* SMTP MX
*
* SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class.
*
* PHP version 5
*
* LICENSE:
*
* Copyright (c) 2010-2017 gERD Schaufelberger
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Mail
* @package Mail_smtpmx
* @author gERD Schaufelberger <gerd@php-tools.net>
* @copyright 2010-2017 gERD Schaufelberger
* @license http://opensource.org/licenses/BSD-3-Clause New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/Mail/
*/
require_once 'Net/SMTP.php';
/**
* SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class.
*
*
* @access public
* @author gERD Schaufelberger <gerd@php-tools.net>
* @package Mail
* @version $Revision$
*/
class Mail_smtpmx extends Mail {
/**
* SMTP connection object.
*
* @var object
* @access private
*/
var $_smtp = null;
/**
* The port the SMTP server is on.
* @var integer
* @see getservicebyname()
*/
var $port = 25;
/**
* Hostname or domain that will be sent to the remote SMTP server in the
* HELO / EHLO message.
*
* @var string
* @see posix_uname()
*/
var $mailname = 'localhost';
/**
* SMTP connection timeout value. NULL indicates no timeout.
*
* @var integer
*/
var $timeout = 10;
/**
* use either PEAR:Net_DNS or getmxrr
*
* @var boolean
*/
var $withNetDns = true;
/**
* PEAR:Net_DNS_Resolver
*
* @var object
*/
var $resolver;
/**
* Whether to use VERP or not. If not a boolean, the string value
* will be used as the VERP separators.
*
* @var mixed boolean or string
*/
var $verp = false;
/**
* Whether to use VRFY or not.
*
* @var boolean $vrfy
*/
var $vrfy = false;
/**
* Switch to test mode - don't send emails for real
*
* @var boolean $debug
*/
var $test = false;
/**
* Turn on Net_SMTP debugging?
*
* @var boolean $peardebug
*/
var $debug = false;
/**
* internal error codes
*
* translate internal error identifier to PEAR-Error codes and human
* readable messages.
*
* @var boolean $debug
* @todo as I need unique error-codes to identify what exactly went wrond
* I did not use intergers as it should be. Instead I added a "namespace"
* for each code. This avoids conflicts with error codes from different
* classes. How can I use unique error codes and stay conform with PEAR?
*/
var $errorCode = array(
'not_connected' => array(
'code' => 1,
'msg' => 'Could not connect to any mail server ({HOST}) at port {PORT} to send mail to {RCPT}.'
),
'failed_vrfy_rcpt' => array(
'code' => 2,
'msg' => 'Recipient "{RCPT}" could not be veryfied.'
),
'failed_set_from' => array(
'code' => 3,
'msg' => 'Failed to set sender: {FROM}.'
),
'failed_set_rcpt' => array(
'code' => 4,
'msg' => 'Failed to set recipient: {RCPT}.'
),
'failed_send_data' => array(
'code' => 5,
'msg' => 'Failed to send mail to: {RCPT}.'
),
'no_from' => array(
'code' => 5,
'msg' => 'No from address has be provided.'
),
'send_data' => array(
'code' => 7,
'msg' => 'Failed to create Net_SMTP object.'
),
'no_mx' => array(
'code' => 8,
'msg' => 'No MX-record for {RCPT} found.'
),
'no_resolver' => array(
'code' => 9,
'msg' => 'Could not start resolver! Install PEAR:Net_DNS or switch off "netdns"'
),
'failed_rset' => array(
'code' => 10,
'msg' => 'RSET command failed, SMTP-connection corrupt.'
),
);
/**
* Constructor.
*
* Instantiates a new Mail_smtp:: object based on the parameters
* passed in. It looks for the following parameters:
* mailname The name of the local mail system (a valid hostname which matches the reverse lookup)
* port smtp-port - the default comes from getservicebyname() and should work fine
* timeout The SMTP connection timeout. Defaults to 30 seconds.
* vrfy Whether to use VRFY or not. Defaults to false.
* verp Whether to use VERP or not. Defaults to false.
* test Activate test mode? Defaults to false.
* debug Activate SMTP and Net_DNS debug mode? Defaults to false.
* netdns whether to use PEAR:Net_DNS or the PHP build in function getmxrr, default is true
*
* If a parameter is present in the $params array, it replaces the
* default.
*
* @access public
* @param array Hash containing any parameters different from the
* defaults.
* @see _Mail_smtpmx()
*/
function __construct($params)
{
if (isset($params['mailname'])) {
$this->mailname = $params['mailname'];
} else {
// try to find a valid mailname
if (function_exists('posix_uname')) {
$uname = posix_uname();
$this->mailname = $uname['nodename'];
}
}
// port number
if (isset($params['port'])) {
$this->_port = $params['port'];
} else {
$this->_port = getservbyname('smtp', 'tcp');
}
if (isset($params['timeout'])) $this->timeout = $params['timeout'];
if (isset($params['verp'])) $this->verp = $params['verp'];
if (isset($params['test'])) $this->test = $params['test'];
if (isset($params['peardebug'])) $this->test = $params['peardebug'];
if (isset($params['netdns'])) $this->withNetDns = $params['netdns'];
}
/**
* Constructor wrapper for PHP4
*
* @access public
* @param array Hash containing any parameters different from the defaults
* @see __construct()
*/
function Mail_smtpmx($params)
{
$this->__construct($params);
register_shutdown_function(array(&$this, '__destruct'));
}
/**
* Destructor implementation to ensure that we disconnect from any
* potentially-alive persistent SMTP connections.
*/
function __destruct()
{
if (is_object($this->_smtp)) {
$this->_smtp->disconnect();
$this->_smtp = null;
}
}
/**
* Implements Mail::send() function using SMTP direct delivery
*
* @access public
* @param mixed $recipients in RFC822 style or array
* @param array $headers The array of headers to send with the mail.
* @param string $body The full text of the message body,
* @return mixed Returns true on success, or a PEAR_Error
*/
function send($recipients, $headers, $body)
{
if (!is_array($headers)) {
return PEAR::raiseError('$headers must be an array');
}
$result = $this->_sanitizeHeaders($headers);
if (is_a($result, 'PEAR_Error')) {
return $result;
}
// Prepare headers
$headerElements = $this->prepareHeaders($headers);
if (is_a($headerElements, 'PEAR_Error')) {
return $headerElements;
}
list($from, $textHeaders) = $headerElements;
// use 'Return-Path' if possible
if (!empty($headers['Return-Path'])) {
$from = $headers['Return-Path'];
}
if (!isset($from)) {
return $this->_raiseError('no_from');
}
// Prepare recipients
$recipients = $this->parseRecipients($recipients);
if (is_a($recipients, 'PEAR_Error')) {
return $recipients;
}
foreach ($recipients as $rcpt) {
list($user, $host) = explode('@', $rcpt);
$mx = $this->_getMx($host);
if (is_a($mx, 'PEAR_Error')) {
return $mx;
}
if (empty($mx)) {
$info = array('rcpt' => $rcpt);
return $this->_raiseError('no_mx', $info);
}
$connected = false;
foreach ($mx as $mserver => $mpriority) {
$this->_smtp = new Net_SMTP($mserver, $this->port, $this->mailname);
// configure the SMTP connection.
if ($this->debug) {
$this->_smtp->setDebug(true);
}
// attempt to connect to the configured SMTP server.
$res = $this->_smtp->connect($this->timeout);
if (is_a($res, 'PEAR_Error')) {
$this->_smtp = null;
continue;
}
// connection established
if ($res) {
$connected = true;
break;
}
}
if (!$connected) {
$info = array(
'host' => implode(', ', array_keys($mx)),
'port' => $this->port,
'rcpt' => $rcpt,
);
return $this->_raiseError('not_connected', $info);
}
// Verify recipient
if ($this->vrfy) {
$res = $this->_smtp->vrfy($rcpt);
if (is_a($res, 'PEAR_Error')) {
$info = array('rcpt' => $rcpt);
return $this->_raiseError('failed_vrfy_rcpt', $info);
}
}
// mail from:
$args['verp'] = $this->verp;
$res = $this->_smtp->mailFrom($from, $args);
if (is_a($res, 'PEAR_Error')) {
$info = array('from' => $from);
return $this->_raiseError('failed_set_from', $info);
}
// rcpt to:
$res = $this->_smtp->rcptTo($rcpt);
if (is_a($res, 'PEAR_Error')) {
$info = array('rcpt' => $rcpt);
return $this->_raiseError('failed_set_rcpt', $info);
}
// Don't send anything in test mode
if ($this->test) {
$result = $this->_smtp->rset();
$res = $this->_smtp->rset();
if (is_a($res, 'PEAR_Error')) {
return $this->_raiseError('failed_rset');
}
$this->_smtp->disconnect();
$this->_smtp = null;
return true;
}
// Send data
$res = $this->_smtp->data($body, $textHeaders);
if (is_a($res, 'PEAR_Error')) {
$info = array('rcpt' => $rcpt);
return $this->_raiseError('failed_send_data', $info);
}
$this->_smtp->disconnect();
$this->_smtp = null;
}
return true;
}
/**
* Recieve mx rexords for a spciefied host
*
* The MX records
*
* @access private
* @param string $host mail host
* @return mixed sorted
*/
function _getMx($host)
{
$mx = array();
if ($this->withNetDns) {
$res = $this->_loadNetDns();
if (is_a($res, 'PEAR_Error')) {
return $res;
}
$response = $this->resolver->query($host, 'MX');
if (!$response) {
return false;
}
foreach ($response->answer as $rr) {
if ($rr->type == 'MX') {
$mx[$rr->exchange] = $rr->preference;
}
}
} else {
$mxHost = array();
$mxWeight = array();
if (!getmxrr($host, $mxHost, $mxWeight)) {
return false;
}
for ($i = 0; $i < count($mxHost); ++$i) {
$mx[$mxHost[$i]] = $mxWeight[$i];
}
}
asort($mx);
return $mx;
}
/**
* initialize PEAR:Net_DNS_Resolver
*
* @access private
* @return boolean true on success
*/
function _loadNetDns()
{
if (is_object($this->resolver)) {
return true;
}
if (!include_once 'Net/DNS.php') {
return $this->_raiseError('no_resolver');
}
$this->resolver = new Net_DNS_Resolver();
if ($this->debug) {
$this->resolver->test = 1;
}
return true;
}
/**
* raise standardized error
*
* include additional information in error message
*
* @access private
* @param string $id maps error ids to codes and message
* @param array $info optional information in associative array
* @see _errorCode
*/
function _raiseError($id, $info = array())
{
$code = $this->errorCode[$id]['code'];
$msg = $this->errorCode[$id]['msg'];
// include info to messages
if (!empty($info)) {
$search = array();
$replace = array();
foreach ($info as $key => $value) {
array_push($search, '{' . strtoupper($key) . '}');
array_push($replace, $value);
}
$msg = str_replace($search, $replace, $msg);
}
return PEAR::raiseError($msg, $code);
}
}

1590
libs/pear/Mail/mime.php Normal file

File diff suppressed because it is too large Load Diff

1302
libs/pear/Mail/mimePart.php Normal file

File diff suppressed because it is too large Load Diff

1365
libs/pear/Net/DNS2.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,206 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* a class to handle converting RR bitmaps to arrays and back; used on NSEC
* and NSEC3 RR's
*
*/
class Net_DNS2_BitMap
{
/**
* parses a RR bitmap field defined in RFC3845, into an array of RR names.
*
* Type Bit Map(s) Field = ( Window Block # | Bitmap Length | Bitmap ) +
*
* @param string $data a bitmap stringto parse
*
* @return array
* @access public
*
*/
public static function bitMapToArray($data)
{
if (strlen($data) == 0) {
return [];
}
$output = [];
$offset = 0;
$length = strlen($data);
while ($offset < $length) {
//
// unpack the window and length values
//
$x = unpack('@' . $offset . '/Cwindow/Clength', $data);
$offset += 2;
//
// copy out the bitmap value
//
$bitmap = unpack('C*', substr($data, $offset, $x['length']));
$offset += $x['length'];
//
// I'm not sure if there's a better way of doing this, but PHP doesn't
// have a 'B' flag for unpack()
//
$bitstr = '';
foreach ($bitmap as $r) {
$bitstr .= sprintf('%08b', $r);
}
$blen = strlen($bitstr);
for ($i=0; $i<$blen; $i++) {
if ($bitstr[$i] == '1') {
$type = $x['window'] * 256 + $i;
if (isset(Net_DNS2_Lookups::$rr_types_by_id[$type])) {
$output[] = Net_DNS2_Lookups::$rr_types_by_id[$type];
} else {
$output[] = 'TYPE' . $type;
}
}
}
}
return $output;
}
/**
* builds a RR Bit map from an array of RR type names
*
* @param array $data a list of RR names
*
* @return string
* @access public
*
*/
public static function arrayToBitMap(array $data)
{
if (count($data) == 0) {
return '';
}
$current_window = 0;
//
// go through each RR
//
$max = 0;
$bm = [];
foreach ($data as $rr) {
$rr = strtoupper($rr);
//
// get the type id for the RR
//
$type = @Net_DNS2_Lookups::$rr_types_by_name[$rr];
if (isset($type)) {
//
// skip meta types or qtypes
//
if ( (isset(Net_DNS2_Lookups::$rr_qtypes_by_id[$type]))
|| (isset(Net_DNS2_Lookups::$rr_metatypes_by_id[$type]))
) {
continue;
}
} else {
//
// if it's not found, then it must be defined as TYPE<id>, per
// RFC3845 section 2.2, if it's not, we ignore it.
//
list($name, $type) = explode('TYPE', $rr);
if (!isset($type)) {
continue;
}
}
//
// build the current window
//
$current_window = (int)($type / 256);
$val = $type - $current_window * 256.0;
if ($val > $max) {
$max = $val;
}
$bm[$current_window][$val] = 1;
$bm[$current_window]['length'] = ceil(($max + 1) / 8);
}
$output = '';
foreach ($bm as $window => $bitdata) {
$bitstr = '';
for ($i=0; $i<$bm[$window]['length'] * 8; $i++) {
if (isset($bm[$window][$i])) {
$bitstr .= '1';
} else {
$bitstr .= '0';
}
}
$output .= pack('CC', $window, $bm[$window]['length']);
$output .= pack('H*', self::bigBaseConvert($bitstr));
}
return $output;
}
/**
* a base_convert that handles large numbers; forced to 2/16
*
* @param string $number a bit string
*
* @return string
* @access public
*
*/
public static function bigBaseConvert($number)
{
$result = '';
$bin = substr(chunk_split(strrev($number), 4, '-'), 0, -1);
$temp = preg_split('[-]', $bin, -1, PREG_SPLIT_DELIM_CAPTURE);
for ($i = count($temp)-1;$i >= 0;$i--) {
$result = $result . base_convert(strrev($temp[$i]), 2, 16);
}
return strtoupper($result);
}
}

View File

@ -0,0 +1,263 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.1.0
*
*/
/**
* A class to provide simple dns lookup caching.
*
*/
class Net_DNS2_Cache
{
/*
* the filename of the cache file
*/
protected $cache_file = '';
/*
* the local data store for the cache
*/
protected $cache_data = [];
/*
* the size of the cache to use
*/
protected $cache_size = 0;
/*
* the cache serializer
*/
protected $cache_serializer;
/*
* an internal flag to make sure we don't load the cache content more
* than once per instance.
*/
protected $cache_opened = false;
/**
* returns true/false if the provided key is defined in the cache
*
* @param string $key the key to lookup in the local cache
*
* @return boolean
* @access public
*
*/
public function has($key)
{
return isset($this->cache_data[$key]);
}
/**
* returns the value for the given key
*
* @param string $key the key to lookup in the local cache
*
* @return mixed returns the cache data on sucess, false on error
* @access public
*
*/
public function get($key)
{
if (isset($this->cache_data[$key])) {
if ($this->cache_serializer == 'json') {
return json_decode($this->cache_data[$key]['object']);
} else {
return unserialize($this->cache_data[$key]['object']);
}
} else {
return false;
}
}
/**
* adds a new key/value pair to the cache
*
* @param string $key the key for the new cache entry
* @param mixed $data the data to store in cache
*
* @return void
* @access public
*
*/
public function put($key, $data)
{
$ttl = 86400 * 365;
//
// clear the rdata values
//
$data->rdata = '';
$data->rdlength = 0;
//
// find the lowest TTL, and use that as the TTL for the whole cached
// object. The downside to using one TTL for the whole object, is that
// we'll invalidate entries before they actuall expire, causing a
// real lookup to happen.
//
// The upside is that we don't need to require() each RR type in the
// cache, so we can look at their individual TTL's on each run- we only
// unserialize the actual RR object when it's get() from the cache.
//
foreach ($data->answer as $index => $rr) {
if ($rr->ttl < $ttl) {
$ttl = $rr->ttl;
}
$rr->rdata = '';
$rr->rdlength = 0;
}
foreach ($data->authority as $index => $rr) {
if ($rr->ttl < $ttl) {
$ttl = $rr->ttl;
}
$rr->rdata = '';
$rr->rdlength = 0;
}
foreach ($data->additional as $index => $rr) {
if ($rr->ttl < $ttl) {
$ttl = $rr->ttl;
}
$rr->rdata = '';
$rr->rdlength = 0;
}
$this->cache_data[$key] = [
'cache_date' => time(),
'ttl' => $ttl
];
if ($this->cache_serializer == 'json') {
$this->cache_data[$key]['object'] = json_encode($data);
} else {
$this->cache_data[$key]['object'] = serialize($data);
}
}
/**
* runs a clean up process on the cache data
*
* @return void
* @access protected
*
*/
protected function clean()
{
if (count($this->cache_data) > 0) {
//
// go through each entry and adjust their TTL, and remove entries that
// have expired
//
$now = time();
foreach ($this->cache_data as $key => $data) {
$diff = $now - $data['cache_date'];
if ($data['ttl'] <= $diff) {
unset($this->cache_data[$key]);
} else {
$this->cache_data[$key]['ttl'] -= $diff;
$this->cache_data[$key]['cache_date'] = $now;
}
}
}
}
/**
* runs a clean up process on the cache data
*
* @return mixed
* @access protected
*
*/
protected function resize()
{
if (count($this->cache_data) > 0) {
//
// serialize the cache data
//
if ($this->cache_serializer == 'json') {
$cache = json_encode($this->cache_data);
} else {
$cache = serialize($this->cache_data);
}
//
// only do this part if the size allocated to the cache storage
// is smaller than the actual cache data
//
if (strlen($cache) > $this->cache_size) {
while (strlen($cache) > $this->cache_size) {
//
// go through the data, and remove the entries closed to
// their expiration date.
//
$smallest_ttl = time();
$smallest_key = null;
foreach ($this->cache_data as $key => $data) {
if ($data['ttl'] < $smallest_ttl) {
$smallest_ttl = $data['ttl'];
$smallest_key = $key;
}
}
//
// unset the key with the smallest TTL
//
unset($this->cache_data[$smallest_key]);
//
// re-serialize
//
if ($this->cache_serializer == 'json') {
$cache = json_encode($this->cache_data);
} else {
$cache = serialize($this->cache_data);
}
}
}
if ( ($cache == 'a:0:{}') || ($cache == '{}') ) {
return null;
} else {
return $cache;
}
}
return null;
}
}

View File

@ -0,0 +1,199 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.1.0
*
*/
/**
* File-based caching for the Net_DNS2_Cache class
*
*/
class Net_DNS2_Cache_File extends Net_DNS2_Cache
{
/**
* open a cache object
*
* @param string $cache_file path to a file to use for cache storage
* @param integer $size the size of the shared memory segment to create
* @param string $serializer the name of the cache serialize to use
*
* @throws Net_DNS2_Exception
* @access public
* @return void
*
*/
public function open($cache_file, $size, $serializer)
{
$this->cache_size = $size;
$this->cache_file = $cache_file;
$this->cache_serializer = $serializer;
//
// check that the file exists first
//
if ( ($this->cache_opened == false)
&& (file_exists($this->cache_file) == true)
&& (filesize($this->cache_file) > 0)
) {
//
// open the file for reading
//
$fp = @fopen($this->cache_file, 'r');
if ($fp !== false) {
//
// lock the file just in case
//
flock($fp, LOCK_EX);
//
// read the file contents
//
$data = fread($fp, filesize($this->cache_file));
$decoded = null;
if ($this->cache_serializer == 'json') {
$decoded = json_decode($data, true);
} else {
$decoded = unserialize($data);
}
if (is_array($decoded) == true) {
$this->cache_data = $decoded;
} else {
$this->cache_data = [];
}
//
// unlock
//
flock($fp, LOCK_UN);
//
// close the file
//
fclose($fp);
//
// clean up the data
//
$this->clean();
//
// mark this so we don't read this contents more than once per instance.
//
$this->cache_opened = true;
}
}
}
/**
* Destructor
*
* @access public
*
*/
public function __destruct()
{
//
// if there's no cache file set, then there's nothing to do
//
if (strlen($this->cache_file) == 0) {
return;
}
//
// open the file for reading/writing
//
$fp = fopen($this->cache_file, 'a+');
if ($fp !== false) {
//
// lock the file just in case
//
flock($fp, LOCK_EX);
//
// seek to the start of the file to read
//
fseek($fp, 0, SEEK_SET);
//
// read the file contents
//
$data = @fread($fp, filesize($this->cache_file));
if ( ($data !== false) && (strlen($data) > 0) ) {
//
// unserialize and store the data
//
$c = $this->cache_data;
$decoded = null;
if ($this->cache_serializer == 'json') {
$decoded = json_decode($data, true);
} else {
$decoded = unserialize($data);
}
if (is_array($decoded) == true) {
$this->cache_data = array_merge($c, $decoded);
}
}
//
// trucate the file
//
ftruncate($fp, 0);
//
// clean the data
//
$this->clean();
//
// resize the data
//
$data = $this->resize();
if (!is_null($data)) {
//
// write the file contents
//
fwrite($fp, $data);
}
//
// unlock
//
flock($fp, LOCK_UN);
//
// close the file
//
fclose($fp);
}
}
}

View File

@ -0,0 +1,270 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.1.0
*
*/
/**
* Shared Memory-based caching for the Net_DNS2_Cache class
*
*/
class Net_DNS2_Cache_Shm extends Net_DNS2_Cache
{
/*
* resource id of the shared memory cache
*/
private $_cache_id = false;
/*
* the IPC key
*/
private $_cache_file_tok = -1;
/**
* open a cache object
*
* @param string $cache_file path to a file to use for cache storage
* @param integer $size the size of the shared memory segment to create
* @param string $serializer the name of the cache serialize to use
*
* @throws Net_DNS2_Exception
* @access public
* @return void
*
*/
public function open($cache_file, $size, $serializer)
{
$this->cache_size = $size;
$this->cache_file = $cache_file;
$this->cache_serializer = $serializer;
//
// if we've already loaded the cache data, then just return right away
//
if ($this->cache_opened == true)
{
return;
}
//
// make sure the file exists first
//
if (!file_exists($cache_file)) {
if (file_put_contents($cache_file, '') === false) {
throw new Net_DNS2_Exception(
'failed to create empty SHM file: ' . $cache_file,
Net_DNS2_Lookups::E_CACHE_SHM_FILE
);
}
}
//
// convert the filename to a IPC key
//
$this->_cache_file_tok = ftok($cache_file, 't');
if ($this->_cache_file_tok == -1) {
throw new Net_DNS2_Exception(
'failed on ftok() file: ' . $this->_cache_file_tok,
Net_DNS2_Lookups::E_CACHE_SHM_FILE
);
}
//
// try to open an existing cache; if it doesn't exist, then there's no
// cache, and nothing to do.
//
$this->_cache_id = @shmop_open($this->_cache_file_tok, 'w', 0, 0);
if ($this->_cache_id !== false) {
//
// this returns the size allocated, and not the size used, but it's
// still a good check to make sure there's space allocated.
//
$allocated = shmop_size($this->_cache_id);
if ($allocated > 0) {
//
// read the data from the shared memory segment
//
$data = trim(shmop_read($this->_cache_id, 0, $allocated));
if ( ($data !== false) && (strlen($data) > 0) ) {
//
// unserialize and store the data
//
$decoded = null;
if ($this->cache_serializer == 'json') {
$decoded = json_decode($data, true);
} else {
$decoded = unserialize($data);
}
if (is_array($decoded) == true) {
$this->cache_data = $decoded;
} else {
$this->cache_data = [];
}
//
// call clean to clean up old entries
//
$this->clean();
//
// mark the cache as loaded, so we don't load it more than once
//
$this->cache_opened = true;
}
}
}
}
/**
* Destructor
*
* @access public
*
*/
public function __destruct()
{
//
// if there's no cache file set, then there's nothing to do
//
if (strlen($this->cache_file) == 0) {
return;
}
$fp = fopen($this->cache_file, 'r');
if ($fp !== false) {
//
// lock the file
//
flock($fp, LOCK_EX);
//
// check to see if we have an open shm segment
//
if ($this->_cache_id === false) {
//
// try opening it again, incase it was created by another
// process in the mean time
//
$this->_cache_id = @shmop_open(
$this->_cache_file_tok, 'w', 0, 0
);
if ($this->_cache_id === false) {
//
// otherwise, create it.
//
$this->_cache_id = @shmop_open(
$this->_cache_file_tok, 'c', 0, $this->cache_size
);
}
}
//
// get the size allocated to the segment
//
$allocated = shmop_size($this->_cache_id);
//
// read the contents
//
$data = trim(shmop_read($this->_cache_id, 0, $allocated));
//
// if there was some data
//
if ( ($data !== false) && (strlen($data) > 0) ) {
//
// unserialize and store the data
//
$c = $this->cache_data;
$decoded = null;
if ($this->cache_serializer == 'json') {
$decoded = json_decode($data, true);
} else {
$decoded = unserialize($data);
}
if (is_array($decoded) == true) {
$this->cache_data = array_merge($c, $decoded);
}
}
//
// delete the segment
//
shmop_delete($this->_cache_id);
//
// clean the data
//
$this->clean();
//
// clean up and write the data
//
$data = $this->resize();
if (!is_null($data)) {
//
// re-create segment
//
$this->_cache_id = @shmop_open(
$this->_cache_file_tok, 'c', 0644, $this->cache_size
);
if ($this->_cache_id === false) {
return;
}
$o = shmop_write($this->_cache_id, $data, 0);
}
//
// close the segment
//
shmop_close($this->_cache_id);
//
// unlock
//
flock($fp, LOCK_UN);
//
// close the file
//
fclose($fp);
}
}
}

View File

@ -0,0 +1,96 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* Exception handler used by Net_DNS2
*
*/
class Net_DNS2_Exception extends Exception
{
private $_request;
private $_response;
/**
* Constructor - overload the constructor so we can pass in the request
* and response object (when it's available)
*
* @param string $message the exception message
* @param int $code the exception code
* @param object $previous the previous Exception object
* @param object $request the Net_DNS2_Packet_Request object for this request
* @param object $response the Net_DNS2_Packet_Response object for this request
*
* @access public
*
*/
public function __construct(
$message = '',
$code = 0,
$previous = null,
Net_DNS2_Packet_Request $request = null,
Net_DNS2_Packet_Response $response = null
) {
//
// store the request/response objects (if passed)
//
$this->_request = $request;
$this->_response = $response;
//
// call the parent constructor
//
// the "previous" argument was added in PHP 5.3.0
//
// https://code.google.com/p/netdns2/issues/detail?id=25
//
if (version_compare(PHP_VERSION, '5.3.0', '>=') == true) {
parent::__construct($message, $code, $previous);
} else {
parent::__construct($message, $code);
}
}
/**
* returns the Net_DNS2_Packet_Request object (if available)
*
* @return Net_DNS2_Packet_Request object
* @access public
* @since function available since release 1.3.1
*
*/
public function getRequest()
{
return $this->_request;
}
/**
* returns the Net_DNS2_Packet_Response object (if available)
*
* @return Net_DNS2_Packet_Response object
* @access public
* @since function available since release 1.3.1
*
*/
public function getResponse()
{
return $this->_response;
}
}

View File

@ -0,0 +1,229 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* DNS Packet Header class
*
* This class handles parsing and constructing DNS Packet Headers as defined
* by section 4.1.1 of RFC1035.
*
* DNS header format - RFC1035 section 4.1.1
* DNS header format - RFC4035 section 3.2
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | ID |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | QDCOUNT |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | ANCOUNT |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | NSCOUNT |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | ARCOUNT |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_Header
{
public $id; // 16 bit - identifier
public $qr; // 1 bit - 0 = query, 1 = response
public $opcode; // 4 bit - op code
public $aa; // 1 bit - Authoritative Answer
public $tc; // 1 bit - TrunCation
public $rd; // 1 bit - Recursion Desired
public $ra; // 1 bit - Recursion Available
public $z; // 1 bit - Reserved
public $ad; // 1 bit - Authentic Data (RFC4035)
public $cd; // 1 bit - Checking Disabled (RFC4035)
public $rcode; // 4 bit - Response code
public $qdcount; // 16 bit - entries in the question section
public $ancount; // 16 bit - resource records in the answer section
public $nscount; // 16 bit - name server rr in the authority records section
public $arcount; // 16 bit - rr's in the additional records section
/**
* Constructor - builds a new Net_DNS2_Header object
*
* @param mixed &$packet either a Net_DNS2_Packet object or null
*
* @throws Net_DNS2_Exception
* @access public
*
*/
public function __construct(Net_DNS2_Packet &$packet = null)
{
if (!is_null($packet)) {
$this->set($packet);
} else {
$this->id = $this->nextPacketId();
$this->qr = Net_DNS2_Lookups::QR_QUERY;
$this->opcode = Net_DNS2_Lookups::OPCODE_QUERY;
$this->aa = 0;
$this->tc = 0;
$this->rd = 1;
$this->ra = 0;
$this->z = 0;
$this->ad = 0;
$this->cd = 0;
$this->rcode = Net_DNS2_Lookups::RCODE_NOERROR;
$this->qdcount = 1;
$this->ancount = 0;
$this->nscount = 0;
$this->arcount = 0;
}
}
/**
* returns the next available packet id
*
* @return integer
* @access public
*
*/
public function nextPacketId()
{
if (++Net_DNS2_Lookups::$next_packet_id > 65535) {
Net_DNS2_Lookups::$next_packet_id = 1;
}
return Net_DNS2_Lookups::$next_packet_id;
}
/**
* magic __toString() method to return the header as a string
*
* @return string
* @access public
*
*/
public function __toString()
{
$output = ";;\n;; Header:\n";
$output .= ";;\t id = " . $this->id . "\n";
$output .= ";;\t qr = " . $this->qr . "\n";
$output .= ";;\t opcode = " . $this->opcode . "\n";
$output .= ";;\t aa = " . $this->aa . "\n";
$output .= ";;\t tc = " . $this->tc . "\n";
$output .= ";;\t rd = " . $this->rd . "\n";
$output .= ";;\t ra = " . $this->ra . "\n";
$output .= ";;\t z = " . $this->z . "\n";
$output .= ";;\t ad = " . $this->ad . "\n";
$output .= ";;\t cd = " . $this->cd . "\n";
$output .= ";;\t rcode = " . $this->rcode . "\n";
$output .= ";;\t qdcount = " . $this->qdcount . "\n";
$output .= ";;\t ancount = " . $this->ancount . "\n";
$output .= ";;\t nscount = " . $this->nscount . "\n";
$output .= ";;\t arcount = " . $this->arcount . "\n";
return $output;
}
/**
* constructs a Net_DNS2_Header from a Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet Object
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function set(Net_DNS2_Packet &$packet)
{
//
// the header must be at least 12 bytes long.
//
if ($packet->rdlength < Net_DNS2_Lookups::DNS_HEADER_SIZE) {
throw new Net_DNS2_Exception(
'invalid header data provided; too small',
Net_DNS2_Lookups::E_HEADER_INVALID
);
}
$offset = 0;
//
// parse the values
//
$this->id = ord($packet->rdata[$offset]) << 8 |
ord($packet->rdata[++$offset]);
++$offset;
$this->qr = (ord($packet->rdata[$offset]) >> 7) & 0x1;
$this->opcode = (ord($packet->rdata[$offset]) >> 3) & 0xf;
$this->aa = (ord($packet->rdata[$offset]) >> 2) & 0x1;
$this->tc = (ord($packet->rdata[$offset]) >> 1) & 0x1;
$this->rd = ord($packet->rdata[$offset]) & 0x1;
++$offset;
$this->ra = (ord($packet->rdata[$offset]) >> 7) & 0x1;
$this->z = (ord($packet->rdata[$offset]) >> 6) & 0x1;
$this->ad = (ord($packet->rdata[$offset]) >> 5) & 0x1;
$this->cd = (ord($packet->rdata[$offset]) >> 4) & 0x1;
$this->rcode = ord($packet->rdata[$offset]) & 0xf;
$this->qdcount = ord($packet->rdata[++$offset]) << 8 |
ord($packet->rdata[++$offset]);
$this->ancount = ord($packet->rdata[++$offset]) << 8 |
ord($packet->rdata[++$offset]);
$this->nscount = ord($packet->rdata[++$offset]) << 8 |
ord($packet->rdata[++$offset]);
$this->arcount = ord($packet->rdata[++$offset]) << 8 |
ord($packet->rdata[++$offset]);
//
// increment the internal offset
//
$packet->offset += Net_DNS2_Lookups::DNS_HEADER_SIZE;
return true;
}
/**
* returns a binary packed DNS Header
*
* @param Net_DNS2_Packet &$packet Object
*
* @return string
* @access public
*
*/
public function get(Net_DNS2_Packet &$packet)
{
$packet->offset += Net_DNS2_Lookups::DNS_HEADER_SIZE;
return pack('n', $this->id) .
chr(
($this->qr << 7) | ($this->opcode << 3) |
($this->aa << 2) | ($this->tc << 1) | ($this->rd)
) .
chr(
($this->ra << 7) | ($this->ad << 5) | ($this->cd << 4) | $this->rcode
) .
pack('n4', $this->qdcount, $this->ancount, $this->nscount, $this->arcount);
}
}

View File

@ -0,0 +1,33 @@
Net_DNS2 - DNS Library for handling lookups and updates.
Copyright (c) 2010-2020, Mike Pultz <mike@mikepultz.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Mike Pultz nor the names of his contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,561 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
//
// initalize the packet id value
//
Net_DNS2_Lookups::$next_packet_id = mt_rand(0, 65535);
//
// build the reverse lookup tables; this is just so we don't have to
// have duplicate static content laying around.
//
Net_DNS2_Lookups::$rr_types_by_id = array_flip(Net_DNS2_Lookups::$rr_types_by_name);
Net_DNS2_Lookups::$classes_by_id = array_flip(Net_DNS2_Lookups::$classes_by_name);
Net_DNS2_Lookups::$rr_types_class_to_id = array_flip(Net_DNS2_Lookups::$rr_types_id_to_class);
Net_DNS2_Lookups::$algorithm_name_to_id = array_flip(Net_DNS2_Lookups::$algorithm_id_to_name);
Net_DNS2_Lookups::$digest_name_to_id = array_flip(Net_DNS2_Lookups::$digest_id_to_name);
Net_DNS2_Lookups::$rr_qtypes_by_id = array_flip(Net_DNS2_Lookups::$rr_qtypes_by_name);
Net_DNS2_Lookups::$rr_metatypes_by_id = array_flip(Net_DNS2_Lookups::$rr_metatypes_by_name);
Net_DNS2_Lookups::$protocol_by_id = array_flip(Net_DNS2_Lookups::$protocol_by_name);
/**
* This class provides simple lookups used througout the Net_DNS2 code
*
*/
class Net_DNS2_Lookups
{
/*
* size (in bytes) of a header in a standard DNS packet
*/
const DNS_HEADER_SIZE = 12;
/*
* max size of a UDP packet
*/
const DNS_MAX_UDP_SIZE = 512;
/*
* Query/Response flag
*/
const QR_QUERY = 0; // RFC 1035
const QR_RESPONSE = 1; // RFC 1035
/*
* DNS Op Codes
*/
const OPCODE_QUERY = 0; // RFC 1035
const OPCODE_IQUERY = 1; // RFC 1035, RFC 3425
const OPCODE_STATUS = 2; // RFC 1035
const OPCODE_NOTIFY = 4; // RFC 1996
const OPCODE_UPDATE = 5; // RFC 2136
const OPCODE_DSO = 6; // RFC 8490
/*
* Resource Record Classes
*/
const RR_CLASS_IN = 1; // RFC 1035
const RR_CLASS_CH = 3; // RFC 1035
const RR_CLASS_HS = 4; // RFC 1035
const RR_CLASS_NONE = 254; // RFC 2136
const RR_CLASS_ANY = 255; // RFC 1035
/*
* DNS Response Codes
*/
const RCODE_NOERROR = 0; // RFC 1035
const RCODE_FORMERR = 1; // RFC 1035
const RCODE_SERVFAIL = 2; // RFC 1035
const RCODE_NXDOMAIN = 3; // RFC 1035
const RCODE_NOTIMP = 4; // RFC 1035
const RCODE_REFUSED = 5; // RFC 1035
const RCODE_YXDOMAIN = 6; // RFC 2136
const RCODE_YXRRSET = 7; // RFC 2136
const RCODE_NXRRSET = 8; // RFC 2136
const RCODE_NOTAUTH = 9; // RFC 2136
const RCODE_NOTZONE = 10; // RFC 2136
const RCODE_DSOTYPENI = 11; // RFC 8490
// 12-15 reserved
const RCODE_BADSIG = 16; // RFC 2845
const RCODE_BADVERS = 16; // RFC 6891
const RCODE_BADKEY = 17; // RFC 2845
const RCODE_BADTIME = 18; // RFC 2845
const RCODE_BADMODE = 19; // RFC 2930
const RCODE_BADNAME = 20; // RFC 2930
const RCODE_BADALG = 21; // RFC 2930
const RCODE_BADTRUNC = 22; // RFC 4635
const RCODE_BADCOOKIE = 23; // RFC 7873
/*
* internal errors codes returned by the exceptions class
*/
const E_NONE = 0;
const E_DNS_FORMERR = self::RCODE_FORMERR;
const E_DNS_SERVFAIL = self::RCODE_SERVFAIL;
const E_DNS_NXDOMAIN = self::RCODE_NXDOMAIN;
const E_DNS_NOTIMP = self::RCODE_NOTIMP;
const E_DNS_REFUSED = self::RCODE_REFUSED;
const E_DNS_YXDOMAIN = self::RCODE_YXDOMAIN;
const E_DNS_YXRRSET = self::RCODE_YXRRSET;
const E_DNS_NXRRSET = self::RCODE_NXRRSET;
const E_DNS_NOTAUTH = self::RCODE_NOTAUTH;
const E_DNS_NOTZONE = self::RCODE_NOTZONE;
// 11-15 reserved
const E_DNS_BADSIG = self::RCODE_BADSIG;
const E_DNS_BADKEY = self::RCODE_BADKEY;
const E_DNS_BADTIME = self::RCODE_BADTIME;
const E_DNS_BADMODE = self::RCODE_BADMODE;
const E_DNS_BADNAME = self::RCODE_BADNAME;
const E_DNS_BADALG = self::RCODE_BADALG;
const E_DNS_BADTRUNC = self::RCODE_BADTRUNC;
const E_DNS_BADCOOKIE = self::RCODE_BADCOOKIE;
// other error conditions
const E_NS_INVALID_FILE = 200;
const E_NS_INVALID_ENTRY = 201;
const E_NS_FAILED = 202;
const E_NS_SOCKET_FAILED = 203;
const E_NS_INVALID_SOCKET = 204;
const E_PACKET_INVALID = 300;
const E_PARSE_ERROR = 301;
const E_HEADER_INVALID = 302;
const E_QUESTION_INVALID = 303;
const E_RR_INVALID = 304;
const E_OPENSSL_ERROR = 400;
const E_OPENSSL_UNAVAIL = 401;
const E_OPENSSL_INV_PKEY = 402;
const E_OPENSSL_INV_ALGO = 403;
const E_CACHE_UNSUPPORTED = 500;
const E_CACHE_SHM_FILE = 501;
const E_CACHE_SHM_UNAVAIL = 502;
/*
* EDNS0 Option Codes (OPT)
*/
// 0 - Reserved
const EDNS0_OPT_LLQ = 1;
const EDNS0_OPT_UL = 2;
const EDNS0_OPT_NSID = 3;
// 4 - Reserved
const EDNS0_OPT_DAU = 5;
const EDNS0_OPT_DHU = 6;
const EDNS0_OPT_N3U = 7;
const EDNS0_OPT_CLIENT_SUBNET = 8;
const EDNS0_OPT_EXPIRE = 9;
const EDNS0_OPT_COOKIE = 10;
const EDNS0_OPT_TCP_KEEPALIVE = 11;
const EDNS0_OPT_PADDING = 12;
const EDNS0_OPT_CHAIN = 13;
const EDNS0_OPT_KEY_TAG = 14;
// 15 - unsassigned
const EDNS0_OPT_CLIENT_TAG = 16;
const EDNS0_OPT_SERVER_TAG = 17;
// 18-26945 - unassigned
const EDNS0_OPT_DEVICEID = 26946;
/*
* DNSSEC Algorithms
*/
const DNSSEC_ALGORITHM_RES = 0;
const DNSSEC_ALGORITHM_RSAMD5 = 1;
const DNSSEC_ALGORITHM_DH = 2;
const DNSSEC_ALGORITHM_DSA = 3;
const DNSSEC_ALGORITHM_ECC = 4;
const DNSSEC_ALGORITHM_RSASHA1 = 5;
const DNSSEC_ALGORITHM_DSANSEC3SHA1 = 6;
const DSNSEC_ALGORITHM_RSASHA1NSEC3SHA1 = 7;
const DNSSEC_ALGORITHM_RSASHA256 = 8;
const DNSSEC_ALGORITHM_RSASHA512 = 10;
const DNSSEC_ALGORITHM_ECCGOST = 12;
const DNSSEC_ALGORITHM_ECDSAP256SHA256 = 13;
const DNSSEC_ALGORITHM_ECDSAP384SHA384 = 14;
const DNSSEC_ALGORITHM_ED25519 = 15;
const DNSSEC_ALGORITHM_ED448 = 16;
const DNSSEC_ALGORITHM_INDIRECT = 252;
const DNSSEC_ALGORITHM_PRIVATEDNS = 253;
const DNSSEC_ALGORITHM_PRIVATEOID = 254;
/*
* DNSSEC Digest Types
*/
const DNSSEC_DIGEST_RES = 0;
const DNSSEC_DIGEST_SHA1 = 1;
const DNSSEC_DIGEST_SHA256 = 2;
const DNSSEC_DIGEST_GOST = 3;
const DNSSEC_DIGEST_SHA384 = 4;
/*
* The packet id used when sending requests
*/
public static $next_packet_id;
/*
* Used to map resource record types to their id's, and back
*/
public static $rr_types_by_id = [];
public static $rr_types_by_name = [
'SIG0' => 0, // RFC 2931 pseudo type
'A' => 1, // RFC 1035
'NS' => 2, // RFC 1035
'MD' => 3, // RFC 1035 - obsolete, Not implemented
'MF' => 4, // RFC 1035 - obsolete, Not implemented
'CNAME' => 5, // RFC 1035
'SOA' => 6, // RFC 1035
'MB' => 7, // RFC 1035 - obsolete, Not implemented
'MG' => 8, // RFC 1035 - obsolete, Not implemented
'MR' => 9, // RFC 1035 - obsolete, Not implemented
'NULL' => 10, // RFC 1035 - obsolete, Not implemented
'WKS' => 11, // RFC 1035
'PTR' => 12, // RFC 1035
'HINFO' => 13, // RFC 1035
'MINFO' => 14, // RFC 1035 - obsolete, Not implemented
'MX' => 15, // RFC 1035
'TXT' => 16, // RFC 1035
'RP' => 17, // RFC 1183
'AFSDB' => 18, // RFC 1183
'X25' => 19, // RFC 1183
'ISDN' => 20, // RFC 1183
'RT' => 21, // RFC 1183
'NSAP' => 22, // RFC 1706
'NSAP_PTR' => 23, // RFC 1348 - obsolete, Not implemented
'SIG' => 24, // RFC 2535
'KEY' => 25, // RFC 2535, RFC 2930
'PX' => 26, // RFC 2163
'GPOS' => 27, // RFC 1712 - Not implemented
'AAAA' => 28, // RFC 3596
'LOC' => 29, // RFC 1876
'NXT' => 30, // RFC 2065, obsoleted by by RFC 3755
'EID' => 31, // [Patton][Patton1995]
'NIMLOC' => 32, // [Patton][Patton1995]
'SRV' => 33, // RFC 2782
'ATMA' => 34, // Windows only
'NAPTR' => 35, // RFC 2915
'KX' => 36, // RFC 2230
'CERT' => 37, // RFC 4398
'A6' => 38, // downgraded to experimental by RFC 3363
'DNAME' => 39, // RFC 2672
'SINK' => 40, // Not implemented
'OPT' => 41, // RFC 2671
'APL' => 42, // RFC 3123
'DS' => 43, // RFC 4034
'SSHFP' => 44, // RFC 4255
'IPSECKEY' => 45, // RFC 4025
'RRSIG' => 46, // RFC 4034
'NSEC' => 47, // RFC 4034
'DNSKEY' => 48, // RFC 4034
'DHCID' => 49, // RFC 4701
'NSEC3' => 50, // RFC 5155
'NSEC3PARAM' => 51, // RFC 5155
'TLSA' => 52, // RFC 6698
'SMIMEA' => 53, // RFC 8162
// 54 unassigned
'HIP' => 55, // RFC 5205
'NINFO' => 56, // Not implemented
'RKEY' => 57, // Not implemented
'TALINK' => 58, //
'CDS' => 59, // RFC 7344
'CDNSKEY' => 60, // RFC 7344
'OPENPGPKEY' => 61, // RFC 7929
'CSYNC' => 62, // RFC 7477
'ZONEMD' => 63, // Not implemented yet
'SVCB' => 64, // Not implemented yet
'HTTPS' => 65, // Not implemented yet
// 66 - 98 unassigned
'SPF' => 99, // RFC 4408
'UINFO' => 100, // no RFC, Not implemented
'UID' => 101, // no RFC, Not implemented
'GID' => 102, // no RFC, Not implemented
'UNSPEC' => 103, // no RFC, Not implemented
'NID' => 104, // RFC 6742
'L32' => 105, // RFC 6742
'L64' => 106, // RFC 6742
'LP' => 107, // RFC 6742
'EUI48' => 108, // RFC 7043
'EUI64' => 109, // RFC 7043
// 110 - 248 unassigned
'TKEY' => 249, // RFC 2930
'TSIG' => 250, // RFC 2845
'IXFR' => 251, // RFC 1995 - only a full (AXFR) is supported
'AXFR' => 252, // RFC 1035
'MAILB' => 253, // RFC 883, Not implemented
'MAILA' => 254, // RFC 973, Not implemented
'ANY' => 255, // RFC 1035 - we support both 'ANY' and '*'
'URI' => 256, // RFC 7553
'CAA' => 257, // RFC 8659
'AVC' => 258, // Application Visibility and Control
'DOA' => 259, // Not implemented yet
'AMTRELAY' => 260, // RFC 8777
// 261 - 32767 unassigned
'TA' => 32768, // same as DS
'DLV' => 32769, // RFC 4431
'TYPE65534' => 65534 // Private Bind record
];
/*
* Qtypes and Metatypes - defined in RFC2929 section 3.1
*/
public static $rr_qtypes_by_id = [];
public static $rr_qtypes_by_name = [
'IXFR' => 251, // RFC 1995 - only a full (AXFR) is supported
'AXFR' => 252, // RFC 1035
'MAILB' => 253, // RFC 883, Not implemented
'MAILA' => 254, // RFC 973, Not implemented
'ANY' => 255 // RFC 1035 - we support both 'ANY' and '*'
];
public static $rr_metatypes_by_id = [];
public static $rr_metatypes_by_name = [
'OPT' => 41, // RFC 2671
'TKEY' => 249, // RFC 2930
'TSIG' => 250 // RFC 2845
];
/*
* used to map resource record id's to RR class names
*/
public static $rr_types_class_to_id = [];
public static $rr_types_id_to_class = [
1 => 'Net_DNS2_RR_A',
2 => 'Net_DNS2_RR_NS',
5 => 'Net_DNS2_RR_CNAME',
6 => 'Net_DNS2_RR_SOA',
11 => 'Net_DNS2_RR_WKS',
12 => 'Net_DNS2_RR_PTR',
13 => 'Net_DNS2_RR_HINFO',
15 => 'Net_DNS2_RR_MX',
16 => 'Net_DNS2_RR_TXT',
17 => 'Net_DNS2_RR_RP',
18 => 'Net_DNS2_RR_AFSDB',
19 => 'Net_DNS2_RR_X25',
20 => 'Net_DNS2_RR_ISDN',
21 => 'Net_DNS2_RR_RT',
22 => 'Net_DNS2_RR_NSAP',
24 => 'Net_DNS2_RR_SIG',
25 => 'Net_DNS2_RR_KEY',
26 => 'Net_DNS2_RR_PX',
28 => 'Net_DNS2_RR_AAAA',
29 => 'Net_DNS2_RR_LOC',
31 => 'Net_DNS2_RR_EID',
32 => 'Net_DNS2_RR_NIMLOC',
33 => 'Net_DNS2_RR_SRV',
34 => 'Net_DNS2_RR_ATMA',
35 => 'Net_DNS2_RR_NAPTR',
36 => 'Net_DNS2_RR_KX',
37 => 'Net_DNS2_RR_CERT',
39 => 'Net_DNS2_RR_DNAME',
41 => 'Net_DNS2_RR_OPT',
42 => 'Net_DNS2_RR_APL',
43 => 'Net_DNS2_RR_DS',
44 => 'Net_DNS2_RR_SSHFP',
45 => 'Net_DNS2_RR_IPSECKEY',
46 => 'Net_DNS2_RR_RRSIG',
47 => 'Net_DNS2_RR_NSEC',
48 => 'Net_DNS2_RR_DNSKEY',
49 => 'Net_DNS2_RR_DHCID',
50 => 'Net_DNS2_RR_NSEC3',
51 => 'Net_DNS2_RR_NSEC3PARAM',
52 => 'Net_DNS2_RR_TLSA',
53 => 'Net_DNS2_RR_SMIMEA',
55 => 'Net_DNS2_RR_HIP',
58 => 'Net_DNS2_RR_TALINK',
59 => 'Net_DNS2_RR_CDS',
60 => 'Net_DNS2_RR_CDNSKEY',
61 => 'Net_DNS2_RR_OPENPGPKEY',
62 => 'Net_DNS2_RR_CSYNC',
99 => 'Net_DNS2_RR_SPF',
104 => 'Net_DNS2_RR_NID',
105 => 'Net_DNS2_RR_L32',
106 => 'Net_DNS2_RR_L64',
107 => 'Net_DNS2_RR_LP',
108 => 'Net_DNS2_RR_EUI48',
109 => 'Net_DNS2_RR_EUI64',
249 => 'Net_DNS2_RR_TKEY',
250 => 'Net_DNS2_RR_TSIG',
// 251 - IXFR - handled as a full zone transfer (252)
// 252 - AXFR - handled as a function call
255 => 'Net_DNS2_RR_ANY',
256 => 'Net_DNS2_RR_URI',
257 => 'Net_DNS2_RR_CAA',
258 => 'Net_DNS2_RR_AVC',
260 => 'Net_DNS2_RR_AMTRELAY',
32768 => 'Net_DNS2_RR_TA',
32769 => 'Net_DNS2_RR_DLV',
65534 => 'Net_DNS2_RR_TYPE65534'
];
/*
* used to map resource record class names to their id's, and back
*/
public static $classes_by_id = [];
public static $classes_by_name = [
'IN' => self::RR_CLASS_IN, // RFC 1035
'CH' => self::RR_CLASS_CH, // RFC 1035
'HS' => self::RR_CLASS_HS, // RFC 1035
'NONE' => self::RR_CLASS_NONE, // RFC 2136
'ANY' => self::RR_CLASS_ANY // RFC 1035
];
/*
* maps response codes to error messages
*/
public static $result_code_messages = [
self::RCODE_NOERROR => 'The request completed successfully.',
self::RCODE_FORMERR => 'The name server was unable to interpret the query.',
self::RCODE_SERVFAIL => 'The name server was unable to process this query due to a problem with the name server.',
self::RCODE_NXDOMAIN => 'The domain name referenced in the query does not exist.',
self::RCODE_NOTIMP => 'The name server does not support the requested kind of query.',
self::RCODE_REFUSED => 'The name server refuses to perform the specified operation for policy reasons.',
self::RCODE_YXDOMAIN => 'Name Exists when it should not.',
self::RCODE_YXRRSET => 'RR Set Exists when it should not.',
self::RCODE_NXRRSET => 'RR Set that should exist does not.',
self::RCODE_NOTAUTH => 'Server Not Authoritative for zone.',
self::RCODE_NOTZONE => 'Name not contained in zone.',
self::RCODE_BADSIG => 'TSIG Signature Failure.',
self::RCODE_BADKEY => 'Key not recognized.',
self::RCODE_BADTIME => 'Signature out of time window.',
self::RCODE_BADMODE => 'Bad TKEY Mode.',
self::RCODE_BADNAME => 'Duplicate key name.',
self::RCODE_BADALG => 'Algorithm not supported.',
self::RCODE_BADTRUNC => 'Bad truncation.'
];
/*
* maps DNS SEC alrorithms to their mnemonics
*/
public static $algorithm_name_to_id = [];
public static $algorithm_id_to_name = [
self::DNSSEC_ALGORITHM_RES => 'RES',
self::DNSSEC_ALGORITHM_RSAMD5 => 'RSAMD5',
self::DNSSEC_ALGORITHM_DH => 'DH',
self::DNSSEC_ALGORITHM_DSA => 'DSA',
self::DNSSEC_ALGORITHM_ECC => 'ECC',
self::DNSSEC_ALGORITHM_RSASHA1 => 'RSASHA1',
self::DNSSEC_ALGORITHM_DSANSEC3SHA1 => 'DSA-NSEC3-SHA1',
self::DSNSEC_ALGORITHM_RSASHA1NSEC3SHA1 => 'RSASHA1-NSEC3-SHA1',
self::DNSSEC_ALGORITHM_RSASHA256 => 'RSASHA256',
self::DNSSEC_ALGORITHM_RSASHA512 => 'RSASHA512',
self::DNSSEC_ALGORITHM_ECCGOST => 'ECC-GOST',
self::DNSSEC_ALGORITHM_ECDSAP256SHA256 => 'ECDSAP256SHA256',
self::DNSSEC_ALGORITHM_ECDSAP384SHA384 => 'ECDSAP384SHA384',
self::DNSSEC_ALGORITHM_ED25519 => 'ED25519',
self::DNSSEC_ALGORITHM_ED448 => 'ED448',
self::DNSSEC_ALGORITHM_INDIRECT => 'INDIRECT',
self::DNSSEC_ALGORITHM_PRIVATEDNS => 'PRIVATEDNS',
self::DNSSEC_ALGORITHM_PRIVATEOID => 'PRIVATEOID'
];
/*
* maps DNSSEC digest types to their mnemonics
*/
public static $digest_name_to_id = [];
public static $digest_id_to_name = [
self::DNSSEC_DIGEST_RES => 'RES',
self::DNSSEC_DIGEST_SHA1 => 'SHA-1',
self::DNSSEC_DIGEST_SHA256 => 'SHA-256',
self::DNSSEC_DIGEST_GOST => 'GOST-R-34.11-94',
self::DNSSEC_DIGEST_SHA384 => 'SHA-384'
];
/*
* Protocols names - RFC 1010
*/
public static $protocol_by_id = [];
public static $protocol_by_name = [
'ICMP' => 1,
'IGMP' => 2,
'GGP' => 3,
'ST' => 5,
'TCP' => 6,
'UCL' => 7,
'EGP' => 8,
'IGP' => 9,
'BBN-RCC-MON' => 10,
'NVP-II' => 11,
'PUP' => 12,
'ARGUS' => 13,
'EMCON' => 14,
'XNET' => 15,
'CHAOS' => 16,
'UDP' => 17,
'MUX' => 18,
'DCN-MEAS' => 19,
'HMP' => 20,
'PRM' => 21,
'XNS-IDP' => 22,
'TRUNK-1' => 23,
'TRUNK-2' => 24,
'LEAF-1' => 25,
'LEAF-2' => 26,
'RDP' => 27,
'IRTP' => 28,
'ISO-TP4' => 29,
'NETBLT' => 30,
'MFE-NSP' => 31,
'MERIT-INP' => 32,
'SEP' => 33,
// 34 - 60 - Unassigned
// 61 - any host internal protocol
'CFTP' => 62,
// 63 - any local network
'SAT-EXPAK' => 64,
'MIT-SUBNET' => 65,
'RVD' => 66,
'IPPC' => 67,
// 68 - any distributed file system
'SAT-MON' => 69,
// 70 - Unassigned
'IPCV' => 71,
// 72 - 75 - Unassigned
'BR-SAT-MON' => 76,
// 77 - Unassigned
'WB-MON' => 78,
'WB-EXPAK' => 79
// 80 - 254 - Unassigned
// 255 - Reserved
];
}

View File

@ -0,0 +1,220 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* The main dynamic DNS notifier class.
*
* This class provices functions to handle DNS notify requests as defined by RFC 1996.
*
* This is separate from the Net_DNS2_Resolver class, as while the underlying
* protocol is the same, the functionality is completely different.
*
* Generally, query (recursive) lookups are done against caching server, while
* notify requests are done against authoratative servers.
*
*/
class Net_DNS2_Notifier extends Net_DNS2
{
/*
* a Net_DNS2_Packet_Request object used for the notify request
*/
private $_packet;
/**
* Constructor - builds a new Net_DNS2_Notifier objected used for doing
* DNS notification for a changed zone
*
* @param string $zone the domain name to use for DNS updates
* @param mixed $options an array of config options or null
*
* @throws Net_DNS2_Exception
* @access public
*
*/
public function __construct($zone, array $options = null)
{
parent::__construct($options);
//
// create the packet
//
$this->_packet = new Net_DNS2_Packet_Request(
strtolower(trim($zone, " \n\r\t.")), 'SOA', 'IN'
);
//
// make sure the opcode on the packet is set to NOTIFY
//
$this->_packet->header->opcode = Net_DNS2_Lookups::OPCODE_NOTIFY;
}
/**
* checks that the given name matches the name for the zone we're notifying
*
* @param string $name The name to be checked.
*
* @return boolean
* @throws Net_DNS2_Exception
* @access private
*
*/
private function _checkName($name)
{
if (!preg_match('/' . $this->_packet->question[0]->qname . '$/', $name)) {
throw new Net_DNS2_Exception(
'name provided (' . $name . ') does not match zone name (' .
$this->_packet->question[0]->qname . ')',
Net_DNS2_Lookups::E_PACKET_INVALID
);
}
return true;
}
/**
* 3.7 - Add RR to notify
*
* @param Net_DNS2_RR $rr the Net_DNS2_RR object to be sent in the notify message
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function add(Net_DNS2_RR $rr)
{
$this->_checkName($rr->name);
//
// add the RR to the "notify" section
//
if (!in_array($rr, $this->_packet->answer)) {
$this->_packet->answer[] = $rr;
}
return true;
}
/**
* add a signature to the request for authentication
*
* @param string $keyname the key name to use for the TSIG RR
* @param string $signature the key to sign the request.
*
* @return boolean
* @access public
* @see Net_DNS2::signTSIG()
* @deprecated function deprecated in 1.1.0
*
*/
public function signature($keyname, $signature, $algorithm = Net_DNS2_RR_TSIG::HMAC_MD5)
{
return $this->signTSIG($keyname, $signature, $algorithm);
}
/**
* returns the current internal packet object.
*
* @return Net_DNS2_Packet_Request
* @access public
#
*/
public function packet()
{
//
// take a copy
//
$p = $this->_packet;
//
// check for an authentication method; either TSIG or SIG
//
if ( ($this->auth_signature instanceof Net_DNS2_RR_TSIG)
|| ($this->auth_signature instanceof Net_DNS2_RR_SIG)
) {
$p->additional[] = $this->auth_signature;
}
//
// update the counts
//
$p->header->qdcount = count($p->question);
$p->header->ancount = count($p->answer);
$p->header->nscount = count($p->authority);
$p->header->arcount = count($p->additional);
return $p;
}
/**
* executes the notify request
*
* @param Net_DNS2_Packet_Response &$response ref to the response object
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function notify(&$response = null)
{
//
// check for an authentication method; either TSIG or SIG
//
if ( ($this->auth_signature instanceof Net_DNS2_RR_TSIG)
|| ($this->auth_signature instanceof Net_DNS2_RR_SIG)
) {
$this->_packet->additional[] = $this->auth_signature;
}
//
// update the counts
//
$this->_packet->header->qdcount = count($this->_packet->question);
$this->_packet->header->ancount = count($this->_packet->answer);
$this->_packet->header->nscount = count($this->_packet->authority);
$this->_packet->header->arcount = count($this->_packet->additional);
//
// make sure we have some data to send
//
if ($this->_packet->header->qdcount == 0) {
throw new Net_DNS2_Exception(
'empty headers- nothing to send!',
Net_DNS2_Lookups::E_PACKET_INVALID
);
}
//
// send the packet and get back the response
//
$response = $this->sendPacket($this->_packet, $this->use_tcp);
//
// clear the internal packet so if we make another request, we don't have
// old data being sent.
//
$this->_packet->reset();
//
// for notifies, we just need to know it worked- we don't actualy need to
// return the response object
//
return true;
}
}

View File

@ -0,0 +1,401 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
* This file contains code based off the Net::DNS Perl module by Michael Fuhr.
*
* This is the copyright notice from the PERL Net::DNS module:
*
* Copyright (c) 1997-2000 Michael Fuhr. All rights reserved. This program is
* free software; you can redistribute it and/or modify it under the same terms
* as Perl itself.
*
*/
/**
* This is the base class that holds a standard DNS packet.
*
* The Net_DNS2_Packet_Request and Net_DNS2_Packet_Response classes extend this
* class.
*
*/
class Net_DNS2_Packet
{
/*
* the full binary data and length for this packet
*/
public $rdata;
public $rdlength;
/*
* the offset pointer used when building/parsing packets
*/
public $offset = 0;
/*
* Net_DNS2_Header object with the DNS packet header
*/
public $header;
/*
* array of Net_DNS2_Question objects
*
* used as "zone" for updates per RFC2136
*
*/
public $question = [];
/*
* array of Net_DNS2_RR Objects for Answers
*
* used as "prerequisite" for updates per RFC2136
*
*/
public $answer = [];
/*
* array of Net_DNS2_RR Objects for Authority
*
* used as "update" for updates per RFC2136
*
*/
public $authority = [];
/*
* array of Net_DNS2_RR Objects for Addtitional
*/
public $additional = [];
/*
* array of compressed labeles
*/
private $_compressed = [];
/**
* magic __toString() method to return the Net_DNS2_Packet as a string
*
* @return string
* @access public
*
*/
public function __toString()
{
$output = $this->header->__toString();
foreach ($this->question as $x) {
$output .= $x->__toString() . "\n";
}
foreach ($this->answer as $x) {
$output .= $x->__toString() . "\n";
}
foreach ($this->authority as $x) {
$output .= $x->__toString() . "\n";
}
foreach ($this->additional as $x) {
$output .= $x->__toString() . "\n";
}
return $output;
}
/**
* returns a full binary DNS packet
*
* @return string
* @throws Net_DNS2_Exception
* @access public
*
*/
public function get()
{
$data = $this->header->get($this);
foreach ($this->question as $x) {
$data .= $x->get($this);
}
foreach ($this->answer as $x) {
$data .= $x->get($this);
}
foreach ($this->authority as $x) {
$data .= $x->get($this);
}
foreach ($this->additional as $x) {
$data .= $x->get($this);
}
return $data;
}
/**
* applies a standard DNS name compression on the given name/offset
*
* This logic was based on the Net::DNS::Packet::dn_comp() function
* by Michanel Fuhr
*
* @param string $name the name to be compressed
* @param integer &$offset the offset into the given packet object
*
* @return string
* @access public
*
*/
public function compress($name, &$offset)
{
//
// we're using preg_split() rather than explode() so that we can use the negative lookbehind,
// to catch cases where we have escaped dots in strings.
//
// there's only a few cases like this- the rname in SOA for example
//
$names = str_replace('\.', '.', preg_split('/(?<!\\\)\./', $name));
$compname = '';
while (!empty($names)) {
$dname = join('.', $names);
if (isset($this->_compressed[$dname])) {
$compname .= pack('n', 0xc000 | $this->_compressed[$dname]);
$offset += 2;
break;
}
$this->_compressed[$dname] = $offset;
$first = array_shift($names);
$length = strlen($first);
if ($length <= 0) {
continue;
}
//
// truncate see RFC1035 2.3.1
//
if ($length > 63) {
$length = 63;
$first = substr($first, 0, $length);
}
$compname .= pack('Ca*', $length, $first);
$offset += $length + 1;
}
if (empty($names)) {
$compname .= pack('C', 0);
$offset++;
}
return $compname;
}
/**
* applies a standard DNS name compression on the given name/offset
*
* This logic was based on the Net::DNS::Packet::dn_comp() function
* by Michanel Fuhr
*
* @param string $name the name to be compressed
*
* @return string
* @access public
*
*/
public static function pack($name)
{
$offset = 0;
$names = explode('.', $name);
$compname = '';
while (!empty($names)) {
$first = array_shift($names);
$length = strlen($first);
$compname .= pack('Ca*', $length, $first);
$offset += $length + 1;
}
$compname .= "\0";
$offset++;
return $compname;
}
/**
* expands the domain name stored at a given offset in a DNS Packet
*
* This logic was based on the Net::DNS::Packet::dn_expand() function
* by Michanel Fuhr
*
* @param Net_DNS2_Packet &$packet the DNS packet to look in for the domain name
* @param integer &$offset the offset into the given packet object
* @param boolean $escape_dot_literals if we should escape periods in names
*
* @return mixed either the domain name or null if it's not found.
* @access public
*
*/
public static function expand(Net_DNS2_Packet &$packet, &$offset, $escape_dot_literals = false)
{
$name = '';
while (1) {
if ($packet->rdlength < ($offset + 1)) {
return null;
}
$xlen = ord($packet->rdata[$offset]);
if ($xlen == 0) {
++$offset;
break;
} else if (($xlen & 0xc0) == 0xc0) {
if ($packet->rdlength < ($offset + 2)) {
return null;
}
$ptr = ord($packet->rdata[$offset]) << 8 | ord($packet->rdata[$offset+1]);
$ptr = $ptr & 0x3fff;
$name2 = Net_DNS2_Packet::expand($packet, $ptr);
if (is_null($name2)) {
return null;
}
$name .= $name2;
$offset += 2;
break;
} else {
++$offset;
if ($packet->rdlength < ($offset + $xlen)) {
return null;
}
$elem = '';
$elem = substr($packet->rdata, $offset, $xlen);
//
// escape literal dots in certain cases (SOA rname)
//
if ( ($escape_dot_literals == true) && (strpos($elem, '.') !== false) ) {
$elem = str_replace('.', '\.', $elem);
}
$name .= $elem . '.';
$offset += $xlen;
}
}
return trim($name, '.');
}
/**
* parses a domain label from a DNS Packet at the given offset
*
* @param Net_DNS2_Packet &$packet the DNS packet to look in for the domain name
* @param integer &$offset the offset into the given packet object
*
* @return mixed either the domain name or null if it's not found.
* @access public
*
*/
public static function label(Net_DNS2_Packet &$packet, &$offset)
{
$name = '';
if ($packet->rdlength < ($offset + 1)) {
return null;
}
$xlen = ord($packet->rdata[$offset]);
++$offset;
if (($xlen + $offset) > $packet->rdlength) {
$name = substr($packet->rdata, $offset);
$offset = $packet->rdlength;
} else {
$name = substr($packet->rdata, $offset, $xlen);
$offset += $xlen;
}
return $name;
}
/**
* copies the contents of the given packet, to the local packet object. this
* function intentionally ignores some of the packet data.
*
* @param Net_DNS2_Packet $packet the DNS packet to copy the data from
*
* @return boolean
* @access public
*
*/
public function copy(Net_DNS2_Packet $packet)
{
$this->header = $packet->header;
$this->question = $packet->question;
$this->answer = $packet->answer;
$this->authority = $packet->authority;
$this->additional = $packet->additional;
return true;
}
/**
* resets the values in the current packet object
*
* @return boolean
* @access public
*
*/
public function reset()
{
$this->header->id = $this->header->nextPacketId();
$this->rdata = '';
$this->rdlength = 0;
$this->offset = 0;
$this->answer = [];
$this->authority = [];
$this->additional = [];
$this->_compressed = [];
return true;
}
}

View File

@ -0,0 +1,168 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* This class handles building new DNS request packets; packets used for DNS
* queries and updates.
*
*/
class Net_DNS2_Packet_Request extends Net_DNS2_Packet
{
/**
* Constructor - builds a new Net_DNS2_Packet_Request object
*
* @param string $name the domain name for the packet
* @param string $type the DNS RR type for the packet
* @param string $class the DNS class for the packet
*
* @throws Net_DNS2_Exception
* @access public
*
*/
public function __construct($name, $type = null, $class = null)
{
$this->set($name, $type, $class);
}
/**
* builds a new Net_DNS2_Packet_Request object
*
* @param string $name the domain name for the packet
* @param string $type the DNS RR type for the packet
* @param string $class the DNS class for the packet
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function set($name, $type = 'A', $class = 'IN')
{
//
// generate a new header
//
$this->header = new Net_DNS2_Header;
//
// add a new question
//
$q = new Net_DNS2_Question();
//
// allow queries directly to . for the root name servers
//
if ($name != '.') {
$name = trim(strtolower($name), " \t\n\r\0\x0B.");
}
$type = strtoupper(trim($type));
$class = strtoupper(trim($class));
//
// check that the input string has some data in it
//
if (empty($name)) {
throw new Net_DNS2_Exception(
'empty query string provided',
Net_DNS2_Lookups::E_PACKET_INVALID
);
}
//
// if the type is "*", rename it to "ANY"- both are acceptable.
//
if ($type == '*') {
$type = 'ANY';
}
//
// check that the type and class are valid
//
if ( (!isset(Net_DNS2_Lookups::$rr_types_by_name[$type]))
|| (!isset(Net_DNS2_Lookups::$classes_by_name[$class]))
) {
throw new Net_DNS2_Exception(
'invalid type (' . $type . ') or class (' . $class . ') specified.',
Net_DNS2_Lookups::E_PACKET_INVALID
);
}
if ($type == 'PTR') {
//
// if it's a PTR request for an IP address, then make sure we tack on
// the arpa domain.
//
// there are other types of PTR requests, so if an IP adress doesn't match,
// then just let it flow through and assume it's a hostname
//
if (Net_DNS2::isIPv4($name) == true) {
//
// IPv4
//
$name = implode('.', array_reverse(explode('.', $name)));
$name .= '.in-addr.arpa';
} else if (Net_DNS2::isIPv6($name) == true) {
//
// IPv6
//
$e = Net_DNS2::expandIPv6($name);
if ($e !== false) {
$name = implode(
'.', array_reverse(str_split(str_replace(':', '', $e)))
);
$name .= '.ip6.arpa';
} else {
throw new Net_DNS2_Exception(
'unsupported PTR value: ' . $name,
Net_DNS2_Lookups::E_PACKET_INVALID
);
}
}
}
//
// store the data
//
$q->qname = $name;
$q->qtype = $type;
$q->qclass = $class;
$this->question[] = $q;
//
// the answer, authority and additional are empty; they can be modified
// after the request is created for UPDATE requests if needed.
//
$this->answer = [];
$this->authority = [];
$this->additional = [];
return true;
}
}

View File

@ -0,0 +1,145 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* This class handles building new DNS response packets; it parses binary packed
* packets that come off the wire
*
*/
class Net_DNS2_Packet_Response extends Net_DNS2_Packet
{
/*
* The name servers that this response came from
*/
public $answer_from;
/*
* The socket type the answer came from (TCP/UDP)
*/
public $answer_socket_type;
/*
* The query response time in microseconds
*/
public $response_time = 0;
/**
* Constructor - builds a new Net_DNS2_Packet_Response object
*
* @param string $data binary DNS packet
* @param integer $size the length of the DNS packet
*
* @throws Net_DNS2_Exception
* @access public
*
*/
public function __construct($data, $size)
{
$this->set($data, $size);
}
/**
* builds a new Net_DNS2_Packet_Response object
*
* @param string $data binary DNS packet
* @param integer $size the length of the DNS packet
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function set($data, $size)
{
//
// store the full packet
//
$this->rdata = $data;
$this->rdlength = $size;
//
// parse the header
//
// we don't bother checking the size earlier, because the first thing the
// header class does, is check the size and throw and exception if it's
// invalid.
//
$this->header = new Net_DNS2_Header($this);
//
// if the truncation bit is set, then just return right here, because the
// rest of the packet is probably empty; and there's no point in processing
// anything else.
//
// we also don't need to worry about checking to see if the the header is
// null or not, since the Net_DNS2_Header() constructor will throw an
// exception if the packet is invalid.
//
if ($this->header->tc == 1) {
return false;
}
//
// parse the questions
//
for ($x = 0; $x < $this->header->qdcount; ++$x) {
$this->question[$x] = new Net_DNS2_Question($this);
}
//
// parse the answers
//
for ($x = 0; $x < $this->header->ancount; ++$x) {
$o = Net_DNS2_RR::parse($this);
if (!is_null($o)) {
$this->answer[] = $o;
}
}
//
// parse the authority section
//
for ($x = 0; $x < $this->header->nscount; ++$x) {
$o = Net_DNS2_RR::parse($this);
if (!is_null($o)) {
$this->authority[] = $o;
}
}
//
// parse the additional section
//
for ($x = 0; $x < $this->header->arcount; ++$x) {
$o = Net_DNS2_RR::parse($this);
if (!is_null($o)) {
$this->additional[] = $o;
}
}
return true;
}
}

View File

@ -0,0 +1,377 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.1.0
*
*/
/**
* SSL Private Key container class
*
*/
class Net_DNS2_PrivateKey
{
/*
* the filename that was loaded; stored for reference
*/
public $filename;
/*
* the keytag for the signature
*/
public $keytag;
/*
* the sign name for the signature
*/
public $signname;
/*
* the algorithm used for the signature
*/
public $algorithm;
/*
* the key format of the signature
*/
public $key_format;
/*
* the openssl private key id
*/
public $instance;
/*
* RSA: modulus
*/
private $_modulus;
/*
* RSA: public exponent
*/
private $_public_exponent;
/*
* RSA: rivate exponent
*/
private $_private_exponent;
/*
* RSA: prime1
*/
private $_prime1;
/*
* RSA: prime2
*/
private $_prime2;
/*
* RSA: exponent 1
*/
private $_exponent1;
/*
* RSA: exponent 2
*/
private $_exponent2;
/*
* RSA: coefficient
*/
private $_coefficient;
/*
* DSA: prime
*/
public $prime;
/*
* DSA: subprime
*/
public $subprime;
/*
* DSA: base
*/
public $base;
/*
* DSA: private value
*/
public $private_value;
/*
* DSA: public value
*/
public $public_value;
/**
* Constructor - base constructor the private key container class
*
* @param string $file path to a private-key file to parse and load
*
* @throws Net_DNS2_Exception
* @access public
*
*/
public function __construct($file = null)
{
if (isset($file)) {
$this->parseFile($file);
}
}
/**
* parses a private key file generated by dnssec-keygen
*
* @param string $file path to a private-key file to parse and load
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function parseFile($file)
{
//
// check for OpenSSL
//
if (extension_loaded('openssl') === false) {
throw new Net_DNS2_Exception(
'the OpenSSL extension is required to use parse private key.',
Net_DNS2_Lookups::E_OPENSSL_UNAVAIL
);
}
//
// check to make sure the file exists
//
if (is_readable($file) == false) {
throw new Net_DNS2_Exception(
'invalid private key file: ' . $file,
Net_DNS2_Lookups::E_OPENSSL_INV_PKEY
);
}
//
// get the base filename, and parse it for the local value
//
$keyname = basename($file);
if (strlen($keyname) == 0) {
throw new Net_DNS2_Exception(
'failed to get basename() for: ' . $file,
Net_DNS2_Lookups::E_OPENSSL_INV_PKEY
);
}
//
// parse the keyname
//
if (preg_match("/K(.*)\.\+(\d{3})\+(\d*)\.private/", $keyname, $matches)) {
$this->signname = $matches[1];
$this->algorithm = intval($matches[2]);
$this->keytag = intval($matches[3]);
} else {
throw new Net_DNS2_Exception(
'file ' . $keyname . ' does not look like a private key file!',
Net_DNS2_Lookups::E_OPENSSL_INV_PKEY
);
}
//
// read all the data from the
//
$data = file($file, FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
if (count($data) == 0) {
throw new Net_DNS2_Exception(
'file ' . $keyname . ' is empty!',
Net_DNS2_Lookups::E_OPENSSL_INV_PKEY
);
}
foreach ($data as $line) {
list($key, $value) = explode(':', $line);
$key = trim($key);
$value = trim($value);
switch(strtolower($key)) {
case 'private-key-format':
$this->key_format = $value;
break;
case 'algorithm':
if ($this->algorithm != $value) {
throw new Net_DNS2_Exception(
'Algorithm mis-match! filename is ' . $this->algorithm .
', contents say ' . $value,
Net_DNS2_Lookups::E_OPENSSL_INV_ALGO
);
}
break;
//
// RSA
//
case 'modulus':
$this->_modulus = $value;
break;
case 'publicexponent':
$this->_public_exponent = $value;
break;
case 'privateexponent':
$this->_private_exponent = $value;
break;
case 'prime1':
$this->_prime1 = $value;
break;
case 'prime2':
$this->_prime2 = $value;
break;
case 'exponent1':
$this->_exponent1 = $value;
break;
case 'exponent2':
$this->_exponent2 = $value;
break;
case 'coefficient':
$this->_coefficient = $value;
break;
//
// DSA - this won't work in PHP until the OpenSSL extension is better
//
case 'prime(p)':
$this->prime = $value;
break;
case 'subprime(q)':
$this->subprime = $value;
break;
case 'base(g)':
$this->base = $value;
break;
case 'private_value(x)':
$this->private_value = $value;
break;
case 'public_value(y)':
$this->public_value = $value;
break;
default:
throw new Net_DNS2_Exception(
'unknown private key data: ' . $key . ': ' . $value,
Net_DNS2_Lookups::E_OPENSSL_INV_PKEY
);
}
}
//
// generate the private key
//
$args = [];
switch($this->algorithm) {
//
// RSA
//
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSAMD5:
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA1:
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA256:
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA512:
$args = [
'rsa' => [
'n' => base64_decode($this->_modulus),
'e' => base64_decode($this->_public_exponent),
'd' => base64_decode($this->_private_exponent),
'p' => base64_decode($this->_prime1),
'q' => base64_decode($this->_prime2),
'dmp1' => base64_decode($this->_exponent1),
'dmq1' => base64_decode($this->_exponent2),
'iqmp' => base64_decode($this->_coefficient)
]
];
break;
//
// DSA - this won't work in PHP until the OpenSSL extension is better
//
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_DSA:
$args = [
'dsa' => [
'p' => base64_decode($this->prime),
'q' => base64_decode($this->subprime),
'g' => base64_decode($this->base),
'priv_key' => base64_decode($this->private_value),
'pub_key' => base64_decode($this->public_value)
]
];
break;
default:
throw new Net_DNS2_Exception(
'we only currently support RSAMD5 and RSASHA1 encryption.',
Net_DNS2_Lookups::E_OPENSSL_INV_PKEY
);
}
//
// generate and store the key
//
$this->instance = openssl_pkey_new($args);
if ($this->instance === false) {
throw new Net_DNS2_Exception(
openssl_error_string(),
Net_DNS2_Lookups::E_OPENSSL_ERROR
);
}
//
// store the filename incase we need it for something
//
$this->filename = $file;
return true;
}
}

View File

@ -0,0 +1,196 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* This class handles parsing and constructing the question sectino of DNS
* packets.
*
* This is referred to as the "zone" for update per RFC2136
*
* DNS question format - RFC1035 section 4.1.2
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | |
* / QNAME /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | QTYPE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | QCLASS |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_Question
{
/*
* The name of the question
*
* referred to as "zname" for updates per RFC2136
*
*/
public $qname;
/*
* The RR type for the questino
*
* referred to as "ztype" for updates per RFC2136
*
*/
public $qtype;
/*
* The RR class for the questino
*
* referred to as "zclass" for updates per RFC2136
*
*/
public $qclass;
/**
* Constructor - builds a new Net_DNS2_Question object
*
* @param mixed &$packet either a Net_DNS2_Packet object, or null to
* build an empty object
*
* @throws Net_DNS2_Exception
* @access public
*
*/
public function __construct(Net_DNS2_Packet &$packet = null)
{
if (!is_null($packet)) {
$this->set($packet);
} else {
$this->qname = '';
$this->qtype = 'A';
$this->qclass = 'IN';
}
}
/**
* magic __toString() function to return the Net_DNS2_Question object as a string
*
* @return string
* @access public
*
*/
public function __toString()
{
return ";;\n;; Question:\n;;\t " . $this->qname . '. ' .
$this->qtype . ' ' . $this->qclass . "\n";
}
/**
* builds a new Net_DNS2_Header object from a Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet object
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function set(Net_DNS2_Packet &$packet)
{
//
// expand the name
//
$this->qname = $packet->expand($packet, $packet->offset);
if ($packet->rdlength < ($packet->offset + 4)) {
throw new Net_DNS2_Exception(
'invalid question section: to small',
Net_DNS2_Lookups::E_QUESTION_INVALID
);
}
//
// unpack the type and class
//
$type = ord($packet->rdata[$packet->offset++]) << 8 |
ord($packet->rdata[$packet->offset++]);
$class = ord($packet->rdata[$packet->offset++]) << 8 |
ord($packet->rdata[$packet->offset++]);
//
// validate it
//
$type_name = Net_DNS2_Lookups::$rr_types_by_id[$type];
$class_name = Net_DNS2_Lookups::$classes_by_id[$class];
if ( (!isset($type_name)) || (!isset($class_name)) ) {
throw new Net_DNS2_Exception(
'invalid question section: invalid type (' . $type .
') or class (' . $class . ') specified.',
Net_DNS2_Lookups::E_QUESTION_INVALID
);
}
//
// store it
//
$this->qtype = $type_name;
$this->qclass = $class_name;
return true;
}
/**
* returns a binary packed Net_DNS2_Question object
*
* @param Net_DNS2_Packet &$packet the Net_DNS2_Packet object this question is
* part of. This needs to be passed in so that
* the compressed qname value can be packed in
* with the names of the other parts of the
* packet.
*
* @return string
* @throws Net_DNS2_Exception
* @access public
*
*/
public function get(Net_DNS2_Packet &$packet)
{
//
// validate the type and class
//
$type = Net_DNS2_Lookups::$rr_types_by_name[$this->qtype];
$class = Net_DNS2_Lookups::$classes_by_name[$this->qclass];
if ( (!isset($type)) || (!isset($class)) ) {
throw new Net_DNS2_Exception(
'invalid question section: invalid type (' . $this->qtype .
') or class (' . $this->qclass . ') specified.',
Net_DNS2_Lookups::E_QUESTION_INVALID
);
}
$data = $packet->compress($this->qname, $packet->offset);
$data .= chr($type >> 8) . chr($type) . chr($class >> 8) . chr($class);
$packet->offset += 4;
return $data;
}
}

616
libs/pear/Net/DNS2/RR.php Normal file
View File

@ -0,0 +1,616 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* This is the base class for DNS Resource Records
*
* Each resource record type (defined in RR/*.php) extends this class for
* base functionality.
*
* This class handles parsing and constructing the common parts of the DNS
* resource records, while the RR specific functionality is handled in each
* child class.
*
* DNS resource record format - RFC1035 section 4.1.3
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | |
* / /
* / NAME /
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | TYPE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | CLASS |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | TTL |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | RDLENGTH |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
* / RDATA /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
abstract class Net_DNS2_RR
{
/*
* The name of the resource record
*/
public $name;
/*
* The resource record type
*/
public $type;
/*
* The resouce record class
*/
public $class;
/*
* The time to live for this resource record
*/
public $ttl;
/*
* The length of the rdata field
*/
public $rdlength;
/*
* The resource record specific data as a packed binary string
*/
public $rdata;
/**
* abstract definition - method to return a RR as a string; not to
* be confused with the __toString() magic method.
*
* @return string
* @access protected
*
*/
abstract protected function rrToString();
/**
* abstract definition - parses a RR from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
abstract protected function rrFromString(array $rdata);
/**
* abstract definition - sets a Net_DNS2_RR from a Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
abstract protected function rrSet(Net_DNS2_Packet &$packet);
/**
* abstract definition - returns a binary packet DNS RR object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed string or
* null on failure
* @access protected
*
*/
abstract protected function rrGet(Net_DNS2_Packet &$packet);
/**
* Constructor - builds a new Net_DNS2_RR object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet or null to create
* an empty object
* @param array $rr an array with RR parse values or null to
* create an empty object
*
* @throws Net_DNS2_Exception
* @access public
*
*/
public function __construct(Net_DNS2_Packet &$packet = null, array $rr = null)
{
if ( (!is_null($packet)) && (!is_null($rr)) ) {
if ($this->set($packet, $rr) == false) {
throw new Net_DNS2_Exception(
'failed to generate resource record',
Net_DNS2_Lookups::E_RR_INVALID
);
}
} else {
$class = Net_DNS2_Lookups::$rr_types_class_to_id[get_class($this)];
if (isset($class)) {
$this->type = Net_DNS2_Lookups::$rr_types_by_id[$class];
}
$this->class = 'IN';
$this->ttl = 86400;
}
}
/**
* magic __toString() method to return the Net_DNS2_RR object object as a string
*
* @return string
* @access public
*
*/
public function __toString()
{
return $this->name . '. ' . $this->ttl . ' ' . $this->class .
' ' . $this->type . ' ' . $this->rrToString();
}
/**
* return the same data as __toString(), but as an array, so each value can be
* used without having to parse the string.
*
* @return array
* @access public
*
*/
public function asArray()
{
return [
'name' => $this->name,
'ttl' => $this->ttl,
'class' => $this->class,
'type' => $this->type,
'rdata' => $this->rrToString()
];
}
/**
* return a formatted string; if a string has spaces in it, then return
* it with double quotes around it, otherwise, return it as it was passed in.
*
* @param string $string the string to format
*
* @return string
* @access protected
*
*/
protected function formatString($string)
{
return '"' . str_replace('"', '\"', trim($string, '"')) . '"';
}
/**
* builds an array of strings from an array of chunks of text split by spaces
*
* @param array $chunks an array of chunks of text split by spaces
*
* @return array
* @access protected
*
*/
protected function buildString(array $chunks)
{
$data = [];
$c = 0;
$in = false;
foreach ($chunks as $r) {
$r = trim($r);
if (strlen($r) == 0) {
continue;
}
if ( ($r[0] == '"')
&& ($r[strlen($r) - 1] == '"')
&& ($r[strlen($r) - 2] != '\\')
) {
$data[$c] = $r;
++$c;
$in = false;
} else if ($r[0] == '"') {
$data[$c] = $r;
$in = true;
} else if ( ($r[strlen($r) - 1] == '"')
&& ($r[strlen($r) - 2] != '\\')
) {
$data[$c] .= ' ' . $r;
++$c;
$in = false;
} else {
if ($in == true) {
$data[$c] .= ' ' . $r;
} else {
$data[$c++] = $r;
}
}
}
foreach ($data as $index => $string) {
$data[$index] = str_replace('\"', '"', trim($string, '"'));
}
return $data;
}
/**
* builds a new Net_DNS2_RR object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet or null to create
* an empty object
* @param array $rr an array with RR parse values or null to
* create an empty object
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function set(Net_DNS2_Packet &$packet, array $rr)
{
$this->name = $rr['name'];
$this->type = Net_DNS2_Lookups::$rr_types_by_id[$rr['type']];
//
// for RR OPT (41), the class value includes the requestors UDP payload size,
// and not a class value
//
if ($this->type == 'OPT') {
$this->class = $rr['class'];
} else {
$this->class = Net_DNS2_Lookups::$classes_by_id[$rr['class']];
}
$this->ttl = $rr['ttl'];
$this->rdlength = $rr['rdlength'];
$this->rdata = substr($packet->rdata, $packet->offset, $rr['rdlength']);
return $this->rrSet($packet);
}
/**
* returns a binary packed DNS RR object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet used for
* compressing names
*
* @return string
* @throws Net_DNS2_Exception
* @access public
*
*/
public function get(Net_DNS2_Packet &$packet)
{
$data = '';
$rdata = '';
//
// pack the name
//
$data = $packet->compress($this->name, $packet->offset);
//
// pack the main values
//
if ($this->type == 'OPT') {
//
// pre-build the TTL value
//
$this->preBuild();
//
// the class value is different for OPT types
//
$data .= pack(
'nnN',
Net_DNS2_Lookups::$rr_types_by_name[$this->type],
$this->class,
$this->ttl
);
} else {
$data .= pack(
'nnN',
Net_DNS2_Lookups::$rr_types_by_name[$this->type],
Net_DNS2_Lookups::$classes_by_name[$this->class],
$this->ttl
);
}
//
// increase the offset, and allow for the rdlength
//
$packet->offset += 10;
//
// get the RR specific details
//
if ($this->rdlength != -1) {
$rdata = $this->rrGet($packet);
}
//
// add the RR
//
$data .= pack('n', strlen($rdata)) . $rdata;
return $data;
}
/**
* parses a binary packet, and returns the appropriate Net_DNS2_RR object,
* based on the RR type of the binary content.
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet used for
* decompressing names
*
* @return mixed returns a new Net_DNS2_RR_* object for
* the given RR
* @throws Net_DNS2_Exception
* @access public
*
*/
public static function parse(Net_DNS2_Packet &$packet)
{
$object = [];
//
// expand the name
//
$object['name'] = $packet->expand($packet, $packet->offset);
if (is_null($object['name'])) {
throw new Net_DNS2_Exception(
'failed to parse resource record: failed to expand name.',
Net_DNS2_Lookups::E_PARSE_ERROR
);
}
if ($packet->rdlength < ($packet->offset + 10)) {
throw new Net_DNS2_Exception(
'failed to parse resource record: packet too small.',
Net_DNS2_Lookups::E_PARSE_ERROR
);
}
//
// unpack the RR details
//
$object['type'] = ord($packet->rdata[$packet->offset++]) << 8 |
ord($packet->rdata[$packet->offset++]);
$object['class'] = ord($packet->rdata[$packet->offset++]) << 8 |
ord($packet->rdata[$packet->offset++]);
$object['ttl'] = ord($packet->rdata[$packet->offset++]) << 24 |
ord($packet->rdata[$packet->offset++]) << 16 |
ord($packet->rdata[$packet->offset++]) << 8 |
ord($packet->rdata[$packet->offset++]);
$object['rdlength'] = ord($packet->rdata[$packet->offset++]) << 8 |
ord($packet->rdata[$packet->offset++]);
if ($packet->rdlength < ($packet->offset + $object['rdlength'])) {
return null;
}
//
// lookup the class to use
//
$o = null;
$class = Net_DNS2_Lookups::$rr_types_id_to_class[$object['type']];
if (isset($class)) {
$o = new $class($packet, $object);
if ($o) {
$packet->offset += $object['rdlength'];
}
} else {
throw new Net_DNS2_Exception(
'un-implemented resource record type: ' . $object['type'],
Net_DNS2_Lookups::E_RR_INVALID
);
}
return $o;
}
/**
* cleans up some RR data
*
* @param string $data the text string to clean
*
* @return string returns the cleaned string
*
* @access public
*
*/
public function cleanString($data)
{
return strtolower(rtrim($data, '.'));
}
/**
* parses a standard RR format lines, as defined by rfc1035 (kinda)
*
* In our implementation, the domain *must* be specified- format must be
*
* <name> [<ttl>] [<class>] <type> <rdata>
* or
* <name> [<class>] [<ttl>] <type> <rdata>
*
* name, title, class and type are parsed by this function, rdata is passed
* to the RR specific classes for parsing.
*
* @param string $line a standard DNS config line
*
* @return mixed returns a new Net_DNS2_RR_* object for the given RR
* @throws Net_DNS2_Exception
* @access public
*
*/
public static function fromString($line)
{
if (strlen($line) == 0) {
throw new Net_DNS2_Exception(
'empty config line provided.',
Net_DNS2_Lookups::E_PARSE_ERROR
);
}
$name = '';
$type = '';
$class = 'IN';
$ttl = 86400;
//
// split the line by spaces
//
$values = preg_split('/[\s]+/', $line);
if (count($values) < 3) {
throw new Net_DNS2_Exception(
'failed to parse config: minimum of name, type and rdata required.',
Net_DNS2_Lookups::E_PARSE_ERROR
);
}
//
// assume the first value is the name
//
$name = trim(strtolower(array_shift($values)), '.');
//
// The next value is either a TTL, Class or Type
//
foreach ($values as $value) {
switch(true) {
case is_numeric($value):
$ttl = array_shift($values);
break;
//
// this is here because of a bug in is_numeric() in certain versions of
// PHP on windows.
//
case ($value === 0):
$ttl = array_shift($values);
break;
case isset(Net_DNS2_Lookups::$classes_by_name[strtoupper($value)]):
$class = strtoupper(array_shift($values));
break;
case isset(Net_DNS2_Lookups::$rr_types_by_name[strtoupper($value)]):
$type = strtoupper(array_shift($values));
break 2;
break;
default:
throw new Net_DNS2_Exception(
'invalid config line provided: unknown file: ' . $value,
Net_DNS2_Lookups::E_PARSE_ERROR
);
}
}
//
// lookup the class to use
//
$o = null;
$class_name = Net_DNS2_Lookups::$rr_types_id_to_class[
Net_DNS2_Lookups::$rr_types_by_name[$type]
];
if (isset($class_name)) {
$o = new $class_name;
if (!is_null($o)) {
//
// set the parsed values
//
$o->name = $name;
$o->class = $class;
$o->ttl = $ttl;
//
// parse the rdata
//
if ($o->rrFromString($values) === false) {
throw new Net_DNS2_Exception(
'failed to parse rdata for config: ' . $line,
Net_DNS2_Lookups::E_PARSE_ERROR
);
}
} else {
throw new Net_DNS2_Exception(
'failed to create new RR record for type: ' . $type,
Net_DNS2_Lookups::E_RR_INVALID
);
}
} else {
throw new Net_DNS2_Exception(
'un-implemented resource record type: '. $type,
Net_DNS2_Lookups::E_RR_INVALID
);
}
return $o;
}
}

108
libs/pear/Net/DNS2/RR/A.php Normal file
View File

@ -0,0 +1,108 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* A Resource Record - RFC1035 section 3.4.1
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | ADDRESS |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_A extends Net_DNS2_RR
{
/*
* The IPv4 address in quad-dotted notation
*/
public $address;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->address;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$value = array_shift($rdata);
if (Net_DNS2::isIPv4($value) == true) {
$this->address = $value;
return true;
}
return false;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$this->address = inet_ntop($this->rdata);
if ($this->address !== false) {
return true;
}
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
$packet->offset += 4;
return inet_pton($this->address);
}
}

View File

@ -0,0 +1,129 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* A Resource Record - RFC1035 section 3.4.1
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | |
* | |
* | |
* | ADDRESS |
* | |
* | (128 bit) |
* | |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_AAAA extends Net_DNS2_RR
{
/*
* the IPv6 address in the preferred hexadecimal values of the eight
* 16-bit pieces
* per RFC1884
*
*/
public $address;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->address;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
//
// expand out compressed formats
//
$value = array_shift($rdata);
if (Net_DNS2::isIPv6($value) == true) {
$this->address = $value;
return true;
}
return false;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
//
// must be 8 x 16bit chunks, or 16 x 8bit
//
if ($this->rdlength == 16) {
//
// PHP's inet_ntop returns IPv6 addresses in their compressed form,
// but we want to keep with the preferred standard, so we'll parse
// it manually.
//
$x = unpack('n8', $this->rdata);
if (count($x) == 8) {
$this->address = vsprintf('%x:%x:%x:%x:%x:%x:%x:%x', $x);
return true;
}
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
$packet->offset += 16;
return inet_pton($this->address);
}
}

View File

@ -0,0 +1,126 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* AFSDB Resource Record - RFC1183 section 1
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | SUBTYPE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / HOSTNAME /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_AFSDB extends Net_DNS2_RR
{
/*
* The AFSDB sub type
*/
public $subtype;
/*
* The AFSDB hostname
*/
public $hostname;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->subtype . ' ' . $this->cleanString($this->hostname) . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->subtype = array_shift($rdata);
$this->hostname = $this->cleanString(array_shift($rdata));
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the subtype
//
$x = unpack('nsubtype', $this->rdata);
$this->subtype = $x['subtype'];
$offset = $packet->offset + 2;
$this->hostname = Net_DNS2_Packet::expand($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->hostname) > 0) {
$data = pack('n', $this->subtype);
$packet->offset += 2;
$data .= $packet->compress($this->hostname, $packet->offset);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,259 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.4.5
*
*/
/**
* AMTRELAY Resource Record - RFC8777 section 4.2
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | precedence |D| type | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* ~ relay ~
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_AMTRELAY extends Net_DNS2_RR
{
/*
* type definitions that match the "type" field below
*/
const AMTRELAY_TYPE_NONE = 0;
const AMTRELAY_TYPE_IPV4 = 1;
const AMTRELAY_TYPE_IPV6 = 2;
const AMTRELAY_TYPE_DOMAIN = 3;
/*
* the precedence for this record
*/
public $precedence;
/*
* "Discovery Optional" flag
*/
public $discovery;
/*
* The type field indicates the format of the information that is stored in the relay field.
*/
public $relay_type;
/*
* The relay field is the address or domain name of the AMT relay.
*/
public $relay;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
$out = $this->precedence . ' ' . $this->discovery . ' ' . $this->relay_type . ' ' . $this->relay;
//
// 4.3.1 - If the relay type field is 0, the relay field MUST be ".".
//
if ( ($this->relay_type == self::AMTRELAY_TYPE_NONE) || ($this->relay_type == self::AMTRELAY_TYPE_DOMAIN) )
{
$out .= '.';
}
return $out;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
//
// extract the values from the array
//
$this->precedence = array_shift($rdata);
$this->discovery = array_shift($rdata);
$this->relay_type = array_shift($rdata);
$this->relay = trim(strtolower(trim(array_shift($rdata))), '.');
//
// if there's anything else other than 0 in the discovery value, then force it to one, so
// that it effectively is either "true" or "false".
//
if ($this->discovery != 0) {
$this->discovery = 1;
}
//
// validate the type & relay values
//
switch($this->relay_type) {
case self::AMTRELAY_TYPE_NONE:
$this->relay = '';
break;
case self::AMTRELAY_TYPE_IPV4:
if (Net_DNS2::isIPv4($this->relay) == false) {
return false;
}
break;
case self::AMTRELAY_TYPE_IPV6:
if (Net_DNS2::isIPv6($this->relay) == false) {
return false;
}
break;
case self::AMTRELAY_TYPE_DOMAIN:
; // do nothing
break;
default:
//
// invalid type value
//
return false;
}
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// parse off the first two octets
//
$x = unpack('Cprecedence/Csecond', $this->rdata);
$this->precedence = $x['precedence'];
$this->discovery = ($x['second'] >> 7) & 0x1;
$this->relay_type = $x['second'] & 0xf;
$offset = 2;
//
// parse the relay value based on the type
//
switch($this->relay_type) {
case self::AMTRELAY_TYPE_NONE:
$this->relay = '';
break;
case self::AMTRELAY_TYPE_IPV4:
$this->relay = inet_ntop(substr($this->rdata, $offset, 4));
break;
case self::AMTRELAY_TYPE_IPV6:
//
// PHP's inet_ntop returns IPv6 addresses in their compressed form, but we want to keep
// with the preferred standard, so we'll parse it manually.
//
$ip = unpack('n8', substr($this->rdata, $offset, 16));
if (count($ip) == 8) {
$this->relay = vsprintf('%x:%x:%x:%x:%x:%x:%x:%x', $ip);
} else
{
return false;
}
break;
case self::AMTRELAY_TYPE_DOMAIN:
$doffset = $packet->offset + $offset;
$this->relay = Net_DNS2_Packet::label($packet, $doffset);
break;
default:
//
// invalid type value
//
return false;
}
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
//
// pack the precedence, discovery, and type
//
$data = pack('CC', $this->precedence, ($this->discovery << 7) | $this->relay_type);
//
// add the relay data based on the type
//
switch($this->relay_type) {
case self::AMTRELAY_TYPE_NONE:
; // add nothing
break;
case self::AMTRELAY_TYPE_IPV4:
case self::AMTRELAY_TYPE_IPV6:
$data .= inet_pton($this->relay);
break;
case self::AMTRELAY_TYPE_DOMAIN:
$data .= pack('Ca*', strlen($this->relay), $this->relay);
break;
default:
return null;
}
$packet->offset += strlen($data);
return $data;
}
}

View File

@ -0,0 +1,81 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* This is only used for generating an empty ANY RR.
*
*/
class Net_DNS2_RR_ANY extends Net_DNS2_RR
{
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return '';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
return true;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
return '';
}
}

View File

@ -0,0 +1,295 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.0.0
*
*/
/**
* APL Resource Record - RFC3123
*
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | ADDRESSFAMILY |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | PREFIX | N | AFDLENGTH |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* / AFDPART /
* | |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*
*/
class Net_DNS2_RR_APL extends Net_DNS2_RR
{
/*
* a list of all the address prefix list items
*/
public $apl_items = [];
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
$out = '';
foreach ($this->apl_items as $item) {
if ($item['n'] == 1) {
$out .= '!';
}
$out .= $item['address_family'] . ':' .
$item['afd_part'] . '/' . $item['prefix'] . ' ';
}
return trim($out);
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
foreach ($rdata as $item) {
if (preg_match('/^(!?)([1|2])\:([^\/]*)\/([0-9]{1,3})$/', $item, $m)) {
$i = [
'address_family' => $m[2],
'prefix' => $m[4],
'n' => ($m[1] == '!') ? 1 : 0,
'afd_part' => strtolower($m[3])
];
$address = $this->_trimZeros(
$i['address_family'], $i['afd_part']
);
$i['afd_length'] = count(explode('.', $address));
$this->apl_items[] = $i;
}
}
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$offset = 0;
while ($offset < $this->rdlength) {
//
// unpack the family, prefix, negate and length values
//
$x = unpack(
'naddress_family/Cprefix/Cextra', substr($this->rdata, $offset)
);
$item = [
'address_family' => $x['address_family'],
'prefix' => $x['prefix'],
'n' => ($x['extra'] >> 7) & 0x1,
'afd_length' => $x['extra'] & 0xf
];
switch($item['address_family']) {
case 1:
$r = unpack(
'C*', substr($this->rdata, $offset + 4, $item['afd_length'])
);
if (count($r) < 4) {
for ($c=count($r)+1; $c<4+1; $c++) {
$r[$c] = 0;
}
}
$item['afd_part'] = implode('.', $r);
break;
case 2:
$r = unpack(
'C*', substr($this->rdata, $offset + 4, $item['afd_length'])
);
if (count($r) < 8) {
for ($c=count($r)+1; $c<8+1; $c++) {
$r[$c] = 0;
}
}
$item['afd_part'] = sprintf(
'%x:%x:%x:%x:%x:%x:%x:%x',
$r[1], $r[2], $r[3], $r[4], $r[5], $r[6], $r[7], $r[8]
);
break;
default:
return false;
}
$this->apl_items[] = $item;
$offset += 4 + $item['afd_length'];
}
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (count($this->apl_items) > 0) {
$data = '';
foreach ($this->apl_items as $item) {
//
// pack the address_family and prefix values
//
$data .= pack(
'nCC',
$item['address_family'],
$item['prefix'],
($item['n'] << 7) | $item['afd_length']
);
switch($item['address_family']) {
case 1:
$address = explode(
'.',
$this->_trimZeros($item['address_family'], $item['afd_part'])
);
foreach ($address as $b) {
$data .= chr($b);
}
break;
case 2:
$address = explode(
':',
$this->_trimZeros($item['address_family'], $item['afd_part'])
);
foreach ($address as $b) {
$data .= pack('H', $b);
}
break;
default:
return null;
}
}
$packet->offset += strlen($data);
return $data;
}
return null;
}
/**
* returns an IP address with the right-hand zero's trimmed
*
* @param integer $family the IP address family from the rdata
* @param string $address the IP address
*
* @return string the trimmed IP addresss.
*
* @access private
*
*/
private function _trimZeros($family, $address)
{
$a = [];
switch($family) {
case 1:
$a = array_reverse(explode('.', $address));
break;
case 2:
$a = array_reverse(explode(':', $address));
break;
default:
return '';
}
foreach ($a as $value) {
if ($value === '0') {
array_shift($a);
}
}
$out = '';
switch($family) {
case 1:
$out = implode('.', array_reverse($a));
break;
case 2:
$out = implode(':', array_reverse($a));
break;
default:
return '';
}
return $out;
}
}

View File

@ -0,0 +1,162 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.1.0
*
*/
/**
* ATMA Resource Record
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | FORMAT | |
* | +--+--+--+--+--+--+--+--+
* / ADDRESS /
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_ATMA extends Net_DNS2_RR
{
/*
* One octet that indicates the format of ADDRESS. The two possible values
* for FORMAT are value 0 indicating ATM End System Address (AESA) format
* and value 1 indicating E.164 format
*/
public $format;
/*
* The IPv4 address in quad-dotted notation
*/
public $address;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->address;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$value = array_shift($rdata);
if (ctype_xdigit($value) == true) {
$this->format = 0;
$this->address = $value;
} else if (is_numeric($value) == true) {
$this->format = 1;
$this->address = $value;
} else {
return false;
}
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the format
//
$x = unpack('Cformat/N*address', $this->rdata);
$this->format = $x['format'];
if ($this->format == 0) {
$a = unpack('@1/H*address', $this->rdata);
$this->address = $a['address'];
} else if ($this->format == 1) {
$this->address = substr($this->rdata, 1, $this->rdlength - 1);
} else {
return false;
}
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
$data = chr($this->format);
if ($this->format == 0) {
$data .= pack('H*', $this->address);
} else if ($this->format == 1) {
$data .= $this->address;
} else {
return null;
}
$packet->offset += strlen($data);
return $data;
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.4.2
*
*/
/**
* The AVC RR is implemented exactly like the TXT record, so
* for now we just extend the TXT RR and use it.
*
*/
class Net_DNS2_RR_AVC extends Net_DNS2_RR_TXT
{
}

View File

@ -0,0 +1,138 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.2.0
*
*/
/**
* CAA Resource Record - http://tools.ietf.org/html/draft-ietf-pkix-caa-03
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | FLAGS | TAG LENGTH |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / TAG /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / DATA /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_CAA extends Net_DNS2_RR
{
/*
* The critcal flag
*/
public $flags;
/*
* The property identifier
*/
public $tag;
/*
* The property value
*/
public $value;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->flags . ' ' . $this->tag . ' "' .
trim($this->cleanString($this->value), '"') . '"';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->flags = array_shift($rdata);
$this->tag = array_shift($rdata);
$this->value = trim($this->cleanString(implode(' ', $rdata)), '"');
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the flags and tag length
//
$x = unpack('Cflags/Ctag_length', $this->rdata);
$this->flags = $x['flags'];
$offset = 2;
$this->tag = substr($this->rdata, $offset, $x['tag_length']);
$offset += $x['tag_length'];
$this->value = substr($this->rdata, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->value) > 0) {
$data = chr($this->flags);
$data .= chr(strlen($this->tag)) . $this->tag . $this->value;
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,29 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.4.0
*
*/
/**
* The CDNSKEY RR is implemented exactly like the DNSKEY record, so
* for now we just extend the DNSKEY RR and use it.
*
* http://www.rfc-editor.org/rfc/rfc7344.txt
*
*/
class Net_DNS2_RR_CDNSKEY extends Net_DNS2_RR_DNSKEY
{
}

View File

@ -0,0 +1,29 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.2.0
*
*/
/**
* The CDS RR is implemented exactly like the DS record, so
* for now we just extend the DS RR and use it.
*
* http://www.rfc-editor.org/rfc/rfc7344.txt
*
*/
class Net_DNS2_RR_CDS extends Net_DNS2_RR_DS
{
}

View File

@ -0,0 +1,243 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* CERT Resource Record - RFC4398 section 2
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | format | key tag |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | algorithm | /
* +---------------+ certificate or CRL /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
*
*/
class Net_DNS2_RR_CERT extends Net_DNS2_RR
{
/*
* format's allowed for certificates
*/
const CERT_FORMAT_RES = 0;
const CERT_FORMAT_PKIX = 1;
const CERT_FORMAT_SPKI = 2;
const CERT_FORMAT_PGP = 3;
const CERT_FORMAT_IPKIX = 4;
const CERT_FORMAT_ISPKI = 5;
const CERT_FORMAT_IPGP = 6;
const CERT_FORMAT_ACPKIX = 7;
const CERT_FORMAT_IACPKIX = 8;
const CERT_FORMAT_URI = 253;
const CERT_FORMAT_OID = 254;
public $cert_format_name_to_id = [];
public $cert_format_id_to_name = [
self::CERT_FORMAT_RES => 'Reserved',
self::CERT_FORMAT_PKIX => 'PKIX',
self::CERT_FORMAT_SPKI => 'SPKI',
self::CERT_FORMAT_PGP => 'PGP',
self::CERT_FORMAT_IPKIX => 'IPKIX',
self::CERT_FORMAT_ISPKI => 'ISPKI',
self::CERT_FORMAT_IPGP => 'IPGP',
self::CERT_FORMAT_ACPKIX => 'ACPKIX',
self::CERT_FORMAT_IACPKIX => 'IACPKIX',
self::CERT_FORMAT_URI => 'URI',
self::CERT_FORMAT_OID => 'OID'
];
/*
* certificate format
*/
public $format;
/*
* key tag
*/
public $keytag;
/*
* The algorithm used for the CERt
*/
public $algorithm;
/*
* certificate
*/
public $certificate;
/**
* we have our own constructor so that we can load our certificate
* information for parsing.
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
* @param array $rr a array with parsed RR values
*
* @return
*
*/
public function __construct(Net_DNS2_Packet &$packet = null, array $rr = null)
{
parent::__construct($packet, $rr);
//
// load the lookup values
//
$this->cert_format_name_to_id = array_flip($this->cert_format_id_to_name);
}
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->format . ' ' . $this->keytag . ' ' . $this->algorithm .
' ' . base64_encode($this->certificate);
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
//
// load and check the format; can be an int, or a mnemonic symbol
//
$this->format = array_shift($rdata);
if (!is_numeric($this->format)) {
$mnemonic = strtoupper(trim($this->format));
if (!isset($this->cert_format_name_to_id[$mnemonic])) {
return false;
}
$this->format = $this->cert_format_name_to_id[$mnemonic];
} else {
if (!isset($this->cert_format_id_to_name[$this->format])) {
return false;
}
}
$this->keytag = array_shift($rdata);
//
// parse and check the algorithm; can be an int, or a mnemonic symbol
//
$this->algorithm = array_shift($rdata);
if (!is_numeric($this->algorithm)) {
$mnemonic = strtoupper(trim($this->algorithm));
if (!isset(Net_DNS2_Lookups::$algorithm_name_to_id[$mnemonic])) {
return false;
}
$this->algorithm = Net_DNS2_Lookups::$algorithm_name_to_id[
$mnemonic
];
} else {
if (!isset(Net_DNS2_Lookups::$algorithm_id_to_name[$this->algorithm])) {
return false;
}
}
//
// parse and base64 decode the certificate
//
// certificates MUST be provided base64 encoded, if not, everything will
// be broken after this point, as we assume it's base64 encoded.
//
$this->certificate = base64_decode(implode(' ', $rdata));
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the format, keytag and algorithm
//
$x = unpack('nformat/nkeytag/Calgorithm', $this->rdata);
$this->format = $x['format'];
$this->keytag = $x['keytag'];
$this->algorithm = $x['algorithm'];
//
// copy the certificate
//
$this->certificate = substr($this->rdata, 5, $this->rdlength - 5);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->certificate) > 0) {
$data = pack('nnC', $this->format, $this->keytag, $this->algorithm) . $this->certificate;
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,105 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* CNAME Resource Record - RFC1035 section 3.3.1
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / CNAME /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_CNAME extends Net_DNS2_RR
{
/*
* The canonical name
*/
public $cname;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->cleanString($this->cname) . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->cname = $this->cleanString(array_shift($rdata));
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$offset = $packet->offset;
$this->cname = Net_DNS2_Packet::expand($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->cname) > 0) {
return $packet->compress($this->cname, $packet->offset);
}
return null;
}
}

View File

@ -0,0 +1,155 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.4.1
*
*/
/**
* CSYNC Resource Record - RFC 7477 seciond 2.1.1
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | SOA Serial |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | Flags |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / Type Bit Map /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_CSYNC extends Net_DNS2_RR
{
/*
* serial number
*/
public $serial;
/*
* flags
*/
public $flags;
/*
* array of RR type names
*/
public $type_bit_maps = [];
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
$out = $this->serial . ' ' . $this->flags;
//
// show the RR's
//
foreach ($this->type_bit_maps as $rr) {
$out .= ' ' . strtoupper($rr);
}
return $out;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->serial = array_shift($rdata);
$this->flags = array_shift($rdata);
$this->type_bit_maps = $rdata;
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the serial and flags values
//
$x = unpack('@' . $packet->offset . '/Nserial/nflags', $packet->rdata);
$this->serial = Net_DNS2::expandUint32($x['serial']);
$this->flags = $x['flags'];
//
// parse out the RR bitmap
//
$this->type_bit_maps = Net_DNS2_BitMap::bitMapToArray(
substr($this->rdata, 6)
);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
//
// pack the serial and flags values
//
$data = pack('Nn', $this->serial, $this->flags);
//
// convert the array of RR names to a type bitmap
//
$data .= Net_DNS2_BitMap::arrayToBitMap($this->type_bit_maps);
//
// advance the offset
//
$packet->offset += strlen($data);
return $data;
}
}

View File

@ -0,0 +1,159 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* DHCID Resource Record - RFC4701 section 3.1
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | ID Type Code |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | Digest Type | /
* +--+--+--+--+--+--+--+--+ /
* / /
* / Digest /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_DHCID extends Net_DNS2_RR
{
/*
* Identifier type
*/
public $id_type;
/*
* Digest Type
*/
public $digest_type;
/*
* The digest
*/
public $digest;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
$out = pack('nC', $this->id_type, $this->digest_type);
$out .= base64_decode($this->digest);
return base64_encode($out);
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$data = base64_decode(array_shift($rdata));
if (strlen($data) > 0) {
//
// unpack the id type and digest type
//
$x = unpack('nid_type/Cdigest_type', $data);
$this->id_type = $x['id_type'];
$this->digest_type = $x['digest_type'];
//
// copy out the digest
//
$this->digest = base64_encode(substr($data, 3, strlen($data) - 3));
return true;
}
return false;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the id type and digest type
//
$x = unpack('nid_type/Cdigest_type', $this->rdata);
$this->id_type = $x['id_type'];
$this->digest_type = $x['digest_type'];
//
// copy out the digest
//
$this->digest = base64_encode(
substr($this->rdata, 3, $this->rdlength - 3)
);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->digest) > 0) {
$data = pack('nC', $this->id_type, $this->digest_type) .
base64_decode($this->digest);
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* The DLV RR is implemented exactly like the DS RR; so we just extend that
* class, and use all of it's methods
*
*/
class Net_DNS2_RR_DLV extends Net_DNS2_RR_DS
{
}

View File

@ -0,0 +1,105 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* DNAME Resource Record - RFC2672 section 3
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / DNAME /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_DNAME extends Net_DNS2_RR
{
/*
* The target name
*/
public $dname;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->cleanString($this->dname) . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->dname = $this->cleanString(array_shift($rdata));
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$offset = $packet->offset;
$this->dname = Net_DNS2_Packet::expand($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->dname) > 0) {
return $packet->compress($this->dname, $packet->offset);
}
return null;
}
}

View File

@ -0,0 +1,150 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* DNSKEY Resource Record - RFC4034 sction 2.1
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Flags | Protocol | Algorithm |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* / /
* / Public Key /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_DNSKEY extends Net_DNS2_RR
{
/*
* flags
*/
public $flags;
/*
* protocol
*/
public $protocol;
/*
* algorithm used
*/
public $algorithm;
/*
* the public key
*/
public $key;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->flags . ' ' . $this->protocol . ' ' .
$this->algorithm . ' ' . $this->key;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->flags = array_shift($rdata);
$this->protocol = array_shift($rdata);
$this->algorithm = array_shift($rdata);
$this->key = implode(' ', $rdata);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the flags, protocol and algorithm
//
$x = unpack('nflags/Cprotocol/Calgorithm', $this->rdata);
//
// TODO: right now we're just displaying what's in DNS; we really
// should be parsing bit 7 and bit 15 of the flags field, and store
// those separately.
//
// right now the DNSSEC implementation is really just for display,
// we don't validate or handle any of the keys
//
$this->flags = $x['flags'];
$this->protocol = $x['protocol'];
$this->algorithm = $x['algorithm'];
$this->key = base64_encode(substr($this->rdata, 4));
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->key) > 0) {
$data = pack('nCC', $this->flags, $this->protocol, $this->algorithm);
$data .= base64_decode($this->key);
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,139 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* DS Resource Record - RFC4034 sction 5.1
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Key Tag | Algorithm | Digest Type |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* / /
* / Digest /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_DS extends Net_DNS2_RR
{
/*
* key tag
*/
public $keytag;
/*
* algorithm number
*/
public $algorithm;
/*
* algorithm used to construct the digest
*/
public $digesttype;
/*
* the digest data
*/
public $digest;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->keytag . ' ' . $this->algorithm . ' ' . $this->digesttype . ' ' . $this->digest;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->keytag = array_shift($rdata);
$this->algorithm = array_shift($rdata);
$this->digesttype = array_shift($rdata);
$this->digest = implode('', $rdata);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the keytag, algorithm and digesttype
//
$x = unpack('nkeytag/Calgorithm/Cdigesttype/H*digest', $this->rdata);
$this->keytag = $x['keytag'];
$this->algorithm = $x['algorithm'];
$this->digesttype = $x['digesttype'];
$this->digest = $x['digest'];
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->digest) > 0) {
$data = pack('nCCH*', $this->keytag, $this->algorithm, $this->digesttype, $this->digest);
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,82 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* EID Resource Record - undefined; the rdata is simply used as-is in it's
* binary format, so not process has to be done.
*
*/
class Net_DNS2_RR_EID extends Net_DNS2_RR
{
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return '';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
return true;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
return $this->rdata;
}
}

View File

@ -0,0 +1,139 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.3.2
*
*/
/**
* EUI48 Resource Record - RFC7043 section 3.1
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | EUI-48 Address |
* | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_EUI48 extends Net_DNS2_RR
{
/*
* The EUI48 address, in hex format
*/
public $address;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->address;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$value = array_shift($rdata);
//
// re: RFC 7043, the field must be represented as six two-digit hex numbers
// separated by hyphens.
//
$a = explode('-', $value);
if (count($a) != 6) {
return false;
}
//
// make sure they're all hex values
//
foreach ($a as $i) {
if (ctype_xdigit($i) == false) {
return false;
}
}
//
// store it
//
$this->address = strtolower($value);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$x = unpack('C6', $this->rdata);
if (count($x) == 6) {
$this->address = vsprintf('%02x-%02x-%02x-%02x-%02x-%02x', $x);
return true;
}
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
$data = '';
$a = explode('-', $this->address);
foreach ($a as $b) {
$data .= chr(hexdec($b));
}
$packet->offset += 6;
return $data;
}
}

View File

@ -0,0 +1,140 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.3.2
*
*/
/**
* EUI64 Resource Record - RFC7043 section 4.1
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | EUI-64 Address |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_EUI64 extends Net_DNS2_RR
{
/*
* The EUI64 address, in hex format
*/
public $address;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->address;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$value = array_shift($rdata);
//
// re: RFC 7043, the field must be represented as 8 two-digit hex numbers
// separated by hyphens.
//
$a = explode('-', $value);
if (count($a) != 8) {
return false;
}
//
// make sure they're all hex values
//
foreach ($a as $i) {
if (ctype_xdigit($i) == false) {
return false;
}
}
//
// store it
//
$this->address = strtolower($value);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$x = unpack('C8', $this->rdata);
if (count($x) == 8) {
$this->address = vsprintf(
'%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x', $x
);
return true;
}
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
$data = '';
$a = explode('-', $this->address);
foreach ($a as $b) {
$data .= chr(hexdec($b));
}
$packet->offset += 8;
return $data;
}
}

View File

@ -0,0 +1,125 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* HINFO Resource Record - RFC1035 section 3.3.2
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / CPU /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / OS /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_HINFO extends Net_DNS2_RR
{
/*
* computer informatino
*/
public $cpu;
/*
* operataing system
*/
public $os;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->formatString($this->cpu) . ' ' . $this->formatString($this->os);
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$data = $this->buildString($rdata);
if (count($data) == 2) {
$this->cpu = trim($data[0], '"');
$this->os = trim($data[1], '"');
return true;
}
return false;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$offset = $packet->offset;
$this->cpu = Net_DNS2_Packet::label($packet, $offset);
$this->os = Net_DNS2_Packet::label($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->cpu) > 0) {
$data = pack('Ca*Ca*', strlen($this->cpu), $this->cpu, strlen($this->os), $this->os);
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,239 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.0.0
*
*/
/**
* HIP Resource Record - RFC5205 section 5
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | HIT length | PK algorithm | PK length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* ~ HIT ~
* | |
* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | | |
* +-+-+-+-+-+-+-+-+-+-+-+ +
* | Public Key |
* ~ ~
* | |
* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | |
* ~ Rendezvous Servers ~
* | |
* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_HIP extends Net_DNS2_RR
{
/*
* The length of the HIT field
*/
public $hit_length;
/*
* the public key cryptographic algorithm
*/
public $pk_algorithm;
/*
* the length of the public key field
*/
public $pk_length;
/*
* The HIT is stored as a binary value in network byte order.
*/
public $hit;
/*
* The public key
*/
public $public_key;
/*
* a list of rendezvous servers
*/
public $rendezvous_servers = [];
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
$out = $this->pk_algorithm . ' ' .
$this->hit . ' ' . $this->public_key . ' ';
foreach ($this->rendezvous_servers as $index => $server) {
$out .= $server . '. ';
}
return trim($out);
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->pk_algorithm = array_shift($rdata);
$this->hit = strtoupper(array_shift($rdata));
$this->public_key = array_shift($rdata);
//
// anything left on the array, must be one or more rendezevous servers. add
// them and strip off the trailing dot
//
if (count($rdata) > 0) {
$this->rendezvous_servers = preg_replace('/\.$/', '', $rdata);
}
//
// store the lengths;
//
$this->hit_length = strlen(pack('H*', $this->hit));
$this->pk_length = strlen(base64_decode($this->public_key));
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the algorithm and length values
//
$x = unpack('Chit_length/Cpk_algorithm/npk_length', $this->rdata);
$this->hit_length = $x['hit_length'];
$this->pk_algorithm = $x['pk_algorithm'];
$this->pk_length = $x['pk_length'];
$offset = 4;
//
// copy out the HIT value
//
$hit = unpack('H*', substr($this->rdata, $offset, $this->hit_length));
$this->hit = strtoupper($hit[1]);
$offset += $this->hit_length;
//
// copy out the public key
//
$this->public_key = base64_encode(
substr($this->rdata, $offset, $this->pk_length)
);
$offset += $this->pk_length;
//
// copy out any possible rendezvous servers
//
$offset = $packet->offset + $offset;
while ( ($offset - $packet->offset) < $this->rdlength) {
$this->rendezvous_servers[] = Net_DNS2_Packet::expand(
$packet, $offset
);
}
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if ( (strlen($this->hit) > 0) && (strlen($this->public_key) > 0) ) {
//
// pack the length, algorithm and HIT values
//
$data = pack(
'CCnH*',
$this->hit_length,
$this->pk_algorithm,
$this->pk_length,
$this->hit
);
//
// add the public key
//
$data .= base64_decode($this->public_key);
//
// add the offset
//
$packet->offset += strlen($data);
//
// add each rendezvous server
//
foreach ($this->rendezvous_servers as $index => $server) {
$data .= $packet->compress($server, $packet->offset);
}
return $data;
}
return null;
}
}

View File

@ -0,0 +1,338 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* IPSECKEY Resource Record - RFC4025 section 2.1
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | precedence | gateway type | algorithm | gateway |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------+ +
* ~ gateway ~
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | /
* / public key /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
*
*/
class Net_DNS2_RR_IPSECKEY extends Net_DNS2_RR
{
const GATEWAY_TYPE_NONE = 0;
const GATEWAY_TYPE_IPV4 = 1;
const GATEWAY_TYPE_IPV6 = 2;
const GATEWAY_TYPE_DOMAIN = 3;
const ALGORITHM_NONE = 0;
const ALGORITHM_DSA = 1;
const ALGORITHM_RSA = 2;
/*
* Precedence (used the same was as a preference field)
*/
public $precedence;
/*
* Gateway type - specifies the format of the gataway information
* This can be either:
*
* 0 No Gateway
* 1 IPv4 address
* 2 IPV6 address
* 3 wire-encoded domain name (not compressed)
*
*/
public $gateway_type;
/*
* The algorithm used
*
* This can be:
*
* 0 No key is present
* 1 DSA key is present
* 2 RSA key is present
*
*/
public $algorithm;
/*
* The gatway information
*/
public $gateway;
/*
* the public key
*/
public $key;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
$out = $this->precedence . ' ' . $this->gateway_type . ' ' .
$this->algorithm . ' ';
switch($this->gateway_type) {
case self::GATEWAY_TYPE_NONE:
$out .= '. ';
break;
case self::GATEWAY_TYPE_IPV4:
case self::GATEWAY_TYPE_IPV6:
$out .= $this->gateway . ' ';
break;
case self::GATEWAY_TYPE_DOMAIN:
$out .= $this->gateway . '. ';
break;
}
$out .= $this->key;
return $out;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
//
// load the data
//
$precedence = array_shift($rdata);
$gateway_type = array_shift($rdata);
$algorithm = array_shift($rdata);
$gateway = trim(strtolower(trim(array_shift($rdata))), '.');
$key = array_shift($rdata);
//
// validate it
//
switch($gateway_type) {
case self::GATEWAY_TYPE_NONE:
$gateway = '';
break;
case self::GATEWAY_TYPE_IPV4:
if (Net_DNS2::isIPv4($gateway) == false) {
return false;
}
break;
case self::GATEWAY_TYPE_IPV6:
if (Net_DNS2::isIPv6($gateway) == false) {
return false;
}
break;
case self::GATEWAY_TYPE_DOMAIN:
; // do nothing
break;
default:
return false;
}
//
// check the algorithm and key
//
switch($algorithm) {
case self::ALGORITHM_NONE:
$key = '';
break;
case self::ALGORITHM_DSA:
case self::ALGORITHM_RSA:
; // do nothing
break;
default:
return false;
}
//
// store the values
//
$this->precedence = $precedence;
$this->gateway_type = $gateway_type;
$this->algorithm = $algorithm;
$this->gateway = $gateway;
$this->key = $key;
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// parse off the precedence, gateway type and algorithm
//
$x = unpack('Cprecedence/Cgateway_type/Calgorithm', $this->rdata);
$this->precedence = $x['precedence'];
$this->gateway_type = $x['gateway_type'];
$this->algorithm = $x['algorithm'];
$offset = 3;
//
// extract the gatway based on the type
//
switch($this->gateway_type) {
case self::GATEWAY_TYPE_NONE:
$this->gateway = '';
break;
case self::GATEWAY_TYPE_IPV4:
$this->gateway = inet_ntop(substr($this->rdata, $offset, 4));
$offset += 4;
break;
case self::GATEWAY_TYPE_IPV6:
$ip = unpack('n8', substr($this->rdata, $offset, 16));
if (count($ip) == 8) {
$this->gateway = vsprintf('%x:%x:%x:%x:%x:%x:%x:%x', $ip);
$offset += 16;
} else {
return false;
}
break;
case self::GATEWAY_TYPE_DOMAIN:
$doffset = $offset + $packet->offset;
$this->gateway = Net_DNS2_Packet::expand($packet, $doffset);
$offset = ($doffset - $packet->offset);
break;
default:
return false;
}
//
// extract the key
//
switch($this->algorithm) {
case self::ALGORITHM_NONE:
$this->key = '';
break;
case self::ALGORITHM_DSA:
case self::ALGORITHM_RSA:
$this->key = base64_encode(substr($this->rdata, $offset));
break;
default:
return false;
}
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
//
// pack the precedence, gateway type and algorithm
//
$data = pack(
'CCC', $this->precedence, $this->gateway_type, $this->algorithm
);
//
// add the gateway based on the type
//
switch($this->gateway_type) {
case self::GATEWAY_TYPE_NONE:
; // add nothing
break;
case self::GATEWAY_TYPE_IPV4:
case self::GATEWAY_TYPE_IPV6:
$data .= inet_pton($this->gateway);
break;
case self::GATEWAY_TYPE_DOMAIN:
$data .= chr(strlen($this->gateway)) . $this->gateway;
break;
default:
return null;
}
//
// add the key if there's one specified
//
switch($this->algorithm) {
case self::ALGORITHM_NONE:
; // add nothing
break;
case self::ALGORITHM_DSA:
case self::ALGORITHM_RSA:
$data .= base64_decode($this->key);
break;
default:
return null;
}
$packet->offset += strlen($data);
return $data;
}
}

View File

@ -0,0 +1,142 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* ISDN Resource Record - RFC1183 section 3.2
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / ISDN-address /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / SA /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_ISDN extends Net_DNS2_RR
{
/*
* ISDN Number
*/
public $isdnaddress;
/*
* Sub-Address
*/
public $sa;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->formatString($this->isdnaddress) . ' ' .
$this->formatString($this->sa);
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$data = $this->buildString($rdata);
if (count($data) >= 1) {
$this->isdnaddress = $data[0];
if (isset($data[1])) {
$this->sa = $data[1];
}
return true;
}
return false;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$this->isdnaddress = Net_DNS2_Packet::label($packet, $packet->offset);
//
// look for a SA (sub address) - it's optional
//
if ( (strlen($this->isdnaddress) + 1) < $this->rdlength) {
$this->sa = Net_DNS2_Packet::label($packet, $packet->offset);
} else {
$this->sa = '';
}
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->isdnaddress) > 0) {
$data = chr(strlen($this->isdnaddress)) . $this->isdnaddress;
if (!empty($this->sa)) {
$data .= chr(strlen($this->sa));
$data .= $this->sa;
}
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,37 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* the KEY RR is implemented the same as the DNSKEY RR, the only difference
* is how the flags data is parsed.
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | A/C | Z | XT| Z | Z | NAMTYP| Z | Z | Z | Z | SIG |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*
* DNSKEY only uses bits 7 and 15
*
* We're not doing anything with these flags right now, so duplicating the
* class like this is fine.
*
*/
class Net_DNS2_RR_KEY extends Net_DNS2_RR_DNSKEY
{
}

View File

@ -0,0 +1,131 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* KX Resource Record - RFC2230 section 3.1
*
* This class is almost identical to MX, except that the the exchanger
* domain is not compressed, it's added as a label
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | PREFERENCE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / EXCHANGER /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_KX extends Net_DNS2_RR
{
/*
* the preference for this mail exchanger
*/
public $preference;
/*
* the hostname of the mail exchanger
*/
public $exchange;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->preference . ' ' . $this->cleanString($this->exchange) . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->preference = array_shift($rdata);
$this->exchange = $this->cleanString(array_shift($rdata));
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// parse the preference
//
$x = unpack('npreference', $this->rdata);
$this->preference = $x['preference'];
//
// get the exchange entry server)
//
$offset = $packet->offset + 2;
$this->exchange = Net_DNS2_Packet::label($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->exchange) > 0) {
$data = pack('nC', $this->preference, strlen($this->exchange)) .
$this->exchange;
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,132 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.3.1
*
*/
/**
* L32 Resource Record - RFC6742 section 2.2
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Preference | Locator32 (16 MSBs) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Locator32 (16 LSBs) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_L32 extends Net_DNS2_RR
{
/*
* The preference
*/
public $preference;
/*
* The locator32 field
*/
public $locator32;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->preference . ' ' . $this->locator32;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->preference = array_shift($rdata);
$this->locator32 = array_shift($rdata);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the values
//
$x = unpack('npreference/C4locator', $this->rdata);
$this->preference = $x['preference'];
//
// build the locator value
//
$this->locator32 = $x['locator1'] . '.' . $x['locator2'] . '.' .
$x['locator3'] . '.' . $x['locator4'];
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->locator32) > 0) {
//
// break out the locator value
//
$n = explode('.', $this->locator32);
//
// pack the data
//
return pack('nC4', $this->preference, $n[0], $n[1], $n[2], $n[3]);
}
return null;
}
}

View File

@ -0,0 +1,139 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.3.1
*
*/
/**
* L64 Resource Record - RFC6742 section 2.3
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Preference | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | Locator64 |
* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_L64 extends Net_DNS2_RR
{
/*
* The preference
*/
public $preference;
/*
* The locator64 field
*/
public $locator64;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->preference . ' ' . $this->locator64;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->preference = array_shift($rdata);
$this->locator64 = array_shift($rdata);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the values
//
$x = unpack('npreference/n4locator', $this->rdata);
$this->preference = $x['preference'];
//
// build the locator64
//
$this->locator64 = dechex($x['locator1']) . ':' .
dechex($x['locator2']) . ':' .
dechex($x['locator3']) . ':' .
dechex($x['locator4']);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->locator64) > 0) {
//
// break out the locator64
//
$n = explode(':', $this->locator64);
//
// pack the data
//
return pack(
'n5', $this->preference, hexdec($n[0]), hexdec($n[1]),
hexdec($n[2]), hexdec($n[3])
);
}
return null;
}
}

View File

@ -0,0 +1,392 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* LOC Resource Record - RFC1876 section 2
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | VERSION | SIZE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | HORIZ PRE | VERT PRE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | LATITUDE |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | LONGITUDE |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | ALTITUDE |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_LOC extends Net_DNS2_RR
{
/*
* the LOC version- should only ever be 0
*/
public $version;
/*
* The diameter of a sphere enclosing the described entity
*/
public $size;
/*
* The horizontal precision of the data
*/
public $horiz_pre;
/*
* The vertical precision of the data
*/
public $vert_pre;
/*
* The latitude - stored in decimal degrees
*/
public $latitude;
/*
* The longitude - stored in decimal degrees
*/
public $longitude;
/*
* The altitude - stored in decimal
*/
public $altitude;
/*
* used for quick power-of-ten lookups
*/
private $_powerOfTen = [ 1, 10, 100, 1000, 10000, 100000,
1000000,10000000,100000000,1000000000 ];
/*
* some conversion values
*/
const CONV_SEC = 1000;
const CONV_MIN = 60000;
const CONV_DEG = 3600000;
const REFERENCE_ALT = 10000000;
const REFERENCE_LATLON = 2147483648;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
if ($this->version == 0) {
return $this->_d2Dms($this->latitude, 'LAT') . ' ' .
$this->_d2Dms($this->longitude, 'LNG') . ' ' .
sprintf('%.2fm', $this->altitude) . ' ' .
sprintf('%.2fm', $this->size) . ' ' .
sprintf('%.2fm', $this->horiz_pre) . ' ' .
sprintf('%.2fm', $this->vert_pre);
}
return '';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
//
// format as defined by RFC1876 section 3
//
// d1 [m1 [s1]] {"N"|"S"} d2 [m2 [s2]] {"E"|"W"} alt["m"]
// [siz["m"] [hp["m"] [vp["m"]]]]
//
$res = preg_match(
'/^(\d+) \s+((\d+) \s+)?(([\d.]+) \s+)?(N|S) \s+(\d+) ' .
'\s+((\d+) \s+)?(([\d.]+) \s+)?(E|W) \s+(-?[\d.]+) m?(\s+ ' .
'([\d.]+) m?)?(\s+ ([\d.]+) m?)?(\s+ ([\d.]+) m?)?/ix',
implode(' ', $rdata), $x
);
if ($res) {
//
// latitude
//
$latdeg = $x[1];
$latmin = (isset($x[3])) ? $x[3] : 0;
$latsec = (isset($x[5])) ? $x[5] : 0;
$lathem = strtoupper($x[6]);
$this->latitude = $this->_dms2d($latdeg, $latmin, $latsec, $lathem);
//
// longitude
//
$londeg = $x[7];
$lonmin = (isset($x[9])) ? $x[9] : 0;
$lonsec = (isset($x[11])) ? $x[11] : 0;
$lonhem = strtoupper($x[12]);
$this->longitude = $this->_dms2d($londeg, $lonmin, $lonsec, $lonhem);
//
// the rest of teh values
//
$version = 0;
$this->size = (isset($x[15])) ? $x[15] : 1;
$this->horiz_pre = ((isset($x[17])) ? $x[17] : 10000);
$this->vert_pre = ((isset($x[19])) ? $x[19] : 10);
$this->altitude = $x[13];
return true;
}
return false;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack all the values
//
$x = unpack(
'Cver/Csize/Choriz_pre/Cvert_pre/Nlatitude/Nlongitude/Naltitude',
$this->rdata
);
//
// version must be 0 per RFC 1876 section 2
//
$this->version = $x['ver'];
if ($this->version == 0) {
$this->size = $this->_precsizeNtoA($x['size']);
$this->horiz_pre = $this->_precsizeNtoA($x['horiz_pre']);
$this->vert_pre = $this->_precsizeNtoA($x['vert_pre']);
//
// convert the latitude and longitude to degress in decimal
//
if ($x['latitude'] < 0) {
$this->latitude = ($x['latitude'] +
self::REFERENCE_LATLON) / self::CONV_DEG;
} else {
$this->latitude = ($x['latitude'] -
self::REFERENCE_LATLON) / self::CONV_DEG;
}
if ($x['longitude'] < 0) {
$this->longitude = ($x['longitude'] +
self::REFERENCE_LATLON) / self::CONV_DEG;
} else {
$this->longitude = ($x['longitude'] -
self::REFERENCE_LATLON) / self::CONV_DEG;
}
//
// convert down the altitude
//
$this->altitude = ($x['altitude'] - self::REFERENCE_ALT) / 100;
return true;
} else {
return false;
}
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if ($this->version == 0) {
$lat = 0;
$lng = 0;
if ($this->latitude < 0) {
$lat = ($this->latitude * self::CONV_DEG) - self::REFERENCE_LATLON;
} else {
$lat = ($this->latitude * self::CONV_DEG) + self::REFERENCE_LATLON;
}
if ($this->longitude < 0) {
$lng = ($this->longitude * self::CONV_DEG) - self::REFERENCE_LATLON;
} else {
$lng = ($this->longitude * self::CONV_DEG) + self::REFERENCE_LATLON;
}
$packet->offset += 16;
return pack(
'CCCCNNN',
$this->version,
$this->_precsizeAtoN($this->size),
$this->_precsizeAtoN($this->horiz_pre),
$this->_precsizeAtoN($this->vert_pre),
$lat, $lng,
($this->altitude * 100) + self::REFERENCE_ALT
);
}
return null;
}
/**
* takes an XeY precision/size value, returns a string representation.
* shamlessly stolen from RFC1876 Appendix A
*
* @param integer $prec the value to convert
*
* @return string
* @access private
*
*/
private function _precsizeNtoA($prec)
{
$mantissa = (($prec >> 4) & 0x0f) % 10;
$exponent = (($prec >> 0) & 0x0f) % 10;
return $mantissa * $this->_powerOfTen[$exponent];
}
/**
* converts ascii size/precision X * 10**Y(cm) to 0xXY.
* shamlessly stolen from RFC1876 Appendix A
*
* @param string $prec the value to convert
*
* @return integer
* @access private
*
*/
private function _precsizeAtoN($prec)
{
$exponent = 0;
while ($prec >= 10) {
$prec /= 10;
++$exponent;
}
return ($prec << 4) | ($exponent & 0x0f);
}
/**
* convert lat/lng in deg/min/sec/hem to decimal value
*
* @param integer $deg the degree value
* @param integer $min the minutes value
* @param integer $sec the seconds value
* @param string $hem the hemisphere (N/E/S/W)
*
* @return float the decinmal value
* @access private
*
*/
private function _dms2d($deg, $min, $sec, $hem)
{
$deg = $deg - 0;
$min = $min - 0;
$sign = ($hem == 'W' || $hem == 'S') ? -1 : 1;
return ((($sec/60+$min)/60)+$deg) * $sign;
}
/**
* convert lat/lng in decimal to deg/min/sec/hem
*
* @param float $data the decimal value
* @param string $latlng either LAT or LNG so we can determine the HEM value
*
* @return string
* @access private
*
*/
private function _d2Dms($data, $latlng)
{
$deg = 0;
$min = 0;
$sec = 0;
$msec = 0;
$hem = '';
if ($latlng == 'LAT') {
$hem = ($data > 0) ? 'N' : 'S';
} else {
$hem = ($data > 0) ? 'E' : 'W';
}
$data = abs($data);
$deg = (int)$data;
$min = (int)(($data - $deg) * 60);
$sec = (int)(((($data - $deg) * 60) - $min) * 60);
$msec = round((((((($data - $deg) * 60) - $min) * 60) - $sec) * 1000));
return sprintf('%d %02d %02d.%03d %s', $deg, $min, $sec, round($msec), $hem);
}
}

View File

@ -0,0 +1,129 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.3.1
*
*/
/**
* LP Resource Record - RFC6742 section 2.4
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Preference | /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
* / /
* / FQDN /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_LP extends Net_DNS2_RR
{
/*
* The preference
*/
public $preference;
/*
* The fdqn field
*/
public $fqdn;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->preference . ' ' . $this->fqdn . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->preference = array_shift($rdata);
$this->fqdn = trim(array_shift($rdata), '.');
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// parse the preference
//
$x = unpack('npreference', $this->rdata);
$this->preference = $x['preference'];
$offset = $packet->offset + 2;
//
// get the hostname
//
$this->fqdn = Net_DNS2_Packet::expand($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->fqdn) > 0) {
$data = pack('n', $this->preference);
$packet->offset += 2;
$data .= $packet->compress($this->fqdn, $packet->offset);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,127 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* MX Resource Record - RFC1035 section 3.3.9
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | PREFERENCE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / EXCHANGE /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_MX extends Net_DNS2_RR
{
/*
* the preference for this mail exchanger
*/
public $preference;
/*
* the hostname of the mail exchanger
*/
public $exchange;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->preference . ' ' . $this->cleanString($this->exchange) . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->preference = array_shift($rdata);
$this->exchange = $this->cleanString(array_shift($rdata));
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// parse the preference
//
$x = unpack('npreference', $this->rdata);
$this->preference = $x['preference'];
//
// get the exchange entry server)
//
$offset = $packet->offset + 2;
$this->exchange = Net_DNS2_Packet::expand($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->exchange) > 0) {
$data = pack('n', $this->preference);
$packet->offset += 2;
$data .= $packet->compress($this->exchange, $packet->offset);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,183 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* NAPTR Resource Record - RFC2915
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | ORDER |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | PREFERENCE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / FLAGS /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / SERVICES /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / REGEXP /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / REPLACEMENT /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_NAPTR extends Net_DNS2_RR
{
/*
* the order in which the NAPTR records MUST be processed
*/
public $order;
/*
* specifies the order in which NAPTR records with equal "order"
* values SHOULD be processed
*/
public $preference;
/*
* rewrite flags
*/
public $flags;
/*
* Specifies the service(s) available down this rewrite path
*/
public $services;
/*
* regular expression
*/
public $regexp;
/*
* The next NAME to query for NAPTR, SRV, or address records
* depending on the value of the flags field
*/
public $replacement;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->order . ' ' . $this->preference . ' ' .
$this->formatString($this->flags) . ' ' .
$this->formatString($this->services) . ' ' .
$this->formatString($this->regexp) . ' ' .
$this->cleanString($this->replacement) . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->order = array_shift($rdata);
$this->preference = array_shift($rdata);
$data = $this->buildString($rdata);
if (count($data) == 4) {
$this->flags = $data[0];
$this->services = $data[1];
$this->regexp = $data[2];
$this->replacement = $this->cleanString($data[3]);
return true;
}
return false;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the order and preference
//
$x = unpack('norder/npreference', $this->rdata);
$this->order = $x['order'];
$this->preference = $x['preference'];
$offset = $packet->offset + 4;
$this->flags = Net_DNS2_Packet::label($packet, $offset);
$this->services = Net_DNS2_Packet::label($packet, $offset);
$this->regexp = Net_DNS2_Packet::label($packet, $offset);
$this->replacement = Net_DNS2_Packet::expand($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if ( (isset($this->order)) && (strlen($this->services) > 0) ) {
$data = pack('nn', $this->order, $this->preference);
$data .= chr(strlen($this->flags)) . $this->flags;
$data .= chr(strlen($this->services)) . $this->services;
$data .= chr(strlen($this->regexp)) . $this->regexp;
$packet->offset += strlen($data);
$data .= $packet->compress($this->replacement, $packet->offset);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,139 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.3.1
*
*/
/**
* NID Resource Record - RFC6742 section 2.1
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Preference | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | NodeID |
* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_NID extends Net_DNS2_RR
{
/*
* The preference
*/
public $preference;
/*
* The node ID field
*/
public $nodeid;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->preference . ' ' . $this->nodeid;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->preference = array_shift($rdata);
$this->nodeid = array_shift($rdata);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the values
//
$x = unpack('npreference/n4nodeid', $this->rdata);
$this->preference = $x['preference'];
//
// build the node id
//
$this->nodeid = dechex($x['nodeid1']) . ':' .
dechex($x['nodeid2']) . ':' .
dechex($x['nodeid3']) . ':' .
dechex($x['nodeid4']);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->nodeid) > 0) {
//
// break out the node id
//
$n = explode(':', $this->nodeid);
//
// pack the data
//
return pack(
'n5', $this->preference, hexdec($n[0]), hexdec($n[1]),
hexdec($n[2]), hexdec($n[3])
);
}
return null;
}
}

View File

@ -0,0 +1,82 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* NIMLOC Resource Record - undefined; the rdata is simply used as-is in it's
* binary format, so not process has to be done.
*
*/
class Net_DNS2_RR_NIMLOC extends Net_DNS2_RR
{
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return '';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
return true;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
return $this->rdata;
}
}

View File

@ -0,0 +1,105 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* NS Resource Record - RFC1035 section 3.3.11
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / NSDNAME /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_NS extends Net_DNS2_RR
{
/*
* the hostname of the DNS server
*/
public $nsdname;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->cleanString($this->nsdname) . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->nsdname = $this->cleanString(array_shift($rdata));
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$offset = $packet->offset;
$this->nsdname = Net_DNS2_Packet::expand($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->nsdname) > 0) {
return $packet->compress($this->nsdname, $packet->offset);
}
return null;
}
}

View File

@ -0,0 +1,214 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* NSAP Resource Record - RFC1706
*
* |--------------|
* | <-- IDP --> |
* |--------------|-------------------------------------|
* | AFI | IDI | <-- DSP --> |
* |-----|--------|-------------------------------------|
* | 47 | 0005 | DFI | AA |Rsvd | RD |Area | ID |Sel |
* |-----|--------|-----|----|-----|----|-----|----|----|
* octets | 1 | 2 | 1 | 3 | 2 | 2 | 2 | 6 | 1 |
* |-----|--------|-----|----|-----|----|-----|----|----|
*
*/
class Net_DNS2_RR_NSAP extends Net_DNS2_RR
{
public $afi;
public $idi;
public $dfi;
public $aa;
public $rsvd;
public $rd;
public $area;
public $id;
public $sel;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->cleanString($this->afi) . '.' .
$this->cleanString($this->idi) . '.' .
$this->cleanString($this->dfi) . '.' .
$this->cleanString($this->aa) . '.' .
$this->cleanString($this->rsvd) . '.' .
$this->cleanString($this->rd) . '.' .
$this->cleanString($this->area) . '.' .
$this->cleanString($this->id) . '.' .
$this->sel;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$data = strtolower(trim(array_shift($rdata)));
//
// there is no real standard for format, so we can't rely on the fact that
// the value will come in with periods separating the values- so strip
// them out if they're included, and parse without them.
//
$data = str_replace([ '.', '0x' ], '', $data);
//
// unpack it as ascii characters
//
$x = unpack('A2afi/A4idi/A2dfi/A6aa/A4rsvd/A4rd/A4area/A12id/A2sel', $data);
//
// make sure the afi value is 47
//
if ($x['afi'] == '47') {
$this->afi = '0x' . $x['afi'];
$this->idi = $x['idi'];
$this->dfi = $x['dfi'];
$this->aa = $x['aa'];
$this->rsvd = $x['rsvd'];
$this->rd = $x['rd'];
$this->area = $x['area'];
$this->id = $x['id'];
$this->sel = $x['sel'];
return true;
}
return false;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength == 20) {
//
// get the AFI value
//
$this->afi = dechex(ord($this->rdata[0]));
//
// we only support AFI 47- there arent' any others defined.
//
if ($this->afi == '47') {
//
// unpack the rest of the values
//
$x = unpack(
'Cafi/nidi/Cdfi/C3aa/nrsvd/nrd/narea/Nidh/nidl/Csel',
$this->rdata
);
$this->afi = sprintf('0x%02x', $x['afi']);
$this->idi = sprintf('%04x', $x['idi']);
$this->dfi = sprintf('%02x', $x['dfi']);
$this->aa = sprintf(
'%06x', $x['aa1'] << 16 | $x['aa2'] << 8 | $x['aa3']
);
$this->rsvd = sprintf('%04x', $x['rsvd']);
$this->rd = sprintf('%04x', $x['rd']);
$this->area = sprintf('%04x', $x['area']);
$this->id = sprintf('%08x', $x['idh']) .
sprintf('%04x', $x['idl']);
$this->sel = sprintf('%02x', $x['sel']);
return true;
}
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if ($this->afi == '0x47') {
//
// build the aa field
//
$aa = unpack('A2x/A2y/A2z', $this->aa);
//
// build the id field
//
$id = unpack('A8a/A4b', $this->id);
//
$data = pack(
'CnCCCCnnnNnC',
hexdec($this->afi),
hexdec($this->idi),
hexdec($this->dfi),
hexdec($aa['x']),
hexdec($aa['y']),
hexdec($aa['z']),
hexdec($this->rsvd),
hexdec($this->rd),
hexdec($this->area),
hexdec($id['a']),
hexdec($id['b']),
hexdec($this->sel)
);
if (strlen($data) == 20) {
$packet->offset += 20;
return $data;
}
}
return null;
}
}

View File

@ -0,0 +1,136 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* NSEC Resource Record - RFC3845 section 2.1
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* / Next Domain Name /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* / List of Type Bit Map(s) /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_NSEC extends Net_DNS2_RR
{
/*
* The next owner name
*/
public $next_domain_name;
/*
* identifies the RRset types that exist at the NSEC RR's owner name.
*/
public $type_bit_maps = [];
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
$data = $this->cleanString($this->next_domain_name) . '.';
foreach ($this->type_bit_maps as $rr) {
$data .= ' ' . $rr;
}
return $data;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->next_domain_name = $this->cleanString(array_shift($rdata));
$this->type_bit_maps = $rdata;
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// expand the next domain name
//
$offset = $packet->offset;
$this->next_domain_name = Net_DNS2_Packet::expand($packet, $offset);
//
// parse out the RR's from the bitmap
//
$this->type_bit_maps = Net_DNS2_BitMap::bitMapToArray(
substr($this->rdata, $offset - $packet->offset)
);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->next_domain_name) > 0) {
$data = $packet->compress($this->next_domain_name, $packet->offset);
$bitmap = Net_DNS2_BitMap::arrayToBitMap($this->type_bit_maps);
$packet->offset += strlen($bitmap);
return $data . $bitmap;
}
return null;
}
}

View File

@ -0,0 +1,262 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* NSEC3 Resource Record - RFC5155 section 3.2
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Hash Alg. | Flags | Iterations |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Salt Length | Salt /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Hash Length | Next Hashed Owner Name /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* / Type Bit Maps /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_NSEC3 extends Net_DNS2_RR
{
/*
* Algorithm to use
*/
public $algorithm;
/*
* flags
*/
public $flags;
/*
* defines the number of additional times the hash is performed.
*/
public $iterations;
/*
* the length of the salt- not displayed
*/
public $salt_length;
/*
* the salt
*/
public $salt;
/*
* the length of the hash value
*/
public $hash_length;
/*
* the hashed value of the owner name
*/
public $hashed_owner_name;
/*
* array of RR type names
*/
public $type_bit_maps = [];
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
$out = $this->algorithm . ' ' . $this->flags . ' ' . $this->iterations . ' ';
//
// per RFC5155, the salt_length value isn't displayed, and if the salt
// is empty, the salt is displayed as '-'
//
if ($this->salt_length > 0) {
$out .= $this->salt;
} else {
$out .= '-';
}
//
// per RFC5255 the hash length isn't shown
//
$out .= ' ' . $this->hashed_owner_name;
//
// show the RR's
//
foreach ($this->type_bit_maps as $rr) {
$out .= ' ' . strtoupper($rr);
}
return $out;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->algorithm = array_shift($rdata);
$this->flags = array_shift($rdata);
$this->iterations = array_shift($rdata);
//
// an empty salt is represented as '-' per RFC5155 section 3.3
//
$salt = array_shift($rdata);
if ($salt == '-') {
$this->salt_length = 0;
$this->salt = '';
} else {
$this->salt_length = strlen(pack('H*', $salt));
$this->salt = strtoupper($salt);
}
$this->hashed_owner_name = array_shift($rdata);
$this->hash_length = strlen(base64_decode($this->hashed_owner_name));
$this->type_bit_maps = $rdata;
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the first values
//
$x = unpack('Calgorithm/Cflags/niterations/Csalt_length', $this->rdata);
$this->algorithm = $x['algorithm'];
$this->flags = $x['flags'];
$this->iterations = $x['iterations'];
$this->salt_length = $x['salt_length'];
$offset = 5;
if ($this->salt_length > 0) {
$x = unpack('H*', substr($this->rdata, $offset, $this->salt_length));
$this->salt = strtoupper($x[1]);
$offset += $this->salt_length;
}
//
// unpack the hash length
//
$x = unpack('@' . $offset . '/Chash_length', $this->rdata);
$offset++;
//
// copy out the hash
//
$this->hash_length = $x['hash_length'];
if ($this->hash_length > 0) {
$this->hashed_owner_name = base64_encode(
substr($this->rdata, $offset, $this->hash_length)
);
$offset += $this->hash_length;
}
//
// parse out the RR bitmap
//
$this->type_bit_maps = Net_DNS2_BitMap::bitMapToArray(
substr($this->rdata, $offset)
);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
//
// pull the salt and build the length
//
$salt = pack('H*', $this->salt);
$this->salt_length = strlen($salt);
//
// pack the algorithm, flags, iterations and salt length
//
$data = pack(
'CCnC',
$this->algorithm, $this->flags, $this->iterations, $this->salt_length
);
$data .= $salt;
//
// add the hash length and hash
//
$data .= chr($this->hash_length);
if ($this->hash_length > 0) {
$data .= base64_decode($this->hashed_owner_name);
}
//
// conver the array of RR names to a type bitmap
//
$data .= Net_DNS2_BitMap::arrayToBitMap($this->type_bit_maps);
$packet->offset += strlen($data);
return $data;
}
}

View File

@ -0,0 +1,172 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* NSEC3PARAM Resource Record - RFC5155 section 4.2
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Hash Alg. | Flags | Iterations |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Salt Length | Salt /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_NSEC3PARAM extends Net_DNS2_RR
{
/*
* Algorithm to use
*
* TODO: same as the NSEC3
*/
public $algorithm;
/*
* flags
*/
public $flags;
/*
* defines the number of additional times the hash is performed.
*/
public $iterations;
/*
* the length of the salt- not displayed
*/
public $salt_length;
/*
* the salt
*/
public $salt;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
$out = $this->algorithm . ' ' . $this->flags . ' ' . $this->iterations . ' ';
//
// per RFC5155, the salt_length value isn't displayed, and if the salt
// is empty, the salt is displayed as "-"
//
if ($this->salt_length > 0) {
$out .= $this->salt;
} else {
$out .= '-';
}
return $out;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->algorithm = array_shift($rdata);
$this->flags = array_shift($rdata);
$this->iterations = array_shift($rdata);
$salt = array_shift($rdata);
if ($salt == '-') {
$this->salt_length = 0;
$this->salt = '';
} else {
$this->salt_length = strlen(pack('H*', $salt));
$this->salt = strtoupper($salt);
}
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$x = unpack('Calgorithm/Cflags/niterations/Csalt_length', $this->rdata);
$this->algorithm = $x['algorithm'];
$this->flags = $x['flags'];
$this->iterations = $x['iterations'];
$this->salt_length = $x['salt_length'];
if ($this->salt_length > 0) {
$x = unpack('H*', substr($this->rdata, 5, $this->salt_length));
$this->salt = strtoupper($x[1]);
}
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
$salt = pack('H*', $this->salt);
$this->salt_length = strlen($salt);
$data = pack(
'CCnC',
$this->algorithm, $this->flags, $this->iterations, $this->salt_length
) . $salt;
$packet->offset += strlen($data);
return $data;
}
}

View File

@ -0,0 +1,111 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.4.0
*
*/
/**
* OPENPGPKEY Resource Record - https://tools.ietf.org/html/draft-ietf-dane-openpgpkey-01
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* / /
* / OpenPGP Public KeyRing /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_OPENPGPKEY extends Net_DNS2_RR
{
/*
* the public key
*/
public $key;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->key;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->key = array_shift($rdata);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$this->key = base64_encode(substr($this->rdata, 0, $this->rdlength));
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->key) > 0) {
$data = base64_decode($this->key);
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,244 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.0.0
*
*/
/**
* OPT Resource Record - RFC2929 section 3.1
*
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | OPTION-CODE |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | OPTION-LENGTH |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | |
* / OPTION-DATA /
* / /
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*
*/
class Net_DNS2_RR_OPT extends Net_DNS2_RR
{
/*
* option code - assigned by IANA
*/
public $option_code;
/*
* the length of the option data
*/
public $option_length;
/*
* the option data
*/
public $option_data;
/*
* the extended response code stored in the TTL
*/
public $extended_rcode;
/*
* the implementation level
*/
public $version;
/*
* the DO bit used for DNSSEC - RFC3225
*/
public $do;
/*
* the extended flags
*/
public $z;
/**
* Constructor - builds a new Net_DNS2_RR_OPT object; normally you wouldn't call
* this directly, but OPT RR's are a little different
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet or null to create
* an empty object
* @param array $rr an array with RR parse values or null to
* create an empty object
*
* @throws Net_DNS2_Exception
* @access public
*
*/
public function __construct(Net_DNS2_Packet &$packet = null, array $rr = null)
{
//
// this is for when we're manually building an OPT RR object; we aren't
// passing in binary data to parse, we just want a clean/empty object.
//
$this->type = 'OPT';
$this->rdlength = 0;
$this->option_length = 0;
$this->extended_rcode = 0;
$this->version = 0;
$this->do = 0;
$this->z = 0;
//
// everthing else gets passed through to the parent.
//
if ( (!is_null($packet)) && (!is_null($rr)) ) {
parent::__construct($packet, $rr);
}
}
/**
* method to return the rdata portion of the packet as a string. There is no
* defintion for returning an OPT RR by string- this is just here to validate
* the binary parsing / building routines.
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->option_code . ' ' . $this->option_data;
}
/**
* parses the rdata portion from a standard DNS config line. There is no
* definition for parsing a OPT RR by string- this is just here to validate
* the binary parsing / building routines.
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->option_code = array_shift($rdata);
$this->option_data = array_shift($rdata);
$this->option_length = strlen($this->option_data);
$x = unpack('Cextended/Cversion/Cdo/Cz', pack('N', $this->ttl));
$this->extended_rcode = $x['extended'];
$this->version = $x['version'];
$this->do = ($x['do'] >> 7);
$this->z = $x['z'];
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
//
// parse out the TTL value
//
$x = unpack('Cextended/Cversion/Cdo/Cz', pack('N', $this->ttl));
$this->extended_rcode = $x['extended'];
$this->version = $x['version'];
$this->do = ($x['do'] >> 7);
$this->z = $x['z'];
//
// parse the data, if there is any
//
if ($this->rdlength > 0) {
//
// unpack the code and length
//
$x = unpack('noption_code/noption_length', $this->rdata);
$this->option_code = $x['option_code'];
$this->option_length = $x['option_length'];
//
// copy out the data based on the length
//
$this->option_data = substr($this->rdata, 4);
}
return true;
}
/**
* pre-builds the TTL value for this record; we needed to separate this out
* from the rrGet() function, as the logic in the Net_DNS2_RR packs the TTL
* value before it builds the rdata value.
*
* @return void
* @access protected
*
*/
protected function preBuild()
{
//
// build the TTL value based on the local values
//
$ttl = unpack(
'N',
pack('CCCC', $this->extended_rcode, $this->version, ($this->do << 7), 0)
);
$this->ttl = $ttl[1];
return;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
//
// if there is an option code, then pack that data too
//
if ($this->option_code) {
$data = pack('nn', $this->option_code, $this->option_length) .
$this->option_data;
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,104 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* PTR Resource Record - RFC1035 section 3.3.12
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / PTRDNAME /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_PTR extends Net_DNS2_RR
{
/*
* the hostname of the PTR entry
*/
public $ptrdname;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return rtrim($this->ptrdname, '.') . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->ptrdname = rtrim(implode(' ', $rdata), '.');
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$offset = $packet->offset;
$this->ptrdname = Net_DNS2_Packet::expand($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->ptrdname) > 0) {
return $packet->compress($this->ptrdname, $packet->offset);
}
return null;
}
}

View File

@ -0,0 +1,138 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* PX Resource Record - RFC2163 section 4
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | PREFERENCE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / MAP822 /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / MAPX400 /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--
*
*/
class Net_DNS2_RR_PX extends Net_DNS2_RR
{
/*
* preference
*/
public $preference;
/*
* the RFC822 part of the MCGAM
*/
public $map822;
/*
* the X.400 part of the MCGAM
*/
public $mapx400;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->preference . ' ' . $this->cleanString($this->map822) . '. ' .
$this->cleanString($this->mapx400) . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->preference = $rdata[0];
$this->map822 = $this->cleanString($rdata[1]);
$this->mapx400 = $this->cleanString($rdata[2]);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// parse the preference
//
$x = unpack('npreference', $this->rdata);
$this->preference = $x['preference'];
$offset = $packet->offset + 2;
$this->map822 = Net_DNS2_Packet::expand($packet, $offset);
$this->mapx400 = Net_DNS2_Packet::expand($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->map822) > 0) {
$data = pack('n', $this->preference);
$packet->offset += 2;
$data .= $packet->compress($this->map822, $packet->offset);
$data .= $packet->compress($this->mapx400, $packet->offset);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* RP Resource Record - RFC1183 section 2.2
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / mboxdname /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / txtdname /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_RP extends Net_DNS2_RR
{
/*
* mailbox for the responsible person
*/
public $mboxdname;
/*
* is a domain name for which TXT RR's exists
*/
public $txtdname;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->cleanString($this->mboxdname) . '. ' . $this->cleanString($this->txtdname) . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->mboxdname = $this->cleanString($rdata[0]);
$this->txtdname = $this->cleanString($rdata[1]);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$offset = $packet->offset;
$this->mboxdname = Net_DNS2_Packet::expand($packet, $offset, true);
$this->txtdname = Net_DNS2_Packet::expand($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->mboxdname) > 0) {
return $packet->compress($this->mboxdname, $packet->offset) .
$packet->compress($this->txtdname, $packet->offset);
}
return null;
}
}

View File

@ -0,0 +1,280 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
* This file contains code based off the Net::DNS::SEC Perl module by Olaf M. Kolkman
*
* This is the copyright notice from the PERL Net::DNS::SEC module:
*
* Copyright (c) 2001 - 2005 RIPE NCC. Author Olaf M. Kolkman
* Copyright (c) 2007 - 2008 NLnet Labs. Author Olaf M. Kolkman
* <olaf@net-dns.org>
*
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the author not be
* used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
*
* THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
* AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
/**
* RRSIG Resource Record - RFC4034 sction 3.1
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Type Covered | Algorithm | Labels |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Original TTL |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Signature Expiration |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Signature Inception |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Key Tag | /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Signer's Name /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* / /
* / Signature /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_RRSIG extends Net_DNS2_RR
{
/*
* the RR type covered by this signature
*/
public $typecovered;
/*
* the algorithm used for the signature
*/
public $algorithm;
/*
* the number of labels in the name
*/
public $labels;
/*
* the original TTL
*/
public $origttl;
/*
* the signature expiration
*/
public $sigexp;
/*
* the inception of the signature
*/
public $sigincep;
/*
* the keytag used
*/
public $keytag;
/*
* the signer's name
*/
public $signname;
/*
* the signature
*/
public $signature;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->typecovered . ' ' . $this->algorithm . ' ' .
$this->labels . ' ' . $this->origttl . ' ' .
$this->sigexp . ' ' . $this->sigincep . ' ' .
$this->keytag . ' ' . $this->cleanString($this->signname) . '. ' .
$this->signature;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->typecovered = strtoupper(array_shift($rdata));
$this->algorithm = array_shift($rdata);
$this->labels = array_shift($rdata);
$this->origttl = array_shift($rdata);
$this->sigexp = array_shift($rdata);
$this->sigincep = array_shift($rdata);
$this->keytag = array_shift($rdata);
$this->signname = $this->cleanString(array_shift($rdata));
foreach ($rdata as $line) {
$this->signature .= $line;
}
$this->signature = trim($this->signature);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack
//
$x = unpack(
'ntc/Calgorithm/Clabels/Norigttl/Nsigexp/Nsigincep/nkeytag',
$this->rdata
);
$this->typecovered = Net_DNS2_Lookups::$rr_types_by_id[$x['tc']];
$this->algorithm = $x['algorithm'];
$this->labels = $x['labels'];
$this->origttl = Net_DNS2::expandUint32($x['origttl']);
//
// the dates are in GM time
//
$this->sigexp = gmdate('YmdHis', $x['sigexp']);
$this->sigincep = gmdate('YmdHis', $x['sigincep']);
//
// get the keytag
//
$this->keytag = $x['keytag'];
//
// get teh signers name and signature
//
$offset = $packet->offset + 18;
$sigoffset = $offset;
$this->signname = strtolower(
Net_DNS2_Packet::expand($packet, $sigoffset)
);
$this->signature = base64_encode(
substr($this->rdata, 18 + ($sigoffset - $offset))
);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->signature) > 0) {
//
// parse the values out of the dates
//
preg_match(
'/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', $this->sigexp, $e
);
preg_match(
'/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', $this->sigincep, $i
);
//
// pack the value
//
$data = pack(
'nCCNNNn',
Net_DNS2_Lookups::$rr_types_by_name[$this->typecovered],
$this->algorithm,
$this->labels,
$this->origttl,
gmmktime($e[4], $e[5], $e[6], $e[2], $e[3], $e[1]),
gmmktime($i[4], $i[5], $i[6], $i[2], $i[3], $i[1]),
$this->keytag
);
//
// the signer name is special; it's not allowed to be compressed
// (see section 3.1.7)
//
$names = explode('.', strtolower($this->signname));
foreach ($names as $name) {
$data .= chr(strlen($name));
$data .= $name;
}
$data .= "\0";
//
// add the signature
//
$data .= base64_decode($this->signature);
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,127 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* RT Resource Record - RFC1183 section 3.3
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | preference |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / intermediate-host /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_RT extends Net_DNS2_RR
{
/*
* the preference of this route
*/
public $preference;
/*
* host which will servce as an intermediate in reaching the owner host
*/
public $intermediatehost;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->preference . ' ' .
$this->cleanString($this->intermediatehost) . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->preference = $rdata[0];
$this->intermediatehost = $this->cleanString($rdata[1]);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the preference
//
$x = unpack('npreference', $this->rdata);
$this->preference = $x['preference'];
$offset = $packet->offset + 2;
$this->intermediatehost = Net_DNS2_Packet::expand($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->intermediatehost) > 0) {
$data = pack('n', $this->preference);
$packet->offset += 2;
$data .= $packet->compress($this->intermediatehost, $packet->offset);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,410 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
* This file contains code based off the Net::DNS::SEC Perl module by Olaf M. Kolkman
*
* This is the copyright notice from the PERL Net::DNS::SEC module:
*
* Copyright (c) 2001 - 2005 RIPE NCC. Author Olaf M. Kolkman
* Copyright (c) 2007 - 2008 NLnet Labs. Author Olaf M. Kolkman
* <olaf@net-dns.org>
*
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the author not be
* used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
*
* THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
* AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
/**
* SIG Resource Record - RFC2535 section 4.1
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Type Covered | Algorithm | Labels |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Original TTL |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Signature Expiration |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Signature Inception |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Key Tag | /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Signer's Name /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* / /
* / Signature /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_SIG extends Net_DNS2_RR
{
/*
* and instance of a Net_DNS2_PrivateKey object
*/
public $private_key = null;
/*
* the RR type covered by this signature
*/
public $typecovered;
/*
* the algorithm used for the signature
*/
public $algorithm;
/*
* the number of labels in the name
*/
public $labels;
/*
* the original TTL
*/
public $origttl;
/*
* the signature expiration
*/
public $sigexp;
/*
* the inception of the signature
*/
public $sigincep;
/*
* the keytag used
*/
public $keytag;
/*
* the signer's name
*/
public $signname;
/*
* the signature
*/
public $signature;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->typecovered . ' ' . $this->algorithm . ' ' .
$this->labels . ' ' . $this->origttl . ' ' .
$this->sigexp . ' ' . $this->sigincep . ' ' .
$this->keytag . ' ' . $this->cleanString($this->signname) . '. ' .
$this->signature;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->typecovered = strtoupper(array_shift($rdata));
$this->algorithm = array_shift($rdata);
$this->labels = array_shift($rdata);
$this->origttl = array_shift($rdata);
$this->sigexp = array_shift($rdata);
$this->sigincep = array_shift($rdata);
$this->keytag = array_shift($rdata);
$this->signname = $this->cleanString(array_shift($rdata));
foreach ($rdata as $line) {
$this->signature .= $line;
}
$this->signature = trim($this->signature);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack
//
$x = unpack(
'ntc/Calgorithm/Clabels/Norigttl/Nsigexp/Nsigincep/nkeytag',
$this->rdata
);
$this->typecovered = Net_DNS2_Lookups::$rr_types_by_id[$x['tc']];
$this->algorithm = $x['algorithm'];
$this->labels = $x['labels'];
$this->origttl = Net_DNS2::expandUint32($x['origttl']);
//
// the dates are in GM time
//
$this->sigexp = gmdate('YmdHis', $x['sigexp']);
$this->sigincep = gmdate('YmdHis', $x['sigincep']);
//
// get the keytag
//
$this->keytag = $x['keytag'];
//
// get teh signers name and signature
//
$offset = $packet->offset + 18;
$sigoffset = $offset;
$this->signname = strtolower(
Net_DNS2_Packet::expand($packet, $sigoffset)
);
$this->signature = base64_encode(
substr($this->rdata, 18 + ($sigoffset - $offset))
);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
//
// parse the values out of the dates
//
preg_match(
'/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', $this->sigexp, $e
);
preg_match(
'/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', $this->sigincep, $i
);
//
// pack the value
//
$data = pack(
'nCCNNNn',
Net_DNS2_Lookups::$rr_types_by_name[$this->typecovered],
$this->algorithm,
$this->labels,
$this->origttl,
gmmktime($e[4], $e[5], $e[6], $e[2], $e[3], $e[1]),
gmmktime($i[4], $i[5], $i[6], $i[2], $i[3], $i[1]),
$this->keytag
);
//
// the signer name is special; it's not allowed to be compressed
// (see section 3.1.7)
//
$names = explode('.', strtolower($this->signname));
foreach ($names as $name) {
$data .= chr(strlen($name));
$data .= $name;
}
$data .= chr('0');
//
// if the signature is empty, and $this->private_key is an instance of a
// private key object, and we have access to openssl, then assume this
// is a SIG(0), and generate a new signature
//
if ( (strlen($this->signature) == 0)
&& ($this->private_key instanceof Net_DNS2_PrivateKey)
&& (extension_loaded('openssl') === true)
) {
//
// create a new packet for the signature-
//
$new_packet = new Net_DNS2_Packet_Request('example.com', 'SOA', 'IN');
//
// copy the packet data over
//
$new_packet->copy($packet);
//
// remove the SIG object from the additional list
//
array_pop($new_packet->additional);
$new_packet->header->arcount = count($new_packet->additional);
//
// copy out the data
//
$sigdata = $data . $new_packet->get();
//
// based on the algorithm
//
$algorithm = 0;
switch($this->algorithm) {
//
// MD5
//
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSAMD5:
$algorithm = OPENSSL_ALGO_MD5;
break;
//
// SHA1
//
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA1:
$algorithm = OPENSSL_ALGO_SHA1;
break;
//
// SHA256 (PHP 5.4.8 or higher)
//
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA256:
if (version_compare(PHP_VERSION, '5.4.8', '<') == true) {
throw new Net_DNS2_Exception(
'SHA256 support is only available in PHP >= 5.4.8',
Net_DNS2_Lookups::E_OPENSSL_INV_ALGO
);
}
$algorithm = OPENSSL_ALGO_SHA256;
break;
//
// SHA512 (PHP 5.4.8 or higher)
//
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA512:
if (version_compare(PHP_VERSION, '5.4.8', '<') == true) {
throw new Net_DNS2_Exception(
'SHA512 support is only available in PHP >= 5.4.8',
Net_DNS2_Lookups::E_OPENSSL_INV_ALGO
);
}
$algorithm = OPENSSL_ALGO_SHA512;
break;
//
// unsupported at the moment
//
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_DSA:
case Net_DNS2_Lookups::DSNSEC_ALGORITHM_RSASHA1NSEC3SHA1:
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_DSANSEC3SHA1:
default:
throw new Net_DNS2_Exception(
'invalid or unsupported algorithm',
Net_DNS2_Lookups::E_OPENSSL_INV_ALGO
);
break;
}
//
// sign the data
//
if (openssl_sign($sigdata, $this->signature, $this->private_key->instance, $algorithm) == false) {
throw new Net_DNS2_Exception(
openssl_error_string(),
Net_DNS2_Lookups::E_OPENSSL_ERROR
);
}
//
// build the signature value based
//
switch($this->algorithm) {
//
// RSA- add it directly
//
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSAMD5:
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA1:
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA256:
case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA512:
$this->signature = base64_encode($this->signature);
break;
}
}
//
// add the signature
//
$data .= base64_decode($this->signature);
$packet->offset += strlen($data);
return $data;
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.4.2
*
*/
/**
* The SMIMEA RR is implemented exactly like the TLSA record, so
* for now we just extend the TLSA RR and use it.
*
*/
class Net_DNS2_RR_SMIMEA extends Net_DNS2_RR_TLSA
{
}

View File

@ -0,0 +1,192 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* SOA Resource Record - RFC1035 section 3.3.13
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / MNAME /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / RNAME /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | SERIAL |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | REFRESH |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | RETRY |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | EXPIRE |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | MINIMUM |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_SOA extends Net_DNS2_RR
{
/*
* The master DNS server
*/
public $mname;
/*
* mailbox of the responsible person
*/
public $rname;
/*
* serial number
*/
public $serial;
/*
* refresh time
*/
public $refresh;
/*
* retry interval
*/
public $retry;
/*
* expire time
*/
public $expire;
/*
* minimum TTL for any RR in this zone
*/
public $minimum;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->cleanString($this->mname) . '. ' .
$this->cleanString($this->rname) . '. ' .
$this->serial . ' ' . $this->refresh . ' ' . $this->retry . ' ' .
$this->expire . ' ' . $this->minimum;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->mname = $this->cleanString($rdata[0]);
$this->rname = $this->cleanString($rdata[1]);
$this->serial = $rdata[2];
$this->refresh = $rdata[3];
$this->retry = $rdata[4];
$this->expire = $rdata[5];
$this->minimum = $rdata[6];
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// parse the
//
$offset = $packet->offset;
$this->mname = Net_DNS2_Packet::expand($packet, $offset);
$this->rname = Net_DNS2_Packet::expand($packet, $offset, true);
//
// get the SOA values
//
$x = unpack(
'@' . $offset . '/Nserial/Nrefresh/Nretry/Nexpire/Nminimum/',
$packet->rdata
);
$this->serial = Net_DNS2::expandUint32($x['serial']);
$this->refresh = Net_DNS2::expandUint32($x['refresh']);
$this->retry = Net_DNS2::expandUint32($x['retry']);
$this->expire = Net_DNS2::expandUint32($x['expire']);
$this->minimum = Net_DNS2::expandUint32($x['minimum']);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->mname) > 0) {
$data = $packet->compress($this->mname, $packet->offset);
$data .= $packet->compress($this->rname, $packet->offset);
$data .= pack(
'N5', $this->serial, $this->refresh, $this->retry,
$this->expire, $this->minimum
);
$packet->offset += 20;
return $data;
}
return null;
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* The SPF RR is implemented exactly like the TXT record, so
* for now we just extend the TXT RR and use it.
*
*/
class Net_DNS2_RR_SPF extends Net_DNS2_RR_TXT
{
}

View File

@ -0,0 +1,145 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* SRV Resource Record - RFC2782
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | PRIORITY |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | WEIGHT |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | PORT |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / TARGET /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_SRV extends Net_DNS2_RR
{
/*
* The priority of this target host.
*/
public $priority;
/*
* a relative weight for entries with the same priority
*/
public $weight;
/*
* The port on this target host of this service.
*/
public $port;
/*
* The domain name of the target host
*/
public $target;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->priority . ' ' . $this->weight . ' ' .
$this->port . ' ' . $this->cleanString($this->target) . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->priority = $rdata[0];
$this->weight = $rdata[1];
$this->port = $rdata[2];
$this->target = $this->cleanString($rdata[3]);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the priority, weight and port
//
$x = unpack('npriority/nweight/nport', $this->rdata);
$this->priority = $x['priority'];
$this->weight = $x['weight'];
$this->port = $x['port'];
$offset = $packet->offset + 6;
$this->target = Net_DNS2_Packet::expand($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->target) > 0) {
$data = pack('nnn', $this->priority, $this->weight, $this->port);
$packet->offset += 6;
$data .= $packet->compress($this->target, $packet->offset);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,205 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* SSHFP Resource Record - RFC4255 section 3.1
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | algorithm | fp type | /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
* / /
* / fingerprint /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_SSHFP extends Net_DNS2_RR
{
/*
* the algorithm used
*/
public $algorithm;
/*
* The finger print type
*/
public $fp_type;
/*
* the finger print data
*/
public $fingerprint;
/*
* Algorithms
*/
const SSHFP_ALGORITHM_RES = 0;
const SSHFP_ALGORITHM_RSA = 1;
const SSHFP_ALGORITHM_DSS = 2;
const SSHFP_ALGORITHM_ECDSA = 3;
const SSHFP_ALGORITHM_ED25519 = 4;
/*
* Fingerprint Types
*/
const SSHFP_FPTYPE_RES = 0;
const SSHFP_FPTYPE_SHA1 = 1;
const SSHFP_FPTYPE_SHA256 = 2;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->algorithm . ' ' . $this->fp_type . ' ' . $this->fingerprint;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
//
// "The use of mnemonics instead of numbers is not allowed."
//
// RFC4255 section 3.2
//
$algorithm = array_shift($rdata);
$fp_type = array_shift($rdata);
$fingerprint = strtolower(implode('', $rdata));
//
// There are only two algorithm's defined
//
if ( ($algorithm != self::SSHFP_ALGORITHM_RSA)
&& ($algorithm != self::SSHFP_ALGORITHM_DSS)
&& ($algorithm != self::SSHFP_ALGORITHM_ECDSA)
&& ($algorithm != self::SSHFP_ALGORITHM_ED25519)
) {
return false;
}
//
// there are only two fingerprints defined
//
if ( ($fp_type != self::SSHFP_FPTYPE_SHA1)
&& ($fp_type != self::SSHFP_FPTYPE_SHA256)
) {
return false;
}
$this->algorithm = $algorithm;
$this->fp_type = $fp_type;
$this->fingerprint = $fingerprint;
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the algorithm and finger print type
//
$x = unpack('Calgorithm/Cfp_type', $this->rdata);
$this->algorithm = $x['algorithm'];
$this->fp_type = $x['fp_type'];
//
// There are only three algorithm's defined
//
if ( ($this->algorithm != self::SSHFP_ALGORITHM_RSA)
&& ($this->algorithm != self::SSHFP_ALGORITHM_DSS)
&& ($this->algorithm != self::SSHFP_ALGORITHM_ECDSA)
&& ($this->algorithm != self::SSHFP_ALGORITHM_ED25519)
) {
return false;
}
//
// there are only two fingerprints defined
//
if ( ($this->fp_type != self::SSHFP_FPTYPE_SHA1)
&& ($this->fp_type != self::SSHFP_FPTYPE_SHA256)
) {
return false;
}
//
// parse the finger print; this assumes SHA-1
//
$fp = unpack('H*a', substr($this->rdata, 2));
$this->fingerprint = strtolower($fp['a']);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->fingerprint) > 0) {
$data = pack(
'CCH*', $this->algorithm, $this->fp_type, $this->fingerprint
);
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.2.0
*
*/
/**
* The TA RR is implemented exactly like the DS record, so
* for now we just extend the DS RR and use it.
*
*/
class Net_DNS2_RR_TA extends Net_DNS2_RR_DS
{
}

View File

@ -0,0 +1,121 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.2.0
*
*/
/**
* TALINK Resource Record - DNSSEC Trust Anchor
*
* http://tools.ietf.org/id/draft-ietf-dnsop-dnssec-trust-history-00.txt
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / PREVIOUS /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / NEXT /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_TALINK extends Net_DNS2_RR
{
/*
* the previous domain name
*/
public $previous;
/*
* the next domain name
*/
public $next;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->cleanString($this->previous) . '. ' .
$this->cleanString($this->next) . '.';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->previous = $this->cleanString($rdata[0]);
$this->next = $this->cleanString($rdata[1]);
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$offset = $packet->offset;
$this->previous = Net_DNS2_Packet::label($packet, $offset);
$this->next = Net_DNS2_Packet::label($packet, $offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if ( (strlen($this->previous) > 0) || (strlen($this->next) > 0) ) {
$data = chr(strlen($this->previous)) . $this->previous .
chr(strlen($this->next)) . $this->next;
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,259 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* TKEY Resource Record - RFC 2930 section 2
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / ALGORITHM /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | INCEPTION |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | EXPIRATION |
* | |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | MODE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | ERROR |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | KEY SIZE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / KEY DATA /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | OTHER SIZE |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / OTHER DATA /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_TKEY extends Net_DNS2_RR
{
public $algorithm;
public $inception;
public $expiration;
public $mode;
public $error;
public $key_size;
public $key_data;
public $other_size;
public $other_data;
/*
* TSIG Modes
*/
const TSIG_MODE_RES = 0;
const TSIG_MODE_SERV_ASSIGN = 1;
const TSIG_MODE_DH = 2;
const TSIG_MODE_GSS_API = 3;
const TSIG_MODE_RESV_ASSIGN = 4;
const TSIG_MODE_KEY_DELE = 5;
/*
* map the mod id's to names so we can validate
*/
public $tsgi_mode_id_to_name = [
self::TSIG_MODE_RES => 'Reserved',
self::TSIG_MODE_SERV_ASSIGN => 'Server Assignment',
self::TSIG_MODE_DH => 'Diffie-Hellman',
self::TSIG_MODE_GSS_API => 'GSS-API',
self::TSIG_MODE_RESV_ASSIGN => 'Resolver Assignment',
self::TSIG_MODE_KEY_DELE => 'Key Deletion'
];
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
$out = $this->cleanString($this->algorithm) . '. ' . $this->mode;
if ($this->key_size > 0) {
$out .= ' ' . trim($this->key_data, '.') . '.';
} else {
$out .= ' .';
}
return $out;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
//
// data passed in is assumed: <algorithm> <mode> <key>
//
$this->algorithm = $this->cleanString(array_shift($rdata));
$this->mode = array_shift($rdata);
$this->key_data = trim(array_shift($rdata), '.');
//
// the rest of the data is set manually
//
$this->inception = time();
$this->expiration = time() + 86400; // 1 day
$this->error = 0;
$this->key_size = strlen($this->key_data);
$this->other_size = 0;
$this->other_data = '';
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// expand the algorithm
//
$offset = $packet->offset;
$this->algorithm = Net_DNS2_Packet::expand($packet, $offset);
//
// unpack inception, expiration, mode, error and key size
//
$x = unpack(
'@' . $offset . '/Ninception/Nexpiration/nmode/nerror/nkey_size',
$packet->rdata
);
$this->inception = Net_DNS2::expandUint32($x['inception']);
$this->expiration = Net_DNS2::expandUint32($x['expiration']);
$this->mode = $x['mode'];
$this->error = $x['error'];
$this->key_size = $x['key_size'];
$offset += 14;
//
// if key_size > 0, then copy out the key
//
if ($this->key_size > 0) {
$this->key_data = substr($packet->rdata, $offset, $this->key_size);
$offset += $this->key_size;
}
//
// unpack the other length
//
$x = unpack('@' . $offset . '/nother_size', $packet->rdata);
$this->other_size = $x['other_size'];
$offset += 2;
//
// if other_size > 0, then copy out the data
//
if ($this->other_size > 0) {
$this->other_data = substr(
$packet->rdata, $offset, $this->other_size
);
}
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->algorithm) > 0) {
//
// make sure the size values are correct
//
$this->key_size = strlen($this->key_data);
$this->other_size = strlen($this->other_data);
//
// add the algorithm without compression
//
$data = Net_DNS2_Packet::pack($this->algorithm);
//
// pack in the inception, expiration, mode, error and key size
//
$data .= pack(
'NNnnn', $this->inception, $this->expiration,
$this->mode, 0, $this->key_size
);
//
// if the key_size > 0, then add the key
//
if ($this->key_size > 0) {
$data .= $this->key_data;
}
//
// pack in the other size
//
$data .= pack('n', $this->other_size);
if ($this->other_size > 0) {
$data .= $this->other_data;
}
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,146 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.2.5
*
*/
/**
* TLSA Resource Record - RFC 6698
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Cert. Usage | Selector | Matching Type | /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
* / /
* / Certificate Association Data /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_TLSA extends Net_DNS2_RR
{
/*
* The Certificate Usage Field
*/
public $cert_usage;
/*
* The Selector Field
*/
public $selector;
/*
* The Matching Type Field
*/
public $matching_type;
/*
* The Certificate Association Data Field
*/
public $certificate;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->cert_usage . ' ' . $this->selector . ' ' .
$this->matching_type . ' ' . base64_encode($this->certificate);
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->cert_usage = array_shift($rdata);
$this->selector = array_shift($rdata);
$this->matching_type = array_shift($rdata);
$this->certificate = base64_decode(implode('', $rdata));
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the format, keytag and algorithm
//
$x = unpack('Cusage/Cselector/Ctype', $this->rdata);
$this->cert_usage = $x['usage'];
$this->selector = $x['selector'];
$this->matching_type = $x['type'];
//
// copy the certificate
//
$this->certificate = substr($this->rdata, 3, $this->rdlength - 3);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->certificate) > 0) {
$data = pack(
'CCC', $this->cert_usage, $this->selector, $this->matching_type
) . $this->certificate;
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,456 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* TSIG Resource Record - RFC 2845
*
* 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* / algorithm /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | time signed |
* | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | | fudge |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | mac size | /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
* / mac /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | original id | error |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | other length | /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
* / other data /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_TSIG extends Net_DNS2_RR
{
/*
* TSIG Algorithm Identifiers
*/
const HMAC_MD5 = 'hmac-md5.sig-alg.reg.int'; // RFC 2845, required
const GSS_TSIG = 'gss-tsig'; // unsupported, optional
const HMAC_SHA1 = 'hmac-sha1'; // RFC 4635, required
const HMAC_SHA224 = 'hmac-sha224'; // RFC 4635, optional
const HMAC_SHA256 = 'hmac-sha256'; // RFC 4635, required
const HMAC_SHA384 = 'hmac-sha384'; // RFC 4635, optional
const HMAC_SHA512 = 'hmac-sha512'; // RFC 4635, optional
/*
* the map of hash values to names
*/
public static $hash_algorithms = [
self::HMAC_MD5 => 'md5',
self::HMAC_SHA1 => 'sha1',
self::HMAC_SHA224 => 'sha224',
self::HMAC_SHA256 => 'sha256',
self::HMAC_SHA384 => 'sha384',
self::HMAC_SHA512 => 'sha512'
];
/*
* algorithm used; only supports HMAC-MD5
*/
public $algorithm;
/*
* The time it was signed
*/
public $time_signed;
/*
* fudge- allowed offset from the time signed
*/
public $fudge;
/*
* size of the digest
*/
public $mac_size;
/*
* the digest data
*/
public $mac;
/*
* the original id of the request
*/
public $original_id;
/*
* additional error code
*/
public $error;
/*
* length of the "other" data, should only ever be 0 when there is
* no error, or 6 when there is the error RCODE_BADTIME
*/
public $other_length;
/*
* the other data; should only ever be a timestamp when there is the
* error RCODE_BADTIME
*/
public $other_data;
/*
* the key to use for signing - passed in, not included in the rdata
*/
public $key;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
$out = $this->cleanString($this->algorithm) . '. ' .
$this->time_signed . ' ' .
$this->fudge . ' ' . $this->mac_size . ' ' .
base64_encode($this->mac) . ' ' . $this->original_id . ' ' .
$this->error . ' '. $this->other_length;
if ($this->other_length > 0) {
$out .= ' ' . $this->other_data;
}
return $out;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
//
// the only value passed in is the key-
//
// this assumes it's passed in base64 encoded.
//
$this->key = preg_replace('/\s+/', '', array_shift($rdata));
//
// the rest of the data is set to default
//
$this->algorithm = self::HMAC_MD5;
$this->time_signed = time();
$this->fudge = 300;
$this->mac_size = 0;
$this->mac = '';
$this->original_id = 0;
$this->error = 0;
$this->other_length = 0;
$this->other_data = '';
//
// per RFC 2845 section 2.3
//
$this->class = 'ANY';
$this->ttl = 0;
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// expand the algorithm
//
$newoffset = $packet->offset;
$this->algorithm = Net_DNS2_Packet::expand($packet, $newoffset);
$offset = $newoffset - $packet->offset;
//
// unpack time, fudge and mac_size
//
$x = unpack(
'@' . $offset . '/ntime_high/Ntime_low/nfudge/nmac_size',
$this->rdata
);
$this->time_signed = Net_DNS2::expandUint32($x['time_low']);
$this->fudge = $x['fudge'];
$this->mac_size = $x['mac_size'];
$offset += 10;
//
// copy out the mac
//
if ($this->mac_size > 0) {
$this->mac = substr($this->rdata, $offset, $this->mac_size);
$offset += $this->mac_size;
}
//
// unpack the original id, error, and other_length values
//
$x = unpack(
'@' . $offset . '/noriginal_id/nerror/nother_length',
$this->rdata
);
$this->original_id = $x['original_id'];
$this->error = $x['error'];
$this->other_length = $x['other_length'];
//
// the only time there is actually any "other data", is when there's
// a BADTIME error code.
//
// The other length should be 6, and the other data field includes the
// servers current time - per RFC 2845 section 4.5.2
//
if ($this->error == Net_DNS2_Lookups::RCODE_BADTIME) {
if ($this->other_length != 6) {
return false;
}
//
// other data is a 48bit timestamp
//
$x = unpack(
'nhigh/nlow',
substr($this->rdata, $offset + 6, $this->other_length)
);
$this->other_data = $x['low'];
}
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->key) > 0) {
//
// create a new packet for the signature-
//
$new_packet = new Net_DNS2_Packet_Request('example.com', 'SOA', 'IN');
//
// copy the packet data over
//
$new_packet->copy($packet);
//
// remove the TSIG object from the additional list
//
array_pop($new_packet->additional);
$new_packet->header->arcount = count($new_packet->additional);
//
// copy out the data
//
$sig_data = $new_packet->get();
//
// add the name without compressing
//
$sig_data .= Net_DNS2_Packet::pack($this->name);
//
// add the class and TTL
//
$sig_data .= pack(
'nN', Net_DNS2_Lookups::$classes_by_name[$this->class], $this->ttl
);
//
// add the algorithm name without compression
//
$sig_data .= Net_DNS2_Packet::pack(strtolower($this->algorithm));
//
// add the rest of the values
//
$sig_data .= pack(
'nNnnn', 0, $this->time_signed, $this->fudge,
$this->error, $this->other_length
);
if ($this->other_length > 0) {
$sig_data .= pack('nN', 0, $this->other_data);
}
//
// sign the data
//
$this->mac = $this->_signHMAC(
$sig_data, base64_decode($this->key), $this->algorithm
);
$this->mac_size = strlen($this->mac);
//
// compress the algorithm
//
$data = Net_DNS2_Packet::pack(strtolower($this->algorithm));
//
// pack the time, fudge and mac size
//
$data .= pack(
'nNnn', 0, $this->time_signed, $this->fudge, $this->mac_size
);
$data .= $this->mac;
//
// check the error and other_length
//
if ($this->error == Net_DNS2_Lookups::RCODE_BADTIME) {
$this->other_length = strlen($this->other_data);
if ($this->other_length != 6) {
return null;
}
} else {
$this->other_length = 0;
$this->other_data = '';
}
//
// pack the id, error and other_length
//
$data .= pack(
'nnn', $packet->header->id, $this->error, $this->other_length
);
if ($this->other_length > 0) {
$data .= pack('nN', 0, $this->other_data);
}
$packet->offset += strlen($data);
return $data;
}
return null;
}
/**
* signs the given data with the given key, and returns the result
*
* @param string $data the data to sign
* @param string $key key to use for signing
* @param string $algorithm the algorithm to use; defaults to MD5
*
* @return string the signed digest
* @throws Net_DNS2_Exception
* @access private
*
*/
private function _signHMAC($data, $key = null, $algorithm = self::HMAC_MD5)
{
//
// use the hash extension; this is included by default in >= 5.1.2 which
// is our dependent version anyway- so it's easy to switch to it.
//
if (extension_loaded('hash')) {
if (!isset(self::$hash_algorithms[$algorithm])) {
throw new Net_DNS2_Exception(
'invalid or unsupported algorithm',
Net_DNS2_Lookups::E_PARSE_ERROR
);
}
return hash_hmac(self::$hash_algorithms[$algorithm], $data, $key, true);
}
//
// if the hash extension isn't loaded, and they selected something other
// than MD5, throw an exception
//
if ($algorithm != self::HMAC_MD5) {
throw new Net_DNS2_Exception(
'only HMAC-MD5 supported. please install the php-extension ' .
'"hash" in order to use the sha-family',
Net_DNS2_Lookups::E_PARSE_ERROR
);
}
//
// otherwise, do it ourselves
//
if (is_null($key)) {
return pack('H*', md5($data));
}
$key = str_pad($key, 64, chr(0x00));
if (strlen($key) > 64) {
$key = pack('H*', md5($key));
}
$k_ipad = $key ^ str_repeat(chr(0x36), 64);
$k_opad = $key ^ str_repeat(chr(0x5c), 64);
return $this->_signHMAC(
$k_opad . pack('H*', md5($k_ipad . $data)), null, $algorithm
);
}
}

View File

@ -0,0 +1,129 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* TXT Resource Record - RFC1035 section 3.3.14
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / TXT-DATA /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_TXT extends Net_DNS2_RR
{
/*
* an array of the text strings
*/
public $text = [];
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
if (count($this->text) == 0) {
return '""';
}
$data = '';
foreach ($this->text as $t) {
$data .= $this->formatString($t) . ' ';
}
return trim($data);
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$data = $this->buildString($rdata);
if (count($data) > 0) {
$this->text = $data;
}
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$length = $packet->offset + $this->rdlength;
$offset = $packet->offset;
while ($length > $offset) {
$this->text[] = Net_DNS2_Packet::label($packet, $offset);
}
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
$data = null;
foreach ($this->text as $t) {
$data .= chr(strlen($t)) . $t;
}
$packet->offset += strlen($data);
return $data;
}
}

View File

@ -0,0 +1,107 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.2.5
*
*/
/**
* TYPE65534 - Private space
*
* Since Bind 9.8 beta, it use a private recode as documented
* in the Bind ARM, chapter 4, "Private-type records.
* Basically they store signing process state.
*
*/
class Net_DNS2_RR_TYPE65534 extends Net_DNS2_RR
{
/*
* The Private data field
*/
public $private_data;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return base64_encode($this->private_data);
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->private_data = base64_decode(implode('', $rdata));
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$this->private_data = $this->rdata;
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->private_data) > 0) {
$data = $this->private_data;
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,135 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.2.0
*
*/
/**
* URI Resource Record - http://tools.ietf.org/html/draft-faltstrom-uri-06
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Priority | Weight |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* / /
* / Target /
* / /
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
class Net_DNS2_RR_URI extends Net_DNS2_RR
{
/*
* The priority of this target host.
*/
public $priority;
/*
* a relative weight for entries with the same priority
*/
public $weight;
/*
* The domain name of the target host
*/
public $target;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
//
// presentation format has double quotes (") around the target.
//
return $this->priority . ' ' . $this->weight . ' "' . $this->target . '"';
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->priority = $rdata[0];
$this->weight = $rdata[1];
$this->target = trim(strtolower(trim($rdata[2])), '"');
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// unpack the priority and weight
//
$x = unpack('npriority/nweight/a*target', $this->rdata);
$this->priority = $x['priority'];
$this->weight = $x['weight'];
$this->target = $x['target'];
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->target) > 0) {
$data = pack('nna*', $this->priority, $this->weight, $this->target);
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,187 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 1.0.1
*
*/
/**
* WKS Resource Record - RFC1035 section 3.4.2
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | ADDRESS |
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* | PROTOCOL | |
* +--+--+--+--+--+--+--+--+ |
* | |
* / <BIT MAP> /
* / /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_WKS extends Net_DNS2_RR
{
/*
* The IP address of the service
*/
public $address;
/*
* The protocol of the service
*/
public $protocol;
/*
* bitmap
*/
public $bitmap = [];
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
$data = $this->address . ' ' . $this->protocol;
foreach ($this->bitmap as $port) {
$data .= ' ' . $port;
}
return $data;
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$this->address = strtolower(trim(array_shift($rdata), '.'));
$this->protocol = array_shift($rdata);
$this->bitmap = $rdata;
return true;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
//
// get the address and protocol value
//
$x = unpack('Naddress/Cprotocol', $this->rdata);
$this->address = long2ip($x['address']);
$this->protocol = $x['protocol'];
//
// unpack the port list bitmap
//
$port = 0;
foreach (unpack('@5/C*', $this->rdata) as $set) {
$s = sprintf('%08b', $set);
for ($i=0; $i<8; $i++, $port++) {
if ($s[$i] == '1') {
$this->bitmap[] = $port;
}
}
}
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->address) > 0) {
$data = pack('NC', ip2long($this->address), $this->protocol);
$ports = [];
$n = 0;
foreach ($this->bitmap as $port) {
$ports[$port] = 1;
if ($port > $n) {
$n = $port;
}
}
for ($i=0; $i<ceil($n/8)*8; $i++) {
if (!isset($ports[$i])) {
$ports[$i] = 0;
}
}
ksort($ports);
$string = '';
$n = 0;
foreach ($ports as $s) {
$string .= $s;
$n++;
if ($n == 8) {
$data .= chr(bindec($string));
$string = '';
$n = 0;
}
}
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,112 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* X25 Resource Record - RFC1183 section 3.1
*
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
* / PSDN-address /
* +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*
*/
class Net_DNS2_RR_X25 extends Net_DNS2_RR
{
/*
* The PSDN address
*/
public $psdnaddress;
/**
* method to return the rdata portion of the packet as a string
*
* @return string
* @access protected
*
*/
protected function rrToString()
{
return $this->formatString($this->psdnaddress);
}
/**
* parses the rdata portion from a standard DNS config line
*
* @param array $rdata a string split line of values for the rdata
*
* @return boolean
* @access protected
*
*/
protected function rrFromString(array $rdata)
{
$data = $this->buildString($rdata);
if (count($data) == 1) {
$this->psdnaddress = $data[0];
return true;
}
return false;
}
/**
* parses the rdata of the Net_DNS2_Packet object
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
*
* @return boolean
* @access protected
*
*/
protected function rrSet(Net_DNS2_Packet &$packet)
{
if ($this->rdlength > 0) {
$this->psdnaddress = Net_DNS2_Packet::label($packet, $packet->offset);
return true;
}
return false;
}
/**
* returns the rdata portion of the DNS packet
*
* @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
* compressed names
*
* @return mixed either returns a binary packed
* string or null on failure
* @access protected
*
*/
protected function rrGet(Net_DNS2_Packet &$packet)
{
if (strlen($this->psdnaddress) > 0) {
$data = chr(strlen($this->psdnaddress)) . $this->psdnaddress;
$packet->offset += strlen($data);
return $data;
}
return null;
}
}

View File

@ -0,0 +1,284 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* This is the main resolver class, providing DNS query functions.
*
*/
class Net_DNS2_Resolver extends Net_DNS2
{
/**
* Constructor - creates a new Net_DNS2_Resolver object
*
* @param mixed $options either an array with options or null
*
* @access public
*
*/
public function __construct(array $options = null)
{
parent::__construct($options);
}
/**
* does a basic DNS lookup query
*
* @param string $name the DNS name to loookup
* @param string $type the name of the RR type to lookup
* @param string $class the name of the RR class to lookup
*
* @return Net_DNS2_Packet_Response object
* @throws Net_DNS2_Exception
* @access public
*
*/
public function query($name, $type = 'A', $class = 'IN')
{
//
// make sure we have some name servers set
//
$this->checkServers(Net_DNS2::RESOLV_CONF);
//
// we dont' support incremental zone tranfers; so if it's requested, a full
// zone transfer can be returned
//
if ($type == 'IXFR') {
$type = 'AXFR';
}
//
// if the name *looks* too short, then append the domain from the config
//
if ( (strpos($name, '.') === false) && ($type != 'PTR') ) {
$name .= '.' . strtolower($this->domain);
}
//
// create a new packet based on the input
//
$packet = new Net_DNS2_Packet_Request($name, $type, $class);
//
// check for an authentication method; either TSIG or SIG
//
if ( ($this->auth_signature instanceof Net_DNS2_RR_TSIG)
|| ($this->auth_signature instanceof Net_DNS2_RR_SIG)
) {
$packet->additional[] = $this->auth_signature;
$packet->header->arcount = count($packet->additional);
}
//
// check for the DNSSEC flag, and if it's true, then add an OPT
// RR to the additional section, and set the DO flag to 1.
//
if ($this->dnssec == true) {
//
// create a new OPT RR
//
$opt = new Net_DNS2_RR_OPT();
//
// set the DO flag, and the other values
//
$opt->do = 1;
$opt->class = $this->dnssec_payload_size;
//
// add the RR to the additional section.
//
$packet->additional[] = $opt;
$packet->header->arcount = count($packet->additional);
}
//
// set the DNSSEC AD or CD bits
//
if ($this->dnssec_ad_flag == true) {
$packet->header->ad = 1;
}
if ($this->dnssec_cd_flag == true) {
$packet->header->cd = 1;
}
//
// if caching is turned on, then check then hash the question, and
// do a cache lookup.
//
// don't use the cache for zone transfers
//
$packet_hash = '';
if ( ($this->use_cache == true) && ($this->cacheable($type) == true) ) {
//
// open the cache
//
$this->cache->open(
$this->cache_file, $this->cache_size, $this->cache_serializer
);
//
// build the key and check for it in the cache.
//
$packet_hash = md5(
$packet->question[0]->qname . '|' . $packet->question[0]->qtype
);
if ($this->cache->has($packet_hash)) {
return $this->cache->get($packet_hash);
}
}
//
// set the RD (recursion desired) bit to 1 / 0 depending on the config
// setting.
//
if ($this->recurse == false) {
$packet->header->rd = 0;
} else {
$packet->header->rd = 1;
}
//
// send the packet and get back the response
//
// *always* use TCP for zone transfers- does this cause any problems?
//
$response = $this->sendPacket(
$packet, ($type == 'AXFR') ? true : $this->use_tcp
);
//
// if strict mode is enabled, then make sure that the name that was
// looked up is *actually* in the response object.
//
// only do this is strict_query_mode is turned on, AND we've received
// some answers; no point doing any else if there were no answers.
//
if ( ($this->strict_query_mode == true)
&& ($response->header->ancount > 0)
) {
$found = false;
//
// look for the requested name/type/class
//
foreach ($response->answer as $index => $object) {
if ( (strcasecmp(trim($object->name, '.'), trim($packet->question[0]->qname, '.')) == 0)
&& ($object->type == $packet->question[0]->qtype)
&& ($object->class == $packet->question[0]->qclass)
) {
$found = true;
break;
}
}
//
// if it's not found, then unset the answer section; it's not correct to
// throw an exception here; if the hostname didn't exist, then
// sendPacket() would have already thrown an NXDOMAIN error- so the host
// *exists*, but just not the request type/class.
//
// the correct response in this case, is an empty answer section; the
// authority section may still have usual information, like a SOA record.
//
if ($found == false) {
$response->answer = [];
$response->header->ancount = 0;
}
}
//
// cache the response object
//
if ( ($this->use_cache == true) && ($this->cacheable($type) == true) ) {
$this->cache->put($packet_hash, $response);
}
return $response;
}
/**
* does an inverse query for the given RR; most DNS servers do not implement
* inverse queries, but they should be able to return "not implemented"
*
* @param Net_DNS2_RR $rr the RR object to lookup
*
* @return Net_DNS2_RR object
* @throws Net_DNS2_Exception
* @access public
*
*/
public function iquery(Net_DNS2_RR $rr)
{
//
// make sure we have some name servers set
//
$this->checkServers(Net_DNS2::RESOLV_CONF);
//
// create an empty packet
//
$packet = new Net_DNS2_Packet_Request($rr->name, 'A', 'IN');
//
// unset the question
//
$packet->question = [];
$packet->header->qdcount = 0;
//
// set the opcode to IQUERY
//
$packet->header->opcode = Net_DNS2_Lookups::OPCODE_IQUERY;
//
// add the given RR as the answer
//
$packet->answer[] = $rr;
$packet->header->ancount = 1;
//
// check for an authentication method; either TSIG or SIG
//
if ( ($this->auth_signature instanceof Net_DNS2_RR_TSIG)
|| ($this->auth_signature instanceof Net_DNS2_RR_SIG)
) {
$packet->additional[] = $this->auth_signature;
$packet->header->arcount = count($packet->additional);
}
//
// send the packet and get back the response
//
return $this->sendPacket($packet, $this->use_tcp);
}
}

View File

@ -0,0 +1,440 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/*
* check to see if the socket defines exist; if they don't, then define them
*/
if (defined('SOCK_STREAM') == false) {
define('SOCK_STREAM', 1);
}
if (defined('SOCK_DGRAM') == false) {
define('SOCK_DGRAM', 2);
}
/**
* Socket handling class using the PHP Streams
*
*/
class Net_DNS2_Socket
{
private $sock;
private $type;
private $host;
private $port;
private $timeout;
private $context;
/*
* the local IP and port we'll send the request from
*/
private $local_host;
private $local_port;
/*
* the last error message on the object
*/
public $last_error;
/*
* date the socket connection was created, and the date it was last used
*/
public $date_created;
public $date_last_used;
/*
* type of sockets
*/
const SOCK_STREAM = SOCK_STREAM;
const SOCK_DGRAM = SOCK_DGRAM;
/**
* constructor - set the port details
*
* @param integer $type the socket type
* @param string $host the IP address of the DNS server to connect to
* @param integer $port the port of the DNS server to connect to
* @param integer $timeout the timeout value to use for socket functions
*
* @access public
*
*/
public function __construct($type, $host, $port, $timeout)
{
$this->type = $type;
$this->host = $host;
$this->port = $port;
$this->timeout = $timeout;
$this->date_created = microtime(true);
}
/**
* destructor
*
* @access public
*/
public function __destruct()
{
$this->close();
}
/**
* sets the local address/port for the socket to bind to
*
* @param string $address the local IP address to bind to
* @param mixed $port the local port to bind to, or 0 to let the socket
* function select a port
*
* @return boolean
* @access public
*
*/
public function bindAddress($address, $port = 0)
{
$this->local_host = $address;
$this->local_port = $port;
return true;
}
/**
* opens a socket connection to the DNS server
*
* @return boolean
* @access public
*
*/
public function open()
{
//
// create a list of options for the context
//
$opts = [ 'socket' => [] ];
//
// bind to a local IP/port if it's set
//
if (strlen($this->local_host) > 0) {
$opts['socket']['bindto'] = $this->local_host;
if ($this->local_port > 0) {
$opts['socket']['bindto'] .= ':' . $this->local_port;
}
}
//
// create the context
//
$this->context = @stream_context_create($opts);
//
// create socket
//
$errno;
$errstr;
switch($this->type) {
case Net_DNS2_Socket::SOCK_STREAM:
if (Net_DNS2::isIPv4($this->host) == true) {
$this->sock = @stream_socket_client(
'tcp://' . $this->host . ':' . $this->port,
$errno, $errstr, $this->timeout,
STREAM_CLIENT_CONNECT, $this->context
);
} else if (Net_DNS2::isIPv6($this->host) == true) {
$this->sock = @stream_socket_client(
'tcp://[' . $this->host . ']:' . $this->port,
$errno, $errstr, $this->timeout,
STREAM_CLIENT_CONNECT, $this->context
);
} else {
$this->last_error = 'invalid address type: ' . $this->host;
return false;
}
break;
case Net_DNS2_Socket::SOCK_DGRAM:
if (Net_DNS2::isIPv4($this->host) == true) {
$this->sock = @stream_socket_client(
'udp://' . $this->host . ':' . $this->port,
$errno, $errstr, $this->timeout,
STREAM_CLIENT_CONNECT, $this->context
);
} else if (Net_DNS2::isIPv6($this->host) == true) {
$this->sock = @stream_socket_client(
'udp://[' . $this->host . ']:' . $this->port,
$errno, $errstr, $this->timeout,
STREAM_CLIENT_CONNECT, $this->context
);
} else {
$this->last_error = 'invalid address type: ' . $this->host;
return false;
}
break;
default:
$this->last_error = 'Invalid socket type: ' . $this->type;
return false;
}
if ($this->sock === false) {
$this->last_error = $errstr;
return false;
}
//
// set it to non-blocking and set the timeout
//
@stream_set_blocking($this->sock, 0);
@stream_set_timeout($this->sock, $this->timeout);
return true;
}
/**
* closes a socket connection to the DNS server
*
* @return boolean
* @access public
*
*/
public function close()
{
if (is_resource($this->sock) === true) {
@fclose($this->sock);
}
return true;
}
/**
* writes the given string to the DNS server socket
*
* @param string $data a binary packed DNS packet
*
* @return boolean
* @access public
*
*/
public function write($data)
{
$length = strlen($data);
if ($length == 0) {
$this->last_error = 'empty data on write()';
return false;
}
$read = null;
$write = [ $this->sock ];
$except = null;
//
// increment the date last used timestamp
//
$this->date_last_used = microtime(true);
//
// select on write
//
$result = stream_select($read, $write, $except, $this->timeout);
if ($result === false) {
$this->last_error = 'failed on write select()';
return false;
} else if ($result == 0) {
$this->last_error = 'timeout on write select()';
return false;
}
//
// if it's a TCP socket, then we need to packet and send the length of the
// data as the first 16bit of data.
//
if ($this->type == Net_DNS2_Socket::SOCK_STREAM) {
$s = chr($length >> 8) . chr($length);
if (@fwrite($this->sock, $s) === false) {
$this->last_error = 'failed to fwrite() 16bit length';
return false;
}
}
//
// write the data to the socket
//
$size = @fwrite($this->sock, $data);
if ( ($size === false) || ($size != $length) ) {
$this->last_error = 'failed to fwrite() packet';
return false;
}
return true;
}
/**
* reads a response from a DNS server
*
* @param integer &$size the size of the DNS packet read is passed back
* @param integer $max_size the max data size returned.
*
* @return mixed returns the data on success and false on error
* @access public
*
*/
public function read(&$size, $max_size)
{
$read = [ $this->sock ];
$write = null;
$except = null;
//
// increment the date last used timestamp
//
$this->date_last_used = microtime(true);
//
// make sure our socket is non-blocking
//
@stream_set_blocking($this->sock, 0);
//
// select on read
//
$result = stream_select($read, $write, $except, $this->timeout);
if ($result === false) {
$this->last_error = 'error on read select()';
return false;
} else if ($result == 0) {
$this->last_error = 'timeout on read select()';
return false;
}
$data = '';
$length = $max_size;
//
// if it's a TCP socket, then the first two bytes is the length of the DNS
// packet- we need to read that off first, then use that value for the
// packet read.
//
if ($this->type == Net_DNS2_Socket::SOCK_STREAM) {
if (($data = fread($this->sock, 2)) === false) {
$this->last_error = 'failed on fread() for data length';
return false;
}
if (strlen($data) == 0)
{
$this->last_error = 'failed on fread() for data length';
return false;
}
$length = ord($data[0]) << 8 | ord($data[1]);
if ($length < Net_DNS2_Lookups::DNS_HEADER_SIZE) {
return false;
}
}
//
// at this point, we know that there is data on the socket to be read,
// because we've already extracted the length from the first two bytes.
//
// so the easiest thing to do, is just turn off socket blocking, and
// wait for the data.
//
@stream_set_blocking($this->sock, 1);
//
// read the data from the socket
//
$data = '';
//
// the streams socket is weird for TCP sockets; it doesn't seem to always
// return all the data properly; but the looping code I added broke UDP
// packets- my fault-
//
// the sockets library works much better.
//
if ($this->type == Net_DNS2_Socket::SOCK_STREAM) {
$chunk = '';
$chunk_size = $length;
//
// loop so we make sure we read all the data
//
while (1) {
$chunk = fread($this->sock, $chunk_size);
if ($chunk === false) {
$this->last_error = 'failed on fread() for data';
return false;
}
$data .= $chunk;
$chunk_size -= strlen($chunk);
if (strlen($data) >= $length) {
break;
}
}
} else {
//
// if it's UDP, it's a single fixed-size frame, and the streams library
// doesn't seem to have a problem reading it.
//
$data = fread($this->sock, $length);
if ($length === false) {
$this->last_error = 'failed on fread() for data';
return false;
}
}
$size = strlen($data);
return $data;
}
}

View File

@ -0,0 +1,606 @@
<?php
/**
* DNS Library for handling lookups and updates.
*
* Copyright (c) 2020, Mike Pultz <mike@mikepultz.com>. All rights reserved.
*
* See LICENSE for more details.
*
* @category Networking
* @package Net_DNS2
* @author Mike Pultz <mike@mikepultz.com>
* @copyright 2020 Mike Pultz <mike@mikepultz.com>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link https://netdns2.com/
* @since File available since Release 0.6.0
*
*/
/**
* The main dynamic DNS updater class.
*
* This class provices functions to handle all defined dynamic DNS update
* requests as defined by RFC 2136.
*
* This is separate from the Net_DNS2_Resolver class, as while the underlying
* protocol is the same, the functionality is completely different.
*
* Generally, query (recursive) lookups are done against caching server, while
* update requests are done against authoratative servers.
*
*/
class Net_DNS2_Updater extends Net_DNS2
{
/*
* a Net_DNS2_Packet_Request object used for the update request
*/
private $_packet;
/**
* Constructor - builds a new Net_DNS2_Updater objected used for doing
* dynamic DNS updates
*
* @param string $zone the domain name to use for DNS updates
* @param mixed $options an array of config options or null
*
* @throws Net_DNS2_Exception
* @access public
*
*/
public function __construct($zone, array $options = null)
{
parent::__construct($options);
//
// create the packet
//
$this->_packet = new Net_DNS2_Packet_Request(
strtolower(trim($zone, " \n\r\t.")), 'SOA', 'IN'
);
//
// make sure the opcode on the packet is set to UPDATE
//
$this->_packet->header->opcode = Net_DNS2_Lookups::OPCODE_UPDATE;
}
/**
* checks that the given name matches the name for the zone we're updating
*
* @param string $name The name to be checked.
*
* @return boolean
* @throws Net_DNS2_Exception
* @access private
*
*/
private function _checkName($name)
{
if (!preg_match('/' . $this->_packet->question[0]->qname . '$/', $name)) {
throw new Net_DNS2_Exception(
'name provided (' . $name . ') does not match zone name (' .
$this->_packet->question[0]->qname . ')',
Net_DNS2_Lookups::E_PACKET_INVALID
);
}
return true;
}
/**
* add a signature to the request for authentication
*
* @param string $keyname the key name to use for the TSIG RR
* @param string $signature the key to sign the request.
*
* @return boolean
* @access public
* @see Net_DNS2::signTSIG()
* @deprecated function deprecated in 1.1.0
*
*/
public function signature($keyname, $signature)
{
return $this->signTSIG($keyname, $signature);
}
/**
* 2.5.1 - Add To An RRset
*
* RRs are added to the Update Section whose NAME, TYPE, TTL, RDLENGTH
* and RDATA are those being added, and CLASS is the same as the zone
* class. Any duplicate RRs will be silently ignored by the primary
* master.
*
* @param Net_DNS2_RR $rr the Net_DNS2_RR object to be added to the zone
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function add(Net_DNS2_RR $rr)
{
$this->_checkName($rr->name);
//
// add the RR to the "update" section
//
if (!in_array($rr, $this->_packet->authority)) {
$this->_packet->authority[] = $rr;
}
return true;
}
/**
* 2.5.4 - Delete An RR From An RRset
*
* RRs to be deleted are added to the Update Section. The NAME, TYPE,
* RDLENGTH and RDATA must match the RR being deleted. TTL must be
* specified as zero (0) and will otherwise be ignored by the primary
* master. CLASS must be specified as NONE to distinguish this from an
* RR addition. If no such RRs exist, then this Update RR will be
* silently ignored by the primary master.
*
* @param Net_DNS2_RR $rr the Net_DNS2_RR object to be deleted from the zone
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function delete(Net_DNS2_RR $rr)
{
$this->_checkName($rr->name);
$rr->ttl = 0;
$rr->class = 'NONE';
//
// add the RR to the "update" section
//
if (!in_array($rr, $this->_packet->authority)) {
$this->_packet->authority[] = $rr;
}
return true;
}
/**
* 2.5.2 - Delete An RRset
*
* One RR is added to the Update Section whose NAME and TYPE are those
* of the RRset to be deleted. TTL must be specified as zero (0) and is
* otherwise not used by the primary master. CLASS must be specified as
* ANY. RDLENGTH must be zero (0) and RDATA must therefore be empty.
* If no such RRset exists, then this Update RR will be silently ignored
* by the primary master
*
* @param string $name the RR name to be removed from the zone
* @param string $type the RR type to be removed from the zone
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function deleteAny($name, $type)
{
$this->_checkName($name);
$class = Net_DNS2_Lookups::$rr_types_id_to_class[
Net_DNS2_Lookups::$rr_types_by_name[$type]
];
if (!isset($class)) {
throw new Net_DNS2_Exception(
'unknown or un-supported resource record type: ' . $type,
Net_DNS2_Lookups::E_RR_INVALID
);
}
$rr = new $class;
$rr->name = $name;
$rr->ttl = 0;
$rr->class = 'ANY';
$rr->rdlength = -1;
$rr->rdata = '';
//
// add the RR to the "update" section
//
if (!in_array($rr, $this->_packet->authority)) {
$this->_packet->authority[] = $rr;
}
return true;
}
/**
* 2.5.3 - Delete All RRsets From A Name
*
* One RR is added to the Update Section whose NAME is that of the name
* to be cleansed of RRsets. TYPE must be specified as ANY. TTL must
* be specified as zero (0) and is otherwise not used by the primary
* master. CLASS must be specified as ANY. RDLENGTH must be zero (0)
* and RDATA must therefore be empty. If no such RRsets exist, then
* this Update RR will be silently ignored by the primary master.
*
* @param string $name the RR name to be removed from the zone
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function deleteAll($name)
{
$this->_checkName($name);
//
// the Net_DNS2_RR_ANY class is just an empty stub class used for these
// cases only
//
$rr = new Net_DNS2_RR_ANY;
$rr->name = $name;
$rr->ttl = 0;
$rr->type = 'ANY';
$rr->class = 'ANY';
$rr->rdlength = -1;
$rr->rdata = '';
//
// add the RR to the "update" section
//
if (!in_array($rr, $this->_packet->authority)) {
$this->_packet->authority[] = $rr;
}
return true;
}
/**
* 2.4.1 - RRset Exists (Value Independent)
*
* At least one RR with a specified NAME and TYPE (in the zone and class
* specified in the Zone Section) must exist.
*
* For this prerequisite, a requestor adds to the section a single RR
* whose NAME and TYPE are equal to that of the zone RRset whose
* existence is required. RDLENGTH is zero and RDATA is therefore
* empty. CLASS must be specified as ANY to differentiate this
* condition from that of an actual RR whose RDLENGTH is naturally zero
* (0) (e.g., NULL). TTL is specified as zero (0).
*
* @param string $name the RR name for the prerequisite
* @param string $type the RR type for the prerequisite
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function checkExists($name, $type)
{
$this->_checkName($name);
$class = Net_DNS2_Lookups::$rr_types_id_to_class[
Net_DNS2_Lookups::$rr_types_by_name[$type]
];
if (!isset($class)) {
throw new Net_DNS2_Exception(
'unknown or un-supported resource record type: ' . $type,
Net_DNS2_Lookups::E_RR_INVALID
);
}
$rr = new $class;
$rr->name = $name;
$rr->ttl = 0;
$rr->class = 'ANY';
$rr->rdlength = -1;
$rr->rdata = '';
//
// add the RR to the "prerequisite" section
//
if (!in_array($rr, $this->_packet->answer)) {
$this->_packet->answer[] = $rr;
}
return true;
}
/**
* 2.4.2 - RRset Exists (Value Dependent)
*
* A set of RRs with a specified NAME and TYPE exists and has the same
* members with the same RDATAs as the RRset specified here in this
* section. While RRset ordering is undefined and therefore not
* significant to this comparison, the sets be identical in their
* extent.
*
* For this prerequisite, a requestor adds to the section an entire
* RRset whose preexistence is required. NAME and TYPE are that of the
* RRset being denoted. CLASS is that of the zone. TTL must be
* specified as zero (0) and is ignored when comparing RRsets for
* identity.
*
* @param Net_DNS2_RR $rr the RR object to be used as a prerequisite
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function checkValueExists(Net_DNS2_RR $rr)
{
$this->_checkName($rr->name);
$rr->ttl = 0;
//
// add the RR to the "prerequisite" section
//
if (!in_array($rr, $this->_packet->answer)) {
$this->_packet->answer[] = $rr;
}
return true;
}
/**
* 2.4.3 - RRset Does Not Exist
*
* No RRs with a specified NAME and TYPE (in the zone and class denoted
* by the Zone Section) can exist.
*
* For this prerequisite, a requestor adds to the section a single RR
* whose NAME and TYPE are equal to that of the RRset whose nonexistence
* is required. The RDLENGTH of this record is zero (0), and RDATA
* field is therefore empty. CLASS must be specified as NONE in order
* to distinguish this condition from a valid RR whose RDLENGTH is
* naturally zero (0) (for example, the NULL RR). TTL must be specified
* as zero (0).
*
* @param string $name the RR name for the prerequisite
* @param string $type the RR type for the prerequisite
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function checkNotExists($name, $type)
{
$this->_checkName($name);
$class = Net_DNS2_Lookups::$rr_types_id_to_class[
Net_DNS2_Lookups::$rr_types_by_name[$type]
];
if (!isset($class)) {
throw new Net_DNS2_Exception(
'unknown or un-supported resource record type: ' . $type,
Net_DNS2_Lookups::E_RR_INVALID
);
}
$rr = new $class;
$rr->name = $name;
$rr->ttl = 0;
$rr->class = 'NONE';
$rr->rdlength = -1;
$rr->rdata = '';
//
// add the RR to the "prerequisite" section
//
if (!in_array($rr, $this->_packet->answer)) {
$this->_packet->answer[] = $rr;
}
return true;
}
/**
* 2.4.4 - Name Is In Use
*
* Name is in use. At least one RR with a specified NAME (in the zone
* and class specified by the Zone Section) must exist. Note that this
* prerequisite is NOT satisfied by empty nonterminals.
*
* For this prerequisite, a requestor adds to the section a single RR
* whose NAME is equal to that of the name whose ownership of an RR is
* required. RDLENGTH is zero and RDATA is therefore empty. CLASS must
* be specified as ANY to differentiate this condition from that of an
* actual RR whose RDLENGTH is naturally zero (0) (e.g., NULL). TYPE
* must be specified as ANY to differentiate this case from that of an
* RRset existence test. TTL is specified as zero (0).
*
* @param string $name the RR name for the prerequisite
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function checkNameInUse($name)
{
$this->_checkName($name);
//
// the Net_DNS2_RR_ANY class is just an empty stub class used for these
// cases only
//
$rr = new Net_DNS2_RR_ANY;
$rr->name = $name;
$rr->ttl = 0;
$rr->type = 'ANY';
$rr->class = 'ANY';
$rr->rdlength = -1;
$rr->rdata = '';
//
// add the RR to the "prerequisite" section
//
if (!in_array($rr, $this->_packet->answer)) {
$this->_packet->answer[] = $rr;
}
return true;
}
/**
* 2.4.5 - Name Is Not In Use
*
* Name is not in use. No RR of any type is owned by a specified NAME.
* Note that this prerequisite IS satisfied by empty nonterminals.
*
* For this prerequisite, a requestor adds to the section a single RR
* whose NAME is equal to that of the name whose nonownership of any RRs
* is required. RDLENGTH is zero and RDATA is therefore empty. CLASS
* must be specified as NONE. TYPE must be specified as ANY. TTL must
* be specified as zero (0).
*
* @param string $name the RR name for the prerequisite
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function checkNameNotInUse($name)
{
$this->_checkName($name);
//
// the Net_DNS2_RR_ANY class is just an empty stub class used for these
// cases only
//
$rr = new Net_DNS2_RR_ANY;
$rr->name = $name;
$rr->ttl = 0;
$rr->type = 'ANY';
$rr->class = 'NONE';
$rr->rdlength = -1;
$rr->rdata = '';
//
// add the RR to the "prerequisite" section
//
if (!in_array($rr, $this->_packet->answer)) {
$this->_packet->answer[] = $rr;
}
return true;
}
/**
* returns the current internal packet object.
*
* @return Net_DNS2_Packet_Request
* @access public
#
*/
public function packet()
{
//
// take a copy
//
$p = $this->_packet;
//
// check for an authentication method; either TSIG or SIG
//
if ( ($this->auth_signature instanceof Net_DNS2_RR_TSIG)
|| ($this->auth_signature instanceof Net_DNS2_RR_SIG)
) {
$p->additional[] = $this->auth_signature;
}
//
// update the counts
//
$p->header->qdcount = count($p->question);
$p->header->ancount = count($p->answer);
$p->header->nscount = count($p->authority);
$p->header->arcount = count($p->additional);
return $p;
}
/**
* executes the update request with the object informaton
*
* @param Net_DNS2_Packet_Response &$response ref to the response object
*
* @return boolean
* @throws Net_DNS2_Exception
* @access public
*
*/
public function update(&$response = null)
{
//
// make sure we have some name servers set
//
$this->checkServers(Net_DNS2::RESOLV_CONF);
//
// check for an authentication method; either TSIG or SIG
//
if ( ($this->auth_signature instanceof Net_DNS2_RR_TSIG)
|| ($this->auth_signature instanceof Net_DNS2_RR_SIG)
) {
$this->_packet->additional[] = $this->auth_signature;
}
//
// update the counts
//
$this->_packet->header->qdcount = count($this->_packet->question);
$this->_packet->header->ancount = count($this->_packet->answer);
$this->_packet->header->nscount = count($this->_packet->authority);
$this->_packet->header->arcount = count($this->_packet->additional);
//
// make sure we have some data to send
//
if ( ($this->_packet->header->qdcount == 0)
|| ($this->_packet->header->nscount == 0)
) {
throw new Net_DNS2_Exception(
'empty headers- nothing to send!',
Net_DNS2_Lookups::E_PACKET_INVALID
);
}
//
// send the packet and get back the response
//
$response = $this->sendPacket($this->_packet, $this->use_tcp);
//
// clear the internal packet so if we make another request, we don't have
// old data being sent.
//
$this->_packet->reset();
//
// for updates, we just need to know it worked- we don't actualy need to
// return the response object
//
return true;
}
}

462
libs/pear/Net/IPv4.php Normal file
View File

@ -0,0 +1,462 @@
<?php
/**
* Class to provide IPv4 calculations
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.01 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_01.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Net
* @package Net_IPv4
* @author Eric Kilfoil <edk@ypass.net>
* @author Marco Kaiser <bate@php.net>
* @author Florian Anderiasch <fa@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: $Id: IPv4.php 302879 2010-08-30 06:52:41Z bate $
* @link http://pear.php.net/package/Net_IPv4
*/
require_once 'PEAR.php';
// {{{ Net_IPv4
/**
* Class to provide IPv4 calculations
*
* Provides methods for validating IP addresses, calculating netmasks,
* broadcast addresses, network addresses, conversion routines, etc.
*
* @category Net
* @package Net_IPv4
* @author Eric Kilfoil <edk@ypass.net>
* @author Marco Kaiser <bate@php.net>
* @author Florian Anderiasch <fa@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_01.txt PHP License 3.01
* @version CVS: @package_version@
* @link http://pear.php.net/package/Net_IPv4
* @access public
*/
class Net_IPv4
{
// {{{ properties
var $ip = "";
var $bitmask = false;
var $netmask = "";
var $network = "";
var $broadcast = "";
var $long = 0;
// }}}
// {{{ private
/**
* Map of bitmasks to subnets
*
* This array contains every valid netmask. The index of the dot quad
* netmask value is the corresponding CIDR notation (bitmask).
*
*/
public static $Net_IPv4_Netmask_Map = array(
0 => "0.0.0.0",
1 => "128.0.0.0",
2 => "192.0.0.0",
3 => "224.0.0.0",
4 => "240.0.0.0",
5 => "248.0.0.0",
6 => "252.0.0.0",
7 => "254.0.0.0",
8 => "255.0.0.0",
9 => "255.128.0.0",
10 => "255.192.0.0",
11 => "255.224.0.0",
12 => "255.240.0.0",
13 => "255.248.0.0",
14 => "255.252.0.0",
15 => "255.254.0.0",
16 => "255.255.0.0",
17 => "255.255.128.0",
18 => "255.255.192.0",
19 => "255.255.224.0",
20 => "255.255.240.0",
21 => "255.255.248.0",
22 => "255.255.252.0",
23 => "255.255.254.0",
24 => "255.255.255.0",
25 => "255.255.255.128",
26 => "255.255.255.192",
27 => "255.255.255.224",
28 => "255.255.255.240",
29 => "255.255.255.248",
30 => "255.255.255.252",
31 => "255.255.255.254",
32 => "255.255.255.255"
);
// }}}
// {{{ validateIP()
/**
* Validate the syntax of the given IP adress
*
* Using the PHP long2ip() and ip2long() functions, convert the IP
* address from a string to a long and back. If the original still
* matches the converted IP address, it's a valid address. This
* function does not allow for IP addresses to be formatted as long
* integers.
*
* @param string $ip IP address in the format x.x.x.x
* @return bool true if syntax is valid, otherwise false
*/
public static function validateIP($ip)
{
if ($ip == long2ip(ip2long($ip))) {
return true;
} else {
return false;
}
}
// }}}
// {{{ check_ip()
/**
* Validate the syntax of the given IP address (compatibility)
*
* This function is identical to Net_IPv4::validateIP(). It is included
* merely for compatibility reasons.
*
* @param string $ip IP address
* @return bool true if syntax is valid, otherwise false
*/
public static function check_ip($ip)
{
return Net_IPv4::validateIP($ip);
}
// }}}
// {{{ validateNetmask()
/**
* Validate the syntax of a four octet netmask
*
* There are 33 valid netmask values. This function will compare the
* string passed as $netmask to the predefined 33 values and return
* true or false. This is most likely much faster than performing the
* calculation to determine the validity of the netmask.
*
* @param string $netmask Netmask
* @return bool true if syntax is valid, otherwise false
*/
public static function validateNetmask($netmask)
{
if (! in_array($netmask, self::$Net_IPv4_Netmask_Map)) {
return false;
}
return true;
}
// }}}
// {{{ parseAddress()
/**
* Parse a formatted IP address
*
* Given a network qualified IP address, attempt to parse out the parts
* and calculate qualities of the address.
*
* The following formats are possible:
*
* [dot quad ip]/[ bitmask ]
* [dot quad ip]/[ dot quad netmask ]
* [dot quad ip]/[ hex string netmask ]
*
* The first would be [IP Address]/[BitMask]:
* 192.168.0.0/16
*
* The second would be [IP Address] [Subnet Mask in dot quad notation]:
* 192.168.0.0/255.255.0.0
*
* The third would be [IP Address] [Subnet Mask as Hex string]
* 192.168.0.0/ffff0000
*
* Usage:
*
* $cidr = '192.168.0.50/16';
* $net = Net_IPv4::parseAddress($cidr);
* echo $net->network; // 192.168.0.0
* echo $net->ip; // 192.168.0.50
* echo $net->broadcast; // 192.168.255.255
* echo $net->bitmask; // 16
* echo $net->long; // 3232235520 (long/double version of 192.168.0.50)
* echo $net->netmask; // 255.255.0.0
*
* @param string $ip IP address netmask combination
* @return object true if syntax is valid, otherwise false
*/
public static function parseAddress($address)
{
$myself = new Net_IPv4;
if (strchr($address, "/")) {
$parts = explode("/", $address);
if (! $myself->validateIP($parts[0])) {
return PEAR::raiseError("invalid IP address");
}
$myself->ip = $parts[0];
// Check the style of netmask that was entered
/*
* a hexadecimal string was entered
*/
if (preg_match("/^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i", $parts[1], $regs)) {
// hexadecimal string
$myself->netmask = hexdec($regs[1]) . "." . hexdec($regs[2]) . "." .
hexdec($regs[3]) . "." . hexdec($regs[4]);
/*
* a standard dot quad netmask was entered.
*/
} else if (strchr($parts[1], ".")) {
if (! $myself->validateNetmask($parts[1])) {
return PEAR::raiseError("invalid netmask value");
}
$myself->netmask = $parts[1];
/*
* a CIDR bitmask type was entered
*/
} else if (ctype_digit($parts[1]) && $parts[1] >= 0 && $parts[1] <= 32) {
// bitmask was entered
$myself->bitmask = $parts[1];
/*
* Some unknown format of netmask was entered
*/
} else {
return PEAR::raiseError("invalid netmask value");
}
$myself->calculate();
return $myself;
} else if ($myself->validateIP($address)) {
$myself->ip = $address;
return $myself;
} else {
return PEAR::raiseError("invalid IP address");
}
}
// }}}
// {{{ calculate()
/**
* Calculates network information based on an IP address and netmask.
*
* Fully populates the object properties based on the IP address and
* netmask/bitmask properties. Once these two fields are populated,
* calculate() will perform calculations to determine the network and
* broadcast address of the network.
*
* @return mixed true if no errors occured, otherwise PEAR_Error object
*/
public function calculate()
{
$validNM = self::$Net_IPv4_Netmask_Map;
if (! is_a($this, "net_ipv4")) {
$myself = new Net_IPv4;
return PEAR::raiseError("cannot calculate on uninstantiated Net_IPv4 class");
}
/* Find out if we were given an ip address in dot quad notation or
* a network long ip address. Whichever was given, populate the
* other field
*/
if (strlen($this->ip)) {
if (! $this->validateIP($this->ip)) {
return PEAR::raiseError("invalid IP address");
}
$this->long = $this->ip2double($this->ip);
} else if (is_numeric($this->long)) {
$this->ip = long2ip($this->long);
} else {
return PEAR::raiseError("ip address not specified");
}
/*
* Check to see if we were supplied with a bitmask or a netmask.
* Populate the other field as needed.
*/
if (strlen($this->bitmask)) {
$this->netmask = $validNM[$this->bitmask];
} else if (strlen($this->netmask)) {
$validNM_rev = array_flip($validNM);
$this->bitmask = $validNM_rev[$this->netmask];
} else {
return PEAR::raiseError("netmask or bitmask are required for calculation");
}
$this->network = long2ip(ip2long($this->ip) & ip2long($this->netmask));
$this->broadcast = long2ip(ip2long($this->ip) |
(ip2long($this->netmask) ^ ip2long("255.255.255.255")));
return true;
}
// }}}
// {{{ getNetmask()
public static function getNetmask($length)
{
if (! PEAR::isError($ipobj = Net_IPv4::parseAddress("0.0.0.0/" . $length))) {
$mask = $ipobj->netmask;
unset($ipobj);
return $mask;
}
return false;
}
// }}}
// {{{ getNetLength()
public static function getNetLength($netmask)
{
if (! PEAR::isError($ipobj = Net_IPv4::parseAddress("0.0.0.0/" . $netmask))) {
$bitmask = $ipobj->bitmask;
unset($ipobj);
return $bitmask;
}
return false;
}
// }}}
// {{{ getSubnet()
public static function getSubnet($ip, $netmask)
{
if (! PEAR::isError($ipobj = Net_IPv4::parseAddress($ip . "/" . $netmask))) {
$net = $ipobj->network;
unset($ipobj);
return $net;
}
return false;
}
// }}}
// {{{ inSameSubnet()
public static function inSameSubnet($ip1, $ip2)
{
if (! is_object($ip1) || strcasecmp(get_class($ip1), 'net_ipv4') <> 0) {
$ipobj1 = Net_IPv4::parseAddress($ip1);
if (PEAR::isError($ipobj)) {
return PEAR::raiseError("IP addresses must be an understood format or a Net_IPv4 object");
}
}
if (! is_object($ip2) || strcasecmp(get_class($ip2), 'net_ipv4') <> 0) {
$ipobj2 = Net_IPv4::parseAddress($ip2);
if (PEAR::isError($ipobj)) {
return PEAR::raiseError("IP addresses must be an understood format or a Net_IPv4 object");
}
}
if ($ipobj1->network == $ipobj2->network &&
$ipobj1->bitmask == $ipobj2->bitmask) {
return true;
}
return false;
}
// }}}
// {{{ atoh()
/**
* Converts a dot-quad formatted IP address into a hexadecimal string
* @param string $addr IP-adress in dot-quad format
* @return mixed false if invalid IP and hexadecimal representation as string if valid
*/
public static function atoh($addr)
{
if (! Net_IPv4::validateIP($addr)) {
return false;
}
$ap = explode(".", $addr);
return sprintf("%02x%02x%02x%02x", $ap[0], $ap[1], $ap[2], $ap[3]);
}
// }}}
// {{{ htoa()
/**
* Converts a hexadecimal string into a dot-quad formatted IP address
* @param string $addr IP-adress in hexadecimal format
* @return mixed false if invalid IP and dot-quad formatted IP as string if valid
*/
public static function htoa($addr)
{
if (preg_match("/^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i",
$addr, $regs)) {
return hexdec($regs[1]) . "." . hexdec($regs[2]) . "." .
hexdec($regs[3]) . "." . hexdec($regs[4]);
}
return false;
}
// }}}
// {{{ ip2double()
/**
* Converts an IP address to a PHP double. Better than ip2long because
* a long in PHP is a signed integer.
* @param string $ip dot-quad formatted IP adress
* @return float IP adress as double - positive value unlike ip2long
*/
public static function ip2double($ip)
{
return (double)(sprintf("%u", ip2long($ip)));
}
// }}}
// {{{ ipInNetwork()
/**
* Determines whether or not the supplied IP is within the supplied network.
*
* This function determines whether an IP address is within a network.
* The IP address ($ip) must be supplied in dot-quad format, and the
* network ($network) may be either a string containing a CIDR
* formatted network definition, or a Net_IPv4 object.
*
* @param string $ip A dot quad representation of an IP address
* @param string $network A string representing the network in CIDR format or a Net_IPv4 object.
* @return bool true if the IP address exists within the network
*/
public static function ipInNetwork($ip, $network)
{
if (! is_object($network) || strcasecmp(get_class($network), 'net_ipv4') <> 0) {
$network = Net_IPv4::parseAddress($network);
}
if (strcasecmp(get_class($network), 'pear_error') === 0) {
return false;
}
$net = Net_IPv4::ip2double($network->network);
$bcast = Net_IPv4::ip2double($network->broadcast);
$ip = Net_IPv4::ip2double($ip);
unset($network);
if ($ip >= $net && $ip <= $bcast) {
return true;
}
return false;
}
// }}}
}
// }}}
/*
* vim: sts=4 ts=4 sw=4 cindent fdm=marker
*/
?>

1124
libs/pear/Net/IPv6.php Normal file

File diff suppressed because it is too large Load Diff

1435
libs/pear/Net/SMTP.php Normal file

File diff suppressed because it is too large Load Diff

738
libs/pear/Net/Socket.php Normal file
View File

@ -0,0 +1,738 @@
<?php
/**
* Net_Socket
*
* PHP Version 5
*
* LICENSE:
*
* Copyright (c) 1997-2017 The PHP Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* o Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* o Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Net
* @package Net_Socket
* @author Stig Bakken <ssb@php.net>
* @author Chuck Hagenbuch <chuck@horde.org>
* @copyright 1997-2017 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause
* @link http://pear.php.net/packages/Net_Socket
*/
require_once 'PEAR.php';
define('NET_SOCKET_READ', 1);
define('NET_SOCKET_WRITE', 2);
define('NET_SOCKET_ERROR', 4);
/**
* Generalized Socket class.
*
* @category Net
* @package Net_Socket
* @author Stig Bakken <ssb@php.net>
* @author Chuck Hagenbuch <chuck@horde.org>
* @copyright 1997-2017 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause
* @link http://pear.php.net/packages/Net_Socket
*/
class Net_Socket extends PEAR
{
/**
* Socket file pointer.
* @var resource $fp
*/
public $fp = null;
/**
* Whether the socket is blocking. Defaults to true.
* @var boolean $blocking
*/
public $blocking = true;
/**
* Whether the socket is persistent. Defaults to false.
* @var boolean $persistent
*/
public $persistent = false;
/**
* The IP address to connect to.
* @var string $addr
*/
public $addr = '';
/**
* The port number to connect to.
* @var integer $port
*/
public $port = 0;
/**
* Number of seconds to wait on socket operations before assuming
* there's no more data. Defaults to no timeout.
* @var integer|float $timeout
*/
public $timeout = null;
/**
* Number of bytes to read at a time in readLine() and
* readAll(). Defaults to 2048.
* @var integer $lineLength
*/
public $lineLength = 2048;
/**
* The string to use as a newline terminator. Usually "\r\n" or "\n".
* @var string $newline
*/
public $newline = "\r\n";
/**
* Connect to the specified port. If called when the socket is
* already connected, it disconnects and connects again.
*
* @param string $addr IP address or host name (may be with protocol prefix).
* @param integer $port TCP port number.
* @param boolean $persistent (optional) Whether the connection is
* persistent (kept open between requests
* by the web server).
* @param integer $timeout (optional) Connection socket timeout.
* @param array $options See options for stream_context_create.
*
* @access public
*
* @return boolean|PEAR_Error True on success or a PEAR_Error on failure.
*/
public function connect(
$addr,
$port = 0,
$persistent = null,
$timeout = null,
$options = null
) {
if (is_resource($this->fp)) {
@fclose($this->fp);
$this->fp = null;
}
if (!$addr) {
return $this->raiseError('$addr cannot be empty');
} else {
if (strspn($addr, ':.0123456789') === strlen($addr)) {
$this->addr = strpos($addr, ':') !== false ? '[' . $addr . ']' : $addr;
} else {
$this->addr = $addr;
}
}
$this->port = $port % 65536;
if ($persistent !== null) {
$this->persistent = $persistent;
}
$openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
$errno = 0;
$errstr = '';
if (function_exists('error_clear_last')) {
error_clear_last();
} else {
$old_track_errors = @ini_set('track_errors', 1);
}
if ($timeout <= 0) {
$timeout = @ini_get('default_socket_timeout');
}
if ($options && function_exists('stream_context_create')) {
$context = stream_context_create($options);
// Since PHP 5 fsockopen doesn't allow context specification
if (function_exists('stream_socket_client')) {
$flags = STREAM_CLIENT_CONNECT;
if ($this->persistent) {
$flags = STREAM_CLIENT_PERSISTENT;
}
$addr = $this->addr . ':' . $this->port;
$fp = @stream_socket_client($addr, $errno, $errstr,
$timeout, $flags, $context);
} else {
$fp = @$openfunc($this->addr, $this->port, $errno,
$errstr, $timeout, $context);
}
} else {
$fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout);
}
if (!$fp) {
if ($errno === 0 && !strlen($errstr)) {
$errstr = '';
if (isset($old_track_errors)) {
$errstr = $php_errormsg ?: '';
@ini_set('track_errors', $old_track_errors);
} else {
$lastError = error_get_last();
if (isset($lastError['message'])) {
$errstr = $lastError['message'];
}
}
}
return $this->raiseError($errstr, $errno);
}
if (isset($old_track_errors)) {
@ini_set('track_errors', $old_track_errors);
}
$this->fp = $fp;
$this->setTimeout();
return $this->setBlocking($this->blocking);
}
/**
* Disconnects from the peer, closes the socket.
*
* @access public
* @return mixed true on success or a PEAR_Error instance otherwise
*/
public function disconnect()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
@fclose($this->fp);
$this->fp = null;
return true;
}
/**
* Set the newline character/sequence to use.
*
* @param string $newline Newline character(s)
* @return boolean True
*/
public function setNewline($newline)
{
$this->newline = $newline;
return true;
}
/**
* Find out if the socket is in blocking mode.
*
* @access public
* @return boolean The current blocking mode.
*/
public function isBlocking()
{
return $this->blocking;
}
/**
* Sets whether the socket connection should be blocking or
* not. A read call to a non-blocking socket will return immediately
* if there is no data available, whereas it will block until there
* is data for blocking sockets.
*
* @param boolean $mode True for blocking sockets, false for nonblocking.
*
* @access public
* @return mixed true on success or a PEAR_Error instance otherwise
*/
public function setBlocking($mode)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$this->blocking = $mode;
stream_set_blocking($this->fp, (int)$this->blocking);
return true;
}
/**
* Sets the timeout value on socket descriptor,
* expressed in the sum of seconds and microseconds
*
* @param integer $seconds Seconds.
* @param integer $microseconds Microseconds, optional.
*
* @access public
* @return mixed True on success or false on failure or
* a PEAR_Error instance when not connected
*/
public function setTimeout($seconds = null, $microseconds = null)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
if ($seconds === null && $microseconds === null) {
$seconds = (int)$this->timeout;
$microseconds = (int)(($this->timeout - $seconds) * 1000000);
} else {
$this->timeout = $seconds + $microseconds / 1000000;
}
if ($this->timeout > 0) {
return stream_set_timeout($this->fp, (int)$seconds, (int)$microseconds);
} else {
return false;
}
}
/**
* Sets the file buffering size on the stream.
* See php's stream_set_write_buffer for more information.
*
* @param integer $size Write buffer size.
*
* @access public
* @return mixed on success or an PEAR_Error object otherwise
*/
public function setWriteBuffer($size)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$returned = stream_set_write_buffer($this->fp, $size);
if ($returned === 0) {
return true;
}
return $this->raiseError('Cannot set write buffer.');
}
/**
* Returns information about an existing socket resource.
* Currently returns four entries in the result array:
*
* <p>
* timed_out (bool) - The socket timed out waiting for data<br>
* blocked (bool) - The socket was blocked<br>
* eof (bool) - Indicates EOF event<br>
* unread_bytes (int) - Number of bytes left in the socket buffer<br>
* </p>
*
* @access public
* @return mixed Array containing information about existing socket
* resource or a PEAR_Error instance otherwise
*/
public function getStatus()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
return stream_get_meta_data($this->fp);
}
/**
* Get a specified line of data
*
* @param int $size Reading ends when size - 1 bytes have been read,
* or a newline or an EOF (whichever comes first).
* If no size is specified, it will keep reading from
* the stream until it reaches the end of the line.
*
* @access public
* @return mixed $size bytes of data from the socket, or a PEAR_Error if
* not connected. If an error occurs, FALSE is returned.
*/
public function gets($size = null)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
if (null === $size) {
return @fgets($this->fp);
} else {
return @fgets($this->fp, $size);
}
}
/**
* Read a specified amount of data. This is guaranteed to return,
* and has the added benefit of getting everything in one fread()
* chunk; if you know the size of the data you're getting
* beforehand, this is definitely the way to go.
*
* @param integer $size The number of bytes to read from the socket.
*
* @access public
* @return string $size bytes of data from the socket, or a PEAR_Error if
* not connected.
*/
public function read($size)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
return @fread($this->fp, $size);
}
/**
* Write a specified amount of data.
*
* @param string $data Data to write.
* @param integer $blocksize Amount of data to write at once.
* NULL means all at once.
*
* @access public
* @return mixed If the socket is not connected, returns an instance of
* PEAR_Error.
* If the write succeeds, returns the number of bytes written.
* If the write fails, returns false.
* If the socket times out, returns an instance of PEAR_Error.
*/
public function write($data, $blocksize = null)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
if (null === $blocksize && !OS_WINDOWS) {
$written = @fwrite($this->fp, $data);
// Check for timeout or lost connection
if ($written === false) {
$meta_data = $this->getStatus();
if (!is_array($meta_data)) {
return $meta_data; // PEAR_Error
}
if (!empty($meta_data['timed_out'])) {
return $this->raiseError('timed out');
}
}
return $written;
} else {
if (null === $blocksize) {
$blocksize = 1024;
}
$pos = 0;
$size = strlen($data);
while ($pos < $size) {
$written = @fwrite($this->fp, substr($data, $pos, $blocksize));
// Check for timeout or lost connection
if ($written === false) {
$meta_data = $this->getStatus();
if (!is_array($meta_data)) {
return $meta_data; // PEAR_Error
}
if (!empty($meta_data['timed_out'])) {
return $this->raiseError('timed out');
}
return $written;
}
$pos += $written;
}
return $pos;
}
}
/**
* Write a line of data to the socket, followed by a trailing newline.
*
* @param string $data Data to write
*
* @access public
* @return mixed fwrite() result, or PEAR_Error when not connected
*/
public function writeLine($data)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
return fwrite($this->fp, $data . $this->newline);
}
/**
* Tests for end-of-file on a socket descriptor.
*
* Also returns true if the socket is disconnected.
*
* @access public
* @return bool
*/
public function eof()
{
return (!is_resource($this->fp) || feof($this->fp));
}
/**
* Reads a byte of data
*
* @access public
* @return integer 1 byte of data from the socket, or a PEAR_Error if
* not connected.
*/
public function readByte()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
return ord(@fread($this->fp, 1));
}
/**
* Reads a word of data
*
* @access public
* @return integer 1 word of data from the socket, or a PEAR_Error if
* not connected.
*/
public function readWord()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$buf = @fread($this->fp, 2);
return (ord($buf[0]) + (ord($buf[1]) << 8));
}
/**
* Reads an int of data
*
* @access public
* @return integer 1 int of data from the socket, or a PEAR_Error if
* not connected.
*/
public function readInt()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$buf = @fread($this->fp, 4);
return (ord($buf[0]) + (ord($buf[1]) << 8) +
(ord($buf[2]) << 16) + (ord($buf[3]) << 24));
}
/**
* Reads a zero-terminated string of data
*
* @access public
* @return string, or a PEAR_Error if
* not connected.
*/
public function readString()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$string = '';
while (($char = @fread($this->fp, 1)) !== "\x00") {
$string .= $char;
}
return $string;
}
/**
* Reads an IP Address and returns it in a dot formatted string
*
* @access public
* @return string Dot formatted string, or a PEAR_Error if
* not connected.
*/
public function readIPAddress()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$buf = @fread($this->fp, 4);
return sprintf('%d.%d.%d.%d', ord($buf[0]), ord($buf[1]),
ord($buf[2]), ord($buf[3]));
}
/**
* Read until either the end of the socket or a newline, whichever
* comes first. Strips the trailing newline from the returned data.
*
* @access public
* @return string All available data up to a newline, without that
* newline, or until the end of the socket, or a PEAR_Error if
* not connected.
*/
public function readLine()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$line = '';
$timeout = time() + $this->timeout;
while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
$line .= @fgets($this->fp, $this->lineLength);
if (substr($line, -1) == "\n") {
return rtrim($line, $this->newline);
}
}
return $line;
}
/**
* Read until the socket closes, or until there is no more data in
* the inner PHP buffer. If the inner buffer is empty, in blocking
* mode we wait for at least 1 byte of data. Therefore, in
* blocking mode, if there is no data at all to be read, this
* function will never exit (unless the socket is closed on the
* remote end).
*
* @access public
*
* @return string All data until the socket closes, or a PEAR_Error if
* not connected.
*/
public function readAll()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$data = '';
$timeout = time() + $this->timeout;
while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
$data .= @fread($this->fp, $this->lineLength);
}
return $data;
}
/**
* Runs the equivalent of the select() system call on the socket
* with a timeout specified by tv_sec and tv_usec.
*
* @param integer $state Which of read/write/error to check for.
* @param integer $tv_sec Number of seconds for timeout.
* @param integer $tv_usec Number of microseconds for timeout.
*
* @access public
* @return False if select fails, integer describing which of read/write/error
* are ready, or PEAR_Error if not connected.
*/
public function select($state, $tv_sec, $tv_usec = 0)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$read = null;
$write = null;
$except = null;
if ($state & NET_SOCKET_READ) {
$read[] = $this->fp;
}
if ($state & NET_SOCKET_WRITE) {
$write[] = $this->fp;
}
if ($state & NET_SOCKET_ERROR) {
$except[] = $this->fp;
}
if (false === ($sr = stream_select($read, $write, $except,
$tv_sec, $tv_usec))
) {
return false;
}
$result = 0;
if (count($read)) {
$result |= NET_SOCKET_READ;
}
if (count($write)) {
$result |= NET_SOCKET_WRITE;
}
if (count($except)) {
$result |= NET_SOCKET_ERROR;
}
return $result;
}
/**
* Turns encryption on/off on a connected socket.
*
* @param bool $enabled Set this parameter to true to enable encryption
* and false to disable encryption.
* @param integer $type Type of encryption. See stream_socket_enable_crypto()
* for values.
*
* @see http://se.php.net/manual/en/function.stream-socket-enable-crypto.php
* @access public
* @return false on error, true on success and 0 if there isn't enough data
* and the user should try again (non-blocking sockets only).
* A PEAR_Error object is returned if the socket is not
* connected
*/
public function enableCrypto($enabled, $type)
{
if (version_compare(phpversion(), '5.1.0', '>=')) {
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
return @stream_socket_enable_crypto($this->fp, $enabled, $type);
} else {
$msg = 'Net_Socket::enableCrypto() requires php version >= 5.1.0';
return $this->raiseError($msg);
}
}
}