PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/roundcubemail-0.7.2-dep/plugins/enigma/lib/enigma_driver_gnupg.php

#
PHP | 305 lines | 195 code | 41 blank | 69 comment | 14 complexity | e1dd336aff18bed593c3ca5e32b5189d MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. /*
  3. +-------------------------------------------------------------------------+
  4. | GnuPG (PGP) driver for the Enigma Plugin |
  5. | |
  6. | This program is free software; you can redistribute it and/or modify |
  7. | it under the terms of the GNU General Public License version 2 |
  8. | as published by the Free Software Foundation. |
  9. | |
  10. | This program is distributed in the hope that it will be useful, |
  11. | but WITHOUT ANY WARRANTY; without even the implied warranty of |
  12. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
  13. | GNU General Public License for more details. |
  14. | |
  15. | You should have received a copy of the GNU General Public License along |
  16. | with this program; if not, write to the Free Software Foundation, Inc., |
  17. | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
  18. | |
  19. +-------------------------------------------------------------------------+
  20. | Author: Aleksander Machniak <alec@alec.pl> |
  21. +-------------------------------------------------------------------------+
  22. */
  23. require_once 'Crypt/GPG.php';
  24. class enigma_driver_gnupg extends enigma_driver
  25. {
  26. private $rc;
  27. private $gpg;
  28. private $homedir;
  29. private $user;
  30. function __construct($user)
  31. {
  32. $rcmail = rcmail::get_instance();
  33. $this->rc = $rcmail;
  34. $this->user = $user;
  35. }
  36. /**
  37. * Driver initialization and environment checking.
  38. * Should only return critical errors.
  39. *
  40. * @return mixed NULL on success, enigma_error on failure
  41. */
  42. function init()
  43. {
  44. $homedir = $this->rc->config->get('enigma_pgp_homedir', INSTALL_PATH . '/plugins/enigma/home');
  45. if (!$homedir)
  46. return new enigma_error(enigma_error::E_INTERNAL,
  47. "Option 'enigma_pgp_homedir' not specified");
  48. // check if homedir exists (create it if not) and is readable
  49. if (!file_exists($homedir))
  50. return new enigma_error(enigma_error::E_INTERNAL,
  51. "Keys directory doesn't exists: $homedir");
  52. if (!is_writable($homedir))
  53. return new enigma_error(enigma_error::E_INTERNAL,
  54. "Keys directory isn't writeable: $homedir");
  55. $homedir = $homedir . '/' . $this->user;
  56. // check if user's homedir exists (create it if not) and is readable
  57. if (!file_exists($homedir))
  58. mkdir($homedir, 0700);
  59. if (!file_exists($homedir))
  60. return new enigma_error(enigma_error::E_INTERNAL,
  61. "Unable to create keys directory: $homedir");
  62. if (!is_writable($homedir))
  63. return new enigma_error(enigma_error::E_INTERNAL,
  64. "Unable to write to keys directory: $homedir");
  65. $this->homedir = $homedir;
  66. // Create Crypt_GPG object
  67. try {
  68. $this->gpg = new Crypt_GPG(array(
  69. 'homedir' => $this->homedir,
  70. // 'debug' => true,
  71. ));
  72. }
  73. catch (Exception $e) {
  74. return $this->get_error_from_exception($e);
  75. }
  76. }
  77. function encrypt($text, $keys)
  78. {
  79. /*
  80. foreach ($keys as $key) {
  81. $this->gpg->addEncryptKey($key);
  82. }
  83. $enc = $this->gpg->encrypt($text);
  84. return $enc;
  85. */
  86. }
  87. function decrypt($text, $key, $passwd)
  88. {
  89. // $this->gpg->addDecryptKey($key, $passwd);
  90. try {
  91. $dec = $this->gpg->decrypt($text);
  92. return $dec;
  93. }
  94. catch (Exception $e) {
  95. return $this->get_error_from_exception($e);
  96. }
  97. }
  98. function sign($text, $key, $passwd)
  99. {
  100. /*
  101. $this->gpg->addSignKey($key, $passwd);
  102. $signed = $this->gpg->sign($text, Crypt_GPG::SIGN_MODE_DETACHED);
  103. return $signed;
  104. */
  105. }
  106. function verify($text, $signature)
  107. {
  108. try {
  109. $verified = $this->gpg->verify($text, $signature);
  110. return $this->parse_signature($verified[0]);
  111. }
  112. catch (Exception $e) {
  113. return $this->get_error_from_exception($e);
  114. }
  115. }
  116. public function import($content, $isfile=false)
  117. {
  118. try {
  119. if ($isfile)
  120. return $this->gpg->importKeyFile($content);
  121. else
  122. return $this->gpg->importKey($content);
  123. }
  124. catch (Exception $e) {
  125. return $this->get_error_from_exception($e);
  126. }
  127. }
  128. public function list_keys($pattern='')
  129. {
  130. try {
  131. $keys = $this->gpg->getKeys($pattern);
  132. $result = array();
  133. //print_r($keys);
  134. foreach ($keys as $idx => $key) {
  135. $result[] = $this->parse_key($key);
  136. unset($keys[$idx]);
  137. }
  138. //print_r($result);
  139. return $result;
  140. }
  141. catch (Exception $e) {
  142. return $this->get_error_from_exception($e);
  143. }
  144. }
  145. public function get_key($keyid)
  146. {
  147. $list = $this->list_keys($keyid);
  148. if (is_array($list))
  149. return array_shift($list);
  150. // error
  151. return $list;
  152. }
  153. public function gen_key($data)
  154. {
  155. }
  156. public function del_key($keyid)
  157. {
  158. // $this->get_key($keyid);
  159. }
  160. public function del_privkey($keyid)
  161. {
  162. try {
  163. $this->gpg->deletePrivateKey($keyid);
  164. return true;
  165. }
  166. catch (Exception $e) {
  167. return $this->get_error_from_exception($e);
  168. }
  169. }
  170. public function del_pubkey($keyid)
  171. {
  172. try {
  173. $this->gpg->deletePublicKey($keyid);
  174. return true;
  175. }
  176. catch (Exception $e) {
  177. return $this->get_error_from_exception($e);
  178. }
  179. }
  180. /**
  181. * Converts Crypt_GPG exception into Enigma's error object
  182. *
  183. * @param mixed Exception object
  184. *
  185. * @return enigma_error Error object
  186. */
  187. private function get_error_from_exception($e)
  188. {
  189. $data = array();
  190. if ($e instanceof Crypt_GPG_KeyNotFoundException) {
  191. $error = enigma_error::E_KEYNOTFOUND;
  192. $data['id'] = $e->getKeyId();
  193. }
  194. else if ($e instanceof Crypt_GPG_BadPassphraseException) {
  195. $error = enigma_error::E_BADPASS;
  196. $data['bad'] = $e->getBadPassphrases();
  197. $data['missing'] = $e->getMissingPassphrases();
  198. }
  199. else if ($e instanceof Crypt_GPG_NoDataException)
  200. $error = enigma_error::E_NODATA;
  201. else if ($e instanceof Crypt_GPG_DeletePrivateKeyException)
  202. $error = enigma_error::E_DELKEY;
  203. else
  204. $error = enigma_error::E_INTERNAL;
  205. $msg = $e->getMessage();
  206. return new enigma_error($error, $msg, $data);
  207. }
  208. /**
  209. * Converts Crypt_GPG_Signature object into Enigma's signature object
  210. *
  211. * @param Crypt_GPG_Signature Signature object
  212. *
  213. * @return enigma_signature Signature object
  214. */
  215. private function parse_signature($sig)
  216. {
  217. $user = $sig->getUserId();
  218. $data = new enigma_signature();
  219. $data->id = $sig->getId();
  220. $data->valid = $sig->isValid();
  221. $data->fingerprint = $sig->getKeyFingerprint();
  222. $data->created = $sig->getCreationDate();
  223. $data->expires = $sig->getExpirationDate();
  224. $data->name = $user->getName();
  225. $data->comment = $user->getComment();
  226. $data->email = $user->getEmail();
  227. return $data;
  228. }
  229. /**
  230. * Converts Crypt_GPG_Key object into Enigma's key object
  231. *
  232. * @param Crypt_GPG_Key Key object
  233. *
  234. * @return enigma_key Key object
  235. */
  236. private function parse_key($key)
  237. {
  238. $ekey = new enigma_key();
  239. foreach ($key->getUserIds() as $idx => $user) {
  240. $id = new enigma_userid();
  241. $id->name = $user->getName();
  242. $id->comment = $user->getComment();
  243. $id->email = $user->getEmail();
  244. $id->valid = $user->isValid();
  245. $id->revoked = $user->isRevoked();
  246. $ekey->users[$idx] = $id;
  247. }
  248. $ekey->name = trim($ekey->users[0]->name . ' <' . $ekey->users[0]->email . '>');
  249. foreach ($key->getSubKeys() as $idx => $subkey) {
  250. $skey = new enigma_subkey();
  251. $skey->id = $subkey->getId();
  252. $skey->revoked = $subkey->isRevoked();
  253. $skey->created = $subkey->getCreationDate();
  254. $skey->expires = $subkey->getExpirationDate();
  255. $skey->fingerprint = $subkey->getFingerprint();
  256. $skey->has_private = $subkey->hasPrivate();
  257. $skey->can_sign = $subkey->canSign();
  258. $skey->can_encrypt = $subkey->canEncrypt();
  259. $ekey->subkeys[$idx] = $skey;
  260. };
  261. $ekey->id = $ekey->subkeys[0]->id;
  262. return $ekey;
  263. }
  264. }