PageRenderTime 26ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/bundled-libs/Net/DNS2/RR/SIG.php

http://github.com/s9y/Serendipity
PHP | 459 lines | 153 code | 60 blank | 246 comment | 11 complexity | 550120e35eaf854d95f00da0c4b8cc34 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, Apache-2.0
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * DNS Library for handling lookups and updates.
  5. *
  6. * PHP Version 5
  7. *
  8. * Copyright (c) 2010, Mike Pultz <mike@mikepultz.com>.
  9. * All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. *
  15. * * Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. *
  18. * * Redistributions in binary form must reproduce the above copyright
  19. * notice, this list of conditions and the following disclaimer in
  20. * the documentation and/or other materials provided with the
  21. * distribution.
  22. *
  23. * * Neither the name of Mike Pultz nor the names of his contributors
  24. * may be used to endorse or promote products derived from this
  25. * software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  28. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  29. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  30. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  31. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  32. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  33. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  35. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  37. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. * @category Networking
  41. * @package Net_DNS2
  42. * @author Mike Pultz <mike@mikepultz.com>
  43. * @copyright 2010 Mike Pultz <mike@mikepultz.com>
  44. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  45. * @version SVN: $Id$
  46. * @link http://pear.php.net/package/Net_DNS2
  47. * @since File available since Release 0.6.0
  48. *
  49. * This file contains code based off the Net::DNS::SEC Perl module by
  50. * Olaf M. Kolkman
  51. *
  52. * This is the copyright notice from the PERL Net::DNS::SEC module:
  53. *
  54. * Copyright (c) 2001 - 2005 RIPE NCC. Author Olaf M. Kolkman
  55. * Copyright (c) 2007 - 2008 NLnet Labs. Author Olaf M. Kolkman
  56. * <olaf@net-dns.org>
  57. *
  58. * All Rights Reserved
  59. *
  60. * Permission to use, copy, modify, and distribute this software and its
  61. * documentation for any purpose and without fee is hereby granted,
  62. * provided that the above copyright notice appear in all copies and that
  63. * both that copyright notice and this permission notice appear in
  64. * supporting documentation, and that the name of the author not be
  65. * used in advertising or publicity pertaining to distribution of the
  66. * software without specific, written prior permission.
  67. *
  68. * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  69. * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  70. * AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  71. * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  72. * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  73. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  74. *
  75. */
  76. /**
  77. * SIG Resource Record - RFC2535 section 4.1
  78. *
  79. * 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
  80. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  81. * | Type Covered | Algorithm | Labels |
  82. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  83. * | Original TTL |
  84. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  85. * | Signature Expiration |
  86. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  87. * | Signature Inception |
  88. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  89. * | Key Tag | /
  90. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Signer's Name /
  91. * / /
  92. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  93. * / /
  94. * / Signature /
  95. * / /
  96. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  97. *
  98. * @category Networking
  99. * @package Net_DNS2
  100. * @author Mike Pultz <mike@mikepultz.com>
  101. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  102. * @link http://pear.php.net/package/Net_DNS2
  103. * @see Net_DNS2_RR
  104. *
  105. */
  106. class Net_DNS2_RR_SIG extends Net_DNS2_RR
  107. {
  108. /*
  109. * and instance of a Net_DNS2_PrivateKey object
  110. */
  111. public $private_key = null;
  112. /*
  113. * the RR type covered by this signature
  114. */
  115. public $typecovered;
  116. /*
  117. * the algorithm used for the signature
  118. */
  119. public $algorithm;
  120. /*
  121. * the number of labels in the name
  122. */
  123. public $labels;
  124. /*
  125. * the original TTL
  126. */
  127. public $origttl;
  128. /*
  129. * the signature expiration
  130. */
  131. public $sigexp;
  132. /*
  133. * the inception of the signature
  134. */
  135. public $sigincep;
  136. /*
  137. * the keytag used
  138. */
  139. public $keytag;
  140. /*
  141. * the signer's name
  142. */
  143. public $signname;
  144. /*
  145. * the signature
  146. */
  147. public $signature;
  148. /**
  149. * method to return the rdata portion of the packet as a string
  150. *
  151. * @return string
  152. * @access protected
  153. *
  154. */
  155. protected function rrToString()
  156. {
  157. return $this->typecovered . ' ' . $this->algorithm . ' ' .
  158. $this->labels . ' ' . $this->origttl . ' ' .
  159. $this->sigexp . ' ' . $this->sigincep . ' ' .
  160. $this->keytag . ' ' . $this->cleanString($this->signname) . '. ' .
  161. $this->signature;
  162. }
  163. /**
  164. * parses the rdata portion from a standard DNS config line
  165. *
  166. * @param array $rdata a string split line of values for the rdata
  167. *
  168. * @return boolean
  169. * @access protected
  170. *
  171. */
  172. protected function rrFromString(array $rdata)
  173. {
  174. $this->typecovered = strtoupper(array_shift($rdata));
  175. $this->algorithm = array_shift($rdata);
  176. $this->labels = array_shift($rdata);
  177. $this->origttl = array_shift($rdata);
  178. $this->sigexp = array_shift($rdata);
  179. $this->sigincep = array_shift($rdata);
  180. $this->keytag = array_shift($rdata);
  181. $this->signname = $this->cleanString(array_shift($rdata));
  182. foreach ($rdata as $line) {
  183. $this->signature .= $line;
  184. }
  185. $this->signature = trim($this->signature);
  186. return true;
  187. }
  188. /**
  189. * parses the rdata of the Net_DNS2_Packet object
  190. *
  191. * @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet to parse the RR from
  192. *
  193. * @return boolean
  194. * @access protected
  195. *
  196. */
  197. protected function rrSet(Net_DNS2_Packet &$packet)
  198. {
  199. if ($this->rdlength > 0) {
  200. //
  201. // unpack
  202. //
  203. $x = unpack(
  204. 'ntc/Calgorithm/Clabels/Norigttl/Nsigexp/Nsigincep/nkeytag',
  205. $this->rdata
  206. );
  207. $this->typecovered = Net_DNS2_Lookups::$rr_types_by_id[$x['tc']];
  208. $this->algorithm = $x['algorithm'];
  209. $this->labels = $x['labels'];
  210. $this->origttl = Net_DNS2::expandUint32($x['origttl']);
  211. //
  212. // the dates are in GM time
  213. //
  214. $this->sigexp = gmdate('YmdHis', $x['sigexp']);
  215. $this->sigincep = gmdate('YmdHis', $x['sigincep']);
  216. //
  217. // get the keytag
  218. //
  219. $this->keytag = $x['keytag'];
  220. //
  221. // get teh signers name and signature
  222. //
  223. $offset = $packet->offset + 18;
  224. $sigoffset = $offset;
  225. $this->signname = strtolower(
  226. Net_DNS2_Packet::expand($packet, $sigoffset)
  227. );
  228. $this->signature = base64_encode(
  229. substr($this->rdata, 18 + ($sigoffset - $offset))
  230. );
  231. return true;
  232. }
  233. return false;
  234. }
  235. /**
  236. * returns the rdata portion of the DNS packet
  237. *
  238. * @param Net_DNS2_Packet &$packet a Net_DNS2_Packet packet use for
  239. * compressed names
  240. *
  241. * @return mixed either returns a binary packed
  242. * string or null on failure
  243. * @access protected
  244. *
  245. */
  246. protected function rrGet(Net_DNS2_Packet &$packet)
  247. {
  248. //
  249. // parse the values out of the dates
  250. //
  251. preg_match(
  252. '/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', $this->sigexp, $e
  253. );
  254. preg_match(
  255. '/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/', $this->sigincep, $i
  256. );
  257. //
  258. // pack the value
  259. //
  260. $data = pack(
  261. 'nCCNNNn',
  262. Net_DNS2_Lookups::$rr_types_by_name[$this->typecovered],
  263. $this->algorithm,
  264. $this->labels,
  265. $this->origttl,
  266. gmmktime($e[4], $e[5], $e[6], $e[2], $e[3], $e[1]),
  267. gmmktime($i[4], $i[5], $i[6], $i[2], $i[3], $i[1]),
  268. $this->keytag
  269. );
  270. //
  271. // the signer name is special; it's not allowed to be compressed
  272. // (see section 3.1.7)
  273. //
  274. $names = explode('.', strtolower($this->signname));
  275. foreach ($names as $name) {
  276. $data .= chr(strlen($name));
  277. $data .= $name;
  278. }
  279. $data .= chr('0');
  280. //
  281. // if the signature is empty, and $this->private_key is an instance of a
  282. // private key object, and we have access to openssl, then assume this
  283. // is a SIG(0), and generate a new signature
  284. //
  285. if ( (strlen($this->signature) == 0)
  286. && ($this->private_key instanceof Net_DNS2_PrivateKey)
  287. && (extension_loaded('openssl') === true)
  288. ) {
  289. //
  290. // create a new packet for the signature-
  291. //
  292. $new_packet = new Net_DNS2_Packet_Request('example.com', 'SOA', 'IN');
  293. //
  294. // copy the packet data over
  295. //
  296. $new_packet->copy($packet);
  297. //
  298. // remove the SIG object from the additional list
  299. //
  300. array_pop($new_packet->additional);
  301. $new_packet->header->arcount = count($new_packet->additional);
  302. //
  303. // copy out the data
  304. //
  305. $sigdata = $data . $new_packet->get();
  306. //
  307. // based on the algorithm
  308. //
  309. $algorithm = 0;
  310. switch($this->algorithm) {
  311. //
  312. // MD5
  313. //
  314. case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSAMD5:
  315. $algorithm = OPENSSL_ALGO_MD5;
  316. break;
  317. //
  318. // SHA1
  319. //
  320. case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA1:
  321. $algorithm = OPENSSL_ALGO_SHA1;
  322. break;
  323. //
  324. // SHA256 (PHP 5.4.8 or higher)
  325. //
  326. case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA256:
  327. if (version_compare(PHP_VERSION, '5.4.8', '<') == true) {
  328. throw new Net_DNS2_Exception(
  329. 'SHA256 support is only available in PHP >= 5.4.8',
  330. Net_DNS2_Lookups::E_OPENSSL_INV_ALGO
  331. );
  332. }
  333. $algorithm = OPENSSL_ALGO_SHA256;
  334. break;
  335. //
  336. // SHA512 (PHP 5.4.8 or higher)
  337. //
  338. case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA512:
  339. if (version_compare(PHP_VERSION, '5.4.8', '<') == true) {
  340. throw new Net_DNS2_Exception(
  341. 'SHA512 support is only available in PHP >= 5.4.8',
  342. Net_DNS2_Lookups::E_OPENSSL_INV_ALGO
  343. );
  344. }
  345. $algorithm = OPENSSL_ALGO_SHA512;
  346. break;
  347. //
  348. // unsupported at the moment
  349. //
  350. case Net_DNS2_Lookups::DNSSEC_ALGORITHM_DSA:
  351. case Net_DNS2_Lookups::DSNSEC_ALGORITHM_RSASHA1NSEC3SHA1:
  352. case Net_DNS2_Lookups::DNSSEC_ALGORITHM_DSANSEC3SHA1:
  353. default:
  354. throw new Net_DNS2_Exception(
  355. 'invalid or unsupported algorithm',
  356. Net_DNS2_Lookups::E_OPENSSL_INV_ALGO
  357. );
  358. break;
  359. }
  360. //
  361. // sign the data
  362. //
  363. if (openssl_sign($sigdata, $this->signature, $this->private_key->instance, $algorithm) == false) {
  364. throw new Net_DNS2_Exception(
  365. openssl_error_string(),
  366. Net_DNS2_Lookups::E_OPENSSL_ERROR
  367. );
  368. }
  369. //
  370. // build the signature value based
  371. //
  372. switch($this->algorithm) {
  373. //
  374. // RSA- add it directly
  375. //
  376. case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSAMD5:
  377. case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA1:
  378. case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA256:
  379. case Net_DNS2_Lookups::DNSSEC_ALGORITHM_RSASHA512:
  380. $this->signature = base64_encode($this->signature);
  381. break;
  382. }
  383. }
  384. //
  385. // add the signature
  386. //
  387. $data .= base64_decode($this->signature);
  388. $packet->offset += strlen($data);
  389. return $data;
  390. }
  391. }
  392. /*
  393. * Local variables:
  394. * tab-width: 4
  395. * c-basic-offset: 4
  396. * c-hanging-comment-ender-p: nil
  397. * End:
  398. */
  399. ?>