3 * FusionForge account functions
5 * Copyright 1999-2001, VA Linux Systems, Inc.
6 * Copyright 2010, Franck Villaume - Capgemini
7 * Copyright 2012, Franck Villaume - TrivialDev
9 * This file is part of FusionForge. FusionForge is free software;
10 * you can redistribute it and/or modify it under the terms of the
11 * GNU General Public License as published by the Free Software
12 * Foundation; either version 2 of the Licence, or (at your option)
15 * FusionForge is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with FusionForge; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * account_pwvalid() - Validates a password
28 * @param string The plaintext password string
29 * @returns true on success/false on failure
32 function account_pwvalid($pw) {
33 if (strlen($pw) < 6) {
34 $GLOBALS['register_error'] = _('Password must be at least 6 characters.');
41 * account_namevalid() - Validates a login username
43 * @param string The username string
44 * @param bool Check for an unix username
45 * @returns true on success/false on failure
48 function account_namevalid($name, $unix=0) {
51 // If accounts comes from ldap and no shell access, then disable controls.
52 $pluginManager = plugin_manager_get_object();
53 if (!forge_get_config('use_shell') && $pluginManager->PluginIsInstalled('authldap')) {
59 if (strrpos($name,' ') > 0) {
60 $GLOBALS['register_error'] = _('There cannot be any spaces in the login name.');
65 if (strlen($name) < 3) {
66 $GLOBALS['register_error'] = _('Name is too short. It must be at least 3 characters.');
69 if (strlen($name) > 15) {
70 $GLOBALS['register_error'] = _('Name is too long. It must be less than 15 characters.');
74 if (!preg_match('/^[a-z0-9][-a-z0-9_\.]+$/', $name)) {
75 $GLOBALS['register_error'] = _('Illegal character in name.');
80 $regExpReservedNames = "^(root|bin|daemon|adm|lp|sync|shutdown|halt|mail|news|"
81 . "uucp|operator|games|mysql|httpd|nobody|dummy|www|cvs|shell|ftp|irc|"
82 . "debian|ns|download)$";
83 if( preg_match("/$regExpReservedNames/i", $name) ) {
84 $GLOBALS['register_error'] = _('Name is reserved.');
87 if (forge_get_config('use_shell')) {
88 if ( exec("getent passwd $name") != "" ){
89 $GLOBALS['register_error'] = _('That username already exists.');
92 if ( exec("getent group $name") != "" ){
93 $GLOBALS['register_error'] = _('That username already exists.');
97 if (preg_match("/^(anoncvs_)/i",$name)) {
98 $GLOBALS['register_error'] = _('Name is reserved for CVS.');
106 * account_groupnamevalid() - Validates an account group name
108 * @param string The group name string
109 * @returns true on success/false on failure
112 function account_groupnamevalid($name) {
113 if (!account_namevalid($name, 1)) return 0;
116 $regExpReservedGroupNames = "^(www[0-9]?|cvs[0-9]?|shell[0-9]?|ftp[0-9]?|"
117 . "irc[0-9]?|news[0-9]?|mail[0-9]?|ns[0-9]?|download[0-9]?|pub|users|"
118 . "compile|lists|slayer|orbital|tokyojoe|webdev|projects|cvs|monitor|"
120 if(preg_match("/$regExpReservedGroupNames/i",$name)) {
121 $GLOBALS['register_error'] = _('Name is reserved for DNS purposes.');
125 if(preg_match("/_/",$name)) {
126 $GLOBALS['register_error'] = _('Group name cannot contain underscore for DNS reasons.');
134 * genchr() - Generate a random character
136 * This is a local function used for account_salt()
138 * @return int $num A random character
143 $num = util_randnum(46, 122);
144 } while ( ( $num > 57 && $num < 65 ) || ( $num > 90 && $num < 97 ) );
150 * account_gensalt() - A random salt generator
152 * @returns The random salt string
155 function account_gensalt(){
157 // ncommander: modified for cipher selection
158 // crypt() selects the cipher based on
163 switch(forge_get_config('unix_cipher')) {
169 $salt = "$1$" . "$a$b";
174 $salt .= rand(64,126);
184 * account_genunixpw() - Generate unix password
186 * @param string The plaintext password string
187 * @return string The encrypted password
190 function account_genunixpw($plainpw) {
191 // ncommander: Support clear password hashing
192 // for usergroup_plain.php
194 if (strcasecmp(forge_get_config('unix_cipher'), 'Plain') == 0) {
197 return crypt($plainpw,account_gensalt());
202 * account_get_user_default_shell() - return default user shell
205 function account_get_user_default_shell() {
206 $user_default_shell = forge_get_config('user_default_shell');
207 if (! isset($user_default_shell)) {
208 // same as in DB schema before that config var was introduced
209 $user_default_shell = '/bin/bash';
211 return $user_default_shell;
215 * account_getavailableshells() - return available shells for the users
218 function account_getavailableshells($add_user_default_shell = TRUE) {
219 // we'd better use the shells defined inside the 'chroot' in /var/lib/gforge/chroot/etc/shells it it exists
220 $chroot = forge_get_config('chroot');
221 $shells_file = $chroot.'/etc/shells';
222 if(! file_exists($shells_file) ) {
223 // otherwise, fallback to /etc/shells
224 $shells_file = '/etc/shells';
226 $shells = file($shells_file);
228 $out_shells = array();
229 foreach ($shells as $s) {
230 if (substr($s, 0, 1) == '#') {
233 $out_shells[] = chop($s);
235 // in most cases, we do need to add the default shell in case it wouldn't be in the ../etc/shells already (no regression)
236 if ($add_user_default_shell) {
237 $user_default_shell = account_get_user_default_shell();
238 if (! file_exists($user_default_shell) ) {
239 // we'll always add cvssh if no other defaukt set ... TODO: explain why ?
240 $user_default_shell = "/bin/cvssh";
242 if (!in_array($user_default_shell, $out_shells)) {
243 $out_shells[count($out_shells)] = $user_default_shell;
250 * account_shellselects() - Print out shell selects
252 * @param string The current shell
255 function account_shellselects($current) {
258 $shells = account_getavailableshells();
261 for ($i = 0; $i < count($shells); $i++) {
262 $this_shell = $shells[$i];
264 if ($current == $this_shell) {
266 $html .= "<option selected=\"selected\" value=\"$this_shell\">$this_shell</option>\n";
268 // the last one is supposed to be the default, so select it if not found current shell to observe default settings
269 if ( ($i == (count($shells) - 1)) && (! $found)) {
270 $html .= "<option selected=\"selected\" value=\"$this_shell\">$this_shell</option>\n";
272 $html .= "<option value=\"$this_shell\">$this_shell</option>\n";
277 // add the current option but unselectable -> defaults to cvssh if no other option in /var/lib/gforge/chroot/etc/shells
278 $html .= "<option value=\"$current\" disabled=\"disabled\">$current</option>\n";
284 * account_user_homedir() - Returns full path of user home directory
286 * @param string The username
287 * @return string home directory path
289 function account_user_homedir($user) {
290 //return '/home/users/'.substr($user,0,1).'/'.substr($user,0,2).'/'.$user;
291 return forge_get_config('homedir_prefix').'/'.$user;
295 * account_group_homedir() - Returns full path of group home directory
297 * @param string The group name
298 * @return string home directory path
300 function account_group_homedir($group) {
301 //return '/home/groups/'.substr($group,0,1).'/'.substr($group,0,2).'/'.$group;
302 return forge_get_config('groupdir_prefix').'/'.$group;
306 * checkKeys() - Simple function that tries to check the validity of public ssh keys with a regexp.
307 * Exits with an error message if an invalid key is found.
309 * @param string $keys A string with a set of keys to check. Each key is delimited by a carriage return.
311 function checkKeys($keys) {
312 $key = strtok($keys, "\n");
313 while ($key !== false) {
315 if ((strlen($key) > 0) && ($key[0] != '#')) {
316 /* The encoded key is made of 0-9, A-Z ,a-z, +, / (base 64) characters,
317 ends with zero or up to three '=' and the length must be >= 512 bits (157 base64 characters).
318 The whole key ends with an optional comment. */
319 if ( preg_match("@^(((no-port-forwarding|no-X11-forwarding|no-agent-forwarding|no-pty|command=\"[^\"]+\"|from=\"?[A-Za-z0-9\.-]+\"?),?)*\s+)?ssh-(rsa|dss)\s+[A-Za-z0-9+/]{157,}={0,2}(\s+.*)?$@", $key) === 0 ) { // Warning: we must use === for the test
320 $msg = sprintf(_('The following key has a wrong format: |%s|. Please, correct it by going back to the previous page.'),
321 htmlspecialchars($key));
322 session_redirect('/account/?&error_msg='.urlencode($msg));
331 // c-file-style: "bsd"