Zend - The PHP Company




Miscellaneous

Add Code


shadow.class  

Type: class
Added by: oschlag
Entered: 24/04/2001
Last modified: 04/12/2000
Rating: - (fewer than 3 votes)
Views: 4050
Class to manage User and Group Accounts on Shadow based Linux/Unix Systems


<?php

class shadow {

  
// Class to manage User and Group Accounts on Shadow based Linux/Unix Systems
  // Date     :  04/25/2001
  // Author   :  Oliver Schlag <oliver.schlag@blue-online.de>
  // You can use this class without any warranty. Please report every
  // bug to the Author. If you make changes to this class please report
  // them to the Author, too.

  // To easily manage all accounts we first read them into some arrays.
  // And after making all changes, we write them back to the file. I
  // think thats the fastest way to do the job. Yes it consumes much
  // memory but I think thats not so much important.

  // This is the structure of the files, which we use :
  // /etc/passwd ->        Username:x:UID:GID:GCOS:Home:Shell
  // /etc/shadow ->        Username:Password:DOC:MindD:MaxD:Warn:Exp:Dis:Res
  // /etc/group  ->        Groupname:Password:GID:Member
  // /etc/gshadow->        Groupname:Password:Groupmanager:Member

  // To prevent, that two jobs are using the user and Group Files we
  // create a simple lock file, and if it the file exists at startup
  // we do nothing.

  // All functions in this class return TRUE on success and FALSE on error,
  // so you can easily catch all errors. All errors of this function are
  // stored in the variable $ERROR_MSG. You can then read it and provide
  // a custom error message.

  // You can use the following functions in your applications :
  // int user_add (username,userid,primary_group,name,shell,homedir,password);
  // int user_del (username);
  // int user_mod (username,new_name,new_shell,new_password);
  // int group_add (groupname,member,password,manager);
  // int group_del (groupname);
  // int group_mod(groupname,new_name);
  // int add_to_group(groupname,username);
  // int del_from_group(groupname,username);
  // int del_from_all_groups(username);

  // There are 2 more functions, which provide some simple constructor and
  // destructor functions for the class. So you had to call the constructor
  // first, then use the functions and then call the destructor to write all
  // data back into the files and remove the lock file.

  // int start_shadow(enable_logging);      ->         The pseudo constructor
  // int stop_shadow();                     ->         The pseudo destructor

  // If you like, you can activate the logging into your syslog, so all actions
  // somebody makes, will be reported to it. To do this call the pseudo constructor
  // with a 1 as first parameter.

  // We use the following arrays to manage the user and group Accounts in memory
  // $user["username"] = Username;
  // $user["password"] = Password;
  // $user["uid"] = UserID;
  // $user["gid"] = GroupID;
  // $user["gcos"] = Real Name;
  // $user["home"] = Homedir;
  // $user["shell"] = Shell;
  // $user["doc"] = Date of last password change in days from the 1.1.1970
  // $user["mind"] = Minimal days the password is valid
  // $user["maxd"] = Maximum days the password is valid
  // $user["warn"] = Number of days before the user recives a message that he should change his password
  // $user["exp"] = After maxd, how many days is the password still valid
  // $user["dis"] = Up to this day (counted from 1.1.1970) the account is locked

  // $group["groupname"] = Groupname;
  // $group["password"] = Password;
  // $group["gid"] = GroupID;
  // $group["member"] = Comma seperated list of members;
  // $group["manager"] = Comma seperated list of group managers;

