1<?php 2/*********************************************************** 3 Copyright (C) 2011-2015 Hewlett-Packard Development Company, L.P. 4 Copyright (C) 2015 Siemens AG 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License version 2.1 as published by the Free Software Foundation. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public License 16 along with this library; if not, write to the Free Software Foundation, Inc.0 17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 ***********************************************************/ 19 20/** 21 * \file 22 * \brief This file contains common authentication function 23 */ 24 25 26/** 27 * \brief Check if SiteMinder is enabled. 28 * 29 * \note This can be used for other authentication agents by changing 30 * $IDEnvVar 31 * \return -1 if not enabled, or the users SEA if enabled 32 */ 33function siteminder_check() 34{ 35 // $IDEnvVar = 'HPPF_AUTH_UID'; // for example for PingIdentity 36 $IDEnvVar = 'HTTP_SMUNIVERSALID'; 37 if (isset($_SERVER[$IDEnvVar])) { 38 $SEA = $_SERVER[$IDEnvVar]; 39 return $SEA; 40 } 41 return(-1); 42} // siteminder_check() 43 44/** 45 * \brief Check if the external HTTP authentication is enabled. 46 * The mapping variables should be configured in fossology.conf 47 * Usernames are forced lowercase. 48 * \return false if not enabled 49 */ 50function auth_external_check() 51{ 52 $EXT_AUTH_ENABLE = false; 53 if (array_key_exists('EXT_AUTH', $GLOBALS['SysConf'])) { 54 if (array_key_exists('CONF_EXT_AUTH_ENABLE', $GLOBALS['SysConf']['EXT_AUTH'])) { 55 $EXT_AUTH_ENABLE = $GLOBALS['SysConf']['EXT_AUTH']['CONF_EXT_AUTH_ENABLE']; 56 } 57 } 58 if ($EXT_AUTH_ENABLE) { 59 $EXT_AUTH_USER_KW = $GLOBALS['SysConf']['EXT_AUTH']['CONF_EXT_AUTH_ENV_USER']; 60 $EXT_AUTH_USER = $GLOBALS['_SERVER']["{$EXT_AUTH_USER_KW}"]; 61 if (isset($EXT_AUTH_USER) && !empty($EXT_AUTH_USER)) { 62 if ($GLOBALS['SysConf']['EXT_AUTH']['CONF_EXT_AUTH_LOWERCASE_USER']) { 63 $EXT_AUTH_USER = strtolower($EXT_AUTH_USER); 64 } 65 $out['useAuthExternal'] = true; 66 $out['loginAuthExternal'] = $EXT_AUTH_USER; 67 $out['passwordAuthExternal'] = sha1($EXT_AUTH_USER); 68 $EXT_AUTH_MAIL_KW = $GLOBALS['SysConf']['EXT_AUTH']['CONF_EXT_AUTH_ENV_MAIL']; 69 $out['emailAuthExternal'] = $GLOBALS['_SERVER']["{$EXT_AUTH_MAIL_KW}"]; 70 $EXT_AUTH_DESC_KW = $GLOBALS['SysConf']['EXT_AUTH']['CONF_EXT_AUTH_ENV_DESC']; 71 $out['descriptionAuthExternal'] = $GLOBALS['_SERVER']["{$EXT_AUTH_DESC_KW}"]; 72 return $out; 73 } 74 } 75 return $out['useAuthExternal'] = false; 76} 77 78/** 79 * \brief check if this account is correct 80 * 81 * \param string &$user User name, reference variable 82 * \param string &$passwd Password, reference variable 83 * \param string &$group Group, reference variable (optional) 84 * 85 * \return User id on success, exit(1) on failure. 86 */ 87function account_check(&$user, &$passwd, &$group = "") 88{ 89 global $SysConf; 90 $dbManager = $GLOBALS['container']->get('db.manager'); 91 /* get username/passwd from ~/.fossology.rc */ 92 $user_passwd_file = getenv("HOME") . "/.fossology.rc"; 93 if (empty($user) && empty($passwd) && file_exists($user_passwd_file)) { 94 $user_passwd_array = parse_ini_file($user_passwd_file, true, INI_SCANNER_RAW); 95 96 /* get username and password from conf file */ 97 if (! empty($user_passwd_array) && ! empty($user_passwd_array['user'])) { 98 $user = $user_passwd_array['user']; 99 } 100 if (! empty($user_passwd_array) && ! empty($user_passwd_array['username'])) { 101 $user = $user_passwd_array['username']; 102 } 103 if (! empty($user_passwd_array) && ! empty($user_passwd_array['groupname'])) { 104 $group = $user_passwd_array['groupname']; 105 } 106 if (! empty($user_passwd_array) && ! empty($user_passwd_array['password'])) { 107 $passwd = $user_passwd_array['password']; 108 } 109 } 110 /* check if the user name/passwd is valid */ 111 if (empty($user)) { 112 /* 113 * $uid_arr = posix_getpwuid(posix_getuid()); 114 * $user = $uid_arr['name']; 115 */ 116 echo "FATAL: You should add '--username USERNAME' when running OR add " . 117 "'username=USERNAME' in ~/.fossology.rc before running.\n"; 118 exit(1); 119 } 120 if (empty($passwd)) { 121 echo "The user is: $user, please enter the password:\n"; 122 system('stty -echo'); 123 $passwd = trim(fgets(STDIN)); 124 system('stty echo'); 125 if (empty($passwd)) { 126 echo "You entered an empty password.\n"; 127 } 128 } 129 130 if (! empty($user)) { 131 $userDao = $GLOBALS['container']->get('dao.user'); 132 try { 133 $row = $userDao->getUserAndDefaultGroupByUserName($user); 134 } catch (Exception $e) { 135 echo $e->getMessage(), "\n"; 136 exit(1); 137 } 138 $userId = $row['user_pk']; 139 $SysConf['auth']['UserId'] = $userId; 140 141 if (empty($group)) { 142 $group = $row['group_name']; 143 $groupId = $row['group_fk']; 144 } else { 145 $rowGroup = $dbManager->getSingleRow( 146 "SELECT group_pk 147 FROM group_user_member INNER JOIN groups ON groups.group_pk = group_user_member.group_fk 148 WHERE user_fk = $1 AND group_name = $2", array($userId, $group), 149 __METHOD__ . ".lookUpGroup"); 150 if (false === $rowGroup) { 151 echo "User is not in group.\n"; 152 exit(1); 153 } 154 $groupId = $rowGroup['group_pk']; 155 } 156 $SysConf['auth']['GroupId'] = $groupId; 157 if (empty($groupId)) { 158 echo "Group '$group' not found.\n"; 159 exit(1); 160 } 161 162 if (! empty($row['user_pass'])) { 163 $options = array('cost' => 10); 164 if (password_verify($passwd, $row['user_pass'])) { 165 if (password_needs_rehash($row['user_pass'], PASSWORD_DEFAULT, $options)) { 166 $newHash = password_hash($passwd, PASSWORD_DEFAULT, $options); 167 /* Update old hash with new hash */ 168 update_password_hash($user, $newHash); 169 } 170 return true; 171 } else if (! empty($row['user_seed'])) { 172 $passwd_hash = sha1($row['user_seed'] . $passwd); 173 /* If verify with new hash fails check with the old hash */ 174 if (strcmp($passwd_hash, $row['user_pass']) == 0) { 175 $newHash = password_hash($passwd, PASSWORD_DEFAULT, $options); 176 /* Update old hash with new hash */ 177 update_password_hash($user, $newHash); 178 return true; 179 } else { 180 echo "User name or password is invalid.\n"; 181 exit(1); 182 } 183 } 184 } 185 } 186 return $userId; 187} 188 189/** 190 * \brief Check if the user has the permission to read the 191 * copyright/license/etc information of this upload 192 * 193 * \param int $upload Upload id 194 * \param string $user User name 195 * 196 * \return 1: has the permission; 0: no permission 197 */ 198function read_permission($upload, $user) 199{ 200 $ADMIN_PERMISSION = 10; 201 $dbManager = $GLOBALS['container']->get('db.manager'); 202 203 /* check if the user if the owner of this upload */ 204 $row = $dbManager->getSingleRow( 205 "SELECT 1 206 FROM upload INNER JOIN users ON users.user_pk = upload.user_fk 207 WHERE users.user_name = $1 AND upload.upload_pk = $2", 208 array($user, $upload), 209 __METHOD__.".checkUpload" 210 ); 211 212 if (! empty($row)) { 213 /* user has permission */ 214 return 1; 215 } 216 217 /* check if the user is administrator */ 218 $row = $dbManager->getSingleRow( 219 "SELECT 1 220 FROM users 221 WHERE user_name = $1 AND user_perm = $2", 222 array($user, $ADMIN_PERMISSION), 223 __METHOD__.".checkPerm" 224 ); 225 226 if (! empty($row)) { 227 /* user has permission */ 228 return 1; 229 } 230 231 /* user does not have permission */ 232 return 0; 233} 234 235/** 236 * Check if the password policy has been enabled 237 * @return boolean 238 */ 239function passwordPolicyEnabled() 240{ 241 $sysconfig = $GLOBALS['SysConf']['SYSCONFIG']; 242 if (! array_key_exists('PasswdPolicy', $sysconfig) || 243 $sysconfig['PasswdPolicy'] == 'false') { 244 return false; 245 } 246 return true; 247} 248 249/** 250 * Generate the password policy regex from sysconfig 251 * @return string Regex based on policy selected 252 */ 253function generate_password_policy() 254{ 255 $sysconfig = $GLOBALS['SysConf']['SYSCONFIG']; 256 if (! passwordPolicyEnabled()) { 257 return ".*"; 258 } 259 $limit = "*"; 260 $min = trim($sysconfig['PasswdPolicyMinChar']); 261 $max = trim($sysconfig['PasswdPolicyMaxChar']); 262 if (!empty($min) || !empty($max)) { 263 if (empty($min)) { 264 $min = 0; 265 } 266 $min = intval($min) < 0 ? 0 : $min; 267 $max = intval($max) < 0 ? 0 : $max; 268 $limit = '{' . $min . ",$max}"; 269 } 270 $lookAhead = ""; 271 $charset = "a-zA-Z\\d"; 272 if ($sysconfig['PasswdPolicyLower'] == 'true') { 273 $lookAhead .= '(?=.*[a-z])'; 274 } 275 if ($sysconfig['PasswdPolicyUpper'] == 'true') { 276 $lookAhead .= '(?=.*[A-Z])'; 277 } 278 if ($sysconfig['PasswdPolicyDigit'] == 'true') { 279 $lookAhead .= '(?=.*\\d)'; 280 } 281 $special = trim($sysconfig['PasswdPolicySpecial']); 282 if (!empty($special)) { 283 $lookAhead .= "(?=.*[$special])"; 284 $charset .= $special; 285 $charset = '[' . $charset . ']'; 286 } else { 287 $charset = '.'; // Allow any special character 288 } 289 return $lookAhead . $charset . $limit; 290} 291 292/** 293 * Translate selected password policy into user understandable string 294 * @return string 295 */ 296function generate_password_policy_string() 297{ 298 $sysconfig = $GLOBALS['SysConf']['SYSCONFIG']; 299 if (! passwordPolicyEnabled()) { 300 return "No policy defined."; 301 } 302 $limit = "Any length."; 303 $min = trim($sysconfig['PasswdPolicyMinChar']); 304 $max = trim($sysconfig['PasswdPolicyMaxChar']); 305 if (!empty($min) || !empty($max)) { 306 if (empty($min)) { 307 $min = 0; 308 } 309 $limit = "Minimum $min"; 310 if (!empty($max)) { 311 $limit .= ", maximum $max"; 312 } 313 $limit .= " characters."; 314 } 315 $others = []; 316 if ($sysconfig['PasswdPolicyLower'] == 'true') { 317 $others[] = "lower case"; 318 } 319 if ($sysconfig['PasswdPolicyUpper'] == 'true') { 320 $others[] = "upper case"; 321 } 322 if ($sysconfig['PasswdPolicyDigit'] == 'true') { 323 $others[] = "digit"; 324 } 325 if (!empty($others)) { 326 $others = "At least one " . join(", ", $others); 327 } else { 328 $others = ""; 329 } 330 $special = trim($sysconfig['PasswdPolicySpecial']); 331 if (!empty($special)) { 332 if (!empty($others)) { 333 $others .= " and"; 334 } 335 $others .= " one of <em>$special</em>"; 336 } 337 return "$limit $others."; 338} 339