From d0d53a2c3e200588f062d10d5284286f0900197a Mon Sep 17 00:00:00 2001 From: katagia Date: Wed, 7 May 2003 16:53:03 +0000 Subject: [PATCH] Added quota.layout and a part of quota-functions added lamdaemon.pl WARNING!!!!! Don't use lamdaemon.pl. It's net even alpha and should be extremly insecure. --- lam/lib/account.inc | 56 ++++++++- lam/lib/lamdaemon.pl | 255 ++++++++++++++++++++++++++++++++++++++ lam/templates/account.php | 44 ++++++- 3 files changed, 345 insertions(+), 10 deletions(-) create mode 100755 lam/lib/lamdaemon.pl diff --git a/lam/lib/account.inc b/lam/lib/account.inc index a9fa2977..4ed781fa 100644 --- a/lam/lib/account.inc +++ b/lam/lib/account.inc @@ -63,6 +63,8 @@ class account { // This class keeps all needed values for any account var $smb_flagsW; var $smb_flagsD; var $smb_flagsX; + // Quota Settins + var $quota; // Personal Settings var $personal_title; var $personal_mail; @@ -260,6 +262,28 @@ function checksamba() { // This function checks all samba account paramters return $error; } +function checkquota() { // This function checks all quota paramters + $error = "0"; + $i=0; + while ($_SESSION['account']->quota[$i][0]) { + if (!$_SESSION['account_temp']->quota[$i][2]) $_SESSION['account']->quota[$i][2] = 0; + else if (!ereg('^([0-9])*$', $_SESSION['account_temp']->quota[$i][2])) $error = _('Block soft quota contains invalid characters. Only natural numbers are allowed'); + if (!$_SESSION['account_temp']->quota[$i][3]) $_SESSION['account']->quota[$i][3] = 0; + else if (!ereg('^([0-9])*$', $_SESSION['account_temp']->quota[$i][3])) $error = _('Block hard quota contains invalid characters. Only natural numbers are allowed'); + if (!$_SESSION['account_temp']->quota[$i][6]) $_SESSION['account']->quota[$i][6] = 0; + else if (!ereg('^([0-9])*$', $_SESSION['account_temp']->quota[$i][6])) $error = _('Inode soft quota contains invalid characters. Only natural numbers are allowed'); + if (!$_SESSION['account_temp']->quota[$i][7]) $_SESSION['account']->quota[$i][7] = 0; + else if (!ereg('^([0-9])*$', $_SESSION['account_temp']->quota[$i][7])) $error = _('Inode hard quota contains invalid characters. Only natural numbers are allowed'); + $_SESSION['account']->quota[$i][2] = $_SESSION['account_temp']->quota[$i][2]; + $_SESSION['account']->quota[$i][3] = $_SESSION['account_temp']->quota[$i][3]; + $_SESSION['account']->quota[$i][6] = $_SESSION['account_temp']->quota[$i][6]; + $_SESSION['account']->quota[$i][7] = $_SESSION['account_temp']->quota[$i][7]; + $i++; + } + return $error; + } + + function checkpersonal() { $error = "0"; if ($_SESSION['account_temp']->personal_title) $_SESSION['account']->personal_title = $_SESSION['account_temp']->personal_title ; @@ -327,6 +351,32 @@ function RndInt($Format){ * 8 CHARACTERS IN THE PASSWORD PRODUCED. */ +function getquotas($user='*') { // Whis function will return the quotas from the specified user If empty only filesystems with enabled quotas are returned + //$ldap = $_SESSION['ldap']->decrypt(); + $ldap_q[0] = 'cn=Manager,dc=my-domain,dc=com'; + $ldap_q[1] = 'secret'; + $towrite = $ldap_q[0].' '.$ldap_q[1].' '.$user.' quota get '; + if ($_SESSION['type2']=='user') $towrite = $towrite.'u'; + else $towrite = $towrite.'g'; + $file = fopen('../lib/lamdaemon.fifo', 'w'); + fwrite($file, $towrite); + fclose ($file); + $file = fopen('../lib/lamdaemon.fifo', 'r'); + $input = fread($file, 1024); + fclose ($file); + $vals = explode(';', $input); + $i=0; + while ($vals[$i]) { + $vals2 = explode(',', $vals[$i]); + $j=0; + while ($vals2[$j]) { + $_SESSION['account']->quota[$i][$j] = $vals2[$j]; + $j++; + } + $i++; + } + } + function ldapexists() { // This function will search if the DN already exists switch ($_SESSION['type2']) { @@ -502,6 +552,7 @@ function loaduser($dn) { // Will load all needed values from an existing account $_SESSION['account_old'] = $_SESSION['account']; if ($attr['userPassword'][0]) $_SESSION['account_old']->unix_password = $attr['userPassword'][0]; if ($attr['ntPassword'][0]) $_SESSION['account_old']->smb_password = $attr['ntPassword'][0]; + //getquotas($attr['uid'][0]); } function loadhost($dn) { // Will load all needed values from an existing account @@ -567,6 +618,7 @@ function loadgroup($dn) { // Will load all needed values from an existing group if (is_array($_SESSION['account']->general_memberUid)) array_shift($_SESSION['account']->general_memberUid); $_SESSION['account']->general_dn = $dn; $_SESSION['account_old'] = $_SESSION['account']; + //getquotas($attr['uid'][0]); } @@ -815,10 +867,6 @@ function createhost() { // Will create the LDAP-Host if ($success) ldap_delete($_SESSION['ldap']->server(),$_SESSION['account_old']->general_dn); } if (!$success) return 5; - if ($attr['uidNumber']!=$_SESSION['account_old']->general_uidNumber) StatusMessage('INFO', _('Attention:'), - _('You have to run the following command if yuo want to preserve filepermission: '). - ('find / -uid ' . $_SESSION['account_old' ]->general_uidNumber . ' -exec chown ' . $_SESSION['account']->general_uidNumber . ' {} \;')); - // Write Groupmemberchips $allgroups = $_SESSION['account']->general_groupadd; if (!in_array($_SESSION['account']->general_group, $allgroups)) $allgroups[] = $_SESSION['account']->general_group; $result = ldap_search($_SESSION['ldap']->server(), $_SESSION['config']->get_GroupSuffix(), 'objectClass=PosixGroup', array('memberUid')); diff --git a/lam/lib/lamdaemon.pl b/lam/lib/lamdaemon.pl new file mode 100755 index 00000000..b2314e83 --- /dev/null +++ b/lam/lib/lamdaemon.pl @@ -0,0 +1,255 @@ +#! /usr/bin/perl -T + +# $Id$ +# +# This code is part of LDAP Account Manager (http://www.sourceforge.net/projects/lam) +# Copyright (C) 2003 Tilo Lutz +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# +# LDAP Account Manager daemon to create and delete homedirecotries and quotas + +# At the moment communication is using fifos. Later a network socket will be used. + +use Cwd; # Needed to get the current path. +use Quota; # Needed to get and set quotas +use Net::LDAP; # Needed to connect to ldap-server +use File::NCopy qw(copy); # Needed to copy recursive +use File::Path; # Nedded to delete recursive and create directories recursive + +$path = cwd; # Path of $lam/lib +$server; # URL of ldap-server +$usersuffix; # ldap-suffix of users +@admins; # list of valid admins +@quota_usr; # Filesystems with enabled userquotas +@quota_grp; # Filesystems with enabled userquotas +$debug=true; # Show debug messages +$|=1; + +# Check if Fifo was created. +if (!-e 'lamdaemon.fifo') { + system ('mkfifo', 'lamdaemon.fifo'); + system ('chmod', '777', 'lamdaemon.fifo'); + } + +sub loadcfg { + # Get ldap-server from $lam/config/lam.conf + # Get valid admins from $lam/config/lam.conf + open ( CONFIG, "< $path/../config/lam.conf" ) or die ('Can\'t open lam.conf.'); + while () { + my @line = split (':', $_); + $line[0] =~ s/ //g; + $line[1] =~ s/ //g; + if ($line[0] eq 'serverURL') { $server=$line[1]; } + if ($line[0] eq 'usersuffix') { $usersuffix=$line[1]; } + if ($line[0] eq 'admins') { @admins = split (';', $line[1]); } + } + $time_lam = -M "$path/../config/lam.conf"; + } + +sub get_fs { # Load mountpoints from mtab if enabled quotas + Quota::setmntent(); + my $i=0; + my @args; + while (my @temp = Quota::getmntent()) { + $args[$i][0] = $temp[0]; + $args[$i][1] = $temp[1]; + $args[$i][2] = $temp[2]; + $args[$i][3] = $temp[3]; + $i++; + } + Quota::endmntent(); + my $j=0; my $k=0; $i=0; + while ($args[$i][0]) { + if ( $args[$i][3] =~ m/usrquota/ ) { + $quota_usr[$j][0] = $args[$i][0]; + $quota_usr[$j][1] = $args[$i][1]; + $quota_usr[$j][2] = $args[$i][2]; + $quota_usr[$j][3] = $args[$i][3]; + $j++; + } + elsif ( $args[$i][3] =~ m/grpquota/ ) { + $quota_grp[$k][0] = $args[$i][0]; + $quota_grp[$k][1] = $args[$i][1]; + $quota_grp[$k][2] = $args[$i][2]; + $quota_grp[$k][3] = $args[$i][3]; + $k++; + } + $i++; + } + $time_mtab = -M "/etc/mtab"; + } + +$host="127.0.0.1"; + +while (defined ()) + { + # Reset variables + $found=false; + $return=''; + open ( FIFO, '< lamdaemon.fifo' ) or die ('Can\'t open fifo lamdaemon.fifo.'); # Open Fifo + @vals = split (' ', ); # read values from fifo + # vals = DN, PAssword, user, home, (add|rem), + # quota, (set|get),(u|g), (mountpoint:blocksoft:blockhard:filesoft:filehard:timelimit)+ + # chown options + close FIFO; # Close fifo. + if ($debug==true) { print "@vals\n"; } + if ( $time_lam != -M "$path/../config/lam.conf" ) { loadcfg(); } #load config at start and if configfile has changed + if ( $time_mtab != -M "/etc/mtab" ) { get_fs(); } #load config at start and if configfile has changed + + # Check if DN is listed as admin + foreach my $admin (@admins) { + if ($admin eq $vals[0]) { $found=true; } + } + if ($found==true) { + # Connect to ldap-server and check if password is valid. + $ldap = Net::LDAP->new($host) or die ('Can\'t connect to ldapserver.'); + $result = $ldap->bind (dn => $vals[0], password => $vals[1]) ; + if (!$result->code) { # password is valid + switch: { + # Get user information + my $isrealadmin=false; + if (($vals[5] eq 'u') || ($vals[3] eq 'home')) { + @user = getpwnam($vals[2]); + my $result = $ldap->search ( base=>$userbase, filter=>"uid=$vals[2]", attrs=>['userPassword', 'uidNumber'] ); + my $href = $result->as_struct; + my @arrayOfDNs = keys %$href; # use DN hashes + my $valref = $$href{$arrayOfDNs[0]}; + my @arrayOfAttrs = sort keys %$valref; #use Attr hashes + if (@$valref{$arrayOfAttrs['uidNumber']}!=$user[2]) { # We've found the wrong user with the right usernmae but wron uidnumber + $isrealadmin=false; + if ($debug==true) { print "Found user $user[0] but uidNumber from another user. Please check your settings!!!\n"; } + } + else { + my $userPassword = @$valref{$arrayOfAttrs['userPassword']} ; # Read userPassword. + my $msg = $ldap->modify (dn => $arrayOfDNs[0], add=>{ 'userPassword'=>$userPassword }); + if (!$result->code) { $isrealadmin=true; } + } + } + else { + # Check if admin is really an admin + # If he can modify the password from the user he's one + @user = getgrnam($vals[2]); + my $result = $ldap->search ( base=>$userbase, filter=>"gid=$vals[2]", attrs=>['userPassword', 'gidNumber'] ); + my $href = $result->as_struct; + my @arrayOfDNs = keys %$href; # use DN hashes + my $valref = $$href{$arrayOfDNs[0]}; + my @arrayOfAttrs = sort keys %$valref; #use Attr hashes + if (@$valref{$arrayOfAttrs['gidNumber']}!=$user[2]) { # We've found the wrong user with the right usernmae but wron uidnumber + $isrealadmin=false; + if ($debug==true) { print "Found user $user[0] but uidNumber from another user. Please check your settings!!!\n"; } + } + else { + my $userPassword = @$valref{$arrayOfAttrs['userPassword']} ; # Read userPassword. + if (!$userPassword) { + $roremove=true; + $userPassword = "*"; # Set invalid Password if Password is not set, e.g. groups + } + my $msg = $ldap->modify (dn => $arrayOfDNs[0], replace=>{ 'userPassword'=>$userPassword }); + if (!$result->code) { + $isrealadmin=true; + if ($toremove==true) { + $ldap->modify (dn => $arrayOfDNs[0], delete=>'userPassword'); + } + } + } + } + if ($isrealadmin==true) { + $vals[3] eq 'home' && do { + switch2: { + $vals[4] eq 'add' && do { + # split homedir to set all directories below the last dir. to 755 + my $path = $user[7]; + $path =~ s,/(?:[^/]*)$,,; + eval { mkpath ($patch, 0, '755') }; + if ($@) { $return = 0; } + if ( $return != 0 ) { + eval { mkpath ($user[7], 0, '700') };# Create Homedirectory + if ($@) { $return = 0; } + } + if ($return != 0 ) { + $return =copy \1, '/etc/skel/', $user[7]; # Copy /etc/sekl into homedir + } + if ($return > 0) { + system 'chown', '-R', $user[2], $user[3] , $user[7]; # Change owner to new user + } + system '/usr/sbin/useradd.local', $user[0]; # run useradd-script + last switch2; + }; + $vals[4] eq 'rem' && do { + eval { rmtree ($user[7], 0, 0) }; # Delete Homedirectory + if ($@) { $return = 0; } + if ($return!=0) { system '/usr/sbin/userdel.local', $user[0]; } + last switch2; + }; + } + last switch; + }; + $vals[3] eq 'quota' && do { + # Store quota information in array + @quota_temp1 = split (';', $vals[6]); + $i=0; + while ($quota_temp1[$i]) { + $j=0; + @temp = split (',', $quota_temp1[$i]); + while ($temp[$j]) { + $quota[$i][$j] = $temp[$j]; + $j++; + } + $i++; + } + if ($vals[5] eq 'u') { $group=false; } + else { $group=true; } + switch2: { + $vals[4] eq 'set' && do { + $i=0; + while ($quota_usr[$i][0]) { + $dev = Quota::getqcarg($quota[$i][0]); + $return = Quota::setqlim($dev,$user[2],$quota[$i][1],$quota[$i][2],$quota[$i][3],$quota[$i][4],1,$group); + $i++; + } + last switch2; + }; + $vals[4] eq 'get' && do { + $i=0; + while ($quota_usr[$i][0]) { + if ($vals[2]!='*') { + @temp = Quota::query($quota_usr[$i][0],$user[2],$group); + $return = "$quota_usr[$i][1],$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5],$temp[6],$temp[7];$return"; + } + else { $return = "$quota_usr[$i][1],0,0,0,0,0,0,0,0;$return"; } + $i++; + } + last switch2; + }; + } + last switch; + }; + } + else { + $return = "Got you, stupid hacker.\n"; + } + } + } + else { $return = "Invalid Password"; } + $ldap->unbind(); # Clode ldap connection. + } + else { $return = "Invalid User"; } + open ( FIFO, '> lamdaemon.fifo' ) or die ('Can\'t open fifo lamdaemon.fifo.'); # Open Fifo + print FIFO $return; + close FIFO; # Close fifo. + print "$return\n"; + } diff --git a/lam/templates/account.php b/lam/templates/account.php index 0be30415..72f5637a 100644 --- a/lam/templates/account.php +++ b/lam/templates/account.php @@ -38,6 +38,7 @@ if ( $_GET['type'] ) { // Type is true if account.php was called from Users/Grou $_SESSION['account_temp'] = ""; // Delete $_SESSION['account_temp'] because values are now invalid $_SESSION['modify'] = 0; // Set modify back to false $_SESSION['shelllist'] = getshells(); // Write List of all valid shells in variable + //if (($_GET['type']=='user')||($_GET['type']=='group')) getquotas(); } if ( $_GET['DN'] ) { // $DN is true if an entry should be modified and account.php was called from Users/Group/Host-List @@ -102,7 +103,7 @@ switch ($_POST['select']) { $error = checkunix(); // account.inc // Check which part Site should be displayd if ($_POST['back'] && ($error=="0")) $select_local = 'general'; - if ($_POST['genpass'] && ($error=="0")) $select_local = 'unix'; + if ($_POST['genpass']) $select_local = 'unix'; if ($_POST['next'] && ($error=="0")) $select_local = 'samba'; break; case 'samba': @@ -145,6 +146,15 @@ switch ($_POST['select']) { } break; case 'quota': + $i=0; + while ($_SESSION['account']->quota[$i][0]) { + $_SESSION['account_temp']->quota[$i][2] = $_POST['f_quota_'.$i.'_2']; + $_SESSION['account_temp']->quota[$i][3] = $_POST['f_quota_'.$i.'_3']; + $_SESSION['account_temp']->quota[$i][6] = $_POST['f_quota_'.$i.'_6']; + $_SESSION['account_temp']->quota[$i][7] = $_POST['f_quota_'.$i.'_7']; + $i++; + } + $error = checkquota(); // Check which part Site should be displayd if ($_POST['back'] && ($error=="0")) switch ($_SESSION['type2']) { @@ -244,7 +254,6 @@ if ($_POST['save']) $select_local='save'; - switch ($select_local) { case 'general': // General Account Settings @@ -648,12 +657,27 @@ switch ($select_local) { break; case 'quota': // Quota Settings - echo ' - '; + echo ''; echo _('Quota Properties'); - echo ' + echo ''; echo _('Mointpoint'); echo ''; echo _('used blocks'); echo ''; + echo _('soft block limit'); echo ''; echo _('hard block limit'); echo ''; echo _('grace block period'); + echo ''; echo _('used inodes'); echo ''; echo _('soft inode limit'); echo ''; + echo _('hard inode limit'); echo ''; echo _('grace inode period'); echo ''; + $i=0; + while ($_SESSION['account']->quota[$i][0]) { + echo ''.$_SESSION['account']->quota[$i][0].''.$_SESSION['account']->quota[$i][1].''; // used blocks + echo ''; // blocks soft limit + echo ''; // blocks hard limit + echo ''.$_SESSION['account']->quota[$i][4].''; // block grace period + echo ''.$_SESSION['account']->quota[$i][5].''; // used inodes + echo ''; // inodes soft limit + echo ''; // inodes hard limit + echo ''.$_SESSION['account']->quota[$i][8].''; // inodes grace period + $i++; + } + echo ' - + '; break; @@ -741,6 +765,14 @@ switch ($select_local) { echo ''; } break; + case 'host': + if (($_SESSION['modify']==1) && ($_SESSION['account']->general_uidNumber != $_SESSION['account_old']->general_uidNumber)) { + echo ''; + StatusMessage ('INFO', _('UID-number has changed. You have to run the following command as root in order to change existing file-permissions:'), + 'find / -gid ' . $_SESSION['account_old' ]->general_uidNumber . ' -exec chown ' . $_SESSION['account']->general_uidNumber . ' {} \;'); + echo ''; + } + break; } echo ''; echo '