summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2002-06-17 18:36:36 +0000
committerGerald Carter <jerry@samba.org>2002-06-17 18:36:36 +0000
commit1e6e5b299c235b513095a76a4cd9fffc41e8fc9c (patch)
tree9f741529073ad411cc7328334e26d3e35b1d33f1 /examples
parenta11c5d7ad07d259d764aede4745d13f8163a8212 (diff)
downloadsamba-1e6e5b299c235b513095a76a4cd9fffc41e8fc9c.tar.gz
samba-1e6e5b299c235b513095a76a4cd9fffc41e8fc9c.tar.xz
samba-1e6e5b299c235b513095a76a4cd9fffc41e8fc9c.zip
beginning to sync up for 2.2.5 release....
Diffstat (limited to 'examples')
-rw-r--r--examples/LDAP/README31
-rw-r--r--examples/LDAP/export2_smbpasswd.pl64
-rw-r--r--examples/LDAP/export_smbpasswd.pl51
-rw-r--r--examples/LDAP/import2_smbpasswd.pl108
-rw-r--r--examples/LDAP/import_smbpasswd.pl122
-rw-r--r--examples/LDAP/samba-schema-netscapeds4.x2
-rw-r--r--examples/LDAP/samba-schema-netscapeds5.x4
-rw-r--r--examples/LDAP/samba-schema.IBMSecureWay2
-rw-r--r--examples/LDAP/samba.schema16
-rw-r--r--examples/LDAP/smbldap-tools/AUTHORS0
-rw-r--r--examples/LDAP/smbldap-tools/CONTRIBUTORS29
-rw-r--r--examples/LDAP/smbldap-tools/COPYING340
-rw-r--r--examples/LDAP/smbldap-tools/ChangeLog29
-rw-r--r--examples/LDAP/smbldap-tools/FILES43
-rw-r--r--examples/LDAP/smbldap-tools/INFRASTRUCTURE84
-rw-r--r--examples/LDAP/smbldap-tools/INSTALL28
-rw-r--r--examples/LDAP/smbldap-tools/Makefile35
-rw-r--r--examples/LDAP/smbldap-tools/NEWS0
-rw-r--r--examples/LDAP/smbldap-tools/README87
-rw-r--r--examples/LDAP/smbldap-tools/TODO27
-rw-r--r--examples/LDAP/smbldap-tools/cgi/README27
-rwxr-xr-xexamples/LDAP/smbldap-tools/cgi/ldappass.cgi202
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/Makefile62
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/getopt.c756
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/getopt.h133
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/md4.c171
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.c253
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.h17
-rw-r--r--examples/LDAP/smbldap-tools/mkntpwd/smbdes.c337
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-groupadd.pl86
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-groupdel.pl95
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-groupmod.pl213
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-groupshow.pl74
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl236
-rw-r--r--examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl227
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-passwd.pl217
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-populate.pl296
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-tools.spec169
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-useradd.pl462
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-userdel.pl124
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-usermod.pl405
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap-usershow.pl71
-rw-r--r--examples/LDAP/smbldap-tools/smbldap_conf.pm251
-rwxr-xr-xexamples/LDAP/smbldap-tools/smbldap_tools.pm585
-rw-r--r--examples/VFS/.cvsignore4
-rw-r--r--examples/VFS/Makefile35
-rw-r--r--examples/VFS/Makefile.in31
-rw-r--r--examples/VFS/README11
-rw-r--r--examples/VFS/block/Makefile37
-rw-r--r--examples/VFS/block/block.c14
-rwxr-xr-xexamples/VFS/configure1161
-rw-r--r--examples/VFS/configure.in92
-rw-r--r--examples/VFS/recycle.c287
-rw-r--r--examples/VFS/recycle/README83
-rw-r--r--examples/VFS/recycle/cleanup_recycle.pl25
-rw-r--r--examples/VFS/recycle/recycle.c556
-rw-r--r--examples/VFS/recycle/recycle.conf17
-rw-r--r--examples/libsmbclient/testsmbc.c126
-rw-r--r--examples/smb.conf.default459
59 files changed, 8697 insertions, 812 deletions
diff --git a/examples/LDAP/README b/examples/LDAP/README
index 281a66e65aa..c7ff16ad083 100644
--- a/examples/LDAP/README
+++ b/examples/LDAP/README
@@ -4,29 +4,11 @@
!== written by Gerald Carter <jerry@samba.org>
!==
-This is a quick and dirty means of storing smbpasswd entries
-in smbpasswd. Samba 2.2.x does not have any ability to grab
-this information directly from LDAP so you will need to
-periodically generate an smbpasswd from an ldapsearch
-"(objectclass=smbPasswordEntry)".
-
-Be aware of search limits on your client or server which prevent
-all entries from being returned in the search result.
+This is a quick and dirty means of converting smbpasswd entries
+to sambaAccount entriues in an LDAP directory.
Pre-requisites for import_smbpasswd.pl & export_smbpasswd.pl
-------------------------------------------------------------
-You must install Mozilla PerLDAP which is available at:
-
- http://www.mozilla.org/directory
-
-PerLDAP depends on the Netscape (aka iPlanet) C-SDK which is
-available for download at:
-
- http:// www.iplanet.com/downloads/developer/
-
-
-Pre-requisites for import2_smbpasswd.pl & export2_smbpasswd.pl
--------------------------------------------------------------
These two scripts are modified versions of
[import|export]_smbpasswd.pl rewritten to use the Net::LDAP
@@ -36,6 +18,7 @@ perl module available from
+
OpenLDAP 2.0.x
--------------
@@ -68,7 +51,7 @@ You must restart the LDAP server for these new included schema files
to become active.
-import[2]_smbpasswd.pl
+import_smbpasswd.pl
----------------------
Make sure you customize the local site variable in the perl script
@@ -80,17 +63,17 @@ refer to RFC2307 and http://www.padl.com/software.html).
The following will import an smbpasswd file into an LDAP directory
- $ cat smbpasswd | import[2]_smbpasswd.pl
+ $ cat smbpasswd | import_smbpasswd.pl
-export[2]_smbpasswd.pl
+export_smbpasswd.pl
----------------------
Make sure you customize the local site variable in the perl script
(i.e. ldapserver, rootdn, rootpw, etc...). You can then generate
an smbpasswd file by executing
- $ export[2]_smbpasswd.pl > smbpasswd
+ $ export_smbpasswd.pl > smbpasswd
NOTE: Server side (or client side) search limites may prevent
all users from being listed. Check you directory server documentation
diff --git a/examples/LDAP/export2_smbpasswd.pl b/examples/LDAP/export2_smbpasswd.pl
deleted file mode 100644
index 90f5805e55f..00000000000
--- a/examples/LDAP/export2_smbpasswd.pl
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/perl
-##
-## Example script to export ldap entries into an smbpasswd file format
-## using the Mozilla PerLDAP module.
-##
-## writen by jerry@samba.org
-##
-## ported to Net::LDAP by dkrovich@slackworks.com
-
-use Net::LDAP;
-
-######################################################
-## Set these values to whatever you need for your site
-##
-
-$DN="dc=samba,dc=my-domain,dc=com";
-$ROOTDN="cn=Manager,dc=my-domain,dc=com";
-$rootpw = "secret";
-$LDAPSERVER="localhost";
-
-##
-## end local site variables
-######################################################
-
-$ldap = Net::LDAP->new($LDAPSERVER) or die "Unable to connect to LDAP server $LDAPSERVER";
-
-print "##\n";
-print "## Autogenerated smbpasswd file via ldapsearch\n";
-print "## from $LDAPSERVER ($DN)\n";
-print "##\n";
-
-## scheck for the existence of the posixAccount first
-$result = $ldap->search ( base => "$DN",
- scope => "sub",
- filter => "(objectclass=smbpasswordentry)"
- );
-
-
-
-## loop over the entries we found
-while ( $entry = $result->shift_entry() ) {
-
- @uid = $entry->get_value("uid");
- @uidNumber = $entry->get_value("uidNumber");
- @lm_pw = $entry->get_value("lmpassword");
- @nt_pw = $entry->get_value("ntpassword");
- @acct = $entry->get_value("acctFlags");
- @pwdLastSet = $entry->get_value("pwdLastSet");
-
- if (($#uid+1) && ($#uidNumber+1)) {
-
- $lm_pw[0] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" if (! ($#lm_pw+1));
- $nt_pw[0] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" if (! ($#nt_pw+1));
- $acct[0] = "[DU ]" if (! ($#acct+1));
- $pwdLastSet[0] = "FFFFFFFF" if (! ($#pwdLastSet+1));
-
- print "$uid[0]:$uidNumber[0]:$lm_pw[0]:$nt_pw[0]:$acct[0]:LCT-$pwdLastSet[0]\n";
- }
-
-}
-
-$ldap->unbind();
-exit 0;
-
diff --git a/examples/LDAP/export_smbpasswd.pl b/examples/LDAP/export_smbpasswd.pl
index 3f67dc62427..90f5805e55f 100644
--- a/examples/LDAP/export_smbpasswd.pl
+++ b/examples/LDAP/export_smbpasswd.pl
@@ -5,16 +5,16 @@
##
## writen by jerry@samba.org
##
+## ported to Net::LDAP by dkrovich@slackworks.com
-use Mozilla::LDAP::Conn;
-use Mozilla::LDAP::Entry;
+use Net::LDAP;
######################################################
## Set these values to whatever you need for your site
##
-$DN="ou=people,dc=plainjoe,dc=org";
-$ROOTDN="cn=Manager,dc=plainjoe,dc=org";
+$DN="dc=samba,dc=my-domain,dc=com";
+$ROOTDN="cn=Manager,dc=my-domain,dc=com";
$rootpw = "secret";
$LDAPSERVER="localhost";
@@ -22,9 +22,7 @@ $LDAPSERVER="localhost";
## end local site variables
######################################################
-
-$conn = new Mozilla::LDAP::Conn ("$LDAPSERVER", "389", $ROOTDN, $rootpw );
-die "Unable to connect to LDAP server $LDAPSERVER" unless $conn;
+$ldap = Net::LDAP->new($LDAPSERVER) or die "Unable to connect to LDAP server $LDAPSERVER";
print "##\n";
print "## Autogenerated smbpasswd file via ldapsearch\n";
@@ -32,32 +30,35 @@ print "## from $LDAPSERVER ($DN)\n";
print "##\n";
## scheck for the existence of the posixAccount first
-$result = $conn->search ("$DN", "sub", "(objectclass=smbPasswordEntry)");
-
-
+$result = $ldap->search ( base => "$DN",
+ scope => "sub",
+ filter => "(objectclass=smbpasswordentry)"
+ );
+
+
+
## loop over the entries we found
-while ($result) {
-
- @uid = $result->getValue("uid");
- @uidNumber = $result->getValue("uidNumber");
- @lm_pw = $result->getValue("lmpassword");
- @nt_pw = $result->getValue("ntpassword");
- @acct = $result->getValue("acctFlags");
- @pwdLastSet = $result->getValue("pwdLastSet");
-
+while ( $entry = $result->shift_entry() ) {
+
+ @uid = $entry->get_value("uid");
+ @uidNumber = $entry->get_value("uidNumber");
+ @lm_pw = $entry->get_value("lmpassword");
+ @nt_pw = $entry->get_value("ntpassword");
+ @acct = $entry->get_value("acctFlags");
+ @pwdLastSet = $entry->get_value("pwdLastSet");
+
if (($#uid+1) && ($#uidNumber+1)) {
-
+
$lm_pw[0] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" if (! ($#lm_pw+1));
$nt_pw[0] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" if (! ($#nt_pw+1));
$acct[0] = "[DU ]" if (! ($#acct+1));
$pwdLastSet[0] = "FFFFFFFF" if (! ($#pwdLastSet+1));
-
+
print "$uid[0]:$uidNumber[0]:$lm_pw[0]:$nt_pw[0]:$acct[0]:LCT-$pwdLastSet[0]\n";
}
-
- $result = $conn->nextEntry();
-
+
}
-$conn->close();
+$ldap->unbind();
exit 0;
+
diff --git a/examples/LDAP/import2_smbpasswd.pl b/examples/LDAP/import2_smbpasswd.pl
deleted file mode 100644
index 0f83b5cae45..00000000000
--- a/examples/LDAP/import2_smbpasswd.pl
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/perl
-##
-## Example script of how you could import a smbpasswd file into an LDAP
-## directory using the Mozilla PerLDAP module.
-##
-## writen by jerry@samba.org
-##
-## ported to Net::LDAP by dkrovich@slackworks.com
-
-use Net::LDAP;
-
-#################################################
-## set these to a value appropriate for your site
-##
-
-$DN="dc=samba,dc=my-domain,dc=com";
-$ROOTDN="cn=Manager,dc=my-domain,dc=com";
-$rootpw = "secret";
-$LDAPSERVER="localhost";
-
-##
-## end local site variables
-#################################################
-
-$ldap = Net::LDAP->new($LDAPSERVER) or die "Unable to connect to LDAP server $LDAPSERVER";
-
-## Bind as $ROOTDN so you can do updates
-$mesg = $ldap->bind($ROOTDN, password => $rootpw);
-
-while ( $string = <STDIN> ) {
- chop ($string);
-
- ## Get the account info from the smbpasswd file
- @smbentry = split (/:/, $string);
-
- ## Check for the existence of a system account
- @getpwinfo = getpwnam($smbentry[0]);
- if (! @getpwinfo ) {
- print STDERR "$smbentry[0] does not have a system account... skipping\n";
- next;
- }
-
- ## check and see if account info already exists in LDAP.
- $result = $ldap->search ( base => "$DN",
- scope => "sub",
- filter => "(&(|(objectclass=posixAccount)(objectclass=sambaAccount))(uid=$smbentry[0]))"
- );
-
- ## If no LDAP entry exists, create one.
- if ( $result->count == 0 ) {
- $entry = $ldap->add ( dn => "uid=$smbentry[0]\,$DN",
- attrs => [
- uid => $smbentry[0],
- uidNumber => @getpwinfo[2],
- lmPassword => $smbentry[2],
- ntPassword => $smbentry[3],
- acctFlags => $smbentry[4],
- pwdLastSet => substr($smbentry[5],4),
- objectclass => [ 'top', 'sambaAccount', 'posixAccount']
- ]
- );
- print "Adding [uid=" . $smbentry[0] . "," . $DN . "]\n";
-
- ## Otherwise, supplement/update the existing entry.
- } elsif ($result->count == 1) {
- # Put the search results into an entry object
- $entry = $result->shift_entry;
-
- print "Updating [" . $entry->dn . "]\n";
-
- ## Add the objectclass: sambaAccount attribute if it's not there
- @values = $entry->get_value( "objectclass" );
- $flag = 1;
- foreach $item (@values) {
- if ( lc($item) eq "sambaaccount" ) {
- print $item . "\n";
- $flag = 0;
- }
- }
- if ( $flag ) {
- $entry->add(objectclass => "sambaAccount");
- }
-
- ## Set the other attribute values
- $entry->replace(lmPassword => $smbentry[2],
- ntPassword => $smbentry[3],
- acctFlags => $smbentry[4],
- pwdLastSet => substr($smbentry[5],4)
- );
-
- ## Apply changes to the LDAP server
- $updatemesg = $entry->update($ldap);
- if ( $updatemesg->code ) {
- print "Error updating $smbentry[0]!\n";
- }
-
- ## If we get here, the LDAP search returned more than one value
- ## which shouldn't happen under normal circumstances.
- } else {
- print STDERR "LDAP search returned more than one entry for $smbentry[0]... skipping!\n";
- next;
- }
-}
-
-$ldap->unbind();
-exit 0;
-
-
diff --git a/examples/LDAP/import_smbpasswd.pl b/examples/LDAP/import_smbpasswd.pl
index 14aeff967f1..61ad33c8099 100644
--- a/examples/LDAP/import_smbpasswd.pl
+++ b/examples/LDAP/import_smbpasswd.pl
@@ -1,13 +1,13 @@
#!/usr/bin/perl
##
-## Example script of how you could import and smbpasswd file into an LDAP
+## Example script of how you could import a smbpasswd file into an LDAP
## directory using the Mozilla PerLDAP module.
##
## writen by jerry@samba.org
##
+## ported to Net::LDAP by dkrovich@slackworks.com
-use Mozilla::LDAP::Conn;
-use Mozilla::LDAP::Entry;
+use Net::LDAP;
#################################################
## set these to a value appropriate for your site
@@ -15,51 +15,105 @@ use Mozilla::LDAP::Entry;
$DN="ou=people,dc=plainjoe,dc=org";
$ROOTDN="cn=Manager,dc=plainjoe,dc=org";
-$rootpw = "secret";
-$LDAPSERVER="localhost";
+# If you use perl special character in your
+# rootpw, escape them:
+# $rootpw = "secr\@t" instead of $rootpw = "secr@t"
+$rootpw = "n0pass";
+$LDAPSERVER="scooby";
##
## end local site variables
#################################################
-$conn = new Mozilla::LDAP::Conn ("$LDAPSERVER", "389", $ROOTDN, $rootpw );
-die "Unable to connect to LDAP server $LDAPSERVER" unless $conn;
+$ldap = Net::LDAP->new($LDAPSERVER) or die "Unable to connect to LDAP server $LDAPSERVER";
+## Bind as $ROOTDN so you can do updates
+$mesg = $ldap->bind($ROOTDN, password => $rootpw);
+$mesg->error() if $mesg->code();
while ( $string = <STDIN> ) {
- chop ($string);
+ chomp ($string);
- ## get the account information
+ ## Get the account info from the smbpasswd file
@smbentry = split (/:/, $string);
- ## check for the existence of the posixAccount first
+ ## Check for the existence of a system account
+ @getpwinfo = getpwnam($smbentry[0]);
+ if (! @getpwinfo ) {
+ print STDERR "**$smbentry[0] does not have a system account... \n";
+ next;
+ }
+ ## Calculate RID = uid*2 +1000
+ $rid=@getpwinfo[2]*2+1000;
+
+ ## check and see if account info already exists in LDAP.
+ $result = $ldap->search ( base => "$DN",
+ scope => "sub",
+ filter => "(uid=$smbentry[0])"
+ );
- ## FIXME!! Should do a getownam() and let the NSS modules lookup the account
- ## This way you can have a UNIX account in /etc/passwd and the smbpasswd i
- ## entry in LDAP.
- $result = $conn->search ("$DN", "sub", "(&(uid=$smbentry[0])(objectclass=posixAccount))");
- if ( ! $result ) {
- print STDERR "uid=$smbentry[0] does not have a posixAccount entry in the directory!\n";
- next;
- }
+ ## If no LDAP entry exists, create one.
+ if ( $result->count == 0 ) {
+ $new_entry = Net::LDAP::Entry->new();
+ $new_entry->add( dn => "uid=$smbentry[0],$DN",
+ uid => $smbentry[0],
+ rid => $rid,
+ lmPassword => $smbentry[2],
+ ntPassword => $smbentry[3],
+ acctFlags => $smbentry[4],
+ cn => $smbentry[0],
+ pwdLastSet => hex(substr($smbentry[5],4)),
+ objectclass => 'sambaAccount' );
- print "Updating [" . $result->getDN() . "]\n";
+ $result = $ldap->add( $new_entry );
+ $result->error() if $result->code();
+ print "Adding [uid=" . $smbentry[0] . "," . $DN . "]\n";
- ## Do we need to add the 'objectclass: smbPasswordEntry' attribute?
- if (! $result->hasValue("objectclass", "smbPasswordEntry")) {
- $result->addValue("objectclass", "smbPasswordEntry");
- }
-
- ## Set other attribute values
- $result->setValues ("lmPassword", $smbentry[2]);
- $result->setValues ("ntPassword", $smbentry[3]);
- $result->setValues ("acctFlags", $smbentry[4]);
- $result->setValues ("pwdLastSet", substr($smbentry[5],4));
-
- if (! $conn->update($result)) {
- print "Error updating!\n";
- }
+ ## Otherwise, supplement/update the existing entry.
+ }
+ elsif ($result->count == 1)
+ {
+ # Put the search results into an entry object
+ $entry = $result->entry(0);
+
+ print "Updating [" . $entry->dn . "]\n";
+
+ ## Add the objectclass: sambaAccount attribute if it's not there
+ @values = $entry->get_value( "objectclass" );
+ $flag = 1;
+ foreach $item (@values) {
+ print "$item\n";
+ if ( "$item" eq "sambaAccount" ) {
+ $flag = 0;
+ }
+ }
+ if ( $flag ) {
+ ## Adding sambaAccount objectclass requires adding at least rid:
+ ## uid attribute already exists we know since we searched on it
+ $entry->add(objectclass => "sambaAccount",
+ rid => $rid );
+ }
+
+ ## Set the other attribute values
+ $entry->replace(rid => $rid,
+ lmPassword => $smbentry[2],
+ ntPassword => $smbentry[3],
+ acctFlags => $smbentry[4],
+ pwdLastSet => hex(substr($smbentry[5],4)));
+
+ ## Apply changes to the LDAP server
+ $updatemesg = $entry->update($ldap);
+ $updatemesg->error() if $updatemesg->code();
+
+ ## If we get here, the LDAP search returned more than one value
+ ## which shouldn't happen under normal circumstances.
+ } else {
+ print STDERR "LDAP search returned more than one entry for $smbentry[0]... skipping!\n";
+ next;
+ }
}
-$conn->close();
+$ldap->unbind();
exit 0;
+
+
diff --git a/examples/LDAP/samba-schema-netscapeds4.x b/examples/LDAP/samba-schema-netscapeds4.x
index c5a11b8b66c..074b78c52cc 100644
--- a/examples/LDAP/samba-schema-netscapeds4.x
+++ b/examples/LDAP/samba-schema-netscapeds4.x
@@ -24,7 +24,7 @@ attribute domain 1.3.6.1.4.1.7165.2.1.18 cis single
objectclass sambaAccount
oid
- 1.3.1.5.1.4.1.7165.2.2.2
+ 1.3.1.5.1.4.1.7165.2.2.3
superior
top
requires
diff --git a/examples/LDAP/samba-schema-netscapeds5.x b/examples/LDAP/samba-schema-netscapeds5.x
index 0abc9d82e27..888758f67f3 100644
--- a/examples/LDAP/samba-schema-netscapeds5.x
+++ b/examples/LDAP/samba-schema-netscapeds5.x
@@ -21,8 +21,8 @@ aci: (targetattr = "*")(version 3.0; acl "SIE Group"; allow (all)groupdn = "ld
ap:///cn=slapd-sambaldap, cn=iPlanet Directory Server, cn=Server Group, cn=iPlanetDirectory.samba.org, ou=samba.org, o=NetscapeRoot";)
modifiersName: cn=directory manager
modifyTimestamp: 20020322124844Z
-objectClasses: ( 1.3.1.5.1.4.1.7165.2.2.2 NAME 'sambaAccount' SUP top STRUCTUR
- AL MAY ( acctFlags $ domain $ homeDrive $ kickoffTime $ lmPassword $ logofft
+objectClasses: ( 1.3.1.5.1.4.1.7165.2.2.3 NAME 'sambaAccount' SUP top AUXILIARY
+ MAY ( acctFlags $ domain $ homeDrive $ kickoffTime $ lmPassword $ logofft
ime $ logonTime $ ntPassword $ primaryGroupID $ profilePath $ pwdCanChange $
pwdLastSet $ pwdMustChange $ rid $ scriptPath $ smbHome $ userWorkstations
) X-ORIGIN 'user defined' )
diff --git a/examples/LDAP/samba-schema.IBMSecureWay b/examples/LDAP/samba-schema.IBMSecureWay
index 1fca4a749a6..73d767b03c8 100644
--- a/examples/LDAP/samba-schema.IBMSecureWay
+++ b/examples/LDAP/samba-schema.IBMSecureWay
@@ -10,7 +10,7 @@
## ibm-slapdIncludeSchema: /etc/lapschema/samba.schema
##
objectClasses {
-( 1.3.1.5.1.4.1.7165.2.2.2 NAME 'sambaAccount' DESC 'Samba Account' SUP top MUST uid $ rid MAY ( acctFlags $ cn $ description $ displayName $ homeDrive $ kickoffTime $ lmPassword $ logoffTime $ logonTime $ ntPassword $ primaryGroupID $ profilePath $ pwdCanChange $ pwdLastSet $ pwdMustChange $ scriptPath $ smbHome $ userWorkstations ) )
+( 1.3.1.5.1.4.1.7165.2.2.3 NAME 'sambaAccount' DESC 'Samba Account' SUP top MUST uid $ rid MAY ( acctFlags $ cn $ description $ displayName $ homeDrive $ kickoffTime $ lmPassword $ logoffTime $ logonTime $ ntPassword $ primaryGroupID $ profilePath $ pwdCanChange $ pwdLastSet $ pwdMustChange $ scriptPath $ smbHome $ userWorkstations ) )
}
attributeTypes {
diff --git a/examples/LDAP/samba.schema b/examples/LDAP/samba.schema
index be088c74033..61dface0a20 100644
--- a/examples/LDAP/samba.schema
+++ b/examples/LDAP/samba.schema
@@ -119,8 +119,20 @@ attributetype ( 1.3.6.1.4.1.7165.2.1.15 NAME 'primaryGroupID'
# MUST ( uid $ uidNumber )
# MAY ( lmPassword $ ntPassword $ pwdLastSet $ acctFlags ))
-objectclass ( 1.3.6.1.4.1.7165.2.2.2 NAME 'sambaAccount' SUP top STRUCTURAL
- DESC 'Samba Account'
+#objectclass ( 1.3.6.1.4.1.7165.2.2.2 NAME 'sambaAccount' SUP top STRUCTURAL
+# DESC 'Samba Account'
+# MUST ( uid $ rid )
+# MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $
+# logoffTime $ kickoffTime $ pwdCanChange $ pwdMustChange $ acctFlags $
+# displayName $ smbHome $ homeDrive $ scriptPath $ profilePath $
+# description $ userWorkstations $ primaryGroupID $ domain ))
+
+## The X.500 data model (and therefore LDAPv3) says that each entry can
+## only have one structural objectclass. OpenLDAP 2.0 does not enforce
+## this currently but will in v2.1
+
+objectclass ( 1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' SUP top AUXILIARY
+ DESC 'Samba Auxilary Account'
MUST ( uid $ rid )
MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $
logoffTime $ kickoffTime $ pwdCanChange $ pwdMustChange $ acctFlags $
diff --git a/examples/LDAP/smbldap-tools/AUTHORS b/examples/LDAP/smbldap-tools/AUTHORS
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/AUTHORS
diff --git a/examples/LDAP/smbldap-tools/CONTRIBUTORS b/examples/LDAP/smbldap-tools/CONTRIBUTORS
new file mode 100644
index 00000000000..9765a57e60d
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/CONTRIBUTORS
@@ -0,0 +1,29 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/CONTRIBUTORS,v $
+#
+## Authors and actives contributors to SMBLDAP-TOOLS
+
+Have contributed directly to this tools, or are always in charge of
+some aspects of it developments (alphabetical order):
+ . Terry Davis <tdavis@approbation.org>
+ . David Le Corfec <dlc@freesurf.fr>
+ . Olivier Lemaire <olivier.lemaire@IDEALX.com>
+ . Jérôme Tournier <jerome.tournier@IDEALX.com>
+
+Many thanks to contributors for bug report and patches:
+ . Gert-Jan Braas <braas@wyldebeast-wunderliebe.com>
+ bug report for 2.2.3 samba.schema
+ . Jody Haynes <Jody.Haynes@isunnetworks.com>
+ originaly passwd.pl
+ . Brad Langhorst <brad@langhorst.com>
+ package relocatability
+ . Mirko Manea <mami@arena.sci.univr.it>
+ originaly useradd.pl
+ . Alain Richard <alain.richard@equation.fr>
+ bug report and Perl tips
+ . Roland Schulz <mail@r2s2.de>
+ bug report for smbldap-passwd
+ . Xavier Boschian <Xavier.Boschian@rtlgroup.net>
+ bug report for smbldap-populate
+
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/COPYING b/examples/LDAP/smbldap-tools/COPYING
new file mode 100644
index 00000000000..32d0e6014a7
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/examples/LDAP/smbldap-tools/ChangeLog b/examples/LDAP/smbldap-tools/ChangeLog
new file mode 100644
index 00000000000..9a0bc744e19
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/ChangeLog
@@ -0,0 +1,29 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/ChangeLog,v $
+#
+## ChangeLog for SMBLDAP-TOOLS
+
+* 2002-06-03: notes to webmin.idealx.org (idxldapaccounts)
+* 2002-06-01: release 0.7. tested with 2.2.4
+* 2002-05-31: fixed smbldap-populate compliance to smbldap_conf
+ cleaned up smbldap_conf to be more readable
+ some more documentation
+ bugfixes on smbldap-passwd and smbldap-populate
+* 2002-05-16: modified default mode on homes: now 700
+* 2002-05-13: fixed spec (relocation and reqs)
+* 2002-03-02: fixed 2.2.3 sambaAccount bug with smbldap-useradd.pl
+ (rid is now mandatory in the sambaAccount objectClass)
+* 2002-02-14: just modified default populate for Administrator
+* 2002-02-05: release 0.6. enable/disable user in usermod
+* 2002-02-04: release 0.5. added smbldap-migrate-groups to migrate NT groups
+ from a net group dump. added samba parameters to smbldap-useradd
+ and smbldap-usermod.
+* 2002-01-12: added smbldap-migrate-accounts to migrate users/machines
+ accounts from a PWDUMP dump
+* 2001-12-13: added smbldap-populate to create the initial base
+* 2001-12-13: initial release 0.1
+* 2001-12-12: fixed the SPEC file for RedHat
+* 2001-12-03: cleaned the code and use strict;
+* 2001-11-20: initial needs (for testing purpose on Samba-2.2.2 an Samba-TNG)
+
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/FILES b/examples/LDAP/smbldap-tools/FILES
new file mode 100644
index 00000000000..48ee571b29d
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/FILES
@@ -0,0 +1,43 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/FILES,v $
+#
+## File listing for SMBLDAP-TOOLS
+
+CONTRIBUTORS : authors and contributors
+COPYING : licence
+FILES : this file listing
+README : introduction and usage
+TODO : feature request and bug report list
+ChangeLog : changelog
+
+Core:
+=-=-=
+smbldap-groupadd.pl : to add a new group
+ (objectclass: posixGroup)
+smbldap-groupdel.pl : to delete a group
+ (objectclass: posixGroup)
+smbldap-groupmod.pl : to modify a group (mostly used to add user to a group)
+ (objectclass: posixGroup)
+smbldap-groupshow.pl : to view a group
+ (objectclass: posixGroup)
+smbldap_conf.pm : global configuration datas
+smbldap_tools.pm : functions
+smbldap-useradd.pl : to add a new user
+ (objectclass: posixAccount and/or sambaAccount)
+smbldap-userdel.pl : to delete a user
+ (objectclass: posixAccount and/or sambaAccount)
+smbldap-usermod.pl : to modify an user datas
+ (objectclass: posixAccount and/or sambaAccount)
+smbldap-usershow.pl : to view an user datas
+ (objectclass: posixAccount and/or sambaAccount)
+smbldap-passwd.pl : to sync passwd (Unix and Samba)
+ (a replacement for the system passwd utility)
+smbldap-populate.pl : to add a builtin ldif to initialize your LDAP master for
+ smbldap use, or to add a specified ldif
+smbldap-tools.spec : SPEC file for RedHat RPM package format
+
+Migration:
+=-=-=-=-=-
+smbldap-migrate-accounts.pl : add NT sam entries from pwdump to ldap
+smbldap-migrate-groups.pl : add any LDAP posixGroups from the output of the 'net group' NT command
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/INFRASTRUCTURE b/examples/LDAP/smbldap-tools/INFRASTRUCTURE
new file mode 100644
index 00000000000..75b80bb4c8b
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/INFRASTRUCTURE
@@ -0,0 +1,84 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/INFRASTRUCTURE,v $
+#
+## Some notes about the architecture
+
+
+Global Architecture for smbdlap-tools
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+smbldap-tools help you manage users and groups for Unix and Samba,
+using LDAP. They may be used in any context, and are kept relatively
+simplier enought to let you customize them to you needs.
+
+They need the following objectClasses to work:
+ . sambaAccount: from samba.schema for Samba 2.2 branch
+ . posixAccount and posixGroup : from nis.schema
+ . organizationalUnit and dcObject: from core.schema
+
+They will probably use in a near future some additional objectClasses
+to support :
+ . mail features (sendmail/postfix/qmail/courier).
+ . conform to RFC2307 best practices (and so some maps too like merging
+ Netbios computers (sambaAccounts) with ipHosts
+
+For ease of visualization of the LDAP objects by human standards, we
+used a DIT like this one :
+ . dc=IDEALX,dc=org : the company/organization suffix
+ . ou=Users : to store users accounts
+ . ou=Computers : to store computers accounts
+ . ou=Groups : to store system groups
+Of course, you're free to use a different naming scheme and DIT (see
+smbldap_conf.pm).
+
+
+Built in groups initial population
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+smbldap-populate.pl populate the LDAP directory with some built in groups
+using gidNumber according to Well Know RID of Windows NT4 Srv. In fact, As
+far a Samba 2.2.x is concerned, only the 'Domain Admins' (gidNumber 512) have
+real inpact on the Samba and Windows population. To activate this group as
+the Domain Administrators Group, use the following smb.conf directive (see
+man smb.conf for more):
+
+ domain admin group = " @"Domain Admins" "
+
+Other built in groups are really cosmetic ones with Samba 2.2.x. We did not
+removed them because one of these days, we whish to use Samba 3.0 where
+Windows Group Support should be operational.
+
+Why these specific gidNumbers ?
+It's about unix/windows mapping of numerical ids with Samba. Ids below 1024
+are NT special ids. In fact, 512 is the RID (Windows uid/gid) for the
+"Domain Administrators" NT group. The magic number is found in Samba sources
+and possibly other Samba/Windows documentations.
+
+The goal is to have a set of Unix users who are Domain Administrators and can
+modify Samba datas (eg. LDAP content), with commandline tools or within
+Windows via Samba.
+
+Say you want to add a NT4 ws to an NT domain (controlled by a samba/ldap
+server). You give the domain administrator's login and password in the
+appropriate ws settings, then the ws contacts the samba server, which checks
+the credentials and use them as unix user to run the smbldap-tools (if I
+remember). Giving 512 as a RID to a LDAP entry marks it as a domain admin
+for Samba (thus Windows). Using nss_ldap, you also have an account with
+gid 512.
+
+
+Known BUGS and WORKAROUND used
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+The 2.2.2 has at least a bug : rid/primaryGroupID are read as hex in LDAP,
+but written as decimal. Fixed in CVS by reading as decimal. By default
+smbldap-useradd.pl writes decimal to LDAP. Use -x to support the odd
+behaviour.
+
+The samba-2.2.4-ldapbindnotuid0.patch is not a perfect solution however
+as the check is there because Samba store admin credentials to establish the
+LDAP connection. The uid == 0 check was to ensure that a normal user could
+not get write access to the LDAP backend. A more logical situation should be
+done for 2.2.5 by checking if the user is a member of the domain admin group
+(reported to Jerremy and Gerald 2002-05-28).
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/INSTALL b/examples/LDAP/smbldap-tools/INSTALL
new file mode 100644
index 00000000000..f4c72751a75
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/INSTALL
@@ -0,0 +1,28 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/INSTALL,v $
+#
+## How To Install SMBLDAP-TOOLS
+
+Quick & Dirty:
+=-=-=-=-=-=-=-
+ . Copy all those scripts in /usr/local/sbin/
+ . Modify smbldap_conf.pm to match your configuration
+ . If not already done : "smbpasswd -w secret" to set up
+ the ldap admin password in secrets.tdb
+ . Either add /usr/local/sbin in $PERLLIB or run the scripts
+ from this directory, or make a symlink from /usr/local/sbin/*.pm
+ to /usr/lib/perl5/.
+ . to allow a domain admin to add user using "add user script" in smb.conf :
+ chmod 753 smbldap_conf.pm
+ chmod 750 smbldap-useradd.pl
+ chgrp 512 smbldap_conf.pm smbldap-useradd.pl (512 = 0x200 = Domain Admins)
+ Have your admin belong to this group
+ In smb.conf : domain admin group = " @"Domain Admins" "
+
+RedHat RPM:
+=-=-=-=-=-=
+Install smbldap-tools-0.7-1.i386.rpm
+Modify /usr/local/sbin/smbldap_conf.pm to match you configuration
+If not already done : "smbpasswd -w secret" to set up
+the ldap admin password in secrets.tdb
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/Makefile b/examples/LDAP/smbldap-tools/Makefile
new file mode 100644
index 00000000000..3e5eac427d7
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/Makefile
@@ -0,0 +1,35 @@
+PACKAGE=smbldap-tools
+RELEASE=0.7
+DESTDIR = $(PACKAGE)-$(RELEASE)
+
+dist: distclean $(DESTDIR).tgz
+
+$(DESTDIR).tgz: .diststamp
+ rm -rf $(DESTDIR)
+ mkdir $(DESTDIR)
+ # copy files
+ cp CONTRIBUTORS $(DESTDIR)
+ cp COPYING $(DESTDIR)
+ cp ChangeLog $(DESTDIR)
+ cp FILES $(DESTDIR)
+ cp INSTALL $(DESTDIR)
+ cp README $(DESTDIR)
+ cp TODO $(DESTDIR)
+ cp INFRASTRUCTURE $(DESTDIR)
+ tar cf mkntpwd.tar mkntpwd
+ gzip mkntpwd.tar
+ cp mkntpwd.tar.gz $(DESTDIR)
+ cp smbldap-*.pl $(DESTDIR)
+ cp smbldap_*.pm $(DESTDIR)
+ # copy directories
+ tar cvzf $(DESTDIR).tgz $(DESTDIR)
+ rm -rf $(DESTDIR)
+ touch .diststamp
+
+.diststamp:
+
+distclean:
+ rm -f *~
+ rm -f $(DESTDIR).tgz
+ rm -f mkntpwd.tar.gz
+
diff --git a/examples/LDAP/smbldap-tools/NEWS b/examples/LDAP/smbldap-tools/NEWS
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/NEWS
diff --git a/examples/LDAP/smbldap-tools/README b/examples/LDAP/smbldap-tools/README
new file mode 100644
index 00000000000..add0175c0ce
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/README
@@ -0,0 +1,87 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/README,v $
+#
+
+Latest version may be found at http://samba.idealx.org/
+
+
+What those tools are for?
+=-=-=-=-=-=-=-=-=-=-=-=-=
+
+A collection of scripts, «over» user{add,del,mod} and group{add,del,mod}
+system tools to manipulate users and groups stored in LDAP directory,
+for DEN system like SAMBA-LDAP and pam/nss_ldap systems.
+
+Additionnaly, some scripts are designed to ease your migration from
+a Windows NT 4.0 PDC Server to a Samba-LDAP PDC Server (Killer?;-):
+smbldap-populate, smbldap-migrate-groups, smbldap-migrate-accounts.
+
+They are currently used with Samba 2.2.4, therefore you may (will) have
+to make some fixes for Samba TNG and Samba 3.0. Hint: contribs welcome :)
+
+In the future, some other function may come (like backup and restore,
+Novell migration tools, samba system activity report, dealing with
+mail functions, compliance to RFC2307...): consult TODO.
+
+
+What do SMBLDAP-TOOLS provide?
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Those tools provide the following functions :
+ . populate LDAP database with a basic LDIF
+ . add a user or group
+ . delete a user or group
+ . modify all users or groups data (all attributes types stored in
+ posixAccount and sambaAccount object class)
+Taking care of :
+ . staying compatible with all standard system tools options
+ (user/group{add,del,mod})
+ . be extensible for future developments
+ (manipulation of shadow account options, for example)
+ . error management, in the way system tools do
+Constraints :
+ . usage of PERL (portability)
+ . all options must be placed in an external configuration file
+ . english localization
+
+The current release uses the "mkntpwd" program, in mkntpwd.tar.gz
+in the current directory. It comes from
+http://www.demog.berkeley.edu/~aperrin/tips/src/mkntpwd.tar.gz
+It allows to not use smbpasswd (if $with_smbpasswd == 0 in smbldap_conf.pm)
+
+What do SMBLDAP-TOOLS deliver?
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+Contents :
+ . scripts (see FILES)
+ . user documentation in pod format, included in the sources
+ (or just use the -? option)
+
+These tools aim at delivering the same functionality as the corresponding
+system tools. However they may not be all implemented yet.
+Current limitations :
+ . no shadow support
+ . cannot change uid with usermod
+ . no UTF-8 support (thus ASCII-7 only)
+
+
+How to generate documentation?
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+Just issue the following command:
+ perldoc name_of_script.pl (ex: perldoc smbldap-useradd.pl)
+
+Where can I find the latest release of those scripts?
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Just fire any web browser to http://samba.IDEALX.org/
+and/or contact samba@IDEALX.org
+
+Additionnaly, you will find an useful Webmin module
+at http://webmin.IDEALX.org/ if interested in a graphical
+user interface to manager user and groups accounts via Webmin
+for your Samba+LDAP PDC.
+
+Let us know if these tools helped you, or if we should enhance
+them with some functions you want them to support.
+
+Sincerly,
+ LEM
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/TODO b/examples/LDAP/smbldap-tools/TODO
new file mode 100644
index 00000000000..57424d462af
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/TODO
@@ -0,0 +1,27 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/TODO,v $
+#
+## TODO list - First In, Last in the list...
+## (BF: Bug Report / FR: Feature Request)
+
+
+FR * use RFC2307 best practices (Luke, next time you visit Paris, have a
+ beer at IDEALX'cantina ;-)
+FR * add mail (sendmail/postfix/qmail/courier) support
+FR * bugfix, really : allow non-root users to change passwd
+ (currently the config must be unreadable because of bindpasswd)
+FR * make smbldap-tools to use system configuration files
+ (/etc/login.defs and /etc/ldap.conf for example)
+FR * rewrite smbldap-tools using perl-ldap. In fact, this 0.x
+ release use ldap system tools (ldapadd,ldapdelete,ldapmodify)
+FR * add shadowAccounts manipulation support
+FR * internationalize the SMBLDAP-TOOLS
+FR * add smbldap-sar : Samba System Activity Report to help
+ supporting Samba/LDAP sysadmin activity
+FR * add smbldap-backup/smbldap-restore to backup and restore
+ a SAM (in LDAP) database. No sorcery, just LDIF, but usefull
+ for non-LDAP gurus
+FR * adding migration tools from migration from W2K and NetWare to Samba-LDAP
+FR * adapt smbldap-tools to use Samba 3.0
+
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/cgi/README b/examples/LDAP/smbldap-tools/cgi/README
new file mode 100644
index 00000000000..7a4fc0c02b9
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/cgi/README
@@ -0,0 +1,27 @@
+Description:
+ A cgi to allow users to change their passwords via a web browser.
+
+Installation:
+ Drop this into a cgi-enabled directory on your webserver.
+ Edit it and change the CONFIGURATION section to suit your environment.
+ READ THE NOTES SECTION.
+
+Notes: This script will run as the user who runs your web server. So, to invoke the smbpasswd call, you must implement sudo.
+ Example of /etc/sudoers:
+
+ # Host alias specification
+ # User alias specification
+ User_Alias PASSWD = apache
+ # Cmnd alias specification
+ Cmnd_Alias PASSWD = /usr/bin/smbpasswd
+ # User privilege specification
+ root ALL=(ALL) ALL
+ PASSWD ALL= NOPASSWD: PASSWD
+
+ This concept is probably very insecure and broken. That is why this is a 0.1 release. :)
+
+
+Feel free to drop me suggestions. I am a perl learner so I am always open to suggestions.
+
+Terry Davis
+tdavis@approbation.org
diff --git a/examples/LDAP/smbldap-tools/cgi/ldappass.cgi b/examples/LDAP/smbldap-tools/cgi/ldappass.cgi
new file mode 100755
index 00000000000..4a5ecb8f3a9
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/cgi/ldappass.cgi
@@ -0,0 +1,202 @@
+#!/usr/bin/perl
+
+################################################################################
+#
+# changepass.pl - A program to allow users to change their passwords
+# via a web browser.
+# Terry Davis
+#
+# URLs
+# Net::LDAP - http://
+# usermod and this file - http://www.cloudamster.com/cloudmaster/projects
+#
+# Release History:
+# Version 0.1 - initial write
+#
+# ToDo:
+# ... the ToDo section is on the ToDo list...
+#
+# Limitations:
+# The password cannot contain single and double quotes.....welcome to quoting hell....
+#
+# Notes:
+# This code is largely based on work done by Danny Sauer - http://www.cloudamster.com/cloudmaster/projects
+# His work is not licensed and is marked as 'freely distributable'.
+# Thank you to Danny for his hard work on the initial work.
+#
+################################################################################
+
+use CGI qw(:standard);
+use Net::LDAP;
+
+# CONFIGURATION SECTION
+$masterLDAP = "ldap.idealx.org";
+$basedn = "dc=IDEALX,dc=org";
+$masterPw = "";
+$masterDN = "cn=manager,$basedn";
+$ldap_path = "/usr/bin";
+$ldap_opts = "-x";
+$ldappasswd = "$ldap_path/ldappasswd $ldap_opts -h $masterLDAP -D '$masterDN' -w '$masterPw'";
+$usersdn = "ou=Users,$basedn";
+# END CONFIGURATION
+
+
+
+# DONT EDIT ANYTHING BELOW THIS LINE
+$logtag = "Login:";
+$passtag = "Current password:";
+$npasstag1 = "New password:";
+$npasstag2 = "Retype new pasword:";
+$error = "";
+$color = "<FONT color='red'>";
+$stopcolor = "</FONT>";
+
+if(param()){
+ nologin() unless ($username = param('login'));
+ nopass() unless ($oldpass = param('oldpass'));
+ nonewpass(1) unless ($newpass1 = param('newpass'));
+ nonewpass(2) unless ($newpass2 = param('newpass2'));
+ verifyuser($username) or die "bad user";
+ verifypass($username, $oldpass) or die "bad pass";
+ testnewpass($newpass1, $newpass2) or die "bad new pass";
+ changepass($username, $newpass1) or die "couldn't change pass";
+ printsuccess();
+}else{
+ printpage();
+}
+exit(0);
+
+sub verifyuser{
+ local $user = shift;
+ $ldap = Net::LDAP->new($masterLDAP) or die "can't make new LDAP object: $@";
+ $ldap->bind();
+ if (0 < $ldap->search(base => $basedn, filter => "(uid=$user)")->count){
+ return 1;
+ }
+ $logtag = $color . $logtag . $color;
+ $error = "No such user";
+ printpage();
+ return 0;
+}
+
+sub verifypass{
+ $uid = shift;
+ $pass = shift;
+ $ldap = Net::LDAP->new($masterLDAP) or die "can't make new LDAP object: $@";
+ $binddn = "uid=$uid,ou=People,$basedn";
+ return 1 if($ldap->bind( $binddn, password => $pass)->code == 0);
+ if($ldap->bind()){
+ $passtag = $color . $passtag . $color;
+ $error = "Incorrect password";
+ printpage();
+ return 0;
+ }else{
+ print header, start_html(-title=>"LDAP dead");
+ print h2("<CENTER>The LDAP server is temporarily unavailable."),
+ p,"Please try again later</CENTER>";
+ return 0;
+ }die "Something (or someone) is defective, contact your friendly Systems Administrator";
+}
+
+sub testnewpass{
+ $p1 = shift; $p2 = shift;
+ if ($p1 ne $p2){
+ $npasstag1 = $color . $npasstag1 . $color;
+ $npasstag2 = $color . $npasstag2 . $color;
+ $error = "Passwords don't match ($p1 vs $p2)";
+ printpage();
+ return 0;
+ }
+ if ($p1 =~ /"/ ){
+ $npasstag1 = $color . $npasstag1 . $color;
+ $npasstag2 = $color . $npasstag2 . $color;
+ $error = "Passwords cannot contain double quotes. Sorry";
+ printpage();
+ return 0;
+ }
+ if ($p1 =~ /'/ ){
+ $npasstag1 = $color . $npasstag1 . $color;
+ $npasstag2 = $color . $npasstag2 . $color;
+ $error = "Passwords cannot contain single quotes. Sorry";
+ printpage();
+ return 0;
+ }
+ return 1;
+}
+
+sub changepass{
+ local $user = shift;
+ local $newpass = shift;
+ local $dn = "uid=$user,$usersdn";
+ system "$ldappasswd $dn -s '$newpass' > /dev/null";
+ `/usr/bin/sudo /usr/bin/smbpasswd $user "$newpass"`;
+ exit(1);
+}
+
+sub nologin{
+ $logtag = $color . $logtag . $color;
+ $error = "You need to enter a Login Name";
+ printpage();
+ exit(1);
+}
+
+sub nopass{
+ $passtag = $color . $passtag . $color;
+ $error = "Please enter your old password";
+ printpage();
+ exit(1);
+}
+
+sub nonewpass{
+ $f=shift;
+ $npasstag1 = $color . $npasstag1 . $color if($f==1);
+ $npasstag2 = $color . $npasstag2 . $color if($f==2);
+ $error = "You need to enter your new password";
+ $error .= " twice" if($f==2);
+ printpage();
+ exit(1);
+}
+
+sub printpage{
+ print header,
+ start_html(-title=> "Password Change Page",
+ -author=> 'tdavis@birddog.com',
+ -BGCOLOR=> 'WHITE'),
+ h3('Password Change Page'),
+ startform(-method=>'POST'),
+ "<TABLE BORDER=0 WIDTH=50%>",
+ "<font size=2>",
+ "<TR><TD>",
+ $logtag,
+ "</TD><TD>",
+ textfield(-name=>'login', -default=>$login,
+ -size=>15, -maxlength=>20),
+ "</TD><TR><TD>",
+ $passtag,
+ "</TD><TD>",
+ password_field(-name=>'oldpass', -size=>15, -maxlength=>25),
+ "</TD><TR><TD>",
+ $npasstag1,
+ "</TD><TD>",
+ password_field(-name=>'newpass', -size=>15, -maxlength=>25),
+ "</TD><TR><TD>",
+ $npasstag2,
+ "</TD><TD>",
+ password_field(-name=>'newpass2', -size=>15, -maxlength=>25),
+ "</TD><TR><TD></TD><TD>",
+ submit(-name=>"change"),reset(),
+ "</TD></TR></TABLE>",
+ "</font>",
+ endform(),
+ "<FONT color='red'>$error</FONT>",
+ end_html;
+}
+
+sub printsuccess(){
+ print header,
+ start_html(-title=> "Success",
+ -BGCOLOR=> 'WHITE'),
+ h1("Password Succesfully Changed"),
+ "<br>",
+ end_html;
+}
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/Makefile b/examples/LDAP/smbldap-tools/mkntpwd/Makefile
new file mode 100644
index 00000000000..23c9d471b0a
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/Makefile
@@ -0,0 +1,62 @@
+# Makefile for l0phtcrack - mudge@l0pht.com 11/1/96
+
+# C compiler
+#CC=cc
+CC=gcc
+
+# Uncomment the following to add symbols to the code for debugging
+#DEBUG=-g -Wall -D_DEBUG
+#DEBUG=-D_DEBUG
+
+# Optimization for the compiler
+#OPTIMIZE=
+OPTIMIZE=-O2
+
+# Choose your architecture
+# note that if you are on a big-endian machine like SUN's
+# I haven't tweaked the mem-cmp's and md4 stuff to be in
+# the correct order yet. You're on your own right now.
+#
+# FreeBSD
+ARCH=-DMPU8086
+STATIC=
+XLIBS=
+#
+# SUNOS
+#ARCH=-DBIGENDIAN
+#STATIC=
+#OPTIMIZE=-O2
+#XLIBS=
+#
+# ULTRA_SPARC w/ native compiler
+#ARCH=-DBIGENDIAN
+#STATIC=
+#OPTIMIZE=-fast -xO4 -xdepend -xchip=ultra -xarch=v8plus
+#XLIBS=
+#
+# SunOS/Solaris w/gcc
+#ARCH=-DBIGENDIAN -DTEST
+#STATIC=
+#OPTIMIZE=-O2
+#XLIBS=
+#
+# NeXTStep 3.2
+#CC=cc
+#ARCH=-DBIGENDIAN
+#STATIC=-Bstatic
+#OPTIMIZE=
+#XLIBS=
+
+CFLAGS= $(DEBUG) $(OPTIMIZE) $(ARCH) $(VISUAL) $(PERMUTE) $(STATIC)
+
+OBJS = getopt.o md4.o mkntpwd.o smbdes.o
+
+mkntpwd: $(OBJS)
+ $(CC) $(CFLAGS) $(XLIBS) -o mkntpwd $(OBJS)
+
+clean:
+ rm -f core *.o mkntpwd
+
+install: mkntpwd
+ install -m 555 mkntpwd $(PREFIX)/sbin/mkntpwd
+
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/getopt.c b/examples/LDAP/smbldap-tools/mkntpwd/getopt.c
new file mode 100644
index 00000000000..5b2e7a9100b
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/getopt.c
@@ -0,0 +1,756 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
+ Free Software Foundation, Inc.
+
+This file is part of the GNU C Library. Its master source is NOT part of
+the C library, however. The master source lives in /gd/gnu/lib.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if !defined (__STDC__) || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+#ifdef WIN32
+#include <string.h>
+#endif
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+#include <stdlib.h>
+#endif /* GNU C library. */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* XXX 1003.2 says this must be 1 before any call. */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return EOF with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+#include <string.h>
+#define my_index strchr
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+#if !defined (__STDC__) || !__STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+static const char *
+_getopt_initialize (optstring)
+ const char *optstring;
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns `EOF'.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ optarg = NULL;
+
+ if (optind == 0)
+ optstring = _getopt_initialize (optstring);
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return EOF;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ {
+ if (ordering == REQUIRE_ORDER)
+ return EOF;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0; /* set to zero by Anton */
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp(p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int)(nameend - nextchar) == (unsigned int)strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (opterr)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ "%s: option `--%s' doesn't allow an argument\n",
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ "%s: option `%c%s' doesn't allow an argument\n",
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' requires an argument\n",
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+ else
+ fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: option requires an argument -- %c\n",
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/getopt.h b/examples/LDAP/smbldap-tools/mkntpwd/getopt.h
new file mode 100644
index 00000000000..f3696d955dc
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/getopt.h
@@ -0,0 +1,133 @@
+/* Declarations for getopt.
+ Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
+
+This file is part of the GNU C Library. Its master source is NOT part of
+the C library, however. The master source lives in /gd/gnu/lib.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+#if defined (__STDC__) && __STDC__
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+#if defined (__STDC__) && __STDC__
+#ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/md4.c b/examples/LDAP/smbldap-tools/mkntpwd/md4.c
new file mode 100644
index 00000000000..1c9c2e6ecd5
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/md4.c
@@ -0,0 +1,171 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ a implementation of MD4 designed for use in the SMB authentication protocol
+ Copyright (C) Andrew Tridgell 1997
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+/* NOTE: This code makes no attempt to be fast!
+
+ It assumes that a int is at least 32 bits long
+*/
+
+typedef unsigned int uint32;
+
+static uint32 A, B, C, D;
+
+static uint32 F(uint32 X, uint32 Y, uint32 Z)
+{
+ return (X&Y) | ((~X)&Z);
+}
+
+static uint32 G(uint32 X, uint32 Y, uint32 Z)
+{
+ return (X&Y) | (X&Z) | (Y&Z);
+}
+
+static uint32 H(uint32 X, uint32 Y, uint32 Z)
+{
+ return X^Y^Z;
+}
+
+static uint32 lshift(uint32 x, int s)
+{
+ x &= 0xFFFFFFFF;
+ return ((x<<s)&0xFFFFFFFF) | (x>>(32-s));
+}
+
+#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
+#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s)
+#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s)
+
+/* this applies md4 to 64 byte chunks */
+static void mdfour64(uint32 *M)
+{
+ int j;
+ uint32 AA, BB, CC, DD;
+ uint32 X[16];
+
+ for (j=0;j<16;j++)
+ X[j] = M[j];
+
+ AA = A; BB = B; CC = C; DD = D;
+
+ ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
+ ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
+ ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
+ ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
+ ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
+ ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
+ ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
+ ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
+
+ ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
+ ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
+ ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
+ ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
+ ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
+ ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
+ ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
+ ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
+
+ ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
+ ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
+ ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
+ ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
+ ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
+ ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
+ ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
+ ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
+
+ A += AA; B += BB; C += CC; D += DD;
+
+ A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
+ C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
+
+ for (j=0;j<16;j++)
+ X[j] = 0;
+}
+
+static void copy64(uint32 *M, unsigned char *in)
+{
+ int i;
+
+ for (i=0;i<16;i++)
+ M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
+ (in[i*4+1]<<8) | (in[i*4+0]<<0);
+}
+
+static void copy4(unsigned char *out,uint32 x)
+{
+ out[0] = x&0xFF;
+ out[1] = (x>>8)&0xFF;
+ out[2] = (x>>16)&0xFF;
+ out[3] = (x>>24)&0xFF;
+}
+
+/* produce a md4 message digest from data of length n bytes */
+void mdfour(unsigned char *out, unsigned char *in, int n)
+{
+ unsigned char buf[128];
+ uint32 M[16];
+ uint32 b = n * 8;
+ int i;
+
+ A = 0x67452301;
+ B = 0xefcdab89;
+ C = 0x98badcfe;
+ D = 0x10325476;
+
+ while (n > 64) {
+ copy64(M, in);
+ mdfour64(M);
+ in += 64;
+ n -= 64;
+ }
+
+ for (i=0;i<128;i++)
+ buf[i] = 0;
+ memcpy(buf, in, n);
+ buf[n] = 0x80;
+
+ if (n <= 55) {
+ copy4(buf+56, b);
+ copy64(M, buf);
+ mdfour64(M);
+ } else {
+ copy4(buf+120, b);
+ copy64(M, buf);
+ mdfour64(M);
+ copy64(M, buf+64);
+ mdfour64(M);
+ }
+
+ for (i=0;i<128;i++)
+ buf[i] = 0;
+ copy64(M, buf);
+
+ copy4(out, A);
+ copy4(out+4, B);
+ copy4(out+8, C);
+ copy4(out+12, D);
+
+ A = B = C = D = 0;
+}
+
+
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.c b/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.c
new file mode 100644
index 00000000000..0c7d61e1341
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.c
@@ -0,0 +1,253 @@
+/*
+ This code is based on work from
+ L0phtcrack 1.5 06.02.97 mudge@l0pht.com
+
+ The code also contains sources from:
+ . routines from the samba code source
+ md4.c smbdes.c
+
+ Anton Roeckseisen (anton@genua.de)
+
+*/
+
+/*
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "mkntpwd.h"
+
+void str_to_key(unsigned char *,unsigned char *);
+void usage(char *);
+int PutUniCode(char *dst,char *src);
+void printlanhash(char *tmp);
+void mdfour(unsigned char *out, unsigned char *in, int n);
+void E_P16(unsigned char *p14,unsigned char *p16);
+
+
+void main(int argc, char **argv) {
+ extern char *optarg;
+ int c;
+
+ int printlan = 0;
+ char lanpwd[LMPASSWDLEN+1];
+ int printnt = 0;
+ char inputfile[FILENAMEBUFFER+1] = "";
+ FILE* InputFilePtr;
+ int just_pwd = 0;
+ int i;
+ char hashout[17];
+
+ char ntpasswd[NTPASSWDLEN+1];
+ char *hold;
+ unsigned char *p16;
+ int uni_len;
+ char passwd[NTPASSWDLEN+1];
+
+ if (argc==1)
+ usage(argv[0]);
+
+ if (argc==2)
+ just_pwd=1;
+ else
+ just_pwd=0;
+
+ lanpwd[0] = '\0';
+ ntpasswd[0] = '\0';
+
+ while ( (c = getopt(argc, argv, "L:N:f:")) != EOF){
+ switch(c) {
+ case 'L':
+ printlan++;
+ strncpy(lanpwd,optarg,LMPASSWDLEN);
+ lanpwd[LMPASSWDLEN]='\0';
+ for (i=0;i<LMPASSWDLEN;i++)
+ lanpwd[i]=toupper(lanpwd[i]);
+ break;
+ case 'N':
+ printnt++;
+ strncpy(passwd,optarg,NTPASSWDLEN);
+ passwd[NTPASSWDLEN]='\0';
+ break;
+ case 'f':
+ strncpy(inputfile,optarg,FILENAMEBUFFER);
+ inputfile[FILENAMEBUFFER]='\0';
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ /* Get password from file or STDIN */
+ if (inputfile[0]!='\0') {
+
+ just_pwd=0; /* make sure no shit is happening... */
+
+ /* get NT-password (longer) */
+ if (strcmp(inputfile,"-")==0) {
+ fgets(passwd,NTPASSWDLEN,stdin);
+ } else {
+ if ((InputFilePtr=fopen(inputfile,"r")) == NULL)
+ fprintf(stderr,"Couldn't open passwordfile: %s",inputfile) ;
+ fgets(passwd,NTPASSWDLEN,InputFilePtr);
+ fclose(InputFilePtr);
+ }
+ while (strlen(passwd)>0 && passwd[strlen(passwd)-1]=='\n')
+ passwd[strlen(passwd)-1]='\0';
+
+ /* create LANMAN-password (shorter) */
+ strncpy(lanpwd,passwd,LMPASSWDLEN);
+ lanpwd[LMPASSWDLEN]='\0';
+ for (i=0;i<LMPASSWDLEN;i++)
+ lanpwd[i]=toupper(lanpwd[i]);
+ printlan++;
+ printnt++;
+
+ }
+
+
+ /* Assume the one and only Arg is the new password! */
+
+ if (argc>1 && just_pwd==1) {
+ strncpy(lanpwd,argv[1],LMPASSWDLEN);
+ lanpwd[LMPASSWDLEN]='\0';
+ for (i=0;i<LMPASSWDLEN;i++)
+ lanpwd[i]=toupper(lanpwd[i]);
+ printlan++;
+
+ strncpy(passwd,argv[1],NTPASSWDLEN);
+ passwd[NTPASSWDLEN]='\0';
+ printnt++;
+ }
+
+ if (printlan >0) {
+ memset(hashout,'\0',17);
+ E_P16((uchar *)lanpwd,hashout);
+ printlanhash(hashout);
+ }
+
+ if (printnt >0) {
+
+ if (printlan>0) printf(":");
+
+ memset(ntpasswd, '\0', sizeof(ntpasswd));
+
+ if (passwd[strlen(passwd)-1] == '\n') /* strip the \n - this
+ is done in LowerString for the case sensitive
+ check */
+ passwd[strlen(passwd)-1] = '\0';
+
+ hold = (char *)malloc(NTPASSWDLEN * 2); /* grab space for
+ unicode */
+ if (hold == NULL){
+ fprintf(stderr, "out of memory...crackntdialog hold\n");
+ exit(1);
+ }
+
+ uni_len = PutUniCode(hold, passwd); /* convert to
+ unicode and return correct
+ unicode length for md4 */
+
+ p16 = (unsigned char*)malloc(17); /* grab space for md4 hash */
+ if (p16 == NULL){
+ fprintf(stderr, "out of memory...crackntdialect p16\n");
+ exit(1);
+ }
+
+ memset(p16,'\0',17);
+ mdfour(p16,hold, uni_len);
+
+ printlanhash(p16);
+
+ free(p16);
+ free(hold);
+ }
+
+ printf("\n");
+
+ exit(0);
+
+}
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+void usage(char *progname){
+ char *p;
+
+ p = strrchr(progname, '\\');
+ if (p == NULL)
+ p = progname;
+ else
+ p++;
+
+ fprintf(stderr, "Usage: %s [-L lanmgrpwd] [-N ntpasswd]\n",p);
+ fprintf(stderr, " %s password\n",p);
+ fprintf(stderr, " %s -f [-] [filename]\n\n",p);
+ fprintf(stderr, " -L lanmgrpasswd LanManager cleartextpwd <= 14 chars\n");
+ fprintf(stderr, " -N ntpasswd NT cleartextpwd <=128 chars (usually <=14)\n\n");
+ fprintf(stderr, " with both options present the encrypted LanManager-Pwd is \n");
+ fprintf(stderr, " printed first, followed by a ':' and the encrypted NT-Pwd.\n\n");
+ fprintf(stderr, " The second usage behaves like %s -L pwd -N pwd\n\n",p);
+ fprintf(stderr, " The third usage reads the password from STDIN or a File. Printout\n");
+ fprintf(stderr, " is the same as second.\n\n");
+ fprintf(stderr, "anton@genua.de\n\n");
+ exit(1);
+}
+
+
+/*******************************************************************
+write a string in unicoode format
+********************************************************************/
+int PutUniCode(char *dst,char *src)
+{
+ int ret = 0;
+ while (*src) {
+ dst[ret++] = src[0];
+ dst[ret++] = 0;
+ src++;
+ }
+ dst[ret++]=0;
+ dst[ret++]=0;
+ return(ret-2); /* the way they do the md4 hash they don't represent
+ the last null. ie 'A' becomes just 0x41 0x00 - not
+ 0x41 0x00 0x00 0x00 */
+}
+
+/*
+ print binary buffer as hex-string
+*/
+void printlanhash(char *tmp) {
+
+ int i;
+ unsigned char c;
+ char outbuffer[33];
+
+
+ /* build string from binary hash */
+ for(i=0;i<16;i++) {
+ c=tmp[i];
+ sprintf(outbuffer+2*i,"%x",(c>>4) & 0x0f);
+ sprintf(outbuffer+2*i+1,"%x",c & 0x0f);
+ }
+
+ /* convert to uppercase */
+ for(i=0;i<32;i++)
+ outbuffer[i] = toupper(outbuffer[i]);
+ outbuffer[32]='\0';
+
+ /* print out hex-string */
+ printf("%s",outbuffer);
+}
+
+
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.h b/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.h
new file mode 100644
index 00000000000..9a020b8d286
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/mkntpwd.h
@@ -0,0 +1,17 @@
+#include <memory.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+typedef short int16;
+typedef int int32;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef unsigned char uchar;
+
+#define MAX_STRING 255
+#define MAX_WORD 128
+#define LMPASSWDLEN 14
+#define NTPASSWDLEN 128
+#define FILENAMEBUFFER 128
diff --git a/examples/LDAP/smbldap-tools/mkntpwd/smbdes.c b/examples/LDAP/smbldap-tools/mkntpwd/smbdes.c
new file mode 100644
index 00000000000..e4f8280f9bc
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/mkntpwd/smbdes.c
@@ -0,0 +1,337 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+
+ a partial implementation of DES designed for use in the
+ SMB authentication protocol
+
+ Copyright (C) Andrew Tridgell 1997
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+/* NOTES:
+
+ This code makes no attempt to be fast! In fact, it is a very
+ slow implementation
+
+ This code is NOT a complete DES implementation. It implements only
+ the minimum necessary for SMB authentication, as used by all SMB
+ products (including every copy of Microsoft Windows95 ever sold)
+
+ In particular, it can only do a unchained forward DES pass. This
+ means it is not possible to use this code for encryption/decryption
+ of data, instead it is only useful as a "hash" algorithm.
+
+ There is no entry point into this code that allows normal DES operation.
+
+ I believe this means that this code does not come under ITAR
+ regulations but this is NOT a legal opinion. If you are concerned
+ about the applicability of ITAR regulations to this code then you
+ should confirm it for yourself (and maybe let me know if you come
+ up with a different answer to the one above)
+*/
+
+
+
+static int perm1[56] = {57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36,
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4};
+
+static int perm2[48] = {14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32};
+
+static int perm3[64] = {58, 50, 42, 34, 26, 18, 10, 2,
+ 60, 52, 44, 36, 28, 20, 12, 4,
+ 62, 54, 46, 38, 30, 22, 14, 6,
+ 64, 56, 48, 40, 32, 24, 16, 8,
+ 57, 49, 41, 33, 25, 17, 9, 1,
+ 59, 51, 43, 35, 27, 19, 11, 3,
+ 61, 53, 45, 37, 29, 21, 13, 5,
+ 63, 55, 47, 39, 31, 23, 15, 7};
+
+static int perm4[48] = { 32, 1, 2, 3, 4, 5,
+ 4, 5, 6, 7, 8, 9,
+ 8, 9, 10, 11, 12, 13,
+ 12, 13, 14, 15, 16, 17,
+ 16, 17, 18, 19, 20, 21,
+ 20, 21, 22, 23, 24, 25,
+ 24, 25, 26, 27, 28, 29,
+ 28, 29, 30, 31, 32, 1};
+
+static int perm5[32] = { 16, 7, 20, 21,
+ 29, 12, 28, 17,
+ 1, 15, 23, 26,
+ 5, 18, 31, 10,
+ 2, 8, 24, 14,
+ 32, 27, 3, 9,
+ 19, 13, 30, 6,
+ 22, 11, 4, 25};
+
+
+static int perm6[64] ={ 40, 8, 48, 16, 56, 24, 64, 32,
+ 39, 7, 47, 15, 55, 23, 63, 31,
+ 38, 6, 46, 14, 54, 22, 62, 30,
+ 37, 5, 45, 13, 53, 21, 61, 29,
+ 36, 4, 44, 12, 52, 20, 60, 28,
+ 35, 3, 43, 11, 51, 19, 59, 27,
+ 34, 2, 42, 10, 50, 18, 58, 26,
+ 33, 1, 41, 9, 49, 17, 57, 25};
+
+
+static int sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
+
+static int sbox[8][4][16] = {
+ {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
+ {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
+ {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
+ {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
+
+ {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
+ {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
+ {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
+ {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
+
+ {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
+ {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
+ {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
+ {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
+
+ {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
+ {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
+ {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
+ {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
+
+ {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
+ {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
+ {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
+ {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
+
+ {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
+ {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
+ {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
+ {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
+
+ {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
+ {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
+ {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
+ {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
+
+ {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
+ {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
+ {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
+ {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}};
+
+static void permute(char *out, char *in, int *p, int n)
+{
+ int i;
+ for (i=0;i<n;i++)
+ out[i] = in[p[i]-1];
+}
+
+static void lshift(char *d, int count, int n)
+{
+ char out[64];
+ int i;
+ for (i=0;i<n;i++)
+ out[i] = d[(i+count)%n];
+ for (i=0;i<n;i++)
+ d[i] = out[i];
+}
+
+static void concat(char *out, char *in1, char *in2, int l1, int l2)
+{
+ while (l1--)
+ *out++ = *in1++;
+ while (l2--)
+ *out++ = *in2++;
+}
+
+static void xor(char *out, char *in1, char *in2, int n)
+{
+ int i;
+ for (i=0;i<n;i++)
+ out[i] = in1[i] ^ in2[i];
+}
+
+static void dohash(char *out, char *in, char *key)
+{
+ int i, j, k;
+ char pk1[56];
+ char c[28];
+ char d[28];
+ char cd[56];
+ char ki[16][48];
+ char pd1[64];
+ char l[32], r[32];
+ char rl[64];
+
+ permute(pk1, key, perm1, 56);
+
+ for (i=0;i<28;i++)
+ c[i] = pk1[i];
+ for (i=0;i<28;i++)
+ d[i] = pk1[i+28];
+
+ for (i=0;i<16;i++) {
+ lshift(c, sc[i], 28);
+ lshift(d, sc[i], 28);
+
+ concat(cd, c, d, 28, 28);
+ permute(ki[i], cd, perm2, 48);
+ }
+
+ permute(pd1, in, perm3, 64);
+
+ for (j=0;j<32;j++) {
+ l[j] = pd1[j];
+ r[j] = pd1[j+32];
+ }
+
+ for (i=0;i<16;i++) {
+ char er[48];
+ char erk[48];
+ char b[8][6];
+ char cb[32];
+ char pcb[32];
+ char r2[32];
+
+ permute(er, r, perm4, 48);
+
+ xor(erk, er, ki[i], 48);
+
+ for (j=0;j<8;j++)
+ for (k=0;k<6;k++)
+ b[j][k] = erk[j*6 + k];
+
+ for (j=0;j<8;j++) {
+ int m, n;
+ m = (b[j][0]<<1) | b[j][5];
+
+ n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4];
+
+ for (k=0;k<4;k++)
+ b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0;
+ }
+
+ for (j=0;j<8;j++)
+ for (k=0;k<4;k++)
+ cb[j*4+k] = b[j][k];
+ permute(pcb, cb, perm5, 32);
+
+ xor(r2, l, pcb, 32);
+
+ for (j=0;j<32;j++)
+ l[j] = r[j];
+
+ for (j=0;j<32;j++)
+ r[j] = r2[j];
+ }
+
+ concat(rl, r, l, 32, 32);
+
+ permute(out, rl, perm6, 64);
+}
+
+static void str_to_key(unsigned char *str,unsigned char *key)
+{
+ int i;
+
+ key[0] = str[0]>>1;
+ key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
+ key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
+ key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
+ key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
+ key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
+ key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
+ key[7] = str[6]&0x7F;
+ for (i=0;i<8;i++) {
+ key[i] = (key[i]<<1);
+ }
+}
+
+
+static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key)
+{
+ int i;
+ char outb[64];
+ char inb[64];
+ char keyb[64];
+ unsigned char key2[8];
+
+ str_to_key(key, key2);
+
+ for (i=0;i<64;i++) {
+ inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
+ keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
+ outb[i] = 0;
+ }
+
+ dohash(outb, inb, keyb);
+
+ for (i=0;i<8;i++) {
+ out[i] = 0;
+ }
+
+ for (i=0;i<64;i++) {
+ if (outb[i])
+ out[i/8] |= (1<<(7-(i%8)));
+ }
+}
+
+void E_P16(unsigned char *p14,unsigned char *p16)
+{
+ unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
+ smbhash(p16, sp8, p14);
+ smbhash(p16+8, sp8, p14+7);
+}
+
+void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
+{
+ smbhash(p24, c8, p21);
+ smbhash(p24+8, c8, p21+7);
+ smbhash(p24+16, c8, p21+14);
+}
+
+void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key)
+{
+ unsigned char buf[8];
+
+ smbhash(buf, in, key);
+ smbhash(out, buf, key+9);
+}
+
+void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key)
+{
+ unsigned char buf[8];
+ static unsigned char key2[8];
+
+ smbhash(buf, in, key);
+ key2[0] = key[7];
+ smbhash(out, buf, key2);
+}
+
diff --git a/examples/LDAP/smbldap-tools/smbldap-groupadd.pl b/examples/LDAP/smbldap-tools/smbldap-groupadd.pl
new file mode 100755
index 00000000000..6ced1eed2d0
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-groupadd.pl
@@ -0,0 +1,86 @@
+#!/usr/bin/perl
+
+# $Id: smbldap-groupadd.pl,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+#
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# 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.
+
+# Purpose of smbldap-groupadd : group (posix) add
+
+use strict;
+use smbldap_tools;
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('og:?', \%Options);
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-go?] groupname\n";
+ print " -g gid\n";
+ print " -o gid is not unique\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+my $_groupName = $ARGV[0];
+
+if (defined(get_group_dn($_groupName))) {
+ print "$0: group $_groupName exists\n";
+ exit (6);
+}
+
+my $_groupGidNumber = $Options{'g'};
+
+if (!group_add($_groupName, $_groupGidNumber, $Options{'o'})) {
+ print "$0: error adding group $_groupName\n";
+ exit (6);
+}
+
+exit(0);
+
+########################################
+
+=head1 NAME
+
+ smbldap-groupadd.pl - Create a new group
+
+=head1 SYNOPSIS
+
+ smbldap-groupadd.pl [-g gid [-o]] group
+
+=head1 DESCRIPTION
+ The smbldap-groupadd.pl command creates a new group account using
+ the values specified on the command line and the default values
+ from the system. The new group will be entered into the system
+ files as needed. The options which apply to the groupadd command are
+
+ -g gid The numerical value of the group's ID. This value must be
+ unique, unless the -o option is used. The value must be non-
+ negative. The default is to use the smallest ID value greater
+ than 1000 and greater than every other group.
+
+=head1 SEE ALSO
+
+ groupadd(1)
+
+=cut
+
+#'
+
diff --git a/examples/LDAP/smbldap-tools/smbldap-groupdel.pl b/examples/LDAP/smbldap-tools/smbldap-groupdel.pl
new file mode 100755
index 00000000000..c5b64c3d4ef
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-groupdel.pl
@@ -0,0 +1,95 @@
+#!/usr/bin/perl
+
+# $Id: smbldap-groupdel.pl,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+#
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# 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.
+
+# Purpose of smbldap-groupdel : group (posix) deletion
+
+use strict;
+use smbldap_tools;
+use smbldap_conf;
+
+#####################
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('?', \%Options);
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 groupname\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+my $_groupName = $ARGV[0];
+
+my $dn_line;
+if (!defined($dn_line = get_group_dn($_groupName))) {
+ print "$0: group $_groupName doesn't exist\n";
+ exit (6);
+}
+
+my $dn = get_dn_from_line($dn_line);
+
+my $rc = system "$ldapdelete $dn >/dev/null";
+die "$0: error while deleting group $_groupName\n"
+ unless ($rc == 0);
+
+my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd restart > /dev/null 2>&1";
+}
+
+#if (defined($dn_line = get_group_dn($_groupName))) {
+# print "$0: failed to delete group\n";
+# exit (7);
+#}
+
+
+exit (0);
+
+############################################################
+
+=head1 NAME
+
+ smbldap-groupdel.pl - Delete a group
+
+=head1 SYNOPSIS
+
+ smbldap-groupdel.pl group
+
+=head1 DESCRIPTION
+
+ The smbldap-groupdel.pl command modifies the system account files,
+ deleting all entries that refer to group. The named group must exist.
+
+ You must manually check all filesystems to insure that no files remain
+ with the named group as the file group ID.
+
+=head1 SEE ALSO
+
+ groupdel(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-groupmod.pl b/examples/LDAP/smbldap-tools/smbldap-groupmod.pl
new file mode 100755
index 00000000000..a35e7ea898d
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-groupmod.pl
@@ -0,0 +1,213 @@
+#!/usr/bin/perl
+
+# $Id: smbldap-groupmod.pl,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+#
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# 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.
+
+# Purpose of smbldap-groupmod : group (posix) modification
+
+
+use strict;
+use smbldap_tools;
+use smbldap_conf;
+
+
+#####################
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('og:n:m:x:?', \%Options);
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-g gid [-o]] [-n name] [-m members(,)] [-x members (,)] groupname\n";
+ print " -g new gid\n";
+ print " -o gid is not unique\n";
+ print " -n new group name\n";
+ print " -m add members (comma delimited)\n";
+ print " -x delete members (comma delimted)\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+my $groupName = $ARGV[0];
+
+if (!defined(get_group_dn($groupName))) {
+ print "$0: group $groupName doesn't exist\n";
+ exit (6);
+}
+
+my $newname = $Options{'n'};
+
+my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd restart > /dev/null 2>&1";
+}
+
+my $gid = getgrnam($groupName);
+
+my $tmp;
+if (defined($tmp = $Options{'g'}) and $tmp =~ /\d+/) {
+ if (!defined($Options{'o'})) {
+ if (defined(getgrgid($tmp))) {
+ print "$0: gid $tmp exists\n";
+ exit (6);
+ }
+ }
+ if (!($gid == $tmp)) {
+ my $tmpldif =
+"dn: cn=$groupName,$groupsdn
+changetype: modify
+replace: gidNumber
+gidNumber: $tmp
+
+";
+ die "$0: error while modifying group $groupName\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+
+ }
+}
+
+if (defined($newname)) {
+ my $FILE="|$ldapmodrdn >/dev/null";
+ open (FILE, $FILE) || die "$!\n";
+ print FILE <<EOF;
+cn=$groupName,$groupsdn
+cn=$newname
+
+EOF
+ ;
+ close FILE;
+ die "$0: error while modifying group $groupName\n" if ($?);
+
+ my $tmpldif =
+"dn: cn=$newname,$groupsdn
+changetype: modify
+delete: cn
+-
+add: cn
+cn: $newname
+
+";
+ die "$0: error while modifying group $groupName\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+
+}
+
+# Add members
+if (defined($Options{'m'})) {
+ my $members = $Options{'m'};
+ my @members = split( /,/, $members );
+ my $member;
+ foreach $member ( @members ) {
+ my $tmpldif =
+"dn: cn=$groupName,$groupsdn
+changetype: modify
+add: memberUid
+memberUid: $member
+
+";
+ die "$0: error while modifying group $groupName\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+ }
+}
+
+# Delete members
+if (defined($Options{'x'})) {
+ my $members = $Options{'x'};
+ my @members = split( /,/, $members );
+ my $member;
+ foreach $member ( @members ) {
+ my $tmpldif =
+"dn: cn=$groupName,$groupsdn
+changetype: modify
+delete: memberUid
+memberUid: $member
+
+";
+ die "$0: error while modifying group $groupName\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+ }
+}
+
+$nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd restart > /dev/null 2>&1";
+}
+
+exit (0);
+
+############################################################
+
+=head1 NAME
+
+ smbldap-groupmod.pl - Modify a group
+
+=head1 SYNOPSIS
+
+ smbldap-groupmod.pl [-g gid [-o]] [-n group_name ] group
+
+=head1 DESCRIPTION
+
+ The smbldap-groupmod.pl command modifies the system account files to
+ reflect the changes that are specified on the command line.
+ The options which apply to the smbldap-groupmod command are
+
+ -g gid The numerical value of the group's ID. This value must be
+ unique, unless the -o option is used. The value must be non-
+ negative. Any files which the old group ID is the file
+ group ID must have the file group ID changed manually.
+
+ -n group_name
+ The name of the group will be changed from group to group_name.
+
+ -m members
+ The members to be added to the group in comma-delimeted form.
+
+ -x members
+ The members to be removed from the group in comma-delimted form.
+
+=head1 EXAMPLES
+
+ smbldap-groupmod.pl -g 253 development
+ This will change the GID of the 'development' group to '253'.
+
+ smbldap-groupmod.pl -n Idiots Managers
+ This will change the name of the 'Managers' group to 'Idiots'.
+
+ smbldap-groupmod.pl -m "jdoe,jsmith" "Domain Admins"
+ This will add 'jdoe' and 'jsmith' to the 'Domain Admins' group.
+
+ smbldap-groupmod.pl -x "jdoe,jsmith" "Domain Admins"
+ This will remove 'jdoe' and 'jsmith' from the 'Domain Admins' group.
+
+=head1 SEE ALSO
+
+ groupmod(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-groupshow.pl b/examples/LDAP/smbldap-tools/smbldap-groupshow.pl
new file mode 100755
index 00000000000..2426b85fa83
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-groupshow.pl
@@ -0,0 +1,74 @@
+#!/usr/bin/perl
+
+# $Id: smbldap-groupshow.pl,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+#
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# 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.
+
+# Purpose of smbldap-groupshow : user (posix,shadow,samba) display
+#
+# History :
+# . originally by David Le Corfec <david.le-corfec@IDEALX.com>
+
+use strict;
+use smbldap_tools;
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('?', \%Options);
+
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-?] group\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+# Read only first @ARGV
+my $group = $ARGV[0];
+
+my $lines = read_group($group);
+if (!defined($lines)) {
+ print "$0: group $group doesn't exist\n";
+ exit (1);
+}
+
+print "$lines\n";
+
+exit(0);
+
+############################################################
+
+=head1 NAME
+
+ smbldap-groupshow.pl - Display group informations
+
+=head1 SYNOPSIS
+
+ smbldap-groupshow.pl groupname
+
+=head1 DESCRIPTION
+
+ The smbldap-groupshow.pl command displays informations
+ associated with the given group.
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl b/examples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl
new file mode 100755
index 00000000000..dd66954c41b
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-migrate-accounts.pl
@@ -0,0 +1,236 @@
+#!/usr/bin/perl
+
+# $Id: smbldap-migrate-accounts.pl,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+#
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2002 IDEALX
+#
+# 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.
+
+# Purpose of smbldap-migrate-accounts : add NT sam entries from pwdump
+# to ldap
+
+use strict;
+use Getopt::Std;
+use smbldap_tools;
+use smbldap_conf;
+
+# smbldap-migrate.pl (-? for help)
+#
+# Read pwdump entries on stdin, and add them to the ldap server.
+# Output uncreated/unmodified entries (see parameters -C -U)
+# in pwdump format to stdout.
+# Errors, debug and stats are output to stderr.
+
+sub modify_account
+{
+ my ($login, $basedn, $lmpwd, $ntpwd, $gecos, $homedir) = @_;
+
+ my $tmpldif =
+"dn: uid=$login,$basedn
+changetype: modify
+lmpassword: $lmpwd
+ntpassword: $ntpwd
+gecos: $gecos
+smbHome: $homedir
+
+";
+
+ die "$0: error while modifying user $login\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+}
+
+#####################
+
+
+my %Options;
+
+my $ok = getopts('awA:CUW:?', \%Options);
+
+if ( (!$ok) || ($Options{'?'}) ) {
+ print "Usage: $0 [-awAWCU?]\n";
+ print " -a process only people, ignore computers\n";
+ print " -w process only computers, ignore persons\n";
+ print " -A <opts> option string passed verbatim to smbldap-useradd for persons\n";
+ print " -W <opts> option string passed verbatim to smbldap-useradd for computers\n";
+ print " -C if entry not found, don't create it and log it to stdout (default: create it)\n";
+ print " -U if entry found, don't update it and log it to stdout (default: update it)\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+my %processed = ( 'user' => 0, 'machine' => 0);
+my %created = ( 'user' => 0, 'machine' => 0);
+my %updated = ( 'user' => 0, 'machine' => 0);
+my %logged = ( 'user' => 0, 'machine' => 0);
+my %errors = ( 'user' => 0, 'machine' => 0);
+my %existing = ( 'user' => 0, 'machine' => 0);
+my $specialskipped = 0;
+
+while (<>)
+{
+ my ($login, $rid, $lmpwd, $ntpwd, $gecos, $homedir, $b) = split(/:/, $_);
+ my $usertype;
+ my $userbasedn;
+
+ my $entry_type = 'user';
+
+ if ($login =~ m/.*\$$/ ) { # computer
+ $processed{'machine'}++;
+ $entry_type = 'machine';
+ if (defined($Options{'a'})) {
+ print STDERR "ignoring $login\n";
+ next;
+ }
+
+ $usertype = "-w $Options{'W'}";
+ $userbasedn = $computersdn;
+ }
+ else { # people
+ $processed{'user'}++;
+ if (defined($Options{'w'})) {
+ print STDERR "ignoring $login\n";
+ next;
+ }
+ if ($rid < 1000) {
+ $specialskipped++;
+ print STDERR "$login seems to be a special Win account (rid=$rid), skipping\n";
+ next;
+ }
+
+ $usertype = "-a $Options{'A'}";
+ $userbasedn = $usersdn;
+ }
+
+ # normalize homedir
+# uncomment to replace configured share with share from pwdump
+# if ($homedir eq "") {
+ $homedir = $_userSmbHome;
+# }
+
+ # normalize gecos
+ if (!($gecos eq "")) {
+ $gecos =~ tr/ÁÀÂÄáàâäÇçÉÈÊËÆéèêëæÍÌÏÎíìîÏÑñÓÒÔÖóòôöÚÙÜÛúùüûÝýÿ/AAAAaaaaCcEEEEEeeeeeIIIIiiiiNnOOOOooooUUUUuuuuYyy/;
+ } else {
+ $gecos = $_userGecos;
+ }
+
+ my $user_exists = is_samba_user($login);
+
+ if (!$user_exists) {
+ if (!defined($Options{'C'})) {
+ # uid doesn't exist and we want to create it
+ my $addcmd = "/usr/local/sbin/smbldap-useradd.pl $usertype $login > /dev/null";
+ print STDERR "$addcmd\n";
+ my $r = system "$addcmd";
+ if ($r != 0) {
+ print STDERR "error adding $login, skipping\n";
+ next;
+ }
+ # lem modif... a retirer si pb
+ if ($entry_type eq "user")
+ {
+ modify_account($login, $userbasedn, $lmpwd, $ntpwd, $gecos, $homedir);
+ }
+
+ $created{$entry_type}++;
+ }
+ else { # uid doesn't exist and no create => log
+ print "$_";
+ $logged{$entry_type}++;
+ }
+ }
+ else { # account exists
+ $existing{$entry_type}++;
+ if (!defined($Options{'U'})) { # exists and modify
+ modify_account($login, $userbasedn, $lmpwd, $ntpwd, $gecos, $homedir);
+ $updated{$entry_type}++;
+ }
+ else { # exists and log
+ print "$_";
+ $logged{$entry_type}++;
+ }
+ }
+}
+
+my $sum;
+
+$sum = $processed{'user'} + $processed{'machine'};
+print STDERR "processed: all=$sum user=$processed{'user'} machine=$processed{'machine'}\n";
+
+$sum = $existing{'user'} + $existing{'machine'};
+print STDERR "existing: all=$sum user=$existing{'user'} machine=$existing{'machine'}\n";
+
+$sum = $created{'user'} + $created{'machine'};
+print STDERR "created: all=$sum user=$created{'user'} machine=$created{'machine'}\n";
+
+$sum = $updated{'user'} + $updated{'machine'};
+print STDERR "updated: all=$sum user=$updated{'user'} machine=$updated{'machine'}\n";
+
+$sum = $logged{'user'} + $logged{'machine'};
+print STDERR "logged: all=$sum user=$logged{'user'} machine=$logged{'machine'}\n";
+
+print STDERR "special users skipped: $specialskipped\n";
+
+
+########################################
+
+=head1 NAME
+
+ smbldap-migrate.pl - Migrate NT accounts to LDAP
+
+=head1 SYNOPSIS
+
+ smbldap-migrate.pl [-a] [-w] [-A opts] [-W opts] [-C] [-U] [-?]
+
+=head1 DESCRIPTION
+
+ This command reads from stdin account entries as created by pwdump,
+ a tool to dump an user database on NT.
+ Depending of the options, some account entries may be output on
+ stdout. All errors and informations are sent to stderr.
+
+ -a process only people, ignore computers
+
+ -w process only computers, ignore persons
+
+ -A opts
+ a string containing arguments to pass verbatim to
+ smbldap-useradd when adding users, eg "-m -x".
+ You don't have to specify -a in this string.
+
+ -W opts
+ a string containing arguments to pass verbatim to
+ smbldap-useradd when adding computers, eg "-m -x".
+ You don't have to specify -w in this string.
+
+ -C if NT account not found in LDAP, don't create it and log it to stdout
+ (default: create it)
+
+ -U if NT account found in LDAP, don't update it and log it to stdout
+ (default: update it)
+
+ -? show the help message
+
+=cut
+
+#'
+
+# The End
+
diff --git a/examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl b/examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl
new file mode 100644
index 00000000000..8be0c1b72be
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-migrate-groups.pl
@@ -0,0 +1,227 @@
+#!/usr/bin/perl
+
+# $Id: smbldap-migrate-groups.pl,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+#
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2002 IDEALX
+#
+# 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.
+
+# Purpose of smbldap-migrate-groups : to parse a Windows
+# group dump and populate Unix groups
+# Reads group dump on stdin
+
+
+use strict;
+use smbldap_tools;
+use smbldap_conf;
+use Getopt::Std;
+
+
+
+sub process_rec_group
+{
+ my ($group, $mb) = @_;
+ my @members;
+
+ if (!(@members = group_get_members($group))) {
+ return 0;
+ }
+
+ foreach my $m (@members) {
+ if ( !($m =~ m/^\*/) ) {
+ push @{$mb}, $m;
+ } else {
+ my $gname = $m;
+ $gname =~ s/^.//;
+ if (!process_rec_group($gname, $mb)) {
+ print "recursive group not added : $gname\n";
+ }
+ }
+ }
+}
+
+
+# given a group dn and a list of members, update the group
+sub modify_group
+{
+ my ($group, $dn_line, @members, $recgroup) = @_;
+ my $m;
+ my @new_mb;
+
+ foreach $m (@members) {
+ if ( ($m =~ m/^\*/) ) {
+ my $gname = $m;
+ $gname =~ s/^.//;
+ if (!$recgroup) {
+ print "recursive group not added : $gname\n";
+ } else {
+ if (!process_rec_group($gname, \@new_mb)) {
+ print "recursive group not added : $gname\n";
+ }
+ }
+ } else {
+ push @new_mb, $m;
+ }
+ }
+
+ # new_mb contains flat members from group dump
+ # now append them to existing members
+ push @new_mb, group_get_members($group);
+ # uniq them
+ my %saw;
+ @saw{@new_mb} = ();
+ @new_mb = keys %saw;
+
+ my $nmb = $#new_mb + 1;
+ print STDERR "Group $group now has $nmb member(s)\n";
+
+ my $mbs;
+ foreach $m (@new_mb) {
+ $mbs .= "memberUid: $m\n";
+ }
+
+ my $mods="$dn_line
+changetype: modify
+replace: memberUid
+$mbs
+";
+
+ #print "$mods\n";
+ my $tmpldif =
+"$mods
+";
+
+ die "$0: error while modifying group $group\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+}
+
+sub display_group
+{
+ my ($group, @members) = @_;
+
+ print "Group name $group\n";
+ print "Members\n";
+ my $m;
+ my $i = 0;
+ foreach $m (@members) {
+ print "$m ";
+ if ($i % 5 == 0) {
+ print "\n";
+ }
+ $i++;
+ }
+}
+
+sub process_group
+{
+ my ($group, @members, $nocreate, $noupdate, $recgroup) = @_;
+
+ my $dn_line;
+ if (!defined($dn_line = get_group_dn($group))) {
+ # group not found, create it ?
+ if (!$nocreate) {
+ system "/usr/local/sbin/smbldap-groupadd.pl \"$group\"; sleep 5";
+ if (!defined($dn_line = get_group_dn($group))) {
+ return 1;
+ }
+ modify_group($group, $dn_line, @members, $recgroup);
+ } else {
+ # don't create
+ print "not created:\n";
+ display_group($group, @members);
+ }
+ } else {
+ # group found, update it ?
+ if (!$noupdate) {
+ modify_group($group, $dn_line, @members, $recgroup);
+ } else {
+ # don't update
+ print "not updated:\n";
+ display_group($group, @members);
+ }
+ }
+}
+
+###################################################
+
+my %Options;
+
+my $ok = getopts('CUr?', \%Options);
+if ( (!$ok) || ($Options{'?'}) ) {
+ print "Usage: $0 [-CUr?] < group_dump\n";
+ print " -C don't create group if it doesn't exist\n";
+ print " -U don't update group if it exists\n";
+ print " -r recursively process groups\n";
+ exit(1);
+}
+
+my $group_name;
+my $group_desc;
+my $has_members = 0;
+my @members = ();
+
+while (<>)
+{
+ my $line = $_;
+ chomp($line);
+ next if ( $line =~ m/^\s*$/ );
+
+ if ($group_name eq "") {
+ if ( $line =~ m/^Group name\s+(.+).$/ ) {
+ $group_name = $1;
+ next;
+ }
+ }
+ if ($group_desc eq "") {
+ if ( $line =~ m/^Comment\s+(.*)$/ ) {
+ $group_desc = $1;
+ next;
+ }
+ }
+ next if ( $line =~ m/^-+.$/ );
+ if (!$has_members) {
+ if ( $line =~ m/^Members/ ) {
+ $has_members = 1;
+ next;
+ }
+ } else {
+ if ( $line =~ m/^The command completed successfully/ ) {
+ last;
+ } else {
+ push(@members, split(/\s+/, $line));
+ next;
+ }
+ }
+
+ #print;
+}
+
+if ( $#members > -1) {
+ process_group($group_name, @members, $Options{'C'}, $Options{'U'}, $Options{'r'});
+}
+
+#print "gn=$group_name\n";
+#print "gd=$group_desc\n";
+#my $m;
+#foreach $m (@members)
+#{
+# print "$m ";
+#}
+#print "\n";
diff --git a/examples/LDAP/smbldap-tools/smbldap-passwd.pl b/examples/LDAP/smbldap-tools/smbldap-passwd.pl
new file mode 100755
index 00000000000..325c7718328
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-passwd.pl
@@ -0,0 +1,217 @@
+#!/usr/bin/perl
+
+# LDAP to unix password sync script for samba
+# $Id: smbldap-passwd.pl,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# 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.
+
+# Purpose :
+# . ldap-unix passwd sync for SAMBA-2.2.2 + LDAP
+# . may also replace /bin/passwd
+
+use strict;
+use smbldap_tools;
+use smbldap_conf;
+
+my $user;
+my $oldpass;
+my $ret;
+
+my $arg;
+
+foreach $arg (@ARGV) {
+ if ($< != 0) {
+ die "Only root can specify parameters\n";
+ } else {
+ if ( ($arg eq '-?') || ($arg eq '--help') ) {
+ print "Usage: $0 [username]\n";
+ print " -?, --help show this help message\n";
+ exit (6);
+ } elsif (substr($arg,0) ne '-') {
+ $user = $arg;
+ }
+ $oldpass = 1;
+ }
+}
+
+if (!defined($user)) {
+ $user=$ENV{"USER"};
+}
+
+# test existence of user in LDAP
+my $dn_line;
+if (!defined($dn_line = get_user_dn($user))) {
+ print "$0: user $user doesn't exist\n";
+ exit (10);
+}
+
+my $dn = get_dn_from_line($dn_line);
+
+my $samba = is_samba_user($user);
+
+print "Changing password for $user\n";
+
+# non-root user
+if (!defined($oldpass)) {
+ # prompt for current password
+ system "stty -echo";
+ print "(current) UNIX password: ";
+ chomp($oldpass=<STDIN>);
+ print "\n";
+ system "stty echo";
+
+ if (!is_user_valid($user, $dn, $oldpass)) {
+ print "Authentication failure\n";
+ exit (10);
+ }
+}
+
+# prompt for new password
+
+my $pass;
+my $pass2;
+
+system "stty -echo";
+print "New password : ";
+chomp($pass=<STDIN>);
+print "\n";
+system "stty echo";
+
+system "stty -echo";
+print "Retype new password : ";
+chomp($pass2=<STDIN>);
+print "\n";
+system "stty echo";
+
+if ($pass ne $pass2) {
+ print "New passwords don't match!\n";
+ exit (10);
+}
+
+# only modify smb passwords if smb user
+if ($samba == 1) {
+ if (!$with_smbpasswd) {
+# generate LanManager and NT clear text passwords
+ if ($mk_ntpasswd eq '') {
+ print "Either set \$with_smbpasswd = 1 or specify \$mk_ntpasswd\n";
+ exit(1);
+ }
+ my $ntpwd = `$mk_ntpasswd '$pass'`;
+ chomp(my $lmpassword = substr($ntpwd, 0, index($ntpwd, ':')));
+ chomp(my $ntpassword = substr($ntpwd, index($ntpwd, ':')+1));
+
+# change nt/lm passwords
+ my $tmpldif =
+"$dn_line
+changetype: modify
+replace: lmpassword
+lmpassword: $lmpassword
+-
+changetype: modify
+replace: ntpassword
+ntpassword: $ntpassword
+-
+
+";
+ die "$0: error while modifying password for $user\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+ }
+ else {
+ if ($< != 0) {
+ my $FILE="|$smbpasswd -s >/dev/null";
+ open (FILE, $FILE) || die "$!\n";
+ print FILE <<EOF;
+'$oldpass'
+'$pass'
+'$pass'
+EOF
+ ;
+ close FILE;
+ } else {
+ my $FILE="|$smbpasswd $user -s >/dev/null";
+ open (FILE, $FILE) || die "$!\n";
+ print FILE <<EOF;
+'$pass'
+'$pass'
+EOF
+ ;
+ close FILE;
+ }
+ }
+}
+# change unix password
+$ret = system "$ldappasswd $dn -s '$pass' > /dev/null";
+if ($ret == 0) {
+ print "all authentication tokens updated successfully\n";
+} else {
+ return $ret;
+}
+
+exit 0;
+
+
+# - The End
+
+=head1 NAME
+
+smbldap-passwd.pl - change user password
+
+=head1 SYNOPSIS
+
+ smbldap-passwd.pl [name]
+
+=head1 DESCRIPTION
+
+ smbldap-passwd.pl changes passwords for user accounts. A normal user
+ may only change the password for their own account, the super user may
+ change the password for any account.
+
+ Password Changes
+ The user is first prompted for their old password, if one is present.
+ This password is then tested against the stored password by binding
+ to the server. The user has only one chance to enter the correct pass-
+ word. The super user is permitted to bypass this step so that forgot-
+ ten passwords may be changed.
+
+ The user is then prompted for a replacement password. As a general
+ guideline, passwords should consist of 6 to 8 characters including
+ one or more from each of following sets:
+
+ Lower case alphabetics
+
+ Upper case alphabetics
+
+ Digits 0 thru 9
+
+ Punctuation marks
+
+ passwd will prompt again and compare the second entry against the first.
+ Both entries are require to match in order for the password to be
+ changed.
+
+=head1 SEE ALSO
+
+ passwd(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-populate.pl b/examples/LDAP/smbldap-tools/smbldap-populate.pl
new file mode 100755
index 00000000000..11bc599d865
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-populate.pl
@@ -0,0 +1,296 @@
+#!/usr/bin/perl
+
+# Populate a LDAP base for Samba-LDAP usage
+#
+# $Id: smbldap-populate.pl,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# 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.
+
+# Purpose :
+# . Create an initial LDAP database suitable for Samba 2.2
+# . For lazy people, replace ldapadd (with only an ldif parameter)
+
+use strict;
+use smbldap_tools;
+use smbldap_conf;
+
+use Getopt::Std;
+
+use vars qw(%oc);
+
+# objectclass of the suffix
+%oc = (
+ "ou" => "organizationalUnit",
+ "o" => "organization",
+ "dc" => "dcObject",
+);
+
+
+my %Options;
+
+my $ok = getopts('a:b:?', \%Options);
+if ( (!$ok) || ($Options{'?'}) ) {
+ print "Usage: $0 [-ab?] [ldif]\n";
+ print " -a administrator login name (default: Administrator)\n";
+ print " -b guest login name (default: nobody)\n";
+ print " -? show this help message\n";
+ print " ldif file to add to ldap (default: suffix, Groups,";
+ print " Users, Computers and builtin users )\n";
+ exit (1);
+}
+
+my $_ldifName;
+
+if (@ARGV >= 1) {
+ $_ldifName = $ARGV[0];
+}
+
+my $adminName = $Options{'a'};
+if (!defined($adminName)) {
+ $adminName = "Administrator";
+}
+
+my $guestName = $Options{'b'};
+if (!defined($guestName)) {
+ $guestName = "nobody";
+}
+
+if (!defined($_ldifName)) {
+ my $attr;
+ my $val;
+ my $objcl;
+
+ if ($suffix =~ m/([^=]+)=([^,]+)/) {
+ $attr = $1;
+ $val = $2;
+ $objcl = $oc{$attr} if (exists $oc{$attr});
+ if (!defined($objcl)) {
+ $objcl = "myhardcodedobjectclass";
+ }
+ } else {
+ die "can't extract first attr and value from suffix $suffix";
+ }
+ #print "$attr=$val\n";
+
+ #my $FILE="|cat";
+ my $FILE="|$ldapadd -c";
+ open (FILE, $FILE) || die "$!\n";
+
+ print FILE <<EOF;
+dn: $suffix
+objectClass: $objcl
+$attr: $val
+
+dn: $usersdn
+objectClass: organizationalUnit
+ou: $usersou
+
+dn: $groupsdn
+objectClass: organizationalUnit
+ou: $groupsou
+
+dn: $computersdn
+objectClass: organizationalUnit
+ou: $computersou
+
+dn: uid=$adminName,$usersdn
+cn: $adminName
+objectClass: sambaAccount
+objectClass: posixAccount
+gidNumber: 512
+uid: $adminName
+uidNumber: 998
+homeDirectory: $_userHomePrefix
+pwdLastSet: 0
+logonTime: 0
+logoffTime: 2147483647
+kickoffTime: 2147483647
+pwdCanChange: 0
+pwdMustChange: 2147483647
+smbHome: $_userSmbHome
+homeDrive: $_userHomeDrive
+profilePath: $_userProfile
+rid: 500
+primaryGroupID: 512
+lmPassword: XXX
+ntPassword: XXX
+acctFlags: [U ]
+loginShell: /bin/false
+gecos: Netbios Domain Administrator
+
+dn: uid=$guestName,$usersdn
+cn: $guestName
+objectClass: sambaAccount
+objectClass: posixAccount
+gidNumber: 514
+uid: $guestName
+uidNumber: 999
+homeDirectory: /dev/null
+pwdLastSet: 0
+logonTime: 0
+logoffTime: 2147483647
+kickoffTime: 2147483647
+pwdCanChange: 0
+pwdMustChange: 2147483647
+smbHome: $_userSmbHome
+homeDrive: $_userHomeDrive
+profilePath: $_userProfile
+rid: 501
+primaryGroupID: 514
+lmPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
+ntPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
+acctFlags: [NU ]
+loginShell: /bin/false
+
+dn: cn=Domain Admins,$groupsdn
+objectClass: posixGroup
+gidNumber: 512
+cn: Domain Admins
+memberUid: $adminName
+description: Netbios Domain Administrators (need smb.conf configuration)
+
+dn: cn=Domain Users,$groupsdn
+objectClass: posixGroup
+gidNumber: 513
+cn: Domain Users
+description: Netbios Domain Users (not implemented yet)
+
+dn: cn=Domain Guests,$groupsdn
+objectClass: posixGroup
+gidNumber: 514
+cn: Domain Guests
+description: Netbios Domain Guests Users (not implemented yet)
+
+dn: cn=Administrators,$groupsdn
+objectClass: posixGroup
+gidNumber: 544
+cn: Administrators
+description: Netbios Domain Members can fully administer the computer/domain (not implemented yet)
+
+dn: cn=Users,$groupsdn
+objectClass: posixGroup
+gidNumber: 545
+cn: Users
+description: Netbios Domain Ordinary users (not implemented yet)
+
+dn: cn=Guests,$groupsdn
+objectClass: posixGroup
+gidNumber: 546
+cn: Guests
+memberUid: $guestName
+description: Netbios Domain Users granted guest access to the computer/domain (not implemented yet)
+
+
+dn: cn=Power Users,$groupsdn
+objectClass: posixGroup
+gidNumber: 547
+cn: Power Users
+description: Netbios Domain Members can share directories and printers (not implemented yet)
+
+dn: cn=Account Operators,$groupsdn
+objectClass: posixGroup
+gidNumber: 548
+cn: Account Operators
+description: Netbios Domain Users to manipulate users accounts (not implemented yet)
+
+dn: cn=Server Operators,$groupsdn
+objectClass: posixGroup
+gidNumber: 549
+cn: Server Operators
+description: Netbios Domain Server Operators (need smb.conf configuration)
+
+dn: cn=Print Operators,$groupsdn
+objectClass: posixGroup
+gidNumber: 550
+cn: Print Operators
+description: Netbios Domain Print Operators (need smb.conf configuration)
+
+dn: cn=Backup Operators,$groupsdn
+objectClass: posixGroup
+gidNumber: 551
+cn: Backup Operators
+description: Netbios Domain Members can bypass file security to back up files (not implemented yet)
+
+dn: cn=Replicator,$groupsdn
+objectClass: posixGroup
+gidNumber: 552
+cn: Replicator
+description: Netbios Domain Supports file replication in a domain (not implemented yet)
+
+dn: cn=Domain Computers,$groupsdn
+objectClass: posixGroup
+gidNumber: 553
+cn: Domain Computers
+description: Netbios Domain Computers accounts
+
+EOF
+ close FILE;
+ exit($?)
+
+} else {
+ exec "$ldapadd < $_ldifName";
+}
+
+exit(0);
+
+
+########################################
+
+=head1 NAME
+
+ smbldap-populate.pl - Populate your LDAP database
+
+=head1 SYNOPSIS
+
+ smbldap-populate.pl [ldif-file]
+
+=head1 DESCRIPTION
+
+ The smbldap-populate.pl command helps to populate an LDAP server
+ by adding the necessary entries : base suffix (doesn't abort
+ if already there), organizational units for users, groups and
+ computers, builtin users : Administrator and guest, builtin
+ groups (though posixAccount only, no SambaTNG support).
+
+ -a name Your local administrator login name (default: Administrator)
+ -b name Your local guest login name (default: nobody)
+
+ If you give an extra parameter, it is assumed to be the ldif
+ file to use instead of the builtin one. Options -a and -b
+ will be ignored. This usage mode makes the command behave
+ like ldapadd(1) with extra parameters taken from the smbldap-tools
+ config (smbldap_conf.pm).
+
+=head1 FILES
+
+ /usr/lib/perl5/site-perl/smbldap_conf.pm : Global parameters.
+
+=head1 SEE ALSO
+
+ smp(1)
+
+=cut
+
+#'
+
+
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/smbldap-tools.spec b/examples/LDAP/smbldap-tools/smbldap-tools.spec
new file mode 100755
index 00000000000..7bb438cb321
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-tools.spec
@@ -0,0 +1,169 @@
+# $Source: /data/src/mirror/cvs/samba/examples/LDAP/smbldap-tools/smbldap-tools.spec,v $
+%define version 0.7
+%define release 1
+%define name smbldap-tools
+%define realname smbldap-tools
+
+Summary: User & Group administration tools for Samba-OpenLDAP
+Name: %{name}
+version: %{version}
+Release: %{release}
+Group: System Environment/Base
+License: GPL
+
+Vendor: IDEALX S.A.S.
+URL: http://samba.IDEALX.org/
+Packager: Olivier Lemaire <olivier.lemaire@IDEALX.com>
+Source0: smbldap-groupadd.pl
+Source1: smbldap-groupdel.pl
+Source2: smbldap-groupmod.pl
+Source3: smbldap-groupshow.pl
+Source4: smbldap-passwd.pl
+Source5: smbldap-useradd.pl
+Source6: smbldap-userdel.pl
+Source7: smbldap-usermod.pl
+Source8: smbldap-usershow.pl
+Source9: smbldap_conf.pm
+Source10: smbldap_tools.pm
+Source11: CONTRIBUTORS
+Source12: COPYING
+Source13: ChangeLog
+Source14: FILES
+Source15: README
+Source16: TODO
+Source17: mkntpwd.tar.gz
+Source18: smbldap-populate.pl
+Source19: smbldap-migrate-accounts.pl
+Source20: smbldap-migrate-groups.pl
+Source21: INFRA
+BuildRoot: /%{_tmppath}/%{name}
+Prefix: /usr/local
+BuildRequires: perl >= 5.6
+Requires: perl >= 5.6, openldap, openldap-clients, samba
+
+%description
+In settings with OpenLDAP and Samba-LDAP servers, this collection is
+useful to add, modify and delete users and groups, and to change
+Unix and Samba passwords. In those context they replace the system
+tools to manage users, groups and passwords.
+
+%prep
+
+%setup -c -T
+
+%build
+tar zxvf %{SOURCE17}
+cd mkntpwd
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/%{prefix}/sbin
+mkdir -p $RPM_BUILD_ROOT/%{prefix}/share
+mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc
+mkdir -p $RPM_BUILD_ROOT/%{prefix}/share/doc/smbldap-tools
+
+cd mkntpwd ; make PREFIX=$RPM_BUILD_ROOT/%{prefix} install
+
+install -m 550 %{SOURCE0} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-groupadd.pl
+install -m 550 %{SOURCE1} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-groupdel.pl
+install -m 550 %{SOURCE2} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-groupmod.pl
+install -m 555 %{SOURCE3} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-groupshow.pl
+install -m 555 %{SOURCE4} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-passwd.pl
+install -m 550 %{SOURCE5} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-useradd.pl
+install -m 550 %{SOURCE6} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-userdel.pl
+install -m 550 %{SOURCE7} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-usermod.pl
+install -m 555 %{SOURCE8} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-usershow.pl
+install -m 550 %{SOURCE18} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-populate.pl
+install -m 751 %{SOURCE9} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap_conf.pm
+install -m 555 %{SOURCE10} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap_tools.pm
+install -m 550 %{SOURCE19} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-migrate-accounts.pl
+install -m 550 %{SOURCE20} $RPM_BUILD_ROOT/%{prefix}/sbin/smbldap-migrate-groups.pl
+
+install -m 644 %{SOURCE11} $RPM_BUILD_ROOT/%{prefix}/share/doc/smbldap-tools/CONTRIBUTORS
+install -m 644 %{SOURCE12} $RPM_BUILD_ROOT/%{prefix}/share/doc/smbldap-tools/COPYING
+install -m 644 %{SOURCE13} $RPM_BUILD_ROOT/%{prefix}/share/doc/smbldap-tools/ChangeLog
+install -m 644 %{SOURCE14} $RPM_BUILD_ROOT/%{prefix}/share/doc/smbldap-tools/FILES
+install -m 644 %{SOURCE15} $RPM_BUILD_ROOT/%{prefix}/share/doc/smbldap-tools/README
+install -m 644 %{SOURCE16} $RPM_BUILD_ROOT/%{prefix}/share/doc/smbldap-tools/TODO
+install -m 644 %{SOURCE21} $RPM_BUILD_ROOT/%{prefix}/share/doc/smbldap-tools/INFRA
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+ln -sf %{prefix}/sbin/smbldap_tools.pm /usr/lib/perl5/site_perl/smbldap_tools.pm
+ln -sf %{prefix}/sbin/smbldap_conf.pm /usr/lib/perl5/site_perl/smbldap_conf.pm
+chgrp 512 %{prefix}/sbin/smbldap-useradd.pl %{prefix}/sbin/smbldap_conf.pm || echo "An error occured while changing groups of smbldap-useradd.pl and smbldap_conf.pm in /usr/local/sbin. For proper operations, please ensure that they have the same posix group as the Samba domain administrator if there's a local Samba PDC."
+perl -i -pe 's/_SLAVELDAP_/localhost/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_MASTERLDAP_/localhost/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_SUFFIX_/dc=IDEALX,dc=org/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_USERS_/Users/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_COMPUTERS_/Computers/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_GROUPS_/Groups/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_LOGINSHELL_/\/bin\/bash/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_USERHOMEPREFIX_/\/home\//' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_BINDDN_/cn=Manager,\$suffix/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_BINDPW_/secret/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_PDCNAME_/PDC-SRV/' %{prefix}/sbin/smbldap_conf.pm
+perl -i -pe 's/_HOMEDRIVE_/D/' %{prefix}/sbin/smbldap_conf.pm
+
+# FIXME: links should not be removed on upgrade
+#%postun
+#if [ $1 = 0 ] ; then
+# rm -f /usr/lib/perl5/site_perl/smbldap_tools.pm
+# rm -f /usr/lib/perl5/site_perl/smbldap_conf.pm
+#fi
+
+%files
+%defattr(-,root,root)
+%{prefix}/sbin/*.pl
+%{prefix}/sbin/smbldap_tools.pm
+%config %{prefix}/sbin/smbldap_conf.pm
+%{prefix}/sbin/mkntpwd
+%doc %{prefix}/share/doc/%{name}/TODO
+%doc %{prefix}/share/doc/%{name}/README
+%doc %{prefix}/share/doc/%{name}/CONTRIBUTORS
+%doc %{prefix}/share/doc/%{name}/FILES
+%doc %{prefix}/share/doc/%{name}/COPYING
+
+
+%changelog
+* Sat Jun 1 2002 Olivier Lemaire <olem@IDEALX.com> 0.7-1
+- some bugfixes about smbldap-populate
+- bugfixed the smbpasswd call in smbldap-useradd
+- cleaned up the smbldap_conf
+- more documentation
+
+* Tue Apr 30 2002 Brad Langhorst <brad@langhorst.com> 0.6-2
+- changed requires samba-common to samba
+- replaced /usr/local with %{prefix} to allow relocation
+
+* Tue Feb 5 2002 David Le Corfec <dlc@IDEALX.com> 0.6-1
+- v0.6
+
+* Mon Feb 4 2002 David Le Corfec <dlc@IDEALX.com> 0.5-1
+- v0.5
+
+* Mon Jan 14 2002 David Le Corfec <dlc@IDEALX.com> 0.3-4
+- internal changes
+- should upgrade smoothly from now on
+
+* Mon Jan 14 2002 David Le Corfec <dlc@IDEALX.com> 0.2-1
+- added migration scripts
+
+* Fri Dec 28 2001 David Le Corfec <dlc@IDEALX.com> 0.1-5
+- numeric group for chmod
+
+* Thu Dec 27 2001 David Le Corfec <dlc@IDEALX.com> 0.1-4
+- misc bugfixes
+
+* Mon Dec 18 2001 David Le Corfec <dlc@IDEALX.com> 0.1-3
+- changed files attrs for domain admins to add users
+- added smbldap-populate.pl
+
+* Fri Dec 14 2001 David Le Corfec <dlc@IDEALX.com>
+- added mkntpwd
+
+* Wed Dec 12 2001 Olivier Lemaire <olivier.lemaire@IDEALX.com>
+- Spec file was generated, and tested atomically.
diff --git a/examples/LDAP/smbldap-tools/smbldap-useradd.pl b/examples/LDAP/smbldap-tools/smbldap-useradd.pl
new file mode 100755
index 00000000000..9d2ca90bd29
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-useradd.pl
@@ -0,0 +1,462 @@
+#!/usr/bin/perl
+
+# $Id: smbldap-useradd.pl,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+#
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2002 IDEALX
+#
+# 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.
+
+# Purpose of smbldap-useradd : user (posix,shadow,samba) add
+
+use strict;
+use smbldap_tools;
+use smbldap_conf;
+
+
+#####################
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('axnmwPG:u:g:d:s:c:k:A:B:C:D:E:F:H:?', \%Options);
+
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-awmugdsckGPABCDEFH?] username\n";
+ print " -a is a Windows User (otherwise, Posix stuff only)\n";
+ print " -w is a Windows Workstation (otherwise, Posix stuff only)\n";
+ print " -x creates rid and primaryGroupID in hex instead of decimal\n";
+ print " -u uid\n";
+ print " -g gid\n";
+ print " -G supplementary comma-separated groups\n";
+ print " -n do not create a group\n";
+ print " -d home\n";
+ print " -s shell\n";
+ print " -c gecos\n";
+ print " -m creates home directory and copies /etc/skel\n";
+ print " -k skeleton dir (with -m)\n";
+ print " -P ends by invoking smbldap-passwd.pl\n";
+ print " -A can change password ? 0 if no, 1 if yes\n";
+ print " -B must change password ? 0 if no, 1 if yes\n";
+ print " -C smbHome (SMB home share, like '\\\\PDC-SRV\\homes')\n";
+ print " -D homeDrive (letter associated with home share, like 'H:')\n";
+ print " -E scriptPath (DOS script to execute on login)\n";
+ print " -F profilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')\n";
+ print " -H acctFlags (samba account control bits like '[NDHTUMWSLKI]')\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+# cause problems when dealing with getpwuid because of the
+# negative ttl and ldap modification
+my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd stop > /dev/null 2>&1";
+}
+
+# Read options
+my $userUidNumber = $Options{'u'};
+if (!defined($userUidNumber)) {
+ # find first unused uid starting from $UID_START
+ while (defined(getpwuid($UID_START))) {
+ $UID_START++;
+ }
+ $userUidNumber = $UID_START;
+} elsif (getpwuid($userUidNumber)) { die "Uid already exists.\n"; }
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd start > /dev/null 2>&1";
+}
+
+
+# as rid we use 2 * uid + 1000
+my $userRid = 2 * $userUidNumber + 1000;
+if (defined($Options{'x'})) {
+ $userRid= sprint("%x", $userRid);
+}
+
+my $createGroup = 0;
+my $userGidNumber = $Options{'g'};
+# gid not specified ?
+if (!defined($userGidNumber)) {
+ # windows machine => $_defaultComputerGid
+ if (defined($Options{'w'})) {
+ $userGidNumber = $_defaultComputerGid;
+# } elsif (!defined($Options{'n'})) {
+ # create new group (redhat style)
+ # find first unused gid starting from $GID_START
+# while (defined(getgrgid($GID_START))) {
+# $GID_START++;
+# }
+# $userGidNumber = $GID_START;
+
+# $createGroup = 1;
+
+ } else {
+ # user will have gid = $_defaultUserGid
+ $userGidNumber = $_defaultUserGid;
+ }
+} else {
+ my $gid;
+ if (($gid = parse_group($userGidNumber)) < 0) {
+ print "$0: unknown group $userGidNumber\n";
+ exit (6);
+ }
+ $userGidNumber = $gid;
+}
+
+# as grouprid we use 2 * gid + 1001
+my $userGroupRid = 2 * $userGidNumber + 1001;
+if (defined($Options{'x'})) {
+ $userGroupRid = sprint("%x", $userGroupRid);
+}
+# Read only first @ARGV
+my $userName = $ARGV[0];
+
+# user must not exist in LDAP (should it be nss-wide ?)
+my ($rc, $dn) = get_user_dn2($userName);
+if ($rc and defined($dn)) {
+ print "$0: user $userName exists\n";
+ exit (9);
+} elsif (!$rc) {
+ print "$0: error in get_user_dn2\n";
+ exit(10);
+}
+
+my $userHomeDirectory;
+my $tmp;
+if (!defined($userHomeDirectory = $Options{'d'}))
+{
+ $userHomeDirectory = $_userHomePrefix.$userName;
+}
+$_userLoginShell = $tmp if (defined($tmp = $Options{'s'}));
+$_userGecos = $tmp if (defined($tmp = $Options{'c'}));
+$_skeletonDir = $tmp if (defined($tmp = $Options{'k'}));
+
+########################
+
+# MACHINE ACCOUNT
+if (defined($tmp = $Options{'w'})) {
+
+ # add a trailing dollar if missing
+ if ($userName =~ /[^\$]$/s) {
+ $userName .= "\$";
+ }
+
+ #print "About to create machine $userName:\n";
+
+ if (!add_posix_machine ($userName, $userUidNumber, $userGidNumber)) {
+ die "$0: error while adding posix account\n";
+ }
+
+ if (!$with_smbpasswd) {
+ if (!add_samba_machine_mkntpwd($userName, $userUidNumber)) {
+ die "$0: error while adding samba account\n";
+ }
+ } else {
+ if (!add_samba_machine($userName)) {
+ die "$0: error while adding samba account\n";
+ }
+
+ my $tmpldif =
+"dn: uid=$userName,$computersdn
+changetype: modify
+acctFlags: [W ]
+
+";
+ die "$0: error while modifying accountflags of $userName\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+ }
+
+ exit 0;
+}
+
+#######################
+
+# USER ACCOUNT
+
+# add posix account first
+
+my $tmpldif =
+"dn: uid=$userName,$usersdn
+objectclass: top
+objectclass: account
+objectclass: posixAccount
+cn: $userName
+uid: $userName
+uidNumber: $userUidNumber
+gidNumber: $userGidNumber
+homeDirectory: $userHomeDirectory
+loginShell: $_userLoginShell
+gecos: $_userGecos
+description: $_userGecos
+userPassword: {crypt}x
+
+";
+
+die "$0: error while adding posix user $userName\n"
+ unless (do_ldapadd($tmpldif) == 0);
+
+undef $tmpldif;
+
+#if ($createGroup) {
+# group_add($userName, $userGidNumber);
+#}
+
+group_add_user($userGidNumber, $userName);
+
+my $grouplist;
+# adds to supplementary groups
+if (defined($grouplist = $Options{'G'})) {
+ add_grouplist_user($grouplist, $userName);
+}
+
+# If user was created successfully then we should create his/her home dir
+if (defined($tmp = $Options{'m'})) {
+ if ( !(-e $userHomeDirectory) ) {
+ system "mkdir $userHomeDirectory 2>/dev/null";
+ system "cp -a $_skeletonDir/.[a-z,A-Z]* $_skeletonDir/* $userHomeDirectory 2>/dev/null";
+ system "chown -R $userUidNumber:$userGidNumber $userHomeDirectory 2>/dev/null";
+ system "chmod 700 $userHomeDirectory 2>/dev/null";
+ }
+}
+
+
+# Add Samba user infos
+if (defined($Options{'a'})) {
+ if (!$with_smbpasswd) {
+
+ my $winmagic = 2147483647;
+ my $valpwdcanchange = 0;
+ my $valpwdmustchange = $winmagic;
+ my $valacctflags = "[UX]";
+
+ if (defined($tmp = $Options{'A'})) {
+ if ($tmp != 0) {
+ $valpwdcanchange = "0";
+ } else {
+ $valpwdcanchange = "$winmagic";
+ }
+ }
+
+ if (defined($tmp = $Options{'B'})) {
+ if ($tmp != 0) {
+ $valpwdmustchange = "0";
+ } else {
+ $valpwdmustchange = "$winmagic";
+ }
+ }
+
+ if (defined($tmp = $Options{'H'})) {
+ $valacctflags = "$tmp";
+ }
+
+ my $tmpldif =
+"dn: uid=$userName,$usersdn
+changetype: modify
+objectclass: top
+objectclass: account
+objectclass: posixAccount
+objectClass: sambaAccount
+pwdLastSet: 0
+logonTime: 0
+logoffTime: 2147483647
+kickoffTime: 2147483647
+pwdCanChange: $valpwdcanchange
+pwdMustChange: $valpwdmustchange
+displayName: $_userGecos
+acctFlags: $valacctflags
+rid: $userRid
+
+";
+
+ die "$0: error while adding samba account to posix user $userName\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+
+ undef $tmpldif;
+ } else {
+ my $FILE="|smbpasswd -s -a $userName >/dev/null" ;
+ open (FILE, $FILE) || die "$!\n";
+ print FILE <<EOF;
+x
+x
+EOF
+ ;
+ close FILE;
+ if ($?) {
+ print "$0: error adding samba account\n";
+ exit (10);
+ }
+ } # with_smbpasswd
+
+ my $valscriptpath = "$userName.cmd";
+ my $valprofilepath = "$_userProfile$userName";
+ my $valsmbhome = "$_userSmbHome";
+ my $valhomedrive = "$_userHomeDrive";
+
+if (defined($tmp = $Options{'C'})) {
+ $valsmbhome = "$tmp";
+}
+
+if (defined($tmp = $Options{'D'})) {
+ $tmp = $tmp.":" unless ($tmp =~ /:/);
+ $valhomedrive = "$tmp";
+}
+
+if (defined($tmp = $Options{'E'})) {
+ $valscriptpath = "$tmp";
+}
+
+if (defined($tmp = $Options{'F'})) {
+ $valprofilepath = "$tmp";
+}
+
+ my $tmpldif =
+"dn: uid=$userName,$usersdn
+changetype: modify
+rid: $userRid
+primaryGroupID: $userGroupRid
+homeDrive: $valhomedrive
+smbHome: $valsmbhome
+profilePath: $valprofilepath
+scriptPath: $valscriptpath
+lmPassword: XXX
+ntPassword: XXX
+
+";
+
+ die "$0: error while modifying samba account of user $userName\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+}
+
+if (defined($Options{'P'})) {
+ exec "/usr/local/sbin/smbldap-passwd.pl $userName"
+}
+
+exit 0;
+
+########################################
+
+=head1 NAME
+
+ smbldap-useradd.pl - Create a new user or update default new
+ user information
+
+=head1 SYNOPSIS
+
+ smbldap-useradd.pl [-c comment] [-d home_dir]
+ [-g initial_group] [-G group[,...]]
+ [-m [-k skeleton_dir]]
+ [-s shell] [-u uid [ -o]] [-P]
+ [-A canchange] [-B mustchange] [-C smbhome]
+ [-D homedrive] [-E scriptpath] [-F profilepath]
+ [-H acctflags] login
+
+=head1 DESCRIPTION
+
+ Creating New Users
+ The smbldap-useradd.pl command creates a new user account using
+ the values specified on the command line and the default
+ values from the system.
+ The new user account will be entered into the system
+ files as needed, the home directory will be created, and
+ initial files copied, depending on the command line options.
+
+ You have to use smbldap-passwd to set the user password.
+ For Samba users, rid is 2*uidNumber+1000, and primaryGroupID
+ is 2*gidNumber+1001. Thus you may want to use
+ smbldap-useradd.pl -a -g "Domain Admins" -u 500 Administrator
+ to create a domain administrator (admin rid is 0x1F4 = 500 and
+ grouprid is 0x200 = 512)
+
+ Without any option, the account created will be an Unix (Posix)
+ account. The following options may be used to add information:
+
+ -a The user will have a Samba account (and Unix).
+
+ -w Creates an account for a Samba machine (Workstation), so that
+ it can join a domain.
+
+ -x Creates rid and primaryGroupID in hex (for Samba 2.2.2 bug). Else
+ decimal (2.2.2 patched from cvs or 2.2.x, x > 2)
+
+ -c comment
+ The new user's comment field (gecos).
+
+ -d home_dir
+ The new user will be created using home_dir as the value for the
+ user's login directory. The default is to append the login name
+ to default_home and use that as the login directory name.
+
+ -g initial_group
+ The group name or number of the user's initial login group. The
+ group name must exist. A group number must refer to an already
+ existing group. The default group number is 1.
+
+ -G group,[...]
+ A list of supplementary groups which the user is also a member
+ of. Each group is separated from the next by a comma, with no
+ intervening whitespace. The groups are subject to the same
+ restrictions as the group given with the -g option. The default
+ is for the user to belong only to the initial group.
+
+ -m The user's home directory will be created if it does not exist.
+ The files contained in skeleton_dir will be copied to the home
+ directory if the -k option is used, otherwise the files con­
+ tained in /etc/skel will be used instead. Any directories con­
+ tained in skeleton_dir or /etc/skel will be created in the
+ user's home directory as well. The -k option is only valid in
+ conjunction with the -m option. The default is to not create
+ the directory and to not copy any files.
+
+ -s shell
+ The name of the user's login shell. The default is to leave
+ this field blank, which causes the system to select the default
+ login shell.
+
+ -u uid The numerical value of the user's ID. This value must be
+ unique, unless the -o option is used. The value must be non-
+ negative. The default is to use the smallest ID value greater
+ than 1000 and greater than every other user.
+
+ -P ends by invoking smbldap-passwd.pl
+
+ -A can change password ? 0 if no, 1 if yes
+
+ -B must change password ? 0 if no, 1 if yes
+
+ -C smbHome (SMB home share, like '\\\\PDC-SRV\\homes')
+
+ -D homeDrive (letter associated with home share, like 'H:')
+
+ -E scriptPath, relative to the [netlogon] share (DOS script to execute on login, like 'foo.bat')
+
+ -F profilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')
+
+ -H acctFlags, spaces and trailing bracket are ignored (samba account control bits like '[NDHTUMWSLKI]')
+
+=head1 SEE ALSO
+
+ useradd(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-userdel.pl b/examples/LDAP/smbldap-tools/smbldap-userdel.pl
new file mode 100755
index 00000000000..e2ad403b6d5
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-userdel.pl
@@ -0,0 +1,124 @@
+#!/usr/bin/perl
+
+# $Id: smbldap-userdel.pl,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+#
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# 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.
+
+# Purpose of smbldap-userdel : user (posix,shadow,samba) deletion
+
+use strict;
+use smbldap_tools;
+
+
+#####################
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('r?', \%Options);
+
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-r?] username\n";
+ print " -r remove home directory\n";
+ exit (1);
+}
+
+# Read only first @ARGV
+my $user = $ARGV[0];
+
+my $dn;
+# user must not exist in LDAP
+if (!defined($dn=get_user_dn($user))) {
+ print "$0: user $user does not exist\n";
+ exit (6);
+}
+
+if ($< != 0) {
+ print "You must be root to delete an user\n";
+ exit (1);
+}
+
+my $homedir;
+if (defined($Options{'r'})) {
+ $homedir=get_homedir($user);
+}
+
+# remove user from groups
+my $groups = find_groups_of $user;
+my @grplines = split(/\n/, $groups);
+
+my $grp;
+foreach $grp (@grplines) {
+ my $gname = "";
+ if ( $grp =~ /dn: cn=([^,]+),/) {
+ $gname = $1;
+ #print "xx $gname\n";
+ }
+ if ($gname ne "") {
+ group_remove_member($gname, $user);
+ }
+}
+
+# XXX
+delete_user($user);
+
+# delete dir -- be sure that homeDir is not a strange value
+if (defined($Options{'r'})) {
+ if ($homedir !~ /^\/dev/ and $homedir !~ /^\/$/) {
+ system "rm -rf $homedir";
+ }
+}
+
+my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd restart > /dev/null 2>&1";
+}
+
+exit (0);
+
+############################################################
+
+=head1 NAME
+
+ smbldap-userdel.pl - Delete a user account and related files
+
+=head1 SYNOPSIS
+
+ smbldap-userdel.pl [-r] login
+
+=head1 DESCRIPTION
+
+ The smbldap-userdel.pl command modifies the system
+ account files, deleting all entries that refer to login.
+ The named user must exist.
+
+ -r Files in the user's home directory will be removed along with
+ the home directory itself. Files located in other file
+ systems will have to be searched for and deleted manually.
+
+=head1 SEE ALSO
+
+ userdel(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-usermod.pl b/examples/LDAP/smbldap-tools/smbldap-usermod.pl
new file mode 100755
index 00000000000..dd5fcab74fd
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-usermod.pl
@@ -0,0 +1,405 @@
+#!/usr/bin/perl
+
+# $Id: smbldap-usermod.pl,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+#
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# 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.
+
+# Purpose of smbldap-usermod : user (posix,shadow,samba) modification
+
+use strict;
+use smbldap_tools;
+use smbldap_conf;
+
+
+#####################
+
+use Getopt::Std;
+my %Options;
+my $nscd_status;
+
+my $ok = getopts('A:B:C:D:E:F:H:IJxme:f:u:g:G:d:l:s:c:ok:?', \%Options);
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-awmugdsckxABCDEFGHI?] username\n";
+ print " -c gecos\n";
+ print " -d home directory\n";
+ #print " -m move home directory\n";
+ #print " -e expire date (YYYY-MM-DD)\n";
+ #print " -f inactive days\n";
+ print " -u uid\n";
+ print " -o uid can be non unique\n";
+ print " -g gid\n";
+ print " -G supplementary groups (comma separated)\n";
+ print " -l login name\n";
+ print " -s shell\n";
+ print " -x creates rid and primaryGroupID in hex instead of decimal (for Samba 2.2.2 unpatched only)\n";
+ print " -A can change password ? 0 if no, 1 if yes\n";
+ print " -B must change password ? 0 if no, 1 if yes\n";
+ print " -C smbHome (SMB home share, like '\\\\PDC-SRV\\homes')\n";
+ print " -D homeDrive (letter associated with home share, like 'H:')\n";
+ print " -E scriptPath (DOS script to execute on login)\n";
+ print " -F profilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')\n";
+ print " -H acctFlags (samba account control bits like '[NDHTUMWSLKI]')\n";
+ print " -I disable an user. Can't be used with -H or -J\n";
+ print " -J enable an user. Can't be used with -H or -I\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+if ($< != 0) {
+ print "You must be root to modify an user\n";
+ exit (1);
+}
+
+# Read only first @ARGV
+my $user = $ARGV[0];
+
+# Read user datas
+my $lines = read_user($user);
+if (!defined($lines)) {
+ print "$0: user $user doesn't exist\n";
+ exit (1);
+}
+
+#print "$lines\n";
+my $dn_line;
+if ( $lines =~ /(^dn: .*)/ ) {
+ $dn_line = $1;
+}
+
+chomp($dn_line);
+
+my $samba = 0;
+if ($lines =~ m/objectClass: sambaAccount/) {
+ $samba = 1;
+}
+
+############
+
+my $tmp;
+my $mods;
+
+# Process options
+my $changed_uid;
+my $_userUidNumber;
+my $_userRid;
+if (defined($tmp = $Options{'u'})) {
+ if (defined($Options{'o'})) {
+ $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+ if ($nscd_status == 0) {
+ system "/etc/init.d/nscd stop > /dev/null 2>&1";
+ }
+
+ if (getpwuid($tmp)) {
+ if ($nscd_status == 0) {
+ system "/etc/init.d/nscd start > /dev/null 2>&1";
+ }
+
+ print "$0: uid number $tmp exists\n";
+ exit (6);
+ }
+ if ($nscd_status == 0) {
+ system "/etc/init.d/nscd start > /dev/null 2>&1";
+ }
+
+ }
+ $_userUidNumber = $tmp;
+ # as rid we use 2 * uid + 1000
+ my $_userRid = 2 * $_userUidNumber + 1000;
+ if (defined($Options{'x'})) {
+ $_userRid= sprint("%x", $_userRid);
+ }
+ $mods .= "uidNumber: $_userUidNumber\n";
+ if ($samba) {
+ $mods .= "rid: $_userRid\n";
+ }
+ $changed_uid = 1;
+}
+
+my $changed_gid;
+my $_userGidNumber;
+my $_userGroupRid;
+if (defined($tmp = $Options{'g'})) {
+ $_userGidNumber = parse_group($tmp);
+ if ($_userGidNumber < 0) {
+ print "$0: group $tmp doesn't exist\n";
+ exit (6);
+ }
+# as grouprid we use 2 * gid + 1001
+ my $_userGroupRid = 2 * $_userGidNumber + 1001;
+ if (defined($Options{'x'})) {
+ $_userGroupRid = sprint("%x", $_userGroupRid);
+ }
+ $mods .= "gidNumber: $_userGidNumber\n";
+ if ($samba) {
+ $mods .= "primaryGroupID: $_userGroupRid\n";
+ }
+ $changed_gid = 1;
+}
+
+my $changed_shell;
+my $_userLoginShell;
+if (defined($tmp = $Options{'s'})) {
+ $_userLoginShell = $tmp;
+ $mods .= "loginShell: $_userLoginShell\n";
+ $changed_shell = 1;
+}
+
+my $changed_gecos;
+my $_userGecos;
+if (defined($tmp = $Options{'c'})) {
+ $_userGecos = $tmp;
+ $mods .= "gecos: $_userGecos\n";
+ $changed_gecos = 1;
+}
+
+my $changed_homedir;
+my $newhomedir;
+if (defined($tmp = $Options{'d'})) {
+ $newhomedir = $tmp;
+ $mods .= "homeDirectory: $newhomedir\n";
+ $changed_homedir = 1;
+}
+
+
+if (defined($tmp = $Options{'G'})) {
+
+ # remove user from old groups
+ my $groups = find_groups_of $user;
+ my @grplines = split(/\n/, $groups);
+
+ my $grp;
+ foreach $grp (@grplines) {
+ my $gname = "";
+ if ( $grp =~ /dn: cn=([^,]+),/) {
+ $gname = $1;
+ #print "xx $gname\n";
+ }
+ if ($gname ne "") {
+ group_remove_member($gname, $user);
+ }
+ }
+
+ # add user to new groups
+ add_grouplist_user($tmp, $user);
+}
+
+#
+# A : pwdCanChange
+# B : pwdMustChange
+# C : smbHome
+# D : homeDrive
+# E : scriptPath
+# F : profilePath
+# H : acctFlags
+
+my $attr;
+my $winmagic = 2147483647;
+
+if (defined($tmp = $Options{'A'})) {
+ $attr = "pwdCanChange";
+ if ($tmp != 0) {
+ $mods .= "$attr: 0\n";
+ } else {
+ $mods .= "$attr: $winmagic\n";
+ }
+}
+
+if (defined($tmp = $Options{'B'})) {
+ $attr = "pwdMustChange";
+ if ($tmp != 0) {
+ $mods .= "$attr: 0\n";
+ } else {
+ $mods .= "$attr: $winmagic\n";
+ }
+}
+
+if (defined($tmp = $Options{'C'})) {
+ $attr = "smbHome";
+ #$tmp =~ s/\\/\\\\/g;
+ $mods .= "$attr: $tmp\n";
+}
+
+if (defined($tmp = $Options{'D'})) {
+ $attr = "homeDrive";
+ $tmp = $tmp.":" unless ($tmp =~ /:/);
+ $mods .= "$attr: $tmp\n";
+}
+
+if (defined($tmp = $Options{'E'})) {
+ $attr = "scriptPath";
+ #$tmp =~ s/\\/\\\\/g;
+ $mods .= "$attr: $tmp\n";
+}
+
+if (defined($tmp = $Options{'F'})) {
+ $attr = "profilePath";
+ #$tmp =~ s/\\/\\\\/g;
+ $mods .= "$attr: $tmp\n";
+}
+
+if (defined($tmp = $Options{'H'})) {
+ $attr = "acctFlags";
+ #$tmp =~ s/\\/\\\\/g;
+ $mods .= "$attr: $tmp\n";
+} elsif (defined($tmp = $Options{'I'})) {
+ my $flags;
+
+ if ( $lines =~ /^acctFlags: (.*)/m ) {
+ $flags = $1;
+ }
+
+ chomp($flags);
+
+ if ( !($flags =~ /D/) ) {
+ my $letters;
+ if ($flags =~ /(\w+)/) {
+ $letters = $1;
+ }
+ $mods .= "acctFlags: \[D$letters\]\n";
+ }
+} elsif (defined($tmp = $Options{'J'})) {
+ my $flags;
+
+ if ( $lines =~ /^acctFlags: (.*)/m ) {
+ $flags = $1;
+ }
+
+ chomp($flags);
+
+ if ( $flags =~ /D/ ) {
+ my $letters;
+ if ($flags =~ /(\w+)/) {
+ $letters = $1;
+ }
+ $letters =~ s/D//;
+ $mods .= "acctFlags: \[$letters\]\n";
+ }
+}
+
+if ($mods ne '') {
+ #print "----\n$dn_line\n$mods\n----\n";
+
+ my $tmpldif =
+"$dn_line
+changetype: modify
+$mods
+";
+
+ die "$0: error while modifying user $user\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+
+ undef $tmpldif;
+}
+
+$nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+if ($nscd_status == 0) {
+ system "/etc/init.d/nscd restart > /dev/null 2>&1";
+}
+
+
+############################################################
+
+=head1 NAME
+
+ smbldap-usermod.pl - Modify a user account
+
+=head1 SYNOPSIS
+
+ smbldap-usermod.pl [-c comment] [-d home_dir]
+ [-g initial_group] [-G group[,...]]
+ [-l login_name] [-p passwd]
+ [-s shell] [-u uid [ -o]] [-x]
+ [-A canchange] [-B mustchange] [-C smbhome]
+ [-D homedrive] [-E scriptpath] [-F profilepath]
+ [-H acctflags] login
+
+=head1 DESCRIPTION
+
+ The smbldap-usermod.pl command modifies the system account files
+ to reflect the changes that are specified on the command line.
+ The options which apply to the usermod command are
+
+ -c comment
+ The new value of the user's comment field (gecos).
+
+ -d home_dir
+ The user's new login directory.
+
+ -g initial_group
+ The group name or number of the user's new initial login group.
+ The group name must exist. A group number must refer to an
+ already existing group. The default group number is 1.
+
+ -G group,[...]
+ A list of supplementary groups which the user is also a member
+ of. Each group is separated from the next by a comma, with no
+ intervening whitespace. The groups are subject to the same
+ restrictions as the group given with the -g option. If the user
+ is currently a member of a group which is not listed, the user
+ will be removed from the group
+
+ -l login_name
+ The name of the user will be changed from login to login_name.
+ Nothing else is changed. In particular, the user's home direc­
+ tory name should probably be changed to reflect the new login
+ name.
+
+ -s shell
+ The name of the user's new login shell. Setting this field to
+ blank causes the system to select the default login shell.
+
+ -u uid The numerical value of the user's ID. This value must be
+ unique, unless the -o option is used. The value must be non-
+ negative. Any files which the user owns and which are
+ located in the directory tree rooted at the user's home direc­
+ tory will have the file user ID changed automatically. Files
+ outside of the user's home directory must be altered manually.
+
+ -x Creates rid and primaryGroupID in hex instead of decimal (for
+ Samba 2.2.2 unpatched only - higher versions always use decimal)
+
+ -A can change password ? 0 if no, 1 if yes
+
+ -B must change password ? 0 if no, 1 if yes
+
+ -C smbHome (SMB home share, like '\\\\PDC-SRV\\homes')
+
+ -D homeDrive (letter associated with home share, like 'H:')
+
+ -E scriptPath, relative to the [netlogon] share (DOS script to execute on login, like 'foo.bat')
+
+ -F profilePath (profile directory, like '\\\\PDC-SRV\\profiles\\foo')
+
+ -H acctFlags, spaces and trailing bracket are ignored (samba account control bits like '[NDHTUMWSLKI]')
+
+ -I disable user. Can't be used with -H or -J
+
+ -J enable user. Can't be used with -H or -I
+
+=head1 SEE ALSO
+
+ usermod(1)
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap-usershow.pl b/examples/LDAP/smbldap-tools/smbldap-usershow.pl
new file mode 100755
index 00000000000..41391a91969
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap-usershow.pl
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+
+# $Id: smbldap-usershow.pl,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+#
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# 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.
+
+# Purpose of smbldap-userdisplay : user (posix,shadow,samba) display
+
+use strict;
+use smbldap_tools;
+
+use Getopt::Std;
+my %Options;
+
+my $ok = getopts('?', \%Options);
+
+if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
+ print "Usage: $0 [-?] username\n";
+ print " -? show this help message\n";
+ exit (1);
+}
+
+# Read only first @ARGV
+my $user = $ARGV[0];
+
+my $lines = read_user($user);
+if (!defined($lines)) {
+ print "$0: user $user doesn't exist\n";
+ exit (1);
+}
+
+print "$lines\n";
+
+exit(0);
+
+############################################################
+
+=head1 NAME
+
+ smbldap-usershow.pl - Show a user account informations
+
+=head1 SYNOPSIS
+
+ smbldap-usershow.pl login
+
+=head1 DESCRIPTION
+
+ The smbldap-usershow.pl command displays the informations
+ associated with the login. The named user must exist.
+
+=cut
+
+#'
diff --git a/examples/LDAP/smbldap-tools/smbldap_conf.pm b/examples/LDAP/smbldap-tools/smbldap_conf.pm
new file mode 100644
index 00000000000..158f2c1460e
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap_conf.pm
@@ -0,0 +1,251 @@
+#!/usr/bin/perl
+use strict;
+package smbldap_conf;
+
+# $Id: smbldap_conf.pm,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+#
+# smbldap-tools.conf : Q & D configuration file for smbldap-tools
+
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# 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.
+
+# Purpose :
+# . be the configuration file for all smbldap-tools scripts
+
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS
+$UID_START $GID_START $smbpasswd $slaveLDAP $masterLDAP
+$with_smbpasswd $mk_ntpasswd
+$ldap_path $ldap_opts $ldapsearch $ldapsearchnobind
+$ldapmodify $ldappasswd $ldapadd $ldapdelete $ldapmodrdn
+$suffix $usersdn $computersdn
+$groupsdn $scope $binddn $bindpasswd
+$slaveDN $slavePw $masterDN $masterPw
+$_userLoginShell $_userHomePrefix $_userGecos
+$_defaultUserGid $_defaultComputerGid
+$_skeletonDir $_userSmbHome
+$_userProfile $_userHomeDrive
+$_userScript $usersou $computersou $groupsou
+);
+
+use Exporter;
+$VERSION = 1.00;
+@ISA = qw(Exporter);
+
+@EXPORT = qw(
+$UID_START $GID_START $smbpasswd $slaveLDAP $masterLDAP
+$with_smbpasswd $mk_ntpasswd
+$ldap_path $ldap_opts $ldapsearch $ldapsearchnobind $ldapmodify $ldappasswd
+$ldapadd $ldapdelete $ldapmodrdn $suffix $usersdn
+$computersdn $groupsdn $scope $binddn $bindpasswd
+$slaveDN $slavePw $masterDN $masterPw
+$_userLoginShell $_userHomePrefix $_userGecos
+$_defaultUserGid $_defaultComputerGid $_skeletonDir
+$_userSmbHome $_userProfile $_userHomeDrive $_userScript
+$usersou $computersou $groupsou
+);
+
+
+##############################################################################
+#
+# General Configuration
+#
+##############################################################################
+
+#
+# UID and GID starting at...
+#
+
+$UID_START = 1000;
+$GID_START = 1000;
+
+##############################################################################
+#
+# LDAP Configuration
+#
+##############################################################################
+
+# Notes: to use to dual ldap servers backend for Samba, you must patch
+# Samba with the dual-head patch from IDEALX. If not using this patch
+# just use the same server for slaveLDAP and masterLDAP.
+#
+# Slave LDAP : needed for read operations
+#
+# Ex: $slaveLDAP = "127.0.0.1";
+$slaveLDAP = "_SLAVELDAP_";
+
+#
+# Master LDAP : needed for write operations
+#
+# Ex: $masterLDAP = "127.0.0.1";
+$masterLDAP = "_MASTERLDAP_";
+
+#
+# LDAP Suffix
+#
+# Ex: $suffix = "dc=IDEALX,dc=ORG";
+$suffix = "_SUFFIX_";
+
+#
+# Where are stored Users
+#
+# Ex: $usersdn = "ou=Users,$suffix"; for ou=Users,dc=IDEALX,dc=ORG
+$usersou = q(_USERS_);
+
+$usersdn = "ou=$usersou,$suffix";
+
+#
+# Where are stored Computers
+#
+# Ex: $computersdn = "ou=Computers,$suffix"; for ou=Computers,dc=IDEALX,dc=ORG
+$computersou = q(_COMPUTERS_);
+
+$computersdn = "ou=$computersou,$suffix";
+
+#
+# Where are stored Groups
+#
+# Ex $groupsdn = "ou=Groups,$suffix"; for ou=Groups,dc=IDEALX,dc=ORG
+$groupsou = q(_GROUPS_);
+
+$groupsdn = "ou=$groupsou,$suffix";
+
+#
+# Default scope Used
+#
+$scope = "sub";
+
+#
+# Credential Configuration
+#
+# Bind DN used
+# Ex: $binddn = "cn=Manager,$suffix"; for cn=Manager,dc=IDEALX,dc=org
+$binddn = "_BINDDN_";
+#
+# Bind DN passwd used
+# Ex: $bindpasswd = 'secret'; for 'secret'
+$bindpasswd = "_BINDPW_";
+
+#
+# Notes: if using dual ldap patch, you can specify to different configuration
+# By default, we will use the same DN (so it will work for standard Samba
+# release)
+#
+$slaveDN = $binddn;
+$slavePw = $bindpasswd;
+$masterDN = $binddn;
+$masterPw = $bindpasswd;
+
+##############################################################################
+#
+# Unix Accounts Configuration
+#
+##############################################################################
+
+# Login defs
+#
+# Default Login Shell
+#
+# Ex: $_userLoginShell = q(/bin/bash);
+$_userLoginShell = q(_LOGINSHELL_);
+
+#
+# Home directory prefix (without username)
+#
+#Ex: $_userHomePrefix = q(/home/);
+$_userHomePrefix = q(_USERHOMEPREFIX_);
+
+#
+# Gecos
+#
+$_userGecos = q(System User);
+
+#
+# Default User (POSIX and Samba) GID
+#
+$_defaultUserGid = 100;
+
+#
+# Default Computer (Samba) GID
+#
+$_defaultComputerGid = 553;
+
+#
+# Skel dir
+#
+$_skeletonDir = q(/etc/skel);
+
+##############################################################################
+#
+# SAMBA Configuration
+#
+##############################################################################
+
+#
+# The UNC path to home drives location without the username last extension
+# (will be dynamically prepended)
+# Ex: q(\\\\My-PDC-netbios-name\\homes) for \\My-PDC-netbios-name\homes
+$_userSmbHome = q(\\\\_PDCNAME_\\homes);
+
+#
+# The UNC path to profiles locations without the username last extension
+# (will be dynamically prepended)
+# Ex: q(\\\\My-PDC-netbios-name\\profiles) for \\My-PDC-netbios-name\profiles
+$_userProfile = q(\\\\_PDCNAME_\\profiles\\);
+
+#
+# The default Home Drive Letter mapping
+# (will be automatically mapped at logon time if home directory exist)
+# Ex: q(U:) for U:
+$_userHomeDrive = q(_HOMEDRIVE_:);
+
+#
+# The default user netlogon script name
+# if not used, will be automatically username.cmd
+#
+#$_userScript = q(startup.cmd); # make sure script file is edited under dos
+
+
+##############################################################################
+#
+# SMBLDAP-TOOLS Configuration (default are ok for a RedHat)
+#
+##############################################################################
+
+# Allows not to use smbpasswd (if $with_smbpasswd == 0 in smbldap_conf.pm) but
+# prefer mkntpwd... most of the time, it's a wise choice :-)
+$with_smbpasswd = 0;
+$smbpasswd = "/usr/bin/smbpasswd";
+$mk_ntpasswd = "/usr/local/sbin/mkntpwd";
+
+$ldap_path = "/usr/bin";
+$ldap_opts = "-x";
+$ldapsearch = "$ldap_path/ldapsearch $ldap_opts -h $slaveLDAP -D '$slaveDN' -w '$slavePw'";
+$ldapsearchnobind = "$ldap_path/ldapsearch $ldap_opts -h $slaveLDAP";
+$ldapmodify = "$ldap_path/ldapmodify $ldap_opts -h $masterLDAP -D '$masterDN' -w '$masterPw'";
+$ldappasswd = "$ldap_path/ldappasswd $ldap_opts -h $masterLDAP -D '$masterDN' -w '$masterPw'";
+$ldapadd = "$ldap_path/ldapadd $ldap_opts -h $masterLDAP -D '$masterDN' -w '$masterPw'";
+$ldapdelete = "$ldap_path/ldapdelete $ldap_opts -h $masterLDAP -D '$masterDN' -w '$masterPw'";
+$ldapmodrdn = "$ldap_path/ldapmodrdn $ldap_opts -h $masterLDAP -D '$masterDN' -w '$masterPw'";
+
+
+
+1;
+
+# - The End
diff --git a/examples/LDAP/smbldap-tools/smbldap_tools.pm b/examples/LDAP/smbldap-tools/smbldap_tools.pm
new file mode 100755
index 00000000000..1f0d4d1c43b
--- /dev/null
+++ b/examples/LDAP/smbldap-tools/smbldap_tools.pm
@@ -0,0 +1,585 @@
+#! /usr/bin/perl
+use strict;
+package smbldap_tools;
+use smbldap_conf;
+
+# $Id: smbldap_tools.pm,v 1.1.4.1 2002/06/17 18:35:08 jerry Exp $
+#
+# This code was developped by IDEALX (http://IDEALX.org/) and
+# contributors (their names can be found in the CONTRIBUTORS file).
+#
+# Copyright (C) 2001-2002 IDEALX
+#
+# 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.
+
+
+# ugly funcs using global variables and spawning openldap clients
+
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
+use Exporter;
+$VERSION = 1.00;
+@ISA = qw(Exporter);
+
+@EXPORT = qw(
+get_user_dn
+get_group_dn
+is_samba_user
+is_user_valid
+get_dn_from_line
+add_posix_machine
+add_samba_machine
+add_samba_machine_mkntpwd
+group_add_user
+add_grouplist_user
+disable_user
+delete_user
+group_add
+get_homedir
+read_user
+read_group
+find_groups_of
+parse_group
+group_remove_member
+group_get_members
+do_ldapadd
+do_ldapmodify
+get_user_dn2
+);
+
+# dn_line = get_user_dn($username)
+# where dn_line is like "dn: a=b,c=d"
+sub get_user_dn
+{
+ my $user = shift;
+ my $dn=`$ldapsearch -b '$suffix' -s '$scope' '(&(objectclass=posixAccount)(uid=$user))' | grep "^dn:"`;
+ chomp $dn;
+ if ($dn eq '') {
+ return undef;
+ }
+
+ return $dn;
+}
+
+# return (success, dn)
+sub get_user_dn2
+{
+ my $user = shift;
+
+ my $sr = `$ldapsearch -b '$suffix' -s '$scope' '(&(objectclass=posixAccount)(uid=$user))'`;
+ if ($sr eq "") {
+ print "get_user_dn2: error in ldapsearch :
+$ldapsearch -b '$suffix' -s '$scope' '(&(objectclass=posixAccount)(uid=$user))'\n";
+ return (0, undef);
+ }
+
+ my @lines = split(/\n/, $sr);
+
+ my @matches = grep(/^dn:/, @lines);
+
+ my $dn = $matches[0];
+ chomp $dn;
+ if ($dn eq '') {
+ return (1, undef);
+ }
+
+ return (1, $dn);
+}
+
+# dn_line = get_group_dn($groupname)
+# where dn_line is like "dn: a=b,c=d"
+sub get_group_dn
+{
+ my $group = shift;
+ my $dn=`$ldapsearch -b '$groupsdn' -s '$scope' '(&(objectclass=posixGroup)(|(cn=$group)(gidNumber=$group)))' | grep "^dn:"`;
+ chomp $dn;
+ if ($dn eq '') {
+ return undef;
+ }
+
+ return $dn;
+}
+
+# bool = is_samba_user($username)
+sub is_samba_user
+{
+ my $user = shift;
+ my $cmd = "$ldapsearch -b '$suffix' -s '$scope' '(&(objectClass=sambaAccount)(uid=$user))' | grep '^dn:\'";
+ my $res=`$cmd`;
+ chomp $res;
+ if ($res ne '') {
+ return 1;
+ }
+ return 0;
+}
+
+# bool = is_user_valid($username)
+# try to bind with user dn and password to validate current password
+sub is_user_valid
+{
+ my ($user, $dn, $pass) = @_;
+ my $res=`$ldapsearchnobind -b '$usersdn' -s '$scope' -D '$dn' -w '$pass' '(&(objectclass=posixAccount)(uid=$user))' 2>/dev/null | grep "^dn:"`;
+ chomp $res;
+ if ($res eq '') {
+ return 0;
+ }
+ return 1;
+}
+
+# dn = get_dn_from_line ($dn_line)
+# helper to get "a=b,c=d" from "dn: a=b,c=d"
+sub get_dn_from_line
+{
+ my $dn = shift;
+ $dn =~ s/^dn: //;
+ return $dn;
+}
+
+# success = add_posix_machine($user, $uid, $gid)
+sub add_posix_machine
+{
+ my ($user, $uid, $gid) = @_;
+
+my $tmpldif =
+"dn: uid=$user,$computersdn
+objectclass: top
+objectclass: posixAccount
+cn: $user
+uid: $user
+uidNumber: $uid
+gidNumber: $gid
+homeDirectory: /dev/null
+loginShell: /bin/false
+description: Computer
+
+";
+
+ die "$0: error while adding posix account to machine $user\n"
+ unless (do_ldapadd($tmpldif) == 0);
+
+ undef $tmpldif;
+
+ return 1;
+}
+
+# success = add_samba_machine($computername)
+sub add_samba_machine
+{
+ my $user = shift;
+ system "smbpasswd -a -m $user";
+
+ return 1;
+}
+
+sub add_samba_machine_mkntpwd
+{
+ my ($user, $uid) = @_;
+ my $rid = 2 * $uid + 1000; # Samba 2.2.2 stuff
+
+ my $name = $user;
+ $name =~ s/.$//s;
+
+ if ($mk_ntpasswd eq '') {
+ print "Either set \$with_smbpasswd = 1 or specify \$mk_ntpasswd\n";
+ return 0;
+ }
+
+ my $ntpwd = `$mk_ntpasswd '$name'`;
+ chomp(my $lmpassword = substr($ntpwd, 0, index($ntpwd, ':')));
+ chomp(my $ntpassword = substr($ntpwd, index($ntpwd, ':')+1));
+
+ my $tmpldif =
+"dn: uid=$user,$computersdn
+changetype: modify
+objectclass: top
+objectclass: posixAccount
+objectClass: sambaAccount
+pwdLastSet: 0
+logonTime: 0
+logoffTime: 2147483647
+kickoffTime: 2147483647
+pwdCanChange: 0
+pwdMustChange: 2147483647
+acctFlags: [W ]
+lmpassword: $lmpassword
+ntpassword: $ntpassword
+rid: $rid
+primaryGroupID: 0
+
+";
+
+ die "$0: error while adding samba account to $user\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+
+ return 1;
+}
+
+
+
+sub group_add_user
+{
+ my ($group, $userid) = @_;
+ my $dn_line;
+
+ if (!defined($dn_line = get_group_dn($group))) {
+ return 1;
+ }
+ my $dn = get_dn_from_line($dn_line);
+ my $members = `$ldapsearch -b '$dn' -s base | grep -i "^memberUid:"`;
+ chomp($members);
+ # user already member ?
+ if ($members =~ m/^memberUid: $userid/) {
+ return 2;
+ }
+ my $mods = "";
+ if ($members ne '') {
+ $mods="$dn_line
+changetype: modify
+replace: memberUid
+$members
+memberUid: $userid
+";
+ } else {
+ $mods="$dn_line
+changetype: modify
+add: memberUid
+memberUid: $userid
+";
+ }
+
+ #print "$mods\n";
+
+ my $tmpldif =
+"$mods
+";
+
+ die "$0: error while modifying group $group\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+ return 0;
+}
+
+sub add_grouplist_user
+{
+ my ($grouplist, $user) = @_;
+ my @array = split(/,/, $grouplist);
+ foreach my $group (@array) {
+ group_add_user($group, $user);
+ }
+}
+
+# XXX FIXME : acctFlags |= D, and not acctFlags = D
+sub disable_user
+{
+ my $user = shift;
+ my $dn_line;
+
+ if (!defined($dn_line = get_user_dn($user))) {
+ print "$0: user $user doesn't exist\n";
+ exit (10);
+ }
+
+ my $tmpldif =
+"dn: $dn_line
+changetype: modify
+replace: userPassword
+userPassword: {crypt}!x
+
+";
+
+ die "$0: error while modifying user $user\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+
+ if (is_samba_user($user)) {
+
+ my $tmpldif =
+"dn: $dn_line
+changetype: modify
+replace: acctFlags
+acctFlags: [D ]
+
+";
+
+ die "$0: error while modifying user $user\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+
+ }
+
+}
+
+# delete_user($user)
+sub delete_user
+{
+ my $user = shift;
+ my $dn_line;
+
+ if (!defined($dn_line = get_user_dn($user))) {
+ print "$0: user $user doesn't exist\n";
+ exit (10);
+ }
+
+ my $dn = get_dn_from_line($dn_line);
+ system "$ldapdelete $dn >/dev/null";
+}
+
+# $success = group_add($groupname, $group_gid, $force_using_existing_gid)
+sub group_add
+{
+ my ($gname, $gid, $force) = @_;
+
+ my $nscd_status = system "/etc/init.d/nscd status >/dev/null 2>&1";
+
+ if ($nscd_status == 0) {
+ system "/etc/init.d/nscd stop > /dev/null 2>&1";
+ }
+
+ if (!defined($gid)) {
+ while (defined(getgrgid($GID_START))) {
+ $GID_START++;
+ }
+ $gid = $GID_START;
+ } else {
+ if (!defined($force)) {
+ if (defined(getgrgid($gid))) {
+ return 0;
+ }
+ }
+ }
+
+ if ($nscd_status == 0) {
+ system "/etc/init.d/nscd start > /dev/null 2>&1";
+ }
+
+ my $tmpldif =
+"dn: cn=$gname,$groupsdn
+objectclass: posixGroup
+cn: $gname
+gidNumber: $gid
+
+";
+
+ die "$0: error while adding posix group $gname\n"
+ unless (do_ldapadd($tmpldif) == 0);
+
+ undef $tmpldif;
+
+ return 1;
+}
+
+# $homedir = get_homedir ($user)
+sub get_homedir
+{
+ my $user = shift;
+ my $homeDir=`$ldapsearch -b '$suffix' -s '$scope' '(&(objectclass=posixAccount)(uid=$user))' | grep "^homeDirectory:"`;
+ chomp $homeDir;
+ if ($homeDir eq '') {
+ return undef;
+ }
+ $homeDir =~ s/^homeDirectory: //;
+
+ return $homeDir;
+}
+
+# search for an user
+sub read_user
+{
+ my $user = shift;
+ my $lines=`$ldapsearch -b '$suffix' -s '$scope' '(&(objectclass=posixAccount)(uid=$user))' -LLL`;
+ chomp $lines;
+ if ($lines eq '') {
+ return undef;
+ }
+
+ return $lines;
+}
+
+# search for a group
+sub read_group
+{
+ my $user = shift;
+ my $lines=`$ldapsearch -b '$groupsdn' -s '$scope' '(&(objectclass=posixGroup)(cn=$user))' -LLL`;
+ chomp $lines;
+ if ($lines eq '') {
+ return undef;
+ }
+
+ return $lines;
+}
+
+# find groups of a given user
+sub find_groups_of
+{
+ my $user = shift;
+ my $lines=`$ldapsearch -b '$groupsdn' -s '$scope' '(&(objectclass=posixGroup)(memberuid=$user))' -LLL | grep "^dn: "`;
+ chomp $lines;
+ if ($lines eq '') {
+ return undef;
+ }
+
+ return $lines;
+}
+
+# return the gidnumber for a group given as name or gid
+# -1 : bad group name
+# -2 : bad gidnumber
+sub parse_group
+{
+ my $userGidNumber = shift;
+
+ if ($userGidNumber =~ /[^\d]/ ) {
+ my $gname = $userGidNumber;
+ my $gidnum = getgrnam($gname);
+ if ($gidnum !~ /\d+/) {
+ return -1;
+ } else {
+ $userGidNumber = $gidnum;
+ }
+ } elsif (!defined(getgrgid($userGidNumber))) {
+ return -2;
+ }
+ return $userGidNumber;
+}
+
+# remove $user from $group
+sub group_remove_member
+{
+ my ($group, $user) = @_;
+
+ my $grp_line = get_group_dn($group);
+ if (!defined($grp_line)) {
+ return 0;
+ }
+ my $members = `$ldapsearch -b '$groupsdn' -s '$scope' '(&(objectclass=posixgroup)(cn=$group))' | grep -i "^memberUid:"`;
+
+ #print "avant ---\n$members\n";
+ $members =~ s/memberUid: $user\n//;
+ #print "----\n$members\n---\n";
+
+ chomp($members);
+
+ my $header;
+ if ($members eq '') {
+ $header = "changetype: modify\n";
+ $header .= "delete: memberUid";
+ } else {
+ $header = "changetype: modify\n";
+ $header .= "replace: memberUid";
+ }
+
+ my $tmpldif =
+"$grp_line
+$header
+$members
+";
+ die "$0: error while modifying group $group\n"
+ unless (do_ldapmodify($tmpldif) == 0);
+ undef $tmpldif;
+
+ return 1;
+}
+
+sub group_get_members
+{
+ my ($group) = @_;
+ my @members;
+
+ my $grp_line = get_group_dn($group);
+ if (!defined($grp_line)) {
+ return 0;
+ }
+ my $members = `$ldapsearch -b '$groupsdn' -s '$scope' '(&(objectclass=posixgroup)(cn=$group))' memberUid | grep -i "^memberUid:"`;
+
+ my @lines = split (/\n/, $members);
+ foreach my $line (@lines) {
+ $line =~ s/^memberUid: //;
+ push(@members, $line);
+ }
+
+ return @members;
+}
+
+sub file_write {
+ my ($filename, $filecontent) = @_;
+ local *FILE;
+ open (FILE, "> $filename") ||
+ die "Cannot open «$filename» for writing: $!\n";
+ print FILE $filecontent;
+ close FILE;
+}
+
+# wrapper for ldapadd
+sub do_ldapadd2
+{
+ my $ldif = shift;
+
+ my $tempfile = "/tmp/smbldapadd.$$";
+ file_write($tempfile, $ldif);
+
+ my $rc = system "$ldapadd < $tempfile >/dev/null";
+ unlink($tempfile);
+ return $rc;
+}
+
+sub do_ldapadd
+{
+ my $ldif = shift;
+
+ my $FILE = "|$ldapadd >/dev/null";
+ open (FILE, $FILE) || die "$!\n";
+ print FILE <<EOF;
+$ldif
+EOF
+ ;
+ close FILE;
+ my $rc = $?;
+ return $rc;
+}
+
+# wrapper for ldapmodify
+sub do_ldapmodify2
+{
+ my $ldif = shift;
+
+ my $tempfile = "/tmp/smbldapmod.$$";
+ file_write($tempfile, $ldif);
+
+ my $rc = system "$ldapmodify -r < $tempfile >/dev/null";
+ unlink($tempfile);
+ return $rc;
+}
+
+sub do_ldapmodify
+{
+ my $ldif = shift;
+
+ my $FILE = "|$ldapmodify -r >/dev/null";
+ open (FILE, $FILE) || die "$!\n";
+ print FILE <<EOF;
+$ldif
+EOF
+ ;
+ close FILE;
+ my $rc = $?;
+
+ return $rc;
+}
+
+
+
+1;
+
diff --git a/examples/VFS/.cvsignore b/examples/VFS/.cvsignore
index 0b0923a496a..e3ebfe8e3d5 100644
--- a/examples/VFS/.cvsignore
+++ b/examples/VFS/.cvsignore
@@ -1,2 +1,6 @@
.libs
*.so
+Makefile
+config.status
+config.log
+config.cache
diff --git a/examples/VFS/Makefile b/examples/VFS/Makefile
deleted file mode 100644
index eaa1ffbb54e..00000000000
--- a/examples/VFS/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Makefile for samba-vfs examples
-#
-#
-
-# Variables
-
-CC = gcc
-LIBTOOL = libtool
-
-SAMBA_SRC = ../../source
-SAMBA_INCL = ../../source/include
-UBIQX_SRC = ../../source/ubiqx
-SMBWR_SRC = ../../source/smbwrapper
-CFLAGS = -I$(SAMBA_SRC) -I$(SAMBA_INCL) -I$(UBIQX_SRC) -I$(SMBWR_SRC) -Wall -g
-VFS_OBJS = audit.so skel.so recycle.so
-
-# Default target
-
-default: $(VFS_OBJS)
-
-# Pattern rules
-
-%.so: %.lo
- $(LIBTOOL) $(CC) -shared -o $@ $< $(LDFLAGS)
-
-%.lo: %.c
- $(LIBTOOL) $(CC) $(CPPFLAGS) $(CFLAGS) -c $<
-
-# Misc targets
-
-clean:
- rm -rf .libs
- rm -f core *~ *% *.bak \
- $(VFS_OBJS) $(VFS_OBJS:.so=.o) $(VFS_OBJS:.so=.lo)
diff --git a/examples/VFS/Makefile.in b/examples/VFS/Makefile.in
new file mode 100644
index 00000000000..a39ab511dd1
--- /dev/null
+++ b/examples/VFS/Makefile.in
@@ -0,0 +1,31 @@
+##########################################################################
+# Makefile.in for Samba VFS modules
+###########################################################################
+
+CC=@CC@
+LIBTOOL=@LIBTOOL@
+CFLAGS=@CFLAGS@
+LDFLAGS=@LDFLAGS@
+
+VFS_OBJS=audit.so skel.so block/block.so recycle/recycle.so
+
+SHELL=/bin/sh
+
+default: $(VFS_OBJS)
+
+# Pattern rules
+
+%.so: %.lo
+ @echo Linking $<
+ @$(LIBTOOL) --mode=link $(CC) -o $@ $< $(LDFLAGS)
+
+%.lo: %.c
+ @echo Compiling $<
+ @$(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+
+# Misc targets
+
+clean:
+ rm -rf .libs */.libs
+ rm -f core *~ *% *.bak *.o */*.o *.lo $(VFS_OBJS)
+
diff --git a/examples/VFS/README b/examples/VFS/README
index d3053a48f3b..475c4ec43fe 100644
--- a/examples/VFS/README
+++ b/examples/VFS/README
@@ -17,14 +17,9 @@ construction. The following VFS modules are given:
connect/disconnect, directory opens/create/remove,
file open/close/rename/unlink/chmod.
- recycle
- Add a recycle bin facility to a samba share
- Copy this to somewhere like /usr/local/samba/lib/recycle.so
- and then add these options on a per-share basis to enable the
- recycle bin :
-
- vfs object = /usr/local/samba/lib/recycle.so
- vfs options= recycle=.recycle
+ recycle/
+ Add a recycle bin facility to a samba share.
+ see recycle/README for details
block/
diff --git a/examples/VFS/block/Makefile b/examples/VFS/block/Makefile
deleted file mode 100644
index 4887915fb4f..00000000000
--- a/examples/VFS/block/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Makefile for samba-vfs examples
-#
-#
-
-# Variables
-
-CC = gcc
-LIBTOOL = libtool
-
-SAMBA_SRC = ../../../source
-SAMBA_INCL = ${SAMBA_SRC}/include
-UBIQX_SRC = ${SAMBA_SRC}/ubiqx
-SMBWR_SRC = ${SAMBA_SRC}/smbwrapper
-CFLAGS = -I$(SAMBA_SRC) -I$(SAMBA_INCL) -I$(UBIQX_SRC) -I$(SMBWR_SRC) -Wall -g
-
-
-VFS_OBJS = block.so
-
-# Default target
-
-default: $(VFS_OBJS)
-
-# Pattern rules
-
-%.so: %.lo
- $(LIBTOOL) $(CC) -shared -o $@ $< $(LDFLAGS)
-
-%.lo: %.c
- $(LIBTOOL) $(CC) $(CPPFLAGS) $(CFLAGS) -c $<
-
-# Misc targets
-
-clean:
- rm -rf .libs
- rm -f core *~ *% *.bak \
- $(VFS_OBJS) $(VFS_OBJS:.so=.o) $(VFS_OBJS:.so=.lo)
diff --git a/examples/VFS/block/block.c b/examples/VFS/block/block.c
index 8c0fa61d506..a8b17a35dd4 100644
--- a/examples/VFS/block/block.c
+++ b/examples/VFS/block/block.c
@@ -47,6 +47,7 @@
+
DIR *block_opendir(struct connection_struct *conn, const char *fname);
int block_connect(struct connection_struct *conn, const char *service, const char *user);
void block_disconnect(struct connection_struct *conn);
@@ -461,7 +462,18 @@ BOOL search(struct stat *stat_buf)
BOOL dir_search(char *link, const char *dir)
{
- char buf[PATH_MAX +1], *ext_path;
+ char *ext_path;
+
+#ifdef PATH_MAX
+ char buf[PATH_MAX +1];
+#else
+#ifdef MAXPATHLEN
+ char buf[MAXPATHLEN +1];
+#else
+ char buf[BUFSIZ];
+#endif
+#endif
+
int len = 0;
struct block_dir *tmp_pblock = pblock_dir;
diff --git a/examples/VFS/configure b/examples/VFS/configure
new file mode 100755
index 00000000000..e70d69f02d7
--- /dev/null
+++ b/examples/VFS/configure
@@ -0,0 +1,1161 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --with-included-popt use bundled popt library, not from system"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+uname=`uname`
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:533: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:563: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:614: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:646: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 657 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:662: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:688: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:693: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:702: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:721: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+
+# Extract the first word of "libtool", so it can be a program name with args.
+set dummy libtool; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:756: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_LIBTOOL'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$LIBTOOL" in
+ /*)
+ ac_cv_path_LIBTOOL="$LIBTOOL" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_LIBTOOL="$LIBTOOL" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_LIBTOOL="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+LIBTOOL="$ac_cv_path_LIBTOOL"
+if test -n "$LIBTOOL"; then
+ echo "$ac_t""$LIBTOOL" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test "$LIBTOOL" = ""; then
+ echo
+ echo 'FATAL ERROR: libtool does not seem to be installed.'
+ echo $pkg_name cannot be built without a working libtool installation.
+ exit 1
+fi
+
+#
+# Config CFLAGS settings
+#
+CFLAGS="-Wall"
+
+case "$uname" in
+ AIX)
+ if test "${GCC}" = "yes"; then
+ CFLAGS="$CFLAGS -I/usr/include -D_LINUX_SOURCE_COMPAT"
+ else
+ CFLAGS="-D_LINUX_SOURCE_COMPAT"
+ fi
+ ;;
+ SunOS)
+ if test "${GCC}" = "yes"; then
+ CFLAGS="$CFLAGS"
+ else
+ CFLAGS=""
+ fi
+ ;;
+# Linux)
+# CFLAGS="-Wall"
+# ;;
+esac
+
+#
+# Config LDLAGS settings
+#
+LDFLAGS="-shared"
+
+case "$uname" in
+ AIX)
+ LDFLAGS="-Wl,-G,-bexpall,-bnoentry"
+ ;;
+ SunOS)
+ LDFLAGS="-G"
+ ;;
+# Linux)
+# echo "Linux found"
+# LDFLAGS="-shared"
+# ;;
+esac
+
+#################################################
+# Check to see if we should use the included popt
+
+# Check whether --with-included-popt or --without-included-popt was given.
+if test "${with_included_popt+set}" = set; then
+ withval="$with_included_popt"
+
+ case "$withval" in
+ yes)
+ INCLUDED_POPT=yes
+ ;;
+ no)
+ INCLUDED_POPT=no
+ ;;
+ esac
+fi
+
+if test x"$INCLUDED_POPT" != x"yes"; then
+ echo $ac_n "checking for poptGetContext in -lpopt""... $ac_c" 1>&6
+echo "configure:857: checking for poptGetContext in -lpopt" >&5
+ac_lib_var=`echo popt'_'poptGetContext | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lpopt $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 865 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char poptGetContext();
+
+int main() {
+poptGetContext()
+; return 0; }
+EOF
+if { (eval echo configure:876: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ INCLUDED_POPT=no
+else
+ echo "$ac_t""no" 1>&6
+INCLUDED_POPT=yes
+fi
+
+fi
+
+echo $ac_n "checking whether to use included popt""... $ac_c" 1>&6
+echo "configure:900: checking whether to use included popt" >&5
+if test x"$INCLUDED_POPT" = x"yes"; then
+ echo "$ac_t""$srcdir/popt" 1>&6
+ CFLAGS="$CFLAGS -I../../source/popt"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+CFLAGS="$CFLAGS -I../../source -I../../source/include -I../../source/ubiqx -I../../source/smbwrapper"
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@LIBTOOL@%$LIBTOOL%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/examples/VFS/configure.in b/examples/VFS/configure.in
new file mode 100644
index 00000000000..2afa2e1a044
--- /dev/null
+++ b/examples/VFS/configure.in
@@ -0,0 +1,92 @@
+dnl Samba VFS Modules
+
+AC_INIT
+
+uname=`uname`
+
+dnl Check programs needed
+AC_PROG_CC
+
+dnl ensure libtool is installed
+AC_PATH_PROG(LIBTOOL, libtool,,)
+if test "$LIBTOOL" = ""; then
+ echo
+ echo 'FATAL ERROR: libtool does not seem to be installed.'
+ echo $pkg_name cannot be built without a working libtool installation.
+ exit 1
+fi
+
+#
+# Config CFLAGS settings
+#
+CFLAGS="-Wall"
+
+case "$uname" in
+ AIX)
+ if test "${GCC}" = "yes"; then
+ CFLAGS="$CFLAGS -I/usr/include -D_LINUX_SOURCE_COMPAT"
+ else
+ CFLAGS="-D_LINUX_SOURCE_COMPAT"
+ fi
+ ;;
+ SunOS)
+ if test "${GCC}" = "yes"; then
+ CFLAGS="$CFLAGS"
+ else
+ CFLAGS=""
+ fi
+ ;;
+# Linux)
+# CFLAGS="-Wall"
+# ;;
+esac
+
+#
+# Config LDLAGS settings
+#
+LDFLAGS="-shared"
+
+case "$uname" in
+ AIX)
+ LDFLAGS="-Wl,-G,-bexpall,-bnoentry"
+ ;;
+ SunOS)
+ LDFLAGS="-G"
+ ;;
+# Linux)
+# echo "Linux found"
+# LDFLAGS="-shared"
+# ;;
+esac
+
+#################################################
+# Check to see if we should use the included popt
+
+AC_ARG_WITH(included-popt,
+[ --with-included-popt use bundled popt library, not from system],
+[
+ case "$withval" in
+ yes)
+ INCLUDED_POPT=yes
+ ;;
+ no)
+ INCLUDED_POPT=no
+ ;;
+ esac ],
+)
+if test x"$INCLUDED_POPT" != x"yes"; then
+ AC_CHECK_LIB(popt, poptGetContext,
+ INCLUDED_POPT=no, INCLUDED_POPT=yes)
+fi
+
+AC_MSG_CHECKING(whether to use included popt)
+if test x"$INCLUDED_POPT" = x"yes"; then
+ AC_MSG_RESULT($srcdir/popt)
+ CFLAGS="$CFLAGS -I../../source/popt"
+else
+ AC_MSG_RESULT(no)
+fi
+
+CFLAGS="$CFLAGS -I../../source -I../../source/include -I../../source/ubiqx -I../../source/smbwrapper"
+
+AC_OUTPUT([Makefile])
diff --git a/examples/VFS/recycle.c b/examples/VFS/recycle.c
deleted file mode 100644
index 74d3657895a..00000000000
--- a/examples/VFS/recycle.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Auditing VFS module for samba. Log selected file operations to syslog
- * facility.
- *
- * Copyright (C) 2001, Brandon Stone, Amherst College, <bbstone@amherst.edu>.
- * Copyright (C) 2002, Jeremy Allison - modified to make a VFS module.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <sys/stat.h>
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#include <syslog.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#include <errno.h>
-#include <string.h>
-#include <includes.h>
-#include <vfs.h>
-
-/* VFS operations */
-
-extern struct vfs_ops default_vfs_ops; /* For passthrough operation */
-
-static int recycle_unlink(connection_struct *, const char *);
-static int recycle_connect(struct connection_struct *conn, const char *service, const char *user);
-static void recycle_disconnect(struct connection_struct *conn);
-
-struct vfs_ops recycle_ops = {
-
- /* Disk operations */
-
- recycle_connect, /* connect */
- recycle_disconnect, /* disconnect */
- NULL, /* disk free */
-
- /* Directory operations */
-
- NULL, /* opendir */
- NULL, /* readdir */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* closedir */
-
- /* File operations */
-
- NULL, /* open */
- NULL, /* close */
- NULL, /* read */
- NULL, /* write */
- NULL, /* lseek */
- NULL, /* rename */
- NULL, /* fsync */
- NULL, /* stat */
- NULL, /* fstat */
- NULL, /* lstat */
- recycle_unlink,
- NULL, /* chmod */
- NULL, /* fchmod */
- NULL, /* chown */
- NULL, /* fchown */
- NULL, /* chdir */
- NULL, /* getwd */
- NULL, /* utime */
- NULL, /* ftruncate */
- NULL, /* lock */
- NULL, /* symlink */
- NULL, /* readlink */
- NULL, /* link */
- NULL, /* mknod */
- NULL, /* realpath */
- NULL, /* fget_nt_acl */
- NULL, /* get_nt_acl */
- NULL, /* fset_nt_acl */
- NULL, /* set_nt_acl */
-
- NULL, /* chmod_acl */
- NULL, /* fchmod_acl */
-
- NULL, /* sys_acl_get_entry */
- NULL, /* sys_acl_get_tag_type */
- NULL, /* sys_acl_get_permset */
- NULL, /* sys_acl_get_qualifier */
- NULL, /* sys_acl_get_file */
- NULL, /* sys_acl_get_fd */
- NULL, /* sys_acl_clear_perms */
- NULL, /* sys_acl_add_perm */
- NULL, /* sys_acl_to_text */
- NULL, /* sys_acl_init */
- NULL, /* sys_acl_create_entry */
- NULL, /* sys_acl_set_tag_type */
- NULL, /* sys_acl_set_qualifier */
- NULL, /* sys_acl_set_permset */
- NULL, /* sys_acl_valid */
- NULL, /* sys_acl_set_file */
- NULL, /* sys_acl_set_fd */
- NULL, /* sys_acl_delete_def_file */
- NULL, /* sys_acl_get_perm */
- NULL, /* sys_acl_free_text */
- NULL, /* sys_acl_free_acl */
- NULL /* sys_acl_free_qualifier */
-};
-
-/* VFS initialisation function. Return initialised vfs_ops structure
- back to SAMBA. */
-
-struct vfs_ops *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops)
-{
- struct vfs_ops tmp_ops;
-
- *vfs_version = SMB_VFS_INTERFACE_VERSION;
- memcpy(&tmp_ops, def_vfs_ops, sizeof(struct vfs_ops));
- tmp_ops.unlink = recycle_unlink;
- tmp_ops.connect = recycle_connect;
- tmp_ops.disconnect = recycle_disconnect;
- memcpy(&recycle_ops, &tmp_ops, sizeof(struct vfs_ops));
- return &recycle_ops;
-}
-
-static int recycle_connect(struct connection_struct *conn, const char *service, const char *user)
-{
- pstring opts_str;
- fstring recycle_bin;
- char *p;
-
- DEBUG(3,("recycle_connect: called for service %s as user %s\n", service, user));
-
- pstrcpy(opts_str, (const char *)lp_vfs_options(SNUM(conn)));
- if (!*opts_str) {
- DEBUG(3,("recycle_connect: No options listed (%s).\n", lp_vfs_options(SNUM(conn)) ));
- return 0; /* No options. */
- }
-
- p = opts_str;
- if (next_token(&p,recycle_bin,"=",sizeof(recycle_bin))) {
- if (!strequal("recycle", recycle_bin)) {
- DEBUG(3,("recycle_connect: option %s is not recycle\n", recycle_bin ));
- return -1;
- }
- }
-
- if (!next_token(&p,recycle_bin," \n",sizeof(recycle_bin))) {
- DEBUG(3,("recycle_connect: no option after recycle=\n"));
- return -1;
- }
-
- DEBUG(10,("recycle_connect: recycle name is %s\n", recycle_bin ));
-
- conn->vfs_private = (void *)strdup(recycle_bin);
- return 0;
-}
-
-static void recycle_disconnect(struct connection_struct *conn)
-{
- SAFE_FREE(conn->vfs_private);
-}
-
-static BOOL recycle_XXX_exist(connection_struct *conn, const char *dname, BOOL isdir)
-{
- SMB_STRUCT_STAT st;
-
- if (default_vfs_ops.stat(conn,dname,&st) != 0)
- return(False);
-
- if (isdir)
- return S_ISDIR(st.st_mode) ? True : False;
- else
- return S_ISREG(st.st_mode) ? True : False;
-}
-
-static BOOL recycle_directory_exist(connection_struct *conn, const char *dname)
-{
- return recycle_XXX_exist(conn, dname, True);
-}
-
-static BOOL recycle_file_exist(connection_struct *conn, const char *fname)
-{
- return recycle_XXX_exist(conn, fname, False);
-}
-
-static SMB_OFF_T recycle_get_file_size(connection_struct *conn, const char *fname)
-{
- SMB_STRUCT_STAT st;
-
- if (default_vfs_ops.stat(conn,fname,&st) != 0)
- return (SMB_OFF_T)-1;
-
- return(st.st_size);
-}
-
-/********************************************************************
- Check if file should be recycled
-*********************************************************************/
-
-static int recycle_unlink(connection_struct *conn, const char *inname)
-{
- fstring recycle_bin;
- pstring fname;
- char *base, *ext;
- pstring bin;
- int i=1, len, addlen;
- int dir_mask=0770;
- SMB_BIG_UINT dfree,dsize,bsize;
-
- *recycle_bin = '\0';
- pstrcpy(fname, inname);
-
- if (conn->vfs_private)
- fstrcpy(recycle_bin, (const char *)conn->vfs_private);
-
- if(!*recycle_bin) {
- DEBUG(3, ("recycle bin: share parameter not set, purging %s...\n", fname));
- return default_vfs_ops.unlink(conn,fname);
- }
-
- if(recycle_get_file_size(conn, fname) == 0) {
- DEBUG(3, ("recycle bin: file %s is empty, purging...\n", fname));
- return default_vfs_ops.unlink(conn,fname);
- }
-
- base = strrchr(fname, '/') + 1;
- if(base == (char*)1)
- ext = strrchr(fname, '.');
- else
- ext = strrchr(base, '.');
-
- pstrcpy(bin, recycle_bin);
- pstrcat(bin, "/");
- pstrcat(bin, base);
-
- if(strcmp(fname,bin) == 0) {
- DEBUG(3, ("recycle bin: file %s exists, purging...\n", fname));
- return default_vfs_ops.unlink(conn,fname);
- }
-
- len = strlen(bin);
- addlen = sizeof(pstring)-len-1;
- while(recycle_file_exist(conn,bin)) {
- slprintf(bin+len, addlen, " (Copy #%d)", i++);
- pstrcat(bin, ext);
- }
-
- DEBUG(3, ("recycle bin: moving source=%s to dest=%s\n", fname, bin));
- default_vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
- if((unsigned int)dfree > 0) {
- int ret;
- if(!recycle_directory_exist(conn,recycle_bin)) {
- DEBUG(3, ("recycle bin: directory %s nonexistant, creating...\n", recycle_bin));
- if (default_vfs_ops.mkdir(conn,recycle_bin,dir_mask) == -1) {
- DEBUG(3, ("recycle bin: unable to create directory %s. Error was %s\n",
- recycle_bin, strerror(errno) ));
- }
- }
- DEBUG(3, ("recycle bin: move %s -> %s\n", fname, bin));
-
- ret = default_vfs_ops.rename(conn, fname, bin);
- if (ret == -1) {
- DEBUG(3, ("recycle bin: move error %d (%s)\n", errno, strerror(errno) ));
- DEBUG(3, ("recycle bin: move failed, purging...\n"));
- return default_vfs_ops.unlink(conn,fname);
- }
- return ret;
- } else {
- DEBUG(3, ("recycle bin: move failed, purging...\n"));
- return default_vfs_ops.unlink(conn,fname);
- }
-}
diff --git a/examples/VFS/recycle/README b/examples/VFS/recycle/README
new file mode 100644
index 00000000000..2b85a65925e
--- /dev/null
+++ b/examples/VFS/recycle/README
@@ -0,0 +1,83 @@
+The recycle VFS module implements a recycle bin for Samba.
+Deleted files will be moved to a special directory and
+not be deleted unless specified in the configuration file.
+It is up to the administrator/user to clean up the files
+in the recycle bin.
+
+Installation:
+
+1. Build VFS module using the GNU autoconf script and Makefile
+ in the parent directory (cd .. && ./configure && make)
+2. Install module by copying to /usr/lib/samba/vfs (or any other place you like)
+3. Install/modify recycle.conf. See below for the description
+4. Modify smb.conf to use the recycle module
+ Add the lines "vfs object = /usr/lib/samba/recycle.so"
+ and "vfs options = /etc/samba/recycle.conf".
+5. Start Samba
+
+
+Options for recycle.conf:
+name
+ name of the recycle bin at root level of the share
+ allows smb.conf substutitions like %U.
+ Example:
+ name = .recycle/%U
+
+mode
+ KEEP_DIRECTORIES : retain directory hierarchy of deleted file,
+ VERSIONS : create several versions of a file in recycle bin if
+ the file already exists in the recycle bin
+ e.g. mytext.doc
+ Copy #1 of mytext.doc
+ Copy #2 of mytext.doc
+
+ TOUCH : touch access date when moving files to the recycle bin.
+ This is useful for automatic cleanup scripts.
+ Attn: This doesn't work if you have no write permissions
+ to the file being deleted. Deletion works if you
+ have write permissions to the parent directory.
+ Example:
+ mode = KEEP_DIRECTORIES|VERSIONS|TOUCH
+
+maxsize
+ maximum size of files to be moved to recycle bin. Setting this zo
+ zero (default) moves files of any size to the recycle bin.
+ Example:
+ maxsize = 0
+
+exclude
+ exclude files from moving to recycle bin. Delete them immediately
+ Useful for temporary files. You can use the wildcards * and ?
+ Example:
+ exclude = *.tmp|*.temp|*.obj|~$*|*.$$$
+
+excludedir
+ exclude directories from the recycle bin, useful for temporary
+ directories.
+ Example
+ excludedir = /tmp|/temp|/trash
+
+noversions
+ don't create versions of files in the recycle bin. Only usefull if
+ mode = VERSIONS is set.
+ Examples:
+ noversions = *.doc|*.xls|*.ppt
+
+Example smb.conf:
+
+[homes]
+ comment = Home-directory
+ path = /home/%u
+ read only = No
+ create mask = 0750
+ vfs object = /usr/lib/samba/recycle.so
+ vfs options = /etc/samba/recycle.conf
+
+Example recycle.conf:
+
+name = .recycle/%U
+mode = KEEP_DIRECTORIES|NOVERSIONS|TOUCH
+maxsize = 0
+exclude = *.tmp|*.temp|*.o|*.obj|~$*
+excludedir = /tmp|/temp|/cache
+noversions = *.doc|*.xls|*.ppt
diff --git a/examples/VFS/recycle/cleanup_recycle.pl b/examples/VFS/recycle/cleanup_recycle.pl
new file mode 100644
index 00000000000..f614cf78708
--- /dev/null
+++ b/examples/VFS/recycle/cleanup_recycle.pl
@@ -0,0 +1,25 @@
+# !/usr/bin/perl -w
+#
+# this script looks for all files with an access date older than
+# $maxage days and deletes them.
+# Empty directories will be deleted afterwards
+#
+
+$dirpath = "/data/.recycle";
+$maxage = 2;
+
+# delete all old files
+@a=`find $dirpath -atime +$maxage`;
+foreach (@a)
+ {
+ print "deleting file: $_";
+ $r = `rm -f $_ 2> /dev/zero`;
+ }
+
+# delete all empty directories
+@a=`find $dirpath -type d | sort -r`;
+foreach (@a)
+ {
+ print "deleting directory: $_";
+ $r = `rmdir $_ 2> /dev/zero`;
+ }
diff --git a/examples/VFS/recycle/recycle.c b/examples/VFS/recycle/recycle.c
new file mode 100644
index 00000000000..3d2d5d79697
--- /dev/null
+++ b/examples/VFS/recycle/recycle.c
@@ -0,0 +1,556 @@
+/*
+ * Recycle bin VFS module for Samba.
+ *
+ * Copyright (C) 2001, Brandon Stone, Amherst College, <bbstone@amherst.edu>.
+ * Copyright (C) 2002, Jeremy Allison - modified to make a VFS module.
+ * Copyright (C) 2002, Juergen Hasch - added some options.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <sys/stat.h>
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#endif
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <errno.h>
+#include <string.h>
+#include <includes.h>
+#include <vfs.h>
+
+const char delimiter = '|'; /* delimiter for options */
+
+/* One per connection */
+
+typedef struct recycle_bin_struct
+{
+ TALLOC_CTX *ctx;
+ char *recycle_bin; /* name of the recycle bin directory */
+ BOOL keep_directories; /* keep directory structure of deleted file in recycle bin */
+ BOOL versions; /* create versions of deleted files with identical name */
+ BOOL touch; /* touch access date of deleted file */
+ char *exclude; /* which files to exclude */
+ char *exclude_dir; /* which directories to exclude */
+ char *noversions; /* which files to exclude from versioning */
+ SMB_OFF_T max_size; /* maximum file size to be saved */
+} recycle_bin_struct;
+
+/* Global Variables */
+static recycle_bin_struct *current;
+
+/* VFS operations */
+
+extern struct vfs_ops default_vfs_ops; /* For passthrough operation */
+
+static int recycle_unlink(connection_struct *, const char *);
+static int recycle_connect(struct connection_struct *conn, const char *service, const char *user);
+static void recycle_disconnect(struct connection_struct *conn);
+
+BOOL checkparam(char *haystack,char *needle);
+
+struct vfs_ops recycle_ops = {
+
+ /* Disk operations */
+
+ recycle_connect, /* connect */
+ recycle_disconnect, /* disconnect */
+ NULL, /* disk free */
+
+ /* Directory operations */
+
+ NULL, /* opendir */
+ NULL, /* readdir */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* closedir */
+
+ /* File operations */
+
+ NULL, /* open */
+ NULL, /* close */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* lseek */
+ NULL, /* rename */
+ NULL, /* fsync */
+ NULL, /* stat */
+ NULL, /* fstat */
+ NULL, /* lstat */
+ recycle_unlink,
+ NULL, /* chmod */
+ NULL, /* fchmod */
+ NULL, /* chown */
+ NULL, /* fchown */
+ NULL, /* chdir */
+ NULL, /* getwd */
+ NULL, /* utime */
+ NULL, /* ftruncate */
+ NULL, /* lock */
+ NULL, /* symlink */
+ NULL, /* readlink */
+ NULL, /* link */
+ NULL, /* mknod */
+ NULL, /* realpath */
+ NULL, /* fget_nt_acl */
+ NULL, /* get_nt_acl */
+ NULL, /* fset_nt_acl */
+ NULL, /* set_nt_acl */
+
+ NULL, /* chmod_acl */
+ NULL, /* fchmod_acl */
+
+ NULL, /* sys_acl_get_entry */
+ NULL, /* sys_acl_get_tag_type */
+ NULL, /* sys_acl_get_permset */
+ NULL, /* sys_acl_get_qualifier */
+ NULL, /* sys_acl_get_file */
+ NULL, /* sys_acl_get_fd */
+ NULL, /* sys_acl_clear_perms */
+ NULL, /* sys_acl_add_perm */
+ NULL, /* sys_acl_to_text */
+ NULL, /* sys_acl_init */
+ NULL, /* sys_acl_create_entry */
+ NULL, /* sys_acl_set_tag_type */
+ NULL, /* sys_acl_set_qualifier */
+ NULL, /* sys_acl_set_permset */
+ NULL, /* sys_acl_valid */
+ NULL, /* sys_acl_set_file */
+ NULL, /* sys_acl_set_fd */
+ NULL, /* sys_acl_delete_def_file */
+ NULL, /* sys_acl_get_perm */
+ NULL, /* sys_acl_free_text */
+ NULL, /* sys_acl_free_acl */
+ NULL /* sys_acl_free_qualifier */
+};
+
+/**
+ * Parse recycle bin configuration parameters
+ *
+ * @retval False if out of memory
+ **/
+static BOOL do_parameter(char *pszParmName, char *pszParmValue)
+{
+ if (StrCaseCmp("name",pszParmName)==0) {
+ current->recycle_bin = (char *)talloc(current->ctx,sizeof(pstring));
+ if (current->recycle_bin == NULL)
+ return False;
+ current->recycle_bin = safe_strcpy(current->recycle_bin,pszParmValue,sizeof(pstring));
+ standard_sub_basic(current->recycle_bin);
+ trim_string(current->recycle_bin,"/","/");
+ DEBUG(10, ("name=%s\n", current->recycle_bin));
+ } else if (StrCaseCmp("mode",pszParmName)==0) {
+ if (checkparam(pszParmValue,"KEEP_DIRECTORIES") == True)
+ current->keep_directories = True;
+ if (checkparam(pszParmValue,"VERSIONS") == True)
+ current->versions = True;
+ if (checkparam(pszParmValue,"TOUCH") == True)
+ current->touch = True;
+ DEBUG(10, ("mode=%s\n", pszParmValue));
+ } else if (StrCaseCmp("maxsize",pszParmName)==0) {
+ current->max_size = strtoul(pszParmValue,NULL,10);
+ DEBUG(10, ("max_size=%ld\n", (long int)current->max_size));
+ } else if (StrCaseCmp("exclude",pszParmName)==0) {
+ current->exclude = talloc_strdup(current->ctx, pszParmValue);
+ if (current->exclude == NULL)
+ return False;
+ DEBUG(10, ("exclude=%s\n", current->exclude));
+ } else if (StrCaseCmp("excludedir",pszParmName)==0) {
+ current->exclude_dir = talloc_strdup(current->ctx, pszParmValue);
+ if (current->exclude_dir == NULL)
+ return False;
+ DEBUG(10, ("exclude_dir=%s\n", current->exclude_dir));
+ } else if (StrCaseCmp("noversions",pszParmName)==0) {
+ current->noversions = talloc_strdup(current->ctx, pszParmValue);
+ if (current->noversions == NULL)
+ return False;
+ DEBUG(10, ("noversions=%s\n", current->noversions));
+ }
+ return True;
+}
+
+/**
+ * We don't care for sections in configuration file
+ *
+ **/
+static BOOL do_section(char *pszSectionName)
+{
+ return True;
+}
+
+/**
+ * VFS initialisation function.
+ *
+ * @retval initialised vfs_ops structure
+ **/
+struct vfs_ops *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops)
+{
+ struct vfs_ops tmp_ops;
+ DEBUG(3, ("Initializing VFS module recycle\n"));
+
+ *vfs_version = SMB_VFS_INTERFACE_VERSION;
+ memcpy(&tmp_ops, def_vfs_ops, sizeof(struct vfs_ops));
+ tmp_ops.unlink = recycle_unlink;
+ tmp_ops.connect = recycle_connect;
+ tmp_ops.disconnect = recycle_disconnect;
+ memcpy(&recycle_ops, &tmp_ops, sizeof(struct vfs_ops));
+ return &recycle_ops;
+}
+
+static int recycle_connect(struct connection_struct *conn, const char *service, const char *user)
+{
+ const char *p;
+ pstring conf_file;
+ int rc;
+ TALLOC_CTX *ctx=NULL;
+
+ DEBUG(3,("Called for service %s (%d) as user %s\n", service, SNUM(conn), user));
+
+ if (!(ctx = talloc_init_named("recycle bin"))) {
+ DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
+ return 0;
+ }
+
+ /* read configuration file */
+ *conf_file='\0';
+ p = (const char *)lp_vfs_options(SNUM(conn));
+ if (p != NULL && strlen(p) > 0) {
+ pstrcpy(conf_file,p);
+ DEBUG(10,("Using configuration file %s\n",conf_file));
+ }
+
+ current = talloc(ctx,sizeof(recycle_bin_struct));
+ if ( current == NULL) {
+ DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n"));
+ return -1;
+ }
+ current->ctx = ctx;
+ /* Set defaults */
+ current->recycle_bin = talloc_strdup(ctx,".recycle");
+ current->keep_directories = False;
+ current->versions = False;
+ current->touch = False;
+ current->exclude = "";
+ current->exclude_dir = "";
+ current->noversions = "";
+ current->max_size = 0;
+ if (strlen(conf_file) > 0) {
+ rc=pm_process( conf_file, do_section, do_parameter);
+ DEBUG(10, ("pm_process returned %d\n", rc));
+ }
+ conn->vfs_private= (void *)current;
+ return 0;
+}
+
+static void recycle_disconnect(struct connection_struct *conn)
+{
+ DEBUG(3, ("Disconnecting VFS module recycle_bin\n"));
+ talloc_destroy(((recycle_bin_struct*)conn->vfs_private)->ctx);
+ default_vfs_ops.disconnect(conn);
+}
+
+static BOOL recycle_XXX_exist(connection_struct *conn, const char *dname, BOOL isdir)
+{
+ SMB_STRUCT_STAT st;
+
+ if (default_vfs_ops.stat(conn,dname,&st) != 0)
+ return(False);
+
+ if (isdir)
+ return S_ISDIR(st.st_mode) ? True : False;
+ else
+ return S_ISREG(st.st_mode) ? True : False;
+}
+
+static BOOL recycle_directory_exist(connection_struct *conn, const char *dname)
+{
+ return recycle_XXX_exist(conn, dname, True);
+}
+
+static BOOL recycle_file_exist(connection_struct *conn, const char *fname)
+{
+ return recycle_XXX_exist(conn, fname, False);
+}
+
+/**
+ * Return file size
+ * @param conn connection
+ * @param fname file name
+ * @return size in bytes
+ **/
+static SMB_OFF_T recycle_get_file_size(connection_struct *conn, const char *fname)
+{
+ SMB_STRUCT_STAT st;
+ if (default_vfs_ops.stat(conn,fname,&st) != 0) {
+ DEBUG(0,("stat for %s returned %s\n",fname,strerror(errno)));
+ return (SMB_OFF_T)0;
+ }
+ return(st.st_size);
+}
+
+/**
+ * Create directory tree
+ * @param conn connection
+ * @param dname Directory tree to be created
+ * @return Returns True for success
+ **/
+static BOOL recycle_create_dir(connection_struct *conn, const char *dname)
+{
+ char *c,*y;
+ int i;
+
+ mode_t mode;
+ pstring tempstr;
+ pstring newdir;
+
+ *newdir='\0';
+ mode=S_IREAD|S_IWRITE|S_IEXEC;
+ pstrcpy(tempstr,dname);
+ y=tempstr;
+ /* Create directory tree if neccessary */
+ while((c=strsep(&y,"/"))) {
+ pstrcat(newdir,c);
+ if (recycle_directory_exist(conn,newdir))
+ DEBUG(3, ("dir %s already exists\n",newdir));
+ else {
+ DEBUG(3, ("creating new dir %s\n",newdir));
+ i=default_vfs_ops.mkdir(conn,newdir,mode);
+ if (i) {
+ DEBUG(3,("mkdir failed for %s with error %s\n",newdir,strerror(errno)));
+ return False;
+ }
+ }
+ pstrcat(newdir,"/");
+ }
+ return True;
+}
+
+/**
+ * Check if needle is contained exactly in haystack
+ * @param haystack list of parameters separated by delimimiter character
+ * @param needle string to be matched exactly to haystack
+ * @return True if found
+ **/
+BOOL checkparam(char *haystack,char *needle)
+{
+ char *p,*c;
+ pstring str;
+ int i,len;
+
+ if (haystack==NULL || strlen(haystack)==0 || needle == NULL || strlen(needle)== 0)
+ return False;
+
+ pstrcpy(str,haystack);
+ len=strlen(str)+1;
+ p=c=str;
+
+ for (i=0; i < len; i++, p++) {
+ if (*p == delimiter || *p == '\0') {
+ *p='\0';
+ if(strncmp(c,needle,c-p) == 0)
+ return True;
+ c=p+1;
+ }
+ }
+ return False;
+}
+
+/**
+ * Check if needle is contained in haystack, * and ? patterns are resolved
+ * @param haystack list of parameters separated by delimimiter character
+ * @param needle string to be matched exectly to haystack including pattern matching
+ * @return True if found
+ **/
+BOOL matchparam(char *haystack,char *needle)
+{
+ char *p,*c;
+ pstring str;
+ int i,len;
+
+ if (haystack==NULL || strlen(haystack)==0 || needle == NULL || strlen(needle)== 0)
+ return False;
+
+ pstrcpy(str,haystack);
+ len=strlen(str)+1;
+ p=c=str;
+
+ for (i=0; i < len; i++, p++) {
+ if (*p == delimiter || *p == '\0') {
+ *p='\0';
+ if (!unix_wild_match(c,needle))
+ return True;
+ c=p+1;
+ }
+ }
+ return False;
+}
+
+/**
+ * Touch access date
+ **/
+void recycle_touch(connection_struct *conn, const char *fname)
+{
+ SMB_STRUCT_STAT st;
+ struct utimbuf tb;
+ time_t current;
+
+ if (default_vfs_ops.stat(conn,fname,&st) != 0) {
+ DEBUG(0,("stat for %s returned %s\n",fname,strerror(errno)));
+ return;
+ }
+ current = time(&current);
+ tb.actime = current;
+ tb.modtime = st.st_mtime;
+
+ if (default_vfs_ops.utime(conn, fname, &tb) == -1 )
+ DEBUG(0, ("Touching %s failed, reason = %s\n",fname,strerror(errno)));
+ }
+
+/**
+ * Check if file should be recycled
+ **/
+static int recycle_unlink(connection_struct *conn, const char *inname)
+{
+ pstring fname,fpath, bin;
+ char *base, *ext;
+ int i=1, len, addlen;
+ SMB_BIG_UINT dfree,dsize,bsize;
+ SMB_OFF_T fsize,space_avail;
+ BOOL exist;
+ int rc;
+
+ pstrcpy(fname,inname);
+ if (conn->vfs_private)
+ current = (recycle_bin_struct *)conn->vfs_private;
+ else {
+ DEBUG(0,("Recycle bin not initialized!\n"));
+ return default_vfs_ops.unlink(conn,fname);
+ }
+
+ if(!current->recycle_bin || !*(current->recycle_bin)) {
+ DEBUG(3, ("Recycle path not set, purging %s...\n", fname));
+ return default_vfs_ops.unlink(conn,fname);
+ }
+
+ /* we don't recycle the recycle bin... */
+ if (strstr(fname,current->recycle_bin)==fname) {
+ DEBUG(3, ("File is within recycling bin\n"));
+ return default_vfs_ops.unlink(conn,fname);
+ }
+
+ fsize = recycle_get_file_size(conn,fname);
+ if(fsize == 0) {
+ DEBUG(3, ("File %s is empty, purging...\n", fname));
+ return default_vfs_ops.unlink(conn,fname);
+ }
+
+ if(current->max_size > 0 && fsize > current->max_size) {
+ DEBUG(3, ("File %s exceeds maximum recycle size, purging... \n", fname));
+ return default_vfs_ops.unlink(conn,fname);
+ }
+
+ space_avail = default_vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize)*1024L;
+ DEBUG(10,("space_avail = %Lu, fsize = %Lu\n",space_avail,fsize));
+ if(space_avail < fsize) {
+ DEBUG(3, ("Not enough diskspace, purging file %s\n",fname));
+ return default_vfs_ops.unlink(conn,fname);
+ }
+
+ /* extract filename and path */
+ pstrcpy(fpath,"/");
+ pstrcat(fpath, fname);
+ base = strrchr(fpath, '/');
+ if (base == NULL) {
+ ext = strrchr(fname, '.');
+ base = (char *)fname;
+ pstrcpy(fpath,"/");
+ }
+ else {
+ ext = strrchr(base, '.');
+ *(base++) = '\0';
+ }
+
+ DEBUG(10, ("fname:%s\n", fname)); /* original filename with path */
+ DEBUG(10, ("fpath:%s\n", fpath)); /* original path */
+ DEBUG(10, ("base:%s\n", base)); /* filename without path */
+ DEBUG(10, ("ext:%s\n", ext)); /* filename extension */
+
+ if (matchparam(current->exclude,base)) {
+ DEBUG(3, ("file %s is excluded \n",base));
+ return default_vfs_ops.unlink(conn,fname);
+ }
+
+ if (checkparam(current->exclude_dir,fpath)) {
+ DEBUG(3, ("directory %s is excluded \n",fpath));
+ return default_vfs_ops.unlink(conn,fname);
+ }
+
+ pstrcpy(bin, current->recycle_bin);
+
+ /* see if we need to recreate the original directory structure in the recycle bin */
+ if (current->keep_directories == True)
+ pstrcat(bin, fpath);
+
+ exist=recycle_directory_exist(conn,bin);
+ if (exist)
+ DEBUG(10, ("Directory already exists\n"));
+ else {
+ DEBUG(10, ("Creating directory %s\n",bin));
+ rc=recycle_create_dir(conn,bin);
+ if (rc == False)
+ {
+ DEBUG(3, ("Could not create directory, purging %s...\n", fname));
+ return default_vfs_ops.unlink(conn,fname);
+ }
+ }
+
+ pstrcat(bin, "/");
+ pstrcat(bin,base);
+ DEBUG(10, ("bin:%s\n", bin)); /* new filename with path */
+
+ /* check if we should delete file from recycle bin */
+ if (recycle_file_exist(conn,bin)) {
+ if (current->versions == False || matchparam(current->noversions,base) == True) {
+ DEBUG(3, ("Removing old file %s from recycle bin\n",bin));
+ default_vfs_ops.unlink(conn,bin);
+ }
+ }
+
+ /* rename file we move to recycle bin */
+ len = strlen(bin);
+ addlen = sizeof(pstring)-len-1;
+ while(recycle_file_exist(conn,bin)) {
+ slprintf(bin+len, addlen, " (Copy #%d)", i++);
+ pstrcat(bin, ext);
+ }
+
+ DEBUG(10, ("Moving source=%s to dest=%s\n", fname, bin));
+ rc = default_vfs_ops.rename(conn, fname, bin);
+ if (rc == -1) {
+ DEBUG(3, ("Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno),fname,bin));
+ return default_vfs_ops.unlink(conn,fname);
+ }
+
+ /* touch access date of moved file */
+ if (current->touch == True )
+ recycle_touch(conn,bin);
+ return rc;
+}
diff --git a/examples/VFS/recycle/recycle.conf b/examples/VFS/recycle/recycle.conf
new file mode 100644
index 00000000000..00cc7982124
--- /dev/null
+++ b/examples/VFS/recycle/recycle.conf
@@ -0,0 +1,17 @@
+# name of the recycle bin at root level of share
+name = .recycle
+# mode :
+# KEEP_DIRECTORIES = retain directory hierarchy of deleted file,
+# i.e. recreate all directories in recycle bin
+# VERSIONS = create copies in case of identical file names in recycle bin
+# TOUCH = touch access date of files moved into the recycle bin
+mode = KEEP_DIRECTORIES|VERSIONS|TOUCH
+# maximum file size to be moved to the recycle bin (0 means any size)
+maxsize = 0
+# exclude file names with the following extensions:
+exclude = *.tmp|*.temp|*.o|*.obj|~$*
+# exclude directories:
+excludedir = /tmp|/temp|/cache
+# Add file extensions of files where no versioning is wanted (i.e. copy # 1...)
+# only valid when mode=VERSIONS is set
+noversions = *.doc|*.xls|*.ppt
diff --git a/examples/libsmbclient/testsmbc.c b/examples/libsmbclient/testsmbc.c
index f67c91073c6..7aae9d85616 100644
--- a/examples/libsmbclient/testsmbc.c
+++ b/examples/libsmbclient/testsmbc.c
@@ -95,10 +95,74 @@ int main(int argc, char *argv[])
if (argc > 1) {
- if ((dh1 = smbc_opendir(argv[1]))<1) {
+ /* Try to list the print jobs ... */
- fprintf(stderr, "Could not open directory: %s: %s\n",
- argv[1], strerror(errno));
+ if (smbc_list_print_jobs("smb://samba/pclp", print_list_fn) < 0) {
+
+ fprintf(stderr, "Could not list print jobs: %s, %d\n", strerror(errno), errno);
+ exit(1);
+
+ }
+
+ /* Try to delete the last job listed */
+
+ if (global_id > 0) {
+
+ fprintf(stdout, "Trying to delete print job %u\n", global_id);
+
+ if (smbc_unlink_print_job("smb://samba/pclp", global_id) < 0) {
+
+ fprintf(stderr, "Failed to unlink job id %u, %s, %u\n", global_id,
+ strerror(errno), errno);
+
+ exit(1);
+
+ }
+
+ }
+
+ /* Try to print a file ... */
+
+ if (smbc_print_file("smb://samba/public/testfile2.txt", "smb://samba/pclp") < 0) {
+
+ fprintf(stderr, "Failed to print job: %s %u\n", strerror(errno), errno);
+ exit(1);
+
+ }
+
+ /* Try to delete argv[1] as a file ... */
+
+ if (smbc_unlink(argv[1]) < 0) {
+
+ fprintf(stderr, "Could not unlink: %s, %s, %d\n",
+ argv[1], strerror(errno), errno);
+
+ exit(0);
+
+ }
+
+ if ((dh1 = smbc_opendir("smb://"))<1) {
+
+ fprintf(stderr, "Could not open directory: smb://: %s\n",
+ strerror(errno));
+
+ exit(1);
+
+ }
+
+ if ((dh2 = smbc_opendir("smb://sambanet")) < 0) {
+
+ fprintf(stderr, "Could not open directory: smb://sambanet: %s\n",
+ strerror(errno));
+
+ exit(1);
+
+ }
+
+ if ((dh3 = smbc_opendir("smb://samba")) < 0) {
+
+ fprintf(stderr, "Could not open directory: smb://samba: %s\n",
+ strerror(errno));
exit(1);
@@ -139,6 +203,62 @@ int main(int argc, char *argv[])
dirp = (char *)dirbuf;
+ if ((dirc = smbc_getdents(dh2, (struct smbc_dirent *)dirp,
+ sizeof(dirbuf))) < 0) {
+
+ fprintf(stderr, "Problems getting directory entries: %s\n",
+ strerror(errno));
+
+ exit(1);
+
+ }
+
+ /* Now, process the list of names ... */
+
+ fprintf(stdout, "\nDirectory listing, size = %u\n", dirc);
+
+ while (dirc > 0) {
+
+ dsize = ((struct smbc_dirent *)dirp)->dirlen;
+ fprintf(stdout, "Dir Ent, Type: %u, Name: %s, Comment: %s\n",
+ ((struct smbc_dirent *)dirp)->smbc_type,
+ ((struct smbc_dirent *)dirp)->name,
+ ((struct smbc_dirent *)dirp)->comment);
+
+ dirp += dsize;
+ (char *)dirc -= dsize;
+
+ }
+
+ dirp = (char *)dirbuf;
+
+ if ((dirc = smbc_getdents(dh3, (struct smbc_dirent *)dirp,
+ sizeof(dirbuf))) < 0) {
+
+ fprintf(stderr, "Problems getting directory entries: %s\n",
+ strerror(errno));
+
+ exit(1);
+
+ }
+
+ /* Now, process the list of names ... */
+
+ fprintf(stdout, "Directory listing, size = %u\n", dirc);
+
+ while (dirc > 0) {
+
+ dsize = ((struct smbc_dirent *)dirp)->dirlen;
+ fprintf(stdout, "\nDir Ent, Type: %u, Name: %s, Comment: %s\n",
+ ((struct smbc_dirent *)dirp)->smbc_type,
+ ((struct smbc_dirent *)dirp)->name,
+ ((struct smbc_dirent *)dirp)->comment);
+
+ (char *)dirp += dsize;
+ (char *)dirc -= dsize;
+
+ }
+
exit(1);
}
diff --git a/examples/smb.conf.default b/examples/smb.conf.default
index 72925cdcb92..90737b37b51 100644
--- a/examples/smb.conf.default
+++ b/examples/smb.conf.default
@@ -3,158 +3,247 @@
# here. Samba has a huge number of configurable options (perhaps too
# many!) most of which are not shown in this example
#
-# Any line which starts with a ; (semi-colon) or a # (hash)
+# Any line which starts with a ; (semi-colon) or a # (hash)
# is a comment and is ignored. In this example we will use a #
# for commentry and a ; for parts of the config file that you
# may wish to enable
#
# NOTE: Whenever you modify this file you should run the command "testparm"
-# to check that you have not many any basic syntactic errors.
+# to check that you have not many any basic syntactic errors.
#
#======================= Global Settings =====================================
[global]
-# workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4
- workgroup = MYGROUP
-
-# server string is the equivalent of the NT Description field
- server string = Samba Server
-
-# This option is important for security. It allows you to restrict
-# connections to machines which are on your local network. The
-# following example restricts access to two C class networks and
-# the "loopback" interface. For more examples of the syntax see
-# the smb.conf man page
-; hosts allow = 192.168.1. 192.168.2. 127.
-
-# If you want to automatically load your printer list rather
-# than setting them up individually then you'll need this
- load printers = yes
-
-# you may wish to override the location of the printcap file
-; printcap name = /etc/printcap
-
-# on SystemV system setting printcap name to lpstat should allow
-# you to automatically obtain a printer list from the SystemV spool
-# system
-; printcap name = lpstat
-
-# It should not be necessary to specify the print system type unless
-# it is non-standard. Currently supported print systems include:
-# bsd, sysv, plp, lprng, aix, hpux, qnx
-; printing = bsd
-
-# Uncomment this if you want a guest account, you must add this to /etc/passwd
-# otherwise the user "nobody" is used
-; guest account = pcguest
-
-# this tells Samba to use a separate log file for each machine
-# that connects
- log file = /usr/local/samba/var/log.%m
-
-# Put a capping on the size of the log files (in Kb).
- max log size = 50
-
-# Security mode. Most people will want user level security. See
-# security_level.txt for details.
- security = user
-
-# Use password server option only with security = server
-# The argument list may include:
-# password server = My_PDC_Name [My_BDC_Name] [My_Next_BDC_Name]
-# or to auto-locate the domain controller/s
-# password server = *
-; password server = <NT-Server-Name>
-
-# Note: Do NOT use the now deprecated option of "domain controller"
-# This option is no longer implemented.
-
-# You may wish to use password encryption. Please read
-# ENCRYPTION.txt, Win95.txt and WinNT.txt in the Samba documentation.
-# Do not enable this option unless you have read those documents
-; encrypt passwords = yes
-
-# Using the following line enables you to customise your configuration
-# on a per machine basis. The %m gets replaced with the netbios name
-# of the machine that is connecting
-; include = /usr/local/samba/lib/smb.conf.%m
-
-# Most people will find that this option gives better performance.
-# See speed.txt and the manual pages for details
-# You may want to add the following on a Linux system:
-# SO_RCVBUF=8192 SO_SNDBUF=8192
- socket options = TCP_NODELAY
-
-# Configure Samba to use multiple interfaces
-# If you have multiple network interfaces then you must list them
-# here. See the man page for details.
-; interfaces = 192.168.12.2/24 192.168.13.2/24
-
-# Browser Control Options:
-# set local master to no if you don't want Samba to become a master
-# browser on your network. Otherwise the normal election rules apply
-; local master = no
-
-# OS Level determines the precedence of this server in master browser
-# elections. The default value should be reasonable
-; os level = 33
-
-# Domain Master specifies Samba to be the Domain Master Browser. This
-# allows Samba to collate browse lists between subnets. Don't use this
-# if you already have a Windows NT domain controller doing this job
-; domain master = yes
-
-# Preferred Master causes Samba to force a local browser election on startup
-# and gives it a slightly higher chance of winning the election
-; preferred master = yes
-
-# Enable this if you want Samba to be a domain logon server for
-# Windows95 workstations.
-; domain logons = yes
-
-# if you enable domain logons then you may want a per-machine or
-# per user logon script
-# run a specific logon batch file per workstation (machine)
-; logon script = %m.bat
-# run a specific logon batch file per username
-; logon script = %U.bat
-
-# Where to store roving profiles (only for Win95 and WinNT)
-# %L substitutes for this servers netbios name, %U is username
-# You must uncomment the [Profiles] share below
-; logon path = \\%L\Profiles\%U
-
-# Windows Internet Name Serving Support Section:
-# WINS Support - Tells the NMBD component of Samba to enable it's WINS Server
-; wins support = yes
-
-# WINS Server - Tells the NMBD components of Samba to be a WINS Client
-# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both
-; wins server = w.x.y.z
-
-# WINS Proxy - Tells Samba to answer name resolution queries on
-# behalf of a non WINS capable client, for this to work there must be
-# at least one WINS Server on the network. The default is NO.
-; wins proxy = yes
-
-# DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names
-# via DNS nslookups. The built-in default for versions 1.9.17 is yes,
-# this has been changed in version 1.9.18 to no.
- dns proxy = no
+##
+## Basic Server Settings
+##
+
+ # workgroup = NT-Domain-Name or Workgroup-Name, eg: REDHAT4
+ workgroup = MYGROUP
+
+ # server string is the equivalent of the NT Description field
+ server string = Samba Server
+
+ # This option is important for security. It allows you to restrict
+ # connections to machines which are on your local network. The
+ # following example restricts access to two C class networks and
+ # the "loopback" interface. For more examples of the syntax see
+ # the smb.conf man page
+ ; hosts allow = 192.168.1. 192.168.2.0./24 192.168.3.0/255.255.255.0 127.0.0.1
+
+ # Uncomment this if you want a guest account, you must add this to /etc/passwd
+ # otherwise the user "nobody" is used
+ ; guest account = pcguest
+
+ # this tells Samba to use a separate log file for each machine
+ # that connects
+ log file = /usr/local/samba/var/log.%m
+
+ # How much information do you want to see in the logs?
+ # default is only to log critical messages
+ ; log level = 1
+
+ # Put a capping on the size of the log files (in Kb).
+ max log size = 50
+
+ # Security mode. Most people will want user level security. See
+ # security_level.txt for details.
+ security = user
+
+ # Using the following line enables you to customise your configuration
+ # on a per machine basis. The %m gets replaced with the netbios name
+ # of the machine that is connecting.
+ # Note: Consider carefully the location in the configuration file of
+ # this line. The included file is read at that point.
+ ; include = /usr/local/samba/lib/smb.conf.%m
+
+ # Most people will find that this option gives better performance.
+ # See speed.txt and the manual pages for details
+ # You may want to add the following on a Linux system:
+ # SO_RCVBUF=8192 SO_SNDBUF=8192
+ ; socket options = TCP_NODELAY
+
+ # Configure Samba to use multiple interfaces
+ # If you have multiple network interfaces and want to limit smbd will
+ # use, list the ones desired here. Otherwise smbd & nmbd will bind to all
+ # active interfaces on the system. See the man page for details.
+ ; interfaces = 192.168.12.2/24 192.168.13.2/24
+
+ # Should smbd report that it has MS-DFS Capabilities? Only available
+ # if --with-msdfs was passed to ./configure
+ ; host msdfs = yes
+
+##
+## Network Browsing
+##
+ # set local master to no if you don't want Samba to become a master
+ # browser on your network. Otherwise the normal election rules apply
+ ; local master = no
+
+ # OS Level determines the precedence of this server in master browser
+ # elections. The default value (20) should be reasonable
+ ; os level = 20
+
+ # Domain Master specifies Samba to be the Domain Master Browser. This
+ # allows Samba to collate browse lists between subnets. Don't use this
+ # if you already have a Windows NT domain controller doing this job
+ ; domain master = yes
+
+ # Preferred Master causes Samba to force a local browser election on startup
+ # and gives it a slightly higher chance of winning the election
+ ; preferred master = yes
+
+
+##
+## WINS & Name Resolution
+##
+ # Windows Internet Name Serving Support Section:
+ # WINS Support - Tells the NMBD component of Samba to enable it's WINS Server
+ ; wins support = yes
+
+ # WINS Server - Tells the NMBD components of Samba to be a WINS Client
+ # Note: Samba can be either a WINS Server, or a WINS Client, but NOT both
+ ; wins server = w.x.y.z
+
+ # WINS Proxy - Tells Samba to answer name resolution queries on
+ # behalf of a non WINS capable client, for this to work there must be
+ # at least one WINS Server on the network. The default is NO.
+ ; wins proxy = yes
+
+ # DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names
+ # via DNS nslookups.
+ dns proxy = no
+
+
+##
+## Passwords & Authentication
+##
+ # Use password server option only with security = server
+ # The argument list may include:
+ # password server = My_PDC_Name [My_BDC_Name] [My_Next_BDC_Name]
+ # or to auto-locate the domain controller/s
+ ; password server = *
+ ; password server = <NT-Server-Name>
+
+ # You may wish to use password encryption. Please read
+ # ENCRYPTION.txt, Win95.txt and WinNT.txt in the Samba documentation.
+ # Do not enable this option unless you have read those documents
+ ; encrypt passwords = yes
+
+ # Should smbd obey the session and account lines in /etc/pam.d/samba ?
+ # only available if --with-pam was used at compile time
+ ; obey pam restrictions = yes
+
+ # When using encrypted passwords, Samba can synchronize the local
+ # UNIX password as well. You will also need the "passwd chat" parameters
+ ; unix passwword sync = yes
+
+ # how should smbd talk to the local system when changing a UNIX
+ # password? See smb.conf(5) for details
+ ; passwd chat = <custom chat string>
+
+ # This is only available if you compiled Samba to include --with-pam
+ # Use PAM for changing the password
+ ; pam password change = yes
+
+##
+## Domain Control
+##
+ # Enable this if you want Samba act as a domain controller.
+ # make sure you have read the Samba-PDC-HOWTO included in the documentation
+ # before enabling this parameter
+ ; domain logons = yes
+
+ # if you enable domain logons then you may want a per-machine or
+ # per user logon script
+ # run a specific logon batch file per workstation (machine)
+ ; logon script = %m.bat
+ # run a specific logon batch file per username
+ ; logon script = %U.bat
+
+ # Where to store roving profiles (only for Win95 and WinNT)
+ # %L substitutes for this servers netbios name, %U is username
+ # You must uncomment the [Profiles] share below
+ ; logon path = \\%L\Profiles\%U
+
+ # UNC path specifying the network location of the user's home directory
+ # only used when acting as a DC for WinNT/2k/XP. Ignored by Win9x clients
+ ; logon home = \\%L\%U
+
+ # What drive should the "logon home" be mounted at upon login ?
+ # only used when acting as a DC for WinNT/2k/XP. Ignored by Win9x clients
+ ; logon drive = H:
+
+##
+## Printing
+##
+
+ # If you want to automatically load your printer list rather
+ # than setting them up individually then you'll need this
+ load printers = yes
+
+ # you may wish to override the location of the printcap file
+ ; printcap name = /etc/printcap
+
+ # on SystemV system setting printcap name to lpstat should allow
+ # you to automatically obtain a printer list from the SystemV spool
+ # system
+ ; printcap name = lpstat
+
+ # It should not be necessary to specify the print system type unless
+ # it is non-standard. Currently supported print systems include:
+ # bsd, sysv, plp, lprng, aix, hpux, qnx
+ ; printing = bsd
+
+ # Enable this to make Samba 2.2 behavior just like Samba 2.0
+ # not recommended nuless you are sure of what you are doing
+ ; disable spoolss = yes
+
+ # list of users and groups which should be able to remotely manage
+ # printer drivers installed on the server
+ ; printer admin = root, +ntadmin
+
+
+##
+## Winbind
+##
+
+ # specify the uid range which can be used by winbindd
+ # to allocate uids for Windows users as necessary
+ ; winbind uid = 10000-65000
+
+ # specify the uid range which can be used by winbindd
+ # to allocate uids for Windows users as necessary
+ ; winbind gid = 10000-65000
+
+ # Define a home directory to be given to passwd(5) style entries
+ # generated by libnss_winbind.so. You can use variables here
+ ; winbind template homedir = /home/%D/%U
+
+ # Specify a shell for all winbind user entries return by the
+ # libnss_winbind.so library.
+ ; winbind template shell = /bin/sh
+
+ # What character should be used to separate the DOMAIN and Username
+ # for a Windows user. The default is DOMAIN\user, but many people
+ # prefer DOMAIN+user
+ ; winbind separator = +
+
#============================ Share Definitions ==============================
[homes]
- comment = Home Directories
- browseable = no
- writable = yes
+ comment = Home Directories
+ browseable = no
+ writable = yes
+ valid users = %S
# Un-comment the following and create the netlogon directory for Domain Logons
; [netlogon]
-; comment = Network Logon Service
-; path = /usr/local/samba/lib/netlogon
-; guest ok = yes
-; writable = no
-; share modes = no
+; comment = Network Logon Service
+; path = /usr/local/samba/lib/netlogon
+; guest ok = yes
+; writable = no
+; share modes = no
# Un-comment the following to provide a specific roving profile share
@@ -165,23 +254,30 @@
; guest ok = yes
-# NOTE: If you have a BSD-style print system there is no need to
+# NOTE: If you have a BSD-style print system there is no need to
# specifically define each individual printer
[printers]
comment = All Printers
path = /usr/spool/samba
browseable = no
-# Set public = yes to allow user 'guest account' to print
+ # Set public = yes to allow user 'guest account' to print
guest ok = no
writable = no
printable = yes
# This one is useful for people to share files
-;[tmp]
-; comment = Temporary file space
-; path = /tmp
-; read only = no
-; public = yes
+#[tmp]
+# comment = Temporary file space
+# path = /tmp
+# read only = no
+# public = yes
+
+
+# MS-DFS support is only available if Samba was compiled to
+# include --with-msdfs
+;[dfsroot]
+; dfs root = yes
+
# A publicly accessible directory, but read only, except for people in
# the "staff" group
@@ -193,64 +289,67 @@
; printable = no
; write list = @staff
-# Other examples.
-#
+
+##
+## Other examples.
+##
+
# A private printer, usable only by fred. Spool data will be placed in fred's
# home directory. Note that fred must have write access to the spool directory,
# wherever it is.
-;[fredsprn]
-; comment = Fred's Printer
-; valid users = fred
-; path = /homes/fred
-; printer = freds_printer
-; public = no
-; writable = no
-; printable = yes
+#[fredsprn]
+# comment = Fred's Printer
+# valid users = fred
+# path = /homes/fred
+# printer = freds_printer
+# public = no
+# writable = no
+# printable = yes
# A private directory, usable only by fred. Note that fred requires write
# access to the directory.
-;[fredsdir]
-; comment = Fred's Service
-; path = /usr/somewhere/private
-; valid users = fred
-; public = no
-; writable = yes
-; printable = no
+#[fredsdir]
+# comment = Fred's Service
+# path = /usr/somewhere/private
+# valid users = fred
+# public = no
+# writable = yes
+# printable = no
# a service which has a different directory for each machine that connects
# this allows you to tailor configurations to incoming machines. You could
# also use the %U option to tailor it by user name.
# The %m gets replaced with the machine name that is connecting.
-;[pchome]
-; comment = PC Directories
-; path = /usr/pc/%m
-; public = no
-; writable = yes
+#[pchome]
+# comment = PC Directories
+# path = /usr/pc/%m
+# public = no
+# writable = yes
# A publicly accessible directory, read/write to all users. Note that all files
# created in the directory by users will be owned by the default user, so
# any user with access can delete any other user's files. Obviously this
# directory must be writable by the default user. Another user could of course
# be specified, in which case all files would be owned by that user instead.
-;[public]
-; path = /usr/somewhere/else/public
-; public = yes
-; only guest = yes
-; writable = yes
-; printable = no
+#[public]
+# path = /usr/somewhere/else/public
+# public = yes
+# only guest = yes
+# writable = yes
+# printable = no
# The following two entries demonstrate how to share a directory so that two
# users can place files there that will be owned by the specific users. In this
# setup, the directory should be writable by both users and should have the
# sticky bit set on it to prevent abuse. Obviously this could be extended to
# as many users as required.
-;[myshare]
-; comment = Mary's and Fred's stuff
-; path = /usr/somewhere/shared
-; valid users = mary fred
-; public = no
-; writable = yes
-; printable = no
-; create mask = 0765
+#[myshare]
+# comment = Mary's and Fred's stuff
+# path = /usr/somewhere/shared
+# valid users = mary fred
+# public = no
+# writable = yes
+# printable = no
+# create mask = 0765