  // $homed["dir"] = Homedirectory;
  // $homed["user"] = User which this directory belongs to;
  // $homed["group"] = The group which this directory belongs to;
  // All homedirectorys are chmoded 755;

  
VAR $ERROR_MSG;
  VAR 
$LOGGING;          //    Tells us if syslog logging is enabled or not
  
VAR $STARTED;          //    Keeps track if the constructor was called
  
VAR $USERDATA;         //    Here are all arrays of the type $user are stored in
  
VAR $GROUPDATA;        //    Here are all arrays of the type $group are stored in
  
VAR $FASTSEEK;         //    Little Array which contains number to name assignments for usernames
  
VAR $GFASTSEEK;        //    Little Array which contains number to name assignments for groupnames
  
VAR $HOMEDIRS;         //    The homedirectorys which have to be created;
  
VAR $STARTUID;         //    The first UserID a user can have
  
VAR $STARTGID;         //    The first GroupID a group can have

  
function start_shadow($enable_logging 0)
  {
   
// Set logging state
   
$this->LOGGING $enable_logging;

   
// Set the minimum UserID
   
$this->STARTUID 100;

   
// Set the minimum GroupID
   
$this->STARTGID 100;

   
// This is the lockfile for this class
   
$lockfile "/var/lock/shadow.class.lock";

   
// Check if a log file exists, if not create one
   
if (file_exists($lockfile))
   {
     
$this->ERROR_MSG "Lockfile exists";
     
$this->STARTED 0;
     if (
$this->LOGGING == 1)
     {
      
syslog(LOG_NOTICE,"Could not start shadow class. Lockfile exists.");
     }
     return 
FALSE;
   }
   else
   {
     
$fp fopen($lockfile,"w");
     
fputs($fp," ");
     
fclose($fp);
   }

   
// Read the shadow user file into the array
   
$sp fopen("/etc/shadow","r");
   
$i 0;

   while(!
feof($sp))
   {
    
$temp fgets($sp,8069);
    
$temp rtrim(ereg_replace("n"," ",$temp));
    
$temp explode(":",$temp);

    
$user["username"] = $temp[0];
    
$user["password"] = $temp[1];
    
$user["doc"] = $temp[2];
    
$user["mind"] = $temp[3];
    
$user["maxd"] = $temp[4];
    
$user["warn"] = $temp[5];
    
$user["exp"] = $temp[6];
    
$user["dis"] = $temp[7];
    
$temp $user["username"];

    
$this->USERDATA[$i] = $user;
    
$this->FASTSEEK[$temp] = $i;
    
$i++;
   }

   
fclose($sp);

   
$pp fopen("/etc/passwd","r");
   while(!
feof($pp))
   {
    
$temp fgets($pp,8096);
    
$temp rtrim(ereg_replace("n"," ",$temp));
    
$temp explode(":",$temp);
    
$username $temp[0];
    
$i = -1;
    
$i $this->FASTSEEK[$username];

    if ( 
$i != -)
    {
     
$this->USERDATA[$i]["uid"] = $temp[2];
     
$this->USERDATA[$i]["gid"] = $temp[3];
     
$this->USERDATA[$i]["gcos"] = $temp[4];
     
$this->USERDATA[$i]["home"] = $temp[5];
     
$this->USERDATA[$i]["shell"] = $temp[6];
    }
   }

  
fclose($pp);

  
// Now we read all groups into another array

  
$gp fopen("/etc/group","r");
  
$i 0;
  while(!
feof($gp))
  {
   
$temp fgets($gp,8096);
   
$temp rtrim(ereg_replace("n"," ",$temp));
   
$temp explode(":",$temp);

   
$group["groupname"] = $temp[0];
   
$group["gid"] = $temp[2];
   
$group["member"] = $temp[3];
   
$temp $group["groupname"];

   
$this->GROUPDATA[$i] = $group;
   
$this->GFASTSEEK[$temp] = $i;
   
$i++;
  }

  
fclose($gp);

  
$gs fopen("/etc/gshadow","r");
  
$i = -1;
  while(!
feof($gs))
  {
   
$temp fgets($gs,8096);
    
$temp rtrim(ereg_replace("n"," ",$temp));
   
$temp explode(":",$temp);
   
$groupname $temp[0];
   
$i $this->GFASTSEEK[$groupname];

   if ( 
$i != -)
   {
    
$this->GROUPDATA[$i]["password"] = $temp[1];
    
$this->GROUPDATA[$i]["manager"] = $temp[2];
   }
  }
  
fclose($gs);

  if (
$this->LOGGING == 1)
  {
    
syslog(LOG_NOTICE,"Shadow Class initalized.");
  }

  return 
TRUE;
  
//      End of pseudo constructor
  
}

