PageRenderTime 73ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 0ms

/action.php

https://github.com/x42/dokuoauth
PHP | 799 lines | 642 code | 73 blank | 84 comment | 139 complexity | d204fb7b7d47c0052a9dbff90b17af18 MD5 | raw file
  1. <?php
  2. /**
  3. * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
  4. * @author Robin Gareus <robin@gareus.org>
  5. */
  6. // must be run within Dokuwiki
  7. if(!defined('DOKU_INC')) die();
  8. class action_plugin_oauth extends DokuWiki_Action_Plugin {
  9. var $_outargs = NULL;
  10. /**
  11. * return some info
  12. */
  13. function getInfo(){
  14. return array(
  15. 'author' => 'Robin Gareus',
  16. 'email' => 'robin@gareus.org',
  17. 'date' => '2008-10-15',
  18. 'name' => 'oauth',
  19. 'desc' => 'Authorize User requests by oAuth',
  20. 'url' => 'http://mir.dnsalias.com/wiki/dokuoauth',
  21. );
  22. }
  23. /**
  24. * register the eventhandlers
  25. */
  26. function register(&$contr){/*{{{*/
  27. $contr->register_hook('ACTION_ACT_PREPROCESS',
  28. 'BEFORE',
  29. $this,
  30. 'handle_act_preprocess');
  31. $contr->register_hook('ACTION_ON_AUTH',
  32. 'BEFORE',
  33. $this,
  34. 'handle_act_authhook');
  35. $contr->register_hook('TPL_ACT_UNKNOWN',
  36. 'BEFORE',
  37. $this,
  38. 'handle_act_output');
  39. }/*}}}*/
  40. /**
  41. * handles all oauth-signed requests, but for those to the
  42. * do[oauth]=XXX API.
  43. *
  44. * validates signature and sets $_SERVER['REMOTE_USER']
  45. * just like auth_login().
  46. */
  47. function handle_act_authhook(&$event, $param){/*{{{*/
  48. if (is_array($_REQUEST['do']) && !empty($_REQUEST['do']['oauth'])) return; // skip requests to oauth-API
  49. if (!empty($_REQUEST['oauth_signature'])) {
  50. require_once("dokuoauth.php");
  51. $user='';
  52. // verify signature - check consumer and access token
  53. try {
  54. $req = OAuthRequest::from_request();
  55. list($consumer, $token) = $doku_server->verify_request($req);
  56. $user=$doku_server->get_dokuwiki_user($consumer->key, $token->key);
  57. } catch (OAuthException $e) {
  58. print($e->getMessage() . "\n<hr />\n");
  59. print_r($req);
  60. $this->_debug("oauth error:\n".$e->getMessage()."\n".print_r($req, true));
  61. $this->_log("oauth error:\n".$e->getMessage()."\n".print_r($req, true));
  62. die();
  63. }
  64. if (!$this->getConf('enable')) {
  65. $this->_debug('oAuth: good signature but plugin is not enabled.');
  66. $this->_log("signature ok, but plugin disabled.");
  67. msg('good signature - but OAuth authorization not enabled in plugin configuration');
  68. return;
  69. }
  70. if (empty($user)) $this->_debug('oAuth: empty user name.');
  71. if (empty($user)) {
  72. $this->_log("signature ok, mapped username is empty.");
  73. return;
  74. }
  75. // -> set username for this session
  76. $_SERVER['REMOTE_USER'] = $user;
  77. global $USERINFO;
  78. global $auth;
  79. $USERINFO = $auth->getUserData($user);
  80. if (!is_array($USERINFO)) {
  81. $_SERVER['REMOTE_USER'] = ""; // after _log() ?
  82. $this->_debug('oAuth: could not find user: '.$user);
  83. $this->_log("signature ok, user '$user' not found.");
  84. }
  85. else {
  86. $this->_debug('oAuth: set-user: '.$user);
  87. $this->_log("granted access.");
  88. }
  89. }
  90. }/*}}}*/
  91. /**
  92. * handles do=oauth and do[oauth]='XXX' requests to
  93. * oAuth API and oAuth Admin.
  94. */
  95. function handle_act_preprocess(&$event, $param){/*{{{*/
  96. $handled=false; // continue with dokuwiki..
  97. $finished=false; // request finished - exit after this function
  98. $user_notified=false; // TODO
  99. $dwoauthnonce=rawurldecode($_REQUEST['dwoauthnonce']);
  100. // LOGIN PAGE WORKAROUND XXX
  101. global $ID;
  102. if ($event->data=='login' && !strncasecmp($ID,"OAUTHPLUGINNONCE:",17)) {
  103. $dwoauthnonce=rawurldecode(substr($ID,17));
  104. unset($event->data);
  105. $event->data=array();
  106. $event->data['oauth']='resume';
  107. $this->_debug('intercepted oauth login');
  108. }
  109. // END LOGIN PAGE WORKAROUND XXX
  110. if (trim($event->data) == 'oauth') {
  111. $handled=true;
  112. $event->data="oauthinfo";
  113. }
  114. else if (!empty($event->data['oauth'])) {
  115. require_once("dokuoauth.php");
  116. try {
  117. switch (trim($event->data['oauth'])) {
  118. case 'cancel':
  119. $this->_debug('ACT: cancel');
  120. $handled=true;
  121. $consumer_key='';
  122. if($ses=$doku_server->load_session($dwoauthnonce))
  123. $consumer_key=$ses['consumer_key'];
  124. if (!empty($consumer_key)) {
  125. $consumer = $doku_server->get_consumer_by_key($consumer_key);
  126. if (!empty($consumer) && ($req instanceof OAuthConsumer)) {
  127. if (!empty($consumer->callback_url)) {
  128. $this->redirect($consumer->callback_url, array());
  129. $finished=true;
  130. break;
  131. }
  132. }
  133. }
  134. $event->data="oauthcancel";
  135. break;
  136. case 'delconsumer':
  137. $doit=true;
  138. $consumer_key=$_REQUEST['consumer_key'];
  139. $this->_debug("remove Consumer: $consumer_key");
  140. if (empty($consumer_key)) {
  141. $doit=false;
  142. msg("empty consumer key.",-1);
  143. }
  144. if ($doit && !$this->oauth_isadmin()) {
  145. $acllimit = $doku_server->get_consumer_acl($consumer_key);
  146. if (!is_array($acllimit)
  147. || $acllimit['owner'] != $_SERVER['REMOTE_USER']
  148. || empty($_SERVER['REMOTE_USER'])) {
  149. $doit=false;
  150. }
  151. // allow anyone to delete consumers added by '' (anonymous) ?!
  152. if (is_array($acllimit)
  153. && empty($acllimit['owner'])
  154. && $this->getConf('consumerdel') == 'anyone') {
  155. $doit=true;
  156. }
  157. if (!$doit)
  158. msg("permission denied to delete consumer.",-1);
  159. }
  160. if ($doit && !$doku_server->get_consumer_by_key($consumer_key)) {
  161. msg("unknown consumer key. maybe it has been deleted already.",-1);
  162. $doit=false;
  163. }
  164. if ($doit) {
  165. $doku_server->delete_consumer($consumer_key);
  166. msg("removed Consumer: $consumer_key",1);
  167. }
  168. # continue to list
  169. case 'clist':
  170. $handled=true;
  171. $event->data="oauthlist";
  172. $this->_outargs=array();
  173. $consumers=$doku_server->list_consumers();
  174. foreach ($consumers as $c) {
  175. $acllimit = $doku_server->get_consumer_acl($c->key);
  176. $secret = $c->secret;
  177. if (!$this->oauth_isadmin()) {
  178. if (!is_array($acllimit)
  179. || $acllimit['owner'] != $_SERVER['REMOTE_USER']
  180. || empty($_SERVER['REMOTE_USER'])) {
  181. $secret = '&lt;<em>hidden</em>&gt;';
  182. unset($acllimit);
  183. }
  184. }
  185. // check add auto-trust
  186. $actions = array('delconsumer&consumer_key=' => 'Delete', 'cinfo&consumer_key=' => 'Inspect');
  187. if ($this->check_consumer_confirm($doku_server, $_SERVER['REMOTE_USER'], $c->key)) {
  188. $actions['rmtrust&&consumer_key='] = 'remove trust';
  189. }
  190. $this->_outargs[]=array(
  191. 'key' => $c->key,
  192. 'user' => '-', # SUID ?
  193. 'type' => 'consumer',
  194. 'secret' => $secret,
  195. 'acllimit' => $acllimit,
  196. 'action' => $actions
  197. );
  198. }
  199. break;
  200. case 'deltoken':
  201. $doit=true;
  202. $token_key=$_REQUEST['token_key'];
  203. $this->_debug("remove Token: $token_key");
  204. if (empty($token_key)) {
  205. $doit=false;
  206. msg("empty token key.",-1);
  207. }
  208. if ($doit && !$this->oauth_isadmin()) {
  209. $owner = $doku_server->get_token_user($token_key);
  210. if (empty($owner)) {
  211. $doit=false; // TODO - delete those after they expire..
  212. $this->_debug("found yet unmapped request token.");
  213. } else
  214. if ($owner != $_SERVER['REMOTE_USER'] || empty($_SERVER['REMOTE_USER'])) {
  215. msg("permission denied to delete consumer.",-1);
  216. $doit=false;
  217. }
  218. }
  219. if ($doit && !$doku_server->get_token_by_key(NULL, $token_key)) {
  220. msg("token does not exist.",-1);
  221. $doit=false;
  222. }
  223. if ($doit) {
  224. $doku_server->unmap_user($token_key);
  225. msg("removed token: $token_key",1);
  226. }
  227. # break;
  228. case 'tlist':
  229. $handled=true;
  230. $event->data="oauthlist";
  231. if ($this->oauth_isadmin()) {
  232. $userfilter=$_REQUEST['userfilter']; # TODO - admin-form
  233. msg("admin mode - showing tokens of all users",0);
  234. } else {
  235. $userfilter=trim($_SERVER['REMOTE_USER']);
  236. if (empty($userfilter)) {
  237. // permission denied.
  238. $event->data="oautherror"; // TODO go back to list-form?
  239. $this->_outargs['errormessage'] = 'you need to be logged in to view your tokens.';
  240. break;
  241. }
  242. }
  243. $this->_outargs=array();
  244. foreach($doku_server->list_usertokens($userfilter) as $token) {
  245. $ti=$doku_server->get_token_by_key(NULL, $token['token_key']);
  246. $rqmap=NULL;
  247. # TODO ; see also list_tokens() in OAuth_DokuServer.php
  248. #if ($this->oauth_isadmin()) {
  249. # //lookup userX mappings. (consumer<>token map for [unexchanged] request-tokens)
  250. # $rqmap=array('Consumer-Key' => $doku_server->get_consumer_by_requesttoken($token));
  251. #}
  252. $secret=$ti['obj']->secret;
  253. # TODO: disclose it to admin's anyway ?! only auth_admin()'s ?
  254. if ($ti['type']=='access' && !$this->getConf('disclose_access_token_secret'))
  255. $secret = '&lt;<em>hidden</em>&gt;';
  256. $this->_outargs[]=array(
  257. 'user' => $token['user'],
  258. 'type' => $ti['type'],
  259. 'action' => array ( 'deltoken&token_key=' => 'Revoke'),
  260. 'key' => $ti['obj']->key,
  261. 'secret' => $secret,
  262. # 'acllimit' => $rqmap // XXX - temp. re-using this array for display
  263. );
  264. }
  265. break;
  266. case 'debug':
  267. die('you are not debugging.'); # XXX
  268. $finished=true;
  269. print_r($doku_server->list_consumers()); # XXX - shows secrets of the consumer !
  270. print "<br/>\n";
  271. print "<br/>\n";
  272. print_r($doku_server->list_usertokens($_SERVER['REMOTE_USER']));
  273. print "<br/>\n";
  274. print "<br/>\n";
  275. foreach($doku_server->list_usertokens('') as $token) { # XXX lists ALL tokens
  276. print 'token for user :'.$token['user'].' - ';
  277. print_r($doku_server->get_token_by_key($token['consumer_key'], $token['token_key'])); # XXX - shows token secrets
  278. print "<br/>\n";
  279. }
  280. break;
  281. case 'addconsumer':
  282. $this->_debug('ACT: addconsumer');
  283. $handled=true;
  284. $consumer_key=$_REQUEST['consumer_key'];
  285. $consumer_sec=$_REQUEST['consumer_secret'];
  286. $consumer_cal=$_REQUEST['callback_url'];
  287. if (empty($consumer_cal)) $consumer_cal=NULL;
  288. if (empty($consumer_key)) {
  289. $event->data="oauthaddconsumer";
  290. $this->_debug('addconsumer: empty consumer-key.');
  291. $this->_outargs=array('consumer_key' => '', 'consumer_secret' => $consumer_sec, 'callback_url' => $consumer_cal);
  292. $this->_outargs['errormessage'] = 'addconsumer: empty consumer key.';
  293. break;
  294. }
  295. if ( ($this->getConf('consumeradd') == 'admin' && !$this->oauth_isadmin())
  296. ||($this->getConf('consumeradd') == 'user' && empty($_SERVER['REMOTE_USER']))
  297. ) {
  298. $event->data="oautherror";
  299. $this->_debug('addconsumer: permission denied.');
  300. $this->_outargs['errormessage'] = 'permission denied to create consumer.';
  301. break;
  302. }
  303. $finished=true;
  304. if ($doku_server->get_consumer_by_key($consumer_key)) {
  305. ; // TODO: error or ignore ?
  306. if ($_REQUEST['feedback']) {
  307. $finished=false;
  308. msg('consumer add: A consumer with this key already exists.', -1);
  309. $this->_outargs=array('consumer_key' => '', 'consumer_secret' => $consumer_sec, 'callback_url' => $consumer_cal);
  310. $event->data="oauthaddconsumer";
  311. }
  312. $this->_debug('addconsumer: consumer already exists.');
  313. break;
  314. }
  315. // TODO check ACL is_admin(), allow to create suid tokens, ...
  316. $doku_server->create_consumer($consumer_key, $consumer_sec, $consumer_cal);
  317. $acllimit=array('suid' => '', 'users'=>NULL, 'timeout' => 0, 'owner' => $_SERVER['REMOTE_USER']);
  318. $doku_server->map_consumer($consumer_key, $acllimit);
  319. if ($_REQUEST['feedback']) {
  320. $finished=false;
  321. $event->data="oautherror"; // TODO: _OK_ - go back to add-form or list-consumers
  322. $this->_outargs['errormessage'] = 'scratch that error. Consumer '.$consumer_key.' was added suceccfully.';
  323. }
  324. break;
  325. case 'accesstoken': // exchange [authorized] request-token for an access-token.
  326. $this->_debug('ACT: accesstoken');
  327. $finished=true;
  328. $req = OAuthRequest::from_request();
  329. $this->_log("oauth requesttoken.");
  330. # DokuOAuthDataStore for access tokens:
  331. # - tests if given request-token has been (authorized by|mapped to) a user
  332. # - if not user found: `fetch_access_token()` returns NULL!
  333. # else the request-token is exchanged for an access-token, retraining the user mapping
  334. $token = $doku_server->fetch_access_token($req);
  335. if ($token && $token instanceof OAuthToken)
  336. print $token;
  337. else {
  338. #trigger_error('request token is invalid not not authorized.');
  339. $this->_debug("failed to exchange request for access token.");
  340. }
  341. break;
  342. case 'requesttoken': // request a request-token
  343. $this->_debug('ACT: requesttoken');
  344. $finished=true;
  345. $req = OAuthRequest::from_request();
  346. $this->_log("oauth requesttoken.");
  347. $token = $doku_server->fetch_request_token($req);
  348. $op=$req->get_parameters();
  349. $consumer_key=$op['oauth_consumer_key'];
  350. # auto-authorize suid tokens
  351. $user = $this->check_consumer_acl($doku_server, $consumer_key);
  352. if (!empty($user)) {
  353. $doku_server->map_user($user,$consumer_key, $token->key);
  354. $doku_server->map_requesttoken($consumer_key, $token->key); // will be deleted when getting access-token.
  355. } else {
  356. //remember consumer key for this token until authorization.
  357. $doku_server->map_requesttoken($consumer_key, $token->key);
  358. }
  359. print $token;
  360. break;
  361. case 'info': // general information on oAuth
  362. $handled=true;
  363. $event->data="oauthinfo";
  364. break;
  365. case 'rmtrust':
  366. $consumer_key=$_REQUEST['consumer_key'];
  367. $doit=true;
  368. # continue to cinfo
  369. if (empty($consumer_key)) {
  370. $doit=false;
  371. msg("empty consumer key.",-1);
  372. }
  373. if (!$this->check_consumer_confirm($doku_server, $_SERVER['REMOTE_USER'], $consumer_key)) {
  374. $doit=false;
  375. msg("YOU are not trusting this consumer, and thus can not remove the trust.",-1);
  376. }
  377. if ($doit) {
  378. $cs=$doku_server->get_consumer_settings($consumer_key);
  379. $cs['trusted']=array_unique(array_diff($cs['trusted'],array($_SERVER['REMOTE_USER'])));
  380. $doku_server->set_consumer_settings($consumer_key,$cs);
  381. msg("removed trust in consumer: $consumer_key",1);
  382. }
  383. case 'cinfo': // show consumer info (optionally back to authorize-token)
  384. $handled=true;
  385. $secpass=NULL;
  386. if (!empty($dwoauthnonce)) {
  387. $ses=$doku_server->load_session($dwoauthnonce);
  388. if (is_array($ses)) {
  389. $secpass=$doku_server->save_session($ses);
  390. $consumer_key=$ses['consumer_key'];
  391. } else {
  392. // silently ignore reload? XXX
  393. $this->_debug('consumer info: empty session');
  394. $consumer_key='';
  395. }
  396. }
  397. if (empty($consumer_key))
  398. $consumer_key=$_REQUEST['consumer_key'];
  399. if (empty($consumer_key)) {
  400. $event->data="oautherror";
  401. $this->_outargs['errormessage'] = 'consumer info: empty consumer key.';
  402. break;
  403. }
  404. if ($consumer=$doku_server->get_consumer_by_key($consumer_key)) {
  405. $event->data="oauthcinfo";
  406. $this->_outargs=array('consumer_key' => $consumer->key, 'callback_url' => $consumer->callback_url);
  407. $this->_outargs['acllimit'] = $doku_server->get_consumer_acl($consumer->key);
  408. if ($this->oauth_isadmin()) {
  409. $this->_outargs['consumer_secret'] = $consumer->secret;
  410. $this->_outargs['acllimit']['settings'] = $doku_server->get_consumer_settings($consumer->key); // TODO - make special settings array.
  411. } else {
  412. $this->_outargs['consumer_secret'] = '&lt;<em>hidden</em>&gt;';
  413. unset($this->_outargs['acllimit']);
  414. }
  415. if ($this->check_consumer_confirm($doku_server, $_SERVER['REMOTE_USER'], $consumer_key)) {
  416. #$this->_outargs['action']['rmtrust&&consumer_key='] = 'remove trust'; // TODO - form checkbox or button
  417. $this->_outargs['acllimit']['trusted'] = 'yes';
  418. }
  419. if (!empty($secpass))
  420. $this->_outargs['secpass'] = $secpass;
  421. } else {
  422. $event->data="oautherror";
  423. $this->_outargs['errormessage']= "Consumer is unknown.";
  424. }
  425. break;
  426. case 'resume':
  427. $this->_debug('ACT: resume authentication');
  428. $ses=$doku_server->load_session($dwoauthnonce);
  429. if (!is_array($ses)) {
  430. // TODO make error
  431. #$handled=true;
  432. #$event->data="oautherror";
  433. #$this->_outargs['errormessage'] = 'can not resume this session.';
  434. #break;
  435. trigger_error('Invalid token. Can not resume this session. Try hitting your browser\'s "back" button.');
  436. exit(0);
  437. }
  438. $consumer_key=$ses['consumer_key'];
  439. $token_key=$ses['token_key'];
  440. $callback_url=$ses['oauth_callback'];
  441. $userconfirmed=$_REQUEST['userconfirmed']?true:false;
  442. $trustconsumer=$_REQUEST['trustconsumer']?true:false;
  443. $user_notified=true; // TODO
  444. case 'authorize':
  445. $this->_debug('ACT: authorize');
  446. if (empty($token_key)) {
  447. $token_key=$_REQUEST['oauth_token'];
  448. }
  449. if (empty($token_key)) {
  450. // TODO -> ask user for token! token-add/admin form
  451. #$handled=true;
  452. #$event->data="oauthtoken";
  453. #break;
  454. trigger_error('no oauth_token given for authorization.'); exit(0);
  455. }
  456. if (empty($consumer_key)) {
  457. # TODO parse or lookup consumer for this token ...
  458. #$consumer_key=$_REQUEST['oauth_consumer_key'];
  459. $consumer_key=$doku_server->get_consumer_by_requesttoken($token_key);
  460. }
  461. if (empty($callback_url)) {
  462. $callback_url = $REQUEST['oauth_callback'];
  463. }
  464. #case 'XXXauth':
  465. $this->_debug('ACT: authorize step 2 t:'.$token_key.' c:'.$consumer_key);
  466. $finished=true;
  467. # we need a request-token-key and consumer-key
  468. if (empty($token_key) || empty($consumer_key)) {
  469. trigger_error('insufficient info to grant token authorization.');
  470. exit(0);
  471. }
  472. $user = $doku_server->get_dokuwiki_user($consumer_key, $token_key);
  473. if (!empty($user)) {
  474. trigger_error('token is already authorized for user:'.$user);
  475. exit(0);
  476. }
  477. $user = $this->check_consumer_acl($doku_server, $consumer_key);
  478. if (empty($user)) {
  479. $user = $this->check_doku_auth($doku_server, $consumer_key);
  480. }
  481. if (empty($user)) {
  482. $secpass=$doku_server->save_session(array('consumer_key' =>$consumer_key, 'token_key' => $token_key, 'oauth_callback' => $callback_url));
  483. // LOGIN PAGE WORKAROUND XXX
  484. global $ID; $ID="OAUTHPLUGINNONCE:".rawurlencode($secpass);
  485. $finished=false; $event->data="login";
  486. $handled=false; /// don't $event->preventDefault(); 'login' is the default ;)
  487. $this->_debug('dropping to login..');
  488. // END LOGIN PAGE WORKAROUND XXX
  489. break;
  490. }
  491. if (!$userconfirmed) {
  492. if (!$this->check_consumer_confirm($doku_server, $user, $consumer_key, $token)) {
  493. $secpass=$doku_server->save_session(array('consumer_key' =>$consumer_key, 'token_key' => $token_key, 'oauth_callback' => $callback_url));
  494. $this->_outargs=array('secpass' => $secpass, 'consumer_key' => $consumer_key, 'token_key' => $token_key, 'oauth_callback' => $callback_url);
  495. $this->_debug('heading to confirm..');
  496. $finished=false; $handled=true;
  497. $event->data="oauthconfirm";
  498. global $ACT; $ACT="oauthconfirm"; // override default as well (in case we intercepeted a login)
  499. break;
  500. }
  501. }
  502. if ($trustconsumer) {
  503. // save confirmation for next time.. (TODO: unless SUID ?!)
  504. $cs=$doku_server->get_consumer_settings($consumer_key);
  505. if (!is_array($cs['trusted'])) $cs['trusted']=array();
  506. $cs['trusted']=array_unique(array_merge($cs['trusted'],array($user)));
  507. $doku_server->set_consumer_settings($consumer_key,$cs);
  508. }
  509. $doku_server->map_user($user, $consumer_key, $token_key);
  510. # NOTE: userX (consumer/request-token map for 'resume' auth is removed when exchanging the token!
  511. # we could also remove it now with map_user..
  512. if (!$user_notified) {
  513. ; // TODO send email is configured..
  514. }
  515. # redirect back to consumer
  516. if (empty($callback_url)) {
  517. $consumer = $doku_server->get_consumer_by_key($consumer_key);
  518. $callback_url=$consumer->callback_url;
  519. }
  520. if (!empty($callback_url)) {
  521. # TODO: include xoauth parameters ?!
  522. $this->redirect($callback_url, array('oauth_token'=>rawurlencode($token_key)));
  523. } else {
  524. $this->_debug("token-auth suceeded.");
  525. echo ("request token $token_key authorized.");
  526. #TODO: tell user to go back to consumer. $token is now authorized ..
  527. #finished=false;
  528. }
  529. break;
  530. default:
  531. break;
  532. }
  533. } catch (OAuthException $e) {
  534. print($e->getMessage() . "\n<hr />\n");
  535. print_r($req);
  536. $this->_debug("oauth error:\n".$e->getMessage()."\n".print_r($req, true));
  537. $this->_log("oauth error:\n".$e->getMessage()."\n".print_r($req, true));
  538. die();
  539. }
  540. }
  541. if ($finished) {
  542. $this->_debug('over and out.');
  543. exit(0);
  544. }
  545. if ($handled) {
  546. $this->_debug('handled action');
  547. $event->preventDefault();
  548. }
  549. }/*}}}*/
  550. /**
  551. * print output of do=oauth, do[auth]=XX actions
  552. */
  553. function handle_act_output(&$event){/*{{{*/
  554. $handled=false;
  555. $this->_debug('output event: '.print_r($event, true));
  556. if (!in_array(trim($event->data), array(
  557. 'oauthconfirm', 'oautherror',
  558. 'oauthcancel', 'oauthcinfo',
  559. 'oauthinfo', 'oauth', 'oauthlist',
  560. 'oauthaddconsumer'
  561. ))) {
  562. return false;
  563. }
  564. if (!($helper = &plugin_load('helper', 'oauth'))){
  565. trigger_error('oauth plugin helper is not available.');
  566. exit(0);
  567. break;
  568. }
  569. switch (trim($event->data)) {
  570. case 'oautherror':
  571. // TODO
  572. $helper->oauthToolbar();
  573. #$helper->oauthError($this->_outargs);
  574. print('<p><b>Oauth Error:</b>&nbsp;'.$this->_outargs['errormessage'].'</p>');
  575. $handled=true;
  576. break;
  577. case 'oauthcancel':
  578. $helper->oauthToolbar();
  579. print('<p>Oauth Transaction Cancelled. I don\'t know what to do next. Have nice day.</p><p> truly yours,<br/> OAuth plugin</p>');
  580. $handled=true;
  581. break;
  582. case 'oauth':
  583. case 'oauthinfo':
  584. $helper->oauthInfo();
  585. $handled=true;
  586. break;
  587. case 'oauthcinfo':
  588. $helper->oauthConsumerInfo($this->_outargs);
  589. $handled=true;
  590. break;
  591. case 'oauthconfirm':
  592. if ($this->_outargs) {
  593. $helper->oauthConfirm($this->_outargs);
  594. $handled=true;
  595. }
  596. break;
  597. case 'oauthaddconsumer':
  598. $helper->oauthAddConsumer($this->_outargs);
  599. $handled=true;
  600. break;
  601. case 'oauthlist':
  602. $helper->oauthTokenList($this->_outargs);
  603. $handled=true;
  604. break;
  605. default:
  606. break;
  607. }
  608. if ($handled) {
  609. $this->_debug('handled output');
  610. #$event->result = true;
  611. #$event->stopPropagation();
  612. $event->preventDefault();
  613. return true;
  614. }
  615. }/*}}}*/
  616. private function check_consumer_acl($doku_server, $consumer_key) {/*{{{*/
  617. $acllimit = $doku_server->get_consumer_acl($consumer_key);
  618. $user=NULL;
  619. if (is_array($acllimit) && !empty($acllimit['suid'])) {
  620. $user = $acllimit['suid'];
  621. return $user;
  622. }
  623. return $user;
  624. }/*}}}*/
  625. private function check_doku_auth($doku_server, $consumer_key) {/*{{{*/
  626. $acllimit = $doku_server->get_consumer_acl($consumer_key);
  627. $user=NULL;
  628. if ($_SERVER['REMOTE_USER']) {
  629. $user=$_SERVER['REMOTE_USER'];
  630. $this->_debug("dokuwiki already authenticated user: $user");
  631. } else if (auth_login("","",false,true)) {
  632. # auth_login($_REQUEST['u'],$_REQUEST['p'],$_REQUEST['r'],false,true); # workaround for workaround above ;)
  633. $this->_debug("user logged-in via COOKIE: $user");
  634. global $USERINFO;
  635. $user=$_SERVER['REMOTE_USER'];
  636. }
  637. // TODO: check group(s), not is_admin, etc.
  638. if (is_array($acllimit['users']) && !in_array($user, $acllimit['users'])) {
  639. $this->_debug("denied user '$user' for this consumer.");
  640. msg("Consumer is not allowed access to this user.",-1);
  641. #auth_logoff();
  642. $user=NULL;
  643. }
  644. return $user;
  645. }/*}}}*/
  646. private function check_consumer_confirm($doku_server, $user, $consumer_key, $request_token = NULL) {/*{{{*/
  647. $acllimit = $doku_server->get_consumer_acl($consumer_key);
  648. if (is_array($acllimit) && !empty($acllimit['suid'])) return true;
  649. // check database ... for user <> consumer user-whitelist (auto-confirm)
  650. if (empty($user)) return false;
  651. $cs=$doku_server->get_consumer_settings($consumer_key);
  652. if (!is_array($cs['trusted']) || !in_array($user, $cs['trusted'])) return false;
  653. return true;
  654. }/*}}}*/
  655. private function oauth_isadmin() {/*{{{*/
  656. if (auth_isadmin() || ($this->getConf('manager_admin') && auth_ismanager()))
  657. return true;
  658. return false;
  659. }/*}}}*/
  660. private function redirect($uri, $params) {/*{{{*/
  661. if (!empty($params)) {
  662. $q = array();
  663. foreach ($params as $name=>$value)
  664. $q[] = $name.'='.$value;
  665. $q_s = implode('&', $q);
  666. if (strpos($uri, '?'))
  667. $uri .= '&'.$q_s;
  668. else
  669. $uri .= '?'.$q_s;
  670. }
  671. // simple security - multiline location headers can inject all kinds of extras
  672. $uri = preg_replace('/\s/', '%20', $uri);
  673. if (strncasecmp($uri, 'http://', 7) && strncasecmp($uri, 'https://', 8)) {
  674. if (strpos($uri, '://'))
  675. throw new OAuthException('Illegal protocol in redirect uri '.$uri);
  676. $uri = 'http://'.$uri;
  677. }
  678. header('HTTP/1.1 302 Found');
  679. header('Location: '.$uri);
  680. echo '';
  681. exit(0);
  682. } /*}}}*/
  683. private function _log ($m = null){ /*{{{*/
  684. $OAdebug= $this->getConf('log_all_requests');
  685. $OAlogdb= '/tmp/oAuth.log';
  686. $dbh = dba_popen($OAlogfile, 'c', 'inifile');
  687. if (! isset($OAlog) || $OAlog === false) return;
  688. $data = array (
  689. 'REMOTE_USER' => $_SERVER['REMOTE_USER'],
  690. 'HTTP_USER_AGENT' => $_SERVER['HTTP_USER_AGENT'],
  691. 'REMOTE_ADDR' => $_SERVER['REMOTE_ADDR'],
  692. 'REMOTE_PORT' => $_SERVER['REMOTE_PORT'],
  693. 'HTTP_X_REAL_IP' => $_SERVER['HTTP_X_REAL_IP'],
  694. 'HTTP_X_FORWARDED_FOR' => $_SERVER['HTTP_X_FORWARDED_FOR'],
  695. 'HTTP_COOKIE' => $_SERVER['HTTP_COOKIE'],
  696. 'REQUEST_METHOD' => $_SERVER['REQUEST_METHOD'],
  697. 'REQUEST_URI' => $_SERVER['REQUEST_URI'],
  698. 'QUERY_STRING' => $_SERVER['QUERY_STRING'],
  699. 'REQUEST_TIME' => $_SERVER['REQUEST_TIME'],
  700. 'GET' => $_GET,
  701. 'POST' => $_POST,
  702. 'REQUEST' => $_REQUEST,
  703. 'msg' => $m
  704. );
  705. if (!$dbh ||
  706. !dba_insert("log_$token", serialize($data), $dbh)) {
  707. header("HTTP/1.1 500 Internal Server Error");
  708. echo 'Cannot write to log: ' . $OAlogdb;
  709. return;
  710. }
  711. dba_close($this->dbh);
  712. } /*}}}*/
  713. private function _debug ($m = null){ /*{{{*/
  714. $OAdebug= $this->getConf('trace_plugin');
  715. $OAlogfile= '/tmp/oAuth.debug';
  716. if (! isset($OAdebug) || $OAdebug === false) return;
  717. if (! is_writable(dirname($OAlogfile)) &! is_writable($OAlogfile)){
  718. header("HTTP/1.1 500 Internal Server Error");
  719. echo 'Cannot write to debug log: ' . $OAlogfile;
  720. return;
  721. }
  722. $vhost=DOKU_URL;
  723. error_log($vhost.' '.date("c ").$m."\n", 3, $OAlogfile);
  724. } /*}}}*/
  725. }
  726. /* vim: set ts=4 sw=4 et foldmethod=marker enc=utf-8 : */