1<?php 2 3// Pandora FMS - http://pandorafms.com 4// ================================================== 5// Copyright (c) 2005-2009 Artica Soluciones Tecnologicas 6// Please see http://pandorafms.org for full contribution list 7 8// This program is free software; you can redistribute it and/or 9// modify it under the terms of the GNU Lesser General Public License 10// as published by the Free Software Foundation; version 2 11 12// This program is distributed in the hope that it will be useful, 13// but WITHOUT ANY WARRANTY; without even the implied warranty of 14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15// GNU General Public License for more details. 16 17/** 18 * @package Include/auth 19 */ 20 21if (!isset ($config)) { 22 die (' 23<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 24<html> 25 <head> 26 <title>Pandora FMS - The Flexible Monitoring System - Console error</title> 27 <meta http-equiv="expires" content="0"> 28 <meta http-equiv="content-type" content="text/html; charset=utf8"> 29 <meta name="resource-type" content="document"> 30 <meta name="distribution" content="global"> 31 <meta name="author" content="Sancho Lerena"> 32 <meta name="copyright" content="This is GPL software. Created by Sancho Lerena and others"> 33 <meta name="keywords" content="pandora, monitoring, system, GPL, software"> 34 <meta name="robots" content="index, follow"> 35 <link rel="icon" href="../../images/pandora.ico" type="image/ico"> 36 <link rel="stylesheet" href="../styles/pandora.css" type="text/css"> 37 </head> 38 <body> 39 <div id="main" style="float:left; margin-left: 100px"> 40 <div align="center"> 41 <div id="login_f"> 42 <h1 id="log_f" class="error">You cannot access this file</h1> 43 <div> 44 <img src="../../images/pandora_logo.png" border="0" /> 45 </div> 46 <div class="msg"> 47 <span class="error"> 48 <b>ERROR:</b> You can\'t access this file directly! 49 </span> 50 </div> 51 </div> 52 </div> 53 </div> 54 </body> 55</html> 56'); 57} 58 59include_once($config['homedir'] . "/include/functions_profile.php"); 60enterprise_include ('include/auth/mysql.php'); 61 62$config["user_can_update_info"] = true; 63$config["user_can_update_password"] = true; 64$config["admin_can_add_user"] = true; 65$config["admin_can_delete_user"] = true; 66$config["admin_can_disable_user"] = false; //currently not implemented 67$config["admin_can_make_admin"] = true; 68 69/** 70 * process_user_login accepts $login and $pass and handles it according to current authentication scheme 71 * 72 * @param string $login 73 * @param string $pass 74 * @param boolean $api 75 * 76 * @return mixed False in case of error or invalid credentials, the username in case it's correct. 77 */ 78function process_user_login ($login, $pass, $api = false) { 79 global $config, $mysql_cache; 80 81 // Always authenticate admins against the local database 82 if (strtolower ($config["auth"]) == 'mysql' || is_user_admin ($login)) { 83 return process_user_login_local ($login, $pass, $api); 84 } 85 else { 86 $login_remote = process_user_login_remote ($login, $pass, $api); 87 if ($login_remote == false && $config['fallback_local_auth'] == '1') { 88 return process_user_login_local ($login, $pass, $api); 89 } 90 else { 91 return $login_remote; 92 } 93 } 94 95 return false; 96} 97 98function process_user_login_local ($login, $pass, $api = false) { 99 global $config, $mysql_cache; 100 101 // Connect to Database 102 switch ($config["dbtype"]) { 103 case "mysql": 104 if (!$api) { 105 $sql = sprintf ("SELECT `id_user`, `password` 106 FROM `tusuario` 107 WHERE `id_user` = '%s' AND `not_login` = 0 108 AND `disabled` = 0", $login); 109 } 110 else { 111 $sql = sprintf ("SELECT `id_user`, `password` 112 FROM `tusuario` 113 WHERE `id_user` = '%s' 114 AND `disabled` = 0", $login); 115 } 116 break; 117 case "postgresql": 118 if (!$api) { 119 $sql = sprintf ('SELECT "id_user", "password" 120 FROM "tusuario" 121 WHERE "id_user" = \'%s\' AND "not_login" = 0 122 AND "disabled" = 0', $login); 123 } 124 else { 125 $sql = sprintf ('SELECT "id_user", "password" 126 FROM "tusuario" 127 WHERE "id_user" = \'%s\' 128 AND "disabled" = 0', $login); 129 } 130 break; 131 case "oracle": 132 if (!$api) { 133 $sql = sprintf ('SELECT id_user, password 134 FROM tusuario 135 WHERE id_user = \'%s\' AND not_login = 0 136 AND disabled = 0', $login); 137 } 138 else { 139 $sql = sprintf ('SELECT id_user, password 140 FROM tusuario 141 WHERE id_user = \'%s\' 142 AND disabled = 0', $login); 143 } 144 break; 145 } 146 $row = db_get_row_sql ($sql); 147 148 //Check that row exists, that password is not empty and that password is the same hash 149 if ($row !== false && $row["password"] !== md5 ("") 150 && $row["password"] == md5 ($pass)) { 151 // Login OK 152 // Nick could be uppercase or lowercase (select in MySQL 153 // is not case sensitive) 154 // We get DB nick to put in PHP Session variable, 155 // to avoid problems with case-sensitive usernames. 156 // Thanks to David Muñiz for Bug discovery :) 157 return $row["id_user"]; 158 } 159 else { 160 if (!user_can_login($login)) { 161 $mysql_cache["auth_error"] = "User only can use the API."; 162 $config["auth_error"] = "User only can use the API."; 163 } 164 else { 165 $mysql_cache["auth_error"] = "User not found in database or incorrect password"; 166 $config["auth_error"] = "User not found in database or incorrect password"; 167 } 168 } 169 170 return false; 171} 172 173function process_user_login_remote ($login, $pass, $api = false) { 174 global $config, $mysql_cache; 175 176 177 178 // Remote authentication 179 switch ($config["auth"]) { 180 // LDAP 181 case 'ldap': 182 if (ldap_process_user_login ($login, $pass) === false) { 183 $config["auth_error"] = "User not found in database or incorrect password"; 184 return false; 185 } 186 break; 187 188 // Active Directory 189 case 'ad': 190 if (enterprise_hook ('ad_process_user_login', array ($login, $pass)) === false) { 191 $config["auth_error"] = "User not found in database or incorrect password"; 192 return false; 193 } 194 break; 195 196 // Remote Pandora FMS 197 case 'pandora': 198 if (enterprise_hook ('remote_pandora_process_user_login', array ($login, $pass)) === false) { 199 $config["auth_error"] = "User not found in database or incorrect password"; 200 return false; 201 } 202 break; 203 204 // Remote Babel Enterprise 205 case 'babel': 206 if (enterprise_hook ('remote_babel_process_user_login', array ($login, $pass)) === false) { 207 $config["auth_error"] = "User not found in database or incorrect password"; 208 return false; 209 } 210 break; 211 212 // Remote Integria 213 case 'integria': 214 if (enterprise_hook ('remote_integria_process_user_login', array ($login, $pass)) === false) { 215 $config["auth_error"] = "User not found in database or incorrect password"; 216 return false; 217 } 218 break; 219 220 // Unknown authentication method 221 default: 222 $config["auth_error"] = "User not found in database 223 or incorrect password"; 224 return false; 225 break; 226 } 227 228 // Authentication ok, check if the user exists in the local database 229 if (is_user ($login)) { 230 231 232 if (!user_can_login($login)) { 233 return false; 234 } 235 236 if (($config["auth"] === 'ad') && 237 (isset($config['ad_advanced_config']) && $config['ad_advanced_config'])) { 238 239 240 241 $return = enterprise_hook ('prepare_permissions_groups_of_user_ad', 242 array ($login, $pass, false, true)); 243 244 if ($return === "error_permissions") { 245 $config["auth_error"] = 246 __("Problems with configuration permissions. Please contact with Administrator"); 247 return false; 248 } 249 else { 250 if ($return === "permissions_changed") { 251 $config["auth_error"] = __("Your permmission have been change. Please, login again"); 252 return false; 253 } 254 } 255 } 256 return $login; 257 } 258 259 260 261 262 // The user does not exist and can not be created 263 if ($config['autocreate_remote_users'] == 0 || is_user_blacklisted ($login)) { 264 $config["auth_error"] = __("Ooops User not found in 265 database or incorrect password"); 266 267 return false; 268 } 269 270 // Create the user in the local database 271 if (isset($config['ad_advanced_config']) && $config['ad_advanced_config']) { 272 273 274 if ( defined('METACONSOLE') ) { 275 enterprise_include_once('include/functions_metaconsole.php'); 276 enterprise_include_once ('meta/include/functions_groups_meta.php'); 277 278 $return = groups_meta_synchronizing(); 279 280 if ($return["group_create_err"] > 0 || $return["group_update_err"] > 0) { 281 $config["auth_error"] = __('Fail the group synchronizing'); 282 return false; 283 } 284 285 $return = meta_tags_synchronizing(); 286 if ($return['tag_create_err'] > 0 || $return['tag_update_err'] > 0) { 287 $config["auth_error"] = __('Fail the tag synchronizing'); 288 return false; 289 } 290 } 291 292 // Create the user 293 if (enterprise_hook ('prepare_permissions_groups_of_user_ad', 294 array($login, 295 $pass, 296 array ('fullname' => $login, 297 'comments' => 'Imported from ' . $config['auth']), 298 false, defined('METACONSOLE'))) === false) { 299 300 $config["auth_error"] = __("User not found in database 301 or incorrect password"); 302 303 return false; 304 } 305 } 306 else { 307 // Create the user in the local database 308 if (create_user ($login, $pass, 309 array ('fullname' => $login, 310 'comments' => 'Imported from ' . $config['auth']) 311 ) === false) { 312 $config["auth_error"] = __("User not found in database or incorrect password"); 313 return false; 314 } 315 316 //TODO: Check the creation in the nodes 317 318 profile_create_user_profile ($login, $config['default_remote_profile'], 319 $config['default_remote_group'], false, $config['default_assign_tags']); 320 } 321 322 return $login; 323} 324 325/** 326 * Checks if a user is administrator. 327 * 328 * @param string User id. 329 * 330 * @return bool True is the user is admin 331 */ 332function is_user_admin ($id_user) { 333 $is_admin = (bool) db_get_value ('is_admin', 'tusuario', 'id_user', $id_user); 334 335 return $is_admin; 336} 337 338 339/** 340 * Get the user id field on a mixed structure. 341 * 342 * This function is needed to make auth system more compatible and independant. 343 * 344 * @param mixed User structure to get id. It might be a row returned from 345 * tusuario or tusuario_perfil. If it's not a row, the int value is returned. 346 * 347 * @return int User id of the mixed parameter. 348 */ 349function get_user_id ($user) { 350 if (is_array ($user)) { 351 if (isset ($user['id_user'])) 352 return $user['id_user']; 353 elseif (isset ($user['id_usuario'])) 354 return $user['id_usuario']; 355 else 356 return false; 357 } 358 else { 359 return $user; 360 } 361} 362 363/** 364 * Check is a user exists in the system 365 * 366 * @param mixed User id. 367 * 368 * @return bool True if the user exists. 369 */ 370function is_user ($user) { 371 $user = db_get_row('tusuario', 'id_user', get_user_id ($user)); 372 373 if (! $user) 374 return false; 375 376 return true; 377} 378 379function user_can_login($user) { 380 $not_login = db_get_value('not_login', 'tusuario', 'id_user', $user); 381 382 if ($not_login != 0) { 383 return false; 384 } 385 386 return true; 387} 388 389/** 390 * Gets the users real name 391 * 392 * @param mixed User id. 393 * 394 * @return string The users full name 395 */ 396function get_user_fullname ($user) { 397 return (string) db_get_value ('fullname', 'tusuario', 'id_user', get_user_id ($user)); 398} 399 400/** 401 * Gets the users email 402 * 403 * @param mixed User id. 404 * 405 * @return string The users email address 406 */ 407function get_user_email ($user) { 408 return (string) db_get_value ('email', 'tusuario', 'id_user', get_user_id ($user)); 409} 410 411/** 412 * Gets a Users info 413 * 414 * @param mixed User id 415 * 416 * @return mixed An array of users 417 */ 418function get_user_info ($user) { 419 return db_get_row ("tusuario", "id_user", get_user_id ($user)); 420} 421 422/** 423 * Get a list of all users in an array [username] => array (userinfo) 424 * We can't simplify this because some auth schemes (like LDAP) automatically (or it's at least cheaper to) return all the information 425 * Functions like get_user_info allow selection of specifics (in functions_db) 426 * 427 * @param string Field to order by (id_user, fullname or registered) 428 * 429 * @return array An array of user information 430 */ 431function get_users ($order = "fullname", $filter = false, $fields = false) { 432 if (is_array($order)) { 433 $filter['order'] = $order['field'] . ' ' . $order['order']; 434 } 435 else { 436 switch ($order) { 437 case "registered": 438 case "last_connect": 439 case "fullname": 440 break; 441 default: 442 $order = "fullname"; 443 break; 444 } 445 446 $filter['order'] = $order." ASC"; 447 } 448 449 450 $output = array(); 451 452 $result = db_get_all_rows_filter ("tusuario", $filter, $fields); 453 if ($result !== false) { 454 foreach ($result as $row) { 455 $output[$row["id_user"]] = $row; 456 } 457 } 458 459 return $output; 460} 461 462/** 463 * Sets the last login for a user 464 * 465 * @param string User id 466 */ 467function process_user_contact ($id_user) { 468 return db_process_sql_update ("tusuario", 469 array ("last_connect" => get_system_time ()), 470 array ("id_user" => $id_user)); 471} 472 473/** 474 * Create a new user 475 * 476 * @return bool false 477 */ 478function create_user ($id_user, $password, $user_info) { 479 $values = $user_info; 480 $values["id_user"] = $id_user; 481 $values["password"] = md5 ($password); 482 $values["last_connect"] = 0; 483 $values["registered"] = get_system_time (); 484 485 return (@db_process_sql_insert ("tusuario", $values)) !== false; 486} 487 488/** 489 * Save password history 490 * 491 * @return bool false 492 */ 493function save_pass_history ($id_user, $password) { 494 $values["id_user"] = $id_user; 495 $values["password"] = md5 ($password); 496 $values["date_begin"] = date ("Y/m/d H:i:s", get_system_time()); 497 498 return (@db_process_sql_insert ("tpassword_history", $values)) !== false; 499} 500 501/** 502 * Deletes the user 503 * 504 * @param string User id 505 */ 506function delete_user ($id_user) { 507 $result = db_process_sql_delete('tusuario_perfil', 508 array('id_usuario' => $id_user)); 509 if ($result === false) { 510 return false; 511 } 512 513 $result = db_process_sql_delete('tusuario', 514 array('id_user' => $id_user)); 515 if ($result === false) { 516 return false; 517 } 518 return true; 519} 520 521/** 522 * Update the password in MD5 for user pass as id_user with 523 * password in plain text. 524 * 525 * @param string user User ID 526 * @param string password Password in plain text. 527 * 528 * @return mixed False in case of error or invalid values passed. Affected rows otherwise 529 */ 530function update_user_password ($user, $password_new) { 531 global $config; 532 if (isset($config['auth']) && $config['auth'] == 'pandora') { 533 $sql = sprintf("UPDATE tusuario SET password = '" . md5($password_new) . 534 "', last_pass_change = '" . date("Y-m-d H:i:s", get_system_time()) . 535 "' WHERE id_user = '" . $user . "'"); 536 537 $connection = mysql_connect_db($config['rpandora_server'], 538 $config['rpandora_dbname'], $config['rpandora_user'], 539 $config['rpandora_pass']); 540 $remote_pass_update = db_process_sql ($sql, 'affected_rows', $connection); 541 542 if (!$remote_pass_update) { 543 $config["auth_error"] = __('Could not changes password on remote pandora'); 544 return false; 545 } 546 } 547 return db_process_sql_update ('tusuario', 548 array ('password' => md5 ($password_new), 'last_pass_change' => date ("Y/m/d H:i:s", get_system_time())), 549 array ('id_user' => $user)); 550} 551 552/** 553 * Update the data of a user that user is choose with 554 * id_user. 555 * 556 * @param string user User ID 557 * @param array values Associative array with index as name of field and content. 558 * 559 * @return mixed False in case of error or invalid values passed. Affected rows otherwise 560 */ 561function update_user ($id_user, $values) { 562 if (! is_array ($values)) 563 return false; 564 565 return db_process_sql_update ("tusuario", $values, array ("id_user" => $id_user)); 566} 567 568/** 569 * Authenticate against an LDAP server. 570 * 571 * @param string User login 572 * @param string User password (plain text) 573 * 574 * @return bool True if the login is correct, false in other case 575 */ 576function ldap_process_user_login ($login, $password) { 577 global $config; 578 579 if (! function_exists ("ldap_connect")) { 580 $config["auth_error"] = __('Your installation of PHP does not support LDAP'); 581 582 return false; 583 } 584 585 // Connect to the LDAP server 586 $ds = @ldap_connect ($config["ldap_server"], $config["ldap_port"]); 587 588 if (!$ds) { 589 $config["auth_error"] = 'Error connecting to LDAP server'; 590 591 return false; 592 } 593 594 // Set the LDAP version 595 ldap_set_option ($ds, LDAP_OPT_PROTOCOL_VERSION, $config["ldap_version"]); 596 597 if ($config["ldap_start_tls"]) { 598 if (!@ldap_start_tls ($ds)) { 599 $config["auth_error"] = 'Could not start TLS for LDAP connection'; 600 @ldap_close ($ds); 601 602 return false; 603 } 604 } 605 606 $ldap_login_attr = isset($config["ldap_login_attr"]) ? io_safe_output($config["ldap_login_attr"]) . "=" : ''; 607 $ldap_base_dn = isset($config["ldap_base_dn"]) ? "," . io_safe_output($config["ldap_base_dn"]) : ''; 608 609 if (strlen($password) == 0 || 610 !@ldap_bind($ds, 611 $ldap_login_attr. io_safe_output($login) . $ldap_base_dn, 612 $password)) { 613 614 $config["auth_error"] = 'User not found in database or incorrect password'; 615 @ldap_close ($ds); 616 617 return false; 618 } 619 620 @ldap_close ($ds); 621 622 return true; 623} 624 625/** 626 * Checks if a user is in the autocreate blacklist. 627 * 628 * @param string User 629 * 630 * @return bool True if the user is in the blacklist, false otherwise. 631 */ 632function is_user_blacklisted ($user) { 633 global $config; 634 635 $blisted_users = explode (',', $config['autocreate_blacklist']); 636 foreach ($blisted_users as $blisted_user) { 637 if ($user == $blisted_user) { 638 return true; 639 } 640 } 641 642 return false; 643} 644 645//Reference the global use authorization error to last auth error. 646$config["auth_error"] = &$mysql_cache["auth_error"]; 647?>