  function 
stop_shadow()
  {
     
// This is the lockfile for this class
     
$lockfile "/var/lock/shadow.class.lock";

    
// To avoide damages to production files, we make backup copies
    // of the original files. We delete them at the next run.

    
if(file_exists("/etc/passwd-backup"))
    {
      
unlink("/etc/passwd-backup");
    }
    
copy("/etc/passwd","/etc/passwd-backup");
    if(
file_exists("/etc/shadow-backup"))
    {
      
unlink("/etc/shadow-backup");
    }
    
copy("/etc/shadow","/etc/shadow-backup");
    if(
file_exists("/etc/group-backup"))
    {
      
unlink("/etc/group-backup");
    }
    
copy("/etc/group","/etc/group-backup");
    if(
file_exists("/etc/gshadow-backup"))
    {
      
unlink("/etc/gshadow-backup");
    }
    
copy("/etc/gshadow","/etc/gshadow-backup");

    if (
$this->LOGGING == 1)
    {
      
syslog(LOG_NOTICE,"Backup files created in /etc");
    }

    
// Write back all user informations into the correct files;

    
$pf fopen("/etc/passwd","w");
    
$sf fopen("/etc/shadow","w");
    for ( 
$i $i count($this->USERDATA) ; $i++ )
    {
      if (
$this->USERDATA[$i]["username"] != "")
      {
       
$passwd "n".$this->USERDATA[$i]["username"].":x:".$this->USERDATA[$i]["uid"].":".$this->USERDATA[$i]["gid"].":".$this->USERDATA[$i]["gcos"].":".$this->USERDATA[$i]["home"].":".$this->USERDATA[$i]["shell"];
       
$shadow "n".$this->USERDATA[$i]["username"].":".$this->USERDATA[$i]["password"].":".$this->USERDATA[$i]["doc"].":".$this->USERDATA[$i]["mind"].":".$this->USERDATA[$i]["maxd"].":".$this->USERDATA[$i]["warn"].":".$this->USERDATA[$i]["exp"].":".$this->USERDATA[$i]["dis"].":";
       
fputs($pf,$passwd);
       
fputs($sf,$shadow);
      }
    }
    
fclose($pf);
    
fclose($sf);

    
// Write all group informations into the correct files;

    
$gf fopen("/etc/group","w");
    
$sg fopen("/etc/gshadow","w");
    for ( 
$i $i count ($this->GROUPDATA) ; $i++ )
    {
      if (
$this->GROUPDATA[$i]["groupname"] != "")
      {
       
$group "n".$this->GROUPDATA[$i]["groupname"].":x:".$this->GROUPDATA[$i]["gid"].":".$this->GROUPDATA[$i]["member"];
       
$gshadow "n".$this->GROUPDATA[$i]["groupname"].":".$this->GROUPDATA[$i]["password"].":".$this->GROUPDATA[$i]["manager"].":".$this->GROUPDATA[$i]["member"];
       
fputs($gf,$group);
       
fputs($sg,$gshadow);
      }
    }
    
fclose($gf);
    
fclose($sg);

    if (
$this->LOGGING == 1)
    {
      
syslog(LOG_NOTICE,"User and Group Database generated");
    }

    
// Create or delete homedirectorys and set permissions;

    
for ( $i $i count($this->HOMEDIRS) ; $i++ )
    {
      if (
$this->HOMEDIRS[$i]["action"] == "create")
      {
       
mkdir($this->HOMEDIRS[$i]["dir"],0755);
       
chown($this->HOMEDIRS[$i]["dir"],$this->HOMEDIRS[$i]["user"]);
       
chgrp($this->HOMEDIRS[$i]["dir"],$this->HOMEDIRS[$i]["group"]);
       if (
$this->LOGGING == 1)
       {
        
syslog(LOG_NOTICE,"User : ".$this->HOMEDIRS[$i]["user"]." created");
       }
      }
      else
      {
       
$cmd "/bin/rm -R ".$this->HOMEDIRS[$i]["dir"];
       
$res exec($cmd);
       if (
$this->LOGGING == 1)
       {
        
syslog(LOG_NOTICE,"User : ".$this->HOMEDIRS[$i]["user"]." deleted");
       }
      }
    }

    if (
$this->LOGGING == 1)
    {
      
syslog(LOG_NOTICE,"Homedirectorys created and deleted");
    }

    
unlink($lockfile);

    if (
$this->LOGGING == 1)
    {
      
syslog(LOG_NOTICE,"Shadow class ended");
    }

  RETURN 
TRUE;
  
// End of pseudo destructor
  
}

