<?
include "ldap.inc";

define(SUFFIX"PUT YOUR LDAP SUFFIX HERE (ie dc=example,dc=com)");
define(UIDFILE"/usr/local/lib/next-uid-ldap");
define(NAME"uid");
define(UID"uidnumber");

if (
SUFFIX "PUT YOUR LDAP SUFFIX HERE (ie dc=example,dc=com)")
{
    die(
"You must edit the users.inc file and modify the Suffix defninition\nYou may also want to view the genHomeDir and validUserName functions\n");
}


class 
USER
{
    var 
$username;
    var 
$password;
    var 
$uid;
    var 
$gid;
    var 
$gecos;
    var 
$status;
    var 
$error;
    var 
$ldap;

    function 
genHomeDir($username)
    {
        
$home ereg_replace("(.)(.)(.*)""/export/home/\\1/\\2/$username"$name);
        return(
$home);
    }

    function 
validUserName($username)
    {
        if ((
strlen($username) < 2) || (strlen($username) > 25) || ereg("[^a-z0-9]+"$username$reg))
            return(
0);
        return(
1);
    }

    function 
add($username$password$crypted$uid=""$gecos="")
    {
        if (! 
$this->ldap)
            
$this->ldap = new LDAP();

        if (! 
$gecos)
            
$gecos $username;
        
$attrs["objectclass"][0] = "top";
        
$attrs["objectclass"][1] = "posixAccount";
        
$attrs["objectclass"][2] = "shadowAccount";
        
$attrs["uid"][0] = $username;
        
$this->username $username;
        if (
$crypted// Already encrypted;
            
$attrs["userpassword"][0] = "{crypt}" $password;
        else
            
$attrs["userpassword"][0] = "{crypt}" crypt($password$this->genSalt());
        
$this->password $attrs["userpassword"][0];
        if (
$uid)
            
$attrs["uidnumber"][0] = $uid;
        else
            
$attrs["uidnumber"][0] = $this->getUID();
        
$this->uid $attrs["uidnumber"][0];
        
$attrs["gidnumber"][0] = "1";
        
$this->gid $attrs["gidnumber"][0];
        
$attrs["gecos"][0] = $gecos;
        
$this->gecos $attrs["gecos"][0];
        
$attrs["homedirectory"][0] = $this->genHomeDir($username);
        
$this->gecos $attrs["gecos"][0];
        
$attrs["loginshell"][0] = "/usr/bin/false";
        
$attrs["cn"][0] = $gecos;
        
$attrs["shadowlastchange"][0] = "-1";
        
$attrs["shadowmin"][0] = "-1";
        
$attrs["shadowmax"][0] = "-1";
        
$attrs["shadowwarning"][0] = "-1";
        
$attrs["shadowinactive"][0] = "-1";
        
$attrs["shadowexpire"][0] = "-1";
        
$attrs["shadowflag"][0] = "-1";
        
$attrs["description"][0] = "-1";
        if (!
$this->verifyUser($this))
        {
            
$this->error "Invalid user: " $this->error;
            return(
0);
        }

        
$this->ldap->cd("ou=People," SUFFIX);
        
$this->ldap->mkdir("uid"$username);
        
$this->ldap->cd("uid=$username,ou=People," SUFFIX);
        if (! 
$this->ldap->modify($attrs))
        {
            
$this->error "Couldn't create user: " $this->ldap->error;
            return(
0);
        }
        return(
1);
    }

    function 
lock()
    {
        if (! 
$this->username)
        {
            
$this->error "Class not initialized";
            return(
0);
        }

        if (
$this->isLocked())
        {
            
$this->error "user is already locked";
            return(
0);
        }

        if (
$this->changePassword(ereg_replace("^\{crypt\}(.*)$""*LK*\\1"$this->password), 1))
            return(
1);
    }

    function 
unlock()
    {
        if (! 
$this->username)
        {
            
$this->error "Class not initialized";
            return(
0);
        }

        if (! 
$this->isLocked())
        {
            
$this->error "user is not locked";
            return(
0);
        }

        if (
$this->changePassword(ereg_replace("^\{crypt\}\*LK\*(.*)$""\\1"$this->password), 1))
            return(
1);
    }

    function 
isLocked()
    {
        if (
strstr($this->password"*LK*"))
            return(
1);
        return(
0);
    }

    function 
grep($searchtype$spec)
    {
        
$ldap = new LDAP();
        
$users = array();

        if (! 
$this->validSearchType($searchtype))
        {
            
$this->error "'$searchtype' is an invalid type of search";
            return(
0);
        }

        
$ldap->cd("ou=People," SUFFIX);
        if (! 
$ldap->search("($searchtype=*$spec*)"))
            return(array());

        
$ctr 0;
        while (
$attrs $ldap->fetch())
            
$users[$ctr++] = $attrs;
        return(
$users);
    }

    function 
match($searchtype$spec)
    {
        if (! 
$this->ldap)
            
$this->ldap = new LDAP();

        if (! 
$this->validSearchType($searchtype))
        {
            
$this->error "'$searchtype' is an invalid type of search";
            return(array());
        }

        
$users = array();

        
$this->ldap->cd("ou=People," SUFFIX);
        if (! 
$this->ldap->search("($searchtype=$spec)"))
            return(array());

        while (
$attrs $this->ldap->fetch())
            
$users[$this->ldap->getDN()] = $attrs;
        return(
$users);
    }

    function 
validSearchType($searchtype)
    {
        switch (
$searchtype)
        {
            case 
"uid":
            case 
"uidnumber":
                return(
1);
            default:
                return(
0);
        }
    }

    function 
getpwnam($username)
    {
        
$attrs $this->match(NAME$username);
        if (
count($attrs) == 0)
        {
            
$this->error "'$username' does not exist.";
            return(
0);
        }
        if (
count($attrs) > 1)
        {
            
$this->error "User load failed.  The '$username' username is duplicated in the directory.";
            return(
0);
        }
        
$dn key($attrs);
        
$this->username $attrs[$dn]["uid"][0];
        
$this->password $attrs[$dn]["userpassword"][0];
        
$this->uid $attrs[$dn]["uidnumber"][0];
        
$this->gid $attrs[$dn]["gidnumber"][0];
        
$this->gecos $attrs[$dn]["gecos"][0];
        
$this->status $attrs[$dn]["vwaccountstatus"][0];
        return(
1);
    }

    function 
getpwuid($uid)
    {
        
$attrs $this->match(UID$uid);
        if (
count($attrs) == 0)
        {
            
$this->error "'$username' does not exist.";
            return(
0);
        }
        if (
count($attrs) > 1)
        {
            
$this->error "User load failed.  The uid '$uid' is duplicated in the directory.";
            return(
0);
        }
        
$dn key($attrs);
        
$this->username $attrs[$dn]["uid"][0];
        
$this->password $attrs[$dn]["userpassword"][0];
        
$this->uid $attrs[$dn]["uidnumber"][0];
        
$this->gid $attrs[$dn]["gidnumber"][0];
        
$this->gecos $attrs[$dn]["gecos"][0];
        
$this->status $attrs[$dn]["vwaccountstatus"][0];
        return(
1);
    }

    function 
getUID()
    {
        
$er error_reporting(0);
        if (! (
$f fopen(UIDFILE"r+")))
        {
            
$this->error "Couldn't open " UIDFILE;
            
error_reporting($er);
            return(
0);
        }

        
$numtries=0;
        while (
$numtries 10)
        {
            if (
flock($fLOCK_EX LOCK_NB))
            {
                
$uid fgets($f10);
                
$uid chop($uid);
                
rewind($f);
                
ftruncate($f0);
                
$nextuid $uid+1;
                
fputs($f$nextuid);
                
flock($fLOCK_UN);
                
fclose($f);
                
error_reporting($er);
                return(
$uid);
            } else {
                
usleep(100000); // a tenth of a second
                
$numtries++;
            }
        }
        
error_reporting($er);
        return(
0);
    }

    function 
genSalt()
    {
        
srand((double)microtime()*1000000);
        
$saltseeds = array('.','/','0','1','2','3','4','5','6','7','8','9',
                
'a','b','c','d','e','f','g','h','i','j','k','l','m',
                
'n','o','p','q','r','s','t','u','v','w','x','y','z',
                
'A','B','C','D','E','F','G','H','I','J','K','L','M',
                
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z');
        return(
$saltseeds[rand(0,63)] . $saltseeds[rand(0,63)]);
    }

    function 
verifyUser($user)
    {
        if (
$user->uid 100)
        {
            
$this->error "$user->uid is not a valid UID";
            return(
0);
        }
        if (! 
$this->validUserName($user->username))
        {
            
$this->error "$user->username is not a valid username";
            return(
0);
        }
        if (
$this->getpwnam($user->username))
        {
            
$this->error "duplicate username already exists";
            return(
0);
        }
        if (
$this->getpwuid($user->uid))
        {
            
$this->error "duplicate UID already exists";
            return(
0);
        }
        return(
1);
    }

    function 
changePassword($password$crypted 0)
    {
        if (! 
$this->ldap)
            
$this->ldap = new LDAP();
        if (! 
$this->username)
        {
            
$this->error "Class has not been initialized";
            return(
0);
        }

        if (! 
$this->getpwnam($this->username))
        {
            
$this->error "User '$this->username' doesn't exist";
            return(
0);
        }

        if (
$crypted// Already encrypted;
            
$attrs["userpassword"][0] = "{crypt}" $password;
        else
            
$attrs["userpassword"][0] = "{crypt}" crypt($password$this->genSalt());

        
$this->ldap->cd("uid=$this->username,ou=People," SUFFIX);
        if (
$this->ldap->modify($attrs))
            return(
1);
        return(
0);
    }

    function 
delete()
    {
        if (! 
$this->ldap)
            
$this->ldap = new LDAP();
        if (! 
$this->username)
        {
            
$this->error "Class has not been initialized";
            return(
0);
        }

        if (! 
$this->getpwnam($this->username))
        {
            
$this->error "User '$this->username' doesn't exist";
            return(
0);
        }

        if (
$this->ldap->rmdir("uid=$this->username,ou=People," SUFFIX))
            return(
1);
        return(
0);
    }
}

function 
showuserlist($users)
{
    foreach (
$users as $dn => $pw)
        echo 
$pw["uid"][0] . ":" $pw["userpassword"][0] . ":" $pw["uidnumber"][0] . ":" $pw["gidnumber"][0] . ":" $pw["gecos"][0] . ":" $pw["homedirectory"][0] . ":" $pw["loginshell"][0] . "\n";
}


?>