557 * @param string $challenge The 256-bit MD5 challenge string - first 128 bits should be the hash, the last 128 should be the challenge salt |
557 * @param string $challenge The 256-bit MD5 challenge string - first 128 bits should be the hash, the last 128 should be the challenge salt |
558 * @param int $level The privilege level we're authenticating for, defaults to 0 |
558 * @param int $level The privilege level we're authenticating for, defaults to 0 |
559 * @return string 'success' on success, or error string on failure |
559 * @return string 'success' on success, or error string on failure |
560 */ |
560 */ |
561 |
561 |
562 function login_with_crypto($username, $aes_data, $aes_key, $challenge, $level = USER_LEVEL_MEMBER) |
562 function login_with_crypto($username, $aes_data, $aes_key_id, $challenge, $level = USER_LEVEL_MEMBER) |
563 { |
563 { |
564 global $db, $session, $paths, $template, $plugins; // Common objects |
564 global $db, $session, $paths, $template, $plugins; // Common objects |
565 |
565 |
566 $privcache = $this->private_key; |
566 $privcache = $this->private_key; |
567 |
567 |
568 // Instanciate the Rijndael encryption object |
568 // Instanciate the Rijndael encryption object |
569 $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE); |
569 $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE); |
570 |
570 |
571 // Fetch our decryption key |
571 // Fetch our decryption key |
572 |
572 |
573 $aes_key = $this->fetch_public_key($aes_key); |
573 $aes_key = $this->fetch_public_key($aes_key_id); |
574 if(!$aes_key) |
574 if(!$aes_key) |
575 return 'Couldn\'t look up public key "'.$aes_key.'" for decryption'; |
575 return 'Couldn\'t look up public key "'.htmlspecialchars($aes_key_id).'" for decryption'; |
576 |
576 |
577 // Convert the key to a binary string |
577 // Convert the key to a binary string |
578 $bin_key = hexdecode($aes_key); |
578 $bin_key = hexdecode($aes_key); |
579 |
579 |
580 if(strlen($bin_key) != AES_BITS / 8) |
580 if(strlen($bin_key) != AES_BITS / 8) |
585 |
585 |
586 // Initialize our success switch |
586 // Initialize our success switch |
587 $success = false; |
587 $success = false; |
588 |
588 |
589 // Escaped username |
589 // Escaped username |
|
590 $username = str_replace('_', ' ', $username); |
590 $db_username_lower = $this->prepare_text(strtolower($username)); |
591 $db_username_lower = $this->prepare_text(strtolower($username)); |
591 $db_username = $this->prepare_text($username); |
592 $db_username = $this->prepare_text($username); |
592 |
593 |
593 // Select the user data from the table, and decrypt that so we can verify the password |
594 // Select the user data from the table, and decrypt that so we can verify the password |
594 $this->sql('SELECT password,old_encryption,user_id,user_level,theme,style,temp_password,temp_password_time FROM '.table_prefix.'users WHERE lcase(username)=\''.$db_username_lower.'\' OR username=\'' . $db_username . '\';'); |
595 $this->sql('SELECT password,old_encryption,user_id,user_level,theme,style,temp_password,temp_password_time FROM '.table_prefix.'users WHERE lcase(username)=\''.$db_username_lower.'\' OR username=\'' . $db_username . '\';'); |
700 { |
701 { |
701 global $db, $session, $paths, $template, $plugins; // Common objects |
702 global $db, $session, $paths, $template, $plugins; // Common objects |
702 |
703 |
703 $pass_hashed = ( $already_md5ed ) ? $password : md5($password); |
704 $pass_hashed = ( $already_md5ed ) ? $password : md5($password); |
704 |
705 |
|
706 // Replace underscores with spaces in username |
|
707 // (Added in 1.0.2) |
|
708 $username = str_replace('_', ' ', $username); |
|
709 |
705 // Perhaps we're upgrading Enano? |
710 // Perhaps we're upgrading Enano? |
706 if($this->compat) |
711 if($this->compat) |
707 { |
712 { |
708 return $this->login_compat($username, $pass_hashed, $level); |
713 return $this->login_compat($username, $pass_hashed, $level); |
709 } |
714 } |
894 $query = $this->sql('INSERT INTO '.table_prefix.'session_keys(session_key, salt, user_id, auth_level, source_ip, time) VALUES(\''.$keyhash.'\', \''.$salt.'\', '.$user_id.', '.$level.', \''.$ip.'\', '.$time.');'); |
899 $query = $this->sql('INSERT INTO '.table_prefix.'session_keys(session_key, salt, user_id, auth_level, source_ip, time) VALUES(\''.$keyhash.'\', \''.$salt.'\', '.$user_id.', '.$level.', \''.$ip.'\', '.$time.');'); |
895 return true; |
900 return true; |
896 } |
901 } |
897 |
902 |
898 /** |
903 /** |
899 * Identical to register_session in nature, but uses the old login/table structure. DO NOT use this. |
904 * Identical to register_session in nature, but uses the old login/table structure. DO NOT use this except in the upgrade script under very controlled circumstances. |
900 * @see sessionManager::register_session() |
905 * @see sessionManager::register_session() |
901 * @access private |
906 * @access private |
902 */ |
907 */ |
903 |
908 |
904 function register_session_compat($user_id, $username, $password, $level = 0) |
909 function register_session_compat($user_id, $username, $password, $level = 0) |
1336 */ |
1341 */ |
1337 |
1342 |
1338 function check_banlist() |
1343 function check_banlist() |
1339 { |
1344 { |
1340 global $db, $session, $paths, $template, $plugins; // Common objects |
1345 global $db, $session, $paths, $template, $plugins; // Common objects |
1341 if($this->compat) |
1346 $col_reason = ( $this->compat ) ? '"No reason entered (session manager is in compatibility mode)" AS reason' : 'reason'; |
1342 $q = $this->sql('SELECT ban_id,ban_type,ban_value,is_regex FROM '.table_prefix.'banlist ORDER BY ban_type;'); |
1347 $is_banned = false; |
1343 else |
1348 if ( $this->user_logged_in ) |
1344 $q = $this->sql('SELECT ban_id,ban_type,ban_value,is_regex,reason FROM '.table_prefix.'banlist ORDER BY ban_type;'); |
1349 { |
1345 if(!$q) $db->_die('The banlist data could not be selected.'); |
1350 // check by IP, email, and username |
1346 $banned = false; |
1351 $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE \n" |
1347 while($row = $db->fetchrow()) |
1352 . " ( ban_type = " . BAN_IP . " AND is_regex = 0 ) OR \n" |
1348 { |
1353 . " ( ban_type = " . BAN_IP . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' REGEXP ban_value ) OR \n" |
1349 if($this->compat) |
1354 . " ( ban_type = " . BAN_USER . " AND is_regex = 0 AND ban_value = '{$this->username}' ) OR \n" |
1350 $row['reason'] = 'None available - session manager is in compatibility mode'; |
1355 . " ( ban_type = " . BAN_USER . " AND is_regex = 1 AND '{$this->username}' REGEXP ban_value ) OR \n" |
1351 switch($row['ban_type']) |
1356 . " ( ban_type = " . BAN_EMAIL . " AND is_regex = 0 AND ban_value = '{$this->email}' ) OR \n" |
1352 { |
1357 . " ( ban_type = " . BAN_EMAIL . " AND is_regex = 1 AND '{$this->email}' REGEXP ban_value ) \n" |
1353 case BAN_IP: |
1358 . " ORDER BY ban_type ASC;"; |
1354 if(intval($row['is_regex'])==1) { |
1359 $q = $this->sql($sql); |
1355 if(preg_match('#'.$row['ban_value'].'#i', $_SERVER['REMOTE_ADDR'])) |
1360 if ( $db->numrows() > 0 ) |
|
1361 { |
|
1362 while ( list($reason, $ban_value, $ban_type, $is_regex) = $db->fetchrow_num() ) |
|
1363 { |
|
1364 if ( $ban_type == BAN_IP && $row['is_regex'] != 1 ) |
1356 { |
1365 { |
|
1366 // check range |
|
1367 $regexp = parse_ip_range_regex($ban_value); |
|
1368 if ( !$regexp ) |
|
1369 { |
|
1370 continue; |
|
1371 } |
|
1372 if ( preg_match("/$regexp/", $_SERVER['REMOTE_ADDR']) ) |
|
1373 { |
|
1374 $banned = true; |
|
1375 } |
|
1376 } |
|
1377 else |
|
1378 { |
|
1379 // User is banned |
1357 $banned = true; |
1380 $banned = true; |
1358 $reason = $row['reason']; |
|
1359 } |
1381 } |
1360 } |
1382 } |
1361 else { |
1383 } |
1362 if($row['ban_value']==$_SERVER['REMOTE_ADDR']) { $banned = true; $reason = $row['reason']; } |
1384 $db->free_result(); |
1363 } |
1385 } |
1364 break; |
1386 else |
1365 case BAN_USER: |
1387 { |
1366 if(intval($row['is_regex'])==1) { |
1388 // check by IP only |
1367 if(preg_match('#'.$row['ban_value'].'#i', $this->username)) |
1389 $sql = "SELECT $col_reason, ban_value, ban_type, is_regex FROM " . table_prefix . "banlist WHERE |
|
1390 ( ban_type = " . BAN_IP . " AND is_regex = 0 ) OR |
|
1391 ( ban_type = " . BAN_IP . " AND is_regex = 1 AND '{$_SERVER['REMOTE_ADDR']}' REGEXP ban_value ) |
|
1392 ORDER BY ban_type ASC;"; |
|
1393 $q = $this->sql($sql); |
|
1394 if ( $db->numrows() > 0 ) |
|
1395 { |
|
1396 while ( list($reason, $ban_value, $ban_type, $is_regex) = $db->fetchrow_num() ) |
|
1397 { |
|
1398 if ( $ban_type == BAN_IP && $row['is_regex'] != 1 ) |
1368 { |
1399 { |
|
1400 // check range |
|
1401 $regexp = parse_ip_range_regex($ban_value); |
|
1402 if ( !$regexp ) |
|
1403 continue; |
|
1404 if ( preg_match("/$regexp/", $_SERVER['REMOTE_ADDR']) ) |
|
1405 { |
|
1406 $banned = true; |
|
1407 } |
|
1408 } |
|
1409 else |
|
1410 { |
|
1411 // User is banned |
1369 $banned = true; |
1412 $banned = true; |
1370 $reason = $row['reason']; |
|
1371 } |
1413 } |
1372 } |
1414 } |
1373 else { |
1415 } |
1374 if($row['ban_value']==$this->username) { $banned = true; $reason = $row['reason']; } |
1416 $db->free_result(); |
1375 } |
1417 } |
1376 break; |
1418 if ( $banned && $paths->get_pageid_from_url() != $paths->nslist['Special'].'CSS' ) |
1377 case BAN_EMAIL: |
|
1378 if(intval($row['is_regex'])==1) { |
|
1379 if(preg_match('#'.$row['ban_value'].'#i', $this->email)) |
|
1380 { |
|
1381 $banned = true; |
|
1382 $reason = $row['reason']; |
|
1383 } |
|
1384 } |
|
1385 else { |
|
1386 if($row['ban_value']==$this->email) { $banned = true; $reason = $row['reason']; } |
|
1387 } |
|
1388 break; |
|
1389 default: |
|
1390 die('Ban error: rule "'.$row['ban_value'].'" has an invalid type ('.$row['ban_type'].')'); |
|
1391 } |
|
1392 } |
|
1393 if($banned && $paths->get_pageid_from_url() != $paths->nslist['Special'].'CSS') |
|
1394 { |
1419 { |
1395 // This guy is banned - kill the session, kill the database connection, bail out, and be pretty about it |
1420 // This guy is banned - kill the session, kill the database connection, bail out, and be pretty about it |
1396 die_semicritical('Ban notice', '<div class="error-box">You have been banned from this website. Please contact the site administrator for more information.<br /><br />Reason:<br />'.$reason.'</div>'); |
1421 die_semicritical('Ban notice', '<div class="error-box">You have been banned from this website. Please contact the site administrator for more information.<br /><br />Reason:<br />'.$reason.'</div>'); |
1397 exit; |
1422 exit; |
1398 } |
1423 } |
1400 |
1425 |
1401 # Registration |
1426 # Registration |
1402 |
1427 |
1403 /** |
1428 /** |
1404 * Registers a user. This does not perform any type of login. |
1429 * Registers a user. This does not perform any type of login. |
1405 * @param string $username |
1430 * @param string New user's username |
1406 * @param string $password This should be unencrypted. |
1431 * @param string This should be unencrypted. |
1407 * @param string $email |
1432 * @param string E-mail address. |
1408 * @param string $real_name Optional, defaults to ''. |
1433 * @param string Optional, defaults to ''. |
1409 * @param bool $coppa Optional. If true, the account is not activated initially and an admin activation request is sent. The caller is responsible for sending the address info and notice. |
1434 * @param bool Optional. If true, the account is not activated initially and an admin activation request is sent. The caller is responsible for sending the address info and notice. |
1410 */ |
1435 */ |
1411 |
1436 |
1412 function create_user($username, $password, $email, $real_name = '', $coppa = false) |
1437 function create_user($username, $password, $email, $real_name = '', $coppa = false) |
1413 { |
1438 { |
1414 global $db, $session, $paths, $template, $plugins; // Common objects |
1439 global $db, $session, $paths, $template, $plugins; // Common objects |
1415 |
1440 |
1416 // Initialize AES |
1441 // Initialize AES |
1417 $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE); |
1442 $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE); |
1418 |
1443 |
1419 if(!preg_match('#^'.$this->valid_username.'$#', $username)) return 'The username you chose contains invalid characters.'; |
1444 if(!preg_match('#^'.$this->valid_username.'$#', $username)) return 'The username you chose contains invalid characters.'; |
|
1445 $username = str_replace('_', ' ', $username); |
1420 $user_orig = $username; |
1446 $user_orig = $username; |
1421 $username = $this->prepare_text($username); |
1447 $username = $this->prepare_text($username); |
1422 $email = $this->prepare_text($email); |
1448 $email = $this->prepare_text($email); |
1423 $real_name = $this->prepare_text($real_name); |
1449 $real_name = $this->prepare_text($real_name); |
1424 |
1450 |