  function 
user_add($username,$uid,$group,$gcos,$shell,$home,$password)
  {
   if (
$username == "")
   {
     
$this->ERROR_MSG "NO Username specified";
     RETURN 
FALSE;
   }

   if (
$uid || $uid 64999)
   {
     
$this->ERROR_MSG "Incorrect UserID";
     RETURN 
FALSE;
   }

   if (
$home == "")
   {
     
$this->ERROR_MSG "Please provide a home directory !";
     RETURN 
FALSE;
   }

   for ( 
$i $i count($this->USERDATA) ; $i++ )
   {
     if ( 
$this->USERDATA[$i]["uid"] == $uid )
     {
       
$this->ERROR_MSG "Userid already exists";
       RETURN 
FALSE;
     }
   }

   
$i count($this->USERDATA);
   
$this->USERDATA[$i]["username"] = $username;
   
$this->USERDATA[$i]["password"] = crypt($password);
   
$this->USERDATA[$i]["uid"] = $uid;
   
$this->USERDATA[$i]["gid"] = $this->group_to_gid($group);
   
$this->USERDATA[$i]["gcos"] = $gcos;
   
$this->USERDATA[$i]["home"] = $home;
   
$this->USERDATA[$i]["shell"] = $shell;
   
$doc time() / 86400;
   
$doc explode(".",$doc);
   
$this->USERDATA[$i]["doc"] = $doc[0];
   
$this->USERDATA[$i]["mind"] = "";
   
$this->USERDATA[$i]["maxd"] = "";
   
$this->USERDATA[$i]["warn"] = "";
   
$this->USERDATA[$i]["exp"] = "";
   
$this->USERDATA[$i]["dis"] = "";

   
$i count($this->HOMEDIRS);
   
$this->HOMEDIRS[$i]["action"] = "create";
   
$this->HOMEDIRS[$i]["dir"] = $home;
   
$this->HOMEDIRS[$i]["user"] = $username;
   
$this->HOMEDIRS[$i]["group"] = $group;

   
$this->FASTSEEK[$username] = $i;

   if (!
$this->add_to_group($group,$username))
   {
      
$this->ERROR_MSG "Could not add user ".$username." to group ".$group;
      unset(
$this->USERDATA[count($this->USERDATA)]);
      RETURN 
FALSE;
   }

   RETURN 
TRUE;
   
// End of user_add
  
}

  function 
user_del($username)
  {
    if ( 
$username == "" )
    {
      
$this->ERROR_MSG "No Username specified !";
      RETURN 
FALSE;
    }

    for ( 
$i $i count($this->USERDATA) ; $i++ )
    {
      if ( 
$this->USERDATA[$i]["username"] == $username )
      break;
    }

    
$this->del_from_all_groups($username);
    
$j count($this->HOMEDIRS);
    
$this->HOMEDIRS[$j]["action"] = "delete";
    
$this->HOMEDIRS[$j]["dir"] = $this->USERDATA[$i]["home"];
    
$this->HOMEDIRS[$j]["user"] = $username;
    unset(
$this->USERDATA[$i]);
    RETURN 
TRUE;
    
// End of user_del

    
unset($this->FASTSEEK[$username]);
  }

  function 
user_mod($username,$new_gcos,$new_shell,$new_password)
  {
    if ( 
$username == "" )
    {
      
$this->ERROR_MSG "No Username specified !";
      RETURN 
FALSE;
    }
    else
    {
      for ( 
$i $i count($this->USERDATA) ; $i++ )
      {
        if ( 
$this->USERDATA[$i]["username"] == $username )
          break;
      }

      if ( 
$new_gcos != "" )
      {
        
$this->USERDATA[$i]["gcos"] = $new_gcos;
      }

      if ( 
$new_shell != "" )
      {
        
$this->USERDATA[$i]["shell"] = $new_shell;
      }

      if ( 
$new_password != "" )
      {
        
$this->USERDATA[$i]["password"] = crypt($new_password);
      }
    }

    RETURN 
TRUE;
    
// End of user_mod
  
}

