summaryrefslogtreecommitdiffstats
path: root/examples/logon
diff options
context:
space:
mode:
Diffstat (limited to 'examples/logon')
-rw-r--r--examples/logon/genlogon/genlogon.pl71
-rw-r--r--examples/logon/mklogon/mklogon.conf78
-rw-r--r--examples/logon/mklogon/mklogon.pl392
-rw-r--r--examples/logon/ntlogon/README160
-rw-r--r--examples/logon/ntlogon/ntlogon.conf44
-rwxr-xr-xexamples/logon/ntlogon/ntlogon.py375
6 files changed, 1120 insertions, 0 deletions
diff --git a/examples/logon/genlogon/genlogon.pl b/examples/logon/genlogon/genlogon.pl
new file mode 100644
index 0000000..4799ac8
--- /dev/null
+++ b/examples/logon/genlogon/genlogon.pl
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+#
+# genlogon.pl
+#
+# Perl script to generate user logon scripts on the fly, when users
+# connect from a Windows client. This script should be called from smb.conf
+# with the %U, %G and %L parameters. I.e:
+#
+# root preexec = genlogon.pl %U %G %L
+#
+# The script generated will perform
+# the following:
+#
+# 1. Log the user connection to /var/log/samba/netlogon.log
+# 2. Set the PC's time to the Linux server time (which is maintained
+# daily to the National Institute of Standard's Atomic clock on the
+# internet.
+# 3. Connect the user's home drive to H: (H for Home).
+# 4. Connect common drives that everyone uses.
+# 5. Connect group-specific drives for certain user groups.
+# 6. Connect user-specific drives for certain users.
+# 7. Connect network printers.
+
+# Log client connection
+#($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
+($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
+open LOG, ">>/var/log/samba/netlogon.log";
+print LOG "$mon/$mday/$year $hour:$min:$sec - User $ARGV[0] logged into $ARGV[1]\n";
+close LOG;
+
+# Start generating logon script
+open LOGON, ">/shared/netlogon/$ARGV[0].bat";
+print LOGON "\@ECHO OFF\r\n";
+
+# Connect shares just use by Software Development group
+if ($ARGV[1] eq "SOFTDEV" || $ARGV[0] eq "softdev")
+{
+ print LOGON "NET USE M: \\\\$ARGV[2]\\SOURCE\r\n";
+}
+
+# Connect shares just use by Technical Support staff
+if ($ARGV[1] eq "SUPPORT" || $ARGV[0] eq "support")
+{
+ print LOGON "NET USE S: \\\\$ARGV[2]\\SUPPORT\r\n";
+}
+
+# Connect shares just used by Administration staff
+if ($ARGV[1] eq "ADMIN" || $ARGV[0] eq "admin")
+{
+ print LOGON "NET USE L: \\\\$ARGV[2]\\ADMIN\r\n";
+ print LOGON "NET USE K: \\\\$ARGV[2]\\MKTING\r\n";
+}
+
+# Now connect Printers. We handle just two or three users a little
+# differently, because they are the exceptions that have desktop
+# printers on LPT1: - all other user's go to the LaserJet on the
+# server.
+if ($ARGV[0] eq 'jim'
+ || $ARGV[0] eq 'yvonne')
+{
+ print LOGON "NET UsE LPT2: \\\\$ARGV[2]\\LJET3\r\n";
+ print LOGON "NET USE LPT3: \\\\$ARGV[2]\\FAXQ\r\n";
+}
+else
+{
+ print LOGON "NET USE LPT1: \\\\$ARGV[2]\\LJET3\r\n";
+ print LOGON "NET USE LPT3: \\\\$ARGV[2]\\FAXQ\r\n";
+}
+
+# All done! Close the output file.
+close LOGON;
diff --git a/examples/logon/mklogon/mklogon.conf b/examples/logon/mklogon/mklogon.conf
new file mode 100644
index 0000000..9e585c5
--- /dev/null
+++ b/examples/logon/mklogon/mklogon.conf
@@ -0,0 +1,78 @@
+# Mapping should be kept in the form
+# username(USER) or groupname(WEBUSERS) = driveletter (W:), samba share name (WEB)
+# ie. user = W:,WEB or webusers = W:,WEB
+# Problem found when testing, if there is a duplicate entry only the last one is used,
+# not the first or both, another problem is that when testing I found a bug in Config::Simple, if you have a tab
+# infront of your # on a comment it breaks ...
+# logging = yes # Should Logging be enabled (YES,ON,1 or NO,OFF,0)(if not specified defaults to no)
+# logdir = "/root/perl" # What is the base directory the logs should be stored.
+# logfile = "userlist.txt" # What should the file be named.
+# VERY IMPORTANT anything that has a "\" (backslash) in it ex. "C:\" MUST be changed to a double "\\" for
+# it to be used in the script. ex. "C:\\"
+
+[global]
+logging = yes
+logdir = "/home/samba/netlogon"
+logfile = "UserLogs.txt"
+mkprofile = 1
+timesync = yes
+sambaconf = "/etc/samba/smb.conf"
+logtype = file
+
+# Change and uncomment the below value to force the servername, some clients occasionally
+# have trouble picking up the right servername so it may need to be set. It CANNOT be left blank AND uncommented.
+servername = "TIGER"
+
+[common]
+public = P:, public
+home = H:, /home
+
+[groupmap]
+adm = R:, NETLOGON, Y:, ARCHIVES
+teachers = S:, RECORDS, X:, SIS
+plato = T:, PLATO
+webpage = W:, WEB
+hsoffice = N:, HSOFFICE, Q:, COMMON, X:, SIS
+suoffice = N:, super, Q:, COMMON, X:, SIS
+emoffice = N:, emOFFICE, Q:, COMMON, X:, SIS
+tech = O:, utils
+yearbook = Y:, yearbook
+
+[usermap]
+rnance = G:, GHOST, I:, TTL, Y:, ARCHIVES, R:, NETLOGON, X:, SIS
+lwatts = G:, GHOST, I:, TTL, Y:, ARCHIVES, R:, NETLOGON, X:, SIS
+droot = U:, stuhomes
+2007mbk = Y:, yearbook
+2008mll = Y:, yearbook
+2008jtj = Y:, yearbook
+2007tja = Y:, yearbook
+2007hms = Y:, yearbook
+2006dpv = Y:, yearbook
+2006jwb2 = Y:, yearbook
+2007npd = Y:, yearbook
+astewart = Y:, yearbook
+
+
+
+# Here is where things get confusing, you can assign a computer, or make a group of computers.
+# The same context will go for ip address's as well, however you can also specify ip ranges,
+# but I have not yet figured out how to do multiple ranges.
+# Use the following examples for help.
+# To define a single computer to do commands
+# mymachinename = command1, command2
+# To define a group of computers to do commands
+# mymachinegroup = machinename1, machinename2
+# [performcommands]
+# mymachinegroup = command1,command2
+# iprangegroup1 = 10.1.2.1 - 10.1.3.1
+
+
+
+[machines]
+
+[ip]
+sixthemints = 10.1.5.201 - 10.1.5.215
+
+[performcommands]
+common = "XCOPY P:\\TYPEN32.INI C:\\WINDOWS\\ /Y \>NUL", "XCOPY P:\\ARPROGRAMS\\DBLOCATION\\\*\.\* C:\\WINDOWS\\ /Y \>NUL", "XCOPY P:\\EMACTIVITIES\\EMGAMESPREFS.INI C:\\WINDOWS\\ /Y \>NUL", "PATH\=\%PATH\%;p:\\PXPerl\parrot\\bin;p:\\PXPerl\\bin"
+sixthemints = "start \\\\10.1.5.20\\printer"
diff --git a/examples/logon/mklogon/mklogon.pl b/examples/logon/mklogon/mklogon.pl
new file mode 100644
index 0000000..870abd1
--- /dev/null
+++ b/examples/logon/mklogon/mklogon.pl
@@ -0,0 +1,392 @@
+#!/usr/bin/perl -w
+
+# 05/01/2005 - 18:07:10
+#
+# mklogon.pl - Login Script Generator
+# Copyright (C) 2005 Ricky Nance
+# ricky.nance@gmail.com
+# http://www.weaubleau.k12.mo.us/~rnance/samba/mklogon.txt
+#
+# 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 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, see <http://www.gnu.org/licenses/>.
+#
+
+# Version: 1.0 (Stable)
+# Revised: 07/28/2005
+
+# Comments...
+# Working on logging to the system logs, Logs user activity, but not errors yet.
+
+use strict;
+use Getopt::Long;
+
+eval { require Config::Simple; };
+if ($@) {
+ print("\n");
+ print( "It appears as though you don't have the Config Simple perl module installed.\n" );
+ print("The package is typically called 'Config::Simple' \n");
+ print("and it needs to be installed, before you can use this utility\n");
+ print("Most PERL installations will allow you to use a command like\n");
+ print("\ncpan -i Config::Simple\n");
+ print("from the command line while logged in as the root user.\n");
+ print("\n");
+ exit(1);
+}
+
+# use Data::Dumper; #Used for debugging purposes
+
+# This variable should point to the external conf file, personally I would set
+# it to /etc/samba/mklogon.conf
+my $configfile;
+
+foreach my $dir ( ( '/etc', '/etc/samba', '/usr/local/samba/lib' ) ) {
+ if ( -e "$dir/mklogon.conf" ) {
+ $configfile = "$dir/mklogon.conf";
+ last;
+ }
+}
+
+# This section will come directly from the samba server. Basically it just makes the script easier to read.
+my $getopts = GetOptions(
+ 'u|username=s' => \my $user,
+ 'm|machine=s' => \my $machine,
+ 's|servername=s' => \my $server,
+ 'o|ostype=s' => \my $os,
+ 'i|ip=s' => \my $ip,
+ 'd|date=s' => \my $smbdate,
+ 'h|help|?' => \my $help
+);
+
+if ($help) {
+ help();
+ exit(0);
+}
+
+# We want the program to error out if its missing an argument.
+if ( !defined($user) ) { error("username"); }
+if ( !defined($machine) ) { error("machine name") }
+if ( !defined($server) ) { error("server name") }
+if ( !defined($os) ) { error("operating system") }
+if ( !defined($ip) ) { error("ip address") }
+if ( !defined($smbdate) ) { error("date") }
+
+# This section will be read from the external config file
+my $cfg = new Config::Simple($configfile) or die "Could not find $configfile";
+
+# Read this part from the samba config
+my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime(time);
+my $sambaconf = $cfg->param("global.sambaconf") or die "Couldn't find your samba config! \n";
+my $smbcfg = new Config::Simple( filename => $sambaconf, syntax => "ini" );
+my $smbprof = $smbcfg->param("profiles.path");
+my $smbnetlogdir = $smbcfg->param("netlogon.path");
+my $logging = lc( $cfg->param("global.logging") );
+my $mkprofile = lc( $cfg->param("global.mkprofile") );
+my $logdir = $cfg->param("global.logdir");
+my $logfile = $cfg->param("global.logfile");
+my $logs = "$logdir\/$logfile";
+my $logtype = $cfg->param("global.logtype");
+my $usermap = "usermap.$user";
+my $osmap = "os.$os";
+my @ostype = $cfg->param($osmap);
+my @username = $cfg->param($usermap);
+my $compname = $cfg->param( -block => "machines" );
+my $ipname = $cfg->param( -block => "ip" );
+my $timesync = $cfg->param("global.timesync");
+my $altserver = $cfg->param("global.servername");
+if ( defined($altserver) ) { $server = $altserver; }
+$server = uc($server);
+
+# Lets start logging stuff if it is turned on in the config
+if ( $logging =~ m/on|yes|1/i ) {
+ if ($logtype =~ m/file/i) {
+ print "----- Logging is turned on in the config. -----\n";
+ print "----- Location of the logfile is \"$logs\" -----\n";
+ open LOG, ">>$logs";
+ printf LOG "Date: $smbdate Time: ";
+ printf LOG '%02d', $hour;
+ print LOG ":";
+ printf LOG '%02d', $min;
+ print LOG ".";
+ printf LOG '%02d', $sec;
+ print LOG " -- User: $user - Machine: $machine - IP: $ip -- \n";
+ close(LOG);
+ } elsif ($logtype =~ m/syslog|system/i){
+ use Sys::Syslog;
+ my $alert = "User: $user Logged into $machine ($ip) at $hour:$min.$sec on $smbdate.";
+ openlog($0, 'cons', 'user');
+ syslog('alert', $alert);
+ closelog();
+
+ }
+} else {
+ print "----- Logging is turned off in the config. -----\n";
+}
+
+# If the user wants to make profiles with this script lets go
+if ( defined($smbprof) ) {
+ if ( $mkprofile =~ m/on|yes|1/i ) {
+ print "----- Automatic making of user profiles is turned on in the config. ----- \n";
+ ( my $login, my $pass, my $uid, my $gid ) = getpwnam($user)
+ or die "$user not in passwd file \n";
+ $smbprof =~ s/\%U/$user/g;
+ my $dir2 = "$smbprof\/$user";
+ print "$smbprof \n";
+ print "$dir2 \n";
+ if ( !-e $dir2 ) {
+ print "Creating " . $user . "'s profile with a uid of $uid\n";
+ mkdir $smbprof;
+ mkdir $dir2;
+ chomp($user);
+# chown $uid, $gid, $smbprof;
+ chown $uid, $gid, $dir2;
+ } else {
+ print $user . "'s profile already exists \n";
+ }
+ } else {
+ print "----- Automatic making of user profiles is turned off in the config. ----- \n";
+ }
+}
+
+# Lets start making the batch files.
+open LOGON, ">$smbnetlogdir\/$user.bat" or die "Unable to create userfile $smbnetlogdir\/$user.bat";
+print LOGON "\@ECHO OFF \r\n";
+
+if ( $timesync =~ m/on|yes|1/i ) {
+ print LOGON "NET TIME /SET /YES \\\\$server \r\n";
+} else {
+ print "----- Time syncing to the client is turned off in the config. -----\n";
+}
+
+# Mapping from the common section
+my $common = $cfg->param( -block => "common" );
+for my $key ( keys %$common ) {
+ drive_map( @{ $common->{$key} } );
+}
+
+my @perform_common = $cfg->param("performcommands.common");
+if ( defined( $perform_common[0] ) ) {
+ foreach (@perform_common) {
+ print LOGON "$_ \r\n";
+ }
+}
+
+# Map shares on a per user basis.
+drive_map(@username);
+
+# Map shares based on the Operating System.
+drive_map(@ostype);
+
+# Map shares only if they are in a group
+# This line checks against the unix "groups" command, to see the secondary groups of a user.
+my @usergroups = split( /\s/, do { open my $groups, "-|", groups => $user; <$groups> } );
+foreach (@usergroups) {
+ my $groupmap = "groupmap.$_";
+ my @groupname = $cfg->param($groupmap);
+ drive_map(@groupname);
+}
+
+#Here is where we check the machine name against the config...
+for my $key ( keys %$compname ) {
+ my $test = $compname->{$key};
+ if ( ref $test eq 'ARRAY' ) {
+ foreach (@$test) {
+ if ( $_ eq $machine ) {
+ my $performit = $cfg->param("performcommands.$key");
+ if ( defined($performit) ) {
+ if ( ref $performit ) {
+ foreach (@$performit) { print LOGON "$_ \r\n"; }
+ } else {
+ print LOGON "$performit \r\n";
+ }
+ }
+ }
+ }
+ }
+ elsif ( $test eq $machine ) {
+ my $performit = $cfg->param("performcommands.$key");
+ if ( defined($performit) ) {
+ if ( ref $performit ) {
+ foreach (@$performit) { print LOGON "$_ \r\n"; }
+ } else {
+ print LOGON "$performit \r\n";
+ }
+ }
+ }
+}
+
+# Here is where we test the ip address against the client to see if they have "Special Mapping"
+# A huge portion of the ip matching code was made by
+# Carsten Schaub (rcsu in the #samba chan on freenode.net)
+
+my $val;
+for my $key ( sort keys %$ipname ) {
+ if ( ref $ipname->{$key} eq 'ARRAY' ) {
+ foreach ( @{ $ipname->{$key} } ) {
+ getipval( $_, $key );
+ }
+ } else {
+ getipval( $ipname->{$key}, $key );
+ }
+}
+
+sub getipval {
+ my ( $range, $rangename ) = @_;
+ if ( parse( $ip, ipmap($range) ) ) {
+ if ( $val eq 'true' ) {
+ my $performit = $cfg->param("performcommands.$rangename");
+ if ( defined($performit) ) {
+ if ( ref $performit ) {
+ foreach (@$performit) { print LOGON "$_ \r\n"; }
+ } else {
+ print LOGON "$performit \r\n";
+ }
+ }
+ } elsif ( $val eq 'false' ) {
+ }
+ } else {
+ }
+}
+
+sub ipmap {
+ my $pattern = shift;
+ my ( $iprange, $iprange2, $ipmask );
+ if ( $pattern =~ m/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/ ) {
+ # 1.1.1.1/3 notation
+ $iprange = pack( "U4", $1, $2, $3, $4 );
+ $ipmask = pack( "U4", 0, 0, 0, 0 );
+ my $numbits = $5;
+ for ( my $i = 0 ; $i < $numbits ; $i++ ) {
+ vec( $ipmask, int( $i / 8 ) * 8 + ( 8 - ( $i % 8 ) ) - 1, 1 ) = 1;
+ }
+ $iprange &= "$ipmask";
+ } elsif ( $pattern =~ m/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/ ) {
+ # 1.1.1.1/255.255.255.255 notation
+ $iprange = pack( "U4", $1, $2, $3, $4 );
+ $ipmask = pack( "U4", $5, $6, $7, $8 );
+ $iprange &= "$ipmask";
+ } elsif ( $pattern =~ m/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ ) {
+ # 1.1.1.1 notation
+ $iprange = pack( "U4", $1, $2, $3, $4 );
+ $ipmask = pack( "U4", 255, 255, 255, 255 );
+ } elsif ( $pattern =~ m/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\s*\-\s*(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ ) {
+ # 1.1.1.1 - 2.2.2.2 notation
+ $iprange = pack( "U4", $1, $2, $3, $4 );
+ $iprange2 = pack( "U4", $5, $6, $7, $8 );
+ $ipmask = pack( "U4", 255, 255, 255, 255 );
+ } else {
+ return;
+ }
+ return $iprange, $ipmask, $iprange2;
+}
+
+sub parse {
+ my ( $origip, $ipbase, $ipmask, $iprange2 ) = @_;
+ $origip =~ m/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
+ $origip = pack( "U4", $1, $2, $3, $4 );
+ if ( defined($iprange2) ) {
+ if ( $ipbase le $origip && $origip le $iprange2 ) {
+ return $val = 'true';
+ } else {
+ return $val = 'false';
+ }
+ } elsif ( ( "$origip" & "$ipmask" ) eq $ipbase ) {
+ return $val = 'true';
+ } else {
+ return $val = 'false';
+ }
+}
+
+# This sub will distinguish the drive mappings
+sub drive_map {
+ my @data = @_;
+ for ( my $i = 0 ; $i < scalar(@data) ; ) {
+ if ( $data[$i] =~ m/^[a-z]\:$/i ) {
+ my $driveletter = $data[$i];
+ $i++;
+ my $sharename = $data[$i];
+ $i++;
+ if ( $sharename eq '/home' ) {
+ print LOGON uc("NET USE $driveletter \\\\$server\\$user \/Y \r\n");
+ } else {
+ print LOGON
+ uc("NET USE $driveletter \\\\$server\\$sharename \/Y \r\n");
+ }
+ } else {
+ print LOGON uc("$data[$i] \r\n");
+ $i++;
+ }
+ }
+}
+
+close(LOGON);
+
+sub error {
+ my $var = shift(@_);
+ help();
+ print "\n\tCritical!!! \n\n\tNo $var specified\n\n\tYou must specify a $var.\n\n";
+ exit(0);
+}
+
+sub help {
+
+ print << "EOF" ;
+
+ Usage: $0 [options]
+
+ Options:
+
+ -h,--help This help screen.
+
+ -u,--username The name of the user from the samba server.
+
+ -m,--machinename The name of the client connecting to the server.
+
+ -s,--server The name of the server this script is running in.
+
+ -o,--os The clients OS -- Windows 95/98/ME (Win95), Windows NT (WinNT),
+ Windows 2000 (Win2K), Windows XP (WinXP), and Windows 2003
+ (Win2K3). Anything else will be known as ``UNKNOWN''
+ That snippet is directly from man smb.conf.
+
+ -i,--ip The clients IP address.
+
+ -d,--date Time and Date returned from the samba server.
+
+
+
+ --IMPORTANT--
+
+
+ All options MUST be specified.
+
+ The mklogon.conf file MUST be located in /etc, /etc/samba, or
+ /usr/local/samba/lib.
+
+ To use this file from the command line:
+ $0 -u User -m machine -s servername -o ostype -i X.X.X.X -d MM/DD/YY
+
+ To use this file from the samba server add these lines to your /etc/samba/smb.conf:
+
+
+ This line goes in the [global] section
+ login script = %U.bat
+
+ This line should be at the end of the [netlogon] section.
+ root preexec = /path/to/mklogon.pl -u %U -m %m -s %L -o %a -i %I -d %t
+
+
+EOF
+
+ print "\n\n";
+
+}
diff --git a/examples/logon/ntlogon/README b/examples/logon/ntlogon/README
new file mode 100644
index 0000000..da52562
--- /dev/null
+++ b/examples/logon/ntlogon/README
@@ -0,0 +1,160 @@
+ntlogon.py v0.8b Copyright 2002 by Timothy (rhacer) Grant
+This programme is released under the terms of the GNU Public License
+This programme has NO WARRANTY of any kind, use at your own risk.
+
+===================
+CHANGES SINCE v0.7b
+===================
+included patch that made machine name %m a macro substitution value.
+Thanks to: Nick Lopez <kimo_sabe@atdot.org>
+
+==================
+CHANGES SINCE v0.6
+==================
+PLEASE NOT THAT I AM CONSIDERING THIS A BETA UNTIL I GET SOME FEEDBACK
+FROM USERS ON WHETHER THE MACRO FEATURE WORKS FOR THEM.
+
+added the ability to define substitution macros: see the usage section
+
+removed the large docstring from the file and moved the information to
+the USAGE section of this file
+
+cleaned up the code and made more flexible
+
+improved the code comments
+
+==================
+CHANGES SINCE v0.5
+==================
+added a -v --version switch
+
+added a --pause switch which will put a pause statement between each
+non-blank line of the script.
+
+===============
+A PERSONAL NOTE
+===============
+When I originally posted v0.5 on Freshmeat, I really expected *some*
+feedback. To date this little script has been downloaded over 700 times, but
+absolutely nobody has sent me an e-mail to tell me if it is useful, or if
+it is absolutely the stupidest waste of bandwidth they have ever seen.
+I'd really love to know if even one person other than me and the other techs
+here at Avalon have found it useful.
+
+Thanks.
+ rhacer (rhacer@craigelachie.org)
+
+September 27, 2000
+Thanks to those that did respond to my plea! I'd still love to hear from
+any other users!
+
+============
+INTRODUCTION
+============
+As my experience with Linux and Samba increased, I had no trouble whipping up
+a custom Perl, Python or Bash script to create Samba Logon Scripts, but I
+noticed that I changed things from place to place, and that my users had *no*
+chance of ever figuring out how to modify those scripts themselves.
+
+In an attempt to create a company wide standard that both my co-workers and my
+customers could *easily* modify I hit upon the scheme I used here.
+
+I settled on an INI file feel, because most who have experience with Win boxes
+have some concept of INI files.
+
+============
+INSTALLATION
+============
+The distribution archive contains three files:
+
+README This file
+ntlogon.py The actual Python script (place in /usr/local/samba/bin)
+ntlogon.conf A sample configuration file (place in /etc)
+
+This script was created using Python v1.5.2, and I believe it uses only
+standard libraries.
+
+Your smb.conf file needs to contain a netlogon section similar to the
+following (These settings *are not* normal on a RH box. These settings
+are all based on the excellent book that I learned Samba from: Samba
+Integrating Unix and Windows by John D. Blair. It is somewhat out of
+date now, but that's the history of the strange file locations):
+
+[netlogon]
+ path = /usr/local/samba/netlogon
+ writeable = no
+ guest ok = no
+ root preexec = /usr/local/samba/bin/ntlogon --user=%U --os=%m
+ root postexec = rm /usr/local/samba/netlogon/%U.bat
+
+======
+USAGE
+======
+PLEASE SEE NTLOGON.CONF FOR A DETAILED CONFIGURATION EXAMPLE
+
+This programme will build a Windows NT logon script for users connecting
+to a Samba server. Samba macros that are currently understood:
+
+ %U user name
+ %G group name
+ %a machine architecture
+ %m machine netbios name
+
+This programme reads a configuration that looks strikingly similar to both
+the Samba configuration file, and a DOS "boot menu" AUTOEXEC.BAT file.
+
+The default file name is /etc/ntlogon.conf (though I really think it ought
+to be called ntlogon.batch!) You may change the filename by using the -f
+or --templatefile startup option.
+
+The default netlogon directory is /usr/local/samba/netlogon though this
+can be changed with the -d or --dir startup option.
+
+The default batch file name generated is username.bat if no username is
+specified the default value is logon.bat (e.g., if --user=fred is specified
+on the command line then the logon script generated will be stored in
+fred.bat)
+
+Use the --debug option to print the logon script to screen instead of the
+output file
+
+Use the --pause option to place a pause statement between each line of the
+script to assist in debugging a logon script.
+
+The file is divided into sections that have headers in square brackets
+
+[Global]
+[User-username]
+[Group-groupname]
+[OS-osname]
+
+The file may also contain user defined substitution macros. They are
+defined by placing the macro name on the left side of an equal sign,
+and the substitution text on the right side of the equal sign. They
+are also case sensitive:
+
+MAINDRIVE = G:
+USERDRIVE = U:
+SERVERNAME = myservername
+
+They are referenced by prepending a "%" sign to the variable name:
+
+NET USE %MAINDRIVE \\\\servername\\mainshare /YES
+NET USE %USERDRIVE \\\\%SERVERNAME\\usershare /YES
+
+==============
+SPECIAL THANKS
+==============
+Nick Lopez <kimo_sabe@atdot.org> for the net bios name patch.
+
+===================
+CONTACT INFORMATION
+===================
+Author : Timothy (rhacer) Grant
+
+I can be reached at tjg@craigelachie.org
+ntlogon website www.craigelachie.org/rhacer/ntlogon
+
+Please feel free to contact me with any suggestions, improvements, bugs you
+might find.
+
diff --git a/examples/logon/ntlogon/ntlogon.conf b/examples/logon/ntlogon/ntlogon.conf
new file mode 100644
index 0000000..e1573a6
--- /dev/null
+++ b/examples/logon/ntlogon/ntlogon.conf
@@ -0,0 +1,44 @@
+# Everything in the Global section applies to all users logging on to the
+# network
+[Global]
+
+#Some substitution macro definitions
+MAINDRIVE = G:
+USERDRIVE = U:
+SERVERNAME = myservername
+
+@ECHO "Welcome to our network!!!"
+NET TIME \\servername /SET /YES
+NET USE %MAINDRIVE \\%SERVERNAME\globalshare /YES
+
+# Map the private user area in the global section so we don't have to
+# create individual user entries for each user!
+NET USE %USERDRIVE \\servername\%U /YES
+
+# Group entries, User entries and OS entries each start with the
+# keyword followed by a dash followed by--appropriately enough the Group
+# name, the User name, or the OS name.
+[Group-admin]
+@ECHO "Welcome administrators!"
+NET USE G: \\servername\adminshare1 /YES
+NET USE I: \\servername\adminshare2 /YES
+
+[Group-peons]
+@ECHO "Be grateful we let you use computers!"
+NET USE G: \\servername\peonshare1 /YES
+
+[Group-hackers]
+@ECHO "What can I do for you today great one?"
+NET USE G: \\servername\hackershare1 /YES
+NET USE I: \\servername\adminshare2 /YES
+
+[User-fred]
+@ECHO "Hello there Fred!"
+NET USE F: \\servername\fredsspecialshare /YES
+
+[OS-WfWg]
+@ECHO "Time to upgrade isn't it?"
+
+# End configuration file
+
+X = Will this break?
diff --git a/examples/logon/ntlogon/ntlogon.py b/examples/logon/ntlogon/ntlogon.py
new file mode 100755
index 0000000..7213012
--- /dev/null
+++ b/examples/logon/ntlogon/ntlogon.py
@@ -0,0 +1,375 @@
+#!/usr/bin/env python3
+"""
+ntlogon.py written by Timothy (rhacer) Grant
+
+Copyright 1999 - 2002 by Timothy Grant
+
+is distributed under the terms of the GNU Public License.
+
+The format for the configuration file is as follows:
+
+While there is some room for confusion, we attempt to process things in
+order of specificity: Global first, Group second, User third, OS Type
+forth. This order can be debated forever, but it seems to make the most
+sense.
+
+# Everything in the Global section applies to all users logging on to the
+# network
+[Global]
+@ECHO "Welcome to our network!!!"
+NET TIME \\\\servername /SET /YES
+NET USE F: \\\\servername\\globalshare /YES
+
+# Map the private user area in the global section so we don't have to
+# create individual user entries for each user!
+NET USE U: \\\\servername\\%U /YES
+
+# Group entries, User entries and OS entries each start with the
+# keyword followed by a dash followed by--appropriately enough the Group
+# name, the User name, or the OS name.
+[Group-admin]
+@ECHO "Welcome administrators!"
+NET USE G: \\\\servername\\adminshare1 /YES
+NET USE I: \\\\servername\\adminshare2 /YES
+
+[Group-peons]
+@ECHO "Be grateful we let you use computers!"
+NET USE G: \\\\servername\\peonshare1 /YES
+
+[Group-hackers]
+@ECHO "What can I do for you today great one?"
+NET USE G: \\\\servername\\hackershare1 /YES
+NET USE I: \\\\servername\\adminshare2 /YES
+
+[User-fred]
+@ECHO "Hello there Fred!"
+NET USE F: \\\\servername\\fredsspecialshare /YES
+
+[OS-WfWg]
+@ECHO "Time to upgrade it?"
+
+# End configuration file
+
+usage: ntlogon [-g | --group=groupname]
+ [-u | --user=username]
+ [-o | --os=osname]
+ [-m | --machine=netbiosname]
+ [-f | --templatefile=filename]
+ [-d | --dir=netlogon directory]
+ [-v | --version]
+ [-h | --help]
+ [--pause]
+ [--debug]
+"""
+#
+#" This quote mark is an artifact of the inability of my editor to
+# correctly colour code anything after the triple-quoted docstring.
+# if your editor does not have this flaw, feel free to remove it.
+
+
+import sys
+import getopt
+import re
+import string
+import os
+
+version = "ntlogon.py v0.8"
+
+def buildScript(buf, sections, group, user, ostype, machine, debug, pause):
+ """
+ buildScript() Takes the contents of the template file and builds
+ a DOS batch file to be executed as an NT logon script. It does this
+ by determining which sections of the configuration file should be included
+ and creating a list object that contains each line contained in each
+ included section. The list object is then returned to the calling
+ routine.
+
+ All comments (#) are removed. A REM is inserted to show
+ which section of the configuration file each line comes from.
+ We leave blanklines as they are sometimes useful for debugging
+
+ We also replace all of the Samba macros (e.g., %U, %G, %a, %m) with their
+ expanded versions which have been passed to us by smbd
+ """
+ hdrstring = ''
+ script = []
+
+ #
+ # These are the Samba macros that we currently know about.
+ # any user defined macros will also be added to this dictionary.
+ # We do not store the % sign as part of the macro name.
+ # The replace routine will prepend the % sign to all possible
+ # replacements.
+ #
+ macros = {
+ 'U': user,
+ 'G': group,
+ 'a': ostype,
+ 'm': machine
+ }
+
+ #
+ # Process each section defined in the list sections
+ #
+ for s in sections:
+ # print 'searching for: ' + s
+
+ idx = 0
+
+ while idx < len(buf):
+ ln = buf[idx]
+
+ #
+ # We need to set up a regex for each possible section we
+ # know about. This is slightly complicated due to the fact
+ # that section headers contain user defined text.
+ #
+ if s == 'Global':
+ hdrstring = r'\[ *' + s + r' *\]'
+ elif s == 'Group':
+ hdrstring = r'\[ *' + s + ' *- *' + group + r' *\]'
+ elif s == 'User':
+ hdrstring = r'\[ *' + s + ' *- *' + user + r' *\]'
+ elif s == 'OS':
+ hdrstring = r'\[ *' + s + ' *- *' + ostype + r' *\]'
+ elif s == 'Machine':
+ hdrstring = r'\[ *' + s + ' *- *' + machine + r' *\]'
+
+ #
+ # See if we have found a section header
+ #
+ if re.search(r'(?i)' + hdrstring, ln):
+ idx = idx + 1 # increment the counter to move to the next
+ # line.
+
+ x = re.match(r'([^#\r\n]*)', ln) # Determine the section
+ # name and strip out CR/LF
+ # and comment information
+
+ if debug:
+ print 'rem ' + x.group(1) + ' commands'
+ else:
+ # create the rem at the beginning of each section of the
+ # logon script.
+ script.append('rem ' + x.group(1) + ' commands')
+
+ #
+ # process each line until we have found another section
+ # header
+ #
+ while not re.search(r'.*\[.*\].*', buf[idx]):
+
+ #
+ # strip comments and line endings
+ #
+ x = re.match(r'([^#\r\n]*)', buf[idx])
+
+ if string.strip(x.group(1)) != '' :
+ # if there is still content after stripping comments and
+ # line endings then this is a line to process
+
+ line = x.group(1)
+
+ #
+ # Check to see if this is a macro definition line
+ #
+ vardef = re.match(r'(.*)=(.*)', line)
+
+ if vardef:
+ varname = string.strip(vardef.group(1)) # Strip leading and
+ varsub = string.strip(vardef.group(2)) # and trailing spaces
+
+ if varname == '':
+ print "Error: No substitution name specified line: %d" % idx
+ sys.exit(1)
+
+ if varsub == '':
+ print "Error: No substitution text provided line: %d" % idx
+ sys.exit(1)
+
+ if varname in macros:
+ print "Warning: macro %s redefined line: %d" % (varname, idx)
+
+ macros[varname] = varsub
+ idx = idx + 1
+ continue
+
+ #
+ # Replace all the macros that we currently
+ # know about.
+ #
+ # Iterate over the dictionary that contains all known
+ # macro substitutions.
+ #
+ # We test for a macro name by prepending % to each dictionary
+ # key.
+ #
+ for varname in macros.keys():
+ line = re.sub(r'%' + varname + r'(\W)',
+ macros[varname] + r'\1', line)
+
+ if debug:
+ print line
+ if pause:
+ print 'pause'
+ else:
+ script.append(line)
+
+ idx = idx + 1
+
+ if idx == len(buf):
+ break # if we have reached the end of the file
+ # stop processing.
+
+ idx = idx + 1 # increment the line counter
+
+ if debug:
+ print ''
+ else:
+ script.append('')
+
+ return script
+
+# End buildScript()
+
+def run():
+ """
+ run() everything starts here. The main routine reads the command line
+ arguments, opens and reads the configuration file.
+ """
+ configfile = '/etc/ntlogon.conf' # Default configuration file
+ group = '' # Default group
+ user = '' # Default user
+ ostype = '' # Default os
+ machine = '' # Default machine type
+ outfile = 'logon.bat' # Default batch file name
+ # this file name WILL take on the form
+ # username.bat if a username is specified
+ debug = 0 # Default debugging mode
+ pause = 0 # Default pause mode
+ outdir = '/usr/local/samba/netlogon/' # Default netlogon directory
+
+ sections = ['Global', 'Machine', 'OS', 'Group', 'User'] # Currently supported
+ # configuration file
+ # sections
+
+ options, args = getopt.getopt(sys.argv[1:], 'd:f:g:ho:u:m:v',
+ ['templatefile=',
+ 'group=',
+ 'help',
+ 'os=',
+ 'user=',
+ 'machine=',
+ 'dir=',
+ 'version',
+ 'pause',
+ 'debug'])
+
+ #
+ # Process the command line arguments
+ #
+ for i in options:
+ # template file to process
+ if (i[0] == '-f') or (i[0] == '--templatefile'):
+ configfile = i[1]
+ # print 'configfile = ' + configfile
+
+ # define the group to be used
+ elif (i[0] == '-g') or (i[0] == '--group'):
+ group = i[1]
+ # print 'group = ' + group
+
+ # define the os type
+ elif (i[0] == '-o') or (i[0] == '--os'):
+ ostype = i[1]
+ # print 'os = ' + os
+
+ # define the user
+ elif (i[0] == '-u') or (i[0] == '--user'):
+ user = i[1]
+ outfile = user + '.bat' # Setup the output file name
+ # print 'user = ' + user
+
+ # define the machine
+ elif (i[0] == '-m') or (i[0] == '--machine'):
+ machine = i[1]
+
+ # define the netlogon directory
+ elif (i[0] == '-d') or (i[0] == '--dir'):
+ outdir = i[1]
+ # print 'outdir = ' + outdir
+
+ # if we are asked to turn on debug info, do so.
+ elif (i[0] == '--debug'):
+ debug = 1
+ # print 'debug = ' + debug
+
+ # if we are asked to turn on the automatic pause functionality, do so
+ elif (i[0] == '--pause'):
+ pause = 1
+ # print 'pause = ' + pause
+
+ # if we are asked for the version number, print it.
+ elif (i[0] == '-v') or (i[0] == '--version'):
+ print version
+ sys.exit(0)
+
+ # if we are asked for help print the docstring.
+ elif (i[0] == '-h') or (i[0] == '--help'):
+ print __doc__
+ sys.exit(0)
+
+ #
+ # open the configuration file
+ #
+ try:
+ iFile = open(configfile, 'r')
+ except IOError:
+ print 'Unable to open configuration file: ' + configfile
+ sys.exit(1)
+
+ #
+ # open the output file
+ #
+ if not debug:
+ try:
+ oFile = open(outdir + outfile, 'w')
+ except IOError:
+ print 'Unable to open logon script file: ' + outdir + outfile
+ sys.exit(1)
+
+ buf = iFile.readlines() # read in the entire configuration file
+
+ #
+ # call the script building routine
+ #
+ script = buildScript(buf, sections, group, user, ostype, machine, debug, pause)
+
+ #
+ # write out the script file
+ #
+ if not debug:
+ for ln in script:
+ oFile.write(ln + '\r\n')
+ if pause:
+ if string.strip(ln) != '': # Because whitespace
+ oFile.write('pause' + '\r\n') # is a useful tool, we
+ # don't put pauses after
+ # an empty line.
+
+
+# End run()
+
+#
+# immediate-mode commands, for drag-and-drop or execfile() execution
+#
+if __name__ == '__main__':
+ run()
+else:
+ print "Module ntlogon.py imported."
+ print "To run, type: ntlogon.run()"
+ print "To reload after changes to the source, type: reload(ntlogon)"
+
+#
+# End NTLogon.py
+#