Changeset 1304
- Timestamp:
- 10/22/07 15:06:20 (1 year ago)
- Files:
-
- trunk/wifidog-auth/CHANGELOG (modified) (1 diff)
- trunk/wifidog-auth/wifidog/classes/Authenticator.php (modified) (3 diffs)
- trunk/wifidog-auth/wifidog/classes/Authenticators/AuthenticatorLDAP.php (modified) (3 diffs)
- trunk/wifidog-auth/wifidog/classes/Authenticators/AuthenticatorLocalUser.php (modified) (2 diffs)
- trunk/wifidog-auth/wifidog/classes/Authenticators/AuthenticatorRadius.php (modified) (1 diff)
- trunk/wifidog-auth/wifidog/classes/User.php (modified) (3 diffs)
- trunk/wifidog-auth/wifidog/login/index.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/wifidog-auth/CHANGELOG
r1301 r1304 1 1 # $Id$ 2 2007-10-22 Benoit Grégoire <bock@step.polymtl.ca> 3 * Major security fix: Fix the authenticator for a security breach where a user could get Internet access using an empty username. LocalUser and LDAP were definitely vulnerable, RADIUS may have been. 4 2 5 2007-10-01 Benoit Grégoire <bock@step.polymtl.ca> 3 6 * Remove Array type hinting in Security.php. It's not supported in PHP < 5.1. Fixes #393 trunk/wifidog-auth/wifidog/classes/Authenticator.php
r1289 r1304 140 140 $selectedUser=null; 141 141 } 142 142 143 143 $smarty=SmartyWiFiDog::getObject(); 144 144 // Set network selector … … 163 163 { 164 164 if (!empty($_REQUEST["login_form_submit"])) { 165 if (isset($_REQUEST["user_id"])) {165 if (isset($_REQUEST["user_id"])) { 166 166 $username = User::getObject($_REQUEST["user_id"])->getUsername(); 167 167 } … … 173 173 $password = $_REQUEST["password"]; 174 174 } 175 175 176 176 // Authenticating the user through the selected auth source. 177 177 $network = Network::processSelectUI('auth_source'); trunk/wifidog-auth/wifidog/classes/Authenticators/AuthenticatorLDAP.php
r1249 r1304 125 125 * @return void 126 126 */ 127 public function __construct($account_orgin, $host, $rdn, $pass, $o, $filter)127 public function __construct($account_orgin, $host, $rdn, $pass, $o, $filter) 128 128 { 129 129 // Call parent constructor 130 130 parent::__construct($account_orgin); 131 131 132 $this->mldap_hostname = $host;133 $this->mldap_filter = $filter;134 $this->mldap_o = $o;135 $this->mldap_rdn = trim($rdn);136 $this->mldap_pass = trim($pass);132 $this->mldap_hostname = $host; 133 $this->mldap_filter = $filter; 134 $this->mldap_o = $o; 135 $this->mldap_rdn = trim($rdn); 136 $this->mldap_pass = trim($pass); 137 137 } 138 138 … … 151 151 152 152 */ 153 private function checkLdapUser($username, $password, $ldap_server, $o, $f, &$errmsg = null )154 {155 // Init values156 $rtval = true;157 158 // Check if php-ldap extension is loaded159 if (Dependency::check("ldap", $errmsg)) {160 if ($connect = @ldap_connect($ldap_server)) {161 // if connected to ldap server162 ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);163 164 // bind to ldap connection153 private function checkLdapUser($username, $password, $ldap_server, $o, $f, &$errmsg = null ) 154 { 155 // Init values 156 $rtval = true; 157 158 // Check if php-ldap extension is loaded 159 if (Dependency::check("ldap", $errmsg)) { 160 if ($connect = @ldap_connect($ldap_server)) { 161 // if connected to ldap server 162 ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3); 163 164 // bind to ldap connection 165 165 if (strlen(trim($this->mldap_rdn)) == 0) { 166 if (($bind = @ldap_bind($connect)) == false) {167 $errmsg = _("Error while connecting to the LDAP server.");168 return false;169 }170 } else {171 if (($bind = @ldap_bind($connect, $this->mldap_rdn, $this->mldap_pass )) == false) {172 $errmsg = _("Error while connecting to the LDAP server.");173 return false;174 }175 }176 177 // search for user178 if (($res_id = ldap_search($connect, "o=$o", "$f=$username")) == false) {179 $errmsg = _("Error while obtaining your LDAP information.");180 181 return false;182 }183 184 if (ldap_count_entries($connect, $res_id) != 1) {185 $errmsg = _("Error while obtaining your username or password from the LDAP server.");186 187 return false;188 }189 190 if (($entry_id = ldap_first_entry($connect, $res_id)) == false) {191 $errmsg = _("Error while obtaining your username or password from the LDAP server.");192 193 return false;194 }195 196 if (($user_dn = ldap_get_dn($connect, $entry_id)) == false) {197 $errmsg = _("Error while obtaining your username or password from the LDAP server.");198 199 return false;200 }201 202 //Authenticate the User203 if (($link_id = ldap_bind($connect, $user_dn, $password)) == false) {204 $errmsg = _("Error in username or password.");205 206 return false;207 }208 209 return true;210 } else {211 $errmsg = _("Error connecting to the LDAP Server.");212 }213 214 ldap_close($connect);215 } else {216 $rtval = false;217 }218 }166 if (($bind = @ldap_bind($connect)) == false) { 167 $errmsg = _("Error while connecting to the LDAP server."); 168 return false; 169 } 170 } else { 171 if (($bind = @ldap_bind($connect, $this->mldap_rdn, $this->mldap_pass )) == false) { 172 $errmsg = _("Error while connecting to the LDAP server."); 173 return false; 174 } 175 } 176 177 // search for user 178 if (($res_id = ldap_search($connect, "o=$o", "$f=$username")) == false) { 179 $errmsg = _("Error while obtaining your LDAP information."); 180 181 return false; 182 } 183 184 if (ldap_count_entries($connect, $res_id) != 1) { 185 $errmsg = _("Error while obtaining your username or password from the LDAP server."); 186 187 return false; 188 } 189 190 if (($entry_id = ldap_first_entry($connect, $res_id)) == false) { 191 $errmsg = _("Error while obtaining your username or password from the LDAP server."); 192 193 return false; 194 } 195 196 if (($user_dn = ldap_get_dn($connect, $entry_id)) == false) { 197 $errmsg = _("Error while obtaining your username or password from the LDAP server."); 198 199 return false; 200 } 201 202 //Authenticate the User 203 if (($link_id = ldap_bind($connect, $user_dn, $password)) == false) { 204 $errmsg = _("Error in username or password."); 205 206 return false; 207 } 208 209 return true; 210 } else { 211 $errmsg = _("Error connecting to the LDAP Server."); 212 } 213 214 ldap_close($connect); 215 } else { 216 $rtval = false; 217 } 218 } 219 219 220 220 /** … … 231 231 * otherwise. 232 232 */ 233 public function login($username, $password, &$errmsg = null)234 {235 236 $db = AbstractDb::getObject();237 238 // Init values239 $retval = false;240 $username = $db->EscapeString($username);241 $password = $db->EscapeString($password);242 243 // Check if php-ldap extension is loaded244 if (Dependency::check("ldap", $errmsg)) {245 if ($this->checkLdapUser($username, $password, $this->mldap_hostname, $this->mldap_o, $this->mldap_filter, $errmsg)) {246 //LDAP Authentication Successful247 $sql = "SELECT user_id, pass FROM users WHERE (username='$username') AND account_origin='".$this->getNetwork()->getId()."'";248 249 $db->ExecSqlUniqueRes($sql, $user_info, false);250 251 if ($user_info != null) {252 $user = User::getObject($user_info['user_id']);253 254 if ($user->isUserValid($errmsg)) {255 $retval = $user;256 User::setCurrentUser($user);257 $errmsg = _("Login successfull");258 } else {259 $retval = false;260 //Error already been set261 }262 } else {263 $user = User::createUser(get_guid(), $username, $this->getNetwork(), "", "");264 $retval = &$user;265 $user->setAccountStatus(ACCOUNT_STATUS_ALLOWED);266 User::setCurrentUser($user); 267 $errmsg = _("Login successfull");268 }269 } else {270 returnfalse;271 //Error already been set272 }273 }274 275 return $retval;276 }233 public function login($username, $password, &$errmsg = null) 234 { 235 236 $db = AbstractDb::getObject(); 237 238 // Init values 239 $retval = false; 240 $username = $db->EscapeString($username); 241 $password = $db->EscapeString($password); 242 243 // Check if php-ldap extension is loaded 244 if (Dependency::check("ldap", $errmsg)) { 245 if ($this->checkLdapUser($username, $password, $this->mldap_hostname, $this->mldap_o, $this->mldap_filter, $errmsg)) { 246 //LDAP Authentication Successful 247 $sql = "SELECT user_id, pass FROM users WHERE (username='$username') AND account_origin='".$this->getNetwork()->getId()."'"; 248 249 $db->ExecSqlUniqueRes($sql, $user_info, false); 250 251 if ($user_info != null) { 252 $user = User::getObject($user_info['user_id']); 253 254 if ($user->isUserValid($errmsg)) { 255 $retval = $user; 256 User::setCurrentUser($user); 257 $errmsg = _("Login successfull"); 258 } else { 259 $retval = false; 260 //Error already been set 261 } 262 } else { 263 $user = User::createUser(get_guid(), $username, $this->getNetwork(), "", ""); 264 $retval = &$user; 265 $user->setAccountStatus(ACCOUNT_STATUS_ALLOWED); 266 267 $errmsg = _("Login successfull"); 268 } 269 } else { 270 $retval = false; 271 //Error already been set 272 } 273 } 274 User::setCurrentUser($retval); 275 return $retval; 276 } 277 277 278 278 /** trunk/wifidog-auth/wifidog/classes/Authenticators/AuthenticatorLocalUser.php
r1249 r1304 107 107 public function login($username, $password, &$errmsg = null) 108 108 { 109 109 //echo "DEBUG: login($username, $password, $errmsg)<br/>"; 110 110 $db = AbstractDb::getObject(); 111 111 … … 114 114 115 115 $username = $db->escapeString($username); 116 $password = $db->escapeString($password); 117 $password_hash = User::passwordHash($_REQUEST['password']); 118 119 $sql = "SELECT user_id FROM users WHERE (username='$username' OR email='$username') AND account_origin='".$this->getNetwork()->getId()."' AND pass='$password_hash'"; 120 $db->execSqlUniqueRes($sql, $user_info, false); 121 122 if ($user_info != null) { 123 $user = User::getObject($user_info['user_id']); 124 125 if ($user->isUserValid($errmsg)) { 126 $retval = &$user; 127 User::setCurrentUser($user); 128 $errmsg = _("Login successfull"); 129 } else { 130 $retval = false; 131 //Reason for refusal is already in $errmsg 132 } 133 } else { 134 /* 135 * This is only used to discriminate if the problem was a 136 * non-existent user of a wrong password. 137 */ 138 $user_info = null; 139 $db->execSqlUniqueRes("SELECT * FROM users WHERE (username='$username' OR email='$username') AND account_origin='".$this->getNetwork()->getId()."'", $user_info, false); 140 141 if ($user_info == null) { 142 $errmsg = _('Unknown username or email'); 143 } else { 144 $errmsg = _('Incorrect password (Maybe you have CAPS LOCK on?)'); 145 } 146 116 if (empty($username)) { 117 $errmsg .= sprintf(_("Fatal error: Username cannot be empty")); 147 118 $retval = false; 148 119 } 149 120 else{ 121 $password = $db->escapeString($password); 122 $password_hash = User::passwordHash($_REQUEST['password']); 123 124 $sql = "SELECT user_id FROM users WHERE (username='$username' OR email='$username') AND account_origin='".$this->getNetwork()->getId()."' AND pass='$password_hash'"; 125 $db->execSqlUniqueRes($sql, $user_info, false); 126 127 if ($user_info != null) { 128 $user = User::getObject($user_info['user_id']); 129 130 if ($user->isUserValid($errmsg)) { 131 $retval = &$user; 132 $errmsg = _("Login successfull"); 133 } else { 134 $retval = false; 135 //Reason for refusal is already in $errmsg 136 } 137 } else { 138 /* 139 * This is only used to discriminate if the problem was a 140 * non-existent user of a wrong password. 141 */ 142 $user_info = null; 143 $db->execSqlUniqueRes("SELECT * FROM users WHERE (username='$username' OR email='$username') AND account_origin='".$this->getNetwork()->getId()."'", $user_info, false); 144 145 if ($user_info == null) { 146 $errmsg = _('Unknown username or email'); 147 } else { 148 $errmsg = _('Incorrect password (Maybe you have CAPS LOCK on?)'); 149 } 150 151 $retval = false; 152 } 153 } 154 User::setCurrentUser($retval); 150 155 return $retval; 151 156 } trunk/wifidog-auth/wifidog/classes/Authenticators/AuthenticatorRadius.php
r1249 r1304 174 174 175 175 $db = AbstractDb::getObject(); 176 176 User :: setCurrentUser(null);//This should fix a security hole if using an empty username. I didn't have time to audit the radius code to see if it really was vulnerable, and code a better fix. 177 177 // Init values 178 178 $retval = false; trunk/wifidog-auth/wifidog/classes/User.php
r1289 r1304 121 121 * This should NOT be called by anything except the Authenticators 122 122 * 123 * @param object $user User a user object 123 * @param object $user User a user object, or null 124 124 * 125 125 * @return bool True if everything went well setting the session 126 126 127 127 */ 128 public static function setCurrentUser(User $user) { 128 public static function setCurrentUser($user) { 129 130 if (get_class($user) == 'User'){ 131 $userId = $user->getId(); 132 $passwordHash = $user->getPasswordHash(); 133 } 134 else { 135 $userId = null; 136 $passwordHash = null; 137 } 138 129 139 try { 130 140 $session = Session::getObject(); 131 $session->set(SESS_USER_ID_VAR, $user ->getId());132 $session->set(SESS_PASSWORD_HASH_VAR, $ user->getPasswordHash());141 $session->set(SESS_USER_ID_VAR, $userId); 142 $session->set(SESS_PASSWORD_HASH_VAR, $passwordHash); 133 143 return true; 134 144 } catch (Exception $e) { … … 330 340 return $this->_row['open_id_url']; 331 341 } 332 342 333 343 function getUsername() { 334 344 return $this->_row['username']; … … 936 946 'title' => _("Import NoCat user database"), 937 947 'url' => BASE_URL_PATH."admin/import_user_database.php" 938 );939 } 940 if(Security::getObjectsWithPermission(Permission::P('NETWORK_PERM_EDIT_ANY_USER')))948 ); 949 } 950 if(Security::getObjectsWithPermission(Permission::P('NETWORK_PERM_EDIT_ANY_USER'))) 941 951 { 942 952 $items[] = array('path' => 'users/user_manager', 943 953 'title' => _("User manager"), 944 954 'url' => BASE_URL_PATH."admin/user_log.php" 945 );946 } 947 if(Security::getObjectsWithPermission(Permission::P('NETWORK_PERM_VIEW_STATISTICS')))955 ); 956 } 957 if(Security::getObjectsWithPermission(Permission::P('NETWORK_PERM_VIEW_STATISTICS'))) 948 958 { 949 959 $items[] = array('path' => 'users/statistics', 950 960 'title' => _("Statistics"), 951 961 'url' => BASE_URL_PATH."admin/stats.php" 952 );962 ); 953 963 } 954 964 $items[] = array('path' => 'users', trunk/wifidog-auth/wifidog/login/index.php
r1261 r1304 199 199 $user = User::getCurrentUser(); 200 200 if (!$user) { 201 //Normally, we already have a user logged-in (pr ecessed by process_login_out.php). But we try again, if only to display the error201 //Normally, we already have a user logged-in (processed by process_login_out.php). But we try again, if only to display the error 202 202 Authenticator::processLoginUI($errmsg); 203 203 } 204 204 //echo "DEBUG: user: "; echo $user->getUsername(); 205 205 if ($user != null) { 206 206 if (!empty($gw_address) && !empty($gw_port)) {
