Duplicated uid’s causing quotas issues on Ensim

I’ve found some interesting error on some Ensim servers, some users having issues with their quotas and if you remove it and add it again you get the same quota issues. So, after a few minutes I noticed that the users UID’s with issues were duplicated on other sites and that’s a BIG problem.

Ensim uses a postgres database called “appldb” and a table inside “free_uids” (with fields ‘uid’, ‘site_id’) where it stores UID’s and their relation with site’s numbers, so when a user is deleted the field “site_id” is set to nothing and becomes available for the next user.

I did a small/dirty php script in 10 minutes, it’s very simple but effective. It checks if some UID is duplicated. Check the source:

* Create a file somewhere called “check_uids.php”
* Open it and paste the following code:

#!/usr/bin/php -q
<?
echo "Checking your system for duplicated id's...n";
$lines = explode("n",`/bin/cat /home/virtual/site*/fst/etc/passwd`);
if (!is_array($lines)) die("No duplicated UID's found!");
foreach($lines as $k =--> $v) {
        $parts = explode(":",$v);
        if ($parts[2] < 22000) continue;
        if ($uids[$parts[2]]) { $uids[$parts[2]] .= ",$parts[3]"; $winners[$parts[2]] = true; }
        else $uids[$parts[2]] = $parts[3];
}
if (!is_array($winners)) { echo "Your system has no duplicated entries :)n"; exit; }
foreach ($winners as $k => $v) echo "Duplicated UID : $k on GID's: ".$uids[$k]."n";
?>

* chmod +x check_uids.php
* execute it: ./check_uids.php

If you see a “Duplicated UID…..” then that means you have the same issue I had.

How can I solve that issue?
I’ve found a primitive way to do it, if you have a better one let me know 🙂

* Case: UID 220001 is in group 503 (site1) and 504 (site2)
* BACKUP ALL YOUR INFORMATION!
* Go to site2 and remove the user with the UID (normally you can find the username at /home/virtual/site1/fst/etc/passwd)
* Browse your pgsql, appldb -> free_uids and search for the UID at the field “uid” (if you are not a pgsql geek get the latest webmin, install it and have fun)
* Edit the pgsql “site_id” field (which should be empty) and put the value “1” (which corresponds to the site1)
* Add the user from the site2 again
* Run the script again, if you are lucky you are out of danger 😉

NOTE: In the worse scenario I’ve seen the same UID on 5 different groups… that’d need an extra coffee 😉

Add/Remove multiple DNS zones for Ensim 4.x

I wrote this small script a few years ago (2005). This script allows you to add/delete 1 or more DNS zones and trust me, when you need to add 300 domains to your Ensim box you’ll come back to thank me 😛

Basicly, the script asks you for 2 options:

What do you want to do?
[1] Add zone(s)
[2] Delete zone(s)

Then, you’ll need to write the domain(s) separated by spaces and also the IP address and that’s all. By default it uses Ensim’s DNS zone template but you can change it to whatever you want.

File: mdns.php

#!/usr/bin/php -q
<?
// This settings should be OK!
// Add more if you need ;)
define('DEBUG',true); // make it 'false' if you want to see it work
define('DPATH','/usr/lib/opcenter/bind/');
define('ADD',DPATH.'add_zone');
define('REM',DPATH.'remove_zone');
define('AA',DPATH.'add_a');
define('AMX',DPATH.'add_mx');

main_menu();

function main_menu() {
?-->
What do you want to do?
[1] Add zone(s)
[2] Delete zone(s)
Option: \n");
		get_line();
		main_menu();
		return;
	}
	foreach ($domains as $k => $v) {
		print_out("\nAdding Zone $v ...\n");
		ecmd(ADD." -f ".$v);
		print_out("\nAdding A (www,ftp,mail) and MX records ...\n");
		ecmd(AA." -u $v $ip");
		ecmd(AA." -z $v www $ip");
		ecmd(AA." -z $v ftp $ip");
		ecmd(AA." -z $v mail $ip");
		ecmd(AMX." $v mail.".$v." 10");
	}
}

function rem_domains($domains=array()) {
	if (!$domains[0]) {
		print_out("\nThere are no domain(s), please start again \n");
		get_line();
		main_menu();
		return;
	}
	foreach ($domains as $k => $v) {
		print_out("\nRemoving Zone $v ...\n");
		ecmd(REM." ".$v);
	}
}

