makenetworkdrives.pl - Automatische Erstellung von Logon-Skripten für Windows-Domänen
makenetworkdrives.pl [--destdir /Pfad/zum/Zielverzeichnis] [--sambadir /Pfad/zum/Sambaverzeichnis] [--sshdir LW:\Pfad\zur\SSH] [--debug] [--help|--?] [--verbose] [--version]
Dieses Programm erzeugt für jeden Benutzer in /$SAMBADIR/smbpasswd eine Datei zum automatischen Anmeldung der Netzlaufwerke und zum Setzen diverser Einstellungen während der Domänenanmeldung.
Dabei werden die zugelassenen Benutzer, die vorhandenen Freigaben sowie die Berechtigungen selbständig ermittelt und beim Erzeugen der Dateien berücksichtigt.
Dafür erforderlich die Freigaben in der Sambakonfigurationsdatei smb.conf um zwei Kommentarzeilen nach folgenden Schema zu erweitern: [Freigabename] # Laufwerk: <Laufwerksbuchstabe> # Gruppe : <Benutzergruppe>
Standard: aktuelle Verzeichnis
smb.conf und smbpasswd enthält.
Standard: /etc/samba
Die im Skript verwendeten Servernamen sollten als FQDN vorliegen, es sei denn die Zielplattform unterstützt KEIN DNS in Loginskripten wie Windows 9x oder Windows NT.
Emails mit Lob, Kritik, Verbesserungsvorschlägen sowie über Programmfehler sind jederzeit willkommen.
makenetworkdrives.pl v0.4a
von Carsten Grohmann mail_an_carstengrohmann.de
Erstellungsdatum: 19. Juli 2004
$Id: makenetworkdrives.pl.html,v 1.1 2005-01-23 14:04:20 carsten Exp $
Copyright (c) 2003-2004 Carsten Grohmann
Dieses Softwarepaket enthält freie Software. Sie kann entsprechend den Bedingungen der GNU General Public License Version 2 oder höher, veröffentlicht durch die Free Software Foundation, vertrieben und/oder modifiziert werden.
Details dazu befinden sich unter http://www.fsf.org/licenses/licenses.html.
#!/usr/bin/perl -w # # Skriptname : makenetworkdirves.pl # # Autor : Carsten Grohmann # # Stand : 19. Juli 2004 # # Lizenz : GPL # # $Id: makenetworkdrives.pl.html,v 1.1 2005-01-23 14:04:20 carsten Exp $ # # Status : funktioniert fehlerfrei # # Beschreibung : Erstellt aus den Sambafreigeben, den Gruppenzugehörigkeiten # der Benutzer und der Sambapaßwortdatei für jeden Benutzer # eine individuelle Datei, mit der unter Windows die # Netzwerklaufwerke verbunden werden können. # Die im Skript verwendeten Servernamen sollten als FQDN # vorliegen, es sei denn die Zielplattform unterstützt # KEIN DNS in Logonskripten wie Win9x oder WinNT. # Zum automatischen Erstellen der Logon-Skripte ist es # erforderlich bei den Freigaben in smb.conf folgendes # Schema einzuhalten: # [Freigabename] # # Laufwerk: <Laufwerksbuchstabe> # # Gruppe : <Benutzergruppe> # # Änderungen : zu 0.2 09.08.2001 # - auf perl umgestellt # zu 0.2b 10.08.2001 # - Benutzer aus smbpasswd auslesen # - debug ab nun mit Debuglevel # zu 0.3 26.09.2001 # - Freigaben, Gruppen und Laufwerksbuchstaben werden # aus @smbconffile gelesen # zu 0.3b 26.11.2001 # - Syntax wird ausgegeben # - Funktionen kommentiert # zu 0.3c 18.04.2002 # - Einstellungen für die SSH werden gesetzt # nicht veröffentlicht 26.06.2004 # - Hinweis FQDN hinzugefügt # zu 0.4 04.07.2004 # - Version 0.4 # - Ausführliche Syntaxmeldung und Skriptdokumentation # hinzugefügt # - Samba- und Zielverzeichnis sowie Ausgabesteuerung # per Kommandozeile wählbar # - Überprüfung des Benutzerkontos und der Existenz # der Gruppe # - Ermittlung der Gruppenmitgliedschaft über getgrnam # - Konfigurationsvariablen in einen Hash verschoben # - Quelltext umstrukturiert und formatiert # # $Log: makenetworkdrives.pl.html,v $ # Revision 1.1 2005-01-23 14:04:20 carsten # - aus dem Quellcode automatisch mit perltidy erzeugte Dokumentationen # - ursprünglicher Speicherort: / # # Revision 1.1 2004/07/30 21:20:24 carsten # - Dokumentation hinzugefügt # # Revision 1.9 2004/07/19 20:35:08 carsten # - Version 0.4a # - Löschen temporärer Verzeichnisse geändert es wird nur noch %TEMP% gelöscht # # # Syntax : siehe makenetworkdrives.pl --help # # Hinweis : Dieses Skript wurde mit perltidy -bbvt=0 -bl formatiert use strict; use diagnostics; use Getopt::Long; # # Variablen initialisieren # # Verwendete Schalter: my %config = ( 'DEBUGLEVEL' => '0', # 0 -> keine Ausgaben 2-> viel Ausgaben 'DESTDIR' => '.', # Zielverzeichnis 'HOME' => 'no', # Heimatverzeichnis verbinden 'NETTIME_SERVER' => 'myserver.mydomain.tld', # FQDN Zeitserver 'PERSISTENT' => 'no', # Freigaben dauerhaft binden 'DELTEMP' => 'yes', # temp. Verzeichnis %TEMP% löschen 'SAMBADIR' => '/etc/samba', # Konfigurationsverzeichnis 'SERVER' => 'myserver.mydomain.tld', # FQDN Server 'SETSSHSETTINGS' => 'no', # Einstellungen für SSH setzen 'SETTIME' => 'no', # Lokale Zeit setzen 'SSHDIR' => 'C:\Programme\NetworkSimplicity\ssh', # Pfad zur SSH 'VERBOSE' => 'yes', # yes -> Zusatzinformationen 'VERBOSE' => 'no' # no -> keine Ausgaben ); # # ----- Keine Änderungen unterhalb dieser Linie ----- # $0 =~ s,.*/,,; # Entferne fuehrende Pfadnamen my $programname = $0; # Programmname my $version = "0.4a"; # Akutelle Version dieses Skriptes my @smbconffile; # Inhalt von smb.conf my @smbpasswdfile; # Inhalt von smbpasswd my @userlist; # Liste, welche alle Benutzer enthaelt my @shares; # Beinhaltet die Freigaben und Optionen my $newline = "\r\n"; # Newline-Zeichen # # Subroutinen # # Meldungen nur ausgeben, wenn dies gewuenscht wird. sub output { my $message = $_[0]; if ( $config{'VERBOSE'} eq "yes" ) { print $message; } } # Fehlermeldungen ausgeben und beenden sub error { my $message = $_[0]; print($message); exit(1); } # Warnung ausgeben # Übergebene Parameter: # 1. Warnmeldung Typ Skalar sub warning ($) { my $message = $_[0]; printf( "WARNUNG: %s", $message ); } # Debugmeldungen ausgeben sub debug ($$) { my ( $level, @list ) = @_; if ( $config{'DEBUGLEVEL'} >= $level ) { print @list; } } # Programmname und -version ausgeben sub show_version() { print("$programname Version $version\n"); print("Copyright (c) 2001-2004 Carsten Grohmann\n"); } # Syntax ausgeben sub show_usage { my $returnvalue = $_[0]; if ( !defined $returnvalue ) { $returnvalue = 0; } # Programmname und Version nicht doppelt anzeigen if ( $config{'VERBOSE'} ne "yes" ) { show_version(); } print( "Dieses Programm erzeugt für jeden Benutzer in " . "$config{'SAMBADIR'}/smbpasswd\n" . "eine Datei zum automatischen Anmeldung der Netzlaufwerke und zum\n" . "Setzen diverser Einstellungen während der Domänenanmeldung.\n" . "Dabei werden die zugelassenen Benutzer, die vorhandenen Freigaben\n" . "sowie die Berechtigungen selbständig ermittelt und beim Erzeugen der\n" . "Dateien automatisch berücksichtigt.\n" . "Syntax:\n" . " [--destdir /Pfad/zum/Zielverzeichnis]\n" . " [--sambadir /Pfad/zum/Sambaverzeichnis]\n" . " [--sshdir LW:\\Pfad\\zur\\SSH] Pfad für die Windows-SSH setzen\n" . " [--debug] Zeigt Debugmeldungen an\n" . " [--help|--?] Zeigt diesen Text an\n" . " [--verbose] Zeigt zusätzliche Meldungen an\n" . " [--version] Zeigt die Programmversion an\n\n" . "Zusätzlich enthält dieses Skript eine integrierte Dokumentation.\n" . "Sie kann mit pod2(html|man|latex|text) angezeigt werden.\n" . "Beispiel: \"pod2man $programname | man -l -\" " . "zeigt die Dokumentation\n" . "als man page formatiert an.\n" ); exit($returnvalue); } # Programmoptionen auswerten sub get_options() { my $config_debug; my $config_destdir; my $config_sambadir; my $config_sshdir; my $config_usage; my $config_verbose; my $config_version; GetOptions( 'debug+' => \$config_debug, 'destdir=s' => \$config_destdir, 'help|?' => \$config_usage, 'sambadir=s' => \$config_sambadir, 'sshdir=s' => \$config_sshdir, 'verbose' => \$config_verbose, 'version' => \$config_version ) or show_usage(); if ( defined $config_version ) { show_version(); exit; } if ( defined $config_verbose ) { $config{'VERBOSE'} = "yes"; } else { $config{'VERBOSE'} = "no"; } show_usage(0) if ( defined $config_usage ); $config{'DEBUGLEVEL'} = $config_debug if ( defined $config_debug ); $config{'DESTDIR'} = $config_destdir if ( defined $config_destdir ); $config{'SAMBADIR'} = $config_sambadir if ( defined $config_sambadir ); $config{'SSHDIR'} = $config_sshdir if ( defined $config_sshdir ); } # Uhrzeit auslesen und zurueckgeben sub read_time { my ( $sec, $min, $hour, $day, $mon, $year ) = ( localtime(time) )[ 0, 1, 2, 3, 4, 5 ]; $year = 1900 + $year; return sprintf( "%02d.%02d.%02d %02d:%02d:%02d", $day, $mon, $year, $hour, $min, $sec ); } # Erzeugt aus den übergebenen Parameter syntaktisch korrekte Freigaben und # schreibt diese in ein Array # Zu uebergebende Parameter # 1. Parameter: Freigabename # 2. Parameter: Benutzername # 3. Parameter: Benutzergruppe # 4. Parameter: Laufwerksbuchstabe # 5. Parameter: Zieldatei - Referenz auf einen Array sub make_network_drive { my ( $share, $user, $group, $driveletter, $list ) = @_; debug( 2, "make_network_drive: Freigabe: $share\, Laufwerk: $driveletter\n" ); # überprüfe ab die Gruppe existiert if ( !defined getgrnam($group) ) { warning( sprintf( "Die Gruppe \"%s\" existiert nicht. Freigabe %s wird nicht " . "angelegt.", $group, $share ) ); return; } # hole Gruppenmitglieder my @groupmembers = split( / /, ( getgrnam($group) )[3] ); # überprüfe Gruppenmitgliedschaft if ( grep { $_ eq $user } @groupmembers == 0 ) { return; } # erzeuge Freigabeneintrag push( @{$list}, "rem Laufwerk $driveletter: $share" . " - Netzwerkverzeichnis verbinden$newline", "NET USE $driveletter: \\\\$config{'SERVER'}\\$share " . "/USER:$user$newline", "rem$newline" ); } # Erzeugt den Kopf des Anmeldeskriptes und schreibt diesen in ein Array # Zu uebergebende Parameter # 1. Parameter: Benutzername # 2. Parameter: Zieldatei sub make_head { my ( $user, $list ) = @_; debug( 2, "make_head: Benutzer: $user\n" ); push( @{$list}, '@echo' . " off$newline", "echo Dieses Skript wird waehrend der Anmeldung an der Domaene$newline", "echo ausgefuehrt und setztt dabei diverse Einstellungen.$newline", "echo Da diese Datei automatisch erstellt wird, gehen manu-$newline", "echo elle Aenderungen verloren.$newline", "echo Wenden Sie sich mit Ihren Aenderungswuenschen bitte an$newline", "echo Ihren Systemadministrator$newline", "echo .$newline", "echo Autor : Carsten Grohmann$newline", "echo .$newline", "echo Erstellungsdatum: " . read_time . $newline, "echo .$newline", "echo Die Einstellungen fuer den Benutzer $user werden gesetzt$newline", "echo .$newline", "rem Variablen setzen$newline", "set SERVER=$config{'SERVER'}$newline", "set TIMESERVER=$config{'NETTIME_SERVER'}$newline", "set VERBOSE=" . uc( $config{'VERBOSE'} ) . $newline, "set SETTIME=" . uc( $config{'SETTIME'} ) . $newline, "set DELTEMP=" . uc( $config{'DELTEMP'} ) . $newline, "set SET_SSHSETTINGS=" . uc( $config{'SETSSHSETTINGS'} ) . $newline, "echo .$newline", "if not \"%VERBOSE%\" == \"YES\" goto SETTIME$newline", "echo Benutzer: %username%$newline", "echo Computer: %computername%$newline", "echo Betriebssystem: %OS%$newline", "echo Server: %SERVER%$newline", "echo Zeitserver: %TIMESERVER%$newline", "echo .$newline", "if not \"%SETTIME%\" == \"YES\" goto SETSSH$newline", $newline, ":SETTIME$newline", "echo Lokale Uhr mit dem Server abgleichen$newline", "rem Bedeutung der Parameter$newline", "rem /s - Systemzeit syncronisieren$newline", "rem /y - Keine Bestaetigungsmeldung anzeigen$newline", "NET TIME \\\\%TIMESERVER% /s /y$newline", $newline, ":SETSSH$newline", "if not \"%SET_SSHSETTINGS%\" == \"YES\" goto DELTEMP$newline", "echo Setzte Einstellungen fuer die SSH$newline", "set HOME=z:\\$newline", "set PATH=%PATH%:$config{'SSHDIR'}$newline", $newline, ":DELTEMP$newline", "if not \"%DELTEMP%\" == \"YES\" goto NETDIR$newline", "echo Inhalt der temporaeren Benutzerverzeichnisse loeschen$newline", 'if exist \"%TEMP%\" del %TEMP%\*.* /s /q' . $newline, $newline, ":NETDIR$newline", "echo Netzwerkverzeichnisse einbinden$newline", "echo .$newline" ); # Ende push if ( $config{'PERSISTENT'} eq "yes" ) { push( @{$list}, "echo Verbindungen automatisch wiederherstellen$newline", "NET USE /PERSISTENT:YES$newline", "echo .$newline" ); } else { push( @{$list}, "echo Verbindungen nicht automatisch wiederherstellen$newline", "NET USE /PERSISTENT:NO$newline", "echo .$newline" ); } } # Ende des Logon-Skriptes schreiben # Zu uebergebende Parameter # 1. Parameter: Benutzername # 2. Parameter: Zieldatei sub make_end { my ( $user, $list ) = @_; debug( 2, "make_end: Benutzer: $user\n" ); push( @{$list}, $newline, ":ENDE$newline" ); } # Erzeugt das Ende des Anmeldeskriptes und schreibt diesen in ein Array # Zu uebergebende Parameter # 1. Parameter: Benutzername # 2. Parameter: Zieldatei sub make_file { my ( $user, $list ) = @_; my $share; # Name der Freigabe my $drive; # Laufwerksbuchstabe my $group; # Gruppe debug( 2, "make_file: Benutzer: $user\n" ); make_head( $user, $list ); foreach (@shares) { output( "Freigabe: " . ( split( /\n/, $_ ) )[0] . "\n" ); output( "Laufwerk: " . ( split( /:/, ( split( /\n/, $_ ) )[1] ) )[1] . "\n" ); output( "Gruppe: " . ( split( /:/, ( split( /\n/, $_ ) )[2] ) )[1] . "\n" ); $share = ( split( /\n/, $_ ) )[0]; $group = ( split( /:/, ( split( /\n/, $_ ) )[2] ) )[1]; $drive = ( split( /:/, ( split( /\n/, $_ ) )[1] ) )[1]; if ( $share ne "homes" ) { # Normale Verzeichnisse verbinden make_network_drive( $share, $user, $group, $drive, $list ); } if ( ( $config{'HOME'} eq "yes" ) and ( $share eq "homes" ) ) { # home verbinden make_network_drive( $user, $user, $group, $drive, $list ); } } # Ende foreach make_end( $user, $list ); } # # Hauptfunktion # show_version() if ( $config{'VERBOSE'} eq "yes" ); get_options(); # Überprüfe Einstellungen if ( !-d $config{'DESTDIR'} ) { error("Fehler: Zielverzeichnis $config{'DESTDIR'} nicht gefunden.\n"); } if ( !-f "$config{'SAMBADIR'}/smb.conf" ) { error( "Fehler: Sambakonfigurationsdatei " . "\"$config{'SAMBADIR'}/smb.conf\" existiert nicht\n" ); } if ( !-f "$config{'SAMBADIR'}/smbpasswd" ) { error( "Fehler: Sambapasswortdatei \"$config{'SAMBADIR'}/smbpasswd\"" . " existiert nicht\n" ); } # Sambakonfigurationsdatei einlesen, um später daraus die Freigaben mit # den benötigten Informationen zu extrahieren debug( 1, "Samba-Konfigurationsdatei $config{'SAMBADIR'}/smb.conf einlesen\n" ); open( IFH, "< $config{'SAMBADIR'}/smb.conf" ) or error "Fehler $!: Beim Oeffnen von $config{'SAMBADIR'}/smb.conf\n"; @smbconffile = <IFH>; close(IFH) or error "Fehler $!: Beim Schliessen von $config{'SAMBADIR'}/smb.conf\n"; # Sambapasswortdatei einlesen, um später daraus die zugelassenen Benutzer # zu ermitteln debug( 1, "Smbpasswddatei $config{'SAMBADIR'}/smbpasswd einlesen\n" ); open( IFH, "< $config{'SAMBADIR'}/smbpasswd" ) or error "Fehler $!: Beim Oeffnen von $config{'SAMBADIR'}/smbpasswd\n"; @smbpasswdfile = <IFH>; close(IFH) or error "Fehler $!: Beim Schliessen von $config{'SAMBADIR'}/smbpasswd\n"; # Freigaben, Gruppen und Laufwerksbuchstaben ermitteln @shares = join( '', @smbconffile ) =~ /.*(\[.*\].*\n\# Laufwerk.*:.*\n\# Gruppe.*:.*\n).*/g; s/( |#|\[|\]|)//g for @shares; # Störende Zeichen entfernen # Benutzer extrahieren # Alle Zeilen finden, wo nur ein U fuer user im account flag steht foreach ( grep ( /^.*\[[U ]{11}.*\]/, @smbpasswdfile ) ) { push( @userlist, ( split( /:/, $_ ) )[0] ); } # Fuer jeden Benutzer seine spezifische Datei erzeugen foreach my $user (@userlist) { my $destfile; # Zieldatei my @userfile; # Array mit der Zieldatei als Inhalt # Sicherheitshalber letztes newline entfernen chomp $user; # nicht existierender Benutzer -> überspringen if ( !defined getpwnam($user) ) { warning( sprintf( "Für \"%s\" existiert kein Benutzerkonto. " . "Benutzer wird übersprungen.\n", $user ) ); next; } debug( 1, "Erzeuge Skript fuer $user\n" ); make_file( $user, \@userfile ); $destfile = $config{'DESTDIR'} . $user . ".cmd"; if ( -f $destfile ) { debug( 2, "Sicherheitshalber Datei $destfile loechen\n" ); unlink $destfile or error "Fehler $!: Beim Loeschen von $destfile\n"; } debug( 2, "NT-Logon-Skript $destfile schreiben\n" ); open( OFH, "> $destfile" ) or error "Fehler $!: Beim Oeffnen von $destfile\n"; print OFH @userfile; close(OFH) or error "Fehler $!: Beim Schliessen von $destfile\n"; # Besitzer und Rechte setzen debug( 2, "Besitzer und Rechte setzen\n" ); chmod 0600, $destfile; chown( ( getpwnam($user) )[2], ( getgrnam("users") )[2], $destfile ); @userfile = ""; } # Skript beenden exit; #----------------------------------------------------------------------- # END OF SCRIPT #----------------------------------------------------------------------- __END__