now after you install the packages you start by editing slapd.conf
#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/inetorgperson.schema
include /etc/openldap/schema/nis.schema
pidfile /var/run/slapd.pid
argsfile /var/run/slapd.args
## ACL ##
access to * by * read
#######################################################################
# ldbm and/or bdb database definitions
#######################################################################
database bdb
suffix "dc=lab,dc=local"
rootdn "cn=admin,dc=lab,dc=local"
rootpw {crypt}
defaultaccess read
directory /var/lib/ldap
# Indices to maintain for this database
index objectClass eq,pres
index ou,cn,mail,surname,givenname eq,pres,sub
#index uidNumber,gidNumber,loginShell eq,pres
index uid,memberUid eq,pres,sub
#index nisMapName,nisMapEntry eq,pres,sub
now some concepts (don't rely on me for concepts), these are my 2cents notes on understanding this issue
example of an entry for a user (see how it has DN object to identify it and the a set of attributes for details)
dn: uid=john,ou=people,dc=example,dc=com cn: John Doe uid: john uidNumber: 1001 gidNumber: 100 homeDirectory: /home/john loginShell: /bin/bash objectClass: top objectClass: posixAccount
now the most important thing to do thetrick is to figure out what to put in that ldif file (that took a lot of time and reading, lucky for you i did my homework and you can bypass that time, i hope) here is my sample file
dn: dc=lab, dc=local
objectClass: top
objectclass: organization
objectclass: dcObject
o: Opencraft labs
dc: lab
dn: ou=users,dc=lab, dc=local
ou: users
objectClass: top
objectClass: organizationalUnit
dn: ou=groups,dc=lab, dc=local
ou: groups
objectClass: top
objectClass: organizationalUnit
dn: cn=engineering, ou=groups, dc=lab, dc=local
objectclass: top
objectclass: posixGroup
cn: engineering
gidnumber: 500
memberuid: foo
dn: cn=ramez hanna,ou=users,dc=lab, dc=local
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: organizationalPerson
objectClass: inetOrgPerson
uid: ramez
userpassword: {crypt}
uidnumber: 500
gidnumber: 500
gecos:ramez zoheir hanna
loginShell:/bin/bash
homeDirectory: /home/rhanna
shadowLastChange:10877
shadowMin: 0
shadowMax: 999999
shadowWarning: 7
shadowInactive: -1
shadowExpire: -1
shadowFlag: 0
cn: ramez hanna
givenname: ramez
sn: hanna
mail: me@domain.com
title: CEO
StreetAddress: somewhere
l: cairo
postalCode: huh
telephoneNumber: 54545454
homephone: 454545454
mobile: 555555555
facsimileTelephoneNumber: 555555
references : scripts:
srand (time());
my $randletter = "(int (rand (26)) + (int (rand (1) + .5) % 2 ? 65 : 97))";
my $salt = sprintf ("%c%c", eval $randletter, eval $randletter);
my $plaintext = <STDIN>;
my $crypttext = "{CRYPT}".crypt ($plaintext, $salt);
#!/usr/bin/perl
use Net::LDAP;
# configuration section
# edit the next lines to meet your environment
#
$server = "ldap.opencraft.local";
$suffix = "dc=opencraft,dc=local";
$rootdn = "cn=admin,$suffix"; #if not present the script will ask for it
$ou = "ou=People";
$gou = "ou=Group";
$homeDir = "/home/";
# end of configuration
$action = shift;
if ($action eq "useradd") {
$username = shift;
$options = shift;
$groupname = $username;
$_ = $options;
if (/^-g/) {
$groupname = $';
}
ifexist($username,"user","exit");
ifexist($groupname,"group","exit");
adduser();
addgroup($groupname,"auto");
}
elsif ($action eq "groupadd") {
$group = shift;
ifexist($group,"group","exit");
$idNumber = generate_uid_num();
addgroup($group,"user");
}
elsif ($action eq "passwd") {
$username = shift;
print "changing password for user $username";
ifexist($username,"user","continue");
`ldappasswd -x -v -S -w secret -Dcn=admin,dc=opencraft,dc=local uid=$username,ou=People,dc=opencraft,dc=local`;
}
elsif ($action eq "usermod") {
$username = shift;
$changes = shift;
ifexist($username,"user","continue");
usermod();
}
else {
die "you have to specify an action";
}
################################ sub routines ##############################
#
# connect to ldap server
sub ldapconnect {
$ldap = Net::LDAP->new( $server, version => 3 ) or die "new failed : $!";
$ldap->bind( $rootdn,password => 'secret') or die "cannot bind :$!";
}
# disconnect from the server
sub ldapdisconnect {
$ldap->unbind;
}
# add a user
sub adduser {
open(TMP,">/tmp/ldapuser.tmp") || die "cannot cache data: $1";
open(TEMPLATE,"< adduser.ldif") || die "cannot read template file: $!";
while (<TEMPLATE>) {
if (!/^#/) {
@field = split(/:/,$_);
if ($field[1,1] eq "") {
if ($field[1,0] eq "dn") {
$field[1,1] = "uid=$username,$ou,$suffix\n";
}
elsif ($field[1,0] eq "uid") {
$field[1,1] = $username."\n";
}
elsif ($field[1,0] eq "userPassword") {
print "enter value of $field[1,0]-$field[1,2]";
$crypted = generate_pass();
$field[1,1] = $crypted."\n";
}
elsif ($field[1,0] eq "uidNumber") {
$idNumber = generate_uid_num();
$field[1,1] = $idNumber."\n";
}
elsif ($field[1,0] eq "gidNumber") {
$field[1,1] = $idNumber."\n";
}
elsif ($field[1,0] eq "homeDirectory") {
$field[1,1] = $homeDir.$username."\n";
}
elsif ($field[1,0] eq "cn") {
print "enter value of $field[1,0]-$field[1,2]";
my $name = <STDIN>;
$name =~ s/\n//;
$field[1,1] = $name."\n";
}
else {
print "enter value of $field[1,0]-$field[1,2]";
$field[1,1] = <STDIN>;
}
}
print TMP "$field[1,0]:$field[1,1]";
}
}
close (TMP);
print "adding user $username to LDAP . . .";
`ldapadd -x -w secret -D"$rootdn" -f /tmp/ldapuser.tmp`;
print "user added\n";
print "creating home folder . . .";
system ("cp -Rfa /etc/skel/ $homeDir$username & chown -R $username:$username $homeDir$username");
}
# encrypt the password using {crypt}
sub generate_pass {
srand (time());
my $randletter = "(int (rand (26)) + (int (rand (1) + .5) % 2 ? 65 : 97))";
my $salt = sprintf ("%c%c", eval $randletter, eval $randletter);
my $plaintext = <STDIN>;
my $crypttext = "{CRYPT}".crypt ($plaintext, $salt);
return $crypttext;
}
# get the latest uid/gid number to get a new uid for the user or the group
sub generate_uid_num {
ldapconnect();
$searchbase = $suffix;
my $filter = "!(uidNumber=65534)";
my $attrs = "";
my $results = $ldap->search(base=>$searchbase,filter=>$filter,attrs=>$attrs);
my $count = $results->count;
my $entry;
my $list;
for (my $i=0; $i<$count; $i++) {
$entry = $results->entry($i);
if (($entry->get_value('uidNumber')>499 and $entry->get_value('uidNumber')<65534)or($entry->get_value('gidNumber')>499 and $entry->get_value('gidNumber')<65534)) {
$list = $list.",".$entry->get_value('uidNumber').",".$entry->get_value('gidNumber');
}
}
ldapdisconnect();
my @uids = split(/,/,$list);
@uids = sort { $a <=> $b } @uids;
my $count = @uids;
my $last = $uids[$count-1];
my $newuid = $last+1;
return $newuid;
}
# add a group
sub addgroup {
my $name = @_[0];
my $mode = @_[1];
open(TMP2,">/tmp/ldapgroup.tmp") || die "cannot cache data: $1";
open(TEMPLATE2,"< addgroup.ldif") || die "cannot read template file: $!";
while (<TEMPLATE2>) {
if (!/^#/) {
@field = split(/:/,$_);
if ($field[1,1] eq "") {
if ($field[1,0] eq "dn") {
$field[1,1] = "cn=$name,$gou,$suffix\n";
print TMP2 "$field[1,0]:$field[1,1]";
}
elsif ($field[1,0] eq "gidNumber") {
$field[1,1] = $idNumber."\n";
print TMP2 "$field[1,0]:$field[1,1]";
}
elsif ($field[1,0] eq "cn") {
$field[1,1] = $name."\n";
print TMP2 "$field[1,0]:$field[1,1]";
}
elsif ($field[1,0] eq "memberUid") {
if ($mode eq "user") {
print "enter value of $field[1,0]-$field[1,2]";
my $input = <STDIN>;
chomp ($input);
my @members = split(/,/,$input);
ldapconnect();
foreach $member (@members) {
$searchbase = $ou.",".$suffix;
my $filter = "uid=$member";
my $attrs = "uidNumber";
my $results = $ldap->search(base=>$searchbase,filter=>$filter,attrs=>$attrs);
my $entry = $results->entry(0);
my $memberUid = $entry->get_value('uidNumber');
$field[1,1] ="$memberUid\n";
print TMP2 "$field[1,0]:$field[1,1]";
}
ldapdisconnect();
}
elsif ($mode eq "auto") {
$field[1,1] = $idNumber;
print TMP2 "$field[1,0]:$field[1,1]";
}
}
}
else { print TMP2 "$field[1,0]:$field[1,1]"; }
}
}
close (TMP);
print "adding group $group to LDAP . . .";
`ldapadd -x -w secret -D"$rootdn" -f /tmp/ldapgroup.tmp`;
print "group added\n";
}
# modify the users attributes
sub usermod {
my %ReplaceHash = ( keyword => "x", proxy => "x" );
my $result = LDAPmodifyUsingHash ( $ldap, $dn, \%ReplaceHash );
my $result = $ldap->modify ( $dn,replace => { %$whatToChange } );
return $result;
}
# check if user/group exists
sub ifexist {
ldapconnect();
my ($attrib,$entity,$action) = @_;
my $searchbas,$filter,$attrs;
if ($entity eq "group") {
$searchbase = $gou.",".$suffix;
$filter = "cn=$attrib";
$attrs = "gidNumber";
}
else {
$searchbase = $ou.",".$suffix;
$filter = "uid=$attrib";
$attrs = "uidNumber";
}
my $results = $ldap->search(base=>$searchbase,filter=>$filter,attrs=>$attrs);
my $count = $results->count;
if ($count > 0) {
if ($action eq "exit") {
print STDOUT "dependency failure ( user/group exists\nin case you are adding new user you can use -g with useradd to assign another default group)\n";
exit;
}
}
ldapdisconnect();
}
#adduser.ldif the template for new users #this is the template for creating users #syntax: #attr:value:comment #only missing values will be prompted by the scrip #note that even if you won't have comments you need to add the ":" dn::identifier usually the full name or the username objectClass:top objectClass:person objectClass:posixAccount objectClass:shadowAccount objectClass:organizationalPerson objectClass:inetOrgPerson uid::username userPassword::password not less than 5 char uidNumber:: gidNumber:: gecos::more information divided by commas loginShell:/bin/bash homeDirectory::home folder shadowLastChange:10877 shadowMin:0 shadowMax:999999 shadowWarning:7 shadowInactive:-1 shadowExpire:-1 shadowFlag:0 cn:: givenname::surname sn::full name mail::user's email title::job title StreetAddress::home address l::city telephoneNumber::home phone number mobile::mobile number