  function 
group_add($groupname,$member "",$password "",$manager "")
  {
    if (
$groupname == "")
    {
      
$this->ERROR_MSG "No groupname specified";
      RETURN 
FALSE;
    }

    
$i count($this->GROUPDATA);

    
$this->GROUPDATA[$i]["groupname"] = $groupname;
    if (
$password != "")
    {
      
$this->GROUPDATA[$i]["password"] = crypt($password);
    }
    else
    {
      
$this->GROUPDATA[$i]["password"] = "";
    }
    
$this->GROUPDATA[$i]["gid"] = $this->get_next_gid();
    
$this->GROUPDATA[$i]["member"] = $member;
    
$this->GROUPDATA[$i]["manager"] = $manager;

    
$this->GFASTSEEK[$groupname] = $i;
    RETURN 
TRUE;
  }

  function 
group_del($groupname)
  {
    
$i $this->GFASTSEEK[$groupname];
    unset(
$this->GROUPDATA[$i]);
    unset(
$this->GFASTSEEK[$groupname]);
    RETURN 
TRUE;
  }

  function 
group_mod($groupname,$new_name)
  {
   if (
$groupname == "")
   {
     
$this->ERROR_MSG "No Groupname specified";
     RETURN 
FALSE;
   }

   if (
$new_name == "")
   {
     
$this->ERROR_MSG "No new Groupname specified";
     RETURN 
FALSE;
   }

   
$i $this->GFASTSEEK[$groupname];
   if (!isset(
$i))
   {
     
$this->ERROR_MSG "Group does not exist";
     return 
FALSE;
   }

   
$this->GROUPDATA[$i]["groupname"] = $new_name;
   RETURN 
TRUE;
  }

  function 
add_to_group($groupname,$user)
  {
    
$i $this->GFASTSEEK[$groupname];
    if (
$i == "")
    {
      
$this->ERROR_MSG "Group does not exist";
      return 
FALSE;
    }

    
$member $this->GROUPDATA[$i]["member"];
    
$member explode(",",$member);
    
$memcount count($member);
    
$member[$memcount] = $user;

    for ( 
$j 0$j <= $memcount$j++ )
    {
      if ( 
$j == 0)
      {
        
$new_member $member[$j];
      }
      else
      {
        
$new_member $new_member.",".$member[$j];
      }
    }

    
$this->GROUPDATA[$i]["member"] = $new_member;

    RETURN 
TRUE;
  }

  function 
del_from_group($groupname,$user)
  {
    
$i $this->GFASTSEEK[$groupname];
    if (!isset(
$i))
    {
      
$this->ERROR_MSG "Group does not exist";
      return 
FALSE;
    }

    
$member $this->GROUPDATA[$i]["member"];
    
$member explode(",",$member);
    
$memcount count($member);

    for ( 
$j 0$j $memcount$j++)
    {
      if (
$member[$j] != $user)
      {
        if ( 
$j == )
        {
          
$new_member $member[$j];
        }
        else
        {
          
$new_member $new_member.",".$member[$j];
        }
      }
    }

    
$this->GROUPDATA[$i]["member"] = $new_member;

    RETURN 
TRUE;
  }

  function 
del_from_all_groups($user)
  {
    for (
$i 0$i count($this->GROUPDATA); $i++)
    {
      
$this->del_from_group($this->GROUPDATA[$i]["groupname"],$user);
    }

    RETURN 
TRUE;
  }

  function 
get_next_uid()
  {
    
$uid $this->STARTUID;

    do {
      
$used 0;
      for ( 
$i 0$i count($this->USERDATA); $i++ )
      {
        if ( 
$uid == $this->USERDATA[$i]["uid"] )
        {
          
$used 1;
          
$uid++;
          break;
        }
      }
    } while(
$used == && $uid <= 64999);

    if ( 
$uid <= 64999 )
    {
      return 
$uid;
    }
    else
    {
      
$this->ERROR_MSG "UserID greater than 65000";
      return 
FALSE;
    }
  }

  function 
get_next_gid()
  {
    
$gid $this->STARTGID;

    do {
      
$used 0;
      for ( 
$i 0$i count($this->GROUPDATA); $i++ )
      {
        if ( 
$gid == $this->GROUPDATA[$i]["gid"] && $gid <= 64999)
        {
          
$used 1;
          
$gid++;
          break;
        }
      }
    } while(
$used == && $gid <= 64999);

    if ( 
$gid <= 64999 )
    {
      return 
$gid;
    }
    else
    {
      
$this->ERROR_MSG "GroupID greater than 65000";
      return 
FALSE;
    }
  }

