1<?php 2 3/** 4 * OpenLDAP + Kerberos authentication backend 5 * 6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 7 * @author Sebastián Santisi <s@ntisi.com.ar> 8 */ 9class auth_plugin_authopenldapkerberos extends DokuWiki_Auth_Plugin 10{ 11 /** @var array filter pattern */ 12 protected $pattern = array(); 13 14 public function __construct() 15 { 16 parent::__construct(); 17 18 if(!function_exists('ldap_connect') || !class_exists('KRB5CCache')) { 19 // This condition isn't checking for a valid Kerberos ticket or for 20 // a system GSSAPI library, the only way to check that is trying to 21 // bind to LDAP. 22 $this->success = false; 23 return; 24 } 25 26 $this->cando['getUsers'] = true; 27 $this->cando['getUserCount'] = true; 28 $this->cando['getGroups'] = true; 29 } 30 31 public function checkPass($user, $pass) 32 { 33 try { 34 $p = new KRB5CCache(); 35 $p->initPassword($user, $pass); 36 return true; 37 } 38 catch(Exception $e) { 39 return false; 40 } 41 } 42 43 public function getUserData($user, $requireGroups = true) 44 { 45 $c = $this->connect(); 46 $r = ldap_search( 47 $c, 48 "ou={$this->getConf('user_ou')},{$this->getConf('base_dn')}", 49 "({$this->getConf('userkey')}=$user)", 50 Array($this->getConf('username'), $this->getConf('usergid'), $this->getConf('usermail')) 51 ); 52 53 $e = ldap_get_entries($c, $r); 54 55 $userdata = Array( 56 'name' => $e[0][$this->getConf('username')][0], 57 'mail' => $e[0][$this->getConf('usermail')][0], 58 'grps' => Array() 59 ); 60 61 if($requireGroups) { 62 $gid = $e[0][$this->getConf('usergid')][0]; 63 64 $r = ldap_search( 65 $c, 66 "ou={$this->getConf('group_ou')},{$this->getConf('base_dn')}", 67 "({$this->getConf('groupkey')}=*)", 68 Array($this->getConf('groupkey'), $this->getConf('groupgid'), $this->getConf('groupuids')) 69 ); 70 $e = ldap_get_entries($c, $r); 71 72 for($i = 0; $i < $e['count']; $i++) { 73 $cn = $e[$i][$this->getConf('groupkey')][0]; 74 $gn = $e[$i][$this->getConf('groupgid')]['0']; 75 76 if($gn == $gid) 77 $userdata['grps'][] = $cn; 78 else if(array_key_exists($this->getConf('groupuids'), $e[$i])) { 79 for($j = 0; $j < $e[$i][$this->getConf('groupuids')]['count']; $j++) { 80 if($e[$i][$this->getConf('groupuids')][$j] == $user) 81 $userdata['grps'][] = $cn; 82 } 83 } 84 } 85 } 86 87 ldap_unbind($c); 88 89 return $userdata; 90 } 91 92 protected function connect() { 93 $c = ldap_connect($this->getConf('server'), $this->getConf('port')); 94 ldap_set_option($c, LDAP_OPT_PROTOCOL_VERSION, 3); 95 ldap_sasl_bind($c, NULL, NULL, 'GSSAPI'); 96 return $c; 97 } 98 99 public function getUserCount($filter = array()) 100 { 101 $c = $this->connect(); 102 $r = ldap_search( 103 $c, 104 "ou={$this->getConf('user_ou')},{$this->getConf('base_dn')}", 105 "({$this->getConf('userkey')}=*)", 106 Array($this->getConf('usergid')) 107 ); 108 $e = ldap_get_entries($c, $r); 109 110 ldap_unbind($c); 111 112 return $e['count']; 113 } 114 115 public function retrieveUsers($start = 0, $limit = 0, $filter = array()) 116 { 117 $this->constructPattern($filter); 118 119 $c = $this->connect(); 120 $r = ldap_search( 121 $c, 122 "ou={$this->getConf('user_ou')},{$this->getConf('base_dn')}", 123 "({$this->getConf('userkey')}=*)", 124 Array($this->getConf('userkey'), $this->getConf('username'), $this->getConf('usergid'), $this->getConf('usermail')) 125 ); 126 $e = ldap_get_entries($c, $r); 127 128 $users = Array(); 129 130 for($i = 0; $i < $e['count']; $i++) 131 $users[$e[$i][$this->getConf('userkey')][0]] = Array( 132 'name' => $e[$i][$this->getConf('username')][0], 133 'mail' => $e[$i][$this->getConf('usermail')][0], 134 'grps' => Array(), 135 'gid' => $e[$i][$this->getConf('usergid')][0] 136 ); 137 138 $r = ldap_search( 139 $c, 140 "ou={$this->getConf('group_ou')},{$this->getConf('base_dn')}", 141 "({$this->getConf('groupkey')}=*)", 142 Array($this->getConf('groupkey'), $this->getConf('groupgid'), $this->getConf('groupuids')) 143 ); 144 $e = ldap_get_entries($c, $r); 145 146 ldap_unbind($c); 147 148 $groups = Array(); 149 150 for($i = 0; $i < $e['count']; $i++) { 151 $cn = $e[$i][$this->getConf('groupkey')][0]; 152 $gn = $e[$i][$this->getConf('groupgid')]['0']; 153 154 $groups[$gn] = $cn; 155 156 if(array_key_exists($this->getConf('groupuids'), $e[$i])) 157 for($j = 0; $j < $e[$i][$this->getConf('groupuids')]['count']; $j++) 158 $users[$e[$i][$this->getConf('groupuids')][$j]]['grps'][] = $cn; 159 } 160 161 $out = Array(); 162 163 $uids = array_keys($users); 164 sort($uids); 165 166 foreach($uids as $uid) { 167 $users[$uid]['grps'][] = $groups[$users[$uid]['gid']]; 168 169 if($this->filter($uid, $users[$uid])) { 170 if($start > 0) 171 $start--; 172 else { 173 $out[$uid] = $users[$uid]; 174 if(count($out) == $limit) 175 break; 176 } 177 } 178 } 179 180 return $out; 181 } 182 183 public function retrieveGroups($start = 0, $limit = 0) 184 { 185 $c = $this->connect(); 186 $r = ldap_search( 187 $c, 188 "ou={$this->getConf('group_ou')},{$this->getConf('base_dn')}", 189 "({$this->getConf('groupkey')}=*)", 190 Array($this->getConf('groupkey')) 191 ); 192 $e = ldap_get_entries($c, $r); 193 194 ldap_unbind($c); 195 196 if($limit == 0 || $limit > $e['count']) $limit = $e['count']; 197 198 $groups = Array(); 199 200 for($i = $start; $i < $limit; $i++) { 201 $groups[] = $e[$i][$this->getConf('groupkey')][0]; 202 } 203 204 return $groups; 205 } 206 207 208 /** 209 * return true if $user + $info match $filter criteria, false otherwise 210 * 211 * @author Chris Smith <chris@jalakai.co.uk> 212 * 213 * @param string $user User login 214 * @param array $info User's userinfo array 215 * @return bool 216 */ 217 protected function filter($user, $info) 218 { 219 foreach ($this->pattern as $item => $pattern) { 220 if ($item == 'user') { 221 if (!preg_match($pattern, $user)) return false; 222 } elseif ($item == 'grps') { 223 if (!count(preg_grep($pattern, $info['grps']))) return false; 224 } else { 225 if (!preg_match($pattern, $info[$item])) return false; 226 } 227 } 228 return true; 229 } 230 231 /** 232 * construct a filter pattern 233 * 234 * @param array $filter 235 */ 236 protected function constructPattern($filter) 237 { 238 $this->pattern = array(); 239 foreach ($filter as $item => $pattern) { 240 $this->pattern[$item] = '/'.str_replace('/', '\/', $pattern).'/i'; // allow regex characters 241 } 242 } 243} 244