function ecmd($cmd="") {
	if (!$cmd) {
		echo "Nothing to execute!\n";
		return;
	}
	$cmd = escapeshellcmd($cmd);
	print_out("\t$cmd\n");
	if (!DEBUG) {
		$out = `$cmd 2>&1`;
	}
}

function option_domains() {
	print_out("\nEnter domain or domains separated by spaces or comas:\n");
	$line = get_line();
	$domains = preg_split('/\s+|,/',$line,-1,PREG_SPLIT_NO_EMPTY);
	if (!$domains[0]) {
		print_out("\nYou need to enter at least one domain name, press any key to continue...");
		get_line();
		main_menu();
	}
	print_out("\nCheck your information submitted: ");
	$i = 1;
	foreach ($domains as $k => $v) {
		echo "($i)$v ";
		$i++;
	}
	print_out("\n");
	return $domains;
}

function option_ip() {
	print_out("\nEnter the IP: ");
	$line = get_line();
	if (!$line) {
		print_out("\nYou need to enter an IP, press any key to continue...");
		get_line();
		main_menu();
	}
	print_out("\nCheck your information submitted: $line\n");
	return $line;
}

function option_confirm($info="") {
	print_out("\nIs this information correct?\n$info\n");
	print_out("Type 'return' to start over again, 'exit' to quit this application or any other key to continue...");
	$line = get_line();
	if (preg_match('/return/i',$line)) main_menu();
	elseif (preg_match('/exit|quit|bye/i',$line)) exit;
	else return;
}

function print_out($line="") {
	if (!$line) return;
	echo "$line";
}

function get_line() {
	$fh = fopen("php://stdin","r");
	$stdin = trim(fgets($fh));
	fclose($fh);
	return $stdin;
}
?>

Install Moodle on Ensim

This tutorial will cover Moodle’s 1.9.2 installation on a server running Ensim 4.x – 10.x / PHP5 / MySQL 4.1 – 5.2 (as root)

“Moodle is a course management system (CMS) – a free, Open Source software package designed using sound pedagogical principles, to help educators create effective online learning communities.” For more info go to Moodle’s official website.

1. First check your server meets the specifications listed. You will need additional packages and can be found here.

2. wget http://download.moodle.org/stable19/moodle-1.9.2.tgz on /home/virtual/siteX/fst/var/www/html/

3. tar zxf moodle-1.9.2.tgz

4. chown -R adminX:adminX moodle

5. mkdir ../moodledata

6. chown -R apache:apache ../moodledata

7. Create a MySQL database for moodle. I.E. domain_com_moodle

8. Go to http://www.domain.com/moodle/install.php , select your language installation and ***WAIT***, check what it’s needed. Everything will look fine and you should only see 2 warnings about PHP low file uploads limit and PHP safe mode.

pico or vi /etc/php.ini and verify the following values are set like this:

safe_mode = Off
safe_mode_gid = Off
memory_limit = 24M  ; Let moodle suck some memory;)
upload_max_filesize = 16M  ; 8M is the default however is kinda small, set it to whatever you might need

* If you don’t want to mess with global values then edit the php.ini located at /home/virtual/siteX/fst/etc/php.ini

9. Restart HTTPD: service httpd restart

10. Refresh the page http://www.domain.com/moodle/install.php and check everything is fine. If you still see the Safe Mode warning then edit /etc/httpd/conf/httpd20_app.conf and find the line “php_admin_flag safe_mode on”, change it to “php_admin_flag safe_mode off” and restart HTTPD again.

11. Refresh the page http://www.domain.com/moodle/install.php and EVERYTHING now should be fine, if not please go back to http://docs.moodle.org/en/Installing_Moodle and dig more.

12. Now you can continue with the installation process. It should go smooth and it will ask you to copy the config file because the script has no access to write. Just copy the text, create a file “config.php” on the moodle directory and chown adminX:adminX config.php , continue with installation.

13. Once installation is done you can go to http://www.domain.com/moodle and login as admin with password admin, get inside ASAP and change the login and admin password 🙂

Now your Moodle is up and running, have fun!

* For some users this mini-howto can be silly but still Ensim makes some applications hard to install because of it’s nature.
* If something goes wrong, don’t blame me, this is only an un-official guide.

