auth.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. /*
  3. Copyright (c) 2009-2014 F3::Factory/Bong Cosca, All rights reserved.
  4. This file is part of the Fat-Free Framework (http://fatfree.sf.net).
  5. THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF
  6. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  7. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  8. PURPOSE.
  9. Please see the license.txt file for more information.
  10. */
  11. //! Authorization/authentication plug-in
  12. class Auth {
  13. //@{ Error messages
  14. const
  15. E_LDAP='LDAP connection failure',
  16. E_SMTP='SMTP connection failure';
  17. //@}
  18. protected
  19. //! Auth storage
  20. $storage,
  21. //! Mapper object
  22. $mapper,
  23. //! Storage options
  24. $args;
  25. /**
  26. * Jig storage handler
  27. * @return bool
  28. * @param $id string
  29. * @param $pw string
  30. * @param $realm string
  31. **/
  32. protected function _jig($id,$pw,$realm) {
  33. return (bool)
  34. call_user_func_array(
  35. array($this->mapper,'load'),
  36. array(
  37. array_merge(
  38. array(
  39. '@'.$this->args['id'].'==? AND '.
  40. '@'.$this->args['pw'].'==?'.
  41. (isset($this->args['realm'])?
  42. (' AND @'.$this->args['realm'].'==?'):''),
  43. $id,$pw
  44. ),
  45. (isset($this->args['realm'])?array($realm):array())
  46. )
  47. )
  48. );
  49. }
  50. /**
  51. * MongoDB storage handler
  52. * @return bool
  53. * @param $id string
  54. * @param $pw string
  55. * @param $realm string
  56. **/
  57. protected function _mongo($id,$pw,$realm) {
  58. return (bool)
  59. $this->mapper->load(
  60. array(
  61. $this->args['id']=>$id,
  62. $this->args['pw']=>$pw
  63. )+
  64. (isset($this->args['realm'])?
  65. array($this->args['realm']=>$realm):array())
  66. );
  67. }
  68. /**
  69. * SQL storage handler
  70. * @return bool
  71. * @param $id string
  72. * @param $pw string
  73. * @param $realm string
  74. **/
  75. protected function _sql($id,$pw,$realm) {
  76. return (bool)
  77. call_user_func_array(
  78. array($this->mapper,'load'),
  79. array(
  80. array_merge(
  81. array(
  82. $this->args['id'].'=? AND '.
  83. $this->args['pw'].'=?'.
  84. (isset($this->args['realm'])?
  85. (' AND '.$this->args['realm'].'=?'):''),
  86. $id,$pw
  87. ),
  88. (isset($this->args['realm'])?array($realm):array())
  89. )
  90. )
  91. );
  92. }
  93. /**
  94. * LDAP storage handler
  95. * @return bool
  96. * @param $id string
  97. * @param $pw string
  98. **/
  99. protected function _ldap($id,$pw) {
  100. $dc=@ldap_connect($this->args['dc']);
  101. if ($dc &&
  102. ldap_set_option($dc,LDAP_OPT_PROTOCOL_VERSION,3) &&
  103. ldap_set_option($dc,LDAP_OPT_REFERRALS,0) &&
  104. ldap_bind($dc,$this->args['rdn'],$this->args['pw']) &&
  105. ($result=ldap_search($dc,$this->args['base_dn'],
  106. 'uid='.$id)) &&
  107. ldap_count_entries($dc,$result) &&
  108. ($info=ldap_get_entries($dc,$result)) &&
  109. @ldap_bind($dc,$info[0]['dn'],$pw) &&
  110. @ldap_close($dc)) {
  111. return $info[0]['uid'][0]==$id;
  112. }
  113. user_error(self::E_LDAP);
  114. }
  115. /**
  116. * SMTP storage handler
  117. * @return bool
  118. * @param $id string
  119. * @param $pw string
  120. **/
  121. protected function _smtp($id,$pw) {
  122. $socket=@fsockopen(
  123. (strtolower($this->args['scheme'])=='ssl'?
  124. 'ssl://':'').$this->args['host'],
  125. $this->args['port']);
  126. $dialog=function($cmd=NULL) use($socket) {
  127. if (!is_null($cmd))
  128. fputs($socket,$cmd."\r\n");
  129. $reply='';
  130. while (!feof($socket) &&
  131. ($info=stream_get_meta_data($socket)) &&
  132. !$info['timed_out'] && $str=fgets($socket,4096)) {
  133. $reply.=$str;
  134. if (preg_match('/(?:^|\n)\d{3} .+\r\n/s',
  135. $reply))
  136. break;
  137. }
  138. return $reply;
  139. };
  140. if ($socket) {
  141. stream_set_blocking($socket,TRUE);
  142. $dialog();
  143. $fw=Base::instance();
  144. $dialog('EHLO '.$fw->get('HOST'));
  145. if (strtolower($this->args['scheme'])=='tls') {
  146. $dialog('STARTTLS');
  147. stream_socket_enable_crypto(
  148. $socket,TRUE,STREAM_CRYPTO_METHOD_TLS_CLIENT);
  149. $dialog('EHLO '.$fw->get('HOST'));
  150. }
  151. // Authenticate
  152. $dialog('AUTH LOGIN');
  153. $dialog(base64_encode($id));
  154. $reply=$dialog(base64_encode($pw));
  155. $dialog('QUIT');
  156. fclose($socket);
  157. return (bool)preg_match('/^235 /',$reply);
  158. }
  159. user_error(self::E_SMTP);
  160. }
  161. /**
  162. * Login auth mechanism
  163. * @return bool
  164. * @param $id string
  165. * @param $pw string
  166. * @param $realm string
  167. **/
  168. function login($id,$pw,$realm=NULL) {
  169. return $this->{'_'.$this->storage}($id,$pw,$realm);
  170. }
  171. /**
  172. * HTTP basic auth mechanism
  173. * @return bool
  174. * @param $func callback
  175. **/
  176. function basic($func=NULL) {
  177. $fw=Base::instance();
  178. $realm=$fw->get('REALM');
  179. $hdr=NULL;
  180. if (isset($_SERVER['HTTP_AUTHORIZATION']))
  181. $hdr=$_SERVER['HTTP_AUTHORIZATION'];
  182. elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']))
  183. $hdr=$_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
  184. if (!empty($hdr))
  185. list($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW'])=
  186. explode(':',base64_decode(substr($hdr,6)));
  187. if (isset($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']) &&
  188. $this->login(
  189. $_SERVER['PHP_AUTH_USER'],
  190. $func?
  191. $fw->call($func,$_SERVER['PHP_AUTH_PW']):
  192. $_SERVER['PHP_AUTH_PW'],
  193. $realm
  194. ))
  195. return TRUE;
  196. if (PHP_SAPI!='cli')
  197. header('WWW-Authenticate: Basic realm="'.$realm.'"');
  198. $fw->status(401);
  199. return FALSE;
  200. }
  201. /**
  202. * Instantiate class
  203. * @return object
  204. * @param $storage string|object
  205. * @param $args array
  206. **/
  207. function __construct($storage,array $args=NULL) {
  208. if (is_object($storage) && is_a($storage,'DB\Cursor')) {
  209. $this->storage=$storage->dbtype();
  210. $this->mapper=$storage;
  211. unset($ref);
  212. }
  213. else
  214. $this->storage=$storage;
  215. $this->args=$args;
  216. }
  217. }