6 * The rest Copyright 2002-2005 (c) GForge Team
11 * This file is part of GForge.
13 * GForge is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * GForge is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with GForge; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 This file creates user / group permissions by editing
30 the /etc/passwd /etc/shadow and /etc/group files
32 require_once('squal_pre.php');
33 require ('common/include/cron_utils.php');
36 // Default values for the script
38 define('DEFAULT_SHELL','/bin/cvssh.pl'); //use /bin/grap for cvs-only
39 define('FILE_EXTENSION','.new'); // use .new when testing
41 if (util_is_root_dir($groupdir_prefix)) {
42 $err .= "Error! groupdir_prefix Points To Root Directory!";
49 // Get the users' unix_name and password out of the database
50 // ONLY USERS WITH CVS READ AND COMMIT PRIVS ARE ADDED
52 $res = db_query("SELECT distinct users.user_name,users.unix_pw,users.unix_uid,users.unix_gid,users.user_id
53 FROM users,user_group,groups
54 WHERE users.user_id=user_group.user_id
55 AND user_group.group_id=groups.group_id
57 AND user_group.cvs_flags IN ('0','1')
59 ORDER BY users.user_id ASC");
62 $gforge_users =& util_result_column_to_array($res,'user_name');
63 $user_unix_uids =& util_result_column_to_array($res,'unix_uid');
64 $user_unix_gids =& util_result_column_to_array($res,'unix_gid');
65 $user_pws =& util_result_column_to_array($res,'unix_pw');
67 // Create the entries for the GForge users
68 $gforge_lines = array();
70 // user description is something like "MyGForge user"
71 $user_description = preg_replace('/[^[:alnum:] _-]/', '', $sys_name);
72 $user_description .= " user";
74 for ($i=0; $i < count($gforge_users); $i++) {
75 $username = $gforge_users[$i];
76 $user_unix_uid = $user_unix_uids[$i];
77 $user_unix_gid = $user_unix_gids[$i];
78 $shell = DEFAULT_SHELL;
79 $unix_passwd = $user_pws[$i];
81 $line_passwd = $username.":x:".$user_unix_uid.":".$user_unix_gid.":".
82 $user_description.":/home/".$username.":".$shell;
83 $line_shadow = $username.":".$unix_passwd.":12090:0:99999:7:::";
85 $gforge_lines_passwd[] = $line_passwd;
86 $gforge_lines_shadow[] = $line_shadow;
90 /*************************************************************************
91 * Step 1: Process /etc/passwd
92 *************************************************************************/
94 // Read the passwd file line by line
95 $passwd_orig = file("/etc/passwd", "r");
97 // Now write the file with the gforge users at the end
98 $passwd = fopen("/etc/passwd".FILE_EXTENSION, "w");
99 $unmanaged_etc = array();
100 for ($i=0; $i < count($passwd_orig); $i++) {
101 $line = trim($passwd_orig[$i]);
102 // Skip the GForge users (will be written later)
103 if (preg_match("/^[[:blank:]]*#GFORGEBEGIN/", $line)) {
106 $line = trim($passwd_orig[$i]);
107 } while ($i < count($passwd_orig) && !preg_match("/^[[:blank:]]*#GFORGEEND/", $line));
109 // Got to end of file (shouldn't happen, means #GFORGEEND wasn't found on file
110 if ($i >= (count($passwd_orig)-1)) break;
114 $line = trim($passwd_orig[$i]);
117 $entries = explode(":", $line);
118 if (!empty($entries[0])) {
119 $username = $entries[0];
120 $unmanaged_etc[] = $username;
121 fwrite($passwd, $line."\n");
123 // blank line or comment
124 fwrite($passwd, $line."\n");
128 /*************************************************************************
129 * Step 2: Process /etc/shadow
130 *************************************************************************/
132 // Read the shadow file line by line
133 $passwd_orig = file("/etc/shadow", "r");
135 // Now write the file with the gforge users at the end
136 $shadow = fopen("/etc/shadow".FILE_EXTENSION, "w");
137 $unmanaged_shadow = array();
138 for ($i=0; $i < count($passwd_orig); $i++) {
139 $line = trim($passwd_orig[$i]);
140 // Skip the GForge users (will be written later)
141 if (preg_match("/^[[:blank:]]*#GFORGEBEGIN/", $line)) {
144 $line = trim($passwd_orig[$i]);
145 } while ($i < count($passwd_orig) && !preg_match("/^[[:blank:]]*#GFORGEEND/", $line));
147 // Got to end of file (shouldn't happen, means #GFORGEEND wasn't found on file
148 if ($i >= (count($passwd_orig)-1)) break;
152 $line = trim($passwd_orig[$i]);
155 $entries = explode(":", $line);
156 if (!empty($entries[0])) {
157 $username = $entries[0];
158 $unmanaged_shadow[] = $username;
159 fwrite($shadow, $line."\n");
161 // blank line or comment
162 fwrite($shadow, $line."\n");
167 /*************************************************************************
168 * Step 3: Write the GForge users to /etc/passwd and /etc/shadow
169 *************************************************************************/
171 // now write the GForge users
172 fwrite($passwd, "#GFORGEBEGIN\n");
173 fwrite($shadow, "#GFORGEBEGIN\n");
174 assert(count($gforge_lines_passwd) == count($gforge_lines_shadow));
175 for ($i=0; $i < count($gforge_lines_passwd); $i++) {
176 $line_passwd = $gforge_lines_passwd[$i];
177 $line_shadow = $gforge_lines_shadow[$i];
180 $entries = explode(":", $line_passwd);
181 $username = $entries[0];
182 if (!in_array($username, $unmanaged_etc)) {
183 // Only write the user if it must be managed by gforge (that is, if it's a new
184 // user or it was found inside the #GFORGE markers).
185 fwrite($passwd, $line_passwd."\n");
188 $entries = explode(":", $line_shadow);
189 $username = $entries[0];
190 if (!in_array($username, $unmanaged_shadow)) {
191 fwrite($shadow, $line_shadow."\n");
194 fwrite($passwd, "#GFORGEEND\n");
195 fwrite($shadow, "#GFORGEEND\n");
201 /*************************************************************************
202 * Step 4: Parse /etc/group
203 *************************************************************************/
204 $group_orig = file("/etc/group");
205 $group = fopen("/etc/group".FILE_EXTENSION, "w");
207 // Add the groups from the gforge database
208 $group_res = db_query("SELECT group_id, unix_group_name, (is_public=1 AND enable_anonscm=1 AND type_id=1) AS enable_pserver FROM groups WHERE status='A' AND type_id='1'");
211 $gforge_groups = array();
212 for($i = 0; $i < db_numrows($group_res); $i++) {
213 $gforge_groups[] = db_result($group_res,$i,'unix_group_name');
214 $gids[db_result($group_res,$i,'unix_group_name')] = db_result($group_res,$i,'group_id') + 50000; // 50000: hardcoded value (for now).
217 for ($i=0; $i < count($group_orig); $i++) {
218 $line = trim($group_orig[$i]);
219 // Skip the GForge groups (will be written later)
220 if (preg_match("/^[[:blank:]]*#GFORGEBEGIN/", $line)) {
223 $line = trim($passwd_orig[$i]);
224 } while ($i < count($passwd_orig) && !preg_match("/^[[:blank:]]*#GFORGEEND/", $line));
226 // Got to end of file (shouldn't happen, means #GFORGEEND wasn't found on file
227 if ($i >= (count($passwd_orig)-1)) break;
231 $line = trim($passwd_orig[$i]);
234 $entries = explode(":", $line);
235 if (!empty($entries[0])) {
236 $groupname = $entries[0];
237 if (!in_array($groupname, $gforge_groups)) {
238 // write the user only if it's not a gforge user
239 fwrite($group, $line."\n");
242 // blank line or comment
243 fwrite($group, $line."\n");
247 // Now write the GForge groups
248 // Note that we FORCE the GForge groups to be managed by GForge. This is different than the
249 // users, where the administrator could move a user outside the #GFORGE markers and manually
250 // manage the user. This is done because we must add the users to the group, and for this we
252 fwrite($group, "#GFORGEBEGIN\n");
254 for ($i = 0; $i < count($gforge_groups); $i++) {
255 $group_name = $gforge_groups[$i];
256 $unix_gid = $gids[$group_name];
258 $line = $group_name.":x:".$unix_gid.":";
260 /* we need to get the project object to check if a project
261 * has a private CVS repository - in which case we need to add
262 * the apache user to the group so that ViewCVS can be used
265 $group_id = db_result($group_res, $i, 'group_id');
266 $project = &group_get_object($group_id);
267 $enable_pserver = (db_result($group_res, $i, 'enable_pserver') == 't');
269 $resusers = db_query("SELECT user_name
270 FROM users,user_group,groups
271 WHERE groups.group_id=user_group.group_id
272 AND users.user_id=user_group.user_id
273 AND user_group.cvs_flags IN ('0','1')
275 AND groups.unix_group_name='".$group_name."'");
276 $gmembers = util_result_column_to_array($resusers,'user_name');
277 if ($enable_pserver) $gmembers[] = 'anonymous';
278 if (!$project->enableAnonSCM()) {
279 $gmembers[] = $sys_apache_user;
282 $line .= implode(',', $gmembers);
284 fwrite($group, $line."\n");
288 fwrite($group, "#GFORGEEND\n");