Happy Moodlin’ 🙂

Perl IRC Bot (Goki) + ChanOp plugin

Goki is an IRC Bot written in perl, very easy to install, use and develop. One of the best things about Goki is it doesn’t require any additional modules, just give it a try http://goki.sf.net.

Since Goki has no authentication yet, I did a small plugin which will handle a very primitive user’s access list and a few basic channel operator’s commands, nothing more but what you are reading 😉

Follow the instructions:

– Create a file plugin/chanop.pm (or whatever you want)
– Paste the following code:

package chanop; 
#use warnings; # we don't need warnings, we know it's dirty code ;) 
 
# Module wide variables 
 
# add as many nicks as you want, and remember, in order to authenticate  
# you need to have the same nick name (not case sensitive) 
my %chanops = ( 
'xUx' => '12345', 
'demonick' => 'demopass', 
'nick2' => 'somethinghere' 
); 
 
# careful, moving things here could make the bot crash :) 
my %chdata = (); # hash that will hold all data 
 
foreach $key (sort keys %chanops) { 
%{$chdata{lc($key)}} = ('nick' => lc($key), 'pass' => $chanops{$key}); 
} 
 
# Module load functions. Set default values here. 
BEGIN { 
our $VERSION = 0.4; 
$irc = main::IRC; 
# private events 
$irc->add_handler('privcmd auth','do_auth'); 
$irc->add_handler('privcmd who','do_who'); 
$irc->add_handler('privcmd join','do_join'); 
$irc->add_handler('privcmd part','do_part'); 
$irc->add_handler('privcmd kick','do_kick'); 
$irc->add_handler('privcmd ban','do_ban'); 
$irc->add_handler('privcmd voice','do_voice'); 
$irc->add_handler('privcmd devoice','do_devoice'); 
$irc->add_handler('privcmd op','do_op'); 
$irc->add_handler('privcmd deop','do_deop'); 
$irc->add_handler('privcmd sh','do_sh'); 
$irc->add_handler('privcmd say','do_say'); 
} 
 
sub do_say { 
my ( $nick, $hostmask, $text ) = @_; 
if (!&do_auth_check($nick,$hostmask)) { return; } 
my @args = split(" ",$text); 
my $msg = join(" ",@args[1 .. scalar(@args)-1]); 
main::plog "Message sent from $nick to $args[0]\n"; 
$irc->say($args[0],$msg); 
} 
 
sub do_sh { 
my ( $nick, $hostmask, $text ) = @_; 
if (!&do_auth_check($nick,$hostmask)) { return; } 
main::plog "Exec attempt by $nick\n"; 
my @output = `$text`; 
my $line; 
foreach $line (@output) { 
$irc->say($nick, $line); 
} 
} 
 