  function 
uid_to_user($uid)
  {
    for ( 
$i 0$i count($this->USERDATA); $i++ )
    {
      if ( 
$uid == $this->USERDATA[$i]["uid"] )
      {
        return 
$this->USERDATA[$i]["username"];
      }
    }
  }

  function 
gid_to_group($gid)
  {
    for ( 
$i 0$i count($this->GROUPDATA); $i++ )
    {
      if ( 
$gid == $this->GROUPDATA[$i]["gid"] )
      {
        return 
$this->GROUPDATA[$i]["groupname"];
      }
    }
  }

  function 
group_to_gid($group)
  {
    for ( 
$i 0$i count($this->GROUPDATA); $i++ )
    {
      if ( 
$group == $this->GROUPDATA[$i]["groupname"] )
      {
        return 
$this->GROUPDATA[$i]["gid"];
      }
    }
  }

  function 
user_to_uid($user)
  {
    for ( 
$i 0$i count($this->USERDATA); $i++ )
    {
      if ( 
$user == $this->USERDATA[$i]["username"] )
      {
        return 
$this->USERDATA[$i]["uid"];
      }
    }
  }

  function 
show_all()
  {
    for ( 
$i 0$i count($this->USERDATA); $i++)
    {
     while (list(
$key$val) = each($this->USERDATA[$i]))
     {
       echo 
"$key => $valn";
     }
    }
    for ( 
$i 0$i count($this->GROUPDATA); $i++)
    {
     while (list(
$key$val) = each($this->GROUPDATA[$i]))
     {
       echo 
"$key => $valn";
     }
    }
  }

// End of class
}
?>


Usage Example


<?php

include("shadow.class.php");

$user = new shadow;

if(
$user->start_shadow(1))
{
  echo 
"Free User ID : ".$user->get_next_uid()."n";
  echo 
"Free Group ID : ".$user->get_next_gid()."n";
  echo 
"oschlag Uid : ".$user->user_to_uid("oschlag")."n";
  echo 
"oschlag Name : ".$user->uid_to_user($user->user_to_uid("oschlag"))."n";
  echo 
"Perl_User GID : ".$user->group_to_gid("Perl_User")."n";
  echo 
"Add user ostestn";
  if (!
$user->user_add("ostest",$user->get_next_uid(),"Perl_User","Olivers Tester","/bin/bash","/home/sites/site3/users/ostst","hubba"))
  {
    echo 
$user->ERROR_MSG."n";
  }
  echo 
"Free User ID : ".$user->get_next_uid()."n";
  echo 
"ostest Name : ".$user->uid_to_user("101")."n";
  echo 
"ostest Uid : ".$user->user_to_uid("ostest")."n";
  echo 
"Add user ostest to group wheeln";
  if (!
$user->add_to_group("wheel","ostest"))
  {
    echo 
$user->ERROR_MSG."n";
  }
  echo 
"Delete user ostestn";
  if (!
$user->user_del("ostest"))
  {
    echo 
$user->ERROR_MSG."n";
  }
  echo 
"Free User ID : ".$user->get_next_uid()."n";
  echo 
"ostest Name : ".$user->uid_to_user("101")."n";
  echo 
"ostest Uid : ".$user->user_to_uid("ostest")."n";
  echo 
"Add group ostestn";
  if (!
$user->group_add("ostest"))
  {
    echo 
$user->ERROR_MSG."n";
  }
  echo 
"Free Group ID : ".$user->get_next_gid()."n";
  echo 
"ostest Name : ".$user->gid_to_group("103")."n";
  echo 
"ostest GID : ".$user->group_to_gid("ostest")."n";
  echo 
"Delete group ostestn";
  if (!
$user->group_del("ostest"))
  {
    echo 
$user->ERROR_MSG."n";
  }
  echo 
"Free Group ID : ".$user->get_next_gid()."n";
  echo 
"ostest Name : ".$user->gid_to_group("103")."n";
  echo 
"ostest GID : ".$user->group_to_gid("ostest")."n";

  
$user->stop_shadow();
}
else
{
  echo 
$user->ERROR_MSG."n";
}

?>


Rate This Script





Search



This Category All Categories