[Fusionforge-commits] FusionForge branch Branch_5_0 updated. 0cc51b3aca51fa915a35195fdf729bcdb903f2af

Roland Mas lolando at fusionforge.org
Sun Feb 24 10:38:20 CET 2013


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "FusionForge".

The branch, Branch_5_0 has been updated
       via  0cc51b3aca51fa915a35195fdf729bcdb903f2af (commit)
      from  0ea7ec4327cc40dded6926c0f0c85349da786c00 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 0cc51b3aca51fa915a35195fdf729bcdb903f2af
Author: Roland Mas <lolando at debian.org>
Date:   Sun Feb 24 10:35:13 2013 +0100

    SECURITY: Avoid attacks with symbolic or hard links that could lead to
    privilege escalation (CVE-2013-1423).  Thanks to Helmut Grohne for the
    initial report and help in preparing the fix.

diff --git a/gforge/common/include/utils.php b/gforge/common/include/utils.php
index efbb840..5f6ac80 100644
--- a/gforge/common/include/utils.php
+++ b/gforge/common/include/utils.php
@@ -860,6 +860,72 @@ function valid_hostname ($hostname = "xyz") {
 
 }
 
+/**
+ * util_create_file_with_contents() — Securely create (or replace) a file with given contents
+ *
+ * @param	string	$path		Path of the file to be created
+ * @param	string	$contents	Contents of the file
+ *
+ * @return	boolean	FALSE on error
+ */
+function util_create_file_with_contents($path, $contents) {
+	if (file_exists($path) && !unlink($path)) {
+		return false;
+	}
+	$handle = fopen($path, "x+");
+	if ($handle == false) {
+		return false;
+	}
+	fwrite($handle, $contents);
+	fclose($handle);
+}
+
+/**
+ * Create a directory in the system temp directory with a hard-to-predict name.
+ * Does not have the guarantees of the actual BSD libc function or Python tempfile function.
+ * @param string $suffix Append to the new directory's name
+ * @param string $prefix Prepend to the new directory's name
+ * @return string The path of the new directory.
+ *
+ * Mostly taken from https://gist.github.com/1407245 as a "temporary"
+ * workaround to https://bugs.php.net/bug.php?id=49211
+ */
+function util_mkdtemp($suffix = '', $prefix = 'tmp') {
+	$tempdir = sys_get_temp_dir();
+	for ($i=0; $i<5; $i++) {
+		$id = strtr(base64_encode(openssl_random_pseudo_bytes(6)), '+/', '-_');
+		$path = "{$tempdir}/{$prefix}{$id}{$suffix}";
+		if (mkdir($path, 0700)) {
+			return $path;
+		}
+	}
+	return false;
+}
+
+/**
+ * Run a function with only the permissions of a given Unix user
+ * Function can be an anonymous
+ * Optional arguments in an array
+ * @param	string	Unix user name
+ * @param	function	function to run (possibly anonymous)
+ * @param	array	parameters
+ * @return	boolean	true on success, false on error
+ */
+function util_sudo_effective_user($username, $function, $params=array()) {
+	$saved_egid = posix_getegid();
+	$saved_euid = posix_geteuid();
+
+	$userinfo = posix_getpwnam($username);
+	if ($userinfo === False) {
+		return False;
+	}
+	if (posix_setegid($userinfo['gid']) && posix_seteuid($userinfo['uid'])) {
+		$function($params);
+	}
+
+	posix_setegid($saved_egid);
+	posix_seteuid($saved_euid);
+}
 
 /**
  * human_readable_bytes() - Translates an integer representing bytes to a human-readable format.
diff --git a/gforge/contrib/gforge-3.0-cronjobs.patch b/gforge/contrib/gforge-3.0-cronjobs.patch
deleted file mode 100644
index 8fc62e4..0000000
--- a/gforge/contrib/gforge-3.0-cronjobs.patch
+++ /dev/null
@@ -1,291 +0,0 @@
-diff -Nur -x '*.orig' -x '*.rej' gforge-3.0pre9/utils/create-cvs-repository.sh mezzanine_patched_gforge-3.0pre9/utils/create-cvs-repository.sh
---- gforge-3.0pre9/utils/create-cvs-repository.sh	Wed Dec 31 19:00:00 1969
-+++ mezzanine_patched_gforge-3.0pre9/utils/create-cvs-repository.sh	Fri Jan 24 18:19:03 2003
-@@ -0,0 +1,70 @@
-+#!/bin/sh
-+#
-+# CVS Repository Tool
-+# (c)1999 SourceForge Development Team
-+# Released under the GPL, 1999
-+#
-+
-+CVS="cvs"
-+PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin"
-+
-+# Read config info, if any
-+for i in /etc/gforge/env /etc/sysconfig/gforge /etc/sysconfig/cvs
-+    test -f $i && . $i
-+done
-+
-+# Set the variable for our CVS tree if not set already
-+if [ "x$CVSTREETOP" = "x" ]; then
-+    CVSTREETOP=/usr/share/gforge/cvsroot
-+fi
-+
-+# if no arguments, print out help screen
-+if test $# -lt 2; then 
-+    echo "usage:"
-+    echo "  $0 [repositoryname] [groupid]"
-+    echo ""
-+    exit 1 
-+fi
-+
-+# make sure this repository doesn't already exist
-+if [ -d ${CVSTREETOP}/$1 ] ; then
-+    echo "$1 already exists."
-+    echo ""
-+    exit 1
-+fi
-+
-+# first create the repository
-+mkdir ${CVSTREETOP}/$1
-+$CVS -d${CVSTREETOP}/$1 init
-+
-+# make it group writable
-+chmod 775 ${CVSTREETOP}/$1
-+
-+# import default directory, with default cvs.txt
-+#mkdir $1
-+#cp cvs.txt $1
-+#cd $1
-+#$CVS -d${CVSTREETOP}/$1 import -m "SourceForge CVStool creation" $1 SourceForge start	
-+#rm cvs.txt
-+#cd ..
-+#rmdir $1
-+
-+# turn off pserver writers, on anonymous readers
-+echo > ${CVSTREETOP}/$1/CVSROOT/writers
-+echo "anonymous" > ${CVSTREETOP}/$1/CVSROOT/readers
-+echo "anonymous:\$1\$0H\$2/LSjjwDfsSA0gaDYY5Df/:anoncvs_$1" > ${CVSTREETOP}/$1/CVSROOT/passwd 
-+
-+# setup loginfo to make group ownership every commit
-+echo "ALL chgrp -R $1 ${CVSTREETOP}/$1" > ${CVSTREETOP}/$1/CVSROOT/loginfo
-+echo > ${CVSTREETOP}/$1/CVSROOT/val-tags
-+chmod 664 ${CVSTREETOP}/$1/CVSROOT/val-tags
-+
-+# set group ownership, anonymous group user 
-+chown -R nobody:$2 ${CVSTREETOP}/$1
-+
-+# Create/modify anoncvs account
-+if ! id -u anoncvs_$1 >/dev/null 2>&1; then
-+    useradd -g $2 -d${CVSTREETOP}/$1 -c "$1 Anonymous CVS User" -s /bin/false -M anoncvs_$1
-+else
-+    usermod -g $2 -d${CVSTREETOP}/$1 -c "$1 Anonymous CVS User" -s /bin/false anoncvs_$1
-+fi
-diff -Nur -x '*.orig' -x '*.rej' gforge-3.0pre9/utils/create-cvs-tarballs.sh mezzanine_patched_gforge-3.0pre9/utils/create-cvs-tarballs.sh
---- gforge-3.0pre9/utils/create-cvs-tarballs.sh	Wed Dec 31 19:00:00 1969
-+++ mezzanine_patched_gforge-3.0pre9/utils/create-cvs-tarballs.sh	Fri Jan 24 18:15:00 2003
-@@ -0,0 +1,42 @@
-+#!/bin/sh
-+#
-+# Create tarballs of individual CVS repositories nightly
-+#
-+# 24 January 2003
-+# Michael Jennings
-+#
-+
-+CVS="cvs"
-+PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin"
-+TAR="tar"
-+#TAR="gtar"
-+GZIP="gzip"
-+#GZIP="gzip -9"
-+
-+# Read config info, if any
-+for i in /etc/gforge/env /etc/sysconfig/gforge /etc/sysconfig/cvs
-+    test -f $i && . $i
-+done
-+
-+# Set the variable for our CVS tree if not set already
-+if [ "x$CVSTREETOP" = "x" ]; then
-+    CVSTREETOP=/usr/share/gforge/cvsroot
-+fi
-+
-+# Set the variable for where to put our tarballs if not set already
-+if [ "x$CVSTARBALLS" = "x" ]; then
-+    CVSTARBALLS=/usr/share/gforge/www/cvstarballs
-+fi
-+
-+# Make sure the place we want to put these things exists.
-+if [ ! -d $CVSTARBALLS ]; then
-+    mkdir $CVSTARBALLS
-+    chmod 755 $CVSTARBALLS
-+fi
-+
-+# Create the tarballs
-+cd $CVSTREETOP
-+for i in ???* ; do
-+    test -d $i/CVSROOT || continue
-+    $TAR -cf - $i/ | $GZIP -c > $CVSTARBALLS/$i-cvsroot.tar.gz
-+done
-diff -Nur -x '*.orig' -x '*.rej' gforge-3.0pre9/utils/cvs.txt mezzanine_patched_gforge-3.0pre9/utils/cvs.txt
---- gforge-3.0pre9/utils/cvs.txt	Wed Jan 15 19:16:46 2003
-+++ mezzanine_patched_gforge-3.0pre9/utils/cvs.txt	Wed Dec 31 19:00:00 1969
-@@ -1 +0,0 @@
--Welcome to your SourceForge CVS Repository.
-diff -Nur -x '*.orig' -x '*.rej' gforge-3.0pre9/utils/cvs1/cvscreate.sh mezzanine_patched_gforge-3.0pre9/utils/cvs1/cvscreate.sh
---- gforge-3.0pre9/utils/cvs1/cvscreate.sh	Wed Jan 15 19:16:46 2003
-+++ mezzanine_patched_gforge-3.0pre9/utils/cvs1/cvscreate.sh	Wed Dec 31 19:00:00 1969
-@@ -1,55 +0,0 @@
--#!/bin/sh
--echo ""
--echo "CVS Repository Tool"
--echo "(c)1999 SourceForge Development Team"
--echo "Released under the GPL, 1999"
--echo ""
--
--# if no arguments, print out help screen
--if test $# -lt 2; then 
--	echo "usage:"
--	echo "  cvscreate.sh [repositoryname] [groupid]"
--	echo ""
--	exit 1 
--fi
--
--# make sure this repository doesn't already exist
--if [ -d /cvsroot/$1 ] ; then
--	echo "$1 already exists."
--	echo ""
--	exit 1
--fi
--
--# first create the repository
--mkdir /cvsroot/$1
--cvs -d/cvsroot/$1 init
--
--# make it group writable
--chmod 775 /cvsroot/$1
--
--# import default directory, with default cvs.txt
--#mkdir $1
--#cp cvs.txt $1
--#cd $1
--#cvs -d/cvsroot/$1 import -m "SourceForge CVStool creation" $1 SourceForge start	
--#rm cvs.txt
--#cd ..
--#rmdir $1
--
--# turn off pserver writers, on anonymous readers
--echo "" > /cvsroot/$1/CVSROOT/writers
--echo "anonymous" > /cvsroot/$1/CVSROOT/readers
--echo "anonymous:\$1\$0H\$2/LSjjwDfsSA0gaDYY5Df/:anoncvs_$1" > /cvsroot/$1/CVSROOT/passwd 
--
--# setup loginfo to make group ownership every commit
--echo "ALL chgrp -R $1 /cvsroot/$1" > /cvsroot/$1/CVSROOT/loginfo
--echo "" > /cvsroot/$1/CVSROOT/val-tags
--chmod 664 /cvsroot/$1/CVSROOT/val-tags
--
--# set group ownership, anonymous group user 
--chown -R nobody:$2 /cvsroot/$1
--cat /etc/passwd | grep -v anoncvs_$1 > newpasswd 
--cp newpasswd /etc/passwd
--rm -f newpasswd
--/usr/sbin/adduser -M -g $2 -d/cvsroot/$1 -s /bin/false -n anoncvs_$1
--
-diff -Nur -x '*.orig' -x '*.rej' gforge-3.0pre9/utils/cvs1/cvstar_genlist.pl mezzanine_patched_gforge-3.0pre9/utils/cvs1/cvstar_genlist.pl
---- gforge-3.0pre9/utils/cvs1/cvstar_genlist.pl	Wed Jan 15 19:16:46 2003
-+++ mezzanine_patched_gforge-3.0pre9/utils/cvs1/cvstar_genlist.pl	Wed Dec 31 19:00:00 1969
-@@ -1,9 +0,0 @@
--#!/usr/bin/perl
--echo ""
--echo "CVSTar List Generator"
--echo "(c)1999 VA Linux Systems"
--echo ""
--
--$rawlist = `ls /cvsroot/*`;
--
--
-diff -Nur -x '*.orig' -x '*.rej' gforge-3.0pre9/utils/cvs1/cvstar_superscript.pl mezzanine_patched_gforge-3.0pre9/utils/cvs1/cvstar_superscript.pl
---- gforge-3.0pre9/utils/cvs1/cvstar_superscript.pl	Wed Jan 15 19:16:46 2003
-+++ mezzanine_patched_gforge-3.0pre9/utils/cvs1/cvstar_superscript.pl	Wed Dec 31 19:00:00 1969
-@@ -1,12 +0,0 @@
--#!/usr/bin/perl
--echo ""
--echo "CVSTar SuperScript"
--echo "(c)1999 VA Linux Systems"
--echo ""
--
--use DBI;
--require("include.pl");
--
--&db_connect;
--
--
-diff -Nur -x '*.orig' -x '*.rej' gforge-3.0pre9/utils/gforge-hourly-cronjobs.sh mezzanine_patched_gforge-3.0pre9/utils/gforge-hourly-cronjobs.sh
---- gforge-3.0pre9/utils/gforge-hourly-cronjobs.sh	Wed Dec 31 19:00:00 1969
-+++ mezzanine_patched_gforge-3.0pre9/utils/gforge-hourly-cronjobs.sh	Fri Jan 24 16:42:02 2003
-@@ -0,0 +1,20 @@
-+#!/bin/sh
-+#
-+# Run all GForge hourly cronjobs in the proper order.
-+# (Based on original SourceForge sample crontab.)
-+#
-+# 24 January 2003
-+# Michael Jennings <mej at eterm.org>
-+#
-+
-+GFORGE_ROOT="/usr/share/gforge"
-+CRON_DIR="$GFORGE_ROOT/cronjobs"
-+PHP="/usr/bin/php"
-+RUN_AS="gforge"
-+
-+if [ "`id -n -u`" != "$RUN_AS" ]; then
-+    exec su -l $RUN_AS -s $SHELL -c "$0"
-+fi
-+
-+### Send pending mass-mailings, if any.
-+# $PHP $CRON_DIR/massmail.php
-diff -Nur -x '*.orig' -x '*.rej' gforge-3.0pre9/utils/gforge-nightly-cronjobs.sh mezzanine_patched_gforge-3.0pre9/utils/gforge-nightly-cronjobs.sh
---- gforge-3.0pre9/utils/gforge-nightly-cronjobs.sh	Wed Dec 31 19:00:00 1969
-+++ mezzanine_patched_gforge-3.0pre9/utils/gforge-nightly-cronjobs.sh	Fri Jan 24 17:04:28 2003
-@@ -0,0 +1,50 @@
-+#!/bin/sh
-+#
-+# Run all nightly GForge cronjobs in the proper order
-+# (Based on original SourceForge sample crontab.)
-+#
-+# 24 January 2003
-+# Michael Jennings <mej at eterm.org>
-+#
-+
-+GFORGE_ROOT="/usr/share/gforge"
-+CRON_DIR="$GFORGE_ROOT/cronjobs"
-+PHP="/usr/bin/php"
-+RUN_AS="gforge"
-+
-+if [ "`id -n -u`" != "$RUN_AS" ]; then
-+    exec su -l $RUN_AS -s $SHELL -c "$0"
-+fi
-+
-+### daily rotation of the activity_log
-+$PHP $CRON_DIR/rotate_activity.php
-+
-+### daily aggregating of the numbers
-+$PHP $CRON_DIR/site_stats.php
-+
-+### recalculate user popularity metric
-+$PHP $CRON_DIR/calculate_user_metric.php
-+
-+### daily project_weekly_metric recalc
-+$PHP $CRON_DIR/project_weekly_metric.php
-+
-+### daily deletion of sessions, closing jobs, etc
-+$PHP $CRON_DIR/project_cleanup.php
-+
-+### daily crunching of survey data and other associated ratings
-+$PHP $CRON_DIR/rating_stats.php
-+
-+### daily crunching of project summary data (counts)
-+$PHP $CRON_DIR/db_project_sums.php
-+
-+### daily recalculate of the sums under the trove map
-+$PHP $CRON_DIR/db_trove_maint.php
-+
-+### daily close pending artifacts
-+$PHP $CRON_DIR/check_stale_tracker_items.php
-+
-+### Stats aggregation work
-+$PHP $CRON_DIR/db_stats_agg.php
-+
-+### VACUUM should be done after ALL OTHER JOBS
-+$PHP $CRON_DIR/vacuum.php
diff --git a/gforge/cronjobs/homedirs.php b/gforge/cronjobs/homedirs.php
index ca64782..75446da 100644
--- a/gforge/cronjobs/homedirs.php
+++ b/gforge/cronjobs/homedirs.php
@@ -171,7 +171,7 @@ foreach($groups as $group) {
 		fwrite($fw,$contents);
 		fclose($fw);
 	}
-	system("chown -R $sys_apache_user:$sys_apache_group $groupdir_prefix/$group");
+	system("chown $sys_apache_user:$sys_apache_group $groupdir_prefix/$group");
 }
 
 
diff --git a/gforge/deb-specific/fileforge.pl b/gforge/deb-specific/fileforge.pl
deleted file mode 100644
index 688d1d6..0000000
--- a/gforge/deb-specific/fileforge.pl
+++ /dev/null
@@ -1,164 +0,0 @@
-#! /usr/bin/perl -Tw
-
-use strict ;
-use vars qw/ $file $dirty_file $user $dirty_user $group $dirty_group
-    $real_file $dirty_real_file $src_file $dest_dir $dest_file $retval
-    $homedir_prefix $sys_dbpasswd / ;
-use subs qw/ &fileforge &tmpfilemove &wash_string / ;
-no locale ;
-
-# Clean up our environment
-delete @ENV{qw(IFS CDPATH ENV BASH_ENV PATH)};
-
-# Check access to secret
-require ("/etc/gforge/local.pl") ;
-unless ( (defined $sys_dbpasswd)
-	 and (defined $ENV{'sys_dbpasswd'})
-	 and ($sys_dbpasswd eq $ENV{'sys_dbpasswd'}) ) {
-    die "You are not authorized to run this script" ;
-}
-
-# Initialize a constant
-$homedir_prefix = "/var/lib/gforge/chroot/home/users/" ;
-
-# Check which mode we're in
-# Normal fileforge
-if ($0 eq "/usr/share/gforge/bin/fileforge.pl") {
-    &fileforge ;
-    exit 0 ;
-}
-# Temporary moving of files (for quick release system)
-if ($0 eq "/usr/share/gforge/bin/tmpfilemove.pl") {
-    &tmpfilemove ;
-    exit 0 ;
-}
-# If we're not in one of these two modes, then fail
-print STDERR "You must call this script as one of:
-* /usr/share/gforge/bin/fileforge.pl (normal execution)
-* /usr/share/gforge/bin/tmpfilemove.pl (for QRS)" ;
-die "Unauthorized invocation '$0'" ;
-
-sub fileforge {
-    if ($#ARGV != 2) {
-	die "Usage: fileforge.pl file user group" ;
-    }
-
-    # "Parse" command-line options
-    $dirty_file = $ARGV [0] ;
-    $dirty_user = $ARGV [1] ;
-    $dirty_group = $ARGV [2] ;
-
-    # Check and untaint $user and $file here
-    $file = &wash_string ($dirty_file, "file") ;
-    $user = &wash_string ($dirty_user, "user") ;
-
-    # Compute source file name
-    $src_file = $homedir_prefix ;
-    $src_file .= $user ;
-    $src_file .= "/incoming/" ;
-    $src_file .= $file ;
-
-    # Check and untaint $group here
-    $group = &wash_string ($dirty_group, "group") ;
-
-    # Compute and test destination dir name
-    $dest_dir = "/var/lib/gforge/download/" ;
-    $dest_dir .= $group ;
-    $dest_dir .= "/" ;
-    unless ( -d $dest_dir ) {
-	mkdir $dest_dir, 0755 or die $! ;
-	chown 0, 0, $dest_dir or die $! ;
-    }
-    unless ( -d $dest_dir ) {
-	die "Destination directory '$dest_dir' does not exist" ;
-    }
-
-    chmod 0400, $src_file ;
-    chown 0, 0, $src_file ;
-    chmod 0644, $src_file ;
-    $retval = system "/bin/mv $src_file $dest_dir" ;
-    if ($retval == -1) {
-	die "Could not execute /bin/mv: $!" ;
-    }
-    if ($retval != 0) {
-	die "Error moving file" ;
-    }
-}
-
-sub tmpfilemove {
-    if ($#ARGV != 2) {
-	die "Usage: tmpfilemove.pl temp_filename real_filename user_unix_name" ;
-    }
-    $dirty_file = $ARGV [0] ;
-    $dirty_real_file = $ARGV [1] ;
-    $dirty_user = $ARGV [2] ;
-
-    # Check and untaint variables here
-    $file = &wash_string ($dirty_file, "file") ;
-    $real_file = &wash_string ($dirty_real_file, "real_file") ;
-    $user = &wash_string ($dirty_user, "user") ;
-
-    # Compute source file name
-    $src_file = "/tmp/" ;
-    $src_file .= $file ;
-
-    # Insure the source file is good
-    chmod 0400, $src_file ;
-    $retval = system "/bin/chown $user:$user $src_file" ;
-    if ($retval == -1) {
-	die "Could not execute '/bin/chmod $user:$user $src_file': $!" ;
-    }
-    if ($retval != 0) {
-	die "Error reattributing file" ;
-    }
-    chmod 0644, $src_file ;
-
-    # Compute and test destination directory name
-    $dest_dir = $homedir_prefix ;
-    $dest_dir .= $user ;
-    $dest_dir .= "/incoming/" ;
-    unless ( -d $dest_dir ) {
-	die "Destination directory '$dest_dir' does not exist" ;
-    }
-    
-    # Compute destination file name
-    $dest_file = $dest_dir . $real_file ;
-
-    $retval = system "/bin/mv $src_file $dest_file" ;
-    if ($retval == -1) {
-	die "Could not execute /bin/mv: $!" ;
-    }
-    if ($retval != 0) {
-	die "Error moving file" ;
-    }
-}
-
-sub wash_string {
-    my $string = shift ;
-    my $name = shift ;
-
-    # Empty strings are not allowed
-    if (length $string == 0) {
-	die "Forbidden empty $name '$string'" ;
-    }
-    
-    # Only allowed characters are alphanumerical . + _ -
-    if ($string =~ m,[^\w.+_-],) {
-	die "Forbidden characters in $name '$string'" ;
-    }
-
-    # No .. sequence is allowed
-    if ($string =~ m,\.\.,) {
-	die "Forbidden '..' sequence in $name 'string'" ;
-    }
-    
-    my $clean = '' ;
- 
-    if ($string =~ /^([\w.+_-]+)$/) {
-	$clean = $1 ;
-    } else {
-	die "Unexpected error while untainting $name '$string'" ;
-    }
-
-    return $clean ;
-}
diff --git a/gforge/deb-specific/group_dump_update.pl b/gforge/deb-specific/group_dump_update.pl
index a794b40..2626629 100755
--- a/gforge/deb-specific/group_dump_update.pl
+++ b/gforge/deb-specific/group_dump_update.pl
@@ -81,6 +81,61 @@ while ($ln = pop(@groupdump_array)) {
 # Begin functions
 ###############################################
 
+## Become this effective user (EUID/EGID) and perform this action.
+## 
+## This protect against symlink attacks; they are inevitable when
+## working in a directory owned by a local user.  We could naively
+## check for the presence of symlinks, but then we'd still be
+## vulnerable to a symlink race attack.
+## 
+## We'll use set_e_uid/set_e_gid for efficiency and simplicity
+## (e.g. we can get the return value directly), which is enough for
+## opening files and similar basic operations.  When calling external
+## programs, you should use fork&exec&setuid/setgid.
+## 
+# arg1: username
+# arg2: a Perl sub{}
+sub SudoEffectiveUser {
+    my $user = $_[0];
+    my $sub_unprivileged = $_[1];
+
+    my ($uid,$gid) = GetUserUidGid($user);
+    if ($uid eq "" or $gid eq "") {
+	print "Unknown user: $user";
+	return;
+    }
+
+    my $old_GID = $GID; # save additional groups
+    $! = '';
+    $EGID = "$gid $gid"; # set egid and additional groups
+    if ($! ne '') {
+	warn "Cannot setegid($gid $gid): $!";
+	return;
+    }
+    $EUID = $uid;
+    if ($! ne '') {
+	warn "Cannot seteuid($uid): $!";
+	return;
+    }
+
+    # Perform the action under this effective user:
+    my $ret = &$sub_unprivileged();
+
+    # Back to root
+    undef($EUID);     # restore euid==uid
+    $EGID = $old_GID; # restore egid==gid + additional groups
+
+    return $ret;
+}
+
+## Get system uid/gid
+sub GetUserUidGid {
+    my $user = $_[0];
+    my ($name,$passwd,$uid,$gid,
+	$quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($user);
+    return ($uid,$gid);
+}
+
 #############################
 # Group Add Function
 #############################
@@ -109,19 +164,21 @@ sub add_group {
 	
 	if ($verbose) {print("Making a Group for : $gname\n")};
 		
-	mkdir $group_dir, $default_perms ;
-	mkdir $log_dir, $default_perms ;
-	mkdir $cgi_dir, $default_perms ;
-	mkdir $ht_dir, $default_perms ;
-	system("cp $default_page $ht_dir/index.php");
-	# perl is sometime fucked to create with right permission
-	system("chmod $default_perms $group_dir");
-	system("chmod $default_perms $log_dir");
-	system("chmod $default_perms $cgi_dir");
-	system("chmod $default_perms $ht_dir");
-	system("chmod $file_default_perms $ht_dir/index.php");
-	chown $dummy_uid, $gid, ($group_dir, $log_dir, $cgi_dir, $ht_dir);
-	chown $dummy_uid, $gid, ("$ht_dir/index.php");
+	if (mkdir $group_dir, $default_perms) {
+	    chown $dummy_uid, $gid, $group_dir ;
+	    
+	    SudoEffectiveUser($dummy_uid, sub {
+		mkdir $log_dir, $default_perms ;
+		mkdir $cgi_dir, $default_perms ;
+		mkdir $ht_dir, $default_perms ;
+		system("cp $default_page $ht_dir/index.php");
+		chmod $default_perms, $group_dir;
+		chmod $default_perms, $log_dir;
+		chmod $default_perms, $cgi_dir;
+		chmod $default_perms, $ht_dir;
+		chmod $file_default_perms, "$ht_dir/index.php";
+			      });
+	}
 }
 
 #############################
@@ -146,26 +203,16 @@ sub update_group {
 
 	if ($verbose) {print("Updating Group: $gname\n")};
 		
-	system("chmod $default_perms $group_dir");
-	system("chmod $default_perms $log_dir");
-	system("chmod $default_perms $cgi_dir");
-	system("chmod $default_perms $ht_dir");
-	chown $dummy_uid, $gid, ($group_dir, $log_dir, $cgi_dir, $ht_dir);
+	chown $dummy_uid, $gid, $group_dir;
+
+	SudoEffectiveUser($dummy_uid, sub {
+	    chmod $default_perms, $group_dir;
+	    chmod $default_perms, $log_dir;
+	    chmod $default_perms, $cgi_dir;
+	    chmod $default_perms, $ht_dir;
+	    chmod $default_perms, $inc_dir;
+			  });
 	
-	my $realuid=get_file_owner_uid($group_dir);
-	if ($dummy_uid eq $realuid){
-        	system("chown $dummy_uid $group_dir");
-	} else {
-		if($verbose){print("Changing owner of $group_dir $realuid -> $dummy_uid\n")};
-        	system("chown -R $dummy_uid $group_dir");
-	}
-	my $realgid=get_file_owner_gid($group_dir);
-	if ($gid eq $realgid){
-        	system("chgrp $gid $group_dir");
-	} else {
-		if($verbose){print("Changing group of $group_dir $realgid -> $gid\n")};
-        	system("chgrp -R $gid $group_dir");
-	}
 }
 
 #############################
diff --git a/gforge/deb-specific/ssh_dump_update.pl b/gforge/deb-specific/ssh_dump_update.pl
index 1f9852e..be90dd7 100755
--- a/gforge/deb-specific/ssh_dump_update.pl
+++ b/gforge/deb-specific/ssh_dump_update.pl
@@ -104,23 +104,22 @@ while ($ln = pop(@ssh_array)) {
 	if($verbose){print ("Processing $username\n")};
 
 	if (-d "$homedir_prefix/$username"){
-		if (! -d $ssh_dir) {
-			mkdir $ssh_dir, 0755;
-                        chown $uid, $uid, $ssh_dir;
-		}
-	
-		if($verbose){print("Writing authorized_keys for $username: ")};
+		chown $uid, $uid, ("$homedir_prefix/$username");
 	
 		SudoEffectiveUser($username, sub {
+		    if (! -d $ssh_dir) {
+			mkdir $ssh_dir, 0755;
+		    }
+		    
+		    if($verbose){print("Writing authorized_keys for $username: ")};
+		    
 		    if (write_array_file("$ssh_dir/authorized_keys", @user_authorized_keys)) {
                         warn "Problem writing authorized_keys for $username\n";
                         next;
 		    }
+		    chmod 0644, "$ssh_dir/authorized_keys";
 				  });
 
-		chown $uid, $uid, ("$homedir_prefix/$username", $ssh_dir, "$ssh_dir/authorized_keys");
-		chmod 0644, "$ssh_dir/authorized_keys";
-
 		if($verbose){print ("Done\n")};
 	} else {
 		if($verbose){print ("Not yet done, waiting for home creation\n")};
@@ -155,13 +154,11 @@ while ($ln = pop(@ssh_array)) {
 	if (-d $ssh_dir) {
 	    if($verbose){print("Resetting authorized_keys for $username: ")};
 
-	    if (-l "$ssh_dir") {
-		warn("$ssh_dir is a symlink, possible symlink attack!");
-	    } else {
+	    SudoEffectiveUser($username, sub {
 		unlink("$ssh_dir/authorized_keys");
-	    }
-	    system("chown $uid:$uid $homedir_prefix/$username");
-	    system("chown $uid:$uid $ssh_dir");
+			      });
+
+	    chown $uid, $uid, "$homedir_prefix/$username";
 
 	    if($verbose){print ("Done\n")};
 	}
diff --git a/gforge/deb-specific/user_dump_update.pl b/gforge/deb-specific/user_dump_update.pl
index 420598e..adf042f 100755
--- a/gforge/deb-specific/user_dump_update.pl
+++ b/gforge/deb-specific/user_dump_update.pl
@@ -79,6 +79,61 @@ while ($ln = pop(@userdump_array)) {
 # Begin functions
 ###############################################
 
+## Become this effective user (EUID/EGID) and perform this action.
+## 
+## This protect against symlink attacks; they are inevitable when
+## working in a directory owned by a local user.  We could naively
+## check for the presence of symlinks, but then we'd still be
+## vulnerable to a symlink race attack.
+## 
+## We'll use set_e_uid/set_e_gid for efficiency and simplicity
+## (e.g. we can get the return value directly), which is enough for
+## opening files and similar basic operations.  When calling external
+## programs, you should use fork&exec&setuid/setgid.
+## 
+# arg1: username
+# arg2: a Perl sub{}
+sub SudoEffectiveUser {
+    my $user = $_[0];
+    my $sub_unprivileged = $_[1];
+
+    my ($uid,$gid) = GetUserUidGid($user);
+    if ($uid eq "" or $gid eq "") {
+	print "Unknown user: $user";
+	return;
+    }
+
+    my $old_GID = $GID; # save additional groups
+    $! = '';
+    $EGID = "$gid $gid"; # set egid and additional groups
+    if ($! ne '') {
+	warn "Cannot setegid($gid $gid): $!";
+	return;
+    }
+    $EUID = $uid;
+    if ($! ne '') {
+	warn "Cannot seteuid($uid): $!";
+	return;
+    }
+
+    # Perform the action under this effective user:
+    my $ret = &$sub_unprivileged();
+
+    # Back to root
+    undef($EUID);     # restore euid==uid
+    $EGID = $old_GID; # restore egid==gid + additional groups
+
+    return $ret;
+}
+
+## Get system uid/gid
+sub GetUserUidGid {
+    my $user = $_[0];
+    my ($name,$passwd,$uid,$gid,
+	$quota,$comment,$gcos,$dir,$shell,$expire) = getpwnam($user);
+    return ($uid,$gid);
+}
+
 #############################
 # User Add Function
 #############################
@@ -94,8 +149,9 @@ sub add_user {
 	mkdir $home_dir, 0755;
         chown $uid, $gid, $home_dir;
 	
-	mkdir $home_dir.'/incoming', 0755;
-	chown $uid, $gid, $home_dir.'/incoming' ;
+	SudoEffectiveUser($username, sub {
+	    mkdir $home_dir.'/incoming', 0755;
+			  });
 }
 
 #############################
@@ -107,27 +163,14 @@ sub update_user {
 	
 	if($verbose){print("Updating Account for: $username\n")};
 	
-        $home_dir = $homedir_prefix.'/'.$username;
-	unless (-d $home_dir.'/incoming') {
-	    mkdir $home_dir.'/incoming', 0755;
-	}
-
-	my $realuid=get_file_owner_uid($home_dir);
-	if ($uid eq $realuid){
-        	system("chown $uid $home_dir/incoming");
-		system("chmod 0755 $home_dir/incoming");
-	} else {
-		if($verbose){print("Changing owner of $home_dir $realuid -> $uid\n")};
-        	system("chown -R $uid $home_dir");
-		system("chmod 0755 $home_dir/incoming");
-	}
-	my $realgid=get_file_owner_gid($home_dir);
-	if ($gid eq $realgid){
-        	system("chgrp $gid $home_dir/incoming");
-	} else {
-		if($verbose){print("Changing group of $home_dir $realgid -> $gid\n")};
-        	system("chgrp -R $gid $home_dir");
-	}
+	SudoEffectiveUser($username, sub {
+	    $home_dir = $homedir_prefix.'/'.$username;
+	    if (-d $home_dir.'/incoming') {
+		chmod 0755, $home_dir.'/incoming';
+	    } else {
+		mkdir $home_dir.'/incoming', 0755;
+	    }
+			  });
 }
 
 #############################
diff --git a/gforge/debian/changelog b/gforge/debian/changelog
index 52209c3..0ebc010 100644
--- a/gforge/debian/changelog
+++ b/gforge/debian/changelog
@@ -1,3 +1,11 @@
+fusionforge (5.0.3-2) UNRELEASED; urgency=low
+
+  * SECURITY: Avoid attacks with symbolic or hard links that could lead to
+    privilege escalation (CVE-2013-1423).  Thanks to Helmut Grohne for the
+    initial report and help in preparing the fix.
+
+ -- Roland Mas <lolando at debian.org>  Tue, 19 Feb 2013 15:22:46 +0100
+
 fusionforge (5.0.3-1) unstable; urgency=low
 
   * New upstream bugfix release.
diff --git a/gforge/plugins/scmbzr/common/BzrPlugin.class.php b/gforge/plugins/scmbzr/common/BzrPlugin.class.php
index c3b58f0..5875991 100644
--- a/gforge/plugins/scmbzr/common/BzrPlugin.class.php
+++ b/gforge/plugins/scmbzr/common/BzrPlugin.class.php
@@ -162,16 +162,27 @@ class BzrPlugin extends SCMPlugin {
 		}
 		
 		if (!$repo_exists) {
+			$tmp_repo = util_mkdtemp('.bzr', $project_name);
+			if ($tmp_repo == false) {
+				return false;
+			}
+
+			system ("bzr init-repo --no-trees $tmp_repo >/dev/null") ;
+			system ("find $tmp_repo/.bzr -type d | xargs chmod g+s") ;
+			system ("chmod -R g+wX,o+rX-w $tmp_repo/.bzr") ;
+			system ("chgrp $unix_group $tmp_repo/.bzr") ;
+
 			system ("mkdir -p $repo") ;
-			system ("bzr init-repo --no-trees $repo >/dev/null") ;
-			system ("find $repo -type d | xargs chmod g+s") ;
+			system ("chgrp $unix_group $repo") ;
+			system ("chmod g+s $repo") ;
+			rename ("$tmp_repo/.bzr", "$repo/.bzr");
+			rmdir ($tmp_repo);
 		}
-
-		system ("chgrp -R $unix_group $repo") ;
+			
 		if ($project->enableAnonSCM()) {
-			system ("chmod -R g+wX,o+rX-w $repo") ;
+			system ("chmod o+rX-w $repo") ;
 		} else {
-			system ("chmod -R g+wX,o-rwx $repo") ;
+			system ("chmod o-rwx $repo") ;
 		}
 	}
 
diff --git a/gforge/plugins/scmcvs/common/CVSPlugin.class.php b/gforge/plugins/scmcvs/common/CVSPlugin.class.php
index 318d216..a7b37dc 100644
--- a/gforge/plugins/scmcvs/common/CVSPlugin.class.php
+++ b/gforge/plugins/scmcvs/common/CVSPlugin.class.php
@@ -208,18 +208,44 @@ class CVSPlugin extends SCMPlugin {
 		}
 		
 		if (!$repo_exists) {
-			system ("cvs -d $repo init") ;
+			if (!mkdir($repo, 0700)) {
+				return false;
+			}
+			$ret = 0;
+			system ("cvs -d $repo init", $ret) ;
+			if ($ret != 0) {
+				return false;
+			}
 			system ("mkdir -p $locks_dir") ;
+			system ("chgrp $unix_group $locks_dir") ;
+			system ("chmod 3777 $locks_dir") ;
+			
+			if ($GLOBALS['sys_use_shell']) {
+				$unix_group = 'scm_' . $project->getUnixName() ;
+				
+				util_create_file_with_contents ("$repo/CVSROOT/config", "SystemAuth=no\nLockDir=$locks_dir\nUseNewInfoFmtStrings=yes\n");
+				if ($project->enableAnonSCM()) {
+					util_create_file_with_contents ("$repo/CVSROOT/readers", "anonymous\n");
+					util_create_file_with_contents ("$repo/CVSROOT/passwd", "anonymous:\n");
+					system ("chmod -R g+wXs,o+rX-w $repo") ;
+				} else {
+					util_create_file_with_contents ("$repo/CVSROOT/readers", "\n");
+					util_create_file_with_contents ("$repo/CVSROOT/passwd", "\n");
+					system ("chmod -R g+wXs,o-rwx $repo") ;
+				}
+				system ("chgrp -R $unix_group $repo") ;
+			}
 		}
 
 		if ($GLOBALS['sys_use_shell']) {
-			$unix_group = 'scm_' . $project->getUnixName() ;
-			system ("chgrp -R $unix_group $repo $locks_dir") ;
-			system ("chmod 3777 $locks_dir") ;
 			if ($project->enableAnonSCM()) {
-				system ("chmod -R g+wXs,o+rX-w $repo") ;
+				util_create_file_with_contents ("$repo/CVSROOT/readers", "anonymous\n");
+				util_create_file_with_contents ("$repo/CVSROOT/passwd", "anonymous:\n");
+				system ("chmod g+wXs,o+rX-w $repo") ;
 			} else {
-				system ("chmod -R g+wXs,o-rwx $repo") ;
+				util_create_file_with_contents ("$repo/CVSROOT/readers", "\n");
+				util_create_file_with_contents ("$repo/CVSROOT/passwd", "\n");
+				system ("chmod g+wXs,o-rwx $repo") ;
 			}
 		} else {
 			$unix_user = $GLOBALS['sys_apache_user'];
diff --git a/gforge/plugins/scmcvs/cronjobs/cvs.php b/gforge/plugins/scmcvs/cronjobs/cvs.php
index 949272b..23191be 100755
--- a/gforge/plugins/scmcvs/cronjobs/cvs.php
+++ b/gforge/plugins/scmcvs/cronjobs/cvs.php
@@ -303,10 +303,9 @@ function update_cvs_repositories() {
                 if(!is_dir($cvsdir_prefix."/.deleted"))
                         system("mkdir ".$cvsdir_prefix."/.deleted");
 
-                system("mv -f $cvsdir_prefix/$deleted_group_name/ $cvsdir_prefix/.deleted/");
-                system("chown -R root:root $cvsdir_prefix/.deleted/$deleted_group_name");
-                system("chmod -R o-rwx $cvsdir_prefix/.deleted/$deleted_group_name");
-
+                system("tar czfC $cvsdir_prefix/.deleted/$deleted_group_name.tar.gz $cvsdir_prefix $deleted_group_name");
+                system("chmod o-rwx $cvsdir_prefix/.deleted/$deleted_group_name.tar.gz");
+                system("rm -rf $cvsdir_prefix/$deleted_group_name");
 
                 $res9 = db_query_params ('UPDATE deleted_groups set isdeleted = 1 WHERE unix_group_name = $1',
 			array ($deleted_group_name));
diff --git a/gforge/plugins/scmcvs/cronjobs/ssh_create.php b/gforge/plugins/scmcvs/cronjobs/ssh_create.php
index c992f8c..ff7cb97 100755
--- a/gforge/plugins/scmcvs/cronjobs/ssh_create.php
+++ b/gforge/plugins/scmcvs/cronjobs/ssh_create.php
@@ -38,6 +38,19 @@ $res=db_query_params ('SELECT user_name,user_id,authorized_keys
 			    'A',
 			    'A'));
 
+function create_authkeys($params) {
+	$ssh_dir = $params['ssh_dir'];
+	$ssh_key = $params['ssh_key'];
+	if (!is_dir($ssh_dir)) {
+		mkdir ($ssh_dir, 0755);
+	}
+	$h8 = fopen("$ssh_dir/authorized_keys","w");
+	fwrite($h8,'# This file is automatically generated from your account settings.'."\n");
+	fwrite($h8,$ssh_key);
+	fclose($h8);
+	chmod ("$ssh_dir/authorized_keys", 0644);
+}
+
 for ($i=0; $i<db_numrows($res); $i++) {
 
 
@@ -48,32 +61,12 @@ for ($i=0; $i<db_numrows($res); $i++) {
 		$err .=  "Error! homedir_prefix/username Points To Root Directory!";
 		continue;
 	}
-	$uid=db_result($res,$i,'user_id');
 
-	$ssh_key=str_replace('###',"\n",$ssh_key);
-	$uid += 1000;
-
-	$ssh_dir = "$homedir_prefix/$username/.ssh";
-	if (!is_dir($ssh_dir)) {
-		mkdir ($ssh_dir, 0755);
-	}
-
-	# Set the effective uid/gid to this user, so as to avoid symlink attacks
-	$userinfo = posix_getpwnam($username);
-	posix_setegid($userinfo['gid']);
-	posix_seteuid($userinfo['uid']);
-	$h8 = fopen("$ssh_dir/authorized_keys","w");
-	fwrite($h8,'# This file is automatically generated from your account settings.'."\n");
-	fwrite($h8,$ssh_key);
-	fclose($h8);
-	posix_seteuid(0);
-	posix_setegid(0);
-		
-	system("chown $username:users $homedir_prefix/$username");
-	system("chown $username:users $ssh_dir");
-	system("chmod 0644 $ssh_dir/authorized_keys");
-	system("chown $username:users $ssh_dir/authorized_keys");
+	$params = array();
+	$params['ssh_key'] = str_replace('###',"\n",$ssh_key);
+	$params['ssh_dir'] = $homedir_prefix."/$username/.ssh";
 
+	util_sudo_effective_user($username, "create_authkeys", $params);
 }
 
 cron_entry(15,$err);
diff --git a/gforge/plugins/scmgit/common/GitPlugin.class.php b/gforge/plugins/scmgit/common/GitPlugin.class.php
index aef99b7..bc3b151 100644
--- a/gforge/plugins/scmgit/common/GitPlugin.class.php
+++ b/gforge/plugins/scmgit/common/GitPlugin.class.php
@@ -197,30 +197,46 @@ class GitPlugin extends SCMPlugin {
 
 		system ("mkdir -p $repo") ;
 		if (!is_file ("$repo/HEAD") && !is_dir("$repo/objects") && !is_dir("$repo/refs")) {
-			system ("GIT_DIR=\"$repo\" git init --bare --shared=group") ;
-			system ("GIT_DIR=\"$repo\" git update-server-info") ;
-			if (is_file ("$repo/hooks/post-update.sample")) {
-				rename ("$repo/hooks/post-update.sample",
-					"$repo/hooks/post-update") ;
-			}
-			if (!is_file ("$repo/hooks/post-update")) {
-				$f = fopen ("$repo/hooks/post-update") ;
++			$tmp_repo = util_mkdtemp('.git', $project_name);
++			if ($tmp_repo == false) {
++				return false;
++			}
++			system ("GIT_DIR=\"$tmp_repo\" git init --bare --shared=group") ;
++			system ("GIT_DIR=\"$tmp_repo\" git update-server-info") ;
++			if (is_file ("$tmp_repo/hooks/post-update.sample")) {
++				rename ("$tmp_repo/hooks/post-update.sample",
++					"$tmp_repo/hooks/post-update") ;
++			}
++			if (!is_file ("$tmp_repo/hooks/post-update")) {
++				$f = fopen ("$tmp_repo/hooks/post-update") ;
+
 				fwrite ($f, "exec git-update-server-info\n") ;
 				fclose ($f) ;
 			}
-			if (is_file ("$repo/hooks/post-update")) {
-				system ("chmod +x $repo/hooks/post-update") ;
+			if (is_file ("$tmp_repo/hooks/post-update")) {
+				system ("chmod +x $tmp_repo/hooks/post-update") ;
+			}
+			system ("echo \"Git repository for $project_name\" > $tmp_repo/description") ;
+			system ("find $tmp_repo -type d | xargs chmod g+s") ;
+			system ("chgrp -R $unix_group $tmp_repo") ;
+			if ($project->enableAnonSCM()) {
+				system ("chmod g+wX,o+rX-w $root") ;
+				system ("chmod -R g+wX,o+rX-w $tmp_repo") ;
+			} else {
+				system ("chmod g+wX,o-rwx $root") ;
+				system ("chmod -R g+wX,o-rwx $tmp_repo") ;
+			}
+			if (!rename ($tmp_repo, $repo)) {
+				return false;
 			}
-			system ("echo \"Git repository for $project_name\" > $repo/description") ;
-			system ("find $repo -type d | xargs chmod g+s") ;
 		}
 
-		system ("chgrp -R $unix_group $root") ;
+		system ("chgrp $unix_group $root") ;
 		system ("chmod g+s $root") ;
 		if ($project->enableAnonSCM()) {
-			system ("chmod -R g+wX,o+rX-w $root") ;
+			system ("chmod g+wX,o+rX-w $root") ;
 		} else {
-			system ("chmod -R g+wX,o-rwx $root") ;
+			system ("chmod g+wX,o-rwx $root") ;
 		}
 	}
 
diff --git a/gforge/plugins/scmsvn/common/SVNPlugin.class.php b/gforge/plugins/scmsvn/common/SVNPlugin.class.php
index 3b3747b..0e5c3c5 100644
--- a/gforge/plugins/scmsvn/common/SVNPlugin.class.php
+++ b/gforge/plugins/scmsvn/common/SVNPlugin.class.php
@@ -204,24 +204,43 @@ class SVNPlugin extends SCMPlugin {
 		$repo = $this->svn_root . '/' . $project->getUnixName() ;
 
 		if (!is_dir ($repo) || !is_file ("$repo/format")) {
-			system ("svnadmin create $repo") ;
+			if (!mkdir($repo, 0700)) {
+				return false;
+			}
+			$ret = 0;
+			system ("svnadmin create $repo", $ret) ;
+			if ($ret != 0) {
+				return false;
+			}
+			if ($this->use_ssh) {
+				$unix_group = 'scm_' . $project->getUnixName() ;
+				system ("find $repo -type d | xargs -I{} chmod g+s {}") ;
+				if ($project->enableAnonSCM()) {
+					system ("chmod -R g+wX,o+rX-w $repo") ;
+				} else {
+					system ("chmod -R g+wX,o-rwx $repo") ;
+				}
+				system ("chgrp -R $unix_group $repo") ;
+			} else {
+				$unix_user = $GLOBALS['sys_apache_user'];
+				$unix_group = $GLOBALS['sys_apache_group'];
+				system ("chmod -R g-rwx,o-rwx $repo") ;
+				system ("chown -R $unix_user:$unix_group $repo") ;
+			}
 			system ("svn mkdir -m'Init' file:///$repo/trunk file:///$repo/tags file:///$repo/branches") ;
 		}
 
 		if ($this->use_ssh) {
-			$unix_group = 'scm_' . $project->getUnixName() ;
-			system ("find $repo -type d | xargs chmod g+s") ;
-			system ("chgrp -R $unix_group $repo") ;
 			if ($project->enableAnonSCM()) {
-				system ("chmod -R g+wX,o+rX-w $repo") ;
+				system ("chmod g+wX,o+rX-w $repo") ;
 			} else {
-				system ("chmod -R g+wX,o-rwx $repo") ;
+				system ("chmod g+wX,o-rwx $repo") ;
 			}
 		} else {
 			$unix_user = $GLOBALS['sys_apache_user'];
 			$unix_group = $GLOBALS['sys_apache_group'];
-			system ("chown -R $unix_user:$unix_group $repo") ;
-			system ("chmod -R g-rwx,o-rwx $repo") ;
+			system ("chown $unix_user:$unix_group $repo") ;
+			system ("chmod g-rwx,o-rwx $repo") ;
 		}
 	}
 
diff --git a/gforge/utils/cvs1/cvscreate.sh b/gforge/utils/cvs1/cvscreate.sh
deleted file mode 100644
index 1078235..0000000
--- a/gforge/utils/cvs1/cvscreate.sh
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/sh
-echo ""
-echo "CVS Repository Tool"
-echo "(c)1999 SourceForge Development Team"
-echo "Released under the GPL, 1999"
-echo ""
-
-# if no arguments, print out help screen
-if test $# -lt 2; then 
-	echo "usage:"
-	echo "  cvscreate.sh [repositoryname] [groupid]"
-	echo ""
-	exit 1 
-fi
-
-# make sure this repository doesn't already exist
-if [ -d /cvsroot/$1 ] ; then
-	echo "$1 already exists."
-	echo ""
-	exit 1
-fi
-
-# first create the repository
-mkdir /cvsroot/$1
-cvs -d/cvsroot/$1 init
-
-# make it group writable
-chmod 775 /cvsroot/$1
-
-# import default directory, with default cvs.txt
-#mkdir $1
-#cp cvs.txt $1
-#cd $1
-#cvs -d/cvsroot/$1 import -m "SourceForge CVStool creation" $1 SourceForge start	
-#rm cvs.txt
-#cd ..
-#rmdir $1
-
-# turn off pserver writers, on anonymous readers
-echo "" > /cvsroot/$1/CVSROOT/writers
-echo "anonymous" > /cvsroot/$1/CVSROOT/readers
-echo "anonymous:\$1\$0H\$2/LSjjwDfsSA0gaDYY5Df/:anoncvs_$1" > /cvsroot/$1/CVSROOT/passwd 
-
-# setup loginfo to make group ownership every commit
-echo "ALL chgrp -R $1 /cvsroot/$1" > /cvsroot/$1/CVSROOT/loginfo
-echo "" > /cvsroot/$1/CVSROOT/val-tags
-chmod 664 /cvsroot/$1/CVSROOT/val-tags
-
-# set group ownership, anonymous group user 
-chown -R nobody:$2 /cvsroot/$1
-cat /etc/passwd | grep -v anoncvs_$1 > newpasswd 
-cp newpasswd /etc/passwd
-rm -f newpasswd
-/usr/sbin/adduser -M -g $2 -d/cvsroot/$1 -s /bin/false -n anoncvs_$1
-
diff --git a/gforge/utils/include.pl b/gforge/utils/include.pl
index bd189d7..1a44aaa 100644
--- a/gforge/utils/include.pl
+++ b/gforge/utils/include.pl
@@ -77,11 +77,14 @@ sub open_array_file {
 #############################
 sub write_array_file {
         my ($file_name, @file_array) = @_;
+	my $oldmask = umask(077);
 
         use File::Temp qw(tempfile);
         use File::Basename qw(dirname);
 
         my ($fd, $filename) = tempfile( DIR => dirname($file_name), UNLINK => 0) ;
+	umask($oldmask);
+
 	return 1 unless ($fd && $filename) ;
 
         foreach (@file_array) { 

-----------------------------------------------------------------------

Summary of changes:
 gforge/common/include/utils.php                  |   66 +++++
 gforge/contrib/gforge-3.0-cronjobs.patch         |  291 ----------------------
 gforge/cronjobs/homedirs.php                     |    2 +-
 gforge/deb-specific/fileforge.pl                 |  164 ------------
 gforge/deb-specific/group_dump_update.pl         |  111 ++++++---
 gforge/deb-specific/ssh_dump_update.pl           |   27 +-
 gforge/deb-specific/user_dump_update.pl          |   89 +++++--
 gforge/debian/changelog                          |    8 +
 gforge/plugins/scmbzr/common/BzrPlugin.class.php |   23 +-
 gforge/plugins/scmcvs/common/CVSPlugin.class.php |   38 ++-
 gforge/plugins/scmcvs/cronjobs/cvs.php           |    7 +-
 gforge/plugins/scmcvs/cronjobs/ssh_create.php    |   41 ++-
 gforge/plugins/scmgit/common/GitPlugin.class.php |   46 ++--
 gforge/plugins/scmsvn/common/SVNPlugin.class.php |   35 ++-
 gforge/utils/cvs1/cvscreate.sh                   |   55 ----
 gforge/utils/include.pl                          |    3 +
 16 files changed, 362 insertions(+), 644 deletions(-)
 delete mode 100644 gforge/contrib/gforge-3.0-cronjobs.patch
 delete mode 100644 gforge/deb-specific/fileforge.pl
 delete mode 100644 gforge/utils/cvs1/cvscreate.sh


hooks/post-receive
-- 
FusionForge



More information about the Fusionforge-commits mailing list