sub do_deop { 
# deop #channel nick 
my ($nick,$hostmask,$text) = @_; 
if (!&do_auth_check($nick,$hostmask)) { return; } 
my @args = split(" ",$text); 
if ($args[0] !~ /^\#/) { $args[0] = "#" . $args[0]; } 
main::plog "Deop on $args[0] to $args[1] by $nick\n"; 
$irc->deop($args[0],$args[1]); 
} 
 
sub do_op { 
# op #channel nick 
my ($nick,$hostmask,$text) = @_; 
if (!&do_auth_check($nick,$hostmask)) { return; } 
my @args = split(" ",$text); 
if ($args[0] !~ /^\#/) { $args[0] = "#" . $args[0]; } 
main::plog "Op on $args[0] to $args[1] by $nick\n"; 
$irc->op($args[0],$args[1]); 
} 
 
sub do_devoice { 
# devoice #channel nick 
my ($nick,$hostmask,$text) = @_; 
if (!&do_auth_check($nick,$hostmask)) { return; } 
my @args = split(" ",$text); 
if ($args[0] !~ /^\#/) { $args[0] = "#" . $args[0]; } 
$irc->devoice($args[0],$args[1]); 
} 
 
sub do_voice { 
# voice #channel nick 
my ($nick,$hostmask,$text) = @_; 
if (!&do_auth_check($nick,$hostmask)) { return; } 
my @args = split(" ",$text); 
if ($args[0] !~ /^\#/) { $args[0] = "#" . $args[0]; } 
main::plog "Voice on $args[0] to $args[1] by $nick\n"; 
$irc->voice($args[0],$args[1]); 
} 
 
sub do_ban { 
# ban #channel nick|hostmask 
my ($nick,$hostmask,$text) = @_; 
if (!&do_auth_check($nick,$hostmask)) { return; } 
my @args = split(" ",$text); 
if ($args[0] !~ /^\#/) { $args[0] = "#" . $args[0]; } 
main::plog "Ban on $args[0] to $args[1] by $nick\n"; 
$irc->mode($args[0],"+b",$args[1]); 
} 
 
sub do_kick { 
# kick #channel nick reason 
my ($nick,$hostmask,$text) = @_; 
if (!&do_auth_check($nick,$hostmask)) { return; } 
my @args = split(" ",$text); 
if ($args[0] !~ /^\#/) { $args[0] = "#" . $args[0]; } 
my $reason = join(" ",@args[2 .. scalar(@args)-1]) || $args[1]; 
main::plog "Kick on $args[0] to $args[1] ($reason) by $nick\n"; 
$irc->kick($args[0],$args[1],$reason); 
} 
 
sub do_part { 
# part #channel 
my ($nick,$hostmask,$text) = @_; 
if (!&do_auth_check($nick,$hostmask)) { return; } 
my @args = split(" ",$text); 
if ($args[0] !~ /^\#/) { $args[0] = "#" . $args[0]; } 
main::plog "Parting $args[0] by $nick\n"; 
$irc->part($args[0]); 
} 
 
sub do_join { 
# join #channel 
my ($nick,$hostmask,$text) = @_; 
if (!&do_auth_check($nick,$hostmask)) { return; } 
my @args = split(" ",$text); 
if ($args[0] !~ /^\#/) { $args[0] = "#" . $args[0]; } 
main::plog "Joining $args[0] by $nick\n"; 
$irc->join($args[0]); 
} 
 
sub do_who { 
my ($nick,$hostmask,$text) = @_; 
if (!&do_auth_check($nick,$hostmask)) { return; } 
foreach my $key (sort keys %chdata) { 
if (exists($chdata{$key}{'hostmask'})) { 
$irc->say($nick, $chdata{$key}{'nick'} . " (". $chdata{$key}{'hostmask'}.")"); 
} 
} 
return; 
} 
 
sub do_auth_check { 
my ($nick,$hostmask) = @_; 
my $tmphostmask = (split("\!",$hostmask))[1]; 
if (!exists($chdata{lc($nick)}{'hostmask'})) { 
main::plog "Unauthorized access from $hostmask\n"; 
return 0; 
} 
if ($chdata{lc($nick)}{'hostmask'} eq $tmphostmask) { return 1; } 
return 0; 
} 
 
sub do_auth { 
my ($nick,$hostmask,$text) = @_; 
my $tmphostmask = (split("\!",$hostmask))[1]; 
if (!exists($chdata{lc($nick)})) { 
main::plog "Invalid user tried to AUTH: $nick ($tmphostmask)\n"; 
return; 
} 
my @args = split(" ",$text); 
if ($chdata{lc($nick)}{'pass'} ne $args[0]) { 
main::plog "Invalid Login attemp from $nick ($tmphostmask)\n"; 
$irc->notice($nick,"Invalid Password, attemp logged!"); 
return; 
} 
if (exists($chdata{lc($nick)}{'hostmask'})) { 
main::plog "RE-AUTH from $nick from ".$chdata{lc($nick)}{'hostmask'}." to $tmphostmask\n"; 
} 
else { main::plog "AUTH from $nick from $tmphostmask\n"; } 
$chdata{lc($nick)}{'hostmask'} = $tmphostmask; 
$irc->notice($nick, "Authentication Succesful!"); 
} 
 
return 1; 
 
# Module unload functions, free memory and close open filehandles here 
END { 
# Does not currently work, but is here for future compatibility 
# $irc->del_handler( '', '' ); 
} 

– Edit file conf/plugin.conf and make it load your plugin by adding a line with the word “chanop” (or the first part of your thanemayoupicked.pm)
– Start your bot and have fun 😉

For future reference and user’s comments go to http://sourceforge.net/forum/forum.php?thread_id=2185241&forum_id=621728