makenetworkdrives.pl

Code Index:



Name

makenetworkdrives.pl - Automatische Erstellung von Logon-Skripten für Windows-Domänen


Zusammenfassung

makenetworkdrives.pl [--destdir /Pfad/zum/Zielverzeichnis] [--sambadir /Pfad/zum/Sambaverzeichnis] [--sshdir LW:\Pfad\zur\SSH] [--debug] [--help|--?] [--verbose] [--version]


Zweck

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>


Optionen

--destdir Verzeichnis
Pfad zum Zielverzeichnis der Logon-Skripte.

Standard: aktuelle Verzeichnis

--sambadir Verzeichnis
Verzeichnis das die Dateien smb.conf und smbpasswd enthält.

Standard: /etc/samba

--sshdir LW:\Pfad\zur\SSH
Pfad zur Windows-Version der SSH.

--debug
Zeigt Debugmeldungen an. Doppeltes Setzen dieses Schalters erhöht die Tiefe der Meldungen.

--help oder --?
Zeigt eine kurze eine kurze Übersicht über alle Optionen an.

--verbose
Zeigt zusätzliche Meldungen über den Programmablauf an.

--version
Zeigt die Programmversion an


Hinweis

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.


Lob, Kritik und Programmfehler

Emails mit Lob, Kritik, Verbesserungsvorschlägen sowie über Programmfehler sind jederzeit willkommen.


Todo, Erweiterungs- und Verbesserungsmöglichkeiten

Individuelle Einstellungen
in eine benutzergebundene gesonderte Datei auslagern, die bei Existens automatisch aufgerufend wird

Cookies loeschen
Alle Einstellungen über die Kommandozeile steuerbar gestalten


Programmname und Autor

makenetworkdrives.pl v0.4a

von Carsten Grohmann mail_an_carstengrohmann.de

http://www.carstengrohmann.de


Version

Erstellungsdatum: 19. Juli 2004

$Id: makenetworkdrives.pl.html,v 1.1 2005-01-23 14:04:20 carsten Exp $


Copyright

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__