1<?php 2/** 3 * DokuWiki HTTP authentication plugin 4 * https://www.dokuwiki.org/plugin:authhttp 5 * 6 * This is authhttp's action plugin which 7 * a.) skips the 'login' action as it does not make sense with HTTP 8 * authentication. 9 * b.) modifies DokuWiki's register form so that 10 * i.) the username is hard-coded to match the username from the 11 * HTTP authentication. 12 * ii.) the password text fields are replaced by hidden fields with 13 * a random password that won't do any harm. 14 * 15 * All of this code ONLY applies when DokuWiki's configured auth plugin is authsplit 16 * (https://www.dokuwiki.org/plugin:authsplit) and authhttp is its primary auth plugin. 17 * If authhttp is used on its own (ie. as DokuWiki's auth plugin), users will never 18 * see a login or a register screen anyway. 19 * 20 * @license GPL 3 http://www.gnu.org/licenses/gpl-3.0.html 21 * @author Pieter Hollants <pieter@hollants.com> 22 */ 23 24// must be run within Dokuwiki 25if (!defined('DOKU_INC')) 26 die(); 27 28use dokuwiki\Extension\ActionPlugin; 29 30class action_plugin_authhttp extends ActionPlugin { 31 public function __construct() { 32 global $conf; 33 34 /* We have to distinguish between the plugin being loaded and the plugin 35 actually being used for authentication. */ 36 $this->active = ( 37 $conf['authtype'] == 'authhttp' || 38 ( 39 $conf['authtype'] == 'authsplit' && 40 $conf['plugin']['authsplit']['primary_authplugin'] == 'authhttp' 41 ) 42 ); 43 44 if ($this->active) { 45 /* We register an event handler to skip the login action below, but 46 we also don't want the template to show a 'login' link in the 47 first place. 48 49 DokuWiki has no capability setting for 'login', so we need a 50 little hack that pretends the admin disabled the login action 51 himself. */ 52 $disableactions = explode(',', $conf['disableactions']); 53 $disableactions = array_map('trim', $disableactions); 54 if (!in_array('login', $disableactions)) { 55 $disableactions[] = 'login'; 56 } 57 $conf['disableactions'] = implode(',', $disableactions); 58 59 /* We also don't want DokuWiki to generate passwords on its own and 60 mail them to the users upon registration. We need to use the same 61 hack as above, pretending the admin disabled password generation 62 himself. */ 63 $conf['autopasswd'] = 0; 64 } 65 } 66 67 /** 68 * Register the event handlers 69 */ 70 function register(Doku_Event_Handler $controller){ 71 if ($this->active) { 72 $controller->register_hook('ACTION_ACT_PREPROCESS', 73 'AFTER', 74 $this, 75 'skip_login_action', 76 NULL); 77 78 /* Legacy DokuWiki releases with old form class */ 79 $controller->register_hook('HTML_REGISTERFORM_OUTPUT', 80 'BEFORE', 81 $this, 82 'modify_register_form_legacy', 83 NULL); 84 85 /* Newer DokuWiki releases with rewritten form class */ 86 $controller->register_hook('REGISTERFORM_OUTPUT', 87 'BEFORE', 88 $this, 89 'modify_register_form', 90 NULL); 91 } 92 } 93 94 /** 95 * Event handler to skip the 'login' action 96 */ 97 function skip_login_action(&$event, $param) { 98 /* Some actions handled in inc/actions.php:act_dispatch() result in $ACT 99 being modified to 'login', eg. 'register'. */ 100 if ($event->data == 'login') { 101 /* With HTTP authentication, there is no sense in showing a login form, 102 so we directly redirect to a 'show' action instead. By using 103 act_redirect() instead of modifying $event->data, we make sure 104 DokuWiki's entire auth logic can work, which is eg. required so that 105 after a user's registration he gets logged in automatically. */ 106 act_redirect($ID, 'show'); 107 } 108 } 109 110 /** 111 * Event handler to modify the registration form 112 * Version for legacy DokuWiki releases with old form class 113 */ 114 function modify_register_form_legacy(&$event, $param) { 115 $form = $event->data; 116 117 /* Hard-code the HTTP authentication user name as login name for registration as 118 registering as anyone else than the already externally authenticated user does 119 not make much sense. */ 120 $pos = $form->findElementByAttribute('name', 'login'); 121 if (!$pos) 122 return; 123 $elem = $form->getElementAt($pos); 124 $elem['value'] = $_SERVER['PHP_AUTH_USER']; 125 $elem['readonly'] = 'readonly'; 126 $form->replaceElement($pos, $elem); 127 128 /* We do not want DokuWiki to auto-generate a password and mail it to the user. 129 Then, however, inc/auth.php's register() will insist on a non-null password, 130 so we supply a random one in hidden form fields. As this code only runs when 131 both authhttp AND authsplit are active, the password won't end up anywhere 132 since authhttp is the primary auth plugin in that case and does not offer the 133 modPass capability. */ 134 $pwd = auth_pwgen(); 135 foreach (array('pass', 'passchk') as $name) { 136 $pos = $form->findElementByAttribute('name', $name); 137 $form->replaceElement($pos, NULL); 138 $form->addHidden($name, $pwd); 139 } 140 } 141 142 /** 143 * Event handler to modify the registration form 144 * Version for newer DokuWiki releases with rewritten form class 145 */ 146 function modify_register_form(&$event, $param) { 147 $form = $event->data; 148 149 /* Hard-code the HTTP authentication user name as login name for registration as 150 registering as anyone else than the already externally authenticated user does 151 not make much sense. */ 152 $pos = $form->findPositionByAttribute('name', 'login'); 153 if (!$pos) 154 return; 155 $elem = $form->getElementAt($pos); 156 $elem['value'] = $_SERVER['PHP_AUTH_USER']; 157 $elem['readonly'] = 'readonly'; 158 $form->replaceElement($elem, $pos); 159 160 /* We do not want DokuWiki to auto-generate a password and mail it to the user. 161 Then, however, inc/auth.php's register() will insist on a non-null password, 162 so we supply a random one in hidden form fields. As this code only runs when 163 both authhttp AND authsplit are active, the password won't end up anywhere 164 since authhttp is the primary auth plugin in that case and does not offer the 165 modPass capability. */ 166 $pwd = auth_pwgen(); 167 foreach (array('pass', 'passchk') as $name) { 168 $pos = $form->findPositionByAttribute('name', $name); 169 $form->replaceElement(NULL, $pos); 170 $form->setHiddenField($name, $pwd); 171 } 172 } 173} 174