[Rt-devel] MAJOR BUG in group membership.

Ruslan U. Zakirov cubic at acronis.ru
Fri Apr 23 14:20:33 EDT 2004


	Khe-khe, folks, good time of day.
Bug located in $UserObj->Create().
This function buggy in many ways like an 'Maasdam' cheese.
1) Doesn't check return values when add users to system groups. 
AddMember check ACLs. Report below. Step to reproduce: Grant user with 
'AdminUsers', revoke 'AdminGroup' and use his account to create new 
user. :) Not all work under SU.

2)
     my $principal_id = $principal->Create(PrincipalType => 'User',
                                 Disabled => $args{'Disabled'},
                                 ObjectId => '0');
     $principal->__Set(Field => 'ObjectId', Value => $principal_id);
??? IMHO it'll die if we couldn't create a principal Id.
Or update all principals because $principal object don't have fetched 
fields :)))))

     # If we couldn't create a principal Id, get the fuck out.
     unless ($principal_id) {
??? We check it too old.


         $RT::Handle->Rollback();
         $RT::Logger->crit("Couldn't create a Principal on new user 
create. Strange things are afoot at the circle K");
         return ( 0, $self->loc('Could not create user') );
     }

3)
$RT::Handle->Commit; 
 
                                       #$RT::Logger->debug("Adding the 
user as a member of everyone");
Do we realy create user? Why commit? User that doesn't live in 
'Everyone' is not an user. :)

Same with Priveleged/Unpriveleged.

Attached script fix tables, it _must_ be included/merged in RT update 
script in next release.

			Good luck. Ruslan.

An angry PS:
1) I don't need/want/wish/like fucking users who sweem around in RT DB 
like an piece of shit.
2) This bug once again proof that using return values for error handling 
is bad practice.
3) I don't know what exactly moving you guys, marketing team or somebody 
else, you're maintaining two branches at the same time. When your code 
base, core of your project, has lucks in many ways which should be 
refactored.
4) Why does RT operates so slow? It wouldn't be fast if there will be 
next code:
     $RT::Logger->crit("Deleting groups violates referential integrity 
until we go through and fix this");
     # TODO XXX
 
 

     # Remove the principal object
     # Remove this group from anything it's a member of.
     # Remove all cached members of this group
     # Remove any rights granted to this group
     # remove any rights delegated by way of this group
 
 

     return ( $self->SUPER::Delete(@_) );

5) Even MySQL allow FKs now, but RT still doesn't have FKs.
6) Our mail relay was stopped for less then 3 days. 5000 mails were in 
spool. What do you think happened when we did run it? Don't know? Yeh, 
RT didn't live for 5 minutes, This problem not only with RT, all 
together Apache/mod_perl eat all memory and begin lost mysql connection 
due OOMKiller, mysql which can't limit number threads on i386 Linux, RT 
which does some things slowly. It's fine machine with >2GHz, >1GB...

Huh, I end up. Exhausts are ended too. Nearest monthes I'll not retry 
such things :)




Ruslan U. Zakirov wrote:
> We have 449 user who has no member ship in group Everyone!
> 
> select count(1) from Principals pr left join GroupMembers gm on 
> (gm.MemberId = pr.id and gm.GroupId = 3) where pr.PrincipalType = 'User' 
> and gm.id is null;
> 
> Most of this users were created via CLI.
> 
> We have
> select count(1) from Principals where PrincipalType = 'User';
> +----------+
> | count(1) |
> +----------+
> |    43696 |
> +----------+
> users.
> 
> Users by system groups
> select g.id, g.Domain, g.Type, count(gm.id) members from GroupMembers 
> gm, Groups g where gm.GroupId in(3,4,5) and g.id = gm.GroupId group by 
> gm.GroupId;
> +----+----------------+--------------+---------+
> | id | Domain         | Type         | members |
> +----+----------------+--------------+---------+
> |  3 | SystemInternal | Everyone     |   43247 |
> |  4 | SystemInternal | Privileged   |      51 |
> |  5 | SystemInternal | Unprivileged |   43196 |
> +----+----------------+--------------+---------+
> 
> This 449 users don't have membership in system groups.
> 
> Please, I need solution tomorrow.
> 
>                     Best regards. Ruslan.
-------------- next part --------------
#!/usr/bin/perl -w


use strict;
use Carp;
use Getopt::Long;

use lib '/opt/rt3/lib';
use lib '/opt/rt3/etc';

#use RT::Interface::CLI  qw(CleanEnv GetCurrentUser GetMessageContent loc);
#CleanEnv(); 

use RT; 
use RT::Ticket;
use RT::Tickets;

#Load RT's config file
RT::LoadConfig();

# Connect to the database. set up loggign
RT::Init();

my $where = shift;
unless( $where =~ /^(un)?priveleged$/i ) {
	print <<END;
	Script fixes users membership in RT system groups: Everyone, Priveleged, Unpriveleged.
	In RT-3.0.x was bug and under some conditions users can leave this groups and lost
	thier rights.

	User must be always member of Everyone.
	User must be always member of Priveleged or Unpriveleged and must be only in one,
	so you have to choose group where broken users would be placed.

	usage: $0 priveleged | unprivelged

END
	die "Please choose group where scipt would place broken users";
}

my $everyone = RT::Group->new( $RT::SystemUser );
$everyone->LoadSystemInternalGroup('Everyone');
unless( $everyone->id ) {
	die "Something wrong, you don't have system group Everyone";
};
my $unpriv = RT::Group->new( $RT::SystemUser );
$unpriv->LoadSystemInternalGroup('Unprivileged');
unless( $unpriv->id ) {
	die "Something wrong, you don't have group Unpriveleged";
};
my $priv = RT::Group->new( $RT::SystemUser );
$priv->LoadSystemInternalGroup('Privileged');
unless( $priv->id ) {
	die "Something wrong, you don't have group Priveleged";
};


my $dbh = $RT::Handle->dbh;
# select all users who don't belong to everyone.
my $sth = $dbh->prepare( "select 
		pr.id 
	from Principals pr 
		left join GroupMembers gm 
			on (gm.MemberId = pr.id and gm.GroupId = ". $everyone->id ." ) 
	where pr.PrincipalType = 'User' and gm.id is null " );
$sth->execute() or die $sth->errstr;
my $Users = $sth->fetchall_arrayref( [0] );
if( scalar @$Users ) {
	print "You have ". scalar @$Users ." users who aren't members of Everyone group\n";
	FixSystemMembership( $Users, $everyone );
}
$sth->finish;

# select all users who don't belong to priveleged and not to unpriveleged.
$sth = $dbh->prepare( "select 
		pr.id 
	from Principals pr 
		left join GroupMembers gm 
			on (gm.MemberId = pr.id and 
			gm.GroupId in( ". $priv->id .", ". $unpriv->id ." ) ) 
	where pr.PrincipalType = 'User' and gm.id is null " );
$sth->execute() or die $sth->errstr;
$Users = $sth->fetchall_arrayref( [0] );
if( scalar @$Users ) {
	print "You have ". scalar @$Users ." users who aren't members of Priveleged or Unpriveleged groups\n";
	print "Will add this users to ". ucfirst lc $where ." group\n";
	if( $where =~ /^un/i ) {
		FixSystemMembership( $Users, $unpriv );
	} else {
		FixSystemMembership( $Users, $priv );
	}
}
$sth->finish;

print "Your tables now fine\n";
exit(0);


sub FixSystemMembership {
	my ( $Users, $Group ) = @_;

	foreach my $u ( @$Users ) {
		next if( $u->[0] == $RT::SystemUser->id );
		print "Fixing user #". $u->[0] .":";
		my ( $status, $msg ) = $Group->AddMember( $u->[0] );
		unless( $status ) {
			die "$msg";
		}
		print "\tOK\n";
	}
};



More information about the Rt